/* Кабінет учасника. Одна колонка, великий лічильник, нічого зайвого —
   найчастіша причина зайти сюди це питання «я ще член клубу?».

   ПЕРШЕ ПРАВИЛО ТУТ НЕ ПРО ВИГЛЯД. Атрибут [hidden] програє будь-якому
   display у класі: .btn має display:inline-flex, і кнопка «Вийти»
   світилася на екрані входу, де виходити нема кому. Та сама пастка вже
   ловила перемикач у каталозі бізнесів. Тому — примусово. */
[hidden]{display:none !important}

/* Заставка з лого при вході в кабінет — той самий прийом, що на
   головній сторінці сайту (index.css): лого зʼявляється маленьким,
   тримає паузу, росте до нормального розміру й на завершення різко
   «пролітає» повз (scale 6.8), заставка гасне вслід за ним.
   animation-fill-mode both ховає її саму, без жодного рядка JS — і не
   чекає на перевірку сесії чи вхід. */
.hero-intro {
  position: fixed;
  inset: 0;
  z-index: 300;
  display: grid;
  place-items: center;
  overflow: hidden;
  background: var(--ink-900);
  pointer-events: none;
  animation: hero-intro-exit 2.45s cubic-bezier(.72, 0, .2, 1) both;
}
.hero-intro img {
  width: min(60vw, 420px);
  height: auto;
  transform-origin: 50% center;
  animation: hero-intro-logo 2.15s cubic-bezier(.72, 0, .16, 1) both;
}
@keyframes hero-intro-logo {
  0%       { opacity: 0; transform: scale(.16); }
  13%, 34% { opacity: 1; transform: scale(.2); }
  72%      { opacity: 1; transform: scale(1); }
  100%     { opacity: 0; transform: scale(6.8); }
}
@keyframes hero-intro-exit {
  0%, 72% { visibility: visible; opacity: 1; }
  99%     { visibility: visible; opacity: 0; }
  100%    { visibility: hidden; opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .hero-intro { display: none; }
  /* Картка каталогу підіймається на hover — рамка й тінь лишаються,
     їде тільки рух. */
  .kb-person { transition: border-color .18s ease, box-shadow .18s ease; }
  .kb-person:hover { transform: none; }
}

:root{--kb-top-h:63px;--kb-pad:clamp(14px,2.2vw,28px)} /* 34px лого + 14px+14px паддінгу .kb-top__in + 1px риски знизу — шухляді на вузькому екрані, щоб не ховатися під шапкою */
.kb-top{position:sticky;top:0;z-index:var(--z-header);
  border-bottom:1px solid var(--ink-600);background:var(--ink-900)}
/* padding:14px, а не 14px 0: скорочений запис обнуляє
   padding-inline:var(--gutter) з класу .container на цьому ж елементі,
   і тоді імʼя праворуч упирається просто в край екрана (0px). Повний
   --gutter (20-48px) тут не підходить — кабінет свідомо йде «в край»
   (бокова панель від 0), тож беремо ті самі 14px, що й по вертикалі. */
.kb-top__in{display:flex;align-items:center;justify-content:space-between;
  gap:16px;padding:14px var(--kb-pad)}
.kb-logo{height:34px;width:auto;display:block}
/* Лого-перемикач: так само як у /admin, клацання ховає й повертає
   бокову панель — виходу на сайт тут свідомо немає. */
.kb-top__logo{appearance:none;border:0;background:transparent;padding:0;
  line-height:0;cursor:pointer;position:relative}
/* Жовта риска під лого — псевдоелемент, а не border/padding: висота
   кнопки не міняється, тож --kb-top-h (сама лінія кладеться поверх,
   не в потоці) лишається точною для .kb-tabs на вузькому екрані. */
.kb-top__logo::after{content:'';position:absolute;left:0;right:0;bottom:-8px;
  height:2px;background:var(--gold-500)}
.kb-top__logo:focus-visible{outline:2px solid var(--gold-500);outline-offset:3px;
  border-radius:4px}
.kb-top__right{display:flex;align-items:center;gap:12px}
.kb-who{color:var(--ink-400);font-size:var(--fs-xs)}

.kb-main{padding:0 0 64px;min-height:60vh}
.kb-card{background:var(--ink-800);border:1px solid var(--ink-600);
  border-radius:14px;padding:24px 26px;margin-bottom:18px;max-width:none}
.kb-card h1{margin:0 0 10px;font-family:var(--font-display);font-size:var(--fs-h3)}
.kb-card h2{margin:0 0 8px;font-size:var(--fs-h4)}
.kb-card h3{margin:26px 0 8px;font-size:var(--fs-body);color:var(--gold-500)}
.kb-lead{color:var(--ink-400);margin:0 0 16px;max-width:70ch;line-height:1.6}
.kb-fine{color:var(--ink-400);font-size:var(--fs-xs);line-height:1.55}

/* Вхід — перше, що бачить член, тож картка оформлена як вітрина:
   золота риска згори, мʼяке світіння за карткою, глибока тінь.
   display тут НЕ задається — секцію ховає атрибут hidden (kabinet.js),
   і власний display перебив би його. */
.kb-login{position:relative;max-width:460px;margin:9vh auto 0;
  padding:44px 40px 32px;border-radius:20px;
  border-color:rgba(255,255,255,.07);
  background:linear-gradient(180deg,rgba(255,255,255,.035),rgba(255,255,255,0) 45%),var(--ink-800);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.04),0 32px 80px -32px rgba(0,0,0,.75)}
.kb-login::before{content:'';position:absolute;top:-1px;left:40px;right:40px;height:1px;
  background:linear-gradient(90deg,transparent,var(--gold-500),transparent)}
/* z-index:-1 без власного контексту накладання в батька — світіння
   малюється ПІД тлом картки й видне лише навколо її країв. */
.kb-login::after{content:'';position:absolute;inset:-90px -120px;z-index:-1;
  pointer-events:none;
  background:radial-gradient(closest-side,rgba(242,194,0,.07),transparent)}
.kb-login__eyebrow{margin:0 0 14px;font-size:11px;font-weight:500;
  letter-spacing:.18em;text-transform:uppercase;color:var(--gold-500)}
.kb-login h1{margin:0 0 32px;font-weight:200;font-size:clamp(30px,4.2vw,38px);
  line-height:1.1;letter-spacing:-.02em}
.kb-login label{display:block;font-size:11px;font-weight:500;letter-spacing:.1em;
  text-transform:uppercase;color:var(--ink-400)}
.kb-login input{width:100%;min-height:54px;margin:8px 0 16px;padding:0 16px;
  background:rgba(255,255,255,.03);border:1px solid var(--ink-600);border-radius:12px;
  color:var(--paper);font:inherit;
  transition:border-color var(--t-fast) var(--ease-ui),box-shadow var(--t-fast) var(--ease-ui)}
.kb-login input::placeholder{color:var(--ink-500)}
.kb-login input:hover{border-color:var(--ink-500)}
.kb-login input:focus{outline:none;border-color:var(--gold-500);
  box-shadow:0 0 0 4px rgba(242,194,0,.14)}
.kb-login .btn{width:100%;min-height:54px}
.kb-login .kb-fine{margin:28px 0 0;padding-top:22px;
  border-top:1px solid rgba(255,255,255,.06);text-align:center}
/* 460px картки + 2×120px світіння: вужче за ~720px воно виходило б за
   край екрана, і на телефоні вся сторінка ставала ширшою за екран. */
@media (max-width:720px){
  .kb-login::after{inset:-60px 0}
}
@media (max-width:520px){
  /* .kb-main знімає бокові відступи контейнера — без власних картка
     лягала б упритул до країв телефона. */
  .kb-login{margin:5vh 16px 0;padding:36px 22px 26px;border-radius:16px}
  .kb-login::before{left:22px;right:22px}
}
/* Друга форма — вхід за кодом. Риска потрібна, бо без неї поле коду
   читається як ще одне поле першої форми, і людина тисне «Надіслати
   посилання» вдруге замість «Увійти за кодом». */
#kb-code-form{margin-top:22px;padding-top:20px;border-top:1px solid var(--ink-600)}
#kb-code{letter-spacing:.22em;font-variant-numeric:tabular-nums}

.kb-msg{margin:12px 0 0;font-size:var(--fs-sm)}
.kb-msg.is-good{color:#3DBE7B}
.kb-msg.is-bad{color:#E2685E}

/* ─── бокова панель ───
   Той самий принцип, що в /admin: .kb-layout — сітка з двох колонок,
   що згортається до grid-template-columns:0px 1fr, коли лого в шапці
   ховає панель. min-width:0 на дітях обовʼязковий — інакше вміст
   панелі не дає колонці стиснутися нижче своєї природної ширини. */
/* --kb-pad — той самий відступ, що в шапці (.kb-top__in): край панелі й
   контенту стоїть на одній лінії з лого та імʼям, а зверху є повітря
   замість впритул до риски шапки. */
.kb-layout{display:grid;grid-template-columns:216px 1fr;align-items:start;
  padding:clamp(20px,2.6vw,36px) var(--kb-pad) 0;
  gap:0 clamp(20px,2.4vw,32px);transition:grid-template-columns .2s ease}
.kb-layout.is-collapsed{grid-template-columns:0px 1fr}

/* На широкому екрані гасити нічого не треба — панель сама живе в
   сітці, не над контентом. */
.kb-side-backdrop{display:none}

/* min-block-size — підлога під попап «Налаштування» (kb-menu__list),
   що відкривається вниз від останнього пункту списку: висота .kb-tabs
   інакше дорівнює висоті самого списку (7 вкладок + кнопка), і на
   короткій сторінці попап вилазив би за overflow:hidden. 680px = ~439px
   список (28.08.2026, 7 вкладок) + ~6px відступ + ~202px попап (4
   пункти) із запасом. Зміните список вкладок чи пункти меню — звірте
   це число знову. */
.kb-tabs{min-width:0;min-block-size:680px;overflow:hidden;align-self:stretch;
  background:var(--ink-800);border:1px solid var(--ink-600);border-radius:14px;
  margin-bottom:0}
.kb-tabs__inner{display:flex;flex-direction:column;gap:2px;width:216px;
  padding:14px 10px;white-space:nowrap}
.kb-tab{display:block;width:100%;background:transparent;
  border:0;border-inline-start:3px solid transparent;color:var(--ink-400);
  padding:11px 14px;border-radius:8px;font:inherit;font-size:var(--fs-sm);
  text-align:start;cursor:pointer}
.kb-tab:hover{background:var(--ink-700);color:var(--paper)}
.kb-tab.is-on{background:var(--ink-700);border-inline-start-color:var(--gold-500);
  color:var(--paper);font-weight:600}
/* Іконки в бічному меню — рішення власника 28.09.2026. Ті самі
   знаки, що в нижній панелі на телефоні; активний пункт — золотий. */
.kb-tabs .kb-tab{display:flex;align-items:center;gap:12px}
.kb-tab__ico{width:21px;height:21px;flex:none;opacity:.85}
.kb-tab.is-on .kb-tab__ico{color:var(--gold-500);opacity:1}

.kb-content{min-width:0}

@media(max-width:780px){
  /* Колонка в 216px на телефоні лишила б вмісту смужку. Тому на
     вузькому екрані панель — не колонка в сітці, а шухляда: fixed
     поверх контенту, виїжджає зліва тим самим лого-перемикачем. */
  .kb-layout,.kb-layout.is-collapsed{grid-template-columns:1fr}

  .kb-tabs{position:fixed;top:var(--kb-top-h);inset-inline-start:0;bottom:0;
    width:216px;z-index:90;border-radius:0;
    transform:translateX(0);transition:transform .2s ease}
  .kb-layout.is-collapsed .kb-tabs{transform:translateX(-100%)}
  .kb-tabs__inner{height:100%}

  /* Підкладка гасить контент позаду відкритої шухляди й закриває
     її по кліку. Нижча за панель, вища за звичайний контент. */
  .kb-layout:not(.is-collapsed) .kb-side-backdrop{display:block;position:fixed;
    inset:0;z-index:80;background:rgba(5,15,24,.55)}
}

/* ─── нижня панель на мобільному ───────────────────────────────
   Темна, як решта кабінету — не окрема світла плашка, а продовження
   того самого інтерфейсу. Активний пункт — золота «таблетка» під
   іконкою й підписом, той самий акцент, що скрізь у кабінеті.
   Кнопки — ті самі .kb-tab, що в шухляді (розмітка kabinet/index.html),
   тому активний стан і клік підхоплюються самі; тут лише інше
   компонування (вертикальне, менший текст) під нижню панель. */
.kb-bottomnav{display:none}

@media(max-width:780px){
  .kb-bottomnav{display:flex;position:fixed;inset-inline:0;bottom:0;z-index:85;
    background:var(--ink-800);border-top:1px solid var(--ink-600);
    border-radius:18px 18px 0 0;
    padding:6px 4px calc(6px + env(safe-area-inset-bottom))}

  /* Шухляда відкрита вже показує решту розділів — друга панель
     знизу поверх неї тільки плутала б. */
  .kb-layout:not(.is-collapsed) .kb-bottomnav{display:none}

  /* Ці чотири розділи вже є в нижній панелі (.kb-bottomnav нижче) —
     в шухляді на мобільному вони лише дублювали б її. На десктопі
     нижньої панелі немає взагалі, тому там ці ж .kb-tab лишаються —
     це виключно мобільний медіа-запит. */
  .kb-tabs .kb-tab[data-tab="events"],
  .kb-tabs .kb-tab[data-tab="directory"],
  .kb-tabs .kb-tab[data-tab="knowledge"],
  .kb-tabs .kb-tab[data-tab="offers"]{display:none}

  .kb-bottomnav .kb-tab{flex:1;display:flex;flex-direction:column;
    align-items:center;justify-content:center;gap:2px;width:auto;
    border-inline-start:0;border-radius:14px;padding:6px 2px;
    color:var(--ink-400);font-size:11px;line-height:1.2;text-align:center}
  .kb-bottomnav .kb-tab svg{width:22px;height:22px}
  .kb-bottomnav .kb-tab:hover{background:var(--ink-700);color:var(--paper)}
  .kb-bottomnav .kb-tab.is-on{background:rgba(242,194,0,.16);color:var(--gold-500);font-weight:600}

  /* Контент не ховається під панель, що лежить поверх нього. */
  .kb-content{padding-block-end:calc(68px + env(safe-area-inset-bottom))}

  /* «База знань» дублює підпис вкладки в шухляді/нижній панелі —
     на вузькому екрані зайвий рядок над Книги/Фільми/Матеріали. */
  .kb-pane[data-pane="knowledge"] > .kb-card > h2{display:none}
}

/* ─── лічильник ───
   Той самий словник, що в .kb-passcard нижче (градієнт, водяний
   знак, кольорова смуга) — це теж «картка членства», лише більша й
   без перевороту, тож має відчуватись рідною сестрою перепустки. */
.kb-hero{
  position:relative; overflow:hidden;
  background:linear-gradient(160deg,var(--ink-700),var(--ink-600));
  padding-block-end:32px;
}
.kb-hero::after{
  content:''; position:absolute; pointer-events:none;
  top:50%; inset-inline-end:-20px; transform:translateY(-50%);
  inline-size:170px; block-size:170px;
  background:url(/assets/brand/ncua-mark-white-128.png) center/contain no-repeat;
  opacity:.07;
}
.kb-hero__top{display:flex;align-items:center;justify-content:space-between;
  gap:12px;margin-bottom:6px;position:relative;z-index:1}
.kb-hero__no{color:var(--ink-400);font-size:var(--fs-xs);letter-spacing:.08em;
  text-transform:uppercase}
.kb-hero__badge{font-size:var(--fs-xs);font-weight:600;letter-spacing:.02em;
  padding:4px 11px;border-radius:999px;white-space:nowrap}
.kb-hero--ok .kb-hero__badge{background:rgba(61,190,123,.16);color:#3DBE7B}
.kb-hero--warn .kb-hero__badge{background:rgba(242,194,0,.16);color:var(--gold-500)}
.kb-hero--bad .kb-hero__badge{background:rgba(226,104,94,.16);color:#E2685E}
.kb-hero h1{position:relative;z-index:1;font-size:clamp(1.8rem,4vw,2.6rem);line-height:1.1}
.kb-hero .kb-lead,.kb-hero .btn{position:relative;z-index:1}
.kb-hero__foot{position:absolute;inset-inline:0;bottom:0;block-size:5px}
.kb-hero--ok .kb-hero__foot{background:#3DBE7B}
.kb-hero--warn .kb-hero__foot{background:var(--gold-500)}
.kb-hero--bad .kb-hero__foot{background:#E2685E}

.kb-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));
  gap:12px;margin-bottom:18px}
.kb-tile{background:var(--ink-800);border:1px solid var(--ink-600);
  border-radius:12px;padding:14px 16px}
.kb-tile span{display:block;color:var(--ink-400);font-size:var(--fs-xs);margin-bottom:5px}
.kb-tile b{font-size:1.05rem}
.kb-perks{margin:0;padding-left:20px;color:var(--ink-400);line-height:1.7}
.kb-perks b{color:var(--paper)}

/* ─── форма ─── */
.kb-two{display:grid;grid-template-columns:1fr 1fr;gap:14px}
@media(max-width:700px){.kb-two{grid-template-columns:1fr}}
.kb-f{margin-bottom:14px}
.kb-f label{display:block;font-size:var(--fs-xs);color:var(--ink-400);margin-bottom:5px}
.kb-f input,.kb-f textarea,.kb-f select{width:100%;background:var(--ink-700);
  border:1px solid var(--ink-500);color:var(--paper);padding:10px 12px;
  border-radius:9px;font:inherit}
.kb-f textarea{resize:vertical;line-height:1.55}
/* Замкнена форма (до кліку «Редагувати») — видно, що поле не для
   редагування зараз, а не просто невдало підсвічене. */
.kb-f input:disabled,.kb-f textarea:disabled,.kb-f select:disabled{
  opacity:.6;cursor:not-allowed;border-color:var(--ink-600)}
.kb-chip input:disabled,.kb-check input:disabled{cursor:not-allowed}
.kb-chip:has(input:disabled),.kb-check:has(input:disabled){opacity:.6}
.kb-chips{display:flex;flex-wrap:wrap;gap:7px}
.kb-chip{display:inline-flex;align-items:center;gap:6px;background:var(--ink-700);
  border:1px solid var(--ink-600);border-radius:999px;padding:6px 13px;
  font-size:var(--fs-xs);cursor:pointer}
.kb-chip input{width:auto}
.kb-check{display:flex;align-items:center;gap:9px;margin:8px 0;font-size:var(--fs-sm)}
.kb-check input{width:auto}
.kb-checks-row{display:flex;flex-wrap:wrap;column-gap:24px;row-gap:4px}
.kb-checks-row .kb-check{margin:8px 0}
.kb-actions{display:flex;align-items:center;gap:14px;margin-top:20px}

/* ─── каталог ─── */
.kb-filters{display:flex;gap:10px;flex-wrap:wrap;margin-bottom:16px}
.kb-filters[hidden]{display:none}
.kb-filters input,.kb-filters select{background:var(--ink-700);
  border:1px solid var(--ink-500);color:var(--paper);padding:10px 12px;
  border-radius:9px;font:inherit}
.kb-filters input{flex:1;min-width:200px}
.kb-dir{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:14px}
/* Картка каталогу — стовпчиком: фото, імʼя, локація, чіпи. Раніше
   імʼя стояло праворуч від фото, і в колонці 240px на нього
   лишалось ~80px — майже кожне ламалось навпіл. */
.kb-person{display:flex;flex-direction:column;align-items:flex-start;gap:9px;
  background:var(--ink-700);border:1px solid var(--ink-600);
  border-radius:14px;padding:18px;cursor:pointer;
  transition:border-color .18s ease,transform .18s ease,box-shadow .18s ease}
.kb-person:hover{border-color:var(--gold-500);transform:translateY(-2px);
  box-shadow:0 14px 30px rgba(0,0,0,.38)}
.kb-person:focus-visible{outline:2px solid var(--gold-500);outline-offset:2px}
.kb-person__avatar{flex:none;display:flex;align-items:center;justify-content:center;
  width:140px;height:140px;border-radius:14px;background:var(--ink-600);
  border:1px solid var(--gold-500);color:var(--gold-500);
  font-family:var(--font-display);font-size:var(--fs-h3);font-weight:500}
/* Каталог: кругла аватарка фіксованого розміру, по центру картки —
   решта картки (імʼя, чіпи) лишається зліва. Раніше тримала ширину
   колонки (100% + aspect-ratio:1) і виходила великим квадратом, що
   на широкій колонці «плавав» з нерівними полями. */
.kb-dir .kb-person__avatar{width:88px;height:88px;border-radius:50%;
  align-self:center;font-size:var(--fs-h4)}
/* Фото є в одиниць, решта — ініціали, і великою плиткою пласка
   заливка читалась як порожній квадрат. Градієнт лишає її спокійною,
   але дає глибину. На базовому класі, а не в .kb-dir: та сама
   плитка стоїть і в розгорнутій картці, і в прев'ю фото у формі —
   учасник має виглядати однаково скрізь. Фото не чіпаємо. */
.kb-person__avatar:not(.kb-person__avatar--photo){
  background:linear-gradient(158deg,#24435c 0%,var(--ink-600) 42%,#16293a 100%)}
.kb-person__name{margin:5px 0 0;font-size:var(--fs-h4);line-height:1.25;
  color:var(--paper)}
/* Чіпи — окремим блоком під тонкою рискою: без неї перелік
   зливався з локацією в один сірий стовпчик. Риска на обгортці, а не
   на першій групі: інакше вона зникала б у того, хто має «Відкритий
   до», але не має професії. */
.kb-person__tags{width:100%;margin:3px 0 0;padding-top:11px;
  border-top:1px solid var(--ink-600);
  display:flex;flex-direction:column;gap:7px}
/* Два класи в селекторі обовʼязкові: підпис — це <p> усередині
   .kb-person, тож .kb-person p (клас+тег) специфічніше за один клас
   і перебивало б розмір на --fs-sm, тобто 15px проти 11px у чіпів,
   які цей підпис підписує. Сирі 10px — як і в .kb-chips-ro span. */
.kb-person .kb-person__label{margin:0;font-size:10px;
  text-transform:uppercase;letter-spacing:.08em;color:var(--gold-500)}
.kb-no{color:var(--ink-400);font-weight:400;font-size:var(--fs-xs);margin-left:6px}
.kb-person__head{color:var(--gold-500);margin:0;font-size:var(--fs-sm)}
.kb-person p{margin:0;font-size:var(--fs-sm);line-height:1.55}
.kb-person__c{color:var(--ink-400);font-size:var(--fs-xs)}
.kb-person__loc{display:flex;align-items:center;gap:6px}
.kb-person__pin{width:14px;height:14px;flex:none;color:var(--gold-500)}
.kb-chips-ro{display:flex;flex-wrap:wrap;gap:6px}
.kb-chips-ro span{background:var(--ink-600);border:1px solid var(--ink-500);
  border-radius:20px;padding:3px 10px;font-size:11px;color:var(--ink-400)}
.kb-person__avatar--photo{object-fit:cover;background:var(--ink-600)}

/* Контакти — кнопки-чіпи з іконкою замість рядка тексту через «·». */
.kb-person__chips{display:flex;flex-wrap:wrap;gap:8px;margin:0 0 10px}
.kb-person__chip{display:inline-flex;align-items:center;gap:6px;background:var(--ink-600);
  border:1px solid var(--ink-500);border-radius:10px;padding:7px 12px;
  font-size:var(--fs-xs);color:var(--paper);text-decoration:none}
.kb-person__chip svg{width:15px;height:15px;color:var(--gold-500);flex:none}
a.kb-person__chip:hover{border-color:var(--gold-500)}

/* Основна інформація — рядки «підпис / значення», без рамки: рамка
   тут злилася б із тлом і в прев'ю (.kb-person сам ink-700), і в
   модалці каталогу (сама ink-800). */
/* ─── повна картка людини (personCardBody у kabinet.js) — фото зліва,
   дані праворуч, статус-бейдж у кутку. Той самий блок і в прев'ю
   каталогу (.kb-catalog-preview), і в модалці (.person-modal__body,
   без .kb-person навколо) — тому оформлення лежить на .kb-pcard, а
   не на спільних .kb-person__*, якими досі користується компактна
   картка сітки каталогу. */
.kb-pcard{display:grid;grid-template-columns:min(220px,34%) 1fr;gap:22px;align-items:start}
.kb-pcard__media{max-width:220px}
.kb-pcard__media .kb-person__avatar{width:100%;height:auto;aspect-ratio:3/4;
  border-radius:16px;font-size:var(--fs-h2)}
.kb-pcard__media .kb-person__avatar--photo{object-fit:cover}
.kb-pcard__name{margin:0 0 4px;font-size:var(--fs-h4)}
.kb-pcard__role{color:var(--gold-500);margin:0 0 6px;font-size:var(--fs-sm)}
.kb-pcard__loc{margin:0 0 14px}
.kb-pcard__row{display:grid;grid-template-columns:20px 130px 1fr;gap:14px;
  align-items:start;padding:12px 0;border-top:1px solid var(--ink-600);font-size:var(--fs-sm)}
.kb-pcard__row:first-child{border-top:none;padding-top:0}
.kb-pcard__row-icon{width:20px;height:20px;flex:none;color:var(--gold-500)}
.kb-pcard__row-label{color:var(--ink-400)}
.kb-pcard__row-value{white-space:pre-line}

@media(max-width:640px){
  .kb-pcard{grid-template-columns:1fr}
  .kb-pcard__media{max-width:180px;margin:0 auto 6px}
  .kb-pcard__row{grid-template-columns:20px 1fr;row-gap:2px}
  .kb-pcard__row-value{grid-column:2}
}

/* Завантаження фото у формі — велике фото зверху, кнопки під ним
   (не збоку — при 240px збоку лишалось б порожньо). */
.kb-avatar-upload{display:flex;flex-direction:column;align-items:flex-start;gap:14px}
.kb-avatar-upload__preview{display:block}
.kb-avatar-upload__preview .kb-person__avatar{width:240px;height:240px;font-size:var(--fs-h2)}
.kb-avatar-upload__actions{display:flex;align-items:center;gap:10px;flex-wrap:wrap}

/* Фото й Ім'я/Прізвище — в один ряд: імена вузькою колонкою праворуч
   від фото, на тому самому рівні, а не окремим повношириним рядком
   над ним. */
.kb-identity{display:flex;gap:24px;flex-wrap:wrap}
.kb-identity__name{display:flex;gap:16px;flex-wrap:wrap;flex:1;min-width:280px}
.kb-identity__name .kb-f{flex:1;min-width:180px;margin-bottom:0}

/* Прев'ю власної картки в «Профіль для каталогу» — та сама .kb-person,
   що й у списку каталогу, лише не клікабельна й з відступом знизу
   перед формою/кнопкою «Редагувати». */
.kb-catalog-preview{cursor:default;margin-bottom:18px}
.kb-catalog-preview:hover{border-color:var(--ink-600)}

/* ─── підвкладки всередині пейну (База знань: Книги/Фільми/Матеріали) ─── */
.kb-subtabs{display:flex;gap:4px;border-bottom:1px solid var(--ink-600);
  margin-bottom:18px}
.kb-subtab{appearance:none;background:transparent;border:0;font:inherit;
  color:var(--ink-400);padding:8px 4px;margin-right:18px;cursor:pointer;
  border-bottom:2px solid transparent}
.kb-subtab.is-on{color:var(--paper);border-bottom-color:var(--gold-500)}
.kb-subtab:hover{color:var(--paper)}
.kb-subtab:focus-visible{outline:2px solid var(--gold-500);outline-offset:2px}

/* ─── картка учасника на весь екран ───
   margin:auto ОБОВʼЯЗКОВИЙ. Нативний <dialog> центрується саме ним
   (UA-стиль inset:0 + margin:auto), а скидання `* { margin: 0 }` у
   tokens.css його зносить — той самий фікс, що й .event-modal у
   components.css та .adm-dialog у admin.css. */
.person-modal{margin:auto;width:100%;max-width:min(820px,calc(100vw - 32px));
  max-height:calc(100vh - 64px);padding:0;border:none;border-radius:14px;
  background:var(--ink-800);color:var(--paper);overflow:hidden auto}
.person-modal::backdrop{background:rgba(5,15,24,.72)}
.person-modal__panel{position:relative;padding:24px 26px}
.person-modal__close{position:absolute;top:12px;right:12px;display:flex;
  align-items:center;justify-content:center;width:32px;height:32px;
  border-radius:50%;background:var(--ink-700);border:1px solid var(--ink-600);
  color:var(--ink-400)}
.person-modal__close svg{width:16px;height:16px}
.person-modal__close:hover{color:var(--paper);border-color:var(--gold-500)}
.person-modal__body{padding-right:24px}

/* ─── книга/фільм/матеріал на весь екран (kabinet-hub.js → openLibraryModal) ───
   Той самий фікс margin:auto, що й .person-modal вище. */
.library-modal{margin:auto;max-width:min(560px,calc(100vw - 32px));
  max-height:calc(100vh - 64px);padding:0;border:none;border-radius:14px;
  background:var(--ink-800);color:var(--paper);overflow:hidden auto}
.library-modal::backdrop{background:rgba(5,15,24,.72)}
.library-modal--media{max-width:min(920px,calc(100vw - 32px))}
.library-modal__panel{position:relative}
.library-modal__close{position:absolute;top:12px;right:12px;z-index:2;display:flex;
  align-items:center;justify-content:center;width:32px;height:32px;
  border-radius:50%;background:var(--ink-700);border:1px solid var(--ink-600);
  color:var(--ink-400)}
.library-modal__close svg{width:16px;height:16px}
.library-modal__close:hover{color:var(--paper);border-color:var(--gold-500)}
.library-modal__body{padding:24px 24px 24px 26px;display:flex;flex-direction:column;
  align-items:flex-start;gap:9px}
.library-modal__cover{width:100%;max-width:260px;aspect-ratio:2/3;object-fit:cover;
  border-radius:8px;background:var(--ink-600)}
/* Лого партнера в модалці — contain, бо cover ріже лого; на
   картці воно навпаки на всю ширину (див. .hub-card__cover--wide).
   Матеріали тут не проходять — у них або програвач, або --full. */
.library-modal__cover--wide{max-width:none;aspect-ratio:16/9;
  object-fit:contain;padding:10px}
/* Кадр зі зустрічі — форма наперед невідома (3:2, квадрат, портрет),
   тож жодної рамки: пропорції власні, object-fit:contain лишає його
   цілим, а не обтинає під наш прямокутник. max-height, щоб портретний
   кадр не виштовхнув опис за екран. */
.library-modal__cover--full{max-width:none;aspect-ratio:auto;height:auto;
  object-fit:contain;max-height:min(52vh,380px);background:var(--ink-700)}

/* Обкладинка ПЕРШИМ елементом вікна (пропозиція партнера, програма,
   матеріал без відео) — на всю ширину, впритул до країв вікна, без
   поля й власного тла (рішення власника 29.09.2026). Раніше лого
   стояло в рамці 16:9 з padding 10px на --ink-600, і між картинкою й
   вікном читалась синя смуга. Відʼємні поля дорівнюють padding
   .library-modal__body (24 / 24 / 26), радіус — радіусу вікна.
   max-block-size тримає високий кадр, щоб він не виштовхнув назву й
   опис за екран; object-position — щоб обтинало низ, а не верх.
   Вікно новини (.news-modal__cover) не першим елементом і має свій
   вигляд — сюди не входить. */
.library-modal__body > .library-modal__cover--wide:first-child:not(.news-modal__cover),
.library-modal__body > .library-modal__cover--full:first-child{
  inline-size:calc(100% + 50px);max-inline-size:none;
  margin:-24px -24px 8px -26px;padding:0;background:none;
  border-radius:14px 14px 0 0;aspect-ratio:auto;block-size:auto;
  max-block-size:min(56vh,440px);object-fit:cover;object-position:50% 30%}
/* Вікно само по собі звужується під вміст (shrink-to-fit), і з
   квадратним лого, обмеженим за висотою, ставало ~390px. Ширину
   вікна з обкладинкою фіксуємо на звичайних 560px. */
.library-modal:has(.library-modal__body > .library-modal__cover:first-child){
  width:min(560px,calc(100vw - 32px))}

/* ── книга/фільм/матеріал: обкладинка під нахилом на розмитому тлі
   з того самого кадру — той самий прийом, що обкладинка альбому в
   музичних застосунках («Зараз грає»). .library-modal--media на
   самому <dialog> лише розширює його; макет — тут. */
.library-modal__body--media{position:relative;display:grid;
  grid-template-columns:minmax(220px,38%) 1fr;padding:0;gap:0;align-items:stretch}
.library-modal__ambient{position:absolute;inset:0;background-size:cover;
  background-position:center;filter:blur(50px) saturate(1.35) brightness(.5);
  transform:scale(1.35);z-index:0}
.library-modal__ambient::after{content:'';position:absolute;inset:0;
  background:linear-gradient(105deg, rgba(8,29,42,.6), rgba(8,29,42,.94) 60%)}
.library-modal__media{position:relative;z-index:1;display:flex;align-items:center;
  justify-content:center;padding:44px 28px}
.library-modal__cover--tilt{max-width:210px;
  box-shadow:-16px 26px 46px rgba(0,0,0,.55), 0 0 0 1px rgba(255,255,255,.06);
  transform:perspective(900px) rotateY(-14deg) rotateX(2deg)}
.library-modal__info{position:relative;z-index:1;padding:34px 30px 34px 6px;
  display:flex;flex-direction:column;align-items:flex-start;gap:10px;justify-content:center}
.library-modal__info .hub-card__title{font-size:1.5rem;line-height:1.28}
.library-modal__divider{inline-size:100%;border:0;border-block-start:1px solid rgba(255,255,255,.14);margin:2px 0}

/* ── матеріал: програвач YouTube на всю ширину, під ним опис ──
   Свідомо НЕ два стовпці, як у книг: відео 16:9 у вузькій колонці
   стає смужкою, у якій нічого не розгледіти. Ширина модалки тут
   більша за звичайні 560px саме заради програвача. */
.library-modal--video{max-width:min(1040px,calc(100vw - 32px));width:min(1040px,calc(100vw - 32px))}
/* Новина в кабінеті (openNewsModal) — на всю сторінку, як сторінка
   газети клубу (рішення власника 28.09.2026): світлий папір, темний
   текст, шапка зі знаком і датою під подвійною лінією, буквиця, у
   кінці — горизонт клубу. Колонка тексту вузька, щоб рядки читались. */
.library-modal--news{max-width:none;width:100vw;height:100dvh;max-height:none;
  margin:0;border-radius:0;background:#FBFAF6;color:var(--ink-900)}
.library-modal--news::backdrop{background:rgba(5,15,24,.9)}
.library-modal--news .library-modal__close{position:fixed;top:18px;right:18px;
  width:44px;height:44px;color:var(--ink-900);background:var(--paper);
  border:1px solid rgba(8,29,42,.14);box-shadow:0 6px 18px -8px rgba(8,29,42,.3)}
.library-modal__body--news{gap:0;max-width:760px;margin-inline:auto;align-items:stretch;
  padding:clamp(28px,5vw,56px) clamp(18px,4vw,32px) 72px}

.news-paper__mast{display:flex;align-items:center;justify-content:space-between;gap:16px;
  padding-block-end:14px;border-block-end:3px double var(--ink-900)}
.news-paper__brand{display:flex;align-items:center;gap:12px}
.news-paper__mark{width:40px;height:40px;display:block}
.news-paper__names{display:grid;gap:2px;line-height:1.15}
.news-paper__club{font-family:var(--font-display);font-weight:700;font-size:.95rem;
  letter-spacing:.14em;text-transform:uppercase}
.news-paper__section{font-size:.75rem;letter-spacing:.16em;text-transform:uppercase;
  color:var(--slate-600)}
.news-paper__date{font-size:.8125rem;letter-spacing:.06em;text-transform:uppercase;
  color:var(--slate-600);white-space:nowrap}

.news-paper__kicker{margin:clamp(28px,4vw,40px) 0 10px;font-size:.75rem;font-weight:600;
  letter-spacing:.18em;text-transform:uppercase;color:var(--gold-800)}
.library-modal--news .news-paper__title{margin:0 0 clamp(20px,3vw,28px);
  font-size:clamp(1.75rem,4vw,2.625rem);font-weight:300;line-height:1.15;
  letter-spacing:-.01em;color:var(--ink-900)}

.news-modal__cover{display:block;align-self:center;inline-size:auto;max-inline-size:100%;max-block-size:72vh;
  margin:0 auto clamp(24px,3.4vw,36px);object-fit:contain;padding:0;border-radius:4px;
  background:none;aspect-ratio:auto;box-shadow:0 24px 48px -28px rgba(8,29,42,.45)}

.library-modal--news .hub-desc{max-width:none;font-size:1.0625rem;line-height:1.8;
  color:#1F2F3A}
.library-modal--news .hub-desc__head{color:var(--gold-800);margin-block-start:14px}
.library-modal--news .hub-desc__name{color:var(--ink-900)}
.library-modal--news .hub-desc__list li::before,
.library-modal--news .hub-desc__person::before{background:var(--gold-800)}
/* Буквиця — перша літера першого абзацу, як у газеті. */
.news-paper__text > .hub-desc__p:first-child::first-letter{float:left;
  font-family:var(--font-display);font-weight:500;font-size:3.6em;line-height:.9;
  margin:.06em .1em 0 0;color:var(--ink-800)}
.library-modal--news .hub-card__acts{margin-block-start:28px}

.news-paper__foot{margin-block-start:clamp(40px,6vw,64px);text-align:center;color:var(--ink-800)}
.news-paper__horizon{opacity:.35}
.news-paper__sign{margin:10px 0 0;font-size:.75rem;letter-spacing:.2em;text-transform:uppercase;
  color:var(--slate-600)}
@media (max-width:520px){
  .news-paper__mast{flex-wrap:wrap}
}
/* Обличчя в кадрі: обкладинки новин частіше вертикальні афіші з
   людиною у верхній третині — центр по висоті різав голову. */
.hub-card--news .hub-card__cover{object-position:50% 18%}
/* Фото програми у вікні — кадр зі зустрічі, на всю ширину без полів. */
.program-modal__cover{object-fit:cover;padding:0;border-radius:12px;inline-size:100%;
  margin-block-end:6px}
.library-modal__body--video{padding:0;gap:0;display:flex;flex-direction:column;
  align-items:stretch}
.video-modal__stage{position:relative;aspect-ratio:16/9;background:#000;
  border-radius:14px 14px 0 0;overflow:hidden}
.video-modal__frame{position:absolute;inset:0;width:100%;height:100%;border:0;display:block}
/* Хрестик лежить на кадрі, а не на рівному тлі модалки: --ink-700 на
   світлому кадрі зникає. Тінь і темна підкладка тримають його
   видимим на будь-якому відео. */
.library-modal--video .library-modal__close{color:var(--paper);
  background:rgba(5,15,24,.78);border-color:rgba(255,255,255,.2);
  box-shadow:0 2px 10px rgba(0,0,0,.45)}
.video-modal__info{padding:22px 26px 26px;display:flex;flex-direction:column;
  align-items:flex-start;gap:10px;min-width:0}
.video-modal__info .hub-card__title{font-size:1.5rem;line-height:1.28}
/* Перемикачі записів — не кнопки-дії, а вкладки: одна з них завжди
   ввімкнена, і натискання не веде нікуди, а міняє відео в тому ж
   програвачі. Тому вигляд чіпа, а не .btn. */
.video-modal__parts{display:flex;flex-wrap:wrap;gap:8px}
/* Записи й «Презентація» — один рядок під назвою (openLibraryModal). */
.video-modal__bar{display:flex;flex-wrap:wrap;align-items:center;gap:8px}
.video-modal__bar .btn{margin:0}

/* Розібраний опис (richDescription у kabinet-hub.js): світліший і
   крупніший за сірий службовий текст, з повітрям між абзацами,
   підзаголовки золоті, списки — з акуратними маркерами. */
.hub-desc{display:grid;gap:10px;max-width:76ch;font-size:1rem;line-height:1.7;
  color:rgba(255,255,255,.84)}
/* У широкому вікні з відео текст іде ширше, інакше справа лишалась
   порожня третина вікна. */
.video-modal__info .hub-desc{max-width:none}
.hub-desc__p{margin:0}
.hub-desc__head{margin:10px 0 -2px;font-size:var(--fs-xs);font-weight:600;
  letter-spacing:.08em;text-transform:uppercase;color:var(--gold-500)}
.hub-desc__head:first-child{margin-block-start:0}
.hub-desc__list{margin:0;padding:0;list-style:none;display:grid;gap:6px}
.hub-desc__list li{position:relative;padding-inline-start:18px}
.hub-desc__list li::before{content:"";position:absolute;inset-inline-start:2px;top:.72em;
  width:6px;height:6px;border-radius:50%;background:var(--gold-500)}
/* Спікер: імʼя білим жирним, перед абзацом — та сама золота крапка,
   що й у списках, тож і абзаци, і пункти зі спікерами виглядають
   однаково. */
.hub-desc__name{font-weight:600;color:var(--paper)}
.hub-desc__person{position:relative;padding-inline-start:18px}
.hub-desc__person::before{content:"";position:absolute;inset-inline-start:2px;top:.72em;
  width:6px;height:6px;border-radius:50%;background:var(--gold-500)}
.video-modal__part{padding:6px 13px;border-radius:999px;font-size:var(--fs-sm);
  color:var(--ink-400);background:var(--ink-700);border:1px solid var(--ink-600);
  cursor:pointer}
.video-modal__part:hover{color:var(--paper);border-color:var(--gold-500)}
.video-modal__part.is-on{color:var(--ink-900);background:var(--gold-500);
  border-color:var(--gold-500)}

/* ── подія: фото колонкою на всю висоту зліва, дані праворуч ──
   Свідомо НЕ той самий прийом, що в книг вище: обкладинка книги —
   предмет, який доречно «покласти» під кутом на розмите тло; фото
   події — сцена, і нахилена сцена читається як помилка верстки.
   Тут фото працює як афіша: кадр у край, дата поверх нього. */
.library-modal__body--event{display:grid;
  grid-template-columns:minmax(200px,38%) 1fr;padding:0;gap:0;
  align-items:stretch;min-height:340px}
.event-modal__poster{position:relative;overflow:hidden}
.event-modal__photo{width:100%;height:100%;object-fit:cover;display:block}
/* Затемнення згори й знизу — дата має лишатись читабельною на
   будь-якому кадрі, а не лише на вдало темному. */
.event-modal__poster::after{content:'';position:absolute;inset:0;
  background:linear-gradient(180deg,rgba(5,15,24,.45) 0%,
    rgba(5,15,24,0) 34%,rgba(5,15,24,.82) 100%)}
.event-modal__date{position:absolute;left:22px;bottom:18px;z-index:1;
  margin:0;display:flex;flex-direction:column;gap:2px}
/* Не --ink-400: рік лежить на фото, а не на рівному тлі, і тьмяний
   сірий на світлому кадрі зникає. */
.event-modal__year{font-size:var(--fs-eyebrow);letter-spacing:.12em;
  color:rgba(255,255,255,.72)}
.event-modal__info{padding:30px 28px;display:flex;flex-direction:column;
  align-items:flex-start;gap:11px;min-width:0}
.event-modal__info .hub-card__title{font-size:1.5rem;line-height:1.28}
.event-modal__info .hub-card__acts{margin-block-start:6px}
/* «Спікери» — підпис розділу, не другий заголовок: голий h3 брав
   базовий --fs-h3 і важив майже як назва події, з якою й конкурував.
   Той самий вигляд, що .kb-person__panel h5 у картці учасника. */
.event-modal__label{margin:6px 0 0;font-size:var(--fs-xs);
  text-transform:uppercase;letter-spacing:.04em;color:var(--gold-500)}

@media(max-width:640px){
  /* Вузький екран: фото стає банером зверху. Портретна колонка тут
     з'їла б пів висоти, а кадр у подій горизонтальний. */
  .library-modal__body--event{grid-template-columns:1fr;min-height:0}
  .event-modal__poster{aspect-ratio:16/9}
  .event-modal__info{padding:22px 24px 24px}
  .library-modal__body--media{grid-template-columns:1fr}
  .library-modal__media{padding:28px 24px 6px}
  .library-modal__cover--tilt{max-width:170px;transform:none;
    box-shadow:0 14px 30px rgba(0,0,0,.5)}
  .library-modal__info{padding:16px 22px 26px}
  .video-modal__info{padding:18px 20px 24px}
}

/* ─── інструкція «Додати на початковий екран» (iOS) — той самий
   .library-modal, лише вужчий вміст: три кроки, без обкладинки. ─── */
.pwa-modal{max-width:min(420px,calc(100vw - 32px))}
.pwa-modal__body h2{margin:0 0 14px;font-size:var(--fs-h4)}
.pwa-steps{list-style:none;margin:0 0 14px;padding:0;display:flex;
  flex-direction:column;gap:14px}
.pwa-steps li{display:flex;align-items:flex-start;gap:12px;line-height:1.5}
.pwa-steps__num{flex:none;display:flex;align-items:center;justify-content:center;
  width:26px;height:26px;border-radius:50%;background:var(--ink-700);
  border:1px solid var(--ink-600);color:var(--gold-500);font-size:var(--fs-sm);
  font-weight:600}

/* ─── таблиці ─── */
.kb-table{width:100%;border-collapse:collapse;font-size:var(--fs-sm)}
.kb-table th{text-align:left;color:var(--ink-400);font-weight:500;font-size:var(--fs-xs);
  border-bottom:1px solid var(--ink-600);padding:8px 10px}
.kb-table td{padding:8px 10px;border-bottom:1px solid var(--ink-700)}
.kb-consents{margin:0;padding-left:18px;line-height:1.7}
.kb-consents li{margin-bottom:12px}

.kb-foot{border-top:1px solid var(--ink-600);padding:24px 0;
  color:var(--ink-400);font-size:var(--fs-xs)}
.kb-foot a{color:var(--ink-400)}

/* ═══════════════════════════════════════════════════════════════
   ГОЛОВНА КАБІНЕТУ ТА РЕСУРСНІ РОЗДІЛИ

   Картки, а не таблиця. Людина тут не порівнює рядки — вона шукає
   привід щось зробити: піти на зустріч, встигнути на грант, узяти
   знижку. Картка показує привід цілком, таблиця розрізає його на
   колонки.
   ═══════════════════════════════════════════════════════════════ */

/* Привітання й KPI-плашки в одному рядку на широкому екрані; на
   вузькому плашки самі переносяться під привітання — flex-wrap,
   без окремого медіа-запиту. */
.hub-top {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: 20px;
  margin-block-end: 28px;
}
.hub-top .hub-hi { margin-block-end: 0; flex: 1 1 280px; }

.kpi-row { display: flex; flex-wrap: wrap; gap: 10px; }
.kpi-tile {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 108px;
  flex: 1 1 108px;
  background: var(--ink-800);
  border: 1px solid var(--ink-600);
  border-radius: 12px;
  padding: 11px 13px;
}
.kpi-tile svg { width: 17px; height: 17px; color: var(--gold-500); }
.kpi-tile__value {
  margin: 0;
  font-family: var(--font-display);
  font-size: 1.5rem;
  font-weight: 200;
  line-height: 1;
  letter-spacing: -0.01em;
  font-variant-numeric: tabular-nums;
  color: var(--paper);
}
.kpi-tile__label { margin: 0; font-size: var(--fs-xs); color: var(--ink-400); line-height: 1.35; }

.hub-hi { margin-block-end: 28px; }
.hub-hi__title { margin: 0; font-size: var(--fs-h2); line-height: 1.15; }

/* Смуга стану членства. Вона тут ЛИШЕ коли з членством треба щось
   зробити — інакше перший екран знову перетворюється на нагадування
   про витрату, а це саме те, від чого ми пішли. */
.hub-alert {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 16px;
  align-items: center;
  padding: 14px 18px;
  border-radius: 12px;
  margin-block-end: 28px;
  border: 1px solid var(--ink-600);
  background: var(--ink-700);
}
.hub-alert strong { font-size: var(--fs-body); }
.hub-alert span { color: var(--ink-400); font-size: var(--fs-sm); }
.hub-alert .btn { margin-inline-start: auto; }
.hub-alert.is-warn { border-color: var(--gold-600); }
.hub-alert.is-bad { border-color: #7d3b36; }

/* ─── Пропозиція встановити PWA — той самий вигляд, що .hub-alert
   вище, лише живе в статичній розмітці kabinet/index.html (не
   перемальовується при зміні вкладки), тому власний клас. ─── */
.kb-pwa-banner {
  display: flex;
  flex-wrap: wrap;
  gap: 14px 20px;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  /* Той самий трюк, що .container (layout.css): padding-inline = gutter
     робить одну властивість і зовнішнім відступом від країв екрана
     на мобільному, і внутрішнім — від рамки картки до тексту. */
  max-width: calc(var(--w-wide) + 2 * var(--gutter));
  margin: 16px auto 0;
  padding: 16px var(--gutter);
  border-radius: 12px;
  border: 1px solid var(--ink-600);
  background: var(--ink-700);
}
.kb-pwa-banner__text strong { display: block; font-size: var(--fs-body); }
.kb-pwa-banner__text p {
  margin: 4px 0 0;
  color: var(--ink-400);
  font-size: var(--fs-sm);
  max-width: 52ch;
}
.kb-pwa-banner__actions {
  display: flex;
  gap: 10px;
  flex: none;
}

.hub-sec { margin-block-end: 34px; }
.hub-sec__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 14px;
  margin-block-end: 14px;
}
.hub-sec__title { margin: 0; font-size: var(--fs-h4); }
.hub-sec__more {
  background: none;
  border: 0;
  padding: 4px;
  font: inherit;
  font-size: var(--fs-sm);
  color: var(--gold-500);
  cursor: pointer;
  white-space: nowrap;
}
.hub-sec__more:hover { color: var(--gold-400); }
.hub-sec__more:focus-visible { outline: 2px solid var(--gold-500); outline-offset: 3px; }

.hub-sub { margin: 26px 0 12px; font-size: var(--fs-body); color: var(--gold-500); }
.hub-sub--muted { color: var(--ink-400); }

.hub-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 14px;
  /* Без align-items:start (тобто дефолтний stretch) — картки в рядку
     однакової висоти, і card__foot/margin-block-start:auto штовхає
     кнопку на той самий рівень у кожній колонці. .hub-card теж на це
     розраховував (block-size:100%), просто попередній start це гасив. */
}
/* Минулі події тьмяніші: вони тут для пошуку («як звалась та
   зустріч про нерухомість»), а не для дії. */
.hub-grid--past { opacity: .62; }

/* Матеріали — рівно три в ряду, а не auto-fill по 260px, який давав
   чотири. Кадри тут горизонтальні (16:9), і ширша колонка потрібна,
   щоб вони читались, а не стискались у смужку. Книги й фільми
   лишаються на auto-fill: портретні обкладинки добре стоять і
   вчотирьох. */
#kb-list-materials .hub-grid { grid-template-columns: repeat(3, 1fr); }
@media (max-width: 780px) {
  #kb-list-materials .hub-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 560px) {
  #kb-list-materials .hub-grid { grid-template-columns: 1fr; }
}

/* Книги, фільми й пропозиції партнерів — пʼять у ряд (рішення власника
   28.09.2026; пропозиції — тим самим рішенням пізніше):
   портретна обкладинка 2:3 добре читається й вужчою, а auto-fill
   по 260px давав лише чотири. */
#kb-list-books .hub-grid,
#kb-list-movies .hub-grid,
#kb-list-offers .hub-grid { grid-template-columns: repeat(5, minmax(0, 1fr)); }
@media (max-width: 1180px) {
  #kb-list-books .hub-grid,
  #kb-list-movies .hub-grid,
  #kb-list-offers .hub-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
@media (max-width: 900px) {
  #kb-list-books .hub-grid,
  #kb-list-movies .hub-grid,
  #kb-list-offers .hub-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 560px) {
  #kb-list-books .hub-grid,
  #kb-list-movies .hub-grid,
  #kb-list-offers .hub-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
/* Вужча колонка — компактніший текст під обкладинкою: заголовок
   і автор дрібніші, відступи щільніші (рішення власника 28.09.2026). */
#kb-list-books .hub-card,
#kb-list-movies .hub-card,
#kb-list-offers .hub-card { gap: 6px; padding: 14px 14px 14px; }
#kb-list-books .hub-card__cover,
#kb-list-movies .hub-card__cover,
#kb-list-offers .hub-card__cover { width: calc(100% + 28px); margin: -14px -14px 4px; }
#kb-list-books .hub-card .hub-card__title,
#kb-list-movies .hub-card .hub-card__title,
#kb-list-offers .hub-card .hub-card__title { font-size: 1rem; line-height: 1.3; }
#kb-list-books .hub-card__meta,
#kb-list-movies .hub-card__meta,
#kb-list-offers .hub-card__meta { font-size: .75rem; }
#kb-list-books .kb-chips-ro span,
#kb-list-movies .kb-chips-ro span { font-size: 10px; padding: 2px 8px; }
#kb-list-books .hub-like,
#kb-list-movies .hub-like,
#kb-list-offers .hub-like { padding: 3px 8px; }

/* Обгортка «факти події + кнопка запису» (eventCard() у
   kabinet-hub.js). Тут — рівно те, чим була відстань між ними, поки
   вони були прямими дітьми .card (flex-direction:column;gap:14px):
   на десктопі жодної візуальної різниці. На телефоні
   @media(max-width:560px) нижче перемикає на row. */
.card__meta-row { display: flex; flex-direction: column; gap: 14px; }
/* Обгортка росте на решту висоти картки, а її низ (кнопка) — до дна:
   тоді «Записатися» й «Ви записані» стоять на одній лінії в усьому
   ряду, скільки б рядків не займала назва події. */
.card--event > .card__meta-row { flex: 1 1 auto; }
.card--event .card__meta-row > .card__foot { margin-block-start: auto; }

/* Низ картки програми: стан участі й кнопка разом, притиснуті до дна. */
.hub-card__foot {
  margin-block-start: auto;
  inline-size: 100%;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 12px;
  padding-block-start: 6px;
}
.hub-card__foot .btn,
.hub-card__foot .hub-card__acts { margin-block-start: 0; }
.hub-card__foot .hub-fine { margin: 0; }

/* Картка події клікабельна — відкриває повний опис/спікерів у
   модалці (openEventDetailModal). Той самий hover, що вже дає
   .card:hover (components.css), тут лише курсор. */
.card--event { cursor: pointer; }

/* Сильніше заокруглення карток у кабінеті — рішення власника
   28.09.2026, та сама мова, що в картках партнерів на сайті. */
.hub-grid .card { border-radius: 20px; }

/* Вкладки «Архів подій / Найближчі»: лінія під ними впиралась у верх
   карток і зливалась з їхніми рамками в одну «рисочку» — прибрано
   (рішення власника 28.09.2026), а картки відсунуто від вкладок. */
#kb-list-events .tabs__list { border-bottom: 0; margin-block-end: 18px; }

/* Архів подій — рекапи як на сайті (recapCard() у kabinet-hub.js):
   оголошення, одне фото ліворуч, назва й опис праворуч. Кожна подія
   на всю ширину, а не плиткою в сітці. */
.kb-recaps { display: grid; gap: 16px; }
.kb-recap {
  padding: clamp(18px, 2vw, 24px);
  background: var(--ink-800);
  border: 1px solid var(--ink-600);
  border-radius: 20px;
  cursor: pointer;
  transition: border-color var(--t-fast) var(--ease-ui);
}
.kb-recap:hover { border-color: var(--gold-500); }
.kb-recap:focus-visible { outline: 2px solid var(--gold-500); outline-offset: 2px; }
.kb-recap__ann {
  margin: 0 0 16px;
  font-size: var(--fs-sm);
  font-weight: 500;
  color: var(--gold-500);
}
.kb-recap__grid {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  gap: clamp(18px, 2.4vw, 32px);
  align-items: start;
}
.kb-recap__grid--text { grid-template-columns: 1fr; }
.kb-recap__photo {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: 14px;
  background: var(--ink-700);
}
.kb-recap__info { display: grid; gap: 10px; align-content: start; min-width: 0; }
.kb-recap .kb-recap__title {
  margin: 0;
  font-size: var(--fs-h4);
  font-weight: 500;
  line-height: 1.3;
  color: var(--paper);
}
.kb-recap__text {
  margin: 0;
  font-size: var(--fs-sm);
  line-height: 1.6;
  color: var(--ink-400);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.kb-recap__when { margin: -2px 0 0; font-size: var(--fs-xs); color: var(--ink-400); letter-spacing: .02em; }
.kb-recap__label {
  margin: 4px 0 -4px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--ink-400);
}
.kb-recap__topics { margin: 0; padding: 0; list-style: none; display: grid; gap: 3px; }
.kb-recap__topics li {
  position: relative;
  padding-inline-start: 14px;
  font-size: var(--fs-sm);
  line-height: 1.5;
  color: rgba(255, 255, 255, .8);
}
.kb-recap__topics li::before {
  content: "";
  position: absolute;
  inset-inline-start: 1px;
  top: .62em;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--gold-500);
}
.kb-recap__people { margin: 0; padding: 0; list-style: none; display: flex; flex-wrap: wrap; gap: 6px 18px; }
.kb-recap__people li { display: grid; gap: 1px; font-size: var(--fs-sm); line-height: 1.35; }
.kb-recap__people strong { font-weight: 600; color: var(--paper); }
.kb-recap__people span { font-size: 12px; color: var(--ink-400); }
.kb-recap__more-people { align-self: center; color: var(--ink-400); }
.kb-recap__who { margin: 0; font-size: var(--fs-sm); color: var(--paper); }
.kb-recap__who .kb-recap__label { display: inline; margin: 0 8px 0 0; }
/* Вікно архівної події: ті самі мітки, теми й спікери, що в картці,
   тільки повністю; спікери — стовпчиком, з роллю під іменем. */
.event-modal__info .kb-recap__label { margin-block: 10px -2px; }
.event-modal__desc { font-size: .9375rem; line-height: 1.65; }
.kb-recap__people--full { display: grid; gap: 10px; }
@media (max-width: 700px) {
  .kb-recap__grid { grid-template-columns: 1fr; }
  .kb-recap__photo { aspect-ratio: 16 / 9; }
}
@media (prefers-reduced-motion: reduce) {
  .kb-recap { transition: none; }
}

/* «Записатися» проти «Ви записані» — різна довжина напису робила
   кнопки різної ширини в сусідніх картках одного ряду hub-grid.
   width:100% рівняє їх по ширині картки незалежно від тексту. */
.hub-grid .card--event .card__foot .btn {
  width: 100%;
}

.hub-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 9px;
  align-items: flex-start;
  background: var(--ink-700);
  border: 1px solid var(--ink-600);
  border-radius: 20px;
  padding: 16px 17px 17px;
  block-size: 100%;
}

/* Зірочка «подобається» — внизу картки, окремим рядком (не поверх
   обкладинки). margin-block-start:auto — той самий трюк, що й
   .hub-card .btn нижче: притискає її до низу картки незалежно від
   того, скільки тексту вище. stopPropagation у toggleLike() не дає
   кліку заразом відкрити модалку картки. */
.hub-like {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  margin-block-start: auto;
  background: var(--ink-600);
  border: 1px solid var(--ink-500);
  border-radius: 999px;
  padding: 5px 10px;
  font-size: var(--fs-xs);
  color: var(--paper);
  cursor: pointer;
}
.hub-like svg { width: 14px; height: 14px; color: var(--ink-400); flex: none; }
.hub-like.is-on svg { color: var(--gold-500); fill: var(--gold-500); }
.hub-like:hover { border-color: var(--gold-500); }
.hub-like:disabled { opacity: .6; cursor: not-allowed; }

/* У модалці зірочка сидить одразу під заголовком, а не притиснута
   до низу — там немає «низу картки», що її тягнув би. */
.hub-like--inline {
  margin: 2px 0 6px;
  background: var(--ink-700);
}
.hub-card--prog { background: var(--ink-800); border-color: var(--ink-500); }
.hub-card--clickable { cursor: pointer; }
.hub-card--clickable:hover { border-color: var(--gold-500); }
.hub-card--clickable:focus-visible { outline: 2px solid var(--gold-500); outline-offset: 2px; }
.hub-card__when { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.hub-card__day {
  font-size: var(--fs-sm);
  color: var(--gold-500);
  text-transform: lowercase;
}
/* Обкладинка до самих країв картки (не в межах padding, як решта
   вмісту) — тому мінус-відступи назовні на ширину/верх padding-у
   .hub-card, і заокруглення лише зверху (знизу вона переходить у
   текст картки, не в її справжній нижній край). */
.hub-card__cover {
  width: calc(100% + 34px);
  /* Без max-width:none глобальний ресет `img { max-width: 100% }`
     (tokens.css) обтинає ширину назад до 100%: мінус-відступ виносив
     обкладинку до лівого краю, а справа лишалась щілина в 34px. */
  max-width: none;
  margin: -16px -17px 0;
  aspect-ratio: 2 / 3;
  object-fit: cover;
  /* 20px картки мінус 1px її рамки — інакше в кутах щілина. */
  border-radius: 19px 19px 0 0;
  background: var(--ink-600);
}
/* Лого/промо-графіка партнерів і превʼю матеріалів — не обкладинка
   книги: у портретній 2:3 рамці широкі банери (текст на всю ширину)
   обрізались по краях. 16:9 показує їх цілими й робить картку
   нижчою. */
.hub-card__cover--wide {
  aspect-ratio: 16 / 9;
}
/* Лого партнера на картці — теж cover, на всю ширину (рішення
   власника 28.09.2026). Раніше тут був contain, бо cover різав
   квадратні лого («ACCOUNTIN…» замість «ACCOUNTING ACADEMY»);
   власник свідомо обрав заповнення без полів. Ціле лого лишається
   в модалці (.library-modal__cover--wide). */
/* Те саме, що й .hub-card__title нижче: .kb-card h3 (заголовки
   розділів на кшталт «Контакти») чіпляє й заголовок картки події —
   він теж h3 всередині .kb-card. Крім кольору, звідти прилітав
   margin:26px 0 8px, і відступи в картці виходили 40/22/14 замість
   рівних 14 від flex-gap. Повертаємо те, що задає сам компонент у
   components.css. */
.kb-card .card__title{margin:0;font-size:var(--fs-h4);color:var(--c-text)}

/* Два класи, а не один. `.kb-card h3` (заголовки розділів на кшталт
   «Контакти») важить (0,1,1) і перебиває `.hub-card__title` (0,1,0),
   хоч би нижче той стояв: специфічність сильніша за порядок. Через
   це правило було мертве — назва картки лишалась золотою і з
   відступами 26/8 замість нуля, і виміряти це можна лише на живій
   сторінці, бо у файлі все виглядає правильно. Колір паперовий, щоб
   акцент на картці був один — золотий чіп знижки, а не два. */
.kb-card .hub-card__title { margin: 0; font-size: var(--fs-body); line-height: 1.35; color: var(--paper); }
/* Картки новин, пропозицій і програм на головній лежать не в .kb-card,
   і заголовок брав розмір звичайного h3 (28px) — удвічі більший за
   заголовок картки зустрічі поруч. Тепер той самий, що в зустрічей
   (рішення власника 28.09.2026). */
.hub-card .hub-card__title { font-size: var(--fs-h4); line-height: 1.35; }
/* Заголовок новини під фото — дрібніший (рішення власника 28.09.2026). */
.hub-card--news .hub-card__title { font-size: 1rem; line-height: 1.35; }
/* Чіп і назва — одна група, тому між ними менше повітря, ніж до
   обкладинки над ними. З рівним gap:9px з обох боків чіп «висів»
   посередині й не читався разом із назвою. Через margin, а не gap:
   .hub-card роздає однаковий gap усім дітям. */
.hub-card__cover + .hub-tag { margin-block-start: 5px; }

/* Закрите для рівня (lockedCard у kabinet-hub.js, міграція 065):
   картку видно, але обкладинка приглушена й знебарвлена, а замок
   «Premium» лежить поверх неї в куті. Колір не повертається під
   курсором — інакше закрите виглядало б відкритим. */
.hub-card--locked .hub-card__cover { filter: grayscale(1) brightness(.72); }
.hub-card--locked .hub-card__title { color: var(--paper); opacity: .78; }
.hub-lock {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px 4px 8px;
  border-radius: 999px;
  background: rgba(8, 29, 42, .82);
  border: 1px solid rgba(242, 194, 0, .45);
  color: var(--gold-500);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .04em;
  backdrop-filter: blur(6px);
}
.hub-lock svg { width: 13px; height: 13px; flex: none; }
.hub-card--locked .hub-lock { position: absolute; top: 12px; right: 12px; z-index: 1; }
.hub-card--locked .hub-lock--inline { position: static; }
.hub-card--locked:hover { border-color: rgba(242, 194, 0, .55); }
.hub-lock--big { font-size: 12px; padding: 6px 12px 6px 10px; }
.hub-lock--big svg { width: 15px; height: 15px; }
.library-modal__body--locked { gap: 14px; max-width: 460px; }
.hub-tag + .hub-card__title { margin-block-start: -4px; }
.hub-card__meta { margin: 0; font-size: var(--fs-xs); color: var(--ink-400); line-height: 1.5; }
.hub-card__text { margin: 0; font-size: var(--fs-sm); color: var(--ink-400); line-height: 1.55; }
.hub-card__acts { display: flex; gap: 8px; flex-wrap: wrap; margin-block-start: auto; }
.hub-card .btn { margin-block-start: auto; }
.hub-card__acts .btn { margin-block-start: 0; }

.hub-tag {
  font-size: 11px;
  letter-spacing: .06em;
  text-transform: uppercase;
  padding: 4px 9px;
  border-radius: 20px;
  background: var(--ink-600);
  color: var(--ink-400);
}
/* Строк, що спливає, — єдине місце, де тут дозволено акцент. Якщо
   підсвічувати все, не підсвічено ніщо. */
.hub-tag.is-hot { background: #7d3b36; color: #ffd9d5; }
.hub-tag.is-gold { background: var(--gold-500); color: var(--ink-900); }

.hub-code { display: flex; align-items: center; gap: 9px; margin: 0; }
.hub-code__lab { font-size: var(--fs-xs); color: var(--ink-400); }
.hub-code code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  background: var(--ink-900);
  border: 1px solid var(--ink-500);
  border-radius: 6px;
  padding: 3px 9px;
  letter-spacing: .08em;
}

.hub-joined { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.hub-fine { margin: 4px 0 0; font-size: var(--fs-xs); color: var(--ink-400); line-height: 1.5; }
.hub-empty { margin-block-start: 10px; }

/* ── Меню налаштувань ─────────────────────────────────────────── */
/* Кнопка внизу того самого списку, що й вкладки, тому виглядає як
   вкладка — border-block-start відділяє її від розділів кабінету,
   бо це не ще один розділ, а вихід у попап. */
.kb-menu {
  position: relative;
  margin-block-start: 10px;
  padding-block-start: 10px;
  border-block-start: 1px solid var(--ink-600);
}
.kb-menu__btn {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  background: transparent;
  border: 0;
  border-inline-start: 3px solid transparent;
  border-radius: 8px;
  padding: 11px 14px;
  color: var(--ink-400);
  font: inherit;
  font-size: var(--fs-sm);
  text-align: start;
  cursor: pointer;
}
.kb-menu__btn:hover { background: var(--ink-700); color: var(--paper); }
.kb-menu__btn:focus-visible { outline: 2px solid var(--gold-500); outline-offset: 2px; }
.kb-menu__ico { width: 21px; height: 21px; flex: none; }
/* Панель — рівно 216px: попап на всю ширину батька, а не фіксовані
   220px, бо ті на 4px ширші за саму панель і обрізались би нею
   (overflow:hidden на .kb-tabs тримає заокруглені кути).

   Відкривається ВНИЗ від кнопки — останнього пункту списку. Раніше
   вниз обрізало б overflow:hidden на .kb-tabs (висота дорівнювала
   висоті самого списку); тепер .kb-tabs має свій min-block-size саме
   під цей попап, тож обрізати нема чому. */
.kb-menu__list {
  position: absolute;
  inset-inline-start: 0;
  inset-inline-end: 0;
  inset-block-start: calc(100% + 6px);
  background: var(--ink-700);
  border: 1px solid var(--ink-500);
  border-radius: 10px;
  padding: 6px;
  z-index: 40;
  box-shadow: 0 18px 40px rgba(0, 0, 0, .45);
}
.kb-menu__item {
  display: block;
  inline-size: 100%;
  text-align: start;
  background: none;
  border: 0;
  border-radius: 7px;
  padding: 10px 12px;
  color: var(--paper);
  font: inherit;
  font-size: var(--fs-sm);
  cursor: pointer;
}
.kb-menu__item:hover { background: var(--ink-600); }
.kb-menu__item:focus-visible { outline: 2px solid var(--gold-500); outline-offset: -2px; }
.kb-menu__item--out { color: var(--ink-400); border-block-start: 1px solid var(--ink-600);
  margin-block-start: 6px; padding-block-start: 12px; border-radius: 0 0 7px 7px; }

/* На вузькому екрані 4 плитки в стовпчик по 2 — вже не «на перший
   погляд», а прокрутка вниз. Один рядок з горизонтальним скролом
   рахує зручніше, ніж зменшення тексту до нечитабельного. */
@media (max-width: 560px) {
  .kpi-row {
    flex-wrap: nowrap;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    padding-bottom: 2px;
  }
  .kpi-row::-webkit-scrollbar { display: none; }
  .kpi-tile { flex: 0 0 128px; min-width: 128px; }

  /* «Найближчі зустрічі» на головній — той самий рядок-скрол:
     на телефоні картка на всю ширину означала б гортати вниз
     повз новини й пропозиції, щоб побачити другу подію. */
  .hub-sec--events .hub-grid {
    display: flex;
    flex-wrap: nowrap;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    padding-bottom: 2px;
  }
  .hub-sec--events .hub-grid::-webkit-scrollbar { display: none; }
  .hub-sec--events .hub-grid > * { flex: 0 0 260px; }

  /* «Пропозиції партнерів» на головній — той самий рядок-скрол. */
  .hub-sec--offers .hub-grid {
    display: flex;
    flex-wrap: nowrap;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    padding-bottom: 2px;
  }
  .hub-sec--offers .hub-grid::-webkit-scrollbar { display: none; }
  .hub-sec--offers .hub-grid > * { flex: 0 0 260px; }

  /* Картка події у вкладці «Події» (не на головній — там уже рядок-
     скрол вище): дата поруч із назвою в одному рядку замість над нею
     на всю ширину; опис — один рядок з «…» замість чотирьох; час/
     локація і кнопка запису — один рядок унизу замість трьох
     окремих. grid-column:1/-1 на card__text/card__meta-row працює
     незалежно від того, чи є card__meta (не завжди є). */
  .card--event {
    display: grid;
    grid-template-columns: auto 1fr;
    column-gap: 14px;
    row-gap: 8px;
    align-items: start;
  }
  .card--event > .card__date { grid-column: 1; grid-row: 1; }
  .card--event > .card__meta,
  .card--event > .card__title { grid-column: 2; }
  .card--event > .card__text,
  .card--event > .card__meta-row { grid-column: 1 / -1; }

  .card--event .card__text {
    display: -webkit-box;
    -webkit-line-clamp: 1;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }

  .card--event .card__meta-row {
    flex-direction: row;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px 14px;
  }
  .card--event .event-facts {
    display: flex;
    flex: 1 1 auto;
    align-items: center;
    flex-wrap: wrap;
    gap: 4px 8px;
  }
  .card--event .event-facts svg { width: 15px; height: 15px; }
  /* Розділова риска між «коли» і «де» замість другого рядка. На
     вужчих телефонах («Rebel Oslo» довше за назву й ще не влазить
     поруч) обидва пункти й так лишаються поруч, лише переносяться —
     компактніше за три окремі рядки, що були раніше. */
  .card--event .event-facts li:not(:first-child) {
    padding-inline-start: 8px;
    border-inline-start: 1px solid var(--ink-600);
  }
  .card--event .card__foot {
    margin-block-start: 0;
    padding-block-start: 0;
  }
}

/* ── Перепустка: двостороння картка ──────────────────────────────
   perspective на батьку, обидві грані absolute + backface-visibility
   — стандартний CSS-flip. Висота фіксована (--pc-h): грані absolute
   не тягнуть висоту батька самі, а обидві мусять бути однакового
   розміру. */
.kb-passcard {
  --pc-h: 260px;
  position: relative;
  inline-size: 100%;
  max-inline-size: 480px;
  block-size: var(--pc-h);
  margin-block: 18px;
  cursor: pointer;
  perspective: 1400px;
}
.kb-passcard:focus-visible { outline: 2px solid var(--gold-500); outline-offset: 4px; border-radius: 14px; }
.kb-passcard__inner {
  position: relative;
  inline-size: 100%;
  block-size: 100%;
  transition: transform 0.6s cubic-bezier(0.4, 0.2, 0.2, 1);
  transform-style: preserve-3d;
}
.kb-passcard.is-flipped .kb-passcard__inner { transform: rotateY(180deg); }
.kb-passcard__face {
  position: absolute;
  inset: 0;
  backface-visibility: hidden;
  border-radius: 14px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

/* лицьовий бік. Світліше за фон сторінки (--ink-900) і плитки над нею
   (--ink-800) — інакше картка зверху непомітно зливається з тлом.
   Три яруси: знак і номер, імʼя з рівнем, тихий рядок унизу. Одна
   золота лінія по нижньому краю — єдиний акцент. */
.kb-passcard__face--front {
  background: linear-gradient(150deg, var(--ink-700), var(--ink-600));
  color: var(--paper);
  padding: 22px 24px 20px;
  justify-content: space-between;
  box-shadow: inset 0 -3px 0 var(--gold-500);
}
/* Ванти під текстом: лежать першими в грані й нижче за решту дітей. */
.kb-passcard__face--front > * { position: relative; z-index: 1; }
.kb-passcard__face--front > .kb-passcard__cables {
  position: absolute; z-index: 0;
  inset: 0;
  inline-size: 100%; block-size: 100%;
  pointer-events: none;
}
.kb-cable {
  stroke: var(--paper);
  stroke-width: .8;
  stroke-opacity: .13;
  vector-effect: non-scaling-stroke;
  stroke-dasharray: 1;
  stroke-dashoffset: 0;
}
.kb-cable--pylon { stroke-width: 2.2; stroke-opacity: .2; }
.kb-cable--gold { stroke: var(--gold-500); stroke-opacity: .75; stroke-width: 1; }
.kb-cable-dot { fill: var(--gold-500); }
/* Промальовування — раз, при появі картки. Хто вимкнув рух, бачить
   одразу готовий малюнок. */
@media (prefers-reduced-motion: no-preference) {
  .kb-cable { animation: kb-cable-draw 1.1s cubic-bezier(.4, .1, .2, 1) both; animation-delay: calc(var(--i) * 70ms); }
  .kb-cable--gold { animation-duration: 1.6s; }
  .kb-cable-dot { animation: kb-cable-dot .5s ease-out 1.3s both; }
}
@keyframes kb-cable-draw { from { stroke-dashoffset: 1; } to { stroke-dashoffset: 0; } }
@keyframes kb-cable-dot { from { opacity: 0; transform: scale(.2); } to { opacity: 1; transform: none; } }
.kb-cable-dot { transform-box: fill-box; transform-origin: center; }

.kb-passcard__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.kb-passcard__mark { block-size: 30px; inline-size: auto; display: block; }
.kb-passcard__no {
  font-size: 12px;
  letter-spacing: 0.08em;
  color: var(--ink-400);
  font-variant-numeric: tabular-nums;
}
.kb-passcard__id { min-inline-size: 0; }
.kb-passcard__name {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(22px, 5.4vw, 28px);
  font-weight: 500;
  line-height: 1.12;
  color: var(--paper);
  overflow-wrap: anywhere;
}
.kb-passcard__tier {
  margin: 8px 0 0;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--gold-500);
}
.kb-passcard__foot {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  font-size: 12px;
  color: var(--ink-400);
}
.kb-passcard__note { min-inline-size: 0; }
.kb-passcard__hint { flex: none; letter-spacing: 0.06em; opacity: .8; }
/* зворотний бік — та сама причина світлого тла, що й раніше: сканери
   читають темне на світлому. */
.kb-passcard__face--back {
  background: var(--paper);
  color: var(--ink-900);
  transform: rotateY(180deg);
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 20px;
}
.kb-passcard__qr { inline-size: 140px; }
.kb-passcard__qr svg { display: block; inline-size: 100%; height: auto; }
.kb-passcard__backlabel { margin: 0; font-size: 14px; font-weight: 500; }
.kb-passcard__backmeta { margin: 0; font-size: 11px; color: #4a5a68; letter-spacing: 0.02em; }

@media (max-width: 420px) {
  .kb-passcard { --pc-h: 224px; }
}

/* ── Перепустка на головній ── */
.hub-status {
  display: flex;
  flex-wrap: wrap;
  align-items: stretch;
  gap: 16px;
  margin-block-end: 28px;
}
.hub-status__pass {
  flex: 1 1 420px;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 12px;
}

/* ── Коротке повідомлення ─────────────────────────────────────── */
.kb-toast {
  position: fixed;
  inset-block-end: 22px;
  inset-inline: 0;
  margin-inline: auto;
  inline-size: fit-content;
  max-inline-size: min(92vw, 460px);
  background: var(--ink-600);
  border: 1px solid var(--ink-500);
  color: var(--paper);
  border-radius: 10px;
  padding: 12px 18px;
  font-size: var(--fs-sm);
  z-index: 60;
  opacity: 0;
  transform: translateY(10px);
  pointer-events: none;
  transition: opacity .18s ease, transform .18s ease;
}
.kb-toast.is-on { opacity: 1; transform: translateY(0); }

@media (prefers-reduced-motion: reduce) {
  .kb-toast { transition: none; }
}

/* ─── Зміна рівня підписки ─────────────────────────────────────
   Розкривачка, а не постійний список: змінюють рівень рідко, а
   займав би він стільки ж місця, скільки сама підписка. */
.kb-tier-change{margin:18px 0 0;border-top:1px solid var(--ink-600);padding-top:16px}
.kb-tier-change>summary{cursor:pointer;font-size:var(--fs-sm);color:var(--ink-400);list-style:none}
.kb-tier-change>summary::-webkit-details-marker{display:none}
.kb-tier-change>summary::before{content:"+ ";color:var(--gold-500);font-weight:500}
.kb-tier-change[open]>summary::before{content:"− "}
.kb-tier-change>summary:hover{color:var(--paper)}
.kb-tier-change>summary:focus-visible{outline:2px solid var(--gold-500);outline-offset:3px}
.kb-tier-change__body{margin-top:14px}
.kb-tier-change__body .hub-grid{margin:12px 0}

/* ─── Заявка на Executive Circle і Corporate ───────────────────
   Живе в тій самій модалці, що й решта кабінету (.library-modal).
   Її тіло вирівняне по лівому краю через align-items:flex-start,
   тож формі треба явна ширина — інакше поля стискаються до
   ширини свого тексту. */
.kb-apply{width:100%}
.kb-apply__legend{margin:0 0 10px;font-size:var(--fs-xs);letter-spacing:.08em;
  text-transform:uppercase;color:var(--ink-400)}
.kb-apply__cats{display:grid;gap:8px;margin-bottom:18px}

/* Критерій — це вибір із чотирьох, тому радіо, а не кнопки.
   Підказка під назвою дослівно з BRIEF.md §3: людина має бачити,
   під що підписується, ДО того як писати відповідь. */
.kb-apply__cat{display:grid;grid-template-columns:auto 1fr;gap:10px;align-items:start;
  padding:11px 13px;border:1px solid var(--ink-600);border-radius:12px;
  background:var(--ink-700);cursor:pointer}
.kb-apply__cat:hover{border-color:var(--ink-500)}
.kb-apply__cat:has(input:checked){border-color:var(--gold-500);background:var(--ink-600)}
.kb-apply__cat:has(input:focus-visible){outline:2px solid var(--gold-500);outline-offset:2px}
.kb-apply__cat input{width:auto;margin-top:3px}
.kb-apply__cat b{display:block;font-weight:600;font-size:var(--fs-sm)}
.kb-apply__cat .kb-fine{display:block;margin-top:2px}

.kb-apply__fields{display:block}
.kb-apply .kb-f:last-of-type{margin-bottom:4px}

/* Зірочка обовʼязкового поля. Для скрінрідера працює required на
   самому полі, тож вона суто візуальна. */
.kb-req{color:var(--gold-500)}

/* Перепустка неоплаченого членства. Не ховаємо — на вході рішення
   ухвалює людина, і api/pass.js показує їй справжній стан. Але
   картка не має ВИГЛЯДАТИ чинною: золота смуга внизу тут читається
   як «усе гаразд, проходьте». */
.kb-passcard.is-pending .kb-passcard__face--front{box-shadow:inset 0 -3px 0 var(--ink-500)}

/* ─── «Запроси друга» (kabinet-hub.js) ─────────────────────────
   Другорядна дія на картці події: текст, а не друга жовта кнопка —
   головне на картці лишається «Записатися». */
.kb-invite-link{display:inline-flex;align-items:center;justify-content:center;gap:6px;
  inline-size:100%;margin-block-start:8px;padding:6px 4px;background:none;border:0;
  white-space:nowrap;
  font:inherit;font-size:var(--fs-xs);color:var(--gold-500);cursor:pointer;
  border-radius:8px}
.kb-invite-link svg{width:15px;height:15px;flex:none}
.kb-invite-link:hover{color:var(--gold-400);text-decoration:underline;text-underline-offset:3px}
.kb-invite-link:focus-visible{outline:2px solid var(--gold-500);outline-offset:2px}
/* У модалці події — поруч із кнопкою, а не на всю ширину. */
.hub-card__acts .kb-invite-link{inline-size:auto;margin:0}

/* Вікно «поділитися». Тіло .library-modal вирівняне по лівому краю,
   тож обгортці треба явна ширина — інакше поле з посиланням
   стискається до ширини тексту (та сама причина, що в .kb-apply). */
.kb-invite{inline-size:100%;display:flex;flex-direction:column;gap:10px;padding-inline-end:28px}
.kb-invite .hub-card__title{font-size:1.35rem;line-height:1.28}
.kb-invite__field{margin-block-start:4px}
.kb-invite__label{display:block;font-size:var(--fs-xs);color:var(--ink-400);margin-bottom:5px}
.kb-invite__field input{inline-size:100%;background:var(--ink-700);color:var(--paper);
  border:1px solid var(--ink-600);border-radius:10px;padding:11px 12px;font:inherit;
  font-size:var(--fs-sm);text-overflow:ellipsis}
.kb-invite__field input:focus{outline:none;border-color:var(--gold-500)}
/* Сітка 2×2: «Поділитися/Скопіювати» зверху, месенджери під ними.
   Без «Поділитися» (десктопний Firefox) кнопок три — тоді перша на
   всю ширину. */
.kb-invite__acts{display:grid;grid-template-columns:1fr 1fr;gap:8px}
.kb-invite__acts .btn{inline-size:100%;padding-inline:10px}
.kb-invite__acts .btn:first-child:nth-last-child(odd){grid-column:1 / -1}
.kb-invite__note{margin:0;font-size:var(--fs-sm);color:var(--paper)}
@media(max-width:480px){
  .kb-invite{padding-inline-end:0}
  .kb-invite .hub-card__title{padding-inline-end:34px}
}

/* Блок на головній. Навмисно маленький: перший екран — про те, що
   клуб дає, а не про лічильники. */
.kb-invite-card{display:flex;flex-wrap:wrap;align-items:center;gap:12px 16px;
  background:var(--ink-700);border:1px solid var(--ink-600);border-radius:12px;
  padding:16px 18px}
.kb-invite-card__icon{inline-size:26px;block-size:26px;color:var(--gold-500);flex:none}
.kb-invite-card__text{flex:1 1 260px;min-inline-size:0}
.kb-invite-card__title{margin:0 0 3px;font-size:var(--fs-h4)}
.kb-invite-card__lead{margin:0;color:var(--ink-400);font-size:var(--fs-sm);line-height:1.5}
.kb-invite-card__more{flex:1 1 100%}
.kb-invite-card__more>summary,.kb-invite__terms>summary{display:inline-block;cursor:pointer;
  list-style:none;font-size:var(--fs-sm);color:var(--gold-500)}
.kb-invite-card__more>summary::-webkit-details-marker,
.kb-invite__terms>summary::-webkit-details-marker{display:none}
.kb-invite-card__more>summary::after,.kb-invite__terms>summary::after{content:" +"}
.kb-invite-card__more[open]>summary::after,.kb-invite__terms[open]>summary::after{content:" −"}
.kb-invite-card__more>summary:focus-visible,
.kb-invite__terms>summary:focus-visible{outline:2px solid var(--gold-500);outline-offset:3px;border-radius:4px}
.kb-invite-card__stats{margin:10px 0 0;font-size:var(--fs-sm);color:var(--paper)}
.kb-invite__terms{font-size:var(--fs-xs);color:var(--ink-400);line-height:1.5}
.kb-invite__terms>summary{font-size:var(--fs-xs)}
.kb-invite__rules{margin:8px 0 6px;padding-inline-start:18px}
.kb-invite__rules li{margin-bottom:4px}
.kb-invite__terms p{margin:0}
.kb-invite__terms a{color:var(--gold-500)}
.kb-invite__scratch{position:absolute;inset-inline-start:-9999px;opacity:0}
.kb-invite-list{list-style:none;margin:10px 0 0;padding:0;display:flex;flex-direction:column}
.kb-invite-list li{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:2px 12px;
  padding:8px 0;border-top:1px solid var(--ink-600);font-size:var(--fs-sm)}
.kb-invite-list li:first-child{border-top:0}
.kb-invite-list__name{font-weight:600}
.kb-invite-list__event{grid-column:1;color:var(--ink-400);font-size:var(--fs-xs)}
.kb-invite-list__status{grid-column:2;grid-row:1 / span 2;align-self:center;text-align:end;
  color:var(--ink-400);font-size:var(--fs-xs);max-inline-size:30ch}
.kb-invite-list__status.is-good{color:#3DBE7B}
@media(max-width:560px){
  /* Іконка тут забирала б колонку в і так вузького тексту. */
  .kb-invite-card__icon{display:none}
  .kb-invite-card .btn{inline-size:100%}
  .card--event .kb-invite-link svg{display:none}
  .card--event .kb-invite-link{white-space:nowrap;margin-block-start:4px}
  .kb-invite-list li{grid-template-columns:minmax(0,1fr)}
  .kb-invite-list__status{grid-column:1;grid-row:auto;text-align:start;max-inline-size:none}
}

/* Пропозиція після запису на подію. Там само, де toast, і так само
   зникає сама — але з кнопкою, тож кліки їй потрібні. */
.kb-nudge{position:fixed;inset-block-end:22px;inset-inline:0;margin-inline:auto;
  inline-size:fit-content;max-inline-size:min(calc(100vw - 32px),520px);z-index:90;
  display:flex;align-items:center;gap:12px;padding:12px 12px 12px 18px;
  background:var(--ink-600);border:1px solid var(--ink-500);border-radius:12px;
  color:var(--paper);box-shadow:0 10px 30px rgba(5,15,24,.45);
  opacity:0;transform:translateY(10px);pointer-events:none;visibility:hidden;
  transition:opacity .18s ease,transform .18s ease,visibility 0s linear .18s}
.kb-nudge.is-on{opacity:1;transform:translateY(0);pointer-events:auto;visibility:visible;
  transition:opacity .18s ease,transform .18s ease}
.kb-nudge__text{font-size:var(--fs-sm);line-height:1.45;min-inline-size:0}
.kb-nudge .btn{flex:none}
.kb-nudge__close{flex:none;display:flex;align-items:center;justify-content:center;
  inline-size:30px;block-size:30px;border-radius:50%;background:transparent;
  border:1px solid var(--ink-500);color:var(--ink-400);cursor:pointer}
.kb-nudge__close svg{width:14px;height:14px}
.kb-nudge__close:hover{color:var(--paper);border-color:var(--gold-500)}
/* У модалці події — звичайний рядок під кнопкою. */
.kb-nudge--inline{position:static;inline-size:100%;max-inline-size:none;margin:4px 0 0;
  opacity:1;transform:none;pointer-events:auto;visibility:visible;box-shadow:none;
  background:var(--ink-700);border-color:var(--ink-600);justify-content:space-between;flex-wrap:wrap}
@media(max-width:780px){
  /* Над нижньою панеллю, а не під нею. */
  .kb-nudge:not(.kb-nudge--inline),.kb-toast{inset-block-end:calc(84px + env(safe-area-inset-bottom))}
}
@media(prefers-reduced-motion:reduce){.kb-nudge{transition:none}}

/* ─── Історія оплат ───
   На телефоні шість колонок не влазять: кожен рядок стає маленькою
   карткою — дата й сума вгорі, спосіб і статус під ними. */
.kb-pay__note{display:block;margin-top:2px;color:var(--ink-400);font-size:var(--fs-xs)}
.kb-table--pay tr.is-bonus .kb-pay__sum{color:var(--gold-500);font-weight:600}
.kb-table--pay .kb-pay__sum{white-space:nowrap}
@media(max-width:560px){
  .kb-table--pay thead{display:none}
  .kb-table--pay,.kb-table--pay tbody{display:block}
  .kb-table--pay tr{display:grid;grid-template-columns:minmax(0,1fr) auto;
    gap:3px 12px;padding:11px 0;border-bottom:1px solid var(--ink-700)}
  .kb-table--pay td{padding:0;border:0}
  .kb-table--pay .kb-pay__date{grid-column:1;grid-row:1;color:var(--ink-400);font-size:var(--fs-xs)}
  .kb-table--pay .kb-pay__sum{grid-column:2;grid-row:1;text-align:end;font-weight:600}
  .kb-table--pay .kb-pay__method{grid-column:1;grid-row:2}
  .kb-table--pay .kb-pay__status{grid-column:2;grid-row:2;text-align:end;color:var(--ink-400)}
  .kb-table--pay .kb-pay__period{grid-column:1 / -1;color:var(--ink-400);font-size:var(--fs-xs)}
  .kb-table--pay .kb-pay__receipt{grid-column:1 / -1}
  .kb-table--pay .kb-pay__receipt:empty{display:none}
}

/* Заголовок модалки не мусить заходити під хрестик закриття. */
.library-modal__body > .hub-card__title:first-child{padding-inline-end:36px}
