/* Ambassadors — /ambassadors, the record-shop referral programme waitlist.

   The pitch: The Lead-In tracks what a collection is WORTH, so it doesn't
   compete with a shop selling records — which makes it a rare partner a shop
   can point customers at without cannibalising its own sales. Shops drop QR
   codes in-store and flyers into vinyl bags; in return they earn a share of the
   subscription revenue from customers they refer.

   AUDIENCE NOTE: unlike every other page on this site, the reader here is a shop
   owner who has probably never heard of The Lead-In and is not a user of it. The
   page therefore explains the product BEFORE it pitches the deal — a "what is
   this?" section with a mockup of the app sits above the commercial argument,
   because "50/50 of what, exactly?" is unanswerable otherwise.

   The subscription tier is not live yet, so this is a WAITLIST, not an active
   payout programme — the copy is deliberately "founding partner", not "earn
   today". The 50/50 line is the hook; we do NOT commit to lifetime-vs-window in
   writing here (that term is still being decided).

   Writes each shop straight to the `ambassador_waitlist` Supabase table via the
   anon key (RLS = insert-only), same fire-and-forget posture as NewsletterSignup
   / FeedbackWidget. Duplicate email = "already on the list", not an error.
   Emits GA4 events ambassador_view / ambassador_submit. */

(function () {
  const { useState, useEffect, useRef } = React;

  const track = (name, params) => { try { if (window.gtag) window.gtag("event", name, params || {}); } catch (e) {} };
  const EMAIL_RE = /^[^@\s]+@[^@\s]+\.[^@\s]+$/;

  // Revenue model. The planned subscription is £4.99/month and the shop keeps a
  // 50/50 split, so each referred subscriber is worth £2.495/month to the shop.
  // The slider drives the DIRECT number — subscribers referred — deliberately:
  // we don't bury a made-up "X% of customers convert" rate in the maths, so the
  // figure can't quietly overpromise. The shop plugs in its own expectation.
  const SUB_PRICE = 4.99;
  const SHOP_SHARE = 0.5;
  const PER_SUB = SUB_PRICE * SHOP_SHARE; // 2.495 / month
  const gbp = (n, dp) => "£" + n.toLocaleString("en-GB", { minimumFractionDigits: dp, maximumFractionDigits: dp });

  const VOLUME_BANDS = [
    "Under 50 records a week",
    "50–200 a week",
    "200–500 a week",
    "500+ a week",
  ];

  // Sample shelf for the app mockup. Real records with plausible values, so a
  // shop owner recognises the product at a glance. Deliberately static art —
  // it illustrates the app, it is not a live valuation.
  // Real covers from /covers/<slug>.jpg — the same artwork the product shows.
  // Flat colour swatches read as a placeholder; actual sleeves read as an app.
  const MOCK_SHELF = [
    { t: "Rumours", a: "Fleetwood Mac", v: "£42", slug: "rumours" },
    { t: "Kind of Blue", a: "Miles Davis", v: "£120", slug: "kind-of-blue" },
    { t: "The Queen Is Dead", a: "The Smiths", v: "£38", slug: "the-queen-is-dead" },
    { t: "Remain in Light", a: "Talking Heads", v: "£54", slug: "remain-in-light" },
    { t: "Blue Lines", a: "Massive Attack", v: "£31", slug: "blue-lines" },
    { t: "Unknown Pleasures", a: "Joy Division", v: "£68", slug: "unknown-pleasures" },
  ];
  // Bottom tab bar for the mockup — the app's real shape, and it stops the
  // screen bottom reading as empty dead space.
  const MOCK_TABS = [
    { k: "Shelf", d: "M2 3h12v3.4H2zM2 8.3h12v3.4H2z" },
    { k: "The 100", d: "M2 3.4h12v1.7H2zM2 7.2h12v1.7H2zM2 11h8v1.7H2z" },
    { k: "Today", d: "M8 2a6 6 0 100 12A6 6 0 008 2zm0 4.6a1.4 1.4 0 110 2.8 1.4 1.4 0 010-2.8z" },
    { k: "You", d: "M8 2.6a2.7 2.7 0 110 5.4 2.7 2.7 0 010-5.4zM2.8 13.4a5.2 5.2 0 0110.4 0z" },
  ];
  // Twelve months of shelf value for the phone's sparkline — rising, but with
  // the dips a real market has. Static art, like the rest of the mockup.
  const MOCK_TREND = [18, 26, 22, 34, 30, 44, 52, 47, 60, 71, 66, 82];

  // Deterministic pseudo-QR module grid for the kit mockup. NOT a scannable
  // code — the printed kit carries each shop's real one. A fixed hash rather
  // than Math.random so every paint (and the prerendered shell) is identical.
  function qrModules(n) {
    const out = [];
    const finder = (x, y) => (x < 7 && y < 7) || (x >= n - 7 && y < 7) || (x < 7 && y >= n - 7);
    const hole = (x, y) => x > n / 2 - 4 && x < n / 2 + 3 && y > n / 2 - 4 && y < n / 2 + 3;
    for (let y = 0; y < n; y++) {
      for (let x = 0; x < n; x++) {
        if (finder(x, y) || hole(x, y)) continue;
        const h = (x * 73856093) ^ (y * 19349663) ^ ((x + y) * 83492791);
        if (((h >>> 3) & 7) < 3) out.push(x + "," + y);
      }
    }
    return out;
  }
  const QR_N = 25;
  const QR_CELLS = qrModules(QR_N);

  // Mock QR art. Three finder squares + the deterministic field + a centre punch
  // holding the mark, which is how the printed card will actually look.
  function QrArt() {
    const s = 100 / QR_N;
    const finderAt = (fx, fy) => (
      <g key={fx + "-" + fy}>
        <rect x={fx * s} y={fy * s} width={s * 7} height={s * 7} rx={s} fill="currentColor" />
        <rect x={(fx + 1) * s} y={(fy + 1) * s} width={s * 5} height={s * 5} rx={s * .6} fill="#fffdf8" />
        <rect x={(fx + 2) * s} y={(fy + 2) * s} width={s * 3} height={s * 3} rx={s * .4} fill="currentColor" />
      </g>
    );
    return (
      <svg className="amb-qr" viewBox="0 0 100 100" role="img" aria-label="Illustration of the counter QR code">
        <rect width="100" height="100" fill="#fffdf8" />
        {QR_CELLS.map((c) => {
          const [x, y] = c.split(",");
          return <rect key={c} x={x * s} y={y * s} width={s * .92} height={s * .92} fill="currentColor" />;
        })}
        {[finderAt(0, 0), finderAt(QR_N - 7, 0), finderAt(0, QR_N - 7)]}
        <circle cx="50" cy="50" r="13" fill="#fffdf8" />
        <text x="50" y="55.5" textAnchor="middle" className="amb-qr-mark">LI</text>
      </svg>
    );
  }

  // True once the element has been scrolled into view. Resolves to true
  // immediately where IntersectionObserver is missing, so anything gated on it
  // still renders rather than waiting forever.
  function useInView(ref, threshold) {
    const [seen, setSeen] = useState(false);
    useEffect(() => {
      if (!ref.current) return;
      if (!("IntersectionObserver" in window)) { setSeen(true); return; }
      const io = new IntersectionObserver((entries) => {
        entries.forEach((en) => { if (en.isIntersecting) { setSeen(true); io.disconnect(); } });
      }, { threshold: threshold || 0.3 });
      io.observe(ref.current);
      return () => io.disconnect();
    }, [ref, threshold]);
    return seen;
  }

  // Ease a number up to its target once `active`. Jumps straight to the final
  // value under reduced motion — the figure is information, not decoration, so
  // it must never be left mid-count.
  function useCountUp(target, active, ms) {
    const [v, setV] = useState(0);
    useEffect(() => {
      if (!active) return;
      const reduce = window.matchMedia && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
      if (reduce) { setV(target); return; }
      let raf = 0, t0 = null;
      const dur = ms || 1150;
      const step = (t) => {
        if (t0 === null) t0 = t;
        const p = Math.min(1, (t - t0) / dur);
        setV(target * (1 - Math.pow(1 - p, 3)));   // easeOutCubic
        if (p < 1) raf = requestAnimationFrame(step);
      };
      raf = requestAnimationFrame(step);
      return () => cancelAnimationFrame(raf);
    }, [target, active, ms]);
    return v;
  }

  // Phone mockup. Deliberately device-accurate — bezel, island, status bar,
  // side buttons, home indicator — because a shop owner is being asked to point
  // customers at an app they have never seen, and a flat card doesn't read as
  // one. Comes alive on scroll: the shelf total counts up and the rows deal in.
  function PhoneMock() {
    const ref = useRef(null);
    const seen = useInView(ref, 0.28);
    const total = useCountUp(3418, seen, 1250);
    const spark = MOCK_TREND.map((n, i) =>
      (i / (MOCK_TREND.length - 1) * 100).toFixed(1) + "," + (30 - n / 82 * 26).toFixed(1)).join(" ");
    return (
      <div className="amb-phone-wrap" ref={ref} aria-hidden="true">
        <div className={"amb-phone" + (seen ? " is-live" : "")}>
          <span className="amb-ph-btn amb-ph-btn--silent" />
          <span className="amb-ph-btn amb-ph-btn--up" />
          <span className="amb-ph-btn amb-ph-btn--down" />
          <span className="amb-ph-btn amb-ph-btn--power" />
          <div className="amb-phone-screen">
            <div className="amb-ph-island" />
            <div className="amb-ph-status">
              <span className="amb-ph-time">9:41</span>
              <span className="amb-ph-icons">
                <svg className="amb-ph-ic" viewBox="0 0 17 11"><rect x="0" y="7.5" width="3" height="3.5" rx="1" /><rect x="4.6" y="5.4" width="3" height="5.6" rx="1" /><rect x="9.2" y="2.9" width="3" height="8.1" rx="1" /><rect x="13.8" y="0" width="3" height="11" rx="1" /></svg>
                <svg className="amb-ph-ic" viewBox="0 0 16 12"><path d="M1 4.2A11 11 0 0 1 15 4.2" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" /><path d="M3.7 7.1A7.1 7.1 0 0 1 12.3 7.1" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" /><circle cx="8" cy="10.4" r="1.4" /></svg>
                <svg className="amb-ph-ic amb-ph-ic--bat" viewBox="0 0 27 12"><rect x=".6" y=".6" width="22" height="10.8" rx="3.2" fill="none" stroke="currentColor" strokeWidth="1.1" opacity=".4" /><rect x="2.3" y="2.3" width="16.4" height="7.4" rx="1.9" /><path d="M24.6 4.3a2 2 0 0 1 0 3.4z" opacity=".4" /></svg>
              </span>
            </div>

            <div className="amb-ph-body">
              <div className="amb-app-top"><span className="amb-app-brand"><em>The</em> Lead-In</span></div>

              <div className="amb-app-total">
                <span className="amb-app-total-cap">Collection value</span>
                <span className="amb-app-total-num">
                  £{Math.round(total).toLocaleString("en-GB")}
                </span>
                <span className="amb-app-total-up">▲ £126 this month</span>
                <svg className="amb-app-spark" viewBox="0 0 100 32" preserveAspectRatio="none">
                  <polyline points={spark} fill="none" stroke="currentColor" strokeWidth="2"
                    strokeLinecap="round" strokeLinejoin="round" />
                </svg>
              </div>

              <div className="amb-app-secta">
                <span>Your shelf</span><span className="amb-app-count">104 records</span>
              </div>

              <div className="amb-app-list">
                {MOCK_SHELF.map((r) => (
                  <div className="amb-app-row" key={r.t}>
                    <img className="amb-app-sleeve" src={"/covers/" + r.slug + ".jpg"}
                      alt="" loading="lazy" width="32" height="32" />
                    <span className="amb-app-meta">
                      <span className="amb-app-t">{r.t}</span>
                      <span className="amb-app-a">{r.a}</span>
                    </span>
                    <span className="amb-app-v">{r.v}</span>
                  </div>
                ))}
              </div>
            </div>

            <div className="amb-ph-tabs">
              {MOCK_TABS.map((t, i) => (
                <span className={"amb-ph-tab" + (i === 0 ? " is-on" : "")} key={t.k}>
                  <svg viewBox="0 0 16 16" className="amb-ph-tab-ic"><path d={t.d} /></svg>
                  <span>{t.k}</span>
                </span>
              ))}
            </div>
            <div className="amb-ph-home" />
          </div>
          <span className="amb-ph-sheen" />
        </div>
      </div>
    );
  }

  // Partner-dashboard mockup for the kit section. Static art like the rest,
  // but its figures obey the page's own arithmetic — 41 subscribers × £2.495
  // is exactly the £102.30 shown — so a shop owner who checks the maths (the
  // exact person this page is for) finds it holds.
  function DashboardMock() {
    const ref = useRef(null);
    const seen = useInView(ref, 0.35);
    const scans = useCountUp(128, seen, 900);
    const subsN = useCountUp(41, seen, 1050);
    const fees = useCountUp(102.30, seen, 1200);
    const BARS = [22, 34, 30, 46, 58, 52, 72];
    return (
      <div className="amb-dash-art amb-scene" ref={ref} aria-hidden="true">
        <div className={"amb-dash" + (seen ? " is-live" : "")}>
          <div className="amb-dash-top">
            <span className="amb-dash-brand"><em>The</em> Lead-In · Partners</span>
            <span className="amb-dash-live"><span className="amb-dash-dot" />Live</span>
          </div>
          <div className="amb-dash-tiles">
            <div className="amb-dash-tile">
              <span className="amb-dash-n">{Math.round(scans)}</span>
              <span className="amb-dash-l">Scans</span>
            </div>
            <div className="amb-dash-tile">
              <span className="amb-dash-n">{Math.round(subsN)}</span>
              <span className="amb-dash-l">Subscribers</span>
            </div>
            <div className="amb-dash-tile amb-dash-tile--money">
              <span className="amb-dash-n">£{fees.toFixed(2)}</span>
              <span className="amb-dash-l">Earned this month</span>
            </div>
          </div>
          <div className="amb-dash-chart">
            {BARS.map((h, i) => (
              <span className="amb-dash-bar" key={i}
                style={{ "--h": h + "%", "--d": (i * 70) + "ms" }} />
            ))}
          </div>
        </div>
      </div>
    );
  }

  function Ambassadors() {
    const [form, setForm] = useState({
      shop_name: "", contact_name: "", email: "", city: "", website: "", vinyl_volume: "",
    });
    const [state, setState] = useState("idle"); // idle | saving | done | already | error
    const [msg, setMsg] = useState("");
    const [subs, setSubs] = useState(50); // referred subscribers, for the estimator
    const [moreOpen, setMoreOpen] = useState(false);   // optional form fields
    const [prefilled, setPrefilled] = useState(false); // arrived via a personalised email link
    const formStarted = useRef(false);
    const rootRef = useRef(null);

    // Personalised email links carry #p=<base64url {"e":email,"s":shop}> — the
    // FRAGMENT, deliberately: fragments never reach server logs or GA page
    // URLs, so the address isn't smeared across analytics. Every click on the
    // ambassador emails is someone we already know; making them retype their
    // own shop name into an empty form was the biggest hole in the funnel.
    useEffect(() => {
      try {
        const m = (location.hash || "").match(/[#&]p=([A-Za-z0-9_-]+)/);
        if (!m) return;
        const pad = "=".repeat((4 - (m[1].length % 4)) % 4);
        const d = JSON.parse(atob(m[1].replace(/-/g, "+").replace(/_/g, "/") + pad));
        const e = String(d.e || "").trim();
        const sName = String(d.s || "").trim();
        if (!e && !sName) return;
        setForm((f) => ({ ...f, email: e || f.email, shop_name: sName || f.shop_name }));
        setPrefilled(true);
        track("ambassador_view", { src: "email-prefill" });
        // The reader clicked "join" in an email — land them ON the form, not
        // back at the top of the pitch they've already read.
        setTimeout(() => {
          const el = document.getElementById("amb-join");
          if (el) el.scrollIntoView({ block: "start" });
        }, 60);
      } catch (err) { /* malformed fragment: behave like a normal visit */ }
    }, []);

    // First touch of any form field — separates "form abandoned" from "page
    // abandoned" in GA, which is the difference between fixing the form and
    // fixing the pitch.
    const onFormStart = () => {
      if (formStarted.current) return;
      formStarted.current = true;
      track("ambassador_form_start", { prefilled: prefilled ? "yes" : "no" });
    };
    // Sticky mobile CTA: on once the hero has scrolled away, off while the form
    // itself is on screen (pointing at something already visible is noise).
    const [pastHero, setPastHero] = useState(false);
    const [formOnScreen, setFormOnScreen] = useState(false);

    useEffect(() => { track("ambassador_view"); }, []);

    useEffect(() => {
      if (!("IntersectionObserver" in window) || !rootRef.current) return;
      const hero = rootRef.current.querySelector(".amb-hero");
      const form = rootRef.current.querySelector("#amb-join");
      if (!hero || !form) return;
      const ioHero = new IntersectionObserver(
        (en) => setPastHero(!en[0].isIntersecting), { threshold: 0 });
      const ioForm = new IntersectionObserver(
        (en) => setFormOnScreen(en[0].isIntersecting), { threshold: 0.15 });
      ioHero.observe(hero);
      ioForm.observe(form);
      return () => { ioHero.disconnect(); ioForm.disconnect(); };
    }, []);

    // Scroll reveal. Progressive enhancement only: the .amb-rise class starts
    // hidden ONLY once this effect has confirmed IntersectionObserver and motion
    // are both available (body flag), so a no-JS crawler or a reduced-motion
    // reader never gets content stuck at opacity 0.
    useEffect(() => {
      const reduce = window.matchMedia && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
      if (reduce || !("IntersectionObserver" in window) || !rootRef.current) return;
      const els = rootRef.current.querySelectorAll(".amb-rise");
      if (!els.length) return;
      rootRef.current.classList.add("amb-anim");
      const io = new IntersectionObserver((entries) => {
        entries.forEach((en) => {
          if (en.isIntersecting) { en.target.classList.add("is-in"); io.unobserve(en.target); }
        });
      }, { rootMargin: "0px 0px -8% 0px", threshold: 0.08 });
      els.forEach((el) => io.observe(el));
      return () => io.disconnect();
    }, []);

    const set = (k) => (e) => {
      setForm((f) => ({ ...f, [k]: e.target.value }));
      if (state === "error") { setState("idle"); setMsg(""); }
    };

    async function submit(e) {
      if (e && e.preventDefault) e.preventDefault();
      const shop = form.shop_name.trim();
      const contact = form.contact_name.trim();
      const email = form.email.trim();
      if (!shop) { setState("error"); setMsg("Please add your shop name."); return; }
      if (!email || !EMAIL_RE.test(email)) { setState("error"); setMsg("Please enter a valid email address."); return; }
      setState("saving");
      try {
        if (window.BBR_supabase) {
          const { error } = await window.BBR_supabase
            .from("ambassador_waitlist")
            .insert({
              shop_name: shop,
              contact_name: contact || "",
              email: email,
              city: form.city.trim() || null,
              website: form.website.trim() || null,
              vinyl_volume: form.vinyl_volume || null,
              source: "ambassadors",
            });
          if (error) {
            // Duplicate email (unique constraint) isn't a failure — the shop is
            // already on the list. Distinct confirmation, same as NewsletterSignup.
            if (/duplicate|unique/i.test(error.message || "")) {
              setState("already");
              track("ambassador_submit", { result: "already" });
              return;
            }
            throw error;
          }
        }
        setState("done");
        track("ambassador_submit", { result: "new" });
      } catch (err) {
        console.error("[BBR] ambassador signup failed", err);
        setState("error");
        setMsg("Something went wrong. Please try again, or email luca@thelead-in.com.");
      }
    }

    injectStyles();

    const monthly = subs * PER_SUB;
    const annual = monthly * 12;
    const done = state === "done" || state === "already";

    return (
      <main className="amb" ref={rootRef}>
        {/* ---- hero ---- */}
        <header className="amb-hero">
          <div className="amb-wrap amb-hero-in">
            <div className="amb-kicker">For independent record shops</div>
            <h1 className="amb-h1">Turn every record you sell into recurring revenue.</h1>
            {/* "Over one hundred" mirrors the nurture emails' SHOPS_JOINED claim
                (105 shops agreed by 12 Aug 2026, cold calls + waitlist) — the
                page a proof-led email lands on must repeat the proof. Update in
                lockstep with theleadin-nurture/nurture/sequence.py. */}
            <p className="amb-lede">
              The Lead-In Ambassador Programme lets independent shops earn a
              <strong> 50/50 share</strong> of the subscription revenue from customers they send our
              way — and we never compete with you, because we don't sell records.
              <strong> Over one hundred shops</strong> have already joined our mission.
            </p>
            <a className="amb-cta" href="#amb-join">Join the waitlist</a>
            <ul className="amb-trust">
              <li>Free for your customers to start</li>
              <li>No cost to your shop</li>
              <li>We print and post the kit</li>
            </ul>
          </div>
        </header>

        {/* ---- the mission band ----
            The emails that drive traffic here lead with "We're a startup.
            Record shops are the mission." — so the page has to say it back,
            in the same words, or the click reads as a bait-and-switch. Dark
            band on purpose: it visually echoes the email hero they came from. */}
        <section className="amb-mission amb-rise">
          <div className="amb-wrap">
            <div className="amb-mission-kicker">We're a startup. This is the mission.</div>
            <p className="amb-mission-line">
              Make independent record shops thrive, and bring vinyl collecting
              back into the mainstream — <em>a normal thing to be into, not a niche.</em>
            </p>
            <p className="amb-mission-sub">
              Small team, early days, no marketing budget. What we can offer is half
              of everything a shop's customers ever pay us.
            </p>
          </div>
        </section>

        {/* ---- why it works for shops ---- */}
        <section className="amb-wrap amb-section amb-rise">
          <h2 className="amb-h2">Why it works for you</h2>
          <div className="amb-cards">
            <div className="amb-card">
              <div className="amb-card-h">We don't compete with you</div>
              <p>The Lead-In tracks what a collection is <em>worth</em> — a valuation on every record,
                a value history for the whole shelf. We never sell vinyl. Pointing a customer to us
                takes nothing off your counter; it makes them a keener, higher-spending collector.</p>
            </div>
            <div className="amb-card">
              <div className="amb-card-h">The highest-intent audience there is</div>
              <p>Someone who just bought a record is the perfect person to hand a collection tool.
                A QR code by the till and a flyer in the bag reach them at exactly the right moment —
                and all it costs you is a corner of the counter.</p>
            </div>
            <div className="amb-card">
              <div className="amb-card-h">A revenue stream, not a favour</div>
              <p>When a customer you referred subscribes, you earn a 50/50 split of what they pay.
                Every shop gets its own code so referrals are tracked to you — build a base of
                subscribers and it compounds month after month.</p>
            </div>
          </div>
          {/* The objection every record shop raises first — a real prospect
              replied with exactly these three words on day one of the email
              campaign. Name it and answer it, or it answers itself. */}
          <div className="amb-note amb-note--objection">
            <strong>"Doesn't Discogs already do this?"</strong> Discogs can price a record —
            in fact it's one of the 50+ sources our valuations draw on, which is why ours
            are more accurate. But Discogs is a marketplace. Its business is selling records, often the very
            ones sitting in your racks, and it has never paid a shop a penny for a referral.
            We're the opposite bet: we sell nothing, we write about what makes records worth
            owning, and we split the revenue with the shop that sent the collector. A
            customer's Discogs library imports into The Lead-In in one tap, so you're not
            asking anyone to start over — you're pointing them somewhere that pays you.
          </div>
        </section>

        {/* ---- the kit, as mockup art ---- */}
        <section className="amb-wrap amb-section amb-rise">
          <h2 className="amb-h2">What lands in your shop</h2>
          <p className="amb-p amb-p--wide">
            The print is posted to you, free, carrying your shop's own code — and behind it
            sits a partner dashboard showing you everything that code is doing.
          </p>
          <div className="amb-kit">
            {/* counter card, with a record leaning behind it */}
            <figure className="amb-kit-item">
              <div className="amb-card-art amb-scene" aria-hidden="true">
                <div className="amb-vinyl">
                  <span className="amb-vinyl-label" />
                </div>
                <div className="amb-card-art-in">
                  <div className="amb-cc-band"><em>The</em> Lead-In</div>
                  <div className="amb-cc-covers">
                    {["rumours", "unknown-pleasures", "kind-of-blue"].map((s, i) => (
                      <img key={s} src={"/covers/" + s + ".jpg"} alt="" loading="lazy"
                        width="44" height="44" style={{ "--i": i }} />
                    ))}
                  </div>
                  <div className="amb-cc-kicker">What's your<br />collection worth?</div>
                  <QrArt />
                  <div className="amb-cc-foot">
                    <span className="amb-cc-cta">Scan to find out — free</span>
                    <span className="amb-cc-code">SHOP CODE · RT-042</span>
                  </div>
                </div>
              </div>
              <figcaption>
                <strong>Counter card</strong>
                A small standing card for beside the till, so browsers can scan while they wait.
              </figcaption>
            </figure>

            {/* bag flyer */}
            <figure className="amb-kit-item">
              <div className="amb-flyer-art amb-scene" aria-hidden="true">
                <div className="amb-flyer amb-flyer--back">
                  <div className="amb-fl-brand"><em>The</em> Lead-In</div>
                  <div className="amb-fl-lines">
                    <span /><span /><span className="short" />
                  </div>
                </div>
                <div className="amb-flyer amb-flyer--front">
                  <span className="amb-fl-chip">Free</span>
                  <div className="amb-fl-covers">
                    {["dark-side-of-the-moon", "abbey-road", "nevermind"].map((s) => (
                      <img key={s} src={"/covers/" + s + ".jpg"} alt="" loading="lazy"
                        width="52" height="52" />
                    ))}
                  </div>
                  <div className="amb-fl-brand"><em>The</em> Lead-In</div>
                  <div className="amb-fl-head">You just bought a record.<br />Find out what it's worth.</div>
                  <div className="amb-fl-qr"><QrArt /></div>
                  <div className="amb-fl-foot">thelead-in.com</div>
                </div>
              </div>
              <figcaption>
                <strong>Bag flyers</strong>
                Slipped in with a purchase — it reaches the customer at home, sleeve still in hand.
              </figcaption>
            </figure>

            {/* partner dashboard */}
            <figure className="amb-kit-item">
              <DashboardMock />
              <figcaption>
                <strong>Partner dashboard</strong>
                Real-time metrics and total oversight — who scanned, which customers subscribed,
                and the fees you're earning, updated as it happens.
              </figcaption>
            </figure>
          </div>
          <p className="amb-kit-note">Artwork shown is an illustration — the final kit is designed with you.</p>
        </section>

        {/* ---- what the site actually is ----
            Deliberately NOT first. A shop owner arriving from the email wants
            to know what they get and what it costs; the product explainer
            before that made them read about us to reach their own offer. It
            sits here as backup for the reader already sold on the idea. */}
        <section className="amb-wrap amb-section amb-rise">
          <div className="amb-what">
            <div className="amb-what-copy">
              <h2 className="amb-h2">And what are you sending them to?</h2>
              <p className="amb-p">
                It's where record collectors find out what their vinyl is actually worth.
                A collector adds the records they own, and each one comes back with a market
                valuation drawn from <strong>50+ sources</strong> — the most accurate tracker
                on the market — priced to the specific pressing and its condition. The whole
                shelf gets a running total and a value history they can watch move.
              </p>
              <p className="amb-p">
                Around that sits the writing: the hundred greatest albums ranked and defended
                in full essays, plus pressing guides on which edition is the one to own. Reading
                it is free, and so is tracking a collection.
              </p>
              <p className="amb-p amb-p--punch">
                The part that matters to you: <strong>we never sell records.</strong> We tell people
                what theirs are worth — fuel for the lifelong, gloriously incurable
                addiction that is collecting.
              </p>
            </div>

            {/* App mockup — illustrates the product a shop is pointing people at */}
            <PhoneMock />
          </div>
        </section>

        {/* ---- how it works ---- */}
        <section className="amb-wrap amb-section amb-rise">
          <h2 className="amb-h2">How it works</h2>
          <ol className="amb-steps">
            <li>
              <span className="amb-step-n">1</span>
              <div>
                <div className="amb-step-h">We send you the kit</div>
                <p>Counter QR codes and flyers to drop into customers' bags — printed and posted to you,
                  each carrying your shop's unique referral code.</p>
              </div>
            </li>
            <li>
              <span className="amb-step-n">2</span>
              <div>
                <div className="amb-step-h">Your customers sign up</div>
                <p>They scan, add the records they own, and see what their collection is worth.
                  Free to start — the code keeps them tied to your shop.</p>
              </div>
            </li>
            <li>
              <span className="amb-step-n">3</span>
              <div>
                <div className="amb-step-h">You earn the split — and watch it live</div>
                <p>When a referred collector takes out a subscription, you get 50% of the revenue.
                  We handle billing and payouts, and your partner dashboard shows the whole
                  picture in real time: scans, subscribers, and what you've earned.</p>
              </div>
            </li>
          </ol>
        </section>

        {/* ---- revenue estimator ---- */}
        <section className="amb-wrap amb-section amb-rise">
          <h2 className="amb-h2">What could it be worth?</h2>
          <p className="amb-calc-intro">
            The subscription is planned at <strong>{gbp(SUB_PRICE, 2)} a month</strong>, and you keep
            half of it — around <strong>{gbp(PER_SUB, 2)}</strong> per subscriber, every month they stay.
            Drag to see what it adds up to.
          </p>
          <div className="amb-calc">
            <div className="amb-calc-slider">
              <label className="amb-calc-label" htmlFor="amb-subs">
                Collectors you refer who subscribe
              </label>
              <input
                id="amb-subs"
                className="amb-range"
                type="range"
                min="1" max="500" step="1"
                value={subs}
                onChange={(e) => setSubs(parseInt(e.target.value, 10) || 0)}
                aria-valuetext={subs + " subscribers"}
                style={{ "--amb-fill": ((subs - 1) / 499 * 100) + "%" }}
              />
              <div className="amb-calc-count"><strong>{subs.toLocaleString("en-GB")}</strong> subscribers</div>
            </div>
            <div className="amb-calc-out">
              <div className="amb-calc-fig">
                <span className="amb-calc-num">{gbp(monthly, 2)}</span>
                <span className="amb-calc-cap">to you each month</span>
              </div>
              <div className="amb-calc-fig amb-calc-fig--year">
                <span className="amb-calc-num">{gbp(annual, 0)}</span>
                <span className="amb-calc-cap">over a year, if they stay</span>
              </div>
            </div>
          </div>
          <p className="amb-calc-foot">
            An illustration, not a forecast — you decide how many of your customers take it up.
            Because it's a subscription, it recurs every month a collector stays with us.
          </p>
          {/* The calculator is the peak-motivation moment on the page — the
              reader has just put their own number in and seen what it's worth.
              Making them scroll to act on it was leaving the conversion on the
              table. */}
          <div className="amb-calc-cta">
            <a className="amb-cta" href="#amb-join"
               onClick={() => track("ambassador_cta", { placement: "calculator" })}>
              Claim your shop's place
            </a>
          </div>
        </section>

        {/* ---- founding-partner honesty ---- */}
        <section className="amb-wrap amb-section amb-rise">
          <div className="amb-note">
            <strong>Being honest about where we are.</strong> We're a startup, and the
            subscription tier is still being built — joining the waitlist today won't put
            money in the till tomorrow. What it does get you: your kit first, your code in
            customers' hands before anyone else's, and a real say in how the programme
            works — where the card sits, what the flyer says, how and when you get paid.
            You know your counter better than we ever will.
          </div>
        </section>

        {/* ---- the form ---- */}
        <section className="amb-wrap amb-section amb-rise" id="amb-join">
          <h2 className="amb-h2">Join the waitlist</h2>
          <p className="amb-p amb-p--wide">
            Two fields, ten seconds, no commitment — and your shop is first in line when
            the kit ships. Over one hundred shops have already joined the mission; kits
            go out in the order shops join.
          </p>
          {done ? (
            <div className="amb-done">
              <span className="amb-tick">✓</span>
              <div>
                <div className="amb-done-h">{state === "already" ? "You're already on the list" : "You're on the list"}</div>
                <p>
                  {state === "already"
                    ? "This shop is already registered — we've got your details and we'll be in touch."
                    : "Thanks for registering your shop. We'll be in touch as the programme rolls out."}
                </p>
              </div>
            </div>
          ) : (
            <form className="amb-form" onSubmit={submit} noValidate onFocusCapture={onFormStart}>
              {prefilled && (
                <div className="amb-prefill">
                  ✓ We've filled this in from your email — check it's right and hit the button.
                </div>
              )}
              <div className="amb-row">
                <label className="amb-field">
                  <span className="amb-label">Shop name <em>*</em></span>
                  <input className="amb-input" type="text" value={form.shop_name} onChange={set("shop_name")}
                    placeholder="e.g. Rough Trade" autoComplete="organization" required />
                </label>
                <label className="amb-field">
                  <span className="amb-label">Email <em>*</em></span>
                  <input className="amb-input" type="email" inputMode="email" value={form.email} onChange={set("email")}
                    placeholder="you@yourshop.com" autoComplete="email" required />
                </label>
              </div>
              {/* Everything non-essential lives behind one line. Six visible
                  fields on a cold click reads as work; two reads as ten
                  seconds. The details can follow once they're on the list. */}
              {!moreOpen ? (
                <button type="button" className="amb-more"
                  onClick={() => { setMoreOpen(true); track("ambassador_form_more"); }}>
                  + Add details — your name, city, socials (optional)
                </button>
              ) : (
                <>
                  <div className="amb-row">
                    <label className="amb-field">
                      <span className="amb-label">Your name</span>
                      <input className="amb-input" type="text" value={form.contact_name} onChange={set("contact_name")}
                        placeholder="Who we'll be talking to" autoComplete="name" />
                    </label>
                    <label className="amb-field">
                      <span className="amb-label">City or postcode</span>
                      <input className="amb-input" type="text" value={form.city} onChange={set("city")}
                        placeholder="Where you're based" />
                    </label>
                  </div>
                  <div className="amb-row">
                    <label className="amb-field">
                      <span className="amb-label">Website or Instagram</span>
                      <input className="amb-input" type="text" value={form.website} onChange={set("website")}
                        placeholder="A link or @handle" />
                    </label>
                    <label className="amb-field">
                      <span className="amb-label">Roughly how much vinyl do you sell?</span>
                      <select className="amb-input amb-select" value={form.vinyl_volume} onChange={set("vinyl_volume")}>
                        <option value="">Prefer not to say</option>
                        {VOLUME_BANDS.map((b) => <option key={b} value={b}>{b}</option>)}
                      </select>
                    </label>
                  </div>
                </>
              )}
              {state === "error" && <div className="amb-err">{msg}</div>}
              <div className="amb-actions">
                <button className="amb-submit" type="submit" disabled={state === "saving"}>
                  {state === "saving" ? "Sending…" : "Register my shop"}
                </button>
                <span className="amb-foot">No commitment. We'll only use this to talk to you about the programme.</span>
              </div>
            </form>
          )}
        </section>

        {/* Sticky mobile CTA — email traffic is overwhelmingly phones, and on a
            long page the ask must never be more than a thumb away. Hidden while
            the form is on screen, and gone for good once they've registered. */}
        {pastHero && !formOnScreen && !done && (
          <div className="amb-sticky">
            <span className="amb-sticky-txt"><strong>50/50</strong> on every collector you send us</span>
            <a className="amb-sticky-btn" href="#amb-join"
               onClick={() => track("ambassador_cta", { placement: "sticky" })}>
              Join the waitlist
            </a>
          </div>
        )}
      </main>
    );
  }

  // ---- styles (injected once) ------------------------------------------------
  // Uses the site's :root tokens so the page reads as part of The Lead-In in
  // both the print/editorial palette and any theme override.
  function injectStyles() {
    if (document.getElementById("amb-styles")) return;
    const s = document.createElement("style");
    s.id = "amb-styles";
    s.textContent = `
      .amb{color:var(--ink);}
      .amb-wrap{max-width:1000px;margin:0 auto;padding:0 24px;}
      .amb-p{font-family:var(--body-serif);font-size:16.5px;line-height:1.62;color:var(--ink-2);margin:0 0 15px;}
      .amb-p--wide{max-width:62ch;margin-bottom:30px;}
      .amb-p--punch{margin-top:20px;padding-top:16px;border-top:1px solid var(--rule);color:var(--ink);}

      /* hero.
         The top nav is position:fixed and taller than the --nav-h token claims
         (65px measured against a 50px token on mobile), so a plain padding-top
         put the kicker underneath it. Clear the token AND a generous gap. */
      .amb-hero{background:var(--paper-2);border-bottom:1px solid var(--rule);
        padding:calc(var(--nav-h,50px) + 82px) 0 66px;text-align:center;
        position:relative;overflow:hidden;}
      .amb-hero::after{content:"";position:absolute;left:50%;top:-40%;width:760px;height:760px;
        transform:translateX(-50%);pointer-events:none;
        background:radial-gradient(circle,oklch(0.62 0.19 28 / .07) 0%,transparent 62%);}
      .amb-hero-in{position:relative;}
      .amb-kicker{font:700 12px/1 var(--sans);letter-spacing:.16em;text-transform:uppercase;
        color:var(--accent);margin-bottom:18px;}
      .amb-h1{font-family:var(--serif);font-weight:400;font-size:clamp(34px,5.2vw,56px);
        line-height:1.04;letter-spacing:-.01em;margin:0 auto 18px;max-width:16ch;}
      .amb-lede{font-family:var(--body-serif);font-size:clamp(17px,2.1vw,21px);line-height:1.55;
        color:var(--ink-2);margin:0 auto 30px;max-width:52ch;}
      .amb-lede strong{color:var(--ink);}
      .amb-cta{display:inline-block;background:var(--accent);color:#fff;text-decoration:none;
        font:600 15px/1 var(--sans);padding:15px 26px;border-radius:8px;
        box-shadow:0 6px 18px oklch(0.62 0.19 28 / .28);
        transition:transform .14s ease,box-shadow .14s ease,opacity .14s ease;}
      .amb-cta:hover{opacity:.95;transform:translateY(-2px);box-shadow:0 10px 24px oklch(0.62 0.19 28 / .34);}
      .amb-trust{list-style:none;margin:26px 0 0;padding:0;display:flex;justify-content:center;
        flex-wrap:wrap;gap:10px 26px;}
      .amb-trust li{font:600 12.5px/1 var(--sans);color:var(--ink-mute);letter-spacing:.02em;
        display:flex;align-items:center;gap:8px;
        animation:ambFadeUp .55s cubic-bezier(.2,.8,.3,1) both;}
      .amb-trust li:nth-child(1){animation-delay:.24s;}
      .amb-trust li:nth-child(2){animation-delay:.34s;}
      .amb-trust li:nth-child(3){animation-delay:.44s;}
      .amb-trust li::before{content:"✓";color:var(--accent);font-weight:700;}
      .amb-hero .amb-kicker{animation:ambFadeUp .55s cubic-bezier(.2,.8,.3,1) both;}
      .amb-hero .amb-h1{animation:ambFadeUp .6s cubic-bezier(.2,.8,.3,1) .07s both;}
      .amb-hero .amb-lede{animation:ambFadeUp .6s cubic-bezier(.2,.8,.3,1) .14s both;}
      .amb-hero .amb-cta{animation:ambFadeUp .6s cubic-bezier(.2,.8,.3,1) .2s both;}
      @keyframes ambFadeUp{from{opacity:0;transform:translateY(12px)}to{opacity:1;transform:none}}

      /* padding-top/bottom, NOT the padding shorthand. Every section carries
         both .amb-wrap and .amb-section; the shorthand here has equal
         specificity and comes later, so it was resetting .amb-wrap's
         "padding:0 24px" side gutters to zero and running the copy hard into
         both screen edges on mobile. */
      /* mission band — dark like the email hero the reader just left */
      .amb-mission{background:var(--ink);background-image:linear-gradient(152deg,#2a1e12 0%,var(--ink) 54%,#0e0b07 100%);
        text-align:center;padding:44px 0 46px;}
      .amb-mission-kicker{font:800 11px/1 var(--sans);letter-spacing:.18em;text-transform:uppercase;
        color:oklch(0.75 0.13 40);margin-bottom:14px;}
      .amb-mission-line{font-family:var(--serif);font-weight:400;font-size:clamp(21px,3vw,30px);
        line-height:1.3;color:#fff;margin:0 auto;max-width:34ch;}
      .amb-mission-line em{font-style:italic;color:oklch(0.75 0.13 40);}
      .amb-mission-sub{font-family:var(--body-serif);font-size:15px;line-height:1.6;
        color:#d8cfc2;margin:14px auto 0;max-width:52ch;}

      /* calculator CTA */
      .amb-calc-cta{margin-top:26px;}

      /* sticky mobile CTA */
      .amb-sticky{display:none;}
      @media (max-width:720px){
        .amb-sticky{position:fixed;left:0;right:0;bottom:0;z-index:90;
          display:flex;align-items:center;justify-content:space-between;gap:12px;
          padding:12px 16px calc(12px + env(safe-area-inset-bottom,0px));
          background:#fffdf8;border-top:1px solid var(--rule);
          box-shadow:0 -8px 24px rgba(23,19,15,.14);
          animation:ambFadeUp .3s cubic-bezier(.2,.8,.3,1) both;}
        .amb-sticky-txt{font:400 13px/1.3 var(--sans);color:var(--ink-2);}
        .amb-sticky-txt strong{color:var(--accent);font-weight:800;}
        .amb-sticky-btn{flex:0 0 auto;background:var(--accent);color:#fff;text-decoration:none;
          font:700 14px/1 var(--sans);padding:13px 18px;border-radius:8px;}
      }

      .amb-section{padding-top:56px;padding-bottom:56px;border-bottom:1px solid var(--rule);}
      .amb-section:last-of-type{border-bottom:0;}
      .amb-h2{position:relative;font-family:var(--serif);font-weight:400;
        font-size:clamp(25px,3.2vw,34px);line-height:1.1;margin:0 0 24px;padding-top:16px;}
      .amb-h2::before{content:"";position:absolute;top:0;left:0;width:46px;height:3px;
        border-radius:2px;background:var(--accent);transform-origin:left center;}
      .amb-anim .amb-rise .amb-h2::before{transform:scaleX(0);transition:transform .6s cubic-bezier(.2,.8,.3,1) .12s;}
      .amb-anim .amb-rise.is-in .amb-h2::before{transform:scaleX(1);}

      /* scroll reveal — only armed once JS confirms motion is wanted */
      .amb-anim .amb-rise{opacity:0;transform:translateY(18px);
        transition:opacity .6s cubic-bezier(.2,.7,.3,1),transform .6s cubic-bezier(.2,.7,.3,1);}
      .amb-anim .amb-rise.is-in{opacity:1;transform:none;}

      /* what is The Lead-In + phone */
      .amb-what{display:grid;grid-template-columns:1.02fr .98fr;gap:48px;align-items:center;}
      .amb-phone-wrap{display:flex;justify-content:center;perspective:1400px;}

      /* device */
      .amb-phone{position:relative;width:292px;padding:11px;border-radius:47px;
        background:linear-gradient(155deg,#4a423a 0%,#1d1814 26%,#0d0b09 62%,#39322b 100%);
        box-shadow:0 34px 74px rgba(23,19,15,.36),0 6px 16px rgba(23,19,15,.20),
                   inset 0 1px 0 rgba(255,255,255,.14);
        transform:rotateY(-8deg) rotateX(3deg) translateZ(0);
        transition:transform .7s cubic-bezier(.2,.8,.3,1);}
      .amb-phone.is-live{transform:rotateY(0deg) rotateX(0deg);}
      .amb-phone:hover{transform:rotateY(0deg) rotateX(0deg) translateY(-6px);}
      .amb-ph-btn{position:absolute;background:linear-gradient(90deg,#221d18,#4f463d);border-radius:3px;}
      .amb-ph-btn--silent{left:-2px;top:104px;width:3px;height:24px;}
      .amb-ph-btn--up{left:-2px;top:142px;width:3px;height:44px;}
      .amb-ph-btn--down{left:-2px;top:196px;width:3px;height:44px;}
      .amb-ph-btn--power{right:-2px;top:158px;width:3px;height:64px;}
      .amb-phone-screen{position:relative;background:var(--paper);border-radius:37px;
        overflow:hidden;min-height:534px;display:flex;flex-direction:column;}
      .amb-ph-island{position:absolute;top:10px;left:50%;transform:translateX(-50%);
        width:68px;height:24px;border-radius:13px;background:#0b0908;z-index:4;}
      /* Status row has to clear the island on both sides — the icons were
         running under its right edge at the previous width/padding. */
      .amb-ph-status{display:flex;align-items:center;justify-content:space-between;
        padding:15px 17px 0;height:44px;position:relative;z-index:3;}
      .amb-ph-time{font:700 12.5px/1 var(--sans);color:var(--ink);letter-spacing:.01em;}
      .amb-ph-icons{display:flex;align-items:center;gap:5px;color:var(--ink);}
      .amb-ph-ic{height:10.5px;width:auto;display:block;fill:currentColor;}
      .amb-ph-ic--bat{height:11.5px;}
      .amb-ph-home{position:absolute;bottom:7px;left:50%;transform:translateX(-50%);
        width:112px;height:4px;border-radius:3px;background:var(--ink);opacity:.26;z-index:3;}
      /* one-pass glass sheen when the device settles into view */
      .amb-ph-sheen{position:absolute;inset:0;border-radius:47px;overflow:hidden;pointer-events:none;}
      .amb-ph-sheen::after{content:"";position:absolute;top:-60%;left:-75%;width:55%;height:220%;
        transform:rotate(17deg);opacity:0;
        background:linear-gradient(90deg,transparent,rgba(255,255,255,.20),transparent);}
      .amb-phone.is-live .amb-ph-sheen::after{animation:ambSheen 1.5s cubic-bezier(.35,.1,.3,1) .45s 1 both;}
      @keyframes ambSheen{0%{left:-75%;opacity:0}12%{opacity:1}88%{opacity:1}100%{left:135%;opacity:0}}

      /* app UI inside the screen */
      .amb-ph-body{flex:1 1 auto;padding:8px 15px 0;}
      .amb-app-top{text-align:center;margin-bottom:13px;}
      .amb-app-brand{font-family:var(--serif);font-size:15px;color:var(--ink);}
      .amb-app-brand em{font-style:italic;color:var(--accent);}
      .amb-app-total{position:relative;background:var(--paper-2);border:1px solid var(--rule);
        border-radius:12px;padding:13px 14px 10px;margin-bottom:14px;
        display:flex;flex-direction:column;gap:3px;overflow:hidden;}
      .amb-app-total-cap{font:600 9.5px/1 var(--sans);letter-spacing:.1em;text-transform:uppercase;color:var(--ink-mute);}
      .amb-app-total-num{font-family:var(--serif);font-size:33px;line-height:1;color:var(--ink);
        font-variant-numeric:tabular-nums;}
      .amb-app-total-up{font:600 10.5px/1 var(--sans);color:oklch(0.52 0.13 150);}
      .amb-app-spark{position:absolute;right:0;bottom:0;width:62%;height:38px;
        color:var(--accent);opacity:.32;}
      .amb-phone.is-live .amb-app-spark polyline{
        stroke-dasharray:190;stroke-dashoffset:190;animation:ambDraw 1.5s cubic-bezier(.3,.7,.3,1) .35s both;}
      @keyframes ambDraw{to{stroke-dashoffset:0}}
      .amb-app-secta{display:flex;align-items:baseline;justify-content:space-between;margin-bottom:9px;
        font:700 10px/1 var(--sans);letter-spacing:.09em;text-transform:uppercase;color:var(--ink-mute);}
      .amb-app-count{font-weight:600;letter-spacing:.02em;text-transform:none;font-size:10px;}
      .amb-app-list{display:flex;flex-direction:column;gap:9px;}
      .amb-app-row{display:flex;align-items:center;gap:10px;}
      .amb-phone.is-live .amb-app-row{animation:ambRowIn .52s cubic-bezier(.2,.8,.3,1) both;}
      .amb-phone.is-live .amb-app-row:nth-child(1){animation-delay:.42s;}
      .amb-phone.is-live .amb-app-row:nth-child(2){animation-delay:.52s;}
      .amb-phone.is-live .amb-app-row:nth-child(3){animation-delay:.62s;}
      .amb-phone.is-live .amb-app-row:nth-child(4){animation-delay:.72s;}
      .amb-phone.is-live .amb-app-row:nth-child(5){animation-delay:.82s;}
      .amb-phone.is-live .amb-app-row:nth-child(6){animation-delay:.92s;}
      @keyframes ambRowIn{from{opacity:0;transform:translateY(9px)}to{opacity:1;transform:none}}
      .amb-app-sleeve{flex:0 0 auto;width:32px;height:32px;border-radius:3px;display:block;
        object-fit:cover;background:var(--rule);
        box-shadow:inset 0 0 0 1px rgba(23,19,15,.14),0 1px 3px rgba(23,19,15,.16);}
      .amb-app-meta{flex:1 1 auto;min-width:0;display:flex;flex-direction:column;}
      .amb-app-t{font:600 11.5px/1.25 var(--sans);color:var(--ink);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
      .amb-app-a{font:400 10px/1.25 var(--sans);color:var(--ink-mute);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
      .amb-app-v{flex:0 0 auto;font:700 12px/1 var(--sans);color:var(--accent);font-variant-numeric:tabular-nums;}
      /* tab bar — sits on the screen floor above the home indicator */
      .amb-ph-tabs{margin-top:auto;display:grid;grid-template-columns:repeat(4,1fr);
        align-items:center;padding:9px 6px 15px;border-top:1px solid var(--rule);
        background:var(--paper-2);}
      .amb-ph-tab{display:flex;flex-direction:column;align-items:center;gap:4px;
        font:600 8.5px/1 var(--sans);letter-spacing:.02em;color:var(--ink-mute);}
      .amb-ph-tab-ic{width:15px;height:15px;fill:currentColor;display:block;}
      .amb-ph-tab.is-on{color:var(--accent);}

      /* cards */
      .amb-cards{display:grid;grid-template-columns:repeat(3,1fr);gap:22px;}
      .amb-card{background:var(--paper-2);border:1px solid var(--rule);border-radius:12px;padding:22px 20px;
        transition:transform .16s ease,box-shadow .16s ease;}
      .amb-card:hover{transform:translateY(-3px);box-shadow:0 12px 26px rgba(23,19,15,.10);}
      .amb-card-h{font:700 15px/1.3 var(--sans);margin-bottom:10px;color:var(--ink);}
      .amb-card p{font-family:var(--body-serif);font-size:15px;line-height:1.55;color:var(--ink-2);margin:0;}

      /* the kit mockups */
      .amb-kit{display:grid;grid-template-columns:repeat(3,1fr);gap:26px;}
      /* shared scene: warm light from the top corner plus faint record grooves,
         so the frames read as a styled still life rather than flat swatches */
      .amb-scene{position:relative;overflow:hidden;min-height:280px;
        background:
          radial-gradient(circle at 82% 118%, rgba(23,19,15,.045) 0 3px, transparent 3px 7px,
            rgba(23,19,15,.045) 7px 8px, transparent 8px 14px, rgba(23,19,15,.04) 14px 15px,
            transparent 15px 23px, rgba(23,19,15,.035) 23px 24px, transparent 24px 34px,
            rgba(23,19,15,.03) 34px 35px, transparent 35px 47px, rgba(23,19,15,.03) 47px 48px,
            transparent 48px),
          linear-gradient(148deg, #f4ecdb 0%, var(--paper-2) 46%, #e4dac4 100%);}
      /* a record leaning out from behind the counter card */
      .amb-vinyl{position:absolute;top:22px;right:-52px;width:150px;height:150px;border-radius:50%;
        background:
          radial-gradient(circle, #221d18 0 26%, transparent 26%),
          repeating-radial-gradient(circle, #17130f 0 2.5px, #2c2620 2.5px 4px);
        box-shadow:-8px 10px 24px rgba(23,19,15,.32);}
      .amb-vinyl-label{position:absolute;inset:0;margin:auto;width:44px;height:44px;border-radius:50%;
        background:var(--accent);box-shadow:inset 0 0 0 2px rgba(255,253,248,.25);}
      .amb-vinyl-label::after{content:"";position:absolute;inset:0;margin:auto;width:7px;height:7px;
        border-radius:50%;background:#fffdf8;}
      .amb-anim .amb-rise.is-in .amb-vinyl{animation:ambSpin 26s linear infinite;}
      @keyframes ambSpin{to{transform:rotate(360deg)}}
      .amb-kit-item{margin:0;}
      .amb-kit-item figcaption{margin-top:18px;font-family:var(--body-serif);font-size:15px;
        line-height:1.55;color:var(--ink-2);}
      .amb-kit-item figcaption strong{display:block;font-family:var(--sans);font-weight:700;
        font-size:14px;color:var(--ink);margin-bottom:3px;}
      .amb-qr{width:100%;height:auto;display:block;color:var(--ink);}
      .amb-qr-mark{font-family:var(--serif);font-size:13px;fill:var(--accent);}

      /* counter card art */
      .amb-card-art{border:1px solid var(--rule);border-radius:12px;
        padding:30px 24px;display:flex;justify-content:center;align-items:center;}
      .amb-card-art-in{position:relative;z-index:1;width:196px;background:#fffdf8;
        border:1px solid var(--rule);border-radius:9px;overflow:hidden;
        padding:0 15px 13px;text-align:center;
        box-shadow:0 14px 30px rgba(23,19,15,.20);transform:rotate(-1.6deg);
        transition:transform .25s cubic-bezier(.2,.8,.3,1);}
      .amb-cc-band{margin:0 -15px 10px;padding:8px 0;background:var(--accent);
        font-family:var(--serif);font-size:12.5px;color:#fff;letter-spacing:.01em;}
      .amb-cc-band em{font-style:italic;opacity:.85;}
      /* fanned trio of real covers — the card sells the product, so show it */
      .amb-cc-covers{display:flex;justify-content:center;height:48px;margin-bottom:9px;}
      .amb-cc-covers img{width:44px;height:44px;border-radius:4px;object-fit:cover;
        border:2px solid #fffdf8;box-shadow:0 3px 8px rgba(23,19,15,.28);
        transform:rotate(calc((var(--i) - 1) * 9deg)) translateY(calc((var(--i) - 1) * (var(--i) - 1) * 3px));
        margin:0 -7px;position:relative;z-index:calc(2 - (var(--i) - 1) * (var(--i) - 1));}
      .amb-cc-kicker br{display:block;}
      /* reveal: the card straightens up as it enters */
      .amb-anim .amb-rise.is-in .amb-card-art-in{animation:ambCardPop .8s cubic-bezier(.2,.8,.3,1) .1s backwards;}
      @keyframes ambCardPop{from{transform:rotate(5deg) translateY(14px);opacity:0}
        to{transform:rotate(-1.6deg) translateY(0);opacity:1}}
      .amb-card-art:hover .amb-card-art-in{transform:rotate(0deg) translateY(-4px);}
      .amb-cc-kicker{font-family:var(--serif);font-size:16px;line-height:1.15;color:var(--ink);margin-bottom:11px;}
      .amb-cc-foot{margin-top:11px;display:flex;flex-direction:column;gap:5px;}
      .amb-cc-cta{font:600 10.5px/1.25 var(--sans);color:var(--ink-2);}
      .amb-cc-code{font:700 8.5px/1 var(--mono,var(--sans));letter-spacing:.09em;color:var(--accent);}

      /* flyer art */
      .amb-flyer-art{border:1px solid var(--rule);border-radius:12px;
        padding:30px 24px;position:relative;display:flex;justify-content:center;align-items:center;}
      .amb-fl-chip{position:absolute;top:-9px;right:-11px;background:var(--accent);color:#fff;
        font:800 9.5px/1 var(--sans);letter-spacing:.1em;text-transform:uppercase;
        padding:6px 10px;border-radius:999px;transform:rotate(6deg);
        box-shadow:0 4px 10px rgba(207,72,39,.4);}
      .amb-fl-covers{display:flex;justify-content:center;gap:4px;margin:2px 0 9px;}
      .amb-fl-covers img{width:42px;height:42px;border-radius:3px;object-fit:cover;
        border:1px solid var(--rule);box-shadow:0 2px 5px rgba(23,19,15,.18);}
      /* reveal: the pair fans out from a single stack */
      .amb-anim .amb-rise.is-in .amb-flyer--front{animation:ambFanF .85s cubic-bezier(.2,.8,.3,1) .15s backwards;}
      .amb-anim .amb-rise.is-in .amb-flyer--back{animation:ambFanB .85s cubic-bezier(.2,.8,.3,1) .15s backwards;}
      @keyframes ambFanF{from{transform:translateX(-16%) rotate(-3deg);opacity:0}
        to{transform:translateX(9%) rotate(3deg);opacity:1}}
      @keyframes ambFanB{from{transform:translateX(-50%) rotate(0deg);opacity:0}
        to{transform:translateX(-72%) rotate(-7deg);opacity:.85}}
      .amb-flyer{width:168px;background:#fffdf8;border:1px solid var(--rule);border-radius:6px;
        padding:15px 14px;box-shadow:0 14px 30px rgba(23,19,15,.16);
        transition:transform .25s cubic-bezier(.2,.8,.3,1);}
      .amb-flyer--back{position:absolute;top:38px;left:50%;
        transform:translateX(-72%) rotate(-7deg);opacity:.85;}
      .amb-flyer--front{position:relative;transform:translateX(9%) rotate(3deg);text-align:center;}
      .amb-flyer-art:hover .amb-flyer--front{transform:translateX(9%) rotate(0deg) translateY(-4px);}
      .amb-flyer-art:hover .amb-flyer--back{transform:translateX(-78%) rotate(-10deg);}
      .amb-fl-brand{font-family:var(--serif);font-size:12px;color:var(--ink);margin-bottom:9px;}
      .amb-fl-brand em{font-style:italic;color:var(--accent);}
      .amb-fl-head{font-family:var(--serif);font-size:13.5px;line-height:1.25;color:var(--ink);margin-bottom:11px;}
      .amb-fl-qr{width:86px;margin:0 auto 10px;}
      .amb-fl-foot{font:600 9px/1 var(--sans);letter-spacing:.05em;color:var(--ink-mute);text-transform:uppercase;}
      .amb-fl-lines{display:flex;flex-direction:column;gap:6px;margin-top:4px;}
      .amb-fl-lines span{height:5px;border-radius:3px;background:var(--rule);}
      .amb-fl-lines span.short{width:58%;}
      .amb-kit-note{margin:22px 0 0;font:400 13px/1.5 var(--sans);color:var(--ink-mute);font-style:italic;}

      /* partner dashboard art */
      .amb-dash-art{border:1px solid var(--rule);border-radius:12px;
        padding:26px 20px;display:flex;justify-content:center;align-items:center;}
      .amb-dash{position:relative;z-index:1;width:100%;max-width:250px;background:#211b15;
        border-radius:12px;padding:14px 14px 16px;
        box-shadow:0 16px 34px rgba(23,19,15,.30);
        transform:rotate(1.4deg);transition:transform .25s cubic-bezier(.2,.8,.3,1);}
      .amb-dash-art:hover .amb-dash{transform:rotate(0deg) translateY(-4px);}
      .amb-dash-top{display:flex;align-items:center;justify-content:space-between;margin-bottom:12px;}
      .amb-dash-brand{font-family:var(--serif);font-size:11.5px;color:#f3ede1;}
      .amb-dash-brand em{font-style:italic;color:oklch(0.75 0.13 40);}
      .amb-dash-live{display:flex;align-items:center;gap:5px;font:800 8.5px/1 var(--sans);
        letter-spacing:.12em;text-transform:uppercase;color:#5fcf8a;}
      .amb-dash-dot{width:6px;height:6px;border-radius:50%;background:#5fcf8a;}
      .amb-dash.is-live .amb-dash-dot{animation:ambPulse 1.6s ease-in-out infinite;}
      @keyframes ambPulse{0%,100%{opacity:1}50%{opacity:.3}}
      .amb-dash-tiles{display:grid;grid-template-columns:1fr 1fr;gap:7px;margin-bottom:10px;}
      .amb-dash-tile{background:rgba(255,253,248,.06);border:1px solid rgba(255,253,248,.10);
        border-radius:8px;padding:9px 10px;display:flex;flex-direction:column;gap:2px;}
      .amb-dash-tile--money{grid-column:1 / -1;}
      .amb-dash-tile--money .amb-dash-n{color:oklch(0.75 0.13 40);}
      .amb-dash-n{font-family:var(--serif);font-size:21px;line-height:1;color:#fffdf8;
        font-variant-numeric:tabular-nums;}
      .amb-dash-l{font:600 8.5px/1.2 var(--sans);letter-spacing:.08em;text-transform:uppercase;
        color:#a89e8c;}
      .amb-dash-chart{display:flex;align-items:flex-end;gap:5px;height:44px;padding:0 2px;}
      .amb-dash-bar{flex:1;height:var(--h);border-radius:3px 3px 0 0;
        background:linear-gradient(180deg,oklch(0.68 0.17 32),oklch(0.55 0.16 30));}
      .amb-dash.is-live .amb-dash-bar{transform-origin:bottom;
        animation:ambBarUp .7s cubic-bezier(.2,.8,.3,1) var(--d) both;}
      @keyframes ambBarUp{from{transform:scaleY(0)}to{transform:scaleY(1)}}

      /* steps */
      .amb-steps{list-style:none;margin:0;padding:0;display:grid;gap:22px;}
      .amb-steps li{display:flex;gap:18px;align-items:flex-start;}
      .amb-step-n{flex:0 0 auto;width:38px;height:38px;border-radius:50%;background:var(--accent);color:#fff;
        display:flex;align-items:center;justify-content:center;font:700 17px/1 var(--sans);}
      .amb-step-h{font:700 16px/1.3 var(--sans);margin-bottom:4px;}
      .amb-steps p{font-family:var(--body-serif);font-size:15.5px;line-height:1.55;color:var(--ink-2);margin:0;max-width:60ch;}

      /* calculator */
      .amb-calc-intro{font-family:var(--body-serif);font-size:16.5px;line-height:1.6;color:var(--ink-2);
        max-width:60ch;margin:0 0 26px;}
      .amb-calc-intro strong{color:var(--ink);}
      .amb-calc{display:grid;grid-template-columns:1.15fr 1fr;gap:28px;align-items:center;
        background:var(--paper-2);border:1px solid var(--rule);border-radius:14px;padding:28px 26px;}
      .amb-calc-label{display:block;font:600 13px/1.3 var(--sans);color:var(--ink-2);margin-bottom:16px;}
      .amb-range{-webkit-appearance:none;appearance:none;width:100%;height:6px;border-radius:6px;
        background:linear-gradient(var(--accent),var(--accent)) no-repeat,var(--rule);
        background-size:var(--amb-fill,10%) 100%;cursor:pointer;outline:none;}
      .amb-range::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:24px;height:24px;
        border-radius:50%;background:var(--accent);border:3px solid #fffdf8;
        box-shadow:0 2px 6px rgba(23,19,15,.25);cursor:pointer;}
      .amb-range::-moz-range-thumb{width:22px;height:22px;border-radius:50%;background:var(--accent);
        border:3px solid #fffdf8;box-shadow:0 2px 6px rgba(23,19,15,.25);cursor:pointer;}
      .amb-range:focus-visible{box-shadow:0 0 0 3px oklch(0.62 0.19 28 / .22);}
      .amb-calc-count{margin-top:14px;font-family:var(--body-serif);font-size:15px;color:var(--ink-2);}
      .amb-calc-count strong{font-family:var(--sans);font-weight:700;color:var(--ink);font-size:17px;}
      .amb-calc-out{display:flex;flex-direction:column;gap:16px;}
      .amb-calc-fig{display:flex;flex-direction:column;gap:2px;}
      .amb-calc-num{font-family:var(--serif);font-weight:400;font-size:clamp(30px,4.6vw,42px);
        line-height:1;color:var(--accent);letter-spacing:-.01em;}
      .amb-calc-fig--year .amb-calc-num{color:var(--ink);font-size:clamp(24px,3.6vw,32px);}
      .amb-calc-cap{font:600 12px/1.2 var(--sans);letter-spacing:.02em;color:var(--ink-mute);
        text-transform:uppercase;}
      .amb-calc-foot{font-family:var(--body-serif);font-size:14px;line-height:1.55;color:var(--ink-mute);
        max-width:60ch;margin:18px 0 0;font-style:italic;}

      .amb-note{background:var(--paper-2);border:1px solid var(--rule);border-left:3px solid var(--accent);
        border-radius:8px;padding:20px 22px;font-family:var(--body-serif);font-size:16px;line-height:1.6;
        color:var(--ink-2);}
      .amb-note strong{color:var(--ink);}
      .amb-note--objection{margin-top:26px;}

      /* form */
      .amb-form{max-width:760px;}
      .amb-row{display:grid;grid-template-columns:1fr 1fr;gap:18px;margin-bottom:18px;}
      .amb-field{display:flex;flex-direction:column;gap:7px;}
      .amb-label{font:600 13px/1.2 var(--sans);color:var(--ink-2);}
      .amb-label em{color:var(--accent);font-style:normal;}
      .amb-input{font:400 15px/1.3 var(--sans);color:var(--ink);background:#fffdf8;
        border:1px solid var(--rule);border-radius:8px;padding:12px 13px;width:100%;
        transition:border-color .12s ease,box-shadow .12s ease;}
      .amb-input:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px oklch(0.62 0.19 28 / .16);}
      .amb-select{appearance:auto;cursor:pointer;}
      .amb-err{color:var(--accent);font:600 14px/1.4 var(--sans);margin:2px 0 16px;}
      .amb-prefill{margin:0 0 16px;padding:11px 14px;background:oklch(0.62 0.19 28 / .08);
        border:1px solid oklch(0.62 0.19 28 / .25);border-radius:8px;
        font:600 13.5px/1.4 var(--sans);color:var(--ink-2);}
      .amb-more{display:block;background:none;border:0;padding:0;margin:-4px 0 18px;
        font:600 13.5px/1.4 var(--sans);color:var(--ink-mute);cursor:pointer;
        text-decoration:underline;text-underline-offset:3px;text-align:left;}
      .amb-more:hover{color:var(--ink);}
      .amb-actions{display:flex;align-items:center;gap:18px;flex-wrap:wrap;margin-top:6px;}
      .amb-submit{background:var(--accent);color:#fff;border:0;font:600 15px/1 var(--sans);
        padding:15px 28px;border-radius:8px;cursor:pointer;transition:opacity .12s ease,transform .12s ease;}
      .amb-submit:hover:not(:disabled){opacity:.92;transform:translateY(-1px);}
      .amb-submit:disabled{opacity:.6;cursor:default;}
      .amb-foot{font:400 13px/1.4 var(--sans);color:var(--ink-mute);max-width:40ch;}
      .amb-done{display:flex;gap:16px;align-items:flex-start;background:var(--paper-2);
        border:1px solid var(--rule);border-radius:12px;padding:24px 22px;max-width:620px;}
      .amb-tick{flex:0 0 auto;width:34px;height:34px;border-radius:50%;background:var(--accent);color:#fff;
        display:flex;align-items:center;justify-content:center;font:700 18px/1 var(--sans);}
      .amb-done-h{font:700 17px/1.3 var(--sans);margin-bottom:6px;}
      .amb-done p{font-family:var(--body-serif);font-size:15.5px;line-height:1.55;color:var(--ink-2);margin:0;}

      @media (max-width:860px){
        .amb-what{grid-template-columns:1fr;gap:38px;}
        .amb-kit{grid-template-columns:1fr;gap:30px;}
        .amb-phone{transform:none;}
        .amb-phone.is-live,.amb-phone:hover{transform:none;}
      }
      @media (max-width:720px){
        .amb-hero{padding:calc(var(--nav-h,50px) + 58px) 0 48px;}
        .amb-cards{grid-template-columns:1fr;}
        .amb-row{grid-template-columns:1fr;}
        .amb-calc{grid-template-columns:1fr;gap:24px;}
        .amb-trust{gap:9px 18px;}
        .amb-section{padding-top:46px;padding-bottom:46px;}
        .amb-wrap{padding-left:20px;padding-right:20px;}
      }
      @media (max-width:400px){
        .amb-phone{width:268px;}
        .amb-phone-screen{min-height:500px;}
      }
      @media (prefers-reduced-motion:reduce){
        .amb-cta,.amb-submit,.amb-card,.amb-card-art-in,.amb-flyer,.amb-phone{transition:none;}
        .amb-anim .amb-rise{opacity:1;transform:none;transition:none;}
        .amb-anim .amb-rise .amb-h2::before,
        .amb-anim .amb-rise.is-in .amb-h2::before{transform:scaleX(1);transition:none;}
        .amb-hero .amb-kicker,.amb-hero .amb-h1,.amb-hero .amb-lede,.amb-hero .amb-cta,
        .amb-trust li,.amb-phone.is-live .amb-app-row,.amb-sticky{animation:none;opacity:1;transform:none;}
        .amb-phone.is-live .amb-ph-sheen::after{animation:none;opacity:0;}
        .amb-phone.is-live .amb-app-spark polyline{animation:none;stroke-dashoffset:0;}
        .amb-anim .amb-rise.is-in .amb-vinyl{animation:none;}
        .amb-dash.is-live .amb-dash-dot{animation:none;}
        .amb-dash.is-live .amb-dash-bar{animation:none;transform:scaleY(1);}
        .amb-dash{transition:none;}
        .amb-anim .amb-rise.is-in .amb-card-art-in,
        .amb-anim .amb-rise.is-in .amb-flyer--front,
        .amb-anim .amb-rise.is-in .amb-flyer--back{animation:none;}
        .amb-phone,.amb-phone.is-live,.amb-phone:hover{transform:none;}
      }
    `;
    document.head.appendChild(s);
  }

  window.Ambassadors = Ambassadors;
})();
