@agent-link/server 0.1.114 → 0.1.115

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/web/landing.html CHANGED
@@ -4,20 +4,20 @@
4
4
  <meta charset="UTF-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
6
  <title>AgentLink — Remote Control for Claude Code</title>
7
- <meta name="description" content="Remote control for Claude Code. Start a task in your terminal, walk away, and continue from your phone or any browser. Auto-reconnects, end-to-end encrypted.">
7
+ <meta name="description" content="Remote control for Claude Code. Start a task in your terminal, walk away, and continue from your phone or any browser. Multi-session, end-to-end encrypted.">
8
8
  <meta name="keywords" content="Claude Code, remote control, browser IDE, AI coding assistant, AgentLink, end-to-end encrypted, self-hosted, mobile coding">
9
9
  <link rel="canonical" href="https://msclaude.ai/">
10
10
  <!-- Open Graph -->
11
11
  <meta property="og:type" content="website">
12
12
  <meta property="og:title" content="AgentLink — Remote Control for Claude Code">
13
- <meta property="og:description" content="Remote control for Claude Code. Start a task in your terminal, walk away, and continue from your phone or any browser. Auto-reconnects, end-to-end encrypted.">
13
+ <meta property="og:description" content="Remote control for Claude Code. Start a task in your terminal, walk away, and continue from your phone or any browser. Multi-session, end-to-end encrypted.">
14
14
  <meta property="og:url" content="https://msclaude.ai/">
15
15
  <meta property="og:image" content="https://msclaude.ai/iPad.png">
16
16
  <meta property="og:site_name" content="AgentLink">
17
17
  <!-- Twitter Card -->
18
18
  <meta name="twitter:card" content="summary_large_image">
19
19
  <meta name="twitter:title" content="AgentLink — Remote Control for Claude Code">
20
- <meta name="twitter:description" content="Remote control for Claude Code. Start a task in your terminal, walk away, and continue from your phone or any browser. Auto-reconnects, end-to-end encrypted.">
20
+ <meta name="twitter:description" content="Remote control for Claude Code. Start a task in your terminal, walk away, and continue from your phone or any browser. Multi-session, end-to-end encrypted.">
21
21
  <meta name="twitter:image" content="https://msclaude.ai/iPad.png">
22
22
  <link rel="icon" type="image/svg+xml" href="/favicon.svg">
23
23
  <script type="application/ld+json">
@@ -25,7 +25,7 @@
25
25
  "@context": "https://schema.org",
26
26
  "@type": "SoftwareApplication",
27
27
  "name": "AgentLink",
28
- "description": "Remote control for Claude Code. Start a task in your terminal, walk away, and continue from your phone or any browser. Auto-reconnects, end-to-end encrypted.",
28
+ "description": "Remote control for Claude Code. Start a task in your terminal, walk away, and continue from your phone or any browser. Multi-session, end-to-end encrypted.",
29
29
  "url": "https://msclaude.ai/",
30
30
  "applicationCategory": "DeveloperApplication",
31
31
  "operatingSystem": "Windows, macOS, Linux",
@@ -34,25 +34,106 @@
34
34
  }
35
35
  </script>
36
36
  <style>
37
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&family=JetBrains+Mono:wght@400;500&display=swap');
38
+
37
39
  * { margin: 0; padding: 0; box-sizing: border-box; }
38
40
 
39
41
  :root {
40
- --bg: #0a0a0a;
41
- --surface: #141414;
42
- --border: #252525;
43
- --text: #e8e8e8;
44
- --text-dim: #888;
45
- --accent: #6c63ff;
46
- --accent-hover: #7c74ff;
47
- --green: #22c55e;
42
+ --bg: #06080f;
43
+ --surface: rgba(255,255,255,0.03);
44
+ --surface-hover: rgba(255,255,255,0.06);
45
+ --border: rgba(255,255,255,0.06);
46
+ --border-hover: rgba(255,255,255,0.12);
47
+ --text: #eaeaea;
48
+ --text-dim: rgba(255,255,255,0.45);
49
+ --text-mid: rgba(255,255,255,0.65);
50
+ --accent: #3b82f6;
51
+ --accent-soft: rgba(59,130,246,0.15);
52
+ --accent-glow: rgba(59,130,246,0.4);
53
+ --rose: #f59e0b;
54
+ --amber: #f59e0b;
55
+ --cyan: #22d3ee;
56
+ --green: #34d399;
57
+ --blue: #60a5fa;
48
58
  }
49
59
 
50
60
  body {
51
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
61
+ font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
52
62
  background: var(--bg);
53
63
  color: var(--text);
54
64
  line-height: 1.6;
55
65
  min-height: 100vh;
66
+ overflow-x: hidden;
67
+ }
68
+
69
+ /* ── Ambient Background ── */
70
+ .ambient {
71
+ position: fixed;
72
+ top: 0;
73
+ left: 0;
74
+ width: 100%;
75
+ height: 100%;
76
+ pointer-events: none;
77
+ z-index: 0;
78
+ overflow: hidden;
79
+ }
80
+
81
+ .ambient-orb {
82
+ position: absolute;
83
+ border-radius: 50%;
84
+ filter: blur(120px);
85
+ opacity: 0.35;
86
+ animation: float 20s ease-in-out infinite;
87
+ }
88
+
89
+ .ambient-orb:nth-child(1) {
90
+ width: 600px; height: 600px;
91
+ background: radial-gradient(circle, var(--accent) 0%, transparent 70%);
92
+ top: -10%; left: -5%;
93
+ animation-delay: 0s;
94
+ animation-duration: 25s;
95
+ }
96
+
97
+ .ambient-orb:nth-child(2) {
98
+ width: 500px; height: 500px;
99
+ background: radial-gradient(circle, var(--rose) 0%, transparent 70%);
100
+ top: 20%; right: -10%;
101
+ animation-delay: -8s;
102
+ animation-duration: 22s;
103
+ }
104
+
105
+ .ambient-orb:nth-child(3) {
106
+ width: 400px; height: 400px;
107
+ background: radial-gradient(circle, var(--cyan) 0%, transparent 70%);
108
+ bottom: 10%; left: 20%;
109
+ animation-delay: -15s;
110
+ animation-duration: 28s;
111
+ }
112
+
113
+ @keyframes float {
114
+ 0%, 100% { transform: translate(0, 0) scale(1); }
115
+ 25% { transform: translate(30px, -40px) scale(1.05); }
116
+ 50% { transform: translate(-20px, 20px) scale(0.95); }
117
+ 75% { transform: translate(40px, 10px) scale(1.02); }
118
+ }
119
+
120
+ /* ── Grain overlay ── */
121
+ .grain {
122
+ position: fixed;
123
+ top: 0; left: 0;
124
+ width: 100%; height: 100%;
125
+ pointer-events: none;
126
+ z-index: 1;
127
+ opacity: 0.025;
128
+ background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)'/%3E%3C/svg%3E");
129
+ background-repeat: repeat;
130
+ background-size: 256px 256px;
131
+ }
132
+
133
+ /* ── Content wrapper ── */
134
+ .content {
135
+ position: relative;
136
+ z-index: 2;
56
137
  }
57
138
 
58
139
  /* ── Nav ── */
@@ -60,465 +141,1096 @@
60
141
  display: flex;
61
142
  align-items: center;
62
143
  justify-content: space-between;
63
- padding: 1rem 2rem;
64
- max-width: 1100px;
144
+ padding: 1.5rem 2.5rem;
145
+ max-width: 1200px;
65
146
  margin: 0 auto;
66
147
  }
67
148
 
68
149
  .logo {
69
- font-size: 1.25rem;
150
+ font-size: 1.2rem;
70
151
  font-weight: 700;
71
- letter-spacing: -0.02em;
152
+ letter-spacing: -0.03em;
153
+ display: flex;
154
+ align-items: center;
155
+ gap: 0.5rem;
72
156
  }
73
157
 
74
- .logo span { color: var(--accent); }
158
+ .logo-mark {
159
+ width: 28px; height: 28px;
160
+ border-radius: 8px;
161
+ background: linear-gradient(135deg, var(--accent), var(--rose));
162
+ display: flex;
163
+ align-items: center;
164
+ justify-content: center;
165
+ font-size: 0.75rem;
166
+ font-weight: 800;
167
+ color: #fff;
168
+ box-shadow: 0 0 20px var(--accent-glow);
169
+ }
75
170
 
76
- nav a {
171
+ .logo-text span {
172
+ background: linear-gradient(135deg, var(--accent), var(--rose));
173
+ -webkit-background-clip: text;
174
+ -webkit-text-fill-color: transparent;
175
+ background-clip: text;
176
+ }
177
+
178
+ .nav-links {
179
+ display: flex;
180
+ align-items: center;
181
+ gap: 2rem;
182
+ }
183
+
184
+ .nav-links a {
77
185
  color: var(--text-dim);
78
186
  text-decoration: none;
79
- font-size: 0.9rem;
80
- transition: color 0.2s;
187
+ font-size: 0.85rem;
188
+ font-weight: 500;
189
+ transition: color 0.3s;
190
+ letter-spacing: 0.02em;
191
+ }
192
+
193
+ .nav-links a:hover { color: var(--text); }
194
+
195
+ .nav-gh {
196
+ display: flex;
197
+ align-items: center;
198
+ gap: 0.4rem;
199
+ background: var(--surface);
200
+ border: 1px solid var(--border);
201
+ border-radius: 8px;
202
+ padding: 0.45rem 0.85rem;
203
+ transition: all 0.3s;
204
+ }
205
+
206
+ .nav-gh:hover {
207
+ background: var(--surface-hover);
208
+ border-color: var(--border-hover);
81
209
  }
82
210
 
83
- nav a:hover { color: var(--text); }
211
+ .nav-gh svg { width: 16px; height: 16px; fill: currentColor; }
84
212
 
85
213
  /* ── Hero ── */
86
214
  .hero {
87
215
  text-align: center;
88
- padding: 3.5rem 2rem 2rem;
89
- max-width: 820px;
216
+ padding: 5rem 2rem 4rem;
217
+ max-width: 900px;
90
218
  margin: 0 auto;
219
+ position: relative;
220
+ }
221
+
222
+ .hero-badge {
223
+ display: inline-flex;
224
+ align-items: center;
225
+ gap: 0.5rem;
226
+ background: var(--accent-soft);
227
+ border: 1px solid rgba(59,130,246,0.2);
228
+ border-radius: 100px;
229
+ padding: 0.4rem 1rem 0.4rem 0.5rem;
230
+ font-size: 0.8rem;
231
+ color: var(--accent);
232
+ font-weight: 500;
233
+ margin-bottom: 2.5rem;
234
+ letter-spacing: 0.01em;
235
+ animation: fadeInUp 0.8s ease-out;
236
+ }
237
+
238
+ .hero-badge-dot {
239
+ width: 8px; height: 8px;
240
+ border-radius: 50%;
241
+ background: var(--green);
242
+ box-shadow: 0 0 8px var(--green);
243
+ animation: pulse 2s ease-in-out infinite;
244
+ }
245
+
246
+ @keyframes pulse {
247
+ 0%, 100% { opacity: 1; transform: scale(1); }
248
+ 50% { opacity: 0.6; transform: scale(0.85); }
91
249
  }
92
250
 
93
251
  .hero h1 {
94
- font-size: clamp(2.2rem, 5vw, 3.5rem);
252
+ font-size: clamp(2.8rem, 6vw, 4.5rem);
95
253
  font-weight: 800;
96
- letter-spacing: -0.03em;
97
- line-height: 1.15;
98
- margin-bottom: 1.5rem;
254
+ letter-spacing: -0.04em;
255
+ line-height: 1.08;
256
+ margin-bottom: 1.75rem;
257
+ animation: fadeInUp 0.8s ease-out 0.1s both;
258
+ }
259
+
260
+ .hero h1 .line {
261
+ display: block;
99
262
  }
100
263
 
101
264
  .hero h1 em {
102
265
  font-style: normal;
103
- background: linear-gradient(135deg, var(--accent), #a78bfa);
266
+ position: relative;
267
+ background: linear-gradient(135deg, var(--accent), #60a5fa, var(--rose));
268
+ background-size: 200% 200%;
104
269
  -webkit-background-clip: text;
105
270
  -webkit-text-fill-color: transparent;
106
271
  background-clip: text;
272
+ animation: shimmer 6s ease-in-out infinite;
107
273
  }
108
274
 
109
- .hero p {
110
- font-size: 1.15rem;
111
- color: var(--text-dim);
112
- max-width: 620px;
113
- margin: 0 auto 0.75rem;
275
+ @keyframes shimmer {
276
+ 0%, 100% { background-position: 0% 50%; }
277
+ 50% { background-position: 100% 50%; }
114
278
  }
115
279
 
116
- .hero p strong {
280
+ .hero-sub {
281
+ font-size: 1.2rem;
282
+ color: var(--text-mid);
283
+ max-width: 600px;
284
+ margin: 0 auto 3rem;
285
+ font-weight: 400;
286
+ line-height: 1.7;
287
+ animation: fadeInUp 0.8s ease-out 0.2s both;
288
+ }
289
+
290
+ .hero-sub strong {
117
291
  color: var(--text);
292
+ font-weight: 500;
293
+ }
294
+
295
+ @keyframes fadeInUp {
296
+ from { opacity: 0; transform: translateY(20px); }
297
+ to { opacity: 1; transform: translateY(0); }
298
+ }
299
+
300
+ /* ── CTA Group ── */
301
+ .cta-group {
302
+ display: flex;
303
+ align-items: center;
304
+ justify-content: center;
305
+ gap: 1rem;
306
+ margin-bottom: 1.5rem;
307
+ animation: fadeInUp 0.8s ease-out 0.3s both;
308
+ }
309
+
310
+ .cta-primary {
311
+ display: inline-flex;
312
+ align-items: center;
313
+ gap: 0.5rem;
314
+ background: linear-gradient(135deg, var(--accent), #60a5fa);
315
+ color: #fff;
118
316
  font-weight: 600;
317
+ font-size: 0.95rem;
318
+ padding: 0.8rem 1.75rem;
319
+ border-radius: 12px;
320
+ text-decoration: none;
321
+ transition: all 0.3s;
322
+ box-shadow: 0 0 30px rgba(59,130,246,0.3), 0 4px 15px rgba(0,0,0,0.3);
323
+ border: none;
324
+ cursor: pointer;
325
+ font-family: inherit;
119
326
  }
120
327
 
121
- /* ── Install box ── */
122
- .install {
328
+ .cta-primary:hover {
329
+ transform: translateY(-2px);
330
+ box-shadow: 0 0 40px rgba(59,130,246,0.45), 0 8px 25px rgba(0,0,0,0.4);
331
+ }
332
+
333
+ .cta-secondary {
334
+ display: inline-flex;
335
+ align-items: center;
336
+ gap: 0.5rem;
123
337
  background: var(--surface);
124
338
  border: 1px solid var(--border);
339
+ color: var(--text);
340
+ font-weight: 500;
341
+ font-size: 0.95rem;
342
+ padding: 0.8rem 1.75rem;
125
343
  border-radius: 12px;
126
- padding: 2rem 2.5rem;
127
- max-width: 600px;
128
- margin: 2.5rem auto 4rem;
129
- text-align: left;
344
+ text-decoration: none;
345
+ transition: all 0.3s;
346
+ cursor: pointer;
347
+ font-family: inherit;
130
348
  }
131
349
 
132
- .install-label {
133
- font-size: 0.8rem;
134
- color: var(--text-dim);
135
- text-transform: uppercase;
136
- letter-spacing: 0.08em;
137
- margin-bottom: 1rem;
350
+ .cta-secondary:hover {
351
+ background: var(--surface-hover);
352
+ border-color: var(--border-hover);
353
+ transform: translateY(-2px);
138
354
  }
139
355
 
140
- .install-step {
356
+ .cta-secondary svg { width: 18px; height: 18px; fill: currentColor; }
357
+
358
+ /* ── Terminal Install ── */
359
+ .terminal {
360
+ max-width: 520px;
361
+ margin: 0 auto;
362
+ background: rgba(10,10,20,0.7);
363
+ backdrop-filter: blur(20px);
364
+ -webkit-backdrop-filter: blur(20px);
365
+ border: 1px solid var(--border);
366
+ border-radius: 14px;
367
+ overflow: hidden;
368
+ animation: fadeInUp 0.8s ease-out 0.4s both;
369
+ box-shadow: 0 20px 60px rgba(0,0,0,0.4);
370
+ }
371
+
372
+ .terminal-bar {
141
373
  display: flex;
142
374
  align-items: center;
143
- gap: 0.75rem;
144
- margin-bottom: 0.75rem;
375
+ gap: 6px;
376
+ padding: 0.75rem 1rem;
377
+ background: rgba(255,255,255,0.03);
378
+ border-bottom: 1px solid var(--border);
145
379
  }
146
380
 
147
- .step-num {
148
- width: 24px;
149
- height: 24px;
381
+ .terminal-dot {
382
+ width: 10px; height: 10px;
150
383
  border-radius: 50%;
151
- background: var(--accent);
152
- color: #fff;
153
- font-size: 0.75rem;
154
- font-weight: 700;
155
- display: flex;
156
- align-items: center;
157
- justify-content: center;
158
- flex-shrink: 0;
159
384
  }
160
385
 
161
- .install-cmd {
162
- background: #1a1a2e;
163
- border: 1px solid #2a2a4a;
164
- border-radius: 8px;
165
- padding: 0.6rem 1rem;
166
- font-family: 'SF Mono', 'Fira Code', 'Consolas', monospace;
167
- font-size: 0.9rem;
168
- color: var(--green);
386
+ .terminal-dot:nth-child(1) { background: #ff5f57; }
387
+ .terminal-dot:nth-child(2) { background: #ffbd2e; }
388
+ .terminal-dot:nth-child(3) { background: #28c840; }
389
+
390
+ .terminal-title {
169
391
  flex: 1;
170
- cursor: pointer;
171
- position: relative;
172
- transition: border-color 0.2s;
392
+ text-align: center;
393
+ font-size: 0.72rem;
394
+ color: var(--text-dim);
395
+ font-weight: 500;
396
+ letter-spacing: 0.03em;
173
397
  }
174
398
 
175
- .install-cmd:hover {
176
- border-color: var(--accent);
399
+ .terminal-body {
400
+ padding: 1.25rem 1.5rem;
401
+ font-family: 'JetBrains Mono', 'SF Mono', 'Fira Code', monospace;
402
+ font-size: 0.85rem;
403
+ line-height: 1.8;
177
404
  }
178
405
 
179
- .install-cmd .copy-hint {
180
- position: absolute;
181
- right: 0.75rem;
182
- top: 50%;
183
- transform: translateY(-50%);
184
- font-size: 0.7rem;
406
+ .terminal-line {
407
+ display: flex;
408
+ align-items: center;
409
+ gap: 0.5rem;
410
+ cursor: pointer;
411
+ padding: 0.15rem 0.35rem;
412
+ margin: 0 -0.35rem;
413
+ border-radius: 6px;
414
+ transition: background 0.2s;
415
+ }
416
+
417
+ .terminal-line:hover { background: rgba(255,255,255,0.04); }
418
+
419
+ .terminal-prompt { color: var(--accent); user-select: none; }
420
+ .terminal-cmd { color: var(--green); }
421
+
422
+ .terminal-output {
185
423
  color: var(--text-dim);
186
- opacity: 0;
187
- transition: opacity 0.2s;
424
+ font-size: 0.8rem;
425
+ padding-left: 1.1rem;
426
+ margin-top: 0.15rem;
188
427
  }
189
428
 
190
- .install-cmd:hover .copy-hint { opacity: 1; }
429
+ .terminal-output a {
430
+ color: var(--cyan);
431
+ text-decoration: none;
432
+ }
191
433
 
192
- .install-note {
434
+ .terminal-copy-toast {
435
+ position: fixed;
436
+ bottom: 2rem;
437
+ left: 50%;
438
+ transform: translateX(-50%) translateY(20px);
439
+ background: var(--accent);
440
+ color: #fff;
441
+ padding: 0.5rem 1.25rem;
442
+ border-radius: 8px;
193
443
  font-size: 0.8rem;
194
- color: var(--text-dim);
195
- margin-top: 1rem;
196
- text-align: center;
444
+ font-weight: 500;
445
+ opacity: 0;
446
+ transition: all 0.3s;
447
+ pointer-events: none;
448
+ z-index: 100;
449
+ font-family: 'Inter', sans-serif;
450
+ }
451
+
452
+ .terminal-copy-toast.show {
453
+ opacity: 1;
454
+ transform: translateX(-50%) translateY(0);
197
455
  }
198
456
 
199
- /* ── Device Showcase ── */
457
+ /* ── Showcase ── */
200
458
  .showcase {
201
- max-width: 900px;
202
- margin: 0 auto 4rem;
459
+ max-width: 1000px;
460
+ margin: 6rem auto 0;
203
461
  padding: 0 2rem;
204
462
  position: relative;
205
- display: flex;
206
- justify-content: center;
207
- align-items: flex-end;
463
+ display: grid;
464
+ grid-template-columns: 5fr 2fr;
465
+ align-items: end;
466
+ gap: 2rem;
467
+ animation: fadeInUp 1s ease-out 0.6s both;
468
+ }
469
+
470
+ .showcase::before {
471
+ content: '';
472
+ position: absolute;
473
+ top: 50%;
474
+ left: 50%;
475
+ transform: translate(-50%, -50%);
476
+ width: 120%;
477
+ height: 120%;
478
+ background:
479
+ radial-gradient(ellipse at 35% 50%, rgba(59,130,246,0.12) 0%, transparent 55%),
480
+ radial-gradient(ellipse at 65% 50%, rgba(245,158,11,0.08) 0%, transparent 55%);
481
+ pointer-events: none;
482
+ z-index: 0;
483
+ filter: blur(60px);
484
+ }
485
+
486
+ /* Subtle connecting line between devices */
487
+ .showcase::after {
488
+ content: '';
489
+ position: absolute;
490
+ top: 50%;
491
+ left: 50%;
492
+ transform: translate(-50%, -50%);
493
+ width: 1px;
494
+ height: 35%;
495
+ background: linear-gradient(180deg, transparent, rgba(59,130,246,0.2), rgba(245,158,11,0.2), transparent);
496
+ pointer-events: none;
497
+ z-index: 0;
208
498
  }
209
499
 
210
500
  .device {
211
501
  position: relative;
212
- border-radius: 18px;
213
502
  overflow: hidden;
214
- box-shadow:
215
- 0 0 0 1px rgba(255,255,255,0.06),
216
- 0 25px 80px rgba(0,0,0,0.55),
217
- 0 8px 32px rgba(0,0,0,0.3);
503
+ transition: transform 0.5s cubic-bezier(0.25, 0.46, 0.45, 0.94);
218
504
  }
219
505
 
220
- .device img {
221
- display: block;
222
- width: 100%;
223
- height: auto;
506
+ .device:hover {
507
+ transform: translateY(-8px);
224
508
  }
225
509
 
510
+ .device img, .device picture { display: block; width: 100%; height: auto; }
511
+
226
512
  .device-ipad {
227
- width: 72%;
228
- border-radius: 18px;
513
+ width: 100%;
514
+ border-radius: 20px;
229
515
  z-index: 1;
516
+ box-shadow:
517
+ 0 0 0 1px rgba(255,255,255,0.08),
518
+ 0 40px 100px rgba(0,0,0,0.5),
519
+ 0 15px 50px rgba(0,0,0,0.3),
520
+ 0 0 80px rgba(59,130,246,0.08);
521
+ transform: rotate(-1deg);
522
+ }
523
+
524
+ .device-ipad:hover {
525
+ transform: rotate(-1deg) translateY(-8px);
230
526
  }
231
527
 
232
528
  .device-iphone {
233
- width: 22%;
234
- border-radius: 24px;
529
+ width: 90%;
530
+ border-radius: 28px;
235
531
  z-index: 2;
236
- margin-left: -8%;
237
- transform: translateY(2%);
532
+ justify-self: center;
533
+ align-self: center;
238
534
  box-shadow:
239
- 0 0 0 1px rgba(255,255,255,0.08),
240
- 0 30px 90px rgba(0,0,0,0.6),
241
- 0 10px 40px rgba(0,0,0,0.35);
535
+ 0 0 0 1px rgba(255,255,255,0.1),
536
+ 0 45px 100px rgba(0,0,0,0.55),
537
+ 0 15px 50px rgba(0,0,0,0.35),
538
+ 0 0 80px rgba(245,158,11,0.08);
539
+ transform: rotate(2deg);
242
540
  }
243
541
 
244
- .showcase::before {
542
+ .device-iphone:hover {
543
+ transform: rotate(2deg) translateY(-8px);
544
+ }
545
+
546
+ /* ── Divider ── */
547
+ .section-divider {
548
+ max-width: 200px;
549
+ margin: 6rem auto;
550
+ height: 1px;
551
+ background: linear-gradient(90deg, transparent, var(--border-hover), transparent);
552
+ }
553
+
554
+ /* ── Philosophy Section ── */
555
+ .philosophy {
556
+ max-width: 700px;
557
+ margin: 0 auto;
558
+ padding: 0 2rem;
559
+ text-align: center;
560
+ }
561
+
562
+ .philosophy-label {
563
+ font-size: 0.7rem;
564
+ font-weight: 600;
565
+ letter-spacing: 0.15em;
566
+ text-transform: uppercase;
567
+ color: var(--accent);
568
+ margin-bottom: 1.5rem;
569
+ }
570
+
571
+ .philosophy h2 {
572
+ font-size: clamp(1.6rem, 3.5vw, 2.4rem);
573
+ font-weight: 700;
574
+ letter-spacing: -0.03em;
575
+ line-height: 1.25;
576
+ margin-bottom: 1.5rem;
577
+ }
578
+
579
+ .philosophy h2 em {
580
+ font-style: normal;
581
+ color: var(--text-dim);
582
+ }
583
+
584
+ .philosophy p {
585
+ color: var(--text-mid);
586
+ font-size: 1.05rem;
587
+ line-height: 1.8;
588
+ max-width: 560px;
589
+ margin: 0 auto;
590
+ }
591
+
592
+ /* ── Bento Grid ── */
593
+ .bento {
594
+ max-width: 1000px;
595
+ margin: 6rem auto;
596
+ padding: 0 2rem;
597
+ display: grid;
598
+ grid-template-columns: repeat(3, 1fr);
599
+ grid-auto-rows: minmax(200px, auto);
600
+ gap: 1rem;
601
+ }
602
+
603
+ .bento-card {
604
+ background: var(--surface);
605
+ border: 1px solid var(--border);
606
+ border-radius: 20px;
607
+ padding: 2rem;
608
+ position: relative;
609
+ overflow: hidden;
610
+ transition: all 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94);
611
+ display: flex;
612
+ flex-direction: column;
613
+ justify-content: flex-end;
614
+ }
615
+
616
+ .bento-card:hover {
617
+ border-color: var(--border-hover);
618
+ background: var(--surface-hover);
619
+ transform: translateY(-4px);
620
+ box-shadow: 0 20px 60px rgba(0,0,0,0.3);
621
+ }
622
+
623
+ .bento-card.wide { grid-column: span 2; }
624
+ .bento-card.tall { grid-row: span 2; }
625
+
626
+ .bento-visual {
627
+ flex: 1;
628
+ display: flex;
629
+ align-items: center;
630
+ justify-content: center;
631
+ margin-bottom: 1.5rem;
632
+ position: relative;
633
+ }
634
+
635
+ .bento-icon {
636
+ width: 56px; height: 56px;
637
+ border-radius: 16px;
638
+ display: flex;
639
+ align-items: center;
640
+ justify-content: center;
641
+ font-size: 1.5rem;
642
+ }
643
+
644
+ .bento-icon.purple { background: linear-gradient(135deg, rgba(59,130,246,0.2), rgba(59,130,246,0.05)); color: var(--accent); }
645
+ .bento-icon.rose { background: linear-gradient(135deg, rgba(245,158,11,0.2), rgba(245,158,11,0.05)); color: var(--rose); }
646
+ .bento-icon.cyan { background: linear-gradient(135deg, rgba(34,211,238,0.2), rgba(34,211,238,0.05)); color: var(--cyan); }
647
+ .bento-icon.green { background: linear-gradient(135deg, rgba(52,211,153,0.2), rgba(52,211,153,0.05)); color: var(--green); }
648
+ .bento-icon.amber { background: linear-gradient(135deg, rgba(245,158,11,0.2), rgba(245,158,11,0.05)); color: var(--amber); }
649
+ .bento-icon.blue { background: linear-gradient(135deg, rgba(96,165,250,0.2), rgba(96,165,250,0.05)); color: var(--blue); }
650
+
651
+ /* Encryption visual */
652
+ .encrypt-visual {
653
+ display: flex;
654
+ align-items: center;
655
+ gap: 0.75rem;
656
+ font-family: 'JetBrains Mono', monospace;
657
+ font-size: 0.72rem;
658
+ color: var(--text-dim);
659
+ }
660
+
661
+ .encrypt-block {
662
+ padding: 0.4rem 0.7rem;
663
+ border-radius: 8px;
664
+ background: rgba(255,255,255,0.04);
665
+ border: 1px solid var(--border);
666
+ white-space: nowrap;
667
+ }
668
+
669
+ .encrypt-arrow { color: var(--accent); font-size: 1rem; }
670
+
671
+ .encrypt-block.locked {
672
+ color: var(--green);
673
+ border-color: rgba(52,211,153,0.2);
674
+ background: rgba(52,211,153,0.05);
675
+ }
676
+
677
+ /* Device flow visual */
678
+ .device-flow {
679
+ display: flex;
680
+ align-items: center;
681
+ gap: 1rem;
682
+ }
683
+
684
+ .device-pill {
685
+ display: flex;
686
+ align-items: center;
687
+ gap: 0.4rem;
688
+ padding: 0.5rem 0.8rem;
689
+ border-radius: 10px;
690
+ background: rgba(255,255,255,0.04);
691
+ border: 1px solid var(--border);
692
+ font-size: 0.75rem;
693
+ color: var(--text-mid);
694
+ }
695
+
696
+ .device-pill svg { width: 14px; height: 14px; fill: currentColor; opacity: 0.6; }
697
+
698
+ .flow-line {
699
+ flex: 1;
700
+ height: 1px;
701
+ background: linear-gradient(90deg, var(--border-hover), transparent);
702
+ position: relative;
703
+ }
704
+
705
+ .flow-line::after {
245
706
  content: '';
246
707
  position: absolute;
247
- top: 50%;
248
- left: 50%;
249
- transform: translate(-50%, -50%);
250
- width: 80%;
251
- height: 70%;
252
- background: radial-gradient(ellipse, rgba(108,99,255,0.12) 0%, transparent 70%);
253
- pointer-events: none;
254
- z-index: 0;
708
+ right: 0; top: -2px;
709
+ width: 5px; height: 5px;
710
+ border-radius: 50%;
711
+ background: var(--accent);
712
+ box-shadow: 0 0 8px var(--accent-glow);
713
+ animation: flowPulse 2s ease-in-out infinite;
714
+ }
715
+
716
+ @keyframes flowPulse {
717
+ 0%, 100% { opacity: 0.4; }
718
+ 50% { opacity: 1; }
255
719
  }
256
720
 
257
- /* ── Workflow ── */
721
+ .bento-card h3 {
722
+ font-size: 1.05rem;
723
+ font-weight: 600;
724
+ margin-bottom: 0.4rem;
725
+ letter-spacing: -0.01em;
726
+ }
727
+
728
+ .bento-card p {
729
+ font-size: 0.85rem;
730
+ color: var(--text-dim);
731
+ line-height: 1.55;
732
+ }
733
+
734
+ /* ── How It Works ── */
258
735
  .workflow {
259
- max-width: 800px;
260
- margin: 0 auto 5rem;
736
+ max-width: 700px;
737
+ margin: 0 auto 6rem;
261
738
  padding: 0 2rem;
262
739
  }
263
740
 
741
+ .workflow-label {
742
+ font-size: 0.7rem;
743
+ font-weight: 600;
744
+ letter-spacing: 0.15em;
745
+ text-transform: uppercase;
746
+ color: var(--accent);
747
+ text-align: center;
748
+ margin-bottom: 1.5rem;
749
+ }
750
+
264
751
  .workflow h2 {
265
- font-size: 1.8rem;
752
+ font-size: clamp(1.6rem, 3.5vw, 2.2rem);
266
753
  font-weight: 700;
267
754
  text-align: center;
268
- margin-bottom: 2.5rem;
755
+ letter-spacing: -0.03em;
756
+ margin-bottom: 3rem;
269
757
  }
270
758
 
271
759
  .workflow-steps {
760
+ position: relative;
272
761
  display: flex;
273
762
  flex-direction: column;
274
- gap: 1.25rem;
763
+ gap: 0;
764
+ }
765
+
766
+ .workflow-steps::before {
767
+ content: '';
768
+ position: absolute;
769
+ left: 23px;
770
+ top: 48px;
771
+ bottom: 48px;
772
+ width: 1px;
773
+ background: linear-gradient(180deg, var(--accent), var(--rose), var(--cyan), var(--green));
774
+ opacity: 0.3;
275
775
  }
276
776
 
277
777
  .workflow-step {
278
778
  display: flex;
279
779
  align-items: flex-start;
280
- gap: 1.25rem;
281
- background: var(--surface);
282
- border: 1px solid var(--border);
283
- border-radius: 12px;
284
- padding: 1.25rem 1.5rem;
780
+ gap: 1.5rem;
781
+ padding: 1.5rem 0;
782
+ position: relative;
285
783
  }
286
784
 
287
- .workflow-step .step-icon {
288
- font-size: 1.5rem;
785
+ .step-marker {
786
+ width: 48px; height: 48px;
787
+ border-radius: 14px;
788
+ display: flex;
789
+ align-items: center;
790
+ justify-content: center;
289
791
  flex-shrink: 0;
290
- width: 2rem;
291
- text-align: center;
292
- padding-top: 0.1rem;
792
+ font-size: 1.1rem;
793
+ background: var(--surface);
794
+ border: 1px solid var(--border);
795
+ position: relative;
796
+ z-index: 1;
293
797
  }
294
798
 
295
- .workflow-step h3 {
799
+ .workflow-step:nth-child(1) .step-marker { border-color: rgba(59,130,246,0.3); }
800
+ .workflow-step:nth-child(2) .step-marker { border-color: rgba(245,158,11,0.3); }
801
+ .workflow-step:nth-child(3) .step-marker { border-color: rgba(34,211,238,0.3); }
802
+ .workflow-step:nth-child(4) .step-marker { border-color: rgba(52,211,153,0.3); }
803
+
804
+ .step-content h3 {
296
805
  font-size: 1rem;
297
806
  font-weight: 600;
298
- margin-bottom: 0.3rem;
807
+ margin-bottom: 0.35rem;
808
+ letter-spacing: -0.01em;
299
809
  }
300
810
 
301
- .workflow-step p {
302
- font-size: 0.9rem;
811
+ .step-content p {
812
+ font-size: 0.88rem;
303
813
  color: var(--text-dim);
304
- line-height: 1.5;
814
+ line-height: 1.6;
305
815
  }
306
816
 
307
- .workflow-step code {
308
- font-family: 'SF Mono', 'Fira Code', 'Consolas', monospace;
309
- font-size: 0.85rem;
817
+ .step-content code {
818
+ font-family: 'JetBrains Mono', monospace;
819
+ font-size: 0.8rem;
310
820
  color: var(--green);
311
- background: #1a1a2e;
312
- padding: 0.15rem 0.4rem;
313
- border-radius: 4px;
821
+ background: rgba(52,211,153,0.08);
822
+ padding: 0.15rem 0.45rem;
823
+ border-radius: 5px;
824
+ border: 1px solid rgba(52,211,153,0.12);
314
825
  }
315
826
 
316
- /* ── Features ── */
317
- .features {
318
- display: grid;
319
- grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
320
- gap: 1.5rem;
321
- max-width: 1000px;
322
- margin: 0 auto 5rem;
323
- padding: 0 2rem;
827
+ /* ── Footer ── */
828
+ footer {
829
+ text-align: center;
830
+ padding: 3rem 2rem;
831
+ color: var(--text-dim);
832
+ font-size: 0.8rem;
833
+ position: relative;
324
834
  }
325
835
 
326
- .feature {
327
- background: var(--surface);
328
- border: 1px solid var(--border);
329
- border-radius: 12px;
330
- padding: 1.5rem;
836
+ footer::before {
837
+ content: '';
838
+ display: block;
839
+ max-width: 200px;
840
+ margin: 0 auto 2rem;
841
+ height: 1px;
842
+ background: linear-gradient(90deg, transparent, var(--border-hover), transparent);
331
843
  }
332
844
 
333
- .feature-icon {
334
- font-size: 1.5rem;
335
- margin-bottom: 0.75rem;
845
+ footer a {
846
+ color: var(--text-mid);
847
+ text-decoration: none;
848
+ transition: color 0.3s;
336
849
  }
337
850
 
338
- .feature h3 {
339
- font-size: 1rem;
340
- font-weight: 600;
341
- margin-bottom: 0.5rem;
851
+ footer a:hover { color: var(--text); }
852
+
853
+ .footer-links {
854
+ display: flex;
855
+ align-items: center;
856
+ justify-content: center;
857
+ gap: 1.5rem;
858
+ margin-bottom: 1rem;
342
859
  }
343
860
 
344
- .feature p {
345
- font-size: 0.9rem;
346
- color: var(--text-dim);
347
- line-height: 1.5;
861
+ .footer-brand {
862
+ font-weight: 600;
863
+ letter-spacing: -0.02em;
348
864
  }
349
865
 
350
- /* ── Footer ── */
351
- footer {
352
- text-align: center;
353
- padding: 2rem;
354
- color: var(--text-dim);
355
- font-size: 0.85rem;
356
- border-top: 1px solid var(--border);
866
+ /* ── Responsive ── */
867
+ @media (max-width: 768px) {
868
+ .bento {
869
+ grid-template-columns: 1fr;
870
+ }
871
+ .bento-card.wide { grid-column: span 1; }
872
+ .bento-card.tall { grid-row: span 1; }
873
+ .hero { padding: 5rem 1.5rem 3rem; }
874
+ .cta-group { flex-direction: column; }
875
+ .nav-links { gap: 1rem; }
876
+ .nav-links a:not(.nav-gh) { display: none; }
877
+ .encrypt-visual { flex-wrap: wrap; justify-content: center; }
357
878
  }
358
879
 
359
- footer a { color: var(--accent); text-decoration: none; }
360
- footer a:hover { text-decoration: underline; }
880
+ @media (max-width: 640px) {
881
+ nav { padding: 1rem 1.25rem; }
882
+ .showcase {
883
+ margin-top: 3rem;
884
+ display: flex;
885
+ justify-content: center;
886
+ align-items: flex-end;
887
+ gap: 0;
888
+ }
889
+ .showcase::after { display: none; }
890
+ .device-ipad {
891
+ width: 78%;
892
+ transform: rotate(0deg);
893
+ flex-shrink: 0;
894
+ }
895
+ .device-ipad:hover { transform: translateY(-8px); }
896
+ .device-iphone {
897
+ width: 28%;
898
+ transform: rotate(0deg) translateY(5%);
899
+ margin-left: -12%;
900
+ flex-shrink: 0;
901
+ justify-self: auto;
902
+ align-self: auto;
903
+ }
904
+ .device-iphone:hover { transform: translateY(-3%); }
905
+ .terminal { margin: 0 1rem; }
906
+ .section-divider { margin: 4rem auto; }
907
+ .bento { padding: 0 1rem; margin: 4rem auto; }
908
+ .bento-card { padding: 1.5rem; border-radius: 16px; }
909
+ .workflow-step { gap: 1rem; }
910
+ .step-marker { width: 40px; height: 40px; border-radius: 12px; font-size: 1rem; }
911
+ .workflow-steps::before { left: 19px; }
912
+ }
361
913
 
362
- /* ── GitHub Corner ── */
363
- .github-corner:hover .octo-arm { animation: octocat-wave 560ms ease-in-out; }
364
- @keyframes octocat-wave {
365
- 0%, 100% { transform: rotate(0); }
366
- 20%, 60% { transform: rotate(-25deg); }
367
- 40%, 80% { transform: rotate(10deg); }
914
+ /* ── Scroll animations ── */
915
+ .reveal {
916
+ opacity: 0;
917
+ transform: translateY(30px);
918
+ transition: opacity 0.8s ease, transform 0.8s ease;
368
919
  }
369
- @media (max-width: 500px) {
370
- .github-corner:hover .octo-arm { animation: none; }
371
- .github-corner .octo-arm { animation: octocat-wave 560ms ease-in-out; }
920
+
921
+ .reveal.visible {
922
+ opacity: 1;
923
+ transform: translateY(0);
372
924
  }
373
925
 
374
926
  .sr-only {
375
927
  position: absolute;
376
- width: 1px;
377
- height: 1px;
378
- padding: 0;
379
- margin: -1px;
928
+ width: 1px; height: 1px;
929
+ padding: 0; margin: -1px;
380
930
  overflow: hidden;
381
931
  clip: rect(0,0,0,0);
382
932
  white-space: nowrap;
383
933
  border: 0;
384
934
  }
385
-
386
- @media (max-width: 640px) {
387
- .hero { padding: 2rem 1.5rem 1.5rem; }
388
- .install { padding: 1.5rem; margin: 2rem 1rem 3rem; }
389
- .showcase { margin-bottom: 3rem; }
390
- .device-ipad { width: 78%; }
391
- .device-iphone { width: 26%; margin-left: -10%; border-radius: 16px; }
392
- .workflow-step { flex-direction: column; gap: 0.75rem; }
393
- .workflow-step .step-icon { width: auto; }
394
- }
395
935
  </style>
396
936
  </head>
397
937
  <body>
398
938
 
939
+ <!-- Ambient background -->
940
+ <div class="ambient" aria-hidden="true">
941
+ <div class="ambient-orb"></div>
942
+ <div class="ambient-orb"></div>
943
+ <div class="ambient-orb"></div>
944
+ </div>
945
+ <div class="grain" aria-hidden="true"></div>
946
+
947
+ <div class="content">
948
+
949
+ <!-- Nav -->
399
950
  <header>
400
951
  <nav>
401
- <div class="logo">Agent<span>Link</span></div>
952
+ <div class="logo">
953
+ <div class="logo-mark">A</div>
954
+ <div class="logo-text">Agent<span>Link</span></div>
955
+ </div>
956
+ <div class="nav-links">
957
+ <a href="#features">Features</a>
958
+ <a href="#how-it-works">How It Works</a>
959
+ <a href="https://github.com/yilee/agentlink" target="_blank" rel="noopener" class="nav-gh">
960
+ <svg viewBox="0 0 16 16" aria-hidden="true"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"/></svg>
961
+ GitHub
962
+ </a>
963
+ </div>
402
964
  </nav>
403
- <a href="https://github.com/yilee/agentlink" target="_blank" rel="noopener" class="github-corner" aria-label="View source on GitHub"><svg width="80" height="80" viewBox="0 0 250 250" style="fill:var(--accent);color:var(--bg);position:absolute;top:0;border:0;right:0;z-index:10" aria-hidden="true"><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin:130px 106px" class="octo-arm"></path><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path></svg></a>
404
965
  </header>
405
966
 
406
967
  <main>
968
+
969
+ <!-- Hero -->
407
970
  <section class="hero">
408
- <h1>Remote Control for<br><em>Claude Code</em></h1>
409
- <p>Start a task in your terminal, close the laptop and go for a walk &mdash; then <strong>pick it up from your phone, a tablet, or any browser</strong>. The session stays alive on your machine.</p>
971
+ <div class="hero-badge">
972
+ <div class="hero-badge-dot"></div>
973
+ Open Source &middot; End-to-End Encrypted
974
+ </div>
975
+ <h1>
976
+ <span class="line">Your Code Follows You.</span>
977
+ <span class="line"><em>Everywhere.</em></span>
978
+ </h1>
979
+ <p class="hero-sub">
980
+ Start Claude Code on your machine. Walk away.
981
+ <strong>Pick it up from your phone, a tablet, or any browser</strong> &mdash;
982
+ fully encrypted, zero configuration.
983
+ </p>
984
+ <div class="cta-group">
985
+ <button class="cta-primary" onclick="copyInstall()">
986
+ <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="4 17 10 11 4 5"></polyline><line x1="12" y1="19" x2="20" y2="19"></line></svg>
987
+ Quick Install
988
+ </button>
989
+ <a href="https://github.com/yilee/agentlink" target="_blank" rel="noopener" class="cta-secondary">
990
+ <svg viewBox="0 0 16 16" aria-hidden="true"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"/></svg>
991
+ View on GitHub
992
+ </a>
993
+ </div>
994
+
995
+ <!-- Terminal -->
996
+ <div class="terminal">
997
+ <div class="terminal-bar">
998
+ <div class="terminal-dot"></div>
999
+ <div class="terminal-dot"></div>
1000
+ <div class="terminal-dot"></div>
1001
+ <div class="terminal-title">Terminal</div>
1002
+ </div>
1003
+ <div class="terminal-body">
1004
+ <div class="terminal-line" onclick="copyCmd('npm install -g @agent-link/agent')">
1005
+ <span class="terminal-prompt">$</span>
1006
+ <span class="terminal-cmd">npm install -g @agent-link/agent</span>
1007
+ </div>
1008
+ <div class="terminal-line" onclick="copyCmd('agentlink-client start -D')">
1009
+ <span class="terminal-prompt">$</span>
1010
+ <span class="terminal-cmd">agentlink-client start -D</span>
1011
+ </div>
1012
+ <div class="terminal-output">
1013
+ Session ready &rarr; <a>https://msclaude.ai/s/abc123</a>
1014
+ </div>
1015
+ </div>
1016
+ </div>
410
1017
  </section>
411
1018
 
412
- <section class="showcase">
1019
+ <!-- Device Showcase -->
1020
+ <section class="showcase reveal">
413
1021
  <div class="device device-ipad">
414
- <img src="/iPad.png" alt="AgentLink web interface running Claude Code on an iPad — chat, file editing, and terminal in a browser" loading="eager">
1022
+ <picture>
1023
+ <source srcset="/iPad.webp" type="image/webp">
1024
+ <img src="/iPad.png" alt="AgentLink web interface running Claude Code on an iPad" loading="eager">
1025
+ </picture>
415
1026
  </div>
416
1027
  <div class="device device-iphone">
417
- <img src="/iPhone.png" alt="AgentLink mobile interface running Claude Code on an iPhone" loading="eager">
1028
+ <picture>
1029
+ <source srcset="/iPhone.webp" type="image/webp">
1030
+ <img src="/iPhone.png" alt="AgentLink mobile interface on iPhone" loading="eager">
1031
+ </picture>
418
1032
  </div>
419
1033
  </section>
420
1034
 
421
- <section class="install">
422
- <div class="install-label">Get started in 30 seconds</div>
423
- <div class="install-step">
424
- <div class="step-num">1</div>
425
- <div class="install-cmd" onclick="copyCmd(this)">
426
- npm install -g @agent-link/agent
427
- <span class="copy-hint">click to copy</span>
1035
+ <div class="section-divider"></div>
1036
+
1037
+ <!-- Philosophy -->
1038
+ <section class="philosophy reveal">
1039
+ <div class="philosophy-label">Philosophy</div>
1040
+ <h2>Code shouldn't be <em>chained to a desk.</em></h2>
1041
+ <p>
1042
+ AgentLink turns Claude Code into a truly portable experience.
1043
+ One command, one URL &mdash; your AI assistant is accessible from any device,
1044
+ with military-grade encryption and zero accounts required.
1045
+ </p>
1046
+ </section>
1047
+
1048
+ <div class="section-divider"></div>
1049
+
1050
+ <!-- Bento Features -->
1051
+ <section class="bento reveal" id="features">
1052
+ <h2 class="sr-only">Features</h2>
1053
+
1054
+ <!-- E2E Encryption — wide -->
1055
+ <div class="bento-card wide">
1056
+ <div class="bento-visual">
1057
+ <div class="encrypt-visual">
1058
+ <div class="encrypt-block">hello world</div>
1059
+ <div class="encrypt-arrow">&rarr;</div>
1060
+ <div class="encrypt-block locked">x9f#k2$mQ...</div>
1061
+ <div class="encrypt-arrow">&rarr;</div>
1062
+ <div class="encrypt-block">hello world</div>
1063
+ </div>
1064
+ </div>
1065
+ <h3>End-to-End Encrypted</h3>
1066
+ <p>XSalsa20-Poly1305 encryption. The relay server is a blind forwarder &mdash; it never sees your code, your prompts, or your data.</p>
1067
+ </div>
1068
+
1069
+ <!-- Zero Config -->
1070
+ <div class="bento-card">
1071
+ <div class="bento-visual">
1072
+ <div class="bento-icon purple">
1073
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"></polygon></svg>
1074
+ </div>
1075
+ </div>
1076
+ <h3>Zero Config</h3>
1077
+ <p>No accounts. No registration. Install, start, open &mdash; done.</p>
1078
+ </div>
1079
+
1080
+ <!-- Any Device -->
1081
+ <div class="bento-card">
1082
+ <div class="bento-visual">
1083
+ <div class="bento-icon cyan">
1084
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="5" y="2" width="14" height="20" rx="2" ry="2"></rect><line x1="12" y1="18" x2="12.01" y2="18"></line></svg>
1085
+ </div>
1086
+ </div>
1087
+ <h3>Any Device</h3>
1088
+ <p>Phone, tablet, laptop &mdash; any browser becomes your Claude Code terminal.</p>
1089
+ </div>
1090
+
1091
+ <!-- Full Claude Code — wide -->
1092
+ <div class="bento-card wide">
1093
+ <div class="bento-visual">
1094
+ <div class="device-flow">
1095
+ <div class="device-pill">
1096
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="4 17 10 11 4 5"></polyline><line x1="12" y1="19" x2="20" y2="19"></line></svg>
1097
+ Terminal
1098
+ </div>
1099
+ <div class="flow-line"></div>
1100
+ <div class="device-pill">
1101
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z"></path><polyline points="14 2 14 8 20 8"></polyline></svg>
1102
+ Files
1103
+ </div>
1104
+ <div class="flow-line"></div>
1105
+ <div class="device-pill">
1106
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line></svg>
1107
+ Search
1108
+ </div>
1109
+ <div class="flow-line"></div>
1110
+ <div class="device-pill">
1111
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path></svg>
1112
+ Chat
1113
+ </div>
1114
+ </div>
1115
+ </div>
1116
+ <h3>Full Claude Code Experience</h3>
1117
+ <p>File editing, shell commands, search, multi-turn conversations &mdash; every capability, now in your browser.</p>
1118
+ </div>
1119
+
1120
+ <!-- Self-hostable -->
1121
+ <div class="bento-card">
1122
+ <div class="bento-visual">
1123
+ <div class="bento-icon green">
1124
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="2" width="20" height="8" rx="2" ry="2"></rect><rect x="2" y="14" width="20" height="8" rx="2" ry="2"></rect><line x1="6" y1="6" x2="6.01" y2="6"></line><line x1="6" y1="18" x2="6.01" y2="18"></line></svg>
1125
+ </div>
1126
+ </div>
1127
+ <h3>Self-Hostable</h3>
1128
+ <p>Run your own relay. Full control over your infrastructure and data.</p>
1129
+ </div>
1130
+
1131
+ <!-- Multi Session -->
1132
+ <div class="bento-card">
1133
+ <div class="bento-visual">
1134
+ <div class="bento-icon blue">
1135
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="3" width="8" height="8" rx="1.5"></rect><rect x="14" y="3" width="8" height="8" rx="1.5"></rect><rect x="2" y="13" width="8" height="8" rx="1.5"></rect><rect x="14" y="13" width="8" height="8" rx="1.5"></rect></svg>
1136
+ </div>
428
1137
  </div>
1138
+ <h3>Multi Session</h3>
1139
+ <p>Run multiple conversations in parallel. Switch between tasks without losing context.</p>
429
1140
  </div>
430
- <div class="install-step">
431
- <div class="step-num">2</div>
432
- <div class="install-cmd" onclick="copyCmd(this)">
433
- agentlink-client start -D
434
- <span class="copy-hint">click to copy</span>
1141
+
1142
+ <!-- Password Protection -->
1143
+ <div class="bento-card">
1144
+ <div class="bento-visual">
1145
+ <div class="bento-icon amber">
1146
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="11" rx="2" ry="2"></rect><path d="M7 11V7a5 5 0 0 1 10 0v4"></path></svg>
1147
+ </div>
435
1148
  </div>
1149
+ <h3>Optional Password</h3>
1150
+ <p>Add <code style="color:var(--green);font-family:'JetBrains Mono',monospace;font-size:0.8rem">--password</code> to lock your session. Brute-force protection built in.</p>
436
1151
  </div>
437
- <div class="install-note">Open the URL it prints. That's it.</div>
438
1152
  </section>
439
1153
 
440
- <section class="workflow">
441
- <h2>How it works</h2>
1154
+ <div class="section-divider"></div>
1155
+
1156
+ <!-- How It Works -->
1157
+ <section class="workflow reveal" id="how-it-works">
1158
+ <div class="workflow-label">How It Works</div>
1159
+ <h2>Four steps. No complexity.</h2>
442
1160
  <div class="workflow-steps">
443
1161
  <div class="workflow-step">
444
- <div class="step-icon">&#128187;</div>
445
- <div>
446
- <h3>Start the agent on your dev machine</h3>
447
- <p>Run <code>agentlink-client start -D</code> in your project directory. It prints a URL like <code>https://msclaude.ai/s/abc123</code>.</p>
1162
+ <div class="step-marker">01</div>
1163
+ <div class="step-content">
1164
+ <h3>Start the agent</h3>
1165
+ <p>Run <code>agentlink-client start -D</code> in your project directory. It prints a unique session URL.</p>
448
1166
  </div>
449
1167
  </div>
450
1168
  <div class="workflow-step">
451
- <div class="step-icon">&#128274;</div>
452
- <div>
453
- <h3>The relay encrypts everything</h3>
454
- <p>Your messages and code travel through the relay server, but it can't read any of it. All traffic is end-to-end encrypted with XSalsa20-Poly1305. The server is a stateless, blind forwarder.</p>
1169
+ <div class="step-marker">02</div>
1170
+ <div class="step-content">
1171
+ <h3>Everything gets encrypted</h3>
1172
+ <p>Your traffic is end-to-end encrypted with XSalsa20-Poly1305. The relay server is stateless &mdash; it forwards bytes it cannot read.</p>
455
1173
  </div>
456
1174
  </div>
457
1175
  <div class="workflow-step">
458
- <div class="step-icon">&#128241;</div>
459
- <div>
460
- <h3>Open the URL on any device</h3>
461
- <p>Your phone, a tablet, a colleague's laptop &mdash; any browser works. Kick off a refactoring task from your desk, then monitor progress from the couch.</p>
1176
+ <div class="step-marker">03</div>
1177
+ <div class="step-content">
1178
+ <h3>Open from anywhere</h3>
1179
+ <p>Phone, tablet, a friend's laptop &mdash; open the URL in any browser. Start a task from your desk, check progress from bed.</p>
462
1180
  </div>
463
1181
  </div>
464
1182
  <div class="workflow-step">
465
- <div class="step-icon">&#128260;</div>
466
- <div>
467
- <h3>Pick up where you left off</h3>
468
- <p>Full session history from Claude Code's own logs. Resume any past conversation, switch projects, change working directories &mdash; all from the browser.</p>
1183
+ <div class="step-marker">04</div>
1184
+ <div class="step-content">
1185
+ <h3>Resume any session</h3>
1186
+ <p>Full history from Claude Code's own logs. Resume conversations, switch projects, change working directories &mdash; all from the browser.</p>
469
1187
  </div>
470
1188
  </div>
471
1189
  </div>
472
1190
  </section>
473
1191
 
474
- <section class="features">
475
- <h2 class="sr-only">Features</h2>
476
- <div class="feature">
477
- <div class="feature-icon">&#9889;</div>
478
- <h3>Zero config</h3>
479
- <p>Install, start, open the URL. No accounts, no registration, no configuration files.</p>
480
- </div>
481
- <div class="feature">
482
- <div class="feature-icon">&#128274;</div>
483
- <h3>Optional password protection</h3>
484
- <p>Add <code style="color:var(--green)">--password</code> to lock your session. Brute-force protection built in.</p>
485
- </div>
486
- <div class="feature">
487
- <div class="feature-icon">&#128196;</div>
488
- <h3>Full Claude Code</h3>
489
- <p>File editing, bash commands, search, multi-turn conversations &mdash; everything Claude Code can do, in your browser.</p>
490
- </div>
491
- <div class="feature">
492
- <div class="feature-icon">&#127760;</div>
493
- <h3>Works on any device</h3>
494
- <p>Responsive UI for phones, tablets, and desktops. Use Claude Code from anywhere with a browser.</p>
495
- </div>
496
- <div class="feature">
497
- <div class="feature-icon">&#128260;</div>
498
- <h3>Auto-reconnect</h3>
499
- <p>Laptop sleeps, Wi-Fi drops, network switches &mdash; the agent reconnects automatically when it's back online. No lost sessions.</p>
500
- </div>
501
- <div class="feature">
502
- <div class="feature-icon">&#128679;</div>
503
- <h3>Self-hostable</h3>
504
- <p>Run your own relay server with <code style="color:var(--green)">@agent-link/server</code>. Full control over your infrastructure.</p>
505
- </div>
506
- </section>
507
1192
  </main>
508
1193
 
509
1194
  <footer>
510
- AgentLink &mdash; Open Source on <a href="https://github.com/yilee/agentlink" rel="noopener">GitHub</a>
1195
+ <div class="footer-links">
1196
+ <span class="footer-brand">AgentLink</span>
1197
+ <a href="https://github.com/yilee/agentlink" rel="noopener">GitHub</a>
1198
+ </div>
1199
+ <p>Open source. Free forever.</p>
511
1200
  </footer>
512
1201
 
1202
+ </div>
1203
+
1204
+ <!-- Toast for copy -->
1205
+ <div class="terminal-copy-toast" id="copyToast">Copied to clipboard</div>
1206
+
513
1207
  <script>
514
- function copyCmd(el) {
515
- const text = el.childNodes[0].textContent.trim();
1208
+ function copyCmd(text) {
516
1209
  navigator.clipboard.writeText(text);
517
- const hint = el.querySelector('.copy-hint');
518
- hint.textContent = 'copied!';
519
- hint.style.opacity = '1';
520
- setTimeout(() => { hint.textContent = 'click to copy'; hint.style.opacity = ''; }, 1500);
1210
+ showToast();
521
1211
  }
1212
+
1213
+ function copyInstall() {
1214
+ navigator.clipboard.writeText('npm install -g @agent-link/agent && agentlink-client start -D');
1215
+ showToast();
1216
+ }
1217
+
1218
+ function showToast() {
1219
+ const toast = document.getElementById('copyToast');
1220
+ toast.classList.add('show');
1221
+ setTimeout(() => toast.classList.remove('show'), 1800);
1222
+ }
1223
+
1224
+ // Scroll reveal
1225
+ const observer = new IntersectionObserver((entries) => {
1226
+ entries.forEach(entry => {
1227
+ if (entry.isIntersecting) {
1228
+ entry.target.classList.add('visible');
1229
+ }
1230
+ });
1231
+ }, { threshold: 0.1, rootMargin: '0px 0px -50px 0px' });
1232
+
1233
+ document.querySelectorAll('.reveal').forEach(el => observer.observe(el));
522
1234
  </script>
523
1235
 
524
1236
  </body>