smoothie-code 1.1.0 → 1.2.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.
- package/README.md +39 -57
- package/auto-blend-hook.sh +41 -6
- package/bin/smoothie +211 -0
- package/config.json +3 -1
- package/dist/blend-cli.js +63 -10
- package/dist/index.js +59 -10
- package/dist/select-models.js +2 -0
- package/install.sh +118 -7
- package/package.json +11 -1
- package/pr-blend-hook.sh +39 -5
- package/banner-v2.svg +0 -307
- package/docs/banner.svg +0 -307
- package/docs/favicon.png +0 -0
- package/docs/favicon.svg +0 -17
- package/docs/index.html +0 -319
- package/icon.png +0 -0
- package/icon.svg +0 -17
- package/src/blend-cli.ts +0 -219
- package/src/index.ts +0 -367
- package/src/select-models.ts +0 -318
- package/tsconfig.json +0 -14
package/install.sh
CHANGED
|
@@ -11,7 +11,7 @@ B='\033[1m' # bold
|
|
|
11
11
|
N='\033[0m' # reset
|
|
12
12
|
|
|
13
13
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
14
|
-
TOTAL_STEPS=
|
|
14
|
+
TOTAL_STEPS=8
|
|
15
15
|
STEP=0
|
|
16
16
|
|
|
17
17
|
step() {
|
|
@@ -71,11 +71,13 @@ step "Detecting platform"
|
|
|
71
71
|
HAS_CLAUDE=$(command -v claude &>/dev/null && echo "yes" || echo "no")
|
|
72
72
|
HAS_CODEX=$(command -v codex &>/dev/null && echo "yes" || echo "no")
|
|
73
73
|
HAS_GEMINI=$(command -v gemini &>/dev/null && echo "yes" || echo "no")
|
|
74
|
+
HAS_CURSOR=$([ -d "$HOME/.cursor" ] && echo "yes" || echo "no")
|
|
74
75
|
|
|
75
76
|
DETECTED=()
|
|
76
77
|
[ "$HAS_CLAUDE" = "yes" ] && DETECTED+=("claude:Claude Code")
|
|
77
78
|
[ "$HAS_CODEX" = "yes" ] && DETECTED+=("codex:Codex CLI")
|
|
78
79
|
[ "$HAS_GEMINI" = "yes" ] && DETECTED+=("gemini:Gemini CLI")
|
|
80
|
+
[ "$HAS_CURSOR" = "yes" ] && DETECTED+=("cursor:Cursor")
|
|
79
81
|
|
|
80
82
|
if [ ${#DETECTED[@]} -eq 0 ]; then
|
|
81
83
|
echo -e " ${Y}No AI CLI detected. Defaulting to Claude Code.${N}"
|
|
@@ -176,7 +178,37 @@ else
|
|
|
176
178
|
echo -e " ${D}Skipped — toggle in config.json anytime${N}"
|
|
177
179
|
fi
|
|
178
180
|
|
|
179
|
-
# ─── Step 7:
|
|
181
|
+
# ─── Step 7: Leaderboard ─────────────────────────────────────────────
|
|
182
|
+
step "Leaderboard"
|
|
183
|
+
|
|
184
|
+
# Leaderboard opt-in
|
|
185
|
+
echo ""
|
|
186
|
+
echo -e " ${B}Leaderboard${N} — your GitHub username and token usage"
|
|
187
|
+
echo -e " appear on the public Smoothie rankings."
|
|
188
|
+
echo -e " ${D}https://smoothiecode.com/leaderboard${N}"
|
|
189
|
+
echo ""
|
|
190
|
+
read -p " Join the leaderboard? [Y/n]: " JOIN_LB
|
|
191
|
+
if [[ ! "$JOIN_LB" =~ ^[Nn]$ ]]; then
|
|
192
|
+
LB_GITHUB=$(git config user.name 2>/dev/null || echo "")
|
|
193
|
+
if [ -z "$LB_GITHUB" ]; then
|
|
194
|
+
read -p " GitHub username: " LB_GITHUB
|
|
195
|
+
else
|
|
196
|
+
read -p " GitHub username [$LB_GITHUB]: " INPUT_LB
|
|
197
|
+
LB_GITHUB="${INPUT_LB:-$LB_GITHUB}"
|
|
198
|
+
fi
|
|
199
|
+
node -e "
|
|
200
|
+
const fs = require('fs');
|
|
201
|
+
const c = JSON.parse(fs.readFileSync('$SCRIPT_DIR/config.json','utf8'));
|
|
202
|
+
c.leaderboard = true;
|
|
203
|
+
c.github = '$LB_GITHUB';
|
|
204
|
+
fs.writeFileSync('$SCRIPT_DIR/config.json', JSON.stringify(c, null, 2));
|
|
205
|
+
"
|
|
206
|
+
echo -e " ${G}✓${N} Joined as $LB_GITHUB"
|
|
207
|
+
else
|
|
208
|
+
echo -e " ${D}Skipped — join anytime: smoothie leaderboard join${N}"
|
|
209
|
+
fi
|
|
210
|
+
|
|
211
|
+
# ─── Step 8: Wire up ─────────────────────────────────────────────────
|
|
180
212
|
step "Wiring up"
|
|
181
213
|
|
|
182
214
|
if [ "$PLATFORM" = "claude" ]; then
|
|
@@ -354,6 +386,76 @@ Step 3 — Summarize findings with file:line references. Be direct.
|
|
|
354
386
|
"""
|
|
355
387
|
TOML
|
|
356
388
|
echo -e " ${G}✓${N} Slash command /smoothie-pr (Gemini)"
|
|
389
|
+
|
|
390
|
+
# Register auto-blend hook for Gemini CLI
|
|
391
|
+
chmod +x "$SCRIPT_DIR/gemini-blend-hook.sh"
|
|
392
|
+
GEMINI_SETTINGS="$HOME/.gemini/settings.json"
|
|
393
|
+
GEMINI_EXISTING="{}"
|
|
394
|
+
[ -f "$GEMINI_SETTINGS" ] && GEMINI_EXISTING=$(cat "$GEMINI_SETTINGS")
|
|
395
|
+
|
|
396
|
+
node -e "
|
|
397
|
+
const fs = require('fs');
|
|
398
|
+
let s;
|
|
399
|
+
try { s = JSON.parse(\`$GEMINI_EXISTING\`); } catch(e) { s = {}; }
|
|
400
|
+
s.hooks = s.hooks || {};
|
|
401
|
+
s.hooks.BeforeTool = s.hooks.BeforeTool || [];
|
|
402
|
+
const exists = s.hooks.BeforeTool.some(h => h.matcher === 'exit_plan_mode');
|
|
403
|
+
if (!exists) {
|
|
404
|
+
s.hooks.BeforeTool.push({
|
|
405
|
+
matcher: 'exit_plan_mode',
|
|
406
|
+
hooks: [{
|
|
407
|
+
type: 'command',
|
|
408
|
+
command: 'bash $SCRIPT_DIR/gemini-blend-hook.sh',
|
|
409
|
+
timeout: 600
|
|
410
|
+
}]
|
|
411
|
+
});
|
|
412
|
+
}
|
|
413
|
+
fs.writeFileSync('$GEMINI_SETTINGS', JSON.stringify(s, null, 2));
|
|
414
|
+
"
|
|
415
|
+
echo -e " ${G}✓${N} Auto-blend hook registered (BeforeTool/exit_plan_mode)"
|
|
416
|
+
fi
|
|
417
|
+
|
|
418
|
+
if [ "$PLATFORM" = "cursor" ]; then
|
|
419
|
+
# Register MCP server in Cursor
|
|
420
|
+
CURSOR_MCP="$HOME/.cursor/mcp.json"
|
|
421
|
+
CURSOR_EXISTING="{}"
|
|
422
|
+
[ -f "$CURSOR_MCP" ] && CURSOR_EXISTING=$(cat "$CURSOR_MCP")
|
|
423
|
+
|
|
424
|
+
node -e "
|
|
425
|
+
const fs = require('fs');
|
|
426
|
+
let s;
|
|
427
|
+
try { s = JSON.parse(\`$CURSOR_EXISTING\`); } catch(e) { s = {}; }
|
|
428
|
+
s.mcpServers = s.mcpServers || {};
|
|
429
|
+
s.mcpServers.smoothie = {
|
|
430
|
+
command: 'node',
|
|
431
|
+
args: ['$SCRIPT_DIR/dist/index.js'],
|
|
432
|
+
env: { SMOOTHIE_PLATFORM: 'cursor' }
|
|
433
|
+
};
|
|
434
|
+
fs.writeFileSync('$CURSOR_MCP', JSON.stringify(s, null, 2));
|
|
435
|
+
"
|
|
436
|
+
echo -e " ${G}✓${N} Cursor MCP server registered"
|
|
437
|
+
|
|
438
|
+
# Create Cursor Rule for auto-blend (only if auto-blend is enabled)
|
|
439
|
+
if [[ "$AUTO_BLEND" =~ ^[Yy]$ ]]; then
|
|
440
|
+
mkdir -p "$HOME/.cursor/rules"
|
|
441
|
+
cat > "$HOME/.cursor/rules/smoothie.mdc" << 'CURSORRULE'
|
|
442
|
+
---
|
|
443
|
+
description: Smoothie multi-model review — runs before significant plans
|
|
444
|
+
alwaysApply: true
|
|
445
|
+
---
|
|
446
|
+
|
|
447
|
+
Before proposing or implementing any plan that involves significant code changes,
|
|
448
|
+
call the `smoothie_blend` MCP tool with a description of what you're about to do.
|
|
449
|
+
|
|
450
|
+
Wait for results, then:
|
|
451
|
+
1. Show a summary table: Model | Time | Tokens | Verdict | Key feedback
|
|
452
|
+
2. Incorporate valid suggestions into your plan
|
|
453
|
+
3. Proceed with implementation
|
|
454
|
+
|
|
455
|
+
Skip the blend for trivial changes (typos, single-line fixes, config tweaks).
|
|
456
|
+
CURSORRULE
|
|
457
|
+
echo -e " ${G}✓${N} Cursor Rule created (auto-blend)"
|
|
458
|
+
fi
|
|
357
459
|
fi
|
|
358
460
|
|
|
359
461
|
# ─── Done ─────────────────────────────────────────────────────────────
|
|
@@ -365,11 +467,20 @@ console.log(['Codex', ...d.openrouter_models.map(m=>m.label)].join(' · '));
|
|
|
365
467
|
echo ""
|
|
366
468
|
echo -e " ${D}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${N}"
|
|
367
469
|
echo ""
|
|
368
|
-
|
|
369
|
-
echo ""
|
|
370
|
-
echo
|
|
371
|
-
|
|
372
|
-
|
|
470
|
+
if [ "$PLATFORM" = "cursor" ]; then
|
|
471
|
+
echo -e " ${G}${B}Done!${N} Restart Cursor, then:"
|
|
472
|
+
echo ""
|
|
473
|
+
echo -e " ${D}Ask Cursor to plan something — it calls smoothie_blend via MCP${N}"
|
|
474
|
+
if [[ "$AUTO_BLEND" =~ ^[Yy]$ ]]; then
|
|
475
|
+
echo -e " ${C}auto-blend${N} ${G}on${N} (via Cursor Rule)"
|
|
476
|
+
fi
|
|
477
|
+
else
|
|
478
|
+
echo -e " ${G}${B}Done!${N} Restart Claude Code, then:"
|
|
479
|
+
echo ""
|
|
480
|
+
echo -e " ${C}/smoothie${N} ${D}<your problem>${N} blend in Claude Code"
|
|
481
|
+
if [[ "$AUTO_BLEND" =~ ^[Yy]$ ]]; then
|
|
482
|
+
echo -e " ${C}auto-blend${N} ${G}on${N} for all plans"
|
|
483
|
+
fi
|
|
373
484
|
fi
|
|
374
485
|
echo -e " ${C}smoothie models${N} manage models"
|
|
375
486
|
echo ""
|
package/package.json
CHANGED
|
@@ -1,11 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "smoothie-code",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
7
7
|
"smoothie": "./bin/smoothie"
|
|
8
8
|
},
|
|
9
|
+
"files": [
|
|
10
|
+
"dist/",
|
|
11
|
+
"bin/",
|
|
12
|
+
"install.sh",
|
|
13
|
+
"auto-blend-hook.sh",
|
|
14
|
+
"plan-hook.sh",
|
|
15
|
+
"pr-blend-hook.sh",
|
|
16
|
+
"config.json",
|
|
17
|
+
"README.md"
|
|
18
|
+
],
|
|
9
19
|
"scripts": {
|
|
10
20
|
"build": "tsc",
|
|
11
21
|
"start": "node dist/index.js"
|
package/pr-blend-hook.sh
CHANGED
|
@@ -67,6 +67,36 @@ Provide concise, actionable feedback."
|
|
|
67
67
|
|
|
68
68
|
BLEND_RESULTS=$(echo "$REVIEW_PROMPT" | node "$SCRIPT_DIR/dist/blend-cli.js" 2>/dev/stderr)
|
|
69
69
|
|
|
70
|
+
# Generate share link (metadata only, no raw content)
|
|
71
|
+
SHARE_URL=""
|
|
72
|
+
SHARE_PARAMS=$(echo "$BLEND_RESULTS" | node -e "
|
|
73
|
+
const fs=require('fs');
|
|
74
|
+
let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>{
|
|
75
|
+
try {
|
|
76
|
+
const r=JSON.parse(d);
|
|
77
|
+
const models=r.results.map(m=>m.model).join(',');
|
|
78
|
+
const times=r.results.map(m=>m.elapsed_s||0).join(',');
|
|
79
|
+
const tokens=r.results.map(m=>(m.tokens&&m.tokens.total)||0).join(',');
|
|
80
|
+
const responded=r.results.filter(m=>!m.response.startsWith('Error:')&&m.response!=='No response content'&&m.response!=='(empty response)').length;
|
|
81
|
+
let github='',judge='Claude Code';
|
|
82
|
+
try{const c=JSON.parse(fs.readFileSync('$SCRIPT_DIR/config.json','utf8'));github=c.github||'';const p=process.env.SMOOTHIE_PLATFORM||'claude';judge={claude:'Claude Code',gemini:'Gemini CLI',codex:'Codex CLI',cursor:'Cursor'}[p]||'Claude Code';}catch{}
|
|
83
|
+
let params='models='+encodeURIComponent(models)+'×='+encodeURIComponent(times)+'&tokens='+encodeURIComponent(tokens)+'&type=pr&suggestions='+responded+'&judge='+encodeURIComponent(judge);
|
|
84
|
+
if(github)params+='&user='+encodeURIComponent(github);
|
|
85
|
+
console.log(params);
|
|
86
|
+
} catch { console.log(''); }
|
|
87
|
+
});
|
|
88
|
+
" 2>/dev/null)
|
|
89
|
+
|
|
90
|
+
if [ -n "$SHARE_PARAMS" ]; then
|
|
91
|
+
SHARE_URL=$(curl -s --max-time 5 --connect-timeout 3 -X POST "https://api.smoothiecode.com/api/share" \
|
|
92
|
+
-H "Content-Type: application/json" \
|
|
93
|
+
-d "{\"type\":\"report\",\"data\":\"$SHARE_PARAMS\"}" 2>/dev/null | node -e "
|
|
94
|
+
let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>{
|
|
95
|
+
try{console.log(JSON.parse(d).url)}catch{console.log('')}
|
|
96
|
+
});
|
|
97
|
+
" 2>/dev/null) || true
|
|
98
|
+
fi
|
|
99
|
+
|
|
70
100
|
if [ -z "$BLEND_RESULTS" ]; then
|
|
71
101
|
echo '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"allow"}}'
|
|
72
102
|
exit 0
|
|
@@ -79,12 +109,16 @@ $BLEND_RESULTS
|
|
|
79
109
|
|
|
80
110
|
IMPORTANT — You must do TWO things:
|
|
81
111
|
|
|
82
|
-
1. FIRST, show a
|
|
112
|
+
1. FIRST, show a Smoothie report table. Use elapsed_s and tokens from each result:
|
|
113
|
+
|
|
114
|
+
🧃 Smoothie reviewed this PR (N models, Xs total):
|
|
83
115
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
116
|
+
| Model | Time | Tokens | Finding |
|
|
117
|
+
|-------|------|--------|---------|
|
|
118
|
+
| ModelName | 3.1s | 1,847 | one-line key finding |
|
|
119
|
+
(skip errored/empty models)
|
|
120
|
+
$([ -n "$SHARE_URL" ] && echo "
|
|
121
|
+
Share this report: $SHARE_URL")
|
|
88
122
|
|
|
89
123
|
2. THEN address any valid issues — fix the code or note them in the PR description."
|
|
90
124
|
|
package/banner-v2.svg
DELETED
|
@@ -1,307 +0,0 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 440" fill="none">
|
|
2
|
-
<style>
|
|
3
|
-
/* === PERSISTENT: fade in once, stay forever === */
|
|
4
|
-
@keyframes shineOnce {
|
|
5
|
-
0% { opacity: 0; filter: blur(10px) brightness(2); }
|
|
6
|
-
40% { opacity: 1; filter: blur(3px) brightness(1.3); }
|
|
7
|
-
100% { opacity: 1; filter: blur(0) brightness(1); }
|
|
8
|
-
}
|
|
9
|
-
@keyframes fadeOnce {
|
|
10
|
-
from { opacity: 0; transform: translateY(8px); }
|
|
11
|
-
to { opacity: 1; transform: translateY(0); }
|
|
12
|
-
}
|
|
13
|
-
.persist-title { opacity: 0; animation: shineOnce 1.2s ease 0.1s forwards; }
|
|
14
|
-
.persist-sub { opacity: 0; animation: fadeOnce 0.7s ease 0.4s forwards; }
|
|
15
|
-
.persist-term { opacity: 0; animation: fadeOnce 0.5s ease 0.7s forwards; }
|
|
16
|
-
.persist-dollar{ opacity: 0; animation: fadeOnce 0.3s ease 1s forwards; }
|
|
17
|
-
|
|
18
|
-
/* === LOOPING: 14s cycle === */
|
|
19
|
-
/* fade=85-89%, pause=89-100%(1.54s)+0-1%(0.14s)=1.68s total dead */
|
|
20
|
-
|
|
21
|
-
@keyframes pathLoop {
|
|
22
|
-
0%, 14% { opacity: 0; }
|
|
23
|
-
17% { opacity: 1; }
|
|
24
|
-
85% { opacity: 1; }
|
|
25
|
-
89% { opacity: 0; }
|
|
26
|
-
100% { opacity: 0; }
|
|
27
|
-
}
|
|
28
|
-
@keyframes mA { 0%,22% { opacity:0; transform:translateY(8px); } 25% { opacity:1; transform:translateY(0); } 85% { opacity:1; } 89% { opacity:0; } 100% { opacity:0; } }
|
|
29
|
-
@keyframes mB { 0%,24% { opacity:0; transform:translateY(8px); } 27% { opacity:1; transform:translateY(0); } 85% { opacity:1; } 89% { opacity:0; } 100% { opacity:0; } }
|
|
30
|
-
@keyframes mC { 0%,26% { opacity:0; transform:translateY(8px); } 29% { opacity:1; transform:translateY(0); } 85% { opacity:1; } 89% { opacity:0; } 100% { opacity:0; } }
|
|
31
|
-
@keyframes mD { 0%,28% { opacity:0; transform:translateY(8px); } 31% { opacity:1; transform:translateY(0); } 85% { opacity:1; } 89% { opacity:0; } 100% { opacity:0; } }
|
|
32
|
-
|
|
33
|
-
@keyframes spin { to { transform: rotate(360deg); } }
|
|
34
|
-
@keyframes svA { 0%,22% { opacity:0; } 23% { opacity:1; } 36% { opacity:1; } 37% { opacity:0; } 100% { opacity:0; } }
|
|
35
|
-
@keyframes svB { 0%,24% { opacity:0; } 25% { opacity:1; } 39% { opacity:1; } 40% { opacity:0; } 100% { opacity:0; } }
|
|
36
|
-
@keyframes svC { 0%,26% { opacity:0; } 27% { opacity:1; } 42% { opacity:1; } 43% { opacity:0; } 100% { opacity:0; } }
|
|
37
|
-
@keyframes svD { 0%,28% { opacity:0; } 29% { opacity:1; } 45% { opacity:1; } 46% { opacity:0; } 100% { opacity:0; } }
|
|
38
|
-
|
|
39
|
-
@keyframes ckA { 0%,36% { opacity:0; transform:scale(0); } 38% { opacity:1; transform:scale(1.15); } 39% { transform:scale(1); } 85% { opacity:1; } 89% { opacity:0; } 100% { opacity:0; } }
|
|
40
|
-
@keyframes ckB { 0%,39% { opacity:0; transform:scale(0); } 41% { opacity:1; transform:scale(1.15); } 42% { transform:scale(1); } 85% { opacity:1; } 89% { opacity:0; } 100% { opacity:0; } }
|
|
41
|
-
@keyframes ckC { 0%,42% { opacity:0; transform:scale(0); } 44% { opacity:1; transform:scale(1.15); } 45% { transform:scale(1); } 85% { opacity:1; } 89% { opacity:0; } 100% { opacity:0; } }
|
|
42
|
-
@keyframes ckD { 0%,45% { opacity:0; transform:scale(0); } 47% { opacity:1; transform:scale(1.15); } 48% { transform:scale(1); } 85% { opacity:1; } 89% { opacity:0; } 100% { opacity:0; } }
|
|
43
|
-
|
|
44
|
-
@keyframes dA { 0%,36% { opacity:0; } 37% { opacity:1; } 85% { opacity:1; } 89% { opacity:0; } 100% { opacity:0; } }
|
|
45
|
-
@keyframes dB { 0%,39% { opacity:0; } 40% { opacity:1; } 85% { opacity:1; } 89% { opacity:0; } 100% { opacity:0; } }
|
|
46
|
-
@keyframes dC { 0%,42% { opacity:0; } 43% { opacity:1; } 85% { opacity:1; } 89% { opacity:0; } 100% { opacity:0; } }
|
|
47
|
-
@keyframes dD { 0%,45% { opacity:0; } 46% { opacity:1; } 85% { opacity:1; } 89% { opacity:0; } 100% { opacity:0; } }
|
|
48
|
-
|
|
49
|
-
/* Output: appear at 53%, hold until 85%, fade 89% → 4.5s visible */
|
|
50
|
-
@keyframes outShine {
|
|
51
|
-
0%, 53% { opacity:0; filter: blur(10px) brightness(2); }
|
|
52
|
-
57% { opacity:1; filter: blur(3px) brightness(1.3); }
|
|
53
|
-
59% { opacity:1; filter: blur(0) brightness(1); }
|
|
54
|
-
85% { opacity:1; }
|
|
55
|
-
89% { opacity:0; }
|
|
56
|
-
100% { opacity:0; }
|
|
57
|
-
}
|
|
58
|
-
@keyframes olA { 0%,57% { opacity:0; transform:translateY(8px); } 60% { opacity:1; transform:translateY(0); } 85% { opacity:1; } 89% { opacity:0; } 100% { opacity:0; } }
|
|
59
|
-
@keyframes olB { 0%,59% { opacity:0; transform:translateY(8px); } 62% { opacity:1; transform:translateY(0); } 85% { opacity:1; } 89% { opacity:0; } 100% { opacity:0; } }
|
|
60
|
-
@keyframes olC { 0%,61% { opacity:0; transform:translateY(8px); } 64% { opacity:1; transform:translateY(0); } 85% { opacity:1; } 89% { opacity:0; } 100% { opacity:0; } }
|
|
61
|
-
@keyframes labelFade {
|
|
62
|
-
0%,14% { opacity:0; } 17% { opacity:0.7; } 85% { opacity:0.7; } 89% { opacity:0; } 100% { opacity:0; }
|
|
63
|
-
}
|
|
64
|
-
@keyframes judgeLabelFade {
|
|
65
|
-
0%,50% { opacity:0; } 53% { opacity:0.7; } 85% { opacity:0.7; } 89% { opacity:0; } 100% { opacity:0; }
|
|
66
|
-
}
|
|
67
|
-
@keyframes gentleFloat {
|
|
68
|
-
0%, 100% { transform: translateY(0); }
|
|
69
|
-
50% { transform: translateY(-4px); }
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/* Class assignments */
|
|
73
|
-
.paths { animation: pathLoop 14s ease infinite; }
|
|
74
|
-
.label-par { animation: labelFade 14s ease infinite; }
|
|
75
|
-
.label-judge { animation: judgeLabelFade 14s ease infinite; }
|
|
76
|
-
.mA { animation: mA 14s ease infinite; }
|
|
77
|
-
.mB { animation: mB 14s ease infinite; }
|
|
78
|
-
.mC { animation: mC 14s ease infinite; }
|
|
79
|
-
.mD { animation: mD 14s ease infinite; }
|
|
80
|
-
.spA { transform-origin: 448px 165px; animation: spin 0.7s linear infinite, svA 14s ease infinite; }
|
|
81
|
-
.spB { transform-origin: 448px 225px; animation: spin 0.7s linear infinite, svB 14s ease infinite; }
|
|
82
|
-
.spC { transform-origin: 448px 285px; animation: spin 0.7s linear infinite, svC 14s ease infinite; }
|
|
83
|
-
.spD { transform-origin: 448px 345px; animation: spin 0.7s linear infinite, svD 14s ease infinite; }
|
|
84
|
-
.ckA { transform-origin: 448px 165px; animation: ckA 14s ease infinite; }
|
|
85
|
-
.ckB { transform-origin: 448px 225px; animation: ckB 14s ease infinite; }
|
|
86
|
-
.ckC { transform-origin: 448px 285px; animation: ckC 14s ease infinite; }
|
|
87
|
-
.ckD { transform-origin: 448px 345px; animation: ckD 14s ease infinite; }
|
|
88
|
-
.dnA { animation: dA 14s ease infinite; }
|
|
89
|
-
.dnB { animation: dB 14s ease infinite; }
|
|
90
|
-
.dnC { animation: dC 14s ease infinite; }
|
|
91
|
-
.dnD { animation: dD 14s ease infinite; }
|
|
92
|
-
.output-card { animation: outShine 14s ease infinite; }
|
|
93
|
-
.output-float { animation: gentleFloat 3s ease-in-out infinite; }
|
|
94
|
-
.olA { animation: olA 14s ease infinite; }
|
|
95
|
-
.olB { animation: olB 14s ease infinite; }
|
|
96
|
-
.olC { animation: olC 14s ease infinite; }
|
|
97
|
-
</style>
|
|
98
|
-
|
|
99
|
-
<defs>
|
|
100
|
-
<linearGradient id="og" x1="0" y1="0" x2="1" y2="0">
|
|
101
|
-
<stop offset="0%" stop-color="#f78166" stop-opacity="0.2"/>
|
|
102
|
-
<stop offset="100%" stop-color="#f78166"/>
|
|
103
|
-
</linearGradient>
|
|
104
|
-
<filter id="sh" x="-8%" y="-8%" width="116%" height="120%">
|
|
105
|
-
<feDropShadow dx="0" dy="2" stdDeviation="8" flood-color="#000" flood-opacity="0.35"/>
|
|
106
|
-
</filter>
|
|
107
|
-
|
|
108
|
-
<!-- Typewriter clip: grows to reveal text, shrinks on loop reset -->
|
|
109
|
-
<clipPath id="type-clip">
|
|
110
|
-
<rect x="72" y="250" width="0" height="30">
|
|
111
|
-
<animate attributeName="width" values="0;0;80;80;0;0" keyTimes="0;0.01;0.10;0.82;0.85;1" dur="14s" repeatCount="indefinite"/>
|
|
112
|
-
</rect>
|
|
113
|
-
</clipPath>
|
|
114
|
-
</defs>
|
|
115
|
-
|
|
116
|
-
<!-- ======= BACKGROUND (always visible) ======= -->
|
|
117
|
-
<rect width="1200" height="440" fill="#0d1117"/>
|
|
118
|
-
<pattern id="dots" width="24" height="24" patternUnits="userSpaceOnUse">
|
|
119
|
-
<circle cx="12" cy="12" r="0.5" fill="#f0f6fc" opacity="0.06"/>
|
|
120
|
-
</pattern>
|
|
121
|
-
<rect width="1200" height="440" fill="url(#dots)"/>
|
|
122
|
-
<line x1="100" y1="105" x2="1100" y2="105" stroke="#21262d" stroke-width="0.5"/>
|
|
123
|
-
<line x1="100" y1="418" x2="1100" y2="418" stroke="#21262d" stroke-width="0.5"/>
|
|
124
|
-
|
|
125
|
-
<!-- ======= PERSISTENT: Title + logo (fade in once, stay) ======= -->
|
|
126
|
-
<g class="persist-title">
|
|
127
|
-
<!-- Smoothie cup icon -->
|
|
128
|
-
<g transform="translate(480, 24)" fill="none" stroke="#f0f6fc" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round">
|
|
129
|
-
<!-- Cup body (trapezoid) -->
|
|
130
|
-
<path d="M 4 14 L 7 34 L 25 34 L 28 14"/>
|
|
131
|
-
<!-- Lid -->
|
|
132
|
-
<path d="M 1 11 L 31 11 C 31 11 31 14 16 14 C 1 14 1 11 1 11"/>
|
|
133
|
-
<!-- Dome top -->
|
|
134
|
-
<path d="M 5 11 C 5 5 11 1 16 1 C 21 1 27 5 27 11"/>
|
|
135
|
-
<!-- Straw -->
|
|
136
|
-
<line x1="20" y1="1" x2="27" y2="-8"/>
|
|
137
|
-
<line x1="27" y1="-8" x2="30" y2="-8"/>
|
|
138
|
-
<!-- Drip details -->
|
|
139
|
-
<path d="M 9 14 C 9 17 12 17 12 14" opacity="0.5"/>
|
|
140
|
-
<path d="M 18 14 C 18 17 21 17 21 14" opacity="0.5"/>
|
|
141
|
-
</g>
|
|
142
|
-
<text x="620" y="55" text-anchor="middle" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif" font-size="40" font-weight="700" fill="#f0f6fc" letter-spacing="-0.5">Smoothie</text>
|
|
143
|
-
</g>
|
|
144
|
-
<text class="persist-sub" x="600" y="85" text-anchor="middle" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif" font-size="14" fill="#7d8590" letter-spacing="0.5">multi-model review for Claude Code</text>
|
|
145
|
-
|
|
146
|
-
<!-- ======= PERSISTENT: Terminal box (fade in once, stay) ======= -->
|
|
147
|
-
<g class="persist-term">
|
|
148
|
-
<rect x="42" y="225" width="195" height="65" rx="10" fill="#161b22" stroke="#30363d" stroke-width="1" filter="url(#sh)"/>
|
|
149
|
-
<circle cx="60" cy="240" r="4" fill="#f85149" fill-opacity="0.7"/>
|
|
150
|
-
<circle cx="73" cy="240" r="4" fill="#d29922" fill-opacity="0.7"/>
|
|
151
|
-
<circle cx="86" cy="240" r="4" fill="#3fb950" fill-opacity="0.7"/>
|
|
152
|
-
</g>
|
|
153
|
-
<g class="persist-dollar">
|
|
154
|
-
<text x="58" y="272" font-family="'SF Mono', 'Fira Code', monospace" font-size="13" fill="#7d8590">$</text>
|
|
155
|
-
</g>
|
|
156
|
-
|
|
157
|
-
<!-- ======= LOOPING: Typewriter "/smoothie" ======= -->
|
|
158
|
-
<g clip-path="url(#type-clip)">
|
|
159
|
-
<text x="72" y="272" font-family="'SF Mono', 'Fira Code', monospace" font-size="13" fill="#f0f6fc">/smoothie</text>
|
|
160
|
-
</g>
|
|
161
|
-
|
|
162
|
-
<!-- Cursor: follows typing, blinks after -->
|
|
163
|
-
<rect y="260" width="7" height="14" rx="1" fill="#f78166">
|
|
164
|
-
<animate attributeName="x" values="72;72;148;148;148;148;72;72" keyTimes="0;0.01;0.10;0.11;0.13;0.82;0.85;1" dur="14s" repeatCount="indefinite"/>
|
|
165
|
-
<animate attributeName="opacity" values="0;1;1;0;1;0;1;1;0;0" keyTimes="0;0.01;0.10;0.105;0.11;0.115;0.13;0.82;0.85;1" dur="14s" repeatCount="indefinite"/>
|
|
166
|
-
</rect>
|
|
167
|
-
|
|
168
|
-
<!-- ======= LOOPING: Branching paths ======= -->
|
|
169
|
-
<g class="paths" stroke="#30363d" stroke-width="1.5" fill="none" stroke-dasharray="4 4">
|
|
170
|
-
<path d="M 250 258 L 320 258 L 320 165 L 430 165"/>
|
|
171
|
-
<path d="M 250 258 L 320 258 L 320 225 L 430 225"/>
|
|
172
|
-
<path d="M 250 258 L 320 258 L 320 285 L 430 285"/>
|
|
173
|
-
<path d="M 250 258 L 320 258 L 320 345 L 430 345"/>
|
|
174
|
-
<path d="M 680 165 L 790 165 L 790 258 L 860 258"/>
|
|
175
|
-
<path d="M 680 225 L 790 225 L 790 258 L 860 258"/>
|
|
176
|
-
<path d="M 680 285 L 790 285 L 790 258 L 860 258"/>
|
|
177
|
-
<path d="M 680 345 L 790 345 L 790 258 L 860 258"/>
|
|
178
|
-
</g>
|
|
179
|
-
<g class="paths">
|
|
180
|
-
<rect x="318" y="256" width="4" height="4" rx="1" fill="#484f58"/>
|
|
181
|
-
<rect x="788" y="256" width="4" height="4" rx="1" fill="#484f58"/>
|
|
182
|
-
</g>
|
|
183
|
-
<text class="label-par" x="285" y="240" text-anchor="middle" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif" font-size="10" fill="#f78166">parallel query</text>
|
|
184
|
-
<text class="label-judge" x="825" y="240" text-anchor="middle" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif" font-size="10" fill="#3fb950">Claude judges</text>
|
|
185
|
-
|
|
186
|
-
<!-- ======= LOOPING: Orange data packets (after typing, 14-19%) ======= -->
|
|
187
|
-
<circle r="3.5" fill="#f78166" opacity="0">
|
|
188
|
-
<animate attributeName="opacity" values="0;0;1;1;0;0" keyTimes="0;0.14;0.145;0.23;0.24;1" dur="14s" repeatCount="indefinite"/>
|
|
189
|
-
<animateMotion dur="14s" repeatCount="indefinite" keyPoints="0;0;1;1" keyTimes="0;0.14;0.24;1" calcMode="linear" path="M 250 258 L 320 258 L 320 165 L 430 165"/>
|
|
190
|
-
</circle>
|
|
191
|
-
<circle r="3.5" fill="#f78166" opacity="0">
|
|
192
|
-
<animate attributeName="opacity" values="0;0;1;1;0;0" keyTimes="0;0.14;0.145;0.23;0.24;1" dur="14s" repeatCount="indefinite"/>
|
|
193
|
-
<animateMotion dur="14s" repeatCount="indefinite" keyPoints="0;0;1;1" keyTimes="0;0.14;0.24;1" calcMode="linear" path="M 250 258 L 320 258 L 320 225 L 430 225"/>
|
|
194
|
-
</circle>
|
|
195
|
-
<circle r="3.5" fill="#f78166" opacity="0">
|
|
196
|
-
<animate attributeName="opacity" values="0;0;1;1;0;0" keyTimes="0;0.14;0.145;0.23;0.24;1" dur="14s" repeatCount="indefinite"/>
|
|
197
|
-
<animateMotion dur="14s" repeatCount="indefinite" keyPoints="0;0;1;1" keyTimes="0;0.14;0.24;1" calcMode="linear" path="M 250 258 L 320 258 L 320 285 L 430 285"/>
|
|
198
|
-
</circle>
|
|
199
|
-
<circle r="3.5" fill="#f78166" opacity="0">
|
|
200
|
-
<animate attributeName="opacity" values="0;0;1;1;0;0" keyTimes="0;0.14;0.145;0.23;0.24;1" dur="14s" repeatCount="indefinite"/>
|
|
201
|
-
<animateMotion dur="14s" repeatCount="indefinite" keyPoints="0;0;1;1" keyTimes="0;0.14;0.24;1" calcMode="linear" path="M 250 258 L 320 258 L 320 345 L 430 345"/>
|
|
202
|
-
</circle>
|
|
203
|
-
|
|
204
|
-
<!-- ======= LOOPING: Model cards ======= -->
|
|
205
|
-
|
|
206
|
-
<!-- Opus -->
|
|
207
|
-
<g class="mA">
|
|
208
|
-
<rect x="430" y="143" width="250" height="44" rx="8" fill="#161b22" stroke="#30363d" stroke-width="1"/>
|
|
209
|
-
<text x="472" y="170" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif" font-size="13.5" fill="#f0f6fc">Opus 4.6</text>
|
|
210
|
-
<rect x="440" y="178" width="230" height="3" rx="1.5" fill="#21262d"/>
|
|
211
|
-
</g>
|
|
212
|
-
<g class="spA"><circle cx="448" cy="165" r="5" fill="none" stroke="#f78166" stroke-width="1.5" stroke-dasharray="20 12" stroke-linecap="round"/></g>
|
|
213
|
-
<g class="ckA">
|
|
214
|
-
<circle cx="448" cy="165" r="6" fill="#3fb950" fill-opacity="0.15"/>
|
|
215
|
-
<path d="M 443 165 L 446.5 168.5 L 453 162" stroke="#3fb950" stroke-width="1.5" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
|
|
216
|
-
</g>
|
|
217
|
-
<text class="dnA" x="670" y="170" text-anchor="end" font-family="'SF Mono', monospace" font-size="10" fill="#3fb950">2.1s</text>
|
|
218
|
-
|
|
219
|
-
<!-- GPT Codex -->
|
|
220
|
-
<g class="mB">
|
|
221
|
-
<rect x="430" y="203" width="250" height="44" rx="8" fill="#161b22" stroke="#30363d" stroke-width="1"/>
|
|
222
|
-
<text x="472" y="230" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif" font-size="13.5" fill="#f0f6fc">GPT 5.4 Codex</text>
|
|
223
|
-
<rect x="440" y="238" width="230" height="3" rx="1.5" fill="#21262d"/>
|
|
224
|
-
</g>
|
|
225
|
-
<g class="spB"><circle cx="448" cy="225" r="5" fill="none" stroke="#f78166" stroke-width="1.5" stroke-dasharray="20 12" stroke-linecap="round"/></g>
|
|
226
|
-
<g class="ckB">
|
|
227
|
-
<circle cx="448" cy="225" r="6" fill="#3fb950" fill-opacity="0.15"/>
|
|
228
|
-
<path d="M 443 225 L 446.5 228.5 L 453 222" stroke="#3fb950" stroke-width="1.5" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
|
|
229
|
-
</g>
|
|
230
|
-
<text class="dnB" x="670" y="230" text-anchor="end" font-family="'SF Mono', monospace" font-size="10" fill="#3fb950">3.8s</text>
|
|
231
|
-
|
|
232
|
-
<!-- Gemini -->
|
|
233
|
-
<g class="mC">
|
|
234
|
-
<rect x="430" y="263" width="250" height="44" rx="8" fill="#161b22" stroke="#30363d" stroke-width="1"/>
|
|
235
|
-
<text x="472" y="290" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif" font-size="13.5" fill="#f0f6fc">Gemini 3.1 Pro</text>
|
|
236
|
-
<rect x="440" y="298" width="230" height="3" rx="1.5" fill="#21262d"/>
|
|
237
|
-
</g>
|
|
238
|
-
<g class="spC"><circle cx="448" cy="285" r="5" fill="none" stroke="#f78166" stroke-width="1.5" stroke-dasharray="20 12" stroke-linecap="round"/></g>
|
|
239
|
-
<g class="ckC">
|
|
240
|
-
<circle cx="448" cy="285" r="6" fill="#3fb950" fill-opacity="0.15"/>
|
|
241
|
-
<path d="M 443 285 L 446.5 288.5 L 453 282" stroke="#3fb950" stroke-width="1.5" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
|
|
242
|
-
</g>
|
|
243
|
-
<text class="dnC" x="670" y="290" text-anchor="end" font-family="'SF Mono', monospace" font-size="10" fill="#3fb950">4.2s</text>
|
|
244
|
-
|
|
245
|
-
<!-- Grok -->
|
|
246
|
-
<g class="mD">
|
|
247
|
-
<rect x="430" y="323" width="250" height="44" rx="8" fill="#161b22" stroke="#30363d" stroke-width="1"/>
|
|
248
|
-
<text x="472" y="350" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif" font-size="13.5" fill="#f0f6fc">Grok 4.20</text>
|
|
249
|
-
<rect x="440" y="358" width="230" height="3" rx="1.5" fill="#21262d"/>
|
|
250
|
-
</g>
|
|
251
|
-
<g class="spD"><circle cx="448" cy="345" r="5" fill="none" stroke="#f78166" stroke-width="1.5" stroke-dasharray="20 12" stroke-linecap="round"/></g>
|
|
252
|
-
<g class="ckD">
|
|
253
|
-
<circle cx="448" cy="345" r="6" fill="#3fb950" fill-opacity="0.15"/>
|
|
254
|
-
<path d="M 443 345 L 446.5 348.5 L 453 342" stroke="#3fb950" stroke-width="1.5" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
|
|
255
|
-
</g>
|
|
256
|
-
<text class="dnD" x="670" y="350" text-anchor="end" font-family="'SF Mono', monospace" font-size="10" fill="#3fb950">5.1s</text>
|
|
257
|
-
|
|
258
|
-
<!-- Per-model progress bars -->
|
|
259
|
-
<rect x="440" y="178" width="0" height="3" rx="1.5" fill="url(#og)">
|
|
260
|
-
<animate attributeName="width" values="0;0;230;230;0;0" keyTimes="0;0.23;0.36;0.37;0.38;1" dur="14s" repeatCount="indefinite"/>
|
|
261
|
-
</rect>
|
|
262
|
-
<rect x="440" y="238" width="0" height="3" rx="1.5" fill="url(#og)">
|
|
263
|
-
<animate attributeName="width" values="0;0;230;230;0;0" keyTimes="0;0.25;0.39;0.40;0.41;1" dur="14s" repeatCount="indefinite"/>
|
|
264
|
-
</rect>
|
|
265
|
-
<rect x="440" y="298" width="0" height="3" rx="1.5" fill="url(#og)">
|
|
266
|
-
<animate attributeName="width" values="0;0;230;230;0;0" keyTimes="0;0.27;0.42;0.43;0.44;1" dur="14s" repeatCount="indefinite"/>
|
|
267
|
-
</rect>
|
|
268
|
-
<rect x="440" y="358" width="0" height="3" rx="1.5" fill="url(#og)">
|
|
269
|
-
<animate attributeName="width" values="0;0;230;230;0;0" keyTimes="0;0.29;0.45;0.46;0.47;1" dur="14s" repeatCount="indefinite"/>
|
|
270
|
-
</rect>
|
|
271
|
-
|
|
272
|
-
<!-- ======= LOOPING: Green dots (staggered return, collect at junction) ======= -->
|
|
273
|
-
<!-- Opus: leaves at 38%, arrives junction at 42%, holds, goes to output at 51% -->
|
|
274
|
-
<circle r="3.5" fill="#3fb950" opacity="0">
|
|
275
|
-
<animate attributeName="opacity" values="0;0;1;1;0;0" keyTimes="0;0.38;0.385;0.52;0.53;1" dur="14s" repeatCount="indefinite"/>
|
|
276
|
-
<animateMotion dur="14s" repeatCount="indefinite" keyPoints="0;0;0.6;0.6;1;1" keyTimes="0;0.38;0.42;0.48;0.53;1" calcMode="linear" path="M 680 165 L 790 165 L 790 258 L 860 258"/>
|
|
277
|
-
</circle>
|
|
278
|
-
<!-- GPT: leaves at 41%, arrives junction at 44%, holds, goes to output at 51% -->
|
|
279
|
-
<circle r="3.5" fill="#3fb950" opacity="0">
|
|
280
|
-
<animate attributeName="opacity" values="0;0;1;1;0;0" keyTimes="0;0.41;0.415;0.52;0.53;1" dur="14s" repeatCount="indefinite"/>
|
|
281
|
-
<animateMotion dur="14s" repeatCount="indefinite" keyPoints="0;0;0.6;0.6;1;1" keyTimes="0;0.41;0.44;0.48;0.53;1" calcMode="linear" path="M 680 225 L 790 225 L 790 258 L 860 258"/>
|
|
282
|
-
</circle>
|
|
283
|
-
<!-- Gemini: leaves at 44%, arrives junction at 47%, holds, goes to output at 51% -->
|
|
284
|
-
<circle r="3.5" fill="#3fb950" opacity="0">
|
|
285
|
-
<animate attributeName="opacity" values="0;0;1;1;0;0" keyTimes="0;0.44;0.445;0.52;0.53;1" dur="14s" repeatCount="indefinite"/>
|
|
286
|
-
<animateMotion dur="14s" repeatCount="indefinite" keyPoints="0;0;0.6;0.6;1;1" keyTimes="0;0.44;0.47;0.49;0.53;1" calcMode="linear" path="M 680 285 L 790 285 L 790 258 L 860 258"/>
|
|
287
|
-
</circle>
|
|
288
|
-
<!-- Grok: leaves at 47%, arrives junction at 49%, holds briefly, goes to output at 51% -->
|
|
289
|
-
<circle r="3.5" fill="#3fb950" opacity="0">
|
|
290
|
-
<animate attributeName="opacity" values="0;0;1;1;0;0" keyTimes="0;0.47;0.475;0.52;0.53;1" dur="14s" repeatCount="indefinite"/>
|
|
291
|
-
<animateMotion dur="14s" repeatCount="indefinite" keyPoints="0;0;0.6;0.6;1;1" keyTimes="0;0.47;0.49;0.50;0.53;1" calcMode="linear" path="M 680 345 L 790 345 L 790 258 L 860 258"/>
|
|
292
|
-
</circle>
|
|
293
|
-
|
|
294
|
-
<!-- ======= LOOPING: Output card ======= -->
|
|
295
|
-
<g class="output-card">
|
|
296
|
-
<g class="output-float">
|
|
297
|
-
<rect x="870" y="210" width="210" height="100" rx="10" fill="#161b22" stroke="#3fb950" stroke-opacity="0.3" stroke-width="1" filter="url(#sh)"/>
|
|
298
|
-
<text x="975" y="236" text-anchor="middle" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif" font-size="10" font-weight="600" fill="#3fb950" letter-spacing="2.5" opacity="0.8">OUTPUT</text>
|
|
299
|
-
<line x1="893" y1="246" x2="1057" y2="246" stroke="#21262d" stroke-width="1"/>
|
|
300
|
-
</g>
|
|
301
|
-
</g>
|
|
302
|
-
<g class="output-float">
|
|
303
|
-
<g class="olA"><text x="893" y="266" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif" font-size="12" fill="#8b949e">Judged by Claude</text></g>
|
|
304
|
-
<g class="olB"><text x="893" y="284" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif" font-size="12" fill="#8b949e">Conflicts resolved</text></g>
|
|
305
|
-
<g class="olC"><text x="893" y="302" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif" font-size="12.5" fill="#3fb950" font-weight="600">One clean answer</text></g>
|
|
306
|
-
</g>
|
|
307
|
-
</svg>
|