/* ═══════════════ МОБІЛЬНИЙ ЗАСТОСУНОК ═══════════════

   ЖОДНОГО backdrop-filter. Розмиття під панелями — найдорожча частина
   кадру: воно перераховується щоразу, коли під ним щось рухається, тобто
   на КОЖНОМУ кадрі прокрутки. Саме через нього рух і виглядав рваним.
   Панелі тепер щільні: при .93–.95 прозорості різниці на око немає, а
   кадр коштує вдвічі дешевше.

   Значення — з design_handoff_crm_app/README.md, один в один. Це не
   «стиснутий десктоп»: у телефона свої поверхні, своя щільність і свої
   стани дотику замість наведення.

   Файл самодостатній: щоб прибрати застосунок, досить не підключати
   mobile.css і mobile.js — сторінка лишиться десктопною. */

:root {
  --m-bg:        #F6F3F0;   /* фон застосунку */
  --m-card:      #FFFFFF;   /* картка, блок */
  --m-raised:    #FFFDFB;   /* шторка */
  --m-sunken:    #FBF7F4;   /* підвал шторки, поле вводу */
  --m-tint:      #F5EDE3;   /* тінт кнопок і плашок */
  --m-tint-2:    #F5EFE8;
  --m-tint-3:    #F7F3EE;
  --m-tint-4:    #FAF6F1;
  --m-line:      #F4EFE9;   /* роздільник у картці */
  --m-line-2:    #F2E9DD;   /* роздільник у шторці */
  --m-line-3:    #F0E9E1;   /* межа картки-опції */
  --m-hair:      #EFE6DA;   /* hairline скла */
  --m-faint:     #B3A493;
  --m-mute:      #C0B0A0;
  --m-soft:      #6B5C50;
  --m-ink:       #2B231D;
  --m-sh-card:   0 1px 2px rgba(58, 44, 32, .05);
  --m-ease:      cubic-bezier(.16, 1, .3, 1);
  --m-pill:      cubic-bezier(.22, 1, .36, 1);
  /* Натиск: вниз різко, назад — з легким перельотом («желейно»). */
  --m-press-in:  cubic-bezier(.2, .8, .2, 1);
  --m-press-out: cubic-bezier(.34, 1.56, .64, 1);
  /* Перехід між екранами.

     --m-ease тут не годиться: вона проходить половину шляху за перші 9%
     часу. На короткій відстані це непомітно, а на ширину екрана читається
     як стрибок — екран уже майже на місці, коли анімація тільки почалась.
     Ця крива долає половину за чверть часу: рух видно від початку й до
     кінця. */
  --m-nav-ease: cubic-bezier(.35, .35, .25, 1);
  --m-nav-dur:  .4s;
}

/* Поки застосунок активний, десктопна сторінка не показується взагалі:
   інакше два списки жили б один під одним. */
/* Розділи веба тепер лежать в обгортках (#secOrders, #secMaterials) —
   правило «прямий нащадок body» їх більше не діставало, і десктопна
   сторінка світилась під застосунком. Ховаємо самі обгортки. */
body.m-app > header,
body.m-app > main,
body.m-app > #secOrders,
body.m-app > #secMaterials,
body.m-app > .bulk-wrap,
body.m-app > .mod-ov,
body.m-app > .dw-scrim { display: none !important; }
/* Фон сторінки під застосунком — кольору ПОЛОТНА (--m-bg).

   Раніше тут стояв #FCFAF8 — колір старої нижньої панелі: вона була
   суцільною смугою впритул до низу, і смужку, яку айфон лишає під
   оболонкою, фарбували в той самий колір, щоб вона читалась продовженням
   панелі. Панель стала плаваючою капсулою, а фарба лишилась — і та
   смужка перетворилась на світлу бежеву лінію біля самого низу екрана,
   бо #FCFAF8 світліший за полотно. Тепер зливається з фоном. */
/* overflow: hidden лишається ТІЛЬКИ на body — рівно як у робочому
   прикладі. На <html> його не ставимо: у застосунку з іконки айфон із
   таким html рахує вікно інакше, і фіксовані елементи впираються не в
   край екрана, а в межу розкладкового вікна. */
body.m-app { background: #F6F3F0; overflow: hidden; overscroll-behavior: none;
             height: 100vh; }
html:has(body.m-app) { background: #F6F3F0; }

#mApp { display: none; }
/* Оболонка розтягнута на все розкладкове вікно — і крапка.

   Задавати їй висоту (100dvh чи viewport-вимір) не можна: обидва бувають
   МЕНШИМИ за вікно — на айфоні з плаваючою панеллю Safari сторінка видима
   й ПІД нею, а visualViewport про це не знає. Саме звідси й бралась смуга
   під меню: оболонка закінчувалась там, де екран ще тривав. inset: 0
   такого дати не може.

   Підіймати щось над панеллю браузера ми більше не намагаємось: єдине, що
   міряємо, — клавіатура (--m-kb), і на неї підіймається тільки шторка. */
body.m-app #mApp {
  /* height: 100vh — як body у робочому прикладі. Тепер це безпечно: док
     став fixed і рахується від вікна, тож навіть якщо оболонка вилізе за
     межу, панель лишиться на місці. Заразом фон накриває смугу знизу. */
  display: block; position: fixed; top: 0; left: 0; right: 0;
  height: 100vh; bottom: 0;
  z-index: 10;
  background: var(--m-bg);
  font-family: var(--font-sans);
  -webkit-font-smoothing: antialiased;
  overflow: hidden;
}
#mApp *, #mApp *::before, #mApp *::after { box-sizing: border-box; }
/* Висота нижньої панелі — одним виразом. Раніше її міряв скрипт, і якщо
   вимір траплявся до того, як айфон повідомив безпечну зону, смуга
   статусів опинялась ПІД панеллю меню. */
/* Під іконками НЕМАЄ нічого.

   Тут стояв системний нижній відступ (env(safe-area-inset-bottom)) — саме
   він і був тією «підкладкою знизу»: смуга кольору панелі під іконками,
   через яку меню читалось як підвішене. Прибрано повністю: висота панелі —
   рівно висота ряду іконок, і низ панелі збігається з низом оболонки.

   Те, що система лишить нижче (смужка «додому», край екрана), — уже не
   наша поверхня; вона пофарбована в колір панелі через фон сторінки
   (див. body.m-app вище), тож виглядає продовженням меню, а не фоном. */
/* Висота панелі = ряд іконок плюс мінімум повітря над ними. Верхня межа
   через це лежить низько: панель не «підкладка під меню», а просто смуга
   з іконками на краю екрана. */
/* Док не смуга на весь низ, а плаваюча капсула: 64px висоти й 30px
   повітря під нею. --m-tabh лишається тим самим «скільки низу зайнято» —
   від нього рахуються і хвіст списку, і смуга фільтрів. */
/* Змінні дока — на :root, а не на #mApp.

   Док тепер живе прямо в body (щоб рахуватись від краю екрана, як у
   робочому прикладі), а туди значення з #mApp не наслідуються: капсула
   лишалась без розмірів і схлопувалась угорі екрана. */
:root {
  --m-dock-h: 62px;            /* висота капсули */
  --m-dock-btn: 46px;          /* кнопка всередині */
  --m-dock-cell: 58px;         /* крок пілюлі: кнопка + проміжок 6 */
  --m-dock-pad: 8px;           /* внутрішнє поле капсули */
  --m-dock-side: 20px;         /* поле дока від краю екрана */
  --m-top-h: 44px;             /* висота верхніх капсул: знак і аватарка */
  --m-bal-pad: 16px;           /* поле від краю капсули до вмісту */
  --m-bal-gap: 9px;            /* між значком, сумою й рискою */
  --m-top-gap: 8px;            /* однаковий проміжок між усіма капсулами */
  /* Повітря під доком. На айфоні системна безпечна зона додає ще 34px, і
     разом виходило 64 — панель висіла помітно високо. Тепер беремо від
     безпечної зони лише те, що потрібно, щоб не залізти під смужку
     «додому». Нижче вже нікуди: далі капсула полізла б за край екрана. */
  /* Орієнтир — таб-бар телеграма: під капсулою лишається смужка «додому»
     і більше нічого. На айфоні безпечна зона 34px, з них 14 з'їдаємо —
     виходить 20px до краю. Опустити ще нижче можна (мінімум 8), але тоді
     смужка ляже на саму капсулу. */
  /* Скільки низу накрила панель браузера — міряє скрипт (bindViewport).
     У застосунку з іконки й у Safari з прихованою панеллю це 0. */
  --m-browser-b: 0px;
  /* Просте число, БЕЗ env(safe-area-inset-bottom).

     Саме так зроблено в робочому прикладі: «полностью убираем
     env(safe-area-inset-bottom), кнопки уходят к самому низу». З env
     док відступав на 34px системної зони й висів високо. */
  /* Чисте число, без env() і без виміряних на льоту величин — так само,
     як у робочому прикладі. Усе, що рахувалось у JS, з'їдало низ. */
  /* Рівно стільки ж, скільки поля з боків (.tabdock left/right: 20px),
     щоб рамка навколо капсули була однакова з трьох сторін. */
  --m-dock-b: 20px;
  --m-keyb: 284px;             /* висота клавіатури айфона — на стільки підіймаємось */
  --m-tabh: calc(var(--m-dock-h) + var(--m-dock-b));
  --m-ease-soft: cubic-bezier(.22, 1, .36, 1);
  /* Крива для «входу» масштабу: повільний старт, м'який прихід. Пружинна
     крива тут не годиться — вона зривається з місця ривком. */
  --m-ease-in-soft: cubic-bezier(.45, .02, .3, 1);
  --m-ease-spring: cubic-bezier(.34, 1.4, .5, 1);
}
/* manipulation прибирає подвійний тап для зуму — разом із ним зникає й
   пауза перед кліком, через яку інтерфейс здавався млявим. */
#mApp, #mApp * { touch-action: manipulation; }
/* Списки гортаються звично, але сторінка під ними не тягнеться. */
/* ─── Прокрутка тільки вгору-вниз ───

   Тут була дірка, через яку сторінка «пливла» вбік. Правило вище дає всім
   вузлам touch-action: manipulation — а це дозвіл панорамувати по ОБОХ
   осях. Палець при гортанні ніколи не йде строго вертикально, і щойно він
   зносився вбік, браузер шукав, що б посунути горизонтально. Знаходив сам
   скролер: якщо задано лише overflow-y, друга вісь за специфікацією стає
   auto, тобто теж прокручується.

   Тому: усередині вертикального скролера дозволена ЛИШЕ вертикаль — і
   самому скролеру, і всьому, що в ньому лежить. Виняток — смуги, які
   гортаються вбік навмисно (капсули статусів): їм повертаємо горизонталь. */
#mApp .m-scroll, #mApp .m-scroll * { touch-action: pan-y; }
#mApp .m-scroll { overflow-x: hidden; overscroll-behavior-x: none; }
#mApp .m-sx, #mApp .m-sx * { touch-action: pan-x; }
#mApp .m-sx { overflow-x: auto; }
/* Синя підсвітка від дотику — це системний highlight мобільного браузера.
   Прибираємо його всюди й даємо натомість свою реакцію: елемент трохи
   присідає під пальцем. */
/* Док живе в body, поза оболонкою, тому правило має бути на всій
   сторінці — інакше айфон малює свій сірий прямокутник на кнопках дока. */
#mApp *, body.m-app > #mTabs, body.m-app > #mTabs * ,
body.m-app > #mVeil { -webkit-tap-highlight-color: transparent; }
body.m-app > #mTabs button { -webkit-touch-callout: none; user-select: none;
                             -webkit-user-select: none; }
#mApp :focus { outline: none; }

/* ─── Натиск ───

   Клас .press вішає скрипт (див. bindPress у mobile.js): він чекає мить
   перед підсвіткою й скасовує її, щойно палець рушив, — рівно як iOS
   усередині списку. :active тут НЕ використовується взагалі: на айфоні
   він вмикається на початку жесту й залипає на весь час інерції, тобто
   дає масштаб просто під час прокрутки.

   Дві криві: вниз — коротко й різко (--m-press-in), назад — з крихітним
   перельотом (--m-press-out), від якого натиск відчувається пружним, а
   не «підміненим кадром». */
#mApp button, #mApp [data-m], #mApp [data-pick], #mApp [data-opt], #mApp [data-st],
#mApp .m-card, #mApp .m-block, #mApp .m-profit, #mApp .m-chip, #mApp .m-tab {
  transition: transform .42s var(--m-ease-spring), background .18s ease,
              color .18s ease, box-shadow .18s ease, opacity .18s ease;
}
/* Присідання — плавне, з м'яким початком, як у панелі меню. Було .09s по
   різкій кривій: рух зривався з місця й читався як підмінений кадр.
   Повернення веде базове правило вище — воно з перельотом, тобто пружне. */
#mApp .press { transition-duration: .2s, .18s, .18s, .18s, .18s;
               transition-timing-function: var(--m-ease-in-soft); }

/* Дрібні елементи керування присідають. */
#mApp .press { transform: scale(.93); }

/* ВЕЛИКІ поверхні не масштабуються зовсім.

   Саме масштаб і давав «смикання всередині картки»: у .m-card стоїть
   contain: content, тож на кожен кадр браузер перерастрував увесь її
   вміст — текст під пальцем дрібно тремтів. У нативних списках рядок під
   пальцем теж не їде: він просто підсвічується. Робимо так само. */
/* Картка присідає ЦІЛКОМ. Смикання давав не масштаб як такий, а те, що
   присідало тіло картки (.m-card-b) окремо від рамки — тепер натиск
   завжди піднімається на саму картку (див. bindPress), тож рухається
   один суцільний прямокутник, як у нативних списках. */
/* Картка присідає ЛЕДЬ помітно й м'яко. Різке .97 на всю ширину екрана
   читалось як стрибок; .988 — це вже не стрибок, а рух, який око ловить,
   але не спотикається об нього. */
#mApp .m-card.press { transform: scale(.988); background: #F4EEE6; }
#mApp .m-block.press { transform: scale(.985); }
/* Середні поверхні — капсула статусу, рядок тарифу, плитка суми — тексту
   несуть небагато й contain на них немає, тож ледь помітне присідання їм
   не шкодить і дає відчуття «натиснулось». */
#mApp .m-profit.press, #mApp .m-rate.press, #mApp .m-opt-row.press,
#mApp .m-inv-state.press, #mApp .m-o-status.press, #mApp .m-trackbox.press,
#mApp .m-sum-block.press, #mApp .m-carrier.press {
  transform: scale(.985);
}
/* Кнопка на всю ширину від scale(.93) виглядає так, ніби її зім'яли:
   що ширший елемент, то менший масштаб потрібен для того самого відчуття. */
#mApp .m-btn.press { transform: scale(.975); }
#mApp .m-in.press, #mApp textarea.press { transform: none; background: inherit; }
/* Межі кнопок малюємо кільцем (box-shadow), а не border: скидання нижче
   б'є по всіх кнопках усередині #mApp і за специфічністю перемагає класи. */
#mApp button { -webkit-appearance: none; appearance: none; border: none; font-family: inherit; }
/* Поля вводу шрифт не успадковують — браузер підставляє системний. Наш — усюди. */
#mApp input, #mApp textarea, #mApp select { font-family: var(--font-sans); }
#mApp .num { font-variant-numeric: lining-nums tabular-nums; }
/* Акцентний текст — той самий Jost, що й решта інтерфейсу. */
#mApp .disp { font-family: var(--font-display); }
/* contain — щоб потяг у списку не тягнув за собою сторінку під ним;
   власний відскок айфона при цьому лишається. */
/* Без -webkit-overflow-scrolling: touch.

   Ця властивість застаріла з iOS 13 (плавна прокрутка там і так рідна), а
   от шкода від неї лишилась: контейнер із нею стає окремим прокрутним
   шаром, і коли такий шар ЇДЕ всередині трансформованого екрана, айфон
   перемальовує його на кожному кадрі. Саме це й смикало екран замовлення
   під час свайпу назад. */
.m-scroll {
  overflow-y: auto; scrollbar-width: none; -ms-overflow-style: none;
  overscroll-behavior-y: contain;
}
.m-scroll::-webkit-scrollbar { width: 0; height: 0; display: none; }
.m-sx { overflow-x: auto; scrollbar-width: none; -ms-overflow-style: none; }
.m-sx::-webkit-scrollbar { height: 0; display: none; }

/* ─────────── Шапка ─────────── */
/* ─────────── Верх ───────────
   Суцільної смуги немає: сам шар прозорий і нічого не перехоплює, а на
   ньому висять дві капсули — знак і аватарка. Скло, тінь і радіус ті
   самі, що в дока внизу, тому верх і низ виглядають однією парою. */
.m-top {
  position: fixed; left: 16px; right: 16px; z-index: 20;
  top: calc(12px + env(safe-area-inset-top));
  /* Чотири елементи стоять на однаковій відстані одне від одного, а ряд
     тримається країв екрана: вільне місце роздає space-between, і жодна
     капсула для цього не розтягується. */
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--m-top-gap);          /* мінімум, якщо вільного місця немає */
  background: none; border: none; padding: 0;
  pointer-events: none;                 /* сам шар не ловить дотики */
}
.m-top > * { pointer-events: auto; }

.m-brand {
  /* Тільки знак, без напису: у ряд стали три капсули балансів, і слово
     «babakteam» вже не влазило по ширині екрана. */
  display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto;
  width: var(--m-top-h); height: var(--m-top-h); padding: 0; border-radius: 999px;
  /* Світла підкладка, а не саме лише розмиття: угорі під капсулами часто
     порожній пісочний фон — розмивати там нічого, і плашка зливалась із
     ним. Напівпрозорість лишає скло там, де під низом їдуть картки. */
  background: rgba(255, 253, 251, .78);
  backdrop-filter: blur(8px) saturate(1.4);
  -webkit-backdrop-filter: blur(8px) saturate(1.4);
  box-shadow: 0 6px 26px -14px rgba(58, 44, 32, .25),
              inset 0 0 0 1px rgba(255, 255, 255, .55);
}
.m-brand span {
  font: 600 13.5px 'IBM Plex Sans', sans-serif; letter-spacing: -.01em; color: var(--m-ink);
}
/* ─────────── Баланси у шапці ───────────
   Капсули між знаком і аватаркою, у тій самій манері. Своєї коробки смуга
   не має: display:contents ставить капсули просто в ряд шапки, тож усі
   чотири елементи ділять вільне місце за одним правилом. Доти проміжок
   усередині смуги жив окремо від проміжку між смугою й сусідами — звідси
   й бралися нерівні відстані. */
.m-bals { display: contents; }
.m-bal {
  /* Рівно по вмісту: значок притиснутий до лівого краю, поля однакові з
     обох боків. На плашці заввишки 44px чотирнадцять пікселів поля — те
     саме дихання, що й у кнопок дока; менше виглядало тісно.

     shrink лишаємо ввімкненим: на вузькому екрані краще підтиснути поля
     капсули, ніж випустити ряд за край — там його вже не побачити. */
  flex: 0 1 auto; min-width: 0; height: var(--m-top-h);
  padding: 0 var(--m-bal-pad); border-radius: 999px;
  display: flex; align-items: center; justify-content: flex-start; gap: var(--m-bal-gap);
  background: rgba(255, 253, 251, .78);
  backdrop-filter: blur(8px) saturate(1.4);
  -webkit-backdrop-filter: blur(8px) saturate(1.4);
  box-shadow: 0 6px 26px -14px rgba(58, 44, 32, .25),
              inset 0 0 0 1px rgba(255, 255, 255, .55);
}
.m-bal-i { display: grid; place-items: center; color: var(--m-faint); flex: 0 0 auto; }

/* Дві валюти в одній плашці розділяє волосяна риска, а не проміжок: так
   видно, що це одна кишеня, просто в різних грошах. */
.m-bal-sep {
  flex: 0 0 auto; width: 1px; height: 16px;
  background: rgba(58, 44, 32, .14);
}
.m-bal-i { flex: 0 0 auto; width: 14px; height: 14px; opacity: .5; }
/* WesternBid: значок притиснутий до лівого краю, сума — рівно посередині
   капсули. Праворуч тому лишаємо дзеркальне поле під ширину значка, а сама
   капсула тягнеться рівно по вмісту: мала сума — вузька плашка. Вільне
   місце в ряду забирає сусідня, з доларами й гривнею. */

.m-bal-v {
  font: 500 13.5px var(--font-sans); color: var(--m-ink); white-space: nowrap;
  overflow: hidden; text-overflow: clip;
}
.m-bal.minus .m-bal-v, .m-bal-v.minus { color: #9C4B45; }
.m-icon-btn {
  width: 36px; height: 36px; flex: 0 0 auto; border-radius: 999px;
  background: var(--m-tint); color: var(--m-soft);
  display: grid; place-items: center; cursor: pointer; position: relative;
  transition: transform .14s var(--m-pill), background .16s ease;
}
/* :active не використовуємо — див. блок «Натиск» вище. */
.m-badge {
  position: absolute; top: 7px; right: 8px;
  width: 7px; height: 7px; border-radius: 999px;
  background: #DD8A85; box-shadow: 0 0 0 2px var(--m-tint);
}
/* Аватарка живе у своєму кружечку — рівно такому ж, як кнопка пошуку в
   доку: те саме скло, та сама тінь, той самий розмір. */
.m-ava {
  border: none; padding: 0; cursor: pointer;
  width: var(--m-top-h); height: var(--m-top-h); flex: 0 0 auto; border-radius: 999px;
  background: rgba(255, 253, 251, .78); color: var(--m-ink);
  display: grid; place-items: center; font: 500 12.5px var(--font-sans);
  backdrop-filter: blur(8px) saturate(1.4);
  -webkit-backdrop-filter: blur(8px) saturate(1.4);
  box-shadow: 0 6px 26px -14px rgba(58, 44, 32, .25),
              inset 0 0 0 1px rgba(255, 255, 255, .55);
}

/* ─────────── Черга ─────────── */
/* Перехід у картку — як штовхання екрана в iOS: нижній шар їде вліво
   приблизно на чверть ширини й ПРИТЕМНЮЄТЬСЯ, але не зникає. Раніше він
   гаснув у нуль, і замість глибини виходило просто блимання.

   Зсув у відсотках, а не в пікселях: на широкому екрані 42px — це майже
   непомітно, а рух має читатись однаково скрізь. */
/* Один шар на все, що лежить під екраном замовлення. */
.m-under { position: absolute; inset: 0; z-index: 5; }
/* Смуга статусів і шар розмиття тепер лежать ПОЗА .m-under (їх довелось
   винести, щоб контексти накладання не сперечались), тому їх треба
   перелічити тут окремо — інакше на сторінці замовлення вони лишаються
   висіти поверх неї. */
#mApp.m-deep .m-under,
#mApp.m-deep .m-fab { transform: translate3d(-24%, 0, 0); opacity: .28; pointer-events: none; }
/* Смуга статусів на сторінці замовлення просто прибирається зі сцени.
   Ніякого згасання: сторінка тепер лежить ПОВЕРХ неї, тож показувати рух
   капсул нема кому — а без цього правила вони ще й ловили б дотики. */
#mApp.m-deep .m-filters {
  opacity: 0; pointer-events: none; transition: none;
}
/* Шар розмиття черги на сторінці замовлення просто зникає: там свій. */
#mApp.m-deep > .m-under-fade { opacity: 0; pointer-events: none; }
/* Нижній шар їде рівно тим самим часом і тією самою кривою, що й екран
   зверху: інакше вони розходяться, і рух розсипається на два. */
.m-under, .m-fab, #mApp > .m-under-fade {
  transition: transform var(--m-nav-dur) var(--m-nav-ease),
              opacity var(--m-nav-dur) var(--m-nav-ease);
}
/* Шар готовий до руху ще до того, як палець торкнувся екрана: створювати
   його в першому кадрі жесту — це і є те «спотикання» на початку. */
#mApp.m-deep .m-under { will-change: transform, opacity; }
/* Довгий список — важкий шар. Обмежуємо перемальовку картками: без цього
   зсув черги перераховував усю сторінку на кожен кадр. */
.m-card { contain: content; }

.m-queue {
  position: absolute; inset: 0;
  padding-top: calc(66px + env(safe-area-inset-top));
  /* Хвіст списку. Раніше тут було +64px «на всяк випадок» — і під доком
     лишалась порожня смуга на 138px, яку видно як бежеву плашку, щойно
     догортаєш до кінця. Лишаємо рівно висоту дока плюс висоту стрічки
     фільтрів: остання картка зупиняється під стрічкою, а не в порожнечі. */
  padding-bottom: calc(var(--m-tabh) + 58px);
}
.m-group { padding: 16px 20px 0; }
.m-group-h { display: flex; align-items: baseline; gap: 8px; margin-bottom: 11px; }
.m-group-t { font: 500 15.5px var(--font-display); letter-spacing: -.005em; color: var(--m-ink); white-space: nowrap; }
.m-group-n { font: 400 11.5px var(--font-sans); color: var(--m-faint); }
.m-group-l { flex: 1; height: 1px; background: #E7DFD6; }
.m-group-d { font: 400 11px var(--font-sans); color: var(--m-mute); white-space: nowrap; }
.m-list { display: flex; flex-direction: column; gap: 10px; }

/* ─────────── Картка замовлення ─────────── */
.m-card {
  background: var(--m-card); border-radius: 18px; overflow: hidden;
  box-shadow: var(--m-sh-card);
  transition: transform .2s var(--m-pill);
  transform-origin: center;
}
/* Картка під пальцем не їде — тільки підсвічується (блок «Натиск»). */
/* Картка оновилась (змінився статус, з'явився трек) — проявляється, а не
   підмінюється ривком. */
.m-fresh { animation: m-fade .34s var(--m-ease) both; }
@keyframes m-fade { from { opacity: .35; } to { opacity: 1; } }

/* Змінили статус-фільтр — новий список ПРИЇЖДЖАЄ, а не підміняється
   ривком. Картки з'являються одна за одною, з крихітною затримкою: саме
   ця сходинка й читається як «застосунок», а не «сторінка».

   Анімуємо самі картки, а не контейнер: контейнер — це скролер, і рух
   разом із ним збиває позицію прокрутки. Сходинку робимо лише першим
   восьми: далі її однаково не видно, а кадри вона коштує. */
/* Картка, якої в попередній вибірці не було, проявляється. Тільки вона:
   ті, що вже стояли на екрані, не чіпаються зовсім — саме їхнє «мигання»
   й дратувало. Анімується самий лише opacity, без жодного руху, тож
   смикатись тут нічому. */
.m-card.m-appear { animation: m-appear .22s ease both; }
@keyframes m-appear { from { opacity: 0; } to { opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .m-card.m-appear { animation: none; } }

/* Зміна вибірки нічого не анімує.

   Спершу тут була сходинка з появою карток, потім — коротке проявлення
   всього списку. Обидва варіанти чіпали #mQueue, а це прокрутний
   контейнер: анімувати його прозорість означає підняти в шар усі картки
   рівно в той кадр, коли список і так перебудовується. Через це щойно
   з'явлене замовлення смикалось у мить появи.

   Тепер перемикання миттєве. Картки, які були в попередній вибірці,
   переносяться готовими вузлами (див. buildQueue) і взагалі не
   перемальовуються — на екрані просто змінюється склад списку.
   Підтвердження натиску дає сама капсула. */
.m-card-b { display: flex; gap: 13px; padding: 13px 15px 12px; }
/* Макет вписуємо цілком (contain) і без підкладки: на темному тлі PNG з
   прозорістю виглядав як пляма, а cover різав малюнок по краях. */
.m-thumb {
  width: 62px; height: 62px; flex: 0 0 auto; border-radius: 13px;
  background-color: transparent; background-size: contain;
  background-position: center; background-repeat: no-repeat;
}
.m-thumb.empty { display: grid; place-items: center; color: var(--m-mute); }
.m-card-t { flex: 1; min-width: 0; }
.m-meta-row { display: flex; align-items: baseline; gap: 10px; }
.m-meta {
  flex: 1; min-width: 0; font: 400 10px var(--font-sans); letter-spacing: .1em;
  text-transform: uppercase; color: var(--m-faint);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Сума лишається темною — сірою вона читалась як другорядна, хоча це
   головне число картки. Притишуємо її розміром і вагою, а не кольором. */
.m-sum { font: 400 15px var(--font-display); color: var(--m-ink); white-space: nowrap; }
.m-name {
  font: 500 17px/1.2 var(--font-display); letter-spacing: -.01em; color: var(--m-ink); margin-top: 4px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.m-variant {
  display: flex; align-items: center; gap: 7px; flex-wrap: wrap; margin-top: 6px;
  font: 400 12.5px var(--font-sans); color: var(--m-soft);
}
.m-size {
  height: 19px; padding: 0 7px; border-radius: 999px; background: var(--m-tint-2);
  font: 400 10.5px/19px var(--font-sans); color: var(--m-soft);
}
/* Колір — кружком: так само, як у веб-версії. */
.m-sq {
  width: 10px; height: 10px; border-radius: 999px; flex: 0 0 auto;
  box-shadow: inset 0 0 0 1px rgba(43, 35, 29, .16);
}
.m-opts { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 7px; }
.m-opt {
  height: 20px; padding: 0 9px 0 7px; border-radius: 999px; background: var(--m-tint-4);
  display: inline-flex; align-items: center; gap: 4px;
  font: 400 10.5px var(--font-sans); color: #8C7C6D; white-space: nowrap;
}

.m-card-f {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 13px 11px 15px; border-top: 1px solid var(--m-line);
}
.m-st {
  height: 30px; padding: 0 12px; border-radius: 999px;
  display: inline-flex; align-items: center; gap: 7px;
  font: 400 12.5px var(--font-sans); white-space: nowrap; cursor: pointer;
  transition: transform .14s var(--m-pill);
}

.m-st-dot { width: 6px; height: 6px; border-radius: 999px; }
/* Комірка фіксованої висоти: поява накладної не міняє висоту картки. */
.m-inv-cell {
  flex: 1; min-width: 0; height: 30px; display: flex;
  align-items: center; justify-content: flex-end;
}
.m-inv-none { font: 400 11px var(--font-sans); color: var(--m-mute); }
/* Номер накладної в картці — без плашки. Поряд і так кольоровий статус,
   друга заливка перевантажує рядок. Лишаємо тихий рядок тексту й м'яко
   зелену іконку — цього досить, щоб побачити, що накладна є. */
.m-track {
  max-width: 152px; height: 30px; padding: 0;
  background: none; color: var(--m-faint);
  display: inline-flex; align-items: center; gap: 6px;
  font: 400 11.5px var(--font-sans); white-space: nowrap;
  overflow: hidden;
  /* Анімації появи тут НЕМАЄ.

     Вона стояла безумовно — і програвалась щоразу, коли вузол створювався
     заново. А під час гортання список дозбирується, тож номери накладних
     блимали на кожній прокрутці. Поява має сенс лише тоді, коли накладну
     справді щойно оформили: цим завідує клас .m-pop нижче. */
}
/* Номер довший за місце — обрізаємо крапками. min-width: 0 обов'язковий:
   без нього flex-елемент не стискається менше за свій вміст. */
.m-track span {
  min-width: 0; overflow: hidden; text-overflow: ellipsis;
  color: var(--m-faint); letter-spacing: .01em;
}
@keyframes m-appear {
  from { opacity: 0; transform: translateY(5px) scale(.97); }
  to   { opacity: 1; transform: none; }
}
.m-chev { flex: 0 0 auto; display: inline-flex; color: #D3C7B9; }

/* Полоса пропозиції накладної */
.m-suggest {
  display: flex; align-items: center; gap: 12px;
  padding: 11px 13px 12px 15px; background: #FBF2DE;
}
.m-sg-txt { flex: 1; min-width: 0; text-align: left; background: none; cursor: pointer; padding: 0; }
.m-sg-k {
  display: flex; align-items: center; gap: 6px;
  font: 400 9px var(--font-sans); letter-spacing: .14em; text-transform: uppercase; color: #A9822F;
}
.m-sg-k i { width: 3px; height: 3px; border-radius: 999px; background: #D5B57C; }
.m-sg-b { display: flex; align-items: baseline; gap: 8px; margin-top: 3px; flex-wrap: wrap; }
.m-sg-price { font: 500 16px var(--font-display); letter-spacing: -.01em; color: var(--m-ink); }
.m-sg-days { font: 400 11.5px var(--font-sans); color: #A9822F; }
.m-sg-more {
  display: inline-flex; align-items: center; gap: 3px;
  font: 400 11.5px var(--font-sans); color: #C09A55;
}
.m-sg-ok {
  width: 42px; height: 42px; flex: 0 0 auto; border-radius: 999px;
  background: #FFFDFA; color: #6E4F16; display: grid; place-items: center;
  cursor: pointer; transition: transform .14s var(--m-pill);
}

.m-spin { animation: m-spin .85s linear infinite; }
@keyframes m-spin { to { transform: rotate(360deg); } }

/* ─────────── Фільтр статусів ─────────── */
/* Чипи стоять НАД панеллю меню з проміжком: висота панелі рахується тим
   самим виразом, що й у неї самої (--m-tabh), плюс 8px повітря — інакше
   вони впритул торкались панелі й здавались нею накритими. */
.m-filters {
  position: absolute; left: 0; right: 0; z-index: 30;
  /* Стрічка стоїть НАД доком і має рівно свою висоту.

     У хендофі смуга навмисно на 284px довша й опущена нижче екрана — щоб
     при підйомі над клавіатурою низ лишався закритим склом. На живому
     списку це давало суцільну бежеву заливку на 160px від низу: під нею
     ховались картки, і низ екрана виглядав мертвим. У телеграма інакше —
     список іде під панель і просвічує. Тому скло тримаємо тільки під
     самою стрічкою, а нижче лишаємо прозоро. */
  /* 12px, а не 3: тінь дока йде вгору приблизно на стільки ж, і нижній
     ряд чіпів опинявся під нею — виглядало як «кнопка не натискається». */
  bottom: calc(var(--m-tabh) + 12px);
  padding: 14px 20px 12px;
  display: flex; align-items: flex-start; gap: 8px;
  overflow-x: auto;
  /* Горизонтальний жест віддаємо стрічці одразу. Без цього браузер спершу
     вирішує, скрол це чи натиск, — звідси і «то не скролиться, то не
     натискається». */
  touch-action: pan-x;
  /* Жодної підкладки: ні заливки, ні скла. Капсули лежать прямо на
     полотні, а найдорожче місце прокрутки — розмиття — зникає. */
  background: none;
  will-change: transform;
  transition: transform .4s var(--m-ease-soft),
              opacity var(--m-nav-dur) var(--m-nav-ease);
  overscroll-behavior-x: contain;
  scroll-padding: 0 20px;
}
/* Підйом — після того, як капсула пошуку розкрилась (затримка .34s):
   відкриття читається як два кроки, закриття йде одним рухом вниз. */
/* Поки відкритий пошук, статуси не потрібні: вони лише сперечаються з
   полем за місце. Ховаємо їх, а не піднімаємо. */
.m-filters.hidden {
  opacity: 0; pointer-events: none;
  transform: translateY(10px);
  transition: opacity .2s ease, transform .28s var(--m-ease-soft);
}
.m-filters.lifted {
  /* Так само по реальній висоті й теж без затримки: статуси мають стояти
     над полем пошуку, а не залишатись під клавіатурою. */
  transform: translateY(calc(-1 * var(--m-kb, 0px)));
  /* Не linear: приїзд і від'їзд мають гальмувати м'яко. */
  transition: transform .3s var(--m-ease-soft);
  /* Вище шару закриття (32) — інакше статуси лишаються ПІД ним: їх не
     видно й не натиснути, поки відкритий пошук. */
  z-index: 34;
}

/* ─────────── Підкладка низу ───────────

   Айфон у застосунку з іконки дає вікно 852 при екрані 896: смуга під
   вікном нам не належить — намалювати там нічого не можна, вона просто
   зафарбована фоном сторінки. Розмити її теж не вийде: backdrop-filter
   бачить лише те, що всередині вікна.

   Тому маскуємо: кладемо шар РІВНО того самого кольору й розчиняємо його
   вгору десь на рівні капсул статусів. Тоді список не обривається різкою
   межею, а перехід у смугу під вікном непомітний — вона читається як
   продовження фону, а не як обрізана панель. */
.m-under-fade {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 25;
  /* Догори — по верхній край смуги статусів, щоб під капсулами теж було
     розмиття. Кайму навколо них давала не висота, а різкий початок маски,
     тому вгорі вона тепер наростає повільно й межі не видно. */
  /* Тягнемо помітно вище смуги статусів: розмиття має відчуватись, а не
     ледь угадуватись біля самого дока. */
  height: calc(var(--m-tabh) + 190px);
  pointer-events: none;
  /* Не заливка кольором, а МАСКА РОЗМИТТЯ: картки під доком не зникають
     під бежевим, а поступово розмиваються. Прозорість маски = сила
     розмиття, тож угорі список різкий, а до низу м'яко тане. */
  background: none;
  backdrop-filter: blur(18px) saturate(1.08);
  -webkit-backdrop-filter: blur(18px) saturate(1.08);
  -webkit-mask-image: linear-gradient(180deg,
    transparent 0%, rgba(0, 0, 0, .10) 18%, rgba(0, 0, 0, .34) 38%,
    rgba(0, 0, 0, .62) 56%, rgba(0, 0, 0, .86) 74%, #000 90%, #000 100%);
  mask-image: linear-gradient(180deg,
    transparent 0%, rgba(0, 0, 0, .10) 18%, rgba(0, 0, 0, .34) 38%,
    rgba(0, 0, 0, .62) 56%, rgba(0, 0, 0, .86) 74%, #000 90%, #000 100%);
}

/* На сторінці замовлення смуга потрібна лише під самим доком: там немає
   списку, який має м'яко танути, а висока смуга просто з'їдає вміст. */
.m-order .m-under-fade { height: calc(var(--m-tabh) + 40px); }

/* Після зміни статусу список не «вистрибує», а проявляється.

   Гасимо саме #mQueue, а не .m-list: списки всередині груп при перебудові
   створюються заново, тож клас гасіння відлітав разом зі старим вузлом —
   новий приходив уже видимим, і поява виглядала різкою. */
#mQueue, #mMats, #mExp, #mFin, #mStat { transition: opacity .34s var(--m-ease-soft); }
/* Згасання скелета — .22s, поява замовлень — довша й м'якша. */
#mQueue.swap, #mMats.swap, #mExp.swap, #mFin.swap, #mStat.swap { opacity: 0; transition: opacity .22s ease; }

.m-chip {
  /* 40px замість 34: у 34 доводилось цілитись, палець часто промахувався. */
  transform-origin: center;
  height: 40px; padding: 0 16px; border-radius: 999px; flex: 0 0 auto;
  background: #FFFFFF; color: var(--m-soft); box-shadow: inset 0 0 0 1px #EDE3D6;
  display: inline-flex; align-items: center; gap: 8px;
  font: 400 13px var(--font-sans); white-space: nowrap; cursor: pointer;
  /* Перехід довший і по одній кривій — різка зміна кольору читалась як
     ривок. Тепер стан «перетікає». */
  transition: background .26s var(--m-ease-soft), color .26s var(--m-ease-soft),
              box-shadow .26s var(--m-ease-soft),
              /* Повернення масштабу пружиною — трохи перелітає одиницю й
                 м'яко всідається. Це і є «легкий баунс». */
              transform .44s var(--m-ease-spring);
}
/* Відскок капсули — той самий, що в меню на десктопі: не одна пружина
   туди-назад, а кілька коливань, які згасають. Пружину несуть САМІ кадри,
   тому крива між ними майже рівна — інакше вона додає власне прискорення
   й рух знову стає різким.

   Раніше це був перехід зі spring-кривою: коротко, з одним перельотом і
   різкою зупинкою — на око «сіпнулось», а не «спружинило». */
@keyframes m-chip-bump {
  0%   { transform: scale(1); }
  14%  { transform: scale(1.07); }
  36%  { transform: scale(.972); }
  58%  { transform: scale(1.022); }
  80%  { transform: scale(.994); }
  100% { transform: scale(1); }
}
.m-chip.bump {
  animation: m-chip-bump .62s cubic-bezier(.42, .5, .45, 1) both;
}
/* Капсула НЕ присідає під пальцем.

   Відскок після натиску грав правильно, але поверх нього лежало загальне
   правило натиску (scale .93 з ваги #mApp): рух починався не з одиниці, а
   зі стиснутої капсули — і замість пружного затухання виходив стрибок.
   У меню на вебі присідання немає взагалі, тож і тут його немає: відгук
   на натиск дає сам відскок. */
#mApp .m-chip.press { transform: none; }
@media (prefers-reduced-motion: reduce) {
  .m-chip.bump { animation: none; }
}

.m-chip i { width: 6px; height: 6px; border-radius: 999px; }
/* Перемикач режиму періоду в смузі магазинів: іконка й підпис, від капсул
   магазинів відділений тонкою рискою. */
.m-chip-sep { flex: 0 0 1px; width: 1px; height: 22px; background: #E4D9CB; margin: 0 2px; align-self: center; }
.m-chip-mode svg { width: 14px; height: 14px; margin-right: -2px; }
.m-stat-mode { display: inline-flex; align-items: center; height: 20px; padding: 0 9px; border-radius: 999px; background: rgba(255, 255, 255, .7); font: 500 10px var(--font-sans); letter-spacing: .02em; text-transform: none; color: var(--m-soft); }
.m-chip b { font-weight: 400; color: var(--m-mute); }
.m-chip.on { background: var(--m-ink); color: #F7F1EA; box-shadow: none; font-weight: 500; }
.m-chip.on b { color: rgba(247, 241, 234, .5); }

/* ─────────── FAB і док ─────────── */
.m-fab {
  position: absolute; right: 20px; bottom: calc(var(--m-tabh) + 76px); z-index: 16;
  width: 54px; height: 54px; border-radius: 999px;
  background: var(--m-ink); color: #F7F1EA; display: grid; place-items: center;
  box-shadow: 0 14px 30px -12px rgba(43, 35, 29, .85); cursor: pointer;
  transition: transform .14s var(--m-pill);
}

/* ═══════════ ДОК (design_handoff_tabbar) ═══════════
   Дві незалежні капсули: меню 232x64 і пошук 64x64, між ними 10px.
   Разом в одній капсулі бути не можуть — пошук ламає розкладку іконок.

   П'ять правил, на яких тримається гладкість (усі здобуті на реальному
   лагу цього дока):
     1. анімуємо лише transform і opacity — layout не анімуємо ніколи;
     2. капсулі, що міняє ширину зі склом, даємо translateZ(0) і
        will-change, щоб шар підняли на GPU ДО старту руху;
     3. скло лишається на самій капсулі: винесене в окремий шар воно
        ігнорує overflow і вилазить прямокутником з-під круглої форми;
     4. жодних mix-blend-mode на рухомому;
     5. службовий шар (veil) — без transition. */

/* Шар закриття пошуку: вище смуги, нижче дока. Саме БЕЗ transition —
   інакше входить у спільний такт анімації й закриття виглядає рваним. */
.searchveil {
  position: fixed; inset: 0; z-index: 32; opacity: 0; pointer-events: none;
  /* Затемнення вмикається окремим класом, щоб його можна було зняти
     плавно, не прибираючи сам шар: шар ще потрібен, щоб ловити дотик
     повз поле. */
  background: transparent;
  transition: opacity .34s var(--m-ease-soft),
              background .34s var(--m-ease-soft);
}
.searchveil.dim { background: rgba(43, 35, 29, .22); }
/* Дотиків шар НЕ ловить: інакше він накриває список і з'їдає натиск по
   знайденій картці. Закриття пошуку по тапу повз док робить обробник. */
.searchveil.searching { opacity: 1; }

.tabdock {
  /* Док не по центру фіксованої ширини, а розтягнутий між тими самими
     полями, що й капсули статусів (20px). Тоді його лівий край завжди
     збігається з початком чипів — на будь-якій ширині телефона. */
  /* fixed, а не absolute. absolute рахувався від оболонки, а вона
     розтягнута по РОЗКЛАДКОВОМУ вікну (852 при екрані 896) — тому док і
     впирався в його межу. fixed рахується від видимого вікна: так само
     зроблено в робочому прикладі (.bottom-nav { position: fixed; bottom: 0 }). */
  position: fixed; left: var(--m-dock-side); right: var(--m-dock-side); bottom: var(--m-dock-b);
  z-index: 33; display: flex; align-items: center; gap: 10px;
  transition: transform .4s var(--m-ease-soft), opacity .28s ease;
}
/* Док прибирається зовсім — коли фото відкрите на весь екран. */
.tabdock.away {
  transform: translateY(calc(100% + var(--m-dock-b) + 12px));
  opacity: 0; pointer-events: none;
  transition: transform .34s var(--m-ease-soft), opacity .22s ease;
}

.tabdock.searching {
  /* Підіймаємось рівно на ту висоту, яку клавіатура зайняла НАСПРАВДІ
     (--m-kb міряє скрипт), а не на записані наперед 284px: у них поле
     опинялось під клавіатурою. Затримки немає і крива лінійна — капсула
     їде синхронно з клавіатурою, тож та не встигає її накрити. */
  /* +14px запасу: поле має стояти НАД клавіатурою з просвітом, а не
     впритул до неї. */
  transform: translateY(calc(-1 * var(--m-kb, 0px)));
  /* Не linear: приїзд і від'їзд мають гальмувати м'яко. */
  transition: transform .3s var(--m-ease-soft);
  /* Меню схлопнулось до нуля, а проміжок між капсулами лишався — і док,
     центрований цілком, з'їжджав праворуч на пів проміжку: поля виходили
     25 і 15 замість однакових. */
  gap: 0;
}

/* ── капсула меню ── */
.tabcap {
  /* Ширина ЯВНА: уся ширина дока мінус капсула пошуку (70) і проміжок
     (10). flex тут не годиться — на айфоні капсула зі склом і contain:
     paint схлопувалась вліво. Анімація ширини при пошуку теж вимагає
     справжнього значення, а не flex-розтягування. */
  position: relative; flex: 0 0 auto; width: 100%;
  height: var(--m-dock-h);
  padding: var(--m-dock-pad); border-radius: 999px;
  background: rgba(255, 253, 251, .78);   /* світла підкладка, як у капсул шапки */
  backdrop-filter: blur(8px) saturate(1.4);
  -webkit-backdrop-filter: blur(8px) saturate(1.4);
  /* Тінь тільки ВГОРУ. Док стоїть за 4px від краю вікна, і будь-яка
     нижня тінь зрізається його межею — виходив помітний стик. */
  /* Тінь іде ВНИЗ і ледь помітна (25%). Угору її розвертали, поки док
     стояв за 4px від краю і нижню тінь зрізало вікном; тепер під ним 20px
     і місця вистачає. */
  box-shadow: 0 6px 26px -14px rgba(58, 44, 32, .25),
              inset 0 0 0 1px rgba(255, 255, 255, .55);
  display: flex; align-items: center; gap: 6px;
  flex: 0 0 auto; overflow: hidden; touch-action: none;
  will-change: width, opacity; contain: paint;
  transform-origin: center;
  transition: backdrop-filter .34s ease, -webkit-backdrop-filter .34s ease,
              width .44s var(--m-ease-soft),
              padding .44s var(--m-ease-soft),
              opacity .28s ease,
              /* Повернення з відскоку — пружиною: масштаб трохи перелітає
                 одиницю й м'яко всідається. Це і є «баунс». */
              transform .52s var(--m-ease-spring);
}
/* Ліва пара дока: «назад» + меню. Ширина СТАЛА (усе, крім правої капсули),
   тож хай як капсули всередині діляться місцем, права стоїть на місці. */
.leftgrp {
  display: flex; align-items: center; gap: 10px; flex: 0 0 auto;
  width: calc(100% - var(--m-dock-h) - 10px); height: var(--m-dock-h);
  transition: width .44s var(--m-ease-soft), opacity .28s ease;
}
.tabdock.searching .leftgrp { width: 0; opacity: 0; pointer-events: none; }
.tabdock.searching .tabcap { width: 0; padding: 0; opacity: 0; pointer-events: none; }

/* ── Плавність переходів дока ──────────────────────────────────────────
   Поки капсули змінюють ширину, скло (backdrop-filter) перемальовується
   щокадру — розмиття по 28px на двох шарах айфон не витягує, і рух іде
   ривками. На час переходу міняємо скло на суцільний колір: він майже
   збігається з тим, що дає розмиття поверх полотна (#F6F3F0), тож підміни
   не видно, а кадри стають рівними. Клас вішає та знімає скрипт. */
/* Скло НЕ гасимо взагалі. Будь-яке його вимикання на час руху видно як
   «увімкнення розмиття» наприкінці — хоч через none, хоч через blur(0).
   Тому лишаємо розмиття сталим, а плавність руху беремо з меншого
   радіуса (нижче) — його вистачає, і перемальовується він утричі дешевше. */

/* ── М'який відскок панелі при зміні вкладки ───────────────────────────
   Як у телеграма: капсула ледь «дихає» — на 2%, і одразу назад.
   Тільки transform, тому не коштує нічого. */
/* Саме ПЕРЕХІД, а не @keyframes. Кадрова анімація при повторному натиску
   стартує з нуля — звідси різкий смик, якщо тицьнути швидко. Перехід же
   переінтерполюється від поточного масштабу, тож хоч як часто тицяй, рух
   лишається неперервним. */
/* Уперед — плавно, з м'яким початком; назад — пружиною (крива в .tabcap). */
/* Список переходів тут ПОВНИЙ: коротший перекривав базовий і на час підскоку
   вимикав перехід ширини — капсула стрибала, поки решта ще їхала. */
.tabcap.bump { transform: scale(1.05);
               transition: transform .24s var(--m-ease-in-soft),
                           width .44s var(--m-ease-soft), padding .44s var(--m-ease-soft),
                           opacity .28s ease,
                           backdrop-filter .34s ease, -webkit-backdrop-filter .34s ease; }
@media (prefers-reduced-motion: reduce) {
  .tabcap.bump { transform: none; }
}
/* Кнопки розходяться рівно по капсулі: крок пілюлі скрипт бере з їхніх
   реальних позицій, тож він підлаштовується сам. */
/* Група кнопок меню має СТАЛУ ширину (нутро капсули в звичайному стані) і
   притиснута до правого краю: коли капсула звужується під статистику,
   кнопки не переїжджають — капсула просто виростає чи ховається зліва. */
.tabgrp {
  position: absolute; top: var(--m-dock-pad); bottom: var(--m-dock-pad); right: var(--m-dock-pad);
  width: calc(100vw - 2 * var(--m-dock-side) - var(--m-dock-h) - 10px - 2 * var(--m-dock-pad));
  display: flex; align-items: center; justify-content: space-between;
}

/* Пілюля — дві ноди навмисно: зовнішня рухається, внутрішня міняє ширину.
   Однією нодою transform і width б'ються, і форма деформується. */
.tabpill {
  position: absolute; top: var(--m-dock-pad); right: var(--m-dock-pad);
  width: var(--m-dock-btn); height: var(--m-dock-btn);
  display: grid; place-items: center;
  transition: transform .46s var(--m-ease-soft), opacity .24s ease;
}
.tabpill i {
  display: block; width: var(--m-dock-btn); height: var(--m-dock-btn);
  border-radius: 999px; background: #2B231D;
  /* Розтяг масштабом, а НЕ шириною. Ширина щокадру перераховує розкладку —
     саме через це переїзд кола смикався. transform лежить на композиторі. */
  transform-origin: center;
  will-change: transform;
  transition: transform .42s cubic-bezier(.34, 1.12, .42, 1);
}
/* На переїзді коло і розтягується вздовж руху, і трохи більшає загалом —
   так рух читається живим, а не просто зсувом. */
.tabpill.moving i { transform: scale(1.07) scaleX(1.1); }
.tabpill.drag { transition: none; }           /* під пальцем — без згладжування */
.tabpill.drag i { transform: scale(1.05) scaleX(1.04); transition: transform .18s ease; }
.tabdock.searching .tabpill { opacity: 0; }

.tabbtn {
  position: relative; z-index: 1; flex: 0 0 var(--m-dock-btn); height: var(--m-dock-btn);
  border: none; background: none; padding: 0; cursor: pointer;
  display: grid; place-items: center; color: #8C7C6D;
}
.tabbtn svg { display: block; transition: transform .46s var(--m-ease-soft), color .22s ease; }
.tabbtn.on { color: #FFFDFA; }
.tabbtn.on svg { transform: scale(1.06); }
/* Червоний кружок із числом: закупка на складі, незакриті заявки у
   витратах. Стоїть НАД пілюлею і не ловить натиски. */
.tabbadge {
  position: absolute; top: 3px; right: 1px; z-index: 2; pointer-events: none;
  min-width: 16px; height: 16px; padding: 0 4px; box-sizing: border-box;
  border-radius: 999px; background: #C6564E; color: #FFF6F0;
  font: 600 9.5px/16px var(--font-sans); text-align: center; letter-spacing: 0;
}
/* Відгук з'являється миттєво, ще до того, як пілюля доїхала. */
.tabbtn::before {
  content: ''; position: absolute; inset: 0; border-radius: 999px;
  background: rgba(43, 35, 29, .07); opacity: 0; transform: scale(.7);
  pointer-events: none;
  transition: opacity .2s ease, transform .32s var(--m-ease-soft);
}
.tabbtn:active::before { opacity: 1; transform: scale(1); }
.tabbtn:active svg { transform: scale(.84) !important; }

/* ── капсула пошуку ── */
/* Ближню тінь 0 1px 2px тут НЕ ставимо: на круглій формі вона читається
   як твердий обідок. */
.searchcap {
  position: relative; flex: 0 0 var(--m-dock-h); width: var(--m-dock-h);
  height: var(--m-dock-h); padding: var(--m-dock-pad); border-radius: 999px;
  background: rgba(255, 253, 251, .78);   /* світла підкладка, як у капсул шапки */
  backdrop-filter: blur(8px) saturate(1.4);
  -webkit-backdrop-filter: blur(8px) saturate(1.4);
  /* Тінь іде ВНИЗ і ледь помітна (25%). Угору її розвертали, поки док
     стояв за 4px від краю і нижню тінь зрізало вікном; тепер під ним 20px
     і місця вистачає. */
  box-shadow: 0 6px 26px -14px rgba(58, 44, 32, .25),
              inset 0 0 0 1px rgba(255, 255, 255, .55);
  display: flex; align-items: center; gap: 0; flex: 0 0 auto; overflow: hidden;
  transform: translateZ(0); will-change: width;
  transition: backdrop-filter .34s ease, -webkit-backdrop-filter .34s ease,
              transform .24s var(--m-ease-in-soft),
              width .5s cubic-bezier(.34, 1.16, .46, 1),
              gap .44s var(--m-ease-soft),
              padding .44s var(--m-ease-soft);
}
/* 352px — з макета, але на вузькому телефоні капсула впиралась би в краї.
   Тому це стеля: реальна ширина ніколи не більша за екран мінус поля по
   20px з кожного боку. Док центрований, тож поля виходять однакові. */
.searchcap.bump { transform: translateZ(0) scale(1.05); }
@media (prefers-reduced-motion: reduce) { .searchcap.bump { transform: translateZ(0); } }
.tabdock.searching .searchcap {
  width: 100%;
  gap: 10px; padding: var(--m-dock-pad) 14px;
}
/* Кругла капсула «назад» зліва: те саме скло, що й у пошуку. Поза
   статистикою згорнута в нуль і з від'ємним полем — щоб не лишати
   проміжку в доку. */
.backcap {
  position: relative; flex: 0 0 auto; width: 0; height: 50px; padding: 0; box-sizing: border-box;
  margin-right: -10px; opacity: 0; pointer-events: none; overflow: hidden;
  border-radius: 999px; background: rgba(255, 253, 251, .78);
  backdrop-filter: blur(8px) saturate(1.4); -webkit-backdrop-filter: blur(8px) saturate(1.4);
  box-shadow: 0 6px 26px -14px rgba(58, 44, 32, .25), inset 0 0 0 1px rgba(255, 255, 255, .55);
  display: grid; place-items: center; transform: translateZ(0);
  transition: width .44s var(--m-ease-soft), margin .44s var(--m-ease-soft), padding .44s var(--m-ease-soft),
              opacity .26s ease, transform .24s var(--m-ease-in-soft);
}
#mApp.m-stat ~ #mTabs .backcap { width: 50px; padding: 7px; margin-right: 0; opacity: 1; pointer-events: auto; }
#mApp.m-stat ~ #mTabs .tabcap { width: calc(100% - 60px); }
/* Натиск: кружок виростає й світлішає — і тільки потім іде перехід. */
.backcap.pop { transform: translateZ(0) scale(1.1); background: rgba(255, 255, 255, .62); }
.backcap { transition: width .44s var(--m-ease-soft), margin .44s var(--m-ease-soft), padding .44s var(--m-ease-soft),
              opacity .26s ease, transform .22s var(--m-ease-in-soft), background .2s ease; }
.backbtn {
  width: 36px; height: 36px; border: none; border-radius: 999px; padding: 0;
  background: transparent; color: #6B5C50; display: grid; place-items: center; cursor: pointer;
  transition: transform .16s var(--m-ease-soft);
}
.backbtn:active { transform: scale(.92); }
.searchbtn, .searchin, .searchx { position: relative; z-index: 1; }

.searchbtn {
  flex: 0 0 var(--m-dock-btn); width: var(--m-dock-btn); height: var(--m-dock-btn);
  border: none; border-radius: 999px;
  background: transparent; color: #6B5C50; padding: 0; cursor: pointer;
  display: grid; place-items: center;
  transition: transform .16s var(--m-ease-soft),
              width .42s var(--m-ease-soft),
              flex-basis .42s var(--m-ease-soft);
}
.tabdock.searching .searchbtn { flex: 0 0 22px; width: 22px; }

/* ── Перетікання іконки: лупа ⇄ коментарі ──────────────────────────────
   Обидві іконки лежать одна на одній і міняються масштабом та поворотом.
   Підміняти вузол не можна — тоді це просто стрибок, а не перехід. */
.searchbtn { position: relative; }
.searchbtn .ic {
  position: absolute; inset: 0; display: grid; place-items: center;
  transition: opacity .24s ease, transform .44s var(--m-ease-spring);
}
.searchbtn .ic-chat, .searchbtn .ic-shop { opacity: 0; transform: scale(.5) rotate(-45deg); }
.tabdock.deep .searchbtn .ic-find { opacity: 0; transform: scale(.5) rotate(45deg); }
.tabdock.deep .searchbtn .ic-chat { opacity: 1; transform: none; }
/* Розділ складу: замість лупи — намет крамниці. Кнопка робить те саме
   (шукає), просто в складі шукають по складу. */
/* На складі кнопка лишається пошуком: заявка тепер живе власною смугою
   над доком, і ділити з нею одну кнопку більше не треба. */
/* Зайшли зі складу в замовлення — коментарі важливіші, намет ховається. */
#mApp.m-mats ~ #mTabs.deep .searchbtn .ic-shop { opacity: 0; transform: scale(.5) rotate(-45deg); }
/* Лічильник коментарів — маленька мітка на іконці. Порожній текст ховає
   її повністю, тож окремого класу не треба. */
.searchbtn .ic-n {
  position: absolute; top: -2px; right: -1px;
  min-width: 15px; height: 15px; padding: 0 4px; border-radius: 999px;
  background: var(--m-ink); color: #F7F1EA;
  font: 500 9.5px/15px var(--font-sans); text-align: center;
}
.searchbtn .ic-n:empty { display: none; }
.searchbtn:active { transform: scale(.92); }

/* Поле без placeholder: порожнє й одразу активне. Фокус ставимо через
   420 мс — коли капсула вже розкрилась, інакше клавіатура зриває рух. */
.searchin {
  flex: 1; min-width: 0; width: 0; height: 44px; border: none; outline: none;
  background: transparent; padding: 0;
  font: 400 16px var(--font-sans); color: #2B231D; caret-color: #6E5343;
  white-space: nowrap; opacity: 0; pointer-events: none;
  transition: opacity .18s ease;                       /* закриття — швидко */
}
.tabdock.searching .searchin {
  opacity: 1; pointer-events: auto;
  transition: opacity .24s ease .14s;                  /* поява — із затримкою */
}

/* Хрестик з'являється підскоком і так само зникає — масштабом, а не
   схлопуванням ширини; місця не займає через від'ємний margin. */
.searchx {
  flex: 0 0 40px; width: 40px; height: 40px; margin-right: -40px;
  border: none; border-radius: 999px; background: #E7DCC9; color: #6B5C50;
  display: grid; place-items: center; cursor: pointer;
  opacity: 0; transform: scale(.5); pointer-events: none;
  transition: opacity .22s ease,
              transform .42s var(--m-ease-spring),
              margin-right .42s var(--m-ease-soft),
              background .16s ease;
}
.tabdock.searching .searchx {
  margin-right: 0; opacity: 1; transform: scale(1); pointer-events: auto;
  transition: opacity .2s ease .14s,
              transform .42s var(--m-ease-spring) .12s,
              margin-right .42s var(--m-ease-soft),
              background .16s ease;
}
.searchx:active { transform: scale(.9); }

/* Капсула статусу, яку щойно обрали, під'їжджає у видиму частину сама —
   інакше вибраний фільтр лишається за краєм і здається, ніби нічого не
   натиснулось. Прокрутку веде скрипт, тут лише крива. */
.m-filters { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
  .m-filters { scroll-behavior: auto; }
  .m-tab.pop svg { animation: none; }
}

/* ─────────── Екран замовлення ───────────
   Значення з design_handoff_order_screen. Скролер повноекранний
   (inset: 0), фото й навігація — окремими шарами поверх нього. Так у
   скролера немає власної лінії обрізання посеред екрана, і блоки, що
   піднімаються, не ріжуться навпіл. */
/* Спільна поведінка екранів, що заїжджають збоку (замовлення, накладна). */
.m-screen {
  /* Вище смуги статусів (30): сторінка замовлення має НАКРИВАТИ її, а не
     стояти під нею. Поки було 25, смуга лишалась зверху — і при переході
     було видно, як капсули гаснуть по прозорості. Док (33) усе одно вище. */
  position: absolute; inset: 0; z-index: 31; background: var(--m-bg);
  overflow: hidden;
  transform: translate3d(100%, 0, 0);
  transition: transform var(--m-nav-dur) var(--m-nav-ease);
  will-change: transform; contain: paint;
}
.m-screen.on { transform: translate3d(0, 0, 0); }
/* Перший кадр — без анімацій узагалі.

   Поки застосунок тільки будується, жоден шар не має нікуди їхати. Інакше
   при запуску видно, як щось «іде вправо»: браузер встигає порівняти
   початковий стан елемента з тим, який задає клас, і програє перехід. */
#mApp:not(.m-ready) * { transition: none !important; animation: none !important; }
/* Поки екран тягнуть пальцем, він має йти РІВНО за пальцем: жодних
   переходів, інакше кожен кадр доганяє попередній і рух «пливе».
   Переходи вмикаються назад у мить, коли палець відпустили, — і той самий
   перехід доводить екран до кінця або повертає на місце. */
#mApp.m-drag .m-screen,
#mApp.m-drag .m-under { transition: none !important; }

/* Системний жест «назад» уже показав свій перехід — свій ми не додаємо,
   інакше екран закривається двічі. */
#mApp.m-nofx .m-screen,
#mApp.m-nofx .m-under { transition: none !important; animation: none !important; }
/* Тінь на лівому краї екрана — поки він відкритий.

   Вмикати її на початку жесту не можна: поява розмиття 34px змушує
   браузер перемалювати повноекранний шар рівно в перший кадр руху, і
   екран смикається. Але й вішати назавжди теж не можна: закритий екран
   стоїть за правим краєм, а його тінь тягнеться на 34px ЛІВОРУЧ — тобто
   видніє смугою біля правого краю застосунку.

   Тому тінь живе рівно стільки, скільки відкритий екран: вона з'являється
   разом із ним, задовго до будь-якого жесту. */
.m-screen.on { box-shadow: -14px 0 34px -12px rgba(43, 35, 29, .28); }

/* Макет має бути видно цілим. Тому картинку тримаємо в межах внутрішньої
   коробки (padding + content-box): згори лишається місце під кнопки, знизу —
   під розчинення у фон. Так вона не впирається в градієнт і не ріжеться. */
/* Коробка паралаксу. Її веде прокрутка (нижче), тому скрипт її не чіпає. */
.m-hero-par { position: absolute; left: 0; right: 0; top: 0; height: 268px; z-index: 1; }
.m-hero {
  position: absolute; inset: 0;
  box-sizing: border-box;
  padding: calc(64px + env(safe-area-inset-top)) 46px 40px;
  background-color: transparent;
  background-size: contain; background-position: center;
  background-repeat: no-repeat;
  background-origin: content-box; background-clip: content-box;
  /* will-change не потрібен: фото більше не рухається. Зайвий шар лише
     дорожчав кадр і, що гірше, створювався й знищувався на початку
     жесту — тобто сам додавав ривок. */
}
/* Розчинення у фон починається нижче за картинку. */
.m-hero::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(246, 243, 240, 0) 86%, var(--m-bg) 100%);
}
.m-hero.empty { display: grid; place-items: center; color: var(--m-mute); }

/* ─── Паралакс макета ───

   Веде його ПРОКРУТКА, а не скрипт. Раніше фото рухав обробник події
   scroll — а на айфоні прокрутку виконує компоситор і подія приходить уже
   після кадру, тому макет завжди їхав із запізненням і смикався.

   scroll-timeline прив'язує анімацію просто до положення скролера: рух
   рахує та сама система, що й саму прокрутку, тож відставати нема від
   чого. Якщо браузер такого не вміє — блок не застосовується взагалі, і
   макет просто стоїть, як стояв. Нічого не ламається. */
@supports (animation-timeline: scroll()) and (timeline-scope: --t) {
  .m-order { timeline-scope: --m-hero-scroll; }
  .m-order-body { scroll-timeline: --m-hero-scroll block; }
  .m-hero-par {
    animation: m-hero-par linear both;
    animation-timeline: --m-hero-scroll;
    /* Шлях рахує скрипт за реальною висотою сторінки: коротка картка
       матеріалу інакше не встигала показати рух. 340px — запасне
       значення, якщо змінну ще не проставили. */
    animation-range: 0 var(--hero-range, 340px);
    will-change: transform, opacity;
  }
  /* Ті самі числа, що були в скрипті: фото йде втричі повільніше за
     вміст і повністю згасає за 340px прокрутки. */
  @keyframes m-hero-par {
    from { transform: translate3d(0, 0, 0); opacity: 1; }
    to   { transform: translate3d(0, -102px, 0); opacity: 0; }
  }
}

/* ─── Навігація поверх макета ───
   Шар кнопок лежить ПОЗА скролером, тому вони не їдуть разом із вмістом.
   Сама смуга дотиків не ловить — тільки самі кнопки. */
.m-nav {
  position: absolute; left: 0; right: 0; top: 0; z-index: 4;
  display: flex; align-items: center; gap: 10px;
  padding: calc(16px + env(safe-area-inset-top)) 18px 0;
  pointer-events: none;
}
.m-nav > * { pointer-events: auto; }

/* Кругла кнопка на світлому тлі макета: своя підкладка й м'яка тінь,
   інакше значок губиться на світлій частині зображення. */
.m-round {
  position: relative;
  width: 40px; height: 40px; flex: 0 0 auto; border-radius: 999px;
  background: #FFFDFB; color: var(--m-ink);
  display: grid; place-items: center; cursor: pointer;
  box-shadow: 0 2px 10px -4px rgba(58, 44, 32, .3);
}
.m-round.danger { color: #C1524B; }
/* Лічильник коментарів на кнопці чату. */
.m-round-n {
  position: absolute; top: -3px; right: -3px;
  min-width: 17px; height: 17px; padding: 0 4px; border-radius: 999px;
  background: var(--m-ink); color: #F7F1EA;
  font: 500 10px var(--font-sans); display: grid; place-items: center;
  box-shadow: 0 0 0 2px #FFFDFB;
}

/* Підпис під рядком у шторці («Знайдено 12»). */
.m-row-sub {
  font: 400 11.5px var(--font-sans); color: var(--m-faint);
}

.m-order-body {
  position: absolute; inset: 0; z-index: 2;
  /* Низ лишає місце під док: інакше остання картка — чек або габарити —
     ховається під панеллю меню, і догорнути до неї неможливо. */
  padding: 12px 18px calc(var(--m-tabh) + 24px + env(safe-area-inset-bottom));
  display: flex; flex-direction: column; gap: 12px;
  /* contain, а не none: власний відскок айфона лишається, а сторінка
     під застосунком не тягнеться. */
  overscroll-behavior: contain;
  /* Убік цій сторінці їхати нікуди — навіть якщо якийсь блок на мить
     виявиться ширшим за екран. */
  overflow-x: hidden;
  overscroll-behavior-x: none;
  touch-action: pan-y;
}

/* Жодної підкладки під вмістом.

   Вона тут була рівно доти, доки макет стояв нерухомо: без неї фото
   визирало у проміжках між блоками. Тепер макет знову їде й гасне разом
   із прокруткою (див. паралакс вище), тож ховати його нічим не треба —
   а суцільний непрозорий лист і перекривав макет, і давав блик у мить
   переходу. */

/* Прозоре місце під фото: по ньому гортають і по ньому ж клікають. */
.m-hero-hit {
  height: 226px; margin: 0 -18px; background: none; padding: 0; border: 0;
  cursor: zoom-in;
}
/* Без цього блок з overflow:hidden сплющується в нуль. */
.m-order-body > * { flex: 0 0 auto; }

/* ─────────── Поява блоків, що доїхали пізніше ───────────
   Сторінка НЕ гасне цілком: усе, що вже є, стоїть одразу. Плавно
   проступають лише ті блоки, дані для яких приїхали згодом, — чек і
   накладна. Рухається сама прозорість, місце під блок уже є, тож нічого
   не стрибає. */
.m-late { animation: m-late-in .34s ease both; }
@keyframes m-late-in { from { opacity: 0; } to { opacity: 1; } }
@media (prefers-reduced-motion: reduce) {
  .m-late { animation: none; }
}

.m-o-head { padding: 0 2px; }
.m-o-meta {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  font: 400 10.5px var(--font-sans); letter-spacing: .12em;
  text-transform: uppercase; color: #A2917F;
}
.m-o-meta i { font-style: normal; opacity: .45; }
.m-o-meta em { font-style: normal; color: #9A5F23; }
.m-o-name { font: 500 23px/1.15 var(--font-display); letter-spacing: -.015em; color: var(--m-ink); margin-top: 6px; }

.m-o-status {
  display: flex; align-items: center; gap: 10px;
  padding: 6px 6px 6px 18px; border-radius: 999px; cursor: pointer;
}
.m-o-status i { width: 9px; height: 9px; border-radius: 999px; flex: 0 0 auto; }
.m-o-st-name { flex: 1; min-width: 0; font: 400 15px var(--font-sans); }
.m-o-change {
  height: 38px; padding: 0 11px 0 15px; border-radius: 999px; flex: 0 0 auto;
  background: rgba(255, 255, 255, .72); color: var(--m-soft);
  display: inline-flex; align-items: center; gap: 2px;
  font: 400 12.5px var(--font-sans); cursor: pointer; white-space: nowrap;
}
.m-o-change svg { width: 12px; height: 12px; color: var(--m-faint); }

/* ─── Блоки, що редагуються ─── */
.m-block {
  background: var(--m-card); border-radius: 19px; padding: 15px 17px 16px;
  box-shadow: var(--m-sh-card); cursor: pointer;
  transition: background .16s ease;
}
.m-block.press { background: #FBF8F4; }
/* Блок лише для перегляду: без курсора-пальця й без відгуку на дотик. */
.m-block.m-view { cursor: default; }
.m-block.m-view.press { background: var(--m-card); transform: none; }
.m-block-prod { padding: 16px 17px 17px; }
.m-block-pers { padding: 16px 17px 6px; }
.m-k {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  font: 400 10.5px var(--font-sans); letter-spacing: .18em;
  text-transform: uppercase; color: var(--m-faint); margin-bottom: 11px;
}
.m-k svg { color: #CFC0B0; }

.m-c-addr { font: 400 13px/1.55 var(--font-sans); color: var(--m-soft); white-space: pre-line; }
.m-c-sub {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 6px;
  font: 400 12.5px var(--font-sans); color: var(--m-faint);
}
.m-c-sub i { width: 3px; height: 3px; border-radius: 999px; background: #D3C7B9; }

.m-p-head { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; }
.m-p-name { font: 400 17px var(--font-sans); color: var(--m-ink); }
.m-p-line {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 10px;
}
.m-c-val { font: 400 13px var(--font-sans); color: var(--m-soft); }
.m-block .m-size { height: 21px; padding: 0 8px; font-size: 11px; line-height: 21px; }
.m-block .m-sq { width: 10px; height: 10px; border-radius: 3px; }
.m-block .m-opts { margin-top: 9px; }
.m-block .m-opt {
  height: 29px; padding: 0 12px 0 9px; background: var(--m-tint-3);
  font-size: 12.5px; color: var(--m-soft); gap: 6px;
}
.m-block .m-opt svg { color: #B4894F; }

.m-pers-row {
  display: flex; align-items: baseline; gap: 12px;
  padding: 10px 0; border-bottom: 1px solid var(--m-line);
}
.m-pers-row:last-child { border-bottom: none; }
.m-pers-k { font: 400 12.5px var(--font-sans); color: var(--m-faint); }
.m-pers-v { flex: 1; text-align: right; font: 400 14.5px var(--font-sans); color: var(--m-ink); }

/* ─── Накладна: два стани в одній комірці ─── */
.m-inv { display: grid; min-width: 0; border-radius: 19px; }
.m-inv > * { grid-area: 1 / 1; }
.m-inv-state {
  min-width: 0; padding: 16px 17px 17px; border-radius: 19px;
  transition: opacity .26s ease, transform .38s var(--m-ease);
}
/* Класи навмисно з префіксом: короткі .in/.out уже зайняті десктопною
   таблицею (поле вводу заввишки 38px), і картка накладної схлопувалась. */
.m-inv-state.m-show { opacity: 1; transform: scale(1); }
.m-inv-state.m-hide { opacity: 0; transform: scale(.9); pointer-events: none; }
.m-inv-sug { background: #FCF5E7; }
.m-inv-done { background: #EDF2EC; }
/* Хрестик у шапці пропозиції: прибрати її й вписати номер руками. */
.m-sg-off {
  display: flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; margin: -6px -6px -6px 0;
  border-radius: 999px; background: transparent; color: #B99C6A;
}
.m-sg-off svg { width: 13px; height: 13px; }
.m-sg-off.press { background: rgba(185, 156, 106, .14); }

/* Накладної ще немає й тарифів теж — спокійний стан: що заважає й куди
   натиснути. Раніше на цьому місці не було нічого. */
.m-inv-wait { background: var(--m-tint-4); }
.m-inv-wait .m-inv-h { color: var(--m-faint); }
.m-inv-note {
  font: 400 13px/1.45 var(--font-sans); color: var(--m-soft);
  margin: -4px 0 13px;
}
.m-inv-wait .m-btn { width: 100%; }
.m-inv-done.m-pop, .m-track.m-pop { animation: m-pop .46s var(--m-pill) both; }
@keyframes m-pop {
  0%   { opacity: 0; transform: scale(.5); }
  60%  { opacity: 1; transform: scale(1.12); }
  100% { opacity: 1; transform: scale(1); }
}
.m-inv-h {
  display: flex; align-items: center; gap: 9px; margin-bottom: 12px;
  font: 400 10.5px var(--font-sans); letter-spacing: .18em;
  text-transform: uppercase; color: #4C6353;
}
.m-inv-h i { width: 7px; height: 7px; border-radius: 999px; flex: 0 0 auto; }
.m-inv-h em {
  font: 400 11.5px var(--font-sans); font-style: normal;
  letter-spacing: 0; text-transform: none; color: #5E6B58;
}
.m-pill-soft {
  height: 22px; padding: 0 10px; border-radius: 999px;
  background: rgba(255, 255, 255, .72); color: inherit;
  font: 400 10.5px/22px var(--font-sans); letter-spacing: .04em; text-transform: none;
}
.m-carrier {
  display: flex; align-items: center; gap: 12px;
  min-width: 0; max-width: 100%;
  padding: 12px 14px; border-radius: 16px; background: rgba(255, 255, 255, .72);
}
.m-carrier-i {
  width: 34px; height: 34px; flex: 0 0 auto; border-radius: 11px;
  display: grid; place-items: center; background: #F8EFDC; color: #8A6428;
}
.m-carrier-t { flex: 1; min-width: 0; }
/* Усі рядки всередині — в одну лінію з крапками на хвості. */
.m-carrier-t > span, .m-track-k, .m-track-n, .m-carrier-n, .m-carrier-s {
  display: block; min-width: 0; overflow: hidden;
  white-space: nowrap; text-overflow: ellipsis;
}
.m-carrier-n { font: 400 14px var(--font-sans); color: var(--m-ink); }
.m-carrier-s { font: 400 11.5px var(--font-sans); color: #9C8B7C; margin-top: 2px; }
.m-carrier-p { font: 500 20px var(--font-display); letter-spacing: -.015em; color: var(--m-ink); flex: 0 0 auto; }
.m-inv-go { margin-top: 12px; }

/* Картка накладної завжди по ширині картки замовлення. Трек-номер —
   суцільний рядок цифр, який нема де перенести, тому він просто
   обрізається крапками: краще недобачити хвіст, ніж роз'їхати блок.
   Повний номер лишається в копії по кліку. */
.m-trackbox {
  display: flex; align-items: center; gap: 12px; width: 100%;
  min-width: 0; max-width: 100%;
  padding: 13px 14px; border-radius: 16px; background: rgba(255, 255, 255, .72);
  text-align: left; cursor: pointer; color: #8FA292;
}
.m-trackbox .m-carrier-i { background: #EAF1E9; color: #5C7A63; }
.m-track-k { font: 400 10px var(--font-sans); letter-spacing: .14em; text-transform: uppercase; color: #8FA292; }
.m-track-n { font: 500 16px var(--font-sans); color: var(--m-ink); margin-top: 3px; }
/* Щойно оформлена накладна: номер спершу зелений, далі колір плавно
   перетікає у звичайний — щоб око одразу знайшло, що саме з'явилось. */
@keyframes m-track-fresh {
  0%   { color: #3F8B57; }
  50%  { color: #3F8B57; }     /* тримаємо помітно довше */
  100% { color: var(--m-ink); }
}
/* Номер у КАРТЦІ черги лежить у .m-track > .num, а на сторінці замовлення —
   у .m-track-n. Правило було лише на другий випадок, тому в картці зеленого
   не було видно взагалі. */
.m-pop .m-track-n,
.m-track.m-pop .num { animation: m-track-fresh 2.2s var(--m-ease-soft) both; }
@media (prefers-reduced-motion: reduce) {
  .m-pop .m-track-n { animation: none; }
}
.m-inv-line {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin-top: 11px; padding: 0 3px;
  font: 400 12.5px var(--font-sans); color: #4C6353;
}
.m-inv-line i { width: 3px; height: 3px; border-radius: 999px; background: #A9BCAB; }
.m-inv-line span:last-child { color: #8FA292; }
.m-btn-row { display: flex; gap: 9px; margin-top: 13px; }
.m-btn-row .m-btn { height: 44px; width: auto; flex: 1; border-radius: 14px; font-size: 13px; gap: 8px; }
.m-btn-row .m-btn svg { flex: 0 0 auto; }
.m-inv-done .m-btn-soft { color: #4C6353; }

/* ─── Кнопки ───
   Базові стилі: вони жили в секції, яку я переписував під новий хендоф,
   і без них кнопки лишались сірими, а картка накладної розповзалась. */
.m-btn {
  width: 100%; height: 50px; border-radius: 16px; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center; gap: 9px;
  font: 500 14px var(--font-sans);
  transition: transform .14s var(--m-pill), filter .16s ease, background .16s ease;
}

.m-btn-dark { background: var(--m-ink); color: #F7F1EA; }
.m-btn-soft { background: rgba(255, 255, 255, .72); color: var(--m-ink); }

/* ─────────── Шторка профілю ───────────
   Два рядки «ключ — значення» і вихід. Більше тут нічого не треба: усе
   решта живе на своїх екранах. */
.m-row {
  display: flex; align-items: baseline; gap: 12px;
  padding: 13px 2px; border-bottom: 1px solid rgba(226, 214, 200, .5);
}
.m-row:last-of-type { border-bottom: none; }
.m-row-k {
  flex: 0 0 auto; min-width: 78px;
  font: 400 12px var(--font-sans); color: var(--m-faint);
}
.m-row-v {
  flex: 1; min-width: 0; text-align: right;
  font: 400 14px var(--font-sans); color: var(--m-ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.m-signout { margin-top: 14px; justify-content: center; gap: 9px; }

/* ─────────── Габарити ───────────
   Роль «Виробництво» бачить тут те, що справді заповнює, — замість чека.
   Чотири поля в один ряд: на телефоні це рівно та ширина, де цифри ще
   читаються без прокрутки. */
/* Габарити — звичайний блок сторінки: та сама поверхня, радіус, тінь і
   заголовок .m-k, що в «Клієнта» й «Товару». Раніше він мав власне
   оформлення й випадав із ряду. */
.m-dims { width: 100%; border: none; text-align: left; display: block; }
.m-dims-v {
  display: block; margin-top: 9px;
  font: 400 15px var(--font-sans); color: var(--m-ink);
  font-variant-numeric: tabular-nums;
}
.m-dims-v.none { color: var(--m-faint); }
/* Замість слова «Змінити» — олівець: у заголовку блоку слово важче за
   саму дію. */
.m-dims-go { flex: 0 0 auto; display: inline-flex; color: var(--m-faint); }
.m-dims-go svg { width: 15px; height: 15px; }

/* Форма у шторці. */
.m-dims-form { display: flex; flex-direction: column; gap: 12px; }
.m-dims-hint { font: 400 12px/1.5 var(--font-sans); color: var(--m-faint); }
.m-dims-row { display: flex; gap: 8px; }
.m-dims-row.one { max-width: 50%; }
.m-dim-f { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 6px; }
.m-dim-l { font: 400 11px var(--font-sans); color: var(--m-faint); }
.m-dim-w {
  position: relative; display: flex; align-items: center;
  background: #FFFDFA; border: 1px solid #E7DAC9; border-radius: 12px;
  transition: border-color .16s ease, box-shadow .16s ease;
}
.m-dim-w:focus-within { border-color: #DCC49B; box-shadow: 0 0 0 3px #F6EEE4; }
.m-dim-in {
  width: 100%; min-width: 0; height: 44px; padding: 0 26px 0 11px;
  border: none; outline: none; background: none;
  font: 400 16px var(--font-sans); color: var(--m-ink);
}
.m-dim-in::placeholder { color: var(--m-faint); }
.m-dim-w i {
  position: absolute; right: 9px; font-style: normal;
  font: 400 11px var(--font-sans); color: var(--m-faint); pointer-events: none;
}

/* Розміри в картці черги — там, де в решти стоїть сума. Звичайний шрифт,
   приглушений тон: це довідка, а не головне число рядка. */
.m-dimtag {
  flex: 0 0 auto; font: 400 11.5px var(--font-sans); color: var(--m-faint);
  white-space: nowrap; font-variant-numeric: tabular-nums; letter-spacing: .01em;
}
.m-btn-text {
  background: none; color: #8A6428; height: 42px;
  font-weight: 400; font-size: 13px; margin-top: 2px;
}
.m-btn-text svg { width: 13px; height: 13px; }

/* ─── Прибуток і чек ─── */
.m-profit {
  width: 100%; text-align: left; cursor: pointer;
  background: #F1E9DE; border-radius: 20px; padding: 17px 18px 18px;
}
.m-profit-k {
  display: flex; align-items: center; gap: 10px;
  font: 400 10.5px var(--font-sans); letter-spacing: .18em;
  text-transform: uppercase; color: #9C8B7C;
}
.m-profit-k svg { color: #C0B0A0; transition: transform .3s var(--m-ease); }
.m-profit.open .m-profit-k svg { transform: rotate(180deg); }
/* Сума й маржа — на одній базовій лінії. */
.m-profit-row { display: flex; align-items: baseline; gap: 10px; margin-top: 11px; }
.m-profit-n { font: 500 27px/1 var(--font-display); letter-spacing: -.02em; color: var(--m-ink); }
.m-profit-m { font: 400 12px var(--font-sans); color: var(--m-soft); }
/* Чотири окремі скруглені сегменти — без підкладки-треку. */
.m-bar { display: flex; gap: 3px; height: 8px; margin-top: 16px; }
.m-bar i { border-radius: 999px; }
.m-legend {
  display: flex; flex-wrap: wrap; gap: 9px 14px; margin-top: 12px;
  font: 400 11.5px var(--font-sans); color: var(--m-soft);
}
.m-legend span { display: inline-flex; align-items: center; gap: 6px; }
.m-legend i { width: 7px; height: 7px; border-radius: 2px; }

.m-receipt {
  display: grid; grid-template-rows: 0fr; opacity: 0;
  transition: grid-template-rows .42s var(--m-ease), opacity .26s ease,
              margin-top .42s var(--m-ease);
}
.m-receipt.on { grid-template-rows: 1fr; opacity: 1; }
.m-receipt > div { overflow: hidden; min-height: 0; }
/* Проміжок між карткою прибутку й першим блоком чека дає сітка екрана
   (gap: 12px) — власного відступу тут не треба. */
.m-rc-wrap { display: flex; flex-direction: column; gap: 10px; }
.m-rc {
  padding: 15px 17px 7px; background: var(--m-card); border-radius: 19px;
  box-shadow: var(--m-sh-card);
}
.m-rc-h {
  display: flex; align-items: center; gap: 9px;
  font: 400 10.5px var(--font-sans); letter-spacing: .18em;
  text-transform: uppercase; color: #9C8B7C;
}
.m-rc-h i { width: 7px; height: 7px; border-radius: 999px; }
.m-rc-row {
  display: flex; align-items: center; gap: 12px;
  padding: 10px 0; border-bottom: 1px solid var(--m-line);
}
.m-rc-row span { flex: 1; font: 400 13px var(--font-sans); color: var(--m-soft); }
.m-rc-row b { font: 400 14px var(--font-sans); color: #8C7C6D; }
.m-rc-row.sum span, .m-rc-row.sum b { color: var(--m-ink); font-weight: 500; }
.m-rc-row.last { border-bottom-color: transparent; }

/* ─────────── Шторки ─────────── */
.m-scrim {
  position: absolute; inset: 0; z-index: 40;
  background: rgba(43, 35, 29, .34);
  opacity: 0; pointer-events: none;
  transition: opacity .3s cubic-bezier(.4, 0, .2, 1), visibility 0s;
  will-change: opacity;
}
.m-scrim.on { opacity: 1; pointer-events: auto; }
/* Затемнення висить у розмітці завжди. Поки шторки немає, прибираємо
   його зі сцени: прозорий шар на весь екран усе одно компонується. */
/* Так само й затемнення: ховаємо його після того, як воно згасло. */
.m-scrim:not(.on) { visibility: hidden; transition-delay: 0s, .3s; }
/* Шторка їде на композиторі: translate3d плюс заздалегідь піднятий шар.
   Без цього браузер створює шар у момент показу — і перший кадр
   «спотикається», що й читалось як ривок. */
/* Схована шторка стоїть за нижнім краєм, але її тінь (розмиття 50px)
   діставала аж до панелі меню — саме вона й видніла смугою знизу. Поки
   шторка закрита, прибираємо її зовсім. */
/* visibility ховаємо ЛИШЕ після того, як шторка доїхала вниз. Доти вона
   мусить лишатись видимою — інакше зникає миттєво, і плавного від'їзду
   не видно взагалі (це й читалось як «закривається в кат»). */
.m-sheet:not(.on) { visibility: hidden; box-shadow: none; transition-delay: 0s, .3s; }
.m-sheet {
  position: absolute; left: 0; right: 0; z-index: 41;
  /* Клавіатура не має ховати поле: шторка стає рівно над нею. */
  bottom: var(--m-kb, 0px);
  max-height: calc(90% - var(--m-kb, 0px)); display: flex; flex-direction: column;
  background: var(--m-raised); border-radius: 28px 28px 0 0;
  box-shadow: 0 -20px 50px -30px rgba(43, 35, 29, .7);
  transform: translate3d(0, 101%, 0);
  /* Звичайна, всім знайома крива для шторок — cubic-bezier(.4, 0, .2, 1),
     0.3s. Ніяких вигадливих вигинів: до цього тут стояли то крива з
     розгоном у кінці, то майже прямий старт, і обидві читались як ривок. */
  transition: transform .3s cubic-bezier(.4, 0, .2, 1), visibility 0s;
  will-change: transform; contain: paint;
}
.m-sheet.on {
  transform: translate3d(0, 0, 0);
  /* Поява: різкий кидок на старті й дуже довгий хвіст у кінці.

     Крива майже «експоненційна» — до 80% шляху шторка долітає за першу
     третину часу, а решту повзе. Саме тому не видно моменту зупинки:
     швидкість згасає поступово, а не обривається на межі. */
  transition: transform .62s cubic-bezier(.08, .92, .12, 1), visibility 0s;
}
.m-grab { width: 38px; height: 5px; border-radius: 999px; background: #E2D6C8; margin: 9px auto 0; flex: 0 0 auto; }
.m-sheet-h {
  display: flex; align-items: flex-start; gap: 12px;
  padding: 14px 20px 10px; flex: 0 0 auto;
}
.m-sheet-k { font: 400 10px var(--font-sans); letter-spacing: .2em; text-transform: uppercase; color: #9C8B7C; }
.m-sheet-t { font: 500 19px var(--font-display); letter-spacing: -.01em; color: var(--m-ink); margin-top: 4px; }
.m-x {
  width: 32px; height: 32px; flex: 0 0 auto; border-radius: 999px;
  background: var(--m-tint); color: var(--m-soft); display: grid; place-items: center; cursor: pointer;
}
.m-sheet-b {
  padding: 4px 18px 6px; overflow-y: auto; flex: 1;
  display: flex; flex-direction: column; gap: 11px;
}
.m-sheet-b:has(.m-rates) { padding: 2px 16px 6px; }
/* Підвал без підкладки й лінії — так у референсі: кнопки лежать просто
   на поверхні шторки. */
.m-sheet-f {
  display: flex; gap: 9px; padding: 13px 18px calc(24px + env(safe-area-inset-bottom));
  flex: 0 0 auto;
}
/* У підвалі кнопки ділять рядок, тож ширину задає flex, а не 100%
   з базового правила .m-btn. */
.m-sheet-f .m-btn { height: 50px; width: auto; }
/* Єдина кнопка в підвалі — на всю ширину й трохи вища, як у макеті. */
.m-sheet-f .m-btn:only-child { flex: 1; height: 52px; }
.m-btn-tint { flex: 0 0 auto; padding: 0 22px; background: var(--m-tint); color: var(--m-soft); font-weight: 400; }

/* ─────────── Шторка редагування: два рівні ───────────
   Тіло фіксованої висоти — інакше при переході між рівнями шторка
   стрибає. Рівень 2 приходить справа, повернення — зліва. */
/* Висоту ставить скрипт під вміст рівня; тут — лише перехід, щоб
   шторка змінювала розмір плавно, а не стрибала. */
.m-ed-body {
  box-sizing: border-box; display: block; flex: 0 0 auto;
  transition: height .34s var(--m-ease);
}
@keyframes m-lvl-in   { from { opacity: 0; transform: translateX(26px); } }
@keyframes m-lvl-back { from { opacity: 0; transform: translateX(-18px); } }
.lvl2 { animation: m-lvl-in .34s var(--m-ease) both; display: flex; flex-direction: column; gap: 2px; }
.lvl1 { animation: m-lvl-back .34s var(--m-ease) both; }

/* Рівень 1 — картка з рядками. Підпис ЗГОРИ, значення під ним. */
.m-f-card {
  background: #FFFFFF; border-radius: 18px; overflow: hidden;
  box-shadow: var(--m-sh-card);
}
.m-f-row {
  padding: 12px 16px 13px; display: flex; flex-direction: column; gap: 5px;
  border-bottom: 1px solid var(--m-line);
}
.m-f-row.last { border-bottom: none; }
.m-f-lb {
  font: 400 10.5px var(--font-sans); letter-spacing: .14em;
  text-transform: uppercase; color: var(--m-faint);
}
.m-f-pick {
  width: 100%; background: none; padding: 0; cursor: pointer;
  display: flex; align-items: center; gap: 9px; text-align: left;
}
.m-f-val {
  flex: 1; min-width: 0; font: 400 15px var(--font-sans); color: var(--m-ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.m-f-pick svg { flex: 0 0 auto; width: 13px; height: 13px; color: #CFC0B0; }
.m-f-sq {
  width: 13px; height: 13px; flex: 0 0 auto; border-radius: 4px;
  box-shadow: inset 0 0 0 1px rgba(43, 35, 29, .16);
}
.m-f-sq.big { width: 14px; height: 14px; }
.m-f-in {
  width: 100%; height: 22px; padding: 0; border: none; outline: none;
  background: transparent; font: 400 15px var(--font-sans); color: var(--m-ink);
}
.m-f-area {
  width: 100%; padding: 0; border: none; outline: none; background: transparent;
  font: 400 14px/1.5 var(--font-sans); color: var(--m-ink); resize: none;
}
.m-f-opts { padding: 0 4px; margin-top: 14px; }
.m-f-opts-k {
  font: 400 10.5px var(--font-sans); letter-spacing: .16em;
  text-transform: uppercase; color: var(--m-faint); margin-bottom: 9px;
}
/* Чипи опцій: увімкнений — темний із галочкою, вимкнений — світлий. */
.m-f-opts .m-pick { height: 36px; padding: 0 14px; }
.m-f-opts .m-pick.on { padding-left: 11px; }

/* Рівень 2 — пункти вибору. */
.m-f-opt {
  display: flex; align-items: center; gap: 12px; width: 100%;
  min-height: 52px; padding: 0 15px; border-radius: 16px;
  background: transparent; cursor: pointer; text-align: left;
}
.m-f-opt.on { background: var(--m-tint-3); }
.m-f-opt-t { flex: 1; font: 400 15px var(--font-sans); color: var(--m-ink); }
.m-f-opt.on .m-f-opt-t { font-weight: 500; }
.m-x.back { color: var(--m-soft); }

/* Пункт списку в шторці (статуси) */
.m-opt-row {
  display: flex; align-items: center; gap: 12px; width: 100%;
  height: 50px; padding: 0 12px; border-radius: 15px; background: none;
  font: 400 15px var(--font-sans); color: var(--m-ink); text-align: left; cursor: pointer;
}
.m-opt-row.press { background: var(--m-tint-3); }
.m-opt-row.on { background: var(--m-tint-3); font-weight: 500; }
.m-opt-row i { width: 11px; height: 11px; border-radius: 999px; flex: 0 0 auto; }

/* Поля редагування */
.m-field { display: flex; flex-direction: column; gap: 6px; }
.m-label { font: 400 11.5px var(--font-sans); color: #9C8B7C; }
/* Підзаголовок частини форми. */
.m-part {
  font: 400 10px var(--font-sans); letter-spacing: .18em; text-transform: uppercase;
  color: var(--m-mute); padding-top: 6px; border-top: 1px solid var(--m-line);
  margin-top: 3px;
}
.m-part-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.m-in {
  width: 100%; height: 46px; padding: 0 14px; border-radius: 14px;
  border: 1px solid #E7DAC9; background: #FFFDFA; color: var(--m-ink);
  font: 400 14.5px var(--font-sans); outline: none;
  transition: border-color .16s ease;
}
.m-in:focus { border-color: var(--gold); }
textarea.m-in { height: auto; padding: 12px 14px; line-height: 1.5; resize: none; }
.m-chips { display: flex; flex-wrap: wrap; gap: 8px; }
.m-pick { padding: 0 15px; }
.m-pick {
  height: 38px; padding: 0 14px; border-radius: 999px;
  background: #FFFDFA; box-shadow: inset 0 0 0 1px #E7DAC9; color: var(--m-soft);
  display: inline-flex; align-items: center; gap: 8px;
  font: 400 13.5px var(--font-sans); cursor: pointer;
  transition: transform .14s var(--m-pill), background .16s ease, color .16s ease;
}

.m-pick.on { background: var(--m-ink); box-shadow: none; color: #F7F1EA; font-weight: 500; }
.m-pick .m-sq { width: 12px; height: 12px; }
/* Галочка в чипі опції: вимкнена не займає місця, тож чип не стрибає. */
.m-pick .m-check { width: 0; opacity: 0; margin-right: -8px; transition: width .2s var(--m-ease), opacity .15s ease, margin-right .2s var(--m-ease); }
.m-pick.on .m-check { width: 13px; opacity: 1; margin-right: 0; }
.m-item-x {
  width: 26px; height: 26px; border-radius: 999px; background: none;
  color: var(--m-mute); display: grid; place-items: center; cursor: pointer;
}
.m-add-item {
  display: inline-flex; align-self: flex-start; align-items: center; gap: 8px;
  height: 42px; padding: 0 18px; border-radius: 999px;
  background: var(--m-tint-3); color: var(--m-soft);
  font: 400 13px var(--font-sans); cursor: pointer; margin-top: 2px;
}
.m-group2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
/* Усередині пари відступ між полями не потрібен — вони поруч, а не одне
   під одним; без цього друга колонка з'їжджала вниз. */
.m-group2 > .m-field + .m-field { margin-top: 0; }

/* Картки тарифів. Значення з макета: поле 16px по боках, крок 8, картка
   13/15, радіус 17, межа 1.5px, ціна Cormorant 20. */
.m-rates { display: flex; flex-direction: column; gap: 8px; }
.m-rate {
  display: flex; align-items: center; gap: 12px; width: 100%; text-align: left;
  padding: 13px 15px; border-radius: 17px;
  box-shadow: inset 0 0 0 1.5px var(--m-line-3); background: #FFFFFF; cursor: pointer;
  transition: box-shadow .16s ease, background .16s ease, transform .22s var(--m-pill);
}
.m-rate.on { box-shadow: inset 0 0 0 1.5px #DCC49B; background: #FFFDF7; }
.m-radio {
  width: 21px; height: 21px; flex: 0 0 auto; border-radius: 999px;
  box-shadow: inset 0 0 0 1.5px #D3C4B2; background: #FFFDFA;
  display: grid; place-items: center; color: #FFFDFA;
}
.m-rate.on .m-radio { box-shadow: inset 0 0 0 1.5px var(--walnut); background: var(--walnut); }
.m-rate-t { flex: 1; min-width: 0; }
.m-rate-n { display: flex; align-items: center; gap: 7px; min-width: 0; }
.m-rate-n b {
  font: 400 14px var(--font-sans); color: var(--m-ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.m-rate.on .m-rate-n b { font-weight: 500; }
.m-rate-s {
  display: block; font: 400 11.5px var(--font-sans); color: #9C8B7C; margin-top: 3px;
}
.m-rate-p { flex: 0 0 auto; font: 500 17px/1 var(--font-display); letter-spacing: -.01em; color: var(--m-ink); }
.m-tag {
  height: 18px; padding: 0 7px; border-radius: 999px; flex: 0 0 auto;
  font: 500 9.5px var(--font-sans); font-style: normal; letter-spacing: .06em;
  text-transform: uppercase; display: inline-flex; align-items: center;
}
.m-tag.warm { background: #F8EFDC; color: #8A6428; }
.m-tag.cool { background: #EDF2EC; color: #4C6353; }

/* Схлопування полоси пропозиції: висота йде в нуль тією ж кривою, що й
   решта анімацій, — картка не «обрізається» ривком. */
/* Схлопування полоси пропозиції. Анімуємо height у пікселях, а не
   grid-template-rows: сітку браузер перераховує на кожен кадр, і саме це
   давало ривок. Висоту ставить скрипт, коли починає анімацію. */
.m-collapse {
  overflow: hidden;
  transition: height .42s var(--m-ease), opacity .26s ease;
  will-change: height;
}
.m-collapse[style*="0px"] { opacity: 0; }

/* Паралакс під екраном оформлення: попередній крок трохи від'їжджає. */
/* Паралакс під екраном накладної. Цілимось у #mOrder, а не в клас: сам
   екран накладної теж «екран», і правило по класу ховало б його. */
#mApp.m-deep2 .m-queue,
#mApp.m-deep2 .m-filters,
#mApp.m-deep2 .m-fab { transform: translate3d(-42px, 0, 0); opacity: 0; pointer-events: none; }
#mApp.m-deep2 #mOrder.on { transform: translate3d(-42px, 0, 0); opacity: .5; }
/* Док на цьому екрані ні до чого — у нього своя нижня панель дій. */
body.m-app #mApp.m-deep2 ~ #mTabs, #mApp.m-deep2 ~ #mTabs { opacity: 0; pointer-events: none; }
/* Той самий час і крива, що й у решти екранів. Тут вони були задані
   окремо (заради прозорості під час другого рівня) — і мовчки
   перекривали загальне правило, бо селектор з id сильніший. Саме через
   це перехід у картку лишався різким, скільки б я не міняв --m-nav-*. */
#mOrder.on {
  transition: transform var(--m-nav-dur) var(--m-nav-ease),
              opacity var(--m-nav-dur) var(--m-nav-ease);
}

/* Позначка «розібрала аі» біля підпису блоку. */
.m-ai {
  margin-left: 8px; padding: 0 7px; height: 16px; border-radius: 999px;
  background: var(--m-tint-2); color: #8C7C6D;
  font: 400 9px var(--font-sans); font-style: normal; letter-spacing: .08em;
  display: inline-flex; align-items: center; vertical-align: 1px;
}

/* Дизайн копілки («C-6») — той самий бабл, але з цифрами. */
.m-design { font-variant-numeric: lining-nums tabular-nums; }

/* ─────────── Повне оформлення ───────────
   Три підсумкові блоки: повний — білий із зеленою галочкою, неповний —
   теплий, зі знаком оклику. */
.m-sum-block {
  display: flex; align-items: center; gap: 12px; width: 100%;
  padding: 14px 15px; border-radius: 17px;
  background: #FFFFFF; box-shadow: inset 0 0 0 1px var(--m-line-3);
  color: #CFC0B0; cursor: pointer;
  /* Блок — кнопка, а кнопка за замовчуванням центрує текст. */
  text-align: left;
}
.m-sum-block.warn { background: #FDF9F1; box-shadow: inset 0 0 0 1px #EFDDBC; }
.m-sum-i {
  width: 27px; height: 27px; flex: 0 0 auto; border-radius: 999px;
  background: #EBF1EA; color: #5C7A63; display: grid; place-items: center;
}
.m-sum-block.warn .m-sum-i { background: #F8EFDC; color: #A9762B; }
.m-sum-t { flex: 1; min-width: 0; }
.m-sum-t em {
  display: block; font: 400 10.5px var(--font-sans); font-style: normal;
  letter-spacing: .16em; text-transform: uppercase; color: #9C8B7C;
}
.m-sum-t b {
  display: block; font: 400 13px/1.45 var(--font-sans); color: var(--m-ink);
  margin-top: 4px; white-space: pre-line;
}
.m-sum-block.warn .m-sum-t b { color: #8A6428; }

/* Роздільник «Тариф ——— пораховано автоматично». */
.m-part-line {
  display: flex; align-items: center; gap: 9px; margin-top: 8px; padding: 0 2px;
  font: 400 10.5px var(--font-sans); letter-spacing: .16em;
  text-transform: uppercase; color: #9C8B7C;
}
.m-part-line i { flex: 1; height: 1px; background: #EBE2D6; }
/* Кнопка перерахунку тарифу — тиха, поруч із заголовком. */
.m-recalc {
  display: inline-flex; align-items: center; gap: 6px; flex: 0 0 auto;
  height: 28px; padding: 0 11px; border-radius: 999px;
  background: var(--m-tint-3); color: var(--m-soft);
  font: 400 11.5px var(--font-sans); letter-spacing: 0; text-transform: none;
  cursor: pointer;
}
.m-recalc[disabled] { opacity: .6; }
.m-part-line em {
  font: 400 11.5px var(--font-sans); font-style: normal;
  letter-spacing: 0; text-transform: none; color: var(--m-faint);
}

/* ─────────── Екран повного оформлення ───────────
   Окремий крок, що заїжджає збоку — як картка замовлення. */
/* Вище сторінки замовлення (31) і вище дока (33): повне оформлення —
   верхній екран, під ним не має проглядати нічого. Раніше тут стояло 30,
   а сторінку замовлення я підняв до 31 — і форма опинилась ПІД нею. На
   око це виглядало як «усе зависло»: два екрани один крізь одного. */
.m-full-screen { z-index: 34; }
.m-full-top {
  position: absolute; left: 0; right: 0; top: 0; z-index: 3;
  display: flex; align-items: center; gap: 12px;
  padding: calc(14px + env(safe-area-inset-top)) 18px 12px;
  background: #FCFAF8;
  border-bottom: 1px solid var(--m-hair);
}
.m-full-t { font: 500 18px/1.15 var(--font-display); letter-spacing: -.01em; color: var(--m-ink); margin-top: 2px; }
.m-full-body {
  position: absolute; left: 0; right: 0;
  top: calc(66px + env(safe-area-inset-top)); bottom: 0;
  padding: 14px 18px 150px;
  display: flex; flex-direction: column; gap: 9px;
  /* Прокрутки тут не було зовсім: поки блоків було три, вміст вміщався
     в екран і цього ніхто не помічав. З повним набором блоків нижні
     просто зрізало — дотягтись до них було нічим. */
  overflow-y: auto; -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
}
.m-full-foot {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 4;
  padding: 13px 18px calc(22px + env(safe-area-inset-bottom));
  background: #F7F4F1;
  border-top: 1px solid #E9E1D8;
  display: flex; flex-direction: column; gap: 10px;
}
.m-full-foot .m-btn { width: 100%; height: 52px; }
/* Результат перевірки накладної — над кнопками, щоб читалось першим. */
.m-check {
  padding: 12px 14px; border-radius: 14px; margin-bottom: 2px;
  font: 400 12.5px/1.5 var(--font-sans);
  max-height: 34vh; overflow-y: auto; overscroll-behavior: contain;
}
.m-check.good { background: #EDF2EC; color: #3F5A42; }
.m-check.bad { background: #FBF0EC; color: #7A4230; }
.m-check b { display: block; margin-bottom: 5px; font-weight: 500; }
.m-check span { display: block; padding: 2px 0; }
.m-check em { font-style: normal; font-weight: 500; opacity: .75; }
.m-full-foot .m-btn[disabled] { opacity: .45; }

/* Поля накладної: два в рядок, довгі — на всю ширину. */
.m-inv-group { display: flex; flex-direction: column; gap: 10px; }
/* Випадний список у шторці накладної — та сама «коробочка», що й поле
   вводу: рідний select, але зі своїм шевроном, бо системну стрілку в iOS
   не пересунути. */
.m-selw { position: relative; display: block; }
.m-sel {
  width: 100%; appearance: none; -webkit-appearance: none;
  padding-right: 38px; text-overflow: ellipsis;
}
.m-selw > svg {
  position: absolute; right: 12px; top: 50%; transform: translateY(-50%) rotate(90deg);
  pointer-events: none; color: var(--m-faint);
}

/* Пошук тарифів. Скільки він триватиме — наперед не знає ніхто, тож
   ніяких відсотків: три крапки, що дихають по черзі. */
.m-rates-load {
  display: flex; align-items: center; gap: 10px; padding: 16px 2px;
  font: 400 13.5px var(--font-sans); color: var(--m-soft);
}
.m-dots { display: inline-flex; gap: 5px; }
.m-dots i {
  width: 6px; height: 6px; border-radius: 50%; background: var(--gold);
  animation: m-dot 1.3s ease-in-out infinite;
}
.m-dots i:nth-child(2) { animation-delay: .16s; }
.m-dots i:nth-child(3) { animation-delay: .32s; }
@keyframes m-dot { 0%, 100% { opacity: .22; } 50% { opacity: 1; } }

/* Поява тарифів — по черзі знизу вгору, а не всі разом у кадр. */
.m-rates.fresh > .m-rate { animation: m-rate-in .44s var(--m-ease) both; }
.m-rates.fresh > .m-rate:nth-child(2) { animation-delay: .06s; }
.m-rates.fresh > .m-rate:nth-child(3) { animation-delay: .12s; }
.m-rates.fresh > .m-rate:nth-child(4) { animation-delay: .18s; }
.m-rates.fresh > .m-rate:nth-child(n+5) { animation-delay: .24s; }
@keyframes m-rate-in {
  from { opacity: 0; transform: translateY(10px) scale(.985); }
  to { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .m-dots i, .m-rates.fresh > .m-rate { animation: none; }
}

.m-inv-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
.m-inv-grid .m-field.wide { grid-column: 1 / -1; }

/* Підвал повного оформлення: кнопка плюс рядок про баланс. */
.m-foot-col { flex: 1; display: flex; flex-direction: column; gap: 10px; }
.m-foot-col .m-btn { width: 100%; height: 52px; }
.m-foot-col .m-btn[disabled] { opacity: .45; }
.m-foot-note {
  display: flex; align-items: center; justify-content: center; gap: 7px;
  font: 400 11.5px var(--font-sans); color: #9C8B7C;
}

/* Рядок «Повне оформлення» — окрема плашка, а не кнопка-текст. */
.m-full {
  display: flex; align-items: center; gap: 11px; width: 100%; text-align: left;
  margin-top: 2px; padding: 13px 15px; border-radius: 17px;
  background: var(--m-tint-3); color: #CFC0B0; cursor: pointer;
}
.m-full-i {
  width: 28px; height: 28px; flex: 0 0 auto; border-radius: 9px;
  background: #F1EAE1; color: var(--m-soft); display: grid; place-items: center;
}
.m-full-t { flex: 1; min-width: 0; }
.m-full-t b { display: block; font: 400 13.5px var(--font-sans); color: var(--m-ink); }
.m-full-t em {
  display: block; font: 400 11.5px var(--font-sans); font-style: normal;
  color: #9C8B7C; margin-top: 2px;
}

/* Чат */
.m-msgs { display: flex; flex-direction: column; gap: 11px; }
.m-day {
  text-align: center; font: 400 10px var(--font-sans); letter-spacing: .18em;
  text-transform: uppercase; color: var(--m-mute); margin: 4px 0;
}
.m-msg { max-width: 78%; align-self: flex-start; }
.m-msg-a { font: 400 10.5px var(--font-sans); color: var(--m-faint); margin: 0 0 4px 4px; }
.m-bub {
  padding: 10px 13px; border-radius: 15px 15px 15px 5px;
  background: var(--m-tint); color: var(--m-ink);
  font: 400 13.5px/1.45 var(--font-sans);
}
.m-msg.me { align-self: flex-end; }
.m-msg.me .m-bub {
  background: var(--m-ink); color: #F7F1EA; border-radius: 15px 15px 5px 15px;
  box-shadow: 0 6px 14px -10px rgba(43, 35, 29, .9);
}
.m-msg.me .m-msg-a { text-align: right; margin: 0 4px 4px 0; }
.m-msg.fresh { animation: m-msg-in .44s var(--m-ease) both; }
@keyframes m-msg-in { from { opacity: 0; transform: translateY(12px) scale(.94); } }
.m-send { display: flex; align-items: center; gap: 10px; width: 100%; }
.m-send input {
  flex: 1; min-width: 0; height: 40px; border: none; background: none; outline: none;
  font: 400 14px var(--font-sans); color: var(--m-ink);
}
.m-send-b {
  width: 38px; height: 38px; flex: 0 0 auto; border-radius: 999px;
  background: var(--m-ink); color: #F7F1EA; display: grid; place-items: center; cursor: pointer;
}
.m-send-b:disabled { opacity: .4; }

/* Тост */
.m-toast {
  position: absolute; left: 50%; bottom: 108px; z-index: 60;
  padding: 11px 20px; border-radius: 999px;
  background: var(--m-ink); color: #F7F1EA; font: 400 13px var(--font-sans);
  white-space: nowrap;
  transform: translateX(-50%) translateY(14px) scale(.94); opacity: 0;
  /* Дотиків НЕ ловить. Без цього прозорий тост лишався висіти на z-index 60
     рівно над смугою статусів (він на 108px від низу, смуга — 94…160) і
     глушив по ній жести. Саме тому прокрутка статусів ламалась ПІСЛЯ
     перемикання розділу меню: там показується тост «розділ у роботі». */
  pointer-events: none;
  transition: transform .34s var(--m-ease), opacity .22s ease;
}
.m-toast.on { transform: translateX(-50%) scale(1); opacity: 1; }

/* Лінійка: службова плашка з вимірами екрана. Вмикається трьома тапами
   по логотипу, потрібна тільки щоб побачити справжні цифри з телефона. */
.m-ruler {
  position: absolute; left: 12px; right: 12px; top: 84px; z-index: 999;
  background: rgba(43, 35, 29, .93); color: #F7F1EA; border-radius: 14px;
  padding: 12px 14px; font: 400 12px/1.55 ui-monospace, monospace;
  box-shadow: 0 16px 40px -14px rgba(0, 0, 0, .6);
}
.m-ruler b { color: #E4B26B; font-weight: 600; }

.m-empty { padding: 60px 20px; text-align: center; font: 400 13px var(--font-sans); color: var(--m-faint); }

/* ─────────── Стани черги ───────────
   Порожньо, помилка і «ще їде» — це три різні речі. Раніше всі три
   виглядали як «Замовлень не знайдено», тож недоїхала відповідь була
   не відрізнити від порожнього статусу. */
.m-state {
  padding: 64px 32px; text-align: center;
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  animation: m-state-in .34s var(--m-ease) both;
}
@keyframes m-state-in { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
.m-state-t { font: 500 17px var(--font-display); color: var(--m-ink); }
.m-state-s {
  font: 400 12.5px var(--font-sans); color: var(--m-faint);
  line-height: 1.5; max-width: 260px; word-break: break-word;
}
.m-state-btn { width: auto; padding: 0 22px; height: 42px; margin-top: 10px; }

/* Скелет: та сама геометрія, що в картки, тож поява списку не зсуває
   екран. Пульсація — на opacity, найдешевша річ у кадрі. */
.m-sk-card { pointer-events: none; }
.m-sk {
  display: block; border-radius: 8px;
  background: linear-gradient(90deg, #F1EBE3 0%, #F7F2EC 50%, #F1EBE3 100%);
  background-size: 220% 100%;
  animation: m-sk-slide 1.25s ease-in-out infinite;
}
@keyframes m-sk-slide { from { background-position: 120% 0; } to { background-position: -120% 0; } }
.m-sk-t { width: 168px; height: 17px; border-radius: 9px; }
.m-sk-th { width: 62px; height: 62px; flex: 0 0 auto; border-radius: 13px; }
.m-sk-col { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 8px; padding-top: 3px; }
.m-sk-l1 { width: 58%; height: 11px; }
.m-sk-l2 { width: 76%; height: 15px; }
.m-sk-l3 { width: 44%; height: 11px; }
.m-sk-pill { width: 104px; height: 30px; border-radius: 999px; }
@media (prefers-reduced-motion: reduce) {
  .m-sk { animation: none; }
  .m-state { animation: none; }
}

/* Хвіст черги: крапки, поки домальовується наступна порція, або підсумок. */
.m-more { display: flex; justify-content: center; gap: 6px; padding: 22px 0 6px; }
.m-more span {
  width: 5px; height: 5px; border-radius: 999px; background: var(--m-mute);
  animation: m-pulse 1.1s ease-in-out infinite;
}
.m-more span:nth-child(2) { animation-delay: .16s; }
.m-more span:nth-child(3) { animation-delay: .32s; }
@keyframes m-pulse { 0%, 100% { opacity: .25; transform: scale(.82); } 50% { opacity: .9; transform: scale(1); } }
.m-more-end { text-align: center; padding: 22px 0 6px; font: 400 11.5px var(--font-sans); color: var(--m-mute); }

@media (prefers-reduced-motion: reduce) {
  #mApp * { animation: none !important; transition-duration: .01ms !important; }
}

/* ─────────── Фото на весь екран ───────────
   Тло тьмяніє, фото виростає з місця картки. Ніякої рамки й підписів —
   дивитись треба на фото. */
.m-lb {
  position: absolute; inset: 0; z-index: 60;
  display: grid; place-items: center; padding: 22px;
  background: rgba(28, 22, 18, 0);
  opacity: 0; pointer-events: none;
  transition: opacity .2s ease, background .28s ease;
}
.m-lb.on {
  opacity: 1; pointer-events: auto;
  background: rgba(28, 22, 18, .93);
}
.m-lb-img {
  max-width: 100%; max-height: 100%;
  border-radius: 14px; object-fit: contain;
  transform: scale(.86); opacity: 0;
  transition: transform .42s var(--m-pill), opacity .24s ease;
}
.m-lb.on .m-lb-img { transform: scale(1); opacity: 1; }
.m-lb-x {
  position: absolute; top: calc(16px + env(safe-area-inset-top)); right: 18px;
  background: rgba(255, 253, 250, .16); color: #FFFDFA;
}

/* Підказка при сильному потягу вниз. Лежить у скролері абсолютно, тож
   їде разом із ним і виринає саме там, куди дивиться око. */
.m-pull-hint {
  position: absolute; top: 16px; left: 0; right: 0; z-index: 3;
  margin: 0 auto; width: max-content; max-width: calc(100% - 40px);
  padding: 7px 15px; border-radius: 999px;
  background: rgba(43, 35, 29, .82); color: #FFFDFA;
  font: 400 11.5px var(--font-sans); letter-spacing: .02em;
  opacity: 0; transform: translateY(-6px) scale(.94);
  transition: opacity .18s ease, transform .28s var(--m-pill);
  pointer-events: none;
}
.m-order.m-pull-ready .m-pull-hint { opacity: 1; transform: none; }

/* ─────────── Кнопка в роботі ───────────
   Текст лишається, поряд крутиться кільце, і по кнопці раз у секунду
   пробігає світло. Порожня чорна смуга зі спінером читалась як
   зависання — саме через це здавалося, що застосунок завмер. */
.m-btn.m-busy {
  position: relative; overflow: hidden;
  pointer-events: none; opacity: .92;
}
.m-btn.m-busy svg { animation: m-spin .85s linear infinite; }
.m-btn.m-busy::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(90deg, transparent, rgba(255, 253, 250, .17), transparent);
  transform: translateX(-100%);
  animation: m-sweep 1.15s ease-in-out infinite;
}
@keyframes m-sweep { to { transform: translateX(100%); } }

/* ─────────── Оновлення потягом ───────────
   Кільце лежить під шапкою й проявляється рівно настільки, наскільки
   протягнули. Переходу в transform немає навмисно: під пальцем воно має
   йти кадр у кадр, а плавність вмикаємо лише на відпусканні (.anim). */
.m-refresh {
  position: absolute; z-index: 6;
  top: calc(56px + env(safe-area-inset-top)); left: 50%; margin-left: -17px;
  width: 34px; height: 34px; border-radius: 999px;
  background: var(--m-card); box-shadow: var(--m-sh-card);
  display: grid; place-items: center; color: var(--m-faint);
  opacity: 0; transform: translate3d(0, 0, 0) scale(.6);
  transition: opacity .18s ease, color .2s ease;
  pointer-events: none;
}
.m-refresh.anim { transition: opacity .18s ease, color .2s ease, transform .42s var(--m-ease); }
/* Дотягнули — кільце темніє: видно, що відпускання спрацює. */
.m-refresh.ready { color: var(--m-ink); }
/* Поки тягнуть, кільце повертає палець, а не анімація. */
.m-refresh svg { animation: none; }
.m-refresh.spin svg { animation: m-spin .8s linear infinite; }
/* Крутилка в кнопці «Підтвердити і створити» окремого правила не потребує:
   сама іконка вже несе клас .m-spin. Тут лише приглушуємо кнопку, поки
   йде запит, щоб було видно, що вона зайнята. */
[data-m="make"].busy { opacity: .9; }

/* На вузькому екрані (SE та подібні) чотири капсули в ряд ледве вміщаються —
   підтискаємо поля разом, замість того щоб різати числа. */
@media (max-width: 374px) {
  :root { --m-bal-pad: 13px; --m-bal-gap: 8px; }
}


/* ═════════════ Склад ═════════════
   Картка складу — та сама .m-card, що й у черзі: ті самі поля, та сама
   підошва зі статусом і шевроном. Різниця одна: замість фото товару —
   значок матеріалу на кольорі його стану. */
/* Плитка вужча за макет товару в замовленні: там фото, яке роздивляються,
   тут — позначка типу, тож вона поступається місцем назві. Колір спокійний
   пісочний і без обведення: стан уже показують капсула й шкала. */
.m-mthumb {
  width: 52px; height: 52px; border-radius: 15px;
  background: var(--m-tint-2); color: var(--m-soft);
  display: grid; place-items: center;
}

/* Текст картки складу починається рівно від верхньої межі плитки.

   Доти колонка розтягувалась на всю висоту плитки, а всередині ще й
   лишався просвіт від міжрядка дрібного напису — через це підпис і назва
   «з'їжджали» вниз, причому по-різному: у картках із постачальником
   рядків три, і зсув виходив інший, ніж там, де їх два. Тепер колонка не
   тягнеться, міжрядок дрібного напису притиснутий, а проміжок між
   підписом і назвою — три пікселі замість шести. */
#mMats .m-card-b { align-items: flex-start; }
#mMats .m-card-t { padding-top: 0; }
/* Ціна більше не тягне за собою підпис.

   Рядок вирівнювався по базовій лінії, а ціна вища за дрібний підпис —
   і сам підпис від'їжджав униз рівно там, де ціна є. Тому картки з ціною
   й без неї починались на різній висоті. Тепер обидва тримають однакову
   висоту рядка й починаються від верху колонки. */
/* Рядок підпису тримає висоту ТЕКСТУ, а не капсули стану.

   Капсула вища за дрібний підпис (24px проти 15), і поки вона розсувала
   рядок, назва від'їжджала вниз на цілих дванадцять пікселів — той самий
   «величезний відступ». Тепер вона висить у рядку, не збільшуючи його:
   від'ємні поля рівно на різницю висот. */
#mMats .m-meta-row { align-items: center; height: 16px; }
#mMats .m-meta { line-height: 16px; }
#mMats .m-sum { line-height: 16px; }
#mMats .m-mst { margin-top: -4px; margin-bottom: -4px; }
#mMats .m-name { margin-top: 2px; }
#mMats .m-variant { margin-top: 4px; }

/* Шкала залишку просто в картці: цифра поруч, але дивляться на смужку. */
/* Фарба — кольоровим колом замість значка: п'ятнадцять однакових крапель
   у списку не розрізняються, а колір видно з відстані витягнутої руки. */
/* Комірка під фарбу — без плитки: тільки саме коло, на всю ширину місця,
   що займав значок. */
.m-mpaint {
  width: 52px; height: 52px; background: none;
  display: grid; place-items: center;
}
.m-paint {
  width: 44px; height: 44px; border-radius: 999px; display: block;
  box-shadow: inset 0 0 0 1px rgba(43, 35, 29, .13);
}
/* У шторці заявки коло менше — там це просто позначка рядка. */
.m-cart-row .m-paint { width: 26px; height: 26px; }
.m-paint-big {
  width: 78px; height: 78px; border-radius: 999px; display: block;
  box-shadow: inset 0 0 0 1px rgba(43, 35, 29, .12);
}

.m-cbar-row {
  display: flex; align-items: center; gap: 10px;
  padding: 0 15px 13px;                 /* поля картки, бо рядок тепер її власний */
}
.m-cbar {
  flex: 1; min-width: 0; height: 5px; border-radius: 999px;
  background: var(--m-tint-2); overflow: hidden;
}
.m-cbar i { display: block; height: 100%; border-radius: 999px; }
.m-cqty { flex: 0 0 auto; font: 400 12px var(--font-sans); color: var(--m-soft); }

/* Кнопка заявки навпроти капсули стану. */
.m-buy {
  position: relative; width: 34px; height: 34px; flex: 0 0 auto; border: none;
  border-radius: 999px; background: var(--m-tint-2); color: var(--m-soft);
  display: grid; place-items: center; cursor: pointer;
  transition: transform .14s var(--m-pill), background .16s ease, color .16s ease;
}
.m-buy.press { transform: scale(.9); }
.m-buy.on { background: #EDE4D6; color: #8A6428; }
.m-buy-dot {
  position: absolute; right: -3px; top: -3px; width: 15px; height: 15px;
  border-radius: 999px; background: #8A6428; color: #FFF;
  display: grid; place-items: center;
  box-shadow: 0 0 0 2px var(--m-card);
}

/* Смуга заявки під списком складу. */
.m-cart-bar {
  margin: 14px 20px 0; padding: 13px 14px 13px 17px; border-radius: 17px;
  background: var(--m-card); box-shadow: var(--m-sh-card);
  display: flex; align-items: center; gap: 12px;
}
.m-cart-t { flex: 1; min-width: 0; font: 400 14px var(--font-sans); color: var(--m-ink); }
.m-cart-go {
  flex: 0 0 auto; height: 34px; padding: 0 15px; border: none; border-radius: 999px;
  background: var(--walnut); color: #F7F1EA; cursor: pointer;
  font: 400 12.5px var(--font-sans); white-space: nowrap;
}
.m-cart-bar.busy .m-cart-go { opacity: .6; }

/* Герой сторінки матеріалу. Фото немає й не буде, тож на його місці —
   великий значок на тому ж кольорі, що й капсула стану. Градієнт у
   .m-hero::after розчиняє низ у полотно, як і в замовленні. */
.m-mhero {
  display: grid; place-items: center;
  padding-bottom: 64px;                /* значок трохи вище центру: під ним лягає назва */
  background: var(--m-tint-2); color: var(--m-mute);
}
.m-mhero svg { opacity: .75; }

/* Капсула стану на сторінці: ліворуч назва рівня, праворуч сам залишок.
   Кнопки «Змінити» тут немає — склад у застосунку поки лише читають. */
.m-o-status.m-view { cursor: default; padding: 12px 18px; }
.m-o-st-q { flex: 0 0 auto; font: 400 14px var(--font-display); }

/* ─── Залишок ─── */
.m-mrow { display: flex; align-items: baseline; gap: 7px; margin-top: 2px; }
.m-mbig { font: 500 26px/1 var(--font-display); letter-spacing: -.02em; color: var(--m-ink); }
.m-munit { font: 400 14px var(--font-sans); color: var(--m-soft); }
.m-mmax { flex: 1; text-align: right; font: 400 13px var(--font-sans); color: var(--m-faint); }
.m-bar {
  height: 7px; border-radius: 999px; background: var(--m-tint-2);
  margin: 12px 0 9px; overflow: hidden;
}
.m-bar i { display: block; height: 100%; border-radius: 999px; }
.m-mfoot {
  display: flex; align-items: baseline; justify-content: space-between;
  font: 400 12px var(--font-sans); color: var(--m-faint);
}

/* ─── Рух ───
   Виписка, як у банку: кружечок зі стрілкою, за що і коли, кількість
   праворуч. Рядки одного дня стоять під спільним заголовком. Роздільних
   ліній між рядками немає — їх роль виконують самі проміжки. */
.m-block-mv { padding-bottom: 8px; }
/* По виписці ГОРТАЮТЬ, а не тиснуть: присідання на кожен дотик читалось
   як збій. Вага запису тут та сама, що в правила з #mApp вище (id + два
   класи), інакше воно б перемогло. */
#mApp .m-block-mv.press { transform: none; background: var(--m-card); }
.m-mv-day {
  font: 400 10.5px var(--font-sans); letter-spacing: .1em; text-transform: uppercase;
  color: var(--m-faint); padding: 14px 0 6px;
}
.m-mv-day:first-of-type { padding-top: 6px; }
/* Сума — на лінії заголовка, а не посередині рядка: інакше вона стоїть
   навпроти дати й імені, тобто навпроти найменш важливого. */
.m-mv { display: flex; align-items: flex-start; gap: 12px; padding: 7px 0; }
.m-mv-i {
  flex: 0 0 auto; width: 34px; height: 34px; border-radius: 999px;
  display: grid; place-items: center;
  align-self: center;            /* значок лишається по центру рядка */
}
.m-mv-i.up { background: #E8EFE7; color: #566A5B; }
.m-mv-i.down { background: #F6EDEC; color: #9C4B45; }
.m-mv-t { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.m-mv-t b {
  font: 400 14px var(--font-sans); color: var(--m-ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.m-mv-t i { font: 400 11.5px var(--font-sans); color: var(--m-faint); font-style: normal; }
.m-mv-d {
  flex: 0 0 auto; font: 400 14.5px/1.25 var(--font-display);
  font-variant-numeric: lining-nums tabular-nums; white-space: nowrap;
}
.m-mv-d em { font: 400 11px var(--font-sans); font-style: normal; color: var(--m-faint); margin-left: 3px; }
.m-mv-d.up { color: #566A5B; }
.m-mv-d.down { color: var(--m-ink); }
.m-mv-wait { font: 400 13px var(--font-sans); color: var(--m-faint); padding: 6px 0 2px; }


/* Підміна розділу: те, що на екрані, гасне за 130 мс, нове проявляється за
   190. Гасимо самі СПИСКИ, а не шар .m-under.

   Правило на #mUnder ламало паралакс: у шару вже є свій перехід (transform
   + opacity, --m-nav-dur), а запис по id переважував його й лишав самий
   opacity — тож при відкритті картки черга не від'їжджала, а стрибала. */
/* Базовий перехід у списків уже є вище (там, де гасіння при зміні
   капсули) — другий такий самий запис нижче за текстом просто переміг би
   його своєю тривалістю. Тут лишаємо ТІЛЬКИ згасання. */
#mUnder.m-swap #mQueue, #mUnder.m-swap #mMats,
#mUnder.m-swap #mExp, #mUnder.m-swap #mFin, #mUnder.m-swap #mStat { opacity: 0; transition-duration: .13s; }


/* Зміна розділу: смуга капсул іде вниз і зникає, нова приходить згори з
   легким перельотом. Рух короткий — він супроводжує підміну списку, а не
   змагається з нею. */
/* Рухаються САМІ капсули, а не смуга під ними.

   Поки гасла вся смуга, будь-яка її перемальовка посеред руху читалась як
   блимання: вміст мінявся, а прозорість у цей момент була десь між нулем
   і одиницею. Тепер кожна капсула має власний рух і власне затухання, а
   смуга просто стоїть. Заразом з'явився й розбіг — сусідні капсули
   рушають із невеликим зсувом, тож ряд «перетікає», а не клацає разом. */
/* Відхід — усією смугою разом, униз і в нуль.

   Розбіг тут був зайвий: перемальовка приходить раніше, ніж догуляє
   остання капсула, і хвіст ряду просто зникав на півдорозі. Тому на
   відході розбігу немає (див. нижче), а часу трохи більше — рух устигає
   скінчитись до підміни. */
#mFilters.chips-out .m-chip {
  opacity: 0; transform: translateY(10px);
  transition: opacity .16s ease, transform .16s cubic-bezier(.4, 0, .7, .2);
  transition-delay: 0s !important;
}
/* Поява — з тим самим затуханням, що й відскок капсули: кілька коливань,
   кожне вдвічі менше за попереднє. Крива між кадрами майже рівна — пружину
   несуть самі кадри, інакше вона додає власне прискорення. */
/* Прозорість — окремо від руху.

   Доти капсула ставала повністю видимою на вісімнадцятому відсотку — тобто
   за сто двадцять мілісекунд, і поява читалась як спалах, хоч сам рух і
   тривав далі. Тепер видимість доходить до одиниці аж під кінець
   коливань, тож капсула саме проявляється, а не вмикається. */
@keyframes m-chips-in {
  /* Рух — точно той, що був: −16 → +3.6 → −2.2 → +1.2 → −0.5 → 0.
     Змінена ЛИШЕ прозорість: вона доходить до одиниці на десятому
     відсотку замість вісімнадцятого. Жодного кадру руху не додано й не
     зсунуто — на десятому відсотку положення просто не оголошене, тож
     воно інтерполюється між нулем і вісімнадцятим, як і раніше. */
  0%   { opacity: 0; transform: translateY(-16px); }
  /* Раніше видимість доходила до одиниці на десятому відсотку — за 66 мс.
     Формально це проявлення, а на око — вмикання: капсула виникала й уже
     потім доїжджала. Тепер прозорість наростає до третини руху, і поява
     читається саме як поява. */
  35%  { opacity: 1; }
  18%  { transform: translateY(3.6px); }
  40%  { transform: translateY(-2.2px); }
  62%  { transform: translateY(1.2px); }
  82%  { transform: translateY(-.5px); }
  100% { opacity: 1; transform: translateY(0); }
}
#mFilters.chips-in .m-chip {
  animation: m-chips-in .66s cubic-bezier(.42, .5, .45, 1) both;
  /* Обрана капсула має з'явитись ОДРАЗУ чорною.

     Колір у капсули переходить за 0.26s — і на появі це читалось як
     блимання: спершу біла капсула виїжджала, а вже потім наливалась
     чорним. Поки йде поява, переходів немає взагалі: стан капсули не
     міняється, він просто вже такий. */
  transition: none;
}
/* Розбіг: 34 мс на капсулу. Більше — і ряд помітно «сиплеться», менше —
   і зсуву не видно взагалі. Той самий крок і на вихід, і на появу. */
#mFilters.chips-in .m-chip:nth-child(2) { animation-delay: .034s; }
#mFilters.chips-in .m-chip:nth-child(3) { animation-delay: .068s; }
#mFilters.chips-in .m-chip:nth-child(4) { animation-delay: .102s; }
#mFilters.chips-in .m-chip:nth-child(5) { animation-delay: .136s; }
#mFilters.chips-in .m-chip:nth-child(6) { animation-delay: .17s; }
#mFilters.chips-in .m-chip:nth-child(7) { animation-delay: .2s; }
#mFilters.chips-in .m-chip:nth-child(n+8) { animation-delay: .23s; }


/* ─── Заявка на закупку ─── */
.m-cart-row {
  display: flex; align-items: center; gap: 12px;
  padding: 11px 0; border-bottom: 1px solid var(--m-line);
}
.m-cart-row:last-of-type { border-bottom: none; }
.m-cart-dot { flex: 0 0 auto; width: 26px; height: 26px; border-radius: 999px; }
.m-cart-dot-e { background: var(--m-tint-2); }
.m-cart-n { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.m-cart-n b {
  font: 400 14.5px var(--font-sans); color: var(--m-ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.m-cart-n i { font: 400 11.5px var(--font-sans); color: var(--m-faint); font-style: normal; }
.m-cart-q { flex: 0 0 auto; font: 400 13px var(--font-sans); color: var(--m-soft); }
.m-cart-x {
  flex: 0 0 auto; width: 28px; height: 28px; border: none; border-radius: 999px;
  background: var(--m-tint-2); color: var(--m-mute);
  display: grid; place-items: center; cursor: pointer;
}
.m-cart-sum {
  display: flex; align-items: baseline; justify-content: space-between;
  margin-top: 14px; padding-top: 13px; border-top: 1px solid var(--m-line);
  font: 400 14px var(--font-sans); color: var(--m-soft);
}
.m-cart-sum .num { font: 500 18px var(--font-display); letter-spacing: -.01em; color: var(--m-ink); }
.m-cart-empty { font: 400 13.5px/1.5 var(--font-sans); color: var(--m-faint); padding: 4px 0 8px; }


/* ─── Правка меж запасу просто в блоці ───
   Розкриття роблять сіткою: у height анімація потребує точного числа, а
   тут воно залежить від вмісту. 1fr → 0fr працює з будь-якою висотою й
   не смикається, коли поле раптом переносить рядок. */
.m-lim { cursor: pointer; }
.m-lim-chev { display: grid; place-items: center; color: var(--m-faint); }
.m-lim-chev svg { transition: transform .28s var(--m-ease-soft); }
.m-lim.open .m-lim-chev svg { transform: rotate(180deg); }
/* Розкриття веде ВИСОТА, і ставить її скрипт із реального вмісту.

   Раніше тут була сітка (0fr → 1fr) — запис короткий, але його анімують
   не всі версії Safari, а на телефоні саме вона. Тепер висота: працює
   скрізь, і рух видно навіть там, де сітка просто клацала. */
.m-lim-wrap {
  height: 0; overflow: hidden;
  transition: height .34s var(--m-ease-soft), opacity .24s ease;
  opacity: 0;
}
.m-lim.open .m-lim-wrap { opacity: 1; }
/* Відступ згори живе в обгортці, а НЕ полем margin у вмісті.

   Зовнішній відступ дитини не входить у offsetHeight батька (він
   «схлопується» назовні) — саме через це висота, порахована скриптом,
   виходила на дванадцять пікселів меншою: блок не доїжджав, а тоді
   стрибком ставав на місце. */
.m-lim-wrap > div { padding-top: 12px; }
.m-lim-in {
  display: flex; flex-direction: column; gap: 9px;
  padding-top: 14px; border-top: 1px solid var(--m-line);
}
.m-lim-row { display: flex; align-items: center; gap: 12px; }
.m-lim-row > span { flex: 1; min-width: 0; font: 400 13.5px var(--font-sans); color: var(--m-soft); }
/* Одиниця живе ВСЕРЕДИНІ поля, а не окремою колонкою праворуч.

   Окремою колонкою вона тримала фіксовану ширину під найдовше слово — і
   в рядках із коротким («шт») праворуч зяяла порожнеча, та ще й поле не
   доходило до краю блока. Тепер поле впирається в край, а підпис одиниці
   стоїть у ньому ж, приглушений. */
.m-lim-f { flex: 0 0 auto; position: relative; width: 136px; }
.m-lim-f input {
  width: 100%; height: 42px; box-sizing: border-box;
  text-align: right; padding: 0 52px 0 14px;
  border-radius: 13px; border: none; background: var(--m-tint-2);
  font: 400 15px var(--font-sans); color: var(--m-ink);
}
.m-lim-f input:focus { outline: none; background: #F1E9DE; }
.m-lim-f i {
  position: absolute; right: 14px; top: 50%; transform: translateY(-50%);
  font: 400 12.5px var(--font-sans); font-style: normal; color: var(--m-faint);
  pointer-events: none;
}


/* ─── Кнопка «Фільтри» в смузі ─── */
.m-chip-ico { gap: 7px; padding-left: 13px; }
.m-chip-ico svg { color: var(--m-mute); }
.m-chip-ico.on svg, .m-chip.on .m-chip-ico svg { color: inherit; }

/* ─── Список статусів у шторці ─── */
.m-frow {
  width: 100%; border: none; background: none; cursor: pointer;
  display: flex; align-items: center; gap: 12px;
  padding: 13px 2px; border-bottom: 1px solid var(--m-line);
}
.m-frow:last-child { border-bottom: none; }
.m-frow i { width: 8px; height: 8px; border-radius: 999px; flex: 0 0 auto; }
.m-frow-e { background: var(--m-line); }
.m-frow span { flex: 1; min-width: 0; text-align: left; font: 400 15px var(--font-sans); color: var(--m-ink); }
.m-frow b { font: 400 13px var(--font-sans); color: var(--m-faint); }
.m-frow.on span { font-weight: 500; }
.m-frow.on b { color: var(--m-soft); }
.m-frow.press { background: #FBF8F4; }


/* ─── Фільтри у шторці ─── */
.m-fgrp + .m-fgrp { margin-top: 20px; }
.m-fgrp-t {
  font: 400 10.5px var(--font-sans); letter-spacing: .1em; text-transform: uppercase;
  color: var(--m-faint); margin-bottom: 9px;
}
.m-fchips { display: flex; flex-wrap: wrap; gap: 7px; }
.m-fchip {
  height: 36px; padding: 0 14px; border-radius: 999px; border: none; cursor: pointer;
  background: var(--m-tint-2); color: var(--m-soft);
  display: inline-flex; align-items: center; gap: 7px;
  font: 400 13px var(--font-sans); white-space: nowrap;
  transition: background .2s var(--m-ease-soft), color .2s var(--m-ease-soft),
              transform .18s var(--m-pill);
}
.m-fchip i { width: 11px; height: 11px; border-radius: 999px; box-shadow: inset 0 0 0 1px rgba(43,35,29,.14); }
.m-fchip.on { background: var(--m-ink); color: #F7F1EA; }
.m-fchip.press { transform: scale(.95); }
/* Підошва шторки: скинути й застосувати. */
.m-fbar { display: flex; gap: 9px; }
.m-fclear { flex: 0 0 auto; background: var(--m-tint-2); color: var(--m-soft); }


/* ─── Картка складу: стан угорі, постачальник і ціна внизу ─── */
/* Капсула стану в рядку підпису — дрібніша за ту, що була в підошві:
   там вона була головним елементом рядка, тут ділить місце з типом. */
.m-mst {
  flex: 0 0 auto; height: 24px; padding: 0 10px; border-radius: 999px;
  display: inline-flex; align-items: center; gap: 6px;
  font: 400 11.5px var(--font-sans); white-space: nowrap;
}
.m-mst i { width: 5px; height: 5px; border-radius: 999px; }
/* Постачальник займає весь вільний рядок підошви, ціна тримається праворуч
   біля кнопки заявки. */
.m-msup {
  flex: 1; min-width: 0; font: 400 12.5px var(--font-sans); color: var(--m-soft);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.m-mprice {
  /* Ближче до кошика: ціна й кнопка — одна дія («скільки коштує» —
     «поклади»), і розводити їх на пів картки нема за чим. */
  flex: 0 0 auto; margin-right: 2px;
  font: 400 14px var(--font-display); color: var(--m-ink); white-space: nowrap;
}


/* ─── Кнопка «Застосувати» ───
   Поки нічого не обрано, кнопки немає зовсім — не сіра й не заблокована,
   а саме немає: тиснути нема на що. Коли з'явилось перше обране, вона
   виростає, а не клацає. */
/* З'являється й зникає ОДНИМ рухом: масштаб і прозорість одного часу.

   Доти прозорість гасла швидше за масштаб, а підошва шторки ще й
   схлопувала поля — і кнопка зникала стрибком разом із висотою шторки.
   Поля лишаються на місці: висота шторки від кнопки не залежить. */
#mSheet .m-fapply {
  width: 100%;
  transform: scale(.92); opacity: 0; pointer-events: none;
  transition: transform .3s var(--m-pill), opacity .3s var(--m-ease-soft);
}
#mSheet .m-fapply.on { transform: none; opacity: 1; pointer-events: auto; }

/* ─── Скільки знайшлось ───
   Рядок над списком: він з'являється лише під час пошуку, тож нехай і
   виглядає як частина пошуку, а не як ще один заголовок черги. */
.m-found {
  margin: 0 20px 12px; padding: 12px 15px; border-radius: 15px;
  background: rgba(43, 35, 29, .05);
  display: flex; align-items: baseline; gap: 10px;
}
.m-found b { font: 500 15px var(--font-display); color: var(--m-ink); letter-spacing: -.01em; }
.m-found span {
  flex: 1; min-width: 0; font: 400 12px var(--font-sans); color: var(--m-soft);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* ─── Календар свого періоду ─── */
.m-cal { margin-top: 12px; background: var(--m-tint-2); border-radius: 17px; padding: 12px 12px 10px; }
.m-cal-h { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }
.m-cal-h span { font: 400 14px var(--font-sans); color: var(--m-ink); }
.m-cal-nav {
  width: 32px; height: 32px; border: none; border-radius: 999px; cursor: pointer;
  background: rgba(255, 255, 255, .7); color: var(--m-soft);
  display: grid; place-items: center;
}
.m-cal-nav svg { width: 14px; height: 14px; }
.m-cal-w, .m-cal-g { display: grid; grid-template-columns: repeat(7, 1fr); gap: 3px; }
.m-cal-w span {
  text-align: center; font: 400 10.5px var(--font-sans); color: var(--m-faint);
  padding-bottom: 4px;
}
/* День — коло. Квадрати в календарі виглядають як таблиця, а тут
   вибирають дати, а не клітинки. Проміжок між краями показуємо тонкою
   смугою ПІД кружками, тож самі дні лишаються круглими. */
.m-cal-d {
  position: relative; height: 40px; border: none; border-radius: 999px;
  cursor: pointer; background: none; color: var(--m-ink);
  font: 400 13.5px var(--font-sans);
  transition: background .16s ease, color .16s ease;
}
.m-cal-e { display: block; }
/* Проміжні дні — теж кружечками, а не суцільною смугою: у календарі
   вибирають дати, і все, що позначено, має бути однієї форми. */
.m-cal-d.mid { background: rgba(43, 35, 29, .07); }
.m-cal-d.on { background: var(--m-ink); color: #F7F1EA; }
.m-cal-d.press { background: rgba(43, 35, 29, .12); }
.m-cal-g { position: relative; z-index: 0; }

/* Поява календаря — анімацією на самому вузлі.

   Переходом висоти керував скрипт, і будь-яка зайва перемальовка шторки
   лишала календар згорнутим — тобто невидимим. Анімація ж грає рівно
   тоді, коли вузол з'явився, і нічим більше не керується. Верхня межа
   max-height узята із запасом: календар найвищого місяця — близько 240px. */
/* Поява календаря — БЕЗ анімації висоти.

   І перехід height, і кадри max-height роблять те саме: певний час вузол
   має нульову висоту. Досить будь-чому в цей момент зміряти або обрізати
   контейнер — і календар лишається невидимим назавжди. Тому висота від
   першого кадру справжня, а рухаються лише прозорість і зсув: зіпсувати
   розкладку вони не можуть у принципі. */
.m-calwrap { animation: m-cal-in .3s var(--m-ease-soft) both; }
@keyframes m-cal-in {
  0%   { opacity: 0; transform: translateY(-8px); }
  100% { opacity: 1; transform: none; }
}
.m-cal-f {
  margin-top: 9px; text-align: center;
  font: 400 12.5px var(--font-sans); color: var(--m-soft);
  font-variant-numeric: lining-nums tabular-nums;
}


/* Четвертий стан кнопки дока: увімкнений фільтр. */
.searchbtn .ic-clear { opacity: 0; transform: scale(.5) rotate(-45deg); }
#mTabs.clearing .searchbtn .ic-find,
#mTabs.clearing .searchbtn .ic-shop { opacity: 0; transform: scale(.5) rotate(45deg); }
#mTabs.clearing .searchbtn .ic-clear { opacity: 1; transform: none; }

.m-cal-err { padding: 14px; font: 400 12.5px var(--font-sans); color: #9C4B45; }

.m-fdiag {
  margin: 8px 0 0; font: 400 11px var(--font-sans); color: var(--m-faint);
}


/* ─── Попап календаря ───
   Лежить у шторці, тому й закривається разом із нею. Тло приглушує все
   позаду, картка виростає з дев'яноста відсотків — той самий рух, що й у
   решти вікон застосунку. */
.m-calpop {
  position: absolute; inset: 0; z-index: 5;
  background: rgba(43, 35, 29, .28);
  display: grid; place-items: center; padding: 18px;
  animation: m-calpop-bg .2s ease both;
  -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px);
}
@keyframes m-calpop-bg { from { opacity: 0; } to { opacity: 1; } }
.m-calpop-c {
  width: 100%; max-width: 340px; background: var(--m-card);
  border-radius: 22px; padding: 14px;
  box-shadow: 0 26px 60px -24px rgba(43, 35, 29, .5);
  animation: m-calpop-in .3s var(--m-pill) both;
}
@keyframes m-calpop-in {
  from { opacity: 0; transform: scale(.92); }
  to   { opacity: 1; transform: none; }
}
.m-calpop .m-cal { margin-top: 0; }

/* Прибуток, який ще чекає на собівартість. */
.m-sum-wait { color: var(--m-faint); letter-spacing: .06em; }

/* Підпис під собівартістю: курс і день розрахунку. */
.m-rc-note {
  padding: 6px 0 2px; font: 400 11px/1.4 var(--font-sans); color: var(--m-faint);
}

/* Поки їде доводка після свайпу, картки не мають ще й проявлятись:
   дві анімації в одному кадрі — це і є те «стробування». */
#mApp.m-anim .m-card.m-appear { animation: none; }

/* Нова транзакція проступає зверху, а не виникає разом з усіма: так видно,
   що саме щойно сталось, і список не блимає цілком. */
.m-mv-new { animation: m-mv-in .36s cubic-bezier(.2,.7,.2,1) both; }
@keyframes m-mv-in {
  from { opacity: 0; transform: translateY(-9px); }
  to   { opacity: 1; transform: none; }
}

/* Полоса запасу переїжджає, а не перескакує: зміну видно як рух. */
.m-bar i { transition: width .4s cubic-bezier(.32,.72,0,1), background .3s ease; }
/* Знята транзакція гасне й іде вгору — так само, як у вебі. */
.m-mv-out { animation: m-mv-out .26s cubic-bezier(.4,0,.7,.2) both; pointer-events: none; }
@keyframes m-mv-out {
  from { opacity: 1; transform: none; }
  to   { opacity: 0; transform: translateY(-10px); }
}

/* Порожнє місце знизу, яке дає короткій сторінці той самий запас ходу для
   паралакса, що й довгій. Висоту ставить скрипт, тут — лише поведінка. */
.m-hero-space { flex: 0 0 auto; pointer-events: none; }

/* ─────────── Історія руху: цикли ───────────

   У картці матеріалу — по рядку-кнопці на цикл. Сам цикл живе на власній
   сторінці: період із чотирма числами не поміщається в смужку. */
.m-cycb {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 12px 14px; margin-bottom: 8px;
  background: var(--m-card); border: 1px solid var(--m-line); border-radius: 16px;
  text-align: left; cursor: pointer; -webkit-tap-highlight-color: transparent;
  transition: transform .18s var(--m-ease-soft), background .18s ease;
}
.m-cycb:active { transform: scale(.985); background: var(--m-tint); }
.m-cycb:last-child { margin-bottom: 0; }
.m-cycb-l { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.m-cycb-t {
  font: 500 14px var(--font-sans); color: var(--m-ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.m-cycb-s {
  font: 400 12px var(--font-sans); color: var(--m-faint);
  font-variant-numeric: lining-nums tabular-nums;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.m-cycb-r {
  flex: 0 0 auto; display: flex; flex-direction: column;
  align-items: flex-end; gap: 3px;
}
.m-cycb-buy {
  font: 400 13.5px var(--font-display); color: #566A5B;
  font-variant-numeric: lining-nums tabular-nums;
}
.m-cycb-chev { flex: 0 0 auto; display: grid; place-items: center; color: var(--m-faint); }

/* Числа циклу. Колір тут — сенс, а не оздоба: червоне означає, що зі
   складу зникло більше, ніж рахував розкрій. */
.m-cyc-buy em, .m-cyc-diff em, .m-cp-h b em, .m-cp-row b em,
.m-cycb-buy em, .m-cycb-r em, .m-rc-row b em, .m-profit-n em {
  font: 400 10.5px var(--font-sans); font-style: normal;
  color: var(--m-faint); margin-left: 2px;
}
.m-cyc-diff { font: 400 12px var(--font-sans); color: var(--m-soft);
  font-variant-numeric: lining-nums tabular-nums; }
.m-cyc-diff.minus { color: #9C4B45; }   /* пішло більше, ніж рахували */
.m-cyc-diff.plus { color: #566A5B; }    /* рахунок був із запасом */
.m-cyc-blind { font: 400 12px var(--font-sans); color: #9A7B4F; }

/* Картка циклу — та сама плитка, що картка прибутку в замовленні:
   заголовок, велике число, смуга часток, легенда. Натискати її нема
   куди: усе, що вона каже, вже видно. */
.m-cyc-kpi { cursor: default; }
/* Коли відповідь — слова («Усе зійшлось»), вони не мають кричати
   розміром числа. */
.m-cyc-kpi .m-profit-n:not(.num) { font-size: 21px; }
.m-cyc-kpi .m-profit-n em {
  font: 400 13px var(--font-sans); font-style: normal;
  color: var(--m-soft); margin-left: 4px;
}
/* Відрізок звірки — окремий блок: видно, які замовлення в нього
   потрапили і чим він закінчився. */
.m-seg-h { display: flex; align-items: baseline; gap: 10px; }
.m-seg-t {
  flex: 1; min-width: 0; font: 500 14.5px var(--font-display);
  letter-spacing: -.005em; color: var(--m-ink);
}
.m-seg-ok { flex: 0 0 auto; font: 400 12px var(--font-sans); color: #566A5B; }
.m-seg-gap {
  flex: 0 0 auto; font: 400 12px var(--font-sans); color: #9C4B45;
  font-variant-numeric: lining-nums tabular-nums;
}
.m-seg-gap.plus { color: #566A5B; }
.m-seg-gap em, .m-legend b em {
  font: 400 10.5px var(--font-sans); font-style: normal;
  color: var(--m-faint); margin-left: 2px;
}
.m-seg-s {
  margin: 5px 0 2px; font: 400 12px var(--font-sans); color: var(--m-faint);
  font-variant-numeric: lining-nums tabular-nums;
}
/* У легенді картки стоять кількості, а не відсотки. */
.m-legend b {
  font: 400 11.5px var(--font-sans); color: var(--m-ink);
  font-variant-numeric: lining-nums tabular-nums;
}

/* Сторінка циклу лежить поверх картки матеріалу. Героя тут немає, тож
   місце під круглу кнопку «назад» лишає сам відступ. */
.m-cycle { z-index: 32; }
.m-cycle .m-order-body { padding-top: calc(74px + env(safe-area-inset-top)); }

.m-cp-wrap {
  height: 0; overflow: hidden; opacity: 0;
  transition: height .34s var(--m-ease-soft), opacity .24s ease;
}
.m-cp.open > .m-cp-wrap { opacity: 1; }
.m-cp-wrap > div { padding: 2px 0 6px 2px; }
.m-cp.open .m-cp-chev { transform: rotate(180deg); }

/* Товар усередині циклу. */
.m-cp { border-top: 1px solid var(--m-line); }
.m-cp:first-child { border-top: 0; }
.m-cp-h {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 10px 0; background: none; border: 0; cursor: pointer; text-align: left;
  -webkit-tap-highlight-color: transparent;
}
.m-cp-n { flex: 1; min-width: 0; font: 400 13.5px var(--font-sans); color: var(--m-ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.m-cp-h i {
  flex: 0 0 auto; font: 400 11.5px var(--font-sans); font-style: normal;
  color: var(--m-faint); background: var(--m-tint);
  padding: 1px 7px; border-radius: 999px;
}
.m-cp-h b {
  flex: 0 0 auto; font: 400 13.5px var(--font-display); color: #8A6252;
  font-variant-numeric: lining-nums tabular-nums;
}
.m-cp-chev { flex: 0 0 auto; display: grid; place-items: center; color: var(--m-faint);
  transition: transform .3s var(--m-ease-soft); }
.m-cp-row {
  display: flex; align-items: center; gap: 10px; padding: 6px 0 6px 10px;
  font: 400 13px var(--font-sans); color: var(--m-soft);
}
.m-cp-row span { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.m-cp-row span i {
  font-style: normal; color: var(--m-faint); margin-left: 7px;
  font-size: 11.5px;
}
.m-cp-row b { flex: 0 0 auto; font: 400 13px var(--font-display); color: var(--m-soft); }

/* Звірка — не папка, а засічка: вона ділить цикл на відрізки. */
.m-cyc-empty { font: 400 13px var(--font-sans); color: var(--m-faint); padding: 4px 0 8px; }

@media (prefers-reduced-motion: reduce) {
  .m-cp-wrap, .m-cp-chev, .m-cycb { transition: none; }
}

/* ─────────── Заявка на закупку ─────────── */
.m-cartbar {
  position: absolute; left: 14px; right: 14px; z-index: 29;
  /* Над капсулами статусів, а не під ними: інакше довелось би рухати їх
     щоразу, коли смуга приходить, іде або розкривається. */
  bottom: calc(var(--m-tabh) + 12px + var(--m-chips-h, 0px));
  padding: 10px 12px 10px 14px; border-radius: 999px;
  background: var(--m-ink); color: #F7F1EA;
  box-shadow: 0 18px 40px -18px rgba(43, 35, 29, .8);
  transform: translateY(16px) scale(.97); opacity: 0; pointer-events: none;
  transition: transform .4s cubic-bezier(.22, 1, .36, 1), opacity .24s ease,
              bottom .26s var(--m-ease-soft);
}
.m-cartbar.on { transform: none; opacity: 1; pointer-events: auto; }
.m-cartbar.hidden { opacity: 0; transform: translateY(16px) scale(.97); pointer-events: none; }
.m-cartbar:empty { display: none; }

.m-cbhead { display: flex; align-items: center; gap: 10px; }
.m-cbtoggle {
  flex: 1; min-width: 0; display: flex; align-items: center; gap: 10px;
  background: none; border: 0; padding: 0; text-align: left; cursor: pointer;
  -webkit-tap-highlight-color: transparent; color: inherit;
}
.m-cbico { flex: 0 0 auto; display: grid; place-items: center; opacity: .65; }
.m-cbtx { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.m-cbtx b { font: 500 13px var(--font-sans); color: #F7F1EA; white-space: nowrap; }
.m-cbtx i {
  font: 400 11.5px var(--font-sans); font-style: normal; color: #B9A78F;
  white-space: nowrap; font-variant-numeric: lining-nums tabular-nums;
}
.m-cbchev {
  flex: 0 0 auto; display: grid; place-items: center; color: #B9A78F;
  transition: transform .3s var(--m-ease-soft);
}
.m-cbchev.up { transform: rotate(180deg); }
.m-cbclear {
  flex: 0 0 auto; width: 32px; height: 32px; border: 0; padding: 0; border-radius: 999px;
  background: rgba(247, 241, 234, .13); color: #E8DCCB;
  display: grid; place-items: center; cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.m-cbgo {
  flex: 0 0 auto; height: 32px; padding: 0 15px; border: 0; border-radius: 999px;
  background: #F7F1EA; color: var(--m-ink); cursor: pointer;
  display: inline-flex; align-items: center; gap: 6px;
  font: 500 12.5px var(--font-sans); white-space: nowrap;
  transition: transform .12s ease, opacity .16s ease, background .2s ease, color .2s ease;
}
.m-cbgo:active { transform: scale(.97); }
.m-cbgo[disabled] { opacity: .55; }
/* Заявку створено: кнопка каже це сама — зеленим, і не блякне. */
.m-cbgo.ok { background: #CFE3CC; color: #3F6247; }
.m-cbgo.ok[disabled] { opacity: 1; }
.m-cbgo.ok svg { width: 12px; height: 12px; }

/* Список позицій розкривається сіткою — так само, як чек у замовленні. */
.m-cartlist {
  display: grid; grid-template-rows: 0fr; opacity: 0;
  transition: grid-template-rows .38s var(--m-ease-soft), opacity .24s ease;
}
.m-cartlist.on { grid-template-rows: 1fr; opacity: 1; }
.m-cartlist > div { overflow: hidden; min-height: 0; }
.m-cartlist-in { padding: 2px 2px 10px; max-height: 46vh; overflow-y: auto; }
.m-cbrow {
  display: flex; align-items: center; gap: 8px; padding: 9px 0;
  border-bottom: 1px solid rgba(247, 241, 234, .09);
}
.m-cbrow:last-child { border-bottom: 0; }
.m-cbdot {
  flex: 0 0 auto; width: 9px; height: 9px; border-radius: 999px;
  box-shadow: inset 0 0 0 1px rgba(247, 241, 234, .18);
}
.m-cbdot-e { background: rgba(247, 241, 234, .22); }
.m-cbn { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.m-cbn b {
  font: 400 12.5px var(--font-sans); color: #F7F1EA;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.m-cbn i {
  font: 400 10.5px var(--font-sans); font-style: normal; color: #8C7C6D;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Два числа закупу: скільки беремо й скільки платимо. Поля навмисно
   вузькі — це не форма, а правка на ходу. */
.m-cbf { flex: 0 0 auto; display: flex; align-items: baseline; gap: 3px; }
.m-cbin {
  width: 52px; height: 30px; box-sizing: border-box; padding: 0 7px;
  border: 1px solid rgba(247, 241, 234, .16); border-radius: 9px;
  background: rgba(247, 241, 234, .06); color: #F7F1EA;
  font: 400 12.5px var(--font-sans); text-align: right; outline: none;
  font-variant-numeric: lining-nums tabular-nums;
  transition: border-color .16s ease, background .16s ease;
}
.m-cbin:focus { border-color: rgba(247, 241, 234, .42); background: rgba(247, 241, 234, .1); }
/* У спокої на місці поля стоїть кнопка: виглядає так само, але фокус на
   ній ставимо ми, а не система (і тому нічого не підкручується). */
.m-cbin-b {
  display: flex; align-items: center; justify-content: flex-end;
  cursor: pointer; -webkit-tap-highlight-color: transparent;
}
.m-cbin-b:active { background: rgba(247, 241, 234, .12); }
.m-cbf em { font-style: normal; font: 400 10.5px var(--font-sans); color: #8C7C6D; }
.m-cbx {
  flex: 0 0 auto; width: 24px; height: 24px; border: 0; padding: 0; border-radius: 999px;
  background: rgba(247, 241, 234, .08); color: #B9A78F;
  display: grid; place-items: center; cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

/* Статуси стоять НАД смугою: піднімаємо їх рівно на її висоту. */
/* Розкрита смуга — вже не капсула, а список: краї стають плиткою. */
.m-cartbar.open { border-radius: 26px; }

/* Поки в полі стоїть курсор, смуга не «піднімається на висоту
   клавіатури» — вона СТАЄ на неї: низ прив'язується до верхнього краю
   клавіатури з невеликим просвітом.

   Різниця важлива. Смуга й так стоїть над капсулами статусів, тобто вже
   на сотню з гаком пікселів вище дна; додавши до цього повну висоту
   клавіатури, ми відправляли її кудись під шапку. Тепер положення
   рахується від самої клавіатури, і смуга сідає рівно над нею.

   У --m-kb уже закладено запас 30px (див. bindViewport), тож віднімаємо
   зайве — лишається просвіт близько десяти пікселів. */
#mApp.m-cart-kb .m-cartbar.on {
  /* Плюс 15% висоти клавіатури: над самим її краєм смуга сиділа надто
     низько — око читає її як частину клавіатури, а не як окрему річ. */
  bottom: calc(var(--m-kb, 0px) * 1.15 - 20px);
  transform: none;
}
/* Капсули статусів під клавіатурою все одно не видно — прибираємо їх,
   щоб не мигали з-під смуги, поки та їде. */
#mApp.m-cart-kb .m-filters { opacity: 0; pointer-events: none; }
/* І список усередині тримаємо нижчим: піднята смуга з повним списком
   вилізла б за верхній край. */
#mApp.m-cart-kb .m-cartlist-in { max-height: 30vh; }
/* Хвіст списку не має ховатись під смугою. */
#mApp.m-has-cart #mMats { padding-bottom: calc(var(--m-tabh) + 58px + var(--m-cart-h, 0px) + 12px); }

@media (prefers-reduced-motion: reduce) {
  .m-cartbar, .m-cartlist, .m-cbchev { transition: none; }
}

/* ─────────── Прострочене замовлення ───────────

   Те саме правило, що й у таблиці, і той самий значок. Картка обрізає
   вміст по своїх краях, тож кружечок стоїть не НА куті, а В куті —
   поверх макета, за той самий погляд. */
.m-card { position: relative; }
.m-card .fire-badge {
  position: absolute; left: 7px; top: 7px; z-index: 3;
  width: 23px; height: 23px; border-radius: 999px;
  background: #C0483F; box-shadow: 0 3px 9px -2px rgba(157, 60, 52, .75);
  display: grid; place-items: center;
}
.m-card .fire-badge i {
  display: block; width: 18px; height: 18px; background: #FFF;
  -webkit-mask-image: url(fire-sprite.png); mask-image: url(fire-sprite.png);
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-size: 540px 18px; mask-size: 540px 18px;   /* 30 кадрів × 18px */
  /* Вогонь горить угору, тож і в кружечку стоїть трохи вище центру:
     інакше здається, що він з нього випадає. */
  transform: translateY(-1px);
  animation: m-fire-run .8s steps(30) infinite;
}
@keyframes m-fire-run {
  to { -webkit-mask-position: -540px 0; mask-position: -540px 0; }
}
@media (prefers-reduced-motion: reduce) {
  .m-card .fire-badge i { animation: none; }
}

/* Ціна, що випливає із закупу: 20 м² за 10 000 ₴ — це 500 ₴/м². Рядок
   з'являється лише тоді, коли ця ціна інша, ніж на складі. */
/* Підпис про нову ціну. Кнопки немає — склад підхоплює ціну сам, тож
   це просто підтвердження того, що щойно вписали. Зникає, щойно ціна
   стане тією самою. */
.m-cbfix {
  display: block; padding: 0 0 9px 19px; margin-top: -5px;
}
.m-cbfix[hidden] { display: none; }
.m-cbfix-t {
  display: block; font: 400 11.5px var(--font-sans); color: #D8B45F;
  font-variant-numeric: lining-nums tabular-nums;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* ═══════════ ВИТРАТИ (мобільний застосунок) ═══════════ */
/* Кнопка дока у витратах — плюс замість лупи. */
#mApp.m-exp ~ #mTabs .searchbtn .ic-find { opacity: 0; transform: scale(.5) rotate(45deg); }
#mApp.m-exp ~ #mTabs .searchbtn .ic-eplus { opacity: 1; transform: none; }
/* У фінансах кнопка дока — статистика; плюс стоїть окремо над капсулами. */
#mApp.m-fin ~ #mTabs .searchbtn .ic-find { opacity: 0; transform: scale(.5) rotate(45deg); }
#mApp.m-fin ~ #mTabs .searchbtn .ic-stat { opacity: 1; transform: none; }
/* Плюс фінансів: та сама кнопка, що й FAB, лише над смугою капсул і лише
   в розділі фінансів. У глибині (сторінка, шторка) ховається разом із доком. */
.m-ffab {
  bottom: calc(var(--m-tabh) + 92px);
  opacity: 0; transform: scale(.55); pointer-events: none;
  transition: opacity .28s ease, transform .5s var(--m-pill);
}
/* З'являється разом із розділом (той самий такт, що й проявлення списку)
   і трохи «виростає». */
#mApp.m-fin:not(.m-deep) .m-ffab { opacity: 1; transform: none; pointer-events: auto; transition-delay: .13s; }
#mApp.m-fin.m-deep .m-ffab { transform: translate3d(-24%, 0, 0) scale(.9); opacity: .28; pointer-events: none; }
.m-ffab svg { width: 22px; height: 22px; }

/* ─── Фінанси: картка балансу + стрічка транзакцій ─── */
.m-fdot { width: 8px; height: 8px; border-radius: 999px; flex: 0 0 auto; display: inline-block; }

/* Цех: замість капсул із грошима — тиха назва ролі; док ВУЖЧИЙ, бо
   вкладок на одну менше і поля розповзались. */
/* Той самий вигляд, що плашки з сумами в інших ролей. */
.m-bal-prod {
  justify-content: center;
  font: 500 13px var(--font-sans); letter-spacing: .05em; color: var(--m-soft);
}
#mApp.m-prod ~ #mTabs { --m-dock-side: 42px; }

/* Обрано конкретний рахунок: одна тепла картка гаманця замість стрічки. */
.m-fshop { cursor: default; width: auto; margin: 14px 20px 6px; }
.m-fshop-n { font: 400 12px var(--font-sans); color: var(--m-soft); margin: 7px 0 3px; }

/* Перемикач типу транзакції — як на столі: зелена гілка надходження,
   теракотова — витрата. */
.m-ftgl { display: flex; gap: 8px; }
.m-ftgl-b {
  flex: 1; height: 46px; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  border: 1px solid #E7DAC9; border-radius: 14px;
  background: #FFFDFA; color: #6B5C50; font: 400 13.5px var(--font-sans);
  transition: background .18s ease, color .18s ease, border-color .18s ease, transform .18s var(--m-pill);
}
.m-ftgl-b.on.tin { background: #E4EFE2; border-color: #CFE2CC; color: #3A5C41; font-weight: 500; }
.m-ftgl-b.on.tout { background: #F5E4DA; border-color: #E8CDBB; color: #8A5735; font-weight: 500; }
.m-ftgl-b.bump { animation: m-chip-bump .62s cubic-bezier(.42, .5, .45, 1) both; }

/* Рахунки — ОДНА горизонтальна стрічка карток: перше — тепле зведення,
   далі магазини. Гортається пальцем, скролбара не видно. */
/* Плашка синхронізації ПІД картками балансів: тихий підпис «коли перевіряли»
   і кнопка «Оновити», уся — капсулою. Доки Make читає пошту — значок крутиться. */
.m-fsync {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  margin: 4px 20px 6px; padding: 6px 6px 6px 16px; min-width: 0;
  background: var(--m-card); border-radius: 999px; box-shadow: var(--m-sh-card);
}
.m-fsync-t {
  font: 400 12px var(--font-sans); color: var(--m-soft);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.m-fsync-b {
  flex: 0 0 auto; height: 32px; padding: 0 13px 0 11px; border: none; cursor: pointer;
  display: inline-flex; align-items: center; gap: 6px; border-radius: 999px;
  background: var(--m-tint); color: var(--m-ink); font: 500 12.5px var(--font-sans);
  transition: transform .14s var(--m-pill);
}
.m-fsync-b:active { transform: scale(.96); }
.m-fsync-b svg { flex: 0 0 auto; }
.m-fsync-b.busy svg { animation: m-spin .8s linear infinite; }
/* Після картки одного гаманця плашці потрібен свій відступ зверху. */
.m-fshop + .m-fsync { margin-top: 10px; }

.m-facc-row {
  display: flex; align-items: stretch; gap: 8px;
  overflow-x: auto; -webkit-overflow-scrolling: touch;
  padding: 14px 20px 6px; scrollbar-width: none;
}
.m-facc-row::-webkit-scrollbar { display: none; }
.m-facc {
  flex: 0 0 auto; min-width: 150px; max-width: 200px;
  display: flex; flex-direction: column;
  background: var(--m-card); border-radius: 16px; box-shadow: var(--m-sh-card);
  padding: 11px 14px 12px;
}
/* Тип рахунку — тихим капсом ліворуч, кольорова крапка магазину праворуч. */
.m-facc-top {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  font: 500 9.5px var(--font-sans); letter-spacing: .12em; text-transform: uppercase;
  color: var(--m-faint); overflow: hidden; white-space: nowrap;
}
.m-facc-top span { overflow: hidden; text-overflow: ellipsis; }
.m-facc-top i { width: 7px; height: 7px; border-radius: 999px; flex: 0 0 auto; }
.m-facc-n {
  font: 400 11.5px var(--font-sans); color: var(--m-faint); margin-top: 6px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.m-facc-b {
  font: 500 18px/1 var(--font-display); letter-spacing: -.015em; color: var(--m-ink);
  margin-top: auto; padding-top: 7px; white-space: nowrap;
}
/* Зведення — тепла картка без тіні, як картка прибутку. */
.m-facc-total { background: #F1E9DE; box-shadow: none; }
.m-facc-b2 { font: 400 13.5px/1 var(--font-display); color: var(--m-soft); margin-top: 5px; white-space: nowrap; }
.m-facc-total .m-facc-b { margin-top: 8px; padding-top: 0; }

.m-ftx { padding: 4px 17px; cursor: default; }
.m-ftx-row { display: flex; align-items: center; gap: 11px; padding: 11px 0; border-bottom: 1px solid #F4EDE5; }
.m-ftx-row:last-child { border-bottom: none; }
.m-ftx-ic { width: 32px; height: 32px; border-radius: 10px; flex: 0 0 auto; display: grid; place-items: center; }
.m-ftx-ic.pos { background: #E4EFE2; color: #47694E; }
.m-ftx-ic.neg { background: #F5E4DA; color: #9C6A47; }
.m-ftx-in { flex: 1; min-width: 0; }
.m-ftx-t { font: 400 13px var(--font-sans); color: var(--m-ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.m-ftx-s { font: 400 11px var(--font-sans); color: var(--m-faint); margin-top: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Гаманець у підписі — зі СВОЄЮ кольоровою крапкою. */
.m-ftx-shop { display: inline-flex; align-items: center; gap: 4px; vertical-align: bottom; }
.m-ftx-shop i { width: 6px; height: 6px; border-radius: 999px; flex: 0 0 auto; }
.m-ftx-amt { flex: 0 0 auto; font: 500 14px var(--font-display); letter-spacing: -.01em; color: var(--m-ink); }
.m-ftx-amt.pos { color: #47694E; }
.m-fmore-wrap { padding: 14px 20px 4px; }
.searchbtn .ic-eplus { opacity: 0; transform: scale(.5) rotate(-45deg); }
.searchbtn .ic-stat { opacity: 0; transform: scale(.5) rotate(-45deg); }

/* Картка заявки — конструкція й стилі повністю від карток замовлень
   (.m-card-b / .m-card-t / .m-card-f). Своє: текст стартує від верхньої
   межі плитки (як на складі), автор праворуч у меті, типи — баблами, і
   ніщо не переносить рядок — усі картки однієї висоти. */
.m-ecard .m-card-b { align-items: flex-start; }
.m-ecard .m-meta-row { align-items: center; height: 16px; }
.m-ecard .m-meta { line-height: 16px; }
/* Автор — тихим звичайним текстом, не капсом: це підпис, а не мета. */
.m-ecard .m-eby {
  flex: 0 0 auto; font: 400 11px var(--font-sans);
  letter-spacing: 0; text-transform: none; color: var(--m-mute);
}
.m-ecard .m-name { margin-top: 2px; }
.m-ecard .m-variant { margin-top: 6px; flex-wrap: nowrap; min-width: 0; }
.m-ecard .m-opt {
  display: inline-block; line-height: 20px; padding: 0 9px;
  flex: 0 1 auto; min-width: 0; max-width: 100%;
  overflow: hidden; text-overflow: ellipsis;
}
.m-ecard .m-size { flex: 0 0 auto; }
.m-ecanc { opacity: .55; }
.m-ecanc .m-name { text-decoration: line-through; }

/* KPI над стрічкою — та сама картка, що «Чистий прибуток» у замовленні.
   Смуга часток — власна: глобальний .m-bar сторінки матеріалу має
   підкладку-трек, а тут сегменти окремі, як у прибутку. */
.m-ekpi { cursor: default; width: auto; margin: 0 20px; }
.m-ekpi-bar { display: flex; gap: 3px; height: 8px; margin-top: 16px; }
.m-ekpi-bar i { border-radius: 999px; }

/* Закритий місяць — картка-зведення, що розгортається чеком донизу. */
.m-emon { padding: 16px 20px 0; }
.m-emon-chev { color: var(--m-mute); display: grid; place-items: center; transition: transform .3s var(--m-ease-soft); }
.m-emon.open .m-emon-chev { transform: rotate(180deg); }
/* Відступ живе ПОСТІЙНО на вмісті, а не з'являється разом з .on:
   стрибок паддінгу на старті й давав смикання карток при розгортанні. */
.m-emon .m-rc-wrap { padding-top: 12px; }
/* Прозорість іде В НОГУ з висотою: рідне .26s гасило картки раніше,
   ніж доїжджав рух, — і згортання читалось рвано. */
.m-emon .m-receipt {
  transition: grid-template-rows .42s var(--m-ease), opacity .42s var(--m-ease);
}

/* Кнопка «Прийняти» на картці матеріалу. */
.m-accept {
  flex: 0 0 auto; height: 30px; padding: 0 13px; border-radius: 999px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid #CFE2CC; background: #E4EFE2; color: #47694E;
  font-weight: 500; font-size: 12px; line-height: 1; white-space: nowrap;
}

/* Сторінка заявки — той самий каркас, що в замовлення й матеріалу:
   герой, .m-nav, .m-order-body, .m-o-status, блоки .m-block. Своє тут —
   лише рядки позицій усередині блока та зелена кнопка оплати. */
.m-ep-item { display: flex; align-items: center; gap: 10px; padding: 10px 0; border-bottom: 1px solid #F4EDE5; }
.m-ep-item:last-child { border-bottom: none; padding-bottom: 3px; }
.m-block-eitems .m-ep-item:first-of-type { margin-top: 2px; }
/* Позиція — зі значком свого матеріалу в пісочній плитці; фарба — колом
   свого кольору. */
.m-ep-tile {
  width: 34px; height: 34px; flex: 0 0 auto; border-radius: 10px;
  background: var(--m-tint-2); color: var(--m-mute);
  display: grid; place-items: center;
}
.m-ep-dot { width: 16px; height: 16px; border-radius: 999px; box-shadow: inset 0 0 0 1px rgba(43,35,29,.12); }
/* Фарба — лише коло кольору, плитка-підкладка зникає. */
.m-ep-tpaint { background: none; }
.m-ep-tpaint .m-ep-dot { width: 20px; height: 20px; }
.m-ep-in { flex: 1; min-width: 0; }
.m-ep-name { font-weight: 400; font-size: 13.5px; color: var(--m-ink); }
.m-ep-meta { font-weight: 400; font-size: 11.5px; color: var(--m-faint); margin-top: 2px; }
/* Чип стану позиції — тих самих розмірів, що кнопка оплати поряд. */
.m-echip {
  flex: 0 0 auto; height: 30px; padding: 0 12px; border-radius: 999px;
  display: inline-flex; align-items: center;
  font-weight: 500; font-size: 11.5px; line-height: 1; white-space: nowrap;
}
/* «Прийнято» — блакитне: зелене лишається за оплатою, щоб дві різні дії не зливались. */
.m-echip-ok { background: #E1ECF5; color: #3F6786; }
.m-echip-go { background: #F5E4DA; color: #9C6A47; }
.m-emini {
  flex: 0 0 auto; height: 30px; padding: 0 12px; border-radius: 999px;
  display: inline-flex; align-items: center; gap: 5px;
  border: 1px solid #E7DAC9; background: #fff; font-weight: 500; font-size: 12px; line-height: 1;
}
.m-emini .num { font-weight: 400; opacity: .8; }
.m-emini-pay { background: #E4EFE2; border-color: #CFE2CC; color: #47694E; }
.m-ep-acts { display: flex; gap: 8px; }
/* Головна оплата — темна, як основні кнопки застосунку. Без тіні. */
.m-ep-pay { background: var(--m-ink); border: none; color: #F7F1EA; }

/* Нижній бар дії на сторінці заявки — стоїть на місці схованого дока. */
.m-ep-bar {
  position: absolute; left: 20px; right: 20px; bottom: var(--m-dock-b);
  z-index: 34; display: flex; flex-direction: column; gap: 9px;
}
.m-ep-bar .m-btn { border-radius: 999px; height: 54px; font-size: 15px; }
/* Натиск на кнопки бара — виразніший за звичайні .m-btn. */
#mApp .m-ep-bar .m-btn.press { transform: scale(.965); filter: brightness(1.12); }
.m-ep-bsum { font-weight: 400; opacity: .8; }
.m-ep-unpay {
  align-self: center; background: none; border: none; cursor: pointer;
  padding: 5px 12px; font: 400 13px var(--font-sans); color: var(--m-soft);
}
.m-ep-done {
  height: 54px; border-radius: 999px; background: #E4EFE2; color: #3F6247;
  display: flex; align-items: center; justify-content: center; gap: 8px;
  font: 500 14.5px var(--font-sans);
}
/* Хвіст скролера — щоб останній блок виїжджав над баром, а не під ним. */
.m-expp .m-order-body { padding-bottom: calc(var(--m-tabh) + 74px + env(safe-area-inset-bottom)); }

/* ═══════════ СТАТИСТИКА ═══════════
   Розділ дока. Угорі картка вибору: два поля в один рядок (магазини —
   дропдаун, період — календар) і кнопка. Нижче — картки звітів у стилі
   карток черги; натиск відкриває сторінку звіту з плитками KPI. */
/* ─── Морфінг капсули меню ───
   Клас morph стискає капсулу до кружка; коли клас знято, вона знову
   розтягується власним переходом ширини — уже з іншим вмістом. */
.tabcap.morph { width: var(--m-dock-h) !important; transition: width .24s var(--m-ease-in-soft), padding .24s var(--m-ease-in-soft), opacity .28s ease, transform .52s var(--m-ease-spring); }
/* Меню розчиняється на місці, а панель статистики приїжджає справа наліво.
   Назад меню проявляється лише КОЛИ капсула вже повернула ширину — інакше
   кнопки перерозкладаються на очах. */
/* Лише прозорість, без transform: трансформований блок стає offsetParent
   для кнопок, і пілюля, поставлена в цей момент, з'їжджала на 8px. */
.tabgrp { transition: opacity .24s ease; }
#mApp.m-stat ~ #mTabs .tabgrp { opacity: 0; pointer-events: none; }
/* Панель статистики в капсулі: період · згенерувати. Ширина СТАЛА і
   дорівнює нутру капсули в стані статистики; притиснута до правого краю,
   тож зміна ширини капсули (зліва) її не рухає — рухає лише власний зсув. */
.statbar {
  position: absolute; top: var(--m-dock-pad); bottom: var(--m-dock-pad); right: var(--m-dock-pad);
  width: calc(100vw - 188px); z-index: 2;
  display: flex; align-items: center; gap: 6px;
  opacity: 0; transform: translate3d(44px, 0, 0) scale(.9); pointer-events: none;
  transition: opacity .24s ease, transform .44s var(--m-ease-soft);
}
#mApp.m-stat ~ #mTabs .statbar { opacity: 1; transform: none; pointer-events: auto; }
.sb-btn {
  flex: 0 0 var(--m-dock-btn); width: var(--m-dock-btn); height: var(--m-dock-btn);
  border: none; border-radius: 999px; padding: 0; cursor: pointer;
  background: transparent; color: #6B5C50; display: grid; place-items: center;
  transition: transform .16s var(--m-ease-soft), background .2s ease, color .2s ease;
}
.sb-btn:active { transform: scale(.92); }
.sb-go { background: var(--m-ink); color: #FFFDFA; }
.sb-go.dis { background: rgba(43, 35, 29, .1); color: #A99D91; }
.sb-date {
  flex: 1; min-width: 0; height: var(--m-dock-btn); border: none; cursor: pointer;
  border-radius: 999px; background: rgba(43, 35, 29, .06); padding: 0 10px;
  display: flex; align-items: center; justify-content: center; gap: 8px; line-height: 1;
  transition: background .2s ease, transform .14s var(--m-pill);
}
.sb-date:active { transform: scale(.97); }
.sb-date.open { background: rgba(43, 35, 29, .12); }
.sb-date.pop { transform: scale(.95); background: rgba(43, 35, 29, .14); }
.sb-date-l { font: 400 9px var(--font-sans); letter-spacing: .14em; text-transform: uppercase; color: var(--m-faint); }
.sb-date > svg { flex: 0 0 auto; width: 15px; height: 15px; color: var(--m-soft); }
.sb-date-v { min-width: 0; font: 500 12.5px var(--font-sans); letter-spacing: -.01em; color: var(--m-ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sb-date.empty .sb-date-v { color: var(--m-soft); font-weight: 400; }

/* ─── Панель відкритого звіту ───
   (класи rp-*: .rtab уже зайнятий вкладками робочого сайту.)
   Своя капсула на всю ширину дока. Док цілком (назад · меню · статистика)
   від'їжджає вліво й гасне, панель приходить справа. Кнопки — рівними
   клітинками, пілюля під активною їздить, як у меню. */
/* МОРФІНГ: сама капсула меню розтягується на всю ширину дока пружиною (з
   баунсом наприкінці), круг «назад» і круг статистики схлопуються в нуль і
   «втягуються» в неї; панель дати гасне, а поверх — уже на повній ширині —
   проявляються розділи звіту. Одна геометрія, одне скло. */
#mApp.m-rpage ~ #mTabs .leftgrp { width: 100%; }
#mApp.m-rpage ~ #mTabs .tabcap { width: 100%; }
#mApp.m-rpage ~ #mTabs .backcap { width: 0; padding: 0; margin-right: -10px; opacity: 0; pointer-events: none; }
#mApp.m-rpage ~ #mTabs .searchcap { width: 0; flex-basis: 0; padding: 0; margin-left: -10px; opacity: 0; pointer-events: none; }
#mApp.m-rpage ~ #mTabs .statbar { opacity: 0; transform: scale(.92); pointer-events: none; }
/* На час морфінгу всі частини їдуть однією пружною кривою — з баунсом у кінці. */
#mApp.m-rpage ~ #mTabs .leftgrp { transition: width .62s var(--m-ease-spring), opacity .24s ease, transform .44s var(--m-ease-soft); }
#mApp.m-rpage ~ #mTabs .tabcap { transition: width .62s var(--m-ease-spring), padding .62s var(--m-ease-spring), opacity .28s ease,
  transform .52s var(--m-ease-spring), backdrop-filter .34s ease, -webkit-backdrop-filter .34s ease; }
#mApp.m-rpage ~ #mTabs .backcap { transition: width .62s var(--m-ease-spring), margin .62s var(--m-ease-spring), padding .62s var(--m-ease-spring),
  opacity .26s ease, transform .22s var(--m-ease-in-soft), background .2s ease; }
#mApp.m-rpage ~ #mTabs .searchcap { transition: width .62s var(--m-ease-spring), flex-basis .62s var(--m-ease-spring), margin .62s var(--m-ease-spring),
  padding .62s var(--m-ease-spring), opacity .26s ease, transform .24s var(--m-ease-in-soft), backdrop-filter .34s ease, -webkit-backdrop-filter .34s ease; }
.leftgrp { transition: width .44s var(--m-ease-soft), opacity .24s ease, transform .44s var(--m-ease-soft); }
.searchcap { transition: width .44s var(--m-ease-soft), flex-basis .44s var(--m-ease-soft),
              margin .44s var(--m-ease-soft), opacity .24s ease,
              padding .44s var(--m-ease-soft), gap .44s var(--m-ease-soft),
              transform .24s var(--m-ease-in-soft),
              backdrop-filter .34s ease, -webkit-backdrop-filter .34s ease; }
/* Розділи звіту — прозорий шар УСЕРЕДИНІ капсули: скло дає вона сама, і
   підскок капсули масштабує й текст. */
/* Ширина СТАЛА — нутро капсули на повній ширині дока. Поки капсула ще
   росте, кнопки не стискаються, а пілюля стоїть де має. */
.rdock {
  position: absolute; top: var(--m-dock-pad); bottom: var(--m-dock-pad); left: var(--m-dock-pad);
  width: calc(100vw - 2 * var(--m-dock-side) - 2 * var(--m-dock-pad)); z-index: 3; padding: 0; border-radius: 999px;
  background: none; box-shadow: none;
  display: flex; align-items: center; gap: 0;
  opacity: 0; transform: scale(.94); pointer-events: none;
  transition: opacity .26s ease, transform .52s var(--m-ease-spring);
}
#mApp.m-rpage ~ #mTabs .rdock { opacity: 1; transform: none; pointer-events: auto; transition-delay: .12s; }
.rp-tab {
  position: relative; z-index: 1; flex: 1 1 0; min-width: 0; height: var(--m-dock-btn);
  border: none; background: none; padding: 0 8px; cursor: pointer; border-radius: 999px;
  font: 500 12.5px var(--font-sans); letter-spacing: 0; color: #8C7C6D; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis;
  transition: color .22s ease;
}
.rp-tab.on { color: #FFFDFA; }
/* Сіра капсула під пальцем — той самий відгук, що в кнопок меню. */
.rp-tab::before {
  content: ''; position: absolute; inset: 0; z-index: -1; border-radius: 999px;
  background: rgba(43, 35, 29, .07); opacity: 0; transform: scale(.7);
  transition: opacity .18s ease, transform .22s var(--m-ease-soft); pointer-events: none;
}
.rp-tab:active::before { opacity: 1; transform: scale(1); }
.rp-tab.on:active::before { opacity: 0; }
/* Пілюля — дві ноди, як у меню: зовнішня їздить і міняє ширину, внутрішня
   на час переїзду трохи розтягується вздовж руху. */
#mTabs .rt-pill {
  position: absolute; top: 0; left: 0; z-index: 0; height: var(--m-dock-btn); width: 80px;
  display: block; background: none;
  /* М'яке гасіння з ледь помітним перельотом: крайні пункти не вилазять за
     скруглений край капсули (там лише 8px поля). */
  transition: transform .52s cubic-bezier(.3, 1.1, .35, 1), width .52s cubic-bezier(.3, 1.1, .35, 1);
}
#mTabs .rt-pill i {
  display: block; width: 100%; height: 100%; border-radius: 999px; background: #2B231D;
  transition: transform .18s ease;
}
#mTabs .rt-pill.moving i { transform: scale(1.07) scaleX(1.1); }
/* Підскок панелі при перемиканні — той самий, що в капсули меню. */

/* Підміна розділу звіту під прозорістю. */
#mStatBody { transition: opacity .34s var(--m-ease-soft); }
#mStatBody.swap { opacity: 0; transition: opacity .13s ease; }

/* У розділі статистики обраною є ПРАВА кнопка дока: вона темніє, значок
   статистики лишається, а пілюля в капсулі меню гасне. */
#mApp.m-stat ~ #mTabs .searchbtn .ic-find { opacity: 0; transform: scale(.5) rotate(45deg); }
#mApp.m-stat ~ #mTabs .searchbtn .ic-stat { opacity: 1; transform: none; }
#mApp.m-stat ~ #mTabs .searchbtn { background: #2B231D; color: #FFFDFA; }
#mApp.m-stat ~ #mTabs .tabpill { opacity: 0; }
#mApp.m-stat ~ #mTabs .tabbtn.on { color: #8C7C6D; }
#mApp.m-stat ~ #mTabs .tabbtn.on svg { transform: none; }
/* Календар над розділом — від вікна, а не від картки: інакше обрізається. */
/* Календар статистики — попап над смугою капсул у стилі дока: скло, біла
   кромка, той самий радіус. Без затемнення: шар позаду лише ловить дотик. */
.m-calveil { position: fixed; inset: 0; z-index: 44; }
.m-calpop-glass {
  position: fixed; left: 20px; right: 20px; z-index: 45; padding: 8px; border-radius: 26px;
  /* Щільніше за док: попап має ПЕРЕКРИВАТИ капсули магазинів, а не просвічувати їх. */
  background: rgba(246, 243, 240, .93);
  -webkit-backdrop-filter: blur(18px) saturate(1.4); backdrop-filter: blur(18px) saturate(1.4);
  box-shadow: 0 14px 34px -18px rgba(58, 44, 32, .4), inset 0 0 0 1px rgba(255, 255, 255, .6);
  animation: m-calpop-up .32s var(--m-pill) both;
}
@keyframes m-calpop-up {
  from { opacity: 0; transform: translateY(14px) scale(.96); }
  to   { opacity: 1; transform: none; }
}
.m-calpop-glass.out { animation: m-calpop-down .22s ease both; pointer-events: none; }
@keyframes m-calpop-down {
  from { opacity: 1; transform: none; }
  to   { opacity: 0; transform: translateY(14px) scale(.96); }
}
.m-calpop-glass .m-cal { margin-top: 0; background: transparent; padding: 8px 8px 6px; }
.m-calpop-glass .m-cal-nav { background: rgba(255, 255, 255, .75); }
.m-calpop-glass .m-cal-f { margin-top: 6px; }
/* Картка звіту — як картка прибутку в замовленні: тепла плашка, підпис
   капсом, велика цифра з маржею, смуга часток, рядок фактів. */
.m-scard {
  display: block; margin: 0 0 10px; padding: 17px 18px 16px; cursor: pointer;
  background: #F1E9DE; border-radius: 20px; box-shadow: none;
}
.m-scard.press { background: #EBE1D3; }
/* Непрочитаний звіт — світла картка; після відкриття стає звичайною. */
.m-scard { transition: background .5s ease; }
.m-scard.fresh { background: rgba(255, 253, 251, .92); }
/* Поки збираємо дані — картка тепла, щоб світлий градієнт по ній було видно;
   світлою вона стає разом із проявленням цифр. */
.m-scard.gen.fresh:not(.ready) { background: #F1E9DE; }
.m-scard.fresh.press { background: #F7F1EA; }
.m-scard-k {
  display: flex; align-items: center; gap: 9px; min-width: 0;
  font: 400 10.5px var(--font-sans); letter-spacing: .18em; text-transform: uppercase; color: #9C8B7C;
}
.m-scard-dots { display: inline-flex; gap: 3px; flex: 0 0 auto; }
.m-scard-dots i { width: 7px; height: 7px; border-radius: 999px; }
.m-scard-t { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.m-scard-p { flex: 0 0 auto; letter-spacing: .08em; }
/* Сума й маржа — на одній базовій лінії, шеврон притиснутий до краю. */
.m-scard-row { display: flex; align-items: baseline; gap: 10px; margin-top: 11px; }
.m-scard-n { font: 500 27px/1 var(--font-display); letter-spacing: -.02em; color: var(--m-ink); }
.m-scard-n.neg { color: #9C4B45; }
.m-scard-m { font: 400 12px var(--font-sans); color: var(--m-soft); flex: 1; }
.m-scard-chev { flex: 0 0 auto; color: #C0B0A0; display: grid; align-self: center; }
.m-scard .m-bar { margin-top: 14px; }
.m-scard-f {
  display: flex; align-items: center; gap: 7px; margin-top: 11px; min-width: 0;
  font: 400 11.5px var(--font-sans); color: var(--m-soft); white-space: nowrap; overflow: hidden;
}
.m-scard-f span { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.m-scard-f i { color: #C0B0A0; font-style: normal; flex: 0 0 auto; }
/* Легенда під смугою в картці списку — як у зведенні звіту, трохи щільніше. */
.m-scard-l { margin-top: 11px; gap: 7px 12px; font-size: 11px; }

/* ─── Поява згенерованої картки ───
   Обгортка-сітка: 0fr → 1fr розкриває висоту, і список під нею з'їжджає
   вниз тим самим рухом. Сама картка при цьому трохи виростає з прозорості. */
.m-scard-wrap { display: grid; grid-template-rows: 1fr; }
.m-scard-wrap > div { min-height: 0; overflow: hidden; }
.m-scard-wrap.enter { grid-template-rows: 0fr; transition: grid-template-rows .55s var(--m-ease-soft); }
/* Сама картка входить кадровою анімацією, а не переходом: перехід стартував
   із випадкового значення й давав спалах перед проявленням. */
.m-scard-wrap.enter .m-scard { animation: m-scard-in .55s var(--m-ease-soft) .1s both; }
.m-scard-wrap.enter.on { grid-template-rows: 1fr; }
@keyframes m-scard-in {
  from { opacity: 0; transform: translateY(-10px) scale(.97); }
  to   { opacity: 1; transform: none; }
}
/* Стан генерації: порожня картка, по якій плавно дихає світлий градієнт, і
   акуратний підпис по центру. Вміст лежить під ними з нульовою прозорістю;
   готово — підпис і подих гаснуть, вміст проявляється. */
.m-scard { position: relative; overflow: hidden; }
.m-scard-c { position: relative; z-index: 2; transition: opacity .7s ease; }
.m-scard.gen .m-scard-c { opacity: 0; }
/* Порожня картка, поки дані ще їдуть: та сама висота, що в готової. */
.m-scard-c.gen-empty { min-height: 125px; }
.m-scard.gen { overflow: hidden; }
.m-scard.gen.ready .m-scard-c { opacity: 1; transition-delay: .2s; }
.m-scard.gen::before {
  content: ''; position: absolute; inset: 0; z-index: 1; border-radius: inherit;
  background: linear-gradient(115deg, rgba(255, 252, 247, 0) 20%, rgba(255, 252, 247, .85) 50%, rgba(255, 252, 247, 0) 80%);
  background-size: 260% 100%;
  animation: m-gen-breathe 2.6s ease-in-out infinite;
  transition: opacity .5s ease;
}
.m-scard.gen.ready::before { opacity: 0; }
/* Підпис — маленькою білою капсулою в лівому верхньому куті, там, де потім стане
   рядок магазинів. */
.m-scard-sk {
  position: absolute; left: 18px; top: 15px; z-index: 3;
  pointer-events: none; transition: opacity .45s ease;
}
.m-scard.ready .m-scard-sk { opacity: 0; }
.m-gen-t {
  display: inline-flex; align-items: center; height: 22px; padding: 0 9px; border-radius: 999px;
  background: rgba(255, 253, 251, .92); color: var(--m-soft);
  font: 500 10.5px var(--font-sans); letter-spacing: .04em;
  animation: m-gen-text 2.6s ease-in-out infinite;
}
@keyframes m-gen-breathe {
  0%   { background-position: 130% 0; opacity: .25; }
  50%  { opacity: .9; }
  100% { background-position: -130% 0; opacity: .25; }
}
@keyframes m-gen-text { 0%, 100% { opacity: .55; } 50% { opacity: 1; } }
@media (prefers-reduced-motion: reduce) {
  .m-scard.gen::before, .m-gen-t { animation: none; }
}
/* Сторінка звіту: без героя, шапка під круглими кнопками, далі — тепла
   картка прибутку й блоки чека, ті самі класи й відступи, що в замовленні. */
.m-statp .m-order-body {
  /* Відступ під кнопки — на вмісті, а не на самому скролері: від padding
     скролера Chromium і Safari рахують sticky по-різному. */
  padding-top: 0;
  padding-bottom: calc(var(--m-tabh) + 40px + env(safe-area-inset-bottom));
}
.m-statp .m-stat-sheet { padding-top: calc(72px + env(safe-area-inset-top)); }
.m-statp .m-o-head { margin-bottom: 18px; }
.m-stat-sheet { display: flex; flex-direction: column; gap: 12px; }
.m-stat-profit { cursor: default; }
/* Велика сума — одним рядком; підпис поруч переноситься сам. */
.m-stat-profit .m-profit-n { white-space: nowrap; flex: 0 0 auto; }
.m-stat-profit .m-profit-m { flex: 1 1 auto; min-width: 0; line-height: 1.3; }
.m-profit-sub { margin-top: 7px; font: 400 12px/1.35 var(--font-sans); color: var(--m-soft); }
.m-stat-profit .m-profit-n.neg { color: #9C4B45; }
/* Білі блоки на сторінці звіту — без тіні: спокійніше поруч із теплою карткою. */
.m-statp .m-rc { box-shadow: none; }
/* Показники — одна біла картка, усередині пастельні плитки по дві в ряд:
   зелені — що надійшло, червонуваті — що вирахувано; підсумок на всю
   ширину і зелений або червоний за знаком. */
.m-kv-card { padding: 10px; }
.m-kv-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
.m-kv { padding: 13px 14px 12px; min-width: 0; border-radius: 14px; background: #F5EFE8; box-shadow: none; }
/* Пастель зовсім ніжна: ледь-ледь зеленувата і ледь-ледь рожева. */
.m-kv.pos { background: #FAFCF9; }
.m-kv.neg { background: #FEFAF8; }
/* Кольорові крапки при заголовках — як у блоків чека. */
.m-kv .m-rc-h i { display: inline-block; flex: 0 0 auto; }
/* Заголовки показників — звичайним регістром, без розрядки: капс лишаємо чеку. */
/* Назва блоку — маленькою світлою капсулою, як «Збираємо дані», з крапкою всередині. */
.m-kv .m-rc-h { display: inline-flex; align-items: center; gap: 6px; max-width: 100%; height: 22px; padding: 0 9px 0 8px; border-radius: 999px; background: #FFFFFF; margin-bottom: 10px; font: 500 10.5px var(--font-sans); letter-spacing: .02em; text-transform: none; color: var(--m-soft); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.m-kv-v { font: 500 21px/1 var(--font-display); letter-spacing: -.02em; color: var(--m-ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.m-kv.pos .m-kv-v { color: #567A5E; }
.m-kv.neg .m-kv-v { color: #A9666A; }
.m-kv-n { margin-top: 7px; font: 400 11px/1.4 var(--font-sans); color: var(--m-soft); opacity: .85; }
/* У плитках підписів під цифрою немає — лише заголовок і число. */
.m-kv-grid .m-kv-n { display: none; }
/* Більше повітря: вищі плитки, число дихає між капсулою й нижнім краєм. */
.m-kv-grid .m-kv { padding: 9px 12px 15px; }
.m-kv-grid .m-kv .m-rc-h { margin-bottom: 18px; }
/* Підсумок — у білій підкладці, на всю ширину сітки. */
/* Широка плитка (повернення): на всю ширину, підпис із кількістю — праворуч
   на рівні числа. */
.m-kv-grid .m-kv-wide { grid-column: 1 / -1; }
.m-kv-grid .m-kv-wide .m-kv-n { display: block; position: absolute; right: 14px; bottom: 17px; margin: 0; font-size: 11.5px; }
.m-kv-grid .m-kv-wide:not(.m-kv-tap) { position: relative; }
.m-kv-grid .m-kv-total { grid-column: 1 / -1; padding: 16px 16px 18px; border-radius: 14px; }
.m-kv-grid .m-kv-total .m-kv-n { display: block; }
.m-kv-total.pos { background: #F7FAF6; }
.m-kv-total.neg { background: #FCF6F4; }
.m-kv-total .m-rc-h { height: 24px; padding: 0 10px 0 9px; font-size: 11.5px; margin-bottom: 11px; }
.m-kv-total .m-kv-v { font-size: 30px; }
.m-kv-total .m-kv-n { font-size: 11.5px; margin-top: 9px; }
/* Блок, який відкриває шторку: натиск дає той самий відгук, що в картки. */
.m-kv-tap { cursor: pointer; position: relative; }
.m-kv-chev { position: absolute; top: 11px; right: 10px; display: grid; color: var(--m-faint); }
.m-kv-chev svg { width: 13px; height: 13px; }
#mApp .m-kv-tap.press { transform: scale(.985); background: #FBF8F4; }
/* ── Розрахунок по замовленнях: таблиця в білій картці ──
   Ширша за екран, тож гортається вбік; номер замовлення прилипає зліва.
   Клас m-sx вимикає на ній жест «назад», а touch-action повертає ще й
   вертикальне гортання сторінки — інакше палець на таблиці стояв би. */
/* clip, а не hidden: hidden робить картку контейнером прокрутки, і липка
   шапка чіплялась би до неї, а не до сторінки. */
.m-otab-card { padding: 10px 0 10px; }
/* Смуга з назвами колонок: липне під кнопками навігації (відступ дає
   padding-top самої сторінки — Chromium відлічує sticky від нього),
   гортається вбік разом із таблицею (зсув ставить скрипт). */
.m-otab-hd { position: sticky; top: calc(72px + env(safe-area-inset-top)); z-index: 4; background: var(--m-card); border-radius: 19px 19px 0 0; padding-top: 2px; transition: box-shadow .2s ease; }
.m-otab-hd.stuck { box-shadow: 0 10px 16px -14px rgba(43, 35, 29, .22); }
.m-otab-hdin { overflow: hidden; }
/* Плашка над прилиплою шапкою: на всю ширину екрана, кольору сторінки, —
   рядки, що йдуть угору, ховаються під нею, а не під кнопками. */
.m-otab-hd::before { content: ''; position: absolute; left: -18px; right: -18px; bottom: 100%; height: calc(72px + env(safe-area-inset-top)); background: var(--m-bg); opacity: 0; pointer-events: none; }
.m-otab-hd.stuck::before { opacity: 1; }
/* «Вушка» кутів: прозорий прямокутник зі скругленим верхом і величезною
   тінню кольору сторінки — тінь зафарбовує все НАВКОЛО скруглення, і кути
   прилиплої шапки читаються круглими навіть на білій картці під нею. */
.m-otab-hd::after { content: ''; position: absolute; left: 0; right: 0; top: 0; height: 19px; border-radius: 19px 19px 0 0; box-shadow: 0 -40px 0 40px var(--m-bg); z-index: -1; opacity: 0; pointer-events: none; }
.m-otab-hd.stuck::after { opacity: 1; }
.m-otab-hd table { border-collapse: separate; border-spacing: 0; white-space: nowrap; table-layout: fixed; }
/* Копія шапки в тілі таблиці — лише задає ширину колонок, сама невидима. */
.m-otab thead.ghost th { height: 0; padding-top: 0; padding-bottom: 0; line-height: 0; color: transparent; border-bottom: none; overflow: hidden; }
.m-otab-h, .m-cap-h { display: inline-flex; align-items: center; gap: 7px; margin: 0 14px 10px; height: 22px; padding: 0 9px 0 8px; border-radius: 999px; background: #F5EFE8; font: 500 10.5px var(--font-sans); letter-spacing: .02em; color: var(--m-soft); }
.m-otab-h i, .m-cap-h i { width: 6px; height: 6px; border-radius: 999px; background: #7F9382; }
.m-otab-h b, .m-cap-h b { font-weight: 500; color: var(--m-ink); }
/* Біла картка з капсулою-заголовком і рядками чека всередині (Etsy). */
.m-cap-card { padding: 12px 0 10px; }
.m-cap-card .m-rc-row { margin: 0 14px; }
.m-cap-card .m-rc-row b.minus { color: #A9666A; }
.m-cap-card .m-rc-row b.plus { color: #567A5E; }
.m-cap-card .m-rc-row.sum b { color: #3A5C41; }
.m-cap-card .m-rc-note { margin: 6px 14px 0; }
/* Виплати: крапка кольору магазину, під назвою — кількість переказів. */
.m-pay-card .m-rc-row span { display: flex; flex-wrap: wrap; align-items: center; gap: 0 8px; }
.m-pay-card .m-rc-row span small { flex-basis: 100%; padding-left: 15px; font: 400 11px var(--font-sans); color: var(--m-faint); margin-top: 1px; }
.m-payd { width: 7px; height: 7px; border-radius: 999px; flex: 0 0 auto; }
.m-pay-card .m-rc-row.last b { color: var(--m-soft); font-weight: 400; }
.m-pay-card .m-rc-row.warn span { color: #9C4B45; }
.m-pay-fix { display: block; width: calc(100% - 28px); margin: 10px 14px 4px; }
.m-otab tr.outside td.prod span { color: var(--m-soft); font-style: italic; }
.m-pay-card .m-rc-row.warn span small { color: #B98380; padding-left: 0; }
/* Графік реклами: крива з точками, заливка під нею, пік підписано. */
/* Заголовок картки реклами: капсула зліва, список магазинів справа. */
.m-ads-card { position: relative; }
.m-cap-top { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin: 0 14px 10px; }
.m-cap-top .m-cap-h { margin: 0; }
.m-cap-side { font: 500 13px var(--font-sans); color: #A9666A; font-variant-numeric: lining-nums tabular-nums; }
/* Картка, що розкривається: заголовок натискається, шеврон повертається,
   список їде висотою 0fr → 1fr. */
.m-fold.can { cursor: pointer; }
#mApp .m-fold.can.press { transform: scale(.99); }
/* Останні рядки згорнутої картки тануть у білому — видно, що список іде далі. */
.m-fold-prev { position: relative; }
.m-fold-prev::after { content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 64px; pointer-events: none; background: linear-gradient(to bottom, rgba(255, 255, 255, 0), var(--m-card) 92%); opacity: 1; transition: opacity .28s ease; }
.m-fold.open .m-fold-prev::after { opacity: 0; }
.m-fold-foot { display: flex; justify-content: center; padding: 6px 14px 2px; }
.m-fold-btn { display: inline-flex; align-items: center; gap: 6px; height: 30px; padding: 0 12px 0 14px; border-radius: 999px; background: #F5EFE8; font: 500 12px var(--font-sans); color: var(--m-ink); }
.m-fold-btn .less { display: none; }
.m-fold.open .m-fold-btn .more { display: none; }
.m-fold.open .m-fold-btn .less { display: inline; }
.m-fold .m-cap-side { margin-left: auto; }
.m-fold-chev { display: grid; color: var(--m-soft); transition: transform .32s var(--m-ease-soft); }
.m-fold-chev svg { width: 14px; height: 14px; transform: rotate(90deg); }
.m-fold.open .m-fold-chev { transform: rotate(180deg); }
.m-fold-body { display: grid; grid-template-rows: 0fr; transition: grid-template-rows .36s var(--m-ease-soft); }
.m-fold-body > div { overflow: hidden; min-height: 0; }
.m-fold.open .m-fold-body { grid-template-rows: 1fr; }
.m-fold .m-anom-meta { margin-bottom: 0; }
.m-fold.open .m-anom-meta { margin-bottom: 2px; }
#mApp .m-fold .m-cap-top.press { opacity: .7; }
/* Нетипові доставки: рядок — номер і товар зліва, вартість і переплата справа. */
.m-anom-card .m-anom-meta { margin-top: -2px; }
.m-anom { display: flex; align-items: center; gap: 12px; margin: 0 14px; padding: 10px 0; border-bottom: 1px solid var(--m-line); }
.m-anom:last-of-type { border-bottom: none; }
.m-anom-l { flex: 1; min-width: 0; }
.m-anom-t { font: 500 13px var(--font-sans); color: var(--m-ink); }
.m-anom-t span { font-weight: 400; color: var(--m-soft); margin-left: 4px; }
.m-anom-t i { display: inline-block; margin-left: 5px; padding: 1px 6px; border-radius: 999px; background: #F5EFE8; font: 500 10px/14px var(--font-sans); color: var(--m-soft); font-style: normal; vertical-align: 1px; }
.m-anom-s { margin-top: 3px; font: 400 11px/1.4 var(--font-sans); color: var(--m-faint); }
.m-anom-r { flex: 0 0 auto; text-align: right; }
.m-anom-r b { display: block; font: 500 14px var(--font-sans); color: #A9666A; font-variant-numeric: lining-nums tabular-nums; }
.m-anom-r small { display: block; margin-top: 2px; font: 400 10.5px var(--font-sans); color: var(--m-faint); font-variant-numeric: lining-nums tabular-nums; }
.m-anom-r b.ink, .m-cap-side.ink { color: var(--m-ink); }
/* Країни: назва, код, кількість і відсоток в один рядок, під ним смуга. */
.m-cty { margin: 0 14px; padding: 9px 0 10px; border-bottom: 1px solid var(--m-line); }
.m-cty:last-of-type { border-bottom: none; }
.m-cty-h { display: flex; align-items: center; gap: 7px; }
.m-cty-n { font: 500 13px var(--font-sans); color: var(--m-ink); }
.m-cty-h i { padding: 1px 6px; border-radius: 999px; background: #F5EFE8; font: 500 10px/14px var(--font-sans); color: var(--m-soft); font-style: normal; }
.m-cty-c { margin-left: auto; font: 400 12px var(--font-sans); color: var(--m-faint); }
.m-cty-p { min-width: 46px; text-align: right; font: 500 13px var(--font-sans); color: var(--m-ink); }
.m-cty-bar { height: 6px; margin-top: 7px; border-radius: 999px; background: #F3EDE5; overflow: hidden; }
.m-cty-bar i { display: block; height: 100%; border-radius: 999px; background: #B89484; }
.m-anom-t span.p { font-weight: 500; color: var(--m-ink); margin-left: 0; }
.m-anom-t i.q { background: #EFE7DC; color: var(--m-ink); }
.m-adsdd { display: inline-flex; align-items: center; gap: 6px; height: 26px; padding: 0 8px 0 9px; border: none; border-radius: 999px; background: #F5EFE8; font: 500 11px var(--font-sans); color: var(--m-ink); cursor: pointer; max-width: 55%; }
.m-adsdd span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.m-adsdd i { width: 7px; height: 7px; border-radius: 999px; background: #D6A75E; flex: 0 0 auto; }
.m-adsdd i.all, .m-adsrow i.all { background: conic-gradient(#8b5cf6, #f59e0b, #ec4899, #10b981, #8b5cf6); }
.m-adsdd svg { width: 12px; height: 12px; color: var(--m-faint); transform: rotate(90deg); }
.m-adsveil { position: fixed; inset: 0; z-index: 5; }
.m-adspop { position: absolute; right: 12px; top: 42px; z-index: 6; min-width: 190px; padding: 6px; border-radius: 16px; background: #FFFFFF; box-shadow: 0 18px 44px -18px rgba(43, 35, 29, .38), inset 0 0 0 1px rgba(43, 35, 29, .05); animation: m-calpop-in .22s var(--m-pill) both; }
.m-adsrow { display: flex; align-items: center; gap: 9px; width: 100%; padding: 9px 10px; border: none; border-radius: 11px; background: none; font: 400 13px var(--font-sans); color: var(--m-ink); text-align: left; cursor: pointer; }
.m-adsrow i { width: 8px; height: 8px; border-radius: 999px; flex: 0 0 auto; }
.m-adsrow span { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.m-adsrow svg { width: 13px; height: 13px; color: var(--m-ink); opacity: 0; }
.m-adsrow.on { font-weight: 500; background: #F7F3EE; }
.m-adsrow.on svg { opacity: 1; }
/* Полотно графіка: ширше за екран, гортається вбік; палець по ньому не
   тягне екран назад (m-sx) і не глушить вертикальну прокрутку сторінки. */
.m-adsc { overflow-x: auto; overscroll-behavior-x: contain; scrollbar-width: none; -ms-overflow-style: none; margin: 0; padding: 0 6px; }
.m-adsc::-webkit-scrollbar { width: 0; height: 0; display: none; }
#mApp .m-adsc.m-sx, #mApp .m-adsc.m-sx * { touch-action: pan-x pan-y; }
.m-adsc svg { display: block; overflow: visible; }
.m-adsc .base { stroke: var(--m-line); stroke-width: 1; }
.m-adsc .ln { fill: none; stroke: #D6A75E; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.m-adsc .pt { fill: #FFFFFF; stroke: #D6A75E; stroke-width: 2; transition: r .15s ease; }
.m-adsc .pt.sel { fill: #D6A75E; stroke: #FFFFFF; r: 6.5; }
.m-adsc .hit { fill: transparent; stroke: none; cursor: pointer; }
.m-adsc text { font: 400 10px var(--font-sans); fill: var(--m-faint); font-variant-numeric: tabular-nums; }
.m-adsc .m-adstip rect { fill: #2B231D; }
.m-adsc .m-adstip .tail { fill: #2B231D; }
.m-adsc .m-adstip text { font: 400 10.5px var(--font-sans); fill: #FFFDFA; }
.m-adsc .m-adstip text.d { font: 500 12px var(--font-sans); fill: #FFFDFA; }
.m-adsc .m-adstip text.l { fill: #FFFDFA; opacity: .55; }
.m-adsc .m-adstip text.v { font: 500 11.5px var(--font-sans); font-variant-numeric: lining-nums tabular-nums; }
.m-adsc .m-adstip text.v.a { fill: #E8C98A; }
.m-ads-st { display: flex; gap: 8px; margin: 8px 14px 0; }
.m-ads-st > div { flex: 1 1 0; min-width: 0; background: #FAF7F3; border-radius: 12px; padding: 9px 11px 10px; }
.m-ads-st small { display: block; font: 400 10.5px var(--font-sans); color: var(--m-faint); margin-bottom: 4px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.m-ads-st b { font: 500 14px var(--font-sans); color: var(--m-ink); font-variant-numeric: lining-nums tabular-nums; white-space: nowrap; }
.m-otab { overflow-x: auto; overscroll-behavior-x: contain; scrollbar-width: none; -ms-overflow-style: none; }
.m-otab::-webkit-scrollbar { width: 0; height: 0; display: none; }
#mApp .m-otab.m-sx, #mApp .m-otab.m-sx * { touch-action: pan-x pan-y; }
.m-otab table { border-collapse: separate; border-spacing: 0; min-width: 100%; font: 400 11.5px var(--font-sans); color: var(--m-ink); white-space: nowrap; }
.m-otab-card th { font: 400 10px var(--font-sans); letter-spacing: .04em; color: var(--m-faint); text-align: right; padding: 2px 9px 8px; border-bottom: 1px solid var(--m-line); background: var(--m-card); overflow: hidden; text-overflow: clip; }
.m-otab-card th.id, .m-otab-card th.prod, .m-otab td.id, .m-otab td.prod { text-align: left; }
.m-otab td { padding: 8px 9px; border-bottom: 1px solid var(--m-line); text-align: right; font-variant-numeric: lining-nums tabular-nums; }
.m-otab-card th:last-child, .m-otab td:last-child { padding-right: 14px; }
/* Дві перші колонки — номер і товар — прилипають зліва: при гортанні вбік
   завжди видно, чий це рядок. Номер має сталу ширину, товар стає за ним. */
.m-otab td.id, .m-otab-card th.id { position: sticky; left: 0; z-index: 2; background: var(--m-card); padding-left: 14px; color: var(--m-soft); width: 56px; min-width: 56px; max-width: 56px; box-sizing: border-box; }
.m-otab td.prod, .m-otab-card th.prod { position: sticky; left: 56px; z-index: 2; background: var(--m-card); box-shadow: 8px 0 10px -8px rgba(43, 35, 29, .12); }
.m-otab td.prod span { color: var(--m-ink); }
.m-otab td.prod i { display: inline-block; margin-left: 5px; padding: 1px 6px; border-radius: 999px; background: #F5EFE8; font: 500 10px/14px var(--font-sans); color: var(--m-soft); font-style: normal; vertical-align: 1px; }
.m-otab td.neg { color: #A9666A; }
.m-otab td.plus { color: #567A5E; }
.m-otab td.zero, .m-otab td.dash { color: var(--m-faint); }
.m-otab td.prof { font-weight: 500; }
.m-otab td.prof.pos { color: #567A5E; }
.m-otab td.prof.neg { color: #A9666A; }
.m-otab tr.nodata td { color: var(--m-faint); }
.m-otab tr.nodata td.prod span { color: var(--m-soft); }
.m-otab tr.total td { border-bottom: none; font-weight: 500; color: var(--m-ink); padding-top: 10px; padding-bottom: 4px; }
/* «Показати ще» — рядок на всю ширину таблиці, кнопка прилипає зліва разом із номером. */
.m-otab tr.more td { padding: 8px 0 8px 14px; border-bottom: 1px solid var(--m-line); text-align: left; position: sticky; left: 0; }
.m-otab-more { height: 32px; padding: 0 14px; border: none; border-radius: 999px; background: #F5EFE8; font: 500 12px var(--font-sans); color: var(--m-ink); cursor: pointer; }
.m-otab tr.total td.id { color: var(--m-ink); }
.m-otab-card .m-rc-note { margin: 8px 14px 0; }
/* Розклад у шторці — рядки чека без картки навколо. */
.m-rc-sheet { padding: 0 2px 26px; box-shadow: none; background: none; }
.m-rc-sheet .m-rc-row span small { display: block; font: 400 11px var(--font-sans); color: var(--m-faint); margin-top: 2px; }
.m-rc-sheet .m-rc-row.sum span small { color: var(--m-soft); font-weight: 400; }
/* Підпис у рядку чека може бути довгим — переносимо, сума лишається праворуч. */
.m-statp .m-rc-row span { min-width: 0; line-height: 1.35; }
.m-statp .m-rc-row b { flex: 0 0 auto; white-space: nowrap; }
.m-stat-made { margin-top: 8px; font: 400 11.5px var(--font-sans); color: var(--m-faint); }

/* Плашка синхронізації: результат запиту підсвічує підпис. */
.m-fsync.ok .m-fsync-t { color: #47694E; }
.m-fsync.fail .m-fsync-t { color: #9C4B45; }
/* Док на сторінці заявки ховається; кнопка дії стоїть на його місці. */
body.m-app #mApp.m-ebar ~ #mTabs, #mApp.m-ebar ~ #mTabs { opacity: 0; pointer-events: none; }

/* Шторка нової заявки: рядки — той самий вигляд, що пропозиції накладної
   (.m-rate), лише зі значком категорії в пісочній плитці замість радіо. */
.m-enrows { display: flex; flex-direction: column; gap: 8px; padding: 4px 0 10px; }
/* Натиск по рядку відчувається одразу: присідає помітніше за звичайну
   картку і темнішає під пальцем. */
#mApp .m-enrow.press { transform: scale(.965); background: #F4EDE3; }
.m-enrow:active { transform: scale(.965); background: #F4EDE3; }
.m-en-ic {
  width: 40px; height: 40px; flex: 0 0 auto; border-radius: 12px;
  background: var(--m-tint-2); color: var(--m-mute);
  display: grid; place-items: center;
}
.m-enrow .m-chev { color: var(--m-faint); flex: 0 0 auto; }
.m-en-go { margin: 6px 0 10px; }
.m-erows { display: flex; flex-direction: column; gap: 8px; padding: 4px 0 8px; }
.m-erow {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  min-height: 52px; padding: 8px 14px; border-radius: 14px; text-align: left;
  border: 1px solid #E7DAC9; background: #FFFDFA; color: #2B231D; font-weight: 500; font-size: 14px;
}
.m-eback { display: inline-flex; align-items: center; gap: 7px; border: none; background: none; padding: 4px 0 10px; color: #9C8B7C; font-weight: 400; font-size: 13px; }
.m-eform { display: flex; flex-direction: column; padding-bottom: 8px; }
.m-elbl { font-weight: 500; font-size: 10.5px; letter-spacing: .08em; text-transform: uppercase; color: #9C8B7C; margin: 12px 0 6px; }
.m-ein {
  width: 100%; box-sizing: border-box; height: 44px; padding: 0 13px;
  border: 1px solid #E7DAC9; border-radius: 13px; background: #FFFDFA;
  font-family: var(--font-sans); font-weight: 400; font-size: 15px; color: #2B231D; outline: none;
}
.m-eta { height: auto; padding: 11px 13px; resize: none; }
.m-echips { display: flex; gap: 7px; }
.m-echips-wrap { flex-wrap: wrap; }
.m-echoice {
  height: 36px; padding: 0 14px; border-radius: 999px;
  border: 1px solid #E7DAC9; background: #FFFDFA; color: #6B5C50; font-weight: 500; font-size: 13px; line-height: 1;
  transition: background .18s ease, color .18s ease, border-color .18s ease, transform .18s var(--m-pill);
}
.m-echoice.on { background: #2B231D; border-color: #2B231D; color: #F7F1EA; }
.m-echoice.bump { animation: m-chip-bump .62s cubic-bezier(.42, .5, .45, 1) both; }
/* Шторка видалення: текст і стовпчик кнопок — тиха згори, темна знизу. */
.m-edel-txt { font: 400 13.5px/1.55 var(--font-sans); color: var(--m-soft); padding: 2px 2px 8px; }
.m-edel-col { display: flex; flex-direction: column; gap: 8px; padding: 4px 0 8px; }
/* Рядок картки в кошику: поле-кнопка тягнеться, цифри вліво. */
.m-cbin-card { flex: 1 1 auto; width: auto; min-width: 0; text-align: left; }
.m-cbcard .m-cbn { flex: 0 0 auto; }
.m-epay-row { display: flex; gap: 8px; align-items: center; }
.m-epay-tg { flex: 0 0 auto; }
.m-epay-total { display: flex; justify-content: space-between; align-items: baseline; margin-top: 16px; padding-top: 12px; border-top: 1px dashed #EDE3D6; font-weight: 400; font-size: 13px; color: #6B5C50; }
.m-epay-total b { font-weight: 500; font-size: 17px; color: #2B231D; }

/* ─── Шторка перегляду транзакції фінансів (лише читання) ─── */
.m-ftxd { padding: 2px 0 6px; }
.m-ftxd-top { display: flex; align-items: center; gap: 12px; padding: 4px 0 14px; }
.m-ftxd-top .m-ftx-ic { width: 40px; height: 40px; border-radius: 13px; }
.m-ftxd-amt { font-weight: 600; font-size: 26px; letter-spacing: -.02em; color: #2B231D; line-height: 1.1; }
.m-ftxd-amt.pos { color: #47694E; }
.m-ftxd-sub { font-size: 12px; color: #98897B; margin-top: 3px; }
.m-ftxd-rows { border-top: 1px solid #F0E7DB; }
.m-ftxd-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 11px 0; border-bottom: 1px solid #F0E7DB; }
.m-ftxd-k { font-size: 12.5px; color: #98897B; flex: 0 0 auto; }
.m-ftxd-v { font-size: 13.5px; color: #2B231D; text-align: right; min-width: 0; overflow-wrap: anywhere; }
.m-ftxd .m-elbl { margin-top: 16px; }
.m-ftxd-rc { background: #FBF6EE; border: 1px solid #F0E7DB; border-radius: 14px; padding: 4px 12px; }
.m-ftxd-rcrow { display: flex; align-items: baseline; gap: 10px; padding: 9px 0; border-bottom: 1px dashed #EDE3D6; }
.m-ftxd-rcrow:last-child { border-bottom: none; }
.m-ftxd-rcn { flex: 1; min-width: 0; font-size: 13px; color: #2B231D; overflow-wrap: anywhere; }
.m-ftxd-rcq { flex: 0 0 auto; font-size: 12px; color: #98897B; }
.m-ftxd-rca { flex: 0 0 auto; font-size: 13px; color: #2B231D; }
.m-ftxd-rcfee { padding-top: 0; margin-top: -6px; border-bottom: 1px dashed #EDE3D6; }
.m-ftxd-rcfee .m-ftxd-rcn, .m-ftxd-rcfee .m-ftxd-rca { color: #98897B; font-size: 12px; }
.m-ftxd-rctot .m-ftxd-rcn, .m-ftxd-rctot .m-ftxd-rca { font-weight: 500; font-size: 13.5px; }
#mApp .m-ftx-row { cursor: pointer; transition: transform .14s ease; }
#mApp .m-ftx-row:active { transform: scale(.985); }

/* ─── Графік матеріалів (вкладка «Витрати» звіту) ─── */
.m-matc-card { position: relative; }
.m-adspop { overflow-y: auto; overscroll-behavior: contain; -webkit-overflow-scrolling: touch; }
.m-adspop.fx { position: fixed; z-index: 40; }
#mApp .m-adspop, #mApp .m-adspop * { touch-action: pan-y; }
.m-adsveil { z-index: 39; }
.m-adsc .ln.mat { stroke: #C98E6D; }
.m-adsc .ln.est { stroke-dasharray: 3 5; opacity: .55; }
.m-adsc .edge { stroke: var(--m-line); stroke-width: 1; stroke-dasharray: 2 4; }
.m-matc-card .m-adsc .pt { stroke: #C98E6D; }
.m-matc-card .m-adsc .pt.sel { fill: #C98E6D; }
.m-matc-card .m-adsc .pt.req { stroke: #6E93B4; r: 4.5; }
.m-matc-card .m-adsc .pt.req.sel { fill: #6E93B4; stroke: #FFFFFF; r: 6; }
.m-adsc text.cyc { font: 500 10px var(--font-sans); fill: #B4894F; }
.m-adsc .stem { stroke: #C98E6D; stroke-width: 2; stroke-linecap: round; opacity: .55; }
.m-adsc .brk { fill: none; stroke: #D9C2AE; stroke-width: 1; }
.m-adsc .gap { stroke: #C4625C; stroke-width: 3; stroke-linecap: round; }
.m-adsc text.gapt { font: 500 10px var(--font-sans); fill: #C4625C; }
.m-ads-st b.neg { color: #C4625C; }
.m-adsc text.buy { fill: var(--m-soft); font-weight: 500; }
.m-colr-dot { width: 11px; height: 11px; border-radius: 999px; flex: 0 0 auto; box-shadow: inset 0 0 0 1px rgba(43, 35, 29, .14); }
.m-adsrow i.ic, .m-adsdd i.ic { width: 14px; height: 14px; border-radius: 0; background: none; display: inline-flex; align-items: center; justify-content: center; color: var(--m-soft); }
.m-adsrow i.ic svg, .m-adsdd i.ic svg { width: 14px; height: 14px; transform: none; color: inherit; }
.m-adsrow i.ic svg, .m-adsdd i.ic svg { opacity: 1; }

/* ─── Фінанси: одна KPI-картка балансів ─── */
/* Три суми — в один рядок: трохи менший кегль, без переносу. */
.m-fkpi-row { flex-wrap: nowrap; gap: 6px 12px; min-width: 0; }
.m-fkpi .m-profit-n { font-size: 23px; white-space: nowrap; flex: 0 1 auto; min-width: 0; }
.m-fkpi .m-profit-n.uah { color: #6E5343; }
.m-fkpi .m-profit-n.wb { display: inline-flex; align-items: center; gap: 6px; color: var(--m-soft); margin-left: auto; }
.m-fkpi { position: relative; overflow: hidden; }
#mApp .m-fkpi[data-m] { cursor: pointer; transition: transform .16s var(--m-pill); }
#mApp .m-fkpi.press { transform: scale(.985); }
.m-fkpi-legend i { flex: 0 0 auto; width: 8px; height: 8px; }
.m-fkpi-btn svg { color: #6E5343; }
.m-fkpi-btn.busy { opacity: .6; }
/* Поки летить запит до Make — по картці йде світло, як у картки звіту. */
.m-fkpi::before {
  content: ''; position: absolute; inset: 0; z-index: 1; border-radius: inherit; pointer-events: none; opacity: 0;
  background: linear-gradient(115deg, rgba(255, 252, 247, 0) 20%, rgba(255, 252, 247, .85) 50%, rgba(255, 252, 247, 0) 80%);
  background-size: 260% 100%;
  transition: opacity .4s ease;
}
.m-fkpi.busy::before { animation: m-gen-breathe 2.6s ease-in-out infinite; }
.m-fkpi.pulse:not(.busy)::before { animation: m-gen-breathe 2.6s ease-in-out 1; }
@media (prefers-reduced-motion: reduce) { .m-fkpi.busy::before { animation: none; } }
.m-fkpi .m-profit-n.wb svg { width: 19px; height: 19px; color: #C9BBA9; }
/* Магазини — рівно у два рядки, без прокрутки. */
.m-fkpi-legend { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 9px 16px; align-items: center; }
.m-fkpi-legend span { display: flex; align-items: center; gap: 6px; min-width: 0; }
.m-fkpi-legend em { flex: 1 1 auto; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-style: normal; }
.m-fkpi-legend b { flex: 0 0 auto; white-space: nowrap; }
.m-fkpi-legend { margin-top: 12px; gap: 8px 14px; }
.m-fkpi-legend i { border-radius: 999px; }
.m-fkpi-legend b { font-weight: 500; color: var(--m-ink); }

/* ─── Шторка «+» у фінансах: вибір рахунку ─── */
.m-fnew-dd { position: relative; }
.m-fnew-ddb { width: 100%; max-width: none; height: 42px; padding: 0 12px; justify-content: flex-start; background: #F5EFE8; font: 400 14px var(--font-sans); border-radius: 12px; }
.m-fnew-ddb span { flex: 1 1 auto; text-align: left; }
.m-fnew-pop { left: 0; right: 0; top: 47px; min-width: 0; }

/* ─── Макет і проєкт руками (сторінка замовлення, адміністратор) ─── */
.m-lay .m-blk-h { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.m-lay .m-blk-s { font: 400 12px var(--font-sans); color: var(--m-faint); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.m-lay-row { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.m-lay-row .m-btn { flex: 1 1 auto; justify-content: center; }

/* ─── Хрестик «видалити накладну» в шапці блоку накладної ─── */
.m-inv-x { width: 26px; height: 26px; margin-left: 6px; border: none; border-radius: 999px; background: rgba(43, 35, 29, .06); color: var(--m-soft); display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto; }
.m-inv-x svg { width: 12px; height: 12px; }
#mApp .m-inv-x.press { transform: scale(.92); }
/* Позначка повторного відправлення на картці замовлення. */
.m-reship { padding: 1px 7px; border-radius: 999px; background: #EFE7DC; color: #8A6A44; font-size: 10.5px; }
/* Підпис пересилки під сумою на сторінці замовлення. */
.m-reship-tag { padding: 2px 9px; border-radius: 999px; background: #EFE7DC; color: #8A6A44; font-size: 11px; white-space: nowrap; }
/* Підзаголовок усередині розкладу звіту (напр. «Пересилки»). */
.m-rc-sub { margin: 14px 0 6px; font: 500 11px var(--font-sans); letter-spacing: .08em; text-transform: uppercase; color: var(--m-faint); }
