@openephemeris/mcp-server 3.13.9 → 3.13.10

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 (61) hide show
  1. package/README.md +2 -2
  2. package/config/dev-allowlist.json +28 -4
  3. package/dist/index.js +45 -0
  4. package/dist/oauth/dcr.d.ts +11 -0
  5. package/dist/oauth/dcr.js +49 -0
  6. package/dist/oauth/discovery.d.ts +11 -0
  7. package/dist/oauth/discovery.js +40 -0
  8. package/dist/oauth/pkce.d.ts +18 -0
  9. package/dist/oauth/pkce.js +34 -0
  10. package/dist/oauth/rate-limit.d.ts +20 -0
  11. package/dist/oauth/rate-limit.js +65 -0
  12. package/dist/oauth/store.d.ts +68 -0
  13. package/dist/oauth/store.js +247 -0
  14. package/dist/oauth/supabase-jwt.d.ts +39 -0
  15. package/dist/oauth/supabase-jwt.js +194 -0
  16. package/dist/oauth/token.d.ts +21 -0
  17. package/dist/oauth/token.js +213 -0
  18. package/dist/prompts.js +171 -159
  19. package/dist/server-sse.js +134 -36
  20. package/dist/tools/apps/bazi-app.d.ts +23 -0
  21. package/dist/tools/apps/bazi-app.js +224 -0
  22. package/dist/tools/apps/bi-wheel-app.d.ts +14 -7
  23. package/dist/tools/apps/bi-wheel-app.js +293 -108
  24. package/dist/tools/apps/bodygraph-app.js +38 -3
  25. package/dist/tools/apps/moon-phase-app.d.ts +19 -0
  26. package/dist/tools/apps/moon-phase-app.js +190 -0
  27. package/dist/tools/apps/transit-timeline-app.d.ts +20 -0
  28. package/dist/tools/apps/transit-timeline-app.js +243 -0
  29. package/dist/tools/apps/vedic-chart-app.d.ts +17 -0
  30. package/dist/tools/apps/vedic-chart-app.js +226 -0
  31. package/dist/tools/index.js +4 -0
  32. package/dist/tools/specialized/acg.js +2 -2
  33. package/dist/tools/specialized/bazi.js +367 -44
  34. package/dist/tools/specialized/bi_wheel.js +1 -1
  35. package/dist/tools/specialized/chart_wheel.js +1 -1
  36. package/dist/tools/specialized/comparative.js +4 -4
  37. package/dist/tools/specialized/eclipse.js +1 -1
  38. package/dist/tools/specialized/electional.js +4 -4
  39. package/dist/tools/specialized/ephemeris_core.js +2 -2
  40. package/dist/tools/specialized/ephemeris_extended.js +8 -8
  41. package/dist/tools/specialized/hd_bodygraph.js +1 -1
  42. package/dist/tools/specialized/hd_cycles.js +2 -2
  43. package/dist/tools/specialized/hd_group.js +2 -2
  44. package/dist/tools/specialized/human_design.js +1 -1
  45. package/dist/tools/specialized/moon.js +2 -2
  46. package/dist/tools/specialized/natal.js +1 -1
  47. package/dist/tools/specialized/progressed.js +1 -1
  48. package/dist/tools/specialized/relocation.js +1 -1
  49. package/dist/tools/specialized/returns.js +3 -3
  50. package/dist/tools/specialized/synastry.js +1 -1
  51. package/dist/tools/specialized/transits.js +1 -1
  52. package/dist/tools/specialized/vedic.js +1 -1
  53. package/dist/tools/specialized/venus_star_points.js +6 -6
  54. package/dist/ui/bazi.html +213 -0
  55. package/dist/ui/bi-wheel.html +762 -489
  56. package/dist/ui/bodygraph.html +1788 -1649
  57. package/dist/ui/chart-wheel.html +1772 -1593
  58. package/dist/ui/moon-phase.html +6758 -0
  59. package/dist/ui/transit-timeline.html +6835 -0
  60. package/dist/ui/vedic-chart.html +210 -0
  61. package/package.json +2 -2
@@ -49,7 +49,7 @@ registerTool({
49
49
  required: ["planet", "datetime", "return_year"],
50
50
  additionalProperties: false,
51
51
  },
52
- annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true },
52
+ annotations: { title: "HD Planetary Return", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
53
53
  handler: async (args) => {
54
54
  validateRequired(args, ["planet", "datetime", "return_year"]);
55
55
  return await getActiveClient().request("POST", "/human-design/cycles/return", {
@@ -100,7 +100,7 @@ registerTool({
100
100
  required: ["planet", "datetime", "target_year"],
101
101
  additionalProperties: false,
102
102
  },
103
- annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true },
103
+ annotations: { title: "HD Opposition Chart", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
104
104
  handler: async (args) => {
105
105
  validateRequired(args, ["planet", "datetime", "target_year"]);
106
106
  return await getActiveClient().request("POST", "/human-design/cycles/opposition", {
@@ -28,7 +28,7 @@ registerTool({
28
28
  required: ["person_a_datetime", "person_b_datetime"],
29
29
  additionalProperties: false,
30
30
  },
31
- annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true },
31
+ annotations: { title: "HD Composite Chart", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
32
32
  handler: async (args) => {
33
33
  validateRequired(args, ["person_a_datetime", "person_b_datetime"]);
34
34
  const body = {
@@ -88,7 +88,7 @@ registerTool({
88
88
  required: ["group_name", "members"],
89
89
  additionalProperties: false,
90
90
  },
91
- annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true },
91
+ annotations: { title: "HD Penta Group Chart", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
92
92
  handler: async (args) => {
93
93
  validateRequired(args, ["group_name", "members"]);
94
94
  const members = args.members.map((m) => ({
@@ -64,7 +64,7 @@ registerTool({
64
64
  required: ["datetime"],
65
65
  additionalProperties: false,
66
66
  },
67
- annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true },
67
+ annotations: { title: "Human Design Chart", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
68
68
  handler: async (args) => {
69
69
  validateRequired(args, ["datetime"]);
70
70
  const body = {
@@ -33,7 +33,7 @@ registerTool({
33
33
  required: [],
34
34
  additionalProperties: false,
35
35
  },
36
- annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true },
36
+ annotations: { title: "Moon Phase", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
37
37
  handler: async (args) => {
38
38
  validateCoordinates(args, "latitude", "longitude");
39
39
  const params = {};
@@ -91,7 +91,7 @@ registerTool({
91
91
  required: ["phase"],
92
92
  additionalProperties: false,
93
93
  },
94
- annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true },
94
+ annotations: { title: "Next Lunar Phase", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
95
95
  handler: async (args) => {
96
96
  // Map our clean enum to display names the calendar API returns
97
97
  const phaseNameMap = {
@@ -73,7 +73,7 @@ registerTool({
73
73
  required: ["datetime", "latitude", "longitude"],
74
74
  additionalProperties: false,
75
75
  },
76
- annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true },
76
+ annotations: { title: "Natal Chart", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
77
77
  handler: async (args) => {
78
78
  validateRequired(args, ["datetime", "latitude", "longitude"]);
79
79
  const body = {
@@ -56,7 +56,7 @@ registerTool({
56
56
  required: ["birth_datetime", "birth_latitude", "birth_longitude", "target_datetime"],
57
57
  additionalProperties: false,
58
58
  },
59
- annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true },
59
+ annotations: { title: "Progressed Chart", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
60
60
  handler: async (args) => {
61
61
  validateRequired(args, ["birth_datetime", "birth_latitude", "birth_longitude", "target_datetime"]);
62
62
  const body = {
@@ -46,7 +46,7 @@ registerTool({
46
46
  required: ["natal_datetime", "natal_latitude", "natal_longitude", "relocation_latitude", "relocation_longitude"],
47
47
  additionalProperties: false,
48
48
  },
49
- annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true },
49
+ annotations: { title: "Relocation Chart", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
50
50
  handler: async (args) => {
51
51
  validateRequired(args, ["natal_datetime", "natal_latitude", "natal_longitude", "relocation_latitude", "relocation_longitude"]);
52
52
  const body = {
@@ -59,7 +59,7 @@ registerTool({
59
59
  required: ["birth_datetime"],
60
60
  additionalProperties: false,
61
61
  },
62
- annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true },
62
+ annotations: { title: "Solar Return", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
63
63
  handler: async (args) => {
64
64
  validateRequired(args, ["birth_datetime"]);
65
65
  // Default target to current year if not provided
@@ -127,7 +127,7 @@ registerTool({
127
127
  required: ["birth_datetime"],
128
128
  additionalProperties: false,
129
129
  },
130
- annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true },
130
+ annotations: { title: "Lunar Return", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
131
131
  handler: async (args) => {
132
132
  validateRequired(args, ["birth_datetime"]);
133
133
  const targetDt = args.target_datetime ?? new Date().toISOString();
@@ -182,7 +182,7 @@ registerTool({
182
182
  required: ["body", "birth_datetime", "target_datetime"],
183
183
  additionalProperties: false,
184
184
  },
185
- annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true },
185
+ annotations: { title: "Planetary Return", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
186
186
  handler: async (args) => {
187
187
  validateRequired(args, ["body", "birth_datetime", "target_datetime"]);
188
188
  const requestBody = {
@@ -50,7 +50,7 @@ registerTool({
50
50
  ],
51
51
  additionalProperties: false,
52
52
  },
53
- annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true },
53
+ annotations: { title: "Synastry Chart", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
54
54
  handler: async (args) => {
55
55
  validateRequired(args, [
56
56
  "person_a_datetime", "person_a_latitude", "person_a_longitude",
@@ -66,7 +66,7 @@ registerTool({
66
66
  required: ["natal_datetime", "natal_latitude", "natal_longitude", "start_date", "end_date"],
67
67
  additionalProperties: false,
68
68
  },
69
- annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true },
69
+ annotations: { title: "Transit Search", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
70
70
  handler: async (args) => {
71
71
  validateRequired(args, ["natal_datetime", "natal_latitude", "natal_longitude", "start_date", "end_date"]);
72
72
  // ── Step 1: Compute natal chart to extract real planetary longitudes ──
@@ -33,7 +33,7 @@ registerTool({
33
33
  required: ["datetime", "latitude", "longitude"],
34
34
  additionalProperties: false,
35
35
  },
36
- annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true },
36
+ annotations: { title: "Vedic Natal Chart", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
37
37
  handler: async (args) => {
38
38
  validateRequired(args, ["datetime", "latitude", "longitude"]);
39
39
  validateCoordinates(args, "latitude", "longitude");
@@ -29,7 +29,7 @@ registerTool({
29
29
  required: ["datetime", "latitude", "longitude"],
30
30
  additionalProperties: false,
31
31
  },
32
- annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true },
32
+ annotations: { title: "Venus Star Points", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
33
33
  handler: async (args) => {
34
34
  validateRequired(args, ["datetime", "latitude", "longitude"]);
35
35
  const query = {};
@@ -59,7 +59,7 @@ registerTool({
59
59
  required: ["start_date", "end_date"],
60
60
  additionalProperties: false,
61
61
  },
62
- annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true },
62
+ annotations: { title: "Venus Conjunctions", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
63
63
  handler: async (args) => {
64
64
  validateRequired(args, ["start_date", "end_date"]);
65
65
  const query = {};
@@ -89,7 +89,7 @@ registerTool({
89
89
  required: ["date"],
90
90
  additionalProperties: false,
91
91
  },
92
- annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true },
92
+ annotations: { title: "Venus 8-Year Star", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
93
93
  handler: async (args) => {
94
94
  validateRequired(args, ["date"]);
95
95
  const query = {};
@@ -120,7 +120,7 @@ registerTool({
120
120
  required: [],
121
121
  additionalProperties: false,
122
122
  },
123
- annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true },
123
+ annotations: { title: "Venus Phase", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
124
124
  handler: async (args) => {
125
125
  const query = {};
126
126
  if (args.format)
@@ -147,7 +147,7 @@ registerTool({
147
147
  required: ["start_date", "end_date"],
148
148
  additionalProperties: false,
149
149
  },
150
- annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true },
150
+ annotations: { title: "Venus Elongations", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
151
151
  handler: async (args) => {
152
152
  validateRequired(args, ["start_date", "end_date"]);
153
153
  const query = {};
@@ -177,7 +177,7 @@ registerTool({
177
177
  required: ["start_date"],
178
178
  additionalProperties: false,
179
179
  },
180
- annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true },
180
+ annotations: { title: "Venus Stations", readOnlyHint: true, destructiveHint: false, idempotentHint: true },
181
181
  handler: async (args) => {
182
182
  validateRequired(args, ["start_date"]);
183
183
  const query = {};
@@ -0,0 +1,213 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <meta name="color-scheme" content="dark light" />
7
+ <title>BaZi Four Pillars Explorer</title>
8
+
9
+
10
+ <style>*,:before,:after{box-sizing:border-box;margin:0;padding:0}:root{--bg-primary:#090b0f;--bg-secondary:#12161d;--bg-tertiary:#1c222b;--bg-hover:#272e3b;--border:#282e38;--border-subtle:#1d2229;--text-primary:#e1e5eb;--text-secondary:#9da5b1;--text-muted:#6c727b;--accent:#62b3ff;--accent-warm:#e6ac3d;--radius:8px;--radius-sm:4px;--radius-lg:12px;--wuxing-wood:#31aa40;--wuxing-fire:#f14d4c;--wuxing-earth:#ca8a10;--wuxing-metal:#9fafc8;--wuxing-water:#0099e0;--wuxing-wood-bg:#1b451e;--wuxing-fire-bg:#65201e;--wuxing-earth-bg:#583c10;--wuxing-metal-bg:#3c434d;--wuxing-water-bg:#003f60;--dm-border:#d29922;--dm-bg:#201a10;--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark}@supports (color:color(display-p3 0 0 0)){:root{--bg-primary:color(display-p3 .036047 .0438664 .059078);--bg-secondary:color(display-p3 .0739679 .0866504 .111186);--bg-tertiary:color(display-p3 .114361 .13221 .166818);--bg-hover:color(display-p3 .15679 .180114 .225406);--border:color(display-p3 .161376 .180145 .216325);--border-subtle:color(display-p3 .118728 .13221 .158123);--text-primary:color(display-p3 .883958 .896627 .920543);--text-secondary:color(display-p3 .622745 .646433 .6914);--text-muted:color(display-p3 .429297 .445909 .477439);--accent:color(display-p3 .446063 .694439 1.01077);--accent-warm:color(display-p3 .866978 .684443 .324483);--wuxing-wood:color(display-p3 .343741 .657851 .307102);--wuxing-fire:color(display-p3 .872583 .352089 .325751);--wuxing-earth:color(display-p3 .754604 .550516 .200367);--wuxing-metal:color(display-p3 .636614 .68404 .77495);--wuxing-water:color(display-p3 .226818 .589506 .875825);--wuxing-wood-bg:color(display-p3 .150499 .267148 .135899);--wuxing-fire-bg:color(display-p3 .36387 .143128 .129405);--wuxing-earth-bg:color(display-p3 .328547 .240912 .0972974);--wuxing-metal-bg:color(display-p3 .240898 .260909 .299258);--wuxing-water-bg:color(display-p3 .0921333 .242221 .364185);--dm-border:color(display-p3 .789908 .60997 .245434);--dm-bg:color(display-p3 .119765 .101379 .0671137)}}@supports (color:lab(0% 0 0)){:root{--bg-primary:lab(3.02674% -.179462 -2.15476);--bg-secondary:lab(7.16596% -.441141 -5.41423);--bg-tertiary:lab(12.9118% -.60384 -7.27841);--bg-hover:lab(18.6882% -.727877 -9.08878);--border:lab(18.7165% -.689313 -7.30941);--border-subtle:lab(12.9391% -.548743 -5.49436);--text-primary:lab(90.6878% -.517368 -3.73452);--text-secondary:lab(67.45% -.932217 -7.41489);--text-muted:lab(47.7476% -.701487 -5.56231);--accent:lab(70.4043% -7.21234 -50.7672);--accent-warm:lab(74.5248% 14.3487 62.5064);--wuxing-wood:lab(61.5358% -50.6384 43.17);--wuxing-fire:lab(57.3944% 63.124 38.0626);--wuxing-earth:lab(62.7263% 19.0613 64.9727);--wuxing-metal:lab(70.8424% -1.5474 -14.6858);--wuxing-water:lab(59.1191% -14.8305 -49.6808);--wuxing-wood-bg:lab(25.5679% -22.4482 18.6532);--wuxing-fire-bg:lab(23.6033% 31.5073 18.7032);--wuxing-earth-bg:lab(28.0231% 9.19801 30.8603);--wuxing-metal-bg:lab(28.0014% -.778109 -7.34471);--wuxing-water-bg:lab(24.4811% -7.8918 -24.9024);--dm-border:lab(67.5362% 14.8294 64.5914);--dm-bg:lab(9.55197% 1.60985 7.31485)}}@media (prefers-color-scheme:light){:root{--bg-primary:#f3f5f9;--bg-secondary:#e7ebf2;--bg-tertiary:#d8dee8;--bg-hover:#d0d8e5;--border:#bdc5d1;--border-subtle:#d2d8e2;--text-primary:#0f1216;--text-secondary:#414853;--text-muted:#6c727b;--accent:#0065b2;--accent-warm:#966800;--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--wuxing-wood:#005f0e;--wuxing-fire:#a20519;--wuxing-earth:#805300;--wuxing-metal:#48566c;--wuxing-water:#005380;--wuxing-wood-bg:#c0e3c0;--wuxing-fire-bg:#fdc9c4;--wuxing-earth-bg:#f2daba;--wuxing-metal-bg:#d6dfec;--wuxing-water-bg:#b4defc;--dm-border:#966800;--dm-bg:#f6ede0}@supports (color:color(display-p3 0 0 0)){:root{--bg-primary:color(display-p3 .95471 .961142 .973263);--bg-secondary:color(display-p3 .909797 .922535 .946581);--bg-tertiary:color(display-p3 .852455 .871315 .906983);--bg-hover:color(display-p3 .821139 .84609 .893374);--border:color(display-p3 .745559 .770059 .816515);--border-subtle:color(display-p3 .826933 .845684 .881152);--text-primary:color(display-p3 .0608605 .0691527 .0850621);--text-secondary:color(display-p3 .261513 .281801 .32064);--text-muted:color(display-p3 .429297 .445909 .477439);--accent:color(display-p3 .143802 .388951 .683672);--accent-warm:color(display-p3 .596632 .396992 -.158844);--wuxing-wood:color(display-p3 .0968244 .374385 .0683277);--wuxing-fire:color(display-p3 .580784 .119608 .128804);--wuxing-earth:color(display-p3 .489279 .326588 -.0287041);--wuxing-metal:color(display-p3 .294019 .335238 .415486);--wuxing-water:color(display-p3 -.0775243 .316124 .547443);--wuxing-wood-bg:color(display-p3 .778394 .884493 .76257);--wuxing-fire-bg:color(display-p3 .959986 .795906 .773571);--wuxing-earth-bg:color(display-p3 .93331 .858308 .743829);--wuxing-metal-bg:color(display-p3 .84663 .871726 .919277);--wuxing-water-bg:color(display-p3 .739548 .864306 .975015);--dm-border:color(display-p3 .596632 .396992 -.158844);--dm-bg:color(display-p3 .957692 .931855 .88349)}}@supports (color:lab(0% 0 0)){:root{--bg-primary:lab(96.5044% -.267148 -1.87216);--bg-secondary:lab(93.0079% -.518024 -3.73493);--bg-tertiary:lab(88.3503% -.749856 -5.58736);--bg-hover:lab(86.0117% -.963002 -7.43048);--border:lab(79.0511% -.952899 -7.42528);--border-subtle:lab(86.0302% -.748128 -5.58645);--text-primary:lab(5.23796% -.285208 -3.0582);--text-secondary:lab(30.3224% -.794604 -7.35167);--text-muted:lab(47.7476% -.701487 -5.56231);--accent:lab(41.1205% -1.70796 -50.1423);--accent-warm:lab(47.6194% 20.1868 104.51);--wuxing-wood:lab(34.5429% -45.3762 42.1829);--wuxing-fire:lab(34.3495% 57.1812 37.8813);--wuxing-earth:lab(39.4811% 17.4358 64.8795);--wuxing-metal:lab(36.0172% -1.09252 -14.5181);--wuxing-water:lab(32.2784% -8.65509 -43.065);--wuxing-wood-bg:lab(86.8562% -16.7675 13.1583);--wuxing-fire-bg:lab(85.5193% 18.485 10.0423);--wuxing-earth-bg:lab(88.4503% 4.9783 19.0112);--wuxing-metal-bg:lab(88.3319% -.966102 -7.43206);--wuxing-water-bg:lab(86.1283% -8.87641 -19.3614);--dm-border:lab(47.6194% 20.1868 104.51);--dm-bg:lab(94.2538% 1.22291 7.5882)}}}html,body{background:var(--bg-primary);width:100%;height:100%;color:var(--text-primary);font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Noto Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;font-size:13px;line-height:1.5;overflow:hidden}body{flex-direction:column;display:flex}#app{flex-direction:column;flex:1;display:flex;overflow:hidden}#loading-state{color:var(--text-secondary);flex-direction:column;flex:1;justify-content:center;align-items:center;gap:12px;display:flex}#loading-state[hidden]{display:none}.oe-loader{width:48px;height:48px;animation:1.2s linear infinite spin}.oe-loader circle{fill:none;stroke:var(--accent);stroke-width:3px;stroke-dasharray:200;stroke-dashoffset:80px;stroke-linecap:round}@keyframes spin{to{transform:rotate(360deg)}}.chart-status{background:var(--bg-secondary);border-top:1px solid var(--border-subtle);color:var(--text-muted);opacity:0;z-index:50;padding:6px 14px;font-size:11px;transition:opacity .2s,transform .2s;position:fixed;bottom:0;left:0;right:0;transform:translateY(100%)}.chart-status.visible{opacity:1;transform:translateY(0)}#bazi-container{flex-direction:column;flex:1;gap:16px;padding:16px;display:flex;overflow-y:auto}#bazi-container[hidden]{display:none}.bazi-pillars{grid-template-columns:repeat(4,1fr);gap:8px;animation:.6s ease-out bazi-fade-in;display:grid}@keyframes bazi-fade-in{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}.bazi-pillar{border:1px solid var(--border-subtle);border-radius:var(--radius);background:var(--bg-secondary);cursor:pointer;flex-direction:column;transition:border-color .15s,box-shadow .15s,transform .15s;display:flex;overflow:hidden}.bazi-pillar:hover{border-color:var(--border);transform:translateY(-1px);box-shadow:0 2px 12px rgba(0,0,0,.1);box-shadow:0 2px 12px color(display-p3 0 0 0/.1);box-shadow:0 2px 12px lab(0% 0 0/.1)}.bazi-pillar--dm{border-color:var(--dm-border);background:var(--dm-bg);box-shadow:inset 3px 0 0 var(--dm-border), inset -3px 0 0 var(--dm-border)}.bazi-pillar--dm:hover{border-color:var(--dm-border);box-shadow:inset 3px 0 0 var(--dm-border), inset -3px 0 0 var(--dm-border), 0 4px 16px rgba(210,153,34,.15)}@supports (color:color(display-p3 0 0 0)){.bazi-pillar--dm:hover{box-shadow:inset 3px 0 0 var(--dm-border), inset -3px 0 0 var(--dm-border), 0 4px 16px color(display-p3 .789908 .60997 .245434/.15)}}@supports (color:lab(0% 0 0)){.bazi-pillar--dm:hover{box-shadow:inset 3px 0 0 var(--dm-border), inset -3px 0 0 var(--dm-border), 0 4px 16px lab(67.5362% 14.8294 64.5914/.15)}}.bazi-pillar-header{text-transform:uppercase;letter-spacing:.08em;color:var(--text-muted);background:var(--bg-tertiary);border-bottom:1px solid var(--border-subtle);justify-content:center;align-items:center;gap:4px;padding:6px 8px;font-size:10px;font-weight:700;display:flex}.bazi-pillar--dm .bazi-pillar-header{color:var(--dm-border)}.dm-badge{background:var(--dm-border);color:#090b0f;color:color(display-p3 .036047 .0438664 .059078);color:lab(3.02674% -.179462 -2.15476);letter-spacing:.04em;border-radius:10px;padding:1px 5px;font-size:9px;font-weight:700}@media (prefers-color-scheme:light){.dm-badge{color:#fcf8f1;color:color(display-p3 .985424 .972455 .948118);color:lab(97.7087% .579864 3.77247)}}.bazi-stem-zone{border-bottom:1px solid var(--border-subtle);flex-direction:column;align-items:center;gap:2px;padding:10px 8px;display:flex}.bazi-stem-chinese{font-size:28px;font-weight:700;line-height:1.1}.bazi-stem-name{color:var(--text-secondary);font-size:11px;font-weight:600}.bazi-stem-element{color:var(--bg-primary);border-radius:10px;padding:1px 6px;font-size:10px;font-weight:500}@media (prefers-color-scheme:light){.bazi-stem-element{color:#fff6f8;color:color(display-p3 .992746 .964982 .972458);color:lab(97.5544% 3.37881 .0330448)}}.bazi-branch-zone{border-bottom:1px solid var(--border-subtle);flex-direction:column;align-items:center;gap:2px;padding:10px 8px;display:flex}.bazi-branch-animal-emoji{font-size:22px;line-height:1.1}.bazi-branch-name{color:var(--text-secondary);font-size:11px;font-weight:600}.bazi-branch-animal{color:var(--text-muted);font-size:10px}.bazi-hidden-zone{flex-direction:column;align-items:center;gap:3px;min-height:48px;padding:6px 8px;display:flex}.bazi-hidden-label{text-transform:uppercase;letter-spacing:.06em;color:var(--text-muted);margin-bottom:1px;font-size:9px;font-weight:600}.bazi-hidden-stems{flex-wrap:wrap;justify-content:center;gap:6px;display:flex}.bazi-hidden-stem{flex-direction:column;align-items:center;gap:1px;display:flex}.bazi-hidden-char{font-size:16px;font-weight:600;line-height:1.1}.bazi-hidden-strength{opacity:.7;border-radius:50%;width:6px;height:6px}.bazi-hidden-strength--main{opacity:1}.bazi-hidden-strength--secondary{opacity:.65}.bazi-hidden-strength--residual{opacity:.35}.bazi-ten-god-tag{background:var(--bg-hover);color:var(--text-secondary);border-radius:10px;padding:1px 5px;font-size:9px;font-weight:600}.bazi-balance{background:var(--bg-secondary);border:1px solid var(--border-subtle);border-radius:var(--radius);flex-direction:column;gap:8px;padding:12px 14px;animation:.8s ease-out .2s both bazi-fade-in;display:flex}.bazi-balance-header{justify-content:space-between;align-items:center;display:flex}.bazi-balance-title{text-transform:uppercase;letter-spacing:.06em;color:var(--text-muted);font-size:11px;font-weight:700}.bazi-balance-strength{background:var(--bg-hover);color:var(--text-secondary);border-radius:10px;padding:2px 8px;font-size:11px;font-weight:600}.bazi-balance-strength--strong{color:var(--wuxing-wood)}.bazi-balance-strength--weak{color:var(--wuxing-fire)}.bazi-bar-container{border-radius:var(--radius-sm);border:1px solid var(--border-subtle);height:28px;display:flex;overflow:hidden}.bazi-bar-segment{min-width:24px;color:var(--text-primary);justify-content:center;align-items:center;font-size:10px;font-weight:700;transition:flex .4s ease-out;display:flex;position:relative;overflow:hidden}.bazi-bar-segment-label{opacity:.8;white-space:nowrap;font-size:9px}.bazi-bar-legend{flex-wrap:wrap;justify-content:center;gap:12px;display:flex}.bazi-legend-item{color:var(--text-secondary);cursor:pointer;align-items:center;gap:4px;font-size:11px;transition:color .15s;display:flex}.bazi-legend-item:hover{color:var(--text-primary)}.bazi-legend-dot{border-radius:50%;flex-shrink:0;width:8px;height:8px}.bazi-legend-pct{font-variant-numeric:tabular-nums;font-weight:700}.bazi-legend-score{color:var(--text-muted);font-size:10px}.bazi-yongshen{border-radius:var(--radius-sm);background:var(--bg-tertiary);border:1px solid var(--border-subtle);color:var(--text-secondary);justify-content:center;align-items:center;gap:6px;padding:6px 12px;font-size:12px;display:flex}.bazi-yongshen-label{color:var(--text-muted);font-weight:500}.bazi-yongshen-value{font-weight:700}.bazi-drawer-overlay{z-index:60;opacity:0;background:rgba(0,0,0,.4);background:color(display-p3 0 0 0/.4);background:lab(0% 0 0/.4);transition:opacity .2s;position:fixed;top:0;bottom:0;left:0;right:0}.bazi-drawer-overlay.visible{opacity:1}.bazi-drawer{background:var(--bg-secondary);border-top:1px solid var(--border);border-radius:var(--radius-lg) var(--radius-lg) 0 0;z-index:61;max-height:60vh;padding:16px;transition:transform .25s ease-out;position:fixed;bottom:0;left:0;right:0;overflow-y:auto;transform:translateY(100%)}.bazi-drawer.visible{transform:translateY(0)}.bazi-drawer-handle{background:var(--border);border-radius:2px;width:36px;height:4px;margin:0 auto 12px}.bazi-drawer-title{align-items:center;gap:8px;margin-bottom:12px;font-size:15px;font-weight:700;display:flex}.bazi-drawer-section{margin-bottom:12px}.bazi-drawer-section-title{text-transform:uppercase;letter-spacing:.06em;color:var(--text-muted);margin-bottom:6px;font-size:10px;font-weight:700}.bazi-drawer-ten-god{background:var(--bg-tertiary);border-radius:var(--radius-sm);align-items:center;gap:10px;margin-bottom:6px;padding:8px 10px;display:flex}.bazi-drawer-tg-chinese{font-size:22px;font-weight:700}.bazi-drawer-tg-info{flex-direction:column;gap:1px;display:flex}.bazi-drawer-tg-name{font-size:13px;font-weight:600}.bazi-drawer-tg-category{color:var(--text-muted);text-transform:capitalize;font-size:11px}.bazi-drawer-hidden-table{border-collapse:collapse;width:100%;font-size:12px}.bazi-drawer-hidden-table th{text-transform:uppercase;letter-spacing:.04em;color:var(--text-muted);text-align:left;border-bottom:1px solid var(--border-subtle);padding:4px 8px;font-size:10px;font-weight:700}.bazi-drawer-hidden-table td{border-bottom:1px solid var(--border-subtle);color:var(--text-secondary);padding:5px 8px}.bazi-drawer-hidden-table tr:last-child td{border-bottom:none}.bazi-actions{flex-wrap:wrap;gap:8px;animation:.8s ease-out .4s both bazi-fade-in;display:flex}.action-btn{border-radius:var(--radius);border:1px solid var(--border);background:var(--bg-secondary);color:var(--text-secondary);cursor:pointer;align-items:center;gap:4px;padding:8px 14px;font-size:12px;font-weight:600;transition:background .15s,color .15s,box-shadow .15s;display:inline-flex}.action-btn:hover{background:var(--bg-hover);color:var(--text-primary)}.action-btn--primary{color:#cbdfff;color:color(display-p3 .811259 .873257 .992208);color:lab(88.2011% -1.89927 -18.3428);background:linear-gradient(135deg,#1d4587,#32326d);background:linear-gradient(135deg,color(display-p3 .153533 .2659 .511983),color(display-p3 .195291 .194916 .412031));background:linear-gradient(135deg,lab(29.3399% 5.63866 -42.0206),lab(23.3003% 14.2058 -35.0966));border-color:#33548c;border-color:color(display-p3 .229049 .327581 .533696);border-color:lab(35.4848% 1.84765 -35.3079)}.action-btn--primary:hover{background:linear-gradient(135deg,#2151a1,#3d3c86);background:linear-gradient(135deg,color(display-p3 .180134 .31482 .611657),color(display-p3 .239239 .236673 .50744));background:linear-gradient(135deg,lab(34.9279% 7.15981 -48.9835),lab(28.8006% 17.5515 -42.0715));box-shadow:0 2px 12px rgba(29,69,135,.3);box-shadow:0 2px 12px color(display-p3 .153533 .2659 .511983/.3);box-shadow:0 2px 12px lab(29.3399% 5.63866 -42.0206/.3)}.error-state,.empty-state{text-align:center;flex-direction:column;flex:1;justify-content:center;align-items:center;gap:8px;padding:32px;display:flex}.error-icon,.empty-icon{font-size:32px}.tooltip{z-index:100;border-radius:var(--radius-sm);background:var(--bg-tertiary);border:1px solid var(--border);color:var(--text-primary);pointer-events:none;opacity:0;max-width:200px;padding:6px 10px;font-size:11px;transition:opacity .15s;position:fixed}.tooltip.visible{opacity:1}@media (max-width:360px){.bazi-stem-chinese{font-size:22px}.bazi-branch-animal-emoji{font-size:18px}.bazi-hidden-char{font-size:13px}.bazi-pillar-header{padding:4px 6px;font-size:9px}#bazi-container{gap:10px;padding:10px}.bazi-pillars{gap:4px}}.chart-layer{opacity:0;transform-origin:310px 310px;will-change:opacity, transform;transform:scale(.98)translateZ(0)}#chart-container.chart-visible .chart-layer{animation:.6s cubic-bezier(.16,1,.3,1) forwards svgLayerAssemble;animation-delay:calc(var(--layer-index,1) * .1s + .1s)}@keyframes svgLayerAssemble{0%{opacity:0;transform:scale(.97)}to{opacity:1;transform:scale(1)}}.floating-action-btn:after{content:"";background:linear-gradient(90deg,transparent,rgba(255,255,255,.2),transparent);width:50%;height:100%;animation:3s 2s infinite shimmer;position:absolute;top:0;left:-100%;transform:skew(-20deg)}@keyframes shimmer{0%{left:-100%}20%{left:200%}to{left:200%}}@keyframes slideUpFadeIn{0%{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}@keyframes slideUpFadeInPanel{0%{opacity:0;transform:translateY(12px)scale(.98)}to{opacity:1;transform:translateY(0)scale(1)}}
11
+ /*$vite$:1*/</style>
12
+ </head>
13
+ <body>
14
+ <div id="app">
15
+ <div id="loading-state">
16
+ <svg class="oe-loader" viewBox="0 0 100 100"><circle cx="50" cy="50" r="45"/></svg>
17
+ <p>Computing Four Pillars…</p>
18
+ </div>
19
+ <div id="chart-status" class="chart-status" role="status" aria-live="polite"></div>
20
+ <div id="bazi-container" hidden></div>
21
+ <div id="tooltip" class="tooltip" role="tooltip"></div>
22
+ </div>
23
+
24
+ <script type="module">(function() {
25
+ let e2 = document.createElement("link").relList;
26
+ if (e2 && e2.supports && e2.supports("modulepreload")) return;
27
+ for (let e3 of document.querySelectorAll('link[rel="modulepreload"]')) n2(e3);
28
+ new MutationObserver((e3) => {
29
+ for (let t3 of e3) if (t3.type === "childList") for (let e4 of t3.addedNodes) e4.tagName === "LINK" && e4.rel === "modulepreload" && n2(e4);
30
+ }).observe(document, { childList: true, subtree: true });
31
+ function t2(e3) {
32
+ let t3 = {};
33
+ return e3.integrity && (t3.integrity = e3.integrity), e3.referrerPolicy && (t3.referrerPolicy = e3.referrerPolicy), e3.crossOrigin === "use-credentials" ? t3.credentials = "include" : e3.crossOrigin === "anonymous" ? t3.credentials = "omit" : t3.credentials = "same-origin", t3;
34
+ }
35
+ function n2(e3) {
36
+ if (e3.ep) return;
37
+ e3.ep = true;
38
+ let n3 = t2(e3);
39
+ fetch(e3.href, n3);
40
+ }
41
+ })();
42
+ var e = { Jia: "\u7532", Yi: "\u4E59", Bing: "\u4E19", Ding: "\u4E01", Wu: "\u620A", Ji: "\u5DF1", Geng: "\u5E9A", Xin: "\u8F9B", Ren: "\u58EC", Gui: "\u7678" }, t = { Zi: "\u5B50", Chou: "\u4E11", Yin: "\u5BC5", Mao: "\u536F", Chen: "\u8FB0", Si: "\u5DF3", Wu: "\u5348", Wei: "\u672A", Shen: "\u7533", You: "\u9149", Xu: "\u620C", Hai: "\u4EA5" }, n = { Rat: "\u{1F400}", Ox: "\u{1F402}", Tiger: "\u{1F405}", Rabbit: "\u{1F407}", Dragon: "\u{1F409}", Snake: "\u{1F40D}", Horse: "\u{1F40E}", Goat: "\u{1F410}", Monkey: "\u{1F412}", Rooster: "\u{1F413}", Dog: "\u{1F415}", Pig: "\u{1F416}" }, r = { Wood: "var(--wuxing-wood)", Fire: "var(--wuxing-fire)", Earth: "var(--wuxing-earth)", Metal: "var(--wuxing-metal)", Water: "var(--wuxing-water)" }, i = { Wood: "var(--wuxing-wood-bg)", Fire: "var(--wuxing-fire-bg)", Earth: "var(--wuxing-earth-bg)", Metal: "var(--wuxing-metal-bg)", Water: "var(--wuxing-water-bg)" }, a = { Wood: "\u{1F333}", Fire: "\u{1F525}", Earth: "\u26F0\uFE0F", Metal: "\u2694\uFE0F", Water: "\u{1F4A7}" }, o = ["Year", "Month", "Day", "Hour"], s = ["year", "month", "day", "hour"];
43
+ function c(e2) {
44
+ let t2 = [];
45
+ return t2.push(l(e2)), t2.push(f(e2)), t2.push(p()), t2.join("");
46
+ }
47
+ function l(e2) {
48
+ return '<div class="bazi-pillars">' + s.map((t2, n2) => {
49
+ var r2;
50
+ let i2 = e2.chart[t2], a2 = (r2 = e2.ten_gods) == null || (r2 = r2.pillars) == null ? void 0 : r2[n2], s2 = n2 === 2;
51
+ return u(o[n2], i2, a2, s2, n2);
52
+ }).join("") + "</div>";
53
+ }
54
+ function u(i2, a2, o2, s2, c2) {
55
+ var l2, u2, f2, p2;
56
+ let m2 = ((l2 = a2.stem) == null ? void 0 : l2.name) || "?", g2 = ((u2 = a2.stem) == null ? void 0 : u2.element) || "", _2 = ((f2 = a2.branch) == null ? void 0 : f2.name) || "?", v2 = ((p2 = a2.branch) == null ? void 0 : p2.animal) || "", y2 = e[m2] || m2, b2 = t[_2] || _2, x2 = n[v2] || "", S2 = r[g2] || "var(--text-primary)", C2 = s2 ? " bazi-pillar--dm" : "", w2 = s2 ? '<span class="dm-badge">DM</span>' : "", T2 = "";
57
+ if (o2 != null && o2.visible_ten_god) {
58
+ let e2 = o2.visible_ten_god;
59
+ T2 = '<span class="bazi-ten-god-tag">' + h(e2.chinese || e2.name) + "</span>";
60
+ }
61
+ let E2 = d((o2 == null ? void 0 : o2.hidden_ten_gods) || []);
62
+ return '<div class="bazi-pillar' + C2 + '" data-pillar="' + c2 + '"><div class="bazi-pillar-header">' + h(i2) + " " + w2 + " " + T2 + '</div><div class="bazi-stem-zone"><span class="bazi-stem-chinese" style="color:' + S2 + '">' + h(y2) + '</span><span class="bazi-stem-name">' + h(m2) + '</span><span class="bazi-stem-element" style="background:' + S2 + '">' + h(g2) + '</span></div><div class="bazi-branch-zone"><span class="bazi-branch-animal-emoji">' + x2 + '</span><span class="bazi-branch-name">' + h(b2) + " " + h(_2) + '</span><span class="bazi-branch-animal">' + h(v2) + "</span></div>" + E2 + "</div>";
63
+ }
64
+ function d(e2) {
65
+ return !e2 || e2.length === 0 ? '<div class="bazi-hidden-zone"><span class="bazi-hidden-label">Hidden Stems</span><span style="font-size:10px;color:var(--text-muted)">\u2014</span></div>' : '<div class="bazi-hidden-zone"><span class="bazi-hidden-label">Hidden Stems</span><div class="bazi-hidden-stems">' + e2.map(function(e3) {
66
+ var t2;
67
+ let n2 = e3.hidden_stem, i2 = r[n2.element] || "var(--text-secondary)", a2 = "bazi-hidden-strength--" + (n2.strength || "main");
68
+ return '<div class="bazi-hidden-stem" title="' + h(n2.name) + " (" + h(n2.element) + " " + h(n2.polarity) + ") \u2014 " + h(((t2 = e3.ten_god) == null ? void 0 : t2.name) || "") + '"><span class="bazi-hidden-char" style="color:' + i2 + '">' + h(n2.chinese || n2.name) + '</span><span class="bazi-hidden-strength ' + a2 + '" style="background:' + i2 + '"></span></div>';
69
+ }).join("") + "</div></div>";
70
+ }
71
+ function f(e2) {
72
+ let t2 = e2.element_balance;
73
+ if (!t2 || !t2.elements || t2.elements.length === 0) return "";
74
+ let n2 = ["Wood", "Fire", "Earth", "Metal", "Water"].map(function(e3) {
75
+ return t2.elements.find(function(t3) {
76
+ return t3.element === e3;
77
+ });
78
+ }).filter(Boolean), o2 = t2.day_master_strength || "neutral", s2 = o2 === "strong" ? "bazi-balance-strength--strong" : o2 === "weak" ? "bazi-balance-strength--weak" : "", c2 = o2.charAt(0).toUpperCase() + o2.slice(1), l2 = n2.map(function(e3) {
79
+ let t3 = Math.max(e3.percentage, 3), n3 = r[e3.element] || "var(--text-primary)", a2 = i[e3.element] || "var(--bg-tertiary)", o3 = e3.percentage >= 12 ? '<span class="bazi-bar-segment-label">' + Math.round(e3.percentage) + "%</span>" : "";
80
+ return '<div class="bazi-bar-segment" style="flex:' + t3 + ";background:" + a2 + ";color:" + n3 + '">' + o3 + "</div>";
81
+ }).join(""), u2 = n2.map(function(e3) {
82
+ let t3 = r[e3.element] || "var(--text-primary)", n3 = a[e3.element] || "";
83
+ return '<div class="bazi-legend-item"><span class="bazi-legend-dot" style="background:' + t3 + '"></span><span>' + n3 + " " + h(e3.element) + '</span><span class="bazi-legend-pct">' + Math.round(e3.percentage) + '%</span><span class="bazi-legend-score">(' + e3.score.toFixed(1) + ")</span></div>";
84
+ }).join(""), d2 = t2.yong_shen_element || "", f2 = a[d2] || "", p2 = d2 ? '<div class="bazi-yongshen"><span class="bazi-yongshen-label">Useful God (\u7528\u795E)</span><span class="bazi-yongshen-value" style="color:' + (r[d2] || "inherit") + '">' + f2 + " " + h(d2) + "</span></div>" : "";
85
+ return '<div class="bazi-balance"><div class="bazi-balance-header"><span class="bazi-balance-title">Wu Xing Balance</span><span class="bazi-balance-strength ' + s2 + '">' + h(t2.day_master_element || "") + " Day Master \u2014 " + h(c2) + '</span></div><div class="bazi-bar-container">' + l2 + '</div><div class="bazi-bar-legend">' + u2 + "</div>" + p2 + "</div>";
86
+ }
87
+ function p() {
88
+ return '<div class="bazi-actions"><button class="action-btn action-btn--primary" data-action="ask-claude" data-query="day-master">\u{1F52E} Interpret My Day Master</button><button class="action-btn" data-action="ask-claude" data-query="element-balance">\u2696\uFE0F Analyse My Element Balance</button><button class="action-btn" data-action="ask-claude" data-query="ten-gods">\u{1F3DB}\uFE0F Explain My Ten Gods</button></div>';
89
+ }
90
+ function m(i2, a2) {
91
+ var c2, l2, u2, d2, f2;
92
+ let p2 = o[a2] || "Pillar", m2 = i2.chart[s[a2]], g2 = (c2 = i2.ten_gods) == null || (c2 = c2.pillars) == null ? void 0 : c2[a2], _2 = ((l2 = m2.stem) == null ? void 0 : l2.name) || "?", v2 = ((u2 = m2.stem) == null ? void 0 : u2.element) || "", y2 = ((d2 = m2.branch) == null ? void 0 : d2.name) || "?", b2 = ((f2 = m2.branch) == null ? void 0 : f2.animal) || "", x2 = e[_2] || _2, S2 = t[y2] || y2, C2 = r[v2] || "var(--text-primary)", w2 = "";
93
+ if (g2 != null && g2.visible_ten_god) {
94
+ let e2 = g2.visible_ten_god;
95
+ w2 = '<div class="bazi-drawer-section"><div class="bazi-drawer-section-title">Ten God (\u5341\u795E)</div><div class="bazi-drawer-ten-god"><span class="bazi-drawer-tg-chinese" style="color:' + C2 + '">' + h(e2.chinese || "") + '</span><div class="bazi-drawer-tg-info"><span class="bazi-drawer-tg-name">' + h(e2.name) + " (" + h(e2.pinyin || "") + ')</span><span class="bazi-drawer-tg-category">' + h(e2.category) + "</span></div></div></div>";
96
+ } else a2 === 2 && (w2 = '<div class="bazi-drawer-section"><div class="bazi-drawer-section-title">Day Master (\u65E5\u4E3B)</div><p style="font-size:12px;color:var(--text-secondary)">This is your Day Master \u2014 the stem that represents you. Ten Gods are calculated relative to this pillar.</p></div>');
97
+ let T2 = (g2 == null ? void 0 : g2.hidden_ten_gods) || [], E2 = "";
98
+ return T2.length > 0 && (E2 = '<div class="bazi-drawer-section"><div class="bazi-drawer-section-title">Hidden Stems (\u85CF\u5E72)</div><table class="bazi-drawer-hidden-table"><thead><tr><th>Stem</th><th>Element</th><th>Strength</th><th>Ten God</th></tr></thead><tbody>' + T2.map(function(e2) {
99
+ let t2 = e2.hidden_stem, n2 = e2.ten_god;
100
+ return '<tr><td style="color:' + (r[t2.element] || "inherit") + ';font-weight:700">' + h(t2.chinese || t2.name) + " " + h(t2.name) + "</td><td>" + h(t2.element) + " " + h(t2.polarity) + "</td><td>" + h(t2.strength) + " (" + t2.weight.toFixed(1) + ")</td><td>" + h((n2 == null ? void 0 : n2.name) || "\u2014") + " " + h((n2 == null ? void 0 : n2.chinese) || "") + "</td></tr>";
101
+ }).join("") + "</tbody></table></div>"), '<div class="bazi-drawer-handle"></div><div class="bazi-drawer-title"><span style="color:' + C2 + '">' + h(x2) + h(S2) + "</span> " + h(p2) + " Pillar \u2014 " + h(_2) + " " + h(y2) + " (" + (n[b2] || "") + " " + h(b2) + ")</div>" + w2 + E2 + '<div class="bazi-drawer-section"><button class="action-btn action-btn--primary" data-action="ask-claude" data-query="pillar-' + a2 + '">\u{1F52E} Interpret this ' + h(p2) + " Pillar</button></div>";
102
+ }
103
+ function h(e2) {
104
+ return e2 ? e2.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;") : "";
105
+ }
106
+ var g = null, _ = false, v = document.getElementById("loading-state"), y = document.getElementById("bazi-container"), b = document.getElementById("chart-status"), x = document.getElementById("tooltip");
107
+ function S() {
108
+ let e2 = window.__BAZI_DATA__;
109
+ if (!e2 || !e2.chart) {
110
+ A("No BaZi data was provided.");
111
+ return;
112
+ }
113
+ g = e2, y.innerHTML = c(e2), v.hidden = true, y.hidden = false;
114
+ let t2 = e2.chart.day_master;
115
+ t2 && k("Day Master: " + (t2.stem || "\u2014") + " " + (t2.element || "\u2014")), C(), document.addEventListener("keydown", function(e3) {
116
+ if (e3.key === "Escape" && _) {
117
+ let e4 = document.querySelector(".bazi-drawer-overlay"), t3 = document.querySelector(".bazi-drawer");
118
+ e4 && t3 && E(e4, t3);
119
+ }
120
+ });
121
+ }
122
+ function C() {
123
+ y.addEventListener("click", function(e2) {
124
+ let t2 = e2.target, n2 = t2.closest("[data-action]");
125
+ if (n2) {
126
+ D(n2);
127
+ return;
128
+ }
129
+ let r2 = t2.closest("[data-pillar]");
130
+ r2 && g && T(parseInt(r2.getAttribute("data-pillar") || "0", 10));
131
+ }), y.addEventListener("mouseover", function(e2) {
132
+ let t2 = e2.target.closest(".bazi-hidden-stem");
133
+ if (t2) {
134
+ let n2 = t2.getAttribute("title");
135
+ n2 && (x.textContent = n2, x.classList.add("visible"), w(e2));
136
+ }
137
+ }), y.addEventListener("mouseout", function(e2) {
138
+ e2.target.closest(".bazi-hidden-stem") && x.classList.remove("visible");
139
+ }), y.addEventListener("mousemove", function(e2) {
140
+ x.classList.contains("visible") && w(e2);
141
+ });
142
+ }
143
+ function w(e2) {
144
+ x.style.left = e2.clientX + 12 + "px", x.style.top = e2.clientY - 30 + "px";
145
+ }
146
+ function T(e2) {
147
+ if (!g || _) return;
148
+ _ = true;
149
+ let t2 = document.createElement("div");
150
+ t2.className = "bazi-drawer-overlay";
151
+ let n2 = document.createElement("div");
152
+ n2.className = "bazi-drawer", n2.innerHTML = m(g, e2), n2.addEventListener("click", function(e3) {
153
+ let r2 = e3.target.closest("[data-action]");
154
+ r2 && (D(r2), E(t2, n2));
155
+ }), document.body.appendChild(t2), document.body.appendChild(n2), requestAnimationFrame(function() {
156
+ t2.classList.add("visible"), n2.classList.add("visible");
157
+ }), t2.addEventListener("click", function() {
158
+ E(t2, n2);
159
+ });
160
+ }
161
+ function E(e2, t2) {
162
+ e2.classList.remove("visible"), t2.classList.remove("visible"), setTimeout(function() {
163
+ e2.remove(), t2.remove(), _ = false;
164
+ }, 250);
165
+ }
166
+ function D(e2) {
167
+ let t2 = e2.getAttribute("data-action"), n2 = e2.getAttribute("data-query") || "";
168
+ if (t2 === "ask-claude" && g) {
169
+ var r2;
170
+ let e3 = O(n2, g);
171
+ (r2 = window.__mcp_host__) != null && r2.askClaude && window.__mcp_host__.askClaude(e3);
172
+ }
173
+ }
174
+ function O(e2, t2) {
175
+ let n2 = t2.chart.day_master, r2 = ((n2 == null ? void 0 : n2.stem) || "") + " " + ((n2 == null ? void 0 : n2.element) || "");
176
+ if (e2 === "day-master") {
177
+ var i2, a2;
178
+ return "Interpret my BaZi Day Master: " + r2 + ". My element balance shows " + (((i2 = t2.element_balance) == null ? void 0 : i2.day_master_strength) || "unknown") + " strength. Useful God (Yong Shen): " + (((a2 = t2.element_balance) == null ? void 0 : a2.yong_shen_element) || "unknown") + ". Give me personality traits, strengths, challenges, and practical advice.";
179
+ }
180
+ if (e2 === "element-balance") {
181
+ var o2, s2, c2;
182
+ return "Analyse my BaZi Wu Xing element balance: " + (((o2 = t2.element_balance) == null ? void 0 : o2.elements) || []).map(function(e3) {
183
+ return e3.element + " " + Math.round(e3.percentage) + "%";
184
+ }).join(", ") + ". Day Master strength: " + (((s2 = t2.element_balance) == null ? void 0 : s2.day_master_strength) || "unknown") + ". Yong Shen: " + (((c2 = t2.element_balance) == null ? void 0 : c2.yong_shen_element) || "unknown") + ". Explain what this balance means for my health, career, and relationships.";
185
+ }
186
+ if (e2 === "ten-gods") {
187
+ var l2;
188
+ return "Explain my BaZi Ten Gods configuration: " + (((l2 = t2.ten_gods) == null ? void 0 : l2.pillars) || []).filter(function(e3) {
189
+ return e3.visible_ten_god;
190
+ }).map(function(e3) {
191
+ var t3;
192
+ return e3.pillar + ": " + (((t3 = e3.visible_ten_god) == null ? void 0 : t3.name) || "");
193
+ }).join(", ") + ". Day Master: " + r2 + ". How do these Ten Gods shape my destiny and what areas of life do they govern?";
194
+ }
195
+ if (e2.startsWith("pillar-")) {
196
+ var u2, d2, f2;
197
+ let n3 = parseInt(e2.replace("pillar-", ""), 10), i3 = ["Year", "Month", "Day", "Hour"], a3 = ["year", "month", "day", "hour"], o3 = i3[n3] || "Unknown", s3 = t2.chart[a3[n3]], c3 = (s3 == null || (u2 = s3.stem) == null ? void 0 : u2.name) || "?", l3 = (s3 == null || (d2 = s3.branch) == null ? void 0 : d2.name) || "?", p2 = (s3 == null || (f2 = s3.branch) == null ? void 0 : f2.animal) || "?";
198
+ return "Interpret my BaZi " + o3 + " Pillar in depth: " + c3 + " " + l3 + " (" + p2 + "). Day Master: " + r2 + ". What does this pillar reveal about my " + (n3 === 0 ? "ancestry, early influences, and social facade" : n3 === 1 ? "career, parents, and middle years" : n3 === 2 ? "core self, spouse, and inner character" : "children, ambitions, and later years") + "?";
199
+ }
200
+ return "Interpret my BaZi Four Pillars chart. Day Master: " + r2;
201
+ }
202
+ function k(e2) {
203
+ b.textContent = e2, b.classList.add("visible"), setTimeout(function() {
204
+ b.classList.remove("visible");
205
+ }, 4e3);
206
+ }
207
+ function A(e2) {
208
+ v.hidden = true, y.hidden = false, y.innerHTML = '<div class="error-state"><span class="error-icon">\u26A0\uFE0F</span><p>' + e2 + "</p></div>";
209
+ }
210
+ document.readyState === "loading" ? document.addEventListener("DOMContentLoaded", S) : S();
211
+ </script>
212
+ </body>
213
+ </html>