kryptheon 0.1.19 → 0.1.21

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.
@@ -0,0 +1,446 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <meta name="kryptheon-token" content="%%TOKEN%%">
7
+ <title>Kryptheon</title>
8
+ <link rel="icon" href="/logo.png">
9
+ <style>
10
+ /* Sunset: a warm white ground that turns to peach towards the bottom, soft
11
+ raised surfaces with a warm shadow, and orange used for Kryptheon itself.
12
+ Meaning has its own colours - ember for broken, amber for "look at this",
13
+ leaf for held and fixed - so orange never has to mean "bad". Nothing is
14
+ loaded from anywhere else; the logo is served by this same server. */
15
+ :root {
16
+ --paper: #fffaf5;
17
+ --paper-2: #fcf1e7;
18
+ --paper-3: #f7e4d4;
19
+ --ink: #2d1e17;
20
+ --muted: #8a6d5e;
21
+ --faint: #b39889;
22
+ --sun: #ec7433;
23
+ --sun-soft: #f7a26c;
24
+ --sun-deep: #c6571f;
25
+ --gold: #d49b33;
26
+ --ember: #c2412d;
27
+ --amber: #a8720f;
28
+ --leaf: #3b8657;
29
+ --dusk: #6d4a7c;
30
+ --raised: 10px 12px 28px rgba(199, 118, 66, 0.20), -8px -8px 20px rgba(255, 255, 255, 0.95);
31
+ --raised-sm: 5px 6px 13px rgba(199, 118, 66, 0.20), -4px -4px 10px rgba(255, 255, 255, 0.9);
32
+ --sunken: inset 3px 4px 9px rgba(199, 118, 66, 0.18), inset -3px -3px 8px rgba(255, 255, 255, 0.85);
33
+ --display: "Baloo 2", "Nunito", ui-rounded, "Segoe UI Variable Display", "Segoe UI", system-ui, sans-serif;
34
+ --serif: "Cormorant Garamond", "Cormorant", "Palatino Linotype", Palatino, Georgia, serif;
35
+ --body: "Figtree", ui-sans-serif, "Segoe UI Variable Text", "Segoe UI", system-ui, sans-serif;
36
+ --mono: ui-monospace, "Cascadia Code", Consolas, monospace;
37
+ }
38
+ * { box-sizing: border-box; }
39
+ html { -webkit-text-size-adjust: 100%; }
40
+ body {
41
+ margin: 0; color: var(--ink); font: 14px/1.55 var(--body); min-height: 100vh;
42
+ background: #fdf1e6 linear-gradient(170deg, #fffbf7 0%, #fff3e8 38%, #fde3cf 78%, #f9d2b8 100%) fixed;
43
+ }
44
+ button { font: inherit; color: inherit; }
45
+ .shell { max-width: 1400px; margin: 0 auto; padding: 22px; display: grid; grid-template-columns: 250px minmax(0, 1fr); gap: 26px; align-items: start; }
46
+ @media (max-width: 900px) { .shell { grid-template-columns: minmax(0, 1fr); padding: 16px; gap: 18px; } }
47
+
48
+ /* Materials */
49
+ .raised { background: var(--paper); border-radius: 24px; box-shadow: var(--raised); }
50
+ .sunken { background: var(--paper-2); box-shadow: var(--sunken); }
51
+
52
+ /* The marker: what matters most in a sentence gets a sunset highlight. */
53
+ .hl { font-weight: 700; color: var(--ink); text-decoration: underline; text-decoration-color: rgba(236, 116, 51, 0.85); text-decoration-thickness: 3px; text-underline-offset: 4px; text-decoration-skip-ink: none; }
54
+ .ul { text-decoration: underline; text-decoration-color: var(--sun); text-decoration-thickness: 2px; text-underline-offset: 4px; font-weight: 700; }
55
+
56
+ /* Sidebar */
57
+ .side { position: sticky; top: 22px; padding: 20px 14px; display: flex; flex-direction: column; gap: 16px; min-height: calc(100vh - 44px); border-radius: 26px; }
58
+ @media (max-width: 900px) { .side { position: static; min-height: 0; } }
59
+ .brand { display: flex; align-items: center; gap: 12px; padding: 0 6px; }
60
+ .brand img { width: 50px; height: 50px; border-radius: 16px; background: #0b0b0b; box-shadow: 6px 7px 16px rgba(80, 40, 20, 0.35), -4px -4px 10px rgba(255, 255, 255, 0.9); flex: none; }
61
+ .wordmark { font-family: var(--serif); font-weight: 600; font-size: 19px; letter-spacing: 0.1em; line-height: 1; min-width: 0; }
62
+ .wordmark .dot { color: var(--gold); }
63
+ .wordmark small { display: block; font-family: var(--body); font-weight: 500; font-size: 11px; letter-spacing: 0.02em; color: var(--muted); margin-top: 6px; }
64
+ .nav-label { font-size: 10.5px; font-weight: 800; letter-spacing: 0.16em; color: var(--faint); padding: 0 12px; margin-bottom: 6px; }
65
+ .nav { display: grid; gap: 3px; }
66
+ .nav button { position: relative; display: flex; align-items: center; gap: 11px; width: 100%; border: 0; background: transparent; padding: 9px 12px; border-radius: 14px; cursor: pointer; font-weight: 600; color: var(--muted); text-align: left; transition: color 0.15s ease, background 0.15s ease; }
67
+ .nav button:hover { color: var(--ink); background: rgba(247, 162, 108, 0.12); }
68
+ .nav button.on { color: var(--sun-deep); background: var(--paper-2); box-shadow: var(--sunken); }
69
+ .nav button.on::before { content: ""; position: absolute; left: -14px; top: 9px; bottom: 9px; width: 4px; border-radius: 0 4px 4px 0; background: var(--sun); }
70
+ .nav .n-count { margin-left: auto; font-size: 11px; font-weight: 800; min-width: 22px; text-align: center; padding: 1px 7px; border-radius: 999px; background: var(--paper-3); color: var(--muted); }
71
+ .nav .n-count.hot { background: var(--ember); color: #fff; }
72
+ @media (max-width: 900px) { .nav { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); } .nav button.on::before { display: none; } }
73
+ .built { margin-top: auto; padding: 14px; border-radius: 18px; }
74
+ .built-top { display: flex; justify-content: space-between; font-size: 12px; font-weight: 600; color: var(--muted); }
75
+ .built-top b { color: var(--ink); font-family: var(--display); font-size: 15px; }
76
+ .meter { height: 11px; border-radius: 999px; margin-top: 10px; overflow: hidden; padding: 2px; }
77
+ .meter i { display: block; height: 100%; border-radius: 999px; background: linear-gradient(90deg, var(--gold), var(--sun)); }
78
+ .built p { margin: 8px 0 0; font-size: 11.5px; color: var(--muted); }
79
+ .account { display: flex; align-items: center; gap: 10px; padding: 10px; border-radius: 18px; }
80
+ .avatar { width: 38px; height: 38px; flex: none; border-radius: 50%; display: grid; place-items: center; font-family: var(--display); font-weight: 800; background: linear-gradient(135deg, #ffd9b8, #f7a26c); color: #5a2a10; box-shadow: var(--raised-sm); }
81
+ .account .a-name { font-weight: 700; font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
82
+ .account .a-sub { font-size: 11px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 160px; }
83
+
84
+ /* Topbar */
85
+ .top { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
86
+ .top h1 { margin: 0; font-family: var(--display); font-weight: 800; font-size: 30px; line-height: 1.05; letter-spacing: -0.015em; }
87
+ .top .sub { color: var(--muted); font-size: 13px; margin-top: 4px; display: flex; align-items: center; gap: 8px; }
88
+ .live-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--leaf); box-shadow: 0 0 0 4px rgba(59, 134, 87, 0.15); }
89
+ .top .grow { flex: 1; }
90
+ .search { display: flex; align-items: center; gap: 8px; padding: 10px 16px; border-radius: 999px; min-width: 240px; color: var(--muted); }
91
+ .search input { border: 0; background: transparent; outline: none; font: inherit; color: var(--ink); width: 100%; }
92
+ @media (max-width: 700px) { .search { display: none; } }
93
+ .bell { position: relative; width: 44px; height: 44px; border-radius: 50%; border: 0; display: grid; place-items: center; cursor: pointer; background: var(--paper); box-shadow: var(--raised-sm); color: var(--ink); }
94
+ .bell .bdot { position: absolute; top: 10px; right: 11px; width: 9px; height: 9px; border-radius: 50%; background: var(--ember); border: 2px solid var(--paper); }
95
+ .btn { display: inline-flex; align-items: center; gap: 8px; border: 0; border-radius: 999px; padding: 10px 18px; cursor: pointer; font-weight: 700; background: var(--paper); box-shadow: var(--raised-sm); transition: transform 0.12s ease, box-shadow 0.12s ease; white-space: nowrap; }
96
+ .btn:hover:not(:disabled) { transform: translateY(-1px); }
97
+ .btn:active:not(:disabled) { box-shadow: var(--sunken); transform: none; }
98
+ .btn:disabled { opacity: 0.6; cursor: default; }
99
+ .btn.sun { color: #fff; background: linear-gradient(135deg, #f6a064, #e5652b); box-shadow: 7px 8px 18px rgba(214, 96, 40, 0.38), -4px -4px 11px rgba(255, 255, 255, 0.85); }
100
+ .btn.sm { padding: 7px 14px; font-size: 12.5px; }
101
+ .spin { width: 13px; height: 13px; border-radius: 50%; border: 2px solid currentColor; border-right-color: transparent; animation: spin 0.8s linear infinite; }
102
+ @keyframes spin { to { transform: rotate(360deg); } }
103
+ @media (prefers-reduced-motion: reduce) { .spin { animation-duration: 3s; } .btn { transition: none; } }
104
+ button:focus-visible, input:focus-visible { outline: 2px solid var(--sun); outline-offset: 3px; }
105
+
106
+ /* Views: one section on screen at a time. */
107
+ .view { margin-top: 22px; }
108
+ .view[hidden] { display: none; }
109
+ .when { display: flex; align-items: center; gap: 10px; padding: 12px 18px; border-radius: 16px; font-size: 13.5px; color: var(--muted); margin-bottom: 20px; }
110
+ .when b.lbl { font-size: 10.5px; letter-spacing: 0.14em; color: var(--sun-deep); flex: none; }
111
+
112
+ /* The sky: the headline card. Its sun sinks and reddens when something is broken. */
113
+ .sky { position: relative; overflow: hidden; padding: 26px 28px; border-radius: 26px; display: flex; gap: 20px; align-items: center; flex-wrap: wrap; background: linear-gradient(115deg, #fffaf5 0%, #fff0e2 55%, #ffe0c8 100%); box-shadow: var(--raised); }
114
+ .sky::before { content: ""; position: absolute; width: 260px; height: 260px; right: 40px; bottom: -150px; border-radius: 50%; background: radial-gradient(circle, #ffe2a8 0%, #f9b163 45%, rgba(249, 177, 99, 0) 70%); opacity: 0.9; pointer-events: none; }
115
+ .sky::after { content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 46px; background: repeating-linear-gradient(0deg, rgba(255, 250, 245, 0.75) 0 3px, transparent 3px 11px); pointer-events: none; }
116
+ .sky.bad::before { background: radial-gradient(circle, #ffc38f 0%, #ef7a44 45%, rgba(214, 80, 45, 0) 72%); bottom: -170px; }
117
+ .sky.ok::before { background: radial-gradient(circle, #fff1c4 0%, #ffd27a 45%, rgba(255, 210, 122, 0) 70%); bottom: -110px; }
118
+ .sky > * { position: relative; z-index: 1; }
119
+ .sky .s-chip { width: 58px; height: 58px; border-radius: 18px; display: grid; place-items: center; background: var(--paper); box-shadow: var(--raised-sm); flex: none; }
120
+ .sky .s-text { flex: 1; min-width: 260px; }
121
+ .sky .eyebrow { font-size: 11px; font-weight: 800; letter-spacing: 0.16em; color: var(--sun-deep); }
122
+ .sky h2 { margin: 4px 0 0; font-family: var(--display); font-size: 28px; font-weight: 800; line-height: 1.1; }
123
+ .sky p { margin: 6px 0 0; color: var(--muted); max-width: 640px; }
124
+ .sky .s-actions { display: flex; gap: 10px; flex-wrap: wrap; }
125
+
126
+ /* KPI tiles - each one opens the section it counts. */
127
+ .kpis { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 18px; margin-top: 22px; }
128
+ @media (max-width: 1100px) { .kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
129
+ .kpi { padding: 18px; border-radius: 22px; border: 0; text-align: left; cursor: pointer; transition: transform 0.12s ease; width: 100%; }
130
+ .kpi:hover { transform: translateY(-2px); }
131
+ .kpi-top { display: flex; align-items: center; gap: 10px; }
132
+ .ichip { width: 38px; height: 38px; border-radius: 50%; display: grid; place-items: center; flex: none; }
133
+ .ichip.ember { background: rgba(194, 65, 45, 0.12); color: var(--ember); }
134
+ .ichip.amber { background: rgba(212, 155, 51, 0.18); color: var(--amber); }
135
+ .ichip.leaf { background: rgba(59, 134, 87, 0.13); color: var(--leaf); }
136
+ .ichip.sun { background: rgba(236, 116, 51, 0.14); color: var(--sun-deep); }
137
+ .kpi-label { font-size: 10.5px; font-weight: 800; letter-spacing: 0.13em; color: var(--muted); }
138
+ .kpi-num { font-family: var(--display); font-weight: 800; font-size: 34px; line-height: 1.1; margin-top: 12px; font-variant-numeric: tabular-nums; }
139
+ .kpi-foot { margin-top: 6px; min-height: 22px; display: flex; gap: 6px; flex-wrap: wrap; align-items: center; font-size: 12px; color: var(--muted); }
140
+ .kpi-go { margin-top: 10px; font-size: 12px; font-weight: 700; color: var(--sun-deep); }
141
+ .delta { display: inline-flex; align-items: center; gap: 4px; font-size: 11.5px; font-weight: 700; padding: 2px 9px; border-radius: 999px; background: var(--paper-2); box-shadow: var(--sunken); }
142
+ .delta.up { color: var(--leaf); } .delta.down { color: var(--ember); } .delta.flat { color: var(--muted); }
143
+
144
+ /* "Not sure where to look?" */
145
+ .guide { padding: 22px; border-radius: 24px; margin-top: 22px; }
146
+ .guide-list { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
147
+ @media (max-width: 1000px) { .guide-list { grid-template-columns: minmax(0, 1fr); } }
148
+ .g-row { display: grid; grid-template-columns: 12px minmax(0, 1fr) auto; gap: 12px; align-items: center; padding: 12px 14px; border: 0; border-radius: 16px; background: var(--paper-2); box-shadow: var(--sunken); cursor: pointer; text-align: left; font-size: 13.5px; color: var(--muted); }
149
+ .g-row:hover { background: #fff5ec; }
150
+ .g-row .g-dot { width: 10px; height: 10px; border-radius: 50%; background: var(--faint); }
151
+ .g-row .g-dot.hot { background: var(--ember); box-shadow: 0 0 0 4px rgba(194, 65, 45, 0.15); }
152
+ .g-row .g-dot.warm { background: var(--gold); }
153
+ .g-row .g-dot.cool { background: var(--leaf); }
154
+ .g-row .g-to { display: flex; align-items: center; gap: 6px; font-weight: 800; color: var(--sun-deep); white-space: nowrap; font-size: 12.5px; }
155
+ .g-row .g-state { display: block; font-size: 11.5px; color: var(--faint); margin-top: 2px; }
156
+
157
+ /* Cards */
158
+ .split { display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); gap: 18px; margin-top: 22px; }
159
+ @media (max-width: 1100px) { .split { grid-template-columns: minmax(0, 1fr); } }
160
+ .card { padding: 22px; border-radius: 24px; min-width: 0; }
161
+ .card + .card { margin-top: 18px; }
162
+ .split .card + .card { margin-top: 0; }
163
+ .card-head { display: flex; align-items: flex-start; gap: 12px; flex-wrap: wrap; margin-bottom: 16px; }
164
+ .card-head h3 { margin: 0; font-family: var(--display); font-size: 20px; font-weight: 800; line-height: 1.15; }
165
+ .card-head .c-sub { color: var(--muted); font-size: 12.5px; margin-top: 2px; }
166
+ .card-head .grow { flex: 1; }
167
+ .badge { font-size: 11.5px; font-weight: 800; padding: 3px 10px; border-radius: 999px; background: var(--paper-2); box-shadow: var(--sunken); color: var(--muted); }
168
+ .seg { display: inline-flex; padding: 4px; border-radius: 999px; gap: 2px; }
169
+ .seg button { border: 0; background: transparent; cursor: pointer; padding: 6px 14px; border-radius: 999px; font-size: 12.5px; font-weight: 700; color: var(--muted); }
170
+ .seg button.on { color: #fff; background: linear-gradient(135deg, #f6a064, #e5652b); box-shadow: inset 2px 2px 5px rgba(120, 40, 0, 0.25); }
171
+
172
+ /* Chart */
173
+ .chart-wrap { position: relative; }
174
+ .chart-wrap svg { display: block; width: 100%; height: 210px; overflow: visible; }
175
+ .tip { position: absolute; transform: translate(-50%, -100%); pointer-events: none; padding: 8px 12px; border-radius: 14px; background: var(--paper); box-shadow: var(--raised-sm); white-space: nowrap; font-size: 12px; }
176
+ .tip .t-date { color: var(--muted); font-weight: 600; font-size: 11px; }
177
+ .tip .t-val { display: flex; align-items: center; gap: 6px; font-family: var(--display); font-weight: 800; font-size: 16px; }
178
+ .tip .t-val i { width: 8px; height: 8px; border-radius: 50%; display: inline-block; }
179
+ .stem { position: absolute; width: 1px; background: rgba(45, 30, 23, 0.3); transform: translateX(-50%); pointer-events: none; }
180
+
181
+ /* Donut */
182
+ .donut { display: grid; place-items: center; position: relative; margin: 0 0 14px; }
183
+ .donut svg { width: 160px; height: 160px; }
184
+ .donut .center { position: absolute; text-align: center; }
185
+ .donut .center b { display: block; font-family: var(--display); font-size: 30px; font-weight: 800; line-height: 1; }
186
+ .donut .center span { font-size: 12px; color: var(--muted); }
187
+ .legend { display: grid; gap: 8px; }
188
+ .legend .row { display: flex; align-items: center; gap: 10px; font-weight: 600; }
189
+ .legend .row i { width: 11px; height: 11px; border-radius: 50%; display: inline-block; }
190
+ .legend .row .v { margin-left: auto; font-family: var(--display); font-weight: 800; }
191
+
192
+ /* Table */
193
+ .table-scroll { overflow-x: auto; margin: 0 -6px; padding: 6px; }
194
+ table { width: 100%; min-width: 880px; border-collapse: separate; border-spacing: 0 6px; font-size: 13px; }
195
+ thead th { text-align: left; font-size: 10.5px; font-weight: 800; letter-spacing: 0.1em; color: var(--muted); padding: 11px 14px; background: var(--paper-2); box-shadow: var(--sunken); }
196
+ thead th:first-child { border-radius: 999px 0 0 999px; }
197
+ thead th:last-child { border-radius: 0 999px 999px 0; }
198
+ tbody td { padding: 12px 14px; vertical-align: middle; }
199
+ tbody tr.row td { background: var(--paper); cursor: pointer; }
200
+ tbody tr.row td:first-child { border-radius: 16px 0 0 16px; }
201
+ tbody tr.row td:last-child { border-radius: 0 16px 16px 0; }
202
+ tbody tr.row.bad td:first-child { box-shadow: inset 4px 0 0 var(--ember); }
203
+ tbody tr.row.warn td:first-child { box-shadow: inset 4px 0 0 var(--gold); }
204
+ tbody tr.row:hover td { background: #fff3e8; }
205
+ .f-title { font-weight: 700; max-width: 360px; }
206
+ .f-id { font-family: var(--mono); font-size: 11px; color: var(--faint); }
207
+ .tag { display: inline-flex; align-items: center; gap: 6px; font-size: 11.5px; font-weight: 700; padding: 3px 10px; border-radius: 999px; background: var(--paper); box-shadow: var(--raised-sm); white-space: nowrap; color: var(--muted); }
208
+ .tag.ember { color: var(--ember); } .tag.amber { color: var(--amber); } .tag.leaf { color: var(--leaf); } .tag.sun { color: var(--sun-deep); } .tag.dusk { color: var(--dusk); }
209
+ .tag .g-dot { width: 7px; height: 7px; border-radius: 50%; background: currentColor; }
210
+ .tag .g-half { width: 9px; height: 9px; border-radius: 50%; border: 2px solid currentColor; background: linear-gradient(90deg, currentColor 50%, transparent 50%); }
211
+ .where { font-family: var(--mono); font-size: 11.5px; color: var(--muted); max-width: 240px; overflow-wrap: anywhere; }
212
+ .conf { display: flex; align-items: center; gap: 8px; font-weight: 700; font-size: 12px; }
213
+ .conf .meter { width: 64px; height: 9px; margin: 0; padding: 1.5px; }
214
+ tr.detail td { padding: 4px 14px 16px; }
215
+ .detail-box { border-radius: 18px; padding: 16px 18px; background: var(--paper-2); box-shadow: var(--sunken); }
216
+ .detail-box .d-step { font-size: 11px; font-weight: 800; letter-spacing: 0.12em; color: var(--sun-deep); margin-top: 14px; }
217
+ .detail-box .d-step:first-child { margin-top: 0; }
218
+ .detail-box .d-text { color: var(--muted); font-size: 13px; overflow-wrap: anywhere; margin-top: 4px; }
219
+ .detail-box pre { white-space: pre-wrap; overflow-wrap: anywhere; font: 12px/1.6 var(--mono); background: var(--paper); border-radius: 14px; padding: 14px; margin: 8px 0 0; box-shadow: var(--raised-sm); max-height: 340px; overflow: auto; }
220
+ .d-actions { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 12px; }
221
+ .attempts { margin-top: 10px; display: grid; gap: 6px; font-size: 12px; color: var(--muted); }
222
+ .attempts div { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
223
+ .empty { color: var(--muted); padding: 10px 4px; }
224
+
225
+ /* What changed */
226
+ .timeline { display: grid; gap: 0; max-width: 920px; }
227
+ .tl { display: grid; grid-template-columns: 22px minmax(0, 1fr); gap: 14px; position: relative; padding-bottom: 18px; }
228
+ .tl::before { content: ""; position: absolute; left: 10px; top: 20px; bottom: 0; width: 2px; background: var(--paper-3); }
229
+ .tl:last-child::before { display: none; }
230
+ .tl .knob { width: 22px; height: 22px; border-radius: 50%; margin-top: 1px; background: var(--faint); border: 5px solid var(--paper); box-shadow: var(--raised-sm); position: relative; z-index: 1; }
231
+ .tl .knob.bad { background: var(--ember); } .tl .knob.ok { background: var(--leaf); } .tl .knob.mid { background: var(--gold); }
232
+ .tl-head { font-weight: 700; }
233
+ .tl-meta { font-size: 12px; color: var(--muted); }
234
+ .tl-body { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
235
+ .tl-files { margin-top: 8px; font-family: var(--mono); font-size: 11.5px; color: var(--muted); display: grid; gap: 2px; overflow-wrap: anywhere; }
236
+ .more { margin-top: 4px; }
237
+
238
+ /* Checks */
239
+ .check-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px; }
240
+ @media (max-width: 1100px) { .check-grid { grid-template-columns: minmax(0, 1fr); } }
241
+ .check { padding: 18px; border-radius: 20px; display: flex; flex-direction: column; gap: 8px; }
242
+ .check .c-top { display: flex; align-items: center; gap: 12px; justify-content: space-between; }
243
+ .check .c-name { font-weight: 800; font-size: 15px; }
244
+ .check .c-what { font-size: 12.5px; color: var(--muted); }
245
+ .check .c-foot { margin-top: auto; padding-top: 6px; }
246
+ .na-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 10px; }
247
+ .na { display: flex; align-items: center; gap: 12px; padding: 11px 14px; border-radius: 14px; font-weight: 700; color: var(--muted); font-size: 13px; min-width: 0; }
248
+ .na .na-lock { display: block; font-size: 10px; font-weight: 800; letter-spacing: 0.1em; color: var(--faint); margin-top: 1px; }
249
+ .na .switch { opacity: 0.55; }
250
+ .switch { position: relative; width: 50px; height: 28px; flex: none; }
251
+ .switch input { position: absolute; inset: 0; opacity: 0; margin: 0; cursor: pointer; z-index: 1; }
252
+ .switch input:disabled { cursor: not-allowed; }
253
+ .switch .track { position: absolute; inset: 0; border-radius: 999px; background: var(--paper-2); box-shadow: var(--sunken); transition: background 0.2s ease; }
254
+ .switch .track::after { content: ""; position: absolute; width: 20px; height: 20px; left: 4px; top: 4px; border-radius: 50%; background: var(--paper); box-shadow: 2px 3px 6px rgba(160, 90, 50, 0.35), -2px -2px 5px rgba(255, 255, 255, 0.9); transition: transform 0.2s ease; }
255
+ .switch input:checked + .track { background: linear-gradient(135deg, #f6a064, #e5652b); }
256
+ .switch input:checked + .track::after { transform: translateX(22px); }
257
+
258
+ /* Lists */
259
+ .fix-row { display: flex; gap: 12px; align-items: center; padding: 12px 0; flex-wrap: wrap; }
260
+ .fix-row + .fix-row { border-top: 1px solid rgba(138, 109, 94, 0.15); }
261
+ .fix-row .fr-text { flex: 1; min-width: 200px; }
262
+ .fix-row .fr-sub { font-size: 12px; color: var(--muted); font-family: var(--mono); overflow-wrap: anywhere; }
263
+ .note { color: var(--muted); font-size: 13px; overflow-wrap: anywhere; max-width: 780px; }
264
+ .path { font-family: var(--mono); font-size: 12.5px; padding: 12px 14px; border-radius: 14px; overflow-wrap: anywhere; margin-top: 10px; }
265
+ .states { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 12px; margin-top: 16px; }
266
+ .state-card { padding: 14px 16px; border-radius: 16px; }
267
+ .state-card b { display: block; font-size: 13.5px; }
268
+ .state-card span { font-size: 12px; color: var(--muted); }
269
+ .files { display: grid; gap: 8px; margin-top: 14px; }
270
+ .files div { display: grid; grid-template-columns: 170px minmax(0, 1fr); gap: 12px; font-size: 12.5px; }
271
+ .files code { font-family: var(--mono); color: var(--ink); }
272
+ .files span { color: var(--muted); }
273
+ @media (max-width: 600px) { .files div { grid-template-columns: minmax(0, 1fr); gap: 0; } }
274
+ .error { color: var(--ember); font-size: 12.5px; margin-top: 10px; }
275
+ .toast { position: fixed; left: 50%; bottom: 22px; transform: translate(-50%, 24px); opacity: 0; padding: 12px 18px; border-radius: 16px; background: var(--paper); box-shadow: var(--raised); font-weight: 600; transition: all 0.25s ease; pointer-events: none; z-index: 10; max-width: calc(100vw - 32px); }
276
+ .toast.show { opacity: 1; transform: translate(-50%, 0); }
277
+ </style>
278
+ </head>
279
+ <body>
280
+ <div class="shell">
281
+ <aside class="side raised">
282
+ <div class="brand">
283
+ <img src="/logo.png" alt="Kryptheon logo" width="50" height="50">
284
+ <div class="wordmark">KRYPTHEON<span class="dot">.</span><small>checks what your AI built</small></div>
285
+ </div>
286
+ <div>
287
+ <div class="nav-label">OVERVIEW</div>
288
+ <nav class="nav" id="navOverview"></nav>
289
+ </div>
290
+ <div>
291
+ <div class="nav-label">WORKSPACE</div>
292
+ <nav class="nav" id="navWorkspace"></nav>
293
+ </div>
294
+ <div class="built raised">
295
+ <div class="built-top"><span>Checks built</span><b id="builtText">-</b></div>
296
+ <div class="meter sunken"><i id="builtBar" style="width:0%"></i></div>
297
+ <p id="builtNote"></p>
298
+ </div>
299
+ <div class="account sunken">
300
+ <div class="avatar" id="avatar">K</div>
301
+ <div style="min-width:0">
302
+ <div class="a-name" id="projName">Project</div>
303
+ <div class="a-sub" id="projPath"></div>
304
+ </div>
305
+ </div>
306
+ </aside>
307
+
308
+ <main>
309
+ <div class="top">
310
+ <div>
311
+ <h1 id="viewTitle">Dashboard</h1>
312
+ <div class="sub"><span class="live-dot"></span><span id="subline">Watching for changes</span></div>
313
+ </div>
314
+ <div class="grow"></div>
315
+ <label class="search sunken">
316
+ <span id="searchIcon"></span>
317
+ <input id="search" type="search" placeholder="Search findings" aria-label="Search findings">
318
+ </label>
319
+ <button class="bell" id="bell" type="button" aria-label="What changed in the last look"></button>
320
+ <button class="btn sun" id="runAll" type="button" data-action="run"></button>
321
+ </div>
322
+
323
+ <section class="view" id="view-dashboard">
324
+ <div class="sky" id="sky">
325
+ <div class="s-chip" id="skyIcon"></div>
326
+ <div class="s-text">
327
+ <div class="eyebrow" id="skyEyebrow">RIGHT NOW</div>
328
+ <h2 id="skyTitle">Reading your project...</h2>
329
+ <p id="skySub"></p>
330
+ </div>
331
+ <div class="s-actions" id="skyActions"></div>
332
+ </div>
333
+ <div class="kpis" id="kpis"></div>
334
+ <div class="guide raised">
335
+ <div class="card-head">
336
+ <div>
337
+ <h3>Not sure where to look?</h3>
338
+ <div class="c-sub">Find your problem on the left - the section to open is on the right</div>
339
+ </div>
340
+ </div>
341
+ <div class="guide-list" id="guide"></div>
342
+ </div>
343
+ <div class="split">
344
+ <div class="card raised">
345
+ <div class="card-head">
346
+ <div>
347
+ <h3>Recorded flows over time</h3>
348
+ <div class="c-sub" id="chartSub">Each run: recordings that held</div>
349
+ </div>
350
+ <div class="grow"></div>
351
+ <div class="seg sunken" id="range"></div>
352
+ </div>
353
+ <div class="chart-wrap" id="chart"></div>
354
+ </div>
355
+ <div class="card raised">
356
+ <div class="card-head">
357
+ <div>
358
+ <h3>Open findings</h3>
359
+ <div class="c-sub">By the check that found them</div>
360
+ </div>
361
+ </div>
362
+ <div class="donut" id="donut"></div>
363
+ <div class="legend" id="legend"></div>
364
+ </div>
365
+ </div>
366
+ </section>
367
+
368
+ <section class="view" id="view-findings" hidden>
369
+ <div class="when sunken" id="when-findings"></div>
370
+ <div class="card raised">
371
+ <div class="card-head">
372
+ <div>
373
+ <h3>Findings</h3>
374
+ <div class="c-sub">Click a row: what is wrong, the fix prompt, then Re-check</div>
375
+ </div>
376
+ <span class="badge" id="findingBadge">0</span>
377
+ <div class="grow"></div>
378
+ <div class="seg sunken" id="statusFilter"></div>
379
+ </div>
380
+ <div class="table-scroll">
381
+ <table>
382
+ <thead><tr><th>Finding</th><th>Check</th><th>Status</th><th>Severity</th><th>Where</th><th>Confidence</th></tr></thead>
383
+ <tbody id="findingRows"></tbody>
384
+ </table>
385
+ </div>
386
+ </div>
387
+ </section>
388
+
389
+ <section class="view" id="view-changes" hidden>
390
+ <div class="when sunken" id="when-changes"></div>
391
+ <div class="card raised">
392
+ <div class="card-head"><div><h3>What changed</h3><div class="c-sub">Every look Kryptheon took, newest first</div></div><span class="badge" id="lookBadge">0</span></div>
393
+ <div class="timeline" id="timeline"></div>
394
+ </div>
395
+ </section>
396
+
397
+ <section class="view" id="view-fixes" hidden>
398
+ <div class="when sunken" id="when-fixes"></div>
399
+ <div class="card raised">
400
+ <div class="card-head"><div><h3>Proven fixes</h3><div class="c-sub">Fixed only when a re-check said so</div></div><span class="badge" id="fixBadge">0</span></div>
401
+ <div id="fixList"></div>
402
+ </div>
403
+ </section>
404
+
405
+ <section class="view" id="view-checks" hidden>
406
+ <div class="when sunken" id="when-checks"></div>
407
+ <div class="check-grid" id="checkList"></div>
408
+ <p class="error" id="checkError" hidden></p>
409
+ <div class="card raised" style="margin-top:18px">
410
+ <div class="card-head"><div><h3>Not built yet</h3><div class="c-sub">Listed so you know they exist - never shown as passed</div></div><span class="badge" id="naBadge">0</span></div>
411
+ <div class="na-grid" id="naList"></div>
412
+ </div>
413
+ </section>
414
+
415
+ <section class="view" id="view-runs" hidden>
416
+ <div class="when sunken" id="when-runs"></div>
417
+ <div class="card raised">
418
+ <div class="card-head"><div><h3>Runs</h3><div class="c-sub">Your recorded flows, replayed against your app</div></div><span class="badge" id="runBadge">0</span></div>
419
+ <div id="runList"></div>
420
+ </div>
421
+ </section>
422
+
423
+ <section class="view" id="view-verification" hidden>
424
+ <div class="when sunken" id="when-verification"></div>
425
+ <div class="card raised">
426
+ <div class="card-head"><div><h3>Kryptheon Verified</h3><div class="c-sub">A badge that stands for one version of your project</div></div><span class="badge" id="verifyBadge">not verified</span></div>
427
+ <p class="note" id="verifyText"></p>
428
+ <div class="states" id="verifyStates"></div>
429
+ </div>
430
+ </section>
431
+
432
+ <section class="view" id="view-storage" hidden>
433
+ <div class="when sunken" id="when-storage"></div>
434
+ <div class="card raised">
435
+ <div class="card-head"><div><h3>Where this lives</h3><div class="c-sub">On this machine, outside your project</div></div></div>
436
+ <p class="note" id="storeNote"></p>
437
+ <div class="path sunken" id="storePath"></div>
438
+ <div class="files" id="storeFiles"></div>
439
+ </div>
440
+ </section>
441
+ </main>
442
+ </div>
443
+ <div class="toast" id="toast" role="status" aria-live="polite"></div>
444
+ <script src="/dashboard.js"></script>
445
+ </body>
446
+ </html>