/* ============================================================
   ARTIST DÉCOR
   Charcoal + gold. Petrona display / Archivo body.
   Signature: "The Double-Cut" — §5.
   ------------------------------------------------------------
   1.  Tokens
   2.  Reset & base
   3.  Type primitives
   4.  Buttons, links, utilities
   5.  Media slots (placeholder system)
   6.  Masthead & mobile menu
   7.  Hero
   8.  The Double-Cut  ← signature
   9.  Painting
   10. Credibility
   11. Awards
   12. Projects
   13. Contact CTA
   14. Footer
   15. Motion setup / reduced motion
   16. Content pages (service, projects, about)
   17. Contact page
   18. Story (About) — the site's only long-form prose
   ============================================================ */


/* 1. TOKENS ------------------------------------------------- */

:root {
  /* Locked palette */
  --bg:          #14120f;
  --panel:       #1c1915;
  --gold:        #b8945f;
  --gold-bright: #d4b483;
  --cream:       #ece6da;
  --muted:       #8a8378;
  --line:        #33302a;

  /* Alpha variants of the above — no new hues */
  --gold-a12:  rgba(184, 148, 95, .12);
  --gold-a24:  rgba(184, 148, 95, .24);
  --gold-a40:  rgba(184, 148, 95, .40);
  --cream-a08: rgba(236, 230, 218, .08);
  --cream-a16: rgba(236, 230, 218, .16);
  --bg-a70:    rgba(20, 18, 15, .70);
  --bg-a92:    rgba(20, 18, 15, .92);

  /* Type */
  --ff-display: 'Petrona', 'Iowan Old Style', Georgia, serif;
  --ff-body:    'Archivo', system-ui, -apple-system, 'Segoe UI', sans-serif;

  --t-hero: clamp(2.15rem, 6.4vw, 6.4rem);
  --t-xxl:  clamp(2.2rem, 5.2vw, 4.6rem);
  --t-xl:   clamp(1.9rem, 3.6vw, 3.1rem);
  --t-lg:   clamp(1.45rem, 2.3vw, 2.1rem);
  --t-md:   clamp(1.05rem, 1.15vw, 1.2rem);
  --t-body: 1.0625rem;
  --t-sm:   .9375rem;
  --t-cap:  .6875rem;

  /* Space */
  --gutter:  clamp(1.25rem, 4.5vw, 4.5rem);
  --section: clamp(5.5rem, 12vw, 11rem);
  --wrap-max: 1520px;

  /* Shared panel geometry. The double-cut halves and the Painting panel are
     the same object at the same size, so both read these two values rather
     than each carrying its own copy. --cutGap is the visible separation
     between panels; --panelH is their height. */
  --cutGap: clamp(14px, 2vw, 30px);
  --panelH: min(88svh, 880px);

  /* Motion */
  --ease:      cubic-bezier(.22, .61, .36, 1);
  --ease-expo: cubic-bezier(.16, 1, .3, 1);
  --dur:       .55s;
}

/* Registered so the seam interpolates smoothly rather than snapping. */
@property --seamPct {
  syntax: '<percentage>';
  inherits: true;
  initial-value: 50%;
}


/* 2. RESET & BASE ------------------------------------------- */

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

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--cream);
  font-family: var(--ff-body);
  font-size: var(--t-body);
  line-height: 1.68;              /* +0.06 for light-on-dark */
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

body.is-locked { overflow: hidden; }

img, video { max-width: 100%; display: block; }

h1, h2, h3, h4 { margin: 0; font-weight: 400; }
p { margin: 0; }
ul { margin: 0; padding: 0; list-style: none; }

a { color: inherit; text-decoration: none; }

::selection { background: var(--gold); color: var(--bg); }

/* Focus — visible everywhere, never removed. */
:focus-visible {
  outline: 2px solid var(--gold-bright);
  outline-offset: 3px;
  border-radius: 2px;
}

.skip-link {
  position: fixed;
  top: .75rem; left: .75rem;
  z-index: 200;
  padding: .7rem 1.1rem;
  background: var(--gold-bright);
  color: var(--bg);
  font-size: var(--t-sm);
  font-weight: 600;
  transform: translateY(-160%);
  transition: transform .3s var(--ease);
}
.skip-link:focus { transform: translateY(0); }

.wrap {
  width: min(var(--wrap-max), 100% - var(--gutter) * 2);
  margin-inline: auto;
}

/* Vertical break between two stacked pieces inside one .block. */
.u-stack { margin-top: clamp(2rem, 3.5vw, 3rem); }

.u-visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}


/* 3. TYPE PRIMITIVES ---------------------------------------- */

.h2 {
  font-family: var(--ff-display);
  font-size: var(--t-xxl);
  line-height: 1.02;
  letter-spacing: -.015em;
  font-weight: 400;
}

.meta {
  font-size: var(--t-cap);
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--muted);
  font-weight: 500;
  line-height: 1;
}

/* Masked line reveal — used on the hero and the Double-Cut lede. */
.line {
  display: block;
  overflow: hidden;
  padding-bottom: .12em;
  margin-bottom: -.12em;
}
.line > i { display: block; font-style: inherit; }


/* 4. BUTTONS, LINKS, UTILITIES ------------------------------ */

.btn {
  display: inline-flex;
  align-items: center;
  gap: .9rem;
  padding: 1.05rem 1.9rem;
  font-size: var(--t-sm);
  font-weight: 500;
  letter-spacing: .07em;
  text-transform: uppercase;
  line-height: 1;
  border: 1px solid var(--gold);
  color: var(--gold-bright);
  background: transparent;
  position: relative;
  overflow: hidden;
  transition: color .45s var(--ease), border-color .45s var(--ease);
  will-change: color;
}
.btn::before {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--gold);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform .55s var(--ease-expo);
  z-index: 0;
}
/* The label MUST be wrapped in an element — a positioned descendant at
   z-index 0 paints after the parent's own inline text, so bare text in a
   .btn is covered by the gold fill on hover instead of sitting on it. */
.btn > * { position: relative; z-index: 1; }
.btn:hover, .btn:focus-visible { color: var(--bg); border-color: var(--gold-bright); }
.btn:hover::before, .btn:focus-visible::before { transform: scaleX(1); }
.btn:active { transform: translateY(1px); }
.btn--gold { color: var(--gold-bright); }
.btn:disabled {
  color: var(--muted);
  border-color: var(--line);
  cursor: default;
}
.btn:disabled::before { transform: scaleX(0); }

/* Text link with a rule that draws under it. */
.link-arrow {
  display: inline-flex;
  align-items: baseline;
  gap: .55rem;
  font-size: var(--t-sm);
  letter-spacing: .04em;
  color: var(--gold-bright);
  padding-bottom: .45rem;
  position: relative;
  transition: color .35s var(--ease);
}
.link-arrow::after {
  content: '';
  position: absolute;
  left: 0; bottom: 0;
  width: 100%; height: 1px;
  background: var(--gold);
  transform: scaleX(.28);
  transform-origin: left center;
  transition: transform .55s var(--ease-expo), background-color .35s var(--ease);
}
.link-arrow:hover::after,
.link-arrow:focus-visible::after { transform: scaleX(1); background: var(--gold-bright); }
.link-arrow > span { transition: transform .45s var(--ease-expo); display: inline-block; }
.link-arrow:hover > span { transform: translateX(5px); }

.section-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 1.5rem 2rem;
  padding-bottom: clamp(2.5rem, 4vw, 4rem);
  border-bottom: 1px solid var(--line);
  margin-bottom: clamp(2.5rem, 4vw, 4rem);
}


/* 5. MEDIA SLOTS -------------------------------------------- */
/* Every image/video sits in a .slot. Until the real file exists the
   slot shows a designed, on-brand material placeholder labelled with
   the exact path to drop in. site.js swaps to the real media the
   moment it loads — no edits needed, no broken-image icons. */

.slot {
  position: relative;
  display: block;
  margin: 0;
  overflow: hidden;
  background: var(--panel);
}

.slot > img,
.slot > video {
  position: relative;
  z-index: 1;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Only hide media once JS is available to detect a successful load. */
.js .slot > img,
.js .slot > video { opacity: 0; transition: opacity .9s var(--ease); }
.js .slot.is-loaded > img,
.js .slot.is-loaded > video { opacity: 1; }

/* Placeholder ground — generic hatch. */
.slot::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  background:
    repeating-linear-gradient(135deg,
      rgba(236, 230, 218, .022) 0 1px, transparent 1px 14px),
    linear-gradient(150deg, #211d18, #16130f 70%);
}

/* Placeholder label. */
.slot::after {
  content: 'Drop in — ' attr(data-slot);
  position: absolute;
  left: 1.1rem; bottom: 1rem;
  z-index: 2;
  max-width: calc(100% - 2.2rem);
  padding: .5rem .75rem;
  background: var(--bg-a70);
  border-left: 2px solid var(--gold);
  color: var(--muted);
  font-family: var(--ff-body);
  font-size: .625rem;
  letter-spacing: .12em;
  text-transform: uppercase;
  line-height: 1.35;
  transition: opacity .5s var(--ease);
  pointer-events: none;
}
.slot.is-loaded::before,
.slot.is-loaded::after { opacity: 0; }

/* Material-specific placeholders — wallpaper drops (vertical). */
.slot--paper::before {
  background:
    repeating-linear-gradient(90deg,
      rgba(236, 230, 218, .035) 0 1px, transparent 1px 52px),
    repeating-linear-gradient(0deg,
      rgba(236, 230, 218, .014) 0 1px, transparent 1px 52px),
    linear-gradient(158deg, #201c17, #15120f 72%);
}

/* Material-specific placeholders — timber grain (horizontal). */
.slot--timber::before {
  background:
    repeating-linear-gradient(178deg,
      rgba(184, 148, 95, .055) 0 2px, transparent 2px 9px),
    repeating-linear-gradient(181.5deg,
      rgba(0, 0, 0, .26) 0 1px, transparent 1px 21px),
    linear-gradient(102deg, #26201a, #191510 58%, #241e18);
}

.slot--fill { position: absolute; inset: 0; }


/* 6. MASTHEAD & MOBILE MENU --------------------------------- */

.masthead {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  gap: clamp(1rem, 3vw, 3rem);
  padding: clamp(1.1rem, 2vw, 1.9rem) var(--gutter);
  transition: background-color .5s var(--ease), border-color .5s var(--ease), padding .5s var(--ease);
  border-bottom: 1px solid transparent;
}
.masthead.is-stuck {
  background: var(--bg-a92);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border-bottom-color: var(--line);
  padding-block: clamp(.85rem, 1.3vw, 1.15rem);
}

/* The full lockup — Artist [shield] Décor, the shield centred between the
   two words — used in the masthead and the footer of every page. An SVG, so
   it is sized by height and never re-typeset. Hover shifts opacity rather
   than colour, since the gold gradient lives inside the file.
   The lockup stands far taller in proportion than a single-line wordmark,
   so it carries more height than one would to stay legible. */
.wordmark {
  display: block;
  flex: none;
  line-height: 0;
  transition: opacity .35s var(--ease);
}
.wordmark img {
  display: block;
  height: clamp(34px, 3.4vw, 46px);
  width: auto;
}
.wordmark:hover { opacity: .72; }

.nav { margin-left: auto; }
.nav ul { display: flex; gap: clamp(.9rem, 1.7vw, 1.9rem); }

/* The nav carries its own size rather than the shared caption token, which
   is tuned for labels and captions and reads too small for the primary
   navigation. It grows fluidly, 12px on the narrowest desktop up to 16px on
   a wide screen, so it gains size only where there is room for it.
   Tracking comes in from .16em, and the gap narrows slightly, to buy that
   width back: at the narrow end the row measures about what it did before,
   so a bigger nav never crowds the logo across the masthead. */
.nav a {
  font-size: clamp(.75rem, .43rem + .57vw, 1rem);
  letter-spacing: .11em;
  text-transform: uppercase;
  font-weight: 500;
  color: var(--muted);
  padding: .35rem 0;
  position: relative;
  white-space: nowrap;
  transition: color .35s var(--ease);
}
.nav a::after {
  content: '';
  position: absolute;
  left: 0; bottom: 0;
  width: 100%; height: 1px;
  background: var(--gold);
  transform: scaleX(0);
  transform-origin: right center;
  transition: transform .45s var(--ease-expo);
}
.nav a:hover, .nav a:focus-visible { color: var(--cream); }
.nav a:hover::after, .nav a:focus-visible::after { transform: scaleX(1); transform-origin: left center; }
.nav a[aria-current="page"] { color: var(--gold-bright); }
.nav a[aria-current="page"]::after { transform: scaleX(1); transform-origin: left center; }
.mobile-menu a[aria-current="page"],
.footer__nav a[aria-current="page"] { color: var(--gold-bright); }

/* Set on the same fluid ramp as .nav a: same size, same tracking,
   same weight, so the number reads as one more item in the masthead row
   rather than a smaller aside beside it. Gold and the hairline rule still
   separate it from the nav; size no longer does.
   Below 960px it is hidden with the nav, as before. */
.masthead__tel {
  font-size: clamp(.75rem, .43rem + .57vw, 1rem);
  letter-spacing: .11em;
  font-weight: 500;
  color: var(--gold);
  white-space: nowrap;
  padding-left: clamp(1rem, 2vw, 2.1rem);
  border-left: 1px solid var(--line);
  transition: color .35s var(--ease);
}
.masthead__tel:hover { color: var(--gold-bright); }

.burger {
  display: none;
  margin-left: auto;
  width: 44px; height: 44px;
  padding: 0;
  background: none;
  border: 0;
  cursor: pointer;
  color: var(--cream);
}
.burger__box { position: relative; display: block; width: 26px; height: 12px; margin: 0 auto; }
.burger__box i {
  position: absolute;
  left: 0;
  width: 100%; height: 1px;
  background: currentColor;
  transition: transform .5s var(--ease-expo), opacity .3s var(--ease);
}
.burger__box i:nth-child(1) { top: 0; }
.burger__box i:nth-child(2) { bottom: 0; }
.burger[aria-expanded="true"] .burger__box i:nth-child(1) { transform: translateY(5.5px) rotate(45deg); }
.burger[aria-expanded="true"] .burger__box i:nth-child(2) { transform: translateY(-5.5px) rotate(-45deg); }

.mobile-menu {
  position: fixed;
  inset: 0;
  z-index: 99;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 2.5rem;
  padding: 6rem var(--gutter) 3rem;
  background: var(--bg-a92);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  opacity: 0;
  visibility: hidden;
  transition: opacity .5s var(--ease), visibility .5s;
}
.mobile-menu.is-open { opacity: 1; visibility: visible; }
.mobile-menu ul { display: flex; flex-direction: column; gap: .35rem; }
.mobile-menu a {
  font-family: var(--ff-display);
  font-size: clamp(1.8rem, 8vw, 2.6rem);
  line-height: 1.25;
  letter-spacing: -.01em;
  color: var(--cream);
  display: inline-block;
  transform: translateY(1.1rem);
  opacity: 0;
  transition: transform .6s var(--ease-expo), opacity .5s var(--ease), color .3s var(--ease);
}
.mobile-menu.is-open a { transform: translateY(0); opacity: 1; }
.mobile-menu.is-open li:nth-child(1) a { transition-delay: .08s; }
.mobile-menu.is-open li:nth-child(2) a { transition-delay: .14s; }
.mobile-menu.is-open li:nth-child(3) a { transition-delay: .20s; }
.mobile-menu.is-open li:nth-child(4) a { transition-delay: .26s; }
.mobile-menu.is-open li:nth-child(5) a { transition-delay: .32s; }
.mobile-menu.is-open li:nth-child(6) a { transition-delay: .38s; }
.mobile-menu a:hover { color: var(--gold-bright); }
.mobile-menu__tel {
  font-size: var(--t-sm);
  letter-spacing: .14em;
  color: var(--gold);
  padding-top: 1.75rem;
  border-top: 1px solid var(--line);
}


/* 7. HERO --------------------------------------------------- */

.hero {
  position: relative;
  min-height: 100vh;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding-bottom: clamp(4.5rem, 9vw, 8rem);
  overflow: hidden;
  isolation: isolate;
}

.hero__media {
  position: absolute;
  inset: 0;
  z-index: -2;
  background: var(--bg);
}
/* Hero placeholder — vertical hairline rhythm, echoing wallpaper drops. */
.slot--hero::before {
  background:
    repeating-linear-gradient(90deg,
      rgba(184, 148, 95, .07) 0 1px, transparent 1px 96px),
    radial-gradient(120% 90% at 50% 32%, #241f19 0%, #17140f 58%, #100e0b 100%);
}
/* Sits mid-right, where the scrim is lightest — legible but never loud. */
.slot--hero::after { left: auto; right: 1.1rem; top: 46%; bottom: auto; }

.hero__scrim {
  position: absolute;
  inset: 0;
  z-index: -1;
  background:
    linear-gradient(to top, rgba(20,18,15,.94) 0%, rgba(20,18,15,.55) 42%, rgba(20,18,15,.32) 100%),
    linear-gradient(to right, rgba(20,18,15,.72) 0%, rgba(20,18,15,0) 62%);
}

/* Lockup centred across the hero, above the headline.
   Taken out of the flex flow: the hero anchors its copy to the bottom, and
   in-flow the lockup got pushed up under the masthead once the headline
   filled the available height. Absolute keeps it clear of both. */
.hero__logo {
  position: absolute;
  top: clamp(6.25rem, 14vh, 10rem);
  left: 0;
  right: 0;
  z-index: 1;
  display: flex;
  justify-content: center;
  padding-inline: var(--gutter);
  pointer-events: none;
}
.hero__logo img {
  height: clamp(58px, 8.5vw, 116px);
  width: auto;
  filter: drop-shadow(0 6px 26px rgba(0, 0, 0, .55));
}

/* Short laptop windows: the headline climbs as the hero compresses, so pull
   the lockup in to keep clear air between it and the first line. */
@media (min-width: 861px) and (max-height: 820px) {
  .hero__logo { top: 6.5rem; }
  .hero__logo img { height: clamp(42px, 6.5vh, 78px); }
}

.hero__inner { position: relative; max-width: 62rem; }

.hero__rule {
  display: block;
  width: 1px;
  height: clamp(3rem, 6vw, 5.5rem);
  background: linear-gradient(to bottom, transparent, var(--gold));
  margin-bottom: clamp(1.5rem, 2.5vw, 2.5rem);
  transform-origin: top center;
}

.hero__title {
  font-family: var(--ff-display);
  font-size: var(--t-hero);
  font-weight: 400;
  line-height: 1.03;
  letter-spacing: -.022em;
  color: var(--cream);
  text-wrap: balance;
}

.hero__sub {
  max-width: 34rem;
  margin-top: clamp(1.4rem, 2.2vw, 2.1rem);
  font-size: var(--t-md);
  line-height: 1.62;
  color: var(--muted);
}

.hero__cta { margin-top: clamp(2rem, 3.2vw, 3rem); }

.hero__cue {
  position: absolute;
  right: var(--gutter);
  bottom: clamp(2rem, 4vw, 3rem);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .85rem;
  font-size: var(--t-cap);
  letter-spacing: .24em;
  text-transform: uppercase;
  color: var(--muted);
  writing-mode: vertical-rl;
  transition: color .35s var(--ease);
}
.hero__cue:hover { color: var(--gold-bright); }
.hero__cue-line {
  display: block;
  width: 1px;
  height: 62px;
  background: var(--line);
  position: relative;
  overflow: hidden;
}
.hero__cue-line::after {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--gold);
  transform: translateY(-100%);
  animation: cue 2.6s var(--ease) infinite;
}
@keyframes cue {
  0%   { transform: translateY(-100%); }
  55%  { transform: translateY(0); }
  100% { transform: translateY(100%); }
}


/* 8. THE DOUBLE-CUT — signature ----------------------------- */

.cut { padding-block: var(--section) 0; position: relative; }

.cut__intro { padding-bottom: clamp(3rem, 6vw, 5.5rem); }

.cut__lede {
  font-family: var(--ff-display);
  font-size: var(--t-xl);
  font-weight: 400;
  line-height: 1.14;
  letter-spacing: -.015em;
  max-width: 30ch;
  color: var(--cream);
}
.cut__lede > span { display: block; }
.cut__lede em { font-style: italic; color: var(--cream); }
.cut__lede b { font-weight: 400; color: var(--gold-bright); }

.cut__stage {
  --seamPct: 50%;
  /* --cutGap (:root) is the visible separation between the two panels. The
     halves are pulled back by half this each, so the gap stays centred on the
     seam wherever it travels. */
  position: relative;
  min-height: var(--panelH);
  isolation: isolate;
}

.cut__plane { position: absolute; inset: 0; z-index: 0; }

.cut__half { position: absolute; inset: 0; }

.cut__half--paper  { clip-path: inset(0 calc(100% - var(--seamPct) + var(--cutGap) / 2) 0 0); }
.cut__half--timber { clip-path: inset(0 0 0 calc(var(--seamPct) + var(--cutGap) / 2)); }

/* Legibility scrims sitting over each material, under the copy. */
.cut__half--paper::after,
.cut__half--timber::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 3;
  pointer-events: none;
}
.cut__half--paper::after {
  background: linear-gradient(to right, rgba(20,18,15,.88) 0%, rgba(20,18,15,.30) 46%, rgba(20,18,15,.05) 100%);
}
.cut__half--timber::after {
  background: linear-gradient(to left, rgba(20,18,15,.88) 0%, rgba(20,18,15,.30) 46%, rgba(20,18,15,.05) 100%);
}

/* Hover preview video.
   Deliberately NOT a child of .slot, so the placeholder system's
   opacity rules don't fight it. Layers above the photo (z-index 2) and
   below the legibility scrim (z-index 3), so the copy stays readable.
   Shown only on a fine pointer — see initCutPreviews() in site.js. */
/* The halves are full-stage elements that are *clipped* to their panel, so a
   video at inset:0 was being fitted to the whole stage width — a 9:16 clip
   blown up to 1440px wide showed ~28% of the frame, which is what read as a
   zoom-in. Each video is instead bounded to its own visible panel and set to
   `contain`, so it plays whole, at its natural aspect, centred in the panel.
   No transform is applied anywhere here; the only transition is opacity. */
.cut__video {
  position: absolute;
  top: 0;
  bottom: 0;
  z-index: 2;
  height: 100%;
  object-fit: contain;
  background: var(--bg);
  opacity: 0;
  transition: opacity .4s var(--ease);
  pointer-events: none;
}
/* Width is set explicitly, not via left+right: on a replaced element an auto
   width resolves to the intrinsic aspect ratio, not to the offset box. */
.cut__half--paper .cut__video {
  left: 0;
  width: calc(var(--seamPct) - var(--cutGap) / 2);
}
.cut__half--timber .cut__video {
  left: calc(var(--seamPct) + var(--cutGap) / 2);
  width: calc(100% - var(--seamPct) - var(--cutGap) / 2);
}
.cut__half.is-preview .cut__video { opacity: 1; }
.cut__half.is-preview .cut__video { opacity: 1; }

/* Never on touch layouts or under reduced motion — the photo stands alone. */
@media (max-width: 860px) {
  .cut__video { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .cut__video { display: none; }
}

/* The seam — the double-cut join. */
.cut__seam {
  position: absolute;
  top: 0; bottom: 0;
  left: var(--seamPct);
  z-index: 4;
  width: 1px;
  background: var(--gold);
  box-shadow: 0 0 26px 1px var(--gold-a40);
  pointer-events: none;
}
.cut__seam::before,
.cut__seam::after {
  content: '';
  position: absolute;
  left: 50%;
  width: 3px;
  height: 30px;
  margin-left: -1.5px;
  background: var(--gold-bright);
}
.cut__seam::before { top: calc(50% - 42px); }
.cut__seam::after  { top: calc(50% + 12px); }

.cut__cards {
  position: relative;
  z-index: 5;
  height: 100%;
  min-height: inherit;
  display: grid;
  /* Card columns stay clear of the seam's full travel (66% → 34%).
     32% is the widest they can run and still clear the seam at its
     innermost — the service copy needs the measure. */
  grid-template-columns: minmax(0, 32%) 1fr minmax(0, 32%);
  align-items: center;
  padding: clamp(2.5rem, 5vw, 5rem) var(--gutter);
  gap: 2rem;
  min-height: min(88svh, 880px);
}

.cut__card { max-width: 30rem; }
.cut__card--left  { grid-column: 1; align-self: end; }
.cut__card--right { grid-column: 3; align-self: start; }

.cut__title {
  font-family: var(--ff-display);
  font-size: var(--t-lg);
  line-height: 1.08;
  letter-spacing: -.01em;
  color: var(--cream);
  margin-bottom: .85rem;
}
.cut__body {
  color: var(--muted);
  font-size: var(--t-sm);
  line-height: 1.72;
  margin-bottom: 1.5rem;
  max-width: 46ch;
}

/* Trade-credibility line. A second register beneath a service
   description — italic display face, gold, over a gold hairline — so it
   reads as a credential being cited rather than more body copy.
   Shared by the Double-Cut cards and the Painting panel. */
.cred-line {
  margin-top: 1.3rem;
  margin-bottom: 1.6rem;
  padding-top: 1.15rem;
  border-top: 1px solid var(--gold-a40);
  font-family: var(--ff-display);
  font-style: italic;
  font-size: var(--t-md);
  line-height: 1.45;
  color: var(--gold-bright);
  max-width: 42ch;
}


/* 9. PAINTING ----------------------------------------------- */

.painting {
  background: var(--panel);
  border-block: 1px solid var(--line);
  padding-block: var(--section);
}
/* Two equal columns separated by --cutGap, so the media column resolves to
   calc((100% - var(--cutGap)) / 2) — the exact width of a double-cut half at
   its 50/50 rest position. */
.painting__grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--cutGap);
  align-items: center;
  /* The copy column carries the page gutter on the left; this carries the
     same gutter on the right, so the media panel stops the same distance
     from the right edge as the copy starts from the left. Mirrored margins
     across the panel. Removed once the grid stacks (<=1000px), where the
     media goes full-bleed again. */
  padding-inline-end: var(--gutter);
}
/* The grid is full-bleed, so the copy carries the page gutter itself. */
.painting__text {
  max-width: 38rem;
  padding-inline-start: var(--gutter);
}
.painting__text .meta { display: block; margin-bottom: 1.2rem; }
.painting__text .h2 { font-size: var(--t-xl); margin-bottom: 1.3rem; }
.painting__body {
  color: var(--muted);
  font-size: var(--t-md);
  line-height: 1.7;
  margin-bottom: 1.9rem;
  max-width: 46ch;
}
/* The panel is a fixed box: its height is --panelH and its width is its grid
   column, both matching a double-cut half. Nothing inside it participates in
   layout — the photo and the video are both absolutely positioned and fill it
   edge to edge — so the panel cannot resize when the video swaps in.
   No border: a cut half has none, and the two must read identically. */
.painting__frame {
  position: relative;
  isolation: isolate;
  height: var(--panelH);
  overflow: hidden;
}
.painting__media { position: absolute; inset: 0; }

/* Hover preview video.
   `cover`, matching `.slot > img` — the photo is a 3:2 frame filling a taller
   panel, so it is already centre-cropped to fit. The video is handled by the
   identical rule, which is what makes the swap seamless: same box, same fit,
   same crop behaviour. `contain` was the bug — it fitted the 16:9 clip inside
   a taller panel and painted the shortfall as bars.
   Shown only on a fine pointer — see initPaintingPreview() in site.js. */
.painting__video {
  position: absolute;
  inset: 0;
  z-index: 2;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity .4s var(--ease);
  pointer-events: none;
}
.painting__frame.is-preview .painting__video { opacity: 1; }

/* Never on touch layouts or under reduced motion — the photo stands alone. */
@media (max-width: 860px) {
  .painting__video { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .painting__video { display: none; }
}


/* 10. CREDIBILITY ------------------------------------------- */

.cred { padding-block: clamp(3.5rem, 7vw, 6rem); }
/* Five cells of one track each — no spans, so every cell is the same
   width, and grid stretch already makes them the same height. Five is
   prime: it divides evenly into 5 tracks or 1, and nothing between. Any
   other track count leaves an empty cell, which in this grid reads as a
   solid block of --line rather than as whitespace. So the strip goes
   straight from five-up to stacked, with no intermediate step. */
.cred__grid {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
}
.cred__item {
  background: var(--bg);
  padding: clamp(1.5rem, 2.2vw, 2.25rem);
}
.cred__lead {
  font-family: var(--ff-display);
  /* A step under --t-lg: five narrower cells instead of four, and every
     lead has to hold its line without hyphenating. */
  font-size: clamp(1.3rem, 1.7vw, 1.75rem);
  line-height: 1.1;
  color: var(--gold-bright);
  margin-bottom: .6rem;
}
.cred__note {
  display: block;
  font-size: var(--t-sm);
  line-height: 1.62;
  color: var(--muted);
  max-width: 24ch;
}
.cred__lead { display: block; }

/* Badge variant — trust mark under the text rather than beside it. Beside
   it needed a wider cell, and the cells are all one width now. So the type
   starts on the same line as every other cell and the mark sits in the
   space below it, which the taller cells in the row would leave empty
   anyway. If the image is missing its onerror strips the badge, and the
   cell falls back to reading exactly like every other one. */
.cred__item--badge {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: clamp(1rem, 1.6vw, 1.5rem);
}
.cred__badge { flex: none; line-height: 0; margin-top: auto; }
.cred__badge img {
  display: block;
  width: clamp(52px, 4.6vw, 68px);
  height: auto;
}
.cred__badge-text { min-width: 0; }


/* 11. AWARDS ------------------------------------------------ */
/* A vertical record, one full-width row per award, oldest at the top.
   The list grows downward: adding an award is one more .award-row on the
   end, and nothing above it changes. Prominence is controlled by
   data-awards on the <section>: "on" gives the gold-topped panel,
   "off" a quiet band. */

.awards { padding-block: clamp(3rem, 6vw, 5rem); }
.awards__title {
  font-family: var(--ff-display);
  letter-spacing: -.01em;
  color: var(--cream);
}
.awards__head { margin-bottom: 1.75rem; }

.awards__list { display: flex; flex-direction: column; }

/* One row per award. Three parts across the width: the seal, the award
   itself, and the work it was won for pushed to the far edge - so the
   row reads left to right as what, from whom, and where to see it.
   A hairline under each row is the only division; the rule under the last
   row closes the list off, so it never trails into the panel. */
.award-row {
  display: flex;
  align-items: center;
  gap: clamp(1.25rem, 2.6vw, 2.5rem);
  padding-block: clamp(1.6rem, 2.8vw, 2.4rem);
  border-bottom: 1px solid var(--line);
  transition: border-color .45s var(--ease);
}
.award-row:hover,
.award-row:focus-visible { border-bottom-color: var(--gold-a40); }

/* `flex: none` keeps the seal circular however long the text beside it
   runs. It is the tallest thing in the row, so it sets the row's height
   and can never be cramped by the type. */
.award-row__seal {
  flex: none;
  width: clamp(72px, 7.6vw, 112px);
  height: auto;
  filter: drop-shadow(0 8px 24px rgba(0, 0, 0, .55));
}

.award-row__text {
  display: flex;
  flex-direction: column;
  gap: .4rem;
  min-width: 0;
}
.award-row__name {
  font-family: var(--ff-display);
  font-size: var(--t-lg);
  line-height: 1.15;
  letter-spacing: -.01em;
  color: var(--cream);
}
.award-row__body {
  font-size: var(--t-sm);
  line-height: 1.5;
  color: var(--muted);
}

/* Held at the right edge, so every row ends in the same place and the
   list reads as a column of links rather than ragged text. */
.award-row__cta {
  margin-left: auto;
  flex: none;
  display: inline-flex;
  align-items: baseline;
  gap: .55rem;
  font-size: var(--t-sm);
  letter-spacing: .04em;
  color: var(--gold-bright);
}
.award-row__cta > span { transition: transform .45s var(--ease-expo); }
.award-row:hover .award-row__cta > span,
.award-row:focus-visible .award-row__cta > span { transform: translateX(5px); }

/* --- Quiet state --- */
.awards[data-awards="off"] { border-top: 1px solid var(--line); }
.awards[data-awards="off"] .awards__title { font-size: var(--t-lg); }
.awards[data-awards="off"] .award-row__seal { width: clamp(56px, 5.5vw, 76px); }
.awards[data-awards="off"] .award-row__name { font-size: var(--t-md); }

/* --- Switched on: after the 2026 Christchurch result --- */
.awards[data-awards="on"] {
  background: var(--panel);
  border-block: 1px solid var(--line);
  border-top: 2px solid var(--gold);
  padding-block: var(--section);
}
.awards[data-awards="on"] .awards__head {
  margin-bottom: clamp(2.5rem, 4vw, 3.5rem);
  padding-bottom: clamp(2rem, 3vw, 2.75rem);
  border-bottom: 1px solid var(--line);
}
.awards[data-awards="on"] .awards__title { font-size: var(--t-xxl); }

/* Below this the row has no width left to hold the link out at the edge,
   so it drops under the award text and the row becomes seal + block. */
@media (max-width: 760px) {
  .award-row { align-items: center; }
  .award-row__cta {
    margin-left: 0;
    order: 3;
    width: 100%;
    padding-left: calc(clamp(72px, 7.6vw, 112px) + clamp(1.25rem, 2.6vw, 2.5rem));
    margin-top: .85rem;
  }
  .award-row { flex-wrap: wrap; }
}
@media (max-width: 460px) {
  .award-row__cta { padding-left: 0; }
}


/* 12. PROJECTS ---------------------------------------------- */

.projects { padding-block: var(--section); }

.tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
  gap: clamp(1.25rem, 2.4vw, 2.25rem);
}

.tile__link { display: block; }
.tile__media {
  aspect-ratio: 4 / 5;
  border: 1px solid var(--line);
  transition: border-color .5s var(--ease);
}
.tile__media > img { transition: transform 1.1s var(--ease-expo), opacity .9s var(--ease); }
.tile__link:hover .tile__media > img,
.tile__link:focus-visible .tile__media > img { transform: scale(1.045); }
.tile__link:hover .tile__media,
.tile__link:focus-visible .tile__media { border-color: var(--gold-a40); }

.tile__foot { padding-top: 1.35rem; }
.tile__tag {
  font-size: var(--t-cap);
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--gold);
  margin-bottom: .7rem;
}
.tile__title {
  font-family: var(--ff-display);
  font-size: var(--t-lg);
  line-height: 1.14;
  color: var(--cream);
  margin-bottom: .45rem;
  display: inline-block;
  position: relative;
}
.tile__title::after {
  content: '';
  position: absolute;
  left: 0; bottom: -3px;
  width: 100%; height: 1px;
  background: var(--gold);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform .6s var(--ease-expo);
}
.tile__link:hover .tile__title::after,
.tile__link:focus-visible .tile__title::after { transform: scaleX(1); }
.tile__note { color: var(--muted); font-size: var(--t-sm); line-height: 1.6; }


/* 13. CONTACT CTA ------------------------------------------- */

.cta {
  background: var(--panel);
  border-top: 1px solid var(--line);
  padding-block: var(--section);
}
.cta__inner { max-width: 56rem; }
.cta__title {
  font-family: var(--ff-display);
  font-size: var(--t-xxl);
  line-height: 1.04;
  letter-spacing: -.02em;
  color: var(--cream);
  text-wrap: balance;
}
.cta__sub {
  margin-top: 1.3rem;
  font-size: var(--t-md);
  color: var(--muted);
  max-width: 36ch;
}
.cta__btn { margin-top: clamp(2rem, 3vw, 2.75rem); }

.cta__details {
  display: flex;
  flex-wrap: wrap;
  gap: 1.75rem clamp(2rem, 5vw, 4.5rem);
  margin-top: clamp(3rem, 5vw, 4.5rem);
  padding-top: clamp(2rem, 3vw, 2.75rem);
  border-top: 1px solid var(--line);
}
.cta__details li { display: flex; flex-direction: column; gap: .55rem; }
.cta__details a, .cta__details span:last-child {
  font-size: var(--t-md);
  color: var(--cream);
  transition: color .35s var(--ease);
}
.cta__details a:hover { color: var(--gold-bright); }


/* 13b. STUB PAGES ------------------------------------------- */
/* No page uses this any more — every section is built. Kept so a new
   section can be stubbed into the nav and stay walkable while it is
   being written. */

.stub {
  min-height: 74vh;
  min-height: 74svh;
  display: flex;
  align-items: center;
  padding-block: clamp(9rem, 16vw, 14rem) var(--section);
  border-bottom: 1px solid var(--line);
}
.stub__inner { max-width: 44rem; }
.stub__inner .meta { display: block; margin-bottom: 1.4rem; }
.stub__title {
  font-family: var(--ff-display);
  font-size: var(--t-xxl);
  line-height: 1.02;
  letter-spacing: -.02em;
  color: var(--cream);
  padding-bottom: clamp(1.5rem, 2.5vw, 2.25rem);
  border-bottom: 1px solid var(--line);
  margin-bottom: clamp(1.5rem, 2.5vw, 2.25rem);
}
.stub__note {
  color: var(--muted);
  font-size: var(--t-md);
  line-height: 1.7;
  max-width: 46ch;
  margin-bottom: 2rem;
}


/* 14. FOOTER ------------------------------------------------ */

.footer {
  border-top: 1px solid var(--line);
  padding-block: clamp(2.75rem, 5vw, 4rem);
}
.footer__grid {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1.75rem 2.5rem;
}
/* Same lockup as the masthead, a step down in size — it signs the page off
   rather than heading it. */
.wordmark--foot img { height: clamp(30px, 2.8vw, 38px); }
.footer__nav ul { display: flex; flex-wrap: wrap; gap: .75rem 1.75rem; }
.footer__nav a {
  font-size: var(--t-cap);
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--muted);
  transition: color .35s var(--ease);
}
.footer__nav a:hover { color: var(--gold-bright); }
.footer__legal {
  font-size: var(--t-cap);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--muted);
}
.footer__legal a {
  color: var(--muted);
  border-bottom: 1px solid var(--line);
  padding-bottom: .15rem;
  transition: color .35s var(--ease), border-color .35s var(--ease);
}
.footer__legal a:hover,
.footer__legal a:focus-visible { color: var(--gold-bright); border-bottom-color: var(--gold-a40); }
.footer__legal a[aria-current="page"] { color: var(--gold-bright); }

/* Social. Icons are inline SVG rather than a font or a CDN sprite —
   nothing on this site loads from a third party except the typefaces. */
.social { display: flex; align-items: center; gap: .75rem; }
.social a {
  display: grid;
  place-items: center;
  width: 40px; height: 40px;
  border: 1px solid var(--line);
  color: var(--muted);
  transition: color .35s var(--ease), border-color .35s var(--ease);
}
.social a:hover,
.social a:focus-visible { color: var(--gold-bright); border-color: var(--gold-a40); }
.social svg { display: block; width: 17px; height: 17px; }


/* 15. MOTION SETUP ------------------------------------------ */
/* Pre-animation states apply only on pages that opt in with .anim, and
   only when the visitor has not asked for reduced motion. Pages without
   .anim (the inner pages) never hide anything. */

.anim:not(.rm) [data-reveal] { opacity: 0; }
.anim:not(.rm) .hero__logo { opacity: 0; }
.anim:not(.rm) .hero__title .line > i { transform: translateY(112%); }
.anim:not(.rm) .hero__sub,
.anim:not(.rm) .hero__cta,
.anim:not(.rm) .hero__cue { opacity: 0; }
.anim:not(.rm) .hero__rule { transform: scaleY(0); }
.anim:not(.rm) .masthead { opacity: 0; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .hero__cue-line::after { animation: none; transform: translateY(0); }
  .btn::before,
  .link-arrow::after,
  .nav a::after,
  .tile__title::after { transition-duration: .01ms; }
}


/* RESPONSIVE ------------------------------------------------ */

@media (max-width: 1180px) {
  .nav ul { gap: 1.1rem; }
  .cut__cards { grid-template-columns: minmax(0, 33%) 1fr minmax(0, 33%); }
}

@media (max-width: 1000px) {
  /* Five-up gets too narrow to set the leads on one line below this, and
     five cells have no even arrangement between 5 and 1 — so they stack. */
  .cred__grid { grid-template-columns: 1fr; }
  .painting__grid { grid-template-columns: 1fr; padding-inline-end: 0; }
  .painting__text { padding-inline: var(--gutter); }
  /* Stacked: the panel is full width, so it shortens rather than keeping the
     tall two-column proportion. Still a fixed box — photo and video both
     fill it, so the swap stays seamless. */
  .painting__frame { height: min(60svh, 30rem); }
  .painting__body { max-width: 46ch; }
}

/* The masthead swaps to the burger on its own breakpoint, wider than the
   860px the rest of the layout uses. Six uppercase nav items plus the phone
   number and the logo need about 960px to sit on one line; below that the
   row ran into the logo. That was true before the nav was enlarged — the old
   nav measured over the viewport at 861px too — so this fixes the crowding
   rather than just making room for the bigger type. */
@media (max-width: 959px) {
  .nav, .masthead__tel { display: none; }
  .burger { display: block; }
}

@media (max-width: 860px) {
  /* Double-Cut on small screens: the plane and the copy wrappers become
     display:contents so all five pieces sit in one column and can be
     interleaved — material, its copy, the seam, material, its copy. */
  .cut__stage {
    --seamPct: 50%;
    display: grid;
    grid-template-columns: 1fr;
    min-height: 0;
  }
  .cut__plane, .cut__cards { display: contents; }

  /* With the wrappers set to display:contents, all five pieces become grid
     items of .cut__stage. The desktop placement (grid-column: 3 on the
     right-hand card) would spawn implicit columns and lay the section out
     side by side, so pin everything back to the single column. */
  .cut__half, .cut__seam, .cut__card {
    grid-column: 1;
    align-self: auto;
  }

  .cut__half {
    position: relative;
    inset: auto;
    clip-path: none !important;
    height: 62vw;
    min-height: 290px;
  }
  /* Stacked: the gap becomes vertical breathing room around the seam. */
  .cut__half--paper  { order: 1; margin-bottom: var(--cutGap); }
  .cut__half--timber { order: 4; margin-top: var(--cutGap); }
  .cut__half--paper::after,
  .cut__half--timber::after {
    background: linear-gradient(to top, rgba(20,18,15,.86) 0%, rgba(20,18,15,.12) 62%);
  }

  .cut__seam {
    order: 3;
    position: relative;
    top: auto; bottom: auto; left: auto;
    width: 100%; height: 1px;
    box-shadow: 0 0 18px 1px var(--gold-a40);
  }
  .cut__seam::before, .cut__seam::after {
    width: 34px; height: 3px;
    top: -1px; margin-left: 0;
  }
  .cut__seam::before { left: auto; right: calc(50% + 14px); }
  .cut__seam::after  { left: calc(50% + 14px); }

  .cut__card {
    max-width: none;
    padding: clamp(2rem, 7vw, 3rem) var(--gutter);
  }
  .cut__card--left  { order: 2; }
  .cut__card--right { order: 5; }
  .cut__body { max-width: 46ch; }

  .hero__cue { display: none; }
  .hero__sub { max-width: 46ch; }
}

@media (max-width: 860px) {
}

@media (max-width: 620px) {
  .award { grid-template-columns: 1fr; gap: .5rem; }
  .awards[data-awards="on"] .award { grid-template-columns: 1fr; }
  .cta__details { gap: 1.5rem 2rem; }
  .footer__grid { flex-direction: column; align-items: flex-start; }
}


/* 16. CONTENT PAGES ----------------------------------------- */
/* Service pages, project case studies and About. Photographs run at
   their own aspect ratio here rather than being cropped to a grid —
   every img carries width/height so nothing shifts as they load. */

.page-head {
  padding-block: clamp(8rem, 14vw, 11.5rem) clamp(2.5rem, 4vw, 4rem);
  border-bottom: 1px solid var(--line);
}
.page-head__inner { max-width: 54rem; }
.page-head .meta { display: block; margin-bottom: 1.4rem; }
.page-head__title {
  font-family: var(--ff-display);
  font-size: var(--t-xxl);
  line-height: 1.02;
  letter-spacing: -.02em;
  color: var(--cream);
}
.page-head__note {
  margin-top: clamp(1.25rem, 2vw, 1.9rem);
  color: var(--muted);
  font-size: var(--t-md);
  line-height: 1.7;
  max-width: 54ch;
}

/* Page hero with video ---------------------------------------- */
/* The wallpapering clip is phone-shot 9:16. A full-bleed 16:9 hero would
   crop the wall away entirely, so the video sits in a portrait panel at
   its own ratio and is never cropped. */

.phero {
  padding-block: clamp(7.5rem, 13vw, 11rem) clamp(3rem, 5vw, 4.5rem);
  border-bottom: 1px solid var(--line);
}
.phero__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: clamp(2rem, 5vw, 5rem);
  align-items: center;
}
.phero__text { max-width: 34rem; }
.phero__text .meta { display: block; margin-bottom: 1.4rem; }
.phero__title {
  font-family: var(--ff-display);
  font-size: var(--t-xxl);
  line-height: 1.02;
  letter-spacing: -.02em;
  color: var(--cream);
}
.phero__note {
  margin-top: clamp(1.25rem, 2vw, 1.9rem);
  color: var(--muted);
  font-size: var(--t-md);
  line-height: 1.7;
  max-width: 46ch;
}

.phero__media {
  height: min(76svh, 700px);
  aspect-ratio: 9 / 16;
  width: auto;
  border: 1px solid var(--line);
}

/* 16:9 source (the timber clip) — panel matches it so nothing is cropped. */
.phero__media--wide {
  height: min(48svh, 430px);
  aspect-ratio: 16 / 9;
}
/* Sound toggle over the hero video. The clip autoplays muted because
   browsers refuse sound without a gesture; this is the gesture. */
.phero__sound {
  position: absolute;
  right: .9rem;
  bottom: .9rem;
  z-index: 3;
  display: inline-flex;
  align-items: center;
  gap: .6rem;
  padding: .75rem 1.05rem;
  background: var(--bg-a92);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border: 1px solid var(--gold-a40);
  color: var(--gold-bright);
  font-family: var(--ff-body);
  font-size: var(--t-cap);
  font-weight: 500;
  letter-spacing: .14em;
  text-transform: uppercase;
  line-height: 1;
  cursor: pointer;
  transition: border-color .35s var(--ease), color .35s var(--ease);
}
.phero__sound:hover { border-color: var(--gold-bright); color: var(--cream); }
.phero__sound-icon {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: currentColor;
  opacity: .4;
  transition: opacity .35s var(--ease), box-shadow .35s var(--ease);
}
.phero__sound.is-on .phero__sound-icon {
  opacity: 1;
  box-shadow: 0 0 0 4px var(--gold-a24);
}

@media (max-width: 860px) {
  .phero__grid { grid-template-columns: 1fr; }
  .phero__media {
    height: auto;
    width: 100%;
    aspect-ratio: 9 / 16;
    max-height: 74svh;
  }
  .phero__media--wide { aspect-ratio: 16 / 9; max-height: none; }
}

.block { padding-block: clamp(3.5rem, 7vw, 6rem); }
.block + .block { border-top: 1px solid var(--line); }

.block__head { margin-bottom: clamp(2rem, 3.5vw, 3rem); max-width: 54rem; }
.block__head .meta { display: block; margin-bottom: 1.1rem; }
.block__title {
  font-family: var(--ff-display);
  font-size: var(--t-xl);
  line-height: 1.06;
  letter-spacing: -.015em;
  color: var(--cream);
}
.block__note {
  margin-top: 1.1rem;
  color: var(--muted);
  font-size: var(--t-sm);
  line-height: 1.72;
  max-width: 56ch;
}

/* Definitions ------------------------------------------------ */
/* Two terms set side by side — used for stain vs varnish, where the
   whole point is that they are different things. Same cell structure
   as the credibility strip, so it needs no new visual language. */

/* auto-fit rather than a fixed count: empty tracks collapse, so the same
   rule lays out the two timber finishes and the three paper types. */
.defs {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr));
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
}
.def {
  background: var(--bg);
  padding: clamp(1.75rem, 3vw, 2.75rem);
}
.def__term {
  font-family: var(--ff-display);
  font-size: var(--t-lg);
  line-height: 1.1;
  color: var(--gold-bright);
  margin-bottom: .8rem;
}
.def__body {
  font-size: var(--t-sm);
  line-height: 1.7;
  color: var(--muted);
  max-width: 42ch;
}

@media (max-width: 620px) {
  .defs { grid-template-columns: 1fr; }
}


/* Gallery ---------------------------------------------------- */

.gallery {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  align-items: start;
  gap: clamp(1.25rem, 2.4vw, 2.25rem);
}

.shot { margin: 0; display: block; }
.shot--wide { grid-column: 1 / -1; }

.shot__media {
  border: 1px solid var(--line);
  transition: border-color .5s var(--ease);
}
/* Natural height: overrides the cropping behaviour of the base .slot. */
.shot__media > img {
  width: 100%;
  height: auto;
  object-fit: initial;
}
.shot:hover .shot__media { border-color: var(--gold-a24); }

/* Uniform set: the lead frame keeps its own proportions as the big
   impression shot; every other frame is normalised to one ratio so the
   gallery reads as a consistent grid rather than a ragged column.
   `.pair--uniform` applies the same ratio to a before/after pair, where
   matching frames also let the two states be compared directly.
   A pair of portrait photos would be gutted by a 4:3 crop, so the
   orientation rules below deliberately follow this block and override it
   wherever a frame carries `.shot--land` / `.shot--port`. Keep them in that
   order — the two selectors tie on specificity, so source order decides. */
.gallery--uniform .shot:not(.shot--wide) .shot__media,
.pair--uniform .shot__media { aspect-ratio: 4 / 3; }
.gallery--uniform .shot:not(.shot--wide) .shot__media > img,
.pair--uniform .shot__media > img {
  height: 100%;
  object-fit: cover;
}

/* Orientation set: landscape frames share one ratio and portrait frames
   another, so a mixed gallery reads as two consistent families rather than
   a different shape in every cell. Each ratio is the commonest shape in its
   family, which keeps the crop off most frames to nothing. */
.shot--land .shot__media { aspect-ratio: 4 / 3; }
.shot--port .shot__media { aspect-ratio: 4 / 5; }
.shot--land .shot__media > img,
.shot--port .shot__media > img {
  height: 100%;
  object-fit: cover;
}

/* Full-width video frame inside a gallery. 16:9 matches the source, so the
   picture is never cropped. */
.shot__media--video { aspect-ratio: 16 / 9; }

/* Award badge over a project photo. Drops into any .slot, which is already
   position:relative and clips to its frame. Wrapped in a span rather than
   sitting as a bare <img>, so the `.slot > img` and orientation rules that
   stretch a photo to fill its frame never reach it.
   The inset is a fixed length, not a percentage — a percentage top resolves
   against the frame's height, which would sit the badge lower on a portrait
   than on a landscape. The width stays proportional so it reads at the same
   scale on every photo. */
.award-badge {
  position: absolute;
  top: clamp(.55rem, 1.6vw, 1.05rem);
  left: clamp(.55rem, 1.6vw, 1.05rem);
  z-index: 3;
  width: clamp(46px, 15%, 84px);
  line-height: 0;
  pointer-events: none;
  filter: drop-shadow(0 4px 14px rgba(0, 0, 0, .5));
}
.award-badge img { display: block; width: 100%; height: auto; }

.shot__cap {
  padding-top: .9rem;
  font-size: var(--t-sm);
  line-height: 1.6;
  color: var(--muted);
}
.shot__cap b {
  display: block;
  font-weight: 400;
  color: var(--cream);
  margin-bottom: .15rem;
}

/* Before / after pair ---------------------------------------- */

.pair {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(1.25rem, 2.4vw, 2.25rem);
  align-items: start;
}
.pair .shot__cap b::before {
  content: '';
  display: inline-block;
  width: 1.35rem;
  height: 1px;
  margin-right: .6rem;
  vertical-align: middle;
  background: var(--gold);
}

/* Documents (certificates) ----------------------------------- */

.docs {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 230px), 1fr));
  gap: clamp(1.25rem, 2.4vw, 2rem);
  align-items: start;
}
.docs .shot__media { background: var(--panel); }

/* 17. CONTACT PAGE ------------------------------------------- */
/* The form is the page. Fields are underlined rather than boxed —
   boxes would put nine hard rectangles on a page that has none
   anywhere else. The gold rule that draws under a focused field is
   the same move already used on .link-arrow and the nav, so the
   page gains a signature without inventing a new one. */

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

.contact__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) minmax(0, .6fr);
  gap: clamp(2.5rem, 6vw, 6rem);
  align-items: start;
}

/* Form ------------------------------------------------------- */

/* Capped rather than filling its column. On a wide screen the column
   runs to ~950px, and an underlined field that long reads as a stray
   hairline instead of an input. */
.form { max-width: 48rem; }

.form__head { margin-bottom: clamp(2.25rem, 4vw, 3.25rem); }
.form__head .meta { display: block; margin-bottom: 1.1rem; }

.field { position: relative; display: block; }

/* One rhythm for every block in the form, whatever it is — a field, a
   paired row, the fieldset. Spacing each type separately breaks the
   moment two unlike blocks sit next to each other. */
.form__body > * + * { margin-top: clamp(1.9rem, 3vw, 2.6rem); }

/* Two short fields share a row where there is width for it. */
.field-row {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(1.9rem, 3vw, 2.6rem);
}

.field__label { display: block; margin-bottom: .85rem; transition: color .35s var(--ease); }
.field:focus-within .field__label { color: var(--gold-bright); }
.field__opt { text-transform: none; letter-spacing: .04em; color: #5f5a52; }

.field__input {
  display: block;
  width: 100%;
  padding: .1rem 0 .95rem;
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--line);
  border-radius: 0;
  color: var(--cream);
  font-family: var(--ff-body);
  font-size: var(--t-md);
  line-height: 1.5;
  transition: border-color .35s var(--ease);
}
.field__input::placeholder { color: #5f5a52; }
.field__input:focus { outline: none; }
textarea.field__input { resize: vertical; min-height: 9.5rem; }

/* The drawn rule *is* the focus indicator — full width, gold, on a
   page where nothing else moves. Forced-colours mode can't render it,
   so the native outline comes back there. */
.field__rule {
  position: absolute;
  left: 0; bottom: 0;
  width: 100%; height: 1px;
  background: var(--gold);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform .55s var(--ease-expo), background-color .35s var(--ease);
  pointer-events: none;
}
.field__input:focus ~ .field__rule { transform: scaleX(1); }
.field__input:not(:placeholder-shown) ~ .field__rule {
  transform: scaleX(1);
  background: var(--gold-a40);
}
.field__input:focus:not(:placeholder-shown) ~ .field__rule { background: var(--gold); }

@media (forced-colors: active) {
  .field__input:focus { outline: 2px solid Highlight; outline-offset: 2px; }
}

/* Invalid state. The palette holds no red, so the message carries the
   meaning and the rule only reinforces it — never colour alone. */
.field__error { display: none; margin-top: .6rem; font-size: var(--t-sm); color: var(--gold-bright); }
.field.is-invalid .field__error { display: block; }
.field.is-invalid .field__rule { transform: scaleX(1); background: var(--gold-bright); }

/* Choice set — service chips. Currently unused: the form was cut back to
   name/email/phone/message. Kept for when a service selector is wanted. */
.choice-set { border: 0; padding: 0; margin-inline: 0; min-width: 0; }
.choice-set__legend { padding: 0; margin-bottom: 1.1rem; }
.choice { display: flex; flex-wrap: wrap; gap: .7rem; }
.choice__opt { display: inline-block; }
.choice__opt input {
  position: absolute;
  width: 1px; height: 1px;
  opacity: 0;
  pointer-events: none;
}
.choice__opt span {
  display: block;
  padding: .8rem 1.25rem;
  border: 1px solid var(--line);
  color: var(--muted);
  font-size: var(--t-sm);
  letter-spacing: .05em;
  line-height: 1;
  cursor: pointer;
  transition: border-color .35s var(--ease), color .35s var(--ease), background-color .35s var(--ease);
}
.choice__opt:hover span { color: var(--cream); border-color: var(--gold-a40); }
.choice__opt input:checked + span {
  border-color: var(--gold);
  color: var(--gold-bright);
  background: var(--gold-a12);
}
.choice__opt input:focus-visible + span {
  outline: 2px solid var(--gold-bright);
  outline-offset: 3px;
}

/* Spam trap. Off-screen rather than display:none — some bots skip
   hidden fields but fill positioned ones. Never focusable. */
.hp {
  position: absolute;
  left: -9999px;
  width: 1px; height: 1px;
  overflow: hidden;
}

.form__body > .form__foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1.25rem clamp(1.75rem, 3vw, 2.75rem);
  margin-top: clamp(2.25rem, 3.5vw, 3rem);
  padding-top: clamp(2rem, 3vw, 2.5rem);
  border-top: 1px solid var(--line);
}
.form__status {
  font-size: var(--t-sm);
  line-height: 1.65;
  color: var(--muted);
  max-width: 46ch;
}
.form__status[data-state="ok"] { color: var(--cream); }
.form__status[data-state="error"] { color: var(--gold-bright); }

/* Details rail ----------------------------------------------- */

.rail {
  background: var(--panel);
  border: 1px solid var(--line);
  border-top: 2px solid var(--gold);
  padding: clamp(1.75rem, 3vw, 2.5rem);
}
.rail__item + .rail__item {
  margin-top: clamp(1.5rem, 2.5vw, 2rem);
  padding-top: clamp(1.5rem, 2.5vw, 2rem);
  border-top: 1px solid var(--line);
}
.rail__value {
  margin-top: .7rem;
  font-size: var(--t-md);
  line-height: 1.5;
  color: var(--cream);
  transition: color .35s var(--ease);
}
a.rail__value:hover { color: var(--gold-bright); }
.rail__note { margin-top: .5rem; font-size: var(--t-sm); line-height: 1.6; color: var(--muted); }

.rail__list { margin-top: .95rem; }
.rail__list li {
  position: relative;
  padding-left: 1.5rem;
  font-size: var(--t-sm);
  line-height: 1.7;
  color: var(--muted);
}
.rail__list li + li { margin-top: .55rem; }
.rail__list li::before {
  content: '';
  position: absolute;
  left: 0; top: .82em;
  width: .8rem; height: 1px;
  background: var(--gold);
}

@media (max-width: 1000px) {
  .contact__grid { grid-template-columns: 1fr; }
}

@media (max-width: 620px) {
  .field-row { grid-template-columns: 1fr; }
  .form__body > .form__foot { flex-direction: column; align-items: flex-start; }
}

@media (prefers-reduced-motion: reduce) {
  .field__rule { transition-duration: .01ms; }
}


/* 18. STORY (ABOUT) ------------------------------------------ */
/* The one page on the site that is prose rather than captions, and it
   is set to look like it. The display serif carries the body copy here
   instead of the sans — Petrona is a text face, and handing it the
   narrative is what makes this page read as a story while every other
   page reads as a specification. Nothing else on the site does this. */

.story { padding-block: clamp(3.5rem, 7vw, 6rem); }
.story__inner { max-width: 64rem; }

/* The thesis. Sits above the chapters, at display size, in cream. */
.story__lede {
  font-family: var(--ff-display);
  font-size: var(--t-lg);
  font-weight: 400;
  line-height: 1.3;
  letter-spacing: -.01em;
  color: var(--cream);
  max-width: 46ch;
  padding-bottom: clamp(2.5rem, 5vw, 4rem);
  margin-bottom: clamp(2.5rem, 5vw, 4rem);
  border-bottom: 1px solid var(--line);
}

/* Chapter: a date/place marker in the left margin, prose beside it.
   The marker drops above the prose once there is no margin to sit in. */
.chapter {
  display: grid;
  grid-template-columns: minmax(0, 11rem) minmax(0, 1fr);
  gap: clamp(1.25rem, 4vw, 3.5rem);
}
.chapter + .chapter {
  margin-top: clamp(3rem, 6vw, 5rem);
  padding-top: clamp(3rem, 6vw, 5rem);
  border-top: 1px solid var(--line);
}

.chapter__mark {
  font-size: var(--t-cap);
  letter-spacing: .2em;
  text-transform: uppercase;
  font-weight: 500;
  line-height: 1.5;
  color: var(--gold);
}
.chapter__mark::before {
  content: '';
  display: block;
  width: 2rem; height: 1px;
  margin-bottom: 1rem;
  background: var(--gold);
}

/* A chapter's left column when it carries more than the marker. The marker
   alone still sits as a bare <p>; this wrapper only appears where a logo
   follows it. */
.chapter__aside {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: clamp(1.4rem, 2.6vw, 2.1rem);
}

/* A former employer's own mark, shown at its own colours because that is
   what a logo is. Held small and inside a hairline box so a block of
   burgundy sits as a credential beside the paragraph rather than reading as
   a second brand competing with the gold. Hover lifts the rule, not the
   logo — nothing recolours artwork that is not ours. */
.chapter__logo {
  display: block;
  width: 100%;
  max-width: 11rem;
  border: 1px solid var(--line);
  transition: border-color .35s var(--ease), opacity .35s var(--ease);
}
.chapter__logo img { display: block; width: 100%; height: auto; }
.chapter__logo:hover,
.chapter__logo:focus-visible { border-color: var(--gold-a40); opacity: .86; }

/* Emphasis inside the prose, set the same way as <b> in the homepage
   double-cut lede: gold-bright carries it and the weight does not move, so
   a stressed word never thickens the reading line. */
.chapter__text b { font-weight: 400; color: var(--gold-bright); }

/* Outbound links inside the prose. Named companies are the only links in
   this text, so they are bold and gold with the hairline underline the
   footer legal links carry — findable mid-sentence without shouting. The
   <strong> inside inherits, so the anchor sets the weight once. */
.chapter__text a,
a.story-link {
  font-weight: 600;
  color: var(--gold-bright);
  border-bottom: 1px solid var(--gold-a40);
  padding-bottom: .06em;
  transition: color .35s var(--ease), border-color .35s var(--ease);
}
.chapter__text a strong,
a.story-link strong { font-weight: inherit; color: inherit; }
.chapter__text a:hover,
.chapter__text a:focus-visible,
a.story-link:hover,
a.story-link:focus-visible { color: var(--cream); border-bottom-color: var(--cream); }

/* Reading measure and rhythm. Cream, not muted — this is the one place
   on the site someone reads several hundred words in a row. */
.chapter__text p {
  font-family: var(--ff-display);
  font-size: clamp(1.0625rem, .95rem + .38vw, 1.3rem);
  line-height: 1.78;
  color: var(--cream);
  max-width: 58ch;
}
.chapter__text p + p { margin-top: 1.45em; }

/* Closing statement — panel ground, same register as the homepage lede. */
.story--close {
  background: var(--panel);
  border-block: 1px solid var(--line);
  padding-block: var(--section);
}
.story__close {
  font-family: var(--ff-display);
  font-size: var(--t-xl);
  font-weight: 400;
  line-height: 1.18;
  letter-spacing: -.015em;
  color: var(--cream);
  max-width: 26ch;
}
.story__close em { font-style: italic; color: var(--gold-bright); }
.story__close > span { display: block; }

@media (max-width: 860px) {
  .chapter { grid-template-columns: 1fr; gap: 1.5rem; }
  /* Stacked: the marker and the logo sit side by side on one row rather
     than stacking a second time above the paragraph. */
  .chapter__aside { flex-direction: row; align-items: center; justify-content: space-between; gap: 1.5rem; }
  .chapter__logo { max-width: 9.5rem; flex: none; }
}


/* Video block (About) ---------------------------------------- */

.videoblock {
  border: 1px solid var(--line);
  background: #000;
  max-width: 74rem;
}
.videoblock video { width: 100%; height: auto; display: block; }
.videoblock__cap {
  padding-top: .9rem;
  font-size: var(--t-sm);
  color: var(--muted);
  max-width: 54ch;
}

@media (max-width: 860px) {
  .gallery, .pair { grid-template-columns: 1fr; }
  .shot--wide { grid-column: auto; }
}
