/* 02_shell.css — частина style.css, винесена без перестановки правил.
   Топбар, каркас застосунку, бічне меню, заголовки розділів, порожні
   стани й стани помилки, кнопки, чіпи, бейджі — спільне для всіх екранів.
   Порядок підключення в index.html повторює порядок частин:
   каскад від розділення не змінився (перевірено побайтно). */
/* ── Topbar ───────────────────────────────────────────────────────────── */
.topbar{
  position: sticky; top: 0; z-index: 40;
  height: var(--topbar-h);
  display: flex; align-items: center; gap: var(--sp-14);
  padding: 0 16px;
  background: var(--topbar-bg);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--border-soft);
}
.icon-btn{
  display: inline-flex; align-items: center; justify-content: center;
  width: 36px; height: 36px; border-radius: var(--radius-sm);
  background: transparent; border: 1px solid transparent; color: var(--text-dim);
  cursor: pointer; transition: var(--t-fast) var(--ease);
}
.icon-btn:hover{ background: var(--panel-2); color: var(--text); border-color: var(--border); }
.icon-btn > svg, .icon-btn .svg-ic{ width: 18px; height: 18px; }
.topbar-spacer{ flex: 1; }

.runs-chip{
  display: inline-flex; align-items: center; gap: var(--sp-8);
  padding: 6px 12px; border-radius: 999px;
  background: var(--panel); border: 1px solid var(--border); color: var(--text-dim);
  font: 600 var(--fs-12)/1 var(--sans); cursor: pointer;
  opacity: 0; transform: translateY(-2px);
  transition: opacity var(--t-med) var(--ease), transform var(--t-med) var(--ease), border-color var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}
.runs-chip.show{ opacity: 1; transform: none; }
.runs-chip:hover{ border-color: var(--border-hover); color: var(--text); background: var(--panel-2); }
.runs-chip .dot{
  width: 7px; height: 7px; border-radius: 50%; flex: none;
  background: var(--accent); box-shadow: 0 0 6px var(--accent);
  animation: pulse-dot 1.1s infinite ease-in-out;
}
.runs-chip.waiting .dot{ background: var(--warn); box-shadow: 0 0 6px var(--warn); }
.runs-chip .txt{ white-space: nowrap; max-width: 46vw; overflow: hidden; text-overflow: ellipsis; }
.runs-chip .cnt{ display: none; font: 700 var(--fs-11)/1 var(--mono); color: var(--text); }

@media (max-width: 640px){
  .runs-chip{ padding: 6px 9px; gap: var(--sp-6); }
  .runs-chip .txt{ display: none; }
  .runs-chip .cnt{ display: inline; }
}

.conn-pill{
  display: inline-flex; align-items: center; gap: 7px;
  padding: 6px 12px; border-radius: 999px;
  background: var(--panel); border: 1px solid var(--border);
  font: 600 var(--fs-11)/1 var(--sans);
  color: var(--text-dim);
}
/* Справне з'єднання не показуємо взагалі — див. коментар у index.html. */
.conn-pill.on{ display: none; }
.conn-pill.off{ color: var(--danger); background: rgba(229,72,77,.10); border-color: rgba(229,72,77,.30); }
.conn-pill .dot{ width: 7px; height: 7px; border-radius: 50%; background: var(--danger); }
.conn-pill.off .dot{ animation: pulse-dot 1.4s infinite; }
.conn-pill.on{ color: var(--ok); border-color: rgba(var(--ok-rgb),.3); }
.conn-pill.off{ color: var(--danger); border-color: rgba(var(--danger-rgb),.25); }
.conn-pill.off .dot{ background: var(--danger); }

.user-pill{
  display:flex; align-items:center; gap:var(--sp-8); padding:5px 12px 5px 6px;
  border-radius:999px; background:var(--panel); border:1px solid var(--border);
}
.user-pill .av{
  width:26px; height:26px; border-radius:50%; display:flex; align-items:center; justify-content:center;
  background: var(--grad-brand); font:700 var(--fs-11)/1 var(--sans); color:#fff;
}
.user-pill .un{ font:600 var(--fs-12)/1 var(--sans); color: var(--text-dim); }
.user-pill .logout-btn{
  border:none; background:none; color:var(--text-mute); cursor:pointer; font-size: var(--fs-12); padding:2px 4px;
}
.user-pill .logout-btn:hover{ color: var(--danger); }

/* ── Shell / layout ───────────────────────────────────────────────────── */
.scrim{
  position: fixed; top: 0; right: 0; bottom: 0; left: 0; z-index: 45;
  background: rgba(4,4,10,.6); -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px);
  opacity: 0; pointer-events: none; transition: opacity var(--t-med) var(--ease);
}
.scrim.show{ opacity: 1; pointer-events: auto; }

/* 🛑 --banner-h ОБОВʼЯЗКОВИЙ ДОДАНОК. Тут віднімалась сама шапка, а між
   нею й сценою може стояти смуга «жодної мережі не підключено». Виміряно:
   сцена починалась на 105px, віднімалось 56 — рейка виходила на 949 при
   вікні 900. Висоту віддає сам елемент живим розміром (onboarding.js,
   publishBannerHeight), бо на вузьких вікнах смуга переносить рядок і
   числом у CSS її не вгадати. */
.shell{
  display: flex;
  min-height: calc(100vh - var(--topbar-h) - var(--banner-h, 0px));
}

.nav{
  width: var(--nav-w); flex: none;
  padding: 8px 8px 16px;
  border-right: 1px solid var(--border-soft);
  background: var(--bg-soft);
  display: flex; flex-direction: column; gap: var(--sp-2);
  /* 🛑 ВИСОТУ РЕЙКИ ЗАДАЄ НЕ ТУТ. Справжнє правило — у ux_forms.css, у
     блоці @media (min-width: 861px), і там же полагоджено відрахунок
     смуги. Стеля, поставлена тут, не була обмежена шириною й підрізала
     мобільну шухляду до 666px замість її власних top/bottom-якорів.
     Список розділів має власний контейнер .nav-items з overflow:auto —
     він і забирає різницю. */
}
/* Desktop burger: collapse the sidebar entirely (mobile uses nav-open drawer
   instead — see the max-width:860px block below). */
@media (min-width: 861px){
  body.nav-collapsed .nav{ display: none; }
}
/* Радіус 12, а не --radius-sm. Концентричність: пункт лежить у рейці з
   відступом 4 від її внутрішнього краю, і 16 − 4 = 12. Кут, порахований
   на око, стирчить назовні — це і читається як неохайність. */
.nav-item{
  display: flex; align-items: center; gap: var(--sp-10);
  padding: 9px 10px; border-radius: var(--radius-sm);
  background: transparent; border: none; color: var(--text-dim);
  font: 500 var(--fs-13)/1 var(--sans); text-align: left; cursor: pointer;
  transition: var(--t-fast) var(--ease); position: relative;
}
.nav-item .ic{ width: 18px; height: 18px; flex: none; display:flex; align-items:center; justify-content:center; opacity:.75 }
.nav-item:hover{ background: var(--fill-1); color: var(--text); }
.nav-item:hover .ic{ opacity:1 }
/* 🛑 АКТИВНИЙ ПУНКТ БІЛЬШЕ НЕ БУРШТИНОВИЙ, І ЦЕ ГОЛОВНА ПРАВКА РЕЙКИ.
   Було: бурштиновий градієнт, бурштинова внутрішня рамка й бурштинова
   смужка збоку — три бурштинові предмети на один пункт.

   Правило «один бурштин на екран» через це порушувалось завжди: у
   застосунку бурштин означає «дія, яка щось коштує», і поки ним світився
   пункт меню, кнопка «Створити» за 111 кредитів мусила змагатися з
   написом «Чат» за ту саму увагу.

   Прийом із п'ятипунктової рейки, де активний пункт фарбують акцентом,
   тут не працює ще й арифметично: у нас 12 пунктів у 4 групах, і кольору
   на такій кількості око не читає. Читає ЯСКРАВІСТЬ — біліший текст,
   непрозоріший значок і на щабель щільніша заливка. */
.nav-item.active{
  color: var(--text);
  background: var(--fill-2);
  font-weight: 600;
}
.nav-item.active .ic{ opacity:1 }
.nav-item .badge-count{
  /* Solid ink, not the full gradient — restraint pass: the active nav item
     right next to it is already the gradient "signature", a second rainbow
     fill on its badge read as noisy. */
  /* Лічильник теж перестав бути бурштиновим: непрочитане — це не дія, за
     яку платять. Заливка третього щабля плюс звичайний текст. */
  margin-left: auto; flex: none; min-width: 18px; height: 18px; padding: 0 5px;
  border-radius: 999px; background: var(--fill-3); color: var(--text);
  font: 600 var(--fs-10)/18px var(--mono); text-align: center; display: none;
}
.nav-item .badge-count.show{ display: inline-block; }

/* ── ДУГА ПОСТУПУ В ПІДВАЛІ РЕЙКИ ────────────────────────────────────────
   Рівень 1 онбордингу: тихий, постійний, коштує нуль рядків сцени.
   `margin-top:auto` притискає його до низу рейки — це підвал, а не ще
   один пункт меню, і плутати їх не можна.

   Кільце малюється `conic-gradient` по змінній `--p` (відсоток), без SVG:
   один елемент, жодного скрипта на перемальовку, і воно ділить радіус із
   рештою круглих предметів застосунку. */
/* 🛑 ПРЕДМЕТ НЕСЕ ЗАВДАННЯ, А НЕ ЗНАЧОК. Було: --fill-1 на --fill-1 рейці,
   тобто той самий колір — предмет не існував, поки не наведеш. Для єдиної
   речі, яка стоїть між новою людиною й працюючим продуктом, це замало.
   Тепер він має власну поверхню, теплу рамку й лівий бурштиновий корінець:
   у рейці, де все решта — рівний список, цього досить, щоб око зачепилось,
   і не досить, щоб кричати. */
.onb-arc{
  /* Прилипає до низу рейки, що прокручується: завдання не має їхати геть
     разом зі списком розділів. Фон мусить бути НЕПРОЗОРИМ, інакше пункти
     меню просвічуватимуть крізь нього — тому бурштин кладеться шаром
     поверх власного кольору рейки, а не сам по собі. */
  position: sticky; bottom: 0; z-index: 1;
  background:
    linear-gradient(var(--fill-accent), var(--fill-accent)),
    var(--bg-soft);
  margin-top: auto; display: flex; align-items: center; gap: var(--sp-8);
  padding: 10px 12px; border-radius: var(--radius-sm); cursor: pointer;
  border: 1px solid var(--border-warm);
  border-left: 2px solid var(--accent);
  color: var(--text-dim); text-align: left;
  transition: background var(--t-fast) var(--ease),
              border-color var(--t-fast) var(--ease);
}
.onb-arc:hover{
  background:
    linear-gradient(var(--accent-wash-3), var(--accent-wash-3)),
    var(--bg-soft);
  border-color: var(--accent); color: var(--text);
}
/* Лишились самі необовʼязкові кроки — це вже не «налаштуйте», а «можна
   спробувати». Бурштин звідси йде: він належить ціні й головній дії, а
   пропозиція спробувати не є ні тим, ні тим. */
.onb-arc-soft{
  background: linear-gradient(var(--fill-1), var(--fill-1)), var(--bg-soft);
  border-color: var(--border); border-left-color: var(--border-hover);
}
.onb-arc-soft:hover{
  background: linear-gradient(var(--fill-2), var(--fill-2)), var(--bg-soft);
  border-color: var(--border-hover);
}
/* 🛑 СЕРЕДИНА КІЛЬЦЯ — СПРАВЖНІЙ ОТВІР, А НЕ КРУЖОК ЗВЕРХУ. Раніше центр
   затулявся `::before` кольору --bg-soft, і коментар поруч запевняв, що
   «маска дорожча, а результат той самий». Результат той самий рівно доти,
   доки під кільцем саме --bg-soft. Щойно предмет отримав власну (до того ж
   НАПІВПРОЗОРУ) підкладку, сірий кружок став видно як чужу пляму — і
   жодним суцільним значенням це не лікується: напівпрозорий фон не
   відтворити непрозорим. Маска вирізає діру, крізь яку видно те, що там
   є насправді, хоч би що це було. */
.oa-ring{
  position: relative; flex: none; width: 26px; height: 26px;
  display: grid; place-items: center;
}
.oa-ring::before{
  content: ""; position: absolute; inset: 0; border-radius: 50%;
  background: conic-gradient(var(--accent) calc(var(--p) * 1%), var(--fill-3) 0);
  -webkit-mask: radial-gradient(closest-side, transparent 71%, #000 72%);
          mask: radial-gradient(closest-side, transparent 71%, #000 72%);
}
.onb-arc-soft .oa-ring::before{
  background: conic-gradient(var(--text-mute) calc(var(--p) * 1%), var(--fill-3) 0);
}
.oa-ring b{
  position: relative; font: 700 var(--fs-11)/1 var(--mono); color: var(--text);
}
.oa-txt{ display: flex; flex-direction: column; gap: var(--sp-2); min-width: 0; flex: 1 }
/* Назва дії може не влізти в 232px рейки — обрізаємо її, а не переносимо:
   двоярусний підвал стрибає щоразу, коли міняється крок. */
.oa-txt b{
  font: 600 var(--fs-12)/1.25 var(--sans); color: var(--text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.oa-txt i{ font: 400 var(--fs-11)/1 var(--sans); font-style: normal; color: var(--text-mute) }
/* .nav-foot (рядок версії) прибрано 2026-08-09 — див. nav.js. */

/* Поки картка згоди на екрані, сцена відступає рівно на її висоту —
   змінну виставляє сам consent.js із живого розміру елемента. */
/* Картка згоди стоїть ПРАВОРУЧ ВІД РЕЙКИ, а не в самому куті: рейка
   228px, картка 380 — у куті вона накривала навігацію цілком разом із
   нижніми пунктами, тобто ховала спосіб піти геть зі сторінки, на якій
   щось просить. */
:root{ --consent-x: 228px }
@media (max-width: 900px){ :root{ --consent-x: 0px } }
body.has-consent .workspace{ padding-bottom: calc(60px + var(--consent-h, 0px)) }
.workspace{
  flex: 1; min-width: 0; padding: 26px 30px 60px;
}

.view{ display: none; animation: fadein var(--t-med) var(--ease); }
.view.active{ display: block; }
@keyframes fadein{ from{ opacity: 0; transform: translateY(4px);} to{ opacity:1; transform:none; } }

/* Заголовок розділу. Було 15px — тобто на два кроки більше за основний
   текст, і розділ не читався як розділ. 21px із трекінгом −.02em: у Inter
   без корекції великий кегль розсипається, і саме це відрізняє «дорого» від
   «як вийшло» — усі шість конкурентів тиснуть від −.02 до −.05em. */
.shead{
  display:flex; align-items: baseline; gap: var(--sp-10);
  font: 700 21px/1.25 var(--sans); color: var(--text); letter-spacing: -.02em;
  margin: 32px 0 16px;
}
.shead:first-child{ margin-top: 0; }
.shead .n{ font: 500 var(--fs-12)/1 var(--sans); color: var(--text-mute); }

/* ── ФОРМУ ТРИМАЄ ЗАЛИВКА, А НЕ РАМКА ───────────────────────────────────
   Виміряно на живому застосунку: 202 елементи з рамками в одному кадрі
   (72 кнопки, 14 панелей, 9 полів, 8 значків…). Рамка на кожному предметі
   і є той «дешевий вигляд», з якого починається дизайн-код: сітка ліній
   поверх усього, де кожна лінія однаково гучна, а отже жодна нічого не
   означає.

   `--panel` уже відрізняється від тла — рамка навколо нього повторювала
   те, що заливка вже сказала. Лінія лишається рівно там, де вона РОЗДІЛЯЄ:
   між рядками таблиці, під шапкою, на оправі сцени. */
.panel{
  background: var(--panel); border: 0;
  border-radius: var(--radius); padding: 16px;
}
/* Plain-text loading/error/empty placeholder used inline across ~20 JS
   modules (grids, lists, panels) — was bare centered gray text with no
   chrome; now the same dashed-card treatment as .cmp-media-empty so it
   reads as a designed placeholder instead of "something didn't render". */
.empty{
  color: var(--text-mute); font: 500 var(--fs-12)/1.5 var(--sans); text-align: center;
  padding: 20px 16px; border: 1.5px dashed var(--border-soft); border-radius: var(--radius-sm);
  background: var(--bg-soft);
}

/* ── ОЧІКУВАННЯ: КРОКИ, А НЕ КРУТИЛКА ───────────────────────────────────
   Дизайн-код: очікування називають кроками з часом, що лишився. Причина не
   в красі. Крутилка повідомляє рівно один біт — «щось відбувається», — і
   робить це однаково на другій секунді й на сороковій. Людина, яка щойно
   натиснула кнопку за 111 кредитів, з цього біта не може зрозуміти
   головного: воно ще працює чи вже зависло.

   Три рядки замість кола: який крок іде, котрий він із скількох, скільки
   лишилось. Смуга поступу визначена, коли кроки відомі, і невизначена
   (пробіжка) лише тоді, коли їх справді не знаємо — тобто рідко.

   Дрібні крутилки в 12px поруч із написом лишаються: там колесо не
   ЗАМІНЯЄ повідомлення, а стоїть біля нього. */
.wait{
  display: flex; flex-direction: column; align-items: center; gap: var(--sp-10);
  max-width: 460px; margin: 40px auto; text-align: center;
}
.wait-now{ font: 700 var(--fs-15)/1.3 var(--sans); color: var(--text); }
.wait-meta{ font: 500 var(--fs-12)/1.4 var(--sans); color: var(--text-mute); }
.wait-meta b{ font-weight: 700; color: var(--text-dim); font-variant-numeric: tabular-nums; }
.wait-line{
  width: 100%; height: 4px; border-radius: 999px;
  background: var(--fill-1); overflow: hidden; position: relative;
}
.wait-line i{
  display: block; height: 100%; border-radius: inherit;
  background: var(--accent-solid);
  width: var(--p, 0%); transition: width .4s var(--ease);
}
/* Невизначений стан — пробіжка. Свідомо НЕ схожа на визначену смугу: вона
   коротка й їде наскрізь, а не наповнює. Інакше людина читає її як поступ
   і чекає, коли «дійде до кінця». */
.wait-line.indet i{
  width: 34%; animation: waitRun 1.15s cubic-bezier(.65,0,.35,1) infinite;
}
@keyframes waitRun{
  0%{ transform: translateX(-105%) } 100%{ transform: translateX(310%) }
}
.wait-steps{
  display: flex; align-items: center; gap: var(--sp-6); flex-wrap: wrap;
  justify-content: center; font: 500 var(--fs-11)/1 var(--sans); color: var(--text-mute);
}
.wait-steps span{ display: inline-flex; align-items: center; gap: 5px; }
.wait-steps span::before{
  content: ""; width: 6px; height: 6px; border-radius: 50%;
  background: var(--fill-3);
}
.wait-steps .done::before{ background: var(--step-done, var(--text-mute)); }
.wait-steps .now{ color: var(--text); font-weight: 700; }
.wait-steps .now::before{
  background: var(--accent-solid);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent-solid) 22%, transparent);
}
@media (prefers-reduced-motion: reduce){
  .wait-line.indet i{ animation: none; width: 100%; opacity: .5 }
}

/* ── Empty state (reusable — see SocialOS.UI.renderEmptyState) ──────────── */
.empty-state{
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--sp-8); text-align: center; padding: 34px 16px; color: var(--text-mute);
}
.empty-state .es-icon{ font-size: 30px; opacity: .8; margin-bottom: 2px; }
.empty-state .es-text{ font: 500 var(--fs-13)/1.5 var(--sans); color: var(--text-dim); max-width: 340px; }
.empty-state .es-action{ margin-top: 6px; }

/* Стан помилки — той самий каркас, що й порожній стан, але видимо інший.
   Різниця між «даних немає» і «не зміг спитати» мусить читатись із
   відстані, а не лише з формулювання: рамка й значок кольору --danger. */
.empty-state.error-state{
  border: 1px solid var(--danger); border-radius: var(--radius);
  background: var(--panel); margin: 4px 0;
}
.empty-state.error-state .es-icon{ color: var(--danger); }
.empty-state.error-state .es-text{ color: var(--text); font-weight: 600; }

/* ── Кнопки: ЄДИНЕ визначення в продукті ────────────────────────────────
   Усі значення приходять токенами з core/01_base.css (блок «КЕРУВАННЯ:
   ТОКЕНИ КОМПОНЕНТА»). Тут описано лише УСТРІЙ кнопки — що з чого
   складається; чим саме її пофарбовано, вирішує той блок.

   🛑 НЕ ДОДАВАЙТЕ сюди чисел і кольорів. Якщо треба інший відтінок чи
   висота — правиться токен, і зміна розходиться по всьому застосунку
   одразу. Саме заради цього тут немає жодного hex.

   🛑 І НЕ ПЕРЕОГОЛОШУЙТЕ `.btn` в інших файлах. Так уже було: skin.css
   і 02_shell.css описували кнопку кожен по-своєму (36px проти 38px,
   градієнт проти суцільної заливки), вигравав останній завантажений, і
   правка кольору вимагала обходу трьох файлів.

   Виняток, який лишається законним, — ui_motion.css: він додає кнопці
   ГЛИБИНУ (тіні, перелив, зсув під натиском), а не колір і не розмір.
   Це окремий шар, і він теж бере кольори з токенів. */
.btn{
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  box-sizing: border-box; cursor: pointer;
  height: var(--ctl-h); padding: 0 var(--ctl-pad);
  border: 1px solid transparent; border-radius: var(--ctl-radius);
  background: var(--btn-bg); color: var(--btn-fg);
  font: 600 var(--fs-13)/normal var(--sans); letter-spacing: var(--ctl-tracking);
  transition: var(--t-fast) var(--ease);
}
/* Наведення — щабель заливки, а не інший колір рамки: рух яскравості
   помітніший за зміну тону лінії в 1px, і не вимагає самої лінії. */
.btn:hover{ background: var(--btn-bg-hover); border-color: transparent; }
.btn:active:not(:disabled){ transform: scale(.97); }
.btn:disabled{ opacity: .5; cursor: not-allowed; }

.btn-sm{
  height: var(--ctl-h-sm); padding: 0 var(--ctl-pad-sm);
  font-size: var(--fs-12); border-radius: var(--ctl-radius-sm);
}

/* Головна дія — суцільний колір. Градієнт на кнопці — найшвидший спосіб
   зробити інтерфейс схожим на шаблон: він обіцяє святковість там, де
   людина натискає «витратити гроші». */
.btn-primary{
  background: var(--btn-primary-bg); background-image: none;
  color: var(--btn-primary-fg); border-color: transparent;
}
.btn-primary:hover{ background: var(--btn-primary-bg-hover); filter: none; }
.btn-primary:active:not(:disabled){
  background: var(--btn-primary-bg-active); color: var(--btn-primary-fg-active);
}

/* М'яка головна — дія за акцентом, яка не мусить кричати: тепла підкладка
   й бурштиновий текст замість суцільної заливки. Публічне ім'я потрібне
   тому, що таких кнопок у застосунку виміряно 37, і кожна була описана
   окремим правилом під власним id — тобто одну й ту саму кнопку продукт
   винаходив тридцять сім разів. */
.btn-soft{ background: var(--btn-soft-bg); color: var(--btn-soft-fg); border-color: transparent; }
.btn-soft:hover{ background: var(--accent-edge); }

.btn-ghost{ background: transparent; }
.btn-ghost:hover{ background: var(--fill-1); }

.btn-danger{ color: var(--btn-danger-fg); background: var(--btn-danger-bg); border-color: transparent; }
.btn-danger:hover{ background: var(--btn-danger-bg-hover); }

.btn-outline, .btn-accent{
  background: var(--btn-accent-bg); color: var(--btn-accent-fg); border-color: transparent;
}

/* ── Chip (pill filter/toggle) ────────────────────────────────────────────
   Shared geometry for every filter-chip / switch group in the app: .lib-tab,
   .ib-chip, .gal-tab, .kind-btn (add "chip" alongside the specific class),
   plus .net-toggle and .st-aspect-btn which keep their own class but mirror
   this same box model directly (asymmetric icon padding / mono digits need
   their own rule, so they're not literally tagged .chip in markup).
   line-height is "normal" (NOT 1) so a leading emoji centers against the
   text instead of sitting off-baseline. */
/* ── ЧИП: ЄДИНЕ визначення в продукті ───────────────────────────────────
   Значення — токенами з core/01_base.css. Тут лише устрій.

   🛑 НЕ ПЕРЕОГОЛОШУЙТЕ `.chip` в інших файлах: так уже було зі skin.css,
   і правило працювало не там, де його шукали. Треба інший вигляд — є
   токен. */
.chip{
  display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-6);
  box-sizing: border-box; cursor: pointer;
  height: var(--chip-h); padding: 0 var(--chip-pad);
  border: 1px solid transparent; border-radius: var(--chip-radius);
  background: var(--chip-bg); color: var(--chip-fg);
  font: var(--chip-font);
  transition: var(--t-fast) var(--ease);
}
.chip:hover{ background: var(--chip-bg-hover); color: var(--chip-fg-hover); border-color: transparent; }
.chip.active{
  background: var(--chip-active-bg); color: var(--chip-active-fg);
  border-color: transparent; box-shadow: none;
}
.chip:active{ transform: scale(.96); }

/* ── Badges ───────────────────────────────────────────────────────────── */
.badge{
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px 9px; border-radius: 999px;
  font: 700 var(--fs-11)/1.4 var(--sans);
  background: var(--fill-1); border: 0; color: var(--text-dim);
}
/* Усі числа тут були зафіксовані рукою й розійшлися з токенами: .08 від
   старого зеленого, .3 від старого бурштину, і — найгірше — rgba(238,42,123)
   у `.badge-ig`, тобто рожевий Instagram, вписаний числом уже після того,
   як бренд став бурштиновим. `color-mix` бере колір із самого токена, тож
   розійтись більше нема з чим. */
/* 🛑 БЕЙДЖ «УСЕ ГАРАЗД» БІЛЬШЕ НЕ ЗЕЛЕНИЙ.
   Дві причини, і друга важливіша за першу.

   Перша: база застосунку тепла (тон 60-85), і зелений на ній —
   єдиний холодний тон, тобто стороння пляма незалежно від сенсу.

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

   Нормальний стан тепер читається як текст. --danger і --warn свій
   колір лишають: там колір несе сенс. */
.badge-ok{ color: var(--text-dim); background: var(--fill-1); }
.badge-warn{ color: var(--warn); background: color-mix(in srgb, var(--warn) 14%, transparent); }
.badge-danger{ color: var(--danger); background: color-mix(in srgb, var(--danger) 14%, transparent); }
.badge-ig{ color: var(--brand-ink); background: color-mix(in srgb, var(--brand-ink) 14%, transparent); }
.badge-li{ color: var(--li-soft); background: color-mix(in srgb, var(--li-soft) 16%, transparent); }
.badge > svg{ width: 13px; height: 13px; display: block; flex: none; }


/* ── Смуга перевтілення ──────────────────────────────────────────────────
   Власник сервісу дивиться застосунок очима клієнта. Стан, а не сповіщення:
   він триває, поки його не завершать, тому смуга не закривається хрестиком
   і не зникає сама — єдиний вихід із неї веде назад до себе.

   Колір узятий небезпечний (danger), а не бурштиновий: бурштин у цьому
   застосунку означає ДІЮ, і смуга, пофарбована ним, читалася б як щось,
   що треба натиснути. Тут же треба не натиснути, а памʼятати. */
.imp-bar{
  position:sticky; top:0; z-index:60;
  display:flex; align-items:center; justify-content:center; gap:14px;
  padding:9px 16px;
  /* 🛑 Суцільний колір, а не токен --btn-danger-bg.
     Той токен — заливка КНОПКИ: напівпрозорий вимив у 14%, розрахований
     лежати на картці. Виміряно на живій сторінці: текст на ньому давав
     контраст 4.28 при нормі 4.5, тобто смуга, яку не можна проґавити,
     читалася гірше за звичайний абзац. Тут потрібне зворотне — поверхня,
     що сама себе оголошує. Один committed вигляд на обидві теми: стан
     рідкісний, і «делікатний» він бути не повинен. */
  background:#7f1d1d;
  color:#fff5f5;
  font-size:13px; letter-spacing:var(--ctl-tracking, 0);
}
.imp-bar[hidden]{ display:none }
.imp-txt b{ font-weight:600 }
.imp-out{
  height:var(--ctl-h-sm, 28px); padding:0 var(--ctl-pad-sm, 12px);
  border:1px solid currentColor; border-radius:var(--ctl-radius-sm, 9px);
  background:transparent; color:inherit; font:inherit; cursor:pointer;
}
.imp-out:hover{ background:color-mix(in srgb, currentColor 14%, transparent) }

/* ── ГОСТЬОВИЙ ОГЛЯД ────────────────────────────────────────────────────
   Смуга внизу, а не вгорі: угорі стоїть навігація застосунку, і банер там
   зсував би весь інтерфейс — гість бачив би не продукт, а продукт із
   наліпкою. Знизу вона помітна, але не перебиває те, заради чого прийшли. */
.gst-bar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 60;
  display: flex; gap: 16px; align-items: center; justify-content: center;
  flex-wrap: wrap;
  padding: 10px 16px; font-size: 13px;
  background: var(--panel); border-top: 1px solid var(--border);
  color: var(--text-mute);
}
.gst-bar a { color: var(--accent-solid, var(--accent)); font-weight: 600; }
body.has-gst-bar { padding-bottom: 46px; }

.gst-veil {
  position: fixed; inset: 0; z-index: 200;
  display: flex; align-items: center; justify-content: center;
  padding: 20px; background: rgba(0, 0, 0, .55);
}
.gst-card {
  width: min(460px, 100%); background: var(--panel);
  border: 1px solid var(--border); border-radius: 14px;
  padding: 24px 24px 20px; box-shadow: var(--card-shadow, 0 20px 60px rgba(0,0,0,.4));
}
.gst-card h2 { margin: 0 0 10px; font-size: 20px; }
.gst-what { margin: 0 0 6px; font-size: 14px; color: var(--text); }
.gst-sub { margin: 0 0 18px; font-size: 13px; color: var(--text-mute); line-height: 1.55; }
.gst-acts { display: flex; gap: 10px; flex-wrap: wrap; }

@media (max-width: 560px) {
  .gst-bar { font-size: 12px; gap: 10px; }
  .gst-acts .btn { flex: 1 1 auto; justify-content: center; }
}
