cctally 1.10.0 → 1.10.2
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/CHANGELOG.md +10 -0
- package/bin/_cctally_dashboard.py +5 -3
- package/bin/_lib_blocks.py +74 -44
- package/bin/_lib_view_models.py +2 -0
- package/bin/cctally +79 -5
- package/dashboard/static/assets/{index-DUKjFlG8.js → index-Cy59E7Ru.js} +1 -1
- package/dashboard/static/dashboard.html +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,16 @@ based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
|
5
5
|
|
|
6
6
|
## [Unreleased]
|
|
7
7
|
|
|
8
|
+
## [1.10.2] - 2026-05-21
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
- `blocks` panel + CLI no longer renders a phantom ACTIVE heuristic block when a canonical 5h reset doesn't fall on a 10-minute boundary. The legacy partition predicate used `[R_floored - 5h, R_floored)` as the bucket interval, so floor-band entries — session timestamps inside `[floor(R), R)` (e.g. the 09:30–09:39:59 UTC band for a 09:39:59 reset) — fell into neither the preceding nor the following recorded bucket, dropped to `leftover`, and became a phantom heuristic block running `+5h` from `floor_to_hour(first_leftover_entry)`. With current-time activity in the band, that phantom block was `is_active=True` and overlapped the real canonical ACTIVE block, surfacing as TWO ACTIVE rows in `cctally blocks` and a `~HH:00` heuristic plus a `HH:40` recorded entry in the dashboard `/api/data` payload. The fix routes both the entry partition AND the recorded `Block` construction (start_time / end_time / is_active / burn / projection) through a single `_exact_interval(R)` helper that returns the canonical `(block_start_at, five_hour_resets_at)` from `five_hour_blocks` (jitter intact); `_load_recorded_five_hour_windows` grows a third return — `canonical_intervals: {R_floored → (bs_utc, rs_utc)}` — plumbed through `build_blocks_view`, `cmd_blocks`, `_dashboard_build_blocks_view`, and the `/api/block/:start_at` handler. Raw-only anchors (no canonical `five_hour_blocks` row) fall back to the legacy `(R - 5h, R)` shape. Credit-truncated anchors compose with the new path: the truncation rewrites the upper bound in-place inside `canonical_intervals` while preserving the override-supplied `bs`. Regression: new `tests/fixtures/blocks/floor-band-trap/` scenario (canonical reset at `T:39:59 UTC` with 8 dense entries in the trap band) locks the kernel behavior; new `test_block_detail_floor_band_trap_returns_exact_window` in `tests/test_dashboard_api_block.py` covers the panel ↔ detail consistency surface (clicking a block whose canonical reset is off the 10-min boundary returns 200 with the exact `bs` window instead of 404'ing against the floored bs). ([#76](https://github.com/omrikais/cctally-dev/issues/76))
|
|
12
|
+
|
|
13
|
+
## [1.10.1] - 2026-05-20
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
- dashboard static bundle: `dashboard/static/assets/index-*.js` now matches the TypeScript source. Three Projects-modal fixes that landed on `feat/projects-panel` in the final review round (drill stale-on-window-switch guard, persisted-selection re-bind on dropout, mobile sort cycle's `first_seen` direction) were applied to `dashboard/web/src/modals/*.tsx` but the regenerated Vite bundle was never committed, so the committed `dashboard/static/assets/index-DUKjFlG8.js` lagged the TSX by those three commits. Running `npm run build` (`tsc --noEmit && vite build`) produces `index-Cy59E7Ru.js` instead, and `dashboard/static/dashboard.html` now references it. The Python-side share `period_end` clip from the same review round shipped correctly on v1.10.0 via `bin/_cctally_dashboard.py`; this is purely a bundle-rebuild closure. CI regression: `dashboard-build-stability` job runs `git diff --exit-code dashboard/static/` after `npm run build`.
|
|
17
|
+
|
|
8
18
|
## [1.10.0] - 2026-05-20
|
|
9
19
|
|
|
10
20
|
### Added
|
|
@@ -2330,8 +2330,8 @@ def _dashboard_build_blocks_view(conn: "sqlite3.Connection",
|
|
|
2330
2330
|
entries = get_entries(fetch_start, fetch_end, skip_sync=skip_sync)
|
|
2331
2331
|
entries = [e for e in entries if week_start_at <= e.timestamp < week_end_at]
|
|
2332
2332
|
|
|
2333
|
-
recorded_windows, block_start_overrides =
|
|
2334
|
-
fetch_start, fetch_end
|
|
2333
|
+
recorded_windows, block_start_overrides, canonical_intervals = (
|
|
2334
|
+
_load_recorded_five_hour_windows(fetch_start, fetch_end)
|
|
2335
2335
|
)
|
|
2336
2336
|
c = _cctally()
|
|
2337
2337
|
return c.build_blocks_view(
|
|
@@ -2339,6 +2339,7 @@ def _dashboard_build_blocks_view(conn: "sqlite3.Connection",
|
|
|
2339
2339
|
now_utc=now_utc,
|
|
2340
2340
|
recorded_windows=recorded_windows,
|
|
2341
2341
|
block_start_overrides=block_start_overrides,
|
|
2342
|
+
canonical_intervals=canonical_intervals,
|
|
2342
2343
|
range_start=week_start_at,
|
|
2343
2344
|
range_end=week_end_at,
|
|
2344
2345
|
display_tz=display_tz,
|
|
@@ -5997,7 +5998,7 @@ class DashboardHTTPHandler(BaseHTTPRequestHandler):
|
|
|
5997
5998
|
now_utc = _command_as_of()
|
|
5998
5999
|
# Recorded-windows lookup widens by one block on each side so
|
|
5999
6000
|
# a recorded reset just outside the bounds can still anchor.
|
|
6000
|
-
recorded_windows, block_start_overrides = (
|
|
6001
|
+
recorded_windows, block_start_overrides, canonical_intervals = (
|
|
6001
6002
|
_load_recorded_five_hour_windows(
|
|
6002
6003
|
start_at - BLOCK_DURATION, end_at + BLOCK_DURATION,
|
|
6003
6004
|
)
|
|
@@ -6020,6 +6021,7 @@ class DashboardHTTPHandler(BaseHTTPRequestHandler):
|
|
|
6020
6021
|
entries_in_window, mode="auto",
|
|
6021
6022
|
recorded_windows=recorded_windows,
|
|
6022
6023
|
block_start_overrides=block_start_overrides,
|
|
6024
|
+
canonical_intervals=canonical_intervals,
|
|
6023
6025
|
now=now_utc,
|
|
6024
6026
|
)
|
|
6025
6027
|
target = next(
|
package/bin/_lib_blocks.py
CHANGED
|
@@ -95,6 +95,9 @@ def _group_entries_into_blocks(
|
|
|
95
95
|
*,
|
|
96
96
|
recorded_windows: list[dt.datetime] | None = None,
|
|
97
97
|
block_start_overrides: dict[dt.datetime, dt.datetime] | None = None,
|
|
98
|
+
canonical_intervals: dict[
|
|
99
|
+
dt.datetime, tuple[dt.datetime, dt.datetime]
|
|
100
|
+
] | None = None,
|
|
98
101
|
now: dt.datetime | None = None,
|
|
99
102
|
) -> list[Block]:
|
|
100
103
|
"""Group sorted UsageEntry objects into 5-hour blocks with gap detection.
|
|
@@ -103,21 +106,29 @@ def _group_entries_into_blocks(
|
|
|
103
106
|
The last block is marked active if now < block_start + 5h.
|
|
104
107
|
|
|
105
108
|
When `recorded_windows` is non-empty, entries whose timestamp falls in
|
|
106
|
-
|
|
107
|
-
into per-R buckets and built as 'recorded' blocks.
|
|
108
|
-
run through the existing gap-detection heuristic
|
|
109
|
+
the exact ``[bs, rs)`` interval of each accepted anchor are
|
|
110
|
+
partitioned into per-R buckets and built as 'recorded' blocks.
|
|
111
|
+
Leftover entries run through the existing gap-detection heuristic
|
|
112
|
+
(anchor='heuristic').
|
|
113
|
+
|
|
114
|
+
`canonical_intervals` (issue #76): an optional
|
|
115
|
+
``{R_floored → (bs_utc, rs_utc)}`` map carrying the EXACT
|
|
116
|
+
``(block_start_at, five_hour_resets_at)`` per accepted anchor. Drives
|
|
117
|
+
both the partition predicate AND Phase 1.5 ``Block`` construction
|
|
118
|
+
so floor-band entries (timestamps inside ``[floor(R), R)`` for a
|
|
119
|
+
canonical reset that doesn't fall on a 10-minute boundary) land in
|
|
120
|
+
the right bucket and the rendered window matches Anthropic's actual
|
|
121
|
+
interval. Anchors missing from the map fall back to ``(R - 5h, R)``
|
|
122
|
+
(the legacy floored shape) — preserves raw-only / pre-rollup
|
|
123
|
+
history behavior.
|
|
109
124
|
|
|
110
125
|
`block_start_overrides` (v1.7.2 round-5 / Bug J): an optional
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
``_load_recorded_five_hour_windows``
|
|
115
|
-
``
|
|
116
|
-
|
|
117
|
-
to the credit moment, but the block's API-derived START is
|
|
118
|
-
unchanged — without an override the renderer would compute
|
|
119
|
-
``start = truncated_R - 5h`` which is hours before the real start
|
|
120
|
-
and confuses the user with an off-by-hours window header).
|
|
126
|
+
``{R → block_start_at}`` map. Provides the same override semantics
|
|
127
|
+
for callers that don't pass ``canonical_intervals``. When BOTH are
|
|
128
|
+
present, ``canonical_intervals`` wins (the credit-truncation path
|
|
129
|
+
in ``_load_recorded_five_hour_windows`` writes a unified entry
|
|
130
|
+
into ``canonical_intervals`` already carrying the override-supplied
|
|
131
|
+
``bs`` and the truncated ``rs``).
|
|
121
132
|
|
|
122
133
|
`now` pins the current instant (typically via `_command_as_of()`). When
|
|
123
134
|
omitted, falls back to wall clock so existing callers are unaffected.
|
|
@@ -131,31 +142,44 @@ def _group_entries_into_blocks(
|
|
|
131
142
|
|
|
132
143
|
recorded_windows = sorted(recorded_windows or [])
|
|
133
144
|
block_start_overrides = block_start_overrides or {}
|
|
145
|
+
canonical_intervals = canonical_intervals or {}
|
|
146
|
+
|
|
147
|
+
# Single source of truth for the (bs, rs) interval of each accepted
|
|
148
|
+
# anchor — shared by the partition predicate below AND Phase 1.5
|
|
149
|
+
# block construction. issue #76: a 10-min-floored R as a partition
|
|
150
|
+
# boundary trapped floor-band entries into a phantom heuristic
|
|
151
|
+
# block whenever R was off the 10-min boundary; routing both
|
|
152
|
+
# surfaces through this helper keeps them consistent.
|
|
153
|
+
def _exact_interval(R: dt.datetime) -> tuple[dt.datetime, dt.datetime]:
|
|
154
|
+
if R in canonical_intervals:
|
|
155
|
+
return canonical_intervals[R]
|
|
156
|
+
bs = block_start_overrides.get(R, R - BLOCK_DURATION)
|
|
157
|
+
return (bs, R)
|
|
134
158
|
|
|
135
159
|
# ── Partition entries by recorded windows ──────────────────────────
|
|
136
160
|
# For each R in recorded_windows, entries whose timestamp falls in
|
|
137
|
-
# [
|
|
138
|
-
#
|
|
139
|
-
#
|
|
140
|
-
# grouper.
|
|
141
|
-
#
|
|
142
|
-
# Why override_start_or_R-5h, not always R-5h: a credit-truncated
|
|
143
|
-
# canonical block has R = effective_reset_at_utc (e.g. 17:58Z) but
|
|
144
|
-
# its real ``block_start_at`` is unchanged (e.g. 15:50Z). Using
|
|
145
|
-
# `R - 5h` as the partition floor would pull entries from earlier
|
|
146
|
-
# blocks (e.g. 12:58-15:50Z range) into the truncated bucket. The
|
|
147
|
-
# override keeps the real start so each entry lands in the bucket
|
|
148
|
-
# whose API-defined interval actually contains it.
|
|
161
|
+
# [bs, rs) (the EXACT canonical interval, NOT the 10-min-floored
|
|
162
|
+
# shape) go into recorded_buckets[R]. Everything else (gaps between
|
|
163
|
+
# recorded windows, or fully outside any window) drops into
|
|
164
|
+
# `leftover` and runs through the existing heuristic grouper.
|
|
149
165
|
recorded_buckets: dict[dt.datetime, list[UsageEntry]] = {
|
|
150
166
|
R: [] for R in recorded_windows
|
|
151
167
|
}
|
|
152
168
|
leftover: list[UsageEntry] = []
|
|
169
|
+
# Sort the (interval, R) pairs by rs so bisect_right(rs_keys, ts)
|
|
170
|
+
# locates the candidate window in O(log n) per entry.
|
|
171
|
+
sorted_intervals: list[
|
|
172
|
+
tuple[tuple[dt.datetime, dt.datetime], dt.datetime]
|
|
173
|
+
] = sorted(
|
|
174
|
+
[(_exact_interval(R), R) for R in recorded_windows],
|
|
175
|
+
key=lambda item: item[0][1],
|
|
176
|
+
)
|
|
177
|
+
rs_keys = [iv[0][1] for iv in sorted_intervals]
|
|
153
178
|
for entry in entries_sorted:
|
|
154
|
-
idx = bisect.bisect_right(
|
|
155
|
-
if idx < len(
|
|
156
|
-
R =
|
|
157
|
-
|
|
158
|
-
if bucket_start <= entry.timestamp:
|
|
179
|
+
idx = bisect.bisect_right(rs_keys, entry.timestamp)
|
|
180
|
+
if idx < len(sorted_intervals):
|
|
181
|
+
(bs, rs), R = sorted_intervals[idx]
|
|
182
|
+
if bs <= entry.timestamp < rs:
|
|
159
183
|
recorded_buckets[R].append(entry)
|
|
160
184
|
continue
|
|
161
185
|
leftover.append(entry)
|
|
@@ -192,17 +216,22 @@ def _group_entries_into_blocks(
|
|
|
192
216
|
|
|
193
217
|
# Clamp each raw_block's end so it cannot overlap a later recorded
|
|
194
218
|
# window. Entries in `leftover` are by construction earlier than the
|
|
195
|
-
# next recorded
|
|
196
|
-
# PREVIOUS 5h window that ended no later than that boundary.
|
|
197
|
-
# this clamp, the +5h heuristic span can cross into the
|
|
198
|
-
# window and produce two simultaneously-active rows.
|
|
219
|
+
# next recorded window's real ``bs``, so the heuristic block belongs
|
|
220
|
+
# to a PREVIOUS 5h window that ended no later than that boundary.
|
|
221
|
+
# Without this clamp, the +5h heuristic span can cross into the
|
|
222
|
+
# recorded window and produce two simultaneously-active rows.
|
|
223
|
+
# issue #76: use the EXACT ``bs`` from ``_exact_interval`` so the
|
|
224
|
+
# clamp matches the partition predicate above (using a floored
|
|
225
|
+
# ``R - 5h`` would leave a sliver of overlap whenever bs sits in
|
|
226
|
+
# the 10-min floor band).
|
|
199
227
|
if recorded_windows:
|
|
200
228
|
for rb in raw_blocks:
|
|
201
229
|
idx = bisect.bisect_right(recorded_windows, rb["start"])
|
|
202
230
|
if idx < len(recorded_windows):
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
231
|
+
next_R = recorded_windows[idx]
|
|
232
|
+
next_bs, _next_rs = _exact_interval(next_R)
|
|
233
|
+
if rb["start"] < next_bs < rb["end"]:
|
|
234
|
+
rb["end"] = next_bs
|
|
206
235
|
|
|
207
236
|
# Track the "actual first entry timestamp" for each block so Phase 3
|
|
208
237
|
# can compute gap ends the same way the legacy interleaved code did
|
|
@@ -210,18 +239,19 @@ def _group_entries_into_blocks(
|
|
|
210
239
|
# floor-to-hour window start). Maps id(block) -> actual first ts.
|
|
211
240
|
first_entry_ts_by_block: dict[int, dt.datetime] = {}
|
|
212
241
|
|
|
213
|
-
# Phase 1.5: Build recorded Block objects from non-empty buckets
|
|
242
|
+
# Phase 1.5: Build recorded Block objects from non-empty buckets.
|
|
243
|
+
# issue #76: ``start_time`` / ``end_time`` come from the SAME
|
|
244
|
+
# ``_exact_interval(R)`` that drives the partition predicate above.
|
|
245
|
+
# Without this, a canonical reset off the 10-min boundary would
|
|
246
|
+
# render with the floored window (off by up to 9m59s) and
|
|
247
|
+
# ``is_active`` / burn / projection would compute against the
|
|
248
|
+
# wrong endpoints, even though the partition was correct.
|
|
214
249
|
recorded_block_objs: list[Block] = []
|
|
215
250
|
for R in recorded_windows:
|
|
216
251
|
bucket = recorded_buckets[R]
|
|
217
252
|
if not bucket:
|
|
218
253
|
continue
|
|
219
|
-
|
|
220
|
-
# canonical blocks need their real block_start_at so the
|
|
221
|
-
# rendered window header matches Anthropic's actual interval);
|
|
222
|
-
# default to R - BLOCK_DURATION for normal canonical anchors.
|
|
223
|
-
start_time = block_start_overrides.get(R, R - BLOCK_DURATION)
|
|
224
|
-
end_time = R
|
|
254
|
+
start_time, end_time = _exact_interval(R)
|
|
225
255
|
bucket_sorted = sorted(bucket, key=lambda e: e.timestamp)
|
|
226
256
|
blk = _build_activity_block(
|
|
227
257
|
bucket_sorted, start_time, end_time, now, mode,
|
package/bin/_lib_view_models.py
CHANGED
|
@@ -1146,6 +1146,7 @@ def build_blocks_view(
|
|
|
1146
1146
|
now_utc,
|
|
1147
1147
|
recorded_windows=None,
|
|
1148
1148
|
block_start_overrides=None,
|
|
1149
|
+
canonical_intervals=None,
|
|
1149
1150
|
range_start=None,
|
|
1150
1151
|
range_end=None,
|
|
1151
1152
|
display_tz=None,
|
|
@@ -1191,6 +1192,7 @@ def build_blocks_view(
|
|
|
1191
1192
|
mode=mode,
|
|
1192
1193
|
recorded_windows=recorded_windows,
|
|
1193
1194
|
block_start_overrides=block_start_overrides,
|
|
1195
|
+
canonical_intervals=canonical_intervals,
|
|
1194
1196
|
now=now_utc,
|
|
1195
1197
|
)
|
|
1196
1198
|
rows: list = []
|
package/bin/cctally
CHANGED
|
@@ -3401,10 +3401,42 @@ def _select_non_overlapping_recorded_windows(
|
|
|
3401
3401
|
def _load_recorded_five_hour_windows(
|
|
3402
3402
|
range_start: dt.datetime,
|
|
3403
3403
|
range_end: dt.datetime,
|
|
3404
|
-
) -> tuple[
|
|
3404
|
+
) -> tuple[
|
|
3405
|
+
list[dt.datetime],
|
|
3406
|
+
dict[dt.datetime, dt.datetime],
|
|
3407
|
+
dict[dt.datetime, tuple[dt.datetime, dt.datetime]],
|
|
3408
|
+
]:
|
|
3405
3409
|
"""Return sorted, UTC-aware recorded ``five_hour_resets_at`` values
|
|
3406
3410
|
that anchor real 5h windows in ``[range_start, range_end]``.
|
|
3407
3411
|
|
|
3412
|
+
Returns a 3-tuple ``(selected, block_start_overrides, canonical_intervals)``:
|
|
3413
|
+
|
|
3414
|
+
* ``selected``: list of 10-min-floored ``R`` anchors (sorted),
|
|
3415
|
+
each representing one accepted canonical 5h window. Same shape
|
|
3416
|
+
as before — drives `_group_entries_into_blocks`'s
|
|
3417
|
+
``recorded_windows=`` kwarg.
|
|
3418
|
+
|
|
3419
|
+
* ``block_start_overrides``: ``{R_floored → block_start_at_utc}``
|
|
3420
|
+
for credit-truncated anchors (Bug J). When a credit moment
|
|
3421
|
+
falls inside a canonical block's overlap with the next block,
|
|
3422
|
+
the earlier ``R`` is replaced by the credit moment (floored to
|
|
3423
|
+
10 min) and the original ``block_start_at`` is recorded here so
|
|
3424
|
+
the renderer keeps the real display start.
|
|
3425
|
+
|
|
3426
|
+
* ``canonical_intervals``: ``{R_floored → (bs_utc, rs_utc)}``
|
|
3427
|
+
carrying the **exact** ``(block_start_at, five_hour_resets_at)``
|
|
3428
|
+
for every selected anchor that has a canonical
|
|
3429
|
+
``five_hour_blocks`` row. ``rs_utc`` is the un-floored reset
|
|
3430
|
+
moment (jitter intact), ``bs_utc`` is the API-derived block
|
|
3431
|
+
start normalized to UTC. Drives `_group_entries_into_blocks`'s
|
|
3432
|
+
partition predicate AND Phase 1.5 block construction
|
|
3433
|
+
(issue #76 — 10-min-floor partition trap). Anchors with no
|
|
3434
|
+
canonical row (legacy weekly-snapshots-only) are absent from
|
|
3435
|
+
the map and the partitioner falls back to ``(R - 5h, R)``.
|
|
3436
|
+
Credit-truncated anchors land here with the truncated upper
|
|
3437
|
+
bound (``rs = effective_reset``) and the override-supplied
|
|
3438
|
+
``bs`` (the real pre-truncation block start).
|
|
3439
|
+
|
|
3408
3440
|
Two sources contribute to the merged anchor set:
|
|
3409
3441
|
|
|
3410
3442
|
1. ``weekly_usage_snapshots.five_hour_resets_at`` — every
|
|
@@ -3515,7 +3547,7 @@ def _load_recorded_five_hour_windows(
|
|
|
3515
3547
|
# OSError covers ensure_dirs() failures (read-only FS, permission
|
|
3516
3548
|
# denied on parent dir) that propagate from open_db() before any
|
|
3517
3549
|
# SQL runs. Either way, fall back to the heuristic anchor path.
|
|
3518
|
-
return [], {}
|
|
3550
|
+
return [], {}, {}
|
|
3519
3551
|
counts: dict[dt.datetime, int] = {}
|
|
3520
3552
|
for row in rows:
|
|
3521
3553
|
raw = row["five_hour_resets_at"] if hasattr(row, "keys") else row[0]
|
|
@@ -3571,6 +3603,21 @@ def _load_recorded_five_hour_windows(
|
|
|
3571
3603
|
canonical_pairs.append((bs, rs))
|
|
3572
3604
|
canonical_pairs.sort(key=lambda p: p[0])
|
|
3573
3605
|
|
|
3606
|
+
# issue #76: canonical_intervals maps every floored R -> its EXACT
|
|
3607
|
+
# (block_start_at, five_hour_resets_at) — both UTC, rs un-floored
|
|
3608
|
+
# (jitter intact). Drives the partition predicate AND Phase 1.5
|
|
3609
|
+
# block construction in `_group_entries_into_blocks` so floor-band
|
|
3610
|
+
# entries (timestamps in [floor(R), R)) land in the right bucket
|
|
3611
|
+
# and the displayed window matches Anthropic's actual interval.
|
|
3612
|
+
# Built before the credit-truncation loop below so that loop can
|
|
3613
|
+
# rewrite the upper bound in-place (truncated R replaces rs).
|
|
3614
|
+
canonical_intervals: dict[
|
|
3615
|
+
dt.datetime, tuple[dt.datetime, dt.datetime]
|
|
3616
|
+
] = {}
|
|
3617
|
+
for bs, rs in canonical_pairs:
|
|
3618
|
+
snapped = _floor_to_ten_minutes(rs)
|
|
3619
|
+
canonical_intervals[snapped] = (bs, rs)
|
|
3620
|
+
|
|
3574
3621
|
# Detect overlap-with-credit and replace the earlier R with a
|
|
3575
3622
|
# credit-truncated anchor. The (anchor → real_block_start) map is
|
|
3576
3623
|
# returned alongside the anchor list so the renderer can show the
|
|
@@ -3595,6 +3642,21 @@ def _load_recorded_five_hour_windows(
|
|
|
3595
3642
|
if bs < cm_floored < rs:
|
|
3596
3643
|
truncated_R = cm_floored
|
|
3597
3644
|
block_start_overrides[cm_floored] = bs
|
|
3645
|
+
# Rewrite canonical_intervals[snapped_orig]
|
|
3646
|
+
# to the truncated interval under the
|
|
3647
|
+
# truncated key. issue #76: the
|
|
3648
|
+
# partitioner reads canonical_intervals
|
|
3649
|
+
# for the exact bs/rs; the truncated entry
|
|
3650
|
+
# must reflect the credit-shifted upper
|
|
3651
|
+
# bound (cm_floored) AND the real bs (the
|
|
3652
|
+
# override) so partition + Phase 1.5
|
|
3653
|
+
# render the credit-shortened block
|
|
3654
|
+
# consistently.
|
|
3655
|
+
snapped_orig = _floor_to_ten_minutes(rs)
|
|
3656
|
+
canonical_intervals.pop(snapped_orig, None)
|
|
3657
|
+
canonical_intervals[cm_floored] = (
|
|
3658
|
+
bs, cm_floored,
|
|
3659
|
+
)
|
|
3598
3660
|
break
|
|
3599
3661
|
truncated_pairs.append((bs, truncated_R))
|
|
3600
3662
|
|
|
@@ -3634,7 +3696,16 @@ def _load_recorded_five_hour_windows(
|
|
|
3634
3696
|
selected = sorted(
|
|
3635
3697
|
list(selected_non_truncated) + list(truncated_anchors)
|
|
3636
3698
|
)
|
|
3637
|
-
|
|
3699
|
+
# Filter canonical_intervals down to selected anchors. Raw-only
|
|
3700
|
+
# anchors (selected via weekly_usage_snapshots but absent from
|
|
3701
|
+
# five_hour_blocks) stay out of the map; the partitioner falls
|
|
3702
|
+
# back to (R - 5h, R) for them. issue #76 / spec §1.1 D1.
|
|
3703
|
+
canonical_intervals = {
|
|
3704
|
+
R: canonical_intervals[R]
|
|
3705
|
+
for R in selected
|
|
3706
|
+
if R in canonical_intervals
|
|
3707
|
+
}
|
|
3708
|
+
return selected, block_start_overrides, canonical_intervals
|
|
3638
3709
|
|
|
3639
3710
|
|
|
3640
3711
|
def cmd_blocks(args: argparse.Namespace) -> int:
|
|
@@ -3679,8 +3750,10 @@ def cmd_blocks(args: argparse.Namespace) -> int:
|
|
|
3679
3750
|
# reset R just after ``range_end`` (e.g. the active window when
|
|
3680
3751
|
# range_end is wall-clock "now") can still anchor entries that fall
|
|
3681
3752
|
# inside [range_start, range_end].
|
|
3682
|
-
recorded_windows, block_start_overrides =
|
|
3683
|
-
|
|
3753
|
+
recorded_windows, block_start_overrides, canonical_intervals = (
|
|
3754
|
+
_load_recorded_five_hour_windows(
|
|
3755
|
+
range_start - BLOCK_DURATION, range_end + BLOCK_DURATION,
|
|
3756
|
+
)
|
|
3684
3757
|
)
|
|
3685
3758
|
|
|
3686
3759
|
# Group into blocks via the view-model kernel (issue #56). The
|
|
@@ -3700,6 +3773,7 @@ def cmd_blocks(args: argparse.Namespace) -> int:
|
|
|
3700
3773
|
now_utc=now_utc,
|
|
3701
3774
|
recorded_windows=recorded_windows,
|
|
3702
3775
|
block_start_overrides=block_start_overrides,
|
|
3776
|
+
canonical_intervals=canonical_intervals,
|
|
3703
3777
|
range_start=range_start,
|
|
3704
3778
|
range_end=range_end,
|
|
3705
3779
|
display_tz=tz,
|
|
@@ -15,4 +15,4 @@ Error generating stack: `+e.message+`
|
|
|
15
15
|
`]},t):e.type===`exit`?(0,z.jsxs)(`span`,{className:`update-stream-exit`,children:[`(exited rc=${e.rc??`?`})`,`
|
|
16
16
|
`]},t):(0,z.jsxs)(`span`,{className:`update-stream-line`,children:[e.data??``,`
|
|
17
17
|
`]},t))]})}var Co=3e3,wo=1e3;function To(e){if(e==null)return`0s`;let t=Math.max(0,Math.round((Date.now()-e)/1e3));return t<60?`${t}s`:`${Math.floor(t/60)}m ${t%60}s`}function Eo(){let e=(0,g.useSyncExternalStore)(L,()=>I().update),t=e.runId,n=e.startedAt,r=e.state?.update_command??``,i=e.state?.latest_version??``,[,a]=(0,g.useState)(0);(0,g.useEffect)(()=>{let e=window.setInterval(()=>a(e=>e+1),1e3);return()=>window.clearInterval(e)},[]);let o=(0,g.useRef)(!1);return(0,g.useEffect)(()=>{if(!t)return;let e=null,n=null,r=null,i=!1;o.current=!0;function a(){r!=null&&(window.clearTimeout(r),r=null),o.current=!1}function s(t,n){a();let r={};try{t instanceof MessageEvent&&typeof t.data==`string`&&(r=JSON.parse(t.data))}catch{}if(R({type:`APPEND_UPDATE_STREAM`,event:{type:n,data:typeof r.data==`string`?r.data:void 0,name:typeof r.name==`string`?r.name:void 0,rc:typeof r.rc==`number`?r.rc:void 0,step:typeof r.step==`string`?r.step:void 0,message:typeof r.message==`string`?r.message:void 0,ts:typeof r.ts==`number`?r.ts:void 0}}),n===`exit`){let e=typeof r.rc==`number`?r.rc:-1;e!==0&&R({type:`SET_UPDATE_STATUS`,status:`failed`,errorMessage:`subprocess exited with rc=${e}`})}else n===`execvp`?R({type:`SET_UPDATE_STATUS`,status:`success`}):n===`error_event`?R({type:`SET_UPDATE_STATUS`,status:`failed`,errorMessage:typeof r.message==`string`?r.message:`update worker error`}):n===`done`&&(e&&=(e.close(),null))}function c(){n??=window.setInterval(async()=>{if(!i)try{let e=await fetch(`/api/update/status`);if(!e.ok)return;let t=await e.json(),r=t?.current_run_id??null,i=t?.state??{};if(r===null){let e=i?.current_version,t=i?.latest_version,r=I().update;typeof e==`string`&&typeof t==`string`&&e===t?R({type:`SET_UPDATE_STATUS`,status:`success`}):r.status===`running`&&R({type:`SET_UPDATE_STATUS`,status:`failed`,errorMessage:`update worker exited (stream unavailable)`}),r.stream.length===0&&R({type:`APPEND_UPDATE_STREAM`,event:{type:`stdout`,data:`(SSE stream unavailable; install completed in background — see ~/.local/share/cctally/update.log for full output)`}}),n!=null&&(window.clearInterval(n),n=null)}}catch{}},wo)}r=window.setTimeout(()=>{i||o.current&&(o.current=!1,e&&=(e.close(),null),c())},Co);try{e=new EventSource(`/api/update/stream/${encodeURIComponent(t)}`),e.addEventListener(`message`,e=>s(e,`stdout`)),[`stdout`,`stderr`,`step`,`exit`,`execvp`,`error_event`,`done`,`heartbeat`].forEach(t=>{e.addEventListener(t,e=>s(e,t))}),e.onerror=()=>{o.current&&(a(),e&&=(e.close(),null),c())}}catch{a(),c()}return()=>{i=!0,r!=null&&(window.clearTimeout(r),r=null),n!=null&&(window.clearInterval(n),n=null),e&&=(e.close(),null),o.current=!1,nt()}},[t]),(0,z.jsxs)(`div`,{className:`update-modal-body`,children:[(0,z.jsxs)(`div`,{className:`update-running-row`,children:[(0,z.jsx)(`span`,{className:`update-spinner`,"aria-hidden":`true`,children:`⟳`}),(0,z.jsx)(`code`,{className:`update-cmd update-cmd-inline`,children:r||`updating cctally`}),(0,z.jsxs)(`span`,{className:`update-elapsed`,children:[To(n),` elapsed`]})]}),(0,z.jsx)(Y,{events:e.stream}),(0,z.jsxs)(`p`,{className:`update-stream-cap`,children:[`Output streams over SSE · press Esc to hide (install continues to `,i||`latest`,`)`]})]})}var Do=1500;function Oo(e){if(e==null)return`—`;let t=Math.max(0,Math.round((Date.now()-e)/1e3));return t<60?`${t}s`:`${Math.floor(t/60)}m ${t%60}s`}function ko(){let e=(0,g.useSyncExternalStore)(L,()=>I().update),t=e.startedAt,n=e.state?.update_command??``,r=e.state?.latest_version??``;return(0,g.useEffect)(()=>{let e=window.setInterval(()=>{nt()},Do);return()=>window.clearInterval(e)},[]),(0,z.jsxs)(`div`,{className:`update-modal-body`,children:[(0,z.jsxs)(`div`,{className:`update-running-row update-running-row-success`,children:[(0,z.jsx)(`span`,{className:`update-check`,"aria-hidden":`true`,children:`✓`}),(0,z.jsx)(`code`,{className:`update-cmd update-cmd-inline`,children:n||`cctally`}),(0,z.jsxs)(`span`,{className:`update-elapsed`,children:[`finished in `,Oo(t)]})]}),(0,z.jsxs)(`div`,{className:`update-row-label`,children:[`Restarting dashboard on the new code`,r?` (${r})`:``,`…`]}),(0,z.jsxs)(`div`,{className:`update-running-row`,children:[(0,z.jsx)(`span`,{className:`update-spinner`,"aria-hidden":`true`,children:`⟳`}),(0,z.jsx)(`span`,{className:`update-success-reconnect`,children:`reconnecting (this page will refresh in a moment)`})]})]})}var Ao=12;function jo(e,t){for(let t=e.length-1;t>=0;t--){let n=e[t];if(n.type===`exit`&&typeof n.rc==`number`)return`exited rc=${n.rc}`;if(n.type===`error_event`)return n.message??`worker error`}return t??`unknown failure`}function Mo(){let e=(0,g.useSyncExternalStore)(L,()=>I().update),[t,n]=(0,g.useState)(`idle`),r=e.state?.update_command??``,i=e.stream.filter(e=>e.type===`stderr`&&e.data).map(e=>e.data).slice(-Ao),a=jo(e.stream,e.errorMessage);function o(){R({type:`RESET_UPDATE_RUN`}),rt()}async function s(){if(r)try{await navigator.clipboard.writeText(r),n(`ok`),window.setTimeout(()=>n(`idle`),1500)}catch{n(`err`),window.setTimeout(()=>n(`idle`),1500)}}return(0,z.jsxs)(`div`,{className:`update-modal-body`,children:[(0,z.jsxs)(`div`,{className:`update-running-row update-running-row-failed`,children:[(0,z.jsx)(`span`,{className:`update-x`,"aria-hidden":`true`,children:`✗`}),(0,z.jsx)(`code`,{className:`update-cmd update-cmd-inline`,children:r||`cctally update`}),(0,z.jsx)(`span`,{className:`update-elapsed`,children:a})]}),i.length>0?(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`div`,{className:`update-row-label`,children:[`stderr (last `,i.length,` line`,i.length===1?``:`s`,`)`]}),(0,z.jsx)(`pre`,{className:`update-stream update-stream-fail`,children:i.map((e,t)=>(0,z.jsxs)(`span`,{className:`update-stream-line err`,children:[e,`
|
|
18
|
-
`]},t))})]}):(0,z.jsx)(`p`,{className:`update-manual-note`,children:e.errorMessage??`See ~/.local/share/cctally/update.log for the full failure log.`}),(0,z.jsxs)(`p`,{className:`update-stream-cap`,children:[`Full log: `,(0,z.jsx)(`code`,{children:`~/.local/share/cctally/update.log`})]}),(0,z.jsxs)(`div`,{className:`update-actions`,children:[(0,z.jsx)(`button`,{type:`button`,className:`update-btn update-btn-primary`,onClick:o,children:`Retry`}),(0,z.jsx)(`button`,{type:`button`,className:`update-btn`,onClick:s,disabled:!r,children:t===`ok`?`Copied!`:t===`err`?`Copy failed`:`Copy command`}),(0,z.jsx)(`button`,{type:`button`,className:`update-btn`,onClick:()=>ot.close(),children:`Close`})]})]})}var No={idle:`Update available`,running:`Updating cctally`,success:`Update complete`,failed:`Update failed`},Po={idle:`accent-amber`,running:`accent-amber`,success:`accent-green`,failed:`accent-red`};function Fo(){let e=(0,g.useSyncExternalStore)(L,()=>I().update),t=()=>R({type:`CLOSE_UPDATE_MODAL`});if(V((0,g.useMemo)(()=>[{key:`Escape`,scope:`modal`,action:t,when:()=>I().update.modalOpen}],[])),!e.modalOpen||!e.state)return null;let n=e.status,r=Po[n]??`accent-amber`,i=No[n]??`Update`;n===`running`&&e.state.latest_version?i=`Updating cctally → ${e.state.latest_version}`:n===`success`&&e.state.latest_version&&(i=`Update complete → ${e.state.latest_version}`);let a;switch(n){case`running`:a=(0,z.jsx)(Eo,{});break;case`success`:a=(0,z.jsx)(ko,{});break;case`failed`:a=(0,z.jsx)(Mo,{});break;default:a=(0,z.jsx)(So,{});break}return(0,z.jsxs)(`div`,{id:`update-modal-root`,className:`update-modal-root`,children:[(0,z.jsx)(`div`,{className:`modal-backdrop`,onClick:t}),(0,z.jsxs)(`div`,{className:`modal-card update-modal-card ${r}`,role:`dialog`,"aria-modal":`true`,"aria-labelledby":`update-modal-title`,children:[(0,z.jsx)(`div`,{className:`modal-handle`,"aria-hidden":`true`}),(0,z.jsxs)(`header`,{className:`modal-header`,children:[(0,z.jsx)(`h2`,{id:`update-modal-title`,children:i}),(0,z.jsx)(`button`,{className:`modal-close`,"aria-label":`Close`,onClick:t,children:`×`})]}),(0,z.jsx)(`div`,{className:`modal-body`,children:a})]})]})}function Io({title:e,accentClass:t,children:n,headerExtras:r}){let i=()=>R({type:`CLOSE_MODAL`});return V((0,g.useMemo)(()=>[{key:`Escape`,scope:`modal`,action:i}],[])),(0,z.jsxs)(`div`,{id:`modal-root`,children:[(0,z.jsx)(`div`,{className:`modal-backdrop`,onClick:i}),(0,z.jsxs)(`div`,{className:`modal-card ${t}`,role:`dialog`,"aria-modal":`true`,"aria-labelledby":`modal-title`,children:[(0,z.jsx)(`div`,{className:`modal-handle`,"aria-hidden":`true`}),(0,z.jsxs)(`header`,{className:`modal-header`,children:[(0,z.jsx)(`h2`,{id:`modal-title`,children:e}),r,(0,z.jsx)(`button`,{className:`modal-close`,"aria-label":`Close`,onClick:i,children:`×`})]}),(0,z.jsx)(`div`,{id:`modal-body`,className:`modal-body`,children:n})]})]})}function Lo(e){return e==null||!isFinite(e)?0:Math.max(0,Math.min(100,e))}function Ro(e,t,n){let r=D.dateShort(t,n);return e&&r?`${e} → ${r}`:e||(r?`→ ${r}`:`—`)}function zo(e){if(e==null||!isFinite(e))return[`—`,``];let t=(+e).toFixed(1),n=t.indexOf(`.`);return n===-1?[t,`.0%`]:[t.slice(0,n),t.slice(n)+`%`]}function Bo(e){let t=[],n=[...e].sort((e,t)=>(e.percent??0)-(t.percent??0));for(let e of n)e.percent!=null&&(t.length&&e.percent-(t[t.length-1].percent??0)<3||t.push(e));return t}function Vo(e){if(!Array.isArray(e)||e.length<2)return null;let t=e.map(e=>e.marginal_usd).filter(e=>e!=null&&isFinite(e)),n=t.length?t.reduce((e,t)=>e+t,0)/t.length:null,r=e[e.length-1].percent,i=[];return n!=null&&i.push(`avg marginal $`+n.toFixed(2)),r!=null&&i.push(`latest at `+r+`%`),i.length?i.join(` · `):null}function Ho(e,t){let n=[];for(let t of e)n.push({kind:`milestone`,ts:t.captured_at_utc,data:t});for(let e of t)n.push({kind:`credit`,ts:e.effective_reset_at_utc,data:e});return n.sort((e,t)=>e.ts.localeCompare(t.ts)),n}function Uo(){let e=Ke(),t=Ht(),n={tz:t.resolvedTz,offsetLabel:t.offsetLabel},r=e?.current_week??null,i=e?.header??null,a=Array.isArray(r?.milestones)?r.milestones:[],o=Array.isArray(r?.five_hour_milestones)?r.five_hour_milestones:[],s=Ho(o,Array.isArray(r?.five_hour_block?.credits)?r.five_hour_block.credits:[]),c=Lo(r?.used_pct),[l,u]=zo(r?.used_pct),d=r?Ro(i?.week_label,r.reset_at_utc,n):`—`,f=Bo(a),p=Vo(a);return(0,z.jsx)(Io,{title:`Current Week — per-percent milestones`,accentClass:`accent-green`,headerExtras:(0,z.jsx)(Gt,{panel:`current-week`,panelLabel:`Current week`,triggerId:`current-week-modal`,onClick:()=>R(N(`current-week`,`current-week-modal`))}),children:(0,z.jsxs)(`section`,{className:`modal-current-week`,children:[(0,z.jsx)(`div`,{className:`m-chipstrip`,id:`mcw-badges`,children:(0,z.jsx)(`span`,{className:`m-pill accent-green`,id:`mcw-week-pill`,children:d})}),(0,z.jsxs)(`div`,{className:`mcw-herobar`,children:[(0,z.jsxs)(`div`,{className:`mcw-bignum`,id:`mcw-bignum`,children:[(0,z.jsx)(`span`,{className:`int`,children:l}),(0,z.jsx)(`span`,{className:`unit`,children:u})]}),(0,z.jsxs)(`div`,{className:`mcw-pbar-wrap`,children:[(0,z.jsxs)(`div`,{className:`mcw-pbar`,children:[(0,z.jsx)(`div`,{className:`fill`,id:`mcw-fill`,style:{width:c+`%`}}),(0,z.jsx)(`div`,{className:`ticks`,id:`mcw-ticks`,children:f.map(e=>(0,z.jsx)(`div`,{className:`tick`,"data-p":String(e.percent),style:{left:Lo(e.percent)+`%`}},e.percent))}),(0,z.jsx)(`div`,{className:`marker`,id:`mcw-marker`,style:{left:c+`%`}})]}),(0,z.jsxs)(`div`,{className:`mcw-pscale`,children:[(0,z.jsx)(`span`,{children:`0%`}),(0,z.jsx)(`span`,{children:`25%`}),(0,z.jsx)(`span`,{children:`50%`}),(0,z.jsx)(`span`,{children:`75%`}),(0,z.jsx)(`span`,{children:`100%`})]})]}),(0,z.jsxs)(`div`,{className:`mcw-mini`,id:`mcw-mini`,children:[(0,z.jsxs)(`div`,{className:`s`,children:[(0,z.jsx)(`span`,{className:`k`,children:`spent`}),(0,z.jsx)(`span`,{className:`v v-magenta`,id:`mcw-spent`,children:D.usd2(r?.spent_usd)})]}),(0,z.jsxs)(`div`,{className:`s`,children:[(0,z.jsx)(`span`,{className:`k`,children:`$ / 1%`}),(0,z.jsx)(`span`,{className:`v v-cyan`,id:`mcw-dpp`,children:D.usd3(r?.dollar_per_pct)})]}),(0,z.jsxs)(`div`,{className:`s`,children:[(0,z.jsx)(`span`,{className:`k`,children:`reset`}),(0,z.jsx)(`span`,{className:`v`,id:`mcw-reset`,children:D.datetimeShortZ(r?.reset_at_utc,n)})]})]})]}),(0,z.jsxs)(`h3`,{className:`m-sec sec-ms`,children:[(0,z.jsx)(`svg`,{className:`icon`,"aria-hidden":`true`,children:(0,z.jsx)(`use`,{href:`/static/icons.svg#hash`})}),`Milestones`]}),(0,z.jsxs)(`div`,{className:`mcw-mshead`,children:[(0,z.jsxs)(`span`,{className:`m-pill accent-purple`,id:`mcw-ms-count`,children:[a.length,` crossed`]}),(0,z.jsx)(`span`,{className:`mcw-ms-sub`,id:`mcw-ms-sub`,hidden:!p,children:p??``})]}),a.length===0?(0,z.jsx)(`p`,{className:`empty-state`,id:`mcw-empty`,children:`No milestones yet — earliest crosses at 1\xA0%.`}):(0,z.jsxs)(`table`,{className:`m-histable`,id:`mcw-table`,children:[(0,z.jsx)(`thead`,{children:(0,z.jsxs)(`tr`,{children:[(0,z.jsx)(`th`,{children:`%`}),(0,z.jsxs)(`th`,{children:[`Crossed (`,t.offsetLabel,`)`]}),(0,z.jsx)(`th`,{className:`num`,children:`Cumulative $`}),(0,z.jsx)(`th`,{className:`num`,children:`Marginal $`}),(0,z.jsx)(`th`,{className:`num`,children:`5h %`})]})}),(0,z.jsx)(`tbody`,{id:`mcw-rows`,children:a.map(e=>(0,z.jsxs)(`tr`,{children:[(0,z.jsx)(`td`,{children:(0,z.jsx)(`span`,{className:`m-pill accent-purple pct-cell`,children:e.percent??`—`})}),(0,z.jsx)(`td`,{className:`d`,children:D.startedShort(e.crossed_at_utc,n,{noSuffix:!0})}),(0,z.jsx)(`td`,{className:`num`,children:e.cumulative_usd==null?`—`:`$`+e.cumulative_usd.toFixed(2)}),(0,z.jsx)(`td`,{className:`num`,children:(0,z.jsx)(`span`,{className:`m-marginal`,children:e.marginal_usd==null?`—`:`$`+e.marginal_usd.toFixed(2)})}),(0,z.jsx)(`td`,{className:`num`,children:(0,z.jsx)(`span`,{className:`m-fh`,children:e.five_hour_pct_at_cross==null?`—`:Math.round(e.five_hour_pct_at_cross)+`%`})})]},e.percent))})]}),s.length>0&&(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`h3`,{className:`m-sec sec-ms sec-5h`,children:[(0,z.jsx)(`svg`,{className:`icon`,"aria-hidden":`true`,children:(0,z.jsx)(`use`,{href:`/static/icons.svg#activity`})}),`5h milestones`]}),(0,z.jsx)(`div`,{className:`mcw-mshead`,children:(0,z.jsxs)(`span`,{className:`m-pill accent-purple`,id:`mcw-5h-count`,children:[o.length,` crossed`]})}),(0,z.jsxs)(`table`,{className:`m-histable mcw-5h-table`,id:`mcw-5h-table`,children:[(0,z.jsx)(`thead`,{children:(0,z.jsxs)(`tr`,{children:[(0,z.jsx)(`th`,{children:`%`}),(0,z.jsxs)(`th`,{children:[`When (`,t.offsetLabel,`)`]}),(0,z.jsx)(`th`,{className:`num`,children:`Block $`}),(0,z.jsx)(`th`,{className:`num`,children:`Marginal $`}),(0,z.jsx)(`th`,{className:`num`,children:`7d %`})]})}),(0,z.jsx)(`tbody`,{children:s.map((e,t)=>{if(e.kind===`credit`)return(0,z.jsx)(`tr`,{className:`mcw-5h-credit-row`,children:(0,z.jsxs)(`td`,{colSpan:5,className:`mcw-5h-credit-cell`,children:[`⚡ CREDIT\xA0`,` `,e.data.delta_pp>0?`+`:``,e.data.delta_pp.toFixed(0),`pp\xA0@`,` `,D.startedShort(e.ts,n,{noSuffix:!0})]})},`credit-${t}-${e.ts}`);let r=e.data;return(0,z.jsxs)(`tr`,{children:[(0,z.jsx)(`td`,{children:(0,z.jsx)(`span`,{className:`m-pill accent-purple pct-cell`,children:r.percent_threshold})}),(0,z.jsx)(`td`,{className:`d`,children:D.startedShort(r.captured_at_utc,n,{noSuffix:!0})}),(0,z.jsx)(`td`,{className:`num`,children:`$`+r.block_cost_usd.toFixed(2)}),(0,z.jsx)(`td`,{className:`num`,children:(0,z.jsx)(`span`,{className:`m-marginal`,children:r.marginal_cost_usd==null?`—`:`$`+r.marginal_cost_usd.toFixed(2)})}),(0,z.jsx)(`td`,{className:`num`,children:(0,z.jsx)(`span`,{className:`m-fh`,children:r.seven_day_pct_at_crossing==null?`—`:Math.round(r.seven_day_pct_at_crossing)+`%`})})]},`fhms-${r.percent_threshold}-${r.reset_event_id}`)})})]})]})]})})}function Wo(e){if(!e)return`—`;let t=e.elapsed_hours,n=e.remaining_hours;if(t==null||n==null)return`—`;let r=t+n;if(r<=0)return`—`;let i=t/r*100;return Math.min(100,i).toFixed(1)+`%`}function Go(e){return e==null||!isFinite(e)?null:e<0?0:e>110?110:e}function Ko(e){return e==null||!isFinite(e)?`—`:e<0?`~`+(+e).toFixed(1)+`%`:(+e).toFixed(1)+`%`}function qo(e,t){for(let t of e)t.trueXPct=t.pos/110*100;if(e.length<2||t<=0){for(let t of e)t.resolvedXPct=t.trueXPct;return}let n=e.slice().sort((e,t)=>e.trueXPct-t.trueXPct),r=n[0],i=n[1],a=r.pillWidthPx/2/t*100,o=i.pillWidthPx/2/t*100,s=8/t*100,c=a+o+s,l=2*c;if(i.trueXPct-r.trueXPct<c){let e=(r.trueXPct+i.trueXPct)/2;r.resolvedXPct=e-l/2,i.resolvedXPct=e+l/2;let t=a,n=100-o;r.resolvedXPct<t&&(r.resolvedXPct=t,i.resolvedXPct-r.resolvedXPct<l&&(i.resolvedXPct=Math.min(n,r.resolvedXPct+l))),i.resolvedXPct>n&&(i.resolvedXPct=n,i.resolvedXPct-r.resolvedXPct<l&&(r.resolvedXPct=Math.max(t,i.resolvedXPct-l)))}else r.resolvedXPct=r.trueXPct,i.resolvedXPct=i.trueXPct}function Jo(e,t,n){(0,g.useEffect)(()=>{let r=e.current,i=t.current;if(!r||!i||!n)return;let a=r.querySelector(`.mfc-pills`),o=r.querySelector(`.mfc-leaders`),s=i.querySelector(`.mfc-rangeband`);if(!a||!o)return;let c=n.week_avg_projection_pct,l=n.recent_24h_projection_pct,u=Go(c),d=Go(l),f=[];u!=null&&c!=null&&f.push({kind:`wa`,pos:u,raw:c}),d!=null&&l!=null&&f.push({kind:`r24`,pos:d,raw:l});let p=new Set(f.map(e=>e.kind));i.querySelectorAll(`.mfc-chev`).forEach(e=>{let t=e.dataset.kind;(!t||!p.has(t))&&e.remove()}),a.querySelectorAll(`.mfc-pill`).forEach(e=>{let t=e.dataset.kind;(!t||!p.has(t))&&e.remove()});let m=f.map(e=>({...e,trueXPct:0,resolvedXPct:0,pillWidthPx:0}));for(let e of m){let t=e.pos/110*100,n=i.querySelector(`.mfc-chev[data-kind="${e.kind}"]`);n||(n=document.createElement(`div`),n.className=`mfc-chev `+e.kind,n.dataset.kind=e.kind,i.appendChild(n)),n.style.left=t+`%`;let r=a.querySelector(`.mfc-pill[data-kind="${e.kind}"]`),o=Ko(e.raw);r?r.textContent!==o&&(r.textContent=o):(r=document.createElement(`div`),r.className=`mfc-pill `+e.kind,r.dataset.kind=e.kind,r.textContent=o,a.appendChild(r)),e.pillEl=r}if(s){let e=!1;if(m.length===2){let t=m[0].pos/110*100,n=m[1].pos/110*100,r=Math.min(t,n),i=Math.max(t,n)-r;i>=.5&&(s.style.left=r+`%`,s.style.width=i+`%`,e=!0)}s.hidden=!e}let h=()=>{for(let e of m)if(!e.pillEl||!e.pillEl.isConnected)return;let e=r.clientWidth;if(e<=0){requestAnimationFrame(h);return}for(let e of m)e.pillWidthPx=e.pillEl.getBoundingClientRect().width;qo(m,e);for(let e of m)e.pillEl.style.left=e.resolvedXPct+`%`;for(;o.firstChild;)o.removeChild(o.firstChild);for(let e of m){let t=document.createElementNS(`http://www.w3.org/2000/svg`,`path`);t.setAttribute(`class`,e.kind),t.setAttribute(`vector-effect`,`non-scaling-stroke`),t.setAttribute(`d`,`M ${e.resolvedXPct} 0 C ${e.resolvedXPct} 10, ${e.trueXPct} 8, ${e.trueXPct} 18`),o.appendChild(t)}};h()},[e,t,n])}function Yo(){let e=Ke()?.forecast??null,t=e?.explain??null,n=(0,g.useRef)(null),r=(0,g.useRef)(null);Jo(n,r,e);let i=(0,z.jsx)(Gt,{panel:`forecast`,panelLabel:`Forecast`,triggerId:`forecast-modal`,onClick:()=>R(N(`forecast`,`forecast-modal`))});if(!e)return(0,z.jsx)(Io,{title:`Forecast — explain`,accentClass:`accent-purple`,headerExtras:i,children:(0,z.jsx)(`section`,{className:`modal-forecast`,children:(0,z.jsx)(`p`,{className:`empty-state`,id:`mfc-empty`,children:`No forecast data yet.`})})});let a=St(e.verdict),o=a?`m-pill ${a.accent}`:`m-pill`,s=a?`${a.glyph} ${a.label}`:`—`,c=`m-pill`,l=`—`,u=!0;e.confidence===`high`?(c=`m-pill accent-blue`,l=`high confidence`,u=!1):e.confidence===`low`&&(c=`m-pill accent-red`,l=`low confidence`,u=!1);let d=t?.rates,f=t?.week;return(0,z.jsx)(Io,{title:`Forecast — explain`,accentClass:`accent-purple`,headerExtras:i,children:(0,z.jsxs)(`section`,{className:`modal-forecast`,children:[(0,z.jsxs)(`div`,{className:`m-chipstrip`,id:`mfc-chips`,children:[(0,z.jsx)(`span`,{className:o,id:`mfc-verdict`,children:s}),(0,z.jsx)(`span`,{className:c,id:`mfc-confidence`,hidden:u,children:l})]}),(0,z.jsxs)(`div`,{className:`m-hero cols-2`,children:[(0,z.jsxs)(`div`,{className:`m-kv kv-wa`,children:[(0,z.jsx)(`svg`,{className:`icon`,"aria-hidden":`true`,children:(0,z.jsx)(`use`,{href:`/static/icons.svg#gauge`})}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`div`,{className:`v`,id:`mfc-wa-pct`,children:D.pct1(e.week_avg_projection_pct)}),(0,z.jsx)(`div`,{className:`lbl`,children:`Week-avg projection`}),(0,z.jsx)(`div`,{className:`sub`,id:`mfc-wa-sub`,children:D.ratePctPerHour(d?.week_average_pct_per_hour)})]})]}),(0,z.jsxs)(`div`,{className:`m-kv kv-r24`,children:[(0,z.jsx)(`svg`,{className:`icon`,"aria-hidden":`true`,children:(0,z.jsx)(`use`,{href:`/static/icons.svg#zap`})}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`div`,{className:`v`,id:`mfc-r24-pct`,children:D.pct1(e.recent_24h_projection_pct)}),(0,z.jsx)(`div`,{className:`lbl`,children:`Recent-24h projection`}),(0,z.jsx)(`div`,{className:`sub`,id:`mfc-r24-sub`,children:D.ratePctPerHour(d?.recent_24h_pct_per_hour)})]})]})]}),(0,z.jsxs)(`h3`,{className:`m-sec sec-range`,children:[(0,z.jsx)(`svg`,{className:`icon`,"aria-hidden":`true`,children:(0,z.jsx)(`use`,{href:`/static/icons.svg#bar-chart`})}),`Range vs. caps`]}),(0,z.jsxs)(`div`,{className:`mfc-rangewrap`,id:`mfc-rangewrap`,ref:n,children:[(0,z.jsx)(`div`,{className:`mfc-pills`,id:`mfc-pills`}),(0,z.jsx)(`svg`,{className:`mfc-leaders`,id:`mfc-leaders`,viewBox:`0 0 100 18`,preserveAspectRatio:`none`,"aria-hidden":`true`}),(0,z.jsxs)(`div`,{className:`mfc-rangetrack`,id:`mfc-rangetrack`,ref:r,children:[(0,z.jsx)(`div`,{className:`mfc-zone safe`}),(0,z.jsx)(`div`,{className:`mfc-zone warn`}),(0,z.jsx)(`div`,{className:`mfc-zone over`}),(0,z.jsx)(`div`,{className:`mfc-rangeband`,id:`mfc-rangeband`,hidden:!0}),(0,z.jsx)(`div`,{className:`mfc-bound b90`,children:(0,z.jsx)(`div`,{className:`lbl`,children:`90%`})}),(0,z.jsx)(`div`,{className:`mfc-bound b100`,children:(0,z.jsx)(`div`,{className:`lbl`,children:`100%`})})]})]}),(0,z.jsxs)(`h3`,{className:`m-sec sec-rates`,children:[(0,z.jsx)(`svg`,{className:`icon`,"aria-hidden":`true`,children:(0,z.jsx)(`use`,{href:`/static/icons.svg#activity`})}),`Rates`]}),(0,z.jsxs)(`div`,{className:`mfc-kvgrid`,children:[(0,z.jsxs)(`div`,{className:`mfc-krow`,children:[(0,z.jsx)(`span`,{className:`l`,children:`$ / 1%`}),(0,z.jsx)(`span`,{className:`v v-cyan`,id:`mfc-dpp`,children:D.usd3(d?.dollars_per_percent)})]}),(0,z.jsxs)(`div`,{className:`mfc-krow`,children:[(0,z.jsx)(`span`,{className:`l`,children:`week done`}),(0,z.jsx)(`span`,{className:`v v-green`,id:`mfc-wkdone`,children:Wo(f)})]}),(0,z.jsxs)(`div`,{className:`mfc-krow`,children:[(0,z.jsx)(`span`,{className:`l`,children:`elapsed`}),(0,z.jsx)(`span`,{className:`v v-green`,id:`mfc-elapsed`,children:D.hours1(f?.elapsed_hours)})]}),(0,z.jsxs)(`div`,{className:`mfc-krow`,children:[(0,z.jsx)(`span`,{className:`l`,children:`remaining`}),(0,z.jsx)(`span`,{className:`v`,id:`mfc-remain`,children:D.hours1(f?.remaining_hours)})]})]}),(0,z.jsxs)(`h3`,{className:`m-sec sec-bud`,children:[(0,z.jsx)(`svg`,{className:`icon`,"aria-hidden":`true`,children:(0,z.jsx)(`use`,{href:`/static/icons.svg#dollar`})}),`Daily budgets to stay under`]}),(0,z.jsxs)(`div`,{className:`mfc-kvgrid mfc-kvgrid-single`,children:[(0,z.jsxs)(`div`,{className:`mfc-krow`,children:[(0,z.jsx)(`span`,{className:`l`,children:`@ 100% cap`}),(0,z.jsx)(`span`,{className:`v v-magenta`,id:`mfc-bud100`,children:D.usd2PerDay(e.budget_100_per_day_usd)})]}),(0,z.jsxs)(`div`,{className:`mfc-krow`,children:[(0,z.jsx)(`span`,{className:`l`,children:`@ 90% cap`}),(0,z.jsx)(`span`,{className:`v v-amber`,id:`mfc-bud90`,children:D.usd2PerDay(e.budget_90_per_day_usd)})]})]})]})})}function Xo(e){let t=Math.max(1,Math.round(e/4));return`${e} week${e===1?``:`s`} · ${t} month${t===1?``:`s`}`}function Zo(e){let t=e.findIndex(e=>e&&e.is_current);return t>=0?t:e.length-1}function Qo(e,t){let n=e.filter((e,n)=>n!==t).map(e=>e.dollar_per_pct).filter(e=>e!=null&&isFinite(e));if(n.length<4)return null;let r=n.slice(-4).sort((e,t)=>e-t);return(r[1]+r[2])/2}function $o(e){if(!e.length)return null;let t=[...e].sort((e,t)=>e-t),n=Math.floor(t.length/2);return t.length%2?t[n]:(t[n-1]+t[n])/2}function es(e,t){let n=[];if(!e.length)return n;let r={left:44,right:14,top:12,bottom:22},i=600-r.left-r.right,a=140-r.top-r.bottom,o=e.length,s=e=>r.left+(o===1?i:e/(o-1)*i),c=e.map(e=>e.dollar_per_pct).filter(e=>e!=null&&isFinite(e)),l=c.length?Math.min(...c)*.96:0,u=c.length?Math.max(...c)*1.04:1;u-l<1e-6&&(l-=.01,u+=.01);let d=e=>r.top+a*(1-(e-l)/(u-l)),f=e.map(e=>e.used_pct).filter(e=>e!=null&&isFinite(e)),p=f.length?Math.min(...f)*.96:0,m=f.length?Math.max(...f)*1.04:100;m-p<1e-6&&(--p,m+=1);let h=e=>r.top+a*(1-(e-p)/(m-p));if(n.push({el:`line`,attrs:{class:`mtr-axis`,x1:r.left,y1:r.top+a,x2:600-r.right,y2:r.top+a},key:`axis`}),c.length){let e=$o(c);e!=null&&(n.push({el:`line`,attrs:{class:`mtr-hl`,x1:r.left,y1:d(e),x2:600-r.right,y2:d(e)},key:`med-line`}),n.push({el:`text`,attrs:{class:`mtr-medlabel`,x:r.left+2,y:d(e)-3},text:`median $`+e.toFixed(2),key:`med-label`}))}{let t=[];e.forEach((e,n)=>{e.used_pct!=null&&isFinite(e.used_pct)&&t.push(`${s(n)},${h(e.used_pct)}`)}),t.length>=2&&n.push({el:`polyline`,attrs:{class:`mtr-trendline-dim`,points:t.join(` `)},key:`poly-used`})}{let t=[];e.forEach((e,n)=>{e.dollar_per_pct!=null&&isFinite(e.dollar_per_pct)&&t.push(`${s(n)},${d(e.dollar_per_pct)}`)}),t.length>=2&&n.push({el:`polyline`,attrs:{class:`mtr-trendline`,points:t.join(` `)},key:`poly-dpp`})}e.forEach((e,r)=>{if(e.dollar_per_pct==null||!isFinite(e.dollar_per_pct))return;let i=r===t;n.push({el:`circle`,attrs:{class:`mtr-trenddot`+(i?` cur`:``),cx:s(r),cy:d(e.dollar_per_pct),r:i?5:3},key:`dot-${r}`})}),c.length&&(n.push({el:`text`,attrs:{class:`mtr-ylabel`,x:3,y:r.top+8},text:`$`+(u/1.04).toFixed(2),key:`ymax`}),n.push({el:`text`,attrs:{class:`mtr-ylabel`,x:3,y:r.top+a},text:`$`+(l/.96).toFixed(2),key:`ymin`}));let g=e[t];return g&&g.dollar_per_pct!=null&&isFinite(g.dollar_per_pct)&&n.push({el:`text`,attrs:{class:`mtr-curlabel`,x:Math.max(r.left+4,s(t)-22),y:Math.min(138,d(g.dollar_per_pct)+16)},text:`$`+g.dollar_per_pct.toFixed(2),key:`curlabel`}),n}function ts(e,t){return t===0?`Now`+(e.label?` · `+e.label:``):`W−`+t+(e.label?` · `+e.label:``)}function ns(e){return e==null||!isFinite(e)?{cls:`flat`,text:`—`}:e>5e-4?{cls:`up`,text:`+`+e.toFixed(2)}:e<-5e-4?{cls:`down`,text:e.toFixed(2)}:{cls:`flat`,text:`0.00`}}function rs(e){return e==null||!isFinite(e)?{cls:`delta-flat`,iconHref:`/static/icons.svg#minus`,text:`—`}:e<-5e-4?{cls:`delta-down`,iconHref:`/static/icons.svg#trending-down`,text:`−$`+Math.abs(e).toFixed(3)}:e>5e-4?{cls:`delta-up`,iconHref:`/static/icons.svg#trending-up`,text:`+$`+e.toFixed(3)}:{cls:`delta-flat`,iconHref:`/static/icons.svg#minus`,text:`$0.000`}}function is(){let e=Ke(),t=oe(e),n=(0,z.jsx)(Gt,{panel:`trend`,panelLabel:`Trend`,triggerId:`trend-modal`,onClick:()=>R(N(`trend`,`trend-modal`))});if(!t.length)return(0,z.jsx)(Io,{title:`Trend — 12-week history`,accentClass:`accent-amber`,headerExtras:n,children:(0,z.jsx)(`section`,{className:`modal-trend`,children:(0,z.jsx)(`p`,{className:`empty-state`,id:`mtr-empty`,children:`No history data yet.`})})});let r=Zo(t),i=t[r],a=e?.trend?.history_median_dpp,o=a!=null&&isFinite(a)?a:Qo(t,r),s=rs(i&&i.dollar_per_pct!=null&&o!=null?i.dollar_per_pct-o:null),c=es(t,r),l=t.some(e=>e.used_pct!=null&&isFinite(e.used_pct)),u=t.length;return(0,z.jsx)(Io,{title:`Trend — 12-week history`,accentClass:`accent-amber`,headerExtras:n,children:(0,z.jsxs)(`section`,{className:`modal-trend`,children:[(0,z.jsx)(`div`,{className:`m-chipstrip`,children:(0,z.jsx)(`span`,{className:`m-pill accent-amber`,id:`mtr-weeks-pill`,children:Xo(u)})}),(0,z.jsxs)(`div`,{className:`m-hero cols-3`,children:[(0,z.jsxs)(`div`,{className:`m-kv kv-cur`,children:[(0,z.jsx)(`svg`,{className:`icon`,"aria-hidden":`true`,children:(0,z.jsx)(`use`,{href:`/static/icons.svg#dollar`})}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`div`,{className:`v`,id:`mtr-cur`,children:i&&i.dollar_per_pct!=null?`$`+i.dollar_per_pct.toFixed(3):`—`}),(0,z.jsx)(`div`,{className:`lbl`,children:`Current $ / 1%`})]})]}),(0,z.jsxs)(`div`,{className:`m-kv kv-med`,children:[(0,z.jsx)(`svg`,{className:`icon`,"aria-hidden":`true`,children:(0,z.jsx)(`use`,{href:`/static/icons.svg#minus`})}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`div`,{className:`v`,id:`mtr-med`,children:o==null?`—`:`$`+o.toFixed(3)}),(0,z.jsx)(`div`,{className:`lbl`,children:`4-week median`})]})]}),(0,z.jsxs)(`div`,{className:`m-kv kv-delta ${s.cls}`,id:`mtr-delta-kv`,children:[(0,z.jsx)(`svg`,{className:`icon`,"aria-hidden":`true`,children:(0,z.jsx)(`use`,{href:s.iconHref})}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`div`,{className:`v`,id:`mtr-delta`,children:s.text}),(0,z.jsx)(`div`,{className:`lbl`,children:`vs median`})]})]})]}),(0,z.jsxs)(`h3`,{className:`m-sec sec-spark`,children:[(0,z.jsx)(`svg`,{className:`icon`,"aria-hidden":`true`,children:(0,z.jsx)(`use`,{href:`/static/icons.svg#trending-down`})}),`12-week history · $/1%`,(0,z.jsxs)(`span`,{className:`mtr-legend`+(l?``:` legend-no-used`),"aria-hidden":`true`,children:[(0,z.jsx)(`span`,{className:`sw sw-dpp`}),(0,z.jsx)(`span`,{className:`sw-lbl`,children:`$/1%`}),(0,z.jsx)(`span`,{className:`sw sw-used`}),(0,z.jsx)(`span`,{className:`sw-lbl`,children:`used %`})]})]}),(0,z.jsxs)(`div`,{className:`mtr-sparkhero`,children:[(0,z.jsx)(`svg`,{id:`mtr-svg`,viewBox:`0 0 600 140`,preserveAspectRatio:`none`,"aria-hidden":`true`,children:c.map(e=>{let{el:t,attrs:n,text:r,key:i}=e,a={};for(let e in n)a[e===`class`?`className`:e]=n[e];return t===`line`?(0,z.jsx)(`line`,{...a},i):t===`polyline`?(0,z.jsx)(`polyline`,{...a},i):t===`circle`?(0,z.jsx)(`circle`,{...a},i):(0,z.jsx)(`text`,{...a,children:r},i)})}),(0,z.jsx)(`div`,{className:`mtr-sparkaxis`,id:`mtr-sparkaxis`,children:u>0?(0,z.jsxs)(g.Fragment,{children:[(0,z.jsxs)(`span`,{children:[`W−`,u-1]}),(0,z.jsxs)(`span`,{children:[`W−`,Math.floor((u-1)/2)]}),(0,z.jsx)(`span`,{children:`Now`})]}):null})]}),(0,z.jsxs)(`h3`,{className:`m-sec sec-tbl`,children:[(0,z.jsx)(`svg`,{className:`icon`,"aria-hidden":`true`,children:(0,z.jsx)(`use`,{href:`/static/icons.svg#hash`})}),`Weekly detail`]}),(0,z.jsxs)(`div`,{className:`mtr-tbl-head`,children:[(0,z.jsxs)(`span`,{className:`m-pill accent-purple`,id:`mtr-tbl-count`,children:[u,` weeks`]}),(0,z.jsx)(`span`,{className:`mtr-tbl-sub`,children:`current row highlighted · negative Δ = $/1% down vs prior week`})]}),(0,z.jsxs)(`table`,{className:`m-histable`,id:`mtr-table`,children:[(0,z.jsx)(`thead`,{children:(0,z.jsxs)(`tr`,{children:[(0,z.jsx)(`th`,{children:`Week`}),(0,z.jsx)(`th`,{className:`num`,children:`Used %`}),(0,z.jsx)(`th`,{className:`num`,children:`$ / 1%`}),(0,z.jsx)(`th`,{className:`num`,children:`Δ $/1%`})]})}),(0,z.jsx)(`tbody`,{id:`mtr-rows`,children:t.map((e,t)=>{let n=ts(e,u-1-t),r=e.used_pct==null?`—`:Math.round(e.used_pct)+`%`,i=e.dollar_per_pct==null?`—`:`$`+e.dollar_per_pct.toFixed(2),a=ns(e.delta);return(0,z.jsxs)(`tr`,{className:e.is_current?`cur`:void 0,children:[(0,z.jsx)(`td`,{children:(0,z.jsx)(`span`,{className:`wlab`,children:n})}),(0,z.jsx)(`td`,{className:`num usedpct`,children:r}),(0,z.jsx)(`td`,{className:`num dpp`,children:i}),(0,z.jsx)(`td`,{className:`num delta ${a.cls}`,children:a.text})]},e.label+`|`+t)})})]})]})})}var as=/(^|\/)(subagents\/|agent-)/;function os(){return(0,g.useSyncExternalStore)(L,()=>I().snapshot?.generated_at??``)}function ss(){let e=(0,g.useSyncExternalStore)(L,()=>I().openSessionId),t=os(),[n,r]=(0,g.useState)(null),[i,a]=(0,g.useState)(!0),[o,s]=(0,g.useState)(null),c=(0,g.useRef)(null),l=(0,g.useRef)(!1),u=(0,g.useRef)(null);return(0,g.useEffect)(()=>{u.current=e??I().snapshot?.sessions?.rows?.[0]?.session_id??null,l.current=!1},[e]),(0,g.useEffect)(()=>{let e=u.current;if(!e){a(!1),s(`No session available.`),r(null),c.current=null;return}let t=c.current!==e||n==null;c.current=e,t&&(a(!0),s(null),r(null));let i=new AbortController;return fetch(`/api/session/${encodeURIComponent(e)}`,{signal:i.signal}).then(async e=>{if(e.status===404){(t||l.current)&&(a(!1),s(`Session not found (the cache may have rolled forward).`),r(null)),l.current=!0;return}if(!e.ok)throw Error(`HTTP `+e.status);let n=await e.json();l.current=!1,r(n),s(null),a(!1)}).catch(e=>{e.name!==`AbortError`&&(l.current=!1,t&&(s(`Failed to load: `+e.message),a(!1)))}),()=>i.abort()},[e,t]),(0,z.jsx)(Io,{title:`Session detail`,accentClass:`accent-orange`,headerExtras:(0,z.jsx)(Gt,{panel:`sessions`,panelLabel:`Session`,triggerId:`session-modal`,onClick:()=>R(N(`sessions`,`session-modal`))}),children:(0,z.jsxs)(`section`,{className:`modal-sessions`,children:[i?(0,z.jsx)(`div`,{className:`modal-loading`,id:`msess-loading`,children:`Loading session detail…`}):null,o?(0,z.jsx)(`div`,{className:`modal-error`,id:`msess-error`,children:o}):null,!i&&!o&&n?(0,z.jsx)(cs,{detail:n}):null]})})}function cs({detail:e}){let t=Array.isArray(e.source_paths)?e.source_paths:[],n=[],r=[];t.forEach(e=>{as.test(e)?r.push(e):n.push(e)});let i=e.cost_total_usd??0,a=[[`Input`,e.input_tokens,null],[`Output`,e.output_tokens,null],[`Cache creation`,e.cache_creation_tokens,null],[`Cache read`,e.cache_read_tokens,null],[`Cache hit %`,e.cache_hit_pct,`cache-hit`]].filter(e=>e[1]!=null),o=!e.models||e.models.length===0,s=!e.cost_per_model||e.cost_per_model.length===0;return(0,z.jsxs)(`div`,{className:`modal-content`,id:`msess-content`,children:[(0,z.jsx)(`div`,{className:`m-chipstrip`,children:(0,z.jsx)(`span`,{className:`msess-badge`,id:`msess-id`,"aria-label":`Session ID`,children:e.session_id??`—`})}),(0,z.jsxs)(`div`,{className:`m-hero cols-3`,children:[(0,z.jsxs)(`div`,{className:`m-kv kv-cost`,children:[(0,z.jsx)(`svg`,{className:`icon`,"aria-hidden":`true`,children:(0,z.jsx)(`use`,{href:`/static/icons.svg#dollar`})}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`div`,{className:`v`,id:`msess-cost`,children:e.cost_total_usd==null?`—`:`$`+e.cost_total_usd.toFixed(2)}),(0,z.jsx)(`div`,{className:`lbl`,children:`Total cost`})]})]}),(0,z.jsxs)(`div`,{className:`m-kv kv-dur`,children:[(0,z.jsx)(`svg`,{className:`icon`,"aria-hidden":`true`,children:(0,z.jsx)(`use`,{href:`/static/icons.svg#clock`})}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`div`,{className:`v`,id:`msess-dur`,children:e.duration_min==null?`—`:e.duration_min+` min`}),(0,z.jsx)(`div`,{className:`lbl`,children:`Duration`})]})]}),(0,z.jsxs)(`div`,{className:`m-kv kv-proj`,children:[(0,z.jsx)(`svg`,{className:`icon`,"aria-hidden":`true`,children:(0,z.jsx)(`use`,{href:`/static/icons.svg#folder`})}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`div`,{className:`v`,id:`msess-project`,title:e.project_path??``,"aria-label":`Project`,children:e.project_label??e.project_path??`—`}),(0,z.jsx)(`div`,{className:`lbl`,children:`Project`})]})]})]}),(0,z.jsxs)(`div`,{className:`msess-ts`,children:[(0,z.jsx)(`svg`,{className:`icon`,"aria-hidden":`true`,children:(0,z.jsx)(`use`,{href:`/static/icons.svg#calendar`})}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`span`,{className:`k`,children:`started`}),(0,z.jsx)(`span`,{className:`v`,id:`msess-started`,children:e.started_utc??`—`})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`span`,{className:`k`,children:`last activity`}),(0,z.jsx)(`span`,{className:`v`,id:`msess-last`,children:e.last_activity_utc??`—`})]})]}),(0,z.jsxs)(`h3`,{className:`m-sec sec-tok`,children:[(0,z.jsx)(`svg`,{className:`icon`,"aria-hidden":`true`,children:(0,z.jsx)(`use`,{href:`/static/icons.svg#hash`})}),`Tokens`]}),(0,z.jsx)(`div`,{className:`msess-tok-grid`,id:`msess-tokens`,children:a.map(([e,t,n])=>(0,z.jsxs)(`div`,{className:`msess-tok-tile`+(n?` `+n:``),children:[(0,z.jsx)(`div`,{className:`lbl`,children:e}),(0,z.jsx)(`div`,{className:`n`,children:n===`cache-hit`?t.toFixed(1)+`%`:t.toLocaleString(`en-US`)}),n===`cache-hit`?(0,z.jsx)(`div`,{className:`bar`,children:(0,z.jsx)(`div`,{className:`fill`,style:{width:Math.max(0,Math.min(t,100))+`%`}})}):null]},e))}),o?null:(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`h3`,{className:`m-sec sec-mod`,children:[(0,z.jsx)(`svg`,{className:`icon`,"aria-hidden":`true`,children:(0,z.jsx)(`use`,{href:`/static/icons.svg#sparkles`})}),`Models`]}),(0,z.jsx)(`div`,{className:`m-chipstrip`,id:`msess-models`,children:(e.models||[]).map(e=>(0,z.jsx)(`span`,{className:`chip `+ln(e.name),children:e.name},e.name))})]}),s?null:(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`h3`,{className:`m-sec sec-costm`,children:[(0,z.jsx)(`svg`,{className:`icon`,"aria-hidden":`true`,children:(0,z.jsx)(`use`,{href:`/static/icons.svg#pie-chart`})}),`Cost by model`]}),(0,z.jsxs)(`div`,{className:`msess-costm`,children:[(0,z.jsx)(`div`,{className:`bar`,id:`msess-cost-bar`,children:(e.cost_per_model||[]).map(e=>{let t=i>0&&e.cost_usd!=null?e.cost_usd/i*100:0;return(0,z.jsx)(`div`,{className:`seg `+ln(e.model),style:{width:t+`%`}},e.model)})}),(0,z.jsx)(`div`,{className:`legend`,id:`msess-cost-legend`,children:(e.cost_per_model||[]).map(e=>{let t=i>0&&e.cost_usd!=null?e.cost_usd/i*100:0;return(0,z.jsxs)(`div`,{className:`lg`,children:[(0,z.jsx)(`span`,{className:`sw `+ln(e.model)}),(0,z.jsx)(`span`,{className:`name`,children:e.model}),(0,z.jsx)(`span`,{className:`v`,children:e.cost_usd==null?`—`:`$`+e.cost_usd.toFixed(3)}),(0,z.jsxs)(`span`,{className:`pct`,children:[Math.round(t),`%`]})]},e.model)})})]})]}),t.length>0?(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`h3`,{className:`m-sec sec-src`,children:[(0,z.jsx)(`svg`,{className:`icon`,"aria-hidden":`true`,children:(0,z.jsx)(`use`,{href:`/static/icons.svg#file-text`})}),`Source files`]}),(0,z.jsxs)(`div`,{className:`msess-src`,id:`msess-src`,children:[(0,z.jsxs)(`div`,{className:`src-head`,children:[(0,z.jsxs)(`span`,{className:`count-pill`,children:[t.length,` file`,t.length===1?``:`s`]}),(0,z.jsxs)(`span`,{className:`sub`,children:[n.length,` primary`,r.length>0?(0,z.jsxs)(z.Fragment,{children:[` `,(0,z.jsx)(`span`,{className:`dot`,children:`·`}),` `,(0,z.jsxs)(`span`,{className:`subcount`,children:[r.length,` subagent`,r.length===1?``:`s`]})]}):null]})]}),n.length>0?n.map(e=>(0,z.jsx)(`div`,{className:`primary-path`,children:e},e)):r.length>0?(0,z.jsxs)(`div`,{className:`src-empty-primary`,children:[`No primary path resolved · `,r.length,` subagent path`,r.length===1?``:`s`,` below`]}):null,r.length>0?(0,z.jsxs)(`details`,{className:`subagents`,open:n.length===0,children:[(0,z.jsxs)(`summary`,{children:[`Show `,r.length,` subagent path`,r.length===1?``:`s`]}),(0,z.jsx)(`ul`,{className:`paths`,children:r.map(e=>(0,z.jsx)(`li`,{children:e},e))})]}):null]})]}):null]})}function ls({row:e,variant:t,accentClass:n}){let r=Ht(),i={tz:r.resolvedTz,offsetLabel:r.offsetLabel},a=(e,t)=>`${D.datetimeShort(e,i)} → ${D.datetimeShort(t,i)}`,o=e.delta_cost_pct==null?`flat`:e.delta_cost_pct>0?`up`:e.delta_cost_pct<0?`down`:`flat`,s=t===`weekly`?`week`:t===`monthly`?`month`:`day`,c=t===`daily`?`Today`:`Now`;return(0,z.jsxs)(`div`,{className:`detail-card ${n}`,children:[(0,z.jsxs)(`div`,{className:`head`,children:[(0,z.jsxs)(`div`,{className:`big`,children:[e.label,e.is_current&&(0,z.jsx)(`span`,{className:`pill-current`,children:c})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`span`,{className:`cost`,style:{color:`var(--text)`,fontWeight:700},children:D.usd2(e.cost_usd)}),` `,e.delta_cost_pct==null?(0,z.jsx)(`span`,{className:`delta flat`,children:`—`}):(0,z.jsxs)(`span`,{className:`delta ${o}`,children:[D.deltaPct(e.delta_cost_pct),` vs prior `,s]})]})]}),t===`weekly`&&e.week_start_at&&e.week_end_at&&(0,z.jsxs)(`div`,{className:`window`,children:[`Subscription window: `,a(e.week_start_at,e.week_end_at)]}),(0,z.jsx)(`div`,{className:`model-stack`,role:`presentation`,children:e.models.map(e=>(0,z.jsx)(`span`,{className:e.chip,style:{width:`${e.cost_pct}%`}},e.model))}),(0,z.jsx)(`div`,{className:`chips`,children:e.models.map(e=>(0,z.jsxs)(`span`,{className:`chip ${e.chip}`,children:[e.display,` `,Math.round(e.cost_pct),`% · `,D.usd2(e.cost_usd)]},e.model))}),(0,z.jsxs)(`div`,{className:`tokens-row`,children:[(0,z.jsxs)(`div`,{className:`t`,children:[(0,z.jsx)(`span`,{className:`k`,children:`Input`}),(0,z.jsx)(`span`,{className:`v`,children:D.compact(e.input_tokens)})]}),(0,z.jsxs)(`div`,{className:`t`,children:[(0,z.jsx)(`span`,{className:`k`,children:`Output`}),(0,z.jsx)(`span`,{className:`v`,children:D.compact(e.output_tokens)})]}),(0,z.jsxs)(`div`,{className:`t`,children:[(0,z.jsx)(`span`,{className:`k`,children:`Cache+`}),(0,z.jsx)(`span`,{className:`v`,children:D.compact(e.cache_creation_tokens)})]}),(0,z.jsxs)(`div`,{className:`t`,children:[(0,z.jsx)(`span`,{className:`k`,children:`Cache-read`}),(0,z.jsx)(`span`,{className:`v`,children:D.compact(e.cache_read_tokens)})]}),(0,z.jsxs)(`div`,{className:`t`,children:[(0,z.jsx)(`span`,{className:`k`,children:`Total`}),(0,z.jsx)(`span`,{className:`v`,children:D.compact(e.total_tokens)})]}),e.cache_hit_pct!=null&&(0,z.jsxs)(`div`,{className:`t cache`,children:[(0,z.jsx)(`span`,{className:`k`,children:`Cache hit`}),(0,z.jsxs)(`span`,{className:`v`,children:[e.cache_hit_pct.toFixed(1),`%`]}),(0,z.jsx)(`div`,{className:`bar`,children:(0,z.jsx)(`div`,{className:`fill`,style:{width:`${Math.min(100,Math.max(0,e.cache_hit_pct))}%`}})})]})]}),t===`weekly`&&(0,z.jsxs)(`div`,{className:`stats2`,children:[(0,z.jsxs)(`div`,{className:`s`,children:[(0,z.jsx)(`span`,{className:`k`,children:`Used %`}),(0,z.jsx)(`span`,{className:`v`,children:D.pct0(e.used_pct)})]}),(0,z.jsxs)(`div`,{className:`s`,children:[(0,z.jsx)(`span`,{className:`k`,children:`$/1%`}),(0,z.jsx)(`span`,{className:`v`,children:D.usd2(e.dollar_per_pct)})]})]})]})}function us(e){return e==null||e===0?`num`:e>0?`num delta-up`:`num delta-down`}function ds(e){let t=new Set,n=[];for(let r of e.models)t.has(r.chip)||(t.add(r.chip),n.push(r.chip));return n}function fs({row:e}){let t=ds(e),n=t.slice(0,3),r=t.length>3?t.length-3:0;return(0,z.jsxs)(`span`,{className:`models-chips`,children:[n.map(e=>(0,z.jsx)(`span`,{className:`chip ${e}`,children:e},e)),r>0&&(0,z.jsxs)(`span`,{className:`models-chips-more`,children:[`…+`,r]})]})}function ps({rows:e,variant:t,accentClass:n,selectedIndex:r,onSelect:i}){return(0,z.jsxs)(`table`,{className:`history-table history-table--${t} ${n}`,role:`grid`,"aria-rowcount":e.length,children:[(0,z.jsx)(`thead`,{children:(0,z.jsxs)(`tr`,{children:[(0,z.jsx)(`th`,{children:t===`weekly`?`Week`:`Month`}),(0,z.jsx)(`th`,{children:`Models`}),(0,z.jsx)(`th`,{className:`num`,children:`Cost (USD)`}),t===`weekly`&&(0,z.jsx)(`th`,{className:`num`,children:`Used %`}),t===`weekly`&&(0,z.jsx)(`th`,{className:`num`,children:`$/1%`}),(0,z.jsx)(`th`,{className:`num`,children:`Δ`})]})}),(0,z.jsx)(`tbody`,{children:e.map((e,n)=>(0,z.jsxs)(`tr`,{className:n===r?`selected`:void 0,"aria-rowindex":n+1,"aria-selected":n===r,onClick:()=>i(n),children:[(0,z.jsxs)(`td`,{children:[e.label,n===r?` ▶`:``]}),(0,z.jsx)(`td`,{children:(0,z.jsx)(fs,{row:e})}),(0,z.jsx)(`td`,{className:`num`,children:D.usd2(e.cost_usd)}),t===`weekly`&&(0,z.jsx)(`td`,{className:`num`,children:D.pct0(e.used_pct)}),t===`weekly`&&(0,z.jsx)(`td`,{className:`num`,children:D.usd2(e.dollar_per_pct)}),(0,z.jsx)(`td`,{className:us(e.delta_cost_pct),children:D.deltaPct(e.delta_cost_pct)})]},e.label))})]})}function ms(){let e=Ke()?.weekly?.rows??[],[t,n]=(0,g.useState)(0),r=e.length;(0,g.useEffect)(()=>zt([{key:`ArrowDown`,scope:`modal`,when:()=>I().openModal===`weekly`,action:()=>n(e=>Math.min(e+1,Math.max(0,r-1)))},{key:`ArrowUp`,scope:`modal`,when:()=>I().openModal===`weekly`,action:()=>n(e=>Math.max(e-1,0))}]),[r]);let i=(0,z.jsx)(Gt,{panel:`weekly`,panelLabel:`Weekly`,triggerId:`weekly-modal`,onClick:()=>R(N(`weekly`,`weekly-modal`))});if(r===0)return(0,z.jsx)(Io,{title:`Weekly history · last 12`,accentClass:`accent-cyan`,headerExtras:i,children:(0,z.jsx)(`div`,{className:`panel-empty`,children:`No usage history yet.`})});let a=e[Math.min(t,r-1)];return(0,z.jsxs)(Io,{title:`Weekly history · last 12`,accentClass:`accent-cyan`,headerExtras:i,children:[(0,z.jsx)(ls,{row:a,variant:`weekly`,accentClass:`accent-cyan`}),(0,z.jsx)(ps,{rows:e,variant:`weekly`,accentClass:`accent-cyan`,selectedIndex:t,onSelect:n})]})}function hs(){let e=Ke()?.monthly?.rows??[],[t,n]=(0,g.useState)(0),r=e.length;(0,g.useEffect)(()=>zt([{key:`ArrowDown`,scope:`modal`,when:()=>I().openModal===`monthly`,action:()=>n(e=>Math.min(e+1,Math.max(0,r-1)))},{key:`ArrowUp`,scope:`modal`,when:()=>I().openModal===`monthly`,action:()=>n(e=>Math.max(e-1,0))}]),[r]);let i=(0,z.jsx)(Gt,{panel:`monthly`,panelLabel:`Monthly`,triggerId:`monthly-modal`,onClick:()=>R(N(`monthly`,`monthly-modal`))});if(r===0)return(0,z.jsx)(Io,{title:`Monthly history · last 12`,accentClass:`accent-pink`,headerExtras:i,children:(0,z.jsx)(`div`,{className:`panel-empty`,children:`No usage history yet.`})});let a=e[Math.min(t,r-1)];return(0,z.jsxs)(Io,{title:`Monthly history · last 12`,accentClass:`accent-pink`,headerExtras:i,children:[(0,z.jsx)(ls,{row:a,variant:`monthly`,accentClass:`accent-pink`}),(0,z.jsx)(ps,{rows:e,variant:`monthly`,accentClass:`accent-pink`,selectedIndex:t,onSelect:n})]})}var gs=720,_s=180,vs={left:46,right:20,top:18,bottom:20};function ys(e){return e===0?`$0`:e<10?`$`+e.toFixed(2):`$`+Math.round(e).toString()}function bs(){return(0,g.useSyncExternalStore)(L,()=>I().snapshot?.generated_at??``)}function xs({detail:e}){let t=bs(),n=Ht(),r={tz:n.resolvedTz,offsetLabel:n.offsetLabel},i=Date.parse(e.start_at),a=Date.parse(e.end_at)-i||1,o=e=>vs.left+(Date.parse(e)-i)/a*(gs-vs.left-vs.right),s=Math.max(e.cost_usd,e.projection?.total_cost_usd??0),c=e=>{let t=vs.top,n=_s-vs.bottom;return s<=0?n:n-e/s*(n-t)},l=[];for(let e=0;e<=5;e++)l.push(new Date(i+e*36e5).toISOString());let u=e.samples.length>0?e.samples[e.samples.length-1].cum:0,d=e.is_active?t||new Date().toISOString():null,f=[];if(e.samples.length>0){f.push([o(e.start_at),c(0)]);for(let t of e.samples)f.push([o(t.t),c(t.cum)]);d&&f.push([o(d),c(u)])}let p=f.map(([e,t])=>`${e.toFixed(1)},${t.toFixed(1)}`).join(` `),m=f.length>0?`M ${p.replace(/ /g,` L `)} L ${f[f.length-1][0].toFixed(1)},${c(0).toFixed(1)} Z`:``,h=s<=0?[0]:[0,s/2,s];return(0,z.jsx)(`div`,{className:`mblock-timeline`,children:(0,z.jsxs)(`svg`,{viewBox:`0 0 ${gs} ${_s}`,style:{width:`100%`,height:`auto`},role:`img`,"aria-label":`Cumulative cost over the 5-hour block window`,children:[h.map(e=>(0,z.jsx)(`text`,{x:8,y:c(e)+4,fill:`var(--text-dim)`,fontSize:10,children:ys(e)},e)),(0,z.jsx)(`line`,{x1:vs.left,y1:vs.top,x2:vs.left,y2:_s-vs.bottom,stroke:`var(--border-soft)`,strokeWidth:.8}),(0,z.jsx)(`line`,{x1:vs.left,y1:_s-vs.bottom,x2:gs-vs.right,y2:_s-vs.bottom,stroke:`var(--border-soft)`,strokeWidth:.8}),l.slice(1,-1).map(e=>(0,z.jsx)(`line`,{x1:o(e),y1:vs.top,x2:o(e),y2:_s-vs.bottom,stroke:`var(--border-soft)`,strokeDasharray:`2 3`,strokeWidth:.5},e)),l.map(e=>(0,z.jsx)(`text`,{x:o(e)-14,y:_s-5,fill:`var(--text-dim)`,fontSize:9,children:D.timeHHmm(e,r,{noSuffix:!0})},e)),f.length>0?(0,z.jsxs)(z.Fragment,{children:[(0,z.jsx)(`path`,{d:m,fill:`var(--accent-green)`,opacity:.12}),(0,z.jsx)(`polyline`,{points:p,fill:`none`,stroke:`var(--accent-green)`,strokeWidth:2}),(0,z.jsx)(`circle`,{cx:f[f.length-1][0],cy:f[f.length-1][1],r:3,fill:`var(--accent-green)`})]}):(0,z.jsx)(`text`,{x:gs/2,y:_s/2,fill:`var(--text-faint)`,fontSize:11,textAnchor:`middle`,children:`No spend recorded yet in this block.`}),e.is_active&&e.projection&&d&&f.length>0?(0,z.jsxs)(z.Fragment,{children:[(0,z.jsx)(`polyline`,{points:`${o(d).toFixed(1)},${c(u).toFixed(1)} ${o(e.end_at).toFixed(1)},${c(e.projection.total_cost_usd).toFixed(1)}`,fill:`none`,stroke:`var(--accent-amber)`,strokeWidth:1.5,strokeDasharray:`5 4`,opacity:.85}),(0,z.jsx)(`circle`,{cx:o(e.end_at),cy:c(e.projection.total_cost_usd),r:3,fill:`var(--accent-amber)`,opacity:.85}),(0,z.jsxs)(`text`,{x:o(e.end_at)-50,y:c(e.projection.total_cost_usd)-6,fill:`var(--accent-amber)`,fontSize:9,children:[`proj $`,e.projection.total_cost_usd.toFixed(2)]}),(0,z.jsx)(`line`,{x1:o(d),y1:vs.top,x2:o(d),y2:_s-vs.bottom,stroke:`var(--accent-amber)`,strokeWidth:1.2}),(0,z.jsx)(`text`,{x:o(d)+4,y:vs.top+10,fill:`var(--accent-amber)`,fontSize:9,children:`now`})]}):null]})})}function Ss(){return(0,g.useSyncExternalStore)(L,()=>I().snapshot?.generated_at??``)}function Cs(e,t){let n=Date.parse(e.start_at),r=e.is_active?Date.parse(t)||Date.now():e.actual_end_at?Date.parse(e.actual_end_at):Date.parse(e.end_at),i=Math.max(0,Math.floor((r-n)/6e4)),a=Math.floor(i/60),o=i%60;return`${a}h ${String(o).padStart(2,`0`)}m`}function ws(e,t,n){return`${D.timeHHmm(e,n)} → ${D.timeHHmm(t,n)}`}function Ts(){let e=(0,g.useSyncExternalStore)(L,()=>I().openBlockStartAt),t=Ss(),n=Ht(),r={tz:n.resolvedTz,offsetLabel:n.offsetLabel},[i,a]=(0,g.useState)(null),[o,s]=(0,g.useState)(!0),[c,l]=(0,g.useState)(null),u=(0,g.useRef)(null),d=(0,g.useRef)(!1),f=(0,g.useRef)(null);return(0,g.useEffect)(()=>{f.current=e??null,d.current=!1},[e]),(0,g.useEffect)(()=>{let e=f.current;if(!e){s(!1),l(`No block bound.`),a(null),u.current=null;return}let t=u.current!==e||i==null;u.current=e,t&&(s(!0),l(null),a(null));let n=new AbortController;return fetch(`/api/block/${encodeURIComponent(e)}`,{signal:n.signal}).then(async e=>{if(e.status===404){(t||d.current)&&(s(!1),l(`Block not found (the cache may have rolled forward).`),a(null)),d.current=!0;return}if(!e.ok)throw Error(`HTTP `+e.status);let n=await e.json();d.current=!1,a(n),l(null),s(!1)}).catch(e=>{e.name!==`AbortError`&&(d.current=!1,t&&(l(`Failed to load: `+e.message),s(!1)))}),()=>n.abort()},[e,t]),(0,z.jsx)(Io,{title:i?`${i.anchor===`heuristic`?`~ `:``}Block · ${i.label}`:`Block`,accentClass:`accent-blue`,headerExtras:(0,z.jsx)(Gt,{panel:`blocks`,panelLabel:`5-hour block`,triggerId:`block-modal`,onClick:()=>R(N(`blocks`,`block-modal`))}),children:(0,z.jsxs)(`section`,{className:`modal-block`,children:[o?(0,z.jsx)(`div`,{className:`modal-loading`,children:`Loading block detail…`}):null,c?(0,z.jsx)(`div`,{className:`modal-error`,children:c}):null,!o&&!c&&i?(0,z.jsx)(Es,{detail:i,generatedAt:t,ctx:r}):null]})})}function Es({detail:e,generatedAt:t,ctx:n}){let r=e.cost_usd??0;return(0,z.jsxs)(`div`,{className:`modal-content`,children:[(0,z.jsxs)(`div`,{className:`m-chipstrip`,children:[e.is_active?(0,z.jsx)(`span`,{className:`m-pill accent-green`,children:`● Active`}):null,e.anchor===`heuristic`?(0,z.jsx)(`span`,{className:`m-pill accent-amber`,children:`~ heuristic anchor`}):null,(0,z.jsx)(`span`,{className:`m-pill accent-blue`,children:ws(e.start_at,e.end_at,n)}),(0,z.jsxs)(`span`,{className:`m-pill`,children:[e.entries_count.toLocaleString(`en-US`),` `,e.entries_count===1?`entry`:`entries`]})]}),(0,z.jsxs)(`div`,{className:`m-hero `+(e.is_active?`cols-4`:`cols-3`),children:[(0,z.jsxs)(`div`,{className:`m-kv kv-cost`,children:[(0,z.jsx)(`svg`,{className:`icon`,"aria-hidden":`true`,children:(0,z.jsx)(`use`,{href:`/static/icons.svg#dollar`})}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`div`,{className:`v`,children:D.usd2(e.cost_usd)}),(0,z.jsx)(`div`,{className:`lbl`,children:`Total cost`})]})]}),(0,z.jsxs)(`div`,{className:`m-kv kv-dur`,children:[(0,z.jsx)(`svg`,{className:`icon`,"aria-hidden":`true`,children:(0,z.jsx)(`use`,{href:`/static/icons.svg#clock`})}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`div`,{className:`v`,children:Cs(e,t)}),(0,z.jsx)(`div`,{className:`lbl`,children:`Elapsed`})]})]}),(0,z.jsxs)(`div`,{className:`m-kv`,children:[(0,z.jsx)(`svg`,{className:`icon`,"aria-hidden":`true`,children:(0,z.jsx)(`use`,{href:`/static/icons.svg#hash`})}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`div`,{className:`v`,children:e.total_tokens.toLocaleString(`en-US`)}),(0,z.jsx)(`div`,{className:`lbl`,children:`Total tokens`})]})]}),e.is_active?(0,z.jsxs)(`div`,{className:`m-kv kv-proj`,children:[(0,z.jsx)(`svg`,{className:`icon`,"aria-hidden":`true`,children:(0,z.jsx)(`use`,{href:`/static/icons.svg#crystal-ball`})}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`div`,{className:`v`,children:e.projection?D.usd2(e.projection.total_cost_usd):`—`}),(0,z.jsxs)(`div`,{className:`lbl`,children:[`Projected`,e.projection?` · ${e.projection.remaining_minutes}m left`:``]})]})]}):null]}),(0,z.jsx)(xs,{detail:e}),(0,z.jsxs)(`h3`,{className:`m-sec sec-tok`,children:[(0,z.jsx)(`svg`,{className:`icon`,"aria-hidden":`true`,children:(0,z.jsx)(`use`,{href:`/static/icons.svg#hash`})}),`Tokens`]}),(0,z.jsxs)(`div`,{className:`msess-tok-grid mblock-tok-grid`,children:[(0,z.jsxs)(`div`,{className:`msess-tok-tile`,children:[(0,z.jsx)(`div`,{className:`lbl`,children:`Input`}),(0,z.jsx)(`div`,{className:`n`,children:e.input_tokens.toLocaleString(`en-US`)})]}),(0,z.jsxs)(`div`,{className:`msess-tok-tile`,children:[(0,z.jsx)(`div`,{className:`lbl`,children:`Output`}),(0,z.jsx)(`div`,{className:`n`,children:e.output_tokens.toLocaleString(`en-US`)})]}),(0,z.jsxs)(`div`,{className:`msess-tok-tile`,children:[(0,z.jsx)(`div`,{className:`lbl`,children:`Cache create`}),(0,z.jsx)(`div`,{className:`n`,children:e.cache_creation_tokens.toLocaleString(`en-US`)})]}),(0,z.jsxs)(`div`,{className:`msess-tok-tile`,children:[(0,z.jsx)(`div`,{className:`lbl`,children:`Cache read`}),(0,z.jsx)(`div`,{className:`n`,children:e.cache_read_tokens.toLocaleString(`en-US`)})]}),e.cache_hit_pct==null?null:(0,z.jsxs)(`div`,{className:`msess-tok-tile cache-hit`,children:[(0,z.jsx)(`div`,{className:`lbl`,children:`Cache hit %`}),(0,z.jsxs)(`div`,{className:`n`,children:[e.cache_hit_pct.toFixed(1),`%`]}),(0,z.jsx)(`div`,{className:`bar`,children:(0,z.jsx)(`div`,{className:`fill`,style:{width:Math.min(100,Math.max(0,e.cache_hit_pct))+`%`}})})]})]}),e.models.length>0?(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`h3`,{className:`m-sec sec-costm`,children:[(0,z.jsx)(`svg`,{className:`icon`,"aria-hidden":`true`,children:(0,z.jsx)(`use`,{href:`/static/icons.svg#pie-chart`})}),`Cost by model`]}),(0,z.jsxs)(`div`,{className:`msess-costm`,children:[(0,z.jsx)(`div`,{className:`bar`,children:e.models.map(e=>{let t=r>0?e.cost_usd/r*100:0;return(0,z.jsx)(`div`,{className:`seg `+ln(e.model),style:{width:t+`%`}},e.model)})}),(0,z.jsx)(`div`,{className:`legend`,children:e.models.map(e=>{let t=r>0?e.cost_usd/r*100:0;return(0,z.jsxs)(`div`,{className:`lg`,children:[(0,z.jsx)(`span`,{className:`sw `+ln(e.model)}),(0,z.jsx)(`span`,{className:`name`,children:e.display}),(0,z.jsxs)(`span`,{className:`v`,children:[`$`,e.cost_usd.toFixed(2)]}),(0,z.jsxs)(`span`,{className:`pct`,children:[Math.round(t),`%`]})]},e.model)})})]})]}):null,e.is_active&&e.burn_rate&&e.projection?(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`h3`,{className:`m-sec sec-burn`,children:[(0,z.jsx)(`svg`,{className:`icon`,"aria-hidden":`true`,children:(0,z.jsx)(`use`,{href:`/static/icons.svg#crystal-ball`})}),`Burn rate & projection`]}),(0,z.jsxs)(`div`,{className:`mblock-burn`,children:[(0,z.jsxs)(`div`,{className:`row`,children:[(0,z.jsx)(`span`,{className:`k`,children:`Burn rate`}),(0,z.jsx)(`span`,{className:`v amber`,children:D.usd2(e.burn_rate.cost_per_hour)}),(0,z.jsx)(`span`,{className:`dim`,children:`/ hr`}),(0,z.jsx)(`span`,{className:`sep`,children:`·`}),(0,z.jsx)(`span`,{className:`v cyan`,children:Math.round(e.burn_rate.tokens_per_minute).toLocaleString(`en-US`)}),(0,z.jsx)(`span`,{className:`dim`,children:`tok / min`})]}),(0,z.jsxs)(`div`,{className:`row`,children:[(0,z.jsx)(`span`,{className:`k`,children:`Projection`}),(0,z.jsx)(`span`,{className:`v amber`,children:D.usd2(e.projection.total_cost_usd)}),(0,z.jsx)(`span`,{className:`dim`,children:`total`}),(0,z.jsx)(`span`,{className:`sep`,children:`·`}),(0,z.jsx)(`span`,{className:`v cyan`,children:e.projection.total_tokens.toLocaleString(`en-US`)}),(0,z.jsx)(`span`,{className:`dim`,children:`tok`}),(0,z.jsx)(`span`,{className:`sep`,children:`·`}),(0,z.jsxs)(`span`,{className:`v`,children:[e.projection.remaining_minutes,` min`]}),(0,z.jsx)(`span`,{className:`dim`,children:`remaining`})]})]})]}):null]})}function Ds({rows:e,selectedDate:t,onSelect:n}){let r=[...e].reverse(),i=r.reduce((e,t)=>Math.max(e,t.cost_usd),0),a=r.length>0?Os(r[0].date):``,o=r.length>0?Os(r[r.length-1].date):``,s=r.find(e=>e.is_today),c=s?`${Os(s.date)} · today`:``;return(0,z.jsxs)(`section`,{className:`daily-modal-bars`,"aria-label":`30-day cost`,children:[(0,z.jsxs)(`div`,{className:`daily-modal-bars-head`,children:[(0,z.jsxs)(`span`,{children:[`30-day cost · selected: `,t?Os(t):`—`]}),(0,z.jsx)(`span`,{className:`hint`,children:`↑↓ navigate · click any bar`})]}),(0,z.jsx)(`div`,{className:`daily-modal-bars-grid`,role:`img`,"aria-label":`30-day cost histogram`,children:r.map(e=>{let r=e.cost_usd<=0,a=e.date===t,o=r?4:i>0?e.cost_usd/i*100:0,s=[`bar`,r?`zero`:``,a?`sel`:``,e.is_today?`today`:``].filter(Boolean).join(` `);return(0,z.jsx)(`button`,{"data-date":e.date,className:s,style:{height:`${o}%`},disabled:r,"aria-pressed":a,"aria-label":`${e.label} cost ${e.cost_usd>0?D.usd2(e.cost_usd):`no usage`}`,title:e.cost_usd>0?`${e.label} · ${D.usd2(e.cost_usd)}`:`${e.label} · —`,onClick:()=>{r||n(e.date)}},e.date)})}),r.length>0&&(0,z.jsxs)(`div`,{className:`daily-modal-bars-axis`,children:[(0,z.jsx)(`span`,{children:a}),c&&(0,z.jsx)(`span`,{children:c}),(0,z.jsx)(`span`,{children:o})]})]})}function Os(e){let t=[`Jan`,`Feb`,`Mar`,`Apr`,`May`,`Jun`,`Jul`,`Aug`,`Sep`,`Oct`,`Nov`,`Dec`],n=e.split(`-`).map(Number);return`${t[n[1]-1]} ${n[2]}`}function ks(){let e=Ke()?.daily?.rows??[],t=(0,g.useSyncExternalStore)(L,()=>I().openDailyDate),[n,r]=(0,g.useState)(null);(0,g.useEffect)(()=>{t&&r(t)},[]);let i=new Set(e.map(e=>e.date)),a=e[0]?.date??null,o=n&&i.has(n)?n:a;(0,g.useEffect)(()=>zt([{key:`ArrowDown`,scope:`modal`,when:()=>I().openModal===`daily`,action:()=>{let t=o;if(!t)return;let n=e.findIndex(e=>e.date===t);n<0||n>=e.length-1||r(e[n+1].date)}},{key:`ArrowUp`,scope:`modal`,when:()=>I().openModal===`daily`,action:()=>{let t=o;if(!t)return;let n=e.findIndex(e=>e.date===t);n<=0||r(e[n-1].date)}}]),[e,o]);let s=(0,z.jsx)(Gt,{panel:`daily`,panelLabel:`Daily`,triggerId:`daily-modal`,onClick:()=>R(N(`daily`,`daily-modal`))});if(e.length===0)return(0,z.jsx)(Io,{title:`Daily history · last 30`,accentClass:`accent-indigo`,headerExtras:s,children:(0,z.jsx)(`div`,{className:`panel-empty`,children:`No usage history yet.`})});let c=e.findIndex(e=>e.date===o),l=c>=0?c:0,u=e[l],d=e[l+1],f=As(u,d);return(0,z.jsxs)(Io,{title:`Daily history · last 30`,accentClass:`accent-indigo`,headerExtras:s,children:[(0,z.jsx)(Ds,{rows:e,selectedDate:o,onSelect:r}),(0,z.jsx)(ls,{row:f,variant:`daily`,accentClass:`accent-indigo`})]})}function As(e,t){let n=t&&t.cost_usd>0?(e.cost_usd-t.cost_usd)/t.cost_usd:null;return{label:e.label,cost_usd:e.cost_usd,total_tokens:e.total_tokens,input_tokens:e.input_tokens,output_tokens:e.output_tokens,cache_creation_tokens:e.cache_creation_tokens,cache_read_tokens:e.cache_read_tokens,used_pct:null,dollar_per_pct:null,delta_cost_pct:n,is_current:e.is_today,models:e.models,cache_hit_pct:e.cache_hit_pct}}var js=[`#d946ef`,`#c084fc`,`#60a5fa`,`#fbbf24`,`#22d3ee`],Ms=`#64748b`,Ns=5,Ps=400,Fs=150;function Is({trend:e,yMode:t,windowWeeks:n,onProjectSelect:r}){let i=(0,g.useMemo)(()=>{let t=Math.max(0,Math.min(n,e.window_weeks)),r=e.weeks.slice(-t),i=e.projects.map(e=>{let n=e.weekly_cost.slice(-t),r=n.reduce((e,t)=>e+t,0);return{key:e.key,weekly:n,cost:r,color:``}}).sort((e,t)=>t.cost-e.cost),a=i.slice(0,Ns).map((e,t)=>({...e,color:js[t]??Ms})),o=i.slice(Ns),s=r.map((e,t)=>o.reduce((e,n)=>e+(n.weekly[t]??0),0)),c=s.reduce((e,t)=>e+t,0),l=[...a];return o.length>0&&c>0&&l.push({key:`(other)`,weekly:s,cost:c,color:Ms}),{weeks:r,series:l}},[e,n]),a=on();if(i.weeks.length===0||i.series.length===0)return(0,z.jsxs)(`div`,{className:`panel-empty`,children:[`No project activity in the last `,n,` week`,n===1?``:`s`,`.`]});let o=i.weeks.length,s=i.weeks.map((e,t)=>i.series.reduce((e,n)=>e+(n.weekly[t]??0),0)),c=t===`share`?100:Math.max(...s,.01),l=(e,t=`left`)=>o<=1?t===`left`?Ps*.1:Ps*.9:e/(o-1)*Ps,u=Array(o).fill(0),d=i.series.map(e=>{let n=[];for(let e=0;e<o;e++){let t=Fs-u[e]/c*Fs;n.push(`${l(e,`left`).toFixed(2)},${t.toFixed(2)}`),o===1&&n.push(`${l(e,`right`).toFixed(2)},${t.toFixed(2)}`)}for(let r=o-1;r>=0;r--){let i=s[r]??0,a=t===`share`?i>0?(e.weekly[r]??0)/i*100:0:e.weekly[r]??0;u[r]+=a;let d=Fs-u[r]/c*Fs;o===1&&n.push(`${l(r,`right`).toFixed(2)},${d.toFixed(2)}`),n.push(`${l(r,`left`).toFixed(2)},${d.toFixed(2)}`)}return{color:e.color,key:e.key,points:n.join(` `)}}),f=i.weeks.map(e=>(0,z.jsx)(`span`,{children:e.week_label},e.week_start_date));return(0,z.jsxs)(`div`,{className:`projects-trend`,children:[(0,z.jsx)(`svg`,{viewBox:`0 0 ${Ps} ${Fs}`,preserveAspectRatio:`none`,role:`img`,"aria-label":`Stacked area: project ${t===`share`?`share %`:`cost`} over ${o} weeks`,children:d.map(e=>{let t=e.key===`(other)`;return(0,z.jsx)(`polygon`,{fill:e.color,opacity:t?.5:.65,points:e.points,"data-series-key":e.key,onClick:()=>{t||r?.(e.key)},style:{cursor:t?`default`:`pointer`}},e.key)})}),(0,z.jsx)(`div`,{className:`projects-trend-xaxis`,children:f}),(0,z.jsx)(`div`,{className:`projects-trend-legend`,children:i.series.map(e=>{let t=e.key===`(other)`,n=(0,z.jsxs)(z.Fragment,{children:[(0,z.jsx)(`span`,{className:`sw`,style:{background:e.color}}),e.key]});return a&&!t?(0,z.jsx)(`button`,{type:`button`,className:`projects-trend-legend-item`,"data-series-key":e.key,onClick:()=>r?.(e.key),children:n},e.key):(0,z.jsx)(`span`,{className:`projects-trend-legend-item`,"data-series-key":e.key,children:n},e.key)})})]})}function Ls(e,t){let[n,r]=(0,g.useState)(null),[i,a]=(0,g.useState)(!1),[o,s]=(0,g.useState)(null),c=Ke()?.generated_at??``,l=(0,g.useRef)(0),u=(0,g.useRef)(null),d=(0,g.useRef)(null),f=(0,g.useRef)(!1);return(0,g.useEffect)(()=>{if(!e){r(null),a(!1),s(null),l.current=0,u.current=null,d.current=null,f.current=!1;return}let i=u.current!==e||d.current!==t,o=i||n==null;if(o&&f.current&&!i)return;o&&(a(!0),s(null)),i&&(l.current=0),u.current=e,d.current=t,f.current=!0;let c=new AbortController,p=`/api/project/${encodeURIComponent(e)}?weeks=${t}`;return fetch(p,{signal:c.signal}).then(async e=>{if(e.status===404){l.current+=1,l.current>=2?(r(null),s(`Project no longer in cache — close this drill.`),a(!1)):o&&(s(`Couldn't load project detail — will retry on next tick.`),a(!1));return}if(!e.ok){o&&(s(`Couldn't load project detail — will retry on next tick.`),a(!1));return}l.current=0,r(await e.json()),s(null),a(!1)}).catch(e=>{e?.name!==`AbortError`&&o&&(s(`Couldn't load project detail — will retry on next tick.`),a(!1))}).finally(()=>{f.current=!1}),()=>c.abort()},[e,t,c]),{data:n,loading:i,error:o}}function Rs({projectKey:e,windowWeeks:t}){let{data:n,loading:r,error:i}=Ls(e,t),a=Ht(),o={tz:a.resolvedTz,offsetLabel:a.offsetLabel},s=n!=null&&n.key!==e;if(r&&!n||s)return(0,z.jsx)(`div`,{className:`panel-empty`,children:`Loading…`});if(i&&!n)return(0,z.jsx)(`div`,{className:`panel-empty`,children:i});if(!n)return null;let c=n.models[0]?.cost_usd??0,l=c>0?c:1,u=Math.max(0,n.sessions_total-n.sessions.length);return(0,z.jsxs)(`div`,{className:`projects-drill`,"data-testid":`projects-drill`,"aria-live":`polite`,children:[(0,z.jsx)(`div`,{className:`projects-drill-head`,children:(0,z.jsxs)(`span`,{className:`title`,children:[`▾ `,n.key,` · `,n.sessions_total,` session`,n.sessions_total===1?``:`s`,` · `,D.usd2(n.window_cost_usd),` (`,t,`w)`]})}),(0,z.jsxs)(`div`,{className:`projects-drill-grid`,children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`div`,{className:`section-label`,children:`Models (this project)`}),n.models.length===0?(0,z.jsx)(`div`,{className:`muted`,children:`No model data for this window.`}):n.models.map(e=>{let t={"--w":`${e.cost_usd/l*100}%`};return(0,z.jsxs)(`div`,{className:`drill-bar-row`,children:[(0,z.jsx)(`span`,{className:`chip ${ln(e.model)}`,children:e.model}),(0,z.jsx)(`div`,{className:`drill-bar`,style:t}),(0,z.jsx)(`span`,{className:`cost ${un(e.cost_usd)}`,children:D.usd2(e.cost_usd)})]},e.model)})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`div`,{className:`section-label`,children:`Recent sessions →`}),n.sessions.length===0?(0,z.jsx)(`div`,{className:`muted`,children:`No sessions for this window.`}):n.sessions.map((e,t)=>(0,z.jsxs)(`button`,{"data-testid":`drill-session-${t}`,className:`drill-session-row`,onClick:()=>R({type:`OPEN_MODAL`,kind:`session`,sessionId:e.session_id}),children:[(0,z.jsx)(`span`,{className:`started`,children:D.datetimeShort(e.last_activity_at,o)}),(0,z.jsx)(`span`,{className:`chip ${ln(e.primary_model)}`,children:e.primary_model}),(0,z.jsx)(`span`,{className:`cost ${un(e.cost_usd)}`,children:D.usd2(e.cost_usd)})]},e.session_id)),(0,z.jsxs)(`div`,{className:`drill-session-footer`,children:[u>0&&(0,z.jsxs)(`span`,{className:`muted`,children:[`+`,u,` more`]}),(0,z.jsx)(`button`,{type:`button`,"data-testid":`drill-show-in-sessions`,className:`drill-show-in-sessions`,onClick:()=>{R({type:`SET_FILTER`,text:n.key}),R({type:`CLOSE_MODAL`})},children:`Show in Sessions →`})]})]})]})]})}var zs=(e,t)=>e<t?-1:+(e>t),Bs=[{id:`project`,label:`Project`,defaultDirection:`asc`,compare:(e,t)=>zs(e.key,t.key),className:`project`},{id:`sessions`,label:`Sessions`,defaultDirection:`desc`,numeric:!0,compare:(e,t)=>e.sessionsCount-t.sessionsCount},{id:`first_seen`,label:`First seen`,defaultDirection:`asc`,nullKey:e=>e.firstSeenAt,compare:(e,t)=>zs(e.firstSeenAt,t.firstSeenAt),className:`started`},{id:`last_seen`,label:`Last seen`,defaultDirection:`desc`,nullKey:e=>e.lastSeenAt,compare:(e,t)=>zs(e.lastSeenAt,t.lastSeenAt),className:`started`},{id:`cost`,label:`Cost`,defaultDirection:`desc`,numeric:!0,compare:(e,t)=>e.windowCost-t.windowCost},{id:`used_pct`,label:`Used %`,defaultDirection:`desc`,numeric:!0,nullKey:e=>e.windowPct,compare:(e,t)=>e.windowPct-t.windowPct},{id:`share_of_window`,label:`% of week`,defaultDirection:`desc`,numeric:!0,nullKey:e=>e.shareOfWindow,compare:(e,t)=>e.shareOfWindow-t.shareOfWindow}],Vs=[{column:`cost`,direction:`desc`,label:`cost`,arrow:`↓`},{column:`sessions`,direction:`desc`,label:`sessions`,arrow:`↓`},{column:`used_pct`,direction:`desc`,label:`used`,arrow:`↓`},{column:`share_of_window`,direction:`desc`,label:`share`,arrow:`↓`},{column:`first_seen`,direction:`desc`,label:`first`,arrow:`↓`},{column:`last_seen`,direction:`desc`,label:`last`,arrow:`↓`},{column:`project`,direction:`asc`,label:`project`,arrow:`↑`}],Hs=[1,4,8,12];function Us(){let e=Ke(),t=Ht(),n={tz:t.resolvedTz,offsetLabel:t.offsetLabel},r=(0,g.useSyncExternalStore)(L,()=>I().openProjectKey),i=(0,g.useSyncExternalStore)(L,()=>I().prefs.projectsWindowWeeks),a=(0,g.useSyncExternalStore)(L,()=>I().prefs.projectsTrendYMode),o=(0,g.useSyncExternalStore)(L,()=>I().prefs.projectsSortOverride),[s,c]=(0,g.useState)(r??null),[l,u]=(0,g.useState)(!1);(0,g.useEffect)(()=>{if(r){c(r);return}s||c(e?.projects?.current_week?.rows?.[0]?.key??null)},[r,e?.projects?.current_week?.rows]);let d=e?.projects?.trend??null,f=i,p=d?.window_weeks??0,m=(e,t)=>{R({type:`SAVE_PREFS`,patch:{[e]:t}})},h=e=>{c(t=>t===e?null:e)},_=(d?.projects??[]).map(e=>{let t=e.weekly_cost.slice(-i),n=e.weekly_pct.slice(-i),r=e.sessions_per_week.slice(-i),a=e.first_seen_per_week.slice(-i),o=e.last_seen_per_week.slice(-i),s=t.reduce((e,t)=>e+t,0),c=n.reduce((e,t)=>t==null?e:(e??0)+t,null),l=r.reduce((e,t)=>e+t,0),u=a.reduce((e,t)=>t==null?e:e==null||t<e?t:e,null),d=o.reduce((e,t)=>t==null?e:e==null||t>e?t:e,null);return{key:e.key,sessionsCount:l,firstSeenAt:u,lastSeenAt:d,windowCost:s,windowPct:c,shareOfWindow:null}}),v=_.reduce((e,t)=>e+t.windowCost,0);for(let e of _)e.shareOfWindow=v>0?e.windowCost/v*100:null;let y=o?de(_,Bs,o):de(_,Bs,{column:`cost`,direction:`desc`}),b=y.filter(e=>e.windowCost>0).slice(0,10),x=y.length-b.length,S=l?y:b,C=x>0,w=on(),T=(()=>{if(!o)return 0;let e=Vs.findIndex(e=>e.column===o.column&&e.direction===o.direction);return e===-1?0:e})(),ee=()=>{let e=Vs[(T+1)%Vs.length];R({type:`SET_TABLE_SORT`,table:`projects`,override:{column:e.column,direction:e.direction}})},te=Vs[T];return V([{key:`1`,scope:`modal`,action:()=>m(`projectsWindowWeeks`,1)},{key:`4`,scope:`modal`,action:()=>m(`projectsWindowWeeks`,4)},{key:`8`,scope:`modal`,action:()=>m(`projectsWindowWeeks`,8)},{key:`0`,scope:`modal`,action:()=>m(`projectsWindowWeeks`,12)},{key:`s`,scope:`modal`,action:()=>m(`projectsTrendYMode`,a===`share`?`absolute`:`share`)},{key:`ArrowUp`,scope:`modal`,action:()=>{if(S.length===0)return;let e=S.findIndex(e=>e.key===s);c(S[e<=0?S.length-1:e-1].key)}},{key:`ArrowDown`,scope:`modal`,action:()=>{if(S.length===0)return;let e=S.findIndex(e=>e.key===s);c(S[e===-1||e===S.length-1?0:e+1].key)}},{key:`Enter`,scope:`modal`,action:()=>{s?c(null):S.length>0&&c(S[0].key)}}]),(0,z.jsx)(Io,{title:`Projects · last ${i}w`,accentClass:`accent-magenta`,headerExtras:(0,z.jsx)(Gt,{panel:`projects`,panelLabel:`Projects`,triggerId:`projects-modal`,dataTestId:`share-icon-projects-modal`,onClick:()=>R(N(`projects`,`projects-modal`,{windowWeeks:i}))}),children:(0,z.jsxs)(`div`,{className:`projects-modal-body`,children:[(0,z.jsxs)(`div`,{className:`projects-controls`,role:`radiogroup`,"aria-label":`Window`,children:[Hs.map(e=>(0,z.jsxs)(`button`,{type:`button`,role:`radio`,"aria-checked":i===e,className:`pill ${i===e?`on`:``}`,onClick:()=>m(`projectsWindowWeeks`,e),children:[e,`w`]},`window-${e}`)),(0,z.jsx)(`span`,{className:`sep`,"aria-hidden":`true`,children:`|`}),(0,z.jsx)(`button`,{type:`button`,role:`radio`,"aria-checked":a===`share`,className:`pill ${a===`share`?`on`:``}`,onClick:()=>m(`projectsTrendYMode`,`share`),children:`share %`}),(0,z.jsx)(`button`,{type:`button`,role:`radio`,"aria-checked":a===`absolute`,className:`pill ${a===`absolute`?`on`:``}`,onClick:()=>m(`projectsTrendYMode`,`absolute`),children:`$ absolute`})]}),p>0&&p<f&&(0,z.jsxs)(`div`,{className:`projects-notice`,children:[`Showing `,p,` week`,p===1?``:`s`,` (need more history for the full window).`]}),d?(0,z.jsx)(Is,{trend:d,yMode:a,windowWeeks:i,onProjectSelect:e=>c(e)}):(0,z.jsx)(`div`,{className:`panel-empty`,children:`Projects trend unavailable.`}),w&&(0,z.jsxs)(`button`,{type:`button`,className:`projects-mobile-sort`,"data-testid":`projects-mobile-sort`,onClick:ee,"aria-label":`Cycle sort column`,children:[`Sort: `,te.label,` `,te.arrow]}),(0,z.jsxs)(`table`,{className:`projects-table`,children:[(0,z.jsx)(tn,{columns:Bs,override:o,onChange:e=>R({type:`SET_TABLE_SORT`,table:`projects`,override:e}),accentVar:`--accent-magenta`}),(0,z.jsx)(`tbody`,{children:S.map(e=>(0,z.jsxs)(g.Fragment,{children:[(0,z.jsxs)(`tr`,{"data-testid":`projects-table-row`,"data-cost":e.windowCost,"data-sessions":e.sessionsCount,"aria-expanded":s===e.key,className:s===e.key?`selected`:``,onClick:()=>h(e.key),children:[(0,z.jsx)(`td`,{className:`project`,children:e.key}),(0,z.jsx)(`td`,{children:e.sessionsCount}),(0,z.jsx)(`td`,{className:`started first-seen`,children:D.dateShort(e.firstSeenAt,n)??`—`}),(0,z.jsx)(`td`,{className:`started last-seen`,children:D.dateShort(e.lastSeenAt,n)??`—`}),(0,z.jsx)(`td`,{className:un(e.windowCost),children:D.usd2(e.windowCost)}),(0,z.jsx)(`td`,{children:e.windowPct==null?`—`:D.pct0(e.windowPct)}),(0,z.jsx)(`td`,{children:e.shareOfWindow==null?`—`:D.pct0(e.shareOfWindow)})]}),w&&s===e.key&&(0,z.jsx)(`tr`,{className:`projects-drill-row`,"aria-hidden":`false`,children:(0,z.jsx)(`td`,{colSpan:7,children:(0,z.jsx)(Rs,{projectKey:e.key,windowWeeks:i})})})]},e.key))})]}),C&&(0,z.jsx)(`button`,{type:`button`,className:`projects-table-toggle`,"data-testid":`projects-table-toggle`,"aria-expanded":l,onClick:()=>u(e=>!e),children:l?`Show top 10 active`:`Show all ${y.length} projects (+${x})`}),!w&&s&&(0,z.jsx)(Rs,{projectKey:s,windowWeeks:i}),(0,z.jsxs)(`div`,{className:`projects-modal-footer-hint`,"data-testid":`projects-modal-footer-hint`,"aria-live":`off`,children:[(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`kbd`,{children:`1`}),`/`,(0,z.jsx)(`kbd`,{children:`4`}),`/`,(0,z.jsx)(`kbd`,{children:`8`}),`/`,(0,z.jsx)(`kbd`,{children:`0`}),` window`]}),(0,z.jsx)(`span`,{className:`sep`,"aria-hidden":`true`,children:`·`}),(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`kbd`,{children:`↑↓`}),` row`]}),(0,z.jsx)(`span`,{className:`sep`,"aria-hidden":`true`,children:`·`}),(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`kbd`,{children:`Enter`}),` drill`]}),(0,z.jsx)(`span`,{className:`sep`,"aria-hidden":`true`,children:`·`}),(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`kbd`,{children:`s`}),` share/$`]}),(0,z.jsx)(`span`,{className:`sep`,"aria-hidden":`true`,children:`·`}),(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`kbd`,{children:`Esc`}),` close`]}),(0,z.jsx)(`span`,{className:`sep`,"aria-hidden":`true`,children:`·`}),(0,z.jsx)(yt,{})]})]})})}var Ws=100;function Gs({alert:e,ctx:t}){if(e.axis===`weekly`){let n=e.context.week_start_date?D.weekStart(e.context.week_start_date,t):null,r=e.context.dollars_per_percent;return(0,z.jsxs)(`span`,{className:`alert-context alert-context--weekly`,children:[n?`Week of ${n}`:`Week —`,r!=null&&(0,z.jsxs)(z.Fragment,{children:[` · `,(0,z.jsxs)(`span`,{className:`num`,children:[`$`,r.toFixed(2),`/1%`]})]})]})}return(0,z.jsxs)(`span`,{className:`alert-context alert-context--five-hour`,children:[`Block `,e.context.block_start_at?D.timeOnly(e.context.block_start_at,t):`—`]})}function Ks({alert:e}){let t=e.axis===`weekly`?e.context.cumulative_cost_usd:e.context.block_cost_usd;return(0,z.jsx)(`span`,{className:`num`,children:D.usd2(t??null)})}function qs(){let e=(0,g.useSyncExternalStore)(L,()=>I().alerts),t=Ht(),n={tz:t.resolvedTz,offsetLabel:t.offsetLabel},r=e.slice(0,Ws);return r.length===0?(0,z.jsx)(Io,{title:`Recent alerts`,accentClass:`accent-amber`,children:(0,z.jsx)(`div`,{className:`panel-empty`,children:`No alerts yet. Alerts appear when usage crosses 90% or 95%.`})}):(0,z.jsx)(Io,{title:`Recent alerts`,accentClass:`accent-amber`,children:(0,z.jsxs)(`div`,{className:`alerts-modal-body`,children:[(0,z.jsxs)(`table`,{className:`alerts-table`,children:[(0,z.jsx)(`thead`,{children:(0,z.jsxs)(`tr`,{children:[(0,z.jsx)(`th`,{scope:`col`,children:`%`}),(0,z.jsx)(`th`,{scope:`col`,children:`Axis`}),(0,z.jsx)(`th`,{scope:`col`,children:`Cost`}),(0,z.jsx)(`th`,{scope:`col`,children:`Context`}),(0,z.jsx)(`th`,{scope:`col`,children:`Alerted`})]})}),(0,z.jsx)(`tbody`,{children:r.map(e=>{let t=e.threshold>=95?`red`:`amber`;return(0,z.jsxs)(`tr`,{className:`alert-modal-row`,children:[(0,z.jsxs)(`td`,{className:`alert-threshold severity-${t} ${t} num`,children:[e.threshold,`%`]}),(0,z.jsx)(`td`,{children:(0,z.jsx)(`span`,{className:`chip chip--${e.axis}`,children:e.axis===`weekly`?`WEEKLY`:`5H-BLOCK`})}),(0,z.jsx)(`td`,{className:`num`,children:(0,z.jsx)(Ks,{alert:e})}),(0,z.jsx)(`td`,{children:(0,z.jsx)(Gs,{alert:e,ctx:n})}),(0,z.jsx)(`td`,{className:`alert-when`,children:D.relativeOrAbsolute(e.alerted_at,n)})]},e.id)})})]}),e.length>Ws&&(0,z.jsxs)(`div`,{className:`alerts-modal-foot`,children:[`Showing `,Ws,` of `,e.length,` most recent`]})]})})}function Js(){let e=(0,g.useSyncExternalStore)(L,()=>I().openModal);if(!e)return null;switch(e){case`current-week`:return(0,z.jsx)(Uo,{});case`forecast`:return(0,z.jsx)(Yo,{});case`trend`:return(0,z.jsx)(is,{});case`session`:return(0,z.jsx)(ss,{});case`weekly`:return(0,z.jsx)(ms,{});case`monthly`:return(0,z.jsx)(hs,{});case`block`:return(0,z.jsx)(Ts,{});case`daily`:return(0,z.jsx)(ks,{});case`projects`:return(0,z.jsx)(Us,{});case`alerts`:return(0,z.jsx)(qs,{})}}var X=class extends Error{code;constructor(e,t,n,r){super(n),this.status=e,this.field=t,this.code=r}};async function Ys(e){if(!e.ok){let t={};try{t=await e.json()}catch{}throw new X(e.status,t.field,t.error??`HTTP ${e.status}`,t.code)}return e.json()}async function Xs(e,t){return Ys(await fetch(`/api/share/templates?panel=${encodeURIComponent(e)}`,{signal:t?.signal}))}async function Zs(e,t){return Ys(await fetch(`/api/share/render`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(e),signal:t?.signal}))}var Qs=[{id:`recap`,label:`Recap`,placeholderDescription:`Text + tiny chart`},{id:`visual`,label:`Visual`,placeholderDescription:`Coming in M2`},{id:`detail`,label:`Detail`,placeholderDescription:`Coming in M2`}];function $s(e){return e.endsWith(`-recap`)?`recap`:e.endsWith(`-visual`)?`visual`:e.endsWith(`-detail`)?`detail`:null}function ec({panel:e,templates:t,error:n,selectedTemplateId:r,onSelect:i}){if(n)return(0,z.jsx)(`div`,{className:`share-gallery-error`,role:`alert`,children:n});let a={};for(let e of t??[]){let t=$s(e.id);t&&(a[t]=e)}return(0,z.jsx)(`div`,{className:`share-gallery`,role:`radiogroup`,"aria-label":`Report template`,children:Qs.map(e=>{let n=a[e.id];if(t==null)return(0,z.jsxs)(`div`,{className:`share-tile share-tile-skeleton`,"aria-hidden":`true`,children:[(0,z.jsx)(`div`,{className:`share-tile-skeleton-bar`}),(0,z.jsx)(`div`,{className:`share-tile-skeleton-bar short`})]},e.id);if(!n)return(0,z.jsxs)(`button`,{type:`button`,className:`share-tile share-tile-disabled`,disabled:!0,"aria-disabled":`true`,role:`radio`,"aria-checked":`false`,title:`${e.label} — ${e.placeholderDescription}`,children:[(0,z.jsx)(`div`,{className:`share-tile-label`,children:e.label}),(0,z.jsx)(`div`,{className:`share-tile-desc`,children:e.placeholderDescription})]},e.id);let o=n.id===r;return(0,z.jsxs)(`button`,{type:`button`,className:`share-tile`+(o?` share-tile-selected`:``),role:`radio`,"aria-checked":o,"data-template-id":n.id,onClick:()=>i(n.id),children:[(0,z.jsx)(`div`,{className:`share-tile-label`,children:n.label}),(0,z.jsx)(`div`,{className:`share-tile-desc`,children:n.description})]},e.id)})})}function tc({options:e,onChange:t}){let n=n=>t({...e,...n}),r=n=>t({...e,period:{...e.period,...n}}),i=e=>{if(e===``){n({top_n:null});return}let t=Number.parseInt(e,10);Number.isNaN(t)||n({top_n:Math.max(1,t)})};return(0,z.jsxs)(`div`,{className:`share-knobs`,children:[(0,z.jsxs)(`div`,{className:`share-knob`,children:[(0,z.jsx)(`label`,{htmlFor:`share-knob-period`,children:`Period`}),(0,z.jsxs)(`select`,{id:`share-knob-period`,value:e.period.kind,onChange:e=>r({kind:e.target.value}),children:[(0,z.jsx)(`option`,{value:`current`,children:`This week`}),(0,z.jsx)(`option`,{value:`previous`,children:`Previous week`}),(0,z.jsx)(`option`,{value:`custom`,children:`Custom`})]}),e.period.kind===`custom`?(0,z.jsxs)(`div`,{className:`share-knob-period-custom`,children:[(0,z.jsxs)(`label`,{className:`share-knob-sublabel`,children:[(0,z.jsx)(`span`,{children:`Start`}),(0,z.jsx)(`input`,{type:`date`,value:e.period.start?.slice(0,10)??``,onChange:e=>r({start:e.target.value}),"aria-label":`Custom period start date`})]}),(0,z.jsxs)(`label`,{className:`share-knob-sublabel`,children:[(0,z.jsx)(`span`,{children:`End`}),(0,z.jsx)(`input`,{type:`date`,value:e.period.end?.slice(0,10)??``,onChange:e=>r({end:e.target.value}),"aria-label":`Custom period end date`})]})]}):null]}),(0,z.jsxs)(`div`,{className:`share-knob`,children:[(0,z.jsx)(`span`,{className:`share-knob-label`,children:`Theme`}),(0,z.jsxs)(`div`,{className:`share-knob-radiogroup`,role:`radiogroup`,"aria-label":`Theme`,children:[(0,z.jsxs)(`label`,{className:`share-knob-radio`,children:[(0,z.jsx)(`input`,{type:`radio`,name:`share-theme`,value:`light`,checked:e.theme===`light`,onChange:()=>n({theme:`light`})}),(0,z.jsx)(`span`,{children:`Light`})]}),(0,z.jsxs)(`label`,{className:`share-knob-radio`,children:[(0,z.jsx)(`input`,{type:`radio`,name:`share-theme`,value:`dark`,checked:e.theme===`dark`,onChange:()=>n({theme:`dark`})}),(0,z.jsx)(`span`,{children:`Dark`})]})]})]}),(0,z.jsxs)(`div`,{className:`share-knob`,children:[(0,z.jsx)(`label`,{htmlFor:`share-knob-topn`,children:`Top-N`}),(0,z.jsx)(`input`,{id:`share-knob-topn`,type:`number`,min:1,step:1,inputMode:`numeric`,value:e.top_n??``,onChange:e=>i(e.target.value),"aria-label":`Top-N`})]}),(0,z.jsxs)(`div`,{className:`share-knob`,children:[(0,z.jsx)(`span`,{className:`share-knob-label`,children:`Projects`}),(0,z.jsx)(`button`,{type:`button`,className:`share-knob-allowlist-stub`,disabled:!0,"aria-disabled":`true`,title:`Project allowlist — coming in M3+`,children:`All projects`})]}),(0,z.jsx)(`div`,{className:`share-knob`,children:(0,z.jsxs)(`label`,{className:`share-knob-checkbox`,children:[(0,z.jsx)(`input`,{type:`checkbox`,checked:e.show_chart,onChange:e=>n({show_chart:e.target.checked}),"aria-label":`Include chart in export`}),(0,z.jsx)(`span`,{children:`Show chart`})]})}),(0,z.jsx)(`div`,{className:`share-knob`,children:(0,z.jsxs)(`label`,{className:`share-knob-checkbox`,children:[(0,z.jsx)(`input`,{type:`checkbox`,checked:e.show_table,onChange:e=>n({show_table:e.target.checked}),"aria-label":`Include table in export`}),(0,z.jsx)(`span`,{children:`Show table`})]})}),(0,z.jsx)(`div`,{className:`share-knob`,children:(0,z.jsxs)(`label`,{className:`share-knob-checkbox`,children:[(0,z.jsx)(`input`,{type:`checkbox`,checked:!e.reveal_projects,onChange:e=>n({reveal_projects:!e.target.checked}),"aria-label":`Anonymize project names on export`}),(0,z.jsx)(`span`,{children:`Anon on export`})]})})]})}var nc=200,rc={status:`idle`,body:``,contentType:``,errorMessage:null,errorField:null};function ic({panel:e,templateId:t,options:n}){let[r,i]=(0,g.useState)(rc),a=(0,g.useRef)(null),o=(0,g.useRef)(0);return(0,g.useEffect)(()=>{if(!t){i(rc);return}i(e=>({...e,status:`loading`}));let r=++o.current,s=setTimeout(()=>{a.current?.abort();let s=new AbortController;a.current=s,Zs({panel:e,template_id:t,options:{...n,reveal_projects:!0}},{signal:s.signal}).then(e=>{r===o.current&&i({status:`ready`,body:e.body,contentType:e.content_type,errorMessage:null,errorField:null})}).catch(e=>{if(r===o.current&&!(e&&typeof e==`object`&&e.name===`AbortError`)){if(e instanceof X){i({status:`error`,body:``,contentType:``,errorMessage:e.message??`HTTP ${e.status}`,errorField:e.field??null});return}i({status:`error`,body:``,contentType:``,errorMessage:e.message??`Unknown error`,errorField:null})}})},nc);return()=>{clearTimeout(s)}},[e,t,n]),(0,g.useEffect)(()=>()=>{a.current?.abort()},[]),t?r.status===`error`?(0,z.jsxs)(`div`,{className:`share-preview share-preview-error`,role:`alert`,children:[(0,z.jsx)(`div`,{className:`share-preview-error-title`,children:`Preview failed`}),(0,z.jsxs)(`div`,{className:`share-preview-error-message`,children:[r.errorMessage,r.errorField?(0,z.jsxs)(`span`,{className:`share-preview-error-field`,children:[` `,`(field: `,r.errorField,`)`]}):null]})]}):r.status===`loading`||r.status===`idle`?(0,z.jsx)(`div`,{className:`share-preview share-preview-loading`,"aria-busy":`true`,children:`Rendering preview…`}):n.format===`md`?(0,z.jsx)(`pre`,{className:`share-preview share-preview-md`,"aria-label":`Markdown preview`,children:r.body}):(0,z.jsx)(`iframe`,{className:`share-preview share-preview-iframe`,title:`Report preview (decorative)`,tabIndex:-1,sandbox:`allow-same-origin`,srcDoc:r.body}):(0,z.jsx)(`div`,{className:`share-preview share-preview-empty`,children:`Select a template to preview.`})}var ac={"current-week":`Current week`,trend:`Trend`,weekly:`Weekly`,daily:`Daily`,monthly:`Monthly`,blocks:`5-hour blocks`,forecast:`Forecast`,sessions:`Sessions`,projects:`Projects`};function oc(e){return ac[e]}function sc(e){switch(e){case`md`:return`md`;case`html`:return`html`;case`svg`:return`svg`}}async function cc(e){if(!e.ok){let t={};try{t=await e.json()}catch{}throw new X(e.status,t.field,t.error??`HTTP ${e.status}`)}return e.json()}async function lc(e){return cc(await fetch(`/api/share/presets`,{signal:e?.signal}))}async function uc(e,t){return cc(await fetch(`/api/share/presets`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(e),signal:t?.signal}))}async function dc(e,t,n){let r=await fetch(`/api/share/presets/${encodeURIComponent(e)}/${encodeURIComponent(t)}`,{method:`DELETE`,signal:n?.signal});if(!r.ok){let e={};try{e=await r.json()}catch{}throw new X(r.status,void 0,e.error??`HTTP ${r.status}`)}}async function fc(e){return cc(await fetch(`/api/share/history`,{signal:e?.signal}))}async function Z(e,t){return cc(await fetch(`/api/share/history`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(e),signal:t?.signal}))}function pc({panel:e,templateId:t,options:n,onSaved:r,onCancel:i}){let[a,o]=(0,g.useState)(``),[s,c]=(0,g.useState)(!1),[l,u]=(0,g.useState)(null);async function d(){let i=a.trim();if(!i){u(`Name is required`);return}if(i.length>64){u(`Name must be 64 characters or fewer`);return}if(i.includes(`/`)){u(`Name cannot contain '/'`);return}c(!0),u(null);try{await uc({panel:e,name:i,template_id:t,options:n}),R({type:`SHOW_STATUS_TOAST`,text:`Saved preset "${i}"`}),r()}catch(e){u((e instanceof X?e.message??`HTTP ${e.status}`:e.message)??`Save failed`)}finally{c(!1)}}return(0,z.jsxs)(`div`,{className:`share-save-popover`,role:`dialog`,"aria-label":`Save preset`,children:[(0,z.jsxs)(`label`,{className:`share-save-label`,children:[`Preset name`,(0,z.jsx)(`input`,{type:`text`,className:`share-save-input`,autoFocus:!0,value:a,maxLength:64,disabled:s,onChange:e=>o(e.target.value),onKeyDown:e=>{e.key===`Enter`?(e.preventDefault(),e.stopPropagation(),d()):e.key===`Escape`&&(e.preventDefault(),e.stopPropagation(),i())}})]}),l?(0,z.jsx)(`div`,{className:`share-save-error`,role:`alert`,children:l}):null,(0,z.jsxs)(`div`,{className:`share-save-actions`,children:[(0,z.jsx)(`button`,{type:`button`,onClick:i,disabled:s,children:`Cancel`}),(0,z.jsx)(`button`,{type:`button`,onClick:()=>void d(),disabled:s,children:s?`Saving…`:`Save`})]})]})}async function mc(e,t,n){let r=new Blob([e],{type:`image/svg+xml`}),i=URL.createObjectURL(r);try{let e=new Image;e.src=i,await e.decode();let r=document.createElement(`canvas`);r.width=e.naturalWidth*t,r.height=e.naturalHeight*t;let a=r.getContext(`2d`);if(!a)throw Error(`Could not acquire 2D canvas context`);a.fillStyle=n,a.fillRect(0,0,r.width,r.height),a.scale(t,t),a.drawImage(e,0,0);let o=await new Promise(e=>{r.toBlob(t=>e(t),`image/png`)});if(o)return o;let s=r.toDataURL(`image/png`);return(await fetch(s)).blob()}finally{URL.revokeObjectURL(i)}}function hc(e){let t=document.createElement(`iframe`);t.setAttribute(`aria-hidden`,`true`),t.style.cssText=`position:fixed;right:0;bottom:0;width:0;height:0;border:0`,document.body.appendChild(t);let n=t.contentDocument;if(!n)throw Error(`iframe contentDocument unavailable`);n.open(),n.write(e),n.close();try{t.contentWindow?.focus(),t.contentWindow?.print()}catch{let t=window.open(``,`_blank`,`noopener,noreferrer`);t&&(t.document.open(),t.document.write(e),t.document.close())}setTimeout(()=>t.remove(),1e3)}function gc(e){Z({panel:e.panel,template_id:e.template_id,options:e.options,format:e.options.format,destination:e.destination}).catch(()=>{})}function _c(e){return e===`light`?`#ffffff`:`#0f172a`}function vc(e,t){return`cctally-${e}-${new Date().toISOString().slice(0,10).replaceAll(`-`,``)}.${sc(t)}`}function yc(e){switch(e){case`md`:return`text/markdown;charset=utf-8`;case`html`:return`text/html;charset=utf-8`;case`svg`:return`image/svg+xml;charset=utf-8`}}function bc(e,t){let n=URL.createObjectURL(t),r=document.createElement(`a`);r.href=n,r.download=e,r.style.display=`none`,document.body.appendChild(r),r.click(),document.body.removeChild(r),setTimeout(()=>URL.revokeObjectURL(n),0)}function xc({panel:e,templateId:t,options:n,onOptionsChange:r}){let[i,a]=(0,g.useState)(null),[o,s]=(0,g.useState)(null),[c,l]=(0,g.useState)(!1),u=(0,g.useRef)(null);(0,g.useEffect)(()=>()=>{u.current!=null&&clearTimeout(u.current)},[]);let[d,f]=(0,g.useState)(!1),p=(0,g.useRef)(null);(0,g.useEffect)(()=>{if(!d)return;function e(e){let t=p.current;t&&(t.contains(e.target)||f(!1))}return document.addEventListener(`mousedown`,e),()=>document.removeEventListener(`mousedown`,e)},[d]),(0,g.useEffect)(()=>{s(null)},[n.format,t]);let m=t==null||i!=null,h=e=>R({type:`SHOW_STATUS_TOAST`,text:e}),_=async()=>{if(!t)throw Error(`no template selected`);return{body:(await Zs({panel:e,template_id:t,options:n})).body,format:n.format}},v=async()=>{if(!(m||!t)){a(`copy`),s(null);try{let{body:r}=await _();if(!navigator.clipboard||typeof navigator.clipboard.writeText!=`function`)throw Error(`Clipboard API unavailable in this browser`);await navigator.clipboard.writeText(r),h(`Copied`),gc({panel:e,template_id:t,options:n,destination:`copy`})}catch(e){s(`Copy failed: ${e instanceof X?e.message??`HTTP ${e.status}`:e.message}`)}finally{a(null)}}},y=async()=>{if(!(m||!t)){a(`download`),s(null);try{let{body:r,format:i}=await _(),a=new Blob([r],{type:yc(i)});bc(vc(e,i),a),h(`Downloaded`),gc({panel:e,template_id:t,options:n,destination:`download`})}catch(e){s(`Download failed: ${e instanceof X?e.message??`HTTP ${e.status}`:e.message}`)}finally{a(null)}}},b=async()=>{if(!(m||!t)){a(`basket`),s(null);try{let r=await Zs({panel:e,template_id:t,options:n}),i=xe({panel:e,template_id:t,options:n,added_at:new Date().toISOString(),data_digest_at_add:r.snapshot.data_digest,kernel_version:r.snapshot.kernel_version,label_hint:oc(e)});R({type:`BASKET_ADD`,item:i});let a=I().basket;if(a.rejectedReason===`capacity`)return;l(!0),u.current!=null&&clearTimeout(u.current),u.current=setTimeout(()=>l(!1),800),R({type:`SHOW_STATUS_TOAST`,text:`Added ${i.label_hint} to basket (${a.items.length})`})}catch(e){s(`Add to basket failed: ${e instanceof X?e.message??`HTTP ${e.status}`:e.message}`)}finally{a(null)}}},x=async()=>{if(!(m||!t)){a(`open`),s(null);try{let{body:r,format:i}=await _(),a=new Blob([r],{type:yc(i)}),o=URL.createObjectURL(a);window.open(o,`_blank`,`noopener,noreferrer`),gc({panel:e,template_id:t,options:n,destination:`open`})}catch(e){s(`Open failed: ${e instanceof X?e.message??`HTTP ${e.status}`:e.message}`)}finally{a(null)}}},S=async()=>{if(!(!t||n.format!==`svg`||m)){a(`png`),s(null);try{let{body:r}=await _(),i=await mc(r,2,_c(n.theme));bc(vc(e,`svg`).replace(/\.svg$/,`.png`),i),h(`PNG downloaded`),gc({panel:e,template_id:t,options:n,destination:`png`})}catch(e){s(`PNG export failed: ${e instanceof X?e.message??`HTTP ${e.status}`:e.message}`)}finally{a(null)}}},C=async()=>{if(!(!t||n.format!==`html`||m)){a(`print`),s(null);try{let{body:r}=await _();hc(r),gc({panel:e,template_id:t,options:n,destination:`print`})}catch(e){s(`Print failed: ${e instanceof X?e.message??`HTTP ${e.status}`:e.message}`)}finally{a(null)}}},w=n.format===`md`&&!m,T=(n.format===`html`||n.format===`svg`)&&!m,ee=n.format===`svg`&&!m,te=n.format===`html`&&!m;return(0,z.jsxs)(`div`,{className:`share-actions`,children:[(0,z.jsxs)(`div`,{className:`share-format-row`,role:`radiogroup`,"aria-label":`Export format`,children:[(0,z.jsx)(`span`,{className:`share-format-label`,children:`Format:`}),[`md`,`html`,`svg`].map(e=>(0,z.jsxs)(`label`,{className:`share-format-radio`,children:[(0,z.jsx)(`input`,{type:`radio`,name:`share-format`,value:e,checked:n.format===e,onChange:()=>r({...n,format:e})}),(0,z.jsx)(`span`,{children:e})]},e))]}),(0,z.jsxs)(`div`,{className:`share-action-row`,children:[(0,z.jsx)(`button`,{type:`button`,className:`share-action share-action-copy`,onClick:v,disabled:!w,title:n.format===`md`?i===`copy`?`Copying…`:`Copy to clipboard`:`Copy is available for Markdown only`,children:i===`copy`?`Copying…`:`Copy`}),(0,z.jsx)(`button`,{type:`button`,className:`share-action share-action-download`,onClick:y,disabled:m,title:i===`download`?`Downloading…`:`Download file`,children:i===`download`?`Downloading…`:`Download`}),(0,z.jsx)(`button`,{type:`button`,className:`share-action share-action-open`,onClick:x,disabled:!T,title:n.format===`html`||n.format===`svg`?i===`open`?`Opening…`:`Open in new tab`:`Open is available for HTML/SVG`,children:i===`open`?`Opening…`:`Open`}),(0,z.jsx)(`button`,{type:`button`,className:`share-action share-action-png`,onClick:S,disabled:!ee,title:n.format===`svg`?i===`png`?`Rasterizing…`:`Download PNG (rasterized from SVG)`:`PNG export — available for SVG format only`,children:i===`png`?`Rasterizing…`:`PNG`}),(0,z.jsx)(`button`,{type:`button`,className:`share-action share-action-print`,onClick:C,disabled:!te,title:n.format===`html`?i===`print`?`Opening print dialog…`:`Open the browser print dialog (save as PDF)`:`Print → PDF — available for HTML format only`,children:i===`print`?`Printing…`:`Print → PDF`}),(0,z.jsx)(`button`,{type:`button`,className:`share-action share-action-basket${c?` share-action-basket-added`:``}`,onClick:b,disabled:m,title:m&&t==null?`Pick a template first`:i===`basket`?`Adding to basket…`:`Add this section to the report basket`,children:c?`✓ Added`:i===`basket`?`Adding…`:`+ Basket`})]}),(0,z.jsxs)(`div`,{className:`share-save-preset-row`,ref:p,children:[(0,z.jsx)(`button`,{type:`button`,className:`share-save-preset`,disabled:t==null||i!=null,onClick:()=>f(e=>!e),"aria-haspopup":`dialog`,"aria-expanded":d,title:t==null?`Pick a template first`:`Save the current recipe as a named preset`,children:`Save preset…`}),d&&t?(0,z.jsx)(pc,{panel:e,templateId:t,options:n,onSaved:()=>f(!1),onCancel:()=>f(!1)}):null]}),o?(0,z.jsx)(`div`,{className:`share-action-error`,role:`alert`,children:o}):null]})}function Sc(e){let t=new Date(e);return Number.isNaN(t.getTime())?e:t.toLocaleString()}function Cc({panel:e,onPick:t,onManage:n}){let[r,i]=(0,g.useState)(!1),[a,o]=(0,g.useState)({}),[s,c]=(0,g.useState)([]),[l,u]=(0,g.useState)(null),d=(0,g.useRef)(null);(0,g.useEffect)(()=>{if(!r)return;let t=new AbortController;return u(null),Promise.all([lc({signal:t.signal}),fc({signal:t.signal})]).then(([t,n])=>{o(t.presets[e]??{}),c(n.history.filter(t=>t.panel===e).slice().reverse())}).catch(e=>{e?.name!==`AbortError`&&u((e instanceof X?e.message??`HTTP ${e.status}`:e.message)??`Failed to load presets`)}),()=>t.abort()},[r,e]),(0,g.useEffect)(()=>{if(!r)return;function e(e){let t=d.current;t&&(t.contains(e.target)||i(!1))}return document.addEventListener(`mousedown`,e),()=>document.removeEventListener(`mousedown`,e)},[r]);let f=Object.keys(a).sort();return(0,z.jsxs)(`div`,{className:`share-presets-dropdown`,ref:d,children:[(0,z.jsx)(`button`,{type:`button`,className:`share-presets-trigger`,"aria-haspopup":`menu`,"aria-expanded":r,onClick:()=>i(e=>!e),children:`presets ▾`}),r?(0,z.jsxs)(`div`,{className:`share-presets-menu`,role:`menu`,children:[l?(0,z.jsx)(`div`,{className:`share-presets-error`,role:`alert`,children:l}):null,f.length===0&&!l?(0,z.jsx)(`div`,{className:`share-presets-empty`,children:`No saved presets yet.`}):null,f.length>0?(0,z.jsx)(`ul`,{className:`share-presets-list`,children:f.map(e=>(0,z.jsx)(`li`,{children:(0,z.jsx)(`button`,{type:`button`,role:`menuitem`,className:`share-presets-item`,onClick:()=>{t(a[e].template_id,a[e].options),i(!1)},children:e})},e))}):null,s.length>0?(0,z.jsxs)(`div`,{className:`share-presets-history`,children:[(0,z.jsx)(`div`,{className:`share-presets-history-heading`,role:`presentation`,children:`Recent shares`}),(0,z.jsx)(`ul`,{className:`share-presets-history-list`,children:s.map(e=>(0,z.jsx)(`li`,{children:(0,z.jsxs)(`button`,{type:`button`,role:`menuitem`,className:`share-presets-history-item`,onClick:()=>{t(e.template_id,e.options),i(!1)},title:`${e.template_id} · ${e.format??`unknown`} · ${e.exported_at}`,children:[(0,z.jsx)(`span`,{className:`share-presets-history-template`,children:e.template_id}),(0,z.jsxs)(`span`,{className:`share-presets-history-meta`,children:[` · `,e.format??`unknown`,` · `,Sc(e.exported_at)]})]})},e.recipe_id))})]}):null,(0,z.jsx)(`div`,{className:`share-presets-footer`,children:(0,z.jsx)(`button`,{type:`button`,role:`menuitem`,className:`share-presets-manage`,onClick:()=>{n(),i(!1)},children:`Manage presets…`})})]}):null]})}var wc=`share-manage-presets-title`;function Tc({open:e,onClose:t}){let[n,r]=(0,g.useState)([]),[i,a]=(0,g.useState)(!1),[o,s]=(0,g.useState)(null);V((0,g.useMemo)(()=>e?[{key:`Escape`,scope:`modal`,action:t}]:[],[e,t]));let c=(0,g.useRef)(null),l=(0,g.useRef)(!1);(0,g.useEffect)(()=>{if(e)l.current||(l.current=!0,c.current=document.activeElement);else if(l.current){l.current=!1;let e=c.current;if(c.current=null,e&&typeof e.focus==`function`&&document.contains(e))e.focus();else{let e=document.activeElement;e&&typeof e.blur==`function`&&e.blur(),document.body.focus()}}},[e]),(0,g.useEffect)(()=>{if(!e)return;let t=!1;return s(null),(async()=>{try{let e=await lc();if(t)return;let n=[];for(let[t,r]of Object.entries(e.presets))for(let[e,i]of Object.entries(r))n.push({panel:t,name:e,record:i});n.sort((e,t)=>e.panel===t.panel?e.name.localeCompare(t.name):e.panel.localeCompare(t.panel)),r(n)}catch(e){if(t)return;s((e instanceof X?e.message??`HTTP ${e.status}`:e.message)??`Failed to load presets`)}})(),()=>{t=!0}},[e]);async function u(e){a(!0),s(null);try{await dc(e.panel,e.name),r(t=>t.filter(t=>!(t.panel===e.panel&&t.name===e.name))),R({type:`SHOW_STATUS_TOAST`,text:`Deleted preset "${e.name}"`})}catch(e){s((e instanceof X?e.message??`HTTP ${e.status}`:e.message)??`Delete failed`)}finally{a(!1)}}async function d(e,t){a(!0),s(null);try{await uc({panel:e.panel,name:t,template_id:e.record.template_id,options:e.record.options}),await dc(e.panel,e.name),r(n=>n.map(n=>n.panel===e.panel&&n.name===e.name?{...n,name:t}:n)),R({type:`SHOW_STATUS_TOAST`,text:`Renamed to "${t}"`})}catch(e){s((e instanceof X?e.message??`HTTP ${e.status}`:e.message)??`Rename failed`)}finally{a(!1)}}return e?(0,z.jsxs)(`div`,{className:`share-manage-modal`,role:`dialog`,"aria-modal":`true`,"aria-labelledby":wc,onClick:e=>e.stopPropagation(),children:[(0,z.jsxs)(`div`,{className:`share-manage-header`,children:[(0,z.jsx)(`h2`,{id:wc,children:`Manage presets`}),(0,z.jsx)(`button`,{type:`button`,onClick:t,"aria-label":`Close`,className:`share-manage-close`,children:`⤬`})]}),o?(0,z.jsx)(`div`,{className:`share-manage-error`,role:`alert`,children:o}):null,n.length===0&&!o?(0,z.jsx)(`p`,{className:`share-manage-empty`,children:`No saved presets yet.`}):null,n.length>0?(0,z.jsxs)(`table`,{className:`share-manage-table`,children:[(0,z.jsx)(`thead`,{children:(0,z.jsxs)(`tr`,{children:[(0,z.jsx)(`th`,{children:`Panel`}),(0,z.jsx)(`th`,{children:`Name`}),(0,z.jsx)(`th`,{children:`Saved at`}),(0,z.jsx)(`th`,{})]})}),(0,z.jsx)(`tbody`,{children:n.map(e=>(0,z.jsx)(Ec,{row:e,busy:i,onDelete:()=>void u(e),onRename:t=>void d(e,t)},`${e.panel}/${e.name}`))})]}):null]}):null}function Ec({row:e,busy:t,onDelete:n,onRename:r}){let[i,a]=(0,g.useState)(!1),[o,s]=(0,g.useState)(e.name),c=()=>{let t=o.trim();if(!t||t===e.name){s(e.name),a(!1);return}r(t),a(!1)};return(0,z.jsxs)(`tr`,{children:[(0,z.jsx)(`td`,{children:oc(e.panel)}),(0,z.jsx)(`td`,{children:i?(0,z.jsx)(`input`,{className:`share-manage-name-input`,autoFocus:!0,value:o,disabled:t,maxLength:64,onChange:e=>s(e.target.value),onKeyDown:t=>{t.key===`Enter`?(t.preventDefault(),c()):t.key===`Escape`&&(t.preventDefault(),t.stopPropagation(),s(e.name),a(!1))}}):(0,z.jsx)(`span`,{children:e.name})}),(0,z.jsx)(`td`,{children:e.record.saved_at}),(0,z.jsxs)(`td`,{className:`share-manage-actions`,children:[(0,z.jsx)(`button`,{type:`button`,disabled:t,onClick:()=>{i?(s(e.name),a(!1)):a(!0)},children:i?`Cancel`:`Rename`}),(0,z.jsx)(`button`,{type:`button`,disabled:t,onClick:n,children:`Delete`})]})]})}function Dc(){return{format:`md`,theme:`light`,reveal_projects:!1,no_branding:!1,top_n:5,period:{kind:`current`},project_allowlist:null,show_chart:!0,show_table:!0}}function Oc(e,t){if(!t)return e;let n={...e,...t};return t.period&&(n.period={...e.period,...t.period}),n}function kc({panel:e,onClose:t,initialParams:n}){let r=oc(e),[i,a]=(0,g.useState)(null),[o,s]=(0,g.useState)(null),[c,l]=(0,g.useState)(null),[u,d]=(0,g.useState)(()=>{let e=Dc();return n?.windowWeeks==null?e:{...e,windowWeeks:n.windowWeeks}}),f=(0,g.useRef)(!1),[p,m]=(0,g.useState)(!1),h=`share-modal-title`;V((0,g.useMemo)(()=>[{key:`Escape`,scope:`overlay`,when:()=>!p&&I().composerModal===null,action:t}],[t,p])),(0,g.useEffect)(()=>{let t=!1;return a(null),s(null),Xs(e).then(e=>{if(t)return;a(e.templates);let n=e.templates[0];n&&(l(n.id),f.current||d(e=>Oc(e,n.default_options)))}).catch(e=>{t||s(e instanceof X?`Couldn't load templates: ${e.message??`HTTP ${e.status}`}`:`Couldn't load templates: ${e.message}`)}),()=>{t=!0}},[e]),(0,g.useEffect)(()=>{if(!i||!c||f.current)return;let e=i.find(e=>e.id===c);e&&d(t=>Oc(t,e.default_options))},[c,i]);let _=e=>{f.current=!0,d(e)};return(0,z.jsxs)(`div`,{className:`share-modal`,role:`dialog`,"aria-modal":`true`,"aria-labelledby":h,onClick:e=>e.stopPropagation(),children:[(0,z.jsx)(`header`,{className:`share-modal-header`,children:(0,z.jsxs)(`h2`,{id:h,children:[`Share `,r,` report`]})}),(0,z.jsxs)(`div`,{className:`share-modal-body`,children:[(0,z.jsxs)(`section`,{className:`share-section share-gallery-section`,"aria-label":`Template gallery`,children:[(0,z.jsx)(`div`,{className:`share-gallery-header`,children:(0,z.jsx)(Cc,{panel:e,onPick:(e,t)=>{l(e),f.current=!0,d(e=>({...e,...t}))},onManage:()=>m(!0)})}),(0,z.jsx)(ec,{panel:e,templates:i,error:o,selectedTemplateId:c,onSelect:e=>l(e)})]}),(0,z.jsxs)(`section`,{className:`share-section share-main-section`,children:[(0,z.jsx)(`div`,{className:`share-knobs-col`,"aria-label":`Render options`,children:(0,z.jsx)(tc,{options:u,onChange:_})}),(0,z.jsx)(`div`,{className:`share-preview-col`,"aria-label":`Live preview`,children:(0,z.jsx)(ic,{panel:e,templateId:c,options:u})})]})]}),(0,z.jsx)(`footer`,{className:`share-modal-footer`,children:(0,z.jsx)(xc,{panel:e,templateId:c,options:u,onOptionsChange:_})}),(0,z.jsx)(`button`,{type:`button`,className:`share-modal-close`,"aria-label":`Close share modal`,onClick:t,children:`⤬`}),(0,z.jsx)(Tc,{open:p,onClose:()=>m(!1)})]})}function Ac(e,t){return{title:t.title,theme:t.theme,format:t.format,no_branding:t.no_branding,reveal_projects:t.reveal_projects,sections:e.map(e=>({snapshot:{panel:e.panel,template_id:e.template_id,options:e.options,data_digest_at_add:e.data_digest_at_add,kernel_version:e.kernel_version}}))}}async function jc(e,t){let n=await fetch(`/api/share/compose`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(e),signal:t?.signal});if(!n.ok){let e={};try{e=await n.json()}catch{}throw new X(n.status,e.field,e.error??`HTTP ${n.status}`,e.code)}return n.json()}function Mc({items:e,results:t,kernelVersion:n,onRefresh:r,onRemove:i,onPreviewOnly:a}){let o=jr(Ar(ji,{activationConstraint:{distance:4}}),Ar(Ei,{coordinateGetter:eo}));function s(t){if(!t.over||t.active.id===t.over.id)return;let n=e.findIndex(e=>e.id===t.active.id),r=e.findIndex(e=>e.id===t.over.id);n<0||r<0||R({type:`BASKET_REORDER`,fromIdx:n,toIdx:r})}return(0,z.jsx)(Ta,{sensors:o,collisionDetection:zr,onDragEnd:s,children:(0,z.jsx)(Ha,{items:e.map(e=>e.id),strategy:za,children:(0,z.jsx)(`ul`,{className:`composer-section-list`,children:e.map((e,o)=>(0,z.jsx)(Nc,{item:e,result:t[o],kernelVersion:n,onRefresh:r,onRemove:i,onPreviewOnly:a},e.id))})})})}function Nc({item:e,result:t,kernelVersion:n,onRefresh:r,onRemove:i,onPreviewOnly:a}){let{attributes:o,listeners:s,setNodeRef:c,transform:l,transition:u,isDragging:d}=Xa({id:e.id}),f=so(),p={transform:gr.Transform.toString(l),transition:f?void 0:u,opacity:d?.4:1},[m,h]=(0,g.useState)(!1),_=t?.drift_detected,v=e.kernel_version!==n,y=!!(_||v);return(0,z.jsxs)(`li`,{ref:c,style:p,className:`composer-section-row`,children:[(0,z.jsx)(`button`,{className:`composer-drag-handle`,"aria-label":`Reorder ${e.label_hint}`,type:`button`,...o,...s,children:`≡`}),(0,z.jsx)(`span`,{className:`composer-section-label`,children:e.label_hint}),y?(0,z.jsx)(`span`,{className:`composer-outdated-badge`,title:_&&v?`Data and kernel both shifted since add-time. Refresh to update.`:_?`Data has changed since this section was added. Refresh to update.`:`Kernel updated since this section was added. Refresh to re-render at the new version.`,children:`Outdated`}):null,(0,z.jsxs)(`div`,{className:`composer-section-actions`,children:[(0,z.jsx)(`button`,{type:`button`,"aria-haspopup":`menu`,"aria-expanded":m,onClick:()=>h(e=>!e),"aria-label":`Actions for ${e.label_hint}`,children:`⋯`}),m?(0,z.jsxs)(`ul`,{role:`menu`,className:`composer-section-menu`,children:[(0,z.jsx)(`li`,{children:(0,z.jsx)(`button`,{type:`button`,onClick:()=>{a(e.id),h(!1)},children:`Preview only this`})}),(0,z.jsx)(`li`,{children:(0,z.jsx)(`button`,{type:`button`,onClick:()=>{r(e.id),h(!1)},children:`Refresh from current data`})}),(0,z.jsx)(`li`,{children:(0,z.jsx)(`button`,{type:`button`,onClick:()=>{i(e.id),h(!1)},"aria-label":`Remove ${e.label_hint}`,children:`Remove`})})]}):null]})]})}function Pc(e,t){return t&&e>0}function Fc(e){return`cctally-report-${new Date().toISOString().slice(0,10).replaceAll(`-`,``)}.${e===`md`?`md`:e}`}function Ic(e){switch(e){case`md`:return`text/markdown;charset=utf-8`;case`html`:return`text/html;charset=utf-8`;case`svg`:return`image/svg+xml;charset=utf-8`}}function Lc(e){return e===`light`?`#ffffff`:`#0f172a`}function Rc(e,t){let n=URL.createObjectURL(t),r=document.createElement(`a`);r.href=n,r.download=e,r.style.display=`none`,document.body.appendChild(r),r.click(),document.body.removeChild(r),setTimeout(()=>URL.revokeObjectURL(n),0)}var zc=200;function Bc(){return I().composerModal}function Vc(){return I().basket}var Q=`composer-modal-title`;function Hc(){let e=(0,g.useSyncExternalStore)(L,Bc),t=(0,g.useSyncExternalStore)(L,Vc),n=on(),r=(0,g.useRef)(null),i=(0,g.useRef)(!1),[a,o]=(0,g.useState)(``),[s,c]=(0,g.useState)(`light`),[l,u]=(0,g.useState)(`html`),[d,f]=(0,g.useState)(!0),[p,m]=(0,g.useState)(!1),[h,_]=(0,g.useState)(null),[v,y]=(0,g.useState)(null),[b,x]=(0,g.useState)(!1),S=(0,g.useRef)(null),[C,w]=(0,g.useState)(null),[T,ee]=(0,g.useState)(null);(0,g.useEffect)(()=>{ee(null)},[l,s,d,p]),V((0,g.useMemo)(()=>[{key:`Escape`,scope:`overlay`,when:()=>I().composerModal!==null,action:()=>R(ve())}],[])),(0,g.useEffect)(()=>{e?.open&&a===``&&o(`cctally report — ${new Date().toISOString().slice(0,10)}`)},[e?.open,a]),(0,g.useEffect)(()=>{if(e?.open)i.current||(i.current=!0,r.current=document.activeElement);else if(i.current){i.current=!1;let e=r.current;if(r.current=null,e&&typeof e.focus==`function`&&document.contains(e))e.focus();else{let e=document.activeElement;e&&typeof e.blur==`function`&&e.blur(),document.body.focus()}}},[e?.open]),(0,g.useEffect)(()=>{if(!e?.open||t.items.length===0||a===``)return;let n=setTimeout(()=>{S.current?.abort();let e=new AbortController;S.current=e,x(!0),y(null),jc(Ac(t.items,{title:a,theme:s,format:l,no_branding:p,reveal_projects:!d}),{signal:e.signal}).then(t=>{e.signal.aborted||_(t)}).catch(t=>{t?.name!==`AbortError`&&(e.signal.aborted||y(t instanceof X?t.message??`HTTP ${t.status}`:t.message))}).finally(()=>{e.signal.aborted||x(!1)})},zc);return()=>clearTimeout(n)},[e?.open,t.items,a,s,l,d,p]);async function te(e){let n=t.items.findIndex(t=>t.id===e);if(n<0)return;let r=t.items[n];try{let t=await Zs({panel:r.panel,template_id:r.template_id,options:{...r.options,reveal_projects:!d}}),i=xe({panel:r.panel,template_id:r.template_id,options:r.options,added_at:new Date().toISOString(),data_digest_at_add:t.snapshot.data_digest,kernel_version:t.snapshot.kernel_version,label_hint:r.label_hint,id:r.id});R({type:`BASKET_REMOVE`,id:e}),R({type:`BASKET_ADD`,item:i});let a=I().basket.items.length-1;a!==n&&R({type:`BASKET_REORDER`,fromIdx:a,toIdx:n})}catch(e){y(`Refresh failed: ${e instanceof X?e.message??`HTTP ${e.status}`:e.message}`)}}let E=async e=>{let n=await jc(Ac(t.items,{title:a,theme:s,format:e,no_branding:p,reveal_projects:!d}));return{body:n.body,content_type:n.content_type}},D=e=>R({type:`SHOW_STATUS_TOAST`,text:e}),O=async(e,t,n)=>{if(C==null){w(e),ee(null);try{await t()}catch(e){ee(`${n} failed: ${e instanceof X?e.message??`HTTP ${e.status}`:e.message}`)}finally{w(null)}}},ne=()=>O(`copy`,async()=>{let{body:e}=await E(`md`);if(!navigator.clipboard||typeof navigator.clipboard.writeText!=`function`)throw Error(`Clipboard API unavailable in this browser`);await navigator.clipboard.writeText(e),D(`Copied`)},`Copy`),k=()=>O(`download`,async()=>{let{body:e}=await E(l),t=new Blob([e],{type:Ic(l)});Rc(Fc(l),t),D(`Downloaded`)},`Download`),re=()=>O(`open`,async()=>{let{body:e}=await E(l),t=new Blob([e],{type:Ic(l)}),n=URL.createObjectURL(t);window.open(n,`_blank`,`noopener,noreferrer`)},`Open`),A=()=>O(`png`,async()=>{let{body:e}=await E(`svg`),t=await mc(e,2,Lc(s));Rc(Fc(`svg`).replace(/\.svg$/,`.png`),t),D(`PNG downloaded`)},`PNG export`),ie=()=>O(`print`,async()=>{let{body:e}=await E(`html`);hc(e)},`Print`),ae=C==null&&l===`md`&&t.items.length>0,oe=C==null&&t.items.length>0,se=C==null&&(l===`html`||l===`svg`)&&t.items.length>0,j=C==null&&l===`svg`&&t.items.length>0,ce=C==null&&l===`html`&&t.items.length>0,le=!d,ue=Pc(t.items.length,le),de=le?t.items.length:0;return e?.open?t.items.length===0?(0,z.jsxs)(`div`,{className:`composer-modal composer-modal-empty${n?` composer-modal-mobile`:``}`,role:`dialog`,"aria-modal":`true`,"aria-labelledby":Q,children:[(0,z.jsxs)(`header`,{className:`composer-modal-header`,children:[(0,z.jsx)(`h2`,{id:Q,children:`Compose report`}),(0,z.jsx)(`button`,{type:`button`,className:`composer-modal-close`,onClick:()=>R(ve()),"aria-label":`Close`,children:`⤬`})]}),(0,z.jsx)(`p`,{className:`composer-empty-message`,children:`Basket is empty. Open any panel's share menu and pick + Basket to add a section.`})]}):(0,z.jsxs)(`div`,{className:`composer-modal${n?` composer-modal-mobile`:``}`,role:`dialog`,"aria-modal":`true`,"aria-labelledby":Q,children:[(0,z.jsxs)(`header`,{className:`composer-modal-header`,children:[(0,z.jsx)(`h2`,{id:Q,children:`Compose report`}),(0,z.jsx)(`button`,{type:`button`,className:`composer-modal-close`,onClick:()=>R(ve()),"aria-label":`Close`,children:`⤬`})]}),(0,z.jsxs)(`div`,{className:`composer-knobs`,children:[(0,z.jsxs)(`label`,{children:[`Title`,(0,z.jsx)(`input`,{type:`text`,value:a,onChange:e=>o(e.target.value)})]}),(0,z.jsxs)(`label`,{children:[`Theme`,(0,z.jsxs)(`select`,{value:s,onChange:e=>c(e.target.value),children:[(0,z.jsx)(`option`,{value:`light`,children:`light`}),(0,z.jsx)(`option`,{value:`dark`,children:`dark`})]})]}),(0,z.jsxs)(`label`,{children:[`Format`,(0,z.jsxs)(`select`,{value:l,onChange:e=>u(e.target.value),children:[(0,z.jsx)(`option`,{value:`html`,children:`html`}),(0,z.jsx)(`option`,{value:`md`,children:`md`}),(0,z.jsx)(`option`,{value:`svg`,children:`svg`})]})]}),(0,z.jsxs)(`label`,{children:[(0,z.jsx)(`input`,{type:`checkbox`,checked:d,onChange:e=>f(e.target.checked)}),`Anon on export`]}),(0,z.jsxs)(`label`,{children:[(0,z.jsx)(`input`,{type:`checkbox`,checked:p,onChange:e=>m(e.target.checked)}),`No branding`]})]}),ue?(0,z.jsxs)(`div`,{className:`composer-anon-banner`,role:`status`,"aria-live":`polite`,children:[(0,z.jsxs)(`span`,{children:[de,` section`,de===1?``:`s`,` contain real project names. They will appear in the export.`]}),(0,z.jsx)(`button`,{type:`button`,onClick:()=>f(!0),children:`Anonymize all`})]}):null,(0,z.jsxs)(`div`,{className:`composer-body`,children:[(0,z.jsx)(Mc,{items:t.items,results:h?.snapshot.section_results??[],kernelVersion:h?.snapshot.kernel_version??1,onRefresh:e=>{te(e)},onRemove:e=>R({type:`BASKET_REMOVE`,id:e}),onPreviewOnly:e=>{}}),(0,z.jsx)(`iframe`,{className:`composer-preview`,title:`Combined preview`,tabIndex:-1,sandbox:`allow-same-origin`,srcDoc:h?.body??`<p>Composing…</p>`})]}),b?(0,z.jsx)(`div`,{className:`composer-busy`,children:`Composing…`}):null,v?(0,z.jsx)(`div`,{className:`composer-error`,role:`alert`,children:v}):null,T?(0,z.jsx)(`div`,{className:`composer-error`,role:`alert`,children:T}):null,(0,z.jsxs)(`footer`,{className:`composer-actions`,children:[(0,z.jsxs)(`div`,{className:`composer-export-row`,children:[(0,z.jsx)(`button`,{type:`button`,className:`share-action share-action-copy`,onClick:ne,disabled:!ae,title:l===`md`?C===`copy`?`Copying…`:`Copy composed report to clipboard`:`Copy is available for Markdown only`,children:C===`copy`?`Copying…`:`Copy`}),(0,z.jsx)(`button`,{type:`button`,className:`share-action share-action-download`,onClick:k,disabled:!oe,title:C===`download`?`Downloading…`:`Download composed report`,children:C===`download`?`Downloading…`:`Download`}),(0,z.jsx)(`button`,{type:`button`,className:`share-action share-action-open`,onClick:re,disabled:!se,title:l===`html`||l===`svg`?C===`open`?`Opening…`:`Open composed report in new tab`:`Open is available for HTML/SVG`,children:C===`open`?`Opening…`:`Open`}),(0,z.jsx)(`button`,{type:`button`,className:`share-action share-action-png`,onClick:A,disabled:!j,title:l===`svg`?C===`png`?`Rasterizing…`:`Download composed report as PNG`:`PNG export — available for SVG format only`,children:C===`png`?`Rasterizing…`:`PNG`}),(0,z.jsx)(`button`,{type:`button`,className:`share-action share-action-print`,onClick:ie,disabled:!ce,title:l===`html`?C===`print`?`Opening print dialog…`:`Open the browser print dialog (save as PDF)`:`Print → PDF — available for HTML format only`,children:C===`print`?`Printing…`:`Print → PDF`})]}),(0,z.jsx)(`button`,{type:`button`,className:`composer-clear-all`,onClick:()=>R({type:`BASKET_CLEAR`}),children:`Clear all`})]})]}):null}function Uc(){let e=(0,g.useSyncExternalStore)(L,()=>I().shareModal),t=(0,g.useRef)(null),n=(0,g.useRef)(!1);(0,g.useEffect)(()=>{if(e)n.current||(n.current=!0,t.current=(e.triggerId?document.getElementById(e.triggerId):null)??document.activeElement);else if(n.current){n.current=!1;let e=t.current;if(t.current=null,e&&typeof e.focus==`function`&&document.contains(e))e.focus();else{let e=document.activeElement;e&&typeof e.blur==`function`&&e.blur(),document.body.focus()}}},[e]);let r=()=>R(ge());return(0,z.jsxs)(z.Fragment,{children:[e?(0,z.jsx)(`div`,{id:`share-modal-root`,className:`share-overlay`,onClick:e=>{e.stopPropagation(),e.target===e.currentTarget&&r()},children:(0,z.jsx)(kc,{panel:e.panel,initialParams:e.params,onClose:r})}):null,(0,z.jsx)(Hc,{})]})}function Wc(){let e=(0,g.useSyncExternalStore)(L,()=>I().prefs.panelOrder);return(0,z.jsxs)(z.Fragment,{children:[(0,z.jsx)(Ot,{}),(0,z.jsx)(ho,{items:e,children:(0,z.jsx)(`div`,{className:`grid`,children:e.map((e,t)=>(0,z.jsx)(co,{id:e,index:t},e))})}),(0,z.jsx)(Pt,{}),(0,z.jsx)(Mn,{}),(0,z.jsx)(In,{}),(0,z.jsx)(Js,{}),(0,z.jsx)(Uc,{}),(0,z.jsx)(Fo,{}),(0,z.jsx)(_o,{}),(0,z.jsx)(Un,{})]})}function Gc(e){let t=I().prefs.panelOrder,n=e-1;if(n<0||n>=t.length)return;let r=kn[t[n]];r&&r.openAction()}var Kc=`Click a panel first, then press S to share it.`;function qc(){return typeof window>`u`||!window.matchMedia?!1:window.matchMedia(an).matches}function Jc(){if(typeof document>`u`)return null;let e=document.activeElement;if(!e||!(e instanceof Element))return null;let t=e.closest(`[data-panel-kind]`);return t?t.getAttribute(`data-panel-kind`):null}function Yc(){return{key:`S`,scope:`global`,when:()=>{let e=I();return!(qc()||e.shareModal!==null||e.composerModal!==null||e.openModal!==null||e.update.modalOpen||e.inputMode!==null)},action:()=>{let e=Jc();if(e===null){R({type:`SHOW_STATUS_TOAST`,text:Kc});return}if(!j.has(e))return;let t=e;R(N(t,`${t}-panel`))}}}function Xc(){return typeof window>`u`||!window.matchMedia?!1:window.matchMedia(an).matches}function Zc(){return{key:`B`,scope:`global`,when:()=>{let e=I();return!(Xc()||e.shareModal!==null||e.composerModal!==null||e.openModal!==null||e.update.modalOpen||e.inputMode!==null)},action:()=>R(_e())}}function Qc(){return[Zc()]}mt(),nt(),Bt();var $=()=>{let e=I();return!e.update.modalOpen&&!e.doctorModalOpen};zt([{key:`1`,scope:`global`,when:$,action:()=>Gc(1)},{key:`2`,scope:`global`,when:$,action:()=>Gc(2)},{key:`3`,scope:`global`,when:$,action:()=>Gc(3)},{key:`4`,scope:`global`,when:$,action:()=>Gc(4)},{key:`5`,scope:`global`,when:$,action:()=>Gc(5)},{key:`6`,scope:`global`,when:$,action:()=>Gc(6)},{key:`7`,scope:`global`,when:$,action:()=>Gc(7)},{key:`8`,scope:`global`,when:$,action:()=>Gc(8)},{key:`9`,scope:`global`,when:$,action:()=>Gc(9)},{key:`0`,scope:`global`,when:$,action:()=>Gc(10)},{key:`r`,scope:`global`,when:$,action:()=>Et()},{key:`q`,scope:`global`,when:$,action:Nt},{key:`n`,scope:`global`,when:$,action:()=>jt(1)},{key:`N`,scope:`global`,when:$,action:()=>jt(-1)},{key:`d`,scope:`global`,when:()=>{let e=I();return!(e.openModal!==null||e.update.modalOpen||e.inputMode!==null)},action:()=>R({type:`OPEN_DOCTOR_MODAL`})},Yc(),...Qc(),{key:`c`,scope:`sessions`,when:()=>!I().openModal,action:()=>{let e=I().prefs.sessionsCollapsed;R({type:`SAVE_PREFS`,patch:{sessionsCollapsed:!e}})}}]);var $c=document.getElementById(`root`);if(!$c)throw Error(`missing #root`);(0,_.createRoot)($c).render((0,z.jsx)(g.StrictMode,{children:(0,z.jsx)(Wc,{})}));
|
|
18
|
+
`]},t))})]}):(0,z.jsx)(`p`,{className:`update-manual-note`,children:e.errorMessage??`See ~/.local/share/cctally/update.log for the full failure log.`}),(0,z.jsxs)(`p`,{className:`update-stream-cap`,children:[`Full log: `,(0,z.jsx)(`code`,{children:`~/.local/share/cctally/update.log`})]}),(0,z.jsxs)(`div`,{className:`update-actions`,children:[(0,z.jsx)(`button`,{type:`button`,className:`update-btn update-btn-primary`,onClick:o,children:`Retry`}),(0,z.jsx)(`button`,{type:`button`,className:`update-btn`,onClick:s,disabled:!r,children:t===`ok`?`Copied!`:t===`err`?`Copy failed`:`Copy command`}),(0,z.jsx)(`button`,{type:`button`,className:`update-btn`,onClick:()=>ot.close(),children:`Close`})]})]})}var No={idle:`Update available`,running:`Updating cctally`,success:`Update complete`,failed:`Update failed`},Po={idle:`accent-amber`,running:`accent-amber`,success:`accent-green`,failed:`accent-red`};function Fo(){let e=(0,g.useSyncExternalStore)(L,()=>I().update),t=()=>R({type:`CLOSE_UPDATE_MODAL`});if(V((0,g.useMemo)(()=>[{key:`Escape`,scope:`modal`,action:t,when:()=>I().update.modalOpen}],[])),!e.modalOpen||!e.state)return null;let n=e.status,r=Po[n]??`accent-amber`,i=No[n]??`Update`;n===`running`&&e.state.latest_version?i=`Updating cctally → ${e.state.latest_version}`:n===`success`&&e.state.latest_version&&(i=`Update complete → ${e.state.latest_version}`);let a;switch(n){case`running`:a=(0,z.jsx)(Eo,{});break;case`success`:a=(0,z.jsx)(ko,{});break;case`failed`:a=(0,z.jsx)(Mo,{});break;default:a=(0,z.jsx)(So,{});break}return(0,z.jsxs)(`div`,{id:`update-modal-root`,className:`update-modal-root`,children:[(0,z.jsx)(`div`,{className:`modal-backdrop`,onClick:t}),(0,z.jsxs)(`div`,{className:`modal-card update-modal-card ${r}`,role:`dialog`,"aria-modal":`true`,"aria-labelledby":`update-modal-title`,children:[(0,z.jsx)(`div`,{className:`modal-handle`,"aria-hidden":`true`}),(0,z.jsxs)(`header`,{className:`modal-header`,children:[(0,z.jsx)(`h2`,{id:`update-modal-title`,children:i}),(0,z.jsx)(`button`,{className:`modal-close`,"aria-label":`Close`,onClick:t,children:`×`})]}),(0,z.jsx)(`div`,{className:`modal-body`,children:a})]})]})}function Io({title:e,accentClass:t,children:n,headerExtras:r}){let i=()=>R({type:`CLOSE_MODAL`});return V((0,g.useMemo)(()=>[{key:`Escape`,scope:`modal`,action:i}],[])),(0,z.jsxs)(`div`,{id:`modal-root`,children:[(0,z.jsx)(`div`,{className:`modal-backdrop`,onClick:i}),(0,z.jsxs)(`div`,{className:`modal-card ${t}`,role:`dialog`,"aria-modal":`true`,"aria-labelledby":`modal-title`,children:[(0,z.jsx)(`div`,{className:`modal-handle`,"aria-hidden":`true`}),(0,z.jsxs)(`header`,{className:`modal-header`,children:[(0,z.jsx)(`h2`,{id:`modal-title`,children:e}),r,(0,z.jsx)(`button`,{className:`modal-close`,"aria-label":`Close`,onClick:i,children:`×`})]}),(0,z.jsx)(`div`,{id:`modal-body`,className:`modal-body`,children:n})]})]})}function Lo(e){return e==null||!isFinite(e)?0:Math.max(0,Math.min(100,e))}function Ro(e,t,n){let r=D.dateShort(t,n);return e&&r?`${e} → ${r}`:e||(r?`→ ${r}`:`—`)}function zo(e){if(e==null||!isFinite(e))return[`—`,``];let t=(+e).toFixed(1),n=t.indexOf(`.`);return n===-1?[t,`.0%`]:[t.slice(0,n),t.slice(n)+`%`]}function Bo(e){let t=[],n=[...e].sort((e,t)=>(e.percent??0)-(t.percent??0));for(let e of n)e.percent!=null&&(t.length&&e.percent-(t[t.length-1].percent??0)<3||t.push(e));return t}function Vo(e){if(!Array.isArray(e)||e.length<2)return null;let t=e.map(e=>e.marginal_usd).filter(e=>e!=null&&isFinite(e)),n=t.length?t.reduce((e,t)=>e+t,0)/t.length:null,r=e[e.length-1].percent,i=[];return n!=null&&i.push(`avg marginal $`+n.toFixed(2)),r!=null&&i.push(`latest at `+r+`%`),i.length?i.join(` · `):null}function Ho(e,t){let n=[];for(let t of e)n.push({kind:`milestone`,ts:t.captured_at_utc,data:t});for(let e of t)n.push({kind:`credit`,ts:e.effective_reset_at_utc,data:e});return n.sort((e,t)=>e.ts.localeCompare(t.ts)),n}function Uo(){let e=Ke(),t=Ht(),n={tz:t.resolvedTz,offsetLabel:t.offsetLabel},r=e?.current_week??null,i=e?.header??null,a=Array.isArray(r?.milestones)?r.milestones:[],o=Array.isArray(r?.five_hour_milestones)?r.five_hour_milestones:[],s=Ho(o,Array.isArray(r?.five_hour_block?.credits)?r.five_hour_block.credits:[]),c=Lo(r?.used_pct),[l,u]=zo(r?.used_pct),d=r?Ro(i?.week_label,r.reset_at_utc,n):`—`,f=Bo(a),p=Vo(a);return(0,z.jsx)(Io,{title:`Current Week — per-percent milestones`,accentClass:`accent-green`,headerExtras:(0,z.jsx)(Gt,{panel:`current-week`,panelLabel:`Current week`,triggerId:`current-week-modal`,onClick:()=>R(N(`current-week`,`current-week-modal`))}),children:(0,z.jsxs)(`section`,{className:`modal-current-week`,children:[(0,z.jsx)(`div`,{className:`m-chipstrip`,id:`mcw-badges`,children:(0,z.jsx)(`span`,{className:`m-pill accent-green`,id:`mcw-week-pill`,children:d})}),(0,z.jsxs)(`div`,{className:`mcw-herobar`,children:[(0,z.jsxs)(`div`,{className:`mcw-bignum`,id:`mcw-bignum`,children:[(0,z.jsx)(`span`,{className:`int`,children:l}),(0,z.jsx)(`span`,{className:`unit`,children:u})]}),(0,z.jsxs)(`div`,{className:`mcw-pbar-wrap`,children:[(0,z.jsxs)(`div`,{className:`mcw-pbar`,children:[(0,z.jsx)(`div`,{className:`fill`,id:`mcw-fill`,style:{width:c+`%`}}),(0,z.jsx)(`div`,{className:`ticks`,id:`mcw-ticks`,children:f.map(e=>(0,z.jsx)(`div`,{className:`tick`,"data-p":String(e.percent),style:{left:Lo(e.percent)+`%`}},e.percent))}),(0,z.jsx)(`div`,{className:`marker`,id:`mcw-marker`,style:{left:c+`%`}})]}),(0,z.jsxs)(`div`,{className:`mcw-pscale`,children:[(0,z.jsx)(`span`,{children:`0%`}),(0,z.jsx)(`span`,{children:`25%`}),(0,z.jsx)(`span`,{children:`50%`}),(0,z.jsx)(`span`,{children:`75%`}),(0,z.jsx)(`span`,{children:`100%`})]})]}),(0,z.jsxs)(`div`,{className:`mcw-mini`,id:`mcw-mini`,children:[(0,z.jsxs)(`div`,{className:`s`,children:[(0,z.jsx)(`span`,{className:`k`,children:`spent`}),(0,z.jsx)(`span`,{className:`v v-magenta`,id:`mcw-spent`,children:D.usd2(r?.spent_usd)})]}),(0,z.jsxs)(`div`,{className:`s`,children:[(0,z.jsx)(`span`,{className:`k`,children:`$ / 1%`}),(0,z.jsx)(`span`,{className:`v v-cyan`,id:`mcw-dpp`,children:D.usd3(r?.dollar_per_pct)})]}),(0,z.jsxs)(`div`,{className:`s`,children:[(0,z.jsx)(`span`,{className:`k`,children:`reset`}),(0,z.jsx)(`span`,{className:`v`,id:`mcw-reset`,children:D.datetimeShortZ(r?.reset_at_utc,n)})]})]})]}),(0,z.jsxs)(`h3`,{className:`m-sec sec-ms`,children:[(0,z.jsx)(`svg`,{className:`icon`,"aria-hidden":`true`,children:(0,z.jsx)(`use`,{href:`/static/icons.svg#hash`})}),`Milestones`]}),(0,z.jsxs)(`div`,{className:`mcw-mshead`,children:[(0,z.jsxs)(`span`,{className:`m-pill accent-purple`,id:`mcw-ms-count`,children:[a.length,` crossed`]}),(0,z.jsx)(`span`,{className:`mcw-ms-sub`,id:`mcw-ms-sub`,hidden:!p,children:p??``})]}),a.length===0?(0,z.jsx)(`p`,{className:`empty-state`,id:`mcw-empty`,children:`No milestones yet — earliest crosses at 1\xA0%.`}):(0,z.jsxs)(`table`,{className:`m-histable`,id:`mcw-table`,children:[(0,z.jsx)(`thead`,{children:(0,z.jsxs)(`tr`,{children:[(0,z.jsx)(`th`,{children:`%`}),(0,z.jsxs)(`th`,{children:[`Crossed (`,t.offsetLabel,`)`]}),(0,z.jsx)(`th`,{className:`num`,children:`Cumulative $`}),(0,z.jsx)(`th`,{className:`num`,children:`Marginal $`}),(0,z.jsx)(`th`,{className:`num`,children:`5h %`})]})}),(0,z.jsx)(`tbody`,{id:`mcw-rows`,children:a.map(e=>(0,z.jsxs)(`tr`,{children:[(0,z.jsx)(`td`,{children:(0,z.jsx)(`span`,{className:`m-pill accent-purple pct-cell`,children:e.percent??`—`})}),(0,z.jsx)(`td`,{className:`d`,children:D.startedShort(e.crossed_at_utc,n,{noSuffix:!0})}),(0,z.jsx)(`td`,{className:`num`,children:e.cumulative_usd==null?`—`:`$`+e.cumulative_usd.toFixed(2)}),(0,z.jsx)(`td`,{className:`num`,children:(0,z.jsx)(`span`,{className:`m-marginal`,children:e.marginal_usd==null?`—`:`$`+e.marginal_usd.toFixed(2)})}),(0,z.jsx)(`td`,{className:`num`,children:(0,z.jsx)(`span`,{className:`m-fh`,children:e.five_hour_pct_at_cross==null?`—`:Math.round(e.five_hour_pct_at_cross)+`%`})})]},e.percent))})]}),s.length>0&&(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`h3`,{className:`m-sec sec-ms sec-5h`,children:[(0,z.jsx)(`svg`,{className:`icon`,"aria-hidden":`true`,children:(0,z.jsx)(`use`,{href:`/static/icons.svg#activity`})}),`5h milestones`]}),(0,z.jsx)(`div`,{className:`mcw-mshead`,children:(0,z.jsxs)(`span`,{className:`m-pill accent-purple`,id:`mcw-5h-count`,children:[o.length,` crossed`]})}),(0,z.jsxs)(`table`,{className:`m-histable mcw-5h-table`,id:`mcw-5h-table`,children:[(0,z.jsx)(`thead`,{children:(0,z.jsxs)(`tr`,{children:[(0,z.jsx)(`th`,{children:`%`}),(0,z.jsxs)(`th`,{children:[`When (`,t.offsetLabel,`)`]}),(0,z.jsx)(`th`,{className:`num`,children:`Block $`}),(0,z.jsx)(`th`,{className:`num`,children:`Marginal $`}),(0,z.jsx)(`th`,{className:`num`,children:`7d %`})]})}),(0,z.jsx)(`tbody`,{children:s.map((e,t)=>{if(e.kind===`credit`)return(0,z.jsx)(`tr`,{className:`mcw-5h-credit-row`,children:(0,z.jsxs)(`td`,{colSpan:5,className:`mcw-5h-credit-cell`,children:[`⚡ CREDIT\xA0`,` `,e.data.delta_pp>0?`+`:``,e.data.delta_pp.toFixed(0),`pp\xA0@`,` `,D.startedShort(e.ts,n,{noSuffix:!0})]})},`credit-${t}-${e.ts}`);let r=e.data;return(0,z.jsxs)(`tr`,{children:[(0,z.jsx)(`td`,{children:(0,z.jsx)(`span`,{className:`m-pill accent-purple pct-cell`,children:r.percent_threshold})}),(0,z.jsx)(`td`,{className:`d`,children:D.startedShort(r.captured_at_utc,n,{noSuffix:!0})}),(0,z.jsx)(`td`,{className:`num`,children:`$`+r.block_cost_usd.toFixed(2)}),(0,z.jsx)(`td`,{className:`num`,children:(0,z.jsx)(`span`,{className:`m-marginal`,children:r.marginal_cost_usd==null?`—`:`$`+r.marginal_cost_usd.toFixed(2)})}),(0,z.jsx)(`td`,{className:`num`,children:(0,z.jsx)(`span`,{className:`m-fh`,children:r.seven_day_pct_at_crossing==null?`—`:Math.round(r.seven_day_pct_at_crossing)+`%`})})]},`fhms-${r.percent_threshold}-${r.reset_event_id}`)})})]})]})]})})}function Wo(e){if(!e)return`—`;let t=e.elapsed_hours,n=e.remaining_hours;if(t==null||n==null)return`—`;let r=t+n;if(r<=0)return`—`;let i=t/r*100;return Math.min(100,i).toFixed(1)+`%`}function Go(e){return e==null||!isFinite(e)?null:e<0?0:e>110?110:e}function Ko(e){return e==null||!isFinite(e)?`—`:e<0?`~`+(+e).toFixed(1)+`%`:(+e).toFixed(1)+`%`}function qo(e,t){for(let t of e)t.trueXPct=t.pos/110*100;if(e.length<2||t<=0){for(let t of e)t.resolvedXPct=t.trueXPct;return}let n=e.slice().sort((e,t)=>e.trueXPct-t.trueXPct),r=n[0],i=n[1],a=r.pillWidthPx/2/t*100,o=i.pillWidthPx/2/t*100,s=8/t*100,c=a+o+s,l=2*c;if(i.trueXPct-r.trueXPct<c){let e=(r.trueXPct+i.trueXPct)/2;r.resolvedXPct=e-l/2,i.resolvedXPct=e+l/2;let t=a,n=100-o;r.resolvedXPct<t&&(r.resolvedXPct=t,i.resolvedXPct-r.resolvedXPct<l&&(i.resolvedXPct=Math.min(n,r.resolvedXPct+l))),i.resolvedXPct>n&&(i.resolvedXPct=n,i.resolvedXPct-r.resolvedXPct<l&&(r.resolvedXPct=Math.max(t,i.resolvedXPct-l)))}else r.resolvedXPct=r.trueXPct,i.resolvedXPct=i.trueXPct}function Jo(e,t,n){(0,g.useEffect)(()=>{let r=e.current,i=t.current;if(!r||!i||!n)return;let a=r.querySelector(`.mfc-pills`),o=r.querySelector(`.mfc-leaders`),s=i.querySelector(`.mfc-rangeband`);if(!a||!o)return;let c=n.week_avg_projection_pct,l=n.recent_24h_projection_pct,u=Go(c),d=Go(l),f=[];u!=null&&c!=null&&f.push({kind:`wa`,pos:u,raw:c}),d!=null&&l!=null&&f.push({kind:`r24`,pos:d,raw:l});let p=new Set(f.map(e=>e.kind));i.querySelectorAll(`.mfc-chev`).forEach(e=>{let t=e.dataset.kind;(!t||!p.has(t))&&e.remove()}),a.querySelectorAll(`.mfc-pill`).forEach(e=>{let t=e.dataset.kind;(!t||!p.has(t))&&e.remove()});let m=f.map(e=>({...e,trueXPct:0,resolvedXPct:0,pillWidthPx:0}));for(let e of m){let t=e.pos/110*100,n=i.querySelector(`.mfc-chev[data-kind="${e.kind}"]`);n||(n=document.createElement(`div`),n.className=`mfc-chev `+e.kind,n.dataset.kind=e.kind,i.appendChild(n)),n.style.left=t+`%`;let r=a.querySelector(`.mfc-pill[data-kind="${e.kind}"]`),o=Ko(e.raw);r?r.textContent!==o&&(r.textContent=o):(r=document.createElement(`div`),r.className=`mfc-pill `+e.kind,r.dataset.kind=e.kind,r.textContent=o,a.appendChild(r)),e.pillEl=r}if(s){let e=!1;if(m.length===2){let t=m[0].pos/110*100,n=m[1].pos/110*100,r=Math.min(t,n),i=Math.max(t,n)-r;i>=.5&&(s.style.left=r+`%`,s.style.width=i+`%`,e=!0)}s.hidden=!e}let h=()=>{for(let e of m)if(!e.pillEl||!e.pillEl.isConnected)return;let e=r.clientWidth;if(e<=0){requestAnimationFrame(h);return}for(let e of m)e.pillWidthPx=e.pillEl.getBoundingClientRect().width;qo(m,e);for(let e of m)e.pillEl.style.left=e.resolvedXPct+`%`;for(;o.firstChild;)o.removeChild(o.firstChild);for(let e of m){let t=document.createElementNS(`http://www.w3.org/2000/svg`,`path`);t.setAttribute(`class`,e.kind),t.setAttribute(`vector-effect`,`non-scaling-stroke`),t.setAttribute(`d`,`M ${e.resolvedXPct} 0 C ${e.resolvedXPct} 10, ${e.trueXPct} 8, ${e.trueXPct} 18`),o.appendChild(t)}};h()},[e,t,n])}function Yo(){let e=Ke()?.forecast??null,t=e?.explain??null,n=(0,g.useRef)(null),r=(0,g.useRef)(null);Jo(n,r,e);let i=(0,z.jsx)(Gt,{panel:`forecast`,panelLabel:`Forecast`,triggerId:`forecast-modal`,onClick:()=>R(N(`forecast`,`forecast-modal`))});if(!e)return(0,z.jsx)(Io,{title:`Forecast — explain`,accentClass:`accent-purple`,headerExtras:i,children:(0,z.jsx)(`section`,{className:`modal-forecast`,children:(0,z.jsx)(`p`,{className:`empty-state`,id:`mfc-empty`,children:`No forecast data yet.`})})});let a=St(e.verdict),o=a?`m-pill ${a.accent}`:`m-pill`,s=a?`${a.glyph} ${a.label}`:`—`,c=`m-pill`,l=`—`,u=!0;e.confidence===`high`?(c=`m-pill accent-blue`,l=`high confidence`,u=!1):e.confidence===`low`&&(c=`m-pill accent-red`,l=`low confidence`,u=!1);let d=t?.rates,f=t?.week;return(0,z.jsx)(Io,{title:`Forecast — explain`,accentClass:`accent-purple`,headerExtras:i,children:(0,z.jsxs)(`section`,{className:`modal-forecast`,children:[(0,z.jsxs)(`div`,{className:`m-chipstrip`,id:`mfc-chips`,children:[(0,z.jsx)(`span`,{className:o,id:`mfc-verdict`,children:s}),(0,z.jsx)(`span`,{className:c,id:`mfc-confidence`,hidden:u,children:l})]}),(0,z.jsxs)(`div`,{className:`m-hero cols-2`,children:[(0,z.jsxs)(`div`,{className:`m-kv kv-wa`,children:[(0,z.jsx)(`svg`,{className:`icon`,"aria-hidden":`true`,children:(0,z.jsx)(`use`,{href:`/static/icons.svg#gauge`})}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`div`,{className:`v`,id:`mfc-wa-pct`,children:D.pct1(e.week_avg_projection_pct)}),(0,z.jsx)(`div`,{className:`lbl`,children:`Week-avg projection`}),(0,z.jsx)(`div`,{className:`sub`,id:`mfc-wa-sub`,children:D.ratePctPerHour(d?.week_average_pct_per_hour)})]})]}),(0,z.jsxs)(`div`,{className:`m-kv kv-r24`,children:[(0,z.jsx)(`svg`,{className:`icon`,"aria-hidden":`true`,children:(0,z.jsx)(`use`,{href:`/static/icons.svg#zap`})}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`div`,{className:`v`,id:`mfc-r24-pct`,children:D.pct1(e.recent_24h_projection_pct)}),(0,z.jsx)(`div`,{className:`lbl`,children:`Recent-24h projection`}),(0,z.jsx)(`div`,{className:`sub`,id:`mfc-r24-sub`,children:D.ratePctPerHour(d?.recent_24h_pct_per_hour)})]})]})]}),(0,z.jsxs)(`h3`,{className:`m-sec sec-range`,children:[(0,z.jsx)(`svg`,{className:`icon`,"aria-hidden":`true`,children:(0,z.jsx)(`use`,{href:`/static/icons.svg#bar-chart`})}),`Range vs. caps`]}),(0,z.jsxs)(`div`,{className:`mfc-rangewrap`,id:`mfc-rangewrap`,ref:n,children:[(0,z.jsx)(`div`,{className:`mfc-pills`,id:`mfc-pills`}),(0,z.jsx)(`svg`,{className:`mfc-leaders`,id:`mfc-leaders`,viewBox:`0 0 100 18`,preserveAspectRatio:`none`,"aria-hidden":`true`}),(0,z.jsxs)(`div`,{className:`mfc-rangetrack`,id:`mfc-rangetrack`,ref:r,children:[(0,z.jsx)(`div`,{className:`mfc-zone safe`}),(0,z.jsx)(`div`,{className:`mfc-zone warn`}),(0,z.jsx)(`div`,{className:`mfc-zone over`}),(0,z.jsx)(`div`,{className:`mfc-rangeband`,id:`mfc-rangeband`,hidden:!0}),(0,z.jsx)(`div`,{className:`mfc-bound b90`,children:(0,z.jsx)(`div`,{className:`lbl`,children:`90%`})}),(0,z.jsx)(`div`,{className:`mfc-bound b100`,children:(0,z.jsx)(`div`,{className:`lbl`,children:`100%`})})]})]}),(0,z.jsxs)(`h3`,{className:`m-sec sec-rates`,children:[(0,z.jsx)(`svg`,{className:`icon`,"aria-hidden":`true`,children:(0,z.jsx)(`use`,{href:`/static/icons.svg#activity`})}),`Rates`]}),(0,z.jsxs)(`div`,{className:`mfc-kvgrid`,children:[(0,z.jsxs)(`div`,{className:`mfc-krow`,children:[(0,z.jsx)(`span`,{className:`l`,children:`$ / 1%`}),(0,z.jsx)(`span`,{className:`v v-cyan`,id:`mfc-dpp`,children:D.usd3(d?.dollars_per_percent)})]}),(0,z.jsxs)(`div`,{className:`mfc-krow`,children:[(0,z.jsx)(`span`,{className:`l`,children:`week done`}),(0,z.jsx)(`span`,{className:`v v-green`,id:`mfc-wkdone`,children:Wo(f)})]}),(0,z.jsxs)(`div`,{className:`mfc-krow`,children:[(0,z.jsx)(`span`,{className:`l`,children:`elapsed`}),(0,z.jsx)(`span`,{className:`v v-green`,id:`mfc-elapsed`,children:D.hours1(f?.elapsed_hours)})]}),(0,z.jsxs)(`div`,{className:`mfc-krow`,children:[(0,z.jsx)(`span`,{className:`l`,children:`remaining`}),(0,z.jsx)(`span`,{className:`v`,id:`mfc-remain`,children:D.hours1(f?.remaining_hours)})]})]}),(0,z.jsxs)(`h3`,{className:`m-sec sec-bud`,children:[(0,z.jsx)(`svg`,{className:`icon`,"aria-hidden":`true`,children:(0,z.jsx)(`use`,{href:`/static/icons.svg#dollar`})}),`Daily budgets to stay under`]}),(0,z.jsxs)(`div`,{className:`mfc-kvgrid mfc-kvgrid-single`,children:[(0,z.jsxs)(`div`,{className:`mfc-krow`,children:[(0,z.jsx)(`span`,{className:`l`,children:`@ 100% cap`}),(0,z.jsx)(`span`,{className:`v v-magenta`,id:`mfc-bud100`,children:D.usd2PerDay(e.budget_100_per_day_usd)})]}),(0,z.jsxs)(`div`,{className:`mfc-krow`,children:[(0,z.jsx)(`span`,{className:`l`,children:`@ 90% cap`}),(0,z.jsx)(`span`,{className:`v v-amber`,id:`mfc-bud90`,children:D.usd2PerDay(e.budget_90_per_day_usd)})]})]})]})})}function Xo(e){let t=Math.max(1,Math.round(e/4));return`${e} week${e===1?``:`s`} · ${t} month${t===1?``:`s`}`}function Zo(e){let t=e.findIndex(e=>e&&e.is_current);return t>=0?t:e.length-1}function Qo(e,t){let n=e.filter((e,n)=>n!==t).map(e=>e.dollar_per_pct).filter(e=>e!=null&&isFinite(e));if(n.length<4)return null;let r=n.slice(-4).sort((e,t)=>e-t);return(r[1]+r[2])/2}function $o(e){if(!e.length)return null;let t=[...e].sort((e,t)=>e-t),n=Math.floor(t.length/2);return t.length%2?t[n]:(t[n-1]+t[n])/2}function es(e,t){let n=[];if(!e.length)return n;let r={left:44,right:14,top:12,bottom:22},i=600-r.left-r.right,a=140-r.top-r.bottom,o=e.length,s=e=>r.left+(o===1?i:e/(o-1)*i),c=e.map(e=>e.dollar_per_pct).filter(e=>e!=null&&isFinite(e)),l=c.length?Math.min(...c)*.96:0,u=c.length?Math.max(...c)*1.04:1;u-l<1e-6&&(l-=.01,u+=.01);let d=e=>r.top+a*(1-(e-l)/(u-l)),f=e.map(e=>e.used_pct).filter(e=>e!=null&&isFinite(e)),p=f.length?Math.min(...f)*.96:0,m=f.length?Math.max(...f)*1.04:100;m-p<1e-6&&(--p,m+=1);let h=e=>r.top+a*(1-(e-p)/(m-p));if(n.push({el:`line`,attrs:{class:`mtr-axis`,x1:r.left,y1:r.top+a,x2:600-r.right,y2:r.top+a},key:`axis`}),c.length){let e=$o(c);e!=null&&(n.push({el:`line`,attrs:{class:`mtr-hl`,x1:r.left,y1:d(e),x2:600-r.right,y2:d(e)},key:`med-line`}),n.push({el:`text`,attrs:{class:`mtr-medlabel`,x:r.left+2,y:d(e)-3},text:`median $`+e.toFixed(2),key:`med-label`}))}{let t=[];e.forEach((e,n)=>{e.used_pct!=null&&isFinite(e.used_pct)&&t.push(`${s(n)},${h(e.used_pct)}`)}),t.length>=2&&n.push({el:`polyline`,attrs:{class:`mtr-trendline-dim`,points:t.join(` `)},key:`poly-used`})}{let t=[];e.forEach((e,n)=>{e.dollar_per_pct!=null&&isFinite(e.dollar_per_pct)&&t.push(`${s(n)},${d(e.dollar_per_pct)}`)}),t.length>=2&&n.push({el:`polyline`,attrs:{class:`mtr-trendline`,points:t.join(` `)},key:`poly-dpp`})}e.forEach((e,r)=>{if(e.dollar_per_pct==null||!isFinite(e.dollar_per_pct))return;let i=r===t;n.push({el:`circle`,attrs:{class:`mtr-trenddot`+(i?` cur`:``),cx:s(r),cy:d(e.dollar_per_pct),r:i?5:3},key:`dot-${r}`})}),c.length&&(n.push({el:`text`,attrs:{class:`mtr-ylabel`,x:3,y:r.top+8},text:`$`+(u/1.04).toFixed(2),key:`ymax`}),n.push({el:`text`,attrs:{class:`mtr-ylabel`,x:3,y:r.top+a},text:`$`+(l/.96).toFixed(2),key:`ymin`}));let g=e[t];return g&&g.dollar_per_pct!=null&&isFinite(g.dollar_per_pct)&&n.push({el:`text`,attrs:{class:`mtr-curlabel`,x:Math.max(r.left+4,s(t)-22),y:Math.min(138,d(g.dollar_per_pct)+16)},text:`$`+g.dollar_per_pct.toFixed(2),key:`curlabel`}),n}function ts(e,t){return t===0?`Now`+(e.label?` · `+e.label:``):`W−`+t+(e.label?` · `+e.label:``)}function ns(e){return e==null||!isFinite(e)?{cls:`flat`,text:`—`}:e>5e-4?{cls:`up`,text:`+`+e.toFixed(2)}:e<-5e-4?{cls:`down`,text:e.toFixed(2)}:{cls:`flat`,text:`0.00`}}function rs(e){return e==null||!isFinite(e)?{cls:`delta-flat`,iconHref:`/static/icons.svg#minus`,text:`—`}:e<-5e-4?{cls:`delta-down`,iconHref:`/static/icons.svg#trending-down`,text:`−$`+Math.abs(e).toFixed(3)}:e>5e-4?{cls:`delta-up`,iconHref:`/static/icons.svg#trending-up`,text:`+$`+e.toFixed(3)}:{cls:`delta-flat`,iconHref:`/static/icons.svg#minus`,text:`$0.000`}}function is(){let e=Ke(),t=oe(e),n=(0,z.jsx)(Gt,{panel:`trend`,panelLabel:`Trend`,triggerId:`trend-modal`,onClick:()=>R(N(`trend`,`trend-modal`))});if(!t.length)return(0,z.jsx)(Io,{title:`Trend — 12-week history`,accentClass:`accent-amber`,headerExtras:n,children:(0,z.jsx)(`section`,{className:`modal-trend`,children:(0,z.jsx)(`p`,{className:`empty-state`,id:`mtr-empty`,children:`No history data yet.`})})});let r=Zo(t),i=t[r],a=e?.trend?.history_median_dpp,o=a!=null&&isFinite(a)?a:Qo(t,r),s=rs(i&&i.dollar_per_pct!=null&&o!=null?i.dollar_per_pct-o:null),c=es(t,r),l=t.some(e=>e.used_pct!=null&&isFinite(e.used_pct)),u=t.length;return(0,z.jsx)(Io,{title:`Trend — 12-week history`,accentClass:`accent-amber`,headerExtras:n,children:(0,z.jsxs)(`section`,{className:`modal-trend`,children:[(0,z.jsx)(`div`,{className:`m-chipstrip`,children:(0,z.jsx)(`span`,{className:`m-pill accent-amber`,id:`mtr-weeks-pill`,children:Xo(u)})}),(0,z.jsxs)(`div`,{className:`m-hero cols-3`,children:[(0,z.jsxs)(`div`,{className:`m-kv kv-cur`,children:[(0,z.jsx)(`svg`,{className:`icon`,"aria-hidden":`true`,children:(0,z.jsx)(`use`,{href:`/static/icons.svg#dollar`})}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`div`,{className:`v`,id:`mtr-cur`,children:i&&i.dollar_per_pct!=null?`$`+i.dollar_per_pct.toFixed(3):`—`}),(0,z.jsx)(`div`,{className:`lbl`,children:`Current $ / 1%`})]})]}),(0,z.jsxs)(`div`,{className:`m-kv kv-med`,children:[(0,z.jsx)(`svg`,{className:`icon`,"aria-hidden":`true`,children:(0,z.jsx)(`use`,{href:`/static/icons.svg#minus`})}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`div`,{className:`v`,id:`mtr-med`,children:o==null?`—`:`$`+o.toFixed(3)}),(0,z.jsx)(`div`,{className:`lbl`,children:`4-week median`})]})]}),(0,z.jsxs)(`div`,{className:`m-kv kv-delta ${s.cls}`,id:`mtr-delta-kv`,children:[(0,z.jsx)(`svg`,{className:`icon`,"aria-hidden":`true`,children:(0,z.jsx)(`use`,{href:s.iconHref})}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`div`,{className:`v`,id:`mtr-delta`,children:s.text}),(0,z.jsx)(`div`,{className:`lbl`,children:`vs median`})]})]})]}),(0,z.jsxs)(`h3`,{className:`m-sec sec-spark`,children:[(0,z.jsx)(`svg`,{className:`icon`,"aria-hidden":`true`,children:(0,z.jsx)(`use`,{href:`/static/icons.svg#trending-down`})}),`12-week history · $/1%`,(0,z.jsxs)(`span`,{className:`mtr-legend`+(l?``:` legend-no-used`),"aria-hidden":`true`,children:[(0,z.jsx)(`span`,{className:`sw sw-dpp`}),(0,z.jsx)(`span`,{className:`sw-lbl`,children:`$/1%`}),(0,z.jsx)(`span`,{className:`sw sw-used`}),(0,z.jsx)(`span`,{className:`sw-lbl`,children:`used %`})]})]}),(0,z.jsxs)(`div`,{className:`mtr-sparkhero`,children:[(0,z.jsx)(`svg`,{id:`mtr-svg`,viewBox:`0 0 600 140`,preserveAspectRatio:`none`,"aria-hidden":`true`,children:c.map(e=>{let{el:t,attrs:n,text:r,key:i}=e,a={};for(let e in n)a[e===`class`?`className`:e]=n[e];return t===`line`?(0,z.jsx)(`line`,{...a},i):t===`polyline`?(0,z.jsx)(`polyline`,{...a},i):t===`circle`?(0,z.jsx)(`circle`,{...a},i):(0,z.jsx)(`text`,{...a,children:r},i)})}),(0,z.jsx)(`div`,{className:`mtr-sparkaxis`,id:`mtr-sparkaxis`,children:u>0?(0,z.jsxs)(g.Fragment,{children:[(0,z.jsxs)(`span`,{children:[`W−`,u-1]}),(0,z.jsxs)(`span`,{children:[`W−`,Math.floor((u-1)/2)]}),(0,z.jsx)(`span`,{children:`Now`})]}):null})]}),(0,z.jsxs)(`h3`,{className:`m-sec sec-tbl`,children:[(0,z.jsx)(`svg`,{className:`icon`,"aria-hidden":`true`,children:(0,z.jsx)(`use`,{href:`/static/icons.svg#hash`})}),`Weekly detail`]}),(0,z.jsxs)(`div`,{className:`mtr-tbl-head`,children:[(0,z.jsxs)(`span`,{className:`m-pill accent-purple`,id:`mtr-tbl-count`,children:[u,` weeks`]}),(0,z.jsx)(`span`,{className:`mtr-tbl-sub`,children:`current row highlighted · negative Δ = $/1% down vs prior week`})]}),(0,z.jsxs)(`table`,{className:`m-histable`,id:`mtr-table`,children:[(0,z.jsx)(`thead`,{children:(0,z.jsxs)(`tr`,{children:[(0,z.jsx)(`th`,{children:`Week`}),(0,z.jsx)(`th`,{className:`num`,children:`Used %`}),(0,z.jsx)(`th`,{className:`num`,children:`$ / 1%`}),(0,z.jsx)(`th`,{className:`num`,children:`Δ $/1%`})]})}),(0,z.jsx)(`tbody`,{id:`mtr-rows`,children:t.map((e,t)=>{let n=ts(e,u-1-t),r=e.used_pct==null?`—`:Math.round(e.used_pct)+`%`,i=e.dollar_per_pct==null?`—`:`$`+e.dollar_per_pct.toFixed(2),a=ns(e.delta);return(0,z.jsxs)(`tr`,{className:e.is_current?`cur`:void 0,children:[(0,z.jsx)(`td`,{children:(0,z.jsx)(`span`,{className:`wlab`,children:n})}),(0,z.jsx)(`td`,{className:`num usedpct`,children:r}),(0,z.jsx)(`td`,{className:`num dpp`,children:i}),(0,z.jsx)(`td`,{className:`num delta ${a.cls}`,children:a.text})]},e.label+`|`+t)})})]})]})})}var as=/(^|\/)(subagents\/|agent-)/;function os(){return(0,g.useSyncExternalStore)(L,()=>I().snapshot?.generated_at??``)}function ss(){let e=(0,g.useSyncExternalStore)(L,()=>I().openSessionId),t=os(),[n,r]=(0,g.useState)(null),[i,a]=(0,g.useState)(!0),[o,s]=(0,g.useState)(null),c=(0,g.useRef)(null),l=(0,g.useRef)(!1),u=(0,g.useRef)(null);return(0,g.useEffect)(()=>{u.current=e??I().snapshot?.sessions?.rows?.[0]?.session_id??null,l.current=!1},[e]),(0,g.useEffect)(()=>{let e=u.current;if(!e){a(!1),s(`No session available.`),r(null),c.current=null;return}let t=c.current!==e||n==null;c.current=e,t&&(a(!0),s(null),r(null));let i=new AbortController;return fetch(`/api/session/${encodeURIComponent(e)}`,{signal:i.signal}).then(async e=>{if(e.status===404){(t||l.current)&&(a(!1),s(`Session not found (the cache may have rolled forward).`),r(null)),l.current=!0;return}if(!e.ok)throw Error(`HTTP `+e.status);let n=await e.json();l.current=!1,r(n),s(null),a(!1)}).catch(e=>{e.name!==`AbortError`&&(l.current=!1,t&&(s(`Failed to load: `+e.message),a(!1)))}),()=>i.abort()},[e,t]),(0,z.jsx)(Io,{title:`Session detail`,accentClass:`accent-orange`,headerExtras:(0,z.jsx)(Gt,{panel:`sessions`,panelLabel:`Session`,triggerId:`session-modal`,onClick:()=>R(N(`sessions`,`session-modal`))}),children:(0,z.jsxs)(`section`,{className:`modal-sessions`,children:[i?(0,z.jsx)(`div`,{className:`modal-loading`,id:`msess-loading`,children:`Loading session detail…`}):null,o?(0,z.jsx)(`div`,{className:`modal-error`,id:`msess-error`,children:o}):null,!i&&!o&&n?(0,z.jsx)(cs,{detail:n}):null]})})}function cs({detail:e}){let t=Array.isArray(e.source_paths)?e.source_paths:[],n=[],r=[];t.forEach(e=>{as.test(e)?r.push(e):n.push(e)});let i=e.cost_total_usd??0,a=[[`Input`,e.input_tokens,null],[`Output`,e.output_tokens,null],[`Cache creation`,e.cache_creation_tokens,null],[`Cache read`,e.cache_read_tokens,null],[`Cache hit %`,e.cache_hit_pct,`cache-hit`]].filter(e=>e[1]!=null),o=!e.models||e.models.length===0,s=!e.cost_per_model||e.cost_per_model.length===0;return(0,z.jsxs)(`div`,{className:`modal-content`,id:`msess-content`,children:[(0,z.jsx)(`div`,{className:`m-chipstrip`,children:(0,z.jsx)(`span`,{className:`msess-badge`,id:`msess-id`,"aria-label":`Session ID`,children:e.session_id??`—`})}),(0,z.jsxs)(`div`,{className:`m-hero cols-3`,children:[(0,z.jsxs)(`div`,{className:`m-kv kv-cost`,children:[(0,z.jsx)(`svg`,{className:`icon`,"aria-hidden":`true`,children:(0,z.jsx)(`use`,{href:`/static/icons.svg#dollar`})}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`div`,{className:`v`,id:`msess-cost`,children:e.cost_total_usd==null?`—`:`$`+e.cost_total_usd.toFixed(2)}),(0,z.jsx)(`div`,{className:`lbl`,children:`Total cost`})]})]}),(0,z.jsxs)(`div`,{className:`m-kv kv-dur`,children:[(0,z.jsx)(`svg`,{className:`icon`,"aria-hidden":`true`,children:(0,z.jsx)(`use`,{href:`/static/icons.svg#clock`})}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`div`,{className:`v`,id:`msess-dur`,children:e.duration_min==null?`—`:e.duration_min+` min`}),(0,z.jsx)(`div`,{className:`lbl`,children:`Duration`})]})]}),(0,z.jsxs)(`div`,{className:`m-kv kv-proj`,children:[(0,z.jsx)(`svg`,{className:`icon`,"aria-hidden":`true`,children:(0,z.jsx)(`use`,{href:`/static/icons.svg#folder`})}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`div`,{className:`v`,id:`msess-project`,title:e.project_path??``,"aria-label":`Project`,children:e.project_label??e.project_path??`—`}),(0,z.jsx)(`div`,{className:`lbl`,children:`Project`})]})]})]}),(0,z.jsxs)(`div`,{className:`msess-ts`,children:[(0,z.jsx)(`svg`,{className:`icon`,"aria-hidden":`true`,children:(0,z.jsx)(`use`,{href:`/static/icons.svg#calendar`})}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`span`,{className:`k`,children:`started`}),(0,z.jsx)(`span`,{className:`v`,id:`msess-started`,children:e.started_utc??`—`})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`span`,{className:`k`,children:`last activity`}),(0,z.jsx)(`span`,{className:`v`,id:`msess-last`,children:e.last_activity_utc??`—`})]})]}),(0,z.jsxs)(`h3`,{className:`m-sec sec-tok`,children:[(0,z.jsx)(`svg`,{className:`icon`,"aria-hidden":`true`,children:(0,z.jsx)(`use`,{href:`/static/icons.svg#hash`})}),`Tokens`]}),(0,z.jsx)(`div`,{className:`msess-tok-grid`,id:`msess-tokens`,children:a.map(([e,t,n])=>(0,z.jsxs)(`div`,{className:`msess-tok-tile`+(n?` `+n:``),children:[(0,z.jsx)(`div`,{className:`lbl`,children:e}),(0,z.jsx)(`div`,{className:`n`,children:n===`cache-hit`?t.toFixed(1)+`%`:t.toLocaleString(`en-US`)}),n===`cache-hit`?(0,z.jsx)(`div`,{className:`bar`,children:(0,z.jsx)(`div`,{className:`fill`,style:{width:Math.max(0,Math.min(t,100))+`%`}})}):null]},e))}),o?null:(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`h3`,{className:`m-sec sec-mod`,children:[(0,z.jsx)(`svg`,{className:`icon`,"aria-hidden":`true`,children:(0,z.jsx)(`use`,{href:`/static/icons.svg#sparkles`})}),`Models`]}),(0,z.jsx)(`div`,{className:`m-chipstrip`,id:`msess-models`,children:(e.models||[]).map(e=>(0,z.jsx)(`span`,{className:`chip `+ln(e.name),children:e.name},e.name))})]}),s?null:(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`h3`,{className:`m-sec sec-costm`,children:[(0,z.jsx)(`svg`,{className:`icon`,"aria-hidden":`true`,children:(0,z.jsx)(`use`,{href:`/static/icons.svg#pie-chart`})}),`Cost by model`]}),(0,z.jsxs)(`div`,{className:`msess-costm`,children:[(0,z.jsx)(`div`,{className:`bar`,id:`msess-cost-bar`,children:(e.cost_per_model||[]).map(e=>{let t=i>0&&e.cost_usd!=null?e.cost_usd/i*100:0;return(0,z.jsx)(`div`,{className:`seg `+ln(e.model),style:{width:t+`%`}},e.model)})}),(0,z.jsx)(`div`,{className:`legend`,id:`msess-cost-legend`,children:(e.cost_per_model||[]).map(e=>{let t=i>0&&e.cost_usd!=null?e.cost_usd/i*100:0;return(0,z.jsxs)(`div`,{className:`lg`,children:[(0,z.jsx)(`span`,{className:`sw `+ln(e.model)}),(0,z.jsx)(`span`,{className:`name`,children:e.model}),(0,z.jsx)(`span`,{className:`v`,children:e.cost_usd==null?`—`:`$`+e.cost_usd.toFixed(3)}),(0,z.jsxs)(`span`,{className:`pct`,children:[Math.round(t),`%`]})]},e.model)})})]})]}),t.length>0?(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`h3`,{className:`m-sec sec-src`,children:[(0,z.jsx)(`svg`,{className:`icon`,"aria-hidden":`true`,children:(0,z.jsx)(`use`,{href:`/static/icons.svg#file-text`})}),`Source files`]}),(0,z.jsxs)(`div`,{className:`msess-src`,id:`msess-src`,children:[(0,z.jsxs)(`div`,{className:`src-head`,children:[(0,z.jsxs)(`span`,{className:`count-pill`,children:[t.length,` file`,t.length===1?``:`s`]}),(0,z.jsxs)(`span`,{className:`sub`,children:[n.length,` primary`,r.length>0?(0,z.jsxs)(z.Fragment,{children:[` `,(0,z.jsx)(`span`,{className:`dot`,children:`·`}),` `,(0,z.jsxs)(`span`,{className:`subcount`,children:[r.length,` subagent`,r.length===1?``:`s`]})]}):null]})]}),n.length>0?n.map(e=>(0,z.jsx)(`div`,{className:`primary-path`,children:e},e)):r.length>0?(0,z.jsxs)(`div`,{className:`src-empty-primary`,children:[`No primary path resolved · `,r.length,` subagent path`,r.length===1?``:`s`,` below`]}):null,r.length>0?(0,z.jsxs)(`details`,{className:`subagents`,open:n.length===0,children:[(0,z.jsxs)(`summary`,{children:[`Show `,r.length,` subagent path`,r.length===1?``:`s`]}),(0,z.jsx)(`ul`,{className:`paths`,children:r.map(e=>(0,z.jsx)(`li`,{children:e},e))})]}):null]})]}):null]})}function ls({row:e,variant:t,accentClass:n}){let r=Ht(),i={tz:r.resolvedTz,offsetLabel:r.offsetLabel},a=(e,t)=>`${D.datetimeShort(e,i)} → ${D.datetimeShort(t,i)}`,o=e.delta_cost_pct==null?`flat`:e.delta_cost_pct>0?`up`:e.delta_cost_pct<0?`down`:`flat`,s=t===`weekly`?`week`:t===`monthly`?`month`:`day`,c=t===`daily`?`Today`:`Now`;return(0,z.jsxs)(`div`,{className:`detail-card ${n}`,children:[(0,z.jsxs)(`div`,{className:`head`,children:[(0,z.jsxs)(`div`,{className:`big`,children:[e.label,e.is_current&&(0,z.jsx)(`span`,{className:`pill-current`,children:c})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`span`,{className:`cost`,style:{color:`var(--text)`,fontWeight:700},children:D.usd2(e.cost_usd)}),` `,e.delta_cost_pct==null?(0,z.jsx)(`span`,{className:`delta flat`,children:`—`}):(0,z.jsxs)(`span`,{className:`delta ${o}`,children:[D.deltaPct(e.delta_cost_pct),` vs prior `,s]})]})]}),t===`weekly`&&e.week_start_at&&e.week_end_at&&(0,z.jsxs)(`div`,{className:`window`,children:[`Subscription window: `,a(e.week_start_at,e.week_end_at)]}),(0,z.jsx)(`div`,{className:`model-stack`,role:`presentation`,children:e.models.map(e=>(0,z.jsx)(`span`,{className:e.chip,style:{width:`${e.cost_pct}%`}},e.model))}),(0,z.jsx)(`div`,{className:`chips`,children:e.models.map(e=>(0,z.jsxs)(`span`,{className:`chip ${e.chip}`,children:[e.display,` `,Math.round(e.cost_pct),`% · `,D.usd2(e.cost_usd)]},e.model))}),(0,z.jsxs)(`div`,{className:`tokens-row`,children:[(0,z.jsxs)(`div`,{className:`t`,children:[(0,z.jsx)(`span`,{className:`k`,children:`Input`}),(0,z.jsx)(`span`,{className:`v`,children:D.compact(e.input_tokens)})]}),(0,z.jsxs)(`div`,{className:`t`,children:[(0,z.jsx)(`span`,{className:`k`,children:`Output`}),(0,z.jsx)(`span`,{className:`v`,children:D.compact(e.output_tokens)})]}),(0,z.jsxs)(`div`,{className:`t`,children:[(0,z.jsx)(`span`,{className:`k`,children:`Cache+`}),(0,z.jsx)(`span`,{className:`v`,children:D.compact(e.cache_creation_tokens)})]}),(0,z.jsxs)(`div`,{className:`t`,children:[(0,z.jsx)(`span`,{className:`k`,children:`Cache-read`}),(0,z.jsx)(`span`,{className:`v`,children:D.compact(e.cache_read_tokens)})]}),(0,z.jsxs)(`div`,{className:`t`,children:[(0,z.jsx)(`span`,{className:`k`,children:`Total`}),(0,z.jsx)(`span`,{className:`v`,children:D.compact(e.total_tokens)})]}),e.cache_hit_pct!=null&&(0,z.jsxs)(`div`,{className:`t cache`,children:[(0,z.jsx)(`span`,{className:`k`,children:`Cache hit`}),(0,z.jsxs)(`span`,{className:`v`,children:[e.cache_hit_pct.toFixed(1),`%`]}),(0,z.jsx)(`div`,{className:`bar`,children:(0,z.jsx)(`div`,{className:`fill`,style:{width:`${Math.min(100,Math.max(0,e.cache_hit_pct))}%`}})})]})]}),t===`weekly`&&(0,z.jsxs)(`div`,{className:`stats2`,children:[(0,z.jsxs)(`div`,{className:`s`,children:[(0,z.jsx)(`span`,{className:`k`,children:`Used %`}),(0,z.jsx)(`span`,{className:`v`,children:D.pct0(e.used_pct)})]}),(0,z.jsxs)(`div`,{className:`s`,children:[(0,z.jsx)(`span`,{className:`k`,children:`$/1%`}),(0,z.jsx)(`span`,{className:`v`,children:D.usd2(e.dollar_per_pct)})]})]})]})}function us(e){return e==null||e===0?`num`:e>0?`num delta-up`:`num delta-down`}function ds(e){let t=new Set,n=[];for(let r of e.models)t.has(r.chip)||(t.add(r.chip),n.push(r.chip));return n}function fs({row:e}){let t=ds(e),n=t.slice(0,3),r=t.length>3?t.length-3:0;return(0,z.jsxs)(`span`,{className:`models-chips`,children:[n.map(e=>(0,z.jsx)(`span`,{className:`chip ${e}`,children:e},e)),r>0&&(0,z.jsxs)(`span`,{className:`models-chips-more`,children:[`…+`,r]})]})}function ps({rows:e,variant:t,accentClass:n,selectedIndex:r,onSelect:i}){return(0,z.jsxs)(`table`,{className:`history-table history-table--${t} ${n}`,role:`grid`,"aria-rowcount":e.length,children:[(0,z.jsx)(`thead`,{children:(0,z.jsxs)(`tr`,{children:[(0,z.jsx)(`th`,{children:t===`weekly`?`Week`:`Month`}),(0,z.jsx)(`th`,{children:`Models`}),(0,z.jsx)(`th`,{className:`num`,children:`Cost (USD)`}),t===`weekly`&&(0,z.jsx)(`th`,{className:`num`,children:`Used %`}),t===`weekly`&&(0,z.jsx)(`th`,{className:`num`,children:`$/1%`}),(0,z.jsx)(`th`,{className:`num`,children:`Δ`})]})}),(0,z.jsx)(`tbody`,{children:e.map((e,n)=>(0,z.jsxs)(`tr`,{className:n===r?`selected`:void 0,"aria-rowindex":n+1,"aria-selected":n===r,onClick:()=>i(n),children:[(0,z.jsxs)(`td`,{children:[e.label,n===r?` ▶`:``]}),(0,z.jsx)(`td`,{children:(0,z.jsx)(fs,{row:e})}),(0,z.jsx)(`td`,{className:`num`,children:D.usd2(e.cost_usd)}),t===`weekly`&&(0,z.jsx)(`td`,{className:`num`,children:D.pct0(e.used_pct)}),t===`weekly`&&(0,z.jsx)(`td`,{className:`num`,children:D.usd2(e.dollar_per_pct)}),(0,z.jsx)(`td`,{className:us(e.delta_cost_pct),children:D.deltaPct(e.delta_cost_pct)})]},e.label))})]})}function ms(){let e=Ke()?.weekly?.rows??[],[t,n]=(0,g.useState)(0),r=e.length;(0,g.useEffect)(()=>zt([{key:`ArrowDown`,scope:`modal`,when:()=>I().openModal===`weekly`,action:()=>n(e=>Math.min(e+1,Math.max(0,r-1)))},{key:`ArrowUp`,scope:`modal`,when:()=>I().openModal===`weekly`,action:()=>n(e=>Math.max(e-1,0))}]),[r]);let i=(0,z.jsx)(Gt,{panel:`weekly`,panelLabel:`Weekly`,triggerId:`weekly-modal`,onClick:()=>R(N(`weekly`,`weekly-modal`))});if(r===0)return(0,z.jsx)(Io,{title:`Weekly history · last 12`,accentClass:`accent-cyan`,headerExtras:i,children:(0,z.jsx)(`div`,{className:`panel-empty`,children:`No usage history yet.`})});let a=e[Math.min(t,r-1)];return(0,z.jsxs)(Io,{title:`Weekly history · last 12`,accentClass:`accent-cyan`,headerExtras:i,children:[(0,z.jsx)(ls,{row:a,variant:`weekly`,accentClass:`accent-cyan`}),(0,z.jsx)(ps,{rows:e,variant:`weekly`,accentClass:`accent-cyan`,selectedIndex:t,onSelect:n})]})}function hs(){let e=Ke()?.monthly?.rows??[],[t,n]=(0,g.useState)(0),r=e.length;(0,g.useEffect)(()=>zt([{key:`ArrowDown`,scope:`modal`,when:()=>I().openModal===`monthly`,action:()=>n(e=>Math.min(e+1,Math.max(0,r-1)))},{key:`ArrowUp`,scope:`modal`,when:()=>I().openModal===`monthly`,action:()=>n(e=>Math.max(e-1,0))}]),[r]);let i=(0,z.jsx)(Gt,{panel:`monthly`,panelLabel:`Monthly`,triggerId:`monthly-modal`,onClick:()=>R(N(`monthly`,`monthly-modal`))});if(r===0)return(0,z.jsx)(Io,{title:`Monthly history · last 12`,accentClass:`accent-pink`,headerExtras:i,children:(0,z.jsx)(`div`,{className:`panel-empty`,children:`No usage history yet.`})});let a=e[Math.min(t,r-1)];return(0,z.jsxs)(Io,{title:`Monthly history · last 12`,accentClass:`accent-pink`,headerExtras:i,children:[(0,z.jsx)(ls,{row:a,variant:`monthly`,accentClass:`accent-pink`}),(0,z.jsx)(ps,{rows:e,variant:`monthly`,accentClass:`accent-pink`,selectedIndex:t,onSelect:n})]})}var gs=720,_s=180,vs={left:46,right:20,top:18,bottom:20};function ys(e){return e===0?`$0`:e<10?`$`+e.toFixed(2):`$`+Math.round(e).toString()}function bs(){return(0,g.useSyncExternalStore)(L,()=>I().snapshot?.generated_at??``)}function xs({detail:e}){let t=bs(),n=Ht(),r={tz:n.resolvedTz,offsetLabel:n.offsetLabel},i=Date.parse(e.start_at),a=Date.parse(e.end_at)-i||1,o=e=>vs.left+(Date.parse(e)-i)/a*(gs-vs.left-vs.right),s=Math.max(e.cost_usd,e.projection?.total_cost_usd??0),c=e=>{let t=vs.top,n=_s-vs.bottom;return s<=0?n:n-e/s*(n-t)},l=[];for(let e=0;e<=5;e++)l.push(new Date(i+e*36e5).toISOString());let u=e.samples.length>0?e.samples[e.samples.length-1].cum:0,d=e.is_active?t||new Date().toISOString():null,f=[];if(e.samples.length>0){f.push([o(e.start_at),c(0)]);for(let t of e.samples)f.push([o(t.t),c(t.cum)]);d&&f.push([o(d),c(u)])}let p=f.map(([e,t])=>`${e.toFixed(1)},${t.toFixed(1)}`).join(` `),m=f.length>0?`M ${p.replace(/ /g,` L `)} L ${f[f.length-1][0].toFixed(1)},${c(0).toFixed(1)} Z`:``,h=s<=0?[0]:[0,s/2,s];return(0,z.jsx)(`div`,{className:`mblock-timeline`,children:(0,z.jsxs)(`svg`,{viewBox:`0 0 ${gs} ${_s}`,style:{width:`100%`,height:`auto`},role:`img`,"aria-label":`Cumulative cost over the 5-hour block window`,children:[h.map(e=>(0,z.jsx)(`text`,{x:8,y:c(e)+4,fill:`var(--text-dim)`,fontSize:10,children:ys(e)},e)),(0,z.jsx)(`line`,{x1:vs.left,y1:vs.top,x2:vs.left,y2:_s-vs.bottom,stroke:`var(--border-soft)`,strokeWidth:.8}),(0,z.jsx)(`line`,{x1:vs.left,y1:_s-vs.bottom,x2:gs-vs.right,y2:_s-vs.bottom,stroke:`var(--border-soft)`,strokeWidth:.8}),l.slice(1,-1).map(e=>(0,z.jsx)(`line`,{x1:o(e),y1:vs.top,x2:o(e),y2:_s-vs.bottom,stroke:`var(--border-soft)`,strokeDasharray:`2 3`,strokeWidth:.5},e)),l.map(e=>(0,z.jsx)(`text`,{x:o(e)-14,y:_s-5,fill:`var(--text-dim)`,fontSize:9,children:D.timeHHmm(e,r,{noSuffix:!0})},e)),f.length>0?(0,z.jsxs)(z.Fragment,{children:[(0,z.jsx)(`path`,{d:m,fill:`var(--accent-green)`,opacity:.12}),(0,z.jsx)(`polyline`,{points:p,fill:`none`,stroke:`var(--accent-green)`,strokeWidth:2}),(0,z.jsx)(`circle`,{cx:f[f.length-1][0],cy:f[f.length-1][1],r:3,fill:`var(--accent-green)`})]}):(0,z.jsx)(`text`,{x:gs/2,y:_s/2,fill:`var(--text-faint)`,fontSize:11,textAnchor:`middle`,children:`No spend recorded yet in this block.`}),e.is_active&&e.projection&&d&&f.length>0?(0,z.jsxs)(z.Fragment,{children:[(0,z.jsx)(`polyline`,{points:`${o(d).toFixed(1)},${c(u).toFixed(1)} ${o(e.end_at).toFixed(1)},${c(e.projection.total_cost_usd).toFixed(1)}`,fill:`none`,stroke:`var(--accent-amber)`,strokeWidth:1.5,strokeDasharray:`5 4`,opacity:.85}),(0,z.jsx)(`circle`,{cx:o(e.end_at),cy:c(e.projection.total_cost_usd),r:3,fill:`var(--accent-amber)`,opacity:.85}),(0,z.jsxs)(`text`,{x:o(e.end_at)-50,y:c(e.projection.total_cost_usd)-6,fill:`var(--accent-amber)`,fontSize:9,children:[`proj $`,e.projection.total_cost_usd.toFixed(2)]}),(0,z.jsx)(`line`,{x1:o(d),y1:vs.top,x2:o(d),y2:_s-vs.bottom,stroke:`var(--accent-amber)`,strokeWidth:1.2}),(0,z.jsx)(`text`,{x:o(d)+4,y:vs.top+10,fill:`var(--accent-amber)`,fontSize:9,children:`now`})]}):null]})})}function Ss(){return(0,g.useSyncExternalStore)(L,()=>I().snapshot?.generated_at??``)}function Cs(e,t){let n=Date.parse(e.start_at),r=e.is_active?Date.parse(t)||Date.now():e.actual_end_at?Date.parse(e.actual_end_at):Date.parse(e.end_at),i=Math.max(0,Math.floor((r-n)/6e4)),a=Math.floor(i/60),o=i%60;return`${a}h ${String(o).padStart(2,`0`)}m`}function ws(e,t,n){return`${D.timeHHmm(e,n)} → ${D.timeHHmm(t,n)}`}function Ts(){let e=(0,g.useSyncExternalStore)(L,()=>I().openBlockStartAt),t=Ss(),n=Ht(),r={tz:n.resolvedTz,offsetLabel:n.offsetLabel},[i,a]=(0,g.useState)(null),[o,s]=(0,g.useState)(!0),[c,l]=(0,g.useState)(null),u=(0,g.useRef)(null),d=(0,g.useRef)(!1),f=(0,g.useRef)(null);return(0,g.useEffect)(()=>{f.current=e??null,d.current=!1},[e]),(0,g.useEffect)(()=>{let e=f.current;if(!e){s(!1),l(`No block bound.`),a(null),u.current=null;return}let t=u.current!==e||i==null;u.current=e,t&&(s(!0),l(null),a(null));let n=new AbortController;return fetch(`/api/block/${encodeURIComponent(e)}`,{signal:n.signal}).then(async e=>{if(e.status===404){(t||d.current)&&(s(!1),l(`Block not found (the cache may have rolled forward).`),a(null)),d.current=!0;return}if(!e.ok)throw Error(`HTTP `+e.status);let n=await e.json();d.current=!1,a(n),l(null),s(!1)}).catch(e=>{e.name!==`AbortError`&&(d.current=!1,t&&(l(`Failed to load: `+e.message),s(!1)))}),()=>n.abort()},[e,t]),(0,z.jsx)(Io,{title:i?`${i.anchor===`heuristic`?`~ `:``}Block · ${i.label}`:`Block`,accentClass:`accent-blue`,headerExtras:(0,z.jsx)(Gt,{panel:`blocks`,panelLabel:`5-hour block`,triggerId:`block-modal`,onClick:()=>R(N(`blocks`,`block-modal`))}),children:(0,z.jsxs)(`section`,{className:`modal-block`,children:[o?(0,z.jsx)(`div`,{className:`modal-loading`,children:`Loading block detail…`}):null,c?(0,z.jsx)(`div`,{className:`modal-error`,children:c}):null,!o&&!c&&i?(0,z.jsx)(Es,{detail:i,generatedAt:t,ctx:r}):null]})})}function Es({detail:e,generatedAt:t,ctx:n}){let r=e.cost_usd??0;return(0,z.jsxs)(`div`,{className:`modal-content`,children:[(0,z.jsxs)(`div`,{className:`m-chipstrip`,children:[e.is_active?(0,z.jsx)(`span`,{className:`m-pill accent-green`,children:`● Active`}):null,e.anchor===`heuristic`?(0,z.jsx)(`span`,{className:`m-pill accent-amber`,children:`~ heuristic anchor`}):null,(0,z.jsx)(`span`,{className:`m-pill accent-blue`,children:ws(e.start_at,e.end_at,n)}),(0,z.jsxs)(`span`,{className:`m-pill`,children:[e.entries_count.toLocaleString(`en-US`),` `,e.entries_count===1?`entry`:`entries`]})]}),(0,z.jsxs)(`div`,{className:`m-hero `+(e.is_active?`cols-4`:`cols-3`),children:[(0,z.jsxs)(`div`,{className:`m-kv kv-cost`,children:[(0,z.jsx)(`svg`,{className:`icon`,"aria-hidden":`true`,children:(0,z.jsx)(`use`,{href:`/static/icons.svg#dollar`})}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`div`,{className:`v`,children:D.usd2(e.cost_usd)}),(0,z.jsx)(`div`,{className:`lbl`,children:`Total cost`})]})]}),(0,z.jsxs)(`div`,{className:`m-kv kv-dur`,children:[(0,z.jsx)(`svg`,{className:`icon`,"aria-hidden":`true`,children:(0,z.jsx)(`use`,{href:`/static/icons.svg#clock`})}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`div`,{className:`v`,children:Cs(e,t)}),(0,z.jsx)(`div`,{className:`lbl`,children:`Elapsed`})]})]}),(0,z.jsxs)(`div`,{className:`m-kv`,children:[(0,z.jsx)(`svg`,{className:`icon`,"aria-hidden":`true`,children:(0,z.jsx)(`use`,{href:`/static/icons.svg#hash`})}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`div`,{className:`v`,children:e.total_tokens.toLocaleString(`en-US`)}),(0,z.jsx)(`div`,{className:`lbl`,children:`Total tokens`})]})]}),e.is_active?(0,z.jsxs)(`div`,{className:`m-kv kv-proj`,children:[(0,z.jsx)(`svg`,{className:`icon`,"aria-hidden":`true`,children:(0,z.jsx)(`use`,{href:`/static/icons.svg#crystal-ball`})}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`div`,{className:`v`,children:e.projection?D.usd2(e.projection.total_cost_usd):`—`}),(0,z.jsxs)(`div`,{className:`lbl`,children:[`Projected`,e.projection?` · ${e.projection.remaining_minutes}m left`:``]})]})]}):null]}),(0,z.jsx)(xs,{detail:e}),(0,z.jsxs)(`h3`,{className:`m-sec sec-tok`,children:[(0,z.jsx)(`svg`,{className:`icon`,"aria-hidden":`true`,children:(0,z.jsx)(`use`,{href:`/static/icons.svg#hash`})}),`Tokens`]}),(0,z.jsxs)(`div`,{className:`msess-tok-grid mblock-tok-grid`,children:[(0,z.jsxs)(`div`,{className:`msess-tok-tile`,children:[(0,z.jsx)(`div`,{className:`lbl`,children:`Input`}),(0,z.jsx)(`div`,{className:`n`,children:e.input_tokens.toLocaleString(`en-US`)})]}),(0,z.jsxs)(`div`,{className:`msess-tok-tile`,children:[(0,z.jsx)(`div`,{className:`lbl`,children:`Output`}),(0,z.jsx)(`div`,{className:`n`,children:e.output_tokens.toLocaleString(`en-US`)})]}),(0,z.jsxs)(`div`,{className:`msess-tok-tile`,children:[(0,z.jsx)(`div`,{className:`lbl`,children:`Cache create`}),(0,z.jsx)(`div`,{className:`n`,children:e.cache_creation_tokens.toLocaleString(`en-US`)})]}),(0,z.jsxs)(`div`,{className:`msess-tok-tile`,children:[(0,z.jsx)(`div`,{className:`lbl`,children:`Cache read`}),(0,z.jsx)(`div`,{className:`n`,children:e.cache_read_tokens.toLocaleString(`en-US`)})]}),e.cache_hit_pct==null?null:(0,z.jsxs)(`div`,{className:`msess-tok-tile cache-hit`,children:[(0,z.jsx)(`div`,{className:`lbl`,children:`Cache hit %`}),(0,z.jsxs)(`div`,{className:`n`,children:[e.cache_hit_pct.toFixed(1),`%`]}),(0,z.jsx)(`div`,{className:`bar`,children:(0,z.jsx)(`div`,{className:`fill`,style:{width:Math.min(100,Math.max(0,e.cache_hit_pct))+`%`}})})]})]}),e.models.length>0?(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`h3`,{className:`m-sec sec-costm`,children:[(0,z.jsx)(`svg`,{className:`icon`,"aria-hidden":`true`,children:(0,z.jsx)(`use`,{href:`/static/icons.svg#pie-chart`})}),`Cost by model`]}),(0,z.jsxs)(`div`,{className:`msess-costm`,children:[(0,z.jsx)(`div`,{className:`bar`,children:e.models.map(e=>{let t=r>0?e.cost_usd/r*100:0;return(0,z.jsx)(`div`,{className:`seg `+ln(e.model),style:{width:t+`%`}},e.model)})}),(0,z.jsx)(`div`,{className:`legend`,children:e.models.map(e=>{let t=r>0?e.cost_usd/r*100:0;return(0,z.jsxs)(`div`,{className:`lg`,children:[(0,z.jsx)(`span`,{className:`sw `+ln(e.model)}),(0,z.jsx)(`span`,{className:`name`,children:e.display}),(0,z.jsxs)(`span`,{className:`v`,children:[`$`,e.cost_usd.toFixed(2)]}),(0,z.jsxs)(`span`,{className:`pct`,children:[Math.round(t),`%`]})]},e.model)})})]})]}):null,e.is_active&&e.burn_rate&&e.projection?(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`h3`,{className:`m-sec sec-burn`,children:[(0,z.jsx)(`svg`,{className:`icon`,"aria-hidden":`true`,children:(0,z.jsx)(`use`,{href:`/static/icons.svg#crystal-ball`})}),`Burn rate & projection`]}),(0,z.jsxs)(`div`,{className:`mblock-burn`,children:[(0,z.jsxs)(`div`,{className:`row`,children:[(0,z.jsx)(`span`,{className:`k`,children:`Burn rate`}),(0,z.jsx)(`span`,{className:`v amber`,children:D.usd2(e.burn_rate.cost_per_hour)}),(0,z.jsx)(`span`,{className:`dim`,children:`/ hr`}),(0,z.jsx)(`span`,{className:`sep`,children:`·`}),(0,z.jsx)(`span`,{className:`v cyan`,children:Math.round(e.burn_rate.tokens_per_minute).toLocaleString(`en-US`)}),(0,z.jsx)(`span`,{className:`dim`,children:`tok / min`})]}),(0,z.jsxs)(`div`,{className:`row`,children:[(0,z.jsx)(`span`,{className:`k`,children:`Projection`}),(0,z.jsx)(`span`,{className:`v amber`,children:D.usd2(e.projection.total_cost_usd)}),(0,z.jsx)(`span`,{className:`dim`,children:`total`}),(0,z.jsx)(`span`,{className:`sep`,children:`·`}),(0,z.jsx)(`span`,{className:`v cyan`,children:e.projection.total_tokens.toLocaleString(`en-US`)}),(0,z.jsx)(`span`,{className:`dim`,children:`tok`}),(0,z.jsx)(`span`,{className:`sep`,children:`·`}),(0,z.jsxs)(`span`,{className:`v`,children:[e.projection.remaining_minutes,` min`]}),(0,z.jsx)(`span`,{className:`dim`,children:`remaining`})]})]})]}):null]})}function Ds({rows:e,selectedDate:t,onSelect:n}){let r=[...e].reverse(),i=r.reduce((e,t)=>Math.max(e,t.cost_usd),0),a=r.length>0?Os(r[0].date):``,o=r.length>0?Os(r[r.length-1].date):``,s=r.find(e=>e.is_today),c=s?`${Os(s.date)} · today`:``;return(0,z.jsxs)(`section`,{className:`daily-modal-bars`,"aria-label":`30-day cost`,children:[(0,z.jsxs)(`div`,{className:`daily-modal-bars-head`,children:[(0,z.jsxs)(`span`,{children:[`30-day cost · selected: `,t?Os(t):`—`]}),(0,z.jsx)(`span`,{className:`hint`,children:`↑↓ navigate · click any bar`})]}),(0,z.jsx)(`div`,{className:`daily-modal-bars-grid`,role:`img`,"aria-label":`30-day cost histogram`,children:r.map(e=>{let r=e.cost_usd<=0,a=e.date===t,o=r?4:i>0?e.cost_usd/i*100:0,s=[`bar`,r?`zero`:``,a?`sel`:``,e.is_today?`today`:``].filter(Boolean).join(` `);return(0,z.jsx)(`button`,{"data-date":e.date,className:s,style:{height:`${o}%`},disabled:r,"aria-pressed":a,"aria-label":`${e.label} cost ${e.cost_usd>0?D.usd2(e.cost_usd):`no usage`}`,title:e.cost_usd>0?`${e.label} · ${D.usd2(e.cost_usd)}`:`${e.label} · —`,onClick:()=>{r||n(e.date)}},e.date)})}),r.length>0&&(0,z.jsxs)(`div`,{className:`daily-modal-bars-axis`,children:[(0,z.jsx)(`span`,{children:a}),c&&(0,z.jsx)(`span`,{children:c}),(0,z.jsx)(`span`,{children:o})]})]})}function Os(e){let t=[`Jan`,`Feb`,`Mar`,`Apr`,`May`,`Jun`,`Jul`,`Aug`,`Sep`,`Oct`,`Nov`,`Dec`],n=e.split(`-`).map(Number);return`${t[n[1]-1]} ${n[2]}`}function ks(){let e=Ke()?.daily?.rows??[],t=(0,g.useSyncExternalStore)(L,()=>I().openDailyDate),[n,r]=(0,g.useState)(null);(0,g.useEffect)(()=>{t&&r(t)},[]);let i=new Set(e.map(e=>e.date)),a=e[0]?.date??null,o=n&&i.has(n)?n:a;(0,g.useEffect)(()=>zt([{key:`ArrowDown`,scope:`modal`,when:()=>I().openModal===`daily`,action:()=>{let t=o;if(!t)return;let n=e.findIndex(e=>e.date===t);n<0||n>=e.length-1||r(e[n+1].date)}},{key:`ArrowUp`,scope:`modal`,when:()=>I().openModal===`daily`,action:()=>{let t=o;if(!t)return;let n=e.findIndex(e=>e.date===t);n<=0||r(e[n-1].date)}}]),[e,o]);let s=(0,z.jsx)(Gt,{panel:`daily`,panelLabel:`Daily`,triggerId:`daily-modal`,onClick:()=>R(N(`daily`,`daily-modal`))});if(e.length===0)return(0,z.jsx)(Io,{title:`Daily history · last 30`,accentClass:`accent-indigo`,headerExtras:s,children:(0,z.jsx)(`div`,{className:`panel-empty`,children:`No usage history yet.`})});let c=e.findIndex(e=>e.date===o),l=c>=0?c:0,u=e[l],d=e[l+1],f=As(u,d);return(0,z.jsxs)(Io,{title:`Daily history · last 30`,accentClass:`accent-indigo`,headerExtras:s,children:[(0,z.jsx)(Ds,{rows:e,selectedDate:o,onSelect:r}),(0,z.jsx)(ls,{row:f,variant:`daily`,accentClass:`accent-indigo`})]})}function As(e,t){let n=t&&t.cost_usd>0?(e.cost_usd-t.cost_usd)/t.cost_usd:null;return{label:e.label,cost_usd:e.cost_usd,total_tokens:e.total_tokens,input_tokens:e.input_tokens,output_tokens:e.output_tokens,cache_creation_tokens:e.cache_creation_tokens,cache_read_tokens:e.cache_read_tokens,used_pct:null,dollar_per_pct:null,delta_cost_pct:n,is_current:e.is_today,models:e.models,cache_hit_pct:e.cache_hit_pct}}var js=[`#d946ef`,`#c084fc`,`#60a5fa`,`#fbbf24`,`#22d3ee`],Ms=`#64748b`,Ns=5,Ps=400,Fs=150;function Is({trend:e,yMode:t,windowWeeks:n,onProjectSelect:r}){let i=(0,g.useMemo)(()=>{let t=Math.max(0,Math.min(n,e.window_weeks)),r=e.weeks.slice(-t),i=e.projects.map(e=>{let n=e.weekly_cost.slice(-t),r=n.reduce((e,t)=>e+t,0);return{key:e.key,weekly:n,cost:r,color:``}}).sort((e,t)=>t.cost-e.cost),a=i.slice(0,Ns).map((e,t)=>({...e,color:js[t]??Ms})),o=i.slice(Ns),s=r.map((e,t)=>o.reduce((e,n)=>e+(n.weekly[t]??0),0)),c=s.reduce((e,t)=>e+t,0),l=[...a];return o.length>0&&c>0&&l.push({key:`(other)`,weekly:s,cost:c,color:Ms}),{weeks:r,series:l}},[e,n]),a=on();if(i.weeks.length===0||i.series.length===0)return(0,z.jsxs)(`div`,{className:`panel-empty`,children:[`No project activity in the last `,n,` week`,n===1?``:`s`,`.`]});let o=i.weeks.length,s=i.weeks.map((e,t)=>i.series.reduce((e,n)=>e+(n.weekly[t]??0),0)),c=t===`share`?100:Math.max(...s,.01),l=(e,t=`left`)=>o<=1?t===`left`?Ps*.1:Ps*.9:e/(o-1)*Ps,u=Array(o).fill(0),d=i.series.map(e=>{let n=[];for(let e=0;e<o;e++){let t=Fs-u[e]/c*Fs;n.push(`${l(e,`left`).toFixed(2)},${t.toFixed(2)}`),o===1&&n.push(`${l(e,`right`).toFixed(2)},${t.toFixed(2)}`)}for(let r=o-1;r>=0;r--){let i=s[r]??0,a=t===`share`?i>0?(e.weekly[r]??0)/i*100:0:e.weekly[r]??0;u[r]+=a;let d=Fs-u[r]/c*Fs;o===1&&n.push(`${l(r,`right`).toFixed(2)},${d.toFixed(2)}`),n.push(`${l(r,`left`).toFixed(2)},${d.toFixed(2)}`)}return{color:e.color,key:e.key,points:n.join(` `)}}),f=i.weeks.map(e=>(0,z.jsx)(`span`,{children:e.week_label},e.week_start_date));return(0,z.jsxs)(`div`,{className:`projects-trend`,children:[(0,z.jsx)(`svg`,{viewBox:`0 0 ${Ps} ${Fs}`,preserveAspectRatio:`none`,role:`img`,"aria-label":`Stacked area: project ${t===`share`?`share %`:`cost`} over ${o} weeks`,children:d.map(e=>{let t=e.key===`(other)`;return(0,z.jsx)(`polygon`,{fill:e.color,opacity:t?.5:.65,points:e.points,"data-series-key":e.key,onClick:()=>{t||r?.(e.key)},style:{cursor:t?`default`:`pointer`}},e.key)})}),(0,z.jsx)(`div`,{className:`projects-trend-xaxis`,children:f}),(0,z.jsx)(`div`,{className:`projects-trend-legend`,children:i.series.map(e=>{let t=e.key===`(other)`,n=(0,z.jsxs)(z.Fragment,{children:[(0,z.jsx)(`span`,{className:`sw`,style:{background:e.color}}),e.key]});return a&&!t?(0,z.jsx)(`button`,{type:`button`,className:`projects-trend-legend-item`,"data-series-key":e.key,onClick:()=>r?.(e.key),children:n},e.key):(0,z.jsx)(`span`,{className:`projects-trend-legend-item`,"data-series-key":e.key,children:n},e.key)})})]})}function Ls(e,t){let[n,r]=(0,g.useState)(null),[i,a]=(0,g.useState)(!1),[o,s]=(0,g.useState)(null),c=Ke()?.generated_at??``,l=(0,g.useRef)(0),u=(0,g.useRef)(null),d=(0,g.useRef)(null),f=(0,g.useRef)(!1);return(0,g.useEffect)(()=>{if(!e){r(null),a(!1),s(null),l.current=0,u.current=null,d.current=null,f.current=!1;return}let i=u.current!==e||d.current!==t,o=i||n==null;if(o&&f.current&&!i)return;o&&(a(!0),s(null)),i&&(l.current=0),u.current=e,d.current=t,f.current=!0;let c=new AbortController,p=`/api/project/${encodeURIComponent(e)}?weeks=${t}`;return fetch(p,{signal:c.signal}).then(async e=>{if(e.status===404){l.current+=1,l.current>=2?(r(null),s(`Project no longer in cache — close this drill.`),a(!1)):o&&(s(`Couldn't load project detail — will retry on next tick.`),a(!1));return}if(!e.ok){o&&(s(`Couldn't load project detail — will retry on next tick.`),a(!1));return}l.current=0,r(await e.json()),s(null),a(!1)}).catch(e=>{e?.name!==`AbortError`&&o&&(s(`Couldn't load project detail — will retry on next tick.`),a(!1))}).finally(()=>{f.current=!1}),()=>c.abort()},[e,t,c]),{data:n,loading:i,error:o}}function Rs({projectKey:e,windowWeeks:t}){let{data:n,loading:r,error:i}=Ls(e,t),a=Ht(),o={tz:a.resolvedTz,offsetLabel:a.offsetLabel},s=n!=null&&(n.key!==e||n.window_weeks!==t);if(r&&!n||s)return(0,z.jsx)(`div`,{className:`panel-empty`,children:`Loading…`});if(i&&!n)return(0,z.jsx)(`div`,{className:`panel-empty`,children:i});if(!n)return null;let c=n.models[0]?.cost_usd??0,l=c>0?c:1,u=Math.max(0,n.sessions_total-n.sessions.length);return(0,z.jsxs)(`div`,{className:`projects-drill`,"data-testid":`projects-drill`,"aria-live":`polite`,children:[(0,z.jsx)(`div`,{className:`projects-drill-head`,children:(0,z.jsxs)(`span`,{className:`title`,children:[`▾ `,n.key,` · `,n.sessions_total,` session`,n.sessions_total===1?``:`s`,` · `,D.usd2(n.window_cost_usd),` (`,t,`w)`]})}),(0,z.jsxs)(`div`,{className:`projects-drill-grid`,children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`div`,{className:`section-label`,children:`Models (this project)`}),n.models.length===0?(0,z.jsx)(`div`,{className:`muted`,children:`No model data for this window.`}):n.models.map(e=>{let t={"--w":`${e.cost_usd/l*100}%`};return(0,z.jsxs)(`div`,{className:`drill-bar-row`,children:[(0,z.jsx)(`span`,{className:`chip ${ln(e.model)}`,children:e.model}),(0,z.jsx)(`div`,{className:`drill-bar`,style:t}),(0,z.jsx)(`span`,{className:`cost ${un(e.cost_usd)}`,children:D.usd2(e.cost_usd)})]},e.model)})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`div`,{className:`section-label`,children:`Recent sessions →`}),n.sessions.length===0?(0,z.jsx)(`div`,{className:`muted`,children:`No sessions for this window.`}):n.sessions.map((e,t)=>(0,z.jsxs)(`button`,{"data-testid":`drill-session-${t}`,className:`drill-session-row`,onClick:()=>R({type:`OPEN_MODAL`,kind:`session`,sessionId:e.session_id}),children:[(0,z.jsx)(`span`,{className:`started`,children:D.datetimeShort(e.last_activity_at,o)}),(0,z.jsx)(`span`,{className:`chip ${ln(e.primary_model)}`,children:e.primary_model}),(0,z.jsx)(`span`,{className:`cost ${un(e.cost_usd)}`,children:D.usd2(e.cost_usd)})]},e.session_id)),(0,z.jsxs)(`div`,{className:`drill-session-footer`,children:[u>0&&(0,z.jsxs)(`span`,{className:`muted`,children:[`+`,u,` more`]}),(0,z.jsx)(`button`,{type:`button`,"data-testid":`drill-show-in-sessions`,className:`drill-show-in-sessions`,onClick:()=>{R({type:`SET_FILTER`,text:n.key}),R({type:`CLOSE_MODAL`})},children:`Show in Sessions →`})]})]})]})]})}var zs=(e,t)=>e<t?-1:+(e>t),Bs=[{id:`project`,label:`Project`,defaultDirection:`asc`,compare:(e,t)=>zs(e.key,t.key),className:`project`},{id:`sessions`,label:`Sessions`,defaultDirection:`desc`,numeric:!0,compare:(e,t)=>e.sessionsCount-t.sessionsCount},{id:`first_seen`,label:`First seen`,defaultDirection:`asc`,nullKey:e=>e.firstSeenAt,compare:(e,t)=>zs(e.firstSeenAt,t.firstSeenAt),className:`started`},{id:`last_seen`,label:`Last seen`,defaultDirection:`desc`,nullKey:e=>e.lastSeenAt,compare:(e,t)=>zs(e.lastSeenAt,t.lastSeenAt),className:`started`},{id:`cost`,label:`Cost`,defaultDirection:`desc`,numeric:!0,compare:(e,t)=>e.windowCost-t.windowCost},{id:`used_pct`,label:`Used %`,defaultDirection:`desc`,numeric:!0,nullKey:e=>e.windowPct,compare:(e,t)=>e.windowPct-t.windowPct},{id:`share_of_window`,label:`% of week`,defaultDirection:`desc`,numeric:!0,nullKey:e=>e.shareOfWindow,compare:(e,t)=>e.shareOfWindow-t.shareOfWindow}],Vs=[{column:`cost`,direction:`desc`,label:`cost`,arrow:`↓`},{column:`sessions`,direction:`desc`,label:`sessions`,arrow:`↓`},{column:`used_pct`,direction:`desc`,label:`used`,arrow:`↓`},{column:`share_of_window`,direction:`desc`,label:`share`,arrow:`↓`},{column:`first_seen`,direction:`asc`,label:`first`,arrow:`↑`},{column:`last_seen`,direction:`desc`,label:`last`,arrow:`↓`},{column:`project`,direction:`asc`,label:`project`,arrow:`↑`}],Hs=[1,4,8,12];function Us(){let e=Ke(),t=Ht(),n={tz:t.resolvedTz,offsetLabel:t.offsetLabel},r=(0,g.useSyncExternalStore)(L,()=>I().openProjectKey),i=(0,g.useSyncExternalStore)(L,()=>I().prefs.projectsWindowWeeks),a=(0,g.useSyncExternalStore)(L,()=>I().prefs.projectsTrendYMode),o=(0,g.useSyncExternalStore)(L,()=>I().prefs.projectsSortOverride),[s,c]=(0,g.useState)(r??null),[l,u]=(0,g.useState)(!1);(0,g.useEffect)(()=>{if(r){c(r);return}s||c(e?.projects?.current_week?.rows?.[0]?.key??null)},[r,e?.projects?.current_week?.rows]),(0,g.useEffect)(()=>{r||s&&((e?.projects?.trend?.projects??[]).some(e=>e.key===s)||c(e?.projects?.current_week?.rows?.[0]?.key??null))},[r,s,e?.projects?.trend?.projects,e?.projects?.current_week?.rows]);let d=e?.projects?.trend??null,f=i,p=d?.window_weeks??0,m=(e,t)=>{R({type:`SAVE_PREFS`,patch:{[e]:t}})},h=e=>{c(t=>t===e?null:e)},_=(d?.projects??[]).map(e=>{let t=e.weekly_cost.slice(-i),n=e.weekly_pct.slice(-i),r=e.sessions_per_week.slice(-i),a=e.first_seen_per_week.slice(-i),o=e.last_seen_per_week.slice(-i),s=t.reduce((e,t)=>e+t,0),c=n.reduce((e,t)=>t==null?e:(e??0)+t,null),l=r.reduce((e,t)=>e+t,0),u=a.reduce((e,t)=>t==null?e:e==null||t<e?t:e,null),d=o.reduce((e,t)=>t==null?e:e==null||t>e?t:e,null);return{key:e.key,sessionsCount:l,firstSeenAt:u,lastSeenAt:d,windowCost:s,windowPct:c,shareOfWindow:null}}),v=_.reduce((e,t)=>e+t.windowCost,0);for(let e of _)e.shareOfWindow=v>0?e.windowCost/v*100:null;let y=o?de(_,Bs,o):de(_,Bs,{column:`cost`,direction:`desc`}),b=y.filter(e=>e.windowCost>0).slice(0,10),x=y.length-b.length,S=l?y:b,C=x>0,w=on(),T=(()=>{if(!o)return 0;let e=Vs.findIndex(e=>e.column===o.column&&e.direction===o.direction);return e===-1?0:e})(),ee=()=>{let e=Vs[(T+1)%Vs.length];R({type:`SET_TABLE_SORT`,table:`projects`,override:{column:e.column,direction:e.direction}})},te=Vs[T],E=()=>I().shareModal===null&&I().composerModal===null;return V([{key:`1`,scope:`modal`,when:E,action:()=>m(`projectsWindowWeeks`,1)},{key:`4`,scope:`modal`,when:E,action:()=>m(`projectsWindowWeeks`,4)},{key:`8`,scope:`modal`,when:E,action:()=>m(`projectsWindowWeeks`,8)},{key:`0`,scope:`modal`,when:E,action:()=>m(`projectsWindowWeeks`,12)},{key:`s`,scope:`modal`,when:E,action:()=>m(`projectsTrendYMode`,a===`share`?`absolute`:`share`)},{key:`ArrowUp`,scope:`modal`,when:E,action:()=>{if(S.length===0)return;let e=S.findIndex(e=>e.key===s);c(S[e<=0?S.length-1:e-1].key)}},{key:`ArrowDown`,scope:`modal`,when:E,action:()=>{if(S.length===0)return;let e=S.findIndex(e=>e.key===s);c(S[e===-1||e===S.length-1?0:e+1].key)}},{key:`Enter`,scope:`modal`,when:E,action:()=>{s?c(null):S.length>0&&c(S[0].key)}}]),(0,z.jsx)(Io,{title:`Projects · last ${i}w`,accentClass:`accent-magenta`,headerExtras:(0,z.jsx)(Gt,{panel:`projects`,panelLabel:`Projects`,triggerId:`projects-modal`,dataTestId:`share-icon-projects-modal`,onClick:()=>R(N(`projects`,`projects-modal`,{windowWeeks:i}))}),children:(0,z.jsxs)(`div`,{className:`projects-modal-body`,children:[(0,z.jsxs)(`div`,{className:`projects-controls`,role:`radiogroup`,"aria-label":`Window`,children:[Hs.map(e=>(0,z.jsxs)(`button`,{type:`button`,role:`radio`,"aria-checked":i===e,className:`pill ${i===e?`on`:``}`,onClick:()=>m(`projectsWindowWeeks`,e),children:[e,`w`]},`window-${e}`)),(0,z.jsx)(`span`,{className:`sep`,"aria-hidden":`true`,children:`|`}),(0,z.jsx)(`button`,{type:`button`,role:`radio`,"aria-checked":a===`share`,className:`pill ${a===`share`?`on`:``}`,onClick:()=>m(`projectsTrendYMode`,`share`),children:`share %`}),(0,z.jsx)(`button`,{type:`button`,role:`radio`,"aria-checked":a===`absolute`,className:`pill ${a===`absolute`?`on`:``}`,onClick:()=>m(`projectsTrendYMode`,`absolute`),children:`$ absolute`})]}),p>0&&p<f&&(0,z.jsxs)(`div`,{className:`projects-notice`,children:[`Showing `,p,` week`,p===1?``:`s`,` (need more history for the full window).`]}),d?(0,z.jsx)(Is,{trend:d,yMode:a,windowWeeks:i,onProjectSelect:e=>c(e)}):(0,z.jsx)(`div`,{className:`panel-empty`,children:`Projects trend unavailable.`}),w&&(0,z.jsxs)(`button`,{type:`button`,className:`projects-mobile-sort`,"data-testid":`projects-mobile-sort`,onClick:ee,"aria-label":`Cycle sort column`,children:[`Sort: `,te.label,` `,te.arrow]}),(0,z.jsxs)(`table`,{className:`projects-table`,children:[(0,z.jsx)(tn,{columns:Bs,override:o,onChange:e=>R({type:`SET_TABLE_SORT`,table:`projects`,override:e}),accentVar:`--accent-magenta`}),(0,z.jsx)(`tbody`,{children:S.map(e=>(0,z.jsxs)(g.Fragment,{children:[(0,z.jsxs)(`tr`,{"data-testid":`projects-table-row`,"data-cost":e.windowCost,"data-sessions":e.sessionsCount,"aria-expanded":s===e.key,className:s===e.key?`selected`:``,onClick:()=>h(e.key),children:[(0,z.jsx)(`td`,{className:`project`,children:e.key}),(0,z.jsx)(`td`,{children:e.sessionsCount}),(0,z.jsx)(`td`,{className:`started first-seen`,children:D.dateShort(e.firstSeenAt,n)??`—`}),(0,z.jsx)(`td`,{className:`started last-seen`,children:D.dateShort(e.lastSeenAt,n)??`—`}),(0,z.jsx)(`td`,{className:un(e.windowCost),children:D.usd2(e.windowCost)}),(0,z.jsx)(`td`,{children:e.windowPct==null?`—`:D.pct0(e.windowPct)}),(0,z.jsx)(`td`,{children:e.shareOfWindow==null?`—`:D.pct0(e.shareOfWindow)})]}),w&&s===e.key&&(0,z.jsx)(`tr`,{className:`projects-drill-row`,"aria-hidden":`false`,children:(0,z.jsx)(`td`,{colSpan:7,children:(0,z.jsx)(Rs,{projectKey:e.key,windowWeeks:i})})})]},e.key))})]}),C&&(0,z.jsx)(`button`,{type:`button`,className:`projects-table-toggle`,"data-testid":`projects-table-toggle`,"aria-expanded":l,onClick:()=>u(e=>!e),children:l?`Show top 10 active`:`Show all ${y.length} projects (+${x})`}),!w&&s&&(0,z.jsx)(Rs,{projectKey:s,windowWeeks:i}),(0,z.jsxs)(`div`,{className:`projects-modal-footer-hint`,"data-testid":`projects-modal-footer-hint`,"aria-live":`off`,children:[(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`kbd`,{children:`1`}),`/`,(0,z.jsx)(`kbd`,{children:`4`}),`/`,(0,z.jsx)(`kbd`,{children:`8`}),`/`,(0,z.jsx)(`kbd`,{children:`0`}),` window`]}),(0,z.jsx)(`span`,{className:`sep`,"aria-hidden":`true`,children:`·`}),(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`kbd`,{children:`↑↓`}),` row`]}),(0,z.jsx)(`span`,{className:`sep`,"aria-hidden":`true`,children:`·`}),(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`kbd`,{children:`Enter`}),` drill`]}),(0,z.jsx)(`span`,{className:`sep`,"aria-hidden":`true`,children:`·`}),(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`kbd`,{children:`s`}),` share/$`]}),(0,z.jsx)(`span`,{className:`sep`,"aria-hidden":`true`,children:`·`}),(0,z.jsxs)(`span`,{children:[(0,z.jsx)(`kbd`,{children:`Esc`}),` close`]}),(0,z.jsx)(`span`,{className:`sep`,"aria-hidden":`true`,children:`·`}),(0,z.jsx)(yt,{})]})]})})}var Ws=100;function Gs({alert:e,ctx:t}){if(e.axis===`weekly`){let n=e.context.week_start_date?D.weekStart(e.context.week_start_date,t):null,r=e.context.dollars_per_percent;return(0,z.jsxs)(`span`,{className:`alert-context alert-context--weekly`,children:[n?`Week of ${n}`:`Week —`,r!=null&&(0,z.jsxs)(z.Fragment,{children:[` · `,(0,z.jsxs)(`span`,{className:`num`,children:[`$`,r.toFixed(2),`/1%`]})]})]})}return(0,z.jsxs)(`span`,{className:`alert-context alert-context--five-hour`,children:[`Block `,e.context.block_start_at?D.timeOnly(e.context.block_start_at,t):`—`]})}function Ks({alert:e}){let t=e.axis===`weekly`?e.context.cumulative_cost_usd:e.context.block_cost_usd;return(0,z.jsx)(`span`,{className:`num`,children:D.usd2(t??null)})}function qs(){let e=(0,g.useSyncExternalStore)(L,()=>I().alerts),t=Ht(),n={tz:t.resolvedTz,offsetLabel:t.offsetLabel},r=e.slice(0,Ws);return r.length===0?(0,z.jsx)(Io,{title:`Recent alerts`,accentClass:`accent-amber`,children:(0,z.jsx)(`div`,{className:`panel-empty`,children:`No alerts yet. Alerts appear when usage crosses 90% or 95%.`})}):(0,z.jsx)(Io,{title:`Recent alerts`,accentClass:`accent-amber`,children:(0,z.jsxs)(`div`,{className:`alerts-modal-body`,children:[(0,z.jsxs)(`table`,{className:`alerts-table`,children:[(0,z.jsx)(`thead`,{children:(0,z.jsxs)(`tr`,{children:[(0,z.jsx)(`th`,{scope:`col`,children:`%`}),(0,z.jsx)(`th`,{scope:`col`,children:`Axis`}),(0,z.jsx)(`th`,{scope:`col`,children:`Cost`}),(0,z.jsx)(`th`,{scope:`col`,children:`Context`}),(0,z.jsx)(`th`,{scope:`col`,children:`Alerted`})]})}),(0,z.jsx)(`tbody`,{children:r.map(e=>{let t=e.threshold>=95?`red`:`amber`;return(0,z.jsxs)(`tr`,{className:`alert-modal-row`,children:[(0,z.jsxs)(`td`,{className:`alert-threshold severity-${t} ${t} num`,children:[e.threshold,`%`]}),(0,z.jsx)(`td`,{children:(0,z.jsx)(`span`,{className:`chip chip--${e.axis}`,children:e.axis===`weekly`?`WEEKLY`:`5H-BLOCK`})}),(0,z.jsx)(`td`,{className:`num`,children:(0,z.jsx)(Ks,{alert:e})}),(0,z.jsx)(`td`,{children:(0,z.jsx)(Gs,{alert:e,ctx:n})}),(0,z.jsx)(`td`,{className:`alert-when`,children:D.relativeOrAbsolute(e.alerted_at,n)})]},e.id)})})]}),e.length>Ws&&(0,z.jsxs)(`div`,{className:`alerts-modal-foot`,children:[`Showing `,Ws,` of `,e.length,` most recent`]})]})})}function Js(){let e=(0,g.useSyncExternalStore)(L,()=>I().openModal);if(!e)return null;switch(e){case`current-week`:return(0,z.jsx)(Uo,{});case`forecast`:return(0,z.jsx)(Yo,{});case`trend`:return(0,z.jsx)(is,{});case`session`:return(0,z.jsx)(ss,{});case`weekly`:return(0,z.jsx)(ms,{});case`monthly`:return(0,z.jsx)(hs,{});case`block`:return(0,z.jsx)(Ts,{});case`daily`:return(0,z.jsx)(ks,{});case`projects`:return(0,z.jsx)(Us,{});case`alerts`:return(0,z.jsx)(qs,{})}}var X=class extends Error{code;constructor(e,t,n,r){super(n),this.status=e,this.field=t,this.code=r}};async function Ys(e){if(!e.ok){let t={};try{t=await e.json()}catch{}throw new X(e.status,t.field,t.error??`HTTP ${e.status}`,t.code)}return e.json()}async function Xs(e,t){return Ys(await fetch(`/api/share/templates?panel=${encodeURIComponent(e)}`,{signal:t?.signal}))}async function Zs(e,t){return Ys(await fetch(`/api/share/render`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(e),signal:t?.signal}))}var Qs=[{id:`recap`,label:`Recap`,placeholderDescription:`Text + tiny chart`},{id:`visual`,label:`Visual`,placeholderDescription:`Coming in M2`},{id:`detail`,label:`Detail`,placeholderDescription:`Coming in M2`}];function $s(e){return e.endsWith(`-recap`)?`recap`:e.endsWith(`-visual`)?`visual`:e.endsWith(`-detail`)?`detail`:null}function ec({panel:e,templates:t,error:n,selectedTemplateId:r,onSelect:i}){if(n)return(0,z.jsx)(`div`,{className:`share-gallery-error`,role:`alert`,children:n});let a={};for(let e of t??[]){let t=$s(e.id);t&&(a[t]=e)}return(0,z.jsx)(`div`,{className:`share-gallery`,role:`radiogroup`,"aria-label":`Report template`,children:Qs.map(e=>{let n=a[e.id];if(t==null)return(0,z.jsxs)(`div`,{className:`share-tile share-tile-skeleton`,"aria-hidden":`true`,children:[(0,z.jsx)(`div`,{className:`share-tile-skeleton-bar`}),(0,z.jsx)(`div`,{className:`share-tile-skeleton-bar short`})]},e.id);if(!n)return(0,z.jsxs)(`button`,{type:`button`,className:`share-tile share-tile-disabled`,disabled:!0,"aria-disabled":`true`,role:`radio`,"aria-checked":`false`,title:`${e.label} — ${e.placeholderDescription}`,children:[(0,z.jsx)(`div`,{className:`share-tile-label`,children:e.label}),(0,z.jsx)(`div`,{className:`share-tile-desc`,children:e.placeholderDescription})]},e.id);let o=n.id===r;return(0,z.jsxs)(`button`,{type:`button`,className:`share-tile`+(o?` share-tile-selected`:``),role:`radio`,"aria-checked":o,"data-template-id":n.id,onClick:()=>i(n.id),children:[(0,z.jsx)(`div`,{className:`share-tile-label`,children:n.label}),(0,z.jsx)(`div`,{className:`share-tile-desc`,children:n.description})]},e.id)})})}function tc({options:e,onChange:t}){let n=n=>t({...e,...n}),r=n=>t({...e,period:{...e.period,...n}}),i=e=>{if(e===``){n({top_n:null});return}let t=Number.parseInt(e,10);Number.isNaN(t)||n({top_n:Math.max(1,t)})};return(0,z.jsxs)(`div`,{className:`share-knobs`,children:[(0,z.jsxs)(`div`,{className:`share-knob`,children:[(0,z.jsx)(`label`,{htmlFor:`share-knob-period`,children:`Period`}),(0,z.jsxs)(`select`,{id:`share-knob-period`,value:e.period.kind,onChange:e=>r({kind:e.target.value}),children:[(0,z.jsx)(`option`,{value:`current`,children:`This week`}),(0,z.jsx)(`option`,{value:`previous`,children:`Previous week`}),(0,z.jsx)(`option`,{value:`custom`,children:`Custom`})]}),e.period.kind===`custom`?(0,z.jsxs)(`div`,{className:`share-knob-period-custom`,children:[(0,z.jsxs)(`label`,{className:`share-knob-sublabel`,children:[(0,z.jsx)(`span`,{children:`Start`}),(0,z.jsx)(`input`,{type:`date`,value:e.period.start?.slice(0,10)??``,onChange:e=>r({start:e.target.value}),"aria-label":`Custom period start date`})]}),(0,z.jsxs)(`label`,{className:`share-knob-sublabel`,children:[(0,z.jsx)(`span`,{children:`End`}),(0,z.jsx)(`input`,{type:`date`,value:e.period.end?.slice(0,10)??``,onChange:e=>r({end:e.target.value}),"aria-label":`Custom period end date`})]})]}):null]}),(0,z.jsxs)(`div`,{className:`share-knob`,children:[(0,z.jsx)(`span`,{className:`share-knob-label`,children:`Theme`}),(0,z.jsxs)(`div`,{className:`share-knob-radiogroup`,role:`radiogroup`,"aria-label":`Theme`,children:[(0,z.jsxs)(`label`,{className:`share-knob-radio`,children:[(0,z.jsx)(`input`,{type:`radio`,name:`share-theme`,value:`light`,checked:e.theme===`light`,onChange:()=>n({theme:`light`})}),(0,z.jsx)(`span`,{children:`Light`})]}),(0,z.jsxs)(`label`,{className:`share-knob-radio`,children:[(0,z.jsx)(`input`,{type:`radio`,name:`share-theme`,value:`dark`,checked:e.theme===`dark`,onChange:()=>n({theme:`dark`})}),(0,z.jsx)(`span`,{children:`Dark`})]})]})]}),(0,z.jsxs)(`div`,{className:`share-knob`,children:[(0,z.jsx)(`label`,{htmlFor:`share-knob-topn`,children:`Top-N`}),(0,z.jsx)(`input`,{id:`share-knob-topn`,type:`number`,min:1,step:1,inputMode:`numeric`,value:e.top_n??``,onChange:e=>i(e.target.value),"aria-label":`Top-N`})]}),(0,z.jsxs)(`div`,{className:`share-knob`,children:[(0,z.jsx)(`span`,{className:`share-knob-label`,children:`Projects`}),(0,z.jsx)(`button`,{type:`button`,className:`share-knob-allowlist-stub`,disabled:!0,"aria-disabled":`true`,title:`Project allowlist — coming in M3+`,children:`All projects`})]}),(0,z.jsx)(`div`,{className:`share-knob`,children:(0,z.jsxs)(`label`,{className:`share-knob-checkbox`,children:[(0,z.jsx)(`input`,{type:`checkbox`,checked:e.show_chart,onChange:e=>n({show_chart:e.target.checked}),"aria-label":`Include chart in export`}),(0,z.jsx)(`span`,{children:`Show chart`})]})}),(0,z.jsx)(`div`,{className:`share-knob`,children:(0,z.jsxs)(`label`,{className:`share-knob-checkbox`,children:[(0,z.jsx)(`input`,{type:`checkbox`,checked:e.show_table,onChange:e=>n({show_table:e.target.checked}),"aria-label":`Include table in export`}),(0,z.jsx)(`span`,{children:`Show table`})]})}),(0,z.jsx)(`div`,{className:`share-knob`,children:(0,z.jsxs)(`label`,{className:`share-knob-checkbox`,children:[(0,z.jsx)(`input`,{type:`checkbox`,checked:!e.reveal_projects,onChange:e=>n({reveal_projects:!e.target.checked}),"aria-label":`Anonymize project names on export`}),(0,z.jsx)(`span`,{children:`Anon on export`})]})})]})}var nc=200,rc={status:`idle`,body:``,contentType:``,errorMessage:null,errorField:null};function ic({panel:e,templateId:t,options:n}){let[r,i]=(0,g.useState)(rc),a=(0,g.useRef)(null),o=(0,g.useRef)(0);return(0,g.useEffect)(()=>{if(!t){i(rc);return}i(e=>({...e,status:`loading`}));let r=++o.current,s=setTimeout(()=>{a.current?.abort();let s=new AbortController;a.current=s,Zs({panel:e,template_id:t,options:{...n,reveal_projects:!0}},{signal:s.signal}).then(e=>{r===o.current&&i({status:`ready`,body:e.body,contentType:e.content_type,errorMessage:null,errorField:null})}).catch(e=>{if(r===o.current&&!(e&&typeof e==`object`&&e.name===`AbortError`)){if(e instanceof X){i({status:`error`,body:``,contentType:``,errorMessage:e.message??`HTTP ${e.status}`,errorField:e.field??null});return}i({status:`error`,body:``,contentType:``,errorMessage:e.message??`Unknown error`,errorField:null})}})},nc);return()=>{clearTimeout(s)}},[e,t,n]),(0,g.useEffect)(()=>()=>{a.current?.abort()},[]),t?r.status===`error`?(0,z.jsxs)(`div`,{className:`share-preview share-preview-error`,role:`alert`,children:[(0,z.jsx)(`div`,{className:`share-preview-error-title`,children:`Preview failed`}),(0,z.jsxs)(`div`,{className:`share-preview-error-message`,children:[r.errorMessage,r.errorField?(0,z.jsxs)(`span`,{className:`share-preview-error-field`,children:[` `,`(field: `,r.errorField,`)`]}):null]})]}):r.status===`loading`||r.status===`idle`?(0,z.jsx)(`div`,{className:`share-preview share-preview-loading`,"aria-busy":`true`,children:`Rendering preview…`}):n.format===`md`?(0,z.jsx)(`pre`,{className:`share-preview share-preview-md`,"aria-label":`Markdown preview`,children:r.body}):(0,z.jsx)(`iframe`,{className:`share-preview share-preview-iframe`,title:`Report preview (decorative)`,tabIndex:-1,sandbox:`allow-same-origin`,srcDoc:r.body}):(0,z.jsx)(`div`,{className:`share-preview share-preview-empty`,children:`Select a template to preview.`})}var ac={"current-week":`Current week`,trend:`Trend`,weekly:`Weekly`,daily:`Daily`,monthly:`Monthly`,blocks:`5-hour blocks`,forecast:`Forecast`,sessions:`Sessions`,projects:`Projects`};function oc(e){return ac[e]}function sc(e){switch(e){case`md`:return`md`;case`html`:return`html`;case`svg`:return`svg`}}async function cc(e){if(!e.ok){let t={};try{t=await e.json()}catch{}throw new X(e.status,t.field,t.error??`HTTP ${e.status}`)}return e.json()}async function lc(e){return cc(await fetch(`/api/share/presets`,{signal:e?.signal}))}async function uc(e,t){return cc(await fetch(`/api/share/presets`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(e),signal:t?.signal}))}async function dc(e,t,n){let r=await fetch(`/api/share/presets/${encodeURIComponent(e)}/${encodeURIComponent(t)}`,{method:`DELETE`,signal:n?.signal});if(!r.ok){let e={};try{e=await r.json()}catch{}throw new X(r.status,void 0,e.error??`HTTP ${r.status}`)}}async function fc(e){return cc(await fetch(`/api/share/history`,{signal:e?.signal}))}async function Z(e,t){return cc(await fetch(`/api/share/history`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(e),signal:t?.signal}))}function pc({panel:e,templateId:t,options:n,onSaved:r,onCancel:i}){let[a,o]=(0,g.useState)(``),[s,c]=(0,g.useState)(!1),[l,u]=(0,g.useState)(null);async function d(){let i=a.trim();if(!i){u(`Name is required`);return}if(i.length>64){u(`Name must be 64 characters or fewer`);return}if(i.includes(`/`)){u(`Name cannot contain '/'`);return}c(!0),u(null);try{await uc({panel:e,name:i,template_id:t,options:n}),R({type:`SHOW_STATUS_TOAST`,text:`Saved preset "${i}"`}),r()}catch(e){u((e instanceof X?e.message??`HTTP ${e.status}`:e.message)??`Save failed`)}finally{c(!1)}}return(0,z.jsxs)(`div`,{className:`share-save-popover`,role:`dialog`,"aria-label":`Save preset`,children:[(0,z.jsxs)(`label`,{className:`share-save-label`,children:[`Preset name`,(0,z.jsx)(`input`,{type:`text`,className:`share-save-input`,autoFocus:!0,value:a,maxLength:64,disabled:s,onChange:e=>o(e.target.value),onKeyDown:e=>{e.key===`Enter`?(e.preventDefault(),e.stopPropagation(),d()):e.key===`Escape`&&(e.preventDefault(),e.stopPropagation(),i())}})]}),l?(0,z.jsx)(`div`,{className:`share-save-error`,role:`alert`,children:l}):null,(0,z.jsxs)(`div`,{className:`share-save-actions`,children:[(0,z.jsx)(`button`,{type:`button`,onClick:i,disabled:s,children:`Cancel`}),(0,z.jsx)(`button`,{type:`button`,onClick:()=>void d(),disabled:s,children:s?`Saving…`:`Save`})]})]})}async function mc(e,t,n){let r=new Blob([e],{type:`image/svg+xml`}),i=URL.createObjectURL(r);try{let e=new Image;e.src=i,await e.decode();let r=document.createElement(`canvas`);r.width=e.naturalWidth*t,r.height=e.naturalHeight*t;let a=r.getContext(`2d`);if(!a)throw Error(`Could not acquire 2D canvas context`);a.fillStyle=n,a.fillRect(0,0,r.width,r.height),a.scale(t,t),a.drawImage(e,0,0);let o=await new Promise(e=>{r.toBlob(t=>e(t),`image/png`)});if(o)return o;let s=r.toDataURL(`image/png`);return(await fetch(s)).blob()}finally{URL.revokeObjectURL(i)}}function hc(e){let t=document.createElement(`iframe`);t.setAttribute(`aria-hidden`,`true`),t.style.cssText=`position:fixed;right:0;bottom:0;width:0;height:0;border:0`,document.body.appendChild(t);let n=t.contentDocument;if(!n)throw Error(`iframe contentDocument unavailable`);n.open(),n.write(e),n.close();try{t.contentWindow?.focus(),t.contentWindow?.print()}catch{let t=window.open(``,`_blank`,`noopener,noreferrer`);t&&(t.document.open(),t.document.write(e),t.document.close())}setTimeout(()=>t.remove(),1e3)}function gc(e){Z({panel:e.panel,template_id:e.template_id,options:e.options,format:e.options.format,destination:e.destination}).catch(()=>{})}function _c(e){return e===`light`?`#ffffff`:`#0f172a`}function vc(e,t){return`cctally-${e}-${new Date().toISOString().slice(0,10).replaceAll(`-`,``)}.${sc(t)}`}function yc(e){switch(e){case`md`:return`text/markdown;charset=utf-8`;case`html`:return`text/html;charset=utf-8`;case`svg`:return`image/svg+xml;charset=utf-8`}}function bc(e,t){let n=URL.createObjectURL(t),r=document.createElement(`a`);r.href=n,r.download=e,r.style.display=`none`,document.body.appendChild(r),r.click(),document.body.removeChild(r),setTimeout(()=>URL.revokeObjectURL(n),0)}function xc({panel:e,templateId:t,options:n,onOptionsChange:r}){let[i,a]=(0,g.useState)(null),[o,s]=(0,g.useState)(null),[c,l]=(0,g.useState)(!1),u=(0,g.useRef)(null);(0,g.useEffect)(()=>()=>{u.current!=null&&clearTimeout(u.current)},[]);let[d,f]=(0,g.useState)(!1),p=(0,g.useRef)(null);(0,g.useEffect)(()=>{if(!d)return;function e(e){let t=p.current;t&&(t.contains(e.target)||f(!1))}return document.addEventListener(`mousedown`,e),()=>document.removeEventListener(`mousedown`,e)},[d]),(0,g.useEffect)(()=>{s(null)},[n.format,t]);let m=t==null||i!=null,h=e=>R({type:`SHOW_STATUS_TOAST`,text:e}),_=async()=>{if(!t)throw Error(`no template selected`);return{body:(await Zs({panel:e,template_id:t,options:n})).body,format:n.format}},v=async()=>{if(!(m||!t)){a(`copy`),s(null);try{let{body:r}=await _();if(!navigator.clipboard||typeof navigator.clipboard.writeText!=`function`)throw Error(`Clipboard API unavailable in this browser`);await navigator.clipboard.writeText(r),h(`Copied`),gc({panel:e,template_id:t,options:n,destination:`copy`})}catch(e){s(`Copy failed: ${e instanceof X?e.message??`HTTP ${e.status}`:e.message}`)}finally{a(null)}}},y=async()=>{if(!(m||!t)){a(`download`),s(null);try{let{body:r,format:i}=await _(),a=new Blob([r],{type:yc(i)});bc(vc(e,i),a),h(`Downloaded`),gc({panel:e,template_id:t,options:n,destination:`download`})}catch(e){s(`Download failed: ${e instanceof X?e.message??`HTTP ${e.status}`:e.message}`)}finally{a(null)}}},b=async()=>{if(!(m||!t)){a(`basket`),s(null);try{let r=await Zs({panel:e,template_id:t,options:n}),i=xe({panel:e,template_id:t,options:n,added_at:new Date().toISOString(),data_digest_at_add:r.snapshot.data_digest,kernel_version:r.snapshot.kernel_version,label_hint:oc(e)});R({type:`BASKET_ADD`,item:i});let a=I().basket;if(a.rejectedReason===`capacity`)return;l(!0),u.current!=null&&clearTimeout(u.current),u.current=setTimeout(()=>l(!1),800),R({type:`SHOW_STATUS_TOAST`,text:`Added ${i.label_hint} to basket (${a.items.length})`})}catch(e){s(`Add to basket failed: ${e instanceof X?e.message??`HTTP ${e.status}`:e.message}`)}finally{a(null)}}},x=async()=>{if(!(m||!t)){a(`open`),s(null);try{let{body:r,format:i}=await _(),a=new Blob([r],{type:yc(i)}),o=URL.createObjectURL(a);window.open(o,`_blank`,`noopener,noreferrer`),gc({panel:e,template_id:t,options:n,destination:`open`})}catch(e){s(`Open failed: ${e instanceof X?e.message??`HTTP ${e.status}`:e.message}`)}finally{a(null)}}},S=async()=>{if(!(!t||n.format!==`svg`||m)){a(`png`),s(null);try{let{body:r}=await _(),i=await mc(r,2,_c(n.theme));bc(vc(e,`svg`).replace(/\.svg$/,`.png`),i),h(`PNG downloaded`),gc({panel:e,template_id:t,options:n,destination:`png`})}catch(e){s(`PNG export failed: ${e instanceof X?e.message??`HTTP ${e.status}`:e.message}`)}finally{a(null)}}},C=async()=>{if(!(!t||n.format!==`html`||m)){a(`print`),s(null);try{let{body:r}=await _();hc(r),gc({panel:e,template_id:t,options:n,destination:`print`})}catch(e){s(`Print failed: ${e instanceof X?e.message??`HTTP ${e.status}`:e.message}`)}finally{a(null)}}},w=n.format===`md`&&!m,T=(n.format===`html`||n.format===`svg`)&&!m,ee=n.format===`svg`&&!m,te=n.format===`html`&&!m;return(0,z.jsxs)(`div`,{className:`share-actions`,children:[(0,z.jsxs)(`div`,{className:`share-format-row`,role:`radiogroup`,"aria-label":`Export format`,children:[(0,z.jsx)(`span`,{className:`share-format-label`,children:`Format:`}),[`md`,`html`,`svg`].map(e=>(0,z.jsxs)(`label`,{className:`share-format-radio`,children:[(0,z.jsx)(`input`,{type:`radio`,name:`share-format`,value:e,checked:n.format===e,onChange:()=>r({...n,format:e})}),(0,z.jsx)(`span`,{children:e})]},e))]}),(0,z.jsxs)(`div`,{className:`share-action-row`,children:[(0,z.jsx)(`button`,{type:`button`,className:`share-action share-action-copy`,onClick:v,disabled:!w,title:n.format===`md`?i===`copy`?`Copying…`:`Copy to clipboard`:`Copy is available for Markdown only`,children:i===`copy`?`Copying…`:`Copy`}),(0,z.jsx)(`button`,{type:`button`,className:`share-action share-action-download`,onClick:y,disabled:m,title:i===`download`?`Downloading…`:`Download file`,children:i===`download`?`Downloading…`:`Download`}),(0,z.jsx)(`button`,{type:`button`,className:`share-action share-action-open`,onClick:x,disabled:!T,title:n.format===`html`||n.format===`svg`?i===`open`?`Opening…`:`Open in new tab`:`Open is available for HTML/SVG`,children:i===`open`?`Opening…`:`Open`}),(0,z.jsx)(`button`,{type:`button`,className:`share-action share-action-png`,onClick:S,disabled:!ee,title:n.format===`svg`?i===`png`?`Rasterizing…`:`Download PNG (rasterized from SVG)`:`PNG export — available for SVG format only`,children:i===`png`?`Rasterizing…`:`PNG`}),(0,z.jsx)(`button`,{type:`button`,className:`share-action share-action-print`,onClick:C,disabled:!te,title:n.format===`html`?i===`print`?`Opening print dialog…`:`Open the browser print dialog (save as PDF)`:`Print → PDF — available for HTML format only`,children:i===`print`?`Printing…`:`Print → PDF`}),(0,z.jsx)(`button`,{type:`button`,className:`share-action share-action-basket${c?` share-action-basket-added`:``}`,onClick:b,disabled:m,title:m&&t==null?`Pick a template first`:i===`basket`?`Adding to basket…`:`Add this section to the report basket`,children:c?`✓ Added`:i===`basket`?`Adding…`:`+ Basket`})]}),(0,z.jsxs)(`div`,{className:`share-save-preset-row`,ref:p,children:[(0,z.jsx)(`button`,{type:`button`,className:`share-save-preset`,disabled:t==null||i!=null,onClick:()=>f(e=>!e),"aria-haspopup":`dialog`,"aria-expanded":d,title:t==null?`Pick a template first`:`Save the current recipe as a named preset`,children:`Save preset…`}),d&&t?(0,z.jsx)(pc,{panel:e,templateId:t,options:n,onSaved:()=>f(!1),onCancel:()=>f(!1)}):null]}),o?(0,z.jsx)(`div`,{className:`share-action-error`,role:`alert`,children:o}):null]})}function Sc(e){let t=new Date(e);return Number.isNaN(t.getTime())?e:t.toLocaleString()}function Cc({panel:e,onPick:t,onManage:n}){let[r,i]=(0,g.useState)(!1),[a,o]=(0,g.useState)({}),[s,c]=(0,g.useState)([]),[l,u]=(0,g.useState)(null),d=(0,g.useRef)(null);(0,g.useEffect)(()=>{if(!r)return;let t=new AbortController;return u(null),Promise.all([lc({signal:t.signal}),fc({signal:t.signal})]).then(([t,n])=>{o(t.presets[e]??{}),c(n.history.filter(t=>t.panel===e).slice().reverse())}).catch(e=>{e?.name!==`AbortError`&&u((e instanceof X?e.message??`HTTP ${e.status}`:e.message)??`Failed to load presets`)}),()=>t.abort()},[r,e]),(0,g.useEffect)(()=>{if(!r)return;function e(e){let t=d.current;t&&(t.contains(e.target)||i(!1))}return document.addEventListener(`mousedown`,e),()=>document.removeEventListener(`mousedown`,e)},[r]);let f=Object.keys(a).sort();return(0,z.jsxs)(`div`,{className:`share-presets-dropdown`,ref:d,children:[(0,z.jsx)(`button`,{type:`button`,className:`share-presets-trigger`,"aria-haspopup":`menu`,"aria-expanded":r,onClick:()=>i(e=>!e),children:`presets ▾`}),r?(0,z.jsxs)(`div`,{className:`share-presets-menu`,role:`menu`,children:[l?(0,z.jsx)(`div`,{className:`share-presets-error`,role:`alert`,children:l}):null,f.length===0&&!l?(0,z.jsx)(`div`,{className:`share-presets-empty`,children:`No saved presets yet.`}):null,f.length>0?(0,z.jsx)(`ul`,{className:`share-presets-list`,children:f.map(e=>(0,z.jsx)(`li`,{children:(0,z.jsx)(`button`,{type:`button`,role:`menuitem`,className:`share-presets-item`,onClick:()=>{t(a[e].template_id,a[e].options),i(!1)},children:e})},e))}):null,s.length>0?(0,z.jsxs)(`div`,{className:`share-presets-history`,children:[(0,z.jsx)(`div`,{className:`share-presets-history-heading`,role:`presentation`,children:`Recent shares`}),(0,z.jsx)(`ul`,{className:`share-presets-history-list`,children:s.map(e=>(0,z.jsx)(`li`,{children:(0,z.jsxs)(`button`,{type:`button`,role:`menuitem`,className:`share-presets-history-item`,onClick:()=>{t(e.template_id,e.options),i(!1)},title:`${e.template_id} · ${e.format??`unknown`} · ${e.exported_at}`,children:[(0,z.jsx)(`span`,{className:`share-presets-history-template`,children:e.template_id}),(0,z.jsxs)(`span`,{className:`share-presets-history-meta`,children:[` · `,e.format??`unknown`,` · `,Sc(e.exported_at)]})]})},e.recipe_id))})]}):null,(0,z.jsx)(`div`,{className:`share-presets-footer`,children:(0,z.jsx)(`button`,{type:`button`,role:`menuitem`,className:`share-presets-manage`,onClick:()=>{n(),i(!1)},children:`Manage presets…`})})]}):null]})}var wc=`share-manage-presets-title`;function Tc({open:e,onClose:t}){let[n,r]=(0,g.useState)([]),[i,a]=(0,g.useState)(!1),[o,s]=(0,g.useState)(null);V((0,g.useMemo)(()=>e?[{key:`Escape`,scope:`modal`,action:t}]:[],[e,t]));let c=(0,g.useRef)(null),l=(0,g.useRef)(!1);(0,g.useEffect)(()=>{if(e)l.current||(l.current=!0,c.current=document.activeElement);else if(l.current){l.current=!1;let e=c.current;if(c.current=null,e&&typeof e.focus==`function`&&document.contains(e))e.focus();else{let e=document.activeElement;e&&typeof e.blur==`function`&&e.blur(),document.body.focus()}}},[e]),(0,g.useEffect)(()=>{if(!e)return;let t=!1;return s(null),(async()=>{try{let e=await lc();if(t)return;let n=[];for(let[t,r]of Object.entries(e.presets))for(let[e,i]of Object.entries(r))n.push({panel:t,name:e,record:i});n.sort((e,t)=>e.panel===t.panel?e.name.localeCompare(t.name):e.panel.localeCompare(t.panel)),r(n)}catch(e){if(t)return;s((e instanceof X?e.message??`HTTP ${e.status}`:e.message)??`Failed to load presets`)}})(),()=>{t=!0}},[e]);async function u(e){a(!0),s(null);try{await dc(e.panel,e.name),r(t=>t.filter(t=>!(t.panel===e.panel&&t.name===e.name))),R({type:`SHOW_STATUS_TOAST`,text:`Deleted preset "${e.name}"`})}catch(e){s((e instanceof X?e.message??`HTTP ${e.status}`:e.message)??`Delete failed`)}finally{a(!1)}}async function d(e,t){a(!0),s(null);try{await uc({panel:e.panel,name:t,template_id:e.record.template_id,options:e.record.options}),await dc(e.panel,e.name),r(n=>n.map(n=>n.panel===e.panel&&n.name===e.name?{...n,name:t}:n)),R({type:`SHOW_STATUS_TOAST`,text:`Renamed to "${t}"`})}catch(e){s((e instanceof X?e.message??`HTTP ${e.status}`:e.message)??`Rename failed`)}finally{a(!1)}}return e?(0,z.jsxs)(`div`,{className:`share-manage-modal`,role:`dialog`,"aria-modal":`true`,"aria-labelledby":wc,onClick:e=>e.stopPropagation(),children:[(0,z.jsxs)(`div`,{className:`share-manage-header`,children:[(0,z.jsx)(`h2`,{id:wc,children:`Manage presets`}),(0,z.jsx)(`button`,{type:`button`,onClick:t,"aria-label":`Close`,className:`share-manage-close`,children:`⤬`})]}),o?(0,z.jsx)(`div`,{className:`share-manage-error`,role:`alert`,children:o}):null,n.length===0&&!o?(0,z.jsx)(`p`,{className:`share-manage-empty`,children:`No saved presets yet.`}):null,n.length>0?(0,z.jsxs)(`table`,{className:`share-manage-table`,children:[(0,z.jsx)(`thead`,{children:(0,z.jsxs)(`tr`,{children:[(0,z.jsx)(`th`,{children:`Panel`}),(0,z.jsx)(`th`,{children:`Name`}),(0,z.jsx)(`th`,{children:`Saved at`}),(0,z.jsx)(`th`,{})]})}),(0,z.jsx)(`tbody`,{children:n.map(e=>(0,z.jsx)(Ec,{row:e,busy:i,onDelete:()=>void u(e),onRename:t=>void d(e,t)},`${e.panel}/${e.name}`))})]}):null]}):null}function Ec({row:e,busy:t,onDelete:n,onRename:r}){let[i,a]=(0,g.useState)(!1),[o,s]=(0,g.useState)(e.name),c=()=>{let t=o.trim();if(!t||t===e.name){s(e.name),a(!1);return}r(t),a(!1)};return(0,z.jsxs)(`tr`,{children:[(0,z.jsx)(`td`,{children:oc(e.panel)}),(0,z.jsx)(`td`,{children:i?(0,z.jsx)(`input`,{className:`share-manage-name-input`,autoFocus:!0,value:o,disabled:t,maxLength:64,onChange:e=>s(e.target.value),onKeyDown:t=>{t.key===`Enter`?(t.preventDefault(),c()):t.key===`Escape`&&(t.preventDefault(),t.stopPropagation(),s(e.name),a(!1))}}):(0,z.jsx)(`span`,{children:e.name})}),(0,z.jsx)(`td`,{children:e.record.saved_at}),(0,z.jsxs)(`td`,{className:`share-manage-actions`,children:[(0,z.jsx)(`button`,{type:`button`,disabled:t,onClick:()=>{i?(s(e.name),a(!1)):a(!0)},children:i?`Cancel`:`Rename`}),(0,z.jsx)(`button`,{type:`button`,disabled:t,onClick:n,children:`Delete`})]})]})}function Dc(){return{format:`md`,theme:`light`,reveal_projects:!1,no_branding:!1,top_n:5,period:{kind:`current`},project_allowlist:null,show_chart:!0,show_table:!0}}function Oc(e,t){if(!t)return e;let n={...e,...t};return t.period&&(n.period={...e.period,...t.period}),n}function kc({panel:e,onClose:t,initialParams:n}){let r=oc(e),[i,a]=(0,g.useState)(null),[o,s]=(0,g.useState)(null),[c,l]=(0,g.useState)(null),[u,d]=(0,g.useState)(()=>{let e=Dc();return n?.windowWeeks==null?e:{...e,windowWeeks:n.windowWeeks}}),f=(0,g.useRef)(!1),[p,m]=(0,g.useState)(!1),h=`share-modal-title`;V((0,g.useMemo)(()=>[{key:`Escape`,scope:`overlay`,when:()=>!p&&I().composerModal===null,action:t}],[t,p])),(0,g.useEffect)(()=>{let t=!1;return a(null),s(null),Xs(e).then(e=>{if(t)return;a(e.templates);let n=e.templates[0];n&&(l(n.id),f.current||d(e=>Oc(e,n.default_options)))}).catch(e=>{t||s(e instanceof X?`Couldn't load templates: ${e.message??`HTTP ${e.status}`}`:`Couldn't load templates: ${e.message}`)}),()=>{t=!0}},[e]),(0,g.useEffect)(()=>{if(!i||!c||f.current)return;let e=i.find(e=>e.id===c);e&&d(t=>Oc(t,e.default_options))},[c,i]);let _=e=>{f.current=!0,d(e)};return(0,z.jsxs)(`div`,{className:`share-modal`,role:`dialog`,"aria-modal":`true`,"aria-labelledby":h,onClick:e=>e.stopPropagation(),children:[(0,z.jsx)(`header`,{className:`share-modal-header`,children:(0,z.jsxs)(`h2`,{id:h,children:[`Share `,r,` report`]})}),(0,z.jsxs)(`div`,{className:`share-modal-body`,children:[(0,z.jsxs)(`section`,{className:`share-section share-gallery-section`,"aria-label":`Template gallery`,children:[(0,z.jsx)(`div`,{className:`share-gallery-header`,children:(0,z.jsx)(Cc,{panel:e,onPick:(e,t)=>{l(e),f.current=!0,d(e=>({...e,...t}))},onManage:()=>m(!0)})}),(0,z.jsx)(ec,{panel:e,templates:i,error:o,selectedTemplateId:c,onSelect:e=>l(e)})]}),(0,z.jsxs)(`section`,{className:`share-section share-main-section`,children:[(0,z.jsx)(`div`,{className:`share-knobs-col`,"aria-label":`Render options`,children:(0,z.jsx)(tc,{options:u,onChange:_})}),(0,z.jsx)(`div`,{className:`share-preview-col`,"aria-label":`Live preview`,children:(0,z.jsx)(ic,{panel:e,templateId:c,options:u})})]})]}),(0,z.jsx)(`footer`,{className:`share-modal-footer`,children:(0,z.jsx)(xc,{panel:e,templateId:c,options:u,onOptionsChange:_})}),(0,z.jsx)(`button`,{type:`button`,className:`share-modal-close`,"aria-label":`Close share modal`,onClick:t,children:`⤬`}),(0,z.jsx)(Tc,{open:p,onClose:()=>m(!1)})]})}function Ac(e,t){return{title:t.title,theme:t.theme,format:t.format,no_branding:t.no_branding,reveal_projects:t.reveal_projects,sections:e.map(e=>({snapshot:{panel:e.panel,template_id:e.template_id,options:e.options,data_digest_at_add:e.data_digest_at_add,kernel_version:e.kernel_version}}))}}async function jc(e,t){let n=await fetch(`/api/share/compose`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(e),signal:t?.signal});if(!n.ok){let e={};try{e=await n.json()}catch{}throw new X(n.status,e.field,e.error??`HTTP ${n.status}`,e.code)}return n.json()}function Mc({items:e,results:t,kernelVersion:n,onRefresh:r,onRemove:i,onPreviewOnly:a}){let o=jr(Ar(ji,{activationConstraint:{distance:4}}),Ar(Ei,{coordinateGetter:eo}));function s(t){if(!t.over||t.active.id===t.over.id)return;let n=e.findIndex(e=>e.id===t.active.id),r=e.findIndex(e=>e.id===t.over.id);n<0||r<0||R({type:`BASKET_REORDER`,fromIdx:n,toIdx:r})}return(0,z.jsx)(Ta,{sensors:o,collisionDetection:zr,onDragEnd:s,children:(0,z.jsx)(Ha,{items:e.map(e=>e.id),strategy:za,children:(0,z.jsx)(`ul`,{className:`composer-section-list`,children:e.map((e,o)=>(0,z.jsx)(Nc,{item:e,result:t[o],kernelVersion:n,onRefresh:r,onRemove:i,onPreviewOnly:a},e.id))})})})}function Nc({item:e,result:t,kernelVersion:n,onRefresh:r,onRemove:i,onPreviewOnly:a}){let{attributes:o,listeners:s,setNodeRef:c,transform:l,transition:u,isDragging:d}=Xa({id:e.id}),f=so(),p={transform:gr.Transform.toString(l),transition:f?void 0:u,opacity:d?.4:1},[m,h]=(0,g.useState)(!1),_=t?.drift_detected,v=e.kernel_version!==n,y=!!(_||v);return(0,z.jsxs)(`li`,{ref:c,style:p,className:`composer-section-row`,children:[(0,z.jsx)(`button`,{className:`composer-drag-handle`,"aria-label":`Reorder ${e.label_hint}`,type:`button`,...o,...s,children:`≡`}),(0,z.jsx)(`span`,{className:`composer-section-label`,children:e.label_hint}),y?(0,z.jsx)(`span`,{className:`composer-outdated-badge`,title:_&&v?`Data and kernel both shifted since add-time. Refresh to update.`:_?`Data has changed since this section was added. Refresh to update.`:`Kernel updated since this section was added. Refresh to re-render at the new version.`,children:`Outdated`}):null,(0,z.jsxs)(`div`,{className:`composer-section-actions`,children:[(0,z.jsx)(`button`,{type:`button`,"aria-haspopup":`menu`,"aria-expanded":m,onClick:()=>h(e=>!e),"aria-label":`Actions for ${e.label_hint}`,children:`⋯`}),m?(0,z.jsxs)(`ul`,{role:`menu`,className:`composer-section-menu`,children:[(0,z.jsx)(`li`,{children:(0,z.jsx)(`button`,{type:`button`,onClick:()=>{a(e.id),h(!1)},children:`Preview only this`})}),(0,z.jsx)(`li`,{children:(0,z.jsx)(`button`,{type:`button`,onClick:()=>{r(e.id),h(!1)},children:`Refresh from current data`})}),(0,z.jsx)(`li`,{children:(0,z.jsx)(`button`,{type:`button`,onClick:()=>{i(e.id),h(!1)},"aria-label":`Remove ${e.label_hint}`,children:`Remove`})})]}):null]})]})}function Pc(e,t){return t&&e>0}function Fc(e){return`cctally-report-${new Date().toISOString().slice(0,10).replaceAll(`-`,``)}.${e===`md`?`md`:e}`}function Ic(e){switch(e){case`md`:return`text/markdown;charset=utf-8`;case`html`:return`text/html;charset=utf-8`;case`svg`:return`image/svg+xml;charset=utf-8`}}function Lc(e){return e===`light`?`#ffffff`:`#0f172a`}function Rc(e,t){let n=URL.createObjectURL(t),r=document.createElement(`a`);r.href=n,r.download=e,r.style.display=`none`,document.body.appendChild(r),r.click(),document.body.removeChild(r),setTimeout(()=>URL.revokeObjectURL(n),0)}var zc=200;function Bc(){return I().composerModal}function Vc(){return I().basket}var Q=`composer-modal-title`;function Hc(){let e=(0,g.useSyncExternalStore)(L,Bc),t=(0,g.useSyncExternalStore)(L,Vc),n=on(),r=(0,g.useRef)(null),i=(0,g.useRef)(!1),[a,o]=(0,g.useState)(``),[s,c]=(0,g.useState)(`light`),[l,u]=(0,g.useState)(`html`),[d,f]=(0,g.useState)(!0),[p,m]=(0,g.useState)(!1),[h,_]=(0,g.useState)(null),[v,y]=(0,g.useState)(null),[b,x]=(0,g.useState)(!1),S=(0,g.useRef)(null),[C,w]=(0,g.useState)(null),[T,ee]=(0,g.useState)(null);(0,g.useEffect)(()=>{ee(null)},[l,s,d,p]),V((0,g.useMemo)(()=>[{key:`Escape`,scope:`overlay`,when:()=>I().composerModal!==null,action:()=>R(ve())}],[])),(0,g.useEffect)(()=>{e?.open&&a===``&&o(`cctally report — ${new Date().toISOString().slice(0,10)}`)},[e?.open,a]),(0,g.useEffect)(()=>{if(e?.open)i.current||(i.current=!0,r.current=document.activeElement);else if(i.current){i.current=!1;let e=r.current;if(r.current=null,e&&typeof e.focus==`function`&&document.contains(e))e.focus();else{let e=document.activeElement;e&&typeof e.blur==`function`&&e.blur(),document.body.focus()}}},[e?.open]),(0,g.useEffect)(()=>{if(!e?.open||t.items.length===0||a===``)return;let n=setTimeout(()=>{S.current?.abort();let e=new AbortController;S.current=e,x(!0),y(null),jc(Ac(t.items,{title:a,theme:s,format:l,no_branding:p,reveal_projects:!d}),{signal:e.signal}).then(t=>{e.signal.aborted||_(t)}).catch(t=>{t?.name!==`AbortError`&&(e.signal.aborted||y(t instanceof X?t.message??`HTTP ${t.status}`:t.message))}).finally(()=>{e.signal.aborted||x(!1)})},zc);return()=>clearTimeout(n)},[e?.open,t.items,a,s,l,d,p]);async function te(e){let n=t.items.findIndex(t=>t.id===e);if(n<0)return;let r=t.items[n];try{let t=await Zs({panel:r.panel,template_id:r.template_id,options:{...r.options,reveal_projects:!d}}),i=xe({panel:r.panel,template_id:r.template_id,options:r.options,added_at:new Date().toISOString(),data_digest_at_add:t.snapshot.data_digest,kernel_version:t.snapshot.kernel_version,label_hint:r.label_hint,id:r.id});R({type:`BASKET_REMOVE`,id:e}),R({type:`BASKET_ADD`,item:i});let a=I().basket.items.length-1;a!==n&&R({type:`BASKET_REORDER`,fromIdx:a,toIdx:n})}catch(e){y(`Refresh failed: ${e instanceof X?e.message??`HTTP ${e.status}`:e.message}`)}}let E=async e=>{let n=await jc(Ac(t.items,{title:a,theme:s,format:e,no_branding:p,reveal_projects:!d}));return{body:n.body,content_type:n.content_type}},D=e=>R({type:`SHOW_STATUS_TOAST`,text:e}),O=async(e,t,n)=>{if(C==null){w(e),ee(null);try{await t()}catch(e){ee(`${n} failed: ${e instanceof X?e.message??`HTTP ${e.status}`:e.message}`)}finally{w(null)}}},ne=()=>O(`copy`,async()=>{let{body:e}=await E(`md`);if(!navigator.clipboard||typeof navigator.clipboard.writeText!=`function`)throw Error(`Clipboard API unavailable in this browser`);await navigator.clipboard.writeText(e),D(`Copied`)},`Copy`),k=()=>O(`download`,async()=>{let{body:e}=await E(l),t=new Blob([e],{type:Ic(l)});Rc(Fc(l),t),D(`Downloaded`)},`Download`),re=()=>O(`open`,async()=>{let{body:e}=await E(l),t=new Blob([e],{type:Ic(l)}),n=URL.createObjectURL(t);window.open(n,`_blank`,`noopener,noreferrer`)},`Open`),A=()=>O(`png`,async()=>{let{body:e}=await E(`svg`),t=await mc(e,2,Lc(s));Rc(Fc(`svg`).replace(/\.svg$/,`.png`),t),D(`PNG downloaded`)},`PNG export`),ie=()=>O(`print`,async()=>{let{body:e}=await E(`html`);hc(e)},`Print`),ae=C==null&&l===`md`&&t.items.length>0,oe=C==null&&t.items.length>0,se=C==null&&(l===`html`||l===`svg`)&&t.items.length>0,j=C==null&&l===`svg`&&t.items.length>0,ce=C==null&&l===`html`&&t.items.length>0,le=!d,ue=Pc(t.items.length,le),de=le?t.items.length:0;return e?.open?t.items.length===0?(0,z.jsxs)(`div`,{className:`composer-modal composer-modal-empty${n?` composer-modal-mobile`:``}`,role:`dialog`,"aria-modal":`true`,"aria-labelledby":Q,children:[(0,z.jsxs)(`header`,{className:`composer-modal-header`,children:[(0,z.jsx)(`h2`,{id:Q,children:`Compose report`}),(0,z.jsx)(`button`,{type:`button`,className:`composer-modal-close`,onClick:()=>R(ve()),"aria-label":`Close`,children:`⤬`})]}),(0,z.jsx)(`p`,{className:`composer-empty-message`,children:`Basket is empty. Open any panel's share menu and pick + Basket to add a section.`})]}):(0,z.jsxs)(`div`,{className:`composer-modal${n?` composer-modal-mobile`:``}`,role:`dialog`,"aria-modal":`true`,"aria-labelledby":Q,children:[(0,z.jsxs)(`header`,{className:`composer-modal-header`,children:[(0,z.jsx)(`h2`,{id:Q,children:`Compose report`}),(0,z.jsx)(`button`,{type:`button`,className:`composer-modal-close`,onClick:()=>R(ve()),"aria-label":`Close`,children:`⤬`})]}),(0,z.jsxs)(`div`,{className:`composer-knobs`,children:[(0,z.jsxs)(`label`,{children:[`Title`,(0,z.jsx)(`input`,{type:`text`,value:a,onChange:e=>o(e.target.value)})]}),(0,z.jsxs)(`label`,{children:[`Theme`,(0,z.jsxs)(`select`,{value:s,onChange:e=>c(e.target.value),children:[(0,z.jsx)(`option`,{value:`light`,children:`light`}),(0,z.jsx)(`option`,{value:`dark`,children:`dark`})]})]}),(0,z.jsxs)(`label`,{children:[`Format`,(0,z.jsxs)(`select`,{value:l,onChange:e=>u(e.target.value),children:[(0,z.jsx)(`option`,{value:`html`,children:`html`}),(0,z.jsx)(`option`,{value:`md`,children:`md`}),(0,z.jsx)(`option`,{value:`svg`,children:`svg`})]})]}),(0,z.jsxs)(`label`,{children:[(0,z.jsx)(`input`,{type:`checkbox`,checked:d,onChange:e=>f(e.target.checked)}),`Anon on export`]}),(0,z.jsxs)(`label`,{children:[(0,z.jsx)(`input`,{type:`checkbox`,checked:p,onChange:e=>m(e.target.checked)}),`No branding`]})]}),ue?(0,z.jsxs)(`div`,{className:`composer-anon-banner`,role:`status`,"aria-live":`polite`,children:[(0,z.jsxs)(`span`,{children:[de,` section`,de===1?``:`s`,` contain real project names. They will appear in the export.`]}),(0,z.jsx)(`button`,{type:`button`,onClick:()=>f(!0),children:`Anonymize all`})]}):null,(0,z.jsxs)(`div`,{className:`composer-body`,children:[(0,z.jsx)(Mc,{items:t.items,results:h?.snapshot.section_results??[],kernelVersion:h?.snapshot.kernel_version??1,onRefresh:e=>{te(e)},onRemove:e=>R({type:`BASKET_REMOVE`,id:e}),onPreviewOnly:e=>{}}),(0,z.jsx)(`iframe`,{className:`composer-preview`,title:`Combined preview`,tabIndex:-1,sandbox:`allow-same-origin`,srcDoc:h?.body??`<p>Composing…</p>`})]}),b?(0,z.jsx)(`div`,{className:`composer-busy`,children:`Composing…`}):null,v?(0,z.jsx)(`div`,{className:`composer-error`,role:`alert`,children:v}):null,T?(0,z.jsx)(`div`,{className:`composer-error`,role:`alert`,children:T}):null,(0,z.jsxs)(`footer`,{className:`composer-actions`,children:[(0,z.jsxs)(`div`,{className:`composer-export-row`,children:[(0,z.jsx)(`button`,{type:`button`,className:`share-action share-action-copy`,onClick:ne,disabled:!ae,title:l===`md`?C===`copy`?`Copying…`:`Copy composed report to clipboard`:`Copy is available for Markdown only`,children:C===`copy`?`Copying…`:`Copy`}),(0,z.jsx)(`button`,{type:`button`,className:`share-action share-action-download`,onClick:k,disabled:!oe,title:C===`download`?`Downloading…`:`Download composed report`,children:C===`download`?`Downloading…`:`Download`}),(0,z.jsx)(`button`,{type:`button`,className:`share-action share-action-open`,onClick:re,disabled:!se,title:l===`html`||l===`svg`?C===`open`?`Opening…`:`Open composed report in new tab`:`Open is available for HTML/SVG`,children:C===`open`?`Opening…`:`Open`}),(0,z.jsx)(`button`,{type:`button`,className:`share-action share-action-png`,onClick:A,disabled:!j,title:l===`svg`?C===`png`?`Rasterizing…`:`Download composed report as PNG`:`PNG export — available for SVG format only`,children:C===`png`?`Rasterizing…`:`PNG`}),(0,z.jsx)(`button`,{type:`button`,className:`share-action share-action-print`,onClick:ie,disabled:!ce,title:l===`html`?C===`print`?`Opening print dialog…`:`Open the browser print dialog (save as PDF)`:`Print → PDF — available for HTML format only`,children:C===`print`?`Printing…`:`Print → PDF`})]}),(0,z.jsx)(`button`,{type:`button`,className:`composer-clear-all`,onClick:()=>R({type:`BASKET_CLEAR`}),children:`Clear all`})]})]}):null}function Uc(){let e=(0,g.useSyncExternalStore)(L,()=>I().shareModal),t=(0,g.useRef)(null),n=(0,g.useRef)(!1);(0,g.useEffect)(()=>{if(e)n.current||(n.current=!0,t.current=(e.triggerId?document.getElementById(e.triggerId):null)??document.activeElement);else if(n.current){n.current=!1;let e=t.current;if(t.current=null,e&&typeof e.focus==`function`&&document.contains(e))e.focus();else{let e=document.activeElement;e&&typeof e.blur==`function`&&e.blur(),document.body.focus()}}},[e]);let r=()=>R(ge());return(0,z.jsxs)(z.Fragment,{children:[e?(0,z.jsx)(`div`,{id:`share-modal-root`,className:`share-overlay`,onClick:e=>{e.stopPropagation(),e.target===e.currentTarget&&r()},children:(0,z.jsx)(kc,{panel:e.panel,initialParams:e.params,onClose:r})}):null,(0,z.jsx)(Hc,{})]})}function Wc(){let e=(0,g.useSyncExternalStore)(L,()=>I().prefs.panelOrder);return(0,z.jsxs)(z.Fragment,{children:[(0,z.jsx)(Ot,{}),(0,z.jsx)(ho,{items:e,children:(0,z.jsx)(`div`,{className:`grid`,children:e.map((e,t)=>(0,z.jsx)(co,{id:e,index:t},e))})}),(0,z.jsx)(Pt,{}),(0,z.jsx)(Mn,{}),(0,z.jsx)(In,{}),(0,z.jsx)(Js,{}),(0,z.jsx)(Uc,{}),(0,z.jsx)(Fo,{}),(0,z.jsx)(_o,{}),(0,z.jsx)(Un,{})]})}function Gc(e){let t=I().prefs.panelOrder,n=e-1;if(n<0||n>=t.length)return;let r=kn[t[n]];r&&r.openAction()}var Kc=`Click a panel first, then press S to share it.`;function qc(){return typeof window>`u`||!window.matchMedia?!1:window.matchMedia(an).matches}function Jc(){if(typeof document>`u`)return null;let e=document.activeElement;if(!e||!(e instanceof Element))return null;let t=e.closest(`[data-panel-kind]`);return t?t.getAttribute(`data-panel-kind`):null}function Yc(){return{key:`S`,scope:`global`,when:()=>{let e=I();return!(qc()||e.shareModal!==null||e.composerModal!==null||e.openModal!==null||e.update.modalOpen||e.inputMode!==null)},action:()=>{let e=Jc();if(e===null){R({type:`SHOW_STATUS_TOAST`,text:Kc});return}if(!j.has(e))return;let t=e;R(N(t,`${t}-panel`))}}}function Xc(){return typeof window>`u`||!window.matchMedia?!1:window.matchMedia(an).matches}function Zc(){return{key:`B`,scope:`global`,when:()=>{let e=I();return!(Xc()||e.shareModal!==null||e.composerModal!==null||e.openModal!==null||e.update.modalOpen||e.inputMode!==null)},action:()=>R(_e())}}function Qc(){return[Zc()]}mt(),nt(),Bt();var $=()=>{let e=I();return!e.update.modalOpen&&!e.doctorModalOpen};zt([{key:`1`,scope:`global`,when:$,action:()=>Gc(1)},{key:`2`,scope:`global`,when:$,action:()=>Gc(2)},{key:`3`,scope:`global`,when:$,action:()=>Gc(3)},{key:`4`,scope:`global`,when:$,action:()=>Gc(4)},{key:`5`,scope:`global`,when:$,action:()=>Gc(5)},{key:`6`,scope:`global`,when:$,action:()=>Gc(6)},{key:`7`,scope:`global`,when:$,action:()=>Gc(7)},{key:`8`,scope:`global`,when:$,action:()=>Gc(8)},{key:`9`,scope:`global`,when:$,action:()=>Gc(9)},{key:`0`,scope:`global`,when:$,action:()=>Gc(10)},{key:`r`,scope:`global`,when:$,action:()=>Et()},{key:`q`,scope:`global`,when:$,action:Nt},{key:`n`,scope:`global`,when:$,action:()=>jt(1)},{key:`N`,scope:`global`,when:$,action:()=>jt(-1)},{key:`d`,scope:`global`,when:()=>{let e=I();return!(e.openModal!==null||e.update.modalOpen||e.inputMode!==null)},action:()=>R({type:`OPEN_DOCTOR_MODAL`})},Yc(),...Qc(),{key:`c`,scope:`sessions`,when:()=>!I().openModal,action:()=>{let e=I().prefs.sessionsCollapsed;R({type:`SAVE_PREFS`,patch:{sessionsCollapsed:!e}})}}]);var $c=document.getElementById(`root`);if(!$c)throw Error(`missing #root`);(0,_.createRoot)($c).render((0,z.jsx)(g.StrictMode,{children:(0,z.jsx)(Wc,{})}));
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<meta charset="utf-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
|
|
6
6
|
<title>cctally dashboard</title>
|
|
7
|
-
<script type="module" crossorigin src="/static/assets/index-
|
|
7
|
+
<script type="module" crossorigin src="/static/assets/index-Cy59E7Ru.js"></script>
|
|
8
8
|
<link rel="stylesheet" crossorigin href="/static/assets/index-Dp14ELVt.css">
|
|
9
9
|
</head>
|
|
10
10
|
<body>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cctally",
|
|
3
|
-
"version": "1.10.
|
|
3
|
+
"version": "1.10.2",
|
|
4
4
|
"description": "Claude Code usage tracker and local dashboard for Pro/Max subscription limits - weekly cost-per-percent trend, quota forecasts, threshold alerts. ccusage-compatible.",
|
|
5
5
|
"homepage": "https://github.com/omrikais/cctally",
|
|
6
6
|
"repository": {
|