- {filteredCollective.map((card) => (
-
- ))}
- {filteredCollective.length === 0 &&
}
+
+
+ {pickText('贵州特色住宿候选', 'Distinctive Guizhou stay shortlist', language)}
+
{pickText('先选一晚值得停留的地方,再核实它是否真的适合你', 'Choose a night worth slowing down for—then verify that it truly fits', language)}
+
+
+
{pickText('这 8 家来自客户修改意见。客户文档没有嵌入对应酒店原图,也没有提供经营证照、实时房态或境外客人接待证明,因此本页不会用别处风景图冒充酒店实景,也不会把宣传卖点直接写成保证。', 'These eight candidates come from the client brief. The document contains no matching hotel photography, operating documents, live availability, or evidence of foreign-guest handling, so this page does not substitute unrelated scenery or turn promotional claims into guarantees.', language)}
+
+ {pickText('8 家候选', '8 candidates', language)}
+ {pickText('4 类住宿', '4 stay types', language)}
+ {pickText('预订前逐家确认', 'Verified before booking', language)}
+
+
+
+ {hotelGroups.map((group) => (
+
+
+ {group.number}
+
+
{group.title}
+
{group.intro}
+
+
+
+ {group.hotels.map((hotel, index) => (
+
+
+ {group.number}.{String(index + 1).padStart(2, '0')}
+ {pickText('客户推荐・待确认', 'Client shortlist · To verify', language)}
+
+ {hotel.title}
+ {hotel.location}
+ {hotel.copy}
+
+ - {pickText('路线', 'Route fit', language)}
- {hotel.route}
+ - {pickText('确认', 'Verify', language)}
- {hotel.verify}
+
+ {pickText('加入住宿比选', 'Add to Stay Shortlist', language)}
+
+ ))}
+
+
+ ))}
+
+
+
+
+
+ {pickText('线路联动', 'Route pairing', language)}
+ {pickText('酒店不是独立清单,而是每一天路线的落点', 'A stay is the landing point of each route—not a detached list', language)}
+
+
+ {routeLinks.map((item, index) => (
+
+ {String(index + 1).padStart(2, '0')}
+ {item.route}
+ {item.stays}
+ {item.note}
+
+ ))}
+
+
+
+
+
+
+
{pickText('正式预订前', 'Before booking', language)}
+
{pickText('每一家,都要通过同一套六项确认', 'Every property passes the same six booking checks', language)}
+
{pickText('“可以在平台上看到”不等于适合这组客人,也不等于所有宣传设施在出行日期可用。确认结果会进入报价和入住说明。', 'Being listed online does not mean a property fits this group or that every advertised facility is available on the travel date. Confirmed details go into the quote and check-in notes.', language)}
+
+
+ {bookingChecks.map((check, index) => (
+ - {String(index + 1).padStart(2, '0')}
{check}
+ ))}
+
+
@@ -3020,7 +3995,2959 @@ function TransportDetailPage({ slug }: { slug: string }) {
return
;
}
-function ExperienceDetailPage({ slug }: { slug: string }) {
+function CaveExpeditionDetailPage() {
+ const { language } = useTravelSite();
+ const levels = [
+ {
+ number: '01',
+ label: pickText('轻量', 'Light', language),
+ title: pickText('洞穴步行与入门观察', 'Cave Walk & Introductory Exploration', language),
+ copy: pickText(
+ '以已确认可接待的洞段、明确路径和短时活动为主,不包含技术高度与深水。适合首次进洞、家庭小团或对黑暗与密闭感需要逐步适应的客人。',
+ 'A short, clearly defined route in a cave section approved for visitor access, without technical height or deep water. Best for first-time cave guests, families, and anyone who wants a gradual introduction to darkness and enclosed spaces.',
+ language,
+ ),
+ gate: pickText('年龄、路面与照明条件按具体洞穴复核', 'Age, terrain, and lighting are confirmed for the selected cave', language),
+ },
+ {
+ number: '02',
+ label: pickText('活力', 'Active', language),
+ title: pickText('平缓水域洞穴桨板', 'Calm-Water Cave Paddleboarding', language),
+ copy: pickText(
+ '在运营方允许且水位适合的洞穴水域中进行,会结合不平整洞穴步行、上下板和基础平衡。需要对落水有基本心理准备,且能听从现场指令。',
+ 'Operated only in cave water approved by the local operator and at suitable water levels. It combines uneven cave walking, mounting and dismounting the board, and basic balance. Guests need reasonable water confidence and must be able to follow field instructions.',
+ language,
+ ),
+ gate: pickText('天气、水位、水温、上岸点与通信条件均须通过', 'Weather, water, landing points, and communication must all pass', language),
+ },
+ {
+ number: '03',
+ label: pickText('进阶候选', 'Advanced Candidate', language),
+ title: pickText('非开发洞段、飞拉达与绳索场景', 'Wild Cave, Via Ferrata & Rope Elements', language),
+ copy: pickText(
+ '只面向经验、体能和心理状态匹配的客人,且仅在具体运营方、带队人员、绳索系统、保险和撤离机制完整核验后进入正式方案。',
+ 'For guests whose experience, fitness, and mental readiness match the terrain. It enters a final itinerary only after the exact operator, field team, rope system, insurance, and evacuation plan have been fully validated.',
+ language,
+ ),
+ gate: pickText('这是待核验的进阶方向,不是默认可售项目', 'This is a validation-dependent direction, not a default sellable activity', language),
+ },
+ ];
+ const flow = [
+ { title: pickText('行前问卷与分级', 'Pre-trip Profile & Grading', language), copy: pickText('确认年龄、健康、水性、户外经验、怕黑/恐高和想要的强度。', 'Confirm age, health, water confidence, outdoor experience, fear of darkness or heights, and preferred intensity.', language) },
+ { title: pickText('点位匹配与二次确认', 'Site Match & Final Reconfirmation', language), copy: pickText('按日期对接清镇、安顺或绥阳等洞穴区域候选,出发前再查天气、水位与场地状态。', 'Match a date-specific candidate in the Qingzhen, Anshun, or Suiyang cave regions, then recheck weather, water, and site status before departure.', language) },
+ { title: pickText('现场说明与装备适配', 'Field Briefing & Gear Fit', language), copy: pickText('说明移动方式、手势指令、失衡处理、返回节点与通信方式,再进行头盔、照明或水上装备适配。', 'Review movement, hand signals, loss-of-balance response, return points, and communication before fitting helmets, lighting, or water equipment.', language) },
+ { title: pickText('一项核心活动', 'One Core Activity', language), copy: pickText('洞穴日只保留一项核心活动,不把步行、桨板、飞拉达和绳降堆叠成打卡清单。', 'The cave day keeps one core activity instead of stacking walking, paddleboarding, via ferrata, and rope work into a checklist.', language) },
+ { title: pickText('退出、恢复与复盘', 'Exit, Recovery & Debrief', language), copy: pickText('按预设节点退出,更换干衣、热饮补给,再决定后续行程是保留还是放缓。', 'Exit at the planned point, change into dry layers, warm up, and decide whether the rest of the day should continue or slow down.', language) },
+ ];
+ const gates = [
+ { title: pickText('场地与自然条件', 'Site & Natural Conditions', language), copy: pickText('当日开放状态、天气、降雨、水位、路面与退出路线。', 'Opening status, weather, rainfall, water level, terrain, and exit route.', language) },
+ { title: pickText('运营方与现场团队', 'Operator & Field Team', language), copy: pickText('具体运营主体、带队人员、客人比例、通信与事故处理流程。', 'Named operator, field leaders, guest ratio, communication, and incident procedure.', language) },
+ { title: pickText('装备与保险', 'Equipment & Insurance', language), copy: pickText('逐项确认装备清单、检查记录、使用说明和保险对当日活动的覆盖范围。', 'Verify the equipment list, inspection record, use briefing, and insurance coverage for the exact activity.', language) },
+ { title: pickText('客人状态与退出机制', 'Guest Readiness & Exit Plan', language), copy: pickText('健康、体力、心理反应和现场表现任一不匹配时,降级、中止或切换地面方案。', 'If health, fitness, mental response, or field performance does not match, downgrade, stop, or switch to a surface alternative.', language) },
+ ];
+ const routes = [
+ { number: '01', title: pickText('喀斯特户外探险线', 'Karst Outdoor Adventure', language), copy: pickText('作为主力活动日,前后保留恢复与备选窗口。', 'Use it as the primary activity day, with recovery and fallback space around it.', language), href: '/safaris/outdoor-coffee/' },
+ { number: '02', title: pickText('均衡探索线', 'Balanced Discovery Route', language), copy: pickText('只加入轻量洞穴步行,与村寨慢住和非遗节奏保持平衡。', 'Add only the light cave-walk version to preserve the balance with village and heritage days.', language), href: '/safaris/culture-outdoor-mix/' },
+ { number: '03', title: pickText('经典全景线', 'Classic Panorama Route', language), copy: pickText('按日期与路线加一个轻量半日,不改变全景主线。', 'Add a light half-day when dates and routing allow, without changing the panoramic journey.', language), href: '/safaris/classic-guizhou/' },
+ ];
+
+ return (
+
+
+
+
+
+
+
+
Karst Outdoor Adventures / 01
+
{pickText('地下喀斯特探索', 'Underground Karst Exploration', language)}
+
{pickText('洞穴步行、平缓水域桨板与技术型候选项目——先完成分级,再确定进入哪一处洞穴。', 'Cave walking, calm-water paddleboarding, and technical candidates—graded before any cave site is chosen.', language)}
+
{pickText('先看体验分级', 'See the activity levels', language)}
+
+
+
+
+
+
+
+
+
{pickText('体验定义', 'Experience Definition', language)}
+
{pickText('不是选一张最刺激的图,而是选一个真正适合你的洞穴日。', 'Not the most dramatic photo—the cave day that genuinely fits you.', language)}
+
{pickText('贵州的喀斯特地貌造就了丰富的洞穴系统。客户文档提出清镇、安顺与绥阳的洞穴区域作为地理依托;实际执行时,我们按日期、开放状态、运营条件与客人能力再确定具体点位。', 'Guizhou’s karst landscape supports a rich cave system. The client brief anchors this experience in the cave regions of Qingzhen, Anshun, and Suiyang; the exact site is selected only after date, access status, operating conditions, and guest ability are checked.', language)}
+
+
+ - {pickText('地理依托', 'Geographic Base', language)}
- {pickText('清镇 / 安顺 / 绥阳洞穴区域候选', 'Qingzhen / Anshun / Suiyang cave regions', language)}
+ - {pickText('活动形式', 'Format', language)}
- {pickText('私家小团 / 一天一项核心活动', 'Private small group / one core activity', language)}
+ - {pickText('强度', 'Level', language)}
- {pickText('轻量 / 活力 / 进阶候选', 'Light / Active / Advanced candidate', language)}
+ - {pickText('适合', 'Best For', language)}
- {pickText('对洞穴地貌有好奇心,愿意接受行前评估的客人', 'Cave-curious guests open to pre-trip assessment', language)}
+ - {pickText('执行方式', 'Operation', language)}
- {pickText('场地、运营方、天气与水位逐项确认', 'Site, operator, weather, and water checked item by item', language)}
+ - {pickText('备选', 'Fallback', language)}
- {pickText('轻量洞穴步行 / 地面喀斯特步道 / 村寨与手作', 'Light cave walk / surface karst trail / village or craft', language)}
+
+
+
+
+
+
01 / Activity Grading{pickText('先选强度,再选洞穴。', 'Choose the level before the cave.', language)}
{pickText('三档分级不是套餐名称,而是决定点位、装备、人员配置与退出机制的第一步。', 'These are not package names. They are the first decision for site, equipment, staffing, and exit planning.', language)}
+
+ {levels.map((level) =>
{level.number}{level.label}
{level.title}
{level.copy}
{level.gate})}
+
+
+
+
+
+
+
+
02 / How the Day Works
{pickText('一个洞穴日,应该有清晰的开始和退出。', 'A cave day needs a clear beginning—and a clear exit.', language)}
+
{flow.map((item, index) => - {String(index + 1).padStart(2, '0')}
)}
+
+
+
+
+
+
03 / Go or No-Go{pickText('四道门槛,缺一项就降级或替换。', 'Four gates. If one fails, downgrade or replace.', language)}
{pickText('行程确认不等于无条件出发。现场决策权优先服务于客人安全和可撤回性。', 'An itinerary confirmation is not an unconditional go. Field decisions prioritize guest safety and a reliable exit.', language)}
+
{gates.map((gate, index) =>
{String(index + 1).padStart(2, '0')}{gate.title}
{gate.copy}
)}
+
+
{pickText('可以写入正式方案', 'What the final plan can promise', language)}- {pickText('与客人匹配的活动分级', 'An activity grade matched to the guest', language)}
- {pickText('一项核心活动与地面备选', 'One core activity and a surface fallback', language)}
- {pickText('在正式方案中列明运营方、装备、保险与接驳', 'Named operator, equipment, insurance, and transfers in the final plan', language)}
+
{pickText('必须按具体点位复核', 'Claims that require site-specific proof', language)}- {pickText('全年 18°C 的固定温度表述', 'A blanket year-round 18°C statement', language)}
- {pickText('CE 装备、认证向导与具体保险覆盖', 'CE equipment, certified guides, and exact insurance coverage', language)}
- {pickText('6 岁以上等统一最低年龄与进阶洞段', 'A universal age minimum such as 6+, and any advanced cave section', language)}
+
+
+
+
+
+ 04 / Route Pairing
{pickText('把它放进对的线路,而不是硬塞进每一次贵州之旅。', 'Place it in the right route—not every Guizhou trip.', language)}
+
+
+
+
+
+ );
+}
+
+function WaterfallAbseilingDetailPage() {
+ const { language } = useTravelSite();
+ const levels = [
+ {
+ number: '01',
+ label: pickText('初次体验候选', 'First-Descent Candidate', language),
+ title: pickText('干地练习与可控短线下降', 'Dry Practice & a Controlled Short Descent', language),
+ copy: pickText(
+ '先在干地完成装备识别、下降姿势、手势与中止指令练习,再由已核验的运营方匹配较短、退出明确的线路。不将“36 米入门”当作所有新手的默认选项。',
+ 'Begin on dry ground with equipment recognition, body position, hand signals, and stop commands. A verified operator then matches a shorter line with a clear exit. The brief’s “36 m beginner” figure is not treated as a universal first-timer option.',
+ language,
+ ),
+ gate: pickText('只有干地练习、心理状态与现场条件全部通过才进入', 'Proceed only after dry practice, guest readiness, and field conditions all pass', language),
+ },
+ {
+ number: '02',
+ label: pickText('活力', 'Active', language),
+ title: pickText('单项瀑布绳索下降', 'Single Waterfall Rope Descent', language),
+ copy: pickText(
+ '以一条经核验的瀑布下降线为当日核心,需要面对水雾、噪声、湿滑岩面和高度感。不在同一天再叠加长距离溯溪、跳潭或其他高强度项目。',
+ 'One verified waterfall line becomes the day’s core activity. Guests must manage spray, noise, wet rock, and exposure to height. Long stream tracing, pool jumps, or other high-intensity elements are not stacked onto the same day.',
+ language,
+ ),
+ gate: pickText('降雨、水量、岩面、锚点/绳索系统与下方出口均须通过', 'Rainfall, water, rock, anchor/rope system, and lower exit must all pass', language),
+ },
+ {
+ number: '03',
+ label: pickText('进阶候选', 'Advanced Candidate', language),
+ title: pickText('瀑降与峡谷组合', 'Abseiling & Canyoning Combination', language),
+ copy: pickText(
+ '客户文档提出溯溪、跳潭、溜索与更大落差的组合方向。这些只面向经验、体能和心理状态匹配的客人,并需要具体运营方、人员、场地、保险与救援资料完整。',
+ 'The brief proposes combinations with stream tracing, pool jumps, zip lines, and larger drops. These remain for guests whose experience, fitness, and mental readiness match, and only after operator, team, site, insurance, and rescue records are complete.',
+ language,
+ ),
+ gate: pickText('高度与组合玩法必须逐点核验,不是默认可售项目', 'Height and combined elements require site-specific proof and are not default sellable activities', language),
+ },
+ ];
+ const flow = [
+ { title: pickText('行前筛查与体验匹配', 'Pre-trip Screening & Match', language), copy: pickText('确认健康、体力、恐高程度、游泳/水性、绳索经验和对湿身环境的接受度。', 'Confirm health, fitness, height exposure, water confidence, rope experience, and comfort with a fully wet environment.', language) },
+ { title: pickText('点位、天气与水量二次确认', 'Site, Weather & Water Recheck', language), copy: pickText('从归兰山、摆弓岩、滴水滩等客户文档候选区域中按当日可执行条件选择,不预先锁定高度。', 'Select from brief-listed candidates such as Guilanshan, Baigongyan, or Dishuitan only when the day’s operating conditions pass, without pre-promising a height.', language) },
+ { title: pickText('干地说明与装备适配', 'Dry Briefing & Equipment Fit', language), copy: pickText('由具体运营方说明保护系统、下降动作、手势、中止指令、通信和退出路线,完成穿戴与干地练习。', 'The named operator explains the protection system, descent movement, signals, stop commands, communication, and exit route before fitting equipment and rehearsing on dry ground.', language) },
+ { title: pickText('Go / No-go 与单项下降', 'Go / No-go & One Core Descent', language), copy: pickText('现场不通过就停止或替换;通过后也只执行正式方案列明的一项核心绳索活动。', 'Stop or replace if field checks fail; if they pass, operate only the single rope activity named in the final plan.', language) },
+ { title: pickText('离场、保暖与恢复', 'Exit, Warm-up & Recovery', language), copy: pickText('按预设路线离场,更换干衣、补充热食与水分,当天不再安排赶机、长距离山路或第二项高强度活动。', 'Leave by the planned exit, change into dry layers, hydrate, and take warm food. Do not follow with a flight, long mountain transfer, or second high-intensity activity.', language) },
+ ];
+ const gates = [
+ { title: pickText('降雨、水量与岩面', 'Rain, Water & Rock', language), copy: pickText('降雨趋势、上游来水、瀑布水量、能见度、岩面湿滑和水温。', 'Rain trend, upstream inflow, waterfall volume, visibility, rock traction, and water temperature.', language) },
+ { title: pickText('场地、系统与退出', 'Site, System & Exit', language), copy: pickText('当日开放/授权状态、锚点与绳索方案、上下站位、通信与中途撤离可能性。', 'Day-specific access/authorization, anchor and rope plan, top and bottom stations, communication, and mid-route escape options.', language) },
+ { title: pickText('运营方、人员与救援', 'Operator, Team & Rescue', language), copy: pickText('具体运营主体、带队/操作人员、客人比例、应急联络、救援路线与现场救生装备。', 'Named operator, field/rope staff, guest ratio, emergency contacts, rescue route, and on-site rescue equipment.', language) },
+ { title: pickText('客人、装备与保险', 'Guest, Equipment & Insurance', language), copy: pickText('客人健康与现场表现、装备清单/检查记录、使用说明,以及保险是否覆盖该点位和活动。', 'Guest health and field performance, equipment list/inspection record, use briefing, and insurance coverage for the exact site and activity.', language) },
+ ];
+ const routes = [
+ { number: '01', title: pickText('喀斯特户外探险线', 'Karst Outdoor Adventure', language), copy: pickText('最合适的主线:把瀑降作为唯一主活动日,前后保留备选和恢复。', 'The best-fit route: make abseiling the only core activity that day, with fallback and recovery space around it.', language), href: '/safaris/outdoor-coffee/' },
+ { number: '02', title: pickText('经典全景线', 'Classic Panorama Route', language), copy: pickText('只在安顺段整天替换时加入,不与黄果树全景观光同天满负荷叠加。', 'Add it only by replacing a full Anshun day, not by stacking it onto a full Huangguoshu sightseeing day.', language), href: '/safaris/classic-guizhou/' },
+ { number: '03', title: pickText('均衡探索线', 'Balanced Discovery Route', language), copy: pickText('默认保留瀑布观景或峡谷步行;只在全员能力与资料都匹配时单独定制绳索活动。', 'Default to waterfall viewing or a canyon walk; customize a rope activity only when every guest and operating record matches.', language), href: '/safaris/culture-outdoor-mix/' },
+ ];
+
+ return (
+
+
+
+
+
+
+
+
Karst Outdoor Adventures / 02
+
{pickText('瀑降与峡谷绳索', 'Waterfall Abseiling & Canyoning', language)}
+
{pickText('在水雾、岩壁与绳索之间下降——但只有点位、系统、人员、水量与退出全部通过时才出发。', 'Descend through spray, rock, and rope—only when site, system, team, water, and exit checks all pass.', language)}
+
{pickText('先看强度分级', 'See the activity levels', language)}
+
+
+
+
+
+
+
+
+
{pickText('体验定义', 'Experience Definition', language)}
+
{pickText('它不是一个瀑布打卡点,而是一个高后果的湿绳索活动日。', 'Not a waterfall photo stop—a high-consequence wet-rope activity day.', language)}
+
{pickText('客户文档以贵州密集瀑布群为依托,提到归兰山、摆弓岩与滴水滩等候选区域。水量、岩面、锚点与撤离条件会随地点和当天变化,因此具体瀑布、高度与玩法只在核验后写入正式方案。', 'The client brief anchors this experience in Guizhou’s dense waterfall landscape, naming Guilanshan, Baigongyan, and Dishuitan as candidates. Water, rock, anchors, and escape conditions vary by place and day, so the exact waterfall, height, and format enter the final plan only after validation.', language)}
+
+
+ - {pickText('地理依托', 'Geographic Base', language)}
- {pickText('归兰山 / 摆弓岩 / 滴水滩等候选区域', 'Guilanshan / Baigongyan / Dishuitan candidate areas', language)}
+ - {pickText('活动形式', 'Format', language)}
- {pickText('私家小团 / 一天一项核心绳索活动', 'Private small group / one core rope activity', language)}
+ - {pickText('强度', 'Level', language)}
- {pickText('初次体验候选 / 活力 / 进阶候选', 'First-descent / Active / Advanced candidates', language)}
+ - {pickText('适合', 'Best For', language)}
- {pickText('具备基础体力,能接受湿身、噪声与高度感的客人', 'Guests with baseline fitness who accept full wetness, noise, and exposure', language)}
+ - {pickText('执行方式', 'Operation', language)}
- {pickText('点位、运营方、绳索系统、水量与保险逐项确认', 'Site, operator, rope system, water, and insurance checked item by item', language)}
+ - {pickText('备选', 'Fallback', language)}
- {pickText('瀑布观景 / 峡谷步行 / 山野咖啡或村寨', 'Waterfall viewing / canyon walk / mountain coffee or village', language)}
+
+
+
+
+
+
+
+
01 / Activity Grading{pickText('先匹配下降等级,再谈瀑布高度。', 'Match the descent level before discussing height.', language)}
{pickText('对新手来说,高度数字不是难度的全部。水量、岩面、出口、心理反应和操作系统共同决定是否适合。', 'Height alone does not define difficulty. Water, rock, exit, mental response, and the operating system together decide whether a descent fits.', language)}
+
{levels.map((level) =>
{level.number}{level.label}
{level.title}
{level.copy}
{level.gate})}
+
+
+
+
+
+
+
02 / How the Day Works
{pickText('真正的开始在干地,真正的结束在安全离场之后。', 'The real start is on dry ground. The real finish is a safe exit.', language)}
+
{flow.map((item, index) => - {String(index + 1).padStart(2, '0')}
)}
+
+
+
+
+
+
03 / Go or No-Go{pickText('四道门槛,任一不通过就不进入瀑布线。', 'Four gates. If one fails, do not enter the waterfall line.', language)}
{pickText('客户文档中的“双绳保护、前置探路、实时水量监测与应急救生装备”会成为运营方核验项,核验前不对外作事实承诺。', 'The brief’s double-rope, pre-scouting, live water monitoring, and emergency equipment claims become operator verification items, not public promises before proof.', language)}
+
{gates.map((gate, index) =>
{String(index + 1).padStart(2, '0')}{gate.title}
{gate.copy}
)}
+
+
{pickText('可以写入正式方案', 'What the final plan can promise', language)}- {pickText('具名的点位、运营方与活动等级', 'A named site, operator, and activity grade', language)}
- {pickText('一项核心绳索活动与地面备选', 'One core rope activity and a surface fallback', language)}
- {pickText('列明人员、绳索/装备、保险、通信、撤离与接驳', 'Named team, rope/equipment, insurance, communication, exit, and transfers', language)}
+
{pickText('必须按具体点位复核', 'Claims that require site-specific proof', language)}- {pickText('20–86 米、36 米入门与 86 米进阶等高度数字', 'The 20–86 m range and 36 m beginner / 86 m advanced figures', language)}
- {pickText('双绳保护的具体系统、人员资料与装备检查记录', 'The exact double-rope system, staff records, and equipment inspections', language)}
- {pickText('前置探路、实时水量监测、救生装备与保险覆盖', 'Pre-scouting, live water monitoring, rescue equipment, and insurance coverage', language)}
+
+
+
+
+
+ 04 / Route Pairing
{pickText('给瀑降一个完整的活动日,而不是观光之后的加码项。', 'Give abseiling a complete activity day—not an add-on after sightseeing.', language)}
+
+
+
+
+
+ );
+}
+
+function CanyonRiverDetailPage() {
+ const { language } = useTravelSite();
+ const levels = [
+ {
+ number: '01',
+ label: pickText('轻量亲水', 'Gentle Water', language),
+ title: pickText('平缓水域与短时水边体验', 'Calm Water & a Short Riverside Session', language),
+ copy: pickText(
+ '以已核验的平缓水面、稳定上下船点与短时体验为主,可结合水边步行、山野野餐或只观景不下水的陪同方案。亲子是候选客群,但不直接承诺“全年龄”。',
+ 'A short session on verified calm water with a stable launch and landing point, optionally paired with a riverside walk, wild picnic, or a dry companion plan. Families are a candidate audience, but “all ages” is not promised without operator rules.',
+ language,
+ ),
+ gate: pickText('年龄、身高/体重、救生衣适配、水温与岸线条件按具体运营方复核', 'Age, size, flotation fit, water temperature, and shoreline are operator-specific', language),
+ },
+ {
+ number: '02',
+ label: pickText('活力溯溪', 'Active Tracing', language),
+ title: pickText('峡谷涉水、步行与岩石通过', 'Canyon Wading, Walking & Rock Passage', language),
+ copy: pickText(
+ '在具体河段中逆流或顺流行走,包含不平整河床、湿滑岩石、涉水与短距离攀爬。跳潭不默认包含,可绕行与中途退出必须先确认。',
+ 'Move upstream or downstream through an exact section with uneven riverbed, wet rock, wading, and short scrambling. Pool jumps are not included by default; bypasses and mid-route exits must be confirmed first.',
+ language,
+ ),
+ gate: pickText('需要基础体力、水性和湿滑地形通过能力,大雨或水位上升直接替换', 'Requires baseline fitness, water confidence, and wet-terrain mobility; rising water triggers replacement', language),
+ },
+ {
+ number: '03',
+ label: pickText('白水候选', 'White-water Candidate', language),
+ title: pickText('较快河段的专业皮划艇/漂流艇', 'Rafting or Kayaking on Faster Water', language),
+ copy: pickText(
+ '真正的白水河段与平缓充气艇不是同一类产品。只有具体河段难度、运营许可、艇船与救生系统、操作人员、应急救援、保险和客人能力全部通过后,才进入正式方案。',
+ 'True white water is not the same product as calm-water packrafting. It enters a final plan only after river difficulty, operating permission, craft and rescue systems, field team, emergency response, insurance, and guest ability all pass.',
+ language,
+ ),
+ gate: pickText('客户图片主要展示平缓水域,不用来证明白水漂流已可售', 'The supplied images show mainly calm water and do not prove a sellable white-water product', language),
+ },
+ ];
+ const flow = [
+ { title: pickText('行前能力与客群筛查', 'Guest Screening', language), copy: pickText('确认年龄范围、健康、水性、游泳能力、户外经验、对落水/翻船的心理准备和是否需要不下水的陪同方案。', 'Confirm age range, health, water confidence, swimming ability, outdoor experience, mental readiness for immersion or capsize, and whether a dry companion plan is needed.', language) },
+ { title: pickText('只选一种当日水上模式', 'Choose One Water Mode', language), copy: pickText('在平缓亲水、活力溯溪与白水候选中选一项,不把溯溪、跳潭、漂流和长距离转场全部堆在一天。', 'Choose calm water, active tracing, or a white-water candidate—not stream tracing, pool jumps, rafting, and a long transfer all in one day.', language) },
+ { title: pickText('河段、天气与水文二次确认', 'River, Weather & Hydrology Recheck', language), copy: pickText('按场地开放状态、上游降雨、水位趋势、流速、能见度、水温、上下岸点与退出路线作 Go / No-go。', 'Make the Go / No-go call from access status, upstream rain, water trend, flow, visibility, temperature, launch/landing points, and exit routes.', language) },
+ { title: pickText('装备适配、陆地说明与入水', 'Fit, Shore Briefing & Entry', language), copy: pickText('由具体运营方完成救生衣、头盔或艇船等当日装备适配,说明划行、手势、落水处理、集合与退出。', 'The named operator fits the day’s flotation, helmet, or craft and briefs paddling, signals, immersion response, regrouping, and exit.', language) },
+ { title: pickText('离水、保暖、野餐或热食', 'Exit, Warm-up & Food', language), copy: pickText('按计划点离水,更换干衣、补水与热食。野餐只在合法、安全且不损害环境的休息点安排。', 'Exit at the planned point, change into dry layers, hydrate, and take warm food. Picnics use only legal, safe, low-impact rest points.', language) },
+ ];
+ const gates = [
+ { title: pickText('降雨、水文与水温', 'Rain, Hydrology & Temperature', language), copy: pickText('当地与上游降雨、水位变化、流速、能见度、水温和突发洪水风险。', 'Local and upstream rain, water trend, flow, visibility, temperature, and flash-flood risk.', language) },
+ { title: pickText('河段、上下岸与退出', 'River, Access & Exit', language), copy: pickText('具体起止点、河段难度、岸线、障碍物、通信信号、中途退出点与车辆接回方案。', 'Exact start/finish, river difficulty, banks, hazards, communication, mid-route exits, and vehicle recovery.', language) },
+ { title: pickText('运营方、人员与救援', 'Operator, Team & Rescue', language), copy: pickText('具名运营主体、带队/舟艇操作人员、客人比例、资质证明、急救、水上救援与应急联络。', 'Named operator, field/craft staff, guest ratio, credential records, first aid, water rescue, and emergency contact.', language) },
+ { title: pickText('装备、客人与保险', 'Equipment, Guest & Insurance', language), copy: pickText('救生衣、头盔、护具或艇船的适配与检查记录,客人年龄/身高/体重/能力限制,以及保险对当日河段和活动的覆盖。', 'Fit and inspection records for flotation, helmet, protection, or craft; guest age/size/ability limits; and insurance coverage for the exact river and activity.', language) },
+ ];
+ const routes = [
+ { number: '01', title: pickText('喀斯特户外探险线', 'Karst Outdoor Adventure', language), copy: pickText('最合适作为一个完整水上日,只选一档强度,前后保留备选与恢复。', 'Best as one complete water day at a single level, with fallback and recovery space around it.', language), href: '/safaris/outdoor-coffee/' },
+ { number: '02', title: pickText('均衡探索线', 'Balanced Discovery Route', language), copy: pickText('加入平缓亲水或短时溯溪,与村寨慢住、非遗和恢复节奏保持平衡。', 'Add calm water or a short tracing section while preserving the route’s village, heritage, and recovery rhythm.', language), href: '/safaris/culture-outdoor-mix/' },
+ { number: '03', title: pickText('经典全景线', 'Classic Panorama Route', language), copy: pickText('只在荔波段顺路加入轻量亲水,不与小七孔全天步行或长转场强行叠加。', 'Add only a light on-route water session in Libo, not on top of a full Xiaoqikong walk or long transfer.', language), href: '/safaris/classic-guizhou/' },
+ ];
+
+ return (
+
+
+
+
+
+
+
+
Karst Outdoor Adventures / 03
+
{pickText('峡谷溯溪与白水漂流', 'Canyon River Tracing & White Water Rafting', language)}
+
{pickText('从平缓亲水到活力溯溪,再到待核验的白水河段——先选水上模式,再决定哪一条河适合。', 'From calm water to active tracing and validation-dependent white water—choose the water mode before the river.', language)}
+
{pickText('先看水上分级', 'See the water levels', language)}
+
+
+
+
+
+
+
+
+
{pickText('体验定义', 'Experience Definition', language)}
+
{pickText('亲水、溯溪与白水漂流,是三种不同的决策。', 'Calm water, stream tracing, and white water are three different decisions.', language)}
+
{pickText('客户文档以荔波喀斯特峡谷与黔南森林溪流为地理依托,提出溯溪、皮划艇/漂流艇、小众水潭与山野野餐。这些方向不能默认合并:具体河段、强度、船型、年龄条件、水文和运营方必须分开确认。', 'The brief anchors this experience in Libo’s karst canyons and Qiannan forest streams, proposing tracing, kayaks or rafts, quiet pools, and wild picnics. These do not automatically combine: river, intensity, craft, age rules, hydrology, and operator must be checked separately.', language)}
+
+
+ - {pickText('地理依托', 'Geographic Base', language)}
- {pickText('荔波喀斯特峡谷 / 黔南森林溪流候选', 'Libo karst canyons / Qiannan forest streams', language)}
+ - {pickText('活动形式', 'Format', language)}
- {pickText('私家小团 / 一天只选一档水上活动', 'Private small group / one water level per day', language)}
+ - {pickText('强度', 'Level', language)}
- {pickText('轻量亲水 / 活力溯溪 / 白水候选', 'Gentle water / Active tracing / White-water candidate', language)}
+ - {pickText('适合', 'Best For', language)}
- {pickText('愿意按水性、体力与年龄条件选择对应模式的客人', 'Guests open to a mode matched to water confidence, fitness, and age rules', language)}
+ - {pickText('执行方式', 'Operation', language)}
- {pickText('河段、水文、运营方、人员、装备、保险与退出逐项确认', 'River, hydrology, operator, team, equipment, insurance, and exit checked item by item', language)}
+ - {pickText('备选', 'Fallback', language)}
- {pickText('水森林步道 / 峡谷摄影 / 村寨 / 山野咖啡', 'Water-forest trail / canyon photography / village / mountain coffee', language)}
+
+
+
+
+
+
+
+
01 / Water Grading{pickText('先选水上模式,再选河段和装备。', 'Choose the water mode before the river and gear.', language)}
{pickText('轻量亲水、溯溪和白水漂流对客人能力、年龄条件、艇船、人员和救援系统的要求不同。', 'Gentle water, tracing, and white water require different guest ability, age rules, craft, staffing, and rescue systems.', language)}
+
{levels.map((level) =>
{level.number}{level.label}
{level.title}
{level.copy}
{level.gate})}
+
+
+
+
+
+
+
02 / How the Day Works
{pickText('一个水上日,只做一个清晰的选择。', 'One water day. One clear choice.', language)}
+
{flow.map((item, index) => - {String(index + 1).padStart(2, '0')}
)}
+
+
+
+
+
+
03 / Go or No-Go{pickText('水不对、人不匹配或退出不清楚,就不下水。', 'Wrong water, wrong match, or unclear exit means no entry.', language)}
{pickText('客户文档中的“全年龄、专业救生衣与护具、持证溯溪向导、全程实时监测”会转为具体河段与运营方的核验项。', 'The brief’s all-ages, professional equipment, certified guide, and full-time live monitoring claims become river- and operator-specific verification items.', language)}
+
{gates.map((gate, index) =>
{String(index + 1).padStart(2, '0')}{gate.title}
{gate.copy}
)}
+
+
{pickText('可以写入正式方案', 'What the final plan can promise', language)}- {pickText('明确选择平缓亲水、溯溪或已核验白水中的一项', 'One clearly selected mode: calm water, tracing, or validated white water', language)}
- {pickText('具名河段、运营方、人员、装备与地面备选', 'Named river, operator, team, equipment, and surface fallback', language)}
- {pickText('列明年龄/能力条件、保险、通信、撤离与接驳', 'Age/ability rules, insurance, communication, exit, and transfers', language)}
+
{pickText('必须按具体河段复核', 'Claims that require river-specific proof', language)}- {pickText('“全年龄”和平缓段亲子的最低年龄、身高/体重与陪同规则', '“All ages” and exact family minimum age, size, and companion rules', language)}
- {pickText('持证溯溪向导、操作人员资料与水上救援方案', 'Certified tracing guide, staff records, and water-rescue plan', language)}
- {pickText('救生衣/护具/艇船检查、实时水位与天气监测、白水河段难度与保险覆盖', 'Equipment/craft inspections, live monitoring, white-water difficulty, and insurance coverage', language)}
+
+
+
+
+
+ 04 / Route Pairing
{pickText('把河流变成一段有节奏的旅程,而不是把所有水上玩法放在一天。', 'Make the river a journey chapter—not every water activity in one day.', language)}
+
+
+
+
+
+ );
+}
+
+function KarstHikingCyclingDetailPage() {
+ const { language } = useTravelSite();
+ const levels = [
+ {
+ number: '01',
+ label: pickText('轻量', 'Gentle', language),
+ title: pickText('万峰林田园慢骑或步行', 'Wanfenglin Country Ride or Walk', language),
+ copy: pickText(
+ '在峰林与田园之间选择短程慢骑或步行,不默认把两万座峰林写成可验证的现场数量,也不把“全年龄”当作统一承诺。自行车供应、道路交通、头盔、身高适配、陪骑与接回车辆按日期确认。',
+ 'Choose a short country ride or walk through the peak-forest landscape. The “20,000 peaks” and “all ages” claims are not treated as universal promises. Bike supply, road traffic, helmets, sizing, ride support, and recovery vehicle are confirmed by date.',
+ language,
+ ),
+ gate: pickText('适合想看风景、拍照与保持舒缓节奏的客人', 'Best for scenery, photography, and an unhurried pace', language),
+ },
+ {
+ number: '02',
+ label: pickText('活力', 'Active', language),
+ title: pickText('茂兰喀斯特森林徒步', 'Maolan Karst Forest Hike', language),
+ copy: pickText(
+ '以森林步道、湿润岩面、树根与喀斯特地形为主。溶洞停靠只有在具体开放状态、向导、照明、天气与退出条件通过后才加入;世界遗产地的具体进入范围也需按当日规则确认。',
+ 'A forest hike across damp rock, roots, and karst terrain. Any cave stop enters the plan only after access, guide, lighting, weather, and exit are cleared; the exact accessible area within the heritage landscape is also date-specific.',
+ language,
+ ),
+ gate: pickText('需要稳定步行能力,并接受湿滑、不平整与天气变化', 'Requires steady walking ability and comfort with wet, uneven ground and changing weather', language),
+ },
+ {
+ number: '03',
+ label: pickText('进阶候选', 'Advanced Candidate', language),
+ title: pickText('赤水河谷长距离骑行', 'Chishui River Valley Distance Ride', language),
+ copy: pickText(
+ '客户文档中的 160 公里作为道路网络线索,而不是单日承诺里程。正式方案必须给出实际骑行距离、累计爬升、路况、车型、补给、维修、交通干扰、领骑人员、保障车、保险与中途退出点。',
+ 'The brief’s 160 km figure is treated as a route-network lead, not a promised day distance. A final plan must state actual distance, elevation gain, road surface, bike type, fuel stops, repairs, traffic exposure, ride leader, support vehicle, insurance, and exits.',
+ language,
+ ),
+ gate: pickText('只面向已确认骑行经验、体能和车辆适配的客人', 'Only for guests with confirmed riding experience, fitness, and bike fit', language),
+ },
+ ];
+ const flow = [
+ { title: pickText('行前能力与身体筛查', 'Guest Profile', language), copy: pickText('确认徒步或骑行经验、舒适里程、膝踝情况、年龄范围、怕热程度、身高与自行车尺寸需求。', 'Confirm hiking or riding experience, comfortable distance, knee and ankle history, age range, heat tolerance, height, and bike-sizing needs.', language) },
+ { title: pickText('只选一个区域和一种移动方式', 'Choose One Landscape and Mode', language), copy: pickText('万峰林、茂兰与赤水河谷不包装成一个活动日;根据旅行路线选择慢骑、徒步或进阶骑行中的一项。', 'Wanfenglin, Maolan, and Chishui River Valley are not packaged as one activity day; choose one walk, gentle ride, or advanced ride that fits the journey.', language) },
+ { title: pickText('复核路线、天气与退出', 'Recheck Route, Weather & Exit', language), copy: pickText('在出发前确认开放状态、实际距离、累计爬升、路面或步道、降雨与高温、补给、通信、中途退出和车辆接回。', 'Before departure, confirm access, actual distance, elevation, surface, rain or heat, fuel stops, communication, mid-route exits, and vehicle recovery.', language) },
+ { title: pickText('装备适配与现场说明', 'Fit and Briefing', language), copy: pickText('徒步确认鞋服、防滑与补水;骑行确认车架尺寸、刹车、变速、头盔、维修包、灯具与领骑手势。', 'For hiking, confirm footwear, grip, layers, and water; for cycling, confirm frame size, brakes, gears, helmet, repair kit, lights, and ride signals.', language) },
+ { title: pickText('分段集合、退出与恢复', 'Regroup, Exit & Recover', language), copy: pickText('按分段节点集合,任何疼痛、天气或路况变化都可提前退出;结束后安排补水、热食、换衣和接回。', 'Regroup at planned points, allow early exit for pain, weather, or surface changes, then provide hydration, warm food, dry layers, and return transfer.', language) },
+ ];
+ const gates = [
+ { title: pickText('路线、开放与天气', 'Route, Access & Weather', language), copy: pickText('具名起终点、真实里程与爬升、道路/步道状态、季节、降雨、高温、交通与开放规则。', 'Named start and finish, real distance and elevation, road or trail state, season, rain, heat, traffic, and access rules.', language) },
+ { title: pickText('运营方与现场人员', 'Operator & Field Team', language), copy: pickText('具名供应方、向导或领骑、客人比例、急救、通信、车辆调度和应急联系人。', 'Named supplier, guide or ride leader, guest ratio, first aid, communication, vehicle dispatch, and emergency contact.', language) },
+ { title: pickText('装备与车辆', 'Equipment & Bikes', language), copy: pickText('徒步防滑与补水要求;骑行车型、尺寸、头盔、刹车/变速检查、维修工具、备件与保障车。', 'Hiking grip and hydration requirements; bike type and size, helmet, brake and gear checks, tools, spares, and support vehicle.', language) },
+ { title: pickText('客人、保险与退出', 'Guest, Insurance & Exit', language), copy: pickText('年龄、健康、膝踝、体力和经验限制,活动对应保险,以及中途退出、换乘和医疗转运路径。', 'Age, health, knee and ankle, fitness and experience limits, activity-specific insurance, mid-route exits, transfers, and medical escalation.', language) },
+ ];
+ const routes = [
+ { number: '01', title: pickText('喀斯特户外探险线', 'Karst Outdoor Adventure', language), copy: pickText('安排一个完整徒步或骑行日,保留天气、路线和体力备选,不与高强度洞穴或水上项目叠加。', 'Use one complete hiking or riding day with weather, route, and ability fallbacks—not on top of a demanding cave or water activity.', language), href: '/safaris/outdoor-coffee/' },
+ { number: '02', title: pickText('均衡探索线', 'Balanced Discovery Route', language), copy: pickText('选择万峰林轻量慢骑或半日徒步,与村寨、非遗和恢复节奏保持平衡。', 'Choose a gentle Wanfenglin ride or half-day walk while preserving village, heritage, and recovery time.', language), href: '/safaris/culture-outdoor-mix/' },
+ { number: '03', title: pickText('经典全景线', 'Classic Panorama Route', language), copy: pickText('仅在兴义段顺路加入轻量峰林步行或短程慢骑,不强行加入长距离或高爬升。', 'Add only an easy peak-forest walk or short ride while in Xingyi, without forcing distance or major elevation.', language), href: '/safaris/classic-guizhou/' },
+ ];
+
+ return (
+
+
+
+
+
+
+
+
Karst Outdoor Adventures / 04
+
{pickText('喀斯特峰林徒步与骑行', 'Karst Peak Forest Hiking & Cycling', language)}
+
{pickText('三种地貌、三种移动方式——先匹配地形、里程、天气与退出,再决定哪一条路线适合。', 'Three landscapes, three ways to move—match terrain, distance, weather, and exit before choosing the route.', language)}
+
{pickText('先看三种选择', 'See the three options', language)}
+
+
+
+
+
+
+
+
+
{pickText('体验定义', 'Experience Definition', language)}
+
{pickText('万峰林、茂兰、赤水河谷,不是同一个活动日。', 'Wanfenglin, Maolan, and Chishui River Valley are not one activity day.', language)}
+
{pickText('客户文档提供三个地理依托:万峰林田园、茂兰原始森林与赤水河谷自行车路线。它们距离远、地形和保障条件不同,因此页面把它们拆为三个独立产品方向,由旅行日期、客人能力与整条线路位置决定最终选择。', 'The brief names three geographic bases: Wanfenglin countryside, Maolan forest, and the Chishui River Valley cycle route. They are far apart and require different terrain and support systems, so this page treats them as three independent product directions selected by date, guest ability, and journey geography.', language)}
+
+
+ - {pickText('地理依托', 'Geographic Base', language)}
- {pickText('万峰林 / 茂兰 / 赤水河谷候选', 'Wanfenglin / Maolan / Chishui River Valley', language)}
+ - {pickText('活动形式', 'Format', language)}
- {pickText('私家小团 / 一天只选一个区域与一种方式', 'Private small group / one region and one mode per day', language)}
+ - {pickText('强度', 'Level', language)}
- {pickText('轻量慢骑或步行 / 活力徒步 / 进阶骑行候选', 'Gentle ride or walk / Active hike / Advanced ride candidate', language)}
+ - {pickText('适合', 'Best For', language)}
- {pickText('愿意按体力、经验、膝踝与天气选择对应模式的客人', 'Guests open to matching mode with fitness, experience, joint health, and weather', language)}
+ - {pickText('执行方式', 'Operation', language)}
- {pickText('路线、里程、爬升、装备、团队、保险与退出逐项确认', 'Route, distance, elevation, equipment, team, insurance, and exit checked item by item', language)}
+ - {pickText('备选', 'Fallback', language)}
- {pickText('峰林摄影 / 村寨慢行 / 山野咖啡 / 室内非遗', 'Peak-forest photography / village walk / mountain coffee / indoor craft', language)}
+
+
+
+
+
+
+
+
01 / Choose Your Mode{pickText('先选地貌与移动方式,再谈里程。', 'Choose the landscape and mode before the mileage.', language)}
{pickText('田园慢骑、森林徒步与进阶骑行对路线、装备、体力和保障系统的要求完全不同。', 'A country ride, forest hike, and advanced distance ride require completely different routes, gear, fitness, and support.', language)}
+
{levels.map((level) =>
{level.number}{level.label}
{level.title}
{level.copy}
{level.gate})}
+
+
+
+
+
+
+
02 / How the Day Works
{pickText('一个户外日,只做一个清晰的选择。', 'One outdoor day. One clear choice.', language)}
+
{flow.map((item, index) => - {String(index + 1).padStart(2, '0')}
)}
+
+
+
+
+
+
03 / Go or No-Go{pickText('路线不明、装备不合或退出不清楚,就不出发。', 'Unclear route, poor fit, or no exit means no departure.', language)}
{pickText('客户文档中的“两万座峰林、160 公里专用自行车道、全年龄段”会转为具名路线与运营方的核验项,不直接成为统一营销承诺。', 'The brief’s “20,000 peaks,” “160 km dedicated cycle path,” and “all ages” claims become route- and operator-specific checks—not universal marketing promises.', language)}
+
{gates.map((gate, index) =>
{String(index + 1).padStart(2, '0')}{gate.title}
{gate.copy}
)}
+
+
{pickText('可以写入正式方案', 'What the final plan can promise', language)}- {pickText('明确选择一个区域、一种移动方式与对应强度', 'One named region, mode, and matched intensity', language)}
- {pickText('具名起终点、实际里程/爬升、供应方、装备与接驳', 'Named start/finish, actual distance/elevation, supplier, equipment, and transfers', language)}
- {pickText('列明天气备选、能力条件、保险、通信与退出', 'Weather fallback, ability rules, insurance, communication, and exits', language)}
+
{pickText('必须按具体产品复核', 'Claims requiring product-specific proof', language)}- {pickText('“两万座峰林”的准确口径和可使用来源', 'The exact basis and usable source for “20,000 peaks”', language)}
- {pickText('“160 公里专用自行车道”的实际路段、路权、开放和维护状态', 'The exact section, right-of-way, access, and maintenance behind “160 km dedicated cycle path”', language)}
- {pickText('“全年龄”、世界遗产进入范围、车型照片、向导/领骑资料与保险覆盖', '“All ages,” heritage access, bike imagery, guide/ride-leader records, and insurance coverage', language)}
+
+
+
+
+
+ 04 / Route Pairing
{pickText('让步行或骑行成为旅程里恰到好处的一天。', 'Make walking or riding the right-sized day in the journey.', language)}
+
+
+
+
+
+ );
+}
+
+function CaveLuxuryDiningDetailPage() {
+ const { language } = useTravelSite();
+ const formats = [
+ {
+ number: '01',
+ label: pickText('轻量', 'Gentle', language),
+ title: pickText('洞穴咖啡与茶点', 'Underground Coffee & Tea', language),
+ copy: pickText(
+ '在已经具备安全步道、照明、座席与接待条件的洞穴空间中安排 60–90 分钟咖啡或茶点。菜单、热水、电力、杯具、饮用水、过敏原和垃圾回收按场地确认,不把临时野洞改造成餐厅。',
+ 'A 60–90 minute coffee or tea service inside a cave venue already equipped with safe paths, lighting, seating, and guest reception. Menu, hot water, power, drinkware, potable water, allergens, and waste removal are venue-specific; a wild cave is never improvised into a dining room.',
+ language,
+ ),
+ status: pickText('适合希望安静停留与拍摄、但不需要完整正餐的客人', 'For guests seeking a quiet, photogenic pause without a full meal', language),
+ },
+ {
+ number: '02',
+ label: pickText('私家餐叙', 'Private Dining', language),
+ title: pickText('洞穴私家晚宴', 'Private Cave Dinner', language),
+ copy: pickText(
+ '以具名菜单、座位布置、服务人员、后厨/出餐路径、温控与卫生方案为基础设计 2–3 小时晚宴。默认使用无明火氛围灯;只有场地书面允许并完成消防复核时,才讨论真实蜡烛或其他火源。',
+ 'A 2–3 hour dinner built around a named menu, seating plan, service team, kitchen and delivery route, temperature control, and hygiene plan. Flame-free ambient lighting is the default; real candles or any open flame are considered only with written venue permission and fire review.',
+ language,
+ ),
+ status: pickText('餐食、酒水、花艺、灯光、独享范围与超时费用逐项报价', 'Food, drinks, florals, lighting, exclusivity, and overtime are quoted item by item', language),
+ },
+ {
+ number: '03',
+ label: pickText('组合候选', 'Combined Candidate', language),
+ title: pickText('轻量探洞后落座', 'Light Cave Walk, Then Dine', language),
+ copy: pickText(
+ '先完成独立的轻量洞穴步行,再回到具备接待条件的空间落座。探洞段需要单独核验开放、水位、地面、向导、头盔、头灯、鞋服与退出;饮酒只安排在步行全部结束之后。',
+ 'Complete a separately managed light cave walk before returning to the hospitality-ready area. The walk has its own access, water, surface, guide, helmet, headlamp, footwear, and exit checks; alcohol is served only after all walking is complete.',
+ language,
+ ),
+ status: pickText('不是边走边吃,也不把餐饮场地照片当作探洞安全证明', 'Not a roaming meal, and dining imagery is not evidence of safe cave exploration', language),
+ },
+ ];
+ const flow = [
+ { title: pickText('确认客人需求与限制', 'Guest Brief', language), copy: pickText('确认人数、日期、用餐时段、饮食禁忌与过敏、酒水、行动能力、怕黑/幽闭感、儿童安排和仪式需求。', 'Confirm group size, date, meal time, diet and allergies, alcohol, mobility, darkness or claustrophobia concerns, children, and occasion needs.', language) },
+ { title: pickText('只从具名可接待场地中选择', 'Choose a Named Hospitality Venue', language), copy: pickText('确认场地授权、开放时间、入口与步道、地面、防坠、水体边界、座席、卫生间、通信、应急照明和双向撤离。', 'Confirm venue authority, hours, entrance and path, floor, fall and water edges, seating, toilets, communication, emergency lighting, and two-way evacuation.', language) },
+ { title: pickText('锁定菜单、团队与接驳', 'Lock Menu, Team & Transfers', language), copy: pickText('确定菜单和过敏原表、厨师/供应商、饮用水、保温/冷链、服务人员、英文支持、酒水规则,以及客人和物资的往返接驳。', 'Fix the menu and allergen sheet, chef or caterer, potable water, hot/cold chain, service team, English support, alcohol rules, and guest and supply transfers.', language) },
+ { title: pickText('现场复核与无痕布置', 'Site Check & Low-Impact Setup', language), copy: pickText('活动前复核天气、水位、湿滑、落石、照明、电力和消防;布置不打孔、不触碰洞穴沉积物,电线防水防绊,垃圾与污水全部带离。', 'Before service, recheck weather, water, slip and rockfall, lighting, power, and fire controls. No drilling or touching formations; cables are water- and trip-managed, and all waste and wastewater leave the cave.', language) },
+ { title: pickText('迎宾、用餐与安全离场', 'Host, Dine & Exit', language), copy: pickText('入场先说明路线、卫生间、应急照明和集合点;结束后清点客人及物资,关闭临时设备、恢复场地,并由专车送回。', 'On arrival, brief paths, toilets, emergency lighting, and regroup points. Afterwards, count guests and equipment, shut temporary systems, restore the site, and return by private transfer.', language) },
+ ];
+ const gates = [
+ { title: pickText('场地授权与洞穴保护', 'Venue Authority & Cave Protection', language), copy: pickText('具名场地、可开展餐饮/活动的书面边界、开放状态、容量、独享范围,以及不破坏岩体、沉积物、水体和生物的布置规则。', 'Named venue, written hospitality/activity boundary, access status, capacity, exclusive area, and setup rules protecting rock, formations, water, and cave life.', language) },
+ { title: pickText('消防、电力、照明与撤离', 'Fire, Power, Lighting & Evacuation', language), copy: pickText('是否允许明火、用电负荷、漏保与防水、常规/应急照明、通风、通信、两条撤离路径、灭火器材和医疗转运。', 'Open-flame rule, power load, residual-current and waterproof protection, normal/emergency light, ventilation, communication, two exit routes, fire equipment, and medical transfer.', language) },
+ { title: pickText('餐饮卫生与酒水', 'Food Hygiene & Alcohol', language), copy: pickText('具名餐饮供应方、制作与出餐位置、饮用水、冷热链、餐具消毒、手部卫生、过敏原、垃圾/污水处理与酒水许可及份量。', 'Named food supplier, preparation and service points, potable water, hot/cold chain, utensil hygiene, handwashing, allergens, waste/wastewater, and alcohol permission and quantities.', language) },
+ { title: pickText('人员、客人、接驳与保险', 'Team, Guests, Transfers & Insurance', language), copy: pickText('场地负责人、服务/向导人员、英文支持、客人行动与健康限制、活动前后接驳、备用场地、责任边界与保险覆盖。', 'Venue lead, service or guide team, English support, guest mobility and health limits, pre/post transfers, fallback venue, responsibilities, and insurance coverage.', language) },
+ ];
+ const routes = [
+ { number: '01', title: pickText('经典全景线', 'Classic Panorama Route', language), copy: pickText('在兴义、安顺或返程节点加入咖啡茶点或私家晚宴,以具名场地距离决定,不为一顿饭大幅绕路。', 'Add coffee or private dining near Xingyi, Anshun, or a return node, selected by named-venue geography rather than a major meal-only detour.', language), href: '/safaris/classic-guizhou/' },
+ { number: '02', title: pickText('喀斯特户外探险线', 'Karst Outdoor Adventure', language), copy: pickText('作为洞穴活动后的恢复餐叙,必须与进阶探洞分开管理;晚宴当天不再叠加高强度项目。', 'Use as recovery after a cave day, managed separately from advanced exploration; no additional demanding activity on dinner day.', language), href: '/safaris/outdoor-coffee/' },
+ { number: '03', title: pickText('均衡探索线', 'Balanced Discovery Route', language), copy: pickText('适合安排轻量咖啡、纪念日晚宴或摄影停留,与村寨和非遗节奏保持平衡。', 'Works as gentle coffee, an occasion dinner, or a photography pause while preserving village and heritage pacing.', language), href: '/safaris/culture-outdoor-mix/' },
+ ];
+
+ return (
+
+
+
+
+
+
+
+
Unique Local Experiences / 01
+
{pickText('洞穴野奢体验・地下咖啡与私家晚宴', 'Cave Luxury Experience: Underground Coffee & Private Dining', language)}
+
{pickText('浪漫来自安静与尺度,安心来自具名场地、菜单、团队、照明和撤离。', 'Atmosphere comes from quiet and restraint; confidence comes from a named venue, menu, team, lighting, and exit.', language)}
+
{pickText('查看三种体验方式', 'See the three formats', language)}
+
+
+
+
+
+
+
+
+
{pickText('体验定义', 'Experience Definition', language)}
+
{pickText('不是在任意溶洞里摆一张桌子,而是在可接待场地里完成一场克制的餐叙。', 'Not a table placed in any cave—a restrained service inside a hospitality-ready venue.', language)}
+
{pickText('客户文档提出地下咖啡、烛光晚宴和轻量探洞。页面将三者拆开:餐饮只进入具备步道、照明、卫生和撤离条件的具名场地;探洞另行使用户外活动标准。所谓“18℃恒温”只在具体场地提供测量或官方资料后使用。', 'The brief proposes underground coffee, candlelit dinner, and a light cave walk. This page separates them: food service uses only a named venue with paths, lighting, hygiene, and exit; cave walking follows separate outdoor standards. The proposed “constant 18°C” is used only when supported by measurements or official venue evidence.', language)}
+
+
+ - {pickText('地理依托', 'Geographic Base', language)}
- {pickText('贵州具名、可接待的天然洞穴场地 / 按日期匹配', 'Named hospitality-ready natural cave in Guizhou / matched by date', language)}
+ - {pickText('体验形式', 'Formats', language)}
- {pickText('咖啡茶点 / 私家晚宴 / 轻量洞穴步行后落座', 'Coffee and tea / Private dinner / Light cave walk then dine', language)}
+ - {pickText('建议时长', 'Suggested Time', language)}
- {pickText('60–90 分钟至 2–3 小时,组合体验另计', '60–90 minutes to 2–3 hours; combined format quoted separately', language)}
+ - {pickText('适合', 'Best For', language)}
- {pickText('情侣纪念日、小型家庭、私家小团与摄影客人', 'Couples, small families, private groups, and photography-focused guests', language)}
+ - {pickText('执行方式', 'Operation', language)}
- {pickText('场地、消防、餐饮、人员、接驳、保险与撤离逐项确认', 'Venue, fire, food, team, transfers, insurance, and exit checked item by item', language)}
+ - {pickText('室内备选', 'Fallback', language)}
- {pickText('酒店私宴 / 山野餐厅 / 洞穴风格空间 / 下午茶', 'Hotel private room / mountain restaurant / cave-inspired space / afternoon tea', language)}
+
+
+
+
+
+
+
+
+
+
+
02 / How Hosting Works
{pickText('一场晚宴,从客人离开洞穴时依然安心来倒推。', 'Design the dinner backwards from a calm, safe exit.', language)}
+
{flow.map((item, index) => - {String(index + 1).padStart(2, '0')}
)}
+
+
+
+
+
+
03 / Hosting Gates{pickText('好看只是结果,接待系统才是产品。', 'The atmosphere is the result; the hosting system is the product.', language)}
{pickText('“专属英文服务、精致餐食、氛围布置、往返接送”会在正式方案中拆成具名供应方、人员、菜单、设备和价格,而不是一句笼统承诺。', '“Dedicated English service, refined food, styling, and transfers” become named suppliers, people, menus, systems, and prices in the final proposal—not one generic promise.', language)}
+
{gates.map((gate, index) =>
{String(index + 1).padStart(2, '0')}{gate.title}
{gate.copy}
)}
+
+
{pickText('可以写入正式方案', 'What the final plan can promise', language)}- {pickText('具名洞穴场地、使用区域、真实开放时段与当日温湿度建议', 'Named cave venue, usable area, real hours, and date-specific temperature/humidity advice', language)}
- {pickText('具名菜单、过敏原、餐饮团队、英文支持、灯光和往返接驳', 'Named menu, allergens, food team, English support, lighting, and return transfers', language)}
- {pickText('明确消防、电力、卫生间、通信、保险、撤离和天气/水位备选', 'Clear fire, power, toilet, communication, insurance, exit, and weather/water fallback', language)}
+
{pickText('必须按场地复核', 'Claims requiring venue-specific proof', language)}- {pickText('所有贵州洞穴“18℃恒温”、绝对静谧或完全独享', 'A universal “constant 18°C,” absolute silence, or full exclusivity across Guizhou caves', language)}
- {pickText('真实蜡烛/篝火、洞内烹饪、酒水服务与食品经营边界', 'Real candles or fire, in-cave cooking, alcohol service, and food-operation permissions', language)}
- {pickText('专属英文人员、精致餐食、轻量探洞、往返接送与摄影布置默认包含', 'Dedicated English staff, refined food, light cave walk, transfers, or photography styling as default inclusions', language)}
+
+
+
+
+
+ 04 / Route Pairing
{pickText('让餐叙成为旅程的停顿,而不是一次为了拍照的绕路。', 'Make the meal a pause in the journey—not a photography-only detour.', language)}
+
+
+
+
+
+ );
+}
+
+function WildCoffeeDetailPage() {
+ const { language } = useTravelSite();
+ const formats = [
+ {
+ number: '01',
+ label: pickText('优先推荐', 'Preferred', language),
+ title: pickText('具名观景咖啡馆', 'Named Scenic Café', language),
+ copy: pickText(
+ '选择已有营业主体、固定步道、护栏、座席、卫生间与稳定出品的观景咖啡馆。正式方案写明店名、位置、营业时间、预约方式、停车/步行距离和雨天可用区域,不把照片中的某个场地默认套用到荔波或万峰林。',
+ 'Choose an established scenic café with a named operator, fixed paths, edge protection, seating, toilets, and consistent service. The final plan names the venue, location, hours, reservation, parking or walk distance, and wet-weather area—without assuming a pictured site is in Libo or Wanfenglin.',
+ language,
+ ),
+ status: pickText('风险最低,也最容易稳定安排咖啡、甜点、洗手间与车辆接回', 'The most reliable option for coffee, snacks, toilets, and vehicle recovery', language),
+ },
+ {
+ number: '02',
+ label: pickText('顺路停靠', 'On-Route Pause', language),
+ title: pickText('山林、梯田或村寨咖啡', 'Forest, Terrace or Village Coffee', language),
+ copy: pickText(
+ '把一家山林木屋、梯田窗景或村寨咖啡馆放在实际行车路线中,用 45–90 分钟恢复体力。营业状态、咖啡供应、餐食、无障碍、室内座位和旺季客流按日期复核,不为了“网红视角”增加大幅绕行。',
+ 'Place a forest cabin, terrace-window, or village café on the actual drive for a 45–90 minute recovery pause. Recheck opening, coffee and food service, accessibility, indoor seating, and peak crowds by date—without a major detour for a social-media angle.',
+ language,
+ ),
+ status: pickText('最适合接在徒步、摄影、自驾或村寨体验之后', 'Best after hiking, photography, road travel, or a village experience', language),
+ },
+ {
+ number: '03',
+ label: pickText('专项候选', 'Special Setup Candidate', language),
+ title: pickText('私家户外冲煮', 'Private Outdoor Brew', language),
+ copy: pickText(
+ '只有土地/景区/社区授权、稳定平台或安全地面、临崖隔离、天气、热水与火源规则、饮用水、食品卫生、垃圾与污水带离、通信和退出全部明确时才搭建。无许可的悬崖边、山顶或保护地不做私家布置。',
+ 'Set up only with land, scenic-area, or community authority; stable ground and edge separation; weather, hot-water and fire rules; potable water, food hygiene, waste and wastewater removal, communication, and exit. No private setup on an unauthorized cliff, summit, or protected site.',
+ language,
+ ),
+ status: pickText('日出/日落、独享和无人打扰只能按具体点位与日期申请,不能保证', 'Sunrise, sunset, exclusivity, and solitude are requested by site and date—not guaranteed', language),
+ },
+ ];
+ const flow = [
+ { title: pickText('先确定这一杯咖啡在路线中的作用', 'Define the Pause', language), copy: pickText('确认是晨间出发、徒步后恢复、摄影停靠、日落时段还是纪念日布置,并确定可接受的绕行和步行时间。', 'Decide whether this is a morning start, post-hike recovery, photography pause, sunset window, or occasion setup, plus acceptable detour and walk time.', language) },
+ { title: pickText('选择具名场地或授权点位', 'Choose a Named or Authorized Site', language), copy: pickText('先选公开咖啡馆;如需户外冲煮,则取得土地、景区或社区的明确授权,并确认入口、停车、步道、平台、护栏/边界和卫生间。', 'Prefer an established café; for outdoor brewing, obtain clear land, scenic-area, or community authority and confirm entrance, parking, path, platform, edge protection, and toilets.', language) },
+ { title: pickText('复核天气、光线与临崖条件', 'Recheck Weather, Light & Edge', language), copy: pickText('按风、雨、雷电、雾、地面湿滑、落石和能见度决定执行。日出/日落还要确认营业时段、照明、返程路况和夜间步行。', 'Use wind, rain, lightning, fog, slippery ground, rockfall, and visibility for the go/no-go call. Sunrise or sunset also requires hours, lighting, return-road, and night-walk checks.', language) },
+ { title: pickText('确认咖啡、热水与无痕服务', 'Confirm Coffee & Low-Impact Service', language), copy: pickText('写明咖啡豆/饮品、热水来源、用电或火源、饮用水、杯具、甜点、过敏原、洗手、垃圾分类和全部带离方式。', 'State beans and drinks, hot-water source, power or flame, potable water, cups, snacks, allergens, hand hygiene, waste sorting, and full pack-out.', language) },
+ { title: pickText('停留、收整与车辆接回', 'Pause, Pack Down & Return', language), copy: pickText('控制客人靠近边缘的范围和停留时间;天气变化立即转入室内或取消。结束后恢复场地、清点垃圾与设备,由车辆在具名位置接回。', 'Control edge proximity and dwell time; move indoors or cancel when conditions change. Restore the site, count waste and equipment, and meet the vehicle at a named point.', language) },
+ ];
+ const gates = [
+ { title: pickText('场地身份与授权', 'Venue Identity & Authority', language), copy: pickText('具名营业主体或土地/景区/社区许可、可使用区域、营业/进入时段、容量、预约、停车、步行入口与费用。', 'Named operator or land/scenic/community permission, usable area, hours, capacity, reservation, parking, walking access, and fee.', language) },
+ { title: pickText('临崖、步道与天气', 'Edge, Path & Weather', language), copy: pickText('护栏或安全边界、平台承载、路面、落石、风雨雷电/雾、日出日落照明、通信和中途退出。', 'Edge barrier or safe boundary, platform capacity, surface, rockfall, wind/rain/lightning/fog, sunrise/sunset light, communication, and exit.', language) },
+ { title: pickText('饮品、火源与卫生', 'Drinks, Fire & Hygiene', language), copy: pickText('饮用水、热水与电力/燃气规则、食品供应方、杯具/手部卫生、过敏原、垃圾和污水带离,以及保护地禁火要求。', 'Potable and hot water, power or gas rules, food supplier, cup and hand hygiene, allergens, waste and wastewater removal, and protected-area fire bans.', language) },
+ { title: pickText('客人、接驳与应急', 'Guests, Transfers & Response', language), copy: pickText('行动能力、儿童看护、恐高、鞋服、司机与接回点、备用室内场地、急救、医疗转运和责任/保险边界。', 'Mobility, child supervision, height exposure, footwear and layers, driver and pickup point, indoor fallback, first aid, medical transfer, and responsibility or insurance boundary.', language) },
+ ];
+ const routes = [
+ { number: '01', title: pickText('经典全景线', 'Classic Panorama Route', language), copy: pickText('在万峰林、黄果树或跨城路上加入一家顺路的具名咖啡馆,控制在 45–90 分钟。', 'Add one named on-route café near Wanfenglin, Huangguoshu, or an intercity drive, limited to 45–90 minutes.', language), href: '/safaris/classic-guizhou/' },
+ { number: '02', title: pickText('喀斯特户外探险线', 'Karst Outdoor Adventure', language), copy: pickText('放在高活动量之后作为真正的恢复节点,优先选择有护栏、热食、卫生间和车辆直达的场地。', 'Use as real recovery after an active day, prioritizing edge protection, warm food, toilets, and vehicle access.', language), href: '/safaris/outdoor-coffee/' },
+ { number: '03', title: pickText('均衡探索线', 'Balanced Discovery Route', language), copy: pickText('与村寨、手作或摄影半日组合;私家布置只在不干扰社区与环境时加入。', 'Pair with a village, craft, or photography half-day; add a private setup only when it does not disrupt community or environment.', language), href: '/safaris/culture-outdoor-mix/' },
+ ];
+
+ return (
+
+
+
+
+
+
+
+
Unique Local Experiences / 02
+
{pickText('悬崖与山野观景咖啡', 'Cliffside & Mountain-View Coffee', language)}
+
{pickText('先找到合法、安全、顺路的观景位置,再决定这一杯咖啡值得停多久。', 'Find a legal, safe, on-route viewpoint before deciding how long the coffee pause deserves.', language)}
+
{pickText('查看三种停靠方式', 'See the three formats', language)}
+
+
+
+
+
+
+
+
+
{pickText('体验定义', 'Experience Definition', language)}
+
{pickText('好风景不一定需要私搭,一家正确的咖啡馆往往更松弛。', 'A good view does not require a private setup—the right café is often more relaxed.', language)}
+
{pickText('客户文档提出荔波森林悬崖、万峰林山顶和峡谷观景台,并强调小众、无人拥挤和独享。客户图片实际展示了多种公开咖啡空间,但不足以证明所有图片的地理位置,也不能保证独享。因此第一版优先具名营业场地,私家搭建只作为经过授权的候选。', 'The brief proposes Libo forest cliffs, Wanfenglin summits, and canyon viewpoints, emphasizing privacy and no crowds. The supplied images show several established cafés but do not prove every location or guarantee exclusivity. This first version prioritizes named operating venues and treats private setup as an authority-dependent candidate.', language)}
+
+
+ - {pickText('地理依托', 'Geographic Base', language)}
- {pickText('贵州峰林 / 峡谷 / 梯田 / 山林沿线具名场地', 'Named venues along Guizhou peak forests, canyons, terraces, and forest routes', language)}
+ - {pickText('体验形式', 'Formats', language)}
- {pickText('观景咖啡馆 / 顺路咖啡停靠 / 私家户外冲煮候选', 'Scenic café / On-route coffee pause / Private outdoor brew candidate', language)}
+ - {pickText('建议时长', 'Suggested Time', language)}
- {pickText('45–90 分钟,日出/日落和户外布置另行确认', '45–90 minutes; sunrise, sunset, and private setup confirmed separately', language)}
+ - {pickText('适合', 'Best For', language)}
- {pickText('休闲度假、摄影、咖啡爱好者与户外后的恢复停靠', 'Leisure, photography, coffee lovers, and post-outdoor recovery', language)}
+ - {pickText('执行方式', 'Operation', language)}
- {pickText('场地、步道、临崖、天气、服务、火源、垃圾、接驳逐项确认', 'Venue, path, edge, weather, service, fire, waste, and transfer checked item by item', language)}
+ - {pickText('备选', 'Fallback', language)}
- {pickText('室内窗景咖啡馆 / 酒店下午茶 / 村寨茶歇', 'Indoor view café / hotel afternoon tea / village tea stop', language)}
+
+
+
+
+
+
+
+
+
+
+
02 / How the Stop Works
{pickText('真正的松弛感,来自顺路、可坐、能避雨,也能安全离开。', 'Real ease means on-route, seated, weather-ready, and easy to leave safely.', language)}
+
{flow.map((item, index) => - {String(index + 1).padStart(2, '0')}
)}
+
+
+
+
+
+
03 / Operating Gates{pickText('没有授权、边界不清或天气不对,就换一家室内咖啡馆。', 'No authority, unclear edge, or wrong weather means an indoor café instead.', language)}
{pickText('“小众私家点位、无游客拥挤、独享景观”会转换成具体点位、时段和预约状态,不作为统一承诺。', '“Hidden private site, no crowds, exclusive view” become site-, time-, and reservation-specific checks—not blanket promises.', language)}
+
{gates.map((gate, index) =>
{String(index + 1).padStart(2, '0')}{gate.title}
{gate.copy}
)}
+
+
{pickText('可以写入正式方案', 'What the final plan can promise', language)}- {pickText('具名咖啡馆/授权点位、实际营业或进入时间、预约与费用', 'Named café or authorized site, real hours or access time, reservation, and fee', language)}
- {pickText('停车和步行距离、平台/护栏、座席、卫生间、饮品和雨天区域', 'Parking and walk length, platform or barrier, seating, toilets, drinks, and wet-weather area', language)}
- {pickText('日出/日落时段、司机接回、天气备选与户外布置/撤收清单', 'Sunrise or sunset timing, driver recovery, weather fallback, and outdoor setup/pack-down list', language)}
+
{pickText('必须按点位复核', 'Claims requiring site-specific proof', language)}- {pickText('图片中的咖啡馆是否位于荔波、万峰林或客户所述目的地', 'Whether the pictured cafés are in Libo, Wanfenglin, or another named destination', language)}
- {pickText('“小众、无人拥挤、独享”、日出/日落营业和专属摄影位', '“Hidden, uncrowded, exclusive,” sunrise/sunset operation, or private photo position', language)}
- {pickText('临崖座椅/悬挂设施、户外用火、食物服务、土地许可与保险覆盖', 'Cliff seating or suspended structures, outdoor fire, food service, land permission, and insurance', language)}
+
+
+
+
+
+ 04 / Route Pairing
{pickText('把咖啡放在真正需要停下来的地方。', 'Place the coffee where the journey actually needs a pause.', language)}
+
+
+
+
+
+ );
+}
+
+function VillageImmersionDetailPage() {
+ const { language } = useTravelSite();
+ const formats = [
+ {
+ number: '01',
+ label: pickText('苗族方向', 'Miao Direction', language),
+ title: pickText('苗族吊脚楼住家候选', 'Miao Stilt-House Homestay Candidate', language),
+ copy: pickText(
+ '以雷山掌坳或其他具名苗寨为地理候选。半日可做公共村路与木楼建筑观察,再从家常饭、手作或当季农事中选一项;一至两晚只有在经营主体或留宿人、具体房间、卫浴、消防、夜间出入和住宿登记全部确认后才进入方案。',
+ 'Use Zhangao in Leishan or another named Miao village as a geographic candidate. A half-day can pair a public village and timber-house walk with one hosted meal, craft, or seasonal task. One or two nights enter the plan only after the operator or host, exact room, bathroom, fire conditions, night access, and accommodation registration are confirmed.',
+ language,
+ ),
+ status: pickText('农事、火塘故事与家庭空间按主人、季节和同意确认,不作每日承诺', 'Farm work, fireside stories, and family spaces depend on the host, season, and consent—not a daily promise', language),
+ },
+ {
+ number: '02',
+ label: pickText('侗族方向', 'Dong Direction', language),
+ title: pickText('侗族鼓楼社区生活候选', 'Dong Drum-Tower Community Candidate', language),
+ copy: pickText(
+ '以黎平黄岗或其他具名侗寨为地理候选,围绕鼓楼、风雨桥、村路与稻田安排公共慢行,再按真实档期加入一顿主人餐、一项手作或一次歌唱交流。鼓楼首先是社区公共空间,不为客人临时布置“专场生活”。',
+ 'Use Huanggang in Liping or another named Dong village as a geographic candidate. Build a public walk around the drum tower, wind-and-rain bridge, lanes, and fields, then add one hosted meal, craft, or song exchange only when genuinely available. The drum tower remains a community space first—not a private set built for visitors.',
+ language,
+ ),
+ status: pickText('侗族大歌、夜间对歌与节庆不是每天固定发生,必须按社区与日期确认', 'Grand Song, evening singing, and festivals are not daily fixtures; confirm the community and date', language),
+ },
+ {
+ number: '03',
+ label: pickText('布依族方向', 'Buyi Direction', language),
+ title: pickText('布依石头寨慢居候选', 'Buyi Stone-Village Slow-Stay Candidate', language),
+ copy: pickText(
+ '以安顺石头寨、高荡或其他具名布依村寨为地理候选,安排石构建筑慢行、村寨餐食与一项具名手作或安静夜晚。不能把整座村寨、每间客房或所有新旧建筑都写成“全石古寨”,住宿仍须落实到合法经营主体和真实房间。',
+ 'Use Shitouzhai, Gaodang, or another named Buyi village around Anshun as a geographic candidate. Pair a stone-architecture walk with a village meal and one named craft or a quiet evening. Do not describe every building or room as an all-stone ancient village; the stay still requires a lawful operator and a real room.',
+ language,
+ ),
+ status: pickText('现有客户图片只作山谷与村落氛围参考,不证明具体布依村寨或住宿', 'Current supplied imagery is atmosphere only—not proof of a particular Buyi village or stay', language),
+ },
+ ];
+ const flow = [
+ { title: pickText('选择一条文化方向', 'Choose One Cultural Direction', language), copy: pickText('根据完整线路与客人兴趣,在苗族吊脚楼、侗族鼓楼社区或布依石头寨中选择一处,不把三座村寨压成同一天的民族打卡。', 'Choose one place—Miao stilt-house life, a Dong drum-tower community, or a Buyi stone village—based on the full route and guest interest, rather than compressing three villages into one ethnic checklist.', language) },
+ { title: pickText('匹配具名主体与房间', 'Match a Named Host & Room', language), copy: pickText('确认村寨、经营主体或留宿人、真实客房、卫浴、消防、行李、夜间支持、英文协助与境外客人住宿登记路径;没有这些资料时只做半日。', 'Confirm the village, operator or host, real room, bathroom, fire conditions, luggage, night support, language help, and registration path for international guests. Without this evidence, keep it a half-day.', language) },
+ { title: pickText('确定半日、一晚或两晚', 'Set Half-Day, One Night, or Two', language), copy: pickText('从公共慢行、家常饭、具名手作和当季农事中选择一至两项,提前约定可进入空间、可拍人物、翻译、报酬与取消条件。', 'Choose one or two elements from a public walk, home-style meal, named craft, or seasonal work, then agree access, photography, interpretation, compensation, and cancellation.', language) },
+ { title: pickText('出发前交付核验资料', 'Share the Evidence Before Arrival', language), copy: pickText('住宿方案提供当期房间与卫浴照片、楼梯和出口、消防与夜间联系人、菜单/过敏原、接驳、登记方式和拍摄边界,不只发一张村寨风景图。', 'For an overnight plan, share current room and bathroom images, stairs and exits, fire arrangements and night contact, menu or allergens, transfer, registration, and photo boundaries—not only a scenic village image.', language) },
+ { title: pickText('现场再确认并负责离开', 'Reconfirm On Site & Leave Responsibly', language), copy: pickText('抵达后再次说明礼仪和儿童安全,征得同意后再进入、拍摄或参与;按约定结算,不公开未获同意的人像与住址,并完成住宿登记与离店。', 'Brief etiquette and child safety again on arrival, ask before entering, photographing, or joining, settle as agreed, publish no unapproved portraits or addresses, and complete registration and departure.', language) },
+ ];
+ const gates = [
+ { title: pickText('主人、社区与真实档期', 'Host, Community & Real Availability', language), copy: pickText('具名联系人、社区同意、可接待人数、实际活动、语言协助、服务费用与取消方式;节庆和日常不为镜头临时摆拍。', 'Named contact, community consent, capacity, actual activity, language help, service fee, and cancellation; festivals and daily life are not staged for the camera.', language) },
+ { title: pickText('经营、卫生、消防与登记', 'Operation, Hygiene, Fire & Registration', language), copy: pickText('经营主体或留宿人、具体房间与卫浴、公共场所卫生许可、房屋与消防、夜间值守、旅客实名登记;境外客人住非旅馆住所时,按当地流程在入住后 24 小时内完成登记。', 'Operator or host, exact room and bathroom, public-place hygiene permit, building and fire conditions, night support, and real-name guest records. International guests in non-hotel accommodation must complete registration through the local process within 24 hours of arrival.', language) },
+ { title: pickText('饮食、活动、楼梯与儿童', 'Food, Activities, Stairs & Children', language), copy: pickText('食材与饮水、厨房卫生、过敏原、辣度、酒精,以及木楼楼梯、火源、农具、水田、牲畜、夜路、儿童看护和医疗转运。', 'Ingredients and water, kitchen hygiene, allergens, spice, alcohol, plus timber-house stairs, heat, tools, fields, animals, night paths, child supervision, and medical transfer.', language) },
+ { title: pickText('隐私、拍摄与收益', 'Privacy, Photos & Benefit', language), copy: pickText('住宅与私人区域、人物肖像同意、未成年人拍摄、素材用途、翻译准确性,以及主人、手艺人与社区实际获得的费用路径。', 'Home and private areas, portrait consent, images of minors, intended media use, interpretation accuracy, and the real payment path to hosts, artisans, and community.', language) },
+ ];
+ const routes = [
+ { number: '01', title: pickText('经典全景线', 'Classic Panorama Route', language), copy: pickText('只加入一处顺路村寨:安顺段可选布依石头寨,黔东南段可选苗寨或侗寨;半日和住宿按真实条件决定。', 'Add only one village that fits the route: a Buyi stone village around Anshun, or a Miao or Dong village in Qiandongnan, with half-day or overnight depth based on real conditions.', language), href: '/safaris/classic-guizhou/' },
+ { number: '02', title: pickText('家庭人文慢行', 'Family Heritage Pacing', language), copy: pickText('优先半日或正规民宿一晚,提前核对木楼楼梯、火源、夜路、餐食、儿童拍摄与就医距离。', 'Prefer a half-day or one night in a registered guesthouse, checking stairs, heat, night paths, food, child photography, and medical distance first.', language), href: '/safaris/classic-guizhou/' },
+ { number: '03', title: pickText('均衡探索线', 'Balanced Discovery Route', language), copy: pickText('在一座具名村寨安排经核验的一至两晚,不用“苗侗布依三寨连住”制造表面丰富。', 'Use one or two verified nights in one named village rather than a superficial three-village Miao–Dong–Buyi sampler.', language), href: '/safaris/culture-outdoor-mix/' },
+ ];
+
+ return (
+
+
+
+
+
+
+
+
Unique Local Experiences / 03
+
{pickText('原生村寨沉浸', 'Authentic Village Homestays', language)}
+
{pickText('从苗族吊脚楼、侗族鼓楼社区或布依石头寨中选择一处,以半日至 3 天 2 晚认真进入,而不是白天观光、夜间回城。', 'Choose one Miao stilt-house village, Dong drum-tower community, or Buyi stone village for a half-day to three days and two nights—beyond a daytime stop and return to the city.', language)}
+
{pickText('查看三条村寨方向', 'See the three village directions', language)}
+
+
+
+
+
+
+
+
+
{pickText('体验定义', 'Experience Definition', language)}
+
{pickText('先选对一座村寨,再决定住多久、和谁一起生活。', 'Choose the right village first—then decide how long to stay and with whom.', language)}
+
{pickText('客户文档明确提出苗族吊脚楼住家、侗族鼓楼社区生活与布依石头寨慢居,并希望提供半日至 3 天 2 晚的深度体验。本页保留这三条方向,但不把农事、家宴、火塘故事、侗族大歌或手作写成每天都有的套餐;最终内容由具名村寨、主人、季节、住宿条件与客人边界共同决定。', 'The brief clearly proposes Miao stilt-house homestays, Dong drum-tower community life, and slow stays in Buyi stone villages, from a half-day to three days and two nights. This page keeps all three directions without turning farm work, home meals, fireside stories, Grand Song, or craft into daily package items. The named village, host, season, room, and guest boundaries determine the final experience.', language)}
+
+
+ - {pickText('三条方向', 'Three Directions', language)}
- {pickText('苗族吊脚楼 / 侗族鼓楼社区 / 布依石头寨', 'Miao stilt houses / Dong drum-tower community / Buyi stone village', language)}
+ - {pickText('地理候选', 'Geographic Candidates', language)}
- {pickText('掌坳 / 黄岗 / 安顺石头寨或高荡;最终以接待主体为准', 'Zhangao / Huanggang / Shitouzhai or Gaodang; final choice follows the actual host', language)}
+ - {pickText('建议时长', 'Suggested Time', language)}
- {pickText('半日 / 经核验的一晚 / 最长 3 天 2 晚', 'Half-day / verified one night / up to 3 days and 2 nights', language)}
+ - {pickText('适合', 'Best For', language)}
- {pickText('文化爱好者、亲子、慢旅行与愿意尊重社区边界的客人', 'Culture lovers, families, slow travellers, and guests who respect community boundaries', language)}
+ - {pickText('住宿前提', 'Stay Requirement', language)}
- {pickText('具名房间 / 卫生与消防 / 实名及境外客人登记路径', 'Named room / hygiene and fire / real-name and international guest registration', language)}
+ - {pickText('活动选择', 'Activity Choice', language)}
- {pickText('按主人、社区、季节和日期选择一至两项,不保证全部出现', 'One or two items matched to host, community, season, and date—never all guaranteed', language)}
+
+
+
+
+
{pickText('侗寨建筑氛围参考 · 具体村寨、公共空间开放与住宿主体待确认', 'Dong village atmosphere · Exact village, public access, and stay operator to be confirmed', language)}
+
{pickText('木楼村寨氛围参考 · 非苗族吊脚楼客房或可住宿证明', 'Timber-village atmosphere · Not proof of a Miao guest room or bookable stay', language)}
+
{pickText('客户提供人物实拍 · 身份、地点、拍摄及公开使用授权需归档', 'Client-supplied portrait · Identity, location, capture, and publication consent require records', language)}
+
{pickText('山谷与村落氛围参考 · 非布依石头寨或具名住宿证明', 'Valley and village atmosphere · Not proof of a Buyi stone village or named stay', language)}
+
+
+
+
+
+
+
+
02 / Hosted Flow
{pickText('主人不是演职人员,客人也不是旁观的人群。', 'The host is not a performer, and the guest is not a crowd.', language)}
+
{flow.map((item, index) => - {String(index + 1).padStart(2, '0')}
)}
+
+
+
+
+
+
03 / Hosting Gates{pickText('不能说明谁接待、住哪里、钱怎么分,就不叫深度体验。', 'If we cannot name the host, room, and payment path, it is not an immersion.', language)}
{pickText('“原生态、完整民俗、传承人一对一、全部收益直达村民”都要转换成具名人物、实际活动、书面同意和结算记录。', '“Authentic, complete traditions, one-to-one heritage bearer, all benefit direct to villagers” must become named people, real activities, consent, and settlement records.', language)}
+
{gates.map((gate, index) =>
{String(index + 1).padStart(2, '0')}{gate.title}
{gate.copy}
)}
+
+
{pickText('可以写入正式方案', 'What the final plan can promise', language)}- {pickText('具名村寨、主人/手艺人、实际时长、活动、费用与取消条件', 'Named village, host or artisan, real duration, activity, fee, and cancellation', language)}
- {pickText('可进入和可拍摄范围、翻译、餐食菜单/过敏原及儿童看护安排', 'Agreed access and photo scope, interpretation, menu or allergens, and child supervision', language)}
- {pickText('具名住宿的房间、卫浴、消防、接待/登记流程、接驳和天气备选', 'Named room, bathroom, fire conditions, reception or registration, transfer, and weather fallback', language)}
+
{pickText('必须按主人和日期复核', 'Claims requiring host-and-date proof', language)}- {pickText('“原生态、未商业化、完整保留民俗”以及图片的具体村寨与人物身份', '“Untouched, uncommercialised, complete traditions,” and the pictured village or identities', language)}
- {pickText('非遗传承人一对一、鼓楼对歌、节庆、农事、抓鱼等当天一定发生', 'One-to-one heritage teaching, drum-tower songs, festivals, farming, or fish-catching on demand', language)}
- {pickText('住家/禾仓合法接待境外客人、全部收益直达村民或任何固定分成比例', 'A home or granary stay’s international reception, all benefit direct to villagers, or a fixed revenue split', language)}
+
+
{pickText('公开文化与地理信息参考:贵州省民政厅黄岗村介绍、贵州省人大掌坳苗寨介绍、国家民委及贵州公开的布依石构建筑资料。住宿执行参考贵州省民宿指导意见、现行民宿卫生与消防要求及国家移民管理局住宿登记规则;贵州当前不在 2026 年首批旅馆以外住所网上登记试点范围内,具体登记方式需向当地公安机关确认。', 'Public cultural and location references include Guizhou Civil Affairs on Huanggang, the Guizhou People’s Congress on Zhangao, and official sources on Buyi stone architecture. Stay operation follows Guizhou guesthouse guidance, current hygiene and fire requirements, and National Immigration Administration registration rules. Guizhou is not in the first 2026 online pilot for non-hotel registration, so the exact local process must be confirmed with the public security authority.', language)}
+
+
+
+
+ 04 / Route Pairing
{pickText('给村寨留出真实时间,也给社区保留自己的节奏。', 'Give the village real time—and let the community keep its own rhythm.', language)}
+
+
+
+
+
+ );
+}
+
+function EthnicFestivalsDetailPage() {
+ const { language } = useTravelSite();
+ const festivals = [
+ {
+ number: '01',
+ label: pickText('农历十月', 'Lunar October', language),
+ title: pickText('苗年', 'Miao New Year', language),
+ copy: pickText(
+ '苗年是黔东南苗族重要年节,不同村寨的过年日期、节期和公开活动并不完全相同。2026 年黔东南州公布的苗年假日为 11 月 15 日;盛装巡游、芦笙、打糍粑、斗牛或家庭年饭是否举行,仍须按具体县、村寨和当年活动表确认。',
+ 'Miao New Year is a major celebration in Qiandongnan, but dates, duration, and public programmes differ by community. Qiandongnan’s official 2026 Miao New Year holiday is 15 November; costume parades, lusheng, ciba making, bullfighting, or family meals still require the exact county, village, and current programme.',
+ language,
+ ),
+ status: pickText('客户文档所写“持续 3–15 天”不能套用于每个村寨或每位游客', 'The brief’s “3–15 days” cannot be applied to every village or visitor', language),
+ },
+ {
+ number: '02',
+ label: pickText('农历三月十五至十七', 'Lunar 3rd month, days 15–17', language),
+ title: pickText('苗族姊妹节', 'Miao Sisters’ Meal Festival', language),
+ copy: pickText(
+ '传统节期以台江施洞、老屯一带农历三月十五至十七为核心。2026 年台江县公共系列活动于 4 月 30 日至 5 月 10 日举行,现已结束;下一年度的县城活动、施洞活动、交通管制与观演安排必须等待新通知。',
+ 'The traditional window centres on lunar days 15–17 of the third month around Shidong and Laotun in Taijiang. Taijiang’s 2026 public programme ran from 30 April to 10 May and has ended; next year’s county and Shidong events, traffic controls, and viewing arrangements await a new notice.',
+ language,
+ ),
+ status: pickText('五色姊妹饭、盛装与对歌可作为文化线索,不承诺进入婚恋或家庭仪式', 'Coloured rice, dress, and antiphonal song are cultural anchors—not access to courtship or family rites', language),
+ },
+ {
+ number: '03',
+ label: pickText('两个独立节庆', 'Two Separate Festivals', language),
+ title: pickText('侗族大歌节・黄岗喊天节', 'Dong Grand Song & Huanggang Heaven-Calling', language),
+ copy: pickText(
+ '黄岗喊天节传统日期为农历六月十五,祭祀、侗族大歌与长桌宴的公开范围由村寨当年安排决定。从江侗族大歌节过去曾在 11 月 28 日前后举办,但公开资料不足以证明这是每年固定公历日期,因此两项活动不能合并成一个全年可售产品。',
+ 'Huanggang’s Heaven-Calling Festival traditionally falls on lunar 6/15, while public access to rites, Grand Song, and banquets follows the village’s current plan. Congjiang Grand Song festivals have previously taken place around 28 November, but available evidence does not establish that as a fixed annual Gregorian date; the two events are not one year-round product.',
+ language,
+ ),
+ status: pickText('侗族大歌不是到场即唱;具名歌队、场次、费用和拍摄须单独确认', 'Grand Song is not performed on demand; confirm the named ensemble, session, fee, and photography', language),
+ },
+ {
+ number: '04',
+ label: pickText('水历分批过节', 'Staggered Shui Calendar', language),
+ title: pickText('水族端节', 'Shui Duan Festival', language),
+ copy: pickText(
+ '端节按水历和不同氏族、村寨的亥日分批举行,大致落在公历秋季。公开资料中的“49 天”指各批次从头至尾的整体跨度,不是同一地点连续 49 天的游客活动;赛马、铜鼓、祭祖与家庭宴席也不在每一批次都向游客开放。',
+ 'Duan follows the Shui calendar and staggered Pig Days for different clans and villages, broadly in autumn. The published “49 days” describes the span across all batches—not a continuous 49-day visitor event in one place. Horse racing, bronze drums, ancestor rites, and family meals are not all public in every batch.',
+ language,
+ ),
+ status: pickText('必须先锁定县、村寨、氏族批次和公开活动,再安排交通与住宿', 'Confirm the county, village, clan batch, and public programme before transport and accommodation', language),
+ },
+ ];
+ const flow = [
+ { title: pickText('先确定年份与节庆', 'Start with the Year & Festival', language), copy: pickText('客户先提供旅行年份、日期范围和最感兴趣的节庆;不使用多年以前的海报或历史日期替代当年通知。', 'Begin with the travel year, date range, and festival of interest; an old poster or historic date never substitutes for a current notice.', language) },
+ { title: pickText('拆开传统日期与公共活动', 'Separate Tradition from Public Programme', language), copy: pickText('核对农历/水历传统日期、当年官方公共活动、村寨内部仪式三层信息,并标出游客能进入、只能远观和不可拍摄的部分。', 'Check three layers—the traditional lunar or Shui-calendar date, the current public programme, and internal village rites—then mark what visitors may enter, observe only, or not photograph.', language) },
+ { title: pickText('锁定交通、住宿与缓冲', 'Lock Transport, Stay & Buffer', language), copy: pickText('节庆期间可能拥堵、封路、停车受限或住宿紧张;正式方案写明接驳、步行、集合点、房价、取消条件和至少一个时间缓冲。', 'Festivals may bring congestion, road controls, limited parking, and tight rooms. State transfers, walking, meeting point, room rate, cancellation, and at least one time buffer.', language) },
+ { title: pickText('交付礼仪与拍摄说明', 'Brief Etiquette & Photography', language), copy: pickText('说明服饰、敬酒、对歌、祭祀、未成年人、无人机和商业拍摄边界;人物近景与家庭空间现场再次征得同意。', 'Brief dress, toasting, singing, ritual, minors, drones, and commercial-image boundaries; reconfirm close portraits and home spaces on site.', language) },
+ { title: pickText('当天按现场通知执行', 'Follow the Live Programme', language), copy: pickText('天气、社区决定、安保和人流拥有最终调整权;节目变化时优先保证尊重与安全,不用临时摆拍补足宣传清单。', 'Weather, community decisions, security, and crowd conditions retain the final say. If the programme changes, protect respect and safety rather than staging replacement content.', language) },
+ ];
+ const gates = [
+ { title: pickText('当年日期与主办信息', 'Current Date & Organiser', language), copy: pickText('官方或村寨当年通知、主办/联系人、地点、公开时段、门票/预约和变更渠道齐全后,才写入正式行程。', 'Only publish after the current official or village notice names the organiser, contact, venue, public hours, tickets or reservations, and update channel.', language) },
+ { title: pickText('公开活动与仪式边界', 'Public Events & Ritual Boundaries', language), copy: pickText('区分巡游、舞台展演、公共对歌、宴席与祭祀/家庭环节;公开节庆不等于所有空间和人物均可进入拍摄。', 'Separate parades, staged shows, public singing, banquets, rites, and family moments; a public festival does not make every space or person open to cameras.', language) },
+ { title: pickText('人流、道路与现场安全', 'Crowds, Roads & Field Safety', language), copy: pickText('交通管制、停车/接驳、拥挤踩踏、夜间照明、雨天湿滑、烟火/斗牛/赛马等区域隔离及儿童集合方案。', 'Traffic controls, parking or shuttle, crowd pressure, night lighting, wet ground, separation from fireworks, bullfighting, or horse racing, and a child regrouping plan.', language) },
+ { title: pickText('住宿、费用与取消', 'Stay, Cost & Cancellation', language), copy: pickText('具名酒店/民宿、当前房价与涉外接待、最少入住、预付退款、节目取消后的替代和不退费用逐项写清。', 'State the named hotel or guesthouse, live rate and international reception, minimum stay, deposit refund, event-cancellation alternative, and non-refundable costs.', language) },
+ ];
+ const routes = [
+ { number: '01', title: pickText('黔东南苗族节庆线', 'Qiandongnan Miao Festival Route', language), copy: pickText('围绕苗年或姊妹节只选一项,在凯里/台江/雷山之间保留前后缓冲,不把两个不同季节拼在同一线路。', 'Build around either Miao New Year or Sisters’ Meal, with buffer around Kaili, Taijiang, or Leishan—never combining two different seasons into one route.', language), href: '/safaris/culture-outdoor-mix/' },
+ { number: '02', title: pickText('侗寨节庆与慢住', 'Dong Festival & Village Stay', language), copy: pickText('以黄岗喊天节或当年从江侗族大歌活动为锚点,先核验公共场次,再安排一座具名侗寨住宿。', 'Anchor the route to Huanggang Heaven-Calling or a current Congjiang Grand Song event, verify the public programme, then add one named Dong village stay.', language), href: '/safaris/culture-outdoor-mix/' },
+ { number: '03', title: pickText('三都水族端节窗口', 'Sandu Shui Duan Window', language), copy: pickText('先确定当年村寨批次,再从贵阳/都匀衔接三都;赛马或家庭宴席没有书面确认时不写入核心亮点。', 'Confirm the current village batch before connecting Sandu from Guiyang or Duyun; horse racing or a family feast is not a headline without written confirmation.', language), href: '/safaris/classic-guizhou/' },
+ ];
+
+ return (
+
+
+
+
+
+
+
+
Living Heritage / Seasonal
+
{pickText('节庆民俗盛典', 'Ethnic Festivals & Customs', language)}
+
{pickText('真正的节庆不是全年循环播放的节目。先确认当年日期、村寨和公开范围,再决定我们能看见什么、能参与什么。', 'A living festival is not year-round programming. Confirm the current date, village, and public boundary before deciding what may be witnessed or joined.', language)}
+
{pickText('查看四项节庆窗口', 'Explore four festival windows', language)}
+
+
+
+
+
+
+
+
+
{pickText('节庆定义', 'Festival Definition', language)}
+
{pickText('把节庆放进行程,先要接受它不为旅行者改变时间。', 'To place a festival in a journey, accept that it does not change its time for the traveller.', language)}
+
{pickText('客户文档提出苗年、苗族姊妹节、侗族大歌节与黄岗喊天节、水族端节。公开核验显示:传统日期、政府组织的公共活动和村寨内部仪式不是同一层信息;“11 月 28 日固定举办”“连续 49 天游客活动”等表述也不能直接发布。因此本页以当年确认窗口呈现,而不是常年可下单的节目单。', 'The brief proposes Miao New Year, Sisters’ Meal, Dong Grand Song and Huanggang Heaven-Calling, and Shui Duan. Public verification shows that traditional dates, government-led public programmes, and internal village rites are different layers. Claims such as a fixed 28 November event or a continuous 49-day visitor programme cannot be published as-is, so this page presents annual planning windows rather than year-round inventory.', language)}
+
+
+ - {pickText('规划规则', 'Planning Rule', language)}
- {pickText('每年重新核对官方与社区通知', 'Recheck official and community notices every year', language)}
+ - {pickText('2026 苗年', '2026 Miao New Year', language)}
- {pickText('州级假日 11 月 15 日;具体村寨节目待逐项确认', 'Prefecture holiday 15 Nov; village programmes verified separately', language)}
+ - {pickText('2026 姊妹节', '2026 Sisters’ Meal', language)}
- {pickText('公共系列活动 4 月 30 日至 5 月 10 日,现已结束', 'Public series ran 30 Apr–10 May and has ended', language)}
+ - {pickText('侗族节庆', 'Dong Festivals', language)}
- {pickText('喊天节与侗族大歌节分开核验,不共享固定日期', 'Heaven-Calling and Grand Song verified separately', language)}
+ - {pickText('水族端节', 'Shui Duan', language)}
- {pickText('按氏族与村寨分批,先确认具体亥日和公开活动', 'Staggered by clan and village; confirm the Pig Day and public programme', language)}
+ - {pickText('默认深度', 'Default Depth', language)}
- {pickText('公共活动半日至一日;家庭与仪式不默认进入', 'Half- to full-day public events; no default access to homes or rites', language)}
+
+
+
+
+
{pickText('客户提供苗族节庆氛围图 · 具体活动、年份、地点与公开使用授权待归档', 'Client-supplied Miao festival atmosphere · Event, year, location, and publication rights require records', language)}
+
{pickText('画面可见“中国・雷山”标识 · 不据此认定为某一届苗年或姊妹节', 'The image shows “Leishan, China” · Not proof of a particular Miao New Year or Sisters’ Meal edition', language)}
+
{pickText('苗族盛装氛围参考 · 人物身份、拍摄同意与活动名称待确认', 'Miao ceremonial-dress reference · Identity, consent, and event name to be confirmed', language)}
+
{pickText('客户提供人物实拍 · 不用于证明侗族喊天节或水族端节', 'Client-supplied portrait · Not evidence of Dong Heaven-Calling or Shui Duan', language)}
+
+
+
+
+
01 / Annual Festival Windows{pickText('四项节庆,四套时间逻辑。', 'Four festivals, four different calendars.', language)}
{pickText('页面保留客户提出的文化内容,但会主动标出已经结束、等待新通知、分批轮办或不能进入的部分。', 'The page retains the cultural intent of the brief while marking what has ended, awaits a new notice, rotates by batch, or remains closed to visitors.', language)}
+
{festivals.map((festival) =>
{festival.number}{festival.label}
{festival.title}
{festival.copy}
{festival.status})}
+
+
+
+
+
+
+
02 / Festival Planning
{pickText('先找到当年的真实入口,再安排客人的位置。', 'Find this year’s real point of entry before placing the guest.', language)}
+
{flow.map((item, index) => - {String(index + 1).padStart(2, '0')}
)}
+
+
+
+
+
+
03 / Festival Gates{pickText('日期对,不等于所有内容都能看见。', 'The right date does not guarantee access to every moment.', language)}
{pickText('正式方案必须把“传统上会发生”“当年公共活动已经公布”和“旅行者获准进入”分开写。', 'The final plan separates what traditionally occurs, what the current public programme announces, and what the traveller is actually allowed to enter.', language)}
+
{gates.map((gate, index) =>
{String(index + 1).padStart(2, '0')}{gate.title}
{gate.copy}
)}
+
+
{pickText('可以写入正式方案', 'What the final plan can promise', language)}- {pickText('当年官方或村寨确认的日期、地点、公开活动与开放时段', 'Current confirmed date, venue, public programme, and hours', language)}
- {pickText('具名交通、集合点、酒店/民宿、房价、预约、门票和取消条件', 'Named transport, meeting point, stay, rate, reservation, ticket, and cancellation', language)}
- {pickText('可进入区域、拍摄边界、英文说明、拥挤与天气备选', 'Access areas, photo boundaries, English briefing, crowd and weather fallback', language)}
+
{pickText('必须按当年重新核验', 'Claims requiring annual reconfirmation', language)}- {pickText('客户文档中的公历月份、持续天数和 11 月 28 日固定举办', 'Gregorian windows, durations, or a fixed 28 November from the brief', language)}
- {pickText('斗牛、赛马、宰猪、祭祖、百家宴、夜间对歌或歌队一定出现', 'Bullfighting, horse racing, slaughter, ancestor rites, banquet, evening song, or ensemble guaranteed', language)}
- {pickText('家庭邀请、近距离拍摄、无人机、商业摄影及内部仪式进入权', 'Home invitations, close portraits, drones, commercial shoots, or access to internal rites', language)}
+
+
{pickText('公开信息参考:黔东南州 2026 年节假日通知、台江县政府姊妹节介绍及 2026 年公共活动报道、贵州省政协黄岗喊天节资料、文化和旅游部历届从江侗族大歌节报道,以及贵州公开的水族端节资料。节庆页面每年更新,最终以当年政府、主办方与村寨通知为准。', 'Public references include Qiandongnan’s 2026 holiday notice, Taijiang government material and reporting on the 2026 Sisters’ Meal programme, Guizhou CPPCC material on Huanggang Heaven-Calling, Ministry of Culture and Tourism reports on past Congjiang Grand Song festivals, and official Guizhou sources on Shui Duan. This page is updated annually; current government, organiser, and village notices prevail.', language)}
+
+
+
+
+ 04 / Route Pairing
{pickText('围绕一个节庆留出时间,不把节庆塞进景点清单。', 'Leave time around one festival instead of squeezing it into a sightseeing list.', language)}
+
+
+
+
+
+ );
+}
+
+function CulinaryCulturalJourneysDetailPage() {
+ const { language } = useTravelSite();
+ const streetFoods = [
+ {
+ number: '01',
+ title: pickText('花溪牛肉粉', 'Huaxi Beef Rice Noodles', language),
+ place: pickText('贵阳・花溪代表风味', 'Guiyang · Huaxi signature', language),
+ copy: pickText('牛骨汤、米粉、牛肉与酸萝卜组成的贵阳代表性早餐。正式路线选择具名门店,并提前说明汤底、辣椒、牛肉部位、香菜/葱花与清真需求;“牛骨慢熬”只按具体门店核实。', 'A Guiyang breakfast built around beef broth, rice noodles, sliced beef, and pickled radish. The final walk names the shop and clarifies broth, chilli, cut of beef, herbs, and halal needs. “Slow-simmered bone broth” is verified with the actual kitchen rather than assumed.', language),
+ status: pickText('适合早餐或早午餐;不和夜市营业时间混写', 'Best at breakfast or brunch; not treated as a night-market item by default', language),
+ },
+ {
+ number: '02',
+ title: pickText('贵阳肠旺面', 'Guiyang Changwang Noodles', language),
+ place: pickText('贵阳・城市早餐', 'Guiyang · city breakfast', language),
+ copy: pickText('以鸡蛋面、猪大肠、血旺和脆哨为核心的贵阳小吃,红油和动物内脏风味鲜明。英文说明必须直译主要食材,让客人在品尝前作出知情选择,并询问猪肉、内脏、血制品和辣度接受度。', 'A Guiyang noodle bowl centred on egg noodles, pork intestine, blood curd, crisp pork, and chilli oil. English interpretation names the ingredients plainly so guests can make an informed choice, including comfort with pork, offal, blood products, and heat.', language),
+ status: pickText('不使用模糊的“特色肉面”替代真实食材说明', 'Never hide the ingredients behind a vague “special meat noodle” label', language),
+ },
+ {
+ number: '03',
+ title: pickText('贵阳丝娃娃', 'Guiyang Siwawa', language),
+ place: pickText('贵阳・蔬菜薄饼小吃', 'Guiyang · vegetable wrap', language),
+ copy: pickText('用薄面皮包裹多种切丝蔬菜,再加入酸辣蘸水。蔬菜数量和配料随门店变化,不固定承诺“十种以上”;花生、芝麻、酱油、小麦、折耳根及辣椒作为重点询问项。', 'Thin wrappers hold an assortment of shredded vegetables with a sour-spicy dipping sauce. The number and mix vary by shop rather than a guaranteed “ten-plus.” Ask specifically about peanut, sesame, soy, wheat, fish mint, and chilli.', language),
+ status: pickText('看似清淡不等于无过敏原,也不自动等于全素', 'Light-looking does not mean allergen-free or automatically vegan', language),
+ },
+ {
+ number: '04',
+ title: pickText('青岩豆腐与玫瑰冰粉', 'Qingyan Tofu & Rose Ice Jelly', language),
+ place: pickText('青岩咸食 + 贵阳甜品组合', 'Qingyan savoury + Guiyang dessert pairing', language),
+ copy: pickText('客户希望用炸/炒豆腐与玫瑰冰粉形成咸甜收尾。公开名录分别支持青岩风味炒豆腐和贵阳玫瑰冰粉,但未证明两者是固定传统套餐;页面只把它们作为青岩或贵阳线路中可分开核验的组合。', 'The brief pairs fried or wok-cooked tofu with rose ice jelly as a savoury-sweet finish. Public lists support Qingyan-style tofu and Guiyang rose ice jelly separately, not as one fixed traditional set. They remain individually verified stops within a Qingyan or Guiyang route.', language),
+ status: pickText('豆制品、油炸交叉接触、冰品用水与糖量分别确认', 'Confirm soy, fryer cross-contact, ice-water handling, and sugar separately', language),
+ },
+ {
+ number: '05',
+ title: pickText('水城烙锅', 'Shuicheng Luoguo Griddle', language),
+ place: pickText('六盘水・水城核心风味', 'Liupanshui · Shuicheng signature', language),
+ copy: pickText('食材在桌面铁锅上现烙,并搭配糊辣椒蘸料,是六盘水/水城具有明确地域归属的共享餐食。它更适合作为六盘水一餐,不为了凑齐“贵阳五种小吃”跨城搬运;肉类、豆制品、花生芝麻、辣椒和生熟夹具需要逐项确认。', 'Ingredients are cooked on a tabletop iron griddle and paired with toasted-chilli dip—a shared meal strongly associated with Shuicheng and Liupanshui. It belongs in a Liupanshui meal rather than being imported merely to complete a “five Guiyang snacks” checklist. Confirm meats, soy, peanut or sesame, chilli, and separate raw and cooked utensils.', language),
+ status: pickText('通常是一顿共享餐,不计作一口式街头试吃', 'Usually a shared meal, not a one-bite street-food tasting', language),
+ },
+ ];
+ const formats = [
+ {
+ number: '01',
+ label: pickText('约 3–4 小时', 'Approx. 3–4 hours', language),
+ title: pickText('民族家宴烹饪课', 'Ethnic Home Cooking Class', language),
+ copy: pickText(
+ '与具名主人先逛一处当天营业的市场,再回到已经核验的家庭厨房、工作室或餐饮场所学习一至两道菜。酸汤鱼、糯米饭只作为菜单候选;主人身份、经营或家庭接待边界、食材来源、饮水、过敏原、刀具与热源、儿童参与、翻译、食谱和费用必须写进确认单。',
+ 'Shop at one operating market with a named host, then learn one or two dishes in a verified home kitchen, studio, or food venue. Sour-soup fish and glutinous rice are menu candidates, not defaults. The confirmation names the host and service type, sourcing, drinking water, allergens, knives and heat, children, interpretation, recipe notes, and cost.',
+ language,
+ ),
+ status: pickText('家庭厨房、私房菜与持证餐厅必须如实区分', 'Home kitchen, private dining, and licensed restaurant must be labelled accurately', language),
+ },
+ {
+ number: '02',
+ label: pickText('约 2–3 小时', 'Approx. 2–3 hours', language),
+ title: pickText('原生长桌宴', 'Traditional Long-Table Banquet', language),
+ copy: pickText(
+ '先区分村寨真实节庆或社区宴席、预约型文化餐叙和景区/餐厅商业表演,再决定页面与行程如何命名。具名组织者、地点、最低人数、菜单、座位、天气备选、敬酒与酒歌、无酒精替代、交通、洗手间、价格和取消条件全部确认后才可预订。',
+ 'First distinguish a genuine village or festival gathering, a booked cultural meal, and a scenic-area or restaurant performance. Only book after confirming the named organiser, place, minimum group, menu, seating, weather fallback, toasts and songs, non-alcoholic alternatives, transport, toilets, price, and cancellation.',
+ language,
+ ),
+ status: pickText('不把商业场次写成家庭宴,也不承诺临时到村即开席', 'A commercial session is not a family feast, and no village banquet is promised on demand', language),
+ },
+ {
+ number: '03',
+ label: pickText('约 2–3 小时', 'Approx. 2–3 hours', language),
+ title: pickText('在地市集风味探访', 'Local Market & Street-Food Tour', language),
+ copy: pickText(
+ '选择一处具名市场或一条紧凑街区,在真实营业时段安排 3–5 份小份试吃;只有步行、食量和摊位均合适时才扩展到客户建议的 5–6 份。花溪牛肉粉、肠旺面、丝娃娃、青岩豆腐/玫瑰冰粉与水城烙锅地域和用餐方式不同,不承诺在同一市场一次吃齐;摊位、熟制状态、生熟分离、过敏原、辣度、支付、座位、洗手间和拥挤天气逐项核验。',
+ 'Use one named market or compact food district in its real trading hours for three to five small tastings, expanding to the brief’s five or six only when distance, appetite, and vendors fit. Huaxi beef noodles, changwang noodles, siwawa, Qingyan tofu or rose ice jelly, and Shuicheng luoguo belong to different places and meal formats, so one market is never promised to contain them all. Verify vendor, cooking state, raw/cooked separation, allergens, spice, payment, seating, toilets, weather, and crowds.',
+ language,
+ ),
+ status: pickText('市场是公共商业空间,不自动等于家庭或少数民族私享体验', 'A market is a public commercial space, not automatically a private ethnic or home experience', language),
+ },
+ ];
+ const flow = [
+ { title: pickText('先做饮食画像', 'Build the Food Profile', language), copy: pickText('记录严重过敏、饮食禁忌、素食/清真需求、辣度、酒精、儿童年龄与厨房操作舒适度;不能做到的需求在下单前说明。', 'Record severe allergies, restrictions, vegetarian or halal needs, spice, alcohol, children’s ages, and comfort in a kitchen. Any need that cannot be met is disclosed before booking.', language) },
+ { title: pickText('只选择一种主体验', 'Choose One Anchor Experience', language), copy: pickText('家宴课、长桌宴或市集探访一天只设一个美食锚点,先锁定具名主人、经营场所、组织者或市场。', 'Use one food anchor per day—cooking class, banquet, or market—and first lock the named host, venue, organiser, or market.', language) },
+ { title: pickText('核对菜单与卫生条件', 'Verify Menu & Hygiene', language), copy: pickText('确认菜单、食材采购与保存、饮用水、加工环境、餐具清洁、过敏原交叉接触、熟度和剩余食品处理。', 'Confirm menu, sourcing and storage, drinking water, preparation area, utensil cleaning, allergen cross-contact, cooking, and leftover handling.', language) },
+ { title: pickText('交付礼仪与安全说明', 'Brief Etiquette & Safety', language), copy: pickText('提前说明厨房刀具与热源、未成年人看护、敬酒不劝酒、无酒精替代、人物与家庭空间拍摄,以及市场步行和支付方式。', 'Brief knives and heat, child supervision, no pressure to drink, non-alcoholic alternatives, photography in homes and of people, market walking, and payment.', language) },
+ { title: pickText('当天按供应调整', 'Adapt to the Day’s Supply', language), copy: pickText('早市摊位、时令食材和主人菜单会变化;以新鲜、安全和真实营业为先,不为凑齐宣传菜名跨市场追赶。', 'Stalls, seasonal produce, and host menus change. Freshness, safety, and real opening hours come first—never race between markets to tick off promotional dish names.', language) },
+ ];
+ const gates = [
+ { title: pickText('接待主体与产品身份', 'Host & Product Identity', language), copy: pickText('具名主人/组织者、准确地址、联系方式、家庭接待或餐饮经营属性、可接待人数、英语支持、服务费与取消方式齐全。', 'Name the host or organiser, address, contact, home-hosting or food-business status, capacity, English support, service fee, and cancellation.', language) },
+ { title: pickText('食品、饮水与过敏原', 'Food, Water & Allergens', language), copy: pickText('核对原料来源与保存、生熟分开、饮用水、清洁消毒、熟度、严重过敏原和交叉接触;无法安全满足时改用具名餐厅方案。', 'Check sourcing and storage, raw/cooked separation, drinking water, cleaning, cooking, severe allergens, and cross-contact. Use a named restaurant fallback when needs cannot be met safely.', language) },
+ { title: pickText('工具、儿童与酒精', 'Tools, Children & Alcohol', language), copy: pickText('刀具、明火/热油、湿滑地面、儿童一对一看护、酒精度与饮酒选择、驾车人员零酒精及紧急医疗联系均提前说明。', 'Brief knives, flame or hot oil, wet floors, one-to-one child supervision, alcohol strength and choice, zero alcohol for drivers, and emergency medical contact.', language) },
+ { title: pickText('同意、价格与取消', 'Consent, Price & Cancellation', language), copy: pickText('主人、家庭空间、摊主和未成年人拍摄同意;菜单价格、服务费、小费、采购费、最低人数、天气/停市/主人取消与退款逐项写清。', 'Record consent for hosts, homes, vendors, and minors; state menu price, service and shopping fees, tips, minimum group, weather or market closure, host cancellation, and refunds.', language) },
+ ];
+ const routes = [
+ { number: '01', title: pickText('贵阳抵达日・市集小吃', 'Guiyang Arrival Food Walk', language), copy: pickText('把具名早市或城市小吃线放在抵达后或返程前,按真实营业时间安排 3–5 份小吃,不挤压正餐和转场。', 'Place a named market or city snack walk on arrival or before departure, with three to five tastings in real opening hours and room for transfers and meals.', language), href: '/safaris/classic-guizhou/' },
+ { number: '02', title: pickText('村寨慢住・家宴烹饪', 'Village Stay & Hosted Cooking', language), copy: pickText('在具名村寨住宿确认后,再匹配一位真实主人和一个可执行菜单;不把整个村寨都写成随时可预约的家庭厨房。', 'After a named village stay is confirmed, match one real host and one workable menu. The whole village is never presented as an on-demand home kitchen.', language), href: '/safaris/culture-outdoor-mix/' },
+ { number: '03', title: pickText('节庆窗口・长桌宴候选', 'Festival Window & Banquet Candidate', language), copy: pickText('只有当年节庆或社区公开宴席已有书面安排时进入线路;否则替换为具名餐厅的地方风味分享餐。', 'Add a banquet only when a current festival or public community meal has written arrangements; otherwise use a named restaurant tasting meal.', language), href: '/safaris/culture-outdoor-mix/' },
+ ];
+
+ return (
+
+
+
+
+
+
+
+
Culture Through Food / One Table at a Time
+
{pickText('民族美食文化', 'Culinary Cultural Journeys', language)}
+
{pickText('以美食为切口理解民族生活,全程拒绝流水线团餐。先确认是谁做、在哪里做、食材从哪里来,再决定这一餐如何进入旅程。', 'Understand local life through food, without assembly-line group meals. First confirm who cooks, where, and how ingredients are sourced—then decide how the table belongs in the journey.', language)}
+
{pickText('查看三种美食体验', 'Explore three food formats', language)}
+
+
+
+
+
+
+
+
+
{pickText('美食体验定义', 'Food Experience Definition', language)}
+
{pickText('不追求吃得最多,而是把一餐背后的生活关系说清楚。', 'The aim is not to eat the most, but to understand the relationships behind one meal.', language)}
+
{pickText('客户文档提出家宴烹饪课、原生长桌宴与在地市集探访,并指定花溪牛肉粉、肠旺面、丝娃娃、青岩豆腐/玫瑰冰粉、水城烙锅五类风味。实际落地时,家庭接待、经营餐厅、节庆宴席与公共市场属于不同场景;这五类风味也分属贵阳早餐、青岩停留和六盘水共享餐,不能用一条市集线强行吃齐。菜品、主人、地点和营业时间必须按日期逐项确认。', 'The brief proposes a home-cooking class, traditional long-table banquet, and local market tour, specifying Huaxi beef rice noodles, changwang noodles, siwawa, Qingyan tofu or rose ice jelly, and Shuicheng luoguo. A home visit, food business, festival banquet, and public market are different settings; the five tastes also span Guiyang breakfast, a Qingyan stop, and a shared Liupanshui meal rather than one market checklist. Dish, host, place, and operating hours are verified by date.', language)}
+
+
+ - {pickText('体验数量', 'Formats', language)}
- {pickText('三选一,一天一个美食锚点', 'Choose one; one food anchor per day', language)}
+ - {pickText('建议时长', 'Suggested Duration', language)}
- {pickText('市集 2–3 小时 / 烹饪 3–4 小时 / 宴席 2–3 小时', 'Market 2–3h / cooking 3–4h / banquet 2–3h', language)}
+ - {pickText('市集试吃', 'Market Tastings', language)}
- {pickText('通常 3–5 份;5–6 份只在距离、食量与摊位合适时', 'Usually 3–5; five or six only when distance, appetite, and vendors fit', language)}
+ - {pickText('饮食需求', 'Dietary Needs', language)}
- {pickText('过敏、素食与清真逐项书面确认', 'Allergy, vegetarian, and halal needs confirmed in writing', language)}
+ - {pickText('酒精礼仪', 'Alcohol', language)}
- {pickText('不劝酒,提供无酒精替代', 'No pressure to drink; non-alcoholic alternative', language)}
+ - {pickText('默认备选', 'Default Fallback', language)}
- {pickText('具名餐厅地方风味分享餐', 'A named-restaurant regional tasting meal', language)}
+
+
+
+
+
{pickText('客户提供菜品实拍 · 菜名、餐厅、制作人与使用授权待归档', 'Client-supplied dish photograph · dish, venue, maker, and publication rights require records', language)}
+
{pickText('酸汤风味氛围参考 · 不证明为家庭厨房或民族家宴课程', 'Sour-flavour reference · not evidence of a home kitchen or ethnic cooking class', language)}
+
{pickText('客户提供餐桌实拍 · 场所与菜品身份待确认,不作长桌宴证明', 'Client-supplied table photograph · venue and dish identity pending; not evidence of a long-table banquet', language)}
+
{pickText('客户提供长桌氛围图 · 组织者、地点、年份及是否商业场次待确认', 'Client-supplied banquet atmosphere · organiser, place, year, and commercial status require confirmation', language)}
+
+
+
+
+
Local Market / Street-Food Tour{pickText('五类代表风味,不做一张“必须全部吃完”的清单。', 'Five signature tastes—not a mandatory one-walk checklist.', language)}
{pickText('客户给出的五类内容全部保留,但按真实地域、营业时段和用餐方式重新组织。贵阳早餐、青岩停留和六盘水共享烙锅可以分属不同天,最终一次城市步行通常只选 3–5 份小试。', 'All five items from the brief remain, reorganised by real place, opening time, and meal format. Guiyang breakfast, a Qingyan stop, and a shared Liupanshui griddle may belong on different days; one city walk normally selects only three to five small tastings.', language)}
+
{streetFoods.map((food) =>
{food.number}{food.place}
{food.title}
{food.copy}
{food.status})}
+
{pickText('贵阳城市版建议', 'Suggested Guiyang Edition', language)}
{pickText('早餐线与夜市线二选一。', 'Choose a breakfast route or an evening market route.', language)}
{pickText('早餐线围绕具名粉面店、丝娃娃或糯米饭等 3–4 站;夜间可选择青云市集等成熟商业街区,但它是餐饮、文创与娱乐混合的现代商业市集,不包装成传统农贸早市。具体门店、营业与拥挤度按当天确认。', 'A breakfast route uses three or four named noodle, wrap, or glutinous-rice stops. In the evening, an established commercial district such as Qingyun Market may work, but it is a modern mix of food, culture, and entertainment—not a traditional produce market. Named outlets, live opening, and crowd level are checked for the day.', language)}
+
+
+
+
+
+
+
+
+
02 / Table Planning
{pickText('先把不能吃、不能做和不想被要求做的事说清楚。', 'Begin with what cannot be eaten, done, or socially expected.', language)}
+
{flow.map((item, index) => - {String(index + 1).padStart(2, '0')}
)}
+
+
+
+
+
+
03 / Food & Hosting Gates{pickText('好吃是结果,安全和尊重是前提。', 'Delicious is the outcome; safety and respect are the conditions.', language)}
{pickText('正式确认以国家餐饮食品安全要求和贵州现行食品安全条例为底线,并按实际服务主体落实;页面不以“家庭”“传统”替代卫生与经营核验。', 'Final confirmation uses current national catering food-safety requirements and Guizhou food-safety rules as the baseline, applied to the actual provider. “Home” or “traditional” never substitutes for hygiene and service-status checks.', language)}
+
{gates.map((gate, index) =>
{String(index + 1).padStart(2, '0')}{gate.title}
{gate.copy}
)}
+
+
{pickText('可以写入正式方案', 'What the final plan can promise', language)}- {pickText('具名主人、餐厅/场地、市场、营业时段与准确产品身份', 'Named host, venue, market, opening hours, and accurate product identity', language)}
- {pickText('经确认的菜单、食材、过敏原、辣度、饮水、酒精与无酒精选择', 'Confirmed menu, ingredients, allergens, spice, water, alcohol, and non-alcoholic choice', language)}
- {pickText('时长、人数、费用、翻译、拍摄、交通、洗手间和取消条件', 'Duration, group, cost, interpretation, photos, transport, toilets, and cancellation', language)}
+
{pickText('必须逐单重新核验', 'Claims requiring booking-specific proof', language)}- {pickText('“家庭秘方”“原生长桌宴”“非商业”“有机食材”或固定收益去向', '“Family secret,” “original banquet,” “non-commercial,” organic sourcing, or fixed benefit claims', language)}
- {pickText('每个市场都有丝娃娃、牛肉粉、烤香猪,或任一主人都能教酸汤鱼', 'Every market has siwawa, beef noodles, roast pork, or any host can teach sour-soup fish', language)}
- {pickText('绝对无过敏原、严格清真、全素无交叉接触或未成年人可独立使用刀火', 'Allergen-free, strict halal, fully vegan without cross-contact, or children using knives or heat alone', language)}
+
+
{pickText('公开信息与规则参考:贵州省“黔菜师傅”工程菜品遴选结果及传统优势食品产业方案对贵阳肠旺面、丝娃娃、花溪牛肉粉、青岩风味炒豆腐和贵阳玫瑰冰粉的归属;文化和旅游部及六盘水公开资料对水城烙锅的地域与技艺说明;贵州省政府对青云市集现代综合街区的介绍;以及《中华人民共和国食品安全法》、市场监管总局《餐饮服务食品安全操作规范》和《贵州省食品安全条例》。实际安排仍需核对具名经营主体、门店营业、市场管理和每位客人的饮食需求。', 'Public references include Guizhou’s Qian Cuisine Chef selection and traditional-food industry plan for Guiyang changwang noodles, siwawa, Huaxi beef noodles, Qingyan-style tofu, and Guiyang rose ice jelly; Ministry of Culture and Tourism and Liupanshui material on Shuicheng luoguo; the Guizhou government description of Qingyun Market as a modern mixed-use district; China’s Food Safety Law, SAMR’s catering code, and the Guizhou Food Safety Regulation. Each booking still checks the named provider, live opening, market management, and every guest’s dietary needs.', language)}
+
+
+
+
+ 04 / Route Pairing
{pickText('让一餐成为当天的文化锚点,而不是景点之间的填空题。', 'Make one meal the day’s cultural anchor, not a gap between sights.', language)}
+
+
+
+
+
+ );
+}
+
+function IconicWaterfallClustersDetailPage() {
+ const { language } = useTravelSite();
+ const clusters = [
+ {
+ number: '01',
+ label: pickText('安顺・成熟景区', 'Anshun · Developed Scenic Area', language),
+ title: pickText('黄果树瀑布群', 'Huangguoshu Waterfall Group', language),
+ copy: pickText(
+ '以高 77.8 米、宽 101 米的黄果树大瀑布为核心,通常把陡坡塘、大瀑布和天星桥分区安排为完整一日。陡坡塘的宽缓水幕、天星桥的水上石林和银链坠潭不能被简化成“同一个瀑布机位”;入园时段、观光车、水帘洞/步道开放、客流和步行量按当天确认。',
+ 'Centred on Huangguoshu Great Waterfall, officially described as 77.8 m high and 101 m wide, a full day usually separates Doupotang, the main falls, and Tianxingqiao. Doupotang’s broad curtain, Tianxingqiao’s water-stone landscape, and Yinlianzhuitan are not one photo stop. Entry time, shuttle, Water-Curtain Cave and trail access, crowds, and walking are checked for the day.',
+ language,
+ ),
+ status: pickText('适合首次来黔;夏季水势更强,但丰水、彩虹和水帘洞开放均不作保证', 'Best for a first Guizhou visit; stronger summer water, rainbows, and cave access are never guaranteed', language),
+ },
+ {
+ number: '02',
+ label: pickText('关岭・山谷候选', 'Guanling · Valley Candidate', language),
+ title: pickText('滴水滩瀑布', 'Dishuitan Waterfall', language),
+ copy: pickText(
+ '官方公开资料支持其为坝陵河支流上的七级瀑布、总落差约 410 米,也是黄果树瀑布群中落差最大的瀑布之一;这不等于游客可沿全部落差连续步行。它与黄果树核心景区不是同一套成熟游览动线,入口、道路、停车、步道、观景台、洗手间、通信和当前开放必须单独核验。',
+ 'Official public material describes a seven-stage waterfall on a Baling River tributary with a total drop of about 410 m, among the greatest drops in the Huangguoshu group. That does not mean visitors can walk the full drop. It is not the same mature visitor circuit as core Huangguoshu, so entrance, road, parking, trail, viewpoint, toilets, signal, and live access require a separate check.',
+ language,
+ ),
+ status: pickText('不使用“隐秘、无人、无遮挡”作承诺;只有具名安全观景点才进入方案', 'No promise of “hidden, empty, unobstructed”; only a named safe viewpoint enters the plan', language),
+ },
+ {
+ number: '03',
+ label: pickText('赤水・丹霞峡谷', 'Chishui · Danxia Gorge', language),
+ title: pickText('赤水丹霞瀑布', 'Chishui Danxia Waterfalls', language),
+ copy: pickText(
+ '赤水是世界自然遗产“中国丹霞”的六个组成地之一。核心可规划赤水丹霞旅游区・大瀑布(原十丈洞,公开资料约高 76 米、宽 80 米),再按时间选择四洞沟或其他具名景区;不同门票、接驳和步道不可笼统写成“几十处瀑布一次看完”。',
+ 'Chishui is one of the six components of the UNESCO World Heritage property China Danxia. The anchor can be Chishui Danxia Tourism Area · Great Waterfall, formerly Shizhangdong and publicly described as about 76 m high and 80 m wide, with Sidonggou or another named scenic area added only if time allows. Separate tickets, shuttles, and trails cannot be sold as “dozens of waterfalls in one visit.”',
+ language,
+ ),
+ status: pickText('与安顺黄果树分属贵州不同区域,建议独立安排赤水停留,不做同日往返', 'A different Guizhou region from Huangguoshu; plan a Chishui stay, not a same-day return', language),
+ },
+ ];
+ const flow = [
+ { title: pickText('先选一个瀑布区域', 'Choose One Waterfall Region', language), copy: pickText('黄果树完整景区、滴水滩山谷候选和赤水丹霞是三种不同交通与体力结构;一天只设一个核心区域。', 'Huangguoshu’s full scenic area, a Dishuitan valley candidate, and Chishui Danxia have different transfer and exertion profiles. Use one core region per day.', language) },
+ { title: pickText('核对当日开放与票务', 'Check Live Access & Ticketing', language), copy: pickText('使用官方渠道确认实名预约、入园时段、门票、观光车/电梯、水帘洞或步道开闭、停车与景区变更通知。', 'Use official channels for real-name reservation, entry slot, ticket, shuttle or lift, cave or trail access, parking, and change notices.', language) },
+ { title: pickText('匹配水量、天气与客流', 'Match Water, Weather & Crowds', language), copy: pickText('丰水期更壮观,也可能带来暴雨、涨水、水雾、湿滑与局部关闭;枯水期更轻柔,不用历史照片保证当天水量。', 'High water can be dramatic but also brings rain, rising water, spray, slippery surfaces, and closures. Low water is gentler; historic photos never guarantee the day’s flow.', language) },
+ { title: pickText('计算真实步行与退出', 'Map Real Walking & Exits', language), copy: pickText('按台阶、坡度、湿滑、候车、老人/儿童、膝踝和摄影停留计算;明确电梯、缩短动线、休息点和中途退出。', 'Plan around steps, grade, wet surfaces, queues, elders or children, knees and ankles, and photo stops; name lifts, shortened circuits, rests, and exits.', language) },
+ { title: pickText('当天服从现场安全调整', 'Follow Live Safety Changes', language), copy: pickText('雷雨、洪水、落石、道路管制或景区限流优先于原计划;用具名室内文化点、古镇或恢复型住宿替代,不绕封闭线。', 'Thunderstorms, floods, rockfall, road controls, or capacity limits override the plan. Use a named indoor cultural stop, old town, or recovery stay—never bypass a closure.', language) },
+ ];
+ const gates = [
+ { title: pickText('开放、票务与准确点位', 'Access, Ticket & Exact Site', language), copy: pickText('具名景区/入口、官方开放、预约时段、门票与接驳、停车、具体观景台和临时关闭渠道全部确认。', 'Confirm the named scenic area and entrance, official opening, reservation slot, ticket and shuttle, parking, exact viewpoint, and closure channel.', language) },
+ { title: pickText('水文、天气与地质风险', 'Water, Weather & Geology', language), copy: pickText('上游降雨、河水上涨、雷电、水雾、湿滑、落石和山洪预警逐项检查;不进入警戒线、河道、瀑顶或非开放崖边。', 'Check upstream rain, rising water, lightning, spray, slippery ground, rockfall, and flash-flood alerts; never enter barriers, channels, waterfall tops, or closed edges.', language) },
+ { title: pickText('步行、接驳与无障碍', 'Walking, Shuttle & Accessibility', language), copy: pickText('总步行、台阶、排队、观光车/电梯、洗手间、遮雨、饮水、儿童牵行、轮椅或行动不便替代动线写入行程。', 'State total walking, steps, queues, shuttle or lift, toilets, rain cover, water, child hand-holding, and wheelchair or reduced-mobility alternatives.', language) },
+ { title: pickText('摄影、无人机与现场秩序', 'Photography, Drones & Site Order', language), copy: pickText('只在开放观景点停留;三脚架、商业拍摄、无人机和涉水机位按景区规定。乘坐接驳车主动系安全带并听从现场人员。', 'Stop only at open viewpoints; tripods, commercial shoots, drones, and water-edge positions follow site rules. Wear shuttle seatbelts and follow staff instructions.', language) },
+ ];
+ const routes = [
+ { number: '01', title: pickText('经典全景线・黄果树整日', 'Classic Panorama · Full Huangguoshu Day', language), copy: pickText('贵阳或安顺衔接黄果树,按客流在陡坡塘、大瀑布、天星桥之间排序;老人和亲子版本主动缩短一段。', 'Connect from Guiyang or Anshun and sequence Doupotang, the main falls, and Tianxingqiao around crowds; shorten one section for elders and families.', language), href: '/safaris/classic-guizhou/' },
+ { number: '02', title: pickText('关岭峡谷线・滴水滩候选', 'Guanling Valley · Dishuitan Candidate', language), copy: pickText('与坝陵河/关岭停留组合,只有道路、入口、步道、具名观景台和当地接待全部通过才加入,不与黄果树完整日叠加。', 'Pair with a Baling River or Guanling stay only after road, entrance, trail, named viewpoint, and local support all pass; do not stack it onto a full Huangguoshu day.', language), href: '/safaris/outdoor-expedition/' },
+ { number: '03', title: pickText('赤水丹霞线・两至三晚', 'Chishui Danxia · Two to Three Nights', language), copy: pickText('以赤水城区或具名景观住宿为基地,选择大瀑布与一处丹霞/竹林景区;为长距离转场和雨天留缓冲。', 'Base in Chishui city or a named landscape stay, combining the Great Waterfall with one Danxia or bamboo-forest site and leaving buffer for long transfers and rain.', language), href: '/safaris/culture-outdoor-mix/' },
+ ];
+
+ return (
+
+
+
+
+
+
+
+
Karst Water / Danxia Valleys / Live Conditions
+
{pickText('世界级瀑布群', 'Iconic Waterfall Clusters', language)}
+
{pickText('从壮阔地标到山谷多级瀑布,先分清景区、地点和当天水况,再决定看多少、走多远。', 'From a monumental landmark to multi-tier valley falls, first separate the scenic area, exact place, and live water conditions—then decide how much to see and walk.', language)}
+
{pickText('比较三个瀑布区域', 'Compare three waterfall regions', language)}
+
+
+
+
+
+
+
+
+
{pickText('瀑布群定义', 'Waterfall Cluster Definition', language)}
+
{pickText('“瀑布很多”不是路线;景区边界、水量和脚下的路才是。', '“Many waterfalls” is not an itinerary; boundaries, water, and the path underfoot are.', language)}
+
{pickText('客户文档提出黄果树、滴水滩和赤水三个方向,并使用“亚洲最大瀑布群、410 米隐秘瀑布、几十处瀑布”等宣传语言。公开资料可以支持黄果树大瀑布尺寸、滴水滩总落差和赤水丹霞地貌,但三者的成熟度、距离、票务与安全条件完全不同。因此本页按三个独立区域呈现,不用一张历史丰水照片暗示全年水量,也不把非开放山谷包装成随时可到的“小众秘境”。', 'The brief proposes Huangguoshu, Dishuitan, and Chishui, using phrases such as “Asia’s largest cluster,” a “410 m hidden waterfall,” and “dozens of cascades.” Public material supports the main Huangguoshu dimensions, Dishuitan’s total drop, and Chishui’s Danxia setting, but their maturity, distance, ticketing, and safety differ. This page treats them as separate regions, never using a historic high-water image to imply year-round flow or presenting a non-open valley as an on-demand “hidden gem.”', language)}
+
+
+ - {pickText('区域数量', 'Regions', language)}
- {pickText('三选一,一天一个核心区域', 'Choose one; one core region per day', language)}
+ - {pickText('黄果树主瀑', 'Huangguoshu Main Falls', language)}
- {pickText('公开尺寸高 77.8 米、宽 101 米', 'Officially described as 77.8 m high and 101 m wide', language)}
+ - {pickText('滴水滩', 'Dishuitan', language)}
- {pickText('约 410 米七级总落差;开放动线单独核验', 'About 410 m over seven stages; access verified separately', language)}
+ - {pickText('赤水大瀑布', 'Chishui Great Waterfall', language)}
- {pickText('约高 76 米、宽 80 米;丹霞景区独立安排', 'About 76 m high and 80 m wide; separate Danxia visit', language)}
+ - {pickText('丰水观赏', 'High-Water Viewing', language)}
- {pickText('通常夏季更强;暴雨时也可能局部关闭', 'Usually stronger in summer; heavy rain may close sections', language)}
+ - {pickText('影像承诺', 'Image Promise', language)}
- {pickText('不保证固定水量、彩虹、无人或无遮挡', 'No guaranteed flow, rainbow, emptiness, or clear view', language)}
+
+
+
+
+
{pickText('客户提供黄果树主瀑实拍 · 拍摄日期、水量、机位与公开使用授权待归档', 'Client-supplied Huangguoshu main-falls image · date, flow, viewpoint, and publication rights require records', language)}
+
{pickText('黄果树瀑布群氛围参考 · 具体瀑布与日期待确认,不保证当天彩虹', 'Huangguoshu-group atmosphere · exact falls and date pending; no promise of a rainbow', language)}
+
{pickText('客户文档对应滴水滩多级瀑布 · 具体机位、道路与观景边界待现场核验', 'Client brief associates this with Dishuitan · exact viewpoint, road, and viewing boundary require field verification', language)}
+
{pickText('客户文档对应赤水丹霞瀑布 · 具体景区/瀑布名称与授权待归档', 'Client brief associates this with Chishui Danxia · exact scenic area, waterfall, and rights require records', language)}
+
+
+
+
+
01 / Three Waterfall Regions{pickText('三个区域,不是一张“瀑布打卡清单”。', 'Three regions, not one waterfall checklist.', language)}
{pickText('从成熟景区、山谷候选到丹霞目的地,分别决定时长、交通、体力和可承诺内容。', 'A developed scenic area, a valley candidate, and a Danxia destination each need their own time, transport, exertion, and promise.', language)}
+
{clusters.map((cluster) =>
{cluster.number}{cluster.label}
{cluster.title}
{cluster.copy}
{cluster.status})}
+
+
+
+
+
+
+
02 / Waterfall-Day Planning
{pickText('先看天气和路,再看瀑布。', 'Check weather and the route before the waterfall.', language)}
+
{flow.map((item, index) => - {String(index + 1).padStart(2, '0')}
)}
+
+
+
+
+
+
03 / Waterfall Gates{pickText('水越大,边界越要清楚。', 'The bigger the water, the clearer the boundary must be.', language)}
{pickText('开放、上游降雨、步行和现场管理共同决定当天能到哪里;“小众”从来不是越过护栏或封闭线的理由。', 'Access, upstream rain, walking, and on-site management decide how far the day can go. “Off the beaten path” is never a reason to cross a barrier or closure.', language)}
+
{gates.map((gate, index) =>
{String(index + 1).padStart(2, '0')}{gate.title}
{gate.copy}
)}
+
+
{pickText('可以写入正式方案', 'What the final plan can promise', language)}- {pickText('具名景区、入口、预约时段、票价/接驳、步行与预计停留', 'Named scenic area, entrance, slot, ticket or shuttle, walking, and planned stay', language)}
- {pickText('开放观景台、缩短动线、老人/儿童安排和明确退出点', 'Open viewpoints, shortened route, elder or child plan, and clear exits', language)}
- {pickText('当天官方通知、天气/水情复核和关闭后的具名替代', 'Current notice, weather and water check, and a named closure fallback', language)}
+
{pickText('必须按日期重新核验', 'Claims requiring date-specific proof', language)}- {pickText('“亚洲最大”“完全无人”“无遮挡”“秘境直达”或“几十处一次看完”', '“Asia’s largest,” empty, unobstructed, hidden access, or dozens in one visit', language)}
- {pickText('固定丰水、固定彩虹、水帘洞必开、无人机可飞或可站到瀑顶/水边', 'Guaranteed high flow, rainbow, cave access, drone flight, waterfall-top or water-edge access', language)}
- {pickText('客户图片对应的具体瀑布、拍摄日期、合法机位和人物/图片授权', 'Exact falls, date, lawful viewpoint, and people or image rights in client photography', language)}
+
+
{pickText('公开信息参考:贵州省民政厅黄果树资料、贵州省政协与贵州公开资料中的滴水滩信息、联合国教科文组织“中国丹霞”遗产资料、贵州省 2026 年政府定价景区清单及文化和旅游部 2025 年景区安全暗访通报。最终开放、预约、价格与安全要求以旅行当日景区和属地通知为准。', 'Public references include Guizhou Civil Affairs material on Huangguoshu, Guizhou public material on Dishuitan, UNESCO’s China Danxia record, Guizhou’s 2026 government-priced scenic-area list, and the Ministry of Culture and Tourism’s 2025 safety inspection notice. Live opening, reservation, price, and safety requirements follow the scenic area and local notice on the travel date.', language)}
+
+
+
+
+ 04 / Route Pairing
{pickText('一日看透一个水系,比跨区追赶三张照片更完整。', 'One water system in a day is richer than chasing three photos across regions.', language)}
+
+
+
+
+
+ );
+}
+
+function IndigenousEthnicVillagesDetailPage() {
+ const { language } = useTravelSite();
+ const villages = [
+ {
+ number: '01',
+ label: pickText('雷山・成熟景区', 'Leishan · Developed Scenic Area', language),
+ title: pickText('西江千户苗寨', 'Xijiang Thousand-Household Miao Village', language),
+ copy: pickText(
+ '成片木质吊脚楼、白水河、风雨桥和山腰全景构成最完整的第一印象,官方公开资料记录传统木质吊脚楼 1,300 余栋。这里也是服务成熟、游客集中、商业经营充分的景区型村寨:预约入园、观光车、行李、台阶、木构消防、住宿接待与夜间噪声要一起核对。',
+ 'Timber stilt houses, the Baishui River, wind-and-rain bridges, and a hillside panorama create the strongest first impression; public official material records more than 1,300 traditional timber stilt houses. It is also a mature, busy scenic-area village with substantial commerce, so timed entry, shuttle, luggage, steps, timber-fire safety, accommodation, and night noise all need checking.',
+ language,
+ ),
+ status: pickText('只使用开放观景台和公共动线;不承诺“私家机位、完全无人或避开所有客流”', 'Use open viewpoints and public routes only; no promise of a private angle, empty village, or total crowd avoidance', language),
+ },
+ {
+ number: '02',
+ label: pickText('黎平・两个不同村寨', 'Liping · Two Distinct Villages', language),
+ title: pickText('肇兴与黄岗侗寨', 'Zhaoxing & Huanggang Dong Villages', language),
+ copy: pickText(
+ '肇兴以仁、义、礼、智、信五座鼓楼和风雨桥形成清晰的公共游览骨架,适合第一次理解侗族木构公共空间。黄岗位于黎平县双江镇,是另一处具名社区;喊天节在传统上对应农历六月十五,侗族大歌有节庆、集体交往与接待语境,不能写成每天“村民自发为游客演唱”。',
+ 'Zhaoxing’s five drum towers—Ren, Yi, Li, Zhi, and Xin—and its wind-and-rain bridges form a legible public route for a first reading of Dong communal timber architecture. Huanggang is a separate named community in Shuangjiang, Liping. Its Heaven-Calling Festival traditionally falls on the fifteenth day of the sixth lunar month, while Dong Grand Song belongs to festival, collective, and hosting contexts—not an on-demand daily performance.',
+ language,
+ ),
+ status: pickText('先选肇兴或黄岗;若组合,必须分别确认日期、交通、主人/公开活动与可拍范围', 'Choose Zhaoxing or Huanggang first; a pairing needs separate dates, transport, host or public programme, and photography boundaries', language),
+ },
+ {
+ number: '03',
+ label: pickText('从江・公开景区与社区', 'Congjiang · Scenic Area & Community', language),
+ title: pickText('岜沙苗寨', 'Basha Miao Village', language),
+ copy: pickText(
+ '岜沙由多个自然寨组成,木楼、古树、森林信仰与人生礼俗共同构成村寨语境。镰刀剃头、迎宾和火枪元素如今也进入景区演艺表达;正式方案只引用当日官方公开节目,把舞台呈现与居民日常分开,不保证火枪鸣放,更不安排游客接触或操作枪械、镰刀。',
+ 'Basha comprises several natural hamlets, where timber homes, old trees, forest beliefs, and life-cycle customs form the village context. Sickle haircutting, welcomes, and musket elements also appear in scenic-area performance. A final plan cites only the current official public programme, separates staged presentation from resident life, never guarantees a musket salute, and never offers visitors firearms or sickle handling.',
+ language,
+ ),
+ status: pickText('不用“枪手部落”作为产品标题;成人礼与居民肖像不是可购买的表演道具', 'No “gunmen tribe” product label; rites of passage and resident portraits are not purchasable props', language),
+ },
+ {
+ number: '04',
+ label: pickText('安顺・先定具体村名', 'Anshun · Name the Village First', language),
+ title: pickText('布依石头寨', 'Buyi Stone Villages', language),
+ copy: pickText(
+ '客户文档的方向可落到镇宁扁担山石头寨,官方资料描述其以石块砌墙、石片盖顶;高荡则是另一处石木结构布依古寨,不能把两地历史、建筑和体验合并成一个“600 年全石头村”。慢行、织染或家访只有在村名、具名老师/主人、材料、费用与拍摄同意全部确认后进入方案。',
+ 'The brief can be anchored to Shitouzhai in Biandanshan, Zhenning, officially described with stone walls and stone-slab roofs. Gaodang is a separate Buyi village with stone-and-timber architecture; their histories, buildings, and experiences cannot be merged into one “600-year all-stone village.” A walk, textile session, or home visit enters the plan only after the village, named teacher or host, materials, fee, and photography consent are confirmed.',
+ language,
+ ),
+ status: pickText('用具体建筑和主人讲故事,不把居民日常包装成自动开放的“原生态体验”', 'Tell the story through a specific building and host, not by packaging daily life as automatically open “authenticity”', language),
+ },
+ ];
+ const flow = [
+ { title: pickText('先选接待关系', 'Choose the Visitor Relationship', language), copy: pickText('成熟景区公共游览、公开演艺、具名主人接待和住宿是四种不同关系;先选适合客人的一种,不做“越不商业越真实”的排名。', 'A developed public visit, public performance, named-host visit, and overnight stay are different relationships. Choose one that suits the guest, without ranking “less commercial” as “more authentic.”', language) },
+ { title: pickText('写清具体村寨与日期', 'Name the Village & Date', language), copy: pickText('西江、肇兴、黄岗、岜沙、扁担山石头寨或高荡逐一写明;节庆使用农历与当年公历双重核对,不以旧年海报推算。', 'State Xijiang, Zhaoxing, Huanggang, Basha, Biandanshan Shitouzhai, or Gaodang precisely. Check festivals against both the lunar calendar and current Gregorian notice, never an old poster.', language) },
+ { title: pickText('确认交通、住宿与接待能力', 'Confirm Access, Stay & Hosting', language), copy: pickText('核对入寨/入园、预约、门票接驳、车辆落客、行李、坡路台阶、洗手间、房型消防,以及住宿能否完成境外客人登记。', 'Confirm entry, reservation, ticket and shuttle, drop-off, luggage, slopes and steps, toilets, room and fire safety, and whether the stay can register international guests.', language) },
+ { title: pickText('区分公开节目与生活现场', 'Separate Programme from Daily Life', language), copy: pickText('公开演出只按当日节目表;农事、歌唱、家宴、成人礼和私人空间均需主人或社区明确同意,不能临时要求“来一个”。', 'Public performance follows the day’s programme. Farm work, singing, home meals, rites of passage, and private spaces require explicit host or community consent—never an impromptu demand.', language) },
+ { title: pickText('当天让社区边界优先', 'Let Community Boundaries Lead', language), copy: pickText('活动取消、主人忙碌、天气变化或社区临时事务优先于游客清单;切换到公共建筑步行、具名博物馆或另一项已确认活动。', 'Cancellation, host commitments, weather, or community matters take priority over a visitor checklist. Switch to a public architecture walk, named museum, or another confirmed activity.', language) },
+ ];
+ const gates = [
+ { title: pickText('村寨、主体与商业边界', 'Village, Operator & Commercial Boundary', language), copy: pickText('具体村名、景区/社区/主人身份、公开区域、收费项目、收益对象、门票与取消退款写清;不使用模糊的“当地人安排”。', 'State the village, scenic area, community or host identity, public area, paid items, beneficiary, ticket, and cancellation or refund. Avoid a vague “arranged by locals.”', language) },
+ { title: pickText('住宿、消防与境外登记', 'Stay, Fire & Guest Registration', language), copy: pickText('具名房型、真实图片、卫浴、热水、供暖/空调、木构消防、夜间联系人、车辆/行李和境外客人住宿登记能力逐项确认。', 'Verify the named room, real images, bathroom, hot water, heating or cooling, timber-fire safety, night contact, vehicle or luggage support, and international-guest registration.', language) },
+ { title: pickText('演艺、工具与人群安全', 'Performance, Tools & Crowd Safety', language), copy: pickText('当日节目、舞台/观众边界、火枪或镰刀元素的官方管理、噪声、拥挤、儿童与长者位置、下雨替代和医疗联系明确。', 'Confirm the day’s programme, stage and audience boundary, official control of any musket or sickle element, noise, crowds, child or elder position, rain fallback, and medical contact.', language) },
+ { title: pickText('同意、隐私与影像使用', 'Consent, Privacy & Image Use', language), copy: pickText('公共建筑可拍范围、住宅/祭祀空间、成人与未成年人肖像、服饰租赁、商业拍摄、无人机和图片版权分别取得许可。', 'Obtain separate permission for public architecture, homes or ritual spaces, adult and minor portraits, costume rental, commercial shoots, drones, and image rights.', language) },
+ ];
+ const routes = [
+ { number: '01', title: pickText('西江一晚・景区型初识', 'One Night in Xijiang · Scenic Introduction', language), copy: pickText('以公开观景、木构步行和一间已核验住宿为主;用入园时段与早晚节奏管理客流,不承诺私家机位。', 'Use public viewpoints, a timber-architecture walk, and one verified stay. Manage crowds through entry timing and morning or evening rhythm, not a promised private angle.', language), href: '/safaris/classic-guizhou/' },
+ { number: '02', title: pickText('侗寨两晚・肇兴或黄岗为主', 'Two Dong-Village Nights · Zhaoxing or Huanggang', language), copy: pickText('肇兴适合建筑与公共动线;黄岗只在日期、主人或当年公开节庆成立时加入。两地组合要保留交通和社区时间。', 'Zhaoxing suits architecture and a public route. Add Huanggang only with a valid date, host, or current public festival, leaving time for transfer and community rhythm.', language), href: '/safaris/culture-outdoor-mix/' },
+ { number: '03', title: pickText('从江南线・岜沙具名访问', 'Southern Congjiang · Named Basha Visit', language), copy: pickText('以公开景区动线和当日演艺通知为准,可与从江/肇兴住宿组合;不把火枪、剃头或成人礼做成游客参与项目。', 'Follow the public scenic route and current performance notice, paired with a Congjiang or Zhaoxing stay. Muskets, haircutting, and rites of passage are never visitor-participation products.', language), href: '/safaris/culture-outdoor-mix/' },
+ { number: '04', title: pickText('安顺布依线・只选一座石寨', 'Anshun Buyi Route · One Stone Village', language), copy: pickText('在扁担山石头寨与高荡之间选一处,围绕具体建筑、具名工坊或主人安排半日;可与黄果树衔接但不压缩成停车拍照。', 'Choose either Biandanshan Shitouzhai or Gaodang for a half-day around a specific building, named workshop, or host. Pair with Huangguoshu without reducing it to a roadside photo stop.', language), href: '/safaris/classic-guizhou/' },
+ ];
+
+ return (
+
+
+
+
+
+
+
+
Miao / Dong / Buyi · One Named Village at a Time
+
{pickText('原生民族村寨', 'Indigenous Ethnic Villages', language)}
+
{pickText('从西江、肇兴与黄岗,到岜沙和安顺布依石寨;不评判谁“更原生态”,只把每一处真正能进入的关系说明白。', 'From Xijiang, Zhaoxing, and Huanggang to Basha and Anshun’s Buyi stone villages, we do not rank who is “more authentic.” We clarify the relationship a visitor can honestly enter.', language)}
+
{pickText('比较四个村寨方向', 'Compare four village directions', language)}
+
+
+
+
+
+
+
+
+
{pickText('不是“原生态排行榜”', 'Not an Authenticity Ranking', language)}
+
{pickText('商业化程度不同,不等于文化价值有高低。', 'Different levels of commerce do not create a hierarchy of cultural value.', language)}
+
{pickText('客户文档希望按商业化梯度覆盖苗族、侗族与布依族代表村寨,同时使用了“世界最大、未受破坏、枪手部落、全石头村”等宣传表达。本页保留四组目的地方向,却把评判“真不真实”改为说明游客与村寨的实际关系:景区公共游览、按日期发生的节庆、公开演艺、具名主人接待或住宿。所有表演、住宿、家访、拍摄和费用都必须落到具体村名、具体日期与责任主体。', 'The brief asks for representative Miao, Dong, and Buyi villages along a commercialisation gradient, while using phrases such as “world’s largest,” “unspoiled,” “gunmen tribe,” and “entirely stone.” This page keeps the four destination directions but replaces a judgement of “realness” with the actual visitor relationship: public scenic visit, date-specific festival, public performance, named-host visit, or stay. Every performance, room, home visit, image, and fee must resolve to an exact village, date, and responsible party.', language)}
+
+
+ - {pickText('目的地方向', 'Directions', language)}
- {pickText('四组比较;一天只设一座主村寨', 'Four groups; one anchor village per day', language)}
+ - {pickText('接待模式', 'Visitor Modes', language)}
- {pickText('公共游览 / 具名接待 / 住宿', 'Public visit / named host / overnight', language)}
+ - {pickText('节庆与大歌', 'Festival & Grand Song', language)}
- {pickText('按传统语境与当年公开通知,不随到随演', 'Current notice and proper context, never on demand', language)}
+ - {pickText('岜沙演艺', 'Basha Performance', language)}
- {pickText('只按当日官方节目;不安排枪械或镰刀操作', 'Current official programme only; no weapon or sickle handling', language)}
+ - {pickText('住宿', 'Accommodation', language)}
- {pickText('房型、消防、行李与境外登记逐项确认', 'Room, fire, luggage, and international registration checked', language)}
+ - {pickText('影像原则', 'Image Principle', language)}
- {pickText('不偷拍住宅、仪式、儿童和居民日常', 'No covert images of homes, rites, children, or resident life', language)}
+
+
+
+
+
{pickText('客户文档对应西江千户苗寨 · 拍摄日期、机位与公开使用授权待归档', 'Client brief associates this with Xijiang · date, viewpoint, and publication rights require records', language)}
+
{pickText('西江村寨全景参考 · 只使用公开观景空间,不承诺图片中的客流与季节', 'Xijiang panorama reference · public viewpoints only; crowd level and season are not promised', language)}
+
{pickText('客户提供侗寨氛围图 · 具体为肇兴或黄岗、日期与授权待确认', 'Client-supplied Dong-village atmosphere · exact village, date, and rights pending', language)}
+
{pickText('鼓楼建筑参考 · 不用建筑照片证明当日必有侗族大歌或其他节目', 'Drum-tower architecture reference · the image does not prove a Grand Song or other programme will run', language)}
+
+
+
+
+
01 / Four Village Directions{pickText('先选关系,再选村寨。', 'Choose the relationship, then the village.', language)}
{pickText('成熟景区、侗寨公共空间、景区演艺与具名社区接待各有价值,也各有不同的承诺边界。', 'A developed scenic area, Dong public space, scenic performance, and named-community hosting each have value—and different promise boundaries.', language)}
+
{villages.map((village) =>
{village.number}{village.label}
{village.title}
{village.copy}
{village.status})}
+
+
+
+
+
+
+
02 / Village Planning
{pickText('把“想看什么”,先翻译成“被怎样接待”。', 'Translate “what to see” into “how to be hosted.”', language)}
+
{flow.map((item, index) => - {String(index + 1).padStart(2, '0')}
)}
+
+
+
+
+
+
03 / Hosting Gates{pickText('进入一座村寨,也要知道何时停在门外。', 'Entering a village also means knowing when to remain outside.', language)}
{pickText('开放区域、主人同意与社区当日安排共同决定访问深度;游客兴趣不自动转化为进入住宅、仪式或人物镜头的权利。', 'Public space, host consent, and the community’s day determine visit depth. Visitor interest does not create a right to enter a home, rite, or portrait.', language)}
+
{gates.map((gate, index) =>
{String(index + 1).padStart(2, '0')}{gate.title}
{gate.copy}
)}
+
+
{pickText('可以写入正式方案', 'What the final plan can promise', language)}- {pickText('具体村寨、公共入口/动线、交通、预计步行、洗手间与可休息点', 'Exact village, public entrance or route, transport, walking, toilets, and rests', language)}
- {pickText('具名住宿/主人/老师、接待时段、费用、包含内容、境外登记与取消规则', 'Named stay, host or teacher, time, fee, inclusions, international registration, and cancellation', language)}
- {pickText('当日公开节目、拍摄范围、老人儿童安排,以及取消后的具名替代', 'Current public programme, image boundary, elder or child plan, and named fallback', language)}
+
{pickText('不能直接当作承诺', 'Claims that are not automatic promises', language)}- {pickText('“最原生态、完全未商业化、世界最大、私家避人机位”或居民随叫随到', '“Most authentic,” untouched by commerce, world’s largest, private crowd-free angle, or residents on demand', language)}
- {pickText('黄岗随时唱大歌、喊天节全年可看、岜沙必鸣枪/必剃头或游客可参与工具操作', 'Huanggang song on demand, year-round Heaven-Calling, guaranteed Basha musket or haircut, or visitor tool handling', language)}
- {pickText('“600 年全石头村”、未获同意的家访/儿童肖像,以及客户图片的未归档版权', 'A “600-year all-stone village,” unconsented home visit or child portrait, or undocumented client-image rights', language)}
+
+
{pickText('公开信息参考:贵州省政协与贵州省人大公开的西江吊脚楼、肇兴五座鼓楼和岜沙村资料,贵州省民政厅黄岗村资料及黄岗喊天节公开信息,镇宁县公开的扁担山石头寨与高荡资料,以及贵州省 2026 年政府定价景区清单。最终开放、节目、票价、住宿登记与社区接待以旅行日期的景区、属地和具名主人确认结果为准。', 'Public references include Guizhou CPPCC and People’s Congress material on Xijiang stilt houses, Zhaoxing’s five drum towers, and Basha; Guizhou Civil Affairs and public material on Huanggang and its Heaven-Calling Festival; Zhenning public material on Biandanshan Shitouzhai and Gaodang; and Guizhou’s 2026 government-priced scenic-area list. Live opening, programmes, price, guest registration, and hosting follow the scenic area, locality, and named host for the travel date.', language)}
+
+
+
+
+ 04 / Route Pairing
{pickText('一座主村寨,一段可说清的关系。', 'One anchor village, one relationship we can explain.', language)}
+
+
+
+
+
+ );
+}
+
+function HistoricAncientTownsDetailPage() {
+ const { language } = useTravelSite();
+ const towns = [
+ {
+ number: '01',
+ label: pickText('贵阳花溪・明代石城', 'Huaxi, Guiyang · Ming Stone Town', language),
+ title: pickText('青岩古镇', 'Qingyan Ancient Town', language),
+ copy: pickText(
+ '青岩堡设置于明洪武年间,今天可从石城墙、定广门、石牌坊、街巷、宗教建筑与地方小吃理解其六百余年积累。它离贵阳较近,适合半日,但“古镇公共空间”与收费景点/套票不是同一概念;城墙台阶、节假日客流、停车接驳和餐饮排队需要写进节奏。',
+ 'Qingyan Fort was established in the Hongwu period of the Ming dynasty. Its six centuries can be read through stone walls, Dingguang Gate, memorial arches, lanes, religious buildings, and local food. It suits a half-day from Guiyang, but public town space is not the same as ticketed attractions or a bundled pass. Wall steps, holiday crowds, parking or transfers, and food queues belong in the plan.',
+ language,
+ ),
+ status: pickText('2026 政府定价清单列景区门票与套票两种价格;正式报价说明具体包含景点,不只写“青岩门票”', 'The 2026 government-priced list separates entry and a bundled pass; the final quote names included sites, not just “Qingyan ticket”', language),
+ },
+ {
+ number: '02',
+ label: pickText('黔东南・㵲阳河古城', 'Qiandongnan · Wuyang River City', language),
+ title: pickText('镇远古城', 'Zhenyuan Ancient Town', language),
+ copy: pickText(
+ '镇远自公元前 202 年置县,拥有 2,200 余年建置史;明清时期依托㵲阳河与湘黔滇驿道发展为商贸节点。古城本身仍是居民生活与商业并存的县城,青龙洞、石屏山、下㵲阳河游船等是不同收费项目,不能用“镇远一张票”或一张夜景图概括。',
+ 'Zhenyuan has more than 2,200 years of administrative history since its county was established in 202 BCE. In the Ming and Qing periods, the Wuyang River and Hunan-Guizhou-Yunnan routes supported a trading centre. The old town remains a lived-in county town where residents and commerce coexist; Qinglong Cave, Shiping Mountain, and Lower Wuyang cruises are separate paid products, not one “Zhenyuan ticket” or one night-view photograph.',
+ language,
+ ),
+ status: pickText('适合一晚慢住;灯光开启、游船、沿河噪声、洪水/暴雨与住宿位置均按当天确认', 'Best with one night; lighting, cruises, riverside noise, flood or rain, and the stay location are checked for the date', language),
+ },
+ {
+ number: '03',
+ label: pickText('安顺平坝・屯堡村落', 'Pingba, Anshun · Tunbao Village', language),
+ title: pickText('天龙屯堡', 'Tianlong Tunbao Village', language),
+ copy: pickText(
+ '天龙属于安顺屯堡文化的一处具名村落。明代军屯与后续移民、屯田和各民族交往共同塑造了语言、服饰、石木建筑、饮食与地戏传统;它不是“六百年从未改变”的静态遗址。安顺地戏 2006 年列入首批国家级非遗,景区演武堂的定时短场与春节、农历七月等传统节令中的村寨地戏也应分开理解。',
+ 'Tianlong is one named village within Anshun’s Tunbao culture. Ming military settlement, later migration and farming, and exchange among communities shaped its language, dress, stone-and-timber architecture, food, and Dixi tradition; it is not a static relic “unchanged for 600 years.” Anshun Dixi entered the first national intangible-heritage list in 2006. Timed short scenic-area shows at Yanwutang should be understood separately from village Dixi in traditional periods such as Spring Festival and the seventh lunar month.',
+ language,
+ ),
+ status: pickText('地戏只按当日公开场次;面具、服饰、居民肖像、住宅与仪式空间分别征得同意', 'Dixi follows the day’s public schedule; masks, dress, portraits, homes, and ritual space require separate consent', language),
+ },
+ ];
+ const flow = [
+ { title: pickText('先选一处历史主线', 'Choose One Historical Thread', language), copy: pickText('青岩看明代石城与宗教/市井层次;镇远看河运商贸与活态古城;天龙看屯堡聚落和地戏。一天不把三处压成同类打卡。', 'Use Qingyan for Ming stone-town and religious or street layers, Zhenyuan for river trade and a lived-in city, and Tianlong for Tunbao settlement and Dixi. Do not compress all three into one generic checklist.', language) },
+ { title: pickText('拆开公共空间与收费项目', 'Separate Public Space & Tickets', language), copy: pickText('核对古镇入口、联票所含景点、城墙/寺庙/古建、山体、游船、演出和接驳,不用一个含糊票价代表所有内容。', 'Check town entry, bundled-pass sites, walls, temples or historic buildings, mountain access, cruises, performance, and transfer. One vague price cannot represent them all.', language) },
+ { title: pickText('把真实步行与夜晚算进去', 'Plan Walking & the Night', language), copy: pickText('石板湿滑、城墙台阶、坡巷、夏季日晒、老人儿童、洗手间和休息点逐项说明;镇远过夜还要看河边住宿位置与夜间噪声。', 'State slick stone, wall steps, sloped lanes, summer sun, elders or children, toilets, and rests. A Zhenyuan night also depends on the riverside room and evening noise.', language) },
+ { title: pickText('演出与居民生活分开', 'Separate Performance & Resident Life', language), copy: pickText('景区地戏按节目表,传统节令活动按社区通知;住宅、宗教空间、仪式、店铺经营和居民肖像不能因为位于景区就默认开放。', 'Scenic Dixi follows the programme; traditional-period activity follows community notice. Homes, religious spaces, rites, shops, and resident portraits are not automatically open because they lie inside a scenic area.', language) },
+ { title: pickText('出发前确认当日变化', 'Confirm Live Changes', language), copy: pickText('复核开放、票务、维修、演出、游船、水位、暴雨、道路停车和夜景照明;不成立时切换为仍开放的具名古建、博物馆或城市慢行。', 'Recheck opening, tickets, restoration, performance, cruise, water level, rain, road or parking, and night lighting. If unavailable, switch to a named open building, museum, or town walk.', language) },
+ ];
+ const gates = [
+ { title: pickText('历史表述与具体遗存', 'History & Specific Fabric', language), copy: pickText('建置史、堡城/城墙、驿道商贸、屯堡迁徙与具体建筑分别注明来源;不把整个现有街区都说成六百年原物。', 'Source administrative history, fort or wall, trade routes, Tunbao migration, and specific buildings separately. Do not call the entire present streetscape a 600-year-old original.', language) },
+ { title: pickText('开放、门票与现场运营', 'Access, Tickets & Operations', language), copy: pickText('具名景区、收费项目、联票内容、预约、开放时间、演出场次、游船/接驳、维修关闭、价格与取消退款逐项确认。', 'Confirm the named site, paid item, pass inclusion, reservation, hours, performance, cruise or transfer, restoration closure, price, and cancellation or refund.', language) },
+ { title: pickText('步行、水边与儿童长者', 'Walking, Waterfront & Families', language), copy: pickText('城墙和山体台阶、湿滑石板、临河护栏、夜路照明、拥挤、洗手间、儿童牵行、长者缩短路线和医疗联系写入方案。', 'Include wall and hill steps, slick stone, riverside barriers, night lighting, crowds, toilets, child hand-holding, shortened elder route, and medical contact.', language) },
+ { title: pickText('文物、居民与影像边界', 'Heritage, Residents & Images', language), copy: pickText('不触摸攀爬文物;宗教/仪式/住宅空间、地戏后台、成人与未成年人肖像、商业拍摄、三脚架和无人机按许可。', 'Do not touch or climb heritage fabric. Religious, ritual, or home space, Dixi backstage, adult and minor portraits, commercial shoots, tripods, and drones follow permission.', language) },
+ ];
+ const routes = [
+ { number: '01', title: pickText('贵阳半日・青岩石城与小吃', 'Guiyang Half-Day · Qingyan Stone Town & Food', language), copy: pickText('用一条城门—石巷—具名历史建筑—地方小吃的短线完成,不把全部联票点位塞满;返贵阳前保留停车和客流缓冲。', 'Use a concise gate-lane-named-building-local-food route instead of filling every bundled-pass site, with parking and crowd buffer before returning to Guiyang.', language), href: '/safaris/classic-guizhou/' },
+ { number: '02', title: pickText('镇远一晚・河城日夜', 'One Night in Zhenyuan · River City by Day & Night', language), copy: pickText('白天选古巷、码头/祝圣桥与一处收费古建或山体,傍晚回到河岸;游船和夜景只作为按当天成立的加项。', 'By day, choose lanes, wharf or Zhusheng Bridge, and one ticketed historic building or hill. Return to the river at dusk; cruise and lighting remain date-specific additions.', language), href: '/safaris/classic-guizhou/' },
+ { number: '03', title: pickText('安顺半日・天龙屯堡与地戏', 'Anshun Half-Day · Tianlong Tunbao & Dixi', language), copy: pickText('围绕村落公共动线、具名建筑讲解和当日演武堂短场安排;若地戏取消,保留建筑/移民史讲解,不临时要求村民开演。', 'Use the village public route, a named architecture interpretation, and the day’s short Yanwutang show. If Dixi is cancelled, keep the architecture and migration story—never ask residents for an impromptu show.', language), href: '/safaris/culture-outdoor-mix/' },
+ ];
+
+ return (
+
+
+
+
+
+
+
Stone Fort / River Trade / Tunbao Village
+
{pickText('历史古镇古村', 'Historic Towns & Villages', language)}
+
{pickText('青岩不是江南水乡,镇远不只是一张夜景,天龙屯堡也不是停住六百年的布景。沿石城、河运和军屯三条线读贵州。', 'Qingyan is not a Jiangnan water town, Zhenyuan is more than a night view, and Tianlong is not a set frozen for six centuries. Read Guizhou through stone fort, river trade, and military settlement.', language)}
+
{pickText('比较三处古镇古村', 'Compare three historic places', language)}
+
+
+
+
+ {pickText('三条贵州历史线索', 'Three Guizhou Historical Threads', language)}{pickText('山地古镇的价值,不在于复制一座江南水乡。', 'A mountain town is valuable without imitating a Jiangnan water town.', language)}
{pickText('客户文档把青岩、镇远与天龙屯堡放在同一章节,强调屯堡文化、盐运商贸和多民族融合。我们保留这三处,却不把它们做成同一种“古街夜景”:青岩从明代堡城与石构空间进入,镇远从 2,200 余年建置和㵲阳河商贸进入,天龙从安顺屯堡聚落与地戏进入。建筑年代、现存形态、演出、票务、夜景与居民生活分别说明,避免“整座古镇原样保存六百年”一类误导。', 'The brief groups Qingyan, Zhenyuan, and Tianlong around Tunbao culture, trade, and intercultural exchange. We keep the three without turning them into one generic old-street night scene: Qingyan begins with Ming fortification and stone space, Zhenyuan with more than 2,200 years of administration and Wuyang trade, and Tianlong with Anshun Tunbao settlement and Dixi. Building date, present fabric, performance, tickets, lighting, and resident life are stated separately, avoiding claims that an entire town remains unchanged for six centuries.', language)}
+
+ - {pickText('三个方向', 'Three Places', language)}
- {pickText('青岩 / 镇远 / 天龙屯堡', 'Qingyan / Zhenyuan / Tianlong Tunbao', language)}
+ - {pickText('青岩', 'Qingyan', language)}
- {pickText('明洪武年间设堡;半日石城线', 'Ming Hongwu-period fort; half-day stone-town route', language)}
+ - {pickText('镇远', 'Zhenyuan', language)}
- {pickText('公元前 202 年置县;建议一晚', 'County established in 202 BCE; one night preferred', language)}
+ - {pickText('天龙', 'Tianlong', language)}
- {pickText('安顺屯堡村落;地戏按当日场次', 'Anshun Tunbao village; Dixi by current schedule', language)}
+ - {pickText('票务原则', 'Ticket Principle', language)}
- {pickText('公共街区、单点门票与联票分别说明', 'Public streets, individual tickets, and passes separated', language)}
+ - {pickText('夜景原则', 'Night Principle', language)}
- {pickText('不保证固定亮灯、游船或同等机位', 'No guaranteed lighting, cruise, or identical viewpoint', language)}
+
+
+
+
{pickText('客户文档对应青岩古镇氛围 · 具体机位、建筑名称、日期与授权待归档', 'Client brief associates this with Qingyan · exact viewpoint, building, date, and rights require records', language)}
+
{pickText('客户提供石城墙画面 · 是否为青岩定广门/具体墙段待确认,不作为全线开放证明', 'Client-supplied stone-wall image · exact Qingyan gate or wall section pending; not proof the full route is open', language)}
+
{pickText('客户文档对应镇远夜景 · 灯光、季节、机位与公开使用授权待归档', 'Client brief associates this with Zhenyuan at night · lighting, season, viewpoint, and rights require records', language)}
+
{pickText('镇远河城氛围 · 不保证当日游船、同等亮灯或图片中的客流状态', 'Zhenyuan river-city atmosphere · no promise of cruise, identical lighting, or matching crowd level', language)}
+
+ 01 / Three Historic Places{pickText('一处古镇,一条历史主线。', 'One historic place, one legible historical thread.', language)}
{pickText('堡城、河城和屯堡村落分别决定停留方式,不用“古色古香”替代具体内容。', 'A fortified town, river city, and Tunbao village each require their own stay—specific content replaces a generic “ancient charm.”', language)}
{towns.map((town) =>
{town.number}{town.label}
{town.title}
{town.copy}
{town.status})}
+ })
02 / Historic-Place Planning
{pickText('先读清楚历史,再走进街巷。', 'Read the history before entering the lanes.', language)}
{flow.map((item, index) => - {String(index + 1).padStart(2, '0')}
)}
+ 03 / Heritage & Visit Gates{pickText('开放给游客的古城,也仍然是文物与生活现场。', 'A town open to visitors remains heritage and lived space.', language)}
{pickText('门票不能替代对文物、居民、宗教和演出的边界说明;任何“沉浸”都不意味着可进入未开放区域。', 'A ticket does not replace boundaries around heritage, residents, religion, and performance. “Immersion” never grants access to closed space.', language)}
{gates.map((gate, index) =>
{String(index + 1).padStart(2, '0')}{gate.title}
{gate.copy}
)}
{pickText('可以写入正式方案', 'What the final plan can promise', language)}- {pickText('具名古镇/村落、公共步行线、具体收费景点、开放时间与预计停留', 'Named town or village, public walk, specific paid sites, hours, and planned stay', language)}
- {pickText('真实步行、台阶、停车/接驳、洗手间、休息点和老人儿童替代', 'Real walking, steps, parking or transfer, toilets, rests, and elder or child alternative', language)}
- {pickText('当日地戏/游船/灯光核验,以及取消后的具名建筑或博物馆替代', 'Current Dixi, cruise, or lighting check and a named building or museum fallback', language)}
{pickText('不能直接当作承诺', 'Claims that are not automatic promises', language)}- {pickText('“整座六百年原样不变”“所有建筑都是明代原物”或“完全无商业化”', '“Unchanged for 600 years,” every building a Ming original, or entirely free of commerce', language)}
- {pickText('镇远每天同等夜景/游船、天龙随到即演传统地戏或居民配合换装拍照', 'Identical Zhenyuan lighting or cruise daily, Tianlong Dixi on demand, or resident costume posing', language)}
- {pickText('客户图片的具体机位、建筑、拍摄日期与未归档版权,以及无人机可飞', 'Exact client-image viewpoint, building, date, undocumented rights, or permission to fly a drone', language)}
{pickText('公开信息参考:贵州省人大公开的青岩、镇远、屯堡建筑与地戏资料,镇远县古城/古码头与城市保护规划,中国民族报 2026 年安顺地戏报道,以及贵州省 2026 年政府定价景区门票与景区内交通清单。最终开放、票价、联票内容、地戏场次、游船、夜景与交通以旅行当日景区和属地通知为准。', 'Public references include Guizhou People’s Congress material on Qingyan, Zhenyuan, Tunbao architecture, and Dixi; Zhenyuan county material on the old city, wharves, and conservation planning; a 2026 China Ethnic News report on Anshun Dixi; and Guizhou’s 2026 government-priced scenic-area and transport list. Live access, price, pass inclusions, Dixi, cruise, lighting, and transport follow the scenic area and local notice on the travel date.', language)}
+ 04 / Route Pairing
{pickText('半日读一座石城,一晚读一座河城。', 'A half-day for a stone town; a night for a river city.', language)}
+
+
+ );
+}
+
+function QingyanBattleImmersiveDetailPage() {
+ const { language } = useTravelSite();
+ const formats = [
+ {
+ number: '01',
+ label: pickText('已有产品', 'Operating Product', language),
+ title: pickText('《战青岩》山地实景体验', 'Zhan Qingyan Field Experience', language),
+ copy: pickText(
+ '2026 年公开报道确认,项目由青岩古镇景区管理公司与贵州创新文化旅游开发公司共同打造,落地定广湖畔,设置三处实景战场区域。参与者可分配侦察、医务、担架、机枪、士兵或物资小队等角色,在山地小道、战场救护、障碍和模拟战斗中行进。',
+ 'Public reporting in 2026 confirms a joint project by the Qingyan scenic-area company and Guizhou Innovation Culture & Tourism. Beside Dingguang Lake, three field zones assign roles such as scout, medic, stretcher bearer, machine gunner, soldier, or supply team across mountain paths, rescue tasks, obstacles, and simulated battle.',
+ language,
+ ),
+ status: pickText('已运营不等于随时可订:日期、场次、组团方式、票价和个人游客入口仍按当期书面信息确认', 'Operating does not mean always bookable: date, session, group format, price, and individual access still require current written confirmation', language),
+ },
+ {
+ number: '02',
+ label: pickText('客户构想', 'Brief Concept', language),
+ title: pickText('古镇街巷任务式剧本', 'Old-Town Mission Roleplay', language),
+ copy: pickText(
+ '客户文档提出在石巷、城墙和历史院落中,以红军战士、地下交通员、村民或守城者身份完成线索追踪、情报传递、NPC 互动和剧情解锁,并在结尾由讲解员区分史实与戏剧化处理。它与现有《战青岩》的场地、角色和玩法并不完全相同。',
+ 'The brief proposes clue trails, intelligence delivery, NPC interaction, and branching storylines through stone lanes, walls, and historic courtyards, with guests cast as soldiers, messengers, villagers, or defenders and a final debrief separating history from dramatization. This is not identical to the live product in venue, roles, or gameplay.',
+ language,
+ ),
+ status: pickText('目前作为二期共创方向,不把 3–4 小时、真人 NPC、年代服装和城墙战斗写成现成服务', 'A phase-two co-creation direction; 3–4 hours, live NPCs, period dress, and a wall battle are not presented as existing services', language),
+ },
+ {
+ number: '03',
+ label: pickText('境外私家小团', 'Private International Group', language),
+ title: pickText('翻译与文化敏感版', 'Interpreted, Context-Led Format', language),
+ copy: pickText(
+ '面向境外客人时,优先确认是否可接受私家小团、是否有英文主持或随行翻译、服装与仿真道具规则,以及如何解释长征、交战方、牺牲和纪念语境。客人不愿角色扮演时,改为遗址讲解与历史步行,不强制进入战争模拟。',
+ 'For international guests, first confirm private-group access, English facilitation or an interpreter, dress and replica-prop rules, and how the Long March, opposing forces, loss, and commemoration are contextualised. Guests who decline roleplay receive a site-led historical walk rather than compulsory battle simulation.',
+ language,
+ ),
+ status: pickText('公开报道显示境外客人仅占少量;英文脚本、主持能力和跨文化说明尚无公开证据', 'Public reporting shows only a small international share; no public evidence yet confirms an English script, facilitation, or cross-cultural interpretation', language),
+ },
+ ];
+ const flow = [
+ { title: pickText('确认当日可售版本', 'Confirm the Live Version', language), copy: pickText('向两家运营主体确认项目入口、场次、真实时长、最低/最高人数、散客或包团、价格、付款、取消和天气停运;不以新闻报道替代预约凭证。', 'Confirm entrance, session, real duration, group minimum and maximum, individual or private access, price, payment, cancellation, and weather closure with the two operating entities. A news report is not a booking voucher.', language) },
+ { title: pickText('核对史实与空间', 'Map History to Place', language), copy: pickText('由具名历史顾问把 1935 年 4 月青岩相关战斗、狮子山/簸箕山等史迹与今天项目动线逐点对应;不能把整座古镇或所有院落笼统称为原战场。', 'A named historian maps the April 1935 Qingyan action and sites such as Lion and Boji hills against the present route. The entire town or every courtyard cannot be labelled the original battlefield.', language) },
+ { title: pickText('匹配客人与角色', 'Match Guest & Role', language), copy: pickText('收集年龄、行动能力、心肺/骨关节情况、伤病与战争叙事接受度,再选择角色;儿童、长者和不适合匍匐/负重者需要观察或轻任务版本。', 'Collect age, mobility, cardio or joint conditions, injuries, and comfort with war narratives before assigning roles. Children, older guests, and those unsuited to crawling or load-carrying need an observer or gentle-task version.', language) },
+ { title: pickText('确认语言、服装与道具', 'Confirm Language, Dress & Props', language), copy: pickText('明确英文主持、随行翻译、字幕/术语表、服装尺码与清洁、仿真枪械/爆破/烟雾接触规则、肖像拍摄和退出信号,不让翻译在现场临时猜测。', 'Confirm English facilitation, interpreter, glossary or captions, costume size and cleaning, replica-weapon, blast and smoke rules, image consent, and stop signals—without asking an interpreter to improvise terminology on site.', language) },
+ { title: pickText('体验后做史实复盘', 'Close with a Historical Debrief', language), copy: pickText('结束后说明哪些角色、任务和场景属于戏剧化重构,哪些事件、人物与地点有史料或遗址依据,并给出选择退出、安静纪念或继续古镇步行的空间。', 'Close by distinguishing reconstructed roles, tasks, and scenes from sourced events, people, and places, while allowing guests to opt out, reflect quietly, or continue with a regular town walk.', language) },
+ ];
+ const gates = [
+ { title: pickText('运营、票务与接待', 'Operation, Ticket & Hosting', language), copy: pickText('具名运营主体、当前产品说明、场次/容量、私家小团与境外客接待、价格、发票、取消退款、天气与景区关闭替代。', 'Named operator, current product sheet, session and capacity, private and international-group handling, price, invoice, cancellation or refund, weather, and scenic-area closure alternative.', language) },
+ { title: pickText('历史与文物空间', 'History & Heritage Space', language), copy: pickText('剧本审校人、史料来源、遗址点位、真实与虚构标记,以及古城墙、院落、革命遗址和公共街巷的书面使用边界;不得攀爬、钉挂或损伤文物。', 'Script reviewer, historical sources, site mapping, fact-versus-fiction labels, and written limits for walls, courtyards, revolutionary sites, and public lanes; no climbing, fixing, or damage to heritage fabric.', language) },
+ { title: pickText('爆破、烟雾与现场安全', 'Effects & Field Safety', language), copy: pickText('声效/爆破/烟雾的设备与物料、噪声和能见度控制、消防、急救、通讯、人员比例、雨天泥泞/山路、障碍退出、医疗转运和保险覆盖。', 'Equipment and materials for sound, blast, or smoke effects, noise and visibility control, fire, first aid, communication, staffing ratio, wet mountain terrain, obstacle exits, medical transfer, and insurance coverage.', language) },
+ { title: pickText('年龄、语言与知情选择', 'Age, Language & Consent', language), copy: pickText('客户提出的“12 岁以上”不是已证实门槛;运营方应书面给出年龄、身高/体能、健康和陪同规则,并提供可理解的中英文风险说明、角色自愿选择、肖像同意和随时退出机制。', 'The brief’s “12+” is not a verified operating threshold. The operator must issue written age, size or fitness, health, and guardian rules, plus understandable Chinese and English risk information, voluntary role choice, image consent, and a stop-any-time mechanism.', language) },
+ ];
+ const routes = [
+ { number: '01', title: pickText('贵阳一日・实景体验版', 'Guiyang Day · Live Field Version', language), copy: pickText('仅在《战青岩》当日场次、语言支持与客人筛查通过后安排;前后保留换装、淋浴/清洁、用餐和情绪缓冲。', 'Use only when the live session, language support, and guest screening pass. Keep time around it for changing, washing, food, and emotional decompression.', language), href: '/safaris/classic-guizhou/' },
+ { number: '02', title: pickText('青岩半日・史迹步行版', 'Qingyan Half-Day · Historical Walk', language), copy: pickText('不参加战斗模拟时,以公开可进入的古镇与经核实红色史迹为主,由讲解员说明 1935 年事件和现今遗存,适合轻量人文客人。', 'Without battle simulation, use publicly accessible town space and verified revolutionary sites, with an interpreter explaining the 1935 events and surviving fabric. Suits gentler cultural travellers.', language), href: '/experiences/historic-ancient-towns/' },
+ { number: '03', title: pickText('二期候选・古镇任务剧本', 'Phase Two · Old-Town Mission Script', language), copy: pickText('只有脚本审校、古镇/文物空间许可、演员与英文、居民和游客影响、声光电及保险全部成立后,才把客户构想制作成独立私家产品。', 'Develop the brief’s private old-town mission format only after script review, heritage and venue permission, actors and English, resident and visitor impact, effects, and insurance all pass.', language), href: '/contact/' },
+ ];
+
+ return (
+
+
+
+
+
+
+
Operating Experience / Specialist Review
+
{pickText('青岩战斗・实景沉浸演绎', 'Qingyan 1935: Immersive History', language)}
+
{pickText('《战青岩》已经落地运营;客户提出的古镇街巷剧本则仍是二期构想。先分清两种产品,再决定境外私家小团能预约哪一种。', 'Zhan Qingyan is now operating; the brief’s old-town mission roleplay remains a phase-two concept. We separate the two before deciding what a private international group can actually book.', language)}
+
{pickText('查看现有产品与构想边界', 'See live product vs concept', language)}
+
+
+
+
+ {pickText('2026 年 8 月核验结论', 'Review as of August 2026', language)}{pickText('它已经不是纸上概念,但也不是客户文档所写内容全部兑现。', 'It is no longer a paper concept—nor is every promise in the brief already delivered.', language)}
{pickText('官方与本地媒体已确认《战青岩》:2026 年 1 月联合打造,4 月 29 日起全面运营;截至 7 月 5 日报道累计接待超过 3 万人次,项目位于定广湖畔,使用山地地形、角色分工和模拟战场。客户文档描述的却是石巷、城墙、历史院落、线索追踪、情报传递、真人 NPC 与历史复盘。两者方向接近但不是同一个已被证明的产品,因此官网只把现有《战青岩》列为可询价候选,把古镇任务剧本列为二期共创。', 'Official and local reporting confirms Zhan Qingyan: jointly created in January 2026 and fully operating from 29 April. A 5 July report recorded more than 30,000 visits. It uses mountain terrain, assigned roles, and simulated battlefield zones beside Dingguang Lake. The brief instead describes stone lanes, walls, courtyards, clue trails, intelligence delivery, live NPCs, and a historical debrief. The directions overlap but are not the same evidenced product, so this page treats the live experience as an enquiry candidate and the old-town mission script as phase-two co-creation.', language)}
+
+ - {pickText('史实基础', 'Historical Basis', language)}
- {pickText('1935 年 4 月青岩一带红军战斗', 'Red Army action around Qingyan, April 1935', language)}
+ - {pickText('现有产品', 'Live Product', language)}
- {pickText('《战青岩》/ 定广湖畔三处实景区域', 'Zhan Qingyan / three field zones by Dingguang Lake', language)}
+ - {pickText('公开运营', 'Public Operation', language)}
- {pickText('2026-04-29 起全面运营;当日状态仍复核', 'Full operation from 29 Apr 2026; live status still rechecked', language)}
+ - {pickText('客户方案', 'Brief Format', language)}
- {pickText('3–4 小时古镇任务剧本 / 尚未证明为现有产品', '3–4-hour old-town roleplay / not evidenced as live', language)}
+ - {pickText('年龄', 'Age', language)}
- {pickText('客户建议 12+;运营方书面规则待取得', 'Brief suggests 12+; operator rule still required', language)}
+ - {pickText('英文与私家团', 'English & Private Groups', language)}
- {pickText('尚无公开证据;必须专项确认', 'No public evidence yet; specialist confirmation required', language)}
+
+
+
+
{pickText('客户图片明确标注“战青岩” · 具体拍摄日期、场次、人物同意与公开使用授权仍待归档', 'Client image explicitly labelled Zhan Qingyan · date, session, participant consent, and publication rights still require records', language)}
+
{pickText('客户提供石城氛围图 · 具体墙段、拍摄日期与公开使用授权待归档', 'Client-supplied stone-town context · exact wall, date, and publication rights require records', language)}
+
+ 01 / Product Status{pickText('现有实景项目、客户剧本构想、境外接待,分成三层。', 'Separate the live field product, brief concept, and international delivery.', language)}
{pickText('“已经有《战青岩》”不能自动证明客户文档里的每一项玩法都能预订。', 'The existence of Zhan Qingyan does not automatically make every activity in the brief bookable.', language)}
{formats.map((format) =>
{format.number}{format.label}
{format.title}
{format.copy}
{format.status})}
+ })
02 / Verification Flow
{pickText('先拿到当期产品资料,再为境外客人改编。', 'Obtain the current product file before adapting it for international guests.', language)}
{flow.map((item, index) => - {String(index + 1).padStart(2, '0')}
)}
+ 03 / History, Heritage & Safety Gates{pickText('有真实战场感,更需要把历史、文物和风险说清楚。', 'A convincing battlefield makes historical, heritage, and safety clarity more important.', language)}
{pickText('角色扮演与国防教育可以增强理解,但不能模糊史实、强迫参与,也不能把爆破烟雾和山地障碍当成普通古镇步行。', 'Roleplay and defence education can deepen understanding, but must not blur facts, compel participation, or treat smoke, blast effects, and mountain obstacles as an ordinary town walk.', language)}
{gates.map((gate, index) =>
{String(index + 1).padStart(2, '0')}{gate.title}
{gate.copy}
)}
{pickText('当前可以公开', 'Safe to publish now', language)}- {pickText('1935 年青岩相关战斗的史实基础与红军狮子山战斗遗址线索', 'The historical basis of the 1935 Qingyan action and the Lion Hill battle-site thread', language)}
- {pickText('《战青岩》的具名联合运营方、定广湖畔场地、三处实景区域与公开角色类型', 'Named joint operators, Dingguang Lake setting, three field zones, and reported roles for Zhan Qingyan', language)}
- {pickText('截至 2026 年 7 月公开报道的运营事实;正式方案继续做当日核验', 'Operating facts reported through July 2026, with live checks still required for a final plan', language)}
{pickText('尚不能直接承诺', 'Not an automatic promise', language)}- {pickText('客户构想中的石巷/城墙/院落任务剧本、线索追踪、情报传递与全部真人 NPC', 'The brief’s lane, wall, and courtyard mission script, clue trails, intelligence delivery, or full live-NPC format', language)}
- {pickText('3–4 小时、12+、全程英文、私家包场、年代服装尺码齐全与每日固定场次', 'A 3–4-hour duration, age 12+, full English, private buyout, complete costume sizing, or fixed daily sessions', language)}
- {pickText('城墙声光电战斗已获许可、所有游客可接触仿真道具、保险已覆盖境外客人', 'Permitted wall-based effects, universal replica-prop handling, or confirmed insurance for international guests', language)}
{pickText('公开信息参考:中国国防报 2026-05-20《贵州省贵阳市花溪区沉浸式体验,还原战火烽烟》;贵阳网 2026-07-06《累计接待游客超3万人次!〈战青岩〉沉浸式文旅项目掀起红色旅游热潮》;贵州省政协《青岩历史文化的三个视角》;贵阳市“十四五”文化和旅游发展规划。文物空间的使用还须遵守 2025 年 3 月 1 日起施行的修订《中华人民共和国文物保护法》及属地管理要求。', 'Public references: China National Defense News, 20 May 2026; Guiyang News, 6 July 2026; Guizhou CPPCC, “Three Perspectives on Qingyan History”; and Guiyang’s 14th Five-Year culture and tourism plan. Any heritage-space use must also follow the revised PRC Cultural Relics Protection Law effective 1 March 2025 and local management requirements.', language)}
+ 04 / Route Pairing
{pickText('同一段历史,可以有三种强度。', 'One history, three levels of participation.', language)}
+
+
+ );
+}
+
+function LoushanguanBattleImmersiveMarchDetailPage() {
+ const { language } = useTravelSite();
+ const formats = [
+ {
+ number: '01',
+ label: pickText('现有互动演出', 'Operating Interactive Show', language),
+ title: pickText('“跟着团长攻打娄山关”', 'Follow the Commander at Loushan Pass', language),
+ copy: pickText(
+ '《娄山关大捷》实景演出已经运营多年。2026 年“五一”升级推出游客参与版本,公开报道显示参与者可穿演出服、跟随演员进入战壕与山林,在舞台烟火、声效和模拟战斗场景中完成互动。它位于娄山关大捷实景演艺景区,不等同于沿所有真实战斗点位徒步。',
+ 'The Loushan Pass Victory live show has operated for years. A participatory upgrade launched for May Day 2026, with public reporting showing guests in costume following actors through trenches and woodland amid stage effects, sound, and simulated combat. It operates in the live-performance scenic area and is not the same as hiking every original battle position.',
+ language,
+ ),
+ status: pickText('2026 年公开报道出现每日 13:30 场次;正式方案仍以运营方当期排期、容量与票种为准', 'A 13:30 daily session appeared in 2026 reporting; the final plan still follows current operator schedule, capacity, and ticket type', language),
+ },
+ {
+ number: '02',
+ label: pickText('历史遗址参观', 'Battlefield Heritage Visit', language),
+ title: pickText('娄山关战斗遗址与诗词线', 'Battle Site & Poetry Route', language),
+ copy: pickText(
+ '以娄山关战斗遗址陈列馆、关口、大尖山/小尖山/点金山等公开点位和《忆秦娥・娄山关》展示为主,由讲解员说明 1935 年 2 月 25 日至 26 日战斗与遵义会议后的历史位置。今天山体上的诗词为大理石手迹碑,不应写成 1935 年留下的原始摩崖石刻。',
+ 'Use the battle-site exhibition hall, pass, publicly accessible Dajianshan, Xiaojian Mountain, and Dianjin Mountain positions, and the display of “Loushan Pass,” with interpretation of the 25–26 February 1935 battle and its place after the Zunyi Conference. The poem visible on the mountain is a later marble calligraphy panel, not an original 1935 cliff inscription.',
+ language,
+ ),
+ status: pickText('适合作为不参加战争模拟的默认版本;开放点位、接驳、步行与陈列馆状态按日期确认', 'The default for guests declining combat simulation; access, transfer, walking, and exhibition-hall status are checked by date', language),
+ },
+ {
+ number: '03',
+ label: pickText('客户二期构想', 'Brief Phase-Two Concept', language),
+ title: pickText('4–5 小时山道行军剧本', '4–5-Hour Narrative Mountain March', language),
+ copy: pickText(
+ '客户提出从关下集结、沿“古驿道”上行、在历史点位观看演员分段演绎、登顶读诗并下山复盘。当前没有公开证据证明这条完整动线已经常态运营,也未证明现有演艺景区、战斗遗址和所谓古驿道属于同一条可连续执行路线。',
+ 'The brief proposes a foot-of-pass briefing, an ascent on an “ancient post road,” actor-led scenes at historical positions, summit poetry, and a descent debrief. No public evidence yet shows this complete route in regular operation or proves that the live-show area, battle heritage, and proposed old road form one continuous guest route.',
+ language,
+ ),
+ status: pickText('作为共创方案保留;先完成路线测绘、历史审校、场地许可、演员与英文、山地安全和撤离测试', 'Retained for co-creation only after route mapping, historical review, venue permission, actors and English, mountain safety, and evacuation testing', language),
+ },
+ ];
+ const flow = [
+ { title: pickText('确认买的是哪一种产品', 'Define the Exact Product', language), copy: pickText('区分普通遗址参观、观看《娄山关大捷》、参与“跟着团长”以及尚未落地的山道剧本;分别取得入口、场次、时长、价格、容量、预约和取消资料。', 'Separate a heritage visit, watching the Loushan Pass Victory show, joining “Follow the Commander,” and the unbuilt narrative march. Obtain entrance, session, duration, price, capacity, booking, and cancellation for the exact choice.', language) },
+ { title: pickText('把史实点与演艺场逐点对应', 'Map History Against the Set', language), copy: pickText('由具名历史顾问标明 1935 年战斗点位、现有遗址、陈列馆、纪念性诗词碑和演艺景区;舞台战壕、碉堡与爆破区不得自动表述为原始遗存。', 'A named historian maps 1935 battle positions, surviving sites, the exhibition hall, commemorative poetry panel, and performance area. Stage trenches, bunkers, and effects zones are not automatically original remains.', language) },
+ { title: pickText('测出真实山地负荷', 'Measure the Real Mountain Load', language), copy: pickText('记录起终点、距离、累计爬升、台阶/坡度、路面、遮阴、洗手间、补水、信号、单向或折返和退出点;“铺装山道、中等强度”不能替代数据。', 'Record start and finish, distance, elevation gain, steps or gradient, surface, shade, toilets, water, signal, one-way or return pattern, and exits. “Paved, moderate trail” is not a substitute for measurements.', language) },
+ { title: pickText('筛查客人与特效接受度', 'Screen Guests & Effects', language), copy: pickText('确认年龄、行动能力、心肺/骨关节、听力、呼吸系统、孕期、创伤或战争叙事敏感,以及对制服、仿真道具、烟雾、强声和火焰的接受度;参与必须自愿。', 'Confirm age, mobility, cardio or joint health, hearing, respiratory needs, pregnancy, trauma or war-narrative sensitivity, and comfort with uniforms, replicas, smoke, loud sound, and flame. Participation must be voluntary.', language) },
+ { title: pickText('用史实复盘结束', 'End with Evidence, Not Spectacle', language), copy: pickText('演出后区分战斗史实、诗词意象、纪念设施与艺术重构;英文版本先经历史与语言双重审校,不把戏剧对白直接当作历史结论。', 'After the show, separate battle history, poetic imagery, commemorative installations, and artistic reconstruction. The English version receives historical and language review rather than treating dramatic dialogue as evidence.', language) },
+ ];
+ const gates = [
+ { title: pickText('运营主体与当期票务', 'Operator & Live Ticketing', language), copy: pickText('具名经营公司、景区/演出/互动票种、每日场次、参与容量、服装与角色是否包含、私家小团、价格、付款、发票、迟到、取消退款和天气停演。', 'Named operator, scenic, show, and interactive ticket types, daily sessions, participation capacity, included costume or role, private-group handling, price, payment, invoice, late arrival, cancellation, and weather closure.', language) },
+ { title: pickText('历史、遗址与文物边界', 'History, Site & Heritage', language), copy: pickText('剧本审校人、战斗点位来源、演艺场与遗址的空间关系、陈列馆和山体开放,以及战壕/弹坑/诗词碑的年代说明;不进入关闭区域,不触碰或布置文物本体。', 'Script reviewer, sources for battle positions, relationship between set and heritage, live access to the hall and mountains, and dating of trenches, shell holes, or poem panel; no closed-area entry or staging on heritage fabric.', language) },
+ { title: pickText('火焰、烟雾、强声与道具', 'Flame, Smoke, Sound & Props', language), copy: pickText('特效物料和距离、点火/停机负责人、风向、烟雾成分、噪声、消防器材、观众隔离、仿真枪械管理、服装阻燃/清洁、急停口令、急救与保险逐项留档。', 'Document effect materials and distance, ignition and shutdown lead, wind, smoke composition, noise, fire equipment, audience separation, replica control, costume flame resistance and cleaning, stop commands, first aid, and insurance.', language) },
+ { title: pickText('山地天气、体能与撤离', 'Mountain Weather, Fitness & Exit', language), copy: pickText('高温、暴雨、雷电、大雾、湿滑、落石和森林火险停运标准,真实爬升/路面、前后领队、补水休息、通信、退出接驳、医疗转运、儿童与长者替代,以及全程英文支持。', 'Closure thresholds for heat, rain, lightning, fog, slick ground, rockfall, and forest fire; real ascent and surface, lead and sweep, water and rests, communication, exit transfer, medical transport, child and older-guest alternatives, and full English support.', language) },
+ ];
+ const routes = [
+ { number: '01', title: pickText('互动演出半日', 'Participatory Show Half-Day', language), copy: pickText('只在当日互动票、场次、特效与客人筛查成立时参加;表演前后安排换装、听力/呼吸保护说明、清洁和恢复,不再叠加长距离徒步。', 'Join only when the live interactive ticket, session, effects, and guest screening pass. Allow changing, hearing and respiratory briefing, cleaning, and recovery, without adding a long hike.', language), href: '/contact/' },
+ { number: '02', title: pickText('遗址与诗词半日', 'Battle Site & Poetry Half-Day', language), copy: pickText('陈列馆、公开战斗遗址、关口与诗词展示组成轻量历史线;避开模拟战斗,适合关注史实、摄影或不接受烟火特效的客人。', 'Use the exhibition hall, accessible battle sites, pass, and poetry display as a gentler history route, avoiding simulated combat for evidence-focused, photography, or effects-sensitive guests.', language), href: '/safaris/classic-guizhou/' },
+ { number: '03', title: pickText('二期山道移动剧场', 'Phase Two Moving Mountain Theatre', language), copy: pickText('路线测绘、历史点位、演员调度、英文脚本、特效分区、公共游客影响和撤离演练全部通过后,才把客户的 4–5 小时构想做成私家产品。', 'Turn the brief’s 4–5-hour concept into a private product only after route mapping, historical positions, actor logistics, English script, effects zoning, public-visitor impact, and evacuation drill all pass.', language), href: '/contact/' },
+ ];
+
+ return (
+
+
+
+
+
+
+
Live Performance / Battlefield Heritage / Route Review
+
{pickText('娄山关战役・山道沉浸行军', 'Loushan Pass: Battle & Immersive March', language)}
+
{pickText('现有游客参与演出已经成立;沿真实战斗遗址连续行军 4–5 小时的移动剧场仍待共创。先选“看遗址、看演出或参与演出”,再谈山道剧本。', 'A participatory battle show now exists; a 4–5-hour moving theatre across verified battlefield terrain does not yet. First choose heritage visit, show, or participation—then consider a scripted march.', language)}
+
{pickText('比较三种体验', 'Compare the three formats', language)}
+
+
+
+
+ {pickText('2026 年 8 月核验结论', 'Review as of August 2026', language)}{pickText('“实景演出”已经有,“山道移动剧场”还没有被证明。', 'The live show exists; the moving mountain theatre is not yet evidenced.', language)}
{pickText('娄山关战斗遗址和《娄山关大捷》实景演出均有长期公开记录;2026 年,现有演出升级出“跟着团长攻打娄山关”游客参与项目。客户原文进一步提出沿古驿道上行、在每个历史地标插入演员场景、登顶读诗、下山复盘,并承诺 4–5 小时、全员服装道具、完整英文剧本和专业英文历史向导。后半部分目前没有对应的运营、路线或英文接待证据,所以只作为二期产品蓝图。', 'Both the Loushan Pass battle heritage and live show have a long public record; in 2026, the show added the participatory “Follow the Commander” experience. The brief goes further: climb an old road, stage actors at each historical landmark, read poetry at the summit, and debrief on descent, with a 4–5-hour duration, costume and props for all, a full English script, and a specialist English history host. Those later promises lack matching operating, route, or English-delivery evidence and remain a phase-two blueprint.', language)}
+
+ - {pickText('核心史实', 'Historical Core', language)}
- {pickText('1935-02-25 至 26 娄山关战斗', 'Battle of Loushan Pass, 25–26 Feb 1935', language)}
+ - {pickText('现有演出', 'Live Show', language)}
- {pickText('《娄山关大捷》实景演出', 'Loushan Pass Victory live performance', language)}
+ - {pickText('2026 新玩法', '2026 Addition', language)}
- {pickText('“跟着团长攻打娄山关”游客参与版', 'Participatory “Follow the Commander” format', language)}
+ - {pickText('客户构想', 'Brief Concept', language)}
- {pickText('4–5 小时山道剧情徒步 / 待共创', '4–5-hour narrative mountain hike / under development', language)}
+ - {pickText('体力口径', 'Physical Load', language)}
- {pickText('距离、爬升、台阶和退出点尚待实测', 'Distance, gain, steps, and exits still require measurement', language)}
+ - {pickText('英文与私家团', 'English & Private Groups', language)}
- {pickText('客户需求成立;供应端能力尚待书面确认', 'Valid brief requirement; supplier capability unconfirmed', language)}
+
+
+
+
{pickText('客户图片明确标注“攻打娄山关” · 可支持实景演出氛围,具体日期、场次、制作方、人物与商业使用授权仍待归档', 'Client image explicitly labelled “Attack Loushan Pass” · supports the live-show atmosphere; date, session, producer, participant consent, and commercial rights still require records', language)}
+
+
+
+ })
02 / Verification Flow
{pickText('先把演艺景区和真实战斗遗址画在同一张地图上。', 'Map the performance area and historic battlefield before combining them.', language)}
{flow.map((item, index) => - {String(index + 1).padStart(2, '0')}
)}
+ 03 / History, Effects & Mountain Gates{pickText('火焰、烟雾和山路叠加时,不能只写“中等强度”。', 'Flame, smoke, and mountain terrain demand more than a “moderate” label.', language)}
{pickText('当前图片中的特效规模明显,客户又提出连续上山;产品上线必须同时通过演艺安全、游客筛查、山地天气、遗址保护和英文知情说明。', 'The supplied image shows substantial effects, while the brief adds a sustained climb. Launch requires performance safety, guest screening, mountain weather, heritage protection, and informed English communication to pass together.', language)}
{gates.map((gate, index) =>
{String(index + 1).padStart(2, '0')}{gate.title}
{gate.copy}
)}
{pickText('当前可以公开', 'Safe to publish now', language)}- {pickText('娄山关战斗遗址、1935 年 2 月主要战斗与遵义会议后首次大捷的历史定位', 'Loushan Pass battle heritage, the February 1935 action, and its position as the first major victory after the Zunyi Conference', language)}
- {pickText('《娄山关大捷》实景演出长期存在,以及 2026 年新增游客参与项目', 'The established live show and its 2026 participatory addition', language)}
- {pickText('客户提供的一张“攻打娄山关”演出图,但图片权利与拍摄信息仍须归档', 'One client-supplied performance image labelled “Attack Loushan Pass,” subject to image-rights records', language)}
{pickText('尚不能直接承诺', 'Not an automatic promise', language)}- {pickText('沿原始古驿道连续 4–5 小时、每个历史地标都有演员和旁白、登顶剧情高潮', 'A continuous 4–5-hour original post-road hike, actors and narration at every landmark, or a summit climax', language)}
- {pickText('全员服装道具、完整英文剧本、专业英文历史向导、景区门票和演员协调全部包含', 'Costume and props for all, full English script, specialist English history host, tickets, and actor coordination all included', language)}
- {pickText('客户所称“铺装中等山道”已完成测绘,或大型火焰/烟雾/仿真枪械对所有客人安全', 'A surveyed “moderate paved mountain trail,” or large flame, smoke, and replicas being safe for every guest', language)}
{pickText('公开信息参考:人民日报海外版 2021-07-23 娄山关景区报道;人民网 2026-07-22 红色文旅报道;贵州广播电视台 2026 年“五一”活动与暑期项目报道;解放军报/国防部娄山关战斗史资料;中共贵州省委党史研究室相关史料。公开报道中的历史票价与场次不作为本官网现行报价,全部以出行日期的景区和运营方书面信息为准。', 'Public references: People’s Daily Overseas Edition on Loushan Pass, 23 July 2021; People.cn on red-culture tourism, 22 July 2026; Guizhou Broadcasting reports on 2026 May Day and summer products; PLA Daily / Ministry of National Defense history of the battle; and Guizhou Party History Institute material. Historical prices or sessions in reporting are not current quotes and must be replaced by written scenic-area and operator information for the travel date.', language)}
+ 04 / Route Pairing
{pickText('先选择参与强度,再决定是否走山。', 'Choose participation intensity before adding the mountain.', language)}
+
+
+ );
+}
+
+function KarstGlampingDetailPage() {
+ const { language } = useTravelSite();
+ const formats = [
+ {
+ number: '01',
+ label: pickText('优先推荐', 'Preferred', language),
+ title: pickText('具名经营型营地', 'Named Serviced Camp', language),
+ copy: pickText(
+ '选择已有经营主体、固定营位或帐篷、床品、卫浴、饮水、电力、夜间值守和车辆/步行入口的营地。正式方案写明营地名称、房型、真实图片、容量、价格、服务清单、取消规则和天气备用。',
+ 'Choose a named operator with fixed pitches or tents, bedding, bathrooms, potable water, power, night support, and clear vehicle or walking access. The final plan states the camp, room type, real images, capacity, price, inclusions, cancellation, and weather fallback.',
+ language,
+ ),
+ status: pickText('最接近“野趣与舒适并存”,也最容易核验消防、食品和住宿责任', 'Closest to wild comfort while keeping fire, food, and accommodation duties verifiable', language),
+ },
+ {
+ number: '02',
+ label: pickText('稳定备选', 'Reliable Fallback', language),
+ title: pickText('山地景观住宿 + 夜间观星', 'Mountain Stay + Stargazing', language),
+ copy: pickText(
+ '当风雨、雷电、低温或场地资料不足时,以有固定建筑、卫浴和室内空间的山地住宿承接度假感,再在安全平台安排短时夜观。客户本组3张图片更接近这一类型,而不是帐篷营地。',
+ 'When wind, rain, lightning, cold, or site evidence is weak, use a mountain stay with a fixed building, bathroom, and indoor shelter, then add a short sky watch from a safe platform. The three images supplied for this section resemble this format rather than a tent camp.',
+ language,
+ ),
+ status: pickText('不强求帐篷形式,优先保证睡眠、卫浴、避雨和随时回到室内', 'No forced tent aesthetic; prioritise sleep, bathrooms, rain shelter, and immediate indoor return', language),
+ },
+ {
+ number: '03',
+ label: pickText('专项候选', 'Special Setup Candidate', language),
+ title: pickText('私家临时营地搭建', 'Private Pop-Up Camp', language),
+ copy: pickText(
+ '只有用地/景区/社区授权、生态承载、防火、雷电避险、抗风营帐、厕所与污水、饮水餐食、照明通信、夜间安保和撤离路线全部书面明确时才搭建。天坑底部、峡谷河畔和保护地不因“秘境”而降低门槛。',
+ 'Set up only when land, scenic-area, or community authority; ecological capacity; fire and lightning shelter; wind-rated tents; toilets and wastewater; water and food; lighting and communication; night security; and evacuation are all documented. A sinkhole, riverside canyon, or protected site gets no lower bar for being “hidden.”',
+ language,
+ ),
+ status: pickText('不具名点位、不清楚土地性质或没有恶劣天气固定避难空间时,不执行', 'No operation with an unnamed site, unclear land status, or no fixed severe-weather shelter', language),
+ },
+ ];
+ const flow = [
+ { title: pickText('先定义舒适度与客人条件', 'Define Comfort & Guests', language), copy: pickText('确认日期、人数、儿童/长辈、行动能力、睡眠与床型、独立卫浴、饮食过敏、夜间活动、用电和对帐篷的真实接受度。', 'Confirm dates, group, children or elders, mobility, sleep and bed needs, private bathroom, diet and allergies, night activity, power, and real tolerance for tent living.', language) },
+ { title: pickText('选择具名营地或固定住宿', 'Choose a Named Camp or Stay', language), copy: pickText('先取得经营主体、具体位置、房型/营位、设施、真实现场图、容量、价格和当季开放状态;图片不能替代场地资料。', 'Obtain the operator, exact site, room or pitch, facilities, real on-site images, capacity, price, and seasonal opening before relying on any mood image.', language) },
+ { title: pickText('核对场地、火源与生活保障', 'Check Site, Fire & Living Support', language), copy: pickText('确认用地和可进入区域、森林/景区规则、明火与烹饪、电力燃气、饮用水、食物、厕所、洗浴、垃圾污水、虫害和夜间值守。', 'Confirm land and access, forest or scenic rules, flame and cooking, power or gas, potable water, food, toilets, showers, waste and wastewater, insects, and night staffing.', language) },
+ { title: pickText('出发前两次天气决策', 'Two Weather Decisions', language), copy: pickText('出发前48小时复核趋势,当天下午按雷电、风、雨、温度、地表积水、山洪和能见度做最终 Go / No-Go;不适合时切换固定住宿。', 'Review the trend 48 hours out, then make the final Go / No-Go that afternoon using lightning, wind, rain, temperature, surface water, flash flood, and visibility; switch to fixed lodging when unsuitable.', language) },
+ { title: pickText('入住、夜观与无痕离开', 'Stay, Sky Watch & Leave No Trace', language), copy: pickText('先做逃生、照明、通信、儿童和野生动物说明;夜观只在安全区域短时进行。次日清点人员和装备,分类带走垃圾并核对场地恢复。', 'Brief escape, lighting, communication, children, and wildlife first; sky watching stays short and within a safe area. Next morning count people and equipment, remove sorted waste, and confirm site restoration.', language) },
+ ];
+ const gates = [
+ { title: pickText('场地、经营与住宿责任', 'Site, Operation & Accommodation', language), copy: pickText('具名主体、用地/景区/社区授权、经营与收费、真实营位/房型、容量、住宿登记、责任联系人和取消退款规则。', 'Named entity, land/scenic/community authority, operation and pricing, real pitch or room, capacity, guest registration, responsible contact, and cancellation or refund rules.', language) },
+ { title: pickText('天气、防雷与撤离', 'Weather, Lightning & Evacuation', language), copy: pickText('雷电预警接收、抗风雨阈值、山洪/落石/积水、固定避难空间、照明通信、夜间路线、车辆接回和医疗转运。', 'Lightning warnings, wind and rain limits, flash flood, rockfall and ponding, fixed shelter, lighting and communication, night route, vehicle recovery, and medical transfer.', language) },
+ { title: pickText('防火、电力与餐卫', 'Fire, Power, Food & Sanitation', language), copy: pickText('森林防火期/禁火令、明火和篝火许可、燃气与电力、灭火器材、饮用水、厨房/食品、过敏原、厕所、洗浴、垃圾和污水。', 'Forest fire season or bans, flame and campfire permission, gas and power, extinguishers, potable water, kitchen and food, allergens, toilets, showers, waste, and wastewater.', language) },
+ { title: pickText('夜间值守、儿童与环境', 'Night Staff, Children & Environment', language), copy: pickText('24小时联系人和巡查、儿童临崖/临水/火源边界、野生动物与虫害、噪声照明控制、生态承载和离场恢复记录。', '24-hour contact and patrol, child boundaries near edges, water, or fire, wildlife and insects, noise and light control, ecological capacity, and restoration record.', language) },
+ ];
+ const routes = [
+ { number: '01', title: pickText('经典全景线', 'Classic Panorama Route', language), copy: pickText('使用一晚具名经营营地或山地景观住宿,车辆可达、独立卫浴和天气备选优先。', 'Use one night at a named serviced camp or mountain-view stay, prioritising vehicle access, a private bathroom, and weather fallback.', language), href: '/safaris/classic-guizhou/' },
+ { number: '02', title: pickText('喀斯特户外探险线', 'Karst Outdoor Adventure', language), copy: pickText('放在轻至中等活动日后,不与高风险水上、洞穴或绳索项目叠加;第二天保留较晚出发。', 'Place after a light or moderate activity day, not beside high-risk water, cave, or rope work, with a later departure next morning.', language), href: '/safaris/outdoor-coffee/' },
+ { number: '03', title: pickText('均衡探索线', 'Balanced Discovery Route', language), copy: pickText('与村寨、田园步行或山野咖啡组合;天气不佳时直接切换固定建筑住宿和室内晚餐。', 'Pair with a village, country walk, or mountain coffee; poor weather switches directly to fixed lodging and an indoor dinner.', language), href: '/safaris/culture-outdoor-mix/' },
+ ];
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
{pickText('当前定义', 'Current Definition', language)}
+
{pickText('“野奢”不是一顶漂亮帐篷,而是一整夜有人负责。', 'Glamping is not a beautiful tent—it is a whole night with clear responsibility.', language)}
+
{pickText('客户文档提出峰林田园、峡谷河畔和天坑秘境三类露营,并承诺床品、卫浴、餐食、搭撤与24小时值守。本组3张图片实际展示的是山地景观酒店和观景平台,没有帐篷、夜景或营地设施。第一版保留这些图片作为舒适度与景观参考,不把它们认定为露营地,也不在具名场地资料补齐前开放直接预订。', 'The brief proposes peak-country, riverside-canyon, and sinkhole camping with bedding, bathrooms, food, setup, and 24-hour staffing. The three supplied images actually show a mountain-view lodge and viewing decks, with no tents, night scene, or camp facilities. This first version treats them as comfort and view references—not proof of a campground—and keeps direct booking closed until a named site is documented.', language)}
+
+
+ - {pickText('当前状态', 'Current Status', language)}
- {pickText('候选体验;具名营地与运营资料补齐后开放', 'Candidate experience; opens after named camp and operating records', language)}
+ - {pickText('场景候选', 'Setting Candidates', language)}
- {pickText('峰林田园 / 合规山地营地 / 固定景观住宿', 'Peak-forest countryside / compliant mountain camp / fixed view lodging', language)}
+ - {pickText('建议时长', 'Suggested Time', language)}
- {pickText('1 晚为主;连续住宿需复核洗浴、餐食与天气', 'Primarily one night; longer stays need bathroom, food, and weather review', language)}
+ - {pickText('适合', 'Best For', language)}
- {pickText('情侣、亲子、轻户外与重视睡眠舒适度的自然爱好者', 'Couples, families, gentle outdoor travellers, and nature lovers who value sleep comfort', language)}
+ - {pickText('星空说明', 'Sky Note', language)}
- {pickText('银河、无云、低光污染和日出均受日期与天气影响,不保证', 'Milky Way, clear sky, low light pollution, and sunrise depend on date and weather', language)}
+ - {pickText('默认备选', 'Default Fallback', language)}
- {pickText('固定山地住宿 / 室内晚餐 / 安全平台短时夜观', 'Fixed mountain stay / indoor dinner / short sky watch from a safe deck', language)}
+
+
+
+
+
+
+
+
+
+
+
02 / Operating Flow
{pickText('星空可以落空,睡眠、卫浴和撤离不能。', 'Stars may not appear. Sleep, sanitation, and exit cannot fail.', language)}
+
{flow.map((item, index) => - {String(index + 1).padStart(2, '0')}
)}
+
+
+
+
+
+
03 / Launch Gates{pickText('没有固定避难空间和夜间责任人,就不在山里过夜。', 'No fixed shelter or accountable night lead means no mountain overnight.', language)}
{pickText('“远离光污染、篝火闲谈、银河星空、清晨鸟鸣、24小时值守和卫浴保障”都必须变成具体场地、日期、设施与人员证据。', '“No light pollution, campfire talk, Milky Way, birds at dawn, 24-hour staff, and bathroom support” must become site-, date-, facility-, and person-specific evidence.', language)}
+
{gates.map((gate, index) =>
{String(index + 1).padStart(2, '0')}{gate.title}
{gate.copy}
)}
+
+
{pickText('可以写入正式方案', 'What the final plan can promise', language)}- {pickText('具名营地/住宿、经营主体、实际房型/营位、现场图、容量与价格', 'Named camp or stay, operator, real room or pitch, on-site images, capacity, and price', language)}
- {pickText('床型床品、独立/公共卫浴、饮水餐食、电力、值守、停车与步行距离', 'Bed and linen, private or shared bathroom, water and food, power, staffing, parking, and walk', language)}
- {pickText('天气阈值、固定避难空间、取消/替代住宿、接驳与撤离方式', 'Weather limits, fixed shelter, cancellation or alternative stay, transfer, and evacuation', language)}
+
{pickText('必须按场地和日期复核', 'Claims requiring site-and-date proof', language)}- {pickText('图片是否为实际营地,以及峰林、天坑、峡谷河畔的具体地理归属', 'Whether images show the actual camp and the exact peak, sinkhole, or riverside location', language)}
- {pickText('银河、无云日出、远离光污染、无人打扰、鸟鸣唤醒或“独享秘境”', 'Milky Way, cloudless sunrise, no light pollution, solitude, birds at dawn, or an “exclusive hidden site”', language)}
- {pickText('篝火/野炊可用、24小时值守、卫浴保障、私家搭撤与天坑/河边过夜', 'Campfire or cooking, 24-hour staffing, bathroom guarantee, private setup, or sinkhole/riverside overnight', language)}
+
+
{pickText('执行参考:贵州省森林防火条例、贵州省农村消防管理规定及中国气象局《旅游景区雷电防护安全规范》。森林防火期、禁火令、雷电预警和实际开放状态仍按属地与日期复核。', 'Operating references: Guizhou Forest Fire Prevention Regulations, Guizhou Rural Fire Management Rules, and the China Meteorological Administration tourism lightning-safety standard. Fire season, bans, lightning alerts, and opening status remain local and date-specific.', language)}
+
+
+
+
+ 04 / Route Pairing
{pickText('把一晚山野放进路线,不把整条路线押给天气。', 'Put one mountain night into the route—not the whole route at the mercy of weather.', language)}
+
+
+
+
+
+ );
+}
+
+function MiaoCraftDetailPage() {
+ const { language } = useTravelSite();
+ const formats = [
+ {
+ number: '01',
+ label: pickText('蜡染主题', 'Batik Focus', language),
+ title: pickText('纹样理解 + 点蜡或染色', 'Motif Reading + Wax Drawing or Dyeing', language),
+ copy: pickText(
+ '由具名工坊先讲清当地纹样、工具和工序,再根据时间选择点蜡、染色、脱蜡或成品讲解中的可开放环节。短课以理解和完成小样为主,不承诺从白布到复杂成品的全流程。',
+ 'A named studio first explains local motifs, tools, and process, then opens whichever stage fits the day—wax drawing, dyeing, wax removal, or finished-work interpretation. A short session focuses on understanding and a small sample, not a full complex piece from blank cloth.',
+ language,
+ ),
+ status: pickText('建议 2–3 小时;热蜡、染料、通风、皮肤敏感和作品干燥单独确认', 'Allow 2–3 hours; confirm hot wax, dye, ventilation, skin sensitivity, and drying separately', language),
+ },
+ {
+ number: '02',
+ label: pickText('苗绣主题', 'Embroidery Focus', language),
+ title: pickText('纹样故事 + 一种基础针法', 'Motif Story + One Foundational Stitch', language),
+ copy: pickText(
+ '不把苗绣简化成通用刺绣课。由具名老师选择一种适合初学者的纹样或针法,说明当地服饰与图案语境,再完成可在课程时间内收尾的小型练习。',
+ 'This is not a generic embroidery class. A named teacher selects one beginner-suitable motif or stitch, explains its local dress and visual context, and guides a small exercise that can honestly finish within the session.',
+ language,
+ ),
+ status: pickText('建议 1.5–2.5 小时;针具、视力/精细动作、儿童年龄和成品规格按老师确认', 'Allow 1.5–2.5 hours; needles, eyesight and fine-motor needs, child age, and piece size are teacher-confirmed', language),
+ },
+ {
+ number: '03',
+ label: pickText('双主题半日', 'Combined Half-Day', language),
+ title: pickText('先读懂一块布,再选择动手重点', 'Read the Cloth First, Then Choose the Hands-On Focus', language),
+ copy: pickText(
+ '只有同一具名工坊能够真实提供两项内容、老师和材料时,才安排蜡染与苗绣半日组合。文化讲解可覆盖两项,动手部分仍只选择一个重点,避免课程变成两次匆忙打卡。',
+ 'Combine batik and embroidery only when one named studio genuinely has both teachers and materials. Interpretation may cover both, while the hands-on portion still chooses one focus so the half-day does not become two rushed check-ins.',
+ language,
+ ),
+ status: pickText('建议 4–5 小时;不默认一位老师同时代表所有地区、支系和技艺', 'Allow 4–5 hours; one teacher does not automatically represent every place, community, or technique', language),
+ },
+ ];
+ const flow = [
+ { title: pickText('锁定具名工坊与老师', 'Name the Studio and Teacher', language), copy: pickText('确认地址、授课人真实身份与技艺范围、课程是否日常开放、容量、费用、取消和当天接待窗口。', 'Confirm address, teacher identity and actual craft scope, whether the lesson operates normally, capacity, fee, cancellation, and the date-specific hosting window.', language) },
+ { title: pickText('选择一个真实课程目标', 'Choose One Honest Learning Goal', language), copy: pickText('在蜡染小样、苗绣基础针法或双主题文化讲解中选定重点;根据年龄、精细动作、皮肤敏感和可用时间调整。', 'Choose a small batik sample, one embroidery stitch, or combined cultural interpretation; adapt around age, fine-motor ability, skin sensitivity, and available time.', language) },
+ { title: pickText('核对材料、工具与语言', 'Check Materials, Tools & Language', language), copy: pickText('写明使用蜂蜡或其他蜡材、天然蓝靛或其他染料、热源、针具、围裙/手套、通风与英文讲解由谁完成。', 'State the wax material, natural indigo or other dye, heat source, needles, apron or gloves, ventilation, and exactly who provides English interpretation.', language) },
+ { title: pickText('现场再确认同意与安全', 'Reconfirm Consent & Safety On Site', language), copy: pickText('开课前说明热蜡、染料沾染、针具和儿童操作边界;人物、家庭空间、作品与制作过程拍摄均再次征得同意。', 'Before starting, explain hot wax, dye staining, needles, and child boundaries; reconfirm consent for portraits, homes, works, and the making process.', language) },
+ { title: pickText('完成、干燥或后寄', 'Finish, Dry or Ship Later', language), copy: pickText('离开前说明作品完成度、是否需要脱蜡/清洗/晾干、当天带走或后寄、包装、邮费和破损责任。', 'Before departure, state the finish level, any wax removal, washing, or drying needed, same-day collection or later shipping, packaging, postage, and damage responsibility.', language) },
+ ];
+ const gates = [
+ { title: pickText('身份与课程真实性', 'Identity & Lesson Reality', language), copy: pickText('具名工坊、老师姓名与实际技艺、传承人称号的官方名录依据、课程内容、日常接待能力、容量、费用和取消。', 'Named studio, teacher and actual craft, official-list basis for any heritage-bearer title, lesson content, normal hosting ability, capacity, fee, and cancellation.', language) },
+ { title: pickText('材料与作品边界', 'Material & Piece Boundary', language), copy: pickText('蜡材、染料是否为天然蓝靛、布料与线材、可操作工序、成品尺寸、干燥/脱蜡/清洗、当天带走或后寄。', 'Wax, whether the dye is natural indigo, cloth and thread, available process, piece size, drying, wax removal, washing, same-day collection, or shipping.', language) },
+ { title: pickText('热蜡、针具与儿童', 'Hot Wax, Needles & Children', language), copy: pickText('热源稳定、防烫桌面、通风、染料接触、围裙/手套、针具回收、洗手与急救;儿童年龄和成人陪同由老师确认。', 'Stable heat, burn-safe surface, ventilation, dye contact, aprons or gloves, needle control, handwashing, and first aid; teacher confirms child age and adult supervision.', language) },
+ { title: pickText('英文、拍摄与结算', 'English, Photography & Payment', language), copy: pickText('英文由老师、译员或司导谁来完成;哪些人物/空间可拍、图片可否公开;工坊费、老师费、材料、翻译和寄送分别结算。', 'Who provides English—the teacher, interpreter, or guide; who and what may be photographed and published; separate settlement for studio, teacher, materials, interpretation, and shipping.', language) },
+ ];
+ const routes = [
+ { number: '01', title: pickText('经典全景线', 'Classic Panorama Route', language), copy: pickText('把一项 2–3 小时具名工坊放在安顺、丹寨或黔东南转场中,避免为了手作单独往返。', 'Place one named 2–3 hour studio inside an Anshun, Danzhai, or Qiandongnan transfer rather than making a separate return journey.', language), href: '/safaris/classic-guizhou/' },
+ { number: '02', title: pickText('亲子人文慢游', 'Family Heritage Slow Travel', language), copy: pickText('优先选择低温蜡材或苗绣入门,把儿童年龄、成人陪同、工具分配和作品预期提前写清。', 'Prefer lower-risk wax handling or introductory embroidery, with child age, adult supervision, tool allocation, and piece expectations written in advance.', language), href: '/safaris/family-heritage/' },
+ { number: '03', title: pickText('均衡探索线', 'Balanced Discovery Route', language), copy: pickText('与村寨慢住或梯田步行组成完整人文日,但工坊本身保留足够时间,不再叠加第二项重体验。', 'Build a full culture day with a village stay or terrace walk while preserving real studio time and avoiding a second major activity.', language), href: '/safaris/culture-outdoor-mix/' },
+ ];
+
+ return (
+
+
+
+
+
+
+
+
Human Culture / 01
+
{pickText('苗族蜡染・苗绣', 'Miao Batik & Embroidery', language)}
+
{pickText('先认识纹样、材料和时间,再在具名老师带领下完成一段真实、不过度承诺的手作。', 'Begin with motif, material, and time—then make one honest piece with a named teacher and no inflated promises.', language)}
+
{pickText('查看三种体验方式', 'See Three Experience Formats', language)}
+
+
+
+
+
+
+
+
+
{pickText('体验定义', 'Experience Definition', language)}
+
{pickText('不是把蓝色带回家,而是先理解一块布为什么需要这么多时间。', 'The point is not simply to take blue home, but to understand why one cloth asks for so much time.', language)}
+
{pickText('客户文档提出由“第三代传承人”讲授、使用天然蓝靛、全程英文并把成品带走。第一版保留这些体验期待,但将它们全部转为具名工坊的确认项:传承人身份要有公开名录依据,天然蓝靛要核对实际染缸,英文要说明具体人员,作品则要写清完成、干燥或后寄方式。蜡染与苗绣是两门不同的技艺,不默认一次短课全部完成。', 'The brief asks for third-generation artisans, natural indigo, full English interpretation, and a take-home piece. This first version treats every one as a named-studio confirmation: heritage status needs an official-list basis, natural indigo needs the actual dye vat, English needs a named person, and the piece needs a clear finish, drying, or shipping plan. Batik and embroidery are distinct crafts and are not both completed by default in one short session.', language)}
+
+
+ - {pickText('地区候选', 'Area Candidates', language)}
- {pickText('丹寨 / 安顺 / 黔东南;最终以具名工坊为准', 'Danzhai / Anshun / Qiandongnan; final location follows the named studio', language)}
+ - {pickText('建议时长', 'Suggested Time', language)}
- {pickText('单项 1.5–3 小时;双主题半日 4–5 小时', 'One focus 1.5–3 hours; combined half-day 4–5 hours', language)}
+ - {pickText('体验重点', 'Core Focus', language)}
- {pickText('纹样语境 + 一项可真实完成的动手环节', 'Motif context plus one honestly achievable hands-on stage', language)}
+ - {pickText('语言', 'Language', language)}
- {pickText('老师直讲、专业译员或英文司导三选一并具名', 'Name one: teacher-led English, interpreter, or English-speaking guide', language)}
+ - {pickText('材料', 'Materials', language)}
- {pickText('蜡材、蓝靛/染料、布料与线材逐项确认', 'Confirm wax, indigo or other dye, cloth, and thread item by item', language)}
+ - {pickText('作品', 'Take-Home Piece', language)}
- {pickText('当天带走、完成后寄送或仅做练习,按课程确认', 'Same-day collection, later shipping, or practice only, confirmed by lesson', language)}
+
+
+
+
+
{pickText('客户提供实拍 · 人物身份与公开使用授权需归档', 'Client-supplied photography · identity and publication permission to be recorded', language)}
+
+
+
+
+
+
+
+
+
+
+
02 / Experience Flow
{pickText('从“谁来教”开始,到“作品怎么离开工坊”结束。', 'Start with who teaches and finish with how the piece leaves the studio.', language)}
+
{flow.map((item, index) => - {String(index + 1).padStart(2, '0')}
)}
+
+
+
+
+
+
03 / Confirmation Gates{pickText('不能确认老师、材料和作品完成方式,就不能承诺“传承人课、天然蓝靛、全程英文、成品带走”。', 'If teacher, material, and finish are not confirmed, we cannot promise a master artisan, natural indigo, full English, or a take-home piece.', language)}
{pickText('公开资料可以证明苗族蜡染与苗绣的非遗价值,但不能替代某一家工坊当天真实提供的课程和接待条件。', 'Public records establish the heritage value of Miao batik and embroidery, but cannot replace the real lesson and hosting conditions of one studio on one date.', language)}
+
{gates.map((gate, index) =>
{String(index + 1).padStart(2, '0')}{gate.title}
{gate.copy}
)}
+
+
{pickText('正式方案可以承诺', 'What a final plan can promise', language)}- {pickText('具名工坊、具名老师、实际技艺、课程目标、时长、容量、费用与取消规则', 'Named studio and teacher, actual craft, learning goal, duration, capacity, fee, and cancellation', language)}
- {pickText('具体材料、工具、安全措施、英文人员与允许拍摄/公开的范围', 'Exact materials, tools, safety measures, English support, and photography or publication scope', language)}
- {pickText('具体作品规格、完成度、当天带走或后寄、包装与寄送费用', 'Exact piece, finish level, same-day collection or shipping, packaging, and postage', language)}
+
{pickText('必须按工坊与日期复核', 'Claims requiring studio-and-date proof', language)}- {pickText('授课人是“第三代传承人”、国家/省/市县级代表性传承人或可代表所有苗族支系', 'That the teacher is a “third-generation artisan,” a listed national/provincial/local bearer, or represents every Miao community', language)}
- {pickText('实际使用天然蓝靛、客人参与完整染制流程、全程由老师本人英文讲解', 'That natural indigo is used, guests complete the entire dye process, or the teacher personally interprets in English throughout', language)}
- {pickText('所有年龄都可操作热蜡和针具、所有作品可在课程结束时完整带走', 'That every age may handle hot wax and needles or every piece leaves fully finished at lesson end', language)}
+
+
{pickText('公开依据参考:丹寨苗族蜡染于 2006 年列入第一批国家级非物质文化遗产名录,苗绣同年进入第一批国家级名录;实际工坊、授课人身份、染料配方、课程和开放状态仍按日期书面确认。', 'Public reference: Danzhai Miao batik entered the first national intangible-cultural-heritage list in 2006, as did Miao embroidery. The actual studio, teacher status, dye recipe, lesson, and opening remain date-specific and written into confirmation.', language)}
+
+
+
+
+ 04 / Route Pairing
{pickText('把工坊放在顺路的位置,也给手上的动作留够时间。', 'Place the studio where the route makes sense—and leave enough time for the hands.', language)}
+
+
+
+
+
+ );
+}
+
+function ShuiHorsetailEmbroideryDetailPage() {
+ const { language } = useTravelSite();
+ const formats = [
+ {
+ number: '01',
+ label: pickText('工艺演示', 'Process Demonstration', language),
+ title: pickText('先看懂马尾芯与丝线结构', 'Read the Horsehair-and-Silk Structure First', language),
+ copy: pickText(
+ '由具名工坊或老师展示已准备好的马尾芯、丝线缠裹、盘线固定与填绣关系,并结合真实绣片解释工序。演示以看懂材料和时间为目标,不默认动针,也不承诺带走作品。',
+ 'A named studio or teacher uses prepared horsehair cores, silk wrapping, couching, and filling to explain the structure through real samples. The goal is process literacy—not automatic needlework or a take-home piece.',
+ language,
+ ),
+ status: pickText('建议 45–75 分钟;适合时间有限、儿童或先了解再决定是否动手的客人', 'Allow 45–75 minutes; suited to limited time, families, or guests deciding before hands-on work', language),
+ },
+ {
+ number: '02',
+ label: pickText('入门短课', 'Intro Workshop', language),
+ title: pickText('马尾芯缠线 + 一段基础小样', 'Wrap the Core + Make One Basic Sample', language),
+ copy: pickText(
+ '老师预先准备适合初学者的材料和部分工序,客人练习丝线缠裹马尾芯,并在老师选择的简单纹样中完成一个可控环节。课程不从采集或处理马尾开始,也不把复杂背带、服饰片包装成当日成品。',
+ 'The teacher prepares beginner-suitable materials and selected stages. Guests practise wrapping silk around a horsehair core and complete one controlled part of a simple motif. The lesson does not begin with collecting or processing horsehair, nor promise a complex carrier or garment panel in one day.',
+ language,
+ ),
+ status: pickText('建议 2–3 小时;针具、精细动作、儿童年龄与小样完成度按老师确认', 'Allow 2–3 hours; needles, fine-motor needs, child age, and sample finish are teacher-confirmed', language),
+ },
+ {
+ number: '03',
+ label: pickText('深度工坊', 'Deep Studio Session', language),
+ title: pickText('半日或分段学习,不追赶复杂成品', 'Half-Day or Multi-Session Learning Without Rushing', language),
+ copy: pickText(
+ '只在具名老师、材料、容量与回访条件都成立时安排半日或多次学习,围绕制线、盘绣、填心等一至两个阶段深入练习。可完成的只写明为基础样片;复杂作品由老师收尾或后寄时,提前约定范围、周期与费用。',
+ 'Offer a half-day or repeat sessions only when a named teacher, materials, capacity, and return plan are real. Practise one or two stages such as thread preparation, couching, or filling. Promise only a basic sample; if the teacher finishes or ships a larger piece later, scope, timing, and fee are agreed first.',
+ language,
+ ),
+ status: pickText('建议 4–5 小时或多次课程;不把长期技艺压缩成“一课学会”', 'Allow 4–5 hours or repeat sessions; a long-practised craft is never sold as “mastered in one class”', language),
+ },
+ ];
+ const flow = [
+ { title: pickText('锁定三都具名工坊与老师', 'Name the Sandu Studio & Teacher', language), copy: pickText('确认地址、授课人、实际技艺与课程;使用“代表性传承人”等称号时,核对官方名录、项目层级与姓名对应关系。', 'Confirm address, teacher, actual craft, and lesson. Any “representative heritage bearer” title must match the official list, project level, and person.', language) },
+ { title: pickText('选择演示、小样或深度学习', 'Choose Demonstration, Sample or Deep Learning', language), copy: pickText('根据时间、年龄、精细动作与作品期待,只确定一个真实目标;短时到访优先演示,动手课优先基础小样。', 'Set one honest goal around time, age, fine-motor comfort, and piece expectations; short visits favour demonstration, while hands-on sessions favour a basic sample.', language) },
+ { title: pickText('核对马尾芯、丝线与预制材料', 'Check Horsehair Core, Silk & Prepared Materials', language), copy: pickText('写明马尾来源与清洁/预处理、丝线、布料、针具、绣架和老师预制部分;现场不安排从活体马匹取材。', 'Record horsehair source and cleaning or preparation, silk, cloth, needles, frame, and teacher-prepared stages; no collection from live horses takes place during the class.', language) },
+ { title: pickText('现场确认针具、拍摄与讲解', 'Reconfirm Needles, Photography & Interpretation', language), copy: pickText('开课前说明针具回收、儿童陪同、手部敏感和中途退出;人物、作品、家庭空间与制作过程分别征得拍摄及公开使用同意。', 'Before class, explain needle control, child supervision, hand sensitivities, and exit. Seek separate consent for photographing and publishing people, works, homes, and process.', language) },
+ { title: pickText('记录完成度、包装与后寄', 'Record Finish, Packing & Shipping', language), copy: pickText('离开前写清小样已完成、由老师收尾或后寄,以及预计周期、包装、邮费、国际寄送限制、破损与未完成责任。', 'Before departure, record whether the sample is finished, teacher-finished, or shipped later, plus timing, packing, postage, international limits, damage, and unfinished-work responsibility.', language) },
+ ];
+ const gates = [
+ { title: pickText('具名主体与真实课程', 'Named Host & Real Lesson', language), copy: pickText('三都具体工坊、老师身份与技艺范围、官方称号依据、实际课程、日期容量、费用、取消和接待窗口全部确认。', 'Confirm the specific Sandu studio, teacher and craft scope, basis for official titles, real lesson, date capacity, fee, cancellation, and hosting window.', language) },
+ { title: pickText('材料与工序真实性', 'Material & Process Authenticity', language), copy: pickText('马尾作芯、丝线缠裹后盘绣固定的材料关系要由老师和实物支持;不把普通刺绣、蜡染或通用手作图片冒充马尾绣。', 'The horsehair core, silk wrapping, and couched structure must be supported by the teacher and real samples; generic embroidery, batik, or craft images are never presented as horsehair embroidery proof.', language) },
+ { title: pickText('时长与作品复杂度', 'Duration & Piece Complexity', language), copy: pickText('演示、入门小样和深度学习分别定时;复杂背带或服饰片不作短课成品承诺,“刺绣活化石”只作有来源的文化称谓。', 'Time demonstration, basic sample, and deep learning separately. Do not promise a complex carrier or garment panel in a short class; “living fossil of embroidery” remains a sourced cultural descriptor, not a sales claim.', language) },
+ { title: pickText('针具、儿童、英文与结算', 'Needles, Children, English & Payment', language), copy: pickText('儿童年龄与成人陪同、针具管理、手部敏感、英文由谁完成、拍摄范围,以及老师、材料、翻译、包装和寄送费用逐项写清。', 'Write down child age and supervision, needle control, hand sensitivities, who provides English, photography scope, and separate teacher, material, interpretation, packing, and shipping fees.', language) },
+ ];
+ const routes = [
+ { number: '01', title: pickText('经典全景线', 'Classic Panorama Route', language), copy: pickText('只在黔南/三都动线成立时加入 2–3 小时入门课;若需从黔东南或荔波绕行,先核算真实车程和住宿。', 'Add a 2–3 hour intro only when the Qiannan–Sandu route fits; from Qiandongnan or Libo, calculate real transfer and overnight impact first.', language), href: '/safaris/classic-guizhou/' },
+ { number: '02', title: pickText('亲子人文慢游', 'Family Heritage Slow Travel', language), copy: pickText('优先 45–75 分钟演示或低针具参与的小样课;儿童能否动针由具名老师、年龄和成人陪同共同决定。', 'Prefer a 45–75 minute demonstration or low-needle sample; child needlework follows the named teacher, age, and adult supervision.', language), href: '/safaris/family-heritage/' },
+ { number: '03', title: pickText('均衡探索线', 'Balanced Discovery Route', language), copy: pickText('可与荔波—三都—黔东南转场组成半日人文节点,但当天不再叠加另一项耗时手作。', 'Use the Libo–Sandu–Qiandongnan transfer as a half-day culture node, without adding another time-heavy craft the same day.', language), href: '/safaris/culture-outdoor-mix/' },
+ ];
+
+ return (
+
+
+
+
+
+
+
+
Human Culture / 03
+
{pickText('水族马尾绣', 'Shui Horsetail Embroidery', language)}
+
{pickText('先确认三都的一位老师、一束真实材料和一段可完成的工序,再谈“活化石”与带走作品。', 'Name one Sandu teacher, real materials, and one achievable stage before speaking of a “living fossil” or take-home piece.', language)}
+
{pickText('查看三种体验方式', 'See Three Experience Formats', language)}
+
+
+
+
+
+
+
+
+
{pickText('体验定义', 'Experience Definition', language)}
+
{pickText('真正珍贵的不是“马尾”两个字,而是材料如何被时间变成一条可以绣的线。', 'The value is not the word “horsehair,” but how material and time become a thread that can be embroidered.', language)}
+
{pickText('水族马尾绣于 2006 年列入第一批国家级非物质文化遗产名录,公开资料记录其以马尾为芯、丝线缠裹,再盘在纹样轮廓并固定、填绣。客户文档提供了中英文方向与通用手作照片,但没有给出可公开使用的三都马尾绣工坊、老师和工序实拍;因此第一版先把体验拆成可核验的演示、入门与深度三档,图片也明确不作为工艺证明。', 'Shui horsetail embroidery entered China’s first national intangible-cultural-heritage list in 2006. Public records describe horsehair as a core wrapped in silk, then couched along motif outlines and filled. The client brief supplies bilingual direction and general craft photography, but no publishable Sandu studio, teacher, or process record. This first version therefore separates demonstration, introduction, and deep learning into verifiable formats, and labels imagery as reference rather than craft proof.', language)}
+
+
+ - {pickText('地区', 'Area', language)}
- {pickText('三都水族自治县 / 具名工坊按日期确认', 'Sandu Shui Autonomous County / named studio by date', language)}
+ - {pickText('建议时长', 'Suggested Time', language)}
- {pickText('演示 45–75 分钟;入门 2–3 小时;深度半日或多次', 'Demo 45–75 min; intro 2–3 hr; deep half-day or repeat sessions', language)}
+ - {pickText('工艺核心', 'Process Core', language)}
- {pickText('马尾作芯、丝线缠裹、盘线固定与填绣', 'Horsehair core, silk wrapping, couching, and filling', language)}
+ - {pickText('材料', 'Materials', language)}
- {pickText('预处理马尾芯、丝线、布料、针具与预制部分逐项确认', 'Confirm prepared horsehair, silk, cloth, needles, and pre-made stages', language)}
+ - {pickText('语言', 'Language', language)}
- {pickText('老师 + 具名译员/英文司导,不默认老师可全程英文', 'Teacher plus named interpreter or English-speaking guide; no assumed teacher English', language)}
+ - {pickText('作品', 'Piece', language)}
- {pickText('基础小样 / 老师收尾 / 后寄三种状态写入确认', 'Record one: basic sample, teacher-finished, or shipped later', language)}
+
+
+
+
+
{pickText('通用手作动作参考 · 非马尾绣材料、针法或老师证明', 'General handwork reference · not proof of horsehair material, stitch, or teacher', language)}
+
{pickText('客户提供的工坊氛围 · 具体技艺与地点待确认', 'Client-provided studio atmosphere · exact craft and place to confirm', language)}
+
+
+
+
+
+
+
+
02 / Experience Flow
{pickText('从一位真实老师开始,到一件诚实标注完成度的小样结束。', 'Begin with a real teacher and end with an honestly labelled sample.', language)}
+
{flow.map((item, index) => - {String(index + 1).padStart(2, '0')}
)}
+
+
+
+
+
+
03 / Confirmation Gates{pickText('没有具名老师、真实材料和合理时长,就还不是一项可以售卖的马尾绣体验。', 'Without a named teacher, real materials, and honest timing, this is not yet a sellable horsehair-embroidery experience.', language)}
{pickText('文化身份可以由公开资料说明,商业接待仍要逐日落到具体工坊、老师、材料、课程与责任边界。', 'Public records can establish the craft’s cultural identity; commercial hosting must still resolve to a specific studio, teacher, material, lesson, and responsibility boundary for each date.', language)}
+
{gates.map((gate, index) =>
{String(index + 1).padStart(2, '0')}{gate.title}
{gate.copy}
)}
+
+
{pickText('正式方案可以承诺', 'What a final plan can promise', language)}- {pickText('三都具名工坊、老师、课程类型、真实时长、容量、价格与取消条件', 'Named Sandu studio and teacher, lesson type, real duration, capacity, price, and cancellation', language)}
- {pickText('实际马尾芯、丝线、工具、开放工序、基础小样及老师预制/收尾范围', 'Actual horsehair core, silk, tools, open stages, basic sample, and teacher-prepared or finishing scope', language)}
- {pickText('针具与儿童边界、语言人员、拍摄同意、作品包装/后寄与各项费用', 'Needle and child boundaries, language support, photography consent, packing or shipping, and itemised fees', language)}
+
{pickText('必须按主体与日期复核', 'Claims requiring host-and-date proof', language)}- {pickText('页面图片就是马尾绣工坊/工序实拍、授课老师是代表性传承人或课程日常可约', 'That page images show the actual studio or process, the teacher is a listed bearer, or the class is normally bookable', language)}
- {pickText('客人能现场采集马尾、完整经历所有传统工序或短课完成复杂背带/服饰作品', 'That guests collect horsehair, complete every traditional stage, or finish a complex carrier or garment in a short class', language)}
- {pickText('“活化石”“独家”“大师私授”、全程英文、作品当天带走或国际寄送必然成功', '“Living fossil,” “exclusive,” or “private masterclass” sales claims, full English, same-day collection, or guaranteed international shipping', language)}
+
+
{pickText('公开依据参考:文化和旅游部、国家民委及贵州公开文化资料中对三都水族马尾绣的记录。该技艺于 2006 年列入第一批国家级非物质文化遗产名录,公开工艺资料记录以马尾为芯、丝线缠裹并盘绣固定;实际工坊、老师、材料、课程与开放状态仍按日期书面确认。', 'Public references include records from the Ministry of Culture and Tourism, the national ethnic-affairs authority, and Guizhou cultural sources. The craft entered the first national intangible-cultural-heritage list in 2006; published process records describe horsehair cores wrapped in silk and couched into place. Actual studio, teacher, material, lesson, and opening remain date-specific and confirmed in writing.', language)}
+
+
+
+
+ 04 / Route Pairing
{pickText('让三都成为真实的一站,不把一堂课藏进不可能的转场。', 'Make Sandu a real stop—not a class hidden inside an impossible transfer.', language)}
+
+
+
+
+
+ );
+}
+
+function BuyiTraditionalCraftsDetailPage() {
+ const { language } = useTravelSite();
+ const formats = [
+ {
+ number: '01',
+ label: pickText('安顺石头寨', 'Anshun Stone Village', language),
+ title: pickText('具名工坊蜡染入门', 'Named-Studio Batik Introduction', language),
+ copy: pickText(
+ '在安顺石头寨或周边具名布依工坊,由老师讲清村寨、纹样、蜡材、布料与染液,再开放点蜡、染色、去蜡或成品讲解中适合当天的一段。600 多年石头寨与蜡染传统有公开资料支持,但具体老师、工坊和课程仍按日期确认。',
+ 'At a named Buyi studio in or near Anshun Stone Village, the teacher explains village context, motifs, wax, cloth, and dye before opening one date-suitable stage—wax drawing, dyeing, wax removal, or finished-piece reading. Public records support the 600-plus-year village and its batik tradition, while the teacher, studio, and lesson remain date-specific.',
+ language,
+ ),
+ status: pickText('建议 2–3 小时;热蜡、染液、通风、皮肤敏感、作品干燥与带走方式逐项确认', 'Allow 2–3 hours; confirm hot wax, dye, ventilation, skin sensitivity, drying, and collection', language),
+ },
+ {
+ number: '02',
+ label: pickText('黔西南织造', 'Qianxinan Weaving', language),
+ title: pickText('从绞纱到织布,只学一个真实阶段', 'From Yarn to Cloth—Learn One Real Stage', language),
+ copy: pickText(
+ '在晴隆、望谟或黔西南具名工坊中,根据老师的日常工序选择绞纱、上浆、排线、上机织造、纹样理解或服饰制作中的一项。短课不承诺从棉线到完整布匹,更不把服饰成衣压缩成半日完成。',
+ 'At a named studio in Qinglong, Wangmo, or elsewhere in Qianxinan, select one real stage from winding, sizing, warping, loom weaving, motif reading, or garment making. A short lesson never promises a whole cloth from raw yarn, much less a finished garment in half a day.',
+ language,
+ ),
+ status: pickText('建议 2.5–4 小时或半日;织机类型、材料、老师预制部分、坐姿与精细动作按工坊确认', 'Allow 2.5–4 hours or a half-day; confirm loom, material, teacher-prepared stages, posture, and fine-motor needs', language),
+ },
+ {
+ number: '03',
+ label: pickText('葫芦彩绘候选', 'Gourd-Painting Candidate', language),
+ title: pickText('先确认地方归属,再决定如何命名', 'Verify Local Attribution Before Naming the Class', language),
+ copy: pickText(
+ '客户文档提出在石头寨体验葫芦彩绘,但现有资料没有证明它属于该村的布依传统技艺。只有找到具名布依社区老师、真实作品与日常课程,才能写为布依体验;若只是现代颜料装饰,应诚实命名为当代文创课。若采用烙画,还需另行核对热针与通风。',
+ 'The brief proposes gourd painting in a stone village, but the available evidence does not establish it as that village’s Buyi tradition. It becomes a Buyi experience only with a named community teacher, real work, and normal lesson; modern paint decoration should be labelled a contemporary creative workshop. Pyrography also requires separate hot-tool and ventilation checks.',
+ language,
+ ),
+ status: pickText('建议 1.5–2.5 小时;地点、老师、传统依据、颜料或烙画工具确认前不上线销售', 'Allow 1.5–2.5 hours; do not sell before place, teacher, tradition, and paint or pyrography tools are confirmed', language),
+ },
+ ];
+ const flow = [
+ { title: pickText('先选安顺或黔西南', 'Choose Anshun or Qianxinan First', language), copy: pickText('根据整条线路确定石头寨蜡染或黔西南织造,不把相距很远的工艺包装成同一村、同一位老师或同一堂课。', 'Choose Stone Village batik or Qianxinan weaving from the real route; never present distant crafts as one village, one teacher, or one class.', language) },
+ { title: pickText('锁定具名工坊、老师与课程', 'Name the Studio, Teacher & Lesson', language), copy: pickText('确认地址、老师真实技艺与身份、课程是否日常开放、容量、时长、费用、取消;使用传承人称号时核对官方名录。', 'Confirm address, teacher identity and actual craft, normal availability, capacity, duration, fee, and cancellation; verify any heritage-bearer title against an official list.', language) },
+ { title: pickText('只选一个可以完成的工序', 'Choose One Achievable Stage', language), copy: pickText('在点蜡/染色、绞纱/排线/织造或经核验的葫芦彩绘中只选一个重点,并写明老师预制、客人操作和老师收尾的分界。', 'Choose one focus—wax or dye, winding or weaving, or a verified gourd-painting class—and state what the teacher prepares, what guests do, and what the teacher finishes.', language) },
+ { title: pickText('现场复核工具、安全与拍摄', 'Recheck Tools, Safety & Photography', language), copy: pickText('开课前说明热蜡、染料、织机夹点、剪刀针具或烙画热针;儿童参与、人物/家庭空间/作品拍摄和公开使用分别征得同意。', 'Before class, explain hot wax, dye, loom pinch points, scissors and needles, or a pyrography tool; separately confirm child participation and consent for photographing or publishing people, homes, and works.', language) },
+ { title: pickText('确认完成、干燥、后寄与结算', 'Confirm Finish, Drying, Shipping & Payment', language), copy: pickText('离开前记录作品完成度、去蜡/清洗/晾干、当天带走或后寄、包装与邮费,并分别结算老师、工坊、材料、翻译和社区接待。', 'Before departure, record finish, wax removal, washing or drying, same-day collection or shipping, packing and postage, and itemise teacher, studio, materials, interpretation, and community hosting.', language) },
+ ];
+ const gates = [
+ { title: pickText('地点与技艺不能混写', 'Keep Place & Craft Specific', language), copy: pickText('石头寨、晴隆、望谟或其他地点分别写明;蜡染、织锦/织布、刺绣、服饰与葫芦彩绘不能因为都属“布依”就合并成一种通用古法。', 'Name Stone Village, Qinglong, Wangmo, or another place separately; batik, weaving, embroidery, dress, and gourd painting do not become one generic ancient craft simply because they are Buyi-related.', language) },
+ { title: pickText('材料与工序要有实物', 'Materials & Process Need Evidence', language), copy: pickText('蜡材、蓝靛或其他染液、棉麻/线材、织机、颜料或烙画工具、老师预制部分和真实作品必须由具名工坊说明并可现场对应。', 'Wax, indigo or other dye, cotton or other fibre, loom, paint or pyrography tool, teacher-prepared stages, and real work must be explained and shown by the named studio.', language) },
+ { title: pickText('热蜡、染料、织机与儿童', 'Wax, Dye, Looms & Children', language), copy: pickText('核对热源、防烫桌面、通风、皮肤接触、织机活动部位、剪刀针具、烙画热针、洗手与急救;儿童年龄和成人陪同由老师确认。', 'Check heat, burn-safe surfaces, ventilation, skin contact, moving loom parts, scissors and needles, pyrography heat, handwashing, and first aid; the teacher confirms child age and supervision.', language) },
+ { title: pickText('英文、影像、作品与费用', 'English, Images, Piece & Fees', language), copy: pickText('英文由谁完成、哪些人物和空间可拍、现有客户图片能证明什么、作品是否带走或后寄,以及工坊/老师/材料/翻译/寄送费用逐项写清。', 'State who provides English, who and what may be photographed, what the client imagery actually proves, whether the piece is collected or shipped, and each studio, teacher, material, interpretation, and shipping fee.', language) },
+ ];
+ const routes = [
+ { number: '01', title: pickText('经典全景线', 'Classic Panorama Route', language), copy: pickText('在黄果树段顺路安排安顺石头寨具名蜡染工坊半日;不为黔西南织造额外做跨区域往返。', 'Place a named Stone Village batik half-day alongside Huangguoshu; do not add a cross-region return trip for Qianxinan weaving.', language), href: '/safaris/classic-guizhou/' },
+ { number: '02', title: pickText('亲子人文慢游', 'Family Heritage Slow Travel', language), copy: pickText('优先低风险点蜡/成品讲解或经核验的常温彩绘;儿童是否接触热蜡、染液、织机与热针由老师决定。', 'Prefer lower-risk wax drawing, finished-piece interpretation, or verified room-temperature painting; the teacher decides child access to hot wax, dye, looms, or hot tools.', language), href: '/safaris/family-heritage/' },
+ { number: '03', title: pickText('均衡探索线', 'Balanced Discovery Route', language), copy: pickText('在兴义、晴隆或万峰林段选择具名织造/服饰工坊作为半日人文重点,保留真实车程,不再叠加另一项耗时手作。', 'Use a named weaving or dress studio near Xingyi, Qinglong, or Wanfenglin as the half-day culture focus, keeping real transfer time and avoiding another major craft.', language), href: '/safaris/culture-outdoor-mix/' },
+ ];
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
{pickText('体验定义', 'Experience Definition', language)}
+
{pickText('“布依古法”不是一个万能标签,而是不同地方、不同材料和不同老师的具体手艺。', '“Buyi tradition” is not a catch-all label, but a specific craft, material, teacher, and place.', language)}
+
{pickText('客户文档提出在“600 年石头寨”体验古法织造与葫芦彩绘。官方资料能够支持安顺石头寨有 600 多年历史及当地蜡染传统,也能支持黔西南布依纺织包含绞纱、上浆、排线、织布和服饰制作等复杂工序;但现有资料不能证明这两类技艺与葫芦彩绘由石头寨同一工坊提供。因此第一版把它们拆开,分别按具名地点、工坊、老师和课程核验。', 'The brief proposes ancient weaving and gourd painting in a “600-year-old stone village.” Official records support the 600-plus-year history and batik tradition of Anshun Stone Village, and the complex winding, sizing, warping, weaving, and dress-making stages of Buyi textiles in Qianxinan. The available evidence does not show that one Stone Village studio offers all of these plus gourd painting, so this version separates them for place-, studio-, teacher-, and lesson-specific verification.', language)}
+
+
+ - {pickText('地区候选', 'Area Candidates', language)}
- {pickText('安顺石头寨 / 晴隆、望谟或黔西南具名工坊', 'Anshun Stone Village / a named Qinglong, Wangmo, or Qianxinan studio', language)}
+ - {pickText('建议时长', 'Suggested Time', language)}
- {pickText('单项 1.5–4 小时;织造深度体验建议半日或多次', 'One focus 1.5–4 hours; deep weaving needs a half-day or repeat sessions', language)}
+ - {pickText('体验选择', 'Choose One', language)}
- {pickText('蜡染 / 织造与服饰 / 经地方核验的葫芦彩绘', 'Batik / weaving and dress / locally verified gourd painting', language)}
+ - {pickText('材料', 'Materials', language)}
- {pickText('蜡、染液、布线、织机、颜料或热针按真实课程确认', 'Confirm wax, dye, fibre, loom, paint, or hot tool from the real lesson', language)}
+ - {pickText('语言', 'Language', language)}
- {pickText('具名老师 + 专业译员或英文司导', 'Named teacher plus interpreter or English-speaking guide', language)}
+ - {pickText('关键边界', 'Key Boundary', language)}
- {pickText('不同地区和技艺不拼成“一站式古法课”', 'No one-stop class combining unrelated places and crafts', language)}
+
+
+
+
+
{pickText('蓝染氛围参考 · 非布依工坊、石头寨或具体课程证明', 'Indigo atmosphere · not proof of a Buyi studio, Stone Village, or lesson', language)}
+
{pickText('点蜡工序参考 · 具体民族、老师、材料与地点待确认', 'Wax-process reference · community, teacher, material, and place to confirm', language)}
+
{pickText('通用手作桌面 · 非布依织机或纺织工序证明', 'General craft table · not proof of a Buyi loom or weaving process', language)}
+
{pickText('通用操作氛围 · 非葫芦彩绘或具名老师证明', 'General making reference · not proof of gourd painting or a named teacher', language)}
+
+
+
+
+
+
+
+
02 / Experience Flow
{pickText('先把地点和工艺分开核验,再把一堂课写得具体。', 'Verify place and craft separately, then make one lesson specific.', language)}
+
{flow.map((item, index) => - {String(index + 1).padStart(2, '0')}
)}
+
+
+
+
+
+
03 / Confirmation Gates{pickText('不能说清在哪里、跟谁学、用什么做,就不能只用“古法”两个字销售。', 'If place, teacher, and material cannot be named, “traditional” is not enough to sell the experience.', language)}
{pickText('公开资料证明的是地区文化传统,不等于任何村寨、任何老师、任何日期都能提供同一套课程。', 'Public records establish regional traditions, not that every village, teacher, and date offers the same class.', language)}
+
{gates.map((gate, index) =>
{String(index + 1).padStart(2, '0')}{gate.title}
{gate.copy}
)}
+
+
{pickText('正式方案可以承诺', 'What a final plan can promise', language)}- {pickText('具名村寨、工坊、老师、真实课程、日期容量、时长、价格与取消条件', 'Named village, studio, teacher, real lesson, date capacity, duration, price, and cancellation', language)}
- {pickText('实际蜡染/织造/彩绘材料、工具、开放工序、老师预制与收尾范围', 'Actual batik, weaving, or painting materials, tools, open stage, and teacher preparation or finish', language)}
- {pickText('热源/染料/织机/儿童边界、英文人员、拍摄同意、作品带走或后寄', 'Heat, dye, loom, and child boundaries, language support, photography consent, and collection or shipping', language)}
+
{pickText('必须按主体与日期复核', 'Claims requiring host-and-date proof', language)}- {pickText('现有图片就是布依工坊、石头寨、织机或葫芦彩绘实拍,人物就是授课老师', 'That current images show the Buyi studio, Stone Village, loom, or gourd painting, or that pictured people are teachers', language)}
- {pickText('石头寨同一工坊同时提供古法织布、完整蜡染、服饰制作与葫芦彩绘', 'That one Stone Village studio offers traditional weaving, full batik, dress making, and gourd painting', language)}
- {pickText('天然蓝靛、纯手工、传承人私授、全程英文、所有作品当天完成或全部收益回到社区', 'Natural indigo, all-handmade, private bearer teaching, full English, every piece finished same day, or all proceeds returning to the community', language)}
+
+
{pickText('公开依据参考:安顺市人民政府关于石头寨 600 多年布依村寨及蜡染体验的公开资料,以及贵州省人大、国家民委关于布依族纺织、蜡染和织锦的资料。客户提出的“石头寨葫芦彩绘”尚未找到对应地方与传承依据,实际工坊、老师、材料、课程和开放状态仍按日期书面确认。', 'Public references include Anshun government records on the 600-plus-year Buyi Stone Village and batik experiences, plus Guizhou and national ethnic-affairs records on Buyi textiles, batik, and brocade. The brief’s “Stone Village gourd painting” still lacks matching local and tradition evidence; actual studio, teacher, material, lesson, and opening remain date-specific and confirmed in writing.', language)}
+
+
+
+
+ 04 / Route Pairing
{pickText('让安顺做安顺的手艺,让黔西南做黔西南的手艺。', 'Let Anshun carry Anshun craft, and Qianxinan carry Qianxinan craft.', language)}
+
+
+
+
+
+ );
+}
+
+function DongIndigoArchitectureDetailPage() {
+ const { language } = useTravelSite();
+ const formats = [
+ {
+ number: '01',
+ label: pickText('工坊单项', 'Studio Focus', language),
+ title: pickText('具名侗布染制工坊', 'Named Dong Textile-Dyeing Studio', language),
+ copy: pickText(
+ '由具名工坊说明当地侗布的纺、织、染或亮布整理中实际开放的一段,再完成小样、染色观察或材料触摸。蓝靛、植物汁、蛋清或其他整理材料都按该工坊真实配方说明,不用“纯天然草木染”统一概括。',
+ 'A named studio opens one real stage of local Dong cloth—spinning, weaving, dyeing, or bright-cloth finishing—followed by a small sample, dye observation, or material handling. Indigo, plant juice, egg white, or other finishing materials are described from that studio’s actual recipe, not bundled under a generic “all-natural botanical dye” claim.',
+ language,
+ ),
+ status: pickText('建议 2–3 小时;材料、染缸、可动手工序、通风与皮肤敏感按工坊确认', 'Allow 2–3 hours; confirm materials, vats, hands-on stage, ventilation, and skin sensitivity with the studio', language),
+ },
+ {
+ number: '02',
+ label: pickText('建筑单项', 'Architecture Focus', language),
+ title: pickText('鼓楼与风雨桥公共建筑观察', 'Drum Tower & Wind-and-Rain Bridge Walk', language),
+ copy: pickText(
+ '以一个具名侗寨和一至两座具名公共建筑为主线,观察柱网、穿枋、榫卯、重檐、桥廊和社区使用方式。默认只在公共开放区域讲解,不攀爬、不进入封闭结构,也不把所有建筑都统一写成“不用一钉一铁”。',
+ 'Follow one named Dong village and one or two named public buildings, reading columns, crossbeams, mortise-and-tenon joints, layered eaves, bridge galleries, and community use. Interpretation stays in public areas by default—no climbing, no closed structures, and no claim that every building uses no metal fasteners.',
+ language,
+ ),
+ status: pickText('建议 1.5–2.5 小时;具体建筑、开放区域、讲解人、集会/仪式冲突与拍摄边界逐项确认', 'Allow 1.5–2.5 hours; confirm each building, open area, interpreter, community-event conflict, and photography boundary', language),
+ },
+ {
+ number: '03',
+ label: pickText('完整文化日', 'Full Culture Day', language),
+ title: pickText('侗布工坊 + 木构村寨慢行', 'Dong Cloth Studio + Timber-Village Walk', language),
+ copy: pickText(
+ '只有工坊与建筑位于同一村寨或真实顺路、两端接待人和开放时间都成立时,才组合为完整一日。上午和下午各保留一个重点,中间安排真实车程与用餐,不把远距离素材包装成“村内联动”。',
+ 'Create a full day only when the studio and buildings are in the same village or genuinely en route, with both hosts and opening times confirmed. Give morning and afternoon one focus each, including real transfer and meal time rather than presenting distant references as one village experience.',
+ language,
+ ),
+ status: pickText('建议完整 1 日;优先黔东南具名侗寨,最终路线随工坊和建筑开放确认', 'Allow one full day; prioritise a named Qiandongnan Dong village, with the route set by studio and building access', language),
+ },
+ ];
+ const flow = [
+ { title: pickText('先锁定一个具名侗寨', 'Name One Dong Village First', language), copy: pickText('确认村寨、进出道路、停车/步行、公共空间、当日集会或仪式,以及是否适合境外客人正常进入。', 'Confirm the village, access road, parking and walking, public spaces, community meetings or rituals that day, and normal access for international guests.', language) },
+ { title: pickText('分别锁定工坊与建筑讲解人', 'Name the Studio and Architecture Interpreter', language), copy: pickText('工坊端确认老师与课程;建筑端确认熟悉具体鼓楼/风雨桥的讲解人。两者可以是不同主体,不强行使用“传承人”统一称谓。', 'Confirm the teacher and lesson for textiles, and a person who understands the named drum tower or bridge for architecture. They may be different hosts and are not automatically labelled “heritage bearers.”', language) },
+ { title: pickText('核对材料与建筑事实', 'Check Materials & Building Facts', language), copy: pickText('写清染料、整理材料、实际工序和作品;建筑则写清名称、年代/修缮信息来源、结构类型及哪些部位能够支持榫卯或无铁钉表述。', 'Write down dye and finishing materials, actual stages, and the piece; for buildings, record name, source for age or restoration, structural type, and exactly which parts support a mortise-and-tenon or no-metal-fastener statement.', language) },
+ { title: pickText('现场按社区使用让路', 'Yield to Community Use On Site', language), copy: pickText('鼓楼、桥廊和寨中道路首先是社区空间。遇到议事、仪式、施工、宴席或居民不便拍摄时,缩短、绕行或取消对应内容。', 'Drum towers, bridge galleries, and village lanes are community spaces first. When meetings, rituals, works, meals, or resident privacy intervene, shorten, reroute, or remove that content.', language) },
+ { title: pickText('完成作品并记录真实结算', 'Finish the Piece & Record Settlement', language), copy: pickText('说明小样是否完成、干燥或后寄,并分别记录工坊、老师、建筑讲解、翻译、餐食和社区接待费用,不用模糊的“收益全部回到村寨”。', 'State whether the sample is finished, drying, or shipped later, and record studio, teacher, architecture interpretation, language, meal, and community hosting fees separately instead of a vague “all benefit returns to the village” claim.', language) },
+ ];
+ const gates = [
+ { title: pickText('具名工坊与真实材料', 'Named Studio & Real Materials', language), copy: pickText('老师身份、实际侗布类型、纺/织/染/亮布哪一段开放、蓝靛或其他材料、染缸与热源、通风、皮肤接触、作品和费用。', 'Teacher identity, actual Dong cloth, which spinning, weaving, dyeing, or finishing stage opens, indigo or other materials, vats and heat, ventilation, skin contact, piece, and fee.', language) },
+ { title: pickText('具体建筑与结构口径', 'Named Building & Structural Claim', language), copy: pickText('鼓楼/风雨桥名称、位置、开放范围、修缮状态、结构资料来源;“不用铁钉”只用于能被具体建筑或营造资料支持的部分。', 'Building name and location, open areas, restoration status, and structural source; use “no metal fasteners” only where the named building or construction record supports it.', language) },
+ { title: pickText('公共空间、拍摄与安全', 'Public Space, Photography & Safety', language), copy: pickText('社区活动优先、居民与儿童不默认可拍;雨天木桥湿滑、临水临边、楼梯、夜间照明、施工区域、老人儿童步行和中途退出。', 'Community activity takes priority and residents or children are not automatically photographable; check wet timber, water and edges, stairs, night lighting, works, walking needs, and exit.', language) },
+ { title: pickText('距离、语言与责任', 'Distance, Language & Responsibility', language), copy: pickText('工坊与建筑真实距离、车辆/步行接驳、用餐与卫生间、英文由谁完成、迟到或社区活动导致调整时的费用和责任边界。', 'Real studio-to-building distance, vehicle or walking transfer, meals and toilets, who provides English, and fee or responsibility boundaries when delays or community use change the day.', language) },
+ ];
+ const routes = [
+ { number: '01', title: pickText('经典全景线', 'Classic Panorama Route', language), copy: pickText('选择建筑观察或工坊单项之一,作为黔东南村寨段的完整半日,不再叠加远距离手作。', 'Choose either architecture or one studio as a full Qiandongnan village half-day, without adding a distant second craft.', language), href: '/safaris/classic-guizhou/' },
+ { number: '02', title: pickText('亲子人文慢游', 'Family Heritage Slow Travel', language), copy: pickText('优先公共空间慢行和低风险材料观察;儿童是否进入染制环节由具名老师、材料和工具决定。', 'Prioritise a public-space walk and low-risk material observation; child participation in dyeing follows the named teacher, materials, and tools.', language), href: '/safaris/family-heritage/' },
+ { number: '03', title: pickText('均衡探索线', 'Balanced Discovery Route', language), copy: pickText('最适合使用完整一日组合,与村寨慢住衔接;住宿、工坊和建筑必须在真实动线上成立。', 'Best for the full-day combination alongside a village stay, only when accommodation, studio, and buildings form a real route.', language), href: '/safaris/culture-outdoor-mix/' },
+ ];
+
+ return (
+
+
+
+
+
+
+
+
Human Culture / 02
+
{pickText('侗族草木染・木构建筑', 'Dong Indigo & Timber Architecture', language)}
+
{pickText('一块布讲材料,一座鼓楼讲结构;只有具名工坊与具名建筑都成立时,才把它们放进同一天。', 'One cloth explains material; one drum tower explains structure. They share a day only when both the studio and building can be named.', language)}
+
{pickText('查看三种体验方式', 'See Three Experience Formats', language)}
+
+
+
+
+
+
+
+
+
{pickText('体验定义', 'Experience Definition', language)}
+
{pickText('染布不是建筑课的装饰,鼓楼也不是工坊的拍照背景。', 'Textile dyeing is not decoration for an architecture lesson, and a drum tower is not a studio photo backdrop.', language)}
+
{pickText('客户文档把“侗族草木染・木构建筑”列为一个核心体验方向。第一版保留这种组合,但拆成两个独立、可核验的主体:具名侗布工坊负责材料与工序,具名村寨及建筑讲解人负责鼓楼、风雨桥和社区空间。客户图片能够提供村寨与蓝染氛围,但没有证明具体侗布工坊、老师或所有建筑结构,因此页面只把这些内容作为候选,不作现成可售承诺。', 'The brief proposes “Dong Indigo Weaving & Drum Tower Architecture” as one core direction. This version keeps the pairing but separates two verifiable hosts: a named Dong textile studio for material and process, and a named village plus architecture interpreter for drum towers, bridges, and community space. Client photography supports village and indigo atmosphere, but does not prove a specific Dong studio, teacher, or every structural claim, so the page presents candidates rather than a ready-to-sell promise.', language)}
+
+
+ - {pickText('地区候选', 'Area Candidate', language)}
- {pickText('黔东南具名侗寨;最终随工坊与建筑开放确认', 'A named Qiandongnan Dong village, finalised by studio and building access', language)}
+ - {pickText('建议时长', 'Suggested Time', language)}
- {pickText('单项 1.5–3 小时;组合建议完整 1 日', 'One focus 1.5–3 hours; combined format one full day', language)}
+ - {pickText('工坊重点', 'Studio Focus', language)}
- {pickText('纺、织、染或亮布整理中实际开放的一段', 'One genuinely open stage of spinning, weaving, dyeing, or bright-cloth finishing', language)}
+ - {pickText('建筑重点', 'Architecture Focus', language)}
- {pickText('具名鼓楼/风雨桥的结构与社区使用,不默认进入封闭区域', 'Structure and community use of named towers or bridges; no default closed-area access', language)}
+ - {pickText('语言', 'Language', language)}
- {pickText('工坊与建筑两端分别确认老师、讲解人和英文支持', 'Confirm teacher, architecture interpreter, and English support on both sides', language)}
+ - {pickText('关键边界', 'Key Boundary', language)}
- {pickText('“草木染”“无一钉一铁”均按材料和具体建筑复核', 'Verify “botanical dye” by material and “no nails” by named building', language)}
+
+
+
+
+
{pickText('客户提供实拍 · 具体村寨归属与公开使用授权需归档', 'Client-supplied photography · exact village attribution and publication permission to be recorded', language)}
+
+
{pickText('村寨建筑参考 · 具体地点与建筑身份待确认', 'Village architecture reference · exact place and building identity to confirm', language)}
+
{pickText('蓝染氛围参考 · 非侗布工坊或具体课程证明', 'Indigo atmosphere reference · not proof of a Dong textile studio or lesson', language)}
+
+
+
+
+
+
+
+
02 / Experience Flow
{pickText('从具名村寨开始,以社区空间优先结束。', 'Begin with a named village and end by putting community use first.', language)}
+
{flow.map((item, index) => - {String(index + 1).padStart(2, '0')}
)}
+
+
+
+
+
+
03 / Confirmation Gates{pickText('不能说清是哪块布、哪座楼、谁来讲,就不能把公开村寨包装成私享非遗。', 'If we cannot name the cloth, building, and interpreter, a public village cannot be sold as private heritage access.', language)}
{pickText('侗族木构榫卯传统和侗布工艺都有公开文化依据,但实际材料、建筑结构、开放范围与接待关系必须回到具体工坊和具体建筑。', 'Dong timber joinery and textile traditions have public cultural records, but material, structure, access, and hosting must return to a specific studio and building.', language)}
+
{gates.map((gate, index) =>
{String(index + 1).padStart(2, '0')}{gate.title}
{gate.copy}
)}
+
+
{pickText('正式方案可以承诺', 'What a final plan can promise', language)}- {pickText('具名侗寨、工坊、老师、建筑讲解人、具体课程与公共步行路线', 'Named Dong village, studio, teacher, architecture interpreter, real lesson, and public walking route', language)}
- {pickText('实际染制/整理材料、开放工序、作品,以及具名建筑、开放范围和可支持的结构表述', 'Actual dye or finishing materials, open stage, piece, plus named buildings, open areas, and supported structural description', language)}
- {pickText('真实距离、车辆/步行接驳、语言人员、拍摄范围、社区活动备选和各项费用', 'Real distance, vehicle or walking transfer, language support, photography scope, community-event fallback, and itemised fees', language)}
+
{pickText('必须按主体与日期复核', 'Claims requiring host-and-date proof', language)}- {pickText('图片中的蓝染空间就是侗布工坊、授课人为代表性传承人或课程日常可预约', 'That the pictured indigo space is a Dong studio, the teacher is a listed bearer, or the lesson is normally bookable', language)}
- {pickText('所有侗布都是纯天然草木染、所有鼓楼/风雨桥都完全不用铁钉或可进入内部结构', 'That all Dong cloth uses all-natural botanical dye or every tower and bridge uses no metal and opens its structure', language)}
- {pickText('鼓楼夜间歌唱、百家宴、仪式、家庭接待或居民拍摄每天都会发生并可为游客安排', 'That tower singing, community banquets, rituals, home hosting, or resident photography happen daily and can be arranged for visitors', language)}
+
+
{pickText('公开依据参考:国家民委关于侗族木构建筑营造技艺的资料,以及贵州公开文化资料中对鼓楼、风雨桥榫卯体系和侗族蛋浆亮布工艺的记录。实际村寨、建筑、工坊、材料和开放状态仍按日期书面确认。', 'Public references include the national ethnic-affairs authority on Dong timber-building craft and Guizhou cultural records on drum-tower and bridge joinery and Dong egg-finished bright cloth. The actual village, building, studio, material, and opening remain date-specific and written into confirmation.', language)}
+
+
+
+
+ 04 / Route Pairing
{pickText('让工坊和村寨在真实动线上相遇,而不是在文案里相邻。', 'Let studio and village meet on a real route, not merely sit next to each other in copy.', language)}
+
+
+
+
+
+ );
+}
+
+function HeritageOutdoorPairingsDetailPage() {
+ const { language } = useTravelSite();
+ const pairings = [
+ {
+ number: '01',
+ label: pickText('优先落地', 'First to Build', language),
+ title: pickText('梯田慢行 + 具名蜡染工坊', 'Terrace Walk + Named Batik Studio', language),
+ copy: pickText(
+ '上午由本地带路人完成一段低至中等强度的梯田、村路或田野步行,下午进入具名工坊,在老师带领下完成一件小型蜡染作品。正式方案分别写明步行路线与工坊,不把两处相距很远的素材强行拼成一天。',
+ 'Walk a low- to moderate-intensity terrace, village, or field route with a local guide, then enter a named studio to make one small batik piece. The final plan names both the walk and studio rather than forcing distant reference locations into one day.',
+ language,
+ ),
+ status: pickText('最容易控制强度、天气和作品完成时间;丹寨或安顺工坊按老师档期确认', 'The easiest pairing for pacing, weather, and a finished piece; Danzhai or Anshun studio by host availability', language),
+ },
+ {
+ number: '02',
+ label: pickText('材料受控', 'Materials Controlled', language),
+ title: pickText('植物观察 + 石桥古法造纸', 'Plant Observation + Shiqiao Papermaking', language),
+ copy: pickText(
+ '户外部分以识别、观察和讲解为主,不默认让客人在峡谷或保护地采集植物;造纸使用由石桥具名工坊依法准备的构皮、纤维、纸浆或花草材料。根据开放工序体验抄纸、压制、嵌花或晾晒中的一段。',
+ 'The outdoor part focuses on identification and observation, with no default guest collection in canyons or protected land. Papermaking uses bark fibre, pulp, or botanical materials lawfully prepared by a named Shiqiao studio, then offers one available stage such as sheet forming, pressing, flower inlay, or drying.',
+ language,
+ ),
+ status: pickText('“寻草”不等于自由采集;植物、原料、老师和当天开放工序必须确认', '“Plant finding” is not free collection; species, materials, teacher, and available process require confirmation', language),
+ },
+ {
+ number: '03',
+ label: pickText('季节与路线', 'Season & Route', language),
+ title: pickText('茶园步行/骑行 + 制茶体验', 'Tea Walk or Ride + Tea Craft', language),
+ copy: pickText(
+ '先在湄潭或普安候选区选择一条具名茶园步行或骑行路线,再进入具名茶园、合作社或工坊体验当季可做的采摘、摊晾、杀青、揉捻或品鉴。骑行与制茶各自留足时间,不承诺每个季节都能参与完整流程。',
+ 'Choose a named tea-country walk or ride in a Meitan or Pu’an candidate area, then enter a named estate, cooperative, or studio for whichever seasonal stage is available—picking, withering, fixing, rolling, or tasting. Leave real time for both sides and do not promise the full process in every season.',
+ language,
+ ),
+ status: pickText('可在同一天选择步行或骑行之一;骑行需单独核验道路、车辆、头盔与保障车', 'Choose walking or riding—not both; cycling separately requires route, bikes, helmets, and support vehicle', language),
+ },
+ ];
+ const flow = [
+ { title: pickText('先选一个组合,不堆项目', 'Choose One Pairing', language), copy: pickText('确认客人更看重风景、手作、植物、茶或骑行,并根据年龄、体力、精细动作、过敏和当天转场选择一组。', 'Clarify whether guests value landscape, craft, plants, tea, or cycling, then choose one pairing around age, fitness, fine-motor ability, allergies, and transfers.', language) },
+ { title: pickText('锁定两端的具名主体', 'Name Both Hosts', language), copy: pickText('户外端确认路线、带路人和进入许可;文化端确认工坊、老师、真实课程、材料、作品和费用。只有两端都成立才组合。', 'Confirm route, guide, and access for the outdoor half; confirm studio, teacher, real lesson, materials, take-home piece, and fee for the heritage half. Pair only when both stand.', language) },
+ { title: pickText('核对距离、季节与时间', 'Check Distance, Season & Time', language), copy: pickText('计算接驳和用餐,确认农时、茶季、工坊生产安排与作品干燥/带走时间;不使用“附近”掩盖长距离转场。', 'Calculate transfer and meal time, season, tea harvest, studio production, and drying or collection time; do not use “nearby” to hide a long drive.', language) },
+ { title: pickText('出发前做双重 Go / No-Go', 'Dual Go / No-Go', language), copy: pickText('户外按雨、雷电、路面、温度和客人状态决定;工坊按老师、材料、通风、工具与安全条件决定。任一端不成立就缩短或改为单项。', 'Decide the outdoor half by rain, lightning, surface, temperature, and guest condition; decide the studio half by teacher, materials, ventilation, tools, and safety. If either fails, shorten or run one activity only.', language) },
+ { title: pickText('完成作品并记录真实贡献', 'Finish & Record Real Benefit', language), copy: pickText('作品标明是否可当天带走或后寄;按约向带路人、老师、工坊或合作社结算,不把单次体验泛化成“全部收益直达社区”。', 'State whether the piece leaves that day or ships later; settle as agreed with guide, teacher, studio, or cooperative without turning one transaction into an “all benefit goes direct” claim.', language) },
+ ];
+ const gates = [
+ { title: pickText('具名路线与户外条件', 'Named Route & Outdoor Conditions', language), copy: pickText('入口与许可、里程/爬升/路面、带路人、天气阈值、补水/卫生间、儿童边界、车辆接回和中途退出。', 'Access and permission, distance, ascent and surface, guide, weather limits, water and toilets, child boundaries, vehicle recovery, and exit.', language) },
+ { title: pickText('工坊、老师与真实课程', 'Studio, Teacher & Real Lesson', language), copy: pickText('具名工坊和授课人、实际技艺与工序、课程时长、语言支持、容量、费用、作品规格、干燥/寄送和取消。', 'Named studio and teacher, actual craft and stage, lesson duration, language support, capacity, fee, piece size, drying or shipping, and cancellation.', language) },
+ { title: pickText('材料、工具与植物边界', 'Materials, Tools & Plant Boundary', language), copy: pickText('野生植物只观察或使用工坊合法准备材料;复核蜡/染料/热源/刀具/纸浆、通风、皮肤过敏、儿童操作和洗手处置。', 'Observe wild plants or use lawfully prepared studio material; check wax, dye, heat, blades, pulp, ventilation, skin allergy, child handling, and handwashing.', language) },
+ { title: pickText('骑行、接驳与责任', 'Cycling, Transfer & Responsibility', language), copy: pickText('具名骑行道路、机动车混行、车辆尺寸、头盔、领骑/收队、保障车、保险、医疗点,以及两端迟到或取消时的责任边界。', 'Named cycle road, traffic mix, bike fit, helmet, lead and sweep, support vehicle, insurance, medical point, and responsibility when either half runs late or cancels.', language) },
+ ];
+ const routes = [
+ { number: '01', title: pickText('经典全景线', 'Classic Panorama Route', language), copy: pickText('使用梯田慢行 + 一项具名手作的轻量版本,控制为完整半日或一日。', 'Use a gentle terrace walk plus one named craft as a full half-day or day.', language), href: '/safaris/classic-guizhou/' },
+ { number: '02', title: pickText('喀斯特户外探险线', 'Karst Outdoor Adventure', language), copy: pickText('在高强度活动之间加入工坊恢复半日;植物观察或茶园步行只做低强度,不再叠加骑行。', 'Use a studio half-day for recovery between active days; keep plant or tea walking gentle and do not add cycling.', language), href: '/safaris/outdoor-coffee/' },
+ { number: '03', title: pickText('均衡探索线', 'Balanced Discovery Route', language), copy: pickText('最适合安排完整一日组合,在村寨慢住段或黔东南/茶区转场之间使用。', 'Best for one complete pairing day within a village stay or between Qiandongnan and tea-country transfers.', language), href: '/safaris/culture-outdoor-mix/' },
+ ];
+
+ return (
+
+
+
+
+
+
+
+
Unique Local Experiences / 05
+
{pickText('非遗与轻户外融合体验', 'Heritage & Gentle Outdoor Pairings', language)}
+
{pickText('一天只做一个组合,让路上的风景和手里的作品都拥有完整时间。', 'Choose one pairing per day, giving both the landscape and the piece in your hands enough time.', language)}
+
{pickText('查看三种组合', 'See the three pairings', language)}
+
+
+
+
+
+
+
+
+
{pickText('体验定义', 'Experience Definition', language)}
+
{pickText('融合不是把两个打卡点连起来,而是让两段体验在同一片土地上互相解释。', 'A pairing is not two check-ins—it lets two experiences explain the same landscape.', language)}
+
{pickText('客户文档提出“梯田徒步 + 蜡染”“峡谷寻草 + 古法造纸”“茶山骑行 + 制茶”。第一版保留三种方向,但要求户外路线与工坊在地理、时间和主题上真实相连。客户本组3张图片均为扎染打卡空间概念拼图,没有展示户外路线、造纸、茶园或制茶,因此只采用1张并明确标注为概念参考,其余画面使用客户此前提供的田野和手作素材。', 'The brief proposes terrace hiking with batik, canyon plants with papermaking, and tea-country cycling with tea craft. This first version keeps the three directions only when route and studio connect in place, time, and theme. All three supplied images are indigo check-in concept collages, showing no outdoor route, papermaking, tea field, or tea craft; one is retained and labelled as concept reference, while earlier client field and craft material carries the real visual story.', language)}
+
+
+ - {pickText('核心原则', 'Core Rule', language)}
- {pickText('一天只做一组;户外与非遗两端分别具名确认', 'One pairing per day; name and confirm both outdoor and heritage hosts', language)}
+ - {pickText('地理候选', 'Geographic Candidates', language)}
- {pickText('丹寨/安顺蜡染、丹寨石桥造纸、湄潭/普安茶区', 'Danzhai or Anshun batik, Shiqiao paper, Meitan or Pu’an tea country', language)}
+ - {pickText('建议时长', 'Suggested Time', language)}
- {pickText('完整半日至 1 日;骑行组合优先整日', 'Full half-day to one day; cycling pairing preferably a full day', language)}
+ - {pickText('适合', 'Best For', language)}
- {pickText('文化爱好者、亲子、慢旅行与轻至中等体力客人', 'Culture lovers, families, slow travellers, and low- to moderate-fitness guests', language)}
+ - {pickText('作品', 'Take-Home Piece', language)}
- {pickText('小型蜡染、手工纸或当季茶样;规格和寄送按工坊确认', 'Small batik, handmade paper, or seasonal tea sample; size and shipping by studio', language)}
+ - {pickText('天气备选', 'Weather Fallback', language)}
- {pickText('缩短户外、延长工坊;必要时只保留室内体验', 'Shorten outdoors and extend studio time; run indoors only when needed', language)}
+
+
+
+
+
+
+
+
{pickText('客户概念参考 · 非真实场地证明', 'Client concept reference · not proof of a real venue', language)}
+
+
+
+
+
01 / Paired Experiences{pickText('每一组都必须回答:走哪里、跟谁学、为什么放在一起。', 'Every pairing must answer: where to go, who teaches, and why these belong together.', language)}
{pickText('三种组合不是套餐清单;只有路线、主理人、季节、材料和接驳都成立时,才进入正式方案。', 'These are not package checklists; route, host, season, material, and transfer must all work before entering a final plan.', language)}
+
{pairings.map((pairing) =>
{pairing.number}{pairing.label}
{pairing.title}
{pairing.copy}
{pairing.status})}
+
+
+
+
+
+
+
02 / Planning Flow
{pickText('先让两个真实主体说得通,再让页面看起来好看。', 'Make the two real hosts work together before making the page look seamless.', language)}
+
{flow.map((item, index) => - {String(index + 1).padStart(2, '0')}
)}
+
+
+
+
+
+
03 / Operating Gates{pickText('路线、老师或材料少一项,这一天就退回单项体验。', 'Lose the route, teacher, or materials and the day returns to one activity.', language)}
{pickText('“跟随传承人、识别本地植物、参与采茶制茶全过程、作品可带走”全部要落实到具名主体、当季工序和安全条件。', '“Learn from a heritage bearer, identify local plants, complete tea making, take the piece home” all require a named host, seasonal stage, and operating conditions.', language)}
+
{gates.map((gate, index) =>
{String(index + 1).padStart(2, '0')}{gate.title}
{gate.copy}
)}
+
+
{pickText('可以写入正式方案', 'What the final plan can promise', language)}- {pickText('具名户外路线、里程/爬升/路面、带路人、接驳和天气备选', 'Named route, distance, ascent, surface, guide, transfer, and weather fallback', language)}
- {pickText('具名工坊/老师、真实课程、当季工序、材料、时长、费用与语言支持', 'Named studio or teacher, real lesson, seasonal stage, materials, duration, fee, and language support', language)}
- {pickText('具体作品、是否当天带走/后寄,以及骑行车辆、头盔和保障方式', 'Exact piece and same-day collection or shipping, plus bikes, helmets, and support when cycling', language)}
+
{pickText('必须按主体和日期复核', 'Claims requiring host-and-date proof', language)}- {pickText('图片中的扎染空间为真实工坊、真实老师或实际可预约接待现场', 'That the pictured indigo space is a real studio, teacher, or bookable venue', language)}
- {pickText('客人可在峡谷/山林自由采草、植物可安全接触/食用或用于造纸', 'That guests may freely collect plants or that plants are safe to touch, eat, or use in paper', language)}
- {pickText('非遗传承人一对一、采茶与完整制茶全流程、所有作品当天完成带走', 'One-to-one heritage bearer, picking plus full tea production, or every piece finished that day', language)}
+
+
{pickText('公开依据参考:文化和旅游部门关于丹寨石桥古法造纸保护基地的资料、贵州林业部门野生植物采集要求,以及文化和旅游部普安茶海密林骑行线路案例。实际老师、路线、课程和开放状态仍按日期书面确认。', 'Public references include cultural authorities on the Shiqiao papermaking protection base, Guizhou forestry rules for wild-plant collection, and the Ministry of Culture and Tourism’s Pu’an tea-country cycling route. Actual teachers, routes, lessons, and opening remain date-specific.', language)}
+
+
+
+
+ 04 / Route Pairing
{pickText('把文化放进地貌里,也把体力留给真正重要的那一段。', 'Place culture inside the landscape—and save energy for the part that matters.', language)}
+
+
+
+
+
+ );
+}
+
+function HighBridgeAdventureReviewPage() {
+ const { language } = useTravelSite();
+ const modes = [
+ {
+ number: '01',
+ label: pickText('可优先核验', 'First to Verify', language),
+ title: pickText('桥梁观景与工程参观', 'Bridge Viewing & Engineering Visit', language),
+ copy: pickText(
+ '把坝陵河大桥作为黄果树附近的工程与峡谷景观节点,优先确认观景廊道、桥体参观或高空步行当天是否开放。它与蹦极不是同一种产品,也不要求客人接受自由坠落。',
+ 'Use Balinghe Bridge as an engineering and canyon-view stop near Huangguoshu, subject to same-day access for the viewing corridor, internal bridge visit, or elevated walk. This is separate from bungee and does not require free-fall exposure.',
+ language,
+ ),
+ status: pickText('开放时间、参观范围、年龄/行动能力与交通接驳仍需按日期确认', 'Hours, accessible areas, age/mobility rules, and transfers remain date-specific', language),
+ },
+ {
+ number: '02',
+ label: pickText('高风险候选', 'High-Risk Candidate', language),
+ title: pickText('坝陵河大桥蹦极', 'Balinghe Bridge Bungee', language),
+ copy: pickText(
+ '可核验的历史事实是:吉尼斯世界纪录在 2019 年 1 月 12 日认证这里的商业蹦极设施高度为 370.25 米。页面不把这个设施高度写成客人的自由落差,也不在未确认当前运营状态前使用“世界最高”作为现行承诺。',
+ 'The verifiable historical fact is that Guinness World Records certified a 370.25 m commercial bungee facility here on 12 January 2019. This page does not equate facility height with guest free-fall distance or use “world’s highest” as a current promise without renewed confirmation.',
+ language,
+ ),
+ status: pickText('只有具名运营方、当天开放、限制条件、装备记录、教练、保险和救援全部通过后才进入正式行程', 'Enters a final itinerary only after the named operator, live availability, restrictions, equipment records, instructor, insurance, and rescue all pass', language),
+ },
+ {
+ number: '03',
+ label: pickText('项目性质待确认', 'Activity Type Unconfirmed', language),
+ title: pickText('“破茧之翼”受控体验候选', '“Cocoon Wing” Controlled-Experience Candidate', language),
+ copy: pickText(
+ '客户图片证明现场存在特制服装与体验平台,但不足以证明它是普通人自由翼装飞行,也不能证明 260 米、飞越森林河道等宣传描述。正式对外前必须确认它究竟是悬吊、滑索、摆荡、定轨飞行或其他受控系统。',
+ 'The supplied image proves a special suit and platform exist, but not that this is free wingsuit flight for the public or that the proposed 260 m and landscape-flight claims are accurate. Before publication, the exact system—tether, zipline, swing, guided rail, or another controlled mechanism—must be identified.',
+ language,
+ ),
+ status: pickText('在产品名称、机械系统、运营规则与救援资料确认前不提供预约', 'No booking before the product name, mechanical system, operating rules, and rescue records are confirmed', language),
+ },
+ ];
+ const flow = [
+ { title: pickText('先确认项目到底是什么', 'Define the Activity', language), copy: pickText('向运营方索取当前正式产品名、玩法说明、起终点、控制系统、实际高度/落差与可公开素材,避免把蹦极、跳伞、滑翔伞和“破茧之翼”混写。', 'Obtain the current official product name, operating description, start/finish, control system, actual height/drop, and approved media—without mixing bungee, parachuting, paragliding, and the “Cocoon Wing.”', language) },
+ { title: pickText('核验运营主体与当天开放', 'Verify Operator & Availability', language), copy: pickText('确认具名运营主体、场地授权、预约渠道、开放日期、天气停运标准、维护停运与现场联系人。', 'Confirm the named operator, site authorization, booking channel, operating date, weather closure criteria, maintenance closure, and on-site contact.', language) },
+ { title: pickText('取得限制条件与客人资料', 'Match Guest Restrictions', language), copy: pickText('书面确认年龄、身高、体重、健康、用药、既往病史、孕期、饮酒与运动经验限制,再筛查客人。', 'Obtain written age, height, weight, health, medication, medical-history, pregnancy, alcohol, and experience restrictions before screening guests.', language) },
+ { title: pickText('核对装备、人员、保险与救援', 'Check Gear, Team, Insurance & Rescue', language), copy: pickText('核验装备标准与检查记录、操作人员身份与比例、通信、急救、峡谷救援、医疗转运和保险对具体项目的覆盖。', 'Verify gear standards and logs, operator identities and ratios, communication, first aid, canyon rescue, medical transfer, and insurance coverage for the exact activity.', language) },
+ { title: pickText('出发前再次 Go / No-Go', 'Final Go / No-Go', language), copy: pickText('按当天风、雨、雷电、能见度、设备状态和客人状态决定执行、降级为观景,或完全取消;极限项目不作为行程完成度指标。', 'Use live wind, rain, lightning, visibility, equipment, and guest condition to operate, downgrade to viewing, or cancel. An extreme activity is never a trip-completion metric.', language) },
+ ];
+ const gates = [
+ { title: pickText('合法运营与场地授权', 'Legal Operation & Site Authority', language), copy: pickText('具名主体、营业/经营范围、场地授权、当前可售产品、官方预约渠道与投诉/应急联系人。', 'Named entity, operating scope, site authorization, current sellable product, official booking channel, and complaint/emergency contact.', language) },
+ { title: pickText('装备系统与维护记录', 'System & Maintenance Records', language), copy: pickText('绳索、连接、回收或飞行控制系统的标准、序列号/检查记录、维护周期、报废规则与当天双人复核。', 'Standards, serial/inspection records, maintenance cycle, retirement rules, and same-day dual check for ropes, connections, recovery, or flight-control systems.', language) },
+ { title: pickText('人员、天气与救援', 'Team, Weather & Rescue', language), copy: pickText('现场负责人、操作人员、客人比例、风雨雷电停运阈值、通信、急救、垂直/峡谷救援与医疗转运演练。', 'Site lead, operators, guest ratio, wind/rain/lightning thresholds, communication, first aid, vertical/canyon rescue, and medical-transfer drills.', language) },
+ { title: pickText('客人限制与专项保险', 'Guest Limits & Specialist Insurance', language), copy: pickText('年龄、身高、体重、健康和心理限制的书面依据,知情同意,以及保险是否明确覆盖具名场地和具体活动。', 'Written basis for age, size, health, and psychological limits, informed consent, and insurance explicitly covering the named site and exact activity.', language) },
+ ];
+ const routes = [
+ { number: '01', title: pickText('经典全景线', 'Classic Panorama Route', language), copy: pickText('在黄果树段加入桥梁观景或工程参观;高风险项目只有专项资料通过后才替换进去。', 'Add bridge viewing or an engineering visit near Huangguoshu; a high-risk activity replaces it only after specialist evidence passes.', language), href: '/safaris/classic-guizhou/' },
+ { number: '02', title: pickText('喀斯特户外探险线', 'Karst Outdoor Adventure', language), copy: pickText('可作为独立的高风险候选日,前后不叠加洞穴、瀑降或水上活动,并保留完整取消方案。', 'Use only as a standalone high-risk candidate day, without caves, abseiling, or water activity around it, and retain a full cancellation plan.', language), href: '/safaris/outdoor-coffee/' },
+ { number: '03', title: pickText('均衡探索线', 'Balanced Discovery Route', language), copy: pickText('只建议桥梁观景和轻量参观,不让极限项目破坏村寨、人文与恢复节奏。', 'Prefer viewing and a gentle visit so an extreme activity does not disrupt village, cultural, and recovery pacing.', language), href: '/safaris/culture-outdoor-mix/' },
+ ];
+
+ return (
+
+
+
+
+
+
+
+
Specialist Verification / High Bridge
+
{pickText('高桥观景与极限体验核验', 'High Bridge Viewing & Adventure Verification', language)}
+
{pickText('这不是预约商品页。先分清观景、蹦极与受控飞行体验,再用具名运营资料决定哪一项可以进入行程。', 'This is not a booking page. Separate viewing, bungee, and controlled-flight experiences before named operator evidence decides what can enter an itinerary.', language)}
+
{pickText('查看当前核验结论', 'See the current review', language)}
+
+
+
+
+
+
+
+
+
{pickText('公开边界', 'Publication Boundary', language)}
+
{pickText('可以展示真实证据,但不能把历史纪录写成今天的可售承诺。', 'Show real evidence without turning a historical record into today’s sellable promise.', language)}
+
{pickText('客户文档把坝陵河大桥观光、370 米蹦极、低空跳伞、滑翔伞和“破茧之翼”放在同一段。它们的运营主体、活动系统、客人限制和安全要求不同。第一版只公开地理位置、历史认证事实、客户提供的现场图和核验门槛;不提供直接预约。', 'The brief places Balinghe Bridge viewing, a 370 m bungee, parachuting, paragliding, and the “Cocoon Wing” in one section. These have different operators, systems, guest limits, and safety requirements. This first version publishes only location, the historical record fact, supplied on-site images, and verification gates—with no direct booking.', language)}
+
+
+ - {pickText('地理依托', 'Geographic Base', language)}
- {pickText('安顺关岭 / 坝陵河大桥 / 黄果树附近', 'Guanling, Anshun / Balinghe Bridge / near Huangguoshu', language)}
+ - {pickText('当前定位', 'Current Position', language)}
- {pickText('桥梁观景候选 + 两项专项核验候选', 'Bridge-viewing candidate + two specialist-review candidates', language)}
+ - {pickText('历史事实', 'Historical Fact', language)}
- {pickText('2019-01-12 获认证的商业蹦极设施高度:370.25 米', 'Commercial bungee facility certified on 12 Jan 2019: 370.25 m', language)}
+ - {pickText('不直接承诺', 'Not Promised', language)}
- {pickText('当前“世界最高”、实际自由落差、当天开放与普通人翼装飞行', 'Current “world’s highest,” actual free-fall, live operation, or public wingsuit flight', language)}
+ - {pickText('适合讨论', 'Who Can Enquire', language)}
- {pickText('先接受健康、体重、天气、保险和运营方规则筛查的成人客人', 'Adults willing to pass health, weight, weather, insurance, and operator screening', language)}
+ - {pickText('默认备选', 'Default Fallback', language)}
- {pickText('桥梁观景 / 工程参观 / 黄果树与峡谷摄影', 'Bridge viewing / engineering visit / Huangguoshu and canyon photography', language)}
+
+
+
+
+
+
+
+
01 / Current Review{pickText('三种体验,三套完全不同的证据。', 'Three experiences. Three completely different evidence sets.', language)}
{pickText('观景可以先核验开放状态;蹦极需要专项运营与保险;“破茧之翼”必须先确认产品性质。', 'Viewing starts with access checks; bungee requires specialist operation and insurance; the “Cocoon Wing” first requires a clear product definition.', language)}
+
{modes.map((mode) =>
{mode.number}{mode.label}
{mode.title}
{mode.copy}
{mode.status})}
+
+
+
+
+
+
+
02 / Verification Flow
{pickText('先把资料核清,再把客人带到桥上。', 'Clear the evidence before taking a guest to the bridge.', language)}
+
{flow.map((item, index) => - {String(index + 1).padStart(2, '0')}
)}
+
+
+
+
+
+
03 / Launch Gates{pickText('四类资料缺一项,高风险项目就不进入正式行程。', 'Miss one evidence group and the high-risk activity stays out.', language)}
{pickText('“正规商业运营、进口装备、专业教练一对一、完整安全预案”不能作为笼统宣传句,必须拆成具名文件与可核验记录。', '“Regular commercial operation, imported equipment, one-to-one professional instructor, and complete safety plan” cannot remain generic marketing lines; each must become named documents and verifiable records.', language)}
+
{gates.map((gate, index) =>
{String(index + 1).padStart(2, '0')}{gate.title}
{gate.copy}
)}
+
+
{pickText('当前可以公开', 'Safe to publish now', language)}- {pickText('坝陵河大桥的位置与桥梁/峡谷观景方向', 'Balinghe Bridge location and its bridge/canyon viewing direction', language)}
- {pickText('2019 年 1 月 12 日、370.25 米商业蹦极设施的历史认证事实', 'The historical 12 Jan 2019 certification of a 370.25 m commercial bungee facility', language)}
- {pickText('三张客户提供的现场图,以及“按日期专项核验”的状态', 'Three client-supplied on-site images and the date-specific specialist-review status', language)}
+
{pickText('暂不作为可售承诺', 'Not a sellable promise yet', language)}- {pickText('当前“世界最高”、370 米实际自由落差、低空跳伞或滑翔伞日常开放', 'Current “world’s highest,” a 370 m actual free-fall, or daily parachuting/paragliding access', language)}
- {pickText('“普通人翼装飞行”、260 米高度、飞越森林河道或玻璃桥', '“Public wingsuit flight,” a 260 m height, or flight over forest, river, or glass bridge', language)}
- {pickText('进口装备、一对一教练、完整预案、年龄/体重范围与保险已覆盖', 'Imported equipment, one-to-one instructor, complete response plan, age/weight range, or confirmed insurance', language)}
+
+
{pickText('纪录口径:吉尼斯世界纪录“Highest commercial bungee jump facility”页面,认证日期 2019-01-12;当前开放与运营资料仍须由业务取得运营方书面确认。', 'Record wording: Guinness World Records, “Highest commercial bungee jump facility,” achieved 12 January 2019. Current access and operating evidence still require written confirmation from the operator.', language)}
+
+
+
+
+ 04 / Route Pairing
{pickText('桥梁观景可以顺路,高风险项目必须独立决策。', 'Viewing can sit on the route; high risk requires its own decision.', language)}
+
+
+
+
+
+ );
+}
+
+function GenericExperienceDetailPage({ slug }: { slug: string }) {
const { cmsContent, language } = useTravelSite();
const experience = experienceFromSlug(slug);
const baseDetail = makeExperiencePoiDetail(experience);
@@ -3036,6 +6963,32 @@ function ExperienceDetailPage({ slug }: { slug: string }) {
return
;
}
+function ExperienceDetailPage({ slug }: { slug: string }) {
+ if (slug === 'cave-expedition') return
;
+ if (slug === 'stream-tracing') return
;
+ if (slug === 'rafting') return
;
+ if (slug === 'karst-hiking-cycling') return
;
+ if (slug === 'cave-luxury-dining') return
;
+ if (slug === 'wild-coffee') return
;
+ if (slug === 'village-immersion') return
;
+ if (slug === 'ethnic-festivals') return
;
+ if (slug === 'culinary-cultural-journeys') return
;
+ if (slug === 'iconic-waterfall-clusters') return
;
+ if (slug === 'indigenous-ethnic-villages') return
;
+ if (slug === 'historic-ancient-towns') return
;
+ if (slug === 'qingyan-battle-immersive-roleplay') return
;
+ if (slug === 'loushanguan-battle-immersive-march') return
;
+ if (slug === 'loushanguan') return
;
+ if (slug === 'karst-glamping') return
;
+ if (slug === 'miao-craft') return
;
+ if (slug === 'dong-indigo-architecture') return
;
+ if (slug === 'shui-horsetail-embroidery') return
;
+ if (slug === 'buyi-traditional-crafts') return
;
+ if (slug === 'heritage-outdoor-pairings') return
;
+ if (slug === 'high-bridge-adventure') return
;
+ return
;
+}
+
function PoiDetailPage({ detail, breadcrumbs }: { detail: PoiDetailContent; breadcrumbs: string[] }) {
const { language } = useTravelSite();
const [activeGalleryIndex, setActiveGalleryIndex] = useState
(null);
@@ -3140,7 +7093,12 @@ function PoiDetailPage({ detail, breadcrumbs }: { detail: PoiDetailContent; brea
function SafariDetailPage({ slug }: { slug: string }) {
const { language, cmsContent } = useTravelSite();
- const safari = safariFromSlug(slug, cmsContent, language);
+ const isClassicPanorama = slug === 'classic-guizhou';
+ const isOutdoorAdventure = slug === 'outdoor-coffee';
+ const isBalancedDiscovery = slug === 'culture-outdoor-mix';
+ const isEditorialRoute = isClassicPanorama || isOutdoorAdventure || isBalancedDiscovery;
+ const canonicalRoute = safariCards.find((route) => route.slug === slug) || safariCards[0];
+ const safari = isEditorialRoute ? localizeSafariCard(canonicalRoute, language) : safariFromSlug(slug, cmsContent, language);
const [activeGalleryIndex, setActiveGalleryIndex] = useState(null);
const routePillars = routeDetailPillars(safari, language);
const [routeFlow, stayPlan, foodPlan, transportPlan] = routePillars;
@@ -3150,9 +7108,189 @@ function SafariDetailPage({ slug }: { slug: string }) {
alt: language === 'zh' ? `${safari.title}图册 ${index + 1}` : `${safari.title} gallery ${index + 1}`,
caption: safari.title,
}));
+ const classicFacts = [
+ { label: pickText('建议天数', 'Suggested length', language), value: safari.duration },
+ { label: pickText('起止点', 'Start / finish', language), value: pickText('贵阳 / 贵阳', 'Guiyang / Guiyang', language) },
+ { label: pickText('体力等级', 'Physical level', language), value: safari.intensity },
+ { label: pickText('适合人群', 'Best for', language), value: safari.bestFor[0] },
+ { label: pickText('最佳季节', 'Best season', language), value: safari.season },
+ { label: pickText('旅行方式', 'Travel model', language), value: safari.service },
+ ];
+ const outdoorFacts = [
+ { label: pickText('建议天数', 'Suggested length', language), value: safari.duration },
+ { label: pickText('起止点', 'Start / finish', language), value: pickText('贵阳 / 贵阳', 'Guiyang / Guiyang', language) },
+ { label: pickText('活动等级', 'Activity grade', language), value: pickText('轻量 / 活力 / 进阶三档', 'Light / Active / Advanced', language) },
+ { label: pickText('适合人群', 'Best for', language), value: safari.bestFor[0] },
+ { label: pickText('执行门槛', 'Operating gate', language), value: pickText('天气、水位、运营方与客人状态', 'Weather, water, operator and guest condition', language) },
+ { label: pickText('旅行方式', 'Travel model', language), value: safari.service },
+ ];
+ const balancedFacts = [
+ { label: pickText('建议天数', 'Suggested length', language), value: safari.duration },
+ { label: pickText('起止点', 'Start / finish', language), value: pickText('贵阳 / 贵阳', 'Guiyang / Guiyang', language) },
+ { label: pickText('节奏原则', 'Rhythm rule', language), value: pickText('每天一个核心预约', 'One core booking per day', language) },
+ { label: pickText('适合人群', 'Best for', language), value: safari.bestFor[0] },
+ { label: pickText('户外强度', 'Outdoor level', language), value: pickText('轻量,可替换', 'Gentle and replaceable', language) },
+ { label: pickText('旅行方式', 'Travel model', language), value: safari.service },
+ ];
+ const routeFacts = isOutdoorAdventure ? outdoorFacts : isBalancedDiscovery ? balancedFacts : classicFacts;
+ const classicRouteStops = [
+ { place: pickText('贵阳', 'Guiyang', language), transfer: pickText('抵达与适应', 'Arrival and reset', language) },
+ { place: pickText('黄果树', 'Huangguoshu', language), transfer: pickText('约 2–2.5 小时', 'about 2–2.5 hr', language) },
+ { place: pickText('荔波', 'Libo', language), transfer: pickText('约 4–5 小时', 'about 4–5 hr', language) },
+ { place: pickText('西江 / 黔东南', 'Xijiang / Southeast Guizhou', language), transfer: pickText('约 3.5–4 小时', 'about 3.5–4 hr', language) },
+ { place: pickText('镇远', 'Zhenyuan', language), transfer: pickText('约 2–3 小时', 'about 2–3 hr', language) },
+ { place: pickText('贵阳', 'Guiyang', language), transfer: pickText('约 3.5–4 小时', 'about 3.5–4 hr', language) },
+ ];
+ const outdoorRouteStops = [
+ { place: pickText('贵阳', 'Guiyang', language), transfer: pickText('抵达、问询与装备清单', 'Arrival, assessment and gear list', language) },
+ { place: pickText('北部洞穴区域', 'Northern cave country', language), transfer: pickText('转场 + 基础适应', 'Transfer + field adaptation', language) },
+ { place: pickText('洞穴主活动', 'Cave activity base', language), transfer: pickText('单日单项,不叠加技术活动', 'One core activity, no technical stacking', language) },
+ { place: pickText('安顺 / 黔南', 'Anshun / Qiannan', language), transfer: pickText('恢复后进入峡谷河谷', 'Recover, then enter canyon country', language) },
+ { place: pickText('山野咖啡', 'Mountain coffee', language), transfer: pickText('轻量活动与恢复', 'Light movement and recovery', language) },
+ { place: pickText('贵阳', 'Guiyang', language), transfer: pickText('返程安全缓冲', 'Departure safety buffer', language) },
+ ];
+ const balancedRouteStops = [
+ { place: pickText('贵阳', 'Guiyang', language), transfer: pickText('抵达与偏好对齐', 'Arrival and preference alignment', language) },
+ { place: pickText('黔东南村寨', 'Southeast Guizhou village', language), transfer: pickText('主人见面与慢住', 'Meet the host and settle in', language) },
+ { place: pickText('梯田与工坊', 'Terraces and workshop', language), transfer: pickText('本地人带路 + 一项非遗', 'Local-led walk + one heritage craft', language) },
+ { place: pickText('荔波 / 黔南', 'Libo / Qiannan', language), transfer: pickText('一项轻户外', 'One gentle outdoor day', language) },
+ { place: pickText('山野停靠', 'Mountain pause', language), transfer: pickText('咖啡、短步行或观景', 'Coffee, short walk or a view', language) },
+ { place: pickText('贵阳', 'Guiyang', language), transfer: pickText('城市收尾与返程', 'City finish and departure', language) },
+ ];
+ const activeRouteStops = isOutdoorAdventure ? outdoorRouteStops : isBalancedDiscovery ? balancedRouteStops : classicRouteStops;
+ const outdoorGrades = [
+ {
+ level: pickText('01 / 轻量', '01 / Light', language),
+ title: pickText('先建立舒适感', 'Build comfort first', language),
+ activities: pickText('入门洞穴步行、峰林轻徒步、平缓水域或森林步道。', 'Intro cave walking, gentle peak-forest hikes, calm water or forest trails.', language),
+ fit: pickText('第一次参加户外、怕水/怕高或希望保留更多休息的人。', 'First-time outdoor guests, anyone uneasy with water/heights, or travelers who want more rest.', language),
+ },
+ {
+ level: pickText('02 / 活力', '02 / Active', language),
+ title: pickText('有挑战,但可随时降级', 'A challenge with a clear downgrade', language),
+ activities: pickText('洞穴桨板、溯溪、峡谷步行或较长距离峰林徒步。', 'Cave paddleboarding, stream tracing, canyon walks or a longer peak-forest hike.', language),
+ fit: pickText('具备基础体能、能听从现场指令,并接受因水位替换项目的人。', 'Guests with basic fitness who follow field instructions and accept water-led substitutions.', language),
+ },
+ {
+ level: pickText('03 / 进阶', '03 / Advanced', language),
+ title: pickText('只在完整核验后开放', 'Available only after full validation', language),
+ activities: pickText('未开发洞段、瀑降、技术绳索或激流水域,仅作为候选方向。', 'Undeveloped cave sections, waterfall rappel, technical rope work or white water remain candidate options only.', language),
+ fit: pickText('需验证既往经验、专项保险、运营资质、装备系统和撤离能力。', 'Requires verified prior experience, specialist insurance, operator records, equipment systems and evacuation ability.', language),
+ },
+ ];
+ const outdoorSafetyGates = [
+ { title: pickText('天气与水位', 'Weather & water', language), copy: pickText('降雨、上游水情、能见度或现场道路任何一项不合适,项目降级或取消。', 'Rainfall, upstream conditions, visibility or access can downgrade or cancel the activity.', language) },
+ { title: pickText('运营方与带队人员', 'Operator & field team', language), copy: pickText('具体公司、领队/向导资料、活动边界与应急联系人写入正式方案。', 'The operator, field-team records, operating boundary and emergency contact are stated in the final plan.', language) },
+ { title: pickText('装备、通信与保险', 'Gear, comms & insurance', language), copy: pickText('头盔、照明、绳索/浮具、通信、保暖和保险逐项确认,不用笼统“全套保障”代替。', 'Helmet, lighting, rope/flotation gear, communication, warmth and insurance are checked item by item.', language) },
+ { title: pickText('客人状态与退出机制', 'Guest condition & exit plan', language), copy: pickText('出发当天仍要确认睡眠、伤病、恐惧与执行能力,并预先说明撤回点和替代安排。', 'Sleep, injury, fear and ability are rechecked on the day, with exit points and alternatives explained first.', language) },
+ ];
+ const balancedLayers = [
+ {
+ label: pickText('01 / 慢住', '01 / Stay', language),
+ title: pickText('先让村寨成为生活场景', 'Let the village become a lived setting', language),
+ copy: pickText('连续住下,保留夜晚、清晨、主人家常饭与社区节奏,而不是日间参观后马上离开。', 'Stay long enough to keep the evening, morning, home meal and community rhythm rather than leaving after a daytime visit.', language),
+ },
+ {
+ label: pickText('02 / 跟随', '02 / Follow', language),
+ title: pickText('让熟悉土地和手艺的人带路', 'Follow people who know the land and craft', language),
+ copy: pickText('梯田交给本地农民,手作交给真实工坊;体验随农时、季节和主人档期确认。', 'Terraces belong with a local farmer and craft with a real workshop, all confirmed around season and host availability.', language),
+ },
+ {
+ label: pickText('03 / 轻探', '03 / Explore', language),
+ title: pickText('自然段只保留一项核心活动', 'Keep one core nature experience', language),
+ copy: pickText('水森林、河谷步道、平缓水域或入门洞穴四选一,让风景拥有时间,而不是成为任务清单。', 'Choose one water forest, river trail, calm-water or intro-cave day so nature has time instead of becoming a checklist.', language),
+ },
+ ];
+ const balancedFlexRules = [
+ { label: pickText('需要提前锁定', 'Book first', language), value: pickText('村寨住宿、主人、农民带路、非遗老师与交通', 'Village stay, host, local farmer, heritage maker and transport', language) },
+ { label: pickText('当天可以调整', 'Flex on the day', language), value: pickText('停留时长、轻量散步、休息、咖啡与用餐节奏', 'Stay time, gentle walks, rest, coffee and meal rhythm', language) },
+ { label: pickText('可能需要替换', 'May be replaced', language), value: pickText('受天气、农时、节庆和社区日常影响的活动', 'Activities affected by weather, farming, festivals or community life', language) },
+ ];
+ const classicPracticalNotes = [
+ {
+ title: pickText('山地天气', 'Mountain weather', language),
+ copy: pickText('贵州天气与水量变化快,轻薄分层、防雨外套和防滑鞋比单一厚衣更实用。', 'Weather and water levels change quickly. Light layers, rain protection and grippy shoes are more useful than one heavy layer.', language),
+ },
+ {
+ title: pickText('车程不是固定承诺', 'Drive times are estimates', language),
+ copy: pickText('页面车程用于路线判断;最终方案会按酒店位置、道路、天气和节假日重新核对。', 'Times help with route decisions; the final plan is rechecked against hotels, roads, weather and holiday traffic.', language),
+ },
+ {
+ title: pickText('酒店逐家确认', 'Hotels checked one by one', language),
+ copy: pickText('预订前逐家确认当前涉外接待条件、房态与图片,不使用“全部具备涉外资质”的笼统承诺。', 'Current foreign-guest reception, rooms and imagery are confirmed property by property before booking.', language),
+ },
+ {
+ title: pickText('护照与预约', 'Passport and reservations', language),
+ copy: pickText('景区、酒店和交通可能需要护照信息;具体提交时间与隐私说明在确认方案后告知。', 'Attractions, hotels and transport may require passport details; timing and privacy handling are explained after the plan is aligned.', language),
+ },
+ {
+ title: pickText('保险单列确认', 'Insurance confirmed separately', language),
+ copy: pickText('旅行保险是否包含、保障范围与承保主体必须在正式报价中单独列明。', 'Whether insurance is included, its coverage and provider must be stated separately in the formal quote.', language),
+ },
+ {
+ title: pickText('每天都可讨论', 'Every day stays discussable', language),
+ copy: pickText('开放时间和安全条件允许时,可按体力、天气与兴趣调整停留时长和先后顺序。', 'When opening hours and safety allow, stay times and sequencing can flex around energy, weather and interests.', language),
+ },
+ ];
+ const outdoorPracticalNotes = [
+ {
+ title: pickText('先分级,再选项目', 'Grade first, choose second', language),
+ copy: pickText('页面中的洞穴、峡谷与亲水活动是候选库,不代表每位客人或每个日期都能执行。', 'The cave, canyon and water activities form a candidate library; they are not guaranteed for every guest or date.', language),
+ },
+ {
+ title: pickText('每天重新做 Go / No-go', 'A fresh Go / No-go each day', language),
+ copy: pickText('即使出发前确认过,现场天气、水位、道路与身体状态仍拥有最终否决权。', 'Even after pre-trip approval, field weather, water, access and guest condition retain the final veto.', language),
+ },
+ {
+ title: pickText('不连续堆叠技术活动', 'No back-to-back technical stacking', language),
+ copy: pickText('技术型主活动之间安排恢复或转场日,避免为了“项目更多”牺牲判断力与体力。', 'Recovery or transfer days sit between technical activities so volume never overrides judgment and energy.', language),
+ },
+ {
+ title: pickText('个人信息必须如实', 'Health disclosure matters', language),
+ copy: pickText('既往伤病、用药、心肺情况、怕水怕高与户外经验都会影响活动等级。', 'Past injury, medication, cardio-respiratory condition, water/height fear and experience all affect the grade.', language),
+ },
+ {
+ title: pickText('保险与责任单列', 'Insurance stated separately', language),
+ copy: pickText('旅行保险、专项户外保险、承保主体、免责范围与理赔方式必须在确认文件中单列。', 'Travel and specialist cover, provider, exclusions and claims process must be stated separately in confirmation documents.', language),
+ },
+ {
+ title: pickText('极限项目暂不发布', 'Extreme options are withheld', language),
+ copy: pickText('370 米蹦极、翼装及未经核验的高度、证书、年龄承诺不进入当前可售清单。', 'The 370 m bungee, wingsuit and unverified height, certificate or age claims do not enter the current sellable list.', language),
+ },
+ ];
+ const balancedPracticalNotes = [
+ {
+ title: pickText('灵活不等于不预约', 'Flexible does not mean unbooked', language),
+ copy: pickText('主人、农民带路人、非遗工坊、住宿和车辆先锁定,再在可行范围内调整当天节奏。', 'Hosts, local farmers, workshops, stays and vehicles are booked first; the day then flexes inside those realities.', language),
+ },
+ {
+ title: pickText('村寨住宿逐家确认', 'Village stays checked one by one', language),
+ copy: pickText('卫浴、卫生、隔音、行李搬运、涉外接待与真实图片都需在预订前确认。', 'Bathroom setup, hygiene, sound, luggage access, foreign-guest reception and real imagery are checked before booking.', language),
+ },
+ {
+ title: pickText('不把生活保证成表演', 'Daily life is not staged on demand', language),
+ copy: pickText('鼓楼对歌、农事、集市与节庆取决于社区真实安排,不能承诺每天固定出现。', 'Drum-tower singing, farming, markets and festivals follow real community schedules and cannot be promised daily.', language),
+ },
+ {
+ title: pickText('手作只选一项做深', 'One craft, enough time', language),
+ copy: pickText('蜡染、刺绣、草木染或马尾绣根据地区、老师与客人耐心选择,不做流水线拼盘。', 'Batik, embroidery, indigo or horsetail work is chosen by place, maker and guest patience—not compressed into a sampler.', language),
+ },
+ {
+ title: pickText('节庆日期需复核', 'Festival dates need reconfirmation', language),
+ copy: pickText('农历节庆、村寨批次与具体活动每年可能变化,正式方案以当年官方和社区信息为准。', 'Lunar festivals, village rotations and events can change; the final plan follows current official and community information.', language),
+ },
+ {
+ title: pickText('轻户外仍看天气', 'Gentle outdoors still follows weather', language),
+ copy: pickText('水森林、河谷与入门洞穴也可能因降雨、水位或道路调整,地面文化备选会提前准备。', 'Water forests, valleys and intro caves can still change with rain, water or access, so a cultural ground alternative is prepared.', language),
+ },
+ ];
+ const practicalNotes = isOutdoorAdventure ? outdoorPracticalNotes : isBalancedDiscovery ? balancedPracticalNotes : classicPracticalNotes;
const detailSections = [
safari.gallery.length > 0 && { label: translateUi('图册', language), id: 'gallery', iconKey: 'detail-tab-gallery' },
{ label: translateUi('预览', language), id: 'overview', iconKey: 'detail-tab-overview' },
+ isEditorialRoute && { label: 'Why This Trip', id: 'why-this-trip', iconKey: 'detail-tab-description' },
+ isOutdoorAdventure && { label: pickText('活动分级', 'Activity Levels', language), id: 'activity-levels', iconKey: 'detail-tab-overview' },
+ isBalancedDiscovery && { label: pickText('平衡方式', 'How It Balances', language), id: 'balance-framework', iconKey: 'detail-tab-overview' },
routeFlow && { label: routeFlow.label, id: routeFlow.id, iconKey: 'detail-tab-itineraries' },
...servicePillars.map((pillar) => ({
label: pillar.label,
@@ -3165,10 +7303,11 @@ function SafariDetailPage({ slug }: { slug: string }) {
: 'detail-tab-location',
})),
{ label: translateUi('费用说明', language), id: 'includes', iconKey: 'detail-tab-rates' },
+ isEditorialRoute && { label: pickText('安全说明', 'Safety', language), id: 'practical', iconKey: 'detail-tab-includes' },
].filter(Boolean) as AnchorTabItem[];
return (
-
+
{pickText('先判断这是不是你的贵州线路', 'First, decide if this is your Guizhou route', language)}
{safari.summary}
{safari.routeLine}
+ {isEditorialRoute && (
+
+ {routeFacts.map((fact) => (
+
+
- {fact.label}
+ - {fact.value}
+
+ ))}
+
+ )}
{translateUi('适合:', language)}{safari.bestFor[0]}
{translateUi('核心:', language)}{safari.focus}
@@ -3207,7 +7356,7 @@ function SafariDetailPage({ slug }: { slug: string }) {