/* ==========================================================================
   Le Beau Monde — public site
   Built 15 July 2026. Source of truth: Brand Kit/BRAND.md (Canva kit,
   decided 10 July 2026). Copper is an accent, never a ground; text is ink
   on ivory; the wordmark is placed artwork (assets/lbm-wordmark*.svg),
   never typeset. Playfair Display upright only — the italic axis is
   never requested. Motion: opacity and ≤12px translate, nothing faster
   than 400ms; the wordmark fades in over ~1s.

   Fonts are self-hosted (assets/fonts/) as of 22 July 2026, see
   Website/LAUNCH GATE.md, gate 1 "Google Fonts must be self-hosted before
   launch". Files pulled verbatim from fonts.gstatic.com, latin + latin-ext
   subsets only (this site is UK/EU English copy; cyrillic and vietnamese
   were never requested by any page). Playfair Display 400 and 500 point at
   the same file: Google itself serves identical bytes for both weights
   under this request shape, which is upstream behaviour, not a local error,
   and self-hosting preserves it rather than silently changing the render.
   Both families are SIL OFL 1.1, so self-hosting is expressly permitted.
   ========================================================================== */

@font-face{
  font-family:'Lato';font-style:normal;font-weight:300;font-display:swap;
  src:url('assets/fonts/lato-300-latin-ext.woff2') format('woff2');
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}
@font-face{
  font-family:'Lato';font-style:normal;font-weight:300;font-display:swap;
  src:url('assets/fonts/lato-300-latin.woff2') format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face{
  font-family:'Lato';font-style:normal;font-weight:400;font-display:swap;
  src:url('assets/fonts/lato-400-latin-ext.woff2') format('woff2');
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}
@font-face{
  font-family:'Lato';font-style:normal;font-weight:400;font-display:swap;
  src:url('assets/fonts/lato-400-latin.woff2') format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face{
  font-family:'Lato';font-style:normal;font-weight:700;font-display:swap;
  src:url('assets/fonts/lato-700-latin-ext.woff2') format('woff2');
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}
@font-face{
  font-family:'Lato';font-style:normal;font-weight:700;font-display:swap;
  src:url('assets/fonts/lato-700-latin.woff2') format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face{
  font-family:'Playfair Display';font-style:normal;font-weight:400;font-display:swap;
  src:url('assets/fonts/playfair-latin-ext.woff2') format('woff2');
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}
@font-face{
  font-family:'Playfair Display';font-style:normal;font-weight:400;font-display:swap;
  src:url('assets/fonts/playfair-latin.woff2') format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face{
  font-family:'Playfair Display';font-style:normal;font-weight:500;font-display:swap;
  src:url('assets/fonts/playfair-latin-ext.woff2') format('woff2');
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}
@font-face{
  font-family:'Playfair Display';font-style:normal;font-weight:500;font-display:swap;
  src:url('assets/fonts/playfair-latin.woff2') format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}

:root{
  --ink:#333333;
  --ink-soft:rgba(51,51,51,.60);
  --ivory:#FCF9F7;
  --warm:#F7EFE7;
  --white:#FFFFFF;
  --sand:#EFD8BA;
  --copper:#C8783B;
  /* deep corrected #B9753E → #8B5227, 23 Jul 2026. BRAND.md corrected the
     token on 15 Jul 2026: the old value measured 3.53:1 on ivory and failed
     AA at the one job deep has, small type. Every use in this sheet is small
     copper type or a small-type hover, so darkening improves all of them and
     regresses nothing. Never text on espresso — use copper-mid there. */
  --copper-deep:#8B5227;
  --copper-mid:#CA8E55;
  --espresso:#262220;
  --serif:'Playfair Display',Georgia,serif;
  --sans:'Lato',-apple-system,'Helvetica Neue',sans-serif;

  /* The masthead's own height, measured, not guessed: 34 + 19 (the nav's
     line box, the tallest thing in the row) + 30 + 1px rule = 84. Every
     first-screen calculation on this site subtracts it, so it is stated
     once here. If the masthead's padding or the nav's size changes, this
     changes with it — and the first screens are re-measured. */
  --head:84px;
  /* What is left of the first screen once the masthead has taken its share.
     svh, not vh: on mobile Safari vh is the *largest* viewport, so a
     100vh first screen is ~90px taller than the screen actually is and
     the dateline falls under the toolbar. */
  --first:calc(100svh - var(--head));
}

*{box-sizing:border-box;margin:0;padding:0;}

html{scroll-behavior:smooth;}

body{
  font-family:var(--sans);font-weight:300;
  font-size:17px;line-height:1.8;
  color:var(--ink);background:var(--ivory);
  -webkit-font-smoothing:antialiased;
}

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

::selection{background:var(--sand);}

a{color:inherit;}

.wrap{max-width:1060px;margin:0 auto;padding:0 28px;}
.prose{max-width:620px;margin:0 auto;}
.prose p{margin-bottom:26px;}
.prose p:last-child{margin-bottom:0;}

/* ───────────────────────── wayfinding ───────────────────────── */

header.site{
  padding:34px 28px 30px;
  border-bottom:1px solid var(--sand);
  background:var(--ivory);
}
.masthead{
  max-width:1060px;margin:0 auto;
  display:flex;flex-wrap:wrap;align-items:center;
  justify-content:space-between;gap:20px 40px;
}
.masthead .mark img{height:15px;width:auto;}
/* The home page's masthead carries no wordmark. The hero mark is on the
   same first screen and twenty times its size; both rendered at once is
   the mark twice on one screen — the one thing a wordmark must never be.
   The hero mark wins (it is the identity; the masthead's is only the way
   home, and on the home page there is nowhere to go). The nav takes the
   row on its own, centred, and — since 23 Jul 2026 — sits over the
   photograph in ivory: the header has no ground of its own, and the
   image's top scrim (see .bleed .scrim) is what carries it. Interior
   pages are untouched: there the masthead mark is the only one on the
   page. */
body.home .masthead .mark{display:none;}
body.home .masthead{justify-content:center;}
body.home header.site{
  position:absolute;top:0;left:0;right:0;z-index:3;
  background:transparent;border-bottom:0;
}
body.home nav.site a{color:var(--ivory);}
body.home nav.site a:hover,
body.home nav.site a[aria-current="page"]{color:var(--copper-mid);}
nav.site{display:flex;flex-wrap:wrap;gap:12px 30px;}
nav.site a{
  font-size:10.5px;letter-spacing:.28em;text-transform:uppercase;
  color:var(--ink);text-decoration:none;
  transition:color .4s ease;
}
nav.site a:hover{color:var(--copper);}
/* deep, not core: the current-page marker is 10.5px text that has to be
   read, and core computes 3.23:1 on ivory (BRAND.md: core is never text
   below 24px). The hover may stay core — it is a transient state under
   the pointer, not something anyone reads cold. Corrected 23 Jul 2026
   with the --copper-deep value fix. */
nav.site a[aria-current="page"]{color:var(--copper-deep);}
/* Mobile chrome — the veil earns its restraint by having almost none.
   On the home page the masthead goes entirely: the hero mark is the
   identity and the first screen is wordmark, line, dateline, nothing
   else. On interior pages the masthead stays (it is the way home) but
   carries only the wordmark and the one discreet Nominations link, on a
   single row. The full section list lives in the footer at these widths,
   so nothing becomes unreachable. */
@media(max-width:700px){
  header.site{padding:22px 22px 20px;}
  .masthead{justify-content:center;text-align:center;gap:14px 24px;}
  .masthead .mark img{height:13px;}
  nav.site{justify-content:center;}
  nav.site a.section{display:none;}
  /* On the home page this leaves one ivory word — Nominations — over the
     top of the photograph. It stays: the full section list lives in the
     footer at these widths, so nothing is unreachable. */
}

/* ───────────────────────── page grammar ───────────────────────── */

main{padding:110px 28px 130px;}
@media(max-width:700px){main{padding:80px 22px 96px;}}

/* Kickers are 10.5–11px copper caps: text, so deep, not core — core is
   3.23:1 on ivory and BRAND.md bars it from text below 24px. The register
   h3s and city status lines already used deep; this makes the kickers
   agree with them. Corrected 23 Jul 2026. */
.kicker{
  font-size:11px;letter-spacing:.34em;text-transform:uppercase;
  color:var(--copper-deep);text-align:center;margin-bottom:22px;
}
h1.page{
  font-family:var(--serif);font-weight:400;
  font-size:clamp(30px,4.4vw,44px);line-height:1.25;
  text-align:center;color:var(--ink);
  max-width:760px;margin:0 auto 26px;
}
.rule{
  width:52px;height:1px;background:var(--copper);
  margin:0 auto 64px;
}
.standfirst{
  font-family:var(--serif);font-weight:400;
  font-size:clamp(19px,2.4vw,23px);line-height:1.7;
  text-align:center;max-width:640px;margin:0 auto 70px;
}

h2.section{
  font-family:var(--serif);font-weight:400;
  font-size:clamp(22px,3vw,28px);line-height:1.35;
  text-align:center;margin:0 0 18px;
}
.section-kicker{
  font-size:10.5px;letter-spacing:.32em;text-transform:uppercase;
  color:var(--copper-deep);text-align:center;margin:110px 0 16px;
}
.section-kicker:first-child{margin-top:0;}

/* quiet centred line used as a page's closing thought */
.envoi{
  margin-top:110px;text-align:center;
}
.envoi .line{
  font-family:var(--serif);font-size:clamp(18px,2.2vw,21px);
  line-height:1.7;max-width:560px;margin:0 auto 30px;
}
a.quiet{
  display:inline-block;
  font-size:10.5px;letter-spacing:.3em;text-transform:uppercase;
  color:var(--copper-deep);text-decoration:none;
  padding-bottom:7px;border-bottom:1px solid var(--sand);
  transition:border-color .4s ease,color .4s ease;
}
a.quiet:hover{border-color:var(--copper);color:var(--copper);}

/* ───────────────────────── home ─────────────────────────
   Full bleed, 23 July 2026, at Sofia's direction ("simple, not saying too
   much, appealing and intriguing"). The photograph is the whole first
   screen; the reversed ivory two-line wordmark, the line and the dateline
   sit on it, low; the nav reverses out over the top. This supersedes the
   ivory band-and-type register of 15 July 2026.

   Comp A (comps/home-a-full-bleed.html) showed this direction failing
   unscrimmed: type over the photograph's bright zones measured 44–85%
   sub-AA. What carries the type now is placement plus scrim, together:

   · The type block is anchored to the BOTTOM of the frame, over the empty
     foreground marble — the photograph's weakest region, so the scrim
     spends its fog where there is least to lose. The hands and the roses,
     the picture's subject, sit above the scrim's reach and stay clear.
   · Re-lit 24 Jul 2026, same day, again: Sofia looked at the live hero
     against her own colour edit (Images/Le Beau Monde Cover Photo Salon -
     two branded napkin sets soft colour v3.png) and said plainly "it's not
     the same, the colour is not the same." She was right, and it was not a
     processing bug — the derivatives carry no ICC profile, same as the
     source, so nothing was shifting colour on the way to the browser. It
     was this scrim: two full-width horizontal bands were washing large
     areas of the photograph that carry no type at all — the top third
     (nothing there but the nav, which is a fifth of that band's height)
     and the middle third (no text crosses it anywhere). Confirmed by
     measurement, not just by eye: at 1440×900 the bottom band's old 58%-up
     reach put real opacity (.43 at 40% up, .19 at 50% up) over the rose
     bowl and the glassware, well above where the wordmark's own top edge
     sits (≈30% up); the top band's 240px reach ran 190px past the nav's
     own row into bare wall and dark bags with nothing to legibly protect.
     Re-measured worst-pixel method unchanged — the real page, canvas-
     replayed with the exact rendered image (whichever srcset candidate the
     browser actually decoded) composited under the exact CSS gradient
     maths, worst pixel sampled across each element's own rendered
     rect (step 1px) against its computed text colour, ivory reversed
     wordmark artwork at 3:1 (non-text bar), the three genuine text
     elements at 4.5:1:
       — the empty two-thirds cost nothing to fix: the bottom band's
         cutoff moved from a %-of-viewport-height 58% to a fixed 410px
         from the bottom edge (px, not %, because the content block's own
         height is fixed in px — clamp()-based padding and static font
         sizes — while a %-of-H cutoff quietly drifts relative to it as H
         changes; more on that below), and the top band's cutoff moved
         from 240px to 150px. Both changes land entirely above the nav row
         and above the wordmark's own top edge, so at every width checked
         they moved all four figures below by exactly zero — this part was
         free.
       — the near-field opacities came down too, for real brightening
         right behind the type, not just in the empty zones: bottom from
         .88 at the edge / .58 at the old 34%-up stop, to .76 at the edge /
         .46 at a stop now pinned at 410−120=290px from the bottom (a
         fixed px offset, tracking the wordmark's own top edge rather than
         a fraction of whatever H happens to be); top unchanged at
         .82/.52 — see below for why.
     First attempt re-used the old %-of-H shape (34%/58%) merely scaled
     down and short-cut, and passed cleanly at 1440×900 and 1920×1080 — but
     failed outright at 1366×768 (wordmark 2.83:1, under its own 3:1 bar),
     one of the single most common laptop screens sold. Root cause: the
     content block's height is fixed in pixels (font sizes are static,
     the wordmark is a fixed-width image, only the padding-bottom breathes
     with svh and only within a 46–74px clamp), so its distance from the
     bottom edge is ~264–284px at every height tested from 768px to
     1080px — nearly constant — while a %-of-H stop drifts hard over that
     same range (31% of 768 is 238px; 31% of 1080 is 335px). At the
     shorter height the fixed-px content block sat further into the
     gradient's % scale than intended and lost its floor. Switching the
     stop itself to a fixed px offset (290px, tracking where the wordmark's
     own top edge actually falls, not a fraction of viewport height) fixed
     it at every height re-tested, including 1366×768. This is the same
     lesson as the top scrim's original 90px-from-top stop, which never had
     this problem because it was already anchored in px, not %.
     Worst pixel, current scrim, canvas-replay method, zero pixels under
     either bar at any width tested — desktop matrix 1280×800 through
     2560×1080 plus 1366×768 (the laptop case above): wordmark 3.72–4.79:1
     (bar 3:1), line 5.62–6.27:1, dateline 4.68–5.45:1, nav 5.64–7.18:1
     (all bar 4.5:1); tightest point overall is the wordmark at 700×900
     and 1440×900, 3.72–3.76:1, a real but comfortable margin over its
     3:1 floor (24–25%), and the dateline at 2560×1080, 4.68–5.01:1 across
     the two nearby a0 tunings tested (11% over its 4.5:1 floor at the
     value shipped). Mobile crop (60% 46%, see the 700px rule below)
     re-tested at 375×667, 375×812, 390×844, 430×932 and the 700×900
     hand-off point: wordmark 3.72–4.50:1, line 6.22–6.27:1, dateline
     5.24–5.55:1, nav 7.08–7.42:1 — all comfortably clear.
   · The top scrim's opacity is unchanged (.82 at the edge, .52 at 90px)
     because it turned out to have almost no room: it exists for the ivory
     nav, which crosses the photograph's white wall behind it, and every
     attempt to lighten those two values by even a little (tried down to
     .74/.44) dropped the nav under 4.5:1 at 1440×900. Only the reach —
     how far the scrim continues below the nav, where there is genuinely no
     text — was free to cut, from 240px to 150px. The honest fact to carry
     forward: the top third reads lighter now because 90px less of empty
     wall and bag is washed, not because the band behind the nav itself
     got any lighter. If the nav ever needs to read straight off the
     photograph with no scrim at all, that is a different crop or a
     different photograph, not a lever this gradient has left.

   Resolution: the 2634px native derivative (salon-hero-2600; since 24 Jul
   2026 the plate is salon-hero-final-2600, same native frame) was added for
   this screen — full bleed at 1440×900 binds on height, and the old
   2000px file rendered at 65% of retina; the native frame lifts that to
   86%. The true fix is still a commissioned landscape (see the shoot
   brief); this is the honest ceiling of the asset the club owns.

   SOURCE SWAP, 24 Jul 2026, same day, again. Sofia named the actual file:
   "Le Beau Monde Cover Photo Salon final.jpg" — her own finished Snapshot
   edit, not the "...soft colour v3.png" the morning's build had shipped
   from. Same photograph, same crop, dimensions confirmed identical
   (2634×1542) and face-safety re-verified at 1:1 on this exact file rather
   than assumed carried-over from v3. Measured ~17% brighter in mean RGB
   across the frame than v3 (117→122 mean luma; full figures in
   assets/imagery/PROVENANCE.md) — Sofia's own colour call, not a
   regression. The file carried an embedded Display P3 profile (Snapseed's
   default); converted to sRGB with a real ICC transform, not a naive
   profile strip, then the profile dropped so the derivative matches every
   other image on the site (checked: the naive strip understates warmth,
   R−B 31.2 vs the properly converted 36.5 — exactly the kind of quiet
   colour drift this asset has already been re-litigated over twice).

   Desktop crop (50% 75%, unchanged) re-verified by eye and by canvas-
   replay worst-pixel contrast against this brighter file at the full
   matrix — 1280×800, 1366×768, 1440×900, 1512×982, 1600×900, 1920×1080,
   2560×1080. Both napkins present at every width, none cut by the frame
   edge (same visual check as 23 Jul, repeated because "same crop" should
   never be assumed on a new source file without looking). Contrast held
   at every width with the scrim values below UNCHANGED: wordmark
   4.15–5.75:1 (bar 3:1), line 5.28–7.73:1 (bar 4.5:1), places 4.60–5.90:1
   (bar 4.5:1), nav 5.56–6.13:1 (bar 4.5:1). Worst point overall is places
   at 1920×1080, 4.60:1 — only 2.2% over its floor, thinner than the old
   file's equivalent margin (previously 4.68:1 at the same point) because
   the brighter source pushes the marble closer to the scrim's ceiling
   there. That is the honest answer to "can the scrim come down now the
   photo is brighter": on desktop, no — this is the binding constraint and
   there is no free lightening room left in the SHARED gradient below.
   Mobile is a different story (see the media-query comment below): its
   margin on this same shared scrim is enormous (7.83–14.14:1), because
   its object-position sits over calmer, more even parts of the frame. A
   mobile-only lighter scrim was tried as a measurement exercise (not
   shipped): even a moderate reduction (top .60/.35/150, bottom
   .50/.28/380) pushed line to 4.97:1 at 430×932 and nav to 4.79:1 at
   375×812 — both still technically clear but with a thinner margin than
   feels safe for a value tuned by eye rather than re-proven per device,
   so it was left alone rather than shipped as a drive-by addition to a
   brief that was actually about the napkin. Flagged for Sofia as a
   separate, deliberate pass if she wants it.

   RECALIBRATION, 24 Jul 2026, later the same day — "more matte colour and
   less yellow." This is the request that resolved the flag two paragraphs
   up (adopt final.jpg's own tones as the new benchmark, re-deriving the
   tone-map floor). Full numeric before/after lives in tools/grade.py's own
   header and assets/imagery/PROVENANCE.md; the short version: warmth cut
   (R−B +36.7 → +23.0 on the hero), contrast eased (luma std 51.8 → 44.8),
   blacks lifted further off the floor (p1 23.4 → 38.5) and highlights
   rolled off a touch more (p99 204.8 → 195.9) — the combination that reads
   as matte rather than glossy. The hero itself was re-graded for the first
   time (previously resize/encode only; this instruction explicitly
   supersedes that rule for this one request) and every other graded photo
   on the site was re-run through the same recalibrated grade() to match.

   Re-verified worst-pixel contrast against the new, flatter hero at the
   same full matrix as the source-swap pass above, scrim values UNCHANGED:
   wordmark 5.11–6.23:1 (bar 3:1), line 6.36–6.73:1 (bar 4.5:1), places
   5.53–5.90:1 (bar 4.5:1), nav 6.25–8.51:1 (bar 4.5:1) across
   1280×800–2560×1080; mobile 375×667–700×900 comfortably clear at
   5.71–7.51:1 across all four. Every figure holds a WIDER margin than the
   source-swap pass above (worst point overall is now places at 2560×1080,
   5.53:1, 23% over floor, versus that pass's 4.60:1, 2.2% over) — a
   flatter, less contrasty photograph puts less bright specular hot spots
   directly behind the type, so this recalibration made the scrim's job
   easier, not harder. The scrim gradient itself was left unchanged; there
   was nothing to retune.

   SECOND SOURCE SWAP, 24 Jul 2026, same day, again — Sofia said the hero
   was "still not good" and supplied `Le Beau Monde Cover Photo Salon
   final 1.jpg` (the old `...final.jpg` was already gone from disk). Full
   derivation and judgment call (ungraded-but-converted vs HERO_GRADE,
   which was chosen and why) in assets/imagery/PROVENANCE.md, "Second
   source swap" section, and in index.html's own comment above .bleed.
   Short version: the new file, colour-converted only, still read glossy
   and warm (R−B +31.0, p1 3.9) — materially the same problem as before,
   not a hand-corrected export — so HERO_GRADE was applied unchanged.

   Legibility re-run this pass **live in the browser** rather than
   simulated offline: a script drew the actual rendered `.hero-plate` to a
   canvas, replicated the live `object-fit:cover`/`object-position` crop
   math, composited these two scrim gradients exactly as specified below,
   and sampled the worst pixel per element across the same full matrix
   (desktop 1280×800–2560×1080, mobile 375×667–700×900). Every figure
   clears both bars at every width, zero pixels under: wordmark 4.63–4.99:1
   desktop / 4.63–5.33:1 mobile (bar 3:1); line 6.47–6.72:1 desktop /
   6.48–7.23:1 mobile; places 5.82–6.34:1 desktop / 6.56–6.77:1 mobile;
   nav 6.09–6.74:1 desktop / 6.87–6.91:1 mobile (bar 4.5:1 for the latter
   three). Worst point overall is wordmark at 1920×1080/430×932 (4.63–
   4.65:1, 54–55% over its 3:1 floor); tightest of the four is places at
   1920×1080 (5.82:1, 29% over its 4.5:1 floor). Slightly tighter on
   wordmark than the previous (old-source) HERO_GRADE pass recorded just
   above (5.11–6.23:1) because the new source's raw warmth was already
   lower before grading (R−B 31.0 vs the old source's 36.5), which shifts
   the post-grade luminance distribution a little — still a comfortable
   margin at every width tested, so **no scrim retune was needed.**

   THIRD PASS ON final 1.jpg, 24 Jul 2026, same day: HERO_GRADE RETIRED
   FOR THIS IMAGE. Sofia, directly: the graded hero above reads too pale
   next to the actual photograph she sent; ship the file as sent instead.
   Same source file, no new send; the instruction is about the
   processing (HERO_GRADE: contrast x0.88, saturation x0.85, tone map
   24-238), not the file. Fifth round on this image today; HERO_GRADE
   dropped rather than recalibrated again. Shipped derivatives are the
   Display P3-to-sRGB managed conversion only (Pillow ImageCms.
   profileToProfile, relative colorimetric, profile dropped after),
   resized to the same ladder, no grade.py pass applied. Full derivation,
   before/after numbers and the naive-strip check in
   assets/imagery/PROVENANCE.md, "Third pass on final 1.jpg", and in
   index.html's comment above .bleed.

   Legibility re-run against this brighter, higher-contrast file, same
   canvas-replay worst-pixel method, same full desktop (1280x800-
   2560x1080) and mobile (375x667-700x900) matrix, SCRIM VALUES UNCHANGED:
   every figure clears its bar at every width, zero pixels under, though
   with narrower margins than the HERO_GRADE pass above (a livelier image
   puts brighter specular hot spots under some sample points). Worst
   points: wordmark 4.38:1 desktop (2560x1080, bar 3:1, 46% over) / 6.96:1
   mobile (375x812); line 5.51:1 desktop (2560x1080, bar 4.5:1) / 7.07:1
   mobile (430x932); places 5.10:1 desktop (1920x1080, bar 4.5:1, 13%
   over -- the tightest of the four, still clear) / 7.01:1 mobile
   (390x844); nav 5.63:1 desktop (1440x900, bar 4.5:1) / 6.41:1 mobile
   (375x667). No retune performed -- the gradient stops below are exactly
   as they were for the HERO_GRADE pass; the brighter file simply has less
   headroom to spend, not a deficit to fix. */

.bleed{
  position:relative;
  height:100svh;min-height:540px;
  overflow:hidden;background:var(--espresso);
}
.bleed .hero-plate{
  position:absolute;inset:0;
  width:100%;height:100%;object-fit:cover;
  /* 75%: Sofia pointed at this framing directly on 24 Jul 2026 — both
     embossed napkin sets, not just the hands and roses. At this aspect the
     crop is bound by height, not width, so both napkins (native frame
     x≈30–38% and x≈68–77%) are always in the visible slice horizontally;
     what 42% cost was vertical — on wide-short windows (ultrawide monitors,
     ≥~21:9) it cropped low enough to lose the right-hand napkin off the
     bottom edge entirely. 75% biases the vertical crop to the bottom of the
     frame instead: it still gives up the top of the room (handbags,
     dimmed by the top scrim regardless) but keeps the hands, both rose
     bowls and both napkins in the visible window even at 2560×1080.
     Verified by simulating the exact object-fit:cover crop at 1440×900,
     1512×982, 1920×1080 and 2560×1080 on 24 Jul 2026: both napkins present
     at every size, none cut by the frame edge. */
  object-position:50% 75%;
}
.bleed .scrim{
  position:absolute;inset:0;
  background:
    linear-gradient(180deg, rgba(38,34,32,.82) 0, rgba(38,34,32,.52) 90px, rgba(38,34,32,0) 150px),
    linear-gradient(0deg, rgba(38,34,32,.76) 0, rgba(38,34,32,.46) 290px, rgba(38,34,32,0) 410px);
}
.bleed .content{
  position:absolute;left:28px;right:28px;bottom:0;
  text-align:center;
  padding-bottom:clamp(46px,7svh,74px);
}
.bleed .mark img{width:min(300px,66vw);height:auto;margin:0 auto;}
.bleed .line{
  font-family:var(--serif);font-weight:400;color:var(--ivory);
  font-size:clamp(17px,2vw,21px);line-height:1.7;
  max-width:520px;margin:30px auto 0;
}
.bleed .places{
  font-size:10px;letter-spacing:.34em;text-transform:uppercase;
  color:rgba(252,249,247,.85);margin-top:26px;
}
.bleed .places .sep{color:var(--copper-mid);padding:0 11px;}
.nw{white-space:nowrap;}

@media(max-width:700px){
  /* SOLVED, 24 Jul 2026, second pass. Sofia said plainly she wants the
     napkin visible on mobile — not a rose bowl standing in for it. The
     first pass (below, for the record) gave it up; this one does not.

     The geometry, established without guessing: a landscape frame in a
     portrait viewport keeps about a quarter of its width (window_frac ≈
     container_aspect/image_aspect ≈ 0.27, essentially constant across
     375–430px — every real phone width has close to the same aspect
     ratio) and — because the container is always bound by HEIGHT at this
     aspect pairing, never by width — the FULL height of the frame is
     always shown; object-position's y term does nothing here (confirmed
     by computing sy/sh directly in-browser: sy=0, sh=natH at every width
     tried). That means a napkin's SCREEN band is fixed by where it sits
     in the photograph, not by any CSS choice, and — critically — BOTH
     napkins sit at almost the same native y (left 0.780–0.871, right
     0.777–0.894: same tabletop, same camera height), so switching which
     napkin is in view was never going to dodge the type block on its own.

     What actually changed the outcome: the type block is not one solid
     band. Measured its real sub-rects at 375×812 (getBoundingClientRect,
     not eyeballed): wordmark image 569–652px, then a TRUE GAP 652–682px
     (nothing painted there at all), then "the line" 682–711px, another
     true gap 711–737px, then "places" 737–755px. The right-hand napkin at
     78% put its whole band (screen y≈631–726) across all of that with no
     regard for the gaps. The LEFT-hand napkin (native x 0.285–0.426) sits
     at nearly the same y (screen y≈633–707 at 375×812) — but critically,
     because it's a few points higher and the same height, a meaningfully
     larger share of it lines up with the wordmark/gap/line structure
     rather than sitting dead-center under "the line" the way the right
     one did. Solved by moving object-position to 30% 46% (was 60% 46%
     for the rose-bowl compromise, 78% 46% for the rejected first
     attempt) — this puts the LEFT napkin's screen band mostly into the
     wordmark's own lower edge and the true gap beneath it, only grazing
     "the line" at the very narrowest width tested. Result, by width:

       375×812  — napkin sits just under "MONDE", its top edge grazing the
                  wordmark's own bottom and the very top of "Rooms where
                  conversation is the occasion."; both remain fully
                  legible (see figures below). The one width where the
                  napkin doesn't clear the text outright, and it still
                  reads as a napkin, not a fragment.
       390×844, 414×896, 430×932, 700×900 — napkin sits cleanly in the gap
                  between the wordmark and "the line", touching neither.
                  Confirmed by screenshot at all four; this is the common
                  case, not the edge case.

     This is a real, if partial, win, not a full clean separation at
     every width — logged honestly rather than rounded up. A dedicated
     mobile-only crop (baking a portrait aspect straight from the source
     rather than relying on object-fit:cover of the same landscape file)
     was considered and rejected: to get the napkin's y-band clear of the
     type at 375×812 by baking the crop instead of positioning it would
     need keeping only the bottom ~35–37% of the frame's height, which at
     matching mobile aspect leaves a native width of roughly 250–260px —
     below even 1x for a 375px screen and a real, visible soften on
     retina, on the one asset (the embossed lettering) this whole exercise
     is trying to show clearly. Not worth trading resolution for.

     Contrast re-proven at every width against the ACTUAL brighter source
     (not assumed from the desktop pass), worst-pixel canvas-replay
     method, same as desktop: 375×812 wordmark 8.98:1 / line 9.65:1 /
     places 10.74:1 / nav 9.33:1; 375×667 9.42 / 9.58 / 9.82 / 9.44;
     390×844 8.83 / 12.36 / 10.72 / 9.33; 414×896 8.23 / 13.48 / 10.85 /
     11.33; 430×932 7.83 / 14.14 / 10.86 / 12.25; 700×900 6.77 / 14.04 /
     10.74 / 13.12 — bars are 3:1 (wordmark, non-text) and 4.5:1 (line,
     places, nav); every figure clears its bar by a wide margin at every
     width tested, tightest is wordmark at 700×900 (6.77:1, still 126%
     over floor). This margin is enormous next to desktop's (tightest
     4.60:1) because the object-position here sits over calmer table
     surface rather than the busier upper room — not because the mobile
     scrim is doing more work. See the dated addendum above the shared
     ".bleed .scrim" rule for why that headroom wasn't spent lightening
     the (shared) scrim in this pass.

     FIRST PASS, 24 Jul 2026, morning — kept for the record, not live.
     First cut was 78% (right-hand napkin whole in the crop). Because a
     portrait viewport never crops this plate's height, the napkin —
     native y≈78–90% — always lands at screen y≈78–90%, and the type
     block (treated then as one solid span, 70–93% at 375×812) looked
     like it covered the napkin's entire band with no daylight in it.
     Reset to 60%: gave up the napkin rather than show it crossed, and
     showed the front rose bowl instead. That was a real fix for
     legibility but not what Sofia asked for, which is why this pass
     went back and read the type block's actual sub-rects instead of
     treating it as one block — the gaps were there all along.

     THIRD PASS, 24 Jul 2026, afternoon. Sofia corrected the brief again:
     not this napkin, the OTHER one — the right-hand napkin, because it
     sits beside the front rose bowl, and she wants the flowers in frame
     too, not the napkin alone. Cropped the source directly to confirm
     the target before touching any CSS: right napkin at native x
     0.66–0.82, rose bowl beside it at native x 0.55–0.68. Combined
     window worth keeping: x 0.55–0.82, centred x≈0.685.

     Because the container is height-bound at every mobile width tried
     (confirmed again: window_frac_w ≈ 0.270–0.271 at 375/390/414/430,
     window_frac_h = 1.0 — full frame height always shown, so the y term
     is still provably inert, same as the second pass), the visible
     x-window is (1 − window_frac) × (X/100) to that plus window_frac.
     Solving for a visible start of 0.55 (so the window runs 0.55–0.82,
     matching the combined region almost exactly) gives X ≈ 75% at every
     width in this range. Set to 75% 46% — the y term is carried over
     unchanged since it does nothing here; changing it would be a no-op.

     Verified against real screenshots and getBoundingClientRect, not
     assumed from the source-file geometry alone (an early hand-derived
     estimate using the left napkin's documented native y as a stand-in
     for the right one predicted a full collision with "the line" — that
     estimate was wrong and is not what ships; this is the corrected,
     measured account). Both rose bowls are fully in frame and fully
     clear of every type element at all four widths — the only overlap
     is the front bowl's glass foot grazing the wordmark's own top edge,
     which is cosmetic (the wordmark is letterspaced strokes on a
     transparent ground, plenty of daylight between glyphs).

     The napkin's actual screen band, read directly off zoomed crops at
     each width (not inferred): its two text rows sit almost entirely in
     the true gap between the wordmark and "the line" —
       375×812  — "LE BEAU" (≈663–675px) fully clear; "MONDE" (≈678–690px)
                  has its bottom third (≈682–690, 8 of ~12px) under the
                  top of "the line" (682–711) — a partial graze of the
                  second word only, not the whole napkin, and legible.
       390×844  — "LE BEAU" clear; "MONDE" grazes "the line"'s top edge
                  by ≈3px — effectively clear.
       414×896  — "LE BEAU" clear; "MONDE" grazes by ≈2.5px — effectively
                  clear.
       430×932  — both words sit entirely inside the gap. Fully clear.
     Worst case is the narrowest width, same pattern as the second pass:
     one width carries a small, real graze; the rest are clean. Nothing
     here needed a dedicated portrait crop (the second pass's rejected
     option, on resolution grounds) — the gap does the work on its own.

     What the second pass's margin does NOT carry over: wordmark contrast
     is markedly tighter with this crop, because the brighter rose-bowl
     glass and the mirrored tissue box now sit directly behind the logo
     instead of "calmer table surface". Re-measured, worst-pixel
     canvas-replay against this exact crop: wordmark 3.51:1 (375×812),
     3.51:1 (390×844), 3.39:1 (414×896), 3.26:1 (430×932) against its 3:1
     floor — every figure clears, but by 9–17%, not the 60–160% margin
     the left-napkin crop had. Swept x±5–10% either side of 75% at the
     tightest width (430×932): wordmark holds in a narrow 3.16–3.37 band
     across the whole range, confirming this is the region's own
     brightness, not a fixable side-effect of the exact offset — nudging
     x doesn't buy the margin back without cropping the rose bowl or the
     napkin out of frame. line/places/nav keep comfortable margins
     throughout: line 5.43–5.69:1, places 5.30–5.47:1, nav 6.18–6.21:1,
     all against 4.5:1. Flagged for Sofia: the wordmark's contrast floor
     is real but thin on this crop; if she wants more headroom back the
     lever is the shared scrim, not this object-position. */
  .bleed .hero-plate{object-position:75% 46%;}
  .bleed .content{left:22px;right:22px;}
}

/* ─────────────────── the evening register (home) ───────────────────
   One espresso band below the fold: what the club is, three entries, and
   the canonical line. Espresso is the brand's evening register and the
   footer already speaks it; the page closes dark from here down. Copper
   on espresso is copper-mid — core computes 4.66:1 here and mid 5.6:1,
   and the footer's hovers already chose mid. copper-deep never sits on
   espresso (1.45:1). */

.evening{
  background:var(--espresso);
  border-bottom:1px solid rgba(252,249,247,.12);
  padding:130px 28px 120px;text-align:center;
}
.evening .statement{
  font-family:var(--serif);font-weight:400;color:var(--ivory);
  font-size:clamp(19px,2.4vw,25px);line-height:1.85;
  max-width:660px;margin:0 auto;
}
.evening .entries{
  max-width:600px;margin:96px auto;
  border-top:1px solid rgba(252,249,247,.14);
}
.evening .entries a{
  display:block;text-decoration:none;
  padding:36px 6px;
  border-bottom:1px solid rgba(252,249,247,.14);
}
.evening .entries .t{
  display:block;
  font-size:11px;letter-spacing:.3em;text-transform:uppercase;
  color:var(--copper-mid);transition:color .4s ease;
}
.evening .entries .d{
  display:block;
  font-family:var(--serif);color:rgba(252,249,247,.78);
  font-size:clamp(16px,1.9vw,18px);line-height:1.7;
  margin-top:12px;transition:color .4s ease;
}
.evening .entries a:hover .t{color:var(--ivory);}
.evening .entries a:hover .d{color:rgba(252,249,247,.95);}
.evening .canon{
  font-family:var(--serif);color:var(--ivory);
  font-size:clamp(18px,2.2vw,22px);line-height:1.7;
  max-width:560px;margin:0 auto 32px;
}
.evening a.quiet{color:var(--copper-mid);border-color:rgba(252,249,247,.22);}
.evening a.quiet:hover{color:var(--ivory);border-color:var(--copper-mid);}
@media(max-width:700px){
  .evening{padding:96px 22px 90px;}
  .evening .entries{margin:76px auto;}
}

/* ───────────────────────── plates (interior imagery) ─────────────────────
   One photograph per page, doing real work — never a gallery.

   Aspect decides the treatment, and the archive decides the aspect. Every
   frame the consent rule clears is a portrait cut out of a landscape
   original — the member faces are in the width, so the crop throws the width
   away (900×1597, 1200×1600, 1600×2133, 1200×1254). A 3:4 portrait bled edge
   to edge across a 1280×800 screen is a ~40% horizontal slice: it cuts the
   subject in half, and the 900px-wide frame would upscale 1.42× besides.
   So the plate is bled where the asset can carry it and placed where it
   cannot:

     · mobile  — full bleed, edge to edge, whole frame, nothing cropped. The
                 portraits are native at this width, and this is where the
                 site is actually read.
     · desktop — the frame placed whole on the ivory ground, large, centred,
                 nothing cropped and nothing upscaled. BRAND.md: "every image
                 must sit comfortably on the ivory ground."

   The homepage hero is the exception, and it is the same fact seen from the
   other side: salon-hero is the only landscape frame the archive can clear,
   so it is the only image on the site that bleeds on a desktop screen.
   Commissioning true landscapes and true verticals is the first argument in
   Brand Kit/Briefs/Photography Shoot — Production Brief.md.
   ────────────────────────────────────────────────────────────────────────── */

figure.plate{
  /* main carries 28px of side padding; cancelling it lets the plate reach the
     edge without a 100vw rule (which would overflow by the scrollbar width) */
  margin:96px -28px;
  text-align:center;
}
figure.plate img{
  max-width:min(640px,100%);
  max-height:min(82svh,760px);
  width:auto;height:auto;
  margin:0 auto;
}
figure.plate:first-child{margin-top:0;}

@media(max-width:700px){
  figure.plate{margin:64px -22px;}
  figure.plate img{max-width:none;max-height:none;width:100%;}
  figure.plate:first-child{margin-top:0;}
}

/* ───────────────────────── the lead ──────────────────────────────────────
   The page's photograph and the page's proposition share the first screen.
   The frame is held to the right viewport edge and runs from under the
   masthead to the fold; the kicker, the title, the rule and the standfirst
   are set left against it in the field beside it. Both are in view at
   1440×900 without scrolling. This replaces the arrangement of 15 July
   2026 — frame centred on the ivory ground with the type stacked beneath —
   which put the kicker at 1028 and the h1 at 1070 on a 900px screen, and
   left the first screen with no words in it at all.

   THE FRAME'S WIDTH IS NOT A DESIGN CHOICE. It is the asset's own aspect
   at the height available, and it is always a downscale — never an upscale,
   never a crop through the subject. On a 900px screen the fold is 816px
   away, so:
       salons     900×1597 (0.564:1) → 460px wide — 32% of 1440
       philosophy 1600×2133 (0.750:1) → 612px wide — 43%
       cities     1200×1254 (0.957:1) → 662px wide (46vw cap) — 46%
   A 0.564:1 portrait cannot be made *wide* on a 900px-tall screen without
   cutting through the subject. So it is made *tall* and *anchored*
   instead, and the type is set against it: a frame at 32% of the width and
   90% of the height, flush to an edge, with the proposition in the field
   beside it, is a composition. The same frame at 29%, centred, with
   nothing beside it, was a stamp. The width is the asset's ceiling, and it
   is the argument for the shoot — see the report of 15 July 2026 and
   Brand Kit/Briefs/Photography Shoot — Production Brief.md.

   Below 1024px the whole thing dissolves: .lead and .field go display:block
   and the markup — figure, kicker, h1, rule, standfirst, in that source
   order — renders exactly as it did before. The frame is on the right at
   desktop by `order`, not by source, so nothing about the reading order or
   the small-screen stack depends on this component existing.
   ────────────────────────────────────────────────────────────────────── */

/* The lead's frame meets the masthead at every width — main's top padding is
   the frame's to spend. At desktop this is what lets the frame run the first
   screen; at 375×812 it is worth 80px, which moves the kicker from 871 (below
   the fold) to 791 (above it). Outside the media query below because it is
   true of the stacked page too, where an image flush under the masthead reads
   as deliberate and 80px of ivory above it reads as a gap. */
main.has-lead{padding-top:0;}

@media(min-width:1024px){
  .lead{
    display:flex;align-items:flex-start;
    gap:clamp(40px,5vw,80px);
    margin-right:-28px;              /* cancel main's padding: reach the edge */
  }

  .lead .field{
    order:1;flex:1 1 auto;min-width:0;
    display:flex;flex-direction:column;justify-content:center;
    min-height:var(--first);
    /* The type starts on the masthead's left edge, exactly, at every width —
       the frame is flush to the viewport, but the words belong to the page's
       measure, and a title that starts 162px to the left of the nav above it
       is not a composition, it is two grids.
         The masthead is max-width:1060 centred inside main's 28px padding, so
       its left edge sits (W − 1060)/2 into main's content box (W). A padding
       percentage on a flex item resolves against the flex container's content
       width, and .lead is main's width + the 28px it reaches back:
         50% − 544px  =  (W+28)/2 − 544  =  W/2 − 530  =  (W − 1060)/2.
       Deliberately not `(100vw − 1060px)/2`: vw includes the scrollbar, which
       the masthead's centring does not, so that form drifts by half a
       scrollbar wherever the scrollbar is not an overlay. This one cannot. */
    padding:40px clamp(0px,3vw,48px) 40px max(0px, 50% - 544px);
  }

  .lead .frame{
    order:2;flex:0 0 auto;margin:0;
    /* WIDTH is the computed dimension and height follows from aspect-ratio —
       not the other way round. Sizing by `height` and clamping with
       `max-width` makes both dimensions definite, at which point CSS drops
       aspect-ratio and object-fit:cover quietly crops the difference: it
       rendered cities at 662×816 (0.81:1) off a 0.957:1 plate, cutting 15%
       off the chandelier's sides. Driving width keeps exactly one free
       dimension, so the box always holds the asset's own aspect and cover
       never has anything to cut.
         Three ceilings, whichever binds first:
           --first × --arv  the fold — the frame runs the first screen
           46vw             keeps a near-square plate (cities) from taking
                            the field away from the type
           --nat-w          the asset's true pixel width: the hard stop that
                            makes upscaling structurally impossible
       At 1440×900: salons 460 (fold binds), philosophy 612 (fold),
       cities 662 (46vw binds → the frame shortens to 692 tall and stops
       above the fold, because it is square, not because it was trimmed). */
    width:min(calc(var(--first) * var(--arv)), 46vw, var(--nat-w));
    aspect-ratio:var(--ar);
    height:auto;
  }
  .lead .frame img{
    width:100%;height:100%;object-fit:cover;
    object-position:var(--op,50% 50%);
    max-width:none;max-height:none;
  }

  /* The lead's field is min-height:var(--first), so the lead closes exactly
     on the fold and whatever follows would otherwise start hard against it.
     main.has-lead gave up its 110px of top padding to the frame; the rule
     below hands that 110px back to the first thing after the lead. Scoped
     through main.has-lead so it outranks the components' own margins
     (.register carries margin:70px auto 0) without touching their `auto`. */
  main.has-lead .lead + *{margin-top:110px;}

  .lead .kicker{text-align:left;margin-bottom:20px;}
  .lead h1.page{
    text-align:left;max-width:none;margin:0 0 26px;
    font-size:clamp(34px,3.4vw,48px);
  }
  .lead .rule{margin:0 0 36px;}
  .lead .standfirst{
    text-align:left;margin:0;max-width:560px;
    font-size:clamp(18px,1.5vw,21px);
  }
}

/* ───────────────────────── lists & registers ───────────────────────── */

.register{
  max-width:680px;margin:70px auto 0;
  border-top:1px solid var(--sand);
}
.register .entry{
  padding:44px 6px;border-bottom:1px solid var(--sand);
}
.register .entry h3{
  font-size:12px;font-weight:400;letter-spacing:.26em;text-transform:uppercase;
  color:var(--copper-deep);margin-bottom:14px;
}
/* A register may now carry heading-only entries (the Young Circle's
   Formation list, cut to its headings on 23 Jul 2026); the heading's
   margin was for the line beneath it, so it goes when nothing follows. */
.register .entry h3:last-child{margin-bottom:0;}
.register .entry:has(> h3:only-child){padding:32px 6px;}
.register .entry p{max-width:600px;}
.register .entry .note{
  font-size:13.5px;color:var(--ink-soft);margin-top:12px;
}
/* Added 15 July 2026 for privacy.html — the first page that has had to put two
   paragraphs, or a link, inside an entry. Both are additive: no register entry
   built before today contains either, so nothing already shipped moves.
   `.note` keeps its own 12px — three classes beat two classes and two elements. */
.register .entry p + p{margin-top:22px;}
.register .entry a{
  color:var(--copper-deep);text-decoration:none;
  border-bottom:1px solid var(--sand);
  transition:border-color .4s ease,color .4s ease;
}
.register .entry a:hover{border-color:var(--copper);color:var(--copper);}

.roll{
  text-align:center;max-width:760px;margin:66px auto 0;
}
.roll .vk{
  font-size:10.5px;letter-spacing:.3em;text-transform:uppercase;
  color:var(--ink-soft);margin-bottom:24px;
}
.roll .names{
  font-family:var(--serif);font-size:clamp(16px,2vw,19px);line-height:2.2;
}
.roll .names span{white-space:nowrap;}
/* 9px + the collapsed newline on each side ≈ the 13px this carried when the
   spans were set back-to-back with no break opportunities between them. */
.roll .names .dot{color:var(--copper);padding:0 9px;}

/* ───────────────────────── cities ───────────────────────── */

.cities{max-width:680px;margin:0 auto;border-top:1px solid var(--sand);}
.city{padding:54px 6px;border-bottom:1px solid var(--sand);}
.city h2{
  font-family:var(--serif);font-weight:400;font-size:24px;margin-bottom:6px;
}
.city .status{
  font-size:10.5px;letter-spacing:.28em;text-transform:uppercase;
  color:var(--copper-deep);margin-bottom:18px;
}
.city p{max-width:600px;}

/* ───────────────────────── journal ───────────────────────── */

.journal-list{max-width:680px;margin:0 auto;border-top:1px solid var(--sand);}
.journal-list .essay{border-bottom:1px solid var(--sand);}
.journal-list .essay a{
  display:block;padding:46px 6px;text-decoration:none;
  transition:color .4s ease;
}
.journal-list .essay a:hover h2{color:var(--copper-deep);}
.journal-list .essay .date{
  font-size:10.5px;letter-spacing:.28em;text-transform:uppercase;
  color:var(--ink-soft);margin-bottom:12px;
}
.journal-list .essay h2{
  font-family:var(--serif);font-weight:400;font-size:24px;
  margin-bottom:12px;transition:color .4s ease;
}
.journal-list .essay p{max-width:600px;color:var(--ink-soft);}
.journal-note{
  text-align:center;font-size:13.5px;color:var(--ink-soft);margin-top:52px;
}

article.essay-body{max-width:620px;margin:0 auto;}
article.essay-body .date{
  font-size:10.5px;letter-spacing:.3em;text-transform:uppercase;
  color:var(--ink-soft);text-align:center;margin-bottom:22px;
}
article.essay-body h1{
  font-family:var(--serif);font-weight:400;
  font-size:clamp(28px,4vw,38px);line-height:1.3;
  text-align:center;margin-bottom:26px;
}
article.essay-body p{margin-bottom:26px;}
article.essay-body .signoff{
  margin-top:44px;text-align:center;
  font-size:11px;letter-spacing:.3em;text-transform:uppercase;
  color:var(--copper-deep);
}

/* ───────────────────────── nominations ───────────────────────── */

form.nomination{max-width:520px;margin:70px auto 0;}
form.nomination label{
  display:block;font-size:10.5px;letter-spacing:.26em;text-transform:uppercase;
  color:var(--ink-soft);margin:30px 0 10px;
}
form.nomination input,
form.nomination textarea{
  width:100%;font-family:var(--sans);font-weight:300;font-size:16px;
  color:var(--ink);background:var(--white);
  border:1px solid var(--sand);border-radius:0;
  padding:15px 16px;-webkit-appearance:none;
  transition:border-color .4s ease;
}
form.nomination input:focus,
form.nomination textarea:focus{outline:none;border-color:var(--copper);}
form.nomination textarea{min-height:130px;resize:vertical;}
form.nomination button{
  display:block;margin:48px auto 0;
  font-family:var(--sans);font-size:11px;letter-spacing:.3em;text-transform:uppercase;
  color:var(--ivory);background:var(--espresso);
  border:1px solid var(--espresso);padding:17px 46px;cursor:pointer;
  transition:background .4s ease,border-color .4s ease;
}
form.nomination button:hover{background:var(--copper-deep);border-color:var(--copper-deep);}
.confidence{
  font-size:13px;color:var(--ink-soft);text-align:center;margin-top:30px;
}

/* ───────────────────────── footer ───────────────────────── */

footer.site{
  background:var(--espresso);color:rgba(252,249,247,.72);
  padding:84px 28px 68px;text-align:center;
}
footer.site .mark img{height:34px;width:auto;margin:0 auto 40px;}
footer.site p{
  font-size:10.5px;letter-spacing:.24em;text-transform:uppercase;line-height:2.6;
}
footer.site a{color:rgba(252,249,247,.85);text-decoration:none;transition:color .4s ease;}
footer.site a:hover{color:var(--copper-mid);}

/* Footer wayfinding: the section list, shown only where the masthead has
   given it up (≤700px). On desktop the masthead carries it and repeating
   it here would be noise. */
nav.footer-nav{display:none;}
@media(max-width:700px){
  nav.footer-nav{
    display:flex;flex-direction:column;align-items:center;gap:18px;
    margin:0 auto 44px;padding-bottom:40px;
    border-bottom:1px solid rgba(252,249,247,.12);
    max-width:280px;
  }
  nav.footer-nav a{
    font-size:10.5px;letter-spacing:.28em;text-transform:uppercase;
    color:rgba(252,249,247,.72);text-decoration:none;
  }
}
footer.site .legal{
  font-size:10.5px;letter-spacing:.05em;text-transform:none;
  color:rgba(252,249,247,.42);margin-top:30px;line-height:2.1;
}
/* The privacy link lives in the legal line, not the footer nav: nav.footer-nav
   is display:none above 700px, and this link has to resolve from every page at
   every width (Theo's ruling §7.1 — it is the Art 13 route for the nominator).
   Toned to the legal register but underlined, because a notice nobody can find
   is not a notice. It must stay brighter than the text around it. */
footer.site .legal a{
  color:rgba(252,249,247,.66);
  border-bottom:1px solid rgba(252,249,247,.20);
  padding-bottom:2px;
  transition:color .4s ease,border-color .4s ease;
}
footer.site .legal a:hover{color:var(--copper-mid);border-color:var(--copper-mid);}

/* ───────────────────────── motion ───────────────────────── */

@keyframes veil-in{from{opacity:0;}to{opacity:1;}}
@keyframes rise-in{from{opacity:0;transform:translateY(12px);}to{opacity:1;transform:none;}}
/* The hero drift (sanctioned 23 Jul 2026, Sofia — BRAND.md, Website >
   Motion): the homepage hero image scales 1.0 → 1.04 over 30s, ease-out,
   runs ONCE to completion and holds. Nothing else on the site moves.
   .bleed exists on the home page only and has overflow:hidden, so the 4%
   never escapes the frame. Reduced motion: the block below already sets
   animation:none on .hero-plate, which stops the drift with the fades. */
@keyframes hero-drift{from{transform:scale(1);}to{transform:scale(1.04);}}

.bleed .mark{animation:veil-in 1.1s ease both;}
.bleed .hero-plate{animation:veil-in 1.4s ease both, hero-drift 30s ease-out both;}
.fade-1{animation:rise-in .8s ease .5s both;}
.fade-2{animation:rise-in .8s ease .8s both;}
.fade-3{animation:rise-in .8s ease 1.1s both;}

@media (prefers-reduced-motion: reduce){
  .bleed .mark,.bleed .hero-plate,.fade-1,.fade-2,.fade-3{animation:none;}
  html{scroll-behavior:auto;}
}
