@kgdiff/viewer 0.3.0 → 0.5.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.
Files changed (120) hide show
  1. package/README.md +9 -8
  2. package/dist/context.d.ts +42 -0
  3. package/dist/context.d.ts.map +1 -0
  4. package/dist/context.js +87 -0
  5. package/dist/context.js.map +1 -0
  6. package/dist/controller.d.ts +30 -173
  7. package/dist/controller.d.ts.map +1 -1
  8. package/dist/controller.js +94 -1099
  9. package/dist/controller.js.map +1 -1
  10. package/dist/element.d.ts +12 -6
  11. package/dist/element.d.ts.map +1 -1
  12. package/dist/element.js +105 -236
  13. package/dist/element.js.map +1 -1
  14. package/dist/hash-sync.d.ts +4 -2
  15. package/dist/hash-sync.d.ts.map +1 -1
  16. package/dist/hash-sync.js +21 -5
  17. package/dist/hash-sync.js.map +1 -1
  18. package/dist/i18n.d.ts +7 -7
  19. package/dist/i18n.d.ts.map +1 -1
  20. package/dist/i18n.js +14 -14
  21. package/dist/i18n.js.map +1 -1
  22. package/dist/index.d.ts +24 -10
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js.map +1 -1
  25. package/dist/keyboard.d.ts +6 -4
  26. package/dist/keyboard.d.ts.map +1 -1
  27. package/dist/keyboard.js +6 -5
  28. package/dist/keyboard.js.map +1 -1
  29. package/dist/pipeline.d.ts.map +1 -1
  30. package/dist/pipeline.js +3 -2
  31. package/dist/pipeline.js.map +1 -1
  32. package/dist/prefs.d.ts +7 -1
  33. package/dist/prefs.d.ts.map +1 -1
  34. package/dist/prefs.js +15 -3
  35. package/dist/prefs.js.map +1 -1
  36. package/dist/root.d.ts +54 -0
  37. package/dist/root.d.ts.map +1 -0
  38. package/dist/root.js +265 -0
  39. package/dist/root.js.map +1 -0
  40. package/dist/schedule.d.ts +22 -0
  41. package/dist/schedule.d.ts.map +1 -0
  42. package/dist/schedule.js +41 -0
  43. package/dist/schedule.js.map +1 -0
  44. package/dist/session.d.ts +253 -0
  45. package/dist/session.d.ts.map +1 -0
  46. package/dist/session.js +1239 -0
  47. package/dist/session.js.map +1 -0
  48. package/dist/standalone/kgdiff-viewer-compute.js +1 -1
  49. package/dist/standalone/kgdiff-viewer.js +4 -4
  50. package/dist/styles.d.ts +13 -6
  51. package/dist/styles.d.ts.map +1 -1
  52. package/dist/styles.js +270 -295
  53. package/dist/styles.js.map +1 -1
  54. package/dist/theme.d.ts +25 -0
  55. package/dist/theme.d.ts.map +1 -0
  56. package/dist/theme.js +149 -0
  57. package/dist/theme.js.map +1 -0
  58. package/dist/ui/change-list.d.ts +18 -0
  59. package/dist/ui/change-list.d.ts.map +1 -0
  60. package/dist/ui/change-list.js +331 -0
  61. package/dist/ui/change-list.js.map +1 -0
  62. package/dist/ui/context.d.ts +21 -5
  63. package/dist/ui/context.d.ts.map +1 -1
  64. package/dist/ui/context.js.map +1 -1
  65. package/dist/ui/dock.d.ts +17 -0
  66. package/dist/ui/dock.d.ts.map +1 -0
  67. package/dist/ui/dock.js +151 -0
  68. package/dist/ui/dock.js.map +1 -0
  69. package/dist/ui/filters.d.ts +9 -0
  70. package/dist/ui/filters.d.ts.map +1 -0
  71. package/dist/ui/filters.js +68 -0
  72. package/dist/ui/filters.js.map +1 -0
  73. package/dist/ui/header.d.ts +7 -2
  74. package/dist/ui/header.d.ts.map +1 -1
  75. package/dist/ui/header.js +26 -135
  76. package/dist/ui/header.js.map +1 -1
  77. package/dist/ui/popovers.d.ts.map +1 -1
  78. package/dist/ui/popovers.js +3 -2
  79. package/dist/ui/popovers.js.map +1 -1
  80. package/dist/ui/search.d.ts +13 -0
  81. package/dist/ui/search.d.ts.map +1 -0
  82. package/dist/ui/search.js +191 -0
  83. package/dist/ui/search.js.map +1 -0
  84. package/dist/ui/sidebar.d.ts +8 -16
  85. package/dist/ui/sidebar.d.ts.map +1 -1
  86. package/dist/ui/sidebar.js +15 -538
  87. package/dist/ui/sidebar.js.map +1 -1
  88. package/dist/ui/stage.d.ts +4 -0
  89. package/dist/ui/stage.d.ts.map +1 -1
  90. package/dist/ui/stage.js +42 -95
  91. package/dist/ui/stage.js.map +1 -1
  92. package/dist/ui/swatch.d.ts +7 -0
  93. package/dist/ui/swatch.d.ts.map +1 -0
  94. package/dist/ui/swatch.js +26 -0
  95. package/dist/ui/swatch.js.map +1 -0
  96. package/package.json +6 -6
  97. package/src/context.ts +106 -0
  98. package/src/controller.ts +120 -1196
  99. package/src/element.ts +114 -254
  100. package/src/hash-sync.ts +20 -6
  101. package/src/i18n.ts +15 -14
  102. package/src/index.ts +24 -10
  103. package/src/keyboard.ts +12 -6
  104. package/src/pipeline.ts +4 -1
  105. package/src/prefs.ts +19 -4
  106. package/src/root.ts +308 -0
  107. package/src/schedule.ts +43 -0
  108. package/src/session.ts +1386 -0
  109. package/src/styles.ts +277 -299
  110. package/src/theme.ts +167 -0
  111. package/src/ui/change-list.ts +401 -0
  112. package/src/ui/context.ts +23 -5
  113. package/src/ui/dock.ts +198 -0
  114. package/src/ui/filters.ts +79 -0
  115. package/src/ui/header.ts +40 -170
  116. package/src/ui/popovers.ts +3 -2
  117. package/src/ui/search.ts +220 -0
  118. package/src/ui/sidebar.ts +28 -667
  119. package/src/ui/stage.ts +50 -115
  120. package/src/ui/swatch.ts +31 -0
package/dist/styles.js CHANGED
@@ -5,62 +5,10 @@ export const FAMILIES = [
5
5
  'structure',
6
6
  'identity',
7
7
  ];
8
- /** CSS custom properties for `theme` (a `:host` rule body). */
9
- export function themeVariables(theme) {
10
- const dark = theme.name === 'dark';
11
- const vars = {
12
- 'color-scheme': dark ? 'dark' : 'light',
13
- '--kg-bg': theme.canvas.background,
14
- '--kg-grid': theme.canvas.grid,
15
- '--kg-panel': theme.surface.panel,
16
- '--kg-raised': theme.surface.raised,
17
- '--kg-overlay': theme.surface.overlay,
18
- '--kg-border': theme.surface.border,
19
- '--kg-border-strong': theme.surface.borderStrong,
20
- '--kg-control-border': theme.surface.controlBorder,
21
- '--kg-shadow': theme.surface.shadow,
22
- '--kg-text': theme.text.primary,
23
- '--kg-text-2': theme.text.secondary,
24
- '--kg-text-3': theme.text.muted,
25
- '--kg-accent': theme.accent.base,
26
- '--kg-accent-strong': theme.accent.strong,
27
- '--kg-accent-soft': theme.accent.soft,
28
- '--kg-accent-text': theme.accent.text,
29
- '--kg-neutral': theme.neutral.node,
30
- '--kg-neutral-stroke': theme.neutral.nodeStroke,
31
- '--kg-neutral-edge': theme.neutral.edge,
32
- '--kg-font': theme.font.family,
33
- '--kg-mono': theme.font.mono,
34
- '--kg-fast': `${theme.motion.fast}ms`,
35
- '--kg-base': `${theme.motion.base}ms`,
36
- '--kg-slow': `${theme.motion.slow}ms`,
37
- '--kg-ease': `cubic-bezier(${theme.motion.easing.join(', ')})`,
38
- // Derived interaction tints (not color-coded: hover / press / inputs / scrims).
39
- '--kg-hover': dark ? 'rgba(255,255,255,0.045)' : 'rgba(15,23,42,0.04)',
40
- '--kg-press': dark ? 'rgba(255,255,255,0.08)' : 'rgba(15,23,42,0.07)',
41
- '--kg-input': dark ? theme.surface.raised : '#F3F5F8',
42
- '--kg-selected': dark ? theme.surface.raised : '#F5F7FB',
43
- '--kg-scrim': dark ? 'rgba(5,7,11,0.56)' : 'rgba(15,23,42,0.18)',
44
- '--kg-skeleton': dark ? 'rgba(255,255,255,0.05)' : 'rgba(15,23,42,0.05)',
45
- '--kg-skeleton-hi': dark ? 'rgba(255,255,255,0.09)' : 'rgba(15,23,42,0.09)',
46
- '--kg-track': dark ? 'rgba(255,255,255,0.08)' : 'rgba(15,23,42,0.08)',
47
- '--kg-kbd': dark ? 'rgba(255,255,255,0.06)' : 'rgba(15,23,42,0.05)',
48
- };
49
- for (const f of FAMILIES) {
50
- const c = theme.family[f];
51
- vars[`--kg-${f}`] = c.base;
52
- vars[`--kg-${f}-strong`] = c.strong;
53
- vars[`--kg-${f}-soft`] = c.soft;
54
- vars[`--kg-${f}-text`] = c.text;
55
- }
56
- return Object.entries(vars)
57
- .map(([k, v]) => `${k}: ${v};`)
58
- .join(' ');
59
- }
60
8
  const familyRules = [...FAMILIES, 'neutral']
61
9
  .map((f) => f === 'neutral'
62
- ? `[data-family="neutral"] { --fam-base: var(--kg-neutral); --fam-soft: var(--kg-hover); --fam-text: var(--kg-text-2); }`
63
- : `[data-family="${f}"] { --fam-base: var(--kg-${f}); --fam-soft: var(--kg-${f}-soft); --fam-text: var(--kg-${f}-text); }`)
10
+ ? `[data-family="neutral"] { --fam-base: var(--kgdiff-neutral); --fam-soft: var(--kgdiff-hover); --fam-text: var(--kgdiff-text-2); }`
11
+ : `[data-family="${f}"] { --fam-base: var(--kgdiff-${f}); --fam-soft: var(--kgdiff-${f}-soft); --fam-text: var(--kgdiff-${f}-text); }`)
64
12
  .join('\n');
65
13
  export const STYLES = /* css */ `
66
14
  :host {
@@ -70,11 +18,11 @@ export const STYLES = /* css */ `
70
18
  height: 100%;
71
19
  min-height: 420px;
72
20
  contain: content;
73
- font-family: var(--kg-font);
21
+ font-family: var(--kgdiff-font);
74
22
  font-size: 13px;
75
23
  line-height: 1.45;
76
- color: var(--kg-text);
77
- background: var(--kg-bg);
24
+ color: var(--kgdiff-text);
25
+ background: var(--kgdiff-bg);
78
26
  -webkit-font-smoothing: antialiased;
79
27
  }
80
28
  :host([hidden]) { display: none; }
@@ -89,7 +37,7 @@ button {
89
37
  }
90
38
  button:disabled { cursor: default; opacity: 0.4; }
91
39
  :focus { outline: none; }
92
- :focus-visible { outline: 2px solid var(--kg-accent); outline-offset: 2px; }
40
+ :focus-visible { outline: 2px solid var(--kgdiff-accent); outline-offset: 2px; }
93
41
  .icon { width: 16px; height: 16px; flex: none; display: block; }
94
42
  .sr-only {
95
43
  position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px;
@@ -98,139 +46,128 @@ button:disabled { cursor: default; opacity: 0.4; }
98
46
  kbd {
99
47
  display: inline-flex; align-items: center; justify-content: center;
100
48
  min-width: 20px; height: 20px; padding: 0 5px; border-radius: 5px;
101
- font: 500 11px/1 var(--kg-mono); color: var(--kg-text-2);
102
- background: var(--kg-kbd); box-shadow: inset 0 0 0 1px var(--kg-border), inset 0 -1px 0 var(--kg-border);
49
+ font: 500 11px/1 var(--kgdiff-mono); color: var(--kgdiff-text-2);
50
+ background: var(--kgdiff-kbd); box-shadow: inset 0 0 0 1px var(--kgdiff-border), inset 0 -1px 0 var(--kgdiff-border);
103
51
  }
104
- .scroll { overflow: auto; scrollbar-width: thin; scrollbar-color: var(--kg-border-strong) transparent; }
52
+ .scroll { overflow: auto; scrollbar-width: thin; scrollbar-color: var(--kgdiff-border-strong) transparent; }
105
53
 
106
54
  /* ── Root layout ─────────────────────────────────────────────────────────── */
107
55
  .root {
108
56
  position: absolute; inset: 0; display: flex; flex-direction: column; overflow: hidden;
109
- background: var(--kg-bg);
57
+ background: var(--kgdiff-bg);
110
58
  }
111
59
  .body { position: relative; flex: 1; min-height: 0; display: flex; }
112
- .stage-wrap { position: relative; flex: 1; min-width: 0; min-height: 0; overflow: hidden; background: var(--kg-bg); }
60
+ .stage-wrap { position: relative; flex: 1; min-width: 0; min-height: 0; overflow: hidden; background: var(--kgdiff-bg); container-type: inline-size; }
113
61
  .stage { position: absolute; inset: 0; }
114
62
  .stage canvas { outline: none; }
115
- .stage canvas:focus-visible { outline: 2px solid var(--kg-accent); outline-offset: -2px; }
63
+ .stage canvas:focus-visible { outline: 2px solid var(--kgdiff-accent); outline-offset: -2px; }
116
64
  .chrome { position: absolute; inset: 0; pointer-events: none; }
117
65
  .chrome > * { pointer-events: auto; }
118
66
 
119
67
  /* ── Buttons ─────────────────────────────────────────────────────────────── */
120
68
  .icon-btn {
121
69
  display: inline-flex; align-items: center; justify-content: center; flex: none;
122
- width: 32px; height: 32px; border-radius: 8px; color: var(--kg-text-2);
123
- transition: background var(--kg-fast) var(--kg-ease), color var(--kg-fast) var(--kg-ease);
70
+ width: 32px; height: 32px; border-radius: 8px; color: var(--kgdiff-text-2);
71
+ transition: background var(--kgdiff-fast) var(--kgdiff-ease), color var(--kgdiff-fast) var(--kgdiff-ease);
124
72
  }
125
- .icon-btn:hover { background: var(--kg-hover); color: var(--kg-text); }
126
- .icon-btn:active { background: var(--kg-press); }
127
- .icon-btn[aria-pressed="true"], .icon-btn[aria-expanded="true"] { background: var(--kg-press); color: var(--kg-text); }
73
+ .icon-btn:hover { background: var(--kgdiff-hover); color: var(--kgdiff-text); }
74
+ .icon-btn:active { background: var(--kgdiff-press); }
75
+ .icon-btn[aria-pressed="true"], .icon-btn[aria-expanded="true"] { background: var(--kgdiff-press); color: var(--kgdiff-text); }
128
76
  .icon-btn.sm { width: 28px; height: 28px; border-radius: 7px; }
129
77
  .btn {
130
78
  display: inline-flex; align-items: center; gap: 6px; height: 28px; padding: 0 10px;
131
- border-radius: 7px; font-size: 12px; font-weight: 500; color: var(--kg-text);
132
- background: var(--kg-hover); box-shadow: inset 0 0 0 1px var(--kg-border);
133
- transition: background var(--kg-fast) var(--kg-ease), box-shadow var(--kg-fast) var(--kg-ease);
79
+ border-radius: 7px; font-size: 12px; font-weight: 500; color: var(--kgdiff-text);
80
+ background: var(--kgdiff-hover); box-shadow: inset 0 0 0 1px var(--kgdiff-border);
81
+ transition: background var(--kgdiff-fast) var(--kgdiff-ease), box-shadow var(--kgdiff-fast) var(--kgdiff-ease);
134
82
  }
135
- .btn:hover { background: var(--kg-press); box-shadow: inset 0 0 0 1px var(--kg-border-strong); }
136
- .link-btn { min-height: 28px; color: var(--kg-accent-text); font-weight: 500; font-size: 12px; border-radius: 4px; }
83
+ .btn:hover { background: var(--kgdiff-press); box-shadow: inset 0 0 0 1px var(--kgdiff-border-strong); }
84
+ .link-btn { min-height: 28px; color: var(--kgdiff-accent-text); font-weight: 500; font-size: 12px; border-radius: 4px; }
137
85
  .link-btn:hover { text-decoration: underline; text-underline-offset: 3px; }
138
86
 
139
- /* ── Header ──────────────────────────────────────────────────────────────── */
140
- .header {
141
- position: relative; z-index: 3; flex: none; height: 52px; display: flex; align-items: center; gap: 12px;
142
- padding: 0 10px 0 14px; background: var(--kg-panel); border-bottom: 1px solid var(--kg-border);
143
- }
144
- .brand { display: flex; align-items: center; gap: 8px; flex: none; color: var(--kg-text); }
87
+ /* ── HUD: title (top-left) and actions (top-right), over the canvas ──────── */
88
+ .hud { position: absolute; inset: 0; z-index: 3; pointer-events: none; }
89
+ .hud > * { pointer-events: auto; }
90
+ .hud-title {
91
+ position: absolute; top: 12px; left: 12px; max-width: calc(100% - 184px); height: 40px;
92
+ display: flex; align-items: center; gap: 10px; padding: 0 14px 0 10px;
93
+ }
94
+ .hud[data-titled="false"] .header-sep { display: none; }
95
+ :host([header="compact"]) .hud-title { display: none; }
96
+ .hud-end { position: absolute; top: 12px; right: 12px; }
97
+ .hud-actions { display: flex; align-items: center; gap: 2px; padding: 4px; }
98
+ .brand { display: flex; align-items: center; gap: 8px; flex: none; color: var(--kgdiff-text); }
145
99
  .brand-mark { width: 20px; height: 20px; display: block; }
146
100
  .brand-name { font-size: 14px; font-weight: 650; letter-spacing: -0.01em; }
147
- .header-sep { width: 1px; height: 20px; background: var(--kg-border-strong); flex: none; }
148
- .versions { display: flex; align-items: center; gap: 8px; min-width: 0; flex: 1 1 0; font-size: 13px; overflow: hidden;
149
- mask-image: linear-gradient(90deg, #000 calc(100% - 16px), transparent); }
150
- .versions .name { font-weight: 550; color: var(--kg-text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
151
- .versions .arrow { color: var(--kg-text-3); flex: none; }
101
+ .header-sep { width: 1px; height: 18px; background: var(--kgdiff-border-strong); flex: none; }
102
+ .versions { display: flex; align-items: center; gap: 8px; min-width: 0; flex: 0 1 auto; font-size: 13px; overflow: hidden; }
103
+ .versions .name { font-weight: 550; color: var(--kgdiff-text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
104
+ .versions .arrow { color: var(--kgdiff-text-3); flex: none; }
152
105
  .versions .side { display: flex; align-items: center; gap: 6px; min-width: 0; }
153
106
  .tag {
154
107
  display: inline-flex; align-items: center; height: 20px; padding: 0 6px; border-radius: 5px; flex: none;
155
- font: 500 11px/1 var(--kg-mono); color: var(--kg-text-2); background: var(--kg-hover);
156
- box-shadow: inset 0 0 0 1px var(--kg-border); white-space: nowrap; max-width: 160px; overflow: hidden; text-overflow: ellipsis;
157
- }
158
- .header-center { flex: none; display: flex; justify-content: center; }
159
- /* header="compact": no brand or names (the host shows them); the names keep their space so the
160
- mode control stays centered. */
161
- :host([header="compact"]) .brand, :host([header="compact"]) .header-sep { display: none; }
162
- :host([header="compact"]) .versions { visibility: hidden; }
163
- .header-end { display: flex; align-items: center; gap: 4px; flex: 1 0 auto; justify-content: flex-end; }
164
- .stats { display: flex; align-items: center; gap: 4px; margin-right: 6px; }
108
+ font: 500 11px/1 var(--kgdiff-mono); color: var(--kgdiff-text-2); background: var(--kgdiff-hover);
109
+ box-shadow: inset 0 0 0 1px var(--kgdiff-border); white-space: nowrap; max-width: 160px; overflow: hidden; text-overflow: ellipsis;
110
+ }
165
111
 
166
112
  .segmented {
167
- position: relative; display: inline-flex; align-items: center; gap: 2px; height: 32px; padding: 2px;
168
- border-radius: 9px; background: var(--kg-hover); box-shadow: inset 0 0 0 1px var(--kg-border);
113
+ position: relative; display: inline-flex; align-items: center; gap: 2px; height: 32px; padding: 2px; flex: none;
114
+ border-radius: 9px; background: var(--kgdiff-hover); box-shadow: inset 0 0 0 1px var(--kgdiff-border);
169
115
  }
170
116
  .segmented .thumb {
171
117
  position: absolute; top: 2px; bottom: 2px; left: 0; width: 0; border-radius: 7px;
172
- background: var(--kg-raised); box-shadow: 0 1px 2px rgba(0,0,0,0.12), inset 0 0 0 1px var(--kg-border-strong);
173
- transition: transform var(--kg-base) var(--kg-ease), width var(--kg-base) var(--kg-ease);
118
+ background: var(--kgdiff-raised); box-shadow: 0 1px 2px rgba(0,0,0,0.12), inset 0 0 0 1px var(--kgdiff-border-strong);
119
+ transition: transform var(--kgdiff-base) var(--kgdiff-ease), width var(--kgdiff-base) var(--kgdiff-ease);
174
120
  }
175
121
  .seg {
176
122
  position: relative; z-index: 1; display: inline-flex; align-items: center; gap: 6px; height: 28px; padding: 0 10px;
177
- border-radius: 7px; font-size: 12.5px; font-weight: 500; color: var(--kg-text-2); white-space: nowrap;
178
- transition: color var(--kg-fast) var(--kg-ease);
123
+ border-radius: 7px; font-size: 12.5px; font-weight: 500; color: var(--kgdiff-text-2); white-space: nowrap;
124
+ transition: color var(--kgdiff-fast) var(--kgdiff-ease);
179
125
  }
180
- .seg:hover { color: var(--kg-text); }
181
- .seg[aria-checked="true"] { color: var(--kg-text); }
126
+ .seg:hover { color: var(--kgdiff-text); }
127
+ .seg[aria-checked="true"] { color: var(--kgdiff-text); }
182
128
  .seg .icon { opacity: 0.9; }
183
129
 
184
- .pill {
185
- display: inline-flex; align-items: center; gap: 4px; height: 28px; padding: 0 9px; border-radius: 14px;
186
- font-size: 12px; font-weight: 600; font-variant-numeric: tabular-nums; white-space: nowrap;
187
- transition: box-shadow var(--kg-fast) var(--kg-ease), background var(--kg-fast) var(--kg-ease), opacity var(--kg-fast) var(--kg-ease);
188
- }
189
- .stat { color: var(--fam-text); background: var(--fam-soft); box-shadow: inset 0 0 0 1px transparent; }
190
- .stat:hover { box-shadow: inset 0 0 0 1px var(--fam-base); }
191
- .stat[aria-pressed="true"] { box-shadow: inset 0 0 0 1.5px var(--fam-base); }
192
- .stats.filtering .stat[aria-pressed="false"] { opacity: 0.55; }
193
- .stat .glyph { font-weight: 700; }
194
-
195
130
 
196
131
  ${familyRules}
197
132
 
198
133
  /* ── Floating chrome ─────────────────────────────────────────────────────── */
199
134
  .card {
200
- background: var(--kg-overlay); border-radius: 12px; box-shadow: var(--kg-shadow), 0 0 0 1px var(--kg-border);
135
+ background: var(--kgdiff-overlay); border-radius: 12px; box-shadow: var(--kgdiff-shadow), 0 0 0 1px var(--kgdiff-border);
201
136
  backdrop-filter: blur(16px) saturate(140%);
202
137
  }
203
138
  .float { position: absolute; }
204
- .top-left { top: 12px; left: 12px; }
205
139
  .bottom-left { bottom: 16px; left: 16px; }
206
140
  .bottom-right { bottom: 16px; right: 16px; }
207
141
  .chip {
208
142
  display: inline-flex; align-items: center; gap: 6px; height: 28px; padding: 0 10px; border-radius: 8px;
209
- font-size: 12px; font-weight: 600; color: var(--kg-text-2); letter-spacing: 0.01em;
143
+ font-size: 12px; font-weight: 600; color: var(--kgdiff-text-2); letter-spacing: 0.01em;
210
144
  }
211
145
 
212
146
  .map-cluster { display: flex; align-items: flex-end; gap: 8px; }
213
147
  .zoom-bar { display: flex; flex-direction: column; padding: 2px; gap: 2px; }
214
148
  .zoom-bar .icon-btn { width: 30px; height: 30px; }
215
- .minimap-host { position: relative; width: 184px; height: 128px; border-radius: 12px; box-shadow: 0 0 0 1px var(--kg-border); }
149
+ .minimap-host { position: relative; width: 184px; height: 128px; border-radius: 12px; box-shadow: 0 0 0 1px var(--kgdiff-border);
150
+ animation: fade var(--kgdiff-base) var(--kgdiff-ease); }
151
+ /* Everything is in view: the minimap has nothing to add. */
152
+ .minimap-host[data-hidden="true"] { display: none; }
216
153
  .minimap-host canvas { border-radius: 12px; }
217
154
 
218
155
  .legend { padding: 6px; min-width: 0; }
219
156
  .legend-head { display: flex; align-items: center; gap: 6px; height: 28px; padding: 0 6px 0 8px; font-size: 11px; font-weight: 600;
220
- letter-spacing: 0.06em; text-transform: uppercase; color: var(--kg-text-3); border-radius: 7px; width: 100%; }
221
- .legend-head:hover { color: var(--kg-text-2); background: var(--kg-hover); }
222
- .legend-head .icon { width: 14px; height: 14px; margin-left: auto; transition: transform var(--kg-base) var(--kg-ease); }
157
+ letter-spacing: 0.06em; text-transform: uppercase; color: var(--kgdiff-text-3); border-radius: 7px; width: 100%; }
158
+ .legend-head:hover { color: var(--kgdiff-text-2); background: var(--kgdiff-hover); }
159
+ .legend-head .icon { width: 14px; height: 14px; margin-left: auto; transition: transform var(--kgdiff-base) var(--kgdiff-ease); }
223
160
  .legend[data-open="false"] .legend-head .icon { transform: rotate(180deg); }
224
161
  .legend[data-open="false"] .legend-body { display: none; }
225
162
  .legend[data-open="false"] { padding: 2px; }
226
163
  .legend-body { display: grid; gap: 2px; padding: 2px 4px 4px; }
227
164
  .legend-row { display: grid; grid-template-columns: 22px auto; align-items: center; column-gap: 8px; height: 26px; padding: 0 10px 0 4px; border-radius: 6px; cursor: default; }
228
- .legend-row .name { font-size: 12px; font-weight: 550; color: var(--kg-text); }
165
+ .legend-row .name { font-size: 12px; font-weight: 550; color: var(--kgdiff-text); }
229
166
  .swatch { width: 22px; height: 22px; display: block; }
230
167
  .mini-legend { display: none; }
231
168
  .stage-wrap[data-legend="mini"] .mini-legend {
232
169
  display: flex; flex-wrap: wrap; align-items: center; gap: 2px 12px; bottom: 8px; left: 12px; max-width: calc(100% - 24px);
233
- font-size: 11px; line-height: 16px; color: var(--kg-text-2);
170
+ font-size: 11px; line-height: 16px; color: var(--kgdiff-text-2);
234
171
  }
235
172
  .mini-item { display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; }
236
173
  .mini-item .dot { width: 8px; height: 8px; border-radius: 50%; flex: none; background: var(--fam-base); }
@@ -238,28 +175,49 @@ ${familyRules}
238
175
  .stage-wrap[data-legend="mini"] .legend, .stage-wrap[data-legend="none"] .legend { display: none; }
239
176
 
240
177
  .caption {
241
- position: absolute; top: 12px; left: 50%; transform: translateX(-50%); max-width: min(560px, calc(100% - 200px));
242
- display: flex; align-items: center; gap: 8px; height: 32px; padding: 0 12px 0 6px; font-size: 12.5px; font-weight: 550;
243
- transition: opacity var(--kg-base) var(--kg-ease);
178
+ max-width: min(560px, 100%); display: flex; align-items: center; gap: 8px; height: 32px; padding: 0 12px 0 6px;
179
+ font-size: 12.5px; font-weight: 550;
244
180
  }
245
181
  .caption .text { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
246
- .caption .count { color: var(--kg-text-3); font-weight: 500; font-variant-numeric: tabular-nums; flex: none; }
247
- .caption[data-empty="true"] { opacity: 0; pointer-events: none; }
182
+ .caption .count { color: var(--kgdiff-text-3); font-weight: 500; font-variant-numeric: tabular-nums; flex: none; }
183
+ .caption[data-empty="true"] { display: none; }
248
184
 
249
185
  .glyph-box {
250
186
  display: inline-flex; align-items: center; justify-content: center; flex: none; width: 20px; height: 20px; border-radius: 6px;
251
187
  font-size: 12px; font-weight: 700; line-height: 1; color: var(--fam-text); background: var(--fam-soft);
252
188
  }
253
189
 
254
- .stepper { display: inline-flex; align-items: center; gap: 8px; height: 38px; padding: 0 4px 0 12px; }
255
- .stepper .label { font-size: 12px; font-weight: 550; color: var(--kg-text-2); }
256
- .stepper .opts { display: inline-flex; gap: 2px; padding: 2px; border-radius: 8px; background: var(--kg-hover); }
257
- .stepper .opt { width: 28px; height: 28px; border-radius: 6px; font-size: 12px; font-weight: 600; color: var(--kg-text-2); font-variant-numeric: tabular-nums; }
258
- .stepper .opt:hover { color: var(--kg-text); }
259
- .stepper .expand { display: inline-flex; align-items: center; gap: 4px; height: 28px; padding: 0 10px 0 8px; margin-left: 4px; border-radius: 7px; font-size: 12px; font-weight: 600; color: var(--kg-text-2); box-shadow: inset 0 0 0 1px var(--kg-border-strong); font-variant-numeric: tabular-nums; }
260
- .stepper .expand:hover:not(:disabled) { color: var(--kg-text); background: var(--kg-hover); }
261
- .stepper .expand .icon { width: 14px; height: 14px; }
262
- .stepper .opt[aria-checked="true"] { background: var(--kg-raised); color: var(--kg-text); box-shadow: inset 0 0 0 1px var(--kg-border-strong); }
190
+ /* View dock (bottom center): replay's finished pill, caption and transport stack above the bar. */
191
+ .chrome > .dock {
192
+ position: absolute; left: 16px; right: 16px; bottom: 16px; display: flex; flex-direction: column; align-items: center;
193
+ gap: 8px; pointer-events: none;
194
+ }
195
+ .dock > * { pointer-events: auto; }
196
+ .dock-bar { display: flex; align-items: center; gap: 4px; height: 44px; padding: 0 6px; max-width: 100%; }
197
+ .dock-sep { width: 1px; height: 20px; margin: 0 2px; flex: none; background: var(--kgdiff-border-strong); }
198
+ .scope-btn {
199
+ display: inline-flex; align-items: center; gap: 6px; height: 32px; padding: 0 10px; border-radius: 9px; flex: none;
200
+ font-size: 12.5px; font-weight: 500; color: var(--kgdiff-text-2); white-space: nowrap;
201
+ transition: background var(--kgdiff-fast) var(--kgdiff-ease), color var(--kgdiff-fast) var(--kgdiff-ease), box-shadow var(--kgdiff-fast) var(--kgdiff-ease);
202
+ }
203
+ .scope-btn:hover { color: var(--kgdiff-text); background: var(--kgdiff-hover); }
204
+ .scope-btn[aria-pressed="true"] { color: var(--kgdiff-accent-text); background: var(--kgdiff-accent-soft); box-shadow: inset 0 0 0 1px var(--kgdiff-accent-soft); }
205
+ .scope-btn[aria-disabled="true"] { cursor: default; }
206
+ .context { display: inline-flex; align-items: center; gap: 8px; padding-left: 2px; flex: none; animation: reveal var(--kgdiff-base) var(--kgdiff-ease); }
207
+ @keyframes reveal { from { opacity: 0; transform: translateX(-6px); } }
208
+ .context .label { font-size: 12px; font-weight: 550; color: var(--kgdiff-text-3); white-space: nowrap; }
209
+ .context .opts { display: inline-flex; gap: 2px; padding: 2px; border-radius: 8px; background: var(--kgdiff-hover); }
210
+ .context .opt { width: 28px; height: 28px; border-radius: 6px; font-size: 12px; font-weight: 600; color: var(--kgdiff-text-2); font-variant-numeric: tabular-nums; }
211
+ .context .opt:hover { color: var(--kgdiff-text); }
212
+ .context .opt[aria-checked="true"] { background: var(--kgdiff-raised); color: var(--kgdiff-text); box-shadow: inset 0 0 0 1px var(--kgdiff-border-strong); }
213
+ .context .expand { display: inline-flex; align-items: center; gap: 4px; height: 28px; padding: 0 10px 0 8px; border-radius: 7px; font-size: 12px; font-weight: 600; color: var(--kgdiff-text-2); box-shadow: inset 0 0 0 1px var(--kgdiff-border-strong); font-variant-numeric: tabular-nums; }
214
+ .context .expand:hover:not(:disabled) { color: var(--kgdiff-text); background: var(--kgdiff-hover); }
215
+ .context .expand .icon { width: 14px; height: 14px; }
216
+ /* Narrower canvases keep the dock clear of the legend and the minimap: labels give way to icons
217
+ (each control keeps its name as a tooltip). */
218
+ @container (max-width: 1180px) { .context .label { display: none; } }
219
+ @container (max-width: 1000px) { .dock-bar .seg .lbl { display: none; } .dock-bar .seg { padding: 0 9px; } }
220
+ @container (max-width: 640px) { .scope-btn .lbl { display: none; } .scope-btn { padding: 0 9px; } }
263
221
 
264
222
  /* Swipe */
265
223
  .swipe { position: absolute; inset: 0; pointer-events: none; }
@@ -267,40 +225,40 @@ ${familyRules}
267
225
  position: absolute; top: 0; bottom: 0; left: 0; width: 24px; margin-left: -12px; cursor: ew-resize; pointer-events: auto;
268
226
  touch-action: none; display: flex; justify-content: center;
269
227
  }
270
- .swipe .divider::before { content: ''; width: 1.5px; height: 100%; background: var(--kg-accent); opacity: 0.85; box-shadow: 0 0 12px var(--kg-accent-soft); }
228
+ .swipe .divider::before { content: ''; width: 1.5px; height: 100%; background: var(--kgdiff-accent); opacity: 0.85; box-shadow: 0 0 12px var(--kgdiff-accent-soft); }
271
229
  .swipe .handle {
272
230
  position: absolute; top: 50%; left: 50%; width: 32px; height: 32px; margin: -16px 0 0 -16px; border-radius: 50%;
273
- display: flex; align-items: center; justify-content: center; gap: 0; color: var(--kg-accent-text);
274
- background: var(--kg-overlay); box-shadow: var(--kg-shadow), 0 0 0 1.5px var(--kg-accent);
231
+ display: flex; align-items: center; justify-content: center; gap: 0; color: var(--kgdiff-accent-text);
232
+ background: var(--kgdiff-overlay); box-shadow: var(--kgdiff-shadow), 0 0 0 1.5px var(--kgdiff-accent);
275
233
  backdrop-filter: blur(16px);
276
- transition: transform var(--kg-fast) var(--kg-ease);
234
+ transition: transform var(--kgdiff-fast) var(--kgdiff-ease);
277
235
  }
278
236
  .swipe .handle .icon { width: 12px; height: 12px; }
279
237
  .swipe .divider:hover .handle, .swipe .divider.dragging .handle { transform: scale(1.08); }
280
238
  .swipe .divider:focus-visible { outline: none; }
281
- .swipe .divider:focus-visible .handle { box-shadow: var(--kg-shadow), 0 0 0 2px var(--kg-accent), 0 0 0 5px var(--kg-accent-soft); }
282
- .swipe .side-chip { position: absolute; top: 12px; pointer-events: none; }
239
+ .swipe .divider:focus-visible .handle { box-shadow: var(--kgdiff-shadow), 0 0 0 2px var(--kgdiff-accent), 0 0 0 5px var(--kgdiff-accent-soft); }
240
+ /* Below the HUD's title and actions. */
241
+ .swipe .side-chip { position: absolute; top: 64px; pointer-events: none; }
283
242
  .swipe .side-chip.before { left: 12px; }
284
243
  .swipe .side-chip.after { right: 12px; }
285
244
 
286
- /* Replay transport */
245
+ /* Replay transport (in the dock, clear of the legend and the minimap) */
287
246
  .transport {
288
- position: absolute; left: 50%; bottom: 16px; transform: translateX(-50%); width: min(600px, calc(100% - 496px));
289
- min-width: 360px;
247
+ width: min(600px, calc(100% - 464px)); min-width: min(360px, 100%);
290
248
  display: flex; align-items: center; gap: 4px; height: 48px; padding: 0 8px;
291
249
  }
292
- .transport .play { width: 36px; height: 36px; border-radius: 10px; color: var(--kg-text); }
250
+ .transport .play { width: 36px; height: 36px; border-radius: 10px; color: var(--kgdiff-text); }
293
251
  .transport .play .icon { width: 18px; height: 18px; }
294
- .transport .pos { flex: none; min-width: 64px; text-align: center; font-size: 12px; font-weight: 550; color: var(--kg-text-2); font-variant-numeric: tabular-nums; }
295
- .transport .speed { flex: none; height: 28px; min-width: 44px; padding: 0 8px; border-radius: 7px; font-size: 12px; font-weight: 600; color: var(--kg-text-2); font-variant-numeric: tabular-nums; box-shadow: inset 0 0 0 1px var(--kg-border); }
296
- .transport .speed:hover { color: var(--kg-text); background: var(--kg-hover); }
252
+ .transport .pos { flex: none; min-width: 64px; text-align: center; font-size: 12px; font-weight: 550; color: var(--kgdiff-text-2); font-variant-numeric: tabular-nums; }
253
+ .transport .speed { flex: none; height: 28px; min-width: 44px; padding: 0 8px; border-radius: 7px; font-size: 12px; font-weight: 600; color: var(--kgdiff-text-2); font-variant-numeric: tabular-nums; box-shadow: inset 0 0 0 1px var(--kgdiff-border); }
254
+ .transport .speed:hover { color: var(--kgdiff-text); background: var(--kgdiff-hover); }
297
255
  .scrubber { position: relative; flex: 1; height: 36px; margin: 0 8px; cursor: pointer; touch-action: none; border-radius: 6px; }
298
- .scrubber .track { position: absolute; left: 0; right: 0; top: 50%; height: 4px; margin-top: -2px; border-radius: 2px; background: var(--kg-track); overflow: hidden; }
299
- .scrubber .fill { position: absolute; left: 0; top: 0; bottom: 0; width: 100%; transform-origin: left; background: var(--kg-accent); opacity: 0.85; }
256
+ .scrubber .track { position: absolute; left: 0; right: 0; top: 50%; height: 4px; margin-top: -2px; border-radius: 2px; background: var(--kgdiff-track); overflow: hidden; }
257
+ .scrubber .fill { position: absolute; left: 0; top: 0; bottom: 0; width: 100%; transform-origin: left; background: var(--kgdiff-accent); opacity: 0.85; }
300
258
  .scrubber .ticks { position: absolute; left: 0; right: 0; top: 50%; height: 14px; margin-top: -7px; width: 100%; pointer-events: none; overflow: visible; }
301
259
  .scrubber .knob {
302
260
  position: absolute; top: 50%; left: 0; width: 14px; height: 14px; margin: -7px 0 0 -7px; border-radius: 50%;
303
- background: var(--kg-text); box-shadow: 0 1px 4px rgba(0,0,0,0.35), 0 0 0 3px var(--kg-accent-soft); pointer-events: none;
261
+ background: var(--kgdiff-text); box-shadow: 0 1px 4px rgba(0,0,0,0.35), 0 0 0 3px var(--kgdiff-accent-soft); pointer-events: none;
304
262
  }
305
263
  .scrubber:focus-visible { outline-offset: 0; }
306
264
  .scrub-tip {
@@ -309,26 +267,26 @@ ${familyRules}
309
267
  display: flex; align-items: center; gap: 6px;
310
268
  }
311
269
  .finished {
312
- position: absolute; left: 50%; bottom: 76px; transform: translateX(-50%); display: flex; align-items: center; gap: 10px;
313
- height: 36px; padding: 0 6px 0 12px; font-size: 12.5px; font-weight: 550; color: var(--kg-text);
314
- animation: rise var(--kg-base) var(--kg-ease);
270
+ display: flex; align-items: center; gap: 10px;
271
+ height: 36px; padding: 0 6px 0 12px; font-size: 12.5px; font-weight: 550; color: var(--kgdiff-text);
272
+ animation: rise var(--kgdiff-base) var(--kgdiff-ease);
315
273
  }
316
- .finished .icon { color: var(--kg-accent-text); }
317
- @keyframes rise { from { opacity: 0; transform: translate(-50%, 6px); } }
274
+ .finished .icon { color: var(--kgdiff-accent-text); }
275
+ @keyframes rise { from { opacity: 0; transform: translateY(6px); } }
318
276
 
319
277
  /* Tooltip */
320
278
  .tooltip {
321
279
  position: absolute; left: 0; top: 0; z-index: 4; width: max-content; max-width: 300px; padding: 10px 12px; pointer-events: none;
322
- border-radius: 10px; opacity: 0; transition: opacity var(--kg-fast) var(--kg-ease);
280
+ border-radius: 10px; opacity: 0; transition: opacity var(--kgdiff-fast) var(--kgdiff-ease);
323
281
  }
324
282
  .tooltip[data-open="true"] { opacity: 1; }
325
- .tooltip .t-label { font-size: 13px; font-weight: 600; color: var(--kg-text); overflow-wrap: anywhere; }
326
- .tooltip .t-old { font-size: 12px; color: var(--kg-text-3); text-decoration: line-through; overflow-wrap: anywhere; }
327
- .tooltip .t-id { margin-top: 2px; font: 11px/1.4 var(--kg-mono); color: var(--kg-text-3); overflow-wrap: anywhere; }
283
+ .tooltip .t-label { font-size: 13px; font-weight: 600; color: var(--kgdiff-text); overflow-wrap: anywhere; }
284
+ .tooltip .t-old { font-size: 12px; color: var(--kgdiff-text-3); text-decoration: line-through; overflow-wrap: anywhere; }
285
+ .tooltip .t-id { margin-top: 2px; font: 11px/1.4 var(--kgdiff-mono); color: var(--kgdiff-text-3); overflow-wrap: anywhere; }
328
286
  .tooltip .t-status { margin-top: 8px; display: flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 550; color: var(--fam-text); }
329
287
  .tooltip .t-status .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--fam-base); flex: none; }
330
- .tooltip .t-sum { margin-top: 4px; font-size: 12px; color: var(--kg-text-2); overflow-wrap: anywhere; }
331
- .tooltip .t-hint { margin-top: 6px; font-size: 11px; color: var(--kg-text-3); }
288
+ .tooltip .t-sum { margin-top: 4px; font-size: 12px; color: var(--kgdiff-text-2); overflow-wrap: anywhere; }
289
+ .tooltip .t-hint { margin-top: 6px; font-size: 11px; color: var(--kgdiff-text-3); }
332
290
 
333
291
  /* States (loading / identical / error / empty) */
334
292
  .state {
@@ -336,36 +294,36 @@ ${familyRules}
336
294
  pointer-events: none;
337
295
  }
338
296
  .state > * { pointer-events: auto; }
339
- .state.blocking { background: var(--kg-bg); }
297
+ .state.blocking { background: var(--kgdiff-bg); }
340
298
  .state-card { width: min(380px, 100%); padding: 24px; text-align: left; }
341
299
  .state-card .state-icon {
342
300
  width: 36px; height: 36px; border-radius: 10px; display: flex; align-items: center; justify-content: center;
343
- color: var(--kg-accent-text); background: var(--kg-accent-soft); margin-bottom: 16px;
301
+ color: var(--kgdiff-accent-text); background: var(--kgdiff-accent-soft); margin-bottom: 16px;
344
302
  }
345
303
  .state-card .state-icon .icon { width: 20px; height: 20px; }
346
- .state-card.error .state-icon { color: var(--kg-removed-text); background: var(--kg-removed-soft); }
347
- .state-card.ok .state-icon { color: var(--kg-added-text); background: var(--kg-added-soft); }
304
+ .state-card.error .state-icon { color: var(--kgdiff-removed-text); background: var(--kgdiff-removed-soft); }
305
+ .state-card.ok .state-icon { color: var(--kgdiff-added-text); background: var(--kgdiff-added-soft); }
348
306
  .state-card h2 { margin: 0; font-size: 15px; font-weight: 650; letter-spacing: -0.01em; }
349
- .state-card p { margin: 6px 0 0; color: var(--kg-text-2); font-size: 13px; }
350
- .state-card details { margin-top: 16px; font-size: 12px; color: var(--kg-text-2); }
351
- .state-card summary { cursor: pointer; font-weight: 550; color: var(--kg-text-2); border-radius: 4px; width: max-content; }
307
+ .state-card p { margin: 6px 0 0; color: var(--kgdiff-text-2); font-size: 13px; }
308
+ .state-card details { margin-top: 16px; font-size: 12px; color: var(--kgdiff-text-2); }
309
+ .state-card summary { cursor: pointer; font-weight: 550; color: var(--kgdiff-text-2); border-radius: 4px; width: max-content; }
352
310
  .state-card pre {
353
- margin: 8px 0 0; max-height: 200px; padding: 10px 12px; border-radius: 8px; background: var(--kg-input);
354
- font: 11.5px/1.5 var(--kg-mono); white-space: pre-wrap; overflow-wrap: anywhere; color: var(--kg-text-2);
355
- box-shadow: inset 0 0 0 1px var(--kg-border);
311
+ margin: 8px 0 0; max-height: 200px; padding: 10px 12px; border-radius: 8px; background: var(--kgdiff-input);
312
+ font: 11.5px/1.5 var(--kgdiff-mono); white-space: pre-wrap; overflow-wrap: anywhere; color: var(--kgdiff-text-2);
313
+ box-shadow: inset 0 0 0 1px var(--kgdiff-border);
356
314
  }
357
315
  .steps { list-style: none; margin: 16px 0 0; padding: 0; display: grid; gap: 10px; }
358
- .steps li { display: flex; align-items: center; gap: 10px; font-size: 13px; color: var(--kg-text-3); transition: color var(--kg-base) var(--kg-ease); }
359
- .steps li[data-state="active"] { color: var(--kg-text); font-weight: 550; }
360
- .steps li[data-state="done"] { color: var(--kg-text-2); }
361
- .steps .mark { width: 18px; height: 18px; flex: none; border-radius: 50%; display: flex; align-items: center; justify-content: center; box-shadow: inset 0 0 0 1.5px var(--kg-border-strong); }
362
- .steps li[data-state="done"] .mark { background: var(--kg-accent-soft); box-shadow: none; color: var(--kg-accent-text); }
316
+ .steps li { display: flex; align-items: center; gap: 10px; font-size: 13px; color: var(--kgdiff-text-3); transition: color var(--kgdiff-base) var(--kgdiff-ease); }
317
+ .steps li[data-state="active"] { color: var(--kgdiff-text); font-weight: 550; }
318
+ .steps li[data-state="done"] { color: var(--kgdiff-text-2); }
319
+ .steps .mark { width: 18px; height: 18px; flex: none; border-radius: 50%; display: flex; align-items: center; justify-content: center; box-shadow: inset 0 0 0 1.5px var(--kgdiff-border-strong); }
320
+ .steps li[data-state="done"] .mark { background: var(--kgdiff-accent-soft); box-shadow: none; color: var(--kgdiff-accent-text); }
363
321
  .steps li[data-state="done"] .mark .icon { width: 12px; height: 12px; }
364
- .steps li[data-state="active"] .mark { box-shadow: inset 0 0 0 1.5px var(--kg-accent-soft); border-top: 1.5px solid var(--kg-accent); animation: spin 0.8s linear infinite; }
322
+ .steps li[data-state="active"] .mark { box-shadow: inset 0 0 0 1.5px var(--kgdiff-accent-soft); border-top: 1.5px solid var(--kgdiff-accent); animation: spin 0.8s linear infinite; }
365
323
  @keyframes spin { to { transform: rotate(360deg); } }
366
324
  .skeleton-grid {
367
325
  position: absolute; inset: 0;
368
- background-image: radial-gradient(var(--kg-skeleton-hi) 1.2px, transparent 1.4px); background-size: 24px 24px;
326
+ background-image: radial-gradient(var(--kgdiff-skeleton-hi) 1.2px, transparent 1.4px); background-size: 24px 24px;
369
327
  mask-image: radial-gradient(ellipse at center, #000 20%, transparent 75%);
370
328
  animation: breathe 2.4s ease-in-out infinite;
371
329
  }
@@ -374,46 +332,46 @@ ${familyRules}
374
332
  /* ── Sidebar ─────────────────────────────────────────────────────────────── */
375
333
  .sidebar {
376
334
  position: relative; z-index: 2; flex: none; width: 360px; display: flex; overflow: hidden;
377
- background: var(--kg-panel); border-left: 1px solid var(--kg-border);
378
- transition: width var(--kg-base) var(--kg-ease), border-color var(--kg-base) var(--kg-ease);
335
+ background: var(--kgdiff-panel); border-left: 1px solid var(--kgdiff-border);
336
+ transition: width var(--kgdiff-base) var(--kgdiff-ease), border-color var(--kgdiff-base) var(--kgdiff-ease);
379
337
  }
380
338
  .sidebar[data-open="false"] { width: 0; border-left-color: transparent; }
381
339
  .sidebar-inner { width: 360px; flex: none; display: flex; flex-direction: column; min-height: 0; }
382
340
  .sheet-handle { display: none; }
383
- .sb-head { flex: none; padding: 12px 12px 8px; display: grid; gap: 10px; border-bottom: 1px solid var(--kg-border); }
341
+ .sb-head { flex: none; padding: 12px 12px 8px; display: grid; gap: 10px; border-bottom: 1px solid var(--kgdiff-border); }
384
342
  .sb-title { display: flex; align-items: center; gap: 8px; height: 24px; padding: 0 2px; }
385
343
  .sb-title h2 { margin: 0; font-size: 13px; font-weight: 650; }
386
344
  .count-badge {
387
345
  display: inline-flex; align-items: center; height: 18px; padding: 0 6px; border-radius: 9px; font-size: 11px; font-weight: 600;
388
- color: var(--kg-text-2); background: var(--kg-hover); box-shadow: inset 0 0 0 1px var(--kg-border); font-variant-numeric: tabular-nums;
346
+ color: var(--kgdiff-text-2); background: var(--kgdiff-hover); box-shadow: inset 0 0 0 1px var(--kgdiff-border); font-variant-numeric: tabular-nums;
389
347
  }
390
- .progress { margin-left: auto; display: flex; align-items: center; gap: 8px; font-size: 11.5px; color: var(--kg-text-3); font-variant-numeric: tabular-nums; }
391
- .progress .bar { width: 64px; height: 4px; border-radius: 2px; background: var(--kg-track); overflow: hidden; }
392
- .progress .bar > div { height: 100%; width: 100%; transform-origin: left; background: var(--kg-accent); border-radius: 2px; transition: transform var(--kg-base) var(--kg-ease); }
393
- .progress[data-complete="true"] { color: var(--kg-accent-text); }
348
+ .progress { margin-left: auto; display: flex; align-items: center; gap: 8px; font-size: 11.5px; color: var(--kgdiff-text-3); font-variant-numeric: tabular-nums; }
349
+ .progress .bar { width: 64px; height: 4px; border-radius: 2px; background: var(--kgdiff-track); overflow: hidden; }
350
+ .progress .bar > div { height: 100%; width: 100%; transform-origin: left; background: var(--kgdiff-accent); border-radius: 2px; transition: transform var(--kgdiff-base) var(--kgdiff-ease); }
351
+ .progress[data-complete="true"] { color: var(--kgdiff-accent-text); }
394
352
 
395
- .search { position: relative; display: flex; align-items: center; height: 32px; border-radius: 8px; background: var(--kg-input);
396
- box-shadow: inset 0 0 0 1px var(--kg-border); transition: box-shadow var(--kg-fast) var(--kg-ease); }
397
- .search:focus-within { box-shadow: inset 0 0 0 1px var(--kg-accent), 0 0 0 3px var(--kg-accent-soft); }
398
- .search > .icon { position: absolute; left: 10px; color: var(--kg-text-3); pointer-events: none; }
353
+ .search { position: relative; display: flex; align-items: center; height: 32px; border-radius: 8px; background: var(--kgdiff-input);
354
+ box-shadow: inset 0 0 0 1px var(--kgdiff-border); transition: box-shadow var(--kgdiff-fast) var(--kgdiff-ease); }
355
+ .search:focus-within { box-shadow: inset 0 0 0 1px var(--kgdiff-accent), 0 0 0 3px var(--kgdiff-accent-soft); }
356
+ .search > .icon { position: absolute; left: 10px; color: var(--kgdiff-text-3); pointer-events: none; }
399
357
  .search input {
400
- flex: 1; min-width: 0; height: 100%; padding: 0 64px 0 32px; border: 0; background: transparent; font-size: 13px; color: var(--kg-text);
358
+ flex: 1; min-width: 0; height: 100%; padding: 0 64px 0 32px; border: 0; background: transparent; font-size: 13px; color: var(--kgdiff-text);
401
359
  }
402
- .search input::placeholder { color: var(--kg-text-3); }
360
+ .search input::placeholder { color: var(--kgdiff-text-3); }
403
361
  .search input::-webkit-search-cancel-button { display: none; }
404
362
  .search kbd { position: absolute; right: 8px; }
405
- .search .clear { position: absolute; right: 2px; width: 28px; height: 28px; border-radius: 6px; display: flex; align-items: center; justify-content: center; color: var(--kg-text-3); }
406
- .search .clear:hover { color: var(--kg-text); background: var(--kg-hover); }
363
+ .search .clear { position: absolute; right: 2px; width: 28px; height: 28px; border-radius: 6px; display: flex; align-items: center; justify-content: center; color: var(--kgdiff-text-3); }
364
+ .search .clear:hover { color: var(--kgdiff-text); background: var(--kgdiff-hover); }
407
365
 
408
366
  .filters { display: flex; flex-wrap: wrap; gap: 4px; }
409
367
  .fchip {
410
368
  display: inline-flex; align-items: center; gap: 5px; height: 28px; padding: 0 8px 0 7px; border-radius: 14px;
411
- font-size: 11.5px; font-weight: 550; color: var(--kg-text-2); box-shadow: inset 0 0 0 1px var(--kg-border);
412
- transition: background var(--kg-fast) var(--kg-ease), box-shadow var(--kg-fast) var(--kg-ease), color var(--kg-fast) var(--kg-ease);
369
+ font-size: 11.5px; font-weight: 550; color: var(--kgdiff-text-2); box-shadow: inset 0 0 0 1px var(--kgdiff-border);
370
+ transition: background var(--kgdiff-fast) var(--kgdiff-ease), box-shadow var(--kgdiff-fast) var(--kgdiff-ease), color var(--kgdiff-fast) var(--kgdiff-ease);
413
371
  }
414
- .fchip:hover { background: var(--kg-hover); color: var(--kg-text); }
415
- .fchip .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--fam-base); flex: none; }
416
- .fchip .n { color: var(--kg-text-3); font-variant-numeric: tabular-nums; font-weight: 500; }
372
+ .fchip:hover { background: var(--kgdiff-hover); color: var(--kgdiff-text); }
373
+ .fchip .swatch { width: 16px; height: 16px; margin: 0 -1px; }
374
+ .fchip .n { color: var(--kgdiff-text-3); font-variant-numeric: tabular-nums; font-weight: 500; }
417
375
  .fchip[aria-pressed="true"] { background: var(--fam-soft); color: var(--fam-text); box-shadow: inset 0 0 0 1px var(--fam-base); }
418
376
  .fchip[aria-pressed="true"] .n { color: var(--fam-text); opacity: 0.8; }
419
377
  .fchip:disabled { opacity: 0.35; }
@@ -421,73 +379,73 @@ ${familyRules}
421
379
  .list-wrap { position: relative; flex: 1 1 50%; min-height: 96px; display: flex; flex-direction: column; }
422
380
  .list { position: relative; flex: 1; min-height: 0; outline: none; }
423
381
  .list:focus-visible { outline: none; }
424
- .list:focus-visible:not(:has(.row[aria-selected="true"])) { box-shadow: inset 0 0 0 2px var(--kg-accent); }
425
- .list:focus-visible .row[aria-selected="true"] { box-shadow: inset 0 0 0 2px var(--kg-accent); }
382
+ .list:focus-visible:not(:has(.row[aria-selected="true"])) { box-shadow: inset 0 0 0 2px var(--kgdiff-accent); }
383
+ .list:focus-visible .row[aria-selected="true"] { box-shadow: inset 0 0 0 2px var(--kgdiff-accent); }
426
384
  .list-inner { position: relative; width: 100%; }
427
385
  .row {
428
386
  position: absolute; left: 8px; right: 8px; height: 52px; display: flex; align-items: center; gap: 10px; padding: 0 6px 0 14px;
429
387
  border-radius: 8px; cursor: pointer; user-select: none; -webkit-user-select: none;
430
- transition: background var(--kg-fast) var(--kg-ease), box-shadow var(--kg-fast) var(--kg-ease);
388
+ transition: background var(--kgdiff-fast) var(--kgdiff-ease), box-shadow var(--kgdiff-fast) var(--kgdiff-ease);
431
389
  }
432
390
  .row::before { content: ''; position: absolute; left: 4px; top: 10px; bottom: 10px; width: 3px; border-radius: 2px; background: var(--fam-base); }
433
- .row:hover { background: var(--kg-hover); }
434
- .row[aria-selected="true"] { background: var(--kg-selected); box-shadow: inset 0 0 0 1px var(--kg-accent), 0 1px 2px rgba(0,0,0,0.06); }
391
+ .row:hover { background: var(--kgdiff-hover); }
392
+ .row[aria-selected="true"] { background: var(--kgdiff-selected); box-shadow: inset 0 0 0 1px var(--kgdiff-accent), 0 1px 2px rgba(0,0,0,0.06); }
435
393
  .row .txt { flex: 1; min-width: 0; display: grid; gap: 1px; }
436
- .row .title { font-size: 13px; font-weight: 500; color: var(--kg-text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
437
- .row .sub { font-size: 12px; color: var(--kg-text-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-height: 17px; }
438
- .row[data-reviewed="true"] .title { color: var(--kg-text-2); }
394
+ .row .title { font-size: 13px; font-weight: 500; color: var(--kgdiff-text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
395
+ .row .sub { font-size: 12px; color: var(--kgdiff-text-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-height: 17px; }
396
+ .row[data-reviewed="true"] .title { color: var(--kgdiff-text-2); }
439
397
  .row[data-reviewed="true"] .glyph-box { opacity: 0.7; }
440
398
  .rv {
441
399
  flex: none; width: 28px; height: 28px; border-radius: 50%; display: flex; align-items: center; justify-content: center; cursor: pointer;
442
400
  }
443
401
  .rv .ring {
444
402
  width: 18px; height: 18px; border-radius: 50%; display: flex; align-items: center; justify-content: center;
445
- box-shadow: inset 0 0 0 1.5px var(--kg-control-border); color: transparent;
446
- transition: background var(--kg-fast) var(--kg-ease), box-shadow var(--kg-fast) var(--kg-ease), color var(--kg-fast) var(--kg-ease), transform var(--kg-fast) var(--kg-ease);
403
+ box-shadow: inset 0 0 0 1.5px var(--kgdiff-control-border); color: transparent;
404
+ transition: background var(--kgdiff-fast) var(--kgdiff-ease), box-shadow var(--kgdiff-fast) var(--kgdiff-ease), color var(--kgdiff-fast) var(--kgdiff-ease), transform var(--kgdiff-fast) var(--kgdiff-ease);
447
405
  }
448
406
  .rv .ring .icon { width: 12px; height: 12px; }
449
- .rv:hover .ring { box-shadow: inset 0 0 0 1.5px var(--kg-accent); color: var(--kg-text-3); }
450
- .rv[data-pressed="true"] .ring { background: var(--kg-accent); box-shadow: none; color: var(--kg-bg); }
407
+ .rv:hover .ring { box-shadow: inset 0 0 0 1.5px var(--kgdiff-accent); color: var(--kgdiff-text-3); }
408
+ .rv[data-pressed="true"] .ring { background: var(--kgdiff-accent); box-shadow: none; color: var(--kgdiff-bg); }
451
409
  .rv[data-pressed="true"]:active .ring { transform: scale(0.9); }
452
410
  .group {
453
411
  position: absolute; left: 0; right: 0; height: 32px; display: flex; align-items: center; gap: 8px; padding: 10px 16px 0 22px;
454
- font-size: 11px; font-weight: 650; letter-spacing: 0.06em; text-transform: uppercase; color: var(--kg-text-3);
412
+ font-size: 11px; font-weight: 650; letter-spacing: 0.06em; text-transform: uppercase; color: var(--kgdiff-text-3);
455
413
  }
456
414
  .group .n { font-weight: 500; letter-spacing: 0; font-variant-numeric: tabular-nums; }
457
415
  .sticky {
458
- position: absolute; top: 0; left: 0; right: 0; z-index: 1; height: 32px; background: var(--kg-panel);
459
- box-shadow: 0 1px 0 var(--kg-border); pointer-events: none;
416
+ position: absolute; top: 0; left: 0; right: 0; z-index: 1; height: 32px; background: var(--kgdiff-panel);
417
+ box-shadow: 0 1px 0 var(--kgdiff-border); pointer-events: none;
460
418
  }
461
419
  .sticky .group { position: static; height: 32px; padding-top: 0; }
462
420
  .sticky[data-shadow="false"] { box-shadow: none; }
463
- .list-empty { padding: 32px 24px; text-align: center; color: var(--kg-text-3); font-size: 12.5px; display: grid; gap: 10px; justify-items: center; }
421
+ .list-empty { padding: 32px 24px; text-align: center; color: var(--kgdiff-text-3); font-size: 12.5px; display: grid; gap: 10px; justify-items: center; }
464
422
  .skeleton-row { height: 52px; margin: 0 8px; padding: 0 14px; display: flex; align-items: center; gap: 10px; }
465
- .skeleton-row .b { flex: 1; max-width: 70%; height: 10px; border-radius: 5px; background: var(--kg-skeleton); }
423
+ .skeleton-row .b { flex: 1; max-width: 70%; height: 10px; border-radius: 5px; background: var(--kgdiff-skeleton); }
466
424
  .skeleton-row:nth-child(even) .b { max-width: 52%; }
467
- .skeleton-row .g { width: 20px; height: 20px; border-radius: 6px; background: var(--kg-skeleton); flex: none; }
425
+ .skeleton-row .g { width: 20px; height: 20px; border-radius: 6px; background: var(--kgdiff-skeleton); flex: none; }
468
426
  .shimmer { animation: breathe 1.6s ease-in-out infinite; }
469
427
 
470
428
  .results { padding: 4px 0 8px; }
471
- .results-head { padding: 8px 16px 6px; font-size: 11px; font-weight: 650; letter-spacing: 0.06em; text-transform: uppercase; color: var(--kg-text-3); }
429
+ .results-head { padding: 8px 16px 6px; font-size: 11px; font-weight: 650; letter-spacing: 0.06em; text-transform: uppercase; color: var(--kgdiff-text-3); }
472
430
  .result {
473
431
  display: flex; align-items: center; gap: 10px; width: calc(100% - 16px); margin: 0 8px; height: 44px; padding: 0 10px; border-radius: 8px;
474
432
  text-align: left;
475
433
  }
476
- .result:hover, .result[aria-selected="true"] { background: var(--kg-hover); }
477
- .result[aria-selected="true"] { box-shadow: inset 0 0 0 1px var(--kg-border-strong); }
434
+ .result:hover, .result[aria-selected="true"] { background: var(--kgdiff-hover); }
435
+ .result[aria-selected="true"] { box-shadow: inset 0 0 0 1px var(--kgdiff-border-strong); }
478
436
  .result .sdot { width: 8px; height: 8px; border-radius: 50%; flex: none; background: var(--fam-base); }
479
- .result[data-family="neutral"] .sdot { background: transparent; box-shadow: inset 0 0 0 1.5px var(--kg-neutral-stroke); }
437
+ .result[data-family="neutral"] .sdot { background: transparent; box-shadow: inset 0 0 0 1.5px var(--kgdiff-neutral-stroke); }
480
438
  .result .txt { flex: 1; min-width: 0; display: grid; }
481
439
  .result .title { font-size: 13px; font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
482
- .result .sub { font: 11px/1.4 var(--kg-mono); color: var(--kg-text-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
483
- .result mark { background: var(--kg-accent-soft); color: inherit; border-radius: 3px; padding: 0 1px; }
440
+ .result .sub { font: 11px/1.4 var(--kgdiff-mono); color: var(--kgdiff-text-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
441
+ .result mark { background: var(--kgdiff-accent-soft); color: inherit; border-radius: 3px; padding: 0 1px; }
484
442
  .result .status { font-size: 11.5px; color: var(--fam-text); flex: none; }
485
443
 
486
444
  /* ── Detail panel ────────────────────────────────────────────────────────── */
487
- .detail { flex: 0 1 auto; max-height: 58%; min-height: 0; display: flex; flex-direction: column; border-top: 1px solid var(--kg-border); background: var(--kg-panel); }
445
+ .detail { flex: 0 1 auto; max-height: 58%; min-height: 0; display: flex; flex-direction: column; border-top: 1px solid var(--kgdiff-border); background: var(--kgdiff-panel); }
488
446
  .detail[data-empty="true"] { flex: none; }
489
- .detail-empty { padding: 16px; display: flex; align-items: center; gap: 12px; color: var(--kg-text-3); font-size: 12.5px; }
490
- .detail-empty .icon { color: var(--kg-text-3); }
447
+ .detail-empty { padding: 16px; display: flex; align-items: center; gap: 12px; color: var(--kgdiff-text-3); font-size: 12.5px; }
448
+ .detail-empty .icon { color: var(--kgdiff-text-3); }
491
449
  .detail-empty .sub { font-size: 11.5px; margin-top: 2px; }
492
450
  .detail-scroll { flex: 1; min-height: 0; padding: 14px 16px 20px; }
493
451
  .d-top { display: flex; align-items: center; gap: 6px; margin-bottom: 10px; }
@@ -495,117 +453,116 @@ ${familyRules}
495
453
  .fam-pill .g { font-weight: 700; }
496
454
  .d-nav { margin-left: auto; display: flex; align-items: center; gap: 2px; }
497
455
  .d-title { margin: 0; font-size: 14.5px; line-height: 1.4; font-weight: 600; letter-spacing: -0.005em; overflow-wrap: anywhere; }
498
- .d-sub { margin-top: 4px; font-size: 12.5px; color: var(--kg-text-2); overflow-wrap: anywhere; }
499
- .rv-btn { display: inline-flex; align-items: center; gap: 6px; height: 28px; padding: 0 10px 0 6px; border-radius: 7px; font-size: 12px; font-weight: 550; color: var(--kg-text-2); box-shadow: inset 0 0 0 1px var(--kg-border); margin-right: 4px; }
500
- .rv-btn:hover { color: var(--kg-text); background: var(--kg-hover); }
501
- .rv-btn .ring { width: 16px; height: 16px; border-radius: 50%; display: flex; align-items: center; justify-content: center; box-shadow: inset 0 0 0 1.5px var(--kg-control-border); color: transparent; }
456
+ .d-sub { margin-top: 4px; font-size: 12.5px; color: var(--kgdiff-text-2); overflow-wrap: anywhere; }
457
+ .rv-btn { display: inline-flex; align-items: center; gap: 6px; height: 28px; padding: 0 10px 0 6px; border-radius: 7px; font-size: 12px; font-weight: 550; color: var(--kgdiff-text-2); box-shadow: inset 0 0 0 1px var(--kgdiff-border); margin-right: 4px; }
458
+ .rv-btn:hover { color: var(--kgdiff-text); background: var(--kgdiff-hover); }
459
+ .rv-btn .ring { width: 16px; height: 16px; border-radius: 50%; display: flex; align-items: center; justify-content: center; box-shadow: inset 0 0 0 1.5px var(--kgdiff-control-border); color: transparent; }
502
460
  .rv-btn .ring .icon { width: 11px; height: 11px; }
503
- .rv-btn[aria-pressed="true"] { color: var(--kg-accent-text); box-shadow: inset 0 0 0 1px var(--kg-accent); background: var(--kg-accent-soft); }
504
- .rv-btn[aria-pressed="true"] .ring { background: var(--kg-accent); box-shadow: none; color: var(--kg-bg); }
461
+ .rv-btn[aria-pressed="true"] { color: var(--kgdiff-accent-text); box-shadow: inset 0 0 0 1px var(--kgdiff-accent); background: var(--kgdiff-accent-soft); }
462
+ .rv-btn[aria-pressed="true"] .ring { background: var(--kgdiff-accent); box-shadow: none; color: var(--kgdiff-bg); }
505
463
  .section { margin-top: 18px; }
506
- .section > h3 { margin: 0 0 8px; font-size: 11px; font-weight: 650; letter-spacing: 0.06em; text-transform: uppercase; color: var(--kg-text-3); display: flex; align-items: center; gap: 6px; }
464
+ .section > h3 { margin: 0 0 8px; font-size: 11px; font-weight: 650; letter-spacing: 0.06em; text-transform: uppercase; color: var(--kgdiff-text-3); display: flex; align-items: center; gap: 6px; }
507
465
  .section > h3 .n { font-weight: 500; letter-spacing: 0; }
508
466
  .kv { display: grid; grid-template-columns: 72px minmax(0, 1fr); gap: 6px 12px; font-size: 12.5px; align-items: baseline; }
509
- .kv dt { color: var(--kg-text-3); }
467
+ .kv dt { color: var(--kgdiff-text-3); }
510
468
  .kv dd { margin: 0; min-width: 0; overflow-wrap: anywhere; }
511
- .id-text { font: 12px/1.5 var(--kg-mono); color: var(--kg-text); overflow-wrap: anywhere; }
469
+ .id-text { font: 12px/1.5 var(--kgdiff-mono); color: var(--kgdiff-text); overflow-wrap: anywhere; }
512
470
  .chips { display: flex; flex-wrap: wrap; gap: 4px; }
513
- .vchip { display: inline-flex; align-items: center; gap: 4px; min-height: 22px; padding: 2px 8px; border-radius: 6px; font-size: 12px; background: var(--kg-hover); box-shadow: inset 0 0 0 1px var(--kg-border); overflow-wrap: anywhere; }
514
- .vchip.add { color: var(--kg-added-text); background: var(--kg-added-soft); box-shadow: none; }
515
- .vchip.del { color: var(--kg-removed-text); background: var(--kg-removed-soft); box-shadow: none; text-decoration: line-through; text-decoration-thickness: 1px; }
471
+ .vchip { display: inline-flex; align-items: center; gap: 4px; min-height: 22px; padding: 2px 8px; border-radius: 6px; font-size: 12px; background: var(--kgdiff-hover); box-shadow: inset 0 0 0 1px var(--kgdiff-border); overflow-wrap: anywhere; }
472
+ .vchip.add { color: var(--kgdiff-added-text); background: var(--kgdiff-added-soft); box-shadow: none; }
473
+ .vchip.del { color: var(--kgdiff-removed-text); background: var(--kgdiff-removed-soft); box-shadow: none; text-decoration: line-through; text-decoration-thickness: 1px; }
516
474
  .vchip .sign { font-weight: 700; text-decoration: none; display: inline-block; }
517
475
  .pair { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 6px; }
518
- .pair .b, .line.old { color: var(--kg-text-2); }
519
- .pair .arr { color: var(--kg-text-3); }
476
+ .pair .b, .line.old { color: var(--kgdiff-text-2); }
477
+ .pair .arr { color: var(--kgdiff-text-3); }
520
478
  .line { display: grid; grid-template-columns: 10px minmax(0, 1fr); gap: 6px; align-items: baseline; }
521
- .line .sign { font: 600 12px/1 var(--kg-mono); text-align: center; }
522
- .line.old .sign { color: var(--kg-removed-text); }
523
- .line.new .sign { color: var(--kg-added-text); }
524
- del.hl { text-decoration: line-through; text-decoration-color: var(--kg-removed); background: var(--kg-removed-soft); color: var(--kg-removed-text); border-radius: 3px; padding: 0 1px; }
525
- ins.hl { text-decoration: none; background: var(--kg-added-soft); color: var(--kg-added-text); border-radius: 3px; padding: 0 1px; }
479
+ .line .sign { font: 600 12px/1 var(--kgdiff-mono); text-align: center; }
480
+ .line.old .sign { color: var(--kgdiff-removed-text); }
481
+ .line.new .sign { color: var(--kgdiff-added-text); }
482
+ del.hl { text-decoration: line-through; text-decoration-color: var(--kgdiff-removed); background: var(--kgdiff-removed-soft); color: var(--kgdiff-removed-text); border-radius: 3px; padding: 0 1px; }
483
+ ins.hl { text-decoration: none; background: var(--kgdiff-added-soft); color: var(--kgdiff-added-text); border-radius: 3px; padding: 0 1px; }
526
484
  .attrs { width: 100%; border-collapse: separate; border-spacing: 0; font-size: 12.5px; table-layout: fixed; }
527
- .attrs td { vertical-align: baseline; padding: 6px 8px 6px 0; border-top: 1px solid var(--kg-border); overflow-wrap: anywhere; }
485
+ .attrs td { vertical-align: baseline; padding: 6px 8px 6px 0; border-top: 1px solid var(--kgdiff-border); overflow-wrap: anywhere; }
528
486
  .attrs tr:first-child td { border-top: 0; padding-top: 0; }
529
487
  .attrs td > * + * { margin-top: 4px; }
530
- .attrs td.k { color: var(--kg-text-2); }
488
+ .attrs td.k { color: var(--kgdiff-text-2); }
531
489
  .attrs col.k { width: 28%; }
532
490
  .val { white-space: pre-wrap; }
533
491
  .val.clamped { display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; overflow: hidden; }
534
492
  .more { margin-top: 2px; }
535
- .disclosure { display: inline-flex; align-items: center; gap: 4px; min-height: 28px; margin-top: 4px; font-size: 12px; color: var(--kg-text-2); border-radius: 4px; }
536
- .disclosure:hover { color: var(--kg-text); }
537
- .disclosure .icon { width: 12px; height: 12px; transition: transform var(--kg-base) var(--kg-ease); }
493
+ .disclosure { display: inline-flex; align-items: center; gap: 4px; min-height: 28px; margin-top: 4px; font-size: 12px; color: var(--kgdiff-text-2); border-radius: 4px; }
494
+ .disclosure:hover { color: var(--kgdiff-text); }
495
+ .disclosure .icon { width: 12px; height: 12px; transition: transform var(--kgdiff-base) var(--kgdiff-ease); }
538
496
  .disclosure[aria-expanded="true"] .icon { transform: rotate(180deg); }
539
497
  .rels { display: grid; gap: 2px; }
540
498
  .rel { display: flex; align-items: baseline; gap: 8px; width: 100%; padding: 6px 8px; margin: 0 -8px; border-radius: 7px; text-align: left; font-size: 12.5px; line-height: 1.5; width: calc(100% + 16px); }
541
- .rel:hover { background: var(--kg-hover); }
542
- .rel .sign { flex: none; width: 12px; font: 600 12px/1.5 var(--kg-mono); color: var(--fam-text); text-align: center; }
499
+ .rel:hover { background: var(--kgdiff-hover); }
500
+ .rel .sign { flex: none; width: 12px; font: 600 12px/1.5 var(--kgdiff-mono); color: var(--fam-text); text-align: center; }
543
501
  .rel .s { min-width: 0; overflow-wrap: anywhere; }
544
502
  .rel .node { font-weight: 550; }
545
- .rel .pred { color: var(--kg-text-2); white-space: nowrap; }
546
- .rel .was { color: var(--kg-text-3); }
547
- .rel.removed .s { text-decoration: line-through; text-decoration-color: var(--kg-text-3); color: var(--kg-text-2); }
503
+ .rel .pred { color: var(--kgdiff-text-2); white-space: nowrap; }
504
+ .rel .was { color: var(--kgdiff-text-3); }
505
+ .rel.removed .s { text-decoration: line-through; text-decoration-color: var(--kgdiff-text-3); color: var(--kgdiff-text-2); }
548
506
  .nodes { display: grid; gap: 2px; }
549
507
  .node-link { display: flex; align-items: center; gap: 8px; width: calc(100% + 16px); margin: 0 -8px; padding: 5px 8px; border-radius: 7px; text-align: left; font-size: 12.5px; }
550
- .node-link:hover { background: var(--kg-hover); }
551
- .node-link[aria-current="true"] { background: var(--kg-hover); box-shadow: inset 0 0 0 1px var(--kg-border-strong); }
508
+ .node-link:hover { background: var(--kgdiff-hover); }
509
+ .node-link[aria-current="true"] { background: var(--kgdiff-hover); box-shadow: inset 0 0 0 1px var(--kgdiff-border-strong); }
552
510
  .node-link .sdot { width: 8px; height: 8px; border-radius: 50%; flex: none; background: var(--fam-base); }
553
511
  .node-link .lbl { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 500; }
554
- .node-link .meta { flex: none; color: var(--kg-text-3); font-size: 11.5px; }
512
+ .node-link .meta { flex: none; color: var(--kgdiff-text-3); font-size: 11.5px; }
555
513
  .comp { display: grid; gap: 6px; }
556
514
  .comp-row { display: flex; align-items: center; gap: 8px; font-size: 12.5px; flex-wrap: wrap; }
557
- .comp-row .arrow { color: var(--kg-text-3); }
558
- .comp-row .note { color: var(--kg-text-3); font-size: 11.5px; }
515
+ .comp-row .arrow { color: var(--kgdiff-text-3); }
516
+ .comp-row .note { color: var(--kgdiff-text-3); font-size: 11.5px; }
559
517
  .bars { display: grid; gap: 6px; }
560
518
  .bar-row { display: grid; grid-template-columns: 84px minmax(0, 1fr) 40px; align-items: center; gap: 10px; font-size: 12px; }
561
- .bar-row .lbl { color: var(--kg-text-2); }
562
- .bar-row .track { height: 6px; border-radius: 3px; background: var(--kg-track); overflow: hidden; }
563
- .bar-row .fill { height: 100%; border-radius: 3px; background: var(--kg-identity); }
564
- .bar-row .v { text-align: right; color: var(--kg-text-2); font-variant-numeric: tabular-nums; }
565
- .note-line { font-size: 12px; color: var(--kg-text-3); margin-top: 6px; }
519
+ .bar-row .lbl { color: var(--kgdiff-text-2); }
520
+ .bar-row .track { height: 6px; border-radius: 3px; background: var(--kgdiff-track); overflow: hidden; }
521
+ .bar-row .fill { height: 100%; border-radius: 3px; background: var(--kgdiff-identity); }
522
+ .bar-row .v { text-align: right; color: var(--kgdiff-text-2); font-variant-numeric: tabular-nums; }
523
+ .note-line { font-size: 12px; color: var(--kgdiff-text-3); margin-top: 6px; }
566
524
 
567
525
  /* ── Popovers ────────────────────────────────────────────────────────────── */
568
526
  .menu {
569
- position: absolute; z-index: 10; top: 48px; right: 10px; width: 240px; padding: 6px; border-radius: 12px;
570
- animation: pop var(--kg-fast) var(--kg-ease);
527
+ position: absolute; z-index: 10; top: calc(100% + 8px); right: 0; width: 240px; padding: 6px; border-radius: 12px;
528
+ animation: pop var(--kgdiff-fast) var(--kgdiff-ease);
571
529
  }
572
530
  @keyframes pop { from { opacity: 0; transform: translateY(-4px) scale(0.98); } }
573
- .menu-group + .menu-group { margin-top: 4px; padding-top: 4px; border-top: 1px solid var(--kg-border); }
574
- .menu-label { padding: 6px 8px 4px; font-size: 11px; font-weight: 650; letter-spacing: 0.06em; text-transform: uppercase; color: var(--kg-text-3); }
575
- .menu-item { display: flex; align-items: center; gap: 8px; width: 100%; height: 32px; padding: 0 8px; border-radius: 7px; font-size: 13px; color: var(--kg-text); text-align: left; }
576
- .menu-item:hover, .menu-item:focus-visible { background: var(--kg-hover); outline: none; }
577
- .menu-item .icon { color: var(--kg-text-2); }
578
- .menu-item .check { margin-left: auto; color: var(--kg-accent-text); opacity: 0; }
531
+ .menu-group + .menu-group { margin-top: 4px; padding-top: 4px; border-top: 1px solid var(--kgdiff-border); }
532
+ .menu-label { padding: 6px 8px 4px; font-size: 11px; font-weight: 650; letter-spacing: 0.06em; text-transform: uppercase; color: var(--kgdiff-text-3); }
533
+ .menu-item { display: flex; align-items: center; gap: 8px; width: 100%; height: 32px; padding: 0 8px; border-radius: 7px; font-size: 13px; color: var(--kgdiff-text); text-align: left; }
534
+ .menu-item:hover, .menu-item:focus-visible { background: var(--kgdiff-hover); outline: none; }
535
+ .menu-item .icon { color: var(--kgdiff-text-2); }
536
+ .menu-item .check { margin-left: auto; color: var(--kgdiff-accent-text); opacity: 0; }
579
537
  .menu-item[aria-checked="true"] .check { opacity: 1; }
580
538
  .menu-item .sw { display: inline-flex; gap: 2px; }
581
539
  .menu-item .sw i { width: 6px; height: 6px; border-radius: 50%; display: block; }
582
540
 
583
541
  .overlay-scrim {
584
542
  position: absolute; inset: 0; z-index: 20; display: flex; align-items: center; justify-content: center; padding: 24px;
585
- background: var(--kg-scrim); animation: fade var(--kg-fast) var(--kg-ease);
543
+ background: var(--kgdiff-scrim); animation: fade var(--kgdiff-fast) var(--kgdiff-ease);
586
544
  }
587
545
  @keyframes fade { from { opacity: 0; } }
588
- .dialog { width: min(640px, 100%); max-height: 100%; display: flex; flex-direction: column; border-radius: 14px; animation: pop var(--kg-base) var(--kg-ease); }
546
+ .dialog { width: min(640px, 100%); max-height: 100%; display: flex; flex-direction: column; border-radius: 14px; animation: pop var(--kgdiff-base) var(--kgdiff-ease); }
589
547
  .dialog-head { display: flex; align-items: center; gap: 10px; padding: 14px 12px 10px 20px; }
590
548
  .dialog-head h2 { margin: 0; font-size: 15px; font-weight: 650; }
591
549
  .dialog-head .icon-btn { margin-left: auto; }
592
550
  .dialog-body { padding: 0 20px 18px; }
593
551
  .keys { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 24px; }
594
- .key-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; min-height: 34px; border-bottom: 1px solid var(--kg-border); font-size: 12.5px; color: var(--kg-text-2); }
595
- .key-row .ks { display: inline-flex; align-items: center; gap: 3px; flex: none; color: var(--kg-text-3); font-size: 11px; }
552
+ .key-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; min-height: 34px; border-bottom: 1px solid var(--kgdiff-border); font-size: 12.5px; color: var(--kgdiff-text-2); }
553
+ .key-row .ks { display: inline-flex; align-items: center; gap: 3px; flex: none; color: var(--kgdiff-text-3); font-size: 11px; }
596
554
 
597
555
  /* ── chrome="none": the graph, its hover tooltip and the legend line only ──── */
598
- .root[data-chrome="none"] .header, .root[data-chrome="none"] .sidebar, .root[data-chrome="none"] .caption,
599
- .root[data-chrome="none"] .transport, .root[data-chrome="none"] .finished, .root[data-chrome="none"] .stepper,
556
+ .root[data-chrome="none"] .hud, .root[data-chrome="none"] .sidebar, .root[data-chrome="none"] .dock,
600
557
  .root[data-chrome="none"] .map-cluster, .root[data-chrome="none"] .side-chip { display: none !important; }
601
558
  .stage-wrap[data-selectable="false"] .tooltip .t-hint { display: none; }
602
559
 
603
560
  /* ── Compact (< 760 px): bottom sheet ────────────────────────────────────── */
604
561
  .root[data-compact="true"] .body { flex-direction: column; }
605
562
  .root[data-compact="true"] .sidebar {
606
- width: auto; height: var(--sheet-h, 40%); min-height: 0; border-left: 0; border-top: 1px solid var(--kg-border);
563
+ width: auto; height: var(--sheet-h, 40%); min-height: 0; border-left: 0; border-top: 1px solid var(--kgdiff-border);
607
564
  border-radius: 14px 14px 0 0; margin-top: -14px; box-shadow: 0 -8px 24px rgba(0,0,0,0.18);
608
- transition: height var(--kg-base) var(--kg-ease);
565
+ transition: height var(--kgdiff-base) var(--kgdiff-ease);
609
566
  }
610
567
  .root[data-compact="true"] .sidebar.dragging { transition: none; }
611
568
  .root[data-compact="true"] .sidebar[data-open="false"] { height: 0; border-top-color: transparent; box-shadow: none; }
@@ -613,22 +570,19 @@ ins.hl { text-decoration: none; background: var(--kg-added-soft); color: var(--k
613
570
  .root[data-compact="true"] .sheet-handle {
614
571
  display: flex; flex: none; justify-content: center; align-items: center; height: 28px; cursor: ns-resize; touch-action: none; border-radius: 14px 14px 0 0;
615
572
  }
616
- .root[data-compact="true"] .sheet-handle::before { content: ""; width: 36px; height: 4px; border-radius: 2px; background: var(--kg-control-border); }
573
+ .root[data-compact="true"] .sheet-handle::before { content: ""; width: 36px; height: 4px; border-radius: 2px; background: var(--kgdiff-control-border); }
617
574
  .root[data-compact="true"] .sb-head { padding-top: 4px; }
618
- .root[data-compact="true"] .seg .lbl { display: none; }
619
- .root[data-compact="true"] .seg { padding: 0 9px; }
620
- .root[data-compact="true"] .versions, .root[data-compact="true"] .header-sep, .root[data-compact="true"] .stats,
575
+ .root[data-compact="true"] .versions, .root[data-compact="true"] .header-sep,
621
576
  .root[data-compact="true"] .brand-name { display: none; }
622
- .root[data-compact="true"] .header-center { flex: 1; justify-content: flex-start; }
623
- .root[data-compact="true"] .header-end { flex: none; }
577
+ .root[data-compact="true"] .hud-title { padding: 0 10px; }
624
578
  .root[data-compact="true"] .minimap-host, .root[data-compact="true"] .legend { display: none; }
625
- /* Zoom controls move to the top-right corner, clear of the full-width replay transport. */
626
- .root[data-compact="true"] .map-cluster { top: 52px; bottom: auto; right: 12px; }
627
- .root[data-compact="true"] .transport { bottom: 24px; width: calc(100% - 24px); min-width: 0; }
579
+ /* Zoom controls move under the actions, clear of the full-width replay transport. */
580
+ .root[data-compact="true"] .map-cluster { top: 64px; bottom: auto; right: 12px; }
581
+ /* The bottom sheet's rounded top overlaps the canvas. */
582
+ .root[data-compact="true"] .chrome > .dock { left: 12px; right: 12px; bottom: 26px; }
583
+ .root[data-compact="true"] .transport { width: 100%; min-width: 0; }
628
584
  .root[data-compact="true"] .transport .pos { min-width: 48px; }
629
585
  .root[data-compact="true"] .detail { max-height: 50%; }
630
- .root[data-compact="true"] .caption { max-width: calc(100% - 24px); }
631
- .root[data-narrow="true"] .stats { display: none; }
632
586
  .root[data-narrow="true"] .versions .tag, .root[data-narrow="true"] .versions .arrow { display: none; }
633
587
 
634
588
  @media (prefers-reduced-motion: reduce) {
@@ -636,4 +590,25 @@ ins.hl { text-decoration: none; background: var(--kg-added-soft); color: var(--k
636
590
  .skeleton-grid, .shimmer { animation: none; }
637
591
  }
638
592
  `;
593
+ /**
594
+ * A stylesheet of `doc` holding `css`. A constructed sheet can only be adopted in the document
595
+ * it was made for, so it is made with that document's own `CSSStyleSheet` (a viewer moved into
596
+ * an iframe or a popup gets sheets of its new document).
597
+ */
598
+ export function sheetFor(doc, css) {
599
+ const Sheet = doc.defaultView?.CSSStyleSheet;
600
+ const sheet = new (Sheet ?? CSSStyleSheet)();
601
+ sheet.replaceSync(css);
602
+ return sheet;
603
+ }
604
+ const shared = new WeakMap();
605
+ /** `STYLES` as a stylesheet of `doc`, parsed once per document. */
606
+ export function stylesheet(doc) {
607
+ let sheet = shared.get(doc);
608
+ if (!sheet) {
609
+ sheet = sheetFor(doc, STYLES);
610
+ shared.set(doc, sheet);
611
+ }
612
+ return sheet;
613
+ }
639
614
  //# sourceMappingURL=styles.js.map