@gotcos/glasses-server 6.98.1 → 6.99.16

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 (98) hide show
  1. package/CHANGELOG.md +227 -0
  2. package/package.json +2 -1
  3. package/server/index.ts +170 -11
  4. package/server/lib/api-auth.ts +31 -14
  5. package/server/lib/claude-bridge.ts +21 -2
  6. package/server/lib/codex-bridge.ts +21 -2
  7. package/server/lib/cos-thread.ts +582 -0
  8. package/server/lib/display-bus.ts +3 -0
  9. package/server/lib/drop-attachments.ts +55 -0
  10. package/server/lib/drop-destinations.ts +134 -0
  11. package/server/lib/drop-history-search.ts +97 -0
  12. package/server/lib/drop-p2-boot.ts +60 -0
  13. package/server/lib/drop-p2-runtime.ts +237 -0
  14. package/server/lib/drop-p2-settings.ts +174 -0
  15. package/server/lib/drop-resolution.ts +168 -0
  16. package/server/lib/drop-router.ts +325 -0
  17. package/server/lib/drop-service.ts +830 -0
  18. package/server/lib/drop-settings.ts +56 -0
  19. package/server/lib/drop-store.ts +450 -0
  20. package/server/lib/drop-when.ts +265 -0
  21. package/server/lib/glasses-pairing.ts +15 -0
  22. package/server/lib/learning-needs-you.ts +111 -0
  23. package/server/lib/live-cues-v2-settings.ts +2 -1
  24. package/server/lib/live-cues-v2.ts +6 -4
  25. package/server/lib/media-store.ts +80 -0
  26. package/server/lib/meeting-batch-transcribe.ts +15 -2
  27. package/server/lib/meeting-consolidation-run.ts +169 -0
  28. package/server/lib/meeting-store.ts +61 -0
  29. package/server/lib/meeting-title-steer.ts +200 -0
  30. package/server/lib/network-policy.ts +84 -6
  31. package/server/lib/permission-broker.ts +13 -0
  32. package/server/lib/phone-recording.ts +1 -1
  33. package/server/lib/ping-budget.ts +149 -0
  34. package/server/lib/ping-engine.ts +245 -0
  35. package/server/lib/ping-feed-sink.ts +33 -0
  36. package/server/lib/ping-sources.ts +192 -0
  37. package/server/lib/query-job-coordinator.ts +5 -2
  38. package/server/lib/query-job-runtime.ts +45 -4
  39. package/server/lib/query-job-types.ts +10 -1
  40. package/server/lib/reminder-scheduler.ts +153 -0
  41. package/server/lib/tailnet-self-name.ts +103 -0
  42. package/server/lib/tailscale-nudge.ts +40 -2
  43. package/server/lib/task-store.ts +32 -0
  44. package/server/lib/web-ask-admission.ts +56 -0
  45. package/server/lib/web-live-chunks.ts +273 -0
  46. package/server/lib/web-memories-bridge.ts +323 -0
  47. package/server/lib/web-session-auth.ts +492 -0
  48. package/server/lib/web-usage-bridge.ts +154 -0
  49. package/server/lib/work-search.ts +14 -1
  50. package/server/lib/your-move-count.ts +58 -0
  51. package/server/routes/cos-thread.ts +79 -0
  52. package/server/routes/display.ts +11 -1
  53. package/server/routes/drops.ts +262 -0
  54. package/server/routes/health.ts +16 -0
  55. package/server/routes/live-cues.ts +5 -4
  56. package/server/routes/meeting.ts +61 -5
  57. package/server/routes/permission-broker.ts +23 -3
  58. package/server/routes/transcribe-stream.ts +43 -4
  59. package/server/routes/web-control.ts +569 -0
  60. package/server/routes/welcome-context.ts +2 -1
  61. package/server/scripts/web-live-cls/cdp.mjs +57 -0
  62. package/server/scripts/web-live-cls/measure.mjs +80 -0
  63. package/server/scripts/web-live-cls/mock.mjs +97 -0
  64. package/server/scripts/web-live-cls/render.mjs +26 -0
  65. package/server/web-control/app.css +519 -0
  66. package/server/web-control/app.js +3643 -0
  67. package/server/web-control/control.css +325 -0
  68. package/server/web-control/fonts/DMSans.ttf +0 -0
  69. package/server/web-control/fonts/Fraunces.ttf +0 -0
  70. package/server/web-control/fonts/JetBrainsMono.ttf +0 -0
  71. package/server/web-control/index.html +275 -0
  72. package/server/web-control/mark.svg +1 -0
  73. package/server/web-control/memories/d3.min.js +2 -0
  74. package/server/web-control/memories/graph-explorer.css +200 -0
  75. package/server/web-control/memories/graph-explorer.js +748 -0
  76. package/server/web-control/memories/memories-app.js +1561 -0
  77. package/server/web-control/memories/memories-theme.css +73 -0
  78. package/server/web-control/memories/memories.html +72 -0
  79. package/server/web-control/memories/memory-stewardship.js +63 -0
  80. package/server/web-control/memories/memory-workspace.js +216 -0
  81. package/server/web-control/panes/cos-chat.css +174 -0
  82. package/server/web-control/panes/cos-chat.js +1118 -0
  83. package/server/web-control/panes/dictation.js +173 -0
  84. package/server/web-control/panes/meetings.css +314 -0
  85. package/server/web-control/panes/meetings.js +2568 -0
  86. package/server/web-control/panes/messages.js +718 -0
  87. package/server/web-control/panes/questions.css +32 -0
  88. package/server/web-control/panes/questions.js +275 -0
  89. package/server/web-control/panes/sessions.css +452 -0
  90. package/server/web-control/panes/settings.js +292 -0
  91. package/server/web-control/panes/speakers.css +269 -0
  92. package/server/web-control/panes/speakers.js +2755 -0
  93. package/server/web-control/panes/threads.js +200 -0
  94. package/server/web-control/panes/work.css +261 -0
  95. package/server/web-control/panes/work.js +1667 -0
  96. package/server/web-control/shell.js +294 -0
  97. package/server/web-control/theme.js +25 -0
  98. package/server/web-control/vendor/qrcode-encoder.js +10 -0
@@ -0,0 +1,200 @@
1
+ /* COS Knowledge graph explorer. Port of operations/scripts/lightrag_d3_template.html
2
+ into the COS Control palette. Scoped under .cgx so it can live inside the Memories pane. */
3
+ .cgx{--cgx-bg:var(--graph-bg,#14100c);--cgx-card:var(--card,#261d16);--cgx-raised:var(--raised,#30271f);--cgx-fg:var(--fg,#f5f0e6);--cgx-muted:var(--muted,#bbae9a);--cgx-line:var(--line,#473a2c);--cgx-gold:var(--accent,#c9a86e);--cgx-green:var(--green,#92c6a1);--cgx-red:var(--red,#e8a494);--cgx-height:520px;
4
+ position:relative;color:var(--cgx-fg);font:12.5px/1.5 var(--body,'DM Sans',system-ui,sans-serif)}
5
+ .cgx *{box-sizing:border-box}
6
+ .cgx button{font:inherit;color:inherit;cursor:pointer}
7
+ .cgx button:disabled{cursor:default;opacity:.45}
8
+ .cgx button:focus-visible,.cgx input:focus-visible,.cgx [tabindex]:focus-visible{outline:2px solid var(--cgx-gold);outline-offset:2px}
9
+
10
+ /* Toolbar (in flow, above the stage) */
11
+ .cgx-bar{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:0 0 10px}
12
+ .cgx-scope{display:inline-flex;align-items:center;gap:7px;padding:5px 11px;border-radius:999px;border:1px solid var(--cgx-line);background:var(--cgx-card);font-size:11px;color:var(--cgx-muted)}
13
+ .cgx-scope b{color:var(--cgx-fg);font-weight:600}
14
+ .cgx-scope i{width:7px;height:7px;border-radius:50%;background:var(--cgx-green);display:inline-block}
15
+ .cgx-scope.example i{background:var(--cgx-gold)}
16
+ .cgx-scope.off i{background:var(--cgx-red)}
17
+ .cgx-fresh{font-size:11px;color:var(--cgx-muted)}
18
+ .cgx-fresh b{color:var(--cgx-fg);font-weight:500}
19
+ .cgx-search{position:relative;margin-left:auto;min-width:220px;flex:0 1 300px}
20
+ .cgx-search input{width:100%;height:32px;padding:0 34px 0 30px;border-radius:9px;border:1px solid var(--cgx-line);background:var(--cgx-card);color:var(--cgx-fg);font:inherit;font-size:12px;transition:border-color .2s,box-shadow .2s}
21
+ .cgx-search input::placeholder{color:var(--cgx-muted)}
22
+ .cgx-search input:focus{border-color:var(--cgx-gold);box-shadow:0 0 0 3px rgba(201,168,110,.14);outline:none}
23
+ .cgx-search .ico{position:absolute;left:10px;top:50%;transform:translateY(-50%);color:var(--cgx-muted);font-size:12px;pointer-events:none}
24
+ .cgx-search kbd{position:absolute;right:9px;top:50%;transform:translateY(-50%);font:10px/1 ui-monospace,Menlo,monospace;color:var(--cgx-muted);border:1px solid var(--cgx-line);border-radius:5px;padding:2px 6px;background:var(--cgx-raised);pointer-events:none}
25
+ .cgx-results{position:absolute;top:38px;left:0;right:0;z-index:40;background:var(--cgx-card);border:1px solid var(--cgx-gold);border-radius:10px;max-height:280px;overflow:auto;display:none;box-shadow:0 16px 40px rgba(0,0,0,.5)}
26
+ .cgx-results.on{display:block}
27
+ .cgx-result{display:flex;align-items:center;gap:9px;width:100%;text-align:left;padding:8px 12px;border:0;background:none;border-bottom:1px solid rgba(255,255,255,.04);font-size:12px}
28
+ .cgx-result:last-child{border-bottom:0}
29
+ .cgx-result:hover,.cgx-result.kbd{background:rgba(201,168,110,.12)}
30
+ .cgx-result .dot{width:8px;height:8px;border-radius:50%;flex-shrink:0;box-shadow:0 0 6px currentColor}
31
+ .cgx-result .nm{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:500}
32
+ .cgx-result .ty{margin-left:auto;font-size:9.5px;text-transform:uppercase;letter-spacing:.08em;color:var(--cgx-muted);flex-shrink:0}
33
+
34
+ /* Stage */
35
+ .cgx-stage{position:relative;height:var(--cgx-height);min-height:380px;border:1px solid var(--cgx-line);border-radius:14px;overflow:hidden;
36
+ background:radial-gradient(ellipse 70% 60% at 50% 45%,rgba(201,168,110,.075),transparent 62%),radial-gradient(circle at 85% 85%,rgba(146,198,161,.04),transparent 40%),var(--cgx-bg)}
37
+ .cgx-stage svg.cgx-canvas{position:absolute;inset:0;width:100%;height:100%;display:block;cursor:grab}
38
+ .cgx-stage svg.cgx-canvas:active{cursor:grabbing}
39
+ .cgx-stage text.nl{pointer-events:none;font-family:var(--body,'DM Sans',system-ui,sans-serif);paint-order:stroke;stroke:var(--cgx-bg);stroke-width:3px;stroke-linejoin:round}
40
+ .cgx-stage .edge.flow{stroke-dasharray:7 9;animation:cgxflow 1.05s linear infinite}
41
+ @keyframes cgxflow{to{stroke-dashoffset:-16}}
42
+ .cgx-stage .orbit{animation:cgxorbit 60s linear infinite}
43
+ @keyframes cgxorbit{to{stroke-dashoffset:-600}}
44
+ .cgx-stage .fresh-ring{animation:cgxfresh 2.2s ease-in-out infinite}
45
+ @keyframes cgxfresh{0%,100%{stroke-opacity:.18;stroke-width:1.5}50%{stroke-opacity:.7;stroke-width:2.5}}
46
+ .cgx-stage .focusable:focus{outline:none}
47
+
48
+ /* States */
49
+ .cgx-state{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;text-align:center;padding:28px;z-index:5}
50
+ .cgx-state>div{max-width:420px}
51
+ .cgx-state h3{margin:0 0 6px;font:600 16px/1.3 var(--display,'Fraunces',Georgia,serif);color:var(--cgx-fg)}
52
+ .cgx-state p{margin:0 0 12px;color:var(--cgx-muted);font-size:12px}
53
+ .cgx-state .cgx-btn{margin:0 4px}
54
+ .cgx-spin{width:22px;height:22px;border-radius:50%;border:2px solid var(--cgx-line);border-top-color:var(--cgx-gold);margin:0 auto 12px;animation:cgxspin .9s linear infinite}
55
+ @keyframes cgxspin{to{transform:rotate(360deg)}}
56
+
57
+ /* Pinned bar */
58
+ .cgx-pinned{position:absolute;top:0;left:0;right:0;z-index:20;display:none;align-items:center;gap:10px;padding:6px 14px;font-size:11px;color:var(--cgx-muted);background:rgba(201,168,110,.08);border-bottom:1px solid rgba(201,168,110,.22);backdrop-filter:blur(8px)}
59
+ .cgx-pinned.on{display:flex}
60
+ .cgx-pinned .lbl{font-size:9.5px;letter-spacing:.12em;text-transform:uppercase;color:var(--cgx-gold)}
61
+ .cgx-pinned .nms{color:var(--cgx-fg);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;flex:1}
62
+
63
+ /* Control rail (bottom-left overlay) */
64
+ .cgx-rail{position:absolute;left:12px;bottom:12px;z-index:15;width:200px;display:flex;flex-direction:column;gap:7px;max-height:calc(100% - 24px);overflow:auto;scrollbar-width:thin}
65
+ .cgx-panel{isolation:isolate;background:var(--cgx-card);border:1px solid var(--cgx-line);border-radius:12px;padding:9px 11px 10px;backdrop-filter:none;-webkit-backdrop-filter:none;box-shadow:0 6px 18px rgba(16,12,9,.16)}
66
+ .cgx-panel-t,.cgx-leg,.cgx-keys{text-shadow:none;filter:none;-webkit-font-smoothing:antialiased}
67
+ .cgx-panel-t{display:flex;align-items:center;justify-content:space-between;font:600 9px/1 ui-monospace,Menlo,monospace;letter-spacing:.16em;text-transform:uppercase;color:var(--cgx-muted);margin-bottom:8px}
68
+ .cgx-panel-t button{border:0;background:none;color:var(--cgx-muted);font-size:10px;padding:0}
69
+ .cgx-row{display:flex;gap:5px;flex-wrap:wrap}
70
+ .cgx-btn{padding:4px 10px;border-radius:7px;border:1px solid var(--cgx-line);background:transparent;color:var(--cgx-muted);font-size:10px;font-weight:600;letter-spacing:.04em;transition:all .18s}
71
+ .cgx-btn:hover:not(:disabled){border-color:var(--cgx-gold);color:var(--cgx-fg)}
72
+ .cgx-btn.on{background:rgba(201,168,110,.16);border-color:var(--cgx-gold);color:var(--cgx-fg)}
73
+ .cgx-btn.primary{background:var(--cgx-gold);border-color:var(--cgx-gold);color:#17120d}
74
+ .cgx-btn.primary:hover:not(:disabled){background:#d8bb86}
75
+ .cgx-slider{display:flex;align-items:center;gap:8px}
76
+ .cgx-slider input[type=range]{flex:1;-webkit-appearance:none;appearance:none;height:3px;background:rgba(201,168,110,.25);border-radius:2px;outline:none}
77
+ .cgx-slider input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;width:12px;height:12px;border-radius:50%;background:var(--cgx-gold);border:2px solid var(--cgx-bg);cursor:pointer;box-shadow:0 0 8px rgba(201,168,110,.5)}
78
+ .cgx-slider .val{font:10px/1 ui-monospace,Menlo,monospace;color:var(--cgx-muted);min-width:18px;text-align:right}
79
+ .cgx-legend{display:flex;flex-direction:column;gap:1px;max-height:170px;overflow:auto;scrollbar-width:thin}
80
+ .cgx-leg{display:flex;align-items:center;gap:8px;padding:3px 6px;margin:0 -6px;border-radius:6px;border:0;background:none;text-align:left;font-size:11px;color:var(--cgx-muted);transition:background .15s}
81
+ .cgx-leg:hover{background:rgba(255,255,255,.04)}
82
+ .cgx-leg.on{color:var(--cgx-fg);background:rgba(201,168,110,.14)}
83
+ .cgx-leg .dot{width:8px;height:8px;border-radius:50%;flex-shrink:0;box-shadow:0 0 7px currentColor}
84
+ .cgx-leg .nm{text-transform:capitalize;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
85
+ .cgx-leg .ct{margin-left:auto;font:10px/1 ui-monospace,Menlo,monospace;color:var(--cgx-muted)}
86
+ .cgx-leg.on .ct{color:var(--cgx-gold)}
87
+ .cgx-keys{font-size:10px;color:var(--cgx-muted);line-height:2}
88
+ .cgx-keys kbd{display:inline-block;min-width:18px;text-align:center;padding:1px 5px;margin-right:3px;border:1px solid var(--cgx-line);border-radius:4px;background:rgba(201,168,110,.08);font:9.5px/1.4 ui-monospace,Menlo,monospace;color:var(--cgx-gold)}
89
+ .cgx-rail.collapsed .cgx-panel:not(.keep){display:none}
90
+ .cgx-railtoggle{position:absolute;left:12px;bottom:12px;z-index:16;display:none}
91
+ .cgx--narrow .cgx-rail{width:176px}.cgx--narrow .cgx-stage{--cgx-height:440px}.cgx--narrow .cgx-hint{display:none}
92
+
93
+ /* Inspector (right overlay) */
94
+ .cgx-body{position:relative}
95
+ .cgx-dp{position:absolute;top:12px;right:12px;bottom:12px;width:312px;z-index:25;display:none;flex-direction:column;background:var(--cgx-card);border:1px solid var(--cgx-line);border-radius:14px;overflow:hidden;box-shadow:0 18px 50px rgba(0,0,0,.55);backdrop-filter:blur(18px) saturate(1.1)}
96
+ .cgx-dp.on{display:flex;animation:cgxdp .26s cubic-bezier(.34,1.3,.5,1)}
97
+ @keyframes cgxdp{from{opacity:0;transform:translateX(14px) scale(.985)}to{opacity:1;transform:none}}
98
+ .cgx-dp-accent{height:3px;flex-shrink:0}
99
+ .cgx-dp-hd{padding:13px 16px 11px;border-bottom:1px solid var(--cgx-line);position:relative;flex-shrink:0}
100
+ .cgx-dp-nm{font:600 18px/1.2 var(--display,'Fraunces',Georgia,serif);letter-spacing:-.01em;padding-right:34px;margin-bottom:8px;overflow-wrap:anywhere}
101
+ .cgx-dp-meta{display:flex;align-items:center;gap:9px;flex-wrap:wrap;font-size:11px;color:var(--cgx-muted)}
102
+ .cgx-tb{display:inline-flex;align-items:center;gap:5px;padding:3px 9px;border-radius:999px;font:600 9px/1 ui-monospace,Menlo,monospace;letter-spacing:.12em;text-transform:uppercase}
103
+ .cgx-tb i{width:6px;height:6px;border-radius:50%}
104
+ .cgx-dp-meta b{color:var(--cgx-fg);font-weight:600}
105
+ .cgx-dp-meta .fresh.new{color:var(--cgx-green)}
106
+ .cgx-meter{margin-top:10px;height:3px;border-radius:2px;background:rgba(255,255,255,.07);overflow:hidden}
107
+ .cgx-meter i{display:block;height:100%;border-radius:2px;transition:width .5s cubic-bezier(.4,0,.2,1)}
108
+ .cgx-dp-x{position:absolute;top:11px;right:11px;width:26px;height:26px;border-radius:7px;border:1px solid var(--cgx-line);background:rgba(255,255,255,.04);color:var(--cgx-muted);font-size:15px;line-height:1;display:flex;align-items:center;justify-content:center;transition:all .15s}
109
+ .cgx-dp-x:hover{color:var(--cgx-red);border-color:rgba(232,164,148,.4);background:rgba(232,164,148,.1)}
110
+ .cgx-dp-bd{padding:12px 16px 16px;overflow:auto;scrollbar-width:thin;font-size:12px;line-height:1.55;color:var(--cgx-muted);flex:1}
111
+ .cgx-sec{font:600 9px/1 ui-monospace,Menlo,monospace;letter-spacing:.16em;text-transform:uppercase;color:var(--cgx-muted);margin:14px 0 7px}
112
+ .cgx-sec:first-child{margin-top:0}
113
+ .cgx-fact{position:relative;padding-left:13px;margin-bottom:6px;color:var(--cgx-fg)}
114
+ .cgx-fact::before{content:'';position:absolute;left:0;top:8px;width:5px;height:5px;border-radius:50%;background:var(--cgx-gold);opacity:.6}
115
+ .cgx-rel{display:block;width:100%;text-align:left;padding:7px 9px;margin:0 -9px 3px;border:0;border-radius:8px;background:none;transition:background .15s}
116
+ .cgx-rel:hover{background:rgba(255,255,255,.045)}
117
+ .cgx-rel-top{display:flex;align-items:center;gap:8px}
118
+ .cgx-rel-nm{font-weight:600;font-size:12px;color:var(--cgx-fg);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
119
+ .cgx-rel-w{margin-left:auto;display:flex;align-items:center;gap:6px;flex-shrink:0}
120
+ .cgx-rel-bar{width:40px;height:3px;border-radius:2px;background:rgba(255,255,255,.08);overflow:hidden}
121
+ .cgx-rel-bar i{display:block;height:100%;border-radius:2px}
122
+ .cgx-rel-wv{font:9.5px/1 ui-monospace,Menlo,monospace;color:var(--cgx-muted)}
123
+ .cgx-rel-d{font-size:11px;color:var(--cgx-muted);line-height:1.45;margin-top:3px}
124
+ .cgx-tags{display:flex;flex-wrap:wrap;gap:5px;margin-top:6px}
125
+ .cgx-tag{padding:3px 9px;border-radius:999px;font-size:10.5px;font-weight:500;background:rgba(255,255,255,.04);border:1px solid var(--cgx-line);color:var(--cgx-muted);transition:all .15s}
126
+ .cgx-tag:hover{color:var(--cgx-fg);border-color:var(--cgx-gold);background:rgba(201,168,110,.12)}
127
+ .cgx-chain{display:flex;flex-wrap:wrap;align-items:center;gap:6px}
128
+ .cgx-step{padding:4px 10px;border-radius:999px;font-size:11px;font-weight:600;background:rgba(201,168,110,.1);border:1px solid rgba(201,168,110,.35);color:var(--cgx-gold)}
129
+ .cgx-arrow{color:var(--cgx-muted);font-size:11px}
130
+ .cgx-dp-actions{display:flex;flex-wrap:wrap;gap:6px;padding:10px 16px 12px;border-top:1px solid var(--cgx-line);flex-shrink:0;background:rgba(0,0,0,.12)}
131
+ .cgx-note{font-size:10.5px;color:var(--cgx-muted);border:1px solid var(--cgx-line);border-radius:8px;padding:8px 10px;margin-top:12px;line-height:1.45}
132
+ .cgx--narrow .cgx-dp{position:relative;top:auto;right:auto;bottom:auto;width:auto;max-height:none;margin-top:10px;border-radius:12px;animation:none}
133
+ .cgx--narrow .cgx-dp-bd{max-height:360px}
134
+
135
+ /* Hover tip, toast, hint */
136
+ .cgx-tip{position:absolute;z-index:30;display:none;max-width:280px;padding:8px 12px;border-radius:9px;background:var(--cgx-card);border:1px solid var(--cgx-line);font-size:12px;color:var(--cgx-fg);pointer-events:none;box-shadow:0 8px 24px rgba(0,0,0,.45)}
137
+ .cgx-tip .top{display:flex;align-items:center;gap:7px;font-weight:600}
138
+ .cgx-tip .dot{width:7px;height:7px;border-radius:50%;flex-shrink:0;box-shadow:0 0 6px currentColor}
139
+ .cgx-tip .deg{margin-left:auto;font:9.5px/1 ui-monospace,Menlo,monospace;color:var(--cgx-muted);padding-left:10px}
140
+ .cgx-tip .desc{font-size:10.5px;color:var(--cgx-muted);line-height:1.45;margin-top:4px;font-weight:400;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
141
+ .cgx-hint{position:absolute;left:50%;bottom:14px;transform:translateX(-50%);z-index:12;font-size:10px;letter-spacing:.03em;color:var(--cgx-muted);background:rgba(20,16,12,.7);border:1px solid var(--cgx-line);border-radius:999px;padding:5px 14px;white-space:nowrap;transition:opacity 1s;pointer-events:none}
142
+ .cgx-hint b{color:var(--cgx-fg);font-weight:500}
143
+ .cgx-hint.hide{opacity:0}
144
+ .cgx-toast{position:absolute;left:50%;bottom:52px;transform:translateX(-50%) translateY(8px);z-index:45;font-size:12px;color:var(--cgx-fg);background:var(--cgx-card);border:1px solid var(--cgx-gold);border-radius:9px;padding:7px 16px;opacity:0;pointer-events:none;transition:all .25s;box-shadow:0 10px 30px rgba(0,0,0,.5)}
145
+ .cgx-toast.show{opacity:1;transform:translateX(-50%)}
146
+
147
+ /* Footer line under the stage */
148
+ .cgx-foot{display:flex;flex-wrap:wrap;gap:8px 16px;align-items:center;justify-content:space-between;margin-top:9px;font-size:10.5px;color:var(--cgx-muted)}
149
+ .cgx-foot b{color:var(--cgx-fg);font-weight:500}
150
+
151
+ @media (prefers-reduced-motion:reduce){
152
+ .cgx-stage .edge.flow,.cgx-stage .orbit,.cgx-stage .fresh-ring,.cgx-spin{animation:none}
153
+ .cgx-dp.on{animation:none}
154
+ }
155
+
156
+ /* Graph management (design mock, 2026-09-06): possible duplicates, review sheet, changes list */
157
+ .cgx-dup{padding:8px 9px;margin:0 -9px 6px;border:1px solid var(--cgx-line);border-radius:9px;background:rgba(255,255,255,.025)}
158
+ .cgx-dup-meta{font-size:10.5px;color:var(--cgx-muted);margin-top:3px}
159
+ .cgx-agree{display:inline-block;margin-top:5px;padding:2px 8px;border-radius:999px;font:600 9.5px/1.4 ui-monospace,Menlo,monospace;letter-spacing:.06em;text-transform:uppercase;border:1px solid var(--cgx-line);color:var(--cgx-muted)}
160
+ .cgx-agree.ok{color:var(--cgx-green);border-color:rgba(146,198,161,.4)}
161
+ .cgx-agree.warn{color:var(--cgx-red);border-color:rgba(232,164,148,.4)}
162
+ .cgx-sheet{position:absolute;inset:0;z-index:50;display:flex;align-items:center;justify-content:center;padding:18px;background:rgba(16,12,9,.72);backdrop-filter:blur(6px)}
163
+ .cgx-sheet-box{width:min(720px,100%);max-height:100%;overflow:auto;background:var(--cgx-card);border:1px solid var(--cgx-line);border-radius:14px;box-shadow:0 24px 70px rgba(0,0,0,.6)}
164
+ .cgx-sheet-hd{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:14px 18px 10px;border-bottom:1px solid var(--cgx-line)}
165
+ .cgx-sheet-hd h3{margin:0;font:600 18px/1.2 var(--display,'Fraunces',Georgia,serif);color:var(--cgx-fg)}
166
+ .cgx-sheet-bd{padding:14px 18px;font-size:12px;color:var(--cgx-muted)}
167
+ .cgx-sheet-bd p{margin:0 0 10px}
168
+ .cgx-cmp{display:grid;grid-template-columns:1fr 1fr;gap:12px}
169
+ .cgx-cmp-col{border:1px solid var(--cgx-line);border-radius:10px;padding:10px 12px;background:rgba(255,255,255,.025)}
170
+ .cgx-cmp-col.keep{border-color:rgba(201,168,110,.55);background:rgba(201,168,110,.07)}
171
+ .cgx-cmp-col h4{margin:0 0 4px;font-size:13px;color:var(--cgx-fg)}
172
+ .cgx-cmp-col .m{font-size:10.5px;color:var(--cgx-muted);margin-bottom:6px}
173
+ .cgx-cmp-col p{margin:4px 0;font-size:11.5px;color:var(--cgx-fg);line-height:1.45}
174
+ .cgx-cmp-col label{display:inline-flex;align-items:center;gap:6px;margin-top:8px;font-size:11px;color:var(--cgx-fg);cursor:pointer}
175
+ .cgx-effect{margin-top:12px;padding:10px 12px;border:1px solid var(--cgx-line);border-radius:10px;background:rgba(0,0,0,.15)}
176
+ .cgx-effect b{color:var(--cgx-fg);font-weight:600}
177
+ .cgx-effect ul{margin:6px 0 0;padding-left:18px}
178
+ .cgx-effect li{margin:2px 0;color:var(--cgx-fg)}
179
+ .cgx-rule{margin-top:12px;padding:10px 12px;border:1px solid var(--cgx-line);border-radius:10px}
180
+ .cgx-rule label{display:flex;align-items:center;gap:8px;color:var(--cgx-fg);font-size:12px;cursor:pointer}
181
+ .cgx-rule .fields{display:flex;gap:8px;flex-wrap:wrap;margin-top:8px;align-items:center}
182
+ .cgx-rule input,.cgx-rule select,.cgx-sheet-bd input[type=text],.cgx-sheet-bd input[type=search]{height:30px;padding:0 10px;border-radius:8px;border:1px solid var(--cgx-line);background:var(--cgx-bg);color:var(--cgx-fg);font:inherit;font-size:12px}
183
+ .cgx-sheet-bd input[type=text],.cgx-sheet-bd input[type=search]{width:100%}
184
+ .cgx-sheet-ft{display:flex;align-items:center;gap:8px;padding:12px 18px 14px;border-top:1px solid var(--cgx-line);flex-wrap:wrap}
185
+ .cgx-sheet-ft .grow{flex:1;font-size:10.5px;color:var(--cgx-muted);min-width:200px}
186
+ .cgx-changes{margin-top:10px;border:1px solid var(--cgx-line);border-radius:10px;padding:8px 12px;font-size:11px;color:var(--cgx-muted);display:none}
187
+ .cgx-changes.on{display:block}
188
+ .cgx-changes .t{font:600 9px/1 ui-monospace,Menlo,monospace;letter-spacing:.16em;text-transform:uppercase;margin-bottom:6px;color:var(--cgx-muted)}
189
+ .cgx-change{display:flex;align-items:center;gap:10px;padding:5px 0;border-top:1px solid rgba(255,255,255,.05)}
190
+ .cgx-change:first-of-type{border-top:0}
191
+ .cgx-change .what{flex:1;color:var(--cgx-fg)}
192
+ .cgx-change .st{font:600 9px/1.4 ui-monospace,Menlo,monospace;letter-spacing:.08em;text-transform:uppercase;padding:2px 7px;border-radius:999px;border:1px solid var(--cgx-line);color:var(--cgx-muted)}
193
+ .cgx-change .st.applied{color:var(--cgx-green);border-color:rgba(146,198,161,.4)}
194
+ .cgx-change .st.queued{color:var(--cgx-gold);border-color:rgba(201,168,110,.5)}
195
+ .cgx-change.reverted .what{opacity:.5;text-decoration:line-through}
196
+ .cgx-pick{max-height:160px;overflow:auto;margin-top:8px;border:1px solid var(--cgx-line);border-radius:8px}
197
+ .cgx-pick button{display:flex;align-items:center;gap:8px;width:100%;text-align:left;padding:7px 10px;border:0;background:none;font-size:12px;color:var(--cgx-fg)}
198
+ .cgx-pick button:hover{background:rgba(201,168,110,.12)}
199
+ .cgx-pick .ty{margin-left:auto;font-size:9.5px;text-transform:uppercase;letter-spacing:.08em;color:var(--cgx-muted)}
200
+ @media (max-width:640px){.cgx-cmp{grid-template-columns:1fr}}