/* frontend/site/site.css, the public site's foundation: tokens for both
 * themes, type, buttons, the header, the footer, entrances, page transitions
 * and the shell pages. Every value comes from the approved prototype in
 * docs/redesign/prototype/, and every component reads a token rather than a
 * literal. The home page adds home.css and the envelope adds envelope.css.
 */

@font-face {
  font-family: "Playfair Display";
  src: url("/assets/fonts/playfair.woff2") format("woff2");
  font-weight: 400 900;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Montserrat";
  src: url("/assets/fonts/montserrat.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

:root {
  color-scheme: light;
  --font-display: "Playfair Display", Georgia, "Times New Roman", serif;
  --font-body: "Montserrat", system-ui, -apple-system, "Segoe UI", sans-serif;

  /* Cream. */
  --bg: #FAF6EF;
  --bg2: #F2EBE0;
  --surface: #FFFFFF;
  --ink: #141010;
  --ink2: #3F3631;
  --muted: #80746A;
  --line: #E7DDD0;
  --accent: #9A2C4C;
  --accent-soft: #F6E3E8;
  --imgline: oklch(0 0 0 / 0.1);
  --paper: #F1E7DB;
  --paper-deep: #E1D1BF;
  --paper-flap: #EADCCA;
  --header-glass: rgb(250 246 239 / 0.78);
  --menu-bg: #FFFAF3;
  --menu-hover: #F2EBE0;

  /* Colours that sit on a photograph and so do not change with the theme. */
  --on-photo: #FFFAF3;
  --on-photo-soft: rgb(255 250 243 / 0.84);
  --on-photo-line: rgb(255 250 243 / 0.45);
  --on-photo-glass: rgb(255 250 243 / 0.12);
  --scrim: 14 10 8;
  --night: #141010;
  --phone: #0E0B09;

  --shadow-lift: 0 1px 2px rgb(0 0 0 / 0.05), 0 50px 90px -45px rgb(0 0 0 / 0.55);
  --shadow-menu: 0 20px 40px -18px rgb(0 0 0 / 0.45);

  /* Motion. Nothing on the site names a literal curve. */
  --ease-out: cubic-bezier(.23, 1, .32, 1);
  --ease-in-out: cubic-bezier(.77, 0, .175, 1);
  --ease-drawer: cubic-bezier(.32, .72, 0, 1);
  --ease-photo: cubic-bezier(.16, 1, .3, 1);
  --dur-press: 160ms;
  --dur-hover: 150ms;
  --dur-ui: 200ms;
  --dur-reveal: 900ms;

  --gutter: clamp(16px, 5vw, 72px);
  --max: 1440px;
  --header-h: 64px;
  --radius-photo: 4px;
}

@media (min-width: 900px) {
  :root { --header-h: 96px; }
}

/* Dark, a charcoal with only a trace of warmth, the same dark the host's
   dashboard uses, with the site's rose kept as its accent. It was a brown
   cappuccino, and Stefan found it read as a brown theme rather than a dark
   one. It follows the system until the visitor picks a theme in the header,
   which the server renders onto the page as data-theme. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --bg: #141312;
    --bg2: #1B1A18;
    --surface: #22211F;
    --ink: #F4F1EC;
    --ink2: #D6D1C9;
    --muted: #A39E96;
    --line: #34322E;
    --accent: #E6A0B1;
    --accent-soft: #362A2B;
    --imgline: oklch(1 0 0 / 0.1);
    --paper: #2E2C29;
    --paper-deep: #242220;
    --paper-flap: #383532;
    --header-glass: rgb(20 19 18 / 0.78);
    --menu-bg: #22211F;
    --menu-hover: #34322E;
  }
}

:root[data-theme="dark"] {
  color-scheme: dark;
  --bg: #141312;
  --bg2: #1B1A18;
  --surface: #22211F;
  --ink: #F4F1EC;
  --ink2: #D6D1C9;
  --muted: #A39E96;
  --line: #34322E;
  --accent: #E6A0B1;
  --accent-soft: #362A2B;
  --imgline: oklch(1 0 0 / 0.1);
  --paper: #2E2C29;
  --paper-deep: #242220;
  --paper-flap: #383532;
  --header-glass: rgb(20 19 18 / 0.78);
  --menu-bg: #22211F;
  --menu-hover: #34322E;
}

/* The theme swap changes every colour at once, and letting each element's
   own transition run would ripple the page for a moment. */
.theme-switching, .theme-switching * { transition: none !important; }

/* ── Base ──────────────────────────────────────────────────────────────── */

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

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  scroll-padding-top: calc(var(--header-h) + 12px);
}

@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}

/* The page itself never scrolls sideways. The body's own clip below is handed
   to the viewport when the root has none, and there it let a face ring drawn
   at 1.6 times before its entrance push the phone home page 19 pixels wide. */
html:has(body.site) { overflow-x: clip; }

body.site {
  margin: 0;
  min-height: 100vh;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: clip;
  /* Stefan asked for the public site not to be selectable (27 September
     2026), so a stray drag over a page never highlights its copy. Anything a
     visitor types into stays selectable below. */
  -webkit-user-select: none;
  user-select: none;
}
body.site :is(input, textarea, select, [contenteditable="true"]) {
  -webkit-user-select: text;
  user-select: text;
}

:where(.site) a { color: inherit; text-decoration: none; }
:where(.site) img { display: block; max-width: 100%; }
/* The browser's own default gives every <figure> a 40px inline margin; left
   unreset it shifted each design-tile card-composed 40px right of its grid
   cell, so the last column ran past a narrow viewport (invisibly, since
   overflow-x: clip above hides it) and every row opened with an empty gutter
   the width of that same 40px, found auditing the designs page on a phone. */
:where(.site) figure { margin: 0; }
:where(.site) :is(h1, h2, h3) {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 400;
  text-wrap: balance;
}
:where(.site) p { margin: 0; text-wrap: pretty; }
:where(.site) button { font: inherit; color: inherit; }
.site :focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 4px; }

.wrap {
  width: 100%;
  max-width: var(--max);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.skip-link {
  position: absolute;
  left: 12px;
  top: -80px;
  z-index: 100;
  padding: 12px 18px;
  border-radius: 999px;
  background: var(--ink);
  color: var(--bg);
  font-weight: 600;
}
.skip-link:focus { top: 12px; }

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.eyebrow {
  font-size: 12px;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--muted);
}

.display-1 {
  font-size: clamp(44px, 6.7vw, 96px);
  line-height: .98;
  letter-spacing: -.025em;
}

.display-2 {
  font-size: clamp(38px, 4.45vw, 64px);
  line-height: 1.02;
  letter-spacing: -.02em;
}

.lede {
  font-size: 16px;
  line-height: 1.75;
  color: var(--ink2);
  max-width: 560px;
}

/* ── Buttons ───────────────────────────────────────────────────────────── */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: 54px;
  padding: 0 30px;
  border: 0;
  border-radius: 999px;
  font-family: var(--font-body);
  font-size: 14px;
  font-weight: 600;
  letter-spacing: .02em;
  text-align: center;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition-property: transform, background-color, color, box-shadow;
  transition-duration: var(--dur-press), var(--dur-hover), var(--dur-hover), var(--dur-hover);
  transition-timing-function: var(--ease-out), ease, ease, ease;
}
.btn:active { transform: scale(.96); transition-duration: 120ms; }
@media (hover: hover) and (pointer: fine) {
  .btn:hover { transform: translateY(-2px); }
  .btn:hover:active { transform: scale(.96); }
}
.btn-primary { background: var(--ink); color: var(--bg); }
.btn-secondary { background: transparent; color: var(--ink); box-shadow: inset 0 0 0 1px var(--ink); }
.btn-light { background: var(--on-photo); color: var(--night); }
.btn-glass { background: var(--on-photo-glass); color: var(--on-photo); box-shadow: inset 0 0 0 1px var(--on-photo-line); -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px); }

.chip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 44px;
  min-width: 44px;
  padding: 0 14px;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: inherit;
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  box-shadow: inset 0 0 0 1px var(--chip-line, currentColor);
  -webkit-tap-highlight-color: transparent;
  transition-property: transform, background-color, box-shadow;
  transition-duration: var(--dur-press), var(--dur-hover), var(--dur-hover);
  transition-timing-function: var(--ease-out), ease, ease;
}
.chip:active { transform: scale(.96); }
@media (hover: hover) and (pointer: fine) {
  .chip:hover { background: color-mix(in oklab, currentColor 8%, transparent); }
}

/* The family switch, a question asked in words above the five families, at
   the head of the home page's film and prices and on /pricing/. Each option
   is outlined, because a row of bare labels did not read as something to
   press. The hero's own switch sits on its photograph and is home.css's. */
.family-switch {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 10px;
  min-width: 0;
}
.family-switch-label {
  margin: 0;
  color: var(--ink2);
  font-size: 14px;
  font-weight: 500;
  letter-spacing: .01em;
}
.family-tabs { display: flex; flex-wrap: wrap; gap: 6px; }
.family-tab {
  flex: none;
  min-height: 44px;
  padding: 0 18px;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--ink);
  font: inherit;
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--ink) 22%, transparent);
  -webkit-tap-highlight-color: transparent;
  transition-property: transform, background-color, color, box-shadow;
  transition-duration: var(--dur-press), var(--dur-hover), var(--dur-hover), var(--dur-hover);
  transition-timing-function: var(--ease-out), ease, ease, ease;
}
.family-tab:active { transform: scale(.96); }
.family-tab[aria-selected="true"] { background: var(--ink); color: var(--bg); box-shadow: none; }
.family-tab:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
@media (hover: hover) and (pointer: fine) {
  .family-tab[aria-selected="false"]:hover { box-shadow: inset 0 0 0 1px var(--ink2); }
}
/* On a phone the families fill the width in two rows rather than scroll,
   because a scrolling row hid the last three. */
@media (max-width: 860px) {
  .family-switch { align-self: stretch; }
  .family-tab { flex: 1 1 auto; }
}
@media (prefers-reduced-motion: reduce) {
  .family-tab { transition: none; }
}

/* ── Header ────────────────────────────────────────────────────────────── */

.site-header {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 50;
  height: var(--header-h);
  background: var(--header-glass);
  color: var(--ink);
  --chip-line: color-mix(in oklab, var(--ink) 35%, transparent);
  box-shadow: 0 1px 0 var(--line);
  -webkit-backdrop-filter: blur(18px) saturate(1.4);
  backdrop-filter: blur(18px) saturate(1.4);
  view-transition-name: site-header;
  transition-property: background-color, color, box-shadow;
  transition-duration: var(--dur-ui);
  transition-timing-function: var(--ease-out);
}
/* Over the home page's photograph the header is clear with light type until
   site.js marks it solid, once the page scrolls or the phone sheet opens. */
body[data-header="photo"] .site-header:not(.is-solid) {
  background: transparent;
  color: var(--on-photo);
  --chip-line: var(--on-photo-line);
  box-shadow: none;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}
.site-header-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  height: 100%;
}
.site-brand {
  font-family: var(--font-display);
  font-size: 24px;
  letter-spacing: .01em;
  line-height: 1;
  white-space: nowrap;
}
.site-nav { display: none; }
.site-nav > a, .site-products-toggle {
  position: relative;
  font-size: 13px;
  font-weight: 500;
  letter-spacing: .06em;
  padding: 12px 0;
  white-space: nowrap;
}
.site-nav > a::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 6px;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--dur-hover) var(--ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .site-nav > a:hover::after { transform: scaleX(1); }
}
.site-tools { display: flex; align-items: center; gap: 10px; font-size: 13px; }
.site-tools .site-login, .site-tools .site-start, .site-tools .site-lang, .site-tools .site-theme { display: none; }
.site-login { padding: 12px 6px; font-weight: 500; }
.site-start { min-height: 46px; padding: 0 22px; white-space: nowrap; }
body[data-header="photo"] .site-header:not(.is-solid) .site-start { background: var(--on-photo); color: var(--night); }

.site-menu-toggle { width: 44px; padding: 0; }
.site-menu-toggle .icon-close, .site-menu-toggle[aria-expanded="true"] .icon-menu { display: none; }
.site-menu-toggle[aria-expanded="true"] .icon-close { display: block; animation: menu-in var(--dur-press) var(--ease-out) both; }

@media (min-width: 1080px) {
  .site-brand { font-size: 30px; }
  .site-nav { display: flex; align-items: center; gap: 24px; }
  .site-tools { gap: 14px; }
  .site-tools .site-login, .site-tools .site-start { display: inline-flex; }
  .site-tools .site-lang, .site-tools .site-theme { display: inline-flex; }
  .site-menu-toggle { display: none; }
}
/* The products dropdown made the bar one item longer, and Albanian's longer
   words ran it out of room below this width. */
@media (min-width: 1280px) {
  .site-nav { gap: 38px; }
}

/* The language dropdown, in the header on a wide screen and in the menu
   sheet on a phone, and the products dropdown, which only the wide header
   has because the sheet lists the product pages outright. */
.site-lang, .site-products { position: relative; }
.site-lang-list, .site-products-list {
  position: absolute;
  right: 0;
  top: calc(100% + 8px);
  z-index: 5;
  min-width: 180px;
  margin: 0;
  padding: 6px;
  list-style: none;
  border-radius: 14px;
  background: var(--menu-bg);
  color: var(--ink);
  box-shadow: var(--shadow-menu), 0 0 0 1px var(--line);
  transform-origin: top right;
}
.site-products-list { right: auto; left: -14px; min-width: 220px; transform-origin: top left; }
.site-lang-list:not([hidden]), .site-products-list:not([hidden]) { display: flex; flex-direction: column; animation: menu-in var(--dur-press) var(--ease-out) both; }
.site-products-toggle {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border: 0;
  background: transparent;
  color: inherit;
  cursor: pointer;
}
.site-products-toggle svg { transition: transform var(--dur-press) var(--ease-out); }
.site-products-toggle[aria-expanded="true"] svg { transform: rotate(180deg); }
.site-lang-option, .site-products-list a {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  min-height: 44px;
  padding: 0 14px;
  border: 0;
  border-radius: 10px;
  background: transparent;
  font-size: 14px;
  text-align: left;
  cursor: pointer;
  transition: background-color var(--dur-hover) ease;
}
.site-lang-option[aria-selected="true"] { background: var(--menu-hover); font-weight: 600; }
@media (hover: hover) and (pointer: fine) {
  .site-lang-option:hover, .site-products-list a:hover { background: var(--menu-hover); }
}
@keyframes menu-in { from { opacity: 0; transform: scale(.96); } to { opacity: 1; transform: none; } }

.site-theme svg { width: 17px; height: 17px; }
.site-theme .icon-sun { display: none; }
:root[data-theme="dark"] .site-theme .icon-sun { display: block; }
:root[data-theme="dark"] .site-theme .icon-moon { display: none; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .site-theme .icon-sun { display: block; }
  :root:not([data-theme="light"]) .site-theme .icon-moon { display: none; }
}

/* The phone menu is a sheet that drops from under the bar. */
.site-sheet {
  position: fixed;
  inset: var(--header-h) 0 auto 0;
  z-index: 49;
  max-height: calc(100dvh - var(--header-h));
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 12px var(--gutter) 28px;
  background: var(--bg);
  color: var(--ink);
  box-shadow: 0 1px 0 var(--line), 0 30px 60px -30px rgb(0 0 0 / 0.35);
  --chip-line: color-mix(in oklab, var(--ink) 35%, transparent);
}
.site-sheet:not([hidden]) { animation: sheet-in 320ms var(--ease-drawer) both; }
/* The page holds still under the open sheet; a swipe over it scrolled the page
   behind, which showed through the strip below the sheet (2 October 2026). */
html.is-sheet-open { overflow: hidden; }
@keyframes sheet-in { from { opacity: 0; transform: translateY(-12px); } to { opacity: 1; transform: none; } }
.site-sheet nav { display: flex; flex-direction: column; }
.site-sheet nav a {
  display: flex;
  align-items: center;
  min-height: 56px;
  border-bottom: 1px solid var(--line);
  font-family: var(--font-display);
  font-size: 26px;
}
.site-sheet-tools { display: flex; align-items: center; gap: 10px; margin-top: 20px; }
.site-sheet-tools .site-lang-list { right: auto; left: 0; transform-origin: top left; }
.site-sheet-actions { display: grid; gap: 10px; margin-top: 20px; }
@media (min-width: 1080px) {
  .site-sheet { display: none !important; }
}

/* Pages without a photograph under the header start below it. */
.site main { display: block; }
.site-page-hero { padding-top: calc(var(--header-h) + clamp(56px, 7vw, 96px)); }

/* ── Footer ────────────────────────────────────────────────────────────── */

.site-footer {
  border-top: 1px solid var(--line);
  color: var(--ink2);
  font-size: 13px;
}
.site-footer-bar {
  display: flex;
  flex-direction: column;
  gap: 24px;
  padding-block: 44px;
}
.site-footer-mark { display: flex; flex-direction: column; gap: 6px; }
.site-footer-brand { font-family: var(--font-display); font-size: 26px; line-height: 1.1; color: var(--ink); }
.site-footer-links { display: flex; flex-wrap: wrap; gap: 4px 24px; margin: 0; padding: 0; list-style: none; }
.site-footer-links a { display: inline-flex; align-items: center; min-height: 44px; }
@media (hover: hover) and (pointer: fine) {
  .site-footer-links a { transition: color var(--dur-hover) ease; }
  .site-footer-links a:hover { color: var(--ink); }
}
.site-footer-contact a { display: inline-flex; align-items: center; min-height: 44px; }
@media (min-width: 900px) {
  .site-footer-bar { flex-direction: row; align-items: center; justify-content: space-between; padding-block: 56px; }
  .site-footer-links { gap: 0 28px; }
}

/* A value only Stefan can give, shown as a bracket rather than invented. */
.needs-confirmation { color: var(--accent); }
.needs-confirmation-block {
  padding: 14px 18px;
  border-radius: 10px;
  background: var(--accent-soft);
  color: var(--ink);
  font-size: 14px;
}

/* ── Entrances ─────────────────────────────────────────────────────────── */
/* An entrance plays once, when motion.js first sees the section, and never
   again. The hidden state is set only where a script will lift it, so a page
   read without scripts shows everything. Pieces of one section stagger by
   about a tenth of a second, which motion.js writes as --i. */
@media (scripting: enabled) and (prefers-reduced-motion: no-preference) {
  .reveal:not(:has(.reveal-item)), .reveal .reveal-item {
    opacity: 0;
    transform: translateY(26px);
  }
  .reveal.is-revealed:not(:has(.reveal-item)), .reveal.is-revealed .reveal-item {
    opacity: 1;
    transform: none;
    transition-property: opacity, transform;
    transition-duration: var(--dur-reveal);
    transition-timing-function: var(--ease-photo);
    transition-delay: calc(var(--i, 0) * 100ms);
  }
}

/* ── Page transitions ──────────────────────────────────────────────────── */
/* The browser's own cross document view transition carries the visitor from
   page to page. The header is named so it holds still while the page under
   it crossfades with a small rise. */
@view-transition { navigation: auto; }
::view-transition-old(root) { animation: page-out 180ms var(--ease-out) both; }
::view-transition-new(root) { animation: page-in 420ms var(--ease-out) both; }
@keyframes page-out { to { opacity: 0; } }
@keyframes page-in { from { opacity: 0; transform: translateY(10px); } }
::view-transition-group(site-header) { animation-duration: var(--dur-ui); animation-timing-function: var(--ease-out); }

@media (prefers-reduced-motion: reduce) {
  @view-transition { navigation: none; }
}

/* ── Shell pages ───────────────────────────────────────────────────────── */

.site-page-hero { padding-bottom: clamp(40px, 6vw, 80px); border-bottom: 1px solid var(--line); }
.site-page-hero h1 {
  max-width: 16ch;
  font-size: clamp(42px, 5.6vw, 80px);
  line-height: 1;
  letter-spacing: -.022em;
}
.site-page-hero .subline {
  margin-top: 22px;
  max-width: 620px;
  font-size: 18px;
  line-height: 1.7;
  color: var(--ink2);
}

.site-product { padding-block: clamp(56px, 9vw, 130px); }
.site-product .wrap { display: grid; gap: 36px; align-items: center; }
.site-product h2 { font-size: clamp(34px, 3.9vw, 56px); line-height: 1.04; letter-spacing: -.02em; }
.site-product p { margin-top: 18px; font-size: 16px; line-height: 1.75; color: var(--ink2); max-width: 540px; }
.site-product .eyebrow { display: block; margin-bottom: 18px; }
.site-product .media {
  overflow: hidden;
  aspect-ratio: 4 / 5;
  border-radius: var(--radius-photo);
  outline: 1px solid var(--imgline);
  outline-offset: -1px;
}
.site-product .media img { width: 100%; height: 100%; object-fit: cover; }
.site-product + .site-product { border-top: 1px solid var(--line); }
@media (min-width: 900px) {
  .site-product .wrap { grid-template-columns: repeat(12, minmax(0, 1fr)); gap: 26px; }
  .site-product .wrap > :first-child { grid-column: 1 / span 6; }
  .site-product .media { grid-column: 8 / span 5; }
  .site-product.is-reversed .wrap > :first-child { grid-column: 7 / span 6; grid-row: 1; }
  .site-product.is-reversed .media { grid-column: 1 / span 5; grid-row: 1; }
}

.site-founder { padding-block: clamp(56px, 8vw, 110px); background: var(--bg2); }
.site-founder h2 { font-size: clamp(32px, 3.4vw, 48px); line-height: 1.05; margin-bottom: 22px; }
.site-founder .needs-confirmation-block { max-width: 640px; }

.site-closing { padding-block: clamp(64px, 10vw, 140px); text-align: center; }
.site-closing h2 {
  max-width: 18ch;
  margin-inline: auto;
  font-size: clamp(38px, 4.45vw, 64px);
  line-height: 1.02;
  letter-spacing: -.02em;
}
.site-closing .actions { justify-content: center; margin-top: 32px; }

.actions { display: flex; flex-wrap: wrap; gap: 12px; }

.site-404 { padding-top: calc(var(--header-h) + clamp(64px, 12vw, 160px)); padding-bottom: clamp(80px, 12vw, 160px); }
.site-404 h1 { font-size: clamp(44px, 6.7vw, 96px); line-height: .98; letter-spacing: -.025em; max-width: 14ch; }
.site-404 .subline { margin-top: 22px; max-width: 540px; font-size: 18px; line-height: 1.7; color: var(--ink2); }
.site-404 .actions { margin-top: 32px; }

/* The accordion every FAQ uses. An answer opens by its row growing from 0fr
   to 1fr, so it slides open at its own height with no measuring. */
.faq-item { border-bottom: 1px solid var(--line); }
.faq-question {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  width: 100%;
  min-height: 64px;
  padding: 18px 0;
  border: 0;
  background: transparent;
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 17px;
  font-weight: 500;
  line-height: 1.45;
  text-align: left;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.faq-question .sign {
  position: relative;
  flex-shrink: 0;
  width: 18px;
  height: 18px;
  font-size: 0;
  transition: transform var(--dur-ui) var(--ease-out);
}
.faq-question .sign::before, .faq-question .sign::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 14px;
  height: 1.5px;
  border-radius: 1px;
  background: currentColor;
  transform: translate(-50%, -50%);
}
.faq-question .sign::after { transform: translate(-50%, -50%) rotate(90deg); }
.faq-item.is-open .sign { transform: rotate(45deg); }
.faq-answer {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 280ms var(--ease-out);
}
.faq-answer > * {
  min-height: 0;
  overflow: hidden;
  opacity: 0;
  transition: opacity var(--dur-ui) var(--ease-out);
}
/* The space under an answer belongs to an open answer only: in the collapsed
   row padding cannot shrink, and 22 pixels of it sat under every closed
   question, setting each one off centre in its row. */
.faq-answer p { padding: 0 60px 0 0; font-size: 15px; line-height: 1.75; color: var(--ink2); transition: padding-bottom 280ms var(--ease-out); }
.faq-item.is-open .faq-answer { grid-template-rows: 1fr; }
.faq-item.is-open .faq-answer > * { opacity: 1; }
.faq-item.is-open .faq-answer p { padding-bottom: 22px; }
@media (max-width: 599px) {
  .faq-answer p { padding-right: 0; }
}

.site-faq { padding-block: clamp(40px, 6vw, 80px); }
.site-faq .wrap { max-width: 980px; }
.site-faq .wrap > .faq-item:first-child,
.site-faq .faq-group + .faq-item { border-top: 1px solid var(--line); }
.faq-group { margin: clamp(40px, 5vw, 64px) 0 14px; font-size: clamp(24px, 2.4vw, 32px); line-height: 1.1; }
.faq-group:first-child { margin-top: 0; }

/* Contact. */
.site-contact { padding-block: clamp(48px, 7vw, 100px); }
.contact-card {
  max-width: 640px;
  padding: clamp(24px, 4vw, 44px);
  border-radius: 20px;
  background: var(--surface);
  box-shadow: 0 0 0 1px var(--line);
}
.contact-card h2 { font-size: clamp(30px, 3vw, 42px); line-height: 1.05; }
.contact-card > p { margin-top: 14px; color: var(--ink2); line-height: 1.7; }
.contact-line { display: flex; flex-wrap: wrap; gap: 4px 12px; padding: 14px 0; border-top: 1px solid var(--line); }
.contact-line:first-of-type { margin-top: 22px; }
.contact-label { min-width: 110px; font-weight: 600; }
.contact-note { max-width: 640px; margin-top: 20px; font-size: 14px; color: var(--muted); }

/* Privacy, terms and cookies read as a document at a comfortable measure. */
.site-legal { padding-block: clamp(40px, 6vw, 80px); }
.site-legal .wrap { max-width: 820px; }
.site-legal h2 { margin-top: 48px; margin-bottom: 14px; font-size: clamp(26px, 2.6vw, 34px); line-height: 1.1; }
.site-legal p, .site-legal li { font-size: 16px; line-height: 1.8; color: var(--ink2); }
.site-legal p + p { margin-top: 14px; }
.legal-list { margin: 14px 0 0; padding-left: 1.2em; }
.legal-list li + li { margin-top: 8px; }
.legal-review-banner {
  padding: 16px 20px;
  border-radius: 12px;
  background: var(--bg2);
  box-shadow: inset 0 0 0 1px var(--line);
  font-size: 14px;
}
.legal-review-banner p { color: var(--ink); }
.legal-controller h2 { margin-top: 32px; }
.legal-controller .needs-confirmation-block + .needs-confirmation-block { margin-top: 8px; }
.cookie-table-scroll { margin-top: 18px; overflow-x: auto; border-radius: 12px; box-shadow: 0 0 0 1px var(--line); }
.cookie-table { width: 100%; min-width: 560px; border-collapse: collapse; font-size: 14px; }
.cookie-table th, .cookie-table td { padding: 12px 16px; border-bottom: 1px solid var(--line); text-align: left; vertical-align: top; line-height: 1.55; }
.cookie-table thead th { background: var(--bg2); font-weight: 600; }
.cookie-table tbody th { font-weight: 600; white-space: nowrap; }
.cookie-table tr:last-child > * { border-bottom: 0; }

@media (prefers-reduced-motion: reduce) {
  .faq-answer, .faq-answer > *, .faq-question .sign { transition: none; }
}

/* ── On a phone ────────────────────────────────────────────────────────── */
/* A phone is read at arm's length and steered with a thumb, so below 700
   pixels no text is smaller than 14 pixels, copy meant to be read is 16, and
   every control is at least 44 pixels each way. The sizes above are the
   prototype's desktop ones and stay as they are. */
@media (max-width: 699px) {
  .eyebrow { font-size: 14px; letter-spacing: .14em; }
  .chip { font-size: 14px; }
  .site-brand, .site-footer-brand { display: inline-flex; align-items: center; min-height: 44px; }
  .site-footer { font-size: 14px; }
  .site-footer-mark p { font-size: 16px; }
  .site-footer-links a { min-width: 44px; }
  .faq-answer p { font-size: 16px; }
  /* A four column table needs 560 pixels, so on a phone each row becomes a
     card, its name on top and every value under the column's own name,
     rather than a table the visitor has to drag sideways. */
  .cookie-table-scroll { overflow: visible; border-radius: 0; box-shadow: none; }
  .cookie-table, .cookie-table tbody, .cookie-table tr, .cookie-table th, .cookie-table td { display: block; }
  .cookie-table { min-width: 0; font-size: 16px; }
  .cookie-table thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
  .cookie-table tr { padding: 16px 18px; border-radius: 12px; box-shadow: 0 0 0 1px var(--line); }
  .cookie-table tr + tr { margin-top: 10px; }
  .cookie-table tbody th, .cookie-table td { padding: 4px 0; border-bottom: 0; white-space: normal; }
  .cookie-table tbody th { font-size: 17px; }
  .cookie-table td::before { content: attr(data-label); display: block; font-size: 14px; font-weight: 600; color: var(--muted); }
}

/* A phone or a tablet showing the desktop layout is still steered with a
   thumb, so the links it reaches keep the 44 pixel floor wherever the
   pointer is coarse, whatever the width. The text keeps its desktop size,
   because the header's links only just fit its row at 1080 pixels. */
@media (hover: none) and (pointer: coarse) {
  .site-brand, .site-footer-brand { display: inline-flex; align-items: center; min-height: 44px; }
  .site-footer-links a { min-width: 44px; }
  .site-nav > a, .site-products-toggle { display: inline-flex; align-items: center; min-height: 44px; padding-block: 0; }
}

/* ── The action bar ────────────────────────────────────────────────────── */
/* Most visitors arrive on a phone, where the hero's buttons are gone after
   the first swipe. The bar brings the page's one action back at the foot of
   the screen, slides away over the page's own closing call and the footer,
   and stands clear of the home indicator. site.js decides when it shows. */
.action-bar { display: none; }
@media (max-width: 699px) {
  .action-bar {
    position: fixed;
    inset: auto 0 0 0;
    z-index: 45;
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 8px var(--gutter) calc(10px + env(safe-area-inset-bottom));
    background: var(--header-glass);
    box-shadow: 0 -1px 0 var(--line);
    -webkit-backdrop-filter: blur(18px) saturate(1.4);
    backdrop-filter: blur(18px) saturate(1.4);
    transform: translateY(calc(100% + 2px));
    transition: transform 320ms var(--ease-drawer);
  }
  .action-bar.is-shown { transform: none; }
  .action-bar__button { min-height: 48px; }
  .action-bar__note { font-size: 14px; line-height: 1.35; text-align: center; color: var(--ink2); }
  /* The page ends the bar's height lower, so nothing is ever left under it,
     and a link or a focused field scrolls to above it. */
  body.site:has(.action-bar) { padding-bottom: calc(88px + env(safe-area-inset-bottom)); }
  html:has(.action-bar) { scroll-padding-bottom: calc(100px + env(safe-area-inset-bottom)); }
}
@media (prefers-reduced-motion: reduce) {
  .action-bar { transition: none; }
}

/* A composed sample card: a bare painted background under a live text
   layer, read in the page's own language instead of painted only in
   Macedonian (Stefan, 27 September 2026, docs/redesign/prototype/README.md).
   Built by site_products.py's _card_figure_html for the designs and printed
   pages and by frontend/site/card-text.js for the home hero and film, both
   reading the same five positions here so the two never drift apart.
   container-type makes each line's cqw font size track the card's own
   rendered width, so one set of rules fits the design grid's small tile, the
   full-size viewer and the envelope's card slot alike. */
.card-composed {
  position: relative;
  display: block;
  width: 100%;
  aspect-ratio: 640 / 900;
  container-type: inline-size;
}
.card-composed__bg { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: top; }
.card-composed__text { position: absolute; inset: 0; }
.card-line {
  position: absolute;
  left: 50%;
  width: 82%;
  margin: 0;
  transform: translateX(-50%);
  text-align: center;
  line-height: 1.15;
  /* The card's own background is a painted scene, not a plain paper, so its
     wording carries a soft shadow to stay readable over a busy corner, dark
     ink and light ink alike, never a hard outline. */
  text-shadow: 0 1px 4px rgb(0 0 0 / .22);
}
