  :root {
    --paper:      #FBFAF6;
    --paper-2:    #F3F1EA;
    /* Фон всплывающих карточек. Переменной не было, и окна питомца и образца
       оставались прозрачными — сквозь них просвечивал экран. */
    --card:       #FFFFFF;
    --grid:       #D9E1EC;
    --rule:       #C9D3E2;
    --ink:        #1B2A4A;
    --ink-soft:   #5A6B87;
    --ink-faint:  #7787A3;
    --accent:     #2563C9;
    --accent-dim: #DCE7FA;
    --grid-l1:    rgba(37,99,201,.16);
    --grid-l2:    rgba(37,99,201,.38);
    --correct:    #1E8A5F;
    --correct-dim:#DCEFE5;
    --wrong:      #C8452E;
    --wrong-dim:  #F8E3DE;
    --gold:       #B8862B;
    /* Буквы на золотой подложке. Само золото светлое и на своей же
       подложке даёт 2.74 — название только что полученной награды
       ребёнок читал с трудом. Рамку и заливку не трогаем. */
    --gold-ink:   #886320;
    --gold-dim:   #F6EBD3;
    --on-accent:  #FFFFFF;
    --shadow:     0 1px 2px rgba(27,42,74,.06), 0 8px 24px rgba(27,42,74,.07);
    --shadow-key: 0 1px 0 rgba(27,42,74,.14);

    --cell: 26px;
    --r: 14px;

    --font-display: ui-rounded, "SF Pro Rounded", "Segoe UI Variable Display", "Nunito", system-ui, sans-serif;
    --font-body: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
  }

  @media (prefers-color-scheme: dark) {
    :root {
      --paper:      #14171F;  --paper-2:    #1A1E28;
      --card:       #1E2430;
      --grid:       #222836;  --rule:       #2C3444;
      --ink:        #E8EBF2;  --ink-soft:   #99A4BA;  --ink-faint: #65728B;
      --accent:     #6BA3F5;  --accent-dim: #1D2A40;
      --correct:    #45C48D;  --correct-dim:#152A22;
      --wrong:      #E8735C;  --wrong-dim:  #2E1C18;
      --gold:       #E0B45E;  --gold-dim:   #2B2314;  --gold-ink: #E0B45E;
      --on-accent:  #10131A;
      --shadow:     0 1px 2px rgba(0,0,0,.3), 0 8px 24px rgba(0,0,0,.35);
      --shadow-key: 0 1px 0 rgba(0,0,0,.4);
    }
  }

  :root[data-theme="dark"] {
    --paper:      #14171F;  --paper-2:    #1A1E28;
    --card:       #1E2430;
    --grid:       #222836;  --rule:       #2C3444;
    --ink:        #E8EBF2;  --ink-soft:   #99A4BA;  --ink-faint: #65728B;
    --accent:     #6BA3F5;  --accent-dim: #1D2A40;
    --grid-l1:    rgba(107,163,245,.16);  --grid-l2: rgba(107,163,245,.38);
    --correct:    #45C48D;  --correct-dim:#152A22;
    --wrong:      #E8735C;  --wrong-dim:  #2E1C18;
    --gold:       #E0B45E;  --gold-dim:   #2B2314;  --gold-ink: #E0B45E;
    --on-accent:  #10131A;
    --shadow:     0 1px 2px rgba(0,0,0,.3), 0 8px 24px rgba(0,0,0,.35);
    --shadow-key: 0 1px 0 rgba(0,0,0,.4);
  }

  :root[data-theme="light"] {
    --paper:      #FBFAF6;  --paper-2:    #F3F1EA;
    /* --card обязателен здесь, а не только в общей палитре. Если система у
       человека тёмная, блок @media prefers-color-scheme перекрывает общую
       палитру, а выбор «Светлая» перекрывает только то, что перечислено тут.
       Без этой строки карточки занятий оставались тёмными, а подписи на них
       красились тёмным по тёмному — контраст 1.09, читать нечего. */
    --card:       #FFFFFF;
    --grid:       #D9E1EC;  --rule:       #C9D3E2;
    --ink:        #1B2A4A;  --ink-soft:   #5A6B87;  --ink-faint: #7787A3;
    --accent:     #2563C9;  --accent-dim: #DCE7FA;
    --grid-l1:    rgba(37,99,201,.16);  --grid-l2: rgba(37,99,201,.38);
    --correct:    #1E8A5F;  --correct-dim:#DCEFE5;
    --wrong:      #C8452E;  --wrong-dim:  #F8E3DE;
    --gold:       #B8862B;  --gold-dim:   #F6EBD3;  --gold-ink: #886320;
    --on-accent:  #FFFFFF;
    --shadow:     0 1px 2px rgba(27,42,74,.06), 0 8px 24px rgba(27,42,74,.07);
    --shadow-key: 0 1px 0 rgba(27,42,74,.14);
  }

  /* ── Оформление: синяя и розовая тема ────────────────
     Меняются только цвета и рисунок на фоне. Размеры, кнопки и порядок
     экранов те же — ребёнок ничего не теряет при переключении.
     data-skin отдельный от data-theme: светлое/тёмное остаётся как было. */

  :root[data-skin="boy"] {
    --paper:      #F4F8FF;  --paper-2:    #E9F1FF;  --card: #FFFFFF;
    --grid:       #D3E2F7;  --rule:       #BFD5F2;
    --ink:        #16294A;  --ink-soft:   #4E6488;  --ink-faint: #7287A8;
    --accent:     #1F62CE;  --accent-dim: #D8E6FC;
    --pattern: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="190" height="190" viewBox="0 0 190 190"><g fill="none" stroke="%232563c9" stroke-opacity="0.07" stroke-width="2.4" stroke-linejoin="round"><path d="M12 40h30l8-9h16l5 9h9v13H12z"/><circle cx="26" cy="55" r="5"/><circle cx="66" cy="55" r="5"/><rect x="84" y="86" width="26" height="22" rx="4"/><circle cx="91" cy="95" r="2.4"/><circle cx="103" cy="95" r="2.4"/><path d="M97 86v-7"/><path d="M84 100h-7M110 100h7"/><path d="M90 108v6M104 108v6"/></g></svg>');
    --pattern-size: 190px 190px;
  }
  :root[data-skin="girl"] {
    --paper:      #FFF6FB;  --paper-2:    #FDEBF4;  --card: #FFFFFF;
    --grid:       #F4D8E7;  --rule:       #EEC7DC;
    --ink:        #3B1B2E;  --ink-soft:   #7A5468;  --ink-faint: #A17A8E;
    --accent:     #C2427F;  --accent-dim: #FBDDEC;
    --pattern: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="190" height="190" viewBox="0 0 190 190"><g fill="none" stroke="%23c2427f" stroke-opacity="0.08" stroke-width="2.4" stroke-linejoin="round"><path d="M14 46c-6 0-9-5-6-9 2-4 8-4 10-1 1-8 12-10 16-3 6-3 12 2 11 8 5 0 6 5 3 7-2 1-31 1-34-2z"/><circle cx="98" cy="84" r="9"/><path d="M98 93v14M90 99h16M92 107l-3 9M104 107l3 9"/><path d="M92 78c2-4 10-4 12 0"/></g></svg>');
    --pattern-size: 190px 190px;
  }

  @media (prefers-color-scheme: dark) {
    :root[data-skin="boy"]:not([data-theme="light"]) {
      --paper:      #101A2E;  --paper-2:    #16233C;  --card: #17253E;  --card: #17253E;
      --grid:       #1E3055;  --rule:       #24365A;
      --ink:        #E9F0FB;  --ink-soft:   #9FB3D2;  --ink-faint: #6A80A6;
      --accent:     #57A6FF;  --accent-dim: #172C4C;  --on-accent: #0B1220;
      --pattern: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="190" height="190" viewBox="0 0 190 190"><g fill="none" stroke="%235d9bea" stroke-opacity="0.10" stroke-width="2.4" stroke-linejoin="round"><path d="M12 40h30l8-9h16l5 9h9v13H12z"/><circle cx="26" cy="55" r="5"/><circle cx="66" cy="55" r="5"/><rect x="84" y="86" width="26" height="22" rx="4"/><circle cx="91" cy="95" r="2.4"/><circle cx="103" cy="95" r="2.4"/><path d="M97 86v-7"/><path d="M84 100h-7M110 100h7"/><path d="M90 108v6M104 108v6"/></g></svg>');
    }
    :root[data-skin="girl"]:not([data-theme="light"]) {
      --paper:      #2A1B27;  --paper-2:    #372333;  --card: #35222F;
      --grid:       #43293C;  --rule:       #4E3348;
      --ink:        #FBEDF6;  --ink-soft:   #D2AFC6;  --ink-faint: #A0788F;
      --accent:     #F58AC0;  --accent-dim: #472739;  --on-accent: #1E1018;
      --pattern: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="190" height="190" viewBox="0 0 190 190"><g fill="none" stroke="%23e58ab9" stroke-opacity="0.11" stroke-width="2.4" stroke-linejoin="round"><path d="M14 46c-6 0-9-5-6-9 2-4 8-4 10-1 1-8 12-10 16-3 6-3 12 2 11 8 5 0 6 5 3 7-2 1-31 1-34-2z"/><circle cx="98" cy="84" r="9"/><path d="M98 93v14M90 99h16M92 107l-3 9M104 107l3 9"/><path d="M92 78c2-4 10-4 12 0"/></g></svg>');
    }
  }
  :root[data-theme="dark"][data-skin="boy"] {
    --paper:      #101A2E;  --paper-2:    #16233C;  --card: #17253E;
    --grid:       #1E3055;  --rule:       #24365A;
    --ink:        #E9F0FB;  --ink-soft:   #9FB3D2;  --ink-faint: #6A80A6;
    --accent:     #57A6FF;  --accent-dim: #172C4C;  --on-accent: #0B1220;
    --pattern: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="190" height="190" viewBox="0 0 190 190"><g fill="none" stroke="%235d9bea" stroke-opacity="0.10" stroke-width="2.4" stroke-linejoin="round"><path d="M12 40h30l8-9h16l5 9h9v13H12z"/><circle cx="26" cy="55" r="5"/><circle cx="66" cy="55" r="5"/><rect x="84" y="86" width="26" height="22" rx="4"/><circle cx="91" cy="95" r="2.4"/><circle cx="103" cy="95" r="2.4"/><path d="M97 86v-7"/><path d="M84 100h-7M110 100h7"/><path d="M90 108v6M104 108v6"/></g></svg>');
  }
  :root[data-theme="dark"][data-skin="girl"] {
    --paper:      #2A1B27;  --paper-2:    #372333;  --card: #35222F;
    --grid:       #43293C;  --rule:       #4E3348;
    --ink:        #FBEDF6;  --ink-soft:   #D2AFC6;  --ink-faint: #A0788F;
    --accent:     #F58AC0;  --accent-dim: #472739;  --on-accent: #1E1018;
    --pattern: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="190" height="190" viewBox="0 0 190 190"><g fill="none" stroke="%23e58ab9" stroke-opacity="0.11" stroke-width="2.4" stroke-linejoin="round"><path d="M14 46c-6 0-9-5-6-9 2-4 8-4 10-1 1-8 12-10 16-3 6-3 12 2 11 8 5 0 6 5 3 7-2 1-31 1-34-2z"/><circle cx="98" cy="84" r="9"/><path d="M98 93v14M90 99h16M92 107l-3 9M104 107l3 9"/><path d="M92 78c2-4 10-4 12 0"/></g></svg>');
  }

  * { box-sizing: border-box; }

  /* Корневой scroll-контейнер в Chromium — html, а не body. На узком экране
     шапка под модальным окном могла расширять документ на 4 px, хотя сам body
     уже обрезал переполнение. Внутренние ленты продолжают прокручиваться в
     своих .tabs-row; страница целиком вбок уезжать не должна. */
  html {
    overflow-x: hidden;
    /* Только по вертикали: боковой прокрутки у нас нет вовсе. */
    overscroll-behavior-y: contain;
  }

  body {
    margin: 0;
    font-family: var(--font-body);
    color: var(--ink);
    background-color: var(--paper);
    /* Первый слой — рисунок темы (машинки или облака), дальше обычная клетка.
       Без темы --pattern пустой, и остаётся только клетка, как было. */
    background-image:
      var(--pattern, none),
      repeating-linear-gradient(to right, var(--grid) 0 1px, transparent 1px var(--cell)),
      repeating-linear-gradient(to bottom, var(--grid) 0 1px, transparent 1px var(--cell));
    background-size: var(--pattern-size, auto), auto, auto;
    -webkit-text-size-adjust: 100%;
    -webkit-tap-highlight-color: transparent;
    /* overflow-x и overscroll-behavior жили здесь и вдвоём убивали прокрутку.
       Владелец 03.09: «не работает колесико». Механика такая: overflow-x на
       теле делает само тело прокручиваемым блоком, прокручивать в нём нечего
       (высота равна содержимому), а overscroll-behavior: contain запрещает
       передать прокрутку дальше, корню. Колесо упиралось в тело и не двигало
       ничего; клавиши работали, потому что идут мимо этой цепочки — и потому
       же проверка обязана крутить именно колесом. Оба свойства теперь на
       корне: там contain по-прежнему гасит «потягивание» страницы, а
       прокручивать есть что. */
    /* Прокрутка пальцем остаётся, щипок и двойное нажатие — нет */
    touch-action: pan-x pan-y;
  }

  button {
    font: inherit;
    color: inherit;
    cursor: pointer;
    touch-action: manipulation;
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    user-select: none;
  }

  :focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }

  .shell {
    max-width: 1080px;
    margin: 0 auto;
    display: flex;
    flex-direction: column;
    gap: 16px;
    padding: calc(14px + env(safe-area-inset-top, 0px))
             calc(16px + env(safe-area-inset-right, 0px))
             calc(24px + env(safe-area-inset-bottom, 0px))
             calc(16px + env(safe-area-inset-left, 0px));
  }

  /* ── Шапка ─────────────────────────────────────────── */

  .top { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }

  .brand { display: flex; align-items: baseline; gap: 9px; margin-right: auto;
           min-width: 0; overflow: hidden; }
  .brand b {
    font-family: var(--font-display);
    font-size: 1.06rem; font-weight: 700; letter-spacing: -.01em; white-space: nowrap;
    /* На 375 px шесть значков по 44 px занимают строку целиком, и название
       уезжало под них: приложение не могло назвать себя на телефоне — ровно
       там, где им и пользуются. Пусть лучше подрежется многоточием. */
    overflow: hidden; text-overflow: ellipsis; min-width: 0;
  }
  /* Пустой ряд кнопок: вне главной и занятия в нём не остаётся ни одной
     видимой, а строка с отступами всё равно отнимала место у доски. */
  .top-actions:not(:has(> .icon-btn:not([hidden]))) { display: none; }

  .icon-btn {
    flex: none;
    width: 44px; height: 44px;
    display: grid; place-items: center;
    border: 1px solid var(--rule);
    border-radius: 14px;
    background: var(--paper-2);
    font-size: 1.05rem; line-height: 1;
    transition: transform .12s, border-color .15s, background .15s, color .15s,
                box-shadow .15s;
  }
  .icon-btn:hover { border-color: var(--accent); }
  .icon-btn[aria-pressed="true"] {
    border-color: var(--accent); background: var(--accent-dim); color: var(--accent);
  }
  /* Служебные кнопки — одна контурная система вместо смеси emoji и символов
     шрифта. Одинаковый viewBox сохраняет оптический размер на всех ОС. */
  .top-actions { display: flex; align-items: center; gap: 8px; flex: none; }
  .top-actions .icon-btn {
    color: var(--icon, var(--ink-soft));
    background: var(--paper-2); /* запас для Safari без color-mix */
    background: color-mix(in srgb, var(--icon, var(--accent)) 13%, var(--paper-2));
    border-color: color-mix(in srgb, var(--icon, var(--accent)) 28%, var(--rule));
    box-shadow: 0 2px 6px rgba(27,42,74,.08);
  }
  .top-actions .icon-btn:hover {
    color: var(--icon, var(--accent));
    background: color-mix(in srgb, var(--icon, var(--accent)) 20%, var(--paper-2));
    border-color: var(--icon, var(--accent)); transform: translateY(-1px);
  }
  .top-actions .icon-btn:active { transform: scale(.94); box-shadow: none; }
  .top-actions .icon-btn[aria-pressed="true"] {
    color: #fff; background: var(--icon, var(--accent));
    border-color: var(--icon, var(--accent));
  }
  #btnStartTop { --icon: #A8650A; }
  #btnTodayTop { --icon: #2766B5; }
  #btnDiaryTop { --icon: #7353B2; }
  #btnShopTop  { --icon: #B04E3B; }
  #btnPetTop   { --icon: #A84674; }
  #btnVoiceTop { --icon: #19796C; }
  #btnProfile  { --icon: #6848A8; }
  #btnGrid     { --icon: #28719E; }
  .app-icon { width: 23px; height: 23px; display: block; pointer-events: none; }
  .app-icon:not(.nav-art) * {
    fill: none; stroke: currentColor; stroke-width: 1.8;
    stroke-linecap: round; stroke-linejoin: round; vector-effect: non-scaling-stroke;
  }
  @media (max-width: 1024px) {
    .top-actions {
      order: 3; width: 100%; overflow-x: auto; justify-content: flex-start;
      padding: 2px 0 3px; scrollbar-width: none; overscroll-behavior-x: contain;
      scroll-snap-type: x proximity;
    }
    .top-actions::-webkit-scrollbar { display: none; }
    .top-actions .icon-btn { width: 44px; height: 44px; scroll-snap-align: start; }
    /* Взрослые настройки и голос не должны прятаться за невидимым свайпом.
       Частично видимая следующая кнопка подсказывает, что ряд можно листать. */
    #btnProfile { order: -3; margin-left: 14px; }
    #btnVoiceTop { order: -2; }
    #btnStartTop { order: -1; }

    /* В занятии видимы только Тая, профиль и иногда таблица. Они помещаются
       рядом с названием, поэтому вторая строка лишь отнимала 49 px у ответа. */
    body.lesson-open .top { flex-wrap: nowrap; }
    body.lesson-open .brand { flex: 1; margin-right: 0; }
    body.lesson-open .top-actions {
      order: initial; width: auto; overflow: visible; padding: 0; gap: 6px;
      scroll-snap-type: none;
    }
    body.lesson-open .top-actions .icon-btn { order: initial; }
    body.lesson-open #btnProfile { margin-left: 0; }

    /* Ряд листается — край гаснет, поверх стрелка «›» (верхРядПодсказка). */
    .top { position: relative; }
    .top-actions.more-right {
      -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 64px), transparent);
      mask-image: linear-gradient(to right, #000 calc(100% - 64px), transparent);
    }
    .top-more {
      position: absolute; right: 0; z-index: 3; width: 44px; min-height: 44px; padding: 0;
      display: flex; align-items: center; justify-content: center;
      border: 0; background: transparent; color: var(--ink);
    }
    .top-more .app-icon {
      width: 30px; height: 30px; padding: 4px; box-sizing: border-box; border-radius: 50%;
      background: var(--card); border: 1px solid var(--rule); box-shadow: var(--shadow);
    }
  }
  .top-more[hidden] { display: none; }
  @media (prefers-reduced-motion: reduce) {
    .top-actions .icon-btn { transition: none; }
    .top-actions .icon-btn:hover, .top-actions .icon-btn:active { transform: none; }
  }

  /* ── Общее ──────────────────────────────────────────── */

  .card {
    background: var(--paper-2);
    border: 1px solid var(--rule);
    border-radius: var(--r);
    box-shadow: var(--shadow);
  }

  .view { display: none; }
  .view.on { display: block; }

  /* display у .field/.sidebar иначе побеждает атрибут hidden */
  [hidden] { display: none !important; }

  .field { display: flex; flex-direction: column; gap: 10px; }
  /* Подписи разделов и полей — мелкий текст в 12 точек, и его читают: это
     «Занятия для возраста 7–8 лет», «Русский язык», «Как зовут». Бледными
     чернилами контраст выходил 3.44 в тёмной теме и 2.53 в светлой при
     норме 4.5 для мелкого текста. Мягкие чернила дают 5.17 и 7.14, а
     второстепенными подписи остаются за счёт размера и разрядки. */
  .field > label, .sec-label {
    font-size: .76rem; letter-spacing: .08em; text-transform: uppercase;
    color: var(--ink-soft); font-weight: 600;
  }

  /* Разделы занятий: полоса прокручивается вбок, чтобы не съедать высоту */
  .tabs-row {
    display: flex; gap: 8px; overflow-x: auto; padding: 2px 0 6px;
    -webkit-overflow-scrolling: touch;
  }
  .tabs-row::-webkit-scrollbar { height: 0; }
  .tab-btn {
    flex: none; min-height: 44px; padding: 9px 15px;
    border: 1px solid var(--rule); border-radius: 999px;
    background: var(--paper-2); color: var(--ink-soft);
    font-size: .93rem; font-weight: 700; white-space: nowrap;
  }
  .tab-btn[aria-pressed="true"] {
    background: var(--accent); border-color: var(--accent); color: var(--on-accent);
  }
  .tab-btn b { font-weight: 700; opacity: .65; margin-left: 6px; font-size: .84em; }
  @supports not (inset: 0) {
    .tabs-row > * + * { margin-left: 8px; }
  }

  /* История экзаменов под карточкой оценок */
  .ex-log { text-align: left; margin: 8px 0 2px; }
  .ex-log > b { display: block; font-size: .88rem; margin-bottom: 5px; }
  .ex-row {
    display: flex; align-items: baseline; gap: 8px;
    font-size: .85rem; color: var(--ink-soft); padding: 3px 0;
    border-top: 1px solid var(--rule);
  }
  .ex-row span { flex: 1; min-width: 0; }
  .ex-row i { flex: none; font-style: normal; font-weight: 700; }
  .ex-row i.good { color: var(--correct); }
  .ex-row i.bad { color: var(--wrong); }
  @supports not (inset: 0) {
    .ex-row > * + * { margin-left: 8px; }
  }

  /* Дневник: сводка родителю */
  .diary-sum { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; margin: 4px 0 10px; }
  .diary-cell {
    min-width: 0; overflow-wrap: anywhere;
    border: 1px solid var(--rule); border-radius: 12px;
    background: var(--paper); padding: 9px 11px; text-align: left;
  }
  .diary-cell b { display: block; font-size: 1.25rem; font-family: var(--font-display); }
  .diary-cell small { display: block; color: var(--ink-soft); font-size: .8rem; margin-top: 1px; }
  .diary-cell.good b { color: var(--correct); }
  .diary-cell.bad b { color: var(--wrong); }
  .diary-weak { text-align: left; margin: 0 0 10px; }
  .diary-weak > b { display: block; font-size: .9rem; margin-bottom: 6px; }
  .weak-note { margin: -4px 0 8px; font-size: .8rem; color: var(--ink-soft); }
  .weak-row {
    display: flex; align-items: center; gap: 8px;
    border: 1px solid var(--rule); border-radius: 10px;
    background: var(--paper); padding: 7px 10px; margin-bottom: 6px;
  }
  .weak-row span { flex: 2 1 auto; min-width: 0; font-size: .9rem; }
  .weak-row i {
    flex: 0 0 auto; font-style: normal; font-size: .82rem; font-weight: 700; color: var(--wrong);
  }
  /* Полоса тянется, но не забирает место у названия темы на телефоне */
  .weak-bar { flex: 1 1 56px; max-width: 220px; height: 8px; border-radius: 4px; background: var(--paper-2); }
  .weak-bar u { display: block; height: 100%; border-radius: 4px; background: var(--wrong); }
  @supports not (inset: 0) {
    .diary-sum > * + * { margin-left: 0; }
    .weak-row > * + * { margin-left: 8px; }
  }

  .chips { display: flex; flex-wrap: wrap; gap: 8px; }
  /* Лента вбок вместо переноса: ряд кнопок с переносом растёт вниз и съедает
     экран до содержимого. Владелец 03.09 обвёл такие ряды дважды подряд —
     фильтры игр и раскрытое оформление. */
  .chips.one-line { flex-wrap: nowrap; overflow-x: auto; padding-bottom: 4px;
                    -webkit-overflow-scrolling: touch; }
  .chips.one-line::-webkit-scrollbar { height: 0; }
  .chips.one-line > * { flex: none; white-space: nowrap; }
  /* Подпись раздела в ленте не растягиваем на всю ширину — иначе она
     утащит кнопки за край. */
  .chips.one-line .sec-label { flex: none; align-self: center;
                               margin: 0 2px 0 0; }
  .chip {
    border: 1px solid var(--rule);
    background: var(--paper);
    border-radius: 10px;
    padding: 10px 15px;
    min-height: 44px; min-width: 44px;   /* однобуквенные чипы иначе уже пальца */
    font-size: .95rem; font-weight: 600;
    font-variant-numeric: tabular-nums;
    transition: border-color .14s, background .14s, color .14s;
  }
  .chip:hover { border-color: var(--accent); }
  .chip[aria-pressed="true"] {
    background: var(--accent); border-color: var(--accent); color: var(--on-accent);
  }
  .chip-num { min-width: 48px; text-align: center; padding: 10px 8px; }

  .go {
    border: none; border-radius: 12px;
    background: var(--accent); color: var(--on-accent);
    padding: 16px; min-height: 52px;
    font-family: var(--font-display);
    font-size: 1.08rem; font-weight: 700;
    transition: filter .15s;
  }
  .go:hover { filter: brightness(1.08); }
  .go:disabled { opacity: .45; cursor: not-allowed; }

  .ghost {
    border: 1px solid var(--rule);
    background: var(--paper);
    border-radius: 12px;
    padding: 13px 20px; min-height: 48px;
    font-weight: 600; font-size: .95rem;
    transition: border-color .15s;
  }
  .ghost:hover { border-color: var(--accent); }

  .hint { font-size: .84rem; color: var(--ink-soft); line-height: 1.5; margin: 0; }

  /* ── Выбор возраста ─────────────────────────────────── */

  .ages { padding: 22px 20px; display: flex; flex-direction: column; gap: 18px; }

  .age-list { display: grid; gap: 10px; }
  /* При крупном тексте на 320 значок «5–6» рвался на две строки, а
     «Дошкольник» распирал карточку на 14 точек (нашёл test-age11, 29.09):
     значок растёт по ширине, а текст уходит под него, если рядом тесно. */
  .age-opt {
    display: flex; flex-wrap: wrap; align-items: center; gap: 14px; min-width: 0;
    border: 1px solid var(--rule);
    background: var(--paper);
    border-radius: 12px;
    padding: 15px 16px;
    text-align: left;
    transition: border-color .15s, background .15s;
  }
  .age-opt:hover { border-color: var(--accent); }
  .age-opt[aria-pressed="true"] { border-color: var(--accent); background: var(--accent-dim); }
  .age-opt em {
    flex: none;
    min-width: 46px; height: 46px; padding: 0 8px; white-space: nowrap;
    display: grid; place-items: center;
    border-radius: 11px;
    background: var(--accent); color: var(--on-accent);
    font-family: var(--font-display); font-style: normal;
    font-weight: 700; font-size: .92rem;
    font-variant-numeric: tabular-nums;
  }
  .age-opt div { flex: 1 1 8rem; display: flex; flex-direction: column; gap: 3px; min-width: 0; }
  .age-opt b { font-family: var(--font-display); font-size: 1rem; font-weight: 700; }
  .age-opt small { font-size: .82rem; color: var(--ink-soft); line-height: 1.4; }

  /* ── Главная: плитки занятий ────────────────────────── */

  .home { display: flex; flex-direction: column; gap: 16px; }

  .banner {
    padding: 16px 18px;
    display: flex; align-items: center; gap: 14px;
  }
  .ring { flex: none; width: 54px; height: 54px; position: relative; }
  .ring svg { width: 100%; height: 100%; transform: rotate(-90deg); }
  .ring b {
    position: absolute; inset: 0;
    display: grid; place-items: center;
    font-family: var(--font-display); font-size: .82rem; font-weight: 700;
    font-variant-numeric: tabular-nums;
  }
  .banner-text { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
  .banner-text b { font-family: var(--font-display); font-size: .98rem; font-weight: 700; }
  .banner-text small { font-size: .82rem; color: var(--ink-soft); line-height: 1.4; }

  .tiles { display: grid; gap: 12px; grid-template-columns: 1fr; }

  .tile {
    --tile-color: #2766B5;
    display: grid; align-items: center; gap: 8px 14px;
    grid-template-columns: 48px minmax(0, 1fr) auto;
    border: 1px solid var(--rule);
    background: var(--card);
    border-radius: 18px;
    box-shadow: var(--shadow);
    min-height: 92px; padding: 16px;
    text-align: left;
    transition: border-color .15s, transform .08s;
  }
  .tile:hover { border-color: var(--accent); }
  .tile:active { transform: translateY(1px); }
  .tile:focus-visible { outline: 3px solid var(--accent); outline-offset: 3px; }
  .tile[data-subject="ari"] { --tile-color: #7353B2; }
  .tile[data-subject="task"] { --tile-color: #19796C; }
  .tile[data-subject="time"] { --tile-color: #97620F; }
  .tile[data-subject="ru"] { --tile-color: #A84674; }
  .tile[data-subject="en"] { --tile-color: #28719E; }
  .tile[data-subject="zh"] { --tile-color: #B0453A; }
  .tile[data-subject="fun"] { --tile-color: #B04E3B; }
  .tile[data-subject="attention"] { --tile-color: #92702D; }
  .tile[data-subject="logic"] { --tile-color: #7053A2; }
  .tile[data-subject="motor"] { --tile-color: #237B76; }
  .tile[data-subject="tech"] { --tile-color: #2F6F8F; }
  .tile em {
    flex: none;
    width: 48px; height: 48px;
    display: grid; place-items: center;
    border-radius: 15px;
    background: var(--accent-dim); color: var(--accent);
    background: color-mix(in srgb, var(--tile-color) 13%, var(--card));
    color: color-mix(in srgb, var(--tile-color) 50%, var(--ink));
    font-family: var(--font-display); font-style: normal;
    font-weight: 700; font-size: 1.3rem;
  }
  .tile div { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
  /* Длинное слово («Программирование») при крупном тексте на 320 распирало
     сетку плиток на 25–107 px: переносим по слогам, а в крайнем случае где угодно. */
  .tile b { font-family: var(--font-display); font-size: 1.05rem; font-weight: 700; line-height: 1.35;
           hyphens: auto; -webkit-hyphens: auto; overflow-wrap: anywhere; }
  .tile small { font-size: .9rem; color: var(--ink-soft); line-height: 1.45; }
  /* 27.09: при тексте ×2 на 320 px подпись «…строй последовательности»
     (слово 271 px при месте 178) и «Прямоугольник на клетках» везли главную
     вбок на 50 px. Словарного переноса для русского Chrome на Windows не
     делает, а рвать слова по буквам нельзя. Поэтому подпись не крупнее доли
     ширины самой плитки. На обычных размерах предел выше .9rem и ничего не
     меняет. Ширина плитки задана сеткой (1fr), от содержимого не зависит,
     так что контейнером она быть может. */
  .tile { container-type: inline-size; }
  .tile small { font-size: min(.9rem, 6.3cqi); }
  /* 29.09: и заголовок рвался посреди слова — при тексте ×2 на 320 и 375
     «Непроизносим/ые», «Словарны/е», «Отрицательны/е»: overflow-wrap выше
     спасает от вылета ценой рваных букв. Мерить надо от колонки текста, а
     не от плитки: значок, отступы и «ур. 3» съедают 110–180 px, и доля
     плитки на разных ширинах даёт разное место. Колонка — контейнер (её
     ширину задаёт сетка, minmax(0, 1fr)), кегль — не больше её доли:
     слово из 14 букв (8,7 кегля) влезает с запасом. Подпись — так же:
     «последовательности» — 9,4 кегля. */
  .tile > div { container-type: inline-size; }
  .tile > div > b { font-size: min(1.05rem, 10.8cqi); }
  .tile > div > small { font-size: min(.9rem, 10cqi); }
  .tile i {
    flex: none; font-style: normal; font-size: .72rem;
    color: var(--ink-soft); font-variant-numeric: tabular-nums;
  }
  .tile i:empty { display: none; }
  .tile.other em { background: var(--paper); color: var(--ink-faint); }
  @media (max-width: 420px) {
    .tile { grid-template-columns: 48px minmax(0, 1fr); padding: 14px; gap: 7px 12px; }
    .tile i { grid-column: 2; justify-self: start; }
  }
  @media (prefers-reduced-motion: reduce) {
    .tile { transition: none; }
    .tile:active { transform: none; }
  }

  .badges { display: flex; flex-wrap: wrap; gap: 8px; }
  .badge {
    display: inline-flex; align-items: center; gap: 7px;
    border: 1px solid var(--gold);
    background: var(--gold-dim); color: var(--gold-ink);
    border-radius: 999px;
    padding: 6px 12px;
    font-size: .8rem; font-weight: 600;
  }

  /* ── Тренировка ─────────────────────────────────────── */

  .play { display: grid; gap: 16px; grid-template-columns: 1fr; align-items: start; }
  .stage { display: flex; flex-direction: column; gap: 13px; }

  /* Строка для взрослого из рекламы: над заданием, в цветах темы. */
  .ad-parent { margin: 0 0 8px; padding: 9px 12px; border-radius: 14px; background: var(--card); color: var(--ink);
    border: 1px solid var(--accent); display: flex; flex-direction: column; gap: 8px; }
  .ad-parent[hidden], .ad-parent [hidden] { display: none !important; }
  .ad-parent-t { margin: 0; font-size: .92rem; line-height: 1.35; }
  .ad-parent-row { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; }
  .ad-parent-save, .ad-parent-send, .ad-parent-opt {
    min-height: 44px; padding: 8px 14px; border-radius: 12px; font: inherit; font-size: .9rem; cursor: pointer; }
  .ad-parent-save, .ad-parent-send { background: var(--accent); color: #fff; border: 0; font-weight: 700; }
  .ad-parent-opt { background: transparent; color: var(--ink); border: 1px solid var(--ink-soft); }
  /* «Ребёнок рядом» — ссылкой, а не кнопкой: на окне 360×560 две кнопки
     встают в столбик и уводят само задание под нижний край. */
  .ad-parent-child { min-height: 44px; padding: 0 8px; background: none; border: 0; color: var(--accent);
    font: inherit; font-size: .9rem; text-decoration: underline; cursor: pointer; }
  .ad-parent-ask { align-self: flex-start; min-height: 44px; padding: 0; background: none; border: 0; color: var(--accent);
    font: inherit; font-size: .85rem; text-decoration: underline; cursor: pointer; }
  .ad-parent-hint, .ad-parent-thanks { margin: 0; font-size: .85rem; line-height: 1.35; }
  .ad-parent-thanks { font-weight: 700; }
  .ad-parent-open { align-self: flex-start; min-height: 44px; display: inline-flex; align-items: center; color: var(--accent); font-weight: 700; }
  .ad-parent-opts { display: flex; flex-wrap: wrap; gap: 8px; }
  .ad-parent-note { display: flex; flex-wrap: wrap; gap: 8px; margin: 0; }
  /* Поле почты не делит строку с кнопкой на телефоне: при 200px подсказка
     «Почта, если хотите ответ (необязательно)» обрезалась на полуслове. */
  .ad-parent-note textarea { flex: 1 1 100%; }
  .ad-parent-note input { flex: 1 1 260px; }
  .ad-parent-note textarea, .ad-parent-note input { min-height: 44px; padding: 8px 10px; border-radius: 12px;
    border: 1px solid var(--ink-soft); background: var(--card); color: var(--ink); font: inherit; font-size: 1rem; }
  /* Приглашение написать (владелец 20.09: «если вы что-то не нашли, можете
     написать в поддержку или оставить отзыв — доработаем»). Во всю строку,
     иначе встаёт узкой колонкой рядом с полем ввода. */
  .ad-parent-invite { flex: 1 1 100%; margin: 0; font-size: .85rem; line-height: 1.35; color: var(--ink-soft); }
  .ad-parent-reward { flex: 1 1 100%; margin: 0; font-size: .8rem; line-height: 1.35; color: var(--ink-soft); }
  .meter {
    display: flex; flex-wrap: wrap; align-items: center; gap: 10px; padding: 0 4px;
    font-size: .8rem; color: var(--ink-soft); font-variant-numeric: tabular-nums;
  }
  .meter .sep { color: var(--ink-faint); }
  .meter b { color: var(--ink); font-weight: 700; }
  .meter .streak {
    margin-left: auto;
    display: inline-flex; align-items: center; gap: 6px;
    padding: 4px 10px; border-radius: 999px;
    background: var(--paper-2); border: 1px solid var(--rule);
    transition: background .2s, border-color .2s, color .2s;
  }
  .meter .streak.hot { background: var(--correct-dim); border-color: var(--correct); color: var(--correct); }
  .meter .streak b { color: inherit; }

  .board {
    padding: 26px 18px 22px;
    display: flex; flex-direction: column; align-items: center; gap: 15px;
    min-height: 196px; justify-content: center;
  }

  .equation {
    display: flex; align-items: center; justify-content: center;
    flex-wrap: wrap; gap: .3em;
    font-family: var(--font-display);
    font-size: 2.6rem;             /* Safari 12: нет clamp() */
    font-size: clamp(2.3rem, 11.5vw, 4rem);
    font-weight: 700; line-height: 1; letter-spacing: -.02em;
    font-variant-numeric: tabular-nums;
  }
  .equation .op { color: var(--ink-faint); font-weight: 500; }

  .slot {
    min-width: 2.2ch;
    padding: 0 .12em .06em;
    border-bottom: 5px solid var(--accent);
    color: var(--accent);
    text-align: center;
    transition: color .18s, border-color .18s;
  }
  .slot.empty { color: var(--ink-faint); border-bottom-color: var(--rule); }
  .board.ok  .slot { color: var(--correct); border-bottom-color: var(--correct); }
  .board.bad .slot { color: var(--wrong);   border-bottom-color: var(--wrong); }

  /* Оставляем место кнопке озвучки справа, даже при сужении уже открытой
     страницы, и 2 px зазора: края не пересекаются при дробной ширине панели.
     Высота следует пропорциям canvas, кружки остаются круглыми. */
  #dots { max-width: calc(100% - 84px); height: auto; display: block; }

  .verdict {
    min-height: 1.4em;
    font-size: .95rem; font-weight: 600; text-align: center;
    color: var(--ink-soft); line-height: 1.45;
  }
  .board.ok  .verdict { color: var(--correct); }
  .board.bad .verdict { color: var(--wrong); }
  .verdict .tip {
    display: block; margin-top: 5px;
    font-weight: 600; color: var(--ink-soft);
    font-variant-numeric: tabular-nums;
    white-space: pre-line;                 /* подсказки со списками — построчно */
  }

  @keyframes nudge { 0%,100%{transform:translateX(0)} 22%{transform:translateX(-7px)} 62%{transform:translateX(6px)} }
  @keyframes pop   { 0%{transform:scale(1)} 45%{transform:scale(1.05)} 100%{transform:scale(1)} }
  .board.bad .equation { animation: nudge .3s ease; }
  .board.ok  .equation { animation: pop .3s ease; }

  @media (prefers-reduced-motion: reduce) {
    .board.bad .equation, .board.ok .equation, td.flash { animation: none; }
    * { transition-duration: .01ms !important; }
  }

  /* ── Ввод ───────────────────────────────────────────── */

  .pad { display: grid; grid-template-columns: repeat(3, 1fr); gap: 9px; }

  .key {
    border: 1px solid var(--rule);
    background: var(--paper-2);
    border-radius: 12px;
    box-shadow: var(--shadow-key);
    padding: 0;
    height: 58px;                  /* Safari 12: нет clamp() */
    height: clamp(54px, 8.4vw + 40px, 68px);
    font-family: var(--font-display);
    font-size: 1.5rem; font-weight: 600;
    font-variant-numeric: tabular-nums;
    transition: background .1s, border-color .1s, transform .06s;
  }
  .key:hover { border-color: var(--accent); }
  .key:active { transform: translateY(1px); box-shadow: none; }
  .key.util { font-size: 1.22rem; color: var(--ink-soft); }
  .key.enter { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
  .key.enter:hover { filter: brightness(1.08); }

  .choices { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
  /* Два варианта — на всю ширину: так кнопки крупнее и ряд не выглядит обрубленным */
  .choices.two { grid-template-columns: repeat(2, 1fr); }
  .choices.four { grid-template-columns: repeat(2, 1fr); }
  .choice {
    /* Ячейка сетки по умолчанию не уже своего содержимого: без этого на 320
       при 200 % остаётся прокрутка вбок (проверено снятием правила). */
    min-width: 0;
    border: 1px solid var(--rule);
    background: var(--paper-2);
    border-radius: 12px;
    box-shadow: var(--shadow-key);
    height: 68px;                  /* Safari 12: нет clamp() */
    height: clamp(62px, 10vw + 42px, 78px);
    font-family: var(--font-display);
    font-size: 1.9rem; font-weight: 700;
    font-variant-numeric: tabular-nums;
    transition: border-color .12s, transform .06s;
  }
  /* Целые фразы тремя колонками не помещаются: на телефоне у «Шишки упали
     с ели.» обрезался конец — та самая точка, по которой и надо выбирать.
     Такие варианты кладём строками во всю ширину, как записи в тетради. */
  .choices.rows { grid-template-columns: 1fr; }
  .choices.rows .choice {
    height: auto; min-height: 54px; padding: 11px 14px;
    font-family: var(--font-body); line-height: 1.35;
    /* Кегль растёт с «Крупным текстом», но не дальше ширины кнопки: при 200 %
       на 320 «прямоугольник» переставал помещаться и рвался посреди букв. */
    font-size: 1.12rem; font-size: min(1.12rem, 7vw);
  }

  .choice:hover { border-color: var(--accent); }
  .choice:active { transform: translateY(1px); }

  /* Не влезает ряд — переносится кнопка целиком, а не буквы в подписи: то же
     лечение, что у ряда обучалки (22.81). До 20.09 «Подсказка» ломалась на
     «Подсказ / ка» уже при обычном тексте на 320, а при 150 % страница ехала
     вбок. Основа кнопки — подпись в одну строку; не помещается ряд — кнопка
     уходит на следующую строку и растягивается во всю ширину. */
  .helpbar { display: flex; flex-wrap: wrap; gap: 9px; }
  /* Основа в rem: при обычном тексте три кнопки стоят одним рядом, как
     раньше, а когда текст крупнее — ряд честно переносится. С основой
     auto ряд переносился уже на 375 и уходил за первый экран iPhone SE. */
  .helpbar .ghost { flex: 1 1 6rem; min-width: 0; padding: 11px 14px; font-size: .88rem; }

  /* ── Таблица прогресса ──────────────────────────────── */

  .panel { padding: 17px 15px; display: flex; flex-direction: column; gap: 13px; }
  .panel-head { display: flex; align-items: baseline; gap: 10px; }
  .panel-head h2 { margin: 0; font-family: var(--font-display); font-size: .95rem; font-weight: 700; }
  .panel-head span {
    font-size: .78rem; color: var(--ink-faint);
    margin-left: auto; font-variant-numeric: tabular-nums;
  }

  .table-wrap { overflow-x: auto; }
  .grid-hint { margin: 2px 0 8px; font-size: .8rem; color: var(--ink-soft); }
  table.grid { border-collapse: collapse; font-variant-numeric: tabular-nums; font-size: .78rem; margin: 0 auto; }
  table.grid th, table.grid td { width: 30px; height: 27px; text-align: center; padding: 0; }
  table.grid th { color: var(--ink-faint); font-weight: 700; font-size: .72rem; }
  table.grid td {
    border: 1px solid var(--rule); color: var(--ink-faint);
    font-weight: 600; border-radius: 4px;
    transition: background .3s, color .3s;
  }
  /* Статические rgba вместо color-mix: он есть только в Safari 16.2+ */
  td.l1 { background: var(--grid-l1); color: var(--ink-soft); }
  td.l2 { background: var(--grid-l2); color: var(--ink); }
  td.l3 { background: var(--correct); border-color: var(--correct); color: var(--paper-2); }
  td.flash { animation: cellpulse .5s ease; }
  @keyframes cellpulse { 0%{transform:scale(1)} 40%{transform:scale(1.28)} 100%{transform:scale(1)} }

  .legend { display: flex; flex-wrap: wrap; gap: 12px; font-size: .76rem; color: var(--ink-soft); }
  .legend i {
    display: inline-block; width: 12px; height: 12px;
    border-radius: 3px; border: 1px solid var(--rule);
    vertical-align: -2px; margin-right: 5px;
  }
  .legend i.a { background: var(--grid-l1); }
  .legend i.b { background: var(--grid-l2); }
  .legend i.c { background: var(--correct); border-color: var(--correct); }

  /* ── Итоги ──────────────────────────────────────────── */

  .done { padding: 26px 20px; display: flex; flex-direction: column; gap: 19px; align-items: center; text-align: center; }
  .done h2 { margin: 0; font-family: var(--font-display); font-size: 1.5rem; font-weight: 700; }
  .done p { margin: 0; color: var(--ink-soft); font-size: .92rem; line-height: 1.55; max-width: 42ch; }
  .stats { display: flex; gap: 24px; flex-wrap: wrap; justify-content: center; }
  .stat { display: flex; flex-direction: column; gap: 3px; }
  .stat b {
    font-family: var(--font-display); font-size: 2rem; font-weight: 700;
    font-variant-numeric: tabular-nums; line-height: 1;
  }
  /* Подписи под числами итогов занятия. Мелкие, но их читают: по ним
     понятно, что за число сверху. Бледными выходило 2.97 при норме 4.5. */
  .stat span { font-size: .74rem; text-transform: uppercase; letter-spacing: .07em; color: var(--ink-soft); }
  .done-actions { display: flex; gap: 10px; flex-wrap: wrap; justify-content: center; }

  .earned {
    display: flex; flex-direction: column; gap: 9px; align-items: center;
    padding: 14px 16px; border-radius: 12px;
    background: var(--gold-dim); border: 1px solid var(--gold);
    width: 100%;
  }
  .earned b { font-family: var(--font-display); font-size: .88rem; color: var(--gold-ink); }

  /* ── Отчёт ──────────────────────────────────────────── */

  .report { display: flex; flex-direction: column; gap: 14px; }
  .rep-card { padding: 17px 16px; display: flex; flex-direction: column; gap: 12px; }
  .rep-card h2 { margin: 0; font-family: var(--font-display); font-size: 1rem; font-weight: 700; }

  /* minmax(0, …) и перенос: при «Вдвое» на 320 px подпись и значение вместе
     шире карточки, и список «о приложении» уезжал за экран (аудит 07.09). */
  .kv { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 8px 14px; font-size: .88rem; }
  .kv dt { color: var(--ink-soft); margin: 0; overflow-wrap: anywhere; }
  .kv dd { margin: 0; font-weight: 700; font-variant-numeric: tabular-nums; text-align: right; min-width: 0; overflow-wrap: anywhere; }

  .weak { display: flex; flex-direction: column; gap: 7px; }
  .weak-row {
    display: flex; align-items: center; gap: 10px;
    font-size: .88rem; font-variant-numeric: tabular-nums;
  }
  .weak-row b { font-family: var(--font-display); font-weight: 700; min-width: 4.6em; }
  .weak-bar { flex: 1; height: 7px; border-radius: 4px; background: var(--paper); border: 1px solid var(--rule); overflow: hidden; }
  .stat-head { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }
  .stat-head h2 { margin: 0; }
  .small-btn { padding: 6px 10px; font-size: .82rem; border-radius: 10px; }
  @supports not (inset: 0) { .stat-head > * + * { margin-left: 10px; } }
  .day-card { padding-top: 10px; }
  .day-head {
    display: flex; align-items: center; gap: 10px; width: 100%;
    background: none; border: none; padding: 9px 0 11px; min-height: 44px; text-align: left;
    font-family: var(--font-display); font-size: 1rem; color: var(--ink);
  }
  .day-head .day-sum { margin-left: auto; font-weight: 400; color: var(--ink-soft); font-size: .78rem; }
  .day-head .chev { color: var(--ink-soft); font-size: 1.1rem; }
  .day-topics { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 8px; }
  .topic-chip {
    font-size: .74rem; padding: 3px 8px; border-radius: 999px;
    background: var(--paper-2); color: var(--ink-soft); border: 1px solid var(--rule);
  }
  .topic-chip.has-err { border-color: var(--wrong); color: var(--wrong); }
  @supports not (inset: 0) {
    .day-topics > * { margin: 0 6px 6px 0; }
    .day-head > * + * { margin-left: 10px; }
  }
  .weak-bar i { display: block; height: 100%; background: var(--wrong); }
  .weak-row small { color: var(--ink-faint); min-width: 5.6em; text-align: right; }

  .days { display: flex; flex-wrap: wrap; gap: 5px; }
  .day {
    width: 22px; height: 22px; border-radius: 5px;
    border: 1px solid var(--rule); background: var(--paper);
  }
  .day.on { background: var(--correct); border-color: var(--correct); }

  /* ── Сообщить о проблеме ────────────────────────────── */

  /* Поддержка — чат: карточка ростом с экран, лента сжимается, композер
     всегда на виду. С 78vh на 320 px поле ввода уходило за нижний край, и
     чтобы написать, приходилось прокручивать страницу (замер на бою 07.09).
     dvh — реальная высота с учётом панелей браузера; vh остаётся запасом. */
  .support { display: flex; flex-direction: column; gap: 14px; }
  /* Высоту задаёт настоящий верх карточки (supВысота): на 768 px шапка
     выше, и «экран минус 132» уводило поле ввода за нижний край. */
  .sup-chat { flex: 1 1 auto; gap: 8px; min-height: 0;
              height: calc(100vh - var(--sup-top, 132px)); height: calc(100dvh - var(--sup-top, 132px)); }
  .sup-head { display: flex; align-items: center; gap: 8px; }
  .sup-head h2 { margin: 0; }
  .sup-back { min-width: 44px; min-height: 44px; padding: 0 12px; font-size: 1.3rem; line-height: 1; }
  .sup-composer { display: grid; grid-template-columns: 44px minmax(0, 1fr) 44px; gap: 6px; align-items: end; }
  .sup-clip, .sup-send { width: 44px; min-height: 44px; height: 44px; display: flex; align-items: center; justify-content: center;
                          border-radius: 12px; border: 1px solid var(--rule); background: var(--paper); color: var(--ink-soft); }
  .sup-send { background: var(--accent); border-color: transparent; color: var(--on-accent); }
  .sup-clip:hover, .sup-clip:focus-visible { border-color: var(--accent); color: var(--accent); }
  /* Подсказки: на телефоне листаются пальцем, на широком экране просто
     переносятся. Полосу прокрутки прячем — она лезла серой лентой во всю
     ширину под чипами (владелец 07.09: «убери это»). */
  /* В карточке фиксированной высоты сжимается только лента. Ряд подсказок —
     прокручиваемый блок, его минимальная высота 0, и при длинной истории он
     сплющивался до 9 px из 44 (снимки владельца 14.09): доля сжатия считалась
     от базы ленты, а это вся переписка. */
  .sup-chat > * { flex-shrink: 0; }
  /* Файлы тащат на экран поддержки — рамка показывает, что их примут (136). */
  .sup-chat.sup-drop { outline: 3px dashed var(--accent); outline-offset: -6px; }
  .sup-chat > .sup-thread, .sup-chat > .msg-thread { flex: 1 1 0; min-height: 0; }
  .sup-chips { flex-wrap: nowrap; overflow-x: auto; overscroll-behavior-x: contain;
               scrollbar-width: none; -ms-overflow-style: none; }
  .sup-chips::-webkit-scrollbar { display: none; }
  .sup-chips .chip { flex: none; white-space: nowrap; }
  @media (min-width: 700px) { .sup-chips { flex-wrap: wrap; overflow-x: visible; } }
  .sup-ctx { font-size: .82rem; }
  /* Приложенные снимки — миниатюрами над полем, крестик убирает снимок
     (обращение 100). Цель касания крестика 44 px — невидимым расширением. */
  .sup-thumbs { grid-column: 1 / -1; display: flex; gap: 12px; overflow-x: auto; padding: 10px 10px 2px 2px; }
  .sup-thumbs[hidden] { display: none; }
  .sup-thumb { position: relative; flex: none; width: 56px; height: 56px; }
  .sup-thumb img { width: 56px; height: 56px; object-fit: cover; object-position: top center; border-radius: 10px; border: 1px solid var(--rule); display: block; }
  .sup-thumb button {
    position: absolute; top: -8px; right: -8px; width: 28px; height: 28px; min-height: 0; padding: 0;
    border-radius: 50%; border: 1px solid var(--rule); background: var(--card); color: var(--ink);
    font-size: .75rem; line-height: 1; display: flex; align-items: center; justify-content: center;
  }
  .sup-thumb button::before { content: ""; position: absolute; inset: -8px; }
  /* Свои снимки в ленте поддержки — миниатюрами, а не «(снимок экрана)»
     (обращение 104). */
  .sup-shots { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 4px; }
  /* Выше, чем шире, и от верхнего края: снимок экрана телефона высокий, а
     самое важное владелец обводит наверху (обращение 125 от 21.09: «верх не
     видно в фото» — квадрат резал середину). */
  .sup-shots img { width: 72px; height: 104px; object-fit: cover; object-position: top center;
                   border-radius: 8px; display: block; cursor: zoom-in; }
  /* Поле ввода вровень со скрепкой и отправкой (обращение 101): на айфоне
     строка с межстрочным 1.62 и внутренние поля textarea давали 58 pt при
     кнопках 44. Одна строка — ровно 44, дальше растёт по тексту. */
  .sup-composer textarea {
    -webkit-appearance: none; appearance: none;
    height: 44px; min-height: 44px; max-height: 132px;
    line-height: 22px; padding: 10px 12px; resize: none; overflow-y: auto;
  }
  /* Фото на весь экран по нажатию на снимок в ленте (обращение 99). */
  .photo-view { position: fixed; inset: 0; z-index: 60; background: rgba(0, 0, 0, .92);
                display: flex; align-items: center; justify-content: center;
                padding: calc(56px + env(safe-area-inset-top, 0px)) 8px calc(16px + env(safe-area-inset-bottom, 0px)); }
  .photo-view[hidden] { display: none; }
  /* Во весь экран, даже если копия меньше экрана: маленькую растягиваем,
     а не оставляем крошкой посередине (обращение 124). */
  .photo-view img { width: 100%; height: 100%; object-fit: contain; border-radius: 6px; }
  .photo-view button { position: absolute; top: calc(8px + env(safe-area-inset-top, 0px)); right: 8px;
                       width: 44px; height: 44px; border-radius: 50%; border: 0;
                       background: rgba(255, 255, 255, .16); color: #fff; font-size: 1.1rem; }
  .sup-card { padding: 18px 16px; display: flex; flex-direction: column; gap: 14px; }
  .sup-card h2 { margin: 0; font-family: var(--font-display); font-size: 1rem; font-weight: 700; }

  .sup-card textarea {
    /* 16 px по той же причине, что и у остальных полей: айфон увеличивает
       страницу, когда фокус попадает в поле мельче, а вернуть масштаб нечем. */
    font: inherit; font-size: 16px;
    color: var(--ink);
    background: var(--paper);
    border: 1px solid var(--rule);
    border-radius: 11px;
    padding: 12px 13px;
    min-height: 96px;
    resize: vertical;
    width: 100%;
  }
  .sup-card textarea:focus-visible { outline: 3px solid var(--accent); outline-offset: 1px; }
  /* Поле в ленте — как в переписке: две строки, растёт по тексту. */
  .sup-card #bugText { min-height: 44px; max-height: 132px; padding: 10px 12px; resize: none; overflow-y: auto; }
  .sch-nav { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
  .sch-nav b { flex: 1; text-align: center; font-family: var(--font-display); }
  .sch-nav .ghost { min-width: 44px; padding-left: 12px; padding-right: 12px; }
  .sch-grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 4px; }
  /* Подпись дня недели не растёт быстрее клетки: при «Вдвое» на 320 px «Пн» и
     «Вт» наезжали друг на друга. */
  .sch-grid .sch-wd { text-align: center; font-size: min(.8rem, 4vw); color: var(--ink-soft); padding: 4px 0; }
  .sch-cell { min-height: 48px; min-width: 0; overflow-wrap: anywhere; border: 1px solid var(--grid); border-radius: 10px; background: var(--paper-2);
    color: var(--ink); font: inherit; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; padding: 4px 2px; }
  .sch-cell.other { opacity: .45; }
  .sch-cell.today { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent) inset; }
  .sch-cell.picked { background: var(--accent); color: var(--on-accent); }
  .sch-cell small { font-size: .75rem; }
  .sch-strip { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; }
  .sch-strip button { min-height: 52px; border: 1px solid var(--grid); border-radius: 12px; background: var(--paper-2);
    color: var(--ink); font: inherit; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; padding: 4px 0; }
  .sch-strip button small { font-size: .72rem; color: var(--ink-soft); text-transform: uppercase; letter-spacing: .04em; }
  .sch-strip button b { font-size: 1.05rem; }
  .sch-strip button i { font-style: normal; font-size: .7rem; color: var(--ink-soft); }
  .sch-strip button.today { border-color: var(--accent); }
  .sch-strip button.picked { background: var(--accent); color: var(--on-accent); }
  .sch-strip button.picked small, .sch-strip button.picked i { color: var(--on-accent); }
  /* На телефоне у настроечных экранов было три вложенных отступа — 54 px с
     каждого края на 320 px: лента дней ужималась до 210 px, кнопки дней —
     до 27 px, меньше пальца, а при «Вдвое» уезжали за экран (аудит 07.09).
     Внешний отступ обёртки на узком экране лишний, а семь дней идут в два
     ряда — четыре и три, каждый не уже 44 px. */
  @media (max-width: 419px) {
    .sch-strip { grid-template-columns: repeat(4, 1fr); }
  }
  /* Заголовок и число-день-время в одной строке: дата прижата к правому краю. */
  .sch-head-row { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; flex-wrap: wrap; }
  .sch-head-row h2 { margin: 0; }
  .sch-now { font: inherit; font-size: .8rem; font-variant-numeric: tabular-nums; color: var(--ink-soft);
             background: transparent; border: 0; border-radius: 8px; padding: 10px 4px; min-height: 44px;
             white-space: nowrap; margin-left: auto; }
  .sch-now:hover, .sch-now:focus-visible { color: var(--accent); outline: 2px solid var(--accent); outline-offset: -2px; }
  .sch-page { display: grid; gap: 8px; }
  .sch-page h3 { margin: 6px 0 0; font-family: var(--font-display); font-size: 1rem; }
  /* Разворот бумажного дневника: №, время, урок или перерыв, отметка домашки;
     панель со всем сразу — под строкой по нажатию. */
  .sch-table { display: grid; gap: 4px; }
  .sch-head { display: grid; grid-template-columns: 30px minmax(0, min(4.6rem, 24vw)) minmax(0, 1fr) 44px; gap: 6px; padding: 0 6px 2px 4px; font-size: .72rem; color: var(--ink-soft); text-transform: uppercase; letter-spacing: .04em; }
  /* Колонка времени не шире четверти экрана: при «Вдвое» на 320 px она
     съедала место у предмета, и «Математика» вставала столбиком по букве
     (нашла быстрая проверка 07.09). */
  .sch-row { display: grid; grid-template-columns: 30px minmax(0, min(4.6rem, 24vw)) minmax(0, 1fr) 44px; align-items: stretch; gap: 6px; min-height: 48px; padding: 4px 6px 4px 4px; border: 1px solid var(--grid); border-radius: 12px; background: var(--paper-2); }
  .sch-row.empty { background: transparent; }
  .sch-num { width: 28px; height: 28px; border-radius: 50%; background: var(--accent); color: var(--on-accent); display: flex; align-items: center; justify-content: center; font-weight: 700; font-size: .85rem; flex: none; align-self: center; }
  .sch-row.empty .sch-num { background: var(--paper-2); color: var(--ink-soft); }
  .sch-subj { font: inherit; font-size: .92rem; white-space: normal; overflow-wrap: anywhere; font-weight: 600; line-height: 1.2; color: var(--ink); background: transparent; border: 0; border-radius: 8px; text-align: left; padding: 10px 4px; min-height: 40px; display: block; align-self: center; overflow-wrap: break-word; hyphens: auto; min-width: 0; }
  .sch-subj.ph { color: var(--ink-faint); font-weight: 400; }
  /* Наводка подсвечивает клетку, а рамку фокуса рисует вся строка ниже:
     рамка на одной клетке читалась как «выделено слово», а не «выбран урок». */
  button.sch-subj:hover { background: var(--paper); }
  button.sch-subj:focus-visible, button.sch-time:focus-visible { outline: none; }
  .sch-hw { font: inherit; font-size: 16px; line-height: 1.3; color: var(--ink); background: var(--paper); border: 1px dashed var(--rule); border-radius: 8px; padding: 8px; min-height: 40px; width: 100%; resize: none; overflow: hidden; }
  .sch-hw:focus-visible { outline: 2px solid var(--accent); outline-offset: 0; border-style: solid; }
  .sch-hw:disabled { border-color: transparent; background: transparent; }
  .sch-note { min-height: 44px; }
  /* Время урока: у ребёнка надпись, у взрослого кнопка с родным выбором времени. */
  /* Время не растёт быстрее клетки: при «Вдвое» на 320 px «10:10–10:30»
     обрезалось (нашла быстрая проверка 07.09). */
  .sch-time { font: inherit; font-size: min(.82rem, 3.6vw); font-variant-numeric: tabular-nums; white-space: nowrap; color: var(--ink-soft); background: transparent; border: 0; border-radius: 8px; padding: 10px 0; min-height: 40px; text-align: left; align-self: center; }
  button.sch-time:hover { background: var(--paper); color: var(--ink); }
  .sch-time-edit { font: inherit; font-size: 16px; width: 100%; min-height: 40px; border: 1px solid var(--rule); border-radius: 8px; background: var(--paper); color: var(--ink); padding: 4px 6px; }
  /* Отметка домашки в строке: «·» нет, «✎» записано, «✓» сделано. */
  .sch-mark { width: 44px; min-height: 40px; height: 40px; align-self: center; border-radius: 10px; border: 1px solid var(--grid); background: var(--paper); color: var(--ink-soft); font: inherit; font-size: 1.15rem; }
  .sch-mark:disabled { visibility: hidden; }
  .sch-mark[aria-expanded="true"] { border-color: var(--accent); color: var(--accent); }
  .sch-row { cursor: pointer; }
  /* Вся строка: и когда в ней фокус с клавиатуры, и пока под ней панель. */
  .sch-row:focus-within, .sch-row.open { outline: 2px solid var(--accent); outline-offset: -2px; }
  .sch-row.open { background: var(--paper); border-color: var(--accent); }
  .sch-row.break { background: transparent; border-style: dashed; }
  .sch-row.break .sch-num { background: var(--paper-2); color: var(--ink-soft); }
  .sch-subj.brk { font-style: italic; font-weight: 500; color: var(--ink-soft); }
  .sch-mark.on { background: var(--correct); color: #fff; border-color: transparent; }
  /* Панель строки: урок или перерыв, время, задание — всё сразу. */
  .sch-edit { display: grid; gap: 6px; padding: 8px 8px 8px 34px; border: 1px solid var(--accent); border-radius: 12px; }
  .sch-edit h4 { margin: 4px 0 0; font-size: .72rem; font-weight: 600; color: var(--ink-soft); text-transform: uppercase; letter-spacing: .04em; }
  .sch-edit .chips { gap: 6px; }
  /* Список предметов прокручивается: их может стать много, а экран телефона
     не растёт (владелец 07.09). Прокрутка не уходит на страницу. */
  .sch-subj-list { max-height: 8.4rem; overflow-y: auto; overscroll-behavior-y: contain; padding: 2px; }
  .sch-edit .chip.brk { font-style: italic; color: var(--ink-soft); }
  .chip-own { display: inline-flex; align-items: stretch; gap: 2px; }
  .chip-x { width: 44px; min-height: 40px; border: 1px solid var(--rule); border-radius: 10px;
            background: var(--paper); color: var(--ink-soft); font: inherit; font-size: .95rem; }
  .chip-x:hover, .chip-x:focus-visible { border-color: var(--wrong); color: var(--wrong); }
  .sch-edit-time { display: grid; grid-template-columns: 1fr 1fr; gap: 6px 8px; }
  .sch-edit-time label { display: grid; gap: 3px; font-size: .78rem; color: var(--ink-soft); }
  .sch-edit .sch-break-hint { color: var(--ink-soft); font-size: .78rem; }
  .sch-edit-actions { display: flex; gap: 8px; flex-wrap: wrap; }
  .sch-edit-actions .ghost { min-height: 40px; flex: 1 1 8rem; }
  /* Месяц: строки уроков на широком экране, коротко — на телефоне. */
  .sch-cell { text-align: left; }
  .sch-cell b { text-align: center; }
  .sch-lines { display: grid; gap: 1px; margin-top: 2px; }
  .sch-lines i { font-style: normal; font-size: .7rem; line-height: 1.2; color: var(--ink-soft); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .sch-cell.picked .sch-lines i, .sch-cell.picked .sch-brief { color: var(--on-accent); }
  .sch-brief { display: block; text-align: center; }
  @media (max-width: 599px) { .sch-lines { display: none; } }
  @media (min-width: 600px) { .sch-brief { display: none; } .sch-cell { min-height: 84px; } }
  @keyframes sch-pulse { 0% { box-shadow: 0 0 0 0 var(--accent); } 100% { box-shadow: 0 0 0 10px transparent; } }
  .sch-strip button.pulse { animation: sch-pulse .6s ease-out 2; }
  .sch-done { width: 44px; min-height: 40px; height: 40px; align-self: center; border-radius: 10px; border: 1px solid var(--grid); background: var(--paper); color: var(--ink-soft); font: inherit; font-size: 1.15rem; }
  .sch-done[aria-pressed="true"] { background: var(--correct); color: #fff; border-color: transparent; }
  .sch-done:disabled { visibility: hidden; }
  .sch-pick { display: grid; gap: 8px; padding: 8px; border: 1px solid var(--accent); border-radius: 12px; }
  .sch-pick .chips { gap: 6px; }
  /* На узком телефоне колонки уже: номер, время, предмет, отметка. */
  @media (max-width: 479px) {
    .sch-head { display: none; }        /* подписи колонок ели строку на телефоне */
    .sch-edit h4 { margin-top: 2px; }
  }
  @media (max-width: 360px) {
    .sch-row { grid-template-columns: 26px minmax(0, min(4.2rem, 22vw)) minmax(0, 1fr) 40px; gap: 4px 6px; }
    .sch-mark { width: 40px; }
    .sch-edit { padding-left: 6px; }
  }
  .sch-empty { color: var(--ink-soft); padding: 8px 2px; }
  .sch-add { display: grid; gap: 8px; }
  .sch-add .chips { gap: 6px; }
  .bug-item { display: grid; gap: 6px; padding: 10px 12px; border: 1px solid var(--grid); border-radius: 12px; }
  .bug-item small { color: var(--ink-soft); }
  .bug-item p { margin: 0; }
  .bug-reply { border-left: 3px solid var(--accent); padding: 8px 10px; border-radius: 8px; background: var(--paper-2); white-space: pre-wrap; }
  /* Лента поддержки: реплики родителя справа, помощника и владельца слева. */
  .sup-thread { display: flex; flex-direction: column; gap: 8px; flex: 1 1 auto; min-height: 0;
                overflow-y: auto; overscroll-behavior-y: contain; padding: 2px; }
  .sup-msg { max-width: 92%; padding: 10px 12px; border-radius: 14px; line-height: 1.35; white-space: pre-wrap; overflow-wrap: anywhere; }
  .sup-msg.me { align-self: flex-end; background: var(--accent); color: var(--on-accent); border-bottom-right-radius: 4px; }
  .sup-msg.helper { align-self: flex-start; background: var(--paper-2); border: 1px solid var(--grid); border-bottom-left-radius: 4px; }
  .sup-msg.owner { align-self: flex-start; background: var(--paper-2); border-left: 3px solid var(--accent); border-radius: 8px 14px 14px 8px; }
  .sup-msg small { display: block; font-size: .72rem; color: var(--ink-soft); margin-bottom: 3px; }
  .sup-msg.me small { color: var(--on-accent); opacity: .85; }
  .sup-msg .sup-act { display: block; margin-top: 8px; }
  .set-list.set-sub { padding-left: 10px; }

  pre.ctx {
    margin: 0;
    background: var(--paper);
    border: 1px solid var(--rule);
    border-radius: 11px;
    padding: 12px 13px;
    font-family: ui-monospace, "SF Mono", "Cascadia Code", Consolas, monospace;
    font-size: .76rem;
    line-height: 1.55;
    color: var(--ink-soft);
    white-space: pre-wrap;
    word-break: break-word;
    max-height: 240px;
    overflow-y: auto;
    -webkit-user-select: text;
    user-select: text;
  }

  /* Тон сообщения задаём явно, а зелёный оставляем только успеху. Раньше это
     поле всегда было зелёным — и «Отправлено», и «Имя не сохранилось», и
     «Это устройство отключили от семьи». Человек скользит взглядом по цвету
     раньше, чем читает: зелёная тревога выглядит как «всё в порядке».
     Нейтральный цвет по умолчанию значит, что новое сообщение не соврёт,
     даже если про его тон забудут. */
  .sup-status {
    font-size: .84rem; font-weight: 600; min-height: 1.3em;
    color: var(--ink-soft);
  }
  .sup-status.ok { color: var(--correct); }
  .sup-status.bad { color: var(--wrong); }

  /* ── Мессенджер ─────────────────────────────────────── */

  /* Список разговоров и лента — по образцу «Поддержки разговором». Цвета
     только из токенов: тёмная тема и скины меняют токены, а не структуру.
     Оформление ведёт GPT; здесь каркас, который держит 44 px и 320 px. */
  #btnMsgTop { --icon: #3F7A2A; }
  @media (max-width: 640px) { #btnMsgTop { order: -1; } }
  /* Размер от корня: тело страницы задано в px, и при крупном тексте имена и
     реплики оставались мелкими, а подписи под ними росли. */
  .msg-card, .msg-chat { font-size: 1rem; }
  .msg-card { padding: 14px 14px 16px; display: flex; flex-direction: column; gap: 6px; }
  .msg-card h2 { margin: 0; font-family: var(--font-display); font-size: 1rem; font-weight: 700; }
  .msg-sec { margin: 12px 4px 2px; font-size: .78rem; font-weight: 700; letter-spacing: .04em;
             text-transform: uppercase; color: var(--ink-soft); }
  .msg-list { display: flex; flex-direction: column; gap: 2px; }
  .msg-row { display: flex; align-items: center; gap: 10px; width: 100%; min-height: 56px;
             padding: 8px 10px; text-align: left; background: transparent; border: 0;
             border-radius: 12px; color: var(--ink); font: inherit; cursor: pointer; }
  .msg-row:hover { background: var(--paper-2); }
  .msg-row:focus-visible { outline: 3px solid var(--accent); outline-offset: 1px; }
  .msg-ava { flex: none; width: 40px; height: 40px; border-radius: 50%; display: flex;
             align-items: center; justify-content: center; font-family: var(--font-display);
             font-weight: 700; background: var(--accent-dim); color: var(--accent); }
  .msg-row.k-family .msg-ava { background: var(--gold-dim); color: var(--gold-ink); }
  .msg-row.k-outside .msg-ava, .msg-row.k-taya .msg-ava { background: var(--correct-dim); color: var(--correct); }
  .msg-row.k-support .msg-ava, .msg-row.k-people .msg-ava { background: var(--paper-2); color: var(--ink-soft);
             border: 1px solid var(--grid); }
  .msg-mid { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
  .msg-top { display: flex; align-items: baseline; gap: 8px; }
  .msg-top b { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; }
  .msg-when { flex: none; color: var(--ink-faint); font-size: .75rem; }
  .msg-last { color: var(--ink-soft); font-size: .88rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .msg-unread { flex: none; min-width: 22px; height: 22px; padding: 0 6px; border-radius: 11px;
                background: var(--accent); color: var(--on-accent); font-size: .75rem; font-weight: 700;
                display: flex; align-items: center; justify-content: center; }
  .msg-who-hint { margin: 0 4px 6px; }
  .msg-who-new { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
  .msg-who-new input { flex: 1 1 12em; min-width: 0; min-height: 44px; }
  .msg-who-new .go { min-height: 44px; padding: 10px 16px; font-size: 1rem; }
  /* Высота ленты — от настоящего верха карточки (мсгВысота): шапка на телефоне
     выше 132 px, и композер уезжал под край экрана. */
  .sup-chat.msg-chat { height: calc(100vh - var(--msg-top, 132px)); height: calc(100dvh - var(--msg-top, 132px)); }
  .msg-chat-title { flex: 1 1 auto; min-width: 0; }
  .sup-card #msgText { min-height: 44px; max-height: 132px; padding: 10px 12px; resize: none; overflow-y: auto; }
  /* Без скрепки (учитель, друг) поле занимает её место, а не ужимается в 44 px. */
  .sup-composer.no-clip { grid-template-columns: minmax(0, 1fr) 44px; }
  .msg-chat-title h2 { overflow-wrap: anywhere; }
  .msg-chat-title small { display: block; color: var(--ink-soft); font-size: .78rem; }
  .msg-menu { min-width: 44px; min-height: 44px; padding: 0; display: flex; align-items: center; justify-content: center; }
  .msg-menu-pop { display: flex; flex-direction: column; gap: 4px; padding: 6px; background: var(--card);
                  border: 1px solid var(--grid); border-radius: 12px; box-shadow: var(--shadow); }
  .msg-menu-pop[hidden] { display: none; }
  .msg-menu-pop button { min-height: 44px; text-align: left; }
  .msg-note { margin: 0; padding: 8px 10px; border-radius: 10px; background: var(--gold-dim);
              color: var(--gold-ink); font-size: .85rem; }
  .msg-msg.them { align-self: flex-start; background: var(--paper-2); border: 1px solid var(--grid);
                  border-bottom-left-radius: 4px; }
  .msg-msg.deleted { font-style: italic; color: var(--ink-soft); }
  .msg-msg.me.deleted { color: var(--on-accent); }
  .msg-msg.failed { outline: 2px solid var(--wrong); outline-offset: 1px; }
  .msg-refused { display: block; margin-top: 6px; font-size: .8rem; font-weight: 600; white-space: normal; }
  .msg-msg.me[tabindex] { cursor: pointer; }
  .msg-msg.me[tabindex]:focus-visible { outline: 3px solid var(--ink); outline-offset: 2px; }
  /* Снимок в ленте — не больше 240 px и без полей: длинный снимок экрана
     занимал весь экран, а вокруг узкой картинки оставались белые поля
     (обращение 99). Целиком — по нажатию. */
  /* 240 px — обращение 107 («увеличь на 50%» от 160). Снимки одного
     сообщения идут рядом и переносятся строкой (обращение 108). */
  .msg-photos { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 6px; margin-top: 6px; white-space: normal; }
  /* Несколько снимков — плитками, как в ленте поддержки: пузырь по ширине
     плиток, а не шире их (обращение 111: справа оставалась пустота). */
  .msg-photos-many { display: grid; grid-template-columns: repeat(2, 116px); width: max-content; max-width: 100%; }
  .msg-photos-many .msg-photo { width: 116px; height: 116px; max-width: 116px; max-height: 116px; object-fit: cover; }
  .msg-photo { display: block; width: auto; height: auto; max-width: min(100%, 240px); max-height: 240px;
               border-radius: 10px; cursor: zoom-in; }
  .msg-photo.bad { min-height: 44px; }
  .msg-photo-gone { display: block; margin-top: 6px; font-size: .8rem; font-style: italic; }
  .msg-acts { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; white-space: normal; }
  .msg-act { min-height: 44px; padding: 0 12px; font-size: .85rem; }
  .msg-msg.me .msg-act { background: transparent; color: var(--on-accent); border-color: currentColor; }
  .msg-earlier { align-self: center; min-height: 44px; }
  .msg-empty { align-self: center; margin: auto 0; }
  .msg-person { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding: 8px 4px;
                border-bottom: 1px solid var(--grid); }
  .msg-person > span { flex: 1 1 10em; min-width: 0; display: flex; flex-direction: column; }
  .msg-person small { color: var(--ink-soft); }
  .msg-code { padding: 12px; border-radius: 12px; background: var(--accent-dim); }
  .msg-code[hidden] { display: none; }
  .msg-code b { display: block; font-family: var(--font-display); font-size: 1.8rem; letter-spacing: .12em;
                font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
  .msg-code p { margin: 6px 0 0; }
  .msg-people-actions { display: flex; flex-wrap: wrap; gap: 8px; }
  .msg-people-actions button { min-height: 44px; flex: 1 1 10em; }
  .msg-accept { display: flex; flex-wrap: wrap; gap: 8px; }
  .msg-accept input { flex: 1 1 9em; min-width: 0; min-height: 44px; text-transform: uppercase; }

  /* Разговоры: отдельные читаемые карточки и компактная шапка переписки. */
  .msg-card { max-width: 720px; margin-inline: auto; padding: 18px; gap: 12px; }
  .msg-list { gap: 8px; }
  .msg-sec { text-transform: none; letter-spacing: 0; font-size: .9rem; }
  .msg-row { min-height: 76px; padding: 12px; border: 1px solid var(--grid);
    background: var(--card); border-radius: 18px; }
  .msg-ava { width: 48px; height: 48px; border-radius: 16px; }
  .msg-ava svg { width: 40px; height: 40px; }
  .msg-top { flex-wrap: wrap; gap: 2px 8px; }
  .msg-last { white-space: normal; display: -webkit-box; -webkit-line-clamp: 2;
    -webkit-box-orient: vertical; line-height: 1.4; }
  .msg-unread { min-height: 26px; height: auto; }
  .msg-chat .sup-head { align-items: flex-start; padding-bottom: 8px; border-bottom: 1px solid var(--grid); }
  .msg-chat-title h2 { font-size: 1rem; line-height: 1.25; }
  .msg-chat-title small { margin-top: 3px; }
  .msg-thread { padding: 6px 2px; scroll-padding-block: 12px; }
  .msg-msg { line-height: 1.45; }
  .msg-note { font-size: .8rem; line-height: 1.35; }
  .msg-chat #msgText { font-size: 1rem; line-height: 1.3; }
  .msg-person { padding: 12px; margin-bottom: 8px; border: 1px solid var(--grid); border-radius: 14px; }
  @media (max-width: 640px) {
    body:has(#viewMsgChat.on) header { display: none; }
    .msg-card { padding: 12px; }
    .msg-row { padding: 10px; gap: 8px; }
    .msg-chat.sup-card { padding: 12px; }
    .msg-chat .sup-head { gap: 6px; }
    /* Разговор на телефоне держится видимой области над клавиатурой
       (--msg-vt/--msg-vh из мсгВидОбновить), как окно Таи. Без этого лента
       уезжала за верхний край, а поле висело посреди экрана. */
    /* Без клавиатуры карточка держится за низ окна, а не считает высоту из
       visualViewport: в установленном приложении на iOS 26 высота видимой
       области идёт без строки состояния (894 при экране 956), а верх
       карточки уже отступает на безопасное поле — строка вычиталась дважды,
       и под карточкой оставалось ~60 точек пустоты (обращение 98, 15.09). */
    /* --ios-gap (окноНедобор): на iOS 26 в установленном приложении окно для
       fixed кончается на высоту строки состояния выше низа экрана (обращение
       102: fixed 894 при экране 956, поля 62/34). Ниже окна fixed не рисуется —
       22.84 дотягивал карточку туда, и низ с полем обрезался (обращение 106).
       Полоса «Домой» при этом ниже края окна: отступ под неё не нужен. */
    #viewMsgChat.on .sup-chat.msg-chat,
    #viewSupport.on .sup-chat {
      position: fixed; left: 8px; right: 8px; z-index: 20; margin: 0; box-sizing: border-box;
      top: calc(var(--msg-vt, 0px) + 8px + env(safe-area-inset-top, 0px));
      bottom: calc(8px + max(0px, env(safe-area-inset-bottom, 0px) - var(--ios-gap, 0px))); height: auto;
    }
    #viewMsgChat.on .sup-chat.msg-chat.msg-kb,
    #viewSupport.on .sup-chat.msg-kb {
      bottom: auto;
      height: calc(var(--msg-vh, 100dvh) - 16px - env(safe-area-inset-top, 0px));
    }
    /* «Поддержка» — такой же чат: шапка приложения ей не нужна, у карточки
       своя стрелка назад (снимок владельца 22:47 — поле ушло за край). */
    body:has(#viewSupport.on) header { display: none; }
    #viewSupport.on .sup-chat .sup-thread { min-height: 0; }
    /* С открытой клавиатурой строка «Куда ответить…» под полем отнимала место
       у ленты — прячем, пока фокус не в ней самой (там поле почты). */
    #viewSupport.on .sup-chat.msg-kb .sup-ctx:not(:focus-within) { display: none; }
    .msg-chat .msg-thread { min-height: 0; }
  }
  .msg-unbound { margin: 4px 4px 8px; font-size: .95rem; line-height: 1.45; }
  .prof-code-kids { margin-top: 8px; }
  .prof-code-kids[hidden] { display: none; }
  .prof-code-kids .chip { min-height: 44px; padding: 10px 14px; }

  .icon-btn.alert[aria-pressed="true"] {
    border-color: var(--wrong); background: var(--wrong-dim); color: var(--wrong);
  }

  .foot { font-size: .74rem; color: var(--ink-faint); text-align: center; padding-top: 4px; }
  .linklike {
    /* Выглядит ссылкой, а нажимается как кнопка: на телефоне высота была
       19 px, и «Другая почта» рядом с «Отправить ещё раз» превращалась в
       лотерею. Палец у взрослого и у семилетки одинаково широкий. */
    min-height: 44px; padding: 0 10px;
    background: none; border: none;
    font-size: inherit; color: inherit;
    text-decoration: underline; text-underline-offset: 2px;
  }
  .linklike:hover { color: var(--accent); }

  /* Настройки */
  .settings { padding: 22px 20px; display: flex; flex-direction: column; gap: 14px; max-width: 560px; margin: 0 auto; }
  /* На телефоне боковой отступ обёртки лишний: снаружи уже 16 px оболочки,
     внутри 18 px карточки — вместе 54 px с края на 320 px (аудит 07.09).
     Правило стоит после основного, иначе проигрывает ему по порядку. */
  @media (max-width: 479px) { .settings { padding-left: 0; padding-right: 0; } }
  .set-card { padding: 18px 18px 20px; display: flex; flex-direction: column; gap: 12px; }
  .set-card h2 { margin: 0; font-family: var(--font-display); font-size: 1.02rem; }
  /* Колонка не шире карточки: при крупном тексте на 320 слово
     «конфиденциальность» иначе растягивало сетку за край экрана. */
  .set-list { display: grid; gap: 10px; grid-template-columns: minmax(0, 1fr); }
  /* Первые шаги. Рамка цветом согласия, а не тревоги: это приглашение, а не
     ошибка, и висеть карточка будет ровно до конца настройки. */
  .start-card { border: 2px solid var(--accent); }
  .start-head { display: flex; align-items: center; justify-content: space-between;
                margin-bottom: 4px; }
  .start-num { flex: none; width: 30px; height: 30px; border-radius: 50%;
               display: inline-flex; align-items: center; justify-content: center;
               background: var(--paper); font-weight: 700; }
  .start-done .start-num { background: var(--correct); color: #fff; }
  .start-done b { text-decoration: line-through; opacity: .65; }
  /* Строка без стрелки (сделанная или запертая) не должна разъезжаться:
     без этого текст уходил вправо, и запертый шаг выглядел другой породой. */
  .start-card .set-row > div { flex: 1; }
  .start-card .set-row[disabled] { cursor: default; opacity: .8; }
  .start-card .set-row[disabled]:hover { border-color: var(--rule); }
  .step-mark { margin: 4px 0 2px; font-weight: 700; color: var(--ink-soft); }
  .fam-ask { border: 2px solid var(--accent); }
  /* Строка устройства: слева кто и когда, справа отключение. Своё устройство
     без кнопки — отключить себя нельзя, и лишняя кнопка только пугала бы. */
  .dev-row { display: flex; align-items: center; gap: 10px; padding: 12px 14px;
             border-radius: 14px; background: var(--paper-2); }
  .dev-row > div { flex: 1; min-width: 0; }
  .dev-row b { display: block; }
  .dev-row small { display: block; color: var(--ink-soft); }
  .dev-row .ghost { min-height: 44px; padding: 0 14px; flex: none; }
  .dev-mine { border: 2px solid var(--accent); }
  .set-row {
    display: flex; align-items: center; justify-content: space-between; gap: 12px;
    padding: 12px 14px; border: 1.5px solid var(--rule); border-radius: var(--r);
    background: var(--paper); color: var(--ink); font: inherit; text-align: left;
    width: 100%; cursor: pointer; text-decoration: none;
    transition: border-color .15s, background .15s;
  }
  .set-row:hover { border-color: var(--accent); }
  .set-row > div { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
  .set-row b { font-family: var(--font-display); font-size: .95rem; font-weight: 700; overflow-wrap: anywhere; hyphens: auto; }
  .set-row small { font-size: .8rem; color: var(--ink-soft); line-height: 1.35; overflow-wrap: anywhere; hyphens: auto; }
  .set-row small.fun-progress, .tile small.fun-progress { color: var(--accent); font-weight: 800; }
  .set-row .chev { color: var(--ink-faint); font-size: 1.15rem; flex: none; }
  .set-row.danger b { color: var(--wrong); }
  #profShare small { font-size: 1rem; line-height: 1.5; }
  .share-fallback { display: grid; gap: 12px; padding: 14px; min-width: 0;
    border: 1px solid var(--rule); border-radius: var(--r); background: var(--card); }
  .share-fallback p { margin: 0; font-size: 1rem; line-height: 1.5; color: var(--ink); overflow-wrap: anywhere; }
  .share-fallback .share-link { padding: 10px; background: var(--paper); border: 1px solid var(--ink-soft);
    border-radius: 10px; overflow-wrap: anywhere; -webkit-user-select: text; user-select: text;
    -webkit-touch-callout: default; }
  .share-fallback button { min-height: 48px; font-size: 1rem; white-space: normal; overflow-wrap: anywhere; }
  .knob {
    flex: none; width: 42px; height: 26px; border-radius: 13px; position: relative;
    background: var(--paper-2); border: 1.5px solid var(--rule);
    transition: background .15s, border-color .15s;
  }
  .knob::after {
    content: ""; position: absolute; top: 2px; left: 2px; width: 18px; height: 18px;
    border-radius: 50%; background: var(--ink-faint);
    transition: left .15s, background .15s;
  }
  .set-row[aria-pressed="true"] .knob { background: var(--accent-dim); border-color: var(--accent); }
  .set-row[aria-pressed="true"] .knob::after { left: 18px; background: var(--accent); }

  /* Подсказка «дальше по касанию» после неправильного ответа */
  .verdict .solved-ok { display: block; font-size: 1.1rem; margin-top: 4px; color: var(--correct); }
  .verdict .cont { display: block; margin-top: 8px; font-size: .8rem; font-weight: 400; color: var(--ink-faint); }

  /* Крупные цели нажатия для 5–6 лет (класс age5 на body; идёт после
     медиа-запроса невысоких экранов и поэтому побеждает его) */
  .age5 .key { height: 72px; font-size: 1.5rem; }
  .age5 .choice { height: 80px; font-size: 1.8rem; }
  .age5 .pad { gap: 12px; }
  .age5 .choices { gap: 14px; }

  /* На невысоких экранах (iPhone SE/8) крупные клавиши не помещаются целиком —
     ужимаем, чтобы «Подсказка» и «Закончить» оставались на виду без прокрутки */
  @media (max-height: 700px) {
    .age5 .key { height: 54px; font-size: 1.25rem; }
    .age5 .choice { height: 58px; font-size: 1.45rem; }
    .age5 .pad { gap: 8px; }
    .age5 .choices { gap: 9px; }
    .board { min-height: 132px; padding: 12px 12px 10px; }
    .helpbar .ghost { padding: 9px 12px; }
  }

  /* Компактная карточка «Что не так?» */
  .sup-card { padding: 14px 14px 16px; gap: 10px; }
  .sup-card .chip { padding: 10px 12px; min-height: 44px; font-size: .88rem; }
  /* Три кнопки выбора темы ушли — освободившееся место отдаём тому, ради
     чего экран и открывают: рассказу. 72 точки обрезали даже подсказку. */
  .sup-card textarea { padding: 10px 12px; }
  /* Две колонки, пока обе помещаются: при «Вдвое» на 320 px кнопки «Фото» и
     «Отправить» вылезали за экран на 78 px (аудит 07.09). Ниже 7,5rem на
     колонку — в столбик. */
  .fam-form.two { grid-template-columns: repeat(auto-fit, minmax(min(100%, 7.5rem), 1fr)); }
  /* Окно добавления ребёнка: поле и две кнопки, пока оно раскрыто. */
  .fam-kid-box { padding: 10px; border: 1px solid var(--accent); border-radius: 12px; }
  .fam-kid-actions { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
  .fam-kid-actions button { min-height: 44px; }
  .fam-form.two .wide { grid-column: 1 / -1; margin: 0; }

  .tile i.fixmark { color: var(--wrong); font-weight: 700; white-space: nowrap; }

  /* Обучалка */
  .lesson-pic { display: flex; justify-content: center; margin: 2px 0 12px; min-height: 120px; align-items: center; }
  .lesson-pic svg { width: 100%; max-width: 320px; height: auto; display: block; }
  .lesson-text {
    font-size: 1.05rem; line-height: 1.5; font-weight: 600;
    color: var(--ink); text-align: center; margin: 0 0 12px;
  }
  .lesson-svg text { font-family: var(--font-body); }

  /* Чтение */
  /* Колонка не шире списка: без minmax(0, 1fr) сетка росла по самому
     широкому ряду, и на 320 px при тексте ×2 «Стихи» уезжали вбок на 29 px
     (обход всех занятий, 28.09). */
  .read-list { display: grid; gap: 8px; grid-template-columns: minmax(0, 1fr); }
  .read-row > div { min-width: 0; }
  .read-row {
    display: flex; align-items: center; gap: 12px; width: 100%;
    text-align: left; padding: 12px 14px; min-height: 58px;
    border: 1px solid var(--rule); border-radius: 12px; background: var(--paper);
  }
  .read-row em { font-style: normal; font-size: 1.3rem; font-size: min(1.3rem, 8.5vw); }
  .read-row b { display: block; font-size: 1rem; }
  .read-row small { display: block; color: var(--ink-soft); font-size: .82rem; }
  .read-row i.done { margin-left: auto; font-style: normal; color: var(--correct); font-weight: 700; }
  .poem-author { color: var(--ink-soft); font-size: .9rem; font-weight: 600; margin-top: 2px; }
  .poem {
    font-size: 1.16rem; line-height: 1.75; font-weight: 600;
    text-align: center; margin: 10px 0 14px;
  }
  .poem div { padding: 3px 8px; border-radius: 8px; }
  .poem.prose { text-align: left; font-size: 1.04rem; line-height: 1.65; }
  .poem.prose div { padding: 4px 8px; }
  /* Чтение вслух: текст крупнее обычного — читают с руки, а не глазами про себя */
  .poem.aloud {
    text-align: left; font-size: 1.22rem; line-height: 1.95; font-weight: 600;
    letter-spacing: .01em;
  }
  .aloud-clock {
    font-family: var(--font-display); font-size: 2.6rem; font-weight: 800;
    text-align: center; color: var(--accent); margin: 2px 0 6px;
    font-variant-numeric: tabular-nums;
  }
  .aloud-big {
    font-family: var(--font-display); font-size: 2.3rem; font-weight: 800;
    text-align: center; color: var(--correct); margin: 6px 0 2px; line-height: 1.15;
  }
  .aloud-big small { display: block; font-size: .9rem; font-weight: 600; color: var(--ink-soft); }
  /* Кнопки на этом экране лежат прямо в карточке, без сетки — растягиваем сами */
  #viewAloud .age-opt { width: 100%; }
  /* На длинном отрывке кнопка уезжала вниз, и ребёнок листал страницу, пока
     идёт секундомер. Держим её на виду. -webkit- нужен старому Safari. */
  #btnAloudDone {
    position: -webkit-sticky; position: sticky; bottom: 6px; z-index: 2;
    box-shadow: 0 6px 18px rgba(0, 0, 0, .35);
  }
  #aloudClock {
    position: -webkit-sticky; position: sticky; top: 0; z-index: 2;
    background: var(--card); padding: 4px 0 2px;
  }
  .read-head {
    font-size: .78rem; letter-spacing: .08em; text-transform: uppercase;
    color: var(--ink-faint); font-weight: 700; margin: 6px 0 2px 4px;
  }
  #btnPoemSyl[aria-pressed="true"] {
    background: var(--accent); border-color: var(--accent); color: var(--on-accent);
  }
  /* Длинные строки не должны ломаться посередине — уменьшаем шрифт */
  .poem.long { font-size: 1.02rem; line-height: 1.7; }
  .poem.longer { font-size: .92rem; line-height: 1.65; }
  .poem div.now { background: var(--accent-dim); }
  @supports not (inset: 0) {
    .read-list > * + * { margin-top: 8px; }
    .read-row > * + * { margin-left: 12px; }
  }
  /* Подпорка окна (окноПодпорка): на iOS 26 в установленном приложении окно
     ниже экрана на строку состояния. Выше делаем страницу, а не карточку —
     дотягивать закреплённое за край окна нельзя, его там не рисуют. */
  .окно-подпорка { min-height: calc(100% + var(--ios-shim, 0px)); }
  .lesson-dots { display: flex; justify-content: center; gap: 7px; margin-bottom: 14px; }
  .lesson-dots i { width: 9px; height: 9px; border-radius: 50%; background: var(--rule); display: block; }
  .lesson-dots i.on { background: var(--accent); }
  /* Не влезает ряд — переносится кнопка целиком, а не буквы в подписи. С
     overflow-wrap: anywhere (22.81) при 150–200 % выходило «Нач / нё / м ▶» и
     «Даль / ше» даже на 440 px; без него (22.80) — прокрутка вбок на 4 px.
     Основа кнопки — подпись в одну строку: когда подписи не помещаются,
     кнопка уходит на следующую строку и растягивается во всю ширину. */
  .lesson-nav { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 12px; }
  .lesson-nav .ghost, .lesson-nav .go {
    flex: 1 1 auto; min-width: 0; min-height: 48px; padding: 10px 8px;
  }
  .lesson-nav .hint { flex: 1 1 100%; }
  .lesson-nav #btnLessonPrev { flex: 0 0 64px; }   /* стрелке треть ряда не нужна: подписи соседей не переносятся */
  @supports not (inset: 0) {
    .lesson-dots > * + * { margin-left: 7px; }
    .lesson-nav > * + * { margin-left: 8px; }
  }

  .tbl { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin: 2px 0 10px; }
  .tbl-row {
    display: flex; align-items: center; justify-content: center;
    border: 1px solid var(--rule); border-radius: 10px;
    background: var(--paper); color: var(--ink);
    min-height: 46px; padding: 6px 8px;
    font-size: 1.02rem; font-weight: 700;
    font-variant-numeric: tabular-nums; white-space: nowrap;
  }
  .tbl-row.mark { border-color: var(--accent); color: var(--accent); }
  .tbl-note {
    color: var(--ink-soft); font-size: .9rem; font-weight: 600;
    text-align: center; margin: 0 0 10px; line-height: 1.4;
  }
  @media (max-width: 340px) { .tbl { grid-template-columns: 1fr; } }

  /* Дневник ответов: пример + ответ ребёнка, цветом */
  .ans-list { display: flex; flex-direction: column; gap: 6px; }
  .ans {
    display: flex; align-items: baseline; gap: 10px;
    padding: 7px 10px; border-radius: 10px; border: 1px solid var(--rule);
    background: var(--paper);
  }
  .ans b {
    font-family: var(--font-display); font-size: 1rem; font-weight: 700;
    font-variant-numeric: tabular-nums; flex: 1; min-width: 0;
  }
  .ans small { color: var(--ink-faint); font-size: .74rem; white-space: nowrap; }
  .ans.ok { border-color: var(--accent); background: var(--accent-dim); }
  .ans.ok b { color: var(--accent); }
  .ans.bad { border-color: var(--wrong); background: var(--wrong-dim); }
  .ans.bad b, .ans.bad small { color: var(--wrong); }
  h2 .day-sum {
    font-family: var(--font-body); font-weight: 400; font-size: .78rem;
    color: var(--ink-faint); margin-left: 8px;
  }
  @supports not (inset: 0) {
    .ans-list > * + * { margin-top: 6px; }
    .ans > * + * { margin-left: 10px; }
  }

  /* Свёрнутый блок «Что будет отправлено» */
  .ctx-fold summary {
    font-family: var(--font-display); font-size: 1.02rem; font-weight: 700;
    cursor: pointer; list-style: none; -webkit-user-select: none; user-select: none;
  }
  .ctx-fold summary::-webkit-details-marker { display: none; }
  .ctx-fold summary::before { content: "▸ "; color: var(--ink-faint); }
  .ctx-fold[open] summary::before { content: "▾ "; }
  .ctx-fold > * + * { margin-top: 10px; }

  /* Семья */
  .fam-form { display: grid; gap: 8px; }
  /* Поля ввода — все сразу, а не по одному классу. Правило писали под
     .fam-form, и каждое новое поле оказывалось системным: высота 21 точка,
     шрифт 13 — попасть пальцем нечем. Так вышло с «куда ответить» в
     поддержке, с названием и адресом места, со словом подтверждения при
     удалении данных и с именем взрослого. Проще описать все поля разом.

     Шрифт не меньше 16 px намеренно: айфон увеличивает страницу, когда
     фокус попадает в поле мельче, — а вернуть масштаб ребёнку нечем, мы сами
     запретили щипок ради того, чтобы он не сбивал экран во время занятия. */
  .view input[type="text"], .view input[type="email"], .view input[type="tel"],
  .view input[type="search"], .view input[type="number"], .view textarea,
  .fam-form input, .fam-input {
    padding: 12px 14px; border: 1.5px solid var(--rule); border-radius: var(--r);
    background: var(--paper); color: var(--ink); font: inherit; font-size: 16px;
    width: 100%; -webkit-appearance: none; appearance: none;
  }
  .view input[type="text"]:focus, .view input[type="email"]:focus,
  .view input[type="tel"]:focus, .view input[type="search"]:focus,
  .view input[type="number"]:focus, .view textarea:focus,
  .fam-form input:focus, .fam-input:focus { border-color: var(--accent); outline: none; }
  .set-row .kid-stat { color: var(--ink-faint); font-size: .8rem; flex: none; }

  /* Альбом наклеек */
  /* Куда идём. Кнопки крупные: ребёнок жмёт их на ходу, часто в варежке. */
  /* При крупном тексте пара «откуда → куда» складывается в столбик, а длинное
     название места переносится, а не уезжает за экран (аудит 07.09). */
  .way-pair { display: flex; align-items: center; gap: 8px; margin: 6px 0 10px; flex-wrap: wrap; }
  .way-slot { flex: 1 1 6rem; min-width: 0; min-height: 76px; display: flex; flex-direction: column;
              align-items: flex-start; justify-content: center; gap: 2px;
              padding: 10px 12px; border-radius: 16px; border: 1px solid var(--rule);
              background: var(--card); color: var(--ink); text-align: left; }
  .way-slot-cap { font-size: .78rem; color: var(--ink-soft); }
  .way-slot-name { font-size: 1.15rem; font-weight: 700; overflow-wrap: anywhere; }
  /* Кнопка, а не значок: ею меняют направление. Размер пальцевый — её жмут
     на улице, на ходу, одной рукой. */
  .way-arrow { font-size: 1.5rem; color: var(--ink-soft); flex: none;
               min-width: 44px; min-height: 44px; padding: 0; border-radius: 14px;
               border: 1px solid var(--rule); background: var(--paper-2);
               font-family: inherit; line-height: 1; cursor: pointer; }
  .way-arrow:disabled { opacity: .45; cursor: default; }
  .way-places { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
                gap: 8px; margin-top: 6px; }
  /* Мои места. Плитки типов крупные: их жмут с телефона одной рукой,
     часто стоя. */
  .pl-kinds { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
  .pl-kind { min-height: 68px; display: flex; flex-direction: column; align-items: center;
             justify-content: center; gap: 2px; padding: 8px 4px; border-radius: 14px;
             border: 2px solid var(--rule); background: var(--paper-2); color: var(--ink);
             font: inherit; font-size: .82rem; cursor: pointer; }
  .pl-kind span { font-size: 1.5rem; line-height: 1; }
  .pl-kind.on { border-color: var(--accent); background: var(--accent-dim); }
  /* Шаг дороги: номер, текст и две кнопки. Номер крупный — ребёнок ищет
     глазами «где я сейчас», а не читает подряд. */
  /* Карта в пути. Ребёнок смотрит на неё на ходу, поэтому она крупная —
     мелкую он будет разглядывать, стоя посреди тротуара. */
  /* position: relative обязателен: кнопка «На весь экран» внутри коробки
     стоит absolute, и без этого она отсчитывается от страницы. 04.09 она
     так и уехала под чёлку телефона — владелец видел её поверх часов и не
     мог нажать, а написал «дай возможность разворачивать карту». Кнопка всё
     это время была, просто не там. */
  .way-map { position: relative; margin: 10px 0; border-radius: 16px; overflow: hidden;
             border: 2px solid var(--rule); background: var(--paper-2); }
  .way-map iframe { display: block; width: 100%; height: 40vh; min-height: 220px;
                    max-height: 380px; border: 0; }
  .way-map.big iframe { height: 38vh; min-height: 200px; max-height: 420px; }
  /* «Я дошёл» — главная кнопка пути, и она обязана быть под пальцем всегда.
     На телефоне карта со списком шагов уводили её за нижний край: ребёнок
     стоял у школы и не понимал, чем отметить приход. */
  .way-done { position: sticky; bottom: 10px; z-index: 5; }
  /* Профиль в шапке. Точка-подсказка горит, пока вход не сделан: без входа
     прогресс живёт только в этом браузере, и родитель должен это заметить
     раньше, чем потеряет планшет. */
  .prof-btn { position: relative; }
  .prof-btn b { position: absolute; top: -4px; right: -4px; min-width: 18px; height: 18px;
                border: 2px solid var(--paper); box-sizing: border-box;
                border-radius: 9px; background: var(--gold); color: #241a00;
                font-size: .62rem; line-height: 14px; text-align: center; }
  /* Карточка профиля — кнопка во всю ширину: имя правится нажатием по ней. */
  .prof-who { display: flex; align-items: center; gap: 12px; margin: 8px 0 10px;
              width: 100%; text-align: left; font: inherit; color: var(--ink);
              background: var(--paper-2); border: 1px solid var(--grid);
              border-radius: 14px; padding: 12px 14px; min-height: 64px; }
  .prof-who:hover, .prof-who:focus-visible { border-color: var(--accent); background: var(--paper); }
  .prof-who-text { flex: 1 1 auto; min-width: 0; }
  .prof-who .chev { color: var(--ink-faint); flex: none; }
  .prof-who[aria-expanded="true"] { border-color: var(--accent); }
  /* Ссылка живёт в самой карточке и мельче имени: её замечают, когда ищут,
     и не мешают, когда нет. Владелец 03.09: «много места занимает». */
  .prof-rename { display: inline-block; margin-top: 2px; padding: 6px 0;
                 font-size: .82rem; }
  .prof-ava { width: 52px; height: 52px; border-radius: 50%; display: flex; flex: none;
              font-size: 1.3rem; font-family: var(--font-display);
              align-items: center; justify-content: center; font-weight: 700;
              font-size: 1.2rem; background: var(--accent); color: var(--on-accent); }
  .prof-who small { display: block; color: var(--ink-soft); font-size: .82rem; }
  .prof-main { width: 100%; margin-bottom: 12px; }
  /* Код показываем один раз и крупно: его переписывают на другое устройство
     или диктуют голосом, поэтому он должен читаться с расстояния руки. */
  .prof-code { margin: 8px 0 12px; padding: 12px; border-radius: 14px;
               background: var(--paper-2); border: 2px solid var(--accent);
               text-align: center; }
  .prof-code b { display: block; font-size: 1.7rem; letter-spacing: .12em;
                 font-family: var(--font-display), monospace; }
  .prof-code small { display: block; margin-top: 6px; color: var(--ink-soft); }
  .rt-step { display: grid; grid-template-columns: 34px 1fr; gap: 8px;
             align-items: start; padding: 8px; border-radius: 12px;
             background: var(--paper-2); margin-bottom: 8px; }
  .rt-num { width: 30px; height: 30px; border-radius: 50%; display: flex;
            align-items: center; justify-content: center; font-weight: 700;
            background: var(--accent); color: var(--on-accent); }
  .rt-step input { width: 100%; }
  .rt-tools { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 6px; }
  /* 44 пикселя — не про красоту: меньше палец не попадает, и взрослый
     промахивается по «убрать» вместо «выше». */
  .rt-tools button { flex: 1 1 auto; min-width: 92px; min-height: 44px; font-size: .82rem;
                     padding: 8px; border-radius: 10px; border: 2px solid var(--rule);
                     background: var(--paper); color: var(--ink); font-family: inherit;
                     cursor: pointer; }
  /* Стрелки порядка — узкие и рядом: их жмут парой. Раньше кнопка была
     одна, подписана словом «выше», и терялась между «на карте» и
     «убрать» — владелец её просто не нашёл. */
  .rt-tools .rt-move { flex: 0 0 auto; min-width: 52px; font-size: 1.05rem;
                       line-height: 1; font-weight: 700; }
  .rt-tools .rt-move:disabled { opacity: .35; cursor: default; }
  /* «Убрать» больше не растягивается на всю строку рядом со стрелками. */
  .rt-tools .rt-rm { flex: 0 1 auto; min-width: 92px; }
  .rt-tools button.has { border-color: var(--accent); }
  /* Главная строка экрана: её читают одним взглядом, стоя в дверях. */
  .watch-now { font-size: 1.15rem; font-weight: 700; margin: 6px 0 2px; }
  /* Модификаторы с собственным именем: класс go в проекте уже занят синей
     кнопкой, и «Идёт в школу» получилось синим по синему — строку, ради
     которой открывают экран, прочитать было нельзя. */
  .watch-now.wt-go { color: var(--accent); }
  .watch-now.wt-done { color: var(--correct); }
  .wt-ev { display: flex; justify-content: space-between; gap: 10px;
           padding: 8px 10px; border-radius: 10px; background: var(--paper-2);
           margin-bottom: 6px; }
  .wt-ev small { color: var(--ink-soft); white-space: nowrap; }
  .rt-add { width: 100%; margin-bottom: 10px; }
  .pl-find { width: 100%; margin-top: 8px; }
  /* Несколько домов подошли под адрес — кнопками под подсказкой. */
  .pl-found-list { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 6px; }
  .pl-found-list[hidden] { display: none; }
  .pl-found { min-height: 44px; }
  .pl-row-geo { color: var(--ink-soft); font-size: .8rem; }
  .pl-row-geo.no { color: var(--gold); }
  /* Карта грузится только по кнопке: тариф ключа — сто обращений в сутки,
     и открытый «на всякий случай» экран съедал бы их молча. */

  /* Карта во весь экран. Секция обычного экрана — блок в потоке, а карте
     нужен весь экран целиком: карта считает масштаб по размеру кадра. */
  #viewMapAll.on { position: fixed; inset: 0; z-index: 40; background: var(--paper); }
  .map-all { position: absolute; inset: 0; }
  .map-all iframe { display: block; width: 100%; height: 100%; border: 0; }
  .map-bar {
    position: absolute; left: 0; right: 0; top: 0; z-index: 2;
    display: flex; align-items: center; gap: 10px;
    padding: calc(8px + env(safe-area-inset-top)) 12px 10px;
    background: linear-gradient(var(--paper), rgba(0,0,0,0));
    pointer-events: none;
  }
  .map-bar button { pointer-events: auto; }
  .map-tip { font-size: .9rem; color: var(--ink-soft); pointer-events: none;
             text-shadow: 0 1px 2px var(--paper); }
  /* Вопрос «что это?» поверх карты. Внизу, а не по центру: палец родителя
     уже внизу экрана, и тянуться через весь телефон не надо. */
  .map-ask { position: fixed; inset: 0; z-index: 60; display: flex;
             align-items: flex-end; background: rgba(0,0,0,.35); }
  .map-ask-card {
    width: 100%; max-height: 86%; overflow-y: auto;
    background: var(--card); color: var(--ink);
    border-radius: 18px 18px 0 0; padding: 16px 16px calc(16px + env(safe-area-inset-bottom));
    box-shadow: var(--shadow); display: flex; flex-direction: column; gap: 12px;
  }
  .map-ask-card h3 { margin: 0; font-size: 1.15rem; }
  /* Остаток карточек занятий на главной и на итогах (вид доводит GPT). */
  .cards-left { margin: 8px 0 0; font-size: .92rem; color: var(--ink-soft); }
  .cards-left.empty { color: var(--ink); font-weight: 600; }
  /* Подсказка «на экран телефона» в конце дня (28.09). */
  .done-home { margin: 12px 0 0; padding: 12px 14px; border-radius: 14px;
               background: var(--accent-dim); text-align: center; }
  .done-home p { margin: 0 0 10px; font-size: .95rem; line-height: 1.4; }
  .done-home button { min-height: 44px; }

  /* Осенний марафон на экране «Сегодня» (план аудита, п. 19). */
  .marathon { margin: 14px 0 10px; padding: 14px; border-radius: 16px;
              background: var(--accent-dim); }
  .marathon-head { display: flex; flex-wrap: wrap; justify-content: space-between;
                   align-items: baseline; gap: 4px 10px; }
  .marathon-head b { font-family: var(--font-display); font-size: 1.05rem; }
  .marathon-dots { display: flex; gap: 8px; margin: 10px 0 6px; }
  .marathon-dots i { width: 22px; height: 22px; border-radius: 50%;
                     border: 2px solid var(--accent); background: var(--card); }
  .marathon-dots i.on { background: var(--accent); }
  .marathon .hint { margin: 4px 0 0; }
  .marathon button { margin-top: 10px; min-height: 44px; }

  /* Грамота марафона: на экране — карточка, на печати — одна страница. */
  .cert { display: grid; gap: 18px; padding: 16px; max-width: 720px; margin: 0 auto; }
  .cert-editor { display: grid; gap: 8px; min-width: 0; }
  .cert-editor label { font-size: 1rem; font-weight: 700; line-height: 1.4; }
  .cert-editor input { width: 100%; min-width: 0; min-height: 48px; padding: 10px 12px;
    border: 1px solid var(--ink-soft); border-radius: 12px; background: var(--card);
    color: var(--ink); font: inherit; font-size: 1rem; }
  .cert-note { margin: 0; font-size: 1rem; line-height: 1.5; color: var(--ink-soft); }
  .cert-page { text-align: center; padding: 26px 16px; border: 3px double var(--accent);
               border-radius: 18px; background: var(--card); min-width: 0; overflow-wrap: anywhere; }
  .cert-top { margin: 0; color: var(--ink-soft); font-size: 1rem; font-weight: 700; letter-spacing: .03em; }
  /* min(…, 13vw): при тексте ×2 на 320 px «Грамота» в 2.4rem (77 px) была
     шире карточки. */
  .cert-title { margin: 8px 0 4px; font-family: var(--font-display); font-size: 2.4rem; font-size: min(2.4rem, 13vw); }
  .cert-for { margin: 0 0 8px; color: var(--ink-soft); font-size: 1rem; }
  .cert-name { margin: 0; min-height: 1.4em; text-align: center; font-size: 1.35rem;
               line-height: 1.4; font-weight: 700; color: var(--ink); }
  .cert-name.is-empty { border-bottom: 2px solid var(--rule); color: var(--ink-soft); font-size: 1rem; }
  .cert-text { margin: 12px 0 6px; font-size: 1.05rem; line-height: 1.45; }
  .cert-date { margin: 0; color: var(--ink-soft); font-size: 1rem; }
  .cert-actions button { min-height: 48px; max-width: 100%; overflow-wrap: anywhere; }
  @media print {
    @page { size: A4; margin: 15mm; }
    body * { visibility: hidden !important; }
    html, body { height: auto !important; min-height: 0 !important; background: white !important; }
    body > :not(.shell), .shell > :not(#viewCert), #viewCert .cert > :not(#certPage) { display: none !important; }
    .shell { display: block; max-width: none; padding: 0; margin: 0; }
    #viewCert .cert { display: block; padding: 0; margin: 0; max-width: none; border: 0; box-shadow: none; background: white; }
    #certPage, #certPage * { visibility: visible !important; }
    #certPage { position: static; width: 100%; padding: 20mm 12mm; border: 3px double #333; background: white; break-inside: avoid; }
    #certPage * { color: #1B2A4A; }
    #certPage .cert-top, #certPage .cert-for, #certPage .cert-date { font-size: 14pt; }
    #certPage .cert-title { font-size: 36pt; margin: 8mm 0 4mm; }
    #certPage .cert-name { font-size: 28pt; margin: 4mm 0; }
    #certPage .cert-name.is-empty { visibility: hidden !important; }
    #certPage .cert-text { font-size: 18pt; margin: 8mm 0 6mm; }
  }

  /* Единственная видимая ссылка внутри текста приложения — на политику, и
     читают её ровно перед тем, как ввести почту. Без своего отступа цель
     выходит в 19 точек на строку при наших 44. Отрицательное поле
     возвращает абзацу прежнюю высоту: растёт только область нажатия. */
  .hint a { display: inline-block; padding: 11px 0; margin: -11px 0; }
  /* Поле в окне живёт вне карточки настроек и не подхватывает её вид: без
     своего правила оно выходит 21 точку высотой — вдвое тоньше пальца. */
  .map-ask-card input {
    width: 100%; min-height: 48px; padding: 12px 14px; font-size: 1.02rem;
    border-radius: 12px; border: 1px solid var(--rule);
    background: var(--paper-2); color: var(--ink);
  }
  .map-ask-card input:focus { border-color: var(--accent); outline: none; }
  .rt-draw { margin-top: 8px; display: flex; flex-wrap: wrap; gap: 8px;
             align-items: center; }
  .rt-draw .hint { flex-basis: 100%; margin: 0; }
  .pl-map { position: relative; margin-top: 10px; border-radius: 14px; overflow: hidden;
            border: 2px solid var(--rule); background: var(--paper-2); }
  .pl-map iframe { display: block; width: 100%; height: 46vh; min-height: 240px;
                   max-height: 420px; border: 0; }

  /* Карта на весь экран. Владелец 03.09 в поддержку: «нет возможности
     открыть карту поверх». На телефоне карта живёт кусочком в карточке —
     обвести по ней дорогу пальцем можно только с лупой, а именно этим
     взрослый и занимается.
     Коробку не переносим по дереву, а раздвигаем на месте: кадр при
     переносе перезагружается, и вся нарисованная дорога пропадает. */
  /* Отступы под чёлку и домашнюю полосу задаёт коробка, а не сама карта:
     внутри кадра env(safe-area-*) всегда нули — эти отступы знает только
     верхний документ. Владелец 04.09 прислал снимок, где надпись карты
     «Остановок у этой дороги: 3» легла поверх часов и не читалась. */
  .map-full { position: fixed; inset: 0; z-index: 90; margin: 0;
              border-radius: 0; border: 0; background: var(--paper);
              padding-top: env(safe-area-inset-top);
              padding-bottom: env(safe-area-inset-bottom); }
  /* Кадр внутри тоже обязан стать во весь экран, и селектор здесь не
     придирка. У «.way-map.big iframe» два класса, у «.map-full iframe» —
     один, и высоту держало прежнее правило: коробка разворачивалась, а
     карта оставалась полоской посреди серого поля. Владелец 04.09: «карта
     на весь экран не на весь экран раскрывается». Мой прошлый замер этого
     не поймал, потому что мерил коробку, а не кадр. */
  .way-map.map-full iframe,
  .way-map.big.map-full iframe,
  .pl-map.map-full iframe { height: 100%; max-height: none; min-height: 0; }
  /* Кнопка выхода — над кадром и под палец. Без неё из карты не выбраться:
     кнопки приложения остались под ней. */
  .map-full-out { position: absolute; right: 12px; z-index: 5;
                  top: calc(12px + env(safe-area-inset-top));
                  min-height: 44px; min-width: 44px; padding: 0 14px;
                  border: 0; border-radius: 12px; background: var(--card);
                  color: var(--ink); font: 600 15px/44px inherit;
                  box-shadow: 0 2px 10px rgba(0,0,0,.28); }
  /* Пока карта во весь экран, страница под ней не ездит. */
  body.map-open { overflow: hidden; }
  /* «Включить звук» над картой. Показывается только когда облёт в кадре
     прислал слово, а звук в нашем документе заперт (айфон без жеста).
     Слева сверху: справа кнопка «На весь экран», внизу — кнопки самой
     карты. Две строки: что нажать и где ещё посмотреть на айфоне. */
  .map-sound-on { position: absolute; left: 12px; z-index: 6;
                  top: calc(12px + env(safe-area-inset-top));
                  max-width: calc(100% - 150px); min-height: 48px;
                  padding: 6px 14px; border: 0; border-radius: 12px;
                  background: var(--accent); color: var(--on-accent);
                  text-align: left; font: inherit; line-height: 1.25;
                  box-shadow: 0 2px 10px rgba(0,0,0,.28); }
  .map-sound-on b { display: block; font-size: 15px; }
  .map-sound-on small { display: block; font-size: .78rem; opacity: .9; }
  .map-sound-on[hidden] { display: none; }

  /* Полоса «вышло обновление». Внизу, а не вверху: вверху её закрывает
     чёлка, а палец всё равно живёт внизу экрана. */
  #newVer { position: fixed; left: 10px; right: 10px; z-index: 95;
            bottom: calc(10px + env(safe-area-inset-bottom));
            display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
            padding: 10px 12px; border-radius: 14px;
            background: var(--card); color: var(--ink);
            border: 1px solid var(--rule); box-shadow: 0 4px 18px rgba(0,0,0,.25); }
  #newVer[hidden] { display: none; }
  #newVer span { flex: 1 1 140px; font-size: .95rem; }
  #newVer button { min-height: 44px; padding: 0 14px; border-radius: 12px;
                   border: 1px solid var(--rule); background: var(--paper-2);
                   color: var(--ink); font: inherit; }
  #newVerGo { background: var(--accent); border-color: var(--accent); color: #fff; }

  .way-place { min-height: 96px; display: flex; flex-direction: column; align-items: center;
               justify-content: center; gap: 4px; padding: 8px; border-radius: 16px;
               border: 1px solid var(--rule); background: var(--card); color: var(--ink); }
  .way-place b { font-size: 1rem; }
  .way-place small { color: var(--ink-soft); font-size: .78rem; }
  .way-place-ico { font-size: 1.7rem; line-height: 1; }
  .way-steps { display: grid; gap: 8px; margin: 10px 0; }
  .way-step { display: flex; align-items: center; gap: 10px; padding: 10px 12px;
              border-radius: 14px; border: 1px solid var(--rule); background: var(--card); }
  .way-step.now { border-color: var(--accent); background: rgba(103,168,246,.12); }
  .way-step-num { flex: none; width: 30px; height: 30px; border-radius: 50%;
                  display: flex; align-items: center; justify-content: center;
                  background: var(--accent); color: #0d1420; font-weight: 700; }
  .way-go, .way-done { min-height: 72px; font-size: 1.25rem; }
  /* Полоса «родители видят» не прячется, пока идёт передача: ребёнок обязан
     знать, что его ведут. Это не оформление, а честность. */
  .way-watch { margin: 0 0 10px; padding: 10px 12px; border-radius: 14px;
               background: rgba(103,168,246,.16); border: 1px solid var(--accent);
               color: var(--ink); font-size: .92rem; }
  .album-link {
    display: flex; align-items: center; gap: 12px;
    padding: 14px 16px; width: 100%; cursor: pointer;
    color: var(--ink); font: inherit; text-align: left;
    border: 1.5px solid var(--rule);
    transition: border-color .15s;
  }
  .album-link:hover { border-color: var(--accent); }
  .album-ico { font-size: 1.5rem; flex: none; }
  .album-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1; }
  .album-text b { font-family: var(--font-display); font-size: .95rem; }
  .album-text small { font-size: .8rem; color: var(--ink-soft); }
  .album-link .chev { color: var(--ink-faint); font-size: 1.15rem; }
  #viewAlbum h2 { margin: 0; font-size: 1.3rem; line-height: 1.35; text-align: left; }
  .album-stats { display: grid; gap: 8px; }
  .album-stats p { margin: 0; color: var(--ink); font-size: 1rem; line-height: 1.5; text-align: left; }
  #albumCount { font-size: 1.15rem; font-weight: 700; }
  #albumProgress { display: block; width: 100%; height: 14px; accent-color: var(--accent); }
  .album-rule, .album-next { margin: 0; font-size: 1rem; line-height: 1.5; color: var(--ink); text-align: left; }
  .album-next { border: 1px solid var(--rule); border-radius: 12px; padding: 12px; background: var(--paper-2); font-weight: 700; }
  .sticker-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 8rem), 1fr)); gap: 12px; list-style: none; padding: 0; margin: 0; }
  .sticker {
    min-width: 0; display: grid; align-content: start; justify-items: center; gap: 6px; padding: 12px;
    font-size: 1rem; line-height: 1.5; text-align: center; border-radius: var(--r);
    background: var(--paper); border: 1.5px solid var(--rule);
    color: var(--ink); overflow-wrap: anywhere; hyphens: auto;
  }
  .sticker-picture { display: block; font-size: 4rem; line-height: 1.25; }
  .sticker-name, .sticker-state, .sticker-target { font-size: 1rem; line-height: 1.5; }
  .sticker.locked { background: var(--paper-2); border-style: dashed; }
  .sticker.locked .sticker-picture { font-size: 2rem; }
  .sticker.next { border: 2px solid var(--accent); }
  .album-more summary { min-height: 48px; padding: 12px; border: 1px solid var(--rule); border-radius: 12px; font-size: 1rem; line-height: 1.5; color: var(--ink); text-align: left; cursor: pointer; }
  .album-more .sticker-grid { margin-top: 12px; }
  .stars-got {
    margin: 0; font-family: var(--font-display); font-weight: 700;
    color: var(--gold); font-size: .95rem;
  }
  .lvl-note {
    margin: 6px 0 0; font-weight: 700; font-size: .95rem; color: var(--accent);
  }
  /* Список к школе */
  #shopTitle { margin: 0; text-align: left; font-size: 1.3rem; line-height: 1.3; }
  .shop-help, #shopCount { margin: 8px 0; font-size: 1rem; line-height: 1.5; color: var(--ink); text-align: left; }
  #viewShop .read-head { font-size: 1.1rem; text-transform: none; letter-spacing: normal; color: var(--ink); margin: 14px 0 4px; overflow-wrap: anywhere; }
  /* Колонка — ширина экрана, а не самое длинное слово. Заголовок группы
     «ПИСЬМЕННЫЕ ПРИНАДЛЕЖНОСТИ» заглавными с разрядкой при 150–200 % шире
     320 px, и сетка растягивала под него весь список: прокрутка вбок на
     28–88 px, карандаш правки за краем (замер 15.09). */
  .shop-list { display: grid; grid-template-columns: minmax(0, 1fr); gap: 6px; }
  .shop-row {
    display: grid; grid-template-columns: 48px minmax(0, 1fr) 48px; align-items: start; gap: 10px;
    border: 1px solid var(--rule); border-radius: 12px;
    background: var(--paper); padding: 9px 10px 9px 12px;
  }
  .shop-row.done { background: var(--paper-2); }
  .shop-row.done { border-style: dashed; }
  .shop-check {
    flex: none; width: 48px; height: 48px; border-radius: 11px;
    border: 2px solid var(--rule); background: var(--paper);
    font-size: 1.3rem; font-weight: 700; color: var(--on-accent); padding: 0;
  }
  .shop-check[aria-pressed="true"] { background: var(--accent); border-color: var(--accent); }
  /* Длинные названия и заметки переносятся внутри своей колонки. */
  .shop-text { flex: 1; min-width: 0; text-align: left; hyphens: auto; overflow-wrap: break-word; }
  .shop-text b { display: block; font-size: 1.1rem; font-weight: 700; line-height: 1.4; }
  .shop-text small { display: block; color: var(--ink); font-size: 1rem; line-height: 1.5; }
  .shop-text i.shop-note { display: block; font-style: normal; color: var(--ink); font-size: 1rem; line-height: 1.5; margin-top: 6px; }
  .shop-state { display: block; font-size: 1rem; font-weight: 700; line-height: 1.5; color: var(--ink); margin-top: 6px; }
  .shop-pen { flex: none; width: 48px; height: 48px; border-radius: 11px; padding: 0;
              border: 1px solid var(--rule); background: var(--paper); font-size: 1.05rem; }
  /* При нехватке места текст получает всю ширину, две кнопки — отдельную
     строку. Условие учитывает и ширину карточки, и крупный текст. */
  .shop-list { container-type: inline-size; }
  @container (max-width: 22rem) {
    .shop-row { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .shop-check { grid-column: 1; grid-row: 2; }
    .shop-pen { grid-column: 2; grid-row: 2; justify-self: end; }
    .shop-text { grid-column: 1 / -1; grid-row: 1; }
  }
  .shop-edit { display: grid; grid-template-columns: minmax(0, 1fr); gap: 10px; margin: 2px 0 10px; padding: 12px; border: 1px solid var(--rule); border-radius: 12px; }
  #viewShop .shop-edit label { display: grid; gap: 8px; min-width: 0; text-align: left; font-size: 1rem; line-height: 1.5; color: var(--ink); overflow-wrap: anywhere; }
  #viewShop .shop-edit input {
    width: 100%; min-width: 0; box-sizing: border-box; min-height: 48px; padding: 8px 10px; font-size: 1rem;
    border: 1px solid var(--rule); border-radius: 10px;
    background: var(--paper); color: var(--ink);
  }
  .shop-edit-actions { display: flex; flex-wrap: wrap; gap: 8px; }
  .shop-edit-actions button { flex: 1 1 9rem; min-height: 48px; font-size: 1rem; }
  .shop-foot { text-align: left; line-height: 1.45; }
  .shop-ico { position: relative; }
  /* значок держим внутри кнопки: на айфоне с чёлкой шапка уходит под статус-бар */
  .shop-ico b {
    position: absolute; top: -5px; right: -5px; min-width: 20px; height: 20px;
    border: 2px solid var(--paper); border-radius: 10px;
    background: var(--accent); color: var(--on-accent);
    font-size: .64rem; font-weight: 700; line-height: 16px; text-align: center;
    padding: 0 3px; box-sizing: border-box;
  }
  .shop-norms-btn { width: 100%; text-align: left; }
  .shop-norms { text-align: left; }
  .shop-norms b { display: block; font-size: .95rem; margin: 10px 0 4px; color: var(--accent); }
  .shop-norms p {
    margin: 0 0 5px; padding-left: 16px; position: relative;
    font-size: .88rem; line-height: 1.45; color: var(--ink-soft);
  }
  .shop-norms p:before { content: "•"; position: absolute; left: 4px; color: var(--accent); }
  @supports not (inset: 0) {
    .shop-list > * + * { margin-top: 6px; }
    .shop-row > * + * { margin-left: 10px; }
    .shop-edit > * + * { margin-left: 8px; }
  }

  .lvl-list { display: grid; gap: 8px; }
  .lvl-group { border:1px solid var(--rule); border-radius:16px; background:var(--paper); overflow:hidden; }
  .lvl-group summary { display:flex; align-items:center; gap:12px; min-height:76px; padding:12px; cursor:pointer; list-style:none; }
  .lvl-group summary::-webkit-details-marker { display:none; }
  .lvl-group summary::after { content:'+'; margin-left:auto; font-size:1.4rem; color:var(--accent); }
  .lvl-group[open] summary::after { content:'−'; }
  .lvl-group summary .illustrated-icon { flex:none; width:42px; height:42px; }
  .lvl-group summary .illustrated-icon svg { width:38px; height:38px; }
  .lvl-group-title { display:grid; gap:4px; min-width:0; overflow-wrap:anywhere; }
  .lvl-group-title small { font-size:.8rem; color:var(--ink-soft); }
  .lvl-group-list { display:grid; gap:8px; padding:0 10px 12px; }
  .lvl-group .lvl-row { flex-wrap:wrap; padding:10px; }
  .lvl-group .lvl-row > b { flex:1 1 135px; min-width:0; overflow-wrap:anywhere; }
  .lvl-group .lvl-row .chips { flex-wrap:nowrap; }
  .lvl-row {
    display: flex; align-items: center; gap: 10px;
    border: 1px solid var(--rule); border-radius: 12px;
    background: var(--paper); padding: 8px 10px 8px 14px;
  }
  .lvl-row > b { font-size: .95rem; font-weight: 700; }
  .lvl-row .chips { margin-left: auto; gap: 6px; }
  /* 44 — минимальная цель для пальца; ступеней много, промахиваться нельзя */
  .lvl-row .chip { min-height: 44px; min-width: 44px; padding: 6px 12px; font-size: .9rem; }
  @supports not (inset: 0) {
    .lvl-list > * + * { margin-top: 8px; }
    .lvl-row > * + * { margin-left: 10px; }
  }
  @supports not (inset: 0) {
    .album-link > * + * { margin-left: 12px; }
    .album-text > * + * { margin-top: 2px; }
  }

  /* Числовая прямая и задачки */
  /* Картинка вместо примера: она и есть всё задание, поэтому во всю доску */
  .equation.bigpic { font-size: 4.6rem; line-height: 1.1; }
  /* Длинная запись из нескольких действий (порядок действий): мельче обычного
     примера, чтобы «= ?» оставалось в той же строке. */
  .equation.wide { font-size: 2rem; font-size: clamp(1.7rem, 7.6vw, 3rem); gap: .22em; }
  .equation.small {
    font-size: 1.15rem; line-height: 1.5; font-weight: 600;
    letter-spacing: 0; font-family: var(--font-body);
    max-width: 30em;
  }
  /* Длинные вопросы-предложения: мельче, чтобы влезали целиком */
  .equation.small.long { font-size: 1.02rem; line-height: 1.45; max-width: 26em; }
  .equation.small.longer { font-size: .92rem; line-height: 1.4; max-width: 24em; }
  /* Задание плашкой над словом, слово — крупно по центру своей строкой
     (обращения 127, 129, 132 от 22.09). */
  .equation.with-task { flex-direction: column; gap: .55rem; }
  .equation .task-cap {
    max-width: 100%; text-align: center;
    font-family: var(--font-body); font-size: 1rem; font-weight: 700;
    line-height: 1.35; letter-spacing: 0; color: var(--ink);
    background: var(--accent-dim); border-radius: 14px; padding: .35em .9em;
  }
  .equation.small .task-cap { font-size: .92rem; }
  .equation .task-item {
    display: flex; align-items: center; justify-content: center;
    flex-wrap: wrap; gap: .3em; max-width: 100%;
  }
  #lineBox { width: 100%; max-width: 440px; }
  #lineBox svg { width: 100%; height: auto; display: block; }
  /* Японские линии: квадратная фигура, ограничиваем, чтобы не съедала доску */
  #lineBox svg.jplines { max-width: 300px; margin: 0 auto; }
  #lineBox svg.clockface { max-width: 190px; margin: 0 auto; }
  /* Координатная плоскость (11.10): квадрат, не шире 300 точек. */
  /* Сетка начинается ниже кнопки «прослушать»: точка в правом верхнем углу
     (5; 5) иначе пряталась под ней (снимок 320 при ×2, 11.10). */
  #lineBox svg.coordplane { max-width: 300px; margin: 14px auto 0; }
  /* Фигуру держим в разумном размере: на доске она одна, но во весь экран
     смотреть на квадрат незачем — варианты ответа уедут вниз. */
  #lineBox svg.shape-art { max-width: 168px; margin: 0 auto; }
  #lineBox svg.angle-art { max-width: 190px; margin: 0 auto; }
  #lineBox svg.digitalface { max-width: 220px; margin: 0 auto; }
  .numline text, .clockface text { font-family: var(--font-body); }
  .choice.word {
    font-size: 1.05rem; font-size: min(1.05rem, 5.5vw);
    font-family: var(--font-body); font-weight: 700;
    overflow-wrap: break-word; hyphens: auto; -webkit-hyphens: auto;
  }
  /* Схема слова: варианты — цветные квадраты, а не слова. Им нужен
     крупный кегль, иначе ребёнок не различит синий и зелёный. */
  /* Квадраты схемы — картинка, а не текст: перенос на вторую строку
     ломает саму схему, поэтому строка неразрывна, а кегль ограничен
     шириной экрана — при «Крупном тексте» они остаются в кнопке. */
  /* Точность селектора: .choices.rows .choice задаёт свой кегль и иначе
     перебивает этот — квадраты становятся мелкими, как у длинных фраз. */
  .choice.squares, .choices.rows .choice.squares {
    font-size: 2.4rem; font-size: min(2.4rem, 9vw);
    letter-spacing: .1em; line-height: 1.15; white-space: nowrap;
  }

  /* Обводка и раскраска */
  .fun-wrap { padding: 22px 16px; max-width: 460px; margin: 0 auto; }
  /* Доска начинается сразу под шапкой: на компьютере пустая полоса сверху
     уводила её за край экрана (владелец 20.09: «подними выше»). */
  #viewChess .fun-wrap, #viewCheckers .fun-wrap, #viewBackgammon .fun-wrap { padding-top: 6px; }
  #viewChess .fun-card, #viewCheckers .fun-card, #viewBackgammon .fun-card { padding-top: 10px; }
  /* Пояснение под доской меняется на каждом ходу, и вместе с ним менялась
     высота страницы: доска на глазах подпрыгивала на два десятка точек.
     Держим место под две строки — тогда строка меняется, а страница стоит. */
  .board-hint { margin-top: 8px; line-height: 1.4; min-height: 3em; }
  /* Запас внизу: без него страница упирается в край, и любое изменение высоты
     на пару точек сдвигает её вместе с доской. */
  #viewChess .fun-wrap, #viewCheckers .fun-wrap, #viewBackgammon .fun-wrap { padding-bottom: 28px; }
  /* Игровые экраны: поле во весь экран, без карточки и лишних отступов */
  /* Шапку у игр во весь экран больше не прячем: без неё не было стрелки
     «назад» и названия (обращение 126 от 21.09, «Змейка»: «нет назад»).
     Выбор режима живёт в ней же, поэтому поле почти не потеряло места. */
  body.game-full .top { margin-bottom: 4px; padding-bottom: 6px; }
  body.game-full { overflow: hidden; }
  /* На низком экране (320×568, старые iPhone SE) поле, пульт и кнопки не
     помещаются, и «Старт» уходил под край без прокрутки — игру было не
     начать. Там прокрутку возвращаем: поле свайпы не прокручивают, у него
     touch-action: none. */
  @media (max-height: 620px) { body.game-full { overflow: auto; } }
  body.game-full .fun-wrap { padding: 6px 6px 8px; max-width: none; }
  body.game-full .fun-card {
    padding: 6px; gap: 6px; border: none; border-radius: 0;
    background: transparent; box-shadow: none;
  }
  body.game-full .fun-card h2 { font-size: .95rem; }
  body.game-full .fun-card .hint { margin: 0; font-size: .78rem; }
  #viewSnake .pads, #viewRace .pads, #viewTank .pads { max-width: 100%; }
  #snakeCv, #raceCv, #tankCv { touch-action: none; }
  #raceCv { cursor: ew-resize; }
  #raceCv:focus-visible { outline-offset: 3px; }
  #raceMode { justify-content: center; gap: 6px; }
  #raceMode .chip { min-height: 44px; padding: 8px; font-size: .82rem; }
  #snakeMode, #tankLevels { justify-content: center; gap: 6px; }
  #snakeMode .chip, #tankLevels .chip { min-height: 44px; padding: 8px; font-size: .82rem; }
  #tankLevels .chip { min-width: 44px; }
  .fun-card { padding: 16px; display: flex; flex-direction: column; gap: 12px; align-items: center; }
  .fun-card h2 { margin: 0; font-family: var(--font-display); font-size: 1.05rem; }
  #traceCv {
    touch-action: none; border: 1.5px dashed var(--rule);
    border-radius: var(--r); background: var(--paper);
  }
  /* Поле не шире карточки: на 320 холст в 280 точек вылезал за её края (при
     крупном тексте — на 25 точек с каждой стороны). Высоту задаёт пропорция
     холста; tracePos пересчитывает перо от настоящего размера (29.09). */
  #traceCv { max-width: 100%; height: auto !important; }
  /* Итог обводки (29.09): звёзды и слова крупно, а не серой строкой внизу. */
  .trace-result { width: 100%; max-width: 360px; display: grid; gap: 6px; justify-items: center; text-align: center;
    padding: 10px 14px; border-radius: 14px; background: var(--gold-dim); border: 1px solid var(--gold); }
  .trace-result[hidden] { display: none; }
  .trace-stars { font-size: 2.2rem; line-height: 1; letter-spacing: .12em; color: var(--gold); }
  .trace-result p { margin: 0; font-size: 1rem; font-weight: 700; line-height: 1.4; color: var(--ink); }
  .trace-result .trace-next { font-weight: 400; font-size: .92rem; }
  #traceChoices .chip[data-stars]::after { content: attr(data-stars); display: block; font-size: .62rem; line-height: 1; color: var(--gold); }
  /* Змейка */
  #snakeCv {
    touch-action: none; border-radius: var(--r);
    border: 1.5px solid var(--rule); background: var(--paper);
  }
  .snake-pad { display: flex; flex-direction: column; align-items: center; gap: 8px; }
  .snake-row { display: flex; gap: 8px; }
  .snake-key {
    width: 62px; height: 52px; border-radius: 14px; border: 1px solid var(--rule);
    background: var(--card); font-size: 1.1rem; color: var(--ink);
    box-shadow: var(--shadow-key);
  }
  .snake-key:active { background: var(--accent-dim); }

  /* Управление играми: движение под левый палец, огонь — под правый */
  .pads {
    display: flex; align-items: center; justify-content: space-between;
    width: 100%; max-width: 340px; gap: 12px; margin-top: 4px;
  }
  .pads-center { justify-content: center; }
  .pads-right { justify-content: flex-end; }

  .dpad {
    position: relative; width: 156px; height: 156px; flex: none;
    touch-action: none;
  }
  .dkey, .dkey-mid {
    position: absolute; width: 52px; height: 52px; border-radius: 14px;
    border: 1px solid var(--rule); background: var(--card); color: var(--ink);
    font-size: 1.05rem; display: flex; align-items: center; justify-content: center;
    box-shadow: var(--shadow-key);
  }
  .dkey-mid { border: none; background: transparent; box-shadow: none; }  /* мёртвая зона */
  .dkey.up    { left: 52px; top: 0; }
  .dkey.left  { left: 0; top: 52px; }
  .dkey-mid   { left: 52px; top: 52px; }
  .dkey.right { left: 104px; top: 52px; }
  .dkey.down  { left: 52px; top: 104px; }
  .dkey:active, .dkey.on { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
  .fire-btn {
    flex: none; width: 96px; height: 96px; border-radius: 50%;
    border: 1px solid var(--wrong); background: var(--wrong-dim); color: var(--wrong);
    font-family: var(--font-display); font-weight: 700; font-size: .95rem;
    box-shadow: var(--shadow-key); touch-action: none;
  }
  .fire-btn:active { background: var(--wrong); color: #fff; }
  /* Узкая площадка только «влево-вправо» — для гонок */
  .dpad.dpad-lr { width: 168px; height: 60px; }
  .dpad.dpad-lr .dkey.left { left: 0; top: 4px; }
  .dpad.dpad-lr .dkey-mid { left: 58px; top: 4px; }
  .dpad.dpad-lr .dkey.right { left: 116px; top: 4px; }
  @media (max-width: 360px) {
    .dpad { width: 138px; height: 138px; }
    .dkey, .dkey-mid { width: 46px; height: 46px; }
    .dkey.up { left: 46px; } .dkey.left { top: 46px; }
    .dkey-mid { left: 46px; top: 46px; }
    .dkey.right { left: 92px; top: 46px; } .dkey.down { left: 46px; top: 92px; }
    .fire-btn { width: 84px; height: 84px; }
    .dpad.dpad-lr { width: 150px; height: 54px; }
    .dpad.dpad-lr .dkey.left { left: 0; top: 4px; }
    .dpad.dpad-lr .dkey-mid { left: 52px; top: 4px; }
    .dpad.dpad-lr .dkey.right { left: 104px; top: 4px; }
  }
  @supports not (inset: 0) {
    .snake-pad > * + * { margin-top: 8px; }
    .snake-row > * + * { margin-left: 8px; }
  }

  .paint-head { display: flex; align-items: center; gap: 12px; justify-content: center; width: 100%; }
  #paintBox { width: 100%; }
  .paint-svg { width: 100%; height: auto; display: block; }
  /* Экран раскраски целиком помещается в окно: рисунок отдаёт высоту,
     но краски и кнопки остаются на виду. Иначе на невысоком экране (735 точек
     у ноутбука, айфон в альбомной) палитра уезжала за нижний край. */
  /* Карточка растёт по содержимому: внутренняя прокрутка резала кнопки и
     прятала образец. Если окно слишком низкое, прокручивается страница. */
  #paintNote { line-height: 1.35; }
  #paintBox { display: flex; align-items: center; justify-content: center; }
  /* Рисунок отдаёт высоту, чтобы краски и кнопки остались на виду. Проценты
     от окна, а не растяжение флексом: у svg без заданной высоты флекс даёт
     ноль, и картинка исчезает совсем. */
  #paintBox .paint-svg { width: 100%; height: auto; max-height: 38vh; }
  /* Телефон: поля потоньше, чтобы краски помещались без прокрутки */
  @media (max-width: 480px) {
    #viewPaint .fun-card { padding: 12px; gap: 8px; }
    #viewPaint .fun-wrap { padding: 10px 12px; }
    #paintNote { font-size: .78rem; }
    /* Три уровня сложности переносились на вторую строку и съедали 50 точек —
       на телефоне чипы компактнее, ряд снова один */
    #viewPaint .chips .chip { padding: 10px 8px; font-size: .8rem; }
  }
  /* Невысокое окно (ноутбук, телефон лёжа): рисунок уступает ещё немного,
     чтобы «Очистить» и «Назад» не убегали за нижний край. */
  @media (max-height: 780px) {
    #paintBox .paint-svg { max-height: 30vh; }
  }
  /* iPhone SE и подобные: рисунок ещё меньше, зато краски видно без прокрутки */
  @media (max-height: 700px) {
    #paintBox .paint-svg { max-height: 25vh; }
  }
  .paint-svg path, .paint-svg circle, .paint-svg ellipse { cursor: pointer; }
  .spot-svg [role="button"]:focus-visible,
  .paint-svg [role="button"]:focus-visible {
    outline: none;
    stroke: var(--accent);
    stroke-width: 5;
  }
  /* Отличия ищут глазами, поэтому этому экрану даём больше места, чем
     остальным играм: на узкой карточке кошка выходит с ноготок */
  #viewSpot .fun-wrap { max-width: 760px; }
  /* На компьютере и планшете места больше: на 10 отличиях есть мелочь
     (звёздочка на двери машины), и картинка в 340 точек её прятала (14.10). */
  @media (min-width: 1000px) { #viewSpot .fun-wrap { max-width: 1120px; } }
  /* Раскраска тоже про глаза: узкая карточка делала и образец, и рабочую
     картинку мелкими, хотя места на экране полно */
  #viewPaint .fun-wrap { max-width: 620px; }
  /* Найди отличия: на телефоне картинки одна под другой, на широком — рядом */
  /* flex-wrap: длинное название сцены («Воздушный шарик», «Мороженое») при
     тексте ×2 на 320 px не помещалось рядом со счётом — страница уезжала
     вбок на 23 px (обход всех занятий, 28.09). Счёт переносится строкой ниже. */
  .spot-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; width: 100%; gap: 10px; }
  .spot-score {
    font-family: var(--font-display); font-weight: 800; color: var(--accent);
    font-size: 1.05rem; white-space: nowrap;
  }
  .spot-pair { display: flex; flex-direction: column; gap: 8px; width: 100%; }
  .spot-one {
    border: 2px solid var(--rule); border-radius: 14px; overflow: hidden;
    background: var(--paper); display: flex; justify-content: center; position: relative;
  }
  /* Номер картинки — маленький и сквозной для касаний: 14.10 метка «1» была
     крупной, закрывала солнце и облако в углу сцены и забирала касание —
     облако под ней было не найти. Сбоку её не поставить: на 320 точках
     картинка сжималась с 226 до 186. Угол под меткой сцены держат пустым;
     кегль в точках: при тексте ×2 метка росла вдвое и снова лезла на сцену. */
  .spot-one::before { content: attr(data-label); position: absolute; z-index: 1; top: 4px; left: 4px; min-width: 16px; padding: 1px 4px; border-radius: 999px; background: var(--paper-2); color: var(--ink-soft); font-weight: 800; font-size: 11px; line-height: 14px; text-align: center; opacity: .85; pointer-events: none; }
  /* Обе картинки должны быть видны разом: отличия ищут, сравнивая, а не
     листая туда-сюда. Поэтому каждая занимает не больше трети высоты экрана. */
  .spot-svg {
    width: 100%; height: auto; max-height: 29vh; display: block;
    /* Здесь ничего не рисуют, только тыкают, поэтому прокрутку пальцем по
       картинке оставляем — иначе страницу не пролистать вовсе. */
    touch-action: pan-y;
  }
  /* Предмет сцены — группа фигур со своими контурами: обводка на группе их не
     перекрасит, поэтому фокус показываем свечением вокруг предмета. */
  .spot-svg g[role="button"]:focus-visible { outline: none; filter: drop-shadow(0 0 2px var(--accent)) drop-shadow(0 0 3px var(--accent)); }
  .spot-svg g[role="button"] { cursor: pointer; }
  .spot-svg .mark { fill: none; stroke: var(--correct); stroke-width: 4; }
  .spot-svg .miss { fill: none; stroke: var(--wrong, #E53935); stroke-width: 3; opacity: .8; }
  /* Подсказка обводит место бледно: показать, но не решить за ребёнка */
  .spot-svg .tip { fill: none; stroke: var(--gold); stroke-width: 3; opacity: .75; }
  /* Парные карточки: размер кнопки не меняется при открытии, поэтому поле не
     прыгает и ребёнок тренирует память, а не ловит уехавшие клетки. */
  .memory-grid {
    display: grid; grid-template-columns: repeat(4, minmax(0, 92px));
    gap: 10px; justify-content: center; width: 100%; margin: 12px auto;
  }
  .memory-grid.easy { grid-template-columns: repeat(3, minmax(0, 100px)); } .memory-grid.wide { grid-template-columns: repeat(6, minmax(0, 74px)); gap: 8px; }
  .memory-card {
    --memory-card-height: clamp(58px, 11vw, 92px);
    height: var(--memory-card-height); border: 2px solid var(--rule); border-radius: 16px;
    background: var(--accent-dim); color: var(--ink); font-size: 2rem; line-height: 1; padding: 0;
    display: grid; grid-template: 1fr / 1fr; place-items: center; cursor: pointer; user-select: none;
    transition: background .16s ease;
    container-type: inline-size;
  }
  /* Emoji can have a wider advance than their font size. Fit the actual
     picture/letter to the card, including narrow classic-scrollbar views. */
  .memory-card::before, .memory-face { font-size: min(1em, 70cqi, calc(var(--memory-card-height) - 8px)); }
  .memory-card::before { content: "?"; grid-area: 1 / 1; color: var(--accent); font-weight: 800; }
  .memory-face { grid-area: 1 / 1; visibility: hidden; }
  .memory-card.open .memory-face, .memory-card.done .memory-face { visibility: visible; }
  .memory-card.open, .memory-card.done { background: var(--paper); color: var(--ink); }
  .memory-card.open::before, .memory-card.done::before { content: none; }
  .memory-card.done { border-color: var(--correct); background: var(--accent-dim); }
  .memory-card.word { font-size: clamp(1.2rem, 5vw, 2rem); font-weight: 900; }
  .memory-card.preview { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-dim); }
  .memory-card:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; } @media (max-width: 560px) { .memory-grid.wide { grid-template-columns: repeat(4, minmax(0, 78px)); } }
  .puzzle-stage { display: flex; gap: 14px; align-items: flex-start; justify-content: center; width: 100%; }
  .puzzle-grid { display: grid; gap: 4px; width: min(72vw, 430px); }
  .puzzle-piece { padding: 0; border: 2px solid var(--rule); border-radius: 8px; background: var(--paper); overflow: hidden; }
  .puzzle-piece svg { display: block; width: 100%; height: 100%; }
  .puzzle-piece.sel { outline: 4px solid var(--accent); outline-offset: 1px; }
  .puzzle-preview { width: 104px; flex: 0 0 104px; text-align: center; color: var(--ink-soft); font-size: .78rem; }
  .puzzle-preview svg { width: 100%; border: 2px solid var(--rule); border-radius: 10px; background: var(--paper); }
  .puzzle-pictures { justify-content: center; gap: 6px; }
  .puzzle-pictures .chip { padding: 7px 9px; min-width: 44px; font-size: 1.2rem; }
  .checker-board {
    display: grid; grid-template-columns: repeat(8, 1fr); width: 100%; max-width: 430px;
    border: 4px solid #704b32; border-radius: 12px; overflow: hidden;
    box-shadow: var(--shadow); background: #704b32;
  }
  .checker-cell {
    position: relative; display: grid; place-items: center; padding: 0; border: 0;
    border-radius: 0; min-width: 0; color: inherit;
  }
  .checker-cell.light { background: #f3d8aa; }
  .checker-cell.dark { background: #a86f45; }
  .checker-cell.can-select::before, .checker-cell.target::before {
    content: ""; position: absolute; inset: 9%; border-radius: 50%; pointer-events: none;
  }
  .checker-cell.can-select::before { border: 3px solid color-mix(in srgb, var(--accent) 72%, white); }
  .checker-cell.target::before { background: color-mix(in srgb, var(--correct) 55%, transparent); }
  .checker-cell.selected { box-shadow: inset 0 0 0 4px var(--accent); }
  .checker-man {
    position: relative; z-index: 1; width: 72%; height: 72%; border-radius: 50%;
    border: 3px solid rgba(0,0,0,.28); box-shadow: inset 0 4px 0 rgba(255,255,255,.35), 0 3px 5px rgba(0,0,0,.28);
  }
  .checker-man.white { background: #fffaf0; }
  .checker-man.black { background: #343545; }
  .checker-man.king::after {
    content: "★"; position: absolute; inset: 0; display: grid; place-items: center;
    color: #e9b83f; font-size: clamp(.8rem, 5vw, 1.55rem); text-shadow: 0 1px 1px rgba(0,0,0,.3);
  }
  .checker-meta { width: 100%; max-width: 430px; display: flex; justify-content: space-between; gap: 10px; color: var(--ink-soft); font-size: .86rem; }
  .chess-board {
    display: grid; grid-template-columns: repeat(8, 1fr); width: 100%; max-width: 460px;
    border: 4px solid #65472f; border-radius: 12px; overflow: hidden;
    box-shadow: var(--shadow); background: #65472f;
  }
  .chess-cell {
    position: relative; display: grid; place-items: center; padding: 0; border: 0;
    border-radius: 0; min-width: 0; font-size: clamp(1.7rem, 8vw, 3.05rem);
    line-height: 1; font-family: "Segoe UI Symbol", "Arial Unicode MS", serif;
  }
  .chess-cell.light { background: #eed6aa; }
  /* Низкий телефон (03.10, ролик рекламы на 360×640): задание урока — сразу под
     доской, а свёрнутое «Знакомство с доской» — под заданием. Над доской место
     нужнее: доску ужимает шахматыВЭкран(), чтобы задание было видно целиком. */
  @media (max-width: 600px) and (max-height: 800px) {
    #viewChess .fun-card > * { order: 3; }
    #viewChess #chessTitle, #viewChess .fun-card > .board-meta { order: 0; }
    #viewChess .fun-card > .board-stage { order: 1; }
    #viewChess .fun-card > .board-hint-row { order: 2; }
    #viewChess .fun-card > .board-primer { order: 4; }
  }
  .chess-cell.dark { background: #9b704c; }
  .chess-piece.white { color: #fffdf5; text-shadow: 0 1px 2px #322, 0 0 1px #322; }
  .chess-piece.black { color: #252938; text-shadow: 0 1px 1px rgba(255,255,255,.35); }
  .chess-cell.can-select::before, .chess-cell.target::before {
    content: ""; position: absolute; inset: 10%; border-radius: 50%; pointer-events: none;
  }
  .chess-cell.can-select::before { border: 3px solid color-mix(in srgb, var(--accent) 72%, white); }
  .chess-cell.target::before { background: color-mix(in srgb, var(--correct) 55%, transparent); }
  .chess-cell.selected { box-shadow: inset 0 0 0 4px var(--accent); }
  .chess-piece { position: relative; z-index: 1; pointer-events: none; }
  /* Съеденная фигура. В разметке её уже нет, поэтому на миг показываем копию
     на её клетке: она тает и чуть уменьшается — ребёнок видит, кого сняли. */
  /* Настройки доски одной строкой: выбранное видно, остальное раскрывается
     по нажатию. Два ряда кнопок съедали верх экрана, и доска уезжала вниз. */
  .board-setup-toggle {
    display: flex; align-items: center; gap: 6px; align-self: center;
    min-height: 44px; padding: 8px 14px; border-radius: 999px;
    border: 1px solid var(--rule); background: var(--paper-2); color: var(--ink-soft);
    font: inherit; font-size: .9rem; cursor: pointer;
  }
  .board-setup-toggle b { color: var(--ink); }
  .board-setup-toggle::after { content: "▾"; color: var(--ink-faint); }
  .board-setup-toggle[aria-expanded="true"]::after { content: "▴"; }
  .board-setup { display: grid; gap: 8px; justify-items: center; width: 100%; }

  /* «Как играем» в шапке, справа от названия доски (владелец 21.09:
     «переноси за линию»), а выбор — окном поверх доски, а не раскрытием:
     доска больше не уезжает вниз, пока выбираешь. */
  .top-tools { display: flex; align-items: center; flex: 0 1 auto; min-width: 0; position: relative; }
  .top-tools:empty { display: none; }
  /* Одна строка: на 320 кнопка ужимается многоточием, а не уезжает вниз
     второй строкой — ради этой строки её в шапку и переносили. */
  .top:has(.top-tools:not(:empty)) { flex-wrap: nowrap; }
  .top:has(.top-tools:not(:empty)) .brand { flex-shrink: 0; }
  .top-tools .board-setup-wrap { position: relative; min-width: 0; max-width: 100%; }
  .top-tools .board-setup-toggle { max-width: 100%; min-width: 0; padding: 6px 12px; font-size: .86rem; }
  .top-tools .board-setup-toggle b { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .top-tools .board-setup {
    position: absolute; top: calc(100% + 8px); right: 0; z-index: 60;
    width: max-content; max-width: calc(100vw - 32px);
    padding: 14px; border-radius: 18px; background: var(--card);
    border: 1px solid var(--rule); box-shadow: 0 14px 36px rgba(27,42,74,.22);
  }
  @media (max-width: 559px) {
    .top-tools .setup-label { display: none; }
  }

  /* Строка сообщения под доской и кнопка «прочитать вслух» рядом. */
  .board-hint-row { display: flex; align-items: flex-start; justify-content: center; gap: 8px;
                    width: 100%; max-width: 460px; }
  .board-hint-row .board-hint { flex: 1 1 auto; min-width: 0; }
  .board-say {
    flex: none; width: 44px; height: 44px; margin-top: 4px; padding: 0; border-radius: 50%;
    display: grid; place-items: center; cursor: pointer;
    border: 1px solid var(--rule); background: var(--paper-2); color: var(--ink-soft);
  }
  .board-say:hover { color: var(--accent); border-color: var(--accent); }
  .board-howto { font: 800 1.15rem/1 var(--font-display); }
  .board-howto[aria-pressed="true"] { background: var(--accent); border-color: var(--accent); color: #fff; }

  /* Буквы и цифры снаружи доски: цифры в полоске слева, буквы — снизу.
     Внутри клеток они сливались с фигурами (владелец 22.09). Полоски в той же
     сетке, что и доска, поэтому каждая подпись стоит ровно напротив своей
     клетки; 4 px — рамка доски. */
  .board-frame {
    display: grid; grid-template-columns: 1rem minmax(0, 1fr); grid-template-rows: auto 1.15rem;
    column-gap: 3px; width: 100%; max-width: 479px; margin: 0 auto;
  }
  .board-frame > .chess-board, .board-frame > .checker-board { width: 100%; max-width: none; }
  .board-ranks { display: grid; grid-template-rows: repeat(8, 1fr); padding: 4px 0; }
  .board-files { grid-column: 2; display: grid; grid-template-columns: repeat(8, 1fr); padding: 0 4px; }
  .board-ranks i, .board-files i {
    display: grid; place-items: center; font: 800 .8rem/1 var(--font-body); font-style: normal;
    color: var(--ink-soft);
  }
  .board-ranks i.coord-hot, .board-files i.coord-hot {
    color: #fff; background: var(--accent); border-radius: 6px; font-size: .92rem;
  }
  .chess-cell.coord-example, .checker-cell.coord-example {
    box-shadow: inset 0 0 0 4px var(--accent), inset 0 0 0 8px rgba(255,255,255,.55);
    animation: coord-example 1.1s ease-in-out 3;
  }
  @keyframes coord-example { 50% { box-shadow: inset 0 0 0 7px var(--accent), inset 0 0 0 11px rgba(255,255,255,.55); } }
  @media (prefers-reduced-motion: reduce) { .chess-cell.coord-example, .checker-cell.coord-example { animation: none; } }

  /* Разбор урока: какой ход, почему он верный и к чему привёл. Урок не
     уходит сам — ребёнок читает (или слушает) и жмёт «Следующий урок». */
  /* Ответы на вопрос урока — пальцевые кнопки под доской (курс с азов). */
  .chess-quiz { justify-content: center; gap: 10px; }
  .chess-quiz .chess-answer { min-height: 52px; padding: 0 18px; font-size: 1.05rem; font-weight: 700; }

  .board-debrief {
    width: 100%; max-width: 460px; margin-top: 10px; padding: 14px 16px; box-sizing: border-box;
    display: grid; gap: 7px; text-align: left; border-radius: 16px;
    background: var(--card); border: 1.5px solid var(--accent);
  }
  .board-debrief-head { font-family: var(--font-display); font-size: 1.15rem; color: var(--accent); }
  /* Размер от корня: при «Вдвое» разбор растёт вместе с остальным текстом. */
  .board-debrief p { margin: 0; font-size: .95rem; line-height: 1.45; color: var(--ink-soft); }
  .board-debrief p > span:first-child { font-weight: 700; color: var(--ink); }
  .board-debrief-actions { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; margin-top: 6px; }
  .board-debrief-actions button { display: inline-flex; align-items: center; justify-content: center; gap: 6px; min-height: 44px; }
  .board-debrief-actions .app-icon { width: 20px; height: 20px; }
  #viewBackgammon .board-hint-row, #viewBackgammon .board-debrief { max-width: 680px; }

  /* Копия фигуры, которая едет за пальцем. */
  .board-drag {
    position: fixed; z-index: 70; pointer-events: none;
    display: grid; place-items: center; opacity: .92;
    filter: drop-shadow(0 6px 10px rgba(0,0,0,.35));
  }

  /* «Где больше?»: два ряда на одной сетке, клетка к клетке, чтобы пары
     было видно глазом. Ряд длиной до девяти предметов помещается и на 320. */
  .cmp-rows { display: grid; gap: 10px; justify-content: center; padding: 4px 0 8px; }
  .cmp-row {
    display: grid; grid-auto-flow: column; justify-content: start;
    grid-auto-columns: min(2.6rem, 9vw); font-size: min(2rem, 7vw); line-height: 1.15;
  }
  .cmp-row span { text-align: center; }

  .board-ghost {
    position: fixed; z-index: 60; pointer-events: none;
    display: grid; place-items: center;
    animation: board-ghost-out .34s ease-out both;   /* both: до начала стоит целой */
  }
  .board-ghost > * { width: 74%; height: 74%; }
  @keyframes board-ghost-out {
    from { opacity: 1; transform: scale(1); }
    to { opacity: 0; transform: scale(.55); }
  }
  @media (prefers-reduced-motion: reduce) { .board-ghost { display: none; } }

  .board-meta { width: 100%; max-width: 460px; display: flex; justify-content: space-between; gap: 10px; color: var(--ink-soft); font-size: .86rem; }
  #viewBackgammon .fun-wrap { max-width: 740px; }
  #viewBackgammon .board-meta { width: 100%; max-width: 680px; }
  .backgammon-board {
    /* Размер от карточки, не от viewport: 12 фиксированных минимумов
       распирали сетку и прятали крайние пункты на узком телефоне. */
    display: grid; grid-template-columns: repeat(12, minmax(0, 1fr));
    gap: 3px; width: 100%; max-width: 680px; min-width: 0; padding: 8px;
    border: 4px solid #65472f; border-radius: 14px; background: #c89b67;
    box-shadow: var(--shadow);
  }
  .bg-point {
    position: relative; isolation: isolate; min-width: 0; min-height: 102px; padding: 18px 2px 5px; border: 0; border-radius: 6px;
    display: flex; flex-direction: column; align-items: center; justify-content: flex-start;
    font-size: clamp(.75rem, 2.5vw, 1rem); font-weight: 800; line-height: 1.08;
    color: #222; background: transparent;
  }
  .bg-point::before {
    content: ""; position: absolute; z-index: -1; inset: 0 2px 5px;
    clip-path: polygon(0 0, 100% 0, 50% 100%); background: #f0d5a4;
    filter: drop-shadow(0 1px 0 rgba(72,45,24,.35)); pointer-events: none;
  }
  .bg-point.dark::before { background: #9f523b; }
  .bg-point.bottom::before { inset: 5px 2px 0; clip-path: polygon(50% 0, 100% 100%, 0 100%); }
  .bg-point.bottom { justify-content: flex-end; }
  .bg-point.bottom { padding: 5px 2px 18px; }
  .bg-point-number {
    position: absolute; top: 3px; left: 0; right: 0; text-align: center;
    z-index: 2; font-size: .68rem; line-height: 1; font-weight: 900; opacity: .82; pointer-events: none;
  }
  .bg-point.bottom .bg-point-number { top: auto; bottom: 3px; }
  .bg-point.dark .bg-point-number { color: #fff8e8; text-shadow: 0 1px 1px rgba(0,0,0,.55); }
  .bg-point.selected { box-shadow: inset 0 0 0 4px var(--accent); }
  .bg-point.target { box-shadow: inset 0 0 0 4px var(--correct); }
  .bg-point.can-select { outline: 3px solid var(--accent); outline-offset: -3px; }
  .bg-stack { position: relative; z-index: 1; display: flex; flex-direction: column; align-items: center; width: 100%; min-width: 0; pointer-events: none; }
  .bg-stack i { display: block; width: clamp(18px, 3.6vw, 29px); max-width: 100%; aspect-ratio: 1; flex-shrink: 0; border-radius: 50%; border: 2px solid rgba(0,0,0,.28); box-shadow: inset 0 2px rgba(255,255,255,.35), 0 1px 2px rgba(0,0,0,.22); }
  .bg-stack i + i { margin-top: -7px; }
  .bg-stack i.white { background: #fffaf0; }
  .bg-stack i.black { background: #303442; }
  .bg-stack em { font-style: normal; padding: 1px 5px; border-radius: 8px; background: var(--paper); }
  .bg-middle { grid-column: 1 / -1; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; padding: 5px; min-width: 0; }
  .bg-middle button { min-height: 44px; padding: 7px 12px; border: 2px solid #65472f; border-radius: 10px; background: #eed6aa; color: #30251e; font-weight: 800; }
  .bg-middle button.can-select { outline: 3px solid var(--accent); }
  .bg-middle button.target { outline: 3px solid var(--correct); }
  .bg-tray { min-height: 44px; padding: 8px 10px; border: 1px solid #65472f; border-radius: 10px; background: #eed6aa; font-weight: 800; }
  .bg-guide { margin: -4px 0 2px; color: var(--ink-soft); font-size: .86rem; font-weight: 700; text-align: center; }
  .bg-dice { min-height: 47px; display: flex; gap: 7px; justify-content: center; align-items: center; }
  .bg-move-choices { display: grid; grid-template-columns: repeat(2, minmax(150px, 1fr)); gap: 8px; width: min(100%, 560px); }
  .bg-move-choice { min-height: 48px; padding: 10px 14px; border: 2px solid var(--correct); border-radius: 13px; background: color-mix(in srgb, var(--correct) 12%, var(--paper)); color: var(--ink); font: inherit; font-weight: 900; cursor: pointer; }
  @media (max-width: 560px) { .bg-move-choices { grid-template-columns: 1fr; } }
  .bg-die {
    width: 58px; height: 58px; display: inline-grid; grid-template-columns: repeat(3, 1fr); grid-template-rows: repeat(3, 1fr); place-items: center;
    padding: 7px; border: 3px solid color-mix(in srgb, var(--accent) 75%, #17365f); border-radius: 13px;
    background: #fffaf0; color: #10213b; font-size: 1.85rem; line-height: 1; font-weight: 950;
    box-shadow: 0 3px 0 color-mix(in srgb, var(--accent) 45%, #111), inset 0 1px rgba(255,255,255,.45);
  }
  .bg-pip { width: 9px; height: 9px; border-radius: 50%; background: transparent; }
  .bg-pip.on { background: #14243c; box-shadow: inset 0 -1px 0 rgba(255,255,255,.25); }
  .bg-die.empty { grid-template: 1fr / 1fr; place-items: center; border-style: dashed; color: var(--ink-faint); background: var(--paper); box-shadow: none; }
  .bg-target-die {
    position: absolute; right: 3px; top: 3px; min-width: 20px; height: 20px;
    display: grid; place-items: center; border-radius: 7px; background: var(--correct);
    color: #07190f; font-size: .72rem; font-weight: 950; pointer-events: none;
  }
  .bg-point.bottom .bg-target-die { top: 3px; bottom: auto; }
  @media (max-width: 560px) {
    /* Доске нужен каждый пиксель ширины: с отступами карточки клетка падала
       до 41 точки, и палец промахивается. Боковые отступы у досок убираем —
       карточка остаётся фоном, а доска получает всю ширину. */
    #viewCheckers .fun-wrap, #viewChess .fun-wrap, #viewBackgammon .fun-wrap {
      padding: 10px 2px; margin-left: -12px; margin-right: -12px;
    }
    #viewCheckers .fun-card, #viewChess .fun-card, #viewBackgammon .fun-card { padding: 10px 0; }
    .checker-board, .checker-meta, .chess-board, .board-meta { width: 100%; max-width: 460px; }
    .bg-point { min-height: 76px; font-size: .72rem; }
    .bg-stack i + i { margin-top: -5px; }
    #viewChess .fun-wrap, #viewBackgammon .fun-wrap { padding: 8px 4px; }
    #viewChess .fun-card, #viewBackgammon .fun-card { padding: 8px 3px; }
    /* Полоска цифр снаружи доски съела ширину: клетка на 390 упала до 42.
       Узкая полоска, зазор в точку и боковые поля шахмат как у шашек —
       клетка снова не меньше 44 точек. */
    .board-frame { grid-template-columns: .8rem minmax(0, 1fr); column-gap: 1px; }
    #viewChess .fun-wrap { padding-left: 2px; padding-right: 2px; }
    #viewChess .fun-card { padding-left: 0; padding-right: 0; }
    /* На 390 px с обычным скроллбаром остаётся 375 px. Отдаём полю
       боковые поля и внешнюю рамку карточки, сохраняя координаты снаружи:
       клетка остаётся 44 px, у самой доски рамка и тень сохраняются. */
    #viewCheckers .fun-wrap, #viewChess .fun-wrap {
      padding-left: 0; padding-right: 0; margin-left: -16px; margin-right: -16px;
    }
    #viewCheckers .fun-card, #viewChess .fun-card { border-left: 0; border-right: 0; }
    #viewBackgammon .fun-wrap { width: calc(100% + 16px); margin-left: -8px; margin-right: -8px; }
    .backgammon-board { gap: 2px; padding: 6px; }
    .bg-middle { padding: 4px 0; }
    .bg-middle button { min-width: 0; padding: 7px 4px; font-size: .8rem; }
    .bg-target-die { right: 1px; min-width: 18px; height: 18px; font-size: .65rem; }
  }
  .logic-board { width: 100%; min-height: 126px; display: grid; place-items: center; gap: 10px; padding: 16px; border: 2px solid var(--rule); border-radius: 16px; background: var(--paper); }
  .logic-sequence { display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: 9px; font-size: clamp(2rem, 7vw, 3.4rem); }
  .logic-sequence span { min-width: 48px; text-align: center; }
  .logic-sequence .missing { width: 52px; height: 52px; display: grid; place-items: center; border: 2px dashed var(--accent); border-radius: 13px; color: var(--accent); font-size: 1.55rem; }
  .logic-clues { display: grid; gap: 8px; width: min(100%, 560px); color: var(--ink); font-weight: 700; text-align: left; }
  .logic-clues span { padding: 8px 11px; border-radius: 10px; background: var(--paper-2); } .logic-odd-note { max-width: 430px; color: var(--ink-soft); font-size: 1rem; font-weight: 700; text-align: center; }
  .logic-analogy { display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: 10px; font-size: clamp(1.45rem, 5vw, 2.2rem); font-weight: 900; }
  .logic-analogy span { padding: 10px 14px; border-radius: 13px; background: var(--paper-2); }
  .logic-route { display: grid; gap: 12px; justify-items: center; }
  .logic-route-grid { display: grid; grid-template-columns: repeat(3, 54px); gap: 5px; }
  .logic-route-cell { width: 54px; height: 54px; display: grid; place-items: center; border: 2px solid var(--rule); border-radius: 11px; background: var(--paper-2); font-size: 1.65rem; }
  /* Мастерская (13.09): программирование, робототехника, ИИ */
  .work-levels { justify-content: center; }
  .prog-board { width: 100%; display: grid; gap: 4px; padding: 6px; border: 2px solid var(--rule); border-radius: 16px; background: var(--paper); }
  .prog-cell { aspect-ratio: 1; min-width: 0; border-radius: 10px; background: var(--paper-2); display: grid; place-items: center; font-size: clamp(1.4rem, 7vw, 2.2rem); line-height: 1; color: var(--gold); }
  .prog-cell.rock { background: repeating-linear-gradient(135deg, var(--rule) 0 6px, var(--paper-2) 6px 12px); }
  .prog-robot { width: 78%; height: 78%; }
  .prog-cell.bump .prog-robot { animation: prog-bump .35s ease-in-out 2; }
  @keyframes prog-bump { 25% { transform: translateX(-4px); } 75% { transform: translateX(4px); } }
  .prog-program { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 6px; justify-content: center; }
  .prog-program li { min-width: 48px; min-height: 48px; }
  .prog-slot { border: 2px dashed var(--rule); border-radius: 12px; }
  .prog-step { width: 100%; min-width: 48px; min-height: 48px; border: 2px solid var(--rule); border-radius: 12px; background: var(--card); color: var(--ink); font-size: 1.3rem; font-weight: 800; }
  .prog-step.rep { padding: 0 10px; font-size: 1rem; white-space: nowrap; }
  .prog-step.on { border-color: var(--accent); background: var(--accent-dim); }
  .prog-step.bad { border-color: var(--wrong); background: var(--wrong-dim); }
  .prog-palette { width: min(100%, 300px); display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
  .prog-cmd { min-height: 56px; border: 2px solid var(--rule); border-radius: 14px; background: var(--card); color: var(--ink); font-size: 1.7rem; font-weight: 800; }
  .prog-cmd:disabled { opacity: .5; }
  .prog-cmd[hidden] { display: none; }
  /* Стрелки крестом, как на пульте: вверх над «вниз», влево и вправо по бокам. */
  .prog-cmd[data-cmd="U"] { grid-column: 2; grid-row: 1; }
  .prog-cmd.prog-del { grid-column: 3; grid-row: 1; font-size: 1.3rem; }
  .prog-cmd[data-cmd="L"] { grid-column: 1; grid-row: 2; }
  .prog-cmd[data-cmd="D"] { grid-column: 2; grid-row: 2; }
  .prog-cmd[data-cmd="R"] { grid-column: 3; grid-row: 2; }
  .prog-cmd.prog-rep { font-size: .95rem; grid-row: 3; }
  .prog-cmd[data-cmd="x2"] { grid-column: 1; }
  .prog-cmd[data-cmd="x3"] { grid-column: 2; }
  /* «До упора», кристаллы, второй робот и след пути (22.09, по задачам
     Учи.ру, присланным владельцем). */
  .prog-cmd.prog-slide { font-size: .95rem; grid-row: 3; grid-column: 3; }
  /* «Жди» и сторож (29.09): кнопка в пустом углу креста, путь сторожа — точки. */
  .prog-cmd.prog-wait { font-size: .95rem; grid-row: 1; grid-column: 1; }
  .prog-cell.patrol { background-image: radial-gradient(circle, color-mix(in srgb, var(--wrong) 40%, transparent) 0 11%, transparent 13%); }
  .prog-guard { width: 78%; height: 78%; }
  /* Процедура «П» (29.09): вторая строка, выбранная строка обведена. */
  .prog-rows { justify-content: center; }
  .prog-rows[hidden], .prog-program[hidden] { display: none; }
  .prog-program.row-on { outline: 3px solid var(--accent); outline-offset: 4px; border-radius: 12px; }
  .prog-proc::before { content: "П ="; align-self: center; font-weight: 800; color: var(--ink); }
  .prog-step.call { color: var(--accent); }
  .prog-cmd.prog-call { grid-row: 3; grid-column: 1; }
  /* Электросеть (29.09): клетки с проводами, под током — золотые. */
  .wire-board { width: 100%; margin: 0 auto; display: grid; gap: 4px; padding: 6px; border: 2px solid var(--rule); border-radius: 16px; background: var(--paper); }
  .wire-cell { aspect-ratio: 1; min-width: 0; min-height: 44px; padding: 0; border: 0; border-radius: 10px; background: var(--paper-2); display: grid; place-items: center; color: inherit; }
  button.wire-cell { cursor: pointer; }
  button.wire-cell:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }
  button.wire-cell:disabled { opacity: 1; cursor: default; }
  .wire-cell.empty { background: transparent; }
  .wire-cell svg { width: 100%; height: 100%; }
  /* Класс одним нажатием на главной (29.09). */
  .age-ask { display: grid; gap: 10px; padding: 14px 16px; }
  .age-ask[hidden] { display: none; }
  .age-ask .chips { justify-content: flex-start; }
  /* Кегль в rem: у body встроенные 14px, и вопрос без своего размера при
     «Крупном тексте» ×2 оставался 14 px над кнопками в 30 (Chrome владельца). */
  .age-ask > b { font-family: var(--font-display); font-size: 1.05rem; line-height: 1.35; }
  /* Первая встреча: карточка итога у робота и шахмат — сверху, поверх экрана. */
  .first-done { position: fixed; z-index: 30; top: 12px; left: 50%; transform: translateX(-50%);
    width: min(440px, calc(100% - 24px)); display: grid; gap: 10px; padding: 14px 16px;
    box-shadow: 0 10px 30px rgba(0, 0, 0, .18); }
  .first-done[hidden] { display: none; }
  .first-done p { margin: 0; font-size: 1rem; font-weight: 700; line-height: 1.4; }
  /* Лестница уроков (29.09): ступени с названием, текущая выделена. */
  .prog-ladder { width: 100%; display: grid; gap: 4px; }
  .prog-rung { display: grid; gap: 2px; padding: 4px 8px 6px; border-radius: 12px; }
  .prog-rung.on { background: var(--accent-dim); }
  .prog-rung-name { margin: 0; text-align: center; font-weight: 700; font-size: .9rem; color: var(--ink-soft); }
  .prog-rung.on .prog-rung-name { color: var(--ink); }
  .prog-cell.caught { display: flex; align-items: center; justify-content: center; }
  .prog-cell.caught svg { width: 46%; height: 46%; }
  /* Колонки креста равные: при крупном тексте «до упора» распирала свою и
     сжимала среднюю до 42 точек на 320 (с 22.09, нашёл test-prog-guard). Слова
     на кнопках не крупнее доли экрана, чтобы «упора» не рвалось. */
  .prog-palette { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .prog-cmd.prog-rep, .prog-cmd.prog-slide, .prog-cmd.prog-wait { font-size: min(.95rem, 5.5vw); overflow-wrap: normal; }
  .prog-board { position: relative; }
  .prog-cell.gem { color: var(--accent); }
  .prog-cell.star2 { color: var(--correct); }
  /* Этап 2 (29.09): ящик, отметка для него, кнопка и дверь. Дверь закрытая —
     сплошная планка, открытая — пунктир: разница видна и без цвета. */
  .prog-cell.spot { box-shadow: inset 0 0 0 3px var(--gold); background-image: radial-gradient(circle, var(--gold) 0 18%, transparent 20%); }
  .prog-cell.box::after { content: ""; width: 72%; height: 72%; box-sizing: border-box; border: 3px solid var(--ink); border-radius: 6px;
    background: linear-gradient(45deg, transparent 44%, var(--ink-soft) 44% 56%, transparent 56%), linear-gradient(-45deg, transparent 44%, var(--ink-soft) 44% 56%, transparent 56%), color-mix(in srgb, var(--gold) 40%, var(--paper-2)); }
  .prog-cell.press { color: var(--wrong); font-size: clamp(1.8rem, 9vw, 2.8rem); }
  .prog-cell.door { background: repeating-linear-gradient(90deg, var(--ink-soft) 0 8px, var(--paper-2) 8px 12px); }
  .prog-cell.door-open { box-shadow: inset 0 0 0 3px var(--ink-soft); outline: 2px dashed var(--ink-soft); outline-offset: -8px; }
  .prog-path { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
  .robo-sensors { justify-content: center; }
  .robo-sensors[hidden] { display: none; }
  .robo-scene { width: 100%; display: grid; grid-template-columns: repeat(auto-fit, minmax(4.4rem, 1fr)); gap: 6px; padding: 8px; border: 2px solid var(--rule); border-radius: 16px; background: var(--paper); transition: background .3s; }
  .robo-scene.dark { background: color-mix(in srgb, var(--ink) 22%, var(--paper)); }
  .robo-sensor { grid-column: 1 / -1; display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 6px 10px; min-height: 64px; }
  .robo-sensor small { color: var(--ink); font-weight: 700; }
  .robo-eye { width: 22px; height: 22px; border-radius: 50%; border: 3px solid var(--ink); background: var(--paper-2); }
  .robo-eye.on { background: var(--correct); }
  .robo-belt { width: 64px; height: 48px; display: grid; place-items: center; border-bottom: 5px solid var(--ink-soft); }
  .robo-item { width: 36px; height: 36px; }
  .robo-bin { min-width: 0; min-height: 92px; padding: 6px 3px; border: 2px solid var(--rule); border-radius: 12px; background: var(--card); text-align: center; }
  .robo-bin b { display: block; font-size: .8rem; overflow-wrap: anywhere; }
  .robo-pile { display: flex; flex-wrap: wrap; justify-content: center; gap: 2px; margin-top: 4px; }
  .robo-pile .robo-item { width: 22px; height: 22px; }
  .robo-pile .robo-item.bad { outline: 2px solid var(--wrong); border-radius: 4px; }
  .robo-rules { width: 100%; display: grid; gap: 8px; }
  /* На 320 кнопка правила налезала на «Если красный»: строка переносится. */
  .robo-rule { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 10px; padding: 6px 8px; border: 1px solid var(--rule); border-radius: 12px; background: var(--paper); font-weight: 700; }
  .robo-rule > span { flex: 1 1 5.5rem; min-width: 0; }
  .robo-act { flex: 1 0 7.5rem; min-height: 48px; padding: 8px 12px; border: 2px solid var(--accent); border-radius: 12px; background: var(--card); color: var(--ink); font-weight: 800; }
  .ml-head { margin: 4px 0 0; font-size: 1rem; align-self: flex-start; }
  .ml-head[hidden], .ml-grid[hidden], .ml-label[hidden], .ml-filters[hidden] { display: none; }
  /* Фильтр признаков (29.09): выключенный признак — зачёркнут, машина его не видит. */
  .ml-filters { width: 100%; display: grid; gap: 6px; }
  .ml-filters .chips { justify-content: center; }
  .ml-filters [aria-pressed="false"] { text-decoration: line-through; opacity: .7; }
  .ml-grid { width: 100%; display: grid; grid-template-columns: repeat(auto-fill, minmax(88px, 1fr)); gap: 8px; }
  .ml-card { min-height: 112px; padding: 6px 4px; display: grid; justify-items: center; align-content: start; gap: 2px; border: 2px solid var(--rule); border-radius: 12px; background: var(--card); color: var(--ink); font: inherit; }
  .ml-card.now { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-dim); }
  .ml-card.ok { border-color: var(--correct); background: var(--correct-dim); }
  .ml-card.bad { border-color: var(--wrong); background: var(--wrong-dim); }
  .ml-card.added { opacity: .55; }
  .ml-monster { width: 64px; height: 64px; }
  .ml-tag { font-size: .85rem; font-weight: 700; }
  @media (prefers-reduced-motion: reduce) {
    .prog-cell.bump .prog-robot { animation: none; }
    .robo-scene { transition: none; }
  }
  .logic-route-cell.start { border-color: var(--accent); box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--accent) 28%, transparent); }
  .logic-route-steps { color: var(--ink); font-size: 1.35rem; font-weight: 900; letter-spacing: .08em; }
  .logic-answers { display: grid; grid-template-columns: repeat(2, minmax(110px, 1fr)); gap: 10px; width: 100%; }
  .logic-answer { min-height: 64px; padding: 10px 12px; border: 2px solid var(--rule); border-radius: 14px; background: var(--paper); color: var(--ink); font-size: clamp(1.05rem, 4vw, 1.45rem); font-weight: 800; }
  .logic-answer.good { border-color: var(--correct); background: color-mix(in srgb, var(--correct) 13%, var(--paper)); }
  .logic-answer.bad { border-color: var(--wrong); background: color-mix(in srgb, var(--wrong) 10%, var(--paper)); }
  .logic-meta { width: 100%; display: flex; flex-wrap: wrap; justify-content: space-between; gap: 2px 10px; color: var(--ink-soft); font-size: .86rem; }
  .logic-meta span { min-width: 0; overflow-wrap: anywhere; }   /* «Вдвое» на 320: длинное слово уезжало вбок */
  @media (max-width: 560px) {
    .puzzle-stage { flex-direction: column; align-items: center; }
    .puzzle-grid { width: min(88vw, 390px); gap: 2px; }
    /* Образец — то, что ребёнок собирает. На телефоне он был 58 точек и
       читался как значок рядом с подписью: владелец 02.09 прислал снимок с
       айфона, «образец слишком маленький». Теперь это половина ширины
       экрана, ограниченная разумным пределом, и стоит он над подписью, а не
       сбоку от неё. */
    .puzzle-preview {
      width: auto; flex-basis: auto; display: flex; flex-direction: column;
      gap: 6px; align-items: center;
    }
    .puzzle-preview svg { width: min(46vw, 190px); }
  }
  @media (min-width: 700px) {
    .spot-pair { flex-direction: row; }
    .spot-one { width: 50%; }
    .spot-svg { max-height: 46vh; }
  }
  /* На невысоких экранах (альбом, маленький телефон) поджимаем всё вокруг
     картинок: заголовок, подпись и отступы — лишь бы пара влезла целиком */
  /* На телефоне под картинками ещё чипы, счёт, подсказка и кнопки — всё это
     должно поместиться на экран разом, иначе «Другая пара» не видно */
  @media (max-width: 699px) {
    #viewSpot .fun-wrap { padding: 12px 14px; }
    #viewSpot h2 { font-size: 1.02rem; }
    #viewSpot .hint { margin: 2px 0; font-size: .8rem; }
  }
  @media (max-height: 720px) {
    #viewSpot .fun-wrap { padding: 8px 12px; }
    #viewSpot .fun-card { gap: 6px; }
    .spot-svg { max-height: 26vh; }
  }
  @supports not (gap: 10px) {
    .spot-pair > * + * { margin-top: 10px; }
  }
  /* Три режима раскраски в узкой карточке умещаются только компактными */
  #paintMode .chip { padding: 8px 12px; font-size: .88rem; }
  /* Образец для малышей: маленькая цветная картинка над своей раскраской */
  /* Образец — то, на что ребёнок смотрит всё время, поэтому он крупный:
     не фиксированные пиксели, а доля ширины. Мелкий образец бесполезен. */
  .paint-sample {
    display: flex; flex-direction: column; align-items: center;
    border: 2px dashed var(--rule); border-radius: 14px; padding: 4px 10px 8px;
  }
  .paint-sample b {
    font-size: .74rem; letter-spacing: .08em; text-transform: uppercase;
    color: var(--ink-faint); margin-bottom: 2px;
  }
  .paint-sample svg { width: 100%; height: auto; display: block; }

  /* Образец и рабочая картинка всегда стоят рядом: так их и сравнивают,
     и высота не складывается — краски остаются на виду. */
  .paint-work {
    width: 100%; display: flex; flex-direction: row; gap: 10px; align-items: flex-start;
  }
  .paint-sample { flex: 0 0 42%; }
  .paint-work > div:last-child { flex: 1 1 auto; min-width: 0; }
  /* Всплывающий образец: на телефоне он прячется за кнопку, чтобы рабочая
     картинка занимала всю ширину — раскрашивать пальцем важнее, чем всё время
     видеть пример. Посмотрел, закрыл, красишь дальше. */
  .sample-peek {
    position: fixed; inset: 0; z-index: 40; display: flex;
    align-items: center; justify-content: center;
    background: rgba(0, 0, 0, .62); padding: 20px;
  }
  .sample-peek-box {
    background: var(--card); border: 2px solid var(--rule); border-radius: 18px;
    padding: 12px 16px 14px; max-width: 92vw; text-align: center;
  }
  .sample-peek-box b {
    display: block; font-size: .74rem; letter-spacing: .08em;
    text-transform: uppercase; color: var(--ink-faint); margin-bottom: 6px;
  }
  .sample-peek-box small { display: block; color: var(--ink-faint); margin-top: 8px; font-size: .8rem; }
  .sample-peek-box svg { width: 78vw; max-width: 340px; height: auto; display: block; }
  #btnSamplePeek { width: 100%; }

  /* Раскраска не должна прыгать при смене режима: строка-подсказка, кнопка
     образца и колонка образца занимают своё место всегда — меняется только
     содержимое. Иначе ребёнок жмёт «Образец», и палитра уезжает вниз. */
  #paintNote { min-height: 1.3em; margin: 6px 0; }
  /* Ряд сложности, строка-подсказка и кнопка образца есть в любом режиме —
     поэтому при переключении ничего не появляется и не исчезает. Резервировать
     пустое место больше не нужно: раньше оно съедало полэкрана. */
  #paintNote[aria-hidden="true"] { visibility: hidden; }

  /* ── Питомец ──────────────────────────────────────────
     Живёт в шапке и открывается поверх экрана. Радуется занятиям и скучает
     без них — но никогда не болеет и не исчезает: пугать ребёнка нельзя. */
  /* Уголок питомца на занятии: маленький, у края, не перекрывает клавиатуру.
     Нажатие открывает то же окно ухода. */
  .pet-buddy {
    position: fixed; right: 14px; bottom: 14px; z-index: 30;
    width: 84px; height: 84px; padding: 0; border: none; background: none;
    line-height: 0; cursor: pointer;
  }
  .pet-buddy svg { width: 100%; height: auto; display: block; }
  @media (max-width: 560px) { .pet-buddy { width: 62px; height: 62px; right: 8px; bottom: 8px; } }
  @media (max-height: 620px) { .pet-buddy { display: none; } }   /* мало места — не мешаем */

  .pet-pop {
    position: fixed; inset: 0; z-index: 60; display: flex;
    align-items: center; justify-content: center;
    background: rgba(0, 0, 0, .62); padding: 18px;
    overflow-y: auto;                /* на телефоне окно длиннее экрана */
  }
  .pet-box {
    background: var(--card); border: 2px solid var(--rule); border-radius: 20px;
    padding: 16px 18px 18px; max-width: 380px; width: 100%; text-align: center;
    margin: auto;                    /* при прокрутке остаётся по центру */
  }
  .pet-head-row {
    display: flex; align-items: center; justify-content: center; gap: 8px; margin-bottom: 8px;
  }
  .pet-badge {
    font-size: .72rem; font-weight: 800; letter-spacing: .04em; text-transform: uppercase;
    padding: 4px 10px; border-radius: 999px;
  }
  .pet-badge.glad { background: var(--correct-dim); color: var(--correct); }
  .pet-badge.calm { background: var(--accent-dim); color: var(--accent); }
  .pet-badge.sad  { background: var(--paper-2); color: var(--ink-soft); }

  .pet-chips { display: flex; gap: 6px; justify-content: center; margin: 8px 0 10px; flex-wrap: wrap; }
  .pet-chip {
    font-size: .78rem; font-weight: 700; padding: 5px 10px; border-radius: 999px;
    background: var(--paper-2); color: var(--ink-soft); border: 1px solid var(--rule);
    display: inline-flex; align-items: center; gap: 5px;
  }
  .pet-chip .ph { width: 14px; height: 14px; flex: none; }
  .pet-chip.ok { color: var(--correct); border-color: var(--correct-dim); }

  /* Плитки ухода: крупные цветные цели вместо ряда одинаковых серых кнопок —
     малышу проще попасть и понять, что делает каждая. */
  .pet-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; margin-bottom: 12px; }
  .pet-tile {
    border: 2px solid var(--rule); border-radius: 18px; padding: 12px 8px 10px;
    background: var(--paper-2); color: var(--ink); cursor: pointer;
    display: flex; flex-direction: column; align-items: center; gap: 2px;
    transition: transform .08s, border-color .12s;
  }
  .pet-tile .ph { width: 30px; height: 30px; display: block; }
  /* Значок в шапке рисуем вектором: эмодзи «микрофон» есть не в каждом наборе
     шрифтов, и кнопка выглядела пустой. */
  .icon-btn.ph-btn { display: inline-flex; align-items: center; justify-content: center; }
  .ghost.with-ph { display: inline-flex; align-items: center; justify-content: center; gap: 8px; }
  .ghost.with-ph .ph { width: 20px; height: 20px; flex: none; }
  .pet-tile b { font-size: .96rem; }
  .pet-tile small { font-size: .74rem; color: var(--ink-soft); min-height: 1em; }
  .pet-tile:active { transform: translateY(2px); }
  .pet-tile-pat   { border-color: #E7A2B4; }
  .pet-tile-eat   { border-color: #E0A55C; }
  .pet-tile-clean { border-color: #7FC6A6; }
  .pet-tile-play  { border-color: #7FA9D8; }
  .pet-tile-pat   .ph { color: #E7A2B4; }
  .pet-tile-eat   .ph { color: #E0A55C; }
  .pet-tile-clean .ph { color: #7FC6A6; }
  .pet-tile-play  .ph { color: #7FA9D8; }
  .ghost.with-ph  .ph { color: var(--gold, #E8B44A); }

  .pet-box h2 { margin: 0; font-size: 1.25rem; }
  .pet-box .pet-mood { color: var(--ink-soft); font-size: .92rem; margin: 0 0 10px; }
  .pet-art { width: 220px; max-width: 74%; height: auto; display: block; margin: 0 auto 10px; }
  /* Телефон: питомец поменьше и поля тоньше — иначе кнопки ухода уезжают
     за нижний край, и до «Покормить» надо докручивать. */
  @media (max-height: 720px) {
    .pet-pop { padding: 8px; align-items: flex-start; }
    .pet-box { padding: 10px 12px 12px; }
    .pet-art { width: 132px; margin-bottom: 4px; }
    .pet-say { padding: 8px 10px; font-size: .9rem; margin-bottom: 8px; }
    .pet-acts { gap: 6px; }
    .pet-box h2 { font-size: 1.1rem; }
    .pet-box .pet-mood { margin-bottom: 6px; font-size: .85rem; }
  }
  .pet-say {
    background: var(--paper); border: 1px solid var(--rule); border-radius: 14px;
    padding: 10px 12px; font-size: .95rem; line-height: 1.4; margin: 0 0 12px;
  }
  .pet-acts { display: flex; flex-direction: column; gap: 8px; }
  /* Голосовой помощник: разговор, а не список кнопок. Владелец 20.08 показал
     на «Таю» в CRM — там крупная кнопка посреди экрана и лента реплик, и
     ребёнку так понятнее: видно, что сказал он и что ответили ему.
     Кнопки «прочитать задание» здесь нет намеренно: чтение уже живёт в самом
     задании, отдельной кнопкой с динамиком. Второй раз то же самое — лишний
     выбор там, где ребёнок и так знает, куда нажать. */
  .voice-log {
    min-height: 96px; max-height: 40vh; overflow-y: auto; text-align: left;
    background: var(--paper-2); border: 1px solid var(--rule); border-radius: 14px;
    padding: 10px 12px; margin: 0 0 14px;
  }
  .voice-log p { margin: 0 0 8px; font-size: .95rem; line-height: 1.4; }
  .voice-log p:last-child { margin-bottom: 0; }
  .voice-log .voice-me { color: var(--ink); font-weight: 600; }
  .voice-log .voice-ai { color: var(--ink-soft); }
  .voice-mic-wrap { display: flex; flex-direction: column; align-items: center; gap: 8px; }
  .voice-mic {
    width: 96px; height: 96px; border-radius: 50%; border: none;
    background: var(--accent); color: var(--on-accent);
    font-size: 2.2rem; line-height: 1; box-shadow: var(--shadow-key);
  }
  .voice-mic[aria-pressed="true"] { background: var(--wrong); }
  .voice-mic[data-state="thinking"] { opacity: .7; }
  .voice-mic[data-state="speaking"] { box-shadow: 0 0 0 6px rgba(96,165,250,.18); }
  .voice-mic[data-state="error"] { background: var(--wrong); }
  .voice-hint { color: var(--ink-soft); font-size: .9rem; margin: 0; }
  .voice-ready { text-align: center; min-height: 1.2em; }
  /* ── Окно Таи ────────────────────────────────────────
     Своя ширина: у помощника внутри разговор, а не одна картинка, и в колонке
     380 px реплики ломались на три полосы. Питомец остаётся как был. */
  /* Клавиатура сжимает ВИДИМУЮ область, но не layout viewport, поэтому высоту
     окна задаёт JS из visualViewport (--taya-h), а 100dvh остаётся запасным.
     ⚠ Правило общее, а не только для телефона: на планшете ширина больше 560px,
     мобильный медиа-запрос не срабатывал — и там окно выдавливало клавиатурой
     ровно так же, шапка уезжала за верхний край. */
  .voice-pop { align-items: flex-start; }
  .voice-pop .pet-box {
    width: min(760px, calc(100vw - 24px)); max-width: 760px;
    height: min(760px, var(--taya-h, 100dvh));
    max-height: 100%;          /* 100% оверлея, у которого отступы уже вычтены */
    margin: auto; text-align: left; padding: 0;
    overflow: hidden;
  }
  .voice-pop #voiceBody { height: 100%; }
  .voice-chat-shell { height: 100%; display: flex; flex-direction: column; min-height: 0; }
  .voice-chat-head {
    display: flex; align-items: center; gap: 4px;
    padding: 14px 16px; border-bottom: 1px solid var(--rule);
  }
  /* Заголовок забирает всё свободное место, кнопки прижимаются вправо. */
  .voice-chat-head h2 { flex: 1 1 auto; }
  .voice-chat-gear { font-size: 1.05rem; }
  .voice-chat-head h2 { text-align: left; font-size: 1.12rem; }
  /* 44 точки — минимум под палец. 05.09 аудит на 375×812: закрыть и
     шестерёнка были 38, микрофон и «отправить» — 42; это главные кнопки
     ребёнка в разговоре с Таей, и промах по ним читается как «не работает». */
  .voice-chat-close, .voice-chat-gear {
    width: 44px; height: 44px; border: none; border-radius: 50%;
    background: transparent; color: var(--ink); font: inherit; font-size: 1.35rem;
    cursor: pointer;
  }
  .voice-chat-close:hover { background: var(--paper-2); }
  .voice-pop .pet-mood { text-align: center; }

  /* Реплики пузырями: видно, где спросил ребёнок, а где ответила Тая.
     Раньше отличие несла только приписка «Ты:» и жирность — на длинной ленте
     это сливалось в сплошной текст. */
  .voice-log p {
    max-width: 84%; padding: 9px 13px; border-radius: 16px;
    margin: 0 0 8px; width: fit-content; line-height: 1.4;
  }
  .voice-log .voice-me {
    margin-left: auto; background: var(--accent); color: var(--on-accent);
    border-bottom-right-radius: 5px; font-weight: 500;
  }
  .voice-log .voice-ai {
    background: var(--paper-2); color: var(--ink);
    border: 1px solid var(--rule); border-bottom-left-radius: 5px;
  }
  .voice-log {
    min-height: 0; max-height: none; flex: 1 1 auto; padding: 18px 20px;
    margin: 0; border: none; border-radius: 0; background: transparent;
  }

  /* Подсказки-кнопки: раньше это была строка на пять полос, которую ребёнок
     6–9 лет не дочитывает. Теперь по ней можно ткнуть и сразу спросить. */
  .voice-chips { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 12px; }
  .voice-chip {
    border: 1px solid var(--rule); background: var(--paper-2); color: var(--ink);
    border-radius: 999px; padding: 8px 14px; font-size: .88rem; font-weight: 600;
  }
  .voice-chip:hover { border-color: var(--accent); color: var(--accent); }

  .voice-ask { gap: 10px; }
  .voice-input { font-size: 1.02rem; padding: 12px 14px; }
  .voice-send { padding: 12px 18px; font-size: 1rem; }
  @media (max-width: 560px) {
    .voice-pop .pet-box { padding: 14px; }
    .voice-log p { max-width: 92%; }
  }
  /* Строка «напиши вопрос»: голосом умеет не каждый браузер и не в каждой
     комнате, а спросить хочется всегда. */
  .voice-ask { display: flex; gap: 8px; margin: 0 0 14px; }
  .voice-input {
    flex: 1 1 auto; min-width: 0; font: inherit; font-size: 1rem;
    padding: 10px 12px; border-radius: 12px;
    border: 1px solid var(--rule); background: var(--paper-2); color: var(--ink);
  }
  .voice-input:focus { outline: 2px solid var(--accent); outline-offset: 1px; }
  .voice-send {
    flex: 0 0 auto; font: inherit; font-weight: 600; padding: 10px 14px;
    border: none; border-radius: 12px;
    background: var(--accent); color: var(--on-accent); box-shadow: var(--shadow-key);
  }
  /* Нижняя строка устроена как в современном чате: текст, голос и отправка
     находятся в одном месте и не спорят за внимание. */
  .voice-chat-tools { padding: 0 16px 8px; }
  .voice-chat-tools.voice-media-launch { margin: 0; }
  .voice-chat-shell > .voice-hint { padding: 7px 16px 0; text-align: center; }
  .voice-composer-wrap { padding: 0 16px 14px; }
  .voice-composer {
    display: flex; align-items: flex-end; gap: 7px; margin: 0;
    padding: 7px; border: 1px solid var(--rule); border-radius: 23px;
    background: var(--paper-2); box-shadow: var(--shadow-key);
  }
  .voice-composer .voice-input {
    min-height: 42px; max-height: 132px; resize: none; overflow-y: auto;
    padding: 10px 9px; border: none; border-radius: 16px; background: transparent;
  }
  .voice-composer .voice-input:focus { outline: none; }
  /* Фокус с клавиатуры виден на всей строке ввода: у поля нет ни границы,
     ни обводки, и Tab «терялся» (GPT 06.09, a11y). */
  .voice-composer:focus-within { outline: 3px solid var(--accent); outline-offset: 2px; }
  .voice-composer .voice-send,
  .voice-composer .voice-mic-inline {
    width: 44px; height: 44px; min-width: 44px; padding: 0; border: none;
    border-radius: 50%; display: grid; place-items: center; font-size: 1.15rem;
  }
  .voice-composer .voice-mic-inline {
    background: transparent; color: var(--ink); box-shadow: none;
  }
  .voice-composer .voice-mic-inline[aria-pressed="true"] {
    background: var(--wrong); color: var(--on-accent);
  }
  .voice-chat-status {
    min-height: 18px; margin: 5px 8px 0; text-align: center;
    color: var(--ink-soft); font-size: .78rem;
  }
  /* Сам оверлей тоже держится видимой области: иначе на планшете он остаётся
     во весь экран, а окно внутри него уезжает под клавиатуру. */
  .voice-pop {
    overflow: hidden;
    /* box-sizing обязателен: у оверлея есть свои отступы, и без него окно
       вылезало под клавиатуру ровно на их величину. */
    box-sizing: border-box;
    top: var(--taya-t, 0px); height: var(--taya-h, 100dvh); bottom: auto;
  }
  /* Сжиматься при нехватке места должна лента разговора, а не строка ввода. */
  .voice-chat-head, .voice-chat-tools, .voice-composer-wrap { flex: 0 0 auto; }

  @media (max-width: 560px) {
    .voice-pop { padding: 0; }
    .voice-pop .pet-box {
      width: 100vw; height: 100%; max-width: none; border-radius: 0;
    }
    /* На телефоне окно Таи занимает весь экран, а страница объявлена
       viewport-fit=cover — значит наверху лежит прозрачная полоса под часы,
       вырез и батарею. Заголовок и кнопки заезжали прямо под них: владелец
       прислал снимок с айфона 02.09, «слишком высоко значки». --taya-t тут
       не помогает, он про прокрутку под клавиатуру, а не про вырез. */
    .voice-pop .voice-chat-head {
      padding-top: calc(14px + env(safe-area-inset-top, 0px));
    }
    .voice-log { padding: 14px 12px; }
    .voice-chat-tools, .voice-composer-wrap { padding-left: 10px; padding-right: 10px; }
    /* Сжиматься при нехватке места должна лента разговора, а не строка ввода. */
    .voice-chat-head, .voice-chat-tools, .voice-composer-wrap { flex: 0 0 auto; }
    .voice-log { min-height: 0; }
  }
  .voice-pop.taya-tight .voice-chat-tools,
  .voice-pop.taya-tight .voice-chat-status { display: none; }
  /* С открытой клавиатурой шапка ужимается, но вырез никуда не делся. */
  .voice-pop.taya-tight .voice-chat-head {
    padding-top: calc(8px + env(safe-area-inset-top, 0px)); padding-bottom: 8px;
  }
  /* Карточка ответа: то же самое, что помощник сказал вслух, но глазами. */
  .voice-card {
    /* Карточка — это тоже реплика Таи: та же ширина и та же сторона, что у её
       пузырей, иначе она читается как отдельный блок, выпавший из разговора. */
    margin: 0 0 8px; padding: 10px 12px; border-radius: 16px;
    border-bottom-left-radius: 5px; max-width: 84%;
    background: var(--card); border: 1px solid var(--rule);
  }
  .voice-card-top { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
  .voice-card-icon { font-size: 1.5rem; line-height: 1; }
  .voice-card-top b { font-size: 1.6rem; color: var(--ink); }
  .voice-card-sub { color: var(--ink-soft); font-size: .9rem; }
  .voice-chart { display: block; width: 100%; height: auto; margin-top: 6px; }
  .voice-chart-line { fill: none; stroke: var(--accent); stroke-width: 2;
                      stroke-linejoin: round; stroke-linecap: round; }
  .voice-chart-dot { fill: var(--accent); }
  .voice-chart-hour { fill: var(--ink-faint); font-size: 9px; text-anchor: middle; }
  .voice-chart-val { fill: var(--ink-soft); font-size: 10px; text-anchor: middle; }
  /* Проигрыватель: крупные кнопки — по ним попадает палец ребёнка. */
  .voice-player-name { font-weight: 600; color: var(--ink); margin-bottom: 4px; }
  .voice-player-meta { color: var(--ink-soft); font-size: .88rem; margin-bottom: 8px; }
  .voice-player-instead { color: #c98a1f; font-size: .8rem; margin-bottom: 8px; line-height: 1.3; }
  .voice-player-head { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }
  .voice-player-art-none {
    width: 76px; height: 76px; border-radius: 14px; flex: 0 0 76px;
    display: flex; align-items: center; justify-content: center;
    font-size: 1.6rem; background: var(--paper-2); color: var(--accent);
  }
  .voice-player-art {
    width: 76px; height: 76px; border-radius: 14px; flex: 0 0 76px;
    display: block; object-fit: cover; background: var(--paper-2);
  }
  /* Плитка используется только когда настоящей обложки нет. Она состоит из
     проверенных данных и обычного текста — без SVG, HTML и внешних ресурсов. */
  .voice-player-art-tile {
    width: 76px; height: 76px; border-radius: 14px; flex: 0 0 76px;
    display: flex; flex-direction: column; align-items: center;
    justify-content: center; gap: 2px; overflow: hidden; padding: 4px;
    box-sizing: border-box; color: #fff; text-align: center;
  }
  .voice-player-art-tile i { font-style: normal; font-size: 1.5rem; line-height: 1; }
  .voice-player-art-tile span {
    width: 100%; font-size: .66rem; line-height: 1.05; font-weight: 700;
    overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
  }
  .voice-player-bar { height: 4px; border-radius: 4px; background: var(--rule); overflow: hidden; }
  .voice-player-bar > i { display: block; height: 100%; background: var(--accent); width: 0; }
  /* Время у книги: ребёнок видит, сколько ещё слушать, и где остановился. */
  /* ⚠ Раньше здесь стоял отрицательный верхний отступ (-4px): строка времени
     подтягивалась вверх и налезала на полосу и обложку — владелец 25.08:
     «время накладывается». Отступ теперь обычный, полоса и время стоят друг
     под другом. */
  .voice-player-time {
    color: var(--ink-soft); font-size: .82rem; margin: 6px 0 10px;
    font-variant-numeric: tabular-nums;
  }
  .voice-player-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
  .voice-player-btn {
    font-size: 1.2rem; line-height: 1; min-width: 44px; min-height: 44px;
    border: 1px solid var(--rule); border-radius: 12px;
    background: var(--paper-2); color: var(--ink);
  }
  .voice-player-vol { flex: 1 1 90px; min-width: 90px; accent-color: var(--accent); }
  /* Медиатека видна всегда: ребёнку не надо догадываться о голосовой команде. */
  .voice-media-launch {
    display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 8px; margin: 0 0 12px;
  }
  .voice-media-launch button {
    min-height: 54px; padding: 8px 5px; border: 1px solid var(--rule);
    border-radius: 14px; background: var(--paper-2); color: var(--ink);
    font: inherit; font-weight: 650; cursor: pointer;
  }
  .voice-media-launch button span { display: block; font-size: 1.35rem; margin-bottom: 2px; }
  /* Общая компоновка привычного мессенджера; голосовая логика не меняется. */
  .voice-chat-head { padding: 10px 14px; gap: 10px; background: var(--card); }
  .voice-chat-avatar { display: grid; place-items: center; width: 44px; height: 44px;
    flex: 0 0 44px; border-radius: 50%; background: var(--accent-dim); }
  .voice-chat-avatar svg { width: 36px; height: 36px; }
  .voice-chat-identity { flex: 1; min-width: 0; }
  .voice-chat-identity h2 { margin: 0; line-height: 1.25; }
  .voice-chat-identity small { display: block; color: var(--ink-soft); font-size: .78rem; margin-top: 2px; }
  .voice-chat-shell { font-size: 1rem; background: var(--paper); }
  .voice-log { padding: 20px 16px; }
  .voice-log p { padding: 11px 14px; line-height: 1.5; box-shadow: 0 1px 2px #0000000a; }
  .voice-log .voice-ai { background: var(--card); }
  .voice-chat-tools.voice-media-launch { display: flex; gap: 8px; overflow-x: auto;
    padding: 8px 14px; background: var(--card); border-top: 1px solid var(--rule); }
  .voice-chat-tools.voice-media-launch button { display: flex; align-items: center; gap: 6px;
    flex: 0 0 auto; min-height: 44px; padding: 8px 12px; border-radius: 999px;
    font-size: .88rem; white-space: nowrap; }
  .voice-chat-tools.voice-media-launch button span { display: inline; font-size: 1.1rem; margin: 0; }
  .voice-composer-wrap { padding: 8px 14px max(10px, env(safe-area-inset-bottom, 0px)); background: var(--card); }
  .voice-composer { border-radius: 26px; box-shadow: none; }
  .voice-chat-status { text-align: left; margin-left: 12px; }
  .voice-pop.taya-tight .voice-chat-tools { display: none; }
  @media (max-width: 560px) {
    .voice-pop .pet-box { padding: 0; }
    .voice-chat-head { gap: 6px; }
    .voice-chat-avatar { width: 38px; height: 38px; flex-basis: 38px; }
    .voice-chat-identity h2 { font-size: 1rem; }
    .voice-composer-wrap { padding-inline: 8px; }
    .voice-log { padding: 14px 10px; }
  }
  .voice-media-menu { max-width: 100%; }
  .voice-media-title { color: var(--ink); font-weight: 700; margin-bottom: 2px; }
  .voice-media-sub { color: var(--ink-soft); font-size: .82rem; margin-bottom: 9px; }
  .voice-media-list { display: grid; gap: 6px; }
  .voice-media-choice {
    width: 100%; min-height: 44px; padding: 8px 10px; text-align: left;
    border: 1px solid var(--rule); border-radius: 12px;
    background: var(--paper-2); color: var(--ink); font: inherit; cursor: pointer;
  }
  .voice-media-choice b { display: block; font-size: .94rem; }
  .voice-media-choice small { display: block; color: var(--ink-soft); margin-top: 2px; }
  .voice-media-error { color: var(--ink-soft); margin: 4px 0 0; }
  .voice-draw-menu .voice-ask { margin: 8px 0 0; }
  .voice-draw-words { display: flex; flex-wrap: wrap; gap: 8px; margin: 4px 0 10px; }
  .voice-draw-words .chip { min-height: 44px; }
  .voice-draw-examples { color: var(--ink-soft); font-size: .8rem; margin-top: 7px; }
  .voice-draw-wait { color: var(--ink-soft); font-size: .95rem; }
  .voice-draw-img { width: 100%; height: auto; border-radius: 10px; display: block; }
  /* Домик — фон сцены, питомец сидит в лежанке поверх него. Размеры заданы в
     процентах от сцены, поэтому при любой ширине окна он остаётся на месте. */
  .pet-scene { position: relative; width: 100%; }
  .pet-room { position: relative; width: 100%; display: block; border-radius: 14px;
              overflow: hidden; }
  .pet-room-bg { width: 100%; height: auto; display: block; }
  /* Предметы сцены. Позиции в процентах от комнаты, поэтому на любой ширине
     экрана лежанка, миска и игрушка стоят там же, где на десктопе. */
  .pet-bed  { position: absolute; left: 50%; bottom: 6%;  width: 46%;
              transform: translateX(-50%); }
  .pet-bowl { position: absolute; left: 12%; bottom: 10%; width: 17%; }
  .pet-toy-art { position: absolute; right: 8%; bottom: 9%; width: 12%; }
  .pet-room-care { position: absolute; inset: 0; width: 100%; height: 100%; }
  /* Питомец-картинка: наряды ложатся поверх тем же слоем, что и раньше. */
  .pet-live { position: relative; display: block; }
  .pet-photo { width: 100%; height: auto; display: block; }
  .pet-wear-layer { position: absolute; inset: 0; width: 100%; height: 100%; }
  .pet-scene .pet-art {
    /* Питомец сидит в лежанке: низ рисунка совпадает с подушкой, а не висит
       под ней. Проценты — от сцены, поэтому на любой ширине сидит одинаково. */
    position: absolute; left: 50%; bottom: 13%;
    width: 34%; transform: translateX(-50%); margin: 0;
  }
  .pet-state {
    color: var(--ink-soft); font-size: .82rem; margin: 0 0 8px;
  }
  .pet-toy { position: absolute; left: 50%; top: 6%; font-size: 1.6rem; }
  .pet-mess { position: absolute; right: 8%; bottom: 4%; font-size: 1.4rem; opacity: .75; }
  /* Питомец подпрыгивает от радости, игрушка улетает и возвращается */
  @keyframes pet-jump { 0%,100% { transform: translateY(0); } 40% { transform: translateY(-10px); } }
  .pet-jump { animation: pet-jump .45s ease-in-out 1; }
  @keyframes pet-throw {
    0% { transform: translate(0, 0) scale(1); }
    45% { transform: translate(-120px, -40px) scale(.8); }
    100% { transform: translate(0, 0) scale(1); }
  }
  .pet-throw { animation: pet-throw .9s ease-in-out 1; }

  /* Живой питомец. Двигаем только transform и opacity: их браузер считает на
     видеокарте, а на слабом планшете любая другая анимация начнёт заикаться.
     transform-box задаём точечно, по классам: на группах с атрибутом transform
     (поза ушей по настроению) он бы сместил центр поворота. */
  .pet-body, .pet-head, .pet-tail, .pet-ear-l, .pet-ear-r, .pet-lid-l, .pet-lid-r,
  .pet-muzzle, .pet-fluff, .pet-hearts, .pet-shadow { transform-box: fill-box; }
  .pet-body { transform-origin: 50% 100%; animation: pet-breath 3.5s ease-in-out infinite; }
  .pet-head { transform-origin: 50% 100%; animation: pet-bob 3.5s ease-in-out infinite; }
  .pet-shadow { transform-origin: 50% 50%; animation: pet-shade 3.5s ease-in-out infinite; }
  .pet-muzzle { transform-origin: 50% 0; }
  .pet-hearts { transform-origin: 50% 100%; animation: pet-float 2.8s ease-in-out infinite; }
  .pet-tail { transform-origin: 7% 45%; }
  .pet-glad .pet-tail { animation: pet-wag-w 1.1s ease-in-out infinite; }
  .pet-calm .pet-tail { animation: pet-wag-m 2.6s ease-in-out infinite; }
  .pet-sad .pet-tail { animation: pet-wag-s 5s ease-in-out infinite; }
  /* Веко закрыто при scaleY(1); базовое состояние — 0, иначе при отключённых
     анимациях питомец остался бы с закрытыми глазами. */
  .pet-lid-l, .pet-lid-r { transform-origin: 50% 0; transform: scaleY(0); }
  .pet-cat .pet-lid-l, .pet-cat .pet-lid-r { animation: pet-blink 5.2s linear infinite; }
  .pet-dog .pet-lid-l, .pet-dog .pet-lid-r { animation: pet-blink 4.3s linear infinite; }
  .pet-cat .pet-ear-l { transform-origin: 60% 96%; animation: pet-turn 9s ease-in-out infinite; }
  .pet-cat .pet-ear-r { transform-origin: 40% 96%; animation: pet-turn 11s -4s ease-in-out infinite; }
  .pet-dog .pet-ear-l { transform-origin: 55% 5%; animation: pet-flick 6.5s ease-in-out infinite; }
  .pet-dog .pet-ear-r { transform-origin: 45% 5%; animation: pet-flick 7.4s -2.6s ease-in-out infinite; }
  .pet-fluff { transform-origin: 50% 100%; opacity: 0; }
  @keyframes pet-breath { 0%, 100% { transform: scale(1, 1); } 50% { transform: scale(1.008, 1.024); } }
  @keyframes pet-bob { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-1.4px); } }
  @keyframes pet-shade { 0%, 100% { transform: scaleX(1); opacity: 1; } 50% { transform: scaleX(.965); opacity: .85; } }
  @keyframes pet-float { 0%, 100% { transform: translateY(0); opacity: .95; } 50% { transform: translateY(-5px); opacity: .6; } }
  @keyframes pet-wag-w { 0%, 100% { transform: rotate(-8deg); } 50% { transform: rotate(8deg); } }
  @keyframes pet-wag-m { 0%, 100% { transform: rotate(-3.5deg); } 50% { transform: rotate(3.5deg); } }
  @keyframes pet-wag-s { 0%, 100% { transform: rotate(-1deg); } 50% { transform: rotate(1deg); } }
  @keyframes pet-blink { 0%, 95.4%, 100% { transform: scaleY(0); } 95.9%, 98.2% { transform: scaleY(1); } 98.7% { transform: scaleY(0); } }
  @keyframes pet-flick { 0%, 86%, 100% { transform: rotate(0); } 89% { transform: rotate(5deg); } 92% { transform: rotate(-4deg); } 95% { transform: rotate(2deg); } }
  @keyframes pet-turn { 0%, 74%, 100% { transform: rotate(0); } 80%, 86% { transform: rotate(-9deg); } 93% { transform: rotate(3deg); } }

  /* Разовые отклики: petReact вешает класс на корень SVG и снимает по таймеру.
     Правила ниже специфичнее фоновых, поэтому на время отклика перебивают их. */
  @keyframes pet-squint { 0%, 100% { transform: scaleY(0); } 8%, 88% { transform: scaleY(.82); } }
  @keyframes pet-tilt { 0%, 100% { transform: rotate(0); } 20%, 80% { transform: rotate(-8deg); } }
  @keyframes pet-chew { 0%, 100% { transform: translateY(0) scaleY(1); } 50% { transform: translateY(3px) scaleY(.9); } }
  @keyframes pet-narrow { 0%, 100% { transform: scaleY(0); } 15%, 85% { transform: scaleY(.45); } }
  @keyframes pet-hop { 0%, 100% { transform: translateY(0); } 35% { transform: translateY(-14px); } 60% { transform: translateY(0); } 78% { transform: translateY(-5px); } }
  @keyframes pet-back-l { 0%, 100% { transform: rotate(0); } 15%, 85% { transform: rotate(-34deg); } }
  @keyframes pet-back-r { 0%, 100% { transform: rotate(0); } 15%, 85% { transform: rotate(34deg); } }
  @keyframes pet-bristle { 0%, 100% { opacity: 0; transform: scaleY(1); } 15%, 85% { opacity: 1; transform: scaleY(1.3); } }
  @keyframes pet-lean { 0%, 100% { transform: rotate(0); } 20%, 80% { transform: rotate(-3deg); } }
  .pet-react-pat .pet-lid-l, .pet-react-pat .pet-lid-r { animation: pet-squint 1.5s ease-in-out; }
  .pet-react-pat .pet-head { animation: pet-tilt 1.5s ease-in-out; }
  .pet-react-eat .pet-muzzle { animation: pet-chew .24s ease-in-out 4; }
  .pet-react-play { animation: pet-hop .5s ease-in-out 2; }
  .pet-react-play .pet-tail { animation: pet-wag-w .2s linear 5; }
  .pet-react-hiss { animation: pet-lean .9s ease-in-out; }
  .pet-react-hiss .pet-ear-l { animation: pet-back-l .9s ease-in-out; }
  .pet-react-hiss .pet-ear-r { animation: pet-back-r .9s ease-in-out; }
  .pet-react-hiss .pet-fluff { animation: pet-bristle .9s ease-in-out; }
  /* Недовольный зверь щурится: с широко открытыми глазами прижатые уши
     читались бы испугом, а не «хватит меня тискать». */
  .pet-react-hiss .pet-lid-l, .pet-react-hiss .pet-lid-r { animation: pet-narrow .9s ease-in-out; }
  @media (prefers-reduced-motion: reduce) {
    .pet-jump, .pet-throw, .pet-art, .pet-art * { animation: none !important; }
  }
  /* ── Живой питомец-картинка ─────────────────────────
     Владелец 20.08: «просто картинка, нет динамики». У прежнего SVG двигались
     отдельные части (уши, хвост, веки) — у картинки таких частей нет, поэтому
     оживляем её целиком: дыхание в покое и отклик на каждое действие.
     Точка опоры — низ картинки: зверь сидит на лежанке и не отрывается от неё. */
  @keyframes pet-breathe {
    0%, 100% { transform: scale(1, 1); }
    50%      { transform: scale(.995, 1.015); }
  }
  @keyframes pet-sway {
    0%, 100% { transform: rotate(-1.2deg); }
    50%      { transform: rotate(1.2deg); }
  }
  @keyframes pet-appear {
    0%   { transform: translateY(8%) scale(.9); opacity: 0; }
    100% { transform: translateY(0) scale(1); opacity: 1; }
  }
  @keyframes pet-photo-tilt {
    0%, 100% { transform: rotate(0); }
    25%      { transform: rotate(-7deg) translateY(-2%); }
    60%      { transform: rotate(5deg); }
  }
  @keyframes pet-photo-chew {
    0%, 100% { transform: translateY(0) scale(1, 1); }
    50%      { transform: translateY(3%) scale(1.02, .96); }
  }
  @keyframes pet-photo-hop {
    0%, 100% { transform: translateY(0) scale(1, 1); }
    30%      { transform: translateY(-16%) scale(.97, 1.05); }
    55%      { transform: translateY(0) scale(1.04, .95); }
    75%      { transform: translateY(-6%) scale(1, 1); }
  }
  @keyframes pet-photo-lean {
    0%, 100% { transform: rotate(0); }
    20%, 80% { transform: rotate(-5deg) translateX(-3%); }
  }
  @keyframes pet-toy-roll {
    0%   { transform: translateX(0) rotate(0); }
    45%  { transform: translateX(-160%) rotate(-320deg); }
    100% { transform: translateX(0) rotate(0); }
  }
  @keyframes pet-bowl-shake {
    0%, 100% { transform: translateY(0) rotate(0); }
    25%      { transform: translateY(-6%) rotate(-4deg); }
    60%      { transform: translateY(0) rotate(3deg); }
  }
  .pet-live .pet-photo {
    transform-origin: 50% 100%;
    animation: pet-appear .4s ease-out 1, pet-breathe 3.6s ease-in-out infinite .4s;
  }
  /* Радость видна по темпу: дышит чаще и слегка покачивается. Грусть —
     наоборот, медленнее и без покачивания. */
  .pet-live.pet-glad .pet-photo {
    animation: pet-appear .4s ease-out 1, pet-breathe 2.4s ease-in-out infinite .4s,
               pet-sway 2.8s ease-in-out infinite .4s;
  }
  .pet-live.pet-sad .pet-photo {
    animation: pet-appear .4s ease-out 1, pet-breathe 5s ease-in-out infinite .4s;
  }
  /* Отклики перебивают фоновое дыхание: правила ниже и специфичнее, и позже. */
  .pet-live.pet-react-pat .pet-photo { animation: pet-photo-tilt 1.5s ease-in-out 1; }
  .pet-live.pet-react-eat .pet-photo { animation: pet-photo-chew .26s ease-in-out 4; }
  .pet-live.pet-react-play .pet-photo { animation: pet-photo-hop .55s ease-in-out 2; }
  .pet-live.pet-react-hiss .pet-photo { animation: pet-photo-lean .9s ease-in-out 1; }
  /* Игрушка укатывается, когда играли, миска подрагивает, когда кормят —
     действие видно не только на звере. */
  .pet-scene.pet-doing-play .pet-toy-art { animation: pet-toy-roll 1.1s ease-in-out 1; }
  .pet-scene.pet-doing-eat .pet-bowl { animation: pet-bowl-shake .3s ease-in-out 3; }
  @media (prefers-reduced-motion: reduce) {
    /* Гасим и картинку, и прежний SVG-питомец: настройка «меньше движения»
       обязана снимать ВСЁ движение сцены, а не половину. */
    .pet-art, .pet-art *, .pet-live .pet-photo,
    .pet-toy-art, .pet-bowl { animation: none !important; }
  }

  /* Отчёт прогона: список «что проверяли — что вышло». Моноширинный, потому
     что его читают глазами по строкам и пересылают текстом. */
  .st-list {
    max-height: 46vh; overflow-y: auto; text-align: left; margin: 12px 0;
    font-family: ui-monospace, "SF Mono", Consolas, monospace; font-size: .82rem;
  }
  .st-row { padding: 4px 6px; border-bottom: 1px solid var(--rule); line-height: 1.35; }
  .st-row:last-child { border-bottom: none; }
  .st-ok { color: var(--ink-soft); }
  .st-bad { color: var(--wrong); font-weight: 600; }
  .pet-pick { display: flex; gap: 10px; justify-content: center; margin-bottom: 12px; }
  .pet-pick button {
    flex: 1 1 0; background: var(--paper-2); border: 2px solid var(--rule);
    border-radius: 16px; padding: 10px; font-size: 1rem; font-weight: 700; color: var(--ink);
  }
  .pet-pick button[aria-pressed="true"] { border-color: var(--accent); }
  .pet-pick svg { width: 100%; height: auto; display: block; }
  .pet-wear-list {
    display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin: 10px 0 12px;
  }
  .pet-wear-item {
    background: var(--paper-2); border: 2px solid var(--rule); border-radius: 14px;
    padding: 10px 6px; color: var(--ink); font-weight: 700; font-size: .9rem;
    display: flex; flex-direction: column; gap: 2px; align-items: center;
  }
  .pet-wear-item small { color: var(--ink-soft); font-size: .78rem; font-weight: 600; }
  .pet-wear-item[aria-pressed="true"] { border-color: var(--accent); }
  /* Недоступное приглушено, но нажимается: нажатие — примерка, а не отказ. */
  .pet-wear-item.far { opacity: .6; border-style: dashed; }

  .pet-names { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; margin-bottom: 12px; }
  .pet-names button {
    background: var(--paper-2); border: 1px solid var(--rule); border-radius: 12px;
    padding: 9px 12px; font-size: .92rem; font-weight: 700; color: var(--ink);
  }
  .pet-names button[aria-pressed="true"] { border-color: var(--accent); color: var(--accent); }
  .pet-hint { text-align: center; color: var(--ink-soft); font-size: .86rem; margin: 0 0 10px; }
  /* Пока не выбраны вид и кличка, «Готово» видимо погашена: иначе ребёнок жмёт
     обычную с виду кнопку и не понимает, почему ничего не происходит. */
  .pet-acts button[disabled] { opacity: .4; }

  /* ── Библиотека ────────────────────────────────────────
     Читают дети, поэтому буква крупная, строка короткая, а фон по умолчанию
     тёплый: белый лист в тёмной комнате бьёт по глазам сильнее всего. */
  .lib-h { margin: 0 0 4px; font-size: 1.3rem; }
  .lib-sub { margin: 0 0 14px; color: var(--ink-soft); font-size: .92rem; }
  /* Фигура на доске: крупная, одного размера для всех — сравнивают форму. */
  .shape-art { width: 150px; height: 150px; display: block; margin: 0 auto; }

  .lib-shelf { display: grid; gap: 8px; }
  .lib-row { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 12px; }
  .lib-group { display: flex; align-items: baseline; gap: 8px; margin: 10px 0 2px; }
  .lib-group b { font-size: 1.02rem; }
  .lib-group small { color: var(--ink-soft); font-size: .84rem; }
  .lib-book {
    display: flex; gap: 10px; align-items: center; text-align: left;
    background: var(--paper-2); border: 2px solid var(--rule); border-radius: 16px;
    padding: 10px; color: var(--ink); cursor: pointer;
  }
  .lib-book svg { width: 64px; height: 64px; flex: none; border-radius: 12px; }
  .lib-book .book-art { width: 64px; height: 64px; flex: none; border-radius: 12px;
                        object-fit: cover; background: var(--paper-2); }
  .lib-book b { display: block; font-size: 1rem; }
  .lib-book small { display: block; color: var(--ink-soft); font-size: .82rem; }
  .lib-book.read { border-color: var(--correct); }
  .lib-book .tick { color: var(--correct); font-weight: 700; }
  .lib-more { margin: 16px 0 12px; }
  .lib-more summary { cursor: pointer; font-weight: 700; }
  .lib-note { color: var(--ink-soft); font-size: .86rem; margin: 8px 0; }
  .lib-list { display: grid; gap: 6px; }
  .lib-list div { font-size: .92rem; }
  .lib-list b { color: var(--accent); }

  .book-card { max-width: 44rem; margin: 0 auto; }
  .book-bar { display: flex; justify-content: space-between; gap: 8px; flex-wrap: wrap; margin-bottom: 10px; }
  /* На узком телефоне четыре кнопки (294 px) в карточку 264 px не влезают:
     без переноса они сжимаются в кашу. Перенос дешевле, чем прятать кнопки. */
  .book-tools { display: flex; gap: 6px; flex-wrap: wrap; justify-content: flex-end; }
  .book-title { margin: 0 0 2px; font-size: 1.4rem; }
  .book-author { margin: 0 0 12px; color: var(--ink-soft); font-size: .9rem; }
  .book-pic svg { width: 100%; height: auto; max-height: 190px; border-radius: 14px; display: block; }
  /* Высоту обложки задаём заранее. При height: auto место под картинку до её
     загрузки равно нулю: ребёнок начинает читать, обложка догружается и весь
     текст прыгает вниз — строка теряется. Держим долю ширины экрана, чтобы на
     телефоне обложка не занимала пол-страницы. */
  .book-pic .book-art { width: 100%; height: 42vw; max-height: 260px; border-radius: 14px;
                        display: block; object-fit: cover; background: var(--paper-2); }
  /* Ширину строки держим короткой: длинную строку глаз теряет при переносе. */
  .book-text { max-width: 34em; margin: 14px auto 0; }
  .book-text p { margin: 0 0 1em; }
  .book-rest {
    max-width: 34em; margin: 10px auto 0; padding: 10px 12px; border-radius: 12px;
    background: var(--accent-dim); color: var(--accent); font-size: .92rem; text-align: center;
  }
  .book-acts { display: flex; justify-content: center; margin-top: 16px; }
  /* Читаемый абзац подсвечен мягко: ребёнок ведёт по нему глазами, а резкая
     заливка на светлом листе бьёт по глазам. */
  .book-text p.read-now {
    background: var(--accent-dim); border-radius: 10px;
    box-shadow: 0 0 0 8px var(--accent-dim);
  }
  .book-warm .book-text p.read-now {
    background: #EFE0C0; box-shadow: 0 0 0 8px #EFE0C0;
  }
  .book-mark {
    text-align: center; color: var(--accent); font-size: .82rem;
    letter-spacing: .06em; margin: 0 0 1em;
  }
  .book-warm .book-mark { color: #8A6B3E; }

  /* Размер буквы и просвет — три ступени, выбирает сам ребёнок. */
  .book-text { font-size: 1.15rem; line-height: 1.75; }
  .book-s2 .book-text { font-size: 1.35rem; line-height: 1.8; }
  .book-s3 .book-text { font-size: 1.6rem; line-height: 1.85; }

  /* Тёплый лист: бумажный цвет вместо белого, буква тёмно-коричневая. */
  .book-warm { background: #F6ECD8; color: #3E3323; border-color: #E2D2B4; }
  .book-warm .book-author, .book-warm .book-rest { color: #6B5B44; }
  .book-warm .book-rest { background: #EADFC4; }
  .book-warm .ghost { background: #EADFC4; color: #3E3323; border-color: #D9C6A3; }

  /* ── Раскраска: лист и краски ─────────────────────────
     Рисунок — главное на экране, поэтому ему отдана вся высота, а управление
     собрано в колонку сбоку. На телефоне колонки складываются: сперва лист,
     под ним краски и кнопки. Ничего не появляется и не исчезает при смене
     режима, поэтому экран не дёргается. */
  #viewPaint .fun-wrap { max-width: 1040px; }
  .paint-grid {
    display: grid; gap: 16px; align-items: start;
    grid-template-columns: minmax(0, 1fr) 300px;
    grid-template-areas: "лист образец" "лист управление";
    grid-template-rows: auto 1fr;
    padding: 16px;
  }
  .paint-work { grid-area: лист; }
  .paint-sample { grid-area: образец; }
  .paint-side { grid-area: управление; }
  .paint-side { display: flex; flex-direction: column; gap: 8px; align-items: stretch; }
  .paint-side .paint-head { margin: 0; }
  .paint-side .palette { justify-content: flex-start; }
  .paint-side .chips { justify-content: flex-start; gap: 8px; }
  .paint-side .chip { padding: 10px 10px; font-size: .82rem; }
  .paint-side .done-actions { margin-top: auto; }
  .paint-work { width: 100%; height: 100%; }
  .paint-sample {
    background: var(--paper); border: 1px solid var(--rule); border-radius: 14px;
    padding: 6px 8px 8px; text-align: center;
    display: flex; flex-direction: column; height: 176px;
  }
  /* На широком экране образец и так перед глазами — кнопка «крупно» нужна
     только на телефоне, где колонка уезжает под рисунок */
  @media (min-width: 900px) { #btnSamplePeek { display: none !important; } }
  .paint-sample b {
    display: block; font-size: .68rem; letter-spacing: .09em;
    text-transform: uppercase; color: var(--ink-faint); margin-bottom: 4px;
  }
  .paint-sample svg { width: 100%; flex: 1 1 auto; min-height: 0; display: block; }

  #paintBox {
    display: flex; align-items: center; justify-content: center;
    background: var(--paper); border-radius: 16px; padding: 10px;
    height: 100%; min-height: 260px;
  }
  /* Лист занимает свободную высоту окна, но не заставляет страницу прокручиваться */
  #paintBox .paint-svg { width: 100%; height: auto; max-height: calc(100vh - 230px); }
  #paintNote { min-height: 1.3em; margin: 0; font-size: .8rem; }

  @media (max-width: 899px) {
    /* Телефон: лист и образец рядом в одну строку, краски сразу под ними —
       так ребёнок видит и что красит, и на что смотреть, без прокрутки */
    .paint-grid {
      grid-template-columns: 1fr;
      grid-template-areas: "лист" "образец" "управление";
      gap: 10px; padding: 12px;
    }
    /* Образец — широкая невысокая полоска под листом: обе картинки крупные,
       и ребёнок видит пример, не листая экран */
    .paint-sample { height: 104px; flex-direction: row; align-items: center; gap: 10px; }
    .paint-sample b { margin: 0; writing-mode: vertical-rl; transform: rotate(180deg); }
    .paint-sample svg { max-height: 88px; }
    #viewPaint .fun-wrap { padding: 10px 12px; }
    #paintBox .paint-svg { max-height: 42vh; }
    /* три уровня в одну строку — иначе переносятся и съедают полсотни точек */
    #viewPaint .chips .chip { padding: 10px 8px; font-size: .8rem; }
    .paint-side .palette, .paint-side .chips { justify-content: center; }
  }
  @media (max-height: 700px) and (max-width: 899px) {
    #paintBox .paint-svg { max-height: 30vh; }
    .paint-grid { gap: 8px; }
    .paint-side { gap: 8px; }
  }

  @supports not (gap: 8px) {
    .paint-work > * + * { margin-top: 8px; }
  }
  /* Дела на сегодня: свой экран, вызывается значком в шапке */
  .today-head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 10px; }
  .today-head h2 { margin: 0; font-size: 1.3rem; text-align: left; overflow-wrap: anywhere; }
  .today-head span { color: var(--ink); font-size: 1rem; }
  .today-list { display: flex; flex-direction: column; gap: 8px; }
  .today-row {
    /* Направление задаём явно: на экране «Дела» родительская карточка ставит
       колонку, и без этого значок с текстом вставали друг под друга */
    display: flex; flex-direction: row; flex-wrap: wrap; align-items: flex-start; gap: 10px; width: 100%;
    background: var(--card2, var(--paper)); border: 1px solid var(--rule);
    border-radius: 14px; padding: 10px 12px; min-height: 52px; text-align: left;
  }
  .today-row em {
    font-style: normal; font-size: 1.15rem; width: 30px; text-align: center; flex: 0 0 auto;
  }
  .today-row > div { flex: 1 1 12rem; min-width: 0; text-align: left; }
  .today-row b { display: block; font-size: 1.1rem; line-height: 1.35; }
  .today-row small { display: block; color: var(--ink); font-size: 1rem; line-height: 1.5; }
  .today-row b, .today-row small, .today-state { overflow-wrap: anywhere; }
  .today-state { display: block; margin-top: 6px; color: var(--ink); font-size: 1rem; line-height: 1.4; font-weight: 700; }
  .today-row.done { border-style: dashed; }
  @supports not (gap: 8px) {
    .today > * + * { margin-top: 8px; }
    .today-list > * + * { margin-top: 8px; }
  }
  /* Оформление меняют один раз, поэтому строка свёрнута: три кнопки
     разворачиваются по нажатию и не занимают место в списке настроек */
  .set-skin { justify-content: flex-start; margin: -2px 0 6px; }
  .set-skin .chip { padding: 8px 14px; font-size: .9rem; }
  /* Раскрытое «Оформление» — две группы, у каждой своя подпись. Подпись
     обязана занимать всю строку: иначе кнопки продолжают её ряд, «Светлая»
     встаёт справа от подписи, а «Тёмная» с «Как на устройстве» уезжают вниз
     лесенкой. Владелец 03.09: «перенёс, но пространство не организовал». */
  .set-skin .sec-label { flex: 0 0 100%; margin: 4px 0 2px; }
  /* Обе группы — про одну строку выше, поэтому отодвинуты от края: так
     видно, что это её содержимое, а не новые настройки следом. */
  #skinChips, #themeChips { padding-left: 12px; }
  #skinChips { margin-top: 2px; }
  #themeChips { margin-top: -2px; margin-bottom: 10px; }
  #setSkinRow[aria-expanded="true"] .chev { transform: rotate(90deg); }
  #setSkinRow .chev { transition: transform .15s; }
  .palette { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; }
  /* Кружки краски выбирают пальцем, а не мышью — держим цель не меньше 44 */
  .swatch { width: 44px; height: 44px; border-radius: 50%; border: 2px solid var(--rule); cursor: pointer; }
  .swatch.sel { outline: 3px solid var(--accent); outline-offset: 2px; }
  /* В режиме «по номерам» на краске стоит её номер */
  .swatch { font-weight: 800; font-size: 1rem; color: #fff;
            text-shadow: 0 1px 3px rgba(0,0,0,.55); }
  @supports not (inset: 0) {
    .fun-card > * + * { margin-top: 12px; }
    .paint-head > * + * { margin-left: 12px; }
    .palette { margin: -4px; } .palette > * { margin: 4px; }
  }

  /* Плашка «обновляю» при потягивании вниз */
  .refresh-note {
    position: fixed; top: 14px; left: 50%;
    margin-left: -70px; width: 140px; text-align: center;
    padding: 9px 0; border-radius: 999px; z-index: 40;
    background: var(--accent); color: var(--on-accent);
    font-family: var(--font-display); font-weight: 700; font-size: .9rem;
    box-shadow: var(--shadow);
  }

  /* Кнопка «прослушать задание» на доске */
  .board { position: relative; }
  .say-btn {
    /* 44 — минимальная цель для детского пальца; на слуховых заданиях
       по этой кнопке жмут чаще всего */
    position: absolute; top: 10px; right: 10px; z-index: 1;
    width: 44px; height: 44px; border-radius: 50%;
    border: 1.5px solid var(--rule); background: var(--paper-2);
    font-size: 1.05rem; line-height: 1; cursor: pointer;
    transition: border-color .15s, background .15s;
  }
  .say-btn:hover { border-color: var(--accent); }
  /* Задание не заходит под кнопку. Проверка всех занятий 21.09 нашла под
     ней конец строки у семи досок, и все они — один текст: «12, 18, 24, 30,»,
     «Вставь букву:». Там содержимое начинается ниже кнопки. Доски с картинкой
     (кружки, прямая, часы, столбик) не трогаем: пример стоит под картинкой, а
     картинка и так оставляет кнопке место — зато лишние 38 точек увели бы
     «Подсказку» за край iPhone SE. */
  .board:has(> .say-btn:not([hidden])):has(> #dots[hidden]):has(> #lineBox[hidden]) { padding-top: 64px; }

  /* Невысокие экраны (iPhone 6/7/8, SE): всё занятие — без прокрутки */
  @media (max-height: 700px) {
    .shell { gap: 10px; padding-top: calc(8px + env(safe-area-inset-top, 0px)); }
    .stage { gap: 10px; }
    .board { min-height: 150px; padding: 16px 14px 14px; }
    .key { height: 54px; }
    .choice { height: 58px; }
  }
  @media (max-height: 700px) and (max-width: 640px) {
    /* На SE само поле с десятью цифровыми клавишами высокое. Экономим только
       воздух между блоками — цели, кегль и рисунок задания не уменьшаем. */
    body.lesson-open .shell {
      gap: 4px; padding-top: calc(4px + env(safe-area-inset-top, 0px));
    }
    body.lesson-open .stage { gap: 5px; }
  }

  /* ── Старые iPhone (Safari до 14.1): там flex не понимает gap.
        `inset` появился в том же выпуске, что и flex-gap, поэтому блок
        ниже выполняют только старые браузеры — современные его пропускают. */
  @supports not (inset: 0) {
    .shell > * + * { margin-top: 16px; }
    .top > * + * { margin-left: 10px; }
    .brand > * + * { margin-left: 9px; }
    .field > * + * { margin-top: 10px; }
    .chips { margin: -4px; }            .chips > * { margin: 4px; }
    .ages > * + * { margin-top: 18px; }
    .age-opt > * + * { margin-left: 14px; }
    .age-opt div > * + * { margin-top: 3px; }
    .home > * + * { margin-top: 16px; }
    .banner > * + * { margin-left: 14px; }
    .banner-text > * + * { margin-top: 3px; }
    .tile > * + * { margin-left: 13px; }
    .tile div > * + * { margin-top: 2px; }
    .badges { margin: -4px; }           .badges > * { margin: 4px; }
    .stage > * + * { margin-top: 13px; }
    .meter > * + * { margin-left: 10px; }
    .meter .streak > * + * { margin-left: 6px; }
    .board > * + * { margin-top: 15px; }
    .equation > * + * { margin-left: .3em; }
    .helpbar > * + * { margin-left: 9px; }
    .panel > * + * { margin-top: 13px; }
    .panel-head > * + * { margin-left: 10px; }
    .legend { margin: -6px; }           .legend > * { margin: 6px; }
    .done > * + * { margin-top: 19px; }
    .stats { margin: -12px; }           .stats > * { margin: 12px; }
    .stat > * + * { margin-top: 3px; }
    .done-actions { margin: -5px; }     .done-actions > * { margin: 5px; }
    .earned > * + * { margin-top: 9px; }
    .report > * + * { margin-top: 14px; }
    .rep-card > * + * { margin-top: 12px; }
    .weak > * + * { margin-top: 7px; }
    .weak-row > * + * { margin-left: 10px; }
    .days { margin: -2px; }             .days > * { margin: 2px; }
    .support > * + * { margin-top: 14px; }
    .sup-card > * + * { margin-top: 14px; }
    .settings > * + * { margin-top: 14px; }
    .set-card > * + * { margin-top: 12px; }
    .set-row > * + * { margin-left: 12px; }
    .set-row > div > * + * { margin-top: 3px; }
  }

  /* ── Большой экран (не альбомный телефон) ───────────── */

  @media (min-width: 760px) and (min-height: 620px) {
    .shell { gap: 18px; }
    .play { grid-template-columns: minmax(0, 1fr) 296px; gap: 20px; }
    /* Боковая панель «Что уже знаю» скрыта почти во всех режимах, а столбец
       под неё оставался: на планшете 834 точки кадр занимал 486, справа
       пустовала треть экрана. Аудит 05.09 на 834×1112 — это планшет, на
       котором занимается сын владельца. Без панели — один столбец, кадр по
       центру и не шире 640, чтобы клавиши не расползались. */
    .play.alone { grid-template-columns: minmax(0, 1fr); }
    .play.alone .stage { width: 100%; max-width: 640px; margin: 0 auto; }
    .sidebar { position: sticky; top: 20px; }
    .board { min-height: 240px; padding: 36px 24px 30px; }
    .tiles { grid-template-columns: 1fr 1fr; }
    .age-list { grid-template-columns: repeat(4, 1fr); }
    .brand b { font-size: 1.15rem; }
  }

  @media not all and (min-width: 760px) and (min-height: 620px) {
    .sidebar[hidden] { display: none; }
  }

/* Illustrated app layout: shared with the approved welcome page.
   Lesson controls retain their existing sizing and theme tokens. */
body { background-image: none; }
.shell { max-width: 1200px; }
body:not(.lesson-open) .top { padding-bottom: 12px; border-bottom: 1px solid var(--rule); margin-bottom: 20px; }
body:not(.lesson-open) #brandTitle { font-family: var(--font-display); font-size: 1.35rem; letter-spacing: -.5px; }
/* Плитка шире подписи, а не подпись шире плитки: «Расписание» и «Сообщения»
   вылезали за 70 px на айфоне (обращение 97, 15.09). */
body:not(.lesson-open) .top-actions .icon-btn { display: grid; flex: none; width: auto; min-width: 70px; height: 65px; grid-template-rows: 28px auto; gap: 5px; padding: 7px 8px; border-radius: 15px; }
body:not(.lesson-open) .top-actions .icon-btn::after { content: attr(data-label); font: 600 10px/1.15 var(--font-body); white-space: nowrap; text-align: center; }
.home { gap: 20px; }
.home .banner { padding: 18px 24px; min-height: 154px; border-radius: 24px; background: var(--card); overflow: hidden; position: relative; gap: 20px; }
.home-heading { margin: 0 0 9px; font-family: var(--font-display); font-size: clamp(23px,2.4vw,31px); line-height: 1.15; letter-spacing: -.6px; }
.home .banner-text { flex: 1; }
.home .banner-text b { font-size: .87rem; color: var(--ink-soft); }
.home .banner-text small { max-width: 540px; }
.home .ring { width: 60px; height: 60px; }
.home-art { width: 156px; height: 130px; object-fit: cover; border-radius: 18px; flex: none; }
/* Восемь колонок, пока в них влезает слово; при крупном тексте колонок
   меньше. Колонка не уже 7rem (rem растёт с размером текста): до 28.09 при
   тексте ×1,5 и ×2 «Английский», «Технологии» и «Китайский» вылезали из
   кнопок на всех ширинах от 601 до 1707 px. */
#tileTabs { display: grid; grid-template-columns: repeat(auto-fit,minmax(max(7rem,calc((100% - 70px) / 8)),1fr)); overflow: visible; gap: 10px; padding: 0; }
/* Число занятий справа от названия, а не строкой ниже — плитки ниже на треть
   (владелец 15.09: «количество не снизу, а сбоку, для экономии пространства»).
   Не хватает места — число переносится целиком, слово не рвётся. */
#tileTabs .tab-btn { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: center; gap: 0 6px; white-space: normal; min-height: 48px; padding: 10px 6px; border-radius: 16px; background: var(--card); font-size: .88rem; }
#tileTabs .tab-btn b { display: inline; margin: 0; font-size: .76rem; opacity: .75; font-weight: 600; }
#tileTabs .tab-btn[aria-pressed=true] { background: var(--accent); color: var(--on-accent); border-color: var(--accent); box-shadow: 0 4px 12px var(--accent-dim); }
#viewHome .sec-label { font-size: .83rem; letter-spacing: .025em; text-transform: none; margin: 3px 0; }
#viewHome .tiles { grid-template-columns: repeat(3,minmax(0,1fr)); gap: 14px; }
#viewHome .tile { min-height: 114px; padding: 18px 14px; border-radius: 20px; box-shadow: 0 3px 14px rgba(27,42,74,.04); grid-template-columns: 46px minmax(0,1fr) auto; gap: 12px; }
#viewHome .tile em { width: 46px; height: 54px; border-radius: 14px; }
#viewHome .tile:hover { box-shadow: 0 5px 18px rgba(27,42,74,.1); }
@media(max-width:1000px){
  body:not(.lesson-open) .top { flex-wrap: wrap; gap: 14px; }
  body:not(.lesson-open) .top-actions { order: 3; width: 100%; overflow-x: auto; padding: 2px 0 6px; }
  #tileTabs { grid-template-columns: repeat(auto-fit,minmax(max(7rem,calc((100% - 30px) / 4)),1fr)); }
  #viewHome .tiles { grid-template-columns: repeat(2,minmax(0,1fr)); }
}
@media(max-width:600px){
  body:not(.lesson-open) .top { margin-bottom: 14px; padding-bottom: 8px; }
  body:not(.lesson-open) #brandTitle { font-size: 1.18rem; }
  /* Внутренние экраны: под шапкой-названием хватает общего зазора ленты.
     Владелец 21.09 перечеркнул эту полосу над доской: «ещё компактнее». */
  body:not(.lesson-open):not(.at-home) .top { margin-bottom: 0; }
  .home { gap: 16px; }
  .home .banner { min-height: 125px; padding: 16px; gap: 12px; border-radius: 20px; }
  .home .ring { width: 42px; height: 42px; }
  .home-art { display: none; }
  .home-heading { font-size: 23px; }
  .home .banner-text small { font-size: .78rem; }
  #tileTabs { gap: 8px; }
  #tileTabs .tab-btn { font-size: .78rem; min-height: 44px; padding: 8px 4px; border-radius: 13px; }
  #viewHome .tiles { grid-template-columns: minmax(0,1fr); gap: 10px; }
  #viewHome .tile { min-height: 90px; padding: 14px; }
  body:not(.lesson-open) .top-actions .icon-btn { min-width: 64px; height: 62px; }
}
.play, .stage { min-width: 0; } .helpbar .ghost { min-width: 0; }
@media(max-width:600px){#tileTabs{grid-template-columns:repeat(auto-fit,minmax(min(100%,6.5rem),1fr))}#tileTabs .tab-btn{overflow-wrap:break-word;line-height:1.25}}

/* Illustrated worlds: art, preview cards and scenery, with stable legacy skin keys. */
body:not(.lesson-open) { background-image: var(--pattern); background-size: var(--pattern-size); }
#skinChips.illustrated-skins { display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:12px; white-space:normal; overflow:visible; padding:12px 0; }
#skinChips[hidden] { display:none; }
.skin-intro { grid-column:1/-1; margin:0 0 4px; color:var(--ink-soft); font-size:.88rem; }
#skinChips .skin-card { position:relative; min-width:0; padding:8px; border-radius:18px; display:flex; flex-direction:column; gap:10px; text-align:left; white-space:normal; background:var(--card); color:var(--ink); border:2px solid var(--rule); }
#skinChips .skin-card[aria-pressed="true"] { border-color:var(--accent); box-shadow:0 0 0 2px var(--accent-dim); }
#skinChips .skin-card[aria-pressed="true"]::after { content:'✓'; position:absolute; right:10px; top:10px; display:grid; place-items:center; width:25px; height:25px; border-radius:50%; background:var(--accent); color:var(--on-accent); font-weight:800; }
.skin-card img { width:100%; height:105px; object-fit:cover; border-radius:12px; background:#fffaf3; }
.skin-card span { display:grid; gap:5px; min-width:0; overflow-wrap:anywhere; }
.skin-card b { font-size:.88rem; line-height:1.3; }
.skin-card small { color:var(--ink-soft); font-size:.76rem; line-height:1.4; font-weight:400; }
:root[data-skin] .home-art { object-fit:cover; background:#fffaf3; }
@media(max-width:600px){
 .home .banner { display:grid; grid-template-columns:44px minmax(0,1fr) 72px; gap:10px; }
 .home .home-art { display:block; width:72px; height:100px; border-radius:14px; }
 .home .home-heading { font-size:1.13rem; }
}
@media(max-width:480px){
 #skinChips.illustrated-skins { grid-template-columns:1fr; gap:10px; }
 #skinChips .skin-card { flex-direction:row; align-items:center; gap:14px; padding:10px; min-height:104px; }
 .skin-card img { width:84px; height:84px; flex:none; }
 .skin-card span { padding-right:16px; }
 .skin-card b { font-size:1rem; }
 .skin-card small { font-size:.84rem; }
 .home .banner { grid-template-columns:minmax(0,1fr) 76px; }
 .home .banner .ring { display:none; }
 .home .banner-text { grid-column:1; }
 .home .home-art { grid-column:2; grid-row:1; }
}
#themeChips { display:grid; grid-template-columns:minmax(0,1fr) minmax(0,1fr) minmax(0,1.4fr); gap:8px; }
#themeChips[hidden] { display:none; }
#themeChips .sec-label { grid-column:1/-1; }
#themeChips .chip { min-width:0; white-space:normal; overflow-wrap:anywhere; min-height:46px; }
/* Illustrated avatars, artwork generated for this application. */
.profile-portrait, .prof-ava.has-portrait { width:64px; height:64px; flex:none; border-radius:50%; display:grid; place-items:center; background-color:var(--accent-dim); color:var(--ink); font-size:1.6rem; border:2px solid var(--card); box-shadow:0 2px 8px #0001; }
.has-portrait { background-image:url('/img/avatars-family.png'); background-size:400% 400%; background-repeat:no-repeat; }
[data-portrait="boy-1"]{background-position:0% 5.5556%}[data-portrait="boy-2"]{background-position:33.3333% 5.5556%}[data-portrait="girl-1"]{background-position:66.6667% 5.5556%}[data-portrait="girl-2"]{background-position:100% 5.5556%}
[data-portrait="dad-1"]{background-position:0% 50%}[data-portrait="dad-2"]{background-position:33.3333% 50%}[data-portrait="mom-1"]{background-position:66.6667% 50%}[data-portrait="mom-2"]{background-position:100% 50%}
[data-portrait="grandma-1"]{background-position:0% 94.4444%}[data-portrait="grandma-2"]{background-position:33.3333% 94.4444%}[data-portrait="grandpa-1"]{background-position:66.6667% 94.4444%}[data-portrait="grandpa-2"]{background-position:100% 94.4444%}
.avatar-toggle { gap:14px; margin:12px 0; }
.avatar-toggle>span:nth-child(2) { flex:1; min-width:0; }
.avatar-toggle small { display:block; color:var(--ink-soft); margin-top:5px; }
.avatar-picker { padding:16px; margin:0 0 16px; border:1px solid var(--rule); border-radius:20px; background:var(--card); }
.avatar-picker[hidden]{display:none}
.avatar-picker h3{margin:0 0 8px}
.avatar-filters{display:flex;flex-wrap:wrap;gap:8px;margin:16px 0}
.avatar-filters .chip{min-height:44px;padding:8px 12px}
.avatar-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px}
.avatar-choice{position:relative;display:flex;align-items:center;flex-direction:column;gap:8px;border:2px solid var(--rule);border-radius:16px;background:var(--paper);color:var(--ink);padding:10px 4px;font:inherit;min-width:0;cursor:pointer}
.avatar-choice>span:last-child{font-size:.72rem;line-height:1.35;overflow-wrap:anywhere}
.avatar-choice[aria-pressed="true"]{border-color:var(--accent);background:var(--accent-dim)}
.avatar-choice[aria-pressed="true"]::after{content:'✓';position:absolute;top:2px;right:2px;border-radius:50%;background:var(--accent);color:var(--on-accent);width:22px;height:22px;font-weight:bold}
.avatar-actions{display:flex;gap:10px;justify-content:space-between;margin-top:12px}
.avatar-actions button{min-height:46px}
@media(max-width:480px){.avatar-grid{grid-template-columns:repeat(3,minmax(0,1fr))}.avatar-choice .profile-portrait{width:58px;height:58px}.avatar-picker{padding:12px}.avatar-actions button{min-width:0;white-space:normal}}
.profile-identity{display:flex;align-items:center;gap:14px;padding:16px;margin:18px 0;border:1px solid var(--rule);border-radius:20px;background:var(--card)}
.identity-avatar{display:flex;flex:none;flex-direction:column;align-items:center;gap:6px;min-width:76px;padding:4px;border:0;border-radius:14px;background:transparent;color:var(--accent);font:inherit;cursor:pointer}
.identity-avatar .prof-ava{width:72px;height:72px;font-size:1.7rem;margin:0}
.identity-avatar-caption{font-size:.78rem;font-weight:600}
.profile-identity .prof-who{margin:0;padding:8px 0;min-width:0;flex:1;border:0;box-shadow:none;background:transparent;text-align:left;border-radius:10px}
.profile-identity .prof-who:disabled{opacity:1;color:var(--ink);cursor:default}
.profile-identity .prof-who-text{overflow-wrap:anywhere}
.profile-identity .identity-action{color:var(--accent);font-weight:600;margin-top:8px}
.identity-guest{min-width:0;flex:1}.identity-guest small{display:block;color:var(--ink-soft);margin-top:5px}
.identity-guest[hidden],.identity-action[hidden]{display:none}
.identity-avatar:focus-visible,.profile-identity .prof-who:focus-visible{outline:3px solid var(--accent);outline-offset:3px}
@media(max-width:380px){.profile-identity{gap:10px;padding:12px}.identity-avatar{min-width:64px}.identity-avatar .prof-ava{width:60px;height:60px}}
@media(max-width:480px){.avatar-filters{flex-wrap:nowrap;overflow-x:auto;padding:3px 2px 8px;scrollbar-width:thin;max-width:100%}.avatar-filters .chip{flex:none}}
/* The banner shows a complete scene, never a face crop. */
.home .banner{background:linear-gradient(110deg,var(--card) 45%,var(--accent-dim))}
.home .banner-text b,.home .banner-text small{color:var(--ink)}
:root .home .home-art{display:block;width:230px;height:185px;object-fit:contain;object-position:center;border-radius:0;background:transparent}
.skin-card[data-skin="girl"] img{object-fit:contain;background:var(--accent-dim)}
.home-art[src$="theme-reading.png"]{mask-image:linear-gradient(to right,transparent,#000 8%,#000 92%,transparent),linear-gradient(to bottom,transparent,#000 8%,#000 92%,transparent);mask-composite:intersect;-webkit-mask-image:linear-gradient(to right,transparent,#000 8%,#000 92%,transparent),linear-gradient(to bottom,transparent,#000 8%,#000 92%,transparent);-webkit-mask-composite:source-in}
@media(max-width:600px){
 .home .banner{grid-template-columns:minmax(0,1fr) 46%;gap:10px 12px}
 .home .banner .ring{display:none}
 .home .banner-text{display:contents}
 .home .home-heading{grid-column:1/-1;grid-row:1;font-size:clamp(19px,4.8vw,23px);margin:0}
 .home #bannerTitle{grid-column:1;grid-row:2;align-self:end}
 .home #bannerNote{grid-column:1;grid-row:3;align-self:start}
 :root .home .home-art{grid-column:2;grid-row:2/span 2;width:100%;height:150px;align-self:center}
}
/* Shared, locally drawn navigation pictograms; lesson content is untouched. */
.illustrated-icon{display:grid;place-items:center;flex:none;width:56px;height:56px;border-radius:17px;background:#F0F5FC;color:#294767;line-height:1;font-style:normal}
.illustrated-icon svg{display:block;width:46px;height:46px;overflow:visible}
#viewHome .tile{grid-template-columns:64px minmax(0,1fr) auto}
#viewHome .tile em.illustrated-icon{width:64px;height:64px;border-radius:18px;background:#F0F5FC}
#viewHome .tile em.illustrated-icon svg{width:52px;height:52px}
.album-link .album-ico.illustrated-icon{width:56px;height:56px;font-size:inherit}
.today-row em.illustrated-icon{width:48px;height:48px}.today-row em.illustrated-icon svg{width:40px;height:40px}
.illustrated-row{gap:14px;min-height:88px}.illustrated-row>div{min-width:0;flex:1}
.top-actions .app-icon{width:28px;height:28px;stroke-width:2}
:root[data-theme="dark"] .top-actions .icon-btn{color:var(--ink)}
@media(prefers-color-scheme:dark){:root:not([data-theme="light"]) .top-actions .icon-btn{color:var(--ink)}}
@media(max-width:480px){#viewHome .tile{grid-template-columns:56px minmax(0,1fr) auto;gap:12px}#viewHome .tile em.illustrated-icon{width:56px;height:56px}#viewHome .tile em.illustrated-icon svg{width:46px;height:46px}.illustrated-row{gap:12px}.illustrated-row .illustrated-icon{width:50px;height:50px}.illustrated-row .illustrated-icon svg{width:42px;height:42px}}
/* Шапка называет экран (владелец 21.09), и длинное название при крупном
   тексте резалось многоточием: «Слушай по-китайс…» на 320 при 200 %.
   Название — подпись экрана, а не текст задания: ограничиваем его долей
   ширины, чтобы оно помещалось целиком. На главной — имя приложения. */
body:not(.at-home) #brandTitle { font-size: 1.06rem; font-size: min(1.18rem, 5.6vw); }

/* Полный выбор символов без случайной пятёрки; поле письма остаётся рядом. */
#tracePicker{width:100%;margin:12px 0;text-align:left;border:1px solid var(--rule);border-radius:14px;background:var(--paper)}
#tracePicker summary{min-height:48px;padding:12px;cursor:pointer;font-weight:700}
#tracePicker summary:focus-visible{outline:3px solid var(--accent);outline-offset:2px}
#traceChoices{display:grid;grid-template-columns:repeat(auto-fit,minmax(44px,1fr));gap:6px;padding:8px;margin:0}
#traceChoices .chip{min-width:44px;min-height:44px;margin:0;padding:8px}

/* Catalogue hierarchy: keep the user's text scale, give large type wider
   cards instead of squeezing three tall columns into the same space. */
#viewHome .tiles { grid-template-columns: repeat(auto-fit,minmax(min(100%,max(17rem,calc((100% - 28px) / 3))),1fr)); }
#viewHome .tile { align-items: start; padding: 18px; }
#viewHome .tile > div { gap: 6px; }
#viewHome .tile b { font-family: var(--font-body); font-size: 1rem; font-weight: 650; line-height: 1.25; }
#viewHome .tile small { font-size: .875rem; line-height: 1.4; overflow-wrap: anywhere; }
#viewHome .tile small.fun-progress { font-size: .8rem; font-weight: 600; line-height: 1.35; margin-top: 3px; }
#tileTabs .tab-btn { font-family: var(--font-body); font-size: .875rem; font-weight: 600; line-height: 1.3; gap: 3px 9px; }
#tileTabs .tab-btn b { font-size: .78em; font-weight: 500; opacity: .85; }
#viewHome .sec-label { font-size: .875rem; font-weight: 600; letter-spacing: 0; }
#ageAsk .chips { gap: 8px; }
#ageAsk .chip { font-size: .9rem; font-weight: 600; line-height: 1.3; min-height: 44px; padding: 10px 14px; }
@media(max-width:600px){
  #viewHome .tiles { grid-template-columns: minmax(0,1fr); }
  #viewHome .tile { padding: 16px; }
  #viewHome .tile > div { display: contents; }
  #viewHome .tile em { grid-row: 1; }
  #viewHome .tile b { grid-column: 1 / -1; align-self: center; font-size:min(1rem,10cqi); }
  #viewHome .tile small, #viewHome .tile i { grid-column: 1 / -1; }
  #viewHome .tile small { font-size:min(.875rem,8.8cqi); }
  #viewHome .tile small.fun-progress { font-size:min(.8rem,8cqi); }
}


/* One clear starting point; parent controls remain separate from activities. */
.home-start { display:grid; gap:12px; }
.home-start h2 { margin:0; font-size:1.2rem; line-height:1.3; }
.home-suggestions { display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:14px; }
.home-suggestion { display:flex; flex-direction:column; align-items:flex-start; text-align:left; gap:8px; padding:20px; background:var(--paper); border:1px solid var(--rule); border-radius:20px; min-width:0; }
.home-suggestion:first-child { border:2px solid var(--accent); }
.home-suggestion b { font-size:1.15rem; line-height:1.3; overflow-wrap:anywhere; }
.home-suggestion small { font-size:.875rem; line-height:1.4; color:var(--ink-soft); }
.home-suggestion .start-label { color:var(--accent); font-weight:650; }
.parent-home { padding:14px 18px; border:1px solid var(--rule); border-radius:16px; }
.parent-home summary { cursor:pointer; font-size:1rem; font-weight:600; min-height:44px; display:flex; align-items:center; gap:10px; flex-wrap:wrap; }
.parent-home summary::before { content:'▸'; }
.parent-home[open] summary::before { content:'▾'; }
.parent-home summary small { font-weight:400; font-size:.85rem; color:var(--ink-soft); }
.parent-home .age-ask { box-shadow:none; margin:12px 0; }
.parent-home button.parent-settings { margin-top:12px; font-size:.9rem; min-height:44px; }
/* Сообщество для родителей (07.10): ссылкой, не кнопкой — уводит из приложения. */
.parent-home a.parent-vk { display:flex; align-items:center; min-height:44px; margin-top:4px; font-size:.9rem; color:var(--ink-soft); }
#viewHome .tile i { font-size:.75rem; font-weight:500; }
@media(max-width:760px){ .home-suggestions { grid-template-columns:1fr; } .home-suggestion { padding:16px; } #catalogPicker { position:sticky; top:0; z-index:5; background:var(--paper); padding-block:8px; } }
/* Прилипает только свёрнутый выбор разделов (30.09): раскрытый при крупном
   тексте выше экрана — на 375 при ×2 он 829 точек при экране 812 — и, прилипнув,
   закрывал плитки целиком: занятие было не открыть (test-big-text-narrow). */
@media(max-width:760px){ #catalogPicker.is-open { position: static; } }

/* Шрифты главной растут вместе с «Крупным текстом» (11.10, владелец со
   снимком «шрифт»). На компьютере заголовок «Что откроем сегодня?» был
   задан в пикселях — clamp(23px, 2.4vw, 31px) — и при тексте ×2 оставался
   31 px, мельче «С чего начнём?» (38) и вопроса о классе (34). Подписи под
   значками верхнего ряда были 10 px при любом размере. Теперь заголовок в
   rem (при ×1 те же 31 px, при ×2 — самый крупный на экране), подписи растут
   до 14 px: крупнее верхний ряд перестаёт помещаться. На телефоне заголовок
   задаёт constructor.css (1.25rem) — его не трогаем. */
body:not(.lesson-open) .top-actions .icon-btn::after { font-size: clamp(10px, .62rem, 14px); }
.home-start h2 { font-family: var(--font-display); }
@media (min-width: 601px) {
  #viewHome .home-heading { font-size: clamp(1.45rem, 1rem + 1vw, 1.95rem); }
  #viewHome .banner-text b { font-size: .95rem; }
  #viewHome .banner-text small { font-size: .9rem; }
}
