编辑
2026-03-16
AI
00

目录

关于skills
结构
github快速引入
使用对比
总结
附录

关于skills

Skills 将特定领域的知识和工作流打包封装,供 Agent 调用以完成特定任务。 (全世界免费可以用的一个模板库&&这个模板库支持普通语言就可以命中对应风格,加上你的需求描述动态生成&&可用性高) 参考:cursor skills

结构

兼容Claude:

js
.claude/ skills/ frontend-design/ LICENSE.txt

cursor本身的:

js
.cursor/skills/

github快速引入

参考引入:

bash
https://github.com/anthropics/skills/tree/main/skills 我希望你可以将这个github库下面的所有skills导入进去

之后就可以chat中通过/或@来直接引用

bash
/pdf\SKILL.md 将index.html生成容易理解,简洁的PDF

使用对比

以下参考:https://juejin.cn/post/7593362940071903284

在上面基础上,加入了个人实践对比及若干改动点,只为了呈现出对比区别:

生成塔罗牌:

  1. 不使用skills:
js
我要做一个 H5 ,功能是一个塔罗牌。不要用任何skills,就直接默认使用大模型本身的能力! 你是一名经验丰富的产品设计专家和资深前端专家,擅长UI构图与前端页面还原。现在请你帮我完成这个塔罗牌应用的 UI/UX 原型图设计。请输出一个包含所有设计页面的完整HTML文件,用于展示完整UI界面。 注意:生成代码的时候请一步一步执行,避免单步任务过大,时间执行过长 直接在左侧目录生成可运行的代码,不要动原来的代码。
  1. 使用skills 在项目目录下,新建.claude/skills/frontend-design,内容参考: github frontend-design
js
使用 Skill front-design。我要做一个 H5 ,功能是一个塔罗牌。 你是一名经验丰富的产品设计专家和资深前端专家,擅长UI构图与前端页面还原。现在请你帮我完成这个塔罗牌应用的 UI/UX 原型图设计。请输出一个包含所有设计页面的完整HTML文件,用于展示完整UI界面。 注意:生成代码的时候请一步一步执行,避免单步任务过大,时间执行过长

(上面的会自动命中skills) 或

  1. 使用skills
js
/frontend-design\SKILL.md 使用 Skill front-design。我要做一个 H5 ,功能是一个塔罗牌。 你是一名经验丰富的产品设计专家和资深前端专家,擅长UI构图与前端页面还原。现在请你帮我完成这个塔罗牌应用的 UI/UX 原型图设计。请输出一个包含所有设计页面的完整HTML文件,用于展示完整UI界面。 注意:生成代码的时候请一步一步执行,避免单步任务过大,时间执行过长 直接在左侧目录生成可运行的代码

总结

使用了skills,生成的代码不需要做任何修改,可用度和风格完整性很强,不管是展示界面、还是点击使用、还是过程特性,都不需要做任何修改,直接演示即可。

不使用skills,过程发现了几个问题:

  1. 点击使用时,无法正常工作;
  2. 过程无特效;
  3. 修复1后,过程切换又存在问题;
  4. (待确定)样式风格,不知道是不是因为先用了skills,界面跟用了skills的很像!

附录

  1. 使用了skills的HTML: 对应上面《使用对比》中的1:一遍生成,无任何修改
html
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" /> <title>Moon Arcana · 塔罗占卜</title> <meta name="description" content="Moon Arcana 塔罗 H5,占卜、抽牌、解读,一页完成。"> <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=Cinzel:wght@500;700&family=Noto+Serif+SC:wght@300;500;700&display=swap" rel="stylesheet"> <style> :root { --bg: #050612; --bg-elevated: rgba(10, 12, 26, 0.96); --bg-soft: rgba(16, 18, 40, 0.92); --accent: #eccb7c; --accent-soft: rgba(236, 203, 124, 0.22); --accent-strong: #f7da92; --accent-danger: #ff6b81; --text-main: #f7f0e8; --text-muted: #a6a4c1; --border-subtle: rgba(255, 255, 255, 0.08); --card-back: radial-gradient(circle at 20% 10%, #3f2849 0, #0f172a 40%, #050612 100%); --card-front: rgba(14, 16, 36, 0.98); --radius-xl: 24px; --radius-lg: 18px; --radius-md: 12px; --shadow-soft: 0 22px 60px rgba(5, 6, 18, 0.95); --shadow-glow: 0 0 60px rgba(236, 203, 124, 0.4); --noise: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160' viewBox='0 0 160 160'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='3' stitchTiles='noStitch'/></filter><rect width='100%' height='100%' filter='url(%23n)' opacity='0.22'/></svg>"); } * { box-sizing: border-box; -webkit-tap-highlight-color: transparent; } html, body { margin: 0; padding: 0; height: 100%; font-family: 'Noto Serif SC', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; color: var(--text-main); background: radial-gradient(circle at top, #1a2442 0, #050612 52%, #02020a 100%); overscroll-behavior-y: contain; scroll-behavior: smooth; } body::before { content: ""; position: fixed; inset: 0; background-image: radial-gradient(circle at 10% -10%, rgba(236, 203, 124, 0.13), transparent 55%), radial-gradient(circle at 90% 110%, rgba(85, 194, 214, 0.13), transparent 55%); mix-blend-mode: screen; opacity: 0.9; pointer-events: none; z-index: -2; } body::after { content: ""; position: fixed; inset: 0; background-image: var(--noise); mix-blend-mode: soft-light; opacity: 0.52; pointer-events: none; z-index: -1; } .app-shell { min-height: 100vh; max-width: 480px; margin: 0 auto; padding: env(safe-area-inset-top, 20px) 16px env(safe-area-inset-bottom, 22px); display: flex; flex-direction: column; gap: 16px; position: relative; } .chrome { display: flex; align-items: center; justify-content: space-between; padding: 6px 2px 2px; } .brand { display: flex; align-items: center; gap: 8px; } .brand-mark { width: 26px; height: 26px; border-radius: 999px; border: 1px solid rgba(236, 203, 124, 0.7); background: radial-gradient(circle at 30% 0%, rgba(250, 235, 195, 0.8), transparent 55%), radial-gradient(circle at 70% 120%, rgba(84, 164, 210, 0.7), transparent 60%), #050612; box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.07), 0 0 26px rgba(236, 203, 124, 0.8); position: relative; overflow: hidden; } .brand-mark::before { content: ""; position: absolute; inset: 4px; border-radius: inherit; border: 1px dashed rgba(255, 255, 255, 0.35); border-top: none; opacity: 0.9; } .brand-text { display: flex; flex-direction: column; gap: 1px; } .brand-name { font-family: 'Cinzel', serif; font-size: 16px; letter-spacing: 0.16em; text-transform: uppercase; } .brand-sub { font-size: 11px; color: var(--text-muted); letter-spacing: 0.28em; text-transform: uppercase; } .chrome-actions { display: flex; align-items: center; gap: 10px; } .icon-button { width: 32px; height: 32px; border-radius: 999px; border: 1px solid var(--border-subtle); background: radial-gradient(circle at 30% 0%, rgba(255, 255, 255, 0.12), transparent 60%), rgba(10, 13, 28, 0.9); display: inline-flex; align-items: center; justify-content: center; color: var(--text-muted); font-size: 16px; cursor: pointer; box-shadow: 0 8px 18px rgba(0, 0, 0, 0.55); transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease, background 0.2s ease, color 0.2s ease; } .icon-button span { transform: translateY(0.5px); } .icon-button.active, .icon-button:active { transform: translateY(1px) scale(0.97); box-shadow: 0 2px 10px rgba(0, 0, 0, 0.65); border-color: rgba(236, 203, 124, 0.9); color: var(--accent-strong); background: radial-gradient(circle at 30% 0%, rgba(236, 203, 124, 0.3), transparent 65%), rgba(15, 18, 38, 0.96); } main { flex: 1; display: flex; flex-direction: column; gap: 14px; } .hero-card { border-radius: var(--radius-xl); padding: 18px 18px 14px; background: radial-gradient(circle at -20% 0%, rgba(250, 230, 172, 0.16), transparent 58%), radial-gradient(circle at 110% 40%, rgba(84, 164, 210, 0.26), transparent 55%), linear-gradient(135deg, rgba(9, 10, 30, 0.96), rgba(9, 10, 26, 0.98)); box-shadow: var(--shadow-soft); border: 1px solid rgba(255, 255, 255, 0.06); position: relative; overflow: hidden; isolation: isolate; } .hero-card::before { content: ""; position: absolute; inset: -30%; background-image: repeating-radial-gradient(circle at 10% 0%, rgba(255, 255, 255, 0.05) 0, rgba(255, 255, 255, 0.05) 1px, transparent 1px, transparent 8px); opacity: 0.6; mix-blend-mode: soft-light; pointer-events: none; z-index: -1; } .hero-top { display: flex; justify-content: space-between; gap: 14px; } .hero-copy { max-width: 62%; } .hero-tag { display: inline-flex; align-items: center; gap: 6px; padding: 2px 9px; border-radius: 99px; border: 1px solid rgba(236, 203, 124, 0.8); background: linear-gradient(135deg, rgba(10, 11, 28, 0.95), rgba(30, 25, 60, 0.9)); font-size: 11px; letter-spacing: 0.16em; text-transform: uppercase; color: var(--accent-strong); margin-bottom: 6px; } .hero-tag-dot { width: 7px; height: 7px; border-radius: 999px; background: radial-gradient(circle, #ffe9b8 0, #eccb7c 40%, rgba(236, 203, 124, 0.2) 100%); box-shadow: 0 0 18px rgba(236, 203, 124, 0.9); } .hero-title-main { font-family: 'Cinzel', serif; font-size: 26px; letter-spacing: 0.18em; text-transform: uppercase; margin-bottom: 6px; } .hero-title-sub { font-size: 14px; color: var(--text-muted); } .hero-moon-orbit { position: relative; width: 105px; flex-shrink: 0; display: flex; align-items: center; justify-content: center; } .orbit-ring { width: 90px; height: 90px; border-radius: 999px; border: 1px dashed rgba(236, 203, 124, 0.55); border-left-color: transparent; border-bottom-color: transparent; transform: rotate(-25deg); position: relative; box-shadow: 0 0 40px rgba(236, 203, 124, 0.45); } .orbit-moon { position: absolute; inset: 15px; border-radius: inherit; background: radial-gradient(circle at 18% 0, #fff7dc 0, #f3d291 40%, #f0b875 60%, #f3f0e6 100%); box-shadow: 0 0 36px rgba(236, 203, 124, 0.9); overflow: hidden; } .orbit-moon::before { content: ""; position: absolute; inset: 0; background: radial-gradient(circle at 65% 35%, rgba(5, 6, 18, 0.75), transparent 55%); mix-blend-mode: multiply; } .orbit-dot { position: absolute; width: 6px; height: 6px; border-radius: 999px; background: #f7da92; box-shadow: 0 0 12px rgba(247, 218, 146, 0.9); top: 1px; left: 50%; transform: translateX(-50%); } .hero-meta { display: flex; justify-content: space-between; align-items: flex-end; margin-top: 14px; gap: 8px; font-size: 11px; } .hero-meta-col { display: flex; flex-direction: column; gap: 4px; } .hero-meta-label { letter-spacing: 0.16em; text-transform: uppercase; color: var(--text-muted); } .hero-meta-value { display: flex; align-items: baseline; gap: 4px; } .hero-meta-value span { color: var(--accent-strong); } .hero-cta { display: flex; gap: 8px; align-items: center; } .primary-btn { flex: 1; border: none; border-radius: 999px; padding: 10px 16px; font-family: inherit; font-size: 15px; letter-spacing: 0.16em; text-transform: uppercase; background: radial-gradient(circle at 0 0, rgba(255, 255, 255, 0.36), transparent 62%), linear-gradient(135deg, #f7da92, #e8b96f); color: #20140c; cursor: pointer; display: inline-flex; align-items: center; justify-content: center; gap: 8px; box-shadow: 0 14px 28px rgba(0, 0, 0, 0.7), 0 0 0 1px rgba(255, 255, 255, 0.6); position: relative; overflow: hidden; transition: transform 0.2s ease, box-shadow 0.2s ease, filter 0.2s ease, opacity 0.15s ease; } .primary-btn:active { transform: translateY(1px) scale(0.98); box-shadow: 0 6px 18px rgba(0, 0, 0, 0.8); filter: brightness(0.95); opacity: 0.9; } .primary-btn::after { content: ""; position: absolute; inset: 0; background: linear-gradient(120deg, rgba(255, 255, 255, 0.4), transparent 40%); mix-blend-mode: soft-light; opacity: 0.7; pointer-events: none; } .primary-btn-icon { width: 18px; height: 18px; border-radius: 999px; border: 1px solid rgba(32, 20, 12, 0.4); display: inline-flex; align-items: center; justify-content: center; font-size: 12px; background: rgba(255, 255, 255, 0.55); } .secondary-link { font-size: 12px; color: var(--text-muted); text-decoration: underline; text-underline-offset: 4px; opacity: 0.9; } .section { border-radius: var(--radius-xl); padding: 12px 14px 12px; background: var(--bg-soft); box-shadow: 0 18px 40px rgba(0, 0, 0, 0.85); border: 1px solid var(--border-subtle); } .section-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; } .section-title { font-size: 13px; letter-spacing: 0.18em; text-transform: uppercase; color: var(--text-muted); } .section-badge { padding: 2px 8px; border-radius: 999px; border: 1px solid rgba(255, 255, 255, 0.18); font-size: 10px; color: var(--accent-strong); letter-spacing: 0.16em; text-transform: uppercase; } .layout-tabs { display: flex; gap: 8px; margin-bottom: 10px; } .layout-pill { flex: 1; padding: 7px 10px; border-radius: 999px; border: 1px solid rgba(255, 255, 255, 0.04); background: radial-gradient(circle at 10% 0%, rgba(255, 255, 255, 0.08), transparent 55%), rgba(10, 11, 28, 0.9); font-size: 11px; display: flex; align-items: center; justify-content: space-between; color: var(--text-muted); cursor: pointer; position: relative; overflow: hidden; transition: background 0.2s ease, border-color 0.2s ease, color 0.2s ease, transform 0.15s ease; } .layout-pill span:first-child { text-transform: uppercase; letter-spacing: 0.16em; font-size: 10px; } .layout-pill span:last-child { font-size: 11px; opacity: 0.8; } .layout-pill.active { border-color: rgba(236, 203, 124, 0.7); color: var(--accent-strong); background: radial-gradient(circle at 20% 0%, rgba(247, 218, 146, 0.45), transparent 65%), rgba(17, 16, 33, 0.96); box-shadow: var(--shadow-glow); transform: translateY(-1px); } .layout-pill::after { content: ""; position: absolute; inset: 0; background: linear-gradient(120deg, rgba(255, 255, 255, 0.2), transparent 50%); mix-blend-mode: soft-light; opacity: 0; transition: opacity 0.2s ease; } .layout-pill.active::after { opacity: 0.9; } .spread-stage { border-radius: var(--radius-lg); padding: 10px 10px 10px; background: radial-gradient(circle at 0 0, rgba(112, 146, 210, 0.18), transparent 60%), linear-gradient(145deg, rgba(5, 7, 21, 0.98), rgba(4, 6, 18, 0.98)); border: 1px solid rgba(255, 255, 255, 0.08); box-shadow: 0 14px 32px rgba(0, 0, 0, 0.85); position: relative; overflow: hidden; } .spread-stage::before { content: ""; position: absolute; inset: -20%; background-image: radial-gradient(circle at 30% 0%, rgba(236, 203, 124, 0.18), transparent 60%); opacity: 0; transition: opacity 0.5s ease; pointer-events: none; } .spread-stage.is-shuffling::before { opacity: 1; animation: halo-pulse 1.4s ease-in-out infinite; } @keyframes halo-pulse { 0%, 100% { opacity: 0.2; transform: translateY(0); } 50% { opacity: 0.8; transform: translateY(-4px); } } .spread-guides { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; font-size: 10px; color: var(--text-muted); letter-spacing: 0.18em; text-transform: uppercase; } .spread-guides .dotline { flex: 1; height: 1px; border-top: 1px dashed rgba(255, 255, 255, 0.18); margin: 0 6px; } .deck { margin-top: 4px; padding: 4px 0 8px; position: relative; height: 150px; } .deck-stack { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); width: 104px; height: 154px; perspective: 1200px; } .tarot-card { width: 100%; height: 100%; border-radius: 18px; position: absolute; left: 0; top: 0; background: var(--card-back); border: 1px solid rgba(248, 234, 192, 0.9); box-shadow: 0 18px 40px rgba(3, 4, 12, 0.96); cursor: pointer; transform-origin: center center; transform-style: preserve-3d; backface-visibility: hidden; transition: transform 400ms cubic-bezier(0.19, 1, 0.22, 1), box-shadow 0.4s ease, filter 0.3s ease, opacity 0.25s ease; } .tarot-card-back-inner { position: absolute; inset: 7px; border-radius: 13px; border: 1px solid rgba(236, 203, 124, 0.9); background: radial-gradient(circle at 50% 0, rgba(255, 252, 240, 0.7), transparent 55%), repeating-linear-gradient(135deg, rgba(237, 232, 216, 0.32) 0, rgba(237, 232, 216, 0.32) 1px, transparent 1px, transparent 6px), rgba(6, 8, 20, 0.96); display: flex; align-items: center; justify-content: center; overflow: hidden; } .tarot-sigil { width: 78px; height: 78px; border-radius: 999px; border: 1px solid rgba(17, 23, 50, 0.3); background: radial-gradient(circle at 50% 0, rgba(247, 218, 146, 0.85), transparent 60%), conic-gradient(from 220deg, rgba(12, 17, 35, 0.96), rgba(16, 23, 51, 0.96), rgba(12, 17, 35, 0.96)); position: relative; box-shadow: 0 0 35px rgba(236, 203, 124, 0.7); } .tarot-sigil-ring { position: absolute; inset: 9px; border-radius: inherit; border: 1px dashed rgba(13, 16, 36, 0.9); border-bottom: none; } .tarot-sigil-star { position: absolute; inset: 18px; border-radius: inherit; border: 1px solid rgba(243, 237, 219, 0.85); clip-path: polygon(50% 2%, 65% 35%, 98% 35%, 72% 57%, 82% 94%, 50% 72%, 18% 94%, 28% 57%, 2% 35%, 35% 35%); box-shadow: inset 0 0 18px rgba(255, 255, 255, 0.9); } .tarot-sigil-glyph { position: absolute; inset: 28px; display: flex; align-items: center; justify-content: center; font-family: 'Cinzel', serif; font-size: 14px; letter-spacing: 0.4em; text-transform: uppercase; } .tarot-card:nth-child(1) { transform: translate3d(0, 0, 0) rotate(0deg); } .tarot-card:nth-child(2) { transform: translate3d(1px, 2px, -10px) rotate(-1deg); opacity: 0.97; } .tarot-card:nth-child(3) { transform: translate3d(-1px, 4px, -20px) rotate(1deg); opacity: 0.94; } .tarot-card.is-hovered { transform: translate3d(0, -10px, 30px) rotate(0deg); box-shadow: 0 28px 80px rgba(0, 0, 0, 0.98); filter: saturate(1.12); } .tarot-card.is-drawn { transform: translate3d(0, -34px, 120px) scale(1.02) rotate(0deg); box-shadow: 0 40px 90px rgba(0, 0, 0, 0.98), 0 0 60px rgba(236, 203, 124, 0.8); } .deck-subtext { text-align: center; font-size: 11px; color: var(--text-muted); margin-top: 6px; } .deck-subtext-strong { color: var(--accent-strong); letter-spacing: 0.18em; text-transform: uppercase; font-size: 10px; } .insight { display: grid; grid-template-columns: 1.4fr 2fr; gap: 8px; margin-top: 10px; font-size: 12px; } .insight-label { text-transform: uppercase; letter-spacing: 0.16em; color: var(--text-muted); font-size: 10px; } .insight-main { color: var(--text-main); } .insight-tags { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 6px; } .chip { border-radius: 999px; padding: 3px 7px; font-size: 10px; border: 1px solid rgba(255, 255, 255, 0.16); background: rgba(7, 9, 26, 0.9); color: var(--text-muted); display: inline-flex; align-items: center; gap: 4px; } .chip-dot { width: 5px; height: 5px; border-radius: 999px; background: var(--accent-strong); } .bottom-bar { margin-top: auto; display: flex; align-items: center; justify-content: space-between; gap: 12px; font-size: 11px; color: var(--text-muted); } .bottom-bar-meta { display: flex; flex-direction: column; gap: 2px; } .bottom-bar-meter { width: 100px; height: 4px; border-radius: 999px; background: rgba(255, 255, 255, 0.04); overflow: hidden; position: relative; } .bottom-bar-meter-fill { position: absolute; inset: 0; width: 45%; border-radius: inherit; background: linear-gradient(90deg, rgba(236, 203, 124, 0.8), rgba(112, 178, 215, 0.9)); box-shadow: 0 0 16px rgba(236, 203, 124, 0.7); } .bottom-bar-actions { display: flex; gap: 8px; } .ghost-btn { padding: 6px 10px; border-radius: 999px; border: 1px solid rgba(255, 255, 255, 0.14); background: rgba(5, 7, 22, 0.9); font-size: 11px; color: var(--text-muted); display: inline-flex; align-items: center; gap: 4px; cursor: pointer; letter-spacing: 0.14em; text-transform: uppercase; transition: background 0.2s ease, border-color 0.2s ease, color 0.2s ease, transform 0.15s ease; } .ghost-btn span { font-size: 13px; } .ghost-btn:active { background: rgba(16, 18, 38, 0.96); border-color: rgba(236, 203, 124, 0.7); color: var(--accent-strong); transform: translateY(1px); } .sheet { position: fixed; left: 50%; bottom: 0; transform: translateX(-50%) translateY(100%); width: 100%; max-width: 520px; max-height: min(76vh, 620px); background: linear-gradient(to top, rgba(3, 4, 10, 0.98), rgba(12, 16, 32, 0.98)); border-radius: 24px 24px 0 0; box-shadow: 0 -22px 60px rgba(0, 0, 0, 0.96); border-top: 1px solid rgba(236, 203, 124, 0.4); border-inline: 1px solid rgba(255, 255, 255, 0.06); padding: 10px 18px 18px; display: flex; flex-direction: column; gap: 10px; z-index: 40; opacity: 0; pointer-events: none; transition: transform 260ms cubic-bezier(0.19, 1, 0.22, 1), opacity 200ms ease; } .sheet.visible { transform: translateX(-50%) translateY(0%); opacity: 1; pointer-events: auto; } .sheet-header { display: flex; align-items: center; justify-content: space-between; gap: 8px; } .sheet-title { display: flex; flex-direction: column; gap: 2px; } .sheet-eyebrow { font-size: 10px; letter-spacing: 0.18em; text-transform: uppercase; color: var(--text-muted); } .sheet-heading { font-size: 16px; letter-spacing: 0.12em; text-transform: uppercase; } .sheet-close { width: 30px; height: 30px; border-radius: 999px; border: 1px solid rgba(255, 255, 255, 0.18); display: inline-flex; align-items: center; justify-content: center; color: var(--text-muted); background: rgba(8, 10, 26, 0.96); cursor: pointer; font-size: 15px; } .sheet-handle { align-self: center; width: 44px; height: 4px; border-radius: 999px; background: rgba(255, 255, 255, 0.18); margin-top: -2px; } .sheet-body { flex: 1; overflow-y: auto; padding: 4px 0 0; font-size: 13px; color: var(--text-main); } .sheet-body::-webkit-scrollbar { width: 4px; } .sheet-body::-webkit-scrollbar-track { background: transparent; } .sheet-body::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, 0.18); border-radius: 999px; } .result-layout { display: flex; gap: 10px; margin-bottom: 12px; } .result-card { width: 110px; min-width: 110px; height: 170px; border-radius: 18px; background: var(--card-front); border: 1px solid rgba(247, 218, 146, 0.7); box-shadow: 0 18px 46px rgba(0, 0, 0, 0.9); position: relative; overflow: hidden; } .result-card-header { position: absolute; top: 8px; left: 0; right: 0; text-align: center; font-size: 10px; color: var(--text-muted); letter-spacing: 0.18em; text-transform: uppercase; } .result-card-art { position: absolute; inset: 26px 12px 38px; border-radius: 14px; border: 1px solid rgba(219, 192, 142, 0.7); overflow: hidden; background: radial-gradient(circle at 50% 0, rgba(251, 240, 211, 0.95), transparent 55%), conic-gradient(from 200deg, #f2c68c, #f7da92, #e8b96f, #f2c68c); display: flex; align-items: center; justify-content: center; } .result-card-symbol { width: 44px; height: 44px; border-radius: 999px; border: 1px solid rgba(122, 92, 58, 0.9); background: radial-gradient(circle at 50% 0, rgba(255, 255, 255, 0.8), transparent 60%), linear-gradient(140deg, #f0c493, #d69650); display: flex; align-items: center; justify-content: center; font-family: 'Cinzel', serif; font-size: 20px; color: #2c1609; } .result-card-footer { position: absolute; bottom: 10px; left: 0; right: 0; text-align: center; font-size: 11px; letter-spacing: 0.18em; text-transform: uppercase; } .result-meta { flex: 1; display: flex; flex-direction: column; gap: 6px; } .result-chip-row { display: flex; gap: 6px; flex-wrap: wrap; } .result-name { font-size: 16px; letter-spacing: 0.06em; } .result-position { font-size: 11px; color: var(--accent-strong); letter-spacing: 0.18em; text-transform: uppercase; } .result-paragraph { font-size: 13px; line-height: 1.6; color: var(--text-main); opacity: 0.96; } .result-section-title { margin-top: 10px; font-size: 11px; letter-spacing: 0.18em; text-transform: uppercase; color: var(--text-muted); } .result-bullets { margin-top: 6px; padding-left: 16px; font-size: 12px; line-height: 1.7; color: var(--text-main); } .history-list { display: flex; flex-direction: column; gap: 8px; margin-top: 4px; font-size: 12px; } .history-item { padding: 8px 10px; border-radius: 12px; border: 1px solid rgba(255, 255, 255, 0.08); background: rgba(8, 10, 26, 0.96); display: flex; justify-content: space-between; align-items: center; gap: 8px; } .history-main { display: flex; flex-direction: column; gap: 3px; } .history-meta { font-size: 11px; color: var(--text-muted); } .history-pill { padding: 2px 8px; border-radius: 999px; border: 1px solid rgba(236, 203, 124, 0.55); font-size: 10px; color: var(--accent-strong); letter-spacing: 0.18em; text-transform: uppercase; } .guide-section { margin-bottom: 10px; } .guide-title { font-size: 13px; margin-bottom: 4px; } .guide-text { font-size: 12px; line-height: 1.7; color: var(--text-main); opacity: 0.96; } .guide-steps { margin-top: 6px; padding-left: 16px; font-size: 12px; line-height: 1.7; color: var(--text-main); } .overlay-mask { position: fixed; inset: 0; background: radial-gradient(circle at top, rgba(0, 0, 0, 0.85), rgba(0, 0, 0, 0.96)); backdrop-filter: blur(18px); opacity: 0; pointer-events: none; transition: opacity 200ms ease; z-index: 30; } .overlay-mask.visible { opacity: 1; pointer-events: auto; } @media (max-width: 360px) { .hero-title-main { font-size: 22px; } .hero-card { padding: 14px 12px 10px; } .hero-moon-orbit { display: none; } .result-layout { flex-direction: column; } .result-card { margin: 0 auto; } .sheet { border-radius: 18px 18px 0 0; } } @media (min-width: 520px) { .app-shell { padding-top: 28px; padding-bottom: 26px; } } </style> </head> <body> <div class="app-shell"> <header class="chrome"> <div class="brand"> <div class="brand-mark"></div> <div class="brand-text"> <div class="brand-name">Moon Arcana</div> <div class="brand-sub">Tarot Studio</div> </div> </div> <div class="chrome-actions"> <button class="icon-button" id="btnHistory" aria-label="历史记录"> <span></span> </button> <button class="icon-button" id="btnGuide" aria-label="使用指引"> <span>?</span> </button> </div> </header> <main> <section class="hero-card"> <div class="hero-top"> <div class="hero-copy"> <div class="hero-tag"> <span class="hero-tag-dot"></span> <span>即时占卜 · 单张牌</span> </div> <div class="hero-title-main">TAROT</div> <div class="hero-title-sub"> 闭上眼,默念心中问题,<br> 在月光下,为自己抽一张牌。 </div> </div> <div class="hero-moon-orbit"> <div class="orbit-ring"> <div class="orbit-moon"></div> <div class="orbit-dot"></div> </div> </div> </div> <div class="hero-meta"> <div class="hero-meta-col"> <div class="hero-meta-label">今日月相</div> <div class="hero-meta-value"> <span id="moonPhase">···</span> </div> </div> <div class="hero-meta-col hero-cta"> <button class="primary-btn" id="btnDraw"> <span>开始抽牌</span> <span class="primary-btn-icon"></span> </button> </div> </div> </section> <section class="section"> <div class="section-header"> <div class="section-title">抽牌布局</div> <div class="section-badge">单牌心占 · H5</div> </div> <div class="layout-tabs"> <button class="layout-pill active" data-layout="single"> <span>Single</span> <span>单张牌 · 当下心境</span> </button> <button class="layout-pill" data-layout="three"> <span>3-Path</span> <span>过去 / 现在 / 未来</span> </button> </div> <div class="spread-stage" id="spreadStage"> <div class="spread-guides"> <span>洗牌中</span> <div class="dotline"></div> <span>当你准备好,点按抽牌</span> </div> <div class="deck"> <div class="deck-stack" id="deck"> <div class="tarot-card"> <div class="tarot-card-back-inner"> <div class="tarot-sigil"> <div class="tarot-sigil-ring"></div> <div class="tarot-sigil-star"></div> <div class="tarot-sigil-glyph">MA</div> </div> </div> </div> <div class="tarot-card"> <div class="tarot-card-back-inner"> <div class="tarot-sigil"> <div class="tarot-sigil-ring"></div> <div class="tarot-sigil-star"></div> <div class="tarot-sigil-glyph">MA</div> </div> </div> </div> <div class="tarot-card"> <div class="tarot-card-back-inner"> <div class="tarot-sigil"> <div class="tarot-sigil-ring"></div> <div class="tarot-sigil-star"></div> <div class="tarot-sigil-glyph">MA</div> </div> </div> </div> </div> </div> <div class="deck-subtext"> <div class="deck-subtext-strong">触摸并抽取一张牌</div> <div id="deckMessage">请将注意力停留在一个具体的问题上。</div> </div> </div> <div class="insight"> <div> <div class="insight-label">此刻的你</div> <div class="insight-main" id="insightMood">情绪起伏略大,适合用一张牌安静地照亮内心。</div> </div> <div> <div class="insight-label">建议使用场景</div> <div class="insight-main">情绪整理 / 关系困惑 / 重要决策前的小确认。</div> </div> </div> <div class="insight-tags"> <div class="chip"> <span class="chip-dot"></span> <span>约 1 分钟完成</span> </div> <div class="chip"> <span class="chip-dot"></span> <span>无需账号 · 本地保存</span> </div> <div class="chip"> <span class="chip-dot"></span> <span>支持竖屏 / 手机浏览器</span> </div> </div> </section> </main> <footer class="bottom-bar"> <div class="bottom-bar-meta"> <div>Moon Arcana · 为自己留一刻安静</div> <div class="bottom-bar-meter"> <div class="bottom-bar-meter-fill" id="meterFill"></div> </div> </div> <div class="bottom-bar-actions"> <button class="ghost-btn" id="btnReset"> <span></span> <span>重置</span> </button> </div> </footer> </div> <div class="overlay-mask" id="overlay"></div> <section class="sheet" id="sheetResult" aria-hidden="true"> <div class="sheet-handle"></div> <div class="sheet-header"> <div class="sheet-title"> <div class="sheet-eyebrow">抽牌结果</div> <div class="sheet-heading" id="resultHeading">——</div> </div> <button class="sheet-close" data-close-sheet="result" aria-label="关闭结果"></button> </div> <div class="sheet-body"> <div class="result-layout"> <div class="result-card"> <div class="result-card-header">Moon Arcana</div> <div class="result-card-art"> <div class="result-card-symbol" id="resultSymbol">0</div> </div> <div class="result-card-footer" id="resultShort">——</div> </div> <div class="result-meta"> <div class="result-chip-row"> <div class="chip"> <span class="chip-dot"></span> <span id="resultType">大阿尔卡纳</span> </div> <div class="chip"> <span class="chip-dot"></span> <span id="resultOrientation">正位</span> </div> </div> <div class="result-name" id="resultName">——</div> <div class="result-position" id="resultPositionLabel">此牌正在回应「当下心境」</div> <p class="result-paragraph" id="resultIntro"> —— 占卜尚未开始,请先在月光下抽一张牌。 </p> </div> </div> <div class="result-section-title">牌义摘要</div> <p class="result-paragraph" id="resultSummary"> 当你准备好提问时,这里会为你呈现一段简短但直白的说明,帮助你抓住问题的核心。 </p> <div class="result-section-title">给你的三条提示</div> <ul class="result-bullets" id="resultTips"> <li>有时候答案不是「要不要」,而是「先照顾好自己」。</li> <li>你可以把看到的第一句话,记在心里或写在纸上。</li> <li>这不是命令,而是一面镜子 —— 你依然拥有选择。</li> </ul> </div> </section> <section class="sheet" id="sheetHistory" aria-hidden="true"> <div class="sheet-handle"></div> <div class="sheet-header"> <div class="sheet-title"> <div class="sheet-eyebrow">占卜记录</div> <div class="sheet-heading">本机最近 5 次</div> </div> <button class="sheet-close" data-close-sheet="history" aria-label="关闭历史"></button> </div> <div class="sheet-body"> <div class="history-list" id="historyList"> <div class="history-item"> <div class="history-main"> <div>暂无记录</div> <div class="history-meta">首次使用时,我们会在这里为你保留最近的牌面。</div> </div> <div class="history-pill">Empty</div> </div> </div> </div> </section> <section class="sheet" id="sheetGuide" aria-hidden="true"> <div class="sheet-handle"></div> <div class="sheet-header"> <div class="sheet-title"> <div class="sheet-eyebrow">使用指南</div> <div class="sheet-heading">如何与这副牌相处</div> </div> <button class="sheet-close" data-close-sheet="guide" aria-label="关闭指南"></button> </div> <div class="sheet-body"> <div class="guide-section"> <div class="guide-title">1. 先问自己,而不是问牌</div> <p class="guide-text"> 在点击「开始抽牌」前,先默念一个清晰的问题。<br> 与其问「TA 爱不爱我」,不如问:「在这段关系中,我真正需要看见的是什么?」。 </p> </div> <div class="guide-section"> <div class="guide-title">2. 不要疯狂刷新</div> <p class="guide-text"> 你当然可以反复抽牌,但 Moon Arcana 更鼓励你:<br> 一次抽取,一次认真阅读,一次真正停下来面对自己。 </p> <ul class="guide-steps"> <li>抽到的第一张牌,往往最接近你当下的直觉。</li> <li>如果真的想再次占卜,请先换一个提问角度。</li> <li>历史记录只存储在本地浏览器,不会同步到任何服务端。</li> </ul> </div> <div class="guide-section"> <div class="guide-title">3. 把解读当作「协商」,不是「宣判」</div> <p class="guide-text"> 牌义是一个邀请,而不是命令。你完全可以不同意某些句子,也可以只带走最打动你的那一句。<br> 如果某段话让你不舒服,请温柔地对自己说:「谢谢你提醒我,我会用适合自己的方式走下去」。 </p> </div> <div class="guide-section"> <div class="guide-title">4. 关于隐私与边界</div> <p class="guide-text"> 占卜记录仅保存在你的设备浏览器中,不会上传到云端。<br> 如果你在公共环境下使用,建议抽完牌后长按电源键或锁屏,让这段对话只属于你自己。 </p> </div> </div> </section> <script> const deckEl = document.getElementById('deck'); const cards = Array.from(deckEl.querySelectorAll('.tarot-card')); const spreadStage = document.getElementById('spreadStage'); const btnDraw = document.getElementById('btnDraw'); const deckMessage = document.getElementById('deckMessage'); const overlay = document.getElementById('overlay'); const sheetResult = document.getElementById('sheetResult'); const sheetHistory = document.getElementById('sheetHistory'); const sheetGuide = document.getElementById('sheetGuide'); const btnHistory = document.getElementById('btnHistory'); const btnGuide = document.getElementById('btnGuide'); const btnReset = document.getElementById('btnReset'); const layoutPills = Array.from(document.querySelectorAll('.layout-pill')); const meterFill = document.getElementById('meterFill'); const moonPhaseEl = document.getElementById('moonPhase'); const resultHeading = document.getElementById('resultHeading'); const resultSymbol = document.getElementById('resultSymbol'); const resultShort = document.getElementById('resultShort'); const resultType = document.getElementById('resultType'); const resultOrientation = document.getElementById('resultOrientation'); const resultName = document.getElementById('resultName'); const resultPositionLabel = document.getElementById('resultPositionLabel'); const resultIntro = document.getElementById('resultIntro'); const resultSummary = document.getElementById('resultSummary'); const resultTips = document.getElementById('resultTips'); const historyList = document.getElementById('historyList'); let isShuffling = false; let hasDrawn = false; let currentLayout = 'single'; let currentResult = null; const TAROT_POOL = [ { id: 0, name: '愚者', short: '新的旅程', type: '大阿尔卡纳', symbol: '0', summary: '愚者代表一切的起点 —— 你正站在悬崖边,手里只拿着最重要的行囊,准备迈向一个未知却诚实的方向。', intro: '这张牌并不是鼓励你盲目冒险,而是提醒你:你拥有重新出发的资格。也许你并没有准备好所有答案,但你已经厌倦停留在原地。', tips: [ '允许自己在「不知道」中迈出小小一步,而不是逼迫自己马上看见全程路线。', '你可以把这段经历当成一次试验,而不是一次考试 —— 失败并不会让你失去被爱的资格。', '注意区分「真心的好奇」与「为了逃避而冲动」。前者会让你更靠近自己。' ] }, { id: 1, name: '魔术师', short: '自我主导', type: '大阿尔卡纳', symbol: 'Ⅰ', summary: '魔术师像是一条介于天地之间的闪电,提醒你:答案并不在外面,而在你愿不愿意使用手上已有的工具。', intro: '也许你正在寻找一个「完美时机」,但魔术师告诉你:当你开始行动,那一刻就是对的时机。', tips: [ '写下你已经拥有的三样资源(能力、人脉、时间、经验),并尝试用它们拼出一个最小行动方案。', '避免一次性承诺太多,先完成一个微小而可验证的动作。', '如果你习惯把自己放低,请允许自己在这个议题上稍微「自信一点点」。' ] }, { id: 2, name: '女祭司', short: '直觉之海', type: '大阿尔卡纳', symbol: 'Ⅱ', summary: '女祭司安静地坐在门槛上,身后是帷幕与深海。她不急着给出答案,她在等你安静下来,听见自己真正的声音。', intro: '你现在最需要的不是更多信息,而是给自己一段没有干扰的时间,好好区分:哪些是别人的期待,哪些才是你心里真正在意的事情。', tips: [ '本周找一个不被打扰的 20 分钟,只和自己待在一起,把心里最吵的三句话写下来。', '当你感到犹豫时,先不要做决定,把注意力放回身体:是哪里在紧绷?哪里在松开?', '如果一件事让你感到「隐隐不对劲」,那已经是一种答案。你可以选择慢一点。' ] }, { id: 3, name: '恋人', short: '真诚选择', type: '大阿尔卡纳', symbol: 'Ⅵ', summary: '恋人牌并不仅仅指爱情,它更关乎「我是否愿意为这个选择承担真诚的承诺」。', intro: '你很有可能正站在一条分岔路口。无论是关系、工作还是生活方式,这张牌提醒你 —— 你在选择的不只是对象,而是想成为的那种自己。', tips: [ '把你正在纠结的两个选项分别写下,并补上一句:「当我选择它时,我是在成为什么样的人?」', '注意那些让你必须不断「说服自己」的决定,它们也许并不那么适合你。', '允许关系里存在不完美的部分,但不要牺牲掉最基本的尊重与安宁感。' ] }, { id: 4, name: '力量', short: '柔软的勇气', type: '大阿尔卡纳', symbol: 'Ⅷ', summary: '力量不是咬紧牙关硬撑,而是在脆弱与恐惧面前,依然愿意温柔而坚定地活下去。', intro: '你最近可能已经耗费了不少精神去「撑住一切」。这张牌提醒你:真正的力量,允许自己偶尔放下盔甲。', tips: [ '列出一件你最近「勉强自己」去做的事,问问自己:如果不再逞强,我还有没有别的选择?', '给自己安排一个真正意义上的休息,而不是只是换一种形式的忙碌。', '当你向可信任的人示弱时,那不是失败,而是一种对生命的信任。' ] } ]; function getMoonPhaseText() { const now = new Date(); const lp = 2551443; const newMoon = new Date(1970, 0, 7, 20, 35, 0); const phase = ((now.getTime() - newMoon.getTime()) / 1000) % lp; const phaseIndex = Math.floor((phase / lp) * 8); const phases = [ '新月 · 适合种下一个新的念头', '娥眉月 · 小小的行动就足够', '上弦月 · 给自己一个明确选择', '盈凸月 · 事情逐渐清晰起来', '满月 · 情绪与答案都被照亮', '亏凸月 · 学会放下和整理', '下弦月 · 为下一次出发做准备', '残月 · 对自己温柔一点' ]; return phases[phaseIndex] || '月亮正在为你保留一个安静的夜晚'; } function randomFrom(arr) { return arr[Math.floor(Math.random() * arr.length)]; } function setMeter(target) { meterFill.style.width = target + '%'; } function openSheet(sheet) { overlay.classList.add('visible'); sheet.classList.add('visible'); sheet.setAttribute('aria-hidden', 'false'); } function closeSheet(sheet) { sheet.classList.remove('visible'); sheet.setAttribute('aria-hidden', 'true'); if (!sheetResult.classList.contains('visible') && !sheetHistory.classList.contains('visible') && !sheetGuide.classList.contains('visible')) { overlay.classList.remove('visible'); } } function renderResult(card, layoutLabel) { const orientation = Math.random() < 0.75 ? '正位' : '逆位'; const intro = card.intro; const summary = card.summary; currentResult = { id: card.id, name: card.name, type: card.type, orientation, short: card.short, layout: layoutLabel, ts: Date.now() }; resultHeading.textContent = card.name + ' · ' + (orientation === '正位' ? '正位' : '逆位'); resultSymbol.textContent = card.symbol; resultShort.textContent = card.short; resultType.textContent = card.type; resultOrientation.textContent = orientation; resultName.textContent = card.name + '(' + card.short + ')'; resultPositionLabel.textContent = '此牌正在回应「' + layoutLabel + '」'; resultIntro.textContent = intro; resultSummary.textContent = summary; resultTips.innerHTML = ''; card.tips.forEach(t => { const li = document.createElement('li'); li.textContent = t; resultTips.appendChild(li); }); } function loadHistory() { const raw = localStorage.getItem('moon-arcana-history'); if (!raw) return []; try { const list = JSON.parse(raw); if (Array.isArray(list)) return list; } catch (_) {} return []; } function saveHistory() { if (!currentResult) return; const list = loadHistory(); list.unshift(currentResult); const trimmed = list.slice(0, 5); localStorage.setItem('moon-arcana-history', JSON.stringify(trimmed)); renderHistory(trimmed); } function renderHistory(list) { historyList.innerHTML = ''; if (!list.length) { const item = document.createElement('div'); item.className = 'history-item'; item.innerHTML = '<div class="history-main"><div>暂无记录</div><div class="history-meta">首次使用时,我们会在这里为你保留最近的牌面。</div></div><div class="history-pill">Empty</div>'; historyList.appendChild(item); return; } list.forEach(entry => { const date = new Date(entry.ts); const label = date.toLocaleString('zh-CN', { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' }); const item = document.createElement('div'); item.className = 'history-item'; item.innerHTML = ` <div class="history-main"> <div>${entry.name} · ${entry.orientation}</div> <div class="history-meta">${label} · 布局:${entry.layout}</div> </div> <div class="history-pill">${entry.type === '大阿尔卡纳' ? 'Major' : 'Minor'}</div> `; item.addEventListener('click', () => { const card = TAROT_POOL.find(c => c.id === entry.id); if (!card) return; renderResult(card, entry.layout); openSheet(sheetResult); }); historyList.appendChild(item); }); } function resetDeck() { hasDrawn = false; isShuffling = false; spreadStage.classList.remove('is-shuffling'); cards.forEach((card, index) => { card.classList.remove('is-drawn'); card.style.transform = ''; card.style.opacity = ''; void card.offsetWidth; if (index === 0) { card.style.transform = 'translate3d(0,0,0) rotate(0deg)'; } else if (index === 1) { card.style.transform = 'translate3d(1px,2px,-10px) rotate(-1deg)'; card.style.opacity = '0.97'; } else if (index === 2) { card.style.transform = 'translate3d(-1px,4px,-20px) rotate(1deg)'; card.style.opacity = '0.94'; } }); deckMessage.textContent = '请将注意力停留在一个具体的问题上。'; setMeter(45); } function startShuffle() { if (isShuffling) return; isShuffling = true; spreadStage.classList.add('is-shuffling'); deckMessage.textContent = '轻轻触摸牌堆,或点击「开始抽牌」,当你感觉刚刚好,就在那一刻停下。'; setMeter(60); cards.forEach((card, index) => { const baseDelay = index * 100; const animate = () => { if (!isShuffling || hasDrawn) return; const offsetX = (Math.random() - 0.5) * 6; const offsetY = (Math.random() - 0.5) * 6; const rotate = (Math.random() - 0.5) * 4; card.style.transform = `translate3d(${offsetX}px, ${offsetY}px, ${index * -10}px) rotate(${rotate}deg)`; card.style.opacity = 0.9 + (3 - index) * 0.03; setTimeout(animate, 700 + index * 120); }; setTimeout(animate, baseDelay + 150); }); } function drawCard() { if (hasDrawn) { openSheet(sheetResult); return; } if (!isShuffling) { startShuffle(); } hasDrawn = true; isShuffling = false; spreadStage.classList.remove('is-shuffling'); deckMessage.textContent = '这张牌正在为你发声。缓一缓,再点击下方结果。'; setMeter(85); const targetCard = randomFrom(cards); cards.forEach(card => { card.classList.remove('is-hovered'); if (card !== targetCard) { card.style.opacity = '0.18'; card.style.transform += ' translate3d(0,10px,-40px) scale(0.92)'; } }); targetCard.classList.add('is-drawn'); setTimeout(() => { const picked = randomFrom(TAROT_POOL); const layoutLabel = currentLayout === 'single' ? '当下心境' : '过去 / 现在 / 未来的交汇点'; renderResult(picked, layoutLabel); saveHistory(); openSheet(sheetResult); }, 700); } cards.forEach(card => { card.addEventListener('pointerenter', () => { if (hasDrawn) return; card.classList.add('is-hovered'); }); card.addEventListener('pointerleave', () => { card.classList.remove('is-hovered'); }); card.addEventListener('click', () => drawCard()); card.addEventListener('touchstart', (e) => { e.preventDefault(); drawCard(); }, { passive: false }); }); btnDraw.addEventListener('click', () => { if (!isShuffling && !hasDrawn) { startShuffle(); setTimeout(drawCard, 900); } else { drawCard(); } }); btnReset.addEventListener('click', () => { resetDeck(); }); btnHistory.addEventListener('click', () => { renderHistory(loadHistory()); openSheet(sheetHistory); btnHistory.classList.add('active'); setTimeout(() => btnHistory.classList.remove('active'), 260); }); btnGuide.addEventListener('click', () => { openSheet(sheetGuide); btnGuide.classList.add('active'); setTimeout(() => btnGuide.classList.remove('active'), 260); }); overlay.addEventListener('click', () => { [sheetResult, sheetHistory, sheetGuide].forEach(closeSheet); }); document.querySelectorAll('.sheet-close').forEach(btn => { btn.addEventListener('click', () => { const target = btn.getAttribute('data-close-sheet'); if (target === 'result') closeSheet(sheetResult); if (target === 'history') closeSheet(sheetHistory); if (target === 'guide') closeSheet(sheetGuide); }); }); layoutPills.forEach(pill => { pill.addEventListener('click', () => { layoutPills.forEach(p => p.classList.remove('active')); pill.classList.add('active'); currentLayout = pill.getAttribute('data-layout') || 'single'; if (currentLayout === 'single') { deckMessage.textContent = '请将注意力停留在一个具体的问题上。'; setMeter(45); document.getElementById('insightMood').textContent = '情绪起伏略大,适合用一张牌安静地照亮内心。'; } else { deckMessage.textContent = '过去、现在、未来交织在一起,请带着耐心看清时间给你的答案。'; setMeter(52); document.getElementById('insightMood').textContent = '你似乎正在回顾一段长线故事,这个布局会帮你看见时间的脉络。'; } }); }); function init() { resetDeck(); const history = loadHistory(); renderHistory(history); moonPhaseEl.textContent = getMoonPhaseText(); } document.addEventListener('DOMContentLoaded', init); </script> </body> </html>

对应上面《使用对比》中的2:一遍生成,无任何修改

html
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" /> <title>秘境塔罗 · Tarot H5</title> <style> *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } html, body { height: 100%; } body { font-family: "STHeiti", "PingFang SC", "Hiragino Sans GB", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; background: radial-gradient(circle at top, #1e1035 0, #05020a 55%, #010005 100%); color: #f7f3ff; -webkit-font-smoothing: antialiased; overflow: hidden; } :root { --accent: #ffce6a; --accent-soft: rgba(255, 206, 106, 0.1); --accent-strong: #ff9f4a; --danger: #ff4d7a; --card-bg: rgba(12, 7, 30, 0.96); --card-border: rgba(255, 255, 255, 0.06); --muted: #9c8ac7; --muted-soft: rgba(156, 138, 199, 0.16); --surface: rgba(10, 4, 24, 0.9); --radius-lg: 22px; --radius-md: 14px; --blur-strong: 32px; --page-padding: 18px; } body::before { content: ""; position: fixed; inset: -40%; background: radial-gradient(circle at 20% 0%, rgba(255, 231, 153, 0.18), transparent 55%), radial-gradient(circle at 90% 10%, rgba(139, 92, 246, 0.22), transparent 60%), radial-gradient(circle at 0% 80%, rgba(56, 189, 248, 0.12), transparent 55%); mix-blend-mode: screen; opacity: 0.75; pointer-events: none; z-index: -1; } .app-shell { position: relative; max-width: 480px; height: 100vh; margin: 0 auto; padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left); display: flex; flex-direction: column; } .app-frame { flex: 1; margin: 10px var(--page-padding) 6px; background: linear-gradient(145deg, rgba(15, 10, 38, 0.98), rgba(3, 2, 15, 0.98)); border-radius: 28px; box-shadow: 0 25px 80px rgba(0, 0, 0, 0.85), 0 0 0 1px rgba(255, 255, 255, 0.04); overflow: hidden; position: relative; backdrop-filter: blur(var(--blur-strong)); border: 1px solid rgba(185, 148, 255, 0.18); } .app-chrome { position: absolute; inset: 0; pointer-events: none; border-radius: inherit; background: radial-gradient(circle at 10% 0%, rgba(255, 255, 255, 0.16), transparent 65%), radial-gradient(circle at 100% 100%, rgba(255, 148, 255, 0.16), transparent 60%); mix-blend-mode: soft-light; opacity: 0.6; } .app-content { position: relative; z-index: 1; width: 100%; height: 100%; display: flex; flex-direction: column; padding: 16px 16px 10px; } .app-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; } .app-title-group { display: flex; flex-direction: column; gap: 2px; } .app-logo-word { font-size: 13px; letter-spacing: 0.32em; text-transform: uppercase; color: rgba(255, 255, 255, 0.6); } .app-title { font-size: 20px; letter-spacing: 0.08em; font-weight: 600; display: inline-flex; align-items: baseline; gap: 6px; } .app-title span { background: linear-gradient(120deg, #ffe39a, #ffc46e, #ff9f4a); -webkit-background-clip: text; color: transparent; } .app-title-sub { font-size: 11px; color: var(--muted); } .app-actions { display: flex; align-items: center; gap: 8px; } .icon-btn { width: 28px; height: 28px; border-radius: 999px; border: 1px solid rgba(255, 255, 255, 0.1); background: radial-gradient(circle at 0 0, rgba(255, 255, 255, 0.2), transparent 65%), rgba(8, 4, 22, 0.9); display: inline-flex; align-items: center; justify-content: center; color: var(--muted); font-size: 15px; box-shadow: 0 6px 18px rgba(0, 0, 0, 0.7); backdrop-filter: blur(14px); cursor: pointer; transition: transform 0.16s ease, box-shadow 0.16s ease, border-color 0.16s ease, color 0.16s ease; } .icon-btn:active { transform: translateY(1px) scale(0.98); box-shadow: 0 2px 10px rgba(0, 0, 0, 0.8); } .icon-btn--primary { border-color: rgba(255, 206, 106, 0.5); color: var(--accent); } .app-main { flex: 1; position: relative; overflow: hidden; border-radius: 20px; background: radial-gradient(circle at top, rgba(71, 45, 143, 0.96), rgba(14, 5, 37, 0.96)); box-shadow: inset 0 0 40px rgba(0, 0, 0, 0.65); padding: 14px 12px; display: flex; flex-direction: column; gap: 8px; } .page { position: absolute; inset: 0; padding: 14px 12px 14px; display: flex; flex-direction: column; gap: 14px; opacity: 0; pointer-events: none; transform: translateX(6%); transition: opacity 0.28s ease, transform 0.28s ease; } .page--active { opacity: 1; pointer-events: auto; transform: translateX(0); } .page-header { display: flex; align-items: center; justify-content: space-between; gap: 8px; } .page-title-group { display: flex; flex-direction: column; gap: 3px; } .page-tagline { font-size: 11px; color: var(--muted); letter-spacing: 0.12em; text-transform: uppercase; } .page-title { font-size: 18px; letter-spacing: 0.06em; display: flex; align-items: center; gap: 8px; } .page-title span { background: linear-gradient(120deg, #ffe6aa, #ffbf67, #ff9c4b); -webkit-background-clip: text; color: transparent; } .page-title-badge { font-size: 11px; padding: 2px 8px; border-radius: 999px; border: 1px solid rgba(255, 255, 255, 0.12); background: radial-gradient(circle at 0 0, rgba(255, 255, 255, 0.2), transparent 60%), rgba(9, 3, 26, 0.9); color: var(--muted); } .page-desc { font-size: 12px; line-height: 1.6; color: rgba(234, 224, 255, 0.92); } .page-desc strong { color: var(--accent); } .pill-row { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; margin-top: 2px; } .pill { font-size: 11px; padding: 3px 9px; border-radius: 999px; border: 1px solid rgba(255, 255, 255, 0.12); background: rgba(13, 6, 33, 0.9); color: var(--muted); display: inline-flex; align-items: center; gap: 4px; } .pill-dot { width: 5px; height: 5px; border-radius: 50%; background: radial-gradient(circle, var(--accent), rgba(255, 206, 106, 0.1)); } .card-shell { border-radius: var(--radius-lg); padding: 10px 10px 8px; background: radial-gradient(circle at 0 0, rgba(255, 255, 255, 0.2), transparent 65%), linear-gradient(140deg, rgba(19, 8, 48, 0.97), rgba(17, 4, 42, 0.98)); box-shadow: 0 12px 40px rgba(0, 0, 0, 0.9), 0 0 0 1px rgba(255, 255, 255, 0.06); display: flex; flex-direction: column; gap: 8px; position: relative; overflow: hidden; } .card-shell::before { content: ""; position: absolute; inset: 0; background: linear-gradient(115deg, rgba(255, 230, 182, 0.1), transparent 50%, rgba(156, 138, 199, 0.1)), repeating-linear-gradient(135deg, rgba(95, 68, 155, 0.1), rgba(95, 68, 155, 0.1) 1px, transparent 1px, transparent 3px); mix-blend-mode: soft-light; opacity: 0.7; pointer-events: none; } .hero-row { display: grid; grid-template-columns: 1.1fr 1fr; gap: 10px; align-items: stretch; } .hero-card { border-radius: 20px; background: radial-gradient(circle at 15% 0%, rgba(255, 255, 255, 0.35), transparent 65%), radial-gradient(circle at 100% 100%, rgba(252, 211, 77, 0.5), transparent 60%), linear-gradient(145deg, #1a0828, #11071f); padding: 9px 9px 11px; box-shadow: 0 18px 45px rgba(0, 0, 0, 0.95), 0 0 0 1px rgba(255, 255, 255, 0.16); position: relative; overflow: hidden; } .hero-orbit { position: absolute; inset: 10px 18px 18px; border-radius: 18px; border: 1px dashed rgba(255, 255, 255, 0.18); opacity: 0.75; } .hero-orbit::before, .hero-orbit::after { content: ""; position: absolute; border-radius: 999px; border: 1px solid rgba(255, 255, 255, 0.22); opacity: 0.4; } .hero-orbit::before { inset: 12px 6px; } .hero-orbit::after { inset: 6px 18px; } .hero-card-inner { position: relative; z-index: 1; height: 100%; display: flex; flex-direction: column; justify-content: space-between; gap: 10px; } .hero-card-top { display: flex; align-items: center; justify-content: space-between; gap: 8px; } .hero-chip { font-size: 11px; padding: 2px 7px; border-radius: 999px; border: 1px solid rgba(255, 255, 255, 0.24); background: rgba(5, 2, 14, 0.8); color: rgba(255, 255, 255, 0.78); display: inline-flex; align-items: center; gap: 4px; } .hero-chip-dot { width: 6px; height: 6px; border-radius: 999px; background: radial-gradient(circle, var(--accent), rgba(255, 255, 255, 0.1)); box-shadow: 0 0 8px rgba(255, 228, 181, 0.9); } .hero-constellation { width: 26px; height: 26px; border-radius: 999px; border: 1px solid rgba(255, 255, 255, 0.24); display: inline-flex; align-items: center; justify-content: center; font-size: 14px; color: rgba(255, 255, 255, 0.8); background: radial-gradient(circle at 30% 0%, rgba(255, 255, 255, 0.4), transparent 60%), rgba(4, 2, 15, 0.9); box-shadow: 0 8px 20px rgba(0, 0, 0, 0.9); } .hero-signature { text-align: center; padding-top: 4px; } .hero-signature-main { font-size: 14px; letter-spacing: 0.2em; text-transform: uppercase; color: rgba(255, 255, 255, 0.92); } .hero-signature-sub { font-size: 11px; margin-top: 2px; color: rgba(243, 244, 246, 0.8); } .hero-figure { position: relative; margin-top: 6px; height: 72px; } .hero-moon { position: absolute; top: 4px; left: 50%; transform: translateX(-50%); width: 50px; height: 50px; border-radius: 50%; background: radial-gradient(circle at 30% 15%, #fff7d1, #f7c26c 65%, #e7873e 100%); box-shadow: 0 0 30px rgba(255, 252, 210, 0.85), 0 0 80px rgba(253, 224, 171, 0.7); } .hero-moon::after { content: ""; position: absolute; inset: 4px 2px; border-radius: 50%; background: radial-gradient(circle at 10% 20%, #fffbe8, transparent 55%); mix-blend-mode: screen; } .hero-rays { position: absolute; inset: 12px 10px 0; border-radius: 36px; border: 1px dashed rgba(255, 255, 255, 0.55); opacity: 0.65; } .hero-stars { position: absolute; inset: 10px 8px 0; pointer-events: none; } .hero-stars span { position: absolute; width: 3px; height: 3px; border-radius: 50%; background: radial-gradient(circle, #fff, rgba(255, 255, 255, 0)); box-shadow: 0 0 8px rgba(255, 255, 255, 0.9); } .hero-stars span:nth-child(1) { top: 6px; left: 18%; } .hero-stars span:nth-child(2) { top: 2px; right: 26%; } .hero-stars span:nth-child(3) { top: 28px; left: 8%; } .hero-stars span:nth-child(4) { top: 34px; right: 12%; } .hero-stars span:nth-child(5) { bottom: 10px; left: 26%; } .hero-footer { display: flex; align-items: center; justify-content: space-between; margin-top: 3px; font-size: 11px; color: rgba(229, 231, 235, 0.95); } .hero-footer span { display: inline-flex; align-items: center; gap: 4px; } .hero-footer small { color: rgba(229, 231, 235, 0.6); } .hero-metadata { border-radius: 18px; background: rgba(5, 1, 21, 0.9); border: 1px solid rgba(226, 232, 255, 0.09); padding: 9px 10px; display: flex; flex-direction: column; justify-content: space-between; gap: 10px; position: relative; overflow: hidden; } .hero-metadata::before { content: ""; position: absolute; inset: -20%; background: radial-gradient(circle at 0 0, rgba(255, 255, 255, 0.2), transparent 65%), radial-gradient(circle at 100% 90%, rgba(79, 70, 229, 0.42), transparent 65%); opacity: 0.8; filter: blur(4px); } .hero-metadata-inner { position: relative; z-index: 1; display: flex; flex-direction: column; gap: 8px; } .meta-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; } .meta-row strong { font-size: 12px; letter-spacing: 0.12em; text-transform: uppercase; } .meta-row span { font-size: 11px; color: rgba(209, 213, 219, 0.75); } .progress-track { position: relative; width: 100%; height: 6px; border-radius: 999px; background: rgba(19, 14, 47, 0.95); overflow: hidden; border: 1px solid rgba(148, 163, 184, 0.3); } .progress-bar { position: absolute; inset: 0; width: 72%; background: linear-gradient(90deg, var(--accent), var(--accent-strong), #ff7b7b); box-shadow: 0 0 14px rgba(250, 204, 21, 0.9); } .meta-tags { display: flex; flex-wrap: wrap; gap: 6px; } .meta-tag { font-size: 11px; padding: 2px 8px; border-radius: 999px; background: rgba(15, 23, 42, 0.75); border: 1px solid rgba(148, 163, 184, 0.48); color: rgba(226, 232, 255, 0.9); display: inline-flex; align-items: center; gap: 4px; } .meta-tag-dot { width: 6px; height: 6px; border-radius: 50%; background: linear-gradient(135deg, #4ade80, #22c55e); box-shadow: 0 0 10px rgba(74, 222, 128, 0.9); } .section-caption { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-top: 2px; } .section-caption-left { font-size: 11px; color: var(--muted); display: flex; align-items: center; gap: 6px; } .section-divider { flex: 1; height: 1px; border-radius: 999px; background: linear-gradient(90deg, rgba(107, 114, 128, 0.1), rgba(255, 255, 255, 0.4), rgba(107, 114, 128, 0.1)); opacity: 0.8; } .mode-row { display: flex; gap: 8px; } .mode-card { flex: 1; border-radius: var(--radius-md); background: radial-gradient(circle at 0 0, rgba(255, 255, 255, 0.2), transparent 60%), rgba(8, 3, 26, 0.92); border: 1px solid rgba(148, 163, 184, 0.35); padding: 7px 8px 8px; display: flex; flex-direction: column; gap: 4px; cursor: pointer; transition: transform 0.15s ease, box-shadow 0.15s ease, border-color 0.15s ease, background 0.15s ease; box-shadow: 0 10px 30px rgba(15, 23, 42, 0.9); } .mode-card:hover { transform: translateY(-1px); box-shadow: 0 16px 40px rgba(15, 23, 42, 1); border-color: rgba(249, 250, 251, 0.4); background: radial-gradient(circle at 5% 0, rgba(248, 250, 252, 0.28), transparent 55%), rgba(8, 3, 26, 0.96); } .mode-card--primary { border-color: rgba(252, 211, 77, 0.8); background: radial-gradient(circle at 0 0, rgba(255, 243, 199, 0.28), transparent 55%), rgba(24, 16, 45, 0.96); } .mode-label { display: flex; align-items: center; justify-content: space-between; gap: 4px; } .mode-name { font-size: 13px; font-weight: 500; letter-spacing: 0.08em; text-transform: uppercase; } .mode-badge { font-size: 10px; padding: 1px 6px; border-radius: 999px; border: 1px solid rgba(148, 163, 184, 0.45); color: rgba(209, 213, 219, 0.9); } .mode-desc { font-size: 11px; color: rgba(209, 213, 219, 0.9); line-height: 1.55; } .primary-btn { width: 100%; margin-top: 8px; border-radius: 999px; border: none; padding: 10px 14px; font-size: 15px; letter-spacing: 0.18em; text-transform: uppercase; font-weight: 600; background: linear-gradient(120deg, #fbbf24, #fb923c, #f97316); color: #1f2937; box-shadow: 0 18px 40px rgba(248, 181, 0, 0.9), 0 0 0 1px rgba(255, 237, 213, 0.9); display: inline-flex; align-items: center; justify-content: center; gap: 6px; cursor: pointer; position: relative; overflow: hidden; transition: transform 0.16s ease, box-shadow 0.16s ease, filter 0.16s ease; } .primary-btn span { position: relative; z-index: 1; } .primary-btn::before { content: ""; position: absolute; inset: -40%; background: radial-gradient(circle at 0 0, rgba(255, 255, 255, 0.75), transparent 60%); opacity: 0; transform: translateX(-40%); transition: transform 0.4s ease, opacity 0.4s ease; } .primary-btn:hover::before { opacity: 1; transform: translateX(40%); } .primary-btn:active { transform: translateY(1px) scale(0.985); box-shadow: 0 10px 30px rgba(248, 181, 0, 0.9), 0 0 0 1px rgba(251, 146, 60, 0.8); filter: brightness(0.98); } .secondary-link { margin-top: 4px; text-align: center; font-size: 11px; color: var(--muted); } .secondary-link button { border: none; background: none; color: rgba(248, 250, 252, 0.86); text-decoration: underline; text-underline-offset: 3px; cursor: pointer; padding: 0 2px; font-size: 11px; } .spread-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; margin-top: 4px; } .spread-card { border-radius: 14px; background: rgba(15, 23, 42, 0.96); padding: 6px 6px 7px; border: 1px solid rgba(75, 85, 99, 0.9); display: flex; flex-direction: column; gap: 4px; cursor: pointer; box-shadow: 0 10px 26px rgba(15, 23, 42, 0.95); transition: transform 0.14s ease, box-shadow 0.14s ease, border-color 0.14s ease, background 0.14s ease; } .spread-card:hover { transform: translateY(-1px); border-color: rgba(249, 250, 251, 0.7); background: radial-gradient(circle at 0 0, rgba(248, 250, 252, 0.25), transparent 55%), rgba(15, 23, 42, 0.96); box-shadow: 0 16px 40px rgba(15, 23, 42, 1); } .spread-card--active { border-color: var(--accent); box-shadow: 0 16px 40px rgba(248, 181, 0, 0.85), 0 0 0 1px rgba(251, 191, 36, 0.6); background: radial-gradient(circle at 0 0, rgba(255, 237, 213, 0.3), transparent 60%), rgba(15, 23, 42, 0.98); } .spread-visual { height: 42px; border-radius: 11px; background: repeating-linear-gradient(135deg, rgba(31, 41, 55, 0.9), rgba(31, 41, 55, 0.9) 2px, rgba(17, 24, 39, 0.9) 2px, rgba(17, 24, 39, 0.9) 4px); overflow: hidden; position: relative; display: flex; align-items: center; justify-content: center; gap: 2px; padding: 0 4px; } .spread-visual span { display: block; border-radius: 6px; border: 1px solid rgba(156, 163, 175, 0.9); background: linear-gradient(145deg, #020617, #020617); width: 16px; height: 32px; } .spread-visual--single span { width: 26px; height: 36px; border-radius: 7px; } .spread-name { font-size: 12px; font-weight: 500; color: rgba(249, 250, 251, 0.96); } .spread-meta { font-size: 10px; color: rgba(209, 213, 219, 0.8); } .flow-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-top: 3px; font-size: 11px; color: rgba(209, 213, 219, 0.8); } .flow-steps { display: flex; align-items: center; gap: 4px; } .flow-dot { width: 10px; height: 10px; border-radius: 999px; background: rgba(15, 23, 42, 0.9); border: 1px solid rgba(156, 163, 175, 0.8); display: inline-flex; align-items: center; justify-content: center; font-size: 7px; } .flow-dot--active { background: linear-gradient(135deg, #fbbf24, #f97316); border-color: rgba(250, 204, 21, 0.9); color: #1f2937; box-shadow: 0 0 10px rgba(250, 204, 21, 0.9); } .table-layout { flex: 1; border-radius: 18px; background: radial-gradient(circle at 10% 0, rgba(31, 41, 55, 0.8), transparent 60%), radial-gradient(circle at 100% 100%, rgba(15, 23, 42, 0.95), transparent 60%); border: 1px solid rgba(148, 163, 184, 0.5); margin-top: 2px; padding: 10px 10px 10px; position: relative; overflow: hidden; display: flex; flex-direction: column; justify-content: center; align-items: center; gap: 8px; } .table-layout::before { content: ""; position: absolute; inset: 18px 22px; border-radius: 18px; border: 1px dashed rgba(229, 231, 235, 0.45); opacity: 0.5; } .deck-area { position: relative; width: 78%; max-width: 260px; height: 140px; perspective: 1400px; } .tarot-card { position: absolute; inset: auto; left: 50%; bottom: 0; width: 76px; height: 118px; margin-left: -38px; border-radius: 12px; background: linear-gradient(145deg, #020617, #020617); border: 1px solid rgba(209, 213, 219, 0.85); box-shadow: 0 18px 40px rgba(15, 23, 42, 0.95), 0 0 0 1px rgba(17, 24, 39, 1); transform-origin: center bottom; transform-style: preserve-3d; cursor: pointer; overflow: hidden; } .tarot-card-back { position: absolute; inset: 3px; border-radius: 9px; background: radial-gradient(circle at 0 0, rgba(248, 250, 252, 0.35), transparent 60%), radial-gradient(circle at 100% 100%, rgba(209, 213, 219, 0.55), transparent 65%), repeating-linear-gradient(135deg, rgba(15, 23, 42, 0.9), rgba(15, 23, 42, 0.9) 2px, rgba(15, 23, 42, 1) 2px, rgba(15, 23, 42, 1) 4px); display: flex; align-items: center; justify-content: center; } .tarot-card-sigil { width: 72%; height: 56%; border-radius: 999px; border: 1px solid rgba(249, 250, 251, 0.8); position: relative; display: flex; align-items: center; justify-content: center; overflow: hidden; } .tarot-card-sigil::before, .tarot-card-sigil::after { content: ""; position: absolute; border-radius: inherit; border: 1px solid rgba(249, 250, 251, 0.7); } .tarot-card-sigil::before { inset: 4px 10px; } .tarot-card-sigil::after { inset: 10px 4px; } .tarot-symbol { position: relative; width: 26px; height: 26px; border-radius: 50%; border: 1px solid rgba(249, 250, 251, 0.9); display: flex; align-items: center; justify-content: center; font-size: 14px; } .tarot-symbol::before, .tarot-symbol::after { content: ""; position: absolute; inset: 2px; border-radius: inherit; border: 1px dashed rgba(249, 250, 251, 0.7); } .tarot-symbol::after { inset: 6px; border-style: solid; opacity: 0.7; } .deck-shadow { position: absolute; left: 50%; bottom: -3px; width: 62%; height: 18px; margin-left: -31%; background: radial-gradient(circle at 50% 0, rgba(0, 0, 0, 0.85), transparent 75%); filter: blur(4px); opacity: 0.9; pointer-events: none; } .deck-hint { font-size: 11px; color: rgba(209, 213, 219, 0.85); text-align: center; margin-top: 0; display: flex; align-items: center; justify-content: center; gap: 6px; } .deck-hint span { font-size: 13px; } .table-footer { display: flex; align-items: center; justify-content: space-between; gap: 8px; font-size: 11px; color: rgba(209, 213, 219, 0.8); margin-top: 2px; } .table-footer-left { display: inline-flex; align-items: center; gap: 6px; } .mini-indicator { padding: 2px 7px; border-radius: 999px; border: 1px solid rgba(148, 163, 184, 0.6); background: rgba(15, 23, 42, 0.85); display: inline-flex; align-items: center; gap: 4px; font-size: 10px; } .mini-indicator-dot { width: 7px; height: 7px; border-radius: 50%; background: linear-gradient(135deg, #22c55e, #16a34a); box-shadow: 0 0 10px rgba(34, 197, 94, 0.9); } .bottom-nav { display: flex; align-items: center; justify-content: space-between; border-radius: 999px; background: rgba(9, 5, 27, 0.96); border: 1px solid rgba(148, 163, 184, 0.45); padding: 6px 8px; margin-top: 10px; box-shadow: 0 15px 40px rgba(0, 0, 0, 0.95); } .nav-item { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; font-size: 10px; color: rgba(156, 163, 175, 0.9); padding: 4px 0; border-radius: 999px; cursor: pointer; transition: background 0.16s ease, color 0.16s ease, transform 0.16s ease; } .nav-item-icon { font-size: 15px; } .nav-item--active { background: radial-gradient(circle at 50% 0, rgba(253, 224, 171, 0.4), transparent 55%), rgba(15, 23, 42, 0.98); color: var(--accent); transform: translateY(-1px); box-shadow: 0 8px 20px rgba(15, 23, 42, 0.9); } .page-scroll { flex: 1; overflow-y: auto; padding-right: 4px; margin-right: -4px; } .page-scroll::-webkit-scrollbar { width: 4px; } .page-scroll::-webkit-scrollbar-track { background: transparent; } .page-scroll::-webkit-scrollbar-thumb { background: rgba(148, 163, 184, 0.6); border-radius: 999px; } .history-list { display: flex; flex-direction: column; gap: 8px; margin-top: 4px; } .history-item { border-radius: 14px; background: rgba(15, 23, 42, 0.92); border: 1px solid rgba(75, 85, 99, 0.9); padding: 8px 9px; display: flex; gap: 8px; font-size: 11px; } .history-thumb { width: 34px; height: 54px; border-radius: 8px; border: 1px solid rgba(156, 163, 175, 0.85); background: linear-gradient(145deg, #020617, #020617); display: flex; align-items: center; justify-content: center; color: rgba(249, 250, 251, 0.9); font-size: 10px; } .history-meta { flex: 1; display: flex; flex-direction: column; gap: 3px; } .history-title-row { display: flex; justify-content: space-between; gap: 6px; font-size: 11px; color: rgba(249, 250, 251, 0.96); } .history-sub { font-size: 10px; color: rgba(209, 213, 219, 0.8); } .history-tags { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 2px; } .history-tag { padding: 1px 6px; border-radius: 999px; border: 1px solid rgba(148, 163, 184, 0.7); color: rgba(209, 213, 219, 0.9); font-size: 10px; } .settings-group { border-radius: 16px; background: rgba(15, 23, 42, 0.96); border: 1px solid rgba(75, 85, 99, 0.9); padding: 8px 9px; display: flex; flex-direction: column; gap: 6px; margin-top: 4px; } .setting-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; } .setting-label { display: flex; flex-direction: column; gap: 2px; font-size: 11px; color: rgba(249, 250, 251, 0.96); } .setting-label span { font-size: 10px; color: rgba(156, 163, 175, 0.9); } .toggle { width: 40px; height: 22px; border-radius: 999px; background: rgba(15, 23, 42, 0.9); border: 1px solid rgba(75, 85, 99, 0.9); padding: 2px; display: flex; align-items: center; cursor: pointer; transition: background 0.18s ease, border-color 0.18s ease; } .toggle-thumb { width: 16px; height: 16px; border-radius: 50%; background: rgba(148, 163, 184, 1); box-shadow: 0 1px 6px rgba(15, 23, 42, 0.9); transition: transform 0.18s ease, background 0.18s ease; } .toggle--on { background: linear-gradient(135deg, #22c55e, #16a34a); border-color: rgba(34, 197, 94, 0.8); } .toggle--on .toggle-thumb { transform: translateX(16px); background: #f9fafb; } .pill-select { display: inline-flex; align-items: center; gap: 4px; border-radius: 999px; background: rgba(15, 23, 42, 0.92); border: 1px solid rgba(75, 85, 99, 0.9); padding: 3px 6px 3px 5px; font-size: 10px; color: rgba(209, 213, 219, 0.9); } .pill-select select { border: none; background: transparent; color: inherit; font-size: inherit; outline: none; } .rules-list { display: flex; flex-direction: column; gap: 5px; margin-top: 4px; font-size: 11px; color: rgba(209, 213, 219, 0.92); } .rules-list li { display: flex; gap: 6px; } .rules-list li::before { content: "✶"; color: var(--accent); font-size: 9px; margin-top: 2px; } .result-layout { flex: 1; border-radius: 18px; background: radial-gradient(circle at 10% 0, rgba(31, 41, 55, 0.8), transparent 60%), radial-gradient(circle at 100% 100%, rgba(15, 23, 42, 0.95), transparent 60%); border: 1px solid rgba(148, 163, 184, 0.5); margin-top: 2px; padding: 10px; display: grid; grid-template-columns: 0.9fr 1.1fr; gap: 10px; } .result-card-shell { border-radius: 16px; background: rgba(15, 23, 42, 0.96); border: 1px solid rgba(75, 85, 99, 0.9); padding: 6px 6px 8px; display: flex; flex-direction: column; gap: 5px; align-items: center; } .result-card { width: 88px; height: 142px; border-radius: 13px; background: linear-gradient(145deg, #facc15, #f97316); padding: 4px; box-shadow: 0 20px 45px rgba(248, 181, 0, 0.85), 0 0 0 1px rgba(255, 248, 220, 0.9); position: relative; overflow: hidden; } .result-card-inner { position: absolute; inset: 4px; border-radius: 10px; background: radial-gradient(circle at 0 0, rgba(255, 255, 255, 0.45), transparent 50%), radial-gradient(circle at 100% 0, rgba(251, 191, 36, 0.4), transparent 55%), linear-gradient(145deg, #1f2937, #020617); display: flex; flex-direction: column; align-items: center; justify-content: space-between; padding: 6px 4px 6px; color: #f9fafb; } .result-card-name { font-size: 10px; letter-spacing: 0.12em; text-transform: uppercase; } .result-card-figure { width: 100%; flex: 1; display: flex; align-items: center; justify-content: center; position: relative; } .result-orbit { width: 56px; height: 56px; border-radius: 999px; border: 1px dashed rgba(249, 250, 251, 0.8); display: flex; align-items: center; justify-content: center; } .result-orbit::before { content: ""; position: absolute; width: 42px; height: 42px; border-radius: inherit; border: 1px solid rgba(249, 250, 251, 0.8); opacity: 0.5; } .result-glyph { width: 24px; height: 24px; border-radius: 50%; background: radial-gradient(circle at 30% 0, #fefce8, #fbbf24); display: flex; align-items: center; justify-content: center; color: #1f2937; font-size: 14px; box-shadow: 0 0 18px rgba(250, 204, 21, 0.9); } .result-card-bottom { font-size: 9px; text-transform: uppercase; letter-spacing: 0.12em; color: rgba(243, 244, 246, 0.8); } .result-meta { text-align: center; font-size: 11px; color: rgba(209, 213, 219, 0.9); display: flex; flex-direction: column; gap: 3px; } .result-meta strong { color: var(--accent); } .result-content { border-radius: 14px; background: rgba(15, 23, 42, 0.96); border: 1px solid rgba(75, 85, 99, 0.9); padding: 7px 8px; display: flex; flex-direction: column; gap: 5px; font-size: 11px; color: rgba(209, 213, 219, 0.96); } .result-tags { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 2px; } .result-tag { padding: 1px 6px; border-radius: 999px; border: 1px solid rgba(148, 163, 184, 0.9); font-size: 10px; } .result-section-title { font-size: 10px; letter-spacing: 0.16em; text-transform: uppercase; color: rgba(156, 163, 175, 0.95); } .result-paragraph { font-size: 11px; line-height: 1.6; } .result-actions { margin-top: 4px; display: flex; align-items: center; justify-content: space-between; gap: 8px; font-size: 11px; } .ghost-btn { flex: 1; border-radius: 999px; border: 1px solid rgba(148, 163, 184, 0.9); background: rgba(15, 23, 42, 0.96); padding: 6px 8px; color: rgba(249, 250, 251, 0.96); font-size: 11px; display: inline-flex; align-items: center; justify-content: center; gap: 4px; cursor: pointer; transition: background 0.16s ease, transform 0.16s ease, box-shadow 0.16s ease; } .ghost-btn:hover { background: radial-gradient(circle at 0 0, rgba(248, 250, 252, 0.2), transparent 55%), rgba(15, 23, 42, 0.98); box-shadow: 0 12px 28px rgba(15, 23, 42, 0.9); transform: translateY(-1px); } .ghost-btn:active { transform: translateY(0); box-shadow: 0 5px 18px rgba(15, 23, 42, 0.9); } .app-toast { position: absolute; left: 50%; bottom: 12px; transform: translateX(-50%) translateY(120%); padding: 7px 12px; border-radius: 999px; background: rgba(15, 23, 42, 0.98); border: 1px solid rgba(148, 163, 184, 0.9); color: rgba(249, 250, 251, 0.96); font-size: 11px; display: inline-flex; align-items: center; gap: 6px; box-shadow: 0 12px 30px rgba(15, 23, 42, 0.9); opacity: 0; pointer-events: none; transition: opacity 0.32s ease, transform 0.32s ease; z-index: 20; } .app-toast--visible { opacity: 1; transform: translateX(-50%) translateY(0); } .app-toast span { font-size: 13px; } @keyframes cardShuffle { 0% { transform: translateX(0) translateY(0) rotate(0deg); } 30% { transform: translateX(-10px) translateY(-12px) rotate(-6deg); } 60% { transform: translateX(12px) translateY(-6px) rotate(5deg); } 100% { transform: translateX(0) translateY(0) rotate(0deg); } } @keyframes cardDraw { 0% { transform: translateX(0) translateY(0) rotate(0deg) scale(1); opacity: 1; } 100% { transform: translateX(-40px) translateY(-60px) rotate(-10deg) scale(1.05); opacity: 0; } } @keyframes pulseGlow { 0%, 100% { box-shadow: 0 0 16px rgba(250, 204, 21, 0.6); } 50% { box-shadow: 0 0 26px rgba(250, 204, 21, 0.9); } } .deck-area--shuffling .tarot-card { animation: cardShuffle 0.8s ease-in-out infinite; } .deck-area--drawing .tarot-card { animation: cardDraw 0.6s ease-in-out forwards; } @media (max-width: 360px) { .app-frame { margin: 4px var(--page-padding) 4px; border-radius: 24px; } .hero-row { grid-template-columns: 1fr; } .result-layout { grid-template-columns: 1fr; grid-auto-rows: auto; } } </style> </head> <body> <div class="app-shell"> <div class="app-frame"> <div class="app-chrome"></div> <div class="app-content"> <header class="app-header"> <div class="app-title-group"> <div class="app-logo-word">ARCANA STUDIO</div> <div class="app-title"> <span>秘境塔罗</span> <span class="app-title-sub">H5 体验版</span> </div> </div> <div class="app-actions"> <button class="icon-btn" data-page-jump="help" title="使用说明">?</button> <button class="icon-btn icon-btn--primary" data-page-jump="result" title="最近一次解读"></button> </div> </header> <main class="app-main"> <section class="page page--active" data-page="home"> <div class="page-header"> <div class="page-title-group"> <div class="page-tagline">DAILY TAROT • 今日灵感</div> <div class="page-title"> <span>开始一次新的占卜</span> <div class="page-title-badge">Mood · 心境校准</div> </div> </div> </div> <div class="page-scroll"> <section class="card-shell"> <div class="hero-row"> <div class="hero-card"> <div class="hero-orbit"></div> <div class="hero-card-inner"> <div class="hero-card-top"> <div class="hero-chip"> <span class="hero-chip-dot"></span> <span>今日主牌</span> </div> <div class="hero-constellation"></div> </div> <div class="hero-signature"> <div class="hero-signature-main">ARCANA FLOW</div> <div class="hero-signature-sub">Shuffle. Draw. Listen.</div> </div> <div class="hero-figure"> <div class="hero-moon"></div> <div class="hero-rays"></div> <div class="hero-stars"> <span></span><span></span><span></span><span></span><span></span> </div> </div> <div class="hero-footer"> <span>直觉指数 <small>Intuition</small></span> <span>灵感在线 <small>在线抽牌</small></span> </div> </div> </div> <aside class="hero-metadata"> <div class="hero-metadata-inner"> <div class="meta-row"> <strong>今日频率</strong> <span id="meta-date-label">•••</span> </div> <div class="progress-track"> <div class="progress-bar"></div> </div> <div class="meta-tags"> <div class="meta-tag"> <span class="meta-tag-dot"></span> 心灵指引 </div> <div class="meta-tag">3~5 分钟完成</div> <div class="meta-tag">适合 · 日常问题</div> </div> </div> </aside> </div> <div class="section-caption"> <div class="section-caption-left"> <span>选择一种抽牌方式</span> </div> <div class="section-divider"></div> </div> <div class="mode-row"> <button class="mode-card mode-card--primary" data-spread-select="single"> <div class="mode-label"> <div class="mode-name">单牌指引</div> <div class="mode-badge">入门 · 快速</div> </div> <div class="mode-desc">适合「今天应该聚焦什么?」这类轻量问题,获得一条清晰的指引。</div> </button> <button class="mode-card" data-spread-select="triple"> <div class="mode-label"> <div class="mode-name">三牌流向</div> <div class="mode-badge">进阶 · 深入</div> </div> <div class="mode-desc">同时看见过去、现在与下一步,理解你所在的完整情境。</div> </button> </div> <button class="primary-btn" data-action="go-spread"> <span>开始洗牌</span> <span></span> </button> <div class="secondary-link"> 想先了解玩法?<button data-page-jump="help">查看塔罗礼仪与注意事项</button> </div> </section> </div> </section> <section class="page" data-page="spread"> <div class="page-header"> <div class="page-title-group"> <div class="page-tagline">SPREAD · 阵列选择</div> <div class="page-title"> <span>选择你的牌阵结构</span> <div class="page-title-badge" id="spread-mode-label">默认:单牌指引</div> </div> </div> <button class="icon-btn" data-page-jump="home"></button> </div> <div class="page-scroll"> <section class="card-shell"> <p class="page-desc"> 每一次抽牌,都从一个清晰的 <strong>问题</strong> 开始。请在心里默念你的问题,并选择一种你此刻最被吸引的牌阵。 </p> <div class="spread-grid"> <button class="spread-card spread-card--active" data-spread-option="single"> <div class="spread-visual spread-visual--single"> <span></span> </div> <div class="spread-name">单牌指引</div> <div class="spread-meta">一次抽出一张,给出当下最需要听见的讯息。</div> </button> <button class="spread-card" data-spread-option="triple"> <div class="spread-visual"> <span></span><span></span><span></span> </div> <div class="spread-name">三牌流向</div> <div class="spread-meta">过去 / 现在 / 下一步,适合关系、规划与决策。</div> </button> <button class="spread-card" data-spread-option="mirror"> <div class="spread-visual"> <span></span><span></span> </div> <div class="spread-name">镜像自我</div> <div class="spread-meta">看见「我以为的自己」与「内在真实的自己」。</div> </button> </div> <div class="flow-row"> <div class="flow-steps"> <div class="flow-dot flow-dot--active">1</div> <span>选择牌阵</span> <div class="flow-dot">2</div> <span>洗牌 · 抽牌</span> <div class="flow-dot">3</div> <span>解读结果</span> </div> <div>当前预计用时 &lt; 5 分钟</div> </div> </section> <section class="table-layout"> <div class="deck-area" id="deck-area"> <div class="tarot-card" id="tarot-card"> <div class="tarot-card-back"> <div class="tarot-card-sigil"> <div class="tarot-symbol"></div> </div> </div> </div> <div class="deck-shadow"></div> </div> <div class="deck-hint"> <span></span> 用手指轻轻「模拟洗牌动作」,准备好后,<strong>点击牌堆</strong> 开始抽牌。 </div> <div class="table-footer"> <div class="table-footer-left"> <span>问题已锁定 · 请保持心中专注</span> </div> <div class="mini-indicator"> <span class="mini-indicator-dot"></span> 在线连接 · 安全私密 </div> </div> </section> </div> </section> <section class="page" data-page="result"> <div class="page-header"> <div class="page-title-group"> <div class="page-tagline">INTERPRETATION · 解读</div> <div class="page-title"> <span>本次抽到的主牌</span> <div class="page-title-badge" id="result-spread-label">单牌指引 · Demo</div> </div> </div> <button class="icon-btn" data-page-jump="spread"></button> </div> <div class="page-scroll"> <section class="result-layout"> <div class="result-card-shell"> <div class="result-card"> <div class="result-card-inner"> <div class="result-card-name" id="result-card-name">THE SUN</div> <div class="result-card-figure"> <div class="result-orbit"> <div class="result-glyph"></div> </div> </div> <div class="result-card-bottom" id="result-card-orientation">正位 · SUN</div> </div> </div> <div class="result-meta"> <span>本页面为 <strong>UI 原型示例</strong>,用于展示塔罗结果的排版方式。</span> <span>真实业务中可根据后端数据填充牌名、正逆位、关键词与详细解读。</span> </div> </div> <div class="result-content"> <div class="result-section-title">核心关键词</div> <div class="result-tags" id="result-tags"> <span class="result-tag">清晰</span> <span class="result-tag">坦诚</span> <span class="result-tag">能量回归</span> <span class="result-tag">信任自己</span> </div> <div class="result-section-title">讯息解读</div> <p class="result-paragraph" id="result-text-main"> 你正从一段相对混沌的阶段走向更清晰的状态。这张牌邀请你<strong>相信自己的判断</strong>,而不是不断向外索取答案。 你已经具备足够的信息与经验,只是还需要一点点勇气,为自己做出一个「真诚的选择」。 </p> <p class="result-paragraph"> 在接下来的几天里,可以刻意安排一些 <strong>让你真正感到轻松、开心</strong> 的小事,例如晒太阳、整理空间、与信任的人聊聊。 这些看似琐碎的行动,会帮助你更快走出旧的循环,迎接新的可能。 </p> <div class="result-actions"> <button class="ghost-btn" data-action="save-history"> <span>存为一次占卜记录</span> </button> <button class="ghost-btn" data-action="redo"> <span>重新抽一轮</span> </button> </div> </div> </section> </div> </section> <section class="page" data-page="history"> <div class="page-header"> <div class="page-title-group"> <div class="page-tagline">ARCHIVE · 记录</div> <div class="page-title"> <span>我的塔罗时间线</span> <div class="page-title-badge">Demo · UI 展示</div> </div> </div> <button class="icon-btn" data-page-jump="home"></button> </div> <div class="page-scroll"> <section class="card-shell"> <p class="page-desc"> 这里会展示你每一次抽牌的 <strong>时间、主题与核心讯息</strong>。当前版本以示例数据展示布局,方便后续和后端对齐字段。 </p> <div class="history-list" id="history-list"> <article class="history-item"> <div class="history-thumb">SUN</div> <div class="history-meta"> <div class="history-title-row"> <div>2026-03-16 · 单牌指引</div> <div>上午 10:23</div> </div> <div class="history-sub">主题:关于工作选择的直觉提示</div> <div class="history-tags"> <span class="history-tag">牌面:太阳 · 正位</span> <span class="history-tag">结论:更靠近让你发光的场域</span> </div> </div> </article> <article class="history-item"> <div class="history-thumb">HER</div> <div class="history-meta"> <div class="history-title-row"> <div>2026-03-15 · 三牌流向</div> <div>晚上 21:07</div> </div> <div class="history-sub">主题:关于一段亲密关系的进展</div> <div class="history-tags"> <span class="history-tag">主牌:女祭司 · 逆位</span> <span class="history-tag">建议:诚实表达而非揣测</span> </div> </div> </article> </div> </section> <section class="settings-group"> <div class="setting-row"> <div class="setting-label"> <div>记录同步</div> <span>视觉上展示是否将记录同步到云端(真实逻辑可接后端)。</span> </div> <div class="toggle" data-toggle="sync"> <div class="toggle-thumb"></div> </div> </div> <div class="setting-row"> <div class="setting-label"> <div>对外分享</div> <span>允许将解读结果以图片形式分享(后续可接分享能力)。</span> </div> <div class="pill-select"> <span>方式</span> <select> <option>仅自己可见</option> <option>图片分享</option> <option>链接分享</option> </select> </div> </div> </section> </div> </section> <section class="page" data-page="help"> <div class="page-header"> <div class="page-title-group"> <div class="page-tagline">GUIDE · 使用说明</div> <div class="page-title"> <span>如何与塔罗好好相处</span> <div class="page-title-badge">界面文案示例</div> </div> </div> <button class="icon-btn" data-page-jump="home"></button> </div> <div class="page-scroll"> <section class="card-shell"> <p class="page-desc"> 塔罗是一种帮助你 <strong>看见自己</strong> 的工具,而不是预言命运。本页面用于展示 <strong>引导文案</strong><strong>说明信息的 UI 排版</strong></p> <ol class="rules-list"> <li>在开始抽牌前,为这次提问设定一个清晰的主题,例如「我和某段关系接下来会如何发展?」。</li> <li>在洗牌与抽牌过程中,尽量让自己专注在问题本身,而不是急着寻找某个「好牌」。</li> <li>看到结果时,先观察自己的第一反应:身体是放松、紧绷,还是有某种画面跳出来?这些都是讯息的一部分。</li> <li>如果对某次解读感到困惑,可以在「记录」中回看几天前的抽牌,有时答案会在时间中慢慢对齐。</li> <li>本应用的 UI/UX 仅为演示,具体业务可根据项目需要接入账号体系、付费模块或更复杂的解读逻辑。</li> </ol> </section> </div> </section> </main> <nav class="bottom-nav"> <button class="nav-item nav-item--active" data-page-jump="home"> <div class="nav-item-icon"></div> <div>首页</div> </button> <button class="nav-item" data-page-jump="spread"> <div class="nav-item-icon"></div> <div>抽牌</div> </button> <button class="nav-item" data-page-jump="result"> <div class="nav-item-icon"></div> <div>结果</div> </button> <button class="nav-item" data-page-jump="history"> <div class="nav-item-icon"></div> <div>记录</div> </button> </nav> <div class="app-toast" id="app-toast"> <span></span> <span id="toast-message">已保存到「记录」示例列表。</span> </div> </div> </div> </div> <script> (function () { const pages = document.querySelectorAll(".page"); const navItems = document.querySelectorAll(".nav-item"); const pageJumpButtons = document.querySelectorAll("[data-page-jump]"); const spreadModeLabel = document.getElementById("spread-mode-label"); const resultSpreadLabel = document.getElementById("result-spread-label"); const metaDateLabel = document.getElementById("meta-date-label"); const deckArea = document.getElementById("deck-area"); const tarotCard = document.getElementById("tarot-card"); const toast = document.getElementById("app-toast"); const toastMessage = document.getElementById("toast-message"); const toggles = document.querySelectorAll(".toggle"); const spreadCards = document.querySelectorAll(".spread-card"); const modeCards = document.querySelectorAll(".mode-card"); let currentPage = "home"; let currentSpread = "single"; let isShuffling = false; function showPage(target) { if (!target || target === currentPage) return; currentPage = target; pages.forEach((page) => { const name = page.getAttribute("data-page"); page.classList.toggle("page--active", name === target); }); navItems.forEach((item) => { const jump = item.getAttribute("data-page-jump"); item.classList.toggle("nav-item--active", jump === target); }); } function showToast(message) { if (!toast) return; toastMessage.textContent = message; toast.classList.add("app-toast--visible"); window.clearTimeout(showToast._timer); showToast._timer = window.setTimeout(() => { toast.classList.remove("app-toast--visible"); }, 1900); } function updateSpreadLabels() { const labelMap = { single: "单牌指引", triple: "三牌流向", mirror: "镜像自我" }; const text = labelMap[currentSpread] || "自定义牌阵"; if (spreadModeLabel) { spreadModeLabel.textContent = "当前:" + text; } if (resultSpreadLabel) { resultSpreadLabel.textContent = text + " · Demo"; } } function initDateLabel() { try { const now = new Date(); const days = ["日", "一", "二", "三", "四", "五", "六"]; const label = now.getFullYear() + " / " + (now.getMonth() + 1) + " / " + now.getDate() + " · 周" + days[now.getDay()]; if (metaDateLabel) { metaDateLabel.textContent = label; } } catch (e) {} } pageJumpButtons.forEach((btn) => { btn.addEventListener("click", () => { const target = btn.getAttribute("data-page-jump"); showPage(target); }); }); if (deckArea && tarotCard) { deckArea.addEventListener("click", () => { if (isShuffling) return; isShuffling = true; deckArea.classList.add("deck-area--drawing"); window.setTimeout(() => { deckArea.classList.remove("deck-area--drawing"); isShuffling = false; showPage("result"); showToast("已为你生成一张示例牌面。"); }, 650); }); deckArea.addEventListener("touchstart", () => { deckArea.classList.add("deck-area--shuffling"); }); deckArea.addEventListener("touchend", () => { deckArea.classList.remove("deck-area--shuffling"); }); deckArea.addEventListener("touchcancel", () => { deckArea.classList.remove("deck-area--shuffling"); }); } document.querySelectorAll("[data-action='go-spread']").forEach((btn) => { btn.addEventListener("click", () => { showPage("spread"); }); }); document.querySelectorAll("[data-action='save-history']").forEach((btn) => { btn.addEventListener("click", () => { showToast("示例:已保存到「记录」列表。"); }); }); document.querySelectorAll("[data-action='redo']").forEach((btn) => { btn.addEventListener("click", () => { showPage("spread"); showToast("你可以带着新问题再抽一次。"); }); }); toggles.forEach((toggle) => { toggle.addEventListener("click", () => { toggle.classList.toggle("toggle--on"); }); }); spreadCards.forEach((card) => { card.addEventListener("click", () => { const option = card.getAttribute("data-spread-option"); if (!option) return; currentSpread = option; spreadCards.forEach((c) => c.classList.toggle("spread-card--active", c === card)); updateSpreadLabels(); showToast("已选择牌阵:「" + (card.querySelector(".spread-name")?.textContent || "") + "」。"); }); }); modeCards.forEach((card) => { card.addEventListener("click", () => { const selectKey = card.getAttribute("data-spread-select"); if (selectKey) { currentSpread = selectKey; updateSpreadLabels(); } modeCards.forEach((c) => c.classList.toggle("mode-card--primary", c === card)); }); }); initDateLabel(); updateSpreadLabels(); })(); </script> </body> </html>

对应上面《使用对比》中的3:提示词重复沟通3遍后:

html
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" /> <title>秘境塔罗 · H5 UI 原型</title> <style> *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } html, body { height: 100%; } body { font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "SF Pro Display", "Segoe UI", system-ui, sans-serif; background: radial-gradient(circle at top, #1e1035 0, #05020a 55%, #010005 100%); color: #f7f3ff; -webkit-font-smoothing: antialiased; } :root { --accent: #ffce6a; --accent-strong: #ff9f4a; --muted: #a6a0c8; --surface: rgba(10, 4, 24, 0.92); --border-subtle: rgba(255, 255, 255, 0.08); --radius-lg: 22px; --radius-md: 14px; } body::before { content: ""; position: fixed; inset: -40%; background: radial-gradient(circle at 20% 0%, rgba(255, 231, 153, 0.18), transparent 55%), radial-gradient(circle at 90% 10%, rgba(139, 92, 246, 0.22), transparent 60%), radial-gradient(circle at 0% 80%, rgba(56, 189, 248, 0.12), transparent 55%); mix-blend-mode: screen; opacity: 0.75; pointer-events: none; z-index: -1; } .app-shell { max-width: 480px; height: 100vh; margin: 0 auto; padding: env(safe-area-inset-top) 16px env(safe-area-inset-bottom); display: flex; flex-direction: column; } .app-frame { flex: 1; margin: 10px 0 6px; border-radius: 28px; background: linear-gradient(145deg, rgba(15, 10, 38, 0.98), rgba(3, 2, 15, 0.98)); box-shadow: 0 25px 80px rgba(0, 0, 0, 0.85), 0 0 0 1px rgba(255, 255, 255, 0.04); overflow: hidden; position: relative; } .app-chrome { position: absolute; inset: 0; pointer-events: none; border-radius: inherit; background: radial-gradient(circle at 10% 0%, rgba(255, 255, 255, 0.16), transparent 65%), radial-gradient(circle at 100% 100%, rgba(255, 148, 255, 0.16), transparent 60%); mix-blend-mode: soft-light; opacity: 0.6; } .app-content { position: relative; z-index: 1; width: 100%; height: 100%; display: flex; flex-direction: column; padding: 16px 14px 10px; } .app-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; } .app-title-group { display: flex; flex-direction: column; gap: 2px; } .app-logo-word { font-size: 13px; letter-spacing: 0.32em; text-transform: uppercase; color: rgba(255, 255, 255, 0.6); } .app-title { font-size: 20px; letter-spacing: 0.08em; font-weight: 600; display: inline-flex; align-items: baseline; gap: 6px; } .app-title span { background: linear-gradient(120deg, #ffe39a, #ffc46e, #ff9f4a); -webkit-background-clip: text; color: transparent; } .app-title-sub { font-size: 11px; color: var(--muted); } .app-actions { display: flex; align-items: center; gap: 8px; } .icon-btn { width: 28px; height: 28px; border-radius: 999px; border: 1px solid rgba(255, 255, 255, 0.1); background: radial-gradient(circle at 0 0, rgba(255, 255, 255, 0.2), transparent 65%), rgba(8, 4, 22, 0.9); display: inline-flex; align-items: center; justify-content: center; color: var(--muted); font-size: 15px; box-shadow: 0 6px 18px rgba(0, 0, 0, 0.7); cursor: pointer; border-radius: 999px; } .icon-btn--primary { border-color: rgba(255, 206, 106, 0.5); color: var(--accent); } .app-main { flex: 1; position: relative; overflow: hidden; border-radius: 20px; background: radial-gradient(circle at top, rgba(71, 45, 143, 0.96), rgba(14, 5, 37, 0.96)); box-shadow: inset 0 0 40px rgba(0, 0, 0, 0.65); padding: 14px 12px; display: flex; flex-direction: column; } .page { position: absolute; inset: 0; padding: 14px 12px 14px; display: flex; flex-direction: column; gap: 14px; opacity: 0; pointer-events: none; transform: translateX(6%); transition: opacity 0.28s ease, transform 0.28s ease; } .page--active { opacity: 1; pointer-events: auto; transform: translateX(0); } .page-header { display: flex; align-items: center; justify-content: space-between; gap: 8px; } .page-title-group { display: flex; flex-direction: column; gap: 3px; } .page-tagline { font-size: 11px; color: var(--muted); letter-spacing: 0.12em; text-transform: uppercase; } .page-title { font-size: 18px; letter-spacing: 0.06em; display: flex; align-items: center; gap: 8px; } .page-title span { background: linear-gradient(120deg, #ffe6aa, #ffbf67, #ff9c4b); -webkit-background-clip: text; color: transparent; } .page-title-badge { font-size: 11px; padding: 2px 8px; border-radius: 999px; border: 1px solid rgba(255, 255, 255, 0.12); background: radial-gradient(circle at 0 0, rgba(255, 255, 255, 0.2), transparent 60%), rgba(9, 3, 26, 0.9); color: var(--muted); } .page-desc { font-size: 12px; line-height: 1.6; color: rgba(234, 224, 255, 0.92); } .page-desc strong { color: var(--accent); } .page-scroll { flex: 1; overflow-y: auto; padding-right: 4px; margin-right: -4px; } .page-scroll::-webkit-scrollbar { width: 4px; } .page-scroll::-webkit-scrollbar-thumb { background: rgba(148, 163, 184, 0.6); border-radius: 999px; } .card-shell { border-radius: var(--radius-lg); padding: 10px 10px 8px; background: radial-gradient(circle at 0 0, rgba(255, 255, 255, 0.2), transparent 65%), linear-gradient(140deg, rgba(19, 8, 48, 0.97), rgba(17, 4, 42, 0.98)); box-shadow: 0 12px 40px rgba(0, 0, 0, 0.9), 0 0 0 1px rgba(255, 255, 255, 0.06); display: flex; flex-direction: column; gap: 8px; position: relative; overflow: hidden; } .hero-row { display: grid; grid-template-columns: 1.1fr 1fr; gap: 10px; align-items: stretch; } .hero-card { border-radius: 20px; background: radial-gradient(circle at 15% 0%, rgba(255, 255, 255, 0.35), transparent 65%), radial-gradient(circle at 100% 100%, rgba(252, 211, 77, 0.5), transparent 60%), linear-gradient(145deg, #1a0828, #11071f); padding: 9px 9px 11px; box-shadow: 0 18px 45px rgba(0, 0, 0, 0.95), 0 0 0 1px rgba(255, 255, 255, 0.16); position: relative; overflow: hidden; } .hero-card-inner { position: relative; z-index: 1; height: 100%; display: flex; flex-direction: column; justify-content: space-between; gap: 10px; } .hero-signature { text-align: center; padding-top: 4px; } .hero-signature-main { font-size: 14px; letter-spacing: 0.2em; text-transform: uppercase; } .hero-signature-sub { font-size: 11px; margin-top: 2px; color: rgba(243, 244, 246, 0.8); } .hero-figure { position: relative; margin-top: 6px; height: 72px; } .hero-moon { position: absolute; top: 4px; left: 50%; transform: translateX(-50%); width: 50px; height: 50px; border-radius: 50%; background: radial-gradient(circle at 30% 15%, #fff7d1, #f7c26c 65%, #e7873e 100%); box-shadow: 0 0 30px rgba(255, 252, 210, 0.85), 0 0 80px rgba(253, 224, 171, 0.7); } .section-caption { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-top: 2px; font-size: 11px; color: var(--muted); } .section-divider { flex: 1; height: 1px; border-radius: 999px; background: linear-gradient(90deg, rgba(107, 114, 128, 0.1), rgba(255, 255, 255, 0.4), rgba(107, 114, 128, 0.1)); opacity: 0.8; } .mode-row { display: flex; gap: 8px; } .mode-card { flex: 1; border-radius: var(--radius-md); background: radial-gradient(circle at 0 0, rgba(255, 255, 255, 0.2), transparent 60%), rgba(8, 3, 26, 0.92); border: 1px solid rgba(148, 163, 184, 0.35); padding: 7px 8px 8px; display: flex; flex-direction: column; gap: 4px; box-shadow: 0 10px 30px rgba(15, 23, 42, 0.9); font-size: 11px; } .mode-card--primary { border-color: rgba(252, 211, 77, 0.8); background: radial-gradient(circle at 0 0, rgba(255, 243, 199, 0.28), transparent 55%), rgba(24, 16, 45, 0.96); } .mode-label { display: flex; align-items: center; justify-content: space-between; gap: 4px; } .mode-name { font-size: 13px; font-weight: 500; letter-spacing: 0.08em; text-transform: uppercase; } .mode-badge { font-size: 10px; padding: 1px 6px; border-radius: 999px; border: 1px solid rgba(148, 163, 184, 0.45); color: rgba(209, 213, 219, 0.9); } .mode-desc { font-size: 11px; color: rgba(209, 213, 219, 0.9); line-height: 1.55; } .primary-btn { width: 100%; margin-top: 8px; border-radius: 999px; border: none; padding: 10px 14px; font-size: 15px; letter-spacing: 0.18em; text-transform: uppercase; font-weight: 600; background: linear-gradient(120deg, #fbbf24, #fb923c, #f97316); color: #1f2937; box-shadow: 0 18px 40px rgba(248, 181, 0, 0.9), 0 0 0 1px rgba(255, 237, 213, 0.9); display: inline-flex; align-items: center; justify-content: center; gap: 6px; } .secondary-link { margin-top: 4px; text-align: center; font-size: 11px; color: var(--muted); } .secondary-link span { color: #f9fafb; text-decoration: underline; text-underline-offset: 3px; } .spread-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; margin-top: 4px; } .spread-card { border-radius: 14px; background: rgba(15, 23, 42, 0.96); padding: 6px 6px 7px; border: 1px solid rgba(75, 85, 99, 0.9); display: flex; flex-direction: column; gap: 4px; font-size: 10px; } .spread-card--active { border-color: var(--accent); box-shadow: 0 16px 40px rgba(248, 181, 0, 0.85), 0 0 0 1px rgba(251, 191, 36, 0.6); background: radial-gradient(circle at 0 0, rgba(255, 237, 213, 0.3), transparent 60%), rgba(15, 23, 42, 0.98); } .spread-visual { height: 40px; border-radius: 11px; background: repeating-linear-gradient(135deg, rgba(31, 41, 55, 0.9), rgba(31, 41, 55, 0.9) 2px, rgba(17, 24, 39, 0.9) 2px, rgba(17, 24, 39, 0.9) 4px); display: flex; align-items: center; justify-content: center; gap: 2px; padding: 0 4px; } .spread-visual span { display: block; border-radius: 6px; border: 1px solid rgba(156, 163, 175, 0.9); background: linear-gradient(145deg, #020617, #020617); width: 16px; height: 30px; } .spread-visual--single span { width: 26px; height: 34px; border-radius: 7px; } .spread-name { font-size: 12px; font-weight: 500; color: rgba(249, 250, 251, 0.96); } .spread-meta { font-size: 10px; color: rgba(209, 213, 219, 0.8); } .table-layout { flex: 1; border-radius: 18px; background: radial-gradient(circle at 10% 0, rgba(31, 41, 55, 0.8), transparent 60%), radial-gradient(circle at 100% 100%, rgba(15, 23, 42, 0.95), transparent 60%); border: 1px solid rgba(148, 163, 184, 0.5); margin-top: 2px; padding: 10px; position: relative; display: flex; flex-direction: column; justify-content: center; align-items: center; gap: 8px; } .deck-area { position: relative; width: 78%; max-width: 260px; height: 140px; } .tarot-card { position: absolute; left: 50%; bottom: 0; width: 76px; height: 118px; margin-left: -38px; border-radius: 12px; background: linear-gradient(145deg, #020617, #020617); border: 1px solid rgba(209, 213, 219, 0.85); box-shadow: 0 18px 40px rgba(15, 23, 42, 0.95), 0 0 0 1px rgba(17, 24, 39, 1); overflow: hidden; } .tarot-card-back { position: absolute; inset: 3px; border-radius: 9px; background: radial-gradient(circle at 0 0, rgba(248, 250, 252, 0.35), transparent 60%), radial-gradient(circle at 100% 100%, rgba(209, 213, 219, 0.55), transparent 65%), repeating-linear-gradient(135deg, rgba(15, 23, 42, 0.9), rgba(15, 23, 42, 0.9) 2px, rgba(15, 23, 42, 1) 2px, rgba(15, 23, 42, 1) 4px); display: flex; align-items: center; justify-content: center; } .tarot-card-sigil { width: 72%; height: 56%; border-radius: 999px; border: 1px solid rgba(249, 250, 251, 0.8); position: relative; display: flex; align-items: center; justify-content: center; overflow: hidden; } .tarot-symbol { width: 24px; height: 24px; border-radius: 50%; display: flex; align-items: center; justify-content: center; border: 1px solid rgba(249, 250, 251, 0.9); font-size: 14px; } .deck-hint { font-size: 11px; color: rgba(209, 213, 219, 0.85); text-align: center; display: flex; align-items: center; justify-content: center; gap: 6px; } .deck-shadow { position: absolute; left: 50%; bottom: -3px; width: 62%; height: 18px; margin-left: -31%; background: radial-gradient(circle at 50% 0, rgba(0, 0, 0, 0.85), transparent 75%); filter: blur(4px); opacity: 0.9; pointer-events: none; } /* 抽卡动效 */ @keyframes cardShuffle { 0% { transform: translateX(0) translateY(0) rotate(0deg); } 30% { transform: translateX(-10px) translateY(-12px) rotate(-6deg); } 60% { transform: translateX(12px) translateY(-6px) rotate(5deg); } 100% { transform: translateX(0) translateY(0) rotate(0deg); } } @keyframes cardDraw { 0% { transform: translateX(0) translateY(0) rotate(0deg) scale(1); opacity: 1; } 100% { transform: translateX(-40px) translateY(-60px) rotate(-10deg) scale(1.05); opacity: 0; } } .deck-area--shuffling .tarot-card { animation: cardShuffle 0.8s ease-in-out infinite; } .deck-area--drawing .tarot-card { animation: cardDraw 0.7s ease-in-out forwards; } .result-layout { flex: 1; border-radius: 18px; background: radial-gradient(circle at 10% 0, rgba(31, 41, 55, 0.8), transparent 60%), radial-gradient(circle at 100% 100%, rgba(15, 23, 42, 0.95), transparent 60%); border: 1px solid rgba(148, 163, 184, 0.5); margin-top: 2px; padding: 10px; display: grid; grid-template-columns: 0.9fr 1.1fr; gap: 10px; } .result-card-shell { border-radius: 16px; background: rgba(15, 23, 42, 0.96); border: 1px solid rgba(75, 85, 99, 0.9); padding: 6px 6px 8px; display: flex; flex-direction: column; gap: 5px; align-items: center; } .result-card { width: 88px; height: 142px; border-radius: 13px; background: linear-gradient(145deg, #facc15, #f97316); padding: 4px; box-shadow: 0 20px 45px rgba(248, 181, 0, 0.85), 0 0 0 1px rgba(255, 248, 220, 0.9); position: relative; overflow: hidden; } .result-card-inner { position: absolute; inset: 4px; border-radius: 10px; background: radial-gradient(circle at 0 0, rgba(255, 255, 255, 0.45), transparent 50%), radial-gradient(circle at 100% 0, rgba(251, 191, 36, 0.4), transparent 55%), linear-gradient(145deg, #1f2937, #020617); display: flex; flex-direction: column; align-items: center; justify-content: space-between; padding: 6px 4px 6px; color: #f9fafb; } .result-card-name { font-size: 10px; letter-spacing: 0.12em; text-transform: uppercase; } .result-card-figure { flex: 1; display: flex; align-items: center; justify-content: center; } .result-orbit { width: 56px; height: 56px; border-radius: 999px; border: 1px dashed rgba(249, 250, 251, 0.8); display: flex; align-items: center; justify-content: center; } .result-glyph { width: 24px; height: 24px; border-radius: 50%; background: radial-gradient(circle at 30% 0, #fefce8, #fbbf24); display: flex; align-items: center; justify-content: center; color: #1f2937; font-size: 14px; } .result-card-bottom { font-size: 9px; text-transform: uppercase; letter-spacing: 0.12em; color: rgba(243, 244, 246, 0.8); } .result-content { border-radius: 14px; background: rgba(15, 23, 42, 0.96); border: 1px solid rgba(75, 85, 99, 0.9); padding: 7px 8px; display: flex; flex-direction: column; gap: 5px; font-size: 11px; color: rgba(209, 213, 219, 0.96); } .result-section-title { font-size: 10px; letter-spacing: 0.16em; text-transform: uppercase; color: rgba(156, 163, 175, 0.95); } .result-paragraph { font-size: 11px; line-height: 1.6; } .result-tags { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 2px; } .result-tag { padding: 1px 6px; border-radius: 999px; border: 1px solid rgba(148, 163, 184, 0.9); font-size: 10px; } .result-actions { margin-top: 4px; display: flex; align-items: center; justify-content: space-between; gap: 8px; font-size: 11px; } .ghost-btn { flex: 1; border-radius: 999px; border: 1px solid rgba(148, 163, 184, 0.9); background: rgba(15, 23, 42, 0.96); padding: 6px 8px; color: rgba(249, 250, 251, 0.96); font-size: 11px; display: inline-flex; align-items: center; justify-content: center; gap: 4px; } .history-list { display: flex; flex-direction: column; gap: 8px; margin-top: 4px; font-size: 11px; } .history-item { border-radius: 14px; background: rgba(15, 23, 42, 0.92); border: 1px solid rgba(75, 85, 99, 0.9); padding: 8px 9px; display: flex; gap: 8px; } .history-thumb { width: 34px; height: 54px; border-radius: 8px; border: 1px solid rgba(156, 163, 175, 0.85); background: linear-gradient(145deg, #020617, #020617); display: flex; align-items: center; justify-content: center; color: rgba(249, 250, 251, 0.9); font-size: 10px; } .history-meta { flex: 1; display: flex; flex-direction: column; gap: 3px; } .history-title-row { display: flex; justify-content: space-between; gap: 6px; font-size: 11px; color: rgba(249, 250, 251, 0.96); } .history-sub { font-size: 10px; color: rgba(209, 213, 219, 0.8); } .history-tags { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 2px; } .history-tag { padding: 1px 6px; border-radius: 999px; border: 1px solid rgba(148, 163, 184, 0.7); color: rgba(209, 213, 219, 0.9); font-size: 10px; } .settings-group { border-radius: 16px; background: rgba(15, 23, 42, 0.96); border: 1px solid rgba(75, 85, 99, 0.9); padding: 8px 9px; display: flex; flex-direction: column; gap: 6px; margin-top: 4px; font-size: 11px; } .setting-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; } .setting-label { display: flex; flex-direction: column; gap: 2px; } .setting-label span { font-size: 10px; color: rgba(156, 163, 175, 0.9); } .toggle { width: 40px; height: 22px; border-radius: 999px; background: rgba(15, 23, 42, 0.9); border: 1px solid rgba(75, 85, 99, 0.9); padding: 2px; display: flex; align-items: center; } .toggle-thumb { width: 16px; height: 16px; border-radius: 50%; background: rgba(148, 163, 184, 1); } .rules-list { display: flex; flex-direction: column; gap: 5px; margin-top: 4px; font-size: 11px; color: rgba(209, 213, 219, 0.92); } .rules-list li { display: flex; gap: 6px; } .rules-list li::before { content: "✶"; color: var(--accent); font-size: 9px; margin-top: 2px; } .bottom-nav { display: flex; align-items: center; justify-content: space-between; border-radius: 999px; background: rgba(9, 5, 27, 0.96); border: 1px solid rgba(148, 163, 184, 0.45); padding: 6px 8px; margin-top: 10px; box-shadow: 0 15px 40px rgba(0, 0, 0, 0.95); } .nav-item { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; font-size: 10px; color: rgba(156, 163, 175, 0.9); padding: 4px 0; border-radius: 999px; } .nav-item-icon { font-size: 15px; } .nav-item--active { background: radial-gradient(circle at 50% 0, rgba(253, 224, 171, 0.4), transparent 55%), rgba(15, 23, 42, 0.98); color: var(--accent); } .app-toast { position: absolute; left: 50%; bottom: 12px; transform: translateX(-50%); padding: 7px 12px; border-radius: 999px; background: rgba(15, 23, 42, 0.98); border: 1px solid rgba(148, 163, 184, 0.9); color: rgba(249, 250, 251, 0.96); font-size: 11px; display: inline-flex; align-items: center; gap: 6px; box-shadow: 0 12px 30px rgba(15, 23, 42, 0.9); opacity: 0; pointer-events: none; transform-origin: center; transition: opacity 0.32s ease; } .app-toast--visible { opacity: 1; } @media (max-width: 360px) { .app-frame { margin: 4px 0 4px; border-radius: 24px; } .hero-row { grid-template-columns: 1fr; } .result-layout { grid-template-columns: 1fr; grid-auto-rows: auto; } } </style> </head> <body> <div class="app-shell"> <div class="app-frame"> <div class="app-chrome"></div> <div class="app-content"> <header class="app-header"> <div class="app-title-group"> <div class="app-logo-word">ARCANA STUDIO</div> <div class="app-title"> <span>秘境塔罗</span> <span class="app-title-sub">H5 UI 原型</span> </div> </div> <div class="app-actions"> <button class="icon-btn" data-page-jump="help" title="使用说明">?</button> <button class="icon-btn icon-btn--primary" data-page-jump="result" title="结果页面"></button> </div> </header> <main class="app-main"> <!-- 首页:问题设定 & 入口 --> <section class="page page--active" data-page="home"> <div class="page-header"> <div class="page-title-group"> <div class="page-tagline">DAILY TAROT • 今日灵感</div> <div class="page-title"> <span>开始一次新的占卜</span> <div class="page-title-badge">Step 1 · 设定问题</div> </div> </div> </div> <div class="page-scroll"> <section class="card-shell"> <div class="hero-row"> <div class="hero-card"> <div class="hero-card-inner"> <div class="hero-signature"> <div class="hero-signature-main">ARCANA FLOW</div> <div class="hero-signature-sub">Shuffle · Draw · Listen</div> </div> <div class="hero-figure"> <div class="hero-moon"></div> </div> </div> </div> <aside class="card-shell" style="gap:6px; padding:8px 9px;"> <p class="page-desc"> 在心里为这次占卜设定一个<strong>清晰的问题</strong>,例如「我今天应该把注意力放在什么上?」。 </p> <p class="page-desc"> 右下角底部导航展示了本原型包含的所有页面:<strong>首页 / 抽牌 / 结果 / 记录 / 说明</strong>,方便产品与设计评审。 </p> </aside> </div> <div class="section-caption"> <span>选择一种抽牌方式</span> <div class="section-divider"></div> </div> <div class="mode-row"> <div class="mode-card mode-card--primary"> <div class="mode-label"> <div class="mode-name">单牌指引</div> <div class="mode-badge">入门 · 快速</div> </div> <div class="mode-desc">适合「今天应该聚焦什么?」这类问题,卡片结果页面会展示核心关键词与短文解读。</div> </div> <div class="mode-card"> <div class="mode-label"> <div class="mode-name">三牌流向</div> <div class="mode-badge">进阶 · 深入</div> </div> <div class="mode-desc">过去 / 现在 / 下一步 的布局可在结果页扩展为三列卡片与三段解读。</div> </div> </div> <button class="primary-btn" data-page-jump="spread"> <span>开始洗牌</span> <span></span> </button> <div class="secondary-link"> 想先了解玩法?<span>查看塔罗礼仪与注意事项(见「说明」页)</span> </div> </section> </div> </section> <!-- 抽牌页:牌阵选择 + 洗牌交互区域 --> <section class="page" data-page="spread"> <div class="page-header"> <div class="page-title-group"> <div class="page-tagline">SPREAD · 阵列选择</div> <div class="page-title"> <span>选择你的牌阵结构</span> <div class="page-title-badge">Step 2 · 选择牌阵</div> </div> </div> </div> <div class="page-scroll"> <section class="card-shell"> <p class="page-desc"> 每一次抽牌,从一个清晰的<strong>主题</strong><strong>合适的牌阵</strong>开始。下方展示了 3 种典型配置,可根据业务需要增删。 </p> <div class="spread-grid"> <div class="spread-card spread-card--active"> <div class="spread-visual spread-visual--single"><span></span></div> <div class="spread-name">单牌指引</div> <div class="spread-meta">一次抽出一张牌,快速获得一个当下的方向提示。</div> </div> <div class="spread-card"> <div class="spread-visual"> <span></span><span></span><span></span> </div> <div class="spread-name">三牌流向</div> <div class="spread-meta">左:过去 · 中:现在 · 右:下一步,适合关系、决策类问题。</div> </div> <div class="spread-card"> <div class="spread-visual"> <span></span><span></span> </div> <div class="spread-name">镜像自我</div> <div class="spread-meta">看见「我以为的自己」与「内在真实的自己」。</div> </div> </div> </section> <section class="table-layout"> <div class="deck-area"> <div class="tarot-card"> <div class="tarot-card-back"> <div class="tarot-card-sigil"> <div class="tarot-symbol"></div> </div> </div> </div> <div class="deck-shadow"></div> </div> <div class="deck-hint"> <span></span> 在真实产品中,这里可接「拖动 / 点击」交互逻辑;原型中仅展示牌堆视觉与提示文案。 </div> </section> </div> </section> <!-- 结果页:主牌展示 + 文案区 --> <section class="page" data-page="result"> <div class="page-header"> <div class="page-title-group"> <div class="page-tagline">INTERPRETATION · 解读</div> <div class="page-title"> <span>本次抽到的主牌</span> <div class="page-title-badge">Step 3 · 结果展示</div> </div> </div> </div> <div class="page-scroll"> <section class="result-layout"> <div class="result-card-shell"> <div class="result-card"> <div class="result-card-inner"> <div class="result-card-name">THE SUN</div> <div class="result-card-figure"> <div class="result-orbit"> <div class="result-glyph"></div> </div> </div> <div class="result-card-bottom">正位 · SUN</div> </div> </div> <div class="page-desc" style="font-size:11px; margin-top:4px;"> 卡片名称、正逆位、元素归属等信息可由后端返回;本原型仅展示视觉与文案承载结构。 </div> </div> <div class="result-content"> <div class="result-section-title">核心关键词</div> <div class="result-tags"> <span class="result-tag">清晰</span> <span class="result-tag">坦诚</span> <span class="result-tag">能量回归</span> <span class="result-tag">信任自己</span> </div> <div class="result-section-title">讯息解读</div> <p class="result-paragraph"> 你正从一段相对混沌的阶段走向更清晰的状态。这张牌邀请你<strong>相信自己的判断</strong>,而不是不断向外索取答案。 你已经具备足够的信息与经验,只是还需要一点点勇气,为自己做出一个「真诚的选择」。 </p> <p class="result-paragraph"> 在接下来的几天里,可以刻意安排一些<strong>让你真正感到轻松、开心</strong>的小事,例如晒太阳、整理空间、与信任的人聊聊。 这些看似琐碎的行动,会帮助你更快走出旧的循环,迎接新的可能。 </p> <div class="result-actions"> <button class="ghost-btn"> <span>存为一次占卜记录</span> </button> <button class="ghost-btn"> <span>重新抽一轮</span> </button> </div> </div> </section> </div> </section> <!-- 记录页:历史抽牌时间线 --> <section class="page" data-page="history"> <div class="page-header"> <div class="page-title-group"> <div class="page-tagline">ARCHIVE · 记录</div> <div class="page-title"> <span>我的塔罗时间线</span> <div class="page-title-badge">Demo · UI 展示</div> </div> </div> </div> <div class="page-scroll"> <section class="card-shell"> <p class="page-desc"> 这里展示每一次抽牌的<strong>时间 / 主题 / 关键词</strong>。示例数据仅用于说明排版,后续可接入登录与云同步。 </p> <div class="history-list"> <article class="history-item"> <div class="history-thumb">SUN</div> <div class="history-meta"> <div class="history-title-row"> <div>2026-03-16 · 单牌指引</div> <div>上午 10:23</div> </div> <div class="history-sub">主题:关于工作选择的直觉提示</div> <div class="history-tags"> <span class="history-tag">牌面:太阳 · 正位</span> <span class="history-tag">结论:更靠近让你发光的场域</span> </div> </div> </article> <article class="history-item"> <div class="history-thumb">HER</div> <div class="history-meta"> <div class="history-title-row"> <div>2026-03-15 · 三牌流向</div> <div>晚上 21:07</div> </div> <div class="history-sub">主题:关于一段亲密关系的进展</div> <div class="history-tags"> <span class="history-tag">主牌:女祭司 · 逆位</span> <span class="history-tag">建议:诚实表达而非揣测</span> </div> </div> </article> </div> </section> <section class="settings-group"> <div class="setting-row"> <div class="setting-label"> <div>记录同步</div> <span>视觉上展示「是否同步到云端」,真实逻辑可与后端对齐。</span> </div> <div class="toggle"> <div class="toggle-thumb"></div> </div> </div> <div class="setting-row"> <div class="setting-label"> <div>结果分享</div> <span>支持将解读结果导出为图片、长图或链接等形式。</span> </div> <div style="font-size:10px; color:rgba(209,213,219,0.9);"> 具体形态可在后续方案中细化。 </div> </div> </section> </div> </section> <!-- 说明页:塔罗礼仪 & 使用指南 --> <section class="page" data-page="help"> <div class="page-header"> <div class="page-title-group"> <div class="page-tagline">GUIDE · 使用说明</div> <div class="page-title"> <span>如何与塔罗好好相处</span> <div class="page-title-badge">使用规则 · 文案示例</div> </div> </div> </div> <div class="page-scroll"> <section class="card-shell"> <p class="page-desc"> 塔罗是一种帮助你<strong>看见自己</strong>的工具,而不是预言命运。本页面用于放置引导文案、品牌语气和使用须知。 </p> <ol class="rules-list"> <li>在开始抽牌前,为这次提问设定一个清晰主题,例如「我和某段关系接下来会如何发展?」。</li> <li>洗牌与抽牌过程中,尽量保持专注,避免频繁切出页面或被打断。</li> <li>看到结果时,先观察自己的第一反应:身体是放松、紧绷,还是有某种画面跳出来?这些都是讯息的一部分。</li> <li>如果对某次解读感到困惑,可以在「记录」中回看几天前的抽牌,有时答案会在时间中慢慢对齐。</li> <li>本原型仅展示 UI / UX 结构,后续可接入账号体系、付费解读、AI 文案生成等能力。</li> </ol> </section> </div> </section> </main> <nav class="bottom-nav"> <button class="nav-item nav-item--active" data-page-jump="home"> <div class="nav-item-icon"></div> <div>首页</div> </button> <button class="nav-item" data-page-jump="spread"> <div class="nav-item-icon"></div> <div>抽牌</div> </button> <button class="nav-item" data-page-jump="result"> <div class="nav-item-icon"></div> <div>结果</div> </button> <button class="nav-item" data-page-jump="history"> <div class="nav-item-icon"></div> <div>记录</div> </button> <button class="nav-item" data-page-jump="help"> <div class="nav-item-icon">?</div> <div>说明</div> </button> </nav> <div class="app-toast" id="app-toast"> <span></span> <span>本文件为 UI 原型示例,无真实占卜逻辑。</span> </div> </div> </div> </div> <script> (function () { const pages = document.querySelectorAll(".page"); const navItems = document.querySelectorAll(".nav-item"); const pageJumpButtons = document.querySelectorAll("[data-page-jump]"); const toast = document.getElementById("app-toast"); const deckArea = document.querySelector(".deck-area"); const saveButtons = document.querySelectorAll(".result-actions .ghost-btn:first-child"); const redoButtons = document.querySelectorAll(".result-actions .ghost-btn:last-child"); const toggles = document.querySelectorAll(".toggle"); let currentPage = "home"; let isDrawing = false; function showPage(target) { if (!target || target === currentPage) return; currentPage = target; pages.forEach((page) => { const name = page.getAttribute("data-page"); page.classList.toggle("page--active", name === target); }); navItems.forEach((item) => { const jump = item.getAttribute("data-page-jump"); item.classList.toggle("nav-item--active", jump === target); }); } pageJumpButtons.forEach((btn) => { btn.addEventListener("click", () => { const target = btn.getAttribute("data-page-jump"); showPage(target); }); }); // 抽牌区域点击 → 跳到结果页并提示 if (deckArea) { // 触摸按下时表现为洗牌,松手后恢复 deckArea.addEventListener("touchstart", () => { deckArea.classList.add("deck-area--shuffling"); }); ["touchend", "touchcancel"].forEach((evt) => { deckArea.addEventListener(evt, () => { deckArea.classList.remove("deck-area--shuffling"); }); }); // 点击触发抽出动画,然后再进入结果页 deckArea.addEventListener("click", () => { if (isDrawing) return; isDrawing = true; deckArea.classList.remove("deck-area--shuffling"); deckArea.classList.add("deck-area--drawing"); setTimeout(() => { deckArea.classList.remove("deck-area--drawing"); isDrawing = false; showPage("result"); if (toast) { toast.querySelector("span:nth-child(2)").textContent = "示例:已为你生成一次占卜结果。"; toast.classList.add("app-toast--visible"); setTimeout(() => toast.classList.remove("app-toast--visible"), 1800); } }, 750); }); } // 结果页按钮:保存记录 / 重新抽一轮 saveButtons.forEach((btn) => { btn.addEventListener("click", () => { if (!toast) return; toast.querySelector("span:nth-child(2)").textContent = "示例:已添加到「记录」列表(静态 UI)。"; toast.classList.add("app-toast--visible"); setTimeout(() => toast.classList.remove("app-toast--visible"), 1800); }); }); redoButtons.forEach((btn) => { btn.addEventListener("click", () => { showPage("spread"); if (!toast) return; toast.querySelector("span:nth-child(2)").textContent = "你可以带着新问题再抽一次(原型演示)。"; toast.classList.add("app-toast--visible"); setTimeout(() => toast.classList.remove("app-toast--visible"), 1800); }); }); // 设置里的开关加一点视觉反馈 toggles.forEach((toggle) => { toggle.addEventListener("click", () => { toggle.classList.toggle("toggle--on"); }); }); // 初始轻提示,用于告知这是 UI 原型 setTimeout(() => { if (!toast) return; toast.classList.add("app-toast--visible"); setTimeout(() => toast.classList.remove("app-toast--visible"), 2200); }, 800); })(); </script> </body> </html>

本文作者:lixf6

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!