openclacky 1.5.7 → 1.5.8
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +33 -0
- data/README.md +2 -2
- data/README_CN.md +1 -1
- data/README_JA.md +1 -1
- data/lib/clacky/agent.rb +2 -3
- data/lib/clacky/agent_config.rb +40 -18
- data/lib/clacky/cli.rb +0 -1
- data/lib/clacky/default_extensions/ext-studio/panels/studio/view.js +23 -10
- data/lib/clacky/default_extensions/ext-studio/skills/ext-develop/SKILL.md +3 -2
- data/lib/clacky/default_extensions/general/ext.yml +1 -1
- data/lib/clacky/extension/api_loader.rb +4 -11
- data/lib/clacky/extension/packager.rb +1 -1
- data/lib/clacky/extension/verifier.rb +1 -1
- data/lib/clacky/media/generator.rb +3 -3
- data/lib/clacky/message_history.rb +1 -1
- data/lib/clacky/providers.rb +2 -1
- data/lib/clacky/server/http_server.rb +60 -76
- data/lib/clacky/session_manager.rb +7 -0
- data/lib/clacky/ui2/components/inline_input.rb +1 -0
- data/lib/clacky/ui2/components/input_area.rb +1 -0
- data/lib/clacky/ui2/components/modal_component.rb +0 -1
- data/lib/clacky/ui2/components/todo_area.rb +1 -0
- data/lib/clacky/ui2/line_editor.rb +1 -0
- data/lib/clacky/ui2/markdown_renderer.rb +5 -1
- data/lib/clacky/ui2/ui_controller.rb +1 -0
- data/lib/clacky/version.rb +1 -1
- data/lib/clacky/web/app.css +134 -210
- data/lib/clacky/web/components/chat-navigator.js +1 -1
- data/lib/clacky/web/features/billing/store.js +3 -3
- data/lib/clacky/web/features/billing/view.js +5 -61
- data/lib/clacky/web/features/extensions/store.js +1 -1
- data/lib/clacky/web/features/extensions/view.js +28 -5
- data/lib/clacky/web/features/new-session/view.js +24 -0
- data/lib/clacky/web/i18n.js +20 -18
- data/lib/clacky/web/index.html +12 -13
- data/lib/clacky/web/projects.js +73 -282
- data/lib/clacky/web/settings.js +6 -1
- metadata +1 -1
|
@@ -335,6 +335,13 @@ module Clacky
|
|
|
335
335
|
# sessions are never deleted and do not count toward the cap.
|
|
336
336
|
# Returns count of soft-deleted sessions.
|
|
337
337
|
def cleanup_by_count(keep:, grouped_keep: 200)
|
|
338
|
+
# Fast path: if total session files can't exceed any single group's cap,
|
|
339
|
+
# skip the expensive all_sessions() full-scan (read + JSON.parse every file).
|
|
340
|
+
# min() is correct because groups are mutually exclusive — any single
|
|
341
|
+
# group's count ≤ non_pinned ≤ file_count ≤ min(keep, grouped_keep).
|
|
342
|
+
file_count = Dir.glob(File.join(@sessions_dir, "*.json")).size
|
|
343
|
+
return 0 if file_count <= [keep, grouped_keep].min
|
|
344
|
+
|
|
338
345
|
non_pinned = all_sessions.reject { |s| s[:pinned] }
|
|
339
346
|
|
|
340
347
|
groups = non_pinned.group_by do |s|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "tty-
|
|
3
|
+
require "tty-screen"
|
|
4
4
|
require_relative "theme_manager"
|
|
5
5
|
|
|
6
6
|
module Clacky
|
|
@@ -14,6 +14,10 @@ module Clacky
|
|
|
14
14
|
def render(content)
|
|
15
15
|
return content if content.nil? || content.empty?
|
|
16
16
|
|
|
17
|
+
# tty-markdown pulls in rouge + kramdown (~0.4s). Server mode renders
|
|
18
|
+
# markdown in the browser, so only pay that cost on a real terminal render.
|
|
19
|
+
require "tty-markdown" unless defined?(TTY::Markdown)
|
|
20
|
+
|
|
17
21
|
# Get current theme colors
|
|
18
22
|
theme = ThemeManager.current_theme
|
|
19
23
|
|
data/lib/clacky/version.rb
CHANGED
data/lib/clacky/web/app.css
CHANGED
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
--color-border-strong: #d4d4ce; /* hover / active outline */
|
|
31
31
|
|
|
32
32
|
/* Text — 4-tier hierarchy */
|
|
33
|
-
--color-text-primary: #
|
|
33
|
+
--color-text-primary: #344054; /* titles, important content */
|
|
34
34
|
--color-text-secondary: #56585e; /* body text */
|
|
35
35
|
--color-text-tertiary: #8a8d94; /* captions, meta */
|
|
36
36
|
--color-text-muted: #a8abb2; /* placeholders, disabled */
|
|
@@ -55,6 +55,7 @@
|
|
|
55
55
|
--color-warning: #f59e0b;
|
|
56
56
|
--color-warning-bg: #fffbeb;
|
|
57
57
|
--color-warning-border: #fcd34d;
|
|
58
|
+
--color-warning-text: #92400e;
|
|
58
59
|
|
|
59
60
|
--color-info: #0ea5e9;
|
|
60
61
|
--color-secondary: #10b981;
|
|
@@ -113,7 +114,7 @@
|
|
|
113
114
|
--color-border-secondary: #1e2229;
|
|
114
115
|
--color-border-strong: #3a3f4a;
|
|
115
116
|
|
|
116
|
-
--color-text-primary: #
|
|
117
|
+
--color-text-primary: #c2cad1;
|
|
117
118
|
--color-text-secondary: #a4a9b4;
|
|
118
119
|
--color-text-tertiary: #6b707b;
|
|
119
120
|
--color-text-muted: #565b66;
|
|
@@ -137,6 +138,7 @@
|
|
|
137
138
|
--color-warning: #fbbf24;
|
|
138
139
|
--color-warning-bg: #2d1f00;
|
|
139
140
|
--color-warning-border: #4d3200;
|
|
141
|
+
--color-warning-text: #fcd34d;
|
|
140
142
|
|
|
141
143
|
--color-info: #38bdf8;
|
|
142
144
|
--color-secondary: #34d399;
|
|
@@ -190,6 +192,7 @@
|
|
|
190
192
|
--color-warning: #fbbf24;
|
|
191
193
|
--color-warning-bg: #2d1f00;
|
|
192
194
|
--color-warning-border: #4d3200;
|
|
195
|
+
--color-warning-text: #fcd34d;
|
|
193
196
|
|
|
194
197
|
--color-info: #38bdf8;
|
|
195
198
|
--color-secondary: #34d399;
|
|
@@ -242,6 +245,7 @@
|
|
|
242
245
|
--color-warning: #f59e0b;
|
|
243
246
|
--color-warning-bg: #fffbeb;
|
|
244
247
|
--color-warning-border: #fcd34d;
|
|
248
|
+
--color-warning-text: #92400e;
|
|
245
249
|
|
|
246
250
|
--color-info: #0ea5e9;
|
|
247
251
|
--color-secondary: #10b981;
|
|
@@ -294,6 +298,7 @@
|
|
|
294
298
|
--color-warning: #fbbf24;
|
|
295
299
|
--color-warning-bg: #2d1f00;
|
|
296
300
|
--color-warning-border: #4d3200;
|
|
301
|
+
--color-warning-text: #fcd34d;
|
|
297
302
|
|
|
298
303
|
--color-info: #38bdf8;
|
|
299
304
|
--color-secondary: #34d399;
|
|
@@ -807,7 +812,11 @@ body {
|
|
|
807
812
|
margin-bottom: 6px;
|
|
808
813
|
border-bottom: 1px solid var(--color-border-secondary);
|
|
809
814
|
}
|
|
810
|
-
#ext-slot-sidebar-nav
|
|
815
|
+
#ext-slot-sidebar-nav {
|
|
816
|
+
margin-top: 10px;
|
|
817
|
+
padding: 10px 0 0px;
|
|
818
|
+
border-top: 1px solid var(--color-border-secondary);
|
|
819
|
+
}
|
|
811
820
|
#ext-slot-sidebar-nav-bottom {
|
|
812
821
|
padding: 8px 0 10px;
|
|
813
822
|
margin-top: 6px;
|
|
@@ -821,7 +830,7 @@ body {
|
|
|
821
830
|
gap: 8px;
|
|
822
831
|
padding: 14px 8px 7px;
|
|
823
832
|
font-family: var(--font-mono);
|
|
824
|
-
font-size: 0.
|
|
833
|
+
font-size: 0.75rem;
|
|
825
834
|
font-weight: 500;
|
|
826
835
|
color: var(--color-text-tertiary);
|
|
827
836
|
text-transform: uppercase;
|
|
@@ -1511,8 +1520,7 @@ body {
|
|
|
1511
1520
|
display: flex;
|
|
1512
1521
|
align-items: center;
|
|
1513
1522
|
gap: 0.25rem;
|
|
1514
|
-
|
|
1515
|
-
font-size: 0.8125rem;
|
|
1523
|
+
font-size: 0.8325rem;
|
|
1516
1524
|
font-weight: 400;
|
|
1517
1525
|
transition: color var(--transition-fast), font-weight var(--transition-fast);
|
|
1518
1526
|
}
|
|
@@ -1805,7 +1813,7 @@ body {
|
|
|
1805
1813
|
opacity: 1;
|
|
1806
1814
|
}
|
|
1807
1815
|
.task-item.active {
|
|
1808
|
-
background: var(--color-
|
|
1816
|
+
background: var(--color-bg-hover);
|
|
1809
1817
|
}
|
|
1810
1818
|
.task-item.active::before {
|
|
1811
1819
|
content: "";
|
|
@@ -2802,7 +2810,7 @@ body {
|
|
|
2802
2810
|
position: absolute;
|
|
2803
2811
|
top: 0.5rem;
|
|
2804
2812
|
right: 0.5rem;
|
|
2805
|
-
z-index:
|
|
2813
|
+
z-index: 100;
|
|
2806
2814
|
display: inline-flex;
|
|
2807
2815
|
align-items: center;
|
|
2808
2816
|
justify-content: center;
|
|
@@ -7982,6 +7990,29 @@ body {
|
|
|
7982
7990
|
border-radius: 4px;
|
|
7983
7991
|
padding: 0.0625rem 0.375rem;
|
|
7984
7992
|
}
|
|
7993
|
+
.extension-verified {
|
|
7994
|
+
font-size: 0.625rem;
|
|
7995
|
+
color: var(--color-success, #16a34a);
|
|
7996
|
+
background: var(--color-success-bg, rgba(22,163,74,0.12));
|
|
7997
|
+
border-radius: 4px;
|
|
7998
|
+
padding: 0.2rem 0.375rem;
|
|
7999
|
+
}
|
|
8000
|
+
.extension-unverified-banner {
|
|
8001
|
+
font-size: 0.75rem;
|
|
8002
|
+
color: var(--color-warning-text, #92400e);
|
|
8003
|
+
background: var(--color-warning-bg, #fffbeb);
|
|
8004
|
+
border: 1px solid var(--color-warning-border, #fcd34d);
|
|
8005
|
+
border-radius: 8px;
|
|
8006
|
+
padding: 0.5rem 0.75rem;
|
|
8007
|
+
line-height: 1.4;
|
|
8008
|
+
display: flex;
|
|
8009
|
+
align-items: center;
|
|
8010
|
+
gap: 0.5rem;
|
|
8011
|
+
}
|
|
8012
|
+
.extension-unverified-icon {
|
|
8013
|
+
flex-shrink: 0;
|
|
8014
|
+
color: var(--color-warning, #d97706);
|
|
8015
|
+
}
|
|
7985
8016
|
.extension-desc {
|
|
7986
8017
|
font-size: 0.75rem;
|
|
7987
8018
|
color: var(--color-text-secondary);
|
|
@@ -11549,6 +11580,42 @@ body.setup-mode[data-theme="dark"] {
|
|
|
11549
11580
|
gap: 0.625rem;
|
|
11550
11581
|
}
|
|
11551
11582
|
|
|
11583
|
+
/* ── Segmented Control (reusable compact tab selector) ──────────────────── */
|
|
11584
|
+
.segmented-control {
|
|
11585
|
+
display: flex;
|
|
11586
|
+
gap: 2px;
|
|
11587
|
+
background: var(--color-bg-hover);
|
|
11588
|
+
border-radius: 8px;
|
|
11589
|
+
padding: 3px;
|
|
11590
|
+
}
|
|
11591
|
+
.segmented-control__btn {
|
|
11592
|
+
padding: 0.3125rem 0.75rem;
|
|
11593
|
+
border: none;
|
|
11594
|
+
background: transparent;
|
|
11595
|
+
color: var(--color-text-secondary);
|
|
11596
|
+
font-size: 0.8125rem;
|
|
11597
|
+
cursor: pointer;
|
|
11598
|
+
border-radius: 6px;
|
|
11599
|
+
transition: all 0.15s ease;
|
|
11600
|
+
white-space: nowrap;
|
|
11601
|
+
}
|
|
11602
|
+
.segmented-control__btn:hover:not(.active) {
|
|
11603
|
+
color: var(--color-text-primary);
|
|
11604
|
+
}
|
|
11605
|
+
.segmented-control__btn.active {
|
|
11606
|
+
background: var(--color-bg-secondary);
|
|
11607
|
+
color: var(--color-text-primary);
|
|
11608
|
+
font-weight: 500;
|
|
11609
|
+
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08), 0 1px 2px rgba(0, 0, 0, 0.06);
|
|
11610
|
+
}
|
|
11611
|
+
[data-theme="dark"] .segmented-control {
|
|
11612
|
+
background: var(--color-bg-primary);
|
|
11613
|
+
}
|
|
11614
|
+
[data-theme="dark"] .segmented-control__btn.active {
|
|
11615
|
+
background: var(--color-bg-hover);
|
|
11616
|
+
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4);
|
|
11617
|
+
}
|
|
11618
|
+
|
|
11552
11619
|
/* ═════════════════════════════════════════════════════════════════════════
|
|
11553
11620
|
* BILLING PANEL
|
|
11554
11621
|
* ═════════════════════════════════════════════════════════════════════════ */
|
|
@@ -11636,39 +11703,9 @@ body.setup-mode[data-theme="dark"] {
|
|
|
11636
11703
|
border-radius: 6px;
|
|
11637
11704
|
}
|
|
11638
11705
|
|
|
11639
|
-
/* ── Period Button Group ─────────────────────────────────────────────── */
|
|
11640
|
-
.billing-period-group {
|
|
11641
|
-
display: flex;
|
|
11642
|
-
background: var(--color-bg-secondary);
|
|
11643
|
-
border: 1px solid var(--color-border-primary);
|
|
11644
|
-
border-radius: 8px;
|
|
11645
|
-
overflow: hidden;
|
|
11646
|
-
}
|
|
11647
|
-
.billing-period-btn {
|
|
11648
|
-
padding: 0.4375rem 0.75rem;
|
|
11649
|
-
border: none;
|
|
11650
|
-
background: transparent;
|
|
11651
|
-
color: var(--color-text-secondary);
|
|
11652
|
-
font-size: 0.8125rem;
|
|
11653
|
-
cursor: pointer;
|
|
11654
|
-
transition: all 0.15s ease;
|
|
11655
|
-
}
|
|
11656
|
-
.billing-period-btn:not(:last-child) {
|
|
11657
|
-
border-right: 1px solid var(--color-border-primary);
|
|
11658
|
-
}
|
|
11659
|
-
.billing-period-btn:hover {
|
|
11660
|
-
background: var(--color-bg-hover);
|
|
11661
|
-
color: var(--color-text-primary);
|
|
11662
|
-
}
|
|
11663
|
-
.billing-period-btn.active {
|
|
11664
|
-
background: var(--color-accent-primary);
|
|
11665
|
-
color: #ffffff;
|
|
11666
|
-
font-weight: 500;
|
|
11667
|
-
}
|
|
11668
|
-
|
|
11669
11706
|
/* ── Model Filter ────────────────────────────────────────────────────── */
|
|
11670
11707
|
.billing-model-filter {
|
|
11671
|
-
padding: 0.
|
|
11708
|
+
padding: 0.5375rem 1.75rem 0.5375rem 0.75rem;
|
|
11672
11709
|
border: 1px solid var(--color-border-primary);
|
|
11673
11710
|
border-radius: 8px;
|
|
11674
11711
|
background: var(--color-bg-secondary);
|
|
@@ -11693,28 +11730,6 @@ body.setup-mode[data-theme="dark"] {
|
|
|
11693
11730
|
}
|
|
11694
11731
|
|
|
11695
11732
|
/* ── Action Buttons ──────────────────────────────────────────────────── */
|
|
11696
|
-
.billing-clear-container {
|
|
11697
|
-
position: relative;
|
|
11698
|
-
}
|
|
11699
|
-
.billing-clear-btn {
|
|
11700
|
-
width: 32px;
|
|
11701
|
-
height: 32px;
|
|
11702
|
-
display: inline-flex;
|
|
11703
|
-
align-items: center;
|
|
11704
|
-
justify-content: center;
|
|
11705
|
-
border: 1px solid var(--color-border-primary);
|
|
11706
|
-
border-radius: 8px;
|
|
11707
|
-
background: var(--color-bg-secondary);
|
|
11708
|
-
color: var(--color-text-secondary);
|
|
11709
|
-
font-size: 0.875rem;
|
|
11710
|
-
cursor: pointer;
|
|
11711
|
-
transition: all 0.15s ease;
|
|
11712
|
-
}
|
|
11713
|
-
.billing-clear-btn:hover {
|
|
11714
|
-
background: var(--color-bg-tertiary);
|
|
11715
|
-
border-color: #ef4444;
|
|
11716
|
-
color: #ef4444;
|
|
11717
|
-
}
|
|
11718
11733
|
.billing-share-btn {
|
|
11719
11734
|
display: inline-flex;
|
|
11720
11735
|
align-items: center;
|
|
@@ -11735,43 +11750,6 @@ body.setup-mode[data-theme="dark"] {
|
|
|
11735
11750
|
color: var(--color-text-primary);
|
|
11736
11751
|
border-color: var(--color-accent-primary);
|
|
11737
11752
|
}
|
|
11738
|
-
.billing-clear-popup {
|
|
11739
|
-
position: absolute;
|
|
11740
|
-
top: 100%;
|
|
11741
|
-
right: 0;
|
|
11742
|
-
margin-top: 0.25rem;
|
|
11743
|
-
display: flex;
|
|
11744
|
-
flex-direction: column;
|
|
11745
|
-
gap: 0.25rem;
|
|
11746
|
-
background: var(--color-bg-secondary);
|
|
11747
|
-
border: 1px solid var(--color-border-primary);
|
|
11748
|
-
border-radius: 8px;
|
|
11749
|
-
padding: 0.375rem;
|
|
11750
|
-
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
|
|
11751
|
-
z-index: 100;
|
|
11752
|
-
min-width: 120px;
|
|
11753
|
-
}
|
|
11754
|
-
.billing-clear-option {
|
|
11755
|
-
padding: 0.4375rem 0.75rem;
|
|
11756
|
-
border: none;
|
|
11757
|
-
border-radius: 6px;
|
|
11758
|
-
background: transparent;
|
|
11759
|
-
color: var(--color-text-primary);
|
|
11760
|
-
font-size: 0.8125rem;
|
|
11761
|
-
cursor: pointer;
|
|
11762
|
-
text-align: left;
|
|
11763
|
-
white-space: nowrap;
|
|
11764
|
-
transition: background 0.15s ease;
|
|
11765
|
-
}
|
|
11766
|
-
.billing-clear-option:hover {
|
|
11767
|
-
background: var(--color-bg-tertiary);
|
|
11768
|
-
}
|
|
11769
|
-
.billing-clear-danger {
|
|
11770
|
-
color: #ef4444;
|
|
11771
|
-
}
|
|
11772
|
-
.billing-clear-danger:hover {
|
|
11773
|
-
background: rgba(239, 68, 68, 0.08) !important;
|
|
11774
|
-
}
|
|
11775
11753
|
|
|
11776
11754
|
/* ── Stats Row ───────────────────────────────────────────────────────── */
|
|
11777
11755
|
.billing-stats-row {
|
|
@@ -11901,11 +11879,6 @@ body.setup-mode[data-theme="dark"] {
|
|
|
11901
11879
|
}
|
|
11902
11880
|
|
|
11903
11881
|
/* ── Cost Trend Line Chart ───────────────────────────────────────────── */
|
|
11904
|
-
.billing-trend-total {
|
|
11905
|
-
font-size: 0.75rem;
|
|
11906
|
-
font-weight: 500;
|
|
11907
|
-
color: var(--color-accent-primary);
|
|
11908
|
-
}
|
|
11909
11882
|
.billing-trend-chart {
|
|
11910
11883
|
flex: 1;
|
|
11911
11884
|
min-height: 0;
|
|
@@ -14050,11 +14023,23 @@ body.setup-mode[data-theme="dark"] {
|
|
|
14050
14023
|
}
|
|
14051
14024
|
|
|
14052
14025
|
/* ── Section-level collapse ────────────────────────────────────────────────── */
|
|
14026
|
+
#projects-section-header {
|
|
14027
|
+
cursor: pointer;
|
|
14028
|
+
padding: 0.25rem 0.5rem;
|
|
14029
|
+
margin-top: 0.5rem;
|
|
14030
|
+
border-radius: var(--radius-sm);
|
|
14031
|
+
transition: background var(--transition-fast);
|
|
14032
|
+
}
|
|
14033
|
+
#projects-section-header:hover {
|
|
14034
|
+
background: var(--color-bg-hover);
|
|
14035
|
+
}
|
|
14036
|
+
#projects-section-header:hover .btn-icon-sm:hover {
|
|
14037
|
+
background: var(--color-border-primary);
|
|
14038
|
+
}
|
|
14053
14039
|
.projects-section-title {
|
|
14054
14040
|
display: inline-flex;
|
|
14055
14041
|
align-items: center;
|
|
14056
14042
|
gap: 3px;
|
|
14057
|
-
cursor: pointer;
|
|
14058
14043
|
}
|
|
14059
14044
|
.projects-section-chevron {
|
|
14060
14045
|
flex-shrink: 0;
|
|
@@ -14078,8 +14063,8 @@ body.setup-mode[data-theme="dark"] {
|
|
|
14078
14063
|
.project-group-header {
|
|
14079
14064
|
display: flex;
|
|
14080
14065
|
align-items: center;
|
|
14081
|
-
gap: 0.
|
|
14082
|
-
padding: 0.
|
|
14066
|
+
gap: 0.575rem;
|
|
14067
|
+
padding: 0.3325rem 0.625rem;
|
|
14083
14068
|
border-radius: var(--radius-sm);
|
|
14084
14069
|
cursor: pointer;
|
|
14085
14070
|
user-select: none;
|
|
@@ -14095,7 +14080,7 @@ body.setup-mode[data-theme="dark"] {
|
|
|
14095
14080
|
overflow: hidden;
|
|
14096
14081
|
text-overflow: ellipsis;
|
|
14097
14082
|
white-space: nowrap;
|
|
14098
|
-
font-size: 0.
|
|
14083
|
+
font-size: 0.875rem;
|
|
14099
14084
|
color: var(--color-text-primary);
|
|
14100
14085
|
}
|
|
14101
14086
|
|
|
@@ -14134,113 +14119,18 @@ body.setup-mode[data-theme="dark"] {
|
|
|
14134
14119
|
margin-top: 0.08rem;
|
|
14135
14120
|
}
|
|
14136
14121
|
|
|
14137
|
-
.project-
|
|
14138
|
-
padding: 0.25rem 0.5rem 0.25rem 0.625rem;
|
|
14139
|
-
font-size: 0.75rem;
|
|
14140
|
-
color: var(--color-text-muted);
|
|
14141
|
-
}
|
|
14142
|
-
|
|
14143
|
-
/* ── Project hover tooltip ─────────────────────────────────────────────────── */
|
|
14144
|
-
.project-tooltip {
|
|
14145
|
-
position: fixed;
|
|
14146
|
-
z-index: 1200;
|
|
14147
|
-
background: var(--color-bg-secondary);
|
|
14148
|
-
border: 1px solid var(--color-border-primary);
|
|
14149
|
-
border-radius: 10px;
|
|
14150
|
-
box-shadow: 0 8px 24px rgba(0,0,0,.10), 0 2px 8px rgba(0,0,0,.06);
|
|
14151
|
-
padding: 0.75rem 0.875rem 0.75rem 1.125rem; /* extra left padding = visual gap */
|
|
14152
|
-
min-width: 13rem;
|
|
14153
|
-
max-width: 18rem;
|
|
14154
|
-
animation: fadeIn 0.12s ease;
|
|
14155
|
-
}
|
|
14156
|
-
/* Transparent bridge on the left side fills the gap between sidebar and tooltip */
|
|
14157
|
-
.project-tooltip::before {
|
|
14158
|
-
content: "";
|
|
14159
|
-
position: absolute;
|
|
14160
|
-
top: 0;
|
|
14161
|
-
left: -8px;
|
|
14162
|
-
width: 8px;
|
|
14163
|
-
height: 100%;
|
|
14164
|
-
}
|
|
14165
|
-
[data-theme="dark"] .project-tooltip {
|
|
14166
|
-
box-shadow: 0 8px 28px rgba(0,0,0,.55), 0 2px 8px rgba(0,0,0,.35);
|
|
14167
|
-
}
|
|
14168
|
-
|
|
14169
|
-
.project-tooltip-header {
|
|
14170
|
-
display: flex;
|
|
14171
|
-
align-items: center;
|
|
14172
|
-
gap: 0.4rem;
|
|
14173
|
-
margin-bottom: 0.75rem;
|
|
14174
|
-
}
|
|
14175
|
-
.project-tooltip-icon {
|
|
14176
|
-
flex-shrink: 0;
|
|
14177
|
-
display: flex;
|
|
14178
|
-
align-items: center;
|
|
14179
|
-
justify-content: center;
|
|
14180
|
-
color: var(--color-text-secondary);
|
|
14181
|
-
line-height: 0;
|
|
14182
|
-
}
|
|
14183
|
-
.project-tooltip-icon svg {
|
|
14184
|
-
display: block;
|
|
14185
|
-
flex-shrink: 0;
|
|
14186
|
-
}
|
|
14187
|
-
.project-tooltip-name {
|
|
14188
|
-
flex: 1;
|
|
14189
|
-
min-width: 0;
|
|
14190
|
-
font-size: 0.8125rem;
|
|
14191
|
-
font-weight: 500;
|
|
14192
|
-
color: var(--color-text-primary);
|
|
14193
|
-
overflow: hidden;
|
|
14194
|
-
text-overflow: ellipsis;
|
|
14195
|
-
white-space: nowrap;
|
|
14196
|
-
}
|
|
14197
|
-
.project-tooltip-rows {
|
|
14198
|
-
display: flex;
|
|
14199
|
-
flex-direction: column;
|
|
14200
|
-
gap: 0.3rem;
|
|
14201
|
-
}
|
|
14202
|
-
.project-tooltip-row {
|
|
14203
|
-
display: flex;
|
|
14204
|
-
align-items: center;
|
|
14205
|
-
gap: 0.4rem;
|
|
14206
|
-
font-size: 0.75rem;
|
|
14207
|
-
color: var(--color-text-secondary);
|
|
14208
|
-
min-width: 0;
|
|
14209
|
-
}
|
|
14210
|
-
.project-tooltip-row--clickable {
|
|
14211
|
-
cursor: pointer;
|
|
14212
|
-
border-radius: 4px;
|
|
14213
|
-
margin: 0 -0.25rem;
|
|
14214
|
-
padding: 0.15rem 0.25rem;
|
|
14215
|
-
transition: background var(--transition-fast);
|
|
14216
|
-
}
|
|
14217
|
-
.project-tooltip-row--clickable:hover {
|
|
14122
|
+
.project-session-group .session-item.active {
|
|
14218
14123
|
background: var(--color-bg-hover);
|
|
14219
14124
|
}
|
|
14220
14125
|
|
|
14221
|
-
.project-
|
|
14222
|
-
|
|
14223
|
-
background: var(--color-border-primary);
|
|
14224
|
-
margin: 0.25rem 0;
|
|
14126
|
+
.project-session-group .session-item.active::before {
|
|
14127
|
+
display: none;
|
|
14225
14128
|
}
|
|
14226
14129
|
|
|
14227
|
-
.project-
|
|
14228
|
-
|
|
14130
|
+
.project-sessions-empty {
|
|
14131
|
+
padding: 0.25rem 0.5rem 0.25rem 0.625rem;
|
|
14132
|
+
font-size: 0.75rem;
|
|
14229
14133
|
color: var(--color-text-muted);
|
|
14230
|
-
display: flex;
|
|
14231
|
-
align-items: center;
|
|
14232
|
-
line-height: 0;
|
|
14233
|
-
}
|
|
14234
|
-
.project-tooltip-row-icon svg {
|
|
14235
|
-
display: block;
|
|
14236
|
-
flex-shrink: 0;
|
|
14237
|
-
}
|
|
14238
|
-
.project-tooltip-row-text {
|
|
14239
|
-
min-width: 0;
|
|
14240
|
-
overflow: hidden;
|
|
14241
|
-
text-overflow: ellipsis;
|
|
14242
|
-
white-space: nowrap;
|
|
14243
|
-
line-height: 1.4;
|
|
14244
14134
|
}
|
|
14245
14135
|
|
|
14246
14136
|
/* ── Project context menu (rename / delete) ────────────────────────────────── */
|
|
@@ -14258,7 +14148,9 @@ body.setup-mode[data-theme="dark"] {
|
|
|
14258
14148
|
box-shadow: 0 8px 24px rgba(0,0,0,.5), 0 2px 6px rgba(0,0,0,.3);
|
|
14259
14149
|
}
|
|
14260
14150
|
.project-actions-menu-item {
|
|
14261
|
-
display:
|
|
14151
|
+
display: flex;
|
|
14152
|
+
align-items: center;
|
|
14153
|
+
gap: 0.5rem;
|
|
14262
14154
|
width: 100%;
|
|
14263
14155
|
padding: 0.375rem 0.625rem;
|
|
14264
14156
|
border: none;
|
|
@@ -14267,17 +14159,43 @@ body.setup-mode[data-theme="dark"] {
|
|
|
14267
14159
|
cursor: pointer;
|
|
14268
14160
|
color: var(--color-text-primary);
|
|
14269
14161
|
font-size: 0.8125rem;
|
|
14162
|
+
line-height: 1.4;
|
|
14270
14163
|
text-align: left;
|
|
14271
14164
|
transition: background .12s ease, color .12s ease;
|
|
14272
14165
|
}
|
|
14166
|
+
.project-actions-menu-icon {
|
|
14167
|
+
display: inline-flex;
|
|
14168
|
+
align-items: center;
|
|
14169
|
+
justify-content: center;
|
|
14170
|
+
width: 0.875rem;
|
|
14171
|
+
height: 0.875rem;
|
|
14172
|
+
flex: 0 0 0.875rem;
|
|
14173
|
+
color: var(--color-text-secondary);
|
|
14174
|
+
transition: color .12s ease;
|
|
14175
|
+
}
|
|
14176
|
+
.project-actions-menu-icon svg {
|
|
14177
|
+
display: block;
|
|
14178
|
+
flex-shrink: 0;
|
|
14179
|
+
}
|
|
14180
|
+
.project-actions-menu-label {
|
|
14181
|
+
min-width: 0;
|
|
14182
|
+
flex: 1;
|
|
14183
|
+
}
|
|
14273
14184
|
.project-actions-menu-item:hover {
|
|
14274
14185
|
background: var(--color-bg-hover);
|
|
14275
14186
|
}
|
|
14187
|
+
.project-actions-menu-item:hover .project-actions-menu-icon {
|
|
14188
|
+
color: var(--color-text-primary);
|
|
14189
|
+
}
|
|
14276
14190
|
.project-actions-menu-item.danger {
|
|
14277
14191
|
color: var(--color-error);
|
|
14278
14192
|
margin-top: 0.25rem;
|
|
14279
14193
|
position: relative;
|
|
14280
14194
|
}
|
|
14195
|
+
.project-actions-menu-item.danger .project-actions-menu-icon,
|
|
14196
|
+
.project-actions-menu-item.danger:hover .project-actions-menu-icon {
|
|
14197
|
+
color: var(--color-error);
|
|
14198
|
+
}
|
|
14281
14199
|
.project-actions-menu-item.danger::before {
|
|
14282
14200
|
content: "";
|
|
14283
14201
|
position: absolute;
|
|
@@ -14406,6 +14324,13 @@ body.setup-mode[data-theme="dark"] {
|
|
|
14406
14324
|
margin-top: 0.75rem;
|
|
14407
14325
|
}
|
|
14408
14326
|
|
|
14327
|
+
.create-project-folder-hint {
|
|
14328
|
+
font-size: 0.72rem;
|
|
14329
|
+
color: var(--color-text-muted);
|
|
14330
|
+
margin-top: 0.35rem;
|
|
14331
|
+
line-height: 1.4;
|
|
14332
|
+
}
|
|
14333
|
+
|
|
14409
14334
|
.create-project-folder-label {
|
|
14410
14335
|
font-size: 0.78rem;
|
|
14411
14336
|
font-weight: 500;
|
|
@@ -14603,4 +14528,3 @@ body.setup-mode[data-theme="dark"] {
|
|
|
14603
14528
|
.project-picker-done-btn:hover {
|
|
14604
14529
|
background: var(--color-bg-hover);
|
|
14605
14530
|
}
|
|
14606
|
-
|
|
@@ -163,7 +163,7 @@
|
|
|
163
163
|
popup.style.bottom = "";
|
|
164
164
|
const popupHeight = popup.offsetHeight;
|
|
165
165
|
let top = barCenter - popupHeight / 2;
|
|
166
|
-
top = Math.max(
|
|
166
|
+
top = Math.max(48, Math.min(top, navRect.height - popupHeight));
|
|
167
167
|
popup.style.top = top + "px";
|
|
168
168
|
|
|
169
169
|
const target = items[idx].popupItem;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
//
|
|
3
3
|
// Owns billing state (summary / daily / sessions / model list / current period
|
|
4
4
|
// & model filter), currency conversion utilities (localStorage-backed), the
|
|
5
|
-
// data fetch, and clear-data actions. It never renders.
|
|
5
|
+
// data fetch, and clear-data actions (retained for API use). It never renders.
|
|
6
6
|
//
|
|
7
7
|
// Currency utilities are pure and read by both the view and other modules, so
|
|
8
8
|
// they live with the data layer. Emits store events the view reacts to; mirrors
|
|
@@ -103,8 +103,8 @@ const BillingStore = (() => {
|
|
|
103
103
|
if (_summary) _emit("billing:changed");
|
|
104
104
|
},
|
|
105
105
|
|
|
106
|
-
setPeriod(period) { _currentPeriod = period; return Billing.load(); },
|
|
107
|
-
setModel(model) { _currentModel = model; return Billing.load(); },
|
|
106
|
+
setPeriod(period) { _currentPeriod = period; _emit("billing:changed"); return Billing.load(); },
|
|
107
|
+
setModel(model) { _currentModel = model; _emit("billing:changed"); return Billing.load(); },
|
|
108
108
|
|
|
109
109
|
async load() {
|
|
110
110
|
const isFirstLoad = !_summary;
|