/* ==========================================================================
   Jennifer Kizzee Design
   Site stylesheet. Built against the JKD Brand Operating System (CLAUDE.md).

   Rules this file enforces:
   - Exact brand color values only. Never invent or approximate. (BOS 2.1)
   - Linen is the default warm ground, not pure white. (BOS 2.1)
   - Dominant pair is Deep Gray + Steel Blue on Linen. (BOS 2.1)
   - Gold is RARE. Monogram and selective accents only. Never a large fill. (BOS 2.1)
   - Photos are full-bleed, sharp corners. No radius, no border, no frame,
     no drop shadow, no gradient or color overlay on a photo. (BOS 1.5, 1.6, 4.7)
   - Photos appear two ways only: full-bleed background, or a clean left-side
     vertical rectangle with text on the right. Never a thin banner strip. (BOS 4.6)
   - Labels and buttons are all caps with extreme tracking. (BOS 2.2)

   DISPLAY FONT
   Brand display face is Modny Light (Monotype). The license in the brand
   folder is a desktop EULA and may not cover webfont embedding, so the stack
   falls back to the web fallback the Brand OS specifies: Cormorant Garamond.
   To switch to the real face once a web license is confirmed, uncomment the
   @font-face block and drop ModnyLight.woff2 into /assets/fonts/.
   ========================================================================== */

/* Fonts are linked from each page's <head>, not imported here.
   An @import inside CSS serialises the request chain: HTML, then site.css,
   then the font CSS, then the font files. Linking in the head lets the
   preload scanner start the font CSS at the same time as this file. */

/*
@font-face {
  font-family:'Modny Light';
  src:url('/assets/fonts/ModnyLight.woff2') format('woff2');
  font-weight:300; font-style:normal; font-display:swap;
}
*/

:root{
  /* Brand color. Exact values from BOS 2.1. Do not add to this list. */
  --jkd-deep-gray:#373737;
  --jkd-stone:#909293;
  --jkd-white:#FFFFFF;
  --jkd-linen:#EAE3DF;
  --jkd-gold:#B59556;
  --jkd-robin-egg:#B9CADD;
  --jkd-slate:#758AAA;
  --jkd-steel-blue:#3A5476;

  /* Working roles */
  --ink:var(--jkd-deep-gray);
  --ink-soft:#5C5C5C;
  /* Text siblings of Stone and Gold. The brand colours are 2.46:1 and 2.24:1 on
     Linen, which fails WCAG for any size. These clear 4.5:1 and read as the same
     colours. Stone and Gold themselves still draw hairlines, diamonds and hovers. */
  --ink-muted:#656667;
  --gold-text:#7A6232;
  --ground:var(--jkd-linen);          /* default warm ground, BOS 2.1 */
  --ground-white:var(--jkd-white);    /* card fills and negative space */
  --ground-dark:var(--jkd-deep-gray);
  --ground-blue:var(--jkd-steel-blue);
  --rule:#D6CCC6;
  --rule-light:rgba(255,255,255,.20);

  /* Type. BOS 2.2 */
  --display:'Modny Light','Cormorant Garamond','Playfair Display',Georgia,serif;
  --sans:'Inter','Acumin Pro',system-ui,-apple-system,'Segoe UI',sans-serif;

  --t-hero:clamp(2rem,4.4vw,3.35rem);
  --t-display:clamp(1.8rem,3.9vw,2.9rem);
  --t-section:clamp(1.45rem,2.9vw,2.1rem);
  --t-title:clamp(1.1rem,1.7vw,1.35rem);
  --t-body:1.0625rem;
  --t-small:.9375rem;
  --t-label:.6875rem;

  /* Tracking. BOS 2.2 calls for +300 to +400 on labels, which is .30 to .40em */
  --track-xwide:.34em;
  --track-wide:.26em;
  --track-mid:.18em;
  --track-soft:.04em;

  --gap-xs:.5rem; --gap-sm:1rem; --gap-md:2rem;
  --gap-lg:3.5rem; --gap-xl:6rem; --gap-2xl:9rem;

  --measure:64ch;
}

*,*::before,*::after{box-sizing:border-box}
html{scroll-padding-top:96px;scroll-behavior:smooth}
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}
}

body{
  margin:0;
  background:var(--ground);
  color:var(--ink);
  font-family:var(--sans);
  font-weight:300;
  font-size:var(--t-body);
  line-height:1.78;
  -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
}

/* Photos: sharp corners, no frame, ever. BOS 1.5 */
img{max-width:100%;height:auto;display:block;border-radius:0;border:0;box-shadow:none}
/* A <picture> must not make a box of its own: the img is what every layout rule targets. */
picture{display:contents}
figure{margin:0}

/* --------------------------------------------------------------- type --- */
h1,h2,h3,h4{margin:0;font-weight:400;text-wrap:balance}

.display{
  font-family:var(--display);
  text-transform:uppercase;
  font-weight:300;
  line-height:1.18;
  letter-spacing:.045em;
}
.display--hero{font-size:var(--t-hero);line-height:1.12;letter-spacing:.03em;max-width:26ch;margin-inline:auto}
.display--lg{font-size:var(--t-display)}
.display--md{font-size:var(--t-section)}
.display--sm{font-size:var(--t-title);letter-spacing:.09em}

/* Labels and buttons: all caps, extreme tracking. BOS 2.2 */
.eyebrow{
  font-family:var(--sans);font-size:var(--t-label);font-weight:400;
  letter-spacing:var(--track-xwide);text-transform:uppercase;
  color:var(--ink-muted);margin:0 0 var(--gap-sm);
}
.eyebrow--gold{color:var(--gold-text)}
.eyebrow--light{color:rgba(255,255,255,.82)}

p{margin:0 0 1.15em;max-width:var(--measure)}
.lede{font-size:1.16rem;font-weight:300;line-height:1.72;color:var(--ink-soft)}
.center{text-align:center}
/* Reveal-on-scroll leaves anything unseen at opacity 0, which prints as a blank band. */
@media print{
  .reveal{opacity:1!important;transform:none!important}
  .masthead{position:static}
  .announce,.stage__ticks,.nav-toggle{display:none}
}
.center p,.center .lede,p.center,.lede.center{margin-left:auto;margin-right:auto}
strong{font-weight:500;color:var(--ink)}

a{color:inherit;text-decoration:none}
a:focus-visible,button:focus-visible,summary:focus-visible,.reel__track:focus-visible{outline:2px solid var(--jkd-steel-blue);outline-offset:4px}
/* On the dark bands steel blue disappears, so the ring goes to Linen there. */
.band--dark :focus-visible,.band--blue :focus-visible,.site-footer :focus-visible,
.announce :focus-visible,.stage :focus-visible,.proj-hero :focus-visible{outline-color:var(--jkd-linen)}

/* ------------------------------------------------------------- layout --- */
.wrap{width:100%;max-width:1240px;margin:0 auto;padding:0 clamp(20px,5vw,56px)}
.wrap--narrow{max-width:840px}
.wrap--wide{max-width:1520px}
.wrap--flush{max-width:none;padding:0}

/* Measured before this change: 21 to 27 percent of every content page's height was
   band padding with nothing in it. A flat 6rem top and bottom is also the same
   interval on a phone as on a desktop, which is why the pages read as padded rather
   than paced. This scales with the viewport and gives back roughly 64px a band. */
.band{padding:clamp(3.25rem,6vw,5rem) 0}
.band--tight{padding:clamp(2.25rem,4vw,3.5rem) 0}
.band--tall{padding:clamp(5rem,9vw,9rem) 0}
.band--linen{background:var(--jkd-linen)}
.band--white{background:var(--jkd-white)}
.band--dark{background:var(--ground-dark);color:#F1EFED}
.band--blue{background:var(--ground-blue);color:#F1EFED}
.band--dark p,.band--dark .lede,.band--blue p,.band--blue .lede{color:rgba(241,239,237,.80)}
.band--dark .display,.band--blue .display{color:#F6F4F2}

/* Hairline with the JKD diamond. Gold used as a rare accent only. BOS 2.1 */
.rule-diamond{display:flex;align-items:center;justify-content:center;gap:var(--gap-sm);
  margin:var(--gap-md) auto;max-width:320px}
.rule-diamond::before,.rule-diamond::after{content:"";flex:1;height:1px;background:var(--rule)}
.band--dark .rule-diamond::before,.band--dark .rule-diamond::after,
.band--blue .rule-diamond::before,.band--blue .rule-diamond::after{background:var(--rule-light)}
.rule-diamond i{width:6px;height:6px;background:var(--jkd-gold);transform:rotate(45deg);flex:0 0 auto}

/* ---------------------------------------------------------- top bars --- */
.announce{
  /* Deep Gray rather than Steel Blue. Both are the brand's dominant pair, and the
     gray sits quieter above a photograph without competing with it. */
  background:var(--jkd-deep-gray);color:var(--jkd-linen);min-height:42px;
  display:flex;align-items:center;justify-content:center;
  flex-wrap:wrap;gap:4px clamp(14px,3vw,30px);
  font-size:var(--t-label);letter-spacing:var(--track-wide);
  text-transform:uppercase;text-align:center;padding:11px 16px;
}
/* The number stays on one line and stays tappable on a phone. */
.announce__phone{white-space:nowrap}
/* On a phone the banner keeps the two things worth tapping and drops the lead. */
@media (max-width:620px){.announce__lead{display:none}}
.announce a{border-bottom:1px solid rgba(234,227,223,.42);padding-bottom:2px;transition:border-color .2s}
.announce a:hover{border-bottom-color:var(--jkd-gold)}

.masthead{position:sticky;top:0;z-index:60;background:rgba(234,227,223,.97);
  backdrop-filter:blur(8px);border-bottom:1px solid var(--rule)}
.masthead__inner{display:flex;align-items:center;justify-content:space-between;
  gap:var(--gap-md);min-height:78px;position:relative}
.masthead__logo img{height:36px;width:auto;display:block}
.nav{display:flex;align-items:center;gap:clamp(12px,1.9vw,28px)}
.nav a{font-size:var(--t-label);letter-spacing:var(--track-mid);text-transform:uppercase;
  color:var(--ink);padding:6px 0;border-bottom:1px solid transparent;transition:border-color .2s,color .2s}
.nav a:hover,.nav a[aria-current="page"]{border-bottom-color:var(--jkd-gold)}
.nav__cta{border:1px solid var(--jkd-deep-gray)!important;padding:11px 20px!important;
  transition:background .2s,color .2s}
.nav__cta:hover{background:var(--jkd-deep-gray);color:#fff}
.nav-toggle{display:none;background:none;border:0;padding:8px;cursor:pointer;font-family:var(--sans);
  font-size:var(--t-label);letter-spacing:var(--track-mid);text-transform:uppercase;color:var(--ink)}

@media (max-width:1240px){
  .nav-toggle{display:block}
  .nav{position:absolute;top:100%;left:calc(-1 * clamp(20px,5vw,56px));right:calc(-1 * clamp(20px,5vw,56px));
    flex-direction:column;align-items:stretch;gap:0;background:var(--jkd-linen);
    border-bottom:1px solid var(--rule);padding:var(--gap-xs) clamp(20px,5vw,56px) var(--gap-md);display:none;
    max-height:calc(100vh - 78px);max-height:calc(100dvh - 78px);overflow-y:auto;overscroll-behavior:contain}
  .nav[data-open="true"]{display:flex}
  .nav a{padding:15px 0;border-bottom:1px solid var(--rule)}
  .nav__cta{margin-top:var(--gap-sm);text-align:center}
}

/* ---------------------------------------------------------------- CTA --- */
.btn{display:inline-block;font-family:var(--sans);font-size:var(--t-label);
  letter-spacing:var(--track-wide);text-transform:uppercase;padding:16px 34px;
  border:1px solid currentColor;transition:background .25s,color .25s;cursor:pointer;background:none}
.btn:hover{background:var(--jkd-deep-gray);color:#fff;border-color:var(--jkd-deep-gray)}
.btn--light{border-color:rgba(255,255,255,.65);color:#fff}
.btn--light:hover{background:#fff;color:var(--jkd-deep-gray);border-color:#fff}
/* On a dark band the two actions are no longer equals: the form is the way in and the
   phone number is the alternative, so it reads quieter. */
.btn--ghost-light{border-color:rgba(255,255,255,.28);color:rgba(255,255,255,.82)}
.btn--ghost-light:hover{border-color:rgba(255,255,255,.65);color:#fff}

/* The enquiry form is a HoneyBook iframe. It arrives at its own pace and can fail, so the
   container holds its own height and the fallback underneath is visible until the iframe
   is actually on the page. */
.enquiry{margin-top:var(--gap-lg)}
.enquiry__form{min-height:0}
.enquiry__form[data-loading]{min-height:420px;position:relative}
.enquiry__form[data-loading]::after{content:"Loading the form";position:absolute;inset:0;
  display:flex;align-items:center;justify-content:center;
  font-size:var(--t-label);letter-spacing:var(--track-mid);text-transform:uppercase;
  color:var(--ink-muted);background:var(--jkd-linen)}
.enquiry__form iframe{width:100%;border:0;display:block}
.enquiry__fallback{margin-top:var(--gap-md);padding:16px 18px;border-left:2px solid var(--jkd-gold);
  background:var(--jkd-linen);max-width:62ch}
.enquiry__fallback p{font-size:var(--t-small);line-height:1.7}
.enquiry__fallback .eyebrow{margin-bottom:6px}
/* If the form never arrives, this stops being a footnote and starts being the instruction. */
.enquiry__fallback[data-only-way] .eyebrow::after{content:" (it did not)"}
.link-underline{display:inline-block;font-size:var(--t-label);letter-spacing:var(--track-wide);
  text-transform:uppercase;padding-bottom:6px;border-bottom:1px solid currentColor;
  transition:color .2s,border-color .2s}
.link-underline:hover{color:var(--jkd-gold);border-bottom-color:var(--jkd-gold)}

/* --------------------------------------------------------------- hero --- */
/* Full-bleed photo background. BOS 4.6 */
.hero{position:relative;min-height:clamp(460px,80vh,800px);display:grid;
  background:var(--jkd-deep-gray);overflow:hidden}
.hero__media{position:absolute;inset:0}
.hero__media img{width:100%;height:100%;object-fit:cover}
/* Scrim exists only to make type legible. Never a decorative color wash. BOS 4.7 */
.hero__scrim{position:absolute;inset:0;background:rgba(37,37,37,.42)}
.hero__body{position:relative;z-index:2;align-self:center;padding:var(--gap-xl) 0;
  color:#fff;text-align:center}
.hero__body .display--hero{color:#fff}
.hero__body .lede{color:rgba(255,255,255,.92);max-width:52ch}
.hero__actions{display:flex;flex-wrap:wrap;gap:var(--gap-sm);justify-content:center;margin-top:var(--gap-md)}

/* Build-time photo slot. NOT a shippable state. BOS rule 1 forbids placeholder
   imagery in finished work. Every slot names the exact file it is waiting for. */
.photo-slot{
  background:repeating-linear-gradient(45deg,#E3DAD5 0 12px,#DED4CE 12px 24px);
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:6px;
  color:#8A7F78;font-size:var(--t-label);letter-spacing:var(--track-mid);
  text-transform:uppercase;text-align:center;padding:24px;aspect-ratio:4/3;width:100%;
}
.photo-slot b{font-weight:500;letter-spacing:var(--track-soft);text-transform:none;font-size:.8rem}
.photo-slot--tall{aspect-ratio:3/4}
.photo-slot--hero{aspect-ratio:auto;height:100%;min-height:460px}

/* -------------------------------------------------------- authority --- */
/* The hairlines used to be this grid's own background showing through a 1px gap, which
   painted a grey slab wherever four items did not fill their rows. Each item draws its
   own hairline now, so an incomplete row leaves nothing behind. */
.authority{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(220px,100%),1fr));
  gap:1px}
.authority__item{background:var(--jkd-linen);padding:var(--gap-md) var(--gap-sm);text-align:center;
  box-shadow:0 0 0 1px var(--rule)}
.band--white .authority__item{background:var(--jkd-white)}
.authority__fig{font-family:var(--display);text-transform:uppercase;
  font-size:clamp(1.7rem,2.7vw,2.3rem);line-height:1;color:var(--jkd-steel-blue);
  font-variant-numeric:tabular-nums;font-weight:300}
.authority__label{display:block;margin-top:12px;font-size:var(--t-label);
  letter-spacing:var(--track-mid);text-transform:uppercase;color:var(--ink-muted);line-height:1.7}

/* -------------------------------------------------- category marquee --- */
/* Deep Gray band with gold diamonds. Gold is never a large fill. BOS 2.1 */
.marquee{background:var(--jkd-deep-gray);color:#fff;overflow:hidden;padding:15px 0}
.marquee__track{display:flex;width:max-content;animation:marquee 50s linear infinite}
.marquee:hover .marquee__track,.marquee:focus-within .marquee__track{animation-play-state:paused}
.marquee__group{display:flex;align-items:center;flex:0 0 auto}
.marquee a,.marquee span{font-size:var(--t-label);letter-spacing:var(--track-wide);
  text-transform:uppercase;padding:0 22px;white-space:nowrap;transition:color .2s}
.marquee a:hover{color:var(--jkd-gold)}
.marquee i{width:5px;height:5px;background:var(--jkd-gold);transform:rotate(45deg);flex:0 0 auto}
@keyframes marquee{from{transform:translateX(0)}to{transform:translateX(-50%)}}
@media (prefers-reduced-motion:reduce){
  .marquee__track{animation:none;width:100%;flex-wrap:wrap;justify-content:center}
}

/* ------------------------------------------------------------ project --- */
.grid{display:grid;gap:var(--gap-md)}
/* min() so a narrow phone collapses to one column instead of overflowing the page */
.grid--2{grid-template-columns:repeat(auto-fit,minmax(min(360px,100%),1fr))}
/* auto-fill, not auto-fit: a section with one card keeps the card size instead of
   stretching a 800px photo across the whole row. */
.grid--3{grid-template-columns:repeat(auto-fill,minmax(min(290px,100%),1fr))}
.grid--4{grid-template-columns:repeat(auto-fit,minmax(min(220px,100%),1fr))}

.project{display:block}
.project__media{overflow:hidden;margin-bottom:var(--gap-sm);background:var(--jkd-linen)}
.project__media img{transition:transform .8s cubic-bezier(.2,.7,.3,1);width:100%}
.project:hover .project__media img{transform:scale(1.04)}
.project__meta{font-size:var(--t-label);letter-spacing:var(--track-mid);
  text-transform:uppercase;color:var(--gold-text);margin-bottom:7px}
.project__name{font-family:var(--display);text-transform:uppercase;font-size:var(--t-title);
  letter-spacing:.09em;line-height:1.28;color:var(--ink);font-weight:300;transition:color .25s}
.project:hover .project__name{color:var(--jkd-steel-blue)}
.project__blurb{font-size:var(--t-small);color:var(--ink-soft);margin:9px 0 0;line-height:1.62}

/* ----------------------------------------------------------- feature --- */
/* Left vertical photo, text on the right. The only non-full-bleed photo
   placement the brand allows in a multi-element layout. BOS 4.6 */
.feature{display:grid;grid-template-columns:minmax(0,5fr) minmax(0,6fr);
  gap:clamp(28px,5vw,72px);align-items:center}
.feature__media{align-self:stretch}
.feature__media img,.feature__media .photo-slot{height:100%;width:100%;object-fit:cover;aspect-ratio:3/4}
@media (max-width:880px){
  .feature{grid-template-columns:1fr}
  .feature__media img,.feature__media .photo-slot{aspect-ratio:4/3}
}

/* --------------------------------------------------------- quotation --- */
.quote{max-width:820px;margin:0 auto;text-align:center}
.quote blockquote{margin:0;font-family:var(--display);text-transform:uppercase;
  font-size:clamp(1.25rem,2.3vw,1.8rem);line-height:1.45;letter-spacing:.055em;font-weight:300}
.quote figcaption{margin-top:var(--gap-sm);font-size:var(--t-label);
  letter-spacing:var(--track-wide);text-transform:uppercase;color:var(--gold-text)}

/* ------------------------------------------------------------- awards --- */
.awards{border-top:1px solid var(--rule)}
.award{display:grid;grid-template-columns:110px 1fr;gap:var(--gap-md);
  padding:var(--gap-md) 0;border-bottom:1px solid var(--rule);align-items:start}
.award__year{font-family:var(--display);text-transform:uppercase;font-size:1.5rem;font-weight:300;
  color:var(--gold-text);font-variant-numeric:tabular-nums;line-height:1;padding-top:.18em}
.award__name{font-size:1.05rem;font-weight:400;color:var(--ink);margin-bottom:5px}
.award__detail{font-size:var(--t-small);color:var(--ink-soft);margin:0;max-width:none}
.award__detail a{border-bottom:1px solid var(--rule);transition:border-color .2s,color .2s}
.award__detail a:hover{border-bottom-color:var(--jkd-gold);color:var(--jkd-gold)}
@media (max-width:620px){.award{grid-template-columns:1fr;gap:var(--gap-xs)}}

/* ---------------------------------------------------------- process --- */
.process{counter-reset:step;border-top:1px solid var(--rule)}
.step{counter-increment:step;display:grid;grid-template-columns:60px 1fr;gap:var(--gap-md);
  padding:var(--gap-md) 0;border-bottom:1px solid var(--rule)}
.step::before{content:counter(step,decimal-leading-zero);font-family:var(--display);
  color:var(--gold-text);font-size:1.1rem;letter-spacing:.1em;padding-top:.4em;font-weight:300}
.step h3{font-family:var(--display);text-transform:uppercase;font-size:var(--t-title);
  letter-spacing:.09em;margin-bottom:6px;font-weight:300}
.step p{margin:0;font-size:var(--t-small);color:var(--ink-soft)}
@media (max-width:620px){.step{grid-template-columns:44px 1fr;gap:var(--gap-sm)}}

/* -------------------------------------------------------------- areas --- */
.areas{display:flex;flex-wrap:wrap;gap:8px 0;list-style:none;padding:0;margin:0;justify-content:center}
.areas li{display:flex;align-items:center}
.areas li::after{content:"";width:4px;height:4px;background:var(--jkd-gold);
  transform:rotate(45deg);margin:0 15px}
.areas li:last-child::after{display:none}
.areas a,.areas span{font-size:var(--t-small);letter-spacing:var(--track-soft);color:var(--ink-soft)}
.areas a:hover{color:var(--jkd-steel-blue)}
/* The neighbourhood list in an alternating prose row runs as a column beside the text
   rather than a centred ribbon, so it reads as a list of places and not a tag cloud. */
.areas--compact{flex-direction:column;align-items:flex-start;justify-content:flex-start;gap:6px 0}
.areas--compact li::after{display:none}
.areas--compact span{font-size:var(--t-small);color:var(--ink)}
.areas--compact li{position:relative;padding-left:16px}
.areas--compact li::before{content:"";position:absolute;left:0;top:.62em;width:4px;height:4px;
  background:var(--jkd-gold);transform:rotate(45deg)}

/* Breadcrumbs were six repeated inline styles per page. One class instead. */
.crumb{margin-bottom:var(--gap-md);font-size:var(--t-label);letter-spacing:var(--track-mid);
  text-transform:uppercase;color:var(--ink-muted)}

/* ---------------------------------------------------------------- faq --- */
.faq{border-top:1px solid var(--rule);max-width:var(--measure);margin-inline:auto}
.faq details{border-bottom:1px solid var(--rule)}
.faq summary{cursor:pointer;list-style:none;padding:var(--gap-sm) 44px var(--gap-sm) 0;
  position:relative;font-size:1.05rem;color:var(--ink)}
.faq summary::-webkit-details-marker{display:none}
.faq summary::after{content:"";position:absolute;right:10px;top:calc(50% - 5px);width:8px;height:8px;
  border-right:1px solid var(--jkd-gold);border-bottom:1px solid var(--jkd-gold);
  transform:rotate(45deg);transition:transform .25s}
.faq details[open] summary::after{transform:rotate(-135deg)}
.faq details p{padding:0 0 var(--gap-sm);font-size:var(--t-small);color:var(--ink-soft);max-width:none}

/* -------------------------------------------------------------- footer --- */
/* Steel Blue is the brand's footer color. BOS 2.1 */
.site-footer{background:var(--jkd-steel-blue);color:rgba(241,239,237,.76);padding:var(--gap-xl) 0 var(--gap-md)}
.site-footer a{color:rgba(241,239,237,.76);transition:color .2s}
.site-footer a:hover{color:var(--jkd-gold)}
.footer__grid{display:grid;grid-template-columns:1.5fr 1fr 1fr 1.2fr;gap:var(--gap-lg)}
@media (max-width:920px){.footer__grid{grid-template-columns:1fr 1fr}}
@media (max-width:560px){.footer__grid{grid-template-columns:1fr}}
.footer__logo img{height:64px;width:auto;margin-bottom:var(--gap-sm)}
.footer__tagline{font-size:var(--t-label);letter-spacing:var(--track-mid);
  text-transform:uppercase;color:rgba(241,239,237,.6);margin:0 0 var(--gap-sm)}
.site-footer h3{font-size:var(--t-label);letter-spacing:var(--track-wide);text-transform:uppercase;
  color:#fff;margin:0 0 var(--gap-sm);font-weight:400}
.site-footer ul{list-style:none;padding:0;margin:0}
.site-footer li{margin-bottom:11px;font-size:var(--t-small)}
.site-footer address{font-style:normal;font-size:var(--t-small);line-height:1.95}
.footer__legal{margin-top:var(--gap-lg);padding-top:var(--gap-md);border-top:1px solid var(--rule-light);
  display:flex;flex-wrap:wrap;gap:var(--gap-sm) var(--gap-md);justify-content:space-between;
  font-size:var(--t-label);letter-spacing:var(--track-soft)}
.social{display:flex;flex-wrap:wrap;gap:var(--gap-sm);margin-top:var(--gap-sm)}
.social a{font-size:var(--t-label);letter-spacing:var(--track-mid);text-transform:uppercase}

/* ------------------------------------------------------- recognition --- */
/* Awards and press are presented as dated, linked text. Never a logo wall.
   Reuses the .awards / .award row from above and adds the outlet line and
   the hub cards. Gold stays a hairline accent only. BOS 2.1 */
.award__source{display:block;font-size:var(--t-label);letter-spacing:var(--track-mid);
  text-transform:uppercase;color:var(--ink-muted);margin:0 0 6px}
.award__cite{display:block;margin-top:9px;font-size:var(--t-label);letter-spacing:var(--track-mid);
  text-transform:uppercase;color:var(--jkd-steel-blue)}
.award__cite a{border-bottom:1px solid var(--rule);padding-bottom:2px;transition:border-color .2s,color .2s}
.award__cite a:hover{color:var(--jkd-gold);border-bottom-color:var(--jkd-gold)}
.award--pending .award__year{color:var(--ink-muted);font-family:var(--sans);font-size:var(--t-label);
  letter-spacing:var(--track-mid);text-transform:uppercase;padding-top:.5em}

.recog-card{display:block;border-top:1px solid var(--rule);padding-top:var(--gap-md)}
.recog-card h3{font-family:var(--display);text-transform:uppercase;font-size:var(--t-title);
  letter-spacing:.09em;font-weight:300;margin:6px 0 10px;transition:color .2s}
.recog-card:hover h3{color:var(--jkd-steel-blue)}
.recog-card p{font-size:var(--t-small);color:var(--ink-soft);margin:0 0 14px}
.recog-card__count{font-family:var(--display);font-size:1.9rem;font-weight:300;
  line-height:1;color:var(--jkd-steel-blue)}

/* Year-grouped award blocks on the awards page */
.award-year{border-top:1px solid var(--rule);padding:var(--gap-md) 0}
.award-year:last-child{border-bottom:1px solid var(--rule)}
.award-year__head{display:flex;align-items:baseline;gap:var(--gap-sm);margin-bottom:var(--gap-sm)}
.award-year__num{font-family:var(--display);font-size:1.9rem;font-weight:300;line-height:1;
  color:var(--jkd-steel-blue);letter-spacing:.02em}
.award-year__tag{font-size:var(--t-label);letter-spacing:var(--track-mid);
  text-transform:uppercase;color:var(--ink-muted)}
.award-year ul{list-style:none;padding:0;margin:0}
.award-year li{position:relative;padding-left:20px;margin-bottom:12px;font-size:var(--t-small);
  color:var(--ink-soft);line-height:1.66}
.award-year li::before{content:"";position:absolute;left:0;top:.62em;width:5px;height:5px;
  background:var(--jkd-gold);transform:rotate(45deg)}
.award-year li b{font-weight:400;color:var(--ink)}

/* ------------------------------------------------------------- people --- */
/* Team card. Photo is a clean vertical rectangle with the text below it,
   sharp corners, no frame, no shadow, no radius. BOS 1.5, 4.6 */
.person__media{margin-bottom:var(--gap-sm);background:var(--jkd-linen);overflow:hidden}
/* The team portraits are out being re-photographed. The cards keep the names,
   roles and bios, so the page is not an empty shell while the pictures are away. */
.team-note{margin:0 0 var(--gap-lg);padding:14px 18px;border-left:2px solid var(--jkd-gold);
  background:var(--jkd-linen);color:var(--ink-soft);font-size:.98rem;line-height:1.6;max-width:62ch}
.team-note b{color:var(--jkd-deep-gray);font-weight:500}
.person__media img,.person__media .photo-slot{width:100%;height:100%;object-fit:cover;aspect-ratio:3/4}
.person__role{font-size:var(--t-label);letter-spacing:var(--track-mid);text-transform:uppercase;
  color:var(--ink-muted);margin:0 0 6px}
.person__name{font-family:var(--display);text-transform:uppercase;font-size:var(--t-title);
  letter-spacing:.09em;font-weight:300;margin:0 0 10px;color:var(--ink)}
.person__bio{font-size:var(--t-small);color:var(--ink-soft);margin:0;line-height:1.66;max-width:none}

/* ---------------------------------------------------------- portfolio --- */
/* Project pages. Photography is the product, so it runs full-bleed at its own
   aspect ratio. Never forced into a banner strip. BOS 4.6, 1.5 */
.proj-hero{position:relative;min-height:clamp(420px,74vh,760px);display:grid;isolation:isolate}
.proj-hero__media{position:absolute;inset:0}
.proj-hero__media img{width:100%;height:100%;object-fit:cover}
/* Neutral darkening only where the type sits, so the photograph stays bright at
   the top and the title and eyebrow stay legible over a light room. */
.proj-hero__scrim{position:absolute;inset:0;background:
  linear-gradient(to right,rgba(37,37,37,.56) 0%,rgba(37,37,37,.40) 38%,rgba(37,37,37,.08) 72%,rgba(37,37,37,0) 100%),
  linear-gradient(to bottom,rgba(37,37,37,.12) 0%,rgba(37,37,37,.06) 30%,rgba(37,37,37,.48) 72%,rgba(37,37,37,.76) 100%)}
.proj-hero__body{position:relative;z-index:2;align-self:end;width:100%;padding:var(--gap-xl) 0 var(--gap-lg)}
.proj-hero__body .display{color:#fff}
.proj-hero__body .eyebrow{color:rgba(255,255,255,.88)}

/* Fact row. Reads as a caption block, not a table. */
.proj-facts{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));
  gap:var(--gap-md);border-top:1px solid var(--rule);padding-top:var(--gap-md)}
.proj-facts dt{font-size:var(--t-label);letter-spacing:var(--track-mid);text-transform:uppercase;
  color:var(--ink-muted);margin-bottom:7px}
.proj-facts dd{margin:0;font-size:var(--t-small);color:var(--ink);line-height:1.6}

/* Gallery. Full-bleed singles, or a clean two-up. Natural aspect either way. */
.gallery{display:block}
.gallery figure{margin:0 0 var(--gap-md)}
.gallery figure:last-child{margin-bottom:0}
.gallery img{width:100%;height:auto}
/* A portrait photograph at full column width runs two screens tall, which reads
   as shouting. On its own it is held to a width that fits one screen. */
.gallery > figure.portrait{max-width:660px;margin-inline:auto}
.gallery__pair figure{margin-bottom:0}
/* Three projects came over from the old site as small files and nothing larger
   exists. Holding those to their own pixel width keeps them sharp. */
.gallery > figure.soft{max-width:760px;margin-inline:auto}
.gallery figcaption{margin-top:12px;font-size:var(--t-label);letter-spacing:var(--track-mid);
  text-transform:uppercase;color:var(--ink-muted)}
.gallery--bleed figure{margin-bottom:0}
.gallery__pair{display:grid;grid-template-columns:1fr 1fr;gap:var(--gap-sm);margin-bottom:var(--gap-md)}
@media (max-width:700px){.gallery__pair{grid-template-columns:1fr;gap:var(--gap-md)}}

/* Portfolio index card. Cover photo keeps its own ratio, no crop to a strip. */
.pcard{display:block}
.pcard__media{overflow:hidden;background:var(--jkd-linen);margin-bottom:var(--gap-sm)}
.pcard__media img{width:100%;height:auto;aspect-ratio:4/3;object-fit:cover;
  transition:transform .8s cubic-bezier(.2,.7,.3,1)}
.pcard:hover .pcard__media img{transform:scale(1.04)}
.pcard__meta{font-size:var(--t-label);letter-spacing:var(--track-mid);text-transform:uppercase;
  color:var(--ink-muted);margin:0 0 6px}
.pcard__name{font-family:var(--display);text-transform:uppercase;font-size:var(--t-title);
  letter-spacing:.09em;font-weight:300;margin:0 0 8px;transition:color .2s}
.pcard:hover .pcard__name{color:var(--jkd-steel-blue)}
.pcard__blurb{font-size:var(--t-small);color:var(--ink-soft);margin:0;line-height:1.62;max-width:none}

/* Filter row on the portfolio index. Text links, never pill buttons. */
.pfilter{display:flex;flex-wrap:wrap;gap:var(--gap-sm) var(--gap-md);justify-content:center;
  border-top:1px solid var(--rule);border-bottom:1px solid var(--rule);padding:var(--gap-sm) 0;margin-bottom:var(--gap-lg)}
.pfilter a{font-size:var(--t-label);letter-spacing:var(--track-mid);text-transform:uppercase;
  color:var(--ink-muted);border-bottom:1px solid transparent;padding-bottom:3px;transition:color .2s,border-color .2s}
.pfilter a:hover,.pfilter a[aria-current="true"]{color:var(--ink);border-bottom-color:var(--jkd-gold)}

/* Prev / next between projects */
.proj-nav{display:grid;grid-template-columns:1fr 1fr;gap:var(--gap-md);
  border-top:1px solid var(--rule);padding-top:var(--gap-md)}
.proj-nav a{font-size:var(--t-label);letter-spacing:var(--track-mid);text-transform:uppercase;color:var(--ink-muted)}
.proj-nav a:hover{color:var(--jkd-steel-blue)}
.proj-nav>:last-child{text-align:right}
@media (max-width:560px){.proj-nav{grid-template-columns:1fr}.proj-nav>:last-child{text-align:left}}

/* ========================================================== stagecraft ===
   Luxury here is scale, restraint and slow motion. The Brand OS forbids
   shadows, gradients, colour washes and large gold fills, so none of that is
   available and none of it is needed. What carries the feeling instead:
   generous negative space, a wider type scale, hairline gold, full-bleed
   photography that is never cropped into a strip, and motion slow enough that
   you notice the room rather than the transition.
   Every animated property here is transform or opacity. Nothing touches layout.
   ====================================================================== */

/* ------------------------------------------------ rotating hero stage --- */
.stage{position:relative;min-height:clamp(560px,92vh,940px);display:grid;isolation:isolate;overflow:hidden}
.stage__slides{position:absolute;inset:0}
.stage__slide{position:absolute;inset:0;opacity:0;transition:opacity 1800ms cubic-bezier(.4,0,.2,1)}
.stage__slide[data-active="true"]{opacity:1}
/* Frames 2+ stay out of layout until site.js arms the stage. Their images are
   loading="lazy", so nothing is fetched for them during page load. Frame 1 is
   active in the HTML, so without JS the stage is a still photograph. */
/* A frame only leaves display:none when it is the one showing or the one next in
   line. Arming all seven at once made a 2x laptop download every hero on the site
   before the visitor had seen the second one. */
.stage:not([data-armed="true"]) .stage__slide:not(:first-child){display:none}
.stage[data-armed="true"] .stage__slide:not([data-active="true"]):not([data-next="true"]):not([data-seen="true"]){display:none}
.stage__slide img{width:100%;height:100%;object-fit:cover;transform:scale(1.0);
  transition:transform 9500ms linear}
/* A very slow drift. Transform only, so it never costs a layout pass. It is
   the one motion that makes a still photograph feel like a held shot. It waits
   for the stage to arm, so the first frame paints still and then begins. */
.stage[data-armed="true"] .stage__slide[data-active="true"] img{transform:scale(1.055)}
/* Neutral darkening only, and only because type sits here. BOS 1.7 */
.stage__scrim{position:absolute;inset:0;z-index:1;
  background:
    linear-gradient(to right,rgba(37,37,37,.62) 0%,rgba(37,37,37,.46) 34%,rgba(37,37,37,.08) 66%,rgba(37,37,37,0) 100%),
    linear-gradient(to bottom,rgba(37,37,37,.20) 0%,rgba(37,37,37,.10) 34%,rgba(37,37,37,.52) 72%,rgba(37,37,37,.78) 100%)}
.stage__body{position:relative;z-index:2;align-self:end;width:100%;padding:0 0 clamp(56px,9vh,110px)}
.stage__body .display{color:#fff}
.stage__body .lede{color:rgba(255,255,255,.88);max-width:44ch;font-size:1.06rem}

/* Slide attribution. Small, quiet, bottom right. */
.stage__credit{position:absolute;right:clamp(20px,5vw,56px);bottom:clamp(28px,4.5vh,52px);z-index:3;
  text-align:right;font-size:var(--t-label);letter-spacing:var(--track-mid);text-transform:uppercase;
  color:rgba(255,255,255,.62);max-width:16ch;line-height:1.7}
.stage__credit b{display:block;font-weight:400;color:rgba(255,255,255,.92)}
@media (max-width:700px){.stage__credit{display:none}}

/* Progress: hairline gold, the only gold on the screen. Never a fill. */
.stage__ticks{position:absolute;left:clamp(20px,5vw,56px);bottom:clamp(28px,4.5vh,52px);z-index:3;
  display:flex;gap:10px}
.stage__tick{width:34px;height:1px;background:rgba(255,255,255,.30);border:0;padding:0;cursor:pointer;
  position:relative;overflow:hidden;transition:background .4s}
.stage__tick::after{content:"";position:absolute;inset:0;background:var(--jkd-gold);
  transform:scaleX(0);transform-origin:left}
/* Which frame is showing. Static by default, so it reads without JS. */
.stage__tick[aria-current="true"]::after{transform:scaleX(1)}
/* While rotating, the hairline fills across the hold. An animation, not a
   transition, so it also runs for frame 1, which is current before JS arrives.
   7000ms matches HOLD in site.js. */
.stage[data-armed="true"] .stage__tick[aria-current="true"]::after{animation:stage-hold 7000ms linear both}
@keyframes stage-hold{from{transform:scaleX(0)}to{transform:scaleX(1)}}
.stage__tick:hover{background:rgba(255,255,255,.55)}

@media (prefers-reduced-motion:reduce){
  .stage__slide{transition:none}
  .stage__slide img{transition:none;transform:none}
  .stage[data-armed="true"] .stage__slide[data-active="true"] img{transform:none}
  .stage[data-armed="true"] .stage__tick[aria-current="true"]::after{animation:none}
}

/* ------------------------------------------------------ scroll reveal --- */
/* Opacity and transform only. Content is visible by default and the class is
   added by JS, so anything without JS or with reduced motion sees it all. */
/* Everything here is opacity and transform only, so it stays on the compositor and
   never costs a layout pass. .reveal is added by JS and only when motion is welcome,
   so a visitor without JS, or who asked for less motion, sees the finished state. */
:root{--ease-rise:cubic-bezier(.22,1,.36,1);--rise:1100ms}

/* A sliding element starts outside its own box, which is what made 58 pages scroll
   sideways the first time this shipped. clip, not hidden: hidden would make these
   scroll containers and break the sticky masthead and anchor scrolling. */
.editorial,.gallery,.grid,.authority{overflow-x:clip}

.reveal{opacity:0;transform:translateY(18px);
  transition:opacity var(--rise) var(--ease-rise),transform var(--rise) var(--ease-rise)}
.reveal[data-seen="true"]{opacity:1;transform:none}

/* The two halves of an editorial band come in from opposite sides and meet. This is
   the move Jennifer's current site uses and the one that reads as motion.
   The direction is a variable set on .editorial rather than baked into these rules,
   so a flipped row slides the other way without a second copy of the motion, and
   .reveal can sit either on the row itself or on a section wrapping it. */
.reveal .editorial__media{opacity:0;transform:translate3d(var(--from-media,-44px),0,0);
  transition:opacity 1200ms var(--ease-rise) 80ms,transform 1200ms var(--ease-rise) 80ms}
.reveal .editorial__body{opacity:0;transform:translate3d(var(--from-body,36px),0,0);
  transition:opacity 1200ms var(--ease-rise) 220ms,transform 1200ms var(--ease-rise) 220ms}
.reveal[data-seen="true"] .editorial__media,
.reveal[data-seen="true"] .editorial__body{opacity:1;transform:none}

/* A pair opens outward from the gutter rather than both sliding the same way. */
.reveal .gallery__pair > figure:first-child{opacity:0;transform:translate3d(-30px,10px,0)}
.reveal .gallery__pair > figure:last-child{opacity:0;transform:translate3d(30px,10px,0)}
.reveal .gallery__pair > figure{transition:opacity 1150ms var(--ease-rise),transform 1150ms var(--ease-rise)}
.reveal[data-seen="true"] .gallery__pair > figure:first-child,
.reveal[data-seen="true"] .gallery__pair > figure:last-child{opacity:1;transform:none}

/* Cards and stats arrive one after another instead of as a block. The delay comes
   from JS so it follows document order rather than a guess at the column count. */
.reveal .pcard,.reveal .authority__item,.reveal .person{
  opacity:0;transform:translateY(22px);
  transition:opacity 900ms var(--ease-rise),transform 900ms var(--ease-rise);
  transition-delay:var(--stagger,0ms)}
.reveal[data-seen="true"] .pcard,
.reveal[data-seen="true"] .authority__item,
.reveal[data-seen="true"] .person{opacity:1;transform:none}

/* A full-bleed photograph drifts slower than the page behind its own band. The
   variable is set by JS on scroll; with no JS it stays 0 and nothing moves. */
.proj-hero__media img,.stage__slide img{will-change:transform}
.proj-hero__media{overflow:hidden}
.proj-hero__media img{transform:translate3d(0,var(--drift,0px),0) scale(1.06)}

@media (prefers-reduced-motion:reduce){
  .reveal,.reveal .editorial__media,.reveal .editorial__body,.reveal .editorial__aside,
  .reveal .gallery__pair > figure,.reveal .pcard,.reveal .authority__item,.reveal .person{
    opacity:1;transform:none;transition:none}
  .proj-hero__media img{transform:none}
}

/* --------------------------------------------------------------- reel --- */
/* Four tall photographs across, the way the slideshow on the old site read.
   Scroll snapping does the work. The arrows only nudge the track, so touch
   and trackpads behave normally and keyboard users can tab into it. */
.reel__head{display:flex;align-items:flex-end;justify-content:space-between;gap:var(--gap-md);
  margin-bottom:var(--gap-md)}
.reel__nav{display:flex;gap:10px;flex:0 0 auto}
.reel__arrow{width:44px;height:44px;border:1px solid var(--rule);background:transparent;color:var(--ink);
  font-family:var(--sans);font-size:1rem;line-height:1;cursor:pointer;transition:background .2s,border-color .2s}
.reel__arrow:hover{background:var(--jkd-linen);border-color:var(--ink)}
.reel__arrow[disabled]{opacity:.3;cursor:default}
.reel__track{display:grid;grid-auto-flow:column;grid-auto-columns:calc((100% - 3 * var(--gap-sm)) / 4);
  gap:var(--gap-sm);overflow-x:auto;scroll-snap-type:x mandatory;scrollbar-width:none;
  -webkit-overflow-scrolling:touch}
.reel__track::-webkit-scrollbar{display:none}
.reel__item{scroll-snap-align:start}
.reel__item img{width:100%;aspect-ratio:3/4;object-fit:cover}
@media (max-width:1100px){.reel__track{grid-auto-columns:calc((100% - var(--gap-sm)) / 2)}}
@media (max-width:700px){.reel__track{grid-auto-columns:78%}}

/* ---------------------------------------------------------------- rates --- */
.rates{display:grid;gap:var(--gap-md);margin:0}
.rate{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:var(--gap-xs) var(--gap-md);
  align-items:baseline;padding-bottom:var(--gap-sm);border-bottom:1px solid var(--rule)}
.rate__name{font-family:var(--sans);font-size:var(--t-label);letter-spacing:var(--track-mid);
  text-transform:uppercase;color:var(--ink)}
.rate__figure{font-family:var(--display);font-size:var(--t-title);letter-spacing:.06em;margin:0;text-align:right}
.rate__note{grid-column:1 / -1;margin:0;font-size:var(--t-small);color:var(--ink-soft);max-width:60ch}
@media (max-width:560px){.rate{grid-template-columns:1fr}.rate__figure{text-align:left}}

/* ------------------------------------------------------ editorial band --- */
/* Full-bleed photograph with the story set beside it. Not a banner strip:
   the image keeps a tall aspect and the type sits in its own column. BOS 4.6 */
.editorial{display:grid;grid-template-columns:minmax(0,7fr) minmax(0,5fr);align-items:stretch}
/* The grid is align-items:stretch, so this cell used to take the HEIGHT of the text
   column, which copy length sets. With object-fit:cover that made a 3:2 photograph
   scale by height while its sizes attribute only described the width, and an 800px
   file shipped into a slot needing 1,580. Capping the cell makes the slot a shape the
   sizes attribute can actually state. */
.editorial__media{position:relative;min-height:clamp(420px,64vh,760px)}
@media (min-width:881px){
  /* Capping this at 64vh kept the slot a shape `sizes` could state, but copy length
     sets the row height and the body runs 844 to 1305px, so the photograph stopped
     short and left 268 to 729px of dead band under it on every editorial hero.
     It stretches again. What makes that safe this time is that the sizes attribute
     now describes the full height the row can reach rather than the old 760px cap,
     so a stretched slot is still asking for enough pixels to cover it. */
  .editorial__media{align-self:stretch;height:auto;min-height:clamp(420px,64vh,760px)}
}
.editorial__media img{width:100%;height:100%;object-fit:cover}
.editorial__body{display:flex;flex-direction:column;justify-content:center;
  padding:clamp(40px,6vw,88px) clamp(24px,5vw,72px)}
.editorial__body .display{margin-bottom:var(--gap-sm)}
/* The cover story runs a portrait photograph, so its photo column narrows. */
.editorial--portrait{grid-template-columns:minmax(0,5fr) minmax(0,7fr)}
.editorial--portrait .editorial__media{min-height:clamp(460px,80vh,900px)}

/* Alternating rows. Flip reverses the columns and the motion with them, so a run of
   sections reads left, right, left instead of one centred column all the way down.
   order is used rather than direction:rtl so the DOM order stays the reading order
   and the photograph is still announced after the text it belongs to. */
.editorial{--from-media:-44px;--from-body:36px}
.editorial--flip{grid-template-columns:minmax(0,5fr) minmax(0,7fr);
  --from-media:44px;--from-body:-36px}
/* A photo row and a prose row put their columns in the DOM in opposite orders — the
   photo leads its row, the text leads its own — so the flip is scoped to each rather
   than one rule trying to serve both. */
.editorial--flip:not(.editorial--prose) .editorial__media{order:2}
.editorial--flip:not(.editorial--prose) .editorial__body{order:1}
.editorial--flip.editorial--portrait{grid-template-columns:minmax(0,7fr) minmax(0,5fr)}

/* A prose row has no photograph, so its second column carries a pull-quote or a short
   fact list instead of being left empty. Narrower than a photo column: the point is to
   counterweight the text, not to compete with it. */
.editorial--prose{grid-template-columns:minmax(0,7fr) minmax(0,4fr);align-items:center}
.editorial--prose.editorial--flip{grid-template-columns:minmax(0,4fr) minmax(0,7fr)}
.editorial--prose.editorial--flip .editorial__aside{order:1}
.editorial--prose.editorial--flip .editorial__body{order:2}
.editorial__aside{padding:clamp(32px,4vw,64px) clamp(24px,4vw,56px);align-self:center}
.editorial__aside .figure-mark{margin-bottom:var(--gap-xs)}
.editorial__aside dl{margin:0;display:grid;gap:var(--gap-sm)}
.editorial__aside dt{font-size:var(--t-label);letter-spacing:var(--track-mid);
  text-transform:uppercase;color:var(--ink-muted);margin-bottom:2px}
.editorial__aside dd{margin:0;font-family:var(--display);font-size:1.15rem;line-height:1.3}
.editorial__aside blockquote{margin:0;font-family:var(--display);font-weight:300;
  font-size:clamp(1.25rem,1.9vw,1.75rem);line-height:1.3;border-left:2px solid var(--jkd-gold);
  padding-left:clamp(16px,2vw,24px)}
.editorial__aside blockquote cite{display:block;margin-top:var(--gap-sm);font-style:normal;
  font-family:var(--sans);font-size:var(--t-label);letter-spacing:var(--track-mid);
  text-transform:uppercase;color:var(--ink-muted)}
/* The aside is the media cell for motion purposes, so it slides with the same rule. */
.reveal .editorial__aside{opacity:0;transform:translate3d(var(--from-media,-44px),0,0);
  transition:opacity 1200ms var(--ease-rise) 80ms,transform 1200ms var(--ease-rise) 80ms}
.reveal[data-seen="true"] .editorial__aside{opacity:1;transform:none}
@media (max-width:880px){
  .editorial--prose,.editorial--prose.editorial--flip{grid-template-columns:1fr}
  .editorial--flip .editorial__media,.editorial--flip .editorial__body,
  .editorial--prose.editorial--flip .editorial__aside{order:initial}
  .editorial__aside{padding-top:0}
}
@media (max-width:880px){
  .editorial{grid-template-columns:1fr}
  .editorial__media{min-height:clamp(300px,52vh,480px)}
}

/* Oversized editorial numeral. Deep Gray at low opacity, never gold. */
.figure-mark{font-family:var(--display);font-size:clamp(3.4rem,7vw,6rem);line-height:.9;
  font-weight:300;color:var(--jkd-steel-blue);opacity:.22;display:block;margin-bottom:-.18em}

/* ------------------------------------------------------- wider scale --- */
.display--stage{font-size:clamp(1.9rem,3.5vw,3.1rem);line-height:1.12;letter-spacing:.03em;max-width:26ch}
.eyebrow--spaced{letter-spacing:var(--track-xwide)}
.band--airy{padding:clamp(6rem,13vh,11rem) 0}

/* ------------------------------------------------------------ utility --- */
.visually-hidden{position:absolute;width:1px;height:1px;padding:0;margin:-1px;
  overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
.skip-link{position:absolute;left:-9999px;top:0;z-index:100;background:var(--jkd-deep-gray);color:#fff;
  padding:12px 20px;font-size:var(--t-label);letter-spacing:var(--track-mid);text-transform:uppercase}
.skip-link:focus{left:0}
.stack-sm>*+*{margin-top:var(--gap-sm)}
.stack-md>*+*{margin-top:var(--gap-md)}
.stack-lg>*+*{margin-top:var(--gap-lg)}
.mt-md{margin-top:var(--gap-md)}
.mt-lg{margin-top:var(--gap-lg)}
