/* Mulberry — design tokens + base. Dark, warm; images carry it. */
:root {
  --bg: #0a0907; --bg-2: #141110; --fg: #efe6d8; --fg-dim: #a99c8c; --line: rgba(239,230,216,.12); --accent: #c98a4b;
  --maple: #e9d7b5; --walnut: #5a3a24; --mahogany: #7a2e21;
  --font-display: 'Fraunces Variable', Georgia, serif;
  --font-ui: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --ease: cubic-bezier(.2,.7,.2,1); --dur: 320ms;
  --max: 1280px;
  --s1: 4px; --s2: 8px; --s3: 12px; --s4: 16px; --s5: 24px; --s6: 40px; --s7: 64px; --s8: 112px;
  --gutter: clamp(16px, 4vw, 48px);
  --header-h: 64px;
  --radius: 2px;
  color-scheme: dark;
}
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; background: var(--bg); }
body {
  margin: 0; background: var(--bg); color: var(--fg);
  font: 400 15px/1.55 var(--font-ui); letter-spacing: .01em;
  -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-rendering: optimizeLegibility;
  min-height: 100vh; display: flex; flex-direction: column;
}
main { flex: 1 0 auto; }
body:not(.is-home) main { padding-top: var(--header-h); }
img, svg, video, canvas, picture { display: block; max-width: 100%; }
img { height: auto; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; padding: 0; cursor: pointer; }
h1, h2, h3, h4 { font-family: var(--font-display); font-weight: 400; line-height: 1.1; margin: 0; letter-spacing: .005em; }
h1 { font-size: clamp(36px, 5vw, 64px); }
h2 { font-size: clamp(28px, 3.4vw, 44px); }
h3 { font-size: clamp(22px, 2.2vw, 28px); }
p { margin: 0; }
::selection { background: var(--accent); color: var(--bg); }

.wrap { max-width: var(--max); margin: 0 auto; padding: 0 var(--gutter); }
.display { font-family: var(--font-display); }
.label { font: 500 11px/1.4 var(--font-ui); letter-spacing: .16em; text-transform: uppercase; color: var(--fg-dim); }
.price, .tabular { font-family: var(--font-display); font-variant-numeric: tabular-nums lining-nums; }
.dim { color: var(--fg-dim); }
.visually-hidden { position: absolute !important; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.skip { position: fixed; left: var(--s4); top: var(--s4); z-index: 100; padding: var(--s2) var(--s4); background: var(--fg); color: var(--bg);
  transform: translateY(-200%); transition: transform var(--dur) var(--ease); }
.skip:focus { transform: none; }

/* focus */
:focus { outline: none; }
:focus-visible { outline: 1.5px solid var(--accent); outline-offset: 3px; border-radius: var(--radius); }

/* buttons */
.btn, .btn-ghost {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s2);
  min-height: 48px; padding: 0 var(--s5); border-radius: var(--radius);
  font: 500 12px/1 var(--font-ui); letter-spacing: .16em; text-transform: uppercase;
  transition: background-color var(--dur) var(--ease), color var(--dur) var(--ease), border-color var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.btn { background: var(--fg); color: var(--bg); border: 1px solid var(--fg); }
.btn:hover { background: var(--accent); border-color: var(--accent); color: var(--bg); }
.btn:active, .btn-ghost:active { transform: scale(.98); }
.btn[disabled], .btn[aria-disabled="true"] { opacity: .45; pointer-events: none; }
.btn-ghost { background: transparent; color: var(--fg); border: 1px solid var(--line); }
.btn-ghost:hover { border-color: var(--fg-dim); }
.btn-block { width: 100%; }
.linkish { font: inherit; }

/* header */
.site-header {
  position: fixed; inset: 0 0 auto 0; z-index: 50; height: var(--header-h);
  display: flex; align-items: center; justify-content: space-between;
  padding: 0 var(--gutter); padding-top: env(safe-area-inset-top);
  isolation: isolate;
}
.site-header::before, .site-header::after { content: ''; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  transition: opacity var(--dur) var(--ease); }
.site-header::before { background: linear-gradient(to bottom, rgba(10,9,7,.72), rgba(10,9,7,0)); height: 160%; }
.site-header::after { background: var(--bg); border-bottom: 1px solid var(--line); opacity: 0; }
.site-header.is-solid::before { opacity: 0; }
.site-header.is-solid::after { opacity: 1; }
.top-sentinel { position: absolute; top: 0; left: 0; width: 1px; height: 80px; pointer-events: none; }
.logo { display: flex; flex-direction: column; align-items: flex-start; font-family: var(--font-display); font-size: 16px;
  line-height: .95; letter-spacing: .26em; text-transform: uppercase; white-space: nowrap; padding: var(--s1) 0; }
.logo span { display: block; }
@media (max-width: 420px) { .logo { font-size: 13.5px; letter-spacing: .22em; } }
.header-actions { display: flex; align-items: center; gap: var(--s1); margin-right: calc(var(--s2) * -1); }
.icon-btn { position: relative; width: 44px; height: 44px; display: grid; place-items: center; border-radius: 50%; }
.cart-count { position: absolute; top: 6px; right: 4px; min-width: 16px; height: 16px; padding: 0 4px; border-radius: 8px;
  background: var(--accent); color: var(--bg); font: 600 10px/16px var(--font-ui); text-align: center; font-variant-numeric: tabular-nums; }
.cart-count[hidden] { display: none; }
.burger span { position: absolute; left: 13px; width: 18px; height: 1.4px; background: currentColor; border-radius: 1px;
  transition: transform var(--dur) var(--ease), opacity var(--dur) var(--ease); }
.burger span:nth-child(1) { transform: translateY(-6px); }
.burger span:nth-child(3) { transform: translateY(6px); }
.burger[aria-expanded="true"] span:nth-child(1) { transform: rotate(45deg); }
.burger[aria-expanded="true"] span:nth-child(2) { opacity: 0; transform: scaleX(.2); }
.burger[aria-expanded="true"] span:nth-child(3) { transform: rotate(-45deg); }

/* drawers (nav + cart shell). Visible = not [hidden]; .is-open is the "in" state; entry also animates via @starting-style. */
.drawer { position: fixed; inset: 0; z-index: 40; background: rgba(8,7,6,.6); opacity: 1;
  transition: opacity var(--dur) var(--ease); }
.drawer[hidden] { display: none; }
.drawer.is-closing { opacity: 0; }
.drawer-inner { position: absolute; top: 0; right: 0; bottom: 0; width: min(420px, 100vw); overflow-y: auto; overscroll-behavior: contain;
  background: var(--bg-2); border-left: 1px solid var(--line); padding: calc(var(--header-h) + var(--s5)) var(--s6) var(--s6);
  transform: none; transition: transform var(--dur) var(--ease); }
.drawer.is-closing .drawer-inner { transform: translateX(100%); }
@starting-style {
  .drawer:not([hidden]) { opacity: 0; }
  .drawer:not([hidden]) .drawer-inner { transform: translateX(100%); }
}
#cart-drawer { z-index: 60; }
#cart-drawer .drawer-inner { padding-top: var(--s6); }
.nav-list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s1); }
.nav-list a, .nav-list button { display: block; width: 100%; text-align: left; padding: var(--s3) 0; font-family: var(--font-display);
  font-size: 30px; line-height: 1.15; transition: color var(--dur) var(--ease); }
.nav-list .nav-sub a { font-size: 20px; padding: var(--s2) 0 var(--s2) var(--s4); color: var(--fg-dim); }
.nav-list a:hover, .nav-list button:hover { color: var(--accent); }
html.drawer-open { overflow: hidden; }

/* images */
.pic { display: block; background-color: var(--bg-2); overflow: hidden; }
.pic img { width: 100%; height: 100%; object-fit: cover; }
.img-ph { width: 100%; aspect-ratio: 4 / 5; background:
  radial-gradient(60% 50% at 50% 42%, rgba(201,138,75,.16), transparent 70%), var(--bg-2); border: 1px solid var(--line); }

/* hero: modefade tier set, fit 'extend' (fits the height, continues the picture off the sides — no bars at any aspect).
   #hero is the modefade container; the SSR .hero-poster (the set's own AVIF tier poster) sits on top until the first frame. */
.hero-scroller { position: relative; height: 340vh; }   /* 100vh of hero + 240vh of picture (t 0 -> 1 = .hero-tend = the whole scroller): the lamp goes out exactly as the sticky hero releases and the first feature follows (no dark hold; was 360vh with a 20vh beat, 2026-10-30) */
#hero { position: sticky; top: 0; width: 100%; height: 100vh; height: 100svh; overflow: hidden; background: #000; }
#hero > .modefade { position: absolute; inset: 0; }
/* end of the hero -> page: the lamp goes out into pure black, the page is --bg (not quite black). hero.js fades this --bg sheet in
   over the last stretch of the dim-out (t 0.9 -> 1, eased in), so at t 1 the hero IS the page colour and the first feature
   follows with no step. Above the canvas / poster / line, never above the header (z 50). */
.hero-end { position: absolute; inset: 0; z-index: 3; background: var(--bg); opacity: 0; pointer-events: none; will-change: opacity; }
/* fitted to the height and centred, like fit 'extend' (narrower viewport = centred crop; wider = the extension shows after) */
.hero-poster { position: absolute; top: 0; left: 50%; height: 100%; width: auto; max-width: none; transform: translateX(-50%);
  z-index: 1; pointer-events: none;
  transition: opacity 600ms var(--ease); }
.hero-poster.is-hidden { opacity: 0; }
.hero-poster.is-slow { transition: opacity 1600ms cubic-bezier(.45,0,.55,1); }   /* deadline reveal from black: symmetric, no fast start */
/* hero copy overlays: opacity/transform set per frame from the scroll t (hero.js); hidden until scroll takes over */
.hero-line, .hero-copy { position: absolute; left: 50%; z-index: 2; margin: 0; pointer-events: none; opacity: 0;
  font-family: var(--font-display); color: #f3ebdf; text-align: center; text-shadow: 0 1px 18px rgba(0,0,0,.45);
  will-change: opacity, transform; }
.hero-line { bottom: calc(max(var(--s5), env(safe-area-inset-bottom)) + 56px); width: min(92vw, 30em);
  transform: translateX(-50%); font-size: clamp(1.35rem, 1rem + 1.6vw, 2.25rem); line-height: 1.2;
  letter-spacing: .01em; }   /* the page's h1 (was a <p>): keep the body letter-spacing, not the h1 one */
.hero-copy { top: 50%; width: min(88vw, 34em); transform: translate(-50%, calc(-50% + 12px));
  font-size: clamp(1.05rem, .95rem + .45vw, 1.35rem); line-height: 1.45; }
.hero-copy p + p { margin-top: 1em; }
.scroll-cue { position: absolute; left: 50%; bottom: max(var(--s5), env(safe-area-inset-bottom)); z-index: 2; width: 44px; height: 44px;
  margin-left: -22px; display: grid; place-items: center; color: var(--fg); opacity: .7;
  transition: opacity var(--dur) var(--ease); animation: cue 2.4s var(--ease) infinite; }
.scroll-cue.is-hidden { opacity: 0; pointer-events: none; }
@keyframes cue { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(6px); } }

/* sections */
.section { padding: var(--s8) 0; }
.section-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s4); margin-bottom: var(--s6);
  padding-bottom: var(--s4); border-bottom: 1px solid var(--line); }

/* product grid */
.grid { display: grid; gap: var(--s6) var(--s5); grid-template-columns: repeat(auto-fill, minmax(min(100%, 280px), 1fr)); }
.lineup { margin: var(--s6) 0 0; } .lineup .pic, .lineup img { display: block; width: 100%; height: auto; }
.card { display: block; }
.card .pic, .card .img-ph { aspect-ratio: 4 / 5; transition: opacity var(--dur) var(--ease); }
.card .pic img { transition: transform 900ms var(--ease); }
.card:hover .pic img { transform: scale(1.025); }
.card-body { display: grid; grid-template-columns: 1fr auto; gap: var(--s1) var(--s4); padding-top: var(--s4); align-items: baseline; }
.card-name { font-family: var(--font-display); font-size: 24px; line-height: 1.2; }
.card-price { font-size: 18px; color: var(--fg); }
.card-price small { font: 400 11px var(--font-ui); letter-spacing: .14em; text-transform: uppercase; color: var(--fg-dim); margin-right: 6px; }
.card-dims { grid-column: 1 / -1; color: var(--fg-dim); font-size: 13px; font-variant-numeric: tabular-nums; }

/* specs strip */
.specs-strip { display: grid; grid-template-columns: repeat(4, 1fr); border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); }
.specs-strip li { list-style: none; padding: var(--s6) var(--s5); border-left: 1px solid var(--line);
  font-family: var(--font-display); font-size: 19px; line-height: 1.35; }
.specs-strip li:first-child { border-left: 0; }
.specs-strip { margin: 0; padding: 0; }
@media (max-width: 900px) { .specs-strip { grid-template-columns: repeat(2, 1fr); }
  .specs-strip li:nth-child(3) { border-left: 0; } .specs-strip li:nth-child(n+3) { border-top: 1px solid var(--line); } }
@media (max-width: 520px) { .specs-strip { grid-template-columns: 1fr; } .specs-strip li { border-left: 0; padding: var(--s5) 0; }
  .specs-strip li + li { border-top: 1px solid var(--line); } }

/* footer */
.site-footer { border-top: 1px solid var(--line); padding: var(--s6) 0 calc(var(--s6) + env(safe-area-inset-bottom)); color: var(--fg-dim); font-size: 13px; }
.footer-row { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--s4); }
.footer-mark { font-family: var(--font-display); font-size: 15px; letter-spacing: .14em; color: var(--fg); }
.footer-links { display: flex; gap: var(--s5); }
.footer-links a:hover { color: var(--fg); }

/* simple pages */
.page { padding: var(--s7) 0 var(--s8); }
.page h1 { margin-bottom: var(--s5); }
.copy-ph { color: var(--fg-dim); font-family: var(--font-ui); font-size: 14px; margin-top: var(--s4); }

/* dev font toast */
.font-toast { position: fixed; left: 50%; bottom: var(--s6); z-index: 200; transform: translate(-50%, 8px); opacity: 0;
  padding: var(--s3) var(--s5); background: var(--fg); color: var(--bg); border-radius: 999px; font: 500 13px var(--font-ui);
  letter-spacing: .04em; pointer-events: none; transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease); }
.font-toast.is-on { opacity: 1; transform: translate(-50%, 0); }

@media (prefers-reduced-motion: reduce) {
  /* the homepage hero (and the header / cue fading in with its intro) keeps its motion: Owen wants it to play regardless */
  *:not(#hero, #hero *, .hero-poster, html.mh-fadein .site-header, html.mh-fadein .scroll-cue), *::before, *::after {
    transition: none !important; animation: none !important; scroll-behavior: auto !important; }
}

/* workaround: modefade sets object-fit:extend (invalid) on its CSS-fallback imgs; the inline value is dropped, so this applies */
#hero img, #hero canvas { object-fit: cover; }

/* page-load blackout (homepage): html.mh-intro is set inline in <head> before first paint; hero.js removes it once the
   intro's first (black) WebGL frame is up, or on any fallback; a 6 s inline timeout removes it if JS never runs. */
html.mh-intro .site-header, html.mh-intro .hero-poster, html.mh-intro .scroll-cue { opacity: 0 !important; }
/* header + cue fade on the intro's timeline (hero.js sets the vars from the intro / fade length: delay 10 %, duration 75 %) */
html.mh-fadein .site-header, html.mh-fadein .scroll-cue { transition: opacity var(--mh-fade-ms, 2200ms) cubic-bezier(.5,0,.75,1) var(--mh-fade-delay, 800ms); }   /* gentle ease-in: white UI keeps step with the picture */
/* scroll position where the hero reaches t = 1 (blackout): the marker's bottom edge meets the viewport bottom. Height = 100vh of
   hero + 240vh of scroll for the picture (unchanged pacing from the 400vh scroller; "Hero smoothness pass") = the whole scroller,
   so t 1 is the moment the sticky hero releases (the 20vh / 60vh black holds after it are gone, 2026-10-30). Kept as an element:
   hero.js and scripts/hero-check.mjs read it. */
.hero-tend { position: absolute; top: 0; left: 0; width: 1px; height: 100%; visibility: hidden; pointer-events: none; }

/* logo mark (lattice r20 from the lamp's kumiko panel, brand/mulberry-logo-lattice-r20.svg) left of the wordmark */
.logo { flex-direction: row; align-items: center; gap: 12px; }
.logo-mark { width: 34px; height: 34px; flex: none; display: block; }
.logo-text { display: flex; flex-direction: column; align-items: flex-start; }
@media (max-width: 420px) { .logo-mark { width: 28px; height: 28px; } .logo { gap: 9px; } }

/* cart button hidden while the cart is empty (html.mh-no-cart set by the inline <head> check + cart.js updateBadge) */
html.mh-no-cart .site-header .cart-btn { display: none; }

/* polish pass 2026-10-25: the specs strip follows the lamps section directly (no doubled section padding);
   balanced wraps (no single-word last lines); footer links get 44 px tap targets; the 404 buttons get a real gap */
.section-specs { padding-top: 0; }
.specs-strip li, .hero-copy p, .hero-line, .card-name { text-wrap: balance; }
.footer-links a { display: inline-flex; align-items: center; min-height: 44px; }
.site-footer { padding-top: var(--s5); }
.page .btn-row { display: flex; flex-wrap: wrap; gap: var(--s3); }
.logo { min-height: 44px; }

/* Owen 2026-10-25: (1) the menu X sits exactly where the hamburger was. Locking scroll for a drawer removed the desktop
   scrollbar and the fixed header widened, shifting the X ~15 px right; a stable gutter keeps the width constant. The X is
   drawn at the hamburger's visual width. */
html { scrollbar-gutter: stable; }
.burger span { top: 50%; margin-top: -.7px; }
.burger[aria-expanded="true"] span:nth-child(1) { transform: rotate(45deg) scaleX(1.18); }
.burger[aria-expanded="true"] span:nth-child(3) { transform: rotate(-45deg) scaleX(1.18); }
/* (2) larger, bolder, slightly tighter wordmark with more room in the corner */
.logo { font-size: 22px; font-weight: 500; letter-spacing: .2em; gap: 14px; }
.logo-mark { width: 44px; height: 44px; }
@media (max-width: 420px) {
  .logo { font-size: clamp(15.5px, 4.85vw, 19px); letter-spacing: .17em; gap: 10px; }
  .logo-mark { width: clamp(32px, 9.7vw, 38px); height: clamp(32px, 9.7vw, 38px); }
}
/* (3) tagline: twice as far from the bottom of the hero, 1.4x the size (timing unchanged: hero.js drives opacity only) */
.hero-line { bottom: calc(2 * (max(var(--s5), env(safe-area-inset-bottom)) + 56px)); width: min(92vw, 22em);
  font-size: clamp(1.89rem, 1.4rem + 2.24vw, 3.15rem); }
/* (3b) tagline sits only over the dark floor band of the night frames. The hero always fits the picture's height (every tier
   crop is the full 1600 px), so that band is the same fraction of the hero's height at every aspect: v 0.70-0.97 (below the
   lit panel). Default: centred at 83.5 % of the hero height; hero.js refines it from the actual frame (placeLine). */
.hero-line { bottom: auto; top: 83.5%; transform: translate(-50%, -50%); }
@media (max-width: 359px) { .logo { font-size: 14.5px; letter-spacing: .15em; gap: 8px; } .logo-mark { width: 30px; height: 30px; } }

/* Owen 2026-10-25 (logo hugged the top): the header is sized from the logo's ink, not its font box. The mark is the tallest
   ink (wordmark caps sit inside it), so header height = mark + 2 x P, the logo's left padding is the same P, and the right
   padding is P - 5 so the hamburger/cart ink sits P from the edge too (the icon ink is inset 13 px in its 44 px tap box,
   less the -8 px row margin). Logo and icons share the header's vertical centre in both header states. */
:root { --hdr-p: 26px; --header-h: 92px; }
@media (max-width: 899px) { :root { --hdr-p: 22px; --header-h: 84px; } }
@media (max-width: 420px) { :root { --hdr-p: 20px; --header-h: 76px; } }
@media (max-width: 359px) { :root { --hdr-p: 18px; --header-h: 66px; } }
.site-header { padding-left: var(--hdr-p); padding-right: calc(var(--hdr-p) - 5px); }

/* Fraunces as the default display face (Owen 2026-10-25): opsz follows the font size automatically (text cut at body sizes,
   display cut on headlines); SOFT/WONK are not in the shipped file, so they stay at 0. Light-on-dark reads heavier, so large
   headings sit a touch lighter than 400 and slightly tighter; Fraunces has a much larger x-height than Cormorant, so the
   serif body uses come down a step. (Static picker fonts round 360 to their nearest weight, 400.) */
:root { font-optical-sizing: auto; }
h1, h2, .pi-name, .cart-title { font-weight: 360; letter-spacing: -.008em; }
h3, .card-name { font-weight: 400; letter-spacing: 0; }
.card-name { font-size: 22px; }
.specs-strip li { font-size: 17px; line-height: 1.45; }
.footer-mark { letter-spacing: .08em; }
.hero-copy { font-weight: 380; }

/* header logo glow (2026-10-25): warm amber bloom on hover (real pointers only, so a tap never leaves it stuck) and on keyboard
   focus; ~350 ms in/out; instant under prefers-reduced-motion */
.logo-mark { transition: filter 350ms var(--ease); }
.logo-text { transition: text-shadow 350ms var(--ease); }
@media (hover: hover) and (pointer: fine) {
  .logo:hover .logo-mark { filter: drop-shadow(0 0 5px rgba(232,164,92,.55)) drop-shadow(0 0 14px rgba(201,138,75,.35)); }
  .logo:hover .logo-text { text-shadow: 0 0 8px rgba(232,164,92,.5), 0 0 22px rgba(201,138,75,.3); }
}
.logo:focus-visible .logo-mark { filter: drop-shadow(0 0 5px rgba(232,164,92,.55)) drop-shadow(0 0 14px rgba(201,138,75,.35)); }
.logo:focus-visible .logo-text { text-shadow: 0 0 8px rgba(232,164,92,.5), 0 0 22px rgba(201,138,75,.3); }
@media (prefers-reduced-motion: reduce) { .logo-mark, .logo-text { transition: none; } }
