/* ==========================================================================
   Augusta Pediatric Associates — the services arc

   Puts the motion library's Arc Card Carousel (C27, a measured replica of the
   Framer Marketplace component) on the services page, carrying the practice's
   eight services.

   `arccards.js` is the library file, copied in **verbatim** and not edited:
   its measured law — a 1576px wheel, 15deg a card, the
   `clamp((60 - |a|) / 20, 0, 1)` fade, 0.0718deg per px of drag — is the whole
   point of the component, and anything changed there stops being a replica.
   Everything specific to this site lives here and in services-arc.css.

   Two things are added on top of it, both deliberate:

     1  a slow drift. The reference has NO ambient motion at all — it moves
        only when dragged. Brayden asked for it to move on its own, slower
        than the service cards it replaces.
     2  the card skin and the links. The reference card is a photograph with a
        title and a number under it; the practice's old cards put the service
        name over the image and reveal the description on hover, and that is
        what people here recognise.
   ========================================================================== */

(function () {
  'use strict';

  /* The cards these replace ran at 31.5px/s over a 336px step — one card every
     10.7s. This is 15deg a card at 0.8deg/s: one card every 18.8s, comfortably
     slower, which is what was asked for. */
  var DRIFT = 0.8;          /* degrees per second */

  /* The old cards did not pause, and that was right for them: you cannot grab
     a thing that dies as your cursor approaches it. These are different — the
     description only appears on hover, so the card has to hold still long
     enough to read. */
  var PAUSE_ON_HOVER = true;

  /* Verbatim from the cards being replaced: the practice's own words, their
     own photographs, their own destinations. `Ear Piercing` has no description
     on the old card either, and its link is the one the capture carries. */
  var SERVICES = [
    { title: 'Sick Child Care',
      href: '/service/sick-child/',
      art: '/wp-content/uploads/2020/10/GettyImages-1190214200-min-scaled.jpg',
      desc: 'When you are concerned about your child’s health, we are concerned. At APA, we try our best to see every child when he or she is sick on the same day you call our office.' },

    { title: 'Newborn Baby Checkup',
      href: '/service/new-baby-checkup/',
      art: '/wp-content/uploads/2020/10/GettyImages-1152209563-min-scaled.jpg',
      desc: 'Newborns will be seen and cared for by the neonatologists or hospital assigned pediatrician while in the nursery and we will welcome you in the office for your first visit 1-3 days after you take your baby home.' },

    { title: 'Well Checks',
      href: '/service/well-checks/',
      art: '/wp-content/uploads/2020/10/GettyImages-1159650216-min-scaled.jpg',
      desc: 'We strive to provide excellent preventive care for children, to include infant checkups, immunizations, childhood screenings, baseline lab work, and sports physicals.' },

    { title: 'Immunizations',
      href: '/service/immunizations/',
      art: '/wp-content/uploads/2020/10/GettyImages-1205239076-min.jpg',
      desc: 'Childhood immunizations are one of the greatest medical blessings our children have, and represent one of the greatest achievements of Western medicine.' },

    { title: 'Lab Testing',
      href: '/service/lab-testing/',
      art: '/wp-content/uploads/2025/11/woman-preparing-tools-for-work-in-the-laboratory-2024-10-21-20-31-05-utc-scaled.jpg',
      desc: 'In keeping with our desire to provide comprehensive care for your child, we offer as many laboratory services as possible right in our own office, including most routine lab work.' },

    { title: 'In-Office Procedures',
      href: '/service/in-office-procedures/',
      art: '/wp-content/uploads/2025/11/baby4.jpg',
      desc: 'We are equipped in office to provide many procedures for sick children, which can often times eliminate the need to send your children to Emergency Departments for care.' },

    { title: 'Lactation Consultation',
      href: '/service/lactation-consultation-services/',
      art: '/wp-content/uploads/2020/10/GettyImages-1173180630-min-scaled.jpg',
      desc: 'Breastfeeding can provide so many great benefits to both baby &amp; mom! Here at Augusta Pediatric Associates, our lactation consultation are dedicated to helping you through this journey &amp; answering any questions or concerns you may have about your breastfeeding journey.' },

    { title: 'Ear Piercing',
      href: '/service/earpiercing',
      art: '/wp-content/uploads/2026/03/apa-ear-piercing.jpg',
      desc: '' }
  ];

  function skin(arc, root) {
    var cards = root.querySelectorAll('.acc__card');

    for (var i = 0; i < cards.length; i++) {
      var s = SERVICES[i];
      var card = cards[i];
      var shot = card.querySelector('.acc__shot');
      var meta = card.querySelector('.acc__meta');

      /* The component's own meta row is a title and a number under the
         picture. The practice's card puts the name ON the picture and keeps
         the description behind a hover, so the row goes and the label moves
         inside the shot. */
      if (meta) meta.parentNode.removeChild(meta);

      var label = document.createElement('div');
      label.className = 'apa-svc-label';
      label.innerHTML =
        '<p class="apa-svc-name">' + s.title + '</p>' +
        '<p class="apa-svc-kind">Services</p>' +
        (s.desc ? '<p class="apa-svc-desc">' + s.desc + '</p>' : '');
      shot.appendChild(label);

      /* A link over the whole card, as the old ones had. The drag guard is
         below — without it, letting go of a spin lands on a service page. */
      var a = document.createElement('a');
      a.className = 'apa-svc-link';
      a.href = s.href;
      a.setAttribute('aria-label', s.title);
      shot.appendChild(a);
    }
  }

  /* The component follows the pointer exactly and never snaps, so a drag ends
     with the pointer still over a card and the browser will happily call that
     a click. Anything past a few pixels is a spin, not a visit. */
  function guardClicks(root) {
    var downX = 0, downY = 0;

    root.addEventListener('pointerdown', function (e) {
      downX = e.clientX;
      downY = e.clientY;
    }, true);

    root.addEventListener('click', function (e) {
      var dx = Math.abs(e.clientX - downX);
      var dy = Math.abs(e.clientY - downY);
      if (dx > 4 || dy > 4) {
        e.preventDefault();
        e.stopPropagation();
      }
    }, true);
  }

  /* The drift. The reference has none, so this is ours entirely: one frame's
     worth of degrees added to the wheel and handed back to the component's own
     `layout()`, which keeps the measured geometry as the only thing deciding
     where a card sits. */
  function drift(arc, root) {
    var last = 0, raf = 0, held = false;

    function frame(t) {
      var dt = last ? Math.min(t - last, 64) : 16.7;   /* clamp tab-switch spikes */
      last = t;

      if (!held && !root.classList.contains('is-dragging')) {
        arc.angle -= DRIFT * dt / 1000;
        arc.layout();
      }
      raf = requestAnimationFrame(frame);
    }

    if (PAUSE_ON_HOVER) {
      root.addEventListener('pointerenter', function () { held = true; });
      root.addEventListener('pointerleave', function () { held = false; });
    }

    /* A wheel that turns while nobody is looking is just battery. */
    document.addEventListener('visibilitychange', function () {
      last = 0;
    });

    raf = requestAnimationFrame(frame);
    return function stop() { cancelAnimationFrame(raf); };
  }

  function boot() {
    var root = document.getElementById('apa-service-arc');
    if (!root || typeof ArcCards === 'undefined') return;

    var arc = new ArcCards(root, {
      cards: SERVICES.map(function (s) { return { art: s.art, title: s.title }; })
    });

    skin(arc, root);
    guardClicks(root);

    if (!matchMedia('(prefers-reduced-motion: reduce)').matches) drift(arc, root);

    root.classList.add('is-ready');
  }

  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', boot);
  } else {
    boot();
  }
})();
