/* NEO Orthodontics - Black Friday open week: offer, treatments, finance, journey, why choose */
(function () {
  const NIcon = window.NIcon;

  const PhotoBreak = ({ src, alt, pos }) => (
    <div className="pbreak"><img src={src} alt={alt} loading="lazy" style={pos ? { objectPosition: pos } : undefined} /></div>
  );

  const Included = ({ cfg }) => {
    const items = [
      ["Up to £550 off fixed braces", "Iconix or tooth-coloured ceramic fixed braces, planned by our Specialist Orthodontist, Preet.", "", "neo/img/braces-smile.webp", "A NEO Orthodontics team member smiling with fixed braces", "center 30%"],
      ["Up to £300 off clear aligners", "Invisalign or Angel aligners, made for your teeth from a 3D scan and nearly invisible when you wear them.", "", "neo/img/aligner-box.webp", "Preet showing a teenage patient her clear aligner case", "center 35%"],
      ["Consultation with Preet, our Specialist Orthodontist", "Preet will review your records, talk through your options and plan your treatment with you.", "Usually £95, now £50", "neo/img/preet-consult.webp", "Preet, our Specialist Orthodontist, explaining treatment to a patient with a model of the teeth", "center 30%"],
      ["Free 3D scan and specialist treatment plan", "An iTero 3D scan, x-rays and a custom treatment plan designed around your smile.", "Worth £150", "neo/img/itero-scan.webp", "A NEO Orthodontics nurse taking an iTero 3D scan of a patient", "center 40%"],
      ["Free retainers", "Retainers to help keep your new smile in place once your treatment ends.", "Worth up to £240 (£120 per arch)", "neo/img/model-explain.webp", "A NEO Orthodontics team member explaining treatment to a young patient using a model", "center 30%"],
      ["Free home whitening after treatment", "Brighten your smile at home once your teeth are straight.", "Worth £399", "neo/img/reception-smile.webp", "A smiling NEO Orthodontics team member with braces at reception", "center 30%"],
      ["Free remote monitoring", "Dental Monitoring lets our team check your progress between appointments. Included with clear aligner treatment only.", "Worth £50", "neo/img/dental-monitoring.webp", "Preet reviewing a patient's Dental Monitoring progress photos on screen", "center 30%"],
    ];
    return (
      <section className="sec sec--paper" id="offer" aria-labelledby="inc-h">
        <div className="wrap">
          <div className="incx__head">
            <h2 className="incx__title" id="inc-h"><span className="incx__big">Up to <span className="incx__gold">£550 off</span></span> in a Black Friday package worth up to £1,383</h2>
            <p className="lead">Start your treatment at your consultation and everything below is included.</p>
          </div>
          <ol className="incx__list">
            {items.map(([t, d, v, img, alt, pos], i) => (
              <li className="incx__row" key={t} style={{ "--i": i }}>
                <div className="incx__copy">
                  <h3 className="h3">{t}</h3>
                  <p>{d}</p>
                  {v && <p className="incx__val">{v}</p>}
                </div>
                <div className="incx__img">{img ? <img src={img} alt={alt} loading="lazy" style={{ objectPosition: pos }} /> : <image-slot id={"neo-inc-" + i} shape="rect" placeholder={alt}></image-slot>}</div>
              </li>
            ))}
          </ol>
          <div className="cta-row"><a className="btn btn--primary" href="#book">Claim up to £1,383 savings package</a></div>
          <p className="fine">Offer terms: available on private orthodontic treatment for consultations booked and attended during open week, {cfg.openWeek} 2026, where you agree to start treatment at that appointment. The total saving on fixed braces is up to £549.50 and on clear aligners up to £299.75. Remote monitoring is included with clear aligner treatment only. All treatment is subject to clinical suitability. The offer cannot be used with any other offer or on NHS treatment.</p>
        </div>
      </section>
    );
  };

  const Treatments = () => {
    const { useState } = React;
    const [on, setOn] = useState(0);
    const tx = [
      { t: "Fixed braces", k: "Up to £550 off", img: "neo/img/teen-mirror.webp", alt: "A teenage patient checking her fixed braces in a hand mirror with her Specialist Orthodontist", pos: "center 28%",
        d: "Iconix or tooth-coloured ceramic brackets, joined by a fine wire, gently guide your teeth into place. A reliable choice for crowding, gaps and bite problems in teenagers and adults, with free bracket repairs if one breaks during treatment." },
      { t: "Clear aligners", k: "Up to £300 off", img: "neo/img/mirror-consult.webp", alt: "An adult patient looking at her smile in a mirror with her Specialist Orthodontist", pos: "center 24%",
        d: "Invisalign or Angel aligners are clear, removable trays made from a 3D scan of your teeth. A discreet choice for crowding, gaps and teeth that have moved over time, and you can take them out to eat, drink and brush." },
    ];
    return (
      <section className="sec sec--cream" id="treatments" aria-labelledby="tx-h">
        <div className="wrap">
          <div className="shead">
            <h2 className="h2" id="tx-h"><span className="hl">Fixed braces</span> or <span className="hl">clear aligners</span>?</h2>
            <p className="lead">Both are available at our West Road practice in Newcastle, and Preet will recommend the right option for you at your consultation.</p>
          </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)}>
                <img className="txp__bg" src={x.img} alt={x.alt} loading="lazy" style={{ objectPosition: x.pos }} />
                <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>
                  <p className="txp__k">{x.k}</p>
                  <hr className="rule" />
                  <p className="txp__d">{x.d}</p>
                  <a className="btn btn--secondary txp__cta" href="#book">Book my £50 consultation</a>
                </div>
              </article>
            ))}
          </div>
        </div>
      </section>
    );
  };

  const Finance = () => (
    <section className="sec sec--navy" id="finance" aria-labelledby="fin-h">
      <div className="wrap fin">
        <div className="split__copy">
          <h2 className="h2" id="fin-h">Spread the cost with <span className="hl">interest-free finance</span></h2>
          <p className="lead">Pay for your treatment in monthly instalments through Chrysalis Finance, so you can start now and spread the cost.</p>
          <ul className="ticks">
            <li><NIcon name="check" /><span>0% interest over 12 months</span></li>
            <li><NIcon name="check" /><span>No deposit needed</span></li>
            <li><NIcon name="check" /><span>Your treatment coordinator will talk you through your options when you visit</span></li>
          </ul>
          <a className="btn btn--primary" href="#book">Claim up to £550 off</a>
          <p className="fin__disc">Neo Orthodontics is an Introducer Appointed Representative of Chrysalis Finance Limited. Neo Orthodontics is a credit broker, not a lender. Chrysalis Finance Limited is authorised and regulated by the Financial Conduct Authority for credit broking and lending. Credit is subject to application, status and affordability.</p>
        </div>
        <div className="split__img fin__img"><img src="neo/img/finance-tc.webp" alt="Our treatment coordinator talking a patient through her treatment and payment options" loading="lazy" /></div>
      </div>
    </section>
  );

  const Journey = ({ cfg }) => {
    const { useRef, useState, useEffect } = React;
    const track = useRef(null);
    const [idx, setIdx] = useState(0);
    /* Snap stops are read off the real card positions (clamped to the end of
       the track), and re-read whenever the track resizes - so the count is
       right however late the layout settles, at any width. */
    const [stops, setStops] = useState([0]);
    const stopsRef = useRef([0]);
    useEffect(() => {
      const el = track.current;
      if (!el) return;
      const measure = () => {
        const max = el.scrollWidth - el.clientWidth;
        const first = el.firstElementChild ? el.firstElementChild.offsetLeft : 0;
        const pos = [];
        [...el.children].forEach((card) => {
          const x = Math.min(max, Math.max(0, card.offsetLeft - first));
          if (!pos.length || x - pos[pos.length - 1] > 4) pos.push(x);
        });
        const next = pos.length ? pos : [0];
        stopsRef.current = next;
        setStops(next);
        onScroll();
      };
      measure();
      const ro = window.ResizeObserver ? new ResizeObserver(measure) : null;
      if (ro) { ro.observe(el); [...el.children].forEach((c) => ro.observe(c)); }
      window.addEventListener('resize', measure);
      window.addEventListener('load', measure);
      return () => { if (ro) ro.disconnect(); window.removeEventListener('resize', measure); window.removeEventListener('load', measure); };
    }, []);

    /* Mouse drag between slides (touch already swipes natively). Snapping is
       paused while dragging, then the track settles on the nearest stop in
       the direction of the drag. A drag never counts as a click. */
    useEffect(() => {
      const el = track.current;
      if (!el) return;
      el.classList.add('is-draggable');
      let startX = 0, startLeft = 0, down = false, moved = false;
      const onDown = (e) => {
        if (e.pointerType !== 'mouse' || e.button !== 0) return;
        down = true; moved = false; startX = e.clientX; startLeft = el.scrollLeft;
      };
      const onMove = (e) => {
        if (!down) return;
        const dx = e.clientX - startX;
        if (!moved && Math.abs(dx) < 5) return;
        if (!moved) { moved = true; el.classList.add('is-dragging'); el.setPointerCapture(e.pointerId); }
        el.scrollLeft = startLeft - dx;
      };
      const onUp = (e) => {
        if (!down) return;
        down = false;
        if (!moved) return;
        const dx = e.clientX - startX;
        const pos = stopsRef.current;
        let target = nearest(el.scrollLeft);
        if (Math.abs(dx) > 40) {
          const from = nearest(startLeft);
          target = Math.max(0, Math.min(pos.length - 1, from + (dx < 0 ? 1 : -1) * Math.max(1, Math.round(Math.abs(dx) / (el.clientWidth / 2)))));
        }
        el.classList.remove('is-dragging');
        el.scrollTo({ left: pos[target], behavior: 'smooth' });
      };
      const onClick = (e) => { if (moved) { e.preventDefault(); e.stopPropagation(); moved = false; } };
      el.addEventListener('pointerdown', onDown);
      el.addEventListener('pointermove', onMove);
      el.addEventListener('pointerup', onUp);
      el.addEventListener('pointercancel', onUp);
      el.addEventListener('click', onClick, true);
      return () => {
        el.removeEventListener('pointerdown', onDown);
        el.removeEventListener('pointermove', onMove);
        el.removeEventListener('pointerup', onUp);
        el.removeEventListener('pointercancel', onUp);
        el.removeEventListener('click', onClick, true);
      };
    }, []);
    const steps = [
      ["Book your consultation", "Fill in the form or call us to book your visit during open week.", "neo/img/reception-arrival.webp", "A patient smiling at the NEO Orthodontics reception desk"],
      ["We'll confirm your appointment", "Our treatment coordinator will call to confirm your time and answer any questions before you come in.", "neo/img/team-phone.webp", "A NEO Orthodontics team member on the phone at reception"],
      ["See Preet, our Specialist Orthodontist", "Preet talks through your concerns, takes an iTero 3D scan and x-rays, and plans your treatment with you.", "neo/img/preet-planning.webp", "Preet talking through treatment options with a patient in the treatment room"],
      ["Agree to start and secure your offer", "Agree to start treatment at your appointment to receive your Black Friday offer.", "neo/img/tc-models.webp", "A smiling patient talking with our treatment coordinator about her brace options"],
      ["Start your treatment", "We'll fit your fixed braces or order your clear aligners.", "neo/img/patient-school-uniform.webp", "A smiling teenage patient wearing fixed braces"],
    ];
    const nearest = (left) => {
      const pos = stopsRef.current;
      let best = 0;
      pos.forEach((x, k) => { if (Math.abs(x - left) < Math.abs(pos[best] - left)) best = k; });
      return best;
    };
    const go = (d) => {
      const el = track.current; if (!el) return;
      const pos = stopsRef.current;
      const k = Math.max(0, Math.min(pos.length - 1, nearest(el.scrollLeft) + d));
      el.scrollTo({ left: pos[k], behavior: 'smooth' });
    };
    function onScroll() { const el = track.current; if (el) setIdx(nearest(el.scrollLeft)); }
    const count = stops.length;
    return (
      <section className="sec sec--paper" id="journey" aria-labelledby="j-h">
        <div className="wrap">
          <div className="incx__head jhead">
            <h2 className="incx__title" id="j-h">From your first call to your <span className="hl">first fitting</span></h2>
            <p className="lead">Five simple steps at our West Road practice in Newcastle, so you always know what comes next.</p>
          </div>
          <ol className="jtrack" ref={track} onScroll={onScroll} tabIndex={0} aria-label="Treatment journey steps, scroll sideways">
            {steps.map(([t, d, img, alt], i) => (
              <li className="jcard" key={t}>
                <div className="jcard__img">{img ? <img src={img} alt={alt} loading="lazy" /> : <image-slot id={"neo-journey-" + i} shape="rect" placeholder={alt}></image-slot>}</div>
                <div className="jcard__body"><span className="jcard__n">{String(i + 1).padStart(2, "0")}</span><h3 className="h3">{t}</h3><p>{d}</p></div>
              </li>
            ))}
          </ol>
          <div className="jctl">
            <button type="button" className="jbtn" onClick={() => go(-1)} aria-label="Previous step" disabled={idx === 0}><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)} aria-label="Next step" disabled={idx >= count - 1}><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 className="jdots" aria-hidden="true">{Array.from({ length: count }, (_, i) => <i key={i} className={i === idx ? "on" : ""}></i>)}</div>
            <span className="jcount">{String(idx + 1).padStart(2, "0")} / {String(count).padStart(2, "0")}</span>
            <a className="btn btn--primary jcta" href="#book">Book my £50 consultation</a>
          </div>
        </div>
      </section>
    );
  };

  const WhyChoose = ({ cfg }) => {
    const { useState } = React;
    const [i, setI] = useState(0);
    const items = [
      ["Over 100 years of combined experience", "An established team that has been looking after smiles across the North East since 2010.", "neo/img/team-corridor.webp", "The NEO Orthodontics team together in the practice"],
      ["Award-winning clinicians", "Our Specialist Orthodontists have been recognised with national prizes for their orthodontic work.", "neo/img/preet-smile.webp", "Preet, our award-winning Specialist Orthodontist, smiling with a patient"],
      ["Aftercare included", "Retainers, retainer reviews at 3 and 12 months and free bracket repairs are included in private treatment.", "neo/img/mirror-review.webp", "A patient smiling at her straighter teeth in a hand mirror"],
      [cfg.loc.accessTitle, cfg.loc.accessText, "neo/img/neon-sign.webp", "The neon NEO Orthodontics sign on the green plant wall at the practice"],
      ["One point of contact", "Our treatment coordinator looks after you from your first call to your first appointment.", "neo/img/tc-smile.webp", "Our treatment coordinator talking a patient through brace options"],
      ["Family-friendly care", "A welcoming practice where teenagers and adults are looked after with the same care and attention.", "neo/img/family-greenwall.webp", "Preet and a dental nurse with a young patient in the practice"],
    ];
    const n = items.length, nx = (i + 1) % n;
    const pad = (v) => String(v).padStart(2, "0");
    /* Drag or swipe the pictures sideways to change reason. */
    const drag = React.useRef(null);
    const onDown = (e) => { if (e.button !== 0) return; drag.current = { x: e.clientX, y: e.clientY, moved: false }; };
    const onMove = (e) => {
      const d = drag.current; if (!d) return;
      if (!d.moved && Math.abs(e.clientX - d.x) > 8 && Math.abs(e.clientX - d.x) > Math.abs(e.clientY - d.y)) { d.moved = true; e.currentTarget.classList.add('is-dragging'); }
    };
    const onUp = (e) => {
      const d = drag.current; drag.current = null;
      e.currentTarget.classList.remove('is-dragging');
      if (!d || !d.moved) return;
      d.swiped = true;
      const dx = e.clientX - d.x;
      if (Math.abs(dx) > 40) setI(dx < 0 ? nx : (i - 1 + n) % n);
      drag.last = Date.now();
    };
    const onClickCapture = (e) => { if (drag.last && Date.now() - drag.last < 300) { e.preventDefault(); e.stopPropagation(); } };
    return (
      <section className="sec sec--paper" id="why" aria-labelledby="why-h">
        <div className="wrap">
          <div className="whyx__head">
            <h2 className="incx__title" id="why-h">Why choose NEO in <span className="hl">{cfg.loc.area || cfg.loc.town}</span>?</h2>
            <p className="lead">The reasons patients from {cfg.loc.areas || "across the area"} choose our {cfg.loc.site} practice.</p>
          </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"><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={() => setI(nx)} aria-label="Next reason"><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>
            <div className="whyx__pics" onPointerDown={onDown} onPointerMove={onMove} onPointerUp={onUp} onPointerCancel={() => { drag.current = null; }} onClickCapture={onClickCapture}>
              <div className="whyx__pic whyx__pic--a" key={"a" + i}>{items[i][2] ? <img src={items[i][2]} alt={items[i][3]} loading="lazy" /> : <image-slot id={"neo-why-" + i} shape="rect" placeholder={items[i][3]}></image-slot>}</div>
              <button type="button" className="whyx__pic whyx__pic--b" key={"b" + nx} onClick={() => setI(nx)} aria-label={"Next: " + items[nx][0]}>{items[nx][2] ? <img src={items[nx][2]} alt="" loading="lazy" /> : <image-slot id={"neo-why-" + nx} shape="rect" placeholder={items[nx][3]}></image-slot>}</button>
            </div>
          </div>
        </div>
      </section>
    );
  };

  Object.assign(window, { NeoPhotoBreak: PhotoBreak, NeoIncluded: Included, NeoTreatments: Treatments, NeoFinance: Finance, NeoJourney: Journey, NeoWhy: WhyChoose });
})();
