(function () {
const { Button, Input, Textarea, Switch, Icon } = window.CarterSCritterCareDesignSystem_68e3fd;
const { useState } = React;
const CC = window.CC;
const Paw = window.CCPaw;

/* Selectable services for the picker. Labels + prices are canonical
   (they match Home cards, the Services page, and the footer). */
const PICK_SERVICES = [
  { key: 'dog-walking',   doodle: 'DogWalk',   color: 'peach',  title: 'Dog walking',        price: '$40', unit: '/ walk'  },
  { key: 'drop-in',       doodle: 'DropIn',    color: 'mint',   title: 'Drop-in visits',     price: '$30', unit: '/ visit' },
  { key: 'overnight',     doodle: 'Overnight', color: 'sky',    title: 'Overnight stays',    price: '$80', unit: '/ night' },
  { key: 'house-care',    doodle: 'HouseCare', color: 'butter', title: 'House & plant care', price: '$25', unit: '/ visit' },
  { key: 'not-sure',      doodle: null,        color: 'cream',  title: 'Other / Not sure yet', price: null, unit: null     },
];

/* Map a Services-page row title to a picker key, so a per-service CTA can
   preselect the right chip without touching the router contract. */
const SERVICE_KEY_BY_TITLE = {
  'Dog walking': 'dog-walking',
  'Drop-in visits': 'drop-in',
  'Overnight stays': 'overnight',
  'House & plant care': 'house-care',
};
window.CCServiceKeyByTitle = SERVICE_KEY_BY_TITLE;

/* ──────────────────────────────────────────────────────────────
   Whatcom County, WA service-area check.
   Incorporated cities/towns + CDPs + unincorporated communities +
   island/reservation communities + common Bellingham neighborhoods,
   so a real local is never wrongly turned away. An exact-match gate
   plus a few strong, unambiguous names that tolerate a directional
   prefix ("north bellingham", "bellingham wa").
   ────────────────────────────────────────────────────────────── */
const WHATCOM_EXACT = new Set([
  'whatcom', 'whatcom county',
  'bellingham', 'lynden', 'ferndale', 'blaine', 'everson', 'nooksack', 'sumas',
  'birch bay', 'birch bay village', 'custer', 'deming', 'geneva', 'kendall',
  'maple falls', 'marietta', 'alderwood', 'marietta alderwood', 'peaceful valley',
  'point roberts', 'sudden valley', 'glacier', 'acme', 'wickersham', 'van zandt',
  'welcome', 'saxon', 'clipper', 'nugents corner', 'laurel', 'lawrence', 'goshen',
  'lummi island', 'lummi', 'gooseberry point', 'sandy point', 'sandy point shores',
  'semiahmoo', 'cherry point', 'eliza island', 'neptune beach', 'agate', 'lake whatcom',
  'mount baker', 'mt baker',
  // Bellingham neighborhoods
  'fairhaven', 'barkley', 'sunnyland', 'columbia', 'silver beach', 'edgemoor', 'sehome',
  'happy valley', 'york', 'alabama hill', 'cordata', 'irongate', 'king mountain',
  'lettered streets', 'downtown', 'south hill', 'samish', 'whatcom falls', 'puget',
  'roosevelt', 'birchwood', 'meridian', 'guide meridian', 'cornwall', 'squalicum',
]);
const WHATCOM_STRONG = [
  'bellingham', 'ferndale', 'lynden', 'blaine', 'everson', 'sumas', 'nooksack',
  'birch bay', 'point roberts', 'maple falls', 'sudden valley', 'lummi island',
  'lummi', 'deming', 'custer', 'kendall', 'glacier', 'semiahmoo', 'cherry point',
  'wickersham', 'acme', 'van zandt', 'nugents corner',
];
function normalizeTown(raw) {
  let s = String(raw || '').toLowerCase().trim();
  s = s.split(',')[0];                                  // drop ", WA 98225"
  s = s.replace(/[0-9]/g, ' ');                          // strip zip / digits
  s = s.replace(/\b(wa|washington|usa|us|united states|county)\b/g, ' ');
  s = s.replace(/^(city of|town of|the)\s+/, '');
  s = s.replace(/[^a-z\s]/g, ' ').replace(/\s+/g, ' ').trim();
  return s;
}
function inServiceArea(raw) {
  const n = normalizeTown(raw);
  if (!n) return false;
  if (WHATCOM_EXACT.has(n)) return true;
  return WHATCOM_STRONG.some((name) =>
    new RegExp('\\b' + name.replace(/ /g, '\\s+') + '\\b').test(n));
}

/* The validated form POSTs all fields here as JSON; the backend (n8n) handles
   storage + notification email. */
const WEBHOOK_URL = 'https://kitterman.app.n8n.cloud/webhook/ccc-web-form';

const EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
const onlyDigits = (p) => String(p).replace(/\D/g, '');
function formatPhone(raw) {
  const d = onlyDigits(raw).slice(0, 10);
  if (!d) return '';
  if (d.length < 4) return '(' + d;
  if (d.length < 7) return '(' + d.slice(0, 3) + ') ' + d.slice(3);
  return '(' + d.slice(0, 3) + ') ' + d.slice(3, 6) + '-' + d.slice(6);
}
const TODAY = (function () {
  try { return new Date().toISOString().slice(0, 10); } catch (e) { return ''; }
})();

/* Display-cased suggestions for the Town field's inline autocomplete.
   Incorporated cities/communities first, then Bellingham neighborhoods. */
const TOWN_SUGGESTIONS = [
  'Bellingham', 'Ferndale', 'Lynden', 'Blaine', 'Everson', 'Nooksack', 'Sumas',
  'Birch Bay', 'Birch Bay Village', 'Custer', 'Deming', 'Geneva', 'Kendall',
  'Maple Falls', 'Marietta', 'Peaceful Valley', 'Point Roberts', 'Sudden Valley',
  'Glacier', 'Acme', 'Wickersham', 'Van Zandt', 'Welcome', 'Saxon', 'Clipper',
  'Nugents Corner', 'Laurel', 'Lawrence', 'Goshen', 'Lummi Island', 'Gooseberry Point',
  'Sandy Point', 'Semiahmoo', 'Cherry Point', 'Eliza Island', 'Lake Whatcom', 'Mount Baker',
  'Fairhaven', 'Barkley', 'Sunnyland', 'Columbia', 'Silver Beach', 'Edgemoor', 'Sehome',
  'Happy Valley', 'Alabama Hill', 'Cordata', 'Irongate', 'King Mountain', 'Lettered Streets',
  'South Hill', 'Samish', 'Whatcom Falls', 'Roosevelt', 'Birchwood', 'Cornwall', 'Squalicum',
];
function townSuggestion(value) {
  if (!value) return '';
  const lower = value.toLowerCase();
  for (let i = 0; i < TOWN_SUGGESTIONS.length; i++) {
    const t = TOWN_SUGGESTIONS[i];
    if (t.length > value.length && t.toLowerCase().slice(0, lower.length) === lower) return t;
  }
  return '';
}

/* Town input with inline "ghost text" autocomplete: the remaining letters of
   the best-matching Whatcom County place show in grey after what you've typed;
   Tab (or Right Arrow at the end) accepts it. Free text is still allowed. */
function TownField({ value, onChange, onBlur, error }) {
  const suggestion = townSuggestion(value);
  const suffix = suggestion ? suggestion.slice(value.length) : '';
  const accept = () => { if (suggestion) onChange(suggestion); };
  const onKeyDown = (e) => {
    if (!suggestion) return;
    if (e.key === 'Tab') { e.preventDefault(); accept(); }
    else if (e.key === 'ArrowRight') {
      const el = e.target;
      if (el.selectionStart === el.value.length && el.selectionStart === el.selectionEnd) { e.preventDefault(); accept(); }
    }
  };
  return (
    <div className="cc-field">
      <label className="cc-field__label" htmlFor="cc-town">Town<span className="cc-field__req"> *</span></label>
      <div className="cc-input__wrap cc-input__wrap--icon townac">
        <span className="cc-input__icon"><Icon name="map-pin" /></span>
        <div className="townac__ghost" aria-hidden="true">
          <span className="townac__typed">{value}</span><span className="townac__suffix">{suffix}</span>
        </div>
        <input
          id="cc-town"
          className={'cc-input townac__input' + (error ? ' cc-input--error' : '')}
          type="text"
          placeholder="Ferndale"
          autoComplete="off"
          autoCorrect="off"
          spellCheck={false}
          aria-autocomplete="inline"
          aria-invalid={!!error}
          data-err="town"
          value={value}
          onChange={(e) => onChange(e.target.value)}
          onBlur={onBlur}
          onKeyDown={onKeyDown}
        />
      </div>
      {error
        ? <span className="cc-field__error">{error}</span>
        : <span className="cc-field__hint">Anywhere in Whatcom County. Press Tab to autocomplete.</span>}
    </div>
  );
}

/* A single selectable service chip: a visually-hidden checkbox with a styled
   label, so it is keyboard-operable, focus-ring visible, and announced. */
function ServiceChip({ svc, checked, onToggle }) {
  const Art = svc.doodle ? CC[svc.doodle] : null;
  return (
    <label className={'svcpick__chip svcpick__chip--' + svc.color + (checked ? ' is-on' : '')}>
      <input type="checkbox" className="svcpick__input" checked={checked} onChange={onToggle} />
      <span className="svcpick__check" aria-hidden="true">
        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="4" strokeLinecap="round" strokeLinejoin="round"><path d="M5 13l4 4L19 7" /></svg>
      </span>
      <span className="svcpick__art" aria-hidden="true">{Art ? <Art /> : <Paw width="26" height="26" />}</span>
      <span className="svcpick__body">
        <span className="svcpick__title">{svc.title}</span>
        {svc.price ? (
          <span className="svcpick__price">{svc.price}<small> {svc.unit}</small></span>
        ) : (
          <span className="svcpick__price svcpick__price--soft">help me choose</span>
        )}
      </span>
    </label>
  );
}

/* Friendly "you're outside Whatcom County" dialog. */
function ServiceAreaDialog({ open, town, onClose }) {
  const ref = React.useRef(null);
  React.useEffect(() => {
    if (!open) return;
    const d = ref.current;
    if (d && !d.open) d.showModal();
    const handleClose = () => onClose();
    d.addEventListener('close', handleClose);
    return () => d.removeEventListener('close', handleClose);
  }, [open, onClose]);
  if (!open) return null;
  const shown = String(town || '').trim().slice(0, 40);
  return (
    <dialog
      ref={ref}
      className="area-modal"
      aria-labelledby="area-modal-title"
      onClick={(e) => { if (e.target === ref.current) onClose(); }}
    >
      <div className="area-modal__card">
        <span className="area-modal__badge" aria-hidden="true"><Paw width="32" height="32" /></span>
        <span className="cc-eyebrow eyebrow-rule is-coral" style={{ justifyContent: 'center' }}>Whatcom County only</span>
        <h2 id="area-modal-title">That looks outside my range</h2>
        <p>Right now I only cover Whatcom County, WA: Bellingham, Ferndale, Lynden, Blaine, Birch Bay, Everson, Sumas, Deming, and the communities in between.{shown ? ' "' + shown + '" seems to be outside that.' : ''}</p>
        <p className="area-modal__soft">If you're nearby or think this is a mix-up, update the town and try again.</p>
        <div className="area-modal__actions">
          <Button variant="sticker" arrow onClick={onClose}>Update my town</Button>
        </div>
      </div>
    </dialog>
  );
}

function BookScreen({ go, preselectService }) {
  const [sent, setSent] = useState(false);
  const [showCard, setShowCard] = useState(false);
  const [services, setServices] = useState(
    preselectService && SERVICE_KEY_BY_TITLE[preselectService]
      ? [SERVICE_KEY_BY_TITLE[preselectService]]
      : []
  );
  const [form, setForm] = useState({ name: '', phone: '', email: '', town: '', start: '', end: '', critters: '' });
  const [errors, setErrors] = useState({});
  const [areaOpen, setAreaOpen] = useState(false);
  const [reportCard, setReportCard] = useState(false);
  const [submitting, setSubmitting] = useState(false);
  const [submitError, setSubmitError] = useState(false);
  const ReportDialog = window.CCReportDialog;

  const setField = (k, v) => setForm((f) => Object.assign({}, f, { [k]: v }));
  const clearErr = (k) => setErrors((e) => { if (!e[k]) return e; const n = Object.assign({}, e); delete n[k]; return n; });
  const setErr = (k, msg) => setErrors((e) => Object.assign({}, e, { [k]: msg }));

  const toggleService = (key) => {
    setServices((cur) => (cur.indexOf(key) === -1 ? cur.concat(key) : cur.filter((k) => k !== key)));
    clearErr('services');
  };

  const onPhone = (e) => { setField('phone', formatPhone(e.target.value)); clearErr('phone'); };
  // Blur validators read the live input value (e.target.value) rather than the
  // state closure, so they are correct regardless of React's render timing.
  const phoneBlur = (e) => { const v = e.target.value; if (v && onlyDigits(v).length !== 10) setErr('phone', 'Please enter a full 10-digit phone number.'); };
  const emailBlur = (e) => {
    const v = e.target.value.trim();
    if (v && !EMAIL_RE.test(v)) setErr('email', "That email address doesn't look quite right."); else clearErr('email');
  };
  const townBlur = (e) => {
    const t = e.target.value.trim();
    if (!t) return;
    if (!inServiceArea(t)) { setErr('town', 'Sorry, that looks outside Whatcom County.'); setAreaOpen(true); }
    else clearErr('town');
  };

  const focusFirst = (er) => {
    const order = ['name', 'phone', 'email', 'services', 'town', 'start', 'end', 'critters'];
    for (let i = 0; i < order.length; i++) {
      const k = order[i];
      if (!er[k]) continue;
      const el = k === 'services'
        ? document.querySelector('.svcpick__input')
        : document.querySelector('[data-err="' + k + '"]');
      if (el && el.focus) { el.focus(); return; }
    }
  };

  const onSubmit = async (e) => {
    e.preventDefault();
    if (submitting) return;
    const er = {};
    if (!form.name.trim()) er.name = 'Please add your name.';
    if (onlyDigits(form.phone).length !== 10) er.phone = 'Please enter a full 10-digit phone number.';
    const email = form.email.trim();
    if (email && !EMAIL_RE.test(email)) er.email = "That email address doesn't look quite right.";
    if (services.length === 0) er.services = 'Please pick at least one service (or "Other / Not sure yet").';
    const town = form.town.trim();
    const townOutside = town && !inServiceArea(town);
    if (!town) er.town = 'Which town are your critters in?';
    else if (townOutside) er.town = 'Sorry, that looks outside Whatcom County.';
    if (!form.start) er.start = 'A start date is required.';
    if (form.start && form.end && form.end < form.start) er.end = 'The end date is before the start date.';
    if (!form.critters.trim()) er.critters = 'Tell me a little about your critters.';

    setErrors(er);
    if (townOutside) { setAreaOpen(true); return; }
    if (Object.keys(er).length) { focusFirst(er); return; }

    const selected = PICK_SERVICES.filter((s) => services.indexOf(s.key) !== -1);
    const payload = {
      name: form.name.trim(),
      phone: form.phone.trim(),
      email: form.email.trim(),
      services: selected.map((s) => s.title),
      town: form.town.trim(),
      startDate: form.start,
      endDate: form.end,
      critters: form.critters.trim(),
      reportCard: reportCard,
      submittedAt: new Date().toISOString(),
      source: 'carterscritter.care booking form',
    };

    setSubmitError(false);
    setSubmitting(true);
    try {
      const res = await fetch(WEBHOOK_URL, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(payload),
      });
      if (!res.ok) throw new Error('HTTP ' + res.status);
      setSent(true);
    } catch (err) {
      setSubmitError(true);
    } finally {
      setSubmitting(false);
    }
  };

  if (sent) {
    const Stamp = CC.Paw;
    return (
      <main>
        <section className="page-head"><div className="container">
          <div className="booked">
            <span className="booked__stamp"><Stamp /></span>
            <span className="cc-eyebrow eyebrow-rule" style={{ justifyContent: 'center' }}>Request received</span>
            <h1>Got it. Talk soon.</h1>
            <p className="page-head__lead" style={{ marginInline: 'auto' }}>Thanks for reaching out. I'll get back to you soon to set up your free meet &amp; greet. Your critters are already as good as in good hands.</p>
            <p className="cc-hand booked__sig">Carter</p>
            <div className="booked__actions">
              <Button variant="sticker" arrow onClick={() => go('home')}>Back to home</Button>
              <Button variant="ghost" onClick={() => setSent(false)}>Send another</Button>
            </div>
          </div>
        </div></section>
      </main>
    );
  }

  return (
    <main>
      <section className="page-head"><div className="container">
        <span className="cc-eyebrow eyebrow-rule">Connect with Carter</span>
        <h1>Tell me about your trip.</h1>
        <p className="page-head__lead">Fill this out and I'll get back to you to set up a free meet &amp; greet, anywhere in Whatcom County.</p>
      </div></section>

      <section className="section container">
        <div className="book-grid">
          <div className="book-form-wrap">
            <form className="book-form" noValidate onSubmit={onSubmit}>
              <fieldset className="book-form__fieldset">
                <legend className="book-form__legend"><span className="num">1</span> Your details</legend>
                <div className="book-form__row">
                  <Input label="Your name" placeholder="Jamie Rivera" required autoComplete="name"
                    value={form.name} onChange={(e) => { setField('name', e.target.value); clearErr('name'); }}
                    error={errors.name} aria-invalid={!!errors.name} data-err="name" />
                  <Input label="Phone" type="tel" inputMode="tel" maxLength={14} placeholder="(360) 555-0000"
                    icon={<Icon name="phone" />} required autoComplete="tel"
                    value={form.phone} onChange={onPhone} onBlur={phoneBlur}
                    error={errors.phone} aria-invalid={!!errors.phone} data-err="phone" />
                </div>
                <Input label="Email" type="email" inputMode="email" placeholder="you@email.com"
                  icon={<Icon name="envelope-simple" />} autoComplete="email"
                  value={form.email} onChange={(e) => { setField('email', e.target.value); clearErr('email'); }} onBlur={emailBlur}
                  error={errors.email} aria-invalid={!!errors.email} data-err="email" />
              </fieldset>

              <fieldset className="book-form__fieldset">
                <legend className="book-form__legend"><span className="num">2</span> The trip</legend>

                <fieldset className={'svcpick' + (errors.services ? ' is-invalid' : '')}>
                  <legend className="svcpick__legend">
                    Which services are you interested in?
                    <span className="svcpick__opt">pick one or more</span>
                  </legend>
                  <div className="svcpick__grid">
                    {PICK_SERVICES.map((svc) => (
                      <ServiceChip
                        key={svc.key}
                        svc={svc}
                        checked={services.indexOf(svc.key) !== -1}
                        onToggle={() => toggleService(svc.key)}
                      />
                    ))}
                  </div>
                  {errors.services ? <p className="svcpick__error">{errors.services}</p> : null}
                </fieldset>

                <TownField
                  value={form.town}
                  onChange={(v) => { setField('town', v); clearErr('town'); }}
                  onBlur={townBlur}
                  error={errors.town} />
                <div className="book-form__row">
                  <Input label="Start date" type="date" required min={TODAY}
                    value={form.start} onChange={(e) => { setField('start', e.target.value); clearErr('start'); clearErr('end'); }}
                    error={errors.start} aria-invalid={!!errors.start} data-err="start" />
                  <Input label="End date" type="date" min={form.start || TODAY}
                    value={form.end} onChange={(e) => { setField('end', e.target.value); clearErr('end'); }}
                    error={errors.end} aria-invalid={!!errors.end} data-err="end" />
                </div>
              </fieldset>

              <fieldset className="book-form__fieldset">
                <legend className="book-form__legend"><span className="num">3</span> The critters</legend>
                <div>
                  <Textarea label="Tell me about your critters" required
                    className={errors.critters ? 'cc-textarea--error' : ''}
                    placeholder="Two cats (Biscuit & Olive), one very chill corn snake. Biscuit needs a daily pill in a treat…"
                    hint={errors.critters ? undefined : 'Names, ages, meds, routines, quirks: the more the better. Exotics totally welcome.'}
                    value={form.critters} onChange={(e) => { setField('critters', e.target.value); clearErr('critters'); }}
                    aria-invalid={!!errors.critters} data-err="critters" />
                  {errors.critters ? <span className="cc-field__error" style={{ display: 'block', marginTop: '6px' }}>{errors.critters}</span> : null}
                </div>
              </fieldset>

              {/* Report-card opt-in - a real selling moment, NOT pre-checked */}
              <div className="optin">
                <div className="optin__text">
                  <b><Icon name="camera" /> Add the daily report card <span className="price">+$5/day</span></b>
                  <p>Photos and honest notes after every visit, so you never wonder how they're doing while you're away. Totally optional. Flip it on if you'd like it.</p>
                  <button type="button" className="optin__example" onClick={() => setShowCard(true)}>See an example →</button>
                </div>
                <span className="optin__switch"><Switch aria-label="Add the daily report card for $5 per day" checked={reportCard} onChange={(e) => setReportCard(e.target.checked)} /></span>
              </div>

              <div className="book-form__submit">
                <Button type="submit" variant="sticker" size="lg" arrow disabled={submitting}>{submitting ? 'Sending…' : 'Send my details to Carter'}</Button>
                <span className="book-form__note"><Icon name="lock-simple" /> No payment today, just a friendly hello.</span>
                {submitError ? <p className="book-form__error" role="alert">Hmm, that didn't go through. Please check your connection and try again in a moment.</p> : null}
              </div>
            </form>
          </div>

          <aside className="book-aside">
            <div className="book-sitter">
              <img className="book-sitter__photo" src="/design-system/assets/carter-avatar.jpg" alt="Carter" />
              <div>
                <b>Carter</b>
                <span>Your sitter · Whatcom County</span>
                <span className="cc-hand aside-hand aside-hand--brand">treats your pets like my own</span>
              </div>
            </div>
            <div className="book-steps">
              <h3>What happens next</h3>
              <ol>
                <li><span><Icon name="chat-circle" /></span><div><b>I get back to you</b><p>A friendly text or email to say hi.</p></div></li>
                <li><span><Icon name="coffee" /></span><div><b>Free meet &amp; greet</b><p>We chat and I meet your critters in person.</p></div></li>
                <li><span><Paw width="20" height="20" style={{ color: 'var(--ink-900)' }} /></span><div><b>You head off</b><p>Add the report card for photos along the way.</p></div></li>
              </ol>
            </div>
            <div className="book-tags">
              <span className="sticker sticker--mint sticker--rot-l"><Icon name="coffee" /> Free meet &amp; greet</span>
              <span className="sticker sticker--sky sticker--rot-r"><Paw width="15" height="15" /> Exotics welcome</span>
            </div>
          </aside>
        </div>
      </section>

      <ReportDialog open={showCard} onClose={() => setShowCard(false)} />
      <ServiceAreaDialog open={areaOpen} town={form.town} onClose={() => setAreaOpen(false)} />
    </main>
  );
}

window.BookScreen = BookScreen;
})();
