astrion-website/demo/mock/files/index.html
JOJO 64d0a377dc feat: 04版本控制动画 + 演示区5条真实对话mock + 文档同步沙箱重构
- 主页第4行特色动画(版本控制)及 01/02/03 动画迭代
- 演示区对话 mock 全部换为真实对话转换:日常使用(汽车对比新/整理周会速记)、
  StarRaid(弹幕调研/像素飞机设计)、开发实战(猫咪咖啡店多智能体)
- 子智能体 activity、消息截图媒体、文件卡片资源(docx/pdf/html)随站点发布
- sw.js: file/content 二进制 MIME、/api/conversations/media 路由、
  模型列表扩为 K3/V4-Flash/MiniMax-M3/GLM-5.2、CACHE v5
- content/ 同步 8-31 沙箱重构文档更新
2026-09-03 07:47:39 +08:00

1350 lines
72 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ひだまり猫茶房 · 向阳猫茶房</title>
<meta name="description" content="ひだまり猫茶房——阳光、咖啡与猫的治愈空间。预约到店,与十二位猫员工共度九十分钟慢时光。">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@400;500;700&family=LXGW+WenKai+TC&family=Zen+Old+Mincho:wght@400;700&family=Cormorant+Garamond:ital,wght@0,400;0,500;0,600;1,400&display=swap" rel="stylesheet">
<style>
/* ============ 配色:茶室陶土 ============ */
:root{
--bg: #F5F0E6; /* 生成り米白 */
--bg-soft: #FAF6EB; /* 米白·亮 */
--linen: #D6C6AF; /* 亚麻 */
--linen-soft:#E7DCC8; /* 亚麻·浅 */
--coffee: #6B4731; /* 焦茶 */
--coffee-deep:#59371F; /* 焦茶·沉 */
--bengara: #8F2E14; /* 弁柄赤 */
--bengara-hover:#7A2611;
--bengara-tint:#F0E2D9;
--ink: #3E2F23; /* 暖近黑 */
--ink-soft: #71604D; /* 次级文字 */
--line: #E5DCCB; /* 细线 */
--line-strong:#C9BBA1;
--cream: #F5F0E6;
--cream-dim: #D8CBB6;
--serif: "Noto Serif SC", "Songti SC", serif;
--wenkai: "LXGW WenKai TC", "Noto Serif SC", serif;
--mincho: "Zen Old Mincho", "Noto Serif SC", serif;
--num: "Cormorant Garamond", "Noto Serif SC", serif;
}
*{margin:0;padding:0;box-sizing:border-box}
html{scroll-behavior:smooth}
body{
background:var(--bg);
color:var(--ink);
font-family:var(--serif);
font-size:15.5px;
line-height:1.9;
-webkit-font-smoothing:antialiased;
overflow-x:hidden;
}
/* 纸张噪点 */
body::after{
content:"";position:fixed;inset:0;z-index:2000;pointer-events:none;opacity:.045;
background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='220' height='220' filter='url(%23n)'/%3E%3C/svg%3E");
}
::selection{background:var(--bengara);color:var(--cream)}
img,svg{display:block}
a{color:inherit;text-decoration:none}
button{font-family:inherit;cursor:pointer;background:none;border:none;color:inherit}
button:focus-visible,a:focus-visible,input:focus-visible{outline:2px solid var(--bengara);outline-offset:2px}
.num{font-family:var(--num)}
.wrap{max-width:1120px;margin:0 auto;padding:0 32px}
section{scroll-margin-top:88px;position:relative}
.sec{padding:96px 0}
.sec-head{margin-bottom:48px}
.sec-jp{
font-family:var(--mincho);font-size:12px;letter-spacing:.32em;
color:var(--bengara);margin-bottom:10px;
}
.sec-head h2{font-size:23px;font-weight:700;letter-spacing:.08em}
.sec-line{display:block;width:44px;height:1px;background:var(--line-strong);margin-top:16px}
.sec-sub{font-size:13px;color:var(--ink-soft);margin-top:12px;letter-spacing:.05em}
/* ============ 导航 ============ */
#site-nav{
position:sticky;top:0;z-index:100;
transition:background .3s ease,border-color .3s ease;
border-bottom:1px solid transparent;
}
#site-nav.scrolled{background:var(--bg);border-bottom-color:var(--line-strong)}
.nav-inner{display:flex;align-items:center;gap:12px;height:68px}
.brand{display:flex;align-items:center;gap:10px;flex-shrink:0}
.brand-name{font-weight:700;font-size:15px;letter-spacing:.1em;line-height:1.2}
.brand-sub{font-family:var(--num);font-size:10px;letter-spacing:.22em;color:var(--ink-soft)}
.nav-links{display:flex;align-items:center;gap:26px;margin-left:auto}
.nav-links a{font-size:13.5px;letter-spacing:.08em;color:var(--ink-soft);position:relative;padding:4px 0;transition:color .2s}
.nav-links a:hover{color:var(--bengara)}
.nav-links a::after{content:"";position:absolute;left:0;bottom:0;width:0;height:1px;background:var(--bengara);transition:width .25s}
.nav-links a:hover::after{width:100%}
.btn{
display:inline-flex;align-items:center;justify-content:center;gap:8px;
height:42px;padding:0 24px;border-radius:4px;
font-size:14px;letter-spacing:.12em;font-weight:500;
transition:background .2s,border-color .2s,color .2s,transform .15s;
white-space:nowrap;
}
.btn-primary{background:var(--bengara);color:var(--cream)}
.btn-primary:hover{background:var(--bengara-hover)}
.btn-ghost{border:1px solid var(--line-strong);color:var(--ink)}
.btn-ghost:hover{border-color:var(--ink)}
.btn-sm{height:36px;padding:0 18px;font-size:13px}
.nav-links a.btn-primary{color:var(--cream);padding:0 18px;font-size:13px}
.nav-links a.btn-primary:hover{color:var(--cream)}
#nav-toggle{display:none;width:40px;height:40px;margin-left:auto;flex-direction:column;align-items:center;justify-content:center;gap:6px}
#nav-toggle span{display:block;width:20px;height:1.5px;background:var(--ink);transition:transform .25s,opacity .25s}
#nav-toggle.open span:nth-child(1){transform:translateY(7.5px) rotate(45deg)}
#nav-toggle.open span:nth-child(2){opacity:0}
#nav-toggle.open span:nth-child(3){transform:translateY(-7.5px) rotate(-45deg)}
#nav-menu{
display:none;flex-direction:column;background:var(--bg);
border-bottom:1px solid var(--line-strong);padding:8px 32px 20px;
}
#nav-menu.open{display:flex}
#nav-menu a{padding:12px 0;font-size:14px;letter-spacing:.08em;border-bottom:1px solid var(--line)}
#nav-menu a:last-of-type{border-bottom:none}
#nav-menu .btn{margin-top:12px}
/* ============ Hero ============ */
#hero{min-height:100vh;display:flex;flex-direction:column}
.hero-space{height:36vh;min-height:180px}
.hero-body{position:relative;padding-bottom:80px}
.hero-grid{display:grid;grid-template-columns:minmax(0,1.05fr) minmax(0,.95fr);gap:48px;align-items:end}
.hero-overline{
font-family:var(--num);font-size:12px;letter-spacing:.28em;color:var(--ink-soft);
margin-bottom:26px;
}
.hero-overline em{font-style:italic;color:var(--bengara)}
.hero-title{
font-size:clamp(40px,5.4vw,56px);font-weight:700;line-height:1.5;letter-spacing:.06em;
}
.hero-wenkai{
font-family:var(--wenkai);font-size:19px;color:var(--ink-soft);
margin-top:26px;letter-spacing:.06em;
}
.hero-cta{display:flex;align-items:center;gap:28px;margin-top:44px}
.hero-link{font-size:13.5px;letter-spacing:.08em;color:var(--ink-soft);border-bottom:1px solid var(--line-strong);padding-bottom:3px;transition:color .2s,border-color .2s}
.hero-link:hover{color:var(--bengara);border-color:var(--bengara)}
.hero-status{
margin-top:22px;font-size:12px;letter-spacing:.1em;color:var(--ink-soft);
display:flex;align-items:center;gap:8px;
}
.hero-status .dot{width:6px;height:6px;border-radius:50%;background:var(--bengara);flex-shrink:0}
.hero-illus{position:relative}
.hero-illus svg{width:100%;max-width:420px;margin-left:auto}
.hero-vertical{
position:absolute;top:-30vh;right:6px;
writing-mode:vertical-rl;font-family:var(--mincho);
font-size:16px;letter-spacing:.42em;color:var(--coffee);
border-right:1px solid var(--line-strong);padding-right:14px;
height:300px;
}
.hero-scroll{
margin-top:auto;padding:34px 0 30px;display:flex;justify-content:center;
}
.hero-scroll span{
writing-mode:vertical-rl;font-family:var(--num);font-size:10px;letter-spacing:.3em;
color:var(--ink-soft);border-left:1px solid var(--line-strong);padding-left:10px;height:72px;
}
/* ============ 关于 ============ */
.about-lead{font-size:17px;line-height:2.1;max-width:620px;font-weight:500}
.about-lead .jp-word{font-family:var(--mincho);color:var(--bengara)}
.about-para{margin-top:18px;max-width:620px;color:var(--ink-soft)}
.about-band{
margin-top:56px;background:var(--linen-soft);
border-top:1px solid var(--line-strong);border-bottom:1px solid var(--line-strong);
}
.about-band-inner{display:grid;grid-template-columns:repeat(4,1fr);padding:40px 0}
.stat{text-align:center;padding:0 12px;border-right:1px solid var(--line-strong)}
.stat:last-child{border-right:none}
.stat b{display:block;font-family:var(--num);font-weight:600;font-size:38px;line-height:1.2;letter-spacing:.02em}
.stat span{font-size:12px;letter-spacing:.12em;color:var(--ink-soft)}
.assure{display:grid;grid-template-columns:repeat(3,1fr);gap:32px;margin-top:56px}
.assure-item{display:flex;gap:14px;align-items:flex-start}
.assure-item svg{flex-shrink:0;margin-top:4px}
.assure-item h3{font-size:15px;font-weight:500;letter-spacing:.05em;margin-bottom:4px}
.assure-item p{font-size:13px;color:var(--ink-soft);line-height:1.8}
/* ============ 度过方式(深底) ============ */
#way{background:var(--coffee);color:var(--cream)}
#way .sec-head h2{color:var(--cream)}
#way .sec-line{background:var(--cream-dim)}
#way .sec-sub{color:var(--cream-dim)}
.way-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:0;border-top:1px solid rgba(245,240,230,.22)}
.way-item{padding:36px 36px 8px;border-right:1px solid rgba(245,240,230,.22)}
.way-item:first-child{padding-left:0}
.way-item:last-child{border-right:none;padding-right:0}
.way-no{font-family:var(--mincho);font-size:13px;color:var(--linen);letter-spacing:.3em;display:block;margin-bottom:18px}
.way-item h3{font-size:19px;font-weight:700;letter-spacing:.1em;margin-bottom:14px}
.way-item p{font-size:13.5px;line-height:2;color:var(--cream-dim)}
/* ============ 今日出勤猫 ============ */
.cats-note{
display:flex;align-items:baseline;gap:16px;flex-wrap:wrap;
}
#cat-grid{
display:grid;grid-template-columns:repeat(4,1fr);gap:20px;margin-top:40px;
}
.cat-card{
position:relative;background:var(--bg-soft);
border:1px solid var(--line);border-radius:6px;
padding:22px 20px 20px;text-align:center;
transition:transform .25s ease,border-color .25s ease,background .25s ease;
}
.cat-card:hover{transform:translateY(-2px);border-color:var(--line-strong);background:#FCF9F0}
.cat-badge{
position:absolute;top:12px;right:12px;
font-size:11px;letter-spacing:.14em;line-height:1;height:22px;
display:inline-flex;align-items:center;padding:0 9px;border-radius:3px;
}
.cat-badge.on{background:var(--bengara);color:var(--cream)}
.cat-badge.off{border:1px solid var(--line-strong);color:var(--ink-soft)}
.cat-avatar{
width:108px;height:108px;margin:6px auto 16px;border-radius:50%;
background:#EFE7D6;border:1px solid var(--line-strong);
display:flex;align-items:center;justify-content:center;overflow:hidden;
}
.cat-avatar svg{width:88%;height:88%}
.cat-card h3{font-size:16px;font-weight:700;letter-spacing:.08em}
.cat-jp{font-family:var(--mincho);font-size:11px;font-weight:400;color:var(--ink-soft);letter-spacing:.1em;margin-left:6px}
.cat-breed{font-size:12px;color:var(--ink-soft);letter-spacing:.06em;margin-top:2px}
.cat-tags{display:flex;justify-content:center;gap:6px;flex-wrap:wrap;margin-top:12px;min-height:24px}
.cat-tags span{
font-size:11px;letter-spacing:.08em;line-height:1;height:22px;
display:inline-flex;align-items:center;padding:0 8px;
border:1px solid var(--line);border-radius:3px;color:var(--ink-soft);background:var(--bg);
}
.cat-bio{font-size:12.5px;color:var(--ink-soft);line-height:1.8;margin-top:12px;min-height:45px}
/* ============ 菜单 ============ */
.sign-block{max-width:660px}
.block-tag{
display:inline-flex;align-items:center;height:24px;padding:0 10px;
border:1px solid var(--bengara);border-radius:3px;
color:var(--bengara);font-size:12px;letter-spacing:.2em;margin-bottom:22px;
}
.menu-row{display:flex;align-items:baseline;gap:12px;padding:13px 0;border-bottom:1px solid var(--line)}
.menu-row:last-child{border-bottom:none}
.menu-name{font-size:15.5px;font-weight:500;letter-spacing:.05em;flex-shrink:0}
.menu-desc{font-size:12px;color:var(--ink-soft);letter-spacing:.03em}
.menu-dots{flex:1;border-bottom:1px dotted var(--line-strong);transform:translateY(-5px);min-width:24px}
.menu-price{font-family:var(--num);font-size:18px;font-weight:600;letter-spacing:.03em;flex-shrink:0}
.menu-price i{font-style:normal;font-size:12px;margin-right:2px;color:var(--ink-soft)}
.menu-cols{display:grid;grid-template-columns:repeat(3,1fr);gap:44px;margin-top:64px}
.menu-col-head{display:flex;align-items:center;gap:10px;padding-bottom:14px;border-bottom:1px solid var(--line-strong);margin-bottom:8px}
.menu-col-head h3{font-size:16px;font-weight:700;letter-spacing:.12em}
.menu-col-head .jp{font-family:var(--mincho);font-size:11px;color:var(--ink-soft);letter-spacing:.14em}
.menu-col .menu-row{padding:11px 0}
.menu-col .menu-name{font-size:14.5px}
.menu-foot{margin-top:28px;font-size:12px;color:var(--ink-soft);letter-spacing:.05em;display:flex;gap:8px;align-items:flex-start}
.menu-foot svg{flex-shrink:0;margin-top:5px}
/* ============ 环境 ============ */
#space{background:var(--linen)}
#space .wrap{position:relative}
.space-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:24px}
.space-item{background:var(--bg);border:1px solid var(--line-strong);border-radius:6px;overflow:hidden}
.space-item .scene{border-bottom:1px solid var(--line)}
.space-item .scene svg{width:100%;height:auto}
.space-item figcaption{padding:18px 20px 20px}
.space-item h3{font-size:15.5px;font-weight:700;letter-spacing:.08em;margin-bottom:6px}
.space-item p{font-size:13px;color:var(--ink-soft);line-height:1.85}
/* ============ 预约 ============ */
.reserve-grid{display:grid;grid-template-columns:minmax(0,1.15fr) minmax(0,.85fr);gap:56px;align-items:start}
.field{margin-bottom:26px}
.field-label{display:flex;align-items:baseline;gap:10px;font-size:14px;font-weight:500;letter-spacing:.08em;margin-bottom:12px}
.field-label .hint{font-size:11.5px;font-weight:400;color:var(--ink-soft);letter-spacing:.04em}
.form-err{display:none;font-size:12px;color:var(--bengara);margin-top:8px;letter-spacing:.04em}
.form-err.show{display:block}
/* 日历 */
.calendar{border:1px solid var(--line-strong);border-radius:6px;background:var(--bg-soft);padding:16px 16px 12px;max-width:400px}
.cal-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:10px}
.cal-title{font-size:14px;font-weight:500;letter-spacing:.1em}
.cal-title b{font-family:var(--num);font-size:16px;font-weight:600}
.cal-nav{display:flex;gap:6px}
.cal-nav button{
width:30px;height:30px;border:1px solid var(--line-strong);border-radius:4px;
display:flex;align-items:center;justify-content:center;transition:border-color .2s,background .2s;
}
.cal-nav button:hover:not(:disabled){border-color:var(--ink)}
.cal-nav button:disabled{opacity:.35;cursor:default}
.cal-week,.cal-days{display:grid;grid-template-columns:repeat(7,1fr);gap:2px}
.cal-week span{text-align:center;font-size:11px;color:var(--ink-soft);letter-spacing:.05em;height:28px;line-height:28px}
.cal-day{
height:38px;border-radius:4px;font-family:var(--num);font-size:15px;font-weight:500;
display:flex;align-items:center;justify-content:center;position:relative;
transition:background .15s,color .15s;
}
.cal-day:hover:not(:disabled):not(.sel){background:var(--linen-soft)}
.cal-day:disabled{color:#B9AC93;cursor:default}
.cal-day.closed::after{
content:"休";position:absolute;bottom:2px;right:3px;font-size:9px;
font-family:var(--serif);color:#B9AC93;letter-spacing:0;
}
.cal-day.sel{background:var(--bengara);color:var(--cream)}
.cal-day.sel::after{color:rgba(245,240,230,.75)}
/* 时段 */
.slots{display:grid;grid-template-columns:repeat(auto-fill,minmax(96px,1fr));gap:10px}
.slot{
height:52px;border:1px solid var(--line-strong);border-radius:4px;background:var(--bg-soft);
display:flex;flex-direction:column;align-items:center;justify-content:center;gap:1px;
transition:border-color .2s,background .2s;
}
.slot:hover:not(:disabled):not(.sel){border-color:var(--ink)}
.slot b{font-family:var(--num);font-size:16px;font-weight:600;letter-spacing:.03em}
.slot small{font-size:10.5px;color:var(--ink-soft);letter-spacing:.06em}
.slot.sel{border-color:var(--bengara);background:var(--bengara-tint)}
.slot.sel b{color:var(--bengara)}
.slot.sel small{color:var(--bengara)}
.slot:disabled{opacity:.45;cursor:default}
.slot:disabled small{color:var(--bengara)}
.slots-empty{
border:1px dashed var(--line-strong);border-radius:4px;height:52px;
display:flex;align-items:center;justify-content:center;
font-size:12.5px;color:var(--ink-soft);letter-spacing:.08em;
}
#seat-warn{display:none;font-size:12px;color:var(--bengara);margin-top:10px;letter-spacing:.04em}
/* 人数步进器 */
.stepper{display:inline-flex;align-items:center;border:1px solid var(--line-strong);border-radius:4px;background:var(--bg-soft);height:46px}
.stepper button{
width:46px;height:44px;font-size:18px;color:var(--ink-soft);
display:flex;align-items:center;justify-content:center;transition:color .2s,background .2s;
}
.stepper button:hover:not(:disabled){color:var(--bengara);background:var(--linen-soft)}
.stepper button:disabled{opacity:.35;cursor:default}
.stepper .val{
width:72px;text-align:center;font-family:var(--num);font-size:19px;font-weight:600;
border-left:1px solid var(--line);border-right:1px solid var(--line);height:100%;
display:flex;align-items:center;justify-content:center;gap:3px;
}
.stepper .val small{font-family:var(--serif);font-size:11px;font-weight:400;color:var(--ink-soft)}
/* 文本输入 */
.text-input{
width:100%;max-width:400px;height:46px;border:1px solid var(--line-strong);border-radius:4px;
background:var(--bg-soft);padding:0 14px;font-family:var(--serif);font-size:14.5px;
color:var(--ink);letter-spacing:.05em;transition:border-color .2s;
}
.text-input::placeholder{color:#B0A288;font-size:13px}
.text-input:focus{border-color:var(--bengara);outline:none}
.submit-row{margin-top:34px;display:flex;align-items:center;gap:18px;flex-wrap:wrap}
.form-fine{font-size:12px;color:var(--ink-soft);letter-spacing:.04em}
/* 守则 */
.rules{border-top:1px solid var(--line-strong)}
.rules h3{font-size:15px;font-weight:700;letter-spacing:.12em;padding:20px 0 6px}
.rules ol{list-style:none;counter-reset:rule}
.rules li{
counter-increment:rule;display:flex;gap:14px;align-items:flex-start;
padding:13px 0;border-bottom:1px solid var(--line);font-size:13.5px;line-height:1.85;
}
.rules li::before{
content:counter(rule,decimal-leading-zero);font-family:var(--num);
font-size:15px;font-weight:600;color:var(--bengara);flex-shrink:0;margin-top:2px;
}
/* 成功态 */
#reserve-done{display:none;border:1px solid var(--line-strong);border-radius:6px;background:var(--bg-soft);padding:40px 36px}
.done-head{display:flex;align-items:center;gap:14px;margin-bottom:8px}
.done-head h3{font-size:19px;font-weight:700;letter-spacing:.1em}
.done-no{font-size:12.5px;color:var(--ink-soft);letter-spacing:.06em;margin-bottom:24px}
.done-no b{font-family:var(--num);letter-spacing:.1em;color:var(--ink);font-size:14px}
.done-rows{border-top:1px solid var(--line-strong)}
.done-row{display:flex;justify-content:space-between;gap:20px;padding:11px 0;border-bottom:1px solid var(--line);font-size:14px}
.done-row .k{color:var(--ink-soft);letter-spacing:.08em;flex-shrink:0}
.done-row .v{text-align:right;letter-spacing:.04em}
.done-tips{margin:26px 0 30px;padding:16px 18px;background:var(--linen-soft);border-radius:4px}
.done-tips h4{font-size:13px;font-weight:700;letter-spacing:.14em;margin-bottom:8px}
.done-tips li{font-size:12.5px;color:var(--ink-soft);line-height:2;list-style:none;padding-left:14px;position:relative}
.done-tips li::before{content:"";position:absolute;left:0;top:13px;width:5px;height:1px;background:var(--bengara)}
/* ============ 交通 ============ */
.access-grid{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:56px;align-items:center}
.access-rows{border-top:1px solid var(--line-strong)}
.access-row{display:flex;gap:24px;padding:18px 0;border-bottom:1px solid var(--line);align-items:baseline}
.access-row .k{width:72px;flex-shrink:0;font-size:12px;letter-spacing:.2em;color:var(--ink-soft)}
.access-row .v{font-size:15px;line-height:1.9;letter-spacing:.04em}
.access-row .v .num{font-size:17px;font-weight:600;letter-spacing:.06em}
.access-row .v small{display:block;font-size:12px;color:var(--ink-soft);margin-top:2px}
.map-frame{border:1px solid var(--line-strong);border-radius:6px;background:var(--bg-soft);padding:10px}
.map-frame svg{width:100%;height:auto}
/* ============ 页脚 ============ */
footer{background:var(--coffee);color:var(--cream);padding:64px 0 0}
.foot-top{display:flex;align-items:flex-start;gap:48px;flex-wrap:wrap}
.foot-brand{max-width:300px}
.foot-brand .brand-name{font-size:17px}
.foot-brand .brand-sub{color:var(--cream-dim)}
.foot-slogan{font-family:var(--mincho);font-size:12.5px;letter-spacing:.24em;color:var(--cream-dim);margin-top:16px}
.foot-nav{display:flex;gap:56px;margin-left:auto;flex-wrap:wrap}
.foot-col h4{font-size:12px;letter-spacing:.22em;color:var(--linen);margin-bottom:14px;font-weight:500}
.foot-col a{display:block;font-size:13px;color:var(--cream-dim);padding:5px 0;letter-spacing:.06em;transition:color .2s}
.foot-col a:hover{color:var(--cream)}
.sns{display:flex;gap:10px}
.sns a{
width:38px;height:38px;border:1px solid rgba(245,240,230,.3);border-radius:4px;
display:flex;align-items:center;justify-content:center;transition:border-color .2s,background .2s;
}
.sns a:hover{border-color:var(--cream);background:rgba(245,240,230,.08)}
.foot-bottom{
margin-top:52px;border-top:1px solid rgba(245,240,230,.18);
padding:20px 0 24px;display:flex;justify-content:space-between;gap:16px;flex-wrap:wrap;
font-size:11.5px;letter-spacing:.1em;color:var(--cream-dim);
}
/* ============ 滚动渐显 ============ */
.reveal{opacity:0;transform:translateY(14px);transition:opacity .7s ease,transform .7s ease}
.reveal.is-visible{opacity:1;transform:none}
/* ============ 响应式 ============ */
@media (max-width:1080px){
#cat-grid{grid-template-columns:repeat(2,1fr)}
.menu-cols{gap:32px}
}
@media (max-width:920px){
.hero-grid{grid-template-columns:1fr;gap:24px}
.hero-illus svg{margin:0 auto}
.hero-vertical{right:0}
.reserve-grid,.access-grid{grid-template-columns:1fr;gap:48px}
.assure{grid-template-columns:1fr;gap:24px}
.about-band-inner{grid-template-columns:repeat(2,1fr);row-gap:28px}
.stat:nth-child(2){border-right:none}
.way-grid{grid-template-columns:1fr;border-top:none}
.way-item{border-right:none;border-top:1px solid rgba(245,240,230,.22);padding:28px 0}
.space-grid{grid-template-columns:1fr;max-width:480px}
}
@media (max-width:860px){
.nav-links{display:none}
#nav-toggle{display:flex}
}
@media (max-width:640px){
.wrap{padding:0 20px}
.sec{padding:72px 0}
#cat-grid{grid-template-columns:1fr}
.menu-cols{grid-template-columns:1fr;gap:40px;margin-top:52px}
.hero-space{height:28vh}
.hero-wenkai{font-size:17px}
.slots{grid-template-columns:repeat(3,1fr)}
#reserve-done{padding:30px 22px}
.foot-nav{margin-left:0;gap:36px}
}
@media (prefers-reduced-motion:reduce){
html{scroll-behavior:auto}
.reveal{opacity:1;transform:none;transition:none}
*{transition-duration:.01ms !important}
}
</style>
</head>
<body>
<!-- 印章做旧 filter -->
<svg width="0" height="0" style="position:absolute" aria-hidden="true">
<defs>
<filter id="seal-rough" x="-10%" y="-10%" width="120%" height="120%">
<feTurbulence type="fractalNoise" baseFrequency="0.09" numOctaves="2" result="n"/>
<feDisplacementMap in="SourceGraphic" in2="n" scale="2.4"/>
</filter>
</defs>
</svg>
<!-- ============ 1. 导航 ============ -->
<header id="site-nav">
<div class="wrap nav-inner">
<a href="#hero" class="brand" aria-label="ひだまり猫茶房 首页">
<svg width="26" height="26" viewBox="0 0 24 24" fill="none" aria-hidden="true">
<path d="M12 21.5 C7.6 21.5 5 18.6 5 15 C5 11.8 6.7 8.9 8.6 6.9 L7.6 2.6 L11 5.2 C11.65 5 12.35 5 13 5.2 L16.4 2.6 L15.4 6.9 C17.3 8.9 19 11.8 19 15 C19 18.6 16.4 21.5 12 21.5 Z" fill="#3E2F23"/>
<path d="M18.6 19.4 C21.4 19.8 22.6 17.2 21 15.4" stroke="#3E2F23" stroke-width="1.5" stroke-linecap="round"/>
</svg>
<span>
<span class="brand-name">ひだまり猫茶房</span><br>
<span class="brand-sub">HIDAMARI CAT CAFÉ</span>
</span>
<svg width="30" height="30" viewBox="0 0 64 64" style="transform:rotate(-4deg);margin-left:4px" aria-hidden="true">
<g filter="url(#seal-rough)">
<rect x="7" y="7" width="50" height="50" rx="5" fill="#8F2E14"/>
<text x="32" y="42" text-anchor="middle" font-size="27" fill="#F5F0E6" font-family="Zen Old Mincho, serif"></text>
</g>
</svg>
</a>
<nav class="nav-links" aria-label="主导航">
<a href="#about">关于</a>
<a href="#cats">今日猫咪</a>
<a href="#menu">菜单</a>
<a href="#space">环境</a>
<a href="#access">交通</a>
<a href="#reserve" class="btn btn-primary btn-sm">预约到店</a>
</nav>
<button id="nav-toggle" aria-label="打开菜单" aria-expanded="false">
<span></span><span></span><span></span>
</button>
</div>
<nav id="nav-menu" aria-label="移动端导航">
<a href="#about">关于</a>
<a href="#cats">今日猫咪</a>
<a href="#menu">菜单</a>
<a href="#space">环境</a>
<a href="#access">交通</a>
<a href="#reserve" class="btn btn-primary">预约到店</a>
</nav>
</header>
<!-- ============ 2. Hero ============ -->
<section id="hero">
<div class="hero-space"></div>
<div class="wrap hero-body">
<p class="hero-vertical" aria-hidden="true">ひだまりで、猫と、一息。</p>
<div class="hero-grid">
<div>
<p class="hero-overline">HIDAMARI CAT CAFÉ <em>·</em> 向阳猫茶房 <em>·</em> SINCE 2019</p>
<h1 class="hero-title">有猫在的地方,<br>时间就会变慢。</h1>
<p class="hero-wenkai">泡一杯咖啡,等一只猫路过你的下午。</p>
<div class="hero-cta">
<a href="#reserve" class="btn btn-primary">预约到店</a>
<a href="#cats" class="hero-link">先看看今天谁上班</a>
</div>
<p class="hero-status"><span class="dot"></span><span id="hero-status">本日营业中 · 11:0020:00</span></p>
</div>
<div class="hero-illus" aria-hidden="true">
<!-- 手绘墨线:窗台上晒太阳的猫 -->
<svg viewBox="0 0 340 300" fill="none">
<!-- 太阳 -->
<g stroke="#8F2E14" stroke-width="2.5" stroke-linecap="round" opacity=".85">
<circle cx="266" cy="66" r="26" fill="none"/>
<path d="M266 26 v-12 M266 118 v-10 M306 66 h12 M214 66 h12 M294 38 l8-8 M230 102 l8-8 M294 94 l8 8 M230 30 l8 8" transform="translate(0,0)"/>
</g>
<!-- 猫:侧坐 -->
<g stroke="#3E2F23" stroke-width="3" stroke-linecap="round" stroke-linejoin="round">
<!-- 尾巴(贴地环绕) -->
<path d="M92 238 C58 250 34 242 33 226 C32 210 48 199 68 203 C88 207 106 220 116 236" />
<!-- 背部 -->
<path d="M96 240 C74 232 64 206 71 176 C78 144 98 114 130 96"/>
<!-- 耳朵 -->
<path d="M122 62 L115 34 L141 50"/>
<path d="M146 54 L153 28 L168 52"/>
<!-- 头顶到脸 -->
<path d="M130 96 C112 88 104 74 110 62 C115 52 128 48 140 52 C154 56 162 68 158 82 C156 90 150 96 142 100"/>
<!-- 口鼻 -->
<path d="M112 82 q-4 2 -3 5" stroke-width="2.4"/>
<!-- 眯起的眼睛 -->
<path d="M120 72 Q127 67 134 72" stroke-width="2.6"/>
<!-- 胡须 -->
<path d="M108 88 Q94 86 82 82 M108 93 Q93 93 81 94 M108 98 Q95 101 85 106" stroke-width="1.8" opacity=".8"/>
<!-- 胸口与前腿 -->
<path d="M142 100 C156 116 162 152 158 192 C156 216 150 234 144 240"/>
<path d="M126 176 C128 200 128 224 126 240" stroke-width="2.4"/>
<!-- 底线 -->
<path d="M96 240 C112 247 132 247 144 240"/>
<!-- 背部墨线点缀 -->
<path d="M84 160 q10 -6 18 -4 M80 180 q9 -5 17 -3" stroke-width="2" opacity=".55"/>
</g>
<!-- 咖啡杯 -->
<g stroke="#3E2F23" stroke-width="2.5" stroke-linecap="round">
<path d="M198 222 h34 v12 q0 10 -10 10 h-14 q-10 0 -10 -10 z" fill="#FAF6EB"/>
<path d="M232 226 q12 2 0 10" />
<path d="M206 214 q3 -6 0 -11 M216 214 q3 -6 0 -11" stroke-width="2" opacity=".7"/>
</g>
<!-- 窗台 -->
<path d="M24 252 H316" stroke="#3E2F23" stroke-width="2" stroke-linecap="round"/>
<path d="M60 259 H280" stroke="#3E2F23" stroke-width="1" opacity=".4"/>
</svg>
</div>
</div>
</div>
<div class="hero-scroll"><span>SCROLL</span></div>
</section>
<!-- ============ 3. 关于 ============ -->
<section id="about" class="sec">
<div class="wrap">
<div class="sec-head reveal">
<p class="sec-jp">はじめに</p>
<h2>初见 · 关于我们</h2>
<span class="sec-line"></span>
</div>
<p class="about-lead reveal"><span class="jp-word">ひだまり</span>」在日语里意为"向阳处"——<br>我们想做的,是让城市里疲惫的人,有一个被阳光和猫接住的地方。</p>
<p class="about-para reveal">2019 年春天,我们把临街的老房子改成了一间洒满阳光的茶房。这里没有 KPI十二位猫员工自由上下班困了睡窗边醒了巡吧台。我们只负责把咖啡冲好、把阳光留好等你推门进来。</p>
</div>
<div class="about-band reveal" style="margin-top:64px">
<div class="wrap about-band-inner">
<div class="stat"><b>2019</b><span>开业年份</span></div>
<div class="stat"><b>12<i style="font-style:normal;font-size:20px"></i></b><span>在职猫员工</span></div>
<div class="stat"><b>90<i style="font-style:normal;font-size:20px"> 分钟</i></b><span>一场的慢时光</span></div>
<div class="stat"><b>28<i style="font-style:normal;font-size:20px"></i></b><span>阳光座位</span></div>
</div>
</div>
<div class="wrap">
<div class="assure">
<div class="assure-item reveal">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#8F2E14" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M12 3 L19 5.5 V11 C19 16 15.5 19.5 12 21 C8.5 19.5 5 16 5 11 V5.5 Z"/><path d="M9 11.5 L11.2 13.7 L15.5 9.4"/>
</svg>
<div><h3>全员定期体检与疫苗</h3><p>猫员工健康档案在前台公示,欢迎查阅。</p></div>
</div>
<div class="assure-item reveal">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#8F2E14" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M4 12 C4 7.5 7.5 4 12 4 C16.5 4 20 7.5 20 12"/><path d="M8 12 C8 9.8 9.8 8 12 8 C14.2 8 16 9.8 16 12"/><path d="M12 12 V20 M12 16 H18 M12 20 H16"/>
</svg>
<div><h3>每日消毒 · 新风常开</h3><p>吧台与座席每场消毒,空气和阳光一起流通。</p></div>
</div>
<div class="assure-item reveal">
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#8F2E14" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<circle cx="12" cy="12" r="8.5"/><path d="M12 7 V12 L15.5 14"/>
</svg>
<div><h3>轮班休息制</h3><p>猫员工每日轮班、定时下班,睡觉也是正经工作。</p></div>
</div>
</div>
</div>
</section>
<!-- ============ 4. 店内度过方式(深底) ============ -->
<section id="way" class="sec">
<div class="wrap">
<div class="sec-head reveal">
<p class="sec-jp" style="color:var(--linen)">過ごし方</p>
<h2>店内度过方式</h2>
<span class="sec-line"></span>
</div>
<div class="way-grid">
<div class="way-item reveal">
<span class="way-no">一 —</span>
<h3>一个人的发呆时间</h3>
<p>靠窗的单人座,配一杯手冲,和一段开了免打扰的下午。书可以带,也可以不带。</p>
</div>
<div class="way-item reveal">
<span class="way-no">二 —</span>
<h3>两个人的轻声细语</h3>
<p>矮桌与蒲团,说话声会自然放低。猫睡在你们中间,话题也变得柔软。</p>
</div>
<div class="way-item reveal">
<span class="way-no">三 —</span>
<h3>和猫的无所事事</h3>
<p>什么都不做也没关系。无所事事这件事,猫最擅长——跟着学就好。</p>
</div>
</div>
</div>
</section>
<!-- ============ 5. 今日出勤猫 ============ -->
<section id="cats" class="sec">
<div class="wrap">
<div class="sec-head reveal">
<p class="sec-jp">今日の出勤</p>
<h2>今日出勤猫</h2>
<span class="sec-line"></span>
<p class="sec-sub"><span id="today-label" class="num"></span> · <span id="duty-count"></span> · 轮班制,实际出勤以到店为准</p>
</div>
<div id="cat-grid">
<noscript><p style="color:var(--ink-soft);font-size:13px">猫咪名册需要启用 JavaScript 才能翻页查看。</p></noscript>
</div>
</div>
</section>
<!-- ============ 6. 菜单 ============ -->
<section id="menu" class="sec" style="padding-top:40px">
<div class="wrap">
<div class="sec-head reveal">
<p class="sec-jp">お品書き</p>
<h2>菜单</h2>
<span class="sec-line"></span>
</div>
<div class="sign-block reveal">
<span class="block-tag">招牌猫咪特调</span>
<div class="menu-row"><span class="menu-name">肉球拿铁</span><span class="menu-dots"></span><span class="menu-price"><i>¥</i>38</span></div>
<p class="menu-desc" style="margin:2px 0 10px">草莓肉球棉花糖,蹲在绵密奶泡上晒太阳。</p>
<div class="menu-row"><span class="menu-name">橘猫气泡美式</span><span class="menu-dots"></span><span class="menu-price"><i>¥</i>32</span></div>
<p class="menu-desc" style="margin:2px 0 10px">浅烘柑橘调加苏打,像橘猫一样明亮不黏人。</p>
<div class="menu-row"><span class="menu-name">猫尾苏打</span><span class="menu-dots"></span><span class="menu-price"><i>¥</i>36</span></div>
<p class="menu-desc" style="margin:2px 0 10px">蜂蜜柚子气泡,杯口挂一条卷卷的"猫尾"柠檬皮。</p>
<div class="menu-row"><span class="menu-name">呼噜焙茶奶茶</span><span class="menu-dots"></span><span class="menu-price"><i>¥</i>34</span></div>
<p class="menu-desc" style="margin:2px 0 2px">焙茶底配黑糖珍珠,醇厚得像猫在耳边的呼噜声。</p>
</div>
<div class="menu-cols">
<div class="menu-col reveal">
<div class="menu-col-head">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#6B4731" stroke-width="1.7" stroke-linecap="round" aria-hidden="true"><path d="M5 9 h11 v6 a4 4 0 0 1 -4 4 h-3 a4 4 0 0 1 -4 -4 z"/><path d="M16 10 q5 1 0 5"/><path d="M8 5.5 q1 -1.5 0 -2.5 M12 5.5 q1 -1.5 0 -2.5"/></svg>
<h3>咖啡</h3><span class="jp">コーヒー</span>
</div>
<div class="menu-row"><span class="menu-name">手冲单品</span><span class="menu-dots"></span><span class="menu-price"><i>¥</i>42</span></div>
<div class="menu-row"><span class="menu-name">拿铁</span><span class="menu-dots"></span><span class="menu-price"><i>¥</i>34</span></div>
<div class="menu-row"><span class="menu-name">美式</span><span class="menu-dots"></span><span class="menu-price"><i>¥</i>28</span></div>
<div class="menu-row"><span class="menu-name">焦糖玛奇朵</span><span class="menu-dots"></span><span class="menu-price"><i>¥</i>36</span></div>
<div class="menu-row"><span class="menu-name">焙茶拿铁</span><span class="menu-dots"></span><span class="menu-price"><i>¥</i>36</span></div>
</div>
<div class="menu-col reveal">
<div class="menu-col-head">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#6B4731" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 20 h14 v-6 a7 7 0 0 0 -14 0 z"/><path d="M12 7 v-2 M12 5 a1 1 0 1 0 0 -0.1"/><path d="M9 13.5 a1.1 1.1 0 1 0 0.1 0 M15 13.5 a1.1 1.1 0 1 0 0.1 0"/></svg>
<h3>甜点</h3><span class="jp">焼き菓子</span>
</div>
<div class="menu-row"><span class="menu-name">猫爪芝士蛋糕</span><span class="menu-dots"></span><span class="menu-price"><i>¥</i>32</span></div>
<div class="menu-row"><span class="menu-name">铜锣烧</span><span class="menu-dots"></span><span class="menu-price"><i>¥</i>22</span></div>
<div class="menu-row"><span class="menu-name">抹茶生乳卷</span><span class="menu-dots"></span><span class="menu-price"><i>¥</i>28</span></div>
<div class="menu-row"><span class="menu-name">当日烤点心</span><span class="menu-dots"></span><span class="menu-price"><i>¥</i>24</span></div>
</div>
<div class="menu-col reveal">
<div class="menu-col-head">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#6B4731" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 12 C6 8 10 6.5 14 7.5 C17 8.3 19.5 10.5 21 12 C19.5 13.5 17 15.7 14 16.5 C10 17.5 6 16 3 12 Z"/><path d="M14 7.5 L17 4 M14 16.5 L17 20"/><circle cx="7" cy="11" r="0.6" fill="#6B4731"/></svg>
<h3>猫咪零食</h3><span class="jp">猫のおやつ</span>
</div>
<div class="menu-row"><span class="menu-name">小鱼干拼盘</span><span class="menu-dots"></span><span class="menu-price"><i>¥</i>15</span></div>
<div class="menu-row"><span class="menu-name">冻干鸡肉粒</span><span class="menu-dots"></span><span class="menu-price"><i>¥</i>18</span></div>
<div class="menu-row"><span class="menu-name">猫草杯</span><span class="menu-dots"></span><span class="menu-price"><i>¥</i>12</span></div>
<div class="menu-row"><span class="menu-name">肉泥条条</span><span class="menu-dots"></span><span class="menu-price"><i>¥</i>16</span></div>
</div>
</div>
<p class="menu-foot reveal">
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="#8F2E14" stroke-width="1.8" stroke-linecap="round" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 8 v.1 M12 11 v5"/></svg>
猫咪零食仅供店内猫员工享用,请在店员陪同下投喂;人类请勿偷吃,小鱼干也不行。
</p>
</div>
</section>
<!-- ============ 7. 环境 ============ -->
<section id="space" class="sec">
<div class="wrap">
<div class="sec-head reveal">
<p class="sec-jp">店内の様子</p>
<h2>环境</h2>
<span class="sec-line"></span>
</div>
<div class="space-grid">
<figure class="space-item reveal">
<div class="scene">
<svg viewBox="0 0 220 150" fill="none" stroke="#3E2F23" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-label="吧台插画">
<!-- 吊柜与杯 -->
<path d="M28 34 H120" opacity=".8"/>
<path d="M40 34 v-8 h12 v8 M62 34 v-8 h12 v8 M84 34 v-8 h12 v8" opacity=".7"/>
<!-- 咖啡机 -->
<rect x="34" y="60" width="38" height="26" rx="2" fill="#F5F0E6"/>
<path d="M44 86 v-8 M62 86 v-8 M50 92 h10" />
<path d="M40 54 q3 -5 0 -9 M48 54 q3 -5 0 -9" opacity=".6" stroke-width="1.8"/>
<!-- 台面 -->
<path d="M18 92 H202" stroke-width="2.6"/>
<path d="M26 92 V136 M194 92 V136" opacity=".8"/>
<path d="M26 112 H194" opacity=".45"/>
<!-- 吧台上的猫 -->
<g stroke-width="2">
<path d="M128 92 c-8 0 -13 -6 -12 -13 c1 -6 6 -10 12 -10 c7 0 12 5 12 11 c0 7 -5 12 -12 12 Z" fill="#F5F0E6"/>
<path d="M120 73 l-3 -8 l8 4 M134 73 l4 -8 l3 8" />
<path d="M124 82 q2 2 4 0 M132 82 q2 2 4 0" stroke-width="1.6"/>
<path d="M140 88 q8 2 6 -4" stroke-width="1.8"/>
</g>
<!-- 高脚凳 -->
<path d="M158 104 h26 M162 104 l-5 32 M180 104 l5 32 M160 124 h24" opacity=".85"/>
<!-- 吊灯 -->
<path d="M168 14 v16 M160 36 a9 9 0 0 1 16 0 z" opacity=".8"/>
</svg>
</div>
<figcaption>
<h3>吧台</h3>
<p>「猫禁止上桌」的规定,从来没有执行成功过。点单时请注意头顶的监督视线。</p>
</figcaption>
</figure>
<figure class="space-item reveal">
<div class="scene">
<svg viewBox="0 0 220 150" fill="none" stroke="#3E2F23" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-label="窗边猫爬架插画">
<!---->
<rect x="22" y="20" width="72" height="62" fill="#F5F0E6"/>
<path d="M58 20 V82 M22 51 H94" opacity=".7"/>
<circle cx="40" cy="36" r="7" stroke="#8F2E14" stroke-width="1.8"/>
<!-- 猫爬架 -->
<path d="M150 138 V40" stroke-width="2.6"/>
<path d="M122 62 h56 M128 96 h50 M116 138 h68" stroke-width="2.4"/>
<path d="M138 62 v-6 M162 96 v-8" opacity=".6"/>
<!-- 顶层猫团 -->
<g stroke-width="2">
<path d="M132 62 c0 -9 8 -15 17 -14 c8 1 13 7 12 14 z" fill="#F5F0E6"/>
<path d="M138 50 l-2 -7 l7 4 M154 49 l3 -7 l4 7"/>
<path d="M159 58 q6 3 3 8" stroke-width="1.8"/>
</g>
<!-- 悬挂玩具 -->
<path d="M186 40 v20" opacity=".6"/>
<circle cx="186" cy="66" r="4" opacity=".8"/>
<!-- 地面 -->
<path d="M16 138 H204" stroke-width="2"/>
</svg>
</div>
<figcaption>
<h3>窗边猫爬架</h3>
<p>下午三点钟,这里会长出三四只晒太阳的猫。想坐窗边,请赶早。</p>
</figcaption>
</figure>
<figure class="space-item reveal">
<div class="scene">
<svg viewBox="0 0 220 150" fill="none" stroke="#3E2F23" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-label="榻榻米座席插画">
<!-- 榻榻米 -->
<rect x="18" y="100" width="92" height="34" fill="#F5F0E6"/>
<rect x="110" y="100" width="92" height="34" fill="#F5F0E6"/>
<path d="M64 100 v34 M156 100 v34" opacity=".5"/>
<!-- 矮桌 -->
<path d="M66 76 h84 M74 76 v18 M142 76 v18" stroke-width="2.4"/>
<!-- 茶杯 -->
<path d="M96 66 h18 v7 q0 6 -9 6 q-9 0 -9 -6 z" fill="#F5F0E6" stroke-width="1.8"/>
<path d="M101 60 q2 -4 0 -7 M109 60 q2 -4 0 -7" opacity=".6" stroke-width="1.6"/>
<!-- 坐垫 -->
<path d="M28 94 q0 -8 16 -8 q16 0 16 8 z" fill="#E7DCC8"/>
<path d="M162 94 q0 -8 16 -8 q16 0 16 8 z" fill="#E7DCC8"/>
<!-- 蜷睡的猫 -->
<g stroke-width="2">
<circle cx="178" cy="86" r="11" fill="#F5F0E6"/>
<path d="M170 80 l-3 -6 l7 3 M185 79 l4 -6 l2 7"/>
<path d="M186 90 q6 4 2 8 M171 89 q-5 3 -2 7" stroke-width="1.7"/>
<path d="M174 85 q2 2 4 0" stroke-width="1.6"/>
</g>
<!-- 挂画 -->
<rect x="30" y="22" width="34" height="44" fill="#F5F0E6" opacity=".9"/>
<path d="M40 52 q6 -14 14 -16" opacity=".7" stroke-width="1.8"/>
<circle cx="52" cy="34" r="3.5" stroke="#8F2E14" stroke-width="1.6"/>
</svg>
</div>
<figcaption>
<h3>榻榻米座席</h3>
<p>脱鞋入座,适合久坐。也适合被猫选中,成为它今天下午的午睡地点。</p>
</figcaption>
</figure>
</div>
</div>
</section>
<!-- ============ 8. 预约 ============ -->
<section id="reserve" class="sec">
<div class="wrap">
<div class="sec-head reveal">
<p class="sec-jp">ご予約</p>
<h2>到店预约</h2>
<span class="sec-line"></span>
</div>
<div class="reserve-grid">
<div>
<form id="reserve-form" novalidate>
<div class="field">
<p class="field-label">到店日期 <span class="hint">每周二定休 · 可约两个月内</span></p>
<div class="calendar">
<div class="cal-head">
<p class="cal-title"><b id="cal-year" class="num">2026</b><b id="cal-month" class="num">9</b></p>
<div class="cal-nav">
<button type="button" id="cal-prev" aria-label="上个月"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M15 5 L8 12 L15 19"/></svg></button>
<button type="button" id="cal-next" aria-label="下个月"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M9 5 L16 12 L9 19"/></svg></button>
</div>
</div>
<div class="cal-week" aria-hidden="true"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></div>
<div class="cal-days" id="cal-days"></div>
</div>
<p class="form-err" id="err-date">请选择到店日期</p>
</div>
<div class="field">
<p class="field-label">入店时段 <span class="hint">每场 90 分钟 · 最后入店 19:00</span></p>
<div class="slots" id="slot-list"></div>
<p class="form-err" id="err-slot">请选择入店时段</p>
<p id="seat-warn" role="alert">该时段余位不足,请减少人数或更换时段</p>
</div>
<div class="field">
<p class="field-label">人数 <span class="hint">每场限 4 人</span></p>
<div class="stepper">
<button type="button" id="people-minus" aria-label="减少人数" disabled></button>
<span class="val"><span id="people-num" class="num">1</span><small></small></span>
<button type="button" id="people-plus" aria-label="增加人数"></button>
</div>
</div>
<div class="field">
<p class="field-label">称呼</p>
<input class="text-input" type="text" id="f-name" placeholder="怎么称呼您" autocomplete="name" maxlength="12">
<p class="form-err" id="err-name">请填写称呼(至少两个字)</p>
</div>
<div class="field">
<p class="field-label">手机号 <span class="hint">仅用于到店确认</span></p>
<input class="text-input num" type="tel" id="f-phone" placeholder="11 位手机号" autocomplete="tel" maxlength="11" inputmode="numeric">
<p class="form-err" id="err-phone">请填写正确的 11 位手机号</p>
</div>
<div class="submit-row">
<button type="submit" class="btn btn-primary" id="submit-btn">确认预约</button>
<span class="form-fine">预约免费,到店后按低消点单即可。</span>
</div>
</form>
<div id="reserve-done" aria-live="polite">
<div class="done-head">
<svg width="26" height="26" viewBox="0 0 24 24" fill="none" stroke="#8F2E14" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9.5"/><path d="M8 12.5 L11 15.5 L16.5 9.5"/></svg>
<h3>预约成功</h3>
</div>
<p class="done-no">预约编号 <b id="done-no" class="num"></b> · 请截图或记下编号,到店出示</p>
<div class="done-rows">
<div class="done-row"><span class="k">日期</span><span class="v" id="done-date"></span></div>
<div class="done-row"><span class="k">时段</span><span class="v num" id="done-slot"></span></div>
<div class="done-row"><span class="k">人数</span><span class="v" id="done-people"></span></div>
<div class="done-row"><span class="k">称呼</span><span class="v" id="done-name"></span></div>
<div class="done-row"><span class="k">手机号</span><span class="v num" id="done-phone"></span></div>
</div>
<div class="done-tips">
<h4>到店须知</h4>
<ul>
<li>请提前 5 分钟到店,迟到超过 15 分钟席位将释放给现场客人</li>
<li>每场 90 分钟,低消一杯饮品</li>
<li>如需改期或取消,请提前一天来电 028-8765-4321</li>
<li>进门请先洗手消毒,猫员工会逐一检阅你的手</li>
</ul>
</div>
<button type="button" class="btn btn-ghost" id="again-btn">再约一单</button>
</div>
</div>
<aside class="reveal">
<div class="rules">
<h3>入店守则</h3>
<ol>
<li>每场次 90 分钟,请按预约时段到店入座。</li>
<li>低消一杯饮品,猫咪零食另计。</li>
<li>12 岁以下的小朋友,需成人陪同入店。</li>
<li>请不要抱猫、追猫——等它们自己走过来,才算数。</li>
<li>拍照请关闭闪光灯与快门声。</li>
<li>睡眠中的猫员工非请勿扰,睡觉也是它们的工作。</li>
</ol>
</div>
</aside>
</div>
</div>
</section>
<!-- ============ 9. 交通与营业时间 ============ -->
<section id="access" class="sec" style="padding-top:40px">
<div class="wrap">
<div class="sec-head reveal">
<p class="sec-jp">アクセス</p>
<h2>交通与营业时间</h2>
<span class="sec-line"></span>
</div>
<div class="access-grid">
<div class="access-rows reveal">
<div class="access-row"><span class="k">地址</span><span class="v">成都市锦江区向阳路 27 号 2 楼<small>地铁 3 号线「向阳路站」C 口出站,步行约 5 分钟</small></span></div>
<div class="access-row"><span class="k">营业时间</span><span class="v"><span class="num">11:00 20:00</span><small>最后入店 19:00 · 每周二定休(猫员工公休日)</small></span></div>
<div class="access-row"><span class="k">电话</span><span class="v"><span class="num">028-8765-4321</span><small>预约改期、包场与猫咪领养咨询,请来电</small></span></div>
</div>
<div class="map-frame reveal" aria-label="简易地图插画">
<svg viewBox="0 0 300 210" fill="none" stroke="#3E2F23" stroke-linecap="round" aria-hidden="true">
<!-- 街区 -->
<path d="M0 62 H300 M0 128 H300 M0 178 H300" stroke-width="2" opacity=".55"/>
<path d="M70 0 V210 M168 0 V210 M238 0 V210" stroke-width="2" opacity=".55"/>
<!-- 绿地 -->
<rect x="70" y="128" width="98" height="50" fill="#E7DCC8" stroke="none"/>
<path d="M96 152 q10 -14 24 -10 M124 162 q8 -8 18 -6" stroke-width="1.6" opacity=".6"/>
<!-- 地铁站 -->
<circle cx="70" cy="62" r="10" fill="#F5F0E6" stroke-width="2"/>
<text x="70" y="67" text-anchor="middle" font-size="11" fill="#3E2F23" stroke="none" font-family="Noto Serif SC, serif"></text>
<text x="52" y="46" font-size="9.5" fill="#71604D" stroke="none" font-family="Noto Serif SC, serif" letter-spacing="1">3号线 · 向阳路站</text>
<!-- 路名 -->
<text x="180" y="120" font-size="9.5" fill="#71604D" stroke="none" font-family="Noto Serif SC, serif" letter-spacing="2">向 阳 路</text>
<!-- 步行路径 -->
<path d="M80 66 C110 74 130 82 158 88" stroke="#8F2E14" stroke-width="1.6" stroke-dasharray="4 5"/>
<!-- 店 pin -->
<g>
<path d="M168 104 c-9 0 -15 -6.5 -15 -14 a15 15 0 1 1 30 0 c0 7.5 -6 14 -15 14 z" fill="#8F2E14" stroke="none"/>
<circle cx="168" cy="89" r="6" fill="#F5F0E6" stroke="none"/>
<path d="M165.5 89 q2.5 -3 5 0 M168 91.5 v-3" stroke="#8F2E14" stroke-width="1.4"/>
<text x="168" y="122" text-anchor="middle" font-size="10" fill="#8F2E14" stroke="none" font-family="Noto Serif SC, serif" letter-spacing="1">ひだまり猫茶房 2F</text>
</g>
<!-- 指北 -->
<path d="M278 30 v-14 M278 16 l-4 6 M278 16 l4 6" stroke-width="1.6"/>
<text x="278" y="40" text-anchor="middle" font-size="9" fill="#71604D" stroke="none" font-family="Cormorant Garamond, serif">N</text>
</svg>
</div>
</div>
</div>
</section>
<!-- ============ 10. 页脚 ============ -->
<footer>
<div class="wrap">
<div class="foot-top">
<div class="foot-brand">
<div class="brand">
<svg width="26" height="26" viewBox="0 0 24 24" fill="none" aria-hidden="true">
<path d="M12 21.5 C7.6 21.5 5 18.6 5 15 C5 11.8 6.7 8.9 8.6 6.9 L7.6 2.6 L11 5.2 C11.65 5 12.35 5 13 5.2 L16.4 2.6 L15.4 6.9 C17.3 8.9 19 11.8 19 15 C19 18.6 16.4 21.5 12 21.5 Z" fill="#F5F0E6"/>
<path d="M18.6 19.4 C21.4 19.8 22.6 17.2 21 15.4" stroke="#F5F0E6" stroke-width="1.5" stroke-linecap="round"/>
</svg>
<span>
<span class="brand-name">ひだまり猫茶房</span><br>
<span class="brand-sub">HIDAMARI CAT CAFÉ</span>
</span>
</div>
<p class="foot-slogan">ひだまりで、猫と、一息。</p>
</div>
<div class="foot-nav">
<div class="foot-col">
<h4>店内</h4>
<a href="#about">关于我们</a>
<a href="#cats">今日猫咪</a>
<a href="#menu">菜单</a>
<a href="#space">环境</a>
</div>
<div class="foot-col">
<h4>到店</h4>
<a href="#reserve">预约到店</a>
<a href="#access">交通与营业时间</a>
</div>
<div class="foot-col">
<h4>关注</h4>
<div class="sns">
<a href="#" aria-label="Instagram" title="Instagram">
<svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="#F5F0E6" stroke-width="1.7"><rect x="3.5" y="3.5" width="17" height="17" rx="4.5"/><circle cx="12" cy="12" r="4"/><circle cx="17.2" cy="6.8" r="1" fill="#F5F0E6" stroke="none"/></svg>
</a>
<a href="#" aria-label="X" title="X">
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="#F5F0E6" stroke-width="1.8" stroke-linecap="round"><path d="M4 4 L20 20 M20 4 L4 20"/></svg>
</a>
<a href="#" aria-label="微博" title="微博">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#F5F0E6" stroke-width="1.6"><path d="M10.5 19.5 C6 19.5 3 16.8 3 13.6 C3 10.2 6.6 7 11 7 C15.4 7 18.5 10 18.5 13.2 C18.5 16.4 15 19.5 10.5 19.5 Z"/><circle cx="9.5" cy="13" r="1.4"/><path d="M16 4.5 q3.5 0 3.8 3.5 M16 7.5 q1.6 .2 1.8 1.7"/></svg>
</a>
</div>
</div>
</div>
</div>
<div class="foot-bottom">
<span>© 2026 ひだまり猫茶房 · 向阳猫茶房</span>
<span>本页面为设计演示 Demo · 店址与电话均为虚构</span>
</div>
</div>
</footer>
<script>
(function(){
"use strict";
var $ = function(s, r){ return (r || document).querySelector(s); };
var $$ = function(s, r){ return Array.prototype.slice.call((r || document).querySelectorAll(s)); };
/* ---------- 导航 ---------- */
var nav = $('#site-nav');
var onScroll = function(){ nav.classList.toggle('scrolled', window.scrollY > 24); };
window.addEventListener('scroll', onScroll, { passive: true });
onScroll();
var navToggle = $('#nav-toggle'), navMenu = $('#nav-menu');
navToggle.addEventListener('click', function(){
var open = navMenu.classList.toggle('open');
navToggle.classList.toggle('open', open);
navToggle.setAttribute('aria-expanded', open ? 'true' : 'false');
navToggle.setAttribute('aria-label', open ? '关闭菜单' : '打开菜单');
});
$$('#nav-menu a').forEach(function(a){
a.addEventListener('click', function(){
navMenu.classList.remove('open');
navToggle.classList.remove('open');
navToggle.setAttribute('aria-expanded', 'false');
});
});
/* ---------- 滚动渐显 ---------- */
var io = new IntersectionObserver(function(entries){
entries.forEach(function(e){
if (e.isIntersecting){ e.target.classList.add('is-visible'); io.unobserve(e.target); }
});
}, { threshold: 0.1, rootMargin: '0px 0px -6% 0px' });
var observeReveals = function(){
$$('.reveal:not(.is-visible)').forEach(function(el){ io.observe(el); });
};
observeReveals();
/* ---------- 日期工具 ---------- */
var WEEK = ['日','一','二','三','四','五','六'];
var pad = function(n){ return (n < 10 ? '0' : '') + n; };
var ymd = function(d){ return d.getFullYear() + '-' + pad(d.getMonth() + 1) + '-' + pad(d.getDate()); };
var today = new Date(); today.setHours(0, 0, 0, 0);
var maxDate = new Date(today); maxDate.setDate(maxDate.getDate() + 62);
var now = new Date();
/* 今日日期 & 营业状态 */
$('#today-label').textContent = (now.getMonth() + 1) + '月' + now.getDate() + '日(周' + WEEK[now.getDay()] + '';
var statusTxt;
if (now.getDay() === 2) statusTxt = '本日定休 · 猫员工公休日';
else if (now.getHours() >= 11 && now.getHours() < 20) statusTxt = '本日营业中 · 11:0020:00';
else statusTxt = '本日营业已结束 · 明日 11:00 见';
$('#hero-status').textContent = statusTxt;
/* ---------- 猫咪数据(内联手绘 SVG 头像) ---------- */
var INK = '#3E2F23';
var whiskers = '<g stroke="' + INK + '" stroke-width="1.6" stroke-linecap="round" fill="none" opacity=".7">'
+ '<path d="M34 62 Q24 60 15 56"/><path d="M34 67 Q24 67 15 68"/><path d="M34 72 Q25 75 17 79"/>'
+ '<path d="M86 62 Q96 60 105 56"/><path d="M86 67 Q96 67 105 68"/><path d="M86 72 Q95 75 103 79"/></g>';
var noseMouth = '<path d="M56 65.5 Q60 63 64 65.5 L60 70.5 Z" fill="#C47A5A"/>'
+ '<path d="M60 70.5 Q60 74 55.5 75.5 M60 70.5 Q60 74 64.5 75.5" stroke="' + INK + '" stroke-width="1.8" stroke-linecap="round" fill="none"/>';
var earsUp = function(fill){
return '<path d="M40 38 L33 12 L59 26 Z" fill="' + fill + '" stroke="' + INK + '" stroke-width="2.6" stroke-linejoin="round"/>'
+ '<path d="M80 38 L87 12 L61 26 Z" fill="' + fill + '" stroke="' + INK + '" stroke-width="2.6" stroke-linejoin="round"/>';
};
var headBase = function(fill, wide){
var d = wide
? 'M32 58 C32 40 45 29 60 29 C75 29 88 40 88 58 C88 76 75 88 60 88 C45 88 32 76 32 58 Z'
: 'M34 56 C34 40 46 30 60 30 C74 30 86 40 86 56 C86 74 74 86 60 86 C46 86 34 74 34 56 Z';
return '<path d="' + d + '" fill="' + fill + '" stroke="' + INK + '" stroke-width="2.6" stroke-linejoin="round"/>';
};
var eyeAlmond = function(color, slit){
var pupil = slit !== false
? '<path d="M50 52.5 V59.5 M70 52.5 V59.5" stroke="' + INK + '" stroke-width="2" stroke-linecap="round"/>' : '';
return '<path d="M44 56 Q50 50 56 56 Q50 61 44 56 Z" fill="' + color + '"/>'
+ '<path d="M64 56 Q70 50 76 56 Q70 61 64 56 Z" fill="' + color + '"/>' + pupil;
};
var eyeRound = function(color){
return '<circle cx="49" cy="55" r="5" fill="' + color + '"/><circle cx="71" cy="55" r="5" fill="' + color + '"/>'
+ '<circle cx="50.5" cy="53.5" r="1.3" fill="#F5F0E6"/><circle cx="72.5" cy="53.5" r="1.3" fill="#F5F0E6"/>';
};
var eyeClosed = '<path d="M44 57 Q50 51.5 56 57 M64 57 Q70 51.5 76 57" stroke="' + INK + '" stroke-width="2.4" stroke-linecap="round" fill="none"/>';
var svgWrap = function(inner){
return '<svg viewBox="0 0 120 120" role="img" aria-hidden="true">' + inner + '</svg>';
};
var CATS = [
{ name:'小春', jp:'こはる', breed:'橘猫 · 3 岁 · 男孩', tags:['干饭王','亲人','话痨'],
bio:'听到开罐头的声音,三秒内必到。', onDuty:true,
svg: svgWrap(
earsUp('#E3A960') + headBase('#E3A960')
+ '<ellipse cx="60" cy="73" rx="13" ry="9" fill="#F7EFDF" opacity=".9"/>'
+ '<g stroke="#B57B3E" stroke-width="3" stroke-linecap="round"><path d="M51 33 V41"/><path d="M60 31.5 V39"/><path d="M69 33 V41"/><path d="M37 57 L45 55.5"/><path d="M37.5 65 L45 62.5"/><path d="M83 57 L75 55.5"/><path d="M82.5 65 L75 62.5"/></g>'
+ eyeAlmond('#7A8B5A') + noseMouth + whiskers) },
{ name:'麦麦', jp:'むぎ', breed:'英国短毛猫 · 4 岁 · 女孩', tags:['高冷','观察员','夜班担当'],
bio:'喜欢蹲在吧台最高处,监督每一杯出品。', onDuty:true,
svg: svgWrap(
earsUp('#9AA3A8') + headBase('#9AA3A8', true)
+ '<path d="M41 33 L37 19 L53 27 Z" fill="#7E888E"/><path d="M79 33 L83 19 L67 27 Z" fill="#7E888E"/>'
+ eyeRound('#C68A2E') + noseMouth + whiskers) },
{ name:'大福', jp:'だいふく', breed:'布偶猫 · 2 岁 · 女孩', tags:['睡神','温柔','慢半拍'],
bio:'一天睡十八个小时,剩下六小时在找地方睡。', onDuty:false,
svg: svgWrap(
earsUp('#8A6B50') + headBase('#F1E6D2')
+ '<ellipse cx="60" cy="58" rx="19" ry="15" fill="#A08464" opacity=".38"/>'
+ '<g stroke="' + INK + '" stroke-width="2" stroke-linecap="round" fill="none"><path d="M34 64 L28 68 L34 72"/><path d="M86 64 L92 68 L86 72"/></g>'
+ eyeClosed + noseMouth + whiskers) },
{ name:'芝麻', jp:'ごま', breed:'黑猫 · 5 岁 · 男孩', tags:['神秘','夜行','蹭腿'],
bio:'会突然出现在你脚边,像一团会呼吸的影子。', onDuty:true,
svg: svgWrap(
earsUp('#4B4239') + headBase('#4B4239')
+ '<ellipse cx="60" cy="74" rx="11" ry="8" fill="#5C5246" opacity=".8"/>'
+ eyeAlmond('#D8A24A') + noseMouth + whiskers) },
{ name:'丸子', jp:'まるこ', breed:'三花猫 · 6 岁 · 女孩', tags:['女王','挑食','窗边常驻'],
bio:'靠窗第二个座位是她的,人类只是租客。', onDuty:true,
svg: svgWrap(
'<path d="M40 38 L33 12 L59 26 Z" fill="#DE9A55" stroke="' + INK + '" stroke-width="2.6" stroke-linejoin="round"/>'
+ '<path d="M80 38 L87 12 L61 26 Z" fill="#54453A" stroke="' + INK + '" stroke-width="2.6" stroke-linejoin="round"/>'
+ headBase('#F5EEDF')
+ '<path d="M34 56 C34 42 44 31 58 30 C57 44 48 54 35 58 Z" fill="#DE9A55" opacity=".85"/>'
+ '<ellipse cx="74" cy="52" rx="11" ry="9" fill="#54453A" opacity=".88"/>'
+ eyeClosed + noseMouth + whiskers) },
{ name:'拿铁', jp:'らて', breed:'暹罗猫 · 1 岁 · 男孩', tags:['话多','黏人','蓝眼睛'],
bio:'会对每位客人打招呼,嗓音洪亮。', onDuty:false,
svg: svgWrap(
earsUp('#5F4632') + headBase('#EFE3C6')
+ '<path d="M43 50 C47 41 73 41 77 50 C79 62 72 73 60 75 C48 73 41 62 43 50 Z" fill="#6B4F36" opacity=".85"/>'
+ '<circle cx="49" cy="55" r="6.5" fill="#EFE3C6" opacity=".35"/><circle cx="71" cy="55" r="6.5" fill="#EFE3C6" opacity=".35"/>'
+ eyeAlmond('#7FA3C4', false)
+ '<circle cx="50" cy="56" r="1.8" fill="' + INK + '"/><circle cx="70" cy="56" r="1.8" fill="' + INK + '"/>'
+ noseMouth + whiskers) },
{ name:'云朵', jp:'くも', breed:'苏格兰折耳 · 3 岁 · 女孩', tags:['安静','圆脸','慢热'],
bio:'熟客专属,第三次来才愿意搭理你。', onDuty:true,
svg: svgWrap(
'<path d="M38 35 Q35 22 49 23 Q55 28 51 37 Z" fill="#C2BAAF" stroke="' + INK + '" stroke-width="2.4" stroke-linejoin="round"/>'
+ '<path d="M82 35 Q85 22 71 23 Q65 28 69 37 Z" fill="#C2BAAF" stroke="' + INK + '" stroke-width="2.4" stroke-linejoin="round"/>'
+ headBase('#CFC8BC', true)
+ '<ellipse cx="42" cy="66" rx="6" ry="3.5" fill="#D9A08A" opacity=".35"/><ellipse cx="78" cy="66" rx="6" ry="3.5" fill="#D9A08A" opacity=".35"/>'
+ eyeRound('#5E5142') + noseMouth + whiskers) },
{ name:'奥利奥', jp:'おれお', breed:'奶牛猫 · 2 岁 · 男孩', tags:['好奇','巡逻','拆家未遂'],
bio:'每天巡视吧台三次,检查有没有小鱼干。', onDuty:true,
svg: svgWrap(
'<path d="M40 38 L33 12 L59 26 Z" fill="#4B4239" stroke="' + INK + '" stroke-width="2.6" stroke-linejoin="round"/>'
+ '<path d="M80 38 L87 12 L61 26 Z" fill="#F6F1E4" stroke="' + INK + '" stroke-width="2.6" stroke-linejoin="round"/>'
+ headBase('#F6F1E4')
+ '<path d="M68 33 C80 35 86 45 84 57 C74 59 66 53 64 43 Z" fill="#4B4239" opacity=".92"/>'
+ '<ellipse cx="60" cy="80" rx="5.5" ry="3.5" fill="#4B4239" opacity=".85"/>'
+ '<circle cx="49" cy="55" r="6" fill="#F6F1E4" opacity=".9"/><circle cx="71" cy="55" r="6.5" fill="#F6F1E4" opacity=".9"/>'
+ eyeAlmond('#8B9151') + noseMouth + whiskers) }
];
var grid = $('#cat-grid');
var onCount = 0;
CATS.forEach(function(c, i){
if (c.onDuty) onCount++;
var card = document.createElement('article');
card.className = 'cat-card reveal';
card.style.transitionDelay = (i % 4) * 60 + 'ms';
card.innerHTML =
'<span class="cat-badge ' + (c.onDuty ? 'on' : 'off') + '">' + (c.onDuty ? '在店' : '休息') + '</span>'
+ '<div class="cat-avatar">' + c.svg + '</div>'
+ '<h3>' + c.name + '<span class="cat-jp">' + c.jp + '</span></h3>'
+ '<p class="cat-breed">' + c.breed + '</p>'
+ '<div class="cat-tags">' + c.tags.map(function(t){ return '<span>' + t + '</span>'; }).join('') + '</div>'
+ '<p class="cat-bio">' + c.bio + '</p>';
grid.appendChild(card);
});
$('#duty-count').textContent = '出勤 ' + onCount + ' 位 / 休息 ' + (CATS.length - onCount) + ' 位';
observeReveals();
/* ---------- 预约表单状态 ---------- */
var state = { date: null, slot: null, seats: 0, people: 1 };
var SLOTS = ['11:00','12:00','13:00','14:00','15:00','16:00','17:00','18:00','19:00'];
/* 余位:由 日期+时段 确定性生成060 即满员) */
function seatsFor(dateStr, slot){
var s = dateStr + '@' + slot, h = 0;
for (var i = 0; i < s.length; i++){ h = (h * 31 + s.charCodeAt(i)) >>> 0; }
return h % 7;
}
/* ---------- 日历 ---------- */
var calView = new Date(today.getFullYear(), today.getMonth(), 1);
var calDays = $('#cal-days');
function bookable(d){ return d >= today && d <= maxDate && d.getDay() !== 2; }
function renderCalendar(){
$('#cal-year').textContent = calView.getFullYear();
$('#cal-month').textContent = calView.getMonth() + 1;
var first = new Date(calView.getFullYear(), calView.getMonth(), 1);
var daysInMonth = new Date(calView.getFullYear(), calView.getMonth() + 1, 0).getDate();
var lead = (first.getDay() + 6) % 7; /* 周一开头 */
var html = '';
for (var i = 0; i < lead; i++){ html += '<span></span>'; }
for (var d = 1; d <= daysInMonth; d++){
var date = new Date(calView.getFullYear(), calView.getMonth(), d);
var key = ymd(date);
var disabled = !bookable(date);
var closed = date.getDay() === 2 && date >= today && date <= maxDate;
var cls = 'cal-day' + (state.date === key ? ' sel' : '') + (closed ? ' closed' : '');
html += '<button type="button" class="' + cls + '" data-date="' + key + '"'
+ (disabled ? ' disabled' : '')
+ (closed ? ' title="周二定休"' : '')
+ ' aria-label="' + (date.getMonth() + 1) + '月' + d + '日 周' + WEEK[date.getDay()] + '">'
+ d + '</button>';
}
calDays.innerHTML = html;
var curMonth = new Date(today.getFullYear(), today.getMonth(), 1);
var maxMonth = new Date(maxDate.getFullYear(), maxDate.getMonth(), 1);
$('#cal-prev').disabled = calView <= curMonth;
$('#cal-next').disabled = calView >= maxMonth;
}
calDays.addEventListener('click', function(e){
var btn = e.target.closest('.cal-day');
if (!btn || btn.disabled) return;
state.date = btn.getAttribute('data-date');
state.slot = null; state.seats = 0;
hideErr('#err-date');
renderCalendar(); renderSlots(); checkSeats();
});
$('#cal-prev').addEventListener('click', function(){ calView.setMonth(calView.getMonth() - 1); renderCalendar(); });
$('#cal-next').addEventListener('click', function(){ calView.setMonth(calView.getMonth() + 1); renderCalendar(); });
/* ---------- 时段 ---------- */
var slotList = $('#slot-list');
function renderSlots(){
if (!state.date){
slotList.className = '';
slotList.innerHTML = '<div class="slots-empty">请先选择到店日期</div>';
return;
}
slotList.className = 'slots';
slotList.innerHTML = SLOTS.map(function(t){
var seats = seatsFor(state.date, t);
var sel = state.slot === t ? ' sel' : '';
var dis = seats === 0 ? ' disabled' : '';
var label = seats === 0 ? '满员' : '余 ' + seats + ' 席';
return '<button type="button" class="slot' + sel + '" data-slot="' + t + '" data-seats="' + seats + '"' + dis + '>'
+ '<b>' + t + '</b><small>' + label + '</small></button>';
}).join('');
}
slotList.addEventListener('click', function(e){
var btn = e.target.closest('.slot');
if (!btn || btn.disabled) return;
state.slot = btn.getAttribute('data-slot');
state.seats = parseInt(btn.getAttribute('data-seats'), 10);
hideErr('#err-slot');
renderSlots(); checkSeats();
});
/* ---------- 人数步进 ---------- */
var peopleNum = $('#people-num');
function renderPeople(){
peopleNum.textContent = state.people;
$('#people-minus').disabled = state.people <= 1;
$('#people-plus').disabled = state.people >= 4;
}
$('#people-minus').addEventListener('click', function(){ if (state.people > 1){ state.people--; renderPeople(); checkSeats(); } });
$('#people-plus').addEventListener('click', function(){ if (state.people < 4){ state.people++; renderPeople(); checkSeats(); } });
function checkSeats(){
var warn = $('#seat-warn');
var lack = state.slot && state.seats < state.people;
warn.style.display = lack ? 'block' : 'none';
return !lack;
}
/* ---------- 校验与提交 ---------- */
function showErr(sel){ $(sel).classList.add('show'); }
function hideErr(sel){ $(sel).classList.remove('show'); }
$('#reserve-form').addEventListener('submit', function(e){
e.preventDefault();
var name = $('#f-name').value.trim();
var phone = $('#f-phone').value.trim();
var ok = true;
if (!state.date){ showErr('#err-date'); ok = false; } else hideErr('#err-date');
if (!state.slot){ showErr('#err-slot'); ok = false; } else hideErr('#err-slot');
if (name.length < 2){ showErr('#err-name'); ok = false; } else hideErr('#err-name');
if (!/^1[3-9]\d{9}$/.test(phone)){ showErr('#err-phone'); ok = false; } else hideErr('#err-phone');
if (!checkSeats()){ ok = false; }
if (!ok) return;
var d = new Date(state.date + 'T00:00:00');
var endHour = parseInt(state.slot, 10) + 1.5;
var endTxt = (endHour % 1 ? pad(Math.floor(endHour)) + ':30' : pad(endHour) + ':00');
var no = 'HDMR-' + state.date.replace(/-/g, '') + '-' + (100 + Math.floor(Math.random() * 900));
$('#done-no').textContent = no;
$('#done-date').textContent = (d.getMonth() + 1) + '月' + d.getDate() + '日 · 周' + WEEK[d.getDay()];
$('#done-slot').textContent = state.slot + ' ' + endTxt + '90 分钟)';
$('#done-people').textContent = state.people + ' 人';
$('#done-name').textContent = name;
$('#done-phone').textContent = phone.slice(0, 3) + '****' + phone.slice(7);
$('#reserve-form').style.display = 'none';
var done = $('#reserve-done');
done.style.display = 'block';
done.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
});
$('#again-btn').addEventListener('click', function(){
state.slot = null; state.seats = 0; state.people = 1;
$('#f-name').value = ''; $('#f-phone').value = '';
renderPeople(); renderCalendar(); renderSlots();
$('#reserve-done').style.display = 'none';
$('#reserve-form').style.display = 'block';
});
/* 输入时即时清除报错 */
$('#f-name').addEventListener('input', function(){ if (this.value.trim().length >= 2) hideErr('#err-name'); });
$('#f-phone').addEventListener('input', function(){
this.value = this.value.replace(/\D/g, '').slice(0, 11);
if (/^1[3-9]\d{9}$/.test(this.value)) hideErr('#err-phone');
});
/* ---------- 初始化:预选出今天起第一个可约日 ---------- */
(function init(){
var d = new Date(today);
for (var i = 0; i <= 62; i++){
if (bookable(d)){ state.date = ymd(d); break; }
d.setDate(d.getDate() + 1);
}
if (state.date){
var sd = new Date(state.date + 'T00:00:00');
calView = new Date(sd.getFullYear(), sd.getMonth(), 1);
}
renderCalendar(); renderSlots(); renderPeople();
})();
})();
</script>
</body>
</html>