// Direction D, "Editorial × Modern"
// Merge: D's structure (sticky blurred nav, asymmetric grids, micro-interactions)
// + C's editorial drama (gradient hero, scroll-snap journey, full-bleed billboards).
// Alternating light/dark sections. Poppins display + Figtree body (brand fonts).

const { useState: useStateD, useRef: useRefD } = React;

// ─── Proposal export helpers ─────────────────────────────────────────
// Builds a print-ready HTML proposal page with the dealer's plan, savings vs
// each competitor, and a clean breakdown, meant to be forwarded internally as
// proof. Opens in a new window with the print dialog auto-triggered.
const buildProposalHTML = ({
  persona, region, brokers, managers, offices, brands,
  easySign, vato, api, web, liveSessions,
  yLines, ywMonthly, compTotals, fmt, accent = "#6941C6", accentLight = "#6941C6",
  logoDataUrl = "",
  dealerName = "", dealerEmail = ""
}) => {
  const date = new Date().toLocaleDateString("en-US", { year: "numeric", month: "long", day: "numeric" });
  const personaLabel = persona === "dealer" ? (offices > 0 ? "Multi-office dealer" : "Dealer") : persona === "shipyard" ? "Shipyard" : "Broker";
  const cur = region === "us" ? "USD" : "EUR";

  // Headline savings, sum of all priced competitor monthlies vs YachtWay,
  // matching the dashboard. The PDF only receives competitors the user
  // explicitly priced, so this is a clean apples-to-apples figure.
  const priced = compTotals.filter((c) => !c.unknown && c.k !== "ywy");
  const sumCompMonthly = priced.reduce((s, c) => s + (c.monthly || 0), 0);
  const maxDeltaRow = priced.reduce((best, c) => {
    const d = c.monthly - ywMonthly;
    return d > (best ? best.monthly - ywMonthly : 0) ? c : best;
  }, null);
  const annualSavings = (sumCompMonthly - ywMonthly) * 12;
  const annualYW = ywMonthly * 12;
  const annualComp = sumCompMonthly * 12;
  const savingsPct = annualComp > 0 ? Math.round(annualSavings / annualComp * 100) : 0;

  const visibleLines = yLines.filter((l) => !(l.optional && !l.on));

  const compRows = compTotals.map((c) => {
    const isYw = c.k === "ywy";
    if (c.unknown && !isYw) {
      return `<tr>
        <td style="padding:14px 16px;border-bottom:1px solid #e5e5e5;font-weight:600;color:#222;">${c.name}</td>
        <td style="padding:14px 16px;border-bottom:1px solid #e5e5e5;color:#999;text-align:right;font-style:italic;">Not public</td>
        <td style="padding:14px 16px;border-bottom:1px solid #e5e5e5;color:#999;text-align:right;">-</td>
      </tr>`;
    }
    const delta = c.monthly - ywMonthly;
    return `<tr style="${isYw ? `background:${accent}12;` : ""}">
      <td style="padding:14px 16px;border-bottom:1px solid #e5e5e5;font-weight:${isYw ? 800 : 600};color:${isYw ? accent : "#111"};font-size:14px;">
        ${c.name}${isYw ? ` <span style="display:inline-block;font-size:10px;background:${accent};color:#fff;padding:3px 10px;border-radius:99px;margin-left:8px;letter-spacing:.1em;font-weight:800;vertical-align:middle;">YOU</span>` : ""}
      </td>
      <td style="padding:14px 16px;border-bottom:1px solid #e5e5e5;text-align:right;font-weight:800;font-variant-numeric:tabular-nums;font-size:15px;color:${isYw ? accent : "#111"};">${fmt(c.monthly)}</td>
      <td style="padding:14px 16px;border-bottom:1px solid #e5e5e5;text-align:right;font-weight:800;font-size:13px;color:${isYw ? accent : delta > 0 ? "#0a7a3b" : "#b32424"};">
        ${isYw ?
    "Your plan" :
    delta > 0 ?
    `<span style="display:inline-block;background:#0a7a3b;color:#fff;padding:4px 10px;border-radius:6px;font-size:12px;letter-spacing:.02em;">Save ${fmt(delta)}/mo</span>` :
    delta < 0 ?
    `<span style="display:inline-block;background:${accent}15;color:${accent};padding:4px 10px;border-radius:6px;font-size:12px;letter-spacing:.02em;font-weight:600;">+${fmt(Math.abs(delta))}/mo on YachtWay, for far more services</span>` :
    `<span style="color:#888;font-weight:600;">Same price</span>`}
      </td>
    </tr>`;
  }).join("");

  const lineRows = visibleLines.map((l, i) => `
    <tr style="${i % 2 ? "background:#fafafa;" : ""}">
      <td style="padding:12px 16px;border-bottom:1px solid #eee;color:#222;font-size:14px;">${l.label}</td>
      <td style="padding:12px 16px;border-bottom:1px solid #eee;text-align:right;font-weight:700;font-variant-numeric:tabular-nums;font-size:14px;color:${l.free ? accent : "#111"};">${l.free ? "Free" : l.amount > 0 ? fmt(l.amount) : "-"}</td>
    </tr>
  `).join("");

  const setupSummary = [
  `${brokers} broker${brokers === 1 ? "" : "s"}`,
  `${managers} manager${managers === 1 ? "" : "s"}`,
  persona === "dealer" ? `${offices} office${offices === 1 ? "" : "s"}` : null,
  persona === "shipyard" ? `${brands} brand${brands === 1 ? "" : "s"}` : null,
  easySign ? "EasySign" : null,
  vato ? "VATo" : null,
  web ? "Website" : null,
  api ? "API" : null,
  liveSessions ? `${liveSessions} LIVE sessions/mo` : null].
  filter(Boolean).join(" · ");

  // Build the list of platforms to compare side-by-side: YachtWay first, then
  // every competitor in the user's region (filters out the YW row from compTotals).
  const compsForGrid = compTotals.filter((c) => c.k !== "ywy");
  const COMP_REGION_LABEL = { ywld: "Global", msrc: "United States", ychr: "United States", rbt: "Europe", ytco: "United States" };
  const COMP_BLURB = {
    ywld: "Global listings platform (incl. Boats.com, BoatTrader).",
    msrc: "United States listings platform.",
    ychr: "United States focused listings platform (IYBA-tied).",
    rbt: "European listings platform (UK / EU focus).",
    ytco: "United States focused B2B MLS platform." };
  const platforms = [
  { k: "yw", name: "YachtWay", isYw: true, region: "Global", blurb: "Global yacht marketplace, listings free for all dealers, brokerages, and shipyards." },
  ...compsForGrid.map((c) => ({ k: c.k, name: c.name, isYw: false, region: COMP_REGION_LABEL[c.k] || "Global", blurb: COMP_BLURB[c.k] }))];

  const compNameForFeatures = maxDeltaRow ? maxDeltaRow.name : "Legacy platforms";
  // Per-competitor support map (mirrors the on-page comparison table data)
  const COMP_SUPPORT = {
    ywld: { listing: false, seat: false, inv: false, live: false, fin: false, ins: false, sign: true, vmp: true, content: false, site: true, tour3d: false, social: true, ref: false, tour: false, events: false, range: false, ai: false, api: true, vat: false, fx: false, press: false, multi: false, gdpr: false, soc2: false },
    msrc: { listing: false, seat: false, inv: false, live: false, fin: false, ins: false, sign: false, vmp: false, content: false, site: false, tour3d: false, social: false, ref: false, tour: false, events: false, range: false, ai: true, api: false, vat: false, fx: false, press: false, multi: false, gdpr: false, soc2: false },
    ychr: { listing: false, seat: false, inv: false, live: false, fin: false, ins: false, sign: true, vmp: false, content: false, site: false, tour3d: false, social: false, ref: false, tour: false, events: false, range: false, ai: false, api: true, vat: false, fx: false, press: false, multi: false, gdpr: false, soc2: false },
    rbt: { listing: false, seat: false, inv: false, live: false, fin: false, ins: false, sign: false, vmp: false, content: false, site: false, tour3d: false, social: false, ref: false, tour: false, events: false, range: false, ai: false, api: true, vat: false, fx: false, press: false, multi: false, gdpr: false, soc2: false },
    ytco: { listing: false, seat: false, inv: false, live: false, fin: false, ins: false, sign: false, vmp: false, content: false, site: true, tour3d: false, social: false, ref: false, tour: false, events: false, range: false, ai: false, api: true, vat: false, fx: false, press: false, multi: false, gdpr: false, soc2: false }
  };
  // YachtWay supports everything by definition.
  const supportsYes = Object.fromEntries(
    Object.keys(COMP_SUPPORT.ywld).map((k) => [k, true])
  );
  const FEATURES = [
  { f: "Free to list (no listing fees)", k: "listing" },
  { f: "Unlimited inventory", k: "inv" },
  { f: "Live streaming to buyers (YachtWay LIVE)", k: "live" },
  { f: "Built-in buyer financing", k: "fin" },
  { f: "Built-in insurance", k: "ins" },
  { f: "Digital contracts (EasySign)", k: "sign" },
  { f: "VATO, Vessel Valuation Tool", k: "vmp" },
  { f: "Content production", k: "content" },
  { f: "Dealer site + inventory sync", k: "site" },
  { f: "3D tour support", k: "tour3d" },
  { f: "Cross-platform social reach", k: "social" },
  { f: "Dealer earns referral income", k: "ref" },
  { f: "Schedule a tour", k: "tour" },
  { f: "Events", k: "events" },
  { f: "Range calculator", k: "range" },
  { f: "AI-assisted buyer chat", k: "ai" },
  { f: "API feed out", k: "api" },
  { f: "GDPR compliant", k: "gdpr" },
  { f: "SOC 2 audited", k: "soc2" },
  { f: "Multi-office / multi-brand support", k: "multi" }];


  // Helper: render a single ✓ /, cell
  const cellMark = (yes, isYwCol) => {
    if (yes) {
      const bg = isYwCol ? accent : "#9ca3af";
      return `<span style="display:inline-block;width:20px;height:20px;line-height:20px;border-radius:50%;background:${bg};color:#fff;font-weight:800;font-size:11px;">✓</span>`;
    }
    return `<span style="color:#d4d4d4;font-size:16px;font-weight:700;">-</span>`;
  };

  const featureRows = FEATURES.map((row, i) => {
    const cells = platforms.map((p) => {
      const support = p.isYw ? supportsYes : COMP_SUPPORT[p.k] || {};
      const yes = !!support[row.k];
      const bg = p.isYw ? `background:${accent}10;` : "";
      return `<td style="padding:10px 8px;border-bottom:1px solid #eee;text-align:center;${bg}">${cellMark(yes, p.isYw)}</td>`;
    }).join("");
    return `<tr style="${i % 2 ? "background:#fafafa;" : ""}">
      <td style="padding:10px 14px;border-bottom:1px solid #eee;color:#111;font-size:12px;font-weight:500;">${row.f}</td>
      ${cells}
    </tr>`;
  }).join("");

  // Header row for the comparison table, one column per platform
  const featureHeaderCells = platforms.map((p) => {
    const bg = p.isYw ? `background:${accent}18;color:${accent};` : "background:#f0f0f0;color:#0a0a0a;";
    return `<th style="text-align:center;padding:12px 6px;font-size:10px;font-weight:800;letter-spacing:.06em;text-transform:uppercase;border-bottom:2px solid #0a0a0a;${bg}">${p.name}</th>`;
  }).join("");

  // Per-platform yes-counts for the summary card row
  const summaryCells = platforms.map((p) => {
    const support = p.isYw ? supportsYes : COMP_SUPPORT[p.k] || {};
    const n = FEATURES.filter((r) => support[r.k]).length;
    const isYw = p.isYw;
    return `<div style="background:${isYw ? accent + "12" : "#fafafa"};border:1px solid ${isYw ? accent + "40" : "#e5e5e5"};border-radius:10px;padding:14px 10px;text-align:center;">
      <div style="font-size:22px;font-weight:900;color:${isYw ? accent : "#666"};letter-spacing:-0.015em;line-height:1;">${n}<span style="font-size:14px;opacity:.6;">/${FEATURES.length}</span></div>
      <div style="font-size:10px;color:${isYw ? accent : "#666"};text-transform:uppercase;letter-spacing:.08em;font-weight:700;margin-top:6px;">${p.name}</div>
    </div>`;
  }).join("");
  const ywYesCount = FEATURES.length;

  // Reach metrics, same data as the public-facing page
  const REACH = [
  { label: "Visits per listing", yw: "4.07", ctx: "9.3× more attention than the closest peer." },
  { label: "Social audience", yw: "2,180,000", ctx: "6× larger than the next platform on the market." },
  { label: "Instagram followers", yw: "472K+", ctx: "Most followed listing platform on Instagram." },
  { label: "YouTube subscribers", yw: "500K", ctx: "The only yacht platform with an active long-form video channel." },
  { label: "Monthly content reach", yw: "20M+", ctx: "Owned audience across IG, YouTube, FB, and TikTok." },
  { label: "Domain authority", yw: "27", ctx: "Matches Yachtr with 123× fewer backlinks. No spam." },
  { label: "Referring domains", yw: "470", ctx: "All-organic backlink profile." },
  { label: "Countries live", yw: "47", ctx: "EU · US · UAE · APAC." },
  { label: "Active dealers", yw: "450+", ctx: "Across 4 continents." },
  { label: "Languages supported", yw: "6", ctx: "Listings auto-translated for cross-border buyers." }];

  const reachRows = REACH.map((r, i) => `
    <tr style="${i % 2 ? "background:#fafafa;" : ""}">
      <td style="padding:13px 16px;border-bottom:1px solid #eee;color:#111;font-weight:600;font-size:13px;">${r.label}</td>
      <td style="padding:13px 16px;border-bottom:1px solid #eee;color:${accent};font-weight:800;font-variant-numeric:tabular-nums;font-size:18px;letter-spacing:-0.01em;">${r.yw}</td>
      <td style="padding:13px 16px;border-bottom:1px solid #eee;color:#666;font-size:12px;line-height:1.45;">${r.ctx}</td>
    </tr>
  `).join("");

  const logoBlock = logoDataUrl ?
  `<img src="${logoDataUrl}" alt="YachtWay" style="height:19px;width:auto;display:block;margin:0 auto;"/>` :
  `<div style="font-family:Georgia,serif;font-weight:800;font-size:15px;letter-spacing:-0.02em;color:#111;text-align:center;">YachtWay</div>`;

  return `<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<title>YachtWay Pricing Proposal, ${date}</title>
<style>
  @page { margin: 14mm 12mm; size: A4; }
  * { box-sizing: border-box; }
  body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    color:#0a0a0a; margin:0; padding:32px; max-width: ${platforms.length >= 4 ? 1100 : 920}px; margin: 0 auto; line-height: 1.5; -webkit-print-color-adjust: exact; print-color-adjust: exact; }
  h1 { font-size: 38px; font-weight: 900; letter-spacing: -0.025em; margin: 0 0 6px; line-height: 1.05; }
  h2 { font-size: 12px; font-weight: 800; letter-spacing: .14em; margin: 24px 0 12px;
    text-transform: uppercase; color:#0a0a0a; padding-bottom: 8px; border-bottom: 3px solid #0a0a0a; }
  table { width: 100%; border-collapse: collapse; }
  th { font-size: 11px; text-transform: uppercase; letter-spacing: .1em; color:#0a0a0a; font-weight:800;
    padding: 12px 16px; text-align: left; background:#f0f0f0; border-bottom: 2px solid #0a0a0a; }

  /* Header strip with centered logo */
  .header { text-align: center; padding: 12px 0 24px; border-bottom: 4px solid #0a0a0a; margin-bottom: 28px; }
  .header .logo-wrap { margin-bottom: 14px; }
  .header .doc-label { font-size: 10px; font-weight: 800; letter-spacing: .2em; color: ${accent}; text-transform: uppercase; }
  .header .doc-meta { font-size: 11px; color: #666; margin-top: 6px; letter-spacing: .04em; }

  /* Hero, annual savings front and center */
  .hero { background: linear-gradient(135deg, ${accent} 0%, #0a0a0a 100%); color:#fff;
    padding: 36px 32px; border-radius: 18px; margin-bottom: 28px; box-shadow: 0 8px 32px ${accent}30; }
  .hero .sub { font-size: 11px; opacity: .92; text-transform: uppercase; letter-spacing: .18em; margin-bottom: 10px; font-weight: 800; }
  .hero h1 { color: #fff; font-size: 32px; margin-bottom: 16px; }
  .hero .annual-num { font-size: 64px; font-weight: 900; letter-spacing: -0.035em; line-height: 1; margin: 8px 0 12px; }
  .hero .annual-num .small { font-size: 22px; font-weight: 700; opacity: .85; }
  .hero .ctx { font-size: 14px; opacity: .94; max-width: 600px; line-height: 1.5; }
  .hero .ctx strong { font-weight: 800; }
  .hero .grid { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; margin-top: 28px;
    padding-top: 24px; border-top: 1px solid rgba(255,255,255,.3); }
  .hero .grid .lbl { font-size: 10px; opacity: .85; text-transform: uppercase; letter-spacing: .14em; margin-bottom: 6px; font-weight: 800; }
  .hero .grid .val { font-size: 26px; font-weight: 900; letter-spacing: -0.015em; line-height: 1; }
  .hero .grid .small { font-size: 11px; opacity: .85; margin-top: 4px; }
  .hero .pct-pill { display: inline-block; background: rgba(255,255,255,.18); padding: 6px 14px;
    border-radius: 99px; font-size: 12px; font-weight: 800; letter-spacing: .04em; margin-top: 14px; }

  /* Configuration strip */
  .config-strip { background: #fafafa; border-left: 4px solid ${accent}; border-radius: 6px;
    padding: 16px 22px; margin-bottom: 28px; font-size: 13px; color: #222; }
  .config-strip .lbl { font-size: 10px; font-weight: 800; color: #888; text-transform: uppercase; letter-spacing: .14em; margin-bottom: 4px; }
  .config-strip .val { font-weight: 600; }

  .total-row td { font-size: 16px !important; font-weight: 900 !important; padding: 16px !important;
    border-top: 3px solid #0a0a0a !important; border-bottom: none !important; background: #0a0a0a !important; color: #fff !important; }
  .total-row td:first-child { color: #fff !important; }
  /* Savings cell, white for max legibility on the black total-row
     background. Keep the row visually anchored by its weight + bg. */
  .total-row td.savings-cell { color: #fff !important; }

  .summary-grid { display: grid; grid-template-columns: repeat(${platforms.length}, 1fr); gap: 8px; margin: 16px 0 8px; }

  .footnote { font-size: 11px; color: #888; margin-top: 12px; line-height: 1.5; }
  .footer { margin-top: 48px; padding-top: 22px; border-top: 2px solid #0a0a0a;
    font-size: 11px; color: #555; line-height: 1.6; text-align: center; }
  .footer strong { color: #0a0a0a; }

  .page-break { page-break-before: always; }
  /* Allow tables to break across pages -- let content flow naturally to fill */
  /* the page rather than skipping huge gaps. Only individual ROWS stay together. */
  tr { page-break-inside: avoid; break-inside: avoid; }
  thead { display: table-header-group; }
  h2 { page-break-after: avoid; break-after: avoid; }
  .keep-together { page-break-inside: avoid; break-inside: avoid; }
  @media print { body { padding: 0; } .no-print { display: none !important; } }
</style>
</head>
<body>
  <div class="no-print" style="display:flex;justify-content:flex-end;gap:10px;margin-bottom:18px;">
    <button id="yw-share-btn" type="button" style="padding:11px 22px;background:#fff;color:#0a0a0a;border:1.5px solid #0a0a0a;border-radius:8px;font-weight:800;cursor:pointer;font-size:13px;letter-spacing:.04em;text-transform:uppercase;display:inline-flex;align-items:center;gap:8px;">
      <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
        <circle cx="18" cy="5" r="3"></circle>
        <circle cx="6" cy="12" r="3"></circle>
        <circle cx="18" cy="19" r="3"></circle>
        <line x1="8.59" y1="13.51" x2="15.42" y2="17.49"></line>
        <line x1="15.41" y1="6.51" x2="8.59" y2="10.49"></line>
      </svg>
      Share
    </button>
    <button onclick="window.print()" style="padding:11px 22px;background:${accent};color:#fff;border:none;border-radius:8px;font-weight:800;cursor:pointer;font-size:13px;letter-spacing:.04em;text-transform:uppercase;box-shadow:0 4px 12px ${accent}40;">Print / Save as PDF</button>
  </div>

  <!-- SHARE MODAL, lets the dealer email this proposal to colleagues.
       Captures the recipient emails for our records. -->
  <div id="yw-share-modal" class="no-print" style="display:none;position:fixed;inset:0;z-index:9999;background:rgba(10,10,10,.65);align-items:center;justify-content:center;padding:24px;">
    <div style="background:#fff;border-radius:18px;max-width:520px;width:100%;padding:32px;box-shadow:0 24px 60px rgba(0,0,0,.35);position:relative;">
      <button id="yw-share-close" type="button" aria-label="Close" style="position:absolute;top:14px;right:14px;width:32px;height:32px;border-radius:50%;border:none;background:#f0f0f0;cursor:pointer;font-size:18px;line-height:1;color:#444;">×</button>
      <div style="font-size:11px;font-weight:800;color:${accent};text-transform:uppercase;letter-spacing:.16em;margin-bottom:8px;">Share this proposal</div>
      <h3 style="font-size:24px;font-weight:900;letter-spacing:-0.02em;margin:0 0 8px;color:#0a0a0a;">Send to your team.</h3>
      <p style="font-size:14px;color:#555;line-height:1.5;margin:0 0 22px;">Add the people who need to see this ,  partners, finance, whoever signs the checks. We will email each of them a copy.</p>

      <form id="yw-share-form">
        <label style="display:block;font-size:11px;font-weight:800;color:#0a0a0a;text-transform:uppercase;letter-spacing:.12em;margin-bottom:8px;">Recipient emails</label>
        <textarea id="yw-share-emails" placeholder="alice@dealer.com, bob@dealer.com" rows="3" required style="width:100%;border:1.5px solid #d4d4d4;border-radius:10px;padding:12px 14px;font-size:14px;font-family:inherit;color:#0a0a0a;resize:vertical;line-height:1.5;outline:none;transition:border-color .15s;box-sizing:border-box;"></textarea>
        <div style="font-size:12px;color:#888;margin-top:6px;line-height:1.4;">Separate multiple addresses with commas, semicolons, spaces, or new lines.</div>

        <label style="display:block;font-size:11px;font-weight:800;color:#0a0a0a;text-transform:uppercase;letter-spacing:.12em;margin:18px 0 8px;">Your name <span style="color:#888;font-weight:600;text-transform:none;letter-spacing:0;">(so they know it is from you)</span></label>
        <input id="yw-share-from" type="text" value="${(dealerName || '').replace(/"/g, '&quot;')}" placeholder="Your name" required style="width:100%;border:1.5px solid #d4d4d4;border-radius:10px;padding:12px 14px;font-size:14px;font-family:inherit;color:#0a0a0a;outline:none;transition:border-color .15s;box-sizing:border-box;">

        <label style="display:block;font-size:11px;font-weight:800;color:#0a0a0a;text-transform:uppercase;letter-spacing:.12em;margin:18px 0 8px;">Message <span style="color:#888;font-weight:600;text-transform:none;letter-spacing:0;">(optional)</span></label>
        <textarea id="yw-share-msg" rows="3" style="width:100%;border:1.5px solid #d4d4d4;border-radius:10px;padding:12px 14px;font-size:14px;font-family:inherit;color:#0a0a0a;resize:vertical;line-height:1.5;outline:none;transition:border-color .15s;box-sizing:border-box;">${annualSavings > 0 ? `Take a look, based on our current setup, it looks like we would save ${fmt(annualSavings)} a year by moving to YachtWay. Worth a discussion.` : `Take a look at this YachtWay proposal, wanted to get your take before we move forward.`}</textarea>

        <div id="yw-share-error" style="display:none;font-size:13px;color:#b32424;margin-top:14px;font-weight:600;"></div>

        <div style="display:flex;gap:10px;margin-top:24px;">
          <button type="button" id="yw-share-cancel" style="flex:0 0 auto;padding:14px 22px;background:#fff;color:#0a0a0a;border:1.5px solid #d4d4d4;border-radius:10px;font-weight:700;cursor:pointer;font-size:14px;">Cancel</button>
          <button type="submit" id="yw-share-submit" style="flex:1;padding:14px 22px;background:${accent};color:#fff;border:none;border-radius:10px;font-weight:800;cursor:pointer;font-size:14px;letter-spacing:.02em;box-shadow:0 4px 12px ${accent}40;">Send proposal</button>
        </div>
      </form>

      <div id="yw-share-success" style="display:none;text-align:center;padding:12px 0;">
        <div style="width:56px;height:56px;border-radius:50%;background:${accent};color:#fff;display:flex;align-items:center;justify-content:center;margin:0 auto 16px;font-size:28px;font-weight:900;">&#10003;</div>
        <h3 style="font-size:22px;font-weight:900;letter-spacing:-0.02em;margin:0 0 8px;color:#0a0a0a;">On its way.</h3>
        <p id="yw-share-success-msg" style="font-size:14px;color:#555;line-height:1.5;margin:0 0 20px;"></p>
        <button type="button" id="yw-share-done" style="padding:12px 24px;background:#0a0a0a;color:#fff;border:none;border-radius:10px;font-weight:700;cursor:pointer;font-size:14px;">Done</button>
      </div>
    </div>
  </div>

  <script>
  (function(){
    var modal = document.getElementById('yw-share-modal');
    var btn = document.getElementById('yw-share-btn');
    var closeBtn = document.getElementById('yw-share-close');
    var cancelBtn = document.getElementById('yw-share-cancel');
    var doneBtn = document.getElementById('yw-share-done');
    var form = document.getElementById('yw-share-form');
    var success = document.getElementById('yw-share-success');
    var successMsg = document.getElementById('yw-share-success-msg');
    var errEl = document.getElementById('yw-share-error');
    var emailsEl = document.getElementById('yw-share-emails');
    var fromEl = document.getElementById('yw-share-from');
    var msgEl = document.getElementById('yw-share-msg');
    var submitBtn = document.getElementById('yw-share-submit');

    function open(){ modal.style.display = 'flex'; form.style.display = ''; success.style.display = 'none'; errEl.style.display = 'none'; setTimeout(function(){ emailsEl.focus(); }, 50); }
    function close(){ modal.style.display = 'none'; }
    btn.addEventListener('click', open);
    closeBtn.addEventListener('click', close);
    cancelBtn.addEventListener('click', close);
    doneBtn.addEventListener('click', close);
    modal.addEventListener('click', function(e){ if(e.target === modal) close(); });
    document.addEventListener('keydown', function(e){ if(e.key === 'Escape' && modal.style.display === 'flex') close(); });

    var EMAIL_RE = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;
    function parseEmails(raw){
      return (raw || '').split(/[\\s,;]+/).map(function(s){ return s.trim(); }).filter(Boolean);
    }

    form.addEventListener('submit', function(e){
      e.preventDefault();
      errEl.style.display = 'none';
      var emails = parseEmails(emailsEl.value);
      if(emails.length === 0){
        errEl.textContent = 'Add at least one email address.';
        errEl.style.display = 'block';
        return;
      }
      var bad = emails.filter(function(em){ return !EMAIL_RE.test(em); });
      if(bad.length){
        errEl.textContent = "These do not look right: " + bad.join(', ');
        errEl.style.display = 'block';
        return;
      }
      var fromName = (fromEl.value || '').trim();
      if(!fromName){
        errEl.textContent = 'Add your name so recipients know who it\\'s from.';
        errEl.style.display = 'block';
        return;
      }

      submitBtn.disabled = true;
      submitBtn.textContent = 'Sending…';

      var payload = {
        kind: 'yw_proposal_share',
        ts: new Date().toISOString(),
        recipients: emails,
        fromName: fromName,
        fromEmail: ${JSON.stringify(dealerEmail || "")},
        dealerName: ${JSON.stringify(dealerName || "")},
        message: (msgEl.value || '').trim(),
        shareUrl: (window.opener && window.opener.location ? window.opener.location.href : ''),
        proposal: {
          persona: ${JSON.stringify(personaLabel)},
          region: ${JSON.stringify(region)},
          monthly: ${JSON.stringify(ywMonthly)},
          annual: ${JSON.stringify(annualYW)},
          annualSavings: ${JSON.stringify(annualSavings)},
          configuration: ${JSON.stringify(setupSummary)}
        }
      };

      // Persist locally so nothing is lost if the endpoint is offline.
      try {
        var KEY = 'yw_share_log';
        var log = JSON.parse(localStorage.getItem(KEY) || '[]');
        log.push(payload);
        localStorage.setItem(KEY, JSON.stringify(log.slice(-200)));
      } catch(e) {}

      // Best-effort POST to a recording endpoint. The endpoint can be
      // configured by setting window.__YW_SHARE_ENDPOINT before this page
      // loads. Falls back to noop (we still keep the local log).
      var endpoint = (window.opener && window.opener.__YW_SHARE_ENDPOINT) ||
                     window.__YW_SHARE_ENDPOINT ||
                     '/api/proposal-share';
      var done = function(){
        form.style.display = 'none';
        success.style.display = 'block';
        successMsg.textContent = 'We\\'ll email this proposal to ' + (emails.length === 1 ? emails[0] : (emails.length + ' people')) + '.';
        submitBtn.disabled = false;
        submitBtn.textContent = 'Send proposal';
      };
      try {
        fetch(endpoint, {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify(payload),
          keepalive: true
        }).then(done).catch(done);
      } catch(e) { done(); }
    });

    // Focus styles
    [emailsEl, fromEl, msgEl].forEach(function(el){
      el.addEventListener('focus', function(){ el.style.borderColor = '${accent}'; });
      el.addEventListener('blur', function(){ el.style.borderColor = '#d4d4d4'; });
    });
  })();
  </script>

  <!-- HEADER with centered logo -->
  <div class="header">
    <div class="logo-wrap">${logoBlock}</div>
    <div class="doc-label">Pricing Proposal</div>
    ${dealerName ? `<div style="font-size:22px;font-weight:900;letter-spacing:-0.02em;color:#0a0a0a;margin-top:10px;">Prepared for ${dealerName}</div>` : ""}
    <div class="doc-meta">${personaLabel} · ${region === "us" ? "United States" : "Europe"} · Generated ${date} · Currency ${cur}</div>
  </div>

  <!-- HERO: Annual savings front and center -->
  ${annualSavings > 0 && priced.length > 0 ? `
  <div class="hero">
    <div class="sub">Estimated annual savings vs. your current platforms</div>
    <div class="annual-num">${fmt(annualSavings)} <span class="small">/ year</span></div>
    <div class="ctx">Replacing ${priced.length === 1 ? "your current platform" : `your ${priced.length} current platforms`} with <strong>YachtWay</strong> saves your business an estimated <strong>${fmt(annualSavings)} every year</strong>.</div>
    ${savingsPct ? `<div class="pct-pill">${savingsPct}% reduction in platform spend</div>` : ""}
    <div class="grid">
      <div>
        <div class="lbl">Your annual on YachtWay</div>
        <div class="val">${fmt(annualYW)}</div>
        <div class="small">${fmt(ywMonthly)} / month</div>
      </div>
      <div>
        <div class="lbl">Annual on current platform${priced.length === 1 ? "" : "s"}</div>
        <div class="val">${fmt(annualComp)}</div>
        <div class="small">${fmt(sumCompMonthly)} / month combined</div>
      </div>
    </div>
  </div>` : `
  <div class="hero">
    <div class="sub">Your YachtWay Annual</div>
    <div class="annual-num">${fmt(annualYW)} <span class="small">/ year</span></div>
    <div class="ctx">${fmt(ywMonthly)} per month, all-in for the configuration below.</div>
  </div>`}

  <!-- CONFIG STRIP -->
  <div class="config-strip">
    <div class="lbl">Your configuration</div>
    <div class="val">${setupSummary}</div>
  </div>

  ${priced.length > 0 ? `
  <!-- COST COMPARISON -->
  <div class="keep-together">
  <h2>Monthly cost comparison</h2>
  <table>
    <thead>
      <tr>
        <th>Platform</th>
        <th style="text-align:right;">Monthly cost</th>
        <th style="text-align:right;">Your savings on YachtWay</th>
      </tr>
    </thead>
    <tbody>${compRows}</tbody>
  </table>
  </div>
  ` : ""}

  <!-- BREAKDOWN -->
  <div class="keep-together">
  <h2>Your YachtWay breakdown</h2>
  <div style="background:linear-gradient(90deg, ${accent}15, ${accent}05); border:1.5px solid ${accent}40; border-radius:10px; padding:16px 20px; margin-bottom:14px; display:flex; align-items:center; gap:14px;">
    <div style="flex-shrink:0; width:40px; height:40px; border-radius:50%; background:${accent}; color:#fff; display:flex; align-items:center; justify-content:center; font-weight:900; font-size:20px;">$0</div>
    <div>
      <div style="font-weight:800; font-size:14px; color:#0a0a0a; letter-spacing:-0.005em;">Listings on YachtWay are always free.</div>
      <div style="font-size:12px; color:#444; margin-top:3px; line-height:1.45;">No setup fee. No per-listing cost. No catalog cap. You only pay for the add-on features and seats you choose below.</div>
    </div>
  </div>
  <table>
    <thead>
      <tr>
        <th>Line item</th>
        <th style="text-align:right;">Amount</th>
      </tr>
    </thead>
    <tbody>
      ${lineRows}
      <tr class="total-row">
        <td>Monthly total</td>
        <td style="text-align:right;font-variant-numeric:tabular-nums;">${fmt(ywMonthly)}</td>
      </tr>
    </tbody>
  </table>
  </div>

  ${annualSavings > 0 && priced.length > 0 ? `
  <!-- 3-YEAR PROJECTION -->
  <div style="margin-top:18px;">
    <h2>3-year cost projection</h2>
    <table>
      <thead>
        <tr>
          <th>Horizon</th>
          <th style="text-align:right;">YachtWay total</th>
          <th style="text-align:right;">${priced.length === 1 ? priced[0].name + " total" : "Current platforms total"}</th>
          <th style="text-align:right;">You save</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td style="padding:13px 16px;border-bottom:1px solid #eee;font-weight:600;font-size:13px;">Year 1</td>
          <td style="padding:13px 16px;border-bottom:1px solid #eee;text-align:right;font-variant-numeric:tabular-nums;font-weight:700;">${fmt(annualYW)}</td>
          <td style="padding:13px 16px;border-bottom:1px solid #eee;text-align:right;font-variant-numeric:tabular-nums;font-weight:700;">${fmt(annualComp)}</td>
          <td style="padding:13px 16px;border-bottom:1px solid #eee;text-align:right;color:#0a7a3b;font-weight:900;font-variant-numeric:tabular-nums;">${fmt(annualSavings)}</td>
        </tr>
        <tr style="background:#fafafa;">
          <td style="padding:13px 16px;border-bottom:1px solid #eee;font-weight:600;font-size:13px;">Year 2</td>
          <td style="padding:13px 16px;border-bottom:1px solid #eee;text-align:right;font-variant-numeric:tabular-nums;font-weight:700;">${fmt(annualYW * 2)}</td>
          <td style="padding:13px 16px;border-bottom:1px solid #eee;text-align:right;font-variant-numeric:tabular-nums;font-weight:700;">${fmt(annualComp * 2)}</td>
          <td style="padding:13px 16px;border-bottom:1px solid #eee;text-align:right;color:#0a7a3b;font-weight:900;font-variant-numeric:tabular-nums;">${fmt(annualSavings * 2)}</td>
        </tr>
        <tr>
          <td style="padding:13px 16px;border-bottom:1px solid #eee;font-weight:600;font-size:13px;">Year 3</td>
          <td style="padding:13px 16px;border-bottom:1px solid #eee;text-align:right;font-variant-numeric:tabular-nums;font-weight:700;">${fmt(annualYW * 3)}</td>
          <td style="padding:13px 16px;border-bottom:1px solid #eee;text-align:right;font-variant-numeric:tabular-nums;font-weight:700;">${fmt(annualComp * 3)}</td>
          <td style="padding:13px 16px;border-bottom:1px solid #eee;text-align:right;color:#0a7a3b;font-weight:900;font-variant-numeric:tabular-nums;">${fmt(annualSavings * 3)}</td>
        </tr>
        <tr class="total-row">
          <td>3-year total savings</td>
          <td style="text-align:right;font-variant-numeric:tabular-nums;">${fmt(annualYW * 3)}</td>
          <td style="text-align:right;font-variant-numeric:tabular-nums;">${fmt(annualComp * 3)}</td>
          <td class="savings-cell" style="text-align:right;font-variant-numeric:tabular-nums;">${fmt(annualSavings * 3)}</td>
        </tr>
      </tbody>
    </table>
    <div class="footnote">Assumes flat configuration over 3 years. Annual increases on legacy platforms are typically a minimum of 10% and often as much as 50%, which would widen this gap further.</div>
  </div>

  <!-- WHY THIS WORKS INSIGHT -->
  <div style="margin-top:18px;">
    <h2>Why this configuration costs less</h2>
    <div style="display:grid;grid-template-columns:1fr 1fr;gap:14px;">
      <div style="padding:18px 20px;border:1.5px solid ${accent}40;border-radius:10px;background:${accent}08;page-break-inside:avoid;break-inside:avoid;">
        <div style="font-size:11px;font-weight:800;color:${accent};text-transform:uppercase;letter-spacing:.12em;margin-bottom:8px;">Bundled, not stacked</div>
        <div style="font-size:13px;color:#222;line-height:1.5;">Listings, e-signing, valuation, financing, insurance, and AI chat all live in one platform. Legacy stacks require separate websites and environments for each.</div>
      </div>
      <div style="padding:18px 20px;border:1.5px solid #e5e5e5;border-radius:10px;page-break-inside:avoid;break-inside:avoid;">
        <div style="font-size:11px;font-weight:800;color:#444;text-transform:uppercase;letter-spacing:.12em;margin-bottom:8px;">No listing fees, ever</div>
        <div style="font-size:13px;color:#222;line-height:1.5;">Most platforms charge per-listing or per-lead. YachtWay charges zero for listings, no setup fee, no catalog cap. Pay only for the seats and add-ons your team uses.</div>
      </div>
      <div style="padding:18px 20px;border:1.5px solid #e5e5e5;border-radius:10px;page-break-inside:avoid;break-inside:avoid;">
        <div style="font-size:11px;font-weight:800;color:#444;text-transform:uppercase;letter-spacing:.12em;margin-bottom:8px;">Transparent pricing</div>
        <div style="font-size:13px;color:#222;line-height:1.5;">Every line item, fee, and add-on is shown above. No multi-year lock-ins, no surprise rate cards, no opaque per-lead invoicing.</div>
      </div>
      <div style="padding:18px 20px;border:1.5px solid #e5e5e5;border-radius:10px;page-break-inside:avoid;break-inside:avoid;">
        <div style="font-size:11px;font-weight:800;color:#444;text-transform:uppercase;letter-spacing:.12em;margin-bottom:8px;">Modern tools included</div>
        <div style="font-size:13px;color:#222;line-height:1.5;">Modern tools for both sellers and buyers come included. Create events, upload 3D tours, and run the NautiX range calculator, all built in.</div>
      </div>
    </div>
  </div>` : ""}

  <!-- SECTION DIVIDER: capabilities -->
  <div style="margin-top:32px;padding-top:20px;border-top:2px solid #0a0a0a;">
    <div style="font-size:11px;font-weight:800;color:${accent};text-transform:uppercase;letter-spacing:.14em;margin-bottom:6px;">Section 02</div>
    <div style="font-size:22px;font-weight:800;color:#0a0a0a;letter-spacing:-0.01em;">Platform capabilities &amp; reach</div>
    <div style="font-size:12px;color:#666;margin-top:4px;">YachtWay vs. ${platforms.length - 1} platform${platforms.length - 1 === 1 ? '' : 's'} from around the world</div>
  </div>

  <div class="summary-grid">${summaryCells}</div>

  <h2>Feature comparison, the platforms you selected</h2>
  <table style="table-layout:fixed;">
    <thead>
      <tr>
        <th style="width:38%;">Capability</th>
        ${featureHeaderCells}
      </tr>
    </thead>
    <tbody>${featureRows}</tbody>
  </table>
  <div class="footnote">All ${platforms.length} platforms from around the world shown side-by-side. Most legacy platforms ship only listings + an API feed, additional services (signing, financing, insurance, content, AI, social) require separate vendors and contracts, and most don't even have those tools.</div>

  <h2>Reach &amp; distribution metrics</h2>
  <table>
    <thead>
      <tr>
        <th style="width:30%;">Metric</th>
        <th style="width:25%;">YachtWay</th>
        <th style="width:45%;">Context</th>
      </tr>
    </thead>
    <tbody>${reachRows}</tbody>
  </table>
  <div class="footnote">Sources: Semrush (traffic, authority), public follower counts (Instagram, YouTube, Facebook, TikTok), tier-1 editorial archives. Metrics current as of ${date}.</div>

  <h2 style="margin-top:24px;">Platforms in this comparison</h2>
  <div style="display:grid;grid-template-columns:repeat(2, 1fr);gap:10px;">
    ${platforms.map((p) => {
    const isYw = p.k === "yw";
    const t = compTotals.find((c) => c.k === p.k);
    const monthly = t ? t.monthly : 0;
    return `
      <div style="padding:14px 16px;border:1.5px solid ${isYw ? accent + "60" : "#e5e5e5"};border-radius:10px;background:${isYw ? accent + "08" : "#fff"};page-break-inside:avoid;break-inside:avoid;">
        <div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:6px;">
          <div style="font-weight:800;font-size:14px;color:#0a0a0a;letter-spacing:-0.005em;">${p.name}</div>
          <div style="font-size:10px;font-weight:700;color:${isYw ? accent : "#888"};text-transform:uppercase;letter-spacing:.1em;">${p.region || "Global"}</div>
        </div>
        <div style="font-size:12px;color:#555;line-height:1.45;margin-bottom:8px;">${p.blurb || "Yacht listings platform."}</div>
        <div style="display:flex;align-items:baseline;gap:6px;">
          <div style="font-size:18px;font-weight:900;color:${isYw ? accent : "#0a0a0a"};font-variant-numeric:tabular-nums;letter-spacing:-0.02em;">${isYw ? "Free" : fmt(monthly)}</div>
          <div style="font-size:11px;color:#888;">${isYw ? "to list" : "for listings"}</div>
        </div>
      </div>`;
  }).join("")}
  </div>
  <div class="footnote">Competitor figures derived from publicly listed rates. Some platforms bundle additional services (CRM, broker tools, websites) into their monthly subscription. YachtWay does not force any services - dealers choose only the ones they need.</div>

  <h2 style="margin-top:24px;">Onboarding &amp; rollout</h2>
  <table>
    <thead>
      <tr>
        <th style="width:22%;">Phase</th>
        <th style="width:18%;">Timing</th>
        <th>What happens</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td style="padding:13px 16px;border-bottom:1px solid #eee;font-weight:700;font-size:13px;">Day 0 to 3</td>
        <td style="padding:13px 16px;border-bottom:1px solid #eee;color:${accent};font-weight:700;font-size:12px;">Kickoff</td>
        <td style="padding:13px 16px;border-bottom:1px solid #eee;color:#444;font-size:12px;line-height:1.45;">Your account is live, your brand is configured, and your team has their seats.</td>
      </tr>
      <tr style="background:#fafafa;">
        <td style="padding:13px 16px;border-bottom:1px solid #eee;font-weight:700;font-size:13px;">Week 1</td>
        <td style="padding:13px 16px;border-bottom:1px solid #eee;color:${accent};font-weight:700;font-size:12px;">Catalog import</td>
        <td style="padding:13px 16px;border-bottom:1px solid #eee;color:#444;font-size:12px;line-height:1.45;">Your inventory comes in via API feed. Talk to your YachtWay representative today to confirm your feed is supported. Live within 5 business days.</td>
      </tr>
      <tr>
        <td style="padding:13px 16px;border-bottom:1px solid #eee;font-weight:700;font-size:13px;">Week 2</td>
        <td style="padding:13px 16px;border-bottom:1px solid #eee;color:${accent};font-weight:700;font-size:12px;">Team training</td>
        <td style="padding:13px 16px;border-bottom:1px solid #eee;color:#444;font-size:12px;line-height:1.45;">Your brokers get hands-on time with the full toolset. Workflows, LIVE, EasyFund, MasterCover. Everything configured to how your team works.</td>
      </tr>
    </tbody>
  </table>

  <div class="footer">
    <strong>YachtWay OS.</strong> The operating system for dealers, brokers, and shipyards.<br/>
    Pricing reflects the configuration above and may vary by contract. Platform comparison figures are based on publicly listed rates or numbers you entered.<br/>
    No credit card required to list. Contact your YachtWay representative to finalize this configuration.
  </div>
</body>
</html>`;
};

const exportProposalPDF = async (params) => {
  // Fetch the YachtWay logo and inline it as a data URL so the print preview
  // is fully self-contained (no broken images on print, no auth issues).
  let logoDataUrl = "";
  try {
    logoDataUrl = window.__YW_ASSETS && window.__YW_ASSETS.logoDark || "";
    if (!logoDataUrl) {
      const res = await fetch("assets/yachtway-logo-dark.png");
      const blob = await res.blob();
      logoDataUrl = await new Promise((resolve) => {
        const r = new FileReader();
        r.onloadend = () => resolve(r.result);
        r.readAsDataURL(blob);
      });
    }
  } catch (e) {/* fall back to text wordmark */}
  const html = buildProposalHTML({ ...params, logoDataUrl });
  const w = window.open("", "_blank");
  if (!w) {
    alert("Please allow pop-ups to export your proposal.");
    return;
  }
  w.document.open();
  w.document.write(html);
  w.document.close();
  // Trigger print after content settles
  setTimeout(() => {try {w.focus();w.print();} catch (e) {}}, 400);
};

const shareProposal = (params) => {
  // Encode the configuration into a URL fragment so it can be shared via link
  const url = new URL(window.location.href);
  const cfg = {
    p: params.persona, r: params.region,
    b: params.brokers, m: params.managers, o: params.offices, br: params.brands,
    es: params.easySign ? 1 : 0, va: params.vato ? 1 : 0, ap: params.api ? 1 : 0, we: params.web ? 1 : 0,
    li: params.liveSessions
  };
  url.hash = "config=" + btoa(JSON.stringify(cfg));
  if (navigator.clipboard && navigator.clipboard.writeText) {
    navigator.clipboard.writeText(url.toString()).then(() => {
      // Lightweight in-page toast
      const t = document.createElement("div");
      t.textContent = "Link copied, paste anywhere to share your plan";
      Object.assign(t.style, {
        position: "fixed", bottom: "24px", left: "50%", transform: "translateX(-50%)",
        background: "#1a1a1a", color: "#fff", padding: "12px 20px",
        borderRadius: "10px", fontSize: "13px", fontWeight: "600",
        zIndex: 99999, boxShadow: "0 8px 32px rgba(0,0,0,.25)",
        fontFamily: "-apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif"
      });
      document.body.appendChild(t);
      setTimeout(() => t.remove(), 2400);
    });
  } else {
    prompt("Copy this link to share your plan:", url.toString());
  }
};

// Inline-editable price cell for competitor rows. Click to edit, Enter/blur to commit, Esc to cancel.
const EditablePrice = ({ row, unknown, region, fmt, fontFamily, accent, isYw, value, onChange }) => {
  const [editing, setEditing] = React.useState(false);
  const [draft, setDraft] = React.useState("");
  const inputRef = React.useRef(null);
  React.useEffect(() => {
    if (editing && inputRef.current) {
      inputRef.current.focus();
      inputRef.current.select();
    }
  }, [editing]);
  const startEdit = () => {
    if (isYw) return; // YachtWay row uses its own breakdown, not editable here
    setDraft(value || (row.monthly ? String(Math.round(row.monthly)) : ""));
    setEditing(true);
  };
  const commit = () => {
    const cleaned = draft.replace(/[^\d]/g, "");
    onChange(cleaned);
    setEditing(false);
  };
  const cancel = () => setEditing(false);
  const symbol = region === "us" ? "$" : "€";
  const hasOv = !!value;

  if (editing) {
    return (
      <div style={{ display: "flex", flexDirection: "column", alignItems: "flex-end", gap: 4 }}>
        <div style={{ display: "flex", alignItems: "baseline", gap: 4 }}>
          <span style={{ fontFamily, fontSize: 16, fontWeight: 800, color: "rgba(255,255,255,.6)" }}>{symbol}</span>
          <input
            ref={inputRef}
            type="text"
            inputMode="numeric"
            value={draft ? Number(draft.replace(/[^\d]/g, "")).toLocaleString("en-US") : ""}
            onChange={(e) => setDraft(e.target.value.replace(/[^\d]/g, ""))}
            onBlur={commit}
            onKeyDown={(e) => {
              if (e.key === "Enter") {e.preventDefault();commit();}
              if (e.key === "Escape") {e.preventDefault();cancel();}
            }}
            placeholder={unknown ? "0" : ""}
            style={{
              width: 92, textAlign: "right",
              background: "rgba(255,255,255,.08)",
              border: `1px solid ${accent}`,
              borderRadius: 6, padding: "4px 8px",
              color: "#fff", fontFamily, fontSize: 16, fontWeight: 800,
              letterSpacing: "-0.02em", outline: "none"
            }} />
          
          <span style={{ fontSize: 11, color: "rgba(255,255,255,.55)", fontWeight: 600 }}>/mo</span>
        </div>
        <div style={{ fontSize: 11, color: "rgba(255,255,255,.5)" }}>Your monthly cost · Enter to save · Esc to cancel</div>
      </div>);

  }

  // YW row: static display, no edit affordance
  if (isYw) {
    return (
      <div style={{ display: "inline-flex", flexDirection: "column", alignItems: "flex-end", gap: 3, textAlign: "right" }}>
        {unknown ?
        <>
            <div style={{ fontFamily, fontSize: 13, fontWeight: 700, color: "rgba(255,255,255,.7)", letterSpacing: "-0.01em", lineHeight: 1 }}>Unknown</div>
            <div style={{ fontSize: 13, color: "rgba(255,255,255,.4)" }}>not public</div>
          </> :

        <>
            <div style={{ fontFamily, fontSize: 18, fontWeight: 800, color: "#fff", letterSpacing: "-0.02em", lineHeight: 1 }}>{fmt(row.monthly)}</div>
            <div style={{ fontSize: 13, color: "rgba(255,255,255,.4)" }}>per month</div>
          </>
        }
      </div>);

  }

  // Competitor rows: clear, dealer-facing edit affordance
  const pencilSvg = `<svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" style="display:block;"><path d="M12 20h9"/><path d="M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4 12.5-12.5z"/></svg>`;

  return (
    <button
      type="button"
      onClick={startEdit}
      title="Click to enter your current monthly cost on this platform"
      style={{
        display: "inline-flex", alignItems: "baseline", gap: 4,
        background: hasOv ? `${accent}26` : "rgba(255,255,255,.04)",
        border: `1.5px ${hasOv ? "solid" : "dashed"} ${hasOv ? accent : "rgba(255,255,255,.22)"}`,
        borderRadius: 8, padding: "6px 10px", margin: 0,
        cursor: "pointer", textAlign: "right",
        transition: "background .12s ease, border-color .12s ease"
      }}
      onMouseOver={(e) => {
        e.currentTarget.style.background = hasOv ? `${accent}3d` : "rgba(255,255,255,.10)";
        e.currentTarget.style.borderColor = accent;
      }}
      onMouseOut={(e) => {
        e.currentTarget.style.background = hasOv ? `${accent}26` : "rgba(255,255,255,.04)";
        e.currentTarget.style.borderColor = hasOv ? accent : "rgba(255,255,255,.22)";
      }}>
      
      {unknown ?
      <>
          <span style={{ fontFamily, fontSize: 14, fontWeight: 700, color: "rgba(255,255,255,.85)", letterSpacing: "-0.01em", whiteSpace: "nowrap" }}>Enter price</span>
          <span dangerouslySetInnerHTML={{ __html: pencilSvg }} style={{ color: accent, marginLeft: 2 }} />
        </> :

      <>
          <span style={{ fontFamily, fontSize: 18, fontWeight: 800, color: "#fff", letterSpacing: "-0.02em", lineHeight: 1 }}>{fmt(row.monthly)}</span>
          <span style={{ fontSize: 11, color: "rgba(255,255,255,.55)", fontWeight: 600 }}>/mo</span>
          <span dangerouslySetInnerHTML={{ __html: pencilSvg }} style={{ color: hasOv ? accent : "rgba(255,255,255,.45)", marginLeft: 2 }} />
        </>
      }
    </button>);

};

// ── Paid card with optional flip-to-detail back face (for Studio Pass etc.) ──
const PaidFlipCard = ({ p, T, rgba }) => {
  const [flipped, setFlipped] = useStateD(false);
  const [hover, setHover] = useStateD(false);
  const hasDetails = !!p.details;
  return (
    <div style={{
      perspective: 1400,
      gridColumn: hasDetails && flipped ? "1 / -1" : "auto",
      transition: "grid-column .35s ease",
      height: "100%"
    }}>
      <div style={{
        position: "relative",
        width: "100%",
        height: "100%",
        minHeight: 168,
        transformStyle: "preserve-3d",
        transition: "transform .55s cubic-bezier(.5,.05,.2,1)",
        transform: flipped ? "rotateY(180deg)" : "rotateY(0deg)"
      }}>
        {/* FRONT — entire card is clickable when details exist */}
        <div
          className="ed-card"
          role={hasDetails ? "button" : undefined}
          tabIndex={hasDetails ? 0 : undefined}
          aria-label={hasDetails ? `View details for ${p.name}` : undefined}
          onClick={hasDetails ? () => setFlipped(true) : undefined}
          onKeyDown={hasDetails ? (e) => {
            if (e.key === "Enter" || e.key === " ") { e.preventDefault(); setFlipped(true); }
          } : undefined}
          onMouseEnter={hasDetails ? () => setHover(true) : undefined}
          onMouseLeave={hasDetails ? () => setHover(false) : undefined}
          style={{
            position: flipped ? "absolute" : "relative",
            inset: flipped ? 0 : "auto",
            background: T.bg,
            border: `1px solid ${hasDetails && hover ? T.accent : T.border}`,
            borderRadius: 14, padding: 22,
            display: "flex", flexDirection: "column", gap: 10,
            backfaceVisibility: "hidden",
            WebkitBackfaceVisibility: "hidden",
            height: "100%",
            minHeight: 168,
            boxSizing: "border-box",
            cursor: hasDetails ? "pointer" : "default",
            transform: hasDetails && hover ? "translateY(-2px)" : "translateY(0)",
            boxShadow: hasDetails && hover
              ? `0 12px 28px -12px ${rgba(T.accent, .35)}, 0 0 0 1px ${rgba(T.accent, .1)}`
              : "0 1px 0 rgba(0,0,0,0)",
            transition: "transform .18s ease, box-shadow .18s ease, border-color .18s ease",
            outline: "none"
          }}>
          <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", gap: 8 }}>
            <div style={{ fontFamily: T.fDisplay, fontSize: 15, fontWeight: 600 }}>{p.name}</div>
            <div style={{ fontSize: 13, color: T.fgFaint }}>{p.unit}</div>
          </div>
          <div style={{ fontFamily: T.fDisplay, fontSize: 26, fontWeight: 700, letterSpacing: "-0.02em", lineHeight: 1, display: "flex", alignItems: "baseline", gap: 4, flexWrap: "wrap" }}>
            <span>{p.price}</span>
            {p.priceSuffix &&
            <span style={{ fontSize: 15, fontWeight: 500, color: T.fgFaint, letterSpacing: 0 }}>{p.priceSuffix}</span>
            }
          </div>
          <p style={{ fontSize: 13, lineHeight: 1.55, color: T.fgMuted, margin: 0 }}>{p.desc}</p>
          {hasDetails &&
            <div style={{
              marginTop: "auto", paddingTop: 14,
              borderTop: `1px solid ${T.border}`,
              display: "flex", alignItems: "center", justifyContent: "flex-start"
            }}>
              <div style={{
                display: "inline-flex", alignItems: "center", gap: 8,
                padding: "7px 12px",
                borderRadius: 999,
                fontSize: 12, fontWeight: 700, letterSpacing: ".06em",
                textTransform: "uppercase",
                background: hover ? T.accent : rgba(T.accent, .08),
                color: hover ? "#fff" : T.accent,
                border: `1px solid ${hover ? T.accent : rgba(T.accent, .25)}`,
                transition: "background .18s ease, color .18s ease, border-color .18s ease"
              }}>
                <span>View details</span>
                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor"
                  strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round"
                  style={{ transform: hover ? "translateX(2px)" : "translateX(0)", transition: "transform .18s ease" }}>
                  <line x1="5" y1="12" x2="19" y2="12" />
                  <polyline points="13 6 19 12 13 18" />
                </svg>
              </div>
            </div>
          }
        </div>

        {/* BACK */}
        {hasDetails &&
        <div className="yw-flip-back" data-flipped={flipped ? "true" : "false"} style={{
          position: flipped ? "relative" : "absolute",
          inset: flipped ? "auto" : 0,
          width: "100%",
          background: "#0e0a18",
          color: "#fff",
          border: `1px solid ${rgba(T.accent, .35)}`,
          borderRadius: 14, padding: 24,
          display: "flex", flexDirection: "column", gap: 12,
          backfaceVisibility: "hidden",
          WebkitBackfaceVisibility: "hidden",
          transform: "rotateY(180deg)",
          overflow: "hidden",
          boxSizing: "border-box"
        }}>
            <div style={{
            position: "absolute", inset: 0,
            background: `radial-gradient(ellipse 80% 60% at 0% 0%, ${rgba(T.accent, .22)}, transparent 60%)`,
            pointerEvents: "none"
          }} />
            <div style={{ position: "relative", display: "flex", flexDirection: "column", gap: 10, height: "100%" }}>
              <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center" }}>
                <div style={{
                fontSize: 13, fontWeight: 700, color: T.accentLight,
                textTransform: "uppercase", letterSpacing: ".14em"
              }}>{p.name} · {p.details.label || "How it pays back"}</div>
                <button
                type="button"
                onClick={() => setFlipped(false)}
                aria-label="Close details"
                style={{
                  width: 28, height: 28, padding: 0,
                  display: "inline-flex", alignItems: "center", justifyContent: "center",
                  borderRadius: 999, cursor: "pointer",
                  background: "rgba(255,255,255,.10)",
                  border: "1px solid rgba(255,255,255,.45)",
                  color: "#fff",
                  transition: "background .15s ease, border-color .15s ease"
                }}
                onMouseOver={(e) => {
                  e.currentTarget.style.background = "rgba(255,255,255,.22)";
                  e.currentTarget.style.borderColor = "rgba(255,255,255,.7)";
                }}
                onMouseOut={(e) => {
                  e.currentTarget.style.background = "rgba(255,255,255,.10)";
                  e.currentTarget.style.borderColor = "rgba(255,255,255,.45)";
                }}>
                
                  <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor"
                strokeWidth="2.6" strokeLinecap="round">
                    <path d="M6 6l12 12M18 6L6 18" />
                  </svg>
                </button>
              </div>
              <div style={{
              fontFamily: T.fDisplay, fontSize: 19, fontWeight: 600,
              letterSpacing: "-0.015em", lineHeight: 1.25, color: "#fff",
              textWrap: "balance"
            }}>{p.details.headline}</div>
              <p style={{ fontSize: 13.5, lineHeight: 1.6, color: "rgba(255,255,255,.92)", margin: 0 }}>
                {p.details.intro}
              </p>
              {/* Bullet/point list - used for explanation-style detail cards
                 (EasyFund, MasterCover) where there is no savings table.
                 Each bullet has a label and short body. */}
              {p.details.bullets ?
            <div style={{ marginTop: 4, display: "flex", flexDirection: "column", gap: 10 }}>
                  {p.details.bullets.map((b, i) =>
              <div key={i} style={{ display: "flex", gap: 10, alignItems: "flex-start" }}>
                      <span style={{
                  flex: "none", marginTop: 5,
                  width: 6, height: 6, borderRadius: 3,
                  background: T.accentLight
                }} />
                      <div style={{ fontSize: 13.5, lineHeight: 1.6, color: "rgba(255,255,255,.95)" }}>
                        {b.k &&
                  <span style={{ color: "#fff", fontWeight: 600 }}>{b.k}{b.v ? ". " : ""}</span>
                  }
                        {b.v || b}
                      </div>
                    </div>
              )}
                </div> :
            null}
              {/* Perks table */}
              {p.details.perks ?
            <div style={{ marginTop: 4, display: "flex", flexDirection: "column", gap: 2 }}>
                <div style={{
                display: "grid", gridTemplateColumns: "1.4fr 0.9fr 1.1fr",
                gap: 10, padding: "6px 0 8px",
                fontSize: 10, fontWeight: 700, color: "rgba(255,255,255,.65)",
                textTransform: "uppercase", letterSpacing: ".1em",
                borderBottom: "1px solid rgba(255,255,255,.18)"
              }}>
                  <div>{p.details.col1 || "Service"}</div>
                  <div>{p.details.col2 || "Standard"}</div>
                  <div>{p.details.col3 || p.name}</div>
                </div>
                {p.details.perks.map((row, i) =>
              <div key={i} style={{
                display: "grid", gridTemplateColumns: "1.4fr 0.9fr 1.1fr",
                gap: 10, alignItems: "center",
                fontSize: 13.5, padding: "10px 0",
                borderBottom: i < p.details.perks.length - 1 ? "1px solid rgba(255,255,255,.12)" : "none"
              }}>
                    <div style={{ color: "rgba(255,255,255,.92)", fontFamily: T.fBody }}>{row.k}</div>
                    <div style={{
                  color: "rgba(255,255,255,.6)",
                  textDecoration: p.details.noStrike ? "none" : "line-through",
                  fontFamily: T.fMono, fontSize: 13.5
                }}>{row.nonMember}</div>
                    <div style={{ display: "flex", alignItems: "center", gap: 8, color: "#fff", fontWeight: 600, fontFamily: T.fMono, fontSize: 13.5 }}>
                      <span>{row.member}</span>
                      <span style={{
                    fontSize: 13, fontWeight: 700, color: T.accentLight,
                    padding: "2px 6px", borderRadius: 3,
                    background: rgba(T.accent, .2),
                    textTransform: "uppercase", letterSpacing: ".06em",
                    whiteSpace: "nowrap"
                  }}>{row.save}</span>
                    </div>
                  </div>
              )}
              </div> :
            null}
              {/* Sample math block: shows real ROI per shoot for plans that
                 define a `roi` object (Studio Pass). Brokers see exactly
                 what one boat saves them and how the membership pays back. */}
              {p.details.roi ?
            <div style={{
              marginTop: 4,
              padding: "14px 14px 12px",
              background: rgba(T.accent, .12),
              border: `1px solid ${rgba(T.accent, .35)}`,
              borderRadius: 10
            }}>
                  <div style={{
                fontSize: 10, fontWeight: 700, color: T.accentLight,
                textTransform: "uppercase", letterSpacing: ".12em",
                marginBottom: 8
              }}>Sample math · {p.details.roi.boat || "One 50ft vessel"}</div>
                  <div style={{
                display: "grid", gridTemplateColumns: "1fr auto", gap: 6,
                fontSize: 13.5, color: "rgba(255,255,255,.92)",
                fontFamily: T.fMono
              }}>
                    <div style={{ color: "rgba(255,255,255,.7)" }}>Without Pass</div>
                    <div style={{ color: "rgba(255,255,255,.7)", textDecoration: "line-through", textAlign: "right" }}>{p.details.roi.non}</div>
                    <div>With Pass</div>
                    <div style={{ textAlign: "right", color: "#fff", fontWeight: 700 }}>{p.details.roi.member}</div>
                    <div style={{
                  gridColumn: "1 / -1", height: 1,
                  background: "rgba(255,255,255,.16)", marginTop: 2, marginBottom: 2
                }} />
                    <div style={{ color: T.accentLight, fontWeight: 700, textTransform: "uppercase", letterSpacing: ".06em", fontSize: 11 }}>Saved per shoot</div>
                    <div style={{
                  textAlign: "right", color: T.accentLight, fontWeight: 800,
                  fontFamily: T.fDisplay, fontSize: 16, letterSpacing: "-0.01em"
                }}>{p.details.roi.save}</div>
                  </div>
                </div> :
            null}
              {p.details.bottom ?
            <div style={{
              fontSize: 13, lineHeight: 1.6, color: "rgba(255,255,255,.78)",
              fontStyle: "italic", marginTop: 4,
              paddingTop: 12, borderTop: "1px solid rgba(255,255,255,.16)"
            }}>{p.details.bottom}</div> :
            null}
            </div>
          </div>
        }
      </div>
    </div>);

};

// ── Live broadcast frame: blinking REC + corner brackets, activates on scroll-in ──
const LiveBroadcastFrame = ({ T, A, AL }) => {
  const ref = useRefD(null);
  const [active, setActive] = useStateD(false);
  const [viewers, setViewers] = useStateD(20);
  // Stream of fake live-chat comments. We keep up to 4; oldest fades out.
  const [comments, setComments] = useStateD([]);
  React.useEffect(() => {
    const el = ref.current;
    if (!el) return;
    const target = el.parentElement;
    if (!target) return;
    let timer = 0;
    let done = false;
    const check = () => {
      if (done) return;
      const r = target.getBoundingClientRect();
      const vh = window.innerHeight || document.documentElement.clientHeight;
      if (r.top < vh * 0.85 && r.bottom > 0) {
        done = true;
        setActive(true);
        return;
      }
      timer = window.setTimeout(check, 250);
    };
    check();
    return () => {done = true;window.clearTimeout(timer);};
  }, []);

  // Viewer counter: gently climbs from 90 to 100 once the section is active,
  // with small jitter so it reads as a live broadcast rather than a fixed
  // figure. Stops at 100 and idles with ±1 fluctuations.
  React.useEffect(() => {
    if (!active) return;
    // Start at 20 viewers; each second roughly 1.5 join, and every 2nd
    // second one leaves, so the count climbs naturally toward ~50, with
    // small ebb-and-flow that looks like a real stream.
    let cur = 20;
    let joinAcc = 0; // fractional accumulator for the 1.5/sec join rate
    let leaveTick = 0; // alternates each second to drop one viewer every 2s
    setViewers(cur);
    let stopped = false;
    const TARGET = 50;
    const tick = () => {
      if (stopped) return;

      // Joins: +1.5 per second on average. We jitter the increment a bit
      // so it does not tick like a metronome (1, 2, 1, 2…).
      joinAcc += 1.2 + Math.random() * 0.6; // 1.2 - 1.8
      let joined = 0;
      while (joinAcc >= 1) {joined += 1;joinAcc -= 1;}

      // Leaves: one viewer every ~2 seconds.
      let left = 0;
      leaveTick += 1;
      if (leaveTick >= 2) {left = 1;leaveTick = 0;}

      // Once we are around the target, ease off so we hover instead of
      // shooting past, joins slow, leaves keep going. Yields a soft
      // plateau around 48 - 52.
      if (cur >= TARGET) {
        joined = Math.random() < 0.55 ? 1 : 0;
      }

      cur = Math.max(20, cur + joined - left);
      setViewers(cur);
      window.setTimeout(tick, 1000);
    };
    const t = window.setTimeout(tick, 600);
    return () => {stopped = true;window.clearTimeout(t);};
  }, [active]);

  // Live-chat comment stream. Spawns a new comment every 2.2 - 3.5s once the
  // section is in view; keeps the most recent 4. Each entry has a unique id
  // (so React can key them) and the text + username are randomized per spawn.
  React.useEffect(() => {
    if (!active) return;
    const POOL = [
    "Range on the 105 footer?",
    "Beautiful lines",
    "Twin MAN V12s?",
    "Can the buyer do a survey via livestream?",
    "📍 Monaco - when is it next here?",
    "Stunning! What is the asking?",
    "Carbon mast option available?",
    "Crew quarters?",
    "How is she handle a head sea?",
    "Watching from Auckland 🇳🇿",
    "What is the fuel burn at cruise?",
    "Beam?",
    "Already messaged the broker",
    "When are sea trials in Palma?",
    "Joystick docking?",
    "Hybrid drive?",
    "Sweet teak deck",
    "Bar setup on the flybridge?",
    "Tender garage hold a 4.5m?",
    "Watching from Fort Lauderdale 👋",
    "Rolls-Royce stabilizers?",
    "Refit history?",
    "Charter income?",
    "EU VAT paid?",
    "Stunning interior",
    "Master cabin on the main deck?"];

    let stopped = false;
    let nextId = 0;
    let pending = new Set();
    const spawn = () => {
      if (stopped) return;
      const text = POOL[Math.floor(Math.random() * POOL.length)];
      const userNum = 100 + Math.floor(Math.random() * 9900);
      const name = `User${userNum}`;
      const id = nextId++;
      setComments((prev) => {
        // Keep last 4, prepending new at the bottom.
        const next = [...prev, { id, name, text }];
        return next.slice(-4);
      });
      // Auto-prune this comment after ~7s so older ones fade out even
      // if the spawn rate slows.
      const pruneT = window.setTimeout(() => {
        setComments((prev) => prev.filter((c) => c.id !== id));
        pending.delete(pruneT);
      }, 7500);
      pending.add(pruneT);
      // Cadence: 1.0 - 2.2s so the chat feels constantly alive, like a
      // real popular livestream where messages stream in non-stop.
      const next = 1000 + Math.random() * 1200;
      const spawnT = window.setTimeout(spawn, next);
      pending.add(spawnT);
    };
    const t = window.setTimeout(spawn, 900);
    pending.add(t);
    return () => {
      stopped = true;
      pending.forEach((id) => window.clearTimeout(id));
      pending.clear();
    };
  }, [active]);
  const cornerBase = {
    position: "absolute", width: 38, height: 38,
    borderColor: "rgba(255,255,255,.6)", borderStyle: "solid",
    transition: "transform .9s cubic-bezier(.5,.05,.2,1)",
    opacity: active ? 1 : 0
  };
  return (
    <div ref={ref} aria-hidden="true" style={{
      position: "absolute", inset: 0,
      pointerEvents: "none", zIndex: 3
    }}>
      {/* Sticky viewport-tracking frame, fits within the section bounds */}
      <div style={{
        position: "sticky",
        top: 0,
        height: "100vh",
        marginInline: 24,
        pointerEvents: "none"
      }}>
        {/* TL */}
        <div style={{ ...cornerBase, top: 24, left: 0, borderWidth: "2px 0 0 2px",
          transform: active ? "translate(0,0)" : "translate(-14px,-14px)" }} />
        {/* TR */}
        <div style={{ ...cornerBase, top: 24, right: 0, borderWidth: "2px 2px 0 0",
          transform: active ? "translate(0,0)" : "translate(14px,-14px)" }} />
        {/* BL */}
        <div style={{ ...cornerBase, bottom: 24, left: 0, borderWidth: "0 0 2px 2px",
          transform: active ? "translate(0,0)" : "translate(-14px,14px)" }} />
        {/* BR */}
        <div style={{ ...cornerBase, bottom: 24, right: 0, borderWidth: "0 2px 2px 0",
          transform: active ? "translate(0,0)" : "translate(14px,14px)" }} />

        {/* Top-right LIVE indicator */}
        <div style={{
          position: "absolute", top: 42, right: 22,
          display: "flex", flexDirection: "column", alignItems: "flex-end", gap: 6,
          opacity: active ? 1 : 0,
          transform: active ? "translateY(0)" : "translateY(-10px)",
          transition: "transform .5s ease .25s"
        }}>
          <div style={{ display: "flex", alignItems: "center", gap: 9 }}>
            <span style={{
              width: 10, height: 10, borderRadius: "50%",
              background: "#ff2a2a",
              boxShadow: "0 0 12px rgba(255,42,42,.8)",
              animation: active ? "lbf-blink 1.1s steps(2, end) infinite" : "none"
            }} />
            <span style={{
              fontFamily: T.fBody,
              fontSize: 11, fontWeight: 700, letterSpacing: ".22em",
              color: "#fff", textTransform: "uppercase"
            }}>LIVE</span>
          </div>
          <div style={{
            fontFamily: T.fBody,
            fontSize: 11, fontWeight: 500, letterSpacing: ".18em",
            color: "rgba(255,255,255,.5)", textTransform: "uppercase"
          }}>REC · CH 01</div>
        </div>

        {/* Top-left viewer count (eye + count climbing 90 → 100) */}
        <div style={{
          position: "absolute", top: 42, left: 22,
          display: "flex", alignItems: "center", gap: 8,
          opacity: active ? 1 : 0,
          transform: active ? "translateY(0)" : "translateY(-10px)",
          transition: "transform .5s ease .25s, opacity .5s ease .25s"
        }}>
          {/* Eye icon */}
          <svg width="14" height="14" viewBox="0 0 24 24" fill="none"
          stroke="rgba(255,255,255,.85)" strokeWidth="1.8"
          strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
            <path d="M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7-10-7-10-7z" />
            <circle cx="12" cy="12" r="3" />
          </svg>
          <span style={{
            fontFamily: T.fBody,
            fontSize: 11, fontWeight: 700, letterSpacing: ".18em",
            color: "#fff", textTransform: "uppercase",
            fontVariantNumeric: "tabular-nums"
          }}>
            {viewers} <span style={{ color: "rgba(255,255,255,.5)", fontWeight: 500 }}>WATCHING</span>
          </span>
        </div>

        {/* Bottom-left live comments stream */}
        <div style={{
          position: "absolute",
          left: 22,
          bottom: 64,
          width: 320,
          maxWidth: "min(45%, 360px)",
          display: "flex",
          flexDirection: "column",
          gap: 6,
          alignItems: "flex-start",
          pointerEvents: "none",
          opacity: active ? 1 : 0,
          transition: "opacity .4s ease"
        }}>
          {comments.map((c) =>
          <div key={c.id} className="lbf-comment" style={{
            display: "flex",
            alignItems: "baseline",
            gap: 8,
            fontSize: 13,
            lineHeight: 1.4,
            color: "#fff",
            fontFamily: T.fBody,
            maxWidth: "100%",
            textShadow: "0 1px 6px rgba(0,0,0,.7), 0 0 14px rgba(0,0,0,.5)"
          }}>
              <span style={{
              fontWeight: 700,
              color: "rgba(255,255,255,.95)",
              whiteSpace: "nowrap",
              fontVariantNumeric: "tabular-nums"
            }}>{c.name}</span>
              <span style={{
              color: "rgba(255,255,255,.85)",
              overflow: "hidden",
              textOverflow: "ellipsis"
            }}>{c.text}</span>
            </div>
          )}
        </div>
      </div>

      <style>{`
        @keyframes lbf-blink {
          0%, 49% { opacity: 1; }
          50%, 100% { opacity: 0.2; }
        }
        @keyframes lbf-comment-in {
          0%   { opacity: 0; transform: translateY(8px); }
          15%  { opacity: 1; transform: translateY(0); }
          75%  { opacity: 1; transform: translateY(0); }
          100% { opacity: 0; transform: translateY(-4px); }
        }
        .lbf-comment {
          animation: lbf-comment-in 7.5s ease-out forwards;
        }
      `}</style>
    </div>);

};

// ── Engagement toast: live activity counter, appears after a long scroll-in delay,
//    then auto-collapses to a small pill so it stops grabbing attention. Hover the
//    pill to re-expand. Bottom-right placement so it stays out of reading flow. ──
const EngagementToast = ({ T, A }) => {
  const [show, setShow] = useStateD(false);
  const [collapsed, setCollapsed] = useStateD(false);
  const [hover, setHover] = useStateD(false);
  const [dismissed, setDismissed] = useStateD(false);
  const [count, setCount] = useStateD(840);
  const [inLive, setInLive] = useStateD(false);

  // Hide toast while the LIVE section OR the footer is on screen, LIVE has
  // its own broadcast UI, and the footer is the bottom of the page where the
  // toast would block the dark CTA panel. We watch BOTH live (#live) and
  // mobile-live (#live-mobile) variants, only one is ever visible at a
  // given viewport, but we observe both so the toast is suppressed in either
  // layout.
  React.useEffect(() => {
    if (typeof IntersectionObserver === "undefined") return;
    const ids = ["live", "live-mobile", "site-footer"];
    const els = ids.map((id) => document.getElementById(id)).filter(Boolean);
    if (!els.length) return;
    const visible = new Map();
    const io = new IntersectionObserver((entries) => {
      for (const e of entries) visible.set(e.target, e.isIntersecting);
      setInLive([...visible.values()].some(Boolean));
    }, { threshold: 0.15 });
    els.forEach((el) => io.observe(el));
    return () => io.disconnect();
  }, []);

  // Mount: appear after 8s so it does not crowd the hero or first scroll.
  React.useEffect(() => {
    const t = window.setTimeout(() => setShow(true), 8000);
    return () => window.clearTimeout(t);
  }, []);

  // After first appearance, auto-collapse to a pill after 7s so it is not constantly looming.
  React.useEffect(() => {
    if (!show || collapsed) return;
    const t = window.setTimeout(() => setCollapsed(true), 7000);
    return () => window.clearTimeout(t);
  }, [show, collapsed]);

  // The headline stat is "840 people engage per minute, globally" - it is
  // a fixed figure, not a live ticker, so the counter stays at 840.
  React.useEffect(() => {
    setCount(840);
  }, []);

  if (dismissed) return null;
  if (inLive) return null;

  return (
    <>
      <style>{`
        @keyframes et-pulse {
          0%, 100% { transform: scale(1); opacity: 1; }
          50% { transform: scale(.7); opacity: .55; }
        }
        @keyframes et-ring {
          0% { transform: scale(.6); opacity: .8; }
          100% { transform: scale(2.4); opacity: 0; }
        }
        @keyframes et-shimmer {
          0% { background-position: -200% 0; }
          100% { background-position: 200% 0; }
        }
        .engagement-toast {
          position: fixed;
          left: 24px;
          bottom: 24px;
          z-index: 9990;
          width: 340px;
          max-width: calc(100vw - 48px);
          background: linear-gradient(135deg, #0d0d10 0%, #18161f 100%);
          color: #fff;
          border: 1px solid rgba(255,255,255,.10);
          border-radius: 16px;
          padding: 16px 18px 16px 20px;
          box-shadow:
            0 24px 60px -20px rgba(0,0,0,.55),
            0 8px 24px -8px rgba(0,0,0,.45),
            0 0 0 1px rgba(255,255,255,.04) inset;
          backdrop-filter: blur(12px);
          -webkit-backdrop-filter: blur(12px);
          display: flex;
          gap: 14px;
          align-items: flex-start;
          opacity: 0;
          transform: translateY(24px) scale(.96);
          transition:
            opacity .45s ease,
            transform .55s cubic-bezier(.2,.7,.2,1),
            width .45s cubic-bezier(.2,.7,.2,1),
            padding .35s ease,
            border-radius .35s ease;
          pointer-events: none;
          overflow: hidden;
        }
        .engagement-toast.is-collapsed {
          width: 200px;
          padding: 10px 14px 10px 14px;
          border-radius: 999px;
          gap: 10px;
        }
        .engagement-toast.is-collapsed .engagement-toast__close,
        .engagement-toast.is-collapsed .engagement-toast__eyebrow,
        .engagement-toast.is-collapsed .engagement-toast__cta,
        .engagement-toast.is-collapsed .engagement-toast__suffix-full,
        .engagement-toast.is-collapsed .engagement-toast__supp,
        .engagement-toast.is-collapsed .engagement-toast__people,
        .engagement-toast.is-collapsed::after { display: none; }
        .engagement-toast.is-collapsed .engagement-toast__pulse-wrap {
          width: 16px; height: 16px;
        }
        .engagement-toast.is-collapsed .engagement-toast__pulse {
          width: 8px; height: 8px;
        }
        .engagement-toast.is-collapsed .engagement-toast__count {
          font-size: 18px;
          min-width: 0;
          line-height: 1;
        }
        .engagement-toast.is-collapsed .engagement-toast__suffix-mini {
          display: inline-block;
          font-size: 11px;
          color: rgba(255,255,255,.6);
          margin-left: 6px;
        }
        .engagement-toast__suffix-mini { display: none; }
        .engagement-toast.is-visible {
          opacity: 1;
          transform: translateY(0) scale(1);
          pointer-events: auto;
        }
        .engagement-toast::before {
          content: "";
          position: absolute;
          inset: 0;
          background: radial-gradient(ellipse 70% 100% at 0% 0%, rgba(124,92,255,.18), transparent 60%);
          pointer-events: none;
        }
        .engagement-toast::after {
          content: "";
          position: absolute;
          left: 0; right: 0; top: 0;
          height: 1px;
          background: linear-gradient(90deg, transparent, rgba(255,255,255,.4), transparent);
          background-size: 200% 100%;
          animation: et-shimmer 6s linear infinite;
        }
        .engagement-toast__close {
          position: absolute;
          top: 2px; right: 2px;
          width: 36px; height: 36px;
          display: inline-flex; align-items: center; justify-content: center;
          border-radius: 8px;
          background: transparent;
          border: none;
          color: rgba(255,255,255,.5);
          cursor: pointer;
          transition: background .15s, color .15s;
          padding: 0;
          z-index: 4;
        }
        .engagement-toast__close:hover {
          background: rgba(255,255,255,.10);
          color: #fff;
        }
        .engagement-toast__pulse-wrap {
          position: relative;
          flex-shrink: 0;
          width: 36px; height: 36px;
          margin-top: 2px;
          display: flex; align-items: center; justify-content: center;
        }
        .engagement-toast__pulse-ring {
          position: absolute; inset: 0;
          border-radius: 50%;
          border: 1.5px solid ${A};
          animation: et-ring 1.8s ease-out infinite;
          transform-origin: center;
        }
        .engagement-toast__pulse {
          width: 12px; height: 12px;
          border-radius: 50%;
          background: ${A};
          box-shadow: 0 0 12px ${A};
          animation: et-pulse 1.4s ease-in-out infinite;
        }
        .engagement-toast__count {
          font-family: ${T.fDisplay};
          font-size: 32px;
          font-weight: 700;
          letter-spacing: -0.025em;
          color: #fff;
          line-height: 1;
          font-variant-numeric: tabular-nums;
          display: inline-block;
        }
        .engagement-toast__people {
          font-family: ${T.fDisplay};
          font-size: 22px;
          font-weight: 600;
          letter-spacing: -0.015em;
          color: rgba(255,255,255,.92);
          line-height: 1;
          margin-left: 8px;
        }
        .engagement-toast__supp {
          display: block;
          margin-top: 8px;
          font-size: 12.5px;
          line-height: 1.45;
          color: rgba(255,255,255,.6);
          font-family: ${T.fBody};
        }
        .engagement-toast__suffix {
          font-size: 13px;
          color: rgba(255,255,255,.65);
          line-height: 1.4;
          margin-left: 8px;
        }
        .engagement-toast__cta {
          display: inline-flex; align-items: center; gap: 6px;
          margin-top: 10px;
          background: none; border: none; padding: 0;
          font: inherit; cursor: pointer;
          color: #c8b6f5;
          font-size: 13px; font-weight: 600;
          font-family: ${T.fBody};
        }
        .engagement-toast__cta:hover { text-decoration: underline; text-underline-offset: 3px; }
        .engagement-toast__eyebrow {
          font-size: 10px; font-weight: 700;
          color: #c8b6f5;
          letter-spacing: .14em; text-transform: uppercase;
          margin-bottom: 8px;
          display: flex; align-items: center; gap: 6px;
        }
      `}</style>
      <div
        className={
        "engagement-toast" + (
        show ? " is-visible" : "") + (
        collapsed && !hover ? " is-collapsed" : "")
        }
        role="status"
        aria-live="polite"
        onMouseEnter={() => setHover(true)}
        onMouseLeave={() => setHover(false)}>
        
        <button
          className="engagement-toast__close"
          aria-label="Dismiss"
          onClick={() => setDismissed(true)}
          type="button">
          
          <svg width="11" height="11" viewBox="0 0 12 12" fill="none">
            <path d="M2 2 L10 10 M10 2 L2 10" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" />
          </svg>
        </button>
        <div className="engagement-toast__pulse-wrap" aria-hidden="true">
          <div className="engagement-toast__pulse-ring" />
          <div className="engagement-toast__pulse" />
        </div>
        <div style={{ flex: 1, minWidth: 0, position: "relative", zIndex: 1 }}>
          <div className="engagement-toast__eyebrow">
            Live · Right now
          </div>
          <div style={{ display: "flex", alignItems: "baseline", flexWrap: "wrap" }}>
            <span className="engagement-toast__count">{count.toLocaleString()}+</span>
            <span className="engagement-toast__people">People</span>
            <span className="engagement-toast__suffix-mini">live now</span>
          </div>
          <div className="engagement-toast__supp engagement-toast__suffix-full">
            engaging with YachtWay every minute, globally.
          </div>
          <button
            type="button"
            className="engagement-toast__cta"
            onClick={() => {
              const target = document.getElementById("configure");
              if (target) {
                const top = target.getBoundingClientRect().top + window.scrollY - 80;
                window.scrollTo({ top, behavior: "smooth" });
              }
            }}>
            
            Do they see your listings?
            <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
              <path d="M5 12h14M13 5l7 7-7 7" />
            </svg>
          </button>
        </div>
      </div>
    </>);

};

// ── Shared deal store ──────────────────────────────────────────────
//    Lightweight pub/sub on window so the §2 cost calculator can hand
//    its values (dealership name, broker seats, current monthly spend)
//    forward to the §6 configurator and the proposal PDF without
//    threading props through twenty components.
(() => {
  if (typeof window === "undefined") return;
  if (window.__YW_DEAL) return;
  const state = { dealership: "", brokers: 3, currentMonthly: 0 };
  const subs = new Set();
  window.__YW_DEAL = {
    get: () => ({ ...state }),
    set: (patch) => {
      Object.assign(state, patch);
      subs.forEach((cb) => { try { cb({ ...state }); } catch (_) {} });
    },
    on: (cb) => { subs.add(cb); return () => subs.delete(cb); },
  };
})();

// ── Cost Calculator (§2) ───────────────────────────────────────────
//    "What you are paying right now." Three inputs (dealership name,
//    broker seats, monthly cost). One big output: annualized spend
//    rendered as a typographic counter, plus a CTA that scrolls to
//    the configurator and seeds it with the entered values.
const CostCalculator = ({ T, A, AOnDark, glow, tint, rgba }) => {
  const [dealership, setDealership] = useState("");
  const [brokers, setBrokers] = useState(3);
  const [monthly, setMonthly] = useState(2500);
  // Region detection mirrors the configurator below, used only to pick
  // the currency + per-seat price so the savings line stays honest.
  const isEU = (typeof navigator !== "undefined" &&
    /^(de|fr|es|it|nl|pt|pl|sv|fi|da|no|cs|hu|ro|bg|hr|sk|sl|et|lv|lt|el|ga|mt)/i.test(
      navigator.language || ""
    ));
  const seatPrice = isEU ? 12 : 19;
  const currency = isEU ? "€" : "$";
  // When the slider hits its 10k ceiling, expose a free-form numeric
  // input so dealers with bigger spend can enter their actual figure.
  const [customMode, setCustomMode] = useState(false);
  const [customStr, setCustomStr] = useState("");
  useEffect(() => {
    if (window.__YW_DEAL) {
      window.__YW_DEAL.set({ dealership, brokers, currentMonthly: monthly });
    }
  }, [dealership, brokers, monthly]);
  const annual = monthly * 12;
  const [shownAnnual, setShownAnnual] = useState(annual);
  useEffect(() => {
    const start = shownAnnual;
    const delta = annual - start;
    if (delta === 0) return;
    const t0 = performance.now();
    let raf;
    const tick = (now) => {
      const t = Math.min(1, (now - t0) / 600);
      const eased = 1 - Math.pow(1 - t, 3);
      setShownAnnual(Math.round(start + delta * eased));
      if (t < 1) raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [annual]);
  const fmt = (n) => `$${Math.round(n).toLocaleString("en-US")}`;
  const handleCta = () => {
    const el = document.getElementById("configure");
    if (el) el.scrollIntoView({ behavior: "smooth", block: "start" });
  };
  return (
    <section id="cost" data-screen-label="02 Cost calculator" style={{
      background: T.bgDark, color: "#fff",
      padding: "120px 32px",
      borderTop: "1px solid rgba(255,255,255,.06)",
      scrollMarginTop: 80,
    }}>
      <div style={{ maxWidth: 1280, margin: "0 auto" }}>
        <div style={{ marginBottom: 56, maxWidth: 880 }}>
          <div style={{
            fontSize: 13, fontWeight: 600, color: AOnDark,
            textTransform: "uppercase", letterSpacing: ".14em", marginBottom: 16,
          }}>What you are paying for it</div>
          <h2 style={{
            fontFamily: T.fDisplay, fontSize: "clamp(40px, 5.5vw, 80px)",
            fontWeight: 700, letterSpacing: "-0.035em", lineHeight: 1.0,
            margin: 0, color: "#fff",
          }}>
            Free to list.<br/>
            <span style={{ color: "rgba(255,255,255,.45)" }}>Pay for what you need.</span>
          </h2>
          <div style={{
            marginTop: 24, padding: "16px 20px",
            background: "rgba(255,255,255,.04)",
            border: "1px solid rgba(255,255,255,.08)",
            borderRadius: 12,
            fontSize: 14, color: "rgba(255,255,255,.75)",
            lineHeight: 1.55, fontFamily: T.fBody, maxWidth: 720,
          }}>
            <span style={{ color: "#fff", fontWeight: 600 }}>Listings on YachtWay are always free.</span> The numbers below are about <span style={{ color: "#fff" }}>optional services</span>, broker tools, contracts, websites, and API feeds.
          </div>
        </div>
        <div className="cc-grid" style={{
          display: "grid",
          gridTemplateColumns: "minmax(0, 1.05fr) minmax(0, 1fr)",
          gap: 56, alignItems: "stretch",
        }}>
          <div style={{ display: "flex", flexDirection: "column", gap: 36 }}>
            <div>
              <label style={{
                fontSize: 11, fontWeight: 700, color: "rgba(255,255,255,.55)",
                textTransform: "uppercase", letterSpacing: ".18em", display: "block",
                marginBottom: 12,
              }}>Dealership name</label>
              <input
                value={dealership}
                onChange={(e) => setDealership(e.target.value)}
                placeholder="Your Dealership name"
                style={{
                  width: "100%", background: "transparent", border: "none",
                  borderBottom: "1px solid rgba(255,255,255,.18)",
                  fontFamily: T.fDisplay, fontSize: 32, fontWeight: 600,
                  letterSpacing: "-0.02em", color: "#fff", padding: "10px 0",
                  outline: "none", transition: "border-color .15s ease",
                }}
                onFocus={(e) => { e.target.style.borderBottomColor = A; }}
                onBlur={(e) => { e.target.style.borderBottomColor = "rgba(255,255,255,.18)"; }}
              />
            </div>
            <div>
              <label style={{
                fontSize: 11, fontWeight: 700, color: "rgba(255,255,255,.55)",
                textTransform: "uppercase", letterSpacing: ".18em", display: "block",
                marginBottom: 12,
              }}>Broker seats</label>
              <div style={{ display: "flex", alignItems: "center", gap: 18,
                borderBottom: "1px solid rgba(255,255,255,.18)", paddingBottom: 10 }}>
                <button onClick={() => setBrokers(Math.max(1, brokers - 1))}
                  aria-label="Decrease broker seats"
                  style={{
                    width: 40, height: 40, borderRadius: 20,
                    background: "rgba(255,255,255,.06)",
                    border: "1px solid rgba(255,255,255,.16)",
                    color: "#fff", fontSize: 20, fontWeight: 400, cursor: "pointer",
                    display: "flex", alignItems: "center", justifyContent: "center",
                    lineHeight: 1, padding: 0,
                  }}>−</button>
                <input
                  type="text"
                  inputMode="numeric"
                  value={brokers}
                  onChange={(e) => {
                    const raw = e.target.value.replace(/[^0-9]/g, "");
                    if (raw === "") { setBrokers(0); return; }
                    const n = Math.min(999, parseInt(raw, 10));
                    setBrokers(isNaN(n) ? 0 : n);
                  }}
                  onBlur={(e) => {
                    if (!e.target.value || parseInt(e.target.value, 10) < 1) setBrokers(1);
                  }}
                  aria-label="Broker seat count"
                  style={{
                    fontFamily: T.fDisplay, fontSize: 40, fontWeight: 600,
                    letterSpacing: "-0.02em", color: "#fff", minWidth: 64,
                    width: 80, textAlign: "center", fontVariantNumeric: "tabular-nums",
                    background: "transparent", border: "none", outline: "none",
                    padding: 0,
                  }}
                />
                <button onClick={() => setBrokers(Math.min(99, brokers + 1))}
                  aria-label="Increase broker seats"
                  style={{
                    width: 40, height: 40, borderRadius: 20,
                    background: "rgba(255,255,255,.06)",
                    border: "1px solid rgba(255,255,255,.16)",
                    color: "#fff", fontSize: 20, fontWeight: 400, cursor: "pointer",
                    display: "flex", alignItems: "center", justifyContent: "center",
                    lineHeight: 1, padding: 0,
                  }}>+</button>
                <div style={{ flex: 1 }} />
                <div style={{ fontSize: 13, color: "rgba(255,255,255,.55)", textAlign: "right", lineHeight: 1.35 }}>
                  On YachtWay that is <span style={{ color: "#fff", fontWeight: 600, fontVariantNumeric: "tabular-nums" }}>{currency}{(brokers * seatPrice).toLocaleString("en-US")}/mo</span>
                  <div style={{ fontSize: 11, color: "rgba(255,255,255,.40)", marginTop: 2 }}>
                    {currency}{seatPrice}/seat
                  </div>
                </div>
              </div>
            </div>
            <div>
              <div style={{ display: "flex", alignItems: "baseline", justifyContent: "space-between",
                marginBottom: 12 }}>
                <label style={{
                  fontSize: 11, fontWeight: 700, color: "rgba(255,255,255,.55)",
                  textTransform: "uppercase", letterSpacing: ".18em",
                }}>What you pay today on legacy platforms, per month</label>
                <div style={{
                  fontFamily: T.fDisplay, fontSize: 32, fontWeight: 600,
                  color: "#fff", letterSpacing: "-0.02em",
                  fontVariantNumeric: "tabular-nums",
                }}>{fmt(monthly)}</div>
              </div>
              <input type="range" min={0} max={10000} step={100}
                value={Math.min(monthly, 10000)}
                onChange={(e) => {
                  const v = parseInt(e.target.value, 10);
                  // Schedule the heavy state update on next frame so the
                  // slider thumb stays glued to the cursor instead of
                  // waiting for the downstream React subtree to re-render.
                  if (window.__monthlyRaf) cancelAnimationFrame(window.__monthlyRaf);
                  window.__monthlyRaf = requestAnimationFrame(() => {
                    setMonthly(v);
                    if (v >= 10000) {
                      setCustomMode(true);
                      setCustomStr(String(v));
                    } else if (customMode) {
                      setCustomMode(false);
                    }
                  });
                }}
                className="cc-slider"
                style={{ width: "100%", accentColor: A }}
              />
              <div style={{ display: "flex", justifyContent: "space-between",
                marginTop: 10, fontSize: 12, color: "rgba(255,255,255,.40)" }}>
                <span>$0</span>
                <span>$5,000</span>
                <span style={{
                  cursor: "pointer",
                  color: customMode ? A : "rgba(255,255,255,.40)",
                  textDecoration: customMode ? "none" : "underline",
                  textUnderlineOffset: 3,
                }} onClick={() => {
                  setCustomMode(true);
                  setCustomStr(monthly >= 10000 ? String(monthly) : "");
                }}>$10,000+</span>
              </div>
              {customMode && (
                <div style={{
                  marginTop: 18, paddingTop: 18,
                  borderTop: "1px dashed rgba(255,255,255,.14)",
                  display: "flex", alignItems: "center", gap: 14,
                }}>
                  <label style={{
                    fontSize: 11, fontWeight: 700, color: "rgba(255,255,255,.55)",
                    textTransform: "uppercase", letterSpacing: ".18em",
                    whiteSpace: "nowrap",
                  }}>Enter exact amount</label>
                  <div style={{ display: "flex", alignItems: "center",
                    borderBottom: `1px solid ${A}`, paddingBottom: 4, flex: 1 }}>
                    <span style={{
                      fontFamily: T.fDisplay, fontSize: 24, fontWeight: 600,
                      color: "rgba(255,255,255,.55)", marginRight: 4,
                    }}>$</span>
                    <input
                      type="text" inputMode="numeric" autoFocus
                      value={customStr ? parseInt(customStr, 10).toLocaleString("en-US") : ""}
                      onChange={(e) => {
                        const raw = e.target.value.replace(/[^0-9]/g, "");
                        setCustomStr(raw);
                        const n = parseInt(raw, 10);
                        if (!isNaN(n)) setMonthly(n);
                        else if (raw === "") setMonthly(0);
                      }}
                      placeholder="15,000"
                      style={{
                        flex: 1, background: "transparent", border: "none",
                        fontFamily: T.fDisplay, fontSize: 24, fontWeight: 600,
                        letterSpacing: "-0.01em", color: "#fff",
                        outline: "none", padding: 0,
                        fontVariantNumeric: "tabular-nums",
                      }}
                    />
                    <span style={{
                      fontSize: 13, color: "rgba(255,255,255,.45)",
                    }}>/mo</span>
                  </div>
                  <button onClick={() => {
                    setCustomMode(false);
                    setMonthly(Math.min(monthly, 10000));
                  }} style={{
                    background: "transparent", border: "none",
                    color: "rgba(255,255,255,.45)", fontSize: 13,
                    cursor: "pointer", padding: "4px 8px",
                  }}>Use slider</button>
                </div>
              )}
            </div>
          </div>
          <div style={{
            background: "rgba(255,255,255,.025)",
            border: "1px solid rgba(255,255,255,.08)",
            borderRadius: 20, padding: "44px 40px",
            display: "flex", flexDirection: "column", justifyContent: "space-between",
            minHeight: 380,
            minWidth: 0,
          }}>
            <div>
              <div style={{
                fontSize: 11, fontWeight: 700, color: "rgba(255,255,255,.55)",
                textTransform: "uppercase", letterSpacing: ".18em", marginBottom: 18,
              }}>{dealership ? `${dealership} pays today` : "You pay today"}</div>
              <div style={{
                fontFamily: T.fDisplay,
                // Scale the hero number by digit count so 7-digit values
                // ($1M+) do not overflow the card on narrow viewports.
                fontSize: shownAnnual >= 10000000
                  ? "clamp(40px, 5.5vw, 76px)"
                  : shownAnnual >= 1000000
                    ? "clamp(48px, 6.8vw, 92px)"
                    : "clamp(64px, 9vw, 120px)",
                fontWeight: 700,
                letterSpacing: "-0.045em", lineHeight: 0.9, color: "#fff",
                fontVariantNumeric: "tabular-nums",
                wordBreak: "keep-all",
              }}>{fmt(shownAnnual)}</div>
              <div style={{
                fontSize: 18, color: "rgba(255,255,255,.55)", marginTop: 10,
                fontFamily: T.fBody,
              }}>per year to legacy platforms, listings, seats, and add-ons across nine vendors.</div>
              {(() => {
                // Potential savings = the dealer's actual current annual
                // spend (what they typed in / dragged) minus what they
                // would pay on YachtWay for the same seat count. So if a
                // dealer pays $5,000/mo today (= $60K/yr) with 8 brokers,
                // their annual savings is $60K − (8 × $19 × 12) = $58,176.
                // Drives directly off the inputs above instead of the
                // synthetic per-broker reference we used before.
                const annualToday = monthly * 12;
                const ywAnnual = brokers * seatPrice * 12;
                const saved = Math.max(0, annualToday - ywAnnual);
                if (saved <= 0 || monthly <= 0) return null;
                return (
                  <div style={{
                    marginTop: 28,
                    background: A,
                    borderRadius: 16,
                    padding: "22px 24px",
                    color: "#fff",
                    boxShadow: `0 18px 48px -16px ${rgba(A, 0.55)}, 0 0 0 1px ${rgba(A, 0.25)}`,
                    fontFamily: T.fBody,
                  }}>
                    <div style={{
                      fontSize: 11, fontWeight: 700,
                      color: "rgba(255,255,255,.75)",
                      textTransform: "uppercase", letterSpacing: ".18em",
                      marginBottom: 6,
                    }}>Potential Savings</div>
                    <div style={{
                      fontFamily: T.fDisplay,
                      fontSize: saved >= 10000000
                        ? "clamp(28px, 3.6vw, 44px)"
                        : saved >= 1000000
                          ? "clamp(34px, 4.4vw, 54px)"
                          : "clamp(44px, 5.4vw, 64px)",
                      fontWeight: 700, color: "#fff",
                      letterSpacing: "-0.035em", lineHeight: 0.95,
                      fontVariantNumeric: "tabular-nums",
                      wordBreak: "keep-all",
                    }}>{fmt(saved)}<span style={{
                      fontSize: ".42em", fontWeight: 600,
                      color: "rgba(255,255,255,.75)", marginLeft: 6,
                      letterSpacing: "-0.01em",
                    }}>/yr</span></div>
                    <div style={{
                      fontSize: 13, color: "rgba(255,255,255,.85)",
                      marginTop: 10, lineHeight: 1.5, fontWeight: 500,
                    }}>
                      {fmt(monthly * 12)}/yr today (legacy) − {fmt(brokers * seatPrice * 12)}/yr on YachtWay ({brokers} seat{brokers === 1 ? "" : "s"} × {fmt(seatPrice)}/mo × 12). Build your real plan below for the exact number.
                    </div>
                  </div>
                );
              })()}
            </div>
            <div style={{ marginTop: 32 }}>
              <div style={{
                fontSize: 14, color: "rgba(255,255,255,.65)",
                marginBottom: 18, fontFamily: T.fBody, lineHeight: 1.5,
              }}>
                Build a full YachtWay plan with add-ons, offices, and LIVE, see
                the itemized breakdown side-by-side.
              </div>
              <button onClick={handleCta} style={{
                background: "#fff", color: "#000", border: "none", borderRadius: 999,
                padding: "16px 28px", fontSize: 15, fontWeight: 600,
                cursor: "pointer", fontFamily: T.fBody, letterSpacing: "-0.005em",
                display: "inline-flex", alignItems: "center", gap: 10,
              }}>
                Build my plan
                <span style={{ fontSize: 18, lineHeight: 1 }}>→</span>
              </button>
            </div>
          </div>
        </div>
      </div>
      <style>{`
        .cc-slider {
          -webkit-appearance: none; appearance: none;
          height: 4px; background: rgba(255,255,255,.12);
          border-radius: 2px; outline: none;
        }
        .cc-slider::-webkit-slider-thumb {
          -webkit-appearance: none; appearance: none;
          width: 22px; height: 22px; border-radius: 50%;
          background: ${A}; border: 3px solid #fff; cursor: pointer;
          box-shadow: 0 2px 8px rgba(0,0,0,.4);
        }
        .cc-slider::-moz-range-thumb {
          width: 22px; height: 22px; border-radius: 50%;
          background: ${A}; border: 3px solid #fff; cursor: pointer;
          box-shadow: 0 2px 8px rgba(0,0,0,.4);
        }
        @media (max-width: 900px) {
          .cc-grid { grid-template-columns: 1fr !important; gap: 40px !important; }
        }
      `}</style>
    </section>
  );
};

// ── Reach numbers strip, collapsed credibility footer to §4
//    (the buyer journey). One row of stats, no expandable cards, no
//    bar charts. The full sourced detail is still available on hover. ──
const ReachNumbersStrip = ({ T, A, AOnDark, glow, tint, rgba }) => {
  // 5 metrics, terse copy. These were previously expanding cards; here
  // they are plain typographic columns separated by hairlines.
  const STATS = [
    { v: "27.4K", l: "Decision-maker visits/mo", note: "Verified dealers, brokers, and buyers — no tire-kickers." },
    { v: "DA 27", l: "Editorial authority", note: "Equal authority to platforms 5× our age. Zero spam." },
    { v: "470",   l: "Editorial backlinks", note: "All-organic, all-editorial. 123× fewer than Yachtr — zero spam links." },
    { v: "2.18M", l: "Social audience", note: "IG, YouTube, FB, TikTok combined." },
    { v: "47",    l: "Countries reached", note: "Buyers in every major yachting market." },
  ];
  return (
    <section data-screen-label="05 Reach in numbers" style={{
      background: T.bgDark,
      color: "#fff",
      padding: "72px 32px",
      borderTop: "1px solid rgba(255,255,255,.06)",
      borderBottom: "1px solid rgba(255,255,255,.06)",
    }}>
      <div style={{ maxWidth: 1280, margin: "0 auto" }}>
        <div style={{
          display: "flex", alignItems: "baseline", justifyContent: "space-between",
          gap: 18, marginBottom: 28, flexWrap: "wrap",
        }}>
          <div>
            <div style={{
              fontSize: 11, fontWeight: 700, color: AOnDark,
              textTransform: "uppercase", letterSpacing: ".18em", marginBottom: 8,
            }}>Reach, in numbers</div>
            <div style={{
              fontFamily: T.fDisplay, fontSize: "clamp(20px, 2.2vw, 28px)",
              fontWeight: 600, letterSpacing: "-0.02em", color: "#fff",
              lineHeight: 1.2, maxWidth: 720,
            }}>
              The credibility footer to the journey above , 
              <span style={{ color: "rgba(255,255,255,.55)" }}> the audience proof, in one line.</span>
            </div>
          </div>
          <div style={{
            fontSize: 12, color: "rgba(255,255,255,.45)", letterSpacing: "-0.005em",
            maxWidth: 320,
          }}>Sourced from Ahrefs, SEMrush, and the platform's own analytics.</div>
        </div>
        <div style={{
          display: "grid",
          gridTemplateColumns: `repeat(${STATS.length}, minmax(0, 1fr))`,
          borderTop: "1px solid rgba(255,255,255,.10)",
          borderBottom: "1px solid rgba(255,255,255,.10)",
        }} className="rns-grid">
          {STATS.map((s, i) => (
            <div key={i} title={s.note} style={{
              padding: "28px 22px",
              borderRight: i < STATS.length - 1 ? "1px solid rgba(255,255,255,.10)" : "none",
              fontFamily: T.fBody,
            }} className="rns-cell">
              <div style={{
                fontFamily: T.fDisplay, fontSize: "clamp(32px, 3.4vw, 44px)",
                fontWeight: 700, letterSpacing: "-0.03em", lineHeight: 1.0,
                color: "#fff", fontVariantNumeric: "tabular-nums",
                marginBottom: 6,
              }}>{s.v}</div>
              <div style={{
                fontSize: 12, color: "rgba(255,255,255,.55)", fontWeight: 500,
                letterSpacing: "-0.005em",
              }}>{s.l}</div>
            </div>
          ))}
        </div>
      </div>
      <style>{`
        @media (max-width: 900px) {
          .rns-grid { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }
          .rns-cell { border-right: none !important; border-bottom: 1px solid rgba(255,255,255,.10); }
          .rns-cell:nth-child(odd) { border-right: 1px solid rgba(255,255,255,.10) !important; }
          .rns-cell:nth-last-child(-n+2) { border-bottom: none; }
        }
      `}</style>
    </section>
  );
};

const DirectionD = () => {
  const useState = useStateD;
  const useRef = useRefD;

  const [hoverFeature, setHoverFeature] = useState(-1);
  const [activeJourney, setActiveJourney] = useState(0);
  const [activeMetric, setActiveMetric] = useState(0);
  const [navScrolled, setNavScrolled] = useState(false);
  // Region toggle for the comparison table (US / EU). Independent from the
  // configurator's region so a US dealer can spot-check EU pricing without
  // resetting their plan build.
  const [compareRegion, setCompareRegion] = useState("us");
  const cost = useCostEstimator();
  const cpl = useCPL();
  const journeyTrackRef = useRef(null);

  // Track whether the user has scrolled past the hero so the nav can flip
  // from solid black (clean editorial header at the top) to a translucent
  // glass that adapts to whatever section is behind it.
  React.useEffect(() => {
    const onScroll = () => setNavScrolled(window.scrollY > 24);
    onScroll();
    window.addEventListener("scroll", onScroll, { passive: true });
    return () => window.removeEventListener("scroll", onScroll);
  }, []);

  // Scrollspy: track which section is currently centered in the viewport so
  // the nav can underline the matching link.
  const [activeSection, setActiveSection] = useState("");
  // Mobile-nav drawer open state. The drawer is rendered absolutely-positioned
  // and gated by [data-open] on its root, while <body> gets [data-yw-drawer]
  // so we can lock page scroll while it is up.
  const [navOpen, setNavOpen] = useState(false);
  React.useEffect(() => {
    document.body.dataset.ywDrawer = navOpen ? "true" : "false";
    return () => {delete document.body.dataset.ywDrawer;};
  }, [navOpen]);
  React.useEffect(() => {
    // Note: "live" appears twice, once for the desktop cinematic, once for
    // the mobile-native version (id="live-mobile"). Whichever is visible at
    // the current viewport drives the LIVE highlight; the other is
    // display:none and never crosses the probe line. We normalise both ids
    // back to "live" so the nav button stays correctly highlighted.
    const ids = ["cost", "journey", "compare", "members", "services", "pricing", "configure", "security"];
    const isVisible = (el) => {
      if (!el) return false;
      const r = el.getBoundingClientRect();
      return r.width > 0 && r.height > 0;
    };
    const normalise = (id) => id === "live-mobile" ? "live" : id;
    const onScroll = () => {
      // Re-resolve elements every scroll. Sections may be added/removed
      // by responsive mounts (live vs live-mobile), and stale references
      // would silently miss matches.
      const els = ids.map((id) => document.getElementById(id)).filter(isVisible);
      if (!els.length) return;
      const probe = window.innerHeight * 0.35;
      // Bottom-of-page edge case: if the user has scrolled to within
      // ~80px of the bottom, force the LAST visible section active.
      // The probe-based test fails here because no section's bottom
      // is past the probe, every visible section's bottom is below
      // it (or above, scrolled past). The last visible section is
      // what the user is reading.
      const nearBottom = window.innerHeight + window.scrollY >=
      document.documentElement.scrollHeight - 80;
      if (nearBottom) {
        setActiveSection(normalise(els[els.length - 1].id));
        return;
      }
      // Otherwise, find the section whose top has crossed the probe
      // line and whose bottom is still below it (i.e., the section
      // currently spanning the probe).
      let current = "";
      for (const el of els) {
        const r = el.getBoundingClientRect();
        if (r.top <= probe && r.bottom > probe) {current = normalise(el.id);break;}
      }
      // Fallback: pick the LAST section whose top has crossed the probe.
      if (!current) {
        for (const el of els) {
          const r = el.getBoundingClientRect();
          if (r.top <= probe) current = normalise(el.id);
        }
      }
      setActiveSection(current);
    };
    onScroll();
    window.addEventListener("scroll", onScroll, { passive: true });
    window.addEventListener("resize", onScroll);
    return () => {
      window.removeEventListener("scroll", onScroll);
      window.removeEventListener("resize", onScroll);
    };
  }, []);

  // Lead-capture modal that gates the PDF export. We stash the export params
  // when the user clicks "Export PDF Proposal" and only fire the actual export
  // once they submit a valid (non-free-domain) email.
  const [exportModalOpen, setExportModalOpen] = useState(false);
  // Pre-fill the dealership name from the §2 calculator if the user
  // entered one. The modal stays editable.
  const [exportName, setExportName] = useState(() => {
    try { return (window.__YW_DEAL && window.__YW_DEAL.get().dealership) || ""; }
    catch (_) { return ""; }
  });
  const [exportEmail, setExportEmail] = useState("");
  // Keep exportName synced with §2 dealership entries until the user types
  // into the export field directly. We track that via a ref.
  const exportNameTouchedRef = useRef(false);
  useEffect(() => {
    if (!window.__YW_DEAL) return;
    return window.__YW_DEAL.on((s) => {
      if (!exportNameTouchedRef.current && s.dealership) {
        setExportName(s.dealership);
      }
    });
  }, []);
  const [exportError, setExportError] = useState("");
  const pendingExportRef = useRef(null);

  const FREE_EMAIL_DOMAINS = [
  "gmail.com", "googlemail.com", "yahoo.com", "yahoo.co.uk", "yahoo.fr", "yahoo.de", "yahoo.it", "yahoo.es",
  "hotmail.com", "hotmail.co.uk", "hotmail.fr", "hotmail.it", "outlook.com", "live.com", "msn.com",
  "aol.com", "icloud.com", "me.com", "mac.com", "proton.me", "protonmail.com", "gmx.com", "gmx.de",
  "mail.com", "yandex.com", "yandex.ru", "zoho.com"];


  const validateExportForm = () => {
    const name = exportName.trim();
    const email = exportEmail.trim().toLowerCase();
    if (!name) return "Please enter your name.";
    if (!email) return "Please enter your work email.";
    // Basic shape: something@something.tld
    if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) return "That does not look like a valid email.";
    const domain = email.split("@")[1];
    if (FREE_EMAIL_DOMAINS.includes(domain)) {
      return "Please use your work email, free email providers are not accepted.";
    }
    return "";
  };

  const handleExportSubmit = async (e) => {
    if (e && e.preventDefault) e.preventDefault();
    const err = validateExportForm();
    if (err) {setExportError(err);return;}
    setExportError("");
    const params = pendingExportRef.current;
    if (!params) {setExportModalOpen(false);return;}
    await exportProposalPDF({
      ...params,
      dealerName: exportName.trim(),
      dealerEmail: exportEmail.trim()
    });
    setExportModalOpen(false);
  };

  // ─── Tweaks ─────────────────────────────────────────────────────────────
  const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
    "accent": "#4A2C8A",
    "accentHover": "#3A2070",
    "accentLight": "#4A2C8A",
    "purpleIntensity": 0.35,
    "gradientHeadline": false,
    "animateStats": true
  } /*EDITMODE-END*/;
  const [tweaks, setTweak] = useTweaks(TWEAK_DEFAULTS);

  // hex → rgba helper (handles #rgb and #rrggbb)
  const rgba = (hex, a) => {
    let h = (hex || "#000000").replace("#", "");
    if (h.length === 3) h = h.split("").map((c) => c + c).join("");
    const r = parseInt(h.slice(0, 2), 16) || 0;
    const g = parseInt(h.slice(2, 4), 16) || 0;
    const b = parseInt(h.slice(4, 6), 16) || 0;
    return `rgba(${r}, ${g}, ${b}, ${a})`;
  };

  const T = {
    bg: "#ffffff",
    bgAlt: "#f7f7f8",
    bgDark: "#0a0a0c",
    bgDark2: "#0f0f14",
    fg: "#0a0a0c",
    fgMuted: "#5e5e66",
    fgFaint: "#9a9aa3",
    border: "#ececef",
    borderStrong: "#dcdce0",
    accent: tweaks.accent,
    accentHover: tweaks.accentHover,
    accentLight: tweaks.accentLight,
    fDisplay: "Poppins, var(--font-display, sans-serif)",
    fBody: "Figtree, var(--font-body, sans-serif)",
    radius: 12
  };
  const A = T.accent;
  const AL = T.accentLight;
  // Lightened accent for use as TEXT on dark backgrounds. The brand purple
  // #4A2C8A is too dark to read against near-black, so we lift L* into a
  // legible range while preserving hue. Used wherever an eyebrow/label/heading
  // sits on T.bgDark.
  const AOnDark = (() => {
    // Convert hex to HSL, bump lightness to ~72%, return as hex.
    const hex = (T.accent || "#4A2C8A").replace("#", "");
    const r = parseInt(hex.slice(0,2), 16) / 255;
    const g = parseInt(hex.slice(2,4), 16) / 255;
    const b = parseInt(hex.slice(4,6), 16) / 255;
    const max = Math.max(r,g,b), min = Math.min(r,g,b);
    let h = 0, s = 0; const l = (max + min) / 2;
    if (max !== min) {
      const d = max - min;
      s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
      switch (max) {
        case r: h = (g - b) / d + (g < b ? 6 : 0); break;
        case g: h = (b - r) / d + 2; break;
        case b: h = (r - g) / d + 4; break;
      }
      h /= 6;
    }
    // Force lightness up; keep saturation healthy.
    const L = 0.72, S = Math.max(s, 0.55);
    const hue2rgb = (p, q, t) => {
      if (t < 0) t += 1; if (t > 1) t -= 1;
      if (t < 1/6) return p + (q - p) * 6 * t;
      if (t < 1/2) return q;
      if (t < 2/3) return p + (q - p) * (2/3 - t) * 6;
      return p;
    };
    const q = L < 0.5 ? L * (1 + S) : L + S - L * S;
    const p = 2 * L - q;
    const R = Math.round(hue2rgb(p, q, h + 1/3) * 255);
    const G = Math.round(hue2rgb(p, q, h) * 255);
    const B = Math.round(hue2rgb(p, q, h - 1/3) * 255);
    return "#" + [R,G,B].map(v => v.toString(16).padStart(2, "0")).join("");
  })();
  const PI = tweaks.purpleIntensity; // 0 (no purple ambience) → 1 (full)
  // glow opacity scales with purple intensity (default 0.55 ≈ original look halved)
  const glow = (a) => rgba(A, a * PI);
  const tint = (a) => rgba(A, a);
  const HeadlineAccent = ({ children }) =>
  <span style={tweaks.gradientHeadline ?
  { background: `linear-gradient(120deg, ${AL}, #fff 65%)`, WebkitBackgroundClip: "text", WebkitTextFillColor: "transparent" } :
  { color: "#fff" }
  }>{children}</span>;


  const scrollJourney = (dir) => {
    if (!journeyTrackRef.current) return;
    const w = journeyTrackRef.current.clientWidth;
    journeyTrackRef.current.scrollBy({ left: dir * w * 0.85, behavior: "smooth" });
  };

  return (
    <div style={{ background: T.bgDark, color: T.fg, fontFamily: T.fBody, WebkitFontSmoothing: "antialiased" }}>
      <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Poppins:wght@500;600;700;800&family=Figtree:wght@400;500;600;700&display=swap" />
      <style>{`
        .ed-link { color: inherit; text-decoration: none; transition: color .15s; position: relative; padding-bottom: 4px; }
        .ed-link:hover { color: ${T.fg}; }
        .ed-link-light:hover { color: #fff; }
        .ed-link.is-active { color: #fff; }
        .ed-link.is-active::after {
          content: ""; position: absolute; left: 0; right: 0; bottom: -2px; height: 2px;
          background: #fff;
          border-radius: 2px;
          box-shadow: 0 0 12px rgba(255,255,255,.55);
          animation: ed-underline-in .35s cubic-bezier(.4,0,.2,1) both;
        }
        @keyframes ed-underline-in {
          from { transform: scaleX(0); transform-origin: left; opacity: 0; }
          to   { transform: scaleX(1); opacity: 1; }
        }
        /* Closing headline, staggered line reveal triggered when section enters viewport.
           Each .ch-inner sits inside a .ch-line clip mask, lifts in from below + fades. */
        .closing-headline .ch-line {
          display: inline-block;
          overflow: hidden;
          padding-bottom: 0.08em;
          vertical-align: bottom;
        }
        .closing-headline .ch-inner {
          display: inline-block;
          transform: translateY(110%);
          opacity: 0;
          transition:
            transform 1.05s cubic-bezier(.16,.84,.3,1),
            opacity   .9s  cubic-bezier(.16,.84,.3,1);
        }
        .closing-headline.is-revealed .ch-line:nth-of-type(1) .ch-inner { transition-delay: 0ms;   transform: translateY(0); opacity: 1; }
        .closing-headline.is-revealed .ch-line:nth-of-type(2) .ch-inner { transition-delay: 140ms; transform: translateY(0); opacity: 1; }
        .closing-headline.is-revealed .ch-line:nth-of-type(3) .ch-inner { transition-delay: 280ms; transform: translateY(0); opacity: 1; }
        .closing-headline.is-revealed .ch-line:nth-of-type(4) .ch-inner { transition-delay: 420ms; transform: translateY(0); opacity: 1; }
        @media (prefers-reduced-motion: reduce) {
          .closing-headline .ch-inner { transform: none; opacity: 1; transition: none; }
        }
        .ed-btn-primary { background: ${T.accent}; color: #fff; transition: background .15s, transform .12s, box-shadow .2s; white-space: nowrap; }
        .ed-btn-primary:hover { background: ${T.accentHover}; transform: translateY(-1px); box-shadow: 0 10px 24px -8px ${rgba(A, .55)}; }
        .ed-btn-ghost { background: transparent; border: 1px solid ${T.border}; color: ${T.fg}; transition: border-color .15s, background .15s; white-space: nowrap; }
        .ed-btn-ghost:hover { border-color: ${T.borderStrong}; background: #fafafa; }
        .ed-btn-ghost-dark { background: rgba(255,255,255,.04); border: 1px solid rgba(255,255,255,.14); color: #fff; transition: background .15s, border-color .15s; white-space: nowrap; }
        .ed-btn-ghost-dark:hover { background: rgba(255,255,255,.08); border-color: rgba(255,255,255,.24); }
        .ed-card { transition: border-color .15s, transform .15s, box-shadow .2s; }
        .ed-card:hover { border-color: ${T.borderStrong}; transform: translateY(-2px); box-shadow: 0 14px 32px -12px rgba(0,0,0,.1); }
        .ed-card-dark { transition: background .2s, border-color .2s, transform .15s; }
        .ed-card-dark:hover { background: rgba(255,255,255,.06); border-color: rgba(255,255,255,.18); transform: translateY(-2px); }
        .ed-row:hover { background: #fafafa; }
        .ed-input:focus { border-color: ${T.accent}; box-shadow: 0 0 0 3px ${rgba(A, .15)}; outline: none; }
        .ed-tab[data-active="true"] { background: ${T.fg}; color: #fff; }
        .ed-tab:hover:not([data-active="true"]) { background: #f0f0f1; }
        .ed-snap { scroll-snap-type: x mandatory; }
        .ed-snap > * { scroll-snap-align: start; }
        .ed-no-scrollbar::-webkit-scrollbar { display: none; }
        .ed-no-scrollbar { scrollbar-width: none; }
        .ed-grid-bg {
          background-image:
            linear-gradient(rgba(255,255,255,.04) 1px, transparent 1px),
            linear-gradient(90deg, rgba(255,255,255,.04) 1px, transparent 1px);
          background-size: 64px 64px;
        }
      `}</style>

      {/* ── NAV (sticky, blurred) ────────────────────────────────────── */}
      <nav style={{
        position: "sticky", top: 0, zIndex: 50,
        display: "flex", alignItems: "center", justifyContent: "space-between",
        padding: "14px 32px",
        background: "rgba(20, 20, 24, .42)",
        backdropFilter: "blur(28px) saturate(180%)",
        WebkitBackdropFilter: "blur(28px) saturate(180%)",
        borderBottom: "1px solid rgba(255,255,255,.08)",
        boxShadow: "inset 0 1px 0 rgba(255,255,255,.06)",
        fontSize: 14,
        color: "#fff",
        transition: "background .35s ease"
      }}>
        <div style={{ display: "flex", alignItems: "center", gap: 32 }}>
          <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
            <img src={window.__YW_ASSETS && window.__YW_ASSETS.logoLight || "assets/yachtway-logo-light.png"} alt="YachtWay"
            style={{ width: 216, height: 30, display: "block", objectFit: "contain" }} />
          </div>
          <div style={{ display: "flex", gap: 24, color: "rgba(255,255,255,.78)", fontWeight: 500 }}>
            {[
            ["compare", "Compare"],
            ["members", "Members"],
            ["services", "Services"],
            ["configure", "Pricing"],
            ["security", "Trust"]].
            map(([id, label]) =>
            <a key={id}
            className={`ed-link ed-link-light${activeSection === id ? " is-active" : ""}`}
            href={`#${id}`}>{label}</a>
            )}
          </div>
        </div>
        <div style={{ display: "flex", gap: 8, alignItems: "center" }}>
          <a href="#configure" style={{
            padding: "9px 16px", borderRadius: 8,
            border: "1.5px solid rgba(255,255,255,.55)", color: "#fff",
            background: "transparent",
            fontSize: 13, fontWeight: 700, fontFamily: T.fBody, cursor: "pointer",
            textDecoration: "none", display: "inline-flex", alignItems: "center", gap: 6,
            whiteSpace: "nowrap", letterSpacing: "-0.005em",
            transition: "background .15s, color .15s, border-color .15s"
          }}
          onMouseOver={(e) => {e.currentTarget.style.background = "#fff";e.currentTarget.style.color = "#0a0a0c";e.currentTarget.style.borderColor = "#fff";}}
          onMouseOut={(e) => {e.currentTarget.style.background = "transparent";e.currentTarget.style.color = "#fff";e.currentTarget.style.borderColor = "rgba(255,255,255,.55)";}}>
            Calculate Savings</a>
          <a className="ed-btn-primary" href="http://yachtway.com/sign-up" target="_blank" rel="noopener noreferrer" style={{
            padding: "9px 16px", borderRadius: 8, border: "none",
            fontSize: 13, fontWeight: 600, fontFamily: T.fBody, cursor: "pointer",
            textDecoration: "none", display: "inline-flex", alignItems: "center"
          }}>Become a Member</a>
          {/* Hamburger, visible only on mobile (CSS in mobile.css gates it). */}
          <button
            type="button"
            className="yw-hamb"
            aria-label="Open navigation menu"
            aria-expanded={navOpen}
            onClick={() => setNavOpen(true)}>
            
            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round">
              <line x1="4" y1="7" x2="20" y2="7" />
              <line x1="4" y1="12" x2="20" y2="12" />
              <line x1="4" y1="17" x2="20" y2="17" />
            </svg>
          </button>
        </div>
      </nav>

      {/* ── MOBILE NAV DRAWER ──────────────────────────────────────────
           Rendered always so we can transition the open/close states; the
           [data-open] attr drives the slide+fade. CSS in mobile.css makes
           this a no-op at desktop widths (display rules suppress it). */}
      <div className="yw-drawer" data-open={navOpen} aria-hidden={!navOpen}>
        <div className="yw-drawer__top">
          <img
            src={window.__YW_ASSETS && window.__YW_ASSETS.logoLight || "assets/yachtway-logo-light.png"}
            alt="YachtWay"
            style={{ height: 22, width: "auto", display: "block" }} />
          
          <button
            type="button"
            className="yw-drawer__close"
            aria-label="Close navigation menu"
            onClick={() => setNavOpen(false)}>
            
            <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round">
              <line x1="6" y1="6" x2="18" y2="18" />
              <line x1="6" y1="18" x2="18" y2="6" />
            </svg>
          </button>
        </div>
        <nav className="yw-drawer__links" aria-label="Mobile sections">
          {[
          ["compare", "Compare"],
          ["members", "Members"],
          ["services", "Services"],
          ["configure", "Pricing"],
          ["security", "Trust"]].
          map(([id, label]) =>
          <a key={id} href={`#${id}`} onClick={() => setNavOpen(false)}>{label}</a>
          )}
        </nav>
        <div className="yw-drawer__cta">
          <a className="is-ghost" href="#configure" onClick={() => setNavOpen(false)}>Calculate Savings</a>
          <a className="is-primary" href="http://yachtway.com/sign-up" target="_blank" rel="noopener noreferrer" onClick={() => setNavOpen(false)}>Become a Member</a>
        </div>
      </div>

      {/* ── HERO (DARK editorial) ────────────────────────────────────── */}
      <section style={{
        position: "relative", padding: "72px 32px 80px",
        background: `radial-gradient(ellipse 70% 55% at 75% 30%, ${glow(.32)}, transparent 60%), ${T.bgDark}`,
        color: "#fff", overflow: "hidden"
      }}>
        <div className="ed-grid-bg" style={{
          position: "absolute", inset: 0, opacity: .5,
          maskImage: "radial-gradient(ellipse 60% 70% at 50% 40%, black, transparent 75%)",
          WebkitMaskImage: "radial-gradient(ellipse 60% 70% at 50% 40%, black, transparent 75%)"
        }} />

        {/* ── Background listing-card grid ────────────────────────────────
             Faint outlined skeleton cards tiled across the entire hero. We
             then drop a dark-color overlay layer on top with two radial
             "spotlights" of dark, centered on the H1 and the stat tower, so
             the cards visually disappear behind those zones (positive-space
             overlay rather than a subtractive mask, which is unreliable
             across browsers when chained). The cards live behind the content
             but in front of the dot-grid bg. */}
        <div aria-hidden="true" style={{
          position: "absolute", inset: 0, zIndex: 0,
          pointerEvents: "none", overflow: "hidden"
        }}>
          {/* The card grid itself. We render two copies of the row pattern
               stacked vertically and translate downward for a seamless
               infinite scroll, the way a real listings feed reads online. The
               track is twice as tall as the section, so cards leaving the top
               wrap around from the bottom. */}
          <style>{`
            @keyframes hero-cards-drift {
              0%   { transform: translateY(0); }
              100% { transform: translateY(-50%); }
            }
            .hero-cards-track {
              animation: hero-cards-drift 90s linear infinite;
              will-change: transform;
            }
            @media (prefers-reduced-motion: reduce) {
              .hero-cards-track { animation: none; }
            }
          `}</style>
          {(() => {
            // Side-profile vessel line-art images. Each is a clean white
            // outline on transparent (pre-processed: white background
            // removed, lines inverted to white). Five distinct silhouettes
            // (mystic speedboat, sportfish tower, day-cruiser, flybridge,
            // superyacht) get pseudo-randomly distributed + h-flipped per
            // cell so the grid reads as a fleet of different boats.
            const BOATS = [
            { type: "img", src: "assets/boat-mystic.png", aspect: 2504 / 1664 },
            { type: "img", src: "assets/boat-sportfish.png", aspect: 2576 / 1664 },
            { type: "img", src: "assets/boat-daycruiser.png", aspect: 3722 / 1152 },
            { type: "img", src: "assets/boat-superyacht.png", aspect: 2816 / 1536 },
            { type: "img", src: "assets/boat-classic.png", aspect: 1365 / 768 },
            { type: "img", src: "assets/boat-venus.png", aspect: 2736 / 1568 },
            { type: "img", src: "assets/boat-aria.png", aspect: 2736 / 1536 }];

            // Pseudo-random but deterministic pick + flip per cell, so
            // the pattern is varied across the grid yet stable across
            // renders. We walk a shuffled "deck" of all boat indices , 
            // each row gets its own seeded shuffle, so every consecutive
            // run of N=BOATS.length cells contains all unique boats. Any
            // pick that would repeat the cell directly above or to the
            // left is swapped with the next deck entry, preserving the
            // no-adjacent-duplicates rule without skewing the distribution.
            const COLS = 5;
            const ROWS = 14;
            const TOTAL = COLS * ROWS;
            // Deterministic shuffle: Fisher - Yates seeded by `seed`.
            const shuffleDeck = (seed) => {
              const deck = BOATS.map((_, j) => j);
              let s = (seed * 2654435761 ^ 0x9e3779b9) >>> 0;
              for (let k = deck.length - 1; k > 0; k--) {
                s = (s * 1664525 + 1013904223) >>> 0;
                const r = s % (k + 1);
                [deck[k], deck[r]] = [deck[r], deck[k]];
              }
              return deck;
            };
            const cells = [];
            const decks = [];
            const cursors = [];
            for (let row = 0; row < ROWS; row++) {
              decks.push(shuffleDeck(row + 17));
              cursors.push(0);
            }
            for (let i = 0; i < TOTAL; i++) {
              const col = i % COLS;
              const row = Math.floor(i / COLS);
              const leftIdx = col > 0 ? cells[i - 1].boatIdx : -1;
              const upIdx = row > 0 ? cells[i - COLS].boatIdx : -1;
              const deck = decks[row];
              // Walk the deck; if the next entry collides with above/left,
              // swap it with a later entry in the deck and try again.
              let attempts = 0;
              while (attempts < deck.length) {
                const c = cursors[row] % deck.length;
                const candidate = deck[c];
                if (candidate !== leftIdx && candidate !== upIdx) break;
                // Swap candidate with the entry after it (cyclic) so
                // it gets retried later in the row, not lost.
                const swap = (c + 1) % deck.length;
                [deck[c], deck[swap]] = [deck[swap], deck[c]];
                attempts++;
              }
              const boatIdx = deck[cursors[row] % deck.length];
              cursors[row]++;
              const h = ((row * 73856093) ^ (col * 19349663)) >>> 0;
              const flip = (h & 1) === 1;
              cells.push({ boat: BOATS[boatIdx], boatIdx, flip, key: i });
            }
            return (
              <div className="hero-cards-track" style={{
                position: "absolute", top: "-1%", left: "-2%", right: "-2%",
                height: "202%",
                display: "grid",
                // Card columns and rows scale with viewport width, narrow
                // screens get fewer/smaller cards, wide screens get larger
                // ones, so cards always read at a believable listing size
                // relative to the H1 next to them.
                gridTemplateColumns: "repeat(5, 1fr)",
                gridAutoRows: "clamp(170px, 18vw, 320px)",
                gap: "clamp(8px, 1vw, 18px)",
                opacity: 0.92
              }}>
                {cells.map(({ boat, flip, key }, i) => (i % COLS) < 2 ? null :
                <div key={key} style={{
                  gridColumn: (i % COLS) + 1,
                  borderRadius: 10,
                  border: "1px solid rgba(255,255,255,.13)",
                  background: "linear-gradient(180deg, rgba(255,255,255,.028), rgba(255,255,255,.008))",
                  display: "flex", flexDirection: "column", overflow: "hidden"
                }}>
                    {/* Photo area, with a side-profile boat outline */}
                    <div style={{
                    flex: "0 0 62%",
                    background: "linear-gradient(180deg, rgba(255,255,255,.055), rgba(255,255,255,.018))",
                    borderBottom: "1px solid rgba(255,255,255,.09)",
                    position: "relative",
                    display: "flex", alignItems: "center", justifyContent: "center"
                  }}>
                      {boat.type === "img" ?
                    <img src={(window.__YW_ASSETS && window.__YW_ASSETS[boat.src]) || boat.src} alt="" loading="lazy" style={{
                      width: "94%", height: "auto",
                      maxHeight: "85%", objectFit: "contain",
                      position: "relative", zIndex: 1,
                      transform: flip ? "scaleX(-1)" : "none",
                      // Images are pre-processed to white outlines on
                      // transparent, just dim to keep the sketch-faint
                      // aesthetic of the surrounding cards.
                      opacity: 0.5
                    }} /> :

                    <svg viewBox={boat.vb} style={{
                      width: "82%", height: "70%",
                      position: "relative", zIndex: 1,
                      transform: flip ? "scaleX(-1)" : "none",
                      overflow: "visible"
                    }} fill="none" stroke="rgba(255,255,255,.32)"
                    strokeWidth="1.4" strokeLinejoin="round" strokeLinecap="round">
                          {boat.paths.map((d, j) => <path key={j} d={d} />)}
                        </svg>
                    }
                    </div>
                    {/* Skeleton text rows */}
                    <div style={{ padding: "8px 10px", display: "flex", flexDirection: "column", gap: 5, flex: 1 }}>
                      <div style={{ height: 6, width: "72%", borderRadius: 3, background: "rgba(255,255,255,.14)" }} />
                      <div style={{ height: 5, width: "44%", borderRadius: 3, background: "rgba(255,255,255,.08)" }} />
                      <div style={{ flex: 1 }} />
                      <div style={{ height: 7, width: "38%", borderRadius: 3, background: "rgba(255,255,255,.16)" }} />
                    </div>
                  </div>
                )}
              </div>);

          })()}

          {/* Dark spotlights that hide the cards behind H1 & stats. Each
               radial-gradient goes from the bg color (opaque) at the center
               to fully transparent at the edge. We use the actual dark hero
               color so the cutout reads as the same surface as the section. */}
          <div style={{
            position: "absolute", inset: 0,
            background: [
            // Single spotlight under the hero copy, kills cards behind the H1 + CTA stack.
            `radial-gradient(ellipse 38% 60% at 25% 48%, ${T.bgDark} 0%, ${T.bgDark} 45%, rgba(10,10,12,0.88) 60%, rgba(10,10,12,0.4) 75%, transparent 88%)`,
            // Top + bottom fade so cards melt into the section edges
            `linear-gradient(180deg, ${T.bgDark} 0%, transparent 12%, transparent 84%, ${T.bgDark} 100%)`].
            join(", ")
          }} />
        </div>
        <div style={{ maxWidth: 1280, margin: "0 auto", position: "relative" }}>
          <div>
            <h1 style={{
              fontFamily: T.fDisplay, fontWeight: 700,
              fontSize: 96, lineHeight: 0.95, letterSpacing: "-0.04em",
              margin: 0, marginBottom: 28, color: "#fff"
            }}>
              Stop paying<br />
              <HeadlineAccent>to list</HeadlineAccent> your<br />own inventory.
            </h1>
            <p style={{ fontSize: 22, lineHeight: 1.4, color: "rgba(255,255,255,.7)",
              margin: 0, marginBottom: 36, maxWidth: 580,
              fontFamily: T.fDisplay, fontWeight: 500, letterSpacing: "-0.01em" }}>
              Inventory · Contracts · Media.{" "}
              <span style={{ color: "#fff" }}>All in one place.</span>
            </p>
            <div style={{ display: "flex", gap: 12, alignItems: "center", marginBottom: 28, flexWrap: "wrap" }}>
              <a className="ed-btn-primary" href="http://yachtway.com/sign-up" target="_blank" rel="noopener noreferrer" style={{
                padding: "18px 28px", borderRadius: 12, border: "none",
                fontSize: 16, fontWeight: 600, fontFamily: T.fBody, cursor: "pointer",
                display: "inline-flex", alignItems: "center", gap: 10,
                textDecoration: "none", letterSpacing: "-0.005em"
              }}>Start Free. No Card Required. <Ic.arrow size={16} /></a>
              <a href="#configure" className="ed-btn-ghost-dark" style={{
                padding: "16px 22px", borderRadius: 12,
                fontSize: 14, fontWeight: 600, fontFamily: T.fBody, cursor: "pointer",
                textDecoration: "none", display: "inline-flex", alignItems: "center", gap: 8
              }}>Calculate Your Savings <Ic.arrow size={14} /></a>
            </div>
            {/* Trust band, anchor logos + count.
                Sits in the hero under the CTAs as a horizontal strip. The
                count is the lead element (it is the proof number); the
                logos sit to its right behind a vertical divider, all on a
                single baseline so they read as a quiet honor roll rather
                than a sales banner. */}
            <div className="hero-trust-band" style={{
              marginTop: 56, paddingTop: 28,
              borderTop: "1px solid rgba(255,255,255,.10)",
              display: "flex", alignItems: "center",
              gap: 36, flexWrap: "wrap",
            }}>
              <div style={{
                display: "flex", flexDirection: "column", gap: 6,
                fontFamily: T.fBody,
              }}>
                <div style={{
                  fontSize: 11, fontWeight: 600, letterSpacing: ".18em",
                  textTransform: "uppercase", color: "rgba(255,255,255,.50)",
                }}>Trusted by</div>
                <div style={{
                  display: "flex", alignItems: "baseline", gap: 10,
                  fontFamily: T.fDisplay,
                }}>
                  <span style={{
                    fontSize: 56, fontWeight: 800, color: "#fff",
                    letterSpacing: "-0.035em", lineHeight: 0.95,
                    fontVariantNumeric: "tabular-nums",
                  }}>400+</span>
                  <span style={{
                    fontSize: 14, color: "rgba(255,255,255,.65)",
                    fontFamily: T.fBody, fontWeight: 500,
                    letterSpacing: "-0.005em", maxWidth: 180, lineHeight: 1.3,
                  }}>brokerages, dealers and shipyards</span>
                </div>
                {/* §5 hero result line */}
                <div style={{
                  marginTop: 8, fontSize: 13,
                  fontFamily: T.fBody, color: "rgba(255,255,255,.62)",
                  fontWeight: 500, letterSpacing: "-0.005em",
                  display: "inline-flex", alignItems: "center", gap: 8, flexWrap: "wrap",
                }}>
                  <span style={{
                    width: 6, height: 6, borderRadius: "50%",
                    background: "#5ce39a", display: "inline-block",
                    boxShadow: "0 0 0 4px rgba(92,227,154,.15)",
                  }} />
                  <span><strong style={{ color: "#fff", fontWeight: 700 }}>Average dealer saves $24,300/year</strong> vs. YachtWorld.</span>
                </div>
              </div>
              <div style={{
                width: 1, alignSelf: "stretch",
                background: "rgba(255,255,255,.12)",
                margin: "0 4px",
              }} className="hero-trust-divider" />
              <div className="hero-trust-logos" style={{
                display: "flex", alignItems: "center",
                gap: 40, flex: 1, flexWrap: "wrap",
                minHeight: 32,
              }}>
                {[
                  { name: "Allied Marine",   file: "allied-logo.svg",     h: 32, treat: "asis" },
                  { name: "FGI Yacht Group", file: "fgi-yacht-group.png", h: 32, treat: "default" },
                  { name: "Sunreef Yachts",  file: "sunreef.webp",        h: 26, treat: "invert" },
                ].map((m) => (
                  <img key={m.file}
                    src={(window.__YW_ASSETS && window.__YW_ASSETS[`assets/members/${m.file}`]) || `assets/members/${m.file}`}
                    alt={m.name}
                    style={{
                      height: m.h, width: "auto", objectFit: "contain",
                      opacity: .80,
                      filter:
                        m.treat === "asis"   ? "none" :
                        m.treat === "invert" ? "invert(1) brightness(2)" :
                                               "brightness(0) invert(1)",
                      transition: "opacity .2s ease",
                    }}
                    onMouseOver={(e) => { e.currentTarget.style.opacity = "1"; }}
                    onMouseOut={(e) => { e.currentTarget.style.opacity = ".80"; }}
                  />
                ))}
              </div>
            </div>
          </div>
          {/* Right column removed per design feedback. */}
        </div>
        {/* Dashboard preview moved out of the hero into its own §3 section
             "This is what replaces all of that.", see below the cost
             calculator. The hero now ends after the H1 + CTA stack. */}
      </section>

      {/* ── PROOF STRIP (§2 — replaces full Buyer Journey Cinema)
          Three highest-impact stats lifted from the journey, presented
          as a compact 3-column proof band directly below the hero so
          the dealer gets credibility before any pricing surface. */}
      <section data-screen-label="02 Proof strip" style={{
        background: T.bgDark, color: "#fff",
        padding: "56px 32px",
        borderTop: "1px solid rgba(255,255,255,.06)",
        borderBottom: "1px solid rgba(255,255,255,.06)",
      }}>
        <div style={{ maxWidth: 1280, margin: "0 auto" }}>
          <div className="yw-proof-grid" style={{
            display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: 0,
          }}>
            {[
              { v: "2.18M", l: "Social audience", s: "Buyers find your inventory before they Google a competitor." },
              { v: "20M+", l: "People reached per month on social", s: "Organic social reach, not paid ads." },
              { v: "100+",  l: "Qualified buyers per LIVE session", s: "Pre-vetted, decision-grade audience." },
            ].map((s, i) => (
              <div key={i} className="yw-proof-cell" style={{
                padding: "8px 28px",
                borderRight: i < 2 ? "1px solid rgba(255,255,255,.10)" : "none",
                fontFamily: T.fBody,
              }}>
                <div style={{
                  fontFamily: T.fDisplay, fontSize: "clamp(40px, 4.4vw, 64px)",
                  fontWeight: 700, letterSpacing: "-0.035em", lineHeight: 1.0,
                  color: "#fff", fontVariantNumeric: "tabular-nums", marginBottom: 8,
                }}>{s.v}</div>
                <div style={{ fontSize: 14, fontWeight: 600, color: "#fff", marginBottom: 4 }}>{s.l}</div>
                <div style={{ fontSize: 13, color: "rgba(255,255,255,.55)", lineHeight: 1.45 }}>{s.s}</div>
              </div>
            ))}
          </div>
        </div>
        <style>{`
          @media (max-width: 760px) {
            .yw-proof-grid { grid-template-columns: 1fr !important; }
            .yw-proof-cell { border-right: none !important; border-bottom: 1px solid rgba(255,255,255,.10); padding: 24px 8px !important; }
            .yw-proof-cell:last-child { border-bottom: none; }
          }
        `}</style>
      </section>

      {/* Legacy "§3 The alternative" + dashboard preview retained in
          v1 only; removed here to keep narrative on cost/value. */}
      <section data-screen-label="03 The alternative" style={{ display: "none" }} aria-hidden="true">
      <section data-screen-label="03 LEGACY" style={{
        background: T.bg,
        padding: "120px 32px 100px",
        borderTop: `1px solid ${T.border}`,
      }}>
        <div style={{ maxWidth: 1280, margin: "0 auto" }}>
          <div style={{ marginBottom: 56, maxWidth: 880 }}>
            <div style={{
              fontSize: 13, fontWeight: 600, color: T.accent,
              textTransform: "uppercase", letterSpacing: ".14em", marginBottom: 16,
            }}>What replaces it</div>
            <h2 style={{
              fontFamily: T.fDisplay, fontSize: "clamp(40px, 5.5vw, 80px)",
              fontWeight: 700, letterSpacing: "-0.035em", lineHeight: 1.0,
              margin: 0, color: T.fg,
            }}>
              One platform.<br/>
              <span style={{ color: T.fgFaint }}>Listings, contracts, global reach and tools you need.</span>
            </h2>
            <p style={{
              fontSize: 18, lineHeight: 1.55, color: T.fgMuted,
              marginTop: 22, maxWidth: 640, fontFamily: T.fBody,
            }}>
              Add listings, manage events, start live streams, or reach more
              people. All in one place.
            </p>
          </div>
          <div style={{
            borderRadius: 16, overflow: "hidden",
            border: `1px solid ${T.border}`,
            boxShadow: "0 40px 80px -20px rgba(0,0,0,.20)",
            background: "#fff",
          }}>
            <div style={{ display: "flex", alignItems: "center", gap: 6, padding: "10px 14px",
              borderBottom: `1px solid ${T.border}`, background: "#fcfcfc" }}>
              <span style={{ width: 10, height: 10, borderRadius: 5, background: "#e5e5e5" }} />
              <span style={{ width: 10, height: 10, borderRadius: 5, background: "#e5e5e5" }} />
              <span style={{ width: 10, height: 10, borderRadius: 5, background: "#e5e5e5" }} />
              <div style={{ flex: 1, textAlign: "center", fontSize: 13, color: T.fgFaint }}>
                YachtWay.com / dealer / inventory
              </div>
            </div>
            <div className="dashboard-preview-pane" style={{ height: 580, color: T.fg, position: "relative" }}>
              <div className="dashboard-img-desktop" style={{ height: "100%", overflowY: "auto", overflowX: "hidden", WebkitOverflowScrolling: "touch" }}>
                <img
                  src={(window.__YW_ASSETS && window.__YW_ASSETS["assets/dealer-dashboard.png"]) || "assets/dealer-dashboard.png"}
                  alt="Dealer dashboard"
                  style={{ width: "100%", height: "auto", display: "block" }}
                />
              </div>
              <div className="dashboard-mock-mobile" style={{ height: "100%", overflow: "hidden" }}>
                <DashboardMock />
              </div>
              <div className="dashboard-img-desktop dashboard-scroll-hint" aria-hidden="true" style={{
                position: "absolute", left: 0, right: 0, bottom: 0, height: 64,
                background: "linear-gradient(to bottom, rgba(255,255,255,0), rgba(255,255,255,.92))",
                pointerEvents: "none", transition: "opacity .25s ease",
              }} />
            </div>
          </div>
        </div>
      </section>
      </section>
      {/* end legacy hidden block */}

      {/* ── BUYER JOURNEY removed per CRO/design review — moved off the
          pricing page entirely. The condensed proof strip (above hero)
          carries the audience credibility into the pricing narrative. */}
      <div id="journey" style={{ display: "none" }} aria-hidden="true">
        <BuyerJourneyCinema T={T} A={A} glow={glow} tint={tint} />
        <BuyerJourneyMobile T={T} A={A} glow={glow} tint={tint} />
      </div>

      {/* ── REACH NUMBERS STRIP — removed per design feedback (m0075).
          The named dealer quote + hero result line now carry the
          credibility weight; the strip felt redundant after the
          information-architecture re-org. ─── */}
      {/* <ReachNumbersStrip T={T} A={A} AOnDark={AOnDark} glow={glow} tint={tint} rgba={rgba} /> */}

      {/* ── FEATURE MATRIX (LIGHT), the nav "Compare" anchor lives
             here. CompetitiveIntelligence above is treated as part of
             the Reach narrative (numbers backing the reach claim). */}
      <section id="compare" style={{ padding: "120px 32px", background: T.bg, scrollMarginTop: 80 }}>
        <div style={{ maxWidth: 1280, margin: "0 auto" }}>
          <div style={{ marginBottom: 56 }}>
            <div style={{ fontSize: 13, fontWeight: 600, color: T.accent,
              textTransform: "uppercase", letterSpacing: ".1em", marginBottom: 14 }}>Capability</div>
            <h2 style={{ fontFamily: T.fDisplay, fontSize: "clamp(40px, 5.5vw, 80px)", fontWeight: 700,
              letterSpacing: "-0.035em", lineHeight: 1.0, margin: 0, maxWidth: 760 }}>
              Every tool a dealer needs,<br />
              <span style={{ color: T.fgFaint }}>in one platform.</span>
            </h2>
            <p style={{ fontSize: 14, color: T.fgMuted, marginTop: 16, maxWidth: 720, lineHeight: 1.55 }}>
              YachtWay vs. the major listing platforms. Hover any row for detail.
            </p>
            {/* Region toggle — switches the priced rows (Listing cost,
                Annual cost, Per-broker seat) between USD and EUR. */}
            <div style={{
              marginTop: 24, display: "inline-flex", alignItems: "center", gap: 12,
              padding: 4, borderRadius: 999,
              background: T.bgAlt || "#f3f1ec", border: `1px solid ${T.border}`
            }}>
              {[
                { k: "us", label: "US (USD)" },
                { k: "eu", label: "EU (EUR)" }
              ].map((opt) => {
                const active = compareRegion === opt.k;
                return (
                  <button
                    key={opt.k}
                    type="button"
                    onClick={() => setCompareRegion(opt.k)}
                    style={{
                      padding: "8px 16px", borderRadius: 999, border: "none",
                      cursor: "pointer",
                      fontFamily: "inherit", fontSize: 13, fontWeight: 600,
                      letterSpacing: ".02em",
                      background: active ? T.fg : "transparent",
                      color: active ? T.bg : T.fgMuted,
                      transition: "background .18s ease, color .18s ease"
                    }}>{opt.label}</button>
                );
              })}
            </div>
          </div>

          {(() => {
            // Competitors. "yw" = YachtWay; the rest are individual platforms.
            // Column order matters, YachtWay sits first as the highlighted column.
            const COLS = [
            { k: "yw", name: "YachtWay", sub: "All-in-one" },
            { k: "ywld", name: "YachtWorld", sub: "incl. Boats.com, BoatTrader" },
            { k: "msrc", name: "MarineSource", sub: "" },
            { k: "ychr", name: "Yachtr", sub: "" },
            { k: "rbt", name: "Rightboat", sub: "" },
            { k: "ytco", name: "Yatco", sub: "" }];

            // Each row: feature label, plus per-column value.
            // true = supported (check), false = not (x), or string for nuance.
            // Priced rows swap between US (USD) and EU (EUR) values based on
            // the section-level compareRegion toggle.
            const isEU = compareRegion === "eu";
            const ROWS = [
            isEU
              ? { f: "Listing cost", yw: "Free", ywld: "€925 - €13.8K+/mo", msrc: "Unknown", ychr: "€349 - €999/mo", rbt: "€25/lead", ytco: "Unknown" }
              : { f: "Listing cost", yw: "Free", ywld: "$1K - $15K+/mo", msrc: "Unknown", ychr: "$399 - $1,199/mo", rbt: "Unknown", ytco: "Unknown" },
            isEU
              ? { f: "Annual cost (typical SMB)", yw: "€0", ywld: "€11K - €165K", msrc: "Unknown", ychr: "€4.2K - €12K", rbt: "Unknown", ytco: "Unknown" }
              : { f: "Annual cost (typical SMB)", yw: "$0", ywld: "$12K - $180K", msrc: "Unknown", ychr: "$4.8K - $14.4K", rbt: "Unknown", ytco: "Unknown" },
            isEU
              ? { f: "Per-broker seat", yw: "€12/seat/mo", ywld: "+€45/seat", msrc: "-", ychr: "+ IYBA fee", rbt: "-", ytco: "-" }
              : { f: "Per-broker seat", yw: "$19/seat/mo", ywld: "+$50/seat", msrc: "-", ychr: "+ IYBA fee", rbt: "-", ytco: "-" },
            { f: "Free unlimited inventory", yw: true, ywld: false, msrc: false, ychr: false, rbt: false, ytco: false },
            { f: "Live streaming to buyers",
              learn: {
                title: "YachtWay Live",
                kicker: "Only on YachtWay",
                tagline: "See it. Live. Now.",
                visual: "live",
                lead: "A one-tap, in-browser walkthrough broadcast from any phone. Buyers worldwide watch, ask questions in real time, and the entire session lives on your listing forever, with analytics, replays, and shareable links.",
                steps: [
                  { h: "Schedule ahead or go live now",
                    b: "Pick any of your listings and set a time. Or go live right now, the moment a buyer asks." },
                  { h: "Set up in seconds",
                    b: "Turn on the lights, pull out your phone, tap Go Live. No apps, no crew, no extra gear, any smartphone from the last five years works." },
                  { h: "Walk buyers through the vessel",
                    b: "Real-time questions stream in as you walk. You answer them on camera. It feels like a real conversation because it practically is one." },
                  { h: "Every Live lives on the listing",
                    b: "The recording auto-attaches to the listing page, viewer analytics go live the second you stop, and buyers can rewatch any time." } ],
                why: [
                  { h: "Direct the camera",
                    b: "Curious about the engine room or the cabin finish? Buyers ask in real time and you show them exactly what they want to see." },
                  { h: "Jump in instantly",
                    b: "No apps, no accounts, no barriers. Tap any live stream and start watching from your browser, wherever you are." },
                  { h: "Live-first catalog",
                    b: "Active Lives are automatically pinned to the top of the catalog so the freshest content sells first." },
                  { h: "Dolby audio, 1080p HD",
                    b: "Built for real conversations, not glitchy mobile streams. Every finish, texture and detail comes through clean." } ],
                footnote: "Other platforms may offer scheduled appointments or a third-party video tool. YachtWay Live is the only integrated, in-platform broadcast: one stream, dozens of showings, the recording stays on the listing." },
              yw: true, ywld: false, msrc: false, ychr: false, rbt: false, ytco: false },
            { f: "Built-in buyer financing", yw: true, ywld: false, msrc: false, ychr: false, rbt: false, ytco: false },
            { f: "Built-in insurance",
              learn: {
                title: "YachtWay MasterCover",
                kicker: "Powered by Lloyd's of London",
                tagline: "Quote, bind, pay. All online.",
                visual: "mastercover",
                lead: "Direct access to the Lloyd's of London marketplace, the same floor that backs superyachts and satellites, built into your listing. Hulls from $100K to $300M, estimate in under 2 minutes, full digital flow from quote to bind.",
                steps: [
                  { h: "Estimate in under 2 minutes",
                    b: "Enter vessel year, length, value, top speed and cruising area. Instant annual estimate, no commitment, no broker call." },
                  { h: "Routed to Lloyd's of London",
                    b: "Your request goes straight to A-rated Lloyd's underwriters — the world's most trusted marine market for 300+ years." },
                  { h: "Quote, bind, and pay online",
                    b: "Compare offers, approve digitally, pay by card or wire. Certificate of Insurance issued the same day." } ],
                why: [
                  { h: "$100K – $300M coverage",
                    b: "Powerboats, sailboats, charter fleets, mega-yachts. If it floats and it's insurable, MasterCover writes it." },
                  { h: "All-Risk, not Named Perils",
                    b: "If it isn't explicitly excluded, it's insured. New-for-old on partial losses, Agreed Value on total loss." },
                  { h: "Worldwide, year-round",
                    b: "On water, on land, in transport, on ferries. Liability, hull & machinery, P&I, personal accident, crew." },
                  { h: "SOC 2 + GDPR",
                    b: "Bank-grade data handling. The same compliance bar enterprise software clears, applied to your buyers' info." } ],
                footnote: "Other listing platforms link out to third-party brokers. MasterCover is the only insurance product built directly into the listing flow — buyers quote, bind and pay without leaving the platform." },
              yw: true, ywld: false, msrc: false, ychr: false, rbt: false, ytco: false },
            { f: "Digital contracts",
              learn: {
                title: "EasySign",
                kicker: "Powered by DocuSign",
                tagline: "Sign. Send. Track. Done.",
                visual: "easysign",
                lead: "Every contract a dealer touches — Listing Agreements, Purchase Agreements, Offers, Commission Agreements, Bill of Sale, State Registration, U.S. Coast Guard Documentation — created, sent, signed and tracked in one dashboard. Powered by DocuSign, legally binding worldwide, and built into your listing flow so a signed Listing Agreement becomes a live draft in seconds.",
                steps: [
                  { h: "Listing Agreement → live draft in seconds",
                    b: "The moment a Listing Agreement is signed, EasySign spins up a draft listing pre-filled with vessel and pricing data. Add photos, hit publish, done." },
                  { h: "20+ documents ready in a few clicks",
                    b: "Purchase Agreements, Closing Statements, Vessel Acceptance, Bill of Sale, State Registration, U.S. Certificate of Documentation, Title, Wire Info, Build Sheet — all templated and ready to send." },
                  { h: "Signed via DocuSign, legally valid worldwide",
                    b: "Every signature is audit-trailed, timestamped, and court-recognized in every market a YachtWay deal closes in." },
                  { h: "Track every deal stage in one dashboard",
                    b: "Created, Sent, Signed, Countersigned — every document on every deal, with automated payment-milestone alerts so nothing slips." } ],
                why: [
                  { h: "Works where others freeze",
                    b: "Built to keep working on bad connections — close contracts at boat shows, on docks, anywhere a 4G bar wobbles. Deals in minutes, not hours." },
                  { h: "Automated state forms",
                    b: "California, Florida, New York, Delaware, Illinois auto-populate from the deal. More states are added regularly." },
                  { h: "AI-assisted paperwork",
                    b: "Built for pros, driven by AI. Fields auto-fill from the listing and buyer profile; the system flags what's missing before you send." },
                  { h: "Your contracts stay private",
                    b: "We can't read them. GDPR-compliant, SOC 2 Type 1 + SOC 2 Type 2 certified, penetration-tested. You control who sees every deal." } ],
                footnote: "$269/mo. First 30 days or 5 contracts free for all users. Up to 5 deals per month included — $20 per additional deal. Replaces DocuSign Business Pro ($300+/mo) and the manual paperwork stack a brokerage normally runs separately." },
              yw: true, ywld: true, msrc: false, ychr: true, rbt: false, ytco: false },
            { f: "VATO, Vessel Valuation Tool", yw: true, ywld: true, msrc: false, ychr: false, rbt: false, ytco: false },
            { f: "Content production", yw: true, ywld: false, msrc: false, ychr: false, rbt: false, ytco: false },
            { f: "Dealer site + inventory sync", yw: true, ywld: true, msrc: false, ychr: false, rbt: false, ytco: true },
            { f: "3D tour support",
              learn: {
                title: "3D Tours",
                kicker: "Walk the boat from anywhere",
                tagline: "Bring every cabin, helm and deck to the listing.",
                visual: "tour3d",
                lead: "Every broker can attach a full 3D virtual tour to their listing, plus an optional vessel brochure. Buyers explore the entire boat — interior, helm, deck, engine room — without leaving the listing page. We accept tours from every major provider so you use whoever you already shoot with.",
                steps: [
                  { h: "Shoot with the provider you already use",
                    b: "Accepted formats: Matterport, Giraffe360, CloudPano, Kuula, VRCloud and Theatro360. If your tour lives on one of those, it works on YachtWay." },
                  { h: "Paste the link in the listing flow",
                    b: "In the listing-creation flow, drop the tour URL into the \"3D Tour\" field. YachtWay auto-detects the provider and embeds it inline on the listing page." },
                  { h: "Upload the brochure (optional)",
                    b: "Attach the manufacturer or dealer PDF brochure for buyers who want to read the full spec sheet. Sits next to the tour as a one-click download." },
                  { h: "Don't have a tour? Use YachtWay Studio",
                    b: "Request a YachtWay Studio shoot directly from the listing flow and a local crew captures the 3D tour, photos and walkthrough video for you." } ],
                why: [
                  { h: "Provider-agnostic",
                    b: "Use the platform you and your photographer already trust — no lock-in, no re-shoots, no proprietary viewer." },
                  { h: "Embedded, not linked away",
                    b: "Tours play full-screen inside the listing. Buyers stay on the page; you keep the engagement." },
                  { h: "3D badge in search",
                    b: "Listings with a tour get a \"3D\" badge in the search grid, lifting click-through versus photo-only listings." },
                  { h: "Brochure download is tracked",
                    b: "See which buyers opened the brochure so your follow-up is informed before the first call." } ],
                footnote: "3D tour embedding is included on every plan. YachtWay Studio production is à-la-carte." },
              yw: true, ywld: false, msrc: false, ychr: false, rbt: false, ytco: false },
            { f: "Social reach", yw: true, ywld: true, msrc: false, ychr: false, rbt: false, ytco: false },
            { f: "Dealer earns referral income", yw: true, ywld: false, msrc: false, ychr: false, rbt: false, ytco: false },
            { f: "Schedule a tour",
              learn: {
                title: "Schedule a Tour",
                kicker: "Built into every listing",
                tagline: "Pick a time. Done.",
                visual: "schedule",
                lead: "Buyers book a showing directly from the listing page — they pick a date, pick a time, pick In-Person or Video Call, and the slot is locked. No phone tag, no email threads, no \"let me check and get back to you.\" The easiest way for a customer to pick a time that suits them without the constant back-and-forth.",
                steps: [
                  { h: "Book from the listing page",
                    b: "Every listing has a Schedule a Tour button. One click opens the booking sheet — no account required to start." },
                  { h: "In-Person or Video Tour",
                    b: "Buyer chooses how they want to see the vessel. In-Person shows the vessel's home port; Video Tour books a FaceTime or Zoom walkthrough." },
                  { h: "Pick a slot that works",
                    b: "Available times are shown in the vessel's local time zone. Booked or unavailable slots are greyed out so the buyer only sees real options." },
                  { h: "Confirm and the broker is notified",
                    b: "Name, email and phone, then Submit. The request lands in the broker's dashboard with the buyer's contact info and the chosen slot." } ],
                why: [
                  { h: "No back-and-forth",
                    b: "Customers self-serve their own time. Brokers stop losing showings to scheduling friction." },
                  { h: "Vessel-local time zone",
                    b: "Times shown match where the vessel is, not where the buyer is — no confusion about whether 3pm is local or remote." },
                  { h: "In-Person or Video, one flow",
                    b: "A buyer in Monaco can book a video walk-through of a vessel in Fort Lauderdale in the same two clicks as a local in-person showing." },
                  { h: "Routed to the right broker",
                    b: "Every booking goes straight to the listing's broker — calls and messages route to the assigned seat, not the office switchboard." } ],
                footnote: "Other listing platforms hand the buyer a phone number or a generic contact form. Schedule a Tour is the only native, calendar-aware booking flow built into the listing — buyer picks a slot, broker gets a confirmed showing." },
              yw: true, ywld: false, msrc: false, ychr: false, rbt: false, ytco: false },
            { f: "Events",
              learn: {
                title: "Events",
                kicker: "Boat shows, unveilings & open houses",
                tagline: "Show up where buyers are already looking.",
                visual: "events",
                lead: "Tell buyers exactly which boat shows you'll be attending, which vessels you're bringing, and let them RSVP straight from the listing. Create unveilings and open houses, send instant invitation emails, and get discovered by buyers browsing boats in your area.",
                steps: [
                  { h: "Create the event in a minute",
                    b: "Boat show, unveiling, open house, sea trial day — pick the type, set the date(s), drop the address (or mark it private), and you're live." },
                  { h: "Pick which vessels you're bringing",
                    b: "Attach any of your listings as 'Vessels on Display.' Each one shows up on the event page with price, location and a direct link back to its listing." },
                  { h: "Buyers RSVP from the listing",
                    b: "Every attached listing shows the upcoming event with an RSVP button. Buyers reserve a slot in one click — no phone tag, no email back-and-forth." },
                  { h: "Instant invitation emails",
                    b: "Invite your saved buyer list with a single click; YachtWay sends a branded invite and tracks who opened, who RSVP'd, and who's still pending." },
                  { h: "Get found by nearby buyers",
                    b: "Anyone browsing boats in your event's region sees it surfaced on relevant listings and in search — free local exposure, every time you set up." } ],
                why: [
                  { h: "Pending requests in one place",
                    b: "A live counter of open RSVPs sits at the top of the event page so nothing falls through the cracks." },
                  { h: "Real engagement metrics",
                    b: "Guests, views, vessels on display and impressions are tracked per event — see exactly what each show or open house is worth." },
                  { h: "Share with one tap",
                    b: "Every event has a shareable link and a branded social card, ready to post on Instagram, LinkedIn or email." },
                  { h: "Private or public",
                    b: "Run a private VIP unveiling with an invite-only guest list, or a public open house indexed across YachtWay." } ],
                footnote: "Included on every dealer plan at no extra cost. Unlimited events, unlimited vessels on display, unlimited RSVPs." },
              yw: true, ywld: false, msrc: false, ychr: false, rbt: false, ytco: false },
            { f: "Range calculator",
              learn: {
                title: "NautiX",
                kicker: "The YachtWay range & speed engine",
                tagline: "Real distance. Real fuel. Real answers.",
                visual: "nautix",
                lead: "NautiX is a context-aware top-speed, range and fuel-burn calculator built into every listing. Plot two points on the map and instantly see trip distance, duration, cruise speed, fuel used (L + GAL) and tank usage — calculated from real vessel specs, hull type, drive system, and a continuously expanding database of manufacturer and sea-trial data, not the generic legacy formulas that miss by 20–30%.",
                steps: [
                  { h: "Pick two points on the map",
                    b: "Buyer drops a start and an end pin. NautiX measures the nautical-mile distance over water and draws the route." },
                  { h: "Real-vessel math, not a generic formula",
                    b: "Top Speed = (C × √(HP ÷ tons)) ÷ 100, where C is dynamically chosen based on hull type (planing / displacement / semi-displacement), drive system, era of design and brand/model reference data." },
                  { h: "Fuel, duration and tank usage",
                    b: "Combines verified builder data, published sea-trial results and engine specs to estimate gallons + litres burned, trip duration and what percentage of the tank that takes." },
                  { h: "Round Trip & Fast Cruise toggles",
                    b: "One click doubles the leg for a return journey; Fast Cruise recalculates everything at the vessel's faster cruise RPM band." } ],
                why: [
                  { h: "Most accurate in the industry",
                    b: "Smarter C values per hull design and era, real builder/test data for popular models, results match published performance within a few knots." },
                  { h: "Manufacturer-verified models",
                    b: "Builders and dealers submit official performance sheets to NautiX@YachtWay.com and get a verified checkmark next to their models — factory-backed, not estimated." },
                  { h: "Safe-side rounding + margin of error",
                    b: "Fuel and time round up to the nearest tenth with a built-in 0.5 buffer for real-world variables, so a buyer is never left short on math." },
                  { h: "Continuously improving",
                    b: "If a result is off, users flag it and the reference database is updated. Every flag makes every future estimate sharper." } ],
                footnote: "Calm-water baseline (the same one used by builders and sea-trial reports). Heavy weather increases real fuel burn — always allow extra margin. All results are estimates for reference, not performance guarantees." },
              yw: true, ywld: false, msrc: false, ychr: false, rbt: false, ytco: false },
            { f: "AI chat",
              learn: {
                title: "Waylo",
                kicker: "The model-specific AI assistant",
                tagline: "Ask anything about this exact boat.",
                visual: "waylo",
                lead: "Waylo is an AI assistant built into every listing that answers basic, model-specific questions in seconds. It draws strictly from manufacturer specifications and verified public journalism about the boat in front of you — never opinions, never cross-vessel comparisons, never sales talk.",
                steps: [
                  { h: "Open any listing, click Ask Waylo",
                    b: "A chat panel opens with three suggested questions pre-loaded: engine type and power, top cruising speed, layout and accommodations. One tap to ask, or type your own." },
                  { h: "Strictly model-scoped answers",
                    b: "Waylo only answers questions about THIS specific make, model and year. Ask about a different boat and it politely declines — no apples-to-apples, no \"compare with…\", no comparisons to other vessels on the platform." },
                  { h: "Sourced from real data, not opinions",
                    b: "Two sources only: the manufacturer's published specs and reputable public journalism (sea trials, magazine reviews, builder press kits). No reviewer star ratings, no buyer chatter, no anecdotes." },
                  { h: "Buyer gets answers, dealer keeps the lead",
                    b: "The basic questions get handled instantly — fuel capacity, beam, draft, range, accommodations. The buyer arrives at your inbox already qualified, ready to discuss the real stuff." } ],
                why: [
                  { h: "No comparisons, ever",
                    b: "Waylo is hard-coded to never recommend, rank, or contrast this vessel against any other. The conversation stays on the boat the buyer is looking at." },
                  { h: "Manufacturer data first",
                    b: "Builder spec sheets are the source of truth. Where a number is officially published, that's the number Waylo returns — not an estimate, not an aggregation." },
                  { h: "Public journalism, not reviews",
                    b: "Sea-trial reports and editorial features add real-world color (handling, cabin layout, build quality notes) without crossing into opinion or buyer sentiment." },
                  { h: "Cites what it doesn't know",
                    b: "If a fact isn't in the spec or the journalism, Waylo says so and points the buyer to ask the dealer directly — no hallucinated numbers." } ],
                footnote: "Available on every listing at no extra cost. Waylo will never recommend a competing boat, suggest a substitute, or run a side-by-side." },
              yw: true, ywld: false, msrc: false, ychr: false, rbt: false, ytco: false },
            { f: "API feed out", yw: true, ywld: true, msrc: false, ychr: true, rbt: true, ytco: true },
            { f: "GDPR",
              tip: "EU regulation governing personal-data handling. Under GDPR, an EU buyer can demand to see, correct, or delete the data a platform holds on them, and demand the platform stop selling or sharing it. A serious dealer needs proof their listing platform actually enforces this so an inquiry from an EU buyer does not turn into a regulatory complaint against the dealership.",
              yw: true,
              ywld: { value: "Self-claimed", tip: "Self-declared in Privacy Notice & agreements. Historical mention of external auditor (2018). No current public proof." },
              msrc: false, ychr: false,
              rbt: { value: "Self-claimed", tip: "Primarily self-claimed GDPR compliance with good documentation but no strong public evidence of independent audits." },
              ytco: { value: "Self-claimed", tip: "Self-claimed GDPR compliance with a basic, outdated policy and no published audits or certifications." } },
            { f: "SOC 2",
              tip: "Independent third-party audit (AICPA standard) that proves a platform's security, availability, and confidentiality controls actually work. A SOC 2 report tells a dealer that buyer data, signed contracts, and financial documents are stored in audited infrastructure, not on someone's laptop. It is the same bar enterprise software has to clear, applied to your listing platform.",
              yw: true, ywld: false, msrc: false, ychr: false, rbt: false, ytco: false }];

            const cellWidth = "minmax(110px, 1fr)";
            const gridCols = `minmax(220px, 1.6fr) ${cellWidth} repeat(${COLS.length - 1}, ${cellWidth})`;

            // Lightweight hover tooltip - shows a styled bubble above the
            // anchor on hover/focus. Native `title` is too slow and clipped
            // by the table chrome, so we render our own.
            const HoverTip = ({ tip, children, width = 280 }) => {
              const [open, setOpen] = useStateD(false);
              const tipRef = React.useRef(null);
              const arrowRef = React.useRef(null);
              // After the tooltip mounts, measure its position. If it
              // would overflow the viewport on the left or right, slide
              // it horizontally (and re-aim the little arrow back at
              // the anchor so the pointer still hits the cell). This
              // matters most on mobile, where columns near the right
              // edge of the table push the centered tooltip past the
              // screen — the user saw the GDPR "Self-claimed" tip
              // running off the right side of the viewport.
              React.useLayoutEffect(() => {
                if (!open) return;
                const tipEl = tipRef.current;
                const arrow = arrowRef.current;
                if (!tipEl) return;
                // Reset before measuring so each open is fresh.
                tipEl.style.transform = "translateX(-50%)";
                if (arrow) arrow.style.left = "50%";
                const rect = tipEl.getBoundingClientRect();
                const margin = 8;
                const vw = document.documentElement.clientWidth;
                let shift = 0;
                if (rect.left < margin) shift = margin - rect.left;
                else if (rect.right > vw - margin) shift = vw - margin - rect.right;
                if (shift !== 0) {
                  tipEl.style.transform = `translateX(calc(-50% + ${shift}px))`;
                  // Push the arrow back the opposite way so it still
                  // points at the anchor's centre.
                  if (arrow) arrow.style.left = `calc(50% - ${shift}px)`;
                }
              }, [open]);
              return (
                <span style={{ position: "relative", display: "inline-flex", alignItems: "center" }}
                onMouseEnter={() => setOpen(true)}
                onMouseLeave={() => setOpen(false)}
                onFocus={() => setOpen(true)}
                onBlur={() => setOpen(false)}>
                  {children}
                  {open &&
                  <span ref={tipRef} role="tooltip" style={{
                    position: "absolute",
                    bottom: "calc(100% + 10px)", left: "50%",
                    transform: "translateX(-50%)",
                    width, maxWidth: "calc(100vw - 16px)",
                    background: "#0a0a0b", color: "#fff",
                    padding: "12px 14px", borderRadius: 10,
                    fontSize: 13, fontWeight: 500, lineHeight: 1.5,
                    letterSpacing: "-0.005em",
                    boxShadow: "0 18px 32px -10px rgba(0,0,0,.35), 0 0 0 1px rgba(0,0,0,.06)",
                    zIndex: 50, pointerEvents: "none",
                    textAlign: "left", whiteSpace: "normal"
                  }}>
                      {tip}
                      <span ref={arrowRef} aria-hidden="true" style={{
                      position: "absolute", top: "100%", left: "50%",
                      marginLeft: -6,
                      width: 0, height: 0,
                      borderLeft: "6px solid transparent",
                      borderRight: "6px solid transparent",
                      borderTop: "6px solid #0a0a0b"
                    }} />
                    </span>
                  }
                </span>);

            };

            // Learn-more popup: click trigger → centered modal in a portal so
            // it escapes the table overflow. Closes on backdrop click, X, or
            // Esc. Locks body scroll while open. Renders the rich "learn"
            // schema attached to a row (title, lead, numbered steps, "why"
            // bullets, footnote) styled to match the dark editorial direction.
            const LearnPopup = ({ data, accent: aPurple }) => {
              const [open, setOpen] = useStateD(false);
              React.useEffect(() => {
                if (!open) return;
                const h = (e) => { if (e.key === "Escape") setOpen(false); };
                document.addEventListener("keydown", h);
                const prev = document.body.style.overflow;
                document.body.style.overflow = "hidden";
                return () => {
                  document.removeEventListener("keydown", h);
                  document.body.style.overflow = prev;
                };
              }, [open]);
              const modal = open && ReactDOM.createPortal(
                <div onClick={() => setOpen(false)} style={{
                  position: "fixed", inset: 0, zIndex: 1000,
                  background: "rgba(10,10,12,.78)", backdropFilter: "blur(8px)",
                  WebkitBackdropFilter: "blur(8px)",
                  display: "flex", alignItems: "center", justifyContent: "center",
                  padding: "32px 20px", animation: "yw-learn-fade .22s ease-out both"
                }}>
                  <style>{`
                    @keyframes yw-learn-fade { from { opacity: 0; } to { opacity: 1; } }
                    @keyframes yw-learn-rise { from { opacity: 0; transform: translateY(16px) scale(.985); } to { opacity: 1; transform: none; } }
                  `}</style>
                  <div role="dialog" aria-modal="true" aria-label={data.title}
                    onClick={(e) => e.stopPropagation()}
                    style={{
                      width: "min(1240px, calc(100vw - 48px))", maxHeight: "calc(100vh - 48px)", overflowY: "auto",
                      background: "#0f0f14", color: "#fff", borderRadius: 24,
                      border: "1px solid rgba(255,255,255,.08)",
                      boxShadow: "0 40px 80px -20px rgba(0,0,0,.6), 0 0 0 1px rgba(255,255,255,.04)",
                      padding: "56px 64px 52px",
                      fontFamily: "Figtree, system-ui, sans-serif",
                      animation: "yw-learn-rise .28s cubic-bezier(.16,.84,.3,1) both",
                      position: "relative"
                    }}>
                    <button aria-label="Close" onClick={() => setOpen(false)} style={{
                      position: "absolute", top: 18, right: 18, width: 36, height: 36,
                      borderRadius: 18, background: "rgba(255,255,255,.06)",
                      border: "1px solid rgba(255,255,255,.1)", color: "#fff",
                      display: "inline-flex", alignItems: "center", justifyContent: "center",
                      cursor: "pointer", fontSize: 16, lineHeight: 1
                    }}>×</button>

                    <div style={{
                      fontSize: 13, fontWeight: 700, letterSpacing: ".14em",
                      textTransform: "uppercase", color: AOnDark, marginBottom: 18,
                      display: "inline-flex", alignItems: "center", gap: 8
                    }}>
                      <span style={{ width: 7, height: 7, borderRadius: 4, background: AOnDark, display: "inline-block" }} />
                      {data.kicker}
                    </div>
                    <h3 style={{
                      fontFamily: "Poppins, system-ui, sans-serif", fontWeight: 700,
                      fontSize: "clamp(36px, 4.4vw, 56px)", lineHeight: 1.05, letterSpacing: "-0.025em", margin: "0 0 12px"
                    }}>{data.title}</h3>
                    {data.tagline &&
                      <div style={{ fontSize: 24, fontWeight: 500, color: AOnDark, margin: "0 0 22px" }}>{data.tagline}</div>}
                    <p style={{ fontSize: 19, lineHeight: 1.6, color: "rgba(255,255,255,.82)", margin: "0 0 36px", maxWidth: 780 }}>{data.lead}</p>

                    {data.visual === "live" && (
                      <div style={{
                        marginBottom: 28, padding: 14, borderRadius: 16,
                        background: "linear-gradient(180deg, rgba(255,255,255,.04), rgba(255,255,255,.015))",
                        border: "1px solid rgba(255,255,255,.06)"
                      }}>
                        <img src="assets/live-preview.jpg" alt="YachtWay Live catalog preview"
                          style={{ width: "100%", height: "auto", display: "block", borderRadius: 10 }} />
                      </div>
                    )}
                    {data.visual === "mastercover" && (
                      <div style={{
                        marginBottom: 28, padding: 14, borderRadius: 16,
                        background: "linear-gradient(180deg, rgba(255,255,255,.04), rgba(255,255,255,.015))",
                        border: "1px solid rgba(255,255,255,.06)",
                        display: "flex", justifyContent: "center"
                      }}>
                        <img src="assets/mastercover-form.jpg" alt="MasterCover quote form"
                          style={{ maxWidth: 560, width: "100%", height: "auto", display: "block", borderRadius: 10 }} />
                      </div>
                    )}
                    {data.visual === "easysign" && (
                      <div style={{
                        marginBottom: 28, padding: 14, borderRadius: 16,
                        background: "linear-gradient(180deg, rgba(255,255,255,.04), rgba(255,255,255,.015))",
                        border: "1px solid rgba(255,255,255,.06)",
                        display: "flex", justifyContent: "center"
                      }}>
                        <img src="assets/easysign-dashboard.jpg" alt="EasySign dashboard"
                          style={{ maxWidth: 820, width: "100%", height: "auto", display: "block", borderRadius: 10 }} />
                      </div>
                    )}
                    {data.visual === "schedule" && (
                      <div style={{
                        marginBottom: 28, padding: 14, borderRadius: 16,
                        background: "linear-gradient(180deg, rgba(255,255,255,.04), rgba(255,255,255,.015))",
                        border: "1px solid rgba(255,255,255,.06)",
                        display: "flex", justifyContent: "center"
                      }}>
                        <img src="assets/schedule-tour.jpg" alt="Schedule a tour booking flow"
                          style={{ maxWidth: 720, width: "100%", height: "auto", display: "block", borderRadius: 10 }} />
                      </div>
                    )}
                    {data.visual === "nautix" && (
                      <div style={{
                        marginBottom: 28, padding: 14, borderRadius: 16,
                        background: "linear-gradient(180deg, rgba(255,255,255,.04), rgba(255,255,255,.015))",
                        border: "1px solid rgba(255,255,255,.06)",
                        display: "flex", justifyContent: "center"
                      }}>
                        <img src="assets/nautix-range.jpg" alt="NautiX range calculator"
                          style={{ maxWidth: 980, width: "100%", height: "auto", display: "block", borderRadius: 10 }} />
                      </div>
                    )}
                    {data.visual === "events" && (
                      <div style={{
                        marginBottom: 28, padding: 14, borderRadius: 16,
                        background: "linear-gradient(180deg, rgba(255,255,255,.04), rgba(255,255,255,.015))",
                        border: "1px solid rgba(255,255,255,.06)",
                        display: "flex", justifyContent: "center"
                      }}>
                        <img src="assets/events.jpg" alt="Events dashboard with vessels on display, RSVPs and stats"
                          style={{ maxWidth: 980, width: "100%", height: "auto", display: "block", borderRadius: 10 }} />
                      </div>
                    )}
                    {data.visual === "waylo" && (
                      <div style={{
                        marginBottom: 28, padding: 14, borderRadius: 16,
                        background: "linear-gradient(180deg, rgba(255,255,255,.04), rgba(255,255,255,.015))",
                        border: "1px solid rgba(255,255,255,.06)",
                        display: "flex", justifyContent: "center"
                      }}>
                        <img src="assets/waylo-chat.jpg" alt="Ask Waylo chat panel on a listing"
                          style={{ maxWidth: 900, width: "100%", height: "auto", display: "block", borderRadius: 10 }} />
                      </div>
                    )}
                    {data.visual === "tour3d" && (
                      <div style={{
                        marginBottom: 28, padding: 14, borderRadius: 16,
                        background: "linear-gradient(180deg, rgba(255,255,255,.04), rgba(255,255,255,.015))",
                        border: "1px solid rgba(255,255,255,.06)",
                        display: "flex", justifyContent: "center"
                      }}>
                        <img src="assets/3d-tour.jpg" alt="3D tour and brochure upload in the listing flow"
                          style={{ maxWidth: 720, width: "100%", height: "auto", display: "block", borderRadius: 10 }} />
                      </div>
                    )}
                    {false && (
                      <div style={{ display: "none" }}>
                        {[
                          { img: "assets/listings/benetti-125.jpg", title: "2024 Benetti Oasis 40M", price: "$23,900,000", loc: "Fort Lauderdale, FL", views: 451 },
                          { img: "assets/listings/vanquish-70.jpg", title: "2025 Sunreef Ultima 55", price: "$2,900,000", loc: "Fort Lauderdale, FL", views: 402 }
                        ].map((c, i) => (
                          <div key={i} style={{
                            position: "relative", borderRadius: 12, overflow: "hidden",
                            background: "#1a1a22", aspectRatio: i === 0 ? "4/3" : "5/4",
                            boxShadow: "0 12px 28px -10px rgba(0,0,0,.6)"
                          }}>
                            <img src={c.img} alt="" style={{ position: "absolute", inset: 0, width: "100%", height: "100%", objectFit: "cover" }} />
                            <div style={{ position: "absolute", top: 10, left: 10, display: "inline-flex", alignItems: "center", gap: 5,
                              background: "#fff", padding: "4px 8px", borderRadius: 6,
                              fontSize: 11, fontWeight: 700, color: "#e11d2c", letterSpacing: ".02em" }}>
                              <span style={{ width: 8, height: 8, borderRadius: 4, background: "#e11d2c",
                                boxShadow: "0 0 0 3px rgba(225,29,44,.25)",
                                animation: "yw-live-pulse 1.4s ease-in-out infinite" }} />
                              Live
                            </div>
                            <div style={{ position: "absolute", top: 10, right: 10,
                              background: "rgba(20,20,26,.78)", color: "#fff",
                              padding: "4px 9px", borderRadius: 6,
                              fontSize: 11, fontWeight: 600, display: "inline-flex", alignItems: "center", gap: 5 }}>
                              <span>👁</span>{c.views}
                            </div>
                            <div style={{ position: "absolute", left: 0, right: 0, bottom: 0,
                              padding: "28px 12px 10px",
                              background: "linear-gradient(180deg, transparent, rgba(0,0,0,.78))",
                              color: "#fff" }}>
                              <div style={{ fontSize: 10, opacity: .8, marginBottom: 2 }}>📍 {c.loc}</div>
                              <div style={{ fontSize: 12, fontWeight: 600, lineHeight: 1.2 }}>{c.title}</div>
                              <div style={{ fontSize: 11, opacity: .85, marginTop: 2 }}>{c.price}</div>
                            </div>
                          </div>
                        ))}
                        <style>{`@keyframes yw-live-pulse { 0%,100%{box-shadow:0 0 0 3px rgba(225,29,44,.25);} 50%{box-shadow:0 0 0 6px rgba(225,29,44,.08);} }`}</style>
                      </div>
                    )}

                    {data.steps && data.steps.length > 0 && (
                      <div style={{ marginBottom: 36 }}>
                        <div style={{ fontSize: 13, fontWeight: 700, letterSpacing: ".12em", textTransform: "uppercase", color: "rgba(255,255,255,.55)", marginBottom: 18 }}>How it works</div>
                        <ol style={{ listStyle: "none", padding: 0, margin: 0, display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(240px, 1fr))", gap: 24 }}>
                          {data.steps.map((s, i) => (
                            <li key={i} style={{ display: "grid", gridTemplateColumns: "52px 1fr", gap: 16, alignItems: "baseline" }}>
                              <span style={{
                                fontFamily: "Poppins, system-ui, sans-serif", fontWeight: 600,
                                fontSize: 32, color: AOnDark, letterSpacing: "-0.01em"
                              }}>{i + 1}</span>
                              <div>
                                <div style={{ fontWeight: 600, fontSize: 19, marginBottom: 4 }}>{s.h}</div>
                                <div style={{ fontSize: 16, lineHeight: 1.55, color: "rgba(255,255,255,.68)" }}>{s.b}</div>
                              </div>
                            </li>
                          ))}
                        </ol>
                      </div>
                    )}

                    {data.why && data.why.length > 0 && (
                      <div style={{ borderTop: "1px solid rgba(255,255,255,.08)", paddingTop: 32, marginBottom: 28 }}>
                        <div style={{ fontSize: 13, fontWeight: 700, letterSpacing: ".12em", textTransform: "uppercase", color: "rgba(255,255,255,.55)", marginBottom: 18 }}>Why buyers love it</div>
                        <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(240px, 1fr))", gap: "24px 36px" }}>
                          {data.why.map((w, i) => (
                            <div key={i}>
                              <div style={{ fontWeight: 600, fontSize: 17, marginBottom: 6 }}>{w.h}</div>
                              <div style={{ fontSize: 15, lineHeight: 1.55, color: "rgba(255,255,255,.65)" }}>{w.b}</div>
                            </div>
                          ))}
                        </div>
                      </div>
                    )}

                    {data.footnote &&
                      <p style={{ fontSize: 14, lineHeight: 1.6, color: "rgba(255,255,255,.55)", margin: 0, paddingTop: 20, borderTop: "1px solid rgba(255,255,255,.06)" }}>{data.footnote}</p>}
                  </div>
                </div>,
                document.body
              );
              return (
                <React.Fragment>
                  <button onClick={(e) => { e.stopPropagation(); setOpen(true); }}
                    aria-label={`Learn more about ${data.title}`}
                    style={{
                      display: "inline-flex", alignItems: "center", justifyContent: "center",
                      width: 26, height: 26, padding: 0, gap: 0,
                      padding: "2px 8px 2px 6px",
                      borderRadius: 999,
                      background: tint(.08), border: `1px solid ${tint(.22)}`,
                      color: aPurple, cursor: "pointer",
                      fontFamily: "Figtree, system-ui, sans-serif",
                      fontSize: 11, fontWeight: 700, letterSpacing: ".04em",
                      textTransform: "uppercase",
                      lineHeight: 1.4, whiteSpace: "nowrap",
                      transition: "background .15s, border-color .15s, transform .12s"
                    }}
                    onMouseEnter={(e) => { e.currentTarget.style.background = tint(.14); e.currentTarget.style.borderColor = tint(.4); }}
                    onMouseLeave={(e) => { e.currentTarget.style.background = tint(.08); e.currentTarget.style.borderColor = tint(.22); }}>
                    <span style={{
                      width: 14, height: 14, borderRadius: 7, background: aPurple, color: "#fff",
                      display: "inline-flex", alignItems: "center", justifyContent: "center",
                      fontSize: 10, fontWeight: 800, fontFamily: "ui-sans-serif, system-ui",
                      letterSpacing: 0, display: "none"
                    }}>i</span>
                    <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
                      <path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/>
                      <circle cx="12" cy="12" r="3"/>
                    </svg>
                  </button>
                  {modal}
                </React.Fragment>
              );
            };

            const Cell = ({ value, isYw }) => {
              // Object form: { value: "...", tip: "..." } -> render as a
              // pill with a dotted underline + native title tooltip so the
              // dealer can hover to see the caveat (e.g. self-claimed GDPR).
              if (value && typeof value === "object" && "value" in value) {
                return (
                  <HoverTip tip={value.tip} width={300}>
                    <span style={{
                      fontSize: 13, fontWeight: 600,
                      color: "#92400e",
                      background: "#fef3c7",
                      border: "1px solid #fcd34d",
                      padding: "4px 9px", borderRadius: 999,
                      letterSpacing: "-0.005em", lineHeight: 1.2,
                      cursor: "help",
                      whiteSpace: "nowrap"
                    }}>{value.value}</span>
                  </HoverTip>);

              }
              if (value === true) {
                return (
                  <span style={{
                    width: 22, height: 22, borderRadius: 11,
                    background: "#16a34a",
                    color: "#fff",
                    display: "inline-flex", alignItems: "center", justifyContent: "center", flex: "none"
                  }}><Ic.check size={12} /></span>);

              }
              if (value === false) {
                return (
                  <span style={{
                    width: 24, height: 24, borderRadius: 12,
                    background: "#0a0a0b", color: "#fff",
                    display: "inline-flex", alignItems: "center", justifyContent: "center", flex: "none",
                    boxShadow: "0 0 0 3px rgba(10,10,11,.10)"
                  }} aria-label="Not available">
                    <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor"
                    strokeWidth="3.2" strokeLinecap="round" strokeLinejoin="round">
                      <path d="M6 6l12 12M18 6 6 18" />
                    </svg>
                  </span>);

              }
              // String value
              return (
                <span style={{
                  fontSize: 13, fontWeight: isYw ? 700 : 500,
                  color: isYw ? T.fg : T.fgMuted,
                  letterSpacing: "-0.005em", lineHeight: 1.3
                }}>{value}</span>);

            };

            // ─── Mobile view ──────────────────────────────────────
            // The 7-column grid is unusable on a 390px screen even with
            // sticky-column scroll. On mobile we render a competitor
            // picker (segmented + select) and a clean stacked list of
            // capabilities, each row shows YachtWay's value vs. the
            // selected competitor's value side-by-side. Hidden on
            // desktop via the `.yw-matrix--mobile` class in mobile.css.
            const MatrixMobile = () => {
              // Default to YachtWorld (most relevant, the incumbent).
              const [selKey, setSelKey] = useStateD("ywld");
              // Collapse state for the comparison area. Default expanded
              // so the comparison is immediately visible, but the user
              // can collapse it to skim the rest of the page faster.
              const [open, setOpen] = useStateD(true);
              const yw = COLS[0]; // YachtWay
              const sel = COLS.find((c) => c.k === selKey) || COLS[1];
              const others = COLS.filter((c) => c.k !== "yw");
              return (
                <div className="yw-matrix--mobile" style={{ display: "none" }}>
                  {/* Picker, title says "Tap any to compare with YachtWay" */}
                  <div style={{
                    background: T.bgAlt, border: `1px solid ${T.border}`,
                    borderRadius: 16, padding: 16, marginBottom: 14
                  }}>
                    <div style={{
                      fontSize: 11, fontWeight: 700, color: T.fgFaint,
                      textTransform: "uppercase", letterSpacing: ".14em",
                      marginBottom: 10
                    }}>Tap any to compare with YachtWay</div>
                    <div style={{
                      display: "grid",
                      gridTemplateColumns: "repeat(2, 1fr)",
                      gap: 6
                    }}>
                      {others.map((c) => {
                        const active = c.k === selKey;
                        return (
                          <button key={c.k}
                          onClick={() => setSelKey(c.k)}
                          style={{
                            appearance: "none",
                            padding: "10px 12px", borderRadius: 10,
                            border: active ? `1.5px solid ${A}` : `1px solid ${T.border}`,
                            background: active ? tint(.08) : "#fff",
                            cursor: "pointer", textAlign: "left",
                            fontFamily: T.fBody,
                            transition: "background .15s, border-color .15s"
                          }}>
                            
                            <div style={{
                              fontFamily: T.fDisplay, fontSize: 14, fontWeight: 700,
                              color: active ? A : T.fg, lineHeight: 1.2,
                              letterSpacing: "-0.005em"
                            }}>{c.name}</div>
                            {c.sub &&
                            <div style={{
                              fontSize: 11, fontWeight: 500,
                              color: T.fgFaint, marginTop: 3,
                              lineHeight: 1.3,
                              whiteSpace: "nowrap",
                              overflow: "hidden",
                              textOverflow: "ellipsis"
                            }}>{c.sub}</div>
                            }
                          </button>);

                      })}
                    </div>
                  </div>

                  {/* Sticky header strip, YW name + sel name, with the
                       collapse toggle. Sits above the row list. */}
                  <div style={{
                    display: "grid",
                    gridTemplateColumns: "130px 110px 110px",
                    alignItems: "stretch",
                    background: "#fff",
                    border: `1px solid ${T.border}`,
                    borderTopLeftRadius: 14, borderTopRightRadius: 14,
                    borderBottom: open ? "none" : `1px solid ${T.border}`,
                    overflow: "hidden"
                  }}>
                    {/* Toggle / title cell */}
                    <button
                      onClick={() => setOpen((v) => !v)}
                      aria-expanded={open}
                      aria-controls="yw-mxm-rows"
                      style={{
                        appearance: "none", border: "none",
                        background: "transparent",
                        textAlign: "left",
                        padding: "12px 14px",
                        cursor: "pointer",
                        display: "flex", alignItems: "center", gap: 8,
                        fontFamily: T.fBody
                      }}>
                      
                      <span style={{
                        width: 18, height: 18, borderRadius: 4,
                        border: `1px solid ${T.border}`,
                        background: T.bgAlt, color: T.fg,
                        display: "inline-flex", alignItems: "center", justifyContent: "center",
                        fontSize: 11, fontWeight: 700,
                        transition: "transform .2s",
                        transform: open ? "rotate(0deg)" : "rotate(-90deg)"
                      }} aria-hidden="true">▾</span>
                      <span style={{
                        fontSize: 12, fontWeight: 700, color: T.fgFaint,
                        textTransform: "uppercase", letterSpacing: ".12em"
                      }}>Capability</span>
                    </button>
                    {/* YachtWay column header */}
                    <div style={{
                      background: tint(.10),
                      borderLeft: `1px solid ${tint(.28)}`,
                      display: "flex", flexDirection: "column",
                      alignItems: "center", justifyContent: "center",
                      padding: "8px 4px"
                    }}>
                      <div style={{
                        fontFamily: T.fDisplay, fontSize: 12, fontWeight: 800,
                        color: A, lineHeight: 1.1, letterSpacing: "-0.005em"
                      }}>{yw.name}</div>
                    </div>
                    {/* Competitor column header */}
                    <div style={{
                      background: T.bgAlt,
                      borderLeft: `1px solid ${T.border}`,
                      display: "flex", flexDirection: "column",
                      alignItems: "center", justifyContent: "center",
                      padding: "8px 4px"
                    }}>
                      <div style={{
                        fontFamily: T.fDisplay, fontSize: 12, fontWeight: 800,
                        color: T.fg, lineHeight: 1.1, letterSpacing: "-0.005em",
                        whiteSpace: "nowrap",
                        overflow: "hidden",
                        textOverflow: "ellipsis",
                        maxWidth: "100%"
                      }}>{sel.name}</div>
                    </div>
                  </div>

                  {/* Comparison rows, one row per capability:
                         [ label                  | YW cell | Comp cell ]
                       The 1fr / 64 / 64 grid keeps both YES/NO cells
                       perfectly aligned vertically, so the wall of YW
                       checks vs. the gaps in the competitor column reads
                       as the headline visual. */}
                  {/* Comparison rows, one row per capability:
                         [ label                  | YW cell | Comp cell ]
                       Single parent grid (subgrid via display: contents
                       on row wrappers) so the YW + competitor columns
                       align across every row, while the label column
                       sizes to the widest label content (no wasted
                       whitespace between label and YW column). */}
                  {open &&
                  <div
                    id="yw-mxm-rows"
                    style={{
                      background: "#fff",
                      border: `1px solid ${T.border}`,
                      borderTop: "none",
                      borderBottomLeftRadius: 14,
                      borderBottomRightRadius: 14,
                      overflow: "hidden",
                      display: "grid",
                      gridTemplateColumns: "1fr 110px 110px"
                    }}>
                    
                      {ROWS.map((r, ri) =>
                    <React.Fragment key={ri}>
                          {/* Label */}
                          <div style={{
                        padding: "12px 14px",
                        display: "flex", alignItems: "center", gap: 6,
                        fontSize: 12.5, fontWeight: 600, color: T.fg,
                        lineHeight: 1.3,
                        textWrap: "balance",
                        borderTop: ri ? `1px solid ${T.border}` : "none"
                      }}>
                            {r.f}
                            {r.learn ?
                        <LearnPopup data={r.learn} accent={T.accent} /> :
                        r.tip &&
                        <HoverTip tip={r.tip} width={240}>
                                <span aria-label={r.tip} style={{
                            width: 14, height: 14, borderRadius: 7,
                            border: `1px solid ${T.border}`,
                            color: T.fgFaint,
                            display: "inline-flex", alignItems: "center", justifyContent: "center",
                            fontSize: 10, fontWeight: 700,
                            fontFamily: "ui-sans-serif, system-ui",
                            cursor: "help",
                            background: T.bgAlt,
                            flex: "none"
                          }}>i</span>
                              </HoverTip>
                        }
                          </div>
                          {/* YachtWay cell */}
                          <div style={{
                        background: tint(.06),
                        borderLeft: `1px solid ${tint(.18)}`,
                        borderTop: ri ? `1px solid ${T.border}` : "none",
                        display: "flex", alignItems: "center", justifyContent: "center",
                        padding: "8px 4px"
                      }}>
                            <Cell value={r[yw.k]} isYw={true} />
                          </div>
                          {/* Competitor cell */}
                          <div style={{
                        background: T.bgAlt,
                        borderLeft: `1px solid ${T.border}`,
                        borderTop: ri ? `1px solid ${T.border}` : "none",
                        display: "flex", alignItems: "center", justifyContent: "center",
                        padding: "8px 4px"
                      }}>
                            <Cell value={r[sel.k]} isYw={false} />
                          </div>
                        </React.Fragment>
                    )}
                    </div>
                  }
                </div>);

            };

            return (
              <React.Fragment>
                <MatrixMobile />
                <div className="yw-matrix--desktop" style={{
                  background: T.bg, border: `1px solid ${T.border}`,
                  borderRadius: 16
                }}>
                {/* Header row - sticks to the top of the viewport while
                       the user scrolls through the rows so they always know
                       which platform each column belongs to. */}
                <div style={{
                    position: "sticky", top: 64, zIndex: 5,
                    display: "grid", gridTemplateColumns: gridCols,
                    background: T.bgAlt,
                    borderTopLeftRadius: 16, borderTopRightRadius: 16,
                    borderBottom: `1px solid ${T.border}`,
                    boxShadow: "0 6px 16px -10px rgba(0,0,0,.15)"
                  }}>
                  <div style={{
                      padding: "22px 28px",
                      fontSize: 13, fontWeight: 700, color: T.fgFaint,
                      textTransform: "uppercase", letterSpacing: ".14em",
                      alignSelf: "center"
                    }}>Capability</div>
                  {COLS.map((c, i) => {
                      const isYw = i === 0;
                      return (
                        <div key={c.k} style={{
                          padding: "20px 14px",
                          background: isYw ? tint(.08) : "transparent",
                          borderLeft: isYw ? `1px solid ${tint(.20)}` : `1px solid ${T.border}`,
                          borderRight: isYw ? `1px solid ${tint(.20)}` : "none",
                          textAlign: "center"
                        }}>
                        <div style={{
                            fontFamily: T.fDisplay, fontSize: 13, fontWeight: 700,
                            color: isYw ? A : T.fg, letterSpacing: "-0.005em"
                          }}>{c.name}</div>
                        <div style={{
                            fontSize: 13, fontWeight: 500,
                            color: isYw ? rgba(A, .8) : T.fgFaint,
                            marginTop: 4, lineHeight: 1.3,
                            minHeight: 12
                          }}>{c.sub || "\u00A0"}</div>
                      </div>);

                    })}
                </div>
                {/* Data rows */}
                {ROWS.map((r, ri) => {
                    const isLast = ri === ROWS.length - 1;
                    return (
                      <div key={ri}
                      onMouseEnter={() => setHoverFeature(ri)}
                      onMouseLeave={() => setHoverFeature(-1)}
                      style={{
                        display: "grid", gridTemplateColumns: gridCols,
                        borderTop: ri ? `1px solid ${T.border}` : "none",
                        borderBottomLeftRadius: isLast ? 16 : 0,
                        borderBottomRightRadius: isLast ? 16 : 0,
                        background: hoverFeature === ri ? T.bgAlt : "transparent",
                        transition: "background .12s",
                        // Keep overflow visible so absolute-positioned hover
                        // tooltips can escape the row. The bottom-corner radius
                        // on the last row still works because the row's own
                        // background is the only thing that needs clipping, and
                        // child cells either match the radius (no fill) or are
                        // contained within the rounded shape visually.
                        overflow: "visible"
                      }}>
                    <span style={{
                          padding: "18px 28px", fontSize: 14, fontWeight: 500,
                          color: T.fg, alignSelf: "center",
                          display: "inline-flex", alignItems: "center", gap: 8
                        }}>
                      {r.f}
                      {r.learn ?
                          <LearnPopup data={r.learn} accent={T.accent} /> :
                          r.tip &&
                          <HoverTip tip={r.tip} width={320}>
                          <span aria-label={r.tip} style={{
                              width: 16, height: 16, borderRadius: 8,
                              border: `1px solid ${T.border}`,
                              color: T.fgFaint,
                              display: "inline-flex", alignItems: "center", justifyContent: "center",
                              fontSize: 13, fontWeight: 700,
                              fontFamily: "ui-sans-serif, system-ui",
                              cursor: "help",
                              background: T.bgAlt,
                              flex: "none",
                              letterSpacing: 0
                            }}>i</span>
                        </HoverTip>
                          }
                    </span>
                    {COLS.map((c, ci) => {
                          const isYw = ci === 0;
                          return (
                            <div key={c.k} style={{
                              padding: "16px 12px",
                              display: "flex", alignItems: "center", justifyContent: "center",
                              background: isYw ? tint(.04) : "transparent",
                              borderLeft: isYw ? `1px solid ${tint(.20)}` : `1px solid ${T.border}`,
                              borderRight: isYw ? `1px solid ${tint(.20)}` : "none",
                              textAlign: "center"
                            }}>
                          <Cell value={r[c.k]} isYw={isYw} />
                        </div>);

                        })}
                  </div>);

                  })}
                </div>
              </React.Fragment>);

          })()}

          <p style={{ fontSize: 13, color: T.fgFaint, marginTop: 16, maxWidth: 900, lineHeight: 1.5 }}>
            Sources: Public pricing pages and platform documentation, December 2025. Traffic, authority, and referring-domain figures from Semrush Domain Overview &amp; Backlink List reports, April - May 2026 (yatco.com, yachtway.com, yachtr.com, marinesource.com, rightboat.com). YachtWorld, Boats.com, and BoatTrader are operated by the same parent company; pricing/feature columns shown once. MarineSource, Yachtr, Rightboat, and Yatco listed individually.
          </p>
        </div>
      </section>

      {/* ── MEMBERS (DARK hall-of-fame) ─────────────────────────────────────
           A staggered 3D logo wall paying respect to early Members. Cards have:
           - Frosted glass treatment (rgba bg + subtle border + backdrop blur)
           - Variable size: a "size" prop on each member promotes anchor brands
           - Per-card scroll-reveal (IntersectionObserver, staggered by index)
           - Per-row floating breath animation (3 row-offset keyframes)
           - 3D hover: parent has perspective, card translateZ(32px) on hover
           Logo treatments per-image (white-on-light vs. native-white vs. has
           a saved gray card matte) are handled by per-tile className flags.    */}
      {(() => {
        // Logos copied from uploads/. Treatments:
        //   "default" , render as-is, white-ish logo on dark glass.
        //   "invert"  , image is dark-on-light → invert + brightness lift.
        //   "screen"  , image was saved with a gray "card matte"; mix-blend
        //                screen drops the matte and lifts the white logo.
        //   "selfbg"  , image carries its own background (Autograph navy,
        //                Merle Wood black). Do not pad; let it fill the tile.
        // size: "lg" → 1.4× span on desktop; "md" → 1×.
        const MEMBERS = [
        { name: "Allied Marine", file: "allied-marine.svg", treat: "default", size: "md" },
        { name: "Alpha Custom Yachts", file: "alpha.webp", treat: "whiten", size: "md" },
        { name: "Autograph Yacht Group", file: "autograph.png", treat: "default", size: "lg" },
        { name: "Azimut | Benetti Group", file: "azimut-benetti.png", treat: "invert", size: "lg" },
        { name: "FGI Yacht Group", file: "fgi-yacht-group.png", treat: "default", size: "md" },
        { name: "Fjord", file: "fjord.png", treat: "whiten", size: "md", maxH: 44 },
        { name: "Formula Boats", file: "formula.png", treat: "invert-mono", size: "md" },
        { name: "FYI Yachts", file: "fyi-yachts.png", treat: "default", size: "md" },
        { name: "Hanse Yachts", file: "hanse.png", treat: "whiten", size: "md" },
        { name: "Hargrave Custom Yachts", file: "hargrave.png", treat: "default", size: "md", maxH: 60 },
        { name: "Horizon Yachts", file: "horizon.png", treat: "default", size: "md" },
        { name: "Italian Yacht Group", file: "iyg.png", treat: "default", size: "md" },
        { name: "Jeff Brown Yachts", file: "jeff-brown.png", treat: "default", size: "md" },
        { name: "Lazzara Yachts", file: "lazzara.webp", treat: "invert-mono", size: "md" },
        { name: "Lekker Boats", file: "lekker.png", treat: "default", size: "md" },
        { name: "Majesty Yachts", file: "majesty.png", treat: "default", size: "md" },
        { name: "MarineMax", file: "marinemax.png", treat: "default", size: "md" },
        { name: "Merle Wood & Associates", file: "merle-wood.webp", treat: "default", size: "lg" },
        { name: "The Moorings Yacht Brokerage", file: "moorings.webp", treat: "whiten", size: "md" },
        { name: "Moran Yacht & Ship", file: "moran.png", treat: "default", size: "md" },
        { name: "Newater", file: "newater.png", treat: "default", size: "md" },
        { name: "Novamarine", file: "novamarine.png", treat: "default", size: "md" },
        { name: "Sirena Yachts", file: "sirena.png", treat: "default", size: "md" },
        { name: "Solaris Power", file: "solaris-power.png", treat: "default", size: "md" },
        { name: "Stratos", file: "stratos.png", treat: "default", size: "md" },
        { name: "Sunreef Yachts", file: "sunreef.webp", treat: "invert", size: "lg" },
        { name: "Van der Valk Shipyard", file: "van-der-valk.webp", treat: "whiten", size: "md" },
        { name: "Vanquish Yachts", file: "vanquish.png", treat: "default", size: "md", maxH: 84 },
        { name: "Yachts360", file: "yachts360.webp", treat: "invert-mono", size: "md" }];

        return (
          <section id="members" style={{
            position: "relative",
            padding: "160px 32px 140px",
            background: `radial-gradient(ellipse 90% 55% at 50% 0%, ${rgba(T.accent, .14)}, transparent 65%), ${T.bgDark}`,
            color: "#fff",
            borderTop: `1px solid rgba(255,255,255,.06)`,
            scrollMarginTop: 0,
            overflow: "hidden"
          }}>
        {/* Soft texture: thin diagonal hairlines for "wall" feel */}
        <div aria-hidden style={{
              position: "absolute", inset: 0, opacity: .35, pointerEvents: "none",
              background: `repeating-linear-gradient(45deg, transparent 0 24px, rgba(255,255,255,.012) 24px 25px)`
            }} />

        <style>{`
          /* Per-card 3D + reveal + breath ─────────────────────────────────── */
          .yw-mem-grid { perspective: 1400px; perspective-origin: 50% 30%; }

          .yw-mem-card {
            position: relative;
            display: flex; align-items: center; justify-content: center;
            min-height: 132px; padding: 28px 32px;
            border-radius: 18px;
            background: rgba(255,255,255,.035);
            border: 1px solid rgba(255,255,255,.08);
            backdrop-filter: blur(14px) saturate(120%);
            -webkit-backdrop-filter: blur(14px) saturate(120%);
            box-shadow:
              0 1px 0 0 rgba(255,255,255,.04) inset,
              0 18px 40px -28px rgba(0,0,0,.6);
            transform-style: preserve-3d;
            transform: translateZ(0px);
            transition: transform 280ms cubic-bezier(0.25, 0.46, 0.45, 0.94),
                        box-shadow 280ms cubic-bezier(0.25, 0.46, 0.45, 0.94),
                        border-color 280ms cubic-bezier(0.25, 0.46, 0.45, 0.94),
                        background 280ms cubic-bezier(0.25, 0.46, 0.45, 0.94);
            opacity: 0;
            will-change: transform, opacity;
          }
          .yw-mem-card.is-tall { min-height: 168px; }

          /* Scroll-reveal: when .is-in is added, cards fade up (staggered via
             inline animation-delay below). */
          .yw-mem-card.is-in {
            animation: yw-mem-rise 720ms cubic-bezier(0.22, 0.61, 0.36, 1) both;
          }
          @keyframes yw-mem-rise {
            from { opacity: 0; transform: translateY(28px) scale(.985); }
            to   { opacity: 1; transform: translateY(0) scale(1); }
          }

          /* Breath: 3 phase-offset keyframes assigned by row index modulo 3.
             After reveal completes the breath takes over (forwards fill on
             rise + then breath plays infinite). The breath translates Z so
             it composes cleanly with the hover translateZ(32px) override. */
          .yw-mem-card.is-in.is-breath-0 { animation:
            yw-mem-rise 720ms cubic-bezier(0.22, 0.61, 0.36, 1) both,
            yw-mem-breathe-0 7.2s ease-in-out 720ms infinite; }
          .yw-mem-card.is-in.is-breath-1 { animation:
            yw-mem-rise 720ms cubic-bezier(0.22, 0.61, 0.36, 1) both,
            yw-mem-breathe-1 7.6s ease-in-out 720ms infinite; }
          .yw-mem-card.is-in.is-breath-2 { animation:
            yw-mem-rise 720ms cubic-bezier(0.22, 0.61, 0.36, 1) both,
            yw-mem-breathe-2 8.0s ease-in-out 720ms infinite; }

          @keyframes yw-mem-breathe-0 {
            0%, 100% { transform: translateY(0) translateZ(0); }
            50%      { transform: translateY(-3px) translateZ(2px); }
          }
          @keyframes yw-mem-breathe-1 {
            0%, 100% { transform: translateY(-1px) translateZ(0); }
            50%      { transform: translateY(2px) translateZ(2px); }
          }
          @keyframes yw-mem-breathe-2 {
            0%, 100% { transform: translateY(2px) translateZ(0); }
            50%      { transform: translateY(-2px) translateZ(2px); }
          }

          /* Hover: translateZ(32px), overrides the breath transform via
             higher specificity (:hover) AND wins over the running animation
             because we set animation-play-state: paused. */
          .yw-mem-card:hover {
            transform: translateZ(32px) !important;
            animation-play-state: paused;
            background: rgba(255,255,255,.06);
            border-color: rgba(255,255,255,.16);
            box-shadow:
              0 1px 0 0 rgba(255,255,255,.06) inset,
              0 40px 80px -24px rgba(0,0,0,.78),
              0 0 0 1px ${rgba(T.accent, .22)};
          }
          /* Soft accent halo behind the card on hover, drawn via ::after so
             it does not disturb the image stacking. */
          .yw-mem-card::after {
            content: "";
            position: absolute; inset: -1px;
            border-radius: inherit; pointer-events: none;
            box-shadow: 0 0 60px 0 ${rgba(T.accent, 0)};
            transition: box-shadow 280ms cubic-bezier(0.25, 0.46, 0.45, 0.94);
          }
          .yw-mem-card:hover::after {
            box-shadow: 0 0 60px 0 ${rgba(T.accent, .18)};
          }

          /* Logo image base + treatments. Constrain by both dim so wide vs.
             tall lockups all sit visually centered. */
          .yw-mem-logo {
            max-width: 100%; max-height: 76px; width: auto; height: auto;
            object-fit: contain;
            opacity: .9;
            transition: opacity 280ms ease;
          }
          .yw-mem-card.is-tall .yw-mem-logo { max-height: 96px; }
          .yw-mem-card:hover .yw-mem-logo { opacity: 1; }

          /* invert: image is dark-on-light → flip to light-on-dark */
          .yw-mem-logo.is-invert {
            filter: invert(1) brightness(1.15) contrast(1.05);
          }
          /* invert-mono: like invert but strips colour first so coloured
             marks (e.g. navy "YACHTS360" lockup) come out clean white
             instead of inverting to a cream/yellow. */
          .yw-mem-logo.is-invert-mono {
            filter: grayscale(1) invert(1) brightness(1.15) contrast(1.05);
          }
          /* whiten: source is a coloured (non-black) mark on transparent;
             collapse to pure white. brightness(0) → black, then invert(1)
             → white. Alpha is preserved because filter does not touch it. */
          .yw-mem-logo.is-whiten {
            filter: brightness(0) invert(1);
          }
          /* screen: image carries a saved gray card matte → blend lifts it */
          .yw-mem-logo.is-screen {
            mix-blend-mode: screen;
            filter: brightness(1.4) contrast(1.1);
          }
          /* selfbg: image already has its own background (e.g. Autograph,
             Merle Wood). Fill the tile, no padding around the logo, and
             give the tile its own subtle frame instead of the glass card. */
          .yw-mem-card.is-selfbg { padding: 0; overflow: hidden; }
          .yw-mem-card.is-selfbg .yw-mem-logo {
            max-width: 100%; max-height: 100%; width: 100%; height: 100%;
            object-fit: cover; opacity: 1;
          }

          /* Punchline card, same chrome, no logo, big number. */
          .yw-mem-card.is-punch {
            background: linear-gradient(180deg, rgba(255,255,255,.045), rgba(255,255,255,.02));
            border-color: rgba(255,255,255,.14);
          }
          .yw-mem-punch-num {
            font-family: ${T.fDisplay};
            font-size: 44px; font-weight: 800; letter-spacing: -0.035em;
            line-height: 1; color: #fff;
            display: block;
          }
          .yw-mem-punch-sub {
            font-family: ${T.fBody};
            font-size: 12px; font-weight: 600;
            text-transform: uppercase; letter-spacing: .14em;
            color: rgba(255,255,255,.55);
            margin-top: 10px; display: block;
          }

          /* Grid: 6-col desktop with .is-lg cards spanning 2.
             Auto-flow dense so the staggering forms a natural mosaic. */
          .yw-mem-grid-inner {
            display: grid;
            grid-template-columns: repeat(6, 1fr);
            grid-auto-flow: dense;
            gap: 14px;
          }
          .yw-mem-card.is-lg { grid-column: span 2; }
          .yw-mem-card.is-md { grid-column: span 2; }

          @media (max-width: 1100px) {
            .yw-mem-grid-inner { grid-template-columns: repeat(4, 1fr); }
            .yw-mem-card.is-lg, .yw-mem-card.is-md { grid-column: span 2; }
          }
          @media (max-width: 720px) {
            .yw-mem-grid-inner { grid-template-columns: repeat(2, 1fr); gap: 10px; }
            .yw-mem-card.is-lg, .yw-mem-card.is-md { grid-column: span 1; }
            .yw-mem-card { min-height: 104px; padding: 20px; }
            .yw-mem-card.is-tall { min-height: 124px; }
            .yw-mem-logo { max-height: 56px; }
            .yw-mem-card.is-tall .yw-mem-logo { max-height: 68px; }
            .yw-mem-punch-num { font-size: 32px; }
          }
          @media (prefers-reduced-motion: reduce) {
            .yw-mem-card, .yw-mem-card.is-in { animation: none !important; opacity: 1 !important; }
          }
        `}</style>

        <div style={{ maxWidth: 1280, margin: "0 auto", position: "relative" }}>

          {/* Header ────────────────────────────────────────────────────── */}
          <div style={{ marginBottom: 72, maxWidth: 980 }}>
            <div style={{
                  fontSize: 13, fontWeight: 700, color: AOnDark,
                  textTransform: "uppercase", letterSpacing: ".14em", marginBottom: 18
                }}>YachtWay Members</div>
            <h2 style={{
                  fontFamily: T.fDisplay, fontSize: "clamp(40px, 5.5vw, 80px)", fontWeight: 700,
                  letterSpacing: "-0.035em", lineHeight: 1.0, margin: 0, color: "#fff",
                  textWrap: "balance"
                }}>
              The ones<br />who are here already.
            </h2>
            <p style={{
                  fontSize: 22, lineHeight: 1.45, color: "rgba(255,255,255,.62)",
                  margin: "28px 0 0", maxWidth: 640,
                  fontFamily: T.fDisplay, fontWeight: 500, letterSpacing: "-0.005em"
                }}>450+ Brokerages, Dealers, and Shipyards across 27 countries. Every one of them free to list. Every one of them part of what comes next.

                </p>
          </div>

          {/* Grid ──────────────────────────────────────────────────────── */}
          <div className="yw-mem-grid">
            <div className="yw-mem-grid-inner" ref={(el) => {
                  if (!el || el.__ywMemObserved) return;
                  el.__ywMemObserved = true;
                  // Observe each card; stagger reveal by DOM order so the wave
                  // moves left-to-right + top-to-bottom as the user scrolls in.
                  const cards = el.querySelectorAll(".yw-mem-card");
                  cards.forEach((card, i) => {
                    const row = Math.floor(i / 3);
                    card.classList.add(`is-breath-${row % 3}`);
                    card.style.animationDelay = `${i * 60}ms`;
                  });
                  const io = new IntersectionObserver((entries) => {
                    entries.forEach((entry) => {
                      if (entry.isIntersecting) {
                        entry.target.classList.add("is-in");
                        io.unobserve(entry.target);
                      }
                    });
                  }, { threshold: 0.15, rootMargin: "0px 0px -40px 0px" });
                  cards.forEach((card) => io.observe(card));
                }}>
              {MEMBERS.map((m, i) =>
                  <div
                    key={m.file}
                    className={[
                    "yw-mem-card",
                    m.size === "lg" ? "is-lg is-tall" : "is-md",
                    m.treat === "selfbg" ? "is-selfbg" : ""].
                    filter(Boolean).join(" ")}
                    title={m.name}>
                    
                  <img
                      src={(window.__YW_ASSETS && window.__YW_ASSETS[`assets/members/${m.file}`]) || `assets/members/${m.file}`}
                      alt={m.name}
                      className={[
                      "yw-mem-logo",
                      m.treat === "invert" ? "is-invert" : "",
                      m.treat === "invert-mono" ? "is-invert-mono" : "",
                      m.treat === "whiten" ? "is-whiten" : "",
                      m.treat === "screen" ? "is-screen" : ""].
                      filter(Boolean).join(" ")}
                      style={m.maxH ? { maxHeight: m.maxH } : undefined}
                      loading="lazy" />
                    
                </div>
                  )}
              {/* Punchline */}
              <div className="yw-mem-card is-md is-tall is-punch">
                <div style={{ textAlign: "center" }}>
                  <span className="yw-mem-punch-num">400+</span>
                  <span className="yw-mem-punch-sub">More worldwide</span>
                </div>
              </div>
            </div>
          </div>

          {/* Closing dedication ───────────────────────────────────────── */}
          <p style={{
                margin: "96px auto 0", maxWidth: 760, textAlign: "center",
                fontSize: 18, lineHeight: 1.6, color: "rgba(255,255,255,.45)",
                fontFamily: T.fBody, fontWeight: 500, textWrap: "pretty"
              }}>
            To every Member building the future of yacht sales with us - on behalf of our entire Team, <span style={{ color: "rgba(255,255,255,.85)" }}>Thank you</span>.
          </p>

          {/* CTA ─────────────────────────────────────────────────────── */}
          <div style={{
                margin: "40px auto 0", display: "flex", justifyContent: "center",
              }}>
            <a className="ed-btn-primary"
                href="http://yachtway.com/sign-up"
                target="_blank"
                rel="noopener noreferrer"
                style={{
                  padding: "20px 32px", borderRadius: 12, border: "none",
                  fontSize: 16, fontWeight: 600, fontFamily: T.fBody, cursor: "pointer",
                  display: "inline-flex", alignItems: "center", gap: 12,
                  textDecoration: "none"
                }}>
              Become a Member <Ic.arrow size={16} />
            </a>
          </div>
        </div>
      </section>);

      })()}

      {/* ── LEGACY PRICING CARDS removed per spec §3a/§3b — the static
          "Free / Paid" cards section was a duplicate pricing surface
          ahead of the configurator. Configurator below is now the
          single, unified pricing moment. */}
      {/* ── SERVICES & ADD-ONS — restored per design feedback (m0121).
          The configurator covers the recurring software subscription;
          this rail surfaces the à-la-carte production / financial
          services (Studio Pass, YachtWay LIVE, EasyFund, MasterCover,
          VATO, Connect, Dealer Website…). The earlier `id="pricing"`
          legacy duplicate stays hidden -- only the paid-cards grid is
          re-exposed below, reframed as Services rather than Pricing. */}
      <section id="pricing" style={{ display: "none" }} aria-hidden="true">
      <section id="pricing-legacy" style={{ padding: "120px 32px", background: T.bgAlt, borderTop: `1px solid ${T.border}`, scrollMarginTop: 80 }}>
        <div style={{ maxWidth: 1280, margin: "0 auto" }}>
          <div style={{ marginBottom: 56 }}>
            <div style={{ fontSize: 13, fontWeight: 600, color: T.accent,
              textTransform: "uppercase", letterSpacing: ".1em", marginBottom: 14 }}>Pricing</div>
            <h2 style={{ fontFamily: T.fDisplay, fontSize: 96, fontWeight: 700,
              letterSpacing: "-0.035em", lineHeight: 0.95, margin: 0 }}>
              Free to list.<br /> <span style={{ color: T.fgFaint }}>Pay for what you need.</span>
            </h2>
          </div>
          <div style={{ display: "grid", gridTemplateColumns: "5fr 7fr", gap: 16, alignItems: "start" }}>
            <div style={{
              background: T.bgDark, color: "#fff",
              borderRadius: 16, padding: 36,
              display: "flex", flexDirection: "column",
              border: "1px solid rgba(255,255,255,.08)",
              position: "sticky", top: 96, overflow: "hidden"
            }}>
              <div style={{
                position: "absolute", top: -100, right: -100, width: 320, height: 320,
                borderRadius: "50%",
                background: `radial-gradient(circle, ${glow(.40)}, transparent 70%)`
              }} />
              <div style={{ position: "relative" }}>
                <div style={{ fontSize: 13, fontWeight: 600, color: AOnDark,
                  textTransform: "uppercase", letterSpacing: ".12em", marginBottom: 18 }}>Always free</div>
                <div style={{ fontFamily: T.fDisplay, fontSize: 104, fontWeight: 700,
                  letterSpacing: "-0.04em", lineHeight: 1, marginBottom: 10 }}>$0</div>
                <div style={{ fontSize: 14, color: "rgba(255,255,255,.6)", marginBottom: 32 }}>
                  Every dealer, every listing.
                </div>
                <div style={{ display: "flex", flexDirection: "column", gap: 11 }}>
                  {CONTENT.pricing.free.map((p, i) =>
                  <div key={i} style={{ display: "flex", gap: 12, alignItems: "center", fontSize: 14, color: "rgba(255,255,255,.85)" }}>
                      <span style={{
                      width: 18, height: 18, borderRadius: 9, background: T.accent, color: "#fff",
                      display: "flex", alignItems: "center", justifyContent: "center", flex: "none"
                    }}><Ic.check size={11} /></span>
                      {p}
                    </div>
                  )}
                </div>
                <button className="ed-btn-primary" style={{
                  marginTop: 36, padding: "13px 18px", borderRadius: 10, border: "none",
                  fontSize: 14, fontWeight: 600, fontFamily: T.fBody, cursor: "pointer",
                  display: "inline-flex", alignItems: "center", justifyContent: "center", gap: 8, width: "100%"
                }}>Start free <Ic.arrow size={14} /></button>
              </div>
            </div>
            <div className="yw-flip-grid" style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12 }}>
              {CONTENT.pricing.paid.map((p, i) =>
              <PaidFlipCard key={i} p={p} T={T} rgba={rgba} />
              )}
            </div>
          </div>
        </div>
      </section>
      </section>
      {/* end legacy pricing-cards hidden block */}

      {/* ── SERVICES RAIL (re-exposed per m0121) ─────────────────────
          Just the paid services grid; no $0 column, no "Pricing" H2 --
          this section's job is to show the à-la-carte services that do
          NOT belong in the configurator (per-event production, loyalty
          program, finance products). Sits after the configurator so
          the recurring price story comes first. */}
      <section id="services" data-screen-label="08 Services" style={{
        padding: "120px 32px",
        background: T.bgAlt,
        borderTop: `1px solid ${T.border}`,
        scrollMarginTop: 0,
      }}>
        <div style={{ maxWidth: 1280, margin: "0 auto" }}>
          <div style={{ marginBottom: 56, maxWidth: 880 }}>
            <div style={{
              fontSize: 13, fontWeight: 600, color: T.accent,
              textTransform: "uppercase", letterSpacing: ".14em", marginBottom: 14,
            }}>Services &amp; add-ons</div>
            <h2 style={{
              fontFamily: T.fDisplay, fontSize: "clamp(40px, 5.5vw, 80px)",
              fontWeight: 700, letterSpacing: "-0.035em", lineHeight: 1.0, margin: 0,
            }}>
              Add only what moves the needle.
            </h2>
            <p style={{
              marginTop: 20, fontSize: 17, lineHeight: 1.55,
              color: T.fgFaint, maxWidth: 720, fontFamily: T.fBody,
            }}>
              Optional services , like live broadcasts, professional shoots, and buyer financing , 
              priced per use so they never inflate your monthly subscription. Tap any card to learn more.
            </p>
          </div>
          <div className="yw-flip-grid" style={{ display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(320px, 1fr))", gap: 12 }}>
            {CONTENT.pricing.paid.map((p, i) =>
              <PaidFlipCard key={i} p={p} T={T} rgba={rgba} />
            )}
          </div>
        </div>
      </section>

      {/* ── PLAN CONFIGURATOR (DARK, interactive) ───────────────────── */}
      {(() => {
        // ─── Pricing data ──────────────────────────────────────────
        const PLANS = {
          us_dealer: { region: "us", currency: "$", broker: 19, manager: 9, office: 69, brand: null, easySign: 269, vato: 99, api: 199, web: 250, live: 75, base: 0, label: "Dealership / Brokerage", regionLabel: "US (USD)" },
          us_shipyard: { region: "us", currency: "$", broker: 19, manager: 9, office: null, brand: 99, easySign: 269, vato: 99, api: 199, web: 250, live: 75, base: 0, label: "Shipyard", regionLabel: "US (USD)" },
          eu_dealer: { region: "eu", currency: "€", broker: 12, manager: 5, office: 49, brand: null, easySign: null, vato: 79, api: 69, web: 209, live: 60, base: 0, label: "Dealership / Brokerage", regionLabel: "EU (EUR)" },
          eu_shipyard: { region: "eu", currency: "€", broker: 12, manager: 5, office: null, brand: 69, easySign: null, vato: 79, api: 69, web: 209, live: 60, base: 0, label: "Shipyard", regionLabel: "EU (EUR)" }
        };
        // Competitor estimates (per-line monthly $/€). Sources: public pricing pages,
        // dealer interviews, and Semrush domain reports (Apr - May 2026).
        // Numbers reflect the LOW end of each range (kindest spin to competitors).
        const COMPETITORS = {
          us: [
          { k: "ywld", name: "YachtWorld", sub: "incl. Boats.com, BoatTrader", base: 2500, broker: 50, manager: 0, office: 300, brand: 300, easySign: 0, vato: 0, api: 0, live: 0, note: "Avg $2,500/mo + $50/seat (varies by package)." },
          { k: "rbt", name: "Rightboat", sub: "UK / EU focus", base: 0, broker: 0, manager: 0, office: 0, brand: 0, easySign: null, vato: null, api: null, live: null, note: "£25/lead. No monthly floor." },
          { k: "ychr", name: "Yachtr", sub: "IYBA membership required", base: 399, broker: 25, manager: 0, office: 150, brand: 150, easySign: null, vato: null, api: null, live: null, note: "$399 - $1,199/mo + IYBA fees." },
          { k: "ytco", name: "Yatco", sub: "Pricing not public", unknown: true, base: 0, broker: 0, manager: 0, office: 0, brand: 0, easySign: null, vato: null, api: null, live: null, note: "B2B MLS feed." },
          { k: "msrc", name: "MarineSource", sub: "Pricing not public", unknown: true, base: 0, broker: 0, manager: 0, office: 0, brand: 0, easySign: null, vato: null, api: null, live: null, note: "Feed-based pricing, opaque." }],

          eu: [
          { k: "ywld", name: "YachtWorld", sub: "incl. Boats.com", base: 2300, broker: 45, manager: 0, office: 260, brand: 260, easySign: 0, vato: 0, api: 0, live: 0, note: "Avg €2,300/mo + €45/seat (varies by package)." },
          { k: "rbt", name: "Rightboat", sub: "UK / EU focus", base: 0, broker: 0, manager: 0, office: 0, brand: 0, easySign: null, vato: null, api: null, live: null, note: "£25/lead. No monthly floor." },
          { k: "ychr", name: "Yachtr", sub: "IYBA membership required", base: 349, broker: 22, manager: 0, office: 130, brand: 130, easySign: null, vato: null, api: null, live: null, note: "€349 - €1,049/mo + IYBA fees." },
          { k: "ytco", name: "Yatco", sub: "Pricing not public", unknown: true, base: 0, broker: 0, manager: 0, office: 0, brand: 0, easySign: null, vato: null, api: null, live: null, note: "B2B MLS feed." },
          { k: "msrc", name: "MarineSource", sub: "Pricing not public", unknown: true, base: 0, broker: 0, manager: 0, office: 0, brand: 0, easySign: null, vato: null, api: null, live: null, note: "Feed-based pricing, opaque." }]

        };

        const [region, setRegion] = useState("us");
        const [persona, setPersona] = useState("dealer");
        const [brokers, setBrokers] = useState(1); // 1 broker seat by default
        const [managers, setManagers] = useState(1);
        const [offices, setOffices] = useState(0); // additional offices beyond the 1 included
        const [brands, setBrands] = useState(0); // additional brands (Shipyard only)
        const [easySign, setEasySign] = useState(false); // off by default; user opts in
        const [vato, setVato] = useState(false);
        const [api, setApi] = useState(false);
        const [web, setWeb] = useState(false);
        const [liveSessions, setLiveSessions] = useState(0);
        const [freeListings, setFreeListings] = useState(false);
        // Floating plan-summary chip in the lower-right of the configure
        // section. Hidden by default; appears once the user scrolls down
        // to Step 2 (the first step that actually moves the price), and
        // hides again once the configure section has scrolled past. The
        // earlier sticky-bar lived at the top of the section and felt
        // like a header rather than a running total -- the floating chip
        // is more like the iOS "continue" pill: out of the way, never
        // covers the steps, only present while the user is configuring.
        const [floatVisible, setFloatVisible] = useState(false);
        useEffect(() => {
          const onScroll = () => {
            const s2 = document.getElementById('cfg-step2');
            const sec = document.getElementById('configure');
            if (!s2 || !sec) return;
            const s2Top = s2.getBoundingClientRect().top;
            const secBottom = sec.getBoundingClientRect().bottom;
            // Show when Step 2's top crosses ~60% of the viewport (the
            // user is clearly engaged with team-size at that point) and
            // keep it visible until the configure section scrolls past
            // the navbar.
            setFloatVisible(s2Top < window.innerHeight * 0.6 && secBottom > 96);
          };
          onScroll();
          window.addEventListener('scroll', onScroll, { passive: true });
          window.addEventListener('resize', onScroll);
          return () => {
            window.removeEventListener('scroll', onScroll);
            window.removeEventListener('resize', onScroll);
          };
        }, []);
        // Per-competitor monthly overrides keyed by competitor key (ywld, msrc, ytco, etc.).
        // Lets dealers plug in their actual numbers for accurate savings.
        const [compOverrides, setCompOverrides] = useState({});
        const ywldEditedRef = useRefD(false);
        const setCompOverride = (k, v) => {
          if (k === "ywld") ywldEditedRef.current = true;
          setCompOverrides((prev) => ({ ...prev, [k]: v }));
        };

        // ── Seed from §2 cost calculator ─────────────────────────
        // On mount, pull dealership/broker/current-monthly values from the
        // shared deal store so the configurator continues the §2 conversation
        // instead of resetting it. Seats only seed once (so the user can
        // adjust here freely), but the YachtWorld competitor row stays
        // *live-synced* to the §2 monthly figure, so dragging the slider
        // up there updates the savings comparison down here in real time.
        // We track whether the user has edited the YachtWorld override
        // manually; once they do, we stop overwriting it from §2.
        // (`ywldEditedRef` is declared above next to `setCompOverride`.)
        useEffect(() => {
          if (!window.__YW_DEAL) return;
          const seed = window.__YW_DEAL.get();
          if (seed.brokers && seed.brokers > 0) setBrokers(seed.brokers);
          if (seed.brokers && seed.brokers >= 4) {
            setManagers(Math.max(1, Math.round(seed.brokers / 4)));
          }
          if (seed.currentMonthly && seed.currentMonthly > 0) {
            setCompOverrides((prev) => ({
              ...prev,
              ywld: prev.ywld || String(seed.currentMonthly),
            }));
          }
          // Live-sync: any change to currentMonthly in §2 flows here.
          return window.__YW_DEAL.on((s) => {
            if (ywldEditedRef.current) return;
            if (s.currentMonthly && s.currentMonthly > 0) {
              setCompOverrides((prev) => ({
                ...prev,
                ywld: String(s.currentMonthly),
              }));
            }
          });
          // eslint-disable-next-line react-hooks/exhaustive-deps
        }, []);

        const planKey = `${region}_${persona}`;
        const P = PLANS[planKey];
        const fmt = (n) => `${P.currency}${Math.round(n).toLocaleString("en-US")}`;

        // ─ YachtWay total ─
        const ywBrokerCost = brokers * P.broker;
        const ywManagerCost = managers * P.manager;
        const ywOfficeCost = persona === "dealer" && P.office ? offices * P.office : 0;
        const ywBrandCost = persona === "shipyard" && P.brand ? brands * P.brand : 0;
        const ywEasySignCost = P.easySign && easySign ? P.easySign : 0;
        const ywVatoCost = P.vato && vato ? P.vato : 0;
        // Website includes API feed at no charge. When website is on, API is
        // forced on and its line item cost goes to 0.
        const apiEffective = web || api;
        const ywApiCost = P.api && api && !web ? P.api : 0;
        const ywWebCost = P.web && web ? P.web : 0;
        // YachtWay LIVE was removed from the configurator (m0093) -- it is
        // a per-event production service, not a monthly subscription line.
        // It now lives as a dedicated services card alongside Studio Pass.
        // We keep `ywLiveCost = 0` so any downstream math that still
        // references it stays a no-op.
        const ywLiveCost = 0;
        const ywMonthly = ywBrokerCost + ywManagerCost + ywOfficeCost + ywBrandCost +
        ywEasySignCost + ywVatoCost + ywApiCost + ywWebCost;

        // ─ Competitor totals ─
        // Note: YachtWay LIVE is excluded from competitor comparison. It is a
        // YachtWay-only product (no equivalent on the other platforms), so we
        // compare like-for-like on broker seats, offices, brands, EasySign,
        // VATO, and API feed only. The LIVE line is shown separately on the
        // YachtWay breakdown.
        const compRegion = COMPETITORS[region];
        const compTotals = compRegion.map((c) => {
          const seats = (brokers + managers) * (c.broker || 0);
          const officeAdd = persona === "dealer" ? offices * (c.office || 0) : 0;
          const brandAdd = persona === "shipyard" ? brands * (c.brand || 0) : 0;
          const sign = easySign ? c.easySign || 0 : 0;
          const v = vato ? c.vato || 0 : 0;
          const a = api ? c.api || 0 : 0;
          // Per-competitor user overrides (numeric monthly TOTAL), if set.
          // When set, we use ov as-is, the dealer enters their actual all-in
          // cost, so we do NOT layer seats/add-ons on top.
          const ov = parseFloat(compOverrides[c.k]);
          const hasOv = !isNaN(ov) && ov > 0;
          // For unknown-priced competitors, only count the override (no add-ons).
          const monthly = hasOv ?
          ov :
          c.unknown ? null : c.base + seats + officeAdd + brandAdd + sign + v + a;
          // l (LIVE) intentionally excluded, not available on competitors.
          return { ...c, monthly, hasOv, unknown: c.unknown && !hasOv };
        });

        // Like-for-like total. With LIVE no longer in the configurator,
        // this is just the monthly itself -- kept as a named alias so
        // downstream references (savings line, breakdown table) keep
        // working without churn.
        const ywMonthlyLikeForLike = ywMonthly;

        // Headline comparison: sum across every priced competitor in the
        // user's region. Dealers typically pay several listing platforms
        // simultaneously, the savings figure reflects what they would
        // pay, in total, if they kept paying all of them. Unknown-pricing
        // platforms are excluded because we cannot estimate them honestly.
        const cheapest = compTotals.find((c) => c.k === "ywld") || compTotals[0];
        const pricedComps = compTotals.filter((c) => !c.unknown);
        const sumCompMonthly = pricedComps.reduce((s, c) => s + (c.monthly || 0), 0);
        // Savings on a like-for-like basis (LIVE excluded, not on competitors).
        const annualSavings = (sumCompMonthly - ywMonthlyLikeForLike) * 12;

        // ─ Line items for the breakdown table ─
        const yLines = [
        { label: "Listings", amount: 0, free: true, alwaysShow: true },
        { label: `${brokers} broker seat${brokers === 1 ? "" : "s"}`, amount: ywBrokerCost, alwaysShow: true },
        { label: `${managers} manager seat${managers === 1 ? "" : "s"}`, amount: ywManagerCost, alwaysShow: true },
        persona === "dealer" && P.office ? { label: `${offices} additional office${offices === 1 ? "" : "s"}`, amount: ywOfficeCost } : null,
        persona === "shipyard" && P.brand ? { label: `${brands} additional brand${brands === 1 ? "" : "s"}`, amount: ywBrandCost } : null,
        P.easySign ? { label: "EasySign", amount: ywEasySignCost, optional: true, on: easySign } : null,
        P.vato ? { label: "VATO valuation", amount: ywVatoCost, optional: true, on: vato } : null,
        P.web ? { label: "Website", amount: ywWebCost, optional: true, on: web } : null,
        P.api ? { label: web ? "API feed (included with Website)" : "API feed", amount: ywApiCost, optional: true, on: apiEffective } : null].
        filter(Boolean);

        // ─ Reusable bits ─
        const SegBtn = ({ active, onClick, children }) =>
        <button onClick={onClick} style={{
          padding: "9px 16px", border: "none", cursor: "pointer",
          fontSize: 13, fontWeight: 600, fontFamily: T.fBody,
          color: active ? T.fg : "rgba(255,255,255,.55)",
          background: active ? "#fff" : "transparent",
          borderRadius: 999, transition: "background .15s, color .15s",
          letterSpacing: "-0.005em"
        }}>{children}</button>;

        const InfoTip = ({ tip }) => {
          if (!tip) return null;
          // Lightweight CSS-only tooltip, sits inline next to the label.
          // Hover/focus the (?) circle to reveal the bubble. Pure CSS so it
          // works without extra state and stays accessible via tab/focus.
          return (
            <span
              tabIndex={0}
              style={{
                display: "inline-flex", alignItems: "center", justifyContent: "center",
                width: 15, height: 15, borderRadius: "50%",
                background: "rgba(255,255,255,.10)", color: "rgba(255,255,255,.7)",
                fontSize: 13, fontWeight: 700, fontFamily: T.fBody,
                marginLeft: 7, cursor: "help", verticalAlign: "middle",
                position: "relative", outline: "none",
                transition: "background .15s, color .15s"
              }}
              className="yw-infotip"
              onMouseEnter={(e) => {
                const b = e.currentTarget.querySelector(".yw-infotip-bubble");
                if (b) b.style.opacity = 1, b.style.transform = "translate(-50%, -4px)", b.style.pointerEvents = "auto";
              }}
              onMouseLeave={(e) => {
                const b = e.currentTarget.querySelector(".yw-infotip-bubble");
                if (b) b.style.opacity = 0, b.style.transform = "translate(-50%, 0)", b.style.pointerEvents = "none";
              }}
              onFocus={(e) => {
                const b = e.currentTarget.querySelector(".yw-infotip-bubble");
                if (b) b.style.opacity = 1, b.style.transform = "translate(-50%, -4px)", b.style.pointerEvents = "auto";
              }}
              onBlur={(e) => {
                const b = e.currentTarget.querySelector(".yw-infotip-bubble");
                if (b) b.style.opacity = 0, b.style.transform = "translate(-50%, 0)", b.style.pointerEvents = "none";
              }}>
              
              ?
              <span
                className="yw-infotip-bubble"
                role="tooltip"
                style={{
                  position: "absolute", bottom: "calc(100% + 8px)", left: "50%",
                  transform: "translate(-50%, 0)", opacity: 0, pointerEvents: "none",
                  width: 240, padding: "10px 12px", borderRadius: 8,
                  background: "#0a0a0c", color: "#fff",
                  border: "1px solid rgba(255,255,255,.14)",
                  fontSize: 13, lineHeight: 1.45, fontWeight: 400,
                  textAlign: "left", whiteSpace: "normal",
                  boxShadow: "0 8px 24px rgba(0,0,0,.5)",
                  transition: "opacity .15s ease, transform .15s ease",
                  zIndex: 50
                }}>
                
                {tip}
                <span style={{
                  position: "absolute", top: "100%", left: "50%",
                  transform: "translateX(-50%)",
                  width: 0, height: 0,
                  borderLeft: "5px solid transparent",
                  borderRight: "5px solid transparent",
                  borderTop: "5px solid #0a0a0c"
                }} />
              </span>
            </span>);

        };
        const Stepper = ({ label, value, set, min = 0, max = 99, sub, tip }) =>
        <div style={{
          display: "grid", gridTemplateColumns: "1fr auto", alignItems: "center",
          padding: "14px 0", borderBottom: "1px solid rgba(255,255,255,.06)", gap: 16
        }}>
            <div>
              <div style={{ fontSize: 14, fontWeight: 600, color: "#fff", letterSpacing: "-0.005em" }}>
                {label}<InfoTip tip={tip} />
              </div>
              {sub ? <div style={{ fontSize: 13, color: "rgba(255,255,255,.45)", marginTop: 3 }}>{sub}</div> : null}
            </div>
            <div style={{ display: "inline-flex", alignItems: "center", gap: 0,
            background: "rgba(255,255,255,.05)", border: "1px solid rgba(255,255,255,.10)",
            borderRadius: 999, overflow: "hidden"
          }}>
              <button onClick={() => set(Math.max(min, value - 1))}
            style={{ width: 32, height: 32, border: "none", background: "transparent", color: "#fff", cursor: "pointer", fontSize: 16 }}
            aria-label="Decrease">
              −</button>
              <div style={{ minWidth: 36, textAlign: "center", fontFamily: T.fDisplay,
              fontSize: 15, fontWeight: 700, color: "#fff" }}>{value}</div>
              <button onClick={() => set(Math.min(max, value + 1))}
            style={{ width: 32, height: 32, border: "none", background: "transparent", color: "#fff", cursor: "pointer", fontSize: 16 }}
            aria-label="Increase">
              +</button>
            </div>
          </div>;

        const Toggle = ({ label, value, set, price, sub, disabled, tip }) =>
        <div style={{
          display: "grid", gridTemplateColumns: "1fr auto auto", alignItems: "center",
          padding: "14px 0", borderBottom: "1px solid rgba(255,255,255,.06)", gap: 16,
          opacity: disabled ? 0.35 : 1
        }}>
            <div>
              <div style={{ fontSize: 14, fontWeight: 600, color: "#fff", letterSpacing: "-0.005em" }}>
                {label}<InfoTip tip={tip} />
              </div>
              {sub ? <div style={{ fontSize: 13, color: "rgba(255,255,255,.45)", marginTop: 3 }}>{sub}</div> : null}
            </div>
            <div style={{ fontSize: 13, color: "rgba(255,255,255,.6)", whiteSpace: "nowrap" }}>{price}</div>
            <button
            onClick={() => !disabled && set(!value)}
            disabled={disabled}
            style={{
              width: 40, height: 22, borderRadius: 999,
              border: "none", padding: 0, cursor: disabled ? "not-allowed" : "pointer",
              background: value && !disabled ? A : "rgba(255,255,255,.12)",
              position: "relative", transition: "background .15s"
            }}
            aria-label={label}>
            
              <span style={{
              position: "absolute", top: 2, left: value ? 20 : 2,
              width: 18, height: 18, borderRadius: "50%", background: "#fff",
              transition: "left .15s"
            }} />
            </button>
          </div>;


        // ── Step header (Apple-style numbered chapters) ─────────────
        const StepHead = ({ n, kicker, title, sub }) =>
        <div style={{ marginBottom: 28, display: "flex", alignItems: "flex-start", gap: 20 }}>
          <div style={{
            flex: "none",
            width: 44, height: 44, borderRadius: "50%",
            background: rgba(A, .14),
            border: `1px solid ${rgba(A, .35)}`,
            color: AL,
            display: "flex", alignItems: "center", justifyContent: "center",
            fontFamily: T.fDisplay, fontSize: 18, fontWeight: 800, letterSpacing: "-0.02em",
            marginTop: 4
          }}>{n}</div>
          <div style={{ flex: 1, minWidth: 0 }}>
            {kicker ?
            <div style={{ fontSize: 12, fontWeight: 700, color: AOnDark,
              textTransform: "uppercase", letterSpacing: ".14em", marginBottom: 6 }}>{kicker}</div> :
            null}
            <h3 style={{ fontFamily: T.fDisplay, fontSize: 36, fontWeight: 700,
              letterSpacing: "-0.025em", lineHeight: 1.05, margin: 0 }}>{title}</h3>
            {sub ?
            <div style={{ fontSize: 16, color: "rgba(255,255,255,.6)", marginTop: 10,
              maxWidth: 720, lineHeight: 1.55, fontWeight: 400 }}>{sub}</div> :
            null}
          </div>
        </div>;

        // ── Card chrome (every step lives in one of these) ─────────
        const stepCard = {
          background: "rgba(255,255,255,.03)",
          border: "1px solid rgba(255,255,255,.10)",
          borderRadius: 24,
          padding: 36
        };

        // Plain-English plan summary, used in Step 4.
        const planSummary = (() => {
          const parts = [];
          parts.push(`${brokers} broker${brokers === 1 ? "" : "s"}`);
          if (managers > 0) parts.push(`${managers} manager${managers === 1 ? "" : "s"}`);
          if (persona === "dealer" && offices > 0) parts.push(`${offices} extra office${offices === 1 ? "" : "s"}`);
          if (persona === "shipyard" && brands > 0) parts.push(`${brands} extra brand${brands === 1 ? "" : "s"}`);
          if (easySign && P.easySign) parts.push("EasySign");
          if (vato && P.vato) parts.push("VATO");
          if (web && P.web) parts.push("Website");
          if (apiEffective && !web && P.api) parts.push("API feed");
          if (liveSessions > 0) parts.push(`${liveSessions} LIVE / mo`);
          return parts.join(" · ");
        })();

        // Competitor rows for Step 5. Keep them in the source order
        // declared in COMPETITORS[region] so that editing a price live
        // does NOT re-shuffle the list under the user's cursor (the
        // earlier "largest overpay first" sort caused rows to leapfrog
        // each other as soon as the user typed, which felt jumpy). We
        // still annotate each row with its delta for the verdict copy.
        const overpayRows = [...compTotals].
        map((c) => ({ ...c, delta: c.unknown ? null : c.monthly - ywMonthlyLikeForLike }));

        return (
          <section id="configure" data-screen-label="07 Pricing" style={{ padding: "120px 32px", background: T.bgDark, color: "#fff", position: "relative" }}>
            <a id="pricing-anchor" style={{ position: "absolute", top: -80 }} aria-hidden="true" />
            <div style={{ maxWidth: 1080, margin: "0 auto", position: "relative" }}>

              {/* Header */}
              <div style={{ marginBottom: 64, textAlign: "center" }}>
                <div style={{ fontSize: 13, fontWeight: 600, color: AOnDark,
                  textTransform: "uppercase", letterSpacing: ".14em", marginBottom: 18 }}>Build your plan</div>
                <h2 style={{ fontFamily: T.fDisplay, fontSize: "clamp(40px, 5.5vw, 80px)", fontWeight: 700,
                  letterSpacing: "-0.035em", lineHeight: 1.0, margin: "0 auto", maxWidth: 880 }}>
                  Three answers.<br />
                  <span style={{ color: "rgba(255,255,255,.45)" }}>One honest price.</span>
                </h2>
                <div style={{ fontSize: 17, color: "rgba(255,255,255,.65)",
                  maxWidth: 620, margin: "24px auto 0", lineHeight: 1.55, fontWeight: 400 }}>
                  Tell us about your team. We will show you exactly what
                  you would pay on YachtWay ,  and exactly how much
                  you are overpaying everywhere else.
                </div>

                {/* §5 named dealer quote — removed per design feedback (m0078). */}
              </div>

              {/* Floating running total -- moved out of the sticky-top
                  position into a fixed lower-right chip per design
                  feedback (m0099). Visibility gated on `floatVisible`,
                  which flips true once Step 2 enters the upper half of
                  the viewport. Hidden on phone via mobile.css. */}
              <div
                className="yw-cfg-float"
                aria-hidden={!floatVisible}
                style={{
                  position: "fixed",
                  bottom: 24, right: 24, zIndex: 60,
                  display: "inline-flex", alignItems: "center", gap: 14,
                  padding: "12px 20px",
                  borderRadius: 999,
                  background: "rgba(10,10,12,.85)",
                  backdropFilter: "blur(14px)",
                  WebkitBackdropFilter: "blur(14px)",
                  border: `1px solid ${rgba(A, .35)}`,
                  boxShadow: "0 12px 32px rgba(0,0,0,.55)",
                  opacity: floatVisible ? 1 : 0,
                  transform: floatVisible ? "translateY(0)" : "translateY(8px)",
                  pointerEvents: floatVisible ? "auto" : "none",
                  transition: "opacity .25s ease, transform .25s ease",
                }}
              >
                <span style={{ fontSize: 11, fontWeight: 700, color: AOnDark,
                  textTransform: "uppercase", letterSpacing: ".14em" }}>Your plan</span>
                <span key={ywMonthly} style={{
                  fontFamily: T.fDisplay, fontSize: 22, fontWeight: 800,
                  letterSpacing: "-0.02em", color: "#fff",
                  animation: "ed-pop .35s ease-out"
                }}>{fmt(ywMonthly)}<span style={{
                  fontSize: 13, color: "rgba(255,255,255,.55)", fontWeight: 500
                }}> /mo</span></span>
              </div>
              <style>{`@keyframes ed-pop { 0% { transform: translateY(2px); opacity: .4 } 100% { transform: translateY(0); opacity: 1 } }`}</style>

              {/* §3e pre-fill pill removed per design feedback. */}

              {/* STEP 0 (Anchor your numbers) — removed per design feedback (m0079).
                  YachtWorld baseline now uses the published market average; users can
                  still override per-platform inline in the comparison table below. */}

              {/* ───────── STEP 1, Who are you? ───────── */}
              <div style={{ ...stepCard, marginBottom: 16 }}>
                <StepHead
                  n="1"
                  kicker="Who are you?"
                  title="Pick your region and what you do."
                  sub="Pricing and add-ons differ by region." />
                <div style={{ display: "flex", flexWrap: "wrap", gap: 12 }}>
                  <div style={{ display: "inline-flex", padding: 4, borderRadius: 999,
                    background: "rgba(255,255,255,.05)", border: "1px solid rgba(255,255,255,.10)" }}>
                    <SegBtn active={region === "us"} onClick={() => setRegion("us")}>US (USD)</SegBtn>
                    <SegBtn active={region === "eu"} onClick={() => setRegion("eu")}>EU (EUR)</SegBtn>
                  </div>
                  <div style={{ display: "inline-flex", padding: 4, borderRadius: 999,
                    background: "rgba(255,255,255,.05)", border: "1px solid rgba(255,255,255,.10)" }}>
                    <SegBtn active={persona === "dealer"} onClick={() => setPersona("dealer")}>Dealership / Brokerage</SegBtn>
                    <SegBtn active={persona === "shipyard"} onClick={() => setPersona("shipyard")}>Shipyard</SegBtn>
                  </div>
                </div>
              </div>

              {/* ───────── STEP 2, Team size ─────────
                  id is the trigger anchor for the floating plan-summary
                  chip in the lower-right (see floatVisible effect). */}
              <div id="cfg-step2" style={{ ...stepCard, marginBottom: 16 }}>
                <StepHead
                  n="2"
                  kicker="Your team"
                  title="How big is your team?"
                  sub="Listings are always free. Add brokers so leads route directly to the people who close them, not to an office line that goes quiet at 5pm." />
                <button
                  type="button"
                  onClick={() => setFreeListings(v => !v)}
                  aria-pressed={freeListings}
                  style={{
                    width: "100%", textAlign: "left", cursor: "pointer",
                    display: "grid",
                    gridTemplateColumns: "1fr auto auto",
                    alignItems: "center", columnGap: 16,
                    padding: "18px 20px", marginBottom: 18,
                    border: `1.5px solid ${freeListings ? A : "rgba(255,255,255,.12)"}`,
                    background: freeListings ? rgba(A, .14) : "rgba(255,255,255,.025)",
                    borderRadius: 14,
                    transition: "background .18s ease, border-color .18s ease",
                    fontFamily: T.fBody,
                  }}
                >
                  <div style={{ minWidth: 0 }}>
                    <div style={{ color: "#fff", fontSize: 15, fontWeight: 700, marginBottom: 4 }}>
                      Free company listings
                    </div>
                    <div style={{ fontSize: 13.5, color: "rgba(255,255,255,.75)", lineHeight: 1.5 }}>
                      {freeListings
                        ? "Included. Your inventory lists at zero cost. Add broker seats below, leads go straight to the broker who can close, not the office voicemail."
                        : "Toggle on to confirm. Any organization can list inventory on YachtWay at zero cost. Most teams add broker seats below for direct lead routing, buyers reach the closer, not the front desk."}
                    </div>
                  </div>
                  <span style={{
                    fontSize: 13, color: "rgba(255,255,255,.6)", whiteSpace: "nowrap",
                    fontFamily: T.fBody,
                  }}>{fmt(0)} / mo</span>
                  <div style={{
                    flex: "0 0 auto", width: 40, height: 22, borderRadius: 999,
                    background: freeListings ? A : "rgba(255,255,255,.18)",
                    position: "relative",
                    transition: "background .18s ease",
                  }}>
                    <div style={{
                      position: "absolute", top: 2, left: freeListings ? 20 : 2,
                      width: 18, height: 18, borderRadius: "50%", background: "#fff",
                      transition: "left .18s ease",
                      boxShadow: "0 2px 6px rgba(0,0,0,.25)",
                    }}/>
                  </div>
                </button>
                <div>
                  <Stepper label="Broker seats" value={brokers} set={setBrokers} sub={`${fmt(P.broker)} / seat / month · brokers get the leads directly`}
                    tip="Each broker gets their own profile, direct lead routing (calls + messages hit their phone, not the office line), EasySign access, the ability to create listings, manage leads, see analytics, go live, and run events. Buyers reach the person who can close, not voicemail after 5pm." />
                  <Stepper label="Manager seats" value={managers} set={setManagers} sub={`${fmt(P.manager)} / seat / month`}
                    tip="Managers can list, manage the company profile, and create contracts with EasySign (EasySign subscription required). Unlike brokers, manager names are not displayed on the listing page." />
                  {persona === "dealer" && P.office ?
                  <Stepper label="Additional offices" value={offices} set={setOffices} sub={`${fmt(P.office)} / office / month · 1 included`}
                    tip="Your first office is included. Each additional office gets its own branded micro-site, lead routing, and inventory section. Useful when locations operate with separate teams or stock." /> :
                  null}
                  {persona === "shipyard" && P.brand ?
                  <Stepper label="Additional brands" value={brands} set={setBrands} sub={`${fmt(P.brand)} / brand / month · 1 included`}
                    tip="Your first brand is included. Each additional brand gets its own dedicated showroom page, model catalog, and lead routing, ideal for shipyards representing multiple builders." /> :
                  null}
                  {/* LIVE-sessions stepper removed (m0093). LIVE is a
                      per-event production service, not a recurring
                      subscription line -- it lives as its own services
                      card next to Studio Pass below. */}
                </div>
              </div>

              {/* ───────── STEP 3, Add-ons ───────── */}
              <div style={{ ...stepCard, marginBottom: 16 }}>
                <StepHead
                  n="3"
                  kicker="Add-ons"
                  title="Which tools do you actually need?"
                  sub="Toggle anything you would use today. You can also add services later when you need them." />
                <div>
                  <Toggle label="EasySign" value={easySign} set={setEasySign}
                    price={P.easySign ? `${fmt(P.easySign)} / mo` : "Not in EU yet"}
                    sub="Replaces DocuSign Business Pro ($300+/mo). All contracts audit-trailed and timestamped."
                    disabled={!P.easySign} />
                  <Toggle label="VATO valuation" value={vato} set={setVato}
                    price={P.vato ? `${fmt(P.vato)} / mo` : "Not in EU yet"}
                    sub="Org-wide vessel valuations. Eliminates manual appraisal requests for pricing meetings."
                    disabled={!P.vato} />
                  <Toggle label="Dealer Website" value={web} set={setWeb}
                    price={P.web ? `${fmt(P.web)} / mo + setup` : "-"}
                    sub="Branded dealer site with live inventory feed. API included. One-time setup quoted separately."
                    tip="The monthly fee covers hosting, the inventory sync engine, and ongoing platform updates. A one-time setup fee is quoted separately based on the scope of work (design, content migration, custom integrations)." />
                  <Toggle label="API feed (out)" value={apiEffective} set={web ? () => {} : setApi}
                    price={web ? "Included with Website" : P.api ? `${fmt(P.api)} / mo` : "-"}
                    sub={web ? "API feed to your site, included free with Website add-on." : "Inventory synced to your site automatically. Included free with Website add-on."}
                    disabled={web} />
                </div>
              </div>

              {/* ───────── STEP 4, Your YachtWay plan ───────── */}
              <div style={{
                ...stepCard, marginBottom: 16,
                background: `linear-gradient(135deg, ${rgba(A, .14)}, transparent 65%), rgba(255,255,255,.03)`,
                border: `1px solid ${rgba(A, .30)}`
              }}>
                <StepHead
                  n="4"
                  kicker="Your plan"
                  title="Here is your YachtWay price."
                  sub="No listing fees, no per-lead surcharges, no surprise tier upgrades. The number below is the number you pay." />

                <div style={{
                  display: "grid", gridTemplateColumns: "1fr auto",
                  gap: 32, alignItems: "end",
                  marginTop: 12
                }} className="yw-cfg-plan-row">
                  <div>
                    <div key={ywMonthly} style={{
                      fontFamily: T.fDisplay, fontSize: 120, fontWeight: 800,
                      letterSpacing: "-0.045em", lineHeight: 0.92,
                      animation: "ed-pop .35s ease-out"
                    }}>
                      {fmt(ywMonthly)}<span style={{
                        fontSize: 22, color: "rgba(255,255,255,.5)", fontWeight: 500,
                        letterSpacing: "0", marginLeft: "0.15em",
                        display: "inline-block",
                      }}>/mo</span>
                    </div>
                    <div style={{ fontSize: 16, color: "rgba(255,255,255,.7)",
                      marginTop: 16, lineHeight: 1.5, maxWidth: 620 }}>
                      {planSummary}
                    </div>
                    <div style={{ fontSize: 14, color: "rgba(255,255,255,.4)", marginTop: 8 }}>
                      {fmt(ywMonthly * 12)} / year &middot; cancel anytime.
                    </div>
                  </div>
                </div>

                {/* Itemized breakdown, collapsed by default */}
                <details style={{ marginTop: 28 }}>
                  <summary style={{
                    cursor: "pointer", listStyle: "none",
                    fontSize: 13, fontWeight: 700, color: AOnDark,
                    textTransform: "uppercase", letterSpacing: ".12em",
                    display: "inline-flex", alignItems: "center", gap: 8,
                    userSelect: "none"
                  }}>
                    <span>See line-by-line breakdown</span>
                    <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
                      <polyline points="6 9 12 15 18 9" />
                    </svg>
                  </summary>
                  <div style={{ marginTop: 18, display: "flex", flexDirection: "column" }}>
                    {yLines.filter((l) => !(l.optional && !l.on)).map((l, i) =>
                    <div key={i} style={{
                      display: "grid", gridTemplateColumns: "1fr auto", gap: 16,
                      padding: "12px 0",
                      borderTop: i ? "1px solid rgba(255,255,255,.06)" : "1px solid rgba(255,255,255,.10)"
                    }}>
                        <span style={{ fontSize: 15, color: "#fff" }}>{l.label}</span>
                        <span style={{ fontFamily: T.fDisplay, fontSize: 15, fontWeight: 700, color: l.free ? AL : "#fff" }}>
                          {l.free ? "Free" : l.amount > 0 ? fmt(l.amount) : "-"}
                        </span>
                      </div>
                    )}
                    <div style={{
                      display: "grid", gridTemplateColumns: "1fr auto", gap: 16,
                      padding: "16px 0 0", marginTop: 4,
                      borderTop: "1px solid rgba(255,255,255,.20)"
                    }}>
                      <span style={{ fontSize: 13, fontWeight: 700, color: AOnDark,
                        textTransform: "uppercase", letterSpacing: ".12em" }}>Monthly total</span>
                      <span style={{ fontFamily: T.fDisplay, fontSize: 22, fontWeight: 800, color: "#fff", letterSpacing: "-0.02em" }}>{fmt(ywMonthly)}</span>
                    </div>
                  </div>
                </details>
              </div>

              {/* ───────── STEP 5, Here is what you save ───────── */}
              <div style={{ ...stepCard, marginBottom: 16 }}>
                <StepHead
                  n="5"
                  kicker="Compare &amp; save"
                  title="See what you could save vs. what you pay today."
                  sub={
                    <span>
                      Below are the platforms most dealers already pay for.{" "}
                      <span style={{ color: "#fff", fontWeight: 600 }}>Tap any price and enter what you actually pay each month.</span>{" "}
                      We will add it up against your YachtWay plan and show your real savings ,  the verdict lands at the bottom.
                    </span>
                  } />

                {/* §3d Post-result CTAs were here; moved BELOW the list per
                    design feedback (m0131) so the verdict and the next
                    step both land after the user has plugged in their
                    actual prices. */}

                <div style={{ display: "flex", flexDirection: "column", gap: 10, marginTop: 8 }}>
                  {overpayRows.map((row) => {
                    const unknown = row.unknown;
                    const delta = row.delta;
                    return (
                      <div key={row.k} style={{
                        position: "relative",
                        padding: "20px 22px", borderRadius: 14,
                        background: "rgba(255,255,255,.025)",
                        border: "1px solid rgba(255,255,255,.08)",
                        display: "grid",
                        gridTemplateColumns: "minmax(180px, 1.5fr) auto auto",
                        gap: 24, alignItems: "center",
                        opacity: unknown ? .55 : 1
                      }} className="yw-cfg-overpay-row">
                        {/* Name + verdict */}
                        <div style={{ minWidth: 0 }}>
                          <div style={{ fontFamily: T.fDisplay, fontSize: 19, fontWeight: 700,
                            color: "#fff", letterSpacing: "-0.01em", marginBottom: 4 }}>
                            {row.name}
                          </div>
                          <div style={{ fontSize: 13, color: "rgba(255,255,255,.45)", marginBottom: 10 }}>
                            {row.sub || "\u00A0"}
                          </div>
                          {unknown ?
                          <div style={{ fontSize: 13, color: "rgba(255,255,255,.5)" }}>
                              Pricing not public ,  tap their price to plug in your own.
                            </div> :
                          delta > 0 ?
                          <div style={{
                            fontFamily: T.fDisplay, fontSize: 17, fontWeight: 700,
                            color: AOnDark, letterSpacing: "-0.01em", lineHeight: 1.25
                          }}>
                              You overpay {fmt(delta)}/mo to {row.name}.
                            </div> :
                          delta < 0 ?
                          <div style={{ fontSize: 14, color: "rgba(255,255,255,.7)", lineHeight: 1.4 }}>
                              {fmt(Math.abs(delta))}/mo less ,  but YachtWay includes far more.
                            </div> :
                          <div style={{ fontSize: 14, color: "rgba(255,255,255,.6)" }}>Same price as YachtWay.</div>
                          }
                        </div>

                        {/* Their price (editable) */}
                        <div style={{ textAlign: "right", minWidth: 120 }}>
                          <div style={{ fontSize: 11, fontWeight: 700, color: "rgba(255,255,255,.4)",
                            textTransform: "uppercase", letterSpacing: ".12em", marginBottom: 4 }}>
                            Their price
                          </div>
                          <EditablePrice
                            row={row}
                            unknown={unknown}
                            region={region}
                            fmt={fmt}
                            fontFamily={T.fDisplay}
                            accent={AL}
                            isYw={false}
                            value={compOverrides[row.k] || ""}
                            onChange={(v) => setCompOverride(row.k, v)} />
                        </div>

                        {/* Your YachtWay price (locked) */}
                        <div style={{ textAlign: "right", minWidth: 120,
                          paddingLeft: 24, borderLeft: "1px solid rgba(255,255,255,.10)" }}>
                          <div style={{ fontSize: 11, fontWeight: 700, color: AOnDark,
                            textTransform: "uppercase", letterSpacing: ".12em", marginBottom: 4 }}>
                            On YachtWay
                          </div>
                          <div style={{ fontFamily: T.fDisplay, fontSize: 22, fontWeight: 800,
                            color: "#fff", letterSpacing: "-0.02em", whiteSpace: "nowrap" }}>
                            {fmt(ywMonthlyLikeForLike)}<span style={{
                              fontSize: 12, color: "rgba(255,255,255,.5)", fontWeight: 500
                            }}> /mo</span>
                          </div>
                        </div>
                      </div>);
                  })}
                </div>

                {/* Verdict + CTAs, moved here per m0131 so the headline
                    "$X overpaying" lands after the user has entered
                    their actual numbers above. */}
                <div style={{
                  marginTop: 28, padding: "28px 28px 24px",
                  borderRadius: 18,
                  background: annualSavings > 0
                    ? `linear-gradient(135deg, ${rgba(A, .14)}, ${rgba(A, .04)})`
                    : "rgba(255,255,255,.025)",
                  border: `1.5px solid ${annualSavings > 0 ? rgba(A, .35) : "rgba(255,255,255,.10)"}`,
                }}>
                  <div style={{
                    fontSize: 12, fontWeight: 700, color: AOnDark,
                    textTransform: "uppercase", letterSpacing: ".14em", marginBottom: 10,
                  }}>Reality check</div>
                  <div style={{
                    fontFamily: T.fDisplay, fontSize: "clamp(28px, 3.4vw, 44px)",
                    fontWeight: 700, letterSpacing: "-0.025em", lineHeight: 1.1,
                    color: "#fff", textWrap: "pretty",
                  }}>
                    {annualSavings > 0
                      ? <span>You are overpaying <span style={{ color: AOnDark }}>{fmt(annualSavings)}</span> a year.</span>
                      : "You are pricing right with the market."}
                  </div>
                  {/* Sign-post line removed per design feedback (m0146);
                      verdict stands on its own without nudging copy. */}
                </div>
              </div>

              {/* ───────── STEP 6, Take it with you ───────── */}
              <div style={{ ...stepCard }}>
                <StepHead
                  n="6"
                  kicker="Make it real"
                  title="Take this with you."
                  sub="Email yourself a PDF proposal you can forward to whoever signs the checks ,  or jump on a 20-minute walkthrough with our team." />

                <div style={{ display: "flex", flexWrap: "wrap", gap: 12, marginTop: 8 }}>
                  <button
                    type="button"
                    onClick={() => {
                      const userPricedComps = compTotals.filter((c) => !c.unknown && c.monthly > 0);
                      pendingExportRef.current = {
                        persona, region, brokers, managers, offices, brands,
                        easySign, vato, api, web, liveSessions,
                        yLines, ywMonthly, compTotals: userPricedComps, fmt, accent: tweaks.accentHover, accentLight: tweaks.accentHover
                      };
                      setExportError("");
                      setExportModalOpen(true);
                    }}
                    style={{
                      flex: "1 1 280px", display: "inline-flex", alignItems: "center", justifyContent: "center", gap: 10,
                      padding: "18px 24px", borderRadius: 12,
                      background: A, color: "#fff",
                      border: "none", fontFamily: T.fBody, fontSize: 15, fontWeight: 700,
                      cursor: "pointer", letterSpacing: "-0.005em",
                      boxShadow: `0 4px 16px ${rgba(A, .35)}`
                    }}
                    onMouseOver={(e) => {e.currentTarget.style.background = AL;}}
                    onMouseOut={(e) => {e.currentTarget.style.background = A;}}>
                    <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
                      <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" />
                      <polyline points="7 10 12 15 17 10" />
                      <line x1="12" y1="15" x2="12" y2="3" />
                    </svg>
                    Email me this proposal (PDF)
                  </button>
                  <a
                    href="https://links.yachtway.com/widget/booking/0YnCBougAZkmCemBiptZ"
                    target="_blank"
                    rel="noopener noreferrer"
                    style={{
                      flex: "1 1 200px", display: "inline-flex", alignItems: "center", justifyContent: "center", gap: 10,
                      padding: "18px 24px", borderRadius: 12,
                      background: "transparent", color: "#fff",
                      border: "1px solid rgba(255,255,255,.18)",
                      fontFamily: T.fBody, fontSize: 15, fontWeight: 700,
                      textDecoration: "none",
                      cursor: "pointer", letterSpacing: "-0.005em"
                    }}
                    onMouseOver={(e) => {e.currentTarget.style.background = "rgba(255,255,255,.06)";}}
                    onMouseOut={(e) => {e.currentTarget.style.background = "transparent";}}>
                    20-min walkthrough
                  </a>
                </div>
              </div>

            </div>
          </section>);


      })()}


      {/* Ask Sarah and standalone "As Seen In" credibility strip removed , 
           press logos now live merged into the members wall above, and the
           AI concierge module was removed per design feedback. */}

      {/* ── TRUST & COMPLIANCE (DARK hero with animated padlock) ─────── */}
      {(() => {
        const TrustHero = () => {
          const sectionRef = useRefD(null);
          const [locked, setLocked] = useStateD(false);
          React.useEffect(() => {
            const el = sectionRef.current;
            if (!el) return;
            const io = new IntersectionObserver((entries) => {
              entries.forEach((e) => {
                if (e.isIntersecting && e.intersectionRatio > 0.35) {
                  setLocked(true);
                }
              });
            }, { threshold: [0, 0.35, 0.6] });
            io.observe(el);
            return () => io.disconnect();
          }, []);
          return (
            <section ref={sectionRef} id="security" style={{
              padding: "140px 32px 120px",
              background: T.bgDark, color: "#fff",
              borderTop: `1px solid ${T.border}`,
              position: "relative", overflow: "hidden"
            }}>
              {/* Soft accent glow behind the lock */}
              <div style={{
                position: "absolute", top: "10%", left: "50%",
                width: 900, height: 900, borderRadius: "50%",
                transform: "translateX(-50%)",
                background: `radial-gradient(circle, ${glow(.18)}, transparent 60%)`,
                pointerEvents: "none"
              }} />
              <div style={{ maxWidth: 1100, margin: "0 auto", position: "relative", textAlign: "center" }}>
                {/* Eyebrow */}
                <div style={{
                  fontSize: 13, fontWeight: 700, color: AOnDark,
                  textTransform: "uppercase", letterSpacing: ".18em", marginBottom: 36,
                  display: "inline-flex", alignItems: "center", gap: 10
                }}>
                  <span style={{
                    width: 6, height: 6, borderRadius: 3, background: T.accentLight
                  }} />
                  Trust &amp; Compliance
                </div>

                {/* Animated padlock - serious 3D, dark purple
                     Built up in layers: cast shadow → back rim →
                     body slab with chamfer/edge highlights → side bevels →
                     top face highlight → recessed keyhole well → keyhole.
                     Shackle is brushed dark metal, drops in on lock. */}
                <div style={{ display: "flex", justifyContent: "center", marginBottom: 40 }}>
                  <svg width="124" height="172" viewBox="0 0 124 172" fill="none"
                  style={{ overflow: "visible", filter: "drop-shadow(0 30px 40px rgba(0,0,0,.55)) drop-shadow(0 8px 14px rgba(0,0,0,.4))" }}>
                    <defs>
                      {/* Body face - deep purple, dark, with subtle vertical lighting */}
                      <linearGradient id="lockBodyGrad" x1="0" y1="0" x2="0" y2="1">
                        <stop offset="0%" stopColor="#3a2a5a" />
                        <stop offset="35%" stopColor="#251a40" />
                        <stop offset="100%" stopColor="#13091f" />
                      </linearGradient>
                      {/* Side bevel - left edge catching light */}
                      <linearGradient id="lockBevelLeft" x1="0" y1="0" x2="1" y2="0">
                        <stop offset="0%" stopColor="rgba(160,135,210,.55)" />
                        <stop offset="100%" stopColor="rgba(160,135,210,0)" />
                      </linearGradient>
                      {/* Side bevel - right edge in shadow */}
                      <linearGradient id="lockBevelRight" x1="0" y1="0" x2="1" y2="0">
                        <stop offset="0%" stopColor="rgba(0,0,0,0)" />
                        <stop offset="100%" stopColor="rgba(0,0,0,.55)" />
                      </linearGradient>
                      {/* Top edge highlight (a thin specular line) */}
                      <linearGradient id="lockTopHi" x1="0" y1="0" x2="0" y2="1">
                        <stop offset="0%" stopColor="rgba(195,170,235,.55)" />
                        <stop offset="50%" stopColor="rgba(195,170,235,.10)" />
                        <stop offset="100%" stopColor="rgba(195,170,235,0)" />
                      </linearGradient>
                      {/* Bottom edge shadow inside the body */}
                      <linearGradient id="lockBottomShadow" x1="0" y1="0" x2="0" y2="1">
                        <stop offset="0%" stopColor="rgba(0,0,0,0)" />
                        <stop offset="100%" stopColor="rgba(0,0,0,.55)" />
                      </linearGradient>
                      {/* Shackle - brushed dark metal */}
                      <linearGradient id="lockShackleGrad" x1="0" y1="0" x2="1" y2="0">
                        <stop offset="0%" stopColor="#1c1426" />
                        <stop offset="22%" stopColor="#5a4d70" />
                        <stop offset="50%" stopColor="#8d80a5" />
                        <stop offset="78%" stopColor="#3d3450" />
                        <stop offset="100%" stopColor="#0e0916" />
                      </linearGradient>
                      {/* Keyhole well - radial recess */}
                      <radialGradient id="lockKeyholeWell" cx="0.5" cy="0.4" r="0.6">
                        <stop offset="0%" stopColor="#08040f" />
                        <stop offset="70%" stopColor="#0d0718" />
                        <stop offset="100%" stopColor="rgba(0,0,0,0)" />
                      </radialGradient>
                      {/* Stage spotlight - a soft elliptical bloom with a
                           tight bright core and a long feathered falloff,
                           rendered in 'screen' blend so it lifts the metal
                           rather than painting on top of it. Travels down the
                           full silhouette. */}
                      <radialGradient id="lockSpotlight" cx="0.5" cy="0.5" r="0.5"
                      gradientUnits="objectBoundingBox">
                        <stop offset="0%" stopColor="rgba(255,250,255,.85)" />
                        <stop offset="22%" stopColor="rgba(240,225,255,.42)" />
                        <stop offset="50%" stopColor="rgba(210,180,245,.16)" />
                        <stop offset="100%" stopColor="rgba(180,140,230,0)" />
                      </radialGradient>
                      {/* Specular crescent that races along the shackle arc -
                           a single bright glint, very small, mostly white. */}
                      <radialGradient id="lockShackleGlint" cx="0.5" cy="0.5" r="0.5"
                      gradientUnits="objectBoundingBox">
                        <stop offset="0%" stopColor="rgba(255,255,255,.95)" />
                        <stop offset="40%" stopColor="rgba(235,225,255,.35)" />
                        <stop offset="100%" stopColor="rgba(220,210,255,0)" />
                      </radialGradient>
                      {/* Clip the projector beam to cover both the lock body
                           AND the shackle so the light reads as washing the
                           full silhouette, not just the body slab. */}
                      <clipPath id="lockBodyClip">
                        <rect x="14" y="68" width="96" height="80" rx="20" />
                        <rect x="30" y="14" width="64" height="62" rx="32" />
                      </clipPath>
                      {/* Soft halo behind the lock so the whole frame lifts
                           slightly out of pure black */}
                      <radialGradient id="lockHalo" cx="0.5" cy="0.55" r="0.7">
                        <stop offset="0%" stopColor="rgba(180,150,230,.28)" />
                        <stop offset="55%" stopColor="rgba(140,110,200,.10)" />
                        <stop offset="100%" stopColor="rgba(140,110,200,0)" />
                      </radialGradient>
                    </defs>

                    {/* Cast shadow ellipse on the floor */}
                    <ellipse cx="62" cy="160" rx="42" ry="6"
                    fill="rgba(0,0,0,.55)"
                    style={{
                      opacity: locked ? 1 : .55,
                      transition: "opacity .5s ease .2s"
                    }} />

                    {/* Shackle - thicker, dark brushed metal. Animates on a
                         loop in sync with the projector beam: rises up before
                         the sweep, then drops down to "lock" as the beam
                         crosses it. */}
                    <path
                      d="M 36 76 V 44 a 26 26 0 0 1 52 0 V 76"
                      stroke="url(#lockShackleGrad)"
                      strokeWidth="9"
                      strokeLinecap="round"
                      fill="none"
                      style={{
                        transformOrigin: "center top",
                        animation: "lock-shackle 5.5s ease-in-out infinite"
                      }} />
                    
                    {/* Shackle inner highlight - a thin lighter stroke offset
                         slightly to suggest a rounded barrel of metal */}
                    <path
                      d="M 36 76 V 44 a 26 26 0 0 1 52 0 V 76"
                      stroke="rgba(220,205,245,.18)"
                      strokeWidth="1.5"
                      strokeLinecap="round"
                      fill="none"
                      style={{
                        transformOrigin: "center top",
                        animation: "lock-shackle-hi 5.5s ease-in-out infinite"
                      }} />
                    

                    {/* Body group - a slab with chamfered edges */}
                    <g style={{
                      transform: locked ? "scale(1)" : "scale(.97)",
                      transformOrigin: "62px 108px",
                      transition: "transform .5s cubic-bezier(.2,.8,.2,1)"
                    }}>
                      {/* Back rim - a darker shape behind to suggest depth */}
                      <rect
                        x="13" y="70" width="98" height="80" rx="20"
                        fill="#0a0512" />
                      
                      {/* Main face */}
                      <rect
                        x="14" y="68" width="96" height="80" rx="20"
                        fill="url(#lockBodyGrad)" />
                      
                      {/* Left bevel catching light */}
                      <rect
                        x="14" y="68" width="14" height="80" rx="20"
                        fill="url(#lockBevelLeft)"
                        opacity=".7" />
                      
                      {/* Right bevel in shadow */}
                      <rect
                        x="96" y="68" width="14" height="80" rx="20"
                        fill="url(#lockBevelRight)"
                        opacity=".8" />
                      
                      {/* Bottom shadow inside body */}
                      <rect
                        x="14" y="100" width="96" height="48" rx="20"
                        fill="url(#lockBottomShadow)" />
                      
                      {/* Top edge specular - a thin highlight along the top */}
                      <rect
                        x="14" y="68" width="96" height="20" rx="20"
                        fill="url(#lockTopHi)" />
                      
                      {/* Hairline top stroke for crisp edge */}
                      <path
                        d="M 34 68 H 90"
                        stroke="rgba(220,205,245,.35)"
                        strokeWidth="1"
                        strokeLinecap="round" />
                      

                      {/* Keyhole well - a recessed darker disc behind the keyhole */}
                      <circle cx="62" cy="104" r="18" fill="url(#lockKeyholeWell)" />
                      {/* Keyhole well inner shadow ring */}
                      <circle cx="62" cy="104" r="14"
                      fill="none"
                      stroke="rgba(0,0,0,.65)"
                      strokeWidth="1.5" />
                      
                      {/* Keyhole well top highlight - subtle catch */}
                      <path
                        d="M 50 100 a 12 10 0 0 1 24 0"
                        fill="none"
                        stroke="rgba(180,155,225,.18)"
                        strokeWidth="1" />
                      

                      {/* Keyhole - serious, classic shape */}
                      <path
                        d="M 62 96
                           a 5.5 5.5 0 0 1 5.5 5.5
                           c 0 2.2 -1.3 4.1 -3.2 5
                           L 65.5 118
                           a 1.5 1.5 0 0 1 -1.5 1.5
                           h -4
                           a 1.5 1.5 0 0 1 -1.5 -1.5
                           L 59.7 106.5
                           C 57.8 105.6 56.5 103.7 56.5 101.5
                           a 5.5 5.5 0 0 1 5.5 -5.5 Z"









                        fill="#000" />
                      
                      {/* Keyhole inner sheen - a tiny highlight on the round
                           chamber so it reads as a real cut, not a flat decal */}
                      <path
                        d="M 60 99 a 2 2 0 0 1 2.5 -.5"
                        stroke="rgba(180,155,225,.5)"
                        strokeWidth="1"
                        strokeLinecap="round"
                        fill="none" />
                      
                    </g>

                    {/* Stage spotlight - a soft elliptical bloom that
                         travels down the lock silhouette, clipped so it only
                         paints onto the body+shackle (not the empty SVG
                         space). Rendered in 'screen' blend for a true light
                         feel rather than a painted overlay. */}
                    <g clipPath="url(#lockBodyClip)" style={{ pointerEvents: "none" }}>
                      <ellipse
                        cx="62" cy="60" rx="78" ry="46"
                        fill="url(#lockSpotlight)"
                        style={{
                          mixBlendMode: "screen",
                          transformOrigin: "62px 60px",
                          animation: "lock-spotlight 6s cubic-bezier(.45,.05,.25,1) infinite",
                          filter: "blur(.5px)"
                        }} />
                      
                    </g>

                    {/* Specular glint that races along the shackle arc as
                         the lock closes - a tiny bright highlight that
                         traces the curved metal, the way a real polished
                         bar catches a moving light. */}
                    <g style={{ pointerEvents: "none" }}>
                      <ellipse
                        cx="0" cy="0" rx="11" ry="5"
                        fill="url(#lockShackleGlint)"
                        style={{
                          mixBlendMode: "screen",
                          animation: "lock-shackle-glint 6s cubic-bezier(.45,.05,.25,1) infinite",
                          filter: "blur(.4px)"
                        }} />
                      
                    </g>

                    {/* Click flash on lock - a refined double-ring ripple
                         that softly expands and dissolves, instead of a hard
                         single circle. */}
                    <circle
                      cx="62" cy="108" r="44"
                      fill="none"
                      stroke="rgba(195,170,240,.85)"
                      strokeWidth=".9"
                      style={{
                        opacity: 0,
                        transformOrigin: "62px 108px",
                        animation: locked ? "lock-pulse 1.6s cubic-bezier(.16,1,.3,1) .85s forwards" : "none"
                      }} />
                    
                    <circle
                      cx="62" cy="108" r="44"
                      fill="none"
                      stroke="rgba(220,200,250,.55)"
                      strokeWidth=".7"
                      style={{
                        opacity: 0,
                        transformOrigin: "62px 108px",
                        animation: locked ? "lock-pulse 1.9s cubic-bezier(.16,1,.3,1) 1s forwards" : "none"
                      }} />
                    
                    <style>{`
                      @keyframes lock-pulse {
                        0%   { opacity: 0;   transform: scale(.6); }
                        18%  { opacity: .8; }
                        100% { opacity: 0;   transform: scale(1.55); }
                      }
                      /* Spotlight: a soft bloom that drifts down the lock,
                         dwells briefly when it kisses the shackle, then
                         fades. Smooth cubic easing - no linear sweeps. */
                      @keyframes lock-spotlight {
                        0%   { transform: translateY(-78px) scale(.85); opacity: 0; }
                        14%  { opacity: .9; }
                        38%  { transform: translateY(-12px) scale(1);   opacity: 1; }
                        58%  { transform: translateY(36px)  scale(1.05); opacity: .85; }
                        78%  { opacity: .25; }
                        100% { transform: translateY(82px)  scale(1.1);  opacity: 0; }
                      }
                      /* Specular glint traces the shackle arc: enters at
                         the left base, sweeps over the top, exits right.
                         The path is approximated with translate + scale. */
                      @keyframes lock-shackle-glint {
                        0%   { transform: translate(34px, 76px)  scale(.6); opacity: 0; }
                        18%  { transform: translate(34px, 60px)  scale(.9); opacity: .6; }
                        32%  { transform: translate(40px, 38px)  scale(1);  opacity: 1; }
                        44%  { transform: translate(62px, 26px)  scale(1.1); opacity: 1; }
                        56%  { transform: translate(84px, 38px)  scale(1);  opacity: .9; }
                        70%  { transform: translate(90px, 60px)  scale(.8); opacity: .35; }
                        82%  { transform: translate(90px, 76px)  scale(.6); opacity: 0; }
                        100% { transform: translate(90px, 76px)  scale(.6); opacity: 0; }
                      }
                      /* Shackle: starts up, drops down (locks) as the
                         spotlight crosses it, holds locked. Springy land. */
                      @keyframes lock-shackle {
                        0%,  18% { transform: translateY(-14px); }
                        34%  { transform: translateY(3px); }
                        42%  { transform: translateY(-2px); }
                        50%, 100% { transform: translateY(0); }
                      }
                      @keyframes lock-shackle-hi {
                        0%,  18% { transform: translate(-1.5px, -15px); opacity: 0; }
                        34%  { transform: translate(-1.5px, 2px);  opacity: 1; }
                        42%  { transform: translate(-1.5px, -3px); opacity: 1; }
                        50%, 100% { transform: translate(-1.5px, -1px); opacity: 1; }
                      }
                    `}</style>
                  </svg>
                </div>

                {/* H1 Title - the impactful one */}
                <h1 style={{
                  fontFamily: T.fDisplay, fontSize: "clamp(56px, 7vw, 96px)", fontWeight: 700,
                  letterSpacing: "-0.04em", lineHeight: 0.95, margin: 0, marginBottom: 24,
                  textWrap: "balance"
                }}>
                  Your data, locked down.
                </h1>

                {/* Sub-headline */}
                <p style={{
                  fontFamily: T.fDisplay, fontSize: 22, fontWeight: 500,
                  color: "rgba(255,255,255,.75)", margin: "0 auto 18px",
                  maxWidth: 720, lineHeight: 1.4, textWrap: "balance"
                }}>
                  The only global yacht listing platform with trackable audits, certified compliance, and enterprise-grade privacy.
                </p>

                {/* Body copy */}
                <p style={{
                  fontSize: 16, lineHeight: 1.6, color: "rgba(255,255,255,.55)",
                  margin: "0 auto 48px", maxWidth: 620, textWrap: "pretty"
                }}>
                  Every Contract is logged. Every Listing and Purchase Agreement signed with DocuSign. Every buyer record is handled under the same privacy frameworks Fortune 500 vendors are held to. When deals get scrutinized, your paper trail holds up.
                </p>

                {/* Certification badges - inline strip */}
                <div style={{
                  display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: 12,
                  maxWidth: 880, margin: "0 auto 48px"
                }}>
                  {[
                  { badge: "SOC 2", type: "Type II · Audited by Prescient Assurance, 2025",
                    desc: "Audited controls for data security, availability, and confidentiality. Summary report on request.",
                    peers: ["Amazon AWS", "Stripe", "Salesforce"] },
                  { badge: "GDPR", type: "Compliant · Reviewed Apr 2026",
                    desc: "EU buyer and dealer data handled under GDPR. Export and deletion on request.",
                    peers: ["Microsoft", "Apple", "Booking.com"] },
                  { badge: "CCPA", type: "Aligned · Reviewed Apr 2026",
                    desc: "California Consumer Privacy Act rights honored for US-based buyers.",
                    peers: ["Google", "Meta", "Netflix"] },
                  { badge: "Audit Trail", type: "Every action logged", desc: "Listing edits, lead handoffs, and EasySign contracts timestamped and exportable.",
                    peers: ["DocuSign", "Workday", "Okta"] }].
                  map((c, i) =>
                  <div key={i} style={{
                    background: "rgba(255,255,255,.04)",
                    border: "1px solid rgba(255,255,255,.10)",
                    borderRadius: 14, padding: "22px 18px",
                    display: "flex", flexDirection: "column", gap: 6,
                    textAlign: "left"
                  }}>
                      <div style={{
                      fontFamily: T.fDisplay, fontSize: 22, fontWeight: 700,
                      letterSpacing: "-0.02em", color: "#fff", lineHeight: 1.0
                    }}>{c.badge}</div>
                      <div style={{
                      fontSize: 13, fontWeight: 600, color: AOnDark,
                      textTransform: "uppercase", letterSpacing: ".1em"
                    }}>{c.type}</div>
                      <div style={{
                      fontSize: 13, lineHeight: 1.5, color: "rgba(255,255,255,.55)",
                      marginTop: 2, textWrap: "pretty"
                    }}>{c.desc}</div>
                      {/* Peer list - shows recognizable companies that
                         also hold this certification, so the dealer
                         knows what tier they are in. */}
                      <div style={{
                      marginTop: "auto", paddingTop: 10,
                      borderTop: "1px solid rgba(255,255,255,.08)"
                    }}>
                        <div style={{
                        fontSize: 13, fontWeight: 700, color: "rgba(255,255,255,.45)",
                        textTransform: "uppercase", letterSpacing: ".12em",
                        marginBottom: 6
                      }}>Also held by</div>
                        <div style={{
                        display: "flex", flexWrap: "wrap", gap: 4
                      }}>
                          {c.peers.map((p, j) =>
                        <span key={j} style={{
                          fontSize: 13, fontWeight: 500,
                          padding: "3px 7px", borderRadius: 4,
                          background: "rgba(255,255,255,.06)",
                          color: "rgba(255,255,255,.78)",
                          border: "1px solid rgba(255,255,255,.08)",
                          fontFamily: T.fBody
                        }}>{p}</span>
                        )}
                        </div>
                      </div>
                    </div>
                  )}
                </div>

                {/* CTA */}
                <a href="https://trust.yachtway.com" target="_blank" rel="noopener noreferrer"
                style={{
                  display: "inline-flex", alignItems: "center", gap: 10,
                  padding: "16px 26px",
                  background: "#fff", color: T.fg,
                  borderRadius: 999, textDecoration: "none",
                  fontSize: 14, fontWeight: 600, letterSpacing: "-0.005em"
                }}>
                  Visit Trust Center
                  <span style={{ fontSize: 16, lineHeight: 1 }}>→</span>
                </a>
              </div>
            </section>);

        };
        return <TrustHero />;
      })()}

      {/* ── FINAL CTA (DARK, asymmetric) ─────────────────────────────── */}
      <section style={{
        padding: "140px 32px",
        background: T.bgDark, color: "#fff",
        position: "relative", overflow: "hidden"
      }}>
        <div style={{
          position: "absolute", top: -200, right: -200,
          width: 700, height: 700, borderRadius: "50%",
          background: `radial-gradient(circle, ${glow(.40)}, transparent 70%)`
        }} />
        <div style={{ maxWidth: 1280, margin: "0 auto", position: "relative",
          display: "grid", gridTemplateColumns: "2fr 1fr", gap: 64, alignItems: "center" }}>
          <div>
            <h2 className="closing-headline" ref={(el) => {
              if (!el || el.dataset.ioBound) return;
              el.dataset.ioBound = "1";
              if (typeof IntersectionObserver === "undefined") {
                el.classList.add("is-revealed");
                return;
              }
              const io = new IntersectionObserver((entries) => {
                entries.forEach((entry) => {
                  if (entry.isIntersecting) {
                    entry.target.classList.add("is-revealed");
                    io.unobserve(entry.target);
                  }
                });
              }, { threshold: 0.4, rootMargin: "0px 0px -10% 0px" });
              io.observe(el);
            }} style={{ fontFamily: T.fDisplay, fontSize: 88, fontWeight: 700,
              letterSpacing: "-0.04em", lineHeight: 0.95, margin: 0, marginBottom: 24 }}>
              <span className="ch-line"><span className="ch-inner">Your Yacht.</span></span>
              <br />
              <span className="ch-line"><span className="ch-inner">Your Way.</span></span>
              <br />
              <span className="ch-line"><span className="ch-inner"><HeadlineAccent>YachtWay.</HeadlineAccent></span></span>
            </h2>
            <p style={{ fontSize: 18, color: "rgba(255,255,255,.65)", margin: 0, maxWidth: 540 }}>
              Start free. Add tools as you grow. 450+ professionals in 27 countries already have.
            </p>
          </div>
          <div style={{ display: "flex", flexDirection: "column", gap: 12 }}>
            <a className="ed-btn-primary" href="http://yachtway.com/sign-up" target="_blank" rel="noopener noreferrer" style={{
              padding: "18px 26px", borderRadius: 12, border: "none",
              fontSize: 16, fontWeight: 600, fontFamily: T.fBody, cursor: "pointer",
              display: "inline-flex", alignItems: "center", justifyContent: "space-between", gap: 12,
              textDecoration: "none"
            }}>Become a Member, Free <Ic.arrow size={16} /></a>
            <a className="ed-btn-ghost-dark"
              href="https://links.yachtway.com/widget/booking/0YnCBougAZkmCemBiptZ"
              target="_blank" rel="noopener noreferrer"
              style={{
              padding: "18px 26px", borderRadius: 12,
              fontSize: 16, fontWeight: 600, fontFamily: T.fBody, cursor: "pointer",
              display: "inline-flex", alignItems: "center", justifyContent: "space-between", gap: 12,
              textDecoration: "none"
            }}>Book a walkthrough <Ic.arrow size={16} /></a>
            <div style={{ fontSize: 13, color: "rgba(255,255,255,.4)", marginTop: 10, textAlign: "center" }}>
              No credit card required to list
            </div>
          </div>
        </div>
      </section>

      {/* Tweaks panel */}
      <TweaksPanel title="Tweaks">
        <TweakSection label="Accent color">
          <TweakColor label="Primary" value={tweaks.accent}
          onChange={(v) => setTweak({ accent: v, accentHover: v, accentLight: v })} />
          <TweakColor label="Hover" value={tweaks.accentHover} onChange={(v) => setTweak('accentHover', v)} />
          <TweakColor label="Light" value={tweaks.accentLight} onChange={(v) => setTweak('accentLight', v)} />
          <TweakSlider label="Purple ambience" value={Math.round(tweaks.purpleIntensity * 100)}
          min={0} max={100} step={5} unit="%"
          onChange={(v) => setTweak('purpleIntensity', v / 100)} />
        </TweakSection>
        <TweakSection label="Headlines">
          <TweakToggle label="Purple gradient text"
          value={tweaks.gradientHeadline}
          onChange={(v) => setTweak('gradientHeadline', v)} />
        </TweakSection>
        <TweakSection label="Motion">
          <TweakToggle label="Animate stat numbers"
          value={tweaks.animateStats}
          onChange={(v) => setTweak('animateStats', v)} />
        </TweakSection>
        <TweakSection label="Reset">
          <TweakButton label="Restore defaults" secondary
          onClick={() => setTweak({
            accent: "#4A2C8A", accentHover: "#3A2070", accentLight: "#4A2C8A",
            purpleIntensity: 0.55, gradientHeadline: false, animateStats: true
          })} />
        </TweakSection>
      </TweaksPanel>

      {/* Footer (DARK) */}
      <footer id="site-footer" style={{
        padding: "32px",
        background: T.bgDark,
        borderTop: `1px solid rgba(255,255,255,.08)`,
        display: "flex", justifyContent: "space-between", alignItems: "center",
        fontSize: 13, color: "rgba(255,255,255,.5)"
      }}>
        <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
          <img src={window.__YW_ASSETS && window.__YW_ASSETS.logoLight || "assets/yachtway-logo-light.png"} alt="YachtWay"
          style={{ height: 18, width: "auto", display: "block" }} />
        </div>
        <span>© 2026 YachtWay. Miami, FL USA. Privacy · Terms · Contact</span>
      </footer>

      {/* ─── Lead-capture modal: gate PDF export behind dealer name + work email ─── */}
      {exportModalOpen &&
      <div
        onClick={(e) => {if (e.target === e.currentTarget) setExportModalOpen(false);}}
        style={{
          position: "fixed", inset: 0, zIndex: 9000,
          background: "rgba(10, 10, 12, 0.72)",
          backdropFilter: "blur(8px)", WebkitBackdropFilter: "blur(8px)",
          display: "flex", alignItems: "center", justifyContent: "center",
          padding: 20, fontFamily: T.fBody,
          animation: "ywFadeIn 180ms ease-out"
        }}>
        
          <style>{`
            @keyframes ywFadeIn { from { opacity: 0; } to { opacity: 1; } }
            @keyframes ywSlideUp { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: translateY(0); } }
          `}</style>
          <form
          onSubmit={handleExportSubmit}
          style={{
            background: "#fff", borderRadius: 16, width: "100%", maxWidth: 460,
            padding: "32px 32px 28px", boxShadow: "0 24px 80px rgba(0,0,0,.35)",
            animation: "ywSlideUp 240ms cubic-bezier(.2,.8,.2,1)",
            position: "relative"
          }}>
          
            {/* Close */}
            <button
            type="button"
            onClick={() => setExportModalOpen(false)}
            aria-label="Close"
            style={{
              position: "absolute", top: 14, right: 14,
              width: 32, height: 32, borderRadius: 8,
              background: "transparent", border: "none", cursor: "pointer",
              display: "flex", alignItems: "center", justifyContent: "center",
              color: T.fgMuted
            }}
            onMouseOver={(e) => {e.currentTarget.style.background = "#f3f3f5";}}
            onMouseOut={(e) => {e.currentTarget.style.background = "transparent";}}>
            
              <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round">
                <line x1="18" y1="6" x2="6" y2="18" />
                <line x1="6" y1="6" x2="18" y2="18" />
              </svg>
            </button>

            {/* Header */}
            <div style={{
            fontSize: 12, fontWeight: 800, letterSpacing: ".18em",
            color: AOnDark, textTransform: "uppercase", marginBottom: 10
          }}>One quick step</div>
            <h3 style={{
            fontFamily: T.fDisplay, fontSize: 24, fontWeight: 800,
            letterSpacing: "-0.02em", color: T.fg, margin: "0 0 8px", lineHeight: 1.2
          }}>
              Get your personalized proposal
            </h3>
            <p style={{
            fontSize: 14, color: T.fgMuted, margin: "0 0 22px", lineHeight: 1.5
          }}>
              We will prepare a PDF with your numbers, your team size, and your exact savings across every platform you are currently paying for.
            </p>

            {/* Name */}
            <label style={{ display: "block", marginBottom: 14 }}>
              <span style={{
              display: "block", fontSize: 13, fontWeight: 700,
              letterSpacing: ".06em", textTransform: "uppercase",
              color: T.fg, marginBottom: 6
            }}>Dealer name</span>
              <input
              type="text"
              value={exportName}
              onChange={(e) => {exportNameTouchedRef.current = true; setExportName(e.target.value);if (exportError) setExportError("");}}
              placeholder="e.g. Riviera Yacht Group"
              autoFocus
              style={{
                width: "100%", padding: "12px 14px", borderRadius: 10,
                border: `1.5px solid ${T.border}`, fontSize: 15,
                fontFamily: T.fBody, color: T.fg, outline: "none",
                transition: "border-color 120ms ease",
                boxSizing: "border-box"
              }}
              onFocus={(e) => {e.currentTarget.style.borderColor = T.accent;}}
              onBlur={(e) => {e.currentTarget.style.borderColor = T.border;}} />
            
            </label>

            {/* Email */}
            <label style={{ display: "block", marginBottom: 18 }}>
              <span style={{
              display: "block", fontSize: 13, fontWeight: 700,
              letterSpacing: ".06em", textTransform: "uppercase",
              color: T.fg, marginBottom: 6
            }}>Work email</span>
              <input
              type="email"
              value={exportEmail}
              onChange={(e) => {setExportEmail(e.target.value);if (exportError) setExportError("");}}
              placeholder="you@yourdealership.com"
              style={{
                width: "100%", padding: "12px 14px", borderRadius: 10,
                border: `1.5px solid ${exportError ? "#dc2626" : T.border}`, fontSize: 15,
                fontFamily: T.fBody, color: T.fg, outline: "none",
                transition: "border-color 120ms ease",
                boxSizing: "border-box"
              }}
              onFocus={(e) => {e.currentTarget.style.borderColor = exportError ? "#dc2626" : T.accent;}}
              onBlur={(e) => {e.currentTarget.style.borderColor = exportError ? "#dc2626" : T.border;}} />
            
              <span style={{
              display: "block", fontSize: 13, color: T.fgFaint,
              marginTop: 6, lineHeight: 1.4
            }}>Use your dealership email, Gmail, Yahoo, and other personal addresses are not accepted.</span>
            </label>

            {/* Error */}
            {exportError &&
          <div style={{
            padding: "10px 12px", borderRadius: 8, marginBottom: 16,
            background: "#fef2f2", border: "1px solid #fecaca",
            color: "#b91c1c", fontSize: 13, fontWeight: 500, lineHeight: 1.4
          }}>{exportError}</div>
          }

            {/* Submit */}
            <button
            type="submit"
            style={{
              width: "100%", padding: "13px 18px", borderRadius: 10,
              background: T.accent, color: "#fff", border: "none",
              fontSize: 14, fontWeight: 700, letterSpacing: "-0.005em",
              fontFamily: T.fBody, cursor: "pointer",
              boxShadow: `0 4px 16px ${rgba(T.accent, .35)}`,
              transition: "background 120ms ease"
            }}
            onMouseOver={(e) => {e.currentTarget.style.background = T.accentHover;}}
            onMouseOut={(e) => {e.currentTarget.style.background = T.accent;}}>
            
              Generate proposal PDF →
            </button>
            <div style={{
            fontSize: 13, color: T.fgFaint, marginTop: 12,
            textAlign: "center", lineHeight: 1.4
          }}>
              Your proposal opens in a new tab, ready to print or save as PDF.
            </div>
          </form>
        </div>
      }

      {/* EngagementToast removed per design feedback */}
    </div>);

};

window.DirectionD = DirectionD;