/* Obscura — main stylesheet. Tokens in tokens.css. */

*, *::before, *::after { box-sizing: border-box; }
html, body { overflow-x: clip; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--color-paper);
  color: var(--color-ink);
  font-family: var(--font-body);
  font-size: var(--text-base);
  line-height: var(--leading-body);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }

/* Skip link. Offscreen rather than display:none so it stays in the tab order —
   hiding it outright is the usual way this control ends up unreachable. */
.skip-link {
  position: absolute;
  left: var(--space-md);
  top: var(--space-md);
  z-index: 200;
  transform: translateY(-200%);
  padding: 0.7rem 1.1rem;
  background: var(--color-accent);
  color: var(--color-accent-ink);
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  border-radius: var(--radius-sm);
  transition: transform var(--dur-fast) var(--ease-out);
}
.skip-link:focus { transform: none; }

/* #main is focus targeted by the skip link; it must not draw a ring of its own
   around the whole page when it receives that programmatic focus. */
#main:focus { outline: none; }

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-style: normal;
  font-weight: 400;
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
  margin: 0;
  overflow-wrap: anywhere;
  min-width: 0;
}

p { margin: 0; }

.wrap {
  width: 100%;
  max-width: var(--page-max);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.eyebrow {
  font-family: var(--font-body);
  font-size: var(--text-xs);
  font-weight: 400;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--color-accent);
  margin: 0 0 var(--space-md);
}

/* Cursive signature accent (Artale "Dennis Mayor") */
.signature {
  font-family: var(--font-script);
  font-weight: 400;
  color: var(--color-script);
  font-size: var(--text-4xl);
  line-height: 1;
  letter-spacing: normal;
  text-transform: none;
}

.section { padding-block: var(--space-4xl); }
.section--tight { padding-block: var(--space-3xl); }

/* ---------- Buttons ---------- */
.btn {
  --_bg: transparent;
  --_fg: var(--color-ink);
  --_bd: var(--color-line-2);
  display: inline-flex;
  align-items: center;
  gap: var(--space-xs);
  padding: 1rem 2rem;
  font-family: var(--font-ui);
  font-size: var(--text-xs);
  font-weight: 400;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--_fg);
  background: var(--_bg);
  border: 1px solid var(--_bd);
  border-radius: var(--radius-sm);
  cursor: pointer;
  white-space: nowrap;
  transition: background var(--dur-fast) var(--ease-out),
              color var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out);
}
.btn:hover, .btn.is-hover { --_bg: var(--color-paper-3); --_bd: var(--color-line-2); }
.btn:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 3px; }
.btn:active, .btn.is-active { transform: translateY(1px); }

.btn--accent { --_bg: var(--color-accent); --_fg: var(--color-accent-ink); --_bd: var(--color-accent); }
.btn--accent:hover, .btn--accent.is-hover { --_bg: var(--color-accent-hi); --_bd: var(--color-accent-hi); }

/* ---------- Header / nav ---------- */
.site-head {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 50;
  display: flex;
  align-items: center;
  /* Brand and toggle are taken out of flow (below), leaving .nav the only
     in-flow child — centering it here keeps the nav on the true middle of the
     viewport no matter how many categories are added. */
  justify-content: center;
  gap: var(--space-lg);
  padding: var(--space-lg) var(--gutter);
  transition: background var(--dur-mid) var(--ease-out),
              border-color var(--dur-mid) var(--ease-out),
              padding var(--dur-mid) var(--ease-out);
  border-bottom: 1px solid transparent;
}
.site-head.is-solid {
  background: color-mix(in oklab, var(--color-paper) 88%, transparent);
  backdrop-filter: blur(10px);
  border-bottom-color: var(--color-line);
  padding-block: var(--space-md);
}
/* backdrop-filter turns the header into the containing block for any
   position:fixed descendant, which would trap the full-screen mobile menu
   inside the header bar. Drop it while the menu is open — the menu paints its
   own opaque background, so there is nothing left to blur anyway. */
.site-head.nav-open {
  backdrop-filter: none;
  border-bottom-color: transparent;
}
.brand {
  /* Out of flow so it never shifts the centered nav off the middle. */
  position: absolute;
  left: var(--gutter);
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  font-family: var(--font-display);
  font-size: var(--text-xl);
  letter-spacing: 0.01em;
}
/* Sized off the wordmark's own font-size, so mark and name stay in proportion
   at every breakpoint without a second set of media queries. */
.brand__mark { width: auto; height: 1em; flex: none; }
.brand__word span { color: var(--color-accent); }

/* Below the nav breakpoint the mark carries the brand on its own: "Bogdan
   Media." beside it crowds the toggle button on a narrow phone. */
@media (max-width: 420px) {
  .brand__word { display: none; }
  .brand__mark { height: 2.2em; }
}

.nav { display: flex; align-items: center; gap: var(--space-lg); }

/* ---------- Nav dropdowns ---------- */
.nav-item { position: relative; display: flex; align-items: center; gap: var(--space-2xs); }

/* Caret: a real button so the submenu is reachable by pointer and, on mobile,
   by tap. Hidden on desktop, where hover/focus-within drive the menu. */
.nav-caret { display: none; }

.nav-menu {
  position: absolute;
  /* Left edge flush with the label; the panel grows to the right. */
  top: calc(100% + 6px);
  left: 0;
  min-width: 13rem;
  margin: 0;
  padding: var(--space-2xs);
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 2px;
  /* Semi-transparent glass: the moody hero reads faintly through it, blur keeps
     the labels legible. */
  background: color-mix(in oklab, var(--color-paper) 72%, transparent);
  backdrop-filter: blur(18px) saturate(1.3);
  -webkit-backdrop-filter: blur(18px) saturate(1.3);
  border: 1px solid color-mix(in oklab, var(--color-line) 70%, transparent);
  border-radius: var(--radius-md);
  box-shadow: 0 18px 40px -16px rgba(0, 0, 0, 0.55);
  /* Hidden until hover/focus. opacity+visibility (not display) so the reveal
     can transition and focus-within can catch keyboard users. Starts lifted a
     touch and glides down into place. */
  opacity: 0;
  visibility: hidden;
  transform: translateY(-10px);
  transform-origin: top left;
  transition: opacity var(--dur-mid) var(--ease-out),
              transform var(--dur-mid) var(--ease-out),
              visibility var(--dur-mid) var(--ease-out);
  z-index: 10;
}
/* A hover bridge over the gap so the pointer can travel from label to menu
   without the menu closing underneath it. */
.nav-menu::before {
  content: "";
  position: absolute;
  left: 0; right: 0; top: -8px;
  height: 8px;
}
.has-menu:hover .nav-menu,
.has-menu:focus-within .nav-menu {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}
.nav-menu a {
  display: block;
  font-family: var(--font-ui);
  padding: var(--space-2xs) var(--space-sm);
  font-size: var(--text-sm);
  color: var(--color-ink-2);
  white-space: nowrap;
  border-radius: var(--radius-sm, 6px);
  transition: color var(--dur-fast) var(--ease-out),
              background var(--dur-fast) var(--ease-out);
}
/* The base .nav a::after underline is anchored to the masthead row; suppress it
   inside the panel, where a background highlight reads better. */
.nav-menu a::after { content: none; }
.nav-menu a:hover,
.nav-menu a:focus-visible {
  color: var(--color-ink);
  background: color-mix(in oklab, var(--color-ink) 8%, transparent);
}

/* Nested flyout — collections under a category. Opens to the right of its
   parent row, mirroring the panel. Dormant until an item carries a `children`
   list (see nav_menu_items()); adding collections is a data change only. */
.nav-menu > li,
.nav-submenu > li { position: relative; }
.nav-menu .has-sub > a {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-sm);
}
/* Re-enable a marker on parent rows (the base panel link kills ::after). */
.nav-menu .has-sub > a::after {
  content: "›";
  color: var(--color-ink-2);
  font-size: 1.15em;
  line-height: 1;
  transition: color var(--dur-fast) var(--ease-out);
}
.nav-menu .has-sub:hover > a::after,
.nav-menu .has-sub:focus-within > a::after { color: var(--color-ink); }

.nav-submenu {
  position: absolute;
  top: calc(-1 * var(--space-2xs));
  left: 100%;
  min-width: 12rem;
  margin: 0;
  padding: var(--space-2xs);
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 2px;
  background: color-mix(in oklab, var(--color-paper) 72%, transparent);
  backdrop-filter: blur(18px) saturate(1.3);
  -webkit-backdrop-filter: blur(18px) saturate(1.3);
  border: 1px solid color-mix(in oklab, var(--color-line) 70%, transparent);
  border-radius: var(--radius-md);
  box-shadow: 0 18px 40px -16px rgba(0, 0, 0, 0.55);
  opacity: 0;
  visibility: hidden;
  transform: translateX(-8px);
  transition: opacity var(--dur-mid) var(--ease-out),
              transform var(--dur-mid) var(--ease-out),
              visibility var(--dur-mid) var(--ease-out);
  z-index: 11;
}
.nav-menu .has-sub:hover > .nav-submenu,
.nav-menu .has-sub:focus-within > .nav-submenu {
  opacity: 1;
  visibility: visible;
  transform: translateX(0);
}

/* A nested flyout (collections under a category) is a hover-bridged neighbour of
   its parent row; the gap between the two panels must not drop the hover. */
.nav-submenu > .has-sub > .nav-submenu::before {
  content: "";
  position: absolute;
  left: -8px; top: 0; bottom: 0;
  width: 8px;
}
.nav a {
  font-family: var(--font-ui);
  font-size: var(--text-sm);
  color: var(--color-ink-2);
  position: relative;
  padding-block: var(--space-2xs);
  transition: color var(--dur-fast) var(--ease-out);
}
.nav a::after {
  content: "";
  position: absolute;
  left: 0; bottom: -2px;
  width: 100%; height: 1px;
  background: var(--color-accent);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--dur-mid) var(--ease-out);
}
.nav a:hover, .nav a:focus-visible { color: var(--color-ink); }
.nav a:hover::after, .nav a:focus-visible::after { transform: scaleX(1); }
.nav a:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 4px; }

.nav-toggle { display: none; }

/* ---------- Hero ---------- */
.hero {
  position: relative;
  min-height: 100svh;
  display: grid;
  align-items: center;
  text-align: center;
  color: var(--color-ink);
  overflow: clip;
}
/* The container is pinned to its own GPU layer with translate3d + backface so it
   moves as a unit under the smoother. It carries no perspective: a perspective
   here projected the zooming image into a 3D space that the smoother's fractional
   offset re-rasterised every frame — the cover shimmer. The image itself is
   promoted to its own stable layer in motion.css (will-change under .motion-on),
   which is what keeps the ken-burns smooth without dragging its neighbours into
   a re-composited 3D context. */
.hero__media {
  position: absolute; inset: 0; z-index: 0; overflow: clip;
  /* Promote the box to its own layer so it moves as a unit under the smoother.
     No perspective: it would project the zooming image child into a 3D space and
     re-rasterise it against the smoother's fractional offset each frame — the
     flicker. The image gets its own stable layer in motion.css instead. */
  -webkit-transform: translate3d(0, 0, 0);
          transform: translate3d(0, 0, 0);
  -webkit-backface-visibility: hidden;
          backface-visibility: hidden;
}
.hero__media img, .hero__media .ph {
  width: 100%; height: 120%; object-fit: cover;
  will-change: transform;
  -webkit-backface-visibility: hidden;
          backface-visibility: hidden;
  animation: kenburns 18s var(--ease-in-out) infinite alternate;
}
@keyframes kenburns {
  from { transform: scale3d(1.03, 1.03, 1) translate3d(0, 0, 0); }
  to   { transform: scale3d(1.15, 1.15, 1) translate3d(-1.5%, -2%, 0); }
}
/* Optional hero video (assets/video/hero.mp4). Photo on mobile, video on
   desktop. The video has NO poster attribute, so on desktop the photo never
   flashes in before the clip starts — the box stays dark until the first frame
   paints. The photo is a separate <img class="hero__poster">, shown only below
   the breakpoint. */
.hero__media video {
  width: 100%; height: 100%; object-fit: cover;
  display: none;                       /* mobile default: photo only */
  background: var(--color-paper);      /* dark, not white, before the clip paints */
  -webkit-backface-visibility: hidden;
          backface-visibility: hidden;
}
@media (min-width: 769px) {
  .hero__media video { display: block; }         /* desktop: video only */
  .hero__media .hero__poster { display: none; }  /* desktop: hide the photo */
}
/* An art-directed background (bg_media) wraps its <img> in <picture>. display:
   contents drops the wrapper's own box, so the <img> stays the direct, sized
   child the .cta__media / .stats__bg rules target. */
.cta__media picture, .stats__bg picture { display: contents; }
.hero::after {
  content: "";
  position: absolute; inset: 0; z-index: 1;
  background:
    radial-gradient(120% 90% at 50% 62%,
      color-mix(in oklab, var(--color-paper) 72%, transparent) 0%,
      transparent 60%),
    linear-gradient(180deg,
      color-mix(in oklab, var(--color-paper) 68%, transparent) 0%,
      color-mix(in oklab, var(--color-paper) 42%, transparent) 40%,
      color-mix(in oklab, var(--color-paper) 88%, transparent) 100%);
}
.hero__inner {
  position: relative; z-index: 2;
  padding: var(--gutter);
  width: 100%;
  max-width: 900px;
  margin-inline: auto;
}
.hero__title {
  font-size: clamp(var(--text-4xl), 9vw, var(--text-display-s));
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: var(--tracking-display);
  line-height: 1.12;
  margin-inline: auto;
}
.hero__title em { font-style: normal; color: inherit; }
.hero__sub {
  margin: var(--space-lg) auto 0;
  max-width: 52ch;
  color: var(--color-ink-2);
  font-size: var(--text-base);
  letter-spacing: 0.06em;
}
.hero__actions { margin-top: var(--space-xl); display: flex; flex-wrap: wrap; gap: var(--space-sm); justify-content: center; }
.scroll-cue {
  position: absolute; z-index: 2;
  right: var(--gutter); bottom: var(--space-xl);
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--color-muted);
  writing-mode: vertical-rl;
}

/* ---------- Section head ---------- */
.sec-head { max-width: 60ch; margin-bottom: var(--space-2xl); }
.sec-head h2 {
  font-size: clamp(var(--text-xl), 3.4vw, var(--text-3xl));
  text-transform: uppercase;
  letter-spacing: var(--tracking-display);
  font-weight: 400;
}
.sec-head p { margin-top: var(--space-md); color: var(--color-ink-2); letter-spacing: 0.04em; }
.sec-head--center { max-width: 60ch; margin-inline: auto; text-align: center; }

/* ---------- Featured gallery (masonry-ish) ---------- */
.feat-grid {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: 6px;
  width: 100vw;
  margin-inline: calc(50% - 50vw);   /* full-bleed edge-to-edge */
}
.feat {
  position: relative;
  overflow: clip;
  border-radius: var(--radius-sm);
  background: var(--color-paper-2);
}
.feat img, .feat .ph { width: 100%; height: 100%; object-fit: cover; transition: transform var(--dur-slow) var(--ease-out); }
.feat:hover img, .feat:hover .ph { transform: scale(1.05); }
.feat::after {
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(180deg, transparent 55%, color-mix(in oklab, var(--color-paper) 80%, transparent));
  opacity: 0; transition: opacity var(--dur-mid) var(--ease-out);
}
.feat:hover::after { opacity: 1; }
.feat__cap {
  position: absolute; z-index: 2; left: var(--space-md); bottom: var(--space-md);
  font-family: var(--font-display); font-size: var(--text-lg);
  opacity: 0; transform: translateY(6px);
  transition: opacity var(--dur-mid) var(--ease-out), transform var(--dur-mid) var(--ease-out);
}
.feat:hover .feat__cap { opacity: 1; transform: none; }
.feat--tall { grid-column: span 4; grid-row: span 2; aspect-ratio: 3/4.4; }
.feat--wide { grid-column: span 8; aspect-ratio: 16/9; }
.feat--sq   { grid-column: span 4; aspect-ratio: 4/5; }

/* ---------- Categories (full-bleed, Artale) ---------- */
.cats {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 4px;
  width: 100vw; margin-inline: calc(50% - 50vw);
}
/* Two-up strip, e.g. "other collections" under a collection's photos.
   Deliberately smaller and centered, not full-bleed, so it reads as a
   suggestion and does not compete with the collection above it. */
.cats--pair {
  grid-template-columns: repeat(2, minmax(0, 1fr));
  width: auto;
  max-width: 620px;
  margin-inline: auto;
  padding-inline: var(--gutter);
  gap: var(--space-md);
}
.cats--pair .cat { aspect-ratio: 4/5; }
.cats--pair .cat__label { padding: var(--space-md); gap: var(--space-2xs); }
.cats--pair .cat__label h3 { font-size: clamp(var(--text-lg), 2.2vw, var(--text-xl)); }

/* A small downward arrow between the heading and the suggestions, nudging the
   eye toward them. */
.more-cue { display: flex; justify-content: center; margin: var(--space-md) 0 var(--space-xl); }
.more-cue::after {
  content: "";
  width: 20px; height: 20px;
  border-right: 1.5px solid var(--color-accent);
  border-bottom: 1.5px solid var(--color-accent);
  transform: rotate(45deg);
  animation: moreCue 1.8s var(--ease-in-out) infinite;
}
@keyframes moreCue {
  0%, 100% { transform: rotate(45deg) translate(0, 0); opacity: 0.6; }
  50%      { transform: rotate(45deg) translate(3px, 3px); opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .more-cue::after { animation: none; }
}
.cat {
  position: relative; display: block; overflow: clip;
  aspect-ratio: 3/4.3; background: var(--color-paper-2);
}
.cat img, .cat .ph { width: 100%; height: 100%; object-fit: cover; transition: transform 900ms var(--ease-out), filter 600ms var(--ease-out); filter: grayscale(0.35) brightness(0.85); }
.cat:hover img, .cat:hover .ph { transform: scale(1.06); filter: grayscale(0) brightness(1); }
.cat::after { content:""; position:absolute; inset:0; background: linear-gradient(180deg, color-mix(in oklab, var(--color-paper) 30%, transparent) 0%, transparent 35%, color-mix(in oklab, var(--color-paper) 72%, transparent) 100%); }
.cat__label {
  position: absolute; z-index: 2; inset: 0; padding: var(--space-lg);
  display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; gap: var(--space-xs);
}
/* The ::after gradient is transparent through the middle band, which is exactly
   where this label sits — near-white type over an arbitrary uploaded photo has
   no contrast guarantee there. A flat scrim behind the text block is the only
   thing that makes the ratio predictable regardless of the image. */
.cat__label::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: color-mix(in oklab, var(--color-paper) 45%, transparent);
}
.cat__label h3 { font-size: clamp(var(--text-2xl), 3.4vw, var(--text-4xl)); text-transform: uppercase; letter-spacing: var(--tracking-display); font-weight: 400; }
.cat__label span { color: var(--color-ink-2); font-size: var(--text-xs); letter-spacing: var(--tracking-wide); text-transform: uppercase; }
.cat__go { margin-top: var(--space-sm); font-size: var(--text-xs); letter-spacing: var(--tracking-wide); text-transform: uppercase; color: var(--color-accent); opacity: 0; transform: translateY(6px); transition: opacity var(--dur-mid) var(--ease-out), transform var(--dur-mid) var(--ease-out); }
.cat:hover .cat__go, .cat:focus-visible .cat__go { opacity: 1; transform: none; }
.cat:focus-visible { outline: 2px solid var(--color-focus); outline-offset: -2px; }
/* Collection cards: category eyebrow above the title, in the accent tint. */
.cat__eyebrow { color: var(--color-accent) !important; margin-bottom: var(--space-2xs); }
/* Corner marker saying what a collection holds: foto, video, or both.
   Built in collection_badge() (includes/gallery.php). */
.cat__badge {
  position: absolute; z-index: 3; top: var(--space-sm); right: var(--space-sm);
  font-size: 11px; letter-spacing: var(--tracking-wide); text-transform: uppercase;
  color: var(--color-ink); background: color-mix(in oklab, var(--color-paper) 55%, transparent);
  backdrop-filter: blur(6px); padding: 3px 8px; border-radius: 999px;
}

/* ---------- About teaser ---------- */
.about { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-2xl); align-items: center; }
.about__media { aspect-ratio: 4/5; overflow: clip; border-radius: var(--radius-sm); background: var(--color-paper-2); }
.about__media img, .about__media .ph { width:100%; height:100%; object-fit: cover; }
.about__body h2 { font-size: clamp(var(--text-2xl), 5vw, var(--text-3xl)); margin-bottom: var(--space-lg); }
.about__body p { color: var(--color-ink-2); margin-bottom: var(--space-md); max-width: var(--measure); }
.about__sig { margin-top: var(--space-md); font-family: var(--font-script); font-size: var(--text-4xl); line-height: 1; color: var(--color-script); }

/* ---------- Reviews ---------- */
.reviews { border-top: 1px solid var(--color-line); }
/* The contact CTA below carries a moving ken-burns background; the 1px divider
   that used to sit between it and the footer shimmered against that layer, so
   it is dropped only where the CTA exists (the home page). */
main:has(.cta) + .site-foot { border-top: 0; }

/* Testimonials marquee — full-bleed, scrolls right→left, pauses on hover. */
.rev-marquee {
  width: 100vw; margin-inline: calc(50% - 50vw);
  overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
}
.rev-track {
  display: flex; width: max-content;
  padding-block: var(--space-sm);
  animation: revScroll 45s linear infinite;
}
.rev-track:hover { animation-play-state: paused; }
@keyframes revScroll { from { transform: translateX(0); } to { transform: translateX(-50%); } }
/* Equal right margin on every card (not flex gap) keeps the two passes the same
   width, so translateX(-50%) loops seamlessly. */
.rev { flex: 0 0 min(84vw, 380px); margin-right: var(--space-2xl); }
.rev__stars { color: var(--color-accent); letter-spacing: 0.15em; margin-bottom: var(--space-md); }
.rev__text { font-family: var(--font-display); font-size: var(--text-xl); line-height: 1.4; color: var(--color-ink); }
.rev__who { margin-top: var(--space-md); color: var(--color-muted); font-size: var(--text-sm); }
/* No auto-scroll for reduced-motion users — the row becomes manually swipeable
   instead (the global rule would otherwise snap it straight to the loop end). */
@media (prefers-reduced-motion: reduce) {
  .rev-track { animation: none; }
  .rev-marquee { overflow-x: auto; }
}

/* ---------- Contact CTA ---------- */
/* No negative margin here on purpose: an odd total height is itself a known
   flicker trigger, and the 1px overlap it bought is no longer needed once the
   media below sits on its own GPU layer. */
.cta { 
  text-align: center; 
  position: relative; 
  overflow: clip; 
  transform: translateZ(0); /* Ai deja asta */
}

.cta__media {
  position: absolute; inset: -80px 0; z-index: 0;
  /* Same as .hero__media: promote to its own layer, but no perspective — that
     projected the zooming image and re-rasterised it against the smoother each
     frame, which was the flicker on the contact block specifically. */
  -webkit-transform: translate3d(0, 0, 0);
          transform: translate3d(0, 0, 0);
  -webkit-backface-visibility: hidden;
          backface-visibility: hidden;
          will-change: transform;
}
.cta__media img, .cta__media .ph {
  width: 100%; height: 100%; object-fit: cover;
  will-change: transform;
  -webkit-backface-visibility: hidden;
          backface-visibility: hidden;
  /* scale3d (not scale): the 3D form keeps the image on a GPU layer composited
     once, instead of being re-rasterised on the CPU every frame. */
  animation: ctaZoom 22s var(--ease-in-out) infinite alternate;
}
@keyframes ctaZoom { from { transform: scale3d(1.03, 1.03, 1); } to { transform: scale3d(1.12, 1.12, 1); } }
/* Scrim so the light text stays legible over an arbitrary photo. */
.cta::after {
  content: "";
  position: absolute; inset: 0; z-index: 1;
  background:
    radial-gradient(120% 90% at 50% 50%,
      color-mix(in oklab, var(--color-paper) 68%, transparent) 0%,
      transparent 65%),
    linear-gradient(180deg,
      color-mix(in oklab, var(--color-paper) 82%, transparent) 0%,
      color-mix(in oklab, var(--color-paper) 55%, transparent) 45%,
      color-mix(in oklab, var(--color-paper) 82%, transparent) 100%);
}
.cta .wrap { position: relative; z-index: 2; }
.cta h2 { font-size: clamp(var(--text-2xl), 6vw, var(--text-4xl)); max-width: 20ch; margin-inline: auto; text-transform: uppercase; letter-spacing: var(--tracking-display); }
.cta p { margin-top: var(--space-lg); color: var(--color-ink-2); max-width: 44ch; margin-inline: auto; }
.cta__actions { margin-top: var(--space-xl); display: flex; gap: var(--space-sm); justify-content: center; flex-wrap: wrap; }

/* ---------- Footer ---------- */
.site-foot { border-top: 1px solid var(--color-line); padding-block: var(--space-3xl) var(--space-xl); }
/* Mark and wordmark on one line, left-aligned.
   The scale lives here rather than on .foot-word so both parts read from the
   same font-size: the mark is sized in em and tracks the name automatically,
   instead of needing a second clamp kept in sync by hand. */
.foot-brand {
  display: flex;
  align-items: center;
  gap: var(--space-md);
  /* Hugs its contents rather than stretching to the footer's full width, so
     the lockup's own measured width is what the clamp above is tuned against. */
  width: fit-content;
  font-size: clamp(var(--text-xl), 5vw, 4.25rem);
}
/* Matched to the type size so the mark never reads larger than the name. */
.foot-brand__mark { width: auto; height: 1em; flex: none; }
/* The previous 16vw was set for the single word "Bogdan"; with "Bogdan Media."
   beside the mark it overflowed onto a second line and swallowed the footer.
   nowrap keeps the name whole, and the clamp above stops the lockup around
   half the page. */
.foot-word {
  font-family: var(--font-display);
  font-size: 1em;
  line-height: 1;
  letter-spacing: -0.02em;
  white-space: nowrap;
}
.foot-word span { color: var(--color-accent); }
.foot-grid { display: flex; flex-wrap: wrap; justify-content: space-between; gap: var(--space-xl); margin-top: var(--space-2xl); }
.foot-grid a { color: var(--color-ink-2); font-size: var(--text-sm); }
.foot-grid a:hover { color: var(--color-ink); }
.foot-col { display: flex; flex-direction: column; gap: var(--space-xs); }
.foot-col h4 { font-family: var(--font-body); font-size: var(--text-xs); letter-spacing: var(--tracking-wide); text-transform: uppercase; color: var(--color-muted); font-weight: 600; margin-bottom: var(--space-xs); }
.foot-legal { margin-top: var(--space-2xl); padding-top: var(--space-lg); border-top: 1px solid var(--color-line); display: flex; justify-content: space-between; flex-wrap: wrap; gap: var(--space-sm); color: var(--color-muted); font-size: var(--text-xs); }

/* ---------- Placeholder art ---------- */
.ph {
  background:
    repeating-linear-gradient(135deg, oklch(22% 0.008 60) 0 2px, transparent 2px 22px),
    linear-gradient(160deg, var(--color-paper-3), var(--color-paper-2));
  display: grid; place-items: center;
}
.ph::before { content: "◈"; color: var(--color-line-2); font-size: 2rem; }

/* Hero content staggered fade-in on load */
.hero__inner > * { opacity: 0; transform: translateY(24px); animation: heroIn 1100ms var(--ease-out) forwards; }
.hero__inner .eyebrow    { animation-delay: 120ms; }
.hero__inner .hero__title{ animation-delay: 240ms; }
.hero__inner .hero__sub  { animation-delay: 420ms; }
.hero__inner .hero__actions { animation-delay: 600ms; }
@keyframes heroIn { to { opacity: 1; transform: none; } }
.scroll-cue { opacity: 0; animation: heroIn 1100ms var(--ease-out) 900ms forwards; }

/* ---------- Public forms ---------- */
.block-title { font-family: var(--font-display); font-weight: 400; text-transform: uppercase; letter-spacing: var(--tracking-display); font-size: var(--text-xl); margin: 0 0 var(--space-md); }
.form-cols { display: grid; grid-template-columns: 1.4fr 1fr; gap: var(--space-2xl); }
.oform { display: flex; flex-direction: column; gap: var(--space-md); }
.oform label { display: flex; flex-direction: column; gap: 6px; font-size: var(--text-xs); text-transform: uppercase; letter-spacing: var(--tracking-wide); color: var(--color-muted); }
.oform input, .oform textarea, .oform select {
  font-family: var(--font-body); font-size: var(--text-base); text-transform: none; letter-spacing: normal;
  color: var(--color-ink); background: var(--color-paper-2);
  border: 1px solid var(--color-line-2); border-radius: var(--radius-sm); padding: 0.8rem 0.9rem;
}
.oform input:focus, .oform textarea:focus, .oform select:focus { outline: 2px solid var(--color-focus); outline-offset: 1px; border-color: transparent; }
.oform textarea { resize: vertical; }
.oform .btn { align-self: flex-start; margin-top: var(--space-xs); }
.oform-row { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-md); }

/* Consent tick. .oform label is a column of uppercase micro-copy, which is the
   wrong shape for a sentence the visitor has to read before agreeing to it, so
   this one goes back to a row of normal-case prose. The <input> sits inside the
   <label>, so the whole sentence is the hit area rather than the 18px box. */
.oform-consent {
  flex-direction: row;
  align-items: flex-start;
  gap: 0.6rem;
  text-transform: none;
  letter-spacing: normal;
  font-size: var(--text-sm);
  color: var(--color-ink-2);
  line-height: 1.5;
  cursor: pointer;
}
.oform-consent input[type="checkbox"] {
  flex: none;
  width: 1.15rem; height: 1.15rem;
  /* .oform input above pads every field by 0.8rem, which on a checkbox is a
     lopsided grey slab. Reset it and align to the first line of the sentence. */
  padding: 0;
  margin-top: 0.12rem;
  accent-color: var(--color-accent);
  cursor: pointer;
}
.oform-consent a { color: var(--color-accent); text-decoration: underline; }

.oform-note { font-size: var(--text-sm); color: var(--color-muted); line-height: 1.5; }
.oform-note a { color: var(--color-ink-2); text-decoration: underline; }
.oform-note a:hover { color: var(--color-accent); }

.contact-info p { margin-bottom: var(--space-sm); }
.contact-info a:hover { color: var(--color-accent); }
.field-err { color: var(--color-danger-ink); font-size: var(--text-xs); text-transform: none; letter-spacing: normal; }
.oform [aria-invalid="true"] { border-color: var(--color-danger); }
.formnote { padding: 0.75rem 1rem; border-radius: var(--radius-sm); margin-bottom: var(--space-md); font-size: var(--text-sm); }
.formnote--ok { background: color-mix(in oklab, var(--color-accent) 22%, var(--color-paper)); color: var(--color-ink); }
.formnote--err { background: var(--color-danger-bg); color: var(--color-danger-ink); }

/* ---------- Blog ---------- */
.post-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: var(--space-xl); }
.post-card { display: block; color: inherit; background: var(--color-paper-2); border-radius: var(--radius-sm); overflow: hidden; transition: transform var(--dur-mid) var(--ease-out); }
.post-card:hover { transform: translateY(-4px); }
.post-card__media { aspect-ratio: 16/10; overflow: hidden; }
.post-card__media img, .post-card__media .ph { width: 100%; height: 100%; object-fit: cover; transition: transform var(--dur-slow) var(--ease-out); }
.post-card:hover .post-card__media img { transform: scale(1.05); }
.post-card__body { padding: var(--space-lg); }
.post-card__date { font-size: var(--text-xs); letter-spacing: var(--tracking-wide); text-transform: uppercase; color: var(--color-accent); margin: 0 0 var(--space-xs); }
.post-card__title { font-size: var(--text-xl); margin: 0 0 var(--space-xs); }
.post-card__excerpt { color: var(--color-ink-2); font-size: var(--text-sm); margin: 0 0 var(--space-md); }
.post-card__more { font-size: var(--text-xs); text-transform: uppercase; letter-spacing: var(--tracking-wide); color: var(--color-accent); }
.post-body p { margin-bottom: var(--space-lg); color: var(--color-ink-2); line-height: var(--leading-body); }
.post-cover { aspect-ratio: 16/9; overflow: hidden; border-radius: var(--radius-sm); background: var(--color-paper-2); }
.post-cover img { width: 100%; height: 100%; object-fit: cover; }

/* ---------- Content pages (Despre / Servicii) ---------- */
.prose { max-width: var(--measure); }
.prose p { color: var(--color-ink-2); margin-bottom: var(--space-md); }
.svc-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: var(--space-lg); }
.svc { border: 1px solid var(--color-line); border-radius: var(--radius-sm); padding: var(--space-xl); background: var(--color-paper-2); }
.svc h2 { font-size: var(--text-xl); margin: 0 0 var(--space-sm); }
.svc .price { font-family: var(--font-script); font-size: var(--text-3xl); color: var(--color-script); margin: var(--space-sm) 0; }
.svc p { color: var(--color-ink-2); font-size: var(--text-sm); }

/* ---------- Inner page hero ---------- */
.page-hero { padding-top: var(--space-4xl); padding-bottom: var(--space-md); }
.page-hero__title { font-size: clamp(var(--text-3xl), 7vw, var(--text-display-s)); text-transform: uppercase; letter-spacing: var(--tracking-display); font-weight: 400; }
.page-hero__date { margin-top: var(--space-sm); color: var(--color-ink-2); font-size: var(--text-sm); letter-spacing: var(--tracking-wide); }
.collection-back { text-transform: uppercase; letter-spacing: var(--tracking-wide); font-size: var(--text-xs); color: var(--color-muted); transition: color var(--dur-fast); }
.collection-back:hover { color: var(--color-accent); }

/* ---------- Medium toggle (Foto | Video) ---------- */
.medium-toggle { display: flex; justify-content: center; gap: var(--space-md); margin-bottom: var(--space-lg); }
.medium-toggle a { font-family: var(--font-display); font-size: var(--text-lg); letter-spacing: 0.06em; padding: 0.15em 0.2em; border-bottom: 2px solid transparent; color: var(--color-ink-2); transition: color var(--dur-fast), border-color var(--dur-fast); }
.medium-toggle a:hover, .medium-toggle a.is-active { color: var(--color-ink); border-bottom-color: var(--color-accent); }

/* ---------- Filter bar ---------- */
.filterbar { display: flex; gap: var(--space-lg); justify-content: center; flex-wrap: wrap; margin-bottom: var(--space-2xl); }
.filterbar a { text-transform: uppercase; letter-spacing: var(--tracking-wide); font-size: var(--text-xs); color: var(--color-muted); padding-bottom: 5px; border-bottom: 1px solid transparent; transition: color var(--dur-fast), border-color var(--dur-fast); }
.filterbar a:hover, .filterbar a.is-active { color: var(--color-ink); border-bottom-color: var(--color-accent); }

/* ---------- Masonry gallery ---------- */
.masonry { columns: 3 280px; column-gap: 6px; }
.masonry__item { break-inside: avoid; display: block; width: 100%; margin: 0 0 6px; padding: 0; border: 0; background: var(--color-paper-2); cursor: pointer; position: relative; overflow: hidden; border-radius: 2px; }
.masonry__item img { width: 100%; display: block; transition: transform var(--dur-slow) var(--ease-out), filter var(--dur-mid) var(--ease-out); filter: grayscale(0.12); }
.masonry__item:hover img { transform: scale(1.045); filter: none; }
.masonry__item::after { content: ""; position: absolute; inset: 0; background: linear-gradient(180deg, transparent 55%, color-mix(in oklab, var(--color-paper) 78%, transparent)); opacity: 0; transition: opacity var(--dur-mid) var(--ease-out); }
.masonry__item:hover::after { opacity: 1; }
.masonry__cap { position: absolute; left: 12px; bottom: 12px; z-index: 2; font-family: var(--font-display); font-size: var(--text-lg); color: var(--color-ink); opacity: 0; transform: translateY(6px); transition: opacity var(--dur-mid), transform var(--dur-mid); }
.masonry__item:hover .masonry__cap { opacity: 1; transform: none; }
.masonry__item:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 2px; }

/* Shared QR gallery — a tidy 3-up grid of 4:3 tiles, slow zoom + lift on hover. */
.share-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-md); }
.share-grid__item {
  display: block; padding: 0; border: 0; cursor: pointer;
  position: relative; overflow: hidden; border-radius: var(--radius-sm);
  background: var(--color-paper-2);
  aspect-ratio: 4 / 3;
  transition: box-shadow var(--dur-mid) var(--ease-out);
}
.share-grid__item img {
  width: 100%; height: 100%; object-fit: cover; display: block;
  transition: transform var(--dur-slow) var(--ease-out), filter var(--dur-mid) var(--ease-out);
  filter: grayscale(0.1);
}
.share-grid__item:hover { box-shadow: 0 22px 44px -16px rgba(0, 0, 0, 0.6); }
.share-grid__item:hover img { transform: scale(1.06); filter: none; }
.share-grid__item:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 2px; }
/* Caption sits over a bottom scrim so it stays legible on any photo; hidden
   until hover so the grid itself reads clean. */
.share-grid__item::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(180deg, transparent 55%, color-mix(in oklab, var(--color-paper) 78%, transparent));
  opacity: 0; transition: opacity var(--dur-mid) var(--ease-out);
}
.share-grid__item:hover::after { opacity: 1; }
.share-grid__cap {
  position: absolute; left: 12px; bottom: 12px; z-index: 2;
  font-family: var(--font-display); font-size: var(--text-lg); color: var(--color-ink);
  opacity: 0; transform: translateY(6px);
  transition: opacity var(--dur-mid), transform var(--dur-mid);
}
.share-grid__item:hover .share-grid__cap { opacity: 1; transform: none; }
@media (max-width: 820px) { .share-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 520px) { .share-grid { grid-template-columns: 1fr; } }

/* ---------- Offer viewer (private share page) ---------- */
/* Inline PDF, read in place, no download control (see share.php). Portrait A4
   is taller than it is wide, so the frame is capped at the viewport height and
   scrolls internally rather than running the page long on a phone. */
.pdf-viewer { margin-top: var(--space-2xl); }
.pdf-viewer__frame {
  display: block;
  width: 100%;
  height: min(85vh, 900px);
  border: 1px solid var(--color-line, rgba(255,255,255,0.12));
  border-radius: var(--radius, 6px);
  background: var(--color-bg-2, #111);
}
.dl__pending { margin-top: var(--space-2xl); color: var(--color-muted); }

/* ---------- YouTube, click-to-load ---------- */
/* aspect-ratio on the wrapper, not a padding-top hack: the poster and the
   iframe that replaces it must occupy exactly the same box, or swapping one
   for the other shifts every element below it down the page mid-click. */
.yt {
  position: relative;
  aspect-ratio: 16 / 9;
  background: var(--color-paper-2);
  border-radius: var(--radius-sm);
  overflow: hidden;
}
.yt__trigger {
  position: absolute; inset: 0;
  display: block; width: 100%; height: 100%;
  padding: 0; border: 0; background: none;
  cursor: pointer;
}
.yt__trigger img, .yt__ph { display: block; width: 100%; height: 100%; object-fit: cover; }
.yt__ph { background: linear-gradient(135deg, var(--color-paper-2), var(--color-paper)); }
.yt__frame { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }

/* Play badge. Drawn in CSS rather than shipped as an SVG or icon font — it is
   one triangle in one circle, and it inherits the accent token for free. */
.yt__play {
  position: absolute; top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  width: 4.5rem; height: 4.5rem;
  border-radius: 50%;
  background: color-mix(in oklab, var(--color-paper) 72%, transparent);
  border: 1px solid var(--color-accent);
  transition: background var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out);
}
.yt__play::after {
  content: ''; position: absolute; top: 50%; left: 54%;
  transform: translate(-50%, -50%);
  border-style: solid;
  border-width: 0.7rem 0 0.7rem 1.15rem;
  border-color: transparent transparent transparent var(--color-accent);
}
.yt__trigger:hover .yt__play { background: var(--color-accent); transform: translate(-50%, -50%) scale(1.06); }
.yt__trigger:hover .yt__play::after { border-left-color: var(--color-paper); }
.yt__trigger:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 3px; }
@media (prefers-reduced-motion: reduce) {
  .yt__play, .yt__trigger:hover .yt__play { transition: none; transform: translate(-50%, -50%); }
}

/* Caption and consent note overlay the poster rather than adding height below
   it, so a row of videos keeps a uniform 16:9 rhythm whatever the text length.
   Both are hidden once the player is live (see .is-playing below), where they
   would otherwise cover YouTube's own controls. */
/* Caption and note sit below the box in normal flow. Selected through
   .yt-block so that `.post-body p { margin-bottom }` (specificity 0,1,1) does
   not outrank these inside an article and reintroduce stray spacing. */
.yt-block .yt__cap, .yt-block .yt__note {
  margin: var(--space-xs) 0 0;
  font-size: var(--text-xs); line-height: 1.45;
  color: var(--color-muted);
}
.yt-block .yt__cap { color: var(--color-ink-2); }
.yt-block .yt__note a { color: var(--color-accent); text-decoration: underline; }
/* Once the player is live the warning has served its purpose — the visitor has
   already chosen. The caption stays, since it describes the clip. The class is
   set on the block by main.js rather than matched with :has(), so this needs no
   support story of its own. */
.yt-block.is-playing .yt__note { display: none; }

.video-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(420px, 1fr)); gap: var(--space-xl); }
.video-grid__title {
  font-family: var(--font-display); font-weight: 500;
  font-size: var(--text-lg); margin: 0 0 var(--space-sm);
}
.post-video { margin: var(--space-xl) 0; }
@media (max-width: 540px) {
  .video-grid { grid-template-columns: 1fr; }
  .yt__play { width: 3.4rem; height: 3.4rem; }
  .yt__play::after { border-width: 0.55rem 0 0.55rem 0.9rem; }
}

/* ---------- Stats counters (Despre) ---------- */
/* A dark band: photograph, a flat scrim over it, outlined cards on top. The
   colours here are literal rather than tokens because the band is dark on a
   light page — --color-ink would be the wrong way round inside it. */
.stats {
  position: relative;
  /* Own stacking context, so the z-index:-1 background sits behind the cards
     but still in front of the page rather than punching through to the body. */
  isolation: isolate;
  overflow: hidden;
  color: oklch(98% 0 0);
}
.stats__bg { position: absolute; inset: 0; z-index: -1; }
.stats__bg img { width: 100%; height: 100%; object-fit: cover; }
/* Painted after the <img> it follows, so it darkens rather than hides it. Deep
   enough that white text over any photograph clears WCAG AA. */
.stats__bg::after {
  content: "";
  position: absolute; inset: 0;
  background: oklch(14% 0 0 / 0.74);
}

.stats__grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--space-lg); }
.stat {
  border: 1px solid oklch(100% 0 0 / 0.34);
  padding: var(--space-xl) var(--space-md);
  text-align: center;
}
.stat__icon { display: block; margin: 0 auto var(--space-md); }
.stat__num {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(var(--text-2xl), 5.5vw, var(--text-4xl));
  font-weight: 400;
  line-height: var(--leading-tight);
  /* The figure is counted up digit by digit; proportional numerals would make
     the card twitch on every frame as the glyph widths change under it. */
  font-variant-numeric: tabular-nums;
}
.stat__label {
  margin: var(--space-sm) 0 0;
  font-size: var(--text-sm);
  color: oklch(100% 0 0 / 0.76);
}
/* Two across on a phone rather than one: four stacked cards make a band taller
   than the viewport, and the figures are short enough to pair comfortably.
   Single column only where two would start wrapping the labels. */
@media (max-width: 900px) { .stats__grid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 380px) { .stats__grid { grid-template-columns: 1fr; } }

/* ---------- FAQ ---------- */
.faq { max-width: 46rem; margin: 0 auto; }
.faq__item { border-bottom: 1px solid var(--color-line); }
.faq__q {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-md);
  padding: var(--space-lg) 0;
  font-family: var(--font-display);
  font-size: var(--text-lg); color: var(--color-ink);
  cursor: pointer;
  list-style: none;                 /* Firefox */
  transition: color var(--dur-fast) var(--ease-out);
}
.faq__q::-webkit-details-marker { display: none; }   /* Safari's default triangle */
.faq__q:hover { color: var(--color-accent); }
.faq__q:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 2px; }

/* Plus that becomes a minus. Two bars, one rotated — the open state only has to
   flip the vertical one, so there is nothing to keep in sync. */
.faq__icon { position: relative; flex: none; width: 1rem; height: 1rem; }
.faq__icon::before, .faq__icon::after {
  content: ''; position: absolute; top: 50%; left: 0;
  width: 100%; height: 1px; background: var(--color-accent);
  transition: transform var(--dur-fast) var(--ease-out);
}
.faq__icon::after { transform: rotate(90deg); }
.faq__item[open] .faq__icon::after { transform: rotate(0deg); }

.faq__a { padding: 0 0 var(--space-lg); max-width: var(--measure); }
.faq__a p { margin: 0; color: var(--color-ink-2); line-height: var(--leading-body); }
@media (prefers-reduced-motion: reduce) {
  .faq__q, .faq__icon::before, .faq__icon::after { transition: none; }
}

/* ---------- Legal pages ---------- */
/* .prose caps the column at --measure, which is what makes a policy readable
   rather than a wall. Everything here is spacing and hierarchy on top of it. */
.legal h2 {
  font-family: var(--font-display); font-weight: 500;
  font-size: var(--text-xl); color: var(--color-ink);
  margin: var(--space-2xl) 0 var(--space-sm);
}
.legal h3 {
  font-size: var(--text-base); color: var(--color-ink);
  text-transform: uppercase; letter-spacing: var(--tracking-wide);
  margin: var(--space-lg) 0 var(--space-xs);
}
.legal p { line-height: var(--leading-body); }
.legal a { color: var(--color-accent); text-decoration: underline; }
.legal code {
  font-size: 0.9em; padding: 0.1em 0.35em;
  background: var(--color-paper-2); border-radius: var(--radius-sm);
}
.legal-meta { color: var(--color-muted); font-size: var(--text-sm); margin-bottom: var(--space-xl); }
.legal-dl { margin: var(--space-md) 0; }
.legal-dl dt { color: var(--color-ink); font-size: var(--text-sm); margin-top: var(--space-md); }
.legal-dl dd { color: var(--color-ink-2); margin: 0 0 0 var(--space-md); font-size: var(--text-sm); line-height: 1.5; }
/* Unfilled controller identity. Loud on purpose -- a policy that ships with
   "[de completat: CUI]" showing is a bug you can see, whereas one that quietly
   renders an empty sentence reads as finished and is not. */
.legal-todo {
  background: var(--color-danger-bg); color: var(--color-danger-ink);
  padding: 0.1em 0.4em; border-radius: var(--radius-sm); font-style: normal;
}

.foot-legal a { color: var(--color-muted); text-decoration: underline; }
.foot-legal a:hover { color: var(--color-accent); }

/* ---------- Pager ---------- */
.pager { display: flex; align-items: center; justify-content: center; gap: var(--space-lg); flex-wrap: wrap; margin-top: var(--space-2xl); }
.pager__count { color: var(--color-muted); font-size: var(--text-xs); letter-spacing: var(--tracking-wide); text-transform: uppercase; }

/* ---------- Lightbox ---------- */
.lightbox { position: fixed; inset: 0; z-index: 100; display: none; place-items: center; background: color-mix(in oklab, var(--color-paper) 94%, black); }
.lightbox.is-open { display: grid; animation: lbIn var(--dur-mid) var(--ease-out); }
@keyframes lbIn { from { opacity: 0; } to { opacity: 1; } }
.lb-stage { margin: 0; max-width: 92vw; display: flex; flex-direction: column; align-items: center; gap: var(--space-sm); }
.lb-stage img { max-width: 92vw; max-height: 82vh; object-fit: contain; box-shadow: 0 24px 70px var(--color-scrim); }
.lb-cap { color: var(--color-ink-2); font-size: var(--text-sm); letter-spacing: 0.04em; min-height: 1.2em; }
.lb-dl { margin-top: var(--space-md); }
.lb-close, .lb-nav { background: none; border: 0; color: var(--color-ink-2); cursor: pointer; line-height: 1; transition: color var(--dur-fast) var(--ease-out); }
.lb-close { position: fixed; top: 16px; right: 22px; font-size: 1.6rem; padding: 8px; }
.lb-nav { position: fixed; top: 50%; transform: translateY(-50%); font-size: 3rem; padding: 8px 14px; }
.lb-prev { left: 10px; } .lb-next { right: 10px; }
.lb-close:hover, .lb-nav:hover, .lb-close:focus-visible, .lb-nav:focus-visible { color: var(--color-accent); outline: none; }

/* ---------- Responsive ---------- */
@media (max-width: 900px) {
  .about { grid-template-columns: 1fr; }
  .cats { grid-template-columns: 1fr 1fr; }
  .rev-grid { grid-template-columns: 1fr; gap: var(--space-lg); }
  .feat--tall, .feat--wide, .feat--sq { grid-column: span 12; grid-row: auto; aspect-ratio: 16/10; }
  .form-cols { grid-template-columns: 1fr; }
  .masonry { columns: 2 200px; }
}
@media (max-width: 560px) {
  .oform-row { grid-template-columns: 1fr; }
  .masonry { columns: 1; }
}
/* Nav switches to the drawer well before the layout actually breaks. The bar
   holds the brand, five links and up to 4rem of gutter each side; below roughly
   820px they no longer fit on one line. Because html/body are overflow-x:clip
   the overflow produces no scrollbar — links are simply cut off silently, which
   is why this needs a deliberate breakpoint rather than a visual check.
   Kept separate from the 620px block so the grid rules there are not dragged
   up to tablet widths with it. */
@media (max-width: 820px) {
  .nav { display: none; }
  .nav.is-open { display: flex; position: fixed; inset: 0; z-index: 40; flex-direction: column; justify-content: center; align-items: center; gap: var(--space-xl); background: var(--color-paper); }
  /* Sizing only the top-level entries as display headings; submenu links get
     their own smaller size below. */
  .nav.is-open > a,
  .nav.is-open .nav-item > a { font-size: var(--text-2xl); font-family: var(--font-display); color: var(--color-ink); }
  /* Pinned right and out of flow so the centered brand/nav stay put. */
  .nav-toggle { display: inline-flex; position: absolute; right: var(--gutter); top: 50%; transform: translateY(-50%); z-index: 60; background: none; border: 0; color: var(--color-ink); cursor: pointer; font-family: var(--font-ui); font-size: var(--text-sm); letter-spacing: var(--tracking-wide); text-transform: uppercase; }

  /* Accordion: the label + caret share a row, the panel wraps to full width
     below and expands on tap. */
  .nav.is-open .nav-item { flex-wrap: wrap; justify-content: center; gap: var(--space-xs); }
  .nav-caret {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.2rem; height: 2.2rem;
    background: none;
    border: 0;
    color: var(--color-ink-2);
    cursor: pointer;
  }
  .nav-caret::before {
    content: "";
    width: 0; height: 0;
    border-left: 5px solid transparent;
    border-right: 5px solid transparent;
    border-top: 6px solid currentColor;
    transition: transform var(--dur-fast) var(--ease-out);
  }
  .nav-item.is-open .nav-caret::before { transform: rotate(180deg); }
  .nav-item.is-open .nav-caret { color: var(--color-ink); }

  .nav.is-open .nav-menu {
    position: static;
    transform: none;
    flex-basis: 100%;
    min-width: 0;
    margin: 0;
    padding: 0;
    background: none;
    border: 0;
    box-shadow: none;
    backdrop-filter: none;
    opacity: 1;
    visibility: visible;
    align-items: center;
    max-height: 0;
    overflow: hidden;
    transition: max-height var(--dur-mid) var(--ease-out);
  }
  .nav.is-open .nav-menu::before { content: none; }
  .nav-item.is-open .nav-menu { max-height: 60vh; }
  .nav.is-open .nav-menu a { font-size: var(--text-lg); color: var(--color-ink-2); }
  .nav.is-open .nav-menu a:hover,
  .nav.is-open .nav-menu a:focus-visible { color: var(--color-ink); background: none; }

  /* Collections flatten into the accordion instead of flying out sideways. */
  .nav.is-open .nav-submenu {
    position: static;
    opacity: 1;
    visibility: visible;
    transform: none;
    min-width: 0;
    padding: var(--space-2xs) 0 var(--space-2xs) var(--space-md);
    background: none;
    border: 0;
    box-shadow: none;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }
  .nav.is-open .nav-menu .has-sub > a { justify-content: center; }
  .nav.is-open .nav-menu .has-sub > a::after { content: none; }
  .nav.is-open .nav-submenu a { font-size: var(--text-md, 1rem); }
  /* Second-level nesting (collections under a category) indents one step more. */
  .nav.is-open .nav-submenu .nav-submenu { padding-left: var(--space-lg); }
}

@media (max-width: 620px) {
  .cats { grid-template-columns: 1fr; }
  .section { padding-block: var(--space-3xl); }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition-duration: 0.01ms !important; animation-duration: 0.01ms !important; }
  .feat img, .feat .ph, .cat img, .cat .ph { transition: none; }
}
