@prajwalghate/sourcetruth 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,429 @@
1
+ /* sourcetruth — the map.
2
+ Two typefaces, and the split is a rule, not a style: MONOSPACE is anything copied from the source
3
+ (a contract, an action, a party, a line of code). SANS is the tool talking. A reader can always
4
+ tell which words are evidence and which are commentary. */
5
+
6
+ :root {
7
+ --ground: #edf0f3;
8
+ --surface: #ffffff;
9
+ --raised: #f6f7f9;
10
+ --ink: #15181d;
11
+ --muted: #5b6574;
12
+ --faint: #8a93a0;
13
+ --line: #d6dce3;
14
+ --line-strong: #b7c0cb;
15
+ --flow: #2f5bea;
16
+ --flow-soft: rgba(47, 91, 234, 0.11);
17
+ --make: #1c8549;
18
+ --make-soft: rgba(28, 133, 73, 0.12);
19
+ --end: #cc2f37;
20
+ --end-soft: rgba(204, 47, 55, 0.1);
21
+ --blind: #a86400;
22
+ --blind-soft: rgba(214, 138, 0, 0.15);
23
+ --power: #8a3fc7;
24
+ --power-soft: rgba(138, 63, 199, 0.11);
25
+ --dot: rgba(21, 24, 29, 0.085);
26
+ --scrim: rgba(12, 15, 20, 0.52);
27
+ --shadow: 0 1px 2px rgba(16, 24, 40, 0.06), 0 2px 6px rgba(16, 24, 40, 0.06);
28
+ --shadow-lift: 0 6px 22px rgba(16, 24, 40, 0.14);
29
+ --sans: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
30
+ --mono: ui-monospace, "SF Mono", SFMono-Regular, "JetBrains Mono", Menlo, Consolas, monospace;
31
+ color-scheme: light;
32
+ }
33
+ @media (prefers-color-scheme: dark) {
34
+ :root:not([data-theme="light"]) {
35
+ --ground: #0d1015; --surface: #151a21; --raised: #1b2129; --ink: #e7ebf0; --muted: #9aa4b2;
36
+ --faint: #6c7686; --line: #262e38; --line-strong: #3a4553;
37
+ --flow: #7ea1ff; --flow-soft: rgba(126, 161, 255, 0.15);
38
+ --make: #4fcb86; --make-soft: rgba(79, 203, 134, 0.13);
39
+ --end: #ff6e72; --end-soft: rgba(255, 110, 114, 0.12);
40
+ --blind: #ffb547; --blind-soft: rgba(255, 181, 71, 0.14);
41
+ --power: #c79dff; --power-soft: rgba(199, 157, 255, 0.14);
42
+ --dot: rgba(231, 235, 240, 0.065); --scrim: rgba(0, 0, 0, 0.6);
43
+ --shadow: 0 1px 2px rgba(0, 0, 0, 0.45); --shadow-lift: 0 8px 26px rgba(0, 0, 0, 0.55);
44
+ color-scheme: dark;
45
+ }
46
+ }
47
+ :root[data-theme="dark"] {
48
+ --ground: #0d1015; --surface: #151a21; --raised: #1b2129; --ink: #e7ebf0; --muted: #9aa4b2;
49
+ --faint: #6c7686; --line: #262e38; --line-strong: #3a4553;
50
+ --flow: #7ea1ff; --flow-soft: rgba(126, 161, 255, 0.15);
51
+ --make: #4fcb86; --make-soft: rgba(79, 203, 134, 0.13);
52
+ --end: #ff6e72; --end-soft: rgba(255, 110, 114, 0.12);
53
+ --blind: #ffb547; --blind-soft: rgba(255, 181, 71, 0.14);
54
+ --power: #c79dff; --power-soft: rgba(199, 157, 255, 0.14);
55
+ --dot: rgba(231, 235, 240, 0.065); --scrim: rgba(0, 0, 0, 0.6);
56
+ --shadow: 0 1px 2px rgba(0, 0, 0, 0.45); --shadow-lift: 0 8px 26px rgba(0, 0, 0, 0.55);
57
+ color-scheme: dark;
58
+ }
59
+
60
+ * { box-sizing: border-box; }
61
+ html, body { margin: 0; background: var(--ground); color: var(--ink); }
62
+ body { font: 14px/1.45 var(--sans); -webkit-font-smoothing: antialiased; }
63
+ button { font: inherit; color: inherit; }
64
+ .mono { font-family: var(--mono); font-size: 0.93em; letter-spacing: -0.01em; }
65
+ .muted { color: var(--muted); }
66
+ :focus-visible { outline: 2px solid var(--flow); outline-offset: 2px; }
67
+ svg.i { width: 15px; height: 15px; flex: none; stroke: currentColor; fill: none; stroke-width: 1.7;
68
+ stroke-linecap: round; stroke-linejoin: round; vertical-align: -3px; }
69
+ svg.i.solid { fill: currentColor; stroke: none; }
70
+
71
+ /* With JS the app owns the screen and the plain listing waits behind the Code tab. Without JS the
72
+ listing is simply the page. The script only ever hides. */
73
+ .js #code { display: none; }
74
+ .js.view-code #code { display: block; }
75
+ #app { display: none; }
76
+ .js #app { display: grid; }
77
+
78
+ /* ── shell ─────────────────────────────────────────────────────────────────────────────────────── */
79
+ .app {
80
+ position: fixed; inset: 0; grid-template-rows: 52px minmax(0, 1fr);
81
+ grid-template-columns: 232px minmax(0, 1fr) 392px;
82
+ grid-template-areas: "top top top" "people map inspect";
83
+ }
84
+ .view-code .app { bottom: auto; height: 52px; }
85
+ .view-code .app > :not(.top) { display: none !important; }
86
+ .view-code #code { padding-top: 52px; }
87
+
88
+ .top {
89
+ grid-area: top; display: flex; align-items: center; gap: 14px; padding: 0 14px;
90
+ background: var(--surface); border-bottom: 1px solid var(--line); min-width: 0; z-index: 20;
91
+ }
92
+ .brand { display: flex; align-items: center; gap: 8px; min-width: 0; }
93
+ .brand-mark { width: 22px; height: 22px; border-radius: 6px; background: var(--ink); color: var(--surface);
94
+ display: grid; place-items: center; flex: none; }
95
+ .brand-mark svg { width: 14px; height: 14px; }
96
+ .brand-name { font-weight: 650; letter-spacing: -0.01em; }
97
+ .brand-title { color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 30vw; }
98
+ .brand-title::before { content: "/"; margin-right: 8px; color: var(--line-strong); }
99
+
100
+ .tabs { display: flex; gap: 2px; background: var(--raised); border: 1px solid var(--line); border-radius: 9px;
101
+ padding: 2px; margin-left: 6px; }
102
+ .tab { border: 0; background: none; padding: 5px 13px; border-radius: 7px; cursor: pointer; color: var(--muted);
103
+ font-weight: 550; }
104
+ .tab:hover { color: var(--ink); }
105
+ .tab[aria-selected="true"] { background: var(--surface); color: var(--ink); box-shadow: var(--shadow); }
106
+
107
+ .top-right { margin-left: auto; display: flex; align-items: center; gap: 10px; min-width: 0; }
108
+ .counts { color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap; }
109
+ .counts b { color: var(--ink); font-weight: 600; }
110
+ .trace { display: flex; align-items: center; gap: 8px; white-space: nowrap; color: var(--muted);
111
+ font-variant-numeric: tabular-nums; }
112
+ .trace-bar { width: 84px; height: 7px; border-radius: 4px; background: var(--blind-soft); overflow: hidden;
113
+ border: 1px solid var(--line); }
114
+ .trace-bar > span { display: block; height: 100%; background: var(--ink); opacity: 0.78; }
115
+ .btn { display: inline-flex; align-items: center; gap: 6px; border: 1px solid var(--line); background: var(--surface);
116
+ border-radius: 8px; padding: 5px 11px; cursor: pointer; white-space: nowrap; font-weight: 550; }
117
+ .btn:hover { border-color: var(--line-strong); }
118
+ .btn.blind { color: var(--blind); border-color: color-mix(in srgb, var(--blind) 45%, var(--line)); background: var(--blind-soft); }
119
+ .btn.primary { background: var(--ink); color: var(--surface); border-color: var(--ink); }
120
+ .btn.primary:hover { opacity: 0.9; }
121
+ .btn.flow { background: var(--flow); color: #fff; border-color: var(--flow); }
122
+ .btn.ghost { background: none; }
123
+
124
+ /* ── people ────────────────────────────────────────────────────────────────────────────────────── */
125
+ .people { grid-area: people; background: var(--surface); border-right: 1px solid var(--line);
126
+ overflow-y: auto; padding: 14px 10px 24px; }
127
+ .label { font-size: 11px; font-weight: 650; letter-spacing: 0.07em; text-transform: uppercase; color: var(--faint);
128
+ margin: 0 6px 8px; display: flex; align-items: center; gap: 6px; }
129
+ .label + .label, .group + .label { margin-top: 18px; }
130
+ .group { display: flex; flex-direction: column; gap: 2px; }
131
+ .person { display: flex; align-items: center; gap: 9px; border: 0; background: none; text-align: left;
132
+ padding: 6px 8px; border-radius: 8px; cursor: pointer; width: 100%; min-width: 0; }
133
+ .person:hover { background: var(--raised); }
134
+ .person[aria-pressed="true"] { background: var(--flow-soft); }
135
+ .avatar { width: 24px; height: 24px; border-radius: 50%; display: grid; place-items: center; flex: none;
136
+ font: 600 11px/1 var(--mono); text-transform: uppercase; background: var(--raised); color: var(--muted);
137
+ border: 1px solid var(--line); }
138
+ .person.outside .avatar { background: var(--ink); color: var(--surface); border-color: var(--ink); }
139
+ .person.anyone .avatar { background: var(--power); border-color: var(--power); color: #fff; }
140
+ .person.unseen .avatar { background: var(--blind-soft); border: 1px dashed var(--blind); color: var(--blind); }
141
+ .person-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
142
+ .person-n { color: var(--faint); font-variant-numeric: tabular-nums; font-size: 12px; }
143
+ .pdot { width: 7px; height: 7px; border-radius: 50%; background: var(--power); flex: none; }
144
+
145
+ /* ── map ───────────────────────────────────────────────────────────────────────────────────────── */
146
+ .map { grid-area: map; position: relative; overflow: hidden; cursor: grab; touch-action: none;
147
+ background-color: var(--ground);
148
+ background-image: radial-gradient(var(--dot) 1.1px, transparent 1.2px); background-size: 22px 22px; }
149
+ .map.dragging { cursor: grabbing; }
150
+ .world { position: absolute; left: 0; top: 0; transform-origin: 0 0; will-change: transform; }
151
+ .world.glide { transition: transform 0.5s cubic-bezier(0.2, 0.7, 0.2, 1); }
152
+ .links, .fx { position: absolute; left: 0; top: 0; overflow: visible; pointer-events: none; }
153
+ .link { fill: none; stroke: var(--line-strong); stroke-width: 1.6; transition: stroke 0.2s, opacity 0.2s; }
154
+ .link.call { stroke-dasharray: 5 4; }
155
+ .link.lit { stroke: var(--flow); stroke-width: 2.2; }
156
+ .link.run-create { stroke: var(--make); stroke-width: 2.6; stroke-dasharray: 8 6; animation: march 0.6s linear infinite; }
157
+ .link.run-call { stroke: var(--flow); stroke-width: 2.6; stroke-dasharray: 8 6; animation: march 0.6s linear infinite; }
158
+ @keyframes march { to { stroke-dashoffset: -28; } }
159
+ .focus .link:not(.lit):not(.run-create):not(.run-call) { opacity: 0.18; }
160
+ .fx path { fill: none; stroke-width: 2.2; stroke-dasharray: 3 5; }
161
+ .fx .fx-read { stroke: var(--muted); }
162
+ .fx .fx-call { stroke: var(--flow); stroke-dasharray: 8 6; }
163
+ .arrow-head { fill: var(--line-strong); }
164
+
165
+ .card { position: absolute; width: 212px; height: 84px; display: flex; flex-direction: column; gap: 5px;
166
+ padding: 9px 11px 8px; text-align: left; background: var(--surface); border: 1px solid var(--line);
167
+ border-radius: 10px; box-shadow: var(--shadow); cursor: pointer;
168
+ transition: opacity 0.2s, border-color 0.2s, box-shadow 0.2s, transform 0.2s; }
169
+ .card:hover { border-color: var(--line-strong); box-shadow: var(--shadow-lift); }
170
+ .card-name { font: 600 13px/1.2 var(--mono); letter-spacing: -0.01em; white-space: nowrap; overflow: hidden;
171
+ text-overflow: ellipsis; }
172
+ .card-signers { display: flex; gap: 4px; overflow: hidden; min-height: 18px; }
173
+ .stamp { display: inline-flex; align-items: center; gap: 3px; padding: 0 6px; height: 18px; border-radius: 4px;
174
+ font: 500 11px/1 var(--mono); color: var(--muted); background: var(--raised); border: 1px solid var(--line);
175
+ white-space: nowrap; }
176
+ .stamp.borrowed { color: var(--power); background: var(--power-soft); border-color: color-mix(in srgb, var(--power) 40%, transparent); }
177
+ .card-foot { margin-top: auto; display: flex; align-items: center; gap: 8px; font-size: 11.5px; color: var(--faint); }
178
+ .card-kind { font-style: italic; }
179
+ .qbadge { display: inline-flex; align-items: center; gap: 3px; color: var(--blind); font-weight: 600; margin-left: auto; }
180
+ .card.ghost { background: transparent; border: 1.5px dashed var(--line-strong); box-shadow: none; }
181
+ .card.ghost .card-name { color: var(--muted); }
182
+ .standalone-label { position: absolute; font-size: 11px; font-weight: 650; letter-spacing: 0.07em;
183
+ text-transform: uppercase; color: var(--faint); }
184
+
185
+ .focus .card { opacity: 0.28; }
186
+ .focus .card.lit, .focus .card.on { opacity: 1; }
187
+ .card.on { border-color: var(--flow); box-shadow: 0 0 0 3px var(--flow-soft), var(--shadow-lift); }
188
+ .card.lit { border-color: color-mix(in srgb, var(--flow) 55%, var(--line)); }
189
+ .card.hit-create { border-color: var(--make); box-shadow: 0 0 0 4px var(--make-soft), var(--shadow-lift); }
190
+ .card.hit-destroy { border-color: var(--end); box-shadow: 0 0 0 4px var(--end-soft); }
191
+ .card.hit-destroy::after { content: ""; position: absolute; left: 8px; right: 8px; top: 50%; height: 2px;
192
+ background: var(--end); transform-origin: left; animation: strike 0.35s ease-out both; }
193
+ @keyframes strike { from { transform: scaleX(0); } to { transform: scaleX(1); } }
194
+ .card.hit-call { border-color: var(--flow); box-shadow: 0 0 0 4px var(--flow-soft); }
195
+ .card.hit-read { border-color: var(--muted); }
196
+ .card .hit-tag { position: absolute; top: -10px; right: 10px; display: inline-flex; align-items: center; gap: 3px;
197
+ padding: 1px 7px; border-radius: 999px; font-size: 11px; font-weight: 650; color: #fff; animation: pop 0.3s ease-out both; }
198
+ .hit-tag.create { background: var(--make); } .hit-tag.destroy { background: var(--end); }
199
+ .hit-tag.call { background: var(--flow); } .hit-tag.read { background: var(--muted); }
200
+ .hit-tag.blind { background: var(--blind); }
201
+ .hit-tag svg.i { width: 12px; height: 12px; stroke-width: 2.2; }
202
+ @keyframes pop { from { transform: scale(0.4); opacity: 0; } to { transform: scale(1); opacity: 1; } }
203
+
204
+ .token { position: absolute; display: inline-flex; align-items: center; gap: 6px; padding: 4px 10px 4px 5px;
205
+ border-radius: 999px; background: var(--ink); color: var(--surface); font: 600 12px/1 var(--mono);
206
+ box-shadow: var(--shadow-lift); white-space: nowrap; animation: arrive 0.45s cubic-bezier(0.2, 0.7, 0.2, 1) both; }
207
+ .token .avatar { width: 18px; height: 18px; font-size: 9.5px; background: var(--surface); color: var(--ink); border: 0; }
208
+ .token.anyone { background: var(--power); color: #fff; }
209
+ @keyframes arrive { from { transform: translateX(-60px); opacity: 0; } to { transform: none; opacity: 1; } }
210
+
211
+ .map-tools { position: absolute; right: 12px; bottom: 12px; display: flex; flex-direction: column; gap: 4px; z-index: 5; }
212
+ .map-tools .btn { padding: 6px; justify-content: center; box-shadow: var(--shadow); }
213
+ .legend { position: absolute; left: 12px; bottom: 12px; display: flex; gap: 14px; align-items: center; z-index: 5;
214
+ background: var(--surface); border: 1px solid var(--line); border-radius: 9px; padding: 6px 11px;
215
+ font-size: 12px; color: var(--muted); box-shadow: var(--shadow); }
216
+ .legend span { display: inline-flex; align-items: center; gap: 6px; }
217
+ .legend svg { width: 26px; height: 10px; overflow: visible; }
218
+ .lg-box { width: 16px; height: 11px; border: 1.5px dashed var(--line-strong); border-radius: 3px; }
219
+ .map-empty { position: absolute; inset: 0; display: grid; place-items: center; color: var(--muted); }
220
+
221
+ /* ── inspector ─────────────────────────────────────────────────────────────────────────────────── */
222
+ .inspect { grid-area: inspect; background: var(--surface); border-left: 1px solid var(--line); overflow-y: auto;
223
+ padding: 16px 16px 40px; }
224
+ .back { border: 0; background: none; color: var(--muted); display: inline-flex; align-items: center; gap: 4px;
225
+ padding: 2px 4px 2px 0; cursor: pointer; margin-bottom: 10px; font-weight: 550; }
226
+ .back:hover { color: var(--ink); }
227
+ .h { font-size: 16px; font-weight: 650; letter-spacing: -0.01em; margin: 0 0 3px; }
228
+ .h.big { font: 650 19px/1.25 var(--mono); letter-spacing: -0.02em; word-break: break-word; }
229
+ .sub { color: var(--muted); font-size: 13px; margin: 0 0 14px; }
230
+ .section { margin-top: 18px; }
231
+ .rows { display: flex; flex-direction: column; gap: 3px; }
232
+ .row { display: flex; align-items: center; gap: 9px; width: 100%; text-align: left; border: 1px solid transparent;
233
+ background: none; border-radius: 9px; padding: 7px 8px; cursor: pointer; min-width: 0; }
234
+ .row:hover { background: var(--raised); border-color: var(--line); }
235
+ .row.static { cursor: default; }
236
+ .row.static:hover { background: none; border-color: transparent; }
237
+ .row-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
238
+ .row-title { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
239
+ .row-sub { font-size: 12px; color: var(--muted); display: flex; flex-wrap: wrap; align-items: center; gap: 2px 4px; }
240
+ .row-marks { display: flex; align-items: center; gap: 5px; flex: none; }
241
+ .chip { display: inline-flex; align-items: center; gap: 5px; height: 22px; padding: 0 8px 0 3px; border-radius: 999px;
242
+ font: 550 12px/1 var(--mono); background: var(--raised); border: 1px solid var(--line); color: var(--ink);
243
+ white-space: nowrap; flex: none; }
244
+ .chip .avatar { width: 16px; height: 16px; font-size: 9px; }
245
+ .chip.outside { background: var(--ink); color: var(--surface); border-color: var(--ink); }
246
+ .chip.outside .avatar { background: var(--surface); color: var(--ink); border: 0; }
247
+ .chip.anyone { background: var(--power); border-color: var(--power); color: #fff; }
248
+ .chip.anyone .avatar { background: #fff; color: var(--power); border: 0; }
249
+ .chips { display: flex; flex-wrap: wrap; gap: 4px; }
250
+ .fx-icon { display: inline-flex; align-items: center; justify-content: center; width: 22px; height: 22px;
251
+ border-radius: 6px; flex: none; }
252
+ .fx-icon.create { color: var(--make); background: var(--make-soft); }
253
+ .fx-icon.destroy { color: var(--end); background: var(--end-soft); }
254
+ .fx-icon.call { color: var(--flow); background: var(--flow-soft); }
255
+ .fx-icon.read { color: var(--muted); background: var(--raised); }
256
+ .fx-icon.blind { color: var(--blind); background: var(--blind-soft); }
257
+ .fx-icon.none { color: var(--muted); background: var(--raised); }
258
+ .fx-icon.transition { color: var(--flow); background: var(--flow-soft); }
259
+ .fx-icon.terminal { color: var(--end); background: var(--end-soft); }
260
+ .effect { display: inline-flex; align-items: center; gap: 5px; font-size: 12.5px; font-weight: 600; }
261
+ .effect.none { color: var(--muted); } .effect.transition { color: var(--flow); } .effect.terminal { color: var(--end); }
262
+ .qmark { color: var(--blind); display: inline-flex; }
263
+ .power-mark { display: inline-flex; align-items: center; gap: 3px; color: var(--power); font-size: 11.5px; font-weight: 650; }
264
+
265
+ .trail { display: flex; flex-wrap: wrap; align-items: center; gap: 3px; margin: -4px 0 12px; font-size: 12px; }
266
+ .trail button { border: 0; background: var(--raised); border-radius: 6px; padding: 2px 7px; cursor: pointer;
267
+ color: var(--muted); font-family: var(--mono); font-size: 11.5px; max-width: 150px; overflow: hidden;
268
+ text-overflow: ellipsis; white-space: nowrap; }
269
+ .trail button:hover { color: var(--ink); }
270
+ .trail button[aria-current="step"] { background: var(--flow-soft); color: var(--flow); }
271
+ .trail .sep { color: var(--faint); }
272
+
273
+ .who-line { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin-bottom: 8px; }
274
+ .on-line { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: 6px 0 12px; color: var(--muted); }
275
+ .unit-link { border: 1px solid var(--line); background: var(--raised); border-radius: 7px; padding: 2px 8px;
276
+ cursor: pointer; font: 600 12.5px/1.5 var(--mono); color: var(--ink); }
277
+ .unit-link:hover { border-color: var(--flow); color: var(--flow); }
278
+ .strip { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; border-radius: 9px; padding: 8px 10px;
279
+ margin: 10px 0; font-size: 12.5px; }
280
+ .strip.power { background: var(--power-soft); color: var(--power); }
281
+ .strip.power .stamp { color: var(--power); border-color: color-mix(in srgb, var(--power) 40%, transparent); background: var(--surface); }
282
+ .strip.warn { background: var(--end-soft); color: var(--end); }
283
+ .strip.blind { background: var(--blind-soft); color: var(--blind); }
284
+ .actions-bar { display: flex; gap: 8px; margin: 12px 0 4px; }
285
+
286
+ .tx { position: relative; display: flex; flex-direction: column; gap: 2px; margin-top: 4px; }
287
+ .tx::before { content: ""; position: absolute; left: 18px; top: 10px; bottom: 10px; width: 1px; background: var(--line); }
288
+ .tx .row { position: relative; }
289
+ .tx .row.now { background: var(--flow-soft); border-color: color-mix(in srgb, var(--flow) 30%, transparent); }
290
+ .tx .row.pending { opacity: 0.45; }
291
+ .times { color: var(--faint); font-size: 11.5px; font-variant-numeric: tabular-nums; }
292
+ .thr { font-size: 11.5px; color: var(--faint); }
293
+ .thr .mono { color: var(--muted); }
294
+
295
+ details.fold { margin-top: 14px; border-top: 1px solid var(--line); padding-top: 10px; }
296
+ details.fold > summary { cursor: pointer; list-style: none; display: flex; align-items: center; gap: 6px;
297
+ font-size: 11px; font-weight: 650; letter-spacing: 0.07em; text-transform: uppercase; color: var(--faint); }
298
+ details.fold > summary::-webkit-details-marker { display: none; }
299
+ details.fold > summary svg { transition: transform 0.15s; }
300
+ details.fold[open] > summary svg { transform: rotate(90deg); }
301
+ .check { font: 12px/1.5 var(--mono); background: var(--raised); border-radius: 6px; padding: 5px 8px; margin: 5px 0 0;
302
+ white-space: pre-wrap; word-break: break-word; }
303
+ .code-snippet { font: 12px/1.55 var(--mono); background: var(--raised); border: 1px solid var(--line); border-radius: 8px;
304
+ padding: 9px 11px; margin: 8px 0 0; overflow: auto; max-height: 360px; white-space: pre; }
305
+
306
+ /* lifecycle */
307
+ .life { display: flex; flex-direction: column; margin-top: 8px; }
308
+ .stage { border: 1px solid var(--line); border-radius: 10px; padding: 9px 10px 8px; background: var(--surface); }
309
+ .stage-head { display: flex; align-items: center; gap: 7px; font-size: 11px; font-weight: 650; letter-spacing: 0.07em;
310
+ text-transform: uppercase; color: var(--faint); margin: 0 0 4px 2px; }
311
+ .stage.core { background: var(--raised); }
312
+ .stage .empty { color: var(--faint); font-size: 12.5px; padding: 3px 2px; }
313
+ .joint { display: flex; justify-content: center; height: 22px; position: relative; }
314
+ .joint::before { content: ""; width: 1.5px; background: var(--line-strong); }
315
+ .joint svg { position: absolute; top: 3px; width: 16px; height: 16px; background: var(--surface); border-radius: 50%; }
316
+
317
+ /* home */
318
+ .hero-q { font-size: 17px; font-weight: 650; letter-spacing: -0.015em; margin: 2px 0 4px; }
319
+ .door .row-title { font-weight: 600; }
320
+ .more { border: 0; background: none; color: var(--flow); cursor: pointer; padding: 6px 8px; font-weight: 600; }
321
+ .tour-card { margin-top: 22px; border: 1px solid var(--line); border-radius: 12px; padding: 12px; background: var(--raised);
322
+ display: flex; flex-direction: column; gap: 8px; }
323
+ .tour-card p { margin: 0; color: var(--muted); font-size: 13px; }
324
+ .tour-card .btns { display: flex; gap: 8px; flex-wrap: wrap; }
325
+
326
+ /* ── learn ─────────────────────────────────────────────────────────────────────────────────────── */
327
+ .learn { grid-row: 2 / -1; grid-column: 1 / -1; overflow-y: auto; background: var(--ground); padding: 26px 26px 60px; z-index: 6; }
328
+ .learn-head { max-width: 1180px; margin: 0 auto 18px; display: flex; align-items: flex-end; gap: 16px; flex-wrap: wrap; }
329
+ .learn-head h2 { margin: 0; font-size: 22px; letter-spacing: -0.02em; }
330
+ .learn-head p { margin: 0; color: var(--muted); }
331
+ .tiles { max-width: 1180px; margin: 0 auto; display: grid; grid-template-columns: repeat(auto-fill, minmax(262px, 1fr)); gap: 14px; }
332
+ .tile { background: var(--surface); border: 1px solid var(--line); border-radius: 14px; overflow: hidden;
333
+ display: flex; flex-direction: column; box-shadow: var(--shadow); }
334
+ .stage-art { height: 150px; flex-wrap: nowrap; background-color: var(--raised);
335
+ background-image: radial-gradient(var(--dot) 1px, transparent 1.1px); background-size: 16px 16px;
336
+ display: flex; align-items: center; justify-content: center; gap: 10px; position: relative; overflow: hidden;
337
+ border-bottom: 1px solid var(--line); padding: 0 12px; }
338
+ .tile-body { padding: 12px 14px 14px; display: flex; flex-direction: column; gap: 6px; flex: 1; }
339
+ .tile-title { font-weight: 650; font-size: 15px; letter-spacing: -0.01em; }
340
+ .tile-line { color: var(--muted); font-size: 13px; }
341
+ .tile-eg { margin-top: auto; padding-top: 6px; display: flex; align-items: center; gap: 6px; flex-wrap: wrap; font-size: 12px; color: var(--faint); }
342
+ .tile-eg button { border: 1px solid var(--line); background: var(--raised); border-radius: 6px; padding: 2px 7px;
343
+ font: 550 11.5px/1.5 var(--mono); cursor: pointer; color: var(--ink); max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
344
+ .tile-eg button:hover { border-color: var(--flow); color: var(--flow); }
345
+ .tile details { font-size: 12.5px; color: var(--muted); }
346
+ .tile details summary { cursor: pointer; color: var(--faint); font-weight: 600; font-size: 12px; }
347
+ .tile details p { margin: 5px 0 0; }
348
+
349
+ .mc { background: var(--surface); border: 1px solid var(--line); border-radius: 8px; padding: 6px 8px; min-width: 70px;
350
+ max-width: 118px; box-shadow: var(--shadow); display: flex; flex-direction: column; gap: 4px; position: relative; flex: none; }
351
+ .mc b { font: 600 11.5px/1.2 var(--mono); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
352
+ .mc .stamps { overflow: hidden; }
353
+ .art-col { display: flex; flex-direction: column; gap: 8px; align-items: flex-start; }
354
+ .art-row { display: flex; align-items: center; gap: 6px; }
355
+ .art-row.indent { padding-left: 28px; }
356
+ .mc .stamps { display: flex; gap: 3px; }
357
+ .mc .stamp { height: 15px; font-size: 9.5px; padding: 0 4px; }
358
+ .mc.ghost { background: transparent; border: 1.5px dashed var(--line-strong); box-shadow: none; }
359
+ .art-arrow { color: var(--faint); display: inline-flex; flex: none; }
360
+ .art-arrow svg { width: 17px; height: 17px; }
361
+ .art-note { position: absolute; bottom: 8px; left: 0; right: 0; text-align: center; font-size: 11px; color: var(--faint); }
362
+
363
+ @keyframes a-strike { 0%, 12% { opacity: 1; } 24%, 100% { opacity: 0.38; } }
364
+ @keyframes a-line { 0%, 12% { transform: scaleX(0); } 24%, 100% { transform: scaleX(1); } }
365
+ @keyframes a-in { 0%, 18% { opacity: 0; transform: translateX(-12px); } 30%, 100% { opacity: 1; transform: none; } }
366
+ @keyframes a-pop1 { 0%, 8% { opacity: 0; transform: scale(0.6); } 16%, 100% { opacity: 1; transform: none; } }
367
+ @keyframes a-pop2 { 0%, 20% { opacity: 0; transform: scale(0.6); } 28%, 100% { opacity: 1; transform: none; } }
368
+ @keyframes a-pop3 { 0%, 32% { opacity: 0; transform: scale(0.6); } 40%, 100% { opacity: 1; transform: none; } }
369
+ @keyframes a-glow { 0%, 20% { box-shadow: none; } 32%, 100% { box-shadow: 0 0 0 3px var(--power-soft); border-color: var(--power); } }
370
+ @keyframes a-pulse { 0%, 100% { opacity: 0.55; } 50% { opacity: 1; } }
371
+ .a-old { animation: a-strike 3.2s infinite; }
372
+ .a-old::after { content: ""; position: absolute; left: 6px; right: 6px; top: 50%; height: 1.5px; background: var(--end);
373
+ transform-origin: left; animation: a-line 3.2s infinite; }
374
+ .a-new { animation: a-in 3.2s infinite; }
375
+ .a-p1 { animation: a-pop1 3.2s infinite; } .a-p2 { animation: a-pop2 3.2s infinite; } .a-p3 { animation: a-pop3 3.2s infinite; }
376
+ .a-glow { animation: a-glow 3.2s infinite; }
377
+ .a-pulse { animation: a-pulse 2s infinite; }
378
+ .type-demo { display: flex; flex-direction: column; gap: 8px; align-items: flex-start; }
379
+ .type-demo .src { font: 600 13px/1.2 var(--mono); }
380
+ .type-demo .say { font: 500 13px/1.2 var(--sans); color: var(--muted); }
381
+
382
+ /* ── tour ──────────────────────────────────────────────────────────────────────────────────────── */
383
+ .tour { position: fixed; inset: 0; z-index: 50; pointer-events: none; }
384
+ .tour-hole { position: fixed; border-radius: 12px; box-shadow: 0 0 0 9999px var(--scrim); pointer-events: none;
385
+ transition: all 0.35s cubic-bezier(0.2, 0.7, 0.2, 1); outline: 2px solid var(--flow); outline-offset: 2px; }
386
+ .tour-tip { position: fixed; width: 290px; background: var(--surface); color: var(--ink); border-radius: 12px;
387
+ box-shadow: var(--shadow-lift); padding: 13px 14px 11px; pointer-events: auto; border: 1px solid var(--line);
388
+ transition: left 0.35s, top 0.35s; }
389
+ .tour-tip p { margin: 0 0 10px; font-size: 14px; font-weight: 550; }
390
+ .tour-actions { display: flex; align-items: center; gap: 8px; }
391
+ .tour-actions .n { color: var(--faint); font-size: 12px; font-variant-numeric: tabular-nums; margin-right: auto; }
392
+
393
+ /* ── code view: the plain listing, for look-up and for JS-off readers ──────────────────────────── */
394
+ #code { background: var(--ground); }
395
+ .js #code .code-top { display: none; }
396
+
397
+ @media (prefers-reduced-motion: reduce) {
398
+ *, *::before, *::after { animation-duration: 0.001s !important; animation-iteration-count: 1 !important;
399
+ transition-duration: 0.001s !important; }
400
+ }
401
+ /* Below 1200px a vertical people rail costs the map a third of its width, and a map drawn too small
402
+ to read shows nothing. The rail becomes a strip across the top instead. */
403
+ @media (max-width: 1200px) {
404
+ .app { grid-template-columns: minmax(0, 1fr) 340px; grid-template-rows: 52px auto minmax(0, 1fr);
405
+ grid-template-areas: "top top" "people inspect" "map inspect"; }
406
+ .people { border-right: 0; border-bottom: 1px solid var(--line); display: flex; align-items: center; gap: 2px;
407
+ overflow-x: auto; overflow-y: hidden; padding: 6px 8px; }
408
+ .people .label { margin: 0 4px 0 6px; flex: none; }
409
+ .people .label + .label, .people .group + .label { margin: 0 4px 0 16px; }
410
+ .people .group { flex-direction: row; gap: 2px; }
411
+ .person { width: auto; flex: none; padding: 4px 8px; }
412
+ .counts { display: none; }
413
+ }
414
+ @media (max-width: 880px) {
415
+ .app { grid-template-columns: minmax(0, 1fr); grid-template-rows: 52px auto minmax(0, 1fr) 44vh;
416
+ grid-template-areas: "top" "people" "map" "inspect"; }
417
+ .people .label { display: none; }
418
+ .inspect { border-left: 0; border-top: 1px solid var(--line); }
419
+ .trace, .brand-title { display: none; }
420
+ }
421
+ @media print {
422
+ .js #app { display: none; }
423
+ .js #code { display: block; padding-top: 0; }
424
+ }
425
+
426
+ [hidden] { display: none !important; }
427
+ .chip.optional { border-style: dashed; }
428
+ .person.expr .avatar, .chip.expr .avatar { font-family: var(--sans); font-style: italic; background: var(--raised); color: var(--muted); border: 1px dashed var(--line-strong); }
429
+ .chip.expr { font-weight: 500; }