@nocturnium/svelte-ide 1.0.4 → 1.0.6

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.
Files changed (27) hide show
  1. package/dist/components/ai/AIPanel.svelte +6 -1
  2. package/dist/components/ai/AIToolCallDisplay.svelte +1 -1
  3. package/dist/components/core/Avatar.svelte +14 -14
  4. package/dist/components/core/Badge.svelte +2 -2
  5. package/dist/components/core/Button.svelte +2 -2
  6. package/dist/components/editor/AIFocusLayer.svelte +3 -3
  7. package/dist/components/editor/CognitiveLoadMeter.svelte +15 -15
  8. package/dist/components/editor/CommandPalette.svelte +17 -17
  9. package/dist/components/editor/ComplexityLayer.svelte +11 -9
  10. package/dist/components/editor/ConflictZoneLayer.svelte +8 -8
  11. package/dist/components/editor/CustomEditor.svelte +34 -12
  12. package/dist/components/editor/CustomEditor.svelte.d.ts +5 -1
  13. package/dist/components/editor/FileIcon.svelte +2 -1
  14. package/dist/components/editor/GitBlameLayer.svelte +8 -8
  15. package/dist/components/editor/InlineDiffLayer.svelte +12 -12
  16. package/dist/components/editor/PluginPreviewSandbox.svelte +21 -21
  17. package/dist/components/editor/SnippetPalette.svelte +21 -21
  18. package/dist/components/editor/StructureMap.svelte +47 -30
  19. package/dist/components/editor/TimelineScrubber.svelte +11 -11
  20. package/dist/components/editor/core/complexity-analyzer.d.ts +4 -0
  21. package/dist/components/editor/core/complexity-analyzer.js +70 -12
  22. package/dist/components/editor/core/diagnostics.js +4 -4
  23. package/dist/components/editor/core/semantic-analyzer.js +13 -1
  24. package/dist/components/editor/core/structure-layout.d.ts +31 -0
  25. package/dist/components/editor/core/structure-layout.js +64 -0
  26. package/dist/styles/theme.css +24 -0
  27. package/package.json +1 -1
@@ -48,13 +48,13 @@
48
48
  function getColor(type: DiffLine['type']): string {
49
49
  switch (type) {
50
50
  case 'added':
51
- return '#22c55e'; // green
51
+ return 'var(--ide-status-created)';
52
52
  case 'modified':
53
- return '#3b82f6'; // blue
53
+ return 'var(--ide-status-modified)';
54
54
  case 'removed':
55
- return '#ef4444'; // red
55
+ return 'var(--ide-status-deleted)';
56
56
  default:
57
- return '#6b7280';
57
+ return 'var(--ide-text-muted)';
58
58
  }
59
59
  }
60
60
 
@@ -283,7 +283,7 @@
283
283
  left: 0;
284
284
  width: 0;
285
285
  height: 0;
286
- border-left: 8px solid #ef4444;
286
+ border-left: 8px solid var(--ide-status-deleted, #ef4444);
287
287
  border-top: 4px solid transparent;
288
288
  border-bottom: 4px solid transparent;
289
289
  pointer-events: auto;
@@ -291,7 +291,7 @@
291
291
  }
292
292
 
293
293
  .diff-removed-marker:hover {
294
- border-left-color: #f87171;
294
+ border-left-color: var(--ide-error, #ef4444);
295
295
  }
296
296
 
297
297
  /* Tooltip */
@@ -301,8 +301,8 @@
301
301
  min-width: 200px;
302
302
  max-width: 400px;
303
303
  padding: 10px;
304
- background: var(--color-surface, #1e1e2e);
305
- border: 1px solid var(--color-border, #333);
304
+ background: var(--ide-bg-secondary, #1a2744);
305
+ border: 1px solid var(--ide-border, #a8c5d9);
306
306
  border-radius: 6px;
307
307
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
308
308
  font-size: 12px;
@@ -324,7 +324,7 @@
324
324
  .tooltip-label {
325
325
  display: block;
326
326
  font-size: 10px;
327
- color: var(--color-text-muted, #888);
327
+ color: var(--ide-text-muted, #a8c5d9);
328
328
  margin-bottom: 4px;
329
329
  }
330
330
 
@@ -332,15 +332,15 @@
332
332
  margin: 0;
333
333
  font-family: 'JetBrains Mono', monospace;
334
334
  font-size: 11px;
335
- color: var(--color-text-secondary, #aaa);
335
+ color: var(--ide-text-secondary, #a8c5d9);
336
336
  white-space: pre-wrap;
337
337
  word-break: break-all;
338
338
  }
339
339
 
340
340
  .tooltip-hint {
341
341
  font-size: 10px;
342
- color: var(--color-text-muted, #888);
343
- border-top: 1px solid var(--color-border, #333);
342
+ color: var(--ide-text-muted, #a8c5d9);
343
+ border-top: 1px solid var(--ide-border, #a8c5d9);
344
344
  padding-top: 8px;
345
345
  }
346
346
  </style>
@@ -405,8 +405,8 @@
405
405
  width: 90vw;
406
406
  max-width: 1200px;
407
407
  height: 80vh;
408
- background: var(--color-surface, #1e1e2e);
409
- border: 1px solid var(--color-border, #333);
408
+ background: var(--ide-bg-secondary, #1a2744);
409
+ border: 1px solid var(--ide-border, #a8c5d9);
410
410
  border-radius: 12px;
411
411
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5);
412
412
  display: flex;
@@ -419,14 +419,14 @@
419
419
  align-items: center;
420
420
  justify-content: space-between;
421
421
  padding: 12px 16px;
422
- border-bottom: 1px solid var(--color-border, #333);
422
+ border-bottom: 1px solid var(--ide-border, #a8c5d9);
423
423
  }
424
424
 
425
425
  .plugin-sandbox__title {
426
426
  margin: 0;
427
427
  font-size: 16px;
428
428
  font-weight: 600;
429
- color: var(--color-text, #e8e8f0);
429
+ color: var(--ide-text-primary, #f4f1e0);
430
430
  }
431
431
 
432
432
  .plugin-sandbox__actions {
@@ -447,14 +447,14 @@
447
447
  background: transparent;
448
448
  border: none;
449
449
  border-radius: 4px;
450
- color: var(--color-text-secondary, #aaa);
450
+ color: var(--ide-text-secondary, #a8c5d9);
451
451
  font-size: 12px;
452
452
  cursor: pointer;
453
453
  transition: all 0.15s ease;
454
454
  }
455
455
 
456
456
  .mode-btn:hover {
457
- color: var(--color-text, #e8e8f0);
457
+ color: var(--ide-text-primary, #f4f1e0);
458
458
  }
459
459
 
460
460
  .mode-btn.active {
@@ -486,7 +486,7 @@
486
486
  /* Plugin sidebar */
487
487
  .plugin-sidebar {
488
488
  width: 240px;
489
- border-right: 1px solid var(--color-border, #333);
489
+ border-right: 1px solid var(--ide-border, #a8c5d9);
490
490
  padding: 12px;
491
491
  overflow-y: auto;
492
492
  }
@@ -495,7 +495,7 @@
495
495
  margin: 0 0 12px;
496
496
  font-size: 12px;
497
497
  font-weight: 600;
498
- color: var(--color-text-secondary, #aaa);
498
+ color: var(--ide-text-secondary, #a8c5d9);
499
499
  text-transform: uppercase;
500
500
  }
501
501
 
@@ -520,7 +520,7 @@
520
520
 
521
521
  .plugin-item:hover {
522
522
  background: rgba(255, 255, 255, 0.05);
523
- border-color: var(--color-border, #333);
523
+ border-color: var(--ide-border, #a8c5d9);
524
524
  }
525
525
 
526
526
  .plugin-item--selected {
@@ -555,12 +555,12 @@
555
555
  .plugin-item__name {
556
556
  font-size: 13px;
557
557
  font-weight: 500;
558
- color: var(--color-text, #e8e8f0);
558
+ color: var(--ide-text-primary, #f4f1e0);
559
559
  }
560
560
 
561
561
  .plugin-item__desc {
562
562
  font-size: 11px;
563
- color: var(--color-text-muted, #888);
563
+ color: var(--ide-text-muted, #a8c5d9);
564
564
  }
565
565
 
566
566
  /* Preview area */
@@ -577,7 +577,7 @@
577
577
  justify-content: center;
578
578
  gap: 8px;
579
579
  height: 100%;
580
- color: var(--color-text-secondary, #aaa);
580
+ color: var(--ide-text-secondary, #a8c5d9);
581
581
  }
582
582
 
583
583
  .loading-spinner {
@@ -601,7 +601,7 @@
601
601
  gap: 12px;
602
602
  padding: 8px 12px;
603
603
  background: rgba(255, 255, 255, 0.03);
604
- border-bottom: 1px solid var(--color-border, #333);
604
+ border-bottom: 1px solid var(--ide-border, #a8c5d9);
605
605
  font-size: 12px;
606
606
  }
607
607
 
@@ -633,7 +633,7 @@
633
633
  }
634
634
 
635
635
  .transform-time {
636
- color: var(--color-text-muted, #888);
636
+ color: var(--ide-text-muted, #a8c5d9);
637
637
  }
638
638
 
639
639
  .transform-error {
@@ -663,7 +663,7 @@
663
663
  background: rgba(255, 255, 255, 0.1);
664
664
  border: none;
665
665
  border-radius: 4px;
666
- color: var(--color-text-secondary, #aaa);
666
+ color: var(--ide-text-secondary, #a8c5d9);
667
667
  font-size: 12px;
668
668
  cursor: pointer;
669
669
  transition: all 0.15s ease;
@@ -685,13 +685,13 @@
685
685
  align-items: center;
686
686
  justify-content: center;
687
687
  height: 100%;
688
- color: var(--color-text-secondary, #aaa);
688
+ color: var(--ide-text-secondary, #a8c5d9);
689
689
  text-align: center;
690
690
  }
691
691
 
692
692
  .preview-hint {
693
693
  font-size: 12px;
694
- color: var(--color-text-muted, #888);
694
+ color: var(--ide-text-muted, #a8c5d9);
695
695
  margin-top: 8px;
696
696
  }
697
697
 
@@ -703,7 +703,7 @@
703
703
  font-family: 'JetBrains Mono', 'Fira Code', monospace;
704
704
  font-size: 13px;
705
705
  line-height: 1.5;
706
- color: var(--color-text, #e8e8f0);
706
+ color: var(--ide-text-primary, #f4f1e0);
707
707
  overflow: auto;
708
708
  white-space: pre;
709
709
  }
@@ -728,7 +728,7 @@
728
728
  border-radius: 6px 6px 0 0;
729
729
  font-size: 11px;
730
730
  font-weight: 600;
731
- color: var(--color-text-secondary, #aaa);
731
+ color: var(--ide-text-secondary, #a8c5d9);
732
732
  text-transform: uppercase;
733
733
  }
734
734
 
@@ -759,7 +759,7 @@
759
759
 
760
760
  .diff-line__num {
761
761
  width: 40px;
762
- color: var(--color-text-muted, #888);
762
+ color: var(--ide-text-muted, #a8c5d9);
763
763
  text-align: right;
764
764
  padding-right: 8px;
765
765
  user-select: none;
@@ -767,7 +767,7 @@
767
767
 
768
768
  .diff-line__sign {
769
769
  width: 16px;
770
- color: var(--color-text-muted, #888);
770
+ color: var(--ide-text-muted, #a8c5d9);
771
771
  }
772
772
 
773
773
  .diff-line--add .diff-line__sign {
@@ -283,8 +283,8 @@
283
283
  max-width: 800px;
284
284
  height: 70vh;
285
285
  max-height: 600px;
286
- background: var(--color-surface, #1e1e2e);
287
- border: 1px solid var(--color-border, #333);
286
+ background: var(--ide-bg-secondary, #1a2744);
287
+ border: 1px solid var(--ide-border, #a8c5d9);
288
288
  border-radius: 12px;
289
289
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5);
290
290
  display: flex;
@@ -298,16 +298,16 @@
298
298
  align-items: center;
299
299
  gap: 12px;
300
300
  padding: 12px 16px;
301
- border-bottom: 1px solid var(--color-border, #333);
301
+ border-bottom: 1px solid var(--ide-border, #a8c5d9);
302
302
  }
303
303
 
304
304
  .snippet-search {
305
305
  flex: 1;
306
306
  padding: 8px 12px;
307
307
  background: rgba(0, 0, 0, 0.2);
308
- border: 1px solid var(--color-border, #333);
308
+ border: 1px solid var(--ide-border, #a8c5d9);
309
309
  border-radius: 6px;
310
- color: var(--color-text, #e8e8f0);
310
+ color: var(--ide-text-primary, #f4f1e0);
311
311
  font-size: 14px;
312
312
  outline: none;
313
313
  }
@@ -318,7 +318,7 @@
318
318
 
319
319
  .snippet-hint {
320
320
  font-size: 11px;
321
- color: var(--color-text-muted, #888);
321
+ color: var(--ide-text-muted, #a8c5d9);
322
322
  white-space: nowrap;
323
323
  }
324
324
 
@@ -326,7 +326,7 @@
326
326
  display: flex;
327
327
  gap: 4px;
328
328
  padding: 8px 16px;
329
- border-bottom: 1px solid var(--color-border, #333);
329
+ border-bottom: 1px solid var(--ide-border, #a8c5d9);
330
330
  overflow-x: auto;
331
331
  }
332
332
 
@@ -335,7 +335,7 @@
335
335
  background: transparent;
336
336
  border: none;
337
337
  border-radius: 4px;
338
- color: var(--color-text-secondary, #aaa);
338
+ color: var(--ide-text-secondary, #a8c5d9);
339
339
  font-size: 12px;
340
340
  cursor: pointer;
341
341
  white-space: nowrap;
@@ -344,7 +344,7 @@
344
344
 
345
345
  .category-tab:hover {
346
346
  background: rgba(255, 255, 255, 0.05);
347
- color: var(--color-text, #e8e8f0);
347
+ color: var(--ide-text-primary, #f4f1e0);
348
348
  }
349
349
 
350
350
  .category-tab.active {
@@ -361,13 +361,13 @@
361
361
 
362
362
  .snippet-list {
363
363
  overflow-y: auto;
364
- border-right: 1px solid var(--color-border, #333);
364
+ border-right: 1px solid var(--ide-border, #a8c5d9);
365
365
  }
366
366
 
367
367
  .snippet-empty {
368
368
  padding: 24px;
369
369
  text-align: center;
370
- color: var(--color-text-muted, #888);
370
+ color: var(--ide-text-muted, #a8c5d9);
371
371
  font-size: 13px;
372
372
  }
373
373
 
@@ -377,7 +377,7 @@
377
377
  padding: 10px 16px;
378
378
  background: transparent;
379
379
  border: none;
380
- border-bottom: 1px solid var(--color-border, #333);
380
+ border-bottom: 1px solid var(--ide-border, #a8c5d9);
381
381
  text-align: left;
382
382
  cursor: pointer;
383
383
  transition: background 0.1s ease;
@@ -407,7 +407,7 @@
407
407
  .snippet-name {
408
408
  font-size: 13px;
409
409
  font-weight: 500;
410
- color: var(--color-text, #e8e8f0);
410
+ color: var(--ide-text-primary, #f4f1e0);
411
411
  }
412
412
 
413
413
  .snippet-badge {
@@ -421,7 +421,7 @@
421
421
 
422
422
  .snippet-item-desc {
423
423
  font-size: 11px;
424
- color: var(--color-text-muted, #888);
424
+ color: var(--ide-text-muted, #a8c5d9);
425
425
  }
426
426
 
427
427
  /* Preview pane */
@@ -442,7 +442,7 @@
442
442
  .preview-name {
443
443
  font-size: 14px;
444
444
  font-weight: 600;
445
- color: var(--color-text, #e8e8f0);
445
+ color: var(--ide-text-primary, #f4f1e0);
446
446
  }
447
447
 
448
448
  .preview-category {
@@ -450,7 +450,7 @@
450
450
  padding: 2px 8px;
451
451
  background: rgba(255, 255, 255, 0.1);
452
452
  border-radius: 4px;
453
- color: var(--color-text-secondary, #aaa);
453
+ color: var(--ide-text-secondary, #a8c5d9);
454
454
  }
455
455
 
456
456
  .preview-body {
@@ -466,7 +466,7 @@
466
466
  font-family: 'JetBrains Mono', 'Fira Code', monospace;
467
467
  font-size: 12px;
468
468
  line-height: 1.5;
469
- color: var(--color-text, #e8e8f0);
469
+ color: var(--ide-text-primary, #f4f1e0);
470
470
  white-space: pre-wrap;
471
471
  word-break: break-all;
472
472
  }
@@ -486,7 +486,7 @@
486
486
  justify-content: space-between;
487
487
  margin-top: 12px;
488
488
  font-size: 11px;
489
- color: var(--color-text-muted, #888);
489
+ color: var(--ide-text-muted, #a8c5d9);
490
490
  }
491
491
 
492
492
  .preview-footer code {
@@ -515,7 +515,7 @@
515
515
  align-items: center;
516
516
  justify-content: center;
517
517
  height: 100%;
518
- color: var(--color-text-muted, #888);
518
+ color: var(--ide-text-muted, #a8c5d9);
519
519
  font-size: 13px;
520
520
  }
521
521
 
@@ -523,8 +523,8 @@
523
523
  display: flex;
524
524
  justify-content: space-between;
525
525
  padding: 8px 16px;
526
- border-top: 1px solid var(--color-border, #333);
526
+ border-top: 1px solid var(--ide-border, #a8c5d9);
527
527
  font-size: 11px;
528
- color: var(--color-text-muted, #888);
528
+ color: var(--ide-text-muted, #a8c5d9);
529
529
  }
530
530
  </style>
@@ -14,6 +14,10 @@
14
14
  import type { SemanticCategory } from './core/semantic-analyzer';
15
15
  import { getSemanticAnalyzer } from './core/semantic-analyzer';
16
16
  import type { ComplexityMetrics } from './core/complexity-analyzer';
17
+ import { layoutStructureRows } from './core/structure-layout';
18
+
19
+ /** Minimum legible height of a single node row, in px (kept in sync with CSS). */
20
+ const ROW_HEIGHT = 18;
17
21
 
18
22
  interface StructureNode {
19
23
  /** Stable unique id (keyed-each safe — multiple regions can share a start line) */
@@ -134,27 +138,39 @@
134
138
  // Sort by line number
135
139
  nodes.sort((a, b) => a.startLine - b.startLine);
136
140
 
137
- return nodes;
141
+ // Drop a generic `exports` node when a more specific structural node
142
+ // (class / function / types) begins on the same line. `export class Foo`
143
+ // emits both an `exports` region ("Export: class") and a `class` region
144
+ // ("Class: Foo") at the identical start line; without this they render as
145
+ // two stacked rows saying the same thing.
146
+ const specificStartLines = new Set(
147
+ nodes
148
+ .filter((n) => n.type === 'function' || n.type === 'class' || n.type === 'types')
149
+ .map((n) => n.startLine)
150
+ );
151
+
152
+ return nodes.filter((n) => !(n.type === 'exports' && specificStartLines.has(n.startLine)));
138
153
  });
139
154
 
155
+ // Measured height of the scrollable node area, kept current by a ResizeObserver
156
+ // via Svelte's `bind:clientHeight`. Drives collision-free row placement.
157
+ let contentHeight = $state(0);
158
+
159
+ // Non-overlapping top offset (px) for each node, proportional to its start
160
+ // line but de-collided so labels never overprint. See structure-layout.ts.
161
+ let nodeTops = $derived(
162
+ layoutStructureRows(
163
+ structure.map((n) => n.startLine),
164
+ totalLines,
165
+ contentHeight,
166
+ ROW_HEIGHT
167
+ )
168
+ );
169
+
140
170
  // Calculate viewport indicator position
141
171
  let viewportTop = $derived((scrollLine / Math.max(1, totalLines)) * 100);
142
172
  let viewportHeight = $derived((visibleLines / Math.max(1, totalLines)) * 100);
143
173
 
144
- /**
145
- * Get node height as percentage
146
- */
147
- function getNodeHeight(node: StructureNode): number {
148
- return ((node.endLine - node.startLine + 1) / Math.max(1, totalLines)) * 100;
149
- }
150
-
151
- /**
152
- * Get node top position as percentage
153
- */
154
- function getNodeTop(node: StructureNode): number {
155
- return (node.startLine / Math.max(1, totalLines)) * 100;
156
- }
157
-
158
174
  /**
159
175
  * Get color for node type
160
176
  */
@@ -231,7 +247,7 @@
231
247
  <span class="structure-map__count">{structure.length}</span>
232
248
  </div>
233
249
 
234
- <div class="structure-map__content">
250
+ <div class="structure-map__content" bind:clientHeight={contentHeight}>
235
251
  <!-- Viewport indicator -->
236
252
  <div
237
253
  class="structure-map__viewport"
@@ -239,15 +255,15 @@
239
255
  ></div>
240
256
 
241
257
  <!-- Structure nodes -->
242
- {#each structure as node (node.id)}
258
+ {#each structure as node, i (node.id)}
243
259
  <button
244
260
  class="structure-map__node"
245
261
  class:structure-map__node--active={isCursorInNode(node)}
246
262
  class:structure-map__node--complex={node.metrics.complexity &&
247
263
  node.metrics.complexity >= 50}
248
264
  style="
249
- top: {getNodeTop(node)}%;
250
- height: {Math.max(1, getNodeHeight(node))}%;
265
+ top: {nodeTops[i] ?? 0}px;
266
+ height: {ROW_HEIGHT}px;
251
267
  --node-color: {getNodeColor(node.type)};
252
268
  --complexity-color: {getComplexityColor(node.metrics.complexity ?? 0)};
253
269
  "
@@ -296,8 +312,8 @@
296
312
  display: flex;
297
313
  flex-direction: column;
298
314
  height: 100%;
299
- background: var(--color-surface, #1a1a2e);
300
- border-left: 1px solid var(--color-border, #333);
315
+ background: var(--ide-bg-secondary, #1a2744);
316
+ border-left: 1px solid var(--ide-border, #a8c5d9);
301
317
  font-size: 11px;
302
318
  user-select: none;
303
319
  }
@@ -307,12 +323,12 @@
307
323
  justify-content: space-between;
308
324
  align-items: center;
309
325
  padding: 8px 10px;
310
- border-bottom: 1px solid var(--color-border, #333);
326
+ border-bottom: 1px solid var(--ide-border, #a8c5d9);
311
327
  }
312
328
 
313
329
  .structure-map__title {
314
330
  font-weight: 600;
315
- color: var(--color-text, #e8e8f0);
331
+ color: var(--ide-text-primary, #f4f1e0);
316
332
  text-transform: uppercase;
317
333
  font-size: 10px;
318
334
  letter-spacing: 0.05em;
@@ -323,7 +339,7 @@
323
339
  background: rgba(255, 255, 255, 0.1);
324
340
  border-radius: 10px;
325
341
  font-size: 10px;
326
- color: var(--color-text-muted, #888);
342
+ color: var(--ide-text-muted, #a8c5d9);
327
343
  }
328
344
 
329
345
  .structure-map__content {
@@ -349,7 +365,8 @@
349
365
  left: 4px;
350
366
  right: 4px;
351
367
  display: flex;
352
- align-items: flex-start;
368
+ align-items: center;
369
+ box-sizing: border-box;
353
370
  gap: 4px;
354
371
  padding: 2px 6px;
355
372
  background: rgba(var(--node-color-rgb, 59, 130, 246), 0.15);
@@ -358,7 +375,7 @@
358
375
  border-radius: 0 3px 3px 0;
359
376
  cursor: pointer;
360
377
  text-align: left;
361
- color: var(--color-text, #e8e8f0);
378
+ color: var(--ide-text-primary, #f4f1e0);
362
379
  font-size: 10px;
363
380
  overflow: hidden;
364
381
  transition: background 0.15s ease;
@@ -407,17 +424,17 @@
407
424
  left: 0;
408
425
  right: 0;
409
426
  height: 2px;
410
- background: var(--color-cursor, #4a9eff);
427
+ background: var(--ide-interactive-focus, #60a5fa);
411
428
  pointer-events: none;
412
429
  z-index: 10;
413
- box-shadow: 0 0 4px var(--color-cursor, #4a9eff);
430
+ box-shadow: 0 0 4px var(--ide-interactive-focus, #60a5fa);
414
431
  }
415
432
 
416
433
  .structure-map__legend {
417
434
  display: flex;
418
435
  gap: 8px;
419
436
  padding: 6px 10px;
420
- border-top: 1px solid var(--color-border, #333);
437
+ border-top: 1px solid var(--ide-border, #a8c5d9);
421
438
  flex-wrap: wrap;
422
439
  }
423
440
 
@@ -425,7 +442,7 @@
425
442
  display: flex;
426
443
  align-items: center;
427
444
  gap: 4px;
428
- color: var(--color-text-muted, #888);
445
+ color: var(--ide-text-muted, #a8c5d9);
429
446
  font-size: 9px;
430
447
  }
431
448
 
@@ -277,13 +277,13 @@
277
277
  gap: 8px;
278
278
  height: 32px;
279
279
  padding: 0 12px;
280
- background: var(--color-surface, #1e1e2e);
281
- border-top: 1px solid var(--color-border, #333);
280
+ background: var(--ide-bg-secondary, #1a2744);
281
+ border-top: 1px solid var(--ide-border, #a8c5d9);
282
282
  user-select: none;
283
283
  }
284
284
 
285
285
  .timeline-scrubber--playback {
286
- background: var(--color-surface-elevated, #252535);
286
+ background: var(--ide-bg-elevated, #1a2744);
287
287
  }
288
288
 
289
289
  .timeline-scrubber__controls {
@@ -303,7 +303,7 @@
303
303
  background: transparent;
304
304
  border: none;
305
305
  border-radius: 4px;
306
- color: var(--color-text-muted, #888);
306
+ color: var(--ide-text-muted, #a8c5d9);
307
307
  cursor: pointer;
308
308
  transition:
309
309
  background 0.15s ease,
@@ -312,7 +312,7 @@
312
312
 
313
313
  .timeline-scrubber__btn:hover {
314
314
  background: rgba(255, 255, 255, 0.1);
315
- color: var(--color-text, #e8e8f0);
315
+ color: var(--ide-text-primary, #f4f1e0);
316
316
  }
317
317
 
318
318
  .timeline-scrubber__btn--live {
@@ -397,7 +397,7 @@
397
397
  .timeline-scrubber__thumb-handle {
398
398
  width: 14px;
399
399
  height: 14px;
400
- background: var(--color-primary, #4a9eff);
400
+ background: var(--ide-interactive, #4a8db7);
401
401
  border: 2px solid #fff;
402
402
  border-radius: 50%;
403
403
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
@@ -413,7 +413,7 @@
413
413
  text-align: center;
414
414
  font-size: 11px;
415
415
  font-family: var(--font-mono, monospace);
416
- color: var(--color-text-muted, #888);
416
+ color: var(--ide-text-muted, #a8c5d9);
417
417
  }
418
418
 
419
419
  .timeline-scrubber__live {
@@ -439,8 +439,8 @@
439
439
  align-items: center;
440
440
  gap: 8px;
441
441
  padding: 8px 12px;
442
- background: var(--color-surface, #1e1e2e);
443
- border: 1px solid var(--color-border, #333);
442
+ background: var(--ide-bg-secondary, #1a2744);
443
+ border: 1px solid var(--ide-border, #a8c5d9);
444
444
  border-radius: 6px;
445
445
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
446
446
  pointer-events: none;
@@ -460,11 +460,11 @@
460
460
  .timeline-scrubber__tooltip-label {
461
461
  font-size: 12px;
462
462
  font-weight: 500;
463
- color: var(--color-text, #e8e8f0);
463
+ color: var(--ide-text-primary, #f4f1e0);
464
464
  }
465
465
 
466
466
  .timeline-scrubber__tooltip-time {
467
467
  font-size: 10px;
468
- color: var(--color-text-muted, #888);
468
+ color: var(--ide-text-muted, #a8c5d9);
469
469
  }
470
470
  </style>
@@ -87,6 +87,10 @@ export declare class ComplexityAnalyzer {
87
87
  * Check if a `{` at position `ch` is the opening brace of a function/class definition
88
88
  */
89
89
  private isDefOpeningBrace;
90
+ /**
91
+ * Extract a definition candidate before its body brace is seen.
92
+ */
93
+ private getDefinitionCandidate;
90
94
  /**
91
95
  * Analyze a specific region
92
96
  */