/* v4.jsx — "Letterhead"
   A direction that deliberately walks away from BlastBoard's bezel cards
   and capsule nav. Feels like a real engineering trade document:
   • A real letterhead masthead with a huge logo and contact details across
   • Sharp rectangles only — no rounded bezels, no eyebrow pills
   • Image slots for real site photography
   • Services laid out as a capability sheet, tabular
   • Cream-on-white layering with ruled hairlines */

function V4Page() {
  useV4Reveals();
  return (
    <div className="v4-root" style={{
      background: 'var(--bo-paper)',
      color: 'var(--ink-900)',
      fontFamily: 'var(--font-sans)',
      width: '100%',
      overflow: 'hidden',
    }}>
      <V4ResponsiveStyles />
      <V4MotionStyles />
      <V4Letterhead />
      <V4Hero />
      <V4Services />
      <V4Selected />
      <V4Closing />
      <V4Footer />
    </div>
  );
}

/* Scroll-reveal controller. Watches every [data-reveal] or
   [data-cap-reveal] element inside .v4-root and flips them to
   .is-revealed once they enter the viewport. One-shot — no fade-out
   when scrolling back up, that always feels distracting. */
function useV4Reveals() {
  React.useEffect(() => {
    if (typeof IntersectionObserver === 'undefined') {
      // SSR / very old browsers — just show everything.
      document.querySelectorAll('.v4-root [data-reveal], .v4-root [data-cap-reveal]')
        .forEach(el => el.classList.add('is-revealed'));
      return;
    }
    const io = new IntersectionObserver((entries) => {
      entries.forEach(e => {
        if (e.isIntersecting) {
          e.target.classList.add('is-revealed');
          io.unobserve(e.target);
        }
      });
    }, { threshold: 0.12, rootMargin: '0px 0px -8% 0px' });
    // Defer a frame so initial styles paint before observation
    requestAnimationFrame(() => {
      document.querySelectorAll('.v4-root [data-reveal], .v4-root [data-cap-reveal]')
        .forEach(el => io.observe(el));
    });
    return () => io.disconnect();
  }, []);
}

/* All animation rules in one place. Three patterns:
   1) [data-reveal]   — 900ms fade-up + blur-out on entry
   2) [data-cap-reveal] — staggered slide-in on the capability codes
   3) .v4-marquee-drift — slow horizontal drift on the BLAST·ONCE bg
   prefers-reduced-motion neutralizes all three. */
function V4MotionStyles() {
  return (
    <style>{`
      /* ── Scroll reveal ───────────────────────────── */
      .v4-root [data-reveal] {
        opacity: 0;
        transform: translateY(28px);
        filter: blur(6px);
        transition: opacity 900ms cubic-bezier(0.22, 1, 0.36, 1),
                    transform 900ms cubic-bezier(0.22, 1, 0.36, 1),
                    filter   900ms cubic-bezier(0.22, 1, 0.36, 1);
        will-change: opacity, transform, filter;
      }
      .v4-root [data-reveal].is-revealed {
        opacity: 1;
        transform: translateY(0);
        filter: blur(0);
      }

      /* ── Capability code stamp — slide in from left, staggered ── */
      .v4-cap-code {
        display: inline-block;
        opacity: 0;
        transform: translateX(-14px);
        transition: opacity 520ms cubic-bezier(0.22, 1, 0.36, 1),
                    transform 520ms cubic-bezier(0.22, 1, 0.36, 1),
                    color 200ms;
        will-change: opacity, transform;
      }
      [data-cap-reveal].is-revealed .v4-cap-row .v4-cap-code {
        opacity: 1;
        transform: translateX(0);
      }
      [data-cap-reveal] .v4-cap-row:nth-of-type(1) .v4-cap-code { transition-delay: 0ms,   0ms, 0ms; }
      [data-cap-reveal] .v4-cap-row:nth-of-type(2) .v4-cap-code { transition-delay: 60ms,  60ms, 0ms; }
      [data-cap-reveal] .v4-cap-row:nth-of-type(3) .v4-cap-code { transition-delay: 120ms, 120ms, 0ms; }
      [data-cap-reveal] .v4-cap-row:nth-of-type(4) .v4-cap-code { transition-delay: 180ms, 180ms, 0ms; }
      [data-cap-reveal] .v4-cap-row:nth-of-type(5) .v4-cap-code { transition-delay: 240ms, 240ms, 0ms; }
      [data-cap-reveal] .v4-cap-row:nth-of-type(6) .v4-cap-code { transition-delay: 300ms, 300ms, 0ms; }

      /* ── Marquee drift — very slow horizontal scroll on the BG ── */
      @keyframes v4-marquee-drift-left {
        from { transform: translateX(0); }
        to   { transform: translateX(-50%); }
      }
      @keyframes v4-marquee-drift-right {
        from { transform: translateX(-50%); }
        to   { transform: translateX(0); }
      }
      .v4-marquee-drift {
        display: inline-block;
        animation-timing-function: linear;
        animation-iteration-count: infinite;
        will-change: transform;
      }
      .v4-marquee-drift[data-dir="left"]  { animation-name: v4-marquee-drift-left; }
      .v4-marquee-drift[data-dir="right"] { animation-name: v4-marquee-drift-right; }

      /* ── Reduced motion neutralizes everything ─────── */
      @media (prefers-reduced-motion: reduce) {
        .v4-root [data-reveal],
        .v4-root [data-reveal].is-revealed {
          opacity: 1 !important;
          transform: none !important;
          filter: none !important;
          transition: none !important;
        }
        .v4-cap-code {
          opacity: 1 !important;
          transform: none !important;
          transition: none !important;
        }
        .v4-marquee-drift { animation: none !important; }
      }
    `}</style>
  );
}

/* Responsive overrides — keep all the mobile rules in one place so the
   inline-styled sections above stay readable. Everything below uses
   !important because it overrides inline style attributes. */
function V4ResponsiveStyles() {
  return (
    <style>{`
      @media (max-width: 900px) {
        /* Section padding — narrower side gutters everywhere */
        .v4-pad { padding-left: 24px !important; padding-right: 24px !important; }
        .v4-sec { padding-top: 72px !important; padding-bottom: 72px !important; }

        /* Letterhead — drop the nav, stack name above contact */
        .v4-mast {
          grid-template-columns: 1fr auto !important;
          gap: 16px !important;
          padding: 14px 24px !important;
        }
        .v4-mast-nav { display: none !important; }
        .v4-mast-contact a:nth-child(2) { font-size: 11px !important; }

        /* Hero — stack type over image */
        .v4-hero-sec { padding-top: 56px !important; padding-bottom: 72px !important; }
        .v4-hero-grid {
          grid-template-columns: 1fr !important;
          gap: 40px !important;
        }
        .v4-hero-image-wrap { max-width: 480px; margin: 0 auto; width: 100%; }

        /* About — stack card above bio, credentials become single column */
        .v4-about-grid {
          display: flex !important;
          flex-direction: column !important;
          gap: 40px !important;
        }
        .v4-creds-grid {
          grid-template-columns: 1fr !important;
        }
        .v4-creds-grid > div {
          border-right: none !important;
          border-bottom: 1px solid var(--ink-900) !important;
        }
        .v4-creds-grid > div:last-child { border-bottom: none !important; }

        /* Capability — collapse the 4-col row to stacked text + arrow */
        .v4-cap-intro {
          display: flex !important;
          flex-direction: column !important;
          gap: 20px !important;
        }
        .v4-cap-row {
          grid-template-columns: 1fr 40px !important;
          gap: 6px 16px !important;
          padding: 22px 8px !important;
        }
        .v4-cap-row > :nth-child(1) { grid-column: 1; grid-row: 1; }
        .v4-cap-row > :nth-child(2) { grid-column: 1; grid-row: 2; font-size: 19px !important; }
        .v4-cap-row > :nth-child(3) { grid-column: 1; grid-row: 3; }
        .v4-cap-row > :nth-child(4) { grid-column: 2; grid-row: 1 / span 3; align-self: center; }

        /* Services — single column of cards on phones */
        .v4-services-grid {
          grid-template-columns: 1fr !important;
          gap: 24px !important;
        }

        /* Added value — stack the map above the list on phones */
        .v4-sel-intro {
          display: flex !important;
          flex-direction: column !important;
          gap: 20px !important;
        }
        .v4-map-layout {
          grid-template-columns: 1fr !important;
          grid-template-rows: auto !important;
          gap: 28px !important;
        }
        /* Reset the desktop grid placement so children stack in DOM order
           (headline → map → list) on one column. */
        .v4-map-head, .v4-map-figcol, .v4-map-listcol {
          grid-column: auto !important;
          grid-row: auto !important;
        }
        /* Keep the stacked map a sensible size, centred */
        .v4-map-figure { max-width: 440px !important; margin: 0 auto !important; }

        /* Closing — stack headline above contact rows */
        .v4-closing-grid {
          display: flex !important;
          flex-direction: column !important;
          gap: 40px !important;
        }

        /* Footer — wrap, smaller mono */
        .v4-footer { padding: 20px 24px !important; gap: 12px !important; }
        .v4-footer > div { font-size: 10px !important; letter-spacing: 0.18em !important; }

        /* Section labels — hide the right "Section · 02" rail on phones */
        .v4-sec-label-tail { display: none !important; }
      }

      @media (max-width: 480px) {
        /* Phone — extra tightening for tiny screens */
        .v4-pad { padding-left: 20px !important; padding-right: 20px !important; }
        .v4-mast { padding: 12px 20px !important; }
        .v4-footer { padding: 18px 20px !important; }

        /* Site list — single column, with clean horizontal dividers */
        .v4-list-grid { grid-template-columns: 1fr !important; }
        .v4-list-cell {
          border-right: none !important;
          border-bottom: 1px solid var(--bo-hair) !important;
        }
        .v4-list-cell:last-child { border-bottom: none !important; }
      }
    `}</style>
  );
}

/* ─── Letterhead — full-width masthead with huge logo ──── */
function V4Letterhead() {
  return (
    <header style={{
      position: 'relative',
      background: 'var(--bo-paper)',
      borderBottom: '2px solid var(--ink-900)',
    }}>
      {/* Main letterhead row */}
      <div className="v4-mast" style={{
        maxWidth: 1440, margin: '0 auto', padding: '18px 48px',
        display: 'grid', gridTemplateColumns: 'auto 1fr auto', alignItems: 'center', gap: 48,
      }}>
        <a href="#" style={{ textDecoration: 'none', display: 'block' }}>
          <BoLogo height={56} />
        </a>

        <nav className="v4-mast-nav" style={{
          display: 'flex', gap: 36, justifySelf: 'center',
          font: '500 13px/1 var(--font-sans)', letterSpacing: '0.06em',
          textTransform: 'uppercase',
        }}>
          {[
            { l: 'Services', h: '#services' },
            { l: 'Projects', h: '#work' },
            { l: 'Contact', h: '#contact' },
          ].map(x => (
            <a key={x.h} href={x.h} style={{
              color: 'var(--ink-700)', textDecoration: 'none',
              borderBottom: '2px solid transparent',
              paddingBottom: 4,
              transition: 'border-color 200ms, color 200ms',
            }}
            onMouseEnter={e => {
              e.currentTarget.style.borderColor = 'var(--bo-red)';
              e.currentTarget.style.color = 'var(--ink-900)';
            }}
            onMouseLeave={e => {
              e.currentTarget.style.borderColor = 'transparent';
              e.currentTarget.style.color = 'var(--ink-700)';
            }}
            >{x.l}</a>
          ))}
        </nav>

        <div className="v4-mast-contact" style={{
          display: 'flex', flexDirection: 'column', alignItems: 'flex-end', gap: 6,
          font: '500 13px/1.3 var(--font-sans)', letterSpacing: '-0.01em',
          color: 'var(--ink-700)',
        }}>
          <a href="tel:+61415689840" style={{
            font: '700 15px/1 var(--font-sans)', letterSpacing: '-0.01em',
            color: 'var(--ink-900)', textDecoration: 'none',
          }}>0415 689 840</a>
          <a href="mailto:kris@blastonce.au" style={{
            font: '500 12px/1.3 var(--font-sans)', letterSpacing: '-0.01em',
            color: 'var(--ink-700)', textDecoration: 'none',
          }}>kris@blastonce.au</a>
        </div>
      </div>
    </header>
  );
}

/* ─── Hero — type left, image-slot right (sharp rectangle) ── */
const V4_HEADLINES = {
  stood: (red) => (<>Stood on <br/><span style={{ color: red }}>the&nbsp;shot.</span></>),
  donedone:   (red) => (<>Done once.<br/><span style={{ color: red }}>Done right.</span></>),
  blastright: (red) => (<>Blast once.<br/><span style={{ color: red }}>Blast right.</span></>),
  drillblast: (red) => (<>Drill once.<br/>Blast <span style={{ color: red }}>once.</span></>),
  designed:   (red) => (<>Designed where <br/>the <span style={{ color: red }}>blast lands.</span></>),
  minegrade:  (red) => (<>Mining-grade<br/><span style={{ color: red }}>drill &amp; blast.</span></>),
  engineered: (red) => (<>Engineered for the<br/>bench in front of<br/><span style={{ color: red }}>you.</span></>),
};

function V4Hero() {
  const t = (React.useContext(window.BoTweaksContext) || {});
  const variant   = t.v4_headline   || 'stood';
  const layout    = t.v4_layout     || 'split';
  const imageSide = t.v4_image_side || 'right';
  const showSubhead = t.v4_show_subhead !== false;
  const headline = (V4_HEADLINES[variant] || V4_HEADLINES.stood)('var(--bo-red)');

  const TypeBlock = (
    <div style={{ minWidth: 0 }}>
      <BoEyebrow>Mining / Drill &amp; blast engineering &middot; Statutory coverage &middot; WA &middot; D&amp;B / Mining Tenders</BoEyebrow>

      <h1 data-reveal style={{
        margin: '20px 0 0',
        font: '800 clamp(40px, 5.6vw, 84px)/0.94 var(--font-sans)',
        letterSpacing: '-0.045em',
        color: 'var(--ink-900)',
        textWrap: 'balance',
      }}>
        {headline}
      </h1>

      {showSubhead && (
        <p style={{
          margin: '24px 0 0', maxWidth: '54ch',
          font: '400 17px/1.5 var(--font-sans)', letterSpacing: '-0.01em',
          color: 'var(--ink-500)',
        }}>
          Mine technical services and mine statutory position coverage
          available at short&nbsp;notice.
        </p>
      )}

      <div style={{
        marginTop: 28,
        display: 'flex', gap: 12, alignItems: 'center', flexWrap: 'wrap',
      }}>
        <BoPrimaryCTA href="#contact" size="lg">Contact Blast Once</BoPrimaryCTA>
        <BoSecondaryCTA href="#work">See Projects</BoSecondaryCTA>
      </div>

      {/* Rolling marquee replaces the static commodities strip */}
      <div style={{ marginTop: 32 }}>
        <V4Marquee />
      </div>
    </div>
  );

  const ImageBlock = (
    <div className="v4-hero-image-wrap">
      <V4HeroImage />
    </div>
  );

  return (
    <section className="bo-noise v4-hero-sec" style={{
      position: 'relative',
      padding: layout === 'stacked' ? '48px 0 64px' : '56px 0 64px',
      background: 'var(--bo-paper)',
      overflow: 'hidden',
      borderBottom: '1px solid var(--bo-hair-2)',
    }}>
      {/* Blueprint hairline grid */}
      <div className="bo-grid-light" style={{
        position: 'absolute', inset: 0, pointerEvents: 'none', opacity: 0.7,
      }} />

      {/* Soft red wash anchored bottom-left, like ground heat */}
      <div style={{
        position: 'absolute', inset: 'auto 0 -120px -10%', width: '70%', height: 360,
        pointerEvents: 'none',
        background: 'radial-gradient(50% 60% at 50% 100%, rgba(200,22,29,0.07), transparent 70%)',
        filter: 'blur(8px)',
      }} />

      {/* Full-background repeating marquee — diagonal, fine type, very subtle */}
      <V4MarqueeBackdrop />
      <div className="v4-hero-grid v4-pad" style={layout === 'stacked' ? {
        maxWidth: 1280, margin: '0 auto', padding: '0 48px',
        display: 'flex', flexDirection: 'column', gap: 56,
      } : {
        maxWidth: 1440, margin: '0 auto', padding: '0 48px',
        display: 'grid',
        gridTemplateColumns: imageSide === 'left' ? '1fr 1.1fr' : '1.1fr 1fr',
        gap: 64,
        alignItems: 'center',
      }}>
        {layout === 'stacked' ? (
          <>
            {TypeBlock}
            <div style={{ maxWidth: 900, alignSelf: 'center', width: '100%' }}>
              <V4HeroImage forceAspect="21 / 9" />
            </div>
          </>
        ) : imageSide === 'left' ? (
          <>{ImageBlock}{TypeBlock}</>
        ) : (
          <>{TypeBlock}{ImageBlock}</>
        )}
      </div>
    </section>
  );
}

function V4HeroImage({ forceAspect } = {}) {
  return (
    <div style={{ position: 'relative' }}>
      <image-slot
        id="v4-hero"
        shape="rounded"
        radius="18"
        src="assets/picture9.jpeg"
        placeholder="Drop a primary site photo — quarry face or bench"
        style={{
          display: 'block',
          width: '100%', height: 'auto', aspectRatio: forceAspect || '5 / 4',
          background: 'var(--bo-cream)',
          boxShadow: '0 24px 60px -24px rgba(13,12,10,0.42), 0 6px 18px -6px rgba(13,12,10,0.15)',
        }}
      ></image-slot>
      {/* Subtle red duotone overlay — color-blend so the photo lives in the brand's warm tones */}
      <div aria-hidden="true" style={{
        position: 'absolute', inset: 0,
        background: 'var(--bo-red)',
        mixBlendMode: 'color',
        opacity: 0.18,
        borderRadius: 18,
        pointerEvents: 'none',
      }} />
    </div>
  );
}

/* ─── About — portrait slot + bio ───────────────────── */
function V4Marquee() {
  const items = [
    'Drill & blast engineering',
    'Statutory coverage',
    'Fly rock & ground vibration',
    'Heritage / sensitive sites',
    'Quarry operations',
    'Open pit mining',
    'Hematite',
    'Magnetite',
    'Gold',
    'Lithium',
    'Pattern design',
    'Charge planning',
    'Shotfiring',
    'Small civil',
  ];
  const fadeMask =
    'linear-gradient(to right, transparent 0%, black 8%, black 92%, transparent 100%)';
  return (
    <section style={{
      position: 'relative',
      paddingTop: 16,
      borderTop: '1px solid var(--bo-hair)',
      overflow: 'hidden',
      WebkitMaskImage: fadeMask,
      maskImage: fadeMask,
    }}>
      <style>{`
        @keyframes v4-marquee-scroll {
          from { transform: translateX(0); }
          to   { transform: translateX(-50%); }
        }
      `}</style>
      <div style={{
        display: 'flex',
        gap: 32,
        width: 'max-content',
        animation: 'v4-marquee-scroll 60s linear infinite',
      }}>
        {[...items, ...items].map((label, i) => (
          <span key={i} style={{
            display: 'inline-flex', alignItems: 'center', gap: 32,
            font: '500 16px/1 var(--font-sans)', letterSpacing: '-0.01em',
            color: 'var(--ink-900)',
            whiteSpace: 'nowrap',
          }}>
            {label}
            <span style={{
              width: 7, height: 7,
              transform: 'rotate(45deg)',
              background: 'var(--bo-red)',
              flexShrink: 0,
            }} />
          </span>
        ))}
      </div>
    </section>
  );
}

/* ─── Services — 2×2 photo cards, photo over a clean caption ──── */
const V4_SERVICES = [
  {
    code: 'D&B-01',
    title: 'Drill & Blast Engineering',
    photo: 'assets/Picture1.jpg',
    items: [
      'Mine production blasting optimisation',
      'Dilution control',
      'Civil / construction blasting',
      'Heritage / vibration-sensitive blasting',
      'Controlled blasting',
    ],
  },
  {
    code: 'STAT-02',
    title: 'Statutory Position Coverage',
    photo: 'assets/Picture2.jpg',
    items: [
      'Quarry Manager',
      'Site Senior Executive',
      'S26 Statutory Supervisor',
      'Exploration Manager',
    ],
  },
  {
    code: 'TND-03',
    title: 'D&B / Mining Tenders',
    photo: 'assets/picture8.jpg',
    items: [
      'Bid analysis',
      'Cost estimating',
      'Tender review',
      'Tender risk assessment',
      'Margin strategy',
    ],
  },
  {
    code: 'ADD-04',
    title: 'Additional Services',
    photo: 'assets/Picture6.jpg',
    items: [
      'Shotfirer',
      'Project Manager',
      'RePL (Drone Operator)',
      'Chief Remote Pilot',
    ],
  },
];

function V4Services() {
  return (
    <section id="services" className="v4-sec" style={{
      position: 'relative',
      padding: '48px 0',
      background: 'var(--bo-cream)',
      borderTop: '1px solid var(--bo-hair-2)',
      borderBottom: '1px solid var(--bo-hair-2)',
    }}>
      <div className="v4-pad" style={{
        maxWidth: 1440, margin: '0 auto', padding: '0 48px',
      }}>
        <div style={{ marginBottom: 24 }}>
          <V4SectionLabel n="01" title="Services" />
        </div>

        <div className="v4-sel-intro" style={{
          display: 'grid', gridTemplateColumns: 'repeat(12, 1fr)', gap: 40,
          alignItems: 'end', marginBottom: 28,
        }}>
          <div style={{ gridColumn: '1 / span 7' }}>
            <h2 data-reveal style={{
              margin: 0,
              font: '800 clamp(28px, 3vw, 44px)/0.98 var(--font-sans)',
              letterSpacing: '-0.04em',
              color: 'var(--ink-900)',
              textWrap: 'balance',
            }}>
              What we look
              <span style={{ color: 'var(--bo-red)' }}> after.</span>
            </h2>
          </div>
          <div style={{ gridColumn: '9 / span 4' }}>
            <p style={{
              margin: 0,
              font: '400 15px/1.5 var(--font-sans)', letterSpacing: '-0.01em',
              color: 'var(--ink-500)',
            }}>
              Engineering, statutory cover, tendering and field support &mdash;
              engaged on their own or together.
            </p>
          </div>
        </div>

        <div className="v4-services-grid" style={{
          display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 20,
          maxWidth: 1000, margin: '0 auto',
        }}>
          {V4_SERVICES.map((s) => <V4ServiceCard key={s.code} {...s} />)}
        </div>
      </div>
    </section>
  );
}

function V4ServiceCard({ code, title, photo, items }) {
  const [hover, setHover] = React.useState(false);
  return (
    <article data-reveal
      onMouseEnter={() => setHover(true)}
      onMouseLeave={() => setHover(false)}
      style={{
        position: 'relative',
        border: '1px solid var(--ink-900)',
        overflow: 'hidden',
        aspectRatio: '4 / 3',
        boxShadow: hover
          ? '0 22px 50px -18px rgba(13,12,10,0.45)'
          : '0 12px 32px -12px rgba(13,12,10,0.18)',
        transition: 'box-shadow 320ms ease-out',
        cursor: 'default',
      }}>
      {/* Photo — desaturated to a neutral base, zooms slightly on hover */}
      <img src={photo} alt={title} loading="lazy" style={{
        position: 'absolute', inset: 0,
        width: '100%', height: '100%', objectFit: 'cover',
        filter: 'grayscale(1) contrast(1.05) brightness(0.94)',
        transform: hover ? 'scale(1.06)' : 'scale(1)',
        transition: 'transform 700ms cubic-bezier(0.22, 1, 0.36, 1)',
      }} />

      {/* Brand duotone — maps the greyscale photo into the brand red, the
          same color-blend the hero image uses. Unifies the four mismatched
          source images into one cohesive, intentional-looking set. */}
      <div aria-hidden="true" style={{
        position: 'absolute', inset: 0, pointerEvents: 'none',
        background: 'var(--bo-red)',
        mixBlendMode: 'color',
        opacity: 0.32,
      }} />

      {/* Fine grain — disguises the source further, adds print texture */}
      <div aria-hidden="true" style={{
        position: 'absolute', inset: 0, pointerEvents: 'none',
        opacity: 0.1, mixBlendMode: 'overlay',
        backgroundImage:
          "url(\"data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='220' height='220'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/></filter><rect width='100%25' height='100%25' filter='url(%23n)' opacity='0.7'/></svg>\")",
      }} />

      {/* Dark scrim — deepened so the lower half is near-solid: it covers the
          weakest part of each photo and keeps the overlaid text crisp. */}
      <div aria-hidden="true" style={{
        position: 'absolute', inset: 0, pointerEvents: 'none',
        background:
          'linear-gradient(to top, rgba(13,12,10,0.97) 0%, rgba(13,12,10,0.9) 36%, rgba(13,12,10,0.55) 60%, rgba(13,12,10,0.16) 84%, transparent 100%)',
      }} />

      {/* Code chip, top-left, brand red */}
      <span style={{
        position: 'absolute', top: 0, left: 0,
        font: '400 10px/1 var(--font-mono)', letterSpacing: '0.22em',
        textTransform: 'uppercase', color: '#fff',
        background: 'var(--bo-red)', padding: '7px 11px',
      }}>{code}</span>

      {/* Title + bullets, overlaid on the lower part of the photo */}
      <div style={{
        position: 'absolute', left: 0, right: 0, bottom: 0,
        padding: '18px 20px 20px',
      }}>
        <h3 style={{
          margin: '0 0 10px',
          font: '800 20px/1.1 var(--font-sans)', letterSpacing: '-0.02em',
          color: '#fff',
          textShadow: '0 1px 14px rgba(0,0,0,0.45)',
        }}>{title}</h3>
        <ul style={{ listStyle: 'none', margin: 0, padding: 0 }}>
          {items.map((it) => (
            <li key={it} style={{
              display: 'grid', gridTemplateColumns: '11px 1fr', gap: 9,
              alignItems: 'baseline', padding: '2.5px 0',
            }}>
              <span style={{
                width: 6, height: 6, flexShrink: 0,
                transform: 'rotate(45deg) translateY(2px)',
                background: 'var(--bo-red)',
              }} />
              <span style={{
                font: '500 13px/1.3 var(--font-sans)', letterSpacing: '-0.005em',
                color: 'rgba(255,255,255,0.92)',
              }}>{it}</span>
            </li>
          ))}
        </ul>
      </div>
    </article>
  );
}

/* Shared diagonal BLAST · ONCE marquee backdrop — used in the hero and
   the capability section so they read as a continuous spread. */
function V4MarqueeBackdrop({ rows = 18 } = {}) {
  return (
    <div aria-hidden="true" style={{
      position: 'absolute', inset: '-20% -10%', pointerEvents: 'none',
      display: 'flex', flexDirection: 'column', justifyContent: 'space-between',
      padding: '24px 0', overflow: 'hidden',
      transform: 'rotate(-12deg)',
      transformOrigin: 'center',
      userSelect: 'none',
    }}>
      {Array.from({ length: rows }).map((_, row) => {
        const isRed = row % 2 === 1;
        const offset = (row % 4) * -60;
        // Slow drift, alternating direction by row, slight per-row
        // duration variation so the rows don't lock-step.
        const dir = row % 2 === 0 ? 'left' : 'right';
        const duration = 1200 + (row % 5) * 150; // 1200s–1800s per cycle — barely perceptible
        return (
          <div key={row} style={{
            whiteSpace: 'nowrap',
            transform: `translateX(${offset}px)`,
            font: '800 clamp(28px, 3.6vw, 56px)/1 var(--font-sans)',
            letterSpacing: '-0.025em',
            color: isRed ? 'var(--bo-red)' : 'var(--ink-900)',
            opacity: isRed ? 0.06 : 0.03,
          }}>
            <span
              className="v4-marquee-drift"
              data-dir={dir}
              style={{ animationDuration: `${duration}s` }}
            >
              {'BLAST · ONCE · '.repeat(24)}
              {'BLAST · ONCE · '.repeat(24)}
            </span>
          </div>
        );
      })}
    </div>
  );
}

/* ─── Where we added value — interactive WA map + site list ─────────
   Self-contained: the Western Australia outline and every marker are
   projected from real lat/long right here, so there are no external
   map tiles, requests or trackers. Hovering or clicking a marker — or
   a list row — highlights the matching site in both places. */

/* Coarse WA boundary, traced as [lng, lat] clockwise from the NT
   border on the north coast. Deliberately simplified — recognisable,
   not survey-grade. */
const BO_WA_OUTLINE = [
  [129.0, -14.85], [128.2, -14.75], [127.8, -15.35], [127.4, -14.5],
  [126.9, -13.75], [126.1, -14.2], [125.3, -14.6], [124.4, -15.6],
  [123.9, -16.1], [123.0, -16.35], [122.6, -16.9], [122.2, -17.55],
  [122.24, -17.96], [121.3, -18.9], [120.2, -19.6], [119.0, -19.95],
  [118.6, -20.31], [117.2, -20.6], [116.8, -20.7], [116.0, -20.9],
  [115.1, -21.64], [114.4, -21.5], [114.1, -21.8], [114.0, -22.6],
  [113.8, -23.1], [113.66, -24.88], [113.4, -25.5], [113.16, -26.15],
  [113.5, -26.6], [114.0, -27.0], [114.16, -27.71], [114.61, -28.77],
  [115.0, -29.5], [115.3, -30.5], [115.74, -32.05], [115.5, -33.3],
  [115.14, -34.37], [116.0, -34.85], [116.7, -35.0], [117.88, -35.02],
  [118.6, -34.5], [119.9, -33.95], [121.0, -33.9], [121.89, -33.86],
  [123.2, -33.95], [124.5, -32.95], [126.0, -32.3], [127.5, -31.9],
  [128.88, -31.68], [129.0, -31.68],
];

/* Every site, with the coordinates researched for the map. */
const BO_SITES = [
  { id:'koodaideri',  name:'Gudai-Darri (Koodaideri)',  commodity:'Iron ore', region:'Pilbara',      op:'Rio Tinto', lat:-22.54, lng:119.04 },
  { id:'westrange',   name:'Western Range',             commodity:'Iron ore', region:'Pilbara',      op:'Rio Tinto', lat:-23.25, lng:117.58 },
  { id:'westangelas', name:'West Angelas',              commodity:'Iron ore', region:'Pilbara',      op:'Rio Tinto', lat:-23.17, lng:118.76 },
  { id:'mesaa',       name:'Robe Valley — Mesa A',      commodity:'Iron ore', region:'Pilbara',      op:'Rio Tinto', lat:-21.67, lng:115.87 },
  { id:'mesah',       name:'Robe Valley — Mesa H',      commodity:'Iron ore', region:'Pilbara',      op:'Rio Tinto', lat:-21.55, lng:116.15 },
  { id:'brockman',    name:'Brockman Syncline 1',       commodity:'Iron ore', region:'Pilbara',      op:'Rio Tinto', lat:-22.45, lng:117.30 },
  { id:'karara',      name:'Karara',                    commodity:'Iron ore', region:'Mid West',     op:'Magnetite', lat:-29.19, lng:116.76 },
  { id:'wodgina',     name:'Wodgina',                   commodity:'Lithium',  region:'Pilbara',      op:null,        lat:-21.18, lng:118.68 },
  { id:'mtmarion',    name:'Mt Marion',                 commodity:'Lithium',  region:'Goldfields',   op:null,        lat:-31.05, lng:121.20 },
  { id:'baldhill',    name:'Bald Hill',                 commodity:'Lithium',  region:'Goldfields',   op:null,        lat:-31.51, lng:122.19 },
  { id:'mtholland',   name:'Mt Holland',                commodity:'Lithium',  region:'Forrestania',  op:null,        lat:-32.10, lng:119.77 },
  { id:'mtcattlin',   name:'Mt Cattlin',                commodity:'Lithium',  region:'Ravensthorpe', op:null,        lat:-33.56, lng:120.04 },
  { id:'dalgaranga',  name:'Dalgaranga',                commodity:'Gold',     region:'Murchison',    op:null,        lat:-27.83, lng:117.30 },
  { id:'goldduke',    name:'Gold Duke',                 commodity:'Gold',     region:'Mid West',     op:null,        lat:-26.70, lng:119.80 },
  { id:'marblebar',   name:'Marble Bar Road Upgrade',   commodity:'Civil',    region:'Pilbara',      op:null,        lat:-21.17, lng:119.75 },
  { id:'coongan',     name:'Coongan Gorge Road Upgrade',commodity:'Civil',    region:'Pilbara',      op:null,        lat:-21.02, lng:119.62 },
];

const BO_COMMODITY_GROUPS = [
  { key:'Iron ore', sub:'RTIO + Karara' },
  { key:'Lithium',  sub:'Hard-rock spodumene' },
  { key:'Gold',     sub:null },
  { key:'Civil',    sub:'Pilbara roadworks' },
];

const BO_COMMODITY_COLORS = {
  'Iron ore': '#c8161d',  // red (your current bo-red)
  'Lithium':  '#22c55e',  // green
  'Gold':     '#eab308',  // yellow
  'Civil':    '#ff8c42',  // orange
};

/* Equirectangular projection with a cos(lat) correction so WA keeps
   its true proportions. Both the outline and the markers run through
   this single function, so they always line up. */
const BO_MAP = (() => {
  const LNG_MIN = 112.8, LNG_MAX = 129.45;
  const LAT_TOP = -13.2, LAT_BOT = -35.6;
  const KX = Math.cos((-24.4 * Math.PI) / 180);
  const SCALE = 46;
  const project = (lng, lat) => ({
    x: (lng - LNG_MIN) * KX * SCALE,
    y: (LAT_TOP - lat) * SCALE,
  });
  const w = (LNG_MAX - LNG_MIN) * KX * SCALE;
  const h = (LAT_TOP - LAT_BOT) * SCALE;
  const path = BO_WA_OUTLINE
    .map(([lng, lat], i) => {
      const { x, y } = project(lng, lat);
      return `${i === 0 ? 'M' : 'L'}${x.toFixed(1)} ${y.toFixed(1)}`;
    })
    .join(' ') + ' Z';
  const graticule = [];
  [116, 120, 124, 128].forEach((lng) => {
    graticule.push([project(lng, -13), project(lng, -36)]);
  });
  [-16, -20, -24, -28, -32].forEach((lat) => {
    graticule.push([project(112, lat), project(130, lat)]);
  });
  return { project, w, h, path, graticule };
})();

function V4Selected() {
  // `selected` persists on click; `hovered` is transient. The effective
  // active marker is whichever is hovered, falling back to the selection.
  const [selected, setSelected] = React.useState(null);
  const [hovered, setHovered]   = React.useState(null);
  const activeId = hovered != null ? hovered : selected;
  const activeSite = BO_SITES.find((s) => s.id === activeId) || null;
  const toggle = (id) => setSelected((cur) => (cur === id ? null : id));

  return (
    <section id="work" className="v4-sec" style={{
      position: 'relative',
      padding: '44px 0',
      background: 'var(--bo-paper)',
      overflow: 'hidden',
      borderTop: '1px solid var(--bo-hair-2)',
      borderBottom: '1px solid var(--bo-hair-2)',
    }}>
      <V4MarqueeBackdrop />
      <div className="v4-pad" style={{
        position: 'relative',
        maxWidth: 1440, margin: '0 auto', padding: '0 48px',
      }}>
        <div style={{ marginBottom: 32 }}>
          <V4SectionLabel n="02" title="Added value" />
        </div>

        {/* Map is the hero (left column, spans both rows). Headline + blurb
            sit top-right, the list below them. DOM order is head → map →
            list so that when this collapses to one column on mobile it
            reads headline, map, list — not map-first. */}
        <div className="v4-map-layout" style={{
          display: 'grid',
          gridTemplateColumns: 'minmax(0, 480px) minmax(0, 1fr)',
          gridTemplateRows: 'auto 1fr',
          columnGap: 48, rowGap: 24,
          alignItems: 'start',
        }}>
          <div className="v4-map-head" style={{ gridColumn: 2, gridRow: 1 }}>
            <h2 data-reveal style={{
              margin: '0 0 16px',
              font: '800 clamp(30px, 3.2vw, 44px)/0.96 var(--font-sans)',
              letterSpacing: '-0.04em',
              color: 'var(--ink-900)',
              textWrap: 'balance',
            }}>
              Where Blast Once
              <br />
              <span style={{ color: 'var(--bo-red)' }}>added value.</span>
            </h2>
            <p style={{
              margin: 0, maxWidth: '52ch',
              font: '400 16px/1.55 var(--font-sans)', letterSpacing: '-0.01em',
              color: 'var(--ink-500)',
            }}>
              Sixteen sites across iron ore, lithium and gold &mdash; plus
              civil roadworks. Tap a marker on the map, or any site in the
              list, to place it.
            </p>
          </div>

          <div className="v4-map-figcol" style={{ gridColumn: 1, gridRow: '1 / span 2' }}>
            <V4WAMap
              activeId={activeId}
              activeSite={activeSite}
              onHover={setHovered}
              onSelect={toggle}
            />
          </div>

          <div className="v4-map-listcol" style={{ gridColumn: 2, gridRow: 2 }}>
            <V4SiteList
              activeId={activeId}
              selectedId={selected}
              onHover={setHovered}
              onSelect={toggle}
            />
          </div>
        </div>
      </div>
    </section>
  );
}

function V4WAMap({ activeId, activeSite, onHover, onSelect }) {
  const PAD = 22;
  const { w, h, path, graticule } = BO_MAP;
  // Draw the active marker last so it always sits on top of its neighbours.
  const ordered = [...BO_SITES].sort((a, b) =>
    (a.id === activeId ? 1 : 0) - (b.id === activeId ? 1 : 0));

  return (
    <figure data-reveal className="v4-map-figure" style={{
      margin: 0,
      border: '2px solid var(--ink-900)',
      background: 'var(--bo-paper)',
      boxShadow: '0 14px 36px -16px rgba(13,12,10,0.22)',
      display: 'flex', flexDirection: 'column',
    }}>
      <style>{`
        .v4-map-dot { transition: r 220ms var(--ease-heavy), fill 200ms, stroke 200ms; }
        .v4-map-hit { cursor: pointer; }
        @keyframes v4-dot-ping { 0%{transform:scale(1);opacity:.55} 70%,100%{transform:scale(2.8);opacity:0} }
        .v4-map-ping { transform-box: fill-box; transform-origin: center; animation: v4-dot-ping 1.9s var(--ease-heavy) infinite; }
        @media (prefers-reduced-motion: reduce) {
          .v4-map-ping { animation: none; opacity: 0; }
          .v4-map-dot { transition: none; }
        }
      `}</style>

      {/* The map itself */}
      <div style={{ padding: 18, background: 'var(--bo-paper)' }}>
        <svg
          role="img"
          aria-label="Map of Western Australia showing Blast Once project sites"
          viewBox={`${-PAD} ${-PAD} ${w + PAD * 2} ${h + PAD * 2}`}
          style={{ display: 'block', width: '100%', height: 'auto', overflow: 'visible' }}
        >
          <defs>
            <clipPath id="bo-wa-clip"><path d={path} /></clipPath>
          </defs>

          {/* Landmass fill */}
          <path d={path} fill="var(--bo-cream)" />
          {/* Survey graticule, clipped to the state outline */}
          <g clipPath="url(#bo-wa-clip)" stroke="rgba(13,12,10,0.09)" strokeWidth="1">
            {graticule.map(([a, b], i) => (
              <line key={i} x1={a.x} y1={a.y} x2={b.x} y2={b.y} />
            ))}
          </g>
          {/* Coastline + borders on top, crisp */}
          <path d={path} fill="none" stroke="var(--ink-900)" strokeWidth="2"
            strokeLinejoin="round" strokeLinecap="round" />

{/* Markers */}
{ordered.map((s) => {
  const { x, y } = BO_MAP.project(s.lng, s.lat);
  const isActive = s.id === activeId;
  const markerColor = BO_COMMODITY_COLORS[s.commodity] || 'var(--ink-900)';
  return (
    <g key={s.id}>
      {isActive && (
        <circle className="v4-map-ping" cx={x} cy={y} r={7}
          fill="none" stroke={markerColor} strokeWidth="2" />
      )}
      <circle className="v4-map-dot"
        cx={x} cy={y} r={isActive ? 7 : 4.5}
        fill={isActive ? markerColor : 'var(--bo-paper)'}
        stroke={isActive ? markerColor : markerColor}
        strokeWidth="1.6" />
      {/* Generous transparent hit target for mouse + touch */}
      <circle className="v4-map-hit"
        cx={x} cy={y} r={15} fill="transparent"
        onMouseEnter={() => onHover(s.id)}
        onMouseLeave={() => onHover(null)}
        onClick={() => onSelect(s.id)}>
        <title>{s.name}</title>
      </circle>
    </g>
  );
})}

          {/* Label for the active marker — paper halo behind ink text */}
          {activeSite && (() => {
            const { x, y } = BO_MAP.project(activeSite.lng, activeSite.lat);
            const tx = x + 12, ty = y + 4;
            const labelFont = '700 15px var(--font-sans)';
            return (
              <g style={{ pointerEvents: 'none' }}>
                <text x={tx} y={ty} fill="var(--bo-paper)"
                  stroke="var(--bo-paper)" strokeWidth="5" strokeLinejoin="round"
                  style={{ font: labelFont, letterSpacing: '-0.01em' }}>
                  {activeSite.name}
                </text>
                <text x={tx} y={ty} fill="var(--ink-900)"
                  style={{ font: labelFont, letterSpacing: '-0.01em' }}>
                  {activeSite.name}
                </text>
              </g>
            );
          })()}
        </svg>
      </div>
    </figure>
  );
}

function V4SiteList({ activeId, selectedId, onHover, onSelect }) {
  return (
    <div data-reveal className="v4-list-grid" style={{
      display: 'grid', gridTemplateColumns: '1fr 1fr',
      borderTop: '2px solid var(--ink-900)',
      borderBottom: '2px solid var(--ink-900)',
    }}>
      {BO_COMMODITY_GROUPS.map((group, gi) => {
        const sites = BO_SITES.filter((s) => s.commodity === group.key);
        return (
          <div key={group.key} className="v4-list-cell" style={{
            padding: '16px 14px 8px',
            // Left-column cells get a vertical divider; top-row cells a
            // horizontal one — together they rule the 2×2 grid.
            borderRight: gi % 2 === 0 ? '1px solid var(--bo-hair)' : 'none',
            borderBottom: gi < BO_COMMODITY_GROUPS.length - 2
              ? '1px solid var(--bo-hair)' : 'none',
          }}>
            <div style={{
              display: 'flex', alignItems: 'baseline', gap: 12, flexWrap: 'wrap',
              marginBottom: 6, paddingLeft: 8,
            }}>
              <h3 style={{
                margin: 0,
                font: '700 19px/1 var(--font-sans)', letterSpacing: '-0.025em',
                color: 'var(--ink-900)',
              }}>{group.key}</h3>
              <span style={{
                font: '400 9px/1 var(--font-mono)', letterSpacing: '0.18em',
                textTransform: 'uppercase', color: 'var(--ink-500)',
              }}>
                {sites.length} site{sites.length === 1 ? '' : 's'}
                {group.sub ? <> &middot; {group.sub}</> : null}
              </span>
            </div>
            {sites.map((s) => (
              <V4SiteRow key={s.id} site={s}
                active={s.id === activeId}
                selected={s.id === selectedId}
                onHover={onHover} onSelect={onSelect} />
            ))}
          </div>
        );
      })}
    </div>
  );
}

function V4SiteRow({ site, active, selected, onHover, onSelect }) {
  return (
    <button
      type="button"
      className="v4-site-btn"
      aria-pressed={selected}
      onMouseEnter={() => onHover(site.id)}
      onMouseLeave={() => onHover(null)}
      onFocus={() => onHover(site.id)}
      onBlur={() => onHover(null)}
      onClick={() => onSelect(site.id)}
      style={{
        display: 'grid', gridTemplateColumns: '16px 1fr auto', gap: 12,
        alignItems: 'center', width: '100%', textAlign: 'left',
        border: 'none', borderRadius: 0,
        padding: '11px 8px',
        background: active ? 'var(--bo-paper)' : 'transparent',
        boxShadow: active ? 'inset 3px 0 0 var(--bo-red)' : 'inset 3px 0 0 transparent',
        cursor: 'pointer',
        font: 'inherit', color: 'inherit',
        transition: 'background 180ms, box-shadow 180ms',
      }}>
<span style={{
  width: active ? 9 : 7, height: active ? 9 : 7, flexShrink: 0,
  justifySelf: 'center',
  transform: 'rotate(45deg)',
  background: BO_COMMODITY_COLORS[site.commodity] || 'var(--bo-red)',
  opacity: active ? 1 : 0.72,
  transition: 'all 180ms',
}} />
      <span style={{
        font: '600 17px/1.3 var(--font-sans)', letterSpacing: '-0.015em',
        color: active ? 'var(--bo-red)' : 'var(--ink-900)',
        transition: 'color 180ms',
      }}>{site.name}</span>
      <span style={{
        font: '400 10px/1 var(--font-mono)', letterSpacing: '0.16em',
        textTransform: 'uppercase', color: 'var(--ink-400)',
        whiteSpace: 'nowrap',
      }}>{site.region}</span>
    </button>
  );
}

/* ─── Closing / Contact ───────────────────────────── */
function V4Closing() {
  return (
    <section id="contact" className="v4-sec" style={{
      position: 'relative',
      padding: '140px 0',
      background: 'var(--ink-900)',
      color: '#fff',
      overflow: 'hidden',
    }}>
      {/* Hairline grid texture */}
      <div style={{
        position: 'absolute', inset: 0, pointerEvents: 'none',
        backgroundImage:
          'linear-gradient(to right, rgba(255,255,255,0.04) 1px, transparent 1px),' +
          'linear-gradient(to bottom, rgba(255,255,255,0.04) 1px, transparent 1px)',
        backgroundSize: '56px 56px',
        WebkitMaskImage: 'radial-gradient(ellipse at 70% 30%, black 30%, transparent 80%)',
        maskImage:       'radial-gradient(ellipse at 70% 30%, black 30%, transparent 80%)',
      }} />
      {/* Red glow */}
      <div style={{
        position: 'absolute', inset: 0, pointerEvents: 'none',
        background: 'radial-gradient(40% 60% at 20% 40%, rgba(200,22,29,0.32), transparent 70%)',
      }} />

      <div className="v4-closing-grid v4-pad" style={{
        position: 'relative',
        maxWidth: 1440, margin: '0 auto', padding: '0 48px',
        display: 'grid', gridTemplateColumns: 'repeat(12, 1fr)', gap: 40,
        alignItems: 'end',
      }}>
        <div style={{ gridColumn: '1 / span 7' }}>
          <BoEyebrow tone="dark">Contact</BoEyebrow>
          <h2 data-reveal style={{
            margin: '24px 0 0',
            font: '800 clamp(40px, 6.4vw, 100px)/0.92 var(--font-sans)',
            letterSpacing: '-0.045em',
            color: '#fff',
            textWrap: 'balance',
          }}>
            Is it time to Polish
            <br />
            <span style={{ color: 'var(--bo-red)' }}>your operation?</span>
          </h2>
          <p style={{
            margin: '24px 0 0', maxWidth: '46ch',
            font: '400 18px/1.55 var(--font-sans)', letterSpacing: '-0.01em',
            color: 'rgba(255,255,255,0.7)',
          }}>
            Technical services support, statutory coverage, D&B tenders across Western Australia and&nbsp;beyond.
          </p>
          <div style={{ marginTop: 40 }}>
            <BoPrimaryCTA href="mailto:kris@blastonce.au" size="lg">Email Blast Once</BoPrimaryCTA>
          </div>
        </div>

        <div style={{ gridColumn: '9 / span 4' }}>
          <div style={{ display: 'flex', flexDirection: 'column' }}>
            {[
              { icon: <BoIcons.Phone size={16} weight="regular" />,  l: 'Phone', v: '0415 689 840',           href: 'tel:+61415689840' },
              { icon: <BoIcons.Mail  size={16} weight="regular" />,  l: 'Email', v: 'kris@blastonce.au',      href: 'mailto:kris@blastonce.au' },
              { icon: <BoIcons.MapPin size={16} weight="regular" />, l: 'Based', v: 'Perth, Western Australia' },
            ].map((row, i, arr) => (
              <V4DarkContactRow key={i} {...row} last={i === arr.length - 1} />
            ))}
          </div>
        </div>
      </div>
    </section>
  );
}

function V4DarkContactRow({ icon, l, v, href, last }) {
  const [hover, setHover] = React.useState(false);
  const Tag = href ? 'a' : 'div';
  return (
    <Tag
      href={href}
      onMouseEnter={() => setHover(true)}
      onMouseLeave={() => setHover(false)}
      style={{
        padding: '20px 0',
        borderTop: '1px solid rgba(255,255,255,0.15)',
        borderBottom: last ? '1px solid rgba(255,255,255,0.15)' : 'none',
        display: 'flex', alignItems: 'center', gap: 16,
        textDecoration: 'none', color: 'inherit',
        cursor: href ? 'pointer' : 'default',
      }}>
      <span style={{
        color: hover && href ? 'var(--bo-red)' : 'rgba(255,255,255,0.6)',
        transition: 'color 200ms',
      }}>{icon}</span>
      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{
          font: '400 10px/1 var(--font-mono)', letterSpacing: '0.22em',
          textTransform: 'uppercase', color: 'rgba(255,255,255,0.5)',
          marginBottom: 4,
        }}>{l}</div>
        <div style={{
          font: '600 16px/1.2 var(--font-sans)', letterSpacing: '-0.01em',
          color: hover && href ? 'var(--bo-red)' : '#fff',
          wordBreak: 'break-word',
          transition: 'color 200ms',
        }}>{v}</div>
      </div>
    </Tag>
  );
}

function V4CardRow_unused({ l, v, href, last }) {
  const [hover, setHover] = React.useState(false);
  const Tag = href ? 'a' : 'div';
  return (
    <Tag
      href={href}
      onMouseEnter={() => setHover(true)}
      onMouseLeave={() => setHover(false)}
      style={{
        display: 'grid', gridTemplateColumns: '90px 1fr', alignItems: 'baseline', gap: 16,
        padding: '14px 0',
        borderBottom: last ? 'none' : '1px solid var(--bo-hair)',
        textDecoration: 'none', color: 'inherit',
        cursor: href ? 'pointer' : 'default',
      }}>
      <span style={{
        font: '400 10px/1 var(--font-mono)', letterSpacing: '0.22em',
        textTransform: 'uppercase', color: 'var(--ink-400)',
      }}>{l}</span>
      <span style={{
        font: `600 17px/1.2 var(--font-sans)`,
        letterSpacing: '-0.01em',
        color: hover && href ? 'var(--bo-red)' : 'var(--ink-900)',
        wordBreak: 'break-word',
        transition: 'color 200ms',
      }}>{v}</span>
    </Tag>
  );
}

/* ─── Footer ──────────────────────────────────────── */
function V4Footer() {
  return (
    <footer className="v4-footer" style={{
      background: 'var(--ink-900)',
      color: 'rgba(255,255,255,0.65)',
      padding: '32px 48px',
      borderTop: '4px solid var(--bo-red)',
      display: 'flex', justifyContent: 'space-between', alignItems: 'center',
      flexWrap: 'wrap', gap: 24,
    }}>
      <div style={{
        display: 'flex', alignItems: 'center', gap: 16,
        font: '400 11px/1 var(--font-mono)', letterSpacing: '0.22em',
        textTransform: 'uppercase',
      }}>
        <span style={{ color: '#fff' }}>Blast Once Pty Ltd</span>
        <span>&middot;</span>
        <span>ABN 91 696 521 696</span>
      </div>
      <div style={{
        display: 'flex', gap: 24, alignItems: 'center',
        font: '400 11px/1 var(--font-mono)', letterSpacing: '0.22em',
        textTransform: 'uppercase',
      }}>
        <span>Perth &middot; WA</span>
        <span>No cookies &middot; no tracking</span>
        <span>© {new Date().getFullYear()}</span>
      </div>
    </footer>
  );
}

/* ─── Helpers ─────────────────────────────────────── */
function V4SectionLabel({ n, title }) {
  return (
    <div data-reveal style={{
      display: 'flex', alignItems: 'center', gap: 20,
      paddingBottom: 12,
      borderBottom: '2px solid var(--ink-900)',
    }}>
      <span style={{
        font: '800 18px/1 var(--font-sans)', letterSpacing: '-0.02em',
        color: 'var(--bo-red)',
      }}>{n}</span>
      <span style={{
        font: '400 11px/1 var(--font-mono)', letterSpacing: '0.22em',
        textTransform: 'uppercase', color: 'var(--ink-900)',
      }}>{title}</span>
      <span style={{ flex: 1 }} />
      <span className="v4-sec-label-tail" style={{
        font: '400 11px/1 var(--font-mono)', letterSpacing: '0.22em',
        textTransform: 'uppercase', color: 'var(--ink-400)',
      }}>Section &middot; {n}</span>
    </div>
  );
}

Object.assign(window, { V4Page, V4Marquee, V4Letterhead, V4Footer });
