/* ==========================================================================
   Zauq Boutique — shared stylesheet
   Palette and display typeface are carried over from the Zauq CRM so the
   public site and the internal system read as one brand.
   ========================================================================== */

:root {
  /* Brand — same amber/gold ramp the CRM uses */
  --gold:        #b8860b;
  --gold-deep:   #8a6508;
  --amber:       #f59e0b;
  --amber-soft:  #fef3c7;
  --amber-tint:  #fffbeb;

  /* Neutrals — warm, not blue-grey, so gold sits naturally on them */
  --ink:         #1c1917;
  --ink-soft:    #44403c;
  --muted:       #78716c;
  --line:        #e7e5e4;
  --cream:       #faf7f2;
  --white:       #ffffff;

  --font-display: "Cormorant Garamond", "Playfair Display", Georgia, serif;
  --font-body:    "Jost", "Inter", system-ui, -apple-system, sans-serif;

  --wrap: 1200px;
  --radius: 2px;          /* couture feel: near-square, not bubbly */
  --shadow: 0 18px 40px -24px rgba(28, 25, 23, .45);

  /* Motion. --ease is an ease-OUT curve: things entering decelerate into place.
     --ease-in accelerates away and is only for exits, which run shorter than
     entrances so going back never feels like waiting. */
  --ease: cubic-bezier(.22, .61, .36, 1);
  --ease-in: cubic-bezier(.55, .06, .68, .19);
  /* A long, soft deceleration — most of the distance is covered early and the
     last of it settles slowly, the way heavy fabric falls. This is the curve for
     the unveil; the shorter --ease handles ordinary UI. */
  --ease-veil: cubic-bezier(.16, 1, .3, 1);
  --t-micro: .2s;         /* hovers, presses — must feel instant */
  --t-enter: .38s;        /* reveals */
  --t-exit: .18s;         /* always shorter than --t-enter */
  --t-veil: .85s;         /* the unveil itself — a gesture, not a UI response */
}

/* ---------- Page transitions ----------
   Cross-document view transitions: the browser cross-fades between two full
   page loads with no JS and no router. Chrome, Edge and Safari animate it;
   Firefox ignores the at-rule and navigates normally, which is the correct
   fallback — nothing is layered on top that could break without it. */
@view-transition { navigation: auto; }

/* The new page is drawn down over the old one like a drape falling, rather than
   the two cross-fading. Same gesture as the image unveil, so navigating and
   scrolling speak the same language. The outgoing page holds still underneath —
   nothing fades, it is simply covered. */
::view-transition-old(root) {
  animation: page-hold var(--t-veil) linear both;
}
::view-transition-new(root) {
  animation: page-drape var(--t-veil) var(--ease-veil) both;
}
@keyframes page-hold  { to   { opacity: .999; } }
@keyframes page-drape { from { clip-path: inset(0 0 100% 0); } }

/* The header is identical on every page, so let it sit out the transition and
   stay put rather than sliding with the content underneath it. */
.site-header { view-transition-name: site-header; }

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

html { scroll-behavior: smooth; }

body {
  margin: 0;
  font-family: var(--font-body);
  color: var(--ink-soft);
  background: var(--white);
  line-height: 1.7;
  font-size: 16px;
  -webkit-font-smoothing: antialiased;
}

img { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }

h1, h2, h3, h4 {
  font-family: var(--font-display);
  color: var(--ink);
  font-weight: 500;
  line-height: 1.15;
  margin: 0 0 .5em;
  letter-spacing: .01em;
}
h1 { font-size: clamp(2.6rem, 6vw, 4.6rem); }
h2 { font-size: clamp(2rem, 4vw, 3rem); }
h3 { font-size: clamp(1.3rem, 2vw, 1.6rem); }
p  { margin: 0 0 1.1em; }

.wrap { width: min(100% - 2.5rem, var(--wrap)); margin-inline: auto; }
.section { padding: clamp(4rem, 9vw, 7.5rem) 0; }
.section--cream { background: var(--cream); }
.section--ink { background: var(--ink); color: #d6d3d1; }
.section--ink h2, .section--ink h3 { color: var(--white); }

/* Zardozi motif behind the tinted bands. One SVG serves both grounds — the tile
   is drawn at full strength and the level is set here, so the dark sections can
   carry it heavier than the cream ones without a second file. z-index:-1 puts it
   above the section's own background but below its content. */
.section--cream, .section--ink { position: relative; isolation: isolate; }
.section--cream::before, .section--ink::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: url("../images/motif.svg") 0 0 / 120px 120px repeat;
  pointer-events: none;
}
.section--cream::before { opacity: .05; }
.section--ink::before   { opacity: .09; }
/* --muted is a warm grey for light grounds; it goes muddy on ink. */
.section--ink .lede, .section--ink .note { color: rgba(255, 255, 255, .68); }

/* Small gold eyebrow label above headings */
.eyebrow {
  font-size: .72rem;
  letter-spacing: .3em;
  text-transform: uppercase;
  color: var(--gold);
  font-weight: 600;
  margin-bottom: 1rem;
  display: block;
}

/* Editorial section numbering — "01 | THE COLLECTIONS". The number comes from a
   data-num attribute so it stays out of the text content: it is decorative and
   shouldn't be read aloud as part of the label. */
.section-marker {
  display: inline-flex; align-items: center; gap: .85rem;
  font-size: .72rem; letter-spacing: .3em; text-transform: uppercase;
  color: var(--gold); font-weight: 600; margin-bottom: 1rem;
}
.section-marker[data-num]::before {
  content: attr(data-num);
  font-family: var(--font-display); font-size: 1.2rem;
  letter-spacing: 0; font-weight: 400; line-height: 1;
  padding-right: .85rem;
  border-right: 1px solid rgba(184, 134, 11, .4);
}
.center .section-marker { justify-content: center; }

.lede { font-size: 1.09rem; max-width: 60ch; color: var(--muted); }
.center { text-align: center; }
.center .lede { margin-inline: auto; }

/* The quiet aside under a lede — used for the "book a video call" note that
   repeats on the home, collections and bridal pages. */
.note {
  color: var(--muted); font-size: .95rem;
  max-width: 52ch; margin-inline: auto;
}

/* ---------- Spacing utilities ----------
   Named steps rather than ad-hoc inline margins, so the vertical rhythm between
   a heading block and what follows it is the same on every page. */
.mt-sm { margin-top: 1rem; }
.mt-md { margin-top: 2.6rem; }
.mt-lg { margin-top: 3rem; }
.mt-xl { margin-top: 3.5rem; }
.mb-md { margin-bottom: 1.6rem; }

/* Thin gold rule used as a section divider */
.rule {
  width: 64px; height: 1px; background: var(--gold);
  margin: 1.25rem 0; border: 0;
}
.center .rule { margin-inline: auto; }

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex; align-items: center; gap: .55rem;
  padding: .95rem 2.1rem;
  font-size: .78rem; font-weight: 600;
  letter-spacing: .18em; text-transform: uppercase;
  border: 1px solid var(--ink);
  background: var(--ink); color: var(--white);
  cursor: pointer; border-radius: var(--radius);
  transition: background var(--t-micro) var(--ease), color var(--t-micro) var(--ease),
              border-color var(--t-micro) var(--ease), transform var(--t-micro) var(--ease);
}
/* Touch has no hover state, so the press itself has to acknowledge the tap. */
.btn:active { transform: scale(.985); }
/* The fill wipes in from the left instead of switching on. isolation lets the
   z-index:-1 pseudo paint above the button's own background but below its label,
   so no extra wrapper element is needed. Each variant only has to restate the
   colour it fills with. */
.btn { position: relative; isolation: isolate; overflow: hidden; }
.btn::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: var(--gold);
  transform: scaleX(0); transform-origin: left;
  transition: transform .42s var(--ease-veil);
}
.btn:hover::before { transform: scaleX(1); }
.btn:hover { border-color: var(--gold); color: var(--white); }

.btn--ghost { background: transparent; color: var(--ink); }
.btn--ghost::before { background: var(--ink); }
.btn--ghost:hover { border-color: var(--ink); color: var(--white); }

.btn--light { background: transparent; border-color: rgba(255,255,255,.55); color: #fff; }
.btn--light::before { background: var(--white); }
.btn--light:hover { border-color: var(--white); color: var(--ink); }

/* Tertiary — no box, so a pair of actions reads as one primary and one quiet
   secondary rather than two buttons of identical weight. */
.btn--text {
  padding: .95rem 0;
  background: transparent; border-color: transparent; color: var(--ink);
  overflow: visible;   /* no box, so nothing to clip a fill against */
}
.btn--text::before { display: none; }
.btn--text::after { content: "\2192"; transition: transform .35s var(--ease); }
.btn--text:hover {
  background: transparent; border-color: transparent; color: var(--gold);
  text-decoration: underline; text-underline-offset: .45em;
}
.btn--text:hover::after { transform: translateX(5px); }
/* On dark grounds the ink default disappears. */
.hero .btn--text, .section--ink .btn--text { color: #fff; }
.hero .btn--text:hover, .section--ink .btn--text:hover { color: var(--amber); }

/* Primary action on a dark ground — the inverse of .btn--light. */
.btn--invert { background: var(--white); border-color: var(--white); color: var(--ink); }
.btn--invert::before { background: var(--gold); }
.btn--invert:hover { border-color: var(--gold); color: var(--white); }

/* Fills its column — the sidebar buttons on the contact page. */
.btn--block { width: 100%; justify-content: center; }

/* Keyboard focus was relying on the browser default, which the dark grounds
   swallow. Applies to links, buttons and form controls alike. */
:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 3px;
}

/* ---------- Header ---------- */
.site-header {
  position: sticky; top: 0; z-index: 60;
  background: rgba(255,255,255,.92);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--line);
  transition: box-shadow var(--t-micro) var(--ease);
}
/* Lifts off the page once you've scrolled past the hero — separates the sticky
   bar from the content sliding under it. */
.site-header.is-scrolled { box-shadow: 0 1px 18px -8px rgba(28, 25, 23, .35); }
.nav { display: flex; align-items: center; justify-content: space-between; gap: 1.5rem; padding: .85rem 0; }
.brand { display: flex; align-items: center; gap: .7rem; }
/* The logo carries the brand name itself, so the header shows it alone — no
   text wordmark beside it. Slightly larger than it was to hold the space the
   wordmark used to occupy. */
.brand img { height: 56px; width: auto; }
@media (max-width: 560px) { .brand img { height: 46px; } }
.brand-word {
  font-family: var(--font-display);
  font-size: 1.45rem; color: var(--ink); letter-spacing: .06em;
}
.brand-word small {
  display: block; font-family: var(--font-body);
  font-size: .58rem; letter-spacing: .34em;
  text-transform: uppercase; color: var(--gold); margin-top: -2px;
}
.nav-links { display: flex; align-items: center; gap: 2rem; list-style: none; margin: 0; padding: 0; }
.nav-links a {
  font-size: .8rem; letter-spacing: .13em; text-transform: uppercase;
  font-weight: 500; color: var(--ink-soft); position: relative; padding: .3rem 0;
}
.nav-links a::after {
  content: ""; position: absolute; left: 0; bottom: 0;
  width: 0; height: 1px; background: var(--gold); transition: width .35s var(--ease);
}
.nav-links a:hover::after, .nav-links a[aria-current="page"]::after { width: 100%; }
.nav-links a[aria-current="page"] { color: var(--gold); }

.nav-toggle {
  display: none; background: none; border: 0; cursor: pointer;
  padding: .4rem; color: var(--ink);
}
.nav-toggle svg { width: 26px; height: 26px; }

/* ---------- Hero ---------- */
.hero {
  position: relative; min-height: min(92vh, 840px);
  display: grid; align-items: center;
  /* A left-weighted scrim rather than a flat wash: dense across the text column,
     thinning only past it so the photograph stays visible on the right.
     The stops are set by contrast, not by eye — the dense band has to hold white
     type at 4.5:1 against the brightest pixel a replacement photo might have, so
     it stays >= .55 out to 72%, past where the headline ends. Don't lighten the
     left of this gradient when swapping the image. */
  background:
    linear-gradient(100deg,
      rgba(28, 25, 23, .90) 0%,
      rgba(28, 25, 23, .84) 45%,
      rgba(28, 25, 23, .55) 72%,
      rgba(28, 25, 23, .28) 100%),
    url("../images/hero.webp") center / cover no-repeat,
    var(--ink);
  color: var(--white); overflow: hidden;
}
.hero-inner { position: relative; z-index: 2; padding: 6rem 0; max-width: 46rem; }
.hero h1 {
  color: var(--white); margin-bottom: .3em;
  font-weight: 300; font-size: clamp(3rem, 7vw, 5.5rem); letter-spacing: -.005em;
}
.hero .eyebrow, .hero .section-marker { color: var(--amber); }
.hero p { color: rgba(255,255,255,.82); max-width: 48ch; font-size: 1.08rem; }

/* Shared action row. Centred by default because the CTA sections that reuse it
   sit inside .center; the hero overrides it back to the left. */
.hero-actions { display: flex; gap: 1.4rem; align-items: center; justify-content: center; flex-wrap: wrap; margin-top: 2.2rem; }
.hero .hero-actions { justify-content: flex-start; margin-top: 2.4rem; }

.hero-scroll {
  position: absolute; left: 50%; bottom: 1.8rem; transform: translateX(-50%);
  z-index: 2; display: flex; flex-direction: column; align-items: center; gap: .6rem;
  font-size: .62rem; letter-spacing: .3em; text-transform: uppercase;
  color: rgba(255,255,255,.6);
  transition: opacity var(--t-exit) var(--ease-in);
}
.hero-scroll.is-gone { opacity: 0; }
/* Three runs, not infinite. A decorative loop that never stops is a permanent
   distraction competing with the headline; three is enough to be noticed. It
   also fades out on first scroll (see main.js) — once the hint has been acted
   on it has nothing left to say. */
.hero-scroll::after {
  content: ""; width: 1px; height: 42px;
  background: linear-gradient(rgba(255,255,255,.65), transparent);
  animation: scroll-cue 2.6s var(--ease) 3;
}
@keyframes scroll-cue {
  0%   { transform: scaleY(0); transform-origin: top; }
  45%  { transform: scaleY(1); transform-origin: top; }
  55%  { transform: scaleY(1); transform-origin: bottom; }
  100% { transform: scaleY(0); transform-origin: bottom; }
}
@media (max-width: 820px) { .hero-scroll { display: none; } }

/* Below 1024px the text column takes up most of the width, so there is no "past
   the text" side left to thin out — a directional scrim would leave the end of
   each line sitting on bare photograph. Back to an even wash, which holds white
   type at 7.4:1 even against a fully blown-out image. The reveal on the right is
   a wide-screen effect; it only earns its keep where there is room for it. */
@media (max-width: 1023px) {
  .hero {
    min-height: min(88vh, 720px);
    background:
      linear-gradient(rgba(28, 25, 23, .82), rgba(28, 25, 23, .74)),
      url("../images/hero.webp") center / cover no-repeat,
      var(--ink);
  }
}

/* ---------- Interior page banner ----------
   Left-aligned to match the hero. The --image variant puts a photograph behind
   the same scrim so the four interior pages stop opening identically; each page
   picks its own via a modifier rather than an inline style. */
.page-head {
  background: var(--ink); color: var(--white);
  padding: clamp(4.5rem, 9vw, 7rem) 0;
}
.page-head h1 {
  color: var(--white); font-weight: 300;
  font-size: clamp(2.6rem, 6vw, 4.4rem); letter-spacing: -.005em;
}
.page-head p { color: rgba(255,255,255,.75); max-width: 54ch; }
/* Denser than the hero's scrim and never thinner than .66, because a banner is
   short enough that its heading can run the full width on a narrow screen. */
.page-head--image {
  background:
    linear-gradient(100deg, rgba(28,25,23,.92) 0%, rgba(28,25,23,.86) 45%, rgba(28,25,23,.66) 100%),
    var(--page-img) center 25% / cover no-repeat,
    var(--ink);
}
.page-head--collections { --page-img: url("../images/farshi-lehanga.webp"); }
.page-head--bridal      { --page-img: url("../images/bridal-barat.webp"); }
.page-head--about       { --page-img: url("../images/studio.webp"); }
.page-head--contact     { --page-img: url("../images/atelier-craft.webp"); }
.page-head--journal     { --page-img: url("../images/fabric-handwork.webp"); }
.page-head--gallery     { --page-img: url("../images/atelier-craft.webp"); }

/* ---------- Grid + cards ---------- */
/* Explicit column counts, not auto-fit. auto-fit landed the nine collection
   tiles as 4/4/1 at some widths; pinning keeps rows even — 9 = 3/3/3, 4 = 4
   or 2/2 — with no orphan sitting alone on the last row. */
.grid { display: grid; gap: 1.6rem; grid-template-columns: 1fr; }
@media (min-width: 560px) {
  .grid--2, .grid--3, .grid--4 { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 900px) {
  .grid--3 { grid-template-columns: repeat(3, 1fr); }
  .grid--4 { grid-template-columns: repeat(4, 1fr); }
}

.card {
  background: var(--white); border: 1px solid var(--line);
  border-radius: var(--radius); overflow: hidden;
  transition: box-shadow .45s var(--ease), border-color .45s var(--ease);
  /* The footer deep-links to individual tiles (collections.html#gharara). The
     header is sticky, so without this the target lands underneath it. */
  scroll-margin-top: 6rem;
}
/* Hover choreography — three things on one timing rather than three separate
   effects: the photograph deepens, a gold hairline draws under the title, and
   the card's border warms. .card--plain has no figure to zoom (about.html uses
   it for text-only cards), so it gets the border-and-shadow lift instead. */
.card:hover .tile-figure img { transform: scale(1.07); }
.card:hover { border-color: var(--amber-soft); }
.card h3 { position: relative; display: inline-block; }
.card h3::after {
  content: ""; position: absolute; left: 0; bottom: -.12em;
  width: 100%; height: 1px; background: var(--gold);
  transform: scaleX(0); transform-origin: left;
  transition: transform .45s var(--ease-veil);
}
.card:hover h3::after { transform: scaleX(1); }
.card--plain:hover { box-shadow: var(--shadow); border-color: var(--amber-soft); }
.card-body { padding: 1.6rem; }
.card h3 { margin-bottom: .35rem; }
.card p { color: var(--muted); font-size: .94rem; margin: 0; }

/* Category tile — holds a 3:4 product photograph. The dark gradient shows only
   while the image loads; object-fit crops the photo to fill the ratio. */
.tile-figure {
  /* Square, because the photography is square. The studio images come out of
     the generator at 1024x1024, and forcing them into a 3:4 tile meant cropping
     25% off the width — which is exactly where the wall logo sits, so it came
     back clipped on most tiles. Matching the tile to the source shows each piece
     whole, centred, with the mark intact.
     If the photography is ever re-generated at 3:4, change this back to 3 / 4
     and change .split-figure below to 4 / 5 at the same time. */
  aspect-ratio: 1 / 1;
  background: linear-gradient(150deg, #2a2724, var(--ink));
  display: grid; place-items: center; position: relative; overflow: hidden;
}
.tile-figure img {
  width: 100%; height: 100%; object-fit: cover;
  transition: transform .9s var(--ease-veil);
}

/* ---------- Feature row (image + text) ---------- */
.split { display: grid; gap: clamp(2rem, 5vw, 4rem); align-items: center; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); }
/* Columns of unequal height — the contact page form and sidebar — should top-align
   rather than float against each other's centre. */
.split--top { align-items: start; }
.split-figure {
  aspect-ratio: 1 / 1; background: linear-gradient(150deg, #2a2724, var(--ink));
  display: grid; place-items: center; position: relative; overflow: hidden;
}
.split-figure img { width: 100%; height: 100%; object-fit: cover; }

/* ---------- Stats / list ---------- */
/* 190px minimum, not 160px: the longest value ("Worldwide") needs ~168px at the
   top of the clamp. Sizing the column to the content removes the need for the
   per-word override this used to carry. */
.stat-row { display: grid; gap: 2rem; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); text-align: center; }
.stat b {
  display: block; font-family: var(--font-display);
  font-size: clamp(2rem, 4.5vw, 2.6rem);
  color: var(--gold); line-height: 1;
}
.stat span { font-size: .76rem; letter-spacing: .18em; text-transform: uppercase; color: var(--muted); }

.ticks { list-style: none; padding: 0; margin: 0; }
.ticks li { padding-left: 1.9rem; position: relative; margin-bottom: .8rem; }
.ticks li::before {
  content: ""; position: absolute; left: 0; top: .62em;
  width: 12px; height: 1px; background: var(--gold);
}
/* Inside a panel, where the surrounding type is already smaller. */
.ticks--sm { margin-top: .8rem; font-size: .94rem; }

/* ---------- Steps ---------- */
.step { position: relative; padding-top: 2.4rem; }
.step-num {
  position: absolute; top: 0; left: 0;
  font-family: var(--font-display); font-size: 2.4rem; color: var(--amber-soft);
  line-height: 1;
}
.section--ink .step-num { color: rgba(184,134,11,.45); }
/* The unit that trails a step number — "12 wks" on the bridal timelines. */
.step-unit { font-size: 1rem; letter-spacing: .04em; }

/* ---------- Panels ----------
   Bordered content boxes, used down the contact page sidebar. The base owns the
   padding, border and radius; modifiers only set the ground, so the boxes stay
   in step with each other however many get added later. */
.panel {
  padding: 1.4rem 1.6rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
}
.panel--lg { padding: clamp(1.8rem, 4vw, 2.6rem); }
.panel--cream { background: var(--cream); }
.panel--amber { background: var(--amber-tint); border-color: var(--amber-soft); }
.panel + .panel { margin-top: 1.6rem; }
.panel h2 { font-size: clamp(1.6rem, 3vw, 2.1rem); }
.panel-title { font-size: 1.15rem; margin-bottom: .5rem; }
.panel-title + p { font-size: .94rem; color: var(--muted); }

/* ---------- FAQ ----------
   Native <details>, so it needs no JavaScript and stays open to a crawler and a
   screen reader whether or not it is expanded on screen. */
.faq { max-width: 68ch; margin-inline: auto; }
.faq details { border-bottom: 1px solid var(--line); padding: 1.15rem 0; }
.faq details:first-of-type { border-top: 1px solid var(--line); }
.faq summary {
  cursor: pointer; list-style: none;
  font-family: var(--font-display); font-size: 1.22rem; color: var(--ink);
  display: flex; justify-content: space-between; align-items: baseline; gap: 1.5rem;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: "+"; color: var(--gold); font-size: 1.35rem; line-height: 1; flex: none;
}
.faq details[open] summary::after { content: "\2212"; }
.faq details p { margin: .9rem 0 0; color: var(--muted); font-size: .97rem; max-width: 62ch; }

/* ---------- Forms ---------- */
.form { display: grid; gap: 1.15rem; }
.field { display: grid; gap: .4rem; }
.field label {
  font-size: .72rem; letter-spacing: .16em; text-transform: uppercase;
  font-weight: 600; color: var(--ink);
}
.field .req { color: var(--gold); }
/* Opts a word out of the uppercase label treatment above. */
.field label .optional {
  color: var(--muted); font-weight: 400;
  text-transform: none; letter-spacing: 0;
}
.field input, .field select, .field textarea {
  font-family: var(--font-body); font-size: .96rem; color: var(--ink);
  padding: .85rem 1rem; background: var(--white);
  border: 1px solid var(--line); border-radius: var(--radius);
  transition: border-color .25s var(--ease), box-shadow .25s var(--ease);
  width: 100%;
}
.field input:focus, .field select:focus, .field textarea:focus {
  outline: 0; border-color: var(--gold);
  box-shadow: 0 0 0 3px rgba(184,134,11,.12);
}
.field textarea { resize: vertical; min-height: 120px; }
.field-row { display: grid; gap: 1.15rem; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
.field .error { color: #b91c1c; font-size: .78rem; display: none; }
.field.invalid input, .field.invalid select, .field.invalid textarea { border-color: #b91c1c; }
.field.invalid .error { display: block; }
.form-note { font-size: .82rem; color: var(--muted); }
/* Confirmation revealed once the enquiry has been handed off to WhatsApp. */
.form-status { padding: 1rem 1.2rem; margin-bottom: 1.4rem; }
.form-status strong { color: var(--ink); }
.form-status p { margin: .3rem 0 0; font-size: .9rem; }

/* ---------- Reference upload ----------
   The real <input type="file"> is hidden rather than removed — it stays in the
   tab order and keeps its label association, so the keyboard and a screen reader
   still reach it. The visible control is the <label> pointing at it. */
.upload-input {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden; clip-path: inset(50%); border: 0;
}
.upload-drop {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: .25rem 1rem;
  padding: 1rem 1.15rem; cursor: pointer;
  border: 1px dashed var(--line); border-radius: var(--radius);
  background: var(--white);
  transition: border-color var(--t-micro) var(--ease), background var(--t-micro) var(--ease);
}
.upload-drop:hover { border-color: var(--gold); background: var(--amber-tint); }
.upload-input:focus-visible + .upload-drop { outline: 2px solid var(--gold); outline-offset: 3px; }
.upload-cta {
  font-size: .78rem; font-weight: 600; letter-spacing: .16em;
  text-transform: uppercase; color: var(--ink);
}
.upload-hint { font-size: .84rem; color: var(--muted); }

.upload-bar { height: 2px; background: var(--line); margin-top: .6rem; overflow: hidden; }
.upload-bar > span {
  display: block; height: 100%; width: 0; background: var(--gold);
  transition: width .2s linear;
}
.upload-status { font-size: .84rem; color: var(--muted); margin: .5rem 0 0; }
.upload-status.is-done  { color: var(--gold-deep); }
.upload-status.is-error { color: #b91c1c; }

/* A single checkbox has to opt out of the full-width input styling above. */
.check { display: flex; align-items: center; gap: .7rem; cursor: pointer; }
.field .check input { width: auto; padding: 0; flex: none; accent-color: var(--gold); }
.check span {
  font-size: .94rem; color: var(--ink);
  text-transform: none; letter-spacing: 0; font-weight: 400;
}

/* ---------- Long-form article ----------
   The rest of the site is short blocks of copy inside a layout; a journal entry
   is one column of continuous prose, so it needs a measure and a rhythm of its
   own. 68ch is about 12 words a line, which is where sustained reading sits. */
.prose { max-width: 68ch; margin-inline: auto; }
.prose > p, .prose > ul, .prose > ol { font-size: 1.06rem; }
.prose h2 { font-size: clamp(1.5rem, 3vw, 2rem); margin-top: 2.6rem; }
.prose h3 { font-size: 1.2rem; margin-top: 2rem; }
.prose a {
  color: var(--gold-deep); text-decoration: underline;
  text-underline-offset: .2em; text-decoration-thickness: 1px;
}
.prose a:hover { color: var(--gold); }
.prose ul { padding-left: 1.15rem; margin: 0 0 1.1em; }
.prose li { margin-bottom: .55rem; }
.prose figure { margin: 2.2rem 0; }
.prose figcaption {
  font-size: .84rem; color: var(--muted); margin-top: .6rem;
  letter-spacing: .02em;
}
.prose strong { color: var(--ink); font-weight: 600; }

.article-meta {
  font-size: .74rem; letter-spacing: .18em; text-transform: uppercase;
  color: var(--muted); margin-bottom: 1rem;
}
/* Closing note at the foot of an entry — a soft hand-off, not another CTA block. */
.article-end {
  margin-top: 3rem; padding-top: 1.8rem; border-top: 1px solid var(--line);
}

/* ---------- Journal listing ----------
   The listing sits inside .prose for the measure, so these have to out-specify
   .prose a — otherwise every entry card gets an underline meant for body links. */
.prose .entry, .entry {
  display: block; border-bottom: 1px solid var(--line); padding: 2.2rem 0;
  text-decoration: none; color: inherit;
}
.entry:first-of-type { border-top: 1px solid var(--line); }
.entry h2 {
  font-size: clamp(1.45rem, 2.6vw, 1.9rem); margin-bottom: .5rem;
  transition: color var(--t-micro) var(--ease);
}
.entry:hover h2 { color: var(--gold-deep); }
.entry p { color: var(--muted); margin: 0; max-width: 64ch; }

/* ---------- Colourway configurator ---------- */
.cfg { display: grid; gap: clamp(2rem, 5vw, 3.5rem); align-items: start; }
@media (min-width: 900px) {
  .cfg { grid-template-columns: minmax(0, 1.15fr) minmax(300px, .85fr); }
}
.cfg-stage {
  position: relative; background: var(--cream);
  border: 1px solid var(--line); overflow: hidden;
}
.cfg-stage canvas { display: block; width: 100%; height: auto; }
/* The plain photograph sits underneath and shows through until the canvas has
   rendered, so the frame is never empty and never collapses. */
.cfg-stage img { display: block; width: 100%; height: auto; }
.cfg.is-ready .cfg-stage img { display: none; }
.cfg-stage canvas { display: none; }
.cfg.is-ready .cfg-stage canvas { display: block; }

.cfg-zone + .cfg-zone { margin-top: 1.9rem; }
.cfg-zone-label {
  font-family: var(--font-body); font-size: .72rem; letter-spacing: .18em;
  text-transform: uppercase; font-weight: 600; color: var(--gold);
  margin-bottom: .85rem;
}
.cfg-swatches { display: flex; flex-wrap: wrap; gap: .6rem; }
/* 44px, not the 32 this wants to be visually — anything smaller is a miss on a
   phone, and this control is used almost entirely on phones. */
.cfg-swatch {
  width: 44px; height: 44px; padding: 0; border-radius: 50%; cursor: pointer;
  background: var(--swatch); border: 1px solid rgba(28, 25, 23, .18);
  transition: transform var(--t-micro) var(--ease), box-shadow var(--t-micro) var(--ease);
}
.cfg-swatch:hover { transform: scale(1.09); }
.cfg-swatch[aria-checked="true"] {
  box-shadow: 0 0 0 2px var(--white), 0 0 0 3px var(--ink);
}
.cfg-summary {
  margin-top: 2rem; padding-top: 1.4rem; border-top: 1px solid var(--line);
  font-family: var(--font-display); font-size: 1.15rem; color: var(--ink);
}
.cfg-summary::first-letter { text-transform: uppercase; }
.cfg-caveat { font-size: .86rem; color: var(--muted); margin-top: .8rem; }

/* ---------- Product page ---------- */
.product { display: grid; gap: clamp(2rem, 5vw, 3.5rem); align-items: start; }
@media (min-width: 900px) {
  .product { grid-template-columns: minmax(0, 1fr) minmax(320px, .9fr); }
  /* The picture stays put while the description scrolls past it. */
  .product-figure { position: sticky; top: 6rem; }
}
.product-figure { overflow: hidden; background: var(--cream); border: 1px solid var(--line); }
.product-figure img { display: block; width: 100%; height: auto; }
.product-detail h1 { font-size: clamp(2.2rem, 5vw, 3.2rem); }
.product-long { margin-top: 1.6rem; max-width: none; }
.product-long > p { font-size: 1rem; }
.product-note { font-size: .82rem; color: var(--muted); margin: .7rem 0 0; text-align: center; }
.product-nav {
  display: flex; justify-content: space-between; gap: 1rem; flex-wrap: wrap;
  margin-top: clamp(3rem, 7vw, 5rem); padding-top: 1.6rem;
  border-top: 1px solid var(--line);
  font-size: .78rem; letter-spacing: .16em; text-transform: uppercase; font-weight: 600;
}
.product-nav a { color: var(--ink); }
.product-nav a:hover { color: var(--gold); }

/* ---------- Gallery ---------- */
.shots { display: grid; gap: 1.4rem; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); }
.shot { margin: 0; }
.shot-open {
  display: block; width: 100%; padding: 0; cursor: zoom-in;
  border: 1px solid var(--line); background: var(--cream); overflow: hidden;
  border-radius: var(--radius);
}
.shot-open img {
  display: block; width: 100%; height: auto; aspect-ratio: 1 / 1; object-fit: cover;
  transition: transform .9s var(--ease-veil);
}
.shot-open:hover img { transform: scale(1.06); }
.shot figcaption {
  margin-top: .7rem; font-family: var(--font-display); font-size: 1.08rem; color: var(--ink);
  display: flex; justify-content: space-between; align-items: baseline; gap: 1rem;
}
.shot-link {
  font-family: var(--font-body); font-size: .68rem; letter-spacing: .16em;
  text-transform: uppercase; font-weight: 600; color: var(--gold); flex: none;
}
.shot-link:hover { color: var(--gold-deep); }

/* ---------- Lightbox ---------- */
.lightbox {
  position: fixed; inset: 0; z-index: 200;
  background: rgba(20, 18, 16, .93);
  display: flex; align-items: center; justify-content: center; gap: clamp(.5rem, 3vw, 2rem);
  padding: clamp(1rem, 4vw, 3rem);
}
.lightbox[hidden] { display: none; }
.lightbox-stage { margin: 0; max-width: min(92vw, 900px); text-align: center; }
.lightbox-stage img {
  max-width: 100%; max-height: 78vh; width: auto; height: auto;
  display: block; margin-inline: auto;
}
.lightbox-stage figcaption {
  color: rgba(255,255,255,.82); margin-top: 1rem;
  font-size: .74rem; letter-spacing: .2em; text-transform: uppercase;
}
.lightbox-close, .lightbox-nav {
  background: none; border: 0; cursor: pointer; color: #fff; flex: none;
  /* 44px minimum — these are the only controls in the dialog. */
  min-width: 44px; min-height: 44px;
  transition: color var(--t-micro) var(--ease);
}
.lightbox-close { position: absolute; top: 1rem; right: 1.2rem; font-size: 2.2rem; line-height: 1; }
.lightbox-nav { font-size: 1.6rem; }
.lightbox-close:hover, .lightbox-nav:hover { color: var(--amber); }
@media (max-width: 640px) {
  /* Arrows would crowd the picture on a phone; swipe-free but Escape and the
     close button still work, and the grid is only a tap away. */
  .lightbox-nav { position: absolute; bottom: 1.2rem; }
  .lightbox-prev { left: 1.2rem; }
  .lightbox-next { right: 1.2rem; }
}

/* ---------- Map ---------- */
.map-embed {
  width: 100%; aspect-ratio: 16 / 9; min-height: 300px;
  border: 1px solid var(--line); border-radius: var(--radius);
  display: block; filter: grayscale(.25);
}
@media (max-width: 640px) { .map-embed { aspect-ratio: 4 / 3; } }

/* ---------- Contact list ---------- */
.contact-list { list-style: none; padding: 0; margin: 1.8rem 0 0; display: grid; gap: 1.6rem; }
/* The studio address, called out under the "Find us" lede. */
.contact-address { font-size: 1.02rem; color: var(--ink); margin-top: .4rem; }
.contact-list dt {
  font-size: .72rem; letter-spacing: .18em; text-transform: uppercase;
  color: var(--gold); font-weight: 600; margin-bottom: .25rem;
}
.contact-list dd { margin: 0; color: var(--ink); font-size: 1.02rem; }
.contact-list a:hover { color: var(--gold); }

/* ---------- Footer ---------- */
.site-footer { background: var(--ink); color: #a8a29e; padding: 4.5rem 0 2rem; }
.site-footer h4 {
  color: var(--white); font-family: var(--font-body);
  font-size: .74rem; letter-spacing: .2em; text-transform: uppercase; margin-bottom: 1.1rem;
}
.site-footer a:hover { color: var(--amber); }
.site-footer .brand-word { color: var(--white); }
.footer-intro { margin-top: 1rem; font-size: .92rem; max-width: 32ch; }
.footer-grid { display: grid; gap: 2.5rem; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); }
.footer-list { list-style: none; padding: 0; margin: 0; display: grid; gap: .6rem; font-size: .92rem; }
.footer-bottom {
  margin-top: 3rem; padding-top: 1.5rem; border-top: 1px solid rgba(255,255,255,.1);
  display: flex; justify-content: space-between; gap: 1rem; flex-wrap: wrap;
  font-size: .82rem; color: #78716c;
}

/* ---------- Reveal-on-scroll (progressive enhancement) ----------
   12px of travel, not the 22px this used to carry: past roughly 16px it stops
   reading as a fade and starts reading as a slide, which puts the attention on
   the motion instead of on the content. Duration came down from 700ms for the
   same reason — a reveal that outlasts the eye's arrival feels sluggish. */
.reveal {
  opacity: 0; transform: translateY(12px);
  transition: opacity var(--t-enter) var(--ease), transform var(--t-enter) var(--ease);
}
.reveal.is-visible { opacity: 1; transform: none; }

/* ---------- Sequencing ----------
   One --d custom property per child carries its place in the queue. It inherits,
   so anything nested inside a child can read the same delay without the selector
   list doubling for every element that needs to move together. Capped at eight
   steps — past that the last tile trails the first far enough that the group
   stops reading as one gesture, so the collections grid's ninth tile shares the
   eighth's place. */
.stagger > *, .veil > * { --d: 0s; }
.stagger > :nth-child(2), .veil > :nth-child(2) { --d: .07s; }
.stagger > :nth-child(3), .veil > :nth-child(3) { --d: .14s; }
.stagger > :nth-child(4), .veil > :nth-child(4) { --d: .21s; }
.stagger > :nth-child(5), .veil > :nth-child(5) { --d: .28s; }
.stagger > :nth-child(6), .veil > :nth-child(6) { --d: .35s; }
.stagger > :nth-child(7), .veil > :nth-child(7) { --d: .42s; }
.stagger > :nth-child(n+8), .veil > :nth-child(n+8) { --d: .49s; }

/* Fade-and-rise, for grids of text where there is no photograph to unveil. */
.stagger > * {
  opacity: 0; transform: translateY(12px);
  transition: opacity var(--t-enter) var(--ease), transform var(--t-enter) var(--ease);
}
.stagger.is-visible > * { opacity: 1; transform: none; transition-delay: var(--d); }

/* ---------- The unveil ----------
   The signature. A photograph is never faded in — it is wiped open from the top
   down, the way a cover comes off a finished piece, while the image itself
   settles back from slightly oversized as though the fabric is coming to rest.

   The settle uses the standalone `scale` property rather than `transform`, on
   purpose: that leaves `transform` free for the hover zoom, so the two compose
   instead of one cancelling the other. */
.veil .tile-figure, .veil-figure {
  clip-path: inset(0 0 100% 0);
}
.veil .tile-figure img, .veil-figure img { scale: 1.14; }

.veil.is-visible .tile-figure, .veil-figure.is-visible {
  clip-path: inset(0 0 0 0);
  transition: clip-path var(--t-veil) var(--ease-veil) var(--d, 0s);
}
.veil.is-visible .tile-figure img, .veil-figure.is-visible img {
  scale: 1;
  /* transform is listed here too, not just on the base rule — this declaration
     replaces that one wholesale rather than merging with it, so leaving it out
     would make the hover zoom snap with no transition once a tile is revealed. */
  transition: scale 1.2s var(--ease-veil) var(--d, 0s),
              transform .9s var(--ease-veil);
}

/* ---------- Masked line reveal ----------
   Each line of a display heading rises out from behind its own hem. The overflow
   clip is what sells it, and the padding/margin pair gives descenders somewhere
   to live so the clip doesn't slice the tail off a "g". */
.lines > .line {
  display: block; overflow: hidden;
  padding-bottom: .14em; margin-bottom: -.14em;
}
.lines > .line > span {
  display: block;
  animation: line-rise .95s var(--ease-veil) backwards;
}
.lines > .line:nth-child(1) > span { animation-delay: .12s; }
.lines > .line:nth-child(2) > span { animation-delay: .26s; }
.lines > .line:nth-child(3) > span { animation-delay: .40s; }
@keyframes line-rise { from { transform: translateY(105%); } }

/* The hero headline carries its own reveal, so it sits out the group entrance. */
.hero h1, .page-head h1 { animation: none; }

/* ---------- The gold rule draws itself ----------
   This hairline is already the site's divider motif; making it draw rather than
   appear costs nothing and ties the section headers into the same language.
   scaleX, not width — width would relayout on every frame. */
.rule { transform: scaleX(0); transform-origin: left; }
.center .rule { transform-origin: center; }
.reveal.is-visible .rule, .stagger.is-visible .rule, .veil.is-visible .rule {
  transform: scaleX(1);
  transition: transform .7s var(--ease-veil) .1s;
}

/* Hero entrance — one choreographed group rather than four elements each doing
   their own thing. Runs on load, so no observer is involved. */
.hero-inner > * { animation: hero-in .5s var(--ease) both; }
.hero-inner > :nth-child(1) { animation-delay: .08s; }
.hero-inner > :nth-child(2) { animation-delay: .16s; }
.hero-inner > :nth-child(3) { animation-delay: .24s; }
.hero-inner > :nth-child(4) { animation-delay: .32s; }
@keyframes hero-in { from { opacity: 0; transform: translateY(14px); } }

/* ---------- Responsive ---------- */
@media (max-width: 820px) {
  .nav-toggle { display: block; }
  .nav-links {
    position: absolute; top: 100%; left: 0; right: 0;
    background: var(--white); border-bottom: 1px solid var(--line);
    flex-direction: column; align-items: flex-start; gap: 0;
    padding: .5rem 1.25rem 1.25rem;
    display: none;
  }
  .nav-links.open { display: flex; }
  .nav-links li { width: 100%; }
  .nav-links a { display: block; padding: .85rem 0; width: 100%; border-bottom: 1px solid var(--line); }
  .nav-links li:last-child a { border-bottom: 0; }
}

/* ---------- No-script safety net ----------
   Every reveal starts from a hidden state that only JavaScript clears, so with
   scripting off the photographs would stay wiped shut and the headings stay
   behind their hems. This hands back the finished state without needing an
   inline script in each page's head. Older browsers that don't understand the
   `scripting` feature ignore the block — same exposure the site had before. */
@media (scripting: none) {
  .reveal, .stagger > * { opacity: 1; transform: none; }
  .veil .tile-figure, .veil-figure { clip-path: none; }
  .veil .tile-figure img, .veil-figure img { scale: 1; }
  .rule { transform: scaleX(1); }
  .lines > .line { overflow: visible; }
  .lines > .line > span { animation: none; }
}

/* Respect users who prefer less motion */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: .001ms !important; transition-duration: .001ms !important; }
  .reveal { opacity: 1; transform: none; }
  .stagger > * { opacity: 1; transform: none; transition-delay: 0s !important; }
  .hero-inner > * { animation: none; }
  /* The unveil is a clip and a scale, neither of which the duration override
     above reaches — without these the photographs would stay wiped shut. */
  .veil .tile-figure, .veil-figure { clip-path: none; }
  .veil .tile-figure img, .veil-figure img { scale: 1; }
  .rule { transform: scaleX(1); }
  .lines > .line > span { animation: none; }
  .lines > .line { overflow: visible; }
  /* Zeroing the duration would still let these snap to their end state. */
  .card:hover .tile-figure img { transform: none; }
  .btn--text:hover::after { transform: none; }
  .btn:active { transform: none; }
  .hero-scroll { display: none; }
  /* The universal selector above does not reach view-transition pseudo-elements,
     so the page transition has to be switched off by name. Without this it keeps
     running for someone who has asked the whole system for less motion. */
  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*) { animation: none !important; }
}

/* Print — keep it legible on paper */
@media print {
  .site-header, .site-footer, .hero-actions, .hero-scroll, .nav-toggle { display: none; }
  body { color: #000; }
}
