/* Прототип мини-приложения MAX для родителя.
   Экран смотрят с телефона между делом: крупный тап, один главный блок на экран,
   цифры и расстояния табличными. Тема светлая и темная, берется системная. */
:root {
  --ink: #0d1420;
  --ink-2: #4a5768;
  --ink-3: #646e7c;   /* текст: 4,8 к фону страницы, читается на улице */
  --ink-4: #8b98aa;   /* иконки и разделители, к тексту не применять */
  --bg: #f4f6fb;
  --card: #ffffff;
  --line: rgba(13, 20, 32, .085);
  --line-2: rgba(13, 20, 32, .045);
  --acc: #2563eb;
  --on-acc: #ffffff;   /* текст на акцентной кнопке */
  --acc-2: #4f8bff;
  --acc-soft: rgba(37, 99, 235, .09);
  --acc-ink: #1d4ed8;   /* акцентный текст на мягкой подложке: 5,5 к 1 */
  --gold: #e0952a;              /* иконки и акценты, к мелкому тексту не применять */
  --gold-ink: #8a5300;          /* текст на золотой плашке: 5,4 к своей подложке */
  --gold-soft: rgba(245, 185, 59, .16);
  --ok: #0b7a44;
  --ok-soft: rgba(15, 157, 88, .12);
  --danger: #c02a2a;
  --r: 18px;
  --r-s: 13px;
  --tap: 52px;
  --pad: 16px;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --ink: #eef2f8; --ink-2: #a8b4c4; --ink-3: #97a3b4; --ink-4: #6e7c8f;
    --bg: #080d15; --card: #131a25; --line: rgba(255,255,255,.10); --line-2: rgba(255,255,255,.05);
    --acc: #7ea6ff; --acc-2: #9dbaff; --acc-soft: rgba(126,166,255,.16); --on-acc: #0a1526;
    --acc-ink: #9dbaff;
    --gold: #f5b93b; --gold-ink: #f7c86a; --gold-soft: rgba(245,185,59,.15);
    --ok: #3ddc84; --ok-soft: rgba(61,220,132,.13);
    --danger: #ff7a7a;
  }
}
:root[data-theme="dark"] {
  --ink: #eef2f8; --ink-2: #a8b4c4; --ink-3: #97a3b4; --ink-4: #6e7c8f;
  --bg: #080d15; --card: #131a25; --line: rgba(255,255,255,.10); --line-2: rgba(255,255,255,.05);
  --acc: #7ea6ff; --acc-2: #9dbaff; --acc-soft: rgba(126,166,255,.16); --on-acc: #0a1526;
  --acc-ink: #9dbaff;
  --gold: #f5b93b; --gold-ink: #f7c86a; --gold-soft: rgba(245,185,59,.15);
  --ok: #3ddc84; --ok-soft: rgba(61,220,132,.13);
  --danger: #ff7a7a;
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
html, body { margin: 0; min-height: 100%; }
body {
  background: var(--bg); color: var(--ink);
  font: 400 16px/1.45 -apple-system, "SF Pro Text", "Segoe UI", Roboto, Inter, sans-serif;
  font-feature-settings: "tnum" 1;
  -webkit-font-smoothing: antialiased;
}
main { max-width: 620px; margin: 0 auto; padding: 0 var(--pad) calc(94px + env(safe-area-inset-bottom)); }
button { font: inherit; color: inherit; border: 0; background: none; cursor: pointer; }
img { display: block; max-width: 100%; }
svg { fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }

/* ---------- шапка с выбором ребенка */
.bar {
  /* шапка лежит вне main, поэтому свои поля держит сама: отрицательные отступы
     тут вылезали за экран и давали горизонтальную прокрутку на узких телефонах */
  position: sticky; top: 0; z-index: 6;
  padding: 10px var(--pad) 11px;
  display: flex; align-items: center; gap: 12px;
  background: color-mix(in srgb, var(--bg) 86%, transparent);
  backdrop-filter: saturate(1.5) blur(14px);
  border-bottom: 1px solid var(--line-2);
}
.kid { display: flex; align-items: center; gap: 10px; flex: 1; min-width: 0; padding: 4px 0; }
.ava {
  width: 38px; height: 38px; border-radius: 12px; flex: none;
  background: linear-gradient(160deg, var(--acc-2), var(--acc));
  color: #fff; font-weight: 640; font-size: 15px;
  display: flex; align-items: center; justify-content: center;
}
.kid .who { min-width: 0; text-align: left; }
.kid .nm { display: flex; align-items: center; gap: 5px; font-weight: 600; letter-spacing: -.015em; }
.kid .nm svg { width: 15px; height: 15px; stroke: var(--ink-4); stroke-width: 2.2; }
.kid .sc { display: block; font-size: 12.5px; color: var(--ink-3); overflow: hidden;
           text-overflow: ellipsis; white-space: nowrap; }
.bar .icon { width: 44px; height: 44px; border-radius: 12px; display: flex; align-items: center;
             justify-content: center; color: var(--ink-2); background: var(--card);
             border: 1px solid var(--line); flex: none; }
.bar .icon svg { width: 21px; height: 21px; }
.bar:empty { display: none; }
@media (min-width: 653px) { .bar { max-width: 652px; margin: 0 auto; } }

/* ---------- заголовки */
h1 { margin: 22px 0 16px; font-size: 29px; font-weight: 680; letter-spacing: -.035em;
     text-wrap: balance;
     line-height: 1.12; }
h1 .sub { display: block; font-size: 13.5px; font-weight: 400; color: var(--ink-3);
          letter-spacing: 0; margin-top: 3px; }
/* шапка экрана ребенка: имя якорь, класс вторым уровнем, школа третьим */
h1 .cls { display: block; margin-top: 5px; font-size: 17px; font-weight: 570;
          letter-spacing: -.012em; color: var(--ink-2); }
h1 .cls:empty { display: none; }
h1 .cls i { display: block; margin-top: 2px; font-style: normal; font-size: 13.5px;
            font-weight: 400; letter-spacing: 0; color: var(--ink-3); }
h2 { margin: 34px 0 12px; font-size: 13px; font-weight: 640; color: var(--ink-2);
     display: flex; justify-content: space-between; align-items: baseline; }
h2 a, h2 .more { color: var(--acc); font-weight: 600; font-size: 13px; text-decoration: none; }
h2 .more { margin: -11px -8px -11px 0; padding: 11px 8px; }
h3 { margin: 0 0 3px; font-size: 17px; font-weight: 630; letter-spacing: -.02em; }
p { margin: 0 0 9px; }
.muted { color: var(--ink-3); }
.small { font-size: 13.5px; }

/* ---------- карточки */
.card { background: var(--card); border: 1px solid var(--line); border-radius: var(--r);
        padding: 14px; margin-bottom: 18px; }
.card.tap { display: block; width: 100%; text-align: left;
            transition: transform .12s ease, border-color .15s ease; }
.card.tap:active { transform: scale(.994); border-color: var(--acc); }
.rows > button { transition: background .12s ease; }
.rows > button:active { background: var(--acc-soft); }
.hero .act button:active, .btn:active { transform: scale(.985); filter: brightness(.95); }
nav button:active span, nav button:active svg { opacity: .6; }
.kid:active { opacity: .65; }
:focus-visible { outline: 2px solid var(--acc); outline-offset: 2px; border-radius: 8px; }
.rows { display: grid; gap: 1px; background: var(--line-2); border-radius: var(--r);
        overflow: hidden; border: 1px solid var(--line); margin-bottom: 14px; }
/* min-width: 0 обязателен: без него клетка грида не ужимается ниже своего
   min-content, строка вылезает за карточку и стрелка справа уходит под обрез */
.rows > * { background: var(--card); padding: 13px 15px; display: flex; gap: 12px;
            align-items: center; text-align: left; width: 100%; min-width: 0; }
.rows .grow { flex: 1; min-width: 0; }
/* ссылка в списке выглядит как соседние строки: синее подчеркивание тут читалось бы
   как единственный кликабельный пункт, хотя нажимается вся строка */
.rows > a { color: inherit; text-decoration: none; }
/* строка-вход над однородным списком: отделяется от него сильнее, чем элементы
   списка друг от друга, и весит меньше их заголовков - иначе читается как первый
   результат выдачи, а не как вход над ней */
.rows.enter { margin-bottom: 26px; }
.rows.enter b { font-weight: 570; }
/* два списка подряд без заголовка между ними: 14px внешнего против 13px
   внутреннего читались как один длинный список, и смена роли весила ровно
   столько же, сколько «изменить класс» */
.rows + .rows { margin-top: 12px; }

/* развилка на входе: это весь смысл экрана, а не строка настроек. Поэтому
   свой кегль и свой воздух, и две двери стоят врозь, а не склеены хайрлайном */
.roles { display: grid; gap: 10px; margin: 26px 0 20px; }
.roles > button { background: var(--card); border: 1px solid var(--line);
                  border-radius: var(--r); padding: 18px 16px; width: 100%;
                  display: flex; gap: 12px; align-items: center; text-align: left;
                  transition: transform .12s ease, border-color .15s ease; }
.roles > button:active { transform: scale(.994); border-color: var(--acc); }
.roles .grow { flex: 1; min-width: 0; }
.roles b { display: block; font-size: 19px; font-weight: 640; letter-spacing: -.022em; }
.roles .small { display: block; margin-top: 3px; }
.chev { width: 17px; height: 17px; stroke: var(--ink-4); stroke-width: 2; flex: none;
         align-self: center; }

/* ---------- главный блок: ближайшее */
.hero {
  position: relative; overflow: hidden; color: #fff; padding: 17px;
  border-radius: var(--r); margin-bottom: 10px;
  background: linear-gradient(145deg, #2f6bf0 0%, #1d4fd8 55%, #163fae 100%);
}
.hero::after {
  content: ""; position: absolute; right: -52px; top: -64px; width: 190px; height: 190px;
  border-radius: 50%; background: rgba(255,255,255,.10);
}
.hero .kicker { position: relative; font-size: 12px; font-weight: 700;
                color: #ffe9bd; margin-bottom: 7px; }
.hero .title { position: relative; font-size: 20px; font-weight: 650; letter-spacing: -.024em;
               line-height: 1.2; }
.hero .meta { position: relative; margin-top: 7px; font-size: 14.5px; color: rgba(255,255,255,.84); }
.hero .act { position: relative; display: flex; gap: 8px; margin-top: 14px; }
.hero .act button { background: #fff; color: #17347f; font-size: 16px; font-weight: 620;
                    min-height: 48px; padding: 0 20px; border-radius: 12px; }
.hero .act .ghost { background: rgba(255,255,255,.16); color: #fff; }

/* витрина достижений: цифры в ряд, с переносом на узком экране. Обычный .facts
   рассчитан на две-три метрики в строку, тут их бывает четыре */
.facts.wins { flex-wrap: wrap; gap: 18px 26px; }
.facts.wins b i { display: inline; }

/* мозаика: главный блок экрана. Теплый тон вместо синего - событие под ней
   синее, и два синих блока подряд читались бы как один. Текст темный: белый по
   золоту не читается на солнце, а экран смотрят на улице */
.hero.puz { background: linear-gradient(145deg, #ffcb5c 0%, #f0a93a 55%, #dd8c1b 100%);
            color: #3a2300; }
.hero.puz::after { background: rgba(255,255,255,.22); }
.hero.puz .kicker { color: #6b4200; }
.hero.puz .meta { color: rgba(58,35,0,.78); }
.hero.puz .act button { background: #3a2300; color: #ffd98a; }
/* полоса кусочков: прогресс глазом, а не словами. Деления считают то же, что
   считает сама мозаика, поэтому их ровно столько, сколько дел в сезоне */
.hero.puz .pbar { position: relative; display: flex; gap: 4px; margin-top: 12px; }
.hero.puz .pbar i { flex: 1; height: 7px; border-radius: 3px;
                    background: rgba(58,35,0,.17); }
.hero.puz .pbar i.on { background: #3a2300; }

/* ---------- кружок в списке */
.prog { display: flex; gap: 13px; align-items: flex-start; }
.prog .pic { width: 46px; height: 46px; border-radius: 13px; flex: none; display: flex;
             align-items: center; justify-content: center; }
.prog .pic svg { width: 23px; height: 23px; }
.prog .grow { flex: 1; min-width: 0; }
.prog .org { font-size: 13px; color: var(--ink-3); margin-top: 2px; overflow: hidden;
             text-overflow: ellipsis; white-space: nowrap; }
.prog .org.wrap { white-space: normal; overflow: visible; line-height: 1.4; margin-top: 4px; }
.tags { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 9px; }
.rows .tags { margin-top: 7px; }
.tag { font-size: 12px; font-weight: 570; padding: 4px 8px; border-radius: 7px;
       background: var(--line-2); color: var(--ink-2); white-space: nowrap;
       display: inline-flex; align-items: center; gap: 4px; }
.tag.km { background: var(--acc-soft); color: var(--acc-ink); }
.tag.free { background: var(--ok-soft); color: var(--ok); }
.tag.dot::before { content: "·"; margin-right: 6px; color: var(--ink-4); }
.tag.gold { background: var(--gold-soft); color: var(--gold-ink); }

/* цвета направлений: один тон на направление во всем приложении */
.d-tech { background: rgba(37,99,235,.11); color: #2563eb; }
.d-art  { background: rgba(219,72,148,.11); color: #c0397f; }
.d-sport{ background: rgba(15,157,88,.12); color: #0f9d58; }
.d-sci  { background: rgba(124,58,237,.11); color: #7c3aed; }
.d-soc  { background: rgba(224,149,42,.14); color: #b5741b; }
.d-tour { background: rgba(13,148,136,.12); color: #0d9488; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .d-tech { color: #7aa5ff }
  :root:not([data-theme="light"]) .d-art { color: #ff86bd }
  :root:not([data-theme="light"]) .d-sport { color: #46dd8b }
  :root:not([data-theme="light"]) .d-sci { color: #b18bff }
  :root:not([data-theme="light"]) .d-soc { color: #f0b354 }
  :root:not([data-theme="light"]) .d-tour { color: #35c9ba }
}

/* ---------- поиск и фильтры */
.search { position: relative; margin-bottom: 10px; }
.search input { width: 100%; min-height: 48px; padding: 0 14px 0 42px; background: var(--card);
                border: 1px solid var(--line); border-radius: var(--r-s); font-size: 16px;
                outline: none; color: var(--ink); }
.search input::placeholder { color: var(--ink-3); }
.search svg { position: absolute; left: 13px; top: 15px; width: 21px; height: 21px; stroke: var(--ink-4); }
.chips { display: flex; gap: 7px; overflow-x: auto; margin: 0 calc(var(--pad) * -1) 12px;
         padding: 0 var(--pad) 2px; scrollbar-width: none; }
.chips::-webkit-scrollbar { display: none; }
/* группа из четырех чипов переносится, а не уезжает за край: последний открывает
   спрятанные события, обрезать его нельзя, а длинные имена детей непредсказуемы */
.chips.wrap { flex-wrap: wrap; overflow: visible; row-gap: 7px;
              margin-left: 0; margin-right: 0; padding-left: 0; padding-right: 0; }
/* четыре чипа встают в строку на 390 только с более тесными полями; длинное имя
   ребенка все равно перенесет ряд, и это лучше обрезанного края */
.chips.wrap .chip { padding: 0 13px; }
.chip { flex: none; min-height: 44px; padding: 0 15px; border-radius: 11px; font-size: 14.5px;
        font-weight: 550; background: var(--card); border: 1px solid var(--line);
        color: var(--ink-2); white-space: nowrap; }
.chip:active { transform: scale(.97); }
.chip svg { width: 16px; height: 16px; stroke-width: 2.2; margin-right: 5px;
            vertical-align: -3px; }
.chip.on { background: var(--acc); border-color: var(--acc); color: var(--on-acc); }
/* кольцо фокуса у чипа рисуем тенью, а не outline: outline поверх заливки
   съедает ее в вебвью мессенджера, и выбранный чип читается как невыбранный */
.chip:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--bg), 0 0 0 4px var(--acc); }
.chip.on:focus-visible { box-shadow: inset 0 0 0 2px var(--on-acc); }

/* ---------- новости */
.news-hero { position: relative; overflow: hidden; border-radius: var(--r); margin-bottom: 10px;
             min-height: 168px; display: flex; flex-direction: column; justify-content: flex-end;
             padding: 16px; color: #fff;
             background: linear-gradient(150deg, #1a2a4f 0%, #24365f 45%, #3b2a5e 100%); }
.news-hero .play { position: absolute; top: 15px; left: 16px; display: flex; align-items: center;
                   gap: 7px; font-size: 12px; font-weight: 640; color: #ffd98a; }
.news-hero .play span { width: 26px; height: 26px; border-radius: 50%; background: rgba(255,255,255,.16);
                        display: flex; align-items: center; justify-content: center; }
.news-hero .play svg { width: 13px; height: 13px; fill: currentColor; stroke: none; }
.news-hero h3 { font-size: 19px; line-height: 1.24; letter-spacing: -.022em; margin-bottom: 5px; }
.news-hero .meta { font-size: 13px; color: rgba(255,255,255,.7); }
.news { display: flex; gap: 12px; align-items: flex-start; }
.news .th { width: 54px; height: 54px; border-radius: 12px; flex: none; display: flex;
            align-items: center; justify-content: center; font-weight: 660; font-size: 15px; }
.news .grow { flex: 1; min-width: 0; }
.news .t { font-size: 15.5px; font-weight: 600; letter-spacing: -.012em; line-height: 1.32; }
.news .meta { font-size: 12.5px; color: var(--ink-3); margin-top: 5px; }

/* ---------- полоски результата теста */
.bars { display: grid; gap: 11px; }
.brow { display: grid; grid-template-columns: 96px 1fr; gap: 12px; align-items: center; }
.brow .nm { font-size: 14px; color: var(--ink-2); }
.brow .tr { height: 7px; border-radius: 4px; background: var(--line-2); overflow: hidden; }
.brow .tr i { display: block; height: 100%; border-radius: 4px;
              background: linear-gradient(90deg, var(--acc-2), var(--acc)); }
/* полоска в тоне своего направления: тот же цвет, что у иконок кружков */
.brow .tr i.tech  { background: linear-gradient(90deg, #6f9dff, #2563eb); }
.brow .tr i.art   { background: linear-gradient(90deg, #e784b6, #c0397f); }
.brow .tr i.sport { background: linear-gradient(90deg, #5fce97, #0f9d58); }
.brow .tr i.sci   { background: linear-gradient(90deg, #a983f0, #7c3aed); }
.brow .tr i.soc   { background: linear-gradient(90deg, #e3b269, #b5741b); }
.brow .tr i.tour  { background: linear-gradient(90deg, #56bdb4, #0d9488); }
.brow .vl { font-size: 13px; color: var(--ink-3); text-align: right; }
.brow.top .nm { color: var(--ink); font-weight: 570; }

/* шкалы методики: имя длинное, поэтому стоит над полоской, а не сбоку */
.sbars { display: grid; gap: 15px; }
.sbar { display: grid; grid-template-columns: 1fr auto; gap: 3px 10px; align-items: baseline; }
.sbar .nm { font-size: 14.5px; color: var(--ink-2); }
.sbar .vl { font-size: 13.5px; color: var(--ink-2); font-variant-numeric: tabular-nums; }
.sbar .vl i { font-style: normal; color: var(--ink-3); margin-left: 3px; }
.sbar .tr { grid-column: 1 / -1; height: 7px; border-radius: 4px;
            background: var(--line-2); overflow: hidden; }
.sbar .tr i { display: block; height: 100%; border-radius: 4px;
              background: linear-gradient(90deg, var(--acc-2), var(--acc)); }
.sbar.top .nm, .sbar.top .vl { color: var(--ink); font-weight: 570; }

/* ---------- состояния и кнопки */
.btn { display: flex; align-items: center; justify-content: center; gap: 8px; width: 100%;
       min-height: var(--tap); border-radius: var(--r-s); background: var(--acc);
       color: var(--on-acc);
       font-size: 16px; font-weight: 580; }
.btn { text-decoration: none; }
.btn.soft { background: var(--acc-soft); color: var(--acc-ink); }
.btn.ghost { background: transparent; color: var(--ink-2); border: 1px solid var(--line); }
.btn svg { width: 19px; height: 19px; }
.btns { display: grid; gap: 8px; margin-top: 12px; }
.dot { width: 8px; height: 8px; border-radius: 50%; flex: none; }
.dot.ok { background: var(--ok); } .dot.wait { background: var(--gold); }
.note { border-radius: var(--r-s); padding: 12px 13px; font-size: 13.5px; line-height: 1.42;
        background: var(--gold-soft); color: var(--ink-2); }
.note b { color: var(--ink); }
/* Приглашение поговорить с психологом это якорь экрана, а не еще одна подсказка.
   На полной карточке ребенка прямо над ним стоит золотая заметка про
   направления, и на одной подложке они слипались в один блок: самое важное
   сообщение продукта читалось как продолжение совета про кружки. */
.note.care { background: var(--card); padding: 16px; margin-top: 22px; }
.note.care > b { display: block; font-size: 15px; line-height: 1.3;
                 letter-spacing: -.01em; margin-bottom: 6px; }

/* ---------- дата в строке события */
/* объявление для скринридера: на экране его не видно, но он читается */
.sr { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
      overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

/* ---------- события: дата и вид
   вид события несет цвет: конкурс это одно решение семьи, учебная смена другое,
   и различить их надо раньше, чем человек дочитает подпись */
.rows .when { width: 46px; flex: none; text-align: center; line-height: 1.05;
              padding: 7px 0 8px; border-radius: 12px; }
/* тон вида события должен перебивать серый по умолчанию, а не наоборот:
   :where даст нулевую специфичность, как у иконки кружка */
:where(.rows .when) { background: var(--line-2); color: var(--ink-2); }
.rows .when b { display: block; font-size: 19px; font-weight: 660; letter-spacing: -.03em;
                font-variant-numeric: tabular-nums; }
.rows .when span { font-size: 11.5px; }
/* прозрачность тут нельзя: 11,5px через opacity .78 давали 3,5 к янтарной
   подложке при 5,4 у полного тона. Разводим день и месяц кеглем и весом */
.rows .when b.span { font-size: 15px; letter-spacing: -.02em; }
.e-comp  { background: rgba(124,58,237,.17); color: #5b21b6; }
.e-near  { background: rgba(224,149,42,.26); color: #7e5307; }
.e-learn { background: rgba(13,148,136,.19); color: #0b5b55; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .e-comp { color: #b18bff }
  :root:not([data-theme="light"]) .e-near { color: #f0b354 }
  :root:not([data-theme="light"]) .e-learn { color: #35c9ba }
}
:root[data-theme="dark"] .e-comp { color: #b18bff }
:root[data-theme="dark"] .e-near { color: #f0b354 }
:root[data-theme="dark"] .e-learn { color: #35c9ba }

/* строка вида: иконка в тоне события, подпись и возраст тихие */
/* вид события и возраст переносятся, а не обрезаются: точку-разделитель между
   ними ставить нельзя, на переносе она уедет в начало строки */
.ekind { display: flex; flex-wrap: wrap; align-items: center; column-gap: 10px;
         row-gap: 1px; margin-top: 3px; min-width: 0; font-size: 13px; color: var(--ink-3); }
.ekind > span { min-width: 0; }
.ekind i { font-style: normal; white-space: nowrap; }
.ei { width: 15px; height: 15px; flex: none; stroke-width: 1.9; background: none; }
.tag .ei { width: 13px; height: 13px; }
.tag .tick { width: 12px; height: 12px; stroke-width: 2.6; }
.tag.fit { background: var(--acc-soft); color: var(--acc-ink); white-space: normal; }
.tag.good { background: var(--ok-soft); color: var(--ok); }

/* ссылка внутри тихой подписи: кнопка тут была бы громче самого текста */
.lnk { background: none; padding: 6px 0; font: inherit; color: var(--acc-ink);
       font-weight: 570; text-decoration: underline; text-underline-offset: 2px; }
.lnk:focus-visible { outline: 2px solid var(--acc); outline-offset: 2px; border-radius: 6px; }

/* квадратная иконка в строке списка */
.pic.sq { width: 38px; height: 38px; border-radius: 11px; flex: none; display: flex;
          align-items: center; justify-content: center; }
/* цвет по умолчанию через :where: у него нулевая специфичность, поэтому тон
   направления (.d-tech и родня) перебивает серый, а не наоборот */
:where(.pic.sq) { background: var(--line-2); color: var(--ink-2); }
.pic.sq svg { width: 20px; height: 20px; }
/* сохраненное: закладка заливается, а не меняет цвет. Разницу между
   пустым и залитым контуром видно с расстояния вытянутой руки, разницу
   между двумя оттенками серого - нет */
.pic.sq.on { background: var(--acc-soft); color: var(--acc-ink); }
.bm.on { fill: currentColor; }

/* переключатель согласия: состояние видно с одного взгляда */
.sw { width: 44px; height: 26px; border-radius: 13px; background: var(--line);
      position: relative; flex: none; transition: background .16s ease; }
.sw::after { content: ""; position: absolute; top: 3px; left: 3px; width: 20px; height: 20px;
             border-radius: 50%; background: var(--card); transition: transform .16s ease; }
.sw.on { background: var(--ok); }
.sw.on::after { transform: translateX(18px); }

/* карточка-кнопка на всю ширину и пустое состояние */
.card.wide { display: block; width: 100%; text-align: left; }
.card.wide .chev { align-self: center; }
.card.empty { text-align: center; padding: 26px 18px 22px; }
.card.empty .pic { width: 54px; height: 54px; border-radius: 16px; margin: 0 auto;
                   display: flex; align-items: center; justify-content: center; }
.card.empty .pic svg { width: 26px; height: 26px; }
.card.empty p { max-width: 34ch; margin: 8px auto 14px; text-wrap: pretty; }
.card.empty .btn { max-width: 280px; margin: 0 auto; }

/* ---------- нижняя навигация */
nav { position: fixed; left: 0; right: 0; bottom: 0; z-index: 7;
      background: color-mix(in srgb, var(--card) 90%, transparent);
      backdrop-filter: saturate(1.5) blur(14px); border-top: 1px solid var(--line);
      padding-bottom: env(safe-area-inset-bottom); }
nav .inner { max-width: 620px; margin: 0 auto; display: flex; }
nav button { flex: 1; min-width: 0; padding: 9px 0 10px; display: flex; flex-direction: column;
             align-items: center; gap: 3px; color: var(--ink-3); font-size: 11px; font-weight: 550; }
nav button svg { width: 23px; height: 23px; }
nav button span { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
nav button.on { color: var(--acc); }

/* ---------- нижний лист: выбор школы, карточка кружка, код для ребенка */
#sheet:empty { display: none; }
.scrim { position: fixed; inset: 0; z-index: 8; background: rgba(6, 10, 18, .48);
         animation: fade .18s ease; }
.pane { position: fixed; left: 0; right: 0; bottom: 0; z-index: 9;
        max-height: 88vh; overflow-y: auto; background: var(--bg);
        border-top: 1px solid var(--line);
        border-radius: 22px 22px 0 0; padding: 6px var(--pad) calc(22px + env(safe-area-inset-bottom));
        animation: rise .22s cubic-bezier(.22,.85,.3,1); }
.pane::before { content: ""; display: block; width: 38px; height: 4px; border-radius: 2px;
                background: var(--line); margin: 8px auto 14px; }
.pane > .btn { margin-top: 14px; }
.pane > .btn + p, .pane > .btn + .btn { margin-top: 12px; }
.pane .head { display: flex; align-items: center; gap: 10px; margin-bottom: 14px; }
.pane .head b { flex: 1; font-size: 18px; font-weight: 650; letter-spacing: -.024em;
                line-height: 1.24; }
.pane .x { width: 44px; height: 44px; flex: none; border-radius: 12px; display: flex;
           align-items: center; justify-content: center; color: var(--ink-2);
           background: var(--card); border: 1px solid var(--line); }
.pane .x svg { width: 18px; height: 18px; stroke-width: 2; }
.pane p { margin: 0 0 12px; }
.pane .rows { max-height: 52vh; overflow-y: auto; }
/* список внутри листа, который прокручивается вместе с листом: два вложенных
   скролла на телефоне читаются как обрыв списка */
.pane .rows.full { max-height: none; overflow: visible; }
.pane.still, .scrim.still { animation: none; }
@keyframes fade { from { opacity: 0 } }
@keyframes rise { from { transform: translateY(100%) } }

/* ---------- поля формы */
.fld { display: block; margin-bottom: 12px; }
.fld > span { display: block; font-size: 12.5px; font-weight: 600; color: var(--ink-2);
              margin-bottom: 6px; }
.fld input { width: 100%; min-height: var(--tap); padding: 0 14px; background: var(--card);
             border: 1px solid var(--line); border-radius: var(--r-s); color: var(--ink);
             font: inherit; }
.fld input::placeholder { color: var(--ink-3); }
/* синяя рамка это подсветка активного поля, а не признак фокуса с клавиатуры:
   кольцо гасим только там, где фокус пришел мышью или пальцем */
.fld input:focus { border-color: var(--acc); }
.fld input:focus:not(:focus-visible) { outline: none; }
.pick { display: flex; align-items: center; gap: 10px; width: 100%; min-height: var(--tap);
        padding: 0 13px 0 14px; background: var(--card); border: 1px solid var(--line);
        border-radius: var(--r-s); text-align: left; }
.pick .chev { margin-left: auto; }
/* строка с выбранным районом над поиском школы */
.where { display: flex; align-items: center; gap: 9px; width: 100%; min-height: 44px;
         margin-bottom: 10px; padding: 0 2px; color: var(--ink-2); font-size: 14.5px; }
.where svg { width: 18px; height: 18px; color: var(--ink-4); flex: none; }
.where span { flex: 1; text-align: left; color: var(--ink); font-weight: 560; }
.where i { font-style: normal; color: var(--acc); font-size: 13.5px; }
.warn { color: var(--danger); margin-top: 10px; }
.btn.danger { background: var(--danger); color: #fff; }
/* на темной теме --danger светлый, и белый по нему дает около 2,5 к 1. Текст
   там должен быть темным, иначе кнопку удаления просто не прочесть */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .btn.danger { color: #2a0b0b; }
}
:root[data-theme="dark"] .btn.danger { color: #2a0b0b; }
.code { word-break: break-all; font-size: 13.5px; background: var(--card); color: var(--ink-2);
        border: 1px solid var(--line); border-radius: var(--r-s); padding: 12px 13px;
        margin-bottom: 12px; }

/* ---------- заглушка на время загрузки: экран не прыгает */
.skel { height: 96px; border-radius: var(--r); margin-bottom: 10px;
        background: linear-gradient(100deg, var(--line-2) 30%, var(--line) 50%, var(--line-2) 70%);
        background-size: 240% 100%; animation: shine 1.3s linear infinite; }
.skel.s2 { height: 132px; } .skel.s3 { height: 132px; opacity: .6; }
@keyframes shine { from { background-position: 140% 0 } to { background-position: -40% 0 } }

.lead { font-size: 16px; line-height: 1.5; color: var(--ink-2); margin: 0 0 22px; max-width: 38ch; }


/* ---------- опросник: отдельный режим, вкладки на время уходят.
   Один вопрос на экран, вариант нажимается пальцем не глядя, прогресс виден всегда. */
body.quiz-on nav { display: none; }
body.quiz-on main { padding-bottom: calc(40px + env(safe-area-inset-bottom)); }
.qtop { display: flex; align-items: center; gap: 14px; padding: 8px 0 4px;
        position: sticky; top: 0; z-index: 5;
        background: color-mix(in srgb, var(--bg) 88%, transparent);
        backdrop-filter: saturate(1.5) blur(14px); }
.qtop .x { width: 44px; height: 44px; margin: 0 -11px; display: flex;
           align-items: center; justify-content: center; color: var(--ink-2); flex: none; }
.qtop .x[disabled] { opacity: .25; }
/* подпись в шапке кабинета и карты. Без flex крестик вставал сразу за
   текстом и гулял по строке вслед за длиной имени ребенка */
.qtop .ktitle { flex: 1; min-width: 0; font-size: 13px; font-weight: 560;
                color: var(--ink-2); white-space: nowrap;
                overflow: hidden; text-overflow: ellipsis; }
.qtop .x svg { width: 21px; height: 21px; }
.qbar { flex: 1; height: 4px; border-radius: 2px; background: var(--line); overflow: hidden; }
.qbar.hidden { background: none; }
.qbar i { display: block; height: 100%; border-radius: 2px; background: var(--acc);
          transition: width .22s ease; }
.qnum { font-size: 13.5px; font-weight: 580; color: var(--ink-2); flex: none;
        font-variant-numeric: tabular-nums; }
.qnum i { font-style: normal; color: var(--ink-3); font-weight: 400; }
.qkicker { margin: 26px 0 0; font-size: 12.5px; font-weight: 560; color: var(--ink-3); }
.qtext, h1.qtext { margin: 9px 0 26px; font-size: 25px; line-height: 1.24; font-weight: 620;
         letter-spacing: -.028em; text-wrap: balance; color: var(--ink); }
.qtext:focus-visible, .qhead:focus-visible,
.qtop + h1:focus-visible { outline: none; }
.qhead.num { font-size: 52px; letter-spacing: -.04em; }
.qhead.num em { font-size: .36em; }
/* крупная цифра итога: индекс ВОЗ, процент тревожности */
.qhead em { font-style: normal; font-weight: 500; color: var(--ink-3);
            font-size: .48em; margin-left: 8px; }
.brow .vl i { font-style: normal; color: var(--ink-4); }
.qopts { display: grid; gap: 9px; }
.qopts > button { display: flex; align-items: center; gap: 12px; width: 100%;
                  min-height: var(--tap); padding: 13px 15px; text-align: left;
                  background: var(--card); border: 1px solid var(--line);
                  border-radius: var(--r-s); font-size: 16px; line-height: 1.34;
                  transition: background .12s ease, border-color .12s ease, transform .1s ease; }
.qopts > button:active { background: var(--acc-soft); border-color: var(--acc);
                         transform: scale(.993); }
.qopts > button.taken { background: var(--acc-soft); border-color: var(--acc); }
/* ответ, который тут стоял до шага назад */
.qopts > button.was { border-color: var(--acc); }
.qopts > button.was::after { content: "было"; margin-left: auto; font-size: 12px;
                             color: var(--acc); flex: none; }
.qopts.pairs > button { align-items: flex-start; padding: 15px; }
.qopts.pairs .ab { width: 26px; height: 26px; flex: none; border-radius: 8px;
                   display: flex; align-items: center; justify-content: center;
                   background: var(--acc-soft); color: var(--acc);
                   font-size: 13px; font-weight: 640; margin-top: 1px; }
/* кто отвечает на опросник. Имя .who занято блоком имени в шапке (.kid .who),
   и без своего имени эта строка молча сдвигала шапку на всех экранах */
.qwho { margin: -12px 0 22px; font-size: 13.5px; font-weight: 560; color: var(--ink-2); }
.facts { display: flex; gap: 26px; margin-bottom: 13px; }
.facts b { display: block; font-size: 25px; font-weight: 660; letter-spacing: -.03em;
           font-variant-numeric: tabular-nums; line-height: 1.1; }
.facts span { font-size: 12.5px; color: var(--ink-3); }
/* советы семье: несколько мыслей в одной карточке, разделенных волоском.
   Буллиты тут не годятся - список пунктов про своего ребенка читается как
   перечень претензий, а это ровно то, чего мы добиваемся не допустить */
.adv p { margin: 0; font-size: 15px; line-height: 1.5; color: var(--ink-2); }
.adv p + p { margin-top: 15px; padding-top: 15px; border-top: 1px solid var(--line-2); }
/* советы отсортированы по срочности, и первый должен читаться первым: три
   одинаковых абзаца подряд человек читает как один кусок прозы */
.adv .lead1 { font-size: 15.5px; color: var(--ink); }
.adv .mo { color: var(--ink-3); font-size: 13.5px; }
/* «из 72» рядом с самим числом, а не хвостом в подписи: без этого 58 не говорит
   ничего, а человек ищет норму глазами по всей карточке */
.facts b i { font-style: normal; font-size: 14px; font-weight: 500; color: var(--ink-3);
             margin-left: 6px; letter-spacing: 0; }
.report { font-size: 15px; line-height: 1.52; color: var(--ink-2); margin: 0 0 12px; }
.report:last-child { margin-bottom: 0; }
.report-list { margin: 0 0 12px; padding: 0; list-style: none; display: grid; gap: 9px; }
.report-list:last-child { margin-bottom: 0; }
.report-list li { font-size: 15px; line-height: 1.45; color: var(--ink-2);
                  padding-left: 15px; position: relative; }
.report-list li::before { content: ""; position: absolute; left: 0; top: 9px;
                          width: 5px; height: 5px; border-radius: 50%; background: var(--acc); }
.btn.wide { margin-top: 18px; }
.small.center { text-align: center; }
.dot.half { background: var(--acc); }
/* «не открывается» показываем серой точкой и отсутствием шеврона, а не
   прозрачностью: подпись под названием это единственное место, где написано,
   почему строка не нажимается, и гасить ее до нечитаемого значит спрятать
   причину. Было opacity .62 — подпись давала 2,5 к фону */
.rows .off { color: var(--ink-2); }
.rows .off .dot { background: var(--ink-4); }


/* ---------- фильтры выдачи: кнопка со счетчиком и группы вариантов в листе */
.tools { display: flex; align-items: center; gap: 8px; margin-bottom: 14px; }
.tools .seg { flex: 1; margin: 0; }
.chip.filt { display: inline-flex; align-items: center; gap: 7px; }
.chip.filt svg { width: 18px; height: 18px; stroke: currentColor; }
.chip.filt i { font-style: normal; font-weight: 660; font-size: 12.5px; min-width: 19px;
       height: 19px; padding: 0 5px; border-radius: 10px; display: inline-flex;
       align-items: center; justify-content: center; background: var(--on-acc);
       color: var(--acc); }
.fgr { margin-bottom: 16px; }
.flab { display: block; margin-bottom: 8px; font-size: 12.5px; font-weight: 600;
        color: var(--ink-2); }
.opts { display: flex; flex-wrap: wrap; gap: 7px; }
.pane .rows { margin-bottom: 4px; }
/* лист фильтров открывается сфокусированным на себе, чтобы кольцо не село на чип.
   Само кольцо на листе не нужно: он и так занимает пол-экрана */
.pane:focus { outline: none; }
.pair { display: flex; gap: 10px; margin-top: 10px; }
.pair .btn { margin-top: 0; }
/* на узком экране лист прокручивается, а главные кнопки должны оставаться на виду */
.acts { position: sticky; bottom: calc(-22px - env(safe-area-inset-bottom));
        z-index: 1; margin: 14px 0 calc(-22px - env(safe-area-inset-bottom));
        padding: 12px 0 calc(24px + env(safe-area-inset-bottom));
        background: var(--bg); border-top: 1px solid var(--line); }
.acts > .btn { margin-top: 0; }
.fnote { margin: 9px 2px 0; font-size: 12.5px; line-height: 1.4; color: var(--ink-3); }

/* ---------- карта кружков: переключатель и сама подложка */
.seg { display: flex; gap: 3px; padding: 3px; margin: 0 0 16px;
       background: var(--line-2); border-radius: 11px; }
.seg button { flex: 1; min-height: 44px; border-radius: 9px; font-size: 14.5px;
              white-space: nowrap;
              font-weight: 560; color: var(--ink-2); transition: background .14s ease; }
.seg button.on { background: var(--card); color: var(--ink); }
/* своя система слоев у карты: у leaflet внутри z-index до тысячи, и без
   собственного контекста карта вылезала поверх нижнего листа */
.map { position: relative; z-index: 0; height: 54vh; min-height: 300px;
       border-radius: var(--r); border: 1px solid var(--line); overflow: hidden;
       background: var(--line-2); }
.mapnote { margin: 9px 2px 0; font-size: 12.5px; line-height: 1.4; color: var(--ink-3); }
/* подложку в темной теме приглушаем: белая карта в ночном интерфейсе слепит.
   Правило про системную тему обязано жить внутри своего media, иначе инверсия
   применится и днем */
:root[data-theme="dark"] .leaflet-tile-pane { filter: invert(1) hue-rotate(180deg)
       brightness(.92) contrast(.92) saturate(.75); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .leaflet-tile-pane { filter: invert(1) hue-rotate(180deg)
         brightness(.92) contrast(.92) saturate(.75); }
}
.leaflet-container { font: inherit; background: var(--line-2); }
/* метка места: видимая точка 24 px внутри тап-зоны 44 px */
.mp i { display: flex; width: 24px; height: 24px; margin: 11px; border-radius: 50%;
        align-items: center; justify-content: center; border: 2px solid #fff;
        color: #fff; font: 600 11.5px/1 -apple-system, "SF Pro Text", sans-serif;
        font-style: normal; }
/* метка нескольких мест: крупнее и нейтрального тона, чтобы не выдавать себя
   за одно направление */
.mp.many i { width: 32px; height: 32px; margin: 7px; font-size: 13px; }
.leaflet-tooltip.tip-home { font-weight: 600; padding: 3px 8px; }
.leaflet-control-attribution { background: color-mix(in srgb, var(--card) 86%, transparent)
       !important; color: var(--ink-3) !important; }
.leaflet-control-attribution a { color: var(--ink-2) !important; }
.leaflet-bar, .leaflet-tooltip { box-shadow: none !important; }
.leaflet-bar { border: 1px solid var(--line) !important; }
.leaflet-tooltip { background: var(--card) !important; color: var(--ink) !important;
       border-color: var(--line) !important; }
.leaflet-control-zoom a { color: var(--ink) !important; background: var(--card) !important;
       border-color: var(--line) !important; width: 40px !important; height: 40px !important;
       line-height: 40px !important; font-size: 22px !important; }

@media (prefers-reduced-motion: reduce) {
  .scrim, .pane, .skel { animation: none; }
  .qbar i { transition: none; }
}

/* ---------- курс: карточка набора и согласие при записи */
/* знак программы рядом с названием: чужой логотип в нашей системе живет на
   своей подложке, чтобы его цвета не спорили с акцентом приложения */
.course-head { display: flex; align-items: center; gap: 12px; }
.course-head .mark { width: 54px; height: 48px; flex: none; object-fit: contain;
                     border-radius: var(--r-s); background: var(--line-2); padding: 4px; }
.course-head .grow { flex: 1; min-width: 0; }

/* согласие перед записью: галочку ставит человек, поэтому зона тапа во всю
   строку, а не в сам квадратик размером с ноготь */
.check { display: flex; gap: 11px; align-items: flex-start; margin: 14px 0 16px;
         padding: 12px 13px; border-radius: var(--r-s); background: var(--line-2);
         cursor: pointer; }
.check input { width: 22px; height: 22px; flex: none; margin: 0; accent-color: var(--acc); }
.check span { color: var(--ink-2); }

/* ---------- викторина по предметам
   Главное на экране - сам вопрос, его надо прочесть за секунду. Время не
   отбирает у него места: оно показано полосой, которая утекает, и движение
   видно боковым зрением. Счет стоит в строке над вопросом и прыгает после
   каждого ответа: связь «быстрее - дороже» человек должен увидеть, а не
   вычитать из правил. */
/* полоса утекает справа налево, к цифре секунд: вместе они читаются как одно
   «сколько осталось». Если оставить ее прижатой влево, заполненный кусок
   читается наоборот - как «сколько пройдено» */
.gtime { flex: 1; height: 6px; border-radius: 3px; background: var(--line);
         overflow: hidden; display: flex; justify-content: flex-end; }
.gtime i { display: block; height: 100%; width: 100%; border-radius: 3px;
           background: var(--acc); }
/* последние секунды: ответ еще стоит очков, но пора жать */
.gtime.hot i { background: var(--danger); }
.gsec { flex: none; min-width: 20px; text-align: right; font-size: 13.5px;
        font-weight: 580; font-variant-numeric: tabular-nums; color: var(--ink-2);
        transition: color .15s ease; }
/* полоска живет на краю бокового зрения, и одного ее цвета мало: меняется и
   цифра, у которой ребенок как раз и смотрит, сколько осталось */
.gsec.hot { color: var(--danger); font-weight: 680; }
.qkicker.gk { display: flex; align-items: baseline; justify-content: space-between;
              gap: 12px; }
/* счет идет той же строкой, что и предмет, и таким же тихим: во время вопроса
   он не должен спорить с самим вопросом за внимание. Его минута - после
   ответа, когда рядом вылетает «плюс столько-то» */
.gpts { flex: none; position: relative; font-size: 12.5px; font-weight: 560;
        color: var(--ink-2); font-variant-numeric: tabular-nums; }
/* сколько принес этот ответ. Это носитель главной мысли игры, поэтому крупнее
   самого счета и висит весь разбор, а гаснет только в конце. Считается от
   счета, иначе внутри флекса улетает в левый край */
.gfly { position: absolute; right: 0; bottom: 100%; margin-bottom: 3px;
        font-size: 17px; font-weight: 680; letter-spacing: -.02em; white-space: nowrap;
        font-variant-numeric: tabular-nums; color: var(--ok); pointer-events: none;
        animation: fly .75s ease-out forwards; }
/* подпись успевает появиться, постоять почти весь разбор и уйти ровно тогда,
   когда экран меняется на следующий вопрос */
@keyframes fly {
  0%   { opacity: 0; transform: translateY(5px) }
  16%  { opacity: 1; transform: translateY(0) }
  74%  { opacity: 1; transform: translateY(0) }
  100% { opacity: 0; transform: translateY(-11px) }
}
/* разбор прямо на месте: где был верный ответ, видно до того, как экран уехал.
   Подпись на карточке обязательна - у красно-зеленой слепоты зеленая и красная
   плашки за эту секунду неразличимы, а цвет тут несет весь смысл */
.qopts > button.right { background: var(--ok-soft); border-color: var(--ok); }
.qopts > button.wrong { background: rgba(192, 42, 42, .09); border-color: var(--danger); }
.qopts > button.late { background: var(--gold-soft); border-color: var(--gold); }
:root[data-theme="dark"] .qopts > button.wrong { background: rgba(255, 122, 122, .14); }
.qopts > button.right::after, .qopts > button.wrong::after,
.qopts > button.late::after { margin-left: auto; flex: none; font-size: 12px;
                              font-weight: 600; letter-spacing: -.01em; }
.qopts > button.right::after { content: "верно"; color: var(--ok); }
.qopts > button.wrong::after { content: "мимо"; color: var(--danger); }
.qopts > button.late::after { content: "поздно"; color: var(--gold-ink); }
.qopts.shown > button { pointer-events: none; }
/* остальные варианты уводим в тихий цвет текста, а не гасим прозрачностью:
   притушенная целиком карточка уходит ниже 4,5 к фону и перестает читаться */
.qopts.shown > button:not(.right):not(.wrong):not(.late) { color: var(--ink-3); }

/* строка под вариантами: тут и разбор ответа, и сообщение о связи. Место под
   нее держится всегда, иначе ряды уезжают из-под пальца в момент нажатия */
.gline { min-height: 19px; margin: 11px 0 0; font-size: 13.5px; font-weight: 560;
         line-height: 1.35; color: var(--ink-2); }
.gline.right { color: var(--ok); }
.gline.wrong { color: var(--danger); }
.gline.late { color: var(--gold-ink); }

/* строка разбора после тура: вопрос, что выбрал ребенок, сколько принесло */
.gitem { display: flex; gap: 12px; align-items: flex-start; }
.gitem .grow { flex: 1; min-width: 0; }
.gitem .t { font-weight: 540; letter-spacing: -.01em; line-height: 1.33; }
.gitem .m { font-size: 13px; color: var(--ink-3); margin-top: 3px; }
.gitem .pt { flex: none; font-size: 13.5px; font-weight: 600; color: var(--ink-4);
             font-variant-numeric: tabular-nums; }
.gitem.ok .pt { color: var(--ok); }
.gitem.late .pt { color: var(--gold-ink); }

/* во время тура вопрос с вариантами стоит по центру экрана, а не прижат к
   верху: десять секунд - это не то время, за которое глаз успевает пробежать
   весь экран сверху вниз, а палец дотянуться до середины.
   Центруем полями, а не justify-content: когда вопрос длинный и места не
   хватает, поля схлопываются в ноль и блок просто встает сверху. При
   центровании он в этом случае вылезал бы вверх под липкую шапку, и начало
   вопроса становилось недоступно даже прокруткой */
body.game-on main { display: flex; flex-direction: column;
                    min-height: calc(100svh - env(safe-area-inset-bottom)); }
.gmid { margin-top: auto; margin-bottom: auto; }
.gmid .qkicker { margin-top: 0; }

@media (prefers-reduced-motion: reduce) {
  /* полоса времени остается: это не украшение, а единственный способ понять,
     сколько осталось. Рядом с ней всегда стоят секунды цифрами.
     «Плюс столько-то» без движения просто висит весь разбор: убрать его
     значит убрать смысл, а не анимацию */
  .gfly { animation: none; opacity: 1; }
}


/* ---------- карта захвата территорий

   Три уровня одной механикой: край, свой муниципалитет, квартал вокруг своей
   школы. Геометрия приходит готовым путем в координатах картинки, тут только
   цвета владения и подписи.
*/
/* Цвета владения. Чужие школы идут приглушенными тонами старого атласа, а наша
   одна берет полный акцент: так на экране остается ровно один яркий кусок, и
   вопрос «где мы» читается раньше, чем человек начнет разбираться в остальном.
   Ничья земля не серая дырка, а светлая заливка: пустоты на карте выглядят как
   ошибка загрузки. */
:root {
  /* t1 нарочно обесцвечен: синий тут занят нашей школой, и второй синий на
     карте путает боковое зрение */
  --t1: #93a0b0; --t2: #86b39a; --t3: #d3a85f;
  --t4: #c88aa0; --t5: #5f949e; --t6: #a494c9;
  /* ничья земля должна отличаться от фона страницы: иначе карта выглядит
     обрезанной, а не свободной */
  --t-free: #d8dfec;
  /* на полоске долей свободный хвост лежит прямо на фоне страницы, и там
     тон ничьей земли с ним сливается: лента обрывается на трети ширины */
  --t-track: #c3cde0;
}
/* темная тема приходит двумя путями: системной настройкой и переключателем в
   приложении. Без первой карта оставалась светлой на черной странице, и пустой
   север светился ярче всего занятого */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --t1: #5c6878; --t2: #4f7a66; --t3: #9a7637;
    --t4: #8e5d6e; --t5: #3f6b76; --t6: #6f628f;
    --t-free: #222b3c; --t-track: #2c3850;
  }
}
:root[data-theme="dark"] {
  --t1: #5c6878; --t2: #4f7a66; --t3: #9a7637;
  --t4: #8e5d6e; --t5: #3f6b76; --t6: #6f628f;
  --t-free: #222b3c; --t-track: #2c3850;
}

.kmap { display: block; width: 100%; height: auto; margin: 4px 0 0; }
/* контур рисуем цветом страницы, а не линией: получается зазор между
   территориями, и карта читается плитками без единой грязной черты */
.kmap path { fill: var(--t-free); stroke: var(--bg); stroke-width: 2.4;
             stroke-linejoin: round; cursor: pointer; }
/* подложка: участки покрывают фигуру целиком, и видна она только по краю, где
   у зон срезаны углы. Своего смысла у нее нет, поэтому красим как ничью землю */
.kmap path.base { fill: var(--t-free); stroke: none; pointer-events: none; }
/* свои территории не просто крашены, а еще и обведены: в городе участок школы
   бывает с ноготь, и одной заливки мало, чтобы найти его взглядом за секунду */
.kmap path.mine { fill: var(--acc); stroke: var(--acc-2); stroke-width: 3.6; }
/* свой район на краевой карте: обводка акцентом без заливки. Заливка читалась
   бы как владение, а район может быть и не наш - именно это и надо увидеть */
.kmap path.home { stroke: var(--acc); stroke-width: 6; }
.kmap path.t1 { fill: var(--t1) } .kmap path.t2 { fill: var(--t2) }
.kmap path.t3 { fill: var(--t3) } .kmap path.t4 { fill: var(--t4) }
.kmap path.t5 { fill: var(--t5) } .kmap path.t6 { fill: var(--t6) }

/* подписи кладем поверх карты обычным текстом, а не внутрь svg: кегль внутри
   svg живет в единицах карты и съеживается вместе с ней, на узком экране до
   десяти точек. Тут подпись всегда 12,5 независимо от ширины */
.kwrap { position: relative; }
.klab { position: absolute; transform: translate(-50%, -50%); white-space: nowrap;
        font-size: 12.5px; font-weight: 620; letter-spacing: -.01em; color: var(--ink);
        background: color-mix(in srgb, var(--bg) 80%, transparent);
        padding: 1px 5px; border-radius: 7px; pointer-events: none;
        max-width: 46%; overflow: hidden; text-overflow: ellipsis; }

/* доля территорий счетом, а не площадью. Карта врет про долю: наши участки
   бывают мелкими там, где люди живут кучно, а соседняя тайга огромна.
   Полоска считает участки, и заголовок перестает спорить с картинкой */
.share { display: flex; gap: 2px; margin: 10px 0 2px; }
.share i { flex: 1; height: 8px; border-radius: 3px; background: var(--t-track); }
.share i.mine { background: var(--acc) }
.share i.t1 { background: var(--t1) } .share i.t2 { background: var(--t2) }
.share i.t3 { background: var(--t3) } .share i.t4 { background: var(--t4) }
.share i.t5 { background: var(--t5) } .share i.t6 { background: var(--t6) }
/* в городе делений за сотню: по волоску на школу не разглядеть, поэтому там
   полоска показывает доли одной сплошной лентой */
.share.thin { gap: 0; border-radius: 3px; overflow: hidden; }
.share.thin i { border-radius: 0; }

/* кольцо вокруг своих участков: в городе их кластер мельче собственной
   подписи, и без метки взгляд уходит к самому крупному чужому пятну */
.kmap circle.here { fill: none; stroke: var(--acc); stroke-width: 4; opacity: .85; }

/* весь список участков текстом: на карте умещаются подписи пяти, остальные
   иначе не узнать - ни пальцем в клетку десять точек, ни скринридером */
.kall { margin: 12px 0 0; }
.kall summary { min-height: 44px; display: flex; align-items: center; gap: 6px;
                font-size: 13.5px; font-weight: 560; color: var(--ink-2);
                cursor: pointer; list-style: none; }
.kall summary::-webkit-details-marker { display: none; }
.kall summary::after { content: ""; width: 8px; height: 8px; flex: none;
                       border-right: 2px solid var(--ink-4);
                       border-bottom: 2px solid var(--ink-4);
                       transform: rotate(45deg) translate(-2px, -2px);
                       transition: transform .15s ease; }
.kall[open] summary::after { transform: rotate(-135deg) translate(-3px, -3px); }
.kall .cols { columns: 2; column-gap: 14px; font-size: 12.5px; line-height: 1.5;
              color: var(--ink-3); padding-bottom: 4px; }
.kall .cols div { break-inside: avoid; }
.kall b { color: var(--ink); font-weight: 560; }

/* строка под картой: кто держит территорию, по которой ткнули пальцем. Имен
   всех участков на карте нет и быть не может, а узнать их надо - всплывающей
   подсказки на телефоне не существует, поэтому тап */
.kpick { margin: 6px 0 18px; min-height: 36px; font-size: 13px; line-height: 1.38;
         color: var(--ink-3); }
.kpick b { color: var(--ink); font-weight: 600; }

/* таблица владений: место, кто, сколько. Цифры табличные, иначе колонка пляшет */
.tab { display: flex; align-items: center; gap: 12px; }
.tab .no { width: 19px; flex: none; font-size: 13px; font-weight: 600; color: var(--ink-3);
           font-variant-numeric: tabular-nums; }
.tab .dot { width: 11px; height: 11px; border-radius: 4px; flex: none; background: var(--t-free); }
.tab.mine .dot { background: var(--acc) }
.tab .t1 { background: var(--t1) } .tab .t2 { background: var(--t2) }
.tab .t3 { background: var(--t3) } .tab .t4 { background: var(--t4) }
.tab .t5 { background: var(--t5) } .tab .t6 { background: var(--t6) }
.tab .grow { flex: 1; min-width: 0; }
.tab .nm { font-weight: 540; letter-spacing: -.01em; overflow: hidden;
           text-overflow: ellipsis; white-space: nowrap; }
/* под именем школы перечислены ее территории: иначе имя участка есть только
   внутри картинки, а туда еще надо попасть пальцем */
.tab .m { display: block; font-size: 12.5px; color: var(--ink-3); margin-top: 2px;
          line-height: 1.33; }
.tab .vl { flex: none; font-size: 13.5px; font-weight: 600;
           font-variant-numeric: tabular-nums; }
.tab.mine .nm { font-weight: 640 }
.tab.mine .vl { color: var(--acc-ink) }

/* счетчик на кнопке карты: число участков прямо на входе. Кнопка без числа
   не говорит, зачем ее нажимать, и ее не нажимают */
.btn.ghost .cnt { margin-left: 8px; padding-left: 9px; font-weight: 560;
                  color: var(--ink-3); font-variant-numeric: tabular-nums;
                  border-left: 1px solid var(--line); }

/* подпись своей территории. На краевой карте свой городской округ занимает
   семь пикселей: обводку видно только на подписи */
.klab.home { background: var(--acc); color: var(--on-acc); }

/* ---------- кабинет участника курса

   Занятие в списке это номер, название и отметка. Номер слева держит колонку
   ровной: расписание читают глазами сверху вниз, и пляшущий левый край мешает
   сильнее, чем кажется. */
.les { display: flex; align-items: flex-start; gap: 12px; }
/* номер занятия это содержание, а не разделитель, поэтому --ink-3: --ink-4
   дает 2,9 к 1 и на светлой теме не читается */
.les .no { width: 22px; flex: none; font-size: 13px; font-weight: 620; color: var(--ink-3);
           font-variant-numeric: tabular-nums; padding-top: 1px; }
.les .grow { flex: 1; min-width: 0; }
.les .nm { font-weight: 560; letter-spacing: -.01em; line-height: 1.3; display: block; }
.les .m { display: block; font-size: 12.5px; color: var(--ink-3); margin-top: 3px;
          line-height: 1.35; }
/* прошедшее занятие тише будущего: расписание смотрят, чтобы узнать, что
   впереди, а не чтобы перечитывать прошлую неделю */
.les.past .nm { font-weight: 520; color: var(--ink-2); }
/* ближайшее занятие единственное, что выделено: это и есть ответ на вопрос,
   с которым человек открыл экран */
.les.next { background: var(--acc-soft); }
.les.next .no { color: var(--acc-ink); }
.les.next .nm { font-weight: 640; }
/* отметка о посещении: короткое слово справа, без рамок и галочек */
.lm { flex: none; font-size: 12px; font-weight: 580; color: var(--ink-3);
      padding-top: 2px; white-space: nowrap; }
.lm.ok { color: var(--ok); }
/* не .no: этим классом в той же строке помечен номер занятия шириной 22px,
   и отметка «не был» молча обрезалась его шириной */
.lm.miss { color: var(--ink-2); }
/* «не отмечено» это отсутствие записи, а не событие: тише пропуска */
.lm.none { font-weight: 440; color: var(--ink-3); }
/* объявления идут группой: между собой они ближе, чем до своего заголовка.
   Собственный margin-bottom карточки тут мешает, поэтому гасим его и ставим
   свой - иначе соседние маржины схлопываются в 18px и группа разъезжается */
.card.post { margin-bottom: 9px; }
.card.post:last-child { margin-bottom: 18px; }

/* название команды это не заголовок третьего уровня: между h1 экрана и h2
   «Занятия» он создавал скачок уровней, которого скринридер не ждет */
.card .nm.big { margin: 0; font-size: 16.5px; font-weight: 620; letter-spacing: -.016em; }

/* список занятий это список: ul дает скринридеру число пунктов и навигацию,
   а маркеры нам не нужны */
.rows.bare { list-style: none; margin-left: 0; padding-left: 0; }

/* посещаемость одним тоном на обоих экранах. .free в приложении значит
   «бесплатно», занимать его под табель нельзя */
.tag.mark { background: var(--acc-soft); color: var(--acc-ink); }

/* ---------- пазл сезона
   Картинка собирается на глазах, поэтому фон лежит на всей сетке, а закрытые
   куски его перекрывают: открыть кусок значит убрать заслонку, и соседние
   фрагменты сходятся сами. Пока картинки сезона нет, под заслонками лежит
   градиент - собирать его так же интересно, как фотографию */
/* без зазоров: открытые куски должны сойтись в одну картинку, а не остаться
   плитками. Сетку рисуют сами заслонки, и она исчезает вместе с ними */
.puz { display: grid; border-radius: var(--r-s); overflow: hidden;
       background: linear-gradient(135deg, #f5b93b 0%, #e0952a 28%, #c05a2a 58%, #2b3a55 100%);
       background-size: cover; background-position: center; }
.puz b { aspect-ratio: 1; display: flex; align-items: center; justify-content: center;
         background: var(--bg); color: var(--ink-4); font-size: 13px; font-weight: 640;
         font-variant-numeric: tabular-nums; transition: opacity .45s ease;
         box-shadow: inset 0 0 0 1px var(--line); }
.puz b.on { opacity: 0; }
/* кусок, который открылся прямо сейчас: показываем, какой именно, иначе в
   сетке из двенадцати клеток человек не заметит свою награду */
@keyframes puz-pop { 0% { opacity: 1; transform: scale(1); }
                     40% { opacity: .5; transform: scale(.82); }
                     100% { opacity: 0; transform: scale(1); } }
.puz b.just { animation: puz-pop .7s ease forwards; }
.puz-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
/* викторина на главной: мягкая акцентная подложка и значок. Яркий геройский
   блок тут был бы второй по счету на экране, и два ярких пятна спорят - поэтому
   тот же синий, но в треть силы, а список внутри остается белым */
.card.quiz { background: linear-gradient(165deg, var(--acc-soft), transparent 62%),
             var(--card); border-color: var(--acc-soft); }
.card.quiz > h3 { display: flex; align-items: center; gap: 9px; color: var(--acc-ink); }
.qbadge { width: 27px; height: 27px; border-radius: 9px; background: var(--acc);
          display: grid; place-items: center; flex: none; }
.qbadge svg { width: 16px; height: 16px; stroke: var(--on-acc); }
/* «идет тур» это срок, а не украшение: он виден только пока тур открыт */
.qlive { margin-left: auto; font-size: 11.5px; font-weight: 620; letter-spacing: .01em;
         text-transform: lowercase; color: var(--on-acc); background: var(--acc);
         border-radius: 999px; padding: 3px 9px; }

/* отметка «сыграно» в списке предметов. Несыгранному оставляем пустой кружок,
   а не пустоту: иначе строки съезжают по горизонтали и список читается криво */
.rows.game > button { align-items: center; }
.gdone, .gdot { flex: none; width: 18px; height: 18px; border-radius: 50%; }
.gdone { background: var(--ok); display: grid; place-items: center; }
.gdone svg { width: 12px; height: 12px; stroke: #fff; stroke-width: 3; }
.gdot { border: 1.5px solid var(--line); }

/* строка предмета в викторине: сверху сам предмет, снизу тихо - что с ним
   сейчас. В одну строку они сливались в «Математика тренировка» */
.rows.game .nm { display: block; font-weight: 560; letter-spacing: -.01em; line-height: 1.3; }
.rows.game .m { display: block; font-size: 12.5px; color: var(--ink-3); margin-top: 3px;
                line-height: 1.38; }

/* выбор предмета сеткой. Списком восемь предметов это целый экран, а решение
   тут одно и короткое: прочитать название и ткнуть. Хайрлайны рисует тот же
   зазор грида, что и в обычном списке, поэтому клетки не разъезжаются.
   Стрелки в клетке нет: нажимается вся клетка, а восемь стрелок подряд шум */
.rows.game.grid2 { grid-template-columns: 1fr 1fr; }
.rows.game.grid2 > button { align-items: flex-start; gap: 9px; padding: 14px 13px; }
/* в клетке вдвое меньше ширины, чем в строке, а названия предметов длинные:
   «Обществознание» одним словом не переносится и вылезает за край */
.rows.game.grid2 .nm { font-size: 15px; letter-spacing: -.015em; overflow-wrap: anywhere; }

.puz-n { font-size: 13px; font-weight: 620; color: var(--ink-3);
         font-variant-numeric: tabular-nums; white-space: nowrap; }
/* задания идут списком под картинкой: сделанное тише несделанного, потому что
   смотрят сюда ради того, что еще можно сделать */
.puz-task .nm { display: block; font-weight: 560; letter-spacing: -.01em; line-height: 1.3; }
.puz-task .m { display: block; font-size: 12.5px; color: var(--ink-3); margin-top: 3px;
               line-height: 1.38; }
.puz-task { align-items: flex-start; }
.puz-task .pn { padding-top: 1px; }
/* сделанное подсвечено зеленым, а не притушено. Сначала было наоборот - тише,
   чтобы взгляд искал оставшееся, - но у ребенка это читается как «ничего не
   засчитали». Сделанное это награда, и видно ее должно быть сразу */
.rows .puz-task.done { background: var(--ok-soft); }
.puz-task.done .nm { color: var(--ink); font-weight: 580; }
.puz-task.done .m { color: var(--ink-2); }
.puz-task .pn { flex: none; width: 22px; color: var(--ink-4); font-size: 12.5px;
                font-weight: 640; font-variant-numeric: tabular-nums; }
.puz-task.done .pn { color: var(--ok); }
.puz-bonus { color: var(--gold-ink); background: var(--gold-soft); }
