@roxyapi/ui 0.9.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (378) hide show
  1. package/AGENTS.md +53 -27
  2. package/README.md +42 -12
  3. package/components-catalog.json +1022 -0
  4. package/dist/cdn/components/angel-number-card.js +52 -0
  5. package/dist/cdn/components/angel-number-card.js.map +7 -0
  6. package/dist/cdn/components/angel-number-lookup.js +52 -0
  7. package/dist/cdn/components/angel-number-lookup.js.map +7 -0
  8. package/dist/cdn/components/ashtakavarga-grid.js +10 -3
  9. package/dist/cdn/components/ashtakavarga-grid.js.map +4 -4
  10. package/dist/cdn/components/aspects-table.js +52 -0
  11. package/dist/cdn/components/aspects-table.js.map +7 -0
  12. package/dist/cdn/components/biorhythm-chart.js +10 -3
  13. package/dist/cdn/components/biorhythm-chart.js.map +4 -4
  14. package/dist/cdn/components/bodygraph.js +17 -10
  15. package/dist/cdn/components/bodygraph.js.map +4 -4
  16. package/dist/cdn/components/choghadiya-grid.js +10 -3
  17. package/dist/cdn/components/choghadiya-grid.js.map +4 -4
  18. package/dist/cdn/components/compatibility-card.js +10 -3
  19. package/dist/cdn/components/compatibility-card.js.map +4 -4
  20. package/dist/cdn/components/crystal-card.js +52 -0
  21. package/dist/cdn/components/crystal-card.js.map +7 -0
  22. package/dist/cdn/components/crystal-grid.js +52 -0
  23. package/dist/cdn/components/crystal-grid.js.map +7 -0
  24. package/dist/cdn/components/dasha-timeline.js +10 -3
  25. package/dist/cdn/components/dasha-timeline.js.map +4 -4
  26. package/dist/cdn/components/data.js +10 -3
  27. package/dist/cdn/components/data.js.map +4 -4
  28. package/dist/cdn/components/divisional-chart.js +31 -24
  29. package/dist/cdn/components/divisional-chart.js.map +4 -4
  30. package/dist/cdn/components/dosha-card.js +10 -3
  31. package/dist/cdn/components/dosha-card.js.map +4 -4
  32. package/dist/cdn/components/dream-card.js +52 -0
  33. package/dist/cdn/components/dream-card.js.map +7 -0
  34. package/dist/cdn/components/dream-search.js +52 -0
  35. package/dist/cdn/components/dream-search.js.map +7 -0
  36. package/dist/cdn/components/endpoint-form.js +3 -3
  37. package/dist/cdn/components/endpoint-form.js.map +3 -3
  38. package/dist/cdn/components/forecast-digest.js +52 -0
  39. package/dist/cdn/components/forecast-digest.js.map +7 -0
  40. package/dist/cdn/components/forecast-timeline.js +10 -3
  41. package/dist/cdn/components/forecast-timeline.js.map +4 -4
  42. package/dist/cdn/components/guna-milan.js +10 -3
  43. package/dist/cdn/components/guna-milan.js.map +4 -4
  44. package/dist/cdn/components/hd-connection.js +52 -0
  45. package/dist/cdn/components/hd-connection.js.map +7 -0
  46. package/dist/cdn/components/hd-penta.js +52 -0
  47. package/dist/cdn/components/hd-penta.js.map +7 -0
  48. package/dist/cdn/components/hd-variables.js +52 -0
  49. package/dist/cdn/components/hd-variables.js.map +7 -0
  50. package/dist/cdn/components/hexagram.js +10 -3
  51. package/dist/cdn/components/hexagram.js.map +4 -4
  52. package/dist/cdn/components/hora-table.js +52 -0
  53. package/dist/cdn/components/hora-table.js.map +7 -0
  54. package/dist/cdn/components/horoscope-card.js +10 -3
  55. package/dist/cdn/components/horoscope-card.js.map +4 -4
  56. package/dist/cdn/components/kp-chart.js +10 -3
  57. package/dist/cdn/components/kp-chart.js.map +4 -4
  58. package/dist/cdn/components/kp-planets-table.js +10 -3
  59. package/dist/cdn/components/kp-planets-table.js.map +4 -4
  60. package/dist/cdn/components/kp-ruling-planets.js +10 -3
  61. package/dist/cdn/components/kp-ruling-planets.js.map +4 -4
  62. package/dist/cdn/components/location-search.js +3 -3
  63. package/dist/cdn/components/location-search.js.map +2 -2
  64. package/dist/cdn/components/moon-phase.js +10 -3
  65. package/dist/cdn/components/moon-phase.js.map +4 -4
  66. package/dist/cdn/components/nakshatra-card.js +10 -3
  67. package/dist/cdn/components/nakshatra-card.js.map +4 -4
  68. package/dist/cdn/components/natal-chart.js +16 -9
  69. package/dist/cdn/components/natal-chart.js.map +4 -4
  70. package/dist/cdn/components/numerology-card.js +10 -3
  71. package/dist/cdn/components/numerology-card.js.map +4 -4
  72. package/dist/cdn/components/panchang-table.js +10 -3
  73. package/dist/cdn/components/panchang-table.js.map +4 -4
  74. package/dist/cdn/components/reference-card.js +52 -0
  75. package/dist/cdn/components/reference-card.js.map +7 -0
  76. package/dist/cdn/components/shadbala-table.js +10 -3
  77. package/dist/cdn/components/shadbala-table.js.map +4 -4
  78. package/dist/cdn/components/synastry-chart.js +16 -9
  79. package/dist/cdn/components/synastry-chart.js.map +4 -4
  80. package/dist/cdn/components/tarot-card.js +10 -3
  81. package/dist/cdn/components/tarot-card.js.map +4 -4
  82. package/dist/cdn/components/tarot-catalog.js +52 -0
  83. package/dist/cdn/components/tarot-catalog.js.map +7 -0
  84. package/dist/cdn/components/tarot-spread.js +10 -3
  85. package/dist/cdn/components/tarot-spread.js.map +4 -4
  86. package/dist/cdn/components/transits-table.js +10 -3
  87. package/dist/cdn/components/transits-table.js.map +4 -4
  88. package/dist/cdn/components/vedic-aspects.js +52 -0
  89. package/dist/cdn/components/vedic-aspects.js.map +7 -0
  90. package/dist/cdn/components/vedic-kundli.js +31 -24
  91. package/dist/cdn/components/vedic-kundli.js.map +4 -4
  92. package/dist/cdn/components/vedic-planets-table.js +10 -3
  93. package/dist/cdn/components/vedic-planets-table.js.map +4 -4
  94. package/dist/cdn/components/western-planets-table.js +10 -3
  95. package/dist/cdn/components/western-planets-table.js.map +4 -4
  96. package/dist/cdn/components/yoga-list.js +10 -3
  97. package/dist/cdn/components/yoga-list.js.map +4 -4
  98. package/dist/cdn/roxy-ui.js +92 -81
  99. package/dist/cdn/roxy-ui.js.map +4 -4
  100. package/dist/components/angel-number-card.d.ts +17 -0
  101. package/dist/components/angel-number-card.d.ts.map +1 -0
  102. package/dist/components/angel-number-card.js +2 -0
  103. package/dist/components/angel-number-card.js.map +7 -0
  104. package/dist/components/angel-number-lookup.d.ts +21 -0
  105. package/dist/components/angel-number-lookup.d.ts.map +1 -0
  106. package/dist/components/angel-number-lookup.js +2 -0
  107. package/dist/components/angel-number-lookup.js.map +7 -0
  108. package/dist/components/ashtakavarga-grid.d.ts +4 -5
  109. package/dist/components/ashtakavarga-grid.d.ts.map +1 -1
  110. package/dist/components/ashtakavarga-grid.js +1 -1
  111. package/dist/components/ashtakavarga-grid.js.map +4 -4
  112. package/dist/components/aspects-table.d.ts +23 -0
  113. package/dist/components/aspects-table.d.ts.map +1 -0
  114. package/dist/components/aspects-table.js +2 -0
  115. package/dist/components/aspects-table.js.map +7 -0
  116. package/dist/components/biorhythm-chart.d.ts +4 -5
  117. package/dist/components/biorhythm-chart.d.ts.map +1 -1
  118. package/dist/components/biorhythm-chart.js +1 -1
  119. package/dist/components/biorhythm-chart.js.map +4 -4
  120. package/dist/components/bodygraph.d.ts +4 -5
  121. package/dist/components/bodygraph.d.ts.map +1 -1
  122. package/dist/components/bodygraph.js +9 -9
  123. package/dist/components/bodygraph.js.map +4 -4
  124. package/dist/components/choghadiya-grid.d.ts +4 -5
  125. package/dist/components/choghadiya-grid.d.ts.map +1 -1
  126. package/dist/components/choghadiya-grid.js +1 -1
  127. package/dist/components/choghadiya-grid.js.map +4 -4
  128. package/dist/components/compatibility-card.d.ts +4 -5
  129. package/dist/components/compatibility-card.d.ts.map +1 -1
  130. package/dist/components/compatibility-card.js +1 -1
  131. package/dist/components/compatibility-card.js.map +4 -4
  132. package/dist/components/crystal-card.d.ts +19 -0
  133. package/dist/components/crystal-card.d.ts.map +1 -0
  134. package/dist/components/crystal-card.js +2 -0
  135. package/dist/components/crystal-card.js.map +7 -0
  136. package/dist/components/crystal-grid.d.ts +26 -0
  137. package/dist/components/crystal-grid.d.ts.map +1 -0
  138. package/dist/components/crystal-grid.js +2 -0
  139. package/dist/components/crystal-grid.js.map +7 -0
  140. package/dist/components/dasha-timeline.d.ts +4 -5
  141. package/dist/components/dasha-timeline.d.ts.map +1 -1
  142. package/dist/components/dasha-timeline.js +1 -1
  143. package/dist/components/dasha-timeline.js.map +4 -4
  144. package/dist/components/data.d.ts +5 -8
  145. package/dist/components/data.d.ts.map +1 -1
  146. package/dist/components/data.js +1 -1
  147. package/dist/components/data.js.map +4 -4
  148. package/dist/components/divisional-chart.d.ts +4 -5
  149. package/dist/components/divisional-chart.d.ts.map +1 -1
  150. package/dist/components/divisional-chart.js +59 -59
  151. package/dist/components/divisional-chart.js.map +4 -4
  152. package/dist/components/dosha-card.d.ts +4 -5
  153. package/dist/components/dosha-card.d.ts.map +1 -1
  154. package/dist/components/dosha-card.js +1 -1
  155. package/dist/components/dosha-card.js.map +4 -4
  156. package/dist/components/dream-card.d.ts +16 -0
  157. package/dist/components/dream-card.d.ts.map +1 -0
  158. package/dist/components/dream-card.js +2 -0
  159. package/dist/components/dream-card.js.map +7 -0
  160. package/dist/components/dream-search.d.ts +18 -0
  161. package/dist/components/dream-search.d.ts.map +1 -0
  162. package/dist/components/dream-search.js +2 -0
  163. package/dist/components/dream-search.js.map +7 -0
  164. package/dist/components/endpoint-form.d.ts +10 -5
  165. package/dist/components/endpoint-form.d.ts.map +1 -1
  166. package/dist/components/endpoint-form.js +1 -1
  167. package/dist/components/endpoint-form.js.map +3 -3
  168. package/dist/components/forecast-digest.d.ts +19 -0
  169. package/dist/components/forecast-digest.d.ts.map +1 -0
  170. package/dist/components/forecast-digest.js +2 -0
  171. package/dist/components/forecast-digest.js.map +7 -0
  172. package/dist/components/forecast-timeline.d.ts +8 -6
  173. package/dist/components/forecast-timeline.d.ts.map +1 -1
  174. package/dist/components/forecast-timeline.js +1 -1
  175. package/dist/components/forecast-timeline.js.map +4 -4
  176. package/dist/components/guna-milan.d.ts +4 -5
  177. package/dist/components/guna-milan.d.ts.map +1 -1
  178. package/dist/components/guna-milan.js +1 -1
  179. package/dist/components/guna-milan.js.map +4 -4
  180. package/dist/components/hd-connection.d.ts +18 -0
  181. package/dist/components/hd-connection.d.ts.map +1 -0
  182. package/dist/components/hd-connection.js +2 -0
  183. package/dist/components/hd-connection.js.map +7 -0
  184. package/dist/components/hd-penta.d.ts +18 -0
  185. package/dist/components/hd-penta.d.ts.map +1 -0
  186. package/dist/components/hd-penta.js +2 -0
  187. package/dist/components/hd-penta.js.map +7 -0
  188. package/dist/components/hd-variables.d.ts +17 -0
  189. package/dist/components/hd-variables.d.ts.map +1 -0
  190. package/dist/components/hd-variables.js +2 -0
  191. package/dist/components/hd-variables.js.map +7 -0
  192. package/dist/components/hexagram.d.ts +4 -5
  193. package/dist/components/hexagram.d.ts.map +1 -1
  194. package/dist/components/hexagram.js +1 -1
  195. package/dist/components/hexagram.js.map +4 -4
  196. package/dist/components/hora-table.d.ts +17 -0
  197. package/dist/components/hora-table.d.ts.map +1 -0
  198. package/dist/components/hora-table.js +2 -0
  199. package/dist/components/hora-table.js.map +7 -0
  200. package/dist/components/horoscope-card.d.ts +4 -5
  201. package/dist/components/horoscope-card.d.ts.map +1 -1
  202. package/dist/components/horoscope-card.js +1 -1
  203. package/dist/components/horoscope-card.js.map +4 -4
  204. package/dist/components/kp-chart.d.ts +4 -5
  205. package/dist/components/kp-chart.d.ts.map +1 -1
  206. package/dist/components/kp-chart.js +1 -1
  207. package/dist/components/kp-chart.js.map +4 -4
  208. package/dist/components/kp-planets-table.d.ts +4 -5
  209. package/dist/components/kp-planets-table.d.ts.map +1 -1
  210. package/dist/components/kp-planets-table.js +1 -1
  211. package/dist/components/kp-planets-table.js.map +4 -4
  212. package/dist/components/kp-ruling-planets.d.ts +4 -5
  213. package/dist/components/kp-ruling-planets.d.ts.map +1 -1
  214. package/dist/components/kp-ruling-planets.js +1 -1
  215. package/dist/components/kp-ruling-planets.js.map +4 -4
  216. package/dist/components/location-search.js +1 -1
  217. package/dist/components/location-search.js.map +2 -2
  218. package/dist/components/moon-phase.d.ts +5 -5
  219. package/dist/components/moon-phase.d.ts.map +1 -1
  220. package/dist/components/moon-phase.js +1 -1
  221. package/dist/components/moon-phase.js.map +4 -4
  222. package/dist/components/nakshatra-card.d.ts +4 -5
  223. package/dist/components/nakshatra-card.d.ts.map +1 -1
  224. package/dist/components/nakshatra-card.js +1 -1
  225. package/dist/components/nakshatra-card.js.map +4 -4
  226. package/dist/components/natal-chart.d.ts +4 -5
  227. package/dist/components/natal-chart.d.ts.map +1 -1
  228. package/dist/components/natal-chart.js +8 -8
  229. package/dist/components/natal-chart.js.map +4 -4
  230. package/dist/components/numerology-card.d.ts +15 -10
  231. package/dist/components/numerology-card.d.ts.map +1 -1
  232. package/dist/components/numerology-card.js +1 -1
  233. package/dist/components/numerology-card.js.map +4 -4
  234. package/dist/components/panchang-table.d.ts +4 -5
  235. package/dist/components/panchang-table.d.ts.map +1 -1
  236. package/dist/components/panchang-table.js +1 -1
  237. package/dist/components/panchang-table.js.map +4 -4
  238. package/dist/components/reference-card.d.ts +19 -0
  239. package/dist/components/reference-card.d.ts.map +1 -0
  240. package/dist/components/reference-card.js +2 -0
  241. package/dist/components/reference-card.js.map +7 -0
  242. package/dist/components/shadbala-table.d.ts +4 -5
  243. package/dist/components/shadbala-table.d.ts.map +1 -1
  244. package/dist/components/shadbala-table.js +1 -1
  245. package/dist/components/shadbala-table.js.map +4 -4
  246. package/dist/components/synastry-chart.d.ts +4 -5
  247. package/dist/components/synastry-chart.d.ts.map +1 -1
  248. package/dist/components/synastry-chart.js +7 -7
  249. package/dist/components/synastry-chart.js.map +4 -4
  250. package/dist/components/tarot-card.d.ts +4 -5
  251. package/dist/components/tarot-card.d.ts.map +1 -1
  252. package/dist/components/tarot-card.js +1 -1
  253. package/dist/components/tarot-card.js.map +4 -4
  254. package/dist/components/tarot-catalog.d.ts +20 -0
  255. package/dist/components/tarot-catalog.d.ts.map +1 -0
  256. package/dist/components/tarot-catalog.js +2 -0
  257. package/dist/components/tarot-catalog.js.map +7 -0
  258. package/dist/components/tarot-spread.d.ts +7 -8
  259. package/dist/components/tarot-spread.d.ts.map +1 -1
  260. package/dist/components/tarot-spread.js +1 -1
  261. package/dist/components/tarot-spread.js.map +4 -4
  262. package/dist/components/transits-table.d.ts +4 -5
  263. package/dist/components/transits-table.d.ts.map +1 -1
  264. package/dist/components/transits-table.js +1 -1
  265. package/dist/components/transits-table.js.map +4 -4
  266. package/dist/components/vedic-aspects.d.ts +16 -0
  267. package/dist/components/vedic-aspects.d.ts.map +1 -0
  268. package/dist/components/vedic-aspects.js +2 -0
  269. package/dist/components/vedic-aspects.js.map +7 -0
  270. package/dist/components/vedic-kundli.d.ts +22 -5
  271. package/dist/components/vedic-kundli.d.ts.map +1 -1
  272. package/dist/components/vedic-kundli.js +63 -63
  273. package/dist/components/vedic-kundli.js.map +4 -4
  274. package/dist/components/vedic-planets-table.d.ts +4 -5
  275. package/dist/components/vedic-planets-table.d.ts.map +1 -1
  276. package/dist/components/vedic-planets-table.js +1 -1
  277. package/dist/components/vedic-planets-table.js.map +4 -4
  278. package/dist/components/western-planets-table.d.ts +4 -5
  279. package/dist/components/western-planets-table.d.ts.map +1 -1
  280. package/dist/components/western-planets-table.js +1 -1
  281. package/dist/components/western-planets-table.js.map +4 -4
  282. package/dist/components/yoga-list.d.ts +6 -7
  283. package/dist/components/yoga-list.d.ts.map +1 -1
  284. package/dist/components/yoga-list.js +1 -1
  285. package/dist/components/yoga-list.js.map +4 -4
  286. package/dist/generated/endpoint-bindings.d.ts +15 -0
  287. package/dist/generated/endpoint-bindings.d.ts.map +1 -0
  288. package/dist/index.cjs +73 -73
  289. package/dist/index.cjs.map +4 -4
  290. package/dist/index.d.ts +16 -0
  291. package/dist/index.d.ts.map +1 -1
  292. package/dist/index.js +71 -71
  293. package/dist/index.js.map +4 -4
  294. package/dist/manifest.d.ts.map +1 -1
  295. package/dist/manifest.json +39 -24
  296. package/dist/styles/tokens-css.d.ts +1 -1
  297. package/dist/styles/tokens-css.d.ts.map +1 -1
  298. package/dist/styles/tokens.css +4 -0
  299. package/dist/types/index.d.ts +1 -1
  300. package/dist/types/index.d.ts.map +1 -1
  301. package/dist/types/types.gen.d.ts +1103 -164
  302. package/dist/types/types.gen.d.ts.map +1 -1
  303. package/dist/utils/angel-sections.d.ts +14 -0
  304. package/dist/utils/angel-sections.d.ts.map +1 -0
  305. package/dist/utils/base-element.d.ts +73 -0
  306. package/dist/utils/base-element.d.ts.map +1 -0
  307. package/dist/utils/base-styles.d.ts.map +1 -1
  308. package/dist/utils/fetch-controller.d.ts +60 -0
  309. package/dist/utils/fetch-controller.d.ts.map +1 -0
  310. package/dist/utils/kundli-render.d.ts +2 -1
  311. package/dist/utils/kundli-render.d.ts.map +1 -1
  312. package/dist/utils/kundli-styles.d.ts.map +1 -1
  313. package/dist/utils/markup-data.d.ts +34 -0
  314. package/dist/utils/markup-data.d.ts.map +1 -1
  315. package/dist/version.d.ts +1 -1
  316. package/dist/version.d.ts.map +1 -1
  317. package/package.json +2 -1
  318. package/src/components/angel-number-card.ts +210 -0
  319. package/src/components/angel-number-lookup.ts +207 -0
  320. package/src/components/ashtakavarga-grid.ts +15 -20
  321. package/src/components/aspects-table.ts +329 -0
  322. package/src/components/biorhythm-chart.ts +14 -18
  323. package/src/components/bodygraph.ts +9 -20
  324. package/src/components/choghadiya-grid.ts +15 -19
  325. package/src/components/compatibility-card.ts +9 -19
  326. package/src/components/crystal-card.ts +242 -0
  327. package/src/components/crystal-grid.ts +182 -0
  328. package/src/components/dasha-timeline.ts +9 -20
  329. package/src/components/data.ts +8 -27
  330. package/src/components/divisional-chart.ts +10 -18
  331. package/src/components/dosha-card.ts +8 -19
  332. package/src/components/dream-card.ts +88 -0
  333. package/src/components/dream-search.ts +135 -0
  334. package/src/components/endpoint-form.ts +149 -55
  335. package/src/components/forecast-digest.ts +213 -0
  336. package/src/components/forecast-timeline.ts +24 -19
  337. package/src/components/guna-milan.ts +8 -19
  338. package/src/components/hd-connection.ts +188 -0
  339. package/src/components/hd-penta.ts +165 -0
  340. package/src/components/hd-variables.ts +128 -0
  341. package/src/components/hexagram.ts +10 -18
  342. package/src/components/hora-table.ts +149 -0
  343. package/src/components/horoscope-card.ts +9 -19
  344. package/src/components/kp-chart.ts +11 -20
  345. package/src/components/kp-planets-table.ts +11 -20
  346. package/src/components/kp-ruling-planets.ts +8 -18
  347. package/src/components/moon-phase.ts +10 -19
  348. package/src/components/nakshatra-card.ts +11 -20
  349. package/src/components/natal-chart.ts +20 -23
  350. package/src/components/numerology-card.ts +90 -31
  351. package/src/components/panchang-table.ts +9 -19
  352. package/src/components/reference-card.ts +212 -0
  353. package/src/components/shadbala-table.ts +15 -18
  354. package/src/components/synastry-chart.ts +17 -20
  355. package/src/components/tarot-card.ts +9 -20
  356. package/src/components/tarot-catalog.ts +129 -0
  357. package/src/components/tarot-spread.ts +20 -21
  358. package/src/components/transits-table.ts +17 -20
  359. package/src/components/vedic-aspects.ts +188 -0
  360. package/src/components/vedic-kundli.ts +46 -19
  361. package/src/components/vedic-planets-table.ts +11 -19
  362. package/src/components/western-planets-table.ts +11 -19
  363. package/src/components/yoga-list.ts +17 -23
  364. package/src/generated/endpoint-bindings.ts +655 -0
  365. package/src/index.ts +27 -0
  366. package/src/manifest.ts +198 -6
  367. package/src/styles/tokens-css.ts +4 -0
  368. package/src/styles/tokens.css +4 -0
  369. package/src/types/index.ts +1 -1
  370. package/src/types/types.gen.ts +1123 -164
  371. package/src/utils/angel-sections.ts +38 -0
  372. package/src/utils/base-element.ts +183 -0
  373. package/src/utils/base-styles.ts +33 -0
  374. package/src/utils/fetch-controller.ts +166 -0
  375. package/src/utils/kundli-render.ts +9 -2
  376. package/src/utils/kundli-styles.ts +7 -1
  377. package/src/utils/markup-data.ts +45 -0
  378. package/src/version.ts +1 -1
@@ -0,0 +1,188 @@
1
+ import { css, html, nothing } from 'lit';
2
+ import { customElement } from 'lit/decorators.js';
3
+ import type { CalculateConnectionResponse } from '../types/index.js';
4
+ import { RoxyDataElement } from '../utils/base-element.js';
5
+ import { baseStyles } from '../utils/base-styles.js';
6
+ import { humanize } from '../utils/string.js';
7
+
8
+ /**
9
+ * Human Design connection chart. Renders /human-design/connection: the composite of two charts as the electromagnetic / compromise / dominance channels they form together, plus the combined definition and a summary. The HD analog of synastry. Each channel row shows its two gates, name, circuit, the relationship dynamic, and which person carries which gate.
10
+ */
11
+ @customElement('roxy-hd-connection')
12
+ export class RoxyHdConnection extends RoxyDataElement<CalculateConnectionResponse> {
13
+ static styles = [
14
+ baseStyles,
15
+ css`
16
+ .wrap {
17
+ background: var(--roxy-surface, #fff);
18
+ color: var(--roxy-fg, #0a0a0a);
19
+ border: 1px solid var(--roxy-border, #e4e4e7);
20
+ border-radius: var(--roxy-radius-md, 8px);
21
+ padding: var(--roxy-space-lg, 1.5rem);
22
+ box-shadow: var(--roxy-shadow-sm);
23
+ display: grid;
24
+ gap: var(--roxy-space-md, 1rem);
25
+ }
26
+ .head {
27
+ display: flex;
28
+ align-items: baseline;
29
+ justify-content: space-between;
30
+ flex-wrap: wrap;
31
+ gap: var(--roxy-space-sm, 0.5rem);
32
+ }
33
+ .title {
34
+ margin: 0;
35
+ font-size: var(--roxy-text-lg, 1.125rem);
36
+ font-weight: var(--roxy-weight-bold, 600);
37
+ }
38
+ .count {
39
+ color: var(--roxy-accent-ink, #b45309);
40
+ font-size: var(--roxy-text-sm, 0.875rem);
41
+ font-weight: var(--roxy-weight-bold, 600);
42
+ font-variant-numeric: tabular-nums;
43
+ }
44
+ .def {
45
+ font-size: var(--roxy-text-sm, 0.875rem);
46
+ color: var(--roxy-muted, #71717a);
47
+ }
48
+ .def strong {
49
+ color: var(--roxy-fg, #0a0a0a);
50
+ text-transform: capitalize;
51
+ }
52
+ .stats {
53
+ display: flex;
54
+ flex-wrap: wrap;
55
+ gap: var(--roxy-space-sm, 0.5rem);
56
+ }
57
+ .stat {
58
+ display: inline-flex;
59
+ align-items: baseline;
60
+ gap: 0.35rem;
61
+ padding: 2px 10px;
62
+ border-radius: var(--roxy-radius-full, 9999px);
63
+ background: color-mix(in srgb, var(--roxy-accent, #f59e0b) 12%, transparent);
64
+ font-size: var(--roxy-text-xs, 0.75rem);
65
+ color: var(--roxy-fg, #0a0a0a);
66
+ }
67
+ .stat b {
68
+ color: var(--roxy-fg, #0a0a0a);
69
+ font-variant-numeric: tabular-nums;
70
+ }
71
+ table {
72
+ width: 100%;
73
+ border-collapse: collapse;
74
+ font-size: var(--roxy-text-sm, 0.875rem);
75
+ }
76
+ th,
77
+ td {
78
+ text-align: left;
79
+ padding: var(--roxy-space-sm, 0.5rem);
80
+ border-bottom: 1px solid var(--roxy-border, #e4e4e7);
81
+ white-space: nowrap;
82
+ }
83
+ th {
84
+ color: var(--roxy-muted, #71717a);
85
+ font-weight: var(--roxy-weight-bold, 600);
86
+ text-transform: uppercase;
87
+ font-size: var(--roxy-text-xs, 0.75rem);
88
+ letter-spacing: 0.04em;
89
+ }
90
+ tbody tr:last-child td {
91
+ border-bottom: none;
92
+ }
93
+ .gates {
94
+ font-variant-numeric: tabular-nums;
95
+ color: var(--roxy-accent-ink, #b45309);
96
+ font-weight: var(--roxy-weight-bold, 600);
97
+ }
98
+ .dyn {
99
+ display: inline-block;
100
+ padding: 1px 8px;
101
+ border-radius: var(--roxy-radius-full, 9999px);
102
+ font-size: var(--roxy-text-xs, 0.75rem);
103
+ background: color-mix(in srgb, var(--roxy-accent, #f59e0b) 16%, transparent);
104
+ color: var(--roxy-fg, #0a0a0a);
105
+ }
106
+ .who {
107
+ color: var(--roxy-muted, #71717a);
108
+ font-size: var(--roxy-text-xs, 0.75rem);
109
+ }
110
+ .scroll {
111
+ overflow-x: auto;
112
+ }
113
+ `,
114
+ ];
115
+
116
+ protected renderData(d: CalculateConnectionResponse) {
117
+ const channels = d.channels ?? [];
118
+ return html`<div class="wrap" aria-label="Human Design connection">
119
+ <header class="head">
120
+ <h2 class="title">Connection</h2>
121
+ ${typeof d.totalChannels === 'number' ? html`<span class="count">${d.totalChannels} channels</span>` : nothing}
122
+ </header>
123
+ ${d.combinedDefinition ? html`<p class="def">Combined definition: <strong>${humanize(String(d.combinedDefinition))}</strong></p>` : nothing}
124
+ ${this.renderSummary(d.summary)}
125
+ ${
126
+ channels.length > 0
127
+ ? html`<div class="scroll">
128
+ <table role="table" aria-label="Connection channels">
129
+ <thead>
130
+ <tr>
131
+ <th scope="col">Channel</th>
132
+ <th scope="col">Gates</th>
133
+ <th scope="col">Circuit</th>
134
+ <th scope="col">Dynamic</th>
135
+ <th scope="col">Held by</th>
136
+ </tr>
137
+ </thead>
138
+ <tbody>
139
+ ${channels.map((c) => this.renderChannel(c))}
140
+ </tbody>
141
+ </table>
142
+ </div>`
143
+ : nothing
144
+ }
145
+ </div>`;
146
+ }
147
+
148
+ private renderSummary(s: CalculateConnectionResponse['summary'] | undefined) {
149
+ if (!s) return nothing;
150
+ // The four ways two charts meet in a channel, in canonical HD order.
151
+ const rows: Array<[string, number | undefined]> = [
152
+ ['Electromagnetic', s.electromagnetic],
153
+ ['Dominance', s.dominance],
154
+ ['Compromise', s.compromise],
155
+ ['Companionship', s.companionship],
156
+ ];
157
+ return html`<div class="stats" aria-label="Channel dynamics">
158
+ ${rows.map(([label, n]) => (typeof n === 'number' ? html`<span class="stat">${label} <b>${n}</b></span>` : nothing))}
159
+ </div>`;
160
+ }
161
+
162
+ private renderChannel(
163
+ c: NonNullable<CalculateConnectionResponse['channels']>[number],
164
+ ) {
165
+ const a = c.personAGates ?? [];
166
+ const b = c.personBGates ?? [];
167
+ const held =
168
+ [a.length ? 'A' : '', b.length ? 'B' : ''].filter(Boolean).join(' + ') ||
169
+ '-';
170
+ return html`<tr>
171
+ <td>${c.name ?? ''}</td>
172
+ <td class="gates">${c.gateA}-${c.gateB}</td>
173
+ <td>${c.circuit ?? ''}</td>
174
+ <td>${c.dynamic ? html`<span class="dyn">${c.dynamic}</span>` : ''}</td>
175
+ <td class="who">${held}</td>
176
+ </tr>`;
177
+ }
178
+
179
+ protected renderEmpty() {
180
+ return html`<div class="roxy-empty" role="status">No connection data</div>`;
181
+ }
182
+ }
183
+
184
+ declare global {
185
+ interface HTMLElementTagNameMap {
186
+ 'roxy-hd-connection': RoxyHdConnection;
187
+ }
188
+ }
@@ -0,0 +1,165 @@
1
+ import { css, html, nothing } from 'lit';
2
+ import { customElement } from 'lit/decorators.js';
3
+ import type { CalculatePentaResponse } from '../types/index.js';
4
+ import { RoxyDataElement } from '../utils/base-element.js';
5
+ import { baseStyles } from '../utils/base-styles.js';
6
+
7
+ /**
8
+ * Human Design penta. Renders /human-design/penta: the group field (3 to 5 people) as the penta channels they form, split into the upper (direction) and lower (execution) triangles, with each channel marked defined or open and core or not, and which members hold each gate. The team/business chart.
9
+ */
10
+ @customElement('roxy-hd-penta')
11
+ export class RoxyHdPenta extends RoxyDataElement<CalculatePentaResponse> {
12
+ static styles = [
13
+ baseStyles,
14
+ css`
15
+ .wrap {
16
+ background: var(--roxy-surface, #fff);
17
+ color: var(--roxy-fg, #0a0a0a);
18
+ border: 1px solid var(--roxy-border, #e4e4e7);
19
+ border-radius: var(--roxy-radius-md, 8px);
20
+ padding: var(--roxy-space-lg, 1.5rem);
21
+ box-shadow: var(--roxy-shadow-sm);
22
+ display: grid;
23
+ gap: var(--roxy-space-md, 1rem);
24
+ }
25
+ .head {
26
+ display: flex;
27
+ align-items: baseline;
28
+ justify-content: space-between;
29
+ flex-wrap: wrap;
30
+ gap: var(--roxy-space-sm, 0.5rem);
31
+ }
32
+ .title {
33
+ margin: 0;
34
+ font-size: var(--roxy-text-lg, 1.125rem);
35
+ font-weight: var(--roxy-weight-bold, 600);
36
+ }
37
+ .count {
38
+ color: var(--roxy-accent-ink, #b45309);
39
+ font-size: var(--roxy-text-sm, 0.875rem);
40
+ font-weight: var(--roxy-weight-bold, 600);
41
+ }
42
+ .stats {
43
+ display: flex;
44
+ flex-wrap: wrap;
45
+ gap: var(--roxy-space-sm, 0.5rem);
46
+ }
47
+ .stat {
48
+ display: inline-flex;
49
+ align-items: baseline;
50
+ gap: 0.35rem;
51
+ padding: 2px 10px;
52
+ border-radius: var(--roxy-radius-full, 9999px);
53
+ background: color-mix(in srgb, var(--roxy-accent, #f59e0b) 12%, transparent);
54
+ font-size: var(--roxy-text-xs, 0.75rem);
55
+ color: var(--roxy-fg, #0a0a0a);
56
+ }
57
+ .stat b {
58
+ color: var(--roxy-fg, #0a0a0a);
59
+ font-variant-numeric: tabular-nums;
60
+ }
61
+ .section h3 {
62
+ margin: 0 0 var(--roxy-space-xs, 0.25rem);
63
+ font-size: var(--roxy-text-xs, 0.75rem);
64
+ color: var(--roxy-muted, #71717a);
65
+ text-transform: uppercase;
66
+ letter-spacing: 0.06em;
67
+ }
68
+ .row {
69
+ display: flex;
70
+ align-items: center;
71
+ gap: var(--roxy-space-sm, 0.5rem);
72
+ padding: var(--roxy-space-sm, 0.5rem) 0;
73
+ border-bottom: 1px solid var(--roxy-border, #e4e4e7);
74
+ font-size: var(--roxy-text-sm, 0.875rem);
75
+ flex-wrap: wrap;
76
+ }
77
+ .row:last-child {
78
+ border-bottom: none;
79
+ }
80
+ .gates {
81
+ font-variant-numeric: tabular-nums;
82
+ color: var(--roxy-accent-ink, #b45309);
83
+ font-weight: var(--roxy-weight-bold, 600);
84
+ min-width: 3.5rem;
85
+ }
86
+ .cname {
87
+ flex: 1;
88
+ min-width: 8rem;
89
+ }
90
+ .badge {
91
+ display: inline-flex;
92
+ padding: 1px 8px;
93
+ border-radius: var(--roxy-radius-full, 9999px);
94
+ font-size: var(--roxy-text-xs, 0.75rem);
95
+ font-weight: var(--roxy-weight-bold, 600);
96
+ }
97
+ .badge.defined {
98
+ background: color-mix(in srgb, var(--roxy-success, #16a34a) 16%, transparent);
99
+ color: var(--roxy-success-fg, #166534);
100
+ }
101
+ .badge.open {
102
+ background: color-mix(in srgb, var(--roxy-border, #e4e4e7) 45%, transparent);
103
+ color: var(--roxy-fg, #0a0a0a);
104
+ }
105
+ .badge.core {
106
+ background: color-mix(in srgb, var(--roxy-accent, #f59e0b) 18%, transparent);
107
+ color: var(--roxy-fg, #0a0a0a);
108
+ }
109
+ `,
110
+ ];
111
+
112
+ protected renderData(d: CalculatePentaResponse) {
113
+ const channels = d.channels ?? [];
114
+ const upper = channels.filter((c) => c.position === 'upper');
115
+ const lower = channels.filter((c) => c.position === 'lower');
116
+ return html`<div class="wrap" aria-label="Human Design penta">
117
+ <header class="head">
118
+ <h2 class="title">Penta</h2>
119
+ ${typeof d.memberCount === 'number' ? html`<span class="count">${d.memberCount} members</span>` : nothing}
120
+ </header>
121
+ ${this.renderSummary(d.summary)}
122
+ ${this.renderGroup('Upper (direction)', upper)}
123
+ ${this.renderGroup('Lower (execution)', lower)}
124
+ </div>`;
125
+ }
126
+
127
+ private renderSummary(s: CalculatePentaResponse['summary'] | undefined) {
128
+ if (!s) return nothing;
129
+ const gaps = s.gapGates ?? [];
130
+ return html`<div class="stats" aria-label="Penta summary">
131
+ ${typeof s.definedChannels === 'number' ? html`<span class="stat">Defined channels <b>${s.definedChannels}</b></span>` : nothing}
132
+ ${typeof s.filledGates === 'number' ? html`<span class="stat">Filled gates <b>${s.filledGates}</b></span>` : nothing}
133
+ ${gaps.length > 0 ? html`<span class="stat">Gap gates <b>${gaps.join(', ')}</b></span>` : nothing}
134
+ ${typeof s.coreDefined === 'boolean' ? html`<span class="stat">${s.coreDefined ? 'Core defined' : 'Core open'}</span>` : nothing}
135
+ </div>`;
136
+ }
137
+
138
+ private renderGroup(
139
+ label: string,
140
+ channels: NonNullable<CalculatePentaResponse['channels']>,
141
+ ) {
142
+ if (channels.length === 0) return nothing;
143
+ return html`<div class="section">
144
+ <h3>${label}</h3>
145
+ ${channels.map(
146
+ (c) => html`<div class="row">
147
+ <span class="gates">${c.gateA}-${c.gateB}</span>
148
+ <span class="cname">${c.name ?? ''}</span>
149
+ <span class="badge ${c.defined ? 'defined' : 'open'}">${c.defined ? 'Defined' : 'Open'}</span>
150
+ ${c.isCore ? html`<span class="badge core">Core</span>` : nothing}
151
+ </div>`,
152
+ )}
153
+ </div>`;
154
+ }
155
+
156
+ protected renderEmpty() {
157
+ return html`<div class="roxy-empty" role="status">No penta data</div>`;
158
+ }
159
+ }
160
+
161
+ declare global {
162
+ interface HTMLElementTagNameMap {
163
+ 'roxy-hd-penta': RoxyHdPenta;
164
+ }
165
+ }
@@ -0,0 +1,128 @@
1
+ import { css, html, nothing } from 'lit';
2
+ import { customElement } from 'lit/decorators.js';
3
+ import type { CalculateVariablesResponse } from '../types/index.js';
4
+ import { RoxyDataElement } from '../utils/base-element.js';
5
+ import { baseStyles } from '../utils/base-styles.js';
6
+
7
+ /**
8
+ * Human Design variables (the four arrows / PHS). Renders /human-design/variables: the four transformation arrows laid out as they sit on the bodygraph head (top-left/right Determination + Motivation, bottom-left/right Environment + Perspective), each showing its left/right direction, the digestion/environment/awareness/perspective labels, and its color/tone/base. A low-confidence calculation (near a color/tone boundary) is flagged.
9
+ */
10
+ @customElement('roxy-hd-variables')
11
+ export class RoxyHdVariables extends RoxyDataElement<CalculateVariablesResponse> {
12
+ static styles = [
13
+ baseStyles,
14
+ css`
15
+ .wrap {
16
+ background: var(--roxy-surface, #fff);
17
+ color: var(--roxy-fg, #0a0a0a);
18
+ border: 1px solid var(--roxy-border, #e4e4e7);
19
+ border-radius: var(--roxy-radius-md, 8px);
20
+ padding: var(--roxy-space-lg, 1.5rem);
21
+ box-shadow: var(--roxy-shadow-sm);
22
+ display: grid;
23
+ gap: var(--roxy-space-md, 1rem);
24
+ }
25
+ .title {
26
+ margin: 0;
27
+ font-size: var(--roxy-text-lg, 1.125rem);
28
+ font-weight: var(--roxy-weight-bold, 600);
29
+ }
30
+ .grid {
31
+ display: grid;
32
+ grid-template-columns: repeat(2, 1fr);
33
+ gap: var(--roxy-space-md, 1rem);
34
+ }
35
+ .arrow {
36
+ border: 1px solid var(--roxy-border, #e4e4e7);
37
+ border-radius: var(--roxy-radius-md, 8px);
38
+ padding: var(--roxy-space-md, 1rem);
39
+ display: grid;
40
+ gap: var(--roxy-space-xs, 0.25rem);
41
+ }
42
+ .arrow-head {
43
+ display: flex;
44
+ align-items: center;
45
+ gap: var(--roxy-space-sm, 0.5rem);
46
+ }
47
+ .glyph {
48
+ font-size: 1.75rem;
49
+ line-height: 1;
50
+ color: var(--roxy-accent-ink, #b45309);
51
+ }
52
+ .name {
53
+ font-weight: var(--roxy-weight-bold, 600);
54
+ }
55
+ .layer {
56
+ font-size: var(--roxy-text-xs, 0.75rem);
57
+ color: var(--roxy-muted, #71717a);
58
+ text-transform: uppercase;
59
+ letter-spacing: 0.05em;
60
+ }
61
+ .labels {
62
+ font-size: var(--roxy-text-sm, 0.875rem);
63
+ color: var(--roxy-fg, #0a0a0a);
64
+ }
65
+ .ctb {
66
+ font-size: var(--roxy-text-xs, 0.75rem);
67
+ color: var(--roxy-muted, #71717a);
68
+ font-variant-numeric: tabular-nums;
69
+ }
70
+ .note {
71
+ font-size: var(--roxy-text-xs, 0.75rem);
72
+ color: var(--roxy-warning-fg, #9a3412);
73
+ }
74
+ @container (max-width: 28rem) {
75
+ .grid {
76
+ grid-template-columns: 1fr;
77
+ }
78
+ }
79
+ `,
80
+ ];
81
+
82
+ protected renderData(d: CalculateVariablesResponse) {
83
+ const arrows = d.arrows ?? [];
84
+ return html`<div class="wrap" aria-label="Human Design variables">
85
+ <h2 class="title">Variables</h2>
86
+ <div class="grid">${arrows.map((a) => this.renderArrow(a))}</div>
87
+ ${
88
+ d.confident === false
89
+ ? html`<p class="note" role="note">
90
+ Low confidence: a birth time near a color or tone boundary${typeof d.confidenceMarginDeg === 'number' ? ` (within ${d.confidenceMarginDeg}°)` : ''}. Verify the exact birth time.
91
+ </p>`
92
+ : nothing
93
+ }
94
+ </div>`;
95
+ }
96
+
97
+ private renderArrow(
98
+ a: NonNullable<CalculateVariablesResponse['arrows']>[number],
99
+ ) {
100
+ // A left arrow is strategic/active, a right arrow receptive/passive in HD.
101
+ const glyph = a.direction === 'left' ? '←' : '→';
102
+ return html`<div class="arrow">
103
+ <div class="arrow-head">
104
+ <span class="glyph" aria-hidden="true">${glyph}</span>
105
+ <span class="name">${a.name ?? ''}</span>
106
+ </div>
107
+ ${a.layer ? html`<span class="layer">${a.layer}</span>` : nothing}
108
+ <span class="labels">
109
+ ${[a.directionLabel, a.colorLabel].filter(Boolean).join(' · ')}
110
+ </span>
111
+ ${
112
+ typeof a.color === 'number'
113
+ ? html`<span class="ctb">Color ${a.color} · Tone ${a.tone} · Base ${a.base}</span>`
114
+ : nothing
115
+ }
116
+ </div>`;
117
+ }
118
+
119
+ protected renderEmpty() {
120
+ return html`<div class="roxy-empty" role="status">No variables data</div>`;
121
+ }
122
+ }
123
+
124
+ declare global {
125
+ interface HTMLElementTagNameMap {
126
+ 'roxy-hd-variables': RoxyHdVariables;
127
+ }
128
+ }
@@ -1,4 +1,4 @@
1
- import { css, html, LitElement, nothing, svg } from 'lit';
1
+ import { css, html, nothing, svg } from 'lit';
2
2
  import { customElement, property } from 'lit/decorators.js';
3
3
  import { TRIGRAM_GLYPH } from '../tokens/index.js';
4
4
  import type {
@@ -9,8 +9,8 @@ import type {
9
9
  Hexagram,
10
10
  LookupHexagramResponse,
11
11
  } from '../types/index.js';
12
+ import { RoxyDataElement } from '../utils/base-element.js';
12
13
  import { baseStyles } from '../utils/base-styles.js';
13
- import { MarkupDataController } from '../utils/markup-data.js';
14
14
 
15
15
  type HexagramData =
16
16
  | GetHexagramResponse
@@ -24,12 +24,12 @@ type HexagramData =
24
24
  * /iching/daily, /iching/daily/cast.
25
25
  */
26
26
  @customElement('roxy-hexagram')
27
- export class RoxyHexagram extends LitElement {
27
+ export class RoxyHexagram extends RoxyDataElement<HexagramData> {
28
28
  static styles = [
29
29
  baseStyles,
30
30
  css`
31
31
  .card {
32
- background: var(--roxy-bg, #fff);
32
+ background: var(--roxy-surface, #fff);
33
33
  border: 1px solid var(--roxy-border, #e4e4e7);
34
34
  border-radius: var(--roxy-radius-md, 8px);
35
35
  padding: var(--roxy-space-lg, 1.5rem);
@@ -137,17 +137,6 @@ export class RoxyHexagram extends LitElement {
137
137
  `,
138
138
  ];
139
139
 
140
- constructor() {
141
- super();
142
- // Enables hydrating `data` from a direct-child
143
- // <script type="application/json" class="roxy-data"> for server-rendered
144
- // and cached consumers. The JavaScript `data` property still wins.
145
- new MarkupDataController(this);
146
- }
147
-
148
- @property({ attribute: false })
149
- data: HexagramData | null = null;
150
-
151
140
  @property({ type: String, reflect: true })
152
141
  mode: 'lookup' | 'cast' | 'daily' = 'lookup';
153
142
 
@@ -179,10 +168,13 @@ export class RoxyHexagram extends LitElement {
179
168
  return { hex: d as Hexagram };
180
169
  }
181
170
 
182
- render() {
171
+ protected renderEmpty() {
172
+ return html`<div class="roxy-empty" role="status">No hexagram data</div>`;
173
+ }
174
+
175
+ protected renderData() {
183
176
  const resolved = this.resolveHexagram();
184
- if (!resolved)
185
- return html`<div class="roxy-empty" role="status">No hexagram data</div>`;
177
+ if (!resolved) return this.renderEmpty();
186
178
 
187
179
  const {
188
180
  hex: h,
@@ -0,0 +1,149 @@
1
+ import { css, html, nothing } from 'lit';
2
+ import { customElement } from 'lit/decorators.js';
3
+ import { PLANET_GLYPH } from '../tokens/index.js';
4
+ import type { GetHoraResponse } from '../types/index.js';
5
+ import { RoxyDataElement } from '../utils/base-element.js';
6
+ import { baseStyles } from '../utils/base-styles.js';
7
+ import { capitalize } from '../utils/string.js';
8
+
9
+ /** HH:MM from a tz-naive ISO local datetime, without reparsing (the times are already wall-clock in the requested timezone). */
10
+ function clockTime(iso: string | undefined): string {
11
+ if (!iso) return '';
12
+ const t = String(iso).slice(11, 16);
13
+ return t || String(iso);
14
+ }
15
+
16
+ type HoraPeriod = NonNullable<GetHoraResponse['dayHoras']>[number];
17
+
18
+ /**
19
+ * Vedic Hora (planetary hours) table. Renders /vedic-astrology/panchang/hora: the 12 daytime and 12 nighttime horas, each ruled by one of the seven classical planets in the Chaldean order, used for electional timing (start a venture in the hora of the planet that favours it). Day horas run sunrise to sunset, night horas sunset to next sunrise; each tile shows the ruling planet and its wall-clock window.
20
+ */
21
+ @customElement('roxy-hora-table')
22
+ export class RoxyHoraTable extends RoxyDataElement<GetHoraResponse> {
23
+ static styles = [
24
+ baseStyles,
25
+ css`
26
+ .wrap {
27
+ background: var(--roxy-surface, #fff);
28
+ color: var(--roxy-fg, #0a0a0a);
29
+ border: 1px solid var(--roxy-border, #e4e4e7);
30
+ border-radius: var(--roxy-radius-md, 8px);
31
+ padding: var(--roxy-space-lg, 1.5rem);
32
+ box-shadow: var(--roxy-shadow-sm);
33
+ display: grid;
34
+ gap: var(--roxy-space-md, 1rem);
35
+ }
36
+ .head {
37
+ display: flex;
38
+ justify-content: space-between;
39
+ align-items: baseline;
40
+ gap: var(--roxy-space-md, 1rem);
41
+ flex-wrap: wrap;
42
+ }
43
+ .title {
44
+ font-size: var(--roxy-text-lg, 1.125rem);
45
+ font-weight: var(--roxy-weight-bold, 600);
46
+ margin: 0;
47
+ }
48
+ .subtitle {
49
+ color: var(--roxy-muted, #71717a);
50
+ font-size: var(--roxy-text-sm, 0.875rem);
51
+ margin: 0;
52
+ }
53
+ .cols {
54
+ display: grid;
55
+ grid-template-columns: repeat(2, 1fr);
56
+ gap: var(--roxy-space-md, 1rem);
57
+ }
58
+ .section-label {
59
+ font-size: var(--roxy-text-xs, 0.75rem);
60
+ color: var(--roxy-muted, #71717a);
61
+ text-transform: uppercase;
62
+ letter-spacing: 0.06em;
63
+ font-weight: var(--roxy-weight-bold, 600);
64
+ margin: 0 0 var(--roxy-space-xs, 0.25rem) 0;
65
+ }
66
+ .row {
67
+ display: flex;
68
+ align-items: center;
69
+ gap: var(--roxy-space-sm, 0.5rem);
70
+ padding: var(--roxy-space-xs, 0.25rem) 0;
71
+ border-bottom: 1px solid var(--roxy-border, #e4e4e7);
72
+ font-size: var(--roxy-text-sm, 0.875rem);
73
+ }
74
+ .row:last-child {
75
+ border-bottom: none;
76
+ }
77
+ .glyph {
78
+ font-size: 1.15em;
79
+ line-height: 1;
80
+ color: var(--roxy-accent-ink, #b45309);
81
+ width: 1.25em;
82
+ text-align: center;
83
+ }
84
+ .planet {
85
+ flex: 1;
86
+ font-weight: 500;
87
+ }
88
+ .time {
89
+ color: var(--roxy-muted, #71717a);
90
+ font-variant-numeric: tabular-nums;
91
+ white-space: nowrap;
92
+ }
93
+ .num {
94
+ color: var(--roxy-muted, #71717a);
95
+ font-size: var(--roxy-text-xs, 0.75rem);
96
+ font-variant-numeric: tabular-nums;
97
+ width: 1.5em;
98
+ text-align: right;
99
+ }
100
+ @container (max-width: 30rem) {
101
+ .cols {
102
+ grid-template-columns: 1fr;
103
+ }
104
+ }
105
+ `,
106
+ ];
107
+
108
+ protected renderEmpty() {
109
+ return html`<div class="roxy-empty" role="status">No hora data</div>`;
110
+ }
111
+
112
+ protected renderData(d: GetHoraResponse) {
113
+ const day = d.dayHoras ?? [];
114
+ const night = d.nightHoras ?? [];
115
+ if (day.length === 0 && night.length === 0) return this.renderEmpty();
116
+
117
+ return html`<div class="wrap" aria-label="Hora periods">
118
+ <div class="head">
119
+ <h2 class="title">Hora</h2>
120
+ ${d.date ? html`<p class="subtitle">${d.date}</p>` : nothing}
121
+ </div>
122
+ <div class="cols">
123
+ ${this.renderColumn('Day', day)}
124
+ ${this.renderColumn('Night', night)}
125
+ </div>
126
+ </div>`;
127
+ }
128
+
129
+ private renderColumn(label: string, horas: HoraPeriod[]) {
130
+ if (horas.length === 0) return nothing;
131
+ return html`<div class="col">
132
+ <p class="section-label">${label}</p>
133
+ ${horas.map(
134
+ (h) => html`<div class="row">
135
+ <span class="glyph" aria-hidden="true">${PLANET_GLYPH[capitalize(h.planet ?? '')] ?? '·'}</span>
136
+ <span class="planet">${h.planet}</span>
137
+ <span class="time">${clockTime(h.start)}-${clockTime(h.end)}</span>
138
+ ${typeof h.number === 'number' ? html`<span class="num">${h.number}</span>` : nothing}
139
+ </div>`,
140
+ )}
141
+ </div>`;
142
+ }
143
+ }
144
+
145
+ declare global {
146
+ interface HTMLElementTagNameMap {
147
+ 'roxy-hora-table': RoxyHoraTable;
148
+ }
149
+ }