// YJ Electric — the YJ van in the booking flow (2026-10-04)
// Load after schedule-v2-shared.jsx and before schedule-v2-steps.jsx.
//
// Six small ideas, all ON: the owners kept every one (2026-10-04) after trying
// them on a preview with a toggle panel, which has since been removed. Each still
// has its own switch in VAN_ENABLED: turning one off is one `false` below, and the
// flow falls back to exactly what it showed before the van.
//
// The van is the same drawing as assets/yj-van.svg and the van on Volt's live
// map (truckBadge.ts in Volt): a white Ford Transit from the real fleet wrap,
// navy YJ mark, amber bolt. Keep the three in step if the art ever changes.
//
// Rules every idea follows:
//   - Never slower than the flow. Nothing waits on an animation; a submit, a
//     step change, or a pick happens at once and the van catches up.
//   - Under a second for anything that repeats; the one-off arrival scene on the
//     receipt is the only longer one, and it runs after the booking landed.
//   - prefers-reduced-motion shows every van parked in its final spot, still.
//   - Decorative only: aria-hidden, no text a screen reader needs.

const VAN_ENABLED = {
  road: true,      // 1. The progress bar is a road, and the van drives to each step
  park: true,      // 2. The van pulls in beside the arrival time you pick
  drive: true,     // 3. The van drives the Send button, then pulls up to the house on the receipt
  uturn: true,     // 4. A U-turn when the time you picked was just taken
  timeline: true,  // 5. "What happens next" is a road, with the van parked at step one
  full: true,      // 6. A parked van marks a booked-up day
};

// Read by every step through useVanIdea (schedule-v2-shared.jsx). A plain
// lookup: nothing changes the switches at runtime any more.
function vanIsOn(key) {
  return VAN_ENABLED[key] !== false;
}
function useVan(key) {
  return vanIsOn(key);
}

// One stylesheet for every idea, injected once. Kept here rather than in
// assets/site.css so the whole feature lives (and can be removed) in one file.
(function vanStyles() {
  if (typeof document === 'undefined' || document.getElementById('yjv-css')) return;
  const css = `
.yjv-road-van { position: absolute; transition: left 700ms cubic-bezier(.45,.05,.2,1); will-change: left; }
.yjv-road-fill { transition: width 700ms cubic-bezier(.45,.05,.2,1); }
.yjv-road-van.moving svg { animation: yjvBob 175ms ease-in-out 4; }
.yjv-road-van .yjv-dust { position: absolute; bottom: 1px; width: 6px; height: 6px; border-radius: 50%; background: rgba(31,42,74,.18); opacity: 0; }
.yjv-road-van.moving .yjv-dust { animation: yjvPuff 700ms ease-out 1; }
.yjv-road-van.moving .yjv-dust.d2 { animation-delay: 140ms; }
.yjv-road-van.back .yjv-dust { display: none; }
@keyframes yjvBob { 0%,100% { transform: translateY(0); } 50% { transform: translateY(-1.5px); } }
@keyframes yjvPuff { 0% { opacity: .9; transform: translate(0,0) scale(.6); } 100% { opacity: 0; transform: translate(-16px,-5px) scale(1.5); } }

.yjv-park { animation: yjvPark 650ms cubic-bezier(.2,.8,.25,1) both; }
@keyframes yjvPark { 0% { transform: translateX(-70px); opacity: 0; } 70% { transform: translateX(4px); opacity: 1; } 85% { transform: translateX(-1px) rotate(-1deg); } 100% { transform: translateX(0) rotate(0); } }

.yjv-btn-van { position: absolute; bottom: 3px; left: 0; z-index: 0; pointer-events: none; animation: yjvAcross 1.15s linear infinite; }
@keyframes yjvAcross { 0% { transform: translateX(-40px); } 100% { transform: translateX(var(--yjv-w, 320px)); } }

.yjv-arrive { position: absolute; bottom: 9px; animation: yjvArrive 1.5s cubic-bezier(.22,.7,.25,1) both; }
@keyframes yjvArrive { 0% { left: -90px; } 82% { left: calc(100% - 158px); } 90% { left: calc(100% - 152px); } 100% { left: calc(100% - 154px); } }
/* Phone size (owner, 2026-10-04): a bigger van and house, so the stop moves out
   to keep the same 12px gap in front of the house. */
.yjv-arrive.lg { animation-name: yjvArriveLg; }
@keyframes yjvArriveLg { 0% { left: -120px; } 82% { left: calc(100% - 210px); } 90% { left: calc(100% - 204px); } 100% { left: calc(100% - 206px); } }
.yjv-arrive .yjv-light { opacity: 0; animation: yjvBlink 1.3s 1.5s ease-in-out forwards; }
@keyframes yjvBlink { 0% { opacity: 0; } 15% { opacity: 1; } 30% { opacity: 0; } 45% { opacity: 1; } 60% { opacity: 0; } 100% { opacity: .85; } }
.yjv-window { animation: yjvGlow 900ms 1.8s ease-out both; }
@keyframes yjvGlow { 0% { fill: #E9E2D4; } 100% { fill: #F6D27A; } }
.yjv-letter { position: absolute; opacity: 0; animation: yjvLetter 1s 1.55s cubic-bezier(.3,.7,.3,1) forwards; }
@keyframes yjvLetter { 0% { opacity: 0; transform: translate(0,0) scale(.7); } 25% { opacity: 1; } 60% { transform: translate(48px,-26px) scale(1); opacity: 1; } 100% { transform: translate(92px,-2px) scale(.5); opacity: 0; } }
.yjv-letter.lg { animation-name: yjvLetterLg; }
@keyframes yjvLetterLg { 0% { opacity: 0; transform: translate(0,0) scale(.7); } 25% { opacity: 1; } 60% { transform: translate(60px,-36px) scale(1); opacity: 1; } 100% { transform: translate(118px,-4px) scale(.5); opacity: 0; } }

.yjv-uturn { position: absolute; left: 0; bottom: 2px; animation: yjvUturn 2s ease-in-out both; }
@keyframes yjvUturn { 0% { transform: translateX(0) scaleX(1); } 42% { transform: translateX(150px) scaleX(1); } 50% { transform: translateX(162px) translateY(-3px) scaleX(-1); } 100% { transform: translateX(10px) scaleX(-1); } }

.yjv-tl-van { animation: yjvDrop 650ms cubic-bezier(.2,.8,.25,1) both; }
@keyframes yjvDrop { 0% { transform: translateY(-22px); opacity: 0; } 100% { transform: translateY(0); opacity: 1; } }

@media (prefers-reduced-motion: reduce) {
  .yjv-road-van, .yjv-road-fill { transition: none; }
  .yjv-road-van.moving svg, .yjv-road-van.moving .yjv-dust, .yjv-park, .yjv-tl-van, .yjv-uturn, .yjv-window { animation: none; }
  .yjv-btn-van { display: none; }
  .yjv-arrive { animation: none; left: calc(100% - 154px); }
  .yjv-arrive.lg { left: calc(100% - 206px); }
  .yjv-arrive .yjv-light { animation: none; opacity: .85; }
  .yjv-letter { display: none; }
}`;
  const el = document.createElement('style');
  el.id = 'yjv-css';
  el.textContent = css;
  document.head.appendChild(el);
})();

// The van itself. `lights` adds the headlight the receipt blinks.
function VanSvg({ width = 44, lights = false, muted = false, className, style }) {
  return (
    <svg viewBox="0 0 64 44" width={width} height={Math.round(width * 44 / 64)} aria-hidden="true" focusable="false"
      className={className} style={{ display: 'block', overflow: 'visible', ...(muted ? { filter: 'grayscale(1)', opacity: 0.5 } : {}), ...style }}>
      <path d="M8 30.5 V14 q0-3.5 3.5-3.5 H37 L50 17.5 q3.5 1 5.5 4 l1.5 3 q1 2-0.5 3.5 l-2 2 q-0.5 0.5-1.5 0.5 H8 z" fill="#ffffff" stroke="#0f1f3d" strokeWidth="2.4" strokeLinejoin="round" />
      <path d="M37.5 12.8 L49 17.3 q1.2 0.5 0.6 1.4 L48 20 h-9.5 q-1 0-1-1 v-5.2 q0-1 1-1 z" fill="#0f1f3d" />
      <path d="M10 25.4 H49.5 q4.5 0 6.5 3.2 l1 1.9 H10 q-1.8 0-1.8-2.5 q0-2.6 1.8-2.6 z" fill="#374151" />
      <g transform="translate(13.5 14)">
        <path d="M0 0 h3 l1.6 3.2 L6.2 0 H9 L5.9 5.4 V9.5 H3.1 V5.4 z" fill="#0f1f3d" />
        <path d="M12.2 -0.5 L8.6 4.6 h2.4 L9.4 9.8 l4.6-6 h-2.4 L13.4 -0.5 z" fill="#f59e0b" />
        <path d="M14.6 0 h6 v2.4 h-1.6 v4.2 q0 3-3.1 3 q-2.2 0-3.2-1.5 l1.7-1.7 q0.5 0.8 1.3 0.8 q0.9 0 0.9-1.1 V2.4 h-2 z" fill="#0f1f3d" />
      </g>
      <circle cx="17" cy="32.5" r="5.4" fill="#111827" />
      <circle cx="17" cy="32.5" r="2.4" fill="#d1d5db" />
      <circle cx="48" cy="32.5" r="5.4" fill="#111827" />
      <circle cx="48" cy="32.5" r="2.4" fill="#d1d5db" />
      {lights && (
        <g className="yjv-light">
          <path d="M57.5 21 L76 15 L76 30 L57.5 24.5 z" fill="#F6C453" opacity="0.45" />
          <circle cx="56.6" cy="22.6" r="2.2" fill="#F59E0B" />
        </g>
      )}
    </svg>
  );
}

// ── 1. Progress bar as a road ─────────────────────────────
// The four step labels stay where they were; the thin bars become one road and
// the van parks directly over the label of the step the customer is on, then
// drives to sit over the next one (owner, 2026-10-04: over "What" on step one,
// over "When" on step two). Backing up a step reverses the van (it keeps facing
// forward, like a truck backing down a drive).
//
// Positions are MEASURED from the labels, not computed from column widths: the
// labels are left-aligned and different lengths, so "the middle of column 2" is
// not over "When". Re-measured on resize, so a phone rotation keeps it on the
// label. Until the first measure the van is hidden, so it never slides in from
// a guessed spot on page load.
function VanRoad({ steps, step, onPick, label }) {
  const prev = React.useRef(step);
  const [moving, setMoving] = React.useState(false);
  const back = step < prev.current;
  React.useEffect(() => {
    if (prev.current === step) return undefined;
    setMoving(true);
    const t = setTimeout(() => setMoving(false), 720);
    prev.current = step;
    return () => clearTimeout(t);
  }, [step]);

  const boxRef = React.useRef(null);
  const labelRefs = React.useRef([]);
  const [centers, setCenters] = React.useState(null); // px from the box's left edge, one per step
  React.useLayoutEffect(() => {
    const measure = () => {
      const box = boxRef.current;
      if (!box) return;
      const left = box.getBoundingClientRect().left;
      const next = steps.map((_, i) => {
        const el = labelRefs.current[i];
        if (!el) return null;
        const r = el.getBoundingClientRect();
        return r.left - left + r.width / 2;
      });
      if (next.every((x) => typeof x === 'number')) setCenters(next);
    };
    measure();
    // Webfonts change the label widths once they load.
    if (document.fonts && document.fonts.ready) document.fonts.ready.then(measure).catch(() => {});
    // Watch the road itself, not just the window: the layout can change width
    // without a resize event (the phone stepper, a device-size switch in a
    // preview), and the van stayed over where the label USED to be.
    let ro = null;
    if (typeof ResizeObserver !== 'undefined' && boxRef.current) {
      ro = new ResizeObserver(measure);
      ro.observe(boxRef.current);
    }
    window.addEventListener('resize', measure);
    return () => { window.removeEventListener('resize', measure); if (ro) ro.disconnect(); };
  }, [steps.length]);

  const x = centers ? centers[Math.min(step, centers.length - 1)] : 0;
  // Bigger on a phone (owner, 2026-10-04): 38px read as a speck at 375 wide.
  // The road drops to fit it, and the van's wheels sit on the road at any size.
  const isMobile = useIsMobileV2();
  const VAN_W = isMobile ? 54 : 38;
  const VAN_H = Math.round(VAN_W * 44 / 64);
  const ROAD_TOP = VAN_H + 4;
  return (
    <div ref={boxRef} role="progressbar" aria-valuemin={1} aria-valuemax={steps.length} aria-valuenow={step + 1} aria-label={label}
      style={{ position: 'relative', marginTop: 10, paddingTop: ROAD_TOP + 4 }}>
      <div style={{ position: 'absolute', left: 0, right: 0, top: ROAD_TOP, height: 4, borderRadius: 2, background: 'rgba(31,42,74,0.12)', overflow: 'hidden' }}>
        <div className="yjv-road-fill" style={{ width: centers ? x : 0, height: '100%', background: SG.navy, borderRadius: 2 }} />
      </div>
      <div className={'yjv-road-van' + (moving ? ' moving' : '') + (back ? ' back' : '')} aria-hidden="true"
        style={{ left: x, top: ROAD_TOP - Math.round(VAN_H * 0.96), transform: 'translateX(-50%)', visibility: centers ? 'visible' : 'hidden' }}>
        <span className="yjv-dust" style={{ left: -4 }} />
        <span className="yjv-dust d2" style={{ left: -10 }} />
        <VanSvg width={VAN_W} />
      </div>
      <div style={{ display: 'flex', gap: 6 }}>
        {steps.map((s, i) => (
          <button key={s.key} type="button" onClick={() => { if (i < step) onPick(i); }} disabled={i >= step}
            aria-label={i < step ? `Back to ${s.label}` : s.label}
            style={{ flex: 1, background: 'none', border: 'none', padding: '0 0 6px', cursor: i < step ? 'pointer' : 'default', textAlign: 'left' }}>
            {/* inline-block so the measured box is the word, not the column */}
            <span ref={(el) => { labelRefs.current[i] = el; }}
              style={{ display: 'inline-block', marginTop: 8, fontFamily: SG.label, fontWeight: 600, fontSize: 11, letterSpacing: '0.16em', textTransform: 'uppercase', color: i <= step ? SG.navy : SG.gray, opacity: i <= step ? 1 : 0.7 }}>{s.label}</span>
          </button>
        ))}
      </div>
    </div>
  );
}

// ── 2. The van pulls in beside the time you picked ─────────
// Re-keyed on every pick, so it drives in again when the customer changes time.
function VanParked({ pickKey, width = 46 }) {
  // About a third bigger on a phone (owner, 2026-10-04), like the road and
  // receipt vans: 46 -> 62 in the arrival box, 30 -> 40 on the 2-hour grid.
  const lg = useIsMobileV2();
  const w = lg ? Math.round(width * 1.35) : width;
  return (
    <div key={pickKey} className="yjv-park" aria-hidden="true" style={{ flexShrink: 0 }}>
      <VanSvg width={w} />
    </div>
  );
}

// ── 3a. The van drives the Send button while the request goes in ──
function VanButtonRun() {
  const ref = React.useRef(null);
  const lg = useIsMobileV2();
  React.useEffect(() => {
    const btn = ref.current && ref.current.parentElement;
    if (btn) ref.current.style.setProperty('--yjv-w', `${btn.clientWidth + 10}px`);
  }, []);
  return (
    <span ref={ref} className="yjv-btn-van" aria-hidden="true">
      {/* 28 -> 38 on a phone, like the other vans (owner, 2026-10-04). It runs
          BEHIND the button label (the label sits at z-index 1), so the bigger
          van never covers "Sending". */}
      <VanSvg width={lg ? 38 : 28} lights />
    </span>
  );
}

// ── 3b. The receipt opens with the van pulling up to the house ──
// Booked or requested: it parks and flashes its lights, and a light comes on
// in the house. A quote: it parks and a letter goes to the door.
function VanArrival({ kind }) {
  // Bigger on a phone (owner, 2026-10-04), the house scaled with the van. The
  // stop point and the letter's path for each size live in the .lg keyframes.
  const lg = useIsMobileV2();
  const VAN_W = lg ? 96 : 66;
  const HOUSE_W = lg ? 92 : 70;
  return (
    <div aria-hidden="true" style={{ position: 'relative', height: lg ? 124 : 92, marginBottom: 18 }}>
      <div style={{ position: 'absolute', left: 0, right: 0, bottom: 8, height: 3, borderRadius: 2, background: 'rgba(31,42,74,0.14)' }} />
      <svg viewBox="0 0 70 60" width={HOUSE_W} height={Math.round(HOUSE_W * 60 / 70)} style={{ position: 'absolute', right: 6, bottom: 9 }}>
        <path d="M5 28 L35 6 L65 28" fill="none" stroke={SG.navy} strokeWidth="2.6" strokeLinecap="round" strokeLinejoin="round" />
        <rect x="12" y="25" width="46" height="34" rx="1.5" fill="#fff" stroke={SG.navy} strokeWidth="2.6" />
        <rect className={kind === 'quote' ? undefined : 'yjv-window'} x="18" y="32" width="11" height="10" rx="1" fill={kind === 'quote' ? '#E9E2D4' : '#F6D27A'} stroke={SG.navy} strokeWidth="1.6" />
        <rect x="37" y="38" width="12" height="21" rx="1" fill={SG.navy} />
        <circle cx="46" cy="49" r="1.1" fill={SG.goldLight} />
      </svg>
      <div className={lg ? 'yjv-arrive lg' : 'yjv-arrive'}>
        <VanSvg width={VAN_W} lights={kind !== 'quote'} />
      </div>
      {kind === 'quote' && (
        <svg className={lg ? 'yjv-letter lg' : 'yjv-letter'} viewBox="0 0 20 14" width={lg ? 26 : 20} height={lg ? 18 : 14} style={{ right: lg ? 150 : 128, bottom: lg ? 62 : 46 }}>
          <rect x="1" y="1" width="18" height="12" rx="1.5" fill="#fff" stroke={SG.navy} strokeWidth="1.6" />
          <path d="M1.5 2 L10 8 L18.5 2" fill="none" stroke={SG.gold} strokeWidth="1.6" />
        </svg>
      )}
    </div>
  );
}

// ── 4. A U-turn when the time was just taken ───────────────
function VanUturn() {
  // 40 -> 54 on a phone, like the other vans (owner, 2026-10-04).
  const lg = useIsMobileV2();
  return (
    <div aria-hidden="true" style={{ position: 'relative', height: lg ? 46 : 34, marginTop: 10, overflow: 'hidden' }}>
      <div style={{ position: 'absolute', left: 0, right: 0, bottom: 1, height: 2, background: 'rgba(138,43,43,0.18)', borderRadius: 1 }} />
      <div className="yjv-uturn"><VanSvg width={lg ? 54 : 40} /></div>
    </div>
  );
}

// ── 5. "What happens next" as a road ──────────────────────
// Same idea as the steps line on the site's pages: a line down the left, a dot
// per step, and the van parked at the step the customer is on now (the first).
// The customer's /s/ portal can carry the same road on from there.
function VanTimeline({ rows }) {
  // 40 -> 54 on a phone, like the other vans (owner, 2026-10-04). The line, the
  // dots, and the van stay centered on one x: 22px from the left on desktop,
  // 29px on a phone, with the text indented to match.
  const lg = useIsMobileV2();
  const VAN_W = lg ? 54 : 40;
  const PAD = lg ? 64 : 52;
  const AXIS = lg ? 29 : 22;
  return (
    <div style={{ position: 'relative', paddingLeft: PAD }}>
      <div aria-hidden="true" style={{ position: 'absolute', left: AXIS - 1, top: 22, bottom: 22, width: 2, background: SG.grayLight }} />
      {rows.map(([when, what], i) => (
        <div key={i} style={{ position: 'relative', padding: '12px 0', fontFamily: SG.font, opacity: i === 0 ? 1 : 0.62 }}>
          {i === 0 ? (
            <div className="yjv-tl-van" aria-hidden="true" style={{ position: 'absolute', left: AXIS - VAN_W / 2 - PAD, top: lg ? 5 : 9 }}>
              <VanSvg width={VAN_W} />
            </div>
          ) : (
            <div aria-hidden="true" style={{ position: 'absolute', left: AXIS - 6 - PAD, top: 15, width: 12, height: 12, boxSizing: 'border-box', borderRadius: '50%', background: SG.cream, border: `2px solid ${SG.gold}` }} />
          )}
          <div style={{ fontWeight: 600, fontSize: 11, letterSpacing: '0.12em', textTransform: 'uppercase', fontFamily: SG.label, color: SG.goldDark }}>{when}</div>
          <div style={{ fontSize: 15, fontWeight: 400, color: SG.navy, lineHeight: 1.5, marginTop: 2 }}>{what}</div>
        </div>
      ))}
    </div>
  );
}

// ── 6. A parked van marks a booked-up day ─────────────────
function VanBookedUp({ width = 22, active = false }) {
  // About a third bigger on a phone (owner, 2026-10-04), like the other vans:
  // 22 -> 30 in a day chip, 54 -> 73 over "No arrival times open". On the
  // selected (navy) chip it shows in full color; grey vanished on the navy.
  const lg = useIsMobileV2();
  const w = lg ? Math.round(width * 1.35) : width;
  return <VanSvg width={w} muted={!active} />;
}

Object.assign(window, {
  VAN_ENABLED, useVan, vanIsOn, VanSvg, VanRoad, VanParked, VanButtonRun, VanArrival, VanUturn, VanTimeline, VanBookedUp,
});
