/* ═══════════════════════════════════════════════════════════════════════════
   MOODY GROVE — shared design system
   Palette sampled from 45 grove photographs. The interface supplies paper, ink
   and one ember; the plants supply every other colour on the page.
   Loaded by every destination so the system exists once, not six times.
   ═══════════════════════════════════════════════════════════════════════════ */
:root{
  --paper:#F5EFE4; --paper-2:#EDE5D6; --paper-3:#E4DAC7;
  --ink:#1B1E14;   --ink-2:#5C5F45;   --rule:#797B58;
  --accent:#D94B18; --gold:#C6AC26;

  --serif:'Fraunces',Georgia,serif;
  --sans:'Inter',system-ui,-apple-system,sans-serif;
  --mono:'IBM Plex Mono',ui-monospace,Menlo,monospace;

  /* seven steps, far apart — scale is the difference between a page and a spread */
  --t7:clamp(52px,10vw,150px); --t6:clamp(30px,5vw,72px); --t5:clamp(21px,2.4vw,31px);
  --t4:18px; --t3:16px; --t2:13px; --t1:10.5px;
  --gutter:clamp(20px,6vw,110px);

  /* ── legacy token bridge ──────────────────────────────────────────────────
     The Apothecary's markup was authored against the old dark theme and refers
     to these names throughout. Rather than rewrite 140 rules by hand — and risk
     losing content Brad asked to keep intact — the names are re-pointed at the
     paper palette, so the existing rules invert themselves. */
  --bg:var(--paper);       --surface:var(--paper-2);
  --surface2:var(--paper-2); --surface3:var(--paper-3);
  --cream:var(--ink);      --white:var(--ink);
  --lteal:var(--ink-2);    --teal:var(--rule);
  --peach:var(--accent);   --orange:var(--accent);
  --purple:#6A5AA8;
  --border:rgba(27,30,20,.14); --border2:rgba(27,30,20,.22);
}
*{box-sizing:border-box;margin:0;padding:0}
html{-webkit-font-smoothing:antialiased;scroll-behavior:smooth}
/* ── THE PAPER ────────────────────────────────────────────────────────────
   The ground was a flat colour value with a 5% grain floating over the top of
   everything — which reads as dirt on the screen, not as a sheet. Paper is two
   things at once, so this is two layers, and they SCROLL WITH THE PAGE because
   the sheet is the thing you are moving down:

     tooth   160px tile, high frequency — the fibre. Also dithers the layer
             below it, which is what stops low-alpha gradients banding on an
             8-bit display.
     mottle  700px tile, very low frequency — broad unevenness in the stock.
             This is the layer that actually kills "flat", and it has to be
             large or it reads as a repeating pattern.

   Both are black at low alpha, multiplied into --paper, so the palette is
   unchanged and only the surface gains depth. Costs two data URIs and no
   requests. */
body{
  background-color:var(--paper);
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='t' filterUnits='userSpaceOnUse' x='0' y='0' width='160' height='160'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='4' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0.29 0 0 0 0 0.24 0 0 0 0 0.15 0 0 0 0.09 0'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23t)'/%3E%3C/svg%3E"),
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='900' height='900'%3E%3Cfilter id='m' filterUnits='userSpaceOnUse' x='0' y='0' width='900' height='900'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.0055' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0.31 0 0 0 0 0.26 0 0 0 0 0.17 0 0 0 0.055 0'/%3E%3C/filter%3E%3Crect width='900' height='900' filter='url(%23m)'/%3E%3C/svg%3E");
  background-size:160px 160px,900px 900px;
  background-blend-mode:multiply,multiply;
  color:var(--ink);font-family:var(--sans);
  font-size:var(--t3);line-height:1.6}
img{display:block;max-width:100%}
a{color:inherit}
button{font:inherit;color:inherit}
:focus-visible{outline:2px solid var(--accent);outline-offset:3px}
h1,h2,h3{text-wrap:balance}
p{text-wrap:pretty}

.skip{position:absolute;left:-9999px;background:var(--ink);color:var(--paper);
      padding:12px 18px;z-index:999}
.skip:focus{left:12px;top:12px}

/* A fixed grain over the whole viewport, now that the paper carries its own
   texture. Its only remaining job is the photography — it stops the canopies
   reading as stock — so it drops to a third of its old weight; at .05 it was
   also darkening the new paper a second time. */
body::after{content:'';position:fixed;inset:0;z-index:900;pointer-events:none;
  opacity:.018;mix-blend-mode:multiply;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.82' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='220' height='220' filter='url(%23n)'/%3E%3C/svg%3E")}

.eyebrow,.s-eyebrow{font-family:var(--mono);font-size:var(--t1);letter-spacing:.24em;
  text-transform:uppercase;color:var(--ink-2)}

/* ── primary navigation ───────────────────────────────────────────────────
   Every destination used to offer only "back to home" plus one arbitrary
   sibling, so getting from The Grove to the Apothecary meant returning home
   first. Five destinations, reachable from all of them, on every page.
   difference blend keeps it legible over any canopy photograph without a bar. */
/* Legibility was previously left to mix-blend-mode:difference, which inverts
   against whatever photograph happens to be underneath — fine over an even
   canopy, unreadable over a bright mushroom cap or a pale fence, and worse
   with five links than with two. Replaced by two explicit states:
     over the hero — light type on a soft gradient that guarantees contrast
     once scrolled  — ink type on paper, with a hairline
   Predictable on every image, instead of hoping the pixels cooperate. */
.topbar{position:fixed;top:0;left:0;right:0;z-index:120;display:flex;
  justify-content:space-between;align-items:center;gap:16px;
  padding:14px var(--gutter);
  transition:background-color .35s ease,box-shadow .35s ease}
/* The scrim has to clear the WORST pixel under it, not the average — this hero
   puts a white roof and a pale driveway directly behind the links. A 54px strip
   at .62 was not enough; it now runs well past the bar so it reads as light
   falling off, not as a band. */
.topbar::before{content:'';position:absolute;left:0;right:0;top:0;
  height:clamp(104px,13vh,148px);pointer-events:none;z-index:-1;
  background:linear-gradient(rgba(12,15,9,.82) 0%,rgba(12,15,9,.55) 40%,
             rgba(12,15,9,.22) 74%,transparent 100%);
  transition:opacity .35s ease}
.topbar a,.topbar button{font-family:var(--mono);font-size:var(--t1);letter-spacing:.2em;
  text-transform:uppercase;text-decoration:none;color:#F5EFE4;
  text-shadow:0 1px 10px rgba(12,15,9,.55)}

/* scrolled past the hero: the bar sits on paper and stops pretending */
.topbar.stuck{background:rgba(245,239,228,.94);backdrop-filter:blur(8px);
  box-shadow:0 1px 0 rgba(27,30,20,.16)}
.topbar.stuck::before{opacity:0}
.topbar.stuck a,.topbar.stuck button{color:var(--ink);text-shadow:none}
.topbar.stuck .tb-menu a{opacity:.66}
.topbar.stuck .tb-menu a:hover,.topbar.stuck .tb-menu a:focus-visible{opacity:1}
.topbar.stuck .tb-menu a[aria-current="page"]{opacity:1;color:var(--accent);
  border-bottom-color:var(--accent)}
.tb-mark{flex:none}
.tb-menu{list-style:none;display:flex;gap:clamp(14px,2.2vw,30px);align-items:center;margin:0;padding:0}
.tb-menu a{opacity:.72;transition:opacity .25s}
.tb-menu a:hover,.tb-menu a:focus-visible{opacity:1}
/* the page you are on is stated, not hidden — one less thing to work out */
.tb-menu a[aria-current="page"]{opacity:1;border-bottom:1px solid currentColor;padding-bottom:2px}
.tb-toggle{display:none;background:none;border:0;cursor:pointer;font-family:var(--mono);
  font-size:var(--t1);letter-spacing:.2em;text-transform:uppercase;color:#F5EFE4;padding:4px 0}

@media(max-width:820px){
  /* The drawer is opt-IN via .js, added by script. Without JS the menu simply
     stays on the page as a wrapped row — navigation must never depend on a
     toggle that never got wired. */
  .topbar{flex-wrap:wrap}
  .topbar.js .tb-toggle{display:block}
  .topbar.js .tb-menu{position:fixed;top:0;left:0;right:0;flex-direction:column;
    align-items:flex-start;gap:2px;background:var(--ink);padding:60px var(--gutter) 26px;
    transform:translateY(-101%);transition:transform .38s cubic-bezier(.2,.8,.2,1)}
  .tb-menu{gap:10px 18px;flex-wrap:wrap}
  .tb-menu a{opacity:1;font-size:var(--t2);letter-spacing:.16em}
  .topbar.js .tb-menu a{padding:10px 0;display:block}
  .topbar.open{mix-blend-mode:normal}
  .topbar.open .tb-menu{transform:none}
  .topbar.open .tb-mark,.topbar.open .tb-toggle{color:var(--paper);position:relative;z-index:2}
  /* The drawer's ground is --ink. Scrolled past the hero, .stuck flips bar type
     to --ink for the paper state — which over the open drawer is dark on dark,
     and every link disappears except the current page, the one item .stuck also
     paints in --accent. Hence "the menu only shows one link" after scrolling.
     While the drawer is open its own colours have to win, stuck or not. */
  .topbar.open .tb-menu a,
  .topbar.open.stuck .tb-menu a{color:var(--paper);opacity:1;text-shadow:none}
  .topbar.open.stuck .tb-menu a[aria-current="page"]{color:var(--accent);opacity:1}
}


/* ── onward link: the page always offers somewhere next ─────────────────── */
.onward{border-top:1px solid var(--ink);margin:0 var(--gutter);padding:clamp(28px,4vh,44px) 0;
  display:flex;flex-wrap:wrap;gap:10px 26px;align-items:baseline;justify-content:space-between}
.onward .ow-lbl{font-family:var(--mono);font-size:var(--t1);letter-spacing:.2em;
  text-transform:uppercase;color:var(--ink-2)}
.onward a{font-family:var(--serif);font-weight:300;font-size:var(--t5);text-decoration:none;
  line-height:1.05;font-variation-settings:'opsz' 48}
.onward a:hover{color:var(--accent)}

/* ── canopy: one image, one idea ── */
.canopy{position:relative;min-height:74svh;display:flex;align-items:flex-end;
  overflow:hidden;padding:0 var(--gutter) clamp(40px,7vh,76px);background:var(--ink)}
.canopy-media{position:absolute;inset:0;overflow:hidden}
.canopy-media img{width:100%;height:100%;object-fit:cover;transform-origin:56% 44%;
  animation:canopy-push 46s ease-out forwards}
@keyframes canopy-push{from{transform:scale(1)}to{transform:scale(1.11)}}
.canopy-scrim{position:absolute;inset:0;background:linear-gradient(to top,
  rgba(12,15,9,.88) 0%,rgba(12,15,9,.42) 40%,rgba(12,15,9,.20) 100%)}
.canopy-inner{position:relative;color:var(--paper)}
.canopy .eyebrow{color:rgba(245,239,228,.76);display:block;margin-bottom:.8em}
.canopy h1{font-family:var(--serif);font-weight:300;font-size:var(--t7);line-height:.88;
  letter-spacing:-.028em;font-variation-settings:'opsz' 144,'WONK' 1;color:var(--paper)}

/* ── section furniture ── */
section{padding:clamp(52px,8vh,110px) var(--gutter)}
.sec-head{border-top:1px solid var(--ink);padding-top:18px;margin-bottom:clamp(24px,4vh,44px)}
.sec-head h2,.s-title{font-family:var(--serif);font-weight:300;font-size:var(--t6);
  line-height:1;letter-spacing:-.02em;margin-top:.18em;font-variation-settings:'opsz' 72}
.sec-head p,.s-sub{font-size:var(--t4);color:var(--ink-2);max-width:54ch;
  margin-top:.7em;line-height:1.55}

footer{border-top:1px solid var(--ink);margin:0 var(--gutter);
  padding:26px 0 clamp(48px,7vh,88px);font-family:var(--mono);font-size:var(--t1);
  letter-spacing:.14em;text-transform:uppercase;color:var(--ink-2);
  display:flex;flex-wrap:wrap;gap:12px 34px;justify-content:space-between}
footer a{text-decoration:none;border-bottom:1px solid rgba(121,123,88,.4)}

@media(prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  .canopy-media img{animation:none}
  *{transition-duration:.01ms!important}
}
