/* Телефон: един слой над всичко останало.
 *
 * Тук е събрано ЦЯЛОТО поведение на панела под 900px, вместо да е разпръснато
 * из файловете на компонентите. Причината е, че телефонът не е „същият екран,
 * но по-тесен“ — той е друго подреждане на същите данни: други колони, друга
 * навигация, друг мащаб. Такава промяна се чете и се връща наведнъж само
 * когато стои на едно място.
 *
 * Файлът се зарежда ПОСЛЕДЕН (виж app.css), затова селекторите тук са същите
 * като оригиналните и печелят по ред, а не с !important.
 *
 * Правилото, което държи двата изгледа разделени:
 *
 *   Всичко тук е ВЪТРЕ в media заявка. Промяна в този файл не може да стигне
 *   до широкия екран, а промяна в който и да е друг файл се препокрива тук,
 *   ако е нужно. Тоест десктопът се поправя в компонентните файлове, без да
 *   се мисли за телефона, а телефонът — тук, без да се мисли за десктопа.
 *   Единственото, което важи и за двата, са базовите стойности на компонент,
 *   които са ОБЩИ по замисъл (например размерът на филтрите); те си остават в
 *   своя файл.
 *
 * Какво прави:
 *   1. Навигацията става лента с раздели в стил iPhone, долепена до долния ръб.
 *   2. Мащабът се смъква с една стъпка — отстояния, шрифтове, контроли — и
 *      остава пропорционален: полетата, бутоните и филтрите се смаляват заедно.
 *   3. Списъците СКРИВАТ колони, вместо да се плъзгат настрани. От всяка
 *      таблица остава това, заради което се отваря на телефон, и то се побира
 *      в ширината на екрана.
 *   4. Попъпите идват отдолу като панели и се държат като на iPhone.
 *   5. Езикът на контролите е на iOS: без главни букви, натискането се вижда,
 *      сивата рамка на браузъра при допир я няма.
 */

/* ================================================================ 1. ЛЕНТА */
@media (max-width:900px) {
  /* Лентата с раздели: полупрозрачна, залепена долу, с размазан фон под нея —
     както е в iOS. Иконата е отгоре, името отдолу; активният раздел е един и
     се познава по цвета, не по плочка. */
  .rail {
    top: auto;
    bottom: 0;
    left: 0;
    right: 0;
    width: auto;
    height: auto;
    flex-direction: row;
    align-items: stretch;
    justify-content: space-between;
    gap: 0;
    padding: 5px 2px calc(3px + env(safe-area-inset-bottom));
    background: color-mix(in srgb,var(--bg-solid) 80%,transparent);
    /* Ако браузърът не може да размазва, фонът остава плътен и лентата пак е
       непрозрачна — нищо не пропада. */
    backdrop-filter: saturate(180%) blur(20px);
    -webkit-backdrop-filter: saturate(180%) blur(20px);
    border-top: 1px solid color-mix(in srgb,var(--text) 12%,transparent);
    z-index: 40;
  }

  @supports not (backdrop-filter: blur(1px)) {
    .rail {
      background: var(--bg-solid);
    }
  }

  /* Разделът вече не е плочка: няма карта, няма рамка, няма пръстен. */
  .rail a {
    flex: 1 1 0;
    width: auto;
    height: auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-start;
    gap: 2px;
    /* Без странично поле: „Абонаменти“ е най-дългото име и му трябва цялата
       ширина на раздела. Стесни ли се екранът под 375px, то се съкращава с
       многоточие — както в iOS. */
    padding: 4px 0 2px;
    border-radius: 10px;
    background: transparent;
    border: 0;
    color: var(--muted);
  }

  .rail a svg {
    width: 23px;
    height: 23px;
  }

  /* Името на раздела. На широкия екран го няма — там рейлът е с икони и
     подсказка при посочване. */
  .rail .tab-label {
    display: block;
    font-size: 9px;
    font-weight: 500;
    line-height: 1.1;
    letter-spacing: -.02em;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  /* Активният раздел: цвят, не плочка — това е разликата между лента с
     раздели и шест бутона. Цветът е мастилото, не синьото на iOS: синьото е
     цветът на препратка в тази система, а разделът не е препратка. Освен това
     --text се обръща сам в тъмната тема, докато синьото щеше да остане едно и
     също и на двата фона. */
  .rail a.on {
    background: transparent;
    color: var(--text);
    border-color: transparent;
  }

  .rail a:hover,
  .rail a:focus-visible {
    box-shadow: none;
    color: var(--text);
  }

  .rail a.on:hover,
  .rail a.on:focus-visible {
    color: var(--text);
  }

  .rail .logo {
    display: none;
  }

  /* Темата слиза от лентата в менюто на профила: шест раздела са таванът на
     една такава лента, а превключвателят е настройка, не място. */
  .rail .rail-theme {
    display: none;
  }
}

/* Другата половина на двойката от base.css: тук се сменят местата. */
@media (max-width:900px) {
  .only-wide {
    display: none;
  }

  .only-phone {
    display: block;
  }

  /* Формата в меню е прозрачна за подредбата (виж .menu form в frame.css) —
     тя не е кутия, а начин да се прати заявка, така че си остава такава. */
  .menu form.only-phone {
    display: contents;
  }
}

/* ============================================== 2. ЕЗИКЪТ НА ДОПИРА (iOS) */
@media (max-width:900px) {
  /* Сивият правоъгълник, който Safari рисува върху всичко натиснато, го няма:
     той закъснява спрямо пръста и оцветява ъглите на закръглените неща. На
     негово място всяко нещо, което се натиска, си казва само. */
  * {
    -webkit-tap-highlight-color: transparent;
  }

  /* Safari уголемява текста сам, когато телефонът се обърне на легнало. Тук
     размерите са премерени и не бива да ги пипа никой друг. */
  html {
    -webkit-text-size-adjust: 100%;
    text-size-adjust: 100%;
  }

  /* Мащаб няма: нито с два пръста, нито с двойно натискане. Панелът е
     премерен за ширината на телефона и увеличен само пречи — остава
     изместен и след като полето загуби фокус. Полетата са 16px (forms.css),
     за да не увеличава Safari при фокус, а viewport-ът в layout.php казва
     същото на инсталираното приложение. Тук се спират самите жестове. */
  html,
  body {
    touch-action: pan-x pan-y;
  }

  /* Натискането се ВИЖДА. На широк екран посочването върши тази работа; на
     телефон посочване няма, и без обратна връзка редът изглежда, като че не е
     приел допира. Свиването е това, което прави iOS: малко и бързо. */
  .row,
  .child,
  .card,
  .pcard,
  .menu-item,
  .btn,
  .segment > a,
  .segment > button,
  .rail a {
    /* Само това, което натискането мени. Фонът нарочно НЕ е тук: той се сменя
       и при смяна на темата, и тогава преходът се вижда като разсинхрон между
       фон и текст. */
    transition: transform .12s ease, opacity .12s ease;
  }

  /* Картата на борда (.tcard) НЕ е тук нарочно: тя се влачи, а startDrag() в
     app.js мери картата с getBoundingClientRect() точно докато :active още е
     включен — призракът излизаше с 1.5% по-тесен и изместен. Влачене с пръст
     не се пуска изобщо, така че свиването ѝ не печели нищо насреща. */
  .row:active,
  .child:active,
  .card:active,
  .pcard:active {
    transform: scale(.985);
  }

  .btn:active,
  .iconbtn:active,
  .addpill .addmain:active,
  .addpill .addmore:active,
  .modal-close:active,
  .field-box:active {
    transform: scale(.96);
  }

  /* Разделът светва под пръста, вместо да чака да се вдигне. */
  .rail a:active {
    opacity: .5;
  }

  /* Пръстът не посочва, така че всичко, писано за посочване, е шум: то се
     задържа върху натиснатото и оставя реда „светнал“, докато не се пипне
     другаде. */
  .row:hover,
  .child:hover,
  .card:hover,
  .menu-item:hover,
  .btn:hover,
  .segment > a:hover,
  .segment > button:hover,
  .check-chip:hover,
  .filter-select:hover,
  .bug-chip:hover {
    box-shadow: none;
  }

  /* Бутоните говорят на човешки. ГЛАВНИТЕ БУКВИ С РАЗРЕДКА са език на
     широкия екран; iOS не крещи на бутоните си, а при 11px разредката прави
     „Разписка“ по-трудна за четене, не по-лесна. Текстът си е сложен с малки
     букви в шаблоните — тук просто спира да се преобразува. */
  .btn,
  button {
    text-transform: none;
    letter-spacing: normal;
  }

  .btn {
    font-weight: 600;
  }

  .addpill .addmain {
    font-weight: 600;
    font-size: 12px;
    letter-spacing: normal;
    text-transform: none;
  }

  /* Избраният филтър остава черен с бял текст и без сянка, както е на широк
     екран — тоест правилото от buttons.css важи и тук, без изключение.
     Пробван беше плъзгачът на iOS (светло хапче със сянка върху сива писта),
     но той казва „това е избраното“ по-тихо, отколкото трябва: на телефон
     филтрите са по цял ред и избраният трябва да се хване с един поглед. */
}

/* ================================================== 3. МАЩАБ И ОТСТОЯНИЯ */
@media (max-width:900px) {
  body {
    font-size: 13px;
  }

  /* Подсказките ги няма изобщо на телефон.
     Показват се при посочване, а пръстът не посочва — на този екран те никога
     не се появяват. Но невидими чупят оформлението: absolute + nowrap +
     opacity:0 значи, че кутията им стои в оформлението и брои към
     скролируемото преливане на всеки предшественик, който може да се плъзга.
     Един чип с подсказка близо до десния ръб правеше секцията с задачите
     широка 416px при 335 налични и слагаше хоризонтален скрол под списъка.

     buttons.css вече ги маха при `hover: none`; тук се маха и по ширина, за
     двата случая, които онова правило изпуска: устройство, което докладва
     посочване, макар да се държи на пръст, и рейлът, чието правило е
     по-специфично от общото. `content: none` не създава псевдоелемента изобщо
     — това, а не opacity, е което спира преливането. */
  [data-tip]::after,
  .rail [data-tip]::after {
    content: none;
    display: none;
  }
}

/* Същото и за всяко устройство без посочване, независимо колко е широко:
   таблет с пръст няма курсор и подсказката там също не може да се появи. */
@media (hover: none) {
  [data-tip]::after {
    content: none;
  }
}

@media (max-width:900px) {

  /* Разстоянието между колоните на всеки списък. Оттук нататък всичко в
     таблиците се мери с него. */
  [data-table],
  .thead,
  .row,
  .child {
    --table-gap: 8px;
  }

  /* --------------------------------------------------------------- рамка */
  /* Две места в топбара: марката вляво, действията вдясно. Марката слиза тук,
     защото долу рейлът стана лента с раздели и логото му се скри с него. */
  .topbar {
    /* В инсталираното приложение (standalone) iOS рисува страницата и под
       статус бара; лентата слиза под него със собствения си фон, за да не се
       застъпват часовникът и логото. В Safari отстъпът е 0 и нищо не се мени. */
    height: calc(54px + env(safe-area-inset-top));
    padding: env(safe-area-inset-top) 10px 0;
    gap: 8px;
    grid-template-columns: auto minmax(0,1fr);
  }

  .topbar-logo {
    display: grid;
    place-items: center;
    grid-column: 1;
    /* Точно колкото аватара отсреща, за да са двата края на лентата равни. */
    width: 34px;
    height: 34px;
    border-radius: 11px;
    background: var(--ink);
    color: var(--ink-text);
    font-weight: 700;
    font-size: 11px;
    letter-spacing: .02em;
  }

  .topbar .right {
    grid-column: 2;
    justify-self: end;
    gap: 7px;
  }

  .iconbtn,
  .avatar {
    width: 34px;
    height: 34px;
  }

  .avatar {
    padding: 2px;
  }

  .avatar span {
    width: 28px;
    height: 28px;
    font-size: 11px;
  }

  /* ------------------------------------------------- плаващият бутон „+“ */
  /*
   * На телефон добавянето слиза от горната лента в долния десен ъгъл и става
   * кръгче с плюс. Две причини.
   * Горе то е далеч от палеца, а е най-често използваното действие; долу
   * вдясно е точно под него. И: с надпис („НОВА ЗАДАЧА“) хапчето изяждаше
   * половината горна лента, в която трябва да се съберат и марката, и
   * търсенето, и профилът.
   * Основното действие отпада заедно с надписа — един бутон отваря списъка с
   * всичките пет вида, вместо да гади кой е нужният.
   */
  .addsplit {
    position: fixed;
    right: 14px;
    /* Над лентата с раздели и над жеста за начало. */
    bottom: calc(66px + env(safe-area-inset-bottom));
    z-index: 35;
  }

  .addpill {
    height: 48px;
    width: 48px;
    border-radius: 50%;
    /* Сянката го отделя от списъка, над който плава. */
    box-shadow: 0 4px 14px rgba(0,0,0,.22);
  }

  /* Основното действие го няма: бутонът отваря менюто, не създава задача. */
  .addpill .addmain {
    display: none;
  }

  .addpill .addmore {
    width: 100%;
    height: 100%;
    padding: 0;
    justify-content: center;
    border-left: 0;
  }

  .addpill .addmore svg {
    width: 22px;
    height: 22px;
  }

  /* В края на страницата: бутонът се свива и просветлява, за да се чете
     последният ред под него. Свива се към долния си десен ъгъл, тоест остава
     на място, а не отскача настрани. 34px още се улучва с пръст (WCAG иска 24).
     Класът се слага от app.js — там е кога, тук е как. */
  .addpill {
    transition: transform .18s ease, opacity .18s ease;
    transform-origin: 100% 100%;
  }

  body.at-end .addpill {
    transform: scale(.65);
    opacity: .55;
  }

  /* Отвори ли се менюто, бутонът се връща: тогава той е активният контрол и
     не бива да е блед. */
  body.at-end .addsplit:has(.menu:not([hidden])) .addpill {
    transform: none;
    opacity: 1;
  }

  /* Менюто се отваря НАГОРЕ: под бутона е ръбът на екрана. */
  .addsplit .menu {
    top: auto;
    bottom: calc(100% + 10px);
  }

  /* На телефон менюто е единственият път към добавяне, значи е пълно. */
  .menu-item.is-main {
    display: flex;
  }

  main {
    /* Долният отстъп е за лентата с раздели плюс жеста за начало на iPhone. */
    margin: calc(54px + env(safe-area-inset-top)) 0 0 0;
    /* Колкото трябва на лентата с раздели, и нищо отгоре за плаващия бутон:
       той се свива в края на страницата (виж .at-end по-долу), вместо всяка
       страница да носи празно поле, високо колкото него. */
    padding: 12px 10px calc(78px + env(safe-area-inset-bottom));
    border-radius: 0;
    min-height: calc(100vh - 54px - env(safe-area-inset-top));
    gap: 12px;
  }

  .menu {
    min-width: 232px;
    border-radius: 15px;
  }

  .menu-item {
    padding: 8px 9px;
    border-radius: 11px;
    font-size: 13px;
  }

  .menu-item .ico {
    width: 30px;
    height: 30px;
    border-radius: 9px;
  }

  .menu-item b {
    font-size: 13px;
  }

  .menu-item small,
  .menu-head small {
    font-size: 11px;
  }

  .section[id] {
    scroll-margin-top: 64px;
  }

  /* ------------------------------------------------------------- филтри */
  /* Шест филтъра в една капсула са 580px — по-широки от телефона. Плъзгане
     настрани не става: половината филтри остават извън екрана и никой не ги
     търси с пръст. Затова капсулата се пренася на нов ред.
     За да не се разпадне на две капсули, тя спира да е хапче и става блок със
     заоблени ъгли: един сив правоъгълник, в който хапчетата стоят на два реда.
     Така превключвателят си остава един контрол, а активният филтър се вижда
     винаги, без да се търси. */
  .filters,
  .hstack-between,
  .hstack,
  .section > header {
    gap: 8px;
  }

  .segment {
    max-width: 100%;
    flex-wrap: wrap;
    padding: 3px;
    border-radius: 14px;
    row-gap: 3px;
  }

  /* Хапчетата са с еднаква ширина и заедно пълнят реда си.
     Основата е нула, а не съдържанието (`1 1 0`, не `1 1 auto`): при основа
     съдържание всяко хапче тръгва от дължината на името си и растежът само
     добавя пропорционално отгоре, тоест „Просрочени“ остава по-широко от
     „Сума“ завинаги. С основа нула наличното се дели поравно и капсулата се
     чете като превключвател с равни позиции, а не като редица от думи.
     Свиването е ограничено от min-content: не остане ли място за най-дългото
     име, то си запазва ширината, вместо да се среже — тогава хапчетата не са
     съвсем равни, но нищо не се губи.
     Полето е с два пиксела по-тясно от преди — точно колкото да събере
     четирите филтъра на „Абонаменти“ и „Пари“ на един ред. */
  .segment > button,
  .segment > a {
    flex: 1 1 0;
    height: 26px;
    padding: 0 9px;
    font-size: 12px;
    white-space: nowrap;
  }

  .segment .n {
    margin-left: 3px;
  }

  /* Капсулата заема целия ред.
     На телефон тя и без това е почти цял ред: остане ли широка колкото имената
     в себе си, увисва в единия край. Пълната ширина я превръща в превключвател
     през екрана — хапчетата растат и я запълват (виж правилото за flex
     по-горе).
     Правилото е едно за всички такива места: Проекти, Клиенти, Абонаменти,
     Пари и Задачи. На „Пари“ групите са две — филтър и подредба — и всяка си
     получава своя етаж, без да се пише отделно. */
  .filter-set {
    width: 100%;
  }

  .filters .segment,
  .filter-set > .segment {
    width: 100%;
  }

  /* Надписът над капсулата пада. „Подредба“ казва какво прави контролът, а
     контролът вече го казва сам: избраното хапче е името на подредбата
     („Следващо“, „Сума“). Един ред текст на всеки екран, за да повтори това,
     е скъп при тази ширина. */
  .filter-set > .text-12 {
    display: none;
  }

  .check-chip,
  .filter-select {
    height: 32px;
    font-size: 12px;
  }

  .check-chip > span {
    height: 26px;
    padding: 0 11px;
  }

  .filter-select {
    max-width: 100%;
    padding: 0 28px 0 11px;
    background-position: right 10px center;
  }

  /* Полето за проект във филтрите на „Задачи“ не бива да разпъва реда. */
  .filter-set {
    max-width: 100%;
    gap: 6px;
  }

  /* Филтър, който стои В ЗАГЛАВИЕТО на секция, отпада на телефон. Такъв е само
     един — „Задачи“ на Таблото: кой чии са и как са групирани. Двете капсули
     заемаха три реда над списъка, преди да се стигне до първата задача, а
     екранът е тесен и списъкът е причината да се отвори.
     Остава подредбата по подразбиране (по срок), а редът под заглавието я
     казва с думи. Който иска друго — „Целият борд“ е до заглавието. */
  .section > header .segment {
    display: none;
  }

  /* Заглавието на секцията става един ред: името вляво, действието вдясно. */
  .section > header {
    flex-wrap: nowrap;
    align-items: center;
  }

  .section > header > .hstack {
    flex: none;
    margin-left: auto;
  }

  /* ------------------------------------------------------------- шрифтове */
  h1,
  h2 {
    font-size: 26px;
  }

  .h1-sm {
    font-size: 24px;
  }

  .big {
    font-size: 23px;
  }

  .big-sm {
    font-size: 19px;
  }

  .list-title {
    font-size: 17px;
    margin: 2px 0 -6px;
  }

  .eyebrow,
  .text-12 {
    font-size: 11px;
  }

  /* --------------------------------------------------------- повърхности */
  .section {
    padding: 12px 10px;
    border-radius: 16px;
  }

  .sechead {
    margin-bottom: 10px;
    gap: 8px;
  }

  /* Две карти на ред. Когато шрифтът на сумата беше 30px, две колони оставяха
     около 126px за „€ 12 480,00“ и то излизаше от картата — затова дотогава
     стояха една под друга. Сега сумата е 23px и вътрешната ширина е 145px, в
     които се побира.
     #info.cards е петте карти на страницата на проекта; носи id, тоест е
     по-специфично от .cards и трябва да се назове, иначе остава на една колона.
     minmax(0,…) пази колоната от дълга сума: тя се пренася, вместо да я
     разпъне (виж и правилото за .big в cards.css). */
  .cards,
  #info.cards {
    grid-template-columns: repeat(2,minmax(0,1fr));
    gap: 8px;
  }

  /* Остане ли последната карта сама на реда си, тя го заема цял: половин карта
     до празно място изглежда като нещо, което липсва.
     Броенето е „of .card:not(.zero)“, а не обикновено nth-child, защото
     картите с нула са скрити, но си стоят в разметката — при обикновено
     броене една скрита карта разваля чет-нечет и правилото се хваща за
     погрешната. Браузър без този синтаксис просто не получава правилото и
     последната карта остава на половин ред, както беше. */
  @supports selector(:nth-child(1 of .card)) {
    .cards > .card:nth-last-child(1 of .card:not(.zero)):nth-child(odd of .card:not(.zero)) {
      grid-column: 1 / -1;
    }
  }

  /* Карта с нула не се показва на телефон. Класът се слага в PHP (zero_card()
     в partials/icons.php), защото въпросът е за числото, не за текста в
     клетката: „€ 0,00“, „0“ и „—“ са три различни низа и един и същ отговор.
     На широк екран картата остава — там нулата е новина, а не заемано място. */
  .card.zero {
    display: none;
  }

  /* Останат ли всички карти скрити, редицата им не бива да оставя празнина
     между заглавието и списъка под него. */
  .cards:not(:has(> .card:not(.zero))) {
    display: none;
  }

  .card,
  #info.cards > .card {
    padding: 13px 14px;
    border-radius: 16px;
  }

  .card .label {
    font-size: 13px;
    padding-right: 38px;
    margin-bottom: 5px;
  }

  .card-ico {
    top: 11px;
    right: 11px;
    width: 28px;
    height: 28px;
  }

  .card-ico svg {
    width: 15px;
    height: 15px;
  }

  .bar {
    height: 5px;
    margin: 7px 0 5px;
  }

  .foot,
  .card .foot {
    font-size: 10px;
    padding-top: 5px;
  }

  .flash {
    padding: 9px 12px;
    border-radius: 11px;
    font-size: 11px;
  }

  /* --------------------------------------------------------------- редове */
  .thead {
    font-size: 10px;
    letter-spacing: .04em;
    padding: 0 8px 5px;
  }

  .row {
    padding: 6px 8px;
    border-radius: 12px;
  }

  .row .name {
    font-size: 13px;
  }

  /* Един ред на клетка. На широк екран дълго име се пречупва и редът просто
     става по-висок; тук колоната е три пъти по-тясна и същото име става на
     четири реда — списъкът престава да е списък. Затова името и редът под
     него се съкращават с многоточие, а цялото стои в картата, която редът
     отваря. */
  .row .name-block > .name,
  .row .name-block > .sub,
  .child .name-block > .name,
  .child .name-block > .sub,
  .money-row .client > .name {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  .row > .sub,
  .child > .sub,
  .row .sub,
  .work-proj .sub {
    font-size: 12px;
  }

  [data-table] > .rows,
  [data-table] .bucket > .rows,
  [data-table] .kids,
  .rows {
    row-gap: 6px;
    gap: 6px;
  }

  /* Лакътят пада. Той рисува връзката „това е под онова“ на широк екран, къде
     то вложеният ред започва цяла колона навътре. На телефон отстъпът е 8px и
     чертичката не свързва нищо — тя е шум точно там, където ширината е малко,
     а отместването на самия ред вече казва същото. */
  .elbow {
    display: none;
  }

  .child {
    padding: 0 9px;
    min-height: 30px;
    border-radius: 9px;
    margin-left: 8px;
  }

  .group {
    padding: 3px 8px 8px;
    border-radius: 14px;
  }

  .group > .row {
    padding: 6px 6px 6px 0;
    min-height: 48px;
  }

  .bucket {
    margin-top: 10px;
    padding-top: 10px;
  }

  .bucket > header {
    margin-bottom: 8px;
    gap: 7px;
  }

  .bucket > header b {
    font-size: 15px;
  }

  .bucket > header span,
  .bucket > header i {
    font-size: 11px;
  }

  .section-part + .section-part {
    margin-top: 12px;
    padding-top: 12px;
  }

  /* ------------------------------------------------------------- значки */
  .glyph {
    width: 32px;
    height: 32px;
  }

  .glyph svg {
    width: 19px;
    height: 19px;
  }

  .glyph.sm {
    width: 21px;
    height: 21px;
  }

  .glyph.sm svg {
    width: 12px;
    height: 12px;
  }

  .money-row .client .glyph {
    width: 28px;
    height: 28px;
  }

  .money-row .client .glyph svg {
    width: 16px;
    height: 16px;
  }

  /* Качено лого в ред: 16px вместо 21. Снимка тежи повече от плоско цветно
     квадратче със същия размер, затова се смъква с една стъпка.
     Височината върви с ширината, за да остане квадрат — значката е квадрат с
     30% ъгъл, а не легнало правоъгълниче.
     `:not(.lg):not(.xl)` пази другите два размера: този в списъка с проекти
     (30px) и този в заглавието на проекта (42px), които имат своя мярка. */
  .code.logo:not(.lg):not(.xl) {
    width: 16px;
    height: 16px;
  }

  .code.lg {
    width: 30px;
    height: 30px;
    font-size: 11px;
  }

  .code.xl {
    width: 42px;
    height: 42px;
    font-size: 14px;
  }

  /* Значката на проекта стои до името му, а не сама на реда над него.
     Досега блокът с името нямаше зададена гъвкавост, тоест мереше се по
     най-дългото в себе си — реда „клиент · вид · адрес“ — и понеже той е
     по-широк от екрана, целият блок се пренасяше под значката. Сега блокът
     се свива до наличното (`flex: 1 1 0` + `min-width: 0`), а редът под
     името се пренася в него. */
  /* Редът си остава с пренасяне — бутоните трябва да слязат под двойката. */
  .proj-head {
    gap: 10px;
    align-items: center;
  }

  .proj-head > div {
    flex: 1 1 0;
    min-width: 0;
  }

  /* Редът под името е един ред текст, не редица от парчета: като flex
     иконката оставаше сама на първия ред, а думите слизаха под нея. Тук той е
     блок, а иконката върви inline с първата дума. Адресът е една дума и не се
     пречупва сам — затова му се разрешава изрично. */
  .proj-head .sub {
    display: block;
    overflow-wrap: anywhere;
  }

  .proj-head .sub svg {
    display: inline-block;
    vertical-align: -2px;
    margin-right: 5px;
  }

  /* Бутоните минават на свой ред под двойката значка + име. (project.css вече
     им дава width:100% под 900px; тук се добавя само основата за пренасянето.) */
  .proj-head .actions {
    flex: 1 0 100%;
    margin-top: 2px;
  }

  .tag {
    padding: 3px 8px;
    font-size: 11px;
    gap: 4px;
  }

  .spaced-tag {
    height: 26px;
    padding: 0 11px;
    font-size: 11px;
    gap: 6px;
  }

  .kind-tag {
    height: 15px;
    padding: 0 6px;
    font-size: 10px;
  }

  /* Чипът в ред: досега 28px и 14px шрифт, тоест по-едър от всичко около
     себе си, след като редът слезе на 13px. */
  .row .tchip {
    height: 24px;
    padding: 0 7px;
    font-size: 12px;
    gap: 4px;
    border-radius: 7px;
  }

  .duepill,
  .duedate {
    padding: 3px 8px;
    font-size: 11px;
    font-weight: 600;
  }

  .duedate {
    padding: 3px 0;
  }

  .due-plain {
    font-size: 11px;
  }

  .check {
    width: 19px;
    height: 19px;
    border-width: 2px;
  }

  /* ------------------------------------------------------------ контроли */
  /* Един мащаб за всичко, което се пипа: поле 38, бутон 32, филтър 34. Така
     ред с поле и бутон до него не изглежда като две различни системи. */
  /* 12px, не 11: с главни букви „РАЗПИСКА“ държи ширината си от разредката и
     формата на буквите; с малки същият размер се чете с една идея по-дребен. */
  .btn {
    height: 32px;
    padding: 0 12px;
    font-size: 12px;
    gap: 5px;
  }

  .btn svg {
    width: 13px;
    height: 13px;
  }

  .btn.compact {
    height: 26px;
    padding: 0 10px;
    font-size: 11px;
  }

  .btn .count {
    min-width: 17px;
    height: 17px;
    padding: 0 5px;
    font-size: 10px;
  }

  .actions {
    gap: 6px;
  }

  .full {
    height: 40px;
  }

  input:where(:not([type=checkbox]):not([type=radio]):not([type=file]):not([type=hidden]):not([type=submit])),
  select,
  .field-box {
    height: 38px;
    padding: 0 11px;
    border-radius: 7px;
  }

  select {
    padding-right: 36px;
    background-position: right 12px center;
    background-size: 14px 14px;
  }

  /* Датата на iPhone. Safari рисува полето за дата като собствен контрол:
     не се свива под „естествената“ си ширина, каквато и да е колоната, и
     центрира текста. Без собствения вид то е поле като всяко друго — пълна
     ширина на реда си, текстът вляво, и не излиза от рамката. */
  input[type=date],
  input[type=time],
  input[type=datetime-local] {
    -webkit-appearance: none;
    appearance: none;
    display: flex;
    align-items: center;
    min-width: 0;
    max-width: 100%;
    text-align: left;
    /* Без собствения вид Safari лепи стойността в горния край на полето.
       Редът е висок колкото вътрешността на полето (38px без рамката), така
       че текстът стои по средата както във всяко друго поле. */
    line-height: 36px;
  }

  input[type=date]::-webkit-date-and-time-value,
  input[type=time]::-webkit-date-and-time-value,
  input[type=datetime-local]::-webkit-date-and-time-value {
    text-align: left;
    margin: 0;
    height: auto;
    line-height: inherit;
  }

  /* Двете колони във формата не растат по съдържанието си: широко поле се
     свива в колоната, вместо да я избута извън панела. */
  .modal .form-row,
  .modal .form-row.amount-date-method,
  .modal .form-row.amount-period-basis,
  .pay-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  /* Сума и Период се събират на първия ред, така че Основанието пада само на
     втория и съседната клетка остава празна. Затова взема целия ред: в половин
     колона „за изтекъл период“ се реже, а мястото до него не върши работа. */
  .modal .form-row.amount-period-basis > .field:last-child {
    grid-column: 1 / -1;
  }


  textarea {
    padding: 9px 11px;
    border-radius: 11px;
  }

  /* Заглавието на два реда взема мярката на полетата тук, не на бележките. */
  textarea.title-area {
    padding: 8px 11px;
    border-radius: 7px;
  }

  label {
    font-size: 11px;
    margin-bottom: 4px;
  }

  .field {
    margin-bottom: 10px;
  }

  .inline-form {
    gap: 8px;
  }
}

/* ========================================================= 4. КОЛОНИТЕ */
/*
 * Дотук списъците на телефон пазеха всичките си колони и се плъзгаха настрани
 * вътре в секцията си. Това е честно, но не се ползва: дясната половина на
 * реда просто не се вижда и никой не я търси с пръст.
 *
 * Затова всяка таблица си има телефонен вид: остават колоните, заради които
 * се отваря на телефон, и се побират в ширината. Останалите падат с
 * display:none, а не с нулева ширина — клетките след тях се преместват сами в
 * останалите коловози, защото решетката ги нарежда по ред. Затова броят на
 * коловозите и броят на видимите клетки трябва да си отговарят точно; на
 * всяка таблица долу е написано кои клетки остават.
 *
 * Пълните данни не се губят: всеки ред отваря картата си (попъп или страница),
 * където стои всичко.
 */
@media (max-width:900px) {
  /* Списъкът вече се побира, така че секцията няма какво да плъзга. Правото
     ѝ да го прави обаче остава: под 375px — стар iPhone SE, или телефон със
     смален шрифт — някоя от таблиците пак може да прелее, и тогава е по-добре
     да се плъзне, отколкото да се отреже. */
  [data-table] {
    min-width: 0;
  }

  /* ------------------------------------------------------ Проекти (t-proj) */
  /* Две колони, един ред: името вляво, платено/стойност вдясно.
     Отпадат клиентът, статусът, отворените и просрочените задачи и „последно“.
     Статусът е това, което освобождава мястото: той е тагът с най-дълъг текст
     на реда („на пауза“, „завършен“), а състоянието на проекта се чете и от
     фона на самия ред — приключеният е плътен, архивираният е щрихован. */
  [data-table]:has(> .thead.t-proj) {
    grid-template-columns:
      minmax(0,1fr)
      max-content;
  }

  .t-proj > :nth-child(2),
  .t-proj > :nth-child(3),
  .t-proj > :nth-child(4),
  .t-proj > :nth-child(5),
  .t-proj > :nth-child(7) {
    display: none;
  }

  /* --------------------------------------------------- Клиенти (t-cli) */
  /* Остават: 1 стрелка · 2 клиент/проект · 5 дължимо.
     Отпадат: брой проекти, задачи, платено, последно. */
  [data-table]:has(> .thead.t-cli) {
    grid-template-columns:
      max-content
      minmax(0,1fr)
      max-content;
  }

  .t-cli > :nth-child(3),
  .t-cli > :nth-child(4),
  .t-cli > :nth-child(6),
  .t-cli > :nth-child(7) {
    display: none;
  }

  /* Вложеният ред (проект или план под клиента) чете същите две колони:
     остават 1 име и 4 дължимо. */
  .t-cli-kid > :nth-child(2),
  .t-cli-kid > :nth-child(3),
  .t-cli-kid > :nth-child(5),
  .t-cli-kid > :nth-child(6) {
    display: none;
  }

  /* Браузър без ::details-content не може да върже вложените редове към
     таблицата и tables.css му дава свой набор от твърди колони; тук той
     получава телефонния. */
  @supports not selector(::details-content) {
    [data-table]:has(> .thead.t-cli) :is(.thead, .row, .child) {
      grid-template-columns: 20px minmax(0,1fr) max-content;
    }
  }

  /* --------------------------------------------------- Абонаменти (t-sub) */
  /* Остават: 1 име+клиент · 3 период · 4 сума.
     Отпадат: статус, следващо таксуване, тази година.
     Периодът измества датата на следващото таксуване, защото казва какво Е
     планът („на всеки месец“), а не кога е следващото плащане по него — на
     екран, който се отваря да се види кой какво плаща, първото е въпросът.
     Датата остава в картата на абонамента. Тук периодът се изписва съкратено
     („1м“, „6м“, „1г“) от самия шаблон, за да се побере в две-три букви. */
  [data-table]:has(> .thead.t-sub) {
    grid-template-columns:
      minmax(0,1fr)
      max-content
      max-content;
  }

  .t-sub > :nth-child(2),
  .t-sub > :nth-child(5),
  .t-sub > :nth-child(6) {
    display: none;
  }

  /* Съкратеният период е две-три букви в колона, широка колкото заглавието ѝ:
     подравнен наляво, той увисва в единия ѝ край. Центрира се заедно със
     заглавието — правилото хваща и заглавния ред, защото клетката е трета и
     в двата. */
  .t-sub > :nth-child(3) {
    text-align: center;
  }


  /* ------------------------------------------------------- Пари (t-money) */
  /*
   * Осем колони не се побират по никакъв начин, а изборът КОИ да останат е
   * същината. Дотук оставаха клиент, дата, сума, статус — редът казваше
   * „Венелин Калинов € 300“, тоест кой и колко, но не и ЗА КАКВО. На екран,
   * който изброява плащания, това е първият въпрос.
   *
   * Два етажа, четири неща и действието:
   *   горе   проект / абонамент ················ сума
   *   долу   клиент ············ дата · бутоните
   *
   * Отпадат основанието (то повтаря плана — „период: 01.01–30.06“ до
   * „шестмесечно“), методът на плащане и тагът със статуса. Статусът не се
   * губи: фонът на реда е червен при просрочено и оранжев при чакащо, сумата е
   * в същия цвят, а бутонът го казва с думи. Три знака за едно нещо са два в
   * повече при тази ширина.
   */
  [data-table] > .thead.t-money {
    display: none;
  }

  /* Фиксирани и тук, по същата причина като на широк екран: двата списъка са
     отделни решетки и по съдържание колоните им излизаха различни — дясната
     се мереше по сумата, а „€ 1 600“ и „€ 300“ не са еднакво широки.
     86px събира и „€ 12 480,00“; повече от това се пренася. */
  [data-table]:has(> .thead.t-money),
  .money-open[data-table]:has(> .thead.t-money) {
    grid-template-columns:
      minmax(0,1fr)
      fit-content(108px)
      86px;
  }

  /* Средната клетка на втория ред: при платено датата, при неплатено периодът
     („септември 2026“ е най-дългият) или основанието на проект. Расте до
     108px по съдържанието си, оттам нататък се отрязва с многоточие. Сумата
     до нея е с фиксирана ширина, така че двата списъка пак се четат в колона. */
  .t-money > :nth-child(4) {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .t-money > :nth-child(3),
  .t-money > :nth-child(6),
  .t-money > :nth-child(7) {
    display: none;
  }

  /* На широк екран tables.css крие клетката за дата при неплатените; тук тя
     носи периода и се вижда. */
  .money-open .t-money > :nth-child(4) {
    display: block;
  }

  .row.t-money {
    row-gap: 2px;
    padding: 7px 9px;
  }

  /* Проектът взема двата леви коловоза, за да има къде да се изпише. */
  .t-money > :nth-child(2) {
    grid-column: 1 / 3;
    grid-row: 1;
  }

  .t-money > :nth-child(5) {
    grid-column: 3;
    grid-row: 1;
  }

  .t-money > :nth-child(1) {
    grid-column: 1;
    grid-row: 2;
  }

  .t-money > :nth-child(4) {
    grid-column: 2;
    grid-row: 2;
  }

  .t-money > :nth-child(8) {
    grid-column: 3;
    grid-row: 2;
  }

  /* Дясната половина е числова и се чете отдясно наляво. */
  .t-money > :nth-child(4),
  .t-money > :nth-child(5) {
    text-align: right;
  }

  /* Бутонът остава само знак. С дума той е 103px от 337 налични; като знак е
     30. Името му не се губи — то е в aria-label (виж money.php), а действието
     се потвърждава с въпрос, така че сгрешен допир не минава мълчаливо. */
  .money-row .actions {
    justify-content: flex-end;
    gap: 5px;
  }

  .money-row .actions .btn-text {
    display: none;
  }

  .money-row .actions .btn {
    height: 30px;
    width: 30px;
    padding: 0;
    gap: 0;
  }

  /* Тежестта се разменя заедно с местата: горе е това, за което са парите, и
     то носи гласа на заглавие; клиентът отдолу е притихнал.
     `:not(.glyph)` не е излишно: класът .sub значи две неща в тази система —
     „вторичен текст“ и „това е абонамент“ върху кръгчето. Без изключението
     правилото оцветяваше и кръгчето, а то е мастилено, тоест иконата вътре
     ставаше черна върху черно и изчезваше.
     Едно име на ред: пренесе ли се, съседните редове престават да са еднакво
     високи, а целият текст и без това стои в картата на плащането. */
  .money-row .origin > .sub:not(.glyph) {
    font-size: 13px;
    font-weight: 600;
    color: var(--text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .money-row .client .name {
    font-size: 12px;
    font-weight: 400;
    color: var(--muted);
  }

  /* Кръгчето с човечето отпада: то е едно и също на всеки ред, тоест не
     различава нищо, а на втория етаж стои и до значката на проекта отгоре —
     две икони една под друга за един ред. */
  .money-row .client .glyph {
    display: none;
  }

  .money-row .client {
    gap: 0;
  }

  /* -------------------------------------------- Табло · пари (t-owed) */
  /* Остават: 1 проект+клиент · 4 сума. Отпадат: статус и разбивката. */
  [data-table]:has(.row.t-owed) {
    grid-template-columns:
      minmax(0,1fr)
      max-content;
  }

  .t-owed > :nth-child(2),
  .t-owed > :nth-child(3) {
    display: none;
  }

  /* ------------------------------------------ Табло · длъжници (t-debt) */
  /* Остават: 1 клиент · 4 сума. Две колони, нищо между тях.
     Средната колона — „133 дни“ на реда на клиента — отпада ЦЯЛАТА, защото е
     пълна само на един ред: под клиента стоят фактурите му, а те нямат какво
     да сложат в нея. Тоест едно число държеше 90px на шест реда празнина.
     Просрочката не се губи: редът на клиента е червен, сумата е червена, а
     „най-стара: …“ под името казва от кога. */
  [data-table]:has(.row.t-debt) {
    grid-template-columns:
      minmax(0,1fr)
      max-content;
  }

  .t-debt > :nth-child(2),
  .t-debt > :nth-child(3) {
    display: none;
  }

  /* „133 дни“ е това, което остана от скритата колона, и е причината редът да
     е червен — носи тежестта, която имаше и там, а не тази на подзаглавие. */
  .t-debt .sub.only-phone {
    font-weight: 600;
  }

  /* Фактурата под длъжника: остават 1 основание и 4 сума — същите две колони
     като на клиента, така че сумите застават една под друга сами, без да им
     се сочи коловоз. */
  .t-debt-kid > :nth-child(2),
  .t-debt-kid > :nth-child(3) {
    display: none;
  }

  /* ------------------------------------------- Табло · задачи (t-work) */
  /* Задачата не губи нищо, а се пренарежда на два етажа:
       горе   отметка · заглавие, през цялата ширина
       долу   ········· проект · подзадачи · срок
     Колоната с подзадачите е `max-content`: няма ли нито една задача в
     списъка с подзадачи, всички клетки са празни, колоната е нула и не отнема
     нищо от проекта. */
  /* Колоната със срока е с таван, а не „колкото държи“. Чипът „12.09.2026 ·
     просрочена“ е 180 от 355-те налични пиксела и понеже колоните са общи за
     целия списък, ЕДНА просрочена задача стесняваше проекта на всеки ред.
     fit-content(118px) го спира на 118 и му позволява да се пренесе на два
     реда; текстът на самия чип не се губи. Прескочи ли една дума този таван,
     колоната пак пораства — това е подът на fit-content(), не отрязване. */
  [data-table]:has(.row.t-work) {
    grid-template-columns:
      max-content
      minmax(0,1fr)
      max-content
      fit-content(118px);
  }

  .t-work .duepill,
  .t-work .duedate {
    white-space: normal;
    text-align: right;
  }

  .row.t-work {
    row-gap: 3px;
    align-items: center;
  }

  .t-work > :nth-child(1) {
    grid-column: 1;
    grid-row: 1 / span 2;
  }

  .t-work > :nth-child(2) {
    grid-column: 2 / -1;
    grid-row: 1;
  }

  .t-work > :nth-child(3) {
    grid-column: 2;
    grid-row: 2;
  }

  .t-work > :nth-child(4) {
    grid-column: 3;
    grid-row: 2;
  }

  .t-work > :nth-child(5) {
    grid-column: 4;
    grid-row: 2;
    text-align: right;
  }

  /* --------------------------------------------------------- Архив (t-arch) */
  /* Остават: 1 име · 4 бутонът за връщане. Статусът и кога е прибрано отпадат:
     в архива влиза само приключеното, а „преди 2 месеца“ изяждаше половината
     ред и оставяше името на четири реда. И двете стоят в картата. */
  [data-table]:has(.row.t-arch) {
    grid-template-columns:
      minmax(0,1fr)
      max-content;
  }

  .t-arch > :nth-child(2),
  .t-arch > :nth-child(3) {
    display: none;
  }

  /* ------------------------------------- таблици, които не са списъци */
  [data-table]:has(.row.t-tok) {
    grid-template-columns: 1fr;
  }
}

/* ======================================== 5. РАДИУСИ, БОРД, НАСТРОЙКИ, ПОПЪП */
/*
 * Ъгълът е пропорция, не число: 20px закръгление на карта с 20px поле изглежда
 * меко, а същите 20px на карта с 13px поле изглеждат надуто. Затова всичко,
 * което се смалява горе, си смъква и ъгъла — приблизително със същата част.
 * Кръговете (999px, 50%, 30%) не се пипат: те се мащабират сами.
 */
@media (max-width:900px) {
  /* ------------------------------------------------------- Проекти · грид */
  .project-grid {
    gap: 8px;
  }

  .pcard {
    gap: 8px;
    padding: 12px;
    border-radius: 15px;
  }

  /* ------------------------------------------------------------- Клиенти */
  details.client.group > summary {
    padding: 6px 8px 6px 0;
    min-height: 48px;
    border-radius: 11px;
  }

  .thead.t-cli {
    padding-right: 14px;
  }

  /* --------------------------------------------------------------- Борд */
  /* Свитата колона („идеите“ вляво, „готовите“ вдясно) е чертата с името си
     напряко. На широк екран тя стои отстрани на дъската, защото дъската е
     редица от колони. На телефон дъската е ЕДНА колона една под друга, така
     че отстрани няма страна — свитите отиват там, където им е мястото в този
     ред: „идеите“ отгоре, „готовите“ отдолу.
     Реденето идва само от посоката на редицата: в разметката стрип-идеи,
     дъска, стрип-готови са точно в този ред. */
  .board-row {
    flex-direction: column;
    gap: 10px;
  }

  /* Чертата се завърта на легнало: пълна ширина, три пиксела висока. */
  .colstrip {
    width: auto;
    height: 3px;
    margin: 6px 0;
  }

  /* Името ляга по четене, вместо да е обърнато на четвърт. */
  .colstrip .colhead {
    transform: translate(-50%,-50%);
  }

  .col {
    min-height: 0;
    padding: 8px;
    border-radius: 12px;
  }

  .col .zone {
    gap: 8px;
    border-radius: 13px;
  }

  .tcard {
    padding: 8px 10px 10px;
    border-radius: 7px;
  }

  /* ---------------------------------------------------------- Настройки */
  .settings-card {
    padding: 14px;
    border-radius: 18px;
  }

  /* Празна карта с факт не се показва. Класът се слага в PHP (empty_card() в
     partials/icons.php), защото въпросът е за стойността, а не за тирето,
     което тя рисува. Останат ли всички празни, редицата им също пада, за да
     не зее празно между заглавието и следващата секция. */
  .mcard.is-empty {
    display: none;
  }

  .mcards:not(:has(> .mcard:not(.is-empty))) {
    display: none;
  }

  /* Редът „Задачата се таксува отделно“: отметката горе, полето за сума на
     свой ред под нея. Едно до друго те не се събират — обяснението под
     заглавието е две изречения и притиска полето до около 90px, а то е поле
     за пари и трябва да се улучва с пръст.
     Обяснението пада: то казва какво прави отметката ПРЕДИ да е натисната, а
     на телефон това е ред и половина текст върху всяка задача, независимо че
     таксуването е рядкото. Заглавието на отметката го казва достатъчно. */
  .bill-row {
    flex-direction: column;
    align-items: stretch;
    gap: 8px;
    min-height: 0;
  }

  .bill-check small {
    display: none;
  }

  .amount-wrap {
    height: 38px;
  }

  /* Височината на „Бъг“ идва от .field-box заедно с останалите полета горе. */
  .bug-chip {
    font-size: 13px;
  }

  /* Полето заема целия си ред, а не 96px в средата му. */
  .amount-wrap input {
    width: auto;
    flex: 1 1 auto;
    min-width: 0;
  }

  /* ------------------------------------------------------------- Попъпи */
  /* Попъпът на телефон е почти целият екран, така че носи ъгъла на екрана,
     не на карта. */
  .modal-box {
    border-radius: 18px;
  }

  .modal-box.palette {
    border-radius: 16px;
  }

  .paper {
    border-radius: 12px;
    padding: 14px;
  }

  /* -------------------------------------------------------------- дребно */
  .avatar-tile {
    width: 42px;
    height: 42px;
    border-radius: 13px;
  }

  .avatar-row {
    gap: 11px;
    margin-bottom: 14px;
  }

  .mono {
    font-size: 14px;
    letter-spacing: .08em;
  }
}

/* =============================================== попъпите на телефон: панели */
/*
 * На телефон всеки попъп идва отдолу и застава на долния ръб на екрана —
 * панелът, който iOS ползва за всичко: изтегля се нагоре, широк е колкото
 * екрана, заоблен е само отгоре и се дърпа надолу, за да се затвори.
 *
 * Защо не центрирана кутия. Центрираната кутия иска поле от четирите си
 * страни, за да се чете като кутия — на 375px това са 32px, тоест една
 * десета от ширината, точно там, където полетата и таблиците вътре я нямат.
 * Освен това идва от средата на екрана, където палецът не стига, докато
 * панелът застава точно под него.
 *
 * Всичко тук стои в един блок и се маха наведнъж; над 640px попъпът си остава
 * центрираната кутия, каквато е бил.
 */
@media (max-width:640px) {
  /*
   * Панелът се закача за долния ръб на екрана и диалогът НЕ е скролируем.
   *
   * Дотук панелът стоеше в решетката на диалога с `place-items: end`, а
   * диалогът беше `overflow: hidden`. На истински iPhone това се чупеше така:
   * натискаш поле в панела („Добави подзадача…“), клавиатурата излиза и iOS
   * скролва най-близкия скролируем предшественик, за да сложи полето над нея.
   * `overflow: hidden` кутия Е скролируема — програмно, не с пръст. Тоест iOS
   * скролва диалога, панелът се качва нагоре, а когато клавиатурата се
   * прибере, диалогът си остава скролнат и няма как да се върне: горният ръб
   * на панела е над екрана, долният по средата, отдолу зее затъмнението.
   * На широк екран клавиатура няма и нищо не се задейства.
   *
   * Две неща го спират. Панелът е `position: fixed`, тоест не е в потока на
   * диалога и никакъв скрол на диалога не го мести. И диалогът е
   * `overflow: visible`, тоест изобщо не е скролируем: iOS няма какво да
   * скролне освен самия панел (`overflow-y: auto`), а него потребителят може
   * и сам да върне с пръст.
   */
  dialog.modal[open],
  dialog.confirm[open] {
    height: 100dvh;
    max-height: 100dvh;
    overflow: visible;
  }

  .modal-box,
  .modal-box.wide,
  .modal-box.palette,
  .confirm-box {
    position: fixed;
    left: 0;
    right: 0;
    /* --keyboard е колко от долния ръб е скрит под клавиатурата на iPhone;
       слага го app.js от visualViewport и е 0, докато клавиатура няма.
       Панелът се вдига над нея и се скъсява със същото, вместо Safari да
       скролва цялата страница, за да покаже полето — точно този скрол го
       оставяше изместен и след като клавиатурата се прибере. */
    bottom: var(--keyboard, 0px);
    width: auto;
    max-width: none;
    margin: 0;
    border-radius: 20px 20px 0 0;
    /* Оставя се да се вижда колкото затъмнение да се разбере, че отдолу има
       страница и че панелът се затваря с натискане встрани. */
    max-height: calc(92dvh - var(--keyboard, 0px));
    overflow-y: auto;
    overscroll-behavior: contain;
  }

  /* Докато има отворен панел, страницата отдолу стои на място (app.js слага
     класа и пази реда, на който беше). Без това iOS дърпа страницата с
     ластика и панелът, макар и fixed, подскача с нея. */
  body.sheet-lock {
    position: fixed;
    left: 0;
    right: 0;
    overflow: hidden;
  }

  html:has(body.sheet-lock) {
    overscroll-behavior: none;
  }

  /* Долният ръб е ръбът на екрана: жестът за начало на iPhone минава оттам. */
  .modal-box {
    padding-bottom: calc(18px + env(safe-area-inset-bottom));
  }

  .confirm-box {
    padding-bottom: calc(18px + env(safe-area-inset-bottom));
  }

  /* Търсачката идва отдолу като всеки друг попъп. `align-self` и полето
     отгоре ѝ идват от modal.css, където тя е лента, закачена под горния ръб;
     тук и двете се отменят, за да сяда на долния ръб като панел. */
  /* При `position: fixed` подравняването в решетката на диалога отпада само;
     тук остава само отстъпът за жеста за начало. */
  .modal-box.palette {
    margin-top: 0;
    padding-bottom: calc(8px + env(safe-area-inset-bottom));
  }

  /* Заглавната лента остава на мястото си, докато съдържанието се плъзга под
     нея — така „Затвори“ е под палеца по всяко време.
     Отметката е -18px, а не 0, защото лепенето се мери от вътрешния ръб на
     скрола, тоест ПОД полето на кутията. С нула лентата залепваше 18px
     по-надолу и през тази ивица се виждаше съдържанието, което минава отгоре.
     Числото е същите 18px, с които лентата е издърпана нагоре по-горе. */
  .modal-head {
    position: sticky;
    top: -18px;
    z-index: 2;
    background: var(--card);
    border-radius: 20px 20px 0 0;
  }

  /* Заглавието слиза от 22px на 17. При 22 дълго име на задача става на три
     реда и изяжда една трета от панела, преди да се стигне до съдържанието му.
     Междуредието се вдига от 1 на 1.2: то беше премерено за ЕДИН ред, а
     пренесе ли се, при 1 буквите от съседните редове почти се допират. */
  .modal-title {
    font-size: 17px;
    line-height: 1.2;
  }

  /* Дъното на панела е ръбът на екрана, а не ъгъл на кутия.
     Редът с бутоните стои залепен долу: скролва се само средата на панела,
     а „Отказ“ и „Запази“ са винаги под пръста — вляво и вдясно, с равна
     ширина. Второстепенните действия (архив, триене) слизат на ред под тях,
     както прави iOS с разрушителните. */
  .modal-foot {
    position: sticky;
    /* Залепването се мери от съдържанието на панела, не от ръба му: отстъпът
       на кутията (18px + жестът за начало) се изважда, за да легне на дъното. */
    bottom: calc(-18px - env(safe-area-inset-bottom));
    z-index: 3;
    justify-content: space-between;
    border-radius: 0;
    margin-bottom: calc(-18px - env(safe-area-inset-bottom));
    /* Бутоните слизат в мястото на лентата с раздели: отдолу остава само
       жестът за начало, не още един ред въздух. Фонът е този на панела, за да
       не се чете като отделна кутия — в тъмния режим разликата биеше на очи. */
    padding-top: 10px;
    padding-bottom: calc(8px + env(safe-area-inset-bottom));
    background: var(--card);
  }

  .modal-foot > .btn,
  .modal-foot.spread .foot-group.end > .btn {
    flex: 1 1 0;
    min-width: 0;
    height: 44px;
    font-size: 14px;
  }

  /* Един ред: „Изтрий“ (и „Архивирай“, ако го има) най-вляво, тесни колкото
     думата си; „Отказ“ и „Запази“ си делят остатъка, но не под 170px — при
     повече и по-дълги второстепенни бутони (разписка, напомняне) главните
     слизат на свой ред, вместо да се смачкат. Групата без .end се разтваря,
     за да не оставя празен ред, когато е празна. */
  .modal-foot.spread {
    justify-content: flex-start;
  }

  .modal-foot.spread .foot-group.end {
    flex: 1 1 170px;
    min-width: 0;
    margin-left: 0;
    gap: 8px;
  }

  .modal-foot.spread .foot-group:not(.end) {
    display: contents;
  }

  .modal-foot.spread .foot-group:not(.end) > .btn {
    flex: 0 0 auto;
    min-width: 0;
    height: 44px;
    padding: 0 12px;
    font-size: 14px;
  }

  /* Бележката до бутона („Платено таксуване… не се трие“) няма място на реда. */
  .modal-foot.spread .foot-group:not(.end) > .muted {
    display: none;
  }

  /* Вдигната клавиатура (app.js слага html.kb-up заедно с --keyboard).
     Над клавиатурата остава по-малко от половин екран; ако в него стоят и
     залепената глава, и залепените бутони, и отстъпът за жеста за начало,
     за самото писане остават два реда. Затова докато се пише: панелът може
     да стигне до горния ръб, главата и бутоните се отлепят и скролват с
     останалото, а долният отстъп пада — клавиатурата покрива жеста. */
  html.kb-up .modal-box,
  html.kb-up .modal-box.wide,
  html.kb-up .modal-box.palette,
  html.kb-up .confirm-box {
    max-height: calc(100dvh - var(--keyboard, 0px) - env(safe-area-inset-top) - 8px);
    padding-bottom: 18px;
  }

  html.kb-up .modal-head {
    position: static;
  }

  html.kb-up .modal-foot {
    position: static;
    margin-bottom: -18px;
    padding-bottom: 10px;
  }

  html.kb-up .confirm-box {
    padding-bottom: 18px;
  }

  /* Дръжката: чертичката, която казва „това се дърпа“. Рисува се от заглавната
     лента, защото тя е първото нещо в панела и остава горе при плъзгане. */
  .modal-head::before,
  .confirm-box::before {
    content: "";
    position: absolute;
    top: 7px;
    left: 50%;
    transform: translateX(-50%);
    width: 36px;
    height: 4px;
    border-radius: 999px;
    background: color-mix(in srgb,var(--text) 22%,transparent);
  }

  .modal-head {
    padding-top: 20px;
  }

  /* Само полето за дръжката. `position` НЕ се пипа тук: кутията е `fixed`
     по-горе, а fixed също е опора за ::before — едно `relative` на това място
     я сваляше от долния ръб и я връщаше по средата като малка кутия. */
  .confirm-box {
    padding-top: 26px;
  }

  /* Панел без заглавна лента (фрагмент, който не носи .modal-head) няма как да
     нарисува дръжката — там горното поле остава нормалното. */

  /* Изтегляне нагоре вместо появяване в средата. Кривата е тази на iOS:
     тръгва бързо и спира меко. */
  @keyframes sheet-in {
    from {
      transform: translateY(100%);
    }
    to {
      transform: none;
    }
  }

  dialog.modal[open] .modal-box,
  dialog.confirm[open] .confirm-box {
    animation: sheet-in .3s cubic-bezier(.32,.72,0,1) both;
  }

  @media (prefers-reduced-motion: reduce) {
    dialog.modal[open] .modal-box,
    dialog.confirm[open] .confirm-box {
      animation: none;
    }
  }

  /* Петте състояния на един ред, който се плъзга настрани.
     Като решетка те се делят поравно, а най-дългото име („Планирани“) не се
     побира в една пета от 375px — на три колони пък падаха на два реда и
     пак се режеха. Тук всяко хапче е широко колкото името си и редът се
     плъзга: това е лента с чипове, а не превключвател, който трябва да се
     види целия наведнъж — избраното състояние е едно и се вижда.
     Лентата излиза до ръбовете на панела (отрицателните полета са същите
     18px, с които той е отвътре), за да личи, че продължава. */
  .status-switch {
    display: flex;
    margin-left: -18px;
    margin-right: -18px;
    padding: 0 18px;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scrollbar-width: none;
  }

  .status-switch::-webkit-scrollbar {
    display: none;
  }

  .status-switch button {
    flex: none;
    height: 32px;
    padding: 0 12px;
    font-size: 11px;
    gap: 6px;
    white-space: nowrap;
  }

  .status-switch button .statemark svg {
    width: 14px;
    height: 14px;
  }

  /* Бутоните в потвърждението стават цели редове: на панел долу те са
     основното действие, а не две хапчета в средата на кутия. */
  .confirm-actions {
    flex-direction: column-reverse;
    gap: 8px;
  }

  .confirm-actions .btn {
    width: 100%;
    height: 44px;
    font-size: 12px;
  }
}
