/* ===================================================================
 *  PIANA — app.css (luxury design system, v1 launchpad)
 *  base.css provides normalize + grid + helpers (html font-size: 62.5%).
 *  Color + font tokens are injected from CMS settings in <head>.
 * =================================================================== */

/* ----- fonts (self-hosted) --------------------------------------- */
@font-face {
  font-family: "ABC Arizona Flare";
  src: url("/assets/fonts/ABCArizonaFlare-Light.woff2") format("woff2");
  font-weight: 300 500;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "ABC Arizona Flare";
  src: url("/assets/fonts/ABCArizonaFlare-LightItalic.woff2") format("woff2");
  font-weight: 300 500;
  font-style: italic;
  font-display: swap;
}

/* ----- tokens (non-brand: scale, space, motion) ------------------- */
:root {
  --fs-h1: clamp(3rem, 5.5vw, 5.6rem);
  --fs-h2: clamp(2.4rem, 3.6vw, 4rem);
  --fs-h3: clamp(2rem, 2.4vw, 2.8rem);
  --fs-lead: clamp(1.9rem, 2.2vw, 2.6rem);
  --fs-headline: 4.2rem; /* fixed display headline: home / studio / archive / CTA */
  --fs-body: 1.7rem;
  --fs-copy: 3rem; /* site-wide reading body copy: studio/project text, archive intro */
  --fs-small: 1.3rem;
  --fs-label: 1.15rem;
  --lh-tight: 1.07;
  --lh-body: 1.65;
  --track-label: 0.26rem;

  --ff-sans: "ABC Arizona Flare", Georgia, "Times New Roman", serif;

  --sp-1: 0.8rem;
  --sp-2: 1.6rem;
  --sp-3: 2.4rem;
  --sp-4: 3.2rem;
  --sp-5: 4.8rem;
  --sp-6: 6.4rem;
  --sp-7: 9.6rem;
  --sp-8: 14rem;
  --section-y: clamp(8rem, 12vw, 18rem);
  --gutter: clamp(2.4rem, 5vw, 7rem);

  --maxw-content: 108rem; /* centred inner-content band (text + body images) */
  --maxw-text: 62rem;
  --sign-w: clamp(21.5rem, 81vw, 62rem); /* signature lockup width: intro + hero MUST match */

  --ease-lux: cubic-bezier(0.7, 0, 0.2, 1);
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --dur-fast: 0.4s;
  --dur: 0.8s;
  --dur-slow: 1.2s;

  --header-h: 7.5rem;
  --content-top: calc(var(--header-h) + var(--sp-6)); /* inner-page top clearance */
  --z-header: 100;
  --z-nav: 200;
  --z-intro: 1000;
}
@media (prefers-reduced-motion: reduce) {
  :root {
    --dur-fast: 0.001s;
    --dur: 0.001s;
    --dur-slow: 0.001s;
  }
}

/* ----- base ------------------------------------------------------- */
body {
  background: var(--c-bg);
  color: var(--c-ink);
  font-family: var(--ff-body);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
}
/* Hide the scrollbar (page still scrolls via Lenis/wheel/keys). Also removes the
   layout shift when the intro unlocks overflow — no scrollbar gutter to appear. */
html {
  scrollbar-width: none; /* Firefox */
  -ms-overflow-style: none; /* old Edge */
}
html::-webkit-scrollbar {
  display: none; /* Chrome / Safari */
}
/* Art direction: the shell — navbar, footer, landing hero and the contact-band
   background — is fully responsive and fills the viewport at any width. Only the
   inner content (text columns + body images) stays fixed, capped by the 108rem
   content bands further down and centred, with empty space at the sides on very
   wide screens. So the shell is no longer boxed at 160rem. */
::selection {
  background: var(--c-accent);
  color: #fff;
}

h1,
h2,
h3,
h4 {
  font-family: var(--ff-display);
  font-weight: 400;
  line-height: var(--lh-tight);
}
h1 {
  font-size: var(--fs-h1);
}
h2 {
  font-size: var(--fs-h2);
}
h3 {
  font-size: var(--fs-h3);
}
p {
  margin: 0 0 1.6rem;
}
a {
  color: inherit;
  text-decoration: none;
}

.u-skip {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 999;
  background: var(--c-dark);
  color: #fff;
  padding: 1rem 1.6rem;
}
.u-skip:focus {
  left: 1rem;
  top: 1rem;
}
.u-vh {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}
:focus-visible {
  outline: 2px solid var(--c-accent);
  outline-offset: 3px;
}

.eyebrow {
  font-family: var(--ff-sans);
  font-size: var(--fs-label);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--c-ink-soft);
}
.measure {
  max-width: var(--maxw-text);
}
.section {
  padding-block: var(--section-y);
}
.bleed {
  padding-inline: var(--gutter);
}
/* Inner content pages (no hero): clear the fixed header AND sit in the same
   centred 108rem band as the project detail page — text stays left-aligned
   within, so the whole site shares one content column. Home is excluded (it
   keeps its own full-bleed centred layout). */
.page-top {
  max-width: var(--maxw-content);
  margin-inline: auto;
  /* clear the fixed header, then a modest, uniform gap to the eyebrow
     (was --section-y ≈ 180px — far too tall) */
  padding-top: var(--content-top);
}

/* ----- header chrome --------------------------------------------- */
.s-header {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: var(--z-header);
  height: var(--header-h);
  display: flex;
  align-items: center;
  /* hairline that "materialises" the bar on inner pages; hidden while the
     header floats over the home hero (data-state="on-image") */
  border-bottom: 1px solid var(--c-ink);
  transition:
    background var(--dur-fast) var(--ease-out),
    color var(--dur-fast) var(--ease-out),
    border-bottom-color var(--dur-fast) var(--ease-out);
}
/* Centered, stacked: RP monogram on top, nav below. */
.s-header__bar {
  position: relative;
  width: 100%;
  max-width: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-inline: var(--gutter);
}
/* RP monogram rendered via mask so it follows the header colour
   (white over a hero, ink when solid). Accessible name via sr-only text. */
.s-header__logo {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: calc(var(--header-h));
  height: calc(var(--header-h));
  background-color: currentColor;
  -webkit-mask: url("/assets/icons/rp-icona.svg") center / contain no-repeat;
  mask: url("/assets/icons/rp-icona.svg") center / contain no-repeat;
}
.s-header__nav {
  display: flex;
  align-items: center;
  gap: var(--sp-5);
}
/* logo only appears inside the mobile menu overlay (see responsive block) */
.s-header__nav-logo {
  display: none;
}
.header-nav {
  display: flex;
  gap: var(--sp-4);
}
.header-nav a,
.s-header__lang a {
  font-family: var(--ff-sans);
  font-size: var(--fs-small);
  color: inherit; /* full contrast: ink when solid, white over a hero image */
}
.s-header__lang a {
  letter-spacing: var(--track-label);
  text-transform: uppercase;
}
.header-nav a {
  letter-spacing: 0.04em;
}
/* Header, lang toggle and footer are EXCLUDED from the site-wide link rule and
   keep their own understated underline: a 1px line, transparent at rest, fading
   to currentColor on hover / aria-current. Colour stays contextual — the header
   inherits white over the hero / ink otherwise; the footer sets its own. */
.header-nav a,
.s-header__lang a,
.s-footer__col a {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-decoration-color: transparent;
  text-underline-offset: 0.35em;
  transition:
    color var(--dur-fast) var(--ease-out),
    text-decoration-color var(--dur-fast) var(--ease-out);
}
.header-nav a:hover,
.s-header__lang a:hover,
.s-footer__col a:hover,
.header-nav a[aria-current="page"],
.s-header__lang a[aria-current="true"] {
  text-decoration-color: currentColor;
}

/* Site-wide link treatment (header + footer excluded): text + a 1px underline of
   the SAME colour in every state — ink at rest, accent on hover. currentColor
   keeps the underline tracking the text colour, so one colour transition drives
   both. */
.cta-center a,
.project-nav__title,
.project-card__title,
.contact-band address a {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-decoration-color: currentColor;
  text-underline-offset: 0.35em;
  transition: color var(--dur-fast) var(--ease-out);
}
.cta-center a:hover,
.project-nav a:hover .project-nav__title,
.project-card:hover .project-card__title,
.contact-band address a:hover {
  color: var(--c-accent);
}

/* header colour states (set by JS) */
.s-header[data-state="on-image"] {
  color: #fff;
  border-bottom-color: transparent;
}
/* Scrim behind the header over a hero image — guarantees legibility of the
   white chrome over any photo (contrast can't be statically verified over images). */
.s-header[data-state="on-image"]::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 180%;
  background: linear-gradient(
    to bottom,
    rgba(10, 10, 9, 0.4),
    rgba(10, 10, 9, 0)
  );
  pointer-events: none;
  z-index: -1;
}
.s-header--solid {
  /* No backdrop-filter: it makes the header a containing block for the fixed
     full-screen mobile overlay, which caused the peek/confinement/close glitches.
     Solid background keeps content from bleeding through. */
  background: var(--c-bg);
  /* border-bottom intentionally NOT overridden — the ink hairline from
     .s-header must stay identical before and after the scroll switch */
  color: var(--c-ink);
}
/* While the mobile overlay is open: no backdrop-filter (so the fixed overlay
   escapes the header's containing block) + white burger over the dark menu. */
/* Menu open: the dark full-screen overlay covers the header, so only the
   burger/X needs to stay light over it (scoped to the toggle so the logo keeps
   its own colour while is-nav-open lingers through the close animation). */
.s-header.is-nav-open .s-header__toggle {
  color: #fff;
}

/* hamburger (reused mechanics) */
.s-header__toggle {
  display: none;
  background: none;
  border: 0;
  cursor: pointer;
  width: 3rem;
  height: 3rem;
  color: inherit; /* buttons don't inherit color by default — make the burger track the header */
}
.s-header__toggle span,
.s-header__toggle span::before,
.s-header__toggle span::after {
  content: "";
  display: block;
  position: relative;
  width: 2.4rem;
  height: 1px;
  background: currentColor;
  transition:
    transform var(--dur-fast) var(--ease-out),
    opacity var(--dur-fast);
}
.s-header__toggle span::before {
  position: absolute;
  top: -7px;
}
.s-header__toggle span::after {
  position: absolute;
  top: 7px;
}
.s-header__toggle.is-active span {
  background: transparent;
}
.s-header__toggle.is-active span::before {
  transform: translateY(7px) rotate(45deg);
}
.s-header__toggle.is-active span::after {
  transform: translateY(-7px) rotate(-45deg);
}

/* ----- footer ----------------------------------------------------- */
.s-footer {
  --logo-w: clamp(32rem, 38vw, 52rem);
  background: var(--c-dark);
  color: var(--c-line);
  font-family: var(--ff-sans);
  padding-block: var(--sp-4);
  padding-inline: var(--gutter);
}
/* per contatti mockup: lockup left at the content inset, link columns right */
.s-footer__top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-6);
  flex-wrap: wrap;
}
/* white brand lockup (mask follows the bg colour -> white). The PNG canvas
   carries generous transparent margins, so the box is wider than the visible
   art (~88% of it). */
.s-footer__logo-img {
  flex: 0 0 auto;
  width: var(--logo-w);
  /* cancel the PNG's ~11.1% transparent side margin so the visible art lines up
     with the gutter — matches the right column's edge (left margin == right) */
  margin-left: calc(-0.111 * var(--logo-w));
  aspect-ratio: 3601 / 1601;
  display: block;
  background-color: #fff;
  -webkit-mask: url("/assets/icons/rp-horizontal.png") center / contain
    no-repeat;
  mask: url("/assets/icons/rp-horizontal.png") center / contain no-repeat;
}
.s-footer__cols {
  display: flex;
  gap: var(--sp-7);
}
.s-footer__col p {
  margin: 0 0 0.4rem;
}
.s-footer__col a {
  display: block;
  color: var(--c-line);
  line-height: 2;
}
.s-footer__col a:hover {
  color: var(--c-accent);
}
/* bottom bar: © left, legal links right — well separated from the lockup */
.s-footer__bottom {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  margin-top: var(--sp-7);
  font-size: var(--fs-small);
  color: var(--c-line);
  opacity: 0.7;
}
/* © lines up with the visible logo art above it — now that the lockup is pulled
   flush to the gutter, the © needs no extra inset (both sit at the gutter) */
.s-footer__legal {
  display: flex;
  gap: var(--sp-3);
}
.s-footer__legal a {
  color: inherit;
}
.s-footer__legal a:hover {
  color: var(--c-accent);
  opacity: 1;
}
@media screen and (max-width: 600px) {
  .s-footer {
    padding-block: var(--sp-5) var(--sp-3);
    --logo-w: clamp(26rem, 72vw, 40rem);
  }
  .s-footer__top {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--sp-4);
  }
  .s-footer__cols {
    gap: var(--sp-5);
  }
  .s-footer__bottom {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--sp-2);
    margin-top: var(--sp-5);
  }
}
/* ----- intro (curtain) — only on first visit (html.intro-play) ---- */
.intro {
  position: fixed;
  inset: 0;
  z-index: var(--z-intro);
  background: var(--c-dark);
  display: none;
  place-items: center;
  will-change: transform;
  --intro-cover-shift: 4px;
}
/* Full-screen curtain video (art-director dolly-in). Covers the viewport; the
   dark .intro bg shows only in any letterbox gap before it loads. */
.intro__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: 0;
}
/* NOTE: signature disabled for now — the intro-cover.jpg (::before) existed only
   to align the signature's underline groove, so it's off. To restore the
   signature, re-enable .intro::before and swap the video back in intro.njk.
.intro::before {
  content: "";
  position: absolute;
  inset: -16px 0;
  background: url("/assets/uploads/intro-cover.jpg") center center / cover
    no-repeat;
  transform: translateY(var(--intro-cover-shift));
  z-index: 0;
}
*/
html.intro-play .intro {
  display: grid;
}
/* the curtain lockup occupies the SAME footprint as the hero lockup PNG
   (rp-firma-payoff, 2401x1110) at the same width + centring, so the signature +
   payoff land exactly on the hero signature when the curtain lifts */
.intro__sign {
  position: relative;
  z-index: 1;
  width: var(--sign-w);
  max-width: 90%;
  aspect-ratio: 2401 / 1110;
}
/* payoff subtext (no line — the photo groove is the line): fills the sign box and
   is present from the first frame, never animated. Its baseline sits below the
   photo's groove. */
.intro__payoff {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}
/* animated signature: paths fill #fff; a clip-rect grows left->right (intro.js)
   so the script "writes" itself. Overlays the sign box, above the groove. */
.intro__logo {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  /* hidden until intro.js starts the tween, so it never flashes beforehand */
  opacity: 0;
  visibility: hidden;
}
@media (prefers-reduced-motion: reduce) {
  html.intro-play .intro {
    display: none;
  }
}

/* ----- Lenis smooth scroll ---------------------------------------- */
html.lenis,
html.lenis body {
  height: auto;
}
.lenis.lenis-smooth {
  scroll-behavior: auto !important;
}
.lenis.lenis-smooth [data-lenis-prevent] {
  overscroll-behavior: contain;
}
.lenis.lenis-stopped {
  overflow: hidden;
}
.lenis.lenis-smooth iframe {
  pointer-events: none;
}

/* ----- hero ------------------------------------------------------- */
.s-hero {
  position: relative;
  height: 100svh;
  min-height: 56rem;
  display: grid;
  place-items: center;
  overflow: hidden;
}
/* White "Roberto Piana" signature centered on the hero — same size/centering as
   the animated intro logo (clamp 21.5rem / 81vw / 62rem). Mask keeps it crisp. */
.s-hero__sign {
  position: relative;
  /* matches the intro curtain sign so it settles seamlessly when the curtain lifts */
  width: var(--sign-w);
  max-width: 90%;
  /* logo art is black ink on transparent — force it white for the dark hero */
  filter: brightness(0) invert(1);
}
.s-hero__media,
.s-hero__media img,
.s-hero__media video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* Hero slideshow: each slide is a <picture> from the image shortcode. Collapse
   the wrapper so the inner <img> stacks absolutely (like the single hero did),
   then crossfade slides on opacity. JS toggles .is-active; only the first slide
   is server-rendered active, so no-JS shows a correct static hero. */
.s-hero__media picture {
  display: contents;
}
.s-hero__slide {
  opacity: 0;
  transition: opacity 1.5s ease-in-out;
}
.s-hero__slide.is-active {
  opacity: 1;
}
@media (prefers-reduced-motion: reduce) {
  .s-hero__slide {
    transition: none;
  }
}
.s-hero__overlay {
  position: absolute;
  inset: 0;
  /* per art direction: a tone darker at the top easing to the photo's normal
     tone at the bottom — never towards white */
  background: linear-gradient(
    to bottom,
    rgba(22, 17, 10, 0.55) 0%,
    rgba(22, 17, 10, 0.12) 100%
  );
}
/* ----- home narrative -------------------------------------------- */
/* Home narrative shares the same centred 108rem band + left-aligned text as
   the project detail / inner pages (the hero above stays full-bleed). */
.home-intro {
  display: grid;
  gap: var(--sp-6);
  /* trim the big top gap above the headline and tighten head → gallery */
  padding-top: var(--sp-7);
  max-width: var(--maxw-content);
  margin-inline: auto;
}
.home-intro__head {
  display: grid;
  gap: 0;
  /* tagline + lead: one tight two-line statement, left-aligned to the grid */
  justify-items: start;
  text-align: left;
}
.lead {
  font-family: var(--ff-display);
  font-size: var(--fs-lead);
  line-height: 1.4;
  max-width: 50ch;
}
/* headline + lead: display headline size, left-justified, full grid width,
   tight leading (home.png) */
.home-headline,
.home-intro__head .lead {
  font-size: var(--fs-headline);
  line-height: 1.35;
  max-width: none;
  margin: 0;
}
/* the home narrative reuses the project-gallery block grid (pair / text /
   wide interleaved); left-aligned text rows, tight image gaps */
.home-blocks {
  text-align: left;
}
/* centred CTA closing home / studio / archive (per mockups). Sits centred in the
   band between the last content block and the footer: the top margin matches the
   section's bottom padding (--section-y), so the whitespace above == below. On
   home the parent grid already adds --sp-6, so the top margin is reduced by that. */
.cta-center {
  margin: 0;
  margin-block-start: var(--section-y);
  text-align: center;
}
.home-intro .cta-center {
  margin-block-start: calc(var(--section-y) - var(--sp-6));
}
/* studio: same divider line as the project-nav sits above the CTA. The CTA is
   centred in the band between the divider and the footer — the section's bottom
   padding is trimmed to --sp-7 and the CTA's padding-top matches it, so the gap
   above == below while keeping the band compact. */
body[data-page="studio"] .page-top {
  padding-bottom: var(--sp-7);
}
body[data-page="studio"] .cta-center {
  border-top: 1px solid var(--c-line);
  margin-block-start: var(--sp-7);
  padding-top: var(--sp-7);
}
/* closing CTA (home / studio / archive): headline-sized. Colour + underline come
   from the site-wide link rule (ink → accent, 1px). */
.cta-center a {
  font-family: var(--ff-display);
  font-size: var(--fs-headline);
  color: var(--c-ink);
}

/* ----- projects overview ----------------------------------------- */
/* the grid spans the full content band (the base .row is 89%/1340px-capped);
   negative side margins swallow the outer column padding so the covers sit
   flush with the text above — wider pictures, aligned edges */
.projects-grid {
  width: calc(100% + 40px);
  max-width: none;
  margin-inline: -20px;
  margin-top: var(--sp-4);
  gap: var(--sp-6) 0;
}
/* base.css shrinks column padding to 16px under 1200px — track it */
@media screen and (max-width: 1200px) {
  .projects-grid {
    width: calc(100% + 32px);
    margin-inline: -16px;
  }
}
.project-card {
  position: relative;
  display: block;
  overflow: hidden;
}
.project-card__media {
  aspect-ratio: 4 / 5;
  overflow: hidden;
}
.project-card__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--dur-slow) var(--ease-lux);
}
.project-card:hover .project-card__media img {
  transform: scale(1.04);
}
/* underlined title below the cover, always on one row (per archive mockup).
   overflow:hidden (needed for the ellipsis) would clip an offset underline,
   so the box gets bottom padding for the line to live in. */
.project-card__title {
  margin-top: var(--sp-2);
  font-family: var(--ff-display);
  font-size: 2rem;
  font-weight: normal;
  letter-spacing: 0.01em;
  /* underline + 1px thickness come from the site-wide link rule; only the
     tighter offset is overridden here */
  text-underline-offset: 0.3em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  padding-bottom: 0.45em;
}

/* ----- project detail -------------------------------------------- */
.project-hero {
  position: relative;
  aspect-ratio: 16 / 9;
  overflow: hidden;
}
.project-hero img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.project-hero__cap {
  position: absolute;
  left: var(--gutter);
  bottom: var(--sp-4);
  color: #fff;
}
.project-hero__cap h1 {
  font-size: var(--fs-h1);
}
/* centred content band — eyebrow, text + image grids share one inset column;
   top padding clears the fixed header (this page has no hero) */
.project-body {
  max-width: var(--maxw-content);
  margin-inline: auto;
  padding-inline: var(--gutter);
  padding-top: var(--content-top);
  padding-bottom: var(--sp-8);
}
.project-head {
  margin-bottom: var(--sp-6);
}
/* body copy: full width of the content band, matching the image box.
   30px top/bottom margin, 1.3 line-height */
.project-text {
  margin-block: 3rem;
}
.project-text p {
  font-size: var(--fs-copy);
  line-height: 1.3;
}
.project-text p:last-child {
  margin-bottom: 0;
}
/* a text block placed inside the image grid spans the whole row */
.project-gallery .project-text {
  grid-column: 1 / -1;
}
/* image grid: narrow (portrait) images sit 2-up; a wide (landscape) image
   spans the whole row. Orientation + crop ratio are driven per image by the
   figure's ratio class (.is-r-*). Tight gaps, both axes. */
.project-gallery {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  /* equal gap both axes: stacked images sit as far apart as side-by-side ones */
  gap: var(--sp-4);
}
/* the crop box lives on the FIGURE so it applies with or without a lightbox
   trigger (home / studio use plain figures, project pages wrap a button) */
.project-gallery figure {
  margin: 0;
  overflow: hidden;
}
.project-gallery figure.is-full {
  grid-column: 1 / -1;
}
.project-gallery figure.is-r-3-4 {
  aspect-ratio: 3 / 4;
}
.project-gallery figure.is-r-9-16 {
  aspect-ratio: 9 / 16;
}
.project-gallery figure.is-r-4-3 {
  aspect-ratio: 4 / 3;
}
.project-gallery figure.is-r-16-9 {
  aspect-ratio: 16 / 9;
}
.project-gallery figure > picture,
.project-gallery figure > picture img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.project-gallery figcaption {
  margin-top: var(--sp-1);
  font-family: var(--ff-sans);
  color: var(--c-ink-soft);
  font-size: var(--fs-small);
}
.project-nav {
  display: flex;
  justify-content: space-between;
  border-top: 1px solid var(--c-line);
  padding-top: var(--sp-4);
  margin-top: var(--sp-7);
}
.project-nav a {
  font-family: var(--ff-display);
  font-size: var(--fs-h3);
}
.project-nav__item {
  display: grid;
  gap: 0.4rem;
}
.project-nav__next {
  text-align: right;
}
/* Only the project title carries the underline; the eyebrow label ("Precedente"
   / "Successivo") stays static. Ink → accent colour + underline come from the
   site-wide link rule. */
/* gallery lightbox trigger: fills the figure's crop box (ratio set above) */
.g-trigger {
  display: block;
  width: 100%;
  height: 100%;
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  cursor: zoom-in;
}
.g-trigger picture,
.g-trigger img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
@media screen and (max-width: 600px) {
  .project-gallery {
    grid-template-columns: 1fr;
  }
}

/* ----- studio / contact ------------------------------------------ */
.statement {
  font-family: var(--ff-display);
  font-size: var(--fs-h2);
  max-width: 42ch;
  line-height: 1.2;
}
/* studio + archive top mirror the home headline: 42px, left-justified, full grid
   width, tight leading (studio.png / archivio.png). */
body[data-page="studio"] .statement,
body[data-page="projects"] .statement {
  font-size: var(--fs-headline);
  line-height: 1.35;
  max-width: none;
}
body[data-page="projects"] .statement {
  margin: 0;
}
/* archive intro reads as body copy, same size as .project-text p (studio/project).
   Wider than the 62rem reading measure so it uses the room under the headline. */
.archive-statement {
  font-size: var(--fs-copy);
  line-height: 1.3;
  max-width: var(--maxw-content);
}
body[data-page="studio"] .statement {
  line-height: 1.3;
  margin-bottom: 5rem;
}
.error-page {
  min-height: 100svh;
  display: grid;
  place-content: center;
  justify-items: center;
  text-align: center;
  gap: var(--sp-3);
}
/* contact head band: eyebrow + two-line statement, then the sand band below */
.contact-head {
  padding-bottom: var(--sp-7);
}
/* full-width sand band split in two columns: form left, showroom right
   (per contatti mockup) */
.contact-band {
  background: var(--c-line);
  border-top: 1px solid var(--c-ink);
  /* full-width bg; the inner box carries the gutter so its left edge lines up
     with the .page-top statement above (108rem band, inset by --gutter) */
  padding-block: var(--sp-7) var(--sp-8);
}
.contact-band__inner {
  max-width: var(--maxw-content);
  margin-inline: auto;
  padding-inline: var(--gutter);
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--sp-7);
  align-items: start;
}
.contact-band__title {
  font-size: var(--fs-h3);
  margin-bottom: var(--sp-5);
}
.contact-band address {
  font-family: var(--ff-display);
  font-size: var(--fs-h3);
  color: var(--c-ink);
  line-height: 1.4;
  margin-block: 0 var(--sp-5);
}
/* address links out to Google Maps; uses the site-wide link treatment above */
/* phone sits on its own line below the address, same display treatment */
.contact-phone {
  display: block;
  margin-top: var(--sp-3);
}
.contact-quote {
  color: var(--c-accent);
  font-style: italic;
  font-size: var(--fs-h3);
  line-height: 1.4;
  max-width: 44rem;
}
/* inputs sit on the sand background — darker rule so the lines read */
.contact-band input,
.contact-band textarea {
  border-bottom-color: var(--c-ink-soft);
}
.contact-band .btn {
  width: 100%;
  margin-top: var(--sp-2);
}
@media screen and (max-width: 800px) {
  .contact-band__inner {
    grid-template-columns: 1fr;
  }
}

/* ----- lightbox (PhotoSwipe v5) ---------------------------------- */
/* Theme PhotoSwipe's chrome to match the site: dark backdrop, restrained
   controls that pick up the accent on hover/focus. Behaviour is in gallery.js;
   PhotoSwipe's own stylesheet (photoswipe.css) is linked on project pages. */
.pswp {
  --pswp-bg: var(--c-dark);
  --pswp-icon-color: var(--c-line);
  --pswp-icon-color-secondary: var(--c-dark);
}
.pswp__button:hover .pswp__icn,
.pswp__button:focus-visible .pswp__icn {
  fill: var(--c-accent);
}

/* ----- scroll reveal --------------------------------------------- */
[data-reveal] {
  opacity: 0;
  transform: translateY(2.4rem);
}
html.no-js [data-reveal] {
  opacity: 1;
  transform: none;
}
[data-reveal].is-in {
  opacity: 1;
  transform: none;
  transition:
    opacity var(--dur) var(--ease-out),
    transform var(--dur) var(--ease-out);
}
@media (prefers-reduced-motion: reduce) {
  [data-reveal] {
    opacity: 1;
    transform: none;
  }
}

/* ----- buttons + forms ------------------------------------------- */
.btn {
  display: inline-block;
  font-family: var(--ff-sans);
  font-size: var(--fs-label);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  padding: 1.4rem 2.6rem;
  cursor: pointer;
  transition:
    background var(--dur-fast) var(--ease-out),
    color var(--dur-fast) var(--ease-out);
}
.btn--stroke {
  border: 1px solid currentColor;
  background: none;
  color: inherit;
}
.btn--stroke:hover {
  background: var(--c-ink);
  color: var(--c-bg);
}

form label {
  display: block;
  margin-bottom: var(--sp-3);
}
form input,
form textarea {
  display: block;
  width: 100%;
  margin-top: 0.6rem;
  padding: 1.2rem 0;
  background: none;
  border: 0;
  border-bottom: 1px solid var(--c-line);
  color: var(--c-ink);
  font-family: var(--ff-body);
  font-size: var(--fs-body);
}
form input:focus,
form textarea:focus {
  outline: none;
  border-color: var(--c-accent);
}
address {
  font-style: normal;
  color: var(--c-ink-soft);
  margin-block: var(--sp-4);
}

/* ----- responsive ------------------------------------------------- */
@media screen and (max-width: 800px) {
  .s-header__nav {
    position: fixed;
    inset: 0;
    z-index: var(--z-nav);
    flex-direction: column;
    justify-content: center;
    gap: var(--sp-4);
    background: var(--c-dark);
    color: #fff;
    transform: translateY(-100%);
    /* Hidden when closed so overflow can't peek below a contained (solid)
       header, and the links leave the tab order. Hide is deferred until the
       slide-up finishes. */
    visibility: hidden;
    transition:
      transform var(--dur) var(--ease-lux),
      visibility 0s var(--dur);
  }
  .s-header__nav.is-open {
    transform: translateY(0);
    visibility: visible;
    transition:
      transform var(--dur) var(--ease-lux),
      visibility 0s;
  }
  /* vertical logo, white, centered above the menu items */
  .s-header__nav-logo {
    display: block;
    width: min(58vw, 22rem);
    height: auto;
    margin: 0 auto var(--sp-5);
    filter: brightness(0) invert(1);
  }
  .header-nav {
    flex-direction: column;
    text-align: center;
    gap: var(--sp-3);
  }
  .header-nav a {
    font-size: var(--fs-h3);
    letter-spacing: 0.02em;
    opacity: 0.9;
  }
  .s-header__toggle {
    display: block;
    z-index: calc(var(--z-nav) + 1);
  }
}
