const { useEffect, useMemo, useRef, useState } = React;

const heroImage = "/hero-teine.jpg";
const homeHeroImage = "/pics/trip/WechatIMG158.jpeg";
const logoImage = "/pics/logo.png";
const spriteImage = "/pics/spirit.png";

const connectImages = [
  { label: "WhatsApp", src: "/pics/connect/CleanShot 2026-06-10 at 12.11.52@2x.png", note: "扫码添加 WhatsApp" },
  { label: "WeChat", src: "/pics/connect/CleanShot 2026-06-10 at 12.13.09@2x.png", note: "扫码添加微信" },
  { label: "LINE", src: "/pics/connect/CleanShot 2026-06-10 at 12.12.21@2x.png", note: "扫码添加 LINE" }
];

const tripImages = {
  seaView: "/pics/trip/WechatIMG158.jpeg",
  family: "/pics/trip/WechatIMG157.jpeg",
  lesson: "/pics/trip/WechatIMG161.jpeg",
  lounge: "/pics/trip/WechatIMG155.jpeg",
  powder: "/pics/trip/WechatIMG160.jpeg"
};

const commentImages = [
  "/pics/comments/WechatIMG539.jpeg",
  "/pics/comments/WechatIMG540.jpeg",
  "/pics/comments/WechatIMG541.jpeg",
  "/pics/comments/WechatIMG542.jpeg",
  "/pics/comments/WechatIMG543.jpeg",
  "/pics/comments/WechatIMG547.jpeg"
];

const resorts = {
  teine: { label: "手稻 Sapporo Teine" },
  kokusai: { label: "札幌国际" },
  onze: { label: "ONZE" },
  asari: { label: "朝里川" },
  niseko: { label: "二世谷 Niseko" },
  rusutsu: { label: "留寿都 Rusutsu" }
};

const customerTiers = {
  regular: { label: "客人", priceKey: "regular" },
  preferred: { label: "二手单价 / 客人线下优惠", priceKey: "preferred" },
  agency: { label: "旅行社 / 大客户", priceKey: "agency" }
};

const services = {
  sharedTransferOneWay: { label: "接送车位单程" },
  sharedTransfer: { label: "接送车位往返" },
  privateTransfer7: { label: "包车接送7座" },
  privateTransfer10: { label: "包车接送10座" },
  rental: { label: "全套租赁" },
  rentalWithProtectors: { label: "全套租赁含护具" },
  liftPassHourly: { label: "雪卡每小时" },
  liftPassDay: { label: "全天雪卡" },
  coach: { label: "教练服务" },
  vip: { label: "VIP厅" },
  escort: { label: "陪滑" },
  butler: { label: "陪同人员管家" }
};

const priceTable = {
  rental: { agency: 500, preferred: 550, regular: 650 },
  rentalWithProtectors: { agency: 550, preferred: 600, regular: 720 },
  liftPassHourly: { agency: 50, preferred: 65, regular: 80 },
  liftPassDay: { agency: 200, preferred: 250, regular: 300 },
  sharedTransferOneWay: { agency: 150, preferred: 150, regular: 200 },
  sharedTransferRoundTrip: { agency: 200, preferred: 250, regular: 300 },
  privateTransfer7: { agency: 1000, preferred: 1300, regular: 1500 },
  privateTransfer10: { agency: 1600, preferred: 1800, regular: 2000 },
  vip: { agency: 70, preferred: 70, regular: 75 },
  coachStart: { agency: 800, preferred: 1000, regular: 1200 },
  coachAfterTwoHourly: { agency: 350, preferred: 450, regular: 550 },
  coachExtraPerPerson: { agency: 100, preferred: 150, regular: 200 },
  escort: { agency: 300, preferred: 350, regular: 400 },
  butler: { agency: 1200, preferred: 1400, regular: 1600 }
};

const rentalOrderOptions = {
  jacket: { label: "雪服" },
  pants: { label: "雪裤" },
  helmet: { label: "头盔(含一次性头套)" },
  goggles: { label: "雪镜" },
  gloves: { label: "手套(含一次性内胆)" },
  board: { label: "雪板（双板含雪杖）" },
  boots: { label: "雪鞋" },
  turtleProtector: { label: "小乌龟护具" },
  innerProtector: { label: "内穿护具" },
  socks: { label: "雪袜（零售）" },
  faceCover: { label: "面罩（零售）" }
};

const rentalOrderKeys = Object.keys(rentalOrderOptions);

const rentalOrderGroups = [
  { title: "服装", keys: ["jacket", "pants", "gloves", "socks", "faceCover"] },
  { title: "雪具", keys: ["board", "boots", "helmet", "goggles"] },
  { title: "护具", keys: ["turtleProtector", "innerProtector"] }
];

const rentalOrderTierLabels = {
  agency: "旅行社",
  preferred: "二手单价 / 客人线下优惠",
  regular: "客人"
};

const rentalOrderPriceTable = {
  snowSuit: { agency: 150, preferred: 180, regular: 200 },
  jacketOrPants: { agency: 100, preferred: 120, regular: 150 },
  helmet: { agency: 50, preferred: 60, regular: 70 },
  goggles: { agency: 30, preferred: 40, regular: 50 },
  gloves: { agency: 30, preferred: 40, regular: 50 },
  board: { agency: 150, preferred: 160, regular: 170 },
  boots: { agency: 150, preferred: 160, regular: 170 },
  boardBootsPoles: { agency: 230, preferred: 260, regular: 280 },
  turtleProtector: { agency: 50, preferred: 60, regular: 90 },
  innerProtector: { agency: 40, preferred: 50, regular: 75 },
  socks: { agency: 50, preferred: 60, regular: 80 },
  faceCover: { agency: 10, preferred: 20, regular: 30 }
};

const channelServiceKeys = [
  "rental",
  "rentalWithProtectors",
  "liftPassHourly",
  "liftPassDay",
  "sharedTransferOneWay",
  "sharedTransfer",
  "privateTransfer7",
  "privateTransfer10",
  "vip",
  "coach",
  "escort",
  "butler"
];

const packagePresets = [
  {
    key: "beginner",
    icon: "1",
    tag: "新手推荐",
    title: "新手全天全包套餐",
    description: "拼车接送、雪具租赁、4小时教学、4小时雪卡"
  },
  {
    key: "free",
    icon: "2",
    tag: "自由行",
    title: "自由行体验套餐",
    description: "拼车接送、雪具租赁、全天雪卡"
  },
  {
    key: "premium",
    icon: "3",
    tag: "高端定制",
    title: "高端服务套餐",
    description: "专车接送、VIP厅、含护具租赁、5小时教学、全天雪卡"
  }
];

const guestTemplate = {
  name: "",
  height: "",
  weight: "",
  shoeSize: "",
  preference: "Snowboard",
  needs: ["jacket", "pants", "helmet", "goggles", "gloves", "board", "boots"]
};

function formatCurrency(value) {
  return `¥${Math.round(value).toLocaleString("zh-CN")}`;
}

function calculateQuoteLines(quote, tierKey) {
  const skierCount = Math.max(0, Number(quote.guestCount) || 0);
  const rideOnlyCount = Math.max(0, Number(quote.rideOnlyCount) || 0);
  const riderCount = skierCount + rideOnlyCount;
  const coachHours = Math.max(1, Number(quote.coachHours) || 1);
  const liftPassHours = Math.max(1, Number(quote.liftPassHours) || 1);
  const groupDiscountEligible = riderCount >= 3;
  const seatMultiplier = groupDiscountEligible ? 0.8 : 1;
  const rentalMultiplier = groupDiscountEligible ? 0.9 : 1;
  const lines = [];

  const addLine = (label, amount) => {
    lines.push({ label, amount });
  };

  if (quote.selectedServices.includes("sharedTransfer")) {
    addLine(
      groupDiscountEligible ? "接送车位往返（3人优惠8折）" : "接送车位往返",
      priceTable.sharedTransferRoundTrip[tierKey] * riderCount * seatMultiplier
    );
  }

  if (quote.selectedServices.includes("sharedTransferOneWay")) {
    addLine(
      groupDiscountEligible ? "接送车位单程（3人优惠8折）" : "接送车位单程",
      priceTable.sharedTransferOneWay[tierKey] * riderCount * seatMultiplier
    );
  }

  if (quote.selectedServices.includes("privateTransfer7")) {
    addLine("包车接送7座", priceTable.privateTransfer7[tierKey]);
  }

  if (quote.selectedServices.includes("privateTransfer10")) {
    addLine("包车接送10座", priceTable.privateTransfer10[tierKey]);
  }

  if (quote.selectedServices.includes("rental")) {
    addLine(
      groupDiscountEligible ? "全套租赁（3人优惠9折）" : "全套租赁",
      priceTable.rental[tierKey] * skierCount * rentalMultiplier
    );
  }

  if (quote.selectedServices.includes("rentalWithProtectors")) {
    addLine(
      groupDiscountEligible ? "全套租赁含护具（3人优惠9折）" : "全套租赁含护具",
      priceTable.rentalWithProtectors[tierKey] * skierCount * rentalMultiplier
    );
  }

  if (quote.selectedServices.includes("liftPassHourly")) {
    addLine(`雪卡每小时 x ${liftPassHours}`, priceTable.liftPassHourly[tierKey] * liftPassHours * skierCount);
  }

  if (quote.selectedServices.includes("liftPassDay")) {
    addLine("全天雪卡", priceTable.liftPassDay[tierKey] * skierCount);
  }

  if (quote.selectedServices.includes("vip")) {
    addLine("VIP厅", priceTable.vip[tierKey] * skierCount);
  }

  if (quote.selectedServices.includes("coach") && skierCount > 0) {
    const extraHours = Math.max(0, coachHours - 2);
    const extraGuests = Math.max(0, skierCount - 1);
    addLine(`教练起步价（含2小时）`, priceTable.coachStart[tierKey]);
    if (extraHours > 0) {
      addLine(`教练超过2小时后每小时 x ${extraHours}`, priceTable.coachAfterTwoHourly[tierKey] * extraHours);
    }
    if (extraGuests > 0) {
      addLine(`教练每加一人每单 x ${extraGuests}人`, priceTable.coachExtraPerPerson[tierKey] * extraGuests);
    }
    if (quote.englishTeaching) {
      addLine("英文教学加价", 500);
    }
  }

  if (quote.selectedServices.includes("escort")) {
    addLine("陪滑", priceTable.escort[tierKey]);
  }

  if (quote.selectedServices.includes("butler")) {
    addLine("陪同人员管家", priceTable.butler[tierKey]);
  }

  const subtotal = lines.reduce((sum, line) => sum + line.amount, 0);
  if (quote.peakSeason && subtotal > 0) {
    addLine("旺季加价10%", subtotal * 0.1);
  }

  const total = lines.reduce((sum, line) => sum + line.amount, 0);
  return { total, lines };
}

function calculateRentalOrderLines(selectedNeeds, tierKey) {
  const needs = new Set(selectedNeeds);
  const lines = [];
  const addLine = (label, amount) => {
    if (amount > 0) lines.push({ label, amount });
  };
  const hasAllStandardRental = ["jacket", "pants", "helmet", "goggles", "gloves", "board", "boots"].every((key) => needs.has(key));
  const hasProtector = needs.has("turtleProtector") || needs.has("innerProtector");

  if (hasAllStandardRental) {
    addLine(
      hasProtector ? "全套租赁含护具（最低组合价）" : "全套租赁（最低组合价）",
      hasProtector ? priceTable.rentalWithProtectors[tierKey] : priceTable.rental[tierKey]
    );
  } else {
    if (needs.has("jacket") && needs.has("pants")) {
      addLine("雪服+雪裤（最低组合价）", rentalOrderPriceTable.snowSuit[tierKey]);
    } else {
      if (needs.has("jacket")) addLine("雪服", rentalOrderPriceTable.jacketOrPants[tierKey]);
      if (needs.has("pants")) addLine("雪裤", rentalOrderPriceTable.jacketOrPants[tierKey]);
    }

    if (needs.has("helmet")) addLine("头盔(含一次性头套)", rentalOrderPriceTable.helmet[tierKey]);
    if (needs.has("goggles")) addLine("雪镜", rentalOrderPriceTable.goggles[tierKey]);
    if (needs.has("gloves")) addLine("手套(含一次性内胆)", rentalOrderPriceTable.gloves[tierKey]);

    if (needs.has("board") && needs.has("boots")) {
      addLine("板鞋杖（最低组合价）", rentalOrderPriceTable.boardBootsPoles[tierKey]);
    } else {
      if (needs.has("board")) addLine("雪板（双板含雪杖）", rentalOrderPriceTable.board[tierKey]);
      if (needs.has("boots")) addLine("雪鞋", rentalOrderPriceTable.boots[tierKey]);
    }

    if (needs.has("turtleProtector")) addLine("小乌龟护具", rentalOrderPriceTable.turtleProtector[tierKey]);
    if (needs.has("innerProtector")) addLine("内穿护具", rentalOrderPriceTable.innerProtector[tierKey]);
  }

  if (needs.has("socks")) addLine("雪袜（零售）", rentalOrderPriceTable.socks[tierKey]);
  if (needs.has("faceCover")) addLine("面罩（零售）", rentalOrderPriceTable.faceCover[tierKey]);

  const total = lines.reduce((sum, line) => sum + line.amount, 0);
  return { lines, total };
}

function calculateRentalOrderPricing(selectedNeeds) {
  return ["agency", "preferred", "regular"].reduce((pricing, tierKey) => {
    const result = calculateRentalOrderLines(selectedNeeds, tierKey);
    return {
      ...pricing,
      [tierKey]: {
        label: rentalOrderTierLabels[tierKey],
        total: formatCurrency(result.total),
        lines: result.lines.map((line) => ({
          item: line.label,
          amount: formatCurrency(line.amount)
        }))
      }
    };
  }, {});
}

function createInitialCalculatorState() {
  return {
    resort: "teine",
    guestCount: 2,
    rideOnlyCount: 0,
    coachHours: 2,
    liftPassHours: 4,
    peakSeason: false,
    englishTeaching: false,
    selectedServices: ["sharedTransfer", "rental", "coach", "liftPassDay"]
  };
}

function applyPackagePreset(current, presetKey) {
  const skierCount = Math.max(0, Number(current.guestCount) || 0);
  const rideOnlyCount = Math.max(0, Number(current.rideOnlyCount) || 0);
  const riderCount = skierCount + rideOnlyCount;
  const premiumTransfer = riderCount >= 7 ? "privateTransfer10" : "privateTransfer7";

  if (presetKey === "beginner") {
    return {
      ...current,
      coachHours: 4,
      liftPassHours: 4,
      selectedServices: ["sharedTransfer", "rental", "coach", "liftPassHourly"]
    };
  }

  if (presetKey === "free") {
    return {
      ...current,
      liftPassHours: 4,
      selectedServices: ["sharedTransfer", "rental", "liftPassDay"]
    };
  }

  if (presetKey === "premium") {
    return {
      ...current,
      coachHours: 5,
      liftPassHours: 4,
      selectedServices: [premiumTransfer, "vip", "rentalWithProtectors", "coach", "liftPassDay"]
    };
  }

  return current;
}

function toggleServiceInList(selectedServices, serviceKey) {
  let nextServices = selectedServices.includes(serviceKey)
    ? selectedServices.filter((key) => key !== serviceKey)
    : [...selectedServices, serviceKey];

  if (serviceKey === "rental" && nextServices.includes("rental")) {
    nextServices = nextServices.filter((key) => key !== "rentalWithProtectors");
  }

  if (serviceKey === "rentalWithProtectors" && nextServices.includes("rentalWithProtectors")) {
    nextServices = nextServices.filter((key) => key !== "rental");
  }

  if (serviceKey === "liftPassHourly" && nextServices.includes("liftPassHourly")) {
    nextServices = nextServices.filter((key) => key !== "liftPassDay");
  }

  if (serviceKey === "liftPassDay" && nextServices.includes("liftPassDay")) {
    nextServices = nextServices.filter((key) => key !== "liftPassHourly");
  }

  if (serviceKey === "privateTransfer7" && nextServices.includes("privateTransfer7")) {
    nextServices = nextServices.filter((key) => key !== "privateTransfer10");
  }

  if (serviceKey === "privateTransfer10" && nextServices.includes("privateTransfer10")) {
    nextServices = nextServices.filter((key) => key !== "privateTransfer7");
  }

  return nextServices;
}

function App() {
  if (window.JQ_PAGE === "partner") {
    return (
      <StandaloneCalculatorPage
        eyebrow="Partner Calculator"
        title="合作者二手单价计算器"
        description="给合作推广者使用，结果只显示二手单价/客人线下优惠与客人原价，方便核算对外报价空间。"
        tiers={[
          { key: "preferred", label: "二手单价 / 客人线下优惠" },
          { key: "regular", label: "客人原价" }
        ]}
      />
    );
  }

	  if (window.JQ_PAGE === "agency") {
	    return (
      <StandaloneCalculatorPage
        eyebrow="Agency Calculator"
        title="旅行社价格计算器"
        description="给旅行社与大客户使用，同时显示旅行社价、二手单价/客人线下优惠和客人原价。"
        tiers={[
          { key: "agency", label: "旅行社价" },
          { key: "preferred", label: "二手单价 / 客人线下优惠" },
          { key: "regular", label: "客人原价" }
        ]}
      />
	    );
	  }

  if (window.JQ_PAGE === "rental") {
    return <RentalOrderPage />;
  }

  const [quote, setQuote] = useState({
    customerType: "regular",
    ...createInitialCalculatorState()
  });
  const [activeQuotePreset, setActiveQuotePreset] = useState("custom");
  const [contact, setContact] = useState({
    contactName: "",
    contactMethod: ""
  });
  const [guests, setGuests] = useState([
    { ...guestTemplate, name: "客人 1" },
    { ...guestTemplate, name: "客人 2" }
  ]);
  const [orderOutput, setOrderOutput] = useState("订单文本将在提交后显示。");
  const [copyStatus, setCopyStatus] = useState("复制订单");

  const quoteResult = useMemo(() => {
    const tierKey = customerTiers[quote.customerType].priceKey;
    const { total, lines } = calculateQuoteLines(quote, tierKey);
    const breakdown = lines.map((line) => `${line.label} ${formatCurrency(line.amount)}`).join(" / ");

    return {
      total,
      lines,
      breakdown: breakdown || "请选择服务内容"
    };
  }, [quote]);

  const updateQuote = (key, value) => {
    setQuote((current) => ({ ...current, [key]: value }));
    if (key !== "guestCount") {
      setActiveQuotePreset("custom");
    }
  };

  const chooseQuotePackage = (presetKey) => {
    setQuote((current) => applyPackagePreset(current, presetKey));
    setActiveQuotePreset(presetKey);
  };

  const toggleQuoteService = (serviceKey) => {
    setQuote((current) => {
      return { ...current, selectedServices: toggleServiceInList(current.selectedServices, serviceKey) };
    });
    setActiveQuotePreset("custom");
  };

  const updateGuest = (index, key, value) => {
    setGuests((current) =>
      current.map((guest, guestIndex) =>
        guestIndex === index ? { ...guest, [key]: value } : guest
      )
    );
  };

  const toggleGuestNeed = (index, need) => {
    setGuests((current) =>
      current.map((guest, guestIndex) => {
        if (guestIndex !== index) return guest;
        const needs = guest.needs.includes(need)
          ? guest.needs.filter((item) => item !== need)
          : [...guest.needs, need];
        return { ...guest, needs };
      })
    );
  };

  const addGuest = () => {
    setGuests((current) => [
      ...current,
      { ...guestTemplate, name: `客人 ${current.length + 1}` }
    ]);
  };

  const removeGuest = (index) => {
    setGuests((current) => current.filter((_, guestIndex) => guestIndex !== index));
  };

  const getRentalGuestRegularTotal = (guest) => calculateRentalOrderLines(guest.needs, "regular").total;
  const rentalOrderTotal = guests.reduce((sum, guest) => sum + getRentalGuestRegularTotal(guest), 0);

  const buildOrder = () => {
    const lines = [
      "金泉国际租赁 / 零售订单",
      `联系人：${contact.contactName || "未填写"}`,
      `联系方式：${contact.contactMethod || "未填写"}`,
      `客人价总计：${formatCurrency(rentalOrderTotal)}`,
      ""
    ];

    guests.forEach((guest, index) => {
      const rentalResult = calculateRentalOrderLines(guest.needs, "regular");
      lines.push(`客人 ${index + 1}：${guest.name || "未填写"}`);
      lines.push(`身高：${guest.height || "未填写"} cm`);
      lines.push(`体重：${guest.weight || "未填写"} kg`);
      lines.push(`鞋码：${guest.shoeSize || "未填写"} cm`);
      lines.push(`滑雪偏好：${guest.preference}`);
      lines.push("租赁 / 零售内容：");
      if (rentalResult.lines.length > 0) {
        rentalResult.lines.forEach((line) => {
          lines.push(`- ${line.label}：${formatCurrency(line.amount)}`);
        });
      } else {
        lines.push("- 未选择");
      }
      lines.push(`客人价小计：${formatCurrency(rentalResult.total)}`);
      lines.push("");
    });

    return lines.join("\n").trim();
  };

  const submitOrder = (event) => {
    event.preventDefault();
    setOrderOutput(buildOrder());
    setCopyStatus("复制订单");
  };

  const copyOrder = async () => {
    const data = buildOrder();
    setOrderOutput(data);
    try {
      await navigator.clipboard.writeText(data);
      setCopyStatus("已复制");
    } catch {
      setCopyStatus("请手动复制");
    }
  };

  return (
    <>
      <SkiTrailProgress />

      <main className="home-main">
        <HomeHero />
        <IntroSection />
        <HomeServicesSection />
        <HomePackagePricingSection />
        <HomeCompanySection />
        <HomeReviewsSection />
        <ContactSection />
      </main>

      <footer className="site-footer">
        <p>© 2026 KINSEN International. 北海道滑雪教学、租赁、接送与定制服务。</p>
      </footer>
    </>
  );
}

function SkiTrailProgress() {
  const pathRef = useRef(null);
  const skierRef = useRef(null);
  const frameRef = useRef(null);

  useEffect(() => {
    const clamp = (value, min, max) => Math.max(min, Math.min(max, value));

    const updateSkier = () => {
      const path = pathRef.current;
      const skier = skierRef.current;
      if (!path || !skier) return;

      const scrollable = Math.max(1, document.documentElement.scrollHeight - window.innerHeight);
      const progress = clamp(window.scrollY / scrollable, 0, 1);
      const pathLength = path.getTotalLength();
      const distance = pathLength * progress;
      const currentPoint = path.getPointAtLength(distance);
      const nextPoint = path.getPointAtLength(clamp(distance + 6, 0, pathLength));
      const angle = (Math.atan2(nextPoint.y - currentPoint.y, nextPoint.x - currentPoint.x) * 180) / Math.PI;

      const scale = window.innerWidth < 720 ? 0.72 : 0.86;
      skier.setAttribute("transform", `translate(${currentPoint.x} ${currentPoint.y}) rotate(${angle + 8}) scale(${scale})`);
    };

    const requestUpdate = () => {
      if (frameRef.current) return;
      frameRef.current = requestAnimationFrame(() => {
        frameRef.current = null;
        updateSkier();
      });
    };

    updateSkier();
    window.addEventListener("scroll", requestUpdate, { passive: true });
    window.addEventListener("resize", requestUpdate);

    return () => {
      window.removeEventListener("scroll", requestUpdate);
      window.removeEventListener("resize", requestUpdate);
      if (frameRef.current) cancelAnimationFrame(frameRef.current);
    };
  }, []);

  return (
    <div className="ski-trail-progress" aria-hidden="true">
      <svg viewBox="0 0 1000 1400" preserveAspectRatio="xMidYMid slice">
        <defs>
          <linearGradient id="trailSky" x1="0" x2="1" y1="0" y2="1">
            <stop offset="0%" stopColor="#dff5ff" />
            <stop offset="52%" stopColor="#f8fcff" />
            <stop offset="100%" stopColor="#fff7df" />
          </linearGradient>
          <linearGradient id="trailGold" x1="0" x2="1" y1="0" y2="0">
            <stop offset="0%" stopColor="#f4c34e" />
            <stop offset="100%" stopColor="#d79a1f" />
          </linearGradient>
        </defs>
        <rect width="1000" height="1400" fill="url(#trailSky)" />
        <circle cx="834" cy="155" r="96" fill="#f8d36b" opacity="0.48" />
        <path d="M-40 420 L178 130 L330 374 L456 172 L712 494 Z" fill="#cfeaff" />
        <path d="M125 203 L178 130 L224 204 L188 190 L162 216 Z" fill="#ffffff" opacity="0.9" />
        <path d="M318 340 L456 172 L572 390 L488 354 L438 392 Z" fill="#ffffff" opacity="0.92" />
        <path d="M94 566 C214 492 302 494 424 546 C560 604 686 575 844 500 C904 472 958 456 1040 465 L1040 1400 L-40 1400 L-40 614 C7 604 48 594 94 566 Z" fill="#ffffff" />
        <path d="M740 118 C660 238 804 310 684 420 C566 528 732 622 608 736 C484 850 682 958 558 1082 C493 1147 514 1220 626 1288" fill="none" stroke="#ffffff" strokeLinecap="round" strokeWidth="74" opacity="0.9" />
        <path ref={pathRef} className="ski-trail-line" d="M740 118 C660 238 804 310 684 420 C566 528 732 622 608 736 C484 850 682 958 558 1082 C493 1147 514 1220 626 1288" fill="none" stroke="url(#trailGold)" strokeDasharray="10 24" strokeLinecap="round" strokeWidth="10" />
        <g ref={skierRef} className="progress-skier" transform="translate(740 118)">
          <path d="M-21 17 C-2 26 17 24 34 13" fill="none" stroke="#0c2e50" strokeLinecap="round" strokeWidth="5" />
          <circle cx="-2" cy="-21" r="9" fill="#f4c34e" />
          <path d="M-7 -10 L11 4 L-4 15 L-18 4 Z" fill="#0c4b79" />
          <path d="M6 2 L21 11" stroke="#0c2e50" strokeLinecap="round" strokeWidth="5" />
          <path d="M-9 6 L-24 15" stroke="#0c2e50" strokeLinecap="round" strokeWidth="5" />
          <path d="M12 -2 L27 -13" stroke="#d79a1f" strokeLinecap="round" strokeWidth="4" />
        </g>
      </svg>
    </div>
  );
}

function IntroSection() {
  const cards = [
    ["札幌区域", "札幌国际", "粉雪稳定、雪道宽阔，适合半日教学、亲子体验与希望稳扎稳打练习转弯的客人。"],
    ["札幌区域", "ONZE / 朝里川", "交通灵活，适合夜滑、短途体验和小团队轻量行程，装备与接送可按需组合。"],
    ["度假区", "二世谷 Niseko", "适合深度滑雪假期、粉雪爱好者与多日行程，可搭配私教和全套装备服务。"],
    ["度假区", "留寿都 Rusutsu", "更适合家庭、大团和高品质定制出行，可按返程时间与教学节奏灵活安排。"]
  ];

  return (
    <section className="home-section brochure-resorts-section" aria-labelledby="intro-title">
      <div className="home-section-heading">
        <div>
          <div className="home-section-kicker">01 / Destinations</div>
          <h2 id="intro-title">我们支持的顶级雪场</h2>
        </div>
        <p>覆盖札幌近郊与北海道度假区，既适合第一次滑雪的家庭和自由行客人，也能承接多日粉雪行程与高端定制服务。</p>
      </div>
      <div className="brochure-resort-layout">
        <article className="brochure-resort-feature">
          <img src={tripImages.seaView} alt="手稻滑雪场海景雪道" />
          <div className="brochure-resort-overlay">
            <span>札幌区域 · Olympic course</span>
            <h3>手稻滑雪场 Sapporo Teine</h3>
            <p>1972 冬奥赛道所在地，天气晴朗时可俯瞰石狩湾与札幌市区，是新手进阶和海景拍摄的高人气雪场。</p>
          </div>
        </article>
        <div className="brochure-resort-grid">
          {cards.map(([area, title, body]) => (
            <article key={title}>
              <span>{area}</span>
              <h3>{title}</h3>
              <p>{body}</p>
            </article>
          ))}
        </div>
      </div>
    </section>
  );
}

function HomeHero() {
  const coverPills = ["国际认证教练", "中英双语教学", "全套装备", "上门接送", "私人定制"];

  return (
    <section className="home-hero" aria-labelledby="hero-title">
      <div className="hero-video-bg" aria-hidden="true">
        <img src={tripImages.seaView} alt="" />
      </div>
      <div className="home-hero-content brochure-cover-hero">
        <div className="hero-brand-lockup">
          <span className="hero-brand-mark">
            <img src={logoImage} alt="" />
          </span>
          <div>
            <strong>金泉国际</strong>
            <small>KINSEN INTERNATIONAL</small>
          </div>
        </div>
        <div className="hero-copy-block brochure-cover-copy">
          <p className="hero-news-pill">HOKKAIDO PREMIUM SKI SERVICE</p>
          <h1 id="hero-title">北海道高品质滑雪管家</h1>
          <p className="brochure-hero-subtitle">专注您的每一次滑行体验</p>
          <p>
            从酒店接送、雪具准备到专业教学与影像记录，一站式安排北海道粉雪旅程，让第一次滑雪也能从容、安全、尽兴。
          </p>
          <div className="brochure-cover-pills" aria-label="服务亮点">
            {coverPills.map((pill) => (
              <span key={pill}>{pill}</span>
            ))}
          </div>
          <div className="home-hero-actions">
            <a className="primary-button" href="#services">查看套餐</a>
            <a className="secondary-button" href="#contact">联系顾问</a>
          </div>
        </div>
        <div className="brochure-hero-footer">
          <span>SAPPORO · NISEKO · RUSUTSU</span>
          <span>2026 SKI SERVICE GUIDE</span>
        </div>
      </div>
    </section>
  );
}

function HeroMountainIllustration() {
  const servicePins = [
    { x: 552, y: 184, label: "Teine", note: "海景雪场" },
    { x: 426, y: 312, label: "Lesson", note: "中英文教学" },
    { x: 564, y: 446, label: "Rental", note: "装备租赁" },
    { x: 394, y: 568, label: "Transfer", note: "接送安排" }
  ];

  return (
    <div className="hero-visual-panel hero-map-card" aria-hidden="true">
      <svg className="hero-mountain-map" viewBox="0 0 720 640" role="img">
        <defs>
          <linearGradient id="heroSky" x1="0" x2="1" y1="0" y2="1">
            <stop offset="0%" stopColor="#dff5ff" />
            <stop offset="56%" stopColor="#f8fcff" />
            <stop offset="100%" stopColor="#fff7db" />
          </linearGradient>
          <linearGradient id="heroMountainBlue" x1="0" x2="1" y1="0" y2="1">
            <stop offset="0%" stopColor="#f7fcff" />
            <stop offset="45%" stopColor="#9ed0ed" />
            <stop offset="100%" stopColor="#0c4b79" />
          </linearGradient>
          <linearGradient id="heroGold" x1="0" x2="1" y1="0" y2="0">
            <stop offset="0%" stopColor="#f7d875" />
            <stop offset="100%" stopColor="#d79a1f" />
          </linearGradient>
          <filter id="heroSoftShadow" x="-20%" y="-20%" width="140%" height="140%">
            <feDropShadow dx="0" dy="18" stdDeviation="18" floodColor="#082744" floodOpacity="0.16" />
          </filter>
        </defs>

        <rect width="720" height="640" rx="34" fill="url(#heroSky)" />
        <circle cx="598" cy="112" r="58" fill="#f4c34e" opacity="0.48" />
        <path d="M-18 532 C94 460 178 452 294 504 C430 565 532 548 742 438 L742 640 L-18 640 Z" fill="#ffffff" />
        <path d="M34 468 L202 166 L316 468 Z" fill="#bfe5fa" />
        <path d="M146 468 L382 82 L638 468 Z" fill="url(#heroMountainBlue)" filter="url(#heroSoftShadow)" />
        <path d="M322 468 L512 190 L744 468 Z" fill="#7fb8d8" opacity="0.78" />
        <path d="M350 134 L382 82 L442 174 L397 154 L368 184 Z" fill="#ffffff" opacity="0.92" />
        <path d="M178 210 L202 166 L226 216 L204 206 L188 224 Z" fill="#ffffff" opacity="0.92" />
        <path d="M498 212 L512 190 L548 244 L519 232 L501 250 Z" fill="#ffffff" opacity="0.86" />

        <path className="hero-map-snow-road-base" d="M548 162 C450 216 594 292 472 354 C342 420 532 484 406 548 C350 576 332 604 356 628" fill="none" stroke="#ffffff" strokeLinecap="round" strokeWidth="48" opacity="0.96" />
        <path className="hero-map-snow-road" d="M548 162 C450 216 594 292 472 354 C342 420 532 484 406 548 C350 576 332 604 356 628" fill="none" stroke="url(#heroGold)" strokeDasharray="12 18" strokeLinecap="round" strokeWidth="8" />

        <g className="hero-map-mini-skier" transform="translate(478 356) rotate(22) scale(.72)">
          <path d="M-24 18 C-8 26 18 24 35 14" fill="none" stroke="#06213d" strokeLinecap="round" strokeWidth="5" />
          <circle cx="-2" cy="-20" r="9" fill="#f4c34e" />
          <path d="M-7 -10 L11 3 L-4 15 L-18 4 Z" fill="#0c4b79" />
          <path d="M6 2 L23 11" stroke="#06213d" strokeLinecap="round" strokeWidth="5" />
          <path d="M12 -2 L29 -14" stroke="#d79a1f" strokeLinecap="round" strokeWidth="4" />
        </g>

        {servicePins.map((pin, index) => (
          <g className="hero-service-pin" key={pin.label} style={{ "--pin-delay": `${index * 110}ms` }} transform={`translate(${pin.x} ${pin.y})`}>
            <circle r="8" fill="#f4c34e" />
            <circle r="18" fill="none" stroke="#f4c34e" strokeWidth="2" opacity="0.42" />
            <foreignObject x="-76" y="22" width="152" height="62">
              <div className="hero-pin-label">
                <strong>{pin.label}</strong>
                <span>{pin.note}</span>
              </div>
            </foreignObject>
          </g>
        ))}
      </svg>
      <div className="hero-map-caption">
        <strong>Hokkaido service map</strong>
        <span>课程、装备、接送和雪卡按同一张行程表确认</span>
      </div>
    </div>
  );
}

function HomeServicesSection() {
  const packages = [
    {
      index: "01",
      title: "新手全包套餐",
      tag: "零基础圆梦",
      image: tripImages.family,
      summary: "适合第一次滑雪、亲子家庭，以及希望把接送、装备、教学一次安排清楚的客人。",
      highlight: "包含雪场拼车接送、全套专业雪具租赁、4 小时教学与 4 小时雪卡，按照新手节奏安排集合、取装、上雪和返程。",
      bullets: ["拼车接送", "全套雪具", "4 小时教学", "4 小时雪卡"]
    },
    {
      index: "02",
      title: "自由行体验套餐",
      tag: "灵活随心",
      image: "/pics/trip/03.jpeg",
      summary: "适合会滑、短途体验或希望保留更多自由活动时间的客人。",
      highlight: "包含雪场拼车接送、全套雪具租赁与全天雪卡；如需教练、摄影或定制路线，可按当天需求继续加购。",
      bullets: ["拼车接送", "全套雪具", "全天雪卡", "适合自由行"]
    },
    {
      index: "03",
      title: "高端服务套餐",
      tag: "尊享定制",
      image: tripImages.lounge,
      summary: "适合商务接待、旅行社团队、小团体以及更看重节奏、私密性和舒适度的客人。",
      highlight: "包含专属专车接送、雪场 VIP 厅、含护具的高端雪具租赁、5 小时教学和全天雪卡，服务链路更完整。",
      bullets: ["专车接送", "VIP 厅", "含护具租赁", "5 小时教学"]
    }
  ];

  return (
    <section className="home-section home-services" id="services" aria-labelledby="services-title">
      <div className="home-section-heading">
        <div>
          <div className="home-section-kicker">02 / Packages</div>
          <h2 id="services-title">核心服务套餐</h2>
        </div>
        <p>针对不同需求的客群，我们把最常见的滑雪服务整理成三类标准化产品，方便快速理解和选择。</p>
      </div>
      <div className="brochure-package-list">
        {packages.map((item) => (
          <article className="brochure-package-card" key={item.title}>
            <div className="brochure-package-copy">
              <span className="brochure-package-index">{item.index}</span>
              <div className="brochure-package-head">
                <h3>{item.title}</h3>
                <small>{item.tag}</small>
              </div>
              <p className="brochure-package-summary"><strong>{item.summary}</strong></p>
              <p>{item.highlight}</p>
              <div className="brochure-package-tags" aria-label={`${item.title}包含内容`}>
                {item.bullets.map((point) => (
                  <span key={point}>{point}</span>
                ))}
              </div>
            </div>
            <div className="brochure-package-media">
              <img src={item.image} alt={item.title} />
            </div>
          </article>
        ))}
      </div>
      <div className="brochure-package-note">
        <p>也售卖单独的零散服务，也承接滑雪研学团、企业团建和旅行社团队的定制需求。</p>
        <a href="#contact">联系我们获取完整方案</a>
      </div>
    </section>
  );
}

function HomePackagePricingSection() {
  const [guestCount, setGuestCount] = useState(2);
  const packageRows = [
    { label: "雪场接送", beginner: "拼车", free: "拼车", premium: "专车" },
    { label: "全套雪具", beginner: "check", free: "check", premium: "额外提供护具" },
    { label: "门票雪卡", beginner: "4小时", free: "全天", premium: "全天" },
    { label: "教学", beginner: "4小时", free: "", premium: "5小时" },
    { label: "雪场VIP厅", beginner: "", free: "", premium: "check" }
  ];
  const packageColumns = [
    { key: "free", title: "自由行体验套餐", note: "会滑 / 轻量出行" },
    { key: "beginner", title: "新手全包套餐", note: "零基础 / 亲子首滑" },
    { key: "premium", title: "高端服务套餐", note: "专车 / VIP / 私教" }
  ];
  const packagePrices = packageColumns.reduce((prices, column) => {
    const quote = applyPackagePreset({ ...createInitialCalculatorState(), guestCount }, column.key);
    prices[column.key] = calculateQuoteLines(quote, "regular").total;
    return prices;
  }, {});

  return (
    <section className="home-section guest-package-pricing" id="quote" aria-labelledby="guest-pricing-title">
      <div className="home-section-heading">
        <div>
          <div className="home-section-kicker">02B / Pricing</div>
          <h2 id="guest-pricing-title">客人套餐价格</h2>
        </div>
        <p>选择人数后，下面的套餐价格会按官网客人价自动更新，适合先快速判断预算范围。</p>
      </div>
      <div className="people-selector service-people-selector" aria-label="选择人数">
        <span>人数</span>
        <div>
          {[1, 2, 3, 4, 5, 6, 7, 8].map((count) => (
            <button
              className={guestCount === count ? "active" : ""}
              key={count}
              type="button"
              onClick={() => setGuestCount(count)}
            >
              {count}
            </button>
          ))}
        </div>
      </div>
      <div className="service-pricing-card">
        <div className="package-table-wrap">
          <table className="package-compare-table">
            <thead>
              <tr>
                <th>服务内容</th>
                {packageColumns.map((column) => (
                  <th key={column.key}>
                    <strong>{column.title}</strong>
                    <small>{column.note}</small>
                    <b>{formatCurrency(packagePrices[column.key])}</b>
                  </th>
                ))}
              </tr>
            </thead>
            <tbody>
              {packageRows.map((row) => (
                <tr key={row.label}>
                  <td>{row.label}</td>
                  {packageColumns.map((column) => (
                    <td key={column.key}>
                      {row[column.key] === "check" ? <span className="check-mark">✓</span> : row[column.key] ? <em>{row[column.key]}</em> : <span className="dash">—</span>}
                    </td>
                  ))}
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </div>
      <p className="service-note">
        以上为官网展示的客人套餐价格。零散服务、团队和定制方案可单独沟通。
        <a href="#contact">联系我们</a>
      </p>
    </section>
  );
}

function HomeCompanySection() {
  return (
    <section className="home-section company-section" id="about" aria-labelledby="company-title">
      <div className="home-section-heading">
        <div>
          <div className="home-section-kicker">03 / About</div>
          <h2 id="company-title">公司介绍</h2>
        </div>
        <p>我们把装备、教练、交通和订单确认做成标准流程，让高品质滑雪服务更稳定。</p>
      </div>
      <div className="company-grid">
        <article className="gear-intro-card">
          <div className="gear-visual">
            <img src="/pics/gears/e5cdc9df-877d-4383-8492-0fe1b41ad0f9.png" alt="雪服雪具装备展示" />
          </div>
          <div>
            <span>Equipment system</span>
            <h3>雪服雪具与规范点单系统</h3>
            <p>
              按每位客人的身高、体重、鞋码和单/双板偏好提前准备装备。规范点单系统减少沟通遗漏，现场取装更高效。
            </p>
            <p className="brand-line">Atomic / Salomon / Rossignol / Head / Fischer / K2 / Ogasaka</p>
            <a className="text-button" href="/rental.html">进入点单系统</a>
          </div>
        </article>
        <article className="coach-intro-card">
          <span>Coaching team</span>
          <h3>教练团队</h3>
          <p>
            中英文教学，教练均具备国际教练证背景。我们重视滑雪技术、安全判断，也重视沟通体验、情绪价值和现场节奏。
          </p>
          <div className="coach-points">
            <b>国际教练证</b>
            <b>中英双语</b>
            <b>亲子友好</b>
            <b>会教也会拍</b>
          </div>
        </article>
      </div>
    </section>
  );
}

function HomeTrustSection() {
  const trustItems = [
    ["Local Experience", "熟悉札幌近郊雪场天气、路线、集合点和适合新手的坡道。"],
    ["Multi-language", "中文沟通，英文教学可选，减少旅行中的信息差。"],
    ["Certified Coaches", "教练团队具备国际教练证背景，重视安全与动作反馈。"],
    ["Reliable Operations", "装备提前整理、司机准时接送、订单信息结构化确认。"]
  ];

  return (
    <section className="home-section home-trust" aria-labelledby="trust-title">
      <div>
        <div className="home-section-kicker">Why trust us</div>
        <h2 id="trust-title">适合第一次来北海道滑雪，也适合要求更高的家庭和团队。</h2>
      </div>
      <div className="trust-list">
        {trustItems.map(([title, body]) => (
          <article key={title}>
            <strong>{title}</strong>
            <p>{body}</p>
          </article>
        ))}
      </div>
    </section>
  );
}

function HomeJourneysSection() {
  const journeys = [
    {
      image: tripImages.seaView,
      location: "Sapporo Teine",
      title: "海景滑雪一日体验",
      audience: "适合情侣、朋友、喜欢拍照的客人",
      points: ["俯瞰石狩湾", "札幌市区出发", "可加私教与拍摄点引导"]
    },
    {
      image: tripImages.family,
      location: "Sapporo Kokusai",
      title: "亲子初学全包日",
      audience: "适合家庭、儿童和零基础成人",
      points: ["装备提前准备", "中文教练陪同", "节奏更稳妥"]
    },
    {
      image: tripImages.lesson,
      location: "Powder Day",
      title: "粉雪教学与进阶",
      audience: "适合已经滑过、想提升动作的客人",
      points: ["路线选择建议", "动作纠正", "可安排多小时课程"]
    },
    {
      image: tripImages.lounge,
      location: "Private Service",
      title: "专车与高端陪同",
      audience: "适合商务、小团和高品质旅行",
      points: ["专车等候", "VIP厅可选", "行程可定制"]
    }
  ];

  return (
    <section className="home-section" id="journeys" aria-labelledby="journeys-title">
      <div className="home-section-kicker">Selected tours</div>
      <div className="home-section-heading">
        <h2 id="journeys-title">精选服务与行程</h2>
        <p>每个行程都可以按人数、滑雪水平、预算和想去的雪场重新组合。</p>
      </div>
      <div className="journey-rail">
        {journeys.map((journey) => (
          <article className="journey-card" key={journey.title}>
            <img src={journey.image} alt={journey.title} />
            <div>
              <span>{journey.location}</span>
              <h3>{journey.title}</h3>
              <p>{journey.audience}</p>
              <ul>
                {journey.points.map((point) => <li key={point}>{point}</li>)}
              </ul>
              <a href="#contact">咨询行程</a>
            </div>
          </article>
        ))}
      </div>
    </section>
  );
}

function HomeGallerySection() {
  return (
    <section className="home-gallery" aria-label="真实客人滑雪照片">
      <img src={tripImages.powder} alt="客人在北海道雪场教学中" />
      <img src={tripImages.seaView} alt="手稻雪场海景拍照" />
      <img src={tripImages.family} alt="亲子滑雪体验" />
    </section>
  );
}

function HomeAboutSection() {
  return (
    <section className="home-section home-about" id="about" aria-labelledby="about-title">
      <div>
        <div className="home-section-kicker">About KINSEN</div>
        <h2 id="about-title">我们把滑雪旅行里最麻烦的部分，提前处理好。</h2>
      </div>
      <p>
        KINSEN 长期服务来北海道滑雪的中文客人。我们理解第一次上雪道的不安，也理解家庭、商务和高端小团对时间、舒适度和沟通效率的要求。好的滑雪体验不是把服务堆满，而是在该出现的时候有人负责。
      </p>
    </section>
  );
}

function HomeReviewsSection() {
  const railRef = useRef(null);
  const resumeTimerRef = useRef(null);
  const pausedRef = useRef(false);

  useEffect(() => {
    const rail = railRef.current;
    if (!rail) return undefined;

    let frameId;
    let lastTime;
    const speed = 28;

    const tick = (time) => {
      if (lastTime === undefined) lastTime = time;
      const delta = time - lastTime;
      lastTime = time;

      if (!pausedRef.current) {
        rail.scrollLeft += (speed * delta) / 1000;
        const halfway = rail.scrollWidth / 2;
        if (rail.scrollLeft >= halfway) rail.scrollLeft -= halfway;
      }

      frameId = requestAnimationFrame(tick);
    };

    frameId = requestAnimationFrame(tick);
    return () => {
      cancelAnimationFrame(frameId);
      if (resumeTimerRef.current) clearTimeout(resumeTimerRef.current);
    };
  }, []);

  const pauseReviews = () => {
    pausedRef.current = true;
    if (resumeTimerRef.current) clearTimeout(resumeTimerRef.current);
    resumeTimerRef.current = setTimeout(() => {
      pausedRef.current = false;
    }, 5000);
  };

  const reviewLoopImages = [...commentImages, ...commentImages];

  return (
    <section className="home-section home-reviews" id="reviews" aria-labelledby="reviews-title">
      <div className="home-section-heading">
        <div>
          <div className="home-section-kicker">04 / Reviews</div>
          <h2 id="reviews-title">来自十几个国家客人的真实口碑</h2>
        </div>
        <p>服务已在各大主流平台上架，覆盖亲子家庭、自由行客人、留学生、研学团与企业团队。历史反馈持续积累，好评如潮。</p>
      </div>
      <div
        className="review-image-rail"
        onPointerDown={pauseReviews}
        onTouchStart={pauseReviews}
        onWheel={pauseReviews}
        ref={railRef}
      >
        {reviewLoopImages.map((src, index) => (
          <figure key={`${src}-${index}`}>
            <img src={src} alt={`客人好评截图 ${(index % commentImages.length) + 1}`} />
          </figure>
        ))}
      </div>
    </section>
  );
}

function MobileContactBar() {
  return (
    <nav className="mobile-contact-bar" aria-label="快速联系">
      <a href="#contact">WeChat</a>
      <a href="#contact">LINE</a>
      <a href="mailto:booking@jinquan-ski.jp">Email</a>
      <a className="primary" href="#contact">Inquiry</a>
    </nav>
  );
}

function TeamSection() {
  return (
    <section className="section team-band" aria-labelledby="team-title">
      <div>
        <p className="eyebrow">Coaches</p>
        <h2 id="team-title">国际教练证团队，中文与英文双语教学</h2>
        <p>
          教练团队熟悉成人零基础、亲子初学、单板入门和双板平行式进阶路径。教学过程兼顾安全、节奏和拍照体验，让客人从集合到返程都有明确安排。
        </p>
      </div>
      <div className="coach-list" aria-label="教练团队能力">
        <span>国际教练证</span>
        <span>中英文双语</span>
        <span>亲子友好</span>
        <span>网红照协助</span>
      </div>
    </section>
  );
}

function PackagesSection() {
  const packages = [
    {
      title: "新手全包套餐",
      tag: "人气推荐",
      className: "featured",
      intro: "适合第一次滑雪、家庭亲子和希望省心出行的客人。",
      items: ["雪场拼车接送", "全套雪具租赁", "教练全程教学", "门票雪卡安排"]
    },
    {
      title: "自由行体验套餐",
      tag: "轻量体验",
      intro: "适合会滑或只需要交通、装备和雪卡的自由行客人。",
      items: ["雪场拼车接送", "雪具与服装租赁", "门票雪卡安排", "可加购拍摄点引导"]
    },
    {
      title: "高端服务套餐",
      tag: "高端定制",
      className: "premium",
      intro: "适合商务、旅行社、大客户和追求私密行程的客人。",
      items: ["专车接送，司机专属等候", "雪场 VIP 厅", "全套装备与雪卡", "定制化私教服务"]
    }
  ];

  return (
    <section className="section packages-section" id="packages" aria-labelledby="packages-title">
      <SectionHeading eyebrow="Packages" title="三类标准化产品套餐" id="packages-title" />
      <div className="package-grid">
        {packages.map((item) => (
          <article className={`package-card ${item.className || ""}`} key={item.title}>
            <span className="tag">{item.tag}</span>
            <h3>{item.title}</h3>
            <p>{item.intro}</p>
            <ul>
              {item.items.map((point) => (
                <li key={point}>{point}</li>
              ))}
            </ul>
          </article>
        ))}
      </div>
    </section>
  );
}

function QuickPackageSelector({ activePreset, onSelect }) {
  const activeTitle = packagePresets.find((preset) => preset.key === activePreset)?.title || "自定义方案";

  return (
    <div className="quick-packages" aria-label="快捷套餐">
      <div className="quick-packages-heading">
        <span>快捷套餐</span>
        <em>{activeTitle}</em>
      </div>
      <div className="quick-package-grid">
        {packagePresets.map((preset) => {
          const selected = activePreset === preset.key;
          return (
            <button
              className={selected ? "selected" : ""}
              key={preset.key}
              type="button"
              onClick={() => onSelect(preset.key)}
              aria-pressed={selected}
              aria-label={`${preset.title}：${preset.description}`}
              title={preset.description}
            >
              <span className="package-copy">
                <b>{preset.title}</b>
              </span>
            </button>
          );
        })}
      </div>
    </div>
  );
}

function SkierCountSlider({ value, onChange }) {
  const currentValue = Math.max(0, Math.min(9, Number(value) || 0));

  return (
    <div className="skier-slider">
      <div className="skier-slider-heading">
        <span>滑雪人数</span>
        <strong>{currentValue} 人</strong>
      </div>
      <input
        type="range"
        min="0"
        max="9"
        step="1"
        value={currentValue}
        onChange={(event) => onChange("guestCount", event.target.value)}
        aria-label="滑雪人数"
      />
      <div className="slider-ticks" aria-hidden="true">
        {Array.from({ length: 10 }, (_, index) => (
          <span key={index}>{index}</span>
        ))}
      </div>
    </div>
  );
}

function SurchargeOptions({ peakSeason, englishTeaching, onChange }) {
  return (
    <div className="surcharge-options" aria-label="附加选项">
      <label>
        <input
          type="checkbox"
          checked={peakSeason}
          onChange={(event) => onChange("peakSeason", event.target.checked)}
        />
        旺季加价10%
      </label>
      <label>
        <input
          type="checkbox"
          checked={englishTeaching}
          onChange={(event) => onChange("englishTeaching", event.target.checked)}
        />
        英文教学
      </label>
    </div>
  );
}

function QuoteSection({
  quote,
  quoteResult,
  updateQuote,
  toggleQuoteService,
  choosePackage,
  activePreset,
  eyebrow = "Smart Quote",
  title = "客人价格计算器",
  description = "官网仅显示客人原价。选择雪场、人数与服务内容，即时估算总价；合作者与旅行社价格请使用单独报价链接。",
  sectionId = "quote",
  className = ""
}) {
  return (
    <section className={`section quote-section ${className}`.trim()} id={sectionId} aria-labelledby={`${sectionId}-title`}>
      <div className="quote-copy">
        <p className="eyebrow">{eyebrow}</p>
        <h2 id={`${sectionId}-title`}>{title}</h2>
        <p>{description}</p>
        <div className="price-notes">
          <span>客人原价</span>
        </div>
      </div>
      <form className="quote-tool">
        <div className="fixed-price-tier">
          <span>价格类型</span>
          <strong>客人原价</strong>
        </div>
        <SkierCountSlider value={quote.guestCount} onChange={updateQuote} />
        <QuickPackageSelector activePreset={activePreset} onSelect={choosePackage} />
        <label>
          目标雪场
          <select value={quote.resort} onChange={(event) => updateQuote("resort", event.target.value)}>
            {Object.entries(resorts).map(([key, resort]) => (
              <option value={key} key={key}>{resort.label}</option>
            ))}
          </select>
        </label>
        <label>
          只坐车不滑雪人数
          <input
            value={quote.rideOnlyCount}
            onChange={(event) => updateQuote("rideOnlyCount", event.target.value)}
            type="number"
            min="0"
            max="30"
          />
        </label>
        <label>
          教练时长
          <input
            value={quote.coachHours}
            onChange={(event) => updateQuote("coachHours", event.target.value)}
            type="number"
            min="1"
            max="8"
          />
        </label>
        <label>
          雪卡小时数
          <input
            value={quote.liftPassHours}
            onChange={(event) => updateQuote("liftPassHours", event.target.value)}
            type="number"
            min="1"
            max="8"
          />
        </label>
        <fieldset>
          <legend>服务内容</legend>
          {Object.entries(services).map(([key, service]) => (
            <label key={key}>
              <input
                type="checkbox"
                checked={quote.selectedServices.includes(key)}
                onChange={() => toggleQuoteService(key)}
              />
              {service.label}
            </label>
          ))}
        </fieldset>
        <SurchargeOptions
          peakSeason={quote.peakSeason}
          englishTeaching={quote.englishTeaching}
          onChange={updateQuote}
        />
        <div className="quote-result" aria-live="polite">
          <span>预估总价</span>
          <strong>{formatCurrency(quoteResult.total)}</strong>
          <div className="quote-lines">
            {quoteResult.lines.length > 0 ? (
              quoteResult.lines.map((line) => (
                <small key={line.label}>
                  <span>{line.label}</span>
                  <b>{formatCurrency(line.amount)}</b>
                </small>
              ))
            ) : (
              <small>请选择服务内容</small>
            )}
          </div>
        </div>
      </form>
    </section>
  );
}

function StandaloneCalculatorPage({ eyebrow, title, description, tiers }) {
  return (
    <>
      <header className="site-header standalone-header" id="top">
        <a className="brand" href="/" aria-label="返回金泉国际官网">
          <span className="brand-logo">
            <img src={logoImage} alt="" />
          </span>
          <span>
            <strong>金泉国际</strong>
            <small>KINSEN International</small>
          </span>
        </a>
	        <nav className="nav" aria-label="渠道报价导航">
	          <a href="/">官网首页</a>
	          <a href="/rental.html">租赁下单</a>
	          <a href="/partner.html">合作者报价</a>
	          <a href="/agency.html">旅行社报价</a>
	        </nav>
      </header>
      <main className="standalone-main">
        <section className="standalone-hero">
          <p className="eyebrow">{eyebrow}</p>
          <h1>{title}</h1>
          <p>{description}</p>
        </section>
        <ChannelPriceCalculator
          id="standalone-calculator"
          eyebrow={eyebrow}
          title={title}
          description="选择散装服务项目，系统会按当前渠道价格表自动计算。"
          tiers={tiers}
        />
      </main>
      <footer className="site-footer">
        <p>© 2026 KINSEN International. 渠道报价计算器仅供内部合作报价参考。</p>
        <p><a href="/">返回官网首页</a></p>
      </footer>
    </>
  );
}

function ChannelPriceCalculator({ id, eyebrow, title, description, tiers }) {
  const [form, setForm] = useState(createInitialCalculatorState);
  const [activePreset, setActivePreset] = useState("custom");

  const updateForm = (key, value) => {
    setForm((current) => ({ ...current, [key]: value }));
    if (key !== "guestCount") {
      setActivePreset("custom");
    }
  };

  const toggleService = (serviceKey) => {
    setForm((current) => ({
      ...current,
      selectedServices: toggleServiceInList(current.selectedServices, serviceKey)
    }));
    setActivePreset("custom");
  };

  const choosePackage = (presetKey) => {
    setForm((current) => applyPackagePreset(current, presetKey));
    setActivePreset(presetKey);
  };

  const comparison = useMemo(() => {
    const tierTotals = {};
    const rows = [];

    tiers.forEach((tier) => {
      tierTotals[tier.key] = 0;
    });

    const addComparisonRow = (label, amounts) => {
      if (Object.values(amounts).every((amount) => amount <= 0)) return;
      rows.push({ label, amounts });
      tiers.forEach((tier) => {
        tierTotals[tier.key] += amounts[tier.key] || 0;
      });
    };

    const serviceLinesByTier = tiers.map((tier) => ({
      tierKey: tier.key,
      result: calculateQuoteLines(form, tier.key)
    }));

    serviceLinesByTier[0].result.lines.forEach((line, index) => {
      const amounts = {};
      tiers.forEach((tier) => {
        amounts[tier.key] = serviceLinesByTier.find((item) => item.tierKey === tier.key).result.lines[index]?.amount || 0;
      });
      addComparisonRow(line.label, amounts);
    });

    return { rows, tierTotals };
  }, [form, tiers]);

  return (
    <section className="section channel-calculator-section" id={id} aria-labelledby={`${id}-title`}>
      <div className="channel-intro">
        <p className="eyebrow">{eyebrow}</p>
        <h2 id={`${id}-title`}>{title}</h2>
        <p>{description}</p>
      </div>
      <div className="channel-calculator">
        <form className="channel-controls">
          <SkierCountSlider value={form.guestCount} onChange={updateForm} />
          <QuickPackageSelector activePreset={activePreset} onSelect={choosePackage} />
          <div className="form-row">
            <label>
              雪场
              <select value={form.resort} onChange={(event) => updateForm("resort", event.target.value)}>
                {Object.entries(resorts).map(([key, resort]) => (
                  <option value={key} key={key}>{resort.label}</option>
                ))}
              </select>
            </label>
            <label>
              只坐车不滑雪人数
              <input
                value={form.rideOnlyCount}
                onChange={(event) => updateForm("rideOnlyCount", event.target.value)}
                type="number"
                min="0"
                max="30"
              />
            </label>
          </div>
          <div className="form-row compact-row">
            <label>
              教练时长
              <input
                value={form.coachHours}
                onChange={(event) => updateForm("coachHours", event.target.value)}
                type="number"
                min="1"
                max="8"
              />
            </label>
            <label>
              雪卡小时
              <input
                value={form.liftPassHours}
                onChange={(event) => updateForm("liftPassHours", event.target.value)}
                type="number"
                min="1"
                max="8"
              />
            </label>
          </div>
          <fieldset>
            <legend>服务</legend>
            {channelServiceKeys.map((key) => (
              <label key={key}>
                <input
                  type="checkbox"
                  checked={form.selectedServices.includes(key)}
                  onChange={() => toggleService(key)}
                />
                {services[key].label}
              </label>
            ))}
          </fieldset>
          <SurchargeOptions
            peakSeason={form.peakSeason}
            englishTeaching={form.englishTeaching}
            onChange={updateForm}
          />
        </form>
        <div className="comparison-panel">
          <div className="comparison-summary">
            {tiers.map((tier) => (
              <strong key={tier.key}>
                {tier.label}
                <b>{formatCurrency(comparison.tierTotals[tier.key] || 0)}</b>
              </strong>
            ))}
          </div>
          <div className="comparison-table-wrap">
            <table className="comparison-table">
              <thead>
                <tr>
                  <th>项目</th>
                  {tiers.map((tier) => (
                    <th key={tier.key}>{tier.label}</th>
                  ))}
                </tr>
              </thead>
              <tbody>
                {comparison.rows.length > 0 ? (
                  comparison.rows.map((row) => (
                    <tr key={row.label}>
                      <td>{row.label}</td>
                      {tiers.map((tier) => (
                        <td key={tier.key}>{formatCurrency(row.amounts[tier.key] || 0)}</td>
                      ))}
                    </tr>
                  ))
                ) : (
                  <tr>
                    <td colSpan={tiers.length + 1}>请选择服务或填写数量</td>
                  </tr>
                )}
              </tbody>
            </table>
          </div>
        </div>
      </div>
    </section>
  );
}

function EquipmentSection() {
  return (
    <section className="section equipment-section" aria-labelledby="equipment-title">
      <SectionHeading eyebrow="Rental Quality" title="专业装备租赁与卫生保障" id="equipment-title" />
      <div className="brand-wall" aria-label="装备品牌">
        {["Atomic", "Head", "Burton", "Salomon", "K2", "Rossignol"].map((brand) => (
          <span key={brand}>{brand}</span>
        ))}
      </div>
      <div className="equipment-grid">
        <article>
          <h3>装备清单</h3>
          <p>头盔、雪镜、手套、雪服、雪裤、雪板、固定器与雪鞋，可按单板或双板偏好提前准备。</p>
        </article>
        <article className="hygiene-card">
          <h3>卫生细节</h3>
          <p>每位客人提供一次性头套和手套内胆，贴身装备按客人尺码独立整理，减少现场反复试穿时间。</p>
        </article>
      </div>
    </section>
  );
}

function RentalOrderPage() {
  const [contact, setContact] = useState({ contactName: "", contactMethod: "" });
  const [contactOpen, setContactOpen] = useState(true);
  const [guests, setGuests] = useState([{ ...guestTemplate, name: "客人 1" }]);
  const [activeGuest, setActiveGuest] = useState(0);
  const [orderOutput, setOrderOutput] = useState("");
  const [copyStatus, setCopyStatus] = useState("复制订单");

  const updateGuest = (index, key, value) => {
    setGuests((current) =>
      current.map((guest, guestIndex) =>
        guestIndex === index ? { ...guest, [key]: value } : guest
      )
    );
  };

  const toggleGuestNeed = (index, need) => {
    setGuests((current) =>
      current.map((guest, guestIndex) => {
        if (guestIndex !== index) return guest;
        const needs = guest.needs.includes(need)
          ? guest.needs.filter((item) => item !== need)
          : [...guest.needs, need];
        return { ...guest, needs };
      })
    );
  };

  const addGuest = () => {
    setGuests((current) => {
      const nextGuest = { ...guestTemplate, name: `客人 ${current.length + 1}` };
      setActiveGuest(current.length);
      return [...current, nextGuest];
    });
  };

  const removeGuest = (index) => {
    setGuests((current) => {
      const nextGuests = current.filter((_, guestIndex) => guestIndex !== index);
      setActiveGuest(nextGuests.length > 0 ? Math.max(0, Math.min(activeGuest, nextGuests.length - 1)) : 0);
      return nextGuests.length > 0 ? nextGuests : [{ ...guestTemplate, name: "客人 1" }];
    });
  };

  const getGuestTotal = (guest) => calculateRentalOrderLines(guest.needs, "regular").total;
  const rentalOrderTotal = guests.reduce((sum, guest) => sum + getGuestTotal(guest), 0);

  const buildOrder = () => {
    const lines = [
      "金泉国际租赁 / 零售订单",
      `联系人：${contact.contactName || "未填写"}`,
      `联系方式：${contact.contactMethod || "未填写"}`,
      `客人价总计：${formatCurrency(rentalOrderTotal)}`,
      ""
    ];

    guests.forEach((guest, index) => {
      const rentalResult = calculateRentalOrderLines(guest.needs, "regular");
      lines.push(`客人 ${index + 1}：${guest.name || "未填写"}`);
      lines.push(`身高：${guest.height || "未填写"} cm`);
      lines.push(`体重：${guest.weight || "未填写"} kg`);
      lines.push(`鞋码：${guest.shoeSize || "未填写"} cm`);
      lines.push(`滑雪偏好：${guest.preference}`);
      lines.push("租赁 / 零售内容：");
      if (rentalResult.lines.length > 0) {
        rentalResult.lines.forEach((line) => lines.push(`- ${line.label}：${formatCurrency(line.amount)}`));
      } else {
        lines.push("- 未选择");
      }
      lines.push(`客人价小计：${formatCurrency(rentalResult.total)}`);
      lines.push("");
    });

    return lines.join("\n").trim();
  };

  const submitOrder = (event) => {
    event.preventDefault();
    setOrderOutput(buildOrder());
    setCopyStatus("复制订单");
  };

  const copyOrder = async () => {
    const data = buildOrder();
    setOrderOutput(data);
    try {
      await navigator.clipboard.writeText(data);
      setCopyStatus("已复制");
    } catch {
      setCopyStatus("请手动复制");
    }
  };

  return (
    <>
      <header className="rental-mobile-header">
        <a className="brand" href="/" aria-label="返回官网首页">
          <span className="brand-logo">
            <img src={logoImage} alt="" />
          </span>
          <span>
            <strong>金泉国际</strong>
            <small>KINSEN International</small>
          </span>
        </a>
        <a href="/">官网</a>
      </header>
      <main className="rental-page">
        <section className="rental-page-hero">
          <p className="eyebrow">Rental Order</p>
          <h1>滑雪装备订单</h1>
          <p>录入尺码，选择装备，生成可直接发送的订单文本。</p>
        </section>
        <RentalSection
          contact={contact}
          setContact={setContact}
          contactOpen={contactOpen}
          setContactOpen={setContactOpen}
          guests={guests}
          activeGuest={activeGuest}
          setActiveGuest={setActiveGuest}
          addGuest={addGuest}
          removeGuest={removeGuest}
          updateGuest={updateGuest}
          toggleGuestNeed={toggleGuestNeed}
          submitOrder={submitOrder}
          copyOrder={copyOrder}
          orderOutput={orderOutput}
          copyStatus={copyStatus}
          rentalOrderTotal={rentalOrderTotal}
        />
      </main>
    </>
  );
}

function RentalSection(props) {
  const {
    contact,
    setContact,
    contactOpen,
    setContactOpen,
    guests,
    activeGuest,
    setActiveGuest,
    addGuest,
    removeGuest,
    updateGuest,
    toggleGuestNeed,
    submitOrder,
    copyOrder,
    orderOutput,
    copyStatus,
    rentalOrderTotal
  } = props;

  return (
    <section className="rental-mobile-section" id="rental" aria-labelledby="rental-title">
      <form className="rental-mobile-form" onSubmit={submitOrder}>
        <article className={`rental-panel contact-panel ${contactOpen ? "open" : ""}`}>
          <button className="collapse-trigger" type="button" onClick={() => setContactOpen(!contactOpen)}>
            <span>
              <small>Step 1</small>
              <strong>联系人信息</strong>
            </span>
            <b>{contact.contactName || "填写"}</b>
          </button>
          {contactOpen && (
            <div className="mobile-field-stack">
              <label>
                姓名
                <input
                  value={contact.contactName}
                  onChange={(event) => setContact((current) => ({ ...current, contactName: event.target.value }))}
                  type="text"
                  placeholder="王女士"
                />
              </label>
              <label>
                联系方式
                <input
                  value={contact.contactMethod}
                  onChange={(event) => setContact((current) => ({ ...current, contactMethod: event.target.value }))}
                  type="text"
                  placeholder="微信 / Line / 邮箱"
                />
              </label>
            </div>
          )}
        </article>

        <div className="rental-step-heading">
          <span>Step 2</span>
          <h2 id="rental-title">客人装备</h2>
        </div>

        <div className="mobile-guest-list">
          {guests.map((guest, index) => {
            const open = activeGuest === index;
            const guestTotal = calculateRentalOrderLines(guest.needs, "regular").total;
            return (
              <article className={`mobile-guest-card ${open ? "open" : ""}`} key={`${guest.name}-${index}`}>
                <button className="mobile-guest-summary" type="button" onClick={() => setActiveGuest(open ? null : index)}>
                  <span>
                    <strong>{guest.name || `客人 ${index + 1}`}</strong>
                    <small>{guest.height ? `${guest.height}cm` : "待填身高"}</small>
                  </span>
                  <b>{formatCurrency(guestTotal)}</b>
                </button>
                {open && (
                  <div className="mobile-guest-body">
                    <div className="mobile-field-stack">
                      <label>
                        姓名或备注
                        <input value={guest.name} onChange={(event) => updateGuest(index, "name", event.target.value)} placeholder={`客人 ${index + 1}`} />
                      </label>
                      <label>
                        身高
                        <input value={guest.height} onChange={(event) => updateGuest(index, "height", event.target.value)} type="number" inputMode="numeric" min="80" placeholder="170 cm" />
                      </label>
                      <label>
                        体重
                        <input value={guest.weight} onChange={(event) => updateGuest(index, "weight", event.target.value)} type="number" inputMode="numeric" min="10" placeholder="60 kg" />
                      </label>
                      <label>
                        鞋码
                        <input value={guest.shoeSize} onChange={(event) => updateGuest(index, "shoeSize", event.target.value)} type="number" inputMode="decimal" min="12" step="0.5" placeholder="24.5 cm" />
                      </label>
                    </div>

                    <div className="segmented-control" aria-label="滑雪偏好">
                      {["Snowboard", "Ski"].map((preference) => (
                        <button
                          className={guest.preference === preference ? "active" : ""}
                          key={preference}
                          type="button"
                          onClick={() => updateGuest(index, "preference", preference)}
                        >
                          {preference === "Snowboard" ? "单板" : "双板"}
                        </button>
                      ))}
                    </div>

                    <div className="rental-tag-groups">
                      {rentalOrderGroups.map((group) => (
                        <div className="rental-tag-group" key={group.title}>
                          <h3>{group.title}</h3>
                          <div className="rental-tag-list">
                            {group.keys.map((key) => {
                              const selected = guest.needs.includes(key);
                              return (
                                <button
                                  className={selected ? "selected" : ""}
                                  key={key}
                                  type="button"
                                  onClick={() => toggleGuestNeed(index, key)}
                                >
                                  {rentalOrderOptions[key].label}
                                </button>
                              );
                            })}
                          </div>
                        </div>
                      ))}
                    </div>

                    <div className="mobile-guest-actions">
                      {guests.length > 1 && (
                        <button className="text-button subtle" type="button" onClick={() => removeGuest(index)}>
                          删除客人
                        </button>
                      )}
                      <button className="text-button" type="button" onClick={() => setActiveGuest(null)}>
                        收起
                      </button>
                    </div>
                  </div>
                )}
              </article>
            );
          })}
        </div>

        {orderOutput && (
          <article className="mobile-order-output">
            <div>
              <button className="primary-button" type="button" onClick={copyOrder}>{copyStatus}</button>
            </div>
            <pre>{orderOutput}</pre>
          </article>
        )}

        <div className="rental-sticky-bar">
          <button className="sticky-add-button" type="button" onClick={addGuest}>+ 客人</button>
          <div>
            <small>客人价总计</small>
            <strong>{formatCurrency(rentalOrderTotal)}</strong>
          </div>
          <button className="primary-button" type="submit">生成订单</button>
        </div>
      </form>
    </section>
  );
}

function RulesSection() {
  return (
    <section className="section rules-section" aria-labelledby="rules-title">
      <SectionHeading eyebrow="Service Rules" title="交通服务规则与出行须知" id="rules-title" />
      <div className="rules-grid">
        <article>
          <h3>拼车服务</h3>
          <p>司机会在约定时间接人。迟到超过 10 分钟不候，学员需自行前往雪场，已产生交通安排费用不因迟到自动取消。</p>
        </article>
        <article>
          <h3>专车服务</h3>
          <p>司机会在指定时间专属等候，适合带小朋友、装备较多、商务接待或需要灵活返程时间的客人。</p>
        </article>
      </div>
    </section>
  );
}

function SpotsSection() {
  return (
    <section className="section spots-section" id="spots" aria-labelledby="spots-title">
      <div className="spots-copy">
        <p className="eyebrow">Photo Guide</p>
        <h2 id="spots-title">手稻雪场海景拍摄点地图</h2>
        <p>内置三个高人气打卡位置，方便教练带队时兼顾教学路线和拍照节奏。</p>
      </div>
      <div className="map-card" role="img" aria-label="手稻雪场海景拍摄点示意图">
        <span className="pin pin-one">Paradise 起点</span>
        <span className="pin pin-two">圣火台山顶</span>
        <span className="pin pin-three">白桦 2 入口</span>
        <div className="bay-label">Ishikari Bay View</div>
      </div>
    </section>
  );
}

function TestimonialsSection() {
  const testimonials = [
    ["从零开始一天学会滑行，教练讲得很清楚，也一直帮我调整动作。", "初学客人 · 手稻"],
    ["教练耐心且会帮忙拍网红照，路线安排很顺，回程也不用操心。", "亲子家庭 · 札幌国际"],
    ["装备提前按尺码准备好，到了直接换装出发，比自己租省了很多时间。", "自由行客人 · 二世谷"]
  ];

  return (
    <section className="section testimonials-section" aria-labelledby="testimonials-title">
      <SectionHeading eyebrow="Testimonials" title="5.0 分超棒评价" id="testimonials-title" />
      <div className="testimonial-grid">
        {testimonials.map(([quote, cite]) => (
          <blockquote key={cite}>
            <p>“{quote}”</p>
            <cite>{cite}</cite>
          </blockquote>
        ))}
      </div>
    </section>
  );
}

function ContactSection() {
  return (
    <section className="section contact-section" id="contact" aria-labelledby="contact-title">
      <div className="contact-card">
        <p className="eyebrow">05 / Contact Us</p>
        <h2 id="contact-title">预订咨询与团队定制</h2>
        <p>个人滑雪、亲子家庭、滑雪研学团、企业团建和旅行社团队都欢迎咨询。我们会按人数、雪场、装备、交通和教学需求给出清晰方案。</p>
      </div>
      <div className="share-card" aria-label="品牌宣传名片">
        <div className="qr-grid">
          {connectImages.map((item) => (
            <figure className="qr-card" key={item.label}>
              <img src={item.src} alt={`${item.label} 联系二维码`} />
              <figcaption>
                <strong>{item.label}</strong>
                <span>{item.note}</span>
              </figcaption>
            </figure>
          ))}
        </div>
      </div>
    </section>
  );
}

function SectionHeading({ eyebrow, title, id }) {
  return (
    <div className="section-heading">
      <p className="eyebrow">{eyebrow}</p>
      <h2 id={id}>{title}</h2>
    </div>
  );
}

ReactDOM.createRoot(document.getElementById("root")).render(<App />);
