// Pavilion Landscapes — Wireframe Shared Components
// Design system: Concept 2B — The Seasons / IBM Plex Sans, Leaf/Slate/Grass/Pale

// ─── TOKENS ────────────────────────────────────────────────
const LEAF  = '#174000';  // sparingly: select headlines, button fills
const SLATE = '#1a1a1a';  // primary text, subtitles, body
const GRASS = '#9dae93';  // sparingly: subtle emphasis, hover, light lines
const PALE  = '#e2e9da';  // light section backgrounds, separation only

const ACCENT = LEAF;
const G1 = '#fbfbfa';   // near-white page ground
const G2 = '#ececec';   // hairline
const G3 = '#d7ddd2';   // grass-tinted line
const G4 = GRASS;       // muted / quiet text
const G5 = '#4a4a4a';   // body
const G6 = '#2e2e2e';   // strong body
const G7 = SLATE;       // headline

const SERIF = "'the-seasons','The Seasons','Unna',serif";
const SANS  = "'IBM Plex Sans','Host Grotesk',sans-serif";

// One-time stylesheet for animated primitives
if (!document.getElementById('pav-ds')) {
  const s = document.createElement('style');
  s.id = 'pav-ds';
  s.textContent = `
@keyframes pavShift{0%{background-position:0% 50%}50%{background-position:100% 50%}100%{background-position:0% 50%}}
.pav-action{background:linear-gradient(100deg,#123300,#174000,#275910,#2a5f12,#174000,#123300)!important;background-size:280% 100%!important;animation:pavShift 9s ease-in-out infinite}
.pav-ar{display:inline-flex;align-items:center;flex-shrink:0}
.pav-ar i{display:block;height:1.2px;width:26px;background:currentColor;transition:width .2s ease-out}
.pav-hov:hover .pav-ar i{width:46px}
@keyframes pavWipe{from{-webkit-mask-position:100% 0;mask-position:100% 0}to{-webkit-mask-position:0% 0;mask-position:0% 0}}
.pav-wipe{-webkit-mask-image:linear-gradient(90deg,#000 0 34%,rgba(0,0,0,0) 66%);mask-image:linear-gradient(90deg,#000 0 34%,rgba(0,0,0,0) 66%);-webkit-mask-size:300% 100%;mask-size:300% 100%;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;animation:pavWipe 2.4s cubic-bezier(.4,.1,.2,1) both}
.pav-navitem{text-decoration:underline!important;text-decoration-color:transparent!important;text-underline-offset:5px;text-decoration-thickness:1px;transition:color .1s ease-out,text-decoration-color .1s ease-out}
.pav-navitem:hover,.pav-navitem-a{text-decoration-color:currentColor!important}
.pav-navitem-i:hover{color:${LEAF}!important}
.pav-navpanel{transition:opacity .42s cubic-bezier(.22,.75,.2,1),clip-path .42s cubic-bezier(.22,.75,.2,1),visibility .42s}
.pav-navscrim{transition:opacity .62s ease-out,visibility .62s}
.pav-ioc-scrim{opacity:.5;height:48%}
a{color:${LEAF};text-decoration:none}a:hover{color:${GRASS}}
.pav-link{color:${GRASS}}.pav-link:hover{color:${LEAF}}
`;
  document.head.appendChild(s);
}

let _uid = 0;

// ─── IMAGERY ───────────────────────────────────────────────
// Hard rule: every image container has an explicit height; image crops to fill.
function ImgBox({ width = '100%', height = 200, label = 'Image', style = {}, overlay = null, scrim = false }) {
  const id = 'wfp' + (++_uid);
  return (
    <div style={{ width, height, background: '#eceee9', position: 'relative', overflow: 'hidden', flexShrink: 0, display: 'block', ...style }}>
      <svg style={{ position: 'absolute', inset: 0, width: '100%', height: '100%' }} preserveAspectRatio="none">
        <defs>
          <pattern id={id} patternUnits="userSpaceOnUse" width="20" height="20">
            <line x1="0" y1="20" x2="20" y2="0" stroke={G3} strokeWidth="0.8"/>
          </pattern>
        </defs>
        <rect width="100%" height="100%" fill={`url(#${id})`}/>
        <line x1="0" y1="0" x2="100%" y2="100%" stroke={G3} strokeWidth="1.5"/>
        <line x1="100%" y1="0" x2="0" y2="100%" stroke={G3} strokeWidth="1.5"/>
      </svg>
      {scrim && <Scrim />}
      {overlay ? (
        <div style={{ position: 'absolute', inset: 0, zIndex: 2 }}>{overlay}</div>
      ) : (
        <div style={{ position: 'absolute', inset: 0, display: 'flex', alignItems: 'center', justifyContent: 'center', zIndex: 2 }}>
          <span style={{ fontFamily: 'monospace', fontSize: 11, color: G5, background: 'rgba(255,255,255,0.85)', padding: '3px 10px', border: `1px solid ${G3}` }}>{label}</span>
        </div>
      )}
    </div>
  );
}

// Top & bottom gradient scrim for full-bleed image sections
// Gradient scrim for full-bleed imagery. sides: 'both' (default) | 'top' | 'bottom'.
function Scrim({ band = '20%', opacity = 0.5, sides = 'both' }) {
  return (
    <div style={{ position: 'absolute', inset: 0, zIndex: 1, pointerEvents: 'none', opacity }}>
      {sides !== 'bottom' && <div style={{ position: 'absolute', top: 0, left: 0, right: 0, height: band, background: 'linear-gradient(to bottom, rgba(0,0,0,1), rgba(0,0,0,0))' }} />}
      {sides !== 'top' && <div style={{ position: 'absolute', bottom: 0, left: 0, right: 0, height: band, background: 'linear-gradient(to top, rgba(0,0,0,1), rgba(0,0,0,0))' }} />}
    </div>
  );
}

// Detail motif: a 1px rule runs off the image edge and continues as the
// left-hand border of adjacent text. Use for stat callouts & captioned images.
function EdgeRule({ children, style = {}, color = GRASS, pad = 18 }) {
  return <div style={{ borderLeft: `1px solid ${color}`, paddingLeft: pad, ...style }}>{children}</div>;
}

// ─── BUTTONS ───────────────────────────────────────────────
function Arrow() {
  return (
    <span className="pav-ar" style={{ marginLeft: 9 }}>
      <i />
      <svg width="8" height="10" viewBox="0 0 8 10" style={{ display: 'block', marginLeft: -6.2 }}><path d="M1 1 L6.2 5 L1 9" fill="none" stroke="currentColor" strokeWidth="1.2" strokeLinecap="butt"/></svg>
    </span>
  );
}

// Btn supplies its own animated arrow — call sites must not include a literal →
function stripArrow(children) {
  if (typeof children === 'string') return children.replace(/^\s*→\s*/, '').replace(/\s*→\s*$/, '');
  return children;
}

// variant: 'large' | 'action' | 'standard' | 'text' | (legacy) 'outline' → text, 'white'
function Btn({ children, variant = 'standard', small = false, full = false, style = {}, onClick }) {
  const label = stripArrow(children);
  const v = variant === 'primary' ? 'standard' : variant === 'outline' ? 'text' : variant;
  const base = {
    display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
    fontFamily: SANS, fontWeight: 500, letterSpacing: '0.01em',
    cursor: 'pointer', width: full ? '100%' : 'auto', flexShrink: 0, userSelect: 'none',
    lineHeight: 1.2, borderRadius: 0,
  };

  if (v === 'link') {
    return (
      <div className="pav-hov pav-link" onClick={onClick} style={{ ...base, fontFamily: SERIF, background: 'transparent', padding: 0, fontSize: small ? 19 : 22, fontWeight: 400, justifyContent: 'flex-start', width: 'auto', ...style }}>
        {label}<Arrow />
      </div>
    );
  }
  if (v === 'text') {
    return (
      <div className="pav-hov" onClick={onClick} style={{ ...base, background: 'transparent', color: LEAF, padding: 0, fontSize: small ? 16 : 18, fontWeight: 300, ...style }}>
        {label}<Arrow />
      </div>
    );
  }
  if (v === 'white') {
    return (
      <div className="pav-hov" onClick={onClick} style={{ ...base, background: '#fff', color: LEAF, padding: small ? '10px 20px' : '15px 32px', fontSize: small ? 13 : 15, ...style }}>
        {label}<Arrow />
      </div>
    );
  }
  if (v === 'large') {
    return (
      <div className="pav-hov" onClick={onClick} style={{ ...base, background: LEAF, color: '#fff', padding: '20px 40px', fontSize: 17, fontWeight: 500, ...style }}>
        {label}<Arrow />
      </div>
    );
  }
  if (v === 'action') {
    return (
      <div className="pav-hov pav-action" onClick={onClick} style={{ ...base, background: LEAF, color: '#fff', padding: small ? '10px 20px' : '13px 26px', fontSize: small ? 13 : 14, ...style }}>
        {label}<Arrow />
      </div>
    );
  }
  return (
    <div className="pav-hov" onClick={onClick} style={{ ...base, background: LEAF, color: '#fff', padding: small ? '10px 20px' : '13px 26px', fontSize: small ? 13 : 14, ...style }}>
      {label}<Arrow />
    </div>
  );
}

// ─── TYPE PRIMITIVES ───────────────────────────────────────
function Tag({ children }) {
  return <span style={{ fontFamily: SANS, fontSize: 12, background: PALE, padding: '4px 11px', color: LEAF, display: 'inline-block', marginRight: 6, marginBottom: 6 }}>{children}</span>;
}

function H1({ children, style = {} }) {
  return <div style={{ fontFamily: SERIF, fontWeight: 700, fontSize: 56, color: SLATE, lineHeight: 1.1, letterSpacing: '-0.01em', ...style }}>{children}</div>;
}
function H1m({ children, style = {} }) {
  return <div style={{ fontFamily: SERIF, fontWeight: 700, fontSize: 32, color: SLATE, lineHeight: 1.16, letterSpacing: '-0.01em', ...style }}>{children}</div>;
}
function H2({ children, style = {} }) {
  return <div style={{ fontFamily: SERIF, fontWeight: 400, fontSize: 38, color: SLATE, lineHeight: 1.2, letterSpacing: '-0.005em', ...style }}>{children}</div>;
}
function H2m({ children, style = {} }) {
  return <div style={{ fontFamily: SERIF, fontWeight: 400, fontSize: 25, color: SLATE, lineHeight: 1.26, ...style }}>{children}</div>;
}
function H3({ children, italic = false, style = {} }) {
  return <div style={{ fontFamily: SERIF, fontWeight: italic ? 400 : 700, fontStyle: italic ? 'italic' : 'normal', fontSize: 23, color: SLATE, lineHeight: 1.3, ...style }}>{children}</div>;
}
function H3m({ children, italic = false, style = {} }) {
  return <div style={{ fontFamily: SERIF, fontWeight: italic ? 400 : 700, fontStyle: italic ? 'italic' : 'normal', fontSize: 18, color: SLATE, lineHeight: 1.3, ...style }}>{children}</div>;
}
function Body({ children, small = false, muted = false, style = {} }) {
  return <div style={{ fontFamily: SANS, fontWeight: 400, fontSize: small ? 13 : 15, color: muted ? '#6d726a' : SLATE, lineHeight: 1.62, ...style }}>{children}</div>;
}
function Lbl({ children, style = {} }) {
  return <div style={{ fontFamily: SANS, fontSize: 11, color: '#6d726a', letterSpacing: '0.14em', textTransform: 'uppercase', fontWeight: 500, ...style }}>{children}</div>;
}
function Annot({ children, style = {} }) {
  return <div style={{ fontFamily: 'monospace', fontSize: 9, color: GRASS, border: `1px dashed ${G3}`, padding: '2px 7px', display: 'inline-block', ...style }}>⌦ {children}</div>;
}
// Breadcrumb — plain text trail, " → " separators. light: for use over imagery.
function Breadcrumb({ items = [], light = false, center = false, style = {} }) {
  const col = light ? 'rgba(255,255,255,0.88)' : '#6d726a';
  return (
    <div style={{ display: 'flex', flexWrap: 'wrap', alignItems: 'center', justifyContent: center ? 'center' : 'flex-start', gap: 8, fontFamily: SANS, fontSize: 13, fontWeight: 400, color: col, letterSpacing: '0.01em', ...style }}>
      {items.map((it, i) => (
        <React.Fragment key={i}>
          {i > 0 && <span style={{ opacity: 0.6 }}>→</span>}
          <span>{it}</span>
        </React.Fragment>
      ))}
    </div>
  );
}

function HR({ style = {} }) {
  return <div style={{ height: 1, background: G2, ...style }} />;
}
function WCard({ children, style = {}, pad = 20 }) {
  return <div style={{ border: `1px solid ${G3}`, background: '#fff', padding: pad, ...style }}>{children}</div>;
}
function SHead({ label, title, sub, center = false, m = false }) {
  return (
    <div style={{ marginBottom: m ? 24 : 36, textAlign: center ? 'center' : 'left' }}>
      {label && <Lbl style={{ marginBottom: 10, color: LEAF }}>{label}</Lbl>}
      {m ? <H2m style={{ marginBottom: 10 }}>{title}</H2m> : <H2 style={{ marginBottom: 14 }}>{title}</H2>}
      {sub && <Body style={{ maxWidth: center ? 560 : '100%', margin: center ? '0 auto' : 0 }}>{sub}</Body>}
    </div>
  );
}

// Process Flow — chevron-connected steps
function ProcessFlow({ steps, m }) {
  const nW = 20;
  if (m) {
    return (
      <div>
        {steps.map(([t, d], i) => (
          <div key={i} style={{ display: 'flex', marginBottom: 0 }}>
            <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', width: 36, flexShrink: 0 }}>
              <div style={{ width: 28, height: 28, background: LEAF, color: '#fff', display: 'flex', alignItems: 'center', justifyContent: 'center', fontFamily: SANS, fontSize: 11, zIndex: 1 }}>{String(i+1).padStart(2,'0')}</div>
              {i < steps.length-1 && <div style={{ width: 1, background: GRASS, flex: 1, minHeight: 20 }} />}
            </div>
            <div style={{ flex: 1, padding: `4px 0 ${i < steps.length-1 ? 22 : 0}px 14px` }}>
              <H3m style={{ marginBottom: 5 }}>{t}</H3m>
              <Body small muted>{d}</Body>
            </div>
          </div>
        ))}
      </div>
    );
  }
  return (
    <div style={{ display: 'flex' }}>
      {steps.map(([t, d], i) => {
        const isFirst = i === 0, isLast = i === steps.length - 1;
        const clip = isFirst
          ? `polygon(0 0, calc(100% - ${nW}px) 0, 100% 50%, calc(100% - ${nW}px) 100%, 0 100%)`
          : isLast
          ? `polygon(${nW}px 0, 100% 0, 100% 100%, ${nW}px 100%, 0 50%)`
          : `polygon(${nW}px 0, calc(100% - ${nW}px) 0, 100% 50%, calc(100% - ${nW}px) 100%, ${nW}px 100%, 0 50%)`;
        return (
          <div key={i} style={{ flex: 1, clipPath: clip, background: i % 2 === 0 ? '#fff' : PALE, padding: `26px ${isLast ? 20 : nW+10}px 26px ${isFirst ? 20 : nW+10}px`, marginLeft: i > 0 ? -(nW-1) : 0, display: 'flex', flexDirection: 'column', minHeight: 160 }}>
            <div style={{ width: 28, height: 28, background: LEAF, color: '#fff', display: 'flex', alignItems: 'center', justifyContent: 'center', fontFamily: SANS, fontSize: 11, marginBottom: 12 }}>{String(i+1).padStart(2,'0')}</div>
            <H3m style={{ marginBottom: 6 }}>{t}</H3m>
            <Body small muted>{d}</Body>
          </div>
        );
      })}
    </div>
  );
}

// ─── NAV — single hamburger-driven component, all breakpoints ──
const NAV_SUB = [['Installation','install'],['Maintenance','maintain'],['Living Landscapes Programme','living']];
const SERVICE_KEYS = ['services','install','maintain','living'];

function SiteNav({ active, onNav, m = false }) {
  const [open, setOpen] = React.useState(false);
  const [servOpen, setServOpen] = React.useState(false);
  const overHero = active === 'home';           // nav sits over the hero image
  const fg = overHero ? '#fff' : SLATE;
  const pad = m ? 20 : 64;
  const go = (k) => { onNav && onNav(k); setOpen(false); setServOpen(false); };

  const item = (name, key, isActive, indent = false, onClickOverride) => (
    <div key={name} className={`pav-navitem${overHero ? '' : ' pav-navitem-i'}${isActive ? ' pav-navitem-a' : ''}`} onClick={onClickOverride || (() => go(key))} style={{
      fontFamily: SERIF, fontSize: m ? (indent ? 15 : 19) : indent ? 18 : 22,
      fontWeight: isActive ? 700 : 400,
      color: overHero ? '#fff' : isActive ? LEAF : SLATE,
      opacity: overHero && !isActive ? 0.88 : 1,
      textDecoration: isActive ? 'underline' : 'none',
      textUnderlineOffset: 5, textDecorationThickness: 1,
      padding: indent ? '7px 0 7px 22px' : '9px 0',
      cursor: 'pointer', whiteSpace: 'nowrap', display: 'flex', alignItems: 'center', gap: 10,
    }}>{name}</div>
  );

  const list = (
    <div onMouseLeave={() => !m && setServOpen(false)} style={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-end' }}>
      {item('Request a Consultation', 'contact', active === 'contact')}
      <div onMouseEnter={() => setServOpen(true)} style={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-end' }}>
        {item('Our Services', 'services', active === 'services')}
        <div style={{
          display: 'flex', flexDirection: 'column', alignItems: 'flex-end',
          borderRight: `1px solid ${overHero ? 'rgba(255,255,255,0.4)' : GRASS}`, paddingRight: 16,
          maxHeight: (m || servOpen) ? 170 : 0, opacity: (m || servOpen) ? 1 : 0,
          marginBottom: (m || servOpen) ? 4 : 0, overflow: 'hidden',
          pointerEvents: (m || servOpen) ? 'auto' : 'none',
          transition: 'max-height .32s cubic-bezier(.3,.7,.2,1), opacity .26s ease-out, margin-bottom .32s cubic-bezier(.3,.7,.2,1)',
        }}>
          {NAV_SUB.map(([n, k]) => item(n, k, active === k, true))}
        </div>
      </div>
      {item('Our Story', 'story', active === 'story')}
      {item('Our Impact', 'impact', active === 'impact')}
      {item('Projects', 'projects', active === 'projects' || active === 'projcms')}
    </div>
  );

  const barH = m ? 106 : 140;
  const rootRef = React.useRef(null);
  const [hidden, setHidden] = React.useState(false);
  React.useEffect(() => {
    if (overHero) return;
    let sc = rootRef.current && rootRef.current.parentElement;
    while (sc && sc !== document.body) {
      const oy = getComputedStyle(sc).overflowY;
      if (oy === 'auto' || oy === 'scroll') break;
      sc = sc.parentElement;
    }
    const target = sc && sc !== document.body ? sc : window;
    const posOf = () => target === window ? window.scrollY : target.scrollTop;
    let last = posOf(), raf = 0, armed = false;
    // Ignore the mount-time scroll restore; start tracking once the page has settled.
    const arm = setTimeout(() => { last = posOf(); armed = true; }, 400);
    const onScroll = () => {
      cancelAnimationFrame(raf);
      raf = requestAnimationFrame(() => {
        const y = posOf();
        if (y <= barH) { setHidden(false); last = y; return; }
        if (!armed) { last = y; return; }
        if (y > last + 4) setHidden(true);
        else if (y < last - 4) setHidden(false);
        last = y;
      });
    };
    target.addEventListener('scroll', onScroll, { passive: true });
    return () => { clearTimeout(arm); target.removeEventListener('scroll', onScroll); cancelAnimationFrame(raf); };
  }, [overHero, barH]);
  const closeT = React.useRef(0);
  const latch = React.useRef(false);   // click-closed: ignore re-entry until a genuine mouseleave
  const hoverIn = () => { if (latch.current) return; clearTimeout(closeT.current); setOpen(true); };
  const hoverOut = () => { latch.current = false; clearTimeout(closeT.current); closeT.current = setTimeout(() => { setOpen(false); setServOpen(false); }, 240); };
  const toggle = () => { clearTimeout(closeT.current); setOpen(o => { const next = !o; latch.current = !next; return next; }); };
  const bar = (w) => <div style={{ width: w, height: 1.6, background: fg, transition: 'width .18s ease-out' }} />;

  return (
    <div ref={rootRef} style={{
      position: overHero ? 'absolute' : 'sticky', top: 0, left: 0, right: 0, zIndex: 200,
      background: overHero ? 'transparent' : '#fff',
      borderBottom: overHero ? 'none' : `1px solid ${G2}`,
      transform: hidden && !open ? `translateY(-${barH + 2}px)` : 'translateY(0)',
      transition: 'transform .34s cubic-bezier(.3,.7,.2,1)',
    }}>
      <div style={{ height: barH, display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: m ? `26px ${pad}px 0 ${pad - 12}px` : `0 ${pad}px`, position: 'relative', zIndex: 220 }}>
        <img src="uploads/Pavilion-Landscapes-Logo-01.png" onClick={() => go('home')}
          style={{ width: m ? 170 : 250, height: 'auto', cursor: 'pointer', filter: overHero ? 'brightness(0) invert(1)' : 'none' }} alt="Pavilion Landscapes" />
        <div onClick={toggle} onMouseEnter={hoverIn} onMouseLeave={hoverOut} style={{ cursor: 'pointer', padding: 8, color: fg, display: 'flex', alignItems: 'center', gap: 14 }}>
          <span style={{ fontFamily: SERIF, fontSize: m ? 17 : 20, color: fg, lineHeight: 1 }}>Menu</span>
          <div style={{ width: 38, height: 30, display: 'flex', flexDirection: 'column', gap: 7, alignItems: 'flex-end', justifyContent: 'center' }}>
            {open ? (
              <svg width="30" height="30" viewBox="0 0 30 30" style={{ display: 'block' }}><line x1="5" y1="5" x2="25" y2="25" stroke={fg} strokeWidth="1.6"/><line x1="25" y1="5" x2="5" y2="25" stroke={fg} strokeWidth="1.6"/></svg>
            ) : (
              <React.Fragment>{bar(38)}{bar(26)}{bar(38)}</React.Fragment>
            )}
          </div>
        </div>
      </div>
      {overHero && (
        <div className="pav-navscrim" style={{
          position: 'absolute', top: -barH * 0.85, right: m ? '-52%' : -430,
          width: m ? '215%' : 1680, height: m ? 900 : 1260,
          background: m
            ? 'radial-gradient(ellipse 78% 48% at 58% 28%, rgba(0,0,0,0.92), rgba(0,0,0,0.7) 36%, rgba(0,0,0,0.3) 64%, rgba(0,0,0,0) 100%)'
            : 'radial-gradient(ellipse 900px 700px at 70% 31%, rgba(0,0,0,0.92), rgba(0,0,0,0.7) 36%, rgba(0,0,0,0.3) 64%, rgba(0,0,0,0) 100%)',
          opacity: open ? 1 : 0, visibility: open ? 'visible' : 'hidden',
          pointerEvents: 'none', zIndex: 205,
        }} />
      )}
      {(
        <div className="pav-navpanel" onMouseEnter={hoverIn} onMouseLeave={hoverOut} style={{
          opacity: open ? 1 : 0,
          clipPath: open ? 'inset(0 0 0 0)' : 'inset(0 0 100% 0)',
          visibility: open ? 'visible' : 'hidden',
          pointerEvents: open ? 'auto' : 'none',
          background: overHero ? 'transparent' : '#fff',
          boxShadow: overHero ? 'none' : '0 18px 40px rgba(23,64,0,0.13)',
          padding: m ? '4px 20px 22px' : '10px 64px 36px',
          position: 'absolute', top: '100%', right: 0, left: m ? 0 : 'auto',
          minWidth: m ? 0 : 420, zIndex: 210,
        }}>{list}</div>
      )}
    </div>
  );
}

// Legacy aliases — both breakpoints now use the same component
const DesktopNav = (p) => <SiteNav {...p} m={false} />;
const MobileNav  = (p) => <SiteNav {...p} m={true} />;

// ─── FOOTER — white ground ─────────────────────────────────
function Footer({ m = false }) {
  const p = m ? 24 : 64;
  const col = m ? '1fr' : 'repeat(4, 1fr)';
  return (
    <div style={{ background: '#fff', borderTop: `1px solid ${G2}`, padding: `56px ${p}px 24px` }}>
      <div style={{ display: 'grid', gridTemplateColumns: col, gap: m ? 32 : 48, marginBottom: 40 }}>
        {/* Col 1: Certifications */}
        <div>
          <Lbl style={{ marginBottom: 16 }}>Certifications</Lbl>
          <div style={{ display: 'flex', gap: 10, flexWrap: 'wrap', marginBottom: 12 }}>
            {['ISO 9001','ISO 14001','ISO 45001'].map(iso => (
              <div key={iso} style={{ width: 70, height: 70, background: PALE, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', gap: 6 }}>
                <div style={{ width: 26, height: 26, borderRadius: '50%', border: `1px solid ${GRASS}` }} />
                <span style={{ fontFamily: SANS, fontSize: 8, color: LEAF, textAlign: 'center', letterSpacing: '0.04em' }}>{iso}</span>
              </div>
            ))}
          </div>
          <Annot>ISO badge placeholders</Annot>
        </div>
        {/* Col 2: Navigation */}
        <div>
          <Lbl style={{ marginBottom: 16 }}>Navigation</Lbl>
          {['Request a Consultation','Our Services','Our Story','Our Impact','Projects'].map(l => (
            <div key={l} style={{ fontFamily: SANS, fontSize: 14, color: SLATE, marginBottom: 10 }}>{l}</div>
          ))}
        </div>
        {/* Col 3: Contact */}
        <div>
          <Lbl style={{ marginBottom: 16 }}>Contact</Lbl>
          <Body small style={{ lineHeight: 2.1 }}>
            Ballygarvan, Co. Cork<br/>
            info@pavilionlandscapes.ie<br/>
            +353 21 XXX XXXX
          </Body>
        </div>
        {/* Col 4: Logo + tagline */}
        <div>
          <img src="uploads/Pavilion-Landscapes-Logo-01.png" style={{ height: 52, display: 'block', marginBottom: 16 }} alt="Pavilion Landscapes" />
          <Body small muted>Creating sustainable, beautiful<br/>landscapes across Ireland.</Body>
        </div>
      </div>
      <HR />
      <Body small muted style={{ textAlign: 'center', marginTop: 18, fontSize: 12 }}>© 2026 Pavilion Landscapes Ltd. All rights reserved. | Registered in Ireland</Body>
    </div>
  );
}

// ─── FIXED-HEIGHT IMAGE ────────────────────────────────────
// Never resizes to the source aspect ratio; always crops to fill.
function CropImg({ src, alt = '', height, scrim = false, pos = 'center center', style = {} }) {
  return (
    <div style={{ position: 'relative', width: '100%', height, overflow: 'hidden', flexShrink: 0, ...style }}>
      <img src={src} alt={alt} style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: 'cover', objectPosition: pos, display: 'block' }} />
      {scrim && <Scrim />}
    </div>
  );
}

// ─── STAT / META ROW ───────────────────────────────────────
// Site-wide meta row: 10px label over a Seasons value, each item on a left hairline.
function StatRow({ items, m = false, style = {} }) {
  return (
    <div style={{ maxWidth: 1180, margin: '0 auto', display: 'grid', gridTemplateColumns: m ? 'repeat(2,1fr)' : `repeat(${items.length},1fr)`, ...style }}>
      {items.map(([label, val], i) => (
        <div key={label} style={{
          padding: m ? '16px 0 16px 16px' : '22px 0 22px 26px',
          borderLeft: `1px solid ${G3}`,
          borderTop: m && i > 1 ? `1px solid ${G3}` : 'none',
        }}>
          <Lbl style={{ marginBottom: 6, fontSize: 10 }}>{label}</Lbl>
          <div style={{ fontFamily: SERIF, fontWeight: 400, fontSize: m ? 17 : 19, color: SLATE, lineHeight: 1.3 }}>{val}</div>
        </div>
      ))}
    </div>
  );
}

// ─── TESTIMONIAL ───────────────────────────────────────────
// Quote, then attribution below a horizontal rule aligned to the quote's baseline.
function TestimonialBlock({ quote, name, role, m = false, style = {} }) {
  const body = Array.isArray(quote) ? quote : [quote];
  return (
    <div style={{ ...style }}>
      <div style={{ marginBottom: m ? 20 : 26 }}>
        {body.map((para, i) => (
          <Body key={i} small style={{ marginBottom: i < body.length - 1 ? 12 : 0, fontStyle: 'italic' }}>{para}</Body>
        ))}
      </div>
      <div style={{ borderTop: `1px solid ${GRASS}`, paddingTop: m ? 14 : 18 }}>
        <div style={{ fontFamily: SANS, fontSize: 13, fontWeight: 600, color: SLATE, marginBottom: 3 }}>{name}</div>
        <div style={{ fontFamily: SANS, fontSize: 13, color: '#6d726a' }}>{role}</div>
      </div>
    </div>
  );
}

// ─── IMAGE OVERLAY CARD ────────────────────────────────────
function ImageOverlayCard({ src, title, desc, height = 300, m = false, style = {} }) {
  return (
    <div className="pav-ioc" style={{ position: 'relative', width: '100%', height, overflow: 'hidden', ...style }}>
      <img src={src} alt={title} style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: 'cover', display: 'block' }} />
      <div className="pav-ioc-scrim" style={{ position: 'absolute', left: 0, right: 0, bottom: 0, zIndex: 1, pointerEvents: 'none', background: 'linear-gradient(0deg, #000000, rgba(0,0,0,0))' }} />
      <div style={{ position: 'absolute', left: 0, right: 0, bottom: 0, padding: m ? '0 18px 20px' : '0 24px 26px', zIndex: 2, textShadow: '0px 4px 15px #0000007F' }}>
        {m ? <H3m style={{ color: '#fff', fontSize: 22, marginBottom: 7 }}>{title}</H3m>
           : <H3 style={{ color: '#fff', fontWeight: 400, marginBottom: 8 }}>{title}</H3>}
        <Body small style={{ color: 'rgba(255,255,255,0.88)', maxWidth: 420 }}>{desc}</Body>
      </div>
    </div>
  );
}

function PageShell({ children, m = false, active, onNav }) {
  return (
    <div style={{ background: G1, minHeight: '100%', position: 'relative' }}>
      <SiteNav active={active} onNav={onNav} m={m} />
      {children}
      <Footer m={m} />
    </div>
  );
}

Object.assign(window, {
  LEAF, SLATE, GRASS, PALE, SERIF, SANS,
  ACCENT, G1, G2, G3, G4, G5, G6, G7,
  ImgBox, Scrim, EdgeRule, Btn, Arrow, Tag, H1, H1m, H2, H2m, H3, H3m,
  Body, Lbl, Annot, HR, WCard, SHead, ProcessFlow, Breadcrumb,
  CropImg, StatRow, TestimonialBlock, ImageOverlayCard,
  SiteNav, DesktopNav, MobileNav, Footer, PageShell
});
