/* MotorInc — main app */
const { useState, useEffect, useRef } = React;

const themeAsset = (path) => {
  if (!path || /^(https?:|data:|blob:|#|tel:|mailto:)/.test(path)) return path;
  const themeUrl = window.motorincTheme && window.motorincTheme.themeUrl;
  if (!themeUrl) return path;
  return `${themeUrl.replace(/\/$/, '')}/${path.replace(/^\/+/, '')}`;
};

const mediaUrl = (media, variant = 'url') => {
  if (typeof media === 'string') return themeAsset(media);
  const variantMap = {
    card: media?.cardUrl,
    wide: media?.wideUrl,
    full: media?.fullUrl
  };
  return themeAsset(variantMap[variant] || media?.url || '');
};
const mediaAlt = (media, fallback = '') => typeof media === 'string' ? fallback : media?.alt || fallback;
const mediaKey = (media, fallback) => typeof media === 'string' ? media : media?.id || media?.url || fallback;
const mediaSrcSet = (media) => typeof media === 'string' ? undefined : media?.srcset || undefined;
const mediaSizes = (media, fallback) => typeof media === 'string' ? undefined : media?.sizes || fallback;
const mediaWidth = (media) => typeof media === 'string' || !media?.width ? undefined : media.width;
const mediaHeight = (media) => typeof media === 'string' || !media?.height ? undefined : media.height;
const normalizeLines = (value) => {
  if (Array.isArray(value)) return value.filter(Boolean);
  if (typeof value === 'string') return value.split(/<br\s*\/?>|\r?\n/).map((line) => line.trim()).filter(Boolean);
  return [];
};
const hasContentProp = (key) => Object.prototype.hasOwnProperty.call(window.motorincContent || {}, key);

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "accent": "#851d2c",
  "ink": "#262220",
  "grain": true,
  "marqueeSpeed": 38
}/*EDITMODE-END*/;

const DEFAULT_SERVICES = [
  {
    n: "01",
    title: "Engine Rebuild",
    desc: "Full top-end and bottom-end rebuilds for Evolution, Twin Cam and Milwaukee-Eight motors. Stripped, measured, balanced and reassembled to spec — then run-in and verified on the bench."
  },
  {
    n: "02",
    title: "Custom Builds & Mods",
    desc: "Bobbers, choppers, baggers and one-off performance customs. Structural modifications, custom frames, tanks and exhausts — from first sketch to first ignition."
  },
  {
    n: "03",
    title: "Diagnostics & EFI Tuning",
    desc: "Diag4Bike-certified computer diagnostics, EFI remapping and fuel-map calibration. We dial in throttle response, AFR and stage upgrades so the bike runs clean and pulls hard."
  },
  {
    n: "04",
    title: "Service & Maintenance",
    desc: "Scheduled servicing to keep the bike healthy — oil and primary changes, valve checks, belt and clutch inspection. Done properly and documented for resale."
  },
  {
    n: "05",
    title: "Paint & Bodywork",
    desc: "Custom paint, candy coats, flake, pinstriping and hand-laid lettering. Tank dent repair and frame straightening done in-house, colour-matched to the build."
  },
  {
    n: "06",
    title: "Parts & After-Sales",
    desc: "OEM Harley-Davidson parts plus S&S, Vance & Hines, Öhlins and Performance Machine, imported direct from the US. Ongoing after-sales support to keep the build running."
  }
];

const DEFAULT_PROJECTS = [
  { name: "Black Lung", model: "Softail Night Train", size: "lg",
    blurb: "Matte black Softail, fully blacked-out. Twin Cam with S&S Stage I air cleaner, mini ape hangers, 40-spoke chrome front wheel, bobbed rear fender.", tag: "FEATURED",
    photos: [
      "assets/bikes/bike1/04.webp",
      "assets/bikes/bike1/01.webp",
      "assets/bikes/bike1/02.webp",
      "assets/bikes/bike1/03.webp",
      "assets/bikes/bike1/05.webp",
      "assets/bikes/bike1/06.webp",
      "assets/bikes/bike1/07.webp",
      "assets/bikes/bike1/08.webp"
    ] },
  { name: "Vulcan", model: "Custom Chopper — S&S 124\"", size: "md",
    blurb: "Long-rake custom chopper. Candy red with hand-laid silver ghost flames, fully chromed S&S V-twin, spike air cleaner, drag pipes, fat 240 rear on billet wheels.", tag: "CHOPPER",
    photos: [
      "assets/bikes/bike2/06.webp",
      "assets/bikes/bike2/01.webp",
      "assets/bikes/bike2/02.webp",
      "assets/bikes/bike2/03.webp",
      "assets/bikes/bike2/04.webp",
      "assets/bikes/bike2/05.webp",
      "assets/bikes/bike2/07.webp",
      "assets/bikes/bike2/08.webp",
      "assets/bikes/bike2/09.webp"
    ] },
  { name: "Apus", model: "Softail Custom", size: "sm",
    blurb: "Candy tangerine Softail with ghost flame graphics. 21\" fat-spoke front, blacked Twin Cam, 2-into-1 shorty drag pipe, bobbed rear, solo seat.", tag: "CUSTOM",
    photos: [
      "assets/bikes/bike3/06.webp",
      "assets/bikes/bike3/01.webp",
      "assets/bikes/bike3/02.webp",
      "assets/bikes/bike3/03.webp",
      "assets/bikes/bike3/04.webp",
      "assets/bikes/bike3/05.webp",
      "assets/bikes/bike3/07.webp"
    ] },
  { name: "Cardinal", model: "Softail Custom — FXSTC", size: "wide",
    blurb: "Old-school bobber on a Softail frame. Red and black scallop paint, ape hangers, diamond-stitched solo seat with red contrast, bobbed rear, dual-disc front.", tag: "BOBBER",
    photos: [
      "assets/bikes/bike4/03.webp",
      "assets/bikes/bike4/01.webp",
      "assets/bikes/bike4/02.webp",
      "assets/bikes/bike4/04.webp",
      "assets/bikes/bike4/05.webp"
    ] },
  { name: "Templierul", model: "Softail — Twin Cam 96", size: "wide",
    blurb: "Murdered-out Softail built around the Iron Cross theme — custom cast wheels, RSD turbine air cleaner, LED headlight, blacked everything. The only colour is the gold-leaf Harley script on the tank.", tag: "BLACKED-OUT",
    photos: [
      "assets/bikes/bike5/02.webp",
      "assets/bikes/bike5/01.webp",
      "assets/bikes/bike5/03.webp",
      "assets/bikes/bike5/04.webp",
      "assets/bikes/bike5/05.webp",
      "assets/bikes/bike5/06.webp"
    ] },
  { name: "Glonț", model: "Custom Chopper — S&S Super Stock 111\"", size: "md",
    blurb: "Frame-up long-rake chopper built in-house. Candy apple red, S&S Super Stock 111ci, open BDL belt primary, polished billet wheels, stretched gas tank.", tag: "CHOPPER",
    photos: [
      "assets/bikes/bike6/03.webp",
      "assets/bikes/bike6/01.webp",
      "assets/bikes/bike6/02.webp",
      "assets/bikes/bike6/04.webp",
      "assets/bikes/bike6/05.webp",
      "assets/bikes/bike6/06.webp",
      "assets/bikes/bike6/07.webp"
    ] },
  { name: "Rubin", model: "2001 FXSTI — Stage 3", size: "sm",
    blurb: "Frame-off rebuild of Johnny's '01 FXSTI — Stage 3. Stripped to the bones, everything new: Ultima fat-spoke rims on Avon Cobras, Cobra Bad Hombre exhaust, Arlen Ness mirrors, stretch fenders, Galfer rotors, custom candy paint, upholstery by Vanity Kustom.", tag: "REBUILT",
    photos: [
      "assets/bikes/bike7/02.webp",
      "assets/bikes/bike7/01.webp",
      "assets/bikes/bike7/03.webp"
    ] },
  { name: "Codru", model: "Sportster 1200 — Iron", size: "wide",
    blurb: "Custom candy-green metallic paint over the tank and fender, hand-laid 24k gold leaf Harley script. Stitched bobbed seat, blacked-out hardware.", tag: "CUSTOM",
    photos: [
      "assets/bikes/bike8/01.webp",
      "assets/bikes/bike8/02.webp",
      "assets/bikes/bike8/03.webp",
      "assets/bikes/bike8/04.webp",
      "assets/bikes/bike8/05.webp"
    ] }
];

const DEFAULT_FOR_SALE = [
  {
    id: "fs-hornet",
    name: "Hornet",
    model: "Softail Slim — Twin Cam 103",
    year: "2014",
    status: "Available",
    blurb: "One-off custom Softail finished in matte graphite with acid-green honeycomb graphics. Blacked-out 103ci Twin Cam, diamond-stitched seat and chrome mini-apes — sorted, serviced and ready to ride away.",
    photos: [
      "assets/forsale/hornet/01.jpg",
      "assets/forsale/hornet/02.jpg"
    ],
    video: "assets/forsale/hornet/reel.mp4",
    specs: [
      { label: "The build", items: [
        "Matte graphite + acid-green honeycomb livery",
        "Hand-painted Harley script & shield",
        "Diamond-stitched solo + pillion seat",
        "Colour-matched bobbed fenders"
      ] },
      { label: "Parts & mods", items: [
        "Chrome mini-ape bars on pullback risers",
        "Billet chrome tank console + cap",
        "Fat rear tyre on gloss-black spoked wheels",
        "Blacked-out 103\" Twin Cam, LED tail"
      ] },
      { label: "Included", items: [
        "Fresh full service",
        "New tyres, front & rear",
        "Documents & two keys"
      ] }
    ]
  }
];

const DEFAULT_ABOUT = {
  section: {
    title: "About",
    accent: "us.",
    metaLines: ["Cluj-Napoca, since 2023", "One garage, no compromises"]
  },
  image: {
    url: "assets/shop-floor.webp",
    alt: "The Motor Inc. shop floor in Apahida — Harleys lined up, painted Motor Inc. Service & Repair Garage sign at the back",
    captionIntro: "///",
    captionLabel: "THE FLOOR",
    captionPlace: "APAHIDA",
    captionYear: "2026",
    coordinates: "46.8292° N · 23.7438° E",
    animate: true
  },
  lead: {
    before: "We grew up on",
    accent: "American iron.",
    after: "Now we keep it running on Romanian roads."
  },
  copy: [
    "Motor Inc. opened its doors in Cluj-Napoca in 2023, but our hands are older than that. Between us we've spent years in California shops, on the Sturgis salt, and bent over Twin Cams in barns from Cluj to Constanța. We work on Harleys and American V-twins — and only that — so every bike leaves running better than it came in, logbook in hand."
  ]
};

const DEFAULT_CONTACT = {
  section: {
    title: "Pull up to the",
    accent: "shop.",
    metaLines: ["Tue — Fri · 10—18", "Sat by appointment"]
  },
  address: {
    label: "Address",
    lines: ["Str. Libertății nr. 347", "(Intrarea Câmpenești)", "Apahida, Cluj, Romania"],
    url: "https://www.google.com/maps/place/MOTOR+Inc/@46.8291979,23.7437639,17z/data=!4m6!3m5!1s0x47490fd97e8c8e93:0x7b3981e7a06daca7!8m2!3d46.8291979!4d23.7437639!16s%2Fg%2F11tsp3f8yn",
    parkingNote: "Free parking on-site · Drop-off bay around back"
  },
  phone: {
    label: "Phone",
    display: "+40 747 428 621",
    tel: "+40747428621"
  },
  whatsapp: {
    label: "WhatsApp",
    pill: "FASTEST",
    url: "https://wa.me/40747428621",
    title: "Open chat",
    subtitle: "Send photos · quote within 24h"
  },
  socials: [
    { type: "facebook", label: "Facebook", url: "https://www.facebook.com/profile.php?id=100067445875017" },
    { type: "instagram", label: "Instagram", url: "https://www.instagram.com/motor.inc.garage/" },
    { type: "tiktok", label: "TikTok", url: "https://www.tiktok.com/@motor.inc.garage" }
  ],
  map: {
    embedUrl: "https://maps.google.com/maps?q=MOTOR%20Inc%2C%20Strada%20C%C3%A2mpene%C8%99ti%2C%20Apahida&z=16&output=embed"
  }
};

const normalizeAbout = (about = {}) => ({
  section: {
    title: about.section?.title || DEFAULT_ABOUT.section.title,
    accent: about.section?.accent || DEFAULT_ABOUT.section.accent,
    metaLines: about.section?.meta_lines || about.section?.metaLines || DEFAULT_ABOUT.section.metaLines
  },
  image: {
    ...DEFAULT_ABOUT.image,
    ...(about.image || {}),
    captionIntro: about.image?.caption_intro || about.image?.captionIntro || DEFAULT_ABOUT.image.captionIntro,
    captionLabel: about.image?.caption_label || about.image?.captionLabel || DEFAULT_ABOUT.image.captionLabel,
    captionPlace: about.image?.caption_place || about.image?.captionPlace || DEFAULT_ABOUT.image.captionPlace,
    captionYear: about.image?.caption_year || about.image?.captionYear || DEFAULT_ABOUT.image.captionYear,
    animate: typeof about.image?.animate === 'boolean' ? about.image.animate : DEFAULT_ABOUT.image.animate
  },
  lead: {
    before: about.lead?.before || DEFAULT_ABOUT.lead.before,
    accent: about.lead?.accent || DEFAULT_ABOUT.lead.accent,
    after: about.lead?.after || DEFAULT_ABOUT.lead.after
  },
  copy: Array.isArray(about.copy) && about.copy.length ? about.copy : DEFAULT_ABOUT.copy
});

const normalizeContact = (contact = {}) => ({
  section: {
    title: contact.section?.title || DEFAULT_CONTACT.section.title,
    accent: contact.section?.accent || DEFAULT_CONTACT.section.accent,
    metaLines: contact.section?.meta_lines || contact.section?.metaLines || DEFAULT_CONTACT.section.metaLines
  },
  address: {
    label: contact.address?.label || DEFAULT_CONTACT.address.label,
    lines: contact.address?.lines || DEFAULT_CONTACT.address.lines,
    url: contact.address?.url || DEFAULT_CONTACT.address.url,
    parkingNote: contact.address?.parking_note || contact.address?.parkingNote || DEFAULT_CONTACT.address.parkingNote
  },
  phone: {
    label: contact.phone?.label || DEFAULT_CONTACT.phone.label,
    display: contact.phone?.display || DEFAULT_CONTACT.phone.display,
    tel: contact.phone?.tel || DEFAULT_CONTACT.phone.tel
  },
  whatsapp: {
    label: contact.whatsapp?.label || DEFAULT_CONTACT.whatsapp.label,
    pill: contact.whatsapp?.pill || DEFAULT_CONTACT.whatsapp.pill,
    url: contact.whatsapp?.url || DEFAULT_CONTACT.whatsapp.url,
    title: contact.whatsapp?.title || DEFAULT_CONTACT.whatsapp.title,
    subtitle: contact.whatsapp?.subtitle || DEFAULT_CONTACT.whatsapp.subtitle
  },
  socials: Array.isArray(contact.socials) && contact.socials.length ? contact.socials : DEFAULT_CONTACT.socials,
  map: {
    embedUrl: contact.map?.embed_url || contact.map?.embedUrl || DEFAULT_CONTACT.map.embedUrl
  }
});

const CONTENT = window.motorincContent || {};
const HERO = hasContentProp('hero') && CONTENT.hero ? CONTENT.hero : {};
const SERVICES = hasContentProp('services') && Array.isArray(CONTENT.services) ? CONTENT.services : DEFAULT_SERVICES;
const PROJECTS = hasContentProp('projects') && Array.isArray(CONTENT.projects) ? CONTENT.projects : DEFAULT_PROJECTS;
const FOR_SALE = hasContentProp('forSale') && Array.isArray(CONTENT.forSale) ? CONTENT.forSale : DEFAULT_FOR_SALE;
const ABOUT = normalizeAbout(CONTENT.about);
const CONTACT = normalizeContact(CONTENT.contact);
const HAS_FOR_SALE = FOR_SALE.length > 0;

const TEAM = [
  { initials: "RM", name: "Radu Mihai", role: "Founder · Master Tech", years: "18", badge: "FOUNDER",
    bio: "MMI Phoenix grad. 18 years on Harleys, 6 of them in California. Started Motor Inc. in '23 to bring it home." },
  { initials: "AC", name: "Andrei Cojocaru", role: "Lead Engine Builder", years: "12",
    bio: "Twin Cam and M8 specialist. If it's apart, he can put it back together better than it came." },
  { initials: "ES", name: "Elena Stoica", role: "Paint & Bodywork", years: "9",
    bio: "Trained in House of Kolor candy work. Hand-pinstriping, lettering, gold leaf. Steady hand, sharp eye." },
  { initials: "VP", name: "Vlad Petrescu", role: "Dyno & Tuning", years: "7",
    bio: "PowerVision and Dynojet certified. Treats every map like it's his own bike. Often, it is." }
];

function Nav() {
  const [scrolled, setScrolled] = useState(false);
  const [active, setActive] = useState("");
  useEffect(() => {
    const onScroll = () => setScrolled(window.scrollY > 30);
    window.addEventListener('scroll', onScroll);
    return () => window.removeEventListener('scroll', onScroll);
  }, []);
  useEffect(() => {
    const ids = ["about", "services", ...(HAS_FOR_SALE ? ["forsale"] : []), "projects", "contact"];
    const sections = ids
      .map(id => document.getElementById(id))
      .filter(Boolean);
    if (!sections.length) return;
    const pickActive = () => {
      // Active = the section whose top is closest to (but at/above) the
      // 30%-from-top probe line. Falls back to first section near the top
      // of the page, and clears past the last section.
      const probe = window.innerHeight * 0.3;
      let current = "";
      for (const s of sections) {
        const top = s.getBoundingClientRect().top;
        if (top - probe <= 0) current = s.id;
      }
      setActive(current);
    };
    pickActive();
    window.addEventListener('scroll', pickActive, { passive: true });
    window.addEventListener('resize', pickActive);
    return () => {
      window.removeEventListener('scroll', pickActive);
      window.removeEventListener('resize', pickActive);
    };
  }, []);
  const linkClass = (id) => active === id ? "is-active" : "";
  return (
    <nav className={`nav ${scrolled ? 'scrolled' : ''}`}>
      <a href="#top" className="nav__brand">
        <img src={themeAsset((window.__resources && window.__resources.logo) || "assets/motorinc-logo.jpg")} alt="MotorInc" />
        <span>Motor<em>Inc</em>.</span>
      </a>
      <div className="nav__links">
        <a href="#about" className={linkClass("about")}>About Us</a>
        <a href="#services" className={linkClass("services")}>Services</a>
        {HAS_FOR_SALE && <a href="#forsale" className={linkClass("forsale")}>For Sale</a>}
        <a href="#projects" className={linkClass("projects")}>Projects</a>
        <a href="#contact" className={linkClass("contact")}>Contact</a>
      </div>
      <a href="#contact" className="nav__cta">Book a slot →</a>
    </nav>
  );
}

function Hero() {
  const sparksRef = useRef(null);
  const ironRef = useRef(null);
  const titleRef = useRef(null);
  const reelRef = useRef(null);
  const videoRef = useRef(null);
  const heroVideoUrl = mediaUrl(HERO.video);
  const heroVideoType = (typeof HERO.video === 'string' ? 'video/mp4' : HERO.video?.mime) || 'video/mp4';

  // Belt-and-braces mute: React's `muted` JSX attr is sometimes not reflected
  // onto the DOM property in time for autoplay, so set it imperatively.
  useEffect(() => {
    const v = videoRef.current;
    if (!v) return;
    v.muted = true;
    v.defaultMuted = true;
    v.volume = 0;
    const enforce = () => { v.muted = true; v.volume = 0; };
    v.addEventListener('volumechange', enforce);
    v.addEventListener('play', enforce);
    return () => {
      v.removeEventListener('volumechange', enforce);
      v.removeEventListener('play', enforce);
    };
  }, []);

  // Match shop-reel height to title height in desktop / wider configurations
  useEffect(() => {
    const titleEl = titleRef.current;
    const reelEl = reelRef.current;
    if (!titleEl || !reelEl) return;
    const sync = () => {
      if (window.matchMedia('(min-width: 981px)').matches) {
        reelEl.style.height = titleEl.offsetHeight + 'px';
      } else {
        reelEl.style.height = '';
      }
    };
    sync();
    const ro = new ResizeObserver(sync);
    ro.observe(titleEl);
    window.addEventListener('resize', sync);
    if (document.fonts && document.fonts.ready) document.fonts.ready.then(sync);
    return () => { ro.disconnect(); window.removeEventListener('resize', sync); };
  }, []);

  useEffect(() => {
    const cnv = sparksRef.current;
    const ironEl = ironRef.current;
    if (!cnv || !ironEl) return;
    const ctx = cnv.getContext('2d');
    let raf, dpr = Math.min(window.devicePixelRatio || 1, 2);
    let w = 0, h = 0;
    let edgePoints = []; // sampled letter-edge points, canvas-local coords
    let wordLocal = { x: 0, y: 0, w: 0, h: 0 }; // word position inside canvas
    const sparks = [];
    const PAD = 60; // padding around the word for sparks to fly into

    function sampleLetters() {
      // Render "Iron." into an offscreen canvas at the same metrics, scan pixels
      const cs = getComputedStyle(ironEl);
      const fontSize = parseFloat(cs.fontSize);
      const fontFamily = cs.fontFamily;
      const fontWeight = cs.fontWeight;
      const text = (ironEl.textContent || 'Iron.').trim();

      const off = document.createElement('canvas');
      const wordW = wordLocal.w;
      const wordH = wordLocal.h;
      off.width = Math.max(1, Math.ceil(wordW));
      off.height = Math.max(1, Math.ceil(wordH));
      const octx = off.getContext('2d');
      octx.fillStyle = '#fff';
      octx.textBaseline = 'alphabetic';
      octx.font = `${fontWeight} ${fontSize}px ${fontFamily}`;
      // Bebas Neue baseline ~ 0.82 of em from top; just place near bottom
      octx.fillText(text, 0, wordH * 0.86);

      const data = octx.getImageData(0, 0, off.width, off.height).data;
      const pts = [];
      const step = 3;
      for (let y = 0; y < off.height; y += step) {
        for (let x = 0; x < off.width; x += step) {
          const i = (y * off.width + x) * 4 + 3;
          if (data[i] > 80) {
            // edge if a neighbor is empty
            const isEdge =
              (x + step >= off.width) ||
              (y + step >= off.height) ||
              data[(y * off.width + (x + step)) * 4 + 3] < 80 ||
              data[((y + step) * off.width + x) * 4 + 3] < 80 ||
              (x - step >= 0 && data[(y * off.width + (x - step)) * 4 + 3] < 80) ||
              (y - step >= 0 && data[((y - step) * off.width + x) * 4 + 3] < 80);
            if (isEdge) pts.push({ x, y });
          }
        }
      }
      edgePoints = pts;
    }

    function place() {
      const titleEl = ironEl.parentElement;
      const tRect = titleEl.getBoundingClientRect();
      const iRect = ironEl.getBoundingClientRect();
      // measure actual rendered text width (not the full row block)
      const inner = ironEl.querySelector('.inner') || ironEl;
      const innerRect = inner.getBoundingClientRect();
      const wordW = innerRect.width;
      const wordH = innerRect.height;
      const wordLeft = innerRect.left - tRect.left;
      const wordTop = innerRect.top - tRect.top;

      // canvas covers word + padding
      const canvasLeft = wordLeft - PAD;
      const canvasTop = wordTop - PAD;
      w = wordW + PAD * 2;
      h = wordH + PAD * 2;

      cnv.style.left = canvasLeft + 'px';
      cnv.style.top = canvasTop + 'px';
      cnv.style.width = w + 'px';
      cnv.style.height = h + 'px';
      cnv.width = w * dpr; cnv.height = h * dpr;
      ctx.setTransform(dpr, 0, 0, dpr, 0, 0);

      wordLocal = { x: PAD, y: PAD, w: wordW, h: wordH };
      sampleLetters();
    }

    // Wait for fonts so sampling matches what's rendered
    if (document.fonts && document.fonts.ready) {
      document.fonts.ready.then(place);
    } else {
      place();
    }
    place();
    const ro = new ResizeObserver(place);
    ro.observe(ironEl.parentElement);
    window.addEventListener('resize', place);

    function spawn(n) {
      if (!edgePoints.length) return;
      for (let i = 0; i < n; i++) {
        const p = edgePoints[(Math.random() * edgePoints.length) | 0];
        // canvas-local position of the edge sample
        const ox = wordLocal.x + p.x;
        const oy = wordLocal.y + p.y;
        // upward-biased fan with sideways spread (looks like grinder shower)
        const angle = -Math.PI / 2 + (Math.random() - 0.5) * Math.PI * 0.9;
        const speed = 1.4 + Math.random() * 4.5;
        sparks.push({
          x: ox, y: oy,
          vx: Math.cos(angle) * speed,
          vy: Math.sin(angle) * speed,
          life: 0,
          maxLife: 45 + Math.random() * 70,
          size: 0.7 + Math.random() * 1.4,
          hue: 18 + Math.random() * 30,
        });
      }
    }

    let active = true;
    let last = 0;
    function tick(t) {
      ctx.clearRect(0, 0, w, h);
      if (active && t - last > 40 + Math.random() * 80) {
        spawn(2 + Math.floor(Math.random() * 5));
        last = t;
      }
      ctx.globalCompositeOperation = 'lighter';
      for (let i = sparks.length - 1; i >= 0; i--) {
        const s = sparks[i];
        s.life++;
        s.x += s.vx; s.y += s.vy;
        s.vy += 0.07;
        s.vx *= 0.99; s.vy *= 0.99;
        const lt = s.life / s.maxLife;
        if (lt >= 1) { sparks.splice(i, 1); continue; }
        const a = (1 - lt) * 0.95;

        // glow
        ctx.beginPath();
        ctx.arc(s.x, s.y, s.size * 3.2, 0, Math.PI * 2);
        ctx.fillStyle = `hsla(${s.hue}, 100%, ${60 - lt * 30}%, ${a * 0.16})`;
        ctx.fill();

        // streak
        ctx.beginPath();
        ctx.moveTo(s.x, s.y);
        ctx.lineTo(s.x - s.vx * 1.6, s.y - s.vy * 1.6);
        ctx.strokeStyle = `hsla(${s.hue}, 100%, ${65 - lt * 30}%, ${a})`;
        ctx.lineWidth = s.size;
        ctx.lineCap = 'round';
        ctx.stroke();

        // hot core
        ctx.beginPath();
        ctx.arc(s.x, s.y, s.size, 0, Math.PI * 2);
        ctx.fillStyle = `hsla(50, 100%, ${85 - lt * 30}%, ${a})`;
        ctx.fill();
      }
      ctx.globalCompositeOperation = 'source-over';
      raf = requestAnimationFrame(tick);
    }
    raf = requestAnimationFrame(tick);

    const io = new IntersectionObserver(([e]) => { active = e.isIntersecting; });
    io.observe(cnv);

    return () => {
      cancelAnimationFrame(raf);
      ro.disconnect();
      io.disconnect();
      window.removeEventListener('resize', place);
    };
  }, []);

  return (
    <section className="hero" id="top">

      <div className="wrap">
        <div className="hero__grid">
          <div className="hero__main">
            <div className="hero__eyebrow">
              <span className="dot"></span>
              <span>All-American Service & Repair · Est. 2023</span>
            </div>
            <h1 className="hero__title" ref={titleRef}>
              <span className="row"><span className="inner">American</span></span>
              <span className="row out" ref={ironRef}><span className="inner">Iron.</span></span>
              <span className="row shift"><span className="inner">Romanian</span></span>
              <span className="row red"><span className="inner">Hands.<span className="caret"></span></span></span>
              <span className="hero__title-spec s2" aria-hidden="true">Est. Cluj-Napoca · 2023</span>
            </h1>
            <p className="hero__sub">
              Harley-Davidson and American V-twin specialists. Engine rebuilds, custom builds, dyno tuning — done right, the first time, in Cluj-Napoca.
            </p>
            <div className="hero__ctas">
              <a className="btn btn--primary" href="#contact">Book service <span className="arrow">→</span></a>
              <a className="btn btn--ghost" href="#projects">See our builds</a>
            </div>

          </div>

          <aside className="hero__reel" aria-label="Shop reel" ref={reelRef}>
            <video
              ref={videoRef}
              key={heroVideoUrl || 'bundled-hero-reel'}
              className="hero__reel-video"
              autoPlay
              loop
              muted
              playsInline
              preload="auto"
              aria-hidden="true"
            >
              {heroVideoUrl ? (
                <source src={heroVideoUrl} type={heroVideoType} />
              ) : (
                <>
                  <source src={themeAsset("assets/motorinc-reel.av1.mp4")} type="video/mp4; codecs=&quot;av01.0.04M.08&quot;" />
                  <source src={themeAsset("assets/motorinc-reel.webm")} type="video/webm" />
                  <source src={themeAsset("assets/motorinc-reel.mp4")} type="video/mp4" />
                </>
              )}
            </video>
            <div className="hero__reel-frame" aria-hidden="true"></div>
            <div className="hero__reel-tag">
              <span className="rec"></span>
              <span>LIVE · SHOP REEL</span>
            </div>
            <div className="hero__reel-meta" aria-hidden="true">
              <span>REC</span><span>CLUJ</span>
            </div>
          </aside>
        </div>
      </div>

      <div className="marquee">
        <div className="marquee__track" id="mq">
          {Array.from({length: 2}).map((_, i) => (
            <span key={i}>
              <em>Harley-Davidson</em> <span className="star">★</span>
              <em>Indian</em> <span className="star">★</span>
              <em>Victory</em> <span className="star">★</span>
              <em>Big Dog</em> <span className="star">★</span>
              <em>Boss Hoss</em> <span className="star">★</span>
            </span>
          ))}
        </div>
      </div>
    </section>
  );
}

function SectionHead({ title, accent, meta, metaLines }) {
  const lines = normalizeLines(metaLines || meta);
  return (
    <div className="section-head">
      <h2 className="section-head__title">
        {title} <em>{accent}</em>
      </h2>
      <div className="section-head__meta">
        {lines.map((line, index) => (
          <React.Fragment key={`${line}-${index}`}>
            {line}
            {index < lines.length - 1 && <br />}
          </React.Fragment>
        ))}
      </div>
    </div>
  );
}

function Services() {
  return (
    <section className="services" id="services">
      <div className="wrap">
        <SectionHead num="§ 02 / SERVICES" title="What we" accent="do." meta="Six core services" />
        <div className="services__grid">
          {SERVICES.map(s => (
            <div className="svc" key={s.n}>
              <div className="svc__bar"></div>
              <div>
                <h3 className="svc__title">{s.title}</h3>
                <p className="svc__desc">{s.desc}</p>
              </div>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

function BikeGallery({ photos, code, name, onOpen }) {
  const galleryPhotos = Array.isArray(photos) ? photos : [];
  const trackRef = useRef(null);
  const [idx, setIdx] = useState(0);
  const [canPrev, setCanPrev] = useState(false);
  const [canNext, setCanNext] = useState(true);

  useEffect(() => {
    const el = trackRef.current;
    if (!el) return;
    const onScroll = () => {
      const w = el.clientWidth;
      const i = Math.round(el.scrollLeft / w);
      setIdx(Math.max(0, Math.min(galleryPhotos.length - 1, i)));
      setCanPrev(el.scrollLeft > 4);
      setCanNext(el.scrollLeft + el.clientWidth < el.scrollWidth - 4);
    };
    onScroll();
    el.addEventListener('scroll', onScroll, { passive: true });
    const ro = new ResizeObserver(onScroll);
    ro.observe(el);
    return () => { el.removeEventListener('scroll', onScroll); ro.disconnect(); };
  }, [galleryPhotos.length]);

  const scrollBy = (dir) => {
    const el = trackRef.current;
    if (!el) return;
    el.scrollBy({ left: dir * el.clientWidth, behavior: 'smooth' });
  };

  return (
    <div className="gal">
      <div className="gal__track" ref={trackRef}>
        {galleryPhotos.map((photo, i) => (
          <button
            type="button"
            className="gal__slide"
            key={mediaKey(photo, `${name}-${i}`)}
            onClick={() => onOpen(i)}
            aria-label={`Open photo ${i + 1} of ${galleryPhotos.length} — ${name}`}
          >
            <img
              src={mediaUrl(photo, 'card')}
              srcSet={mediaSrcSet(photo)}
              sizes={mediaSizes(photo, '(max-width: 700px) 92vw, (max-width: 1200px) 50vw, 720px')}
              width={mediaWidth(photo)}
              height={mediaHeight(photo)}
              alt={mediaAlt(photo, `${name} — ${i + 1}`)}
              loading="lazy"
              decoding="async"
              draggable="false"
            />
          </button>
        ))}
      </div>

      <button
        type="button"
        className="gal__nav gal__nav--prev"
        onClick={(e) => { e.stopPropagation(); scrollBy(-1); }}
        disabled={!canPrev}
        aria-label="Previous photo"
      >←</button>
      <button
        type="button"
        className="gal__nav gal__nav--next"
        onClick={(e) => { e.stopPropagation(); scrollBy(1); }}
        disabled={!canNext}
        aria-label="Next photo"
      >→</button>

      <div className="gal__count" aria-hidden="true">
        <span>{String(idx + 1).padStart(2, '0')}</span>
        <span className="gal__count-sep">/</span>
        <span>{String(galleryPhotos.length).padStart(2, '0')}</span>
      </div>
    </div>
  );
}

function Lightbox({ open, photos, startIdx, caption, onClose }) {
  const [idx, setIdx] = useState(startIdx);

  useEffect(() => { if (open) setIdx(startIdx); }, [open, startIdx]);

  useEffect(() => {
    if (!open) return;
    const onKey = (e) => {
      if (e.key === 'Escape') onClose();
      else if (e.key === 'ArrowRight') setIdx(i => Math.min(photos.length - 1, i + 1));
      else if (e.key === 'ArrowLeft') setIdx(i => Math.max(0, i - 1));
    };
    window.addEventListener('keydown', onKey);
    const prevOverflow = document.body.style.overflow;
    document.body.style.overflow = 'hidden';
    return () => {
      window.removeEventListener('keydown', onKey);
      document.body.style.overflow = prevOverflow;
    };
  }, [open, photos.length, onClose]);

  if (!open) return null;

  return (
    <div className="lb" onClick={onClose} role="dialog" aria-modal="true" aria-label="Photo viewer">
      <div className="lb__stage" onClick={(e) => e.stopPropagation()}>
        <img
          className="lb__img"
          src={mediaUrl(photos[idx], 'wide')}
          srcSet={mediaSrcSet(photos[idx])}
          sizes="100vw"
          width={mediaWidth(photos[idx])}
          height={mediaHeight(photos[idx])}
          alt={mediaAlt(photos[idx], caption)}
          decoding="async"
        />
      </div>

      <button type="button" className="lb__close" onClick={onClose} aria-label="Close">×</button>

      {idx > 0 && (
        <button
          type="button"
          className="lb__nav lb__nav--prev"
          onClick={(e) => { e.stopPropagation(); setIdx(i => Math.max(0, i - 1)); }}
          aria-label="Previous"
        >←</button>
      )}
      {idx < photos.length - 1 && (
        <button
          type="button"
          className="lb__nav lb__nav--next"
          onClick={(e) => { e.stopPropagation(); setIdx(i => Math.min(photos.length - 1, i + 1)); }}
          aria-label="Next"
        >→</button>
      )}

      <div className="lb__meta" onClick={(e) => e.stopPropagation()}>
        <div className="lb__caption">{caption}</div>
        <div className="lb__count">
          {String(idx + 1).padStart(2, '0')}
          <span className="lb__count-sep"> / </span>
          {String(photos.length).padStart(2, '0')}
        </div>
      </div>
    </div>
  );
}

function Projects() {
  const [lb, setLb] = useState({ open: false, photos: [], startIdx: 0, caption: '' });
  const closeLb = () => setLb(l => ({ ...l, open: false }));

  return (
    <section className="projects" id="projects">
      <div className="wrap">
        <SectionHead num="§ 03 / WORK" title="Selected" accent="builds." meta={`2023 — ${new Date().getFullYear()}<br/>27 customs · countless rebuilds`} />
        <div className="proj-grid" style={{marginTop: 50}}>
          {PROJECTS.map((p, index) => (
            <article className={`proj size-${p.size || 'md'}`} key={p.id || p.name || index}>
              <div className="proj__media">
                <BikeGallery
                  photos={p.photos}
                  code={p.id}
                  name={p.name}
                  onOpen={(i) => setLb({ open: true, photos: p.photos, startIdx: i, caption: `${p.name} — ${p.model}` })}
                />
              </div>
              <div className="proj__body">
                <div className="proj__head">
                  <h3 className="proj__name">{p.name}</h3>
                  <span className="badge">{p.tag}</span>
                </div>
                <p className="proj__blurb"><b style={{color:'var(--ink)', fontFamily:'var(--f-mono)', fontSize:11, letterSpacing:'0.12em', textTransform:'uppercase'}}>{p.model}</b><br/>{p.blurb}</p>
              </div>
            </article>
          ))}
        </div>
      </div>
      <Lightbox open={lb.open} photos={lb.photos} startIdx={lb.startIdx} caption={lb.caption} onClose={closeLb} />
    </section>
  );
}

function VideoModal({ open, src, onClose }) {
  useEffect(() => {
    if (!open) return;
    const onKey = (e) => { if (e.key === 'Escape') onClose(); };
    window.addEventListener('keydown', onKey);
    const prevOverflow = document.body.style.overflow;
    document.body.style.overflow = 'hidden';
    return () => {
      window.removeEventListener('keydown', onKey);
      document.body.style.overflow = prevOverflow;
    };
  }, [open, onClose]);
  if (!open) return null;
  return (
    <div className="vlb" onClick={onClose}>
      <button className="vlb__close" aria-label="Close video" onClick={onClose}>×</button>
      <div className="vlb__inner" onClick={(e) => e.stopPropagation()}>
        <video src={mediaUrl(src)} controls autoPlay playsInline></video>
      </div>
    </div>
  );
}

function ForSale() {
  const [lb, setLb] = useState({ open: false, photos: [], startIdx: 0, caption: '' });
  const [vid, setVid] = useState({ open: false, src: '' });
  const closeLb = () => setLb(l => ({ ...l, open: false }));

  if (!FOR_SALE.length) return null;

  return (
    <section className="forsale" id="forsale">
      <div className="wrap">
        <SectionHead title="Bikes" accent="For Sale." meta="In the showroom now" />
        <div className="forsale__list">
          {FOR_SALE.map((b, index) => {
            const hasVideo = !!mediaUrl(b.video);
            return (
            <article className="fs-row" key={b.id || b.name || index}>
              <div className="fs-row__media">
                <BikeGallery
                  photos={b.photos}
                  code={b.id}
                  name={b.name}
                  onOpen={(i) => setLb({ open: true, photos: b.photos, startIdx: i, caption: `${b.name} — ${b.model}` })}
                />
                {hasVideo && (
                  <button
                    type="button"
                    className="fs-videobtn"
                    onClick={() => setVid({ open: true, src: b.video })}
                  >
                    <span className="fs-videobtn__play">▶</span> Watch video
                  </button>
                )}
              </div>
              <div className="fs-row__body">
                <div className="fs-row__head">
                  <span className="fs-row__status">{b.status}</span>
                  <h3 className="fs-row__name">{b.name}</h3>
                  <p className="fs-row__model">{b.model} · {b.year}</p>
                </div>
                <p className="fs-row__blurb">{b.blurb}</p>
                <div className="fs-specs">
                  {(b.specs || []).map(g => (
                    <div className="fs-spec" key={g.label}>
                      <h4>{g.label}</h4>
                      <ul>
                        {(g.items || []).map(it => <li key={it}>{it}</li>)}
                      </ul>
                    </div>
                  ))}
                </div>
                <div className="fs-row__actions">
                  <a className="btn btn--primary" href={`tel:${CONTACT.phone.tel}`}>Call Us</a>
                  {hasVideo && (
                    <button type="button" className="btn btn--ghost" onClick={() => setVid({ open: true, src: b.video })}>
                      <span className="arrow">▶</span> Video
                    </button>
                  )}
                </div>
              </div>
            </article>
            );
          })}
        </div>
      </div>
      <Lightbox open={lb.open} photos={lb.photos} startIdx={lb.startIdx} caption={lb.caption} onClose={closeLb} />
      <VideoModal open={vid.open} src={vid.src} onClose={() => setVid({ open: false, src: '' })} />
    </section>
  );
}

function About() {
  const floorRef = useRef(null);
  const [inView, setInView] = useState(!ABOUT.image.animate);
  const shopImageUrl = mediaUrl(ABOUT.image, 'wide') || themeAsset(DEFAULT_ABOUT.image.url);

  useEffect(() => {
    const el = floorRef.current;
    if (!el || !ABOUT.image.animate) {
      setInView(true);
      return;
    }
    // Respect reduced motion: skip the animation entirely
    if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
      setInView(true);
      return;
    }
    const io = new IntersectionObserver(([entry]) => {
      if (entry.isIntersecting) {
        setInView(true);
        io.disconnect();
      }
    }, { threshold: 0.25 });
    io.observe(el);
    return () => io.disconnect();
  }, []);

  return (
    <section className="about" id="about">
      <div className="wrap">
        <SectionHead title={ABOUT.section.title} accent={ABOUT.section.accent} metaLines={ABOUT.section.metaLines} />

        <figure
          className={`shop-floor${inView ? ' is-in-view' : ''}${ABOUT.image.animate ? '' : ' is-static'}`}
          ref={floorRef}
          role="img"
          aria-label={mediaAlt(ABOUT.image, DEFAULT_ABOUT.image.alt)}
          style={{ "--shop-floor-image": `url(${shopImageUrl})` }}
        >
          <div className="shop-floor__split" aria-hidden="true">
            <div className="shop-floor__half shop-floor__half--left"></div>
            <div className="shop-floor__half shop-floor__half--right"></div>
          </div>
          <span className="shop-floor__tick" aria-hidden="true"></span>
          <figcaption className="shop-floor__cap" aria-hidden="true">
            <span>{ABOUT.image.captionIntro}</span>
            <span>{ABOUT.image.captionLabel}</span>
            <span className="shop-floor__cap-dot">·</span>
            <span>{ABOUT.image.captionPlace}</span>
            <span className="shop-floor__cap-dot">·</span>
            <span>{ABOUT.image.captionYear}</span>
          </figcaption>
          <span className="shop-floor__coord" aria-hidden="true">{ABOUT.image.coordinates}</span>
        </figure>

        <div className="about__intro">
          <h3 className="about__lead">
            {ABOUT.lead.before} <em>{ABOUT.lead.accent}</em> {ABOUT.lead.after}
          </h3>
          <div className="about__copy">
            {ABOUT.copy.map((paragraph, index) => <p key={`${paragraph}-${index}`}>{paragraph}</p>)}
          </div>
        </div>
        {/* Team / individuals section temporarily hidden
        <div className="team">
          {TEAM.map((m, i) => (
            <div className="member" key={m.name}>
              <div className="member__years">{String(i+1).padStart(2,'0')}</div>
              <div className="member__photo">
                {m.badge && <span className="badge">{m.badge}</span>}
                <span className="ph">{m.initials}</span>
              </div>
              <h4 className="member__name">{m.name}</h4>
              <div className="member__role">{m.role} · {m.years} yrs</div>
              <p className="member__bio">{m.bio}</p>
            </div>
          ))}
        </div>
        */}
      </div>
    </section>
  );
}

function WhatsAppIcon() {
  return (
    <svg viewBox="0 0 24 24"><path d="M17.5 14.4c-.3-.1-1.7-.8-2-.9-.3-.1-.5-.2-.7.2-.2.3-.8.9-.9 1.1-.2.2-.3.2-.6.1-1.6-.8-2.6-1.4-3.7-3.2-.3-.5.3-.5.8-1.5.1-.2 0-.4 0-.5l-.9-2.2c-.2-.6-.5-.5-.7-.5h-.6c-.2 0-.5.1-.8.4-.3.3-1 1-1 2.4s1 2.8 1.2 3c.1.2 2 3.1 4.9 4.4 1.8.8 2.5.9 3.4.7.5-.1 1.7-.7 1.9-1.3.2-.7.2-1.2.2-1.3-.1-.1-.3-.2-.6-.3zM12 2C6.5 2 2 6.5 2 12c0 1.9.5 3.6 1.4 5.1L2 22l5-1.4c1.4.8 3.1 1.3 5 1.3 5.5 0 10-4.5 10-10S17.5 2 12 2zm0 18c-1.7 0-3.3-.5-4.7-1.3l-.3-.2-3 .8.8-2.9-.2-.3C3.5 14.7 3 13.4 3 12 3 7 7 3 12 3s9 4 9 9-4 9-9 9z"/></svg>
  );
}

function SocialIcon({ type }) {
  if (type === 'instagram') {
    return <svg viewBox="0 0 24 24"><path d="M12 2.2c3.2 0 3.6 0 4.8.1 1.2 0 1.8.3 2.3.4.5.2 1 .5 1.4 1 .4.4.7.8.9 1.4.2.5.4 1.1.4 2.3.1 1.2.1 1.6.1 4.8s0 3.6-.1 4.8c0 1.2-.3 1.8-.4 2.3-.2.5-.5 1-1 1.4-.4.4-.8.7-1.4.9-.5.2-1.1.4-2.3.4-1.2.1-1.6.1-4.8.1s-3.6 0-4.8-.1c-1.2 0-1.8-.3-2.3-.4-.5-.2-1-.5-1.4-1-.4-.4-.7-.8-.9-1.4-.2-.5-.4-1.1-.4-2.3C2.2 15.6 2.2 15.2 2.2 12s0-3.6.1-4.8c0-1.2.3-1.8.4-2.3.2-.5.5-1 1-1.4.4-.4.8-.7 1.4-.9.5-.2 1.1-.4 2.3-.4C8.4 2.2 8.8 2.2 12 2.2zm0 2.2c-3.1 0-3.5 0-4.7.1-1.1 0-1.7.3-2.1.4-.5.2-.9.4-1.3.8-.4.4-.6.8-.8 1.3-.1.4-.3 1-.4 2.1C2.6 8.5 2.6 8.9 2.6 12s0 3.5.1 4.7c0 1.1.3 1.7.4 2.1.2.5.4.9.8 1.3.4.4.8.6 1.3.8.4.1 1 .3 2.1.4 1.2.1 1.6.1 4.7.1s3.5 0 4.7-.1c1.1 0 1.7-.3 2.1-.4.5-.2.9-.4 1.3-.8.4-.4.6-.8.8-1.3.1-.4.3-1 .4-2.1.1-1.2.1-1.6.1-4.7s0-3.5-.1-4.7c0-1.1-.3-1.7-.4-2.1-.2-.5-.4-.9-.8-1.3-.4-.4-.8-.6-1.3-.8-.4-.1-1-.3-2.1-.4C15.5 4.4 15.1 4.4 12 4.4zm0 3.4a4.2 4.2 0 1 1 0 8.4 4.2 4.2 0 0 1 0-8.4zm0 6.9a2.7 2.7 0 1 0 0-5.4 2.7 2.7 0 0 0 0 5.4zm5.4-7.1a1 1 0 1 1-2 0 1 1 0 0 1 2 0z"/></svg>;
  }
  if (type === 'tiktok') {
    return <svg viewBox="0 0 24 24"><path d="M19.6 6.7a5.6 5.6 0 0 1-3.2-1V15a5.5 5.5 0 1 1-5.5-5.5h.7v2.7a2.8 2.8 0 1 0 2 2.7V2h2.7a3.6 3.6 0 0 0 3.3 3.2v2.5z"/></svg>;
  }
  return <svg viewBox="0 0 24 24"><path d="M22 12a10 10 0 1 0-11.6 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.7l-.4 2.9h-2.3v7A10 10 0 0 0 22 12z"/></svg>;
}

function Contact() {
  return (
    <section className="contact" id="contact">
      <div className="wrap">
        <SectionHead title={CONTACT.section.title} accent={CONTACT.section.accent} metaLines={CONTACT.section.metaLines} />
        <div className="contact__grid">
          <div className="contact__info">
            <div className="info-block">
              <h4>{CONTACT.address.label}</h4>
              <a
                className="address-link"
                href={CONTACT.address.url}
                target="_blank"
                rel="noopener"
              >
                {CONTACT.address.lines.map((line, index) => (
                  <React.Fragment key={line}>
                    {line}
                    {index < CONTACT.address.lines.length - 1 && <br />}
                  </React.Fragment>
                ))}
              </a>
              <p className="small">{CONTACT.address.parkingNote}</p>
            </div>
            <div className="info-block">
              <h4>{CONTACT.phone.label}</h4>
              <a href={`tel:${CONTACT.phone.tel}`}>{CONTACT.phone.display}</a>
            </div>
            <div className="info-block info-block--whatsapp">
              <h4>{CONTACT.whatsapp.label} <span className="info-block__pill">{CONTACT.whatsapp.pill}</span></h4>
              <a className="wa-cta" href={CONTACT.whatsapp.url} target="_blank" rel="noopener">
                <span className="wa-cta__icon" aria-hidden="true"><WhatsAppIcon /></span>
                <span className="wa-cta__body">
                  <strong>{CONTACT.whatsapp.title}</strong>
                  <span className="wa-cta__sub">{CONTACT.whatsapp.subtitle}</span>
                </span>
                <span className="wa-cta__arrow" aria-hidden="true">→</span>
              </a>
            </div>
            <div className="info-block">
              <h4>Follow</h4>
              <div className="socials">
                {CONTACT.socials.map((social) => (
                  <a className="social" href={social.url} target="_blank" rel="noopener" aria-label={social.label} key={social.type}>
                    <SocialIcon type={social.type} />
                    {social.label}
                  </a>
                ))}
              </div>
            </div>
          </div>
          <div className="contact__map">
            <iframe
              src={CONTACT.map.embedUrl}
              loading="lazy"
              referrerPolicy="no-referrer-when-downgrade"
              title="MotorInc location"></iframe>
          </div>
        </div>
      </div>
    </section>
  );
}

function PrivacyPolicyModal({ open, onClose }) {
  const closeRef = useRef(null);

  useEffect(() => {
    if (!open) return;
    const previousActive = document.activeElement;
    const onKey = (e) => { if (e.key === 'Escape') onClose(); };
    window.addEventListener('keydown', onKey);
    const prevOverflow = document.body.style.overflow;
    document.body.style.overflow = 'hidden';
    window.requestAnimationFrame(() => closeRef.current?.focus());
    return () => {
      window.removeEventListener('keydown', onKey);
      document.body.style.overflow = prevOverflow;
      previousActive?.focus?.();
    };
  }, [open, onClose]);

  if (!open) return null;

  return (
    <div className="privacy-modal" role="dialog" aria-modal="true" aria-labelledby="privacy-title" onClick={onClose}>
      <div className="privacy-modal__dialog" onClick={(e) => e.stopPropagation()}>
        <button type="button" className="privacy-modal__close" onClick={onClose} aria-label="Close privacy policy" ref={closeRef}>×</button>
        <div className="privacy-modal__header">
          <span>Motor Inc Garage SRL</span>
          <h2 id="privacy-title">Privacy Policy / Politica de confidentialitate</h2>
          <p>Last updated / Ultima actualizare: 3 June 2026</p>
        </div>

        <div className="privacy-modal__body">
          <section className="privacy-block">
            <h3>English</h3>
            <p>
              This website is operated by MOTOR INC GARAGE SRL, CUI 46322110,
              Trade Register no. J2022003625129, EUID ROONRC.J2022003625129,
              registered on 17 June 2022, with its registered office at Str.
              Libertatii 347, Sat Apahida, Jud. Cluj, 407035, Romania.
            </p>
            <p>
              We process only the data needed to run this website, answer service
              requests, and maintain business communication. This may include
              server logs such as IP address, browser/device information and
              visit time, plus any details you choose to send by phone, WhatsApp,
              email or social media.
            </p>
            <p>
              We use this information to respond to inquiries, prepare service or
              sales follow-up, protect the website, and comply with legal,
              accounting or administrative obligations. We keep inquiry messages
              only for as long as reasonably needed for customer service and
              business records, unless a longer legal retention period applies.
            </p>
            <p>
              The site may load content or services from third parties, including
              Hostinger for hosting, Google Maps, Google Fonts or script CDNs,
              WhatsApp/Meta, Facebook, Instagram and TikTok. If you interact with
              those services, their own privacy terms also apply.
            </p>
            <p>
              We do not intentionally use analytics or marketing cookies on this
              website at this stage. Essential technical cookies or server logs
              may still be used by WordPress, the hosting provider or security
              tools to keep the site working.
            </p>
            <p>
              Under GDPR, you may request access, correction, deletion,
              restriction, portability or objection regarding your personal data.
              You may also lodge a complaint with ANSPDCP. For privacy requests,
              contact us using the phone or WhatsApp details shown on this site.
            </p>
          </section>

          <section className="privacy-block" lang="ro">
            <h3>Romana</h3>
            <p>
              Acest website este operat de MOTOR INC GARAGE SRL, CUI 46322110,
              nr. Registrul Comertului J2022003625129, EUID
              ROONRC.J2022003625129, infiintata la 17 iunie 2022, cu sediul in
              Str. Libertatii 347, Sat Apahida, Jud. Cluj, 407035, Romania.
            </p>
            <p>
              Prelucram doar datele necesare pentru functionarea website-ului,
              pentru a raspunde solicitarilor de service si pentru comunicarea
              comerciala. Aceste date pot include jurnale tehnice precum adresa
              IP, informatii despre browser/dispozitiv si momentul vizitei,
              precum si detaliile pe care ni le trimiteti prin telefon,
              WhatsApp, email sau retele sociale.
            </p>
            <p>
              Folosim aceste informatii pentru a raspunde solicitarilor, pentru
              follow-up legat de service sau vanzari, pentru securitatea
              website-ului si pentru indeplinirea obligatiilor legale, contabile
              sau administrative. Pastram mesajele de solicitare doar cat este
              rezonabil necesar pentru relatia cu clientii si evidentele
              comerciale, cu exceptia cazurilor in care legea cere o perioada
              mai lunga.
            </p>
            <p>
              Website-ul poate incarca servicii sau continut de la terti,
              inclusiv Hostinger pentru gazduire, Google Maps, Google Fonts sau
              CDN-uri de scripturi, WhatsApp/Meta, Facebook, Instagram si
              TikTok. Daca interactionati cu aceste servicii, se aplica si
              politicile lor de confidentialitate.
            </p>
            <p>
              In acest moment nu folosim in mod intentionat cookies de analiza
              sau marketing. Cookies tehnice esentiale sau jurnale de server pot
              fi folosite totusi de WordPress, furnizorul de gazduire sau
              instrumentele de securitate pentru functionarea website-ului.
            </p>
            <p>
              Conform GDPR, puteti solicita accesul, corectarea, stergerea,
              restrictionarea, portabilitatea sau opozitia privind datele
              personale. De asemenea, puteti depune o plangere la ANSPDCP.
              Pentru solicitari privind confidentialitatea, contactati-ne folosind
              telefonul sau WhatsApp-ul afisat pe acest website.
            </p>
          </section>
        </div>
      </div>
    </div>
  );
}

function Footer({ onPrivacyOpen }) {
  return (
    <footer className="footer">
      <div className="wrap">
        <div className="footer__brand">
          <img src={themeAsset((window.__resources && window.__resources.logo) || "assets/motorinc-logo.jpg")} alt="" />
          <span>© 2026 Motor Inc. SRL</span>
        </div>
        <div className="footer__center">All American · Service & Repair · Est. '23</div>
        <div className="footer__right">
          <a href="#privacy" className="footer__link" onClick={onPrivacyOpen}>Privacy Policy</a>
          <span>Built in Cluj-Napoca, RO</span>
        </div>
      </div>
    </footer>
  );
}

function Tweaks() {
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
  useEffect(() => {
    document.documentElement.style.setProperty('--accent', t.accent);
    document.documentElement.style.setProperty('--ink', t.ink);
    document.body.classList.toggle('grain', !!t.grain);
    const mq = document.getElementById('mq');
    if (mq) mq.style.animationDuration = `${t.marqueeSpeed}s`;
  }, [t]);

  return (
    <TweaksPanel title="Tweaks">
      <TweakSection title="Accent">
        <TweakColor
          label="Brand color"
          value={t.accent}
          onChange={v => setTweak('accent', v)}
          options={['#851d2c', '#2db5e8', '#f59e0b', '#22c55e', '#16140f']}
        />
        <TweakColor
          label="Headline ink"
          value={t.ink}
          onChange={v => setTweak('ink', v)}
          options={['#16140f', '#262220', '#37322c', '#4a443c']}
        />
      </TweakSection>
      <TweakSection title="Atmosphere">
        <TweakToggle label="Film grain" value={t.grain} onChange={v => setTweak('grain', v)} />
        <TweakSlider label="Marquee speed" min={15} max={80} step={1} value={t.marqueeSpeed} onChange={v => setTweak('marqueeSpeed', v)} suffix="s" />
      </TweakSection>
    </TweaksPanel>
  );
}

function App() {
  const showTweaks = !!(window.motorincTheme && window.motorincTheme.enableTweaks);
  const [privacyOpen, setPrivacyOpen] = useState(false);
  const openPrivacy = (event) => {
    event?.preventDefault?.();
    if (window.location.hash !== '#privacy') {
      window.history.pushState(null, '', '#privacy');
    }
    setPrivacyOpen(true);
  };
  const closePrivacy = () => {
    setPrivacyOpen(false);
    if (window.location.hash === '#privacy') {
      window.history.pushState(null, document.title, `${window.location.pathname}${window.location.search}`);
    }
  };

  useEffect(() => {
    const syncPrivacyHash = () => setPrivacyOpen(window.location.hash === '#privacy');
    syncPrivacyHash();
    window.addEventListener('hashchange', syncPrivacyHash);
    return () => window.removeEventListener('hashchange', syncPrivacyHash);
  }, []);

  return (
    <>
      <Nav />
      <Hero />
      <About />
      <Services />
      <ForSale />
      <Projects />
      <Contact />
      <Footer onPrivacyOpen={openPrivacy} />
      <PrivacyPolicyModal open={privacyOpen} onClose={closePrivacy} />
      {showTweaks && <Tweaks />}
    </>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<App />);
