/* ==========================================================================
   RAL PLANTATIONS SDN. BHD. — v3
   Design system: "Sequel" — private screening after dark.
   --------------------------------------------------------------------------
   THE RULE THAT GOVERNS EVERYTHING ELSE

   The interface is strictly achromatic: pure black, white, three neutral
   greys, and one warm off-white. 0% colorfulness. All warmth in this design
   comes from PHOTOGRAPHY, never from the chrome.

   That is why the forest green, agarwood brown and resin amber no longer
   appear as interface tones. The job amber used to do — marking an action —
   is now done by Lamp Cream #f5f5f0. Brown and green survive only inside the
   images, which are filtered warm-neutral to read as 35mm film stock.

   FONT SUBSTITUTION (both originals are licensed retail faces)
     VisueltPro -> Inter                    (grotesk, ss01 + cv11 on)
     Bradford   -> Instrument Serif italic  (display serif, italic only)
   Instrument Serif ships one weight (400) where Bradford specifies 500; at
   display sizes on black the difference is not legible.

   1.  Tokens
   2.  Reset & base
   3.  Type
   4.  Components
   5.  Navigation
   6.  Hero
   7.  Sections in document order
   8.  Footer
   9.  Responsive
   10. Reduced motion / print
   ========================================================================== */

/* ---------------------------------------------------------------- 1. TOKENS */
:root {
  /* Colour — the entire system */
  --void:     #000000;
  --white:    #ffffff;
  --charcoal: #202020;
  --graphite: #333333;
  --cream:    #f5f5f0;
  --smoke:    #999999;
  /* The one hue in an otherwise achromatic system. Reserved for the
     bento figure tiles — if it starts appearing elsewhere, it has
     stopped being an accent. Cream on it clears 4.6:1. */
  --resin:    #c0451a;

  /* Surfaces */
  --surface-0: var(--void);      /* canvas, nav, hero */
  --surface-1: var(--charcoal);  /* the single elevation step */
  --surface-2: var(--graphite);  /* hairlines, outlines */

  /* Type families */
  --f-sans:  "Inter", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --f-serif: "Instrument Serif", "Canela", "Tiempos Headline", Georgia, serif;

  /* Type scale — fluid, resolving to the spec sizes at 1440px */
  --t-display:  clamp(2.25rem, 1.2rem  + 4.2vw, 4.75rem);   /* ->  76px */
  --t-h1:       clamp(2.15rem, 1.35rem + 3.2vw, 3.5625rem); /* ->  57px */
  --t-h2:       clamp(1.9rem,  1.4rem  + 2.0vw, 3.375rem);  /* ->  54px */
  --t-h3:       clamp(1.35rem, 1.1rem  + 1.0vw, 1.875rem);  /* ->  30px */
  --t-body-lg:  1.25rem;   /* 20px */
  --t-body:     1rem;      /* 16px — never smaller for running text */
  --t-nav:      .9375rem;  /* 15px */
  --t-sm:       .875rem;   /* 14px */
  --t-label:    .75rem;    /* 12px */
  --t-label-sm: .6875rem;  /* 11px */
  --t-micro:    .625rem;   /* 10px — the floor */

  --w-light:   300;
  --w-regular: 400;
  --w-medium:  500;

  /* Spacing — 4px base */
  --s-4: 4px;   --s-8: 8px;   --s-12: 12px; --s-16: 16px;
  --s-20: 20px; --s-24: 24px; --s-28: 28px; --s-32: 32px;
  --s-40: 40px; --s-64: 64px; --s-80: 80px; --s-96: 96px;

  /* Layout */
  --page: 1200px;
  --pad:  clamp(20px, 4vw, 40px);
  --sect: clamp(64px, 7vw, 120px);
  /* Namespaced: Elementor sets a plain --gap on its containers, and it
     would otherwise inherit into our grids and override this. */
  --ral-gap: 20px;

  /* Radius */
  --r-card: 10px;
  --r-full: 9999px;

  /* Elevation — the ONLY two shadows in the system */
  --shadow-lg: rgba(0, 0, 0, .15) 0 4px 20px 0;
  --shadow-xl: rgba(0, 0, 0, .35) 0 10px 30px 0, rgba(255, 255, 255, .08) 0 1px 0 0 inset;

  /* Motion — slow-out, weighted, never springy */
  --e: cubic-bezier(.625, .05, 0, 1);
  --d: .28s;
  --d-fast: .2s;

  /* Art direction slots. One line each to swap in real photography. */
  /* Real photograph first, procedural placeholder second. A layer that
     fails to load simply is not painted, so the SVG shows through until
     hero-agarwood.jpg exists — the page never renders a blank hero. */
  --img-hero:       url("../img/hero-agarwood.jpg"), url("../img/tex-forest.svg");
  --img-origin:     url("../img/tex-foliage.svg");
  --img-wood:       url("../img/tex-wood.svg");
  --img-resin:      url("../img/tex-resin.svg");
  --img-oil:        url("../img/tex-oil.svg");
  --img-chips:      url("../img/tex-chips.svg");
  --img-block:      url("../img/tex-block.svg");
  --img-macro:      url("../img/tex-macro.svg");
  --img-plantation: url("../img/tex-plantation.svg");
}

/* Image slots applied through classes, never inline styles: url() in a custom
   property resolves against the DOCUMENT from an inline style attribute but
   against THIS FILE from a rule here. */
.i-hero       { background-image: var(--img-hero); }
.i-origin     { background-image: var(--img-origin); }
.i-wood       { background-image: var(--img-wood); }
.i-resin      { background-image: var(--img-resin); }
.i-oil        { background-image: var(--img-oil); }
.i-chips      { background-image: var(--img-chips); }
.i-block      { background-image: var(--img-block); }
.i-macro      { background-image: var(--img-macro); }
.i-plantation { background-image: var(--img-plantation); }

/* ------------------------------------------------------- 2. RESET & BASE */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; background: var(--void); }

body {
  margin: 0;
  background: var(--void);
  color: var(--white);
  font-family: var(--f-sans);
  font-size: var(--t-body);
  font-weight: var(--w-regular);
  line-height: 1.5;
  font-feature-settings: "ss01" on, "cv11" on;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}
body.is-locked { overflow: hidden; }

img, svg { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
::selection { background: var(--cream); color: var(--void); }

:focus-visible { outline: 1px solid var(--cream); outline-offset: 3px; }

.skip {
  position: fixed; top: 8px; left: 8px; z-index: 999;
  padding: 12px 24px; border-radius: var(--r-full);
  background: var(--cream); color: var(--void);
  font-size: var(--t-sm); font-weight: var(--w-medium);
  transform: translateY(-300%);
  transition: transform var(--d) var(--e);
}
.skip:focus { transform: none; }

.wrap { width: 100%; max-width: var(--page); margin-inline: auto; padding-inline: var(--pad); }
.sect { padding-block: var(--sect); }
.sect--tight { padding-block: calc(var(--sect) * .6); }

/* Section separator — graphite hairline only, never 1px solid white */
.rule { height: 1px; background: var(--graphite); border: 0; margin: 0; }

/* ------------------------------------------------------------- 3. TYPE */
h1, h2, h3, h4 { margin: 0; font-weight: var(--w-light); }
p { margin: 0; }

/* Display — the signature. Weight 500 at true display sizes. */
.display {
  font-size: var(--t-display);
  font-weight: var(--w-medium);
  line-height: 1;
  letter-spacing: -.05em;
  text-wrap: balance;
}
.h1 {
  font-size: var(--t-h1);
  font-weight: var(--w-medium);
  line-height: 1;
  letter-spacing: -.05em;
  text-wrap: balance;
}
/* Narrative headline — hairline 300, the whisper. */
.h2 {
  font-size: var(--t-h2);
  font-weight: var(--w-light);
  line-height: 1.2;
  letter-spacing: -.03em;
  text-wrap: balance;
}
.h3 {
  font-size: var(--t-h3);
  font-weight: var(--w-light);
  line-height: 1.2;
  letter-spacing: -.025em;
}

/* The only typographic flourish in the system: one italic serif payoff word,
   inline, lowercase, at the same size as the sans around it. */
.payoff {
  font-family: var(--f-serif);
  font-style: italic;
  font-weight: 400;
  letter-spacing: -.03em;
}

.body-lg { font-size: var(--t-body-lg); line-height: 1.5; color: var(--white); max-width: 58ch; }
.body    { font-size: var(--t-body); line-height: 1.5; color: var(--smoke); max-width: 62ch; }
.body + .body { margin-top: var(--s-20); }

/* Uppercase tracked labels do the work most sites give to colour. */
.label {
  font-size: var(--t-label-sm);
  font-weight: var(--w-medium);
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--smoke);
}
.label--white { color: var(--white); }
.label--micro { font-size: var(--t-micro); letter-spacing: .08em; }
.label--sm    { font-size: 13px; letter-spacing: .03em; font-weight: var(--w-regular); }

/* Tabular figures so digits keep a consistent width in the statistics row. */
.num { font-variant-numeric: tabular-nums; }

/* --------------------------------------------------------- 4. COMPONENTS */

/* Primary filled pill — the only filled button treatment in the system. */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s-8);
  height: 48px; padding-inline: var(--s-24);
  border-radius: var(--r-full);
  background: var(--cream);
  color: var(--void);
  font-size: var(--t-body);
  font-weight: var(--w-medium);
  white-space: nowrap;
  box-shadow: var(--shadow-lg);
  transition: opacity var(--d) var(--e), transform var(--d) var(--e);
}
.btn:hover  { opacity: .88; }
.btn:active { transform: translateY(1px); }
.btn--sm { height: 40px; padding-inline: var(--s-20); font-size: var(--t-nav); }

/* Ghost outline pill — the secondary, recedes into the canvas. */
.btn-ghost {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s-8);
  height: 48px; padding-inline: var(--s-20);
  border: 1px solid var(--white); border-radius: var(--r-full);
  color: var(--white);
  font-size: var(--t-body); font-weight: var(--w-medium);
  white-space: nowrap;
  transition: background-color var(--d) var(--e), color var(--d) var(--e);
}
.btn-ghost:hover { background: var(--white); color: var(--void); }
.btn-ghost--sm { height: 40px; font-size: var(--t-nav); }

/* Frosted glass badge. The inset white top edge is what makes it read as
   glass catching light rather than a flat translucent chip. */
.badge {
  display: inline-flex; align-items: center;
  padding: var(--s-8) var(--s-16);
  border-radius: var(--r-full);
  background: rgba(200, 200, 200, .1);
  backdrop-filter: blur(20px) saturate(1.4);
  -webkit-backdrop-filter: blur(20px) saturate(1.4);
  color: var(--white);
  font-size: var(--t-label-sm);
  font-weight: var(--w-medium);
  letter-spacing: .05em;
  text-transform: uppercase;
  box-shadow: var(--shadow-xl);
}

/*
 * Hero chip. It only ever sits over a photograph, so it carries its own
 * plate: a translucent black wash plus a blur, which holds the label legible
 * whether the frame behind it is bright canopy or deep shadow. Deliberately
 * translucent rather than solid — the point is that the picture still reads
 * through it.
 */
.chip {
  display: inline-flex; align-items: center;
  padding: var(--s-8) var(--s-16);
  border: 1px solid rgba(255,255,255,.28);
  border-radius: var(--r-full);
  font-size: var(--t-label-sm);
  font-weight: var(--w-medium);
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--cream);
  background: rgba(0,0,0,.38);
  -webkit-backdrop-filter: blur(8px);
          backdrop-filter: blur(8px);
}
/* No blur available: lean harder on the wash so the chip never goes flat. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .chip { background: rgba(0,0,0,.58); }
}

/* Elevated card — one tone step above the void. Never a shadow. */
.card {
  background: var(--charcoal);
  border-radius: var(--r-card);
  overflow: hidden;
}
.card__pad { padding: var(--s-32); }

/* Cinematic media card — full-bleed photograph, scrim, overlaid text. */
.media {
  position: relative;
  display: block;
  border-radius: var(--r-card);
  overflow: hidden;
  background-color: var(--charcoal);
  isolation: isolate;
}
/*
 * Hover wash. A background-color transition on .media itself would never be
 * seen — the photograph covers it — so the lift is painted as an overlay above
 * the image and below the card's own text.
 */
.media::after {
  content: ""; position: absolute; inset: 0; z-index: 1;
  background: var(--cream);
  opacity: 0;
  transition: opacity var(--d) var(--e);
  pointer-events: none;
}
.media:hover::after, .media:focus-visible::after { opacity: .12; }

.media__img {
  position: absolute; inset: 0;
  background-position: center;
  background-size: cover;
  /* Warm-neutral, slightly desaturated — 35mm film stock, not saturated
     digital. Applied globally so client photography inherits the treatment. */
  filter: saturate(.6) sepia(.1) contrast(1.04) brightness(.96);
  transform: scale(1);
  transition: transform 1.2s var(--e);
}
.media:hover .media__img { transform: scale(1.03); }

/* Mandatory readability scrim. Text is never placed on raw photography. */
.media__scrim {
  position: absolute; inset: 0;
  background: linear-gradient(to bottom, rgba(0,0,0,0) 60%, rgba(0,0,0,.55) 100%);
  pointer-events: none;
}
.media__scrim--full {
  background: linear-gradient(to bottom, rgba(0,0,0,.25) 0%, rgba(0,0,0,0) 35%, rgba(0,0,0,.72) 100%);
}
.media__body {
  position: relative;
  /* Above the hover wash, so the copy never dims with the card. */
  z-index: 3;
  display: flex; flex-direction: column; justify-content: flex-end;
  gap: var(--s-8);
  min-height: 100%;
  padding: var(--s-28);
}
.media__badge { position: absolute; top: var(--s-20); right: var(--s-20); z-index: 2; }
.media__title { font-size: 21px; font-weight: var(--w-medium); line-height: 1.2; letter-spacing: -.02em; }

/* Circular play button — floating glass, never inside a card. */
.play {
  display: inline-flex; align-items: center; gap: var(--s-12);
  padding: var(--s-8) var(--s-20) var(--s-8) var(--s-8);
  border: 1px solid var(--white);
  border-radius: var(--r-full);
  background: rgba(255, 255, 255, .08);
  backdrop-filter: blur(20px) saturate(1.4);
  -webkit-backdrop-filter: blur(20px) saturate(1.4);
  color: var(--white);
  font-size: 13px; font-weight: var(--w-regular);
  letter-spacing: .03em; text-transform: uppercase;
  transition: background-color var(--d) var(--e);
}
.play:hover { background: rgba(255, 255, 255, .16); }
.play__disc {
  display: grid; place-items: center;
  width: 32px; height: 32px;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, .5);
}
.play__disc svg { width: 10px; height: 10px; }

/* Text link with a rule that draws under it */
.tlink {
  display: inline-flex; align-items: center; gap: var(--s-8);
  font-size: var(--t-sm); font-weight: var(--w-medium);
  color: var(--white);
  padding-bottom: 4px;
  background-image: linear-gradient(var(--cream), var(--cream));
  background-size: 0 1px; background-repeat: no-repeat; background-position: 0 100%;
  transition: background-size var(--d) var(--e);
}
.tlink:hover { background-size: 100% 1px; }
.tlink svg { transition: transform var(--d) var(--e); }
.tlink:hover svg { transform: translateX(3px); }

/* Section heading pair — line 1 context, line 2 the italic serif payoff. */
/*
 * The measure belongs on the heading, not on the wrapper. `ch` resolves
 * against the element's own font-size, so 26ch on the wrapper was 26
 * characters of 16px body text — about 260px — and it broke a 57px headline
 * across five lines. On the heading it means what it says: 26 of its own
 * characters.
 */
.pair { display: grid; gap: var(--s-24); }
.pair > :is(h1, h2, h3, .display, .h1, .h2, .h3) { max-width: 20ch; }
.pair--wide > :is(h1, h2, h3, .display, .h1, .h2, .h3) { max-width: 26ch; }

/* Spec rows — graphite hairlines, uppercase keys, white values. */
.rows { display: grid; }
.rows > div {
  display: grid; grid-template-columns: minmax(120px, 24%) 1fr; gap: var(--s-24);
  padding-block: var(--s-20);
  border-top: 1px solid var(--graphite);
}
.rows > div:last-child { border-bottom: 1px solid var(--graphite); }
.rows dt, .rows b {
  font-size: var(--t-label-sm); font-weight: var(--w-medium);
  letter-spacing: .05em; text-transform: uppercase; color: var(--smoke);
}
.rows span { font-size: var(--t-body); color: var(--white); }

/* ------------------------------------------------------ 5. NAVIGATION */
/* Transparent over the hero, solid black once the photograph is behind you. */
.nav {
  position: fixed; inset: 0 0 auto; z-index: 90;
  background: transparent;
  border-bottom: 1px solid transparent;
  transition: background-color var(--d) var(--e), border-color var(--d) var(--e);
}
.nav.is-solid { background: var(--void); border-bottom-color: var(--graphite); }
.nav__in { display: flex; align-items: center; gap: var(--s-32); height: 96px; }

.logo { display: inline-flex; align-items: center; gap: var(--s-12); }
/* The BARA mark, used at its intended square. The traced artwork has no
   transparent interior — the disc is a filled shape — so it reads as a badge
   rather than as a knocked-out silhouette. */
.logo__badge { width: 80px; height: 80px; display: block; }
.logo__mark { display: flex; align-items: flex-end; gap: 3px; height: 16px; }
.logo__mark i { display: block; width: 2px; background: var(--white); }
.logo__mark i:nth-child(1) { height: 8px; }
.logo__mark i:nth-child(2) { height: 16px; }
.logo__mark i:nth-child(3) { height: 11px; }
.logo__mark i:nth-child(4) { height: 5px; }
.logo__word { font-size: var(--t-body-lg); font-weight: var(--w-medium); letter-spacing: -.03em; }

.nav__links { display: flex; align-items: center; gap: var(--s-32); margin-inline: auto; }
/*
 * wp_nav_menu always emits <li>. Without a list-style reset those render as
 * bullets between the links. The <ul> carries the row layout so that the
 * no-menu-assigned fallback, which emits bare <a>, still lays out from
 * .nav__links above.
 */
.nav__list { display: flex; align-items: center; gap: var(--s-32); list-style: none; margin: 0; padding: 0; }
.menu__list { display: grid; gap: var(--s-4); list-style: none; margin: 0; padding: 0; }

/* ------------------------------------------------- 5c. THE PRODUCTS PANEL */
/*
 * A single drop-down under the Products link. It hangs off .nav rather than
 * off the list item so it can span the full width regardless of where the
 * link sits, and it opens on hover *and* focus-within so a keyboard can reach
 * it without any JavaScript.
 */
.nav__has-panel > a::after {
  content: ""; display: inline-block; margin-left: 7px;
  width: 7px; height: 7px;
  border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor;
  transform: translateY(-2px) rotate(45deg);
  transition: transform var(--d-fast) var(--e);
}
.nav__has-panel:hover > a::after,
.nav__has-panel:focus-within > a::after { transform: translateY(1px) rotate(-135deg); }

/*
 * The panel hangs off the Products item rather than spanning the bar, so it
 * reads as that item's menu. `translate` does the centring and `transform` the
 * open/close motion — one property each, so the two never overwrite each other.
 *
 * The top padding is the bridge between the link and the panel: without it the
 * pointer crosses a gap with no hover in it and the panel closes on the way
 * down.
 */
.nav__has-panel { position: relative; }
.nav__panel {
  position: absolute; top: 100%; left: 50%;
  translate: -50% 0;
  width: 400px; max-width: calc(100vw - var(--s-32));
  padding: var(--s-12) 0 var(--s-24);
  opacity: 0; visibility: hidden;
  transform: translateY(-8px);
  transition: opacity var(--d-fast) var(--e), transform var(--d) var(--e), visibility var(--d);
}
.nav__has-panel:hover .nav__panel,
.nav__has-panel:focus-within .nav__panel { opacity: 1; visibility: visible; transform: none; }

.nav__panel-in {
  display: grid; gap: var(--s-16);
  /* Tighter than the columns' own padding, so the hover plate below can carry
     the breathing room instead and still line up with the panel edge. */
  padding: var(--s-20);
  background: var(--surface-1);
  border: 1px solid var(--surface-2);
  border-radius: var(--r-card);
  box-shadow: var(--shadow-xl);
}
/* One product per row: at 400px three columns would give each product ~120px,
   which is narrower than its own name. */
.nav__panel-grid {
  display: grid; grid-template-columns: 1fr; gap: var(--s-4);
}
/*
 * `.nav__links a` dims every link to .7 and declares its own transition. It
 * outranks a bare `.nav__panel-col` (one class + one type beats one class), so
 * the panel's opacity AND its transition have to be reclaimed at that same
 * weight — otherwise the hover plate appears instantly instead of fading.
 */
.nav__links .nav__panel-col {
  opacity: 1;
  transition: background var(--d-fast) var(--e);
}
.nav__panel-col {
  display: grid; gap: var(--s-4); align-content: start;
  padding: var(--s-12) var(--s-16);
  border-radius: var(--r-card);
  /* The hover target is the whole tile, not the words in it — at this size a
     text-only hover leaves most of the row dead to the pointer. */
  background: transparent;
}
.nav__panel-col:hover,
.nav__panel-col:focus-visible { background: var(--surface-2); }
.nav__panel-col b {
  font-size: var(--t-body); font-weight: var(--w-medium);
  color: var(--white); letter-spacing: -.01em;
}
.nav__panel-col span {
  font-size: var(--t-sm); line-height: 1.5; color: var(--smoke);
  transition: color var(--d-fast) var(--e);
}
.nav__panel-col:hover span, .nav__panel-col:focus-visible span { color: var(--cream); }

/* The way out of the panel and into the full list. */
.nav__panel-all {
  display: inline-flex; align-items: center; gap: var(--s-8);
  justify-self: start;
  padding: var(--s-12) var(--s-16);
  border-radius: var(--r-card);
  font-size: var(--t-sm); font-weight: var(--w-medium);
  color: var(--smoke);
  transition: background var(--d-fast) var(--e), color var(--d-fast) var(--e);
}
.nav__links .nav__panel-all {
  opacity: 1;
  transition: background var(--d-fast) var(--e), color var(--d-fast) var(--e);
}
.nav__panel-all:hover,
.nav__panel-all:focus-visible { background: var(--surface-2); color: var(--cream); }
.nav__links a {
  font-size: var(--t-nav); font-weight: var(--w-medium); color: var(--white);
  opacity: .7; transition: opacity var(--d-fast) var(--e);
}
.nav__links a:hover, .nav__links a[aria-current="true"] { opacity: 1; }

.burger { display: none; width: 44px; height: 44px; }
/* Line pitch is height + gap (3 + 5 = 8px), and the open-state X moves the
   outer lines exactly one pitch onto the middle one. Change the height or the
   margin and the two translateY values below have to follow. */
.burger i { display: block; width: 24px; height: 3px; background: var(--white); margin: 5px auto; transition: transform var(--d) var(--e), opacity var(--d-fast) var(--e); }
body.is-menu .burger i:nth-child(1) { transform: translateY(8px) rotate(45deg); }
body.is-menu .burger i:nth-child(2) { opacity: 0; }
body.is-menu .burger i:nth-child(3) { transform: translateY(-8px) rotate(-45deg); }

/*
 * Mobile menu — a full-screen sheet.
 *
 * It covers the whole viewport, header included: the bar sits above it
 * (z-index 90 over 89), so the links are pushed below the bar with padding
 * rather than with an offset. That way the black runs behind the bar too, and
 * the page never shows through above or below the links.
 *
 * The sheet opens by unclipping from the top edge, downwards, and closes the
 * same way back up. Clipping rather than sliding keeps the sheet's edge
 * straight and the links still while it opens. Visibility flips at the start
 * of the open and only after the close has finished, so the closed sheet
 * cannot be tabbed into or tapped.
 */
.menu {
  --menu-top: 96px;
  position: fixed; inset: 0; z-index: 89;
  height: 100vh; height: 100dvh;
  overflow-y: auto; overscroll-behavior: contain;
  background: var(--void);
  padding: calc(var(--menu-top) + var(--s-24)) var(--pad) var(--s-40);
  display: grid; align-content: start; gap: var(--s-4);
  visibility: hidden;
  clip-path: inset(0 0 100% 0);
  transition: clip-path .45s var(--e), visibility 0s linear .45s;
}
body.is-menu .menu {
  visibility: visible;
  clip-path: inset(0);
  transition: clip-path .45s var(--e), visibility 0s;
}

/*
 * The links come in after the sheet, one after another from the top, so the
 * eye follows the list downwards. Going out they all leave at once and faster
 * — once someone has chosen to close the menu, it shouldn't linger.
 */
.menu__list > li,
.menu > .btn {
  opacity: 0; transform: translateY(14px);
  transition: opacity .15s var(--e), transform .15s var(--e);
}
body.is-menu .menu__list > li,
body.is-menu .menu > .btn {
  opacity: 1; transform: none;
  transition: opacity .35s var(--e), transform .45s var(--e);
  transition-delay: calc(.14s + var(--i, 0) * .05s);
}
.menu__list > li:nth-child(2) { --i: 1; }
.menu__list > li:nth-child(3) { --i: 2; }
.menu__list > li:nth-child(4) { --i: 3; }
.menu__list > li:nth-child(5) { --i: 4; }
.menu__list > li:nth-child(6) { --i: 5; }
.menu__list > li:nth-child(n+7) { --i: 6; }
.menu > .btn { --i: 7; }
.menu a { padding: var(--s-16) 0; font-size: 30px; font-weight: var(--w-light); letter-spacing: -.025em; }
.menu .btn { margin-top: var(--s-16); }

/*
 * Products, inside the mobile menu. The desktop header hangs a hover panel off
 * this item; a touch screen has no hover, so here the same links are simply
 * listed — indented and set smaller so they read as belonging to the item
 * above rather than as five more top-level destinations.
 */
.menu__sub { list-style: none; margin: 0 0 var(--s-16); padding-left: var(--s-20); border-left: 1px solid var(--graphite); }
.menu__sub a { padding: var(--s-8) 0; font-size: var(--t-body-lg); color: var(--smoke); }
.menu__sub a:hover, .menu__sub a:focus-visible { color: var(--cream); }

/*
 * Back to top.
 *
 * Bottom-right, clear of the footer's own content. Same glass treatment as the
 * play button so it reads as part of the system rather than a plugin's badge,
 * and it fades rather than appearing — a control that pops into a corner reads
 * as an advert.
 */
.totop {
  position: fixed; right: var(--pad); bottom: var(--pad); z-index: 88;
  width: 44px; height: 44px;
  display: grid; place-items: center;
  border-radius: var(--r-full);
  color: var(--cream);
  background: rgba(0, 0, 0, .55);
  border: 1px solid rgba(255, 255, 255, .18);
  -webkit-backdrop-filter: blur(10px);
          backdrop-filter: blur(10px);
  box-shadow: var(--shadow-xl);
  cursor: pointer;
  opacity: 0; transform: translateY(8px);
  transition: opacity var(--d) var(--e), transform var(--d) var(--e),
              background var(--d-fast) var(--e);
}
.totop.is-in { opacity: 1; transform: none; }
.totop:hover { background: rgba(0, 0, 0, .78); }
.totop:focus-visible { outline: 2px solid var(--cream); outline-offset: 3px; }
.totop svg { display: block; }

/* No blur available: lean on the wash so the icon never sits on bare page. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .totop { background: rgba(0, 0, 0, .8); }
}

@media (prefers-reduced-motion: reduce) {
  .totop { transition: opacity var(--d-fast) linear; transform: none; }
}

/* ------------------------------------------------------- 5b. THE FORM */
/* One form on the site. Achromatic like everything else: fields are holes in
   the surface marked by a hairline, not raised boxes. */
.form { display: grid; gap: var(--s-20); }
.form__row { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s-20); }
.form__field { display: grid; gap: var(--s-8); margin: 0; }

.form__field label {
  font-size: var(--t-sm); letter-spacing: .04em; text-transform: uppercase;
  color: var(--smoke);
}

.form input[type="text"],
.form input[type="email"],
.form select,
.form textarea {
  width: 100%;
  font: inherit; font-size: var(--t-body);
  color: var(--white);
  background: transparent;
  border: 0; border-bottom: 1px solid var(--surface-2);
  border-radius: 0;              /* iOS rounds these by default. */
  padding: var(--s-12) 0;
  transition: border-color var(--d-fast) var(--e);
  -webkit-appearance: none; appearance: none;
}
.form textarea { resize: vertical; min-height: 120px; }

/* The select arrow, drawn rather than left to the platform, which would render
   a light-mode chevron on this dark surface. */
.form select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' fill='none'%3E%3Cpath d='M1 1l5 5 5-5' stroke='%23999' stroke-width='1.4' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right center;
  padding-right: var(--s-24);
}
.form select option { background: var(--charcoal); color: var(--white); }

.form :is(input, select, textarea):focus-visible {
  outline: none; border-bottom-color: var(--white);
}
.form :is(input, textarea)::placeholder { color: var(--graphite); }
.form :is(input, select, textarea)[aria-invalid="true"] { border-bottom-color: var(--white); }

.form__err { font-size: var(--t-sm); color: var(--white); opacity: .85; }

.form__foot {
  display: flex; align-items: center; gap: var(--s-24);
  flex-wrap: wrap; margin-top: var(--s-12);
}
.form__hint { font-size: var(--t-sm); color: var(--smoke); }

.form__note {
  padding: var(--s-16) var(--s-20);
  border: 1px solid var(--surface-2);
  font-size: var(--t-body);
}
.form__note--ok  { border-color: var(--white); }
.form__note--bad { border-color: var(--smoke); color: var(--white); }

/* The honeypot. Removed from the layout without display:none, which some bots
   check for, and taken out of the accessibility tree by aria-hidden. */
.form__hp {
  position: absolute !important;
  left: -9999px; width: 1px; height: 1px; overflow: hidden;
}

@media (max-width: 600px) {
  .form__row { grid-template-columns: 1fr; }
}

/* --------------------------------------------------- 5d. LOADING SCREEN */
/*
 * Three beats in two seconds: the mark draws itself as an outline, fills in,
 * then turns on its vertical axis like a coin. Then the screen clears.
 *
 *   0.10 - 0.90   outline draws
 *   0.75 - 1.10   fill (overlaps the draw's tail so there is no dead beat)
 *   1.10 - 1.70   coin turn
 *   1.70 - 2.00   screen fades out
 *
 * Retiming it means moving these four together — each one starts where the
 * previous one ends.
 *
 * Driven entirely by CSS, so it clears itself whether or not the script runs —
 * a loading screen that depends on JavaScript to go away is a blank page when
 * JavaScript fails. ral.js only removes the element afterwards.
 */
.loader {
  position: fixed; inset: 0; z-index: 200;
  display: grid; place-items: center;
  background: #333;
  perspective: 1200px;
  animation: loader-out .3s var(--e) 1.7s forwards;
}
.loader__mark {
  width: clamp(110px, 15vw, 180px); aspect-ratio: 1;
  transform-style: preserve-3d;
  /* The coin turn. Starts once the mark has finished filling in. */
  animation: loader-flip .6s var(--e) 1.1s both;
}
.loader .mark { width: 100%; height: 100%; display: block; }

/* The two halves of the trace: ink is the artwork, paper punches the shapes
   back out of it, so it has to match the screen behind. */
.loader .mark .paper { fill: #333; }

/*
 * Beat one: the ink starts unfilled and stroked, so what draws is a line
 * drawing of the mark. The fill has to be transparent here rather than in the
 * keyframes — a `from` in an animation that has not started yet does not
 * apply, so setting the final colour up front would show the mark solid from
 * the first frame and there would be no outline to watch.
 */
.loader .mark .ink {
  fill: transparent;
  stroke: var(--cream); stroke-width: 4;
  stroke-dasharray: 1; stroke-dashoffset: 1;
  animation: loader-draw .8s var(--e) .1s forwards,
             loader-fill .35s ease .75s forwards;
}
.loader .mark .paper { opacity: 0; animation: loader-paper .35s ease .75s forwards; }

@keyframes loader-draw  { to { stroke-dashoffset: 0; } }
@keyframes loader-fill  { to { fill: var(--cream); stroke-opacity: 0; } }
@keyframes loader-paper { to { opacity: 1; } }
@keyframes loader-flip  { from { transform: rotateY(0); } to { transform: rotateY(360deg); } }
@keyframes loader-out   { to { opacity: 0; visibility: hidden; } }

/* Nothing behind the loader should scroll while it is up. The rule lapses by
   itself once ral.js takes the element out of the document. */
body:has(.loader) { overflow: hidden; }

/*
 * Reduced motion: no draw, no spin, no two-second wait. The mark is shown
 * complete and the screen clears almost at once — the point is to not hold
 * someone on a page for an animation they asked not to see.
 */
@media (prefers-reduced-motion: reduce) {
  .loader { animation: loader-out .2s linear .35s forwards; }
  .loader__mark { animation: none; }
  .loader .mark .ink { animation: none; stroke: none; fill: var(--cream); }
  .loader .mark .paper { animation: none; opacity: 1; }
}

/* ------------------------------------------------------------ 6. HERO */
/* The photograph IS the fold. No nav-bar fold, no above-the-fold block. */
.hero {
  position: relative;
  min-height: 100svh;
  display: flex; align-items: flex-end;
  overflow: hidden;
  isolation: isolate;
}
.hero__img {
  position: absolute; inset: 0; z-index: -3;
  background-position: center; background-size: cover;
  /* The hero frame is greener than the rest of the library, so it takes a
     slightly harder pull toward warm-neutral than the global image grade. */
  filter: saturate(.5) sepia(.14) contrast(1.06) brightness(.88);
}
/*
 * Living smoke.
 *
 * The smoke is part of the photograph, so it cannot be animated on its own.
 * assets/js/ral-smoke.js draws a domain-warped noise field here instead and
 * screen-blends it over the frame, which is how backlit smoke behaves: it adds
 * light rather than covering what is behind it.
 *
 * It sits above the photograph and below the scrim, so the headline stays
 * readable no matter how thick the smoke gets. Hidden until the shader has
 * compiled, so a failed context leaves no empty blended box behind.
 */
.hero__smoke {
  position: absolute; inset: 0; z-index: -2;
  width: 100%; height: 100%;
  display: block;
  opacity: 0;
  mix-blend-mode: screen;
  pointer-events: none;
  transition: opacity 1.2s var(--e);
}
.hero__smoke.is-live { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  .hero__smoke { display: none; }
}

/* The only gradient in the system: a readability layer, not decoration. */
.hero__scrim {
  position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(to bottom, rgba(0,0,0,.55) 0%, rgba(0,0,0,.1) 30%, rgba(0,0,0,0) 60%, rgba(0,0,0,.55) 100%);
}
.hero__in {
  width: 100%;
  display: flex; align-items: flex-end; justify-content: space-between; gap: var(--s-40);
  /* The block sits well clear of the bottom edge: the lower third of the
     frame is moss and shadow, and the headline reads better lifted off it. */
  padding-block: var(--s-64) clamp(72px, 15vh, 190px);
}
/*
 * Internal pages: the hero introduces the page rather than being the page, so
 * it is a 360px banner and the first section of content starts in view.
 *
 * A minimum, not a fixed height: at 360 the headline and chips fit with room
 * to spare, but a long headline typed in Elementor, wrapping on a phone, would
 * be clipped by a hard height. Instead the banner grows only as far as the
 * text needs.
 */
.hero--short { min-height: 360px; }
/*
 * The full hero holds its headline high, clear of the moss and shadow in the
 * lower third of that photograph. A short hero has no such problem and the
 * generous bottom padding just strands the title mid-frame, so it sits lower.
 *
 * The top padding clears the fixed header (96px, 72px on small screens) by
 * 12px. The header sits over the banner rather than above it, so without this
 * a longer headline would grow upwards and slide underneath it.
 *
 * Both paddings are fixed and kept tight on purpose: a two-line display
 * headline plus its chips is ~206px, and 108 + 206 + 40 = 354 is what lets
 * that still land inside 360. A viewport-relative bottom padding would push
 * tall screens past 360 again.
 */
.hero--short .hero__in { padding-block: calc(96px + var(--s-12)) var(--s-40); }

.hero__title { display: grid; gap: var(--s-24); }
.hero__meta { display: flex; flex-wrap: wrap; gap: 15px; }
.hero__aside { display: grid; justify-items: end; gap: var(--s-20); flex: none; }

/* --------------------------------------------------- 7. SECTIONS */

/* Statement — a single hairline narrative headline on the void. */
.statement { display: grid; gap: var(--s-40); }
.statement__grid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s-64); align-items: start; }

/* Numbers — oversized, achromatic, static. */
.figures { display: grid; grid-template-columns: repeat(4, 1fr); }
.figure {
  display: grid; gap: var(--s-12);
  /* Centred, so the padding has to be symmetric — the old right-only inset
     was there to left-align the column against the hairline. */
  justify-items: center; text-align: center;
  padding: var(--s-40) var(--s-16);
  border-top: 1px solid var(--graphite);
}
.figure b {
  font-size: clamp(2.5rem, 1.4rem + 3.4vw, 4.5rem);
  font-weight: var(--w-light);
  line-height: 1; letter-spacing: -.05em;
  font-variant-numeric: tabular-nums;
}
.figure b sup { font-size: .34em; vertical-align: super; font-weight: var(--w-regular); }

/* Cinematic media grids */
/*
 * Bento grid.
 *
 * Four columns of equal width, with cells claiming one or two of them and one
 * or two rows. `dense` matters: without it a tall tile leaves a hole beside it
 * that nothing may fill, and the grid reads as a mistake rather than a layout.
 *
 * Rows are a fixed-ish height rather than `auto`, because the tiles have no
 * intrinsic height of their own — a photograph here is a background, and a
 * figure tile is two lines of text.
 */
.bento {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-auto-rows: minmax(180px, 22vw);
  grid-auto-flow: dense;
  gap: var(--ral-gap);
}
.b--wide { grid-column: span 2; }
.b--tall { grid-row: span 2; }
.b--big  { grid-column: span 2; grid-row: span 2; }

/* A bento photograph is the card without its furniture: no caption unless one
   was typed, so the scrim is the only thing between the image and the edge. */
.bento__img { min-height: 0; }
.bento__img .media__body { padding: var(--s-20); }

/*
 * Figure tile. Flat colour, no photograph, no shadow — it is the pause between
 * the pictures, and it earns its place by being the only thing on the page
 * that is not a photograph.
 */
.bento__stat {
  display: flex; flex-direction: column; justify-content: space-between;
  gap: var(--s-16);
  padding: var(--s-28);
  border-radius: var(--r-card);
}
.bento__num {
  font-size: clamp(2rem, 1.1rem + 3vw, 3.25rem);
  font-weight: var(--w-medium);
  line-height: 1;
  letter-spacing: -.03em;
}
.bento__label {
  font-size: var(--t-sm);
  line-height: 1.4;
  /* The number is the headline; the label is the caption under it. Same
     colour at a lower weight would flatten the two into one block. */
  opacity: .82;
}

.bento__stat--accent { background: var(--resin);   color: var(--cream); }
.bento__stat--dark   { background: var(--void);    color: var(--cream); border: 1px solid var(--surface-2); }
.bento__stat--light  { background: var(--cream);   color: var(--void); }

/*
 * Below the two-column breakpoint the shapes stop meaning anything: at two
 * columns a "wide" tile is the full width and a "tall" one is a tower. Only
 * the large tile keeps its span, because at that size it still reads as the
 * anchor of the grid.
 */
@media (max-width: 860px) {
  .bento { grid-template-columns: repeat(2, 1fr); grid-auto-rows: minmax(150px, 34vw); }
  .b--tall { grid-row: span 1; }
  .b--wide { grid-column: span 2; }
  .b--big  { grid-column: span 2; grid-row: span 1; }
}
@media (max-width: 520px) {
  .bento { grid-template-columns: 1fr; grid-auto-rows: minmax(160px, 46vw); }
  .b--wide, .b--big { grid-column: span 1; }
  .bento__stat { padding: var(--s-20); }
}

/*
 * Research papers. The card is the standard media card; these are the two
 * things it adds — the "Open PDF" cue under the title, and the editor-only
 * hint an empty section shows in Elementor.
 */
.paper__open {
  display: inline-flex; align-items: center; gap: var(--s-8);
  font-size: var(--t-label); font-weight: var(--w-medium);
  letter-spacing: .05em; text-transform: uppercase;
  color: var(--smoke);
  transition: color var(--d-fast) var(--e);
}
/* Arrow turned to point up and out: the standard "leaves this page" cue. */
.paper__arrow { transform: rotate(-45deg); transition: transform var(--d) var(--e); }
.paper:hover .paper__open, .paper:focus-visible .paper__open { color: var(--cream); }
.paper:hover .paper__arrow, .paper:focus-visible .paper__arrow { transform: rotate(-45deg) translateX(3px); }

.papers__empty {
  padding: var(--s-40) var(--s-32);
  border: 1px dashed var(--graphite); border-radius: var(--r-card);
  color: var(--smoke); font-size: var(--t-body); line-height: 1.5;
  max-width: none;
}

.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: var(--ral-gap); }
.grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--ral-gap); }
.story .media { min-height: 460px; }

/* Products */
.prod .media { min-height: 520px; }
.prod__lead { min-height: 640px; }

/* Oud — full-bleed still with a charcoal spec panel beside it */
.oud__grid { display: grid; grid-template-columns: 1.15fr .85fr; gap: var(--ral-gap); align-items: stretch; }
.oud__media { min-height: 620px; }
.oud__panel { display: flex; flex-direction: column; justify-content: center; gap: var(--s-32); }

/* Sustainability journey — a sparse numbered list, no connectors */
.journey { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1px; background: var(--graphite); border-block: 1px solid var(--graphite); }
.journey__n { background: var(--void); padding: var(--s-32) var(--s-24); display: grid; gap: var(--s-12); }
.journey__n em { font-style: normal; font-size: var(--t-label-sm); letter-spacing: .05em; color: var(--smoke); }
.journey__n b { font-size: var(--t-h3); font-weight: var(--w-light); letter-spacing: -.025em; }
.journey__n span { font-size: var(--t-sm); color: var(--smoke); }

/* Plantation — full-bleed cinematic band */
.band { position: relative; min-height: 88svh; display: flex; align-items: flex-end; overflow: hidden; }
.band__img { position: absolute; inset: 0; background-position: center; background-size: cover; filter: saturate(.6) sepia(.1) contrast(1.04) brightness(.88); }
.band__scrim { position: absolute; inset: 0; background: linear-gradient(to bottom, rgba(0, 0, 0, .7) 0%, rgba(0, 0, 0, 0) 40%, rgba(0, 0, 0, .7) 100%); }
.band__in { position: relative; width: 100%; padding-block: var(--s-64); }

/*
 * Post and field-note banner: 360px, the same as the internal-page banner, and
 * padded the same way — the top clears the fixed header (96px, 72px on small
 * screens) by 12px so a long title grows the banner downwards instead of
 * sliding under the header. A minimum, so a title that wraps to three lines
 * makes the banner taller rather than getting clipped.
 */
.band--post { min-height: 360px; }
.band--post .band__in { padding-block: calc(96px + var(--s-12)) var(--s-40); }
@media (max-width: 860px) {
  .band--post .band__in { padding-top: calc(72px + var(--s-12)); }
}

/* Marquee — the single long-duration motion in the system */
.marquee { overflow: hidden; border-block: 1px solid var(--graphite); padding-block: var(--s-24); }
.marquee__track { display: flex; width: max-content; animation: marquee 45s linear infinite; }
.marquee__track > span {
  display: inline-flex; align-items: center; gap: var(--s-64);
  padding-right: var(--s-64);
  font-size: var(--t-label); font-weight: var(--w-medium);
  letter-spacing: .08em; text-transform: uppercase; color: var(--smoke);
  white-space: nowrap;
}
@keyframes marquee { from { transform: translate3d(0,0,0); } to { transform: translate3d(-50%,0,0); } }

/* Field notes — sparse rows. Hovering one dims the others. */
.notes { display: grid; }
.note {
  display: grid; grid-template-columns: 160px 1fr auto; gap: var(--s-32); align-items: center;
  padding-block: var(--s-24);
  border-top: 1px solid var(--graphite);
  transition: opacity var(--d) var(--e);
}
.note:last-of-type { border-bottom: 1px solid var(--graphite); }
.notes:hover .note { opacity: .45; }
.notes .note:hover { opacity: 1; }
.note__img { aspect-ratio: 16/10; border-radius: var(--r-card); background-position: center; background-size: cover; filter: saturate(.6) sepia(.1) contrast(1.04); }
.note__t { display: grid; gap: var(--s-8); }
.note__arrow { color: var(--smoke); transition: transform var(--d) var(--e), color var(--d) var(--e); }
.note:hover .note__arrow { transform: translateX(4px); color: var(--white); }

/* Contact */
.contact__grid { display: grid; grid-template-columns: 1.1fr .9fr; gap: var(--s-64); align-items: center; }
.contact__actions { display: flex; flex-wrap: wrap; gap: var(--s-12); margin-top: var(--s-8); }

/* ------------------------------------- 7b. LONG-FORM CONTENT (WordPress)
   Everything the editor can produce inside a Field Note or a page. The rest of
   the site is composed markup; this is the one place arbitrary content lands,
   so it needs its own typographic contract. */
/*
 * Long-form text — Prose sections, posts, field notes, product write-ups. It
 * runs the full content width, lining up with every other section's edge.
 * It used to be held to a 68ch reading measure; at this size a full-width
 * line is ~100 characters, so if paragraphs start to feel long, a max-width
 * here (75-80ch) is the one knob to turn back.
 */
.note-body { font-size: var(--t-body-lg); line-height: 1.6; color: #B9B4A9; }
.note-body > * + * { margin-top: var(--s-24); }
.note-body h2 { font-size: var(--t-h3); font-weight: var(--w-light); color: var(--white); margin-top: var(--s-64); letter-spacing: -.025em; }
.note-body h3 { font-size: var(--t-body-lg); font-weight: var(--w-medium); color: var(--white); margin-top: var(--s-40); letter-spacing: -.01em; }
.note-body a { color: var(--white); text-decoration: underline; text-underline-offset: 4px; text-decoration-color: var(--graphite); transition: text-decoration-color var(--d-fast) var(--e); }
.note-body a:hover { text-decoration-color: var(--cream); }
.note-body strong { color: var(--white); font-weight: var(--w-medium); }
.note-body em { font-family: var(--f-serif); font-style: italic; color: var(--white); }
.note-body ul, .note-body ol { padding-left: 1.2em; display: grid; gap: var(--s-8); }
.note-body li::marker { color: var(--smoke); }
.note-body img, .note-body figure img { border-radius: var(--r-card); width: 100%; }
.note-body figure { margin: var(--s-40) 0; }
.note-body figcaption { margin-top: var(--s-12); font-size: var(--t-label-sm); letter-spacing: .05em; text-transform: uppercase; color: var(--smoke); }
.note-body blockquote {
  margin: var(--s-40) 0; padding-left: var(--s-24);
  border-left: 1px solid var(--graphite);
  font-family: var(--f-serif); font-style: italic;
  font-size: var(--t-h3); line-height: 1.3; color: var(--white);
}
.note-body hr { border: 0; height: 1px; background: var(--graphite); margin: var(--s-64) 0; }
.note-body code { font-size: .9em; background: var(--charcoal); padding: .1em .35em; border-radius: 4px; }
.note-body pre { background: var(--charcoal); padding: var(--s-24); border-radius: var(--r-card); overflow-x: auto; }

/* Pagination — WordPress markup, styled to the system */
.pagination .nav-links { display: flex; flex-wrap: wrap; gap: var(--s-8); align-items: center; }
.pagination .page-numbers {
  display: inline-grid; place-items: center;
  min-width: 40px; height: 40px; padding-inline: var(--s-12);
  border: 1px solid var(--graphite); border-radius: var(--r-full);
  font-size: var(--t-sm); color: var(--smoke);
  transition: border-color var(--d-fast) var(--e), color var(--d-fast) var(--e);
}
.pagination .page-numbers:hover { border-color: var(--smoke); color: var(--white); }
.pagination .page-numbers.current { background: var(--cream); border-color: var(--cream); color: var(--void); }

/* Contact card padding — was an inline style, now a class */
.cta__card { padding: clamp(1.5rem, 1rem + 2.4vw, 3rem); }

/* Lead product card sits above the two-up grid */
.prod__lead { margin-bottom: var(--ral-gap); }

/* WordPress core alignment + admin bar */
.alignwide { max-width: 1200px; }
.alignfull { max-width: none; }
.screen-reader-text {
  position: absolute !important; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}
body.admin-bar .nav { top: 32px; }
@media (max-width: 782px) { body.admin-bar .nav { top: 46px; } }

/* ------------------------------------------------------------ 8. FOOTER */
.ftr { border-top: 1px solid var(--graphite); padding-block: var(--sect) var(--s-40); }
.ftr__display { margin-bottom: var(--s-80); }
.ftr__grid { display: grid; grid-template-columns: 1.4fr repeat(3, .87fr); gap: var(--s-40); }
.ftr h4 { font-size: var(--t-label-sm); font-weight: var(--w-medium); letter-spacing: .05em; text-transform: uppercase; color: var(--smoke); margin-bottom: var(--s-20); }
.ftr ul { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s-12); font-size: var(--t-sm); }
.ftr ul a { opacity: .7; transition: opacity var(--d-fast) var(--e); }
.ftr ul a:hover { opacity: 1; }
.ftr__bot {
  display: flex; flex-wrap: wrap; gap: var(--s-16) var(--s-32); justify-content: space-between;
  margin-top: var(--s-64); padding-top: var(--s-24); border-top: 1px solid var(--graphite);
  font-size: var(--t-label-sm); letter-spacing: .05em; text-transform: uppercase; color: var(--smoke);
}

/* --------------------------------------------------------- 9. RESPONSIVE */
@media (max-width: 1100px) {
  .statement__grid,
  .oud__grid,
  .contact__grid { grid-template-columns: 1fr; gap: var(--s-40); }
  .oud__media { min-height: 460px; }
  .figures { grid-template-columns: repeat(2, 1fr); }
  .journey { grid-template-columns: repeat(2, 1fr); }
  .ftr__grid { grid-template-columns: 1fr 1fr; }
}

@media (max-width: 860px) {
  .nav__links, .nav__cta { display: none; }
  /*
   * On desktop it is .nav__links' auto margin that pushes everything after it
   * to the right. With the links hidden nothing does, so the burger would sit
   * against the logo — it has to claim the free space itself.
   *
   * The negative margin pulls the button's own 10px of side padding (44px tap
   * target, 24px of lines) past the edge, so the lines — not the invisible
   * button box — line up with the page gutter, as the logo does on the left.
   */
  .burger { display: block; margin-left: auto; margin-right: -10px; }
  .nav__in { height: 72px; }
  .logo__badge { width: 52px; height: 52px; }
  .menu { --menu-top: 72px; }
  .grid-2, .grid-3 { grid-template-columns: 1fr; }
  .hero__in { flex-direction: column; align-items: flex-start; gap: var(--s-32); }
  .hero--short .hero__in { padding-top: calc(72px + var(--s-12)); }
  .hero__aside { justify-items: start; }
  .story .media, .prod .media, .prod__lead { min-height: 420px; }
}

@media (max-width: 600px) {
  /* Portrait viewports crop a 16:9 frame hard on both sides. Bias the crop
     right so the wood and smoke stay in shot instead of the empty left third. */
  .hero__img { background-position: 62% 50%; }

  .figures { grid-template-columns: 1fr; }
  .journey { grid-template-columns: 1fr; }
  .note { grid-template-columns: 96px 1fr; gap: var(--s-20); }
  .note__arrow { display: none; }
  .ftr__grid { grid-template-columns: 1fr; gap: var(--s-32); }
  .rows > div { grid-template-columns: 1fr; gap: var(--s-8); }
  .card__pad { padding: var(--s-24); }
  .media__body { padding: var(--s-20); }
  .btn, .btn-ghost { width: 100%; }
  .hero__aside { width: 100%; }
}

/* -------------------------------------------- 10. REDUCED MOTION / PRINT */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important; animation-iteration-count: 1 !important;
    transition-duration: .001ms !important; scroll-behavior: auto !important;
  }
  .marquee__track { animation: none; }
  /* The global rule shortens durations but leaves delays alone, so the menu's
     staggered links would still wait before appearing. */
  .menu, .menu__list > li, .menu > .btn { transition-delay: 0s !important; }
}

@media print {
  .nav, .menu, .skip, .marquee { display: none !important; }
  body { background: #fff; color: #000; }
}
