
  /* Дизайн - вариант 4 «швейцарский ч/б» (выбор Даниила, TG 6787,
     макет _tmp/miniapp_mockups/v4_swiss_mono.html): белый фон, чёрные линии,
     красный акцент, прямые углы, капс в заголовках. */
  :root{
    --ink:#111111;
    --ink-2:#555555;
    --ink-3:#777777;
    --red:#e0342b;
    --accent:var(--red);
    --bg:#f2f2f0;
    --card:#ffffff;
    --field:#ffffff;
    --drop:#ffffff;
  }
  /* Тёмная тема Telegram: та же графика в негативе, красный чуть ярче.
     Карта рисуется под светлый фон, поэтому .chart-card всегда светлая. */
  body.dark{
    --ink:#f2f2f0;
    --ink-2:#b5b5b5;
    --ink-3:#8a8a8a;
    --red:#ff5148;
    --bg:#0d0d0d;
    --card:#191919;
    --field:#191919;
    --drop:#222222;
  }
  *{box-sizing:border-box;margin:0;padding:0;-webkit-font-smoothing:antialiased}
  /* Кнопки с display:block иначе перебивают атрибут hidden. */
  [hidden]{display:none!important}
  html{min-height:100%}
  body{
    font-family:"Helvetica Neue",-apple-system,BlinkMacSystemFont,Arial,sans-serif;
    color:var(--ink);
    background:var(--bg);
    display:flex;justify-content:center;
  }
  .app{
    width:100%;max-width:480px;min-height:100vh;
    display:flex;flex-direction:column;
    padding:0 22px;background:var(--card);
    /* В полноэкранном режиме (TG 7279) статус-бар телефона и кнопки
       Telegram ложатся поверх страницы: --tg-top считает и выставляет JS
       (applyInsets); вне полного экрана там 0. */
    padding-top:var(--tg-top, 0px);
  }
  header{
    padding:24px 0 12px;border-bottom:3px solid var(--ink);
    display:flex;align-items:baseline;justify-content:space-between;
  }
  .logo{font-size:15px;font-weight:700;letter-spacing:-.02em;
    display:flex;align-items:center;gap:7px}
  .logo b{color:var(--red)}
  /* Знак-сакрал с каналами из аватарки (Даниил, TG 7151-7185): хвостики
     всех ворот одной длины, 34 и боковые 27/59 укорочены до неё же.
     Цвета - переменными темы. */
  .logo-mark{width:21px;height:19px;flex:0 0 auto}
  .hello{padding:26px 0 0}
  .hello :is(h1,h2){font-size:34px;line-height:1;font-weight:800;letter-spacing:-.04em;text-transform:uppercase}
  .hello :is(h1,h2) span{color:var(--red)}
  .hello p{margin-top:10px;font-size:12px;line-height:1.5;color:var(--ink-3)}
  main{padding:6px 0 18px}
  .cap{
    font-size:10px;font-weight:700;letter-spacing:.14em;text-transform:uppercase;
    color:var(--ink);padding:24px 0 2px;
  }
  /* Над столбиком разделов - крупное «Списки:» вместо мелкого счётчика карт
     (Даниил, TG 7953/7955): иначе кнопка «← Все списки» внутри раздела
     возвращает непонятно куда: слова «списки» человек до этого не видел.
     Число карт уехало
     строкой под столбик: над списками оно говорило не о том, что ниже. */
  .cap.lists{font-size:22px;letter-spacing:-.02em;text-transform:none;
             font-weight:800;padding-bottom:6px}
  /* Шапки двух групп под бодиграфом (Даниил, TG 8114): крупнее и по центру -
     иначе «Краткие описания» читалось как ещё одна строка раздела, а не как
     название группы. Двоеточие рисуем стилем: в тексте его нет, иначе
     пришлось бы держать в словаре перевода вариант с ним. */
  .cap.group{font-size:14px;letter-spacing:.1em;text-align:center;
             padding:26px 0 8px}
  .cap.group::after{content:':'}
  .item{
    display:flex;align-items:center;gap:12px;width:100%;
    padding:13px 0;
    background:none;border:0;border-bottom:1px solid var(--ink);
    font:inherit;color:inherit;text-align:left;cursor:pointer;
  }
  .item[disabled]{cursor:default;opacity:.75}
  /* Выбор, кого убрать из списка (Даниил, TG 7998): квадратик слева,
     у отмеченного - красный крестик. Пустой квадрат сам говорит, что
     строку можно отметить, а не что нажатие уже что-то сделало. */
  .pick-box{flex:0 0 auto;width:20px;height:20px;
            border:2px solid var(--ink-3);border-radius:4px;
            display:flex;align-items:center;justify-content:center;
            font-size:13px;font-weight:800;line-height:1;color:var(--red)}
  .item.picked .pick-box{border-color:var(--red)}
  /* Выбранный первый участник композита (Даниил, TG 6969): красная
     подсветка вместо строки «Первый: …» - список остаётся неподвижным. */
  .item.sel{color:#d33}
  /* Карты человека, раскрытые «плюсиком» в «Все карты по людям» (TG 7142). */
  .item.sub{padding-left:24px}
  .txt{flex:1 1 auto;min-width:0}
  .txt b{display:block;font-size:15px;font-weight:500;letter-spacing:-.01em;line-height:1.3;
         overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .txt i{display:block;font-style:normal;font-size:11px;color:var(--ink-3);margin-top:2px}
  /* Шапка экрана списка: «← Все списки», название раздела по центру
     следующей строкой (Даниил, TG 7131/7133 - отмена одной строки
     из TG 7057), блок отбит сверху от верхних кнопок экрана (TG 7052).
     Название крупно (Даниил, TG 7832 - для своих списков, TG 7941 - для
     «по людям» и «композитов»): это такие же разделы, и открытый раздел
     должно быть видно с первого взгляда. */
  .lists-head{margin:18px 0 0}
  /* «Все списки» чёрным, а не серым (Даниил, TG 7949): серая рамка читалась
     как неактивная кнопка, хотя это единственный выход с экрана раздела. */
  .lists-head .back-btn,
  .list-foot .back-btn{color:var(--ink);border-color:var(--ink)}
  .lists-head .back-btn{margin:0}
  .lists-head .cap{padding:0;margin-top:12px;text-align:center;
                   overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
                   font-size:22px;font-weight:800;letter-spacing:-.02em;
                   text-transform:none;color:var(--ink)}
  .list-dl{display:block;margin:6px auto 0;padding:4px 8px;background:none;border:0;
    font:inherit;font-size:13px;color:var(--ink-2);text-decoration:underline;cursor:pointer}
  .list-dl:disabled{text-decoration:none;cursor:default}
  .list-bar{display:flex;gap:8px;margin:14px 0 4px}
  /* !important - иначе второй кнопке достаётся margin-top от общего правила
     `.back-btn:not(:first-child)` и она стоит ниже соседки (Даниил, TG 7998:
     «пусть они будут одного размера»). */
  .list-bar .back-btn{flex:1;margin:0 !important;text-align:center}
  /* Красная заливка у удаления (Даниил, TG 7998): действие необратимо
     для состава списка, и оно должно отличаться от «Отмены» с первого взгляда. */
  .list-bar .back-btn.red{background:var(--red);border-color:var(--red);color:#fff}
  /* Без эмодзи (Даниил, TG 7840-7842): рамка у эмодзи внутри рамки кнопки
     давала рамку в рамке. Подпись по центру. */
  .list-bar .item.act{flex:1;padding:7px 8px;justify-content:center;
                      border:2px solid var(--ink-3);border-radius:5px}
  .list-bar .item.act .txt{flex:0 1 auto}
  .list-bar .item.act .txt b{white-space:normal;text-align:center}
  /* Хвост длинного состава (Даниил, TG 7832): после десятка человек
     возвращаться прокруткой неудобно - «Все списки» слева, «В начало» по центру. */
  .list-foot{display:grid;grid-template-columns:1fr auto 1fr;
             align-items:center;margin-top:22px}
  .list-foot .back-btn{margin:0}
  .list-foot .back-btn:first-child{justify-self:start}
  /* Служебные кнопки экрана списка отделены от карт людей (Даниил, TG 7046):
     блок ниже с зазором, строки мельче и серым без жирного - люди остаются
     главным содержимым, административное не шумит. */
  /* «Или добавить…» на экране пополнения списка - крупно, как строки-кнопки:
     серая сноска терялась (Даниил, TG 7062). */
  .list-or{padding:22px 0 4px;font-size:15px;font-weight:700}
  .list-admin{margin-top:26px}
  .list-admin .item{padding:9px 0;border-bottom:0}
  .list-admin .txt b{font-size:13px;font-weight:400;color:var(--ink-2)}
  .list-admin .chip{color:var(--ink-3)}
  /* Строки-действия (Даниил, TG 7654-7657): без стрелки - это не переход
     вглубь; эмодзи в квадратной рамке, у опасного - красной. */
  .item.act{padding:7px 0}
  .act-ico{
    flex:0 0 auto;width:30px;height:30px;display:flex;
    align-items:center;justify-content:center;
    border:1.5px solid var(--ink);border-radius:5px;font-size:14px;
  }
  .item.act.danger .act-ico{border-color:var(--red)}
  .item.act.danger .txt b{color:var(--red)}
  .chip{
    flex:0 0 auto;
    color:var(--ink);font-size:15px;font-weight:700;background:none;
  }
  /* Дата рождения справа (Даниил, TG 7937): моноширинные цифры, чтобы
     даты стояли ровным столбиком, а не плясали по ширине знака. */
  .when{flex:0 0 auto;margin-left:10px;font-size:13px;color:var(--ink-2);
        font-variant-numeric:tabular-nums}
  .note{padding:24px 0;font-size:13px;line-height:1.6;color:var(--ink-2)}
  .note.err{color:var(--red)}
  /* Пустой поиск внутри списка (Даниил, TG 7982): под объяснением - выход
     на все карты, иначе пустой экран читается как «такой карты нет вообще». */
  .note.out{padding-bottom:0}
  .out-btn{margin:10px 0 24px;padding:10px 14px;background:none;color:var(--ink);
    border:1px solid var(--ink);border-radius:5px;font:inherit;font-size:13px;
    font-weight:700;cursor:pointer}
  /* Строчка политики под кнопкой согласия (Даниил, TG 7695): согласие даётся
     осознанно, значит текст, на который соглашаются, должен быть под рукой.
     Прячется вместе со своей кнопкой - соседним селектором, без JS. */
  .policy-line{padding:6px 2px 0;font-size:12px;color:var(--ink-2);text-align:center}
  .policy-line a{color:inherit}
  button[hidden]+.policy-line{display:none}
  footer{
    margin-top:auto;
    padding:20px 0 26px;
    display:flex;justify-content:space-between;align-items:center;
    border-top:3px solid var(--ink);
    font-size:10px;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-3);
  }
  .dot{width:5px;height:5px;background:var(--red);
       display:inline-block;margin-right:6px;vertical-align:1px}
  /* Просмотр карты: бодиграф всегда полноразмерный, без превью и «увеличить»
     (Даниил, 01.09.2026, TG 6704/6711). */
  #chart-view{
    position:fixed;inset:0;z-index:10;overflow-y:auto;
    /* Оверлей position:fixed не наследует отступ .app - запас сверху свой
       (Даниил, TG 7296: «на других экранах сжирает сверху»). */
    background:var(--card);padding:calc(14px + var(--tg-top, 0px)) 10px 24px;
  }
  #chart-view[hidden]{display:none}
  /* Кнопка «← Назад» - контурная, а не голая строка текста: голубую строку
     было легко не заметить (Даниил, TG 6976). Красная и крупнее - чёрный
     контур всё ещё терялся среди остальных кнопок (Даниил, TG 6988). */
  /* Навигация серая, чёрное - действия, красным только опасное («Удалить»
     и подтверждение): красный «Назад» рядом с чёрным «Да, удалить» сбивал,
     а чёрный сливался с «Сохранить» (Даниил, TG 7222-7236). */
  .back-btn{
    display:inline-block;margin:0 0 10px 0;padding:10px 16px;
    background:var(--card);border:2px solid var(--ink-3);border-radius:5px;
    font:inherit;font-size:13px;font-weight:700;text-transform:uppercase;
    letter-spacing:.04em;color:var(--ink-3);cursor:pointer;
  }
  /* «Назад» не первым в блоке отступает сверху - не липнет к кнопке
     над собой; таких мест несколько (Даниил, TG 7217). */
  .back-btn:not(:first-child){margin-top:12px}
  #support-fab{position:fixed;right:16px;bottom:max(16px,env(safe-area-inset-bottom));z-index:15;
    width:50px;height:50px;padding:0;border-radius:50%;background:var(--card);
    border:1.5px solid var(--line,var(--ink-3));color:var(--accent);cursor:pointer;
    display:flex;align-items:center;justify-content:center;box-shadow:0 4px 14px rgba(0,0,0,.14)}
  #support-fab .ui-icon{width:26px;height:26px}
  body:has(#settings-view:not([hidden])) #support-fab{display:none}
  #support-dialog{margin:auto;width:calc(100% - 32px);max-width:440px;max-height:90dvh;
    overflow:auto;padding:24px;border:1px solid var(--line);border-radius:20px;
    background:var(--card);color:var(--ink)}
  #support-dialog::backdrop{background:#0007}
  #support-dialog .settings-panel{padding:0;margin:0;border:0;background:none}
  #support-dialog-close{margin-top:14px}
  /* В полном экране верхний «Назад» уезжает в полосу пилюль Telegram,
     правее штатной стрелки, и остаётся одной стрелкой (Даниил, TG 7881):
     полоса всё равно зарезервирована под пилюли, а экран выигрывает
     ~50 px сверху. Рамки и фона нет (Даниил, TG 7894) - одна стрелка
     на всякий случай, основную работу делает штатная «Назад». Отступ
     98px - сразу за пилюлей «‹ Назад» (она кончается на ~94px, TG 7893),
     по высоте вровень с её серединой: стрелка так указывает на штатную
     кнопку, а не висит сама по себе (Даниил, TG 7897, 7904).
     Вне полного экрана полосы нет - кнопка остаётся обычной строкой
     в потоке. */
  body.fs .back-btn.top{
    position:fixed;left:98px;top:calc(var(--tg-top, 0px) - 38px);
    margin:0;padding:4px 10px;background:none;border:0;
    font-size:22px;line-height:1;z-index:30}
  body.fs .back-btn.top .lbl{display:none}
  /* Правка сохранённой натальной карты прямо из просмотра: имя, дата,
     время, город - те же поля, что в «Редактировать» у бота. */
  /* Зазор под панелью: карта не липнет к «Назад» (Даниил, TG 7171). */
  #chart-bar{display:flex;gap:8px;align-items:center;margin-bottom:12px}
  #chart-bar #chart-back{margin-bottom:0}
  /* В полном экране «Назад» уехала в полосу пилюль, и панель осталась
     пустой - её зазор карте больше не нужен. */
  body.fs #chart-bar{margin-bottom:0}
  /* «Редактировать» и «Удалить» - квадратики справа от «Скачать карту»
     (Даниил, TG 7533): карандаш в серой рамке, корзинка в красной. */
  #chart-dl-row{display:flex;gap:8px;align-items:stretch;max-width:480px;margin:10px auto 0}
  #chart-dl-row .save-btn{flex:1;margin:0}
  /* display:contents: кнопка композита/цикла из dl-box встаёт в общий
     флекс-ряд, а пустой dl-box у натальной карты места не занимает. */
  #chart-dl-box{display:contents}
  /* Меню «Поделиться» (Даниил, TG 9686-9688): картинкой или ссылкой на карту,
     под рядом кнопок; ссылка - как у приглашения: поле, «кому», «скопировать». */
  .share-menu{max-width:480px;margin:8px auto 0}
  .share-menu .btn-row .save-btn{flex:1;margin:0}
  .share-menu .field{margin-top:8px}
  .share-menu .save-btn.share-out{margin-top:8px}
  .share-menu .share-note{margin:8px 0 0;font-size:12.5px;color:var(--ink-2);text-align:center}
  /* Карта, открытая по ссылке: строка «N поделился(лась) с вами…» над бодиграфом. */
  #chart-shared{max-width:480px;margin:0 auto 10px}
  #chart-shared .invite-send-s{margin:0;font-size:13px;line-height:1.4;color:var(--ink-2)}
  #chart-shared .calc-go{margin-top:8px}
  /* «Скачать карту» и «Поделиться» в один ряд под любой картой (Даниил,
     TG 8717-8724); внутри chart-dl-box ряд растворяется в общий флекс. */
  .dl-row{display:flex;gap:8px;margin-top:12px}
  .dl-row .save-btn{flex:1;margin:0;padding:12px 8px;font-size:12px;flex-wrap:wrap}
  /* «Поделиться» - одно слово: общий overflow-wrap:anywhere у .ui-label рвал его
     на «Поделит-ься» (Даниил, TG 8736); пусть лучше уйдёт под значок целиком. */
  .dl-row .save-btn .ui-label{overflow-wrap:normal}
  #chart-dl-box .dl-row{display:contents}
  #chart-plain-bar{display:flex;align-items:center;gap:8px;max-width:480px;margin:10px auto 0}
  /* Полоска исчезает целиком, когда скрыты и тумблер, и обе кнопки. */
  #chart-plain-bar:not(:has(#chart-plain-row:not([hidden]),#chart-edit:not([hidden]),#chart-del:not([hidden]))){display:none}
  #chart-plain-row{flex:1;margin:0}
  #chart-actions{display:flex;gap:8px;margin-left:auto}
  #chart-edit,#chart-del{
    flex:0 0 auto;width:45px;height:45px;padding:0;margin:0;border-radius:5px;
    display:flex;align-items:center;justify-content:center;
    font:inherit;font-size:18px;cursor:pointer;
  }
  #chart-edit[hidden],#chart-del[hidden]{display:none}
  #chart-edit{background:var(--card);border:2px solid var(--ink-3)}
  #chart-del{background:none;color:var(--red);border:2px solid var(--red)}
  #chart-bottom-bar{display:flex;gap:8px;max-width:480px;margin:16px auto 0}
  #chart-bottom-bar .back-btn{margin:0}
  /* «Сохранить как свой бодиграф / это не мой» - живёт внутри формы
     «Редактировать» (Даниил, TG 6930): под именем в просмотре кнопка
     путала - непонятно, сохранён бодиграф или нет. Контурная, чтобы
     красная «Сохранить» формы оставалась главной. */
  #chart-mine-btn{
    display:block;width:100%;margin-top:8px;padding:9px 14px;
    background:none;color:var(--ink);border:1px solid var(--ink);
    font:inherit;font-size:13px;cursor:pointer;border-radius:5px;
  }
  #chart-mine-note{max-width:480px;margin:6px auto 0;font-size:12.5px;color:var(--ink-2);text-align:center}
  /* Карандаш-квадратик у имени - открывает весь блок редактора
     (Даниил, TG 7533). */
  #chart-name-row{
    display:flex;align-items:center;gap:8px;max-width:480px;margin:0 auto 8px;
    padding:4px 2px;
  }
  /* Имя не растягивается на всю строку: карандаш стоит сразу за ним,
     а не у правого края (Даниил, TG 7074). */
  #chart-name-row b{
    flex:0 1 auto;min-width:0;font-size:15px;font-weight:700;
    overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  }
  #chart-rename-btn{
    flex:0 0 auto;width:32px;height:32px;padding:0;
    display:flex;align-items:center;justify-content:center;
    background:var(--card);border:2px solid var(--ink-3);border-radius:5px;
    font:inherit;font-size:14px;cursor:pointer;
  }
  /* Подтверждение удаления - в два шага, как в боте (_lib_delete_kb):
     по кнопке промахиваются, а карта пропадает без возврата. */
  #del-confirm{
    max-width:480px;margin:10px auto 0;
    border:2px solid var(--ink);border-radius:5px;padding:12px 16px;
  }
  #del-confirm p{font-size:13.5px;margin-bottom:10px}
  #del-confirm .del-row{display:flex;gap:8px}
  /* Не заливка, а красная обводка и шрифт (Даниил, TG 7248);
     --red в тёмной теме свой, на тёмном фоне читается. */
  #del-yes{
    flex:1;padding:8px;background:none;color:var(--red);
    border:2px solid var(--red);border-radius:5px;
    font:inherit;font-size:13px;font-weight:700;text-transform:uppercase;
    letter-spacing:.04em;cursor:pointer;
  }
  #del-no{
    flex:1;padding:9px;background:none;color:var(--ink);
    border:1px solid var(--ink);border-radius:5px;
    font:inherit;font-size:13px;cursor:pointer;
  }
  #edit-form{
    max-width:480px;margin:0 auto 12px;
    border:2px solid var(--ink);padding:4px 16px 16px;
  }
  #edit-save{
    display:block;width:100%;margin-top:14px;padding:9px 14px;
    background:var(--red);color:#fff;border:0;
    font:inherit;font-size:13px;font-weight:700;text-transform:uppercase;
    letter-spacing:.04em;cursor:pointer;
  }
  #edit-note{max-width:480px;margin:0 auto 8px;font-size:12.5px;color:var(--ink-2);text-align:center}
  .chart-card{background:#ffffff;border:1px solid #111;padding:8px 4px}
  .chart-card svg{display:block;width:100%;height:auto}
  /* Полноэкранный просмотр: масштабируется только карта, не значки управления. */
  #zoom-view{
    position:fixed;inset:0;z-index:60;background:#ffffff;
    overflow:hidden;touch-action:none;
    display:flex;align-items:center;justify-content:center;
    padding:calc(80px + var(--tg-top, 0px)) 12px 90px;box-sizing:border-box;
  }
  #zoom-body{flex:none;user-select:none;transform-origin:center}
  #zoom-body > svg{display:block;width:100%;height:100%;max-height:none}
  #zoom-body.zoomed{cursor:grab}#zoom-view.panning #zoom-body{cursor:grabbing}
  #zoom-close > svg{width:20px;height:20px;max-height:none}
  #zoom-controls{position:absolute;bottom:38px;left:50%;transform:translateX(-50%);z-index:61;display:flex;align-items:center;gap:6px;padding:6px;border:1px solid var(--line);border-radius:14px;background:var(--card);color:var(--ink)}
  #zoom-controls button{min-width:44px;min-height:44px;padding:8px 12px;border:1px solid var(--line);border-radius:10px;background:var(--card);color:var(--ink);font:inherit;cursor:pointer}
  #zoom-controls button:disabled{opacity:.4;cursor:default}
  /* Системный зум страницы (TG 9548): пинч с пальцем на кнопке не отдаём
     браузеру, а панель в узкой видимой области переносится по строкам. */
  #zoom-view button{touch-action:none}
  #zoom-controls{flex-wrap:wrap;justify-content:center;max-width:calc(100% - 24px)}
  #zoom-download > svg{display:block;width:20px;height:20px;margin:auto}
  #zoom-level{min-width:42px;text-align:center;font-size:12px}
  #zoom-close{
    position:absolute;top:calc(12px + var(--tg-top, 0px));right:12px;z-index:61;
    height:38px;padding:0 14px 0 10px;display:inline-flex;align-items:center;gap:8px;
    background:#ffffff;border:1px solid #111;color:#111;
    font:inherit;font-size:19px;cursor:pointer;
  }
  #zoom-hint{
    position:absolute;bottom:10px;left:0;right:0;z-index:61;
    text-align:center;font-size:12px;color:#777;pointer-events:none;
  }
  /* Этап 2: «мой бодиграф» — заметная карточка над списком, открывает свою
     карту в один тап. Сама карта остаётся и в общем списке, это шорткат. */
  .mine-card{
    display:flex;align-items:center;gap:12px;width:100%;margin:22px 0 0;
    padding:14px 16px;
    background:none;border:2px solid var(--ink);
    font:inherit;color:var(--ink);text-align:left;cursor:pointer;
  }
  .mine-card .ava{flex:0 0 auto;color:var(--red);font-size:18px}
  .mine-card .txt b{white-space:normal;font-weight:700;text-transform:uppercase;letter-spacing:.02em}
  /* Этап 2: форма расчёта (дата → время → город, как в боте). */
  .calc-open{
    display:block;width:100%;margin:12px 0 4px;padding:15px 16px;
    background:var(--red);color:#fff;
    border:0;
    font:inherit;font-size:14px;font-weight:700;text-transform:uppercase;
    letter-spacing:.06em;cursor:pointer;
  }
  #calc-view{
    position:fixed;inset:0;z-index:10;overflow-y:auto;
    background:var(--card);padding:calc(14px + var(--tg-top, 0px)) 10px 40px;
  }
  #calc-view[hidden]{display:none}
  /* Композит: тот же приём полноэкранного оверлея, что у #calc-view - без
     position:fixed блок иначе встаёт в ряд с .app внутри body{display:flex}
     (баг тестировщика, 02.09.2026: карта пары рисовалась узкой колонкой
     рядом со списком, а не поверх него). */
  #pair-view{
    position:fixed;inset:0;z-index:10;overflow-y:auto;
    background:var(--card);padding:calc(14px + var(--tg-top, 0px)) 10px 40px;
  }
  #pair-view[hidden]{display:none}
  /* Приглашение друга - тот же полноэкранный оверлей, что у #calc-view
     и #pair-view. */
  #invite-view{
    position:fixed;inset:0;z-index:10;overflow-y:auto;
    background:var(--card);padding:calc(14px + var(--tg-top, 0px)) 10px 40px;
  }
  #invite-view[hidden]{display:none}
  /* Текущий транзит - такой же полноэкранный оверлей. */
  #transit-view{
    position:fixed;inset:0;z-index:10;overflow-y:auto;
    background:var(--card);padding:calc(14px + var(--tg-top, 0px)) 10px 40px;
  }
  #transit-view[hidden]{display:none}
  /* На компе окно мини-аппа шире телефона - контент оверлеев держим
     в колонке 480px по центру, как .app, а не растягиваем на весь экран
     (Даниил, TG 7553). Пинч-зум (#zoom-view) остаётся полноэкранным -
     «кому надо, сами растянут». */
  #chart-view,#calc-view,#pair-view,#invite-view,#transit-view{
    padding-left:max(10px,calc(50vw - 240px));
    padding-right:max(10px,calc(50vw - 240px));
  }
  /* Настройки - такой же полноэкранный оверлей. */
  #settings-view{
    position:fixed;inset:0;z-index:10;overflow-y:auto;
    background:var(--card);padding:calc(14px + var(--tg-top, 0px)) 10px 40px;
  }
  #settings-view[hidden]{display:none}
  /* Встраивание на своих сайтах (iframe, body.embed ставит сервер): та же
     страница без шапки-логотипа, входа и сохранения - куки третьей стороны
     во фрейме не доезжают, а высоту рамке задаёт родитель по postMessage,
     поэтому экраны не оверлеи, а обычный поток документа. Настройки (EN/RU)
     остаются в шапке. Заменило прежнюю короткую форму 13.09.2026 (TG 8762/8766). */
  body.embed{display:block}
  body.embed .app{min-height:0;margin:0 auto}
  body.embed .app>header .logo{visibility:hidden}
  body.embed .hello,body.embed #web-login-open,body.embed #tg-link-banner,
  body.embed #web-install-open,body.embed #invite-open,body.embed #support-fab,
  body.embed #calc-or,body.embed #calc-fork,body.embed #save-btn,body.embed #consent-btn,
  body.embed #save-pick,body.embed #save-note{display:none}
  body.embed #chart-view,body.embed #calc-view,body.embed #pair-view,body.embed #invite-view,
  body.embed #transit-view,body.embed #settings-view{position:static;overflow:visible}
  body.embed:has(#chart-view:not([hidden]),#calc-view:not([hidden]),#pair-view:not([hidden]),
    #invite-view:not([hidden]),#transit-view:not([hidden]),#settings-view:not([hidden])) .app>:not(header){display:none}
  /* Удаление аккаунта (Даниил, TG 7724): красное слово внизу настроек,
     не кнопка - действие редкое и опасное, кнопкой оно зазывает. */
  #set-del{margin-top:22px;text-align:center}
  .del-acc{background:none;border:none;padding:4px;font:inherit;font-size:13px;
    color:var(--red);cursor:pointer}
  #set-del .who-line{text-align:left}
  .attach-row{display:flex;align-items:center;gap:8px;margin-top:8px;min-width:0}
  .attach-btn,.attach-clear{background:none;border:none;padding:4px 0;font:inherit;
    font-size:13px;color:var(--ink-2);cursor:pointer}
  #set-support-fname{flex:1;min-width:0;font-size:12.5px;color:var(--ink);
    white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  /* Крутилка даты как в iOS (TG 7559): одно поле, тап раскрывает колонки
     день/месяц/год со scroll-snap, выбранное - в рамке по центру.
     Поле выглядит ровно как обычное поле формы (Даниил, TG 7652): те же
     рамка, фон, скругление и цвет подсказки, что у .field input. */
  .wheel-field{
    width:100%;text-align:left;
    padding:10px 12px;font:inherit;font-size:15px;color:var(--ink);
    background:var(--field);border:1px solid var(--ink);border-radius:5px;
    -webkit-appearance:none;appearance:none;cursor:pointer;
  }
  .wheel-field.empty{color:var(--ink-3)}
  .wheel-field.open{border-color:var(--red)}
  /* Дата и время - два поля во всю ширину, одно под другим (Даниил, TG 7736):
     год влез третьей колонкой, а месяц на полной ширине читается целиком
     и мельчить шрифт не надо. Само колесо всплывает окном, а не
     раскрывается под полем (Даниил, TG 7790): раскрытое под полем, оно
     двигало форму на 180 px и накрывало собой поле города, а закрывать его
     приходилось касанием мимо - с промахами по фокусу (TG 7767, 7776).
     Колесо встаёт прямо под своим полем (Даниил, TG 7868, 7872): по центру
     экрана оно накрывало сами поля даты и времени, и тап «по полю» попадал
     в колесо. Верх листа считает wheelPlace - здесь только раскладка. */
  /* Слой прозрачный (Даниил, TG 7889): затемнение с одной формой на экране
     ничего не поясняло, а тап мимо колеса ловит и невидимый слой. */
  #wheel-modal{position:fixed;inset:0;z-index:20}
  #wheel-modal[hidden]{display:none}
  #wheel-sheet{position:absolute;left:50%;transform:translateX(-50%);
    width:calc(100% - 40px);max-width:320px;padding:14px;
    background:var(--bg);border-radius:14px}
  .wheel-box{display:flex;position:relative;
    border:1px solid var(--ink);border-radius:10px;overflow:hidden;
    background:var(--field)}
  .wheel-box[hidden]{display:none}
  /* Выбранное - мягкой полосой, как на сайте (Даниил, TG 7736): рамка
     внутри рамки колеса выглядела жёстко. */
  .wheel-box::before{content:'';position:absolute;left:6px;right:6px;
    top:72px;height:36px;border-radius:8px;background:rgba(224,52,43,.10);
    pointer-events:none}
  .wheel-col{flex:1;height:180px;overflow-y:auto;scroll-snap-type:y mandatory;
    text-align:center;scrollbar-width:none;-webkit-overflow-scrolling:touch}
  .wheel-col::-webkit-scrollbar{display:none}
  .wheel-col .sp{height:72px}
  .wheel-col .wi{height:36px;line-height:36px;font-size:16px;
    color:var(--ink-2);scroll-snap-align:center;cursor:pointer}
  /* Колонки - в пропорции полей формы (Даниил, TG 7716/7717): день узкий,
     как окошко дня, месяцу нужна доля побольше («Сентябрь»). */
  #wheel-date .wheel-col:nth-child(2){flex:1.6}
  #wheel-date .wheel-col:nth-child(3){flex:1.2}
  /* Жест работает на всей половине колеса; сами цифры остаются ближе к центру. */
  #wheel-time .wheel-col{flex:1;min-width:0}
  #wheel-hh .wi{text-align:right;padding-right:24px}
  #wheel-mi .wi{text-align:left;padding-left:24px}
  .wheel-col .wi.on{color:var(--ink);font-weight:700}
  .hdr-right{display:flex;align-items:baseline;gap:10px}
  #settings-open{
    padding:0;background:none;border:0;font:inherit;font-size:13px;
    color:var(--ink-2);cursor:pointer;
  }
  .iv-btn.wide{flex:none;width:100%;text-align:left}
  .field textarea{
    width:100%;padding:10px 12px;font:inherit;font-size:15px;color:var(--ink);
    background:var(--field);border:1px solid var(--ink);border-radius:0;
    -webkit-appearance:none;appearance:none;resize:vertical;
  }
  .field textarea:focus{outline:none;border-color:var(--red)}
  /* Тумблер mutual ("Показать другу и мой бодиграф") - обычный чекбокс,
     своего класса для него в файле раньше не было. */
  .check-row{display:flex;align-items:center;gap:8px;margin-top:14px;font-size:13px}
  /* 20 px, как у согласия: 13 px не попадали пальцем (аудит 09.09.2026, В-08). */
  .check-row input{width:20px;height:20px;flex:0 0 20px;margin:0;accent-color:var(--accent)}
  .calc-card{
    background:var(--card);border:2px solid var(--ink);
    padding:18px 20px 22px;max-width:480px;margin:0 auto;
  }
  .calc-card h2{font-size:19px;font-weight:800;letter-spacing:-.02em;text-transform:uppercase;margin-bottom:14px}
  /* Форма и развилка под ней - раздельные карточки, между ними подводка
     «Или пригласите...» (Даниил, TG 7194, 7202, 7647); без развилки
     прячется и она. */
  #calc-or{text-align:center;font-weight:700;max-width:480px;margin:14px auto}
  #calc-or:has(+ #calc-fork[hidden]){display:none}
  /* Баннер приглашения стоит прямо над формой (развилка и «Или...» скрыты) -
     без отступа две рамки склеиваются (Даниил, TG 7409). */
  /* Согласие на отправку пригласившему (Даниил, TG 7711): рамкой и цветом
     громче соседних кнопок - его нельзя пролистать не заметив. */
  #invite-send{border:2px solid var(--red);border-radius:12px;padding:14px;
    margin:14px 0 10px;background:rgba(224,52,43,.06)}
  #invite-send .invite-send-h{margin:0 0 6px;font-size:16px;font-weight:700;
    color:var(--red)}
  #invite-send .invite-send-s{margin:0 0 12px;font-size:13px;line-height:1.4;
    color:var(--ink-2)}
  /* Основание хранения и ссылка на политику прямо в блоке согласия
     (Даниил, TG 7765): синяя и подчёркнутая - в чёрно-белом макете иначе
     не видно, что по ней можно нажать. */
  #invite-send .invite-send-law{margin:-6px 0 12px;font-size:12px;
    line-height:1.4;color:var(--ink-2)}
  #invite-send .invite-send-law a{color:#1a6dd8;text-decoration:underline}
  body.dark #invite-send .invite-send-law a{color:#6fb0ff}
  #invite-send .save-btn{margin-top:8px}
  .storage-consent{display:flex;align-items:flex-start;gap:10px;margin:14px 0;font-size:13px;line-height:1.5}
  .storage-consent input{width:20px;height:20px;flex:0 0 20px;margin:2px 0;accent-color:var(--accent)}
  /* Ссылки поддержки - цветом бренда, а не браузерным синим с подчёркиванием
     (аудит 09.09.2026, мелкое п. 1). В согласии подчёркивание остаётся: ссылка внутри текста. */
  .storage-consent a{color:var(--accent);text-underline-offset:3px}
  #web-support-link>a{display:inline-block;margin-top:14px;color:var(--accent);font-weight:550;text-decoration:none}
  #web-support-link>a:hover{text-decoration:underline}
  #accept-banner{margin-bottom:14px}
  #accept-quick .accept-person{margin:18px 0;text-align:center;font-size:13px;color:var(--ink-2);line-height:1.6}
  #accept-quick .accept-person strong{display:block;color:var(--ink);font-size:15px}
  #accept-quick .accept-edit{display:inline-block;width:auto;min-height:36px;padding:6px 10px;margin:2px 0 0;border:0;background:none;box-shadow:none;color:var(--ink-2);font:inherit;font-size:12px;text-decoration:underline;text-underline-offset:3px;cursor:pointer}
  #accept-edit-cancel{margin-top:8px}
  /* Приглашение в две строки: кто зовёт - отдельно, что делать - отдельно
     (Даниил, TG 7676). Перевод строки ставится в тексте. */
  #accept-p{white-space:pre-line}
  .field{margin-top:12px}
  .field label{
    display:block;font-size:9.5px;letter-spacing:.14em;text-transform:uppercase;
    color:var(--ink-3);margin-bottom:5px;
  }
  .field input,.field select{
    width:100%;padding:10px 12px;font:inherit;font-size:15px;color:var(--ink);
    background:var(--field);border:1px solid var(--ink);border-radius:0;
    -webkit-appearance:none;appearance:none;
  }
  .field input:focus,.field select:focus{outline:none;border-color:var(--red)}
  .lib-search-row{display:flex;gap:8px;align-items:stretch}
  .lib-search-row input{min-width:0;flex:1}
  .lib-filter-btn{flex:0 0 auto;padding:10px 12px;background:none;color:var(--ink);
    border:1px solid var(--ink);border-radius:5px;font:inherit;font-size:13px;
    font-weight:700;cursor:pointer}
  .lib-filter-panel{margin-top:8px;padding:12px;border:1px solid var(--ink);
    border-radius:5px;background:var(--field)}
  .lib-filter-panel[hidden],.lib-filter-active[hidden]{display:none}
  .lib-filter-group+ .lib-filter-group{margin-top:14px}
  .lib-filter-title{margin-bottom:7px;font-size:11px;font-weight:700;
    letter-spacing:.08em;text-transform:uppercase;color:var(--ink-2)}
  .lib-filter-options{display:flex;gap:6px;flex-wrap:wrap}
  .lib-filter-option{position:relative;display:block}
  .lib-filter-option input{position:absolute;opacity:0;pointer-events:none}
  .lib-filter-option span,.lib-filter-chip{display:block;padding:7px 9px;
    border:1px solid var(--ink-3);border-radius:5px;font-size:12px;cursor:pointer}
  .lib-filter-option input:checked+span{background:var(--ink);border-color:var(--ink);
    color:var(--card)}
  /* Панель фильтров лежит внутри .field, поэтому поле ворот тянулось во всю
     ширину по .field input - под двузначное число нужен только его размер. */
  .field input.lib-gate-input{width:96px}
  .lib-cross-wrap{position:relative}
  #lib-cross-drop{position:absolute;left:0;right:0;top:100%;z-index:5;display:none;
    background:var(--drop);border:1px solid var(--ink);border-radius:5px;
    margin-top:4px;overflow:hidden;box-shadow:0 6px 20px rgba(0,0,0,.10)}
  #lib-cross-drop div{padding:9px 12px;font-size:13px;cursor:pointer}
  #lib-cross-drop div+div{border-top:1px solid var(--ink)}
  .lib-cross-picked,.lib-filter-active{display:flex;gap:6px;flex-wrap:wrap;
    align-items:center;margin-top:8px}
  .lib-filter-chip{cursor:default;background:var(--card);color:var(--ink);font:inherit;
    font-size:12px}
  .lib-filter-clear{padding:5px 0;background:none;border:0;color:var(--red);
    font:inherit;font-size:12px;cursor:pointer}
  .lib-filter-actions{display:flex;gap:8px;margin-top:14px}
  .lib-filter-actions.top{margin:0 0 14px}
  .lib-filter-actions .save-btn{flex:1;margin:0;padding:10px 8px;font-size:12px}
  .cap-check{margin-top:10px}
  .cap-check p{margin:0 0 8px;font-size:13px;color:var(--ink-2);text-align:center}
  .cap-check .save-btn{margin-top:8px}
  /* Дата и время: у WebKit эти поля без -webkit-appearance живут своей
     высотой и получаются узенькими (Даниил, TG 6897) - фиксируем минимум. */
  .field input[type="date"],.field input[type="time"]{min-height:48px}
  /* Дата по частям (TG 7076): день/год - окошки, месяц пошире.
     Поля в строке уплотнены, чтобы введённое время влезало (Даниил, TG 7209).
     Год чуть шире за счёт месяца - «1999» со стрелками не влезал (TG 7589). */
  .date-row{display:flex;gap:6px}
  .date-row input,.date-row select{padding-left:8px;padding-right:8px}
  .date-row input{flex:1 1 0;min-width:0}
  .date-row select{flex:1.8 1 0;min-width:0}
  /* День - тоже крутилка (TG 7101), но узкая: числа 1-31 короткие.
     Чуть шире за счёт месяца, чтобы слово «День» влезало (Даниил, TG 7203). */
  .date-row select:first-child{flex:1 1 0}
  /* «Время» поверх пустого поля времени (TG 7205): native «--:--» прячем. */
  .date-row .time-wrap{flex:1.2 1 0;position:relative;display:flex;min-width:0}
  .time-wrap input{flex:1 1 0;width:100%}
  .time-ph{position:absolute;inset:0;display:flex;align-items:center;
    justify-content:center;pointer-events:none;color:var(--ink-3)}
  /* Подсказки в полях - один цвет и стиль (Даниил, TG 7212): плейсхолдеры,
     невыбранные селекты (required+:invalid) и слой «Время». */
  .field input::placeholder{color:var(--ink-3);opacity:1}
  .date-row select:required:invalid{color:var(--ink-3)}
  .time-wrap input.empty::-webkit-datetime-edit{color:transparent}
  .time-wrap input.empty::-webkit-calendar-picker-indicator{opacity:0}
  /* На компе по полю кликают и печатают в сегменты «--:--», а value пуст,
     пока время не набрано целиком - слой «Время» наезжал на ввод (Даниил,
     TG 7587). В фокусе прячем слой и показываем нативные сегменты. */
  .time-wrap input:focus + .time-ph{display:none}
  .time-wrap input.empty:focus::-webkit-datetime-edit{color:inherit}
  .time-wrap input.empty:focus::-webkit-calendar-picker-indicator{opacity:1}
  .city-wrap{position:relative}
  #city-drop,#edit-drop,#tr-drop,#lc-drop,#p2-drop{
    position:absolute;left:0;right:0;top:100%;z-index:20;display:none;
    background:var(--drop);border:1px solid var(--ink);
    margin-top:4px;overflow:hidden;box-shadow:0 6px 20px rgba(0,0,0,.10);
  }
  #city-drop div,#edit-drop div,#tr-drop div,#lc-drop div,#p2-drop div{padding:9px 12px;font-size:14px;cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  #city-drop div[aria-selected="true"],#edit-drop div[aria-selected="true"],
  #tr-drop div[aria-selected="true"],#lc-drop div[aria-selected="true"],#p2-drop div[aria-selected="true"]{background:var(--paper-2)}
  #city-drop div + div,#edit-drop div + div,#tr-drop div + div,#lc-drop div + div,#p2-drop div + div{border-top:1px solid var(--ink)}
  #city-drop small,#edit-drop small,#tr-drop small,#lc-drop small,#p2-drop small{color:var(--ink-3);font-size:11.5px}
  /* Десктоп (html.desk): селекты дня и месяца спрятаны за текстовыми
     двойниками, у года убраны стрелки-спиннеры */
  .desk-hide{display:none !important}
  .month-wrap{position:relative;flex:1.8 1 0;min-width:0;display:block}
  .month-wrap input{width:100%}
  .month-drop{
    position:absolute;left:0;right:0;top:100%;z-index:20;display:none;
    background:var(--drop);border:1px solid var(--ink);
    margin-top:4px;overflow:hidden;box-shadow:0 6px 20px rgba(0,0,0,.10);
  }
  .month-drop div{padding:9px 12px;font-size:14px;cursor:pointer}
  .month-drop div + div{border-top:1px solid var(--ink)}
  html.desk .date-row input[type=number]::-webkit-outer-spin-button,
  html.desk .date-row input[type=number]::-webkit-inner-spin-button{
    -webkit-appearance:none;margin:0}
  html.desk .date-row input[type=number]{-moz-appearance:textfield;appearance:textfield}
  .calc-go{
    display:block;width:100%;margin-top:18px;padding:15px 16px;
    background:var(--red);color:#fff;
    border:0;
    font:inherit;font-size:14px;font-weight:700;text-transform:uppercase;
    letter-spacing:.06em;cursor:pointer;
  }
  .calc-go[disabled]{opacity:.5;cursor:default}
  .calc-go.ghost{background:none;color:var(--ink);border:2px solid var(--ink)}
  /* Одна красная кнопка на главной (Даниил, TG 6874): главное действие -
     «Новый бодиграф», остальные точки входа - контурные. */
  .calc-open.ghost{background:none;color:var(--ink);border:2px solid var(--ink)}
  .save-btn{
    display:block;width:100%;margin-top:12px;padding:12px 16px;
    background:none;color:var(--ink);border:2px solid var(--ink);
    font:inherit;font-size:13px;font-weight:700;text-transform:uppercase;
    letter-spacing:.04em;cursor:pointer;
  }
  /* Опасное действие - красным, как #del-yes: обводка и шрифт,
     без заливки (Даниил, TG 7227/7248). */
  .save-btn.danger{background:none;border-color:var(--red);color:var(--red)}
  /* «Удалить только список»: рамка красная, а текст остаётся обычного
     цвета - в тёмной теме он белый (Даниил, TG 7661/7671). Красная
     заливка читалась как более опасное действие, чем удаление вместе
     с картами, - поэтому только обводка. */
  .save-btn.danger.soft{color:var(--ink)}
  /* Три кнопки под свежей картой в один ряд (Даниил, TG 7465). */
  .btn-row{display:flex;gap:8px;flex-wrap:wrap}
  /* Четвёртая кнопка («Поделиться», TG 8724) в 390 px не влезает - уходит
     на вторую строку во всю ширину, три первых остаются в ряд. */
  .btn-row .save-btn{flex:1 1 30%;padding:12px 4px;font-size:11px;letter-spacing:.02em}
  /* «Поделиться» само по себе рвалось на «Поделить-ся» общим overflow-wrap:anywhere
     у .ui-label (Даниил, TG 8976): суженные значок и отступ освобождают слову место
     в одну строку без переноса. */
  .btn-row .save-btn{gap:6px;padding:12px 2px;letter-spacing:0}
  .btn-row .save-btn .ui-icon{width:18px;height:18px}
  .btn-row .save-btn .ui-label{overflow-wrap:normal}
  /* Кнопкам, рамкам и полям - небольшое скругление, как у углов Сакрального
     центра на карте (rx=4 в bodygraph_svg; Даниил, TG 6836, 6839). */
  .calc-open,.calc-go,.save-btn,#edit-save,
  .chart-card,.mine-card,.calc-card,#edit-form,
  .field input,.field select,#city-drop,#edit-drop,#tr-drop,#lc-drop,#p2-drop{border-radius:5px}
  .who-line{margin-top:12px;font-size:12.5px;color:var(--ink-2);text-align:center}
  /* Строка «тип · профиль · авторитет» над картой повторяла подпись внутри самой
     картинки, поэтому скрыта (аудит 09.09.2026, мелкое п. 6). Текст по-прежнему
     заполняется - его читают вслух и тесты. */
  #who-line{display:none}
  #calc-note,.calc-form-note{margin-top:10px;font-size:12.5px;line-height:1.5;color:var(--ink-2);text-align:center}
  #calc-note.err,.calc-form-note.err{color:var(--red)}
  /* Этап 3: описания под картой - те же 4 раздела, что кнопки в боте. */
  #chart-desc,#calc-desc{max-width:480px;margin:14px auto 0}
  .desc{border-top:1px solid var(--ink)}
  .desc:last-child{border-bottom:1px solid var(--ink)}
  /* Внутри двух групп под бодиграфом линий нет (Даниил, TG 8139): группу держит
     её шапка, а разделители дробили её на шесть отдельных полос. В циклах
     и транзите линии остаются - там разделы идут без шапки группы. */
  #chart-desc .desc,#chart-more .desc,#calc-desc .desc,#calc-more .desc{
    border-top:none;border-bottom:none}
  .desc summary{
    /* 12px вместо 13: строки стояли далеко друг от друга и группа не читалась
       как столбик (Даниил, TG 8127, 8142), но ниже опускаться нельзя - при 7px
       строка была 35-36 px, а Apple просит на палец минимум 44 (TG 8149).
       Замерено в Chrome: 12px даёт 45-46 px. Капслок снят: заглавными
       остаются только шапки групп - иначе на экране сплошные прописные
       и группы перестают выделяться (TG 8133, 8139). */
    padding:12px 2px;font-size:13.5px;font-weight:700;letter-spacing:.01em;
    cursor:pointer;list-style:none;
    display:flex;justify-content:space-between;align-items:center;gap:10px;
  }
  .desc summary::-webkit-details-marker{display:none}
  /* Шеврон вместо красного плюса (Даниил, TG 8156): привычный знак «раскроется»,
     и серым он не спорит с текстом - строк на экране много. Через прямого
     потомка `>`: у вложенных разделов иначе перекрашивались бы и дочерние шапки.
     Подсветка под пальцем нужна потому, что линий у строк больше нет: без неё
     нажатие ничем не отзывается. Серый полупрозрачный виден в обеих темах. */
  .desc > summary::after{content:'›';display:inline-block;transform:rotate(90deg);
    font-size:19px;font-weight:400;color:var(--ink-3)}
  .desc[open] > summary::after{transform:rotate(-90deg)}
  /* Серый с прозрачностью виден и на светлой, и на тёмной теме. Родной
     тап-хайлайт задан явно: одного `:active` мало - в вебвью iOS он часто
     не срабатывает, и Даниил подсветки не увидел (TG 8159-8161). */
  .desc > summary{-webkit-tap-highlight-color:rgba(127,127,127,.3)}
  .desc > summary:active{background:rgba(127,127,127,.15)}
  /* «Свернуть» в конце раскрытого раздела (Даниил, TG 8159): текст длинный,
     и после чтения приходится листать обратно к шапке. Стрелка та же, что
     в шапке, только смотрит вверх. */
  .desc-close{display:block;width:100%;margin-bottom:6px;padding:13px 0;
    background:none;border:0;font:inherit;line-height:1;color:var(--ink-3);
    cursor:pointer;-webkit-tap-highlight-color:rgba(127,127,127,.3)}
  .desc-close::after{content:'›';display:inline-block;transform:rotate(-90deg);
    font-size:19px}
  .desc-close:active{background:rgba(127,127,127,.15)}
  .desc-body{padding:0 2px 16px;font-size:14px;line-height:1.55}
  .desc-body p{margin:8px 0 0}
  .desc-body .desc-head{display:block;margin-top:16px;font-weight:700}
  .desc-body .desc-head:first-child{margin-top:0}
  .desc-body .desc-circuit{display:block;margin-top:2px;font-style:italic;
    color:var(--ink-3);font-size:12.5px}
  /* Карта цикла (Даниил, TG 8112/8113). Карта прилипала к ряду кнопок
     «Соляр / Лунар», а «Скачать карту» - к линии над «Тип цикла»: и то,
     и другое рисуется вплотную к предыдущему блоку. Линию над первым
     разделом убираем совсем - её роль здесь играет сама кнопка. */
  .cyc-result > .chart-card{margin-top:14px}
  .cyc-result,.cycle-planets-view,.cycle-timeline-view{scroll-margin-top:calc(18px + var(--tg-top,0px))}
  .cyc-result .save-btn + .desc{border-top:none;margin-top:20px}
  /* «Ещё по этой карте»: подпись под SVG и кнопки интервалов устойчивости. */
  .cycle-overview{margin:10px 0 24px}
  .cycle-choices{display:grid;gap:12px;margin:12px 0}
  .cycle-entry{width:100%;text-align:left;font:inherit;padding:18px;border:1px solid var(--line);border-radius:17px;background:var(--card);cursor:pointer}
  .cycle-entry strong{display:block;color:var(--accent);font-size:18px;margin-bottom:7px}
  .cycle-entry small{display:block;color:var(--ink-2);font-size:14px;line-height:1.5}
  .cycle-entry:focus-visible{outline:2px solid var(--accent);outline-offset:3px}
  .cycle-menu .iv-row{display:grid;grid-template-columns:repeat(2,minmax(0,1fr))}
  .cycle-menu .iv-btn:only-child{grid-column:1 / -1}
  .cycle-menu .iv-btn{justify-content:flex-start;text-align:left;padding:10px 8px;gap:6px}
  .cycle-menu .iv-btn>.ui-icon{flex:0 0 25px}
  .cycle-menu .iv-btn>.ui-label{flex:1}
  .cycle-badge{display:inline-block;font-size:11px;line-height:1.5;color:var(--accent);background:var(--tint);padding:5px 8px;border-radius:8px}
  .cycle-link{display:block;color:var(--accent);font:inherit;font-size:13px;text-align:left;background:none;border:0;padding:9px 0;min-height:40px}
  .cycle-scope{float:right;margin-left:8px;font-size:11px;line-height:1.5;padding:4px 8px;border-radius:8px;background:var(--tint);color:var(--accent)}.cycle-scope.big{background:var(--line);color:var(--ink-2)}
  .cycle-fold{width:100%;text-align:center;border:1px dashed var(--line);border-radius:12px;margin:2px 0 6px}
  .cycle-life-row{position:relative;display:flex;align-items:baseline;gap:8px;width:100%;padding:7px 0;min-height:36px;background:none;border:0;font:inherit;font-size:13px;color:var(--ink);text-align:left}.cycle-life-row b{font-weight:600;min-width:0}.cycle-life-row .cycle-age{margin-left:auto;color:var(--ink-3);white-space:nowrap;font-variant-numeric:tabular-nums}
  .cycle-life-row:before{content:'';position:absolute;left:-30px;top:13px;width:8px;height:8px;border-radius:50%;background:var(--ink-3);border:2px solid var(--ink-3)}.cycle-life-row.future:before{background:var(--bg)}
  .cycle-zone{margin:8px 0 8px -25px;padding:6px 0 4px 23px;border-left:2px solid var(--accent);background:linear-gradient(90deg,var(--tint),transparent 70%)}.cycle-zone-label{margin:2px 0 8px;font-size:11px;color:var(--accent);text-transform:uppercase;letter-spacing:.04em}
  .cycle-timeline{border-left:2px dashed var(--line);margin-left:7px;padding-left:23px}.cycle-event{position:relative;padding:15px;border:1px solid var(--line);border-radius:16px;background:var(--card);margin:0 0 17px}.cycle-event:before{content:'';position:absolute;left:-32px;top:20px;width:12px;height:12px;border:2px solid var(--accent);background:var(--bg);border-radius:50%}.cycle-event.past:before{background:var(--ink-3);border-color:var(--ink-3)}.cycle-event.current{border:0;background:none;padding:12px 0;color:var(--red)}.cycle-event.current:before{background:var(--red);border-color:var(--red);left:-32px}.cycle-event.next{border-color:var(--accent)}.cycle-event h4{margin:8px 0;font-size:17px}.cycle-event small{font-size:11px;color:var(--ink-3)}
  .activator-card{border:1px solid var(--line);border-radius:18px;background:var(--card);margin:16px 0;overflow:hidden}.activator-person{padding:17px}.activator-person h3{margin:0 0 8px;font-size:21px}.activator-person p{margin:0;color:var(--ink-2);font-size:13px}
  .activator-actions{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));border-top:1px solid var(--line)}.activator-actions button{display:flex;align-items:center;flex-direction:column;gap:5px;min-width:0;min-height:95px;padding:13px 2px;background:none;border:0;border-right:1px solid var(--line);color:var(--accent);font:inherit;font-size:12px}.activator-actions button:last-child{border-right:0}.activator-actions small{font-size:10px;color:var(--ink-3)}.activator-actions svg{height:28px;width:28px;margin-bottom:4px;color:var(--red)}.activator-actions button[aria-expanded=true]{background:var(--tint)}.activator-actions button:disabled{opacity:.45}
  .activator-description{padding:17px;border-top:1px solid var(--line)}.activator-description h4{font-size:17px;margin:10px 0}.activator-description p{font-size:14px;line-height:1.65}.activator-gates{background:var(--tint);border-radius:12px;padding:12px;display:flex;justify-content:space-between;gap:8px;align-items:center;color:var(--accent);font-size:15px;margin:15px 0}.activator-gates small{display:block;color:var(--ink-3);font-size:11px}

  .more-note{margin-top:8px;font-size:12.5px;color:var(--ink-2)}
  .activators-filter{margin:16px 0;border:1px solid var(--line);border-radius:14px;background:var(--card);overflow:hidden}
  .activators-filter>summary{display:flex;align-items:center;justify-content:space-between;gap:12px;list-style:none;cursor:pointer}
  .activators-filter>summary::after{content:'›';color:var(--accent);transform:rotate(90deg)}.activators-filter[open]>summary::after{transform:rotate(-90deg)}
  .activators-filter>summary>span{font-size:12px;color:var(--ink-3)}.activators-filter>summary>strong{font-size:13px;color:var(--accent);text-align:right;max-width:58%}
  .activators-list-choices{display:grid;gap:7px;padding:0 12px 8px}.activators-filter>p{font-size:12px;color:var(--ink-3);padding:0 12px 12px}
  .activators-guide{margin:12px 0 20px;padding:16px;background:var(--card);border:1px solid var(--line);border-radius:16px}
  .activators-guide h3{margin:0 0 10px;font-size:16px;color:var(--ink)}
  .activators-guide p{font-size:14px;line-height:1.55;color:var(--ink-2)}
  .activators-guide p:first-of-type{font-weight:600;color:var(--ink)}
  .activators-guide p:last-child{margin-bottom:0}
  .stab-note{margin-top:12px;font-size:12.5px;font-style:italic;color:var(--ink-3)}
  .iv-row{display:flex;gap:6px;flex-wrap:wrap;margin-top:10px}
  .iv-btn{
    flex:1;min-width:44px;padding:8px 0;background:none;color:var(--ink);
    border:1px solid var(--ink);border-radius:5px;
    font:inherit;font-size:13px;cursor:pointer;
  }
  .iv-btn.on{background:var(--red);border-color:var(--red);color:#fff}
  /* Лунный цикл Рефлектора: строка режима зелёная, календарь семью столбцами. */
  .lunar-row{border:1.5px solid var(--accent);border-radius:14px;
    background:color-mix(in srgb,var(--accent) 9%,transparent)}
  .lunar-row>summary{color:var(--accent);font-weight:600}
  .lc-head p{margin:6px 0 0}
  .lc-region{margin-top:12px}
  .lc-nav{margin-top:12px}
  .lc-nav .iv-btn{flex:1 1 auto;padding:8px 6px}
  .lc-cal{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:3px;margin-top:10px}
  .lc-wd{font-size:11px;color:var(--ink-3);text-align:center;padding:2px 0}
  .lc-c{min-height:54px;padding:3px 2px 4px;border:1px solid var(--line,var(--ink));
    border-radius:6px;font-size:11.5px;line-height:1.35;text-align:center;cursor:pointer}
  .lc-c.off{opacity:.35;cursor:default}
  .lc-c.today{border-color:var(--accent)}
  .lc-c.on{background:color-mix(in srgb,var(--accent) 14%,transparent);
    border-color:var(--accent);box-shadow:inset 0 0 0 1px var(--accent)}
  .lc-c>b{display:block;font-size:10.5px;font-weight:600;padding-bottom:2px;margin-bottom:3px;
    border-bottom:1px solid var(--line,var(--ink));white-space:nowrap;overflow:hidden}
  .lc-e{display:inline-block;margin:0 2px}
  .lc-e .lc-t,.lc-e .lc-n{display:none}
  .lc-e.harm{color:var(--red);font-weight:700}
  .lc-day{margin-top:12px}
  .lc-day-cap{margin:0 0 4px;font-weight:600}
  .lc-r{padding:6px 0;border-top:1px solid var(--line,var(--ink));font-size:13.5px}
  .lc-r.harm{color:var(--red)}
  .lc-r.cur b{text-decoration:underline}
  .lc-harm{display:block;padding:0;border:0;background:none;color:var(--red);font:inherit;
    font-size:12px;text-align:left;cursor:pointer;text-decoration:underline dotted}
  .lc-desc{margin-top:6px;color:var(--ink);font-size:13px}
  .lc-desc .desc-head,.lc-desc .desc-circuit{display:block}
  .lc-desc p{margin:4px 0 0}
  /* Выбор списков приглашения галочками (Даниил, TG 7148): можно отметить
     несколько сразу, «без списка» снимает остальные и наоборот. */
  .inv-lrow{display:flex;align-items:center;gap:8px;width:100%;padding:10px 12px;
    background:none;border:1px solid var(--ink);border-radius:5px;
    font:inherit;font-size:13px;color:var(--ink);cursor:pointer;text-align:left}
  /* Выбранный список (Даниил, TG 7565-7576): рамка цвета текста потолще
     (в тёмной теме белая, в светлой тёмная) + галочка в зелёном кружке.
     Красный не годится - он в аппе занят под опасные действия. */
  .inv-lrow .tick{margin-left:auto;color:#fff;background:#2ea043;border-radius:50%;
    width:20px;height:20px;display:flex;align-items:center;justify-content:center;
    font-size:12px;font-weight:900;visibility:hidden}
  .inv-lrow.sel{border:2px solid var(--ink);padding:9px 11px}
  .inv-lrow.sel .tick{visibility:visible}
  /* Те же строки в «Добавить в списки:» формы правки (TG 7577) - там они
     лежат не в .iv-row, отступ между рядами свой. */
  #edit-lists .inv-lrow{margin-top:8px}
  /* Чипы фильтра по спискам - по ширине текста: с flex:1 при 6-7 списках
     кнопки сжимались и подписи вылезали за рамки (Даниил, TG 7023). */
  #pair-filter .iv-btn{flex:0 0 auto;padding:8px 10px}
  /* Кнопки дат циклов - по две в ряд, как в боте (_occurrences_kb):
     в узкую кнопку интервала дата со временем не влезает. */
  .iv-btn.dt{flex:1 1 40%}
  /* Выбранная дата над картой цикла - подпись, а не кнопка: её жали,
     а ничего не менялось (Даниил, TG 7078). Соседние даты остаются кнопками. */
  .iv-btn.dt.on{background:none;border-color:transparent;color:var(--ink);
                font-weight:700;pointer-events:none}
  /* Рассылки - строки с тумблерами вместо кнопок ✅/🔕 из бота: колокольчик
     читался как «уведомления», выглядело чужеродно (Даниил, TG 7112/7125). */
  .topic-row{
    display:flex;align-items:center;justify-content:space-between;gap:12px;
    width:100%;padding:12px 2px;background:none;border:0;
    border-bottom:1px solid rgba(127,127,127,.25); /* тонкая линия в обеих темах */
    font:inherit;font-size:14px;color:var(--ink);cursor:pointer;text-align:left;
  }
  .topic-row:last-child{border-bottom:0}
  .tgl{
    flex:0 0 auto;width:44px;height:26px;border-radius:13px;
    background:var(--ink-3);position:relative;transition:background .15s;
  }
  .tgl::after{
    content:'';position:absolute;top:3px;left:3px;width:20px;height:20px;
    border-radius:50%;background:var(--card);
    box-shadow:0 1px 3px rgba(0,0,0,.25);transition:left .15s;
  }
  .topic-row.on .tgl{background:var(--ink)}
  .topic-row.on .tgl::after{left:21px}
