/* NtS 2027 — ніч → світло → ніч.
   Дисплей: Bodoni Moda. Текст: Onest. Рух: тільки transform/opacity. */

/* ── шрифти ───────────────────────────────────────────────────────────────
   Лежать у нас, а не на Google CDN. Річ не у вазі (210 КБ або так, або так),
   а в тому, що звернення до fonts.gstatic.com передає IP кожного відвідувача
   третій стороні. У ЄС це не теорія: німецькі суди визнавали таке
   вбудовування порушенням GDPR, і позови проти власників сайтів були. Сайт
   фундації з польською аудиторією не має підставлятися на порожньому місці.

   Обидві гарнітури під SIL OFL — самохостинг дозволений прямо; тексти
   ліцензій лежать поруч у assets/fonts/.

   Взято лише latin і latin-ext: цього досить для польської й англійської.
   Кирилицю, в'єтнамську, математичні й символьні підмножини не тягнемо —
   це ще дев'ять файлів, які нікому тут не потрібні.

   unicode-range лишаємо як у Google: браузер бере latin-ext лише тоді, коли
   на сторінці справді є ł, ą, ę — а вони є, тож обидва й вантажаться.     */
/* latin-ext */
@font-face {
  font-family: 'Bodoni Moda';
  font-style: italic;
  font-weight: 400 900;
  font-display: swap;
  src: url(assets/fonts/bodoni-moda-italic-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Bodoni Moda';
  font-style: italic;
  font-weight: 400 900;
  font-display: swap;
  src: url(assets/fonts/bodoni-moda-italic-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* latin-ext */
@font-face {
  font-family: 'Bodoni Moda';
  font-style: normal;
  font-weight: 400 900;
  font-display: swap;
  src: url(assets/fonts/bodoni-moda-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Bodoni Moda';
  font-style: normal;
  font-weight: 400 900;
  font-display: swap;
  src: url(assets/fonts/bodoni-moda-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* latin-ext */
@font-face {
  font-family: 'Onest';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url(assets/fonts/onest-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Onest';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url(assets/fonts/onest-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root{
  /* ніч — з постера 2027 */
  /* Ніч не чиста, а з домішкою брендового фіолету — одна на весь сайт:
     перший екран, підвал, переглядачі альбому й сторіс, затемнення під
     вікнами. Чиста #01080E поруч із фіолетовою сторінкою читалася як
     чужа. 14% — межа, за якою кулі на першому екрані йдуть у бузок. */
  /* БЕТА (палітра банера, 03.10.2026): ніч холодніша, синьо-фіолетова,
     акцент — Sunset #FFC880 замість золота постера */
  --night-900:#0F0733;
  --night-800:#160A45; --night-700:#1E0F5C; --night-600:#3A28B0;
  --chrome:#FFC880; --mist:#C3C7EE; --steel:#8C92C8;
  /* світло — з каталогу */
  --violet:#4E2BC9; --violet-deep:#2F1A85; --paper:#FCFAF7; --ink:#15121A;
  /* золото постера, притемнене до читабельного на світлому:
     воно повертає внизу теплу ноту з першого екрана */
  --gold:#93671B;

  /* службові, перевизначаються в .mode-* */
  --surface:var(--paper);
  --accent:var(--violet);
  --hair:color-mix(in srgb, currentColor 14%, transparent);
  /* Не колір, а прозорість, тож усе, що лежить під текстом, просвічує крізь
     нього. На світлових плямах 62% давали 4.03:1 при потрібних 4.5 — саме
     тому, що плями стали активніші. 68% тримають 5.5:1 на найщільнішій
     точці плями й 6.4:1 на чистому папері. */
  --muted:color-mix(in srgb, currentColor 68%, transparent);

  --wrap:min(76rem, 100% - 2.5rem);
  /* Крок між секціями. Міра тут не піксель, а рядок тексту: просвіт між
     розділами має бути 4–6 рядків, інакше сторінка не дихає. Було
     clamp(2.5rem, 2.9vw, 3rem) — на 1440 це 42px з обох боків, тобто 84px,
     або 2.9 рядка. Замало вдвічі. Тепер на 1440 виходить 63px (4.4 рядка),
     на телефоні майже те саме, що було. */
  --step:clamp(2.75rem, 4.4vw, 5rem);
  --fade:clamp(6rem, 16vw, 14rem);   /* висота переходу ніч↔світло */
  --ease:cubic-bezier(.22,1,.36,1);

  --t-eyebrow:clamp(.6875rem, .65rem + .12vw, .8125rem);
  --t-title:clamp(2.25rem, 1.15rem + 3.7vw, 4.25rem);
  --t-lead:clamp(1.125rem, 1rem + .7vw, 1.625rem);
}

*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth}
@media (prefers-reduced-motion:reduce){ html{scroll-behavior:auto} }
body{margin:0;font-family:"Onest",system-ui,sans-serif;color:var(--ink);background:var(--paper);
  /* Стеля 1.125rem (18px) давала 61 знак у рядку при колонці 571px — трохи
     вужче за комфортні 66, і око читало це як «завеликий шрифт». 17px дають
     рівно 65. Низ клампа не чіпаємо: на телефоні 16px правильні. */
  font-size:clamp(1rem,.95rem + .25vw,1.0625rem);line-height:1.6;text-wrap:pretty;
  -webkit-font-smoothing:antialiased;overflow-x:hidden}
img,picture,svg{display:block;max-width:100%;height:auto}
:where(a):focus-visible,:where(button):focus-visible{
  outline:2px solid currentColor;outline-offset:3px;border-radius:6px}
/* currentColor годиться доти, доки колір напису контрастує з тим, що НАВКОЛО
   кнопки. У суцільної це не так: її напис підібрано під заливку. Вночі він
   майже чорний — і рамка зникала на темному першому екрані; на папері він
   білий — і рамка зникала на папері. Обидва випадки лишали кнопку, по якій
   ходять з клавіатури, без жодної позначки фокуса. Рамці потрібен колір
   секції, а не кнопки. */
.mode-night .btn--primary:focus-visible,
.nav.on-night .btn--primary:focus-visible{outline-color:#fff}
.mode-light .btn--primary:focus-visible,
.nav.on-light .btn--primary:focus-visible{outline-color:var(--ink)}

.wrap{position:relative;z-index:1;width:var(--wrap);margin-inline:auto}
.section{position:relative;padding-block:var(--step)}
/* плівкове зерно на всіх нічних зонах — тихе, як на банері */
.mode-night{background:url("assets/grain.png") 0 0/256px,var(--night-900);color:#fff;--surface:var(--night-900);--accent:var(--chrome)}
.mode-light{background:var(--paper);color:var(--ink);--surface:var(--paper);--accent:var(--violet)}

/* ── перехід між зонами ───────────────────────────────────────────────────
   Світла секція після нічної «проявляється» з темряви, і навпаки.          */
.mode-night + .mode-light,
.mode-light + .mode-night{ isolation:isolate }
.mode-night + .mode-light::before,
.mode-light + .mode-night::before{
  content:"";position:absolute;inset-inline:0;top:0;height:var(--fade);z-index:0;pointer-events:none}
.mode-night + .mode-light::before{background:linear-gradient(to bottom,var(--night-900),transparent)}
.mode-light + .mode-night::before{background:linear-gradient(to bottom,rgba(255,236,208,.16),transparent)}

/* ── світлові плями ───────────────────────────────────────────────────────
   Великі розмиті кола у світлих секціях: сторінка перестає бути просто білою,
   а фіолет із золотом ще раз перегукуються з першим екраном.               */
.has-glow{isolation:isolate}
.has-glow::after{content:"";position:absolute;inset:0;z-index:0;pointer-events:none;
  background:
    radial-gradient(58rem 46rem at var(--g1,14% 18%),
      color-mix(in srgb,var(--violet) 18%,transparent), transparent 78%),
    radial-gradient(46rem 38rem at var(--g2,86% 76%),
      color-mix(in srgb,var(--gold) 14%,transparent), transparent 76%),
    /* третя пляма — теплим золотом постера (`--chrome`), а не притемненим
       `--gold`. Воно світліше, тож відсоток більший; дає ту саму персикову
       ноту, що на першому екрані, і зв'язує низ сторінки з верхом. */
    radial-gradient(38rem 30rem at var(--g3,62% 12%),
      color-mix(in srgb,var(--chrome) 26%,transparent), transparent 74%);
  /* до верхнього й нижнього краю пляма сходить нанівець — інакше вона
     обривається на межі секції і читається як лінія */
  -webkit-mask-image:linear-gradient(to bottom,transparent 0,#000 30%,#000 70%,transparent 100%);
          mask-image:linear-gradient(to bottom,transparent 0,#000 30%,#000 70%,transparent 100%)}

/* ── іконки ───────────────────────────────────────────────────────────── */
.ico{width:1.125em;height:1.125em;flex:none}
.ico--lg{width:1.75rem;height:1.75rem}

/* ── смуга прогресу ───────────────────────────────────────────────────── */
/* смуга прогресу читання. Коли випливає шапка — з'їжджає їй під низ,
   а не лишається над нею. */
.progress{position:fixed;inset:0 0 auto;height:2px;z-index:45;pointer-events:none;
  background:color-mix(in srgb,#8d8d8d 22%,transparent);
  transition:transform .45s var(--ease)}
body.nav-on .progress{transform:translateY(var(--nav-h,4.875rem))}
.progress__bar{display:block;height:100%;width:100%;transform:scaleX(0);transform-origin:0 50%;
  background:linear-gradient(90deg,var(--violet),var(--chrome))}

/* ── липка шапка ──────────────────────────────────────────────────────── */
/* ── сторінка, якої немає ─────────────────────────────────────────────────
   Ніч, як на першому екрані: людина потрапила не туди, і перше, що вона має
   впізнати, — що це той самий сайт, а не помилка хостингу. Дві мови поруч,
   бо мови відвідувача ми тут не знаємо.                                   */
.nf{min-height:100svh;display:grid;align-content:center;text-align:center}
.nf .wrap{max-width:34rem}
.nf__mark{margin:0 auto}
.nf__mark img{width:clamp(9rem,26vw,13rem);height:auto;margin-inline:auto}
.nf__title{margin:clamp(1.5rem,4vh,2.5rem) 0 0;
  font-family:"Bodoni Moda",serif;font-optical-sizing:auto;font-weight:700;
  font-size:clamp(1.875rem,1.2rem + 2.4vw,2.75rem);line-height:1.05;
  letter-spacing:-.015em}
.nf__lead{margin:1rem auto 0;max-width:34ch;color:color-mix(in srgb,#fff 70%,transparent)}
.nf__lead--alt{margin-top:.35rem;font-size:.875rem;
  color:color-mix(in srgb,#fff 48%,transparent)}
.nf__back{margin:clamp(1.75rem,4vh,2.5rem) 0 0}
.nf__back--alt{margin-top:.85rem;font-size:.875rem}
.nf__back--alt a{color:color-mix(in srgb,#fff 62%,transparent);
  text-decoration:underline;text-underline-offset:.25em;
  text-decoration-color:color-mix(in srgb,#fff 30%,transparent)}
.nf__back--alt a:hover{color:#fff;text-decoration-color:currentColor}

/* ── сторінка з політикою приватності ─────────────────────────────────────
   Окремий документ, не вікно: на юридичний текст мусить бути адреса, щоб на
   нього можна було послатися й щоб він відкривався без скрипта. Навігації
   тут немає — нема куди вести зміст і нічому з'являтися при прокрутці, —
   тому верхнє поле задаємо самі.                                          */
.legal{padding-block:clamp(2rem,6vh,4rem) clamp(3rem,8vh,6rem)}
.legal .wrap{max-width:44rem}
.legal__back{display:inline-flex;align-items:center;gap:.5rem;min-height:2.75rem;
  font-size:.875rem;font-weight:600;color:var(--accent);text-decoration:none}
.legal__back:hover span{text-decoration:underline;text-underline-offset:.25em}
.legal__arrow{width:.9rem;height:.9rem;rotate:180deg}
.legal__title{margin:clamp(1.25rem,3vw,2rem) 0 0;
  font-family:"Bodoni Moda",serif;font-optical-sizing:auto;font-weight:700;
  font-size:clamp(2rem,1.2rem + 2.6vw,3rem);line-height:1.05;letter-spacing:-.015em;
  color:var(--violet)}
.legal__meta{margin:.75rem 0 0;font-size:.8125rem;letter-spacing:.06em;
  text-transform:uppercase;color:var(--muted)}
/* Вступ крупніший за решту: у ньому головна відповідь, і далі можна не
   читати, якщо питання було саме про куки. */
.legal__lead{margin-top:clamp(1.5rem,4vw,2.25rem);font-size:var(--t-lead);
  line-height:1.5}
.legal__lead p{margin:0 0 .75rem}
.legal__block{margin-top:clamp(1.75rem,4vw,2.5rem)}
.legal__block h2{margin:0 0 .6rem;font-size:1.0625rem;font-weight:600;
  letter-spacing:-.01em}
.legal__block p{margin:0 0 .6rem;color:var(--muted)}
.legal__list{list-style:none;margin:.25rem 0 0;padding:0;display:grid;gap:.4rem;
  color:var(--muted)}
.legal__list li{position:relative;padding-left:1.15rem}
.legal__list li::before{content:"";position:absolute;left:0;top:.55em;
  width:.45rem;height:.45rem;border-radius:50%;
  border:1.5px solid var(--accent)}
/* Дрібний шрифт: хто стоїть за сайтом і політика приватності. Окремий рядок
   у самому низу, під стовпчиками, відділений тонкою лінією. Їх шукають уже
   після корисного — але коли шукають, вони мусять бути. */
/* Реквізити ліворуч, політика праворуч, по краях рядка. Поки обоє
   вміщаються — це один рядок; коли ні, посилання йде під реквізити цілим
   шматком. Ширину реквізитів НЕ обмежуємо: із `max-width` вони ламалися на
   два рядки задовго до краю, і праворуч від них зяяла дірка з посиланням,
   що висіло на першому рядку. */
/* Нижнє поле — місце для кнопки «догори». Вона `fixed` у правому нижньому
   куті, і коли догортати до кінця, вона опиняється рівно над останнім
   рядком. Найдешевше рішення — лишити їй порожнє місце, а не ганяти
   видимість кнопки. */
.foot__fine{grid-column:1/-1;margin-top:clamp(1.75rem,4vw,2.5rem);
  padding-top:clamp(1rem,2.5vw,1.5rem);padding-bottom:3.5rem;
  border-top:1px solid var(--hair);
  display:flex;flex-wrap:wrap;justify-content:space-between;
  gap:.5rem 2.5rem;align-items:baseline}
/* Три рядки, а не абзац: назва, адреса, номери. Кожен рядок — самостійна
   одиниця, і жоден не переноситься посеред себе. */
.foot__entity{flex:1 1 34rem;margin:0;font-size:.8125rem;line-height:1.5;
  color:var(--muted);text-wrap:pretty;
  display:grid;justify-items:start;gap:.1rem}
.foot__entity :is(strong,b){font-weight:600;color:inherit}
/* Номери не читають — їх звіряють, і номер, розірваний переносом, звіряти
   неможливо. Тому кожен цілий, а переноситься лише проміжок між ними. */
.foot__reg{display:flex;flex-wrap:wrap;gap:.1rem 1.1rem}
.foot__reg i{font-style:normal;white-space:nowrap;font-variant-numeric:tabular-nums}
/* На телефоні дрібний шрифт підвалу тримаємо на одному рівні: юридичний
   рядок не має бути помітнішим за примітку під маркою. */
@media (max-width:51.99rem){
  .foot__entity,.foot__legal{font-size:.75rem}
}
/* Три номери в рядок не вміщаються вже від ~450px, і перенос давав два в
   першому рядку й один у другому — розбивку, яка нічого не означає. Там,
   де вони не стають поруч, кожен іде своїм рядком: це перелік, і читається
   він стовпчиком. Вище межі рядок лишається рядком. */
@media (max-width:28rem){
  .foot__reg{display:grid;gap:.15rem;justify-items:start}
}
/* Підкреслення тут обов'язкове: без нього рядок читається як звичайний
   текст, а не як посилання — кольору замало, бо він приглушений. */
/* Простір для пальця — всередину, зовнішнє поле від'ємне: рядок лишається
   на місці, ціль дотику доростає до 24px. */
.foot__legal{flex:none;margin:0;font-size:.8125rem;white-space:nowrap}
.foot__legal a{display:inline-block;padding-block:.4rem;margin-block:-.4rem}
.foot__legal a{text-decoration:underline;text-underline-offset:.25em;
  text-decoration-thickness:1px;
  text-decoration-color:color-mix(in srgb,currentColor 45%,transparent)}
.foot__legal a:hover{text-decoration-color:currentColor}
.foot__legal a{color:var(--muted)}
.foot__legal a:hover{color:inherit}

/* ── пропуск на контент ───────────────────────────────────────────────────
   Перший Tab на сторінці. Лишається у порядку фокуса завжди, але стоїть за
   верхнім краєм — тому виводимо його зсувом, а не display:none: схований
   так він випав би з обходу й сенсу не мав би.                            */
.skip{position:fixed;top:.75rem;left:.75rem;z-index:60;
  display:inline-flex;align-items:center;min-height:2.75rem;
  padding:.65rem 1.25rem;border-radius:999px;
  background:var(--violet);color:#fff;text-decoration:none;
  font-size:.875rem;font-weight:600;
  box-shadow:0 10px 30px -12px color-mix(in srgb,var(--night-900) 65%,transparent);
  translate:0 -250%;transition:translate .28s var(--ease)}
.skip:focus-visible{translate:0;outline:2px solid #fff;outline-offset:-5px}

.nav{position:fixed;inset:0 0 auto;z-index:50;
  transform:translateY(-105%);
  transition:transform .45s var(--ease),background-color .4s ease,color .4s ease;
  backdrop-filter:saturate(1.8) blur(22px) brightness(1.04);
  -webkit-backdrop-filter:saturate(1.8) blur(22px) brightness(1.04);
  /* Смуга йде на всю ширину, тож ребра в неї одне — нижнє. Воно те саме, що
     в кнопок: світла лінія і за нею ледь помітна, разом вони читаються як
     товщина скла. Плюс м'яка тінь, щоб смуга лежала НАД сторінкою, а не
     була її частиною. */
  border-bottom:0;
  box-shadow:
    inset 0 -1px 0 rgba(255,255,255,.34),
    0 1px 0 color-mix(in srgb,var(--night-900) 10%,transparent),
    0 10px 28px -20px color-mix(in srgb,var(--night-900) 55%,transparent);
  /* Відблиск по верхньому краю — світло падає згори. */
  background-image:linear-gradient(to bottom,
    rgba(255,255,255,.13),rgba(255,255,255,0) 62%)}
.nav.is-on{transform:none}
/* Тіло прозоріше, ніж було (72/78%): на такій щільності смуга читалася як
   суцільна панель, а не як скло. Далі йти нема куди — це заміряна межа.
   Нічна найгірше стоїть над яскравою кулею першого екрана (сірий дрібний
   4.65:1), світла — над темною фотосмугою всередині світлої секції
   (4.73:1); шапка там лишається світлою, бо режим береться від секції, а
   не від яскравості картинки. Поріг 4.5:1. */
.nav.on-night{background-color:color-mix(in srgb,var(--night-900) 62%,transparent);color:#fff;
  --accent:var(--chrome)}
.nav.on-light{background-color:color-mix(in srgb,#fff 70%,transparent);color:var(--ink);
  --accent:var(--violet)}
.nav.on-light{box-shadow:
  inset 0 -1px 0 rgba(255,255,255,.9),
  0 1px 0 color-mix(in srgb,var(--ink) 9%,transparent),
  0 10px 26px -20px color-mix(in srgb,var(--ink) 40%,transparent)}
.nav__in{width:var(--wrap);margin-inline:auto;min-height:4.875rem;
  display:flex;align-items:center;gap:1.25rem}
.nav__home{margin-right:auto;text-decoration:none;color:inherit;
  display:inline-flex;align-items:center;gap:.6rem}
/* знак події — маскою, а не картинкою: так він сам бере колір шапки */
.nav__logo{width:4.9rem;aspect-ratio:310/195;background:currentColor;
  -webkit-mask:url("assets/logos/night-to-shine.svg") center/contain no-repeat;
          mask:url("assets/logos/night-to-shine.svg") center/contain no-repeat}
.nav__year{font-size:1.0625rem;font-weight:600;letter-spacing:.02em;color:var(--accent)}
.nav__meta{display:none;margin:0;align-items:center;gap:.5rem;font-size:.8125rem;
  letter-spacing:.06em;text-transform:uppercase;color:var(--muted)}
.nav__meta .ico{width:1rem;height:1rem}
.nav__dot{width:3px;height:3px;border-radius:50%;background:currentColor;opacity:.45;
  margin-inline:.35rem}
@media (min-width:56rem){ .nav__meta{display:flex} }
.nav__act{display:flex;gap:.5rem}

/* ── шапка секції ─────────────────────────────────────────────────────── */
.sect-head{margin:0 0 clamp(2rem,4vw,3.25rem)}
.sect-head__rule{display:block;height:1px;background:currentColor;opacity:.18;
  transform:scaleX(0);transform-origin:0 50%;transition:transform 1.1s var(--ease)}
.is-in .sect-head__rule{transform:scaleX(1)}
.eyebrow{display:flex;align-items:baseline;gap:.75rem;margin:1rem 0 clamp(.75rem,2vw,1.5rem);
  font-size:var(--t-eyebrow);font-weight:500;letter-spacing:.16em;text-transform:uppercase;
  color:var(--muted)}
.eyebrow__num{font-style:normal;font-weight:600;letter-spacing:.06em;color:var(--accent)}
.mode-light .eyebrow__num{color:var(--gold)}
/* заголовок і необов'язкова дія праворуч — на спільному нижньому краї */
/* Дія праворуч тримається ПЕРШОГО рядка заголовка, а не останнього: коли
   заголовок у два рядки, притиснута донизу кнопка з'їжджала на другий і
   висіла в порожнечі. Базова лінія робить це саме по типографіці. */
.sect-head__row{display:flex;align-items:baseline;justify-content:space-between;
  gap:1rem 2rem;flex-wrap:wrap}
/* Заголовок має віддавати ширину, а не зіштовхувати дію вниз: у нього
   `max-width: 17ch`, і на планшеті цей БОКС (а не найдовший рядок) разом
   із кнопкою не влазив у рядок, хоча вільного місця було вдосталь. */
.sect-head__row > :first-child{flex:1 1 14ch;min-width:0}
.sect-head__row > :last-child:not(:first-child){flex:none}
/* Bodoni Moda — змінний шрифт із віссю оптичного розміру (6..96). При
   `font-optical-sizing:auto` браузер ставить вісь рівною кеглю, і на великих
   заголовках вмикається дисплейний накрес: волосяні штрихи там навмисно
   тонші за папір. На екрані вони підрізаються до субпікселя й мерехтять.
   Тому вісь фіксуємо на 18 — це текстовий накрес у дисплейному кеглі:
   контраст штриха лишається бодонівським, але нитки тримають вагу.
   `font-variation-settings` перебиває `font-optical-sizing`, тож той в
   оголошеннях нижче лишається як запасний для браузерів без змінних осей. */
:is(.section__title,.path h3,.st__text h3,.stat__value,.quote p,
    .band__value,.band__unit,.sheet__title,.foot__mark,
    .hero__lead em,.prose em){font-variation-settings:"opsz" 18}

.section__title{font-family:"Bodoni Moda",serif;font-optical-sizing:auto;font-weight:700;
  font-size:var(--t-title);line-height:.98;letter-spacing:-.018em;
  margin:0;max-width:17ch;text-wrap:balance}
.mode-light .section__title{color:var(--violet)}
.mode-night .section__title{color:#fff}
.section__title em{font-style:italic;font-weight:400}

/* поява заголовка по словах */
/* Поле навколо слова більше за самі літери: слово лежить у «шторці»
   з `overflow:hidden`, і все, що виходить за межі коробки, зрізається.
   У Bodoni «ą»/«ę» мають хвостик униз, а «j» — гак ліворуч. */
.w{display:inline-block;overflow:hidden;vertical-align:bottom;
  padding:.08em .18em .28em;margin:-.08em -.18em -.28em}
/* Курсивний гак довший за прямий: заміряно на канві — «j» виходить ліворуч
   рівно на .25em при будь-якому кеглі. Загальні .18em його підрізали, тож
   курсивним словам даємо більше поля. Негативне поле те саме, тож розкладка
   не зсувається ні на піксель. */
:is(em,i) .w{padding-left:.34em;margin-left:-.34em}
.w > i{display:inline-block;font-style:inherit;transform:translateY(115%);
  transition:transform .85s var(--ease);transition-delay:calc(var(--d) * 55ms)}
.is-in .w > i{transform:none}

/* ── кнопки ───────────────────────────────────────────────────────────── */
.actions{display:flex;flex-wrap:wrap;gap:.75rem;margin-top:clamp(2rem,3.5vw,2.75rem)}
/* Коли кнопки стають одна під одну, різна ширина одразу впадає в око.
   Сітка в один стовпець дає їм спільну ширину — по найдовшому напису. */
@media (max-width:40rem){
  .actions{display:grid;grid-template-columns:minmax(0,max-content);justify-content:start}
  .section--hero .actions,.section--cta .actions,.mid .actions{justify-content:center}
}
.btn{position:relative;display:inline-flex;align-items:center;justify-content:center;gap:.6rem;
  min-height:3.5rem;padding:.9rem 1.75rem;border-radius:999px;overflow:hidden;isolation:isolate;
  font:inherit;font-weight:600;font-size:1rem;line-height:1;text-decoration:none;white-space:nowrap;
  border:1px solid transparent;
  transition:color .3s ease,border-color .3s ease,transform .3s var(--ease)}
.btn::before{content:"";position:absolute;inset:0;z-index:-1;border-radius:inherit;
  transform:translateY(101%);transition:transform .45s var(--ease)}
.btn:hover{transform:translateY(-2px)}
.btn:hover::before{transform:none}
.btn__ico{width:1.05rem;height:1.05rem;transition:transform .35s var(--ease)}
.btn:hover .btn__ico{transform:translateX(.25rem)}
.btn--sm{min-height:2.5rem;padding:.5rem 1.05rem;font-size:.875rem;gap:.4rem}
.btn--sm .btn__ico{width:.9rem;height:.9rem}

.btn--primary{background:var(--accent);color:var(--night-900);border-color:var(--accent)}
.btn--primary::before{background:#fff}
.mode-light .btn--primary,.nav.on-light .btn--primary{color:#fff}
.mode-light .btn--primary::before,.nav.on-light .btn--primary::before{background:var(--night-900)}
.btn--primary:hover{color:var(--night-900)}
.mode-light .btn--primary:hover,.nav.on-light .btn--primary:hover{color:#fff}

/* заливку задаємо явно, а не через currentColor: на наведенні колір тексту
   змінюється на колір фону, і кнопка зафарбувалася б сама в себе */
.btn--ghost{border-color:color-mix(in srgb,currentColor 38%,transparent);color:inherit}
.btn--ghost::before{background:#fff}
.mode-night .btn--ghost:hover,.nav.on-night .btn--ghost:hover{color:var(--night-900);border-color:#fff}
.mode-light .btn--ghost,.nav.on-light .btn--ghost{color:var(--violet)}
.mode-light .btn--ghost::before,.nav.on-light .btn--ghost::before{background:var(--violet)}
.mode-light .btn--ghost:hover,.nav.on-light .btn--ghost:hover{color:#fff;border-color:var(--violet)}

/* ── скло ─────────────────────────────────────────────────────────────────
   Liquid Glass — це не «розмиття під кнопкою». Матове скло дає блюр і один
   кант, і на око це лишається кнопкою з розмиттям. Різницю робить ребро:
   в Apple його видно як ТОВЩИНУ — світла лінія всередині канта і за нею ще
   одна, ледь помітна. Око читає цю пару як край лінзи. Плюс яскрава дуга
   блікy згори-ліворуч і слабкий відсвіт знизу-праворуч, як відбите світло.
   Тіло при цьому майже прозоре: скло має показувати, що під ним.
   Ребро малює ::after, а не сам елемент: ::before у кнопки вже зайнятий
   заливкою, що виїжджає на наведенні, а блік мусить лежати під написом,
   тож він іде фоновою картинкою.
   Родина поверхонь тут ширша за .btn: капсули відкривачів альбому й
   записів і кнопка «догори» — такі самі кнопки, просто з іншим родоводом
   у розмітці.                                                             */
/* Капсули відкривачів (.gallery__more, .vids__more) сюди не входять: вони
   завжди лежать на рівному папері, де блюру нема чого розмивати — увесь
   їхній вигляд тримає кант. Без backdrop-filter вони заразом не тягнуть
   за собою .sect-head у правило «контейнер зі склом не розчиняється», і
   заголовки розділів з'являються однаково скрізь. */
:is(.btn,.lb__x,.lb__nav,.vid__btn,.rail__top){
  -webkit-backdrop-filter:blur(20px) saturate(1.8) brightness(1.06);
  backdrop-filter:blur(20px) saturate(1.8) brightness(1.06);
  background-image:
    radial-gradient(120% 90% at 24% -34%,rgba(255,255,255,.4),rgba(255,255,255,0) 58%),
    radial-gradient(100% 80% at 82% 132%,rgba(255,255,255,.19),rgba(255,255,255,0) 60%)}
/* Капсули відкривачів у розмітці нічим не позиційовані — ребру потрібна
   точка відліку. */
.gallery__more,.vids__more{position:relative}
.btn,.lb__x,.lb__nav,.vid__btn,.gallery__more,.vids__more{
  box-shadow:
    0 1px 2px -1px color-mix(in srgb,var(--night-900) 55%,transparent),
    0 10px 28px -12px color-mix(in srgb,var(--night-900) 60%,transparent)}
.btn{transition:color .3s ease,border-color .3s ease,transform .3s var(--ease),
     box-shadow .35s ease,background-color .35s ease}
:is(.btn,.lb__x,.lb__nav,.vid__btn,.gallery__more,.vids__more,.rail__top)::after{
  content:"";position:absolute;inset:0;z-index:1;border-radius:inherit;
  pointer-events:none;
  box-shadow:
    inset 0 0 0 1px rgba(255,255,255,.5),
    inset 0 0 0 2.5px rgba(255,255,255,.09),
    inset 0 1.5px .5px -.5px rgba(255,255,255,.85),
    inset 0 -1.5px .5px -.5px rgba(255,255,255,.32);
  }
/* Край лінзи збирає світло: вузьке кільце по самому канту має власне
   заломлення — яскравіше й контрастніше за тіло. У справжньої лінзи край
   світліший, бо в ньому більше товщини, і саме це відрізняє скло від
   матової плівки. Кільце вирізає маска «усе мінус вміст»: padding задає
   ширину, border-radius успадковується.

   Один раз я це вже знімав, вирішивши, що саме звідси беруться дивні
   обводки на телефоні. Виявилося, ні: винен був стрибок скла в кінці
   появи (див. нижче про контейнери зі склом), і його полагоджено окремо.

   Відкривачі альбому й записів сюди не входять: вони на рівному папері,
   де збирати нема чого, і тоді їхній .sect-head не тягнуло б у правило
   про контейнери зі склом. */
:is(.btn,.lb__x,.lb__nav,.vid__btn,.rail__top)::after{
  padding:var(--ring,3px);
  -webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);
  mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);
  -webkit-mask-composite:xor;mask-composite:exclude;
  -webkit-backdrop-filter:brightness(1.3) saturate(1.5) blur(1px);
  backdrop-filter:brightness(1.3) saturate(1.5) blur(1px)}
/* Ширина кільця мусить іти за розміром кнопки: на низькій те саме кільце
   читається як товста рамка, а не як край скла. */
:is(.btn--sm,.lb__x,.rail__top)::after{--ring:1.4px}
:is(.lb__nav,.vid__btn)::after{--ring:2.1px}
/* Кант елемента прибираємо: його роботу тепер робить ребро, і дві межі
   поруч читалися б як обведення, а не як скло. */
.mode-night .btn--ghost,.nav.on-night .btn--ghost{
  border-color:transparent;background-color:color-mix(in srgb,#fff 7%,transparent)}
/* На папері під кнопкою нема чого розмивати — усе тримає ребро. Пара ліній
   тут перевертається: світла всередині, чорнильна за нею. Це і є прочитання
   заломлення на світлому тлі.                                             */
.mode-light :is(.btn,.gallery__more,.vids__more),.nav.on-light .btn,
.rail__top:not(.on-night){
  box-shadow:
    0 1px 2px -1px color-mix(in srgb,var(--ink) 22%,transparent),
    0 10px 26px -14px color-mix(in srgb,var(--ink) 30%,transparent)}
/* На світлому кільце світиться надто сильно. Причина в його власному
   brightness(1.3): на темному тлі це прочитання заломлення, а на світлому
   під ним уже майже білий папір, і підсвітка просто вибілює кант у
   яскравий обід. Тут вона майже знімається, а біле в лініях гаситься —
   ребро тримає не воно, а чорнильна лінія за ним. */
.mode-light :is(.btn,.gallery__more,.vids__more)::after,.nav.on-light .btn::after,
.rail__top:not(.on-night)::after{
  box-shadow:
    inset 0 0 0 1px rgba(255,255,255,.5),
    inset 0 0 0 2px color-mix(in srgb,var(--ink) 8%,transparent),
    inset 0 1.5px .5px -.5px rgba(255,255,255,.7),
    inset 0 -1.5px 1px -1px color-mix(in srgb,var(--ink) 18%,transparent)}
/* Підсвітку канта на світлому даємо ОКРЕМО й лише тим, у кого кільце
   вирізане маскою. У відкривачів маски немає (вони на рівному папері, і
   заломлювати там нема чого), тож без цього поділу їхня підсвітка лягала б
   не на кант, а на всю кнопку — тим самим німбом, який ми щойно ловили. */
.mode-light :is(.btn,.rail__top)::after,.nav.on-light .btn::after,
.rail__top:not(.on-night)::after{
  -webkit-backdrop-filter:brightness(1.06) saturate(1.15);
  backdrop-filter:brightness(1.06) saturate(1.15)}
.mode-light .btn--ghost,.nav.on-light .btn--ghost{
  background-color:color-mix(in srgb,#fff 42%,transparent)}
.mode-light :is(.gallery__more,.vids__more){
  background-color:color-mix(in srgb,#fff 42%,transparent)}
/* Скляна, але не прозора: 92% лишають головній кнопці суцільність, без якої
   вона перестає читатись як головна дія, і водночас дають легке заломлення
   того, що проїжджає під нею.                                             */
.btn--primary{background-color:color-mix(in srgb,var(--accent) 92%,transparent)}
/* Переглядач альбому й сторіс стоїть на рівному темному тлі: під цими
   кнопками нема чого заломлювати, і кільце по канту читається не як край
   скла, а як яскравий обід — надто помітний для службової кнопки, яка
   мусить поступатися фотографії. Кільце тут гасне майже до натяку, а
   підсвітка канта знімається зовсім: на рівній поверхні вона дає просто
   світліше коло.                                                          */
.lb__x::after,.lb__nav::after{
  -webkit-backdrop-filter:none;backdrop-filter:none;
  box-shadow:
    inset 0 0 0 1px rgba(255,255,255,.14),
    inset 0 1px .5px -.5px rgba(255,255,255,.34)}
.lb__x,.lb__nav{
  background-image:linear-gradient(160deg,
    rgba(255,255,255,.1),rgba(255,255,255,0) 56%)}

/* Суцільна кнопка — не лінза. Під нею нема чого заломлювати, тож кільце
   по канту читається на ній не як край скла, а як бліда обвідка. Тут
   лишається тільки те, що буває на суцільному тілі під світлом: відблиск
   по верхньому ребру й тінь по нижньому.                                  */
.btn--primary::after,.mode-light .btn--primary::after,.nav.on-light .btn--primary::after{
  padding:0;-webkit-mask:none;mask:none;
  -webkit-backdrop-filter:none;backdrop-filter:none;
  box-shadow:
    inset 0 1px .5px -.5px rgba(255,255,255,.7),
    inset 0 -1px 1px -1px color-mix(in srgb,var(--night-900) 28%,transparent)}
/* На наведенні скло гасне: з-під кнопки виїжджає суцільна заливка, і ребро
   з бліком на ній виглядали б як подряпина.                               */
:is(.btn,.gallery__more,.vids__more):hover{background-image:none;box-shadow:
  0 4px 12px -6px color-mix(in srgb,var(--night-900) 45%,transparent),
  0 16px 36px -20px color-mix(in srgb,var(--night-900) 55%,transparent)}
:is(.btn,.gallery__more,.vids__more):hover::after{box-shadow:none;
  -webkit-backdrop-filter:none;backdrop-filter:none}

/* ── перший екран ─────────────────────────────────────────────────────── */
/* Кнопки першого екрана з'являються інакше за решту — і це вимушено.

   Прозорість тут анімувати не можна. Доки в елемента прозорість менша за
   одиницю, він стає «дном» для backdrop-filter усіх нащадків: склу в
   кнопках нема чого заломлювати, і вони весь час появи стоять пласкими
   контурами. Скло вмикається одним кадром рівно тоді, коли прозорість
   дійшла до одиниці, і цей стрибок читається як «кнопка доповнює свою
   анімацію після всього». Жодне перенесення таймінгів його не прибирає —
   він прив'язаний до кінця переходу, хай коли той кінець настане.

   Далі була спроба лишити самий зсув. Вийшло гірше: без прозорості кнопки
   стоять на екрані з першого кадру, у повному вигляді, і тільки трохи
   під'їжджають, поки решта проявляється навколо них.

   Тому їх ховає `visibility`. Вона не створює дна для backdrop-filter, тож
   скло живе від першого показаного кадру; і вона не інтерполюється, тож
   кнопки не «проявляються» напівпрозорими, а просто приходять у свій такт —
   п'ятий, одразу після рядка суті. Хід через `translate`, а не `transform`,
   бо останній зайнятий підйомом на наведенні. */
.js .section--hero .actions{translate:0 1rem;visibility:hidden;
  animation:heroActions .55s var(--ease) both;
  /* Такт свій, як у решти першого екрана: `--seq` приходить із розмітки. */
  animation-delay:calc(var(--seq,0) * 130ms)}
@keyframes heroActions{
  from{visibility:hidden;translate:0 1rem}
  1%{visibility:visible}
  to{visibility:visible;translate:0}
}
@media (prefers-reduced-motion:reduce){
  /* Без руху анімація не виконується, тож `visibility` треба повернути
     руками — інакше кнопки лишилися б схованими назавжди. */
  .section--hero .actions{translate:none;visibility:visible}
}

.section--hero{background:url("assets/grain.png") 0 0/256px,
  radial-gradient(ellipse 60% 55% at 50% 44%,rgba(72,36,214,.42),rgba(72,36,214,0) 72%),
  radial-gradient(ellipse 40% 45% at 92% 92%,rgba(255,145,0,.08),rgba(255,145,0,0) 72%),
  var(--night-900);padding-block:clamp(3.5rem,6vw,5rem) clamp(1.75rem,3.5vw,2.75rem);overflow:hidden;
  min-height:100svh;display:grid;align-content:center}
.section--hero::after{                       /* сфери з постера */
  content:"";position:absolute;inset:-8% 0;z-index:0;pointer-events:none;
  background-image:url("assets/poster/spheres-1400.webp");
  background-size:cover;background-position:50% 42%;background-repeat:no-repeat;opacity:.46;filter:hue-rotate(-34deg) saturate(.85);
  /* Віньєтка ослаблена: еліпс ширший, суцільна зона довша, згасання пізніше.
     Кулі видно майже до країв, але текст під ними лишається на темному. */
  -webkit-mask-image:radial-gradient(ellipse 78% 68% at 50% 45%,#000 37%,transparent 85.5%);
  mask-image:radial-gradient(ellipse 78% 68% at 50% 45%,#000 37%,transparent 85.5%);
  transform:translate3d(0,var(--sy,0),0);will-change:transform;
  /* Повільний наїзд. `scale` — окрема властивість, не `transform`, тож вона
     не б'ється з паралаксом, який пише скрипт. Хід малий і дуже довгий:
     64 секунди на 9% — рух помітний тільки якщо дивитися, і саме тому
     кадр перестає бути статичним, не стаючи атракціоном. */
  animation:heroZoom 26s ease-in-out infinite alternate}
@keyframes heroZoom{from{scale:1}to{scale:1.09}}
/* На телефоні тло лежить НА БОЦІ. Кадр горизонтальний, екран вертикальний,
   і при `cover` від нього лишалася вузька смуга посередині — кілька куль
   упритул, обрізаних з боків. Повернутий на 90° він показує все гроно:
   куль більше, вони дрібніші й нарешті читаються як тло, а не як уламки.
   Розміри міняються місцями: ширина елемента стає висотою екрана.

   Наїзду тут немає — кулі показані дрібно, простору між ними майже не
   видно, і рух читався б як «картинка їде», а не як глибина. Паралакс теж
   вимкнено: після повороту його вертикальний зсув пішов би вбік. */
@media (max-width:51.99rem){
  /* Повернутий кадр обрізається згори рівною лінією: маска-віньєтка живе
     в системі координат самого елемента й після повороту гасить боки, а не
     верх. Тому верхнє згасання робимо окремим шаром — він не повернутий,
     тож гасить саме те, що бачить око. Знизу воно не потрібне: там кулі
     закінчуються самі. */
  .section--hero::before{content:"";position:absolute;inset:0 0 auto;height:7.5vh;
    /* z-index:1 обов'язковий: знімок теж на нульовому шарі, а `::after`
       малюється ПІСЛЯ `::before` — на нулі згасання лягало під кулі
       й не робило нічого. */
    z-index:1;pointer-events:none;
    background:linear-gradient(to bottom,var(--night-900),
      color-mix(in srgb,var(--night-900) 45%,transparent) 45%,transparent)}
  /* Центр світіння в кадрі — рівно посередині знімка. Після повороту він
     ліг би на плитку з датою, а не на заголовок. Тому кадр піднято
     (`top:33%`) і збільшено (`scale:1.32`) — заміряно на рендері без
     тексту: світіння стає на 32% висоти екрана, а центр заголовка на 31%.
     Масштаб тут не смак: без нього підйом оголив би край кадру. */
  .section--hero::after{
    inset:auto;top:33%;left:50%;
    width:104vh;height:104vw;
    translate:-50% -50%;rotate:90deg;scale:1.32;
    transform:none;animation:none}
}
@supports (height:100lvh){
  @media (max-width:51.99rem){
    /* адресний рядок ховається й показується — беремо найбільшу висоту,
       щоб при його зникненні кадр не відкривав край */
    .section--hero::after{width:104lvh}
  }
}
@media (min-width:64rem){
  .section--hero::after{background-image:url("assets/poster/spheres-2000.webp")}
}
.hero__inner{position:relative;z-index:1;display:grid;justify-items:center;text-align:center;
  gap:clamp(.8rem,1.6vw,1.3rem)}
.hero__kicker{margin:0;font-size:var(--t-eyebrow);font-weight:500;
  letter-spacing:.2em;text-transform:uppercase;color:var(--mist);max-width:40ch;text-wrap:balance;
  position:relative;padding-top:1.4rem}
.hero__kicker::before{content:"";position:absolute;top:0;left:50%;width:1px;height:1.1rem;
  background:linear-gradient(to bottom,transparent,var(--chrome));transform:translateX(-50%)}
.hero__mark{margin:0;position:relative;width:min(27rem,72%)}
/* ── зоряне небо ─────────────────────────────────────────────────────────
   Пил лежить ПОВЕРХ знімка: під ним зірки тонули у 44-відсотковій
   прозорості кадру й не читалися зовсім.

   Мерехтіння зроблене трьома шарами з різними періодами, а не двома
   сотнями окремих зірок: браузер робить три композиції за кадр замість
   двохсот сімдесяти. У будь-яку мить одні зірки яскраві, інші пригасли —
   і небо живе.                                                         */
.sky__stars{position:absolute;inset:0;z-index:0;pointer-events:none;
  /* Густіше вгорі, де неба найбільше, і майже нічого внизу під кнопками. */
  -webkit-mask-image:linear-gradient(to bottom,#000 0 52%,rgba(0,0,0,.4) 78%,transparent 97%);
          mask-image:linear-gradient(to bottom,#000 0 52%,rgba(0,0,0,.4) 78%,transparent 97%)}
.sky__stars i{position:absolute;inset:0;display:block;
  background-size:cover;background-position:center;
  animation:twinkle var(--t,4s) var(--d,0s) ease-in-out infinite}
/* Нижня межа висока навмисно: зірка має пригасати, а не зникати. Раніше
   було .28 — шар провалювався майже в нуль, і це читалося не як мерехтіння,
   а як «частина зірок пропала». Чотири стопи замість двох дають нерівний
   пульс: із `alternate` виходив рівний синус, надто механічний. */
@keyframes twinkle{
  0%{opacity:.62}
  28%{opacity:1}
  52%{opacity:.58}
  76%{opacity:.95}
  100%{opacity:.62}
}

/* ── падаючі зірки ──────────────────────────────────────────────────────
   Кут, місце старту, довжина й період у кожної свої — інакше це читається
   як один ефект, що вперто повторюється. Летить лише малу частку циклу:
   решту часу її просто немає.                                          */
.sky__shoot{position:absolute;top:var(--y,12%);left:var(--x,60%);z-index:0;
  pointer-events:none;width:var(--len,10rem);height:1px;
  transform-origin:100% 50%;rotate:var(--ang,28deg);
  background:linear-gradient(to left,#fff,rgba(255,255,255,.7) 14%,transparent 82%);
  opacity:0;filter:drop-shadow(0 0 6px rgba(255,255,255,.55));
  animation:shoot var(--t,13s) var(--d,0s) linear infinite}
.sky__shoot::after{content:"";position:absolute;right:-2px;top:-1.5px;
  width:4px;height:4px;border-radius:50%;background:#fff;
  box-shadow:0 0 10px 2px rgba(255,255,255,.85)}
/* Шлях іде рівно вздовж кута самої зірки: від «-пів шляху» до «+пів шляху».
   `--dy` завжди додатний, тож рух завжди згори вниз — комета не злітає. */
@keyframes shoot{
  0%,88%,100%{opacity:0;translate:calc(var(--dx) * -.5) calc(var(--dy) * -.5)}
  89%{opacity:0;translate:calc(var(--dx) * -.5) calc(var(--dy) * -.5)}
  92%{opacity:1}
  99.5%{opacity:0;translate:calc(var(--dx) * .5) calc(var(--dy) * .5)}
}
/* На телефоні поле зірок теж лягає на бік. Воно горизонтальне (1600×900),
   і `cover` на вертикальному екрані розтягує його по висоті, лишаючи видимою
   вузьку смугу з центру — близько чверті всіх зірок. Повернуте на 90° поле
   вкладається майже цілком: зірок над написом і під кнопками стає втричі
   більше. Маска густини лежить на батьківському шарі й НЕ повернута, тож
   вона й далі гасить низ саме там, де його бачить око. */
@media (max-width:51.99rem){
  .sky__stars i{inset:auto;top:50%;left:50%;
    width:100vh;height:100vw;
    translate:-50% -50%;rotate:90deg}
  /* На телефоні небо доходить донизу: кнопки стоять низько, і під ними
     лишалася чорна пляма без жодної зірки. Гасимо лише самий низ, і то
     частково. На широкому екрані маска лишається як була — там кнопки
     високо, і внизу зіркам справді нема на чому бути. */
  .sky__stars{
    -webkit-mask-image:linear-gradient(to bottom,#000 0 74%,rgba(0,0,0,.72) 92%,rgba(0,0,0,.45) 100%);
            mask-image:linear-gradient(to bottom,#000 0 74%,rgba(0,0,0,.72) 92%,rgba(0,0,0,.45) 100%)}
}
@supports (height:100lvh){
  @media (max-width:51.99rem){
    .sky__stars i{width:100lvh}
  }
}

@media (prefers-reduced-motion:reduce){
  .sky__shoot{display:none}
  .sky__stars i{animation:none;opacity:.7}
}

.hero__mark::before{
/* Ледь помітний об'єм за написом. Був ширший і щільніший — разом із сяйвом
   літер це давало загальну імлу замість світла. */
  content:"";position:absolute;inset:-5% -2%;z-index:-1;
  background:radial-gradient(ellipse at 50% 52%,rgba(110,90,255,.16),transparent 58%)}
/* Сяйво, яке напис кидає на тло, — як на оригінальному банері. У знімка є
   альфа-канал, тож `drop-shadow` іде по контуру самих літер, а не по
   прямокутнику. Головне тут — **щільність**: яскраве вузьке ядро біля самої
   кромки й лише один ширший ореол. Три великі радіуси давали розсіяну імлу,
   на банері ж світло тісно тримається літер. */
.hero__mark img{filter:
  drop-shadow(0 0 2.1px rgba(240,249,255,.95))
  drop-shadow(0 0 5.6px rgba(214,210,255,.75))
  drop-shadow(0 0 14px rgba(96,76,255,.36))}
/* Світло не стоїть на місці: воно спершу займається, коли літери вже сіли,
   а далі повільно дихає.

   Дві анімації на одній властивості, і порядок тут не випадковий. Займання
   йде з `both`: до своєї затримки воно тримає нульовий стан, після себе —
   повний. Дихання йде БЕЗ заповнення: інакше під час власної затримки воно
   вже нав'язало б свій нульовий кадр і світло спалахнуло б одразу. Воно
   стоїть другим у списку, тож щойно починається — перебирає заповнення
   займання на себе. Кадр 0% у нього збігається з кінцем займання, і шва в
   цьому місці не видно.

   Відлік починається від самої появи елемента, як і решта появи
   першого екрана. 0.45s — момент, коли літери вже на місці. Рахувати треба
   не від формального кінця переходу (260ms + 1s = 1.26s), а від того, коли
   око бачить напис: крива cubic-bezier(.22,1,.36,1) передньозважена й
   проходить дев'ять десятих шляху за третину часу, тож літери стоять уже
   близько 0.63s.

   0.45s ставить займання четвертим тактом однієї хвилі: підпис .13, напис
   .26, плитка .39, СВІТЛО .45, рядок .52, кнопки .65. Раніше воно стояло на
   1.35s — після всіх, і це читалося двояко: і як щось відірване від
   завантаження, і як пара до появи кнопок, бо припадало рівно на їхній
   хвіст (кнопки доїжджають близько 1.02s).

   Дихання тісне й помітне. Перша версія була занадто обережна: зовнішній
   ореол ходив 20↔27px за дев'ять секунд, тобто 0.8 пікселя на секунду —
   нижче порога, на якому око взагалі помічає зміну яскравості. Анімація
   була, сприйняття не було.
   Тепер розмах удвічі більший, а сам ореол на третину тісніший: 14↔24px
   замість 20↔27. Світло тримається біля кромки літер, як на банері, і
   водночас видно, що воно живе. Прозорість зовнішнього шару ходить
   .36↔.62 — саме вона робить пульс, а не радіус.
   6.5 секунди в один бік, повний цикл 13. */
.js .hero__mark img{
  animation:markIgnite .8s var(--ease) .45s both,
            markPulse 6.5s ease-in-out 1.25s infinite alternate;
  will-change:filter}
@keyframes markIgnite{
  from{filter:
    drop-shadow(0 0 3px rgba(240,249,255,0))
    drop-shadow(0 0 8px rgba(214,210,255,0))
    drop-shadow(0 0 20px rgba(96,76,255,0))}
  to{filter:
    drop-shadow(0 0 2.1px rgba(240,249,255,.95))
    drop-shadow(0 0 5.6px rgba(214,210,255,.75))
    drop-shadow(0 0 14px rgba(96,76,255,.36))}
}
@keyframes markPulse{
  from{filter:
    drop-shadow(0 0 2.1px rgba(240,249,255,.95))
    drop-shadow(0 0 5.6px rgba(214,210,255,.75))
    drop-shadow(0 0 14px rgba(96,76,255,.36))}
  to{filter:
    drop-shadow(0 0 2.8px rgba(240,249,255,1))
    drop-shadow(0 0 10px rgba(214,210,255,.95))
    drop-shadow(0 0 24px rgba(96,76,255,.62))}
}

/* плитка з даними події: розділювачі — це проміжки сітки, тож вони
   лишаються рівними за будь-якого переносу */
.hero__meta{display:grid;gap:1px;width:fit-content;max-width:100%;margin:.25rem auto 0;
  grid-template-columns:repeat(2,auto);
  background:rgba(255,255,255,.15);border:1px solid rgba(255,255,255,.15);
  border-radius:1.25rem;overflow:hidden;
  backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px)}
/* На широкому всі клітинки в один рядок незалежно від їхньої кількості —
   відлік зникає після балу, і жорстка сітка лишила б дірку. */
@media (min-width:34rem){ .hero__meta{grid-template-columns:none;grid-auto-flow:column} }
.hero__cell{display:flex;align-items:center;justify-content:center;gap:.55rem;
  padding:.7rem 1.15rem;background:rgba(3,11,20,.55);
  font-size:clamp(.875rem,.8rem + .3vw,1rem);letter-spacing:.02em;color:#fff;white-space:nowrap}
.hero__cell:last-child:nth-child(odd){grid-column:1 / -1}
@media (min-width:34rem){ .hero__cell:last-child:nth-child(odd){grid-column:auto} }
.hero__cell .ico{color:var(--chrome)}
/* відлік — та сама клітинка, тільки без знака; число бере акцент */
.hero__cell--count b{font-weight:600;color:var(--chrome);font-variant-numeric:tabular-nums}
.hero__cell time{font-weight:600;font-variant-numeric:tabular-nums}
/* Дві клітинки з чотирьох — дії: дата веде в календар, назва зали відкриває
   вікно про неї. Кнопкою тут працює САМА клітинка, а не щось усередині неї:
   плитка вже поділена на сегменти, і сегмент, що набирає світла, — це і є
   натяк. Пробували підкреслення (читалося як оздоба) і вкладену скляну
   плитку (два зайві прямокутники в рамці, від яких сусідні клітинки почали
   здаватися голими). Лишилося те, що вже було.
   Заливка йде окремим шаром під вмістом, а не через background-color:
   так вона проявляється плавно й не чіпає темного тла клітинки. */
:is(.hero__cell--cal,.hero__cell--act){position:relative;isolation:isolate;
  color:inherit;text-decoration:none;cursor:pointer;
  font-family:inherit;font-weight:inherit;line-height:inherit;
  -webkit-tap-highlight-color:transparent}
:is(.hero__cell--cal,.hero__cell--act)::before{content:"";position:absolute;
  z-index:-1;inset:0;opacity:0;
  background:linear-gradient(180deg,rgba(255,255,255,.17),rgba(255,255,255,.05));
  box-shadow:inset 0 1px 0 rgba(255,255,255,.3);
  transition:opacity .3s var(--ease)}
:is(.hero__cell--cal,.hero__cell--act):is(:hover,:focus-visible)::before{opacity:1}
:is(.hero__cell--cal,.hero__cell--act):active::before{opacity:.75}
:is(.hero__cell--cal,.hero__cell--act) .ico{transition:color .3s ease}
:is(.hero__cell--cal,.hero__cell--act):hover .ico{color:#fff}
/* На дотику наведення не буває взагалі, тож там той самий шар стоїть
   постійно, тільки тихіше. Це не нова форма — та сама клітинка, трохи
   світліша за сусідні. */
@media (pointer:coarse){
  :is(.hero__cell--cal,.hero__cell--act)::before{opacity:.55}
}
@media (prefers-reduced-motion:reduce){
  :is(.hero__cell--cal,.hero__cell--act)::before{transition:none}
}
/* Плашка-підказка над клітинкою: що саме станеться від натискання.
   Рідну підказку браузера не беремо — вона з'являється аж за секунду,
   системним шрифтом і знизу праворуч від курсора, а не над кнопкою.
   Живе в кінці <body>: плитка з датою обрізана по своїх заокругленнях
   (`overflow:hidden`), і будь-що всередині неї підказку б відтяло.
   Позиція приходить від скрипта; тут лише вигляд і поява. */
.tip{position:fixed;z-index:60;top:0;left:0;pointer-events:none;
  transform:translate(-50%,-100%);
  padding:.4rem .7rem;border-radius:.6rem;white-space:nowrap;
  font-size:.75rem;font-weight:500;letter-spacing:.02em;line-height:1.35;color:#fff;
  background:rgba(12,13,40,.72);
  backdrop-filter:blur(14px) saturate(1.7);-webkit-backdrop-filter:blur(14px) saturate(1.7);
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.18),
    inset 0 1px 0 rgba(255,255,255,.26),
    0 .5rem 1.5rem rgba(2,6,14,.45);
  opacity:0;translate:0 .3rem;
  transition:opacity .2s var(--ease),translate .2s var(--ease)}
/* Носика немає. Він був повернутим квадратом того самого кольору — і саме
   тому виглядав латкою: тло плашки напівпрозоре й розмиває те, що під ним,
   а квадрат розмиття не мав. Там, де він налазив на плашку, два прозорі
   шари складалися в темнішу пляму, а там, де виступав, лишався пласким
   темним трикутником на тлі розмитого скла.

   Зробити його одним шматком зі скла можна тільки через маску складної
   форми — і все це заради стрілки, яка ні на що не вказує: плашка й так
   стоїть за вісім пікселів над клітинкою, і зв'язок читається з відстані.
   На сторінці більше ніде носиків немає, тож і тут вони чужі. */
.tip.is-on{opacity:1;translate:0}
@media (prefers-reduced-motion:reduce){
  .tip{transition:opacity .2s linear;translate:none}
}

/* курсив тримаємо цілим рядком: розрив усередині «jak król / lub królowa»
   читався як спотикання */
.hero__lead{margin:0;max-width:38ch;font-size:var(--t-lead);line-height:1.4;color:var(--mist)}
.hero__lead em{white-space:nowrap}
.hero__lead em{font-family:"Bodoni Moda",serif;font-style:italic;color:#fff;font-size:1.06em}
.section--hero .actions{justify-content:center;margin-top:.5rem}

.cue{position:relative;z-index:1;width:fit-content;margin:clamp(2.5rem,7vh,5rem) auto 0;
  display:flex;flex-direction:column;align-items:center;gap:.6rem;
  color:var(--steel);text-decoration:none;font-size:.75rem;letter-spacing:.2em;
  text-transform:uppercase;transition:color .3s ease}
/* Підказка лишається в потоці, з відступом від висоти вікна. Абсолютом до
   нижнього краю її виводити не можна: під нею стоять кнопки, і вона на них
   налізає. Одного разу ми це вже пробували — коли кнопок на першому екрані
   тимчасово не було, низ екрана лишався порожнім і підказка справді мала
   стояти біля самого краю. Кнопки повернулися, і разом з ними повернулася
   причина тримати підказку в потоці. */
.cue:hover{color:var(--chrome)}
/* Підказка прокрутки не повторює стрілку з кнопки над нею: на вказівниках
   це миша з колесом, на дотику — свайп угору. Рухається тільки внутрішня
   частина знака, сам контур стоїть. */
.cue__ico{width:1.85rem;height:2.1rem}
.cue__ico .ico__b{transform-box:view-box;transform-origin:center}
.cue__ico--mouse .ico__b{animation:wheel 2.3s var(--ease) infinite}
.cue__ico--swipe{display:none}
@keyframes wheel{0%{transform:translateY(0);opacity:.4}
  25%{opacity:1}68%{transform:translateY(3.2px);opacity:0}
  69%{transform:translateY(0);opacity:0}100%{opacity:.4}}
/* крапка не зникає повністю — у спокої знак має лишатися читабельним */
@keyframes swipe{0%{transform:translateY(0);opacity:.4}
  25%{opacity:1}72%{transform:translateY(-8px);opacity:0}
  73%{transform:translateY(0);opacity:0}100%{opacity:.4}}
@media (hover:none),(max-width:33.99rem){
  .cue__ico--mouse{display:none}
  .cue__ico--swipe{display:block;animation:none}
  .cue__ico--swipe .ico__b{animation:swipe 2.3s var(--ease) infinite}
}
/* стрілка над фотосмугою лишається стрілкою — там поруч немає кнопки */
@keyframes bob{0%,100%{transform:translateY(0);opacity:.55}50%{transform:translateY(.35rem);opacity:1}}

/* На телефоні перший екран заповнений упритул: блоки великі, а проміжки між
   ними вдвічі менші за них. Зменшуємо самі блоки й віддаємо звільнене місце
   проміжкам — набір той самий, дихати є чим. */
@media (max-width:33.99rem){
  /* Блоки тягнемо на всю колонку: знак, плитка й кнопки стають однієї ширини,
     і поля з боків перестають читатися як порожнеча. Повітря лишається між
     блоками, а не навколо них. */
  .section--hero{padding-block:1.5rem 1rem}
  .hero__inner{gap:1.3rem}
  .hero__kicker{padding-top:1rem;letter-spacing:.14em}
  .hero__kicker::before{height:.8rem}
  .hero__mark{width:min(27rem,74%)}
  .hero__meta{width:min(100%,21rem);border-radius:1rem}
  .hero__cell{padding:.62rem .6rem;font-size:.8125rem;gap:.4rem}
  .section--hero .actions{margin-top:.15rem;width:min(100%,21rem);
    margin-inline:auto;grid-template-columns:minmax(0,1fr)}
  /* слово «przewiń» на дотику зайве — гортання й так очевидне */
  .cue{margin-top:1.35rem}
  .cue span{display:none}
}

/* ── розкладка «заголовок ліворуч, текст праворуч» ────────────────────── */
.split{display:grid;gap:clamp(1.5rem,4vw,2.5rem)}
/* відступ під заголовком тут зайвий: відстань між колонками дає сама сітка.
   Інакше на вузькому екрані вони складаються і розрив подвоюється. */
.split__head .sect-head{margin-bottom:0}
.split__head .lead{margin:clamp(1.1rem,2.2vw,1.6rem) 0 0;max-width:34ch}
@media (min-width:60rem){
  .split{grid-template-columns:minmax(0,1fr) minmax(0,1.05fr);
    column-gap:clamp(3rem,7vw,7rem);align-items:start}
  /* липкий заголовок вмикається тільки там, де права колонка справді довга */
  .split--pin .split__head{position:sticky;top:7.5rem}
  .split--pin .split__head[data-reveal]{transform:none}
}

/* Офіційний знак події. Сам по собі він висів під заголовком сиротою,
   тому зв'язуємо його лінійкою і підписом — виходить свідомий блок. */
.brand{display:flex;align-items:center;gap:clamp(1rem,2.5vw,1.5rem);
  margin-top:clamp(1.5rem,3vw,2.25rem);padding-top:clamp(1.25rem,2.5vw,1.75rem);
  border-top:1px solid var(--hair);max-width:30rem}
.brand__logo{width:clamp(6rem,11vw,8rem);height:auto;flex:none}
.brand p{margin:0;font-size:.8125rem;line-height:1.45;color:var(--muted);max-width:24ch}

/* ── драбинка кроків ──────────────────────────────────────────────────────
   Що відбувається на балі, по порядку. Вертикальна лінія веде від кроку
   до кроку, як у друкованому переліку каталогу.                          */
.steps{--gap:clamp(1.1rem,2.2vw,1.6rem);--dot:2.5rem;
  list-style:none;margin:clamp(2rem,4vw,2.75rem) 0 0;padding:0;display:grid;gap:var(--gap)}
.step{position:relative;display:grid;grid-template-columns:auto auto minmax(0,1fr);
  align-items:start;column-gap:clamp(.75rem,1.8vw,1.1rem)}
.step__ico{position:relative;display:grid;place-items:center;flex:none;
  width:var(--dot);height:var(--dot);border-radius:50%;color:var(--accent);
  border:1px solid color-mix(in srgb,var(--accent) 32%,transparent);
  background:color-mix(in srgb,var(--accent) 7%,transparent)}
/* Лінія від кола до кола. Рахуємо від висоти всього рядка, а не від проміжку
   між ними: текст під заголовком робить рядок вищим за коло, і лінія
   обривалася відразу під знаком. */
.step:not(:last-child)::after{content:"";position:absolute;
  top:calc(var(--dot) + 3px);left:calc(var(--dot) / 2);translate:-50% 0;width:1px;
  height:calc(100% - var(--dot) + var(--gap) - 6px);
  background:color-mix(in srgb,var(--accent) 28%,transparent)}
/* Поява. Крок з'являється всередині колонки, яка сама щойно виїхала, тож
   хід у нього менший за загальний (0.9rem проти 1.75) — подвійний зсув
   читався б як стрибок. */
.steps > .step[data-reveal]:not(.is-in){transform:translateY(.9rem)}
/* Нитка малюється згори вниз услід за кроком: спершу сідає рядок, за ним
   лінія тягнеться до наступного знака. Затримка більша за появу самого
   кроку, інакше лінія йде поперед нього. */
.step:not(:last-child)::after{transform:scaleY(0);transform-origin:50% 0}
/* Коли драбинка розігрується знизу вгору, нитка мусить рости в той самий
   бік: інакше сходинки спалахують угору, а лінії між ними тягнуться вниз,
   і рух читається як два різні. Міняється лише точка опори. */
.steps.is-upward .step:not(:last-child)::after{transform-origin:50% 100%}
.step.is-in:not(:last-child)::after{transform:scaleY(1);
  transition:transform .75s var(--ease);
  transition-delay:calc(var(--d,0) * 90ms + 260ms)}
/* Знак сідає з ледь помітним поштовхом — так око ловить, що нитка дійшла
   саме сюди. Крива з перельотом, але дуже коротким: це акцент, не стрибок. */
.step[data-reveal]:not(.is-in) .step__ico{scale:.72}
.step.is-in .step__ico{scale:1;
  transition:scale .55s cubic-bezier(.34,1.5,.64,1);
  transition-delay:calc(var(--d,0) * 90ms + 110ms)}
.step__n{font-size:.6875rem;font-weight:600;letter-spacing:.1em;color:var(--accent);
  opacity:.6;padding-top:.7rem;font-variant-numeric:tabular-nums}
.step__text{min-width:0;padding-top:.3rem}
.step h3{margin:0;font-size:clamp(1rem,.95rem + .35vw,1.1875rem);font-weight:600;
  line-height:1.3}
.step p{margin:.3rem 0 0;font-size:.9375rem;line-height:1.5;color:var(--muted)}

/* розкладка по центру — для короткого закриття перед закликом */
.mid{max-width:54rem;margin-inline:auto;text-align:center}
.mid .sect-head{margin-bottom:clamp(1.5rem,3vw,2.25rem)}
.mid .eyebrow{justify-content:center}
.mid .section__title{margin-inline:auto;max-width:14ch;
  font-size:clamp(2.125rem,1.1rem + 3.2vw,3.75rem)}
.mid .prose{max-width:52ch;margin-inline:auto}
/* ширину цитати задаємо в rem, а не в ch: у Bodoni нуль широкий,
   і 30ch давало вдвічі вужчий рядок, ніж очікуєш */
.mid .quote{border:0;padding:0;margin:clamp(2.5rem,5vw,4rem) auto 0;
  max-width:min(100%,34rem);text-align:center}
.mid .brand{justify-content:center;margin-inline:auto}

/* ── проза ────────────────────────────────────────────────────────────── */
.prose{max-width:54ch}
.prose p{margin:0 0 1.15em}
.prose--lead p:first-child{font-size:var(--t-lead);line-height:1.45;letter-spacing:-.005em}
.prose p:last-child{margin-bottom:0}
.prose strong{font-weight:600;color:inherit;
  background:linear-gradient(to top,color-mix(in srgb,var(--accent) 22%,transparent) .3em,transparent .3em)}
.mode-night .prose p{color:var(--mist)}
.mode-night .prose--lead p:first-child{color:#fff}
.prose em{font-family:"Bodoni Moda",serif;font-style:italic;font-size:1.06em;color:var(--accent)}

.quote{margin:clamp(2rem,4vw,3rem) 0 0;padding-left:clamp(1rem,2.5vw,1.75rem);
  border-left:2px solid var(--accent);max-width:38ch}
.quote p{margin:0;font-family:"Bodoni Moda",serif;font-optical-sizing:auto;font-style:italic;
  font-weight:400;font-size:clamp(1.5rem,1rem + 1.9vw,2.5rem);line-height:1.16;
  letter-spacing:-.01em;color:var(--accent)}

/* ── цифри ────────────────────────────────────────────────────────────── */
.stats{display:grid;gap:clamp(2rem,3.5vw,3rem) clamp(1.5rem,3vw,2.5rem);
  grid-template-columns:repeat(2,minmax(0,1fr));margin:0;padding:0;list-style:none}
@media (min-width:64rem){ .stats{grid-template-columns:repeat(4,minmax(0,1fr))} }
.stat{display:grid;gap:.45rem;align-content:start}
/* надпис стоїть НАД лінійкою — як шапка колонки, а не як підпис до цифри */
.stat__rule{height:1px;background:currentColor;opacity:.2;margin-bottom:.9rem;
  transform:scaleX(0);transform-origin:0 50%;
  transition:transform .9s var(--ease);transition-delay:calc(var(--i) * 110ms)}
.is-in .stat__rule{transform:scaleX(1)}
.stat__prefix{min-height:1.5em;line-height:1.5;margin-bottom:.15rem;
  font-size:var(--t-eyebrow);font-weight:600;
  letter-spacing:.16em;text-transform:uppercase;color:var(--muted)}
.mode-light .stat__prefix{color:var(--gold)}
.stat__value{font-family:"Bodoni Moda",serif;font-optical-sizing:auto;font-weight:600;
  font-size:clamp(3rem,1rem + 7vw,6rem);line-height:.86;letter-spacing:-.03em;
  font-variant-numeric:tabular-nums lining-nums;color:var(--accent)}
.stat--outline .stat__value{color:transparent;-webkit-text-stroke:1.5px var(--accent)}
.stat__label{font-size:.9375rem;line-height:1.45;max-width:20ch;color:var(--muted)}

/* ── таймлайн ─────────────────────────────────────────────────────────── */
.lead{max-width:46ch;margin:0 0 clamp(2.5rem,5vw,4rem);
  font-size:var(--t-lead);line-height:1.45;color:var(--muted)}
/* Список трохи ширший за контент, а рядок має внутрішні поля — тоді підсвітка
   не впирається в номер, а сам текст лишається на лінії решти сторінки. */
.tl{list-style:none;margin:0;padding:0;display:grid;gap:0;
  border-top:1px solid var(--hair)}
/* Одна колонка. Дві ламали нумерацію: номери йшли 01 02 / 03 04, і око
   стрибало зигзагом замість того, щоб читати реєстр згори вниз. */
.tl__item{position:relative;display:grid;isolation:isolate;
  grid-template-columns:auto auto minmax(0,1fr) auto;align-items:start;
  column-gap:clamp(.9rem,2vw,1.4rem);
  padding:clamp(1.15rem,2.2vw,1.5rem) .85rem;
  border-bottom:1px solid var(--hair)}
.tl__item:last-child{border-bottom:0}
/* Підсвітка рядка — рівна смуга рівно по його межах, без заокруглень:
   заокруглена панель вилазила за лінійки й випадала з ритму переліку. */
/* Підсвітка рівно по межах рядка — там само, де й розділові лінійки.
   Було `inset:0 -.85rem`: смуга вилазила на .85rem далі за лінії з обох
   боків, і на наведенні ставало видно, що вони не одне ціле. */
.tl__item::after{content:"";position:absolute;inset:0;z-index:-1;
  background:color-mix(in srgb,var(--accent) 6%,transparent);
  opacity:0;transition:opacity .3s ease}
.tl__item:hover::after{opacity:1}
.tl__num{font-size:.6875rem;font-weight:600;letter-spacing:.1em;color:var(--accent);
  opacity:.6;padding-top:.85rem;font-variant-numeric:tabular-nums}
.mode-light .tl__num{color:var(--gold);opacity:1}

/* Ключовий елемент рядка — знак справи. Фото в колі 85px не прочитати,
   знак у 24px читається; до того ж знак є в кожного рядка, а дати й описи
   є не скрізь, тож саме він вирівнює перелік. Коло те саме, що в кроках
   першого розділу, — блок нарешті говорить мовою решти сайту. */
.tl__ico{display:grid;place-items:center;flex:none;margin-top:.1rem;
  width:2.75rem;height:2.75rem;border-radius:50%;color:var(--accent);
  border:1px solid color-mix(in srgb,var(--accent) 30%,transparent);
  background:color-mix(in srgb,var(--accent) 7%,transparent);
  transition:background-color .3s ease,border-color .3s ease}
.tl__ico .ico{width:1.25rem;height:1.25rem}
.tl__item:hover .tl__ico{background:color-mix(in srgb,var(--accent) 13%,transparent);
  border-color:color-mix(in srgb,var(--accent) 45%,transparent)}

.tl__text{min-width:0;padding-top:.45rem}
.tl__item h3{margin:0;font-size:clamp(1.0625rem,1rem + .5vw,1.3125rem);font-weight:600;
  line-height:1.25;text-wrap:balance;transition:color .3s ease}
.tl__item:hover h3{color:var(--accent)}
.tl__when{display:inline-block;margin-top:.45rem;padding:.2rem .6rem;border-radius:999px;
  font-size:.6875rem;font-weight:600;letter-spacing:.09em;text-transform:uppercase;
  color:var(--accent);background:color-mix(in srgb,var(--accent) 11%,transparent)}
.tl__item p{margin:.5rem 0 0;max-width:52ch;color:var(--muted);font-size:.9375rem;line-height:1.5}

/* Мініатюра праворуч — не ілюстрація, а підказка: за рядком є стек кадрів.
   Тому вона мала, кругла і з'являється разом зі знаком «розгорнути». */
/* Той самий діаметр і та сама обвідка, що в знака зліва: інакше рядок має
   два різні кола — одне з рамкою на 44px, друге суцільне на 52px, — і
   читається як два різні дизайни в одному рядку. */
.tl__peek{position:relative;display:grid;place-items:center;flex:none;
  width:2.75rem;height:2.75rem;margin-top:.1rem;
  transition:transform .45s var(--ease)}
.tl__item:hover .tl__peek{transform:scale(1.06)}
.tl__photo{width:100%;height:100%;border-radius:50%;object-fit:cover;
  box-shadow:0 0 0 1px color-mix(in srgb,var(--accent) 30%,transparent);
  transition:box-shadow .35s ease}
.tl__item:hover .tl__photo{box-shadow:0 0 0 1px color-mix(in srgb,var(--accent) 45%,transparent)}
/* z-index обов'язковий: затемнення нижче — це `::after`, а псевдоелемент
   малюється ПІСЛЯ дітей, тож без цього він накривав плюс собою.
   Товщина штриха більша за базову: на 18px проста фігура має триматися
   впевнено, інакше на темному кадрі вона тане. */
.tl__peek .ico{position:absolute;z-index:1;width:1.15rem;height:1.15rem;color:#fff;
  stroke-width:2.2;filter:drop-shadow(0 1px 3px color-mix(in srgb,var(--night-900) 55%,transparent));
  opacity:0;transition:opacity .3s ease}
.tl__peek::after{content:"";position:absolute;inset:0;border-radius:50%;
  background:color-mix(in srgb,var(--night-900) 55%,transparent);
  opacity:0;transition:opacity .3s ease}
.tl__item:hover .tl__peek::after,.tl__open:focus-visible .tl__peek::after,
.tl__item:hover .tl__peek .ico,.tl__open:focus-visible .tl__peek .ico{opacity:1}
/* На дотику наводити нічим, тож підказку видно завжди. */
@media (hover:none){
  .tl__peek::after,.tl__peek .ico{opacity:1}
}
@media (max-width:37.99rem){
  /* На телефоні номер іде над рядком, а знак і текст стають поруч. */
  .tl__item{grid-template-columns:auto minmax(0,1fr) auto;column-gap:.9rem}
  .tl__num{grid-column:1 / -1;padding-top:0;padding-bottom:.35rem}
  .tl__peek,.tl__ico{width:2.25rem;height:2.25rem}
  .tl__ico .ico{width:1.05rem;height:1.05rem}
}

/* рядок переліку — кнопка: успадковує сітку рядка, щоб нічого не з'їхало */
.tl__open{display:grid;grid-template-columns:subgrid;grid-column:1 / -1;
  align-items:start;column-gap:inherit;
  margin:0;padding:0;border:0;background:none;font:inherit;color:inherit;
  text-align:left;cursor:zoom-in;width:100%}
/* Кільце фокуса (клавіатура) обіймає рядок. Базове правило малює його
   currentColor — на широкому рядку це читається як чорна рамка браузера,
   тож беремо тонку акцентну лінію з ледь помітною підсвіткою. */
.tl__open:focus-visible{outline:1.5px solid var(--accent);outline-offset:-2px;
  border-radius:.65rem;background:color-mix(in srgb,var(--accent) 7%,transparent)}
@supports not (grid-template-columns:subgrid){
  .tl__open{grid-template-columns:auto auto minmax(0,1fr) auto}
}

/* ── стек із трьох кадрів ─────────────────────────────────────────────────
   Не альбом: три знімки лежать один на одному з невеликим зсувом і поворотом,
   під ними — назва й опис справи.                                          */
/* Швидкі кліки по стрілках браузер рахує як подвійні й починає виділяти
   найближчий текст — у переглядачі виділяти нічого, тож вимикаємо. */
.st,.lb{-webkit-user-select:none;user-select:none}
/* «Привида» перетягування браузер робить із натурального розміру картинки, а в
   SVG це viewBox — у деяких знаків тисячі одиниць, і замість плитки за мишкою
   тягнеться розтягнута пляма. Знаки перетягувати нема куди, тож вимикаємо. */
.fam :is(a,img),.logos__item img{-webkit-user-drag:none}
.st{width:100vw;max-width:100vw;height:100dvh;max-height:100dvh;margin:0;padding:0;border:0;
  background:var(--night-900);color:#fff;overflow:hidden;
  /* вікна живуть поза секціями, тож акцент задаємо явно — інакше сюди
     протікає фіолет із :root і на темному тлі майже не читається */
  --accent:var(--chrome);--surface:var(--night-900)}
.st::backdrop{background:color-mix(in srgb,var(--night-900) 94%,transparent)}
.st[open]{display:grid;grid-template-rows:auto minmax(0,1fr)}
.st__bar{display:flex;align-items:center;justify-content:space-between;gap:1rem;
  padding:.85rem clamp(1rem,3vw,2rem);border-bottom:1px solid rgba(255,255,255,.1)}
.st__count{font-size:.8125rem;letter-spacing:.14em;text-transform:uppercase;color:var(--steel)}
.st__count b{color:var(--chrome);font-weight:600;font-variant-numeric:tabular-nums}
/* Стос завжди на одному місці: під текст зарезервована стала висота,
   інакше довший заголовок чи опис штовхає знімки вгору-вниз між справами. */
.st__body{position:relative;display:grid;grid-template-rows:minmax(0,1fr) auto;
  justify-items:center;row-gap:clamp(1.25rem,3.5vh,2.5rem);
  padding:clamp(1.25rem,4vw,2.5rem);min-height:0}
.st__shot{align-self:center}

/* Рамка квадратна навмисно, і не через смак: третина кадрів у стеках —
   вертикальні оригінали (до 2:3), решта горизонтальні. Квадрат однаково
   чесний до обох, а широка рамка зрізала б вертикальним більш як половину
   висоти й ще й тягла б їх угору — деякі джерела всього 412px завширшки.
   Тому на широкому екрані росте розмір, а не змінюється пропорція. */
.st__shot{display:grid;gap:.85rem;width:min(78vw,clamp(13rem,42vh,24rem))}
@media (min-width:48rem){
  .st__shot{width:min(62vw,clamp(20rem,56vh,34rem))}
}
/* смужки як у сторіс: показують, що кадрів три і вони змінюються самі */
.st__bars{display:flex;gap:.3rem}
.st__bars i{position:relative;flex:1;height:2px;border-radius:999px;overflow:hidden;
  background:rgba(255,255,255,.22)}
.st__bars i::after{content:"";position:absolute;inset:0;background:var(--chrome);
  transform:scaleX(0);transform-origin:0 50%}
.st__bars i.is-done::after{transform:scaleX(1)}
.st__bars i.is-now::after{animation:story var(--story,2.25s) linear forwards}
.st.is-hold .st__bars i.is-now::after{animation-play-state:paused}
@keyframes story{from{transform:scaleX(0)}to{transform:scaleX(1)}}

.st__stack{position:relative;width:100%;aspect-ratio:1}
.st__stack img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  border-radius:1.25rem;box-shadow:0 1.5rem 3rem rgba(0,0,0,.5);
  transition:transform .55s var(--ease),opacity .4s ease;cursor:pointer}
/* задні кадри визирають із-під переднього */
.st__stack img{--front:rotate(0deg) translate(0,0) scale(1)}
.st__stack img:nth-child(1),
.st__stack.pos-1 img:nth-child(2),
.st__stack.pos-2 img:nth-child(3){transform:var(--front);z-index:3}
.st__stack img:nth-child(2),
.st__stack.pos-1 img:nth-child(3),
.st__stack.pos-2 img:nth-child(1){transform:rotate(-9deg) translate(-13%,4%) scale(.9);z-index:2}
.st__stack img:nth-child(3),
.st__stack.pos-1 img:nth-child(1),
.st__stack.pos-2 img:nth-child(2){transform:rotate(9deg) translate(13%,7%) scale(.86);z-index:1}

.st__text{max-width:44ch;text-align:center;display:grid;gap:.6rem;justify-items:center;
  align-content:start;min-height:clamp(8.5rem,17vh,11.5rem)}
.st__text h3{margin:0;font-family:"Bodoni Moda",serif;font-optical-sizing:auto;font-weight:700;
  font-size:clamp(1.5rem,1rem + 1.8vw,2.5rem);line-height:1.08;letter-spacing:-.01em}
.st__text .tl__when{margin:0}
.st__text p{margin:0;color:var(--mist);font-size:clamp(.9375rem,.9rem + .3vw,1.0625rem);
  line-height:1.5}
@media (max-width:40rem){
  .st__body .lb__nav{top:auto;bottom:.75rem;translate:0 0}
}

/* ── стіна знаків родини ──────────────────────────────────────────────────
   Усі проєкти PROEM / PROEM ZAKO / SCh TOMY — так, як вони стоять
   на розвороті 11–12 каталогу.                                            */
/* min-height — те саме правило 24px для цілі дотику: сам напис дає 21px. */
.logos__more{display:inline-flex;align-items:center;gap:.45rem;margin-top:1rem;
  min-height:1.5rem;padding-block:.1rem;
  padding-inline:0;border:0;background:none;cursor:pointer;font:inherit;
  font-size:.8125rem;font-weight:600;color:var(--accent);
  transition:gap .3s var(--ease)}
.logos__more:hover{gap:.75rem}
.logos__more span{text-decoration:underline;text-underline-offset:.28em;
  text-decoration-thickness:1px}
.logos__more .btn__ico{width:.85rem;height:.85rem}

.fam{width:100vw;max-width:100vw;height:100dvh;max-height:100dvh;margin:0;padding:0;border:0;
  background:var(--paper);color:var(--ink);overflow:hidden;--accent:var(--violet)}
.fam::backdrop{background:color-mix(in srgb,var(--night-900) 90%,transparent)}
.fam[open]{display:grid;grid-template-rows:auto minmax(0,1fr)}
.fam__bar{display:flex;align-items:center;justify-content:space-between;gap:1rem;
  padding:.85rem clamp(1rem,3vw,2rem);border-bottom:1px solid var(--hair)}
.fam__title{margin:0;display:flex;align-items:baseline;gap:.6rem;
  font-size:var(--t-eyebrow);font-weight:600;letter-spacing:.16em;text-transform:uppercase}
.fam__title b{font-size:.75rem;color:var(--gold);font-variant-numeric:tabular-nums}
.fam .lb__x{border-color:var(--hair);color:var(--ink)}
.fam .lb__x:hover{background:color-mix(in srgb,var(--ink) 8%,transparent)}
.fam__body{overflow-y:auto;overscroll-behavior:contain;
  padding:clamp(1.5rem,4vw,2.5rem) clamp(1rem,3vw,2rem) clamp(3rem,6vw,4rem)}
.fam__note{max-width:52ch;margin:0 auto clamp(1.75rem,4vw,2.75rem);text-align:center;
  font-size:.9375rem;line-height:1.55;color:var(--muted)}
.fam__grid{list-style:none;margin:0 auto;padding:0;max-width:72rem;display:grid;
  gap:clamp(.75rem,2vw,1.25rem);
  grid-template-columns:repeat(auto-fill,minmax(9.5rem,1fr))}
.fam__grid li{display:grid;border-radius:.875rem;
  border:1px solid var(--hair);background:color-mix(in srgb,var(--accent) 3%,transparent);
  transition:border-color .35s ease,transform .45s var(--ease)}
.fam__grid li:hover{border-color:color-mix(in srgb,var(--accent) 35%,transparent);
  transform:translateY(-3px)}
/* Розкладку тримає вміст плитки, а не сама плитка: у проєктів із сайтом це
   посилання, і воно має клікатися по всій площі, разом із padding. */
.fam__grid li > :is(a,div){display:grid;justify-items:center;align-content:start;gap:.7rem;
  padding:clamp(1rem,2.2vw,1.4rem) .75rem;border-radius:inherit;height:100%}
/* Двадцять підкреслених синіх написів поспіль читаються як список посилань,
   а не як стіна знаків. Тому посилання мовчить, доки на нього не навели. */
.fam__grid a{color:inherit;text-decoration:none}
.fam__grid a:is(:hover,:focus-visible) span{color:var(--ink);
  text-decoration:underline;text-underline-offset:.2em;
  text-decoration-thickness:from-font}
.fam__grid a:focus-visible{outline:1.5px solid var(--accent);outline-offset:-2px}
.fam__grid img{width:100%;height:3.25rem;object-fit:contain;object-position:center}
.fam__grid span{font-size:.6875rem;line-height:1.35;text-align:center;color:var(--muted)}

/* ── наші ініціативи ──────────────────────────────────────────────────────
   Окремий блок під переліком: інша верства, власна плашка, мальовані знаки
   замість круглих фото. Так само, як на розвороті 09–10 каталогу.            */
.inits{margin-top:clamp(3rem,6vw,4.5rem)}
.inits__label{margin:0 0 clamp(1.25rem,2.5vw,1.75rem);
  font-size:var(--t-eyebrow);font-weight:600;letter-spacing:.16em;text-transform:uppercase;
  color:var(--muted)}
.inits__row{display:grid;gap:clamp(2rem,4vw,3.5rem);margin:0;padding:0;list-style:none;
  grid-template-columns:repeat(auto-fit,minmax(15rem,1fr))}
.init{display:grid;justify-items:center;text-align:center;gap:.75rem;
  padding:clamp(1.5rem,3vw,2.25rem) clamp(1rem,2.5vw,1.75rem);
  border-radius:1.25rem;border:1px solid var(--hair);
  background:color-mix(in srgb,var(--accent) 3%,transparent);
  transition:border-color .4s ease,transform .5s var(--ease)}
.init:hover{border-color:color-mix(in srgb,var(--accent) 38%,transparent);
  transform:translateY(-3px)}
.init__mark{width:clamp(9rem,20vw,13rem);height:auto;margin-bottom:.35rem;
  transition:transform .45s var(--ease)}
.init:hover .init__mark{transform:scale(1.04)}
.init h4{margin:0;font-size:clamp(1.0625rem,1rem + .45vw,1.3125rem);font-weight:600;
  line-height:1.25}
.init p{margin:0;max-width:30ch;font-size:.9375rem;line-height:1.5;color:var(--muted)}

/* ── дві стежки ───────────────────────────────────────────────────────── */
.paths{display:grid;gap:clamp(1rem,2.5vw,1.5rem);
  grid-template-columns:repeat(auto-fit,minmax(18rem,1fr))}
/* Колонкою через flex, а не сіткою: у сітці з `align-content:start` рядки
   стискаються до вмісту, і вільне місце внизу лишається нічиїм — кнопки
   трьох карток ставали на трьох різних висотах. У колонці його забирає
   перелік (`margin-bottom:auto`), і кнопка сідає на дно, однаково в усіх. */
.path{position:relative;display:flex;flex-direction:column;gap:.85rem;overflow:hidden;
  padding:clamp(1.75rem,3.5vw,2.75rem);border-radius:1.25rem;
  border:1px solid var(--hair);background:color-mix(in srgb,var(--accent) 3%,transparent);
  transition:border-color .4s ease,transform .5s var(--ease)}
.path::before{content:"";position:absolute;inset:auto -30% -60% auto;width:22rem;height:22rem;
  border-radius:50%;pointer-events:none;opacity:0;transition:opacity .5s ease;
  background:radial-gradient(circle,color-mix(in srgb,var(--accent) 16%,transparent),transparent 70%)}
.path:hover{border-color:color-mix(in srgb,var(--accent) 45%,transparent);transform:translateY(-4px)}
.path:hover::before{opacity:1}
.path__num{font-size:.6875rem;font-weight:600;letter-spacing:.16em;color:var(--accent);opacity:.7}
.mode-light .path__num{color:var(--gold)}
.path__ico{display:inline-flex;align-items:center;justify-content:center;
  width:3.25rem;height:3.25rem;border-radius:50%;color:var(--accent);
  border:1px solid color-mix(in srgb,var(--accent) 35%,transparent);
  background:color-mix(in srgb,var(--accent) 8%,transparent)}
.path h3{margin:0;font-family:"Bodoni Moda",serif;font-optical-sizing:auto;font-weight:700;
  font-size:clamp(1.75rem,1.2rem + 2vw,2.75rem);line-height:1.02;letter-spacing:-.015em}
/* Доріг стало три, і колонка звузилася на третину. Заголовок на 2.75rem у
   ній розсипався на три рядки — беремо на крок тихіше. */
.paths:has(> :nth-child(3)) .path h3{font-size:clamp(1.625rem,1.1rem + 1.4vw,2.25rem)}
.mode-light .path h3{color:var(--violet)}
.path p{margin:0;color:var(--muted)}
.path__meta{list-style:none;margin:.25rem 0 auto;padding:0;display:grid;gap:.4rem;
  font-size:.875rem;color:var(--muted)}
.path__meta li{position:relative;padding-left:1.15rem}
.path__meta li::before{content:"";position:absolute;left:0;top:.5em;width:.45rem;height:.45rem;
  border-radius:50%;border:1.5px solid var(--accent)}
.path .btn{margin-top:1.15rem;align-self:flex-start;flex:none}

/* ── три організації ──────────────────────────────────────────────────── */
.orgs{display:grid;gap:clamp(1.75rem,3.5vw,3rem);
  grid-template-columns:repeat(auto-fit,minmax(15rem,1fr))}
/* Колонка на всю висоту, посилання притиснуте донизу — тоді всі три
   стоять на одній лінії, хоч тексти й різної довжини. */
.org{display:flex;flex-direction:column;gap:.9rem;
  padding-top:clamp(1.25rem,2.5vw,1.75rem);border-top:1px solid var(--hair)}
/* align-self:start — інакше знак розтягується на всю ширину колонки,
   а object-fit центрує його всередині цієї коробки */
.org__logo{align-self:start;height:2.5rem;width:auto;max-width:11rem;object-fit:contain;
  object-position:left center;opacity:.9;margin-bottom:.35rem}
.mode-light .org__logo{color:var(--ink)}
.org h3{margin:0;font-size:clamp(1.0625rem,1rem + .4vw,1.25rem);font-weight:600;
  letter-spacing:.01em}
.org p{margin:0;font-size:.9375rem;line-height:1.55;color:var(--muted)}
.org__link{align-self:start;display:inline-flex;align-items:center;gap:.45rem;
  margin-top:auto;padding-top:.35rem;font-size:.875rem;font-weight:600;color:var(--accent);
  text-decoration:none;transition:gap .3s var(--ease)}
.org__link:hover{gap:.75rem}
.org__link span{text-decoration:underline;text-underline-offset:.25em;
  text-decoration-thickness:1px}
.org__link .btn__ico{width:.9rem;height:.9rem}

/* ── з ким працюємо ───────────────────────────────────────────────────── */
/* Суцільний стовпець на всю ширину правої колонки: у чотири плитки рядки
   ламалися 3+1, а списки міст стояли в два стовпці з дірками посеред рядка. */
.net{display:grid;margin:0;padding:0;list-style:none}
.net__group{display:grid;
  grid-template-columns:auto auto minmax(0,1fr);align-items:start;
  column-gap:clamp(.9rem,2vw,1.4rem);
  padding-block:clamp(1.15rem,2.4vw,1.6rem);border-top:1px solid var(--hair)}
.net__group:first-child{padding-top:0;border-top:0}
/* Порядковий номер тримає ліву кромку рядків спільною, навіть коли знаки
   партнерів різної ширини. */
.net__n{font-size:.75rem;font-weight:600;letter-spacing:.1em;color:var(--gold);
  padding-top:.5rem;font-variant-numeric:tabular-nums}
/* знак партнера — його власний, а не службова іконка */
.net__mark{display:grid;place-items:center;flex:none;
  width:clamp(2.75rem,5.5vw,3.5rem);height:clamp(2.75rem,5.5vw,3.5rem)}
.net__mark img{max-width:100%;max-height:100%;width:auto;height:auto;object-fit:contain}
.mode-light .net__mark img{opacity:.85}
.net__ico{display:grid;place-items:center;width:2.75rem;height:2.75rem;border-radius:50%;
  color:var(--accent);
  border:1px solid color-mix(in srgb,var(--accent) 32%,transparent);
  background:color-mix(in srgb,var(--accent) 7%,transparent)}
.ico--md{width:1.375rem;height:1.375rem}
.net__text{display:grid;gap:.4rem;min-width:0}
.net__group h3{margin:0;font-size:clamp(1.0625rem,1rem + .4vw,1.1875rem);font-weight:600;
  line-height:1.25}
.net__note{margin:0;font-size:.9375rem;line-height:1.55;color:var(--muted);max-width:52ch}
/* Локації течуть рядком і переносяться по ширині: фіксовані колонки лишали
   порожнечу, коли назви різної довжини. */
.net__where{display:flex;flex-wrap:wrap;margin:.3rem 0 0;padding:0;list-style:none;
  gap:.35rem clamp(.9rem,2vw,1.5rem)}
.net__where li{display:flex;align-items:baseline;gap:.35rem;min-width:0;
  font-size:.875rem;line-height:1.45;color:var(--ink)}
.net__pin{width:.8125rem;height:.8125rem;flex:none;color:var(--accent);
  transform:translateY(.1em)}

/* ── галерея: сітка з фіксованою висотою рядка, дві «героїні» ─────────── */
.gallery{display:grid;gap:clamp(.5rem,1.2vw,.875rem);
  grid-template-columns:repeat(2,minmax(0,1fr));
  grid-auto-rows:clamp(8rem,26vw,11rem);grid-auto-flow:dense}
.gallery .shot:nth-child(1){grid-column:span 2;grid-row:span 2}
.gallery .shot:nth-child(6){grid-column:span 2}
@media (min-width:52rem){
  .gallery{grid-template-columns:repeat(4,minmax(0,1fr));grid-auto-rows:clamp(9rem,13vw,13rem)}
}
.shot{position:relative;margin:0;padding:0;height:100%;overflow:hidden;border:0;
  border-radius:.75rem;isolation:isolate;cursor:zoom-in;background:none;
  font:inherit;color:inherit;display:block;appearance:none}
.shot img{width:100%;height:100%;object-fit:cover;transition:transform .7s var(--ease)}
.shot:hover img,.shot:focus-visible img{transform:scale(1.045)}
.shot__cap{position:absolute;inset:auto 0 0;z-index:1;padding:2.5rem .9rem .8rem;
  font-size:.8125rem;line-height:1.35;color:#fff;text-align:left;
  background:linear-gradient(to top,rgba(4,2,16,.82),transparent);
  opacity:0;transform:translateY(.5rem);transition:opacity .4s ease,transform .4s var(--ease)}
.shot__zoom{position:absolute;top:.6rem;right:.6rem;z-index:1;display:grid;place-items:center;
  width:2rem;height:2rem;border-radius:50%;color:#fff;background:rgba(4,2,16,.55);
  backdrop-filter:blur(4px);-webkit-backdrop-filter:blur(4px);
  opacity:0;transform:scale(.85);transition:opacity .35s ease,transform .35s var(--ease)}
.shot:hover .shot__cap,.shot:focus-visible .shot__cap,
.shot:hover .shot__zoom,.shot:focus-visible .shot__zoom{opacity:1;transform:none}

.gallery__more,.vids__more{display:inline-flex;align-items:center;gap:.55rem;margin-bottom:.4rem;
  padding:.6rem 1.1rem;border-radius:999px;cursor:pointer;white-space:nowrap;
  /* Відкривач записів — це <a>, і типове підкреслення посилання лягало
     другою лінією під тією, яку малює <span>. Альбом цього не мав, бо там
     <button>. Підкреслення веде <span> — сам елемент мовчить. */
  text-decoration:none;
  border:1px solid color-mix(in srgb,var(--accent) 38%,transparent);background:none;
  font:inherit;font-weight:600;font-size:.875rem;color:var(--accent);
  transition:background-color .3s ease,color .3s ease,border-color .3s ease}
.gallery__more:hover,.vids__more:hover{background:var(--accent);color:#fff;border-color:var(--accent)}
.gallery__more .ico,.gallery__more .btn__ico,.vids__more .btn__ico{width:.95rem;height:.95rem;
  transition:transform .35s var(--ease)}
/* Знак тут — «розгорнути», а не стрілка, тож на наведення він збільшується,
   а не від'їжджає вбік. */
.gallery__more:hover .btn__ico,.gallery__more:focus-visible .btn__ico{transform:scale(1.2)}
/* тут знак — стрілка «геть зі сторінки», тож він від'їжджає, а не росте */
.vids__more:hover .btn__ico,.vids__more:focus-visible .btn__ico{transform:translateX(.25rem)}
/* На вузьких екранах капсула з'їдає рядок під заголовком: там відкривач іде
   тихим посиланням і стоїть під самим альбомом, а не над ним. */
.gallery__more--foot,.vids__more--foot{display:none}
@media (max-width:51.99rem){
  .sect-head .gallery__more,.sect-head .vids__more{display:none}
  /* під альбомом і під записами — по лівому краю колонки */
  .gallery__more--foot,.vids__more--foot{display:flex;width:fit-content;
    margin:clamp(1.75rem,6vw,2.5rem) 0 0;
    padding:0;border:0;background:none;gap:.45rem}
  :is(.gallery__more--foot,.vids__more--foot) span{text-decoration:underline;text-underline-offset:.25em;
    text-decoration-thickness:1px}
  :is(.gallery__more--foot,.vids__more--foot):hover,
  :is(.gallery__more--foot,.vids__more--foot):focus-visible{background:none;color:var(--accent)}
  :is(.gallery__more--foot,.vids__more--foot) .btn__ico{width:.85rem;height:.85rem}
  /* Те саме правило 24px: тихий напис дає 22px заввишки. Простір додаємо
     всередину, а зовнішній відступ зменшуємо на стільки ж. */
  :is(.gallery__more--foot,.vids__more--foot){min-height:1.5rem;
    padding-block:.2rem;margin-top:calc(clamp(1.75rem,6vw,2.5rem) - .2rem)}
  /* Тут вони не капсули, а тихі написи — скла на них нема чому лежати. */
  .mode-light :is(.gallery__more--foot,.vids__more--foot){box-shadow:none;
    background-image:none;
    -webkit-backdrop-filter:none;backdrop-filter:none}
  :is(.gallery__more--foot,.vids__more--foot)::after{display:none}
  .sect-head__row{align-items:flex-start;gap:.75rem 1.5rem}
}

/* ── карта світу ──────────────────────────────────────────────────────── */
/* Суша крапками, ми — одна з них. Без цифр і без легенд по краях: сенс тут
   один — «нас багато, і ми серед них», і він читається з самої карти. */
.map__wrap{position:relative;margin:clamp(1.5rem,4vw,2.5rem) 0 0;
  width:min(100%,64rem)}
.map{display:block;width:100%;height:auto;color:var(--violet)}
/* суша тримається тлом, світяться тільки міста, де цього вечора йде бал */
.map__land{opacity:.26}
.map__lit{color:var(--gold)}
.mode-night .map{color:var(--chrome)}
.mode-night .map__lit{color:var(--chrome)}
/* з'являються із заходу на схід, по 3 мс — уся хвиля близько секунди */
.map__lit circle{opacity:0;transform:scale(.3);transform-box:fill-box;
  transform-origin:center}
.is-in .map__lit circle{animation:lit .45s var(--ease) forwards;
  animation-delay:calc(var(--i) * 3ms)}
@keyframes lit{60%{opacity:1;transform:scale(1.35)}100%{opacity:1;transform:scale(1)}}
/* позначка міста — HTML, а не SVG: так надпис лишається в загальному наборі */
/* Наша точка приходить останньою, коли хвиля вже пройшла, і лишається
   помітно більшою за решту — інакше в тому розсипі її просто не знайти. */
.map__here{position:absolute;left:var(--mx);top:var(--my);translate:-50% -50%;
  display:grid;place-items:center;color:var(--violet);opacity:0}
.is-in .map__here{animation:here .7s var(--ease) 1.05s forwards}
@keyframes here{0%{opacity:0;scale:.4}60%{opacity:1;scale:1.25}100%{opacity:1;scale:1}}
.mode-night .map__here{color:#fff}
.map__here b{position:absolute;bottom:calc(100% + .7rem);
  padding:.25rem .55rem;border-radius:.4rem;
  font-size:var(--t-eyebrow);font-weight:600;letter-spacing:.12em;
  text-transform:uppercase;white-space:nowrap;color:#fff;background:var(--violet)}
.mode-night .map__here b{color:var(--night-900);background:#fff}
.map__here b::after{content:"";position:absolute;top:100%;left:50%;translate:-50% 0;
  border:.3rem solid transparent;border-top-color:var(--violet)}
.mode-night .map__here b::after{border-top-color:#fff}
.map__here i{display:block;width:.7rem;height:.7rem;border-radius:50%;
  background:currentColor;box-shadow:0 0 0 .22rem var(--surface)}
.map__here::before,.map__here::after{content:"";position:absolute;
  width:2.4rem;height:2.4rem;border-radius:50%;
  border:1px solid currentColor;opacity:0}
.map__here::before{animation:ping 3s var(--ease) 1.5s infinite}
.map__here::after{animation:ping 3s var(--ease) 3s infinite}
@keyframes ping{0%{transform:scale(.28);opacity:.85}70%,100%{transform:scale(1);opacity:0}}
.map__legend{margin:clamp(1.25rem,3vw,2rem) 0 0;max-width:46ch;
  font-size:1rem;color:var(--muted)}
.map__legend strong{color:var(--ink);font-weight:600}
.mode-night .map__legend strong{color:#fff}
@media (prefers-reduced-motion:reduce){
  .map__here::before,.map__here::after{animation:none;opacity:0}
  .map__here{opacity:1;animation:none}
  .map__lit circle{opacity:1;transform:none;animation:none}
}

/* ── відео ────────────────────────────────────────────────────────────── */
/* Обкладинка лежить у нас, YouTube приходить лише після кліку. До того це
   звичайна картинка з кнопкою — ні скриптів, ні куків. */
.vid{position:relative;margin:0;display:grid;gap:.85rem}
.vid--main{margin-top:clamp(1.5rem,3vw,2.25rem)}
.vid__play{position:relative;display:block;width:100%;padding:0;border:0;cursor:pointer;
  background:var(--night-900);border-radius:1rem;overflow:hidden;isolation:isolate;
  aspect-ratio:16/9;transition:transform .45s var(--ease)}
.vid__play img{width:100%;height:100%;object-fit:cover;display:block;
  transition:transform .6s var(--ease),opacity .4s ease}
.vid__play::after{content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(to top,color-mix(in srgb,var(--night-900) 50%,transparent),transparent 52%);
  opacity:.9;transition:opacity .4s ease}
.vid__play:hover img{transform:scale(1.03)}
.vid__play:hover::after{opacity:.65}
.vid__btn{position:absolute;inset:auto auto 50% 50%;translate:-50% 50%;z-index:1;
  display:grid;place-items:center;width:clamp(3.25rem,6vw,4.5rem);aspect-ratio:1;
  border-radius:50%;color:#fff;
  border:1px solid rgba(255,255,255,.55);
  background:color-mix(in srgb,var(--night-900) 42%,transparent);
  backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);
  transition:background-color .35s ease,border-color .35s ease,scale .45s var(--ease)}
/* Трикутник центруємо по центру маси, а не по габаритах: маса в нього
   ліворуч, тож габаритне центрування читається як зсув уліво. Ручний
   зсув тут не потрібен — сам шлях уже намальований зі зміщенням
   (габарит 9.4–18 у полі 24), і центр маси сходиться з центром кола
   з точністю до пікселя. Було `translate:6%` — перебір на 10 px. */
.vid__btn .ico{width:45%;height:45%}
.vid__play:hover .vid__btn{scale:1.08;background:var(--violet);border-color:var(--violet)}
.vid__play:focus-visible{outline:2px solid var(--accent);outline-offset:3px}
.vid__cap{display:grid;gap:.15rem;font-size:.875rem}
.vid__cap b{font-weight:600;font-size:1rem;color:inherit}
.vid__cap span{color:var(--muted);line-height:1.45;text-wrap:pretty}
/* після кліку сюди лягає iframe — рамка та сама */
.vid iframe{position:absolute;inset:0;width:100%;height:100%;border:0}
.vid.is-live .vid__play{cursor:default}
.vid.is-live .vid__btn{display:none}
.vid.is-live .vid__play::after{opacity:0}

.vids{display:grid;gap:clamp(.85rem,2vw,1.4rem);margin-top:clamp(1rem,2.5vw,1.75rem);
  grid-template-columns:repeat(auto-fit,minmax(15rem,1fr))}

/* На телефоні чотири кадри 16:9 один під одним — це майже чотири екрани
   прокрутки. Головний лишається великим, попередні роки стають рядками:
   малий кадр ліворуч, назва праворуч. */
@media (max-width:51.99rem){
  .vids{grid-template-columns:minmax(0,1fr);gap:.75rem}
  .vids .vid{grid-template-columns:9rem minmax(0,1fr);align-items:center;gap:.9rem}
  /* Тільки на вузькому екрані плитки міняються місцями за розміром: там
     програвач у смужці 9rem нечитабельний. На широкому розкладка стоїть
     непорушно — стрибок сітки під час перемикання дратує більше, ніж
     допомагає. */
  .vids .vid.is-live{grid-column:1 / -1;grid-template-columns:minmax(0,1fr);gap:.75rem}
  .vids .vid.is-live .vid__play{border-radius:1rem}
  .vid--main.is-small{grid-template-columns:9rem minmax(0,1fr);
    align-items:center;gap:.9rem}
  .vid--main.is-small .vid__play{border-radius:.6rem}
  .vid--main.is-small .vid__btn{width:2rem;border-width:1px}
  .vid--main.is-small .vid__play::after{
    background:linear-gradient(to top,color-mix(in srgb,var(--night-900) 35%,transparent),transparent 60%)}
  .vid--main.is-small .vid__cap b{font-size:.9375rem}
  .vids .vid__play{border-radius:.6rem}
  .vids .vid__btn{width:2rem;border-width:1px}
  .vids .vid__play::after{background:linear-gradient(to top,color-mix(in srgb,var(--night-900) 35%,transparent),transparent 60%)}
  .vids .vid__cap b{font-size:.9375rem}
}

/* кліп по кромці правої колонки — щоб на екрані було два ліві краї, а не три */
.vid--wide{margin-top:clamp(1.75rem,4vw,2.75rem)}
.vid--wide .vid__play{border-radius:1.25rem}
.vid--wide .vid__btn{width:clamp(3.5rem,6.5vw,5rem)}
.vid--wide .vid__cap{max-width:52ch}
.mode-night .vid__cap b{color:#fff}

/* ── альбом у модальному вікні ────────────────────────────────────────── */
.lb{width:100vw;max-width:100vw;height:100dvh;max-height:100dvh;margin:0;padding:0;border:0;
  background:var(--night-900);color:#fff;overflow:hidden;
  --accent:var(--chrome);--surface:var(--night-900)}
.lb::backdrop{background:color-mix(in srgb,var(--night-900) 92%,transparent)}
.lb[open]{display:grid;grid-template-rows:auto minmax(0,1fr) auto}
.lb__bar{display:flex;align-items:center;justify-content:space-between;gap:1rem;
  padding:.85rem clamp(1rem,3vw,2rem);border-bottom:1px solid rgba(255,255,255,.1)}
.lb__count{font-size:.8125rem;letter-spacing:.14em;text-transform:uppercase;color:var(--steel)}
.lb__count b{color:var(--chrome);font-weight:600;font-variant-numeric:tabular-nums}
.lb__x{display:grid;place-items:center;width:2.75rem;height:2.75rem;border-radius:50%;
  border:1px solid rgba(255,255,255,.18);background:none;color:#fff;cursor:pointer;
  transition:background-color .3s ease,border-color .3s ease}
.lb__x:hover{background:rgba(255,255,255,.12);border-color:rgba(255,255,255,.4)}
.lb__x .ico{width:1.1rem;height:1.1rem}

.lb__stage{position:relative;display:grid;place-items:center;min-height:0;
  padding:clamp(.75rem,2vw,1.5rem)}
/* два рядки: знімок бере всю вільну висоту, підпис — рівно скільки треба */
.lb__fig{margin:0;display:grid;grid-template-rows:minmax(0,1fr) auto;justify-items:center;
  gap:.9rem;min-height:0;height:100%;width:100%}
.lb__fig img{max-width:min(100%,82rem);max-height:100%;min-height:0;width:auto;height:auto;
  object-fit:contain;border-radius:.5rem;
  opacity:0;transition:opacity .35s ease}
.lb__fig img.is-on{opacity:1}
.lb__fig figcaption{font-size:.875rem;color:var(--mist);text-align:center;max-width:60ch}
.lb__nav{position:absolute;top:50%;translate:0 -50%;z-index:2;
  display:grid;place-items:center;width:3rem;height:3rem;border-radius:50%;
  border:1px solid rgba(255,255,255,.18);background:color-mix(in srgb,var(--night-900) 55%,transparent);color:#fff;cursor:pointer;
  backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);
  transition:background-color .3s ease,border-color .3s ease}
.lb__nav:hover{background:rgba(255,255,255,.16);border-color:rgba(255,255,255,.45)}
.lb__nav--prev{left:clamp(.5rem,2vw,1.5rem)}
.lb__nav--next{right:clamp(.5rem,2vw,1.5rem)}
.lb__nav .ico{width:1.25rem;height:1.25rem}

.lb__strip{display:flex;gap:.5rem;overflow-x:auto;overscroll-behavior-x:contain;
  padding:.85rem clamp(1rem,3vw,2rem) 1.1rem;border-top:1px solid rgba(255,255,255,.1);
  scroll-padding-inline:clamp(1rem,3vw,2rem);
  scrollbar-width:thin;scrollbar-color:rgba(255,255,255,.25) transparent}
.lb__thumb{flex:none;width:clamp(4.5rem,9vw,6.5rem);aspect-ratio:3/2;padding:0;border:0;
  border-radius:.375rem;overflow:hidden;cursor:pointer;background:none;
  opacity:.45;transition:opacity .3s ease,box-shadow .3s ease}
.lb__thumb:hover{opacity:.8}
.lb__thumb[aria-current="true"]{opacity:1;box-shadow:inset 0 0 0 2px var(--chrome)}
.lb__thumb img{width:100%;height:100%;object-fit:cover}
@media (max-width:40rem){
  /* На вертикальному екрані горизонтальний знімок займає лише смужку, і
     решта рядка лишалася порожньою: фото притискалося до верху, підпис —
     до низу, а між ними висіла діра з двома стрілками посередині.
     Тепер знімок і підпис — одна група по центру екрана, а поля з боків
     прибрані: кадр іде від краю до краю й від того помітно більший. */
  .lb__stage{padding:0}
  .lb__fig{grid-template-rows:auto auto;align-content:center;gap:1rem}
  .lb__fig img{max-height:70vh;width:100%;border-radius:0}
  .lb__fig figcaption{font-size:.8125rem;padding-inline:1.25rem}
  /* Стрілки стають при самому краю кадру: у центрі порожнечі вони не мали
     до чого кріпитися. Гортати можна й пальцем — свайп тут працює. */
  .lb__nav{width:2.5rem;height:2.5rem}
  .lb__nav--prev{left:.5rem}
  .lb__nav--next{right:.5rem}
}

/* ── логотипи: організатор / патронат / партнер ───────────────────────── */
/* Три групи стоять поруч на будь-якій ширині — блок зменшується, а не переноситься.
   Знак має задану висоту, але в тісній колонці стискається пропорційно
   (`width: min(бажана, 100%)` плюс `aspect-ratio`), тож нічого не вилазить. */
.logos{--logo-h:clamp(1.5rem,4.4vw,3.25rem);
  display:grid;grid-template-columns:repeat(3,minmax(0,auto));
  /* stretch, а не start — інакше розділові лінії виходять різної довжини */
  justify-content:space-between;align-items:stretch;
  column-gap:clamp(.75rem,2.5vw,4.5rem);row-gap:clamp(2rem,4vw,3.5rem)}
.logos__group + .logos__group{padding-left:clamp(.75rem,2.5vw,4.5rem);
  border-left:1px solid var(--hair)}
.logos__label{margin:0 0 1.25rem;font-size:var(--t-eyebrow);font-weight:600;letter-spacing:.14em;
  text-transform:uppercase;color:var(--muted);text-wrap:balance}
/* На вузькому дозволяємо перенос усередині групи, від 40rem — ніколи:
   там знаки стискаються, а не переносяться. */
.logos__row{display:flex;flex-wrap:wrap;align-items:center;
  gap:clamp(.5rem,1.6vw,2.5rem);margin:0;padding:0;list-style:none}
@media (min-width:40rem){
  .logos__row:not(.logos__row--grid):not(.logos__row--flow){flex-wrap:nowrap}
}
/* знаки переносяться за шириною, а не за лічбою: вузькі стають по троє в ряд,
   широкі самі відходять на наступний */
.logos__row--flow{flex-wrap:wrap;max-width:var(--rowmax,24rem);
  gap:clamp(.55rem,1.2vw,1.1rem) clamp(.7rem,1.4vw,1.35rem)}
/* скільки знаків у ряд — задається з контенту через --cols */
/* Колонки за вмістом, а не рівні: знаки тут різної ширини, і рівні колонки
   лишали півколонки порожнечі праворуч від вузького знака — між сусідами
   зяяла діра, більша за самі знаки. За вмістом між ними лишається рівно
   проміжок сітки, а він заданий і однаковий для всіх рядів. */
.logos__row--grid{display:grid;grid-template-columns:repeat(var(--cols,3),max-content);
  justify-content:start;align-items:center;
  gap:clamp(.75rem,1.4vw,1.25rem) clamp(1rem,1.6vw,1.75rem)}
/* Ширину задаємо числом, без відсотків: відсоток усередині min() не дає
   браузеру порахувати ширину колонки сітки, і вона виходила замалою —
   звідси й був зайвий перенос на широкому екрані.
   Стискання бере на себе flex-shrink, пропорцію тримає aspect-ratio. */
.logos__item{display:flex;align-items:center;justify-content:center;color:inherit;
  flex:0 1 auto;min-width:0;
  aspect-ratio:var(--ar,2);height:auto;
  width:calc(var(--logo-h) * var(--gs,1) * var(--s,1) * var(--ar,2));
  opacity:.85;transition:opacity .35s ease,transform .45s var(--ease)}
.logos__item:hover{opacity:1;transform:translateY(-3px)}
.logos__item img{width:100%;height:100%;object-fit:contain}
.mode-light .logos__item{color:var(--ink)}
.mode-night .logos__item{color:#fff}
/* На вузьких екранах три колонки не вміщаються: знаки зіщулюються до
   нечитабельного, а вертикальні лінії ріжуть екран. Групи стають одна під
   одною, розділові — горизонтальні, а самі знаки більшають. */
@media (max-width:51.99rem){
  .logos{--logo-h:clamp(2.25rem,9.5vw,2.75rem);
    grid-template-columns:minmax(0,1fr);row-gap:0}
  .logos__group + .logos__group{padding:clamp(1.5rem,5vw,2rem) 0 0;
    margin-top:clamp(1.5rem,5vw,2rem);
    border-left:0;border-top:1px solid var(--hair)}
  .logos__label{margin-bottom:.9rem}
  /* Шість знаків в один рядок не вміщалися, і `flex-shrink` тиснув кожен
     нижче заданої висоти — виходила тонка нечитабельна смужка. Тому на
     вузькому це сітка по троє: знак тримає свою висоту, а група отримує
     форму замість смужки. Комірки рівні, знак усередині вирівняний по
     лівому краю — тоді ліві кромки знаків стоять одна під одною. */
  .logos__row:not(.logos__row--grid){display:grid;
    grid-template-columns:repeat(3,minmax(0,1fr));
    justify-items:start;align-items:center;
    gap:clamp(.9rem,4vw,1.4rem)}
  .logos__row--flow{max-width:100%}
  .logos__item{flex:none;max-width:100%}
  /* Групи з одним знаком не мусять розтягуватися на третину екрана. */
  .logos__row:not(.logos__row--grid):has(> :only-child){
    grid-template-columns:minmax(0,1fr)}
  .logos__row--grid{grid-template-columns:repeat(var(--cols,3),minmax(0,max-content))}
  /* Локапи з набірним текстом: на спільній висоті прізвище падає до 6–7px.
     Даємо їм власну, більшу — читабельність тут важливіша за єдину міру. */
  .logos__group--wide{--logo-h:clamp(3rem,13vw,4rem)}
}

/* ── смуга «Mówią o nas» ──────────────────────────────────────────────────
   Плитки редакцій ліворуч, панель із цитатою праворуч. Логіка прийшла з
   «As seen in» на evenrealities.com, оформлення — наше: там пласкі сірі
   прямокутники з гострими кутами, тут та сама картка, що в «трьох дорогах»
   і «мережі співпраці» — заокруглення, волосяна рамка, заливка акцентом
   на три відсотки й світлова пляма під курсором.

   Цитуємо текст самої редакції, а не слова названої людини: коротка цитата
   з підписом і посиланням — звичайне право цитати, чиїсь особисті слова
   потребують згоди.                                                      */
.press{display:grid;gap:var(--gap);--gap:clamp(.55rem,1.2vw,.85rem);
  grid-template-columns:minmax(0,1fr);
  margin:clamp(1.75rem,3.5vw,2.75rem) 0 0}
@media (min-width:60rem){
  .press{grid-template-columns:minmax(0,.82fr) minmax(0,1.18fr)}
}

.press__tiles{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));
  align-content:start;gap:var(--gap);margin:0;padding:0;list-style:none}
.press__cell{display:grid;min-width:0}

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

   Сама заливка стану не тримає: акцент 9% проти сусідньої плитки дає
   1.13:1 при потрібних 3:1 (WCAG 1.4.11). Тримає рамка — суцільний
   фіолет на папері це 9:1. */
.press__tile{position:relative;overflow:hidden;
  display:grid;place-items:center;width:100%;height:100%;
  aspect-ratio:2.4 / 1;min-height:4.75rem;
  padding:clamp(.85rem,2.2vw,1.35rem);border-radius:1rem;
  border:1px solid var(--hair);
  background:color-mix(in srgb,var(--accent) 3%,transparent);
  color:inherit;font:inherit;cursor:pointer;
  transition:background-color .35s var(--ease),border-color .4s ease}
.press__tile::before{content:"";position:absolute;inset:auto -35% -75% auto;
  width:14rem;height:14rem;border-radius:50%;pointer-events:none;
  opacity:0;transition:opacity .5s ease;
  background:radial-gradient(circle,color-mix(in srgb,var(--accent) 18%,transparent),transparent 70%)}
.press__tile:hover{border-color:color-mix(in srgb,var(--accent) 45%,transparent);
  background:color-mix(in srgb,var(--accent) 6%,transparent)}
.press__tile[aria-selected="true"]{border-color:var(--accent);
  background:color-mix(in srgb,var(--accent) 9%,var(--paper))}
.press__tile[aria-selected="true"]::before{opacity:1}
.press__tile:focus-visible{outline:2px solid var(--accent);outline-offset:3px}

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

   Механіка та сама, що в сторіс до переліку справ (`@keyframes story`): час
   відмірює CSS-анімація, а JS лише слухає `animationend`. Через це пауза
   дістається задарма — `animation-play-state`, — і смужка ніколи не
   розходиться з тим, що насправді на екрані.

   Сама смужка й означає «крутиться саме». Щойно людина вибирає плитку
   руками, карусель зупиняється назавжди й смужка зникає: рух під чужою
   рукою — це не функція, а перешкода. Стан при цьому не губиться, бо його
   тримають рамка й заливка плитки, а не смужка. */
.press__tile::after{content:"";position:absolute;inset-inline:0;bottom:0;
  height:2px;border-radius:999px;background:var(--accent);
  transform:scaleX(0);transform-origin:0 50%}
.press__tile[aria-selected="true"]::after{
  animation:story var(--press-run,7.5s) linear forwards}
/* Пауза: під курсором і поки секції не видно. */
.press.is-hold .press__tile::after,
.press.is-away .press__tile::after{animation-play-state:paused}
/* Зупинка назавжди — коли плитку вибрали рукою. */
.press.is-stopped .press__tile::after{animation:none;transform:scaleX(0)}

/* На широкому плитки стають стовпчиком у чотири рядки й розтягуються на
   висоту панелі: чотири редакції не заповнюють сітку 2×2 так, щоб вона
   дорівнювала панелі, і під нею лишалася б порожня третина колонки.
   Розтягнуті рядки й `aspect-ratio` несумісні — висоту тут задає сітка. */
@media (min-width:60rem){
  .press__tiles{grid-template-columns:minmax(0,1fr);align-content:stretch;
    /* рівні рядки: інакше плитка з вищим знаком забирає собі більше */
    grid-auto-rows:minmax(0,1fr)}
  .press__tile{aspect-ratio:auto;min-height:0}
}

/* Знаки монохромні. Чотири чужі палітри поруч — червона, синя, фіолетова,
   чорна — перетягували увагу на себе й сперечалися з нашим фіолетом; у
   сірому ряд читається як один перелік, а не як вітрина логотипів.
   Прозорість, а не сірий колір: сірий довелося б підбирати під кожен знак
   окремо, бо в одних чорна заливка, в інших кольорова плашка. */
.press__logo{position:relative;height:calc(var(--h,1) * var(--k,1));width:auto;
  max-width:100%;object-fit:contain;
  --h:clamp(1.25rem,.85rem + 1.4vw,1.85rem);
  filter:grayscale(1) contrast(1.05);opacity:.58;
  transition:opacity .3s var(--ease)}
.press__tile:hover .press__logo{opacity:.78}
.press__tile[aria-selected="true"] .press__logo{opacity:1}
.press__name{font-size:var(--t-eyebrow);font-weight:600;letter-spacing:.06em;
  text-transform:uppercase;text-align:center;color:var(--accent)}

/* ── панель ──────────────────────────────────────────────────────────── */
.press__panels{display:grid}
.press__panel{position:relative;overflow:hidden;
  display:flex;flex-direction:column;gap:clamp(1rem,2.2vw,1.5rem);
  padding:clamp(1.5rem,3.2vw,2.5rem);border-radius:1.25rem;
  border:1px solid var(--hair);
  background:color-mix(in srgb,var(--accent) 3%,transparent)}
/* Панелі лежать в одній клітинці сітки — блок має висоту найбільшої й не
   стрибає при перемиканні. На телефоні це коштувало б екрана порожнечі під
   короткою панеллю, тож там показуємо тільки потрібну, а висоту віддаємо
   вмісту: сторінка під нею й так поїде, це звичний для телефона рух. */
.js .press__panel{display:none}
.js .press__panel.is-on{display:flex;animation:pressIn .4s var(--ease) both}
@keyframes pressIn{from{opacity:0;transform:translateY(.5rem)}to{opacity:1;transform:none}}
@media (min-width:60rem){
  .js .press__panel{display:flex;grid-area:1 / 1;
    visibility:hidden;opacity:0;animation:none;
    transition:opacity .35s var(--ease),visibility .35s}
  .js .press__panel.is-on{visibility:visible;opacity:1;animation:none}
}
/* Без скрипта панелі йдуть одна за одною — і читаються всі чотири. */
html:not(.js) .press__panels{gap:var(--gap)}
html:not(.js) .press__tiles{display:none}

/* Знак у панелі стоїть дрібно в правому куті. Великим угорі він повторював
   щойно натиснуту плитку — той самий логотип двічі поруч, і панель читалася
   як ще одна плитка, а не як її вміст. Його робота тут службова:
   підтвердити, що відкрилося саме те, на що натиснули. Хто саме говорить —
   каже підпис під цитатою, і каже словами. */
.press__panel-mark{display:block;align-self:flex-end;margin-bottom:-.6rem}
.press__panel-mark .press__logo{--h:clamp(.6875rem,.5rem + .55vw,.9375rem);
  opacity:.5}

/* Цитата набрана Bodoni — тією самою гарнітурою, що заголовки секцій. Це
   єдине місце на сторінці, де довгий текст не наш, і гарнітура каже про це
   раніше за підпис. */
.press__quote{margin:0;display:flex;flex-direction:column;gap:.9rem;
  position:relative}
@media (min-width:60rem){
  .press__quote{flex:1 1 auto;justify-content:center}
}
.press__quote p{margin:0;font-family:"Bodoni Moda",serif;font-optical-sizing:auto;
  font-weight:500;font-size:clamp(1.1875rem,1rem + .85vw,1.75rem);
  line-height:1.32;letter-spacing:-.005em;text-wrap:pretty;max-width:34ch}
/* Лапки малює CSS, а не контент: у JSON лежить чистий текст редакції, тож
   його видно в пошуку й у llms.txt без чужої пунктуації. Заодно вони самі
   стають на потрібні для мови сторінки: польська відкриває лапку внизу
   („), англійська вгорі (“).

   Відкривальна висить за лівим краєм (`text-indent`) і взята акцентом. Це
   стара друкарська звичка: якщо лапку лишити в рядку, вона вибиває початок
   абзацу всередину й ліва кромка колонки перестає бути прямою. Заразом це
   єдина позначка, яка й потрібна: велика лапка-водяний знак у кутку, яка
   тут стояла спершу, налазила на перший рядок цитати. */
.press__quote p{text-indent:-.42em}
.press__quote p::before{content:"\201C";color:color-mix(in srgb,var(--accent) 55%,transparent)}
.press__quote p::after{content:"\201D";color:color-mix(in srgb,var(--accent) 55%,transparent)}
.press__quote:lang(pl) p::before{content:"\201E"}
/* Підпис золотом — тим самим, яким на сторінці набрані всі порядкові
   позначки. Риска перед ним відділяє чужі слова від наших. */
.press__cite{display:flex;align-items:flex-start;gap:.6rem;
  font-style:normal;font-size:var(--t-eyebrow);letter-spacing:.06em;
  line-height:1.45;text-transform:uppercase;color:var(--gold)}
.press__cite::before{content:"";flex:none;width:1.5rem;height:1px;
  margin-top:.65em;background:currentColor;opacity:.55}
.press__cite > span{min-width:0}
.press__dot{display:inline-block;width:3px;height:3px;border-radius:50%;
  margin:0 .55em;vertical-align:.2em;background:currentColor;opacity:.55}

/* ── перелік матеріалів ─────────────────────────────────────────────── */
.press__more{display:flex;align-items:center;gap:.5rem;margin:0 0 -.25rem;
  font-size:var(--t-eyebrow);letter-spacing:.06em;text-transform:uppercase;
  color:var(--muted)}
.press__more .ico{width:.9375rem;height:.9375rem;flex:none;color:var(--accent)}
.press__reads{display:grid;margin:0;padding:0;list-style:none}
.press__reads a{display:grid;grid-template-columns:minmax(0,1fr) auto;
  align-items:baseline;gap:.2rem .75rem;padding:.7rem 0;
  border-top:1px solid var(--hair);color:inherit;text-decoration:none;
  transition:border-color .3s var(--ease)}
.press__reads li:first-child a{border-top:0;padding-top:0}
.press__reads a:hover{border-top-color:color-mix(in srgb,var(--accent) 45%,transparent)}
.press__reads a > span{font-size:.9375rem;line-height:1.4;font-weight:500;
  text-decoration:underline;text-decoration-color:transparent;
  text-underline-offset:.22em;text-decoration-thickness:1px;
  transition:text-decoration-color .3s var(--ease),color .3s var(--ease)}
.press__reads a:hover > span,.press__reads a:focus-visible > span{
  color:var(--accent);
  text-decoration-color:color-mix(in srgb,var(--accent) 70%,transparent)}
.press__reads time{grid-column:1;font-size:.75rem;color:var(--muted);
  font-variant-numeric:tabular-nums}
.press__ico{grid-column:2;grid-row:1 / span 2;align-self:start;
  width:.95rem;height:.95rem;margin-top:.15rem;color:var(--muted);
  transition:transform .3s var(--ease),color .3s var(--ease)}
.press__reads a:hover .press__ico,.press__reads a:focus-visible .press__ico{
  color:var(--accent);transform:translate(.15rem,-.15rem)}
.press__reads a:focus-visible{outline:2px solid var(--accent);outline-offset:.35rem;
  border-radius:.25rem}

/* На телефоні плитки лишаються зверху, а не навпаки, як у першоджерела:
   панель — це відповідь на дотик, і якщо вона над пальцем, відповіді не
   видно. */
@media (max-width:34rem){
  .press__tile{aspect-ratio:2 / 1;min-height:4.25rem}
}

/* ── фінальний заклик ─────────────────────────────────────────────────── */
.section--cta{text-align:center;overflow:hidden}
/* Сяйво за закликом. Дві плями замість однієї — тепла й фіолетова, — і кожна
   живе своїм життям: розміри й позиції анімуються незалежно, тож сукупна
   форма постійно змінюється, а не пульсує на місці. Цикл 34 секунди, тобто
   форма ніколи не повторюється в межах одного погляду.

   Одна пляма з різким краєм (`transparent 70%`) читалася як нерівна: край
   потрапляв у кадр і ставало видно, що це еліпс. Тепер `closest-side` плюс
   проміжний стоп — згасання йде до самого краю. */
.section--cta::after{content:"";position:absolute;inset:0;z-index:0;pointer-events:none;
  background-repeat:no-repeat;
  background-image:
    radial-gradient(ellipse closest-side at 50% 50%,
      rgba(255,200,128,.07),rgba(255,200,128,.02) 52%,transparent 100%),
    radial-gradient(ellipse closest-side at 50% 50%,
      rgba(72,36,214,.32),rgba(72,36,214,.08) 58%,transparent 100%);
  /* Секція має `overflow:hidden`, тож пляма впиралася в її межі різаною
     лінією згори й знизу. Маска гасить її до країв. */
  -webkit-mask-image:linear-gradient(to bottom,transparent 0,#000 16%,#000 84%,transparent 100%);
          mask-image:linear-gradient(to bottom,transparent 0,#000 16%,#000 84%,transparent 100%);
  animation:ctaBreathe 34s ease-in-out infinite}
@keyframes ctaBreathe{
  0%,100%{background-size:118% 104%, 84% 76%; background-position:50% 44%, 36% 58%}
  27%    {background-size:134% 116%, 98% 88%; background-position:55% 39%, 48% 66%}
  54%    {background-size:108% 126%, 90% 98%; background-position:46% 48%, 60% 52%}
  78%    {background-size:126% 110%, 80% 84%; background-position:52% 42%, 42% 61%}
}
@media (prefers-reduced-motion:reduce){
  .section--cta::after{animation:none;
    background-size:120% 110%, 90% 84%;background-position:50% 45%, 42% 58%}
}
.section--cta .sect-head{margin-bottom:0}
.section--cta .sect-head__rule{display:none}
.section--cta .section__title{margin-inline:auto;max-width:15ch;
  font-size:clamp(2.5rem,1rem + 6vw,5.5rem)}
.cta__lead{margin:1.5rem auto 0;max-width:40ch;font-size:var(--t-lead);line-height:1.45;
  color:var(--mist)}
.section--cta .actions{justify-content:center}
.cta__meta{display:flex;flex-wrap:wrap;justify-content:center;gap:.6rem 2rem;
  margin:clamp(2.25rem,4vw,3rem) 0 0;font-size:.8125rem;letter-spacing:.1em;
  text-transform:uppercase;color:var(--steel)}
.cta__meta span{display:inline-flex;align-items:center;gap:.5rem}
.cta__meta .ico{width:1rem;height:1rem;color:var(--chrome)}
/* Дата веде в календар. Не окремий рядок із другою такою самою іконкою —
   сама дата: іконка календаря біля неї й так стоїть, тож натяк уже
   наполовину зроблений. Підкреслення тихе, але постійне: на дотику немає
   наведення, і без нього про дію ніхто б не здогадався. */
/* Простір для пальця додаємо всередину й знімаємо від'ємним полем: рядок
   лишається там, де стояв, а ціль дотику доростає до потрібних 24px. */
.cta__cal{display:inline-flex;align-items:center;gap:.5rem;color:inherit;
  text-decoration:none;padding-block:.4rem;margin-block:-.4rem;
  font:inherit;letter-spacing:inherit;border:0;background:none;cursor:pointer}
.cta__cal span{text-decoration:underline;text-underline-offset:.3em;
  text-decoration-thickness:1px;
  text-decoration-color:color-mix(in srgb,currentColor 30%,transparent)}
.cta__cal:hover span{text-decoration-color:currentColor}

/* Небо над фінальним закликом. Маска симетрична, на відміну від першого
   екрана: там пил гасне донизу, бо нижче йде сторінка, а тут секція
   коротка й обрізана з обох боків — видимий край читався б як лінія.
   Смуга широка: розчинення з'їдало по чверті висоти згори й знизу, і пил
   лишався тільки навколо напису. Тепер він іде майже на всю секцію, а
   м'який край беруть на себе останні 9%. */
.sky__stars--cta{
  -webkit-mask-image:linear-gradient(to bottom,transparent 0,#000 9%,#000 91%,transparent 100%);
          mask-image:linear-gradient(to bottom,transparent 0,#000 9%,#000 91%,transparent 100%)}

/* ── підвал ───────────────────────────────────────────────────────────── */
.section--footer{padding-block:clamp(2.25rem,3.2vw,3.25rem)}
.foot{display:grid;gap:clamp(2rem,4vw,3rem);padding-top:clamp(2rem,4vw,3rem);
  border-top:1px solid var(--hair)}
@media (min-width:52rem){
  .foot{grid-template-columns:minmax(0,1fr) auto;align-items:start}
  .foot__cols{grid-auto-flow:column;grid-auto-columns:minmax(8rem,auto)}
}
.foot__logo{width:clamp(9rem,18vw,13rem);height:auto}
.foot__mark{margin:0;font-family:"Bodoni Moda",serif;font-optical-sizing:auto;font-weight:700;
  font-size:clamp(1.5rem,1.1rem + 1.4vw,2.25rem);line-height:1;letter-spacing:-.01em}
.foot__mark b{font-weight:400;font-style:italic;color:var(--accent)}
.foot__when{margin:1rem 0 0;font-size:.8125rem;letter-spacing:.1em;text-transform:uppercase;
  color:var(--muted)}
/* Рядки вирівнюються по довжині. Тут був жорсткий перенос, і разом із
   природним по 42ch виходило довгий-короткий-довгий — рвана драбинка.
   `balance` розкладає ті самі слова на рядки приблизно однакової
   довжини, і робить це на будь-якій ширині, а не лише на тій, під яку
   перенос ставили руками. */
.foot__note{margin:1.25rem 0 0;max-width:42ch;font-size:.875rem;color:var(--muted);
  text-wrap:balance}
/* Розкладку підвалу на телефоні лишаємо вертикальною, як була: знак, під ним
   дата, під нею текст. Двоколонковий варіант пробували й відкотили.

   Кегль тексту на телефоні — 11px замість базових 14. Дійшли до нього
   кроками: 7 → 8.4 → 11. Це нижня межа, на якій рядок ще читається
   з телефона, і саме її тут і варто тримати. */
@media (max-width:51.99rem){
  .foot__note{font-size:.6875rem;line-height:1.55;max-width:60ch}
}

.foot__cols{display:grid;gap:clamp(1.5rem,4vw,3rem);
  grid-template-columns:repeat(auto-fit,minmax(9rem,auto))}
/* Підстраховка: колонка не мусить бути ширшою за свій вміст, а найдовший
   рядок у крайньому разі переноситься, а не тікає за край сторінки. */
.foot__col{min-width:0}
.foot__col li > *{max-width:100%}
.foot__col li span{overflow-wrap:anywhere}
.foot__col h3{margin:0 0 .85rem;font-size:var(--t-eyebrow);font-weight:600;letter-spacing:.16em;
  text-transform:uppercase;color:var(--muted)}
.foot__col ul{list-style:none;margin:0;padding:0;display:grid;gap:.6rem;font-size:.9375rem}
.foot__col li > *{display:inline-flex;align-items:center;gap:.6rem}
.foot__col .ico{width:1rem;height:1rem;flex:none;opacity:.45;
  transition:opacity .3s ease,color .3s ease}
.foot__col a:hover .ico{opacity:1;color:var(--accent)}
.foot__col a{color:inherit;text-decoration:none;opacity:.8;
  transition:opacity .25s ease,color .25s ease}
.foot__col a:hover{opacity:1;color:var(--accent)}

/* На телефоні колонки лишаються поруч. Поставлені одна під одну, вони
   додавали б підвалу ще пів екрана, а він і так найдовше місце сторінки.
   Замість переносу зменшуємо кегль: мірка тут — найдовший рядок, пошта
   `recepcja@proemzako.pl`. При 15px вона просила 151px тексту, а половина
   екрана 375px дає лише 130px під текст. Тому на телефоні дрібнішає все,
   що краде в рядка ширину: кегль, знак, проміжок біля знака й проміжок
   між колонками. */
@media (max-width:32rem){
  /* Колонки тут нерівні: перша по вмісту, друга забирає решту. Рівні
     половини були оманою — короткі адреси лишали праворуч від себе
     півколонки порожнечі, і саме вона читалася як завеликий проміжок,
     а не сам проміжок. Тепер відстань між колонками задана явно, і все,
     що вивільнилося, дістається пошті — найдовшому рядку підвалу. */
  .foot__cols{grid-template-columns:auto minmax(0,1fr);
    gap:0 clamp(1.75rem,10vw,2.75rem)}
  /* Кегль тече разом із шириною. Фіксоване значення тут не працює: на 414px
     пошта має 12px запасу, а на 360 не має жодного — і переїжджає на другий
     рядок просто посеред адреси. 11.5px на вузькому краю — не імпровізація,
     а той самий рівень, на якому в цьому ж підвалі стоїть дрібний текст. */
  .foot__col ul{font-size:clamp(.6875rem,.05rem + 3.2vw,.8125rem);gap:.55rem}
  .foot__col li > *{gap:.4rem}
  .foot__col .ico{width:.8125rem;height:.8125rem}
}

/* ── смуга на всю ширину ──────────────────────────────────────────────── */
.section--band{padding-block:0}
.band{position:relative;margin:0;overflow:hidden;isolation:isolate}
.band img{width:100%;height:clamp(16rem,46vh,32rem);object-fit:cover}
.band img[data-parallax]{transform:scale(1.14);will-change:transform}

/* Головне фото після першого екрана: висока смуга, що знизу розчиняється
   в кольорі сторінки, а наступна секція заходить на неї — текст починається
   вже на фотографії. */
.section--band.is-bleed{z-index:1}
/* Перехід ніч→світло тут не потрібен і шкодить: наступна секція — це
   фотографія на весь екран, і темний градієнт у 224px лягає просто на неї
   темною плямою з видимим краєм. Знімок і так починається темним, тож
   стик читається без допомоги. */
.section--band.is-bleed::before{content:none}
/* Смуга була на 84vh, з яких третина — уже майже чистий папір. Знімок нижчий,
   розчинення коротше і крутіше, а наступна секція заходить глибше — так смуга
   під заголовком читається як тло, а не як порожнеча. */
/* Висота смуги — це і є висота видимого шматка знімка: ширина в нас завжди
   100vw, тож показати більше знизу можна тільки вищою смугою. На 88vh кадр
   іде від 8.3% висоти знімка (над циліндром лишається запас) до 91.7%. */
/* Кадр показуємо вище за середину: у нижній третині знімка через кадр
   проходить розмитий передній план, і під молочним розчиненням він лишався
   темною плямою — усе довкола світлішало, а він ні. З `38%` він іде туди,
   де розчинення вже суцільне. */
.band--bleed img{height:clamp(20rem,66vh,40rem);object-position:50% 38%}
/* Мікроповорот із наїздом: поки смуга заходить знизу, знімок ледь
   повернутий і трохи більший, а до моменту, коли вона стає на місце,
   і поворот, і наїзд сходять у нуль. `--bp` рахує скрол-кадр у скрипті.

   `rotate` і `scale` — окремі властивості, не `transform`: той зайнятий
   паралаксом і мобільним масштабом, і вони б затирали одне одного.
   Наїзд трохи випереджає поворот (`* 1.15`), щоб кути не оголилися:
   при 1.1° на смузі 792px кутам треба близько 8px запасу, а 7% дають 55.

   Тільки від 52rem. На телефоні смуга й так показує знімок цілком,
   а зайва анімація на весь екран там дорожча. */
@media (min-width:52rem){
  .band--bleed img{
    rotate:calc(var(--bp,0) * 1.1deg);
    scale:calc(1 + var(--bp,0) * 0.07);
    will-change:rotate,scale}
}
@media (prefers-reduced-motion:reduce){
  .band--bleed img{rotate:none;scale:1}
}
@media (min-width:52rem){ .band--bleed img{height:clamp(24rem,88vh,52rem)} }
/* Розчинення підіймається разом із текстом: поки блок стоїть високо на фото,
   молочна зона довша, і шапка розділу лишається на майже чистому папері.
   У спокої (--r:0) все повертається до вивіреної висоти 56%. */
/* Розчинення лише знизу й **стале**. Раніше воно росло вгору разом із
   підйомом тексту (`--r`), щоб надпис не впав на неприкритий кадр. Але
   разом із тим воно підсвічувало верхню половину знімка, і темніші місця
   кадру читалися на цьому фоні як брудні плями. Стала висота лишає верх
   фотографії таким, яким його зняли. */
.band--bleed::after{content:"";position:absolute;inset:auto 0 0;
  height:73%;pointer-events:none;
  background:linear-gradient(to bottom,
    rgba(252,250,247,0) 0%,
    rgba(252,250,247,.55) 38%,
    rgba(252,250,247,.92) 66%,
    var(--paper) 88%)}
/* Заходимо рівно настільки, щоб шапка секції стала там, де розчинення вже
   майже суцільне: глибше — і надпис читається крізь фото. */
.is-bleed + .section{margin-top:calc(-1 * clamp(5.5rem,14vh,11rem));
  background:transparent;padding-top:0}
/* На телефоні смуга показує знімок цілком і нижня його частина — це вже ноги
   та підлога. Текст заходить глибше, а розчинення довше й крутіше, щоб під
   шапкою розділу однаково лишався майже чистий папір. */
@media (max-width:51.99rem){
  /* У вузькому кадрі `cover` тягне знімок по висоті, тож видно його повністю —
     і згори лишається смуга стелі, а гість унизу йде під розчинення. Масштаб
     від нижнього краю зрізає чверть знімка згори й підтягує групу вгору. */
  .band--bleed img{transform-origin:50% 100%;transform:scale(1.2)}
  /* А от перехід ніч→світло тут повертаємо. Вище він знятий з міркування
     «знімок і так починається темним» — і на широкому екрані це правда. На
     телефоні ні: після масштабу від нижнього краю зверху відкривається
     пересвічена стіна із прожектором (яскравість 179 із 255 проти 30 унизу
     самого файла). Ніч героя впиралася в білясте фото різким стиком, і
     верхня третина смуги читалася як біла заливка — хоча жодної заливки
     там не було, це сам знімок.
     Градієнт іде з кольору ночі, тобто продовжує перший екран у фото, а не
     кладе на нього пляму. */
  .section--band.is-bleed::before{content:"";height:clamp(5rem,22vw,9rem)}
  /* Розчинення починається м'яко. Було три стопи: 0 → .65 на 30% → .95 на
     52% → папір на 72%. Нахил там сталий від найпершого пікселя, тобто на
     верхньому краї шару стрибком міняється друга похідна — і око читає це
     як лінію поперек знімка. На широкому екрані та сама крива розтягнута
     на вдвічі більшу висоту, тому непомітна; на телефоні перші 65%
     прозорості набиралися за сотню пікселів.
     Тепер шар вищий (76% замість 62%), а стопів більше, і перші з них
     майже плаcкі — нахил наростає поступово, зламу немає. Точка, де папір
     стає суцільним, лишилася там само: 77% від вищого шару — це та сама
     висота, що 72% від нижчого. */
  .band--bleed::after{height:76%;
    background:linear-gradient(to bottom,
      rgba(252,250,247,0) 0%,
      rgba(252,250,247,.03) 12%,
      rgba(252,250,247,.10) 24%,
      rgba(252,250,247,.24) 36%,
      rgba(252,250,247,.44) 48%,
      rgba(252,250,247,.64) 58%,
      rgba(252,250,247,.84) 68%,
      var(--paper) 77%)}
  .is-bleed + .section{margin-top:calc(-1 * clamp(7rem,20vh,13rem))}
}
.is-bleed + .section::before{content:none}
/* Текст виїжджає з-під власного положення: стартує піднятим на фото й
   сходить донизу, поки гортаєш свій звичайний екран. Скрол ніде не
   захоплюється — рухаємо тільки `translate`, прив'язаний до позиції.
   Рухаємо обгортку, а не секцію: трансформ на секції став би контейнером
   для липкої лівої колонки й перерахував би її прив'язку.
   На телефоні хід коротший — там знімок і так видно повністю. */
.rise{translate:0 calc(var(--r,0) * -36vh);will-change:translate}
@media (max-width:51.99rem){ .rise{translate:0 calc(var(--r,0) * -21vh)} }
@media (prefers-reduced-motion:reduce){ .rise{translate:none} }
/* На дотику цього ефекту немає — і це не економія, а неможливість.
   Ефект, прив'язаний до скролу з JS, на телефоні приречений смикатися:
   сторінку з інерцією гортає композитор, а положення нам повідомляє подія
   scroll на головному потоці — із запізненням. Між кадрами палець
   проходить чималу відстань, і текст не їде, а стрибає навздогін. Це не
   питання оптимізації: кадри тут не падають (заміряно 8.6 мс, жодного
   пропуску), просто число приходить запізно.
   Умова саме `pointer:coarse`, а не ширина: винна інерційна прокрутка
   пальцем, а не розмір екрана. Планшет із мишею ефект збереже. */
@media (pointer:coarse){ .rise{translate:none;will-change:auto} }

/* дуотон, як на розворотах каталогу: фото в брендовий фіолет.
   Ґрунт світліший за акцент сторінки — саме таким він був у друку. */
.band--duotone{--duo:#32139F;background:var(--duo)}
/* Було `screen` — він завжди висвітлює, і знімок виходив пересвіченим.
   Тепер просто чорно-білий кадр на 30% поверх фіолетового ґрунту: фото
   лишається як текстура, а не як картинка, що спорить із текстом. */
.band--duotone img{filter:grayscale(1) contrast(1.15);
  opacity:.3;height:clamp(22rem,66vh,42rem)}
/* Затемнення тільки по краях, де лежить текст. Середина лишається світлою —
   там стоїть цифра, і вона тримається власним контуром. */
.band--duotone::after{content:"";position:absolute;inset:0;pointer-events:none;
  background:
    linear-gradient(90deg,rgba(6,1,36,.3) 0%,rgba(6,1,36,.08) 26%,
      rgba(6,1,36,0) 42%,rgba(6,1,36,0) 58%,rgba(6,1,36,.08) 74%,rgba(6,1,36,.3) 100%),
    linear-gradient(to bottom,rgba(6,1,36,.16),transparent 24%,transparent 80%,rgba(6,1,36,.2))}

/* На вузькому все стає в стовпчик по центру — саме туди, де знімок найсвітліший.
   Затемнення по краях уже не рятує, тож там ґрунт темніє рівномірно. */
@media (max-width:55.99rem){
  .band--duotone::after{background:
    linear-gradient(to bottom,rgba(6,1,36,.5) 0%,rgba(6,1,36,.34) 22%,
      rgba(6,1,36,.34) 78%,rgba(6,1,36,.5) 100%)}
}

/* Розкладка розвороту: текст обгортає цифру з двох боків. */
.band__overlay{position:absolute;inset:0;z-index:2;display:grid;align-content:center;
  width:var(--wrap);margin-inline:auto;color:#fff;justify-items:center;text-align:center;
  row-gap:clamp(1rem,2.5vw,1.75rem)}
.band__prefix,.band__label{margin:0;max-width:26ch;
  font-size:clamp(1rem,.9rem + .5vw,1.3125rem);font-weight:400;line-height:1.4;
  text-shadow:0 2px 18px rgba(6,2,32,.75)}
/* Контур цифри намальовано впритул до країв svg — знизу лишається 2.5%
   висоти. Тому просвіт до підпису задає тільки цей gap, і .1rem мало:
   ніжка «1» майже торкалася «W». Тримаємо приблизно третину кегля підпису. */
.band__fig{--num:clamp(6.5rem,3rem + 17vw,13rem);
  margin:0;display:grid;justify-items:center;gap:clamp(.8rem,1.6vw,1.4rem)}

/* Цифра як контур шрифту, а не текст: лише вектор можна вести лінією.
   Текстовий дублікат лишається для читалок і друку. */
.band__num{position:relative;display:block;width:min(88vw,calc(var(--num) * 2.28))}
.band__draw{display:block;width:100%;height:auto;color:#fff;
  stroke-linecap:round;stroke-linejoin:round;vector-effect:non-scaling-stroke;
  stroke-width:clamp(2.4px,.42vw,4px);
  /* дві тіні: щільна відриває лінію від облич на фото, широка дає сяйво */
  filter:drop-shadow(0 0 5px rgba(6,2,32,.7)) drop-shadow(0 0 30px rgba(10,3,54,.55))}
.band__draw path{stroke-dasharray:1;stroke-dashoffset:1}
/* Веде по одному знаку: «1» перша, нулі наздоганяють. */
.is-in .band__draw path{animation:draw 1.15s cubic-bezier(.62,.04,.3,1) forwards;
  animation-delay:calc(.2s + var(--i,0) * .16s)}
@keyframes draw{to{stroke-dashoffset:0}}
/* Іскри лягають поверх цифри й мають запас, щоб розлітатися за її межі. */
/* Полотно з запасом, а по краю — розтушовка: інакше іскри обрізало б рівною
   рамкою (сама смуга теж ховає все, що з неї виходить). */
.band__spark{position:absolute;inset:-115% -48%;width:196%;height:330%;
  pointer-events:none;opacity:0;transition:opacity .7s linear;mix-blend-mode:screen;
  -webkit-mask-image:radial-gradient(closest-side at 50% 50%,#000 52%,transparent 96%);
  mask-image:radial-gradient(closest-side at 50% 50%,#000 52%,transparent 96%)}
.band__spark.is-lit{opacity:1;transition:none}
.band__sr{position:absolute;width:1px;height:1px;overflow:hidden;
  clip-path:inset(50%);white-space:nowrap}
.band__value{font-family:"Bodoni Moda",serif;font-optical-sizing:auto;
  font-weight:500;font-size:clamp(5rem,2rem + 14vw,13rem);line-height:.82;
  letter-spacing:.01em;font-variant-numeric:tabular-nums;
  color:transparent;-webkit-text-stroke:3px #fff;
  filter:drop-shadow(0 0 30px rgba(10,3,54,.55))}
/* Підпис під цифрою набирається по знаку, як на друкарській машинці:
   різкий перехід 0→1, без плавності — інакше це вже не «набір». */
.band__unit i{font-style:normal;opacity:0}
.is-in .band__unit i{animation:type .01s linear forwards;
  animation-delay:calc(1.65s + var(--i) * 45ms)}
@keyframes type{to{opacity:1}}
.band__unit{font-family:"Bodoni Moda",serif;font-optical-sizing:auto;font-weight:600;
  font-size:clamp(1.25rem,.6rem + 3.4vw,3.25rem);line-height:1;letter-spacing:.06em;
  text-transform:uppercase;color:#fff;text-shadow:0 2px 20px rgba(6,2,32,.6)}
@media (min-width:56rem){
  .band__overlay{grid-template-columns:minmax(0,1fr) auto minmax(0,1fr);
    align-items:center;column-gap:clamp(1.5rem,4vw,3.5rem);text-align:left;
    justify-items:stretch}
  .band__prefix{justify-self:start;max-width:18ch}
  .band__label{justify-self:end;max-width:20ch}
  .band__value{-webkit-text-stroke-width:4px}
}

/* ── два вікна на спільному кістяку ───────────────────────────────────── */
/* Вікно листа й вікно перед формою волонтера — одна конструкція: аркуш із
   маркою та графами вгорі, надрядком і заголовком Bodoni, дією внизу.
   Відрізняється тільки середина: там форма, тут розклад. Спільне живе в
   `.sheet`, власне — в `.mail` і `.gate`.
   `mode-light` на самому вікні обов'язковий: воно лежить поза секціями,
   а від класу залежать змінні кольору, зокрема білий напис на кнопці. */
/* Заокруглення те саме, що в карток на сторінці (`.path`, `.press__panel`):
   вікно — така сама поверхня, і 6px поруч із 20px читалися як чужа деталь. */
/* `position` тут НЕ чіпаємо. Браузер дає модальному вікну `position:fixed`
   своїм стилем, а будь-яке авторське правило його перебиває незалежно від
   ваги — і вікно випадає в потік сторінки. Саме це й сталося, коли сюди
   дописали `position:relative` заради хрестика: вікно опинялося там, де
   лежить у розмітці (наприкінці сторінки), браузер підкручував до нього
   фокус, і клік по пошті в підвалі жбурляв людину на початок. Хрестику
   опора й так є: `fixed` — це вже containing block. */
.sheet{--cell:20px;--w:34rem;--r:1.25rem;
  width:min(var(--w),calc(100vw - 1.5rem));max-width:none;margin:auto;padding:0;
  /* Висоту треба задати самому вікну, а не лише його середині. У браузера
     для <dialog> є власна межа висоти, і вона нижча за нашу: поки вікно
     різало все зайве (`overflow:hidden`), різниці не було видно, а щойно
     хрестик поїхав назовні й різання зникло — підвал із кнопкою виліз за
     нижню кромку, у темряву. */
  max-height:calc(100dvh - 2rem);
  border:0;border-radius:var(--r);overflow:hidden;background:var(--paper);
  box-shadow:0 2rem 5rem color-mix(in srgb,var(--night-900) 45%,transparent)}
/* Край, за яким ще є текст. Без нього вміст просто обривався по нижній
   кромці — і обрив на півкнопці читався як дефект верстки, а не як «тут є
   продовження». З'являється лише тоді, коли прокрутка справді лишилася:
   клас ставить скрипт, бо CSS не вміє питати, чи докрутили до кінця. */
.sheet::after{content:"";position:absolute;inset:auto 0 0;height:2.75rem;
  pointer-events:none;opacity:0;transition:opacity .3s var(--ease);
  border-radius:0 0 var(--r) var(--r);
  background:linear-gradient(to top,var(--paper),
    color-mix(in srgb,var(--paper) 0%,transparent))}
.sheet.has-more::after{opacity:1}
.sheet::backdrop{background:color-mix(in srgb,var(--night-900) 74%,transparent);backdrop-filter:blur(4px)}
.sheet[open]{display:block}
.sheet__in{display:grid;gap:calc(var(--cell) * 2);
  padding:clamp(1.5rem,4vw,2.5rem);border-radius:var(--r);
  max-height:calc(100dvh - 2rem);overflow-y:auto;overscroll-behavior:contain;
  /* Системна смуга прокрутки — сіра колонка з кнопками — сідала впритул до
     заокругленого краю й виглядала як чужа деталь у вікні. Тут вона тонка
     й без доріжки: видно, що є куди крутити, і не видно нічого зайвого. */
  scrollbar-width:thin;
  scrollbar-color:color-mix(in srgb,var(--ink) 22%,transparent) transparent}
.sheet__in::-webkit-scrollbar{width:6px}
.sheet__in::-webkit-scrollbar-track{background:transparent}
.sheet__in::-webkit-scrollbar-thumb{border-radius:999px;
  background:color-mix(in srgb,var(--ink) 20%,transparent)}
.sheet__in::-webkit-scrollbar-thumb:hover{
  background:color-mix(in srgb,var(--ink) 34%,transparent)}
/* Хрестик рахується від самого вікна, а не від його середини, хоч і лежить
   у розмітці всередині. Різниця вирішальна: середина — це смуга прокрутки,
   і разом із нею хрестик виїжджав угору. Людина, яка прокрутила довге
   вікно, лишалася без жодної видимої дороги назад — Esc і клік по тлу
   працювали, але про них треба здогадатися. Тепер він на місці завжди. */
.sheet__x{position:absolute;top:clamp(.85rem,2.4vw,1.25rem);right:clamp(.85rem,2.4vw,1.25rem);
  z-index:2;width:2rem;height:2rem;border-color:var(--hair);color:var(--muted);
  background:color-mix(in srgb,var(--paper) 82%,transparent);
  backdrop-filter:blur(6px)}
.sheet__x:hover{background:color-mix(in srgb,var(--ink) 6%,transparent);color:var(--ink)}
.sheet__x .ico{width:.95rem;height:.95rem}

/* шапка: марка ліворуч, графи праворуч */
.sheet__mast{display:flex;align-items:flex-start;justify-content:space-between;
  gap:.9rem clamp(1.25rem,3vw,2.5rem);flex-wrap:wrap;padding-right:2.5rem}
/* Поле праворуч тримається під хрестик. Коли він виходить за вікно, поле
   стає порожнім місцем, і шапка обривається, не дійшовши до краю. */
@media (min-width:58rem){
  .sheet__mast{padding-right:0}
}
.sheet__brand{margin:0;display:flex;align-items:baseline;gap:.4rem;
  font-weight:600;font-size:.875rem;line-height:var(--cell);letter-spacing:-.01em}
.sheet__brand b{font-size:.6875rem;font-weight:600;color:var(--gold);
  font-variant-numeric:tabular-nums}
/* Колонок стільки, скільки справжніх граф у контенті — жодної порожньої. */
.sheet__meta{margin:0;display:grid;gap:.15rem clamp(1.1rem,2.5vw,2rem);
  grid-auto-flow:column;grid-auto-columns:auto}
.sheet__row{display:contents}
.sheet__row dt{grid-row:1;font-size:.6875rem;font-weight:600;letter-spacing:.1em;
  text-transform:uppercase;color:var(--muted);line-height:var(--cell)}
.sheet__row dd{grid-row:2;margin:0;font-size:.875rem;font-weight:500;
  line-height:var(--cell);white-space:nowrap}

/* заголовок */
.sheet__head .eyebrow{margin:0 0 .25rem}
.sheet__title{margin:0;font-family:"Bodoni Moda",serif;font-weight:700;
  font-size:clamp(1.375rem,1.1rem + 1vw,1.875rem);line-height:calc(var(--cell) * 2);
  letter-spacing:-.015em;color:var(--violet)}
.sheet__lead{margin:calc(var(--cell) * -1 + .25rem) 0 0;max-width:46ch;
  font-size:.875rem;line-height:var(--cell);color:var(--muted)}

/* підвал: марка або контакт ліворуч, дія праворуч */
.sheet__foot{display:flex;flex-wrap:wrap;gap:1rem 1.5rem;align-items:center;
  justify-content:space-between}
.sheet__logo{width:clamp(3.75rem,9vw,5rem);height:auto}

/* Поки телефон і пошта стоять поруч, шапка займає один рядок. Щойно
   перестають уміщатися — марка лишається зверху сама, а графи падають під
   неї, і рядок обривається на півдорозі. Тому нижче 38rem вони заздалегідь
   стають стовпчиком «підпис — значення»: два короткі рядки замість
   розірваного одного. Межа саме тут, бо на вужчому вікні марка й обидві
   графи вже не вміщаються в один рядок навіть упритул. */
@media (max-width:38rem){
  .sheet__meta{grid-auto-flow:row;gap:0}
  .sheet__row{display:grid;grid-template-columns:5.5rem minmax(0,1fr);
    align-items:baseline;gap:.75rem}
  .sheet__row dt,.sheet__row dd{grid-row:auto}
}

/* На широкому екрані хрестик виходить за вікно — у темряву праворуч від
   нього. Так роблять переглядачі зображень, і так одразу видно: це не
   частина аркуша, а дія над ним. Заразом він перестає накривати текст.

   Умова одна — щоб обабіч було місце. Найширше вікно має 46rem, тож від
   58rem по боках лишається щонайменше по 6rem: вистачає на кнопку з
   повітрям. Нижче він повертається всередину.

   `overflow:hidden` при цьому знімається з самого вікна (інакше кнопку
   обрізало б), а заокруглення переїжджає на середину — вона ж і прокрутка,
   тож ріже те саме, що різало вікно. */
@media (min-width:58rem){
  .sheet{overflow:visible;--r:1.5rem}
  .sheet__x{top:0;right:-3.25rem;width:2.25rem;height:2.25rem;
    color:#fff;background:color-mix(in srgb,#fff 14%,transparent);
    border-color:color-mix(in srgb,#fff 38%,transparent);backdrop-filter:none}
  .sheet__x:hover{background:#fff;border-color:#fff;color:var(--night-900)}
  .sheet__x .ico{width:1.05rem;height:1.05rem}
}

/* Другий вихід — у тому ж рядку, що й головна дія. Окремою пігулкою під
   лінійкою він читався як ще один розділ вікна; тут видно з першого
   погляду, що це пара «вийти / піти далі», і що друге важливіше.

   Тому він набором, а не кнопкою: рамка поруч зі суцільною кнопкою
   змагалася б із нею за увагу. */
.sheet__act{display:flex;align-items:center;gap:clamp(.75rem,2vw,1.25rem);
  flex-wrap:wrap;margin-left:auto}
.sheet__back{display:inline-flex;align-items:center;gap:.4rem;
  padding:.35rem 0;border:0;background:none;cursor:pointer;font:inherit;
  font-size:.875rem;font-weight:500;color:var(--muted);
  transition:color .25s ease}
.sheet__back span{text-decoration:underline;text-underline-offset:.25em;
  text-decoration-thickness:1px;
  text-decoration-color:color-mix(in srgb,currentColor 35%,transparent)}
.sheet__back:hover{color:var(--ink)}
.sheet__back:hover span{text-decoration-color:currentColor}
.sheet__back:focus-visible{outline:2px solid var(--accent);outline-offset:3px;
  border-radius:.25rem}
.sheet__back .ico{width:.8125rem;height:.8125rem;opacity:.7}

/* Вікно про залу закінчується посиланнями, а не дією — там вихід лишається
   сам і мусить сам виглядати дією. Тому окремий рядок на всю ширину.

   Волосяної лінії над ним немає, хоч спершу була. Кнопка має власну рамку,
   і рамка вже каже «це окремо»; лінія над нею казала те саме вдруге, а
   нижче йшла ще й закруглена кромка самого вікна — три межі поспіль на
   одну думку. Лишили ту, що працює: без рамки кнопка перестала б бути
   кнопкою, а без лінії нічого не втрачається — проміжок сітки відділяє її
   не гірше. */
.sheet__tail{margin-top:calc(var(--cell) * -.25)}
.sheet__back--wide{display:flex;width:100%;justify-content:center;gap:.55rem;
  min-height:2.75rem;padding:.6rem 1rem;border-radius:.875rem;
  border:1px solid var(--hair);font-size:.9375rem;font-weight:600;
  transition:color .25s ease,border-color .25s ease,background-color .25s ease}
.sheet__back--wide span{text-decoration:none}
.sheet__back--wide:hover{color:var(--ink);
  border-color:color-mix(in srgb,var(--ink) 30%,transparent);
  background:color-mix(in srgb,var(--ink) 4%,transparent)}
.sheet__back--wide:focus-visible{outline-offset:2px}
.sheet__back--wide .ico{width:.875rem;height:.875rem}

/* ── вікно листа ──────────────────────────────────────────────────────── */
/* Сайт статичний і нічого не відправляє: форма лише складає готовий лист
   і віддає його поштовій програмі. Тому про це сказано просто у вступі. */
/* Ширше за базові 34rem: у підвалі поруч мусять стати адреса з кнопкою
   «копіювати» і сама дія — на вужчому вони переносяться в два рядки. */
.mail{--w:44rem}
/* Вступ тут не вступ, а технічна примітка: вікно нічого не відправляє саме.
   Знати це варто, але не перед тим, що робити далі. Тому дрібним підписом —
   на тому ж рівні, що й дрібний шрифт у підвалі. У вікні волонтера й у
   вікні про залу вступ лишається вступом: там він веде далі. */
.mail .sheet__lead{font-size:.75rem;line-height:1.5;max-width:56ch}
.mail__form{display:grid;gap:clamp(1rem,2.5vw,1.35rem)}
/* Теми — не ярлики, а розвилка. Пігулки з самими назвами вимагали
   здогадуватися, куди належить твій випадок: «Współpraca» це спонсор чи
   ośrodek? Тепер кожна тема — картка зі знаком, назвою і рядком пояснення,
   і вибір робиться з першого погляду, без гадання. */
.mail__topics{margin:0;padding:0;border:0;display:grid;gap:.75rem;
  grid-template-columns:repeat(auto-fit,minmax(16rem,1fr))}
/* Підпис у сітці — теж комірка, і `float` її не рятує: він у сітці не діє.
   Без явного розтягу підпис займав перше місце, і чотири картки ставали
   2+1+1 замість 2+2. */
/* Підпис групи, а не поля, і повітря під ним рахується тільки з його
   власного поля: `legend` у fieldset малюється в окремому гнізді, а не як
   комірка сітки, тож проміжок сітки над першим рядком не діє — перевірено,
   `display` у нього лишається block попри `display:grid` на самому fieldset.
   Тому 1rem, а не «сітка сама розставить». */
.mail__topics legend{float:none;width:auto;padding:0;margin:0 0 1rem;
  font-size:var(--t-eyebrow);font-weight:600;letter-spacing:.14em;
  text-transform:uppercase;color:var(--muted)}
.mail__topic input{position:absolute;opacity:0;width:0;height:0}
.mail__topic > span{display:grid;grid-template-columns:auto minmax(0,1fr);
  align-items:start;column-gap:.9rem;row-gap:.3rem;height:100%;
  padding:1.1rem 1.15rem;border-radius:.875rem;cursor:pointer;
  border:1px solid var(--hair);background:none;
  transition:border-color .25s ease,background-color .25s ease}
.mail__topic__ico{grid-row:span 2;display:grid;place-items:center;
  width:2.25rem;height:2.25rem;border-radius:50%;color:var(--violet);
  border:1px solid color-mix(in srgb,var(--violet) 28%,transparent);
  background:color-mix(in srgb,var(--violet) 7%,transparent);
  transition:color .25s ease,background-color .25s ease,border-color .25s ease}
.mail__topic__ico .ico{width:1.125rem;height:1.125rem}
.mail__topic b{font-size:.9375rem;font-weight:600;line-height:1.35;color:var(--ink)}
.mail__topic i{font-style:normal;font-size:.8125rem;line-height:1.5;color:var(--muted);
  max-width:30ch}
/* Тема без пояснення (рядком у контенті) не має лишати порожній другий
   рядок — знак тоді тримає лише один. */
.mail__topic > span:not(:has(i)) .mail__topic__ico{grid-row:auto}
.mail__topic:hover > span{border-color:color-mix(in srgb,var(--violet) 40%,transparent)}
.mail__topic input:checked + span{border-color:var(--violet);
  background:color-mix(in srgb,var(--violet) 6%,transparent)}
.mail__topic input:checked + span .mail__topic__ico{color:#fff;background:var(--violet);
  border-color:var(--violet)}
.mail__topic input:focus-visible + span{outline:2px solid var(--violet);outline-offset:2px}
/* Поля.

   Була волосяна лінійка знизу — гарно, але нечитабельно: межа мала контраст
   близько 2:1 до паперу при потрібних 3:1 (WCAG 1.4.11), самої коробки не
   було видно взагалі, і куди писати — доводилося вгадувати. Для сторінки,
   якою користуються люди з вадами зору, це не оздоба, а бар'єр.

   Тепер поле виглядає як поле: рамка по колу з контрастом 3.1:1, власне
   тло, відчутне поле всередині. Підпис — звичайним набором замість капітелі
   з розрядкою: великі літери читаються повільніше, а це перше, що людина
   має зрозуміти. */
.mail__f{display:grid;gap:.4rem}
.mail__f > span{font-size:.875rem;font-weight:600;letter-spacing:0;
  text-transform:none;color:var(--ink)}
.mail__f :is(input,textarea){font:inherit;font-size:1rem;color:var(--ink);width:100%;
  padding:.6rem .75rem;background:var(--paper);
  border:1px solid color-mix(in srgb,var(--ink) 48%,transparent);border-radius:.5rem;
  transition:border-color .2s ease,box-shadow .2s ease}
.mail__f textarea{min-height:6.5rem;line-height:1.5;resize:vertical}
.mail__f :is(input,textarea):hover{border-color:color-mix(in srgb,var(--ink) 66%,transparent)}
/* Фокус видно й кольором, і кільцем: сама зміна кольору рамки для того,
   хто погано розрізняє відтінки, не є ознакою взагалі. */
.mail__f :is(input,textarea):focus-visible{outline:none;border-color:var(--violet);
  box-shadow:0 0 0 3px color-mix(in srgb,var(--violet) 24%,transparent)}
.mail__f :is(input,textarea)::placeholder{color:color-mix(in srgb,var(--muted) 60%,transparent)}
/* Адреса переїхала в шапку, до телефону: це контакт, а не дія, і поруч із
   телефоном читається парою. У підвалі вона стояла впритул до головної
   кнопки й тягла на себе увагу, а «копіювати» при натисканні ще й зсувало
   весь рядок. */
.mail__mail{display:flex;align-items:center;gap:.5rem;min-width:0}
.mail__mail a{color:var(--ink);text-decoration:underline;text-underline-offset:.25em;
  text-decoration-thickness:1px;transition:color .25s ease}
.mail__mail a:hover{color:var(--violet)}
/* Кнопка копіювання — самим знаком. Пігулка з написом «Kopiuj» була ширшою
   за саму графу й читалася як приліплена збоку деталь; ще й мінялася на
   довше «Skopiowano» і зсувала рядок. Знак не міняє розміру ніколи: обидва
   лежать один поверх одного, і після натискання аркуші просто стають
   галочкою. */
.mail__copy{display:grid;place-items:center;width:1.75rem;height:1.75rem;
  flex:none;padding:0;border:0;border-radius:.5rem;cursor:pointer;
  color:var(--muted);background:none;
  transition:color .25s ease,background-color .25s ease}
.mail__copy .ico{grid-area:1 / 1;width:.9375rem;height:.9375rem;
  transition:opacity .2s ease}
.mail__copy__ok{opacity:0}
.mail__copy:hover{color:var(--ink);background:color-mix(in srgb,var(--ink) 6%,transparent)}
.mail__copy:focus-visible{outline:2px solid var(--accent);outline-offset:1px}
.mail__copy.is-done{color:var(--violet)}
.mail__copy.is-done .ico:not(.mail__copy__ok){opacity:0}
.mail__copy.is-done .mail__copy__ok{opacity:1}
/* У підвалі лишилася сама дія — тож вона й тримає правий край. */
.mail__foot{justify-content:flex-end}

/* ── вікно перед формою волонтера ─────────────────────────────────────── */
/* Сходинка між кнопкою і зовнішнім сервісом реєстрації: спершу людина бачить,
   що її чекає, і аж тоді йде заповнювати. Ритм бланковий — усе кратне 20px. */
.gate{--w:46rem}
.gate__days{list-style:none;margin:0;padding:0;display:grid;gap:var(--cell)}
/* Кружечків під знаками немає — обвідка й заливка додавали чорнила рівно там,
   де його треба найменше. Лишився сам знак і волосяна лінія між ними. */
.gate__day{position:relative;display:grid;
  grid-template-columns:1.25rem minmax(0,1fr);column-gap:.9rem;align-items:start}
.gate__mark{display:grid;place-items:center;height:var(--cell);color:var(--violet)}
.gate__mark .ico{width:.95rem;height:.95rem}
.gate__day:not(:last-child)::after{content:"";position:absolute;
  top:calc(var(--cell) + 4px);left:.625rem;translate:-50% 0;width:1px;
  height:calc(100% - 8px);background:var(--hair)}
.gate__body{min-width:0}
.gate__when{display:flex;align-items:baseline;flex-wrap:wrap;gap:.5rem;margin:0;
  line-height:var(--cell)}
.gate__when b{font-size:.6875rem;font-weight:600;letter-spacing:.12em;
  text-transform:uppercase;color:var(--ink)}
.gate__when span{font-size:.8125rem;color:var(--muted);font-variant-numeric:tabular-nums}
.gate__day h3{margin:0;font-size:1.0625rem;font-weight:600;line-height:var(--cell)}
.gate__place{display:flex;align-items:center;gap:.4rem;margin:0;
  font-size:.875rem;line-height:var(--cell);color:var(--muted)}
.gate__place .ico{width:.85rem;height:.85rem;flex:none;opacity:.5}
/* Знаків у рядках розкладу немає: там їхню роботу вже виконує час. */
.gate__hours{list-style:none;margin:var(--cell) 0 0;padding:0;display:grid}
.gate__hours li{display:grid;grid-template-columns:7rem minmax(0,1fr);
  gap:1rem;align-items:baseline;font-size:.875rem;line-height:var(--cell)}
/* Година — опора рядка, по ній читають розклад. Тому вона акцентна
   й трохи щільніша, а не сіра нарівні з описом. */
.gate__hours i{font-style:normal;color:var(--violet);font-weight:600;
  font-variant-numeric:tabular-nums;letter-spacing:.01em}
@media (max-width:30rem){
  .gate__hours li{grid-template-columns:6rem minmax(0,1fr);gap:.75rem}
}
/* Що взяти з собою. Це не розклад і не згода, а памʼятка — і виглядає вона
   інакше: галочка в суцільному колі замість значка у полі, і весь блок
   лежить на власному тлі. Довідка про несудимість і святковий одяг — саме
   ті речі, про які згадують за день до балу, коли вже пізно. */
.gate__bring{padding:var(--cell);border-radius:.875rem;
  border:1px solid color-mix(in srgb,var(--violet) 20%,transparent);
  background:color-mix(in srgb,var(--violet) 5%,transparent)}
.gate__bring__h{margin:0 0 var(--cell);font-size:var(--t-eyebrow);font-weight:600;
  letter-spacing:.14em;text-transform:uppercase;color:var(--violet)}
.gate__bring ul{list-style:none;margin:0;padding:0;display:grid;gap:var(--cell)}
.gate__bring li{display:grid;grid-template-columns:auto minmax(0,1fr);
  align-items:start;column-gap:.85rem}
/* Суцільне коло, а не контур: це єдине місце у вікні, де знак має тиснути. */
.gate__tick{display:grid;place-items:center;width:1.5rem;height:1.5rem;border-radius:50%;
  background:var(--violet);color:#fff;margin-top:.1rem}
.gate__tick .ico{width:.8125rem;height:.8125rem;stroke-width:2.4}
.gate__take{display:grid;gap:.15rem;min-width:0}
.gate__take b{font-size:.9375rem;font-weight:600;line-height:var(--cell);color:var(--ink)}
.gate__take i{font-style:normal;font-size:.875rem;line-height:1.45;color:var(--muted)}

/* Реєстрація ще не відкрита. Стоїть над заголовком, бо це перше, що людина
   мусить дізнатися: кнопка внизу веде не на форму, а в лист. Тло суцільне
   фіолетове — щоб не сплутати з памʼяткою, яка теж лежить у рамці. */
.gate__soon{padding:var(--cell);border-radius:.875rem;background:var(--violet);color:#fff}
.gate__soon__h{margin:0 0 .4rem;font-size:var(--t-eyebrow);font-weight:600;
  letter-spacing:.14em;text-transform:uppercase;color:color-mix(in srgb,#fff 78%,transparent)}
.gate__soon h3{margin:0;font-size:1.0625rem;font-weight:600;line-height:1.35;text-wrap:balance}
.gate__soon p:last-child{margin:.5rem 0 0;font-size:.9375rem;line-height:1.5;
  color:color-mix(in srgb,#fff 88%,transparent)}
.gate__soon strong{color:#fff;font-weight:600;white-space:nowrap}

/* Галочок поки немає — блок з'явиться сам, щойно їх додадуть у контент. */
.gate__checks{display:grid;gap:var(--cell);padding-top:var(--cell);
  border-top:1px solid var(--hair)}
.gate__check{display:grid;grid-template-columns:auto minmax(0,1fr);gap:.6rem;
  align-items:start;font-size:.9375rem;line-height:var(--cell);cursor:pointer}
.gate__check input{margin:.2rem 0 0;width:1.05rem;height:1.05rem;flex:none;
  accent-color:var(--violet);cursor:pointer}
.gate__warn{margin:0;font-size:.875rem;line-height:var(--cell);color:#b3261e}
.gate__warn[hidden]{display:none}
/* Поки не всі галочки виставлені, кнопка лишається кнопкою — не «мертвою»:
   вимкнений елемент не пояснює, чому він не працює, і його не бачить
   екранна читалка. Натомість клік підсвічує те, чого бракує. */
.sheet__foot .btn[aria-disabled="true"]{opacity:.55}


/* ── вікно про залу ───────────────────────────────────────────────────── */
/* Половина гостей приїде на візку або з тим, хто везе. Для них «де це» —
   не адреса, а двері, ліфт і місце, де можна висадити людину під самим
   входом. Каркас той самий, що в розкладі волонтерів: знак у полі,
   текст поруч; лише вертикальної лінії між пунктами немає — вона читалася б
   як послідовність, а тут три незалежні теми. Їх розділяє волосяна лінія.
   Усе, що написано в цьому вікні, взято зі сторінок самого об'єкта. */
.venue{--w:42rem}
.venue .sheet__row dd{white-space:normal}
.mail .sheet__row dd:has(.mail__mail){white-space:normal}
/* Кнопка копіювання вища за рядок тексту (28px проти 20), і графа з поштою
   через неї ставала вищою за графу з телефоном — значення розходилися по
   вертикалі на вісім пікселів. Тому обидві графи в цьому вікні мають спільну
   висоту рядка, а текст у них вирівняний по центру: різні за вмістом, рівні
   за мірою. */
.mail .sheet__row dd{display:flex;align-items:center;min-height:1.75rem}
.venue__groups{gap:var(--cell)}
.venue__groups .gate__day::after{display:none}
.venue__groups .gate__day + .gate__day{padding-top:var(--cell);
  border-top:1px solid var(--hair)}
.venue__groups h3{margin:0 0 .3rem;font-size:1.0625rem;font-weight:600;
  line-height:var(--cell)}
.venue__list{list-style:none;margin:0;padding:0;display:grid;gap:.4rem}
/* Риска замість крапки: крапка при такому розмірі читається як друкарський
   бруд, а коротка лінія тримає лівий край переліку. */
.venue__list li{position:relative;padding-left:1rem;
  font-size:.9375rem;line-height:var(--cell);color:var(--muted)}
.venue__list li::before{content:"";position:absolute;left:0;
  top:calc(var(--cell) / 2);width:6px;height:1px;background:currentColor;opacity:.45}
.venue__foot{align-items:flex-start}
.venue__links{display:grid;gap:.45rem}
.venue__links a{display:inline-flex;align-items:center;gap:.5rem;min-height:1.5rem;
  font-size:.875rem;font-weight:500;color:var(--ink);text-decoration:none}
.venue__links a span{text-decoration:underline;text-underline-offset:.25em;
  text-decoration-thickness:1px;
  text-decoration-color:color-mix(in srgb,var(--ink) 25%,transparent)}
.venue__links a:hover{color:var(--violet)}
.venue__links a:hover span{text-decoration-color:currentColor}
.venue__links .ico{width:1rem;height:1rem;flex:none;color:var(--violet)}
.venue__note{margin:0;max-width:32ch;font-size:.75rem;line-height:1.5;color:var(--muted)}
@media (max-width:34rem){
  .venue__note{max-width:none}
}

/* ── вікна, коли екран нижчий ─────────────────────────────────────────────
   Усе, що стискає вікна, зібране тут — після описів самих вікон. Медіазапит
   не додає ваги правилу: будь-яке звичайне правило, записане нижче, його
   перебиває. Перша спроба стояла вище за секцію `.mail`, і половина рядків
   просто не діяла — при тому, що самі медіазапити виконувались.

   Сходинки йдуть від найм'якшої до найсуворішої (64 → 52 → 48 → 44rem), і
   порядок тут теж не декоративний: на низькому екрані вмикається кілька
   запитів одразу, і виграє записаний нижче. Спершу 44rem стояла вище за
   48rem — тобто найсуворіша сходинка перебивалася м'якшою.

   Перша спроба стискала `--cell` — одну змінну, з якої рахується все.
   Вийшла халепа: `--cell` задає не лише проміжки, а й інтерліньяж
   (`line-height:var(--cell)` у заголовках, графах і рядках розкладу). При
   15px рядки заголовків злиплися. Тому скрізь нижче міняється тільки те,
   де йдеться про **відстань**, а набір лишається недоторканим.        */

/* 1024px і нижче — звичайний ноутбук. Вікно листа в повний зріст займає 984
   пікселі, і на екрані 900 воно вже не вміщалося. Тут зрізані самі
   відступи. */
@media (max-height:64rem){
  .sheet__in{gap:1.6rem;padding:clamp(1.35rem,3.6vw,1.9rem)}
  .mail__topics{gap:.6rem}
  .mail__topic > span{padding:.85rem .95rem}
  .mail__topic__ico{width:2rem;height:2rem}
  .mail__form{gap:1rem}
  /* `rows="4"` задає полю власну висоту, і `min-height` її не зменшує —
     тут висоту треба ставити прямо. */
  .mail__f textarea{min-height:0;height:5.5rem}
  .gate__days{gap:1rem}
  .venue__groups{gap:1rem}
}

/* 832px — низький ноутбук або телефон навпоперек. */
@media (max-height:52rem){
  .sheet__in{gap:1.4rem;padding:clamp(1.15rem,3.4vw,1.75rem)}
  /* вікно волонтера */
  .gate__days{gap:.85rem}
  .gate__hours{margin-top:.55rem}
  .gate__bring{padding:.9rem 1rem}
  .gate__bring__h{margin-bottom:.65rem}
  .gate__bring ul{gap:.7rem}
  /* знак у підвалі вікна декоративний — на низькому екрані він коштує
     рядок розкладу */
  .gate .sheet__logo{display:none}
  /* вікно про залу */
  .venue__groups{gap:.85rem}
  .venue__groups .gate__day + .gate__day{padding-top:.85rem}
  .venue__list{gap:.25rem}
  /* вікно листа: чотири картки тем — найбільший з'їдач висоти */
  .mail__topics{gap:.5rem}
  .mail__topics legend{margin-bottom:.6rem}
  .mail__topic > span{padding:.7rem .85rem;column-gap:.7rem;row-gap:.1rem}
  .mail__topic__ico{width:1.85rem;height:1.85rem}
  .mail__topic__ico .ico{width:1rem;height:1rem}
  .mail__form{gap:.8rem}
  .mail__f textarea{height:4.5rem}
}

/* 768px. */
@media (max-height:48rem){
  .mail .sheet__in{gap:.9rem;padding:.9rem}
  .mail .sheet__title{font-size:1.25rem}
  .mail .sheet__mast{gap:.45rem 1.25rem}
  .mail__topics legend{margin-bottom:.45rem}
  .mail__f textarea{height:4.25rem}
}

/* 704px і нижче: пояснення під назвами тем ховаються. Назви самі по собі
   однозначні («Zgłoszenie gościa honorowego», «Partnerstwo i sponsoring»,
   «Wolontariat», «Inna sprawa»), а чотири пояснення коштують третину
   екрана. */
@media (max-height:44rem){
  .mail__topic i{display:none}
  .mail__topic > span{grid-template-columns:auto minmax(0,1fr);align-items:center}
  .mail__topic__ico{grid-row:auto}
  .mail .sheet__lead{display:none}
  .mail__f textarea{height:3.5rem}
}

/* ── вікна на телефоні ────────────────────────────────────────────────────
   Ширина, а не висота: тут ідеться не про те, що екран низький, а про те,
   що він вузький і що керують ним пальцем.                              */

/* Теми — перелік, а не картки.

   Чотири картки з рамками, полями й поясненнями займали майже весь екран:
   390 пікселів із 780. Людина гортала список замість того, щоб його бачити.

   На телефоні вони стають рядками з волосяною лінією між ними — звичайним
   переліком, як у системних налаштуваннях. Рамка й поля картки на такій
   ширині все одно нічого не додавали: рядок і так на всю ширину вікна.

   Пояснення лишається тільки під вибраним рядком. Ховати його скрізь не
   можна — саме воно й каже, куди належить твій випадок; але потрібне воно
   там, де вибір уже зроблено. Решта показують самі назви.

   Вибраний рядок при цьому лишається карткою: заливка, заокруглення й
   власне повітря. Так видно, що це не просто підсвічений пункт списку. */
@media (max-width:38rem){
  .mail__topics{gap:0}
  /* 44px — нижня межа зручної цілі для пальця; рядок сам виходить на 43,
     тож доводимо його явно, а не підбираємо відступами. */
  .mail__topic > span{border:0;border-radius:.625rem;min-height:2.75rem;
    padding:.55rem .6rem;column-gap:.7rem;row-gap:.2rem;align-items:center}
  .mail__topic + .mail__topic > span{box-shadow:0 -1px 0 var(--hair)}
  .mail__topic__ico{grid-row:auto;width:1.6rem;height:1.6rem}
  .mail__topic__ico .ico{width:.9375rem;height:.9375rem}
  .mail__topic b{font-size:.875rem}
  .mail__topic i{display:none;font-size:.8125rem;line-height:1.4}
  /* вибраний — знову картка, з повітрям і поясненням */
  .mail__topic input:checked + span{align-items:start;padding:.75rem .8rem;
    box-shadow:none;margin:.3rem 0}
  .mail__topic input:checked + span i{display:block}
  .mail__topic input:checked + span .mail__topic__ico{grid-row:span 2}
  .mail__topic:has(input:checked) + .mail__topic > span{box-shadow:none}

  /* Надрядок «Kontakt» дублює заголовок «Napisz do nas», а примітка про те,
     що лист відкриється в поштовій програмі, стоїть за крок до кнопки
     «Otwórz w poczcie» — вона те саме й каже. На широкому екрані обидва
     лишаються: там місце є, і вони дають ритм. */
  .mail .sheet__in{gap:1.1rem;padding:1.1rem}
  .mail .sheet__head .eyebrow{display:none}
  .mail .sheet__lead{display:none}
  .mail__form{gap:.7rem}
  .mail__f{gap:.3rem}
  .mail__f > span{font-size:.8125rem}
  .mail__f :is(input,textarea){padding:.5rem .65rem}
  .mail__f textarea{min-height:0;height:5rem}
  .mail .sheet__mast{gap:.6rem 1.25rem}

  /* Головна кнопка. Загальна міра розрахована на секції, де кнопка стоїть
     сама посеред екрана; у підвалі вікна вона ділить рядок зі знаком і
     виходом, і в повний зріст з'їдала його цілком. */
  .sheet__foot .btn{min-height:3rem;padding:.75rem 1.25rem;font-size:.9375rem;gap:.45rem}
  .sheet__foot .btn__ico{width:1rem;height:1rem}
  .sheet__act{gap:.85rem}
}

/* Вузький і низький разом — поширений андроїд 360×740. */
@media (max-width:38rem) and (max-height:48rem){
  .mail .sheet__in{gap:.9rem;padding:.9rem}
  .mail .sheet__title{font-size:1.25rem}
  .mail__f textarea{height:4.25rem}
}

/* ── перемикач мови ───────────────────────────────────────────────────── */
/* Дві позиції: у шапці, коли вона виїжджає, і в кутку першого екрана —
   інакше той, хто зайшов і не гортав, перемикача взагалі не побачить. */
.lang{display:inline-flex;align-items:center;gap:.5rem;margin:0;
  font-size:.75rem;font-weight:600;letter-spacing:.1em}
/* Ціль дотику мусить бути щонайменше 24×24 (WCAG 2.5.8). Напис PL/EN при
   12px дає 28×19 — палець туди не влучає. Додаємо простір усередину й
   знімаємо його від'ємним полем, щоб рядок лишився там, де стояв. */
.lang > *{text-decoration:none;color:inherit;opacity:.5;
  display:inline-flex;align-items:center;min-height:1.5rem;
  padding-inline:.3rem;margin-inline:-.3rem;
  transition:opacity .3s ease}
.lang a:hover,.lang a:focus-visible{opacity:1}
.lang [aria-current]{opacity:1}
.lang > * + *::before{content:"";display:inline-block;width:1px;height:.75em;
  margin-right:.5rem;vertical-align:-.05em;background:currentColor;opacity:.3}
.lang--nav{margin-left:auto}
.lang--hero{position:absolute;z-index:2;top:clamp(.9rem,2.2vh,1.75rem);
  right:calc((100% - var(--wrap)) / 2);color:#fff}
@media (max-width:51.99rem){
  .lang--nav{display:none}
}

/* ── бічний зміст і кнопка нагору ─────────────────────────────────────── */
/* Обріз сторінок журналу: стовпчик номерів на правому полі, у поточного
   розкривається назва. Колір береться з секції, що зараз посеред екрана. */
.rail{position:fixed;z-index:45;top:50%;translate:0 -50%;
  left:clamp(.75rem,1.6vw,1.5rem);display:none;
  opacity:0;pointer-events:none;transition:opacity .5s var(--ease)}
.rail.is-on{opacity:1;pointer-events:auto}
/* Колір береться не для всього стовпчика, а для кожного пункту: зміст вищий
   за один екран стику секцій, і на межі світлого й темного половина номерів
   ставала невидимою. */
.rail__item{color:var(--ink);--rail-dim:rgba(21,18,26,.34);transition:color .35s ease}
.rail__item.on-night{color:#fff;--rail-dim:rgba(255,255,255,.45)}
.rail__list{list-style:none;margin:0;padding:0;
  display:flex;flex-direction:column;align-items:center;gap:.3rem}
.rail__item a{position:relative;display:flex;flex-direction:column;align-items:center;
  gap:.45rem;padding:.3rem .3rem .45rem;text-decoration:none;color:inherit}
.rail__n{font-style:normal;font-size:.6875rem;font-weight:600;letter-spacing:.05em;
  font-variant-numeric:tabular-nums;color:var(--rail-dim);
  transition:color .35s ease}
.rail__item a:hover .rail__n,.rail__item a:focus-visible .rail__n{color:inherit}
/* Назва тільки в поточного: дев'ять підписів у стовпчик не влізли б у висоту
   екрана, а самих номерів мало, щоб зрозуміти, де ти. */
.rail__t{writing-mode:vertical-rl;font-size:.625rem;font-weight:500;letter-spacing:.16em;
  text-transform:uppercase;white-space:nowrap;
  max-height:0;opacity:0;overflow:hidden;
  transition:max-height .55s var(--ease),opacity .35s ease}
.rail__item.is-now .rail__n{color:inherit}
.rail__item.is-now .rail__t{max-height:15rem;opacity:1}
/* Тонка лінія під поточним пунктом — як у змісті на обрізі сторінок. */
.rail__item::after{content:"";display:block;height:1px;margin:0 auto;
  width:0;background:currentColor;opacity:.45;
  transition:width .45s var(--ease)}
.rail__item.is-now::after{width:1.35rem}

/* Підказка, що сторінка триває: та сама стрілка, що й на першому екрані,
   але вона їде з прокруткою над фотосмугою і гасне, щойно підходить текст. */
.trail{position:fixed;z-index:44;left:50%;translate:-50% 0;
  bottom:clamp(1.15rem,3.5vh,2rem);display:grid;place-items:center;
  color:#fff;opacity:0;pointer-events:none;transition:opacity .45s var(--ease)}
.trail.is-on{opacity:.8}
.trail .ico{width:1.15rem;height:1.15rem;
  animation:bob 2.4s var(--ease) infinite;
  filter:drop-shadow(0 2px 12px color-mix(in srgb,var(--night-900) 70%,transparent))}

.rail__top{position:fixed;z-index:45;right:clamp(.75rem,1.6vw,1.5rem);
  bottom:clamp(1rem,3vh,2rem);display:grid;place-items:center;
  width:2.5rem;height:2.5rem;padding:0;border-radius:50%;cursor:pointer;
  border:1px solid color-mix(in srgb,currentColor 28%,transparent);
  background:color-mix(in srgb,var(--paper) 62%,transparent);color:var(--ink);
  backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);
  /* Ховається видимістю, а не прозорістю. У кнопки є backdrop-filter, і
     доки її власна прозорість менша за одиницю, вона стає дном для самої
     себе: скло мертве всю появу й вмикається стрибком у кінці. Той самий
     механізм, що в кнопок у картках. Зсув такого ефекту не має. */
  visibility:hidden;translate:0 .6rem;pointer-events:none;
  transition:translate .4s var(--ease),visibility 0s .4s,
    background-color .4s ease,color .4s ease,border-color .4s ease}
.rail__top.is-on{visibility:visible;translate:0;pointer-events:auto;
  transition:translate .4s var(--ease),visibility 0s,
    background-color .4s ease,color .4s ease,border-color .4s ease}
.rail__top.on-night{background:color-mix(in srgb,var(--night-900) 55%,transparent);color:#fff}
.rail__top:hover{border-color:currentColor}
.rail__top .ico{width:1.05rem;height:1.05rem}

/* Зміст вимагає вільного поля збоку: за 76rem тексту й полем лишається
   менше 3rem на бік, і стовпчик ліз би на текст. */
@media (min-width:86rem){ .rail{display:block} }

/* ── поява при скролі ─────────────────────────────────────────────────── */
[data-reveal]{opacity:0;transform:translateY(1.75rem)}
[data-reveal].is-in{opacity:1;transform:none;
  transition:opacity .9s var(--ease),transform .9s var(--ease);
  transition-delay:calc(var(--d,0) * 90ms)}
/* Та сама вада, що була в кнопках першого екрана, тільки в інших місцях.
   Доки в контейнера прозорість менша за одиницю, він стає дном для
   backdrop-filter усіх нащадків: скло всередині стоїть пласким усю появу, а
   потім вмикається одним кадром, коли прозорість дійшла до одиниці. Виглядає
   це як «елемент доповнює свою анімацію після всього».
   Спершу я закрив це лише там, де під склом темне тло чи фотографія,
   вирішивши, що на папері стрибок непомітний. Виявилося, помітний:
   кнопка в картці «Dla kogo» доліплювала скло вже після того, як картка
   з'явилася. Тож правило тепер загальне — будь-який контейнер зі склом
   усередині з'являється самим лише зсувом, без розчинення. */
[data-reveal]:has(.btn,.vid__btn){opacity:1}

/* Приховування під клас `js`: без скрипта перший екран мусить просто
   бути, а не чекати на клас, якого ніхто не додасть.

   Поява — АНІМАЦІЯ, а не перехід. Перехід вимагав, щоб клас-вимикач
   зʼявився вже після першого малювання, і це була гонка, яку ми програвали
   тим частіше, чим швидше вантажилася сторінка: при теплому перезавантаженні
   мітка встигала лягти до першого кадру, і сторінка просто зʼявлялася
   готовою або показувала рваний хвіст. Анімація веде відлік від самої появи
   елемента, тож зовнішньої мітки їй не потрібно взагалі — і гонки немає.
   `--seq` приходить з розмітки, а не від скрипта, з тієї ж причини. */
.js [data-step]{opacity:0;transform:translateY(1.25rem);
  animation:stepIn 1s var(--ease) both;
  animation-delay:calc(var(--seq,0) * 130ms)}
@keyframes stepIn{
  from{opacity:0;transform:translateY(1.25rem)}
  to{opacity:1;transform:none}
}

@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.01ms !important;transition-duration:.01ms !important}
  [data-reveal],[data-step]{opacity:1;transform:none}
  .band__draw path{stroke-dashoffset:0}
  .band__unit i{opacity:1}
  .st__bars i.is-now::after{animation:none;transform:scaleX(1)}
  /* карусель преси не крутиться сама, і смужки під плиткою немає:
     показувати відлік до руху, якого не буде, — обман */
  .press__tile::after{animation:none;transform:scaleX(0)}
  .w > i{transform:none}
  .sect-head__rule,.stat__rule{transform:scaleX(1)}
  /* Рух підказки живе на ДОЧІРНЬОМУ .ico__b, а не на самому знаку, тож
     `animation:none` на .cue__ico його не діставало: колесо й свайп ішли
     далі, тільки за .01ms — тобто миготіли. Те саме зі стрілкою над
     фотосмугою. */
  .cue__ico,.cue__ico .ico__b,.trail .ico{animation:none}
  /* Літери лишаються зі своїм сталим світлом: анімація тут міняє filter, а
     не прозорість, тож .01ms дало б не спокій, а смикання яскравості. */
  .js .hero__mark img{animation:none}
  /* Поява першого екрана тепер анімація, і загальне правило вище її не
     знімає: воно скорочує тривалість, але не затримку, тож набір висів би
     невидимим до 0.65s. Тут вимикаємо явно. */
  .js [data-step],.js .section--hero .actions{animation:none}
  /* Кнопки ховає `visibility`, а не прозорість, і без анімації вона
     нікуди не дінеться — повертаємо явно. */
  .js .section--hero .actions{visibility:visible}
  .step:not(:last-child)::after,.step.is-in:not(:last-child)::after{transform:none}
  .step__ico,.step.is-in .step__ico{scale:1}
  /* Загальне правило вище скорочує тривалість до .01ms, а для нескінченної
     анімації це не «нема руху», а миготіння. Тому наїзд і дихання плям
     вимикаємо явно. */
  .section--hero::after{animation:none;scale:1}
}

