@roxyapi/ui 0.3.1 → 0.4.1
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.
- package/AGENTS.md +34 -7
- package/README.md +145 -26
- package/dist/cdn/components/ashtakavarga-grid.js +74 -19
- package/dist/cdn/components/ashtakavarga-grid.js.map +2 -2
- package/dist/cdn/components/biorhythm-chart.js +18 -4
- package/dist/cdn/components/biorhythm-chart.js.map +2 -2
- package/dist/cdn/components/choghadiya-grid.js +47 -12
- package/dist/cdn/components/choghadiya-grid.js.map +3 -3
- package/dist/cdn/components/compatibility-card.js +21 -7
- package/dist/cdn/components/compatibility-card.js.map +2 -2
- package/dist/cdn/components/dasha-timeline.js +113 -28
- package/dist/cdn/components/dasha-timeline.js.map +3 -3
- package/dist/cdn/components/data.js +27 -13
- package/dist/cdn/components/data.js.map +2 -2
- package/dist/cdn/components/divisional-chart.js +225 -118
- package/dist/cdn/components/divisional-chart.js.map +4 -4
- package/dist/cdn/components/dosha-card.js +18 -4
- package/dist/cdn/components/dosha-card.js.map +2 -2
- package/dist/cdn/components/endpoint-form.js +25 -11
- package/dist/cdn/components/endpoint-form.js.map +2 -2
- package/dist/cdn/components/guna-milan.js +20 -6
- package/dist/cdn/components/guna-milan.js.map +2 -2
- package/dist/cdn/components/hexagram.js +22 -8
- package/dist/cdn/components/hexagram.js.map +2 -2
- package/dist/cdn/components/horoscope-card.js +20 -6
- package/dist/cdn/components/horoscope-card.js.map +2 -2
- package/dist/cdn/components/kp-chart.js +19 -5
- package/dist/cdn/components/kp-chart.js.map +2 -2
- package/dist/cdn/components/kp-planets-table.js +17 -3
- package/dist/cdn/components/kp-planets-table.js.map +2 -2
- package/dist/cdn/components/kp-ruling-planets.js +17 -3
- package/dist/cdn/components/kp-ruling-planets.js.map +2 -2
- package/dist/cdn/components/location-search.js +18 -4
- package/dist/cdn/components/location-search.js.map +2 -2
- package/dist/cdn/components/moon-phase.js +27 -13
- package/dist/cdn/components/moon-phase.js.map +2 -2
- package/dist/cdn/components/nakshatra-card.js +16 -2
- package/dist/cdn/components/nakshatra-card.js.map +2 -2
- package/dist/cdn/components/natal-chart.js +79 -40
- package/dist/cdn/components/natal-chart.js.map +3 -3
- package/dist/cdn/components/numerology-card.js +18 -4
- package/dist/cdn/components/numerology-card.js.map +2 -2
- package/dist/cdn/components/panchang-table.js +53 -25
- package/dist/cdn/components/panchang-table.js.map +3 -3
- package/dist/cdn/components/shadbala-table.js +24 -10
- package/dist/cdn/components/shadbala-table.js.map +2 -2
- package/dist/cdn/components/synastry-chart.js +96 -48
- package/dist/cdn/components/synastry-chart.js.map +3 -3
- package/dist/cdn/components/tarot-card.js +17 -3
- package/dist/cdn/components/tarot-card.js.map +2 -2
- package/dist/cdn/components/tarot-spread.js +39 -25
- package/dist/cdn/components/tarot-spread.js.map +2 -2
- package/dist/cdn/components/transits-table.js +18 -4
- package/dist/cdn/components/transits-table.js.map +2 -2
- package/dist/cdn/components/vedic-kundli.js +215 -105
- package/dist/cdn/components/vedic-kundli.js.map +4 -4
- package/dist/cdn/components/vedic-planets-table.js +22 -8
- package/dist/cdn/components/vedic-planets-table.js.map +2 -2
- package/dist/cdn/components/western-planets-table.js +18 -4
- package/dist/cdn/components/western-planets-table.js.map +2 -2
- package/dist/cdn/components/yoga-list.js +17 -3
- package/dist/cdn/components/yoga-list.js.map +2 -2
- package/dist/cdn/roxy-ui.js +1082 -816
- package/dist/cdn/roxy-ui.js.map +4 -4
- package/dist/components/ashtakavarga-grid.d.ts +13 -1
- package/dist/components/ashtakavarga-grid.d.ts.map +1 -1
- package/dist/components/ashtakavarga-grid.js +86 -11
- package/dist/components/ashtakavarga-grid.js.map +2 -2
- package/dist/components/biorhythm-chart.js +14 -0
- package/dist/components/biorhythm-chart.js.map +2 -2
- package/dist/components/choghadiya-grid.d.ts +6 -0
- package/dist/components/choghadiya-grid.d.ts.map +1 -1
- package/dist/components/choghadiya-grid.js +50 -2
- package/dist/components/choghadiya-grid.js.map +2 -2
- package/dist/components/compatibility-card.js +14 -0
- package/dist/components/compatibility-card.js.map +2 -2
- package/dist/components/dasha-timeline.d.ts +10 -0
- package/dist/components/dasha-timeline.d.ts.map +1 -1
- package/dist/components/dasha-timeline.js +135 -4
- package/dist/components/dasha-timeline.js.map +2 -2
- package/dist/components/data.js +14 -0
- package/dist/components/data.js.map +2 -2
- package/dist/components/divisional-chart.d.ts +9 -6
- package/dist/components/divisional-chart.d.ts.map +1 -1
- package/dist/components/divisional-chart.js +546 -251
- package/dist/components/divisional-chart.js.map +4 -4
- package/dist/components/dosha-card.js +14 -0
- package/dist/components/dosha-card.js.map +2 -2
- package/dist/components/endpoint-form.js +14 -0
- package/dist/components/endpoint-form.js.map +2 -2
- package/dist/components/guna-milan.js +14 -0
- package/dist/components/guna-milan.js.map +2 -2
- package/dist/components/hexagram.js +14 -0
- package/dist/components/hexagram.js.map +2 -2
- package/dist/components/horoscope-card.js +14 -0
- package/dist/components/horoscope-card.js.map +2 -2
- package/dist/components/kp-chart.js +14 -0
- package/dist/components/kp-chart.js.map +2 -2
- package/dist/components/kp-planets-table.js +14 -0
- package/dist/components/kp-planets-table.js.map +2 -2
- package/dist/components/kp-ruling-planets.js +14 -0
- package/dist/components/kp-ruling-planets.js.map +2 -2
- package/dist/components/location-search.js +14 -0
- package/dist/components/location-search.js.map +2 -2
- package/dist/components/moon-phase.js +14 -0
- package/dist/components/moon-phase.js.map +2 -2
- package/dist/components/nakshatra-card.js +14 -0
- package/dist/components/nakshatra-card.js.map +2 -2
- package/dist/components/natal-chart.d.ts.map +1 -1
- package/dist/components/natal-chart.js +76 -6
- package/dist/components/natal-chart.js.map +2 -2
- package/dist/components/numerology-card.js +14 -0
- package/dist/components/numerology-card.js.map +2 -2
- package/dist/components/panchang-table.d.ts +1 -0
- package/dist/components/panchang-table.d.ts.map +1 -1
- package/dist/components/panchang-table.js +37 -1
- package/dist/components/panchang-table.js.map +2 -2
- package/dist/components/shadbala-table.js +14 -0
- package/dist/components/shadbala-table.js.map +2 -2
- package/dist/components/synastry-chart.d.ts +6 -0
- package/dist/components/synastry-chart.d.ts.map +1 -1
- package/dist/components/synastry-chart.js +106 -7
- package/dist/components/synastry-chart.js.map +2 -2
- package/dist/components/tarot-card.js +14 -0
- package/dist/components/tarot-card.js.map +2 -2
- package/dist/components/tarot-spread.js +14 -0
- package/dist/components/tarot-spread.js.map +2 -2
- package/dist/components/transits-table.js +14 -0
- package/dist/components/transits-table.js.map +2 -2
- package/dist/components/vedic-kundli.d.ts +14 -9
- package/dist/components/vedic-kundli.d.ts.map +1 -1
- package/dist/components/vedic-kundli.js +537 -245
- package/dist/components/vedic-kundli.js.map +4 -4
- package/dist/components/vedic-planets-table.js +14 -0
- package/dist/components/vedic-planets-table.js.map +2 -2
- package/dist/components/western-planets-table.js +14 -0
- package/dist/components/western-planets-table.js.map +2 -2
- package/dist/components/yoga-list.js +14 -0
- package/dist/components/yoga-list.js.map +2 -2
- package/dist/index.cjs +1397 -797
- package/dist/index.cjs.map +4 -4
- package/dist/index.js +1278 -678
- package/dist/index.js.map +4 -4
- package/dist/manifest.json +23 -23
- package/dist/styles/tokens.css +8 -23
- package/dist/utils/base-styles.d.ts.map +1 -1
- package/dist/utils/kundli-render.d.ts +43 -104
- package/dist/utils/kundli-render.d.ts.map +1 -1
- package/dist/utils/kundli-styles.d.ts +13 -0
- package/dist/utils/kundli-styles.d.ts.map +1 -0
- package/dist/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/components/ashtakavarga-grid.ts +73 -11
- package/src/components/choghadiya-grid.ts +37 -2
- package/src/components/dasha-timeline.ts +135 -4
- package/src/components/divisional-chart.ts +40 -97
- package/src/components/natal-chart.ts +89 -6
- package/src/components/panchang-table.ts +34 -1
- package/src/components/synastry-chart.ts +84 -8
- package/src/components/vedic-kundli.ts +35 -95
- package/src/styles/tokens.css +8 -23
- package/src/utils/base-styles.ts +14 -0
- package/src/utils/kundli-render.ts +609 -270
- package/src/utils/kundli-styles.ts +124 -0
- package/src/version.ts +1 -1
|
@@ -12,7 +12,19 @@ export declare class RoxyAshtakavargaGrid extends LitElement {
|
|
|
12
12
|
render(): import("lit").TemplateResult<1>;
|
|
13
13
|
private onTabKeyDown;
|
|
14
14
|
private focusActiveTab;
|
|
15
|
-
|
|
15
|
+
/**
|
|
16
|
+
* Bhinna bindus per planet per sign run 0..8 (sum of 0/1 contributions
|
|
17
|
+
* from each of the 8 reference points). Bucket directly by raw count.
|
|
18
|
+
*/
|
|
19
|
+
private bhinnaHeat;
|
|
20
|
+
/**
|
|
21
|
+
* Sarva bindus per sign are the column total across all 7 planets, range
|
|
22
|
+
* roughly 0..56 with typical values 20..40. Bucketed per classical
|
|
23
|
+
* interpretation: 25 below par, 25..30 average, 30..40 strong, 40+ very
|
|
24
|
+
* strong. Bucket spans intentionally widen at the extremes so a single
|
|
25
|
+
* outlier sign reads as exceptional.
|
|
26
|
+
*/
|
|
27
|
+
private sarvaHeat;
|
|
16
28
|
private renderSarva;
|
|
17
29
|
private renderBhinna;
|
|
18
30
|
private renderPinda;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ashtakavarga-grid.d.ts","sourceRoot":"","sources":["../../src/components/ashtakavarga-grid.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,UAAU,EAAW,MAAM,KAAK,CAAC;AAGrD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAG9D,KAAK,GAAG,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;AAUxC;;;GAGG;AACH,qBACa,oBAAqB,SAAQ,UAAU;IACnD,MAAM,CAAC,MAAM,
|
|
1
|
+
{"version":3,"file":"ashtakavarga-grid.d.ts","sourceRoot":"","sources":["../../src/components/ashtakavarga-grid.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,UAAU,EAAW,MAAM,KAAK,CAAC;AAGrD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAG9D,KAAK,GAAG,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;AAUxC;;;GAGG;AACH,qBACa,oBAAqB,SAAQ,UAAU;IACnD,MAAM,CAAC,MAAM,4BA4KX;IAGF,IAAI,EAAE,oBAAoB,GAAG,IAAI,CAAQ;IAGzC,SAAS,EAAE,GAAG,CAAW;IAEzB,MAAM;IAwDN,OAAO,CAAC,YAAY;IAapB,OAAO,CAAC,cAAc;IAStB;;;OAGG;IACH,OAAO,CAAC,UAAU;IAUlB;;;;;;OAMG;IACH,OAAO,CAAC,SAAS;IAUjB,OAAO,CAAC,WAAW;IAqCnB,OAAO,CAAC,YAAY;IAiCpB,OAAO,CAAC,WAAW;CA4BnB;AAED,OAAO,CAAC,MAAM,CAAC;IACd,UAAU,qBAAqB;QAC9B,wBAAwB,EAAE,oBAAoB,CAAC;KAC/C;CACD"}
|
|
@@ -130,6 +130,20 @@ var baseStyles = css`
|
|
|
130
130
|
outline: 2px solid var(--roxy-ring, rgba(245, 158, 11, 0.4));
|
|
131
131
|
outline-offset: 2px;
|
|
132
132
|
}
|
|
133
|
+
|
|
134
|
+
/* Force the text-style variant on every Unicode glyph in the component.
|
|
135
|
+
* macOS and iOS substitute coloured emoji glyphs for the planetary and
|
|
136
|
+
* gender Unicode code points (Mars, Venus, Mercury, etc.) when the
|
|
137
|
+
* system colour-emoji font wins font selection. The text-style variant
|
|
138
|
+
* keeps glyphs monochrome so they inherit the surrounding fill colour
|
|
139
|
+
* and match the brand palette consistently across platforms.
|
|
140
|
+
*
|
|
141
|
+
* font-variant-emoji is part of CSS Fonts 4 (Safari 17+, Chrome 134+,
|
|
142
|
+
* Firefox 139+). On older browsers the rule is silently ignored.
|
|
143
|
+
*/
|
|
144
|
+
:host {
|
|
145
|
+
font-variant-emoji: text;
|
|
146
|
+
}
|
|
133
147
|
`;
|
|
134
148
|
|
|
135
149
|
// packages/ui/src/components/ashtakavarga-grid.ts
|
|
@@ -208,7 +222,11 @@ var RoxyAshtakavargaGrid = class extends LitElement {
|
|
|
208
222
|
btn?.focus();
|
|
209
223
|
});
|
|
210
224
|
}
|
|
211
|
-
|
|
225
|
+
/**
|
|
226
|
+
* Bhinna bindus per planet per sign run 0..8 (sum of 0/1 contributions
|
|
227
|
+
* from each of the 8 reference points). Bucket directly by raw count.
|
|
228
|
+
*/
|
|
229
|
+
bhinnaHeat(count) {
|
|
212
230
|
if (count <= 1) return "heat-1";
|
|
213
231
|
if (count <= 2) return "heat-2";
|
|
214
232
|
if (count <= 3) return "heat-3";
|
|
@@ -217,6 +235,22 @@ var RoxyAshtakavargaGrid = class extends LitElement {
|
|
|
217
235
|
if (count <= 6) return "heat-6";
|
|
218
236
|
return "heat-7";
|
|
219
237
|
}
|
|
238
|
+
/**
|
|
239
|
+
* Sarva bindus per sign are the column total across all 7 planets, range
|
|
240
|
+
* roughly 0..56 with typical values 20..40. Bucketed per classical
|
|
241
|
+
* interpretation: 25 below par, 25..30 average, 30..40 strong, 40+ very
|
|
242
|
+
* strong. Bucket spans intentionally widen at the extremes so a single
|
|
243
|
+
* outlier sign reads as exceptional.
|
|
244
|
+
*/
|
|
245
|
+
sarvaHeat(count) {
|
|
246
|
+
if (count <= 18) return "heat-1";
|
|
247
|
+
if (count <= 23) return "heat-2";
|
|
248
|
+
if (count <= 28) return "heat-3";
|
|
249
|
+
if (count <= 32) return "heat-4";
|
|
250
|
+
if (count <= 37) return "heat-5";
|
|
251
|
+
if (count <= 42) return "heat-6";
|
|
252
|
+
return "heat-7";
|
|
253
|
+
}
|
|
220
254
|
renderSarva(signs) {
|
|
221
255
|
const sav = this.data.sarvashtakavarga;
|
|
222
256
|
if (!sav) return html`<p class="roxy-empty">No sarvashtakavarga data</p>`;
|
|
@@ -231,7 +265,7 @@ var RoxyAshtakavargaGrid = class extends LitElement {
|
|
|
231
265
|
<tbody>
|
|
232
266
|
${signs.map((sign, i) => {
|
|
233
267
|
const count = sav.bindus[i] ?? 0;
|
|
234
|
-
const hc = this.
|
|
268
|
+
const hc = this.sarvaHeat(count);
|
|
235
269
|
return html`<tr>
|
|
236
270
|
<td>
|
|
237
271
|
<div class="planet-cell">
|
|
@@ -272,7 +306,7 @@ var RoxyAshtakavargaGrid = class extends LitElement {
|
|
|
272
306
|
(row) => html`<tr>
|
|
273
307
|
<td>${row.planet}</td>
|
|
274
308
|
${row.bindus.map((count) => {
|
|
275
|
-
const hc = this.
|
|
309
|
+
const hc = this.bhinnaHeat(count);
|
|
276
310
|
return html`<td class="${`heat-cell ${hc}`}">${count}</td>`;
|
|
277
311
|
})}
|
|
278
312
|
<td>${row.total}</td>
|
|
@@ -419,27 +453,68 @@ RoxyAshtakavargaGrid.styles = [
|
|
|
419
453
|
border-bottom: none;
|
|
420
454
|
}
|
|
421
455
|
|
|
422
|
-
/* Heat cells
|
|
456
|
+
/* Heat cells. Single base hue (var --roxy-heat) mixed with
|
|
457
|
+
* transparent at increasing percentages produces seven readable
|
|
458
|
+
* tiers in both light and dark themes. Text colour stays
|
|
459
|
+
* var(--roxy-fg) so it inverts with the host theme without
|
|
460
|
+
* per-tier overrides. */
|
|
423
461
|
.heat-cell {
|
|
424
462
|
border-radius: var(--roxy-radius-sm, 4px);
|
|
425
463
|
font-weight: var(--roxy-weight-bold, 600);
|
|
426
464
|
min-width: 2rem;
|
|
427
465
|
font-variant-numeric: tabular-nums;
|
|
466
|
+
color: var(--roxy-fg, currentColor);
|
|
428
467
|
}
|
|
429
468
|
|
|
430
|
-
.heat-1 { background: var(--roxy-heat
|
|
431
|
-
.heat-2 { background: var(--roxy-heat
|
|
432
|
-
.heat-3 { background: var(--roxy-heat
|
|
433
|
-
.heat-4 { background: var(--roxy-heat
|
|
434
|
-
.heat-5 { background: var(--roxy-heat
|
|
435
|
-
.heat-6 { background: var(--roxy-heat
|
|
436
|
-
.heat-7 { background: var(--roxy-heat
|
|
469
|
+
.heat-1 { background: color-mix(in srgb, var(--roxy-heat, #ef4444) 6%, transparent); }
|
|
470
|
+
.heat-2 { background: color-mix(in srgb, var(--roxy-heat, #ef4444) 14%, transparent); }
|
|
471
|
+
.heat-3 { background: color-mix(in srgb, var(--roxy-heat, #ef4444) 26%, transparent); }
|
|
472
|
+
.heat-4 { background: color-mix(in srgb, var(--roxy-heat, #ef4444) 40%, transparent); }
|
|
473
|
+
.heat-5 { background: color-mix(in srgb, var(--roxy-heat, #ef4444) 55%, transparent); }
|
|
474
|
+
.heat-6 { background: color-mix(in srgb, var(--roxy-heat, #ef4444) 72%, transparent); }
|
|
475
|
+
.heat-7 { background: color-mix(in srgb, var(--roxy-heat, #ef4444) 90%, transparent); }
|
|
437
476
|
|
|
438
477
|
/* Bhinna grid: planet header column narrower */
|
|
439
478
|
.bhinna-table th:first-child,
|
|
440
479
|
.bhinna-table td:first-child {
|
|
441
480
|
min-width: 5rem;
|
|
442
481
|
}
|
|
482
|
+
|
|
483
|
+
/* Tight cells below 480px so the 14-column bhinna grid stops
|
|
484
|
+
* overflowing the viewport. The wrapper keeps overflow-x:auto as
|
|
485
|
+
* a fallback for very long content. */
|
|
486
|
+
@container (max-width: 480px) {
|
|
487
|
+
.bhinna-table th,
|
|
488
|
+
.bhinna-table td {
|
|
489
|
+
padding: 0.3rem 0.35rem;
|
|
490
|
+
font-size: var(--roxy-text-xs, 0.75rem);
|
|
491
|
+
}
|
|
492
|
+
.bhinna-table th:first-child,
|
|
493
|
+
.bhinna-table td:first-child {
|
|
494
|
+
min-width: 3.5rem;
|
|
495
|
+
}
|
|
496
|
+
.heat-cell {
|
|
497
|
+
min-width: 1.5rem;
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
/* Visual cue that the bhinna table is scrollable below the breakpoint:
|
|
501
|
+
* a soft gradient at the right edge so users see there is more to scroll. */
|
|
502
|
+
.overflow-scroll {
|
|
503
|
+
mask-image: linear-gradient(
|
|
504
|
+
to right,
|
|
505
|
+
transparent 0,
|
|
506
|
+
black 0.5rem,
|
|
507
|
+
black calc(100% - 1rem),
|
|
508
|
+
transparent 100%
|
|
509
|
+
);
|
|
510
|
+
-webkit-mask-image: linear-gradient(
|
|
511
|
+
to right,
|
|
512
|
+
transparent 0,
|
|
513
|
+
black 0.5rem,
|
|
514
|
+
black calc(100% - 1rem),
|
|
515
|
+
transparent 100%
|
|
516
|
+
);
|
|
517
|
+
}
|
|
443
518
|
`
|
|
444
519
|
];
|
|
445
520
|
__decorateClass([
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/components/ashtakavarga-grid.ts", "../../src/tokens/index.ts", "../../src/utils/base-styles.ts"],
|
|
4
|
-
"sourcesContent": ["import { css, html, LitElement, nothing } from 'lit';\nimport { customElement, property, state } from 'lit/decorators.js';\nimport { SIGN_GLYPH } from '../tokens/index.js';\nimport type { AshtakavargaResponse } from '../types/index.js';\nimport { baseStyles } from '../utils/base-styles.js';\n\ntype Tab = 'sarva' | 'bhinna' | 'pinda';\n\nconst TAB_LABELS: Record<Tab, string> = {\n\tsarva: 'Sarvashtakavarga',\n\tbhinna: 'Bhinnashtakavarga',\n\tpinda: 'Shodhya Pinda',\n};\n\nconst TABS: Tab[] = ['sarva', 'bhinna', 'pinda'];\n\n/**\n * Ashtakavarga grid with three tabbed views: Sarvashtakavarga, Bhinnashtakavarga,\n * and Shodhya Pinda. Pass `data` from /vedic-astrology/ashtakavarga.\n */\n@customElement('roxy-ashtakavarga-grid')\nexport class RoxyAshtakavargaGrid extends LitElement {\n\tstatic styles = [\n\t\tbaseStyles,\n\t\tcss`\n\t\t\t.wrap {\n\t\t\t\tdisplay: grid;\n\t\t\t\tgap: var(--roxy-space-md, 1rem);\n\t\t\t}\n\n\t\t\t.head {\n\t\t\t\tdisplay: flex;\n\t\t\t\tjustify-content: space-between;\n\t\t\t\talign-items: baseline;\n\t\t\t\tgap: var(--roxy-space-md, 1rem);\n\t\t\t\tflex-wrap: wrap;\n\t\t\t}\n\n\t\t\t.title {\n\t\t\t\tfont-size: var(--roxy-text-lg, 1.125rem);\n\t\t\t\tfont-weight: var(--roxy-weight-bold, 600);\n\t\t\t\tmargin: 0;\n\t\t\t}\n\n\t\t\t.subtitle {\n\t\t\t\tcolor: var(--roxy-muted, #71717a);\n\t\t\t\tfont-size: var(--roxy-text-sm, 0.875rem);\n\t\t\t\tmargin: 0;\n\t\t\t}\n\n\t\t\t/* Tabs */\n\t\t\t.tablist {\n\t\t\t\tdisplay: flex;\n\t\t\t\tgap: 2px;\n\t\t\t\tborder-bottom: 2px solid var(--roxy-border, #e4e4e7);\n\t\t\t}\n\n\t\t\t.tab {\n\t\t\t\tpadding: var(--roxy-space-xs, 0.25rem) var(--roxy-space-md, 1rem);\n\t\t\t\tfont-size: var(--roxy-text-sm, 0.875rem);\n\t\t\t\tbackground: none;\n\t\t\t\tborder: none;\n\t\t\t\tborder-bottom: 2px solid transparent;\n\t\t\t\tmargin-bottom: -2px;\n\t\t\t\tcursor: pointer;\n\t\t\t\tcolor: var(--roxy-muted, #71717a);\n\t\t\t\tfont-family: inherit;\n\t\t\t\ttransition: color var(--roxy-motion-duration, 200ms) var(--roxy-motion-easing, ease);\n\t\t\t}\n\n\t\t\t.tab[aria-selected='true'] {\n\t\t\t\tcolor: var(--roxy-accent-fg, #b45309);\n\t\t\t\tborder-bottom-color: var(--roxy-accent, #f59e0b);\n\t\t\t\tfont-weight: var(--roxy-weight-bold, 600);\n\t\t\t}\n\n\t\t\t.tab:hover:not([aria-selected='true']) {\n\t\t\t\tcolor: var(--roxy-fg, #0a0a0a);\n\t\t\t}\n\n\t\t\t/* Tables */\n\t\t\t.overflow-scroll {\n\t\t\t\toverflow-x: auto;\n\t\t\t\t-webkit-overflow-scrolling: touch;\n\t\t\t}\n\n\t\t\ttable {\n\t\t\t\twidth: 100%;\n\t\t\t\tborder-collapse: collapse;\n\t\t\t\tfont-size: var(--roxy-text-sm, 0.875rem);\n\t\t\t}\n\n\t\t\tth,\n\t\t\ttd {\n\t\t\t\tpadding: var(--roxy-space-sm, 0.5rem);\n\t\t\t\tborder-bottom: 1px solid var(--roxy-border, #e4e4e7);\n\t\t\t\ttext-align: center;\n\t\t\t}\n\n\t\t\tth {\n\t\t\t\tcolor: var(--roxy-muted, #71717a);\n\t\t\t\tfont-weight: var(--roxy-weight-bold, 600);\n\t\t\t\ttext-transform: uppercase;\n\t\t\t\tfont-size: var(--roxy-text-xs, 0.75rem);\n\t\t\t\tletter-spacing: 0.06em;\n\t\t\t}\n\n\t\t\ttd:first-child,\n\t\t\tth:first-child {\n\t\t\t\ttext-align: left;\n\t\t\t}\n\n\t\t\t.glyph {\n\t\t\t\tfont-size: 1.1em;\n\t\t\t\tmargin-right: 3px;\n\t\t\t\tline-height: 1;\n\t\t\t}\n\n\t\t\t.planet-cell {\n\t\t\t\tdisplay: flex;\n\t\t\t\talign-items: center;\n\t\t\t\tgap: 4px;\n\t\t\t\twhite-space: nowrap;\n\t\t\t}\n\n\t\t\t.total-row td {\n\t\t\t\tfont-weight: var(--roxy-weight-bold, 600);\n\t\t\t\tborder-top: 2px solid var(--roxy-border, #e4e4e7);\n\t\t\t\tborder-bottom: none;\n\t\t\t}\n\n\t\t\t/* Heat cells */\n\t\t\t.heat-cell {\n\t\t\t\tborder-radius: var(--roxy-radius-sm, 4px);\n\t\t\t\tfont-weight: var(--roxy-weight-bold, 600);\n\t\t\t\tmin-width: 2rem;\n\t\t\t\tfont-variant-numeric: tabular-nums;\n\t\t\t}\n\n\t\t\t.heat-1 { background: var(--roxy-heat-1, #f0fdf4); color: var(--roxy-fg, #0a0a0a); }\n\t\t\t.heat-2 { background: var(--roxy-heat-2, #d1fae5); color: var(--roxy-fg, #0a0a0a); }\n\t\t\t.heat-3 { background: var(--roxy-heat-3, #a7f3d0); color: var(--roxy-fg, #0a0a0a); }\n\t\t\t.heat-4 { background: var(--roxy-heat-4, #fde68a); color: var(--roxy-fg, #0a0a0a); }\n\t\t\t.heat-5 { background: var(--roxy-heat-5, #fdba74); color: var(--roxy-fg, #0a0a0a); }\n\t\t\t.heat-6 { background: var(--roxy-heat-6, #fb923c); color: var(--roxy-fg, #0a0a0a); }\n\t\t\t.heat-7 { background: var(--roxy-heat-7, #ef4444); color: var(--roxy-fg, #0a0a0a); }\n\n\t\t\t/* Bhinna grid: planet header column narrower */\n\t\t\t.bhinna-table th:first-child,\n\t\t\t.bhinna-table td:first-child {\n\t\t\t\tmin-width: 5rem;\n\t\t\t}\n\t\t`,\n\t];\n\n\t@property({ attribute: false })\n\tdata: AshtakavargaResponse | null = null;\n\n\t@state()\n\tactiveTab: Tab = 'sarva';\n\n\trender() {\n\t\tif (!this.data) {\n\t\t\treturn html`<div class=\"roxy-empty\" role=\"status\">No ashtakavarga data</div>`;\n\t\t}\n\n\t\tconst signs = this.data.signs ?? [];\n\n\t\treturn html`<div class=\"wrap\" aria-label=\"Ashtakavarga grid\">\n\t\t\t<div class=\"head\">\n\t\t\t\t<h2 class=\"title\">Ashtakavarga</h2>\n\t\t\t\t${\n\t\t\t\t\tsigns.length\n\t\t\t\t\t\t? html`<p class=\"subtitle\">${signs.length} signs</p>`\n\t\t\t\t\t\t: nothing\n\t\t\t\t}\n\t\t\t</div>\n\n\t\t\t<div\n\t\t\t\tclass=\"tablist\"\n\t\t\t\trole=\"tablist\"\n\t\t\t\taria-label=\"Ashtakavarga views\"\n\t\t\t\t@keydown=${this.onTabKeyDown}\n\t\t\t>\n\t\t\t\t${TABS.map(\n\t\t\t\t\t(tab) => html`<button\n\t\t\t\t\t\tclass=\"tab\"\n\t\t\t\t\t\trole=\"tab\"\n\t\t\t\t\t\tid=\"tab-${tab}\"\n\t\t\t\t\t\taria-selected=${this.activeTab === tab ? 'true' : 'false'}\n\t\t\t\t\t\taria-controls=\"panel-${tab}\"\n\t\t\t\t\t\ttabindex=${this.activeTab === tab ? '0' : '-1'}\n\t\t\t\t\t\t@click=${() => {\n\t\t\t\t\t\t\tthis.activeTab = tab;\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t${TAB_LABELS[tab]}\n\t\t\t\t\t</button>`,\n\t\t\t\t)}\n\t\t\t</div>\n\n\t\t\t<div\n\t\t\t\tid=\"panel-${this.activeTab}\"\n\t\t\t\trole=\"tabpanel\"\n\t\t\t\taria-labelledby=\"tab-${this.activeTab}\"\n\t\t\t>\n\t\t\t\t${\n\t\t\t\t\tthis.activeTab === 'sarva'\n\t\t\t\t\t\t? this.renderSarva(signs)\n\t\t\t\t\t\t: this.activeTab === 'bhinna'\n\t\t\t\t\t\t\t? this.renderBhinna(signs)\n\t\t\t\t\t\t\t: this.renderPinda()\n\t\t\t\t}\n\t\t\t</div>\n\t\t</div>`;\n\t}\n\n\tprivate onTabKeyDown(e: KeyboardEvent) {\n\t\tconst idx = TABS.indexOf(this.activeTab);\n\t\tif (e.key === 'ArrowRight') {\n\t\t\te.preventDefault();\n\t\t\tthis.activeTab = TABS[(idx + 1) % TABS.length];\n\t\t\tthis.focusActiveTab();\n\t\t} else if (e.key === 'ArrowLeft') {\n\t\t\te.preventDefault();\n\t\t\tthis.activeTab = TABS[(idx - 1 + TABS.length) % TABS.length];\n\t\t\tthis.focusActiveTab();\n\t\t}\n\t}\n\n\tprivate focusActiveTab() {\n\t\trequestAnimationFrame(() => {\n\t\t\tconst btn = this.shadowRoot?.querySelector<HTMLButtonElement>(\n\t\t\t\t`#tab-${this.activeTab}`,\n\t\t\t);\n\t\t\tbtn?.focus();\n\t\t});\n\t}\n\n\tprivate heatClass(count: number): string {\n\t\tif (count <= 1) return 'heat-1';\n\t\tif (count <= 2) return 'heat-2';\n\t\tif (count <= 3) return 'heat-3';\n\t\tif (count <= 4) return 'heat-4';\n\t\tif (count <= 5) return 'heat-5';\n\t\tif (count <= 6) return 'heat-6';\n\t\treturn 'heat-7';\n\t}\n\n\tprivate renderSarva(signs: AshtakavargaResponse['signs']) {\n\t\tconst sav = this.data!.sarvashtakavarga;\n\t\tif (!sav) return html`<p class=\"roxy-empty\">No sarvashtakavarga data</p>`;\n\n\t\treturn html`<div class=\"overflow-scroll\">\n\t\t\t<table aria-label=\"Sarvashtakavarga bindu counts per sign\">\n\t\t\t\t<thead>\n\t\t\t\t\t<tr>\n\t\t\t\t\t\t<th scope=\"col\">Sign</th>\n\t\t\t\t\t\t<th scope=\"col\">Bindus</th>\n\t\t\t\t\t</tr>\n\t\t\t\t</thead>\n\t\t\t\t<tbody>\n\t\t\t\t\t${signs.map((sign, i) => {\n\t\t\t\t\t\tconst count = sav.bindus[i] ?? 0;\n\t\t\t\t\t\tconst hc = this.heatClass(count);\n\t\t\t\t\t\treturn html`<tr>\n\t\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t\t<div class=\"planet-cell\">\n\t\t\t\t\t\t\t\t\t<span class=\"glyph\" aria-hidden=\"true\">${SIGN_GLYPH[sign] ?? ''}</span>\n\t\t\t\t\t\t\t\t\t${sign}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t<td class=\"${`heat-cell ${hc}`}\">${count}</td>\n\t\t\t\t\t\t</tr>`;\n\t\t\t\t\t})}\n\t\t\t\t</tbody>\n\t\t\t\t<tfoot>\n\t\t\t\t\t<tr class=\"total-row\">\n\t\t\t\t\t\t<td>Total</td>\n\t\t\t\t\t\t<td>${sav.total}</td>\n\t\t\t\t\t</tr>\n\t\t\t\t</tfoot>\n\t\t\t</table>\n\t\t</div>`;\n\t}\n\n\tprivate renderBhinna(signs: AshtakavargaResponse['signs']) {\n\t\tconst bhinna = this.data!.bhinnashtakavarga;\n\t\tif (!bhinna?.length)\n\t\t\treturn html`<p class=\"roxy-empty\">No bhinnashtakavarga data</p>`;\n\n\t\treturn html`<div class=\"overflow-scroll\">\n\t\t\t<table class=\"bhinna-table\" aria-label=\"Bhinnashtakavarga planet-by-sign grid\">\n\t\t\t\t<thead>\n\t\t\t\t\t<tr>\n\t\t\t\t\t\t<th scope=\"col\">Planet</th>\n\t\t\t\t\t\t${signs.map(\n\t\t\t\t\t\t\t(s) =>\n\t\t\t\t\t\t\t\thtml`<th scope=\"col\" title=${s}>${SIGN_GLYPH[s] ?? s.slice(0, 2)}</th>`,\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t<th scope=\"col\">Total</th>\n\t\t\t\t\t</tr>\n\t\t\t\t</thead>\n\t\t\t\t<tbody>\n\t\t\t\t\t${bhinna.map(\n\t\t\t\t\t\t(row) => html`<tr>\n\t\t\t\t\t\t<td>${row.planet}</td>\n\t\t\t\t\t\t${row.bindus.map((count) => {\n\t\t\t\t\t\t\tconst hc = this.heatClass(count);\n\t\t\t\t\t\t\treturn html`<td class=\"${`heat-cell ${hc}`}\">${count}</td>`;\n\t\t\t\t\t\t})}\n\t\t\t\t\t\t<td>${row.total}</td>\n\t\t\t\t\t</tr>`,\n\t\t\t\t\t)}\n\t\t\t\t</tbody>\n\t\t\t</table>\n\t\t</div>`;\n\t}\n\n\tprivate renderPinda() {\n\t\tconst pinda = this.data!.shodhyaPinda;\n\t\tif (!pinda?.length)\n\t\t\treturn html`<p class=\"roxy-empty\">No shodhya pinda data</p>`;\n\n\t\treturn html`<div class=\"overflow-scroll\">\n\t\t\t<table aria-label=\"Shodhya Pinda planet strength scores\">\n\t\t\t\t<thead>\n\t\t\t\t\t<tr>\n\t\t\t\t\t\t<th scope=\"col\">Planet</th>\n\t\t\t\t\t\t<th scope=\"col\">Rashi Pinda</th>\n\t\t\t\t\t\t<th scope=\"col\">Graha Pinda</th>\n\t\t\t\t\t\t<th scope=\"col\">Shodhya Pinda</th>\n\t\t\t\t\t</tr>\n\t\t\t\t</thead>\n\t\t\t\t<tbody>\n\t\t\t\t\t${pinda.map(\n\t\t\t\t\t\t(row) => html`<tr>\n\t\t\t\t\t\t\t<td>${row.planet}</td>\n\t\t\t\t\t\t\t<td>${row.rashiPinda}</td>\n\t\t\t\t\t\t\t<td>${row.grahaPinda}</td>\n\t\t\t\t\t\t\t<td>${row.shodhyaPinda}</td>\n\t\t\t\t\t\t</tr>`,\n\t\t\t\t\t)}\n\t\t\t\t</tbody>\n\t\t\t</table>\n\t\t</div>`;\n\t}\n}\n\ndeclare global {\n\tinterface HTMLElementTagNameMap {\n\t\t'roxy-ashtakavarga-grid': RoxyAshtakavargaGrid;\n\t}\n}\n", "/**\n * Symbol constants used across components. Single source of truth so chart\n * wheels, card headers, hexagram displays, and panchang tables stay visually\n * consistent.\n */\n\nexport const PLANET_GLYPH: Record<string, string> = {\n\tSun: '\u2609',\n\tMoon: '\u263D',\n\tMercury: '\u263F',\n\tVenus: '\u2640',\n\tEarth: '\u2641',\n\tMars: '\u2642',\n\tJupiter: '\u2643',\n\tSaturn: '\u2644',\n\tUranus: '\u2645',\n\tNeptune: '\u2646',\n\tPluto: '\u2647',\n\tRahu: '\u260A',\n\tKetu: '\u260B',\n\tAscendant: 'Asc',\n\tLagna: 'La',\n\tNorthNode: '\u260A',\n\tSouthNode: '\u260B',\n\t'North node': '\u260A',\n\t'South node': '\u260B',\n\tChiron: '\u26B7',\n\tLilith: '\u26B8',\n\t'Black moon lilith': '\u26B8',\n};\n\nexport const PLANET_ABBR: Record<string, string> = {\n\tSun: 'Su',\n\tMoon: 'Mo',\n\tMercury: 'Me',\n\tVenus: 'Ve',\n\tMars: 'Ma',\n\tJupiter: 'Ju',\n\tSaturn: 'Sa',\n\tUranus: 'Ur',\n\tNeptune: 'Ne',\n\tPluto: 'Pl',\n\tRahu: 'Ra',\n\tKetu: 'Ke',\n\tAscendant: 'Asc',\n\tLagna: 'La',\n};\n\nexport const SIGN_GLYPH: Record<string, string> = {\n\tAries: '\u2648',\n\tTaurus: '\u2649',\n\tGemini: '\u264A',\n\tCancer: '\u264B',\n\tLeo: '\u264C',\n\tVirgo: '\u264D',\n\tLibra: '\u264E',\n\tScorpio: '\u264F',\n\tSagittarius: '\u2650',\n\tCapricorn: '\u2651',\n\tAquarius: '\u2652',\n\tPisces: '\u2653',\n};\n\nexport const SIGN_ABBR: Record<string, string> = {\n\tAries: 'Ar',\n\tTaurus: 'Ta',\n\tGemini: 'Ge',\n\tCancer: 'Cn',\n\tLeo: 'Le',\n\tVirgo: 'Vi',\n\tLibra: 'Li',\n\tScorpio: 'Sc',\n\tSagittarius: 'Sg',\n\tCapricorn: 'Cp',\n\tAquarius: 'Aq',\n\tPisces: 'Pi',\n};\n\nexport const SIGNS_ORDER = [\n\t'Aries',\n\t'Taurus',\n\t'Gemini',\n\t'Cancer',\n\t'Leo',\n\t'Virgo',\n\t'Libra',\n\t'Scorpio',\n\t'Sagittarius',\n\t'Capricorn',\n\t'Aquarius',\n\t'Pisces',\n] as const;\n\n/**\n * Lowercase rashi keys in canonical zodiac order. Derived from `SIGNS_ORDER`\n * so the two stay in lockstep. The /vedic-astrology/birth-chart response\n * carries planet buckets keyed by these names.\n */\nexport const RASHI_KEYS = SIGNS_ORDER.map((s) =>\n\ts.toLowerCase(),\n) as readonly Lowercase<(typeof SIGNS_ORDER)[number]>[];\n\n/** Aspect symbols. Used by synastry and natal chart aspect tables. */\nexport const ASPECT_SYMBOL: Record<string, string> = {\n\tconjunction: '\u260C',\n\topposition: '\u260D',\n\ttrine: '\u25B3',\n\tsquare: '\u25A1',\n\tsextile: '\u2731',\n\tquincunx: '\u22BB',\n\tsemisextile: '\u22BC',\n};\n\n/** Trigrams used by I Ching hexagrams. Eight trigrams compose 64 hexagrams. */\nexport const TRIGRAM_GLYPH: Record<string, string> = {\n\theaven: '\u2630',\n\tlake: '\u2631',\n\tfire: '\u2632',\n\tthunder: '\u2633',\n\twind: '\u2634',\n\twater: '\u2635',\n\tmountain: '\u2636',\n\tearth: '\u2637',\n\tHeaven: '\u2630',\n\tLake: '\u2631',\n\tFire: '\u2632',\n\tThunder: '\u2633',\n\tWind: '\u2634',\n\tWater: '\u2635',\n\tMountain: '\u2636',\n\tEarth: '\u2637',\n};\n\n/** Moon phase emoji set. Used by moon phase card. */\nexport const MOON_PHASE_EMOJI: Record<string, string> = {\n\t'new moon': '\uD83C\uDF11',\n\t'waxing crescent': '\uD83C\uDF12',\n\t'first quarter': '\uD83C\uDF13',\n\t'waxing gibbous': '\uD83C\uDF14',\n\t'full moon': '\uD83C\uDF15',\n\t'waning gibbous': '\uD83C\uDF16',\n\t'last quarter': '\uD83C\uDF17',\n\t'waning crescent': '\uD83C\uDF18',\n};\n", "import { css } from 'lit';\n\n/**\n * Shared host styles every component pulls in. Sets default font, color,\n * container query support, and the entry fade-in.\n */\nexport const baseStyles = css`\n\t:host {\n\t\tdisplay: block;\n\t\tcontainer-type: inline-size;\n\t\tfont-family: var(\n\t\t\t--roxy-font-sans,\n\t\t\tsystem-ui,\n\t\t\t-apple-system,\n\t\t\tBlinkMacSystemFont,\n\t\t\t'Segoe UI',\n\t\t\tRoboto,\n\t\t\tsans-serif\n\t\t);\n\t\tcolor: var(--roxy-fg, #0a0a0a);\n\t\tbackground: transparent;\n\t\tfont-size: var(--roxy-text-base, 1rem);\n\t\tline-height: var(--roxy-leading-normal, 1.5);\n\t\tanimation: roxy-fade-in var(--roxy-motion-duration, 200ms)\n\t\t\tvar(--roxy-motion-easing, cubic-bezier(0.4, 0, 0.2, 1)) both;\n\t}\n\n\t*,\n\t*::before,\n\t*::after {\n\t\tbox-sizing: border-box;\n\t}\n\n\t@keyframes roxy-fade-in {\n\t\tfrom {\n\t\t\topacity: 0;\n\t\t\ttransform: translateY(2px);\n\t\t}\n\t\tto {\n\t\t\topacity: 1;\n\t\t\ttransform: translateY(0);\n\t\t}\n\t}\n\n\t@media (prefers-reduced-motion: reduce) {\n\t\t:host {\n\t\t\tanimation: none;\n\t\t}\n\t}\n\n\t.roxy-skeleton {\n\t\tbackground: linear-gradient(\n\t\t\t90deg,\n\t\t\tvar(--roxy-border, #e4e4e7) 0%,\n\t\t\tcolor-mix(in srgb, var(--roxy-border, #e4e4e7) 60%, transparent) 50%,\n\t\t\tvar(--roxy-border, #e4e4e7) 100%\n\t\t);\n\t\tbackground-size: 200% 100%;\n\t\tanimation: roxy-shimmer 1.4s ease-in-out infinite;\n\t\tborder-radius: var(--roxy-radius-md, 8px);\n\t}\n\n\t@keyframes roxy-shimmer {\n\t\t0% {\n\t\t\tbackground-position: 200% 0;\n\t\t}\n\t\t100% {\n\t\t\tbackground-position: -200% 0;\n\t\t}\n\t}\n\n\t@media (prefers-reduced-motion: reduce) {\n\t\t.roxy-skeleton {\n\t\t\tanimation: none;\n\t\t}\n\t}\n\n\t.roxy-empty {\n\t\tpadding: var(--roxy-space-lg, 1.5rem);\n\t\tcolor: var(--roxy-muted, #71717a);\n\t\ttext-align: center;\n\t\tfont-size: var(--roxy-text-sm, 0.875rem);\n\t}\n\n\t:host(:focus-within) .roxy-card {\n\t\toutline: 2px solid var(--roxy-ring, rgba(245, 158, 11, 0.4));\n\t\toutline-offset: 2px;\n\t}\n`;\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;AAAA,SAAS,OAAAA,MAAK,MAAM,YAAY,eAAe;AAC/C,SAAS,eAAe,UAAU,aAAa;;;AC+CxC,IAAM,aAAqC;AAAA,EACjD,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,KAAK;AAAA,EACL,OAAO;AAAA,EACP,OAAO;AAAA,EACP,SAAS;AAAA,EACT,aAAa;AAAA,EACb,WAAW;AAAA,EACX,UAAU;AAAA,EACV,QAAQ;AACT;AAiBO,IAAM,cAAc;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD;AAOO,IAAM,aAAa,YAAY;AAAA,EAAI,CAAC,MAC1C,EAAE,YAAY;AACf;;;ACpGA,SAAS,WAAW;AAMb,IAAM,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;AFE1B,IAAM,aAAkC;AAAA,EACvC,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,OAAO;AACR;AAEA,IAAM,OAAc,CAAC,SAAS,UAAU,OAAO;AAOxC,IAAM,uBAAN,cAAmC,WAAW;AAAA,EAA9C;AAAA;
|
|
4
|
+
"sourcesContent": ["import { css, html, LitElement, nothing } from 'lit';\nimport { customElement, property, state } from 'lit/decorators.js';\nimport { SIGN_GLYPH } from '../tokens/index.js';\nimport type { AshtakavargaResponse } from '../types/index.js';\nimport { baseStyles } from '../utils/base-styles.js';\n\ntype Tab = 'sarva' | 'bhinna' | 'pinda';\n\nconst TAB_LABELS: Record<Tab, string> = {\n\tsarva: 'Sarvashtakavarga',\n\tbhinna: 'Bhinnashtakavarga',\n\tpinda: 'Shodhya Pinda',\n};\n\nconst TABS: Tab[] = ['sarva', 'bhinna', 'pinda'];\n\n/**\n * Ashtakavarga grid with three tabbed views: Sarvashtakavarga, Bhinnashtakavarga,\n * and Shodhya Pinda. Pass `data` from /vedic-astrology/ashtakavarga.\n */\n@customElement('roxy-ashtakavarga-grid')\nexport class RoxyAshtakavargaGrid extends LitElement {\n\tstatic styles = [\n\t\tbaseStyles,\n\t\tcss`\n\t\t\t.wrap {\n\t\t\t\tdisplay: grid;\n\t\t\t\tgap: var(--roxy-space-md, 1rem);\n\t\t\t}\n\n\t\t\t.head {\n\t\t\t\tdisplay: flex;\n\t\t\t\tjustify-content: space-between;\n\t\t\t\talign-items: baseline;\n\t\t\t\tgap: var(--roxy-space-md, 1rem);\n\t\t\t\tflex-wrap: wrap;\n\t\t\t}\n\n\t\t\t.title {\n\t\t\t\tfont-size: var(--roxy-text-lg, 1.125rem);\n\t\t\t\tfont-weight: var(--roxy-weight-bold, 600);\n\t\t\t\tmargin: 0;\n\t\t\t}\n\n\t\t\t.subtitle {\n\t\t\t\tcolor: var(--roxy-muted, #71717a);\n\t\t\t\tfont-size: var(--roxy-text-sm, 0.875rem);\n\t\t\t\tmargin: 0;\n\t\t\t}\n\n\t\t\t/* Tabs */\n\t\t\t.tablist {\n\t\t\t\tdisplay: flex;\n\t\t\t\tgap: 2px;\n\t\t\t\tborder-bottom: 2px solid var(--roxy-border, #e4e4e7);\n\t\t\t}\n\n\t\t\t.tab {\n\t\t\t\tpadding: var(--roxy-space-xs, 0.25rem) var(--roxy-space-md, 1rem);\n\t\t\t\tfont-size: var(--roxy-text-sm, 0.875rem);\n\t\t\t\tbackground: none;\n\t\t\t\tborder: none;\n\t\t\t\tborder-bottom: 2px solid transparent;\n\t\t\t\tmargin-bottom: -2px;\n\t\t\t\tcursor: pointer;\n\t\t\t\tcolor: var(--roxy-muted, #71717a);\n\t\t\t\tfont-family: inherit;\n\t\t\t\ttransition: color var(--roxy-motion-duration, 200ms) var(--roxy-motion-easing, ease);\n\t\t\t}\n\n\t\t\t.tab[aria-selected='true'] {\n\t\t\t\tcolor: var(--roxy-accent-fg, #b45309);\n\t\t\t\tborder-bottom-color: var(--roxy-accent, #f59e0b);\n\t\t\t\tfont-weight: var(--roxy-weight-bold, 600);\n\t\t\t}\n\n\t\t\t.tab:hover:not([aria-selected='true']) {\n\t\t\t\tcolor: var(--roxy-fg, #0a0a0a);\n\t\t\t}\n\n\t\t\t/* Tables */\n\t\t\t.overflow-scroll {\n\t\t\t\toverflow-x: auto;\n\t\t\t\t-webkit-overflow-scrolling: touch;\n\t\t\t}\n\n\t\t\ttable {\n\t\t\t\twidth: 100%;\n\t\t\t\tborder-collapse: collapse;\n\t\t\t\tfont-size: var(--roxy-text-sm, 0.875rem);\n\t\t\t}\n\n\t\t\tth,\n\t\t\ttd {\n\t\t\t\tpadding: var(--roxy-space-sm, 0.5rem);\n\t\t\t\tborder-bottom: 1px solid var(--roxy-border, #e4e4e7);\n\t\t\t\ttext-align: center;\n\t\t\t}\n\n\t\t\tth {\n\t\t\t\tcolor: var(--roxy-muted, #71717a);\n\t\t\t\tfont-weight: var(--roxy-weight-bold, 600);\n\t\t\t\ttext-transform: uppercase;\n\t\t\t\tfont-size: var(--roxy-text-xs, 0.75rem);\n\t\t\t\tletter-spacing: 0.06em;\n\t\t\t}\n\n\t\t\ttd:first-child,\n\t\t\tth:first-child {\n\t\t\t\ttext-align: left;\n\t\t\t}\n\n\t\t\t.glyph {\n\t\t\t\tfont-size: 1.1em;\n\t\t\t\tmargin-right: 3px;\n\t\t\t\tline-height: 1;\n\t\t\t}\n\n\t\t\t.planet-cell {\n\t\t\t\tdisplay: flex;\n\t\t\t\talign-items: center;\n\t\t\t\tgap: 4px;\n\t\t\t\twhite-space: nowrap;\n\t\t\t}\n\n\t\t\t.total-row td {\n\t\t\t\tfont-weight: var(--roxy-weight-bold, 600);\n\t\t\t\tborder-top: 2px solid var(--roxy-border, #e4e4e7);\n\t\t\t\tborder-bottom: none;\n\t\t\t}\n\n\t\t\t/* Heat cells. Single base hue (var --roxy-heat) mixed with\n\t\t\t * transparent at increasing percentages produces seven readable\n\t\t\t * tiers in both light and dark themes. Text colour stays\n\t\t\t * var(--roxy-fg) so it inverts with the host theme without\n\t\t\t * per-tier overrides. */\n\t\t\t.heat-cell {\n\t\t\t\tborder-radius: var(--roxy-radius-sm, 4px);\n\t\t\t\tfont-weight: var(--roxy-weight-bold, 600);\n\t\t\t\tmin-width: 2rem;\n\t\t\t\tfont-variant-numeric: tabular-nums;\n\t\t\t\tcolor: var(--roxy-fg, currentColor);\n\t\t\t}\n\n\t\t\t.heat-1 { background: color-mix(in srgb, var(--roxy-heat, #ef4444) 6%, transparent); }\n\t\t\t.heat-2 { background: color-mix(in srgb, var(--roxy-heat, #ef4444) 14%, transparent); }\n\t\t\t.heat-3 { background: color-mix(in srgb, var(--roxy-heat, #ef4444) 26%, transparent); }\n\t\t\t.heat-4 { background: color-mix(in srgb, var(--roxy-heat, #ef4444) 40%, transparent); }\n\t\t\t.heat-5 { background: color-mix(in srgb, var(--roxy-heat, #ef4444) 55%, transparent); }\n\t\t\t.heat-6 { background: color-mix(in srgb, var(--roxy-heat, #ef4444) 72%, transparent); }\n\t\t\t.heat-7 { background: color-mix(in srgb, var(--roxy-heat, #ef4444) 90%, transparent); }\n\n\t\t\t/* Bhinna grid: planet header column narrower */\n\t\t\t.bhinna-table th:first-child,\n\t\t\t.bhinna-table td:first-child {\n\t\t\t\tmin-width: 5rem;\n\t\t\t}\n\n\t\t\t/* Tight cells below 480px so the 14-column bhinna grid stops\n\t\t\t * overflowing the viewport. The wrapper keeps overflow-x:auto as\n\t\t\t * a fallback for very long content. */\n\t\t\t@container (max-width: 480px) {\n\t\t\t\t.bhinna-table th,\n\t\t\t\t.bhinna-table td {\n\t\t\t\t\tpadding: 0.3rem 0.35rem;\n\t\t\t\t\tfont-size: var(--roxy-text-xs, 0.75rem);\n\t\t\t\t}\n\t\t\t\t.bhinna-table th:first-child,\n\t\t\t\t.bhinna-table td:first-child {\n\t\t\t\t\tmin-width: 3.5rem;\n\t\t\t\t}\n\t\t\t\t.heat-cell {\n\t\t\t\t\tmin-width: 1.5rem;\n\t\t\t\t}\n\t\t\t}\n\t\t\t/* Visual cue that the bhinna table is scrollable below the breakpoint:\n\t\t\t * a soft gradient at the right edge so users see there is more to scroll. */\n\t\t\t.overflow-scroll {\n\t\t\t\tmask-image: linear-gradient(\n\t\t\t\t\tto right,\n\t\t\t\t\ttransparent 0,\n\t\t\t\t\tblack 0.5rem,\n\t\t\t\t\tblack calc(100% - 1rem),\n\t\t\t\t\ttransparent 100%\n\t\t\t\t);\n\t\t\t\t-webkit-mask-image: linear-gradient(\n\t\t\t\t\tto right,\n\t\t\t\t\ttransparent 0,\n\t\t\t\t\tblack 0.5rem,\n\t\t\t\t\tblack calc(100% - 1rem),\n\t\t\t\t\ttransparent 100%\n\t\t\t\t);\n\t\t\t}\n\t\t`,\n\t];\n\n\t@property({ attribute: false })\n\tdata: AshtakavargaResponse | null = null;\n\n\t@state()\n\tactiveTab: Tab = 'sarva';\n\n\trender() {\n\t\tif (!this.data) {\n\t\t\treturn html`<div class=\"roxy-empty\" role=\"status\">No ashtakavarga data</div>`;\n\t\t}\n\n\t\tconst signs = this.data.signs ?? [];\n\n\t\treturn html`<div class=\"wrap\" aria-label=\"Ashtakavarga grid\">\n\t\t\t<div class=\"head\">\n\t\t\t\t<h2 class=\"title\">Ashtakavarga</h2>\n\t\t\t\t${\n\t\t\t\t\tsigns.length\n\t\t\t\t\t\t? html`<p class=\"subtitle\">${signs.length} signs</p>`\n\t\t\t\t\t\t: nothing\n\t\t\t\t}\n\t\t\t</div>\n\n\t\t\t<div\n\t\t\t\tclass=\"tablist\"\n\t\t\t\trole=\"tablist\"\n\t\t\t\taria-label=\"Ashtakavarga views\"\n\t\t\t\t@keydown=${this.onTabKeyDown}\n\t\t\t>\n\t\t\t\t${TABS.map(\n\t\t\t\t\t(tab) => html`<button\n\t\t\t\t\t\tclass=\"tab\"\n\t\t\t\t\t\trole=\"tab\"\n\t\t\t\t\t\tid=\"tab-${tab}\"\n\t\t\t\t\t\taria-selected=${this.activeTab === tab ? 'true' : 'false'}\n\t\t\t\t\t\taria-controls=\"panel-${tab}\"\n\t\t\t\t\t\ttabindex=${this.activeTab === tab ? '0' : '-1'}\n\t\t\t\t\t\t@click=${() => {\n\t\t\t\t\t\t\tthis.activeTab = tab;\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t${TAB_LABELS[tab]}\n\t\t\t\t\t</button>`,\n\t\t\t\t)}\n\t\t\t</div>\n\n\t\t\t<div\n\t\t\t\tid=\"panel-${this.activeTab}\"\n\t\t\t\trole=\"tabpanel\"\n\t\t\t\taria-labelledby=\"tab-${this.activeTab}\"\n\t\t\t>\n\t\t\t\t${\n\t\t\t\t\tthis.activeTab === 'sarva'\n\t\t\t\t\t\t? this.renderSarva(signs)\n\t\t\t\t\t\t: this.activeTab === 'bhinna'\n\t\t\t\t\t\t\t? this.renderBhinna(signs)\n\t\t\t\t\t\t\t: this.renderPinda()\n\t\t\t\t}\n\t\t\t</div>\n\t\t</div>`;\n\t}\n\n\tprivate onTabKeyDown(e: KeyboardEvent) {\n\t\tconst idx = TABS.indexOf(this.activeTab);\n\t\tif (e.key === 'ArrowRight') {\n\t\t\te.preventDefault();\n\t\t\tthis.activeTab = TABS[(idx + 1) % TABS.length];\n\t\t\tthis.focusActiveTab();\n\t\t} else if (e.key === 'ArrowLeft') {\n\t\t\te.preventDefault();\n\t\t\tthis.activeTab = TABS[(idx - 1 + TABS.length) % TABS.length];\n\t\t\tthis.focusActiveTab();\n\t\t}\n\t}\n\n\tprivate focusActiveTab() {\n\t\trequestAnimationFrame(() => {\n\t\t\tconst btn = this.shadowRoot?.querySelector<HTMLButtonElement>(\n\t\t\t\t`#tab-${this.activeTab}`,\n\t\t\t);\n\t\t\tbtn?.focus();\n\t\t});\n\t}\n\n\t/**\n\t * Bhinna bindus per planet per sign run 0..8 (sum of 0/1 contributions\n\t * from each of the 8 reference points). Bucket directly by raw count.\n\t */\n\tprivate bhinnaHeat(count: number): string {\n\t\tif (count <= 1) return 'heat-1';\n\t\tif (count <= 2) return 'heat-2';\n\t\tif (count <= 3) return 'heat-3';\n\t\tif (count <= 4) return 'heat-4';\n\t\tif (count <= 5) return 'heat-5';\n\t\tif (count <= 6) return 'heat-6';\n\t\treturn 'heat-7';\n\t}\n\n\t/**\n\t * Sarva bindus per sign are the column total across all 7 planets, range\n\t * roughly 0..56 with typical values 20..40. Bucketed per classical\n\t * interpretation: 25 below par, 25..30 average, 30..40 strong, 40+ very\n\t * strong. Bucket spans intentionally widen at the extremes so a single\n\t * outlier sign reads as exceptional.\n\t */\n\tprivate sarvaHeat(count: number): string {\n\t\tif (count <= 18) return 'heat-1';\n\t\tif (count <= 23) return 'heat-2';\n\t\tif (count <= 28) return 'heat-3';\n\t\tif (count <= 32) return 'heat-4';\n\t\tif (count <= 37) return 'heat-5';\n\t\tif (count <= 42) return 'heat-6';\n\t\treturn 'heat-7';\n\t}\n\n\tprivate renderSarva(signs: AshtakavargaResponse['signs']) {\n\t\tconst sav = this.data!.sarvashtakavarga;\n\t\tif (!sav) return html`<p class=\"roxy-empty\">No sarvashtakavarga data</p>`;\n\n\t\treturn html`<div class=\"overflow-scroll\">\n\t\t\t<table aria-label=\"Sarvashtakavarga bindu counts per sign\">\n\t\t\t\t<thead>\n\t\t\t\t\t<tr>\n\t\t\t\t\t\t<th scope=\"col\">Sign</th>\n\t\t\t\t\t\t<th scope=\"col\">Bindus</th>\n\t\t\t\t\t</tr>\n\t\t\t\t</thead>\n\t\t\t\t<tbody>\n\t\t\t\t\t${signs.map((sign, i) => {\n\t\t\t\t\t\tconst count = sav.bindus[i] ?? 0;\n\t\t\t\t\t\tconst hc = this.sarvaHeat(count);\n\t\t\t\t\t\treturn html`<tr>\n\t\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t\t<div class=\"planet-cell\">\n\t\t\t\t\t\t\t\t\t<span class=\"glyph\" aria-hidden=\"true\">${SIGN_GLYPH[sign] ?? ''}</span>\n\t\t\t\t\t\t\t\t\t${sign}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t<td class=\"${`heat-cell ${hc}`}\">${count}</td>\n\t\t\t\t\t\t</tr>`;\n\t\t\t\t\t})}\n\t\t\t\t</tbody>\n\t\t\t\t<tfoot>\n\t\t\t\t\t<tr class=\"total-row\">\n\t\t\t\t\t\t<td>Total</td>\n\t\t\t\t\t\t<td>${sav.total}</td>\n\t\t\t\t\t</tr>\n\t\t\t\t</tfoot>\n\t\t\t</table>\n\t\t</div>`;\n\t}\n\n\tprivate renderBhinna(signs: AshtakavargaResponse['signs']) {\n\t\tconst bhinna = this.data!.bhinnashtakavarga;\n\t\tif (!bhinna?.length)\n\t\t\treturn html`<p class=\"roxy-empty\">No bhinnashtakavarga data</p>`;\n\n\t\treturn html`<div class=\"overflow-scroll\">\n\t\t\t<table class=\"bhinna-table\" aria-label=\"Bhinnashtakavarga planet-by-sign grid\">\n\t\t\t\t<thead>\n\t\t\t\t\t<tr>\n\t\t\t\t\t\t<th scope=\"col\">Planet</th>\n\t\t\t\t\t\t${signs.map(\n\t\t\t\t\t\t\t(s) =>\n\t\t\t\t\t\t\t\thtml`<th scope=\"col\" title=${s}>${SIGN_GLYPH[s] ?? s.slice(0, 2)}</th>`,\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t<th scope=\"col\">Total</th>\n\t\t\t\t\t</tr>\n\t\t\t\t</thead>\n\t\t\t\t<tbody>\n\t\t\t\t\t${bhinna.map(\n\t\t\t\t\t\t(row) => html`<tr>\n\t\t\t\t\t\t<td>${row.planet}</td>\n\t\t\t\t\t\t${row.bindus.map((count) => {\n\t\t\t\t\t\t\tconst hc = this.bhinnaHeat(count);\n\t\t\t\t\t\t\treturn html`<td class=\"${`heat-cell ${hc}`}\">${count}</td>`;\n\t\t\t\t\t\t})}\n\t\t\t\t\t\t<td>${row.total}</td>\n\t\t\t\t\t</tr>`,\n\t\t\t\t\t)}\n\t\t\t\t</tbody>\n\t\t\t</table>\n\t\t</div>`;\n\t}\n\n\tprivate renderPinda() {\n\t\tconst pinda = this.data!.shodhyaPinda;\n\t\tif (!pinda?.length)\n\t\t\treturn html`<p class=\"roxy-empty\">No shodhya pinda data</p>`;\n\n\t\treturn html`<div class=\"overflow-scroll\">\n\t\t\t<table aria-label=\"Shodhya Pinda planet strength scores\">\n\t\t\t\t<thead>\n\t\t\t\t\t<tr>\n\t\t\t\t\t\t<th scope=\"col\">Planet</th>\n\t\t\t\t\t\t<th scope=\"col\">Rashi Pinda</th>\n\t\t\t\t\t\t<th scope=\"col\">Graha Pinda</th>\n\t\t\t\t\t\t<th scope=\"col\">Shodhya Pinda</th>\n\t\t\t\t\t</tr>\n\t\t\t\t</thead>\n\t\t\t\t<tbody>\n\t\t\t\t\t${pinda.map(\n\t\t\t\t\t\t(row) => html`<tr>\n\t\t\t\t\t\t\t<td>${row.planet}</td>\n\t\t\t\t\t\t\t<td>${row.rashiPinda}</td>\n\t\t\t\t\t\t\t<td>${row.grahaPinda}</td>\n\t\t\t\t\t\t\t<td>${row.shodhyaPinda}</td>\n\t\t\t\t\t\t</tr>`,\n\t\t\t\t\t)}\n\t\t\t\t</tbody>\n\t\t\t</table>\n\t\t</div>`;\n\t}\n}\n\ndeclare global {\n\tinterface HTMLElementTagNameMap {\n\t\t'roxy-ashtakavarga-grid': RoxyAshtakavargaGrid;\n\t}\n}\n", "/**\n * Symbol constants used across components. Single source of truth so chart\n * wheels, card headers, hexagram displays, and panchang tables stay visually\n * consistent.\n */\n\nexport const PLANET_GLYPH: Record<string, string> = {\n\tSun: '\u2609',\n\tMoon: '\u263D',\n\tMercury: '\u263F',\n\tVenus: '\u2640',\n\tEarth: '\u2641',\n\tMars: '\u2642',\n\tJupiter: '\u2643',\n\tSaturn: '\u2644',\n\tUranus: '\u2645',\n\tNeptune: '\u2646',\n\tPluto: '\u2647',\n\tRahu: '\u260A',\n\tKetu: '\u260B',\n\tAscendant: 'Asc',\n\tLagna: 'La',\n\tNorthNode: '\u260A',\n\tSouthNode: '\u260B',\n\t'North node': '\u260A',\n\t'South node': '\u260B',\n\tChiron: '\u26B7',\n\tLilith: '\u26B8',\n\t'Black moon lilith': '\u26B8',\n};\n\nexport const PLANET_ABBR: Record<string, string> = {\n\tSun: 'Su',\n\tMoon: 'Mo',\n\tMercury: 'Me',\n\tVenus: 'Ve',\n\tMars: 'Ma',\n\tJupiter: 'Ju',\n\tSaturn: 'Sa',\n\tUranus: 'Ur',\n\tNeptune: 'Ne',\n\tPluto: 'Pl',\n\tRahu: 'Ra',\n\tKetu: 'Ke',\n\tAscendant: 'Asc',\n\tLagna: 'La',\n};\n\nexport const SIGN_GLYPH: Record<string, string> = {\n\tAries: '\u2648',\n\tTaurus: '\u2649',\n\tGemini: '\u264A',\n\tCancer: '\u264B',\n\tLeo: '\u264C',\n\tVirgo: '\u264D',\n\tLibra: '\u264E',\n\tScorpio: '\u264F',\n\tSagittarius: '\u2650',\n\tCapricorn: '\u2651',\n\tAquarius: '\u2652',\n\tPisces: '\u2653',\n};\n\nexport const SIGN_ABBR: Record<string, string> = {\n\tAries: 'Ar',\n\tTaurus: 'Ta',\n\tGemini: 'Ge',\n\tCancer: 'Cn',\n\tLeo: 'Le',\n\tVirgo: 'Vi',\n\tLibra: 'Li',\n\tScorpio: 'Sc',\n\tSagittarius: 'Sg',\n\tCapricorn: 'Cp',\n\tAquarius: 'Aq',\n\tPisces: 'Pi',\n};\n\nexport const SIGNS_ORDER = [\n\t'Aries',\n\t'Taurus',\n\t'Gemini',\n\t'Cancer',\n\t'Leo',\n\t'Virgo',\n\t'Libra',\n\t'Scorpio',\n\t'Sagittarius',\n\t'Capricorn',\n\t'Aquarius',\n\t'Pisces',\n] as const;\n\n/**\n * Lowercase rashi keys in canonical zodiac order. Derived from `SIGNS_ORDER`\n * so the two stay in lockstep. The /vedic-astrology/birth-chart response\n * carries planet buckets keyed by these names.\n */\nexport const RASHI_KEYS = SIGNS_ORDER.map((s) =>\n\ts.toLowerCase(),\n) as readonly Lowercase<(typeof SIGNS_ORDER)[number]>[];\n\n/** Aspect symbols. Used by synastry and natal chart aspect tables. */\nexport const ASPECT_SYMBOL: Record<string, string> = {\n\tconjunction: '\u260C',\n\topposition: '\u260D',\n\ttrine: '\u25B3',\n\tsquare: '\u25A1',\n\tsextile: '\u2731',\n\tquincunx: '\u22BB',\n\tsemisextile: '\u22BC',\n};\n\n/** Trigrams used by I Ching hexagrams. Eight trigrams compose 64 hexagrams. */\nexport const TRIGRAM_GLYPH: Record<string, string> = {\n\theaven: '\u2630',\n\tlake: '\u2631',\n\tfire: '\u2632',\n\tthunder: '\u2633',\n\twind: '\u2634',\n\twater: '\u2635',\n\tmountain: '\u2636',\n\tearth: '\u2637',\n\tHeaven: '\u2630',\n\tLake: '\u2631',\n\tFire: '\u2632',\n\tThunder: '\u2633',\n\tWind: '\u2634',\n\tWater: '\u2635',\n\tMountain: '\u2636',\n\tEarth: '\u2637',\n};\n\n/** Moon phase emoji set. Used by moon phase card. */\nexport const MOON_PHASE_EMOJI: Record<string, string> = {\n\t'new moon': '\uD83C\uDF11',\n\t'waxing crescent': '\uD83C\uDF12',\n\t'first quarter': '\uD83C\uDF13',\n\t'waxing gibbous': '\uD83C\uDF14',\n\t'full moon': '\uD83C\uDF15',\n\t'waning gibbous': '\uD83C\uDF16',\n\t'last quarter': '\uD83C\uDF17',\n\t'waning crescent': '\uD83C\uDF18',\n};\n", "import { css } from 'lit';\n\n/**\n * Shared host styles every component pulls in. Sets default font, color,\n * container query support, and the entry fade-in.\n */\nexport const baseStyles = css`\n\t:host {\n\t\tdisplay: block;\n\t\tcontainer-type: inline-size;\n\t\tfont-family: var(\n\t\t\t--roxy-font-sans,\n\t\t\tsystem-ui,\n\t\t\t-apple-system,\n\t\t\tBlinkMacSystemFont,\n\t\t\t'Segoe UI',\n\t\t\tRoboto,\n\t\t\tsans-serif\n\t\t);\n\t\tcolor: var(--roxy-fg, #0a0a0a);\n\t\tbackground: transparent;\n\t\tfont-size: var(--roxy-text-base, 1rem);\n\t\tline-height: var(--roxy-leading-normal, 1.5);\n\t\tanimation: roxy-fade-in var(--roxy-motion-duration, 200ms)\n\t\t\tvar(--roxy-motion-easing, cubic-bezier(0.4, 0, 0.2, 1)) both;\n\t}\n\n\t*,\n\t*::before,\n\t*::after {\n\t\tbox-sizing: border-box;\n\t}\n\n\t@keyframes roxy-fade-in {\n\t\tfrom {\n\t\t\topacity: 0;\n\t\t\ttransform: translateY(2px);\n\t\t}\n\t\tto {\n\t\t\topacity: 1;\n\t\t\ttransform: translateY(0);\n\t\t}\n\t}\n\n\t@media (prefers-reduced-motion: reduce) {\n\t\t:host {\n\t\t\tanimation: none;\n\t\t}\n\t}\n\n\t.roxy-skeleton {\n\t\tbackground: linear-gradient(\n\t\t\t90deg,\n\t\t\tvar(--roxy-border, #e4e4e7) 0%,\n\t\t\tcolor-mix(in srgb, var(--roxy-border, #e4e4e7) 60%, transparent) 50%,\n\t\t\tvar(--roxy-border, #e4e4e7) 100%\n\t\t);\n\t\tbackground-size: 200% 100%;\n\t\tanimation: roxy-shimmer 1.4s ease-in-out infinite;\n\t\tborder-radius: var(--roxy-radius-md, 8px);\n\t}\n\n\t@keyframes roxy-shimmer {\n\t\t0% {\n\t\t\tbackground-position: 200% 0;\n\t\t}\n\t\t100% {\n\t\t\tbackground-position: -200% 0;\n\t\t}\n\t}\n\n\t@media (prefers-reduced-motion: reduce) {\n\t\t.roxy-skeleton {\n\t\t\tanimation: none;\n\t\t}\n\t}\n\n\t.roxy-empty {\n\t\tpadding: var(--roxy-space-lg, 1.5rem);\n\t\tcolor: var(--roxy-muted, #71717a);\n\t\ttext-align: center;\n\t\tfont-size: var(--roxy-text-sm, 0.875rem);\n\t}\n\n\t:host(:focus-within) .roxy-card {\n\t\toutline: 2px solid var(--roxy-ring, rgba(245, 158, 11, 0.4));\n\t\toutline-offset: 2px;\n\t}\n\n\t/* Force the text-style variant on every Unicode glyph in the component.\n\t * macOS and iOS substitute coloured emoji glyphs for the planetary and\n\t * gender Unicode code points (Mars, Venus, Mercury, etc.) when the\n\t * system colour-emoji font wins font selection. The text-style variant\n\t * keeps glyphs monochrome so they inherit the surrounding fill colour\n\t * and match the brand palette consistently across platforms.\n\t *\n\t * font-variant-emoji is part of CSS Fonts 4 (Safari 17+, Chrome 134+,\n\t * Firefox 139+). On older browsers the rule is silently ignored.\n\t */\n\t:host {\n\t\tfont-variant-emoji: text;\n\t}\n`;\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["css", "css"]
|
|
7
7
|
}
|
|
@@ -97,6 +97,20 @@ var baseStyles = css`
|
|
|
97
97
|
outline: 2px solid var(--roxy-ring, rgba(245, 158, 11, 0.4));
|
|
98
98
|
outline-offset: 2px;
|
|
99
99
|
}
|
|
100
|
+
|
|
101
|
+
/* Force the text-style variant on every Unicode glyph in the component.
|
|
102
|
+
* macOS and iOS substitute coloured emoji glyphs for the planetary and
|
|
103
|
+
* gender Unicode code points (Mars, Venus, Mercury, etc.) when the
|
|
104
|
+
* system colour-emoji font wins font selection. The text-style variant
|
|
105
|
+
* keeps glyphs monochrome so they inherit the surrounding fill colour
|
|
106
|
+
* and match the brand palette consistently across platforms.
|
|
107
|
+
*
|
|
108
|
+
* font-variant-emoji is part of CSS Fonts 4 (Safari 17+, Chrome 134+,
|
|
109
|
+
* Firefox 139+). On older browsers the rule is silently ignored.
|
|
110
|
+
*/
|
|
111
|
+
:host {
|
|
112
|
+
font-variant-emoji: text;
|
|
113
|
+
}
|
|
100
114
|
`;
|
|
101
115
|
|
|
102
116
|
// packages/ui/src/components/biorhythm-chart.ts
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/components/biorhythm-chart.ts", "../../src/utils/base-styles.ts"],
|
|
4
|
-
"sourcesContent": ["import { css, html, LitElement, nothing, svg } from 'lit';\nimport { customElement, property } from 'lit/decorators.js';\nimport type {\n\tGetCriticalDaysResponse,\n\tGetDailyBiorhythmResponse,\n\tGetForecastResponse,\n} from '../types/index.js';\nimport { baseStyles } from '../utils/base-styles.js';\n\ntype BiorhythmData =\n\t| GetDailyBiorhythmResponse\n\t| GetForecastResponse\n\t| GetCriticalDaysResponse;\n\nconst CYCLE_COLOR: Record<string, string> = {\n\tphysical: '#dc2626',\n\temotional: '#0284c7',\n\tintellectual: '#16a34a',\n\tintuitive: '#a855f7',\n\taesthetic: '#f59e0b',\n\tawareness: '#ec4899',\n\tspiritual: '#14b8a6',\n\tpassion: '#ef4444',\n\tmastery: '#6366f1',\n\twisdom: '#475569',\n};\n\n/**\n * Biorhythm chart. Renders /biorhythm/{daily,forecast,critical-days}.\n */\n@customElement('roxy-biorhythm-chart')\nexport class RoxyBiorhythmChart extends LitElement {\n\tstatic styles = [\n\t\tbaseStyles,\n\t\tcss`\n\t\t\t.wrap {\n\t\t\t\tdisplay: grid;\n\t\t\t\tgap: var(--roxy-space-md, 1rem);\n\t\t\t}\n\t\t\t.head {\n\t\t\t\tdisplay: flex;\n\t\t\t\tjustify-content: space-between;\n\t\t\t\talign-items: center;\n\t\t\t\tflex-wrap: wrap;\n\t\t\t\tgap: var(--roxy-space-sm, 0.5rem);\n\t\t\t}\n\t\t\t.title {\n\t\t\t\tmargin: 0;\n\t\t\t\tfont-size: var(--roxy-text-lg, 1.125rem);\n\t\t\t\tfont-weight: var(--roxy-weight-bold, 600);\n\t\t\t}\n\t\t\t.energy {\n\t\t\t\tfont-variant-numeric: tabular-nums;\n\t\t\t\tcolor: var(--roxy-accent-fg, #b45309);\n\t\t\t\tfont-weight: var(--roxy-weight-bold, 600);\n\t\t\t}\n\t\t\t.bars {\n\t\t\t\tdisplay: grid;\n\t\t\t\tgap: var(--roxy-space-xs, 0.25rem);\n\t\t\t}\n\t\t\t.bar {\n\t\t\t\tdisplay: grid;\n\t\t\t\tgrid-template-columns: 8rem 1fr 3.5rem;\n\t\t\t\tgap: var(--roxy-space-sm, 0.5rem);\n\t\t\t\talign-items: center;\n\t\t\t\tfont-size: var(--roxy-text-sm, 0.875rem);\n\t\t\t}\n\t\t\t.track {\n\t\t\t\theight: 14px;\n\t\t\t\tbackground: var(--roxy-border, #e4e4e7);\n\t\t\t\tborder-radius: var(--roxy-radius-full, 9999px);\n\t\t\t\toverflow: hidden;\n\t\t\t\tposition: relative;\n\t\t\t}\n\t\t\t.fill {\n\t\t\t\tdisplay: block;\n\t\t\t\theight: 100%;\n\t\t\t\ttransition:\n\t\t\t\t\twidth var(--roxy-motion-duration, 200ms)\n\t\t\t\t\tvar(--roxy-motion-easing, cubic-bezier(0.4, 0, 0.2, 1));\n\t\t\t}\n\t\t\t.value {\n\t\t\t\tfont-variant-numeric: tabular-nums;\n\t\t\t\ttext-align: right;\n\t\t\t\tcolor: var(--roxy-muted, #71717a);\n\t\t\t}\n\t\t\t.advice {\n\t\t\t\tcolor: var(--roxy-fg, #0a0a0a);\n\t\t\t}\n\t\t\t.alert {\n\t\t\t\tbackground: color-mix(in srgb, var(--roxy-warning, #ea580c) 12%, transparent);\n\t\t\t\tborder: 1px solid color-mix(in srgb, var(--roxy-warning, #ea580c) 32%, transparent);\n\t\t\t\tborder-radius: var(--roxy-radius-md, 8px);\n\t\t\t\tpadding: var(--roxy-space-sm, 0.5rem);\n\t\t\t\tfont-size: var(--roxy-text-sm, 0.875rem);\n\t\t\t\tmargin: 0;\n\t\t\t}\n\t\t\tsvg {\n\t\t\t\tdisplay: block;\n\t\t\t\twidth: 100%;\n\t\t\t\theight: auto;\n\t\t\t}\n\t\t\t.crit {\n\t\t\t\tbackground: color-mix(in srgb, var(--roxy-danger, #dc2626) 12%, transparent);\n\t\t\t\tborder-radius: var(--roxy-radius-sm, 4px);\n\t\t\t\tpadding: 4px 8px;\n\t\t\t\tfont-size: var(--roxy-text-xs, 0.75rem);\n\t\t\t\tdisplay: inline-block;\n\t\t\t\tmargin: 2px;\n\t\t\t}\n\t\t`,\n\t];\n\n\t@property({ attribute: false })\n\tdata: BiorhythmData | null = null;\n\n\t@property({ type: String, reflect: true })\n\tmode: 'daily' | 'forecast' | 'critical-days' = 'daily';\n\n\trender() {\n\t\tconst d = this.data;\n\t\tif (!d)\n\t\t\treturn html`<div class=\"roxy-empty\" role=\"status\">No biorhythm data</div>`;\n\n\t\tif (this.mode === 'critical-days' && 'criticalDays' in d) {\n\t\t\treturn this.renderCritical(d as GetCriticalDaysResponse);\n\t\t}\n\t\tif (this.mode === 'forecast' && 'days' in d) {\n\t\t\treturn this.renderForecast(d as GetForecastResponse);\n\t\t}\n\t\treturn this.renderDaily(d as GetDailyBiorhythmResponse);\n\t}\n\n\tprivate renderDaily(d: GetDailyBiorhythmResponse) {\n\t\tconst raw = d.quickRead ?? {};\n\t\tconst entries = Object.entries(raw).map(([cycle, value]) => {\n\t\t\tconst v = typeof value === 'number' ? value : 0;\n\t\t\tconst normalized = Math.abs(v) > 1 ? v / 100 : v;\n\t\t\treturn [cycle, normalized] as const;\n\t\t});\n\t\treturn html`<section class=\"wrap\" aria-label=\"Daily biorhythm\">\n\t\t\t<header class=\"head\">\n\t\t\t\t<h2 class=\"title\">Biorhythm</h2>\n\t\t\t\t${\n\t\t\t\t\ttypeof d.energyRating === 'number'\n\t\t\t\t\t\t? html`<span class=\"energy\">Energy ${d.energyRating}/10</span>`\n\t\t\t\t\t\t: nothing\n\t\t\t\t}\n\t\t\t</header>\n\t\t\t<div class=\"bars\" role=\"list\">\n\t\t\t\t${entries.map(([cycle, v]) => {\n\t\t\t\t\tconst pct = ((v + 1) / 2) * 100; // -1..1 -> 0..100\n\t\t\t\t\tconst color = CYCLE_COLOR[cycle] ?? 'var(--roxy-accent, #f59e0b)';\n\t\t\t\t\treturn html`<div class=\"bar\" role=\"listitem\">\n\t\t\t\t\t\t<span style=\"text-transform: capitalize\">${cycle}</span>\n\t\t\t\t\t\t<span class=\"track\">\n\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\tclass=\"fill\"\n\t\t\t\t\t\t\t\tstyle=\"width: ${pct}%; background: ${color}\"\n\t\t\t\t\t\t\t></span>\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t<span class=\"value\">${Math.round(v * 100)}%</span>\n\t\t\t\t\t</div>`;\n\t\t\t\t})}\n\t\t\t</div>\n\t\t\t${d.dailyMessage ? html`<p class=\"advice\">${d.dailyMessage}</p>` : nothing}\n\t\t\t${d.advice ? html`<p class=\"advice\">${d.advice}</p>` : nothing}\n\t\t</section>`;\n\t}\n\n\tprivate renderForecast(d: GetForecastResponse) {\n\t\tconst days = d.days ?? [];\n\t\tif (days.length === 0)\n\t\t\treturn html`<div class=\"roxy-empty\" role=\"status\">No forecast</div>`;\n\t\tconst w = 600;\n\t\tconst h = 160;\n\t\tconst xStep = w / Math.max(days.length - 1, 1);\n\t\tconst cycleKeys = [\n\t\t\t'physical',\n\t\t\t'emotional',\n\t\t\t'intellectual',\n\t\t\t'intuitive',\n\t\t] as const;\n\t\treturn html`<section class=\"wrap\" aria-label=\"Biorhythm forecast\">\n\t\t\t<header class=\"head\">\n\t\t\t\t<h2 class=\"title\">Forecast</h2>\n\t\t\t\t<span class=\"energy\">${d.startDate} - ${d.endDate}</span>\n\t\t\t</header>\n\t\t\t<svg\n\t\t\t\tviewBox=\"0 0 ${w} ${h}\"\n\t\t\t\trole=\"img\"\n\t\t\t\taria-label=\"Biorhythm cycle lines across the forecast window\"\n\t\t\t>\n\t\t\t\t<title>Biorhythm forecast</title>\n\t\t\t\t<line\n\t\t\t\t\tx1=\"0\"\n\t\t\t\t\ty1=${h / 2}\n\t\t\t\t\tx2=${w}\n\t\t\t\t\ty2=${h / 2}\n\t\t\t\t\tstroke=\"var(--roxy-border, #e4e4e7)\"\n\t\t\t\t\tstroke-width=\"1\"\n\t\t\t\t/>\n\t\t\t\t${cycleKeys.map((cycle) => {\n\t\t\t\t\tconst points = days\n\t\t\t\t\t\t.map((day, i) => {\n\t\t\t\t\t\t\tconst v = day[cycle] ?? 0;\n\t\t\t\t\t\t\tconst x = i * xStep;\n\t\t\t\t\t\t\tconst y = h / 2 - (v / 100) * (h / 2 - 8);\n\t\t\t\t\t\t\treturn `${x.toFixed(2)},${y.toFixed(2)}`;\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.join(' ');\n\t\t\t\t\tconst color = CYCLE_COLOR[cycle] ?? '#475569';\n\t\t\t\t\treturn svg`<polyline points=${points} fill=\"none\" stroke=${color} stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />`;\n\t\t\t\t})}\n\t\t\t</svg>\n\t\t\t${\n\t\t\t\td.summary?.periodAdvice\n\t\t\t\t\t? html`<p class=\"advice\">${d.summary.periodAdvice}</p>`\n\t\t\t\t\t: nothing\n\t\t\t}\n\t\t</section>`;\n\t}\n\n\tprivate renderCritical(d: GetCriticalDaysResponse) {\n\t\treturn html`<section class=\"wrap\" aria-label=\"Critical days\">\n\t\t\t<header class=\"head\">\n\t\t\t\t<h2 class=\"title\">Critical days</h2>\n\t\t\t\t<span class=\"energy\">${d.totalCriticalDays} total</span>\n\t\t\t</header>\n\t\t\t<div>\n\t\t\t\t${d.criticalDays.map(\n\t\t\t\t\t(day) => html`<span class=\"crit\"\n\t\t\t\t\t\t>${day.date} \u00B7 ${day.cycle} ${day.severity}</span\n\t\t\t\t\t>`,\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</section>`;\n\t}\n}\n\ndeclare global {\n\tinterface HTMLElementTagNameMap {\n\t\t'roxy-biorhythm-chart': RoxyBiorhythmChart;\n\t}\n}\n", "import { css } from 'lit';\n\n/**\n * Shared host styles every component pulls in. Sets default font, color,\n * container query support, and the entry fade-in.\n */\nexport const baseStyles = css`\n\t:host {\n\t\tdisplay: block;\n\t\tcontainer-type: inline-size;\n\t\tfont-family: var(\n\t\t\t--roxy-font-sans,\n\t\t\tsystem-ui,\n\t\t\t-apple-system,\n\t\t\tBlinkMacSystemFont,\n\t\t\t'Segoe UI',\n\t\t\tRoboto,\n\t\t\tsans-serif\n\t\t);\n\t\tcolor: var(--roxy-fg, #0a0a0a);\n\t\tbackground: transparent;\n\t\tfont-size: var(--roxy-text-base, 1rem);\n\t\tline-height: var(--roxy-leading-normal, 1.5);\n\t\tanimation: roxy-fade-in var(--roxy-motion-duration, 200ms)\n\t\t\tvar(--roxy-motion-easing, cubic-bezier(0.4, 0, 0.2, 1)) both;\n\t}\n\n\t*,\n\t*::before,\n\t*::after {\n\t\tbox-sizing: border-box;\n\t}\n\n\t@keyframes roxy-fade-in {\n\t\tfrom {\n\t\t\topacity: 0;\n\t\t\ttransform: translateY(2px);\n\t\t}\n\t\tto {\n\t\t\topacity: 1;\n\t\t\ttransform: translateY(0);\n\t\t}\n\t}\n\n\t@media (prefers-reduced-motion: reduce) {\n\t\t:host {\n\t\t\tanimation: none;\n\t\t}\n\t}\n\n\t.roxy-skeleton {\n\t\tbackground: linear-gradient(\n\t\t\t90deg,\n\t\t\tvar(--roxy-border, #e4e4e7) 0%,\n\t\t\tcolor-mix(in srgb, var(--roxy-border, #e4e4e7) 60%, transparent) 50%,\n\t\t\tvar(--roxy-border, #e4e4e7) 100%\n\t\t);\n\t\tbackground-size: 200% 100%;\n\t\tanimation: roxy-shimmer 1.4s ease-in-out infinite;\n\t\tborder-radius: var(--roxy-radius-md, 8px);\n\t}\n\n\t@keyframes roxy-shimmer {\n\t\t0% {\n\t\t\tbackground-position: 200% 0;\n\t\t}\n\t\t100% {\n\t\t\tbackground-position: -200% 0;\n\t\t}\n\t}\n\n\t@media (prefers-reduced-motion: reduce) {\n\t\t.roxy-skeleton {\n\t\t\tanimation: none;\n\t\t}\n\t}\n\n\t.roxy-empty {\n\t\tpadding: var(--roxy-space-lg, 1.5rem);\n\t\tcolor: var(--roxy-muted, #71717a);\n\t\ttext-align: center;\n\t\tfont-size: var(--roxy-text-sm, 0.875rem);\n\t}\n\n\t:host(:focus-within) .roxy-card {\n\t\toutline: 2px solid var(--roxy-ring, rgba(245, 158, 11, 0.4));\n\t\toutline-offset: 2px;\n\t}\n`;\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import { css, html, LitElement, nothing, svg } from 'lit';\nimport { customElement, property } from 'lit/decorators.js';\nimport type {\n\tGetCriticalDaysResponse,\n\tGetDailyBiorhythmResponse,\n\tGetForecastResponse,\n} from '../types/index.js';\nimport { baseStyles } from '../utils/base-styles.js';\n\ntype BiorhythmData =\n\t| GetDailyBiorhythmResponse\n\t| GetForecastResponse\n\t| GetCriticalDaysResponse;\n\nconst CYCLE_COLOR: Record<string, string> = {\n\tphysical: '#dc2626',\n\temotional: '#0284c7',\n\tintellectual: '#16a34a',\n\tintuitive: '#a855f7',\n\taesthetic: '#f59e0b',\n\tawareness: '#ec4899',\n\tspiritual: '#14b8a6',\n\tpassion: '#ef4444',\n\tmastery: '#6366f1',\n\twisdom: '#475569',\n};\n\n/**\n * Biorhythm chart. Renders /biorhythm/{daily,forecast,critical-days}.\n */\n@customElement('roxy-biorhythm-chart')\nexport class RoxyBiorhythmChart extends LitElement {\n\tstatic styles = [\n\t\tbaseStyles,\n\t\tcss`\n\t\t\t.wrap {\n\t\t\t\tdisplay: grid;\n\t\t\t\tgap: var(--roxy-space-md, 1rem);\n\t\t\t}\n\t\t\t.head {\n\t\t\t\tdisplay: flex;\n\t\t\t\tjustify-content: space-between;\n\t\t\t\talign-items: center;\n\t\t\t\tflex-wrap: wrap;\n\t\t\t\tgap: var(--roxy-space-sm, 0.5rem);\n\t\t\t}\n\t\t\t.title {\n\t\t\t\tmargin: 0;\n\t\t\t\tfont-size: var(--roxy-text-lg, 1.125rem);\n\t\t\t\tfont-weight: var(--roxy-weight-bold, 600);\n\t\t\t}\n\t\t\t.energy {\n\t\t\t\tfont-variant-numeric: tabular-nums;\n\t\t\t\tcolor: var(--roxy-accent-fg, #b45309);\n\t\t\t\tfont-weight: var(--roxy-weight-bold, 600);\n\t\t\t}\n\t\t\t.bars {\n\t\t\t\tdisplay: grid;\n\t\t\t\tgap: var(--roxy-space-xs, 0.25rem);\n\t\t\t}\n\t\t\t.bar {\n\t\t\t\tdisplay: grid;\n\t\t\t\tgrid-template-columns: 8rem 1fr 3.5rem;\n\t\t\t\tgap: var(--roxy-space-sm, 0.5rem);\n\t\t\t\talign-items: center;\n\t\t\t\tfont-size: var(--roxy-text-sm, 0.875rem);\n\t\t\t}\n\t\t\t.track {\n\t\t\t\theight: 14px;\n\t\t\t\tbackground: var(--roxy-border, #e4e4e7);\n\t\t\t\tborder-radius: var(--roxy-radius-full, 9999px);\n\t\t\t\toverflow: hidden;\n\t\t\t\tposition: relative;\n\t\t\t}\n\t\t\t.fill {\n\t\t\t\tdisplay: block;\n\t\t\t\theight: 100%;\n\t\t\t\ttransition:\n\t\t\t\t\twidth var(--roxy-motion-duration, 200ms)\n\t\t\t\t\tvar(--roxy-motion-easing, cubic-bezier(0.4, 0, 0.2, 1));\n\t\t\t}\n\t\t\t.value {\n\t\t\t\tfont-variant-numeric: tabular-nums;\n\t\t\t\ttext-align: right;\n\t\t\t\tcolor: var(--roxy-muted, #71717a);\n\t\t\t}\n\t\t\t.advice {\n\t\t\t\tcolor: var(--roxy-fg, #0a0a0a);\n\t\t\t}\n\t\t\t.alert {\n\t\t\t\tbackground: color-mix(in srgb, var(--roxy-warning, #ea580c) 12%, transparent);\n\t\t\t\tborder: 1px solid color-mix(in srgb, var(--roxy-warning, #ea580c) 32%, transparent);\n\t\t\t\tborder-radius: var(--roxy-radius-md, 8px);\n\t\t\t\tpadding: var(--roxy-space-sm, 0.5rem);\n\t\t\t\tfont-size: var(--roxy-text-sm, 0.875rem);\n\t\t\t\tmargin: 0;\n\t\t\t}\n\t\t\tsvg {\n\t\t\t\tdisplay: block;\n\t\t\t\twidth: 100%;\n\t\t\t\theight: auto;\n\t\t\t}\n\t\t\t.crit {\n\t\t\t\tbackground: color-mix(in srgb, var(--roxy-danger, #dc2626) 12%, transparent);\n\t\t\t\tborder-radius: var(--roxy-radius-sm, 4px);\n\t\t\t\tpadding: 4px 8px;\n\t\t\t\tfont-size: var(--roxy-text-xs, 0.75rem);\n\t\t\t\tdisplay: inline-block;\n\t\t\t\tmargin: 2px;\n\t\t\t}\n\t\t`,\n\t];\n\n\t@property({ attribute: false })\n\tdata: BiorhythmData | null = null;\n\n\t@property({ type: String, reflect: true })\n\tmode: 'daily' | 'forecast' | 'critical-days' = 'daily';\n\n\trender() {\n\t\tconst d = this.data;\n\t\tif (!d)\n\t\t\treturn html`<div class=\"roxy-empty\" role=\"status\">No biorhythm data</div>`;\n\n\t\tif (this.mode === 'critical-days' && 'criticalDays' in d) {\n\t\t\treturn this.renderCritical(d as GetCriticalDaysResponse);\n\t\t}\n\t\tif (this.mode === 'forecast' && 'days' in d) {\n\t\t\treturn this.renderForecast(d as GetForecastResponse);\n\t\t}\n\t\treturn this.renderDaily(d as GetDailyBiorhythmResponse);\n\t}\n\n\tprivate renderDaily(d: GetDailyBiorhythmResponse) {\n\t\tconst raw = d.quickRead ?? {};\n\t\tconst entries = Object.entries(raw).map(([cycle, value]) => {\n\t\t\tconst v = typeof value === 'number' ? value : 0;\n\t\t\tconst normalized = Math.abs(v) > 1 ? v / 100 : v;\n\t\t\treturn [cycle, normalized] as const;\n\t\t});\n\t\treturn html`<section class=\"wrap\" aria-label=\"Daily biorhythm\">\n\t\t\t<header class=\"head\">\n\t\t\t\t<h2 class=\"title\">Biorhythm</h2>\n\t\t\t\t${\n\t\t\t\t\ttypeof d.energyRating === 'number'\n\t\t\t\t\t\t? html`<span class=\"energy\">Energy ${d.energyRating}/10</span>`\n\t\t\t\t\t\t: nothing\n\t\t\t\t}\n\t\t\t</header>\n\t\t\t<div class=\"bars\" role=\"list\">\n\t\t\t\t${entries.map(([cycle, v]) => {\n\t\t\t\t\tconst pct = ((v + 1) / 2) * 100; // -1..1 -> 0..100\n\t\t\t\t\tconst color = CYCLE_COLOR[cycle] ?? 'var(--roxy-accent, #f59e0b)';\n\t\t\t\t\treturn html`<div class=\"bar\" role=\"listitem\">\n\t\t\t\t\t\t<span style=\"text-transform: capitalize\">${cycle}</span>\n\t\t\t\t\t\t<span class=\"track\">\n\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\tclass=\"fill\"\n\t\t\t\t\t\t\t\tstyle=\"width: ${pct}%; background: ${color}\"\n\t\t\t\t\t\t\t></span>\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t<span class=\"value\">${Math.round(v * 100)}%</span>\n\t\t\t\t\t</div>`;\n\t\t\t\t})}\n\t\t\t</div>\n\t\t\t${d.dailyMessage ? html`<p class=\"advice\">${d.dailyMessage}</p>` : nothing}\n\t\t\t${d.advice ? html`<p class=\"advice\">${d.advice}</p>` : nothing}\n\t\t</section>`;\n\t}\n\n\tprivate renderForecast(d: GetForecastResponse) {\n\t\tconst days = d.days ?? [];\n\t\tif (days.length === 0)\n\t\t\treturn html`<div class=\"roxy-empty\" role=\"status\">No forecast</div>`;\n\t\tconst w = 600;\n\t\tconst h = 160;\n\t\tconst xStep = w / Math.max(days.length - 1, 1);\n\t\tconst cycleKeys = [\n\t\t\t'physical',\n\t\t\t'emotional',\n\t\t\t'intellectual',\n\t\t\t'intuitive',\n\t\t] as const;\n\t\treturn html`<section class=\"wrap\" aria-label=\"Biorhythm forecast\">\n\t\t\t<header class=\"head\">\n\t\t\t\t<h2 class=\"title\">Forecast</h2>\n\t\t\t\t<span class=\"energy\">${d.startDate} - ${d.endDate}</span>\n\t\t\t</header>\n\t\t\t<svg\n\t\t\t\tviewBox=\"0 0 ${w} ${h}\"\n\t\t\t\trole=\"img\"\n\t\t\t\taria-label=\"Biorhythm cycle lines across the forecast window\"\n\t\t\t>\n\t\t\t\t<title>Biorhythm forecast</title>\n\t\t\t\t<line\n\t\t\t\t\tx1=\"0\"\n\t\t\t\t\ty1=${h / 2}\n\t\t\t\t\tx2=${w}\n\t\t\t\t\ty2=${h / 2}\n\t\t\t\t\tstroke=\"var(--roxy-border, #e4e4e7)\"\n\t\t\t\t\tstroke-width=\"1\"\n\t\t\t\t/>\n\t\t\t\t${cycleKeys.map((cycle) => {\n\t\t\t\t\tconst points = days\n\t\t\t\t\t\t.map((day, i) => {\n\t\t\t\t\t\t\tconst v = day[cycle] ?? 0;\n\t\t\t\t\t\t\tconst x = i * xStep;\n\t\t\t\t\t\t\tconst y = h / 2 - (v / 100) * (h / 2 - 8);\n\t\t\t\t\t\t\treturn `${x.toFixed(2)},${y.toFixed(2)}`;\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.join(' ');\n\t\t\t\t\tconst color = CYCLE_COLOR[cycle] ?? '#475569';\n\t\t\t\t\treturn svg`<polyline points=${points} fill=\"none\" stroke=${color} stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />`;\n\t\t\t\t})}\n\t\t\t</svg>\n\t\t\t${\n\t\t\t\td.summary?.periodAdvice\n\t\t\t\t\t? html`<p class=\"advice\">${d.summary.periodAdvice}</p>`\n\t\t\t\t\t: nothing\n\t\t\t}\n\t\t</section>`;\n\t}\n\n\tprivate renderCritical(d: GetCriticalDaysResponse) {\n\t\treturn html`<section class=\"wrap\" aria-label=\"Critical days\">\n\t\t\t<header class=\"head\">\n\t\t\t\t<h2 class=\"title\">Critical days</h2>\n\t\t\t\t<span class=\"energy\">${d.totalCriticalDays} total</span>\n\t\t\t</header>\n\t\t\t<div>\n\t\t\t\t${d.criticalDays.map(\n\t\t\t\t\t(day) => html`<span class=\"crit\"\n\t\t\t\t\t\t>${day.date} \u00B7 ${day.cycle} ${day.severity}</span\n\t\t\t\t\t>`,\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</section>`;\n\t}\n}\n\ndeclare global {\n\tinterface HTMLElementTagNameMap {\n\t\t'roxy-biorhythm-chart': RoxyBiorhythmChart;\n\t}\n}\n", "import { css } from 'lit';\n\n/**\n * Shared host styles every component pulls in. Sets default font, color,\n * container query support, and the entry fade-in.\n */\nexport const baseStyles = css`\n\t:host {\n\t\tdisplay: block;\n\t\tcontainer-type: inline-size;\n\t\tfont-family: var(\n\t\t\t--roxy-font-sans,\n\t\t\tsystem-ui,\n\t\t\t-apple-system,\n\t\t\tBlinkMacSystemFont,\n\t\t\t'Segoe UI',\n\t\t\tRoboto,\n\t\t\tsans-serif\n\t\t);\n\t\tcolor: var(--roxy-fg, #0a0a0a);\n\t\tbackground: transparent;\n\t\tfont-size: var(--roxy-text-base, 1rem);\n\t\tline-height: var(--roxy-leading-normal, 1.5);\n\t\tanimation: roxy-fade-in var(--roxy-motion-duration, 200ms)\n\t\t\tvar(--roxy-motion-easing, cubic-bezier(0.4, 0, 0.2, 1)) both;\n\t}\n\n\t*,\n\t*::before,\n\t*::after {\n\t\tbox-sizing: border-box;\n\t}\n\n\t@keyframes roxy-fade-in {\n\t\tfrom {\n\t\t\topacity: 0;\n\t\t\ttransform: translateY(2px);\n\t\t}\n\t\tto {\n\t\t\topacity: 1;\n\t\t\ttransform: translateY(0);\n\t\t}\n\t}\n\n\t@media (prefers-reduced-motion: reduce) {\n\t\t:host {\n\t\t\tanimation: none;\n\t\t}\n\t}\n\n\t.roxy-skeleton {\n\t\tbackground: linear-gradient(\n\t\t\t90deg,\n\t\t\tvar(--roxy-border, #e4e4e7) 0%,\n\t\t\tcolor-mix(in srgb, var(--roxy-border, #e4e4e7) 60%, transparent) 50%,\n\t\t\tvar(--roxy-border, #e4e4e7) 100%\n\t\t);\n\t\tbackground-size: 200% 100%;\n\t\tanimation: roxy-shimmer 1.4s ease-in-out infinite;\n\t\tborder-radius: var(--roxy-radius-md, 8px);\n\t}\n\n\t@keyframes roxy-shimmer {\n\t\t0% {\n\t\t\tbackground-position: 200% 0;\n\t\t}\n\t\t100% {\n\t\t\tbackground-position: -200% 0;\n\t\t}\n\t}\n\n\t@media (prefers-reduced-motion: reduce) {\n\t\t.roxy-skeleton {\n\t\t\tanimation: none;\n\t\t}\n\t}\n\n\t.roxy-empty {\n\t\tpadding: var(--roxy-space-lg, 1.5rem);\n\t\tcolor: var(--roxy-muted, #71717a);\n\t\ttext-align: center;\n\t\tfont-size: var(--roxy-text-sm, 0.875rem);\n\t}\n\n\t:host(:focus-within) .roxy-card {\n\t\toutline: 2px solid var(--roxy-ring, rgba(245, 158, 11, 0.4));\n\t\toutline-offset: 2px;\n\t}\n\n\t/* Force the text-style variant on every Unicode glyph in the component.\n\t * macOS and iOS substitute coloured emoji glyphs for the planetary and\n\t * gender Unicode code points (Mars, Venus, Mercury, etc.) when the\n\t * system colour-emoji font wins font selection. The text-style variant\n\t * keeps glyphs monochrome so they inherit the surrounding fill colour\n\t * and match the brand palette consistently across platforms.\n\t *\n\t * font-variant-emoji is part of CSS Fonts 4 (Safari 17+, Chrome 134+,\n\t * Firefox 139+). On older browsers the rule is silently ignored.\n\t */\n\t:host {\n\t\tfont-variant-emoji: text;\n\t}\n`;\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["css", "css"]
|
|
7
7
|
}
|
|
@@ -8,6 +8,12 @@ import type { GetChoghadiyaResponse } from '../types/index.js';
|
|
|
8
8
|
export declare class RoxyChoghadiyaGrid extends LitElement {
|
|
9
9
|
static styles: import("lit").CSSResult[];
|
|
10
10
|
data: GetChoghadiyaResponse | null;
|
|
11
|
+
/**
|
|
12
|
+
* True when the current wall-clock time falls inside this period. Both
|
|
13
|
+
* `start` and `end` are ISO 8601 with timezone, so the comparison is
|
|
14
|
+
* timezone-aware via the host's `Date` parsing.
|
|
15
|
+
*/
|
|
16
|
+
private isCurrent;
|
|
11
17
|
private renderTile;
|
|
12
18
|
render(): import("lit").TemplateResult<1>;
|
|
13
19
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"choghadiya-grid.d.ts","sourceRoot":"","sources":["../../src/components/choghadiya-grid.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,UAAU,EAAW,MAAM,KAAK,CAAC;AAGrD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAoB/D;;;;GAIG;AACH,qBACa,kBAAmB,SAAQ,UAAU;IACjD,MAAM,CAAC,MAAM,
|
|
1
|
+
{"version":3,"file":"choghadiya-grid.d.ts","sourceRoot":"","sources":["../../src/components/choghadiya-grid.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,UAAU,EAAW,MAAM,KAAK,CAAC;AAGrD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAoB/D;;;;GAIG;AACH,qBACa,kBAAmB,SAAQ,UAAU;IACjD,MAAM,CAAC,MAAM,4BAsGX;IAGF,IAAI,EAAE,qBAAqB,GAAG,IAAI,CAAQ;IAE1C;;;;OAIG;IACH,OAAO,CAAC,SAAS;IAQjB,OAAO,CAAC,UAAU;IA0BlB,MAAM;CAqCN;AAED,OAAO,CAAC,MAAM,CAAC;IACd,UAAU,qBAAqB;QAC9B,sBAAsB,EAAE,kBAAkB,CAAC;KAC3C;CACD"}
|
|
@@ -140,6 +140,20 @@ var baseStyles = css`
|
|
|
140
140
|
outline: 2px solid var(--roxy-ring, rgba(245, 158, 11, 0.4));
|
|
141
141
|
outline-offset: 2px;
|
|
142
142
|
}
|
|
143
|
+
|
|
144
|
+
/* Force the text-style variant on every Unicode glyph in the component.
|
|
145
|
+
* macOS and iOS substitute coloured emoji glyphs for the planetary and
|
|
146
|
+
* gender Unicode code points (Mars, Venus, Mercury, etc.) when the
|
|
147
|
+
* system colour-emoji font wins font selection. The text-style variant
|
|
148
|
+
* keeps glyphs monochrome so they inherit the surrounding fill colour
|
|
149
|
+
* and match the brand palette consistently across platforms.
|
|
150
|
+
*
|
|
151
|
+
* font-variant-emoji is part of CSS Fonts 4 (Safari 17+, Chrome 134+,
|
|
152
|
+
* Firefox 139+). On older browsers the rule is silently ignored.
|
|
153
|
+
*/
|
|
154
|
+
:host {
|
|
155
|
+
font-variant-emoji: text;
|
|
156
|
+
}
|
|
143
157
|
`;
|
|
144
158
|
|
|
145
159
|
// packages/ui/src/utils/string.ts
|
|
@@ -163,12 +177,31 @@ var RoxyChoghadiyaGrid = class extends LitElement {
|
|
|
163
177
|
super(...arguments);
|
|
164
178
|
this.data = null;
|
|
165
179
|
}
|
|
180
|
+
/**
|
|
181
|
+
* True when the current wall-clock time falls inside this period. Both
|
|
182
|
+
* `start` and `end` are ISO 8601 with timezone, so the comparison is
|
|
183
|
+
* timezone-aware via the host's `Date` parsing.
|
|
184
|
+
*/
|
|
185
|
+
isCurrent(period) {
|
|
186
|
+
const now = Date.now();
|
|
187
|
+
const start = Date.parse(period.start);
|
|
188
|
+
const end = Date.parse(period.end);
|
|
189
|
+
if (Number.isNaN(start) || Number.isNaN(end)) return false;
|
|
190
|
+
return now >= start && now < end;
|
|
191
|
+
}
|
|
166
192
|
renderTile(period) {
|
|
167
193
|
const effectClass = period.effect === "Good" ? "good" : period.effect === "Bad" ? "bad" : "neutral";
|
|
194
|
+
const current = this.isCurrent(period);
|
|
168
195
|
const lordGlyph = PLANET_GLYPH[capitalize(period.lord)] ?? "";
|
|
169
196
|
const timeRange = `${fmtTime(period.start)} - ${fmtTime(period.end)}`;
|
|
170
|
-
return html`<div
|
|
171
|
-
|
|
197
|
+
return html`<div
|
|
198
|
+
class="cho-tile ${effectClass}${current ? " now" : ""}"
|
|
199
|
+
role="listitem"
|
|
200
|
+
aria-current=${current ? "time" : "false"}
|
|
201
|
+
>
|
|
202
|
+
<span class="tile-name">
|
|
203
|
+
${period.name}${current ? html`<span class="now-badge">Now</span>` : nothing}
|
|
204
|
+
</span>
|
|
172
205
|
<span class="tile-time" aria-label="Time range">${timeRange}</span>
|
|
173
206
|
<span class="tile-lord">
|
|
174
207
|
${lordGlyph ? html`<span aria-hidden="true">${lordGlyph}</span>` : nothing}
|
|
@@ -268,6 +301,21 @@ RoxyChoghadiyaGrid.styles = [
|
|
|
268
301
|
background: transparent;
|
|
269
302
|
color: var(--roxy-fg, #0a0a0a);
|
|
270
303
|
}
|
|
304
|
+
.cho-tile.now {
|
|
305
|
+
outline: 2px solid var(--roxy-accent, #f59e0b);
|
|
306
|
+
outline-offset: 1px;
|
|
307
|
+
box-shadow: 0 0 0 4px
|
|
308
|
+
color-mix(in srgb, var(--roxy-accent, #f59e0b) 18%, transparent);
|
|
309
|
+
}
|
|
310
|
+
.now-badge {
|
|
311
|
+
display: inline-block;
|
|
312
|
+
margin-left: 0.4em;
|
|
313
|
+
font-size: var(--roxy-text-xs, 0.75rem);
|
|
314
|
+
font-weight: var(--roxy-weight-bold, 600);
|
|
315
|
+
color: var(--roxy-accent-fg, #b45309);
|
|
316
|
+
text-transform: uppercase;
|
|
317
|
+
letter-spacing: 0.06em;
|
|
318
|
+
}
|
|
271
319
|
.tile-name {
|
|
272
320
|
font-size: var(--roxy-text-base, 1rem);
|
|
273
321
|
font-weight: var(--roxy-weight-bold, 600);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/components/choghadiya-grid.ts", "../../src/tokens/index.ts", "../../src/utils/base-styles.ts", "../../src/utils/string.ts"],
|
|
4
|
-
"sourcesContent": ["import { css, html, LitElement, nothing } from 'lit';\nimport { customElement, property } from 'lit/decorators.js';\nimport { PLANET_GLYPH } from '../tokens/index.js';\nimport type { GetChoghadiyaResponse } from '../types/index.js';\nimport { baseStyles } from '../utils/base-styles.js';\nimport { capitalize } from '../utils/string.js';\n\ntype ChoghadiyaPeriod = GetChoghadiyaResponse['dayChoghadiya'][number];\n\n/**\n * Format an ISO 8601 datetime string to a short local time (HH:MM).\n * Falls back to the raw string when parsing fails.\n */\nfunction fmtTime(iso: string): string {\n\ttry {\n\t\tconst d = new Date(iso);\n\t\tif (Number.isNaN(d.getTime())) return iso;\n\t\treturn d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });\n\t} catch {\n\t\treturn iso;\n\t}\n}\n\n/**\n * Choghadiya muhurta grid. Accepts a GetChoghadiyaResponse and renders\n * 8 daytime and 8 nighttime muhurta tiles in a two-column responsive layout.\n * Good periods are highlighted in green, Bad periods in red.\n */\n@customElement('roxy-choghadiya-grid')\nexport class RoxyChoghadiyaGrid extends LitElement {\n\tstatic styles = [\n\t\tbaseStyles,\n\t\tcss`\n\t\t\t.wrap {\n\t\t\t\tdisplay: grid;\n\t\t\t\tgap: var(--roxy-space-md, 1rem);\n\t\t\t}\n\t\t\t.header {\n\t\t\t\tdisplay: grid;\n\t\t\t\tgap: var(--roxy-space-xs, 0.25rem);\n\t\t\t}\n\t\t\t.title {\n\t\t\t\tfont-size: var(--roxy-text-lg, 1.125rem);\n\t\t\t\tfont-weight: var(--roxy-weight-bold, 600);\n\t\t\t\tmargin: 0;\n\t\t\t}\n\t\t\t.subtitle {\n\t\t\t\tfont-size: var(--roxy-text-sm, 0.875rem);\n\t\t\t\tcolor: var(--roxy-muted, #71717a);\n\t\t\t\tmargin: 0;\n\t\t\t}\n\t\t\t.cho-grid {\n\t\t\t\tdisplay: grid;\n\t\t\t\tgrid-template-columns: 1fr;\n\t\t\t\tgap: var(--roxy-space-md, 1rem);\n\t\t\t}\n\t\t\t@media (min-width: 720px) {\n\t\t\t\t.cho-grid {\n\t\t\t\t\tgrid-template-columns: 1fr 1fr;\n\t\t\t\t}\n\t\t\t}\n\t\t\t.period-col {\n\t\t\t\tdisplay: grid;\n\t\t\t\tgap: var(--roxy-space-xs, 0.25rem);\n\t\t\t}\n\t\t\t.period-heading {\n\t\t\t\tfont-size: var(--roxy-text-base, 1rem);\n\t\t\t\tfont-weight: var(--roxy-weight-bold, 600);\n\t\t\t\tmargin: 0 0 var(--roxy-space-xs, 0.25rem);\n\t\t\t\tcolor: var(--roxy-fg, #0a0a0a);\n\t\t\t}\n\t\t\t.cho-tile {\n\t\t\t\tdisplay: grid;\n\t\t\t\tgrid-template-columns: 1fr auto;\n\t\t\t\talign-items: center;\n\t\t\t\tgap: 0.25em 0.75em;\n\t\t\t\tpadding: 0.55em 0.85em;\n\t\t\t\tborder: 1px solid var(--roxy-border, #e4e4e7);\n\t\t\t\tborder-radius: var(--roxy-radius-md, 8px);\n\t\t\t}\n\t\t\t.cho-tile.good {\n\t\t\t\tbackground: color-mix(in srgb, var(--roxy-success, #22c55e) 18%, transparent);\n\t\t\t\tborder-color: color-mix(in srgb, var(--roxy-success, #22c55e) 45%, transparent);\n\t\t\t\tcolor: var(--roxy-fg, #0a0a0a);\n\t\t\t}\n\t\t\t.cho-tile.bad {\n\t\t\t\tbackground: color-mix(in srgb, var(--roxy-danger, #ef4444) 18%, transparent);\n\t\t\t\tborder-color: color-mix(in srgb, var(--roxy-danger, #ef4444) 45%, transparent);\n\t\t\t\tcolor: var(--roxy-fg, #0a0a0a);\n\t\t\t}\n\t\t\t.cho-tile.neutral {\n\t\t\t\tbackground: transparent;\n\t\t\t\tcolor: var(--roxy-fg, #0a0a0a);\n\t\t\t}\n\t\t\t.tile-name {\n\t\t\t\tfont-size: var(--roxy-text-base, 1rem);\n\t\t\t\tfont-weight: var(--roxy-weight-bold, 600);\n\t\t\t\tgrid-column: 1;\n\t\t\t}\n\t\t\t.tile-time {\n\t\t\t\tfont-size: var(--roxy-text-xs, 0.75rem);\n\t\t\t\topacity: 0.8;\n\t\t\t\twhite-space: nowrap;\n\t\t\t\tgrid-column: 2;\n\t\t\t\tgrid-row: 1 / 3;\n\t\t\t\ttext-align: right;\n\t\t\t\talign-self: center;\n\t\t\t}\n\t\t\t.tile-lord {\n\t\t\t\tfont-size: var(--roxy-text-sm, 0.875rem);\n\t\t\t\topacity: 0.85;\n\t\t\t\tgrid-column: 1;\n\t\t\t\tdisplay: flex;\n\t\t\t\talign-items: center;\n\t\t\t\tgap: 0.25em;\n\t\t\t}\n\t\t`,\n\t];\n\n\t@property({ attribute: false })\n\tdata: GetChoghadiyaResponse | null = null;\n\n\tprivate renderTile(period: ChoghadiyaPeriod) {\n\t\tconst effectClass =\n\t\t\tperiod.effect === 'Good'\n\t\t\t\t? 'good'\n\t\t\t\t: period.effect === 'Bad'\n\t\t\t\t\t? 'bad'\n\t\t\t\t\t: 'neutral';\n\t\tconst lordGlyph = PLANET_GLYPH[capitalize(period.lord)] ?? '';\n\t\tconst timeRange = `${fmtTime(period.start)} - ${fmtTime(period.end)}`;\n\t\treturn html`<div class=\"cho-tile ${effectClass}\" role=\"listitem\">\n\t\t\t<span class=\"tile-name\">${period.name}</span>\n\t\t\t<span class=\"tile-time\" aria-label=\"Time range\">${timeRange}</span>\n\t\t\t<span class=\"tile-lord\">\n\t\t\t\t${lordGlyph ? html`<span aria-hidden=\"true\">${lordGlyph}</span>` : nothing}\n\t\t\t\t${period.lord}\n\t\t\t</span>\n\t\t</div>`;\n\t}\n\n\trender() {\n\t\tif (!this.data)\n\t\t\treturn html`<div class=\"roxy-empty\" role=\"status\">No choghadiya data</div>`;\n\n\t\tconst { date, dayChoghadiya, nightChoghadiya } = this.data;\n\n\t\treturn html`<div class=\"wrap\">\n\t\t\t<div class=\"header\">\n\t\t\t\t<h2 class=\"title\">Choghadiya</h2>\n\t\t\t\t${date ? html`<p class=\"subtitle\">${date}</p>` : nothing}\n\t\t\t</div>\n\n\t\t\t<div class=\"cho-grid\">\n\t\t\t\t<section class=\"period-col\" aria-label=\"Day muhurta periods\">\n\t\t\t\t\t<h3 class=\"period-heading\">Day</h3>\n\t\t\t\t\t<div role=\"list\" aria-label=\"Daytime choghadiya\">\n\t\t\t\t\t\t${\n\t\t\t\t\t\t\tdayChoghadiya && dayChoghadiya.length > 0\n\t\t\t\t\t\t\t\t? dayChoghadiya.map((p) => this.renderTile(p))\n\t\t\t\t\t\t\t\t: html`<p class=\"roxy-empty\" role=\"status\">No daytime periods</p>`\n\t\t\t\t\t\t}\n\t\t\t\t\t</div>\n\t\t\t\t</section>\n\n\t\t\t\t<section class=\"period-col\" aria-label=\"Night muhurta periods\">\n\t\t\t\t\t<h3 class=\"period-heading\">Night</h3>\n\t\t\t\t\t<div role=\"list\" aria-label=\"Nighttime choghadiya\">\n\t\t\t\t\t\t${\n\t\t\t\t\t\t\tnightChoghadiya && nightChoghadiya.length > 0\n\t\t\t\t\t\t\t\t? nightChoghadiya.map((p) => this.renderTile(p))\n\t\t\t\t\t\t\t\t: html`<p class=\"roxy-empty\" role=\"status\">No nighttime periods</p>`\n\t\t\t\t\t\t}\n\t\t\t\t\t</div>\n\t\t\t\t</section>\n\t\t\t</div>\n\t\t</div>`;\n\t}\n}\n\ndeclare global {\n\tinterface HTMLElementTagNameMap {\n\t\t'roxy-choghadiya-grid': RoxyChoghadiyaGrid;\n\t}\n}\n", "/**\n * Symbol constants used across components. Single source of truth so chart\n * wheels, card headers, hexagram displays, and panchang tables stay visually\n * consistent.\n */\n\nexport const PLANET_GLYPH: Record<string, string> = {\n\tSun: '\u2609',\n\tMoon: '\u263D',\n\tMercury: '\u263F',\n\tVenus: '\u2640',\n\tEarth: '\u2641',\n\tMars: '\u2642',\n\tJupiter: '\u2643',\n\tSaturn: '\u2644',\n\tUranus: '\u2645',\n\tNeptune: '\u2646',\n\tPluto: '\u2647',\n\tRahu: '\u260A',\n\tKetu: '\u260B',\n\tAscendant: 'Asc',\n\tLagna: 'La',\n\tNorthNode: '\u260A',\n\tSouthNode: '\u260B',\n\t'North node': '\u260A',\n\t'South node': '\u260B',\n\tChiron: '\u26B7',\n\tLilith: '\u26B8',\n\t'Black moon lilith': '\u26B8',\n};\n\nexport const PLANET_ABBR: Record<string, string> = {\n\tSun: 'Su',\n\tMoon: 'Mo',\n\tMercury: 'Me',\n\tVenus: 'Ve',\n\tMars: 'Ma',\n\tJupiter: 'Ju',\n\tSaturn: 'Sa',\n\tUranus: 'Ur',\n\tNeptune: 'Ne',\n\tPluto: 'Pl',\n\tRahu: 'Ra',\n\tKetu: 'Ke',\n\tAscendant: 'Asc',\n\tLagna: 'La',\n};\n\nexport const SIGN_GLYPH: Record<string, string> = {\n\tAries: '\u2648',\n\tTaurus: '\u2649',\n\tGemini: '\u264A',\n\tCancer: '\u264B',\n\tLeo: '\u264C',\n\tVirgo: '\u264D',\n\tLibra: '\u264E',\n\tScorpio: '\u264F',\n\tSagittarius: '\u2650',\n\tCapricorn: '\u2651',\n\tAquarius: '\u2652',\n\tPisces: '\u2653',\n};\n\nexport const SIGN_ABBR: Record<string, string> = {\n\tAries: 'Ar',\n\tTaurus: 'Ta',\n\tGemini: 'Ge',\n\tCancer: 'Cn',\n\tLeo: 'Le',\n\tVirgo: 'Vi',\n\tLibra: 'Li',\n\tScorpio: 'Sc',\n\tSagittarius: 'Sg',\n\tCapricorn: 'Cp',\n\tAquarius: 'Aq',\n\tPisces: 'Pi',\n};\n\nexport const SIGNS_ORDER = [\n\t'Aries',\n\t'Taurus',\n\t'Gemini',\n\t'Cancer',\n\t'Leo',\n\t'Virgo',\n\t'Libra',\n\t'Scorpio',\n\t'Sagittarius',\n\t'Capricorn',\n\t'Aquarius',\n\t'Pisces',\n] as const;\n\n/**\n * Lowercase rashi keys in canonical zodiac order. Derived from `SIGNS_ORDER`\n * so the two stay in lockstep. The /vedic-astrology/birth-chart response\n * carries planet buckets keyed by these names.\n */\nexport const RASHI_KEYS = SIGNS_ORDER.map((s) =>\n\ts.toLowerCase(),\n) as readonly Lowercase<(typeof SIGNS_ORDER)[number]>[];\n\n/** Aspect symbols. Used by synastry and natal chart aspect tables. */\nexport const ASPECT_SYMBOL: Record<string, string> = {\n\tconjunction: '\u260C',\n\topposition: '\u260D',\n\ttrine: '\u25B3',\n\tsquare: '\u25A1',\n\tsextile: '\u2731',\n\tquincunx: '\u22BB',\n\tsemisextile: '\u22BC',\n};\n\n/** Trigrams used by I Ching hexagrams. Eight trigrams compose 64 hexagrams. */\nexport const TRIGRAM_GLYPH: Record<string, string> = {\n\theaven: '\u2630',\n\tlake: '\u2631',\n\tfire: '\u2632',\n\tthunder: '\u2633',\n\twind: '\u2634',\n\twater: '\u2635',\n\tmountain: '\u2636',\n\tearth: '\u2637',\n\tHeaven: '\u2630',\n\tLake: '\u2631',\n\tFire: '\u2632',\n\tThunder: '\u2633',\n\tWind: '\u2634',\n\tWater: '\u2635',\n\tMountain: '\u2636',\n\tEarth: '\u2637',\n};\n\n/** Moon phase emoji set. Used by moon phase card. */\nexport const MOON_PHASE_EMOJI: Record<string, string> = {\n\t'new moon': '\uD83C\uDF11',\n\t'waxing crescent': '\uD83C\uDF12',\n\t'first quarter': '\uD83C\uDF13',\n\t'waxing gibbous': '\uD83C\uDF14',\n\t'full moon': '\uD83C\uDF15',\n\t'waning gibbous': '\uD83C\uDF16',\n\t'last quarter': '\uD83C\uDF17',\n\t'waning crescent': '\uD83C\uDF18',\n};\n", "import { css } from 'lit';\n\n/**\n * Shared host styles every component pulls in. Sets default font, color,\n * container query support, and the entry fade-in.\n */\nexport const baseStyles = css`\n\t:host {\n\t\tdisplay: block;\n\t\tcontainer-type: inline-size;\n\t\tfont-family: var(\n\t\t\t--roxy-font-sans,\n\t\t\tsystem-ui,\n\t\t\t-apple-system,\n\t\t\tBlinkMacSystemFont,\n\t\t\t'Segoe UI',\n\t\t\tRoboto,\n\t\t\tsans-serif\n\t\t);\n\t\tcolor: var(--roxy-fg, #0a0a0a);\n\t\tbackground: transparent;\n\t\tfont-size: var(--roxy-text-base, 1rem);\n\t\tline-height: var(--roxy-leading-normal, 1.5);\n\t\tanimation: roxy-fade-in var(--roxy-motion-duration, 200ms)\n\t\t\tvar(--roxy-motion-easing, cubic-bezier(0.4, 0, 0.2, 1)) both;\n\t}\n\n\t*,\n\t*::before,\n\t*::after {\n\t\tbox-sizing: border-box;\n\t}\n\n\t@keyframes roxy-fade-in {\n\t\tfrom {\n\t\t\topacity: 0;\n\t\t\ttransform: translateY(2px);\n\t\t}\n\t\tto {\n\t\t\topacity: 1;\n\t\t\ttransform: translateY(0);\n\t\t}\n\t}\n\n\t@media (prefers-reduced-motion: reduce) {\n\t\t:host {\n\t\t\tanimation: none;\n\t\t}\n\t}\n\n\t.roxy-skeleton {\n\t\tbackground: linear-gradient(\n\t\t\t90deg,\n\t\t\tvar(--roxy-border, #e4e4e7) 0%,\n\t\t\tcolor-mix(in srgb, var(--roxy-border, #e4e4e7) 60%, transparent) 50%,\n\t\t\tvar(--roxy-border, #e4e4e7) 100%\n\t\t);\n\t\tbackground-size: 200% 100%;\n\t\tanimation: roxy-shimmer 1.4s ease-in-out infinite;\n\t\tborder-radius: var(--roxy-radius-md, 8px);\n\t}\n\n\t@keyframes roxy-shimmer {\n\t\t0% {\n\t\t\tbackground-position: 200% 0;\n\t\t}\n\t\t100% {\n\t\t\tbackground-position: -200% 0;\n\t\t}\n\t}\n\n\t@media (prefers-reduced-motion: reduce) {\n\t\t.roxy-skeleton {\n\t\t\tanimation: none;\n\t\t}\n\t}\n\n\t.roxy-empty {\n\t\tpadding: var(--roxy-space-lg, 1.5rem);\n\t\tcolor: var(--roxy-muted, #71717a);\n\t\ttext-align: center;\n\t\tfont-size: var(--roxy-text-sm, 0.875rem);\n\t}\n\n\t:host(:focus-within) .roxy-card {\n\t\toutline: 2px solid var(--roxy-ring, rgba(245, 158, 11, 0.4));\n\t\toutline-offset: 2px;\n\t}\n`;\n", "/**\n * Shared string helpers used across components. Single source of truth so the\n * same formatting rules apply to every key/label/title that surfaces in the\n * shadow tree.\n *\n * - `capitalize`: title-cases the first character, lowercases the rest. Used\n * when matching API-supplied planet/sign names against the glyph maps in\n * `tokens/index.ts`, which use canonical TitleCase keys.\n * - `humanize`: turns an API key (`birth_date`, `birthDate`, `mahadasha-end`)\n * into a label suitable for display (\"Birth date\", \"Mahadasha end\").\n */\n\nexport function capitalize(s: string): string {\n\tif (!s) return '';\n\treturn s.charAt(0).toUpperCase() + s.slice(1).toLowerCase();\n}\n\nexport function humanize(s: string): string {\n\treturn s\n\t\t.replace(/[_-]+/g, ' ')\n\t\t.replace(/([a-z])([A-Z])/g, '$1 $2')\n\t\t.replace(/^\\w/, (c) => c.toUpperCase());\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;AAAA,SAAS,OAAAA,MAAK,MAAM,YAAY,eAAe;AAC/C,SAAS,eAAe,gBAAgB;;;ACKjC,IAAM,eAAuC;AAAA,EACnD,KAAK;AAAA,EACL,MAAM;AAAA,EACN,SAAS;AAAA,EACT,OAAO;AAAA,EACP,OAAO;AAAA,EACP,MAAM;AAAA,EACN,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,OAAO;AAAA,EACP,MAAM;AAAA,EACN,MAAM;AAAA,EACN,WAAW;AAAA,EACX,OAAO;AAAA,EACP,WAAW;AAAA,EACX,WAAW;AAAA,EACX,cAAc;AAAA,EACd,cAAc;AAAA,EACd,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,qBAAqB;AACtB;AAiDO,IAAM,cAAc;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD;AAOO,IAAM,aAAa,YAAY;AAAA,EAAI,CAAC,MAC1C,EAAE,YAAY;AACf;;;ACpGA,SAAS,WAAW;AAMb,IAAM,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACMnB,SAAS,WAAW,GAAmB;AAC7C,MAAI,CAAC,EAAG,QAAO;AACf,SAAO,EAAE,OAAO,CAAC,EAAE,YAAY,IAAI,EAAE,MAAM,CAAC,EAAE,YAAY;AAC3D;;;AHFA,SAAS,QAAQ,KAAqB;AACrC,MAAI;AACH,UAAM,IAAI,IAAI,KAAK,GAAG;AACtB,QAAI,OAAO,MAAM,EAAE,QAAQ,CAAC,EAAG,QAAO;AACtC,WAAO,EAAE,mBAAmB,CAAC,GAAG,EAAE,MAAM,WAAW,QAAQ,UAAU,CAAC;AAAA,EACvE,QAAQ;AACP,WAAO;AAAA,EACR;AACD;AAQO,IAAM,qBAAN,cAAiC,WAAW;AAAA,EAA5C;AAAA;
|
|
4
|
+
"sourcesContent": ["import { css, html, LitElement, nothing } from 'lit';\nimport { customElement, property } from 'lit/decorators.js';\nimport { PLANET_GLYPH } from '../tokens/index.js';\nimport type { GetChoghadiyaResponse } from '../types/index.js';\nimport { baseStyles } from '../utils/base-styles.js';\nimport { capitalize } from '../utils/string.js';\n\ntype ChoghadiyaPeriod = GetChoghadiyaResponse['dayChoghadiya'][number];\n\n/**\n * Format an ISO 8601 datetime string to a short local time (HH:MM).\n * Falls back to the raw string when parsing fails.\n */\nfunction fmtTime(iso: string): string {\n\ttry {\n\t\tconst d = new Date(iso);\n\t\tif (Number.isNaN(d.getTime())) return iso;\n\t\treturn d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });\n\t} catch {\n\t\treturn iso;\n\t}\n}\n\n/**\n * Choghadiya muhurta grid. Accepts a GetChoghadiyaResponse and renders\n * 8 daytime and 8 nighttime muhurta tiles in a two-column responsive layout.\n * Good periods are highlighted in green, Bad periods in red.\n */\n@customElement('roxy-choghadiya-grid')\nexport class RoxyChoghadiyaGrid extends LitElement {\n\tstatic styles = [\n\t\tbaseStyles,\n\t\tcss`\n\t\t\t.wrap {\n\t\t\t\tdisplay: grid;\n\t\t\t\tgap: var(--roxy-space-md, 1rem);\n\t\t\t}\n\t\t\t.header {\n\t\t\t\tdisplay: grid;\n\t\t\t\tgap: var(--roxy-space-xs, 0.25rem);\n\t\t\t}\n\t\t\t.title {\n\t\t\t\tfont-size: var(--roxy-text-lg, 1.125rem);\n\t\t\t\tfont-weight: var(--roxy-weight-bold, 600);\n\t\t\t\tmargin: 0;\n\t\t\t}\n\t\t\t.subtitle {\n\t\t\t\tfont-size: var(--roxy-text-sm, 0.875rem);\n\t\t\t\tcolor: var(--roxy-muted, #71717a);\n\t\t\t\tmargin: 0;\n\t\t\t}\n\t\t\t.cho-grid {\n\t\t\t\tdisplay: grid;\n\t\t\t\tgrid-template-columns: 1fr;\n\t\t\t\tgap: var(--roxy-space-md, 1rem);\n\t\t\t}\n\t\t\t@media (min-width: 720px) {\n\t\t\t\t.cho-grid {\n\t\t\t\t\tgrid-template-columns: 1fr 1fr;\n\t\t\t\t}\n\t\t\t}\n\t\t\t.period-col {\n\t\t\t\tdisplay: grid;\n\t\t\t\tgap: var(--roxy-space-xs, 0.25rem);\n\t\t\t}\n\t\t\t.period-heading {\n\t\t\t\tfont-size: var(--roxy-text-base, 1rem);\n\t\t\t\tfont-weight: var(--roxy-weight-bold, 600);\n\t\t\t\tmargin: 0 0 var(--roxy-space-xs, 0.25rem);\n\t\t\t\tcolor: var(--roxy-fg, #0a0a0a);\n\t\t\t}\n\t\t\t.cho-tile {\n\t\t\t\tdisplay: grid;\n\t\t\t\tgrid-template-columns: 1fr auto;\n\t\t\t\talign-items: center;\n\t\t\t\tgap: 0.25em 0.75em;\n\t\t\t\tpadding: 0.55em 0.85em;\n\t\t\t\tborder: 1px solid var(--roxy-border, #e4e4e7);\n\t\t\t\tborder-radius: var(--roxy-radius-md, 8px);\n\t\t\t}\n\t\t\t.cho-tile.good {\n\t\t\t\tbackground: color-mix(in srgb, var(--roxy-success, #22c55e) 18%, transparent);\n\t\t\t\tborder-color: color-mix(in srgb, var(--roxy-success, #22c55e) 45%, transparent);\n\t\t\t\tcolor: var(--roxy-fg, #0a0a0a);\n\t\t\t}\n\t\t\t.cho-tile.bad {\n\t\t\t\tbackground: color-mix(in srgb, var(--roxy-danger, #ef4444) 18%, transparent);\n\t\t\t\tborder-color: color-mix(in srgb, var(--roxy-danger, #ef4444) 45%, transparent);\n\t\t\t\tcolor: var(--roxy-fg, #0a0a0a);\n\t\t\t}\n\t\t\t.cho-tile.neutral {\n\t\t\t\tbackground: transparent;\n\t\t\t\tcolor: var(--roxy-fg, #0a0a0a);\n\t\t\t}\n\t\t\t.cho-tile.now {\n\t\t\t\toutline: 2px solid var(--roxy-accent, #f59e0b);\n\t\t\t\toutline-offset: 1px;\n\t\t\t\tbox-shadow: 0 0 0 4px\n\t\t\t\t\tcolor-mix(in srgb, var(--roxy-accent, #f59e0b) 18%, transparent);\n\t\t\t}\n\t\t\t.now-badge {\n\t\t\t\tdisplay: inline-block;\n\t\t\t\tmargin-left: 0.4em;\n\t\t\t\tfont-size: var(--roxy-text-xs, 0.75rem);\n\t\t\t\tfont-weight: var(--roxy-weight-bold, 600);\n\t\t\t\tcolor: var(--roxy-accent-fg, #b45309);\n\t\t\t\ttext-transform: uppercase;\n\t\t\t\tletter-spacing: 0.06em;\n\t\t\t}\n\t\t\t.tile-name {\n\t\t\t\tfont-size: var(--roxy-text-base, 1rem);\n\t\t\t\tfont-weight: var(--roxy-weight-bold, 600);\n\t\t\t\tgrid-column: 1;\n\t\t\t}\n\t\t\t.tile-time {\n\t\t\t\tfont-size: var(--roxy-text-xs, 0.75rem);\n\t\t\t\topacity: 0.8;\n\t\t\t\twhite-space: nowrap;\n\t\t\t\tgrid-column: 2;\n\t\t\t\tgrid-row: 1 / 3;\n\t\t\t\ttext-align: right;\n\t\t\t\talign-self: center;\n\t\t\t}\n\t\t\t.tile-lord {\n\t\t\t\tfont-size: var(--roxy-text-sm, 0.875rem);\n\t\t\t\topacity: 0.85;\n\t\t\t\tgrid-column: 1;\n\t\t\t\tdisplay: flex;\n\t\t\t\talign-items: center;\n\t\t\t\tgap: 0.25em;\n\t\t\t}\n\t\t`,\n\t];\n\n\t@property({ attribute: false })\n\tdata: GetChoghadiyaResponse | null = null;\n\n\t/**\n\t * True when the current wall-clock time falls inside this period. Both\n\t * `start` and `end` are ISO 8601 with timezone, so the comparison is\n\t * timezone-aware via the host's `Date` parsing.\n\t */\n\tprivate isCurrent(period: ChoghadiyaPeriod): boolean {\n\t\tconst now = Date.now();\n\t\tconst start = Date.parse(period.start);\n\t\tconst end = Date.parse(period.end);\n\t\tif (Number.isNaN(start) || Number.isNaN(end)) return false;\n\t\treturn now >= start && now < end;\n\t}\n\n\tprivate renderTile(period: ChoghadiyaPeriod) {\n\t\tconst effectClass =\n\t\t\tperiod.effect === 'Good'\n\t\t\t\t? 'good'\n\t\t\t\t: period.effect === 'Bad'\n\t\t\t\t\t? 'bad'\n\t\t\t\t\t: 'neutral';\n\t\tconst current = this.isCurrent(period);\n\t\tconst lordGlyph = PLANET_GLYPH[capitalize(period.lord)] ?? '';\n\t\tconst timeRange = `${fmtTime(period.start)} - ${fmtTime(period.end)}`;\n\t\treturn html`<div\n\t\t\tclass=\"cho-tile ${effectClass}${current ? ' now' : ''}\"\n\t\t\trole=\"listitem\"\n\t\t\taria-current=${current ? 'time' : 'false'}\n\t\t>\n\t\t\t<span class=\"tile-name\">\n\t\t\t\t${period.name}${current ? html`<span class=\"now-badge\">Now</span>` : nothing}\n\t\t\t</span>\n\t\t\t<span class=\"tile-time\" aria-label=\"Time range\">${timeRange}</span>\n\t\t\t<span class=\"tile-lord\">\n\t\t\t\t${lordGlyph ? html`<span aria-hidden=\"true\">${lordGlyph}</span>` : nothing}\n\t\t\t\t${period.lord}\n\t\t\t</span>\n\t\t</div>`;\n\t}\n\n\trender() {\n\t\tif (!this.data)\n\t\t\treturn html`<div class=\"roxy-empty\" role=\"status\">No choghadiya data</div>`;\n\n\t\tconst { date, dayChoghadiya, nightChoghadiya } = this.data;\n\n\t\treturn html`<div class=\"wrap\">\n\t\t\t<div class=\"header\">\n\t\t\t\t<h2 class=\"title\">Choghadiya</h2>\n\t\t\t\t${date ? html`<p class=\"subtitle\">${date}</p>` : nothing}\n\t\t\t</div>\n\n\t\t\t<div class=\"cho-grid\">\n\t\t\t\t<section class=\"period-col\" aria-label=\"Day muhurta periods\">\n\t\t\t\t\t<h3 class=\"period-heading\">Day</h3>\n\t\t\t\t\t<div role=\"list\" aria-label=\"Daytime choghadiya\">\n\t\t\t\t\t\t${\n\t\t\t\t\t\t\tdayChoghadiya && dayChoghadiya.length > 0\n\t\t\t\t\t\t\t\t? dayChoghadiya.map((p) => this.renderTile(p))\n\t\t\t\t\t\t\t\t: html`<p class=\"roxy-empty\" role=\"status\">No daytime periods</p>`\n\t\t\t\t\t\t}\n\t\t\t\t\t</div>\n\t\t\t\t</section>\n\n\t\t\t\t<section class=\"period-col\" aria-label=\"Night muhurta periods\">\n\t\t\t\t\t<h3 class=\"period-heading\">Night</h3>\n\t\t\t\t\t<div role=\"list\" aria-label=\"Nighttime choghadiya\">\n\t\t\t\t\t\t${\n\t\t\t\t\t\t\tnightChoghadiya && nightChoghadiya.length > 0\n\t\t\t\t\t\t\t\t? nightChoghadiya.map((p) => this.renderTile(p))\n\t\t\t\t\t\t\t\t: html`<p class=\"roxy-empty\" role=\"status\">No nighttime periods</p>`\n\t\t\t\t\t\t}\n\t\t\t\t\t</div>\n\t\t\t\t</section>\n\t\t\t</div>\n\t\t</div>`;\n\t}\n}\n\ndeclare global {\n\tinterface HTMLElementTagNameMap {\n\t\t'roxy-choghadiya-grid': RoxyChoghadiyaGrid;\n\t}\n}\n", "/**\n * Symbol constants used across components. Single source of truth so chart\n * wheels, card headers, hexagram displays, and panchang tables stay visually\n * consistent.\n */\n\nexport const PLANET_GLYPH: Record<string, string> = {\n\tSun: '\u2609',\n\tMoon: '\u263D',\n\tMercury: '\u263F',\n\tVenus: '\u2640',\n\tEarth: '\u2641',\n\tMars: '\u2642',\n\tJupiter: '\u2643',\n\tSaturn: '\u2644',\n\tUranus: '\u2645',\n\tNeptune: '\u2646',\n\tPluto: '\u2647',\n\tRahu: '\u260A',\n\tKetu: '\u260B',\n\tAscendant: 'Asc',\n\tLagna: 'La',\n\tNorthNode: '\u260A',\n\tSouthNode: '\u260B',\n\t'North node': '\u260A',\n\t'South node': '\u260B',\n\tChiron: '\u26B7',\n\tLilith: '\u26B8',\n\t'Black moon lilith': '\u26B8',\n};\n\nexport const PLANET_ABBR: Record<string, string> = {\n\tSun: 'Su',\n\tMoon: 'Mo',\n\tMercury: 'Me',\n\tVenus: 'Ve',\n\tMars: 'Ma',\n\tJupiter: 'Ju',\n\tSaturn: 'Sa',\n\tUranus: 'Ur',\n\tNeptune: 'Ne',\n\tPluto: 'Pl',\n\tRahu: 'Ra',\n\tKetu: 'Ke',\n\tAscendant: 'Asc',\n\tLagna: 'La',\n};\n\nexport const SIGN_GLYPH: Record<string, string> = {\n\tAries: '\u2648',\n\tTaurus: '\u2649',\n\tGemini: '\u264A',\n\tCancer: '\u264B',\n\tLeo: '\u264C',\n\tVirgo: '\u264D',\n\tLibra: '\u264E',\n\tScorpio: '\u264F',\n\tSagittarius: '\u2650',\n\tCapricorn: '\u2651',\n\tAquarius: '\u2652',\n\tPisces: '\u2653',\n};\n\nexport const SIGN_ABBR: Record<string, string> = {\n\tAries: 'Ar',\n\tTaurus: 'Ta',\n\tGemini: 'Ge',\n\tCancer: 'Cn',\n\tLeo: 'Le',\n\tVirgo: 'Vi',\n\tLibra: 'Li',\n\tScorpio: 'Sc',\n\tSagittarius: 'Sg',\n\tCapricorn: 'Cp',\n\tAquarius: 'Aq',\n\tPisces: 'Pi',\n};\n\nexport const SIGNS_ORDER = [\n\t'Aries',\n\t'Taurus',\n\t'Gemini',\n\t'Cancer',\n\t'Leo',\n\t'Virgo',\n\t'Libra',\n\t'Scorpio',\n\t'Sagittarius',\n\t'Capricorn',\n\t'Aquarius',\n\t'Pisces',\n] as const;\n\n/**\n * Lowercase rashi keys in canonical zodiac order. Derived from `SIGNS_ORDER`\n * so the two stay in lockstep. The /vedic-astrology/birth-chart response\n * carries planet buckets keyed by these names.\n */\nexport const RASHI_KEYS = SIGNS_ORDER.map((s) =>\n\ts.toLowerCase(),\n) as readonly Lowercase<(typeof SIGNS_ORDER)[number]>[];\n\n/** Aspect symbols. Used by synastry and natal chart aspect tables. */\nexport const ASPECT_SYMBOL: Record<string, string> = {\n\tconjunction: '\u260C',\n\topposition: '\u260D',\n\ttrine: '\u25B3',\n\tsquare: '\u25A1',\n\tsextile: '\u2731',\n\tquincunx: '\u22BB',\n\tsemisextile: '\u22BC',\n};\n\n/** Trigrams used by I Ching hexagrams. Eight trigrams compose 64 hexagrams. */\nexport const TRIGRAM_GLYPH: Record<string, string> = {\n\theaven: '\u2630',\n\tlake: '\u2631',\n\tfire: '\u2632',\n\tthunder: '\u2633',\n\twind: '\u2634',\n\twater: '\u2635',\n\tmountain: '\u2636',\n\tearth: '\u2637',\n\tHeaven: '\u2630',\n\tLake: '\u2631',\n\tFire: '\u2632',\n\tThunder: '\u2633',\n\tWind: '\u2634',\n\tWater: '\u2635',\n\tMountain: '\u2636',\n\tEarth: '\u2637',\n};\n\n/** Moon phase emoji set. Used by moon phase card. */\nexport const MOON_PHASE_EMOJI: Record<string, string> = {\n\t'new moon': '\uD83C\uDF11',\n\t'waxing crescent': '\uD83C\uDF12',\n\t'first quarter': '\uD83C\uDF13',\n\t'waxing gibbous': '\uD83C\uDF14',\n\t'full moon': '\uD83C\uDF15',\n\t'waning gibbous': '\uD83C\uDF16',\n\t'last quarter': '\uD83C\uDF17',\n\t'waning crescent': '\uD83C\uDF18',\n};\n", "import { css } from 'lit';\n\n/**\n * Shared host styles every component pulls in. Sets default font, color,\n * container query support, and the entry fade-in.\n */\nexport const baseStyles = css`\n\t:host {\n\t\tdisplay: block;\n\t\tcontainer-type: inline-size;\n\t\tfont-family: var(\n\t\t\t--roxy-font-sans,\n\t\t\tsystem-ui,\n\t\t\t-apple-system,\n\t\t\tBlinkMacSystemFont,\n\t\t\t'Segoe UI',\n\t\t\tRoboto,\n\t\t\tsans-serif\n\t\t);\n\t\tcolor: var(--roxy-fg, #0a0a0a);\n\t\tbackground: transparent;\n\t\tfont-size: var(--roxy-text-base, 1rem);\n\t\tline-height: var(--roxy-leading-normal, 1.5);\n\t\tanimation: roxy-fade-in var(--roxy-motion-duration, 200ms)\n\t\t\tvar(--roxy-motion-easing, cubic-bezier(0.4, 0, 0.2, 1)) both;\n\t}\n\n\t*,\n\t*::before,\n\t*::after {\n\t\tbox-sizing: border-box;\n\t}\n\n\t@keyframes roxy-fade-in {\n\t\tfrom {\n\t\t\topacity: 0;\n\t\t\ttransform: translateY(2px);\n\t\t}\n\t\tto {\n\t\t\topacity: 1;\n\t\t\ttransform: translateY(0);\n\t\t}\n\t}\n\n\t@media (prefers-reduced-motion: reduce) {\n\t\t:host {\n\t\t\tanimation: none;\n\t\t}\n\t}\n\n\t.roxy-skeleton {\n\t\tbackground: linear-gradient(\n\t\t\t90deg,\n\t\t\tvar(--roxy-border, #e4e4e7) 0%,\n\t\t\tcolor-mix(in srgb, var(--roxy-border, #e4e4e7) 60%, transparent) 50%,\n\t\t\tvar(--roxy-border, #e4e4e7) 100%\n\t\t);\n\t\tbackground-size: 200% 100%;\n\t\tanimation: roxy-shimmer 1.4s ease-in-out infinite;\n\t\tborder-radius: var(--roxy-radius-md, 8px);\n\t}\n\n\t@keyframes roxy-shimmer {\n\t\t0% {\n\t\t\tbackground-position: 200% 0;\n\t\t}\n\t\t100% {\n\t\t\tbackground-position: -200% 0;\n\t\t}\n\t}\n\n\t@media (prefers-reduced-motion: reduce) {\n\t\t.roxy-skeleton {\n\t\t\tanimation: none;\n\t\t}\n\t}\n\n\t.roxy-empty {\n\t\tpadding: var(--roxy-space-lg, 1.5rem);\n\t\tcolor: var(--roxy-muted, #71717a);\n\t\ttext-align: center;\n\t\tfont-size: var(--roxy-text-sm, 0.875rem);\n\t}\n\n\t:host(:focus-within) .roxy-card {\n\t\toutline: 2px solid var(--roxy-ring, rgba(245, 158, 11, 0.4));\n\t\toutline-offset: 2px;\n\t}\n\n\t/* Force the text-style variant on every Unicode glyph in the component.\n\t * macOS and iOS substitute coloured emoji glyphs for the planetary and\n\t * gender Unicode code points (Mars, Venus, Mercury, etc.) when the\n\t * system colour-emoji font wins font selection. The text-style variant\n\t * keeps glyphs monochrome so they inherit the surrounding fill colour\n\t * and match the brand palette consistently across platforms.\n\t *\n\t * font-variant-emoji is part of CSS Fonts 4 (Safari 17+, Chrome 134+,\n\t * Firefox 139+). On older browsers the rule is silently ignored.\n\t */\n\t:host {\n\t\tfont-variant-emoji: text;\n\t}\n`;\n", "/**\n * Shared string helpers used across components. Single source of truth so the\n * same formatting rules apply to every key/label/title that surfaces in the\n * shadow tree.\n *\n * - `capitalize`: title-cases the first character, lowercases the rest. Used\n * when matching API-supplied planet/sign names against the glyph maps in\n * `tokens/index.ts`, which use canonical TitleCase keys.\n * - `humanize`: turns an API key (`birth_date`, `birthDate`, `mahadasha-end`)\n * into a label suitable for display (\"Birth date\", \"Mahadasha end\").\n */\n\nexport function capitalize(s: string): string {\n\tif (!s) return '';\n\treturn s.charAt(0).toUpperCase() + s.slice(1).toLowerCase();\n}\n\nexport function humanize(s: string): string {\n\treturn s\n\t\t.replace(/[_-]+/g, ' ')\n\t\t.replace(/([a-z])([A-Z])/g, '$1 $2')\n\t\t.replace(/^\\w/, (c) => c.toUpperCase());\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["css", "css"]
|
|
7
7
|
}
|
|
@@ -97,6 +97,20 @@ var baseStyles = css`
|
|
|
97
97
|
outline: 2px solid var(--roxy-ring, rgba(245, 158, 11, 0.4));
|
|
98
98
|
outline-offset: 2px;
|
|
99
99
|
}
|
|
100
|
+
|
|
101
|
+
/* Force the text-style variant on every Unicode glyph in the component.
|
|
102
|
+
* macOS and iOS substitute coloured emoji glyphs for the planetary and
|
|
103
|
+
* gender Unicode code points (Mars, Venus, Mercury, etc.) when the
|
|
104
|
+
* system colour-emoji font wins font selection. The text-style variant
|
|
105
|
+
* keeps glyphs monochrome so they inherit the surrounding fill colour
|
|
106
|
+
* and match the brand palette consistently across platforms.
|
|
107
|
+
*
|
|
108
|
+
* font-variant-emoji is part of CSS Fonts 4 (Safari 17+, Chrome 134+,
|
|
109
|
+
* Firefox 139+). On older browsers the rule is silently ignored.
|
|
110
|
+
*/
|
|
111
|
+
:host {
|
|
112
|
+
font-variant-emoji: text;
|
|
113
|
+
}
|
|
100
114
|
`;
|
|
101
115
|
|
|
102
116
|
// packages/ui/src/utils/format.ts
|