/* Shared across every page: buttons, nav, footer, scroll reveal. */

/* ============ BUTTONS ============ */
/* Фотографія товару в будь-якій мініатюрі — сітка, кошик, шухляда, чек.
   Жила в home.css, який вантажать головна, категорія й сторінка моделі, — а
   кошик вантажить лише pages.css. Тож коли рядок кошика навчився показувати
   фото, воно приїхало б туди без жодного розміру. Правило спільне, бо
   спільний і thumbOf, який його ставить. */
.art__photo{width:100%;height:100%;object-fit:cover;display:block}

.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:8px;
  height:48px;padding:0 30px;border-radius:var(--pill);
  font-family:'Outfit',sans-serif;font-size:14px;font-weight:500;letter-spacing:.06em;text-transform:uppercase;
  transition:transform .18s var(--ease),background .18s var(--ease),color .18s var(--ease),box-shadow .18s var(--ease);
  white-space:nowrap;
}
.btn:hover{transform:translateY(-2px)}
.btn:active{transform:translateY(0)}
.btn--solid{background:var(--graphite);color:#fff}
.btn--solid:hover{background:#000;box-shadow:var(--shadow-2)}
.btn--ghost{background:rgba(255,255,255,.75);color:var(--graphite);backdrop-filter:blur(8px);box-shadow:inset 0 0 0 1px rgba(23,26,32,.16)}
.btn--ghost:hover{background:#fff}
.btn--volt{background:var(--volt);color:#fff}
.btn--volt:hover{background:#c4142f;box-shadow:0 10px 26px rgba(227,25,55,.28)}
.btn--light{background:#fff;color:var(--graphite)}
.btn--light:hover{box-shadow:var(--shadow-2)}
.btn--sm{height:40px;padding:0 22px;font-size:12px}
.btn--block{width:100%}
/* The hover glow drops the focus ring to 2.97:1 against its own halo, so a
   keyboard user with the mouse resting on the primary CTA loses the ring. */
.btn--volt:focus-visible{box-shadow:none}

/* Unavailable. `opacity` composites the label toward the page behind it rather
   than fading it against its own background: .btn--volt at .4 renders white on
   #F4A3AF, about 1.98:1. Swapping tokens instead gives --silver on --cloud,
   about 5.18:1. 1.4.3 does exempt inactive components, but an aria-disabled
   button stays focusable, so "inactive" is a stretch — and the swap passes
   anyway, which makes the argument moot. */
.btn[disabled],
.btn.is-off,
.btn[aria-disabled="true"]:not(.is-busy){
  opacity:1;background:var(--cloud);color:var(--silver);cursor:not-allowed;
  transform:none!important;box-shadow:none!important}
.btn[disabled]:hover,
.btn.is-off:hover,
.btn[aria-disabled="true"]:not(.is-busy):hover{background:var(--cloud);transform:none}

/* Busy is NOT unavailable. Keep the button's own colours — the user has to be
   able to read the control they just pressed — and show pending with a spinner
   rather than by dimming it. The accessible name is never rewritten. */
.btn.is-busy{cursor:progress}
.btn.is-busy::after{content:"";width:14px;height:14px;margin-left:10px;
  border:2px solid currentColor;border-top-color:transparent;border-radius:var(--pill);
  animation:btnspin .7s linear infinite}
@keyframes btnspin{to{transform:rotate(360deg)}}
@media(prefers-reduced-motion:reduce){
  .btn.is-busy::after{animation:none;border-top-color:currentColor;opacity:.6}
}
/* Colour-only affordances disappear in forced-colors mode. */
@media(forced-colors:active){
  .btn[disabled],
  .btn.is-off,
  .btn[aria-disabled="true"]:not(.is-busy){color:GrayText;border:1px solid GrayText}
  .btn.is-busy::after{border-color:CanvasText;border-top-color:transparent}
}

/* "Added" confirmation as a state class, so the button's accessible name is
   never rewritten. The tick is generated content and therefore decorative. */
.btn.is-added .btn__lbl{opacity:.35}
.btn.is-added::after{content:"\2713";margin-left:6px;font-weight:700}

/* ============ NAV ============ */
.nav{
  position:fixed;inset:0 0 auto 0;z-index:80;
  transition:background .3s var(--ease),box-shadow .3s var(--ease),backdrop-filter .3s var(--ease);
}
.nav.is-stuck{background:rgba(255,255,255,.86);backdrop-filter:blur(18px) saturate(1.4);box-shadow:0 1px 0 var(--line)}
.nav__in{
  max-width:var(--maxw);margin:0 auto;padding:0 var(--pad);
  height:70px;display:flex;align-items:center;justify-content:space-between;gap:20px;
}
/* Класи замість атрибутів style="". Вони пішли не заради охайності: поки
   вони були в розмітці, CSP мусила тримати style-src 'unsafe-inline', а це
   єдина директива, яку доводилося послабляти.
   Один із них до того ж псував те, що виправляв: style="color:var(--volt)" на
   #gErr перекривав .news-err{color:var(--volt-on-dark)} — тобто підмінював
   відтінок, підібраний саме під темне тло, на той, що для світлого. */
.u-link{text-decoration:underline;text-underline-offset:3px}
.linklist{list-style:none;display:flex;flex-direction:column;gap:10px}
.subh{font-size:20px;margin-bottom:14px}
.page--narrow{max-width:660px}
.lede--sp{margin-bottom:28px}
.brand--light{color:#fff}

.brand{display:flex;align-items:center;gap:10px;font-family:'Outfit',sans-serif;font-weight:600;font-size:19px;letter-spacing:.24em}
.brand__mark{width:30px;height:30px;flex:none}
.nav__links{display:flex;gap:6px}
.nav__links a{
  padding:9px 18px;border-radius:var(--pill);font-size:14px;font-weight:600;
  transition:background .18s var(--ease);
}
.nav__links a:hover{background:rgba(23,26,32,.07)}
.nav__side{display:flex;align-items:center;gap:6px}
.icobtn{
  width:42px;height:42px;border-radius:var(--pill);display:grid;place-items:center;position:relative;
  transition:background .18s var(--ease);
}
.icobtn:hover{background:rgba(23,26,32,.07)}
.cartdot{
  position:absolute;top:4px;right:3px;min-width:19px;height:19px;padding:0 5px;border-radius:var(--pill);
  background:var(--volt);color:#fff;font-size:11px;font-weight:700;display:none;place-items:center;
  font-family:'JetBrains Mono',monospace;
}
/* Та сама пігулка, що .tab__badge у панелі, і доти без жодного правила для
   високої контрастності: --volt підмінявся на Canvas, білий текст на
   CanvasText, і лічильник лишався голою цифрою поверх іконки кошика — без
   кола, яке відділяє її від самої іконки. Пара Canvas/CanvasText і межа
   тією ж CanvasText: гарантована в кожній темі. */
@media(forced-colors:active){
  .cartdot{background:Canvas;color:CanvasText;border:1px solid CanvasText}
}
.cartdot.on{display:grid}
.burger{display:none}

/* ============ FOOTER ============ */
/* The load-bearing half of 2.4.11: at maximum scroll there is no scroll range
   left for scroll-padding to spend, so the last screenful of links can only be
   kept clear by reserving the space. --cc-h is 0 when no banner exists. */
.foot{background:var(--graphite);color:#fff;
  padding:clamp(52px,7vw,86px) 0 calc(34px + var(--cc-h));margin-top:clamp(64px,8vw,110px)}
.foot__grid{display:grid;grid-template-columns:1.6fr repeat(3,1fr);gap:40px}
.foot__brand p{color:rgba(255,255,255,.55);font-size:14.5px;line-height:1.6;max-width:34ch;margin-top:16px}
.foot h3,.foot h4{font-family:'JetBrains Mono',monospace;font-size:11px;letter-spacing:.2em;text-transform:uppercase;color:rgba(255,255,255,.45);margin-bottom:16px;font-weight:400}
.foot ul{list-style:none;display:flex;flex-direction:column;gap:11px}
.foot ul a{color:rgba(255,255,255,.82);font-size:14.5px;transition:color .16s var(--ease)}
.foot ul a:hover{color:#fff}
.foot__bar{
  margin-top:52px;padding-top:24px;border-top:1px solid rgba(255,255,255,.13);
  display:flex;justify-content:space-between;gap:18px;flex-wrap:wrap;
  font-size:12.5px;color:rgba(255,255,255,.45);font-family:'JetBrains Mono',monospace;
}

/* ============ REVEAL ============ */
/* .js, а не голий .rv: сховане має залежати від того, що скрипт СТАРТУВАВ.
   Інакше з вимкненим JS блоки лишаються на opacity:0 назавжди — видимих
   пікселів нема, а таб у них заходить, бо opacity не чіпає порядок
   табуляції. Разом із вмістом невидимим стає й фокусне кільце. */
.js .rv{opacity:0;transform:translateY(22px);transition:opacity .7s var(--ease),transform .7s var(--ease)}
.js .rv.in{opacity:1;transform:none}
/* І показуємо одразу, щойно фокус зайшов усередину. Спостерігач спрацює й
   сам — прокрутка до посилання це робить, — але між приходом фокуса і кінцем
   700-мілісекундного проявлення кільце ще не видно, а 2.4.7 питає саме про
   мить, коли фокус прийшов. transition:none — щоб для клавіатури не було
   й тих 700 мс. */
.js .rv:focus-within{opacity:1;transform:none;transition:none}

/* ============ REDUCED MOTION ============
   Canonical copy. home.css and product.css each carry their own from before
   base.css had one; they are identical, so they are harmless, but every NEW
   page stylesheet should rely on this rather than adding a fourth. Three copies
   drift; four is worse. */
@media(prefers-reduced-motion:reduce){
  *{animation:none!important;transition-duration:.01ms!important}
  .js .rv{opacity:1;transform:none}
  html{scroll-behavior:auto}
}

/* ============ SEARCH ============
   A combobox: the input owns the listbox and tracks the active row with
   aria-activedescendant, so focus never leaves the field and typing keeps
   working while the arrow keys walk the results. */
.srch__scrim{position:fixed;inset:0;background:rgba(15,17,18,.42);backdrop-filter:blur(3px);z-index:110}
.srch__scrim[hidden]{display:none}
.srch{position:fixed;inset:0;z-index:111;display:grid;place-items:start center;padding:12vh 16px 16px;
  pointer-events:none}
.srch[hidden]{display:none}
.srch__panel{pointer-events:auto;width:min(620px,100%);background:var(--paper);
  border-radius:var(--r-lg);box-shadow:var(--shadow-3);overflow:hidden}
.srch__bar{display:flex;align-items:center;gap:12px;padding:16px 18px;border-bottom:1px solid var(--line)}
.srch__bar input{flex:1;min-height:32px;border:0;background:none;font-size:17px}
.srch__bar input:focus{outline:none}
.srch__close{width:36px;height:36px;border-radius:var(--pill);display:grid;place-items:center;flex:none}
.srch__close:hover{background:var(--mist)}
.srch__hint{padding:12px 18px;font-size:13px;color:var(--silver)}
.srch__hint:empty{display:none}
.srch__list{list-style:none;max-height:52vh;overflow-y:auto;overscroll-behavior:contain}
.srch__list:empty{display:none}
.srch__item a{display:block;padding:13px 18px;border-top:1px solid var(--line)}
.srch__item b{font-family:'Outfit',sans-serif;font-size:15.5px;font-weight:600;display:block}
.srch__item span{font-family:'JetBrains Mono',monospace;font-size:11.5px;color:var(--silver)}
/* The active row is not focused, so :hover/:focus cannot style it. */
.srch__item.on a,.srch__item a:hover{background:var(--mist)}
.srch__item.on a{box-shadow:inset 3px 0 0 var(--volt)}
@media(forced-colors:active){
  .srch__panel{border:1px solid CanvasText}
  .srch__item.on a{outline:2px solid Highlight;outline-offset:-2px}
}

/* Moved from home.css, where it only ever loaded on two of the sixteen pages
   while search.js called setPageInert on all of them. */
body.overlay-open{overflow:hidden}

/* ============ COOKIE CONSENT ============
   A named region, not a dialog. See consent.js for why it does not trap focus,
   why it is removed rather than hidden, and why Escape does nothing.

   z-index 82: above .nav (80), so the mobile menu — which has no scrim — cannot
   cover buttons that are still reachable by Shift+Tab; below every scrim (cart
   90, offer 100, search 110), so that when setPageInert makes this inert it is
   visibly dimmed rather than looking operable while unreachable. */
.cc{
  position:fixed;left:0;right:0;bottom:0;z-index:82;
  /* Fully opaque, and no backdrop-filter. A translucent surface makes contrast
     uncomputable: the same --silver measures 6.11:1 over the hero and 3.80:1
     over the graphite footer through the same sheet. One passes 1.4.3 and one
     fails, depending on scroll position. */
  background:var(--paper);
  /* --ctrl-line, not --line. The strict reading of 1.4.11 exempts a decorative
     container edge, but --line is 1.02:1 against the end of the hero gradient
     and this surface is 1.00:1 against a white page — the edge is the only
     thing declaring this a separate floating surface, so it is not decorative.
     The shadow is depth alongside it, never instead of it: forced-colors
     removes shadows entirely. */
  border-top:1px solid var(--ctrl-line);
  box-shadow:var(--shadow-3);
  /* A transform transition, not a keyframe animation. The global
     prefers-reduced-motion block collapses animation to none, so a keyframe
     that never runs against a translateY(100%) resting state would leave the
     consent banner permanently off screen. A transition just becomes instant. */
  transform:translateY(100%);
  transition:transform .32s var(--ease);
}
.cc.is-in{transform:none}

.cc__in{
  max-width:var(--maxw);margin:0 auto;padding:18px var(--pad);
  display:flex;align-items:center;justify-content:space-between;gap:22px 32px;flex-wrap:wrap;
  /* No fixed height: expanded text spacing has to grow the box, not be clipped
     by it (1.4.12). The cap keeps a bottom bar from eating a 320px viewport at
     400% zoom (1.4.10); consent.js adds tabindex only while it really scrolls. */
  max-height:50dvh;overflow-y:auto;
}
.cc__p{font-size:14.5px;line-height:1.6;max-width:62ch;flex:1 1 340px}
/* Underlined, because colour alone cannot mark a link (1.4.1). Inline in the
   sentence on purpose — beside the buttons its 24px target circle would
   intersect theirs and the 2.5.8 inline exception would stop applying. */
.cc__link{text-decoration:underline;text-underline-offset:3px}

/* Both buttons carry .btn--solid: same fill, same size, same weight. Reject is
   first here and first in the DOM, and must never be reordered with `order:` or
   row-reverse — that desyncs the tab order from the reading order. */
.cc__acts{display:flex;gap:12px;flex:0 0 auto;flex-wrap:wrap}
.cc__acts .btn{flex:1 1 auto;min-width:170px}

@media(max-width:560px){
  .cc__in{padding:16px var(--pad) 18px;gap:16px}
  .cc__acts{width:100%}
}

/* Guard only. The global ring is 3px --volt at 3px offset, which sits entirely
   on --paper here — 4.71:1 against both the ring and the graphite fill. If a
   red fill ever lands in this bar the ring would touch it, so swap the ring
   rather than suppress it. */
.cc .btn--volt:focus-visible{outline-color:var(--graphite)}

@media(forced-colors:active){
  .cc{background:Canvas;border-top:1px solid CanvasText;box-shadow:none}
}

/* ============ НАПИСАТИ НАМ ============
 *
 * Смуга звʼязку. Зараз вона рівно на головній; клас спільний, щоб друга така
 * смуга не з'явилася окремою копією з іншим підписом і іншим порядком кнопок.
 *
 * Темна на світлій сторінці й навпаки: це єдиний блок, який має бути видно
 * не читаючи, і колір тут робить рівно цю роботу. Але не ЛИШЕ колір —
 * кнопки, заголовок і рамка несуть те саме, тож у режимі високої
 * контрастності смуга не зникає, а стає обведеною.
 */
.ctc{background:var(--graphite);color:#fff;border-radius:var(--r-lg);
  padding:clamp(28px,4vw,44px) clamp(22px,4vw,44px)}
.ctc__h{font-family:'Outfit',sans-serif;font-size:clamp(22px,2.6vw,30px);
  line-height:1.22;margin:0 0 10px}
.ctc__p{color:rgba(255,255,255,.68);font-size:15px;line-height:1.6;
  max-width:52ch;margin:0 0 22px}
.ctc__acts{display:flex;flex-wrap:wrap;gap:12px;align-items:center}

/* Кнопки в темній смузі. Первинна біла на темному — 17,43:1; вторинна
   обведена, і обведення тут ЄДИНЕ, що робить із неї кнопку, тож воно на
   .72 — 9,47:1 проти графіту, — а не на .3, як звикли робити «привиди».
   (Тут раніше було написано «на повній непрозорості». Це не так, і саме
   таке читання дало .foot__talk його межу на .22, якої не було видно.) */
.ctc .btn--solid{background:#fff;color:var(--graphite)}
.ctc .btn--solid:hover{background:rgba(255,255,255,.88)}
.ctc .btn--line{background:transparent;color:#fff;
  box-shadow:inset 0 0 0 1.5px rgba(255,255,255,.72)}
.ctc .btn--line:hover{box-shadow:inset 0 0 0 1.5px #fff;background:rgba(255,255,255,.08)}

/* Фокусне кільце в темній смузі. Глобальне --volt дає на --graphite 3,70:1 —
   для нетекстового індикатора вистачає, але тут поруч є білий, який дає
   17,43:1, і на темному тлі саме він читається як «ось воно».
 *
 * ПЕРЕЛІЧЕНО ПОІМЕННО, а не `.ctc :focus-visible`. Нащадковий селектор
 * пофарбував би в біле кільце будь-чого, що колись опиниться в смузі, — і в
 * день, коли туди покладуть світлий елемент (поле вводу, світлу кнопку),
 * кільце стане білим на білому й зникне мовчки. Той самий хід, що в
 * .cc .btn--volt:focus-visible вище. */
.ctc .btn--solid:focus-visible,
.ctc .btn--line:focus-visible,
.ctc__alt a:focus-visible{outline-color:#fff}

.ctc__alt{margin:18px 0 0;font-size:14px;color:rgba(255,255,255,.6)}
.ctc__alt a{color:#fff;text-decoration:underline;text-underline-offset:3px}

/* Значок каналу. aria-hidden у розмітці: назву каналу вже несе підпис
   кнопки, і друге «Telegram» поспіль — це не інформація, а затримка. */
.ctc__ico{flex:none}

@media(max-width:560px){
  /* На вузькому екрані кнопки на всю ширину: два ряди по одній читаються
     краще, ніж два огризки в один ряд.
   *
   * АЛЕ .btn несе white-space:nowrap і padding:0 30px, і на 320px це вбивчо:
   * після відступів обгортки, смуги, самої кнопки та значка на підпис
   * лишається ~149px, а «НАПИСАТИ В TELEGRAM» у верхньому регістрі просить
   * ~180. Підпис вилазив за пігулку — і оскільки в .btn--solid він графітовий
   * на білому, за межами пігулки він ставав графітом на графіті: 1:1, тобто
   * зникав. Не обрізався, а зникав, і в автоматичних перевірках це мовчить,
   * бо доступне ім'я лишається цілим.
   *
   * До того ж кирилиці немає в жодному з наших підмножин шрифту (latin і
   * latin-ext), тож українські літери малює системний шрифт, у якого
   * великі літери ширші за Outfit. Оцінка вище — це підлога, не стеля.
   *
   * min-height замість height: два рядки дозволені, розмір цілі збережено. */
  .ctc__acts{flex-direction:column;align-items:stretch}
  .ctc__acts .btn{width:100%;justify-content:center;
    white-space:normal;padding:0 16px;height:auto;min-height:48px}
}

@media(forced-colors:active){
  /* Заливка зникає — лишається рамка, інакше смуга злилася б зі сторінкою
     й перестала бути окремим блоком. */
  .ctc{border:1px solid CanvasText}
  /* currentColor, а не ButtonText: обидва ці елементи — <a href>, і система
     примусово фарбує їх у LinkText, який у темах високої контрастності
     НАВМИСНО інший (жовтий проти білого). Біла рамка навколо жовтого тексту
     заявляє не ту роль, а пара ButtonText/Canvas ще й не гарантована — темі
     обіцяно контрастувати ButtonText лише з ButtonFace. */
  /* І ПЕРВИННА теж. Без цього рядка виходило навпаки: вторинна кнопка
     малювалася обведеною, а первинна — та, якою користуються, — ставала
     голим текстом без жодної межі. У .btn--solid уся межа це заливка #fff,
     і система її стирає так само, як box-shadow. */
  .ctc .btn--line,
  .ctc .btn--solid{box-shadow:none;border:1px solid currentColor}
}

/* Рядок звʼязку в підвалі. Не колонка посилань, а окремий блок: у колонках
   підвалу лежать сторінки сайту, а це — вихід із сайту в застосунок, і
   змішувати їх означає, що людина натискає «Повернення» і опиняється в
   Telegram. */
.foot__talk{margin-top:14px;display:flex;flex-wrap:wrap;gap:10px}
/* Запасний шлях під пігулками. Це єдине місце з чотирьох, де його не було, —
   і воно ж єдине, що є на КОЖНІЙ сторінці. */
.foot__talkalt{margin-top:12px;font-size:13.5px;color:rgba(255,255,255,.55)}
.foot__talkalt a{color:rgba(255,255,255,.85);text-decoration:underline;
  text-underline-offset:3px}
.foot__talkalt a:hover{color:#fff}
/* Числа тут пораховані, а не підібрані на око — і перший підбір був хибний.
   Заливка .10 і межа .22 давали межу 2,03:1 проти підвалу і 1,52:1 проти
   власної заливки, тобто межі не було видно взагалі. Пігулка виглядала
   кнопкою рівно доти, доки на неї дивишся уважно.
   Тепер: межа .5 — це 5,24:1 проти підвалу і 4,44:1 проти заливки .06,
   а білий текст на цій заливці 14,79:1. Намальована межа, якої не видно,
   гірша за жодну: вона обіцяє межу. */
.foot__talk a{display:inline-flex;align-items:center;gap:8px;
  padding:9px 15px;border-radius:999px;font-size:14px;
  color:#fff;background:rgba(255,255,255,.06);
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.5);
  transition:background .16s var(--ease)}
/* Наведення піднімає й межу, а не лише заливку. Доти воно піднімало саму
   заливку до .2, а межа лишалася на .22 — і ці двоє сходилися на 1,07:1, тобто
   межа СТИРАЛАСЯ рівно в мить, коли на кнопку навели. Тепер .8 проти заливки
   .2 — це 6,02:1. Той самий хід, що в .ctc .btn--line:hover. */
.foot__talk a:hover{background:rgba(255,255,255,.2);
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.8)}
@media(forced-colors:active){
  .foot__talk a{box-shadow:none;border:1px solid currentColor}
}

/* ── [hidden] МУСИТЬ ПЕРЕМАГАТИ, І ЦЕ ЗАПОБІЖНИК НА ВЕСЬ САЙТ ──────────────
   [hidden]{display:none} — правило БРАУЗЕРА, тобто найслабше з усіх. Будь-яке
   авторське display його перебиває незалежно від специфічності, і елемент,
   схований атрибутом, лишається на екрані.

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

   Правило жило в pages.css, який вантажать не всі сторінки: сторінка товару
   бере лише fonts, tokens, base і product. Тому воно тут — base.css вантажать
   усі, і третьої латки більше не знадобиться. */
[hidden]{display:none!important}
