);
}
// ============= HERO =============
function Hero({ lang }) {
return (
{lang === "zh" ? "香港寵物善終 · Est. 2018" : "Hong Kong Pet Aftercare · Est. 2018"}
{lang === "zh" ? (
<>
溫柔的尾站A gentle last stop.
>
) : (
<>
A gentle last stop.溫柔的 尾站。
>
)}
{lang === "zh" ? (
<>
香港寵物水化、火化及追思服務。
在最後一程,給牠應得的尊重與溫柔。
Pet aquamation, cremation & memorial in Hong Kong.
>
) : (
<>
Pet aquamation, cremation & memorial services.
Dignity and warmth, on the final journey home.
香港寵物水化、火化及追思服務
>
)}
{lang === "zh" ? (
<>不是終點,是溫柔的尾站。Not an end — a gentle last stop.>
) : (
<>Not an end — a gentle last stop.不是終點,是溫柔的尾站。>
)}
{lang === "zh"
? "「尾站」的意思,是這條路上最後一個停靠點。我們相信,離別不一定灰暗。像在晴天的小山頂,風吹過,雲飄過,毛孩靜靜地抬頭望著天——這就是我們想給每一位家人的告別。"
: "A \"last stop\" is the final landing on a journey. We believe farewells don\u2019t have to be dark. Picture a hilltop on a bright day — wind, drifting clouds, your pet gazing up at the sky. That\u2019s the goodbye we wish to give every family."}
{stats.map((s, i) => (
{s.n}{s.suf && {s.suf}}
{s.l}
{s.s &&
{s.s}
}
))}
);
}
// ============= SERVICES =============
function Services({ lang }) {
const data = {
water: {
title: { zh: "水化", en: "Aquamation" },
en: "Alkaline Hydrolysis",
tag: { zh: "最環保", en: "MOST ECO" },
desc: { zh: "以溫水與微量鹼性溶液模擬自然分解。碳排放僅為火化的 1/10,沒有火、沒有煙,過程寧靜。", en: "Gentle alkaline hydrolysis mimics the natural decomposition process. 1/10th the carbon footprint of cremation — no fire, no smoke, a quiet farewell." },
features: [
{ zh: "碳排放僅 1/10", en: "1/10 carbon footprint" },
{ zh: "過程無煙無火", en: "No smoke, no flame" },
{ zh: "骨灰量多 20%", en: "20% more ashes returned" },
{ zh: "適合所有體型", en: "Suitable for all sizes" },
],
},
fire: {
title: { zh: "火化", en: "Cremation" },
en: "Traditional Cremation",
tag: { zh: "傳統", en: "TRADITIONAL" },
desc: { zh: "傳統火化服務,提供個別火化或集體火化兩種選擇,全程專人陪同,可選擇出席或視像觀禮。", en: "Traditional cremation — choose individual or communal. A dedicated attendant accompanies the whole process, with optional on-site or video viewing." },
features: [
{ zh: "個別/集體可選", en: "Individual or communal" },
{ zh: "可現場或視像觀禮", en: "On-site or video viewing" },
{ zh: "約 60–90 分鐘完成", en: "Completes in 60–90 min" },
{ zh: "提供紙鶴摺紙儀式", en: "Optional crane folding ritual" },
],
},
};
return (
{lang === "zh" ? "我們的服務" : "Our Services"}
{lang === "zh" ? <>水化,或火化—— 皆以家人之禮相送。> : <>Aquamation or cremation — each a farewell given as family.>}
{lang === "zh" ? "兩種儀式,同一份心意。由你決定,最適合牠的告別方式。" : "Two rites, one intent. You choose the farewell that feels right."}
{["water", "fire"].map(m => {
const d = data[m];
return (
{lang === "zh" ? <>帶一片天回家。> : <>Take a piece of sky home.>}
{lang === "zh" ? "全部手工製作,可加刻毛孩名字、生忌或一句話。" : "All hand-crafted. Engrave a name, date, or a single line."}
{products.map((p, i) => (
{icons[p.ic]}
{L(p.n, lang)}
{p.n.en}
{p.p}
))}
);
}
// ============= TESTIMONIALS =============
function Testimonials({ lang }) {
const data = [
{ t: { zh: "半夜兩點嗰通電話,佢哋一個鐘內就到咗門口。陪我哋坐咗十五分鐘先捧走 Toby,好感謝。", en: "A 2 a.m. call — they arrived within the hour. Sat with us for fifteen minutes before taking Toby. So grateful." }, n: "Carmen", sm: "w/ Toby · 拉布拉多" },
{ t: { zh: "最欣賞係全程冇 pushy sales。想加咩服務先介紹,唔夾硬推套餐。價錢清清楚楚。", en: "Zero pushy sales. They explained options only when asked. Transparent pricing end to end." }, n: "Alvin", sm: "w/ 妹妹 · 英短" },
{ t: { zh: "選咗水化,覺得比較平靜。收到骨灰嗰日,連佢嘅小爪印同一首琴音短片都整埋,喊得好慘。", en: "Chose aquamation — it felt calmer. On the return day, they included her paw print and a piano memorial video. Ugly cried." }, n: "Phoebe", sm: "w/ 點點 · 貴婦" },
];
return (
{lang === "zh" ? "預留給公司預約系統接入" : "Reserved for company booking integration"}
{lang === "zh"
? "將系統網址設定到 AFTERTAIL_BOOKING_EMBED_URL,或寫入 WordPress option aftertail_booking_embed_url,這裡會自動顯示正式預約介面。"
: "Set AFTERTAIL_BOOKING_EMBED_URL or the WordPress option aftertail_booking_embed_url, and the live booking interface will render here automatically."}
);
}
// ============= FAQ =============
function FAQ({ lang }) {
const items = [
{ q: { zh: "水化同火化有咩分別?", en: "What\u2019s the difference between aquamation and cremation?" }, a: { zh: "水化以溫水及微量鹼性溶液分解遺體,碳排放只係火化嘅 1/10,過程無煙無火;火化係傳統高溫分解。兩種都會保留骨灰。", en: "Aquamation uses warm water and a mild alkaline solution — 1/10th the carbon footprint of cremation, with no smoke or flame. Cremation uses traditional high heat. Both preserve ashes." } },
{ q: { zh: "需要預約定係可以即時接送?", en: "Do I need to book in advance?" }, a: { zh: "24 小時熱線即時接收。一般上門時間為 30 至 60 分鐘,視乎交通。夜間亦可。", en: "Our 24h hotline accepts immediate requests. Typical arrival is 30–60 minutes depending on traffic. Night service available." } },
{ q: { zh: "家人可以全程陪同嗎?", en: "Can family accompany the whole process?" }, a: { zh: "個別套餐可以全程在告別室陪同,或透過視像參與。集體套餐則於告別完成後交付骨灰。", en: "With the Individual package, family may accompany the whole farewell on-site or via live video. Communal packages include a farewell before the rite." } },
{ q: { zh: "最快幾時可以收返骨灰?", en: "When can I receive the ashes?" }, a: { zh: "個別套餐一般翌日即可領取或送回家。水化需時較長(約 6 小時),火化約 1-2 小時。", en: "Individual packages: next-day collection or delivery. Aquamation takes ~6 hours; cremation ~1–2 hours." } },
{ q: { zh: "有無特殊寵物服務?(如爬蟲、兔仔)", en: "Do you serve non-cat/dog pets?" }, a: { zh: "所有毛孩、羽毛、鱗片家人我哋都接收——兔、倉鼠、雀、龜、蜥蜴、魚類,都以同樣心意對待。", en: "All companion animals welcome — rabbits, hamsters, birds, turtles, lizards, fish. Same care, same dignity." } },
{ q: { zh: "點收費?有冇隱藏費用?", en: "How does pricing work? Any hidden fees?" }, a: { zh: "明碼實價。三套方案已包全部基本服務;紀念品可加購。離島、夜間、特別佈置會另行報價,預約時會清楚說明。", en: "Transparent pricing. All three packages include core services; keepsakes are add-ons. Outlying islands, late-night, and special settings are quoted clearly at booking." } },
];
return (
);
}
// ============= APP =============
// Read the active page section from the WordPress template.
// front-page.php sets data-section="home"; page.php sets it to the page slug.
// Anything unknown falls back to "home" so the site never renders blank.
function getSection() {
if (typeof document === "undefined") return "home";
const el = document.getElementById("app");
const s = el && el.dataset && el.dataset.section ? el.dataset.section : "home";
const valid = ["home", "about", "services", "pricing", "memorial", "booking", "faq", "contact"];
return valid.includes(s) ? s : "home";
}
function PageBody({ section, lang }) {
switch (section) {
case "about":
return ;
case "services":
return <>>;
case "pricing":
return ;
case "memorial":
return ;
case "booking":
return ;
case "faq":
return ;
case "contact":
return ;
case "home":
default:
return <>>;
}
}
function App() {
const [lang, setLang] = useState("zh");
const [menuOpen, setMenuOpen] = useState(false);
const section = getSection();
return (
<>