/* ==========================================================================
   Salon — "THE WALL": a photographer's portfolio hung as a gallery, not a feed
   A Templatorium template · https://templatorium.com

   THE IDEA. Every photographer's site is a white (or OLED-black) minimalist
   grid. Salon changes the *wall the work hangs on*. Works are matted, framed
   and lit on a deep gallery-green wall in an irregular salon hang, each with a
   small engraved museum label (plate no. · year · medium · edition). Walk up
   to any print — click it — and it STEPS OFF THE WALL into a full-frame
   lightbox and "develops" like a darkroom print. It is a saturated,
   museum-green world. No beige, no white grid.

   HOW TO RE-THEME (30-second version — full guide in docs/README.md):
   every colour, font and size lives as a custom property in the token block
   below (§1). Change the values there and the whole gallery follows. Bring your own
   brand colour by swapping the single --brass token. Everything under the
   tokens is structure; you rarely touch it.

   THE CONTRAST PROMISE. Every text colour is LIGHT (bone / a brass accent) and
   every ground is a DEEP saturated green, so every text/ground pair clears
   WCAG 2.2 AA computed. The worst real-text pair is brass-on-wall at 5.22:1;
   body bone-on-wall is 9.91:1. The wall-grain overlay sits BEHIND opaque
   ground fills, never behind copy, and the tightest pair keeps >0.3 headroom
   over its floor. Re-check any colour you change:
   https://webaim.org/resources/contrastchecker/
   ========================================================================== */

/* --------------------------------------------------------------------------
   0. FONTS — vendored woff2, SIL Open Font License (see fonts/OFL.txt).
      Spectral (Production Type) ships static weights; JetBrains Mono is one
      variable file declared with a weight RANGE. No network, no FOUT-of-town.
   -------------------------------------------------------------------------- */
@font-face { font-family: "Spectral"; font-style: normal; font-weight: 300;
  font-display: swap; src: url("../fonts/spectral-light.woff2") format("woff2"); }
@font-face { font-family: "Spectral"; font-style: normal; font-weight: 400;
  font-display: swap; src: url("../fonts/spectral-regular.woff2") format("woff2"); }
@font-face { font-family: "Spectral"; font-style: normal; font-weight: 500;
  font-display: swap; src: url("../fonts/spectral-medium.woff2") format("woff2"); }
@font-face { font-family: "Spectral"; font-style: italic; font-weight: 400;
  font-display: swap; src: url("../fonts/spectral-italic.woff2") format("woff2"); }
@font-face { font-family: "JetBrains Mono"; font-style: normal; font-weight: 400 500;
  font-display: swap; src: url("../fonts/jetbrains-mono.woff2") format("woff2"); }

/* --------------------------------------------------------------------------
   1. TOKENS — the re-theme contract
   -------------------------------------------------------------------------- */
:root {
  /* --- The gallery wall (the IDENTITY) --------------------------------------
     Three depths of one museum green: the wall, a deeper room, the deepest
     (footer). All dark + saturated; bone text reads on every one with headroom.
     These stay put when you bring a brand colour — only --brass reskins. */
  --wall:   #1C3B2D; /* the gallery wall — the primary ground */
  --wall-2: #122619; /* a deeper room — quieter bands */
  --wall-3: #0E1F15; /* the deepest — the footer / lightbox scrim base */

  /* Hairlines for each ground (a touch lighter than the ground) */
  --wall-line:   #2E5140;
  --wall-2-line: #23402F;
  --wall-3-line: #1B3325;

  /* --- Light text treatments (carried by every ground) ---------------------
     Palette-independent: bone ≥9.9:1 on the wall, bone-dim ≥6.7:1, brass ≥5.2:1. */
  --bone:     #EDE7D3; /* primary text — warm lit off-white, like a lit mat */
  --bone-dim: #C3C1AC; /* muted / secondary text */
  --ink:      #17130B; /* the ONE dark token: a label on a brass/bone fill */

  /* --- The warm mat around each work --------------------------------------- */
  --mat:      #E6DFC9; /* the museum mat board — a warm off-white bevel */
  --mat-line: #cfc6ac; /* the mat's inner bevel */

  /* --- The one accent (a brass picture-light) — the ONLY reskinnable colour -
     The warm brass of a gallery light fixture and its engraved labels. Used on
     < 5% of any viewport: the label rules, the status dot, one button fill, the
     "step in" cue, arrow hovers. Swap this token to bring your brand colour. */
  --brass:       #C7A468;
  --brass-lo:    #9C7C4C; /* dimmer brass — label hairlines, frame edges */
  --brass-hover: color-mix(in oklab, var(--brass) 82%, #fff); /* auto-follows */
  --brass-ink:   var(--ink); /* label on a brass fill */

  /* Reserved decorative field for the brand-colour flow. A hue too light to be
     a readable accent lands HERE (decorative only — never text, never a ground). */
  --field-demote: var(--brass);

  /* --- Ground role variables (default = the wall) --------------------------
     Every band reads these; a [data-ground] rule (§3) swaps the whole set so a
     section's text follows its depth. A section with no data-ground uses the
     wall defaults. */
  --g-bg:     var(--wall);
  --g-fg:     var(--bone);
  --g-mute:   var(--bone-dim);
  --g-accent: var(--brass);
  --g-line:   var(--wall-line);

  /* --- Type -----------------------------------------------------------------
     Spectral — the refined transitional serif (Production Type, OFL): the
     display voice AND the reading voice. Its italic is the one emphasis turn.
     JetBrains Mono is reserved for MACHINE DATA ONLY — plate numbers, years,
     mediums, editions, prices, counts. Never an editorial word (see the
     engraved-label rule below). */
  --serif: "Spectral", Spectral, Georgia, "Times New Roman", serif;
  --mono:  "JetBrains Mono", ui-monospace, "SFMono-Regular", Menlo, monospace;

  /* Type scale (fluid; the size JUMP from label to masthead is the design). */
  --t-masthead: clamp(46px, 8vw, 92px);
  --t-h2:       clamp(30px, 4.6vw, 52px);
  --t-h3:       clamp(21px, 2.6vw, 28px);
  --t-body:     17px;
  --t-lede:     clamp(18px, 2vw, 21px);
  --t-small:    14px;
  --t-label:    11.5px;  /* engraved-label mono size */

  /* Spacing / shape */
  --sp-section: clamp(72px, 10vw, 128px);
  --gutter:     clamp(20px, 5vw, 54px);
  --max:        1240px;
  --radius:     3px;     /* frames & labels are nearly square — museum, not app */

  --ease: cubic-bezier(.22, .61, .36, 1);
}

/* --------------------------------------------------------------------------
   2. RESET + BASE
   -------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}
/* Sticky nav → anchor targets clear the header (LEARNINGS: sticky + scroll-margin). */
[id] { scroll-margin-top: 104px; }

body {
  font-family: var(--serif);
  font-weight: 400;
  font-size: var(--t-body);
  line-height: 1.65;
  color: var(--bone);
  background: var(--wall-2);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

/* The wall texture — a faint plaster grain over the whole page. It sits at
   z-index 0 behind all content (every band paints an opaque ground on top of
   its own area, so text never renders against the raw grain). Contrast budget:
   the tightest pair (brass/wall 5.22) keeps >0.7 headroom over AA — safe. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: .5;
  background:
    radial-gradient(120% 80% at 50% -10%, rgba(199,164,104,.06), transparent 60%),
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)' opacity='0.5'/%3E%3C/svg%3E");
  background-blend-mode: overlay;
  mix-blend-mode: soft-light;
}

img { max-width: 100%; height: auto; display: block; }
a { color: inherit; }
button { font: inherit; color: inherit; background: none; border: none; cursor: pointer; }
:where(ul, ol) { list-style: none; }

/* Content sits above the grain. */
.skip-link, header, main, footer { position: relative; z-index: 1; }

.wrap { width: 100%; max-width: var(--max); margin-inline: auto; padding-inline: var(--gutter); }
.visually-hidden {
  position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* --------------------------------------------------------------------------
   FOCUS — one visible ring, computed on EVERY ground (LEARNINGS: per-ground).
   Brass on wall 5.22, wall-2 6.79, wall-3 7.29 — all ≥3. On a brass FILL the
   ring flips to ink (7.88 on brass). Mouse users never see it (:focus-visible).
   -------------------------------------------------------------------------- */
:focus-visible {
  outline: 2px solid var(--brass);
  outline-offset: 3px;
  border-radius: 2px;
}
.btn--fill:focus-visible,
.status-dot:focus-visible { outline-color: var(--ink); }
.skip-link {
  position: absolute; left: 16px; top: -60px;
  background: var(--brass); color: var(--ink);
  font-family: var(--mono); font-size: 12px; letter-spacing: .08em;
  padding: 10px 16px; border-radius: var(--radius);
  transition: top .18s var(--ease);
}
.skip-link:focus { top: 16px; }

/* --------------------------------------------------------------------------
   3. GROUND ROLES — a band swaps its whole text set to match its depth.
   -------------------------------------------------------------------------- */
[data-ground="wall"]   { --g-bg: var(--wall);   --g-line: var(--wall-line); }
[data-ground="deep"]   { --g-bg: var(--wall-2); --g-line: var(--wall-2-line); }
[data-ground="deepest"]{ --g-bg: var(--wall-3); --g-line: var(--wall-3-line); }
[data-ground] {
  background: var(--g-bg);
  color: var(--g-fg);
}

/* --------------------------------------------------------------------------
   4. EDITORIAL TYPE ROLES
   -------------------------------------------------------------------------- */

/* The kicker/eyebrow is EDITORIAL — it is set in the serif small-caps, NOT in
   mono. (House rule: mono is for machine data only; a mono eyebrow is the
   retired habit.) */
.kicker {
  font-family: var(--serif);
  font-weight: 500;
  font-style: normal;
  font-size: 15px;
  letter-spacing: .22em;
  text-transform: uppercase;
  font-variant: small-caps;
  color: var(--brass);
  display: inline-flex;
  align-items: center;
  gap: 14px;
}
.kicker::after {
  content: "";
  height: 1px; width: 64px;
  background: linear-gradient(90deg, var(--brass), transparent);
}

.masthead {
  font-family: var(--serif);
  font-weight: 300;
  font-size: var(--t-masthead);
  line-height: .98;
  letter-spacing: .002em;
  color: var(--bone);
}
.masthead em { font-style: italic; font-weight: 400; color: var(--brass-hover); }

h2.title, .h2 {
  font-family: var(--serif);
  font-weight: 300;
  font-size: var(--t-h2);
  line-height: 1.04;
  letter-spacing: .004em;
}
h2.title em, .h2 em { font-style: italic; font-weight: 400; color: var(--brass-hover); }

h3, .h3 {
  font-family: var(--serif);
  font-weight: 500;
  font-size: var(--t-h3);
  line-height: 1.12;
}

.lede { font-size: var(--t-lede); line-height: 1.6; color: var(--bone-dim); max-width: 46ch; }
.lede b, .lede strong { color: var(--bone); font-weight: 500; }
p { max-width: 66ch; }

/* MACHINE-DATA voice — the only place mono is allowed. Plate numbers, years,
   mediums, editions, prices, counts, coordinates. If a word would not appear
   on a spec sheet, it does not get this class. */
.data {
  font-family: var(--mono);
  font-weight: 400;
  font-size: var(--t-small);
  letter-spacing: .02em;
  font-variant-numeric: tabular-nums;
  color: var(--bone-dim);
}

/* --------------------------------------------------------------------------
   5. BUTTONS + LINKS
   -------------------------------------------------------------------------- */
.btn {
  display: inline-flex; align-items: center; gap: 10px;
  font-family: var(--serif); font-weight: 500; font-size: 16px;
  letter-spacing: .01em;
  padding: 13px 26px;
  border-radius: var(--radius);
  text-decoration: none;
  transition: background .2s var(--ease), color .2s var(--ease), border-color .2s var(--ease);
}
.btn--fill { background: var(--brass); color: var(--ink); }
.btn--fill:hover { background: var(--brass-hover); }
.btn--line {
  border: 1px solid var(--g-line);
  color: var(--g-fg);
}
.btn--line:hover { border-color: var(--brass); color: var(--brass); }

/* The "walk into the gallery" underlined link. */
.enter-link {
  display: inline-flex; align-items: baseline; gap: 10px;
  font-family: var(--serif); font-size: 17px; color: var(--g-fg);
  text-decoration: none;
  border-bottom: 1px solid var(--brass);
  padding-bottom: 3px;
  transition: gap .2s var(--ease), color .2s var(--ease);
}
.enter-link .arw { color: var(--brass); transition: transform .2s var(--ease); }
.enter-link:hover { gap: 16px; }
.enter-link:hover .arw { transform: translateX(4px); }

/* Body links inside prose. */
.prose a { color: var(--brass); text-decoration: underline; text-underline-offset: 3px;
  text-decoration-color: var(--brass-lo); }
.prose a:hover { text-decoration-color: var(--brass); }

/* --------------------------------------------------------------------------
   6. NAV / HEADER
   -------------------------------------------------------------------------- */
.nav {
  position: sticky; top: 0; z-index: 20;
  background: color-mix(in oklab, var(--wall-2) 88%, transparent);
  backdrop-filter: blur(8px) saturate(120%);
  border-bottom: 1px solid transparent;
  transition: border-color .3s var(--ease), background .3s var(--ease);
}
.nav.scrolled { border-bottom-color: var(--wall-line); }
.nav .wrap { display: flex; align-items: center; gap: 20px; min-height: 72px; }

/* The wordmark is a LOGOTYPE set in the display serif — not a mono chip. */
.wordmark {
  font-family: var(--serif); font-weight: 500; font-size: 21px;
  letter-spacing: .16em; text-transform: uppercase; text-decoration: none;
  color: var(--bone); display: inline-flex; align-items: center; gap: 10px;
}
.wordmark .mk {
  width: 9px; height: 9px; border: 1.5px solid var(--brass); transform: rotate(45deg);
}

nav[aria-label="Main"] { margin-left: auto; }
.nav-links { display: flex; align-items: center; gap: 30px; }
.nav-links a {
  font-family: var(--serif); font-weight: 400; font-size: 15px;
  letter-spacing: .12em; text-transform: uppercase; font-variant: small-caps;
  color: var(--bone-dim); text-decoration: none;
  transition: color .18s var(--ease);
}
.nav-links a:hover, .nav-links a[aria-current="page"] { color: var(--bone); }
.nav-links a[aria-current="page"] { text-decoration: underline; text-underline-offset: 6px;
  text-decoration-color: var(--brass); }

.nav-actions { display: flex; align-items: center; gap: 18px; }
/* The commissions status — the dot is a lit brass lamp; the word is machine
   status, kept in the serif small-caps (editorial), the dot carries the signal. */
.status {
  display: inline-flex; align-items: center; gap: 9px;
  font-family: var(--serif); font-size: 14px; letter-spacing: .1em;
  font-variant: small-caps; text-transform: uppercase; color: var(--bone-dim);
}
.status .dot {
  width: 7px; height: 7px; border-radius: 50%; background: var(--brass);
  box-shadow: 0 0 0 3px color-mix(in oklab, var(--brass) 26%, transparent);
}

/* Mobile menu button — hidden on desktop. */
.nav-toggle { display: none; width: 44px; height: 44px; margin-left: auto;
  align-items: center; justify-content: center; }
.nav-toggle .bars, .nav-toggle .bars::before, .nav-toggle .bars::after {
  content: ""; display: block; width: 22px; height: 1.5px; background: var(--bone);
  transition: transform .2s var(--ease), opacity .2s var(--ease); }
.nav-toggle .bars { position: relative; }
.nav-toggle .bars::before { position: absolute; top: -7px; }
.nav-toggle .bars::after  { position: absolute; top: 7px; }
.nav-toggle[aria-expanded="true"] .bars { background: transparent; }
.nav-toggle[aria-expanded="true"] .bars::before { transform: translateY(7px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] .bars::after  { transform: translateY(-7px) rotate(-45deg); }

/* --------------------------------------------------------------------------
   7. HERO — the promoted concept. A masthead + engraved plate on the wall,
   the featured work feathered in on the right with a "step in" cue.
   -------------------------------------------------------------------------- */
.hero {
  position: relative;
  background:
    radial-gradient(120% 120% at 16% 26%, #234a38 0%, var(--wall) 46%, var(--wall-2) 100%);
  overflow: clip;
  min-height: min(92vh, 860px);
  display: flex; align-items: center;
}
.hero .wrap {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
  gap: clamp(24px, 4vw, 64px);
  align-items: center;
  padding-block: clamp(56px, 9vw, 104px);
}

.hero-field { max-width: 30rem; }
.hero .masthead { margin-top: 26px; }
.hero .lede { margin-top: 24px; }
.hero .enter-link { margin-top: 28px; }

/* The engraved museum label — the signature device. Title in serif italic;
   plate no. / year / medium / edition in mono (machine data). */
.plate-label {
  margin-top: 38px; max-width: 340px;
  background: linear-gradient(160deg, rgba(237,231,211,.07), rgba(237,231,211,.02));
  border: 1px solid var(--brass-lo);
  border-left: 3px solid var(--brass);
  border-radius: var(--radius);
  padding: 15px 18px;
  box-shadow: 0 16px 36px -22px rgba(0,0,0,.75);
}
.plate-label .pl {
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .22em;
  text-transform: uppercase; color: var(--brass); margin-bottom: 7px;
}
.plate-label .ttl {
  font-family: var(--serif); font-style: italic; font-weight: 400;
  font-size: 19px; color: var(--bone); line-height: 1.2;
}
.plate-label .med {
  display: block; margin-top: 8px;
  font-family: var(--mono); font-size: 11px; letter-spacing: .05em; color: var(--bone-dim);
  font-variant-numeric: tabular-nums;
}

/* The featured work, hung and feathered into the wall on the right. */
.hero-piece { position: relative; }
.hero-piece .work { --frame-w: 100%; }
.hero-piece .caption { display: none; } /* the hero uses the plate-label instead */
.hero .stepin-cue {
  position: absolute; left: 50%; bottom: 18px; transform: translateX(-50%);
  z-index: 4; display: inline-flex; align-items: center; gap: 8px;
  background: var(--brass); color: var(--ink);
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .16em;
  text-transform: uppercase; padding: 6px 13px; border-radius: var(--radius);
  box-shadow: 0 10px 24px -8px rgba(0,0,0,.7);
  pointer-events: none;
}

/* --------------------------------------------------------------------------
   8. THE WALL — the salon hang. An INTENTIONALLY irregular grid (not a uniform
   masonry): varied frame sizes on a 12-col field, generous wall between them.
   -------------------------------------------------------------------------- */
.section { padding-block: var(--sp-section); }
.section-head { margin-bottom: clamp(36px, 5vw, 64px); max-width: 60ch; }
.section-head .h2 { margin-top: 18px; }
.section-head p { margin-top: 18px; color: var(--bone-dim); }

.wall {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: clamp(28px, 4vw, 58px) clamp(24px, 3.4vw, 46px);
  align-items: end; /* pieces hang from a shared line, bottoms vary — a real hang */
}
/* An asymmetric, curated arrangement — assigned per position, not auto-flow.
   Column spans + aspect ratios vary so the wall reads composed, never gridded. */
.hang { grid-column: span 4; }
.hang--wide  { grid-column: span 6; }
.hang--tall  { grid-column: span 4; }
.hang--lift  { margin-bottom: clamp(20px, 4vw, 56px); } /* hung higher on the wall */
.hang--drop  { margin-top: clamp(24px, 5vw, 68px); }    /* hung lower */

/* --- A framed work ------------------------------------------------------- */
.work {
  display: block; text-decoration: none; color: inherit;
  outline-offset: 6px;
}
.plate {
  position: relative;
  background: #0c1912; /* the frame's rebate, seen at the bevel */
  padding: clamp(8px, 1.1vw, 14px); /* the frame width */
  border-radius: 2px;
  box-shadow:
    0 2px 0 rgba(255,255,255,.05) inset,       /* top frame highlight */
    0 -2px 0 rgba(0,0,0,.5) inset,             /* bottom frame shadow */
    0 26px 40px -26px rgba(0,0,0,.8),          /* the work casts on the wall */
    0 6px 14px -8px rgba(0,0,0,.6);
  transition: transform .35s var(--ease), box-shadow .35s var(--ease);
}
/* A thin brass frame liner. */
.plate::after {
  content: ""; position: absolute; inset: 4px; border: 1px solid rgba(199,164,104,.28);
  border-radius: 2px; pointer-events: none;
}
/* The brass picture-light — a warm wash from a fixture above each frame. */
.plate::before {
  content: ""; position: absolute; left: 12%; right: 12%; top: -13px; height: 26px;
  background: radial-gradient(60% 130% at 50% 0, rgba(199,164,104,.5), transparent 72%);
  filter: blur(3px); opacity: .8; pointer-events: none;
}
.work:hover .plate { transform: translateY(-4px); }
/* Empty placeholders are not interactive — they don't lift or brass-glow. */
.work--empty:hover .plate { transform: none; }
.work--empty:hover .plate,
.work--empty .plate {
  box-shadow:
    0 2px 0 rgba(255,255,255,.05) inset, 0 -2px 0 rgba(0,0,0,.5) inset,
    0 26px 40px -26px rgba(0,0,0,.8), 0 6px 14px -8px rgba(0,0,0,.6);
}
.work:hover .plate,
.work:focus-visible .plate {
  box-shadow:
    0 2px 0 rgba(255,255,255,.06) inset,
    0 -2px 0 rgba(0,0,0,.5) inset,
    0 34px 50px -26px rgba(0,0,0,.85),
    0 0 0 1px rgba(199,164,104,.4);
}

/* The warm mat, inset inside the frame, around the work. */
.mat {
  position: relative;
  background: var(--mat);
  padding: clamp(12px, 2vw, 26px);
  box-shadow: 0 1px 2px rgba(0,0,0,.35) inset, 0 0 0 1px var(--mat-line) inset;
}
/* The image window inside the mat. */
.win {
  position: relative; overflow: hidden; background: #10231a;
  box-shadow: 0 0 0 1px rgba(0,0,0,.35);
}
.win img {
  width: 100%; height: 100%; object-fit: cover; display: block;
}
/* Aspect windows — the varied sizes of a hang. */
.win--portrait  { aspect-ratio: 4 / 5; }
.win--landscape { aspect-ratio: 5 / 4; }
.win--wide      { aspect-ratio: 3 / 2; }
.win--square    { aspect-ratio: 1 / 1; }
.win--tall      { aspect-ratio: 4 / 5.6; }

/* --- The empty-state window (a designed empty plate, per the Datum rule) ----
   A faint on-brand line motif masked from the brass token (re-themes with the
   palette) and an OFF-CENTRE spec label anchored to the corner. When a real
   photo is wired via data-slot-img, the placeholder is replaced by an <img>
   and the motif retires with it. */
.win--empty { background: #16281e; }
.win--empty::before {
  content: ""; position: absolute; inset: 0;
  /* a horizon + a rising-sun rule — a photographer's framing motif */
  background:
    linear-gradient(transparent 61%, color-mix(in oklab, var(--brass) 40%, transparent) 61.5%, transparent 62%),
    radial-gradient(circle at 50% 61%, transparent 44px, color-mix(in oklab, var(--brass) 30%, transparent) 44.5px, transparent 46px);
  opacity: .5;
}
.win--empty .spec {
  position: absolute; left: 14px; bottom: 12px; /* OFF-centre, cornered */
  font-family: var(--mono); font-size: 10px; letter-spacing: .16em;
  text-transform: uppercase; color: color-mix(in oklab, var(--brass) 78%, var(--mat));
}
.win--empty .spec b { display: block; color: color-mix(in oklab, var(--bone) 60%, transparent);
  font-weight: 400; font-size: 9.5px; margin-top: 3px; letter-spacing: .12em; }
/* When a photo is wired into the slot, the empty plate becomes the
   :has(img) FALLBACK state: the line motif and the spec label retire so the
   print reads clean; clear the slot (in the editor) and both return. */
.win--empty:has(img) { background: #10231a; }
.win--empty:has(img)::before { content: none; }
.win--empty:has(img) .spec { display: none; }

/* --- The engraved caption beneath each frame ----------------------------- */
.caption { margin-top: 16px; padding-left: 2px; }
.caption .pl {
  font-family: var(--mono); font-size: 10px; letter-spacing: .2em;
  text-transform: uppercase; color: var(--brass); display: block; margin-bottom: 5px;
}
.caption .ttl {
  font-family: var(--serif); font-style: italic; font-weight: 400; font-size: 18px;
  color: var(--bone); line-height: 1.25;
}
.caption .med {
  font-family: var(--mono); font-size: 11px; letter-spacing: .04em; color: var(--bone-dim);
  display: block; margin-top: 6px; font-variant-numeric: tabular-nums;
}

/* --------------------------------------------------------------------------
   9. THE LIGHTBOX — a work steps off the wall into a full frame and develops.
   Primary path: View Transitions shared-element morph (js/main.js). This is
   the static presentation; the morph + develop are enhancement.
   -------------------------------------------------------------------------- */
.lightbox {
  position: fixed; inset: 0; z-index: 60;
  display: grid; place-items: center;
  padding: clamp(20px, 5vw, 68px);
  background: color-mix(in oklab, var(--wall-3) 92%, #000);
}
.lightbox[hidden] { display: none; }
.lightbox-figure {
  position: relative; max-width: min(1100px, 100%); max-height: 100%;
  display: flex; flex-direction: column; gap: 18px;
}
.lightbox-frame {
  background: #0c1912; padding: clamp(10px, 1.4vw, 18px);
  box-shadow: 0 40px 90px -30px rgba(0,0,0,.9), 0 0 0 1px rgba(199,164,104,.4);
  border-radius: 2px; min-height: 0;
}
.lightbox-frame .mat { padding: clamp(14px, 2.2vw, 30px); }
.lightbox-frame img {
  max-height: min(72vh, 760px); width: auto; max-width: 100%; margin-inline: auto;
  object-fit: contain;
}
.lightbox-caption { display: flex; align-items: baseline; gap: 16px; flex-wrap: wrap;
  color: var(--bone); }
.lightbox-caption .pl { font-family: var(--mono); font-size: 11px; letter-spacing: .2em;
  text-transform: uppercase; color: var(--brass); }
.lightbox-caption .ttl { font-family: var(--serif); font-style: italic; font-size: 21px; }
.lightbox-caption .med { font-family: var(--mono); font-size: 12px; color: var(--bone-dim);
  font-variant-numeric: tabular-nums; }
.lightbox-close {
  position: absolute; top: -6px; right: -6px;
  width: 44px; height: 44px; display: grid; place-items: center;
  color: var(--bone); background: color-mix(in oklab, var(--wall-3) 80%, #000);
  border: 1px solid var(--wall-line); border-radius: 50%;
  font-family: var(--mono); font-size: 18px; line-height: 1;
}
.lightbox-close:hover { color: var(--brass); border-color: var(--brass); }
.lightbox-count { font-family: var(--mono); font-size: 11px; letter-spacing: .14em;
  color: var(--bone-dim); }

/* --------------------------------------------------------------------------
   10. STATEMENT band — the curator's note. One quiet italic line.
   -------------------------------------------------------------------------- */
.statement { text-align: left; }
.statement .h2 { max-width: 20ch; }
.statement .note { margin-top: 26px; max-width: 52ch; color: var(--bone-dim);
  font-size: var(--t-lede); }
.statement .sig { margin-top: 30px; font-style: italic; color: var(--bone); }
.statement .who { font-style: normal; font-family: var(--mono); font-size: 12px;
  letter-spacing: .12em; text-transform: uppercase; color: var(--brass);
  display: block; margin-top: 6px; }

/* --------------------------------------------------------------------------
   11. SERIES INDEX — the "rooms". A short set of doorway cards.
   -------------------------------------------------------------------------- */
.rooms { display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(20px, 3vw, 40px); }
.room {
  display: block; text-decoration: none; color: inherit;
  border: 1px solid var(--g-line); border-radius: var(--radius);
  padding: 24px 24px 28px; background: color-mix(in oklab, var(--wall) 60%, transparent);
  transition: border-color .25s var(--ease), transform .25s var(--ease);
}
.room:hover { border-color: var(--brass); transform: translateY(-3px); }
.room .no { font-family: var(--mono); font-size: 11px; letter-spacing: .2em; color: var(--brass);
  text-transform: uppercase; }
.room h3 { margin-top: 14px; }
.room .rm-meta { margin-top: 12px; font-family: var(--mono); font-size: 12px;
  color: var(--bone-dim); letter-spacing: .04em; font-variant-numeric: tabular-nums; }
.room .go { margin-top: 18px; display: inline-flex; align-items: center; gap: 8px;
  color: var(--brass); font-size: 15px; }

/* --------------------------------------------------------------------------
   12. COMMISSIONS CTA — a brass-lit invitation.
   -------------------------------------------------------------------------- */
.commission { position: relative; overflow: hidden; }
.commission::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(80% 120% at 50% -20%, rgba(199,164,104,.16), transparent 60%);
}
.commission .wrap { position: relative; text-align: center; display: grid; justify-items: center; }
.commission .h2 { max-width: 22ch; }
.commission .lede { margin-top: 22px; text-align: center; }
.commission .btn-row { margin-top: 34px; display: flex; gap: 16px; flex-wrap: wrap;
  justify-content: center; }
.commission .avail { margin-top: 26px; }

/* --------------------------------------------------------------------------
   13. SUB-PAGE MODULES
   -------------------------------------------------------------------------- */

/* Page header — a quiet title band used by the interior pages. */
.page-head { padding-block: clamp(72px, 10vw, 128px) clamp(28px, 4vw, 52px); }
.page-head .wrap { max-width: 62ch; }
.page-head .masthead { margin-top: 22px; font-size: clamp(40px, 6.4vw, 74px); }
.page-head .lede { margin-top: 24px; }
.page-head .runline { margin-top: 20px; font-family: var(--mono); font-size: 12px;
  letter-spacing: .16em; text-transform: uppercase; color: var(--bone-dim);
  display: flex; gap: 18px; flex-wrap: wrap; }
.page-head .runline b { color: var(--brass); font-weight: 400; }

/* SERIES ROOM — a quiet single-column gallery of plates from one body of work. */
.room-plates { display: flex; flex-direction: column; gap: clamp(48px, 8vw, 104px); }
.room-plates .work { max-width: 860px; margin-inline: auto; width: 100%; }
.room-plates .caption { text-align: center; }
.room-plates .caption .pl,
.room-plates .caption .med { letter-spacing: .18em; }

/* WORK STORY — an essay set beside plates. */
.story { display: grid; grid-template-columns: minmax(0, 1fr); gap: clamp(40px, 6vw, 80px); }
.story .prose { max-width: 62ch; margin-inline: auto; }
.story .prose p + p { margin-top: 1.2em; }
.story .prose .drop::first-letter {
  font-size: 3.4em; float: left; line-height: .8; padding: 4px 12px 0 0;
  font-weight: 300; color: var(--brass);
}
.story .pull {
  font-family: var(--serif); font-style: italic; font-weight: 300;
  font-size: clamp(24px, 3.2vw, 34px); line-height: 1.3; color: var(--bone);
  max-width: 24ch; margin: clamp(32px, 5vw, 56px) auto; text-align: center;
}
.story .plate-row { display: grid; grid-template-columns: repeat(2, 1fr);
  gap: clamp(20px, 3vw, 40px); align-items: start; }

/* ABOUT — bio, exhibitions ledger, clients. */
.bio-grid { display: grid; grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
  gap: clamp(32px, 6vw, 80px); align-items: start; }
.bio .prose p + p { margin-top: 1.1em; }
.portrait .plate { max-width: 380px; }

.ledger { border-top: 1px solid var(--g-line); }
.ledger .row {
  display: grid; grid-template-columns: 92px 1fr auto; gap: 20px; align-items: baseline;
  padding: 16px 0; border-bottom: 1px solid var(--g-line);
}
.ledger .yr { font-family: var(--mono); font-size: 13px; color: var(--brass);
  font-variant-numeric: tabular-nums; letter-spacing: .04em; }
.ledger .ex { font-family: var(--serif); font-size: 17px; color: var(--bone); }
.ledger .ex em { font-style: italic; color: var(--bone-dim); display: block; font-size: 14px;
  margin-top: 2px; }
.ledger .place { font-family: var(--mono); font-size: 12px; color: var(--bone-dim);
  letter-spacing: .04em; text-align: right; }

.clients { display: flex; flex-wrap: wrap; gap: 14px 30px; }
.clients li { font-family: var(--serif); font-size: 17px; color: var(--bone-dim); }
.clients li::before { content: "· "; color: var(--brass-lo); }

/* CONTACT — commissions form + availability. */
.contact-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(36px, 6vw, 80px); align-items: start; }
.avail-card {
  border: 1px solid var(--g-line); border-left: 3px solid var(--brass);
  border-radius: var(--radius); padding: 24px 26px;
  background: color-mix(in oklab, var(--wall) 55%, transparent);
}
.avail-card .status { font-size: 15px; }
.avail-card dl { margin-top: 20px; display: grid; grid-template-columns: auto 1fr; gap: 10px 18px; }
/* Field LABELS are editorial words → serif small-caps; only the VALUES
   (phone, rate) below are machine data and stay mono (.num). */
.avail-card dt { font-family: var(--serif); font-weight: 500; font-size: 13px;
  letter-spacing: .1em; text-transform: uppercase; font-variant: small-caps;
  color: var(--bone-dim); align-self: baseline; }
.avail-card dd { font-family: var(--serif); color: var(--bone); }
.avail-card dd.num { font-family: var(--mono); font-variant-numeric: tabular-nums; }

.field { display: flex; flex-direction: column; gap: 8px; margin-bottom: 20px; }
.field label { font-family: var(--serif); font-size: 14px; letter-spacing: .06em;
  color: var(--bone-dim); font-variant: small-caps; text-transform: uppercase; }
.field input, .field select, .field textarea {
  font-family: var(--serif); font-size: 16px; color: var(--bone);
  background: color-mix(in oklab, var(--wall-3) 60%, transparent);
  border: 1px solid var(--g-line); border-radius: var(--radius);
  padding: 12px 14px;
}
.field textarea { min-height: 130px; resize: vertical; }
.field input::placeholder, .field textarea::placeholder { color: color-mix(in oklab, var(--bone-dim) 62%, transparent); }
.field input:focus-visible, .field select:focus-visible, .field textarea:focus-visible {
  outline: 2px solid var(--brass); outline-offset: 2px; border-color: var(--brass); }
form .btn { margin-top: 6px; }
form .note { margin-top: 16px; font-size: 13px; color: var(--bone-dim); }

/* --------------------------------------------------------------------------
   14. FOOTER
   -------------------------------------------------------------------------- */
.footer { border-top: 1px solid var(--wall-3-line); }
.footer .wrap { padding-block: clamp(52px, 7vw, 84px); }
.footer-top { display: grid; grid-template-columns: minmax(0, 1.4fr) repeat(2, minmax(0, 1fr));
  gap: 36px; }
.footer .wordmark { font-size: 26px; }
.footer .tag { margin-top: 16px; color: var(--bone-dim); max-width: 34ch; }
/* Section headings are EDITORIAL words → serif small-caps, not mono
   (mono is reserved for machine data). */
.footer h4 { font-family: var(--serif); font-weight: 500; font-size: 14px;
  letter-spacing: .16em; text-transform: uppercase; font-variant: small-caps;
  color: var(--brass); margin-bottom: 14px; }
.footer ul { display: grid; gap: 9px; }
.footer a { color: var(--bone-dim); text-decoration: none; font-size: 15px; }
.footer a:hover { color: var(--bone); }
.footer .contact-line { font-family: var(--mono); font-size: 13px; color: var(--bone-dim);
  font-variant-numeric: tabular-nums; }
.footer-base { margin-top: clamp(36px, 5vw, 56px); padding-top: 22px;
  border-top: 1px solid var(--wall-3-line);
  display: flex; justify-content: space-between; gap: 18px; flex-wrap: wrap;
  font-family: var(--mono); font-size: 11.5px; letter-spacing: .08em; color: var(--bone-dim); }
.footer-base a { color: var(--bone-dim); }

/* --------------------------------------------------------------------------
   15. REVEALS — nothing is hidden by default. The .in class PLAYS a keyframe
   whose `backwards` fill supplies the hidden start frame, so print / full-page
   screenshots / no-JS / reduced-motion all render the complete page. Works
   also "develop" (contrast + brightness rise) as they arrive — a darkroom print.
   -------------------------------------------------------------------------- */
.js .reveal { }
.js .reveal.in {
  animation: rise .7s var(--ease) both;
  animation-delay: calc(var(--i, 0) * 70ms);
}
@keyframes rise {
  from { opacity: 0; transform: translateY(16px); }
  to   { opacity: 1; transform: none; }
}
.js .develop.in .win img,
.js .develop.in .win--empty:not(:has(img)) { animation: develop 1.1s var(--ease) both;
  animation-delay: calc(var(--i, 0) * 70ms); }
@keyframes develop {
  from { filter: contrast(.55) brightness(.72) saturate(.6); opacity: .2; }
  to   { filter: none; opacity: 1; }
}

/* --------------------------------------------------------------------------
   16. VIEW TRANSITIONS — the shared-element morph is driven from JS via
   document.startViewTransition; here we tune its timing and add a gentle
   cross-document (page-to-page) fade for supporting browsers. Both are pure
   enhancement — unsupported browsers simply cut, and everything still works.
   -------------------------------------------------------------------------- */
@view-transition { navigation: auto; }

::view-transition-group(work-active) { animation-duration: .48s;
  animation-timing-function: var(--ease); }
::view-transition-old(root), ::view-transition-new(root) { animation-duration: .32s; }

/* --------------------------------------------------------------------------
   17. RESPONSIVE
   -------------------------------------------------------------------------- */
@media (max-width: 960px) {
  .hero .wrap { grid-template-columns: 1fr; }
  .hero-piece { order: -1; max-width: 520px; }
  .hero-field { max-width: none; }
  .rooms { grid-template-columns: 1fr 1fr; }
  .bio-grid, .contact-grid { grid-template-columns: 1fr; }
  .footer-top { grid-template-columns: 1fr 1fr; }
}

@media (max-width: 760px) {
  .nav-toggle { display: inline-flex; }
  nav[aria-label="Main"] { margin-left: 0; }
  .nav-links {
    position: absolute; left: 0; right: 0; top: 100%;
    flex-direction: column; align-items: flex-start; gap: 4px;
    background: var(--wall-2); border-bottom: 1px solid var(--wall-line);
    padding: 12px var(--gutter) 20px; display: none;
  }
  .nav-links.open { display: flex; }
  .nav-actions .status .txt { display: none; } /* keep just the lamp on mobile */

  /* The salon hang linearises to a single hung column. */
  .wall { grid-template-columns: 1fr; align-items: stretch; }
  .hang, .hang--wide, .hang--tall { grid-column: auto; }
  .hang--lift, .hang--drop { margin-block: 0; }

  .rooms { grid-template-columns: 1fr; }
  .story .plate-row { grid-template-columns: 1fr; }
  .footer-top { grid-template-columns: 1fr; }
  .ledger .row { grid-template-columns: 68px 1fr; }
  .ledger .place { grid-column: 2; text-align: left; }
}

/* No-JS: the nav must not trap as a sticky bar with the menu hidden. */
html:not(.js) .nav { position: static; }
html:not(.js) .nav-toggle { display: none; }
@media (max-width: 760px) {
  html:not(.js) .nav-links { position: static; display: flex; flex-direction: row;
    flex-wrap: wrap; background: none; border: 0; padding: 0; gap: 18px 24px; }
}

/* --------------------------------------------------------------------------
   18. REDUCED MOTION — honour the preference: no reveals, no develop, no morph,
   instant lightbox. Every element rests in its final, visible state.
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .001ms !important; animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
  .js .reveal.in, .js .develop.in .win img, .js .develop.in .win--empty { animation: none; }
  @view-transition { navigation: none; }
}

/* --------------------------------------------------------------------------
   19. PRINT — a clean catalogue: white paper, dark ink, labels intact.
   -------------------------------------------------------------------------- */
@media print {
  body { background: #fff; color: #111; }
  body::before, .nav, .commission::before, .stepin-cue, .lightbox { display: none !important; }
  .plate, .mat { box-shadow: none; background: #fff; }
  .caption .pl, .caption .med, .kicker, .data { color: #6b5a2e; }
  .masthead, .h2, h3, .caption .ttl { color: #111; }
}
