- 主页第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 沙箱重构文档更新
1350 lines
72 KiB
HTML
1350 lines
72 KiB
HTML
<!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:00–20: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:00–20: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'];
|
||
|
||
/* 余位:由 日期+时段 确定性生成(0–6,0 即满员) */
|
||
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>
|