/* Dr Jillian - Black Friday open day: icons, header, strip, hero, form, countdown, packages, benefits, photo strip */
(function () {
  const { useState, useEffect, useRef } = React;

  const P = {
    phone: <path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z" />,
    calendar: <><rect x="3" y="4" width="18" height="18" rx="1" /><path d="M16 2v4M8 2v4M3 10h18" /></>,
    check: <path d="M20 6 9 17l-5-5" />,
    plus: <path d="M12 5v14M5 12h14" />,
    user: <><circle cx="12" cy="8" r="4" /><path d="M4 21c0-4 3.6-7 8-7s8 3 8 7" /></>,
    scan: <><path d="M3 7V5a2 2 0 0 1 2-2h2M17 3h2a2 2 0 0 1 2 2v2M21 17v2a2 2 0 0 1-2 2h-2M7 21H5a2 2 0 0 1-2-2v-2" /><path d="M7 12h10" /></>,
    sparkle: <path d="M12 3l1.9 5.8L20 11l-6.1 2.2L12 19l-1.9-5.8L4 11l6.1-2.2z" />,
    car: <><path d="M19 17h2c.6 0 1-.4 1-1v-3c0-.9-.7-1.7-1.5-1.9C18.7 10.6 16 10 16 10s-1.3-1.4-2.2-2.3c-.5-.4-1.1-.7-1.8-.7H5c-.6 0-1.1.4-1.4.9l-1.4 2.9A3.7 3.7 0 0 0 2 12v4c0 .6.4 1 1 1h2" /><circle cx="7" cy="17" r="2" /><path d="M9 17h6" /><circle cx="17" cy="17" r="2" /></>,
    pin: <><path d="M20 10c0 6-8 12-8 12s-8-6-8-12a8 8 0 0 1 16 0Z" /><circle cx="12" cy="10" r="3" /></>,
    clock: <><circle cx="12" cy="12" r="10" /><path d="M12 6v6l4 2" /></>,
    arrowL: <path d="M15 18l-6-6 6-6" />,
    arrowR: <path d="M9 18l6-6-6-6" />,
  };
  const Ic = ({ n }) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">{P[n]}</svg>;

  const Header = ({ cfg }) => (
    <header className="hdr">
      <div className="wrap hdr__row">
        <a className="logo" href="#top" aria-label="Dr Jillian Dental Care and Aesthetics - back to top"><img src="dj/img/logo-slate.png" alt="Dr Jillian Dental Care and Aesthetics" /></a>
        <nav className="nav" aria-label="Page sections">
          {[["The offers", "#offers"], ["Your journey", "#journey"], ["Dr Jillian", "#dr-jillian"], ["Prices", "#prices"], ["FAQs", "#faq"]].map(([l, h]) => <a key={h} href={h}>{l}</a>)}
        </nav>
        <div className="hdr__end">
          <a className="hdr__phone" href={"tel:" + cfg.tel}><Ic n="phone" />{cfg.phone}</a>
          <a className="btn" href="#book">Request your spot</a>
          <a className="hdr__icon" href={"tel:" + cfg.tel} aria-label={"Call " + cfg.phone}><Ic n="phone" /></a>
          <a className="hdr__icon hdr__icon--book" href="#book" aria-label="Request your spot"><Ic n="calendar" /></a>
        </div>
      </div>
    </header>
  );

  const Marquee = ({ cfg }) => {
    const unit = (k) => <span className="marquee__item" key={k}>Black Friday <em>open day</em><i className="marquee__dot"></i>{cfg.dateShort}<i className="marquee__dot"></i></span>;
    return (
      <div className="marquee" role="img" aria-label={"Black Friday open day, " + cfg.dateShort}>
        <div className="marquee__track" aria-hidden="true">{[0, 1, 2, 3].map(unit)}</div>
      </div>
    );
  };

  const Countdown = ({ end }) => {
    const target = new Date(end).getTime();
    const [now, setNow] = useState(Date.now());
    useEffect(() => { const t = setInterval(() => setNow(Date.now()), 1000); return () => clearInterval(t); }, []);
    const left = Math.max(0, target - now);
    const cells = [[Math.floor(left / 864e5), "Days"], [Math.floor(left / 36e5) % 24, "Hours"], [Math.floor(left / 6e4) % 60, "Minutes"], [Math.floor(left / 1e3) % 60, "Seconds"]];
    return (
      <div className="count" role="timer" aria-label={"Open day starts in " + cells[0][0] + " days and " + cells[1][0] + " hours"}>
        <p className="count__label">Open day starts in</p>
        <div className="count__grid">{cells.map(([n, u]) => <div key={u}><div className="count__n">{n}</div><div className="count__u">{u}</div></div>)}</div>
      </div>
    );
  };

  // ActiveCampaign form 29. The embed fills the first empty ._form_29 div when it loads, so it is
  // injected after React has rendered that div. Its JSONP response calls window._show_thank_you,
  // which is wrapped to send the visitor to the thank-you page.
  const LeadForm = ({ cfg }) => {
    useEffect(() => {
      const s = document.createElement("script");
      s.src = "https://drjilliandental.activehosted.com/f/embed.php?id=29";
      s.charset = "utf-8";
      s.onload = () => {
        const show = window._show_thank_you;
        window._show_thank_you = function () {
          try { if (show) show.apply(this, arguments); } catch (e) {}
          window.location.href = cfg.thanks;
        };
      };
      document.body.appendChild(s);
    }, []);
    return <div className="_form_29"></div>;
  };

  const HERO_USPS = [
    ["user", "Every consultation is with Dr Jillian, our clinical lead"],
    ["scan", "See your new smile on screen before you commit"],
    ["sparkle", "One of the first regional Enlighten whitening centres of excellence in Northern Ireland"],
    ["car", "Free roadside parking, five minutes from Larne train and bus station"],
  ];

  const Hero = ({ cfg }) => (
    <section className="hero" id="top" aria-labelledby="hero-h1">
      <div className="hero__bg"><img src="dj/img/dr-jillian-portrait.jpg" alt="Dr Jillian smiling in the reception at her Glenarm Road practice" /></div>
      <div className="wrap hero__grid">
        <div className="hero__side">
          <Countdown end={cfg.countdownEnd} />
          {HERO_USPS.map(([ic, t]) => <div className="usp" key={t}><Ic n={ic} /><span>{t}</span></div>)}
        </div>
        <div className="panel" id="book">
          <span className="blob">Only 14 slots available</span>
          <h1 id="hero-h1">Huge Smile Makeover savings in Larne this <em>Black Friday</em></h1>
          <p className="panel__date"><Ic n="calendar" /><span>{cfg.dateLong}</span></p>
          <p className="panel__sub">Straighter, brighter or completely refreshed - whatever you want to change about your smile, this is the day to start. Sit down with Dr Jillian for £63 instead of £126, and unlock savings on Invisalign, smile makeovers and teeth whitening.</p>
          <LeadForm cfg={cfg} />
        </div>
      </div>
    </section>
  );

  const PACKAGES = [
    { t: "Invisalign", b: "Up to £1,308.43 savings package", items: ["Consultation with Dr Jillian for £63 instead of £252 (saving £189)", "Trios 3D scan and digital smile simulation (worth £85.75)", "X-rays (worth £22.64)", "Free gum health assessment and review (worth £222.04)", "Free teeth whitening (worth £356.56)", "Free retainers (worth £232.44)", "£200 off your treatment if self-funding (£100 off with finance)"] },
    { t: "Full smile makeover, 20 composite veneers", b: "Save £1,310.30", items: ["20 composite veneers, hand-shaped by Dr Jillian", "Free teeth whitening (worth £356.56)", "Free biteguard", "Gum health assessment with Niamh, our dental therapist", "Complimentary review with clinical photos"] },
    { t: "Full smile makeover, 10 composite veneers", b: "Save £804.23", items: ["10 composite veneers, hand-shaped by Dr Jillian", "Free teeth whitening (worth £356.56)", "Free biteguard", "Gum health assessment with Niamh, our dental therapist", "Complimentary review with clinical photos"] },
    { t: "Teeth whitening", b: "Up to half price off", items: ["Enlighten whitening for £400, normally £520", "Bespoke whitening for £178.28, normally £356.56", "Your choice of Enlighten or bespoke whitening", "A guaranteed B1 shade with Enlighten", "Custom-made whitening trays", "A check with Dr Jillian that your teeth are ready to whiten"] },
  ];

  const Packages = () => {
    const [a, setA] = useState(0);
    const [h, setH] = useState(760);
    const stage = useRef(null);
    const n = PACKAGES.length;
    const go = (d) => setA((a + d + n) % n);
    useEffect(() => {
      const m = () => { const el = stage.current; if (!el) return; let mx = 0; el.querySelectorAll(".pkc").forEach((c) => { mx = Math.max(mx, c.offsetHeight); }); setH(mx + 48); };
      m(); window.addEventListener("resize", m); const t = setTimeout(m, 400); return () => { window.removeEventListener("resize", m); clearTimeout(t); };
    }, []);
    const arrows = (cls) => (
      <React.Fragment>
        <button type="button" className={"pk__arrow pk__arrow--l " + cls} onClick={() => go(-1)} aria-label="Previous package"><Ic n="arrowL" /></button>
        <button type="button" className={"pk__arrow pk__arrow--r " + cls} onClick={() => go(1)} aria-label="Next package"><Ic n="arrowR" /></button>
      </React.Fragment>
    );
    return (
      <section className="sec sec--deep pk" id="offers" aria-labelledby="pk-h">
        <img className="pk__mark" src="dj/img/mark-white.png" alt="" />
        <div className="wrap">
          <div className="shead">
            <h2 className="h2" id="pk-h">Three ways to a smile you love this Black Friday, one day to start</h2>
            <p className="lead">Every Black Friday package starts with a half-price consultation with Dr Jillian, including clinical photos, X-rays, oral cancer screening and shade matching. Interest-free finance is available on every package.</p>
          </div>
        </div>
        <div className="pk__stage" ref={stage} style={{ "--pk-h": h + "px" }} aria-roledescription="carousel" aria-label="Black Friday packages">
          {PACKAGES.map((p, i) => {
            let off = (i - a + n) % n; if (off > n / 2) off -= n;
            const cls = off === 0 ? "" : Math.abs(off) === 1 ? " is-side" : " is-off";
            return (
              <article key={p.t} className={"pkc" + cls} data-off={off} aria-hidden={off !== 0} style={{ transform: "translateX(calc(-50% + " + off * 108 + "%)) scale(" + (off === 0 ? 1 : 0.92) + ")" }} onClick={() => { if (off !== 0) setA(i); }}>
                <span className="pkc__badge">{p.b}</span>
                <h3 className="pkc__t">{p.t}</h3>
                <p className="pkc__k">Your package includes:</p>
                <ul className="ticks">{p.items.map((x) => <li key={x}><Ic n="check" /><span>{x}</span></li>)}</ul>
                <a className="btn" href="#book" tabIndex={off === 0 ? 0 : -1}>Request your spot</a>
              </article>
            );
          })}
          {arrows("")}
        </div>
        <div className="pk__mob">{arrows("")}</div>
        <div className="pk__dots">{PACKAGES.map((p, i) => <button key={p.t} type="button" className={i === a ? "on" : ""} onClick={() => setA(i)} aria-label={"Show " + p.t}></button>)}</div>
      </section>
    );
  };

  const Benefits = () => {
    const items = [
      ["\u201CI don't want people to know I'm having my teeth straightened.\u201D", "Invisalign aligners are clear and barely noticeable, and they come out when you eat, brush or have a big occasion. Most people around you will never know."],
      ["\u201CI'm worried it won't look natural.\u201D", "Natural results are what we care about most. Your veneers are shaped by hand and shade matched to suit your face, so people notice that you look well - not that you have had work done."],
      ["\u201CI've tried whitening kits and they didn't work.\u201D", "Professional whitening is planned around your teeth, with custom trays and a dentist checking your teeth are healthy first. The result is even and lasting, not patchy."],
      ["\u201CI don't know what I actually need.\u201D", "You don't have to. Your consultation is there to talk it through, see your options and decide in your own time."],
      ["\u201CDentists make me nervous.\u201D", "You are far from alone. Dr Jillian is known for putting nervous patients at ease, and we offer oral sedation and the Calm Kit, which lets you signal at any moment if you need us to slow down or stop."],
    ];
    return (
      <section className="sec" id="benefits" aria-labelledby="ben-h">
        <div className="wrap">
          <div className="ben__head ben__head--top">
            <h2 className="h2" id="ben-h">The smile you have been putting off is closer than you think</h2>
            <p className="lead">Most people who come to see us have been thinking about it for a while. Here is what tends to hold them back - and what changes.</p>
          </div>
          <div className="ben">
            <div className="ben__img"><img src="dj/img/consultation-chat.jpg" alt="A patient chatting with a member of the Dr Jillian team in the waiting room" loading="lazy" /></div>
            <ul className="ben__list">{items.map(([q, d]) => <li key={q}><p className="ben__q">{q}</p><p>{d}</p></li>)}</ul>
          </div>
        </div>
      </section>
    );
  };

  const Strip = () => (
    <div className="strip" aria-hidden="true">
      <img src="dj/img/washroom.jpg" alt="" loading="lazy" style={{ objectPosition: "center 40%" }} />
      <img src="dj/img/stairwell.jpg" alt="" loading="lazy" />
      <img src="dj/img/lanterns.jpg" alt="" loading="lazy" style={{ objectPosition: "65% center" }} />
    </div>
  );

  const REVIEWS = [
    ["Audrey", "7 months ago", ["Got my invisalign and teeth whitening treatment done here and I am very happy with how my teeth look now. I also come here for dental check ups and hygiene appointments. All staff are very lovely!"]],
    ["Abigail Martin", "2 years ago", ["I was delighted with my Invisalign treatment and the care and service from Jillian was second to none. Probably the best dentist I've ever seen. She makes you feel so calm during treatment, (I'm a very nervous patient)"]],
    ["Jamie Petticrew", "a year ago", ["I\u2019ve just completed my Invisalign journey with Larne Dental Centre, and I honestly couldn\u2019t be happier with the experience! From start to finish, the staff were incredibly friendly, welcoming, and supportive. They truly go above and beyond to make the process as smooth and comfortable as possible.", "I would honestly say this Invisalign treatment has been life-changing for me \u2014 not just in terms of my smile, but also my confidence. It\u2019s been one of the best decisions I\u2019ve ever made, and I\u2019m genuinely so glad I chose Larne Dental Centre to guide me through it.", "I\u2019m now about to begin my teeth whitening treatment, and I\u2019m really excited to see the final results! I can already tell I\u2019m going to love the outcome."]],
    ["Michael Doherty", "9 months ago", ["My journey started 3 years ago, and was completed by having 10 veneers on top then recently I decided to complete my journey have have the bottom completed and I have to say I'm delighted by the outcome, the professional work carried out by Dr Jillian and the advice and guidance that has been given to me throughout the 3 years has been second to none.", "I've never been a fan of any dentist lol", "And the fact that I travel 160mile all round journey when I visit shows how much trust that I have in Dr Jillian and her team \u2764\uFE0F", "It's no wonder they won multiple awards recently for the service and work that they deliver to there patients"]],
    ["Paricia Mcgarvey", "2 months ago", ["Dr jillian is a Magician she has completely changed me,my smile, and has given me back my confidence Thank you", "Michelle is the big personalty puts everyone at ease and is hilarious just love her. And Niamh great Hygienist with a wonderful personality. Not forgetting the dental nurses efficient,friendly and motivated. Altogether fabulous service and very friendly caring staff each and everyone of them \uD83E\uDD70\u2764\uFE0F\u2764\uFE0F"]],
    ["Gareth Stewart", "10 months ago", ["I recently attended Larne Dental Centre for dental work followed by 10 composite veneers, and I honestly couldn\u2019t be happier with the experience or the results. From the moment I walked in, the whole team made me feel so comfortable and at ease. Everything was explained clearly, and I felt listened to and cared for throughout the entire process.", "Dr. Jillian was absolutely amazing. Her professionalism, attention to detail, and calm, reassuring manner made such a difference. She took the time to make sure everything was perfect, and it really shows in the final result.", "I love my new smile , it has completely exceeded my expectations and given me so much confidence. The veneers look so natural, and I can\u2019t stop smiling. The care and skill that went into my treatment were outstanding.", "I can\u2019t recommend Larne Dental Centre and Dr. Jillian highly enough. If you\u2019re considering dental work or a smile makeover, you\u2019ll be in the best possible hands here."]],
  ];

  const GoogleG = () => (
    <svg className="rv__g" viewBox="0 0 48 48" role="img" aria-label="Google">
      <path fill="#EA4335" d="M24 9.5c3.54 0 6.71 1.22 9.21 3.6l6.85-6.85C35.9 2.38 30.47 0 24 0 14.62 0 6.51 5.38 2.56 13.22l7.98 6.19C12.43 13.72 17.74 9.5 24 9.5z" />
      <path fill="#4285F4" d="M46.98 24.55c0-1.57-.15-3.09-.38-4.55H24v9.02h12.94c-.58 2.96-2.26 5.48-4.78 7.18l7.73 6c4.51-4.18 7.09-10.36 7.09-17.65z" />
      <path fill="#FBBC05" d="M10.53 28.59c-.48-1.45-.76-2.99-.76-4.59s.27-3.14.76-4.59l-7.98-6.19C.92 16.46 0 20.12 0 24c0 3.88.92 7.54 2.56 10.78l7.97-6.19z" />
      <path fill="#34A853" d="M24 48c6.48 0 11.93-2.13 15.89-5.81l-7.73-6c-2.15 1.45-4.92 2.3-8.16 2.3-6.26 0-11.57-4.22-13.47-9.91l-7.98 6.19C6.51 42.62 14.62 48 24 48z" />
    </svg>
  );

  const ReviewCard = ({ name, when, paras, i }) => {
    const [open, setOpen] = useState(false);
    const long = paras.join(" ").length > 240;
    const id = "rv-text-" + i;
    return (
      <li className={"rv" + (open ? " is-open" : "")}>
        <div className="rv__top">
          <span className="rv__stars" role="img" aria-label="5 out of 5 stars">{[0, 1, 2, 3, 4].map((k) => <svg key={k} viewBox="0 0 24 24" aria-hidden="true"><path d="M12 2l3.1 6.3 6.9 1-5 4.9 1.2 6.8L12 17.8 5.8 21l1.2-6.8-5-4.9 6.9-1z" /></svg>)}</span>
          <GoogleG />
        </div>
        <div className={"rv__q" + (long && !open ? " is-clamped" : "")} id={id}>{paras.map((p, k) => <p key={k}>{p}</p>)}</div>
        <div className="rv__by">
          <div><p className="rv__n">{name}</p><p className="rv__w">{when}</p></div>
          {long && (
            <button type="button" className="rv__more" aria-expanded={open} aria-controls={id} onClick={() => setOpen(!open)}>
              <span className="sr-only">{open ? "Show less of " + name + "'s review" : "Read more of " + name + "'s review"}</span>
              <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" aria-hidden="true"><path d="M12 5v14M5 12h14" /></svg>
            </button>
          )}
        </div>
      </li>
    );
  };

  const Reviews = () => {
    const track = useRef(null);
    const [idx, setIdx] = useState(0);
    const [stops, setStops] = useState(1);
    const step = () => { const el = track.current; const c = el && el.querySelector(".rv"); return c ? c.offsetWidth + 24 : 1; };
    useEffect(() => {
      const el = track.current; if (!el) return;
      const m = () => setStops(Math.max(1, Math.round((el.scrollWidth - el.clientWidth) / step()) + 1));
      m(); const raf = requestAnimationFrame(m);
      const ro = typeof ResizeObserver !== "undefined" ? new ResizeObserver(m) : null;
      if (ro) { ro.observe(el); Array.from(el.children).forEach((c) => ro.observe(c)); }
      window.addEventListener("resize", m); window.addEventListener("load", m);
      if (document.fonts && document.fonts.ready) document.fonts.ready.then(m);
      return () => { cancelAnimationFrame(raf); ro && ro.disconnect(); window.removeEventListener("resize", m); window.removeEventListener("load", m); };
    }, []);
    const go = (d) => track.current && track.current.scrollBy({ left: d * step(), behavior: "smooth" });
    const onScroll = () => { const el = track.current; if (el) setIdx(Math.min(stops - 1, Math.round(el.scrollLeft / step()))); };
    return (
      <section className="revs" id="reviews" aria-labelledby="revs-h">
        <div className="revs__bg"><image-slot id="dj-reviews-bg" shape="rect" placeholder="Add a large background photo for the reviews section"></image-slot></div>
        <div className="revs__shade" aria-hidden="true"></div>
        <div className="wrap revs__inner">
          <div className="jhead">
            <div className="shead"><h2 className="h2" id="revs-h">What our patients say</h2></div>
            <div className="jctl">
              <button type="button" className="jbtn" onClick={() => go(-1)} disabled={idx === 0} aria-label="Previous reviews"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" aria-hidden="true"><path d="M15 18l-6-6 6-6" /></svg></button>
              <button type="button" className="jbtn jbtn--on" onClick={() => go(1)} disabled={idx >= stops - 1} aria-label="Next reviews"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" aria-hidden="true"><path d="M9 18l6-6-6-6" /></svg></button>
            </div>
          </div>
          <ul className="revs__track" ref={track} onScroll={onScroll} tabIndex={0} aria-label="Patient reviews, scroll sideways">
            {REVIEWS.map(([n, w, p], i) => <ReviewCard key={n} name={n} when={w} paras={p} i={i} />)}
          </ul>
        </div>
      </section>
    );
  };

  Object.assign(window, { DjIc: Ic, DjHeader: Header, DjMarquee: Marquee, DjHero: Hero, DjPackages: Packages, DjBenefits: Benefits, DjStrip: Strip, DjReviews: Reviews });
})();
