kamaji-canvas-only.html
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 6 <title>Kamaji - Canvas 2D</title> 7 <style> 8 body { 9 margin: 0; 10 background: #000; 11 display: flex; 12 justify-content: center; 13 align-items: center; 14 min-height: 100vh; 15 overflow: hidden; 16 } 17 canvas { 18 display: block; 19 } 20 </style> 21 </head> 22 <body> 23 <canvas id="kamaji-canvas" width="600" height="600"></canvas> 24 25 <script> 26 const canvas = document.getElementById('kamaji-canvas'); 27 const ctx = canvas.getContext('2d'); 28 const scale = 600 / 280; // Scale from 280x280 to 600x600 29 30 function drawKamaji() { 31 ctx.clearRect(0, 0, canvas.width, canvas.height); 32 33 // Center everything (positioned higher to match PixiJS) 34 ctx.save(); 35 ctx.translate(300, 250); 36 37 // OLIVE GREEN PANTS (cross-legged, low) - MORE SUBSTANTIAL 38 ctx.fillStyle = '#6b7c4a'; 39 ctx.beginPath(); 40 ctx.ellipse(0, 90 * scale, 42 * scale, 28 * scale, 0, 0, Math.PI * 2); 41 ctx.fill(); 42 43 // DARK BLUE SHIRT (hunched, more filled out elderly physique) 44 ctx.fillStyle = '#3a4f6b'; 45 ctx.beginPath(); 46 ctx.ellipse(0, 50 * scale, 48 * scale, 40 * scale, 0, 0, Math.PI * 2); 47 ctx.fill(); 48 49 ctx.fillStyle = '#2a3f5b'; 50 ctx.beginPath(); 51 ctx.ellipse(0, 52 * scale, 46 * scale, 38 * scale, 0, 0, Math.PI * 2); 52 ctx.fill(); 53 54 // LARGE SPHERICAL HEAD - peachy tan, positioned lower for hunch 55 ctx.fillStyle = '#f5d5b8'; 56 ctx.beginPath(); 57 ctx.ellipse(0, 0, 42 * scale, 45 * scale, 0, 0, Math.PI * 2); 58 ctx.fill(); 59 60 ctx.fillStyle = '#d4a574'; 61 ctx.beginPath(); 62 ctx.ellipse(0, scale, 40 * scale, 43 * scale, 0, 0, Math.PI * 2); 63 ctx.fill(); 64 65 // Wispy white hair on SIDES only (bald on top) 66 ctx.fillStyle = 'rgba(232, 232, 232, 0.75)'; 67 ctx.beginPath(); 68 ctx.ellipse(-30 * scale, -25 * scale, 10 * scale, 6 * scale, -0.3, 0, Math.PI * 2); 69 ctx.fill(); 70 ctx.beginPath(); 71 ctx.ellipse(30 * scale, -25 * scale, 10 * scale, 6 * scale, 0.3, 0, Math.PI * 2); 72 ctx.fill(); 73 74 // HUGE ROUND BLACK GLASSES - dominating the face 75 ctx.fillStyle = '#0a0a0a'; 76 ctx.strokeStyle = '#2a2a2a'; 77 ctx.lineWidth = 2.5 * scale; 78 79 ctx.beginPath(); 80 ctx.arc(-25 * scale, -5 * scale, 18 * scale, 0, Math.PI * 2); 81 ctx.fill(); 82 ctx.stroke(); 83 84 ctx.beginPath(); 85 ctx.arc(25 * scale, -5 * scale, 18 * scale, 0, Math.PI * 2); 86 ctx.fill(); 87 ctx.stroke(); 88 89 // Thick glasses bridge 90 ctx.lineWidth = 3 * scale; 91 ctx.beginPath(); 92 ctx.moveTo(-7 * scale, -5 * scale); 93 ctx.lineTo(7 * scale, -5 * scale); 94 ctx.stroke(); 95 96 // Lens reflections 97 ctx.fillStyle = 'rgba(255, 255, 255, 0.25)'; 98 ctx.beginPath(); 99 ctx.ellipse(-30 * scale, -10 * scale, 3 * scale, 4 * scale, 0, 0, Math.PI * 2); 100 ctx.fill(); 101 ctx.beginPath(); 102 ctx.ellipse(20 * scale, -10 * scale, 3 * scale, 4 * scale, 0, 0, Math.PI * 2); 103 ctx.fill(); 104 105 // Small nose 106 ctx.fillStyle = 'rgba(216, 196, 176, 0.5)'; 107 ctx.beginPath(); 108 ctx.ellipse(0, 3 * scale, 4 * scale, 6 * scale, 0, 0, Math.PI * 2); 109 ctx.fill(); 110 111 // WILD BUSHY DARKER BROWN BEARD - LOWER and smaller on face 112 ctx.fillStyle = '#6b5638'; 113 114 ctx.beginPath(); 115 ctx.ellipse(-25 * scale, 45 * scale, 18 * scale, 35 * scale, -0.2, 0, Math.PI * 2); 116 ctx.fill(); 117 118 ctx.beginPath(); 119 ctx.ellipse(25 * scale, 45 * scale, 18 * scale, 35 * scale, 0.2, 0, Math.PI * 2); 120 ctx.fill(); 121 122 ctx.fillStyle = '#7d6644'; 123 ctx.beginPath(); 124 ctx.ellipse(0, 50 * scale, 22 * scale, 38 * scale, 0, 0, Math.PI * 2); 125 ctx.fill(); 126 127 ctx.fillStyle = '#8f7650'; 128 ctx.beginPath(); 129 ctx.ellipse(-15 * scale, 60 * scale, 16 * scale, 32 * scale, -0.1, 0, Math.PI * 2); 130 ctx.fill(); 131 132 ctx.beginPath(); 133 ctx.ellipse(15 * scale, 60 * scale, 16 * scale, 32 * scale, 0.1, 0, Math.PI * 2); 134 ctx.fill(); 135 136 ctx.fillStyle = '#9d865a'; 137 ctx.beginPath(); 138 ctx.ellipse(0, 55 * scale, 16 * scale, 28 * scale, 0, 0, Math.PI * 2); 139 ctx.fill(); 140 141 // FRAYED STRANDS at the bottom 142 ctx.strokeStyle = '#7d6644'; 143 ctx.lineWidth = 2 * scale; 144 ctx.lineCap = 'round'; 145 146 const frayedStrands = [ 147 [[-45, 58], [-48, 72], [-50, 83]], 148 [[-35, 63], [-37, 77], [-40, 90]], 149 [[-25, 68], [-27, 80], [-30, 94]], 150 [[-15, 72], [-16, 84], [-18, 97]], 151 [[-5, 75], [-5, 87], [-5, 100]], 152 [[5, 75], [5, 87], [5, 100]], 153 [[15, 72], [16, 84], [18, 97]], 154 [[25, 68], [27, 80], [30, 94]], 155 [[35, 63], [37, 77], [40, 90]], 156 [[45, 58], [48, 72], [50, 83]], 157 [[-40, 60], [-42, 74], [-45, 87]], 158 [[0, 76], [0, 89], [0, 102]], 159 [[40, 60], [42, 74], [45, 87]], 160 [[-20, 70], [-21, 82], [-23, 95]], 161 [[20, 70], [21, 82], [23, 95]] 162 ]; 163 164 frayedStrands.forEach(points => { 165 ctx.beginPath(); 166 ctx.moveTo(points[0][0] * scale, points[0][1] * scale); 167 points.slice(1).forEach(([x, y]) => ctx.lineTo(x * scale, y * scale)); 168 ctx.stroke(); 169 }); 170 171 // PROMINENT WILD MUSTACHE - DARKER BROWN matching beard 172 ctx.strokeStyle = '#6b5638'; 173 ctx.lineWidth = 8 * scale; 174 ctx.lineCap = 'round'; 175 176 ctx.beginPath(); 177 ctx.moveTo(-40 * scale, 10 * scale); 178 ctx.quadraticCurveTo(-60 * scale, 20 * scale, -80 * scale, 13 * scale); 179 ctx.stroke(); 180 181 ctx.beginPath(); 182 ctx.moveTo(40 * scale, 10 * scale); 183 ctx.quadraticCurveTo(60 * scale, 20 * scale, 80 * scale, 13 * scale); 184 ctx.stroke(); 185 186 ctx.strokeStyle = '#7d6644'; 187 ctx.lineWidth = 6 * scale; 188 189 ctx.beginPath(); 190 ctx.moveTo(-37 * scale, 12 * scale); 191 ctx.quadraticCurveTo(-55 * scale, 21 * scale, -75 * scale, 15 * scale); 192 ctx.stroke(); 193 194 ctx.beginPath(); 195 ctx.moveTo(37 * scale, 12 * scale); 196 ctx.quadraticCurveTo(55 * scale, 21 * scale, 75 * scale, 15 * scale); 197 ctx.stroke(); 198 199 // SIX WORKING ARMS - anatomically connected to torso 200 // LEFT ARMS 201 // Arm 1 (top left) - holding coal 202 ctx.strokeStyle = '#3a4f6b'; 203 ctx.lineWidth = 18 * scale; 204 ctx.lineCap = 'round'; 205 ctx.beginPath(); 206 ctx.moveTo(-35 * scale, 35 * scale); 207 ctx.lineTo(-65 * scale, 20 * scale); 208 ctx.lineTo(-90 * scale, 0); 209 ctx.stroke(); 210 // Hand 211 ctx.fillStyle = '#d4a574'; 212 ctx.beginPath(); 213 ctx.arc(-90 * scale, 0, 10 * scale, 0, Math.PI * 2); 214 ctx.fill(); 215 // Fingers 216 ctx.fillStyle = '#c89860'; 217 for (let i = 0; i < 5; i++) { 218 const fingerY = -8 + i * 4; 219 ctx.fillRect(-100 * scale, fingerY * scale, 8 * scale, 3 * scale); 220 } 221 // Coal chunk (black) 222 ctx.fillStyle = '#1a1a1a'; 223 ctx.beginPath(); 224 ctx.arc(-105 * scale, -5 * scale, 8 * scale, 0, Math.PI * 2); 225 ctx.fill(); 226 227 // Arm 2 (middle left) - sorting herbs 228 ctx.strokeStyle = '#3a4f6b'; 229 ctx.lineWidth = 18 * scale; 230 ctx.beginPath(); 231 ctx.moveTo(-35 * scale, 45 * scale); 232 ctx.lineTo(-70 * scale, 50 * scale); 233 ctx.lineTo(-105 * scale, 45 * scale); 234 ctx.stroke(); 235 // Hand 236 ctx.fillStyle = '#d4a574'; 237 ctx.beginPath(); 238 ctx.arc(-105 * scale, 45 * scale, 10 * scale, 0, Math.PI * 2); 239 ctx.fill(); 240 // Fingers 241 ctx.fillStyle = '#c89860'; 242 for (let i = 0; i < 5; i++) { 243 const fingerY = 37 + i * 4; 244 ctx.fillRect(-115 * scale, fingerY * scale, 8 * scale, 3 * scale); 245 } 246 // Herb (green sprigs) 247 ctx.strokeStyle = '#4a7c4a'; 248 ctx.lineWidth = 3 * scale; 249 ctx.beginPath(); 250 ctx.moveTo(-120 * scale, 40 * scale); 251 ctx.lineTo(-125 * scale, 35 * scale); 252 ctx.moveTo(-118 * scale, 42 * scale); 253 ctx.lineTo(-122 * scale, 37 * scale); 254 ctx.stroke(); 255 256 // Arm 3 (bottom left) - reaching for something 257 ctx.strokeStyle = '#3a4f6b'; 258 ctx.lineWidth = 18 * scale; 259 ctx.beginPath(); 260 ctx.moveTo(-35 * scale, 55 * scale); 261 ctx.lineTo(-60 * scale, 75 * scale); 262 ctx.lineTo(-85 * scale, 85 * scale); 263 ctx.stroke(); 264 // Hand 265 ctx.fillStyle = '#d4a574'; 266 ctx.beginPath(); 267 ctx.arc(-85 * scale, 85 * scale, 10 * scale, 0, Math.PI * 2); 268 ctx.fill(); 269 // Fingers 270 ctx.fillStyle = '#c89860'; 271 for (let i = 0; i < 5; i++) { 272 const fingerY = 77 + i * 4; 273 ctx.fillRect(-95 * scale, fingerY * scale, 8 * scale, 3 * scale); 274 } 275 276 // RIGHT ARMS 277 // Arm 4 (top right) - writing on tablet 278 ctx.strokeStyle = '#3a4f6b'; 279 ctx.lineWidth = 18 * scale; 280 ctx.beginPath(); 281 ctx.moveTo(35 * scale, 35 * scale); 282 ctx.lineTo(70 * scale, 25 * scale); 283 ctx.lineTo(100 * scale, 15 * scale); 284 ctx.stroke(); 285 // Hand 286 ctx.fillStyle = '#d4a574'; 287 ctx.beginPath(); 288 ctx.arc(100 * scale, 15 * scale, 10 * scale, 0, Math.PI * 2); 289 ctx.fill(); 290 // Fingers 291 ctx.fillStyle = '#c89860'; 292 for (let i = 0; i < 5; i++) { 293 const fingerY = 7 + i * 4; 294 ctx.fillRect(102 * scale, fingerY * scale, 8 * scale, 3 * scale); 295 } 296 // Tablet (tan rectangle) 297 ctx.fillStyle = '#d4c4a4'; 298 ctx.fillRect(108 * scale, 5 * scale, 20 * scale, 15 * scale); 299 ctx.strokeStyle = '#8a7a5a'; 300 ctx.lineWidth = 1 * scale; 301 ctx.strokeRect(108 * scale, 5 * scale, 20 * scale, 15 * scale); 302 303 // Arm 5 (middle right) - pulling lever 304 ctx.strokeStyle = '#3a4f6b'; 305 ctx.lineWidth = 18 * scale; 306 ctx.beginPath(); 307 ctx.moveTo(35 * scale, 45 * scale); 308 ctx.lineTo(75 * scale, 55 * scale); 309 ctx.lineTo(110 * scale, 50 * scale); 310 ctx.stroke(); 311 // Hand gripping 312 ctx.fillStyle = '#d4a574'; 313 ctx.beginPath(); 314 ctx.arc(110 * scale, 50 * scale, 10 * scale, 0, Math.PI * 2); 315 ctx.fill(); 316 // Fingers 317 ctx.fillStyle = '#c89860'; 318 for (let i = 0; i < 5; i++) { 319 const fingerY = 42 + i * 4; 320 ctx.fillRect(112 * scale, fingerY * scale, 8 * scale, 3 * scale); 321 } 322 // Lever (wooden handle) 323 ctx.strokeStyle = '#6b4423'; 324 ctx.lineWidth = 6 * scale; 325 ctx.beginPath(); 326 ctx.moveTo(122 * scale, 45 * scale); 327 ctx.lineTo(132 * scale, 35 * scale); 328 ctx.stroke(); 329 330 // Arm 6 (bottom right) - holding coal bucket 331 ctx.strokeStyle = '#3a4f6b'; 332 ctx.lineWidth = 18 * scale; 333 ctx.beginPath(); 334 ctx.moveTo(35 * scale, 55 * scale); 335 ctx.lineTo(65 * scale, 80 * scale); 336 ctx.lineTo(90 * scale, 90 * scale); 337 ctx.stroke(); 338 // Hand 339 ctx.fillStyle = '#d4a574'; 340 ctx.beginPath(); 341 ctx.arc(90 * scale, 90 * scale, 10 * scale, 0, Math.PI * 2); 342 ctx.fill(); 343 // Fingers 344 ctx.fillStyle = '#c89860'; 345 for (let i = 0; i < 5; i++) { 346 const fingerY = 82 + i * 4; 347 ctx.fillRect(92 * scale, fingerY * scale, 8 * scale, 3 * scale); 348 } 349 350 ctx.restore(); 351 } 352 353 // Draw once 354 drawKamaji(); 355 356 // Breathing animation 357 let time = 0; 358 function animate() { 359 time += 0.02; 360 ctx.clearRect(0, 0, canvas.width, canvas.height); 361 ctx.save(); 362 ctx.translate(300, 250 + Math.sin(time) * 4); 363 364 // Draw all elements with breathing offset 365 // OLIVE GREEN PANTS (cross-legged, low) - MORE SUBSTANTIAL 366 ctx.fillStyle = '#6b7c4a'; 367 ctx.beginPath(); 368 ctx.ellipse(0, 90 * scale, 42 * scale, 28 * scale, 0, 0, Math.PI * 2); 369 ctx.fill(); 370 371 // DARK BLUE SHIRT (hunched, more filled out elderly physique) 372 ctx.fillStyle = '#3a4f6b'; 373 ctx.beginPath(); 374 ctx.ellipse(0, 50 * scale, 48 * scale, 40 * scale, 0, 0, Math.PI * 2); 375 ctx.fill(); 376 377 ctx.fillStyle = '#2a3f5b'; 378 ctx.beginPath(); 379 ctx.ellipse(0, 52 * scale, 46 * scale, 38 * scale, 0, 0, Math.PI * 2); 380 ctx.fill(); 381 382 ctx.fillStyle = '#f5d5b8'; 383 ctx.beginPath(); 384 ctx.ellipse(0, 0, 42 * scale, 45 * scale, 0, 0, Math.PI * 2); 385 ctx.fill(); 386 387 ctx.fillStyle = '#d4a574'; 388 ctx.beginPath(); 389 ctx.ellipse(0, scale, 40 * scale, 43 * scale, 0, 0, Math.PI * 2); 390 ctx.fill(); 391 392 ctx.fillStyle = 'rgba(232, 232, 232, 0.75)'; 393 ctx.beginPath(); 394 ctx.ellipse(-30 * scale, -25 * scale, 10 * scale, 6 * scale, -0.3, 0, Math.PI * 2); 395 ctx.fill(); 396 ctx.beginPath(); 397 ctx.ellipse(30 * scale, -25 * scale, 10 * scale, 6 * scale, 0.3, 0, Math.PI * 2); 398 ctx.fill(); 399 400 ctx.fillStyle = '#0a0a0a'; 401 ctx.strokeStyle = '#2a2a2a'; 402 ctx.lineWidth = 2.5 * scale; 403 404 ctx.beginPath(); 405 ctx.arc(-25 * scale, -5 * scale, 18 * scale, 0, Math.PI * 2); 406 ctx.fill(); 407 ctx.stroke(); 408 409 ctx.beginPath(); 410 ctx.arc(25 * scale, -5 * scale, 18 * scale, 0, Math.PI * 2); 411 ctx.fill(); 412 ctx.stroke(); 413 414 ctx.lineWidth = 3 * scale; 415 ctx.beginPath(); 416 ctx.moveTo(-7 * scale, -5 * scale); 417 ctx.lineTo(7 * scale, -5 * scale); 418 ctx.stroke(); 419 420 ctx.fillStyle = 'rgba(255, 255, 255, 0.25)'; 421 ctx.beginPath(); 422 ctx.ellipse(-30 * scale, -10 * scale, 3 * scale, 4 * scale, 0, 0, Math.PI * 2); 423 ctx.fill(); 424 ctx.beginPath(); 425 ctx.ellipse(20 * scale, -10 * scale, 3 * scale, 4 * scale, 0, 0, Math.PI * 2); 426 ctx.fill(); 427 428 ctx.fillStyle = 'rgba(216, 196, 176, 0.5)'; 429 ctx.beginPath(); 430 ctx.ellipse(0, 3 * scale, 4 * scale, 6 * scale, 0, 0, Math.PI * 2); 431 ctx.fill(); 432 433 ctx.fillStyle = '#6b5638'; 434 435 ctx.beginPath(); 436 ctx.ellipse(-25 * scale, 45 * scale, 18 * scale, 35 * scale, -0.2, 0, Math.PI * 2); 437 ctx.fill(); 438 439 ctx.beginPath(); 440 ctx.ellipse(25 * scale, 45 * scale, 18 * scale, 35 * scale, 0.2, 0, Math.PI * 2); 441 ctx.fill(); 442 443 ctx.fillStyle = '#7d6644'; 444 ctx.beginPath(); 445 ctx.ellipse(0, 50 * scale, 22 * scale, 38 * scale, 0, 0, Math.PI * 2); 446 ctx.fill(); 447 448 ctx.fillStyle = '#8f7650'; 449 ctx.beginPath(); 450 ctx.ellipse(-15 * scale, 60 * scale, 16 * scale, 32 * scale, -0.1, 0, Math.PI * 2); 451 ctx.fill(); 452 453 ctx.beginPath(); 454 ctx.ellipse(15 * scale, 60 * scale, 16 * scale, 32 * scale, 0.1, 0, Math.PI * 2); 455 ctx.fill(); 456 457 ctx.fillStyle = '#9d865a'; 458 ctx.beginPath(); 459 ctx.ellipse(0, 55 * scale, 16 * scale, 28 * scale, 0, 0, Math.PI * 2); 460 ctx.fill(); 461 462 ctx.strokeStyle = '#7d6644'; 463 ctx.lineWidth = 2 * scale; 464 ctx.lineCap = 'round'; 465 466 const frayedStrands = [ 467 [[-45, 58], [-48, 72], [-50, 83]], 468 [[-35, 63], [-37, 77], [-40, 90]], 469 [[-25, 68], [-27, 80], [-30, 94]], 470 [[-15, 72], [-16, 84], [-18, 97]], 471 [[-5, 75], [-5, 87], [-5, 100]], 472 [[5, 75], [5, 87], [5, 100]], 473 [[15, 72], [16, 84], [18, 97]], 474 [[25, 68], [27, 80], [30, 94]], 475 [[35, 63], [37, 77], [40, 90]], 476 [[45, 58], [48, 72], [50, 83]], 477 [[-40, 60], [-42, 74], [-45, 87]], 478 [[0, 76], [0, 89], [0, 102]], 479 [[40, 60], [42, 74], [45, 87]], 480 [[-20, 70], [-21, 82], [-23, 95]], 481 [[20, 70], [21, 82], [23, 95]] 482 ]; 483 484 frayedStrands.forEach(points => { 485 ctx.beginPath(); 486 ctx.moveTo(points[0][0] * scale, points[0][1] * scale); 487 points.slice(1).forEach(([x, y]) => ctx.lineTo(x * scale, y * scale)); 488 ctx.stroke(); 489 }); 490 491 ctx.strokeStyle = '#6b5638'; 492 ctx.lineWidth = 8 * scale; 493 ctx.lineCap = 'round'; 494 495 ctx.beginPath(); 496 ctx.moveTo(-40 * scale, 10 * scale); 497 ctx.quadraticCurveTo(-60 * scale, 20 * scale, -80 * scale, 13 * scale); 498 ctx.stroke(); 499 500 ctx.beginPath(); 501 ctx.moveTo(40 * scale, 10 * scale); 502 ctx.quadraticCurveTo(60 * scale, 20 * scale, 80 * scale, 13 * scale); 503 ctx.stroke(); 504 505 ctx.strokeStyle = '#7d6644'; 506 ctx.lineWidth = 6 * scale; 507 508 ctx.beginPath(); 509 ctx.moveTo(-37 * scale, 12 * scale); 510 ctx.quadraticCurveTo(-55 * scale, 21 * scale, -75 * scale, 15 * scale); 511 ctx.stroke(); 512 513 ctx.beginPath(); 514 ctx.moveTo(37 * scale, 12 * scale); 515 ctx.quadraticCurveTo(55 * scale, 21 * scale, 75 * scale, 15 * scale); 516 ctx.stroke(); 517 518 // SIX WORKING ARMS - anatomically connected to torso 519 // LEFT ARMS 520 // Arm 1 (top left) - holding coal 521 ctx.strokeStyle = '#3a4f6b'; 522 ctx.lineWidth = 18 * scale; 523 ctx.lineCap = 'round'; 524 ctx.beginPath(); 525 ctx.moveTo(-35 * scale, 35 * scale); 526 ctx.lineTo(-65 * scale, 20 * scale); 527 ctx.lineTo(-90 * scale, 0); 528 ctx.stroke(); 529 ctx.fillStyle = '#d4a574'; 530 ctx.beginPath(); 531 ctx.arc(-90 * scale, 0, 10 * scale, 0, Math.PI * 2); 532 ctx.fill(); 533 ctx.fillStyle = '#c89860'; 534 for (let i = 0; i < 5; i++) { 535 const fingerY = -8 + i * 4; 536 ctx.fillRect(-100 * scale, fingerY * scale, 8 * scale, 3 * scale); 537 } 538 ctx.fillStyle = '#1a1a1a'; 539 ctx.beginPath(); 540 ctx.arc(-105 * scale, -5 * scale, 8 * scale, 0, Math.PI * 2); 541 ctx.fill(); 542 543 // Arm 2 (middle left) - sorting herbs 544 ctx.strokeStyle = '#3a4f6b'; 545 ctx.lineWidth = 18 * scale; 546 ctx.beginPath(); 547 ctx.moveTo(-35 * scale, 45 * scale); 548 ctx.lineTo(-70 * scale, 50 * scale); 549 ctx.lineTo(-105 * scale, 45 * scale); 550 ctx.stroke(); 551 ctx.fillStyle = '#d4a574'; 552 ctx.beginPath(); 553 ctx.arc(-105 * scale, 45 * scale, 10 * scale, 0, Math.PI * 2); 554 ctx.fill(); 555 ctx.fillStyle = '#c89860'; 556 for (let i = 0; i < 5; i++) { 557 const fingerY = 37 + i * 4; 558 ctx.fillRect(-115 * scale, fingerY * scale, 8 * scale, 3 * scale); 559 } 560 ctx.strokeStyle = '#4a7c4a'; 561 ctx.lineWidth = 3 * scale; 562 ctx.beginPath(); 563 ctx.moveTo(-120 * scale, 40 * scale); 564 ctx.lineTo(-125 * scale, 35 * scale); 565 ctx.moveTo(-118 * scale, 42 * scale); 566 ctx.lineTo(-122 * scale, 37 * scale); 567 ctx.stroke(); 568 569 // Arm 3 (bottom left) - reaching 570 ctx.strokeStyle = '#3a4f6b'; 571 ctx.lineWidth = 18 * scale; 572 ctx.beginPath(); 573 ctx.moveTo(-35 * scale, 55 * scale); 574 ctx.lineTo(-60 * scale, 75 * scale); 575 ctx.lineTo(-85 * scale, 85 * scale); 576 ctx.stroke(); 577 ctx.fillStyle = '#d4a574'; 578 ctx.beginPath(); 579 ctx.arc(-85 * scale, 85 * scale, 10 * scale, 0, Math.PI * 2); 580 ctx.fill(); 581 ctx.fillStyle = '#c89860'; 582 for (let i = 0; i < 5; i++) { 583 const fingerY = 77 + i * 4; 584 ctx.fillRect(-95 * scale, fingerY * scale, 8 * scale, 3 * scale); 585 } 586 587 // RIGHT ARMS 588 // Arm 4 (top right) - writing on tablet 589 ctx.strokeStyle = '#3a4f6b'; 590 ctx.lineWidth = 18 * scale; 591 ctx.beginPath(); 592 ctx.moveTo(35 * scale, 35 * scale); 593 ctx.lineTo(70 * scale, 25 * scale); 594 ctx.lineTo(100 * scale, 15 * scale); 595 ctx.stroke(); 596 ctx.fillStyle = '#d4a574'; 597 ctx.beginPath(); 598 ctx.arc(100 * scale, 15 * scale, 10 * scale, 0, Math.PI * 2); 599 ctx.fill(); 600 ctx.fillStyle = '#c89860'; 601 for (let i = 0; i < 5; i++) { 602 const fingerY = 7 + i * 4; 603 ctx.fillRect(102 * scale, fingerY * scale, 8 * scale, 3 * scale); 604 } 605 ctx.fillStyle = '#d4c4a4'; 606 ctx.fillRect(108 * scale, 5 * scale, 20 * scale, 15 * scale); 607 ctx.strokeStyle = '#8a7a5a'; 608 ctx.lineWidth = 1 * scale; 609 ctx.strokeRect(108 * scale, 5 * scale, 20 * scale, 15 * scale); 610 611 // Arm 5 (middle right) - pulling lever 612 ctx.strokeStyle = '#3a4f6b'; 613 ctx.lineWidth = 18 * scale; 614 ctx.beginPath(); 615 ctx.moveTo(35 * scale, 45 * scale); 616 ctx.lineTo(75 * scale, 55 * scale); 617 ctx.lineTo(110 * scale, 50 * scale); 618 ctx.stroke(); 619 ctx.fillStyle = '#d4a574'; 620 ctx.beginPath(); 621 ctx.arc(110 * scale, 50 * scale, 10 * scale, 0, Math.PI * 2); 622 ctx.fill(); 623 ctx.fillStyle = '#c89860'; 624 for (let i = 0; i < 5; i++) { 625 const fingerY = 42 + i * 4; 626 ctx.fillRect(112 * scale, fingerY * scale, 8 * scale, 3 * scale); 627 } 628 ctx.strokeStyle = '#6b4423'; 629 ctx.lineWidth = 6 * scale; 630 ctx.beginPath(); 631 ctx.moveTo(122 * scale, 45 * scale); 632 ctx.lineTo(132 * scale, 35 * scale); 633 ctx.stroke(); 634 635 // Arm 6 (bottom right) 636 ctx.strokeStyle = '#3a4f6b'; 637 ctx.lineWidth = 18 * scale; 638 ctx.beginPath(); 639 ctx.moveTo(35 * scale, 55 * scale); 640 ctx.lineTo(65 * scale, 80 * scale); 641 ctx.lineTo(90 * scale, 90 * scale); 642 ctx.stroke(); 643 ctx.fillStyle = '#d4a574'; 644 ctx.beginPath(); 645 ctx.arc(90 * scale, 90 * scale, 10 * scale, 0, Math.PI * 2); 646 ctx.fill(); 647 ctx.fillStyle = '#c89860'; 648 for (let i = 0; i < 5; i++) { 649 const fingerY = 82 + i * 4; 650 ctx.fillRect(92 * scale, fingerY * scale, 8 * scale, 3 * scale); 651 } 652 653 ctx.restore(); 654 requestAnimationFrame(animate); 655 } 656 657 animate(); 658 </script> 659 </body> 660 </html>