/* Dr Jillian - Black Friday open day: journey, Dr Jillian, why choose, prices, how it works, FAQs, final CTA, find us, footer, disclosure, app */
(function () {
  const { useState, useEffect, useRef } = React;
  const Ic = window.DjIc;
  const W = window;
  const pad = (v) => String(v).padStart(2, "0");

  const CFG = {
    phone: "028 2826 0418", tel: "+442828260418",
    dateLong: "Friday 27th November, 8am to 4pm", dateShort: "Friday 27th November",
    countdownEnd: "2026-11-27T08:00:00Z",
    address: "9-11 Glenarm Road, Larne, Co. Antrim, BT40 1BN",
    mapsQ: "Dr Jillian Dental Care and Aesthetics, 9-11 Glenarm Road, Larne BT40 1BN",
    privacy: "https://drjillian.co.uk/privacy-policy/",
    thanks: "thank-you.html",
  };

  const Slot = ({ id, label }) => <image-slot id={id} shape="rect" placeholder={label}></image-slot>;

  const Journey = () => {
    const track = useRef(null);
    const [idx, setIdx] = useState(0);
    const [stops, setStops] = useState(1);
    const steps = [
      ["Request your spot using the form - it takes less than a minute.", "dj/img/reception.jpg", "A patient being welcomed at the stained glass reception desk"],
      ["We call you back to choose your time on Friday 27th November and secure your place.", "dj/img/team-door.jpg", "The Dr Jillian team laughing together at the practice door"],
      ["Your consultation with Dr Jillian - 30 minutes of photos, X-rays, screening and an honest conversation about what you would like.", "dj/img/clinical-photos.jpg", "A patient smiling while clinical photos are taken in the treatment room"],
      ["Time with Michelle, our treatment coordinator - she talks you through your options, your Black Friday savings and how to spread the cost.", "dj/img/michelle-consult.jpg", "A patient talking through her options with the team in the navy panelled room"],
      ["Start your treatment whenever you are ready, with your £63 coming off the cost if you go ahead.", "dj/img/patient-smiling-outdoors.jpg", "A young woman smiling outdoors", "40% 30%"],
    ];
    const step = () => { const el = track.current; const c = el && el.querySelector(".jcard"); 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="sec sec--tint" id="journey" aria-labelledby="j-h">
        <div className="wrap">
          <div className="jhead">
            <div className="shead">
              <h2 className="h2" id="j-h">What happens on our exclusive Black Friday open day?</h2>
              <p className="lead">Five simple steps from requesting your spot to starting treatment.</p>
            </div>
            <div className="jctl">
              <button type="button" className="jbtn" onClick={() => go(-1)} disabled={idx === 0} aria-label="Previous step"><Ic n="arrowL" /></button>
              <button type="button" className="jbtn jbtn--on" onClick={() => go(1)} disabled={idx >= stops - 1} aria-label="Next step"><Ic n="arrowR" /></button>
              <span className="jcount">{pad(idx + 1)} / {pad(stops)}</span>
            </div>
          </div>
          <ol className="jtrack" ref={track} onScroll={onScroll} tabIndex={0} aria-label="Open day steps, scroll sideways">
            {steps.map(([d, img, alt, pos], i) => (
              <li className="jcard" key={i}>
                <div className="jcard__img">{img ? <img src={img} alt={alt} loading="lazy" style={pos ? { objectPosition: pos } : undefined} /> : <Slot id={"dj-journey-" + i} label={alt} />}</div>
                <div className="jcard__body"><span className="jcard__n">{pad(i + 1)}</span><p>{d}</p></div>
              </li>
            ))}
          </ol>
        </div>
      </section>
    );
  };

  const MeetDrJillian = () => (
    <section className="sec" id="dr-jillian" aria-labelledby="dr-h">
      <div className="wrap split">
        <div className="split__img drj__img"><img src="dj/img/dr-jillian-chair.jpg" alt="Dr Jillian smiling in her treatment room" loading="lazy" /><p className="drj__gdc">Dr Jillian Saulters<span>GDC No: 83580</span></p></div>
        <div className="split__copy">
          <h2 className="h2" id="dr-h">Meet Dr Jillian, the dentist behind your new smile</h2>
          <p>Dr Jillian is our clinical lead, with a certificate in restorative dentistry and a quiet focus on results that look like you, only better. She leads every Black Friday consultation personally, so the person you meet is the person who plans your smile.</p>
          <p>She has spent years helping nervous patients feel calm in the chair. If dental visits make you anxious, tell us when we call - we will take things at your pace, and oral sedation is available if it would help.</p>
          <a className="btn" href="#book">Request your spot</a>
        </div>
      </div>
    </section>
  );

  const Why = () => {
    const [i, setI] = useState(0);
    const items = [
      ["Natural results, always.", "We would rather you looked rested and confident than obviously \u201Cdone\u201D.", null, "Add a photo of a natural smile result"],
      ["Fully private, never rushed.", "Your consultation is a proper conversation, not a quick look.", "dj/img/waiting-room.jpg", "A quiet corner of the waiting room with velvet chairs and a lamp"],
      ["A dental practice since the 1960s.", "Our Glenarm Road home still has its original stained glass windows.", "dj/img/glenarm-road-plaque.jpg", "The practice plaque beside the original stained glass door on Glenarm Road"],
      ["Easy to reach.", "Free roadside parking, five minutes' walk from Larne train and bus station and the town centre.", null, "Add a photo of the outside of the practice on Glenarm Road"],
      ["Accessible and inclusive.", "A ground floor surgery, an accessible ramp, and a women-led team where everyone is welcome.", "dj/img/team-door.jpg", "The Dr Jillian team laughing together at the practice door"],
    ];
    const n = items.length, nx = (i + 1) % n;
    return (
      <section className="sec sec--tint" id="why" aria-labelledby="why-h">
        <div className="wrap">
          <div className="shead" style={{ textAlign: "left", alignItems: "flex-start", margin: "0 0 var(--s-12)" }}><h2 className="h2" id="why-h">Why you will feel at home with us in Larne</h2></div>
          <div className="whyx">
            <div className="whyx__copy" aria-live="polite">
              <span className="whyx__n">{pad(i + 1)}</span>
              <h3 className="whyx__t">{items[i][0]}</h3>
              <p>{items[i][1]}</p>
              <div className="jctl whyx__ctl">
                <div className="jdots" aria-hidden="true">{items.map((_, k) => <i key={k} className={k === i ? "on" : ""}></i>)}</div>
                <span className="jcount">{pad(i + 1)} / {pad(n)}</span>
                <button type="button" className="jbtn" onClick={() => setI((i - 1 + n) % n)} aria-label="Previous reason"><Ic n="arrowL" /></button>
                <button type="button" className="jbtn jbtn--on" onClick={() => setI(nx)} aria-label="Next reason"><Ic n="arrowR" /></button>
              </div>
            </div>
            <div className="whyx__pics whyx__pics--one">
              <div className="whyx__pic whyx__pic--a"><img src="dj/img/glenarm-road-plaque.jpg" alt="The practice plaque beside the original stained glass door on Glenarm Road" loading="lazy" /></div>
            </div>
          </div>
        </div>
      </section>
    );
  };

  const Table = ({ head, rows, bfCol }) => (
    <table className="ptable">
      <thead><tr>{head.map((h, k) => <th key={k} scope="col">{h}</th>)}</tr></thead>
      <tbody>{rows.map((r, k) => <tr key={k}>{r.map((c, j) => <td key={j} className={j === bfCol ? "bf" : ""}>{c}</td>)}</tr>)}</tbody>
    </table>
  );

  const Prices = () => (
    <section className="sec prx" id="prices" aria-labelledby="pr-h">
      <img className="prx__bg" src="dj/img/waiting-room.jpg" alt="" loading="lazy" />
      <div className="wrap">
        <div className="shead"><h2 className="h2" id="pr-h">Your Black Friday savings, in full</h2></div>
        <div className="prices">
          <div className="pcard"><h3 className="h3">Your consultation savings</h3>
            <Table head={["Consultation", "Normally", "Black Friday"]} bfCol={2} rows={[["Smile consultation", "£126", "£63"], ["Invisalign consultation", "£252", "£63"]]} />
          </div>
          <div className="pcard"><h3 className="h3">Invisalign savings package</h3>
            <p>Your Invisalign savings package is worth up to £1,308.43, including £200 off your treatment if you self-fund. If you choose finance, you still receive £100 off, with a savings package worth £1,208.43.</p>
          </div>
          <div className="pcard"><h3 className="h3">Full smile makeover savings</h3>
            <Table head={["Package", "Normally", "Black Friday", "You save"]} bfCol={2} rows={[["20 composite veneers", "£7,309.09", "£5,998.79", "£1,310.30"], ["10 composite veneers", "£4,230.88", "£3,426.65", "£804.23"]]} />
          </div>
          <div className="pcard"><h3 className="h3">Teeth whitening savings</h3>
            <Table head={["System", "Normally", "Black Friday", "You save"]} bfCol={2} rows={[["Enlighten whitening", "£520", "£400", "£120"], ["Bespoke whitening", "£356.56", "£178.28", "£178.28 (half price)"]]} />
          </div>
        </div>
        <div className="pnotes">
          <p>When we call you back, we take your £63 as a deposit to secure your slot. If you go ahead with treatment, it comes off the cost.</p>
          <p>Interest-free finance is available, so you can spread the cost of your new smile. Michelle will talk you through your options at your consultation.</p>
          <a className="btn" href="#book">Request your spot</a>
        </div>
      </div>
    </section>
  );

  const How = () => {
    const [on, setOn] = useState(0);
    const tx = [
      { t: "Invisalign", img: "dj/img/invisalign-aligner-model.jpg", alt: "A clear Invisalign aligner held beside a model of teeth", d: "We scan your teeth with our Trios 3D scanner - no impression trays - and show you a digital simulation of how your teeth will move and where they will finish. Once you are happy, your aligners are fitted and we see you around every four weeks to check progress. At the end, any small attachments are removed and your retainers are fitted to hold your new smile in place." },
      { t: "Full smile makeover", img: "dj/img/gum-health.jpg", alt: "Niamh, our dental therapist, carrying out a gum health appointment", d: "It starts with a gum health assessment with Niamh, so your new smile is built on healthy foundations. Next comes whitening, so your veneers can be matched to your brighter shade. Dr Jillian then shapes tooth-coloured composite onto your teeth by hand, building a smile that suits your face. You leave with a biteguard to protect it, and we see you again for a review with clinical photos." },
      { t: "Teeth whitening", img: "dj/img/whitening-shade-guide.jpg", alt: "A tooth shade guide held beside a bright, natural smile", d: "Dr Jillian first checks your teeth and gums are healthy enough to whiten. Bespoke whitening uses custom-made trays you wear at home, at your own pace. Enlighten is our premium system, combining home whitening with a final in-practice session for a guaranteed B1 shade." },
    ];
    return (
      <section className="sec sec--tint" id="how" aria-labelledby="how-h">
        <div className="wrap">
          <div className="shead"><h2 className="h2" id="how-h">How your new smile comes together</h2></div>
          <div className="txp">
            {tx.map((x, i) => (
              <article key={x.t} className={"txp__panel" + (on === i ? " is-on" : "")} onMouseEnter={() => setOn(i)} onFocus={() => setOn(i)} onClick={() => setOn(i)}>
                <div className="txp__bg">{x.img ? <img src={x.img} alt={x.alt} loading="lazy" /> : <Slot id={"dj-how-" + i} label={x.alt} />}</div>
                <div className="txp__shade"></div>
                <span className="txp__vert" aria-hidden="true">{x.t}</span>
                <div className="txp__copy">
                  <h3 className="txp__t">{x.t}</h3>
                  <hr className="txp__rule" />
                  <p className="txp__d">{x.d}</p>
                </div>
              </article>
            ))}
          </div>
        </div>
      </section>
    );
  };

  const Faq = () => {
    const items = [
      ["Do I need to know which treatment I want?", "Not at all. Just request your spot and Dr Jillian will talk you through what would suit you at your consultation."],
      ["Why is the Invisalign consultation £63 when it is normally £252?", "For Black Friday, your £63 consultation replaces our usual £252 orthodontic smile assessment - a saving of £189 before you have even started."],
      ["Will my composite veneers look natural?", "That is the whole aim. Each one is shaped by hand and shade matched to your teeth, so the result looks like your own smile at its best."],
      ["Can I spread the cost?", "Yes. Interest-free finance is available. If you choose finance for Invisalign, you still receive £100 off and the rest of your savings package."],
      ["I get nervous at the dentist. Can you help?", "Yes. Let us know when we call and we will plan around you. We offer the Calm Kit, which lets you signal if you need a pause, and oral sedation is available for an additional £25."],
      ["What if I can't make Friday 27th November?", "The Black Friday savings are tied to the open day itself. Request your spot and mention it when we call - we will let you know what we can do."],
    ];
    return (
      <section className="sec" id="faq" aria-labelledby="faq-h">
        <div className="wrap">
          <div className="shead"><h2 className="h2" id="faq-h">Your Black Friday open day questions, answered</h2></div>
          <div className="faq">{items.map(([q, a], i) => <details key={q} open={i === 0}><summary>{q}<span className="faq__ic" aria-hidden="true"><Ic n="plus" /></span></summary><p>{a}</p></details>)}</div>
        </div>
      </section>
    );
  };

  const Final = () => (
    <section className="sec sec--deep final" aria-labelledby="final-h">
      <img className="final__mark" src="dj/img/mark-white.png" alt="" />
      <div className="wrap">
        <h2 className="h2" id="final-h">Only 14 slots on Friday 27th November - will one be yours?</h2>
        <p className="lead">This is the year you stop waiting for the right time to sort your smile. Request your spot for Friday 27th November and we will call you back to secure it.</p>
        <a className="btn btn--light" href="#book">Request your spot</a>
      </div>
    </section>
  );

  const FindUs = ({ cfg }) => {
    const q = encodeURIComponent(cfg.mapsQ);
    return (
      <section className="sec sec--tint" id="find-us" aria-labelledby="find-h">
        <div className="wrap find">
          <div className="find__map"><iframe title="Map showing Dr Jillian Dental Care and Aesthetics on Glenarm Road, Larne" loading="lazy" src={"https://www.google.com/maps?q=" + q + "&output=embed"}></iframe></div>
          <div className="find__info">
            <h2 className="h2" id="find-h">Find us on Glenarm Road</h2>
            <div className="find__list">
              <div className="find__blk"><h3 className="h3">Dr Jillian Dental Care &amp; Aesthetics</h3><p>{cfg.address}</p></div>
              <div className="find__blk"><h3 className="h3">Phone</h3><p><a href={"tel:" + cfg.tel}>{cfg.phone}</a></p></div>
              <div className="find__blk"><h3 className="h3">Opening hours</h3><p>Mon, Tue, Thurs and Fri, 8am to 4pm</p></div>
              <div className="find__blk"><h3 className="h3">Getting here</h3><p>Free roadside parking, five minutes' walk from Larne train and bus station and the town centre.</p></div>
            </div>
            <div className="find__btns">
              <a className="btn" href={"https://www.google.com/maps/search/?api=1&query=" + q} target="_blank" rel="noopener">Open in Google Maps</a>
              <a className="btn btn--line" href={"https://maps.apple.com/?q=" + q} target="_blank" rel="noopener">Open in Apple Maps</a>
            </div>
          </div>
        </div>
      </section>
    );
  };

  const Footer = ({ cfg, cta }) => (
    <React.Fragment>
      <footer className="ftr">
        <div className="wrap">
          <div className="ftr__top">
            <a className="ftr__logo" href="#top" aria-label="Back to top"><img src="dj/img/logo-white.png" alt="Dr Jillian Dental Care and Aesthetics" /></a>
            <div className="ftr__ctas">
              <a className="btn btn--light" href={cta ? cta[1] : "#book"}>{cta ? cta[0] : "Request your spot"}</a>
              <a className="btn btn--line" style={{ color: "var(--on-deep)", borderColor: "var(--rule-on-deep)" }} href={"tel:" + cfg.tel}><Ic n="phone" />Call {cfg.phone}</a>
            </div>
          </div>
          <nav className="ftr__legal" aria-label="Legal"><a href={cfg.privacy} target="_blank" rel="noopener">Privacy policy</a></nav>
          <div className="ftr__base">
            <span>© 2026 Dr Jillian Dental Care &amp; Aesthetics. {cfg.address}</span>
            <span>Website developed by <a href="https://www.xceleratordental.com/" target="_blank" rel="noopener">Xcelerator Dental</a></span>
          </div>
        </div>
      </footer>
      <section className="disc" aria-label="Finance information">
        <div className="wrap">
          <p>Dr Jillian Dental Care &amp; Aesthetics, 9-11 Glenarm Road, Larne BT40 1BN Telephone 028 2744 1350. Jillian M Saulters Ltd trading as Dr Jillian Dental Care &amp; Aesthetics is a credit broker not a lender and is authorised and regulated by the Financial Conduct Authority, 811539. Registered in Northern Ireland NI604604. Registered Address: 9-11 Glenarm Road, Larne BT40 1BN.</p>
          <p>Medenta Finance Limited, authorised and regulated by the Financial Conduct Authority No: 715523. Registered in Scotland, No: SC276679. Registered address: 50 Lothian Road, Festival Square, Edinburgh, EH3 9WJ. Tel: 01691684175. Medenta act as a credit broker, not a lender and will introduce practices to V12 Retail Finance Limited for which Medenta will receive an introduction commission from Secure Trust Bank plc, V12 Retail Finance Limited’s parent company.</p>
          <p>V12 Retail Finance Limited is authorised and regulated by the Financial Conduct Authority. Registration number:679653. Registered office: Yorke House, Arleston Way, Solihull, B90 4LH. Correspondence address: 25-26 Neptune Court, Vanguard Way, Cardiff, CF24 5PJ. V12 Retail Finance Limited act as a credit broker, not a lender, and only offers credit products from Secure Trust Bank. Secure Trust Bank PLC trading as V12 Retail Finance is authorised by the Prudential Regulation Authority and regulated by the Financial Conduct Authority and the Prudential Regulation Authority. Registration number: 204550. Registered office: Yorke House, Arleston Way, Solihull, B90 4LH.</p>
          <p>Terms and conditions apply. Written quotations are available on request from Secure Trust Bank PLC. Credit facilities are subject to status and affordability checks and only available to UK residents over the age of 18. Secure Trust Bank PLC reserves the right to decline any application. APR and repayment details are correct at time of publish.</p>
        </div>
      </section>
    </React.Fragment>
  );

  const MobileBar = ({ cfg }) => {
    const [show, setShow] = useState(false);
    useEffect(() => {
      document.body.classList.add("has-mbar");
      const f = () => { const r = document.getElementById("book"); setShow(r ? r.getBoundingClientRect().bottom < 0 : window.scrollY > 600); };
      f(); window.addEventListener("scroll", f, { passive: true }); return () => window.removeEventListener("scroll", f);
    }, []);
    return (
      <div className={"mbar" + (show ? " show" : "")} aria-hidden={!show}>
        <a className="mbar__call" href={"tel:" + cfg.tel} aria-label={"Call " + cfg.phone} tabIndex={show ? 0 : -1}><Ic n="phone" /></a>
        <a className="btn" href="#book" tabIndex={show ? 0 : -1}>Request your spot</a>
      </div>
    );
  };

  function App() {
    const cfg = CFG;
    return (
      <React.Fragment>
        <W.DjHeader cfg={cfg} />
        <main>
          <W.DjMarquee cfg={cfg} />
          <W.DjHero cfg={cfg} />
          <W.DjPackages />
          <W.DjStrip />
          <W.DjReviews />
          <W.DjBenefits />
          <How />
          <Journey />
          <MeetDrJillian />
          <Why />
          <Prices />
          <Faq />
          <Final />
          <FindUs cfg={cfg} />
        </main>
        <Footer cfg={cfg} />
        <MobileBar cfg={cfg} />
      </React.Fragment>
    );
  }
  Object.assign(window, { DjCFG: CFG, DjFindUs: FindUs, DjFooter: Footer });
  if (!window.DJ_SKIP_APP) ReactDOM.createRoot(document.getElementById("root")).render(<App />);
})();
