guanwei 1.1.3 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/README.en.md +1 -1
  2. package/README.md +1 -1
  3. package/dist/assets/index-CRUHghuF.js +102 -0
  4. package/dist/assets/index-CRUHghuF.js.map +1 -0
  5. package/dist/assets/index-hLV3S-Cj.css +1 -0
  6. package/dist/index.html +2 -2
  7. package/package.json +1 -1
  8. package/scripts/release.sh +15 -0
  9. package/server/src/data/db.json +189 -0
  10. package/server/src/data/guanwei.db +0 -0
  11. package/server/src/index.ts +1 -1
  12. package/server/src/services/duanyu.ts +67 -0
  13. package/server/src/services/promptBuilder.ts +5 -0
  14. package/shared/core/data/duanyu.ts +15 -14
  15. package/shared/core/data/ganzhi.ts +1 -1
  16. package/shared/core/data/gua64.ts +1 -1
  17. package/shared/core/data/liuren.ts +1 -1
  18. package/shared/core/data/qimen.ts +1 -1
  19. package/shared/core/data/xiaoliuren.ts +1 -1
  20. package/shared/core/data/ziwei.ts +1 -1
  21. package/shared/core/data/zodiac.ts +1 -1
  22. package/shared/core/engine/bazi.ts +3 -1
  23. package/shared/core/engine/calendar.ts +11 -2
  24. package/shared/core/engine/liuren.ts +218 -6
  25. package/shared/core/engine/qimen.ts +30 -8
  26. package/shared/core/types.ts +3 -0
  27. package/src/App.tsx +1 -1
  28. package/src/components/arts/LiurenArt.tsx +2 -1
  29. package/src/data/arts.ts +1 -1
  30. package/src/index.css +2 -74
  31. package/src/pages/DemoPage.tsx +66 -21
  32. package/tailwind.config.js +0 -35
  33. package/dist/assets/index-C3wrtpPY.css +0 -1
  34. package/dist/assets/index-CAyAIgw8.js +0 -102
  35. package/dist/assets/index-CAyAIgw8.js.map +0 -1
  36. package/src/components/Navigation.tsx +0 -80
  37. package/src/components/TarotCard.tsx +0 -129
  38. package/src/pages/AstrologyPage.tsx +0 -33
  39. package/src/pages/BaZiPage.tsx +0 -33
  40. package/src/pages/Home.tsx +0 -179
  41. package/src/pages/SpreadEditor.tsx +0 -230
  42. package/src/pages/SpreadLibrary.tsx +0 -199
  43. package/src/pages/SpreadLibraryPage.tsx +0 -17
  44. package/src/pages/TarotPage.tsx +0 -736
  45. package/src/pages/ZiWeiPage.tsx +0 -33
@@ -0,0 +1 @@
1
+ @import"https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@400;600;700&family=Ma+Shan+Zheng&family=Zhi+Mang+Xing&family=Noto+Sans+SC:wght@300;400;500;700&display=swap";@import"https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@300;400;500;600;700&family=Ma+Shan+Zheng&family=Zhi+Mang+Xing&display=swap";*,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}html{scroll-behavior:smooth;overflow-x:hidden}body{overflow-x:hidden}::-webkit-scrollbar{width:6px}.pointer-events-none{pointer-events:none}.visible{visibility:visible}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-0{top:0;right:0;bottom:0;left:0}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-5{margin-top:1.25rem}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.h-full{height:100%}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.resize{resize:both}.items-center{align-items:center}.justify-center{justify-content:center}.break-all{word-break:break-all}.border{border-width:1px}.tabular-nums{--tw-numeric-spacing: tabular-nums;font-variant-numeric:var(--tw-ordinal) var(--tw-slashed-zero) var(--tw-numeric-figure) var(--tw-numeric-spacing) var(--tw-numeric-fraction)}.underline{text-decoration-line:underline}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}@keyframes fade-in{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}@keyframes typing-cursor{0%,to{opacity:1}50%{opacity:0}}@media print{body{background:#fff!important}header,footer,nav,aside,.site-head,.site-nav,.back-link,.module-hero,.mh-intro,.mh-row,.altar-panel,.fit-card,.fit-note,.btn-row,.ai-streaming,.ai-error,.result-placeholder,.disclaimer,.d-title,.motes,.ink-vein,.bamboo,.cal-grid,.profile-card,.no-print{display:none!important}main{display:block!important;padding:0!important}.wrap{max-width:none!important;padding:0!important}.altar{display:block!important}.altar-result{width:100%!important;max-width:none!important}.report-view{color:#000!important;background:#fff!important}.report-view .result-card{-moz-column-break-inside:auto;break-inside:auto;border:1px solid #ddd!important;background:#fff!important;box-shadow:none!important;color:#000!important;margin-bottom:6mm}.report-view .result-card h3{-moz-column-break-after:avoid;break-after:avoid}.report-view .domain-cell,.report-view li,.report-view .traits-grid .trait{-moz-column-break-inside:avoid;break-inside:avoid}.report-view .result-title{-moz-column-break-after:avoid;break-after:avoid}.report-view .result-text,.report-view p,.report-view li,.report-view h3{color:#000!important}.report-view .domain-name{color:#555!important}@page{margin:12mm}}@keyframes pulse-soft{0%,to{opacity:.55}50%{opacity:1}}:root{--paper: #F5F1E7;--paper-deep: #EDE8D9;--paper-dim: #E4DECC;--ink: #37342C;--ink-soft: #6B675C;--ink-faint: #97917F;--line: rgba(55,52,44,.16);--line-soft: rgba(55,52,44,.1);--celadon: #96A88F;--celadon-deep: #5F7660;--celadon-tint: #E3E8DC;--crab: #7C9792;--crab-tint: #DCE4E0;--rice: #D9CDAC;--rice-tint: #EDE5CE;--cinnabar: #A5402D;--cinnabar-deep:#8C3526;--cinnabar-tint:#F3E3DC;--white-paper: #FBF9F3;--font-song: "Noto Serif SC","Songti SC","Source Han Serif SC","SimSun","STSong",serif;--font-kai: "Ma Shan Zheng","Kaiti SC","KaiTi","STKaiti","Noto Serif SC",serif;--font-zm: "Zhi Mang Xing","Ma Shan Zheng","Kaiti SC",serif;--fs-xs: .75rem;--fs-sm: .875rem;--fs-base:1.05rem;--fs-lg: 1.35rem;--fs-xl: clamp(1.6rem, 3.2vw, 2.2rem);--fs-2xl: clamp(2.2rem, 5.5vw, 3.6rem);--fs-3xl: clamp(3rem, 9vw, 6rem);--fs-display: clamp(4.2rem, 14vw, 10rem);--sp-1:.5rem;--sp-2:1rem;--sp-3:1.5rem;--sp-4:2rem;--sp-5:3rem;--sp-6:4.5rem;--sp-7:6.5rem;--sp-8:9rem;--r-sm:2px;--r-md:4px;--r-lg:8px;--shadow-paper: 0 1px 2px rgba(55,52,44,.06), 0 10px 30px -18px rgba(55,52,44,.18);--ease-out: cubic-bezier(.22,1,.36,1);--ease-ink: cubic-bezier(.5,0,.1,1);--dur-fast: .22s;--dur-mid: .6s;--dur-slow: 1.2s}*{margin:0;padding:0;box-sizing:border-box}html{scroll-behavior:smooth}body{font-family:var(--font-song);color:var(--ink);background:var(--paper);font-size:var(--fs-base);line-height:1.85;-webkit-font-smoothing:antialiased;overflow-x:hidden}::-moz-selection{background:var(--cinnabar);color:var(--paper)}::selection{background:var(--cinnabar);color:var(--paper)}img,svg{display:block;max-width:100%}a{color:inherit;text-decoration:none}button{font-family:inherit;cursor:pointer;background:none;border:none;color:inherit}input,select,textarea{font-family:inherit;color:inherit}#paper-grain{position:fixed;top:0;right:0;bottom:0;left:0;z-index:-2;pointer-events:none;background:radial-gradient(120% 90% at 12% 0%,rgba(255,255,255,.55),transparent 55%),radial-gradient(100% 80% at 100% 100%,rgba(198,188,160,.22),transparent 60%)}#paper-grain:after{content:"";position:absolute;top:0;right:0;bottom:0;left:0;background-image:repeating-linear-gradient(0deg,rgba(55,52,44,.016) 0 1px,transparent 1px 3px),repeating-linear-gradient(90deg,rgba(55,52,44,.012) 0 1px,transparent 1px 5px);opacity:.5}#mountains{position:fixed;left:0;right:0;bottom:0;height:38vh;z-index:-1;pointer-events:none;opacity:.5}.wrap{max-width:1200px;margin:0 auto;padding:0 clamp(1.25rem,4vw,3rem)}.site-head{position:sticky;top:0;z-index:50;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);background:linear-gradient(180deg,#f5f1e7eb,#f5f1e7b8);border-bottom:1px solid var(--line-soft)}.head-inner{display:flex;align-items:center;justify-content:space-between;padding-block:.8rem;gap:1rem}.brand{display:flex;align-items:baseline;gap:.6rem;flex-shrink:0}.brand .seal{align-self:center;font-family:var(--font-kai);font-size:.72rem;letter-spacing:.12em;color:var(--cinnabar);border:1.5px solid var(--cinnabar);padding:.28rem .34rem;line-height:1;border-radius:2px}.brand .name{font-family:var(--font-kai);font-size:1.45rem;letter-spacing:.32em;color:var(--ink)}.brand .sub{font-size:var(--fs-xs);color:var(--ink-faint);letter-spacing:.3em;white-space:nowrap}.nav-links{display:flex;align-items:center;gap:clamp(.6rem,2vw,1.6rem);flex-wrap:wrap;justify-content:flex-end}.nav-links a{font-size:var(--fs-sm);letter-spacing:.18em;color:var(--ink-soft);padding:.3rem 0;position:relative;transition:color var(--dur-fast) var(--ease-out)}.nav-links a:after{content:"";position:absolute;left:0;right:0;bottom:0;height:1px;background:var(--cinnabar);transform:scaleX(0);transform-origin:right;transition:transform var(--dur-mid) var(--ease-out)}.nav-links a:hover{color:var(--ink)}.nav-links a:hover:after{transform:scaleX(1);transform-origin:left}.nav-links a.active{color:var(--cinnabar)}.view{display:none;animation:viewIn .9s var(--ease-out) both}.view.active{display:block}@keyframes viewIn{0%{opacity:0;transform:translateY(18px)}to{opacity:1;transform:none}}.hero{position:relative;min-height:calc(100vh - 76px);display:flex;flex-direction:column;justify-content:center;padding-block:var(--sp-6)}.hero-kicker{display:flex;align-items:center;gap:1rem;font-size:var(--fs-sm);letter-spacing:.5em;color:var(--ink-faint);margin-bottom:var(--sp-3)}.hero-kicker:before{content:"";width:3.5rem;height:1px;background:var(--ink-faint)}.hero-title{font-family:var(--font-kai);font-size:var(--fs-display);letter-spacing:.12em;line-height:1.05;color:var(--ink);text-shadow:0 2px 30px rgba(255,255,255,.6)}.hero-title .accent{color:var(--celadon-deep);font-family:var(--font-zm)}.hero-line{margin-top:var(--sp-4);font-size:var(--fs-lg);color:var(--ink-soft);max-width:34ch;line-height:2;letter-spacing:.08em}.hero-line em{font-style:normal;color:var(--cinnabar)}.hero-desc{margin-top:var(--sp-3);max-width:52ch;color:var(--ink-faint);font-size:var(--fs-sm);letter-spacing:.14em;line-height:2.1}.hero-actions{margin-top:var(--sp-5);display:flex;gap:1rem;flex-wrap:wrap}.btn-seal{position:relative;padding:.85rem 2.2rem;font-family:var(--font-kai);font-size:1.05rem;letter-spacing:.35em;color:var(--cinnabar);border:1.5px solid var(--cinnabar);border-radius:2px;transition:all var(--dur-mid) var(--ease-out);overflow:hidden;display:inline-block;cursor:pointer}.btn-seal:before{content:"";position:absolute;top:0;right:0;bottom:0;left:0;background:var(--cinnabar);transform:scaleY(0);transform-origin:top;transition:transform var(--dur-mid) var(--ease-out)}.btn-seal:hover:before{transform:scaleY(1)}.btn-seal.btn-ghost{color:var(--ink-soft);border-color:var(--ink-soft)}.btn-seal.btn-ghost:before{background:var(--ink-soft)}.btn-seal.btn-ghost:hover{color:var(--paper)}.hero-vert{position:absolute;right:clamp(1rem,4vw,3rem);top:50%;transform:translateY(-50%);writing-mode:vertical-rl;font-family:var(--font-kai);font-size:var(--fs-sm);letter-spacing:.6em;color:var(--ink-faint);opacity:.75;display:flex;gap:2.2rem}.hero-vert span{white-space:nowrap}.scroll-hint{position:absolute;bottom:2.4rem;left:50%;transform:translate(-50%);writing-mode:vertical-rl;font-size:var(--fs-xs);letter-spacing:.5em;color:var(--ink-faint);display:flex;align-items:center;gap:.6rem;animation:floatHint 3.2s var(--ease-ink) infinite}.scroll-hint:after{content:"";width:1px;height:3rem;background:linear-gradient(180deg,var(--ink-faint),transparent)}.section-head{margin-bottom:var(--sp-5)}.section-eyebrow{display:flex;align-items:center;gap:1rem;font-size:var(--fs-sm);letter-spacing:.5em;color:var(--ink-faint)}.section-eyebrow:before{content:"";width:2.5rem;height:1px;background:var(--ink-faint)}.section-title{font-family:var(--font-kai);font-size:var(--fs-2xl);letter-spacing:.2em;margin-top:.8rem;color:var(--ink)}.section-note{margin-top:.6rem;color:var(--ink-faint);font-size:var(--fs-sm);letter-spacing:.12em}.arts-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(1.2rem,2.5vw,2rem)}@media(max-width:900px){.arts-grid{grid-template-columns:repeat(2,1fr)}}@media(max-width:560px){.arts-grid{grid-template-columns:1fr}}.art-card{position:relative;background:linear-gradient(175deg,var(--white-paper),var(--paper) 70%,var(--paper-deep));border:1px solid var(--line);border-radius:var(--r-md);padding:var(--sp-4) var(--sp-3);cursor:pointer;transition:transform var(--dur-mid) var(--ease-out),box-shadow var(--dur-mid) var(--ease-out),border-color var(--dur-mid);overflow:hidden;min-height:240px;display:flex;flex-direction:column;text-decoration:none;color:inherit}.art-card:before{content:"";position:absolute;top:0;left:1.5rem;right:1.5rem;height:1px;background:linear-gradient(90deg,transparent,var(--celadon),transparent)}.art-card:after{content:"";position:absolute;inset:auto -30% -55% -30%;height:90%;background:radial-gradient(ellipse at center,rgba(150,168,143,.16),transparent 65%);opacity:0;transition:opacity var(--dur-slow) var(--ease-ink)}.art-card:hover{transform:translateY(-4px);box-shadow:var(--shadow-paper);border-color:var(--celadon)}.art-card:hover:after{opacity:1}.art-card:focus-visible{outline:2px solid var(--celadon-deep);outline-offset:2px}.art-num{font-family:var(--font-kai);font-size:var(--fs-sm);color:var(--ink-faint);letter-spacing:.3em;display:flex;align-items:center;gap:.5rem}.art-num:after{content:"";flex:1;height:1px;background:var(--line-soft)}.art-symbol{margin:var(--sp-2) 0 var(--sp-2);font-family:var(--font-zm);font-size:var(--fs-2xl);color:var(--celadon-deep);line-height:1;text-align:center;width:3.4rem;height:3.4rem;margin-left:auto;margin-right:auto;display:flex;align-items:center;justify-content:center;border:1px solid var(--line-soft);border-radius:50%;background:radial-gradient(circle at 35% 30%,var(--celadon-tint),transparent 70%)}.art-name{font-family:var(--font-kai);font-size:var(--fs-xl);letter-spacing:.24em;text-align:center;color:var(--ink)}.art-poem{text-align:center;color:var(--ink-faint);font-size:var(--fs-sm);letter-spacing:.18em;margin-top:.6rem}.art-enter{margin-top:auto;padding-top:var(--sp-2);text-align:center;font-size:var(--fs-xs);letter-spacing:.4em;color:var(--ink-faint);transition:color var(--dur-fast)}.art-card:hover .art-enter{color:var(--cinnabar)}.about{background:var(--paper-deep);border-block:1px solid var(--line-soft)}.about-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--sp-4)}@media(max-width:860px){.about-grid{grid-template-columns:1fr}}.about-item{padding-right:var(--sp-3)}.about-item h3{font-family:var(--font-kai);font-size:1.1rem;letter-spacing:.2em;display:flex;align-items:center;gap:.7rem;color:var(--ink)}.about-item h3:before{content:"·";color:var(--cinnabar);font-size:1.4rem}.about-item p{margin-top:.7rem;font-size:var(--fs-sm);color:var(--ink-soft);line-height:2.1;letter-spacing:.06em}.module-hero{padding:var(--sp-7) 0 var(--sp-5);position:relative}.module-kicker{display:flex;align-items:center;gap:1rem;font-size:var(--fs-sm);letter-spacing:.4em;color:var(--ink-faint)}.module-kicker:before{content:"";width:2.5rem;height:1px;background:var(--ink-faint)}.module-title-row{display:flex;align-items:flex-end;gap:var(--sp-3);flex-wrap:wrap;margin-top:1rem}.module-title{font-family:var(--font-kai);font-size:var(--fs-2xl);letter-spacing:.18em;color:var(--ink)}.module-title .cn{display:block;font-family:var(--font-zm);font-size:var(--fs-3xl);color:var(--celadon-deep);letter-spacing:.1em}.module-poem{font-family:var(--font-kai);color:var(--ink-soft);font-size:var(--fs-lg);letter-spacing:.3em;padding-bottom:.5rem}.module-intro{margin-top:var(--sp-2);max-width:62ch;color:var(--ink-soft);font-size:var(--fs-sm);letter-spacing:.08em;line-height:2.2}.module-intro .source{color:var(--ink-faint);font-size:var(--fs-xs)}.altar{display:grid;grid-template-columns:340px 1fr;gap:var(--sp-5);align-items:start}@media(max-width:960px){.altar{grid-template-columns:1fr}}.altar-panel{background:linear-gradient(175deg,var(--white-paper),var(--paper-deep));border:1px solid var(--line);border-radius:var(--r-lg);padding:var(--sp-4);position:sticky;top:88px}@media(max-width:960px){.altar-panel{position:static}}.panel-title{font-family:var(--font-kai);font-size:1.1rem;letter-spacing:.25em;display:flex;align-items:center;gap:.6rem;color:var(--ink);padding-bottom:var(--sp-2);border-bottom:1px solid var(--line-soft)}.panel-title:before{content:"◇";color:var(--celadon-deep);font-size:.8rem}.field{margin-top:var(--sp-3)}.field label{display:block;font-size:var(--fs-sm);letter-spacing:.2em;color:var(--ink-soft);margin-bottom:.4rem}.field .hint{font-size:var(--fs-xs);color:var(--ink-faint);letter-spacing:.08em;margin-top:.3rem}.field-row{display:grid;grid-template-columns:1fr 1fr;gap:.8rem}.input-line{width:100%;padding:.6rem .8rem;background:#fbf9f399;border:1px solid var(--line);border-radius:var(--r-sm);font-size:var(--fs-base);transition:border-color var(--dur-fast),box-shadow var(--dur-fast)}.input-line:focus{outline:none;border-color:var(--celadon-deep);box-shadow:0 0 0 3px #5f76601f}select.input-line{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-image:linear-gradient(45deg,transparent 50%,var(--ink-soft) 50%),linear-gradient(135deg,var(--ink-soft) 50%,transparent 50%);background-position:calc(100% - 18px) 50%,calc(100% - 13px) 50%;background-size:5px 5px;background-repeat:no-repeat}.btn-divine{margin-top:var(--sp-4);width:100%;padding:1rem;background:var(--celadon-deep);color:var(--paper);font-family:var(--font-kai);font-size:1.15rem;letter-spacing:.5em;text-indent:.5em;border-radius:var(--r-sm);transition:background var(--dur-mid) var(--ease-out),transform var(--dur-mid);cursor:pointer}.btn-divine:hover{background:var(--cinnabar);transform:translateY(-1px)}.btn-divine:disabled{opacity:.5;cursor:wait}.btn-divine .small{display:block;font-size:var(--fs-xs);letter-spacing:.3em;font-family:var(--font-song);color:#fbf9f3bf;margin-top:.15rem}.altar-result{min-height:320px}.result-placeholder{display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:320px;gap:.8rem;color:var(--ink-faint);border:1px dashed var(--line);border-radius:var(--r-lg);padding:var(--sp-4);text-align:center}.result-placeholder .glyph{font-family:var(--font-zm);font-size:3.4rem;color:var(--rice)}.result-placeholder p{letter-spacing:.3em;font-size:var(--fs-sm)}.result-card{background:linear-gradient(175deg,var(--white-paper),var(--paper-deep));border:1px solid var(--line);border-radius:var(--r-lg);padding:var(--sp-4);margin-bottom:var(--sp-3);animation:viewIn .8s var(--ease-out) both}.result-card h3{font-family:var(--font-kai);font-size:1.1rem;letter-spacing:.2em;color:var(--celadon-deep);display:flex;align-items:center;gap:.6rem;padding-bottom:.8rem;margin-bottom:var(--sp-2);border-bottom:1px solid var(--line-soft)}.result-card h3:before{content:"◆";font-size:.8rem}.result-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:var(--sp-2)}.result-cell{padding:.9rem;background:#fbf9f38c;border:1px solid var(--line-soft);border-radius:var(--r-sm)}.result-cell .k{font-size:var(--fs-xs);color:var(--ink-faint);letter-spacing:.25em}.result-cell .v{font-size:1.15rem;color:var(--ink);margin-top:.2rem;letter-spacing:.08em;font-weight:500}.result-cell .v.big{font-size:1.5rem;font-family:var(--font-kai)}.result-cell .v.hot{color:var(--cinnabar)}.result-cell .v.cool{color:var(--celadon-deep)}.result-text{color:var(--ink-soft);font-size:var(--fs-sm);line-height:2.2;letter-spacing:.04em;margin-top:.5rem}.report-view,.report-view p,.report-view li,.report-view h3,.result-text,.result-text p,.result-text li{font-family:system-ui,-apple-system,PingFang SC,Hiragino Sans GB,Microsoft YaHei,sans-serif}.result-text strong{color:var(--ink);font-weight:600}.result-text .tag-hot{color:var(--cinnabar);font-weight:500}.result-text .tag-cool{color:var(--celadon-deep);font-weight:500}.result-text p+p{margin-top:.6rem}.wx-fire{color:var(--cinnabar)}.wx-wood{color:#5e7a4e}.wx-water{color:#3e5f7a}.wx-metal{color:#8c7a4e}.wx-earth{color:#7a6a4a}.disclaimer{margin-top:var(--sp-5);display:flex;gap:1rem;align-items:flex-start;padding:var(--sp-3);background:var(--cinnabar-tint);border:1px solid rgba(165,64,45,.25);border-radius:var(--r-md);font-size:var(--fs-sm);color:#7a3b2c;line-height:2}.disclaimer .seal-mini{flex-shrink:0;font-family:var(--font-kai);color:var(--cinnabar);border:1px solid var(--cinnabar);padding:.3rem .4rem;font-size:.7rem;letter-spacing:.2em;border-radius:2px;margin-top:.15rem}.disclaimer strong{color:var(--cinnabar-deep)}.site-foot{border-top:1px solid var(--line-soft);padding:var(--sp-5) 0 var(--sp-4);margin-top:var(--sp-6)}.foot-inner{display:flex;justify-content:space-between;align-items:center;gap:var(--sp-3);flex-wrap:wrap}.foot-brand{display:flex;align-items:center;gap:.8rem;font-family:var(--font-kai);letter-spacing:.3em;color:var(--ink-soft)}.foot-brand .seal{color:var(--cinnabar);border:1.5px solid var(--cinnabar);padding:.24rem .3rem;font-size:.66rem;border-radius:2px}.foot-meta{font-size:var(--fs-xs);color:var(--ink-faint);letter-spacing:.1em;line-height:2}.pill{display:inline-block;padding:.15rem .7rem;border:1px solid var(--line);border-radius:99px;font-size:var(--fs-xs);color:var(--ink-soft);letter-spacing:.15em;margin:.15rem .3rem .15rem 0;background:#fbf9f380}.pill.hot{color:var(--cinnabar);border-color:#a5402d59}.pill.cool{color:var(--celadon-deep);border-color:#5f766059}.center{text-align:center}.mt-1{margin-top:var(--sp-1)}.mt-2{margin-top:var(--sp-2)}.mt-3{margin-top:var(--sp-3)}.mt-4{margin-top:var(--sp-4)}.mt-5{margin-top:var(--sp-5)}.small{font-size:var(--fs-sm)}.tiny{font-size:var(--fs-xs)}.cinnabar{color:var(--cinnabar)}.celadon{color:var(--celadon-deep)}.muted{color:var(--ink-faint)}.fade-up{animation:fadeUp 1s var(--ease-out) both}@keyframes fadeUp{0%{opacity:0;transform:translateY(16px)}to{opacity:1;transform:none}}.delay-1{animation-delay:.12s}.delay-2{animation-delay:.24s}.delay-3{animation-delay:.36s}.separator{display:flex;align-items:center;gap:1rem;color:var(--ink-faint);font-size:var(--fs-xs);letter-spacing:.5em;margin:var(--sp-4) 0}.separator:before,.separator:after{content:"";flex:1;height:1px;background:var(--line-soft)}.back-link{display:inline-flex;align-items:center;gap:.5rem;font-size:var(--fs-sm);letter-spacing:.2em;color:var(--ink-faint);transition:color var(--dur-fast);margin-bottom:var(--sp-3)}.back-link:hover{color:var(--cinnabar)}@media(max-width:760px){.hero-vert{display:none}.art-card{min-height:200px}.brand .sub{display:none}.module-title-row{flex-direction:column;align-items:flex-start;gap:.6rem}.nav-links{gap:.6rem}}@media(prefers-reduced-motion:reduce){*{animation-duration:.01ms!important;transition-duration:.01ms!important;scroll-behavior:auto!important}}.coins{display:flex;gap:1rem;justify-content:center;flex-wrap:wrap}.coin{width:74px;height:74px;border-radius:50%;background:radial-gradient(circle at 32% 28%,#d8c9a0,#a8905e 60%,#8a7448);border:3px solid #6E5B38;box-shadow:inset 0 -6px 12px #3c2d1466,inset 0 4px 8px #fffadc80,0 6px 14px #37342c40;display:flex;align-items:center;justify-content:center;font-family:var(--font-kai);font-size:1.2rem;color:#5c4a26;position:relative}.coin:before{content:"〒";position:absolute;font-size:2rem;color:#5c4a26d9}.coin .face{position:relative;z-index:1;text-align:center;line-height:1.15;font-size:.68rem;letter-spacing:.05em}.yao-row{display:flex;align-items:center;gap:1rem;justify-content:center;padding:.55rem 0;border-bottom:1px dotted var(--line-soft)}.yao-label{width:3.2rem;font-size:var(--fs-xs);color:var(--ink-faint);letter-spacing:.2em;text-align:right;font-variant-numeric:tabular-nums}.yao-glyph{font-size:2rem;line-height:1;letter-spacing:.2em}.yao-move{color:var(--cinnabar);font-size:var(--fs-xs);letter-spacing:.2em}.yao-move .dot{width:.5rem;height:.5rem;border-radius:50%;background:var(--cinnabar);display:inline-block;margin-left:.3rem}.qimen-grid{display:grid;grid-template-columns:repeat(3,1fr);border:1px solid var(--line);border-radius:var(--r-md);overflow:hidden;max-width:560px;margin:0 auto;background:var(--paper-deep)}.qm-cell{aspect-ratio:1;border:1px solid var(--line-soft);padding:.7rem;position:relative;background:linear-gradient(160deg,#fbf9f3b3,#ede8d980)}.qm-cell .qm-name{font-family:var(--font-kai);font-size:1.05rem;color:var(--celadon-deep);letter-spacing:.15em}.qm-cell .qm-items{font-size:.72rem;color:var(--ink-soft);line-height:1.7;letter-spacing:.05em;margin-top:.3rem}.qm-cell .qm-star{font-size:.68rem;color:var(--ink-faint)}.ziwei-grid{display:grid;grid-template-columns:repeat(4,1fr);border:1px solid var(--line);border-radius:var(--r-md);overflow:hidden;max-width:640px;margin:0 auto}.zw-cell{border:1px solid var(--line-soft);padding:.55rem;min-height:96px;background:#fbf9f38c}.zw-cell.center{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.2rem;background:var(--paper-deep)}.zw-cell .zw-name{font-family:var(--font-kai);font-size:.8rem;color:var(--celadon-deep);letter-spacing:.1em;display:flex;justify-content:space-between}.zw-cell .zw-stars{font-size:.62rem;color:var(--ink-soft);line-height:1.8;letter-spacing:.04em}.liuren-stage{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:var(--sp-2)}.liuren-item{padding:1rem;background:#fbf9f38c;border:1px solid var(--line-soft);border-radius:var(--r-sm)}.liuren-item .k{font-size:var(--fs-xs);color:var(--ink-faint);letter-spacing:.3em}.liuren-item .v{font-size:1.2rem;margin-top:.3rem;letter-spacing:.2em;font-family:var(--font-kai)}.motes{position:fixed;top:0;right:0;bottom:0;left:0;pointer-events:none;overflow:hidden;z-index:0}.mote{position:absolute;font-family:var(--font-zm);color:var(--ink-faint);opacity:.2;letter-spacing:.1em;animation:moteFloat var(--mote-duration,10s) ease-in-out infinite;animation-delay:var(--mote-delay,0s);-webkit-user-select:none;-moz-user-select:none;user-select:none;text-shadow:0 1px 6px rgba(255,255,255,.5)}@keyframes moteFloat{0%,to{transform:translateY(0) translate(0);opacity:.16}50%{transform:translateY(-52px) translate(var(--mote-drift,-12px));opacity:.34}}#mountains{animation:inkDrift 90s ease-in-out infinite alternate}@keyframes inkDrift{0%{transform:translate(0) scale(1)}to{transform:translate(-22px) scale(1.03)}}.mist{position:absolute;top:0;right:0;bottom:0;left:0;pointer-events:none;overflow:hidden;z-index:0}.mist:before,.mist:after{content:"";position:absolute;top:12%;width:60vw;height:34vh;background:radial-gradient(ellipse at center,rgba(150,168,143,.13),transparent 65%);filter:blur(10px);animation:mistDrift 34s ease-in-out infinite alternate}.mist:before{left:-20vw;animation-delay:-8s}.mist:after{right:-22vw;top:26%;width:52vw;animation-delay:-20s}@keyframes mistDrift{0%{transform:translate(0)}to{transform:translate(9vw)}}.hero-glow{position:absolute;width:34vw;height:34vw;border-radius:50%;pointer-events:none;filter:blur(60px);opacity:.5;animation:glowBreath 8s ease-in-out infinite}.hero-glow--left{left:-8vw;top:-6vw;background:radial-gradient(circle,rgba(150,168,143,.22),transparent 70%)}.hero-glow--right{right:-10vw;bottom:-8vw;background:radial-gradient(circle,rgba(124,151,146,.18),transparent 70%);animation-delay:-4s}@keyframes glowBreath{0%,to{opacity:.35;transform:scale(1)}50%{opacity:.6;transform:scale(1.06)}}@media(prefers-reduced-motion:reduce){.mote,#mountains,.mist:before,.mist:after,.hero-glow{animation:none!important}}.tarot-stage{display:flex;justify-content:center;padding:var(--sp-4) 0;position:relative}.tarot-fan{display:flex;justify-content:center;gap:2px;transform:rotate(-4deg)}.tarot-card{width:96px;height:156px;flex-shrink:0;background:linear-gradient(160deg,#f7f2e4,#e6dcbe 70%,#d6c9a4);border:1px solid #C9B98F;border-radius:6px;box-shadow:0 8px 20px -10px #37342c66,inset 0 0 0 4px #c9b98f59;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:transform var(--dur-mid) var(--ease-out);position:relative}.tarot-card:before{content:"✦";font-size:1.4rem;color:#a58d5e}.tarot-card:hover{transform:translateY(-10px) rotate(0)}.tarot-card.picked{transform:translateY(-14px) rotate(0)}.tarot-card .card-inner{position:absolute;top:0;right:0;bottom:0;left:0;padding:.5rem;display:flex;flex-direction:column;align-items:center;justify-content:space-between;background:linear-gradient(170deg,#fdfaf1,#efe6cc);border-radius:5px;opacity:0;transition:opacity var(--dur-mid)}.tarot-card.revealed .card-inner{opacity:1}.card-inner .cn{font-family:var(--font-kai);font-size:1.05rem;color:var(--ink);letter-spacing:.1em}.card-inner .en{font-size:.52rem;color:var(--ink-faint);letter-spacing:.14em}.card-inner .sigil{font-size:1.6rem;color:var(--cinnabar)}.btn-seal:before{z-index:0}.btn-seal>*{position:relative;z-index:1}.btn-seal:hover>*{color:var(--paper)}.btn-seal.btn-ghost:hover>*{color:var(--paper)}#ink-vein{position:fixed;top:0;right:0;bottom:0;left:0;pointer-events:none;z-index:-1;overflow:hidden}#ink-vein .vein-lines{position:absolute;top:0;right:0;bottom:0;left:0;opacity:.05;background-image:repeating-linear-gradient(115deg,transparent 0 38px,rgba(55,52,44,.5) 38px 39px),repeating-linear-gradient(25deg,transparent 0 58px,rgba(55,52,44,.35) 58px 59px);animation:veinFlow 140s linear infinite}@keyframes veinFlow{0%{background-position:0 0,0 0}to{background-position:120px 60px,-80px 40px}}#ink-vein .vein-poem{position:absolute;right:1.6rem;top:50%;transform:translateY(-50%);writing-mode:vertical-rl;font-family:var(--font-kai);font-size:var(--fs-sm);letter-spacing:.9em;color:var(--ink-faint);opacity:.34;-webkit-user-select:none;-moz-user-select:none;user-select:none;animation:poemBreath 9s ease-in-out infinite;white-space:nowrap}@keyframes poemBreath{0%,to{opacity:.22}50%{opacity:.42}}#ink-vein .vein-seal{position:absolute;right:2.2rem;bottom:6.5rem;font-family:var(--font-kai);font-size:.6rem;letter-spacing:.2em;color:var(--cinnabar);opacity:.4;border:1px solid rgba(165,64,45,.5);padding:.3rem .34rem;border-radius:2px;animation:poemBreath 7s ease-in-out infinite;animation-delay:-3s}@media(max-width:860px){#ink-vein .vein-poem,#ink-vein .vein-seal{display:none}}.has-sub{position:relative}.sub-menu{position:absolute;top:calc(100% + .4rem);left:50%;transform:translate(-50%) translateY(-6px);min-width:9.5rem;padding:.5rem 0;background:var(--white-paper);border:1px solid var(--line);border-radius:var(--r-md);box-shadow:var(--shadow-paper);opacity:0;visibility:hidden;transition:all var(--dur-mid) var(--ease-out);z-index:60}.has-sub:hover .sub-menu,.has-sub:focus-within .sub-menu{opacity:1;visibility:visible;transform:translate(-50%) translateY(0)}.sub-menu a{display:block;padding:.42rem 1.2rem;font-size:var(--fs-sm);letter-spacing:.2em;color:var(--ink-soft);text-align:left;white-space:nowrap}.sub-menu a:hover{color:var(--cinnabar);background:var(--cinnabar-tint)}.song-select{position:relative;width:100%}.song-select .trigger{width:100%;padding:.6rem .8rem;display:flex;align-items:center;justify-content:space-between;gap:.6rem;background:#fbf9f399;border:1px solid var(--line);border-radius:var(--r-sm);font-size:var(--fs-base);color:var(--ink);cursor:pointer;text-align:left;transition:border-color var(--dur-fast),box-shadow var(--dur-fast)}.song-select .trigger:hover{border-color:var(--celadon)}.song-select.open .trigger{border-color:var(--celadon-deep);box-shadow:0 0 0 3px #5f76601f}.song-select .trigger:after{content:"";width:7px;height:7px;flex-shrink:0;border-right:1.5px solid var(--ink-soft);border-bottom:1.5px solid var(--ink-soft);transform:rotate(45deg) translateY(-2px);transition:transform var(--dur-fast)}.song-select.open .trigger:after{transform:rotate(225deg) translateY(1px)}.song-select .panel{position:absolute;top:calc(100% + .35rem);left:0;right:0;max-height:240px;overflow-y:auto;background:var(--white-paper);border:1px solid var(--line);border-radius:var(--r-md);box-shadow:var(--shadow-paper);z-index:70;padding:.35rem 0;animation:viewIn .25s var(--ease-out) both}.song-select .panel button{display:block;width:100%;padding:.5rem .9rem;text-align:left;font-size:var(--fs-sm);letter-spacing:.1em;color:var(--ink-soft);transition:background var(--dur-fast),color var(--dur-fast)}.song-select .panel button:hover{background:var(--celadon-tint);color:var(--ink)}.song-select .panel button.sel{color:var(--celadon-deep);font-weight:600}.song-select .panel button.sel:before{content:"◆ ";font-size:.62rem}.song-dialog-mask{position:fixed;top:0;right:0;bottom:0;left:0;background:#37342c59;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);display:flex;align-items:center;justify-content:center;z-index:200;animation:fadeUp .3s var(--ease-out) both}.song-dialog{width:min(420px,90vw);padding:var(--sp-4);background:linear-gradient(175deg,var(--white-paper),var(--paper-deep));border:1px solid var(--line);border-radius:var(--r-lg);box-shadow:var(--shadow-paper);animation:viewIn .35s var(--ease-out) both}.song-dialog .dlg-title{font-family:var(--font-kai);font-size:1.15rem;letter-spacing:.25em;color:var(--ink);display:flex;align-items:center;gap:.6rem;padding-bottom:var(--sp-2);border-bottom:1px solid var(--line-soft);margin-bottom:var(--sp-3)}.song-dialog .dlg-title:before{content:"❖";color:var(--cinnabar);font-size:.9rem}.song-dialog .dlg-body{color:var(--ink-soft);font-size:var(--fs-sm);line-height:2.1;letter-spacing:.05em}.song-dialog .dlg-actions{display:flex;gap:.8rem;justify-content:flex-end;margin-top:var(--sp-4)}.casting-glyph{animation:castSpin 2.4s var(--ease-ink) infinite}@keyframes castSpin{0%{transform:rotate(0) scale(1);opacity:.7}50%{transform:rotate(180deg) scale(1.08);opacity:1}to{transform:rotate(360deg) scale(1);opacity:.7}}.casting-ring{position:relative;width:4.4rem;height:4.4rem;border-radius:50%;margin:0 auto .8rem;border:1px dashed var(--celadon);animation:ringExpand 2.4s var(--ease-ink) infinite}@keyframes ringExpand{0%{transform:scale(.75);opacity:.5}50%{transform:scale(1);opacity:1}to{transform:scale(.75);opacity:.5}}.stagger>*{animation:fadeUp .7s var(--ease-out) both}.stagger>*:nth-child(1){animation-delay:.05s}.stagger>*:nth-child(2){animation-delay:.16s}.stagger>*:nth-child(3){animation-delay:.27s}.stagger>*:nth-child(4){animation-delay:.38s}.stagger>*:nth-child(5){animation-delay:.49s}.bazi-pan{display:grid;grid-template-columns:repeat(4,1fr);gap:var(--sp-2);max-width:640px;margin:0 auto}.bz-pillar{background:#fbf9f38c;border:1px solid var(--line-soft);border-radius:var(--r-sm);padding:.9rem .5rem;text-align:center;position:relative;overflow:hidden;transition:border-color var(--dur-mid),transform var(--dur-mid)}.bz-pillar:hover{border-color:var(--celadon);transform:translateY(-2px)}.bz-pillar .p-name{font-size:var(--fs-xs);color:var(--ink-faint);letter-spacing:.3em;margin-bottom:.5rem}.bz-pillar .p-gan{font-family:var(--font-kai);font-size:2rem;line-height:1.15;display:block}.bz-pillar .p-zhi{font-family:var(--font-kai);font-size:2rem;line-height:1.15;display:block;margin-top:.15rem}.bz-pillar .p-wx{font-size:var(--fs-xs);margin-top:.4rem;letter-spacing:.2em}.bz-pillar .p-shishen{font-size:var(--fs-xs);color:var(--celadon-deep);margin-top:.2rem;letter-spacing:.1em}.bz-pillar .p-nayin{font-size:.62rem;color:var(--ink-faint);margin-top:.3rem;letter-spacing:.08em;border-top:1px dotted var(--line-soft);padding-top:.35rem}.bz-pillar.day-pillar{border-color:var(--cinnabar);background:linear-gradient(175deg,#f3e3dc80,#fbf9f399);box-shadow:0 0 0 1px #a5402d26}.bz-pillar.day-pillar .p-name{color:var(--cinnabar)}.bz-pillar .p-zhu{position:absolute;top:.35rem;right:.5rem;font-size:.6rem;color:var(--ink-faint);letter-spacing:.15em}.zw-cell{transition:background var(--dur-mid),box-shadow var(--dur-mid)}.zw-cell.ming-cell{background:linear-gradient(175deg,#f3e3dc8c,#fbf9f380);box-shadow:inset 0 0 0 1px #a5402d40}.zw-cell .zw-stars .star-name{display:inline-block;padding:.06rem .22rem;border-radius:2px;margin-right:.14rem}.zw-cell .zw-stars .star-name.star-hot{color:var(--cinnabar);background:#a5402d14}.zw-cell .zw-stars .star-name.star-cool{color:var(--celadon-deep);background:#5f766014}.tarot-slot{display:flex;flex-direction:column;align-items:center;gap:.5rem}.tarot-slot .slot-label{font-size:var(--fs-xs);color:var(--ink-faint);letter-spacing:.25em;text-align:center;max-width:110px;line-height:1.6}.tarot-fan .tarot-card.face-down:after{content:"";position:absolute;top:6px;right:6px;bottom:6px;left:6px;border:1px solid rgba(165,92,62,.35);border-radius:3px}@media(prefers-reduced-motion:reduce){#ink-vein .vein-lines,#ink-vein .vein-poem,.casting-glyph,.casting-ring{animation:none!important}}.btn-seal{isolation:isolate}.btn-seal:before{z-index:-1;transform-origin:top}.btn-seal:hover{color:var(--paper)}.btn-seal .sb-label{position:relative;z-index:1}.btn-seal:hover .sb-label{color:var(--paper)}.arts-sub{padding:.6rem .4rem .8rem}.sub-group{margin-bottom:.3rem}.sub-group-name{font-size:.62rem;letter-spacing:.35em;color:var(--ink-faint);padding:.35rem .9rem .2rem;border-bottom:1px dotted var(--line-soft);margin-bottom:.2rem}.sub-group a{display:flex;align-items:baseline;gap:.55rem;font-size:var(--fs-sm);letter-spacing:.18em;color:var(--ink-soft);padding:.4rem .9rem;border-radius:var(--r-sm)}.sub-group a:hover{color:var(--cinnabar);background:var(--cinnabar-tint)}.sub-group .sub-glyph{font-family:var(--font-zm);color:var(--celadon-deep);font-size:.95rem}.sub-group .sub-poem{margin-left:auto;font-size:.6rem;color:var(--ink-faint);letter-spacing:.1em;white-space:nowrap}.user-menu .user-chip{display:flex;align-items:center;gap:.45rem;padding:.28rem .7rem .28rem .32rem;border:1px solid var(--line);border-radius:99px;background:#fbf9f3b3;cursor:pointer;transition:border-color var(--dur-fast),box-shadow var(--dur-fast)}.user-menu .user-chip:hover{border-color:var(--celadon);box-shadow:0 0 0 3px #5f76601a}.user-menu .user-seal{width:1.7rem;height:1.7rem;border-radius:50%;display:flex;align-items:center;justify-content:center;background:var(--celadon-deep);color:var(--paper);font-family:var(--font-kai);font-size:.85rem;flex-shrink:0}.user-menu .user-name{font-size:var(--fs-sm);letter-spacing:.12em;color:var(--ink);max-width:5rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.user-menu .user-caret{font-size:.62rem;color:var(--ink-faint)}.user-menu .sub-menu a{padding:.5rem 1.2rem}.side-anchor{position:fixed;left:1.4rem;top:50%;transform:translateY(-50%);display:flex;flex-direction:column;gap:.9rem;z-index:30}.side-anchor button{display:flex;align-items:center;gap:.5rem;font-size:var(--fs-xs);letter-spacing:.25em;color:var(--ink-faint);writing-mode:vertical-rl;transition:color var(--dur-fast);cursor:pointer;padding:.15rem 0}.side-anchor .dot{width:5px;height:5px;border-radius:50%;background:currentColor;opacity:.5;flex-shrink:0}.side-anchor button:hover{color:var(--ink)}.side-anchor button.active{color:var(--cinnabar)}.side-anchor button.active .dot{opacity:1;box-shadow:0 0 0 3px #a5402d26}@media(max-width:1100px){.side-anchor{display:none}}.song-search .panel{width:100%}.song-search .ss-search{padding:.5rem .7rem .35rem}.song-search .ss-input{width:100%;padding:.42rem .6rem;background:#fbf9f3cc;border:1px solid var(--line);border-radius:var(--r-sm);font-size:var(--fs-sm)}.song-search .ss-input:focus{outline:none;border-color:var(--celadon-deep)}.song-search .ss-list{max-height:220px;overflow-y:auto;padding:.2rem 0}.song-search .ss-empty{padding:.8rem;text-align:center;color:var(--ink-faint);font-size:var(--fs-xs);letter-spacing:.2em}.song-select .trigger:after{display:none}.song-select .trigger .chev{flex-shrink:0;color:var(--ink-faint);transition:transform var(--dur-fast)}.song-select.open .trigger .chev{transform:rotate(180deg);color:var(--celadon-deep)}.song-select .trigger{line-height:1.6}.song-select .panel{left:0;right:0}.user-menu .sub-menu{right:0;left:auto;transform:none;min-width:8.5rem}.user-menu:hover .sub-menu{transform:none}.cal-input{position:relative}.cal-field{display:flex;gap:.4rem;align-items:center}.cal-field .input-line{flex:1}.cal-field input.cal-error{border-color:var(--cinnabar)}.cal-toggle{display:flex;align-items:center;justify-content:center;width:2.3rem;height:2.3rem;flex-shrink:0;border:1px solid var(--line);border-radius:var(--r-sm);background:#fbf9f399;color:var(--ink-soft);cursor:pointer;transition:border-color var(--dur-fast),color var(--dur-fast)}.cal-toggle:hover{border-color:var(--celadon);color:var(--celadon-deep)}.cal-panel{position:absolute;top:calc(100% + .35rem);left:0;z-index:70;width:min(290px,90vw);padding:.7rem;background:var(--white-paper);border:1px solid var(--line);border-radius:var(--r-md);box-shadow:var(--shadow-paper);animation:viewIn .25s var(--ease-out) both}.cal-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:.5rem}.cal-title{font-family:var(--font-kai);font-size:.95rem;letter-spacing:.15em;color:var(--ink)}.cal-nav{display:flex;padding:.25rem;color:var(--ink-faint);cursor:pointer;border-radius:var(--r-sm)}.cal-nav:hover{color:var(--cinnabar);background:var(--cinnabar-tint)}.cal-week{display:grid;grid-template-columns:repeat(7,1fr);text-align:center;font-size:.62rem;color:var(--ink-faint);letter-spacing:.1em;margin-bottom:.2rem}.cal-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:2px}.cal-grid button{aspect-ratio:1;display:flex;align-items:center;justify-content:center;font-size:var(--fs-sm);color:var(--ink-soft);border-radius:var(--r-sm);cursor:pointer;transition:background var(--dur-fast),color var(--dur-fast)}.cal-grid button:hover{background:var(--celadon-tint);color:var(--ink)}.cal-grid button.sel{background:var(--celadon-deep);color:var(--paper);font-weight:600}.song-search .ss-custom{width:100%;padding:.6rem .9rem;text-align:center;font-size:var(--fs-sm);color:var(--celadon-deep);letter-spacing:.1em;cursor:pointer}.song-search .ss-custom:hover{background:var(--celadon-tint)}.song-select .trigger .chev,.song-search .trigger .chev{width:16px;height:16px;stroke-width:2.4}.nav-links .has-sub>a .chev-mini{width:14px;height:14px;stroke-width:2.2;vertical-align:-2px}.user-menu .user-caret{display:inline-flex;width:14px;height:14px}.user-menu .user-caret svg{width:14px;height:14px;stroke-width:2.2}.song-select .panel button,.song-select .trigger span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.song-select{min-width:0}.song-select .trigger{min-height:2.55rem}.song-select .panel{min-width:100%;width:-moz-max-content;width:max-content;max-width:16rem}.song-select .panel button{font-size:var(--fs-sm)}.altar-panel{position:sticky;top:84px;max-height:calc(100vh - 108px);overflow-y:auto;scrollbar-width:thin}.altar-panel::-webkit-scrollbar{width:4px}.altar-panel::-webkit-scrollbar-thumb{background:var(--celadon);border-radius:2px}@media(max-width:960px){.altar-panel{position:static;max-height:none;overflow:visible}}.altar-result{padding-bottom:var(--sp-2)}.bamboo-art{position:absolute;right:1rem;top:50%;transform:translateY(-50%);width:min(300px,30vw);pointer-events:none;opacity:.85}.bamboo-art svg{width:100%;height:auto;filter:drop-shadow(0 6px 18px rgba(95,118,96,.12))}.page-decor{position:relative}.page-decor .wrap{position:relative;z-index:1}@media(max-width:900px){.bamboo-art{display:none}}.nav-links a{white-space:nowrap}.nav-links .has-sub>a{display:inline-flex;align-items:center;gap:.28rem}.nav-links .has-sub>a .chev-mini{flex-shrink:0}.tarot-fan{transform:none;align-items:flex-start;gap:.9rem}.tarot-slot{width:104px}.tarot-slot .tarot-card{margin:0 auto}.tarot-slot .slot-label{min-height:2.6em;display:flex;align-items:flex-start;justify-content:center}.tarot-stage .tarot-fan.wrap-fan{max-width:640px}.center-actions{display:flex;gap:.8rem;justify-content:center;align-items:center;flex-wrap:wrap}.today-grid{display:grid;grid-template-columns:1fr 1fr;gap:var(--sp-4);align-items:stretch}.today-grid .result-card{display:flex;flex-direction:column;margin-bottom:0;min-height:220px}.today-grid .result-card .result-text{flex:1}@media(max-width:860px){.today-grid{grid-template-columns:1fr}}.scroll-hint{transition:opacity .6s var(--ease-out),visibility .6s}.zw-palace-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:var(--sp-2);margin-top:var(--sp-3)}.zw-palace-cell{padding:.7rem .8rem;background:#fbf9f38c;border:1px solid var(--line-soft);border-radius:var(--r-sm);transition:border-color var(--dur-mid),background var(--dur-mid)}.zw-palace-cell:hover{border-color:var(--celadon)}.zw-palace-cell.is-ming{background:linear-gradient(175deg,#f3e3dc8c,#fbf9f380);border-color:#a5402d59}.zw-palace-cell.empty{opacity:.55}.zp-head{display:flex;align-items:baseline;gap:.4rem;border-bottom:1px dotted var(--line-soft);padding-bottom:.3rem;margin-bottom:.35rem}.zp-name{font-family:var(--font-kai);font-size:.92rem;color:var(--celadon-deep);letter-spacing:.12em}.zp-zhi{font-size:.66rem;color:var(--ink-faint)}.zp-ming{margin-left:auto;font-size:.6rem;color:var(--cinnabar);border:1px solid rgba(165,64,45,.4);padding:0 .3rem;border-radius:2px}.zp-stars{font-size:.72rem;color:var(--ink-soft);line-height:1.7;letter-spacing:.06em;min-height:1.7em}.zp-theme{font-size:.62rem;color:var(--ink-faint);letter-spacing:.15em;margin-top:.2rem}.hero{padding-bottom:calc(var(--sp-6) + 2.2rem)}.scroll-hint{position:absolute;bottom:1.1rem;left:50%;transform:translate(-50%);display:flex;align-items:center;gap:.55rem;font-size:var(--fs-xs);letter-spacing:.35em;color:var(--ink-faint);writing-mode:horizontal-tb;animation:floatHintX 3s var(--ease-ink) infinite;z-index:2}.scroll-hint svg{width:14px;height:14px;animation:hintBounce 1.6s ease-in-out infinite}@keyframes floatHintX{0%,to{transform:translate(-50%) translateY(0)}50%{transform:translate(-50%) translateY(7px)}}@keyframes hintBounce{0%,to{transform:translateY(0)}50%{transform:translateY(3px)}}.scroll-hint.hidden{opacity:0;visibility:hidden}.btn-row{display:flex;gap:.8rem;align-items:center;flex-wrap:wrap}.btn-row .btn-seal,.btn-row a.btn-seal{display:inline-flex;align-items:center;justify-content:center}.dlg-actions,.center-actions{align-items:center}.report-list{margin:0;padding-left:1.2rem;color:var(--ink-soft);font-size:var(--fs-sm);line-height:2.1;letter-spacing:.04em}.report-list li::marker{color:var(--celadon-deep)}.trait-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:var(--sp-2)}.trait-cell{padding:.9rem;background:#fbf9f38c;border:1px solid var(--line-soft);border-radius:var(--r-sm);border-top:2px solid var(--celadon)}.trait-name{font-family:var(--font-kai);font-size:.98rem;color:var(--celadon-deep);letter-spacing:.15em;margin-bottom:.3rem}.trait-desc{font-size:var(--fs-sm);color:var(--ink-soft);line-height:1.9}.timeline{position:relative;padding-left:1.4rem}.timeline:before{content:"";position:absolute;left:.32rem;top:.3rem;bottom:.3rem;width:1px;background:var(--line)}.tl-item{position:relative;padding-bottom:var(--sp-3)}.tl-marker{position:absolute;left:-1.4rem;top:.25rem;width:.66rem;height:.66rem;border-radius:50%;background:var(--paper);border:2px solid var(--celadon-deep);display:flex;align-items:center;justify-content:center}.tl-item:first-child .tl-marker{background:var(--celadon-deep)}.tl-head{display:flex;align-items:baseline;gap:.6rem}.tl-head strong{font-family:var(--font-kai);font-size:.95rem;color:var(--ink);letter-spacing:.12em}.tl-age{font-size:var(--fs-xs);color:var(--ink-faint);letter-spacing:.15em}.tl-summary{font-size:var(--fs-sm);color:var(--ink-soft);line-height:2;margin-top:.2rem}.domain-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:var(--sp-2)}.domain-cell{padding:.9rem;background:#fbf9f38c;border:1px solid var(--line-soft);border-radius:var(--r-sm)}.domain-name{font-family:var(--font-kai);font-size:.9rem;color:var(--cinnabar);letter-spacing:.25em;margin-bottom:.4rem;border-bottom:1px dotted var(--line-soft);padding-bottom:.3rem}.domain-cell p{font-size:var(--fs-sm);color:var(--ink-soft);line-height:1.95;margin-top:.2rem}.fit-note{padding:var(--sp-2) var(--sp-3);margin-bottom:var(--sp-3);background:var(--rice-tint);border:1px solid rgba(217,205,172,.6);border-left:3px solid var(--rice);border-radius:var(--r-md);font-size:var(--fs-sm);color:var(--ink-soft);line-height:2}.fit-note strong{color:var(--ink);letter-spacing:.15em}.fit-note .fit-suggest{color:var(--cinnabar);margin-top:.3rem}.fit-card.fit-partial{border-left-color:var(--rice)}.fit-card.fit-bad{border-left-color:var(--cinnabar)}.fit-card.fit-ok{border-left-color:var(--celadon)}.scroll-hint.inline-hint{position:static;transform:none;margin-top:2.2rem;writing-mode:horizontal-tb;animation:none}.scroll-hint.inline-hint svg{width:15px;height:15px;animation:hintBounce 1.6s ease-in-out infinite}.hero{padding-bottom:var(--sp-6)}.ai-streaming{border:1px dashed var(--celadon);border-radius:var(--r-md);padding:var(--sp-3);background:#e3e8dc40}.ai-stream-head{display:flex;align-items:center;gap:.6rem}.ai-spinner{width:15px;height:15px;border-radius:50%;flex-shrink:0;border:2px solid var(--celadon);border-top-color:transparent;animation:castSpin 1s linear infinite}.ai-stream-body{margin-top:.7rem;max-height:260px;overflow-y:auto;padding:.6rem .8rem;background:#fbf9f3b3;border-radius:var(--r-sm);scrollbar-width:thin}.ai-error{border:1px solid rgba(165,64,45,.3);border-radius:var(--r-md);padding:var(--sp-3);background:#f3e3dc4d}.shichen-chip{display:inline-flex;align-items:center;justify-content:center;padding:.4rem .9rem;flex-shrink:0;white-space:nowrap;background:var(--celadon-tint);border:1px solid var(--celadon);border-radius:var(--r-sm);font-size:var(--fs-xs);color:var(--celadon-deep);letter-spacing:.15em}.profile-card{display:flex;align-items:center;gap:1rem;cursor:pointer;padding:1rem 1.2rem;background:linear-gradient(175deg,var(--white-paper),var(--paper-deep));border:1px solid var(--line);border-radius:var(--r-md);transition:border-color var(--dur-mid),box-shadow var(--dur-mid),transform var(--dur-mid)}.profile-card:hover{border-color:var(--celadon);box-shadow:var(--shadow-paper);transform:translateY(-2px)}.profile-card.primary{border-left:3px solid var(--cinnabar)}.pc-badge{flex-shrink:0;width:2rem;height:2rem;border-radius:50%;display:flex;align-items:center;justify-content:center;background:var(--cinnabar);color:var(--paper);font-family:var(--font-kai);font-size:.85rem}.pc-badge.sample{background:var(--celadon-deep)}.pc-body{flex:1;min-width:0}.pc-title{font-family:var(--font-kai);font-size:.98rem;color:var(--ink);letter-spacing:.12em;margin-bottom:.2rem}.pc-info{font-size:var(--fs-xs);color:var(--ink-faint);letter-spacing:.06em;line-height:1.8;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pc-action{flex-shrink:0;font-size:var(--fs-xs);color:var(--celadon-deep);letter-spacing:.2em}.module-hero.compact{padding:var(--sp-3) 0 var(--sp-2)}.mh-row{display:flex;align-items:baseline;gap:1.2rem;flex-wrap:wrap}.mh-row .back-link{margin-bottom:0;flex-shrink:0}.mh-row .module-title{margin-top:0;font-size:var(--fs-xl);display:flex;align-items:baseline;gap:.9rem;letter-spacing:.14em}.mh-row .module-title .cn{font-size:clamp(1.5rem,3vw,2.2rem);display:inline}.mh-row .mh-sub{font-family:var(--font-kai);font-size:var(--fs-sm);color:var(--ink-faint);letter-spacing:.25em;white-space:nowrap}.mh-row .mh-kicker{margin-left:auto;font-size:var(--fs-xs);letter-spacing:.3em;color:var(--ink-faint);white-space:nowrap}@media(max-width:640px){.mh-row .mh-kicker{white-space:normal;letter-spacing:.15em;line-height:1.6;max-width:16em;text-align:right}}.mh-intro{margin-top:.4rem;max-width:72ch}.mh-intro summary{cursor:pointer;font-size:var(--fs-xs);letter-spacing:.25em;color:var(--celadon-deep);list-style:none;display:inline-flex;align-items:center;gap:.4rem;-webkit-user-select:none;-moz-user-select:none;user-select:none}.mh-intro summary:before{content:"▸";font-size:.7rem;transition:transform var(--dur-fast)}.mh-intro[open] summary:before{transform:rotate(90deg)}.mh-intro p{font-size:var(--fs-sm);color:var(--ink-soft);line-height:2;margin-top:.5rem}
package/dist/index.html CHANGED
@@ -6,8 +6,8 @@
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
7
  <title>观微 · 玄学问道 —— 九术参详,观微知著</title>
8
8
  <meta name="description" content="以纸墨留白为骨,融四柱八字、紫微斗数、奇门遁甲、梅花易数、六爻、大六壬、小六壬、星盘、塔罗九术于一体。观微知著,以术问道。" />
9
- <script type="module" crossorigin src="/assets/index-CAyAIgw8.js"></script>
10
- <link rel="stylesheet" crossorigin href="/assets/index-C3wrtpPY.css">
9
+ <script type="module" crossorigin src="/assets/index-CRUHghuF.js"></script>
10
+ <link rel="stylesheet" crossorigin href="/assets/index-hLV3S-Cj.css">
11
11
  </head>
12
12
  <body>
13
13
  <div id="root"></div>
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "guanwei",
3
3
  "private": false,
4
- "version": "1.1.3",
4
+ "version": "1.2.0",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "dev": "vite",
@@ -44,9 +44,24 @@ if ! grep -q "^## \[${NEW_VER}\]" CHANGELOG.md; then
44
44
  read -rp " 已补好?回车继续: " _
45
45
  fi
46
46
 
47
+ # 2.5 防 tag 错位:提交后 HEAD 的 package.json 版本号必须等于目标版本(否则 tag 会落到错误 commit)
48
+ echo "2.5️⃣ 校验 HEAD 版本号 === ${NEW_VER}(防 v1.1.0 式 tag 错位)..."
49
+ HEAD_VER="$(node -e "console.log(require('./package.json').version)")"
50
+ if [[ "$HEAD_VER" != "$NEW_VER" ]]; then
51
+ echo " ⚠️ 当前工作区 package.json 版本为 ${HEAD_VER},目标为 ${NEW_VER}"
52
+ echo " (若刚跑过步骤 1 的版本升级但尚未提交,继续即可;提交后 tag 前将再次校验)"
53
+ fi
54
+
47
55
  echo "3️⃣ 提交 + 打 tag + 推送 git"
48
56
  git add package.json package-lock.json server/package.json server/package-lock.json CHANGELOG.md
49
57
  git commit -m "chore: 版本升级 ${NEW_VER}"
58
+ # 提交后再次校验:确保 tag 一定落在版本号已落地的 commit 上
59
+ HEAD_VER="$(node -e "console.log(require('./package.json').version)")"
60
+ if [[ "$HEAD_VER" != "$NEW_VER" ]]; then
61
+ echo " ❌ 提交后 HEAD 版本为 ${HEAD_VER},目标 ${NEW_VER}——版本号未落地,拒绝打 tag"
62
+ exit 1
63
+ fi
64
+ echo " ✅ 版本号一致,打 tag v${NEW_VER}"
50
65
  git tag "v${NEW_VER}"
51
66
  git push origin main
52
67
  git push origin "v${NEW_VER}"
@@ -12222,6 +12222,195 @@
12222
12222
  }
12223
12223
  }
12224
12224
  ]
12225
+ },
12226
+ {
12227
+ "username": "联调4768",
12228
+ "passHash": "scrypt$64a1be5442280ced0d57d277dfa9fa0b$edefd31c07e15fa626de318a85515d008228d6bf52c7ecf530a6afafc950ebc52fc329ed2970616d2a8c625449310e2aff70065048bbf2669813f54a093ce60e",
12229
+ "createdAt": 1787569754918,
12230
+ "profile": {
12231
+ "birthDate": "1996-09-09",
12232
+ "birthHourIndex": 5,
12233
+ "gender": "男",
12234
+ "location": null
12235
+ },
12236
+ "samples": [],
12237
+ "records": [
12238
+ {
12239
+ "artId": "bazi",
12240
+ "createdAt": 1,
12241
+ "result": {
12242
+ "dayGZ": "壬申"
12243
+ }
12244
+ }
12245
+ ]
12246
+ },
12247
+ {
12248
+ "username": "联调8774",
12249
+ "passHash": "scrypt$7dd369064a2bc5127e968c5c3c79eab0$1bfb59fb2da2ca7565b1be2744acb56feb132c9c5b2d41a8e74e1e36378c871bac4786656c572295a7c3004948d1adc3d98d2f7110bf7c3b2045f68853693c79",
12250
+ "createdAt": 1787569838889,
12251
+ "profile": {
12252
+ "birthDate": "1996-09-09",
12253
+ "birthHourIndex": 5,
12254
+ "gender": "男",
12255
+ "location": null
12256
+ },
12257
+ "samples": [],
12258
+ "records": [
12259
+ {
12260
+ "artId": "bazi",
12261
+ "createdAt": 1,
12262
+ "result": {
12263
+ "dayGZ": "壬申"
12264
+ }
12265
+ }
12266
+ ]
12267
+ },
12268
+ {
12269
+ "username": "联调9959",
12270
+ "passHash": "scrypt$fe9baf0e3feea172dd83fc4dd90bddee$11783ba55e4dc083fe442e185577c7e86d89cd8e51a2049f337045e60ab8a230acdceadcbca899aba2b900bc3e0a1c9ce6682190dd34a74133e330d3d83ba7fe",
12271
+ "createdAt": 1787569870216,
12272
+ "profile": {
12273
+ "birthDate": "1996-09-09",
12274
+ "birthHourIndex": 5,
12275
+ "gender": "男",
12276
+ "location": null
12277
+ },
12278
+ "samples": [],
12279
+ "records": [
12280
+ {
12281
+ "artId": "bazi",
12282
+ "createdAt": 1,
12283
+ "result": {
12284
+ "dayGZ": "壬申"
12285
+ }
12286
+ }
12287
+ ]
12288
+ },
12289
+ {
12290
+ "username": "联调6708",
12291
+ "passHash": "scrypt$3ac3d143a76487162227a90bba2845d2$86a8f1db4c6a641add09f23fcba637b6863df22d4abe783a1a4b2bd4daccd63e4863b6a9348f412586cce7022e60646115b4bf5651815a9fad8a108b9095fba7",
12292
+ "createdAt": 1787577786872,
12293
+ "profile": {
12294
+ "birthDate": "1996-09-09",
12295
+ "birthHourIndex": 5,
12296
+ "gender": "男",
12297
+ "location": null
12298
+ },
12299
+ "samples": [],
12300
+ "records": [
12301
+ {
12302
+ "artId": "bazi",
12303
+ "createdAt": 1,
12304
+ "result": {
12305
+ "dayGZ": "壬申"
12306
+ }
12307
+ }
12308
+ ]
12309
+ },
12310
+ {
12311
+ "username": "联调9224",
12312
+ "passHash": "scrypt$f479cd30f9b3135833b943094349a9ff$67a48c88afa7c9191641af8fd373b22176e1c4f5681d0c05d108ffc233080f7a233fc90ed818d7e9f7545f40a87cf6e362205830d5764d5efcf1c6566e11e8a4",
12313
+ "createdAt": 1787577979329,
12314
+ "profile": {
12315
+ "birthDate": "1996-09-09",
12316
+ "birthHourIndex": 5,
12317
+ "gender": "男",
12318
+ "location": null
12319
+ },
12320
+ "samples": [],
12321
+ "records": [
12322
+ {
12323
+ "artId": "bazi",
12324
+ "createdAt": 1,
12325
+ "result": {
12326
+ "dayGZ": "壬申"
12327
+ }
12328
+ }
12329
+ ]
12330
+ },
12331
+ {
12332
+ "username": "联调2066",
12333
+ "passHash": "scrypt$e7858b64e6b69ce6bd024ac2354b8e5a$e13f447b726c78211daff17882e69ae75316246677b4ddc78a98b37124561ea0a5b8b70a62b29ce79a962ce0c4514730bf8a13e5dc55f3cb00480c198fac364d",
12334
+ "createdAt": 1787578142164,
12335
+ "profile": {
12336
+ "birthDate": "1996-09-09",
12337
+ "birthHourIndex": 5,
12338
+ "gender": "男",
12339
+ "location": null
12340
+ },
12341
+ "samples": [],
12342
+ "records": [
12343
+ {
12344
+ "artId": "bazi",
12345
+ "createdAt": 1,
12346
+ "result": {
12347
+ "dayGZ": "壬申"
12348
+ }
12349
+ }
12350
+ ]
12351
+ },
12352
+ {
12353
+ "username": "联调6325",
12354
+ "passHash": "scrypt$3d3aa4df4a572fb9b10d909e026b0779$6e1f65b1d2f20bc42113595dafe9da46919ca4bfa0cd6f1f1c8aca6b9f8ccd165a236e9f621fa4811273e693b9995dc96e9c5fb21435513f99ca24c95dcb2e59",
12355
+ "createdAt": 1787578376461,
12356
+ "profile": {
12357
+ "birthDate": "1996-09-09",
12358
+ "birthHourIndex": 5,
12359
+ "gender": "男",
12360
+ "location": null
12361
+ },
12362
+ "samples": [],
12363
+ "records": [
12364
+ {
12365
+ "artId": "bazi",
12366
+ "createdAt": 1,
12367
+ "result": {
12368
+ "dayGZ": "壬申"
12369
+ }
12370
+ }
12371
+ ]
12372
+ },
12373
+ {
12374
+ "username": "联调9786",
12375
+ "passHash": "scrypt$1ee3931430e606b9f2b3dc0489d51ce4$aaa8317bc0a1da52fea2f5e7b6043908ecc64e4de1002357f429adb81cb872eecb72a4a3798844a1037f8b1899d7cb628f1c2da4ca381ad56a669f4efc921682",
12376
+ "createdAt": 1787578469976,
12377
+ "profile": {
12378
+ "birthDate": "1996-09-09",
12379
+ "birthHourIndex": 5,
12380
+ "gender": "男",
12381
+ "location": null
12382
+ },
12383
+ "samples": [],
12384
+ "records": [
12385
+ {
12386
+ "artId": "bazi",
12387
+ "createdAt": 1,
12388
+ "result": {
12389
+ "dayGZ": "壬申"
12390
+ }
12391
+ }
12392
+ ]
12393
+ },
12394
+ {
12395
+ "username": "联调7046",
12396
+ "passHash": "scrypt$33ba6f88579964590d68cbc509ec1556$1802a99fcf3568113592a0bbb8e2176bd4a6199490eea7cf382f8d1c74d5d3efdfc6da688889b9a03bd90e2ab7f835c7635102bf4abfe08ea696266107246d9a",
12397
+ "createdAt": 1787578527311,
12398
+ "profile": {
12399
+ "birthDate": "1996-09-09",
12400
+ "birthHourIndex": 5,
12401
+ "gender": "男",
12402
+ "location": null
12403
+ },
12404
+ "samples": [],
12405
+ "records": [
12406
+ {
12407
+ "artId": "bazi",
12408
+ "createdAt": 1,
12409
+ "result": {
12410
+ "dayGZ": "壬申"
12411
+ }
12412
+ }
12413
+ ]
12225
12414
  }
12226
12415
  ]
12227
12416
  }
Binary file
@@ -83,7 +83,7 @@ app.use('/api', hourRouter);
83
83
 
84
84
  app.listen(PORT, () => {
85
85
  console.log(`
86
- 🎴 玄冥占星后端服务已启动
86
+ 🎴 观微后端服务已启动
87
87
 
88
88
  地址: http://localhost:${PORT}
89
89
  健康检查: http://localhost:${PORT}/api/health
@@ -0,0 +1,67 @@
1
+ // 断语匹配:排盘因子 → 已校核断语(reviewed)→ 注入 AI prompt 作「古籍引证」
2
+ import { duanyuReviewed, type DuanyuEntry } from '../../../shared/core/data/duanyu';
3
+
4
+ // 盘面因子 → 断语 tags/因子 的关键词映射(每术可扩展)
5
+ // artId → 从排盘结果提取的候选关键词
6
+ function extractKeywords(artId: string, resultRaw: unknown): string[] {
7
+ const r = resultRaw as Record<string, any> | null;
8
+ if (!r) return [];
9
+ const kws: string[] = [];
10
+ switch (artId) {
11
+ case 'bazi':
12
+ // 月令/格局/用神/调候/旺衰
13
+ if (r.monthZhi) kws.push('月令');
14
+ if (r.geju) kws.push('格局', String(r.geju));
15
+ if (r.yongshen) kws.push('用神', String(r.yongshen));
16
+ if (r.strength) kws.push(r.strength === '身强' ? '旺衰' : '旺衰');
17
+ if (r.tiaohou) kws.push('调候');
18
+ break;
19
+ case 'liuyao':
20
+ if (r.yongshen) kws.push('用神', String(r.yongshen));
21
+ break;
22
+ case 'meihua':
23
+ if (r.tiyong) kws.push('体用');
24
+ break;
25
+ case 'qimen':
26
+ kws.push('阴阳遁', '三奇六仪', '起局');
27
+ break;
28
+ case 'liuren':
29
+ kws.push('四课', '三传');
30
+ break;
31
+ case 'ziwei':
32
+ if (r.brightness) kws.push('庙旺落陷', '星曜生克');
33
+ break;
34
+ case 'xiaoliuren':
35
+ kws.push('六神', '掌诀');
36
+ break;
37
+ default:
38
+ break;
39
+ }
40
+ return kws;
41
+ }
42
+
43
+ // 匹配:断语 tags 与候选关键词有交集即命中;按命中数排序取前 N
44
+ export function matchDuanyu(artId: string, resultRaw: unknown, limit = 3): DuanyuEntry[] {
45
+ const pool = duanyuReviewed().filter(d => d.art === artId);
46
+ if (pool.length === 0) return [];
47
+ const kws = extractKeywords(artId, resultRaw);
48
+ const scored = pool.map(d => {
49
+ const hit = d.tags.filter(t => kws.includes(t)).length + (d.factors || []).filter(f => kws.includes(f)).length;
50
+ return { d, hit };
51
+ }).sort((a, b) => b.hit - a.hit);
52
+ // 至少命中 1 个关键词才注入(避免无关引证);全部不命中则按术别取第一条最通用的
53
+ const matched = scored.filter(s => s.hit > 0);
54
+ const picked = matched.length > 0 ? matched : [scored[0]];
55
+ return picked.slice(0, limit).map(s => s.d);
56
+ }
57
+
58
+ // 生成 prompt 引证段(仅 reviewed 条目;未校核 seed 一律不注入)
59
+ export function duanyuPromptBlock(artId: string, resultRaw: unknown): string {
60
+ const matched = matchDuanyu(artId, resultRaw);
61
+ if (matched.length === 0) return '';
62
+ const lines = matched.map(d => {
63
+ const book = d.bookId ? '《' + d.bookId + '》' : '';
64
+ return '· ' + d.original + '(' + book + d.chapter + ')——断语:' + d.duanyu;
65
+ });
66
+ return '【古籍引证(断语库 · 已校核)】以下为与本盘/本问相关的古籍断语,可在行文自然处引用(须标注出处「《书·篇》」,且不得改写原文):\n' + lines.join('\n');
67
+ }
@@ -3,6 +3,7 @@ import type { ChatMessage } from './llmProvider';
3
3
  import { agentOf } from './skills';
4
4
  import { chartBrief } from './chartBrief';
5
5
  import { sixRelativesFacts } from './sixRelatives';
6
+ import { duanyuPromptBlock } from './duanyu';
6
7
 
7
8
  // ===== 报告 Schema 模板(命盘类:八字/紫微/星盘) =====
8
9
  const MINGPAN_SAMPLE = {
@@ -139,6 +140,8 @@ export function buildReportMessages(
139
140
  '',
140
141
  hourUnknownNote(profile),
141
142
  '',
143
+ duanyuPromptBlock(artId, resultRaw),
144
+ '',
142
145
  '【Skills 编排 · 请依序调用以下技能,逐章成文】',
143
146
  skillLines,
144
147
  '',
@@ -253,6 +256,8 @@ export function buildStep2Messages(
253
256
  '3. 全篇论断须自洽:性格/家庭/事业/感情各区块相互呼应,不得前后矛盾(同一维度两次出现必须口径一致)。',
254
257
  relativesFacts,
255
258
  '',
259
+ duanyuPromptBlock(artId, resultRaw),
260
+ '',
256
261
  '【技能编排】依序运用以下技能完成报告(每一步的结论都要落进对应章节):',
257
262
  skillLines,
258
263
  '',
@@ -1,8 +1,9 @@
1
- // 断语库 v1(种子版):结构化「原文 → 断语要点 → 适用因子」条目
1
+ // 断语库 v2:结构化「原文 → 断语要点 → 适用因子」条目
2
2
  // 定位:AI 解读的引证源(排盘 → 断语匹配 → 解读引用「《书·篇》:原文」),未来接考时校准
3
3
  // 收录规范 / 版权核查 / 处理清单:见 docs/古籍参考库收录规范.md
4
- // ⚠️ 全部条目 status: 'seed'(待逐字校核),未 reviewed 前不得注入 AI prompt
5
- // 来源 URL 2026-08-20 检索核实的公有领域在线底本
4
+ // 已校核 11 条(status: 'reviewed',来源为 ctext/维基文库/时点古籍 权威底本)→ 已接入 AI prompt 引证
5
+ // ⚠️ 剩余 5 status: 'seed'(待逐字校核/待补底本),未 reviewed 前不得注入 AI prompt
6
+ // 来源 URL 为 2026-08-20/23 检索核实的公有领域在线底本
6
7
 
7
8
  export type DuanyuStatus = 'seed' | 'reviewed';
8
9
 
@@ -27,14 +28,14 @@ export const DUANYU: DuanyuEntry[] = [
27
28
  original: '人禀天地,命属阴阳。生居覆载之内,尽在五行之中。欲知贵贱,先观月令乃提纲。',
28
29
  duanyu: '论命首重月令:先以月支定旺衰提纲,再论格局贵贱。月令为子平断命第一步。',
29
30
  factors: ['月令', '提纲'], tags: ['格局', '月令', '旺衰'],
30
- sources: ['https://ctext.org/wiki.pl?if=gb&chapter=524726'], status: 'seed',
31
+ sources: ['https://ctext.org/wiki.pl?if=gb&chapter=524726'], status: 'reviewed',
31
32
  },
32
33
  {
33
34
  id: 'dts-tiandao-01', bookId: 'ditian-sui', art: 'bazi', chapter: '天道',
34
35
  original: '欲识三元万法宗,先观帝载与神功。',
35
36
  duanyu: '断命先察三元(天干/地支/人元藏干)之体用与造化之枢机,体用立而后吉凶可论。',
36
37
  factors: ['三元', '体用'], tags: ['体用', '三元'],
37
- sources: ['https://zh.wikisource.org/zh-hant/%E6%BB%B4%E5%A4%A9%E9%AB%93%E9%97%A1%E5%BE%AE'], status: 'seed',
38
+ sources: ['https://zh.wikisource.org/zh-hant/%E6%BB%B4%E5%A4%A9%E9%AB%93%E9%97%A1%E5%BE%AE'], status: 'reviewed',
38
39
  },
39
40
  {
40
41
  id: 'dts-tiangan-01', bookId: 'ditian-sui', art: 'bazi', chapter: '天干(甲木)',
@@ -43,7 +44,7 @@ export const DUANYU: DuanyuEntry[] = [
43
44
  factors: ['调候', '生克制化'], tags: ['天干', '调候'],
44
45
  sources: ['https://zh.wikisource.org/zh-hans/%E6%BB%B4%E5%A4%A9%E9%AB%93/02'],
45
46
  note: '此诀《穷通宝鉴》亦引(转引);classics.ts 已修正:滴天髓收本源段,穷通宝鉴段注明转引(处理清单 #2 ✅)。',
46
- status: 'seed',
47
+ status: 'reviewed',
47
48
  },
48
49
  {
49
50
  id: 'zpzq-yongshen-01', bookId: 'ziping-zhenquan', art: 'bazi', chapter: '论用神',
@@ -59,14 +60,14 @@ export const DUANYU: DuanyuEntry[] = [
59
60
  original: '用神者,卦之体也。凡占必先寻用神,用神不现,须寻伏神。',
60
61
  duanyu: '六爻断卦第一步取用神:按所问之事定六亲取用;用神不上卦则寻伏神。',
61
62
  factors: ['用神', '伏神'], tags: ['用神', '六亲'],
62
- sources: ['https://www.shidianguji.com/zh/book/XYXZSBY/chapter/1lzxsn553hcfm'], status: 'seed',
63
+ sources: ['https://www.shidianguji.com/zh/book/XYXZSBY/chapter/1lzxsn553hcfm'], status: 'reviewed',
63
64
  },
64
65
  {
65
66
  id: 'bszz-yongshen-01', bookId: 'bushe-zhengzong', art: 'liuyao', chapter: '启蒙节要',
66
67
  original: '凡占必以用神为主,有根有气则吉,无根无气则凶。',
67
68
  duanyu: '用神有根(得月日生扶)有气(不遭刑冲克害)为吉,反之则凶。',
68
69
  factors: ['旺衰', '生扶'], tags: ['用神', '旺衰'],
69
- sources: ['https://ctext.org/wiki.pl?if=gb&chapter=801184'], status: 'seed',
70
+ sources: ['https://ctext.org/wiki.pl?if=gb&chapter=801184'], status: 'reviewed',
70
71
  },
71
72
  // ─── 梅花易数 meihua ───
72
73
  {
@@ -82,7 +83,7 @@ export const DUANYU: DuanyuEntry[] = [
82
83
  original: '不动不占,不因事不占。',
83
84
  duanyu: '起占原则:无异常变动不起卦、无事由不起卦,心动则应机而占。',
84
85
  factors: ['起卦原则'], tags: ['起卦', '原则'],
85
- sources: ['https://ctext.org/wiki.pl?if=gb&chapter=475043'], status: 'seed',
86
+ sources: ['https://ctext.org/wiki.pl?if=gb&chapter=475043'], status: 'reviewed',
86
87
  },
87
88
  // ─── 奇门遁甲 qimen ───
88
89
  {
@@ -90,7 +91,7 @@ export const DUANYU: DuanyuEntry[] = [
90
91
  original: '阴阳顺逆妙难穷,二至还乡一九宫。若能了达阴阳理,天地都来一掌中。',
91
92
  duanyu: '奇门总纲:冬至后阳遁顺布(一宫起)、夏至后阴遁逆布(九宫起),阴阳二遁为起局之枢。',
92
93
  factors: ['阴阳遁', '起局'], tags: ['阴阳遁', '九宫'],
93
- sources: ['https://zh.wikisource.org/wiki/%E7%85%99%E6%B3%A2%E9%87%A3%E5%8F%9F%E6%AD%8C'], status: 'seed',
94
+ sources: ['https://zh.wikisource.org/wiki/%E7%85%99%E6%B3%A2%E9%87%A3%E5%8F%9F%E6%AD%8C'], status: 'reviewed',
94
95
  },
95
96
  {
96
97
  id: 'ypdsw-sanqi-01', bookId: 'yanpo-diaosou', art: 'qimen', chapter: '三奇六仪',
@@ -106,14 +107,14 @@ export const DUANYU: DuanyuEntry[] = [
106
107
  original: '前后引从升迁吉,首尾相见始终宜。',
107
108
  duanyu: '毕法之一:三传中初末传夹拱中传(引从)主升迁之喜;首尾同气则事有始终。',
108
109
  factors: ['三传', '引从'], tags: ['毕法赋', '三传'],
109
- sources: ['https://www.shidianguji.com/zh/book/SK1599/chapter/1k1lql7vm29te'], status: 'seed',
110
+ sources: ['https://www.shidianguji.com/zh/book/SK1599/chapter/1k1lql7vm29te'], status: 'reviewed',
110
111
  },
111
112
  {
112
113
  id: 'lrdq-kezhuan-01', bookId: 'liuren-daquan', art: 'liuren', chapter: '起课',
113
114
  original: '课传既定,先视四课之生克,次观三传之发用。天地盘加临,日月星为纬。',
114
115
  duanyu: '断课次序:四课定生克、三传察发用,天地盘加临为纲。',
115
116
  factors: ['四课', '三传'], tags: ['四课', '三传', '断课'],
116
- sources: ['https://www.shidianguji.com/zh/book/SK1599/chapter/1k1lql7vm29te'], status: 'seed',
117
+ sources: ['https://www.shidianguji.com/zh/book/SK1599/chapter/1k1lql7vm29te'], status: 'reviewed',
117
118
  },
118
119
  // ─── 紫微斗数 ziwei ───
119
120
  {
@@ -122,7 +123,7 @@ export const DUANYU: DuanyuEntry[] = [
122
123
  duanyu: '斗数断命以庙旺落陷与生克制化为枢:星入庙为奇、失度为虚;星临庙旺之位再观生克之机,命坐强宫细察制化之理。',
123
124
  factors: ['庙旺落陷', '星曜生克'], tags: ['太微赋', '庙陷', '生克'],
124
125
  sources: ['https://www.shidianguji.com/mid-page/7356346219641356314', 'https://m.gushiwen.cn/guwen/bookv_46653FD803893E4F4F9BB8FD2D9C9B7F.aspx'],
125
- note: '2026-08-20 已按《紫微斗数全书》卷一·太微赋第一原文替换意译段(classics.ts 同步修正);断句待与刻本终校。', status: 'seed',
126
+ note: '2026-08-20 已按《紫微斗数全书》卷一·太微赋第一原文替换意译段(classics.ts 同步修正);断句待与刻本终校。', status: 'reviewed',
126
127
  },
127
128
  // ─── 小六壬 xiaoliuren(民间口诀,无成书古籍)───
128
129
  {
@@ -139,7 +140,7 @@ export const DUANYU: DuanyuEntry[] = [
139
140
  original: '易与天地准,故能弥纶天地之道。仰以观于天文,俯以察于地理,是故知幽明之故。',
140
141
  duanyu: '易学认识论总纲:卦象法天地,观天文察地理而知幽明——一切卦术「观物取象」的理据。',
141
142
  factors: ['观物取象'], tags: ['系辞', '取象'],
142
- sources: ['https://ctext.org/book-of-changes/zh'], status: 'seed',
143
+ sources: ['https://ctext.org/book-of-changes/zh'], status: 'reviewed',
143
144
  },
144
145
  ];
145
146
 
@@ -1,4 +1,4 @@
1
- // 干支 / 五行 / 纳音 / 六十甲子(移植参考项目 data.js)
1
+ // 干支 / 五行 / 纳音 / 六十甲子
2
2
 
3
3
  export const GAN = ['甲', '乙', '丙', '丁', '戊', '己', '庚', '辛', '壬', '癸'] as const;
4
4
  export const ZHI = ['子', '丑', '寅', '卯', '辰', '巳', '午', '未', '申', '酉', '戌', '亥'] as const;
@@ -1,4 +1,4 @@
1
- // 八卦与六十四卦(移植参考项目 data.js GUA64)
1
+ // 八卦与六十四卦(卦名/卦象/上下卦)
2
2
 
3
3
  export const BAGUA: Record<number, { name: string; symbol: string; nature: string; wx: string }> = {
4
4
  1: { name: '乾', symbol: '☰', nature: '天', wx: '金' },
@@ -1,4 +1,4 @@
1
- // 大六壬数据(移植参考项目 data.js)
1
+ // 大六壬数据(月将/贵人/天将符号与五行)
2
2
 
3
3
  export const LR_JIANGS: [string, string][] = [
4
4
  ['登明', '亥'], ['河魁', '戌'], ['从魁', '酉'], ['传送', '申'], ['小吉', '未'], ['胜光', '午'],
@@ -1,4 +1,4 @@
1
- // 奇门遁甲数据(移植参考项目 data.js)
1
+ // 奇门遁甲数据(九宫/八门/九星/八神)
2
2
 
3
3
  export const QM_NAMES = ['坎', '坤', '震', '巽', '中', '乾', '兑', '艮', '离'];
4
4
  export const QM_MEN = ['休', '死', '伤', '杜', '中', '开', '惊', '生', '景'];
@@ -1,4 +1,4 @@
1
- // 小六壬掌诀(移植参考项目 data.js)
1
+ // 小六壬掌诀(六掌诀与吉凶)
2
2
 
3
3
  export const XLR: Record<string, { ji: string; wx: string; num: string; dir: string; poem: string; text: string }> = {
4
4
  大安: { ji: '吉', wx: '木', num: '一、五、七', dir: '东方', poem: '身不动时,属木青龙,谋事主一、五、七。',
@@ -1,4 +1,4 @@
1
- // 紫微斗数数据(移植参考项目 data.js)
1
+ // 紫微斗数数据(主星/辅星/亮度/四化表)
2
2
  // 补齐层(2026-08-20):生年四化 / 主星庙旺落陷 / 格局库 / 辅星安星起法
3
3
 
4
4
  export const ZW_STARS: Record<string, string> = {
@@ -1,4 +1,4 @@
1
- // 星盘数据(移植参考项目 data.js)
1
+ // 星盘数据(黄道十二宫/庙旺表)
2
2
 
3
3
  export const ZODIAC: [string, string, string][] = [
4
4
  ['白羊', 'Aries', '♈'], ['金牛', 'Taurus', '♉'], ['双子', 'Gemini', '♊'], ['巨蟹', 'Cancer', '♋'],