/* =========================================================
   YULIA PHOTOGRAPHER — головна сторінка
   Побудовано за макетом Figma (frame "home-page").
   Шрифти self-hosted: Cormorant Garamond (fonts/) + Vasek (fonts/).
   Правило: у Vasek немає української "і" — у текстах, набраних
   цим шрифтом, замість "і" завжди пишемо латинську "i".
   ========================================================= */

/* ---------- 1. Шрифти (self-hosted, без CDN) ---------- */

@font-face {
  font-family: 'Cormorant Garamond';
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url('fonts/CormorantGaramond-cyrillic-ext.woff2') format('woff2');
  unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
@font-face {
  font-family: 'Cormorant Garamond';
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url('fonts/CormorantGaramond-cyrillic.woff2') format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: 'Cormorant Garamond';
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url('fonts/CormorantGaramond-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2122, U+20AC;
}

@font-face {
  font-family: 'Cormorant Garamond';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('fonts/CormorantGaramond-cyrillic-ext.woff2') format('woff2');
  unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
@font-face {
  font-family: 'Cormorant Garamond';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('fonts/CormorantGaramond-cyrillic.woff2') format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: 'Cormorant Garamond';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('fonts/CormorantGaramond-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2122, U+20AC;
}

@font-face {
  font-family: 'Cormorant Garamond';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('fonts/CormorantGaramond-cyrillic-ext.woff2') format('woff2');
  unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
@font-face {
  font-family: 'Cormorant Garamond';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('fonts/CormorantGaramond-cyrillic.woff2') format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: 'Cormorant Garamond';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('fonts/CormorantGaramond-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2122, U+20AC;
}

@font-face {
  font-family: 'Vasek';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('fonts/Vasek-Italic.ttf') format('truetype');
}

/* ---------- 2. Дизайн-токени ---------- */

:root {
  --ink: #323131;
  --cream: #fffdf8;

  --font-serif: 'Cormorant Garamond', Georgia, 'Times New Roman', serif;
  --font-script: 'Vasek', 'Segoe Script', cursive;

  --page-pad: 24px; /* margin сітки Figma — фіксований, це "поля", не контент-ритм */
  --gutter: 24px;   /* gutter сітки Figma — теж фіксований */
  --header-height: 64px;

  /* Fluid: усі значення задані як % від ширини екрана (vw), точно збігаються
     з Figma (1280×800) саме на 1280px, і масштабуються пропорційно і вгору,
     і вниз. Змінюються на фіксовані лише на планшеті/телефоні (≤1023px),
     де пропорційне масштабування вже зробило б текст нечитабельним. */
  --fs-nav: 0.9375vw;    /* 12px при 1280 */
  --fs-logo: 1.5625vw;   /* 20px при 1280 */
  --fs-meta: 1.25vw;     /* 16px при 1280 */
  /* ОДНА змінна на весь рукописний Vasek-шрифт (hero-headline, portfolio-quote,
     about-eyebrow-label) — раніше було дві окремі (--fs-headline/--fs-quote),
     на десктопі вони завжди були однакові за формулою, але на планшеті випадково
     розійшлись (одну підняли на прохання, другу забули) — весь рукописний текст
     має бути одного розміру на кожному брейкпоінті, тому лишаємо тільки одну. */
  --fs-vasek: min(4.375vw, 64px); /* точно 56px на 1280 */
  --fs-intro: 1.5625vw;  /* 20px при 1280 */
  --fs-label: 12px;      /* дрібний UI-лейбл картки, лишається фіксованим */
  /* окрема категорія — велика серифна ціна ("100€"), використовується
     тільки в price-anchor-section, тому не входить у 4 текстові категорії
     нижче. Стеля за тим самим принципом (×1.5 на 1920), що й інші fluid-
     ширини/розміри на сайті. */
  --fs-price: min(10vw, 192px); /* точно 128px на 1280 */

  /* Line-height — 4 текстові категорії з Figma, задані unitless (без px і
     без vw): unitless line-height множиться на ПОТОЧНИЙ font-size сам по
     собі (як em), тому не треба окремо перераховувати його на кожному
     брейкпоінті — де б не змінився --fs-*, --lh-* лишається тим самим
     співвідношенням. Саме цей приклад — готова "плаваюча одиниця" на
     майбутнє для інших брейкпоінтів. */
  --lh-nav: 1.25;    /* капс 12px / 15px — навігація */
  --lh-intro: 1.2;   /* капс 20px / 24px — лого, заголовки карток */
  --lh-quote: 0.5357;/* Vasek 56px / 30px — рукописні цитати й теги */
  --lh-meta: 1.1875; /* звичайний текст 16px / 19px */
}

/* ---------- 3. Base reset ---------- */

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  position: relative;
  background: var(--cream);
  color: var(--ink);
  font-family: var(--font-serif);
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
}

/* фонова "зерниста" текстура на весь сайт, поверх кремового фону */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  background-image: url('images/texture-cream.jpg');
  background-size: 512px 512px;
  background-repeat: repeat;
  opacity: 0.06;
  pointer-events: none;
  z-index: 0;
}

header {
  position: relative;
  z-index: 10;
}

main {
  position: relative;
  z-index: 1;
}

a {
  color: inherit;
  text-decoration: none;
}

img {
  display: block;
  max-width: 100%;
  height: auto; /* без цього картинки з width/height-атрибутами (для CLS)
    стискаються по ширині через max-width, але лишаються фіксованої
    HTML-висоти — пропорції ламаються (сплюснуте зображення). Елементи
    з власним явним object-fit/height у CSS (footer-photo, portfolio-
    card-image тощо) це правило все одно перебивають своєю вищою
    специфічністю, тут воно — тільки безпечний дефолт. */
}

ul,
p,
h1,
blockquote {
  margin: 0;
}

/* .visually-hidden — для контенту, який має бути в DOM/для скрінрідерів
   і SEO (наприклад h1 сторінки, коли в самому дизайні немає окремого
   текстового заголовка), але візуально на сторінці не показується.
   Стандартний sr-only прийом (не display:none — той ховає і від
   скрінрідерів теж). */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ---------- 4. Header ---------- */

.site-header {
  /* sticky, а не звичайний relative — хедер тепер винесений за межі
     .hero-section (див. HTML) і "приклеєний" до верху вікна на всій
     сторінці, незалежно від того, яка анімація/секція йде під ним */
  position: sticky;
  top: 0;
  z-index: 20; /* вище за sticky-контент нижче (hero-content на телефоні) і portfolio-section */
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  height: var(--header-height);
  padding-inline: var(--page-pad);
  background: var(--cream); /* під хедером далі скролиться контент — фон має бути суцільним, не прозорим */
  border: 0.5px solid var(--ink); /* повна рамка: раніше верхню/бокові грані давав hero-section-обгортка, тепер їх малює сам хедер */
}

/* та сама зерниста текстура, що й на фоні всього сайту — суцільний фон
   вище (background: var(--cream)) сам по собі блокує текстуру body::before
   (position:fixed), тому малюємо власну. z-index: -1 кладе її МІЖ фоном
   .site-header (найнижчий шар його власного stacking context) і
   вмістом (лого/навігація/кнопка — звичайний потік, крок вище), щоб текст
   лишався чітким, а зерно було тільки на фоні. */
.site-header::before {
  content: '';
  position: absolute;
  inset: 0;
  background-image: url('images/texture-cream.jpg');
  background-size: 512px 512px;
  background-repeat: repeat;
  opacity: 0.06;
  pointer-events: none;
  z-index: -1;
}

.nav-menu {
  display: flex;
  align-items: center;
  gap: clamp(16px, 4vw, 96px);
  font-size: var(--fs-nav);
  line-height: var(--lh-nav); /* 12px/15px, категорія "капс 2" з Figma */
  text-align: center;
  white-space: nowrap;
}

.nav-menu a {
  transition: opacity 0.2s ease;
}

.nav-menu a:hover {
  opacity: 0.6;
}

.logo {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  font-size: var(--fs-logo);
  line-height: var(--lh-intro); /* 20px/24px, категорія "капс 1" з Figma */
  white-space: nowrap;
}

.logo-bold {
  font-weight: 700;
}

.cta-button {
  padding: 4px;
  border-bottom: 0.5px solid var(--ink);
  transition: opacity 0.2s ease;
}

/* .cta-button.reveal:hover — деякі кнопки (index.html "записатися" під
   сіткою портфоліо, pro-mene.html "написати мені") мають ще й клас
   .reveal (fade-при-скролі, розділ 15). Коли анімація завершується,
   .reveal.is-visible{opacity:1} (2 класи, специфічність 0,2,0) б'ється
   з .cta-button:hover{opacity:0.6} (теж 0,2,0 — клас+псевдоклас) за
   однакової специфічності, і виграє .reveal.is-visible (він нижче в
   файлі за каскадом) — hover просто переставав щось міняти після
   першого показу. Компаунд-селектор із трьома класами (0,3,0)
   гарантовано переважає незалежно від порядку в файлі. */
.cta-button:hover,
.cta-button.reveal:hover {
  opacity: 0.6;
}

/* та сама специфічність-пастка (0,1,0 проти 0,1,0), тепер із
   transition, а не opacity: .reveal{transition:opacity 0.7s,
   transform 0.7s} нижче в файлі повністю перебиває .cta-button{
   transition:opacity 0.2s} на елементах з обома класами — shorthand
   не мерджиться між правилами, виграє ЦІЛИЙ transition з правила, що
   нижче. Через це hover на "записатися"/"написати мені" відчувався
   як повільний (0.7s замість 0.2s). Явно задаю обидві властивості
   разом на компаунд-селекторі (0,2,0, переважає) — 0.2s для opacity
   (швидкий hover-фідбек), 0.7s для transform лишаю (потрібен для
   плавного fade-in при скролі). */
.cta-button.reveal {
  transition: opacity 0.2s ease, transform 0.7s ease-in-out;
}

/* бургер — прихований на десктопі */
.nav-toggle-checkbox,
.nav-toggle-label,
.mobile-nav {
  display: none;
}

/* той самий hover-прийом, що .nav-menu a (десктопний еквівалент цих
   самих лінків) — пропустила при першій верстці мобільного меню. */
.mobile-nav a {
  transition: opacity 0.2s ease;
}

.mobile-nav a:hover {
  opacity: 0.6;
}

/* поки відкрите мобільне меню — сторінка позаду не скролиться */
body:has(.nav-toggle-checkbox:checked) {
  overflow: hidden;
}

/* ---------- 5. Hero ---------- */

/* .hero-content — sticky "сцена", ПРЯМИЙ сусід .portfolio-section у <main>
   (без обгортки-секції навколо — див. коментар в index.html, чому це
   важливо для анімації накриття нижче). Поки скролиш .hero-scrolljack-
   -wrapper (порожній спейсер перед нею), сцена стоїть на місці
   (top: одразу під хедером), а сам цей скрол script.js переводить у
   горизонтальний translateX .hero-photo-track. Працює однаково на всіх
   розмірах екрана. svh, а не dvh — dvh перераховується прямо під час
   скролу (адресний рядок Safari), через що рух "заїдав".

   border-inline — бокові грані рамки (0.5px), як була в старій
   .hero-section. Верхню грань малює .site-header, нижню (розділову лінію)
   — .portfolio-section (border-top, нижче): вона "їде" разом із блоком,
   що накриває hero, а не лишається нерухомою на місці. */
.hero-content {
  position: sticky;
  top: var(--header-height);
  display: flex;
  flex-direction: column;
  align-items: center;
  height: calc(100vh - var(--header-height));
  height: calc(100svh - var(--header-height));
  padding: 7.5vw var(--page-pad) var(--page-pad); /* 96px зверху (fluid), 24px з боків і знизу — як у Figma */
  overflow: hidden;
  border-inline: 0.5px solid var(--ink);
}

/* Порожній "спейсер" перед .hero-content — тільки висота (= скільки px
   стрічці треба проїхати по горизонталі), без жодного вмісту. script.js
   виставляє точну висоту (travel); тут лишаємо запасне значення на
   випадок, якщо JS ще не встиг порахувати.

   ВАЖЛИВО: .hero-content НЕ вкладена всередину цього спейсера (як було
   раніше) — вона його ПРЯМИЙ сусід. Якби .hero-content лежала всередині
   спейсера-обгортки, "запас", на який вона може лишатись sticky, був би
   обмежений висотою САМЕ ЦІЄЇ обгортки — і анімація накриття (нижче,
   .portfolio-section) не вийшла б плавною: hero-content відліпилась би й
   поїхала звичайним скролом ще ДО того, як portfolio-section встигне
   наїхати зверху. А коли вона прямий сусід .portfolio-section в <main>,
   "запас" на sticky дає вже й висота самого portfolio-section — саме тому
   він встигає плавно накрити застиглий hero, перш ніж той відліпиться. */
.hero-scrolljack-wrapper {
  height: 400vh;
}

.hero-headline {
  font-family: var(--font-script);
  font-style: normal;
  font-weight: 400;
  font-size: var(--fs-vasek);
  line-height: var(--lh-quote); /* 56px/30px, категорія "Vasek" з Figma */
  text-align: center;
}

.hero-headline span {
  display: block;
}

.hero-headline span + span {
  margin-top: 0.3em; /* той самий відступ між рядками, що й у цитати portfolio-section */
}

/* фотострічка — абсолютно центрована по вертикалі всередині hero-content
   (не залежить від висоти заголовка чи meta-рядка — саме тому не "з'їжджає"
   вниз). Ширина екрана — edge-to-edge, gap фіксований 6px як у Figma. На
   великих десктопах більшими стають самі фото (clamp по vw), а не проміжки
   між ними. */
.hero-photo-strip {
  position: absolute;
  top: 50%;
  left: 0;
  transform: translateY(-50%);
  width: 100vw;
  margin-inline: calc(50% - 50vw);
  overflow: hidden;
}

.hero-photo-track {
  display: flex;
  align-items: center;
  gap: 6px;
  width: max-content;
  justify-content: flex-start;
  will-change: transform;
  /* той самий простір, що й gap між фото (6px), з обох країв стрічки —
     перше фото не впирається в край екрана, і останнє має такий самий
     "видих" з іншого боку, коли стрічка доїжджає до кінця. Це просто
     padding на треку — довжина скролу (travel в script.js) рахується від
     track.scrollWidth, який автоматично враховує padding, JS міняти не треба. */
  padding-inline: 6px;
}

.hero-photo {
  display: flex;
  flex-direction: column;
  gap: 6px;
  flex-shrink: 0;
  margin: 0;
}

.hero-photo figcaption {
  font-size: 12px;
  font-weight: 300;
  color: var(--ink);
}

/* ширина = Figma-розмір як мінімум (186/240), росте разом з екраном на десктопі */
.hero-photo--tall {
  width: clamp(186px, 14.5vw, 320px);
}

.hero-photo--tall img {
  width: 100%;
  aspect-ratio: 186 / 240;
  height: auto;
  object-fit: cover;
}

.hero-photo--wide {
  width: clamp(240px, 18.75vw, 410px);
}

.hero-photo--wide img {
  width: 100%;
  aspect-ratio: 240 / 186;
  height: auto;
  object-fit: cover;
}

.hero-meta {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  width: 100%;
  margin-top: auto; /* притискає meta-рядок до низу hero-content незалежно від фотострічки (вона absolute) */
  font-size: var(--fs-meta);
  line-height: var(--lh-meta); /* 16px/19px, категорія "звичайний текст" з Figma */
  font-weight: 300;
  letter-spacing: -0.02em;
}

.hero-meta-links {
  display: flex;
  align-items: baseline;
  gap: 64px; /* точно з Figma (itemSpacing у "contacts"), було 32px */
}

/* лінк "instagram" (не "alicante, spain" — той span, не клікабельний) —
   той самий hover-прийом, що .nav-menu a/.footer-nav a, пропустила при
   першій верстці. */
a.hero-meta-link {
  transition: opacity 0.2s ease;
}

a.hero-meta-link:hover {
  opacity: 0.6;
}

.hero-meta-link--underline {
  text-decoration: underline;
  text-decoration-thickness: 0.5px; /* та сама товщина, що й інші лінії на сайті */
  text-underline-offset: 2px;
}

/* ---------- 6. Portfolio ---------- */

.portfolio-section {
  position: relative;
  overflow: hidden;
  background: var(--cream);
  color: var(--ink);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--page-pad); /* 24px, фіксовано — той самий уніфікований крок між цитатою/діва йдером/сіткою */
  /* верх/низ симетричні — 7.5vw (96px при 1280), той самий відступ, що
     й у заголовка hero. Було: низ фіксовано 24px (margin сітки) — Юля
     попросила зробити відстань від кнопки "ЗАПИСАТИСЯ" до кінця секції
     такою самою, як від верху до цитати. */
  padding: 7.5vw var(--page-pad);
  /* лінія, що відділяє hero від portfolio-section, — раніше це була
     нижня грань .hero-section, тепер верхня грань тут: коли portfolio-section
     "накриває" hero під час скролу (див. .hero-scrolljack-wrapper нижче),
     ця лінія піднімається разом із самим блоком, підкреслюючи його край. */
  border-top: 0.5px solid var(--ink);
}

.portfolio-section::before {
  content: '';
  position: absolute;
  inset: 0;
  background-image: url('images/texture-cream.jpg');
  background-size: 512px 512px;
  background-repeat: repeat;
  opacity: 0.06;
  pointer-events: none;
}

.portfolio-lead,
.portfolio-quote,
.divider-image,
.portfolio-grid {
  position: relative;
  width: 100%;
}

/* група "цитата + divider" (у Figma — безіменний "Frame 1") — власний
   fluid-відступ 48px при 1280 між цими двома елементами */
.portfolio-lead {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3.75vw; /* 48px при 1280 */
}

/* цитата навмисно вужча й центрована (так і в Figma — 575px по центру),
   решта блоків нижче тягнуться на всю ширину секції (margin 24 з обох країв) */
.portfolio-quote {
  font-family: var(--font-script);
  font-style: normal;
  font-weight: 400;
  font-size: var(--fs-vasek);
  line-height: var(--lh-quote); /* 56px/30px, категорія "Vasek" з Figma */
  text-align: center;
  max-width: 46em;
  margin-inline: auto;
}

.portfolio-quote p + p {
  margin-top: 0.3em;
}

/* id="portfolio" сидить на .divider-image (HTML), не на секції й не на
   сітці — клік по "ПОРТФОЛІО" в хедері має приземляти скрол так, щоб
   зверху екрана був сам divider, а картки типів зйомки вже видно нижче —
   на будь-якому пристрої. scroll-margin-top = висота sticky-хедера +
   зовсім невеликий запас (8px, "трохи вище", щоб divider не впирався
   впритул у нижній край хедера).

   Примітка про цитату: gap цитата→divider (.portfolio-lead, 48px при
   1280) менший за висоту хедера (64px) — тому математично неможливо
   ОДНОЧАСНО повністю прибрати цитату з кадру І лишити divider не
   заліпленим хедером (щоб цитата зникла повністю, divider мав би йти
   не нижче 48px від верху, а хедер уже займає перші 64px). Із малим
   запасом (8px) лишається зовсім тонка смужка з останнього рядка цитати
   (~16px) — набагато менше, ніж було з запасом 24px. Якщо й це заважає,
   треба буде або зменшити сам gap 48px, або збільшити його понад 64px —
   звірити з Юлею, який варіант кращий. */
#portfolio {
  scroll-margin-top: calc(var(--header-height) + 8px);
}

/* Кнопка "ЗАПИСАТИСЯ" в хедері (index.html і всі сторінки-альбоми) веде
   сюди замість неіснуючої kontakty.html — той самий прийом компенсації
   sticky-хедера, що #portfolio вище. */
#contact {
  scroll-margin-top: calc(var(--header-height) + 8px);
}

/* декоративний divider (ланцюжок) — на весь екран, edge-to-edge, як фотострічка в hero.
   Пропорції контейнера 1280:160 (8:1) і позиція картинки всередині — точно як у Figma,
   тому картинка масштабується разом з екраном природно, без vw-розрахунків. */
.divider-image {
  aspect-ratio: 1280 / 160;
  width: 100vw;
  margin-inline: calc(50% - 50vw);
  overflow: hidden;
}

.divider-image img {
  position: absolute;
  left: -3.11%;
  top: -103.31%;
  width: 106.22%;
  height: 282.78%;
  max-width: none;
  object-fit: cover;
}

.portfolio-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: var(--gutter);
}

.portfolio-card {
  display: flex;
  flex-direction: column;
  gap: 32px;
}

.portfolio-card-text {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.portfolio-card-title {
  font-family: var(--font-serif);
  font-weight: 500;
  font-size: var(--fs-intro); /* 20px при 1280, fluid */
  line-height: var(--lh-intro); /* 20px/24px, категорія "капс 1" з Figma */
  text-transform: uppercase;
}

.portfolio-card-desc {
  font-family: var(--font-serif);
  font-weight: 300;
  font-size: var(--fs-meta); /* 16px при 1280, fluid */
  line-height: var(--lh-meta); /* 16px/19px, категорія "звичайний текст" з Figma (було 1.4 — довільне значення) */
  text-align: justify;
  max-width: 92%; /* легкий інсет справа, як у Figma */
}

/* посилання і анімація — тільки на самому фото, текст не клікабельний і не тригерить hover.
   Напис "дивитися галерею" видно завжди (не тільки на hover) — саме для мобільних,
   де нема наведення і людині треба явно показати, що фото клікабельне.
   .price-card-image (сторінка цін, розділ 17) — Юля попросила той самий
   клікабельний перехід у галерею для карток цін, тому розширюю ці самі
   селектори замість дубля правил. */
.portfolio-card-image,
.price-card-image {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  padding-block: 16px;
  position: relative;
  width: 100%;
  aspect-ratio: 290 / 390; /* точний розмір з Figma — і збігається з тим, що grid і так розтягує картку до 290px на 1280 */
  overflow: hidden;
}

.portfolio-card-image img,
.price-card-image img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.4s ease;
}

/* "історія кохання" (портфоліо-картка): пробувала прибрати засвічене небо
   CSS-кропом — прибрати його ПОВНІСТЮ і водночас не чіпати боки виявилось
   математично несумісним для цих пропорцій картки (290×390, вужча за фото
   520×780 — щоб прибрати більше зверху без кропу боків, просто нема "звідки
   взяти" зайву висоту). Юля вирішила закинути в images/ вже готове,
   самостійно обрізане фото під потрібний кадр — тому тут свідомо НІЯКОГО
   спеціального object-position/кропу нема, звичайний object-fit:cover
   (спільне правило .portfolio-card-image img вище) сам заповнить рамку. */

.portfolio-card-cta {
  position: relative;
  color: var(--cream);
  font-family: var(--font-serif);
  font-weight: 300;
  font-size: var(--fs-meta);
  line-height: var(--lh-meta); /* 16px/19px, категорія "звичайний текст" з Figma */
  text-decoration: underline;
  text-decoration-thickness: 0.5px;
  text-underline-offset: 2px;
}

.portfolio-card-image:hover img,
.price-card-image:hover img {
  transform: scale(1.04);
}

/* кнопка "записатися" під сіткою карток — з Figma: по центру, 186px на
   1280. Використовує вже наявний .cta-button (той самий "примарний" стиль —
   тільки нижня рамка, без заливки, — що в хедері), тут лише модифікатор
   для розкладки (центрування, ширина). .portfolio-section сам flex-
   контейнер із gap:24px між дітьми (той самий 24px, що і в Figma) —
   Юля попросила зробити відстань саме від сітки фото до цієї кнопки
   вдвічі більшою (48px на 1280), не займаючи решту гепів усередині
   секції (цитата→дівайдер, дівайдер→сітка) — тому НЕ через сам section
   gap (він спільний на всі проміжки), а через додатковий margin-top
   ТІЛЬКИ на кнопці, поверх наявного 24px gap. */
.portfolio-cta-button {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 14.53125vw; /* 186px на 1280 — росте разом з екраном */
  height: 44px; /* у Figma фіксована (Fixed size, не Hug) — тому НЕ vw, стала на будь-якому екрані */
  margin-inline: auto;
  text-align: center;
  /* без цього кнопка просто успадковувала розмір від батька (нічим не
     керований збіг) — у Figma тут точно 20px, капс-токен var(--fs-intro)
     (той самий, що лого в хедері й заголовки карток), НЕ var(--fs-meta) —
     мала цю помилку раніше, Юля виправила напряму розмірами. */
  font-size: var(--fs-intro);
  line-height: var(--lh-intro);
  text-transform: uppercase; /* забула перенести з видаленого .about-cta-button — текст у HTML навмисно малими літерами */
}

/* .portfolio-section .portfolio-cta-button — НЕ просто .portfolio-cta-button:
   той самий клас використовується і на сторінках-альбомах (у комбінації
   з .album-cta-button, розділ 14), там ця добавка не потрібна — тому
   звужую селектор до батька. Додаткові 24px (24/1280=1.875vw), стеля на
   1920 (24×1.5=36px) — той самий принцип "стелі", що й скрізь на сайті:
   разом із наявним gap:24px секції дає 48px на 1280, до 60px на 1920.
   На планшеті/телефоні Юля попросила лишити як було — скидаю назад у
   нуль у спільному @media(max-width:1023px) нижче. */
.portfolio-section .portfolio-cta-button {
  margin-top: min(1.875vw, 36px);
}

/* ---------- 7. Про мене ----------
   Перший темний блок на сайті — кольори свідомо інвертовані відносно
   решти сторінки (фон var(--ink), текст var(--cream)), інакше все ті самі
   токени й ритм: 96px зверху/знизу (7.5vw, як у portfolio-section), той
   самий текстурний ::before, той самий fs-quote для рукописного тега. */
.about-section {
  position: relative;
  background: var(--ink);
  color: var(--cream);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 48px; /* було 32px, Юля змінила в Figma */
  padding: 7.5vw var(--page-pad);
}

/* нове фото-фон (хвилі на скелях) поверх зернистої текстури, під реальним
   контентом — має бути ПЕРШОЮ реальною дитиною секції (не ::after: псевдо
   ::after завжди йде ПІСЛЯ всіх дітей у порядку відмальовки, а тут потрібен
   шар МІЖ текстурою (::before) і текстом). position:relative-контент нижче
   (той самий прийом, що з .about-section::before) природно опиняється над
   цим шаром за порядком у DOM. */
.about-bg-photo {
  position: absolute;
  inset: 0;
  background-image: url('images/about-bg-waves.jpg');
  background-size: cover;
  background-position: center;
  opacity: 0.2;
  pointer-events: none;
}

/* та сама техніка, що в .portfolio-section (НЕ як у .site-header): тут
   .about-section не має власного z-index, тому НЕ утворює свій stacking
   context. У .site-header z-index:-1 на псевдоелементі спрацював, бо в
   header є свій z-index:20; тут без цього z-index:-1 "провалював" текстуру
   під непрозорий чорний фон секції — шуму не було видно взагалі. Замість
   негативного z-index — звичайні (не absolute) діти секції нижче отримують
   свій `position: relative`, тому природно опиняються "над" псевдоелементом
   за порядком у DOM (той самий прийом, що portfolio-lead/portfolio-quote
   і т.д. у portfolio-section). */
.about-section::before {
  content: '';
  position: absolute;
  inset: 0;
  background-image: url('images/texture-cream.jpg');
  background-size: 512px 512px;
  background-repeat: repeat;
  opacity: 0.06;
  pointer-events: none;
}

/* маленький рукописний тег, приколотий трохи зсунутим і нахиленим над фото
   (не по центру всієї секції) — той самий fs-quote і script-шрифт, що в
   hero. top трохи більший за Figma-значення (71px→85px при 1280) —
   rotated-bbox у браузері вийшла меншою за фігмівську, довелось додати,
   щоб тег реально ліг на фото, а не просто торкався краю. */
.about-eyebrow-label {
  /* координати — не % від секції, а % від САМОЇ фото-рамки
     (.about-photo-frame, position:relative нижче) — порахувала через
     absoluteTransform у Figma: центр тега лежить рівно на 8.5px правіше і
     6.3px нижче лівого верхнього кута рамки (186×241), звідси 4.57% / 2.62%.
     Тег тепер завжди прив'язаний до фото, а не до ширини секції. */
  position: absolute;
  z-index: 2; /* явно вище за .about-photo-image — без двозначності в порядку малювання */
  left: 4.57%;
  top: 2.62%;
  transform: translate(-50%, -50%) rotate(-6deg);
  margin: 0;
  font-family: var(--font-script);
  font-weight: 400;
  /* var(--fs-vasek) — той самий токен, що hero-headline/portfolio-quote,
     увесь рукописний Vasek-текст сайту одного розміру на кожному
     брейкпоінті. Текст НЕ прив'язаний до розміру фото формулою — і те,
     і те просто fluid кожне по-своєму, як і скрізь на сайті. */
  font-size: var(--fs-vasek);
  line-height: var(--lh-quote); /* 56px/30px, категорія "Vasek" з Figma */
  white-space: nowrap;
}

.about-portrait {
  position: relative; /* див. коментар над .about-section::before */
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 24px; /* було 16px, Юля змінила в Figma */
}

.about-photo-frame {
  position: relative; /* точка відліку для .about-eyebrow-label */
  display: flex;
  flex-direction: column;
  align-items: center;
  margin: 0;
  /* точний розмір з Figma: 14.53125vw = рівно 186px на 1280 (було 184,
     Юля трохи обрізала фото — рамка на 2px ширша). Напис "YULIA HAVRYLOVA"
     під фото переноситься на 2 рядки, якщо не влазить — вирішуємо на
     самому напису (див. .about-photographer-name нижче), а не роздуванням
     фото. */
  width: 14.53125vw;
}

/* тепер контейнер із overflow:hidden, а не просто img з object-fit:cover —
   Юля зробила в Figma ручний crop/zoom (не центрований), точні відсотки
   нижче порахувала з transform-матриці фотозаливки (scaleX/scaleY і
   зсуви), а не вгадала на око. */
.about-photo-image {
  position: relative;
  width: 100%;
  aspect-ratio: 186 / 234;
  overflow: hidden;
}

/* легкий градієнт знизу — щоб напис "YULIA HAVRYLOVA" (нахлест -0.6em
   у .about-photographer-name нижче) краще читався на фото. Пседоелемент
   у %-величинах від висоти самого фото-контейнера — масштабується разом
   з фото на будь-якому брейкпоінті, окремо підлаштовувати під мобільний/
   планшет не треба. */
.about-photo-image::after {
  content: "";
  position: absolute;
  inset: auto 0 0 0;
  height: 30%;
  background: linear-gradient(to bottom, rgba(50, 49, 49, 0) 0%, rgba(50, 49, 49, 0.8) 100%);
  pointer-events: none;
}

.about-photo-image img {
  position: absolute;
  /* нове фото (0-29.jpg, 4306×6459) — кроп порахований так само не "на
     око", а виміряний: через canvas знайшла яскравісну межу, де починається
     чорна спідниця (різкий перепад ~118→~69 з висоти картинки, приблизно
     3650px), і горизонтальні межі силуету (~1100–2650px). Перша версія
     різала рівно по талії (3650px) — Юля попросила лишити трохи спідниці,
     тому вікно кропу тепер трохи нижче: від верху голови (1150px, із
     запасом) до 4000px (~350px спідниці видно), по центру силуету. */
  top: -40.35%;
  left: -32.77%;
  width: 190.08%;
  height: 226.63%;
  max-width: none;
  object-fit: cover;
  filter: grayscale(1); /* фото кольорове — переводимо у чорно-білий стиль макета фільтром, як у стосу раніше */
}

/* підпис-нашивка внахлест на нижній край фото (margin-top від'ємний —
   той самий прийом, що mb:-6px на фото в Figma, тільки з іншого боку) */
.about-photographer-name {
  /* position:relative — без цього <img> (replaced-елемент) малюється
     ПІЗНІШЕ за звичайний блоковий <figcaption> у порядку відмальовки
     (окремий крок для "заміщених" елементів у CSS2.1), навіть якщо img
     стоїть раніше в DOM — фото просто перекривало верх літер імені.
     position:relative виводить підпис у "свій" шар малювання, і він
     однозначно лягає зверху. */
  position: relative;
  /* em, не px: розмір шрифту fluid (var(--fs-intro)) і зменшується разом
     з екраном, а px-відступ лишався б сталим — тоді на менших екранах
     нахлест "з'їдав" би більшу частку висоти літер, і напис підіймався б
     вище за фото, ніж мав би. -0.6em масштабується разом зі шрифтом, тому
     пропорція нахлесту (половина висоти літер на фото) лишається однаковою
     на будь-якому розмірі екрана. */
  margin: -0.6em 0 0;
  line-height: 1;
  font-family: var(--font-serif);
  font-weight: 400;
  /* var(--fs-intro) — той самий токен, що лого в хедері й заголовки карток
     портфоліо: увесь капс-текст на сайті одного розміру й масштабується
     однаково. Не прив'язуємо до розміру фото. */
  font-size: var(--fs-intro);
  text-align: center;
  /* ширина = ширині фото (photo-frame), а не "скільки влізе" — інакше
     на інших системах/браузерах шрифт може порахувати текст трохи
     ширшим за фото через різницю в шрифтових метриках. white-space:nowrap
     прибрала — з жорсткою шириною рядок і так не мав переноситись при
     нормальних розмірах, а якщо колись не влізе, краще перенос, ніж
     вихід за межі фото. */
  width: 100%;
}

.about-photographer-name b {
  font-weight: 700;
}

.about-quote-text {
  /* стеля піднята з 394px (застигало на 1280) до 591px (застигає на 1920 —
     поширений великий монітор) — шрифт (--fs-meta) сам необмежено росте
     разом з екраном, тож колонка тексту має рости з ним у парі, інакше на
     великому екрані виходить вузька колонка з великими літерами. За 1920 —
     заморожено, щоб на 4K+ не роздувало до абсурду. 591 = 394×(1920/1280). */
  width: min(30.78vw, 591px);
  margin: 0;
  font-family: var(--font-serif);
  font-weight: 300;
  /* var(--fs-meta) — той самий токен, що звичайний текст скрізь на сайті
     (hero-meta-text, portfolio-card-desc). */
  font-size: var(--fs-meta);
  line-height: var(--lh-meta); /* 16px/19px, категорія "звичайний текст" з Figma (було 1.4 — довільне значення) */
  text-align: justify;
}

.about-more-link {
  position: relative; /* див. коментар над .about-section::before */
  font-family: var(--font-serif);
  font-weight: 300;
  font-size: var(--fs-meta);
  line-height: var(--lh-meta); /* 16px/19px, категорія "звичайний текст" з Figma */
  text-decoration: underline;
  text-decoration-thickness: 0.5px;
  text-underline-offset: 3px;
  transition: opacity 0.2s ease;
}

.about-more-link:hover {
  opacity: 0.6;
}

/* ---------- 8. Принципи ----------
   Figma node 295:419 (принципи роботи: сценарій / не постановка / комфорт),
   1280: 3 колонки в ряд, py 96px (fluid, той самий ритм, що portfolio-
   -section/about-section вище), px 24px (page-pad, фіксовано, як усюди).

   ДВІ речі тут критичні для коректного накриття застиглого sticky hero
   (той самий механізм, що й portfolio-section/about-section вище):
   1. position:relative — без нього секція потрапляє в "непозиціоновану"
      групу елементів, яку браузер малює РАНІШЕ за позиціоновані
      (.hero-content: position:sticky), незалежно від порядку в DOM.
   2. background — сам по собі коректний порядок малювання не рятує, якщо
      секція прозора: тоді крізь неї просто видно те, що намальовано під
      нею (hero-фотострічку). Це і був реальний баг: position:relative тут
      стояв правильно з самого початку, фотографії однаково просвічували,
      бо я забула background — секція була прозорою "дірою". */
.principles-section {
  position: relative;
  background: var(--cream);
  display: flex;
  justify-content: center;
  padding: 7.5vw var(--page-pad);
}

/* та сама зерниста текстура, що на всіх кремових ділянках сайту */
.principles-section::before {
  content: '';
  position: absolute;
  inset: 0;
  background-image: url('images/texture-cream.jpg');
  background-size: 512px 512px;
  background-repeat: repeat;
  opacity: 0.06;
  pointer-events: none;
}

/* position:relative — над ::before-текстурою, той самий прийом, що
   portfolio-lead/about-portrait. gap між колонками — фіксований 50px, не
   vw: та сама логіка, що gap рядка в portfolio-grid/hero-meta-links — це
   проміжок між елементами одного рівня, не вертикальний "ритм" секції
   (96/48-подібний), тому не масштабую. */
.principles-list {
  position: relative;
  display: flex;
  gap: 50px;
}

.principle-item {
  display: flex;
  flex-direction: column;
  gap: 16px;
  /* у Figma колонки трохи різні (290/291/290 — округлення від поділу
     ширини на 3), візуально нерозрізнима різниця, тому одне спільне
     значення на всі три: 290px при 1280 = 22.65625vw, росте/стискається
     разом з екраном на десктопі (як about-quote-text вище). Стеля
     обов'язкова (той самий прийом, що .about-quote-text/.testimonial-card
     нижче) — без неї на екранах ширших за 1280 колонка росте необмежено й
     переростає навіть 394px-блоки (про мене/відгуки), ламаючи пропорцію
     394/394/291, яку Юля виміряла по сітці на 1280. Стеля піднята до 435px
     (застигає на 1920, не на 1280) — та сама логіка, що в about-quote-text:
     шрифт росте необмежено, колонка має рости з ним у парі. 435 =
     290×(1920/1280). */
  width: min(22.65625vw, 435px);
}

.principle-title {
  font-family: var(--font-serif);
  font-weight: 500;
  font-size: var(--fs-intro); /* 20px при 1280, fluid — той самий капс-токен, що заголовки карток портфоліо */
  line-height: var(--lh-intro);
  text-transform: uppercase;
}

.principle-text {
  font-family: var(--font-serif);
  font-weight: 300;
  font-size: var(--fs-meta); /* 16px при 1280, fluid */
  line-height: var(--lh-meta);
  text-align: justify;
}

/* ---------- 9. Відгуки ----------
   Figma-нода testimonial-card-liuba (299:462): одна картка відгуку клієнтки
   на тлі фото. Це слайд майбутньої каруселі — поки відгук лише один, тому
   .testimonial-nav (стрілки внизу картки) — суто декоративні, без обробників. */
.testimonials-section {
  position: relative;
  overflow: hidden; /* ріже фон-фото — воно навмисно більше за секцію, див. кроп нижче */
  background: var(--cream);
  display: flex;
  justify-content: center;
  padding: 7.5vw var(--page-pad); /* той самий вертикальний ритм 96px при 1280, що в інших секціях */
}

/* фон-фото на весь блок. За замовчуванням — звичайний object-fit:cover
   (так у Figma задані фото Діани й Анжеліки: просто "cover", без жодного
   ручного зсуву). Люба — виняток: .testimonial-bg-img--liuba нижче. */
.testimonial-bg-photo {
  position: absolute;
  inset: 0;
  overflow: hidden; /* ріже й фото (воно навмисно більше за секцію в Люби), і 16px зсув анімації перемикання нижче */
  background: var(--ink); /* підстраховка на час зсуву фото між слайдами — темний, не білий, край */
}

.testimonial-bg-photo img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Люба — єдина з трьох, де в Figma фото навмисно більше за рамку й
   зсунуте (не проста "cover"): точні відсотки порахувані з
   transform-матриці фотозаливки, той самий прийом, що .about-photo-image.
   Клас перемикає script.js разом зі зміною src при кожному свайпі/кліку
   стрілки — коли активна Люба, замінює звичайний cover на цей ручний кроп.

   БАГ, який тут був: селектор `.testimonial-bg-img--liuba` (0 типів, 1
   клас) має НИЖЧУ специфічність за `.testimonial-bg-photo img` вище
   (1 тип + 1 клас) — тому базове правило завжди перемагало, незалежно
   від порядку в файлі, і Люба замість свого кропу мовчки показувала
   звичайний object-fit:cover (фото просто розтягувалось на контейнер).
   Додала `img` перед класом — тепер той самий 1 тип + 1 клас, що в
   базового правила, і виграє явний порядок (цей блок стоїть нижче). */
img.testimonial-bg-img--liuba {
  left: -0.01%;
  top: -128.86%;
  width: 100%;
  height: 357.5%;
  max-width: none;
}

/* сама картка: 604px при 1280 у Figma. Падінг (105px×2=210px) фіксований —
   тому картку не можна масштабувати як самостійний "X vw" (перша спроба
   так і зробила: підняла стелю картки пропорційно, 604×1.5=906 — і текст
   усередині (906-210=696px) вийшов ширшим за about-quote-text (591px),
   хоча обидва мають бути тим самим "394-категорії" текстом). Правильно —
   рахувати від ТЕКСТУ: він має рости з тим самим 30.78vw, що
   .about-quote-text (тому й `calc(30.78vw + 210px)`, не свій окремий
   47.1875vw), а фіксовані 210px падінгу просто додаються зверху. Стеля
   801px = 591 (стеля тексту, той самий, що в about-quote-text) + 210. На
   1280: 30.78vw=394, +210=604 — точно Figma-значення, як і було. */
.testimonial-card {
  position: relative;
  z-index: 1; /* над .testimonial-bg-photo */
  /* overflow:hidden свідомо НЕ ставлю тут (пробувала — зрізало верхній
     звис .decor-washi-tape, вона навмисно наполовину висить НАД краєм
     картки, від'ємний top, див. коментар над .decor-washi-tape нижче).
     Виліт тега-цитати за край під час анімації виправлений інакше —
     окремими keyframes, які не стирають його власний transform, тому
     цей overflow тут більше не потрібен як "запобіжник". */
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 28px;
  width: min(calc(30.78vw + 210px), 801px);
  padding: 96px 105px;
}

/* напівпрозора кремова "підкладка" картки — окремий шар під текстурою
   (::before малюється найпершим, тобто найнижчим шаром). */
.testimonial-card::before {
  content: '';
  position: absolute;
  inset: 0;
  background: rgba(255, 253, 248, 0.7);
}

/* зерниста текстура поверх підкладки — та сама, що на кремовому фоні
   всього сайту. Звичайний div, а не ::after: ::after малюється ПІСЛЯ
   дітей елемента (тобто поверх тексту картки), а тут потрібен шар МІЖ
   ::before і текстом — тому це реальний перший child (той самий прийом,
   що .about-bg-photo). Решта дітей нижче мають власний position:relative,
   тому природно лягають зверху над обома цими шарами. */
.testimonial-card-texture {
  position: absolute;
  inset: 0;
  background-image: url('images/texture-cream.jpg');
  background-size: 512px 512px;
  background-repeat: repeat;
  opacity: 0.06;
  pointer-events: none;
}

/* стрічка-скотч зверху картки — у Figma це сусід картки (окремий шар
   поверх усього блока), але прив'язана вона саме до верхнього краю картки
   (наполовину звисає над ним), тому як CSS-дитину картки її прикріпити
   простіше й надійніше (від'ємний top), ніж рахувати позицію від усієї
   секції, яка ще й міняє висоту між брейкпоінтами. Через це в картки
   свідомо НЕМАЄ overflow:hidden — інакше стрічку зрізало б по її верхньому
   краю. */
.decor-washi-tape {
  position: absolute;
  left: 50%;
  top: -32px;
  transform: translateX(-50%);
  width: 199px;
  pointer-events: none;
}

.testimonial-header,
.testimonial-divider,
.testimonial-quote,
.testimonial-tag,
.testimonial-nav {
  position: relative; /* над ::before і .testimonial-card-texture, той самий прийом, що в about-section */
}

.testimonial-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  width: 100%;
}

.testimonial-name {
  margin: 0;
  font-family: var(--font-script);
  font-weight: 400;
  font-size: var(--fs-vasek);
  line-height: var(--lh-quote); /* 56px/30px, категорія "Vasek" з Figma */
  white-space: nowrap;
}

.star-rating {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
}

.icon-star {
  width: 28px;
  height: 28px;
}

.testimonial-divider {
  width: 100%;
  border-top: 0.5px solid var(--ink); /* та сама товщина ліній, що скрізь на сайті (site-header, cta-button) */
}

/* min-height — фіксує однакову висоту цитати незалежно від того, на
   скільки рядків розбилась КОНКРЕТНА цитата (у різних відгуків різна
   довжина тексту): виміряла реальну кількість рядків для всіх трьох
   відгуків на 1280/1024 (усюди 3 рядки, збігається саме тут) — без
   цього картка при перемиканні відгуку "стрибала" по висоті, і разом з
   нею стрибали стрілки під цитатою. em, не px — рахується від
   ВЛАСНОГО font-size елемента (той самий var(--lh-meta), що вже задає
   line-height), тому лишається коректним і на fluid-шрифті десктопа, і
   на фіксованому мобільному/планшетному (там своя, більша кількість
   рядків — окремий override у телефонному медіа-запиті нижче). */
.testimonial-quote {
  margin: 0;
  width: 100%;
  min-height: calc(var(--lh-meta) * 3em); /* 3 рядки — максимум на десктопі/планшеті */
  font-family: var(--font-serif);
  font-weight: 300;
  font-size: var(--fs-meta); /* 16px при 1280 — той самий токен "звичайного тексту", що всюди на сайті */
  line-height: var(--lh-meta);
  text-align: justify;
}

/* рукописний тег "сiмейна iсторiя" — той самий принцип, що
   .about-eyebrow-label: координати не на око, а з absoluteTransform у
   Figma (центр тега відносно рамки картки 604×363), переведені у % від
   картки — лишається на своєму місці на будь-якому розмірі картки.
   Перевірено метадатою (get_metadata) для всіх трьох відгуків окремо
   (Люба/Діана/Анжеліка) — центр тега скрізь виходить тим самим
   ~78.3%/81.42%, тому одне спільне правило підходить усім трьом, без
   перемикання класу при зміні відгуку. У Vasek немає української "і" —
   тому "iсторiя"/"iндивiдуальна" з латинською i. */
.testimonial-tag {
  position: absolute;
  left: 78.24%;
  top: 81.42%;
  transform: translate(-50%, -50%) rotate(-6deg);
  margin: 0;
  font-family: var(--font-script);
  font-weight: 400;
  font-size: var(--fs-vasek);
  line-height: var(--lh-quote);
  white-space: nowrap;
}

/* стрілки каруселі — раніше суто декоративна картинка, тепер дві реальні
   кнопки. Іконки — це той самий Figma-асет icon-carousel-nav.svg, просто
   розрізаний на 2 файли по проміжку, що вже був між стрілками в оригіналі
   (icon-arrow-prev.svg/icon-arrow-next.svg, path — 1:1 з Figma, нічого не
   малювала вручну). gap:16px — той самий проміжок, що був між двома
   групами в оригінальному SVG (44.5-28.5=16 у координатах іконки, там
   1 unit = 1px). */
.testimonial-nav {
  display: flex;
  align-items: center;
  gap: 16px;
}

.testimonial-nav-btn {
  display: flex;
  padding: 0;
  border: none;
  background: none;
  cursor: pointer;
  transition: opacity 0.2s ease;
}

.testimonial-nav-btn:hover {
  opacity: 0.6;
}

.testimonial-nav-btn img {
  display: block;
  width: 28.5px;
  height: auto;
}

/* зміна тексту/фото при перемиканні відгуку (script.js) — напрямлений
   "свайп": елемент трохи зсувається і притлумлюється (НЕ до 0 — щоб
   ніколи не було моменту голого блідого фону, саме це й муляло ока в
   першій версії на самій лише opacity:0), тоді підміняється текст/src,
   і новий вміст заїжджає з протилежного боку назад на місце. Напрямок
   (next/prev) задає сам виклик у script.js (клік/стрілка клавіатури/
   свайп уже знають, куди йдуть — рахувати його заново з indexів не
   треба). animation, не transition — так JS може гарантовано
   перезапустити той самий keyframe навіть при швидких повторних кліках
   (transition цього не вміє: однакове кінцеве значення класу вдруге
   просто нічого не змінює). */
@keyframes testimonial-slide-out-next {
  to { opacity: 0.3; transform: translateX(-16px); }
}

@keyframes testimonial-slide-out-prev {
  to { opacity: 0.3; transform: translateX(16px); }
}

@keyframes testimonial-slide-in-next {
  from { opacity: 0.3; transform: translateX(16px); }
  to { opacity: 1; transform: translateX(0); }
}

@keyframes testimonial-slide-in-prev {
  from { opacity: 0.3; transform: translateX(-16px); }
  to { opacity: 1; transform: translateX(0); }
}

/* БАГ, який тут був: .testimonial-tag уже має власний постійний
   transform (translate(-50%,-50%) rotate(-6deg) — центрування й нахил
   рукописного тега). Keyframes вище просто ПИШУТЬ transform:translateX(),
   а не додають його — властивість transform не підсумовується, друге
   значення повністю замінює перше. Тому під час анімації тег на мить
   втрачав і центрування, і нахил, їхав як звичайний нерухомий
   горизонтальний текст і вилазив за праву межу картки. Рішення — окремі
   keyframes ТІЛЬКИ для тега, де в transform явно повторений його базовий
   translate+rotate, а translateX(±16px) дописаний ПЕРШИМ у списку (тому
   застосовується останнім, уже в екранних координатах — зсуває картинку
   вбік, а не "в системі координат" повернутого тега). script.js вибирає
   цей набір keyframes саме для тега, інші три елементи (фото/ім'я/
   цитата) використовують набір вище — у них власного transform нема. */
@keyframes testimonial-tag-slide-out-next {
  to { opacity: 0.3; transform: translateX(-16px) translate(-50%, -50%) rotate(-6deg); }
}

@keyframes testimonial-tag-slide-out-prev {
  to { opacity: 0.3; transform: translateX(16px) translate(-50%, -50%) rotate(-6deg); }
}

@keyframes testimonial-tag-slide-in-next {
  from { opacity: 0.3; transform: translateX(16px) translate(-50%, -50%) rotate(-6deg); }
  to { opacity: 1; transform: translateX(0) translate(-50%, -50%) rotate(-6deg); }
}

@keyframes testimonial-tag-slide-in-prev {
  from { opacity: 0.3; transform: translateX(-16px) translate(-50%, -50%) rotate(-6deg); }
  to { opacity: 1; transform: translateX(0) translate(-50%, -50%) rotate(-6deg); }
}

/* елементи, які JS анімує вище (bg-фото/ім'я/цитата/тег) — сам keyframe
   задається інлайн через el.style.animation, тут лише підказка браузеру
   заздалегідь підготувати композитний шар під opacity/transform. */
.testimonial-fade {
  will-change: opacity, transform;
}

/* ---------- 10. Ціна-анкор ----------
   Figma-нода price-anchor-section (523:49, новий дизайн-напрямок — стара
   нода 374:203 із таблицею колонок більше не використовується): рукописний
   Vasek "зйомка вiд" + велика серифна "100€", тонка горизонтальна риска,
   3-рядковий текстовий блок (жирний фрагмент + звичайний), підкреслений
   лінк на tsiny.html. py 96px (fluid, той самий ритм, що всі секції
   вище), px 24px (page-pad), gap між заголовком/рискою/текстом/лінком —
   фіксований 32px (той самий проміжок, що в faq-section, це не "ритм"
   секції, а власний gap контейнера). */
.price-anchor-section {
  position: relative;
  background: var(--cream);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 32px;
  padding: 7.5vw var(--page-pad);
  /* верхня риска-розділювач із самою секцією (у Figma border-t на
     контейнері price-anchor-section, не окремий елемент) */
  border-top: 0.5px solid var(--ink);
}

/* та сама зерниста текстура, що на всіх кремових секціях сайту */
.price-anchor-section::before {
  content: '';
  position: absolute;
  inset: 0;
  background-image: url('images/texture-cream.jpg');
  background-size: 512px 512px;
  background-repeat: repeat;
  opacity: 0.06;
  pointer-events: none;
}

.price-headline-group {
  position: relative; /* над ::before-текстурою */
  display: flex;
  flex-direction: column;
  align-items: center;
}

.price-headline-label {
  /* Figma дає -20px, але це значення розраховане для тексту, ЗРІЗАНОГО
     до cap-height/baseline (text-box-trim), а в звичайному CSS рядок несе
     ще й "повітря" шрифту над/під літерами (ascent/descent за метриками
     самого файла) — той самий -20px тут виглядає як величезний проміжок.
     Порахувала реальний потрібний відступ через точні метрики шрифту
     (fontTools: sCapHeight=0.625em, hhea ascent=0.924em для Cormorant
     Garamond; baseline "100€" = верх його рядка + (ascent-capHeight)),
     щоб візуальна відстань між базовою лінією "зйомка вiд" і верхом
     цифр "100€" вийшла тими самими -20px, що в Figma. em — не px, той
     самий принцип, що margin-top у about-photographer-name.
     Юля попросила опустити "100€" ще на пару px нижче за цей розрахунок
     (-0.9911em → -0.9375em, тобто +3px при 56px) — суто на око, поверх
     точного Figma-значення. */
  margin: 0 0 -0.9375em;
  font-family: var(--font-script);
  font-weight: 400;
  font-size: var(--fs-vasek);
  line-height: var(--lh-quote); /* 56px/30px, категорія "Vasek" з Figma */
  text-align: center;
}

.price-headline-value {
  /* line-height:normal при 128px несе величезний "хвіст" знизу (descent
     шрифту) ВСЕРЕДИНІ власного блоку, перед тим як почнеться gap:32px до
     наступного елемента (риски) — реальна видима відстань виходила ~69px
     (37px невидимого "повітря" + 32px gap), тоді як в інших сусідніх пар
     елементів того самого gap:32px шрифт дрібний і майже без цього
     "повітря", тому вони виглядали набагато ближче одне до одного.
     margin-bottom: -0.287em — це РІВНО descent-метрика самого файлу
     шрифту (fontTools: sTypoDescender/unitsPerEm = -287/1000), тобто
     "зрізає" саме ту невидиму частину, не більше й не менше — після
     цього riska опиняється рівно на gap:32px від справжньої видимої
     нижньої межі "100€", як і всюди інде. */
  margin: 0 0 -0.287em;
  font-family: var(--font-serif);
  font-weight: 300;
  font-size: var(--fs-price); /* 128px при 1280, унікальна категорія, див. :root */
  line-height: normal; /* у Figma leading-[normal], не одна з 4 стандартних категорій */
  text-align: center;
}

/* горизонтальна риска під заголовком — у Figma окремий SVG-асет (просто
   пряма лінія), тут звичайний border-top, той самий підхід, що вже
   скрізь на сайті (FAQ, header, сама секція). Ширина — та сама формула,
   що .testimonial-card/.faq-list (604px на 1280, стеля 801px на 1920) —
   той самий "604-категорії" контент-блок, звірено get_metadata (523:66
   має буквально ту саму ширину 604, що список специфікацій мав раніше). */
.price-divider {
  width: min(calc(30.78vw + 210px), 801px);
  border-top: 0.5px solid var(--ink);
}

.price-specs-text {
  position: relative; /* над ::before-текстурою */
  text-align: center;
}

.price-specs-text p {
  margin: 0;
  font-family: var(--font-serif);
  font-weight: 300;
  font-size: var(--fs-meta); /* 16px при 1280, той самий токен "звичайного тексту" */
  line-height: var(--lh-meta);
}

.price-specs-highlight {
  font-weight: 600; /* Cormorant Garamond SemiBold з Figma — той самий variable-font файл, вага в межах 300–700 */
}

/* той самий підкреслений лінк, що about-more-link (0.5px риска, offset
   3px, приглушення на hover) — один спільний прийом для всіх текстових
   CTA-посилань на сайті. */
.price-cta-link {
  position: relative; /* над ::before-текстурою */
  font-family: var(--font-serif);
  font-weight: 300;
  font-size: var(--fs-meta);
  line-height: var(--lh-meta);
  text-decoration: underline;
  text-decoration-thickness: 0.5px;
  text-underline-offset: 3px;
  transition: opacity 0.2s ease;
}

/* .price-cta-link.reveal:hover — та сама специфічність-пастка, що
   .cta-button.reveal:hover вище (розділ 4): цей лінк теж має .reveal
   ("пакети й що входить"), і .reveal.is-visible переважав hover після
   завершення fade-анімації. */
.price-cta-link:hover,
.price-cta-link.reveal:hover {
  opacity: 0.6;
}

/* та сама transition-пастка, що .cta-button.reveal вище (розділ 4) —
   .reveal{transition:opacity 0.7s...} перебивав власний 0.2s лінка
   на елементах з обома класами, hover відчувався повільним. */
.price-cta-link.reveal {
  transition: opacity 0.2s ease, transform 0.7s ease-in-out;
}

/* ---------- 11. Питання/відповідь ----------
   Figma-нода faq-section (375:280): рукописний Vasek-заголовок по центру
   + список акордеонів (details/summary, без JS). py 96px (fluid, той
   самий ритм, що всі секції вище), px 24px (page-pad). */
.faq-section {
  position: relative;
  background: var(--cream);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 32px; /* фіксований проміжок між заголовком і списком (gap-[32px] у Figma) — не "ритм" секції, тому не vw */
  padding: 7.5vw var(--page-pad);
  /* верхня риска-розділювач (у Figma border-t на самій секції, той самий
     0.5px-прийом, що вже на header/price-anchor-section) — пропустили при
     першій верстці FAQ, звірено повторно з get_design_context. */
  border-top: 0.5px solid var(--ink);
}

/* та сама зерниста текстура, що на всіх кремових секціях сайту */
.faq-section::before {
  content: '';
  position: absolute;
  inset: 0;
  background-image: url('images/texture-cream.jpg');
  background-size: 512px 512px;
  background-repeat: repeat;
  opacity: 0.06;
  pointer-events: none;
}

.faq-eyebrow-label {
  position: relative; /* над ::before-текстурою */
  margin: 0;
  font-family: var(--font-script);
  font-weight: 400;
  font-size: var(--fs-vasek);
  line-height: var(--lh-quote); /* 56px/30px, категорія "Vasek" з Figma */
  text-align: center;
}

/* Юля попросила ту саму ширину, що в картки відгуку — тому НЕ окрема
   47.1875vw-формула (та хоч і давала однакові 604px на 1280, розходилась
   з testimonial-card на інших розмірах, бо в тієї стеля рахується від
   тексту+фіксованого падінгу, а не від себе самої — див. коментар над
   .testimonial-card вище). Буквально та сама формула, однакова ширина на
   кожному брейкпоінті, не тільки на 1280. */
.faq-list {
  position: relative;
  display: flex;
  flex-direction: column;
  width: min(calc(30.78vw + 210px), 801px);
}

/* риска над кожним пунктом (border-top, той самий прийом-товщина 0.5px,
   що скрізь на сайті) — і ще одна після списку через ::after, щоб рядок
   ліній був і над першим, і під останнім пунктом, як у Figma. */
.faq-item {
  border-top: 0.5px solid var(--ink);
  padding: 24px 0;
}

/* без риски над першим питанням і під останнім (Юля попросила прибрати) —
   :first-child знімає верхню риску там, де вона зайва, а нижню риску, яку
   раніше домальовував .faq-list::after, просто прибрано зовсім. */
.faq-item:first-child {
  border-top: none;
}

.faq-summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  cursor: pointer;
  list-style: none; /* прибирає стандартний трикутник-маркер <summary> */
}

.faq-summary::-webkit-details-marker {
  display: none; /* той самий трикутник у Safari/Chrome — окремий селектор */
}

.faq-question {
  font-family: var(--font-serif);
  font-weight: 500;
  font-size: var(--fs-intro); /* 20px при 1280, той самий капс-токен, що заголовки карток портфоліо/принципів */
  line-height: var(--lh-intro);
  text-transform: uppercase;
}

.faq-icon {
  position: relative;
  flex-shrink: 0;
  width: 24px;
  height: 24px;
}

.faq-icon img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

/* закрито: показуємо "+", відкрито: показуємо "–" (обидві іконки в DOM
   завжди, перемикання суто через display — без жодного JS, атрибут
   [open] на <details> сам вмикається/вимикається кліком по summary) */
.faq-item .icon-minus {
  display: none;
}

.faq-item[open] .icon-plus {
  display: none;
}

.faq-item[open] .icon-minus {
  display: block;
}

.faq-answer {
  margin: 16px 0 0;
  font-family: var(--font-serif);
  font-weight: 300;
  font-size: var(--fs-meta); /* 16px при 1280, той самий токен "звичайного тексту" */
  line-height: var(--lh-meta);
}

/* ---------- 12. Контакти / форма ----------
   Figma-нода contact-form-section (381:353) — фінальний CTA сторінки
   (розділ 8 у struktura-01-golovna.md). py 96px (fluid, той самий ритм,
   що всі секції вище), px 24px (page-pad), gap між заголовком/формою/
   другорядними лінками — фіксований 32px (той самий прийом, що в
   faq-section/price-anchor-section, не "ритм" секції). */
.contact-section {
  position: relative;
  background: var(--cream);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 32px;
  padding: 7.5vw var(--page-pad);
  border-top: 0.5px solid var(--ink);
}

/* та сама зерниста текстура, що на всіх кремових секціях сайту */
.contact-section::before {
  content: '';
  position: absolute;
  inset: 0;
  background-image: url('images/texture-cream.jpg');
  background-size: 512px 512px;
  background-repeat: repeat;
  opacity: 0.06;
  pointer-events: none;
}

.contact-quote {
  position: relative; /* над ::before-текстурою */
  margin: 0;
  font-family: var(--font-script);
  font-style: normal;
  font-weight: 400;
  font-size: var(--fs-vasek);
  line-height: var(--lh-quote); /* 56px/30px, категорія "Vasek" з Figma */
  text-align: center;
}

.contact-quote p {
  margin: 0;
}

/* той самий відступ між рядками рукописного тексту, що hero-headline/
   portfolio-quote — не буквальний Figma leading-[0], а усталений на сайті
   прийом для багаторядкового Vasek */
.contact-quote p + p {
  margin-top: 0.3em;
}

.contact-form {
  position: relative; /* над ::before-текстурою */
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 32px;
}

.form-field {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 16px;
}

.form-label {
  margin: 0;
  font-family: var(--font-serif);
  font-weight: 500;
  font-size: var(--fs-intro); /* 20px при 1280, той самий капс-токен, що faq-question */
  line-height: var(--lh-intro);
  text-transform: uppercase;
}

/* та сама "604-категорія" ширини, що faq-list/price-divider/testimonial-card —
   604px на 1280, стеля 801px на 1920 */
.form-input {
  width: min(calc(30.78vw + 210px), 801px);
  padding: 16px 16px 16px 0;
  border: none;
  border-bottom: 0.5px solid var(--ink);
  border-radius: 0;
  background: transparent;
  font-family: var(--font-serif);
  font-weight: 300;
  font-size: var(--fs-meta); /* 16px при 1280, той самий токен "звичайного тексту" */
  line-height: var(--lh-meta);
  color: var(--ink);
}

.form-input::placeholder {
  color: rgba(50, 49, 49, 0.5); /* той самий приглушений сірий, що в Figma-плейсхолдерах */
}

.form-input:focus {
  outline: none;
  border-bottom-width: 1px; /* легкий фідбек активного поля замість дефолтного браузерного outline */
}

/* КАСТОМНИЙ DROPDOWN "тип зйомки" — Юля попросила під дизайн сайту
   (нативний <select> не дає стилістувати сам відкритий список опцій).
   .custom-select — обгортка з СВОЄЮ копією ширини .form-input (та сама
   "604-категорія"): робимо так, а не просто width:100% від батька, бо
   .form-field — flex-item з align-items:flex-start (hug-ширина, не
   stretch) — % ширина від hug-батька дає циклічну невизначеність.
   Кнопка/список усередині вже прості width:100% від цієї обгортки. */
.custom-select {
  position: relative;
  width: min(calc(30.78vw + 210px), 801px);
}

.custom-select-trigger {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  width: 100%;
  padding: 16px 16px 16px 0;
  border: none;
  border-bottom: 0.5px solid var(--ink);
  border-radius: 0;
  background: transparent;
  appearance: none;
  font-family: var(--font-serif);
  font-weight: 300;
  font-size: var(--fs-meta);
  line-height: var(--lh-meta);
  /* дефолт — приглушений сірий, як плейсхолдери в інших полях, поки
     нічого не вибрано; JS додає .is-selected після вибору опції */
  color: rgba(50, 49, 49, 0.5);
  text-align: left;
  cursor: pointer;
}

.custom-select-trigger.is-selected {
  color: var(--ink);
}

.custom-select-trigger:focus-visible {
  outline: none;
  border-bottom-width: 1px; /* той самий фідбек, що .form-input:focus */
}

.custom-select-icon {
  flex-shrink: 0;
  width: 16px;
  height: 16px;
  background-image: url('images/icon-chevron-down.svg');
  background-repeat: no-repeat;
  background-size: 16px 16px;
  transition: transform 0.2s ease;
}

/* шеврон перевертається, поки список відкритий — aria-expanded і так
   потрібен для доступності, тут же читаємо його й для стилю, без
   дублювання власним data-* атрибутом */
.custom-select-trigger[aria-expanded="true"] .custom-select-icon {
  transform: rotate(180deg);
}

.custom-select-list {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  z-index: 5; /* вище за форму й лінки нижче, той самий рівень, що .site-header-нащадки */
  width: 100%;
  margin: 0;
  padding: 8px 0;
  list-style: none;
  background: var(--cream);
  border: 0.5px solid var(--ink);
}

.custom-select-option {
  padding: 10px 16px;
  font-family: var(--font-serif);
  font-weight: 300;
  font-size: var(--fs-meta);
  line-height: var(--lh-meta);
  color: var(--ink);
  cursor: pointer;
}

/* :hover (миша) і .is-focused (клавіатура — стрілки в script.js) — той
   самий приглушений відтінок, що інші hover-стани на кремовому фоні */
.custom-select-option:hover,
.custom-select-option.is-focused {
  background: rgba(50, 49, 49, 0.06);
}

.custom-select-option[aria-selected="true"] {
  font-weight: 500;
}

/* поки не вибрано формат зйомки (форма не пройшла власну JS-валідацію
   в script.js — прихований required-інпут не рендериться, тому браузер
   сам підказку не покаже) — трохи товща рамка привертає увагу до поля */
.custom-select--invalid .custom-select-trigger {
  border-bottom-width: 1.5px;
}

/* та сама "186-категорія" кнопки, що portfolio-cta-button, але 16px
   (var(--fs-meta)), не 20px — звірено з Figma (тут менший токен тексту).
   .cta-button — справжній <button>, не <a>, тому явно скидаємо border/
   background/appearance замість того, щоб покладатись на відсутність
   дефолтних стилів у посилання. */
.contact-cta-button {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 14.53125vw; /* 186px на 1280 — росте разом з екраном */
  height: 44px;
  border: none;
  border-bottom: 0.5px solid var(--ink);
  border-radius: 0;
  background: none;
  appearance: none;
  font-family: var(--font-serif);
  font-weight: 400;
  font-size: var(--fs-meta);
  line-height: var(--lh-meta);
  color: var(--ink);
  text-transform: uppercase;
  cursor: pointer;
}

.contact-secondary-links {
  position: relative; /* над ::before-текстурою */
  display: flex;
  gap: 80px;
  font-family: var(--font-serif);
  font-weight: 300;
  font-size: var(--fs-meta);
  line-height: var(--lh-meta);
}

/* той самий підкреслений лінк, що price-cta-link/about-more-link — один
   спільний прийом для всіх текстових CTA на сайті */
.contact-secondary-link {
  text-decoration: underline;
  text-decoration-thickness: 0.5px;
  text-underline-offset: 3px;
  transition: opacity 0.2s ease;
}

.contact-secondary-link:hover {
  opacity: 0.6;
}

/* ---------- 13. Футер ----------
   Два окремі Figma-фрейми (footer-section 381:457, footer-bottom-section
   382:512), кожен зі СВОЄЮ border-top+padding:24px — на відміну від
   секцій вище тут padding фіксований 24px (var(--page-pad)), а не 7.5vw:
   футер компактний "підвал", не ще одна велика секція з тим самим
   вертикальним ритмом. */
.footer-main,
.footer-bottom {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  width: 100%;
  padding: var(--page-pad);
  background: var(--cream);
  border-top: 0.5px solid var(--ink);
}

/* та сама зерниста текстура, що на всіх кремових секціях сайту */
.footer-main::before,
.footer-bottom::before {
  content: '';
  position: absolute;
  inset: 0;
  background-image: url('images/texture-cream.jpg');
  background-size: 512px 512px;
  background-repeat: repeat;
  opacity: 0.06;
  pointer-events: none;
}

.footer-content {
  position: relative; /* над ::before-текстурою */
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
}

/* self-stretch у Figma — колонка розтягується на всю висоту сусіда
   (фотострічки, 234px) і сама розводить бренд/меню по краях (space-between) */
.footer-text-column {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  align-self: stretch;
}

.footer-brand {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 16px;
}

.footer-logo {
  margin: 0;
  font-family: var(--font-serif);
  font-weight: 400;
  font-size: var(--fs-intro); /* 20px при 1280, та сама "капс 1"-категорія, що лого в хедері */
  line-height: var(--lh-intro);
  /* без white-space:nowrap (був у Figma-коді, скопійованому з 1280, де й
     так є місце на один рядок) — на вузьких екранах без переносу текст не
     міг стиснутись і виштовхував фотострічку за межі секції (перевірено
     виміром на 375px: фотострічка вилазила на ~60px за праву межу) */
}

/* та сама точна типографіка (line-height 0.96, letter-spacing -0.64px на
   1280), що footer-bottom-row нижче — спільний клас, бо в Figma це буквально
   один і той самий текстовий стиль в обох місцях. em, не px, для tracking —
   масштабується разом зі шрифтом на інших брейкпоінтах (той самий принцип,
   що .hero-meta). Не одна з 4 стандартних --lh-* категорій (найближча,
   --lh-meta, 1.1875 — помітно вища), тому лишаю точним числом з Figma. */
.footer-meta-text {
  font-family: var(--font-serif);
  font-weight: 300;
  font-size: var(--fs-meta);
  line-height: 0.96;
  letter-spacing: -0.04em;
}

.footer-tagline {
  margin: 0;
}

.footer-nav {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 16px;
  font-family: var(--font-serif);
  font-weight: 400;
  font-size: var(--fs-nav); /* 12px при 1280, та сама "капс 2"-категорія, що nav-menu в хедері */
  line-height: var(--lh-nav);
}

.footer-nav a {
  transition: opacity 0.2s ease; /* той самий hover-прийом, що .nav-menu a */
}

.footer-nav a:hover {
  opacity: 0.6;
}

.footer-photo-strip {
  position: relative; /* над ::before-текстурою */
  display: flex;
  gap: var(--gutter); /* 24px, той самий gutter сітки, що і скрізь на сайті */
}

/* та сама "186-категорія" розміру й ті самі пропорції (186×234), що
   .about-photo-frame/.about-photo-image — object-fit:cover без ручного
   Figma-кропу (на відміну від фото Юлі в about-section, тут JSX не дає
   власних transform/offset, звичайний центрований cover). */
.footer-photo {
  margin: 0;
  width: 14.53125vw;
  aspect-ratio: 186 / 234;
  overflow: hidden;
}

.footer-photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Один рядок, 2 колонки: зліва копірайт (ім'я/рік над локацією), справа
   юридичні лінки (оферта над політикою) — обидві колонки вертикальні
   стовпчики з 2 рядків тексту, розведені по краях (той самий
   space-between, що скрізь у футері). */
.footer-bottom-row {
  position: relative; /* над ::before-текстурою */
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  width: 100%;
}

.footer-bottom-copyright,
.footer-legal-links {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

/* правий стовпчик — вирівнювання по правому краю (лівий лишається за
   замовчуванням по лівому, той самий природний text-align/align-items
   для .footer-bottom-copyright). */
.footer-legal-links {
  align-items: flex-end;
  text-align: right;
}

.footer-bottom-row p {
  margin: 0;
}

.footer-legal-links a {
  transition: opacity 0.2s ease;
}

.footer-legal-links a:hover {
  opacity: 0.6;
}

/* ---------- 14. Сторінка альбому (portfolio-family.html і подібні) ----------
   Перша "внутрішня" сторінка сайту — Figma-макета під неї ще нема
   (є тільки текст, 00-resources/kopiraayt/02-typy-zyomky.md), тому
   розмітка й розміри тут не звірені з конкретною Figma-нодою, а свідомо
   побудовані на вже наявних токенах і патернах сайту (--fs-vasek,
   --gutter, .portfolio-grid/.portfolio-card-image тощо) — щоб нова
   сторінка виглядала органічно поруч зі старими, а не власним окремим
   стилем. */
.album-intro-section,
.album-gallery-section {
  position: relative;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--page-pad);
}

.album-intro-section::before,
.album-gallery-section::before {
  content: '';
  position: absolute;
  inset: 0;
  background-image: url('images/texture-cream.jpg');
  background-size: 512px 512px;
  background-repeat: repeat;
  opacity: 0.06;
  pointer-events: none;
}

/* верх 96px, той самий ритм, що .portfolio-section; низ 0 — відстань
   divider→галерея тепер задає ЛИШЕ верхній padding .album-gallery-section
   нижче (щоб не рахувати суму двох чисел, як було). */
.album-intro-section {
  padding: 7.5vw var(--page-pad) 0;
  border-top: 0.5px solid var(--ink); /* лінія під хедером, як усюди на сайті */
}

/* НЕ border-top тут — Юля попросила прибрати лінію одразу після divider
   (.album-intro-section вище й так закінчується divider-картинкою, друга
   лінія одразу під нею була зайвою).

   Верх — var(--page-pad) (24px, фіксовано) — спершу був 3.75vw (48px,
   той самий токен, що gap у .portfolio-lead), Юля попросила ще ближче.
   24px — найменший стандартний крок на сайті (page-pad/gutter), менше
   вже нема куди, не вигадую довільне дрібне число. Низ лишається 7.5vw —
   це остання секція перед футером, і Юля попросила той самий відступ,
   що "всередині" інших блоків головної (about-section/faq-section тощо
   — там симетрично 7.5vw згори/знизу), а не вузькі "поля сітки". */
.album-gallery-section {
  padding: var(--page-pad) var(--page-pad) 7.5vw;
}

/* Юля передумала: заголовок тепер рукописним Vasek (як .portfolio-quote/
   .hero-headline), а не капсом — той самий --fs-vasek/--lh-quote токен,
   що весь інший рукописний текст сайту. Текст у HTML навмисно малими
   літерами — Vasek скрізь на сайті лише lowercase (hero-headline,
   portfolio-quote, about-eyebrow-label), капс тут ламав би єдиний стиль. */
.album-title {
  position: relative;
  margin: 0;
  font-family: var(--font-script);
  font-weight: 400;
  font-size: var(--fs-vasek);
  line-height: var(--lh-quote);
  text-align: center;
}

/* .album-desc замінив .album-quote — той самий шрифт/вага/розмір/lh, що
   .portfolio-card-desc на картках головної (fs-meta/lh-meta/300), і той
   самий text-align:justify. Максимальна ширина на десктопі — той самий
   токен, що .about-quote-text ("про мене" на головній, min(30.78vw,
   591px), стеля на 1920) — Юля попросила саме цей приклад. Тільки
   десктоп: на планшеті/телефоні той самий 30.78vw дав би нечитабельно
   вузьку колонку (~236px на 768) — скидаю до 100% нижче 1024, розділ 16. */
.album-desc {
  position: relative;
  width: 100%;
  max-width: min(30.78vw, 591px);
  margin-inline: auto;
  font-family: var(--font-serif);
  font-weight: 300;
  font-size: var(--fs-meta);
  line-height: var(--lh-meta);
  text-align: justify;
}

/* НЕ той самий приём, що .portfolio-grid (auto-fit(220px)) — перевірила
   виміром: auto-fit там випадково дає рівно 4 колонки тільки тому, що в
   сітці рівно 4 картки (auto-fit схлопує "зайві" порожні колонки до 0,
   тому 5-та порожня колонка не заважає). У галереї карток 8-20, порожніх
   колонок нема що схлопувати — той самий auto-fit чесно порахував 5
   колонок по ~227px замість 4 по 290px. Тут колонок свідомо фіксовано
   repeat(4, 1fr) — те саме число, що просила Юля, на будь-якій кількості
   фото. */
.album-gallery-grid {
  position: relative;
  width: 100%;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--gutter);
}

/* той самий вертикальний формат (290×390) і той самий hover, що
   .portfolio-card-image — "однакова обрізка", як домовились: усі фото
   вписуються в цю рамку через object-fit:cover незалежно від власних
   пропорцій оригіналу */
/* fade при скролі — стартовий стан (непрозоро+трохи нижче), script.js
   (IntersectionObserver, кінець файлу) додає .is-visible, коли картка
   заходить у вʼюпорт, звідти й перехід у видимий стан нижче. Тільки
   opacity/transform — обидва дешеві для браузера (не тригерять layout/
   paint всього документа), плавно навіть на слабших телефонах. */
.album-gallery-photo {
  margin: 0;
  width: 100%;
  aspect-ratio: 290 / 390;
  overflow: hidden;
  opacity: 0;
  /* 2-й заход: 0.4s ease-out виявився занадто швидким/різким у інший бік
     (Юля: "щоб не одразу з'являлось") — ease-out прискорює САМЕ НА
     СТАРТІ (швидкий стрибок, потім сповільнення), тому й читався як
     раптовий, попри коротку тривалість. ease-in-out — повільний старт І
     повільний фініш, довше (0.7s), трохи більший підйом (12px→16px) —
     плавніше на обох кінцях переходу, не "стрибає" відразу. */
  transform: translateY(16px);
  transition: opacity 0.7s ease-in-out, transform 0.7s ease-in-out;
}

.album-gallery-photo.is-visible {
  opacity: 1;
  transform: translateY(0);
}

.album-gallery-photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.4s ease;
}

.album-gallery-photo:hover img {
  transform: scale(1.04);
}

/* .portfolio-cta-button має фіксовану ширину 186px, точну під слово
   "записатися" (Figma-розмір) — текст тут довший ("хочу таку зйомку",
   00-resources/kopiraayt/02-typy-zyomky.md), при 186px переносився на 2
   рядки і вилазив за фіксовану висоту кнопки (44px). Той самий fit-content
   fallback, що вже є в .portfolio-cta-button на планшеті/телефоні (там —
   через іншу причину, замалий vw на вузькому екрані), тут потрібен і на
   десктопі. */
.album-cta-button {
  width: fit-content;
  white-space: nowrap;
  padding-inline: 24px;
}

/* Рамка-заглушка замість <img> в .album-gallery-photo — використана в
   portfolio-family.html, поки не приїхали реальні фото (тепер уже приїхали,
   клас там більше не застосовується). Лишаю клас у styles.css — знадобиться
   так само для інших сторінок-альбомів (portfolio-portrait/-wedding/
   -lovestory.html), поки не приїдуть фото і для них. */
.album-gallery-photo--placeholder {
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px dashed var(--ink);
  opacity: 0.4;
  font-family: var(--font-serif);
  font-size: var(--fs-nav);
  line-height: var(--lh-nav);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

/* ---------- 15. Fade при скролі — основні блоки головної ----------
   Той самий прийом, що .album-gallery-photo (розділ 14): script.js
   (IntersectionObserver, кінець файлу) додає .is-visible, коли елемент
   заходить у вʼюпорт. Один спільний клас .reveal — Юля попросила стагер
   майже скрізь, тому клас переважно на ОКРЕМИХ дочірніх елементах
   секції (data-stagger="0/1/2..."), не на секції як цілому:
   - portfolio-card ×4, principle-item ×3 — картки/пункти в ряд
   - price-headline-group/price-divider/price-specs-text/price-cta-link —
     4 послідовні блоки всередині price-anchor-section
   - faq-eyebrow-label + faq-item ×8 — лейбл і кожне питання окремо
   - contact-quote/contact-form/contact-secondary-links — 3 блоки
     всередині contact-section
   Без стагера (data-stagger не задано → 0, просто плавна поява) —
   about-portrait, testimonial-card: там усередині нема природного
   "ряду" елементів, які б мало сенс розводити в часі. .hero-content і
   .portfolio-section свідомо БЕЗ .reveal — hero вже видно одразу при
   завантаженні (sticky-scroll-jack, не "прокрутка до"), а секція-
   обгортка портфоліо зав'язана на той самий sticky-механізм; чіпати
   їх тут ризиковано. */
.reveal {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 0.7s ease-in-out, transform 0.7s ease-in-out;
}

.reveal.is-visible {
  opacity: 1;
  transform: translateY(0);
}

/* ---------- 16. Сторінка контактів (kontakty.html) ----------
   Нема Figma-макета для цієї сторінки (не було в дизайні, зроблено на
   прохання Юлі окремо) — верстка спирається на вже усталену дизайн-
   систему сайту (кольори/шрифти/токени, ті самі 0.5px рамки й cream-
   текстура), не на конкретний макет. Два стовпці: зліва велике фото
   (crossfade-слайдшоу, JS у script.js), справа — та сама форма, що на
   index.html (.contact-quote/.contact-form/.contact-secondary-links
   перевикористані 1-в-1 без жодної правки — тому й однакові стилі та
   ж сама адаптивність полів на вужчих екранах, розділ 12/17).
   .contacts-form-wrap — не .contact-section: та має власний
   центрований однoколонковий лейаут (max-width форми зверху),
   тут потрібен просто контейнер-стовпець грід-сітки. */
.contacts-hero-section {
  display: grid;
  /* Юля попросила рівно порівну: 50% форма / 50% фон+фото. (Раніше тут
     була вужча 45% колонка фото — компроміс під розмір стиснутих
     файлів, вже не потрібен: фото тепер у фіксованій рамці 290×390,
     розділ нижче, набагато менше за будь-яку половину екрана, апскейл
     тут в принципі неможливий незалежно від ширини колонки.) */
  grid-template-columns: 1fr 1fr;
  align-items: stretch;
  /* Юля попросила: уся секція влазить в один екран, без гортання —
     "height" (не "min-height"), точно висота вʼюпорта мінус хедер, ні
     пікселем більше. Тому нижче й стиснуто padding/gap форми (302px
     мали піти лише на "повітря" при min-height — забагато для
     фіксованої висоти) і доданий overflow-y:auto як запобіжник (розділ
     нижче) — якщо на якомусь екрані контент усе ж не влізе, скролиться
     тільки вузька колонка форми, не вся сторінка. */
  height: calc(100vh - var(--header-height));
  height: calc(100svh - var(--header-height));
  border-top: 0.5px solid var(--ink);
}

/* Ліва половина — тепер просто ФОН (та сама cream-текстура, що форма
   справа) з фото-рамкою по центру, а не фото на всю площу з
   object-fit:cover. Причина зміни: family/portrait/wedding/love файли
   стиснуті sips'ом до ~533-572×800px під МАЛЕНЬКІ картки галереї
   (290×390) — розтягнуті на всю половину екрана (640-720px), вони
   були помітно розмиті. У власному "галерейному" розмірі (290×390,
   той самий, що .album-gallery-photo/.portfolio-card-image) той самий
   файл завжди ЗМЕНШУЄТЬСЯ, ніколи не збільшується — тому завжди чіткий,
   незалежно від ширини самої колонки чи майбутньої заміни фото. */
.contacts-photo {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--cream);
  border-right: 0.5px solid var(--ink); /* та сама тонка риска, що ділить хедер/картки на сайті — тут візуально ділить 50/50 */
}

/* та сама зерниста текстура, що на всіх кремових секціях сайту */
.contacts-photo::before {
  content: '';
  position: absolute;
  inset: 0;
  background-image: url('images/texture-cream.jpg');
  background-size: 512px 512px;
  background-repeat: repeat;
  opacity: 0.06;
  pointer-events: none;
}

/* фіксована рамка-контейнер для слайдшоу — точний розмір "галерейної"
   картки сайту (290×390 на 1280, той самий токен, що .album-gallery-photo/
   .portfolio-card-image), не росте й не тягнеться під ширину колонки. */
.contacts-photo-frame {
  position: relative; /* над ::before-текстурою .contacts-photo */
  z-index: 1;
  width: 290px;
  aspect-ratio: 290 / 390;
  overflow: hidden;
}

/* фото-слайдшоу — усі кадри лежать один на одному (position:absolute
   всередині фіксованої рамки вище), .is-active вмикає видимість з
   crossfade-переходом; JS перемикає клас кожні 4с (script.js). */
.contacts-photo-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity 1.2s ease-in-out;
}

.contacts-photo-img.is-active {
  position: relative; /* над рештою кадрів, поки триває crossfade */
  z-index: 1;
  opacity: 1;
}

.contacts-form-wrap {
  position: relative; /* над ::before-текстурою нижче */
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 24px; /* було 32px (той самий, що .contact-section) — зменшено,
                щоб цитата+форма+лінки влізли в фіксовану висоту секції */
  /* було 7.5vw (той самий "ритм", що .contact-section) — тут секція
     фіксованої висоти (див. .contacts-hero-section вище), а не частина
     довгого скролу, тому великий "ритм"-padding зверху/знизу тут не
     потрібен, лишила тільки стандартний page-pad. */
  padding: var(--page-pad);
  background: var(--cream);
  overflow-y: auto; /* запобіжник: якщо контент все ж не влізе на
                        якомусь екрані (дуже низький вʼюпорт, відкритий
                        custom-select тощо) — скролиться тільки ця
                        колонка, не вся сторінка */
}

/* та сама зерниста текстура, що на всіх кремових секціях сайту */
.contacts-form-wrap::before {
  content: '';
  position: absolute;
  inset: 0;
  background-image: url('images/texture-cream.jpg');
  background-size: 512px 512px;
  background-repeat: repeat;
  opacity: 0.06;
  pointer-events: none;
}

/* .contact-form має спільний з index.html#contact gap:32px (розділ 12)
   — тут звужую ТІЛЬКИ в межах цієї сторінки (вищий селектор-специфічність
   через .contacts-form-wrap, не займає загальне правило), щоб 4 поля +
   кнопка влізли у фіксовану висоту секції разом з цитатою/лінками. */
.contacts-form-wrap .contact-form {
  gap: 16px;
}

/* ---------- 17. Сторінка цін (tsiny.html) ----------
   Figma-нода price-page (570:424), звірено через get_design_context на
   1280 — Юля переробила сторінку ще раз, шари перейменовані описово
   заново (price-main, price-heading, price-card-*, price-outro-*, той
   самий метод, що вже застосовувався на інших блоках). Замінює
   попередню верстку "текстовий список із рисками" (яка сама була звірена
   з попереднього Figma-макета 559:82, тепер застарілого) — знову картки
   з фото, як на головній.

   ОДНА секція (.tsiny-list-section), не дві, як у попередніх двох
   версіях цієї сторінки — за новим Figma-макетом розділювача (border-top)
   між заголовком/картками і текстом умов+кнопкою більше нема, лінії під
   хедером теж нема (як і в попередній версії). */
.tsiny-list-section {
  position: relative;
  background: var(--cream);
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 7.5vw var(--page-pad);
  gap: 7.5vw; /* gap-[96px] на 1280 (Figma) — той самий "великий ритм", що padding секцій сайту, тому fluid, не фіксований */
}

.tsiny-list-section::before {
  content: '';
  position: absolute;
  inset: 0;
  background-image: url('images/texture-cream.jpg');
  background-size: 512px 512px;
  background-repeat: repeat;
  opacity: 0.06;
  pointer-events: none;
}

/* price-main — price-top (заголовок+інтро+дівайдер) і сітка карток.
   gap:24px (фіксовано, Figma) — раніше тут був "великий ритм" 96px/1280,
   поки заголовок+інтро йшли одразу перед сіткою; тепер це проміжок між
   ДІВАЙДЕРОМ і сіткою (сам дівайдер уже дає візуальне розділення, тому
   менший gap не читається як "затісно"). */
.price-main {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 24px;
  /* явна ширина — інакше сама розтягується "за вмістом" (flex-item без
     stretch, бо в .tsiny-list-section align-items:center), і
     .price-card-grid нижче не має від чого рахувати свій width:100%,
     звужуючись до 1 колонки замість чотирьох. */
  width: 100%;
}

/* price-top — заголовок+інтро (price-heading) над дівайдером, gap:48px
   (Figma) — той самий "великий ритм", що раніше був у .price-main, тепер
   перенесений сюди. Явна ширина — та сама причина, що в .price-main
   вище: .divider-image всередині full-bleed на всю ширину екрана
   (margin-inline: calc(50% - 50vw), розділ 6 styles.css), без
   контрольованої ширини батька рахувати цей трюк нема від чого. */
.price-top {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 48px;
  width: 100%;
}

.price-heading {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 32px;
}

/* заголовок "цiни" — .album-title, інтро-абзац — .album-desc,
   перевикористані 1-в-1 (той самий рукописний Vasek і той самий
   justify-параграф 591px-стелі, що на сторінках-альбомах) — звірено з
   Figma: 604px і 391px відповідно, обидва в межах уже наявних формул.
   Дівайдер — .divider-image, теж перевикористаний 1-в-1 (розділ 6). */

/* сітка карток — той самий "4 картки по 290px" патерн, що .portfolio-grid
   на головній (auto-fit(220px) чесно дає 4 колонки рівно тому, що карток
   рівно 4 — той самий коментар, що там). */
.price-card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: var(--gutter);
  width: 100%;
}

/* .price-card (gap:32px) і .price-card-title/.price-card-price
   (капс-medium-20px) — розширення вже наявних .portfolio-card/
   .portfolio-card-title (розділ 6 styles.css): Figma задає ті самі
   значення буквально. uppercase на .price-card-price — безпечний no-op
   (цифри й "€" не мають регістру), тому спільний селектор без винятків. */
.portfolio-card,
.price-card {
  display: flex;
  flex-direction: column;
  gap: 32px;
}

.portfolio-card-title,
.price-card-title,
.price-card-price {
  font-family: var(--font-serif);
  font-weight: 500;
  font-size: var(--fs-intro);
  line-height: var(--lh-intro);
  text-transform: uppercase;
}

.price-card-price {
  margin: 0;
}

/* фото картки — тепер клікабельне (Юля попросила: перехід у галерею типу
   зйомки саме через фото, не через текст) — саме правило .price-card-image
   вже додане розширенням до .portfolio-card-image (розділ 6, там же
   .portfolio-card-cta для підпису "дивитися галерею") — тут свій рулсет
   більше не потрібен. Текст картки (.price-card-text) — окремий елемент
   ПОЗА `<a>`, тому клік по назві/ціні нічого не відкриває. */

.price-card-text {
  display: flex;
  flex-direction: column;
  gap: 16px; /* gap-[16px] на price-card-*-text (Figma) — інша категорія, ніж .portfolio-card-text (12px), тому окреме правило */
}

/* min-height (той самий прийом, що .testimonial-quote, розділ 9) сам по
   собі лише резервував МІСЦЕ під 2 рядки — але коли текст конкретної
   картки фактично влазив в 1 рядок (виміряно на планшеті: "до 2 годин…"
   274-284px природної ширини проти ~348px картки — впритул влазить),
   під ним лишалась порожнеча, і текст виглядав нерівномірно поряд із
   картками, де специфікації реально займають 2 рядки. Юля попросила:
   якщо хоч один текст переноситься на 2 рядки — переносити ВСІ. Рішення
   без JS (не можна одним CSS-правилом "подивитись" на сусідню картку) —
   max-width звужує контейнер настільки, що НАЙКОРОТШИЙ з 4 текстів теж
   гарантовано не влазить в один рядок на жодному брейкпоінті (перевірено
   виміром: 90% картки скрізь менше за природну ширину найкоротшого
   тексту — на планшеті 0.9×348=313px проти 342px природної ширини). */
.price-card-specs {
  margin: 0;
  max-width: 90%;
  min-height: calc(var(--lh-meta) * 2em);
  font-family: var(--font-serif);
  font-weight: 300;
  font-size: var(--fs-meta);
  line-height: var(--lh-meta);
  text-align: justify;
}

/* price-outro — текст умов (3× .album-desc) + кнопка "записатися"
   (.cta-button.portfolio-cta-button, той самий фіксований 186×44, що вже
   був на цій сторінці раніше) одним блоком, gap-[32px] (Figma), без
   риски над кнопкою. */
.price-outro {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 32px;
}

.price-outro-text {
  display: flex;
  flex-direction: column;
  gap: 16px; /* той самий крок, що .tsiny-payment-text мав раніше — заміняє подвійний <br><br> з Figma-експорту */
}

/* ---------- 18. Сторінка про мене (pro-mene.html) ----------
   Figma-нода about-me-page (591:1031), звірено через get_design_context на
   1280 — шари перейменовані заздалегідь (about-intro-section/about-photo/
   about-intro-text/about-heading/about-bio-text/about-story-section/
   about-quote-text/about-story-text, той самий метод, що на інших
   сторінках). Дві секції, без border-top на першій (тільки на другій —
   border-top:0.5px, Figma). */
.pro-mene-intro-section {
  display: flex;
  justify-content: center;
  /* py-[96px] на 1280 (Figma) — той самий "великий ритм", що portfolio-
     section/tsiny-list-section, тому fluid 7.5vw. Горизонтальні px-[233px]
     з Figma НЕ окремий токен — це просто наслідок центрування
     фіксованого 814px-вмісту (фото+gap+текст) у 1280-контейнері, тому
     тут звичайні мінімальні "поля сітки" (page-pad), а центрування дає
     flex justify-content:center. */
  padding: 7.5vw var(--page-pad);
}

.pro-mene-intro-row {
  display: flex;
  /* stretch, не center — текстова колонка має НЕ вилазити за висоту
     фото (Юля попросила прямо), тому підганяємо її висоту під фото
     (найвищий елемент рядка) і розподіляємо простір усередині неї
     через justify-content:space-between (нижче), а не фіксованим
     gap-числом, яке "не знає" про реальну довжину тексту. */
  align-items: stretch;
  gap: var(--gutter); /* gap-[24px] на 1280 (Figma) — фіксований "gutter", як скрізь на сайті */
}

/* та сама техніка, що .about-photo-frame на головній (чисто vw, без
   стелі) — одиничне велике фото портрета, не текстова колонка, стеля
   читабельності тут не потрібна. */
.pro-mene-photo {
  position: relative;
  width: 30.859375vw; /* 395px на 1280 */
  aspect-ratio: 395 / 531;
  overflow: hidden;
  flex-shrink: 0;
}

.pro-mene-photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.pro-mene-intro-text {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  /* Юля попросила: текст не повинен вилазити за висоту фото. Раніше
     тут був фіксований gap-[223px] (з Figma, під короткий текст на
     момент верстки) — коли текст виріс (новий абзац про освіту),
     223px+вміст стали вищими за фото (685px проти 531px). Замість
     підбирати нове магічне число — .pro-mene-intro-row вище тепер
     stretch (висота = висота фото), а тут justify-content:space-
     between сам порахує проміжок від РЕАЛЬНОЇ висоти вмісту: чим
     довший текст, тим менший gap, і колонка ФІЗИЧНО не може стати
     вищою за рядок (=фото). */
  justify-content: space-between;
  /* w-[395px] на 1280, стеля на 1920 (395×1.5) — той самий прийом, що
     .album-desc/.about-quote-text (довгий текст-абзац, обмежуємо
     ширину на великих екранах для читабельності). */
  width: min(30.859375vw, 592.5px);
}

.pro-mene-heading,
.process-heading {
  margin: 0;
  font-family: var(--font-serif);
  font-weight: 400;
  font-size: var(--fs-intro); /* 20px при 1280, той самий капс-токен "капс 1" — текст уже типографічно в капсі в самому HTML, без text-transform */
  line-height: var(--lh-intro);
}

/* .pro-mene-story-text/.process-body-text перевикористовують ті самі
   правила абзаців нижче — усі блоки: 16px light, justify, gap:24px
   замість порожніх <p> з Figma-експорту (той самий прийом, що
   .price-outro-text). */
.pro-mene-bio-text,
.pro-mene-story-text,
.process-body-text {
  display: flex;
  flex-direction: column;
  gap: var(--gutter);
}

.pro-mene-bio-text p,
.pro-mene-story-text p,
.process-body-text p {
  margin: 0;
  font-family: var(--font-serif);
  font-weight: 300;
  font-size: var(--fs-meta); /* 16px при 1280, той самий токен "звичайний текст" */
  line-height: var(--lh-meta);
  text-align: justify;
  /* text-transform:lowercase (з Figma-макета) прибрано — Юля попросила
     звичайні великі літери на початку речень, як у HTML. */
}

/* Посилання всередині абзацу (email/telegram/instagram на юридичних
   сторінках) — шрифт успадковують від <p>, від .about-more-link беруть
   тільки тонке підкреслення і hover, щоб лінк виглядав однаково по сайту. */
.process-body-text a {
  text-decoration: underline;
  text-decoration-thickness: 0.5px;
  text-underline-offset: 3px;
  transition: opacity 0.2s ease;
}

.process-body-text a:hover {
  opacity: 0.6;
}

.pro-mene-story-section {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  /* Юля попросила саме на десктопі 48px на 1280 (було 64px) — 48/1280=
     3.75vw, стеля на 1920 (48×1.5=72px), той самий принцип "стелі".
     Планшет/телефон лишаються на старій формулі (min(5vw,96px)) —
     оверрайд у @media(max-width:1023px) нижче, там про це не просили. */
  gap: min(3.75vw, 72px);
  padding: 7.5vw var(--page-pad);
  border-top: 0.5px solid var(--ink); /* та сама товщина ліній, що скрізь на сайті */
}

.pro-mene-quote-text {
  margin: 0;
  /* Юля попросила: не ширше за текст філософії під нею — та сама
     ширина, що .pro-mene-story-text (594px на 1280), замість власної
     543px-формули з Figma. */
  width: min(30.859375vw, 592.5px);
  font-family: var(--font-serif);
  font-weight: 400;
  font-size: var(--fs-intro);
  line-height: var(--lh-intro);
  text-align: left; /* було center — Юля попросила вирівняти по лівому краю */
  text-transform: uppercase; /* текст у HTML навмисно малими літерами, той самий прийом, що album-title/кнопки CTA */
}

.pro-mene-story-text {
  width: min(30.859375vw, 592.5px); /* та сама ширина, що .pro-mene-intro-text — Figma задає той самий 395px */
}

/* ---------- 19. Як проходить зйомка ----------
   Figma node process (613:1254) — та сама структура-принцип, що
   .pro-mene-story-section: одна центрована колонка (текст + кнопка),
   border-top, gap і padding fluid зі "стелею". Ширина тексту — той
   самий токен, що на "про мене" (395px на 1280, min(30.859375vw,
   592.5px)) — Юля попросила прямо цей принцип. */
.process-section {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: min(3.75vw, 72px); /* 48px на 1280 (Figma), стеля 72px на 1920 — той самий токен, що .pro-mene-story-section */
  padding: 7.5vw var(--page-pad);
  border-top: 0.5px solid var(--ink);
}

.process-text {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: min(3.75vw, 72px); /* gap-[48px] у Figma між заголовком і текстом — той самий "стеля"-токен */
  width: min(30.859375vw, 592.5px); /* 395px на 1280, той самий принцип, що .pro-mene-intro-text/.pro-mene-story-text */
}

/* 404.html — на повний екран під хедером, той самий токен-прийом
   (height/min-height: 100vh/100svh - --header-height), що вже є на
   .contacts-hero-section (розділ 16) — svh-фолбек про запас на
   мобільних браузерах, де адресний рядок з'їдає частину 100vh. */
.notfound-section {
  min-height: calc(100vh - var(--header-height));
  min-height: calc(100svh - var(--header-height));
}
/* .process-body-text саме flex/gap-правило — перевикористане разом із
   .pro-mene-bio-text/.pro-mene-story-text нижче (спільний блок абзаців). */

/* =========================================================
   20. Адаптив — три рівні:
      десктоп ≥1024px, планшет 768–1023px, телефон ≤767px.
      Навігація (бургер) і фіксовані розміри шрифтів спільні для
      планшета й телефона. Фотострічка (scroll-jacking) — однакова
      на всіх трьох рівнях, окремих правок під конкретний розмір
      майже нема (див. розділ 5 "Hero" вище).
   ========================================================= */

@media (max-width: 1023px) {
  /* десктопна ширина .album-desc (min(30.78vw,591px), той самий токен,
     що .about-quote-text) на планшеті/телефоні дала б ~236px на 768 —
     нечитабельно вузько. На всю доступну ширину секції, як і решта
     сторінки на цих розмірах. */
  .album-desc {
    max-width: 100%;
  }

  /* Юля попросила збільшити відстань сітка→кнопка "записатися" ТІЛЬКИ
     на десктопі (розділ 6 вище) — на планшеті/телефоні лишаємо як було
     (сам gap:24px секції, без додаткового margin-top). */
  .portfolio-section .portfolio-cta-button {
    margin-top: 0;
  }

  /* Юля попросила зменшити gap у pro-mene-story-section ТІЛЬКИ на
     десктопі (розділ 18 вище, 64px→48px) — планшет/телефон лишаються
     на старій формулі, тут явно повертаю min(5vw,96px). */
  .pro-mene-story-section {
    gap: min(5vw, 96px);
  }

  .nav-menu-left,
  .nav-menu-right {
    display: none;
  }

  .logo {
    position: static;
    transform: none;
  }

  .site-header {
    justify-content: center;
  }

  .nav-toggle-label {
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    gap: 5px;
    width: 32px;
    height: 32px;
    position: absolute;
    right: var(--page-pad);
    top: 50%;
    transform: translateY(-50%);
    cursor: pointer;
  }

  .nav-toggle-label span {
    width: 22px;
    height: 1px;
    background: var(--ink);
    transition: transform 0.25s ease, opacity 0.25s ease;
  }

  /* бургер перетворюється на хрестик, коли меню відкрите */
  .nav-toggle-checkbox:checked ~ .nav-toggle-label span:nth-child(1) {
    transform: translateY(6px) rotate(45deg);
  }

  .nav-toggle-checkbox:checked ~ .nav-toggle-label span:nth-child(2) {
    opacity: 0;
  }

  .nav-toggle-checkbox:checked ~ .nav-toggle-label span:nth-child(3) {
    transform: translateY(-6px) rotate(-45deg);
  }

  .mobile-nav {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 20px;
    position: absolute;
    top: 64px;
    left: 0;
    right: 0;
    padding: 32px var(--page-pad);
    background: var(--cream);
    border-bottom: 0.5px solid var(--ink);
    font-size: 14px;

    /* прихований, поки чекбокс не активний */
    opacity: 0;
    visibility: hidden;
    transform: translateY(-8px);
    transition: opacity 0.2s ease, transform 0.2s ease, visibility 0.2s;
    z-index: 5;
  }

  /* та сама зерниста текстура, що й на фоні всього сайту */
  .mobile-nav::before {
    content: '';
    position: absolute;
    inset: 0;
    background-image: url('images/texture-cream.jpg');
    background-size: 512px 512px;
    background-repeat: repeat;
    opacity: 0.06;
    pointer-events: none;
    z-index: -1;
  }

  .nav-toggle-checkbox:checked ~ .mobile-nav {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
  }

  /* на мобільному розміри фіксовані (менші за десктопні), а не "стиснуті" clamp'ом */
  :root {
    --fs-logo: 18px; /* був fluid (1.5625vw) без нижньої межі — на 375px "з'їжджав" до ~6px */
    --fs-vasek: 34px; /* раніше тут були 2 окремі числа (34/32) для headline/quote — об'єднано в одне */
    --fs-intro: 16px;
    --fs-meta: 14px;
    /* той самий баг, що вище: --fs-nav теж лишався fluid (0.9375vw) без
       нижньої межі — непомітно, бо .nav-menu (єдине місце, де він
       використовувався) ховається за бургер на цих розмірах ≤1023. Коли
       .footer-nav (нове, видиме на всіх розмірах) почав використовувати
       той самий токен, на 768px він порахувався в 7.2px замість 12px.
       0.75× від --fs-meta (та сама пропорція 12/16, що на 1280) —
       та сама логіка, що в --fs-price вище. */
    --fs-nav: 11px;
    /* та сама пропорція, що на 1280 (128/56 ≈ 2.286×--fs-vasek) — зберігає
       відносний масштаб "великої ціни" до рукописного заголовка над нею
       на кожному брейкпоінті, а не довільне число */
    --fs-price: 78px;
    /* та сама пропорція 1.6×--fs-intro, що на 1280 (тут --fs-intro:16px
       вище в цьому ж блоці) */
    --fs-price-card: 26px;
  }

  /* мобільного/планшетного макета футера у Figma нема (той самий випадок,
     що faq-list/testimonial-card вище) — рядок "текст зліва + 3×186px
     фото справа" фізично не влазить на жодному з цих розмірів (перевірено
     виміром на 375px: фотострічка вилазила на ~29px за контент-бокс, і на
     768px теж не лишається запасу після виправлення --fs-nav вище). Стек
     колонкою на обох рівнях: текст зверху, фото на всю ширину знизу.
     gap:24px, не 32 — той самий принцип "зовнішня ≥ внутрішня", що вище:
     тут зовнішній padding теж фіксований 24px (var(--page-pad)), а не
     7.5vw, тому й внутрішній gap рівняю до того самого фіксованого числа
     замість vw-формули. */
  .footer-content {
    flex-direction: column;
    align-items: flex-start;
    gap: 24px;
  }

  .footer-text-column {
    justify-content: flex-start;
    gap: 24px;
  }

  /* фото більше не "186-категорія" з vw — на всю ширину секції, порівну,
     інакше при стеку колонкою вони лишились би крихітними (54px на 375,
     ще менше на вужчому планшеті) замість заповнювати рядок.

     Було flex:1 + width:auto (нехай flex-grow сам ділить простір порівну,
     aspect-ratio рахує висоту від отриманої ширини) — на артефакті (iOS,
     WebKit-сендбокс) це давало розтягнуті фото на телефоні, хоча на
     реальному сайті в тому самому браузері виглядало нормально. Відома
     категорія нестиковок: flex-basis:0% (те, що ховається за скороченням
     flex:1) + aspect-ratio по-різному рахуються different рушіями. Явний
     width через calc() — те саме "порівну на 3", але без залежності від
     flex-grow, надійніше. */
  .footer-photo-strip {
    width: 100%;
  }

  .footer-photo {
    width: calc((100% - 2 * var(--gutter)) / 3);
  }

  /* Юля попросила прибрати тег-лайн у футері на планшеті й телефоні — той
     самий текст, що вже ховається в hero-meta-text на телефоні (там
     тільки ≤767, тут ширше, на обох рівнях ≤1023) */
  .footer-tagline {
    display: none;
  }

  /* мобільного макета principles-section у Figma нема — рішення власне:
     3 колонки по ~290px + gap 50px (971px) не влазять навіть у планшет
     (768–1023px, доступна ширина з полями 24px — максимум 975px, і то
     впритул), тому на обох рівнях (планшет+телефон) стек колонкою.
     width:min(100%,290px) — той самий розмір колонки, що на десктопі
     (22.65625vw при 1280 = 290px), але не ширше за екран: на вузькому
     телефоні (напр. 320px) колонка сама звужується до 100% замість
     переповнення. */
  .principles-list {
    flex-direction: column;
    align-items: center;
    gap: 48px; /* той самий вертикальний ритм між елементами списку, що row-gap у portfolio-grid на цих рівнях */
  }

  .principle-item {
    width: min(100%, 290px);
  }

  /* той самий принцип, що з fs-*: на планшеті/телефоні fluid vw-розмір
     (14.375vw) стискає фото до нечитабельних ~56px — фіксуємо більшим
     сталим значенням (тепер на рамці — фото саме лише 100% від неї).
     Розміри шрифту тут більше не чіпаємо — вони на стандартних --fs-*
     токенах (вище), які вже мають свій мобільний оверрайд у цьому ж
     медіа-запиті (--fs-vasek/--fs-intro/--fs-meta). */
  .about-photo-frame {
    width: 160px;
  }

  .about-quote-text {
    width: 280px;
  }

  .hero-content {
    padding-top: 56px;
  }

  .hero-headline {
    padding-inline: 8px;
  }

  /* планшет: сітка портфоліо — явно 2 колонки (не auto-fit, щоб 4-та картка
     не "провисала" самотньо в третьому ряду). Вертикальний відступ між
     рядками карток (row-gap) — 48px, більший за горизонтальний (24px,
     var(--gutter), лишається без змін) — щоб два ряди карток явно
     відділялись одне від одного, а не зливались із внутрішнім ритмом
     картки (16/32px). */
  .portfolio-grid,
  .album-gallery-grid,
  .price-card-grid {
    grid-template-columns: repeat(2, 1fr);
    row-gap: 48px;
  }

  /* Баг: ширина 14.53125vw рахувалась від того самого коефіцієнта, що на
     1280 дає рівно 186px — але на планшеті/телефоні (де viewport вужчий, а
     --fs-intro тут вище вже зафіксований у px, не vw) той самий коефіцієнт
     давав box вужчий за сам текст "ЗАПИСАТИСЯ" — підпис-рамка (border-bottom)
     виходила коротшою за текст, який вилазив за неї. Тут, як і зі шрифтом,
     переходимо з vw на "hug": ширина = сама по собі, від тексту + падінг. */
  .portfolio-cta-button {
    width: fit-content;
    padding-inline: 24px;
  }

  /* мобільного/планшетного макета відгуків у Figma нема (як і в
     principles-section) — 604px картка з падінгом 105px фізично не влазить
     навіть у планшет, тому рішення власне: картка на всю ширину контейнера,
     падінг зменшено пропорційно. */
  .testimonial-card {
    width: 100%;
    padding: 48px 24px;
    gap: 20px;
  }

  /* ручний кроп під пропорції 1280×555 (десктоп) тут уже не підходить —
     на вужчому екрані секція набагато вища відносно ширини. Просто
     заповнюємо блок фото по центру, без спроби зберегти той самий кадр,
     що на десктопі. */
  .testimonial-bg-photo img {
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
  }

  /* мобільного/планшетного макета faq-section у Figma теж нема (той самий
     випадок, що testimonial-card/principle-item вище) — 906px-стеля на
     вузькому екрані виходить крихітною, тому список бере всю доступну
     ширину контейнера замість vw-формули. */
  .faq-list {
    width: 100%;
  }

  /* Юля попросила прибрати цю лінію (між "100€" і специфікаціями "від
     1 до 2,5 год..." тощо) на планшеті й телефоні — лишити тільки на
     десктопі. Ширину (width:100%, що стояла тут раніше) більше не
     задаю — за display:none вона однаково нічого не важить. */
  .price-divider {
    display: none;
  }

  /* Правило "зовнішня відстань блоку ≥ внутрішньої" — на телефоні/
     планшеті gap:32px (внутрішній, між headline-group/специфікаціями/
     лінком) був БІЛЬШИЙ за padding-top секції (зовнішній, 7.5vw — на
     375px це лише ~28px). Роблю gap тією самою формулою, що padding
     секції (7.5vw) — тепер вони завжди точно рівні на будь-якій ширині
     в цьому діапазоні, а не лише "на око" на одній контрольній точці.
     Той самий прийом, що вже застосований у faq-section вище. */
  .price-anchor-section {
    gap: 7.5vw;
  }

  /* той самий прийом "зовнішня ≥ внутрішня" — .contact-section теж має
     фіксований gap:32px (Figma) між заголовком/формою/лінками, який на
     вужчих екранах (нижче ~327px) стає більшим за padding-top секції
     (7.5vw). Рівняю gap до тієї самої формули на всьому діапазоні
     ≤1023px, а не тільки для телефону — так вони завжди точно рівні. */
  .contact-section {
    gap: 7.5vw;
  }

  /* мобільного/планшетного макета contact-form-section у Figma нема (той
     самий випадок, що faq-list/testimonial-card вище) — фіксована
     604px-формула поля на вузьких екранах або впритул, або вже вилазить
     за контент-бокс секції (перевірено виміром на 320px). Форма й кожне
     поле розтягуються на всю доступну ширину замість формули з 1280. */
  .contact-form,
  .form-field,
  .form-input,
  .custom-select {
    width: 100%;
  }

  /* та сама вада, що вже виправлена в .portfolio-cta-button (див. коментар
     там): vw-формула ширини (14.53125vw) розрахована під --fs-intro на
     1280, а тут при фіксованому мобільному --fs-meta box виходить вужчим
     за сам текст "ЗАПИСАТИСЯ" — перевірено виміром (54px box проти
     overflow тексту на 375px). Той самий перехід із vw на "hug". */
  .contact-cta-button {
    width: fit-content;
    padding-inline: 24px;
  }

  /* pro-mene.html — Юля скинула новий референс: на планшеті й телефоні
     фото зверху (не поруч із текстом), з вільним місцем СПРАВА (фото
     вужче за контейнер, притиснуте до лівого краю), текст (разом із
     "ПРИВІТ, Я ЮЛЯ...") — під фото. Спільне для обох рівнів —
     різниться лише сама ширина контейнера (.pro-mene-intro-row): 432px
     на планшеті (окремий блок нижче, та сама ширина, що текст
     "про мене" на головній), 100% на телефоні (телефонний блок нижче).

     Заголовок і текст — зліва (не по центру, Юля виправила після
     першої спроби), абзаци — justify (той самий вирівнювання, що на
     десктопі, це не змінювалось — центрування було зайвим кроком). */
  .pro-mene-intro-row {
    flex-direction: column;
    align-items: flex-start; /* фото зліва, простір справа */
  }

  .pro-mene-photo {
    width: 65%; /* лишає видиме вільне місце праворуч, як на референсі */
    max-width: none; /* десктопна vw-формула й телефонна 395px-стеля тут більше не діють */
    aspect-ratio: 395 / 531;
  }

  .pro-mene-intro-text {
    align-self: stretch; /* на всю ширину рядка (432px/100%) — фото звужене окремо, текст лишається "рамкою" на всю колонку */
    /* align-items успадковує базове flex-start (розділ 18 вище) —
       заголовок лишається зліва, а не шринкається-й-центрується. */
    width: auto;
    max-width: none;
    /* 223px-формула рахувалась під вирівнювання з фото ПОРУЧ (десктоп) —
       тут фото над текстом, тому звичайний gutter-ритм, як .price-outro. */
    gap: var(--gutter);
  }

  .pro-mene-bio-text {
    width: 100%; /* на всю ширину рамки — інакше justify нема від чого рахувати */
  }
}

/* ---- Тільки планшет (768–1023px): текст трохи більший ----
   Спільні --fs-* нижче (у @media max-width:1023px) розраховані під
   найвужчий телефон; на планшеті екран помітно ширший, тому тут злегка
   збільшуємо — САМЕ для 768–1023, телефон (≤767) лишається на базових
   значеннях. Мусить стояти в CSS ПІСЛЯ блоку max-width:1023px (там, де
   визначені базові --fs-*) — інакше цей, вужчий за діапазоном, програє
   в каскаді (у CSS порядок вирішує однакову специфічність, а не те,
   який @media "вужчий"). --lh-* самі перерахуються (unitless), окремо
   їх чіпати не треба. */
@media (min-width: 768px) and (max-width: 1023px) {
  :root {
    --fs-logo: 20px;
    --fs-vasek: 46px; /* раніше тут окремо піднімали тільки headline (46), а quote лишався 36 — розійшлись; тепер один розмір на весь Vasek */
    --fs-intro: 18px;
    --fs-meta: 16px;
    --fs-price: 105px; /* та сама пропорція 128/56 ≈ 2.286×--fs-vasek, що в спільному телефон-блоці вище */
    --fs-nav: 12px; /* та сама пропорція 12/16 (0.75×--fs-meta), що на 1280 */
    --fs-price-card: 29px; /* та сама пропорція 1.6×--fs-intro, що на 1280 (тут --fs-intro:18px вище) */
  }

  /* .about-photo-frame нижче лишається на спільних 160px (телефон+планшет) —
     при новому --fs-intro:18px напис "YULIA HAVRYLOVA" важить 161.8px,
     тобто вже ширший за саму рамку (переніс на 2 рядки). На телефоні (16px)
     все ще влазить, тому чіпаємо ширину рамки САМЕ тут, для планшета. */
  .about-photo-frame {
    width: 172px;
  }

  /* на планшеті .testimonial-card успадковував width:100% зі спільного
     блоку max-width:1023px (там воно розраховане для телефону, де картка
     й так одна вузька колонка) — на планшеті контент-бокс значно ширший
     (до ~975px), і картка розтягувалась впритул до нього, втрачаючи
     пропорції "картки" й виглядаючи як суцільний прямокутник. Звужуємо
     назад до чогось card-подібного, по центру (.testimonials-section і
     так flex + justify-content:center). */
  .testimonial-card {
    width: min(70vw, 480px);
  }

  /* Юля помітила: на планшеті текст "про мене" вужчий за текст у
     відгуках, хоча на десктопі вони буквально одна формула (min(30.78vw,
     591px)). Причина — .about-quote-text успадковував старий фіксований
     280px зі спільного блоку max-width:1023px (він там ще з часів, коли
     телефон і планшет не мали окремих правил; коли пізніше для телефону
     зробили свій override на 100%, для планшета "своєї" правки так і не
     додали — лишився той самий застарілий 280px). testimonial-quote на
     планшеті ширший: картка вище зафіксована на 480px, мінус її падінг
     24px×2 = 432px тексту. Тут та сама цифра, щоб колонки знову
     збігались, як і на десктопі. */
  .about-quote-text {
    width: 432px;
  }

  /* Юля попросила: інтро-текст на сторінці цін ("у кожну зйомку
     входить...") тієї самої ширини, що текст "про мене" на головній —
     та сама причина/те саме число, що .about-quote-text щойно вище (на
     max-width:1023px .album-desc сам по собі йде на 100% ширини секції,
     тут звужую ТІЛЬКИ цей екземпляр через .price-heading, не займаючи
     .album-desc в інших місцях сайту). */
  .price-heading .album-desc {
    width: 432px;
  }

  /* та сама правка, та сама причина — тепер для 3 абзаців умов унизу
     сторінки цін (price-outro-text: знижка/передоплата/дорога),
     Юля попросила ту саму ширину 432px, що "про мене". */
  .price-outro-text .album-desc {
    width: 432px;
  }

  /* pro-mene.html — контейнер фото+текст рівно 432px, та сама ширина
     "про мене"-тексту на головній (.about-quote-text щойно вище) —
     Юля попросила саме цю ширину як орієнтир. */
  .pro-mene-intro-row {
    width: 432px;
  }

  /* Юля попросила: текст 2-го блоку (цитата+філософія) на планшеті —
     та сама ширина, що в 1-му блоці (432px), а не своя vw-формула
     (325-434px для quote, 237-315px для story — обидві "пливли" по
     діапазону й не збігались з 1-м блоком). */
  .pro-mene-quote-text,
  .pro-mene-story-text {
    width: 432px;
  }

  /* protses.html — той самий 432px-орієнтир, що .about-quote-text, за
     тим самим принципом, що Юля вже застосувала до "про мене". */
  .process-text {
    width: 432px;
  }

  /* сторінки-альбоми (portfolio-family/lovestory/wedding/portrait) —
     інтро-опис під заголовком, той самий 432px-орієнтир, що
     .about-quote-text. Скопую ТІЛЬКИ .album-intro-section .album-desc
     (не займаю .album-desc на tsiny.html, там свій 432px вже висить
     через .price-heading/.price-outro-text). */
  .album-intro-section .album-desc {
    width: 432px;
  }

  /* kontakty.html — на планшеті 2 стовпці впритул стискали б форму
     (той самий випадок, що на телефоні, розділ max-width:767px нижче:
     604px-категорія полів не влазить у половину екрана). Той самий
     фікс: стек в один стовпець, фото-рамка зверху, форма знизу, звичайний
     скрол сторінки замість фіксованої "height" на весь екран. */
  .contacts-hero-section {
    grid-template-columns: 1fr;
    height: auto;
  }

  .contacts-photo {
    padding: 40px 0;
    border-right: none;
    border-bottom: 0.5px solid var(--ink);
  }

  .contacts-form-wrap {
    overflow-y: visible;
  }
}

/* ---- Тільки планшет (768–1023px): усі описи фізично переносяться на
   2 рядки (не просто резервують висоту з порожнім місцем) — вужчий
   max-width змушує навіть короткі речення зламатись на 2 рядки, тому
   всі 4 картки виглядають однаково заповненими, і фото стоять на одній
   лінії. Значення 260px підібране емпірично — дає рівно 2 рядки для
   всіх поточних описів на всій ширині 768–1023px (шрифт тут фіксований
   14px, тому фіксований px надійніший за %, який "плаває" з шириною
   картки). На десктопі (вужчі колонки) описи й так завжди в 2 рядки.
   На телефоні (1 колонка) картки не стоять поряд — вирівнювати нема сенсу. */
@media (min-width: 768px) and (max-width: 1023px) {
  .portfolio-card-desc {
    /* 260px було підібрано під шрифт 14px; після того, як --fs-meta на
       планшеті збільшили до 16px (той самий текст ширший на той самий
       рядок), при 260px один з описів почав переноситись на 3-й рядок —
       через це висота картки "пливла" відносно сусідньої в рядку.
       280px — заново виміряно (реальна ширина тексту) під новий 16px:
       усі 4 описи знову рівно в 2 рядки. */
    max-width: 280px;
    min-height: 2lh; /* підстраховка, якщо колись зміниться текст */
  }
}

/* ---- Тільки планшет (768–1023px): галерея більша, щоб заповнювати екран ----
   Базова десктопна формула (мінімум 186/240) на ширинах 768–1023 ще не встигає
   вирости — фото лишаються дрібними на вже широкому екрані. Тут швидша крива
   росту, яка виходить на той самий фінальний максимум (320/410), просто
   раніше — без "провалу" розміру рівно на межі 1024px (планшет → десктоп).
   БАГ, який тут був: без верхньої межі (min-width:768px, без max-width) це
   правило діяло і на десктопі теж, і на 1280px "перебивало" базову формулу
   (яка сама точно дає 186/240 — рівно Figma-розмір) значенням аж до
   320/410 — звідси й "занадто велика" галерея на 1280. */
@media (min-width: 768px) and (max-width: 1023px) {
  .hero-photo--tall {
    width: clamp(220px, 30vw, 320px);
  }

  .hero-photo--wide {
    width: clamp(280px, 38vw, 410px);
  }
}

/* ---- Телефон (≤767px) ---- */
@media (max-width: 767px) {
  /* Юля попросила divider трохи більшим саме на телефоні (кільця
     помітніші). Той самий crop-прийом, що в базовому правилі (розділ 6),
     просто масштабовано ×1.3 навколо того самого центру кілець — не
     навмання: підставила Z=1 у формулу масштабування й отримала точно ті
     самі числа, що вже в базовому правилі (-3.11%/-103.31%/106.22%/
     282.78%), тому Z=1.3 так само тримає кільця по центру смуги. */
  .divider-image img {
    left: -19.04%;
    top: -149.3%;
    width: 138.09%;
    height: 367.61%;
  }

  /* трохи більший Vasek-текст на телефоні (34→38px). Перевірено виміром
     реальної ширини (canvas.measureText) для всіх 3 рядків цитати — 38px
     дає запас ~25px на найдовшому рядку; 40px уже лишав лише ~8px запасу,
     а це саме та межа, на якій раніше "на реальному моніторі" щось таки
     переносилось (див. історію з фото Юлі) — тому свідомо не впритул. */
  /* весь інший текст теж трохи більший на телефоні (той самий принцип,
     що на планшеті) — перевірено виміром: лого при 20px лишає 26.6px
     запасу до бургер-кнопки, а от підпис "YULIA HAVRYLOVA" при
     --fs-intro:18px знову впритул перевищує стару рамку фото 160px
     (161.8px) — та сама історія, що на планшеті, тому рамку фото
     нижче теж збільшено до 172px (.about-photo-frame). */
  :root {
    --fs-vasek: 38px;
    --fs-logo: 20px;
    --fs-intro: 18px;
    --fs-meta: 16px;
    /* --fs-vasek тут піднято окремо (34→38, коментар вище) — синхронізуємо
       й --fs-price за тією самою пропорцією 128/56 ≈ 2.286×, інакше на
       реальному телефоні (не в спільному ≤1023-блоці) ціна лишилась би
       розрахованою під старе 34px */
    --fs-price: 87px;
    --fs-nav: 12px; /* та сама пропорція 12/16 (0.75×--fs-meta), що на 1280 і на планшеті */
    --fs-price-card: 29px; /* та сама пропорція 1.6×--fs-intro (18px тут), що на 1280 і на планшеті */
  }

  .about-photo-frame {
    width: 172px;
  }

  /* верх portfolio-section/album-intro-section був fluid (7.5vw ≈ 28px
     на 375px) — помітно менше за відступ хедер→заголовок у hero (56px,
     фіксовано). Роблю однаковим фіксованим значенням, щоб ритм зверху
     був однаковий. */
  .portfolio-section,
  .album-intro-section {
    padding-top: 56px;
  }

  /* .portfolio-section — низ теж 56px (симетрично з верхом, той самий
     запит, що вище на десктопі/планшеті: відстань від кнопки
     "ЗАПИСАТИСЯ" до кінця секції = відстань від верху до цитати).
     .album-intro-section НЕ чіпаю — там низ навмисно 0 (divider впритул
     до галереї, окремий запит).

     .album-gallery-section — та сама логіка: низ мав лишитись 7.5vw
     (≈28px на 375px, той самий "затісно", що вже виправляли для
     верху секцій вище) — тепер теж 56px, симетрично з верхом
     .album-intro-section на сторінці альбому (Юля попросила той самий
     принцип і тут). Верх .album-gallery-section НЕ чіпаю — там 24px
     навмисно, окремий запит "ближче до divider". */
  .portfolio-section,
  .album-gallery-section {
    padding-bottom: 56px;
  }

  /* відстань між цитатою й divider теж була fluid (3.75vw ≈ 14px на
     375px) — затісно (звірено виміром рядків, запас над найдовшим
     рядком лишається малим), тому на телефоні фіксую більшим значенням */
  .portfolio-lead {
    gap: 32px;
  }

  /* 2 колонки на телефоні (не 1, як .portfolio-grid) — Юля попросила
     "2 фото в ряд" саме для цієї галереї; той самий row-gap, що на
     планшеті вище, column-gap лишається var(--gutter) зі спільного
     правила (розділ 6.1). */
  .album-gallery-grid {
    grid-template-columns: repeat(2, 1fr);
    row-gap: 48px;
  }

  /* той самий sticky-scroll-jacking механізм (див. розділ 5 "Hero" вище)
     тепер працює на всіх розмірах екрана однаково — тут лишається тільки
     суто мобільний штрих відступу згори, fluid-варіант (7.5vw) на такому
     вузькому екрані був замалим */
  .hero-content {
    padding-top: 56px;
  }

  /* на телефоні лишається рівно 6 фото в стрічці (щоб скрол не був задовгим
     на маленькому екрані) — усі "додаткові" фото, які показуються тільки на
     десктопі/планшеті, тут просто ховаємо. */
  .hero-photo--extra {
    display: none;
  }

  /* телефон: сітка портфоліо — 1 колонка, з тим самим збільшеним
     вертикальним ритмом між картками, що й на планшеті (48px) —
     тут кожна картка сама по собі "ряд", тому весь gap вертикальний.
     (Пробували 2 колонки, Юля передумала — повернули як було.) Той самий
     принцип для .price-card-grid — картки з тим самим набором
     заголовок+специфікації+ціна, нема окремого мобільного макета в Figma. */
  .portfolio-grid,
  .price-card-grid {
    grid-template-columns: 1fr;
    row-gap: 48px;
  }

  /* на маленькому екрані 16/32px (десктопні значення) виглядають
     задалеко одне від одного — текст ніби "відклеюється" від картки.
     Зменшую пропорційно (та сама пропорція 1:2), щоб усе трималось
     разом як один блок */
  .portfolio-card-text {
    gap: 8px;
  }

  .portfolio-card,
  .price-card {
    gap: 20px;
  }

  .price-card-text {
    gap: 8px;
  }

  /* Юля попросила на телефоні прибрати фразу-підпис і розтягнути
     instagram/alicante по краях рядка (замість купки зліва) — мобільної
     версії цього блоку в Figma нема, розкладку для телефону вирішую сама. */
  .hero-meta-text {
    display: none;
  }

  .hero-meta-links {
    width: 100%;
    justify-content: space-between;
  }

  /* сітка на телефоні — одна колонка з падінгами var(--page-pad) з боків
     (задає сама секція). Раніше текстові блоки мали свою фіксовану ширину
     в px (280px / 290px), яка на реальному телефоні вужча за доступний
     контент-простір (напр. 375px - 2×24px = 327px) — лишався порожній
     "хвіст" замість того, щоб текст розтягувався до тих самих падінгів,
     що й решта сітки. 100% тут = ширина контент-боксу секції. */
  .about-quote-text {
    width: 100%;
  }

  .principle-item {
    width: 100%;
  }

  /* Юля попросила зменшити стрічку-скотч на телефоні — фіксований 199px
     (десктопний/планшетний розмір) на вузькій картці виглядає завеликим.
     top перераховано під той самий пропорційний "звис" (~half над краєм
     картки), що і в базовому правилі: 199/158×500 aspect → half висоти. */
  .decor-washi-tape {
    width: 130px;
    top: -21px;
  }

  /* на телефоні картка вужча (~279px тексту замість ~672px на планшеті),
     тому цитата переноситься на 4 рядки замість 3 — виміряла реально для
     всіх трьох відгуків: Люба/Діана рівно 4, Анжеліка (коротший текст) —
     лише 3. Без цього override картка з Анжелікою була б на 19px нижчою
     за решту, і стрілки під цитатою "стрибали" вгору-вниз при кожному
     перемиканні відгуку. */
  .testimonial-quote {
    min-height: calc(var(--lh-meta) * 4em);
  }

  /* .faq-section мав gap:32px (фіксований) між еірбров-заголовком
     "питання / вiдповiдь" і самим списком питань — на телефоні це
     виглядало помітно більшим, ніж відстань від верху секції до самого
     заголовка (padding-top секції, 7.5vw — та сама формула, що padding
     самої секції). Роблю gap рівним цій самій формулі, щоб "верх блоку
     → назва" і "назва → список питань" були однаковими. Тільки телефон —
     на десктопі 32px звірений з Figma (gap-[32px]), не чіпаю. */
  .faq-section {
    gap: 7.5vw;
  }

  /* ЦЕ й було справжньою причиною "не змінилось" минулого разу: реальна
     відстань від заголовка до ПЕРШОГО видимого питання = gap секції
     (щойно виправлений вище) + власний padding-top першого .faq-item
     (24px, я його не чіпала) = разом ~52px, вдвічі більше за "верх
     блоку → назва" (~28px). У першого пункту немає border-top (див.
     правило вище) — тому цей padding-top не відділяє його від жодної
     риски, а лише зайво віддаляє від заголовка. Прибираю його на
     телефоні — тепер "заголовок → перше питання" теж ~28px. */
  .faq-item:first-child {
    padding-top: 0;
  }

  /* .contact-secondary-links мав фіксований gap:80px (Figma, звірено на
     1280) — на вузькому телефоні (перевірено виміром на 320px: 3 слова
     разом ~149px + 2×80px gap виходять за контент-бокс секції, лінки
     вилазять за ліву межу). Зменшую тільки на телефоні — на планшеті й
     ширше 80px ще влазить без проблем (720px+ контенту). */
  .contact-secondary-links {
    gap: 40px;
  }

  /* .contacts-hero-section (kontakty.html, розділ 16) — на телефоні 2
     стовпці впритул стискали б і фото, і форму (604px-категорія полів
     не влазить у половину екрана). Стек в один стовпець: фото-рамка
     зверху (той самий центрований 290×390-блок, що на десктопі, лише
     з відступом замість border-right — ділити колонки вже нема сенсу),
     форма знизу на всю ширину. "height" з базового правила (розділ 16)
     скасовано на "auto" — на телефоні фото+форма разом свідомо вищі за
     один екран, і це нормально: тут, як і скрізь на сайті на
     мобільному, очікується звичайний скрол сторінки (Юлине прохання
     "без гортання" стосувалось десктопної двоколонкової верстки, де
     для цього достатньо місця по ширині). */
  .contacts-hero-section {
    grid-template-columns: 1fr;
    height: auto;
  }

  .contacts-photo {
    padding: 40px 0;
    border-right: none;
    border-bottom: 0.5px solid var(--ink); /* та сама риска, що ділила колонки на десктопі — тут знизу, бо стек */
  }

  .contacts-form-wrap {
    overflow-y: visible; /* на телефоні скрол — уся сторінка, не колонка */
  }

  /* pro-mene.html — контейнер фото+текст (.pro-mene-intro-row, спільні
     правила розкладки — розділ max-width:1023px вище) на телефоні на
     всю ширину секції (page-pad уже на самій секції, тут окремо не
     треба). На планшеті — свій фіксований 432px, окремий блок нижче. */
  .pro-mene-intro-row {
    width: 100%;
  }

  .pro-mene-quote-text,
  .pro-mene-story-text {
    width: 100%;
  }

  .process-text {
    width: 100%;
  }

  /* Юля попросила для ВСЬОГО сайту: на телефоні верх/низ секцій
     виглядали затісно проти бокових полів (7.5vw на 375px ≈ 28px —
     майже впритул до бокового page-pad:24px, "наляписто"). Правило:
     якщо бокові поля 24px, верх/низ мають бути вдвічі більші — 48px,
     фіксовано (не vw). Той самий принцип "зовнішня відстань ≥
     внутрішньої" (запис на початку файлу), тут явно 2× замість
     "просто більше".

     .hero-content/.portfolio-section/.album-intro-section/
     .album-gallery-section СЮДИ НЕ входять — вони вже отримали свій
     фіксований мобільний padding (56px) в окремому запиті ДО цього
     (розділ вище, "верх portfolio-section/album-intro-section був
     fluid... роблю однаковим фіксованим значенням") — не займаю
     повторно, той фікс лишається як є. .contacts-hero-section і
     .footer-main/.footer-bottom теж НЕ займаю — обидва мають власну
     логіку padding (перший — "влазить в один екран", другий —
     навмисно компактний рівний 24px по всіх сторонах), непридатну до
     цього правила. */
  .about-section,
  .principles-section,
  .testimonials-section,
  .price-anchor-section,
  .faq-section,
  .contact-section,
  .tsiny-list-section,
  .pro-mene-intro-section,
  .pro-mene-story-section,
  .process-section {
    padding-top: 48px;
    padding-bottom: 48px;
  }
}
