/*
  Цветовые токены темы. Сайт всегда светлый (см. :root ниже) —
  переключателя темы нет.

  Единственное место, где заданы конкретные HEX/rgba-значения — все
  компоненты (header.css/footer.css/masonry.css) читают только
  var(--color-*), без хардкода.
*/

:root {

  /* Шкала скруглений. На телефоне (≤767px) все ступени меньше — см. блок
     @media ниже. Пилюли кнопок (--radius-control) и круги не трогаем. */
  --radius-hero: clamp(28px, 3vw, 44px); /* баннер, цветные подложки */
  --radius-surface: 14px; /* панели, меню, карточки, контент кейсов */
  --radius-inner: 10px;   /* аватар, мелкие карточки, картинки в карточках */
  --radius-tag: 6px;      /* бейджи и теги */

  /* Матовое стекло (хедер/футер/кнопки навигации) — одна и та же
     "рецептура" размытия в обеих темах, меняются только цвета-токены
     ниже. -webkit- дубль обязателен для Safari/iOS, у него до сих пор
     нет неprefixed backdrop-filter. */
  --glass-blur: 20px;
  --glass-saturate: 180%;

  /* «Liquid glass» — второй рецепт стекла, используется только у
     хедера, футера и кнопки "наверх" (см. header.css/footer.css) —
     тоньше размытие, выше насыщенность
     + SVG-фильтр (feTurbulence+feDisplacementMap, см.
     #liquid-glass-distort в index.html), слегка "гнущий" картинку под
     стеклом вместо идеально ровного блюра. Цифры подобраны и
     утверждены на тестовом стенде (dev/previews/liquid-glass-sample.html)
     — менять лучше там же, не на глаз в бою. Остальные стеклянные
     плашки (панель мобильного меню, кнопка "Меню") остаются на
     рецепте --glass-blur/--glass-saturate выше, здесь не трогаем.
     --liquid-glass-glow — блик по кромке: обычный box-shadow на самом
     элементе, не псевдоэлемент — ::before у кнопки "наверх" уже занят
     hover-пятном (см. button-hover.css), а ::after везде занят
     переливающейся обводкой (см. ниже). */
  --liquid-glass-blur: 4px;
  --liquid-glass-saturate: 210%;
  --liquid-glass-filter: blur(var(--liquid-glass-blur)) saturate(var(--liquid-glass-saturate)) url(#liquid-glass-distort);
  --liquid-glass-glow:
    inset 1px 1px 0 -1px rgba(255, 255, 255, 0.8),
    inset 0 0 4px 1px rgba(255, 255, 255, 0.35);
}

@media (max-width: 767px) {
  :root {
    --radius-hero: 20px;
    --radius-surface: 10px;
    --radius-inner: 6px;
    --radius-tag: 4px;
  }
}

/* WebKit (весь мобильный браузер на iOS, а не только сама Safari) не
   умеет url()-ссылку на SVG-фильтр внутри backdrop-filter — вместо
   игнора непонятной части он бракует ВСЁ значение целиком и откатывает
   на none, стекло у хедера/футера/кнопки "наверх" пропадает
   полностью, а не просто теряет рябь. Пробник в index.html определяет
   это на реальном рендере (надёжнее @supports — тот в WebKit считает
   синтаксис валидным) и ставит класс сюда.

   Эта переменная — на будущее/другие движки: где-нибудь backdrop-filter
   мог бы не понимать именно url(), но нормально резолвить var() —
   тогда достаточно было бы просто убрать url()-часть. РЕАЛЬНЫЙ фикс
   для сегодняшнего WebKit — ниже, отдельным блоком: та же проверка
   показала, что этот движок не резолвит var() внутри backdrop-filter
   ВООБЩЕ (даже голое число внутри blur(var(--x)) — уже none), так что
   для него годится только буквальное значение без единой переменной. */
html.no-liquid-glass-distort {
  --liquid-glass-filter: blur(var(--liquid-glass-blur)) saturate(var(--liquid-glass-saturate));
}

/* Настоящий фикс для WebKit — см. комментарий выше: var() внутри
   backdrop-filter там не резолвится вообще, поэтому хедеру/футеру/
   кнопке "наверх" нужно буквальное значение без переменных.
   Числа продублированы из --liquid-glass-blur/--liquid-glass-saturate
   вручную — иначе никак, но если поменяете рецепт там, поменяйте и
   здесь. Селекторы перечислены явно (а не через .site-header и т.д.
   в своих файлах) — так весь WebKit-костыль лежит в одном месте, а не
   размазан по header.css/footer.css. */
html.no-liquid-glass-distort .site-footer,
html.no-liquid-glass-distort:not(.chrome--compact) .site-footer.is-collapsed {
  backdrop-filter: blur(4px) saturate(210%);
  -webkit-backdrop-filter: blur(4px) saturate(210%);
}

/* Тот же баг WebKit (var() внутри backdrop-filter не резолвится) бьёт
   и по обычному стеклу (--glass-blur/--glass-saturate, без SVG-ряби и
   url() — так что дело определённо не в url(), а в var() как таковом)
   — панель мобильного меню (.footer-menu-panel__bar, см. footer.css)
   на WebKit тоже была без блюра. Кнопку "Меню" (.site-footer__menu-btn)
   не трогаем — она сплошная розовая, стекла на ней и не видно. */
html.no-liquid-glass-distort .footer-menu-panel__bar {
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
}

:root {
  /* Общий тайминг плавных переходов фона/цвета — читают html/body
     ниже и works-grid.css, чтобы такие переходы шли в один и тот же
     плавный такт, а не дёргано. */
  --theme-transition-duration: 0.6s;
  --theme-transition-ease: cubic-bezier(0.65, 0, 0.35, 1);
}

:root {
  color-scheme: light;

  --color-bg: #ffffff;
  --color-surface: #f3f4f6;
  --color-surface-alt: #eceef2;
  --color-text: #14161a;
  --color-text-muted: #5f6673;
  --color-border: #dde0e6;

  /* "Ink" — цвет обводки/заливки монохромных контролов (кнопки,
     иконки), инвертируется относительно surface в каждой теме. */
  --color-ink: #14161a;
  --color-ink-contrast: #ffffff;

  /* Полупрозрачные версии surface/surface-alt под backdrop-filter —
     сама заливка почти не видна без blur, весь эффект стекла даёт
     именно смазанный фон под ней. Едва заметная тёмная обводка
     (не color-border — он тут слишком плотный/непрозрачный) — типичная
     кромка стекла по краю панели; ею же обведены все дропдауны
     (вместо тени). */
  --color-glass: rgba(255, 255, 255, 0.6);
  --color-glass-alt: rgba(243, 244, 246, 0.6);
  --color-glass-border: rgba(20, 22, 26, 0.08);

  /* Лёгкая обводка картинок: обложки Главной и скриншоты интерфейсов в
     кейсах — та же кромка, что у дропдаунов. */
  --media-border: 1px solid var(--color-glass-border);

  /* Скелетон загрузки — везде одна статичная светло-серая заливка, тот же
     серый, что у кейсов без своей палитры. Без «дыхания» и наложений. */
  --skeleton-color: var(--color-surface);
}

/*
  Переливающаяся обводка стеклянных плашек (хедер/футер/панель меню) —
  conic-gradient, замаскированный так, что виден только тонкий
  кольцевой контур, а не вся заливка. Псевдоэлемент, НЕ настоящий
  border: реальный border (пробовали раньше) на box-sizing:border-box
  отъедает 1px у padding-box изнутри и сдвигает то, что позиционировано
  абсолютными px — у ::after с position:absolute; inset:0 такого
  побочного эффекта нет. Именно ::after, не ::before — у
  .site-footer__top-btn ::before уже занят розовым hover-пятном из
  button-hover.css, второй эффект на том же псевдоэлементе конфликтовал
  бы с ним.

  Цвет — не выдуманный, а взят от реального цветного элемента, который
  на этой плашке действительно есть, и стоит примерно на его месте
  (--glass-accent/--glass-accent-pos, заданы у самих плашек ниже):
  хедер — розовая кнопка "Резюме PDF" (сидит справа), футер и панель
  меню — активный розовый пункт "Работы" (сидит слева/сверху-слева).
  У кнопки "наверх" в футере цветного контента нет — акцент остаётся
  прозрачным, только нейтральный белый слой.
*/
@property --glass-shimmer-angle {
  syntax: "<angle>";
  initial-value: 0deg;
  inherits: false;
}

/* inherits:false — иначе --glass-accent, заданный на .site-footer ниже,
   утекал бы вниз по DOM на .site-footer__top-btn (обычные custom
   properties наследуются по умолчанию) и красил бы её обводку в
   розовый, хотя у неё самой никакого розового элемента нет. */
@property --glass-accent {
  syntax: "<color>";
  initial-value: transparent;
  inherits: false;
}
@property --glass-accent-pos {
  syntax: "*";
  initial-value: 50% 50%;
  inherits: false;
}

.site-header {
  /* Кнопка "Резюме PDF" (--btn-accent) — крайняя справа
     (justify-content: space-between в header.css). */
  --glass-accent: color-mix(in srgb, var(--btn-accent) 70%, transparent);
  --glass-accent-pos: calc(100% - 2.5rem) 50%;
}

.site-footer,
.footer-menu-panel__bar {
  /* Активный пункт "Работы" — всегда первый/крайний слева в списке
     (см. .site-footer__nav / .footer-menu-panel__nav). */
  --glass-accent: color-mix(in srgb, var(--btn-accent) 70%, transparent);
  --glass-accent-pos: 2.25rem 50%;
}

:is(
  .site-header,
  .site-footer,
  .footer-menu-panel__bar
) {
  position: relative;
}

/* .site-footer__top-btn НЕ в списке выше — у неё уже position:absolute
   в footer.css (нужен для right:0), этого достаточно как containing
   block для ::after ниже, лишний position:relative тут только рисковал
   бы конфликтовать по каскаду. У неё же нет --glass-accent (нечего
   отражать — просто стрелка, ink-цвет), задел transparent по умолчанию
   ниже в самом ::after. */

:is(
  .site-footer,
  .footer-menu-panel__bar
)::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  padding: 1px;
  background:
    radial-gradient(ellipse 45% 160% at var(--glass-accent-pos, 50% 50%), var(--glass-accent, transparent), transparent 70%),
    conic-gradient(
      from var(--glass-shimmer-angle),
      rgba(255, 255, 255, 0.9),
      rgba(255, 255, 255, 0.05) 25%,
      rgba(255, 255, 255, 0.75) 50%,
      rgba(255, 255, 255, 0.05) 75%,
      rgba(255, 255, 255, 0.9) 100%
    );
  -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  pointer-events: none;
  /* Плавно перекрашивается вместе с реальной кнопкой/пунктом на
     hover (--button-hover-duration — тот же такт, что и у их
     собственного цвета в button-hover.css). */
  transition: --glass-accent var(--button-hover-duration, 0.5s) ease;
}

html,
body {
  background: var(--color-bg);
  color: var(--color-text);
  transition:
    background-color var(--theme-transition-duration) var(--theme-transition-ease),
    color var(--theme-transition-duration) var(--theme-transition-ease);
}

@media (prefers-reduced-motion: reduce) {
  html,
  body {
    transition-duration: 0.01ms;
  }
}

html {
  scroll-behavior: smooth;
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
}

/* Mood experiment. Palette roles are shared by hero, chrome and DS buttons.
   Project artwork/embeds retain their original colours. */
html[data-mood] {
  --mood-bg: #FEB7D7;
  --mood-chrome: #F9E8EF;
  --mood-ink: #111111;
  --mood-particle: #581B3A;
  --color-action-active: #2448FF;
  --color-action-hover: #2448FF;
  --color-action-active-text: #FFFFFF;
  --color-action-hover-text: #FFFFFF;
}
html[data-mood="stasy"] {
  --mood-bg: #97A6FD;
  --mood-chrome: #E9ECFF;
  --mood-particle: #242C65;
  --color-action-active: #D5FF00;
  --color-action-hover: #D5FF00;
  --color-action-active-text: #111111;
  --color-action-hover-text: #111111;
}
html[data-mood="stas"] {
  --mood-bg: #FDF07F;
  --mood-chrome: #F7F2D9;
  --mood-particle: #52451A;
  --color-action-active: #D60067;
  --color-action-hover: #D60067;
  --color-action-active-text: #FFFFFF;
  --color-action-hover-text: #FFFFFF;
}
/* Text selection follows the active mood, using its contrasting action pair. */
html[data-mood]::selection,
html[data-mood] ::selection {
  background-color: var(--color-action-active);
  color: var(--color-action-active-text);
  text-shadow: none;
}
html[data-mood] .site-header {
  /* Transparent glass: colours follow the page theme, not the mood plate. */
  transition: background-color .55s ease, top .25s ease, left .25s ease;
}
@media (prefers-reduced-motion: reduce) {
  html[data-mood] .site-header { transition: none; }
}
