dsh-design-studio 0.9.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/README.en.md +6 -4
  2. package/README.md +6 -4
  3. package/assets/demo.gif +0 -0
  4. package/assets/hero-sm.jpg +0 -0
  5. package/cordis.patch.yml +5 -0
  6. package/gallery-seed/d/orderg-x__alley-noodles/08e9e40834f9/_shots/menu.jpg +0 -0
  7. package/gallery-seed/d/orderg-x__alley-noodles/08e9e40834f9/app.css +64 -0
  8. package/gallery-seed/d/orderg-x__alley-noodles/08e9e40834f9/cart.html +120 -0
  9. package/gallery-seed/d/orderg-x__alley-noodles/08e9e40834f9/design.json +56 -0
  10. package/gallery-seed/d/orderg-x__alley-noodles/08e9e40834f9/menu.html +200 -0
  11. package/gallery-seed/d/orderg-x__alley-noodles/08e9e40834f9/order.html +135 -0
  12. package/gallery-seed/d/orderg-x__alley-noodles/08e9e40834f9/tokens.css +43 -0
  13. package/gallery-seed/d/orderg-x__autumn-sale/08e9e40834f9/_shots/email.jpg +0 -0
  14. package/gallery-seed/d/orderg-x__autumn-sale/08e9e40834f9/design.json +20 -0
  15. package/gallery-seed/d/orderg-x__autumn-sale/08e9e40834f9/email.html +268 -0
  16. package/gallery-seed/d/orderg-x__little-painter/08e9e40834f9/_shots/courses.jpg +0 -0
  17. package/gallery-seed/d/orderg-x__little-painter/08e9e40834f9/courses.html +364 -0
  18. package/gallery-seed/d/orderg-x__little-painter/08e9e40834f9/design.json +49 -0
  19. package/gallery-seed/d/orderg-x__little-painter/08e9e40834f9/lesson.html +196 -0
  20. package/gallery-seed/d/orderg-x__little-painter/08e9e40834f9/tokens.css +55 -0
  21. package/gallery-seed/d/orderg-x__little-painter/08e9e40834f9/ui.css +255 -0
  22. package/gallery-seed/d/orderg-x__moon-fair/08e9e40834f9/_shots/poster.jpg +0 -0
  23. package/gallery-seed/d/orderg-x__moon-fair/08e9e40834f9/design.json +21 -0
  24. package/gallery-seed/d/orderg-x__moon-fair/08e9e40834f9/poster.html +165 -0
  25. package/gallery-seed/d/orderg-x__moon-fair/08e9e40834f9/tokens.css +35 -0
  26. package/gallery-seed/d/orderg-x__paw-diary/08e9e40834f9/_shots/home.jpg +0 -0
  27. package/gallery-seed/d/orderg-x__paw-diary/08e9e40834f9/app.css +155 -0
  28. package/gallery-seed/d/orderg-x__paw-diary/08e9e40834f9/booking.html +232 -0
  29. package/gallery-seed/d/orderg-x__paw-diary/08e9e40834f9/design.json +57 -0
  30. package/gallery-seed/d/orderg-x__paw-diary/08e9e40834f9/health.html +221 -0
  31. package/gallery-seed/d/orderg-x__paw-diary/08e9e40834f9/home.html +225 -0
  32. package/gallery-seed/d/orderg-x__paw-diary/08e9e40834f9/tokens.css +54 -0
  33. package/gallery-seed/d/orderg-x__pocket-ledger/08e9e40834f9/_shots/overview.jpg +0 -0
  34. package/gallery-seed/d/orderg-x__pocket-ledger/08e9e40834f9/app.css +79 -0
  35. package/gallery-seed/d/orderg-x__pocket-ledger/08e9e40834f9/design.json +51 -0
  36. package/gallery-seed/d/orderg-x__pocket-ledger/08e9e40834f9/entries.html +161 -0
  37. package/gallery-seed/d/orderg-x__pocket-ledger/08e9e40834f9/icons.svg +30 -0
  38. package/gallery-seed/d/orderg-x__pocket-ledger/08e9e40834f9/overview.html +181 -0
  39. package/gallery-seed/d/orderg-x__pocket-ledger/08e9e40834f9/tokens.css +50 -0
  40. package/gallery-seed/d/orderg-x__time-bookshop/08e9e40834f9/_shots/home.jpg +0 -0
  41. package/gallery-seed/d/orderg-x__time-bookshop/08e9e40834f9/book.html +279 -0
  42. package/gallery-seed/d/orderg-x__time-bookshop/08e9e40834f9/design.json +21 -0
  43. package/gallery-seed/d/orderg-x__time-bookshop/08e9e40834f9/home.html +348 -0
  44. package/gallery-seed/d/orderg-x__time-bookshop/08e9e40834f9/style.css +297 -0
  45. package/gallery-seed/d/orderg-x__time-bookshop/08e9e40834f9/tokens.css +49 -0
  46. package/gallery-seed/d/orderg-x__year-review/08e9e40834f9/01-cover.html +133 -0
  47. package/gallery-seed/d/orderg-x__year-review/08e9e40834f9/02-highlights.html +67 -0
  48. package/gallery-seed/d/orderg-x__year-review/08e9e40834f9/03-growth.html +89 -0
  49. package/gallery-seed/d/orderg-x__year-review/08e9e40834f9/04-milestones.html +92 -0
  50. package/gallery-seed/d/orderg-x__year-review/08e9e40834f9/05-next.html +99 -0
  51. package/gallery-seed/d/orderg-x__year-review/08e9e40834f9/06-thanks.html +61 -0
  52. package/gallery-seed/d/orderg-x__year-review/08e9e40834f9/_shots/01-cover.jpg +0 -0
  53. package/gallery-seed/d/orderg-x__year-review/08e9e40834f9/deck.css +67 -0
  54. package/gallery-seed/d/orderg-x__year-review/08e9e40834f9/design.json +25 -0
  55. package/gallery-seed/d/orderg-x__year-review/08e9e40834f9/tokens.css +30 -0
  56. package/gallery-seed/index.json +1 -0
  57. package/gallery-seed/thumbs/orderg-x__alley-noodles.webp +0 -0
  58. package/gallery-seed/thumbs/orderg-x__autumn-sale.webp +0 -0
  59. package/gallery-seed/thumbs/orderg-x__little-painter.webp +0 -0
  60. package/gallery-seed/thumbs/orderg-x__moon-fair.webp +0 -0
  61. package/gallery-seed/thumbs/orderg-x__paw-diary.webp +0 -0
  62. package/gallery-seed/thumbs/orderg-x__pocket-ledger.webp +0 -0
  63. package/gallery-seed/thumbs/orderg-x__time-bookshop.webp +0 -0
  64. package/gallery-seed/thumbs/orderg-x__year-review.webp +0 -0
  65. package/lib/browser.js +23 -9
  66. package/lib/bundle.js +12 -3
  67. package/lib/client.js +3106 -111
  68. package/lib/core.js +44 -11
  69. package/lib/gallery/css.js +230 -0
  70. package/lib/gallery/html.js +313 -0
  71. package/lib/gallery/index.js +22 -0
  72. package/lib/gallery/market-routes.js +306 -0
  73. package/lib/gallery/market.js +623 -0
  74. package/lib/gallery/pack.js +311 -0
  75. package/lib/gallery/policy.js +1560 -0
  76. package/lib/gallery/qrfind.js +181 -0
  77. package/lib/gallery/render.js +148 -0
  78. package/lib/gallery/routes.js +360 -0
  79. package/lib/gallery/tar.js +118 -0
  80. package/lib/gallery/use.js +125 -0
  81. package/lib/gallery/zip.js +212 -0
  82. package/lib/handoff.js +291 -29
  83. package/lib/history.js +3 -1
  84. package/lib/index.js +118 -24
  85. package/lib/inspire.js +142 -0
  86. package/lib/offline.js +17 -0
  87. package/lib/picker.js +425 -32
  88. package/lib/serve.js +88 -11
  89. package/lib/works.js +238 -0
  90. package/locale/en.json +2 -1
  91. package/locale/offline/en.json +6 -0
  92. package/locale/offline/zh.json +6 -0
  93. package/locale/zh.json +2 -1
  94. package/package.json +10 -3
  95. package/skills/ui-design/SKILL.md +9 -0
@@ -0,0 +1,165 @@
1
+ <!doctype html>
2
+ <html lang="zh">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=1080">
6
+ <meta name="dsh-design" content="poster 1080x1350">
7
+ <title>海报 · 月满市集</title>
8
+ <link rel="stylesheet" href="tokens.css">
9
+ <style>
10
+ html, body { margin: 0; width: 1080px; height: 1350px; overflow: hidden; }
11
+ body { background: var(--color-bg); color: var(--color-text); font-family: var(--font-sans); -webkit-font-smoothing: antialiased; }
12
+ .poster { position: relative; width: 1080px; height: 1350px; overflow: hidden; }
13
+ .grain { position: absolute; inset: 0; pointer-events: none; }
14
+ .frame { position: absolute; inset: 28px; border: 1.5px solid var(--color-accent); border-radius: 2px; pointer-events: none; }
15
+ .frame::after { content: ""; position: absolute; inset: 7px; border: 1px solid var(--color-accent); opacity: .55; }
16
+
17
+ .hero { position: absolute; left: var(--safe); top: var(--safe); width: 936px; height: 764px; background: var(--color-primary); border-radius: var(--radius); box-shadow: var(--shadow); overflow: hidden; }
18
+ .hero-art { position: absolute; inset: 0; }
19
+ .title { position: absolute; left: 64px; top: 70px; margin: 0; writing-mode: vertical-rl; text-orientation: upright; font-family: var(--font-head); font-weight: 900; font-size: var(--text-title); line-height: 1; letter-spacing: .04em; color: var(--color-on); text-shadow: 0 4px 0 var(--color-primary-deep); }
20
+ .sub { position: absolute; right: 40px; top: 104px; margin: 0; writing-mode: vertical-rl; font-family: var(--font-head); font-weight: 700; font-size: 32px; letter-spacing: .3em; color: var(--color-accent-light); }
21
+ .seal { position: absolute; left: 600px; top: 428px; width: 120px; height: 120px; box-sizing: border-box; padding: 10px; background: var(--color-primary); border-radius: 4px; box-shadow: inset 0 0 0 5px var(--color-primary), inset 0 0 0 7px var(--color-on); transform: rotate(-4deg); display: grid; grid-template-columns: repeat(2, 48px); grid-auto-rows: 48px; place-content: center; }
22
+ .seal i { font-style: normal; font-family: var(--font-head); font-weight: 900; font-size: 44px; line-height: 48px; text-align: center; color: var(--color-on); }
23
+
24
+ .info { position: absolute; left: var(--safe); right: var(--safe); top: 872px; display: grid; grid-template-columns: 1fr 1fr; column-gap: 72px; }
25
+ .info::before { content: ""; position: absolute; left: 50%; top: 8px; bottom: 6px; width: 1px; background: var(--color-accent); opacity: .7; }
26
+ .label { display: flex; align-items: center; gap: var(--space-3); margin: 0 0 var(--space-3); font-size: var(--text-label); font-weight: 600; letter-spacing: .4em; color: var(--color-accent-ink); }
27
+ .label::before { content: ""; width: 32px; height: 2px; background: var(--color-accent); }
28
+ .big { margin: 0 0 var(--space-3); font-family: var(--font-head); font-weight: 900; font-size: var(--text-sub); line-height: 1.2; letter-spacing: .04em; color: var(--color-primary); }
29
+ .big.ink { color: var(--color-text); }
30
+ .line { margin: 0; font-size: var(--text-info); line-height: 1.5; color: var(--color-text); }
31
+ .line.muted { color: var(--color-muted); }
32
+ .free { display: inline-block; margin-left: var(--space-3); padding: 0 14px; border-radius: 4px; background: var(--color-primary); color: var(--color-on); font-size: var(--text-label); font-weight: 600; line-height: 38px; vertical-align: 3px; letter-spacing: .08em; }
33
+
34
+ .acts { position: absolute; left: var(--safe); right: var(--safe); top: 1092px; display: grid; grid-template-columns: repeat(3, 1fr); border-top: 1.5px solid var(--color-accent); padding-top: 24px; }
35
+ .act { display: grid; grid-template-columns: 56px 1fr; column-gap: var(--space-4); row-gap: var(--space-2); align-items: center; padding-right: var(--space-4); }
36
+ .act + .act { padding-left: var(--space-6); border-left: 1px solid var(--color-line); }
37
+ .act svg { width: 56px; height: 56px; }
38
+ .act b { font-family: var(--font-head); font-weight: 900; font-size: 32px; line-height: 1.3; color: var(--color-text); letter-spacing: .04em; }
39
+ .act span { grid-column: 1 / -1; font-size: var(--text-label); line-height: 1.5; color: var(--color-muted); white-space: nowrap; }
40
+
41
+ .foot { position: absolute; left: var(--safe); right: var(--safe); bottom: 62px; display: flex; justify-content: space-between; align-items: center; font-size: var(--text-label); color: var(--color-muted); letter-spacing: .12em; }
42
+ .foot i { font-style: normal; color: var(--color-accent-ink); }
43
+ </style>
44
+ </head>
45
+ <body>
46
+ <main class="poster">
47
+ <svg class="grain" width="1080" height="1350" aria-hidden="true">
48
+ <filter id="paper"><feTurbulence type="fractalNoise" baseFrequency=".9" numOctaves="2" stitchTiles="stitch"/><feColorMatrix values="0 0 0 0 .45 0 0 0 0 .28 0 0 0 0 .12 0 0 0 .09 0"/></filter>
49
+ <rect width="1080" height="1350" filter="url(#paper)"/>
50
+ </svg>
51
+ <div class="frame"></div>
52
+
53
+ <section class="hero">
54
+ <svg class="hero-art" viewBox="0 0 936 764" width="936" height="764" role="img" aria-label="一轮满月,桂花枝与祥云">
55
+ <defs>
56
+ <radialGradient id="moon" cx="44%" cy="40%" r="62%">
57
+ <stop offset="0" stop-color="#FFF8E6"/>
58
+ <stop offset=".65" stop-color="#FBE6B8"/>
59
+ <stop offset="1" stop-color="#F1CF86"/>
60
+ </radialGradient>
61
+ <radialGradient id="glow" cx="50%" cy="50%" r="50%">
62
+ <stop offset=".55" stop-color="#FFD98A" stop-opacity=".28"/>
63
+ <stop offset="1" stop-color="#FFD98A" stop-opacity="0"/>
64
+ </radialGradient>
65
+ <filter id="redgrain"><feTurbulence type="fractalNoise" baseFrequency=".7" numOctaves="2" stitchTiles="stitch"/><feColorMatrix values="0 0 0 0 .3 0 0 0 0 0 0 0 0 0 0 0 0 0 .12 0"/></filter>
66
+ <symbol id="cloud" viewBox="0 0 380 120">
67
+ <path d="M40 104C14 104 6 78 26 66C18 40 46 24 70 36C78 12 116 4 136 26C150 6 192 6 204 32C222 18 256 24 262 50C290 46 312 66 300 88C316 94 312 106 296 106Z" fill="#B8202A" stroke="#E0AC4A" stroke-width="3" stroke-linejoin="round"/>
68
+ <path d="M46 72C40 56 56 46 66 54C74 60 68 72 58 68M104 58C98 36 124 28 134 42C140 52 130 60 122 54M166 56C162 34 190 28 196 44C200 56 186 62 180 54M236 76C232 58 256 52 262 66C266 76 254 82 248 74M296 106C330 106 352 98 366 82M40 104C16 104 2 94 4 80" fill="none" stroke="#E0AC4A" stroke-width="3" stroke-linecap="round"/>
69
+ </symbol>
70
+ <symbol id="fret" viewBox="0 0 60 60">
71
+ <path d="M4 56V4H56V44H16V16H44V32H28" fill="none" stroke="#E0AC4A" stroke-width="3" stroke-linecap="square"/>
72
+ </symbol>
73
+ <symbol id="leaf" viewBox="0 -14 60 28" overflow="visible">
74
+ <path d="M0 0C14-13 40-13 58 0C40 13 14 13 0 0Z" fill="#8F161F"/>
75
+ <path d="M4 0H50" stroke="#C8952E" stroke-width="1.4" opacity=".8"/>
76
+ </symbol>
77
+ <symbol id="bloom" viewBox="-12 -12 24 24" overflow="visible">
78
+ <circle cx="0" cy="-5" r="4.6" fill="#F6CD6E"/><circle cx="5" cy="0" r="4.6" fill="#F6CD6E"/><circle cx="0" cy="5" r="4.6" fill="#F6CD6E"/><circle cx="-5" cy="0" r="4.6" fill="#F6CD6E"/><circle r="2.4" fill="#C77A1C"/>
79
+ </symbol>
80
+ </defs>
81
+
82
+ <rect width="936" height="764" filter="url(#redgrain)"/>
83
+ <rect x="18" y="18" width="900" height="728" rx="2" fill="none" stroke="#E0AC4A" stroke-width="1.5"/>
84
+ <use href="#fret" x="30" y="30" width="48" height="48"/>
85
+ <use href="#fret" x="30" y="30" width="48" height="48" transform="matrix(-1 0 0 1 936 0)"/>
86
+ <use href="#fret" x="30" y="30" width="48" height="48" transform="matrix(1 0 0 -1 0 764)"/>
87
+ <use href="#fret" x="30" y="30" width="48" height="48" transform="matrix(-1 0 0 -1 936 764)"/>
88
+
89
+ <circle cx="548" cy="360" r="360" fill="url(#glow)"/>
90
+ <circle cx="548" cy="360" r="304" fill="none" stroke="#F2C66B" stroke-width="3" stroke-dasharray="0 14" stroke-linecap="round" opacity=".9"/>
91
+ <circle cx="548" cy="360" r="288" fill="none" stroke="#E0AC4A" stroke-width="1.5"/>
92
+ <circle cx="548" cy="360" r="270" fill="url(#moon)"/>
93
+ <g fill="#EDC679" opacity=".26">
94
+ <ellipse cx="462" cy="300" rx="44" ry="36"/><ellipse cx="640" cy="330" rx="30" ry="24"/><ellipse cx="420" cy="430" rx="22" ry="18"/><ellipse cx="520" cy="392" rx="12" ry="10"/>
95
+ </g>
96
+
97
+ <g>
98
+ <path d="M842 -6C826 40 800 84 760 120C724 152 680 168 618 176" fill="none" stroke="#7A1018" stroke-width="7" stroke-linecap="round"/>
99
+ <path d="M818 52C786 66 760 90 744 116M724 146C700 120 676 108 644 108M770 108C780 144 778 176 762 200" fill="none" stroke="#7A1018" stroke-width="4" stroke-linecap="round"/>
100
+ <use href="#leaf" width="60" height="28" transform="translate(818 52) rotate(170)"/>
101
+ <use href="#leaf" width="60" height="28" transform="translate(830 24) rotate(-150)"/>
102
+ <use href="#leaf" width="60" height="28" transform="translate(744 116) rotate(130)"/>
103
+ <use href="#leaf" width="60" height="28" transform="translate(736 136) rotate(-128)"/>
104
+ <use href="#leaf" width="60" height="28" transform="translate(644 108) rotate(-168)"/>
105
+ <use href="#leaf" width="60" height="28" transform="translate(672 166) rotate(150)"/>
106
+ <use href="#leaf" width="60" height="28" transform="translate(762 200) rotate(104)"/>
107
+ <use href="#leaf" width="60" height="28" transform="translate(618 176) rotate(174)"/>
108
+ <use href="#bloom" width="24" height="24" transform="translate(790 80)"/>
109
+ <use href="#bloom" width="24" height="24" transform="translate(806 66) scale(.8)"/>
110
+ <use href="#bloom" width="24" height="24" transform="translate(752 140)"/>
111
+ <use href="#bloom" width="24" height="24" transform="translate(736 158) scale(.85)"/>
112
+ <use href="#bloom" width="24" height="24" transform="translate(770 156) scale(.7)"/>
113
+ <use href="#bloom" width="24" height="24" transform="translate(676 140)"/>
114
+ <use href="#bloom" width="24" height="24" transform="translate(692 152) scale(.75)"/>
115
+ <use href="#bloom" width="24" height="24" transform="translate(660 126) scale(.8)"/>
116
+ <use href="#bloom" width="24" height="24" transform="translate(776 218) scale(.8)"/>
117
+ <use href="#bloom" width="24" height="24" transform="translate(596 186) scale(.85)"/>
118
+ </g>
119
+
120
+ <use href="#cloud" x="168" y="520" width="380" height="120"/>
121
+ <use href="#cloud" x="250" y="606" width="200" height="64" opacity=".95"/>
122
+ </svg>
123
+
124
+ <h1 class="title">月满市集</h1>
125
+ <p class="sub">中秋夜市 · 第三届</p>
126
+ <div class="seal" role="img" aria-label="印章:花好月圆"><i>月</i><i>花</i><i>圆</i><i>好</i></div>
127
+ </section>
128
+
129
+ <section class="info">
130
+ <div>
131
+ <p class="label">时间</p>
132
+ <p class="big">农历八月十五</p>
133
+ <p class="line">2026 年 9 月 25 日 · 周五</p>
134
+ <p class="line">18:00 – 23:30<span class="free">免费入场</span></p>
135
+ </div>
136
+ <div>
137
+ <p class="label">地点</p>
138
+ <p class="big ink">桂香里老街</p>
139
+ <p class="line muted">东牌坊进 · 沿青溪河至月湖桥</p>
140
+ <p class="line muted">八百米长街 · 一百二十个摊位</p>
141
+ </div>
142
+ </section>
143
+
144
+ <section class="acts">
145
+ <div class="act">
146
+ <svg viewBox="0 0 64 64" fill="none" stroke="#B8202A" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M32 4V10M22 10H42M22 54H42M32 54V62M28 62H36"/><path d="M20 12C8 20 8 44 20 52H44C56 44 56 20 44 12Z" fill="#FBE1D2"/><path d="M32 12C26 22 26 42 32 52M32 12C38 22 38 42 32 52"/></svg>
147
+ <b>灯谜</b>
148
+ <span>百盏花灯 · 猜谜换桂花糕</span>
149
+ </div>
150
+ <div class="act">
151
+ <svg viewBox="0 0 64 64" fill="none" stroke="#B8202A" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M32 6C36 6 37 9 40 9.5S46 8 48.5 10.5 49 16.5 51.5 18.5 57 21 57 26 54 29.5 54 32 57 35 57 38 52 43 51.5 45.5 51 51 48.5 53.5 43 54 40 54.5 36 58 32 58 28 55 24 54.5 18 56 15.5 53.5 15 48 12.5 45.5 7 42 7 38 10 34.5 10 32 7 29 7 26 12 21 12.5 18.5 13 13 15.5 10.5 21 10 24 9.5 28 6 32 6Z" fill="#FBE1D2"/><circle cx="32" cy="32" r="13"/><path d="M32 23V41M23 32H41M26 26L38 38M38 26L26 38" stroke-width="2"/></svg>
152
+ <b>手作月饼</b>
153
+ <span>现场压模 · 带走六只</span>
154
+ </div>
155
+ <div class="act">
156
+ <svg viewBox="0 0 64 64" fill="none" stroke="#B8202A" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M30 4H40L38 20"/><path d="M38 20C52 24 56 40 50 50C44 60 22 60 16 50C10 40 18 24 32 20Z" fill="#FBE1D2"/><path d="M33 20L30 52M37 21L36 52M26 46H44" stroke-width="2"/><circle cx="33" cy="36" r="4"/><path d="M28 8H24M29 13H25" stroke-width="2.5"/></svg>
157
+ <b>民乐</b>
158
+ <span>20:00 · 月下古筝琵琶</span>
159
+ </div>
160
+ </section>
161
+
162
+ <footer class="foot"><span>桂香里街区 · 青溪河商户联合出品</span><i>月圆人团圆</i></footer>
163
+ </main>
164
+ </body>
165
+ </html>
@@ -0,0 +1,35 @@
1
+ :root {
2
+ --color-bg: #FBF3E4;
3
+ --color-surface: #FFFAF0;
4
+ --color-text: #2A1410;
5
+ --color-muted: #6F4A3A;
6
+ --color-line: #E8D3B5;
7
+ --color-primary: #B8202A;
8
+ --color-primary-deep: #8F161F;
9
+ --color-accent: #C8952E;
10
+ --color-accent-light: #F2C66B;
11
+ --color-accent-ink: #8C6420;
12
+ --color-on: #FFF7E6;
13
+ --color-link: #A31D26;
14
+ --color-moon: #FFF4DA;
15
+
16
+ --font-head: "Songti SC", "Noto Serif SC", "Source Han Serif SC", serif;
17
+ --font-sans: "PingFang SC", "HarmonyOS Sans SC", "Microsoft YaHei", system-ui, sans-serif;
18
+ --weight-head: 800;
19
+
20
+ --text-label: 24px;
21
+ --text-info: 28px;
22
+ --text-sub: 44px;
23
+ --text-title: 156px;
24
+
25
+ --space-2: 8px;
26
+ --space-3: 12px;
27
+ --space-4: 16px;
28
+ --space-5: 24px;
29
+ --space-6: 32px;
30
+ --space-7: 48px;
31
+ --safe: 72px;
32
+
33
+ --radius: 6px;
34
+ --shadow: 0 6px 18px rgba(140, 30, 20, .12);
35
+ }
@@ -0,0 +1,155 @@
1
+ * { box-sizing: border-box; }
2
+ html { background: var(--bg); }
3
+ body {
4
+ margin: 0;
5
+ min-height: 100vh;
6
+ background: var(--bg);
7
+ color: var(--text);
8
+ font-family: var(--font-round);
9
+ font-size: var(--fs-body);
10
+ font-weight: 500;
11
+ line-height: 1.5;
12
+ -webkit-font-smoothing: antialiased;
13
+ }
14
+ a { color: inherit; text-decoration: none; }
15
+ button { font: inherit; color: inherit; background: none; border: 0; padding: 0; cursor: pointer; }
16
+ h1, h2, h3, p { margin: 0; }
17
+ svg { display: block; }
18
+ .sprite { position: absolute; width: 0; height: 0; overflow: hidden; }
19
+ :focus-visible { outline: 3px solid var(--link); outline-offset: 2px; }
20
+
21
+ /* 状态栏:中间空着,灵动岛由外框画 */
22
+ .status {
23
+ position: sticky;
24
+ top: 0;
25
+ z-index: 20;
26
+ height: var(--status-h);
27
+ padding: 4px 26px 0 34px;
28
+ display: flex;
29
+ align-items: center;
30
+ justify-content: space-between;
31
+ background: var(--bg);
32
+ }
33
+ .status-time { font-size: var(--fs-body); font-weight: 700; }
34
+ .status-icons { display: flex; align-items: center; gap: 6px; }
35
+
36
+ /* 标签栏:49 + 34 横条 */
37
+ .tabbar {
38
+ position: fixed;
39
+ left: 0;
40
+ right: 0;
41
+ bottom: 0;
42
+ z-index: 20;
43
+ display: grid;
44
+ grid-template-columns: repeat(4, 1fr);
45
+ padding: 6px 12px var(--home-bar);
46
+ background: var(--surface);
47
+ border-radius: 28px 28px 0 0;
48
+ box-shadow: 0 -2px 0 var(--line);
49
+ }
50
+ .tab {
51
+ min-height: 46px;
52
+ display: flex;
53
+ flex-direction: column;
54
+ align-items: center;
55
+ justify-content: center;
56
+ gap: 2px;
57
+ font-size: var(--fs-micro);
58
+ font-weight: 700;
59
+ color: var(--muted);
60
+ }
61
+ .tab-ico { width: 48px; height: 28px; display: grid; place-items: center; border-radius: var(--radius-pill); }
62
+ .tab .ico { width: 24px; height: 24px; }
63
+ .tab.is-on { color: var(--link); }
64
+ .tab.is-on .tab-ico { background: var(--pink-soft); }
65
+
66
+ .page { padding: var(--space-2) var(--gutter) calc(var(--tab-h) + var(--home-bar) + var(--space-7)); }
67
+
68
+ /* 图标:胖胖的线 */
69
+ .ico { width: 24px; height: 24px; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
70
+ .ico.fill { fill: currentColor; stroke: none; }
71
+
72
+ .head { font-weight: var(--w-head); letter-spacing: -.01em; }
73
+ .meta { font-size: var(--fs-meta); color: var(--muted); }
74
+
75
+ .card {
76
+ background: var(--surface);
77
+ border-radius: var(--radius);
78
+ box-shadow: var(--shadow);
79
+ }
80
+
81
+ .section-head {
82
+ display: flex;
83
+ align-items: center;
84
+ justify-content: space-between;
85
+ margin: var(--space-7) 0 var(--space-3);
86
+ }
87
+ .section-head h2 { font-size: var(--fs-h3); }
88
+ .more {
89
+ display: inline-flex;
90
+ align-items: center;
91
+ gap: 2px;
92
+ min-height: 44px;
93
+ padding-left: var(--space-3);
94
+ font-size: var(--fs-meta);
95
+ font-weight: 700;
96
+ color: var(--link);
97
+ }
98
+ .more .ico { width: 16px; height: 16px; stroke-width: 2.6; }
99
+
100
+ /* 小圆块图标 */
101
+ .tile {
102
+ flex: 0 0 auto;
103
+ width: 44px;
104
+ height: 44px;
105
+ border-radius: var(--radius-sm);
106
+ display: grid;
107
+ place-items: center;
108
+ background: var(--pink-soft);
109
+ color: var(--link);
110
+ }
111
+ .tile.yellow { background: var(--yellow-soft); color: var(--text); }
112
+
113
+ /* 小标签 */
114
+ .chip {
115
+ display: inline-flex;
116
+ align-items: center;
117
+ gap: 4px;
118
+ padding: 2px 10px;
119
+ border-radius: var(--radius-pill);
120
+ font-size: var(--fs-micro);
121
+ font-weight: 700;
122
+ line-height: 18px;
123
+ white-space: nowrap;
124
+ background: var(--pink-soft);
125
+ color: var(--text);
126
+ }
127
+ .chip.yellow { background: var(--accent); color: var(--text); }
128
+ .chip.ghost { background: var(--bg); color: var(--muted); }
129
+
130
+ /* 糖果按钮:主色上用深色字,底下一道同色系厚阴影 */
131
+ .btn {
132
+ display: inline-flex;
133
+ align-items: center;
134
+ justify-content: center;
135
+ gap: var(--space-2);
136
+ min-height: 52px;
137
+ padding: 0 var(--space-6);
138
+ border-radius: var(--radius-pill);
139
+ background: var(--primary);
140
+ color: var(--on);
141
+ font-size: var(--fs-h3);
142
+ font-weight: var(--w-head);
143
+ box-shadow: var(--shadow-primary);
144
+ transition: transform .15s cubic-bezier(.2, .8, .2, 1), box-shadow .15s;
145
+ }
146
+ .btn:active { transform: translateY(4px); box-shadow: 0 1px 0 var(--pink-deep); }
147
+
148
+ /* 宠物头像 */
149
+ .avatar { display: grid; place-items: center; border-radius: 50%; background: var(--accent); box-shadow: 0 0 0 3px var(--surface), 0 4px 0 3px #F3C4D3; overflow: hidden; }
150
+ .avatar.pink { background: var(--pink-mid); }
151
+ .avatar svg { width: 100%; height: 100%; }
152
+
153
+ @media (prefers-reduced-motion: reduce) {
154
+ *, *::before, *::after { animation: none !important; transition: none !important; }
155
+ }
@@ -0,0 +1,232 @@
1
+ <!doctype html>
2
+ <html lang="zh">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width,initial-scale=1">
6
+ <meta name="dsh-design" content="app">
7
+ <title>预约洗护 · 毛孩日记</title>
8
+ <link rel="stylesheet" href="tokens.css">
9
+ <link rel="stylesheet" href="app.css">
10
+ <style>
11
+ .nav { display: grid; grid-template-columns: 44px 1fr 44px; align-items: center; gap: var(--space-2); padding-top: var(--space-1); }
12
+ .nav h1 { text-align: center; font-size: var(--fs-h3); }
13
+ .round-btn { width: 44px; height: 44px; border-radius: 50%; display: grid; place-items: center; background: var(--surface); box-shadow: var(--shadow-sm); }
14
+ .round-btn .ico { stroke-width: 2.6; }
15
+
16
+ .store { margin-top: var(--space-4); display: flex; align-items: center; gap: var(--space-3); padding: var(--space-3) var(--space-4) var(--space-3) var(--space-3); }
17
+ .store-art { flex: 0 0 56px; height: 56px; border-radius: var(--radius-sm); background: var(--pink-soft); }
18
+ .store-txt { flex: 1; min-width: 0; line-height: 1.4; }
19
+ .store-txt b { display: block; font-weight: 700; }
20
+ .rate { display: inline-flex; align-items: center; gap: 2px; font-weight: var(--w-head); }
21
+ .rate .ico { width: 18px; height: 18px; color: var(--accent); }
22
+
23
+ .label { display: flex; align-items: baseline; justify-content: space-between; margin: var(--space-5) 0 var(--space-3); }
24
+ .label h2 { font-size: var(--fs-h3); }
25
+
26
+ .who-row { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); margin-top: var(--space-5); }
27
+ .who-row h2 { font-size: var(--fs-h3); }
28
+ .who { display: flex; gap: var(--space-2); }
29
+ .who > span { display: inline-flex; align-items: center; gap: var(--space-2); min-height: 48px; padding: 4px 18px 4px 6px; border-radius: var(--radius-pill); background: var(--surface); box-shadow: inset 0 0 0 2px var(--line); font-weight: 700; color: var(--muted); }
30
+ .who .avatar { width: 36px; height: 36px; box-shadow: none; }
31
+ .who > .on { background: var(--pink-soft); box-shadow: inset 0 0 0 2.5px var(--primary); color: var(--text); }
32
+
33
+ .svcs { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-3); }
34
+ .svc { position: relative; display: flex; flex-direction: column; gap: var(--space-2); padding: var(--space-3) var(--space-3) var(--space-3) var(--space-3); border-radius: var(--radius-md); background: var(--surface); box-shadow: var(--shadow-sm); line-height: 1.35; }
35
+ .svc-top { display: flex; align-items: center; gap: var(--space-2); }
36
+ .svc .tile { width: 32px; height: 32px; border-radius: 11px; }
37
+ .svc .tile .ico { width: 18px; height: 18px; }
38
+ .svc b { font-weight: 700; }
39
+ .svc-foot { display: flex; align-items: baseline; gap: 6px; white-space: nowrap; }
40
+ .svc .price { font-weight: var(--w-head); }
41
+ .svc.on { background: var(--pink-soft); box-shadow: inset 0 0 0 2.5px var(--primary), 0 4px 0 var(--pink-deep); }
42
+ .svc.on .tile { background: var(--primary); color: var(--text); }
43
+ .badge { position: absolute; top: -6px; right: -4px; width: 24px; height: 24px; box-shadow: 0 0 0 2.5px var(--bg); border-radius: 50%; display: grid; place-items: center; background: var(--primary); color: var(--text); }
44
+ .badge .ico { width: 14px; height: 14px; stroke-width: 3.4; }
45
+
46
+ .days { display: flex; gap: var(--space-2); overflow-x: auto; scroll-snap-type: x mandatory; scroll-padding-inline: var(--gutter); margin: 0 calc(var(--gutter) * -1); padding: 2px var(--gutter) 8px; scrollbar-width: none; }
47
+ .days::-webkit-scrollbar { display: none; }
48
+ .day { flex: 0 0 52px; scroll-snap-align: start; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; height: 68px; border-radius: var(--radius-md); background: var(--surface); box-shadow: var(--shadow-sm); line-height: 1.2; }
49
+ .day span { font-size: var(--fs-micro); font-weight: 700; color: var(--muted); }
50
+ .day b { font-size: var(--fs-h3); font-weight: var(--w-head); }
51
+ .day.full { background: transparent; box-shadow: inset 0 0 0 2px var(--line); }
52
+ .day.full b { color: var(--muted); }
53
+ .day.on { background: var(--primary); box-shadow: var(--shadow-primary); }
54
+ .day.on span { color: var(--text); }
55
+
56
+ .slots { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--space-2); }
57
+ .slot { display: grid; place-items: center; min-height: 44px; border-radius: var(--radius-sm); background: var(--surface); box-shadow: inset 0 0 0 2px var(--line); font-weight: 700; font-variant-numeric: tabular-nums; line-height: 1.2; }
58
+ .slot.full { background: transparent; color: var(--muted); font-weight: 600; text-decoration: line-through; text-decoration-thickness: 1.5px; }
59
+ .slot.on { background: var(--accent); box-shadow: 0 4px 0 var(--yellow-deep); }
60
+
61
+ .note { display: flex; gap: var(--space-3); padding: var(--space-4); border-radius: var(--radius-md); background: var(--surface); box-shadow: inset 0 0 0 2px var(--line); }
62
+ .note .ico { flex: 0 0 auto; width: 20px; height: 20px; color: var(--link); margin-top: 2px; }
63
+ .note p { flex: 1; }
64
+ .note .meta { align-self: flex-end; }
65
+
66
+ .page { padding-bottom: calc(104px + var(--home-bar) + var(--space-6)); }
67
+ .checkout { position: fixed; left: 0; right: 0; bottom: 0; z-index: 20; display: flex; align-items: center; gap: var(--space-4); padding: var(--space-3) var(--gutter) calc(var(--home-bar) + var(--space-1)); background: var(--surface); border-radius: 28px 28px 0 0; box-shadow: 0 -2px 0 var(--line); }
68
+ .sumup { flex: 1; min-width: 0; line-height: 1.3; }
69
+ .total { display: flex; align-items: baseline; gap: var(--space-2); }
70
+ .total b { font-size: var(--fs-h2); font-weight: var(--w-head); }
71
+ .checkout .btn { flex: 0 0 auto; min-width: 156px; }
72
+ </style>
73
+ </head>
74
+ <body>
75
+ <svg class="sprite" aria-hidden="true">
76
+ <symbol id="pet-corgi" viewBox="0 0 64 64">
77
+ <path d="M11 34 13.4 9.6c.3-2.4 3-3.4 4.8-1.8L31 19.5z" fill="#FFC93C"/>
78
+ <path d="M15.6 27 17 13.8 25.6 20.4z" fill="#FF9EC0"/>
79
+ <path d="M53 34 50.6 9.6c-.3-2.4-3-3.4-4.8-1.8L33 19.5z" fill="#FFC93C"/>
80
+ <path d="M48.4 27 47 13.8 38.4 20.4z" fill="#FF9EC0"/>
81
+ <ellipse cx="32" cy="38.5" rx="23" ry="19.5" fill="#FFC93C"/>
82
+ <path d="M32 21.5c-2.2 6-7.5 10-7.5 18 0 7.4 3.4 12.6 7.5 12.6s7.5-5.2 7.5-12.6c0-8-5.3-12-7.5-18z" fill="#FFFFFF"/>
83
+ <ellipse cx="32" cy="48" rx="11" ry="7.5" fill="#FFFFFF"/>
84
+ <circle cx="21.5" cy="36.5" r="3.3" fill="#3A2540"/><circle cx="22.7" cy="35.3" r="1.1" fill="#FFFFFF"/>
85
+ <circle cx="42.5" cy="36.5" r="3.3" fill="#3A2540"/><circle cx="43.7" cy="35.3" r="1.1" fill="#FFFFFF"/>
86
+ <ellipse cx="32" cy="43.2" rx="3.6" ry="2.6" fill="#3A2540"/>
87
+ <path d="M28.4 47.4q3.6 3.2 7.2 0" fill="none" stroke="#3A2540" stroke-width="1.8" stroke-linecap="round"/>
88
+ <path d="M30.2 48.6h3.6v2.2a1.8 1.8 0 0 1-3.6 0z" fill="#FF7AA8"/>
89
+ <ellipse cx="16.5" cy="44" rx="3.6" ry="2.3" fill="#FF7AA8" opacity=".6"/>
90
+ <ellipse cx="47.5" cy="44" rx="3.6" ry="2.3" fill="#FF7AA8" opacity=".6"/>
91
+ </symbol>
92
+ <symbol id="pet-cat" viewBox="0 0 64 64">
93
+ <path d="M12 33 13 10.5c.1-2.2 2.6-3.3 4.3-1.9L29 18.5z" fill="#FFB3CC"/>
94
+ <path d="M16.2 26 16.9 14.6 24 20z" fill="#FF7AA8"/>
95
+ <path d="M52 33 51 10.5c-.1-2.2-2.6-3.3-4.3-1.9L35 18.5z" fill="#FFB3CC"/>
96
+ <path d="M47.8 26 47.1 14.6 40 20z" fill="#FF7AA8"/>
97
+ <ellipse cx="32" cy="38.5" rx="23" ry="19" fill="#FFB3CC"/>
98
+ <path d="M32 21v6M25.5 22l1.6 5M38.5 22l-1.6 5" stroke="#FF7AA8" stroke-width="2.6" stroke-linecap="round"/>
99
+ <path d="M19.5 37.5q3.5-4 7 0M37.5 37.5q3.5-4 7 0" fill="none" stroke="#3A2540" stroke-width="2.3" stroke-linecap="round"/>
100
+ <ellipse cx="32" cy="46" rx="7.5" ry="5.4" fill="#FFFFFF"/>
101
+ <path d="M30 42.8h4l-2 2.2z" fill="#FF7AA8" stroke="#FF7AA8" stroke-width="1.2" stroke-linejoin="round"/>
102
+ <path d="M29 47.4q1.5 1.7 3 0q1.5 1.7 3 0" fill="none" stroke="#3A2540" stroke-width="1.5" stroke-linecap="round"/>
103
+ <ellipse cx="16.5" cy="44.5" rx="3.6" ry="2.3" fill="#FFC93C"/>
104
+ <ellipse cx="47.5" cy="44.5" rx="3.6" ry="2.3" fill="#FFC93C"/>
105
+ <path d="M9 41.5l5.5 1M9 46.5l5.5-1.2M55 41.5l-5.5 1M55 46.5l-5.5-1.2" stroke="#3A2540" stroke-opacity=".45" stroke-width="1.4" stroke-linecap="round"/>
106
+ </symbol>
107
+ <symbol id="i-home" viewBox="0 0 24 24"><path d="M4 11.2 12 4.5l8 6.7v7.8a1.8 1.8 0 0 1-1.8 1.8H5.8A1.8 1.8 0 0 1 4 19z"/><path d="M10 20.8v-4.6a2 2 0 0 1 4 0v4.6"/></symbol>
108
+ <symbol id="i-heart" viewBox="0 0 24 24"><path d="M12 20s-7.5-4.6-7.5-10.2A4.2 4.2 0 0 1 12 7.3a4.2 4.2 0 0 1 7.5 2.5C19.5 15.4 12 20 12 20z"/></symbol>
109
+ <symbol id="i-book" viewBox="0 0 24 24"><path d="M6 4.5h10.5A1.5 1.5 0 0 1 18 6v13.5H7.5A2.5 2.5 0 0 1 5 17V5.5a1 1 0 0 1 1-1z"/><path d="M5 17a2.5 2.5 0 0 1 2.5-2.5H18"/><path d="M9.5 8.5h4"/></symbol>
110
+ <symbol id="i-me" viewBox="0 0 24 24"><circle cx="12" cy="8.5" r="3.6"/><path d="M5 20c1.3-3.6 4-5.4 7-5.4s5.7 1.8 7 5.4"/></symbol>
111
+ <symbol id="i-bell" viewBox="0 0 24 24"><path d="M12 4.2a5.3 5.3 0 0 0-5.3 5.3v3.2L5 16.3h14l-1.7-3.6V9.5A5.3 5.3 0 0 0 12 4.2z"/><path d="M10 19a2 2 0 0 0 4 0"/></symbol>
112
+ <symbol id="i-check" viewBox="0 0 24 24"><path d="M5.5 12.5l4.2 4.2 8.8-9"/></symbol>
113
+ <symbol id="i-bowl" viewBox="0 0 24 24"><path d="M3.5 12.5h17a8.5 7 0 0 1-17 0z"/><circle cx="9" cy="9" r="1.6"/><circle cx="14" cy="8" r="1.6"/><circle cx="12" cy="11" r=".6"/></symbol>
114
+ <symbol id="i-walk" viewBox="0 0 24 24"><circle cx="7" cy="17" r="2.6"/><path d="M9 15 17.5 6.5"/><path d="M14 5.5h4.5V10"/></symbol>
115
+ <symbol id="i-pill" viewBox="0 0 24 24"><g transform="rotate(-45 12 12)"><rect x="3.5" y="8.25" width="17" height="7.5" rx="3.75"/><path d="M12 8.25H7.25a3.75 3.75 0 0 0 0 7.5H12z" fill="currentColor"/></g></symbol>
116
+ <symbol id="i-scale" viewBox="0 0 24 24"><rect x="4" y="4" width="16" height="16" rx="5"/><path d="M8.5 10a5 5 0 0 1 7 0"/><path d="M12 10.5l1.2-1.8"/></symbol>
117
+ <symbol id="i-bath" viewBox="0 0 24 24"><path d="M3.5 12h17v1.5a5.5 5.5 0 0 1-5.5 5.5H9a5.5 5.5 0 0 1-5.5-5.5z"/><path d="M6 12V6.5a2 2 0 0 1 3.6-1.2"/><path d="M8 19.5 7 21M16 19.5l1 1.5"/></symbol>
118
+ <symbol id="i-paw" viewBox="0 0 24 24"><ellipse cx="12" cy="16" rx="5" ry="4.2"/><ellipse cx="5.6" cy="10.6" rx="2" ry="2.5"/><ellipse cx="9.4" cy="6.6" rx="2" ry="2.6"/><ellipse cx="14.6" cy="6.6" rx="2" ry="2.6"/><ellipse cx="18.4" cy="10.6" rx="2" ry="2.5"/></symbol>
119
+ <symbol id="i-plus" viewBox="0 0 24 24"><path d="M12 5.5v13M5.5 12h13"/></symbol>
120
+ <symbol id="i-right" viewBox="0 0 24 24"><path d="m9.5 6 6 6-6 6"/></symbol>
121
+ <symbol id="i-down" viewBox="0 0 24 24"><path d="m6.5 9.5 5.5 5.5 5.5-5.5"/></symbol>
122
+ <symbol id="i-syringe" viewBox="0 0 24 24"><g transform="rotate(45 12 12)"><rect x="8.5" y="7" width="7" height="10" rx="1.6"/><path d="M12 17v4.5M9 3.5h6M12 3.5V7M8.5 10.5h3M8.5 13.5h3"/></g></symbol>
123
+ <symbol id="i-shield" viewBox="0 0 24 24"><path d="M12 3.8 18.5 6v5.4c0 4.2-2.8 7.4-6.5 8.8-3.7-1.4-6.5-4.6-6.5-8.8V6z"/><path d="M9.2 12l2 2 3.8-3.8"/></symbol>
124
+ <symbol id="i-left" viewBox="0 0 24 24"><path d="m14.5 6-6 6 6 6"/></symbol>
125
+ <symbol id="i-scissors" viewBox="0 0 24 24"><circle cx="6.5" cy="7" r="2.6"/><circle cx="6.5" cy="17" r="2.6"/><path d="M8.8 8.4 19 16.5M8.8 15.6 19 7.5"/></symbol>
126
+ <symbol id="i-steth" viewBox="0 0 24 24"><path d="M6 4.5v5a4 4 0 0 0 8 0v-5"/><path d="M10 13.5v1.5a4.5 4.5 0 0 0 9 0v-2"/><circle cx="19" cy="11" r="2"/></symbol>
127
+ <symbol id="i-leaf" viewBox="0 0 24 24"><path d="M5 19c0-8 5-13.5 14-14 .5 9-5 14-12 14z"/><path d="M5 19c3-4 6-6.5 9.5-8.5"/></symbol>
128
+ <symbol id="i-pin" viewBox="0 0 24 24"><path d="M12 20.5s-6-5.6-6-10.5a6 6 0 0 1 12 0c0 4.9-6 10.5-6 10.5z"/><circle cx="12" cy="10" r="2.2"/></symbol>
129
+ <symbol id="i-star" viewBox="0 0 24 24"><path d="M12 4.5l2.3 4.7 5.2.7-3.8 3.6.9 5.1-4.6-2.4-4.6 2.4.9-5.1-3.8-3.6 5.2-.7z"/></symbol>
130
+ <symbol id="i-pen" viewBox="0 0 24 24"><path d="M5 19l1-4.5L15.5 5a2.1 2.1 0 0 1 3 3L9 17.5z"/></symbol>
131
+ </svg>
132
+
133
+ <header class="status" aria-hidden="true">
134
+ <span class="status-time">9:41</span>
135
+ <span class="status-icons">
136
+ <svg width="18" height="12" viewBox="0 0 18 12" fill="currentColor"><rect x="0" y="8" width="3" height="4" rx=".8"/><rect x="5" y="5.5" width="3" height="6.5" rx=".8"/><rect x="10" y="3" width="3" height="9" rx=".8"/><rect x="15" y="0" width="3" height="12" rx=".8"/></svg>
137
+ <svg width="16" height="12" viewBox="0 0 16 12" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"><path d="M1.5 4.3a9.5 9.5 0 0 1 13 0"/><path d="M4 7.1a6 6 0 0 1 8 0"/><circle cx="8" cy="10" r="1.3" fill="currentColor" stroke="none"/></svg>
138
+ <svg width="27" height="12" viewBox="0 0 27 12"><rect x=".5" y=".5" width="23" height="11" rx="3.2" fill="none" stroke="currentColor" stroke-opacity=".4"/><rect x="2" y="2" width="17" height="8" rx="1.8" fill="currentColor"/><path d="M25 4v4c.8-.3 1.4-1.1 1.4-2s-.6-1.7-1.4-2z" fill="currentColor" fill-opacity=".4"/></svg>
139
+ </span>
140
+ </header>
141
+
142
+ <main class="page">
143
+ <nav class="nav">
144
+ <a class="round-btn" href="home.html" aria-label="返回首页"><svg class="ico"><use href="#i-left"/></svg></a>
145
+ <h1 class="head">预约洗护</h1>
146
+ <span class="round-btn" role="button" aria-label="我的预约"><svg class="ico"><use href="#i-book"/></svg></span>
147
+ </nav>
148
+
149
+ <section class="card store">
150
+ <svg class="store-art" viewBox="0 0 56 56" aria-hidden="true">
151
+ <rect x="10" y="22" width="36" height="24" rx="4" fill="#FFFFFF"/>
152
+ <path d="M8 14h40l2 9H6z" fill="#FF7AA8"/>
153
+ <path d="M14 14l-2 9M22 14l-1 9M30 14v9M38 14l1 9" stroke="#FFFFFF" stroke-width="2.6"/>
154
+ <path d="M6 23a4.4 4.4 0 0 0 8.8 0 4.4 4.4 0 0 0 8.8 0 4.4 4.4 0 0 0 8.8 0 4.4 4.4 0 0 0 8.8 0 4.4 4.4 0 0 0 8.8 0z" fill="#FF7AA8"/>
155
+ <rect x="22" y="32" width="12" height="14" rx="3" fill="#FFC93C"/>
156
+ <circle cx="40" cy="34" r="3" fill="#FFC93C"/>
157
+ </svg>
158
+ <div class="store-txt">
159
+ <b>豆丁宠物生活馆 · 滨江店</b>
160
+ <span class="meta">营业中 09:30–20:00 · 1.2 km</span>
161
+ </div>
162
+ <span class="rate"><svg class="ico fill"><use href="#i-star"/></svg>4.9</span>
163
+ </section>
164
+
165
+ <div class="who-row">
166
+ <h2 class="head">给谁预约</h2>
167
+ <div class="who">
168
+ <span class="on"><span class="avatar pink"><svg viewBox="0 0 64 64" aria-hidden="true"><use href="#pet-corgi"/></svg></span>团子</span>
169
+ <span><span class="avatar"><svg viewBox="0 0 64 64" aria-hidden="true"><use href="#pet-cat"/></svg></span>芝麻</span>
170
+ </div>
171
+ </div>
172
+
173
+ <div class="label"><h2 class="head">选服务</h2><span class="meta">按 10–15 kg 体型计价</span></div>
174
+ <div class="svcs">
175
+ <div class="svc on">
176
+ <span class="badge"><svg class="ico"><use href="#i-check"/></svg></span>
177
+ <div class="svc-top"><span class="tile"><svg class="ico"><use href="#i-bath"/></svg></span><b>基础洗护</b></div>
178
+ <p class="svc-foot"><span class="price">¥128</span><span class="meta">约 60 分钟</span></p>
179
+ </div>
180
+ <div class="svc">
181
+ <div class="svc-top"><span class="tile"><svg class="ico"><use href="#i-scissors"/></svg></span><b>精致美容</b></div>
182
+ <p class="svc-foot"><span class="price">¥228</span><span class="meta">约 2 小时</span></p>
183
+ </div>
184
+ <div class="svc">
185
+ <div class="svc-top"><span class="tile yellow"><svg class="ico"><use href="#i-steth"/></svg></span><b>年度体检</b></div>
186
+ <p class="svc-foot"><span class="price">¥299</span><span class="meta">约 45 分钟</span></p>
187
+ </div>
188
+ <div class="svc">
189
+ <div class="svc-top"><span class="tile yellow"><svg class="ico"><use href="#i-leaf"/></svg></span><b>草本药浴</b></div>
190
+ <p class="svc-foot"><span class="price">¥168</span><span class="meta">约 75 分钟</span></p>
191
+ </div>
192
+ </div>
193
+
194
+ <div class="label"><h2 class="head">选日期</h2><span class="meta">2026 年 11 月</span></div>
195
+ <div class="days">
196
+ <span class="day full"><span>今天</span><b>7</b></span>
197
+ <span class="day on"><span>周日</span><b>8</b></span>
198
+ <span class="day"><span>周一</span><b>9</b></span>
199
+ <span class="day"><span>周二</span><b>10</b></span>
200
+ <span class="day"><span>周三</span><b>11</b></span>
201
+ <span class="day"><span>周四</span><b>12</b></span>
202
+ <span class="day"><span>周五</span><b>13</b></span>
203
+ </div>
204
+
205
+ <div class="label"><h2 class="head">选时间</h2><span class="meta">划线的已约满</span></div>
206
+ <div class="slots">
207
+ <span class="slot">10:00</span>
208
+ <span class="slot">11:00</span>
209
+ <span class="slot full">13:30</span>
210
+ <span class="slot on">14:30</span>
211
+ <span class="slot">15:30</span>
212
+ <span class="slot">16:30</span>
213
+ <span class="slot full">17:30</span>
214
+ <span class="slot">18:30</span>
215
+ </div>
216
+
217
+ <div class="label"><h2 class="head">给美容师的话</h2></div>
218
+ <div class="note">
219
+ <svg class="ico"><use href="#i-pen"/></svg>
220
+ <p>团子有点怕吹风机,吹干的时候麻烦轻一点、慢一点,谢谢~</p>
221
+ </div>
222
+ </main>
223
+
224
+ <div class="checkout">
225
+ <div class="sumup">
226
+ <span class="meta">11 月 8 日 14:30</span>
227
+ <p class="total"><b>¥128</b><span class="meta">到店付</span></p>
228
+ </div>
229
+ <a class="btn" href="home.html">确认预约</a>
230
+ </div>
231
+ </body>
232
+ </html>