
<!DOCTYPE html>
<html lang="en-AU">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JJH Excavations | Driveways, Site Cuts & Retaining Walls</title>
<meta name="description" content="JJH Excavations builds driveways, house and shed site cuts, and rock retaining walls across the Macedon Ranges and Mitchell Shire. Built once, done right.">
<meta property="og:title" content="JJH Excavations">
<meta property="og:description" content="JJH Excavations builds driveways, house and shed site cuts, and rock retaining walls across the Macedon Ranges and Mitchell Shire. Built once, done right.">
<meta property="og:image" content="https://jjhexcavations.com.au/media/ghl_invite_14d9b135c60bf5ba5a432506/job_photos/f26c3f1e03e4_17323d5c-6f0f-4d87-b6ce-a20d5443b31d.jpg">
<meta property="og:type" content="website">

<script>
!function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function(){n.callMethod?n.callMethod.apply(n,arguments):n.queue.push(arguments)};if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0';n.queue=[];t=b.createElement(e);t.async=!0;t.src=v;s=b.getElementsByTagName(e)[0];s.parentNode.insertBefore(t,s)}(window,document,'script','https://connect.facebook.net/en_US/fbevents.js');
fbq('init','1702108444541489'); fbq('track','PageView'); /* PIXEL 1/10 PageView */
</script>

<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Fraunces:ital,wght@0,400;0,600;1,400&family=Archivo:wght@400;500;600;700&family=Anton&display=swap" rel="stylesheet">

<style>
  :root{
    --font-display:'Anton', Impact, sans-serif; --font-body:'Archivo', system-ui, sans-serif; --font-accent:'Fraunces', serif;
    --black:#0a0b0d; --gunmetal:#1f242b; --gunmetal-2:#2a3038; --steel:#3a424c;
    --silver:#c4c9d0; --silver-soft:#8b929c; --white:#ffffff;
    --paper:#f4f5f7; --paper-2:#e9ebee; --ink:#15181c; --ink-soft:#4a525c;
    --gold:#c9a24b; --gold-bright:#e7cd86; --gold-deep:#a8842f;
    --line-dark:rgba(196,201,208,0.16); --line-light:rgba(21,24,28,0.12);
    --shadow-d:0 24px 70px rgba(0,0,0,0.55); --shadow-l:0 20px 50px rgba(21,24,28,0.12);
    --brushed:linear-gradient(135deg,#262c34 0%,#1c2127 38%,#23292f 62%,#171b20 100%);
    --brushed-deep:linear-gradient(160deg,#15191e 0%,#0c0e11 55%,#101317 100%);
    --gold-polish:linear-gradient(180deg,#f0dca0 0%,#d9b65f 30%,#c9a24b 55%,#a8842f 100%);
  }
  /* Per-member brand overrides, filled by template_filler from
     OperatorProfile.brand. Empty when the member has no brand tokens
     set (the locked metal defaults above stand). See
     PER-MEMBER-BRANDING-SPEC.md and shared/operator_profile.py:Brand. */
  /* Per-member brand overrides (from OperatorProfile.brand). mood: marine-precise */
  :root {
    --gunmetal: #15192a;
    --black: #080a14;
    --gunmetal-2: #1c2238;
    --gold: #5a8db0;
    --gold-bright: #8fb6d0;
    --gold-deep: #3a6585;
    --paper: #eef0f2;
    --paper-2: #dee2e6;
    --white: #f6f8fa;
    --silver: #9aa1ab;
    --ink: #14181d;
    --ink-soft: #525860;
    --gold-polish: linear-gradient(180deg, #8fb6d0 0%, #5a8db0 30%, #5a8db0 55%, #3a6585 100%);
    --brushed-deep: linear-gradient(160deg, #15192a 0%, #080a14 58%, #080a14 100%);
    --brushed: linear-gradient(135deg, #1c2238 0%, #15192a 50%, #080a14 100%);
  }
  *{margin:0;padding:0;box-sizing:border-box;}
  body{font-family:var(--font-body);background:var(--gunmetal);color:var(--white);line-height:1.6;overflow-x:hidden;}
  .wrap{max-width:1120px;margin:0 auto;padding:0 26px;}
  .narrow{max-width:780px;margin:0 auto;}
  section{padding:74px 0;}
  h1,h2,h3{line-height:1.12;}
  .eyebrow{font-size:12px;letter-spacing:0.3em;text-transform:uppercase;font-weight:700;color:var(--gold);}
  @keyframes sheen{0%{background-position:-180% 0;}60%,100%{background-position:280% 0;}}
  .btn{position:relative;display:inline-block;font-family:var(--font-body);font-weight:700;letter-spacing:0.05em;text-transform:uppercase;font-size:14px;background:var(--gold-polish);color:#241a06;padding:18px 36px;text-decoration:none;transition:all .2s;border:none;cursor:pointer;overflow:hidden;box-shadow:0 8px 22px rgba(168,132,47,0.28),inset 0 1px 0 rgba(255,255,255,0.45);}
  .btn::after{content:'';position:absolute;top:0;left:0;width:60%;height:100%;background:linear-gradient(90deg,transparent,rgba(255,255,255,0.5),transparent);transform:skewX(-20deg);background-size:200% 100%;animation:sheen 6s ease-in-out infinite;}
  .btn:hover{filter:brightness(1.06);transform:translateY(-2px);}
  .btn.lg{padding:21px 46px;font-size:15px;}
  .hr-gold{width:120px;height:2px;margin:18px auto;background:var(--gold-polish);box-shadow:0 1px 4px rgba(168,132,47,0.4);}

  /* ===== TOP BAR ===== */
  .topbar{position:sticky;top:0;z-index:40;background:rgba(10,11,13,0.92);backdrop-filter:blur(10px);border-bottom:1px solid var(--line-dark);}
  .topbar .inner{display:flex;align-items:center;justify-content:space-between;padding:16px 26px;max-width:1120px;margin:0 auto;}
  .topbar .logo{height:38px;}
  .topbar .nav{display:flex;gap:26px;align-items:center;}
  .topbar .nav a{color:var(--silver);text-decoration:none;font-size:13px;letter-spacing:0.08em;text-transform:uppercase;}
  .topbar .nav a:hover{color:var(--gold);}
  .topbar .nav a.cta{background:var(--gold-polish);color:#241a06;padding:11px 20px;font-weight:700;}
  /* Logo block in the footer, desktop hides it (logo lives in the top bar);
     phone shows it (the top bar is hidden so the hero/VSL leads). */
  .footer-logo{display:none;}
  .footer-logo img{height:48px;width:auto;}
  @media(max-width:720px){
    .topbar{display:none;}            /* free the top of the phone for the VSL */
    .footer-logo{display:block;text-align:center;margin-bottom:26px;}
  }

  /* ===== HERO ===== */
  .hero{position:relative;background:var(--brushed-deep);color:var(--white);text-align:center;padding:64px 0 70px;overflow:hidden;}
  .hero[data-hero-bg]:not([data-hero-bg=""]){background-image:linear-gradient(135deg,rgba(15,25,30,0.92),rgba(12,14,17,0.88)),var(--hero-bg-image);background-size:cover;background-position:center;}
  .hero::before{content:'';position:absolute;inset:0;background:radial-gradient(ellipse at 50% -10%,rgba(201,162,75,0.14),transparent 62%);}
  .hero::after{content:'';position:absolute;left:0;right:0;bottom:0;height:2px;background:var(--gold-polish);opacity:0.7;}
  .hero .inner{position:relative;z-index:2;}
  .hero h1{font-family:var(--font-accent);font-weight:600;font-size:clamp(34px,6vw,58px);margin:18px 0 14px;letter-spacing:-0.01em;text-transform:capitalize;}
  .hero h1 em{font-style:italic;background:var(--gold-polish);-webkit-background-clip:text;background-clip:text;color:transparent;}
  .hero .sub{font-size:clamp(16px,2.4vw,20px);color:var(--silver);max-width:600px;margin:0 auto 22px;}
  .hero .watch-cue{font-size:13px;letter-spacing:0.18em;text-transform:uppercase;color:var(--gold);font-weight:700;margin-bottom:18px;}
  .hero .vsl{position:relative;max-width:820px;margin:0 auto;aspect-ratio:16/9;background:#000;border:1px solid var(--steel);box-shadow:var(--shadow-d);overflow:hidden;border-radius:4px;display:flex;align-items:center;justify-content:center;}
  .hero .vsl .play{width:74px;height:74px;border-radius:50%;background:var(--gold-polish);display:flex;align-items:center;justify-content:center;box-shadow:0 8px 30px rgba(0,0,0,0.5);z-index:2;}
  .hero .vsl .play svg{width:30px;height:30px;fill:#241a06;margin-left:4px;}
  .hero .vsl .vbg{position:absolute;inset:0;background:linear-gradient(135deg,#2b3a2b,#16201a);opacity:0.6;}
  .hero .vsl .yt{position:absolute;top:10px;left:14px;color:rgba(255,255,255,0.7);font-size:11px;letter-spacing:0.1em;z-index:2;}
  .hero .vsl iframe{position:absolute;inset:0;width:100%;height:100%;border:0;z-index:1;}
  /* Uploaded VSL (the operator's own video file): native player in the same
     16:9 frame. contain = letterbox, never crop a talking head. */
  .hero .vsl video{position:absolute;inset:0;width:100%;height:100%;object-fit:contain;background:#000;z-index:1;}
  .hero .vsl-hint{margin-top:14px;color:var(--gold);font-size:12px;letter-spacing:0.16em;text-transform:uppercase;font-weight:700;}
  /* Hero photo, the alternative to a VSL (same prominent slot as the video). */
  .hero .hero-photo{max-width:820px;margin:0 auto;aspect-ratio:16/9;overflow:hidden;border:1px solid var(--steel);box-shadow:var(--shadow-d);border-radius:4px;background:#000;}
  .hero .hero-photo img{width:100%;height:100%;object-fit:cover;display:block;}
  .hero .hero-photo.te-hero-empty{display:flex;align-items:center;justify-content:center;text-align:center;color:var(--gold);font-size:14px;font-weight:700;letter-spacing:0.04em;padding:24px;background:linear-gradient(135deg,#2b3a2b,#16201a);}

  /* ===== QUALIFY (native multi-step form; gold edge + subtle glow, NO shimmer) ===== */
  .qualify{background:var(--brushed);color:var(--white);padding:58px 0;}
  .qualify .eyebrow{text-align:center;display:block;}
  .qualify h2{font-family:var(--font-accent);font-weight:600;font-size:clamp(26px,4.5vw,40px);text-align:center;margin:14px auto 10px;max-width:720px;}
  .qualify .sub{text-align:center;color:var(--silver);max-width:560px;margin:0 auto 22px;font-size:16px;}
  .survey-shell{background:var(--white);box-shadow:var(--shadow-d), 0 0 30px rgba(201,162,75,0.18);max-width:600px;margin:0 auto;border-radius:4px;
    overflow:hidden;border-top:3px solid var(--gold);padding:32px 30px;color:var(--ink);}
  .te-form .step{display:none;}
  .te-form .step.active{display:block;animation:te-fade 0.25s ease-out;}
  @keyframes te-fade{from{opacity:0;transform:translateY(4px);}to{opacity:1;transform:none;}}
  .te-form .q{font-family:var(--font-accent);font-weight:600;font-size:19px;margin-bottom:16px;color:var(--ink);}
  .te-form .opt{display:flex;align-items:center;gap:12px;width:100%;text-align:left;background:var(--white);padding:13px 16px;border:1px solid var(--line-light);border-radius:6px;margin-bottom:9px;font-size:15px;font-family:var(--font-body);color:var(--ink);cursor:pointer;transition:all .15s;}
  .te-form .opt:hover{border-color:var(--gold);background:#faf6ec;}
  .te-form .opt .ring{width:18px;height:18px;border:2px solid var(--silver-soft);border-radius:50%;flex-shrink:0;}
  .te-form .opt:hover .ring{border-color:var(--gold);}
  .te-back{background:none;border:0;color:var(--ink-soft);font-family:var(--font-body);
    font-size:13px;font-weight:700;letter-spacing:0.04em;cursor:pointer;padding:2px 0;margin-bottom:10px;
    display:inline-flex;align-items:center;gap:5px;}
  .te-back:hover{color:var(--gold-deep);}
  .te-form .te-input{display:block;width:100%;padding:12px 14px;margin-bottom:10px;font-size:15px;font-family:var(--font-body);border:1px solid var(--line-light);border-radius:6px;color:var(--ink);background:var(--white);}
  .te-form .te-input:focus{outline:none;border-color:var(--gold);box-shadow:0 0 0 3px rgba(201,162,75,0.12);}
  .te-form .submit-row{margin-top:14px;}
  .te-form .submit-row .btn{width:100%;}
  .te-form .prog{display:flex;align-items:center;gap:10px;margin-top:18px;}
  .te-form .bar{flex:1;height:7px;background:var(--paper-2);border-radius:4px;overflow:hidden;}
  .te-form .bar i{display:block;height:100%;background:var(--gold-polish);width:33%;transition:width 0.25s;}
  .te-form .pct{font-size:12px;color:var(--ink-soft);white-space:nowrap;}
  .te-form .done{text-align:center;padding:24px 8px;}
  .te-form .done h3{font-family:var(--font-accent);font-weight:600;font-size:22px;margin-bottom:10px;color:var(--ink);}
  .te-form .done p{font-size:15px;color:var(--ink-soft);}
  /* Honeypot, visually + a11y hidden, but still focusable to bots. */
  .te-form .te-hp{position:absolute !important;left:-9999px !important;width:1px;height:1px;opacity:0;pointer-events:none;}
  /* Real-failure band, only shown when retry has also failed. */
  .te-form .te-err{margin-top:12px;padding:10px 12px;border:1px solid #d4a02b;background:#fff8e6;color:#5a4205;font-size:13px;border-radius:6px;}
  /* Turnstile widget gets some room and centres in the form column. */
  .te-form .cf-turnstile{margin:10px 0;display:flex;justify-content:center;min-height:65px;}

  /* ===== LIGHT base ===== */
  .light{background:var(--paper);color:var(--ink);}
  .light.alt{background:var(--paper-2);}
  .light .eyebrow{color:var(--gold-deep);}

  /* ===== SCARCITY (light alt, honest capacity only, Rulebook H4) ===== */
  .scarcity{background:var(--paper-2);color:var(--ink);text-align:center;}
  .scarcity h2{font-family:var(--font-accent);font-weight:600;font-size:clamp(26px,4vw,38px);margin-bottom:6px;}
  .scarcity .cap{font-family:var(--font-display);font-size:clamp(40px,8vw,74px);
    background:var(--gold-polish);-webkit-background-clip:text;background-clip:text;color:transparent;line-height:1;margin:10px 0 18px;
    filter:drop-shadow(0 2px 3px rgba(168,132,47,0.25));}
  .scarcity p{font-size:18px;color:var(--ink-soft);max-width:560px;margin:0 auto 26px;}

  /* ===== GOOGLE REVIEWS (light, EARLY proof) ===== */
  .reviews .eyebrow{text-align:center;display:block;}
  .reviews h2{font-family:var(--font-accent);font-weight:600;font-size:clamp(28px,4.5vw,42px);text-align:center;margin:14px auto 6px;}
  .g-badge{display:flex;align-items:center;justify-content:center;gap:14px;margin:18px auto 8px;flex-wrap:wrap;}
  .g-badge .g-logo{width:26px;height:26px;}
  .g-badge .g-score{font-family:var(--font-accent);font-weight:600;font-size:30px;color:var(--ink);}
  .g-badge .g-stars{color:var(--gold);letter-spacing:2px;font-size:20px;}
  .g-badge .g-count{font-size:13px;color:var(--ink-soft);}
  .g-embed{max-width:980px;margin:18px auto 0;min-height:160px;}
  .g-embed iframe{width:100%;border:0;display:block;min-height:340px;}
  /* Builder-only placeholder card (the real widget renders on the live page). */
  .te-widget-ph{display:flex;align-items:center;justify-content:center;min-height:200px;
    border:2px dashed var(--gold-polish);border-radius:10px;background:rgba(168,132,47,0.05);}
  .te-widget-ph-in{text-align:center;color:var(--ink-soft);font-size:15px;line-height:1.8;}
  .te-widget-ph-in small{color:var(--ink-soft);opacity:0.7;}
  .review-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:22px;margin-top:18px;}
  .review{background:var(--white);border:1px solid var(--line-light);border-top:3px solid var(--gold);padding:28px;box-shadow:var(--shadow-l);}
  .review .rh{display:flex;align-items:center;gap:10px;margin-bottom:10px;}
  .review .rav{width:38px;height:38px;border-radius:50%;background:var(--gunmetal-2);color:var(--gold);display:flex;align-items:center;justify-content:center;font-family:var(--font-display);font-size:16px;}
  .review .stars{color:var(--gold);letter-spacing:3px;margin-bottom:10px;font-size:14px;}
  .review p{font-size:15px;color:var(--ink-soft);margin-bottom:14px;font-style:italic;}
  .review .who{font-weight:700;font-size:14px;}
  .review .where{font-size:13px;color:var(--silver-soft);}
  @media(max-width:720px){.review-grid{grid-template-columns:1fr;}}

  /* ===== WHAT WE DO (dark, premium editorial passages) ===== */
  .wwd{background:var(--brushed);color:var(--white);}
  .wwd .eyebrow{text-align:center;display:block;}
  .wwd h2.head{font-family:var(--font-accent);font-weight:600;font-size:clamp(28px,4.5vw,42px);text-align:center;margin:14px auto 50px;}
  .wwd .passage{max-width:760px;margin:0 auto 44px;text-align:center;}
  .wwd .passage:last-child{margin-bottom:0;}
  .wwd .passage h3{font-family:var(--font-accent);font-style:italic;font-weight:600;font-size:clamp(22px,3.4vw,30px);color:var(--gold-bright);margin-bottom:16px;line-height:1.2;}
  .wwd .passage p{font-size:17px;color:var(--silver);line-height:1.7;}
  .wwd .divider{width:60px;height:1px;background:var(--steel);margin:44px auto;}

  /* ===== PILLARS (light, 3-step journey, STEP 01/02/03) ===== */
  .intro .eyebrow{text-align:center;display:block;}
  .intro h2{font-family:var(--font-accent);font-weight:600;font-size:clamp(28px,4.5vw,42px);text-align:center;margin:14px auto 16px;max-width:760px;}
  .intro .lede{text-align:center;font-size:18px;color:var(--ink-soft);max-width:680px;margin:0 auto 46px;}
  .pillars{display:grid;grid-template-columns:repeat(3,1fr);gap:24px;}
  .pillar{position:relative;text-align:center;background:var(--white);border:1px solid var(--line-light);padding:34px 24px;box-shadow:var(--shadow-l);}
  .pillar::before{content:'';position:absolute;top:0;left:0;right:0;height:3px;background:var(--gold-polish);}
  .pillar .step{font-family:var(--font-display);font-size:13px;letter-spacing:0.1em;color:var(--gold-deep);margin-bottom:10px;}
  .pillar h3{font-family:var(--font-accent);font-weight:600;font-size:20px;margin-bottom:10px;}
  .pillar p{font-size:15px;color:var(--ink-soft);}
  @media(max-width:720px){.pillars{grid-template-columns:1fr;gap:16px;}}

  /* ===== VIDEO TESTIMONIALS (dark, BIG vertical YouTube cards) ===== */
  .vtest{background:var(--brushed-deep);color:var(--white);}
  .vtest .eyebrow{text-align:center;display:block;color:var(--gold);}
  .vtest h2{font-family:var(--font-accent);font-weight:600;font-size:clamp(30px,5vw,48px);text-align:center;margin:14px auto 8px;}
  .vtest .sub{text-align:center;color:var(--silver);max-width:580px;margin:0 auto 44px;font-size:17px;}
  .vgrid{display:grid;grid-template-columns:repeat(3,1fr);gap:22px;}
  .vcard{background:#000;aspect-ratio:9/16;position:relative;border-radius:8px;overflow:hidden;box-shadow:var(--shadow-d);display:flex;align-items:center;justify-content:center;transition:transform .2s;}
  .vcard:hover{transform:translateY(-4px);}
  .vcard iframe{position:absolute;inset:0;width:100%;height:100%;border:0;z-index:1;}
  .vcard .vbg{position:absolute;inset:0;background:linear-gradient(160deg,#2b3a2b,#16201a);opacity:0.7;}
  .vcard .play{width:64px;height:64px;border-radius:50%;background:var(--gold-polish);display:flex;align-items:center;justify-content:center;z-index:2;box-shadow:0 8px 26px rgba(0,0,0,0.6);}
  .vcard .play svg{width:26px;height:26px;fill:#241a06;margin-left:4px;}
  .vcard .yt{position:absolute;top:10px;left:12px;color:rgba(255,255,255,0.75);font-size:11px;letter-spacing:0.08em;z-index:2;}
  .vcard .nm{position:absolute;left:12px;bottom:12px;z-index:2;color:#fff;font-size:14px;font-weight:700;text-shadow:0 1px 4px #000;}
  @media(max-width:720px){.vgrid{grid-template-columns:1fr;max-width:340px;margin:0 auto;}}

  /* ===== CLIENT MESSAGES WALL (light alt, member-uploaded screenshots) ===== */
  .msgs{background:var(--paper-2);color:var(--ink);}
  .msgs .eyebrow{text-align:center;display:block;color:var(--gold-deep);}
  .msgs h2{font-family:var(--font-accent);font-weight:600;font-size:clamp(28px,4.5vw,42px);text-align:center;margin:14px auto 8px;}
  .msgs .sub{text-align:center;color:var(--ink-soft);max-width:560px;margin:0 auto 40px;font-size:16px;}
  .msg-wall{columns:3;column-gap:16px;}
  .msg{break-inside:avoid;margin-bottom:16px;background:var(--white);border:1px solid var(--line-light);border-radius:10px;padding:14px;box-shadow:var(--shadow-l);}
  .msg img{width:100%;display:block;border-radius:6px;}
  .msg .cap{font-size:11px;color:var(--silver-soft);margin-top:8px;}
  @media(max-width:720px){.msg-wall{columns:1;max-width:420px;margin:0 auto;}}

  /* ===== FAQ ===== */
  .faq .eyebrow{text-align:center;display:block;}
  .faq h2{font-family:var(--font-accent);font-weight:600;font-size:clamp(28px,4.5vw,42px);text-align:center;margin:14px auto 36px;}
  .faq-item{border-bottom:1px solid var(--line-light);padding:24px 0;max-width:820px;margin:0 auto;}
  .faq-item h3{font-family:var(--font-accent);font-weight:600;font-size:19px;margin-bottom:9px;color:var(--ink);}
  .faq-item p{font-size:16px;color:var(--ink-soft);}

  /* ===== ABOUT ===== */
  .about{background:var(--paper-2);color:var(--ink);}
  .about .row{display:grid;grid-template-columns:1fr 1.2fr;gap:46px;align-items:center;}
  .about img{width:100%;aspect-ratio:4/5;object-fit:cover;box-shadow:var(--shadow-l);border-radius:4px;}
  .about .ph{width:100%;aspect-ratio:4/5;box-shadow:var(--shadow-l);border-radius:4px;background:linear-gradient(160deg,#2b3a2b,#16201a);display:flex;align-items:flex-end;padding:18px;color:#fff;font-size:13px;}
  .about .eyebrow{display:block;margin-bottom:12px;}
  .about h2{font-family:var(--font-accent);font-weight:600;font-size:clamp(26px,4vw,38px);margin-bottom:18px;}
  .about p{font-size:16px;color:var(--ink-soft);margin-bottom:16px;}
  @media(max-width:720px){.about .row{grid-template-columns:1fr;gap:28px;}}

  /* ===== GUARANTEE ===== */
  .guarantee{background:var(--brushed);color:var(--white);text-align:center;}
  .guarantee .seal{position:relative;width:88px;height:88px;border-radius:50%;display:flex;align-items:center;justify-content:center;margin:0 auto 22px;background:radial-gradient(circle at 38% 32%,#2f3640,#171b20);border:2px solid var(--gold);box-shadow:0 0 46px rgba(201,162,75,0.3),inset 0 2px 8px rgba(255,255,255,0.08);}
  .guarantee .seal svg{width:42px;height:42px;fill:var(--gold-bright);}
  .guarantee h2{font-family:var(--font-accent);font-weight:600;font-size:clamp(26px,4vw,38px);margin-bottom:14px;}
  .guarantee p{font-size:17px;color:var(--silver);max-width:620px;margin:0 auto;}

  /* ===== GALLERY (dark, near bottom) ===== */
  .gallery{background:var(--brushed-deep);color:var(--white);}
  .gallery .eyebrow{text-align:center;display:block;}
  .gallery h2{font-family:var(--font-accent);font-weight:600;font-size:clamp(28px,4.5vw,42px);text-align:center;margin:14px auto 36px;}
  .grid-imgs{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;}
  .grid-imgs img{width:100%;aspect-ratio:4/3;object-fit:cover;border:1px solid var(--steel);transition:all .25s;}
  .grid-imgs img:hover{border-color:var(--gold);transform:scale(1.02);}
  .gallery .cap{text-align:center;margin-top:22px;font-size:14px;color:var(--silver-soft);}
  @media(max-width:720px){.grid-imgs{grid-template-columns:1fr 1fr;}}

  /* ===== CLOSER (gold band, SHIMMER LIVES HERE, second form + final CTA) ===== */
  .closer{position:relative;background:var(--gold-polish);color:#241a06;overflow:hidden;}
  .closer::before{content:'';position:absolute;inset:0;background:linear-gradient(110deg,transparent 30%,rgba(255,255,255,0.3) 50%,transparent 70%);background-size:250% 100%;animation:sheen 9s ease-in-out infinite;}
  .closer .inner{position:relative;z-index:2;text-align:center;}
  .closer h2{font-family:var(--font-accent);font-weight:600;font-size:clamp(28px,5vw,46px);margin-bottom:12px;}
  .closer p{font-size:18px;margin-bottom:28px;max-width:560px;margin-left:auto;margin-right:auto;}
  .closer .survey-shell{text-align:left;}

  /* ===== FOOTER ===== */
  .details{background:var(--black);color:var(--white);padding:54px 0 40px;border-top:1px solid var(--line-dark);}
  .details .row{display:grid;grid-template-columns:repeat(3,1fr);gap:30px;}
  .details h4{font-size:12px;letter-spacing:0.2em;text-transform:uppercase;color:var(--gold);margin-bottom:12px;}
  .details p{font-size:15px;color:var(--silver-soft);}
  .details a{color:var(--silver);}
  @media(max-width:720px){.details .row{grid-template-columns:1fr;gap:24px;}}

  /* ===== STICKY ===== */
  .sticky{position:fixed;left:0;right:0;bottom:0;z-index:50;background:rgba(10,11,13,0.97);backdrop-filter:blur(8px);border-top:2px solid var(--gold);padding:14px 22px;display:flex;align-items:center;justify-content:space-between;gap:16px;}
  .sticky .t{font-family:var(--font-accent);font-weight:600;font-size:18px;color:var(--gold);}
  .sticky .s{font-size:12px;color:var(--silver-soft);margin-top:2px;}
  .sticky a.cta{background:var(--gold-polish);color:#241a06;padding:14px 24px;font-weight:700;text-transform:uppercase;letter-spacing:0.05em;font-size:14px;text-decoration:none;white-space:nowrap;}
  body{padding-bottom:84px;}

  /* Static pages (thank-you / disqualification) reuse this chassis with the
     lead-capture machinery stripped: no enquiry CTA in the nav, no sticky
     apply bar. The VSL + scroll cue stay (a thank-you video is encouraged). */
  .te-static-page .topbar .cta,
  .te-static-page .sticky{display:none !important;}
  .te-static-page{padding-bottom:0 !important;}
  /* Big centred brand logo at the top of the static-page hero. */
  .thanks-logo{text-align:center;margin:0 auto 26px;}
  .thanks-logo img{max-width:300px;max-height:160px;width:auto;height:auto;object-fit:contain;}
  @media(max-width:720px){.thanks-logo img{max-width:220px;max-height:120px;}}
</style>
<link href="https://fonts.googleapis.com/css2?family=Anton&display=swap" rel="stylesheet">
</head>
<body class="">


<header class="topbar">
  <div class="inner">
    <img class="logo" src="/media/ghl_invite_14d9b135c60bf5ba5a432506/logos/179125ac8e78_JJH_LOGO_PNG-01-01__1_.png" alt="JJH Excavations">
    <nav class="nav">
      
      <a href="#work" >Our Work</a>
      <a href="#faq" >FAQs</a>
      <a class="cta" href="#apply" data-pixel="cta_click">Get A Quote</a>
    </nav>
  </div>
</header>


<section class="hero" data-section="hero" data-hero-bg="" style="--hero-bg-image: url('');">
  <div class="inner wrap">
    
    <span class="eyebrow">Family-Run Earthmoving · Macedon Ranges &amp; Mitchell Shire</span>
    <h1>DESIGNED TO IMPRESS BUILT TO ENDURE</h1>
    <p class="sub">Quality earthmoving for homeowners who expect more, backed by a reputation built on quality, not shortcuts </p>
    
    <script>
    /* Lead (Meta standard) fires on the thank-you page, the confirmed post-submit
       conversion. The .ty-next block renders ONLY on the thanks page (never on
       landing or disqualify). DEDUPED: the eventID is the lead id the form
       redirect put in ?lead=, the SAME id the submit-time fire and the
       server-side Conversions API mirror carry, so reloads and the
       browser/server pair collapse to ONE counted Lead. No id (a direct
       visit, a bot, a bookmark) fires nothing, and the honeypot fake-success
       id never fires (one shared id otherwise). fbq is undefined when tracking
       consent is off, so this no-ops then, the consent gate is preserved. */
    try { if (typeof fbq === 'function' && document.querySelector('.ty-next')) { var tyLead = new URLSearchParams(window.location.search).get('lead'); if (tyLead && tyLead !== 'honeypot') { fbq('track', 'Lead', {}, {eventID: 'lead_' + tyLead}); } } } catch (e) {}
    </script>
    
    <div class="hero-photo hero-photo-cover"><img src="/media/ghl_invite_14d9b135c60bf5ba5a432506/job_photos/7cead9ecbebd_20260721_133156.jpg" alt="JJH Excavations" style="object-fit:cover;object-position:50% 50%"></div>
    
  </div>
</section>


<section class="qualify" id="apply" data-section="form" >
  <div class="wrap narrow">
    <span class="eyebrow">Get Started</span>
    <h2>Tell Us What You Need Done</h2>
    <p class="sub">Fill this in and Jason will call you back himself, not a call centre.</p>
  </div>
  <div class="survey-shell" data-form-id="f_ba82f91ac3ef4e00aab95c4b785b8768" data-operator-id="ghl_invite_14d9b135c60bf5ba5a432506">
    <form class="te-form" id="te-form-f_ba82f91ac3ef4e00aab95c4b785b8768" novalidate data-total-steps="3"
          data-pixel="form_start" data-pixel-complete="form_complete">
      <div class="step active" data-step="1"><div class="q">Be honest, what's going on with your property right now?</div><button type="button" class="opt" data-next="2" data-field="pain" data-value="Driveway is rutted, washing out or turning to mud"><span class="ring"></span>Driveway is rutted, washing out or turning to mud</button><button type="button" class="opt" data-next="2" data-field="pain" data-value="Need a level site cut for a new home or shed"><span class="ring"></span>Need a level site cut for a new home or shed</button><button type="button" class="opt" data-next="2" data-field="pain" data-value="Bank or slope needs a retaining wall before it slips"><span class="ring"></span>Bank or slope needs a retaining wall before it slips</button><button type="button" class="opt" data-next="2" data-field="pain" data-value="Want the driveway, site cut and wall done as one package"><span class="ring"></span>Want the driveway, site cut and wall done as one package</button></div><div class="step" data-step="2"><button type="button" class="te-back">&larr; Back</button><div class="q">When are you looking to get started?</div><button type="button" class="opt" data-next="3" data-field="timing" data-value="next_30_days"><span class="ring"></span>In the next 30 days</button><button type="button" class="opt" data-next="3" data-field="timing" data-value="1_to_3_months"><span class="ring"></span>1 to 3 months out</button><button type="button" class="opt" data-next="3" data-field="timing" data-value="researching"><span class="ring"></span>Still researching</button></div>
      <div class="step" data-step="3">
        <button type="button" class="te-back">&larr; Back</button>
        <div class="q">Where should we send the next step?</div>
        <input class="te-input" name="first_name" placeholder="First name" autocomplete="given-name"  required>
        <input class="te-input" name="last_name"  placeholder="Last name"  autocomplete="family-name" required>
        <input class="te-input" name="mobile" placeholder="+61 4xx xxx xxx" type="tel" required>
        <input class="te-input" name="email"  placeholder="Email"          type="email" required>
        
        <input class="te-hp" name="website" tabindex="-1" autocomplete="off" aria-hidden="true" readonly>
        
        
        <div class="submit-row"><button type="submit" class="btn">Send It</button></div>
        <p class="te-consent" style="font-size:12px;line-height:1.5;opacity:.7;margin-top:10px;text-align:center;">
          By submitting, you agree to be contacted about your enquiry by SMS and email, including
          automated messages, at the details you provide. Message &amp; data rates may apply. Reply
          STOP to any text to opt out. See our
          <a href="https://toolbox.taskelites.com/legal/privacy-policy.html" target="_blank" rel="noopener" style="color:inherit;text-decoration:underline;">Privacy Policy</a>.
        </p>
        <div class="te-err" role="alert" aria-live="polite" hidden>
          Couldn't send that. Please try again, or call Jason Hobbs directly.
        </div>
      </div>
      <div class="step done" data-step="done">
        <h3>You're in. We'll be in touch shortly.</h3>
        <p>Check your phone for a confirmation text.</p>
      </div>
      <div class="prog"><span class="pct">Step 1 of 3</span><div class="bar"><i></i></div></div>
    </form>
  </div>
</section>








<section class="wwd" data-section="what_we_do" >
  <div class="wrap">
    <span class="eyebrow">What We Do</span>
    <h2 class="head">We don't just push dirt around. We build driveways, site cuts and walls that hold their shape for years.</h2>
    
    <div class="passage">
      <h3></h3>
      <p>A driveway is the first thing you see coming home and the last thing you drive over leaving. Done properly, it holds its fall, sheds the water and stays firm through a wet Macedon Ranges winter. We grade it right, build the base to carry the load, and finish it so it drives clean in every season, not just the day we leave.</p>
    </div>
    <div class="divider"></div>
    
    <div class="passage">
      <h3>The result you quietly want</h3>
      <p>A level pad ready for the slab. A rock wall that looks like it grew out of the bank. A driveway that never needs a second thought. That is the finish most people are really after, a property that just works and stops costing them weekends of patching, scraping and worrying every time it rains.</p>
    </div>
    <div class="divider"></div>
    
    <div class="passage">
      <h3>Work that belongs to the land</h3>
      <p>The best earthmoving is the kind nobody notices, because it looks like it was always there. We read the fall of your ground, work with the slope instead of fighting it, and set walls and cuts that sit true. In a year the grass takes hold and it looks like the land was shaped that way from the start.</p>
    </div>
    <div class="divider"></div>
    
  </div>
</section>


<section class="light intro" data-section="steps" >
  <div class="wrap narrow">
    <span class="eyebrow">How We Work</span>
    <h2>We Work With Your Land, Not Against It</h2>
    <p class="lede">Plenty of operators dig their part and drive off, leaving you the mess where their job meets yours. We think about the whole job so every piece fits the property.</p>
  </div>
  <div class="wrap">
    <div class="pillars">
      
      <div class="pillar">
        <div class="step">STEP 01</div>
        <h3>Read The Land</h3>
        <p>We walk your property, check the fall and the soil, and work out where the water runs. We plan the whole job before a machine moves so nothing gets fixed twice.</p>
      </div>
      
      <div class="pillar">
        <div class="step">STEP 02</div>
        <h3>Build It Right</h3>
        <p>The right base under the driveway, the right rock in the wall, the pad cut dead level. We use the machines and materials the job actually needs, done once.</p>
      </div>
      
      <div class="pillar">
        <div class="step">STEP 03</div>
        <h3>Looks Like It Belongs</h3>
        <p>We leave the ground tidy, the levels true and the finish clean. In a season it settles in and looks like it was always meant to be there.</p>
      </div>
      
    </div>
  </div>
</section>








<section class="light faq" id="faq" data-section="faq" >
  <div class="wrap">
    <span class="eyebrow" style="text-align:center;display:block;">Common Questions</span>
    <h2>The Questions People Ask Before They Book</h2>
    
    <div class="faq-item"><h3>My last driveway washed out within a year. How is yours different?</h3><p>That happens when the fall is wrong and the base is thin. We build the drainage into the design and set the base to carry the load, so the water runs off instead of cutting ruts. You get a driveway that holds through winter, not one you patch every spring.</p></div>
    
    <div class="faq-item"><h3>Can you do the driveway, site cut and retaining wall as one job?</h3><p>Yes, that is exactly the work we like most. We offer the driveway and site cut as a package, or driveway, site cut and walls all together. Doing it as one job means the levels tie in properly and you deal with one bloke, not three.</p></div>
    
    <div class="faq-item"><h3>Will you leave my property a mess?</h3><p>No. Leaving the land better than we found it is the whole point for us. We clean up as we go, set the levels true and finish the ground tidy. When we drive off it should look settled, not like a war zone with a machine parked in it.</p></div>
    
    <div class="faq-item"><h3>What areas do you cover?</h3><p>We work across the Macedon Ranges and Mitchell Shire, based out of Broadford and covering roughly 30km around, into Melbourne's north. If you're a home owner, farmer, hobby farmer or rural property owner in that patch, we can help.</p></div>
    
  </div>
</section>


<section class="about" data-section="about" >
  <div class="wrap">
    <div class="row">
      <img src="/media/ghl_invite_14d9b135c60bf5ba5a432506/job_photos/a7ee9bdfe13e_20241202_152659_0_.jpg" alt="Jason Hobbs">
      <div>
        <span class="eyebrow">About Us</span>
        <h2><span style="font-family:'Anton', Impact, sans-serif">Hey, I'm Jason Hobbs Owner Of JJH Excavations</span></h2>
        <p>I've been running machines around the Macedon Ranges and Mitchell Shire for 6 years. Driveways new and repaired, house and shed site cuts, rock and concrete retaining walls. Home owners, farmers, hobby farmers and rural property owners are who I build for.</p><p>What I care about is the whole job, not just my part of it. I take the time to understand what you actually want, then build it so it works with your land and lasts. Built once, done right, and the ground left better than I found it.</p><p>I run a 5t and a 14t excavator, a posi track and a tandem tipper, so I've got the gear to do the job start to finish. Get a quote and I'll come have a proper look. </p>
        <a class="btn" href="#apply" data-pixel="cta_click">Get A Quote</a>
      </div>
    </div>
  </div>
</section>





<section class="gallery" id="work" data-section="gallery" >
  <div class="wrap">
    <span class="eyebrow" style="text-align:center;display:block;">Recent Work</span>
    <h2>Driveways, Site Cuts And Walls We've Built</h2>
    <div class="grid-imgs" >
      <img src="/media/ghl_invite_14d9b135c60bf5ba5a432506/job_photos/f26c3f1e03e4_17323d5c-6f0f-4d87-b6ce-a20d5443b31d.jpg" alt="JJH Excavations recent work"><img src="/media/ghl_invite_14d9b135c60bf5ba5a432506/job_photos/ada8edd1dad0_20250219_145521.jpg" alt="JJH Excavations recent work"><img src="/media/ghl_invite_14d9b135c60bf5ba5a432506/job_photos/7f7a68298483_20250121_152049.jpg" alt="JJH Excavations recent work"><img src="/media/ghl_invite_14d9b135c60bf5ba5a432506/job_photos/16ee97dca8b3_20250513_152256.jpg" alt="JJH Excavations recent work"><img src="/media/ghl_invite_14d9b135c60bf5ba5a432506/job_photos/5bbb9c77ee01_20250513_152327.jpg" alt="JJH Excavations recent work"><img src="/media/ghl_invite_14d9b135c60bf5ba5a432506/job_photos/c908aa48d2af_20260116_154057.jpg" alt="JJH Excavations recent work"><img src="/media/ghl_invite_14d9b135c60bf5ba5a432506/job_photos/fb84368acda1_20260211_101002.jpg" alt="JJH Excavations recent work"><img src="/media/ghl_invite_14d9b135c60bf5ba5a432506/job_photos/1dca78bb18dc_DJI_20250917085714_0007_D.jpg" alt="JJH Excavations recent work"><img src="/media/ghl_invite_14d9b135c60bf5ba5a432506/job_photos/37bf1935d991_DJI_20260128175751_0067_D.jpg" alt="JJH Excavations recent work"><img src="/media/ghl_invite_14d9b135c60bf5ba5a432506/job_photos/90c9a78b64f4_DJI_20260128180249_0072_D.jpg" alt="JJH Excavations recent work"><img src="/media/ghl_invite_14d9b135c60bf5ba5a432506/job_photos/96ec31af2cbb_20260116_154319.jpg" alt="JJH Excavations recent work"><img src="/media/ghl_invite_14d9b135c60bf5ba5a432506/job_photos/73d8230f55c4_20260211_120306.jpg" alt="JJH Excavations recent work"><img src="/media/ghl_invite_14d9b135c60bf5ba5a432506/job_photos/a91678ed6e16_20260721_132159.jpg" alt="JJH Excavations recent work"><img src="/media/ghl_invite_14d9b135c60bf5ba5a432506/job_photos/470687e61c6b_20260721_132254.jpg" alt="JJH Excavations recent work"><img src="/media/ghl_invite_14d9b135c60bf5ba5a432506/job_photos/f7f0a7293fe1_20260721_132343.jpg" alt="JJH Excavations recent work"><img src="/media/ghl_invite_14d9b135c60bf5ba5a432506/job_photos/91713794ec9a_20260721_133048.jpg" alt="JJH Excavations recent work"><img src="/media/ghl_invite_14d9b135c60bf5ba5a432506/job_photos/7cead9ecbebd_20260721_133156.jpg" alt="JJH Excavations recent work"><img src="/media/ghl_invite_14d9b135c60bf5ba5a432506/job_photos/e41acf1e779d_20260721_132254__2_.jpg" alt="JJH Excavations recent work"><img src="/media/ghl_invite_14d9b135c60bf5ba5a432506/job_photos/b3eecf631dbe_20260713_104824.jpg" alt="JJH Excavations recent work"><img src="/media/ghl_invite_14d9b135c60bf5ba5a432506/job_photos/fd4fc7b17352_1000008087.jpg" alt="JJH Excavations recent work"><img src="/media/ghl_invite_14d9b135c60bf5ba5a432506/job_photos/4171b7e1ed75_IMG_20240731_211332_835.jpg" alt="JJH Excavations recent work">
    </div>
    
    <div class="cap">A look at recent jobs around the Macedon Ranges and Mitchell Shire.</div>
  </div>
</section>


<section class="closer" data-section="closer" >
  <div class="inner wrap narrow">
    <h2>Jason Will Come Have A Proper Look</h2>
    <p>Fixed price, no pressure. Tell us what you need and we'll work out the right way to do it once.</p>
    <div class="survey-shell" data-form-id="f_ba82f91ac3ef4e00aab95c4b785b8768-closer" data-operator-id="ghl_invite_14d9b135c60bf5ba5a432506">
      <form class="te-form" id="te-form-f_ba82f91ac3ef4e00aab95c4b785b8768-closer" novalidate data-total-steps="3">
        <div class="step active" data-step="1"><div class="q">Be honest, what's going on with your property right now?</div><button type="button" class="opt" data-next="2" data-field="pain" data-value="Driveway is rutted, washing out or turning to mud"><span class="ring"></span>Driveway is rutted, washing out or turning to mud</button><button type="button" class="opt" data-next="2" data-field="pain" data-value="Need a level site cut for a new home or shed"><span class="ring"></span>Need a level site cut for a new home or shed</button><button type="button" class="opt" data-next="2" data-field="pain" data-value="Bank or slope needs a retaining wall before it slips"><span class="ring"></span>Bank or slope needs a retaining wall before it slips</button><button type="button" class="opt" data-next="2" data-field="pain" data-value="Want the driveway, site cut and wall done as one package"><span class="ring"></span>Want the driveway, site cut and wall done as one package</button></div><div class="step" data-step="2"><button type="button" class="te-back">&larr; Back</button><div class="q">When are you looking to get started?</div><button type="button" class="opt" data-next="3" data-field="timing" data-value="next_30_days"><span class="ring"></span>In the next 30 days</button><button type="button" class="opt" data-next="3" data-field="timing" data-value="1_to_3_months"><span class="ring"></span>1 to 3 months out</button><button type="button" class="opt" data-next="3" data-field="timing" data-value="researching"><span class="ring"></span>Still researching</button></div>
        <div class="step" data-step="3">
          <button type="button" class="te-back">&larr; Back</button>
          <div class="q">Where should we send the next step?</div>
          <input class="te-input" name="first_name" placeholder="First name" autocomplete="given-name"  required>
          <input class="te-input" name="last_name"  placeholder="Last name"  autocomplete="family-name" required>
          <input class="te-input" name="mobile" placeholder="+61 4xx xxx xxx" type="tel" required>
          <input class="te-input" name="email"  placeholder="Email"          type="email" required>
          <input class="te-hp" name="website" tabindex="-1" autocomplete="off" aria-hidden="true" readonly>
          
          <div class="submit-row"><button type="submit" class="btn">Send It</button></div>
          <p class="te-consent" style="font-size:12px;line-height:1.5;opacity:.7;margin-top:10px;text-align:center;">
            By submitting, you agree to be contacted about your enquiry by SMS and email, including
            automated messages, at the details you provide. Message &amp; data rates may apply. Reply
            STOP to any text to opt out. See our
            <a href="https://toolbox.taskelites.com/legal/privacy-policy.html" target="_blank" rel="noopener" style="color:inherit;text-decoration:underline;">Privacy Policy</a>.
          </p>
          <div class="te-err" role="alert" aria-live="polite" hidden>
            Couldn't send that. Please try again, or call Jason Hobbs directly.
          </div>
        </div>
        <div class="step done" data-step="done">
          <h3>You're in. We'll be in touch shortly.</h3>
          <p>Check your phone for a confirmation text.</p>
        </div>
        <div class="prog"><span class="pct">Step 1 of 3</span><div class="bar"><i></i></div></div>
      </form>
    </div>
  </div>
</section>


<footer class="details" data-section="footer">
  <div class="wrap">
    <div class="footer-logo" ><img src="/media/ghl_invite_14d9b135c60bf5ba5a432506/logos/179125ac8e78_JJH_LOGO_PNG-01-01__1_.png" alt="JJH Excavations"></div>
    <div class="row">
      <div><h4>Hours</h4><p>Mon-Fri 7:00am-6:00pm<br>Sat by arrangement</p></div>
      <div><h4>Contact</h4><p><br><a href="mailto:"></a></p></div>
      <div><h4>JJH Excavations</h4><p>Victoria , Melbourne,  Mitchell shire Broadford & Macedon rangers</p></div>
    </div>
  </div>
</footer>


<div class="sticky">
  <div>
    <div class="t">Booking Now</div>
    <div class="s">Driveways, site cuts and retaining walls done right.</div>
  </div>
  <a class="cta" href="#apply" data-pixel="cta_click">Get A Quote</a>
</div>

<script>
/* PIXEL 9/10 scroll_50 · PIXEL 10/10 scroll_90, member's pixel 1702108444541489.
   Per-section custom pixel events + native multi-step form handler are
   injected by the Landing Page Agent (template_filler._inject_pixel_events). */
</script>


<style>
  /* Hidden by default; switched on when iframe mode activates. */
  body.te-iframe-mode [data-section] {
    position: relative;
    cursor: pointer;
    border: 2px solid transparent;
    transition: border-color 0.15s, box-shadow 0.15s, background 0.4s;
  }
  body.te-iframe-mode [data-section]:hover { border-color: rgba(245, 184, 0, 0.45); }
  body.te-iframe-mode [data-section].te-picked {
    border-color: #f5b800;
    box-shadow: inset 0 0 0 1px rgba(245, 184, 0, 0.35);
  }
  body.te-iframe-mode [data-section]::before {
    content: attr(data-section);
    position: absolute; top: 8px; right: 8px; z-index: 9;
    background: #f5b800; color: #0c0b09;
    font-family: var(--font-display);
    font-size: 9px; letter-spacing: 0.08em; text-transform: uppercase;
    padding: 3px 8px; border-radius: 4px;
    opacity: 0; transition: opacity 0.15s; pointer-events: none;
  }
  body.te-iframe-mode [data-section]:hover::before,
  body.te-iframe-mode [data-section].te-picked::before { opacity: 1; }
  body.te-iframe-mode [data-section].te-flash {
    animation: te-flash 1.5s ease-out;
  }
  @keyframes te-flash {
    0%   { background: rgba(245, 184, 0, 0.22); }
    100% { background: transparent; }
  }
/* "Just inserted" section style, always applies (looks at home on
     the deployed page too, not just in the Toolbox iframe). */
</style>
<style>
  .te-new-section {
    background: var(--gunmetal-2);
    padding: 60px 26px; color: var(--silver);
  }
  .te-new-section .kicker {
    font-family: var(--font-body); font-weight: 800;
    font-size: 11px; letter-spacing: 0.22em; text-transform: uppercase;
    color: var(--gold); margin-bottom: 14px; text-align: center;
  }
  .te-new-section h2 {
    font-family: var(--font-display); font-size: 28px;
    text-transform: uppercase; color: var(--white);
    text-align: center; margin-bottom: 18px;
  }
  .te-new-section p {
    font-family: var(--font-accent); font-size: 17px; line-height: 1.7;
    color: var(--silver); max-width: 640px; margin: 0 auto;
    text-align: center;
  }
</style>



<script>
// Per-section custom pixel events. Member's pixel: 1702108444541489
(function(){
  if (typeof fbq !== 'function') return;
  var sections = [
    ['.hero',      'ViewedHero'],
    ['#apply',     'ViewedForm'],
    ['.reviews',   'ViewedTestimonials'],
    ['.intro',     'ViewedHowItWorks'],
    ['.about',     'ViewedFounders'],
    ['.vtest',     'ViewedFilter'],
    ['.faq',       'ViewedFAQ'],
    ['.closer',    'ViewedFinalCTA'],
    // Supplementary (ADDITIVE only) events for the winning sections that were
    // previously unwired. These are extra scroll-depth signals; they never
    // replace the 10 required standard events above.
    ['.wwd',       'ViewedWhatWeDo'],
    ['.gallery',   'ViewedWork'],
    ['.guarantee', 'ViewedGuarantee'],
    ['.scarcity',  'ViewedScarcity']
  ];
  var seen = {};
  var io = new IntersectionObserver(function(entries){
    entries.forEach(function(e){
      if (!e.isIntersecting) return;
      sections.forEach(function(s){
        if (e.target.matches(s[0]) && !seen[s[1]]) {
          seen[s[1]] = true;
          fbq('trackCustom', s[1]);
        }
      });
    });
  }, {threshold: 0.4});
  sections.forEach(function(s){
    document.querySelectorAll(s[0]).forEach(function(el){ io.observe(el); });
  });
  // Deep-scroll signal (>=75% of the page) → feeds the HOT retargeting audience.
  var scrolled75 = false;
  window.addEventListener('scroll', function(){
    if (scrolled75) return;
    var st = window.pageYOffset || document.documentElement.scrollTop || 0;
    var h = document.documentElement.scrollHeight - window.innerHeight;
    if (h > 0 && (st / h) >= 0.75) { scrolled75 = true; fbq('trackCustom', 'Scrolled75'); }
  }, {passive: true});
  // Lead (Meta standard), fires on confirmed form submission. The eventID is
  // the lead's own inbox id, the SAME id the thanks-page fire and the
  // server-side Conversions API mirror carry, so Meta counts exactly ONE
  // Lead per lead however many of the fires get through. No id, no fire (a
  // real success always carries one). The honeypot fake-success id is never
  // fired: it would give every trapped submission ONE shared event id.
  window.addEventListener('message', function(e){
    if (e.origin !== window.location.origin) return;  // R10: only our own page's form, not a framing attacker
    if (e && e.data && e.data.type === 'form_submitted' && e.data.lead_id
        && e.data.lead_id !== 'honeypot') {
      fbq('track', 'Lead', {}, {eventID: 'lead_' + e.data.lead_id});
    }
  });
})();

// ---- Native multi-step form (qualify + closer sections share this handler) ----
(function(){
  var forms = document.querySelectorAll('.te-form');
  if (!forms.length) return;
  // Operator setting (survey builder): require a valid AU mobile before submit.
  var REQUIRE_MOBILE = true;
  // Canonicalise an AU mobile to +61 E.164, or null when it isn't one. Mirrors
  // shared/auphone.py on the server. Kept free of backslash escapes (it lives
  // inside a non-raw Python string): a [^0-9] class plus length/prefix checks.
  function normalizeAuMobile(raw){
    var d = String(raw || '').replace(/[^0-9]/g, '');
    var nat = null;
    if (d.length === 11 && d.slice(0, 2) === '61' && d.charAt(2) === '4') nat = d.slice(2);
    else if (d.length === 10 && d.slice(0, 2) === '04') nat = d.slice(1);
    else if (d.length === 9 && d.charAt(0) === '4') nat = d;
    if (!nat || nat.length !== 9 || nat.charAt(0) !== '4') return null;
    return '+61' + nat;
  }
  // Self-hosted invisible challenge: a fresh single-use token is fetched per
  // submit attempt (see attempt()), replacing per-page Turnstile, which can't
  // scale to per-operator domains. Fetching per attempt (not once on load)
  // means a real visitor is NEVER blocked by a load-time blip, a token expiring
  // while they fill the form, or single-use rejecting a retry, while a bot still
  // has to call our token endpoint (signed, single-use, IP-rate-limited).
  var _tokUrl = 'https://toolbox.taskelites.com/api/leads'.replace('/api/leads', '/api/lead-form/token');
  function fetchFormToken(){
    try {
      return fetch(_tokUrl, { credentials: 'omit' })
        .then(function(r){ return r.json(); })
        .then(function(d){ return (d && d.token) || ''; })
        .catch(function(){ return ''; });
    } catch (e) { return Promise.resolve(''); }
  }
  var formStartedFired = false;
  function fireFormStarted(){
    if (formStartedFired) return;
    formStartedFired = true;
    if (typeof fbq === 'function') fbq('trackCustom', 'FormStarted');
  }
  forms.forEach(function(form){
    var shell = form.closest('.survey-shell');
    var operatorId = (shell && shell.getAttribute('data-operator-id')) || '';
    // R7: opaque server-issued form id, what the submit is attributed by.
    var formId = (shell && shell.getAttribute('data-form-id')) || '';
    var total = parseInt(form.getAttribute('data-total-steps') || '3', 10) || 3;
    var state = {};
    var disqualified = false;
    var current = 1;
    var history = [];
    function goToStep(n){
      form.querySelectorAll('.step').forEach(function(s){ s.classList.remove('active'); });
      var target = form.querySelector('.step[data-step="' + n + '"]');
      if (target) target.classList.add('active');
      if (n !== 'done') current = parseInt(n, 10) || current;
      var pct = form.querySelector('.pct');
      var bar = form.querySelector('.bar i');
      if (n === 'done'){
        if (pct) pct.textContent = 'Sent';
        if (bar) bar.style.width = '100%';
      } else {
        if (pct) pct.textContent = 'Step ' + n + ' of ' + total;
        if (bar) bar.style.width = Math.round((parseInt(n, 10) / total) * 100) + '%';
      }
    }
    form.querySelectorAll('.opt').forEach(function(opt){
      opt.addEventListener('click', function(){
        fireFormStarted();
        var field = opt.getAttribute('data-field') || '';
        if (field) state[field] = opt.getAttribute('data-value') || '';
        if (opt.getAttribute('data-disqualify') === '1') disqualified = true;
        var next = opt.getAttribute('data-next');
        if (next) { history.push(current); goToStep(parseInt(next, 10)); }
      });
    });
    // Back buttons, return to the previous step the visitor came from.
    form.querySelectorAll('.te-back').forEach(function(b){
      b.addEventListener('click', function(e){
        e.preventDefault();
        if (history.length) goToStep(history.pop());
        else if (current > 1) goToStep(current - 1);
      });
    });
    form.addEventListener('submit', function(e){
      e.preventDefault();
      // Require a complete name so a lead can never come through partial (the
      // reason a single "name" box let "Harry" through alone). Require whichever
      // name inputs the form actually renders: the two-box form needs first AND
      // last; a legacy single-box page needs its lone `name` (so this guard never
      // blocks a legacy form that has no first/last inputs). Scoped to the name
      // fields; email/phone keep their existing behaviour (`novalidate`).
      var _firstEl = form.querySelector('input[name="first_name"]');
      var _lastEl  = form.querySelector('input[name="last_name"]');
      var _nameEl  = form.querySelector('input[name="name"]');
      var _bad = null;
      if (_firstEl || _lastEl) {
        if (!((_firstEl && _firstEl.value || '').trim()))      _bad = _firstEl;
        else if (!((_lastEl && _lastEl.value || '').trim()))   _bad = _lastEl;
      } else if (_nameEl && !((_nameEl.value || '').trim())) {
        _bad = _nameEl;
      }
      if (_bad) {
        if (_bad.reportValidity) _bad.reportValidity();
        _bad.focus();
        return;
      }
      // When the operator requires a valid AU mobile, block submit until the
      // phone is a real mobile, with an inline nudge (the operator + the SMS
      // concierge need a textable number). Server re-checks as the backstop.
      if (REQUIRE_MOBILE) {
        var _mobEl = form.querySelector('input[name="mobile"]');
        if (!normalizeAuMobile((_mobEl && _mobEl.value) || '')) {
          if (_mobEl) {
            if (_mobEl.setCustomValidity) {
              _mobEl.setCustomValidity('Enter a valid Australian mobile, like 0412 345 678.');
              if (_mobEl.reportValidity) _mobEl.reportValidity();
              _mobEl.setCustomValidity('');
            }
            _mobEl.focus();
          }
          return;
        }
      }
      var submitBtn = form.querySelector('button[type="submit"]');
      var errBand = form.querySelector('.te-err');
      function setSending(on){
        if (submitBtn){
          submitBtn.disabled = on;
          submitBtn.textContent = on ? 'Sending…' : 'Send It';
        }
      }
      function showFailure(){
        if (errBand) { errBand.hidden = false; }
        setSending(false);
        // Re-arm submit so the visitor can fix and try again.
      }
      function readPayload(){
        // Full name is captured as two boxes (first + last) so the operator
        // always gets a complete name. We send the joined "First Last" as
        // customer_name; the whole downstream (inbox, SMS greeting, contact
        // push) already splits customer_name on the first space. Legacy pages
        // that still render a single 'name' input fall back to it.
        var first = ((form.querySelector('input[name="first_name"]') || {}).value || '').trim();
        var last  = ((form.querySelector('input[name="last_name"]')  || {}).value || '').trim();
        if (!first && !last) {
          first = ((form.querySelector('input[name="name"]') || {}).value || '').trim();
        }
        var name  = (first + ' ' + last).trim();
        var phone = ((form.querySelector('input[name="mobile"]') || {}).value || '').trim();
        // Send the mobile as clean +61 E.164 when it's a valid AU mobile, so the
        // operator + SMS concierge get one consistent, textable number.
        if (REQUIRE_MOBILE) { var _pn = normalizeAuMobile(phone); if (_pn) phone = _pn; }
        var email = ((form.querySelector('input[name="email"]')  || {}).value || '').trim();
        // Honeypot, bots fill, humans don't. Server rejects when non-empty.
        var honey = ((form.querySelector('input[name="website"]') || {}).value || '').trim();
        // Turnstile token sits in the auto-injected hidden input inside
        // the .cf-turnstile widget.
        var tokenEl = form.querySelector('[name="cf-turnstile-response"]');
        var token = tokenEl ? (tokenEl.value || '') : '';
        // Source attribution, best-effort. Read the ad/click params off the
        // landing URL so the captured lead carries the ad that sent it. If a
        // param is absent we send '' (no attribution), never block the form.
        var params = new URLSearchParams(window.location.search || '');
        var enquiryParts = [];
        if (disqualified) enquiryParts.push('[DISQUALIFIED]');
        for (var k in state){ if (state[k]) enquiryParts.push(k + ': ' + state[k]); }
        return {
          form_id: formId,
          operator_id: operatorId,
          customer_name: name,
          customer_email: email,
          customer_phone: phone,
          enquiry: enquiryParts.join(' · '),
          disqualified: disqualified,
          page_source: window.location.href,
          submitted_at_iso: new Date().toISOString(),
          website: honey,
          'cf-turnstile-response': token,
          turnstile_token: token,
          te_ad:        params.get('te_ad')        || '',
          fbclid:       params.get('fbclid')       || '',
          utm_source:   params.get('utm_source')   || '',
          utm_medium:   params.get('utm_medium')   || '',
          utm_campaign: params.get('utm_campaign') || '',
          utm_content:  params.get('utm_content')  || '',
          utm_term:     params.get('utm_term')     || ''
        };
      }
      function buildThanksUrl(leadId){
        var base = 'thanks/';
        if (!base || base.charAt(0) === '_') return '';
        if (!leadId) return base;
        // Insert ?lead= BEFORE any #fragment, or a custom thanks URL like
        // /thanks#book would bury the id in the fragment where the thanks
        // page's ?lead= read (the Lead eventID) can never see it.
        var hashAt = base.indexOf('#');
        var frag = hashAt === -1 ? '' : base.slice(hashAt);
        var main = hashAt === -1 ? base : base.slice(0, hashAt);
        return main + (main.indexOf('?') === -1 ? '?' : '&')
                    + 'lead=' + encodeURIComponent(leadId) + frag;
      }
      function redirectOnSuccess(leadId){
        window.postMessage({type: 'form_submitted', lead_id: leadId}, '*');
        var url = buildThanksUrl(leadId);
        if (url) {
          window.location.replace(url);
        } else {
          // No thanks URL configured AND we have a real success, fall
          // back to the inline 'done' step. This branch shouldn't fire
          // in production because publish always sets a thank-you URL.
          goToStep('done');
        }
      }
      // One submit can fire at most one outcome (success redirect OR
      // failure band) and we never call both.
      var settled = false;
      function settleSuccess(leadId){
        if (settled) return; settled = true;
        redirectOnSuccess(leadId);
      }
      function settleFailure(){
        if (settled) return; settled = true;
        showFailure();
      }
      // 8s hard timeout, covers a hung connection. Doesn't redirect;
      // shows the fallback instead, because we never claim success
      // without a real lead id.
      var hardTimeout = setTimeout(settleFailure, 8000);

      function attempt(payload, isRetry){
        // Fresh anti-bot token for THIS attempt, then post. Best-effort: an
        // unreachable token endpoint yields '' and we still post (the server
        // decides whether to require it, staged rollout).
        return fetchFormToken().then(function(tok){
          payload.lead_form_token = tok || '';
          return fetch('https://toolbox.taskelites.com/api/leads', {
            method: 'POST',
            mode: 'cors',
            credentials: 'omit',
            headers: {'Content-Type': 'application/json', 'Accept': 'application/json'},
            body: JSON.stringify(payload)
          });
        }).then(function(r){
          return r.json().catch(function(){ return null; }).then(function(body){
            return {status: r.status, ok: r.ok, body: body};
          });
        });
      }
      function classify(result){
        // Real success only when 2xx, body.ok === true AND a lead_id is
        // present. Anything else = failure. We never fake success.
        if (!result || !result.ok) return 'fail';
        var b = result.body || {};
        if (b.ok === true && b.lead_id) return 'success';
        return 'fail';
      }
      function shouldRetry(result){
        // Don't retry honest 4xx (invalid input, honeypot, challenge
        // failed, rate-limited). Retry network errors and 5xx only.
        if (!result) return true;                  // network blew up
        if (result.status >= 500) return true;     // server hiccup
        return false;
      }

      setSending(true);
      if (errBand) errBand.hidden = true;
      var payload = readPayload();
      attempt(payload, false).then(function(result){
        if (settled) return;
        if (classify(result) === 'success') {
          clearTimeout(hardTimeout);
          settleSuccess(result.body.lead_id);
          return;
        }
        if (!shouldRetry(result)) {
          clearTimeout(hardTimeout);
          settleFailure();
          return;
        }
        // One retry, after a short jittered pause.
        setTimeout(function(){
          attempt(readPayload(), true).then(function(r2){
            if (settled) return;
            clearTimeout(hardTimeout);
            if (classify(r2) === 'success') {
              settleSuccess(r2.body.lead_id);
            } else {
              settleFailure();
            }
          }).catch(function(){
            if (settled) return;
            clearTimeout(hardTimeout);
            settleFailure();
          });
        }, 700);
      }).catch(function(){
        // First-shot network error, try once more.
        if (settled) return;
        setTimeout(function(){
          attempt(readPayload(), true).then(function(r2){
            if (settled) return;
            clearTimeout(hardTimeout);
            if (classify(r2) === 'success') {
              settleSuccess(r2.body.lead_id);
            } else {
              settleFailure();
            }
          }).catch(function(){
            if (settled) return;
            clearTimeout(hardTimeout);
            settleFailure();
          });
        }, 700);
      });
    });
  });
})();
</script>

<script>
(function(){
  // Hero VSL: show the YouTube thumbnail when a video is set. On the LIVE page
  // mount the player immediately with muted autoplay; browsers block autoplay
  // with sound, so the visitor taps the YouTube control to unmute. In the builder
  // (page is in the toolbox iframe) we only show the thumbnail; clicking opens
  // the section settings instead.
  var inBuilder = (window.parent !== window);
  document.querySelectorAll('.vsl[data-vsl-id]').forEach(function(v){
    var id = (v.getAttribute('data-vsl-id')||'').trim();
    if(!id) return;
    var bg = v.querySelector('.vbg') || v;
    bg.style.backgroundImage = "url('https://img.youtube.com/vi/"+id+"/hqdefault.jpg')";
    bg.style.backgroundSize = 'cover';
    bg.style.backgroundPosition = 'center';
    bg.style.opacity = '1';
    if(inBuilder) return;
    v.style.cursor = 'pointer';
    function mount(){
      if(v.querySelector('iframe')) return;
      var f = document.createElement('iframe');
      f.src = 'https://www.youtube.com/embed/'+id+'?autoplay=1&mute=1&playsinline=1&rel=0';
      f.setAttribute('allow','autoplay; encrypted-media; picture-in-picture');
      f.setAttribute('allowfullscreen','');
      f.style.cssText = 'position:absolute;inset:0;width:100%;height:100%;border:0;z-index:5;';
      v.appendChild(f);
    }
    mount();
    v.addEventListener('click', mount);
  });
})();
</script>

</body>
</html>

<!-- te-template:1a03652dc498 -->
