/* 01_base.css — частина style.css, винесена без перестановки правил.
   Змінні, теми, шрифти, скидання, фокус, іконки, анімації, підняття карток.
   Порядок підключення в index.html повторює порядок частин:
   каскад від розділення не змінився (перевірено побайтно). */
/* ==========================================================================
   SocialOS — theme + layout + components
   Dark, modern. Accent = Instagram-ish purple/pink/orange gradient (brand /
   primary actions) blended with a cool LinkedIn blue used for secondary
   accents and platform badges. Fresh design — not a copy of AIOS_Dashboard.
   ========================================================================== */

/* Inter + JetBrains Mono are vendored locally — see vendor/fonts.css, linked
   in index.html before this stylesheet. WKWebView (Tauri, macOS) does not
   reliably resolve a remote Google Fonts @import. */

:root{
  /* RGB-компаньйони для rgba(). color-mix() з'явився лише в Safari 16.2
     (macOS 13), а на старшому WebKit таке ОГОЛОШЕННЯ ПРОСТО ВІДКИДАЄТЬСЯ —
     тобто зникає рамка/тінь/фон, а не «трохи інший відтінок».
     rgba(var(--x-rgb), .55) дає той самий піксель і працює скрізь. */
  --ig-2-rgb: 238, 42, 123;
  /* Бурштин — наш акцент. RGB-компаньйон тут із тієї ж причини, що й решта
     (див. коментар вище): rgba(var(--accent-rgb), .18) працює скрізь. */
  --accent-rgb: 240, 165, 0;
  --brand-ink-rgb: 240, 165, 0;
  --li-soft-rgb: 59, 143, 224;
  --bg-soft-rgb: 22, 18, 15;
  --bg-rgb: 17, 15, 12;
  --info-rgb: 92, 155, 240;

  /* Native widgets (date/time pickers, scrollbars, <select>) follow the app's
     dark theme instead of the OS setting — inputs otherwise pop up light. */
  color-scheme: dark;

  /* 🛑 БАЗА ТЕПЛА, І ЦЕ НЕ СМАК — ЦЕ ВИМІР.
     Тло було oklch(0.169 0.0065 271) — холодний синій. Бурштин акценту
     oklch(0.775 0.163 76) — теплий. Двісті десять градусів між ними, тобто
     протилежні боки кола: холодне тло й теплий акцент сперечались, і саме
     через це бурштин виглядав чужим на власному екрані.

     Цю саму пастку сайт пройшов раніше й записав у свій дизайн-код
     (docs/DESIGN_SITE.md §2): там базу перевели на тон 60, і акцент став
     своїм. Тут те саме: тон 62-72, СВІТЛОТА Й НАСИЧЕНІСТЬ НЕ ЗМІНЕНІ.
     Це важливо — усі перевірки контрасту спираються на світлоту, тож зсув
     тону їх не зачіпає й переперевіряти нічого не треба.

     Тепер застосунок і сайт стоять на одному тоні: спільна база, спільний
     бурштин. Різними лишаються густина, кремовий матеріал (його в приладі
     немає) і засічковий шрифт заголовків — це різниця між вітриною і
     верстатом, а не між двома продуктами. */
  --bg: #110f0c;
  --bg-soft: #16120f;
  --panel: #1b1713;
  --panel-2: #211c18;
  --elevated: #28241f;
  /* 🛑 Ці три токени жили ДВІЧІ — тут і в skin.css, який вантажиться
     останнім і мовчки вигравав. Тут стояло суцільне #2f2a26, у skin.css —
     напівпрозоре; у світлій темі розходились ще й заливки (.042 проти
     .045). Тобто правка теми в «файлі теми» не робила нічого, і причину
     цього не було видно ні з одного з двох файлів.

     Тепер оголошення тут одне, і воно ж чинне. Значення взято те, що
     справді працювало: напівпрозора лінія дає ту саму межу, але зникає
     там, де фон світліший, і не малює сітку з коробок — суцільна сіра
     рамка на темному фоні читалась як обведення приладу. */
  --border: rgba(255,255,255,.075);
  --border-soft: rgba(255,255,255,.045);
  /* FIX: this was self-referencing (var(--border-hover) inside its own
     declaration is invalid → the property computed to nothing), so every
     .btn/.chip/.tile/.card hover in dark mode silently had no border
     highlight. Real value now — one step lighter than --border. */
  --border-hover: rgba(255,255,255,.17);

  --text: #f6f4f1;
  --text-dim: #a8a49f;
  --text-mute: #83807b;

  /* Solid brand ink for icon strokes on soft-tinted chips/tiles (a gradient
     can't stroke an SVG, so we use one accent that reads in both themes). */
  --brand-ink: var(--accent);
  /* Текст поверх заливки --brand-ink. У темній темі брендовий рожевий
     СВІТЛИЙ (#ff5f9e), тож білий текст на ньому дає контраст 2.8 при нормі
     4.5 — виміряно, не на око. Темний текст на тій самій заливці дає 6.6 і
     виглядає навмисним акцентом. У світлій темі рожевий темний, і білий
     текст там правильний. Один токен замість 13 місць із color:#fff. */
  --on-brand: #180f09;

  /* ── Акцент ────────────────────────────────────────────────────────────
     БУРШТИН, і це рішення, а не смак. Раніше акцентом був #ee2a7b —
     середній колір градієнта Instagram, тобто ми фарбувались у колір
     платформи, яку обслуговуємо: продукт у кольорі платформи читається як
     плагін до неї, а не як система над нею. Для мультимережевого B2B
     (IG + LinkedIn + TikTok + Facebook) це ще й фактично неправда.

     Чому саме бурштин: у сегменті зайняті синій (Vista Social, fal),
     фіолетовий (Creatify, Postiz) і кислотний лайм (Higgsfield) — виміряно
     2026-08-05, див. 11_Dyzain_konkurentiv. Бурштин вільний і читається як
     ПРИЛАД, а не як застосунок; це збігається з тим, чим продукт є —
     пультом, де кожна кнопка має ціну.

     Контраст (виміряно, не на око): #f0a500 на --bg дає 8.9, темний текст
     на бурштиновій заливці — 11.2. Тому --on-brand лишається темним. */
  --accent: #f0a500;
  --accent-hi: #ffc861;      /* світліший — ховер, верхня точка градієнта */
  --accent-deep: #c97f00;    /* темніший — натиснутий стан, нижня точка */

  --ig-1: #f9ce34;
  --ig-2: #ee2a7b;
  --ig-3: #6228d7;
  --li: #0a66c2;
  --li-soft: #3b8fe0;

  /* ── ПОСИЛАННЯ ─────────────────────────────────────────────────────
     🛑 Синім посиланням у застосунку був `--li-soft`, тобто пом'якшений
     синій LinkedIn. Сім місць: постійне посилання поста, дозиконтакту в
     досьє, permalink у модалці, підказка про мережі, посилання в картці
     задачі, галочка згоди, посилання в аналітиці.

     Це та сама помилка, що й з рожевим у графіку, лише навпаки: колір
     платформи витрачено на змісти, які до платформи не належать. Посилання
     на пост у LinkedIn і посилання на пост в Instagram фарбувались
     однаково синім — тобто колір не позначав нічого, а брехав.

     Окремий токен, а не `--accent`: бурштин у приладі означає «дія, яка
     щось коштує», і фарбувати ним звичайне посилання означало б розмити
     єдиний акцент. Тепла вохра сусідить із бурштином, але тихіша за нього.
     Контраст 5.9 на --panel у темній темі, 5.4 у світлій. */
  --link: #c9a227;

  --grad-brand: linear-gradient(135deg, #ffc861 0%, #f0a500 55%, #d97706 100%);
  /* 🛑 Числа замінено на токени. Трійки 255,200,97 / 240,165,0 /
     217,119,6 — це --accent-hi, --accent-solid і --accent-deep,
     виписані руками. Поки вони числа, зміна бурштину в продукті їх не
     зачіпає: рівно так рожевий колись повертався в застосунок після
     того, як токен уже був виправлений. */
  --grad-brand-soft: linear-gradient(135deg,
    color-mix(in srgb, var(--accent-hi) 16%, transparent) 0%,
    var(--accent-wash-3) 55%,
    color-mix(in srgb, var(--accent-deep) 16%, transparent) 100%);
  /* Градієнт Instagram лишається — але тепер лише там, де йдеться САМЕ про
     Instagram (іконка мережі, чип акаунта), а не як наш бренд. */
  --grad-ig: linear-gradient(135deg, #6228d7 0%, #ee2a7b 55%, #f9ce34 100%);
  --grad-li: linear-gradient(135deg, #0a66c2 0%, #3b8fe0 100%);

  /* ── КОЛЬОРИ СЕРІЙ ГРАФІКА ─────────────────────────────────────────
     🛑 Тут була діра, і вона коштувала головного графіка продукту.
     Серії аналітики брали кольори з платформених токенів: підписники
     малювались `--ig-2` (рожевий Instagram), охоплення — `--li-soft`
     (синій LinkedIn), ER — `--ok` (зелений «успіх»), пости — `--ig-1`.

     Дизайн-код дозволяє кольори платформ РІВНО там, де колір означає саме
     цю мережу: значок мережі, смуга порівняння. Крива «підписники» у
     зведеному вигляді не означає Instagram — вона означає підписників.
     Тому екран «Разом» малювався рожевим, тобто кольором бренду, від
     якого ми відмовились, і ще й зеленим «успіхом» там, де успіху ніхто
     не обіцяв.

     Рампа одного тону: бурштин на головну серію, далі теплі сірі. Одна
     серія на екрані за раз (вкладки Підписники/Охоплення/ER/Пости), тож
     колір там не несе інформації взагалі — інформацію несе вкладка.
     Кілька кольорів потрібні лише смузі залученості, де чотири частки
     стоять поруч. */
  --chart-1: #f0a500;
  --chart-2: #8a8f99;
  --chart-3: #5c626d;
  --chart-4: #3d424b;

  --ok: #34d17f;
  /* Відсунуто від бурштину у бік кіноварі. Було #eab04a — тобто той самий
     колір, що новий акцент; попередження, невідрізниме від бренду, це
     попередження, якого не видно. Контраст на --bg: 6.8. */
  --warn: #ff7a45;
  /* Було #f2556b — рожевувата малина. Поруч із бурштином вона читається як
     відтінок бренду, а не як аварія; #e5484d відсунутий у бік чистого
     червоного й лишає між собою і --warn помітний розрив. Це один із двох
     токенів, які запросив каркас: §8 посилався на «рамку --danger», а
     самого токена в шкалі не було. */
  --danger: #e5484d;

  /* ── RGB-ТРІЙКИ СТАТУСІВ ────────────────────────────────────────────────
     🛑 Ці три токени існують тому, що підкладка «10% від кольору статусу»
     не збирається з hex: rgba() потребує чисел. Без них кожне таке правило
     вписувало трійку руками — і виміряно, що по 12 файлах так лишилось 18
     живих правил із rgba(255,92,114,…). Це СТАРИЙ рожевуватий --danger:
     токен свого часу перевели на #e5484d, а числа лишились і тягли рожевий
     назад. Те саме із зеленим 61,220,132 проти --ok #34d17f.

     Друга, тихіша біда: число не має тем. Світла тема має власні --danger
     (#c92947) і --ok (#1c9754), але всі 18 правил малювали на папері
     темну підкладку. Тепер трійка теж перевизначається темою. */
  --danger-rgb: 229, 72, 77;
  --ok-rgb: 52, 209, 127;
  --warn-rgb: 255, 122, 69;

  /* Світліші відповідники — рівно для тексту НА власній підкладці статусу,
     як --accent-hi для бурштину. Сам --ok/--danger на підкладці .12 сідає
     в контрасті; ці два стояли в ui_kit.css числами (#5fd99a і #ff8496),
     причому другий був відвертим рожевим — тим самим, який з палітри
     прибирали. */
  --ok-hi: #5fd99a;
  --danger-hi: #ff7b80;
  --info: #5c9bf0;

  /* ── ЗАЛИВКИ ───────────────────────────────────────────────────────────
     Чотири щаблі прозорого білого. Це той шар, якого бракувало найбільше:
     форму в застосунку тримали РАМКИ (виміряно — 74 елементи з рамками в
     календарі, 32 в налаштуваннях), а рамка на кожному предметі й дає той
     «дешевий вигляд», з якого починається дизайн-код.

     Заливка замість рамки означає, що предмет видно за щільністю, а не за
     обведенням, і що предмети можна вкладати один в одного, не множачи
     ліній.

     --fill-0 окремо для ВЕЛИКИХ поверхонь: щаблі .055/.09/.14 розраховані
     на контрол розміром із кнопку, і панель сцени на 1200×740 при --fill-1
     світиться як окремий предмет. Це другий токен, який запросив каркас. */
  --fill-0: rgba(255,255,255,.03);
  --fill-1: rgba(255,255,255,.055);
  --fill-2: rgba(255,255,255,.09);
  --fill-3: rgba(255,255,255,.14);
  /* Бурштиновий шар тієї ж природи — для вибраного стану, не для акценту. */
  --fill-accent: var(--accent-wash-2);

  /* ── ЗАГЛИБИНА ──────────────────────────────────────────────────────────
     Чотири щаблі вище — тільки ДОДАВАННЯ світла, тож усі вони показують
     «тут щось є, і чим світліше, тим більше». Показати «тут порожньо»
     ними неможливо: --fill-1 на картці --fill-1 — це один і той самий
     колір, і предмет зникає. Виміряно рівно так на смужці горизонту в
     автопілоті: rgba(255,255,255,.055) на rgba(255,255,255,.055).

     --well — єдиний щабель у зворотний бік: поверхня, ЗАГЛИБЛЕНА відносно
     тієї, на якій лежить. Порожня комірка, доріжка повзунка, жолоб
     прогресу, поле під введення. Календар це правило вже застосовує
     («порожній день темніший за той, у якому щось є») — тепер у нього є
     токен, а не локальне значення. */
  --well: rgba(0,0,0,.28);

  /* ── РАДІУСИ: КОНЦЕНТРИЧНІ ─────────────────────────────────────────────
     Було 8 / 14 / 20 — три числа без звʼязку. Стало 11 / 16 / 22, і звʼязок
     тут не косметичний: внутрішній радіус дорівнює зовнішньому мінус
     відступ. Пункт рейки 12 = 16 − 4; рядок меню 11 у панелі 16 при
     відступі 6. Без цього кути вкладених предметів «стирчать» назовні —
     дефект, який на око читається як неохайність, а не як геометрія. */
  /* Форма. Три чіткі щаблі замість «майже все 14px»: керування тісніше,
     поверхня м'якша, і різниця між ними видима без наведення. */
  /* 🛑 ДРІБНИЙ ЩАБЕЛЬ. Його бракувало, і саме через це в стилях Studio
     завелись сирі 5, 6 і 7 пікселів: значок, бейдж і мітка не мали свого
     радіуса в системі, тож кожен автор ставив число від себе. Один
     щабель прибирає всі три. */
  --radius-xs: 6px;    /* мітка, бейдж, значок — те, що менше за кнопку */
  --radius-sm: 11px;   /* кнопка, поле, чип */
  --radius: 16px;      /* картка, плитка */
  --radius-lg: 22px;   /* панель, модалка, велика поверхня */

  /* 🛑 Тут стояло «Inter, system-ui, …», але застосунок ним НЕ малювався:
     skin.css оголошував --sans удруге, вантажився останнім і вигравав. Той
     самий розкол, що вже знайшовся в --border і --fill-*; цей був
     найтихішим, бо ламав не колір, а весь текст продукту.

     Значення взято чинне. Inter — найпоширеніший шрифт вебу, тому й
     найбезликіший: у ньому продукт не має обличчя. Geologica технічна, зі
     змінною вагою й рідною кирилицею — читається як прилад, а не як
     вітрина. Inter лишається наступним у стеку: якщо woff2 не
     завантажиться, метрики близькі й розкладка не поїде. */
  --sans: "Geologica", "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
  --mono: "JetBrains Mono", ui-monospace, "SF Mono", Consolas, monospace;
  /* Та сама родина, що на сайті (site.css --serif). Playfair уже лежить у
     vendor/fonts.css і вантажиться застосунком — бракувало саме токена,
     тому знак у шапці малювався Geologica 600 замість Playfair 400, тобто
     був іншим написом, ніж на сайті. Серифне тут належить ЗНАКУ, і більше
     нічому: заголовки застосунку лишаються sans. */
  --serif: "Playfair Display", Georgia, "Times New Roman", serif;

  /* 🛑 232, а НЕ 228. Тут стояло 228 із поясненням «рейка втратила 12px» —
     і це пояснення описувало зміну, якої не сталося: skin.css оголошував
     --nav-w удруге, значенням 232, і вигравав. Виміряно на живій сторінці:
     рейка 232px. Лишаю чинне число, а не задеклароване: проти 232 звірені
     всі відступи в застосунку, і «полагодити» його зараз означало б
     зсунути на 4px кожен екран заради коментаря. */
  --nav-w: 232px;
  /* 56, було 60. Плюс зникла смуга онбордингу на 56 — сцена почалась на
     60px вище на кожному з 16 екранів. Дві лінії рами стали однією. */
  --topbar-h: 56px;

  /* Shadows — 3 levels: resting (barely there) / raised (hover) / modal (popover, overlays) */
  --shadow-1: 0 1px 3px rgba(0,0,0,.28);
  --shadow-2: 0 12px 28px rgba(0,0,0,.4), 0 2px 8px rgba(0,0,0,.3);
  --shadow-soft: 0 8px 30px rgba(0,0,0,.35);
  --shadow-pop: 0 16px 48px rgba(0,0,0,.5);
  --shadow-3: var(--shadow-pop);

  /* Card/panel elevation — single token so every card surface (see the
     shared :is() rule near the Topbar section) gets the same resting lift.
     Dark also gets a hairline top inset highlight for extra depth against
     the near-black canvas; light skips it (a white-on-white highlight is
     invisible, and would double up with the shadow). */
  --card-shadow: 0 1px 2px rgba(0,0,0,.24), inset 0 1px 0 rgba(255,255,255,.035);

  /* Topbar glass tint (the frosted strip behind backdrop-filter blur) and
     inline code/pre background.

     🛑 Значення в'яжеться до --bg-rgb, а не пишеться числом. Тут раніше
     стояло rgba(10,10,18,.85) — синьо-чорна шапка, що лишилась від старої
     холодної палітри: перша смуга екрана була іншого відтінку, ніж усе під
     нею. skin.css це полагодив другим оголошенням, але хибне число так і
     лежало тут, удаючи джерело. */
  --topbar-bg: rgba(var(--bg-rgb), .82);
  --code-bg: rgba(0,0,0,.28);

  /* Motion — durations + easings shared by every transition/animation below */
  --t-fast: 150ms;
  --t-med: 250ms;
  --t-slow: 400ms;
  /* 🛑 --ease ЗВІДСИ ПРИБРАНО. Він був оголошений тричі — тут, у
     00_theme.css і в skin.css, причому тут ІНШОЮ кривою
     (.4,0,.2,1 проти .32,.72,0,1). Діяла не ця. Власник — 00_theme.css:
     рух і форма його. */
  --ease-out-back: cubic-bezier(.34, 1.56, .64, 1);

  /* ══ КЕРУВАННЯ: ТОКЕНИ КОМПОНЕНТА ═══════════════════════════════════════
     Шар між темою й розміткою. Вище лежать СЕМАНТИЧНІ токени (--accent,
     --fill-1, --text) — вони кажуть, який колір у продукту. Нижче лежать
     правила — вони кажуть, як влаштований конкретний елемент. Цей блок
     посередині: він каже, з чого зроблена КНОПКА.

     Навіщо цей шар. Досі `.btn` була оголошена в трьох файлах — у
     02_shell.css, у skin.css і в ui_motion.css, — і вони суперечили одне
     одному: висота 36 проти 38, головна дія градієнтом проти суцільної,
     ховер `brightness(1.08)` проти жорстко вписаного #ffbc38. Перемагав
     той файл, що вантажився останнім. Щоб перефарбувати кнопки, треба було
     знати цю таблицю напам'ять і правити в кількох місцях.

     Тепер правило одне (у 02_shell.css), а значення — тут. Змінити колір
     усіх головних кнопок у продукті — це один рядок нижче.

     🛑 Значення взяті з ВИМІРЯНОГО живого стану (той, що перемагав), а не
     з найкрасивішого файлу: рефакторинг не має права міняти вигляд. */

  /* геометрія — спільна для кнопок, чипів і полів */
  --ctl-h: 38px;
  --ctl-h-sm: 32px;
  --ctl-pad: 15px;
  --ctl-pad-sm: 12px;
  --ctl-radius: var(--radius-sm);
  --ctl-radius-sm: 9px;
  --ctl-tracking: -.01em;

  /* ── ЧИП ──────────────────────────────────────────────────────────────
     Друга сутність із тією самою хворобою, що була в `.btn`: `.chip` був
     оголошений у core/02_shell.css і в skin.css, і вони суперечили одне
     одному — 32px проти 34, вага 600 проти 500, активний стан бурштиновий
     проти нейтрального. Вигравав skin.css, бо вантажиться останнім.

     🛑 Значення взяті з ВИМІРЯНОГО живого стану (того, що перемагав), а не
     з красивішого файлу. Радіус 11px, а не 999: базовий чип у продукті
     прямокутний зі скругленням, пігулку (999px) собі задають окремі
     компоненти — вкладки аналітики й цілі Менеджера. */
  --chip-h: 34px;
  --chip-pad: 14px;
  --chip-radius: var(--radius-sm);
  --chip-font: 500 var(--fs-12)/normal var(--sans);
  --chip-bg: var(--fill-1);
  --chip-bg-hover: var(--fill-2);
  --chip-fg: var(--text-dim);
  --chip-fg-hover: var(--text);
  /* Вибір — яскравістю, не кольором: те саме правило, що в кнопках і
     плитках вибору (--pick-active-*). */
  --chip-active-bg: var(--fill-3);
  --chip-active-fg: var(--text);

  /* ── ШКАЛА РОЗВЕДЕНОГО АКЦЕНТУ ────────────────────────────────────────
     Бурштин рідко лежить суцільним: частіше це підкладка під активним
     станом, тепла кромка чи кольорове сяйво тіні. Виміряно в наших
     стилях: 102 такі місця й **24 різні прозорості** — .04, .06, .07,
     .08, .10, .12, .13, .14, .16, .18, .24, .25, .28… Шкали не було, і
     кожен автор брав число з голови. Два сусідні елементи виходили
     різними без жодної причини, а перефарбувати їх разом було нічим.

     П'ять щаблів покривають усі випадки:
        wash-1  ледь тепла підкладка, майже непомітна
        wash-2  активний стан списку чи вкладки
        wash-3  м'яка головна дія — кнопка, що не кричить
        edge    кромка, обведення, роздільник
        glow    кольорове сяйво тіні

     🛑 Нові місця беруть щабель. Нове число замість щабля — це повернення
     до 24 прозоростей. */
  --accent-wash-1: rgba(var(--accent-solid-rgb), .07);
  --accent-wash-2: rgba(var(--accent-solid-rgb), .12);
  --accent-wash-3: rgba(var(--accent-solid-rgb), .16);
  --accent-edge:   rgba(var(--accent-solid-rgb), .3);
  --accent-edge-hi: rgba(var(--accent-solid-rgb), .34);
  --accent-glow:   rgba(var(--accent-solid-rgb), .55);
  --accent-glow-hi: rgba(var(--accent-solid-rgb), .7);

  /* ── ДРУГИЙ КАНАЛ: --accent-rgb ────────────────────────────────────
     🛑 Це НЕ дублікат --accent-solid-rgb, і плутати їх не можна:

       --accent-solid-rgb  сталий 240,165,0 в ОБОХ темах
       --accent-rgb        іде за --accent, тобто у світлій темі
                           затемнюється до 154,98,0

     Правило просте: підкладка й сяйво беруть СТАЛИЙ канал (заливка мусить
     лишатись бурштином на білому), а те, що йде за кольором ТЕКСТУ
     акценту, — цей.

     Тут теж не було шкали: 40 місць і шістнадцять прозоростей (.06, .08,
     .1, .18, .2, .22, .25, .26, .28, .3, .32, .35, .5, .55, .65). Щаблі
     дзеркалять перший канал, щоб не тримати в голові дві різні шкали. */
  --accent-t-wash-1: rgba(var(--accent-rgb), .07);
  --accent-t-wash-2: rgba(var(--accent-rgb), .12);
  --accent-t-wash-3: rgba(var(--accent-rgb), .16);
  --accent-t-edge:   rgba(var(--accent-rgb), .3);
  --accent-t-edge-hi: rgba(var(--accent-rgb), .34);
  --accent-t-glow:   rgba(var(--accent-rgb), .55);
  --accent-t-glow-hi: rgba(var(--accent-rgb), .7);
  /* Два верхні щаблі додано після другого прогону: перші п'ять покрили
     ПІДКЛАДКИ, а кромки й сяйва лишились на власних числах — .24, .25,
     .28, .32, .34, .35, .38, .5, .7, .88. Тепер шкала має сім щаблів і
     покриває всі 102 місця, де бурштин розведений. */

  /* кнопка звичайна — та, якої в застосунку більшість */
  --btn-bg: var(--fill-1);
  --btn-bg-hover: var(--fill-2);
  --btn-fg: var(--text);

  /* головна дія. Заливка бере --accent-solid, а не --accent: у світлій
     темі --accent навмисно затемнений (#9a6200), щоб бурштиновий ТЕКСТ
     читався на білому, — але як заливка це брунатний, і кнопка виглядає
     вицвілою. Заливка яскрава в обох темах, темніє лише текст поверх. */
  --btn-primary-bg: var(--accent-solid);
  --btn-primary-bg-hover: #ffbc38;
  --btn-primary-bg-active: var(--accent-deep);
  --btn-primary-fg: #17140c;
  --btn-primary-fg-active: #fff;

  /* м'яка головна — дія за акцентом, яка не мусить кричати. Таких у
     застосунку виміряно 37, і кожна була виписана вручну повз токени:
     підміна --btn-primary-bg перефарбовувала 6 кнопок із 43. */
  --btn-soft-bg: var(--accent-wash-3);
  --btn-soft-fg: var(--accent-hi);

  /* ── ПЛИТКА ВИБОРУ (.ui-pick) ─────────────────────────────────────────
     У продукті два записані правила про акцент, і вони суперечили одне
     одному. skin.css: «ВИБІР позначається яскравістю, ДІЯ — кольором».
     ui_kit.css: «обраний = бурштиновий цілком, три сигнали тут
     виправдані». Обидва аргументовані, обидва живі.

     Розсуджено на користь першого, і ось чому. Аргумент ui_kit вірний для
     ОДНІЄЇ групи на екрані: там бурштин справді позначає рівно одне.
     Але в Галереї таких груп дві поспіль — джерело («Завантажене /
     Згенероване») і тип («Всі / Фото / Відео»), — і виходило два теплі
     вибори плюс тепла дія. Правило, яке ламається від другої групи на
     екрані, — не правило.

     🛑 Рішення винесене в токени НАВМИСНО: якщо Міша схоче бурштиновий
     вибір назад, це один рядок нижче, а не обхід усіх плиток. */
  --pick-active-bg: var(--fill-3);
  --pick-active-fg: var(--text);
  --pick-active-ring: rgba(255, 255, 255, .22);

  /* Плитка ніколи не мала свого кегля: у ui_kit заданий лише
     `font-family`, тож усі вкладки галереї, бібліотеки й досліджень
     набирались дефолтом браузера для <button> — 13.3333px вагою 400.
     Виміряно getComputedStyle; це не вибраний розмір, це його відсутність. */
  --pick-font: 600 var(--fs-11)/1.25 var(--sans);

  /* небезпечна дія — колір тексту, а не заливки: суцільний червоний
     прямокутник кричить там, де достатньо позначити наслідок */
  --btn-danger-fg: var(--danger);
  --btn-danger-bg: color-mix(in srgb, var(--danger) 14%, transparent);
  --btn-danger-bg-hover: color-mix(in srgb, var(--danger) 24%, transparent);

  /* теплий другорядний — дія за акцентом, але не головна на екрані */
  --btn-accent-bg: rgba(var(--accent-solid-rgb), .10);
  --btn-accent-fg: var(--accent);
}

/* ── LIGHT THEME ──────────────────────────────────────────────────────────
   Applied when <html data-theme="light">. Overrides only the theme-dependent
   surface / text / border / shadow tokens; brand gradient, motion, radii and
   #fff-on-color stay shared. Premium light-dashboard palette (cool off-white
   canvas, pure-white cards that lift on soft neutral shadows). Kept in sync
   with the dark defaults above token-for-token. */
:root[data-theme="light"]{
  /* RGB-компаньйони для rgba(). color-mix() з'явився лише в Safari 16.2
     (macOS 13), а на старшому WebKit таке ОГОЛОШЕННЯ ПРОСТО ВІДКИДАЄТЬСЯ —
     тобто зникає рамка/тінь/фон, а не «трохи інший відтінок».
     rgba(var(--x-rgb), .55) дає той самий піксель і працює скрізь. */
  /* 🛑 Тут стояло `--brand-ink-rgb: 214, 36, 110` — рожевий старого
     бренду. Мертве оголошення: нижче в цьому ж блоці той самий токен
     перевизначається на бурштин, і виграє останнє. Але воно живе в
     файлі як зразок для копіювання й показує в пошуку по «рожевий»
     те, чого в продукті вже немає. Прибрано. */
  /* 🛑 ЦІ ДВА МУСЯТЬ ДОРІВНЮВАТИ --bg-soft І --bg, І ТУТ НЕ ДОРІВНЮВАЛИ.
     Стояло 238,240,247 і 245,246,251 — холодна блакитнувата білизна старої
     палітри, тоді як --bg уже давно #f6f4f1 (246,244,241), теплий кремовий
     папір. Різниця не декоративна: на ці дві трійки спираються скло шапки,
     три затемнення й градієнт згасання в ui_kit — тобто в світлій темі
     вони малювали холодну плівку поверх теплої сторінки, рівно той шов,
     заради усунення якого палітру й переводили.

     Темна тема була узгоджена; звірено обчисленням з hex, а не оком. */
  --bg-soft-rgb: 238, 237, 233;
  --bg-rgb: 246, 244, 241;
  --info-rgb: 48, 114, 226;

  color-scheme: light;

  /* Світла тема — той самий кремовий папір, що й світлі смуги сайту
     (DESIGN_SITE.md §2, --cream oklch(0.94 0.006 85)). Була холодна
     блакитнувата білизна #f5f6fb, тон 280; бурштин на ній виглядав як
     чужа пляма з тієї ж причини, що й у темній темі. Світлоти не
     чіпав — перевірки контрасту нижче лишаються чинними. */
  --bg: #f6f4f1;
  --bg-soft: #eeede9;
  --panel: #ffffff;
  --panel-2: #f4f2ef;
  --elevated: #ffffff;
  /* Ті самі три токени, єдине оголошення — див. коментар у темній темі. */
  --border: rgba(16,18,40,.10);
  --border-soft: rgba(16,18,40,.065);
  --border-hover: rgba(16,18,40,.22);

  --text: #1a1512;
  --text-dim: #595450;
  /* Виміряно 2026-08-05, світла тема: #6f7189 давав 4.38 на --panel-2 при
     нормі 4.5 для дрібного тексту, а --text-mute — це саме дрібний текст
     (підписи таблиць, .tl-lbl, es-sub, моношрифтові заголовки). Розрив
     невеликий, але систематичний: він у десятках місць. #686a80 дає 4.87. */
  /* 🛑 L 0.52, а не 0.56. Переводячи тему в теплий тон, я поставив
     цьому токену світлоту трохи вищу за початкову — і контраст на
     --panel-2 упав з 4.87 до 4.19 при нормі 4.5 для дрібного тексту.
     0.52 дає 4.93 на панелі й 5.02 на тлі. Світлота тут не косметика:
     саме вона, а не тон, вирішує читабельність. */
  --text-mute: #6d6863;

  /* Світлий бурштин. #f0a500 на білому дає 2.1 — це рівень декорації, а не
     тексту, а --accent носить і текст, і рамки. #9a6200 дає 5.12 на білому,
     лишаючись бурштиновим; білий текст на такій заливці — 5.9. */
  --accent: #9a6200;
  --accent-hi: #c07d00;
  --accent-deep: #7a4d00;
  --accent-rgb: 154, 98, 0;
  --brand-ink-rgb: 154, 98, 0;

  --brand-ink: var(--accent);
  --on-brand: #ffffff;

  /* Softer brand tint over white so pale panels don't look muddy. */
  --grad-brand: linear-gradient(135deg, #c07d00 0%, #9a6200 55%, #7a4d00 100%);
  /* Світла тема: ті самі три токени (--accent-hi / --accent / --accent-deep),
     які тут уже затемнені, — тож числа 192,125,0 / 154,98,0 / 122,77,0
     були їхньою копією. Копію прибрано разом із можливістю розійтись. */
  --grad-brand-soft: linear-gradient(135deg,
    color-mix(in srgb, var(--accent-hi) 12%, transparent) 0%,
    color-mix(in srgb, var(--accent) 12%, transparent) 55%,
    color-mix(in srgb, var(--accent-deep) 14%, transparent) 100%);

  /* Neutral, tinted-navy shadows — black shadows look dirty on light. */
  --shadow-1: 0 1px 2px rgba(18,20,45,.06);
  --shadow-2: 0 12px 28px rgba(18,20,45,.12), 0 2px 8px rgba(18,20,45,.07);
  --shadow-soft: 0 8px 30px rgba(18,20,45,.10);
  --shadow-pop: 0 16px 48px rgba(18,20,45,.18);
  --shadow-3: var(--shadow-pop);

  /* No dark-only inset highlight needed on white cards — plain shadow-1 is
     the whole story. Topbar tint is the off-white canvas at reduced alpha;
     code/pre background is a faint dark tint instead of solid black-on-white. */
  /* Чинні світлі значення, що приїхали зі skin.css разом із темними.
     Тут стояло --topbar-bg: rgba(245,246,251,.82) — холодна блакитнувата
     білизна старої палітри, та сама, від якої відмовився --bg. */
  --card-shadow: 0 1px 2px rgba(18,20,45,.05);
  --topbar-bg: rgba(var(--bg-rgb), .85);
  --code-bg: rgba(20,20,40,.06);

  --link: #8a6d0f;

  /* Крива в світлій темі темніша. #f0a500 на білому дає 2.1 — для заливки
     стовпчика ще годиться, а аналітика малює ЛІНІЮ в 2px, і на такій
     товщині це вже примара. #b87400 дає 3.9: не текст, але впевнена
     графіка. Сірі теж темніші, бо лягають на світлий папір. */
  --chart-1: #b87400;
  --chart-2: #6b7280;
  --chart-3: #9aa1ac;
  --chart-4: #c3c8d0;

  --ok: #1c9754;
  /* Виміряно 2026-08-05 у світлій темі: --warn використовується як КОЛІР
     ТЕКСТУ в десятку місць (.badge-warn, .cal-health.warn, .appr-strip,
     зауваження судді в рецензії розкадровки…), і #a97620 давав контраст
     3.64 на --panel-2 при нормі 4.5 для дрібного тексту. #8a5f13 дає 5.18
     на --panel-2 і 5.63 на --panel, лишаючись бурштиновим. У темній темі
     --warn на тексті й так 8.93 — там нічого не чіпаємо. */
  /* Відсунуто від бурштину разом із темною темою: акцент тепер бурштиновий,
     і попередження того ж кольору було б невидиме як попередження. #b0400f —
     кіновар, контраст 5.85 на білому. */
  --warn: #b0400f;
  /* Те саме й з тією ж причиною: --danger носить не лише рамки, а й текст
     (від'ємна маржа в таблиці собівартості, .btn-danger, статуси). #d6304f
     давав 4.39 на --panel-2 → #c92947 дає 4.96. Темної теми не чіпаємо:
     там і так 5.47. */
  --danger: #c92947;
  /* Ті самі трійки для паперу — див. коментар у темній темі. */
  --danger-rgb: 201, 41, 71;
  --ok-rgb: 28, 151, 84;
  --warn-rgb: 176, 64, 15;
  /* На папері «світліший» означає темніший: текст читається проти білого.
     Виміряно контраст на власній підкладці .12 (тобто там, де ці токени й
     стоять): #167943 давав 4.35 при нормі 4.5 — не пройшов, тож зелений
     довелось поглибити до #12693a (5.39). Червоний #a81f39 дав 5.49
     одразу. У темній темі обидва проходять із запасом: 6.86 і 8.97. */
  --ok-hi: #12693a;
  --danger-hi: #a81f39;

  /* Ті самі чотири щаблі, але чорним: білий по білому не існує.
     Непрозорість менша, бо на світлому папері око ловить різницю
     раніше — 3% чорного помітніші за 3% білого на чорному. */
  --fill-0: rgba(16,18,40,.022);   /* та сама база 16,18,40, що й щаблі нижче */
  --fill-1: rgba(16,18,40,.045);
  --fill-2: rgba(16,18,40,.075);
  --fill-3: rgba(16,18,40,.11);
  --fill-accent: var(--accent-t-wash-2);
  /* 🛑 На папері заглибину не можна ставити ВСЕРЕДИНУ драбини заливок.
     У темній темі щаблі додають світло, а заглибина його віднімає — два
     різні напрямки, і сплутати їх неможливо. На світлому ж усі щаблі
     додають чорнило, тобто «підняте» й «заглиблене» рухаються в один бік;
     .075 збіглося б із --fill-2 колір-у-колір. Тому заглибина стоїть
     ЗА драбиною (глибше за --fill-3 .11) — і читається як отвір, а не
     як ще один щабель. */
  --well: rgba(16,18,40,.17);
  --info: #3072e2;
}

@media (prefers-reduced-motion: reduce){
  *, *::before, *::after{
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}

*, *::before, *::after{ box-sizing: border-box; }
/* The UA [hidden]{display:none} rule loses to any same-specificity author
   class (e.g. .btn{display:inline-flex}) because origin is ranked before
   specificity in the cascade — so a hidden <button class="btn"> stays
   visible. Force it explicitly; this is the correct meaning of `hidden`
   everywhere in this app, including third-party widgets. */
[hidden]{ display: none !important; }
html, body{ height: 100%; }
body{
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: 400 var(--fs-14)/1.5 var(--sans);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}
a{ color: inherit; }
/* 🛑 Не лише кнопки. `input`, `select` і `textarea` теж не успадковують
   шрифт від сторінки — це давня примха браузерів, і без цього рядка
   поле вводу набирається системним 13.3333px, а підпис поруч —
   нашим. Виміряно на полях ліміту в Грошах і Менеджері. */
button, input, select, textarea{ font-family: inherit; }
/* 🛑 Кегль тут НЕ задаємо глобально. Лишились три елементи з дефолтним
   13.3333px — два `input[type=range]` і один `checkbox`; у них шрифт не
   малює нічого, бо тексту всередині немає. Загальне правило на всі поля
   зачепило б і ті, що вже мають свій кегль, заради елементів, у яких він
   невидимий. Перевірено поелементно, а не припущено. */
::selection{ background: rgba(var(--accent-rgb),.35); color: #fff; }

::-webkit-scrollbar{ width: 10px; height: 10px; }
::-webkit-scrollbar-track{ background: transparent; }
::-webkit-scrollbar-thumb{ background: var(--border); border-radius: 8px; border: 2px solid transparent; background-clip: padding-box; transition: background var(--t-fast) var(--ease); }
::-webkit-scrollbar-thumb:hover{ background: var(--elevated); background-clip: padding-box; }

/* ── Keyboard focus ring — visible only for keyboard nav, never on mouse click ── */
:focus-visible{
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}
input:focus-visible, textarea:focus-visible{ outline-offset: 0; }

/* Pill (999px) and circular (50%) controls: the default outline above is
   rounded to --radius-sm, which reads as square corners poking out past a
   round control. Trace the same shape as the element underneath instead —
   additive only, every control here still gets the same color/width/offset. */
:is(.chip, .net-toggle, .st-aspect-btn, .cmp-tab, .pw-tab, .ib-seg-btn,
    .ana-chart-chip, .runs-chip, .au-switch):focus-visible{
  border-radius: 999px;
}
:is(.st-count-btn, .mi-del, .st-zoom-btn):focus-visible{
  border-radius: 50%;
}

.brand-text{
  font-weight: 800; letter-spacing: -.02em; font-size:  var(--fs-18);
  background: var(--grad-brand);
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.brand-logo{
  width: 30px; height: 30px; border-radius: 8px; flex: none;
  display: block; object-fit: contain;
  box-shadow: 0 0 0 1px var(--border-soft), 0 2px 10px rgba(0,0,0,.35);
}
.auth-logo{
  width: 96px; height: 96px; border-radius: 20px; display: block;
  margin: 0 auto 14px; object-fit: contain;
  box-shadow: 0 0 0 1px var(--border-soft), 0 8px 30px rgba(0,0,0,.45);
}

/* ── Inline-SVG icon wrapper (window.Icons.el → <span class="svg-ic">) ──────
   The SVG inside is width/height:100% + stroke:currentColor, so the wrapper's
   font-color and box size drive the icon. Containers (.nav-item .ic, .tl-ic …)
   set the size; color is inherited unless overridden. */
.svg-ic{ display: inline-flex; align-items: center; justify-content: center; line-height: 0; flex: none; width: 1em; height: 1em; vertical-align: -0.125em; }
.svg-ic svg{ display: block; width: 100%; height: 100%; }
.nav-item .ic .svg-ic, .nav-item .ic > svg{ width: 20px; height: 20px; }
/* Icon-only action buttons that put .svg-ic directly on the .btn itself
   (no separate wrapper span) inherit .svg-ic's width:1em/height:1em on the
   BUTTON element too, clamping its content-box to ~0 (padding/border alone
   exceed 1em) — the icon then gets flex-shrunk to 0 regardless of its own
   size. Undo the button-level sizing and give the icon itself a fixed size. */
.btn.svg-ic{ width: auto; }
.btn.svg-ic > svg{ width: 16px; height: 16px; flex: none; }

/* ── Shared micro-interaction keyframes ──────────────────────────────────
   cardIn      — grid/list item entrance (fade + slide up), staggered below
   shimmer     — skeleton-loader sweep
   wsFlash     — brief tinted-background pulse when a card is patched live
                 over WS; --flash-end sets the resting background it settles
                 back into (set per-component, see .ib-card.ws-flash etc.)
   badgePop    — nav badge-count "pop" when its number changes
   overlayFade / modalPop — modal backdrop + card entrance
   ========================================================================== */
@keyframes cardIn{
  from{ opacity: 0; transform: translateY(10px); }
  to{ opacity: 1; transform: translateY(0); }
}
@keyframes shimmer{
  from{ background-position: 200% 0; }
  to{ background-position: -200% 0; }
}
@keyframes wsFlash{
  0%{ background-color: rgba(var(--accent-rgb),.28); }
  100%{ background-color: var(--flash-end, transparent); }
}
@keyframes badgePop{
  0%{ transform: scale(.55); }
  55%{ transform: scale(1.28); }
  100%{ transform: scale(1); }
}
@keyframes overlayFade{
  from{ opacity: 0; } to{ opacity: 1; }
}
@keyframes modalPop{
  from{ opacity: 0; transform: scale(.96) translateY(6px); }
  to{ opacity: 1; transform: scale(1) translateY(0); }
}

/* Entrance animation for the main card/list components, staggered by
   position for the first ~10 items so grids feel like they "arrive"
   instead of popping in all at once. */
:is(.lib-grid > .lib-card, .gal-grid > .gal-item, .skill-cards > .skill-card,
    .conn-grid > .conn-card, .tiles > .tile, .ib-list > .ib-card,
    .st-recent-grid > .st-recent-card, .cal-day-body > .post-card,
    .appr-strip > .appr-card){
  animation: cardIn var(--t-slow) var(--ease) both;
}
:is(.lib-grid > .lib-card, .gal-grid > .gal-item, .skill-cards > .skill-card, .conn-grid > .conn-card, .tiles > .tile, .ib-list > .ib-card, .st-recent-grid > .st-recent-card, .cal-day-body > .post-card, .appr-strip > .appr-card):nth-child(1){ animation-delay: 0ms; }
:is(.lib-grid > .lib-card, .gal-grid > .gal-item, .skill-cards > .skill-card, .conn-grid > .conn-card, .tiles > .tile, .ib-list > .ib-card, .st-recent-grid > .st-recent-card, .cal-day-body > .post-card, .appr-strip > .appr-card):nth-child(2){ animation-delay: 40ms; }
:is(.lib-grid > .lib-card, .gal-grid > .gal-item, .skill-cards > .skill-card, .conn-grid > .conn-card, .tiles > .tile, .ib-list > .ib-card, .st-recent-grid > .st-recent-card, .cal-day-body > .post-card, .appr-strip > .appr-card):nth-child(3){ animation-delay: 80ms; }
:is(.lib-grid > .lib-card, .gal-grid > .gal-item, .skill-cards > .skill-card, .conn-grid > .conn-card, .tiles > .tile, .ib-list > .ib-card, .st-recent-grid > .st-recent-card, .cal-day-body > .post-card, .appr-strip > .appr-card):nth-child(4){ animation-delay: 120ms; }
:is(.lib-grid > .lib-card, .gal-grid > .gal-item, .skill-cards > .skill-card, .conn-grid > .conn-card, .tiles > .tile, .ib-list > .ib-card, .st-recent-grid > .st-recent-card, .cal-day-body > .post-card, .appr-strip > .appr-card):nth-child(5){ animation-delay: 160ms; }
:is(.lib-grid > .lib-card, .gal-grid > .gal-item, .skill-cards > .skill-card, .conn-grid > .conn-card, .tiles > .tile, .ib-list > .ib-card, .st-recent-grid > .st-recent-card, .cal-day-body > .post-card, .appr-strip > .appr-card):nth-child(6){ animation-delay: 200ms; }
:is(.lib-grid > .lib-card, .gal-grid > .gal-item, .skill-cards > .skill-card, .conn-grid > .conn-card, .tiles > .tile, .ib-list > .ib-card, .st-recent-grid > .st-recent-card, .cal-day-body > .post-card, .appr-strip > .appr-card):nth-child(7){ animation-delay: 240ms; }
:is(.lib-grid > .lib-card, .gal-grid > .gal-item, .skill-cards > .skill-card, .conn-grid > .conn-card, .tiles > .tile, .ib-list > .ib-card, .st-recent-grid > .st-recent-card, .cal-day-body > .post-card, .appr-strip > .appr-card):nth-child(8){ animation-delay: 280ms; }
:is(.lib-grid > .lib-card, .gal-grid > .gal-item, .skill-cards > .skill-card, .conn-grid > .conn-card, .tiles > .tile, .ib-list > .ib-card, .st-recent-grid > .st-recent-card, .cal-day-body > .post-card, .appr-strip > .appr-card):nth-child(9){ animation-delay: 320ms; }
:is(.lib-grid > .lib-card, .gal-grid > .gal-item, .skill-cards > .skill-card, .conn-grid > .conn-card, .tiles > .tile, .ib-list > .ib-card, .st-recent-grid > .st-recent-card, .cal-day-body > .post-card, .appr-strip > .appr-card):nth-child(10){ animation-delay: 360ms; }

/* WS live-patch pulse — class is added by JS right where a single card is
   re-rendered from a WS event (inbox.js patchCard, studio.js onEvent,
   skills.js setState), never on a plain list render, so it reads as "this
   one just changed" rather than firing on every paint. */
.ib-card.ws-flash{ --flash-end: var(--panel); animation: wsFlash 1.4s var(--ease); }
.skill-card.ws-flash{ --flash-end: var(--panel); animation: wsFlash 1.4s var(--ease); }
.st-recent-card.ws-flash{ --flash-end: var(--panel); animation: wsFlash 1.4s var(--ease); }
.post-card.ws-flash{ --flash-end: var(--panel-2); animation: wsFlash 1.4s var(--ease); }

/* Nav badge pop — toggled by nav.js's setBadge() whenever the number changes */
.nav-item .badge-count.badge-pop{ animation: badgePop 320ms var(--ease-out-back); }

/* Skeleton loader — shimmer placeholder shown while a grid/list awaits its
   first API response (see gallery.js/library.js/inbox.js loaders). */
.skel-card, .skel-row{
  border-radius: var(--radius); border: 1px solid var(--border-soft);
  background: linear-gradient(90deg, var(--panel) 25%, var(--panel-2) 50%, var(--panel) 75%);
  background-size: 200% 100%;
  animation: shimmer 1.4s linear infinite;
}
.skel-card{ aspect-ratio: 1; }
.skel-row{ height: 78px; }

/* Modal / overlay entrance — plays whenever a `.modal-overlay` (or the
   lightbox variant, which reuses the same class) goes from [hidden] to
   visible; browsers restart CSS animations when an element re-enters the
   render tree, so no JS hook is needed. */
.modal-overlay:not([hidden]){ animation: overlayFade var(--t-med) var(--ease); }
.modal-overlay:not([hidden]) > .modal-card,
.modal-overlay:not([hidden]) > .lib-lightbox-inner{ animation: modalPop var(--t-med) var(--ease-out-back); }
.auth-card{ animation: modalPop var(--t-med) var(--ease-out-back); }

/* ── Card / panel elevation ───────────────────────────────────────────────
   Every card-like surface in the app gets the same resting lift via
   --card-shadow (shadow-1 + a dark-only inset highlight — see :root). Hover
   states (shadow-2, set per-component below) and any selected/active variant
   with its own box-shadow both win on specificity, so this is purely the
   "at rest" baseline that was previously missing on most of these. */
:is(.panel, .tile, .conn-card, .skill-card, .gal-item, .lib-card, .job-card,
    .prov-card, .st-recent-card, .cal-day, .post-card, .brand-card, .svc-card,
    .autonomy-row, .key-row, .pw-card, .rs-card, .appr-card,
    .mg-tpl-card, .st-format-card, .st-pick-card, .lead-card, .onb-step,
    .cmp-ai-card, .ib-col, .brand-ctx-item, .cal-quickform, .st-carousel-group,
    .info-step, .aud-person-row, .apx-tile, .apx-demo-card, .ana-rs-card,
    .pw-mode-card, .ca-topic-card){
  box-shadow: var(--card-shadow);
}

