/* ==========================================================================
   BEIRUT COUTURE
   Editorial type system — white dominant, humanist sans throughout.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Tokens
   -------------------------------------------------------------------------- */
:root {
  /* Palette — white is the subject, not the background */
  --white:     #ffffff;
  --paper:     #f8f6f3;
  --paper-dim: #f1ede8;
  --ink:       #141414;   /* 18.4:1 on white */
  --ink-soft:  #4f4a45;   /* 8.9:1  — body copy          */
  --ink-faint: #6f6861;   /* 5.5:1  — labels, meta, captions */
  --ink-ghost: #a9a39d;   /* reserved: decorative only, not currently used for text */
  --rule:      #e4dfd8;
  --flag:      #8a4a4a;   /* 5.9:1 on white — unanswered required field */

  /* Type
     Calibri throughout — display and UI both. Client decision.
     Served by Google Fonts, which licenses it from Monotype; that licence
     covers serving the webfont only, so the wordmark is live text here and
     must NOT be converted to outlines the way an OFL face could be.
     Calibri ships 400/700 roman and italic only — there is no 300, so
     nothing in this file may ask for one (see .numeral).
     Carlito is the metric-compatible OFL fallback; Candara and Segoe UI
     are the nearest Microsoft humanist sans if neither resolves.       */
  --display: Calibri, Carlito, Candara, "Segoe UI", "Helvetica Neue", Arial, sans-serif;
  --sans:    Calibri, Carlito, Candara, "Segoe UI", "Helvetica Neue", Arial, sans-serif;
  --serif:   var(--display);   /* alias, kept so older rules still resolve */

  /* Rhythm — deliberately slow */
  --gutter:  clamp(1.5rem, 5vw, 5.5rem);
  --section: clamp(5rem, 12vw, 11rem);
  --measure: 34rem;

  /* Motion — long, no bounce, ever */
  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
  --slow: 1.1s;
  --mid:  0.55s;

  --header-h: 5.5rem;
}

/* --------------------------------------------------------------------------
   2. Base
   -------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--header-h) + 2rem);   /* anchors land clear of the fixed header */
  overflow-x: hidden;
}

body {
  margin: 0;
  background: var(--white);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 0.9375rem;
  font-weight: 400;
  line-height: 1.8;
  letter-spacing: 0.012em;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

img { display: block; max-width: 100%; height: auto; }
a   { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }

::selection { background: var(--ink); color: var(--white); }

:focus-visible {
  outline: 1px solid var(--ink);
  outline-offset: 4px;
}

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--ink);
  color: var(--white);
  padding: 1rem 1.5rem;
  z-index: 200;
}
.skip:focus { left: 0; }

/* --------------------------------------------------------------------------
   3. Typography
   -------------------------------------------------------------------------- */
h1, h2, h3, h4 {
  font-family: var(--display);
  font-weight: 400;
  line-height: 1.1;
  letter-spacing: 0.005em;
  margin: 0;
}

.display {
  font-size: clamp(2.75rem, 8.5vw, 7.5rem);
  line-height: 1.0;
  letter-spacing: 0.005em;
  font-weight: 400;
}

.h-xl { font-size: clamp(2.1rem, 5vw, 4rem); }
.h-lg { font-size: clamp(1.75rem, 3.4vw, 2.75rem); }
.h-md { font-size: clamp(1.35rem, 2.2vw, 1.85rem); }

.italic { font-style: italic; }

/* Subsection title inside a section (Journal › Editorials): centred tracked
   caps, a hairline running out to each side */
.subtitle {
  display: flex;
  align-items: center;
  gap: clamp(1.25rem, 3vw, 2rem);
  margin-bottom: clamp(2.25rem, 5vw, 3.5rem);
  font-family: var(--sans);
  font-size: 0.8125rem;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  white-space: nowrap;
}
.subtitle::before,
.subtitle::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--rule);
}

/* The tracked uppercase grotesque — all labels, nav, buttons, meta */
.label {
  font-family: var(--sans);
  font-size: 0.6875rem;
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.22em;
  line-height: 1.4;
}

.label--faint { color: var(--ink-faint); }
.label--soft  { color: var(--ink-soft); }

.lede {
  font-family: var(--sans);
  font-size: clamp(0.9375rem, 1.15vw, 1.0625rem);
  font-weight: 400;
  line-height: 1.85;
  letter-spacing: 0.015em;
  max-width: var(--measure);
  color: var(--ink-soft);
}

.body-copy {
  font-family: var(--sans);
  font-size: 0.9375rem;
  line-height: 1.85;
  letter-spacing: 0.012em;
  max-width: var(--measure);
  color: var(--ink-soft);

  /* Every paragraph is justified; hyphenation keeps the word spacing even. */
  text-align: justify;
  text-justify: inter-word;
  hyphens: auto;
  -webkit-hyphens: auto;
}
.body-copy p + p { margin-top: 1.4em; }

/* Journal: a long editorial read, so its paragraphs sit at half the gap
   used elsewhere — the text block is tighter without the lines themselves
   closing up. Covers the Banet Beirut piece and the Individual Portraits. */
#journal .body-copy p + p,
#maison-ali .body-copy p + p,
#nayla .body-copy p + p,
#memories .body-copy p + p,
#muses .body-copy p + p { margin-top: 0.7em; }

/* The About anchor lands on its label, not on the section's empty top padding */
#about { scroll-margin-top: calc(-1 * var(--section)); }

/* Larger reading size for the About text */
.body-copy--lg {
  font-size: clamp(1rem, 1.45vw, 1.45rem);
  line-height: 1.75;
  max-width: 40rem;
}

/* Numeral used as an editorial device */
.numeral {
  font-family: var(--display);
  font-size: clamp(2.5rem, 6vw, 4.5rem);
  font-style: italic;
  font-weight: 400;          /* Calibri has no 300 — asking for one fakes it */
  color: var(--ink-faint);
  line-height: 1;
}

/* --------------------------------------------------------------------------
   4. Layout
   -------------------------------------------------------------------------- */
.shell {
  width: 100%;
  margin-inline: auto;
  padding-inline: var(--gutter);
  max-width: 100rem;
}

.shell--narrow { max-width: 62rem; }

.section { padding-block: var(--section); }
.section--paper { background: var(--paper); }
.section--tight { padding-block: clamp(3.5rem, 7vw, 6rem); }

.rule {
  height: 1px;
  background: var(--rule);
  border: 0;
  margin: 0;
}

/* Editorial split — asymmetric by default, never 50/50 */
.split {
  display: grid;
  gap: clamp(2rem, 5vw, 5rem);
  align-items: center;
}

.split--text-first { grid-template-columns: 1fr; }

@media (min-width: 60rem) {
  .split { grid-template-columns: 5fr 7fr; }
  .split--flip { grid-template-columns: 7fr 5fr; }
  .split--wide-text { grid-template-columns: 6fr 5fr; }
  .split--offset > *:last-child { transform: translateY(clamp(1rem, 4vw, 4rem)); }

  /* Swap sides on wide screens only; stacked, the text still reads first. */
  .split--swap > *:first-child { order: 2; }
}

.stack > * + * { margin-top: 1.5rem; }
.stack--tight > * + * { margin-top: 0.75rem; }
.stack--loose > * + * { margin-top: 2.5rem; }

/* Section heading pattern: tracked label, hairline, serif statement */
.section-head {
  display: grid;
  gap: 1.75rem;
  margin-bottom: clamp(2.5rem, 6vw, 4.5rem);
}

.section-head__meta {
  display: flex;
  align-items: baseline;
  gap: 1.25rem;
}

.section-head__meta::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--rule);
}

/* --------------------------------------------------------------------------
   5. Links & buttons — underline that draws itself
   -------------------------------------------------------------------------- */
.link {
  position: relative;
  display: inline-block;
  padding-bottom: 0.35em;
}

.link::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  width: 100%;
  height: 1px;
  background: currentColor;
  transform: scaleX(1);
  transform-origin: left;
  transition: transform var(--mid) var(--ease);
}

.link:hover::after { transform: scaleX(0); transform-origin: right; }

.link--reveal::after { transform: scaleX(0); transform-origin: left; }
.link--reveal:hover::after { transform: scaleX(1); transform-origin: left; }

.btn {
  display: inline-block;
  border: 1px solid var(--ink);
  padding: 1.15rem 2.75rem;
  background: transparent;
  color: var(--ink);
  transition: background var(--mid) var(--ease), color var(--mid) var(--ease);
}

.btn:hover { background: var(--ink); color: var(--white); }

/* --------------------------------------------------------------------------
   6. Header
   -------------------------------------------------------------------------- */
.header {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 100;
  background: transparent;
  transition: background var(--mid) var(--ease), border-color var(--mid) var(--ease);
  border-bottom: 1px solid transparent;
}

.header.is-solid {
  background: rgba(255, 255, 255, 0.92);
  backdrop-filter: saturate(180%) blur(14px);
  -webkit-backdrop-filter: saturate(180%) blur(14px);
  border-bottom-color: var(--rule);
}

.header__inner {
  height: var(--header-h);
  display: grid;
  grid-template-columns: 1fr auto 1fr;   /* col 1 empty, balances the button */
  align-items: center;
  gap: 1rem;
}

/* Wordmark. Live text, not outlines: the Google/Monotype licence for Calibri
   covers serving the font, not redistributing its glyph shapes, so this may
   not be converted to SVG paths. That means it does depend on the webfont
   loading, and the tracking is letter-spacing rather than baked artwork. */
.wordmark {
  grid-column: 2;
  justify-self: center;
  font-family: var(--display);
  font-size: clamp(1rem, 1.8vw, 1.3rem);
  font-weight: 400;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  white-space: nowrap;
  margin: 0;
}


/* Burger. This is the whole of the navigation now — the inline Services /
   Portfolio / Inquiries links were removed from the header — so unlike
   before it stays visible at every width rather than being hidden on
   desktop. */
.nav-toggle {
  grid-column: 3;
  justify-self: end;
  display: grid;
  gap: 5px;
  padding: 0.75rem 0;
  width: 1.5rem;
}

.nav-toggle span {
  height: 1px;
  width: 100%;
  background: var(--ink);
  transition: transform var(--mid) var(--ease), opacity var(--mid) var(--ease);
}

body.is-menu-open .nav-toggle span:nth-child(1) { transform: translateY(6px) rotate(45deg); }
body.is-menu-open .nav-toggle span:nth-child(2) { opacity: 0; }
body.is-menu-open .nav-toggle span:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }

/* Full-bleed drawer */
.drawer {
  position: fixed;
  inset: 0;
  z-index: 90;
  background: var(--white);
  display: grid;
  place-items: center;
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--slow) var(--ease), visibility var(--slow) var(--ease);
}

body.is-menu-open .drawer { opacity: 1; visibility: visible; }
body.is-menu-open { overflow: hidden; }

.drawer__nav {
  display: grid;
  gap: clamp(1.25rem, 4vw, 2.25rem);
  text-align: center;
}

.drawer__nav a {
  font-family: var(--display);
  font-size: clamp(1.9rem, 9vw, 3.25rem);
  font-weight: 400;
  opacity: 0;
  transform: translateY(0.75rem);
  transition: opacity var(--slow) var(--ease), transform var(--slow) var(--ease);
}

body.is-menu-open .drawer__nav a { opacity: 1; transform: none; }
body.is-menu-open .drawer__nav a:nth-child(2) { transition-delay: 0.07s; }
body.is-menu-open .drawer__nav a:nth-child(3) { transition-delay: 0.14s; }
body.is-menu-open .drawer__nav a:nth-child(4) { transition-delay: 0.21s; }
body.is-menu-open .drawer__nav a:nth-child(5) { transition-delay: 0.28s; }

/* --------------------------------------------------------------------------
   7. Hero — full bleed film. Type sits over the footage in white, on a scrim
   graded so the worst frame still clears AA (measured: 6.4:1 at the title).
   -------------------------------------------------------------------------- */
.hero {
  position: relative;
  min-height: 100svh;
  display: grid;
  align-items: end;
  overflow: hidden;
  background: var(--white);
}

.hero__media { position: absolute; inset: 0; }
.hero__media picture { position: absolute; inset: 0; display: block; }

.hero__media img,
.hero__media video {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.hero__media img { animation: hero-settle 2.4s var(--ease) both; }

@keyframes hero-settle {
  from { transform: scale(1.04); opacity: 0; }
  to   { transform: scale(1);    opacity: 1; }
}

/* the film fades in over the poster once it can genuinely play */
.hero__video {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity 1.8s var(--ease);
  pointer-events: none;
}

.hero__video.is-playing { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  .hero__video { display: none; }
}

/* Full-bleed photograph. A faint wash at the very top keeps the wordmark and
   menu legible over the pale picture. */
.hero__scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(to bottom, rgba(255,255,255,0.40) 0%, rgba(255,255,255,0.00) 16%);
}

.hero__media img { object-position: 50% 55%; }

}

@media (max-width: 23.5rem) {
  .wordmark { font-size: 0.875rem; letter-spacing: 0.2em; }
  .header__inner { gap: 0.5rem; }
}

/* The header floats over a pale photograph, so it keeps ink type throughout. */
.header--overlay.is-solid { color: var(--ink); }
.header--overlay.is-solid .nav-toggle span { background: var(--ink); }

/* Text for screen readers only */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* --------------------------------------------------------------------------
   8. Figures
   -------------------------------------------------------------------------- */
.figure { margin: 0; }

.figure__frame {
  overflow: hidden;
  background: var(--paper-dim);
}

.figure__frame img {
  width: 100%;
  transition: transform 1.4s var(--ease);
}

.figure a:hover .figure__frame img,
.figure__frame:hover img { transform: scale(1.035); }

.figure__caption {
  display: flex;
  justify-content: space-between;
  gap: 1.5rem;
  margin-top: 1.1rem;
  padding-top: 0.9rem;
  border-top: 1px solid var(--rule);
}

.ratio-portrait  { aspect-ratio: 3 / 4; }
.ratio-tall      { aspect-ratio: 2 / 3; }
.ratio-landscape { aspect-ratio: 4 / 3; }
.ratio-square    { aspect-ratio: 1 / 1; }
.ratio-4x5       { aspect-ratio: 4 / 5; }
.ratio-film      { aspect-ratio: 3 / 2; }   /* the film is 2730 x 1440; cover crops its sides a little */

.figure__frame video {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  background: var(--ink);
}

.ratio-4x5 img, .ratio-portrait img, .ratio-tall img, .ratio-landscape img, .ratio-square img {
  height: 100%;
  object-fit: cover;
}

/* Home "About": flexbox. Stacked on small screens (text, then film). From
   60rem it becomes a row — film left, text right — and the text column is
   stretched to the film's height, with the link pinned to the bottom edge. */
.about {
  display: flex;
  flex-direction: column;
  gap: clamp(2rem, 5vw, 5rem);
}

.about__text {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 2.5rem;
  min-width: 0;
}

.about__text .link { align-self: flex-start; }
.about__media { min-width: 0; }
.about + .about { margin-top: clamp(2.5rem, 5vw, 5rem); }

@media (min-width: 60rem) {
  .about { flex-direction: row; align-items: stretch; }
  .about__media { order: -1; flex: 6 1 0; }
  .about__text  { flex: 5 1 0; }
}


/* --------------------------------------------------------------------------
   9. Portfolio grid — asymmetric, magazine-spread
   -------------------------------------------------------------------------- */
.gallery {
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(2.5rem, 5vw, 4.5rem) clamp(1.25rem, 3vw, 2.5rem);
}

@media (min-width: 48rem) {
  .gallery { grid-template-columns: repeat(12, 1fr); }

  /* Each piece claims a different measure and offset — the asymmetry is the design */
  .gallery > * { grid-column: span 6; }
  .gallery > *:nth-child(6n+1) { grid-column: 1 / span 7; }
  .gallery > *:nth-child(6n+2) { grid-column: 9 / span 4; align-self: end; }
  .gallery > *:nth-child(6n+3) { grid-column: 2 / span 4; }
  .gallery > *:nth-child(6n+4) { grid-column: 7 / span 6; align-self: center; }
  .gallery > *:nth-child(6n+5) { grid-column: 1 / span 5; align-self: end; }
  .gallery > *:nth-child(6n+6) { grid-column: 7 / span 5; }
}

/* Filter bar */
.filters {
  display: flex;
  flex-wrap: wrap;
  gap: clamp(1rem, 3vw, 2.25rem);
  padding-block: 1.5rem;
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
  margin-bottom: clamp(3rem, 7vw, 5rem);
}

.filters button { color: var(--ink-faint); transition: color var(--mid) var(--ease); }
.filters button:hover { color: var(--ink); }
.filters button[aria-pressed="true"] { color: var(--ink); }

.gallery__item[hidden] { display: none; }

/* Editorial: five photographs in a flexbox row that re-flows with the screen,
   no sideways scrolling. 5 across on wide screens, 3 on tablets, 2 on phones;
   the leftover photographs sit left-aligned at the same size. Title, photos
   and text all share one column, so their left edges line up. */
.editorial {
  --gap: clamp(1rem, 2vw, 2rem);
  display: flex;
  flex-wrap: wrap;
  gap: clamp(2rem, 4vw, 3rem) var(--gap);
}
.editorial__item { flex: 0 0 calc((100% - var(--gap)) / 2); min-width: 0; }

@media (min-width: 40rem) {
  .editorial__item { flex-basis: calc((100% - 2 * var(--gap)) / 3); }
}
@media (min-width: 64rem) {
  .editorial__item { flex-basis: calc((100% - 4 * var(--gap)) / 5); }
}

/* One photograph on its own, shown far larger than it was in the five-up
   strip. Centred, and capped so a 2:3 portrait cannot run away vertically —
   at full shell width this image would be well over 2000px tall. The frame
   keeps the picture's own ratio, so nothing is cropped. */
.editorial--single { justify-content: center; }
.editorial--single .editorial__item {
  flex: 0 0 100%;
  max-width: 55rem;
}

/* Wider and shorter than the photograph's own 2:3. The four women stand in
   the lower half of the frame — heads about 57% down, hems almost at the
   bottom edge — so the crop is pulled downwards. Centring it would take the
   gowns off at the knee; what is given up instead is the upper balcony. */
#journal .editorial--single .figure__frame { aspect-ratio: 7 / 8; }
#journal .editorial--single .figure__frame img { object-position: center 85%; }

/* The group photograph is the control for its own editorial, so it has to
   look pressable and carry a visible hint — without one, nothing suggests
   the piece is behind it. */
.editorial--single .figure { text-align: center; }
.editorial--single .figure__frame { cursor: pointer; }

/* Always directly under the media and centred, whatever it is nested in —
   `margin-inline: auto` on a fit-content box rather than relying on the
   parent's text-align, which only existed on the editorial--single figures.
   The open state is a class set by main.js, not a sibling selector: the
   hint under the Maison Ali film sits inside the figure, out of reach of
   any `~` from the heading that controls it. */
.disclosure__hint {
  display: flex;
  width: fit-content;
  align-items: baseline;
  gap: 0.55rem;
  margin: 1.1rem auto 0;
  cursor: pointer;
  color: var(--ink-faint);
  transition: color var(--mid) var(--ease);
}
.disclosure__hint::after { content: "+"; }
.disclosure__hint:hover,
.disclosure__hint.is-open { color: var(--ink); }
.disclosure__hint.is-open::after { content: "\2013"; }

.disclosure { margin-top: clamp(2.5rem, 6vw, 4.5rem); }
.disclosure .justified-gallery { margin-top: clamp(2.5rem, 6vw, 4rem); }

/* The editorial heading opens the piece as well as the photograph does */
.editorial__title--toggle { cursor: pointer; transition: color var(--mid) var(--ease); }
.editorial__title--toggle:hover { color: var(--ink-faint); }

.editorial__title {
  letter-spacing: 0.08em;
  margin-bottom: clamp(2rem, 5vw, 3.5rem);
}

/* The text runs the full width of the column, under the photographs */
.editorial__text {
  max-width: none;
  margin-top: clamp(2.5rem, 6vw, 4.5rem);
}

/* Individual portraits: a name and a full-width text, ruled apart */
.portraits { margin-top: clamp(4rem, 9vw, 7rem); }
.portraits__title { margin-bottom: clamp(2rem, 5vw, 3.5rem); }
.portrait { padding-top: clamp(2rem, 4vw, 3rem); border-top: 1px solid var(--rule); }
.portrait + .portrait { margin-top: clamp(2rem, 4vw, 3rem); }
.portrait .editorial__text { margin-top: clamp(1.25rem, 2.5vw, 2rem); }

/* A portrait beside its text: the photograph takes less of the row than the film does */
@media (min-width: 60rem) {
  .about--portrait .about__media { flex: 4 1 0; }
  .about--portrait .about__text  { flex: 7 1 0; }
}
.portraits .about--portrait { padding-top: clamp(2rem, 4vw, 3rem); border-top: 1px solid var(--rule); }
.portraits .about--portrait + .about--portrait { margin-top: clamp(2rem, 4vw, 3rem); }
.about__media .credits { margin-top: clamp(2.5rem, 5vw, 3.5rem); }

/* Justified gallery: photographs of different shapes share a row at one
   height (each grows in proportion to its aspect ratio). Stacks on phones. */
.justified-gallery { display: grid; gap: clamp(1rem, 2vw, 2rem); }
.justified { display: flex; gap: clamp(1rem, 2vw, 2rem); }
.justified__item { flex: var(--r) 1 0; min-width: 0; }
.justified__item .figure__frame img { width: 100%; height: 100%; object-fit: cover; }

@media (max-width: 39.99rem) {
  .justified { flex-direction: column; }
  .justified__item { flex: none; }
}

/* A single line set large and centred, ahead of the text (Arabic, so right-to-left) */
.pullquote {
  margin: clamp(3rem, 7vw, 5rem) auto 0;
  max-width: 48rem;
  text-align: center;
  font-size: clamp(1.6rem, 3.4vw, 2.6rem);
  line-height: 1.6;
  color: var(--ink);
}

/* Creative credits: one small running paragraph, no ruled rows */
.credits { margin-top: clamp(3rem, 7vw, 5rem); }
.credits > h3 {
  font-family: var(--sans);
  font-size: 0.8125rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
}
.credits__text {
  margin: clamp(1rem, 2vw, 1.5rem) 0 0;
  max-width: none;
  font-size: 0.8125rem;
  line-height: 1.9;
  color: var(--ink-soft);
  text-align: left;          /* the site justifies body copy; a credit run reads better ragged */
}
.credits__role { color: var(--ink-faint); }

/* --------------------------------------------------------------------------
   10. Services
   -------------------------------------------------------------------------- */
.service {
  display: grid;
  gap: clamp(1.75rem, 4vw, 3.5rem);
  padding-block: clamp(3rem, 7vw, 5.5rem);
  border-top: 1px solid var(--rule);
  align-items: start;
}

@media (min-width: 60rem) {
  .service { grid-template-columns: 5rem 4fr 6fr; }
}

.service__list { margin: 0; padding: 0; list-style: none; }

.service__list li {
  font-family: var(--sans);
  padding-block: 0.8rem;
  border-bottom: 1px solid var(--rule);
  color: var(--ink-soft);
  font-size: 0.875rem;
  letter-spacing: 0.015em;
}

/* Concierge: one photograph, three tabs. The photograph follows the tab and
   stays in view (sticky) while the longer forms scroll. Without JS every
   panel simply stacks and the first photograph shows. */
.tabs { display: grid; gap: clamp(2rem, 5vw, 4rem); align-items: start; }

.tabs__media .figure__frame { position: relative; }
.tabs__photo {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity var(--slow) var(--ease);
}
.tabs__photo.is-active { opacity: 1; }

.tabs__list {
  display: flex;
  flex-wrap: wrap;
  gap: clamp(1.5rem, 4vw, 3rem);
  border-bottom: 1px solid var(--rule);
  margin-bottom: clamp(2rem, 4vw, 3rem);
}
.tabs__tab {
  position: relative;
  padding: 0.25rem 0 1.1rem;
  color: var(--ink-faint);
  transition: color var(--mid) var(--ease);
}
.tabs__tab::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: -1px;
  height: 1px;
  background: var(--ink);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--mid) var(--ease);
}
.tabs__tab:hover,
.tabs__tab[aria-selected="true"] { color: var(--ink); }
.tabs__tab[aria-selected="true"]::after { transform: scaleX(1); }

.tabs__panel[hidden] { display: none; }
.tabs__panel + .tabs__panel { margin-top: clamp(3rem, 6vw, 5rem); }
.tabs.is-ready .tabs__panel + .tabs__panel { margin-top: 0; }
.tabs__main { min-width: 0; }
.tabs .form { max-width: none; }

@media (min-width: 60rem) {
  .tabs { grid-template-columns: 5fr 7fr; }
  .tabs__media {
    position: sticky;
    top: calc(var(--header-h) + 1.5rem);
  }
}

/* --------------------------------------------------------------------------
   11. Forms
   -------------------------------------------------------------------------- */
.form {
  display: grid;
  gap: clamp(2rem, 4vw, 2.75rem);
  max-width: 44rem;
}

.form__row { display: grid; gap: clamp(2rem, 4vw, 2.75rem); }

@media (min-width: 42rem) {
  .form__row--two { grid-template-columns: 1fr 1fr; }
}

.field { display: grid; gap: 0.75rem; }

.field label { color: var(--ink-soft); }

.field input,
.field select,
.field textarea {
  font-family: var(--sans);
  font-size: 1rem;
  font-weight: 400;
  color: var(--ink);
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--rule);
  border-radius: 0;
  padding: 0.65rem 0 0.8rem;
  transition: border-color var(--mid) var(--ease);
  -webkit-appearance: none;
  appearance: none;
}

.field select {
  background-image: linear-gradient(45deg, transparent 50%, var(--ink-soft) 50%),
                    linear-gradient(135deg, var(--ink-soft) 50%, transparent 50%);
  background-position: calc(100% - 9px) calc(50% + 1px), calc(100% - 4px) calc(50% + 1px);
  background-size: 5px 5px;
  background-repeat: no-repeat;
  padding-right: 1.75rem;
}

.field textarea { resize: vertical; min-height: 7rem; line-height: 1.7; }

.field input:focus,
.field select:focus,
.field textarea:focus {
  outline: 0;
  border-bottom-color: var(--ink);
}

.field input::placeholder,
.field textarea::placeholder { color: var(--ink-faint); }

/* Only after a submit attempt — marking fields invalid while someone is
   still filling the form in is hostile. main.js adds `was-validated`.
   The label sits BEFORE its input in the markup, so flagging it needs
   :has() on the field rather than a sibling combinator. */
.form.was-validated .field input:invalid,
.form.was-validated .field select:invalid,
.form.was-validated .field textarea:invalid {
  border-bottom-color: var(--flag);
}

.form.was-validated .field:has(:invalid) label { color: var(--flag); }

.form__note { color: var(--ink-faint); max-width: 30rem; }

.form__status {
  display: none;
  padding: 1.1rem 1.5rem;
  background: var(--paper);
  border-left: 1px solid var(--ink);
  color: var(--ink-soft);
}

.form__status.is-visible { display: block; }

/* --------------------------------------------------------------------------
   12. Footer
   -------------------------------------------------------------------------- */
.footer {
  padding-block: clamp(4rem, 9vw, 7rem) 2.5rem;
  border-top: 1px solid var(--rule);
}

.footer__grid {
  display: grid;
  gap: clamp(2.5rem, 6vw, 4rem);
}

@media (min-width: 48rem) {
  .footer__grid { grid-template-columns: 4fr 3fr 3fr; }
}

.footer__col { display: grid; gap: 1.1rem; align-content: start; }
.footer__col a { color: var(--ink-soft); transition: color var(--mid) var(--ease); }
.footer__col a:hover { color: var(--ink); }

.footer__base {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 1rem;
  margin-top: clamp(3.5rem, 8vw, 6rem);
  padding-top: 1.75rem;
  border-top: 1px solid var(--rule);
}

/* --------------------------------------------------------------------------
   13. Reveal on scroll
   -------------------------------------------------------------------------- */
.reveal {
  opacity: 0;
  transform: translateY(1.75rem);
  transition: opacity var(--slow) var(--ease), transform var(--slow) var(--ease);
}

.reveal.is-in { opacity: 1; transform: none; }

.reveal[data-delay="1"] { transition-delay: 0.1s; }
.reveal[data-delay="2"] { transition-delay: 0.2s; }
.reveal[data-delay="3"] { transition-delay: 0.3s; }

/* --------------------------------------------------------------------------
   14. Lightbox
   -------------------------------------------------------------------------- */
[data-lightbox] { cursor: zoom-in; }

.lightbox {
  position: fixed;
  inset: 0;
  height: 100vh;
  height: 100dvh;
  z-index: 150;
  background: var(--white);
  display: grid;
  grid-template-rows: auto 1fr auto;
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--mid) var(--ease), visibility var(--mid) var(--ease);
}

.lightbox.is-open { opacity: 1; visibility: visible; }

.lightbox__bar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
  padding: 0.9rem var(--gutter);
}

.lightbox__stage {
  position: relative;      /* the photograph is laid over this box and contained inside it */
  min-height: 0;
}

.lightbox__stage img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  padding: 0 clamp(0.75rem, 3vw, 2.5rem);
  object-fit: contain;     /* the whole photograph, never cropped, never overflowing */
}

.lightbox__foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 1rem clamp(1.25rem, 5vw, 2.5rem);
  padding: 0.6rem var(--gutter) 1rem;
  text-align: center;
}

/* --------------------------------------------------------------------------
   15. Preferences
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
  .reveal { opacity: 1; transform: none; }
}

@media print {
  .header, .drawer, .lightbox, .hero__scroll, .nav-toggle { display: none !important; }
  body { color: #000; }
}
