logo NodeSeekbeta

gemini4网页直出鹈鹕

难道gemini真的王朝了

🖼️预览

6yN1uDdBXlwIK2BSXGoUhJOWs5YBTEmm.gif

💻代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>鹈鹕翘头骑自行车牵引波音747 - SVG 2D动画</title>
  <script src="https://cdn.tailwindcss.com"></script>
  <style>
    @import url('https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@500;700;900&display=swap');

    * {
      box-sizing: border-box;
      user-select: none;
      -webkit-user-select: none;
    }

    body {
      margin: 0;
      padding: 0;
      font-family: 'Noto Sans SC', system-ui, -apple-system, sans-serif;
      background: #0f172a;
      color: #f8fafc;
      overflow-x: hidden;
    }

    .scene-container {
      box-shadow: 0 25px 60px -15px rgba(0, 0, 0, 0.7), 0 0 0 1px rgba(255, 255, 255, 0.12);
    }

    /* Engine turbine spin animation */
    @keyframes spinFast {
      from { transform: rotate(0deg); }
      to { transform: rotate(360deg); }
    }

    .turbine-spin {
      transform-box: fill-box;
      transform-origin: center;
      animation: spinFast 0.18s linear infinite;
    }

    /* Interactive cursor for draggable 747 */
    #boeing-747-group {
      cursor: grab;
      transition: filter 0.2s ease;
    }
    #boeing-747-group:hover {
      filter: drop-shadow(0 0 12px rgba(255, 255, 255, 0.55));
    }
    #boeing-747-group:active {
      cursor: grabbing;
    }

    /* Custom range slider styling */
    input[type="range"] {
      accent-color: #f59e0b;
    }
  </style>
</head>
<body class="min-h-screen flex flex-col items-center justify-between p-3 sm:p-5 bg-gradient-to-b from-slate-950 via-slate-900 to-slate-950">

  <!-- Top Header Bar -->
  <header class="w-full max-w-6xl flex flex-wrap items-center justify-between gap-3 mb-3 px-2">
    <div class="flex items-center gap-3">
      <div class="w-10 h-10 rounded-xl bg-gradient-to-br from-amber-400 to-orange-600 flex items-center justify-center shadow-lg shadow-orange-500/30 text-xl font-black text-slate-950">
        🦩
      </div>
      <div>
        <h1 class="text-lg sm:text-2xl font-black tracking-tight bg-gradient-to-r from-amber-200 via-orange-300 to-sky-300 bg-clip-text text-transparent">
          鹈鹕单轮翘头骑行 × 牵引波音747
        </h1>
        <p class="text-xs sm:text-sm text-slate-400">
          2D 物理联动骨骼与悬链线动画 · 支持鼠标/触控直接拖拽空中的波音747
        </p>
      </div>
    </div>

    <!-- Real-time Telemetry Pill -->
    <div class="flex items-center gap-2 sm:gap-3 bg-slate-900/90 border border-slate-700/80 px-3.5 py-2 rounded-2xl text-xs sm:text-sm shadow-inner">
      <span class="flex items-center gap-1.5 text-amber-400 font-bold">
        <span class="w-2 h-2 rounded-full bg-amber-400 animate-ping"></span>
        翘头倾角: <strong id="pitch-readout" class="font-mono">27.5°</strong>
      </span>
      <span class="text-slate-600">|</span>
      <span class="text-sky-300 font-bold">
        牵引拉力: <strong id="tension-readout" class="font-mono">42.8 kN</strong>
      </span>
      <span class="text-slate-600 hidden sm:inline">|</span>
      <span class="text-emerald-400 font-bold hidden sm:inline">
        地速: <strong id="speed-readout" class="font-mono">38 km/h</strong>
      </span>
    </div>
  </header>

  <!-- Main SVG Animation Viewport -->
  <main class="w-full max-w-6xl flex-1 flex items-center justify-center">
    <div class="scene-container relative w-full aspect-[16/10] max-h-[74vh] rounded-3xl overflow-hidden bg-sky-900 border border-slate-700/70">
      <svg
        id="main-svg"
        viewBox="0 0 1280 800"
        preserveAspectRatio="xMidYMid slice"
        class="w-full h-full block"
        xmlns="http://www.w3.org/2000/svg"
      >
        <defs>
          <!-- Sky Gradients for Day / Sunset / Night -->
          <linearGradient id="sky-grad-day" x1="0%" y1="0%" x2="0%" y2="100%">
            <stop offset="0%" stop-color="#0284c7" />
            <stop offset="48%" stop-color="#38bdf8" />
            <stop offset="85%" stop-color="#bae6fd" />
            <stop offset="100%" stop-color="#fef3c7" />
          </linearGradient>

          <linearGradient id="sky-grad-sunset" x1="0%" y1="0%" x2="0%" y2="100%">
            <stop offset="0%" stop-color="#1e1b4b" />
            <stop offset="35%" stop-color="#7c2d12" />
            <stop offset="70%" stop-color="#ea580c" />
            <stop offset="92%" stop-color="#facc15" />
            <stop offset="100%" stop-color="#fef08a" />
          </linearGradient>

          <linearGradient id="sky-grad-night" x1="0%" y1="0%" x2="0%" y2="100%">
            <stop offset="0%" stop-color="#020617" />
            <stop offset="50%" stop-color="#0f172a" />
            <stop offset="88%" stop-color="#1e293b" />
            <stop offset="100%" stop-color="#334155" />
          </linearGradient>

          <!-- Sun / Moon Glow -->
          <radialGradient id="sun-glow" cx="50%" cy="50%" r="50%">
            <stop offset="0%" stop-color="#fffbeb" stop-opacity="1" />
            <stop offset="35%" stop-color="#fde047" stop-opacity="0.9" />
            <stop offset="70%" stop-color="#f97316" stop-opacity="0.3" />
            <stop offset="100%" stop-color="#f97316" stop-opacity="0" />
          </radialGradient>

          <!-- Distant Mountains Gradient -->
          <linearGradient id="mountain-far" x1="0%" y1="0%" x2="0%" y2="100%">
            <stop offset="0%" stop-color="#64748b" stop-opacity="0.55" />
            <stop offset="100%" stop-color="#94a3b8" stop-opacity="0.2" />
          </linearGradient>

          <linearGradient id="mountain-near" x1="0%" y1="0%" x2="0%" y2="100%">
            <stop offset="0%" stop-color="#334155" stop-opacity="0.75" />
            <stop offset="100%" stop-color="#475569" stop-opacity="0.9" />
          </linearGradient>

          <!-- Road Asphalt Gradient -->
          <linearGradient id="road-grad" x1="0%" y1="0%" x2="0%" y2="100%">
            <stop offset="0%" stop-color="#334155" />
            <stop offset="15%" stop-color="#1e293b" />
            <stop offset="85%" stop-color="#0f172a" />
            <stop offset="100%" stop-color="#020617" />
          </linearGradient>

          <!-- Pelican Pouch (Gular Pouch) Gradient -->
          <linearGradient id="pouch-grad" x1="0%" y1="0%" x2="100%" y2="100%">
            <stop offset="0%" stop-color="#fbbf24" />
            <stop offset="55%" stop-color="#f97316" />
            <stop offset="100%" stop-color="#ea580c" />
          </linearGradient>

          <!-- Pelican Upper Beak Gradient -->
          <linearGradient id="beak-grad" x1="0%" y1="0%" x2="100%" y2="0%">
            <stop offset="0%" stop-color="#fde047" />
            <stop offset="75%" stop-color="#f59e0b" />
            <stop offset="100%" stop-color="#dc2626" />
          </linearGradient>

          <!-- Pelican Feather Body Gradient -->
          <linearGradient id="pelican-body-grad" x1="0%" y1="0%" x2="0%" y2="100%">
            <stop offset="0%" stop-color="#ffffff" />
            <stop offset="70%" stop-color="#f1f5f9" />
            <stop offset="100%" stop-color="#cbd5e1" />
          </linearGradient>

          <!-- Bike Frame Metallic Red/Orange Gradient -->
          <linearGradient id="bike-frame-grad" x1="0%" y1="0%" x2="100%" y2="100%">
            <stop offset="0%" stop-color="#ef4444" />
            <stop offset="50%" stop-color="#dc2626" />
            <stop offset="100%" stop-color="#991b1b" />
          </linearGradient>

          <!-- Chrome / Alloy Rim Gradient -->
          <linearGradient id="chrome-grad" x1="0%" y1="0%" x2="100%" y2="100%">
            <stop offset="0%" stop-color="#f8fafc" />
            <stop offset="50%" stop-color="#94a3b8" />
            <stop offset="100%" stop-color="#475569" />
          </linearGradient>

          <!-- Boeing 747 Fuselage Metallic White/Silver Gradient -->
          <linearGradient id="b747-fuselage-grad" x1="0%" y1="0%" x2="0%" y2="100%">
            <stop offset="0%" stop-color="#ffffff" />
            <stop offset="58%" stop-color="#f8fafc" />
            <stop offset="82%" stop-color="#cbd5e1" />
            <stop offset="100%" stop-color="#64748b" />
          </linearGradient>

          <!-- Boeing 747 Tail Fin Blue/Gold Livery Gradient -->
          <linearGradient id="b747-tail-grad" x1="0%" y1="0%" x2="100%" y2="100%">
            <stop offset="0%" stop-color="#0284c7" />
            <stop offset="55%" stop-color="#1d4ed8" />
            <stop offset="100%" stop-color="#1e3a8a" />
          </linearGradient>

          <!-- Jet Contrail / Exhaust Gradient -->
          <linearGradient id="jet-exhaust-grad" x1="100%" y1="0%" x2="0%" y2="0%">
            <stop offset="0%" stop-color="#38bdf8" stop-opacity="0.85" />
            <stop offset="25%" stop-color="#e0f2fe" stop-opacity="0.65" />
            <stop offset="70%" stop-color="#ffffff" stop-opacity="0.25" />
            <stop offset="100%" stop-color="#ffffff" stop-opacity="0" />
          </linearGradient>

          <!-- Rope Pattern for Braided Look -->
          <linearGradient id="rope-grad" x1="0%" y1="0%" x2="100%" y2="0%">
            <stop offset="0%" stop-color="#d97706" />
            <stop offset="50%" stop-color="#fde68a" />
            <stop offset="100%" stop-color="#b45309" />
          </linearGradient>

          <!-- Soft Shadow Filter -->
          <filter id="drop-shadow" x="-15%" y="-15%" width="135%" height="135%">
            <feDropShadow dx="0" dy="8" stdDeviation="6" flood-color="#0f172a" flood-opacity="0.35" />
          </filter>
        </defs>

        <!-- 1. SKY BACKGROUND -->
        <rect id="sky-rect" x="0" y="0" width="1280" height="650" fill="url(#sky-grad-day)" />

        <!-- Night Stars Layer (visible in night/sunset modes) -->
        <g id="stars-layer" opacity="0" style="transition: opacity 0.6s ease;">
          <circle cx="120" cy="80" r="1.8" fill="#fff" />
          <circle cx="290" cy="45" r="2.4" fill="#fde047" />
          <circle cx="460" cy="110" r="1.5" fill="#fff" />
          <circle cx="650" cy="60" r="2.2" fill="#fff" />
          <circle cx="820" cy="40" r="1.6" fill="#bae6fd" />
          <circle cx="1040" cy="95" r="2.5" fill="#fde047" />
          <circle cx="1180" cy="50" r="1.7" fill="#fff" />
          <circle cx="200" cy="160" r="1.4" fill="#fff" />
          <circle cx="540" cy="180" r="2.0" fill="#fff" />
          <circle cx="950" cy="155" r="1.5" fill="#fff" />
        </g>

        <!-- Sun / Celestial Body -->
        <g id="sun-group" transform="translate(210, 145)">
          <circle cx="0" cy="0" r="95" fill="url(#sun-glow)" />
          <circle cx="0" cy="0" r="42" fill="#fef9c3" />
        </g>

        <!-- 2. PARALLAX CLOUDS (Far & Mid Sky) -->
        <g id="clouds-far-layer" opacity="0.72">
          <g class="cloud-item" data-speed="0.35" data-x="150" data-y="110" data-scale="0.85">
            <path d="M0,0 Q20,-28 52,-18 Q80,-45 120,-20 Q158,-30 175,-2 Q205,2 200,26 Q195,42 165,42 L-10,42 Q-35,42 -30,18 Q-25,0 0,0 Z" fill="#ffffff" />
          </g>
          <g class="cloud-item" data-speed="0.28" data-x="680" data-y="75" data-scale="0.65">
            <path d="M0,0 Q20,-28 52,-18 Q80,-45 120,-20 Q158,-30 175,-2 Q205,2 200,26 Q195,42 165,42 L-10,42 Q-35,42 -30,18 Q-25,0 0,0 Z" fill="#ffffff" />
          </g>
          <g class="cloud-item" data-speed="0.42" data-x="1090" data-y="135" data-scale="0.95">
            <path d="M0,0 Q20,-28 52,-18 Q80,-45 120,-20 Q158,-30 175,-2 Q205,2 200,26 Q195,42 165,42 L-10,42 Q-35,42 -30,18 Q-25,0 0,0 Z" fill="#ffffff" />
          </g>
        </g>

        <!-- Distant Mountain Range (Scrolling slowly left) -->
        <g id="mountains-far" transform="translate(0, 0)">
          <path d="M-100,640 L110,455 L280,565 L490,410 L710,550 L920,435 L1140,560 L1320,445 L1520,570 L1700,420 L1950,640 Z" fill="url(#mountain-far)" />
        </g>
        <g id="mountains-near" transform="translate(0, 0)">
          <path d="M-150,640 L60,520 L230,590 L420,485 L640,585 L830,500 L1050,590 L1240,490 L1460,580 L1680,495 L1900,640 Z" fill="url(#mountain-near)" />
        </g>

        <!-- 3. ROAD & GROUND LAYER -->
        <g id="ground-layer">
          <!-- Roadside Grass Verge -->
          <rect x="0" y="622" width="1280" height="18" fill="#16a34a" />
          <rect x="0" y="636" width="1280" height="6" fill="#15803d" />

          <!-- Main Asphalt Road -->
          <rect x="0" y="640" width="1280" height="160" fill="url(#road-grad)" />

          <!-- Road Top Shoulder Line -->
          <line x1="0" y1="646" x2="1280" y2="646" stroke="#cbd5e1" stroke-width="3" stroke-opacity="0.6" />

          <!-- Scrolling Center Dashed Yellow Road Lines -->
          <g id="road-dashes"></g>

          <!-- Scrolling Roadside Milestones, Shrubs & Pebbles -->
          <g id="road-props"></g>

          <!-- Dynamic Ground Shadow directly under Rear Wheel & Bike -->
          <ellipse id="bike-ground-shadow" cx="370" cy="656" rx="88" ry="11" fill="#020617" opacity="0.55" />
          <!-- Shadow of the 747 far on the road -->
          <ellipse id="plane-ground-shadow" cx="920" cy="662" rx="145" ry="9" fill="#020617" opacity="0.24" />
        </g>

        <!-- 4. BOEING 747 IN THE SKY (Towed by Rope, Facing Right) -->
        <g id="boeing-747-group" filter="url(#drop-shadow)" transform="translate(910, 175) rotate(-8)">
          <!-- Jet Engine Contrails / Airflow Streaks (Streaming Left behind engines) -->
          <g id="jet-contrails">
            <path id="contrail-1" d="M-65,42 Q-210,48 -380,38" stroke="url(#jet-exhaust-grad)" stroke-width="14" stroke-linecap="round" fill="none" />
            <path id="contrail-2" d="M-15,56 Q-180,64 -340,54" stroke="url(#jet-exhaust-grad)" stroke-width="18" stroke-linecap="round" fill="none" />
            <path id="contrail-3" d="M25,22 Q-120,25 -260,18" stroke="url(#jet-exhaust-grad)" stroke-width="11" stroke-linecap="round" fill="none" />
          </g>

          <!-- Far-side (Port/Left) Swept Wing & Far Engines (Behind Fuselage) -->
          <g id="b747-far-wing">
            <!-- Far Wing Surface -->
            <path d="M-20,6 L-125,-34 L-152,-32 L-75,14 Z" fill="#94a3b8" stroke="#475569" stroke-width="1.5" />
            <!-- Winglet Far -->
            <path d="M-125,-34 L-138,-48 L-152,-32 Z" fill="#1d4ed8" />
            <!-- Far Engine #1 -->
            <g transform="translate(-95, -18)">
              <rect x="-16" y="-7" width="28" height="14" rx="5" fill="#64748b" stroke="#334155" stroke-width="1.2" />
              <ellipse cx="12" cy="0" rx="3.5" ry="6.5" fill="#1e293b" />
            </g>
          </g>

          <!-- Tail Horizontal Stabilizer (Far side) -->
          <path d="M-215,2 L-272,-12 L-285,-8 L-240,8 Z" fill="#94a3b8" />

          <!-- Iconic Tall Swept Vertical Stabilizer (Tail Fin) -->
          <g id="b747-tail-fin">
            <path d="M-175,-6 L-248,-108 L-282,-108 L-246,4 Z" fill="url(#b747-tail-grad)" stroke="#1e3a8a" stroke-width="2" />
            <!-- Decorative Airline Golden Speedbird / Globe Emblem on Tail -->
            <path d="M-208,-48 Q-235,-52 -260,-78 Q-238,-42 -222,-32 Z" fill="#fbbf24" />
            <circle cx="-238" cy="-65" r="8" fill="#fde047" opacity="0.9" />
            <!-- Rudder Divider Line -->
            <line x1="-256" y1="-108" x2="-232" y2="-2" stroke="#93c5fd" stroke-width="1.2" stroke-opacity="0.6" />
          </g>

          <!-- MAIN FUSELAGE with Iconic Boeing 747 Upper Deck Hump ("Queen of the Skies" 鹅头双层隆起) -->
          <!-- Facing Right: Tail is on Left (-265), Nose Cone is on Right (+215) -->
          <path
            d="M -265,2
               L -235,-8
               L -70,-12
               C -30,-12, 5,-28, 42,-32
               C 85,-35, 128,-33, 152,-20
               C 168,-11, 182,-4, 198,3
               C 218,11, 224,20, 212,27
               C 198,35, 165,38, 120,38
               L -145,36
               C -195,35, -242,20, -265,8
               Z"
            fill="url(#b747-fuselage-grad)"
            stroke="#334155"
            stroke-width="2.2"
          />

          <!-- Classic Airline Red & Blue Cheatline Stripe along Fuselage -->
          <path
            d="M -252,4 L 198,12 C 208,15 212,19 208,22 L -246,12 Z"
            fill="#dc2626"
          />
          <path
            d="M -246,12 L 208,22 C 204,25 196,27 185,27 L -238,18 Z"
            fill="#1d4ed8"
          />

          <!-- Nose Radome Cone Shading (Right Tip) -->
          <path
            d="M 196,2 C 216,10, 224,20, 212,27 C 204,31, 196,33, 190,34 C 194,22, 195,12, 196,2 Z"
            fill="#1e293b"
          />

          <!-- Cockpit Windshield Windows (Nestled on the front slope of the 747 Upper Deck Hump!) -->
          <path
            d="M 135,-24 L 154,-16 L 150,-8 L 130,-12 Z"
            fill="#0f172a"
            stroke="#38bdf8"
            stroke-width="1.2"
          />
          <line x1="142" y1="-21" x2="140" y2="-10" stroke="#94a3b8" stroke-width="1.2" />

          <!-- Iconic Upper Deck Passenger Windows (2nd Floor Hump Windows!) -->
          <g fill="#0f172a" stroke="#64748b" stroke-width="0.8">
            <rect x="42" y="-23" width="6" height="8" rx="2.5" />
            <rect x="54" y="-23" width="6" height="8" rx="2.5" />
            <rect x="66" y="-23" width="6" height="8" rx="2.5" />
            <rect x="78" y="-23" width="6" height="8" rx="2.5" />
            <rect x="90" y="-23" width="6" height="8" rx="2.5" />
            <rect x="102" y="-22" width="6" height="8" rx="2.5" />
            <rect x="114" y="-21" width="6" height="8" rx="2.5" />
          </g>

          <!-- Main Deck Passenger Windows & Cabin Doors -->
          <g fill="#0f172a">
            <!-- Forward Section Windows -->
            <rect x="155" y="0" width="5.5" height="7.5" rx="2" />
            <rect x="143" y="0" width="5.5" height="7.5" rx="2" />
            <rect x="131" y="0" width="5.5" height="7.5" rx="2" />
            <rect x="119" y="0" width="5.5" height="7.5" rx="2" />
            <!-- Door 1 -->
            <rect x="102" y="-3" width="10" height="16" rx="2" fill="none" stroke="#475569" stroke-width="1.3" />
            <!-- Mid Section Windows -->
            <rect x="85" y="-1" width="5.5" height="7.5" rx="2" />
            <rect x="73" y="-1" width="5.5" height="7.5" rx="2" />
            <rect x="61" y="-1" width="5.5" height="7.5" rx="2" />
            <rect x="49" y="-1" width="5.5" height="7.5" rx="2" />
            <rect x="37" y="-1" width="5.5" height="7.5" rx="2" />
            <rect x="25" y="-1" width="5.5" height="7.5" rx="2" />
            <rect x="13" y="-1" width="5.5" height="7.5" rx="2" />
            <rect x="1" y="-1" width="5.5" height="7.5" rx="2" />
            <!-- Door 2 -->
            <rect x="-15" y="-3" width="10" height="16" rx="2" fill="none" stroke="#475569" stroke-width="1.3" />
            <!-- Aft Section Windows -->
            <rect x="-32" y="-1" width="5.5" height="7.5" rx="2" />
            <rect x="-44" y="-1" width="5.5" height="7.5" rx="2" />
            <rect x="-56" y="-1" width="5.5" height="7.5" rx="2" />
            <rect x="-68" y="-1" width="5.5" height="7.5" rx="2" />
            <rect x="-80" y="-1" width="5.5" height="7.5" rx="2" />
            <rect x="-92" y="-1" width="5.5" height="7.5" rx="2" />
            <rect x="-104" y="-1" width="5.5" height="7.5" rx="2" />
            <rect x="-116" y="-1" width="5.5" height="7.5" rx="2" />
            <rect x="-128" y="-1" width="5.5" height="7.5" rx="2" />
            <rect x="-140" y="-1" width="5.5" height="7.5" rx="2" />
            <rect x="-152" y="-1" width="5.5" height="7.5" rx="2" />
            <rect x="-164" y="-1" width="5.5" height="7.5" rx="2" />
            <!-- Aft Door -->
            <rect x="-184" y="-3" width="10" height="16" rx="2" fill="none" stroke="#475569" stroke-width="1.3" />
          </g>

          <!-- "747 PELICAN AIR" Fuselage Title -->
          <text x="-35" y="-13" font-size="9.5" font-weight="900" fill="#1e3a8a" letter-spacing="1.5">BOEING 747-400</text>

          <!-- Near-Side (Starboard/Right) Swept Main Wing & Two Big Underwing Turbofan Engines -->
          <g id="b747-near-wing">
            <!-- Wing Root Fairing -->
            <ellipse cx="15" cy="28" rx="58" ry="9" fill="#e2e8f0" stroke="#94a3b8" stroke-width="1" />

            <!-- Swept Main Wing Surface (extending back and down-left in perspective) -->
            <path
              d="M 55,22 L -95,62 L -132,60 L -25,20 Z"
              fill="#f1f5f9"
              stroke="#475569"
              stroke-width="2"
            />
            <!-- Wing Flap Corrugations -->
            <line x1="-10" y1="28" x2="-102" y2="57" stroke="#94a3b8" stroke-width="1.4" />
            <!-- Iconic 747-400 Angled Winglet (Near Wingtip) -->
            <path d="M -95,62 L -114,44 L -132,60 Z" fill="#dc2626" stroke="#991b1b" stroke-width="1.2" />

            <!-- Near-Side Engine #3 (Outboard Underwing Pylon & Turbofan Pod) -->
            <g transform="translate(-52, 56)">
              <!-- Pylon Strut -->
              <path d="M -5,-8 L 8,-12 L 14,-2 L -2,-2 Z" fill="#94a3b8" />
              <!-- Exhaust Nozzle Cone -->
              <path d="M -24,-6 L -12,-9 L -12,9 L -24,6 Z" fill="#334155" />
              <!-- Engine Cowling Nacelle -->
              <rect x="-14" y="-11" width="36" height="22" rx="7" fill="#ffffff" stroke="#334155" stroke-width="1.8" />
              <line x1="-6" y1="-10" x2="-6" y2="10" stroke="#dc2626" stroke-width="2.5" />
              <!-- Front Air Intake & Spinning Fan Blades -->
              <ellipse cx="22" cy="0" rx="5" ry="10" fill="#0f172a" stroke="#cbd5e1" stroke-width="1.5" />
              <g transform="translate(22, 0)">
                <g class="turbine-spin">
                  <line x1="-3" y1="-7" x2="3" y2="7" stroke="#94a3b8" stroke-width="1.6" />
                  <line x1="-3" y1="7" x2="3" y2="-7" stroke="#94a3b8" stroke-width="1.6" />
                  <circle cx="0" cy="0" r="2.2" fill="#f8fafc" />
                </g>
              </g>
            </g>

            <!-- Near-Side Engine #2 (Inboard Underwing Pylon & Larger Turbofan Pod) -->
            <g transform="translate(8, 42)">
              <!-- Pylon Strut -->
              <path d="M -6,-10 L 10,-15 L 16,-3 L -2,-3 Z" fill="#94a3b8" />
              <!-- Exhaust Nozzle Cone -->
              <path d="M -28,-7 L -14,-11 L -14,11 L -28,7 Z" fill="#334155" />
              <!-- Engine Cowling Nacelle -->
              <rect x="-16" y="-13" width="42" height="26" rx="8" fill="#ffffff" stroke="#334155" stroke-width="2" />
              <line x1="-6" y1="-12" x2="-6" y2="12" stroke="#dc2626" stroke-width="3" />
              <!-- Front Air Intake & Spinning Fan Blades -->
              <ellipse cx="26" cy="0" rx="5.5" ry="12" fill="#0f172a" stroke="#cbd5e1" stroke-width="1.8" />
              <g transform="translate(26, 0)">
                <g class="turbine-spin">
                  <line x1="-3.5" y1="-8.5" x2="3.5" y2="8.5" stroke="#cbd5e1" stroke-width="1.8" />
                  <line x1="-3.5" y1="8.5" x2="3.5" y2="-8.5" stroke="#cbd5e1" stroke-width="1.8" />
                  <circle cx="0" cy="0" r="2.5" fill="#f8fafc" />
                </g>
              </g>
            </g>
          </g>

          <!-- Tail Horizontal Stabilizer (Near side) -->
          <path d="M -205,12 L -268,26 L -284,22 L -235,8 Z" fill="#e2e8f0" stroke="#475569" stroke-width="1.6" />

          <!-- Tow Hook / Bridle Ring under Forward Fuselage (at local coordinates (125, 39)) -->
          <g id="b747-tow-ring" transform="translate(125, 39)">
            <path d="M -10,-2 L 10,-2 L 6,7 L -6,7 Z" fill="#f59e0b" stroke="#78350f" stroke-width="1.5" />
            <circle cx="0" cy="9" r="5.5" fill="none" stroke="#fbbf24" stroke-width="3" />
          </g>

          <!-- Blinking Navigation Strobes -->
          <circle cx="145" cy="-26" r="3.5" fill="#ef4444">
            <animate attributeName="opacity" values="1;0.1;1" dur="0.9s" repeatCount="indefinite" />
          </circle>
          <circle cx="-114" cy="44" r="3" fill="#22c55e">
            <animate attributeName="opacity" values="0.2;1;0.2" dur="1.1s" repeatCount="indefinite" />
          </circle>
          <circle cx="-265" cy="-108" r="3.5" fill="#ffffff">
            <animate attributeName="opacity" values="1;0;1" dur="0.7s" repeatCount="indefinite" />
          </circle>
        </g>

        <!-- 5. TOW ROPE CONNECTING BIKE HANDLEBAR TO BOEING 747 -->
        <g id="tow-rope-layer">
          <!-- Rope Shadow / Outer Casing -->
          <path id="tow-rope-outline" d="" fill="none" stroke="#451a03" stroke-width="8" stroke-linecap="round" />
          <!-- Main Braided Rope Core -->
          <path id="tow-rope-main" d="" fill="none" stroke="url(#rope-grad)" stroke-width="5" stroke-linecap="round" />
          <!-- Dashed Twist Texture along Rope -->
          <path id="tow-rope-twist" d="" fill="none" stroke="#78350f" stroke-width="4" stroke-dasharray="7 9" stroke-linecap="round" />

          <!-- Red Aviation Tow Pennant Flag fluttering in the middle of the rope -->
          <g id="rope-pennant" transform="translate(700, 260)">
            <path id="pennant-shape" d="M 0,0 L -38,12 L -28,0 L -42,-10 Z" fill="#ef4444" stroke="#991b1b" stroke-width="1.5" />
            <circle cx="0" cy="0" r="3.5" fill="#fde047" stroke="#78350f" stroke-width="1.2" />
          </g>
        </g>

        <!-- 6. PELICAN & WHEELIE BICYCLE ASSEMBLY (Pivoting around Rear Wheel Axle (350, 576)) -->
        <!-- Rear Wheel radius = 66, so bottom of tire touches road at y = 576 + 66 = 642 -->
        <g id="wheelie-assembly" transform="translate(0, 0)">

          <!-- 6A. PELICAN FAR LEG (Left Leg behind bike frame, dynamically driven by IK) -->
          <g id="pelican-left-leg">
            <!-- Left Thigh -->
            <line id="leg-l-thigh" x1="370" y1="430" x2="430" y2="480" stroke="#e2e8f0" stroke-width="14" stroke-linecap="round" />
            <!-- Left Knee Joint -->
            <circle id="leg-l-knee" cx="430" cy="480" r="6" fill="#ea580c" />
            <!-- Left Orange Scaly Shin -->
            <line id="leg-l-shin" x1="430" y1="480" x2="445" y2="540" stroke="#ea580c" stroke-width="8.5" stroke-linecap="round" />
            <!-- Left Webbed Foot on Left Pedal -->
            <path id="leg-l-foot" d="M 435,540 L 465,536 L 460,546 L 435,545 Z" fill="#c2410c" stroke="#7c2d12" stroke-width="1.5" />
          </g>

          <!-- Far Pedal Crank Arm (Left Crank behind frame) -->
          <g id="crank-left-group">
            <line id="crank-l-arm" x1="452" y1="538" x2="452" y2="568" stroke="#64748b" stroke-width="7" stroke-linecap="round" />
            <rect id="pedal-l-body" x="438" y="564" width="28" height="8" rx="3" fill="#1e293b" stroke="#475569" stroke-width="1.5" />
          </g>

          <!-- Pelican Far Wing (Left Wing reaching toward handlebar behind neck) -->
          <path
            id="pelican-left-wing"
            d="M 412,385 Q 475,365 538,352 Q 492,390 422,405 Z"
            fill="#cbd5e1"
            stroke="#64748b"
            stroke-width="2"
          />

          <!-- 6B. REAR WHEEL (Supporting the entire wheelie on the road at (350, 576)) -->
          <g id="rear-wheel-center" transform="translate(350, 576)">
            <g id="rear-wheel-spin">
              <!-- Outer Rubber Tire -->
              <circle cx="0" cy="0" r="66" fill="none" stroke="#0f172a" stroke-width="13" />
              <!-- Tire Tread Notches -->
              <circle cx="0" cy="0" r="66" fill="none" stroke="#334155" stroke-width="13" stroke-dasharray="8 12" />
              <!-- Alloy Rim -->
              <circle cx="0" cy="0" r="56" fill="none" stroke="url(#chrome-grad)" stroke-width="4.5" />
              <!-- High-visibility Orange Rim Stripe -->
              <circle cx="0" cy="0" r="52" fill="none" stroke="#f97316" stroke-width="2" stroke-dasharray="28 18" />
              <!-- Wheel Spokes (12 spokes) -->
              <g stroke="#cbd5e1" stroke-width="1.8">
                <line x1="-54" y1="0" x2="54" y2="0" />
                <line x1="0" y1="-54" x2="0" y2="54" />
                <line x1="-38" y1="-38" x2="38" y2="38" />
                <line x1="-38" y1="38" x2="38" y2="-38" />
                <line x1="-47" y1="-27" x2="47" y2="27" />
                <line x1="-27" y1="-47" x2="27" y2="47" />
                <line x1="-47" y1="27" x2="47" y2="-27" />
                <line x1="-27" y1="47" x2="27" y2="-47" />
              </g>
              <!-- Gold Tire Valve & Reflector -->
              <rect x="28" y="-8" width="12" height="6" rx="2" fill="#facc15" stroke="#ca8a04" stroke-width="1" />
              <!-- Rear Sprocket Cassette -->
              <circle cx="0" cy="0" r="15" fill="#475569" stroke="#1e293b" stroke-width="2" stroke-dasharray="4 3" />
            </g>
            <!-- Rear Hub Center -->
            <circle cx="0" cy="0" r="8" fill="#e2e8f0" stroke="#1e293b" stroke-width="2.5" />
          </g>

          <!-- 6C. FRONT WHEEL (Lifted high in the air doing a wheelie at (622, 456)!) -->
          <g id="front-wheel-center" transform="translate(622, 456)">
            <!-- Motion Blur Arc around elevated spinning front wheel -->
            <path d="M -76,-15 A 78,78 0 0,1 65,-42" fill="none" stroke="#ffffff" stroke-width="2.5" stroke-opacity="0.45" stroke-dasharray="18 12" />
            <g id="front-wheel-spin">
              <!-- Outer Rubber Tire -->
              <circle cx="0" cy="0" r="66" fill="none" stroke="#0f172a" stroke-width="13" />
              <!-- Tire Tread Notches -->
              <circle cx="0" cy="0" r="66" fill="none" stroke="#334155" stroke-width="13" stroke-dasharray="8 12" />
              <!-- Alloy Rim -->
              <circle cx="0" cy="0" r="56" fill="none" stroke="url(#chrome-grad)" stroke-width="4.5" />
              <!-- High-visibility Orange Rim Stripe -->
              <circle cx="0" cy="0" r="52" fill="none" stroke="#f97316" stroke-width="2" stroke-dasharray="28 18" />
              <!-- Wheel Spokes -->
              <g stroke="#cbd5e1" stroke-width="1.8">
                <line x1="-54" y1="0" x2="54" y2="0" />
                <line x1="0" y1="-54" x2="0" y2="54" />
                <line x1="-38" y1="-38" x2="38" y2="38" />
                <line x1="-38" y1="38" x2="38" y2="-38" />
                <line x1="-47" y1="-27" x2="47" y2="27" />
                <line x1="-27" y1="-47" x2="27" y2="47" />
                <line x1="-47" y1="27" x2="47" y2="-27" />
                <line x1="-27" y1="47" x2="27" y2="-47" />
              </g>
              <!-- Reflector -->
              <rect x="-40" y="-8" width="12" height="6" rx="2" fill="#facc15" stroke="#ca8a04" stroke-width="1" />
              <!-- Front Brake Disc -->
              <circle cx="0" cy="0" r="16" fill="none" stroke="#94a3b8" stroke-width="3" stroke-dasharray="5 3" />
            </g>
            <!-- Front Hub Center -->
            <circle cx="0" cy="0" r="8" fill="#e2e8f0" stroke="#1e293b" stroke-width="2.5" />
          </g>

          <!-- 6D. BICYCLE DRIVETRAIN & FRAME (Pitched up in Wheelie Posture, Facing Right) -->
          <g id="bicycle-frame">
            <!-- Drive Chain Loop connecting Rear Hub (350, 576) and Bottom Bracket (452, 538) -->
            <path
              id="bike-chain"
              d="M 346,562 L 448,516 A 22,22 0 1,1 456,560 L 354,590 A 14,14 0 1,1 346,562 Z"
              fill="none"
              stroke="#1e293b"
              stroke-width="4"
              stroke-dasharray="6 4"
            />

            <!-- Rear Fender / Mudguard -->
            <path d="M 278,568 A 74,74 0 0,1 368,504" fill="none" stroke="#f59e0b" stroke-width="6" stroke-linecap="round" />

            <!-- Frame Tubes (Red Metallic Tubing) -->
            <!-- Chainstay: Rear Axle (350,576) -> Bottom Bracket (452,538) -->
            <line x1="350" y1="576" x2="452" y2="538" stroke="url(#bike-frame-grad)" stroke-width="10" stroke-linecap="round" />
            <!-- Seatstay: Rear Axle (350,576) -> Seat Cluster (384,442) -->
            <line x1="350" y1="576" x2="384" y2="442" stroke="url(#bike-frame-grad)" stroke-width="9" stroke-linecap="round" />
            <!-- Seat Tube: Bottom Bracket (452,538) -> Seat Cluster (384,442) -->
            <line x1="452" y1="538" x2="384" y2="442" stroke="url(#bike-frame-grad)" stroke-width="11" stroke-linecap="round" />
            <!-- Down Tube: Bottom Bracket (452,538) -> Head Tube Lower (562,406) -->
            <line x1="452" y1="538" x2="562" y2="406" stroke="url(#bike-frame-grad)" stroke-width="13" stroke-linecap="round" />
            <!-- Top Tube: Seat Cluster (384,442) -> Head Tube Upper (546,374) -->
            <line x1="384" y1="442" x2="546" y2="374" stroke="url(#bike-frame-grad)" stroke-width="11" stroke-linecap="round" />

            <!-- Frame Brand Decal -->
            <text x="458" y="476" transform="rotate(-48, 458, 476)" font-size="8.5" font-weight="900" fill="#fef08a" letter-spacing="1.2">PELICAN-PRO</text>

            <!-- Seatpost & Saddle -->
            <line x1="384" y1="442" x2="372" y2="420" stroke="#94a3b8" stroke-width="8" stroke-linecap="round" />
            <path d="M 342,418 Q 372,412 402,420 Q 396,430 370,428 Q 348,428 342,418 Z" fill="#1e293b" stroke="#0f172a" stroke-width="2" />

            <!-- Front Fork: Head Tube Lower (562,406) -> Front Wheel Axle (622,456) -->
            <path d="M 558,402 L 622,456" stroke="url(#chrome-grad)" stroke-width="10" stroke-linecap="round" />
            <path d="M 558,402 L 622,456" stroke="#f59e0b" stroke-width="4" stroke-linecap="round" />

            <!-- Head Tube & Handlebar Stem (Facing Right) -->
            <line x1="542" y1="368" x2="566" y2="412" stroke="url(#bike-frame-grad)" stroke-width="14" stroke-linecap="round" />
            <!-- Chrome Riser Stem & Curved Cruiser/BMX Handlebars -->
            <path d="M 544,370 L 558,342 L 535,346" fill="none" stroke="#e2e8f0" stroke-width="8" stroke-linecap="round" stroke-linejoin="round" />
            <!-- Classic Vintage Headlight on Front of Stem (Facing Right!) -->
            <path d="M 562,350 L 578,344 L 578,360 L 562,356 Z" fill="#facc15" stroke="#ca8a04" stroke-width="1.5" />
            <!-- Headlight Beam Cone -->
            <path id="headlight-beam" d="M 578,346 L 675,315 L 685,375 L 578,358 Z" fill="#fef08a" opacity="0.22" />

            <!-- TOW ROPE KNOT ON HANDLEBAR STEM (Exact anchor point at local (562, 342)) -->
            <g id="handlebar-rope-knot" transform="translate(562, 342)">
              <circle cx="0" cy="0" r="8" fill="#d97706" stroke="#78350f" stroke-width="2.2" />
              <path d="M -5,-4 Q 0,-9 6,-3 Q 4,5 -4,4 Z" fill="#fbbf24" stroke="#78350f" stroke-width="1.5" />
            </g>

            <!-- Handlebar Rubber Grip (at (532, 347)) -->
            <rect x="518" y="341" width="22" height="10" rx="5" transform="rotate(-12, 529, 346)" fill="#0f172a" stroke="#f59e0b" stroke-width="1.5" />

            <!-- Bottom Bracket Chainring (at (452, 538)) -->
            <g transform="translate(452, 538)">
              <g id="chainring-spin">
                <circle cx="0" cy="0" r="23" fill="#334155" stroke="#94a3b8" stroke-width="3" stroke-dasharray="5 3" />
                <circle cx="0" cy="0" r="16" fill="none" stroke="#cbd5e1" stroke-width="2" />
                <line x1="-20" y1="0" x2="20" y2="0" stroke="#94a3b8" stroke-width="3" />
                <line x1="0" y1="-20" x2="0" y2="20" stroke="#94a3b8" stroke-width="3" />
              </g>
              <circle cx="0" cy="0" r="6" fill="#e2e8f0" />
            </g>
          </g>

          <!-- 6E. PELICAN BODY, NECK, HEAD & ICONIC GULAR POUCH (Facing Right) -->
          <g id="pelican-character">
            <!-- Plump White Feathered Torso sitting on Saddle -->
            <path
              d="M 332,402
                 L 310,392
                 L 325,384
                 L 308,374
                 L 335,372
                 C 355,342, 412,338, 434,368
                 C 448,388, 436,422, 405,426
                 C 374,430, 346,420, 332,402 Z"
              fill="url(#pelican-body-grad)"
              stroke="#475569"
              stroke-width="2.5"
              stroke-linejoin="round"
            />
            <!-- Subtle Feather Wing Scallops on Back -->
            <path d="M 358,366 Q 382,376 404,364" fill="none" stroke="#94a3b8" stroke-width="2" stroke-linecap="round" />
            <path d="M 350,382 Q 376,392 400,378" fill="none" stroke="#94a3b8" stroke-width="2" stroke-linecap="round" />

            <!-- Pelican Long Curved S-Neck & Head (bobbing slightly with pedaling effort) -->
            <g id="pelican-head-group" transform="translate(0, 0)">
              <!-- S-Curved White Neck rising from Chest (422, 368) to Head (458, 268) -->
              <path
                d="M 412,374
                   C 402,340, 422,300, 436,274
                   C 442,256, 464,250, 476,262
                   C 484,272, 476,292, 464,306
                   C 448,326, 438,354, 434,378 Z"
                fill="url(#pelican-body-grad)"
                stroke="#475569"
                stroke-width="2.5"
              />

              <!-- Tuft of Feathers on Crown of Head -->
              <path d="M 442,256 L 426,244 L 446,250 L 434,236 L 456,248 Z" fill="#f8fafc" stroke="#475569" stroke-width="2" stroke-linejoin="round" />

              <!-- ICONIC GIANT PELICAN THROAT POUCH (Gular Pouch - 弹性大喉囊, Facing Right) -->
              <path
                id="pelican-pouch"
                d="M 472,278
                   L 598,282
                   C 592,324, 548,344, 504,334
                   C 476,328, 464,304, 472,278 Z"
                fill="url(#pouch-grad)"
                stroke="#9a3412"
                stroke-width="2.5"
                stroke-linejoin="round"
              />
              <!-- Pouch Stretch Ribs / Striations -->
              <path d="M 488,284 Q 505,318 532,326" fill="none" stroke="#c2410c" stroke-width="1.6" stroke-opacity="0.65" />
              <path d="M 518,284 Q 532,314 558,318" fill="none" stroke="#c2410c" stroke-width="1.6" stroke-opacity="0.65" />

              <!-- Cute Little Fish Tail Poking Out of the Pelican's Beak Pouch! -->
              <g id="pouch-fish" transform="translate(556, 280)">
                <path d="M 0,0 L 16,-12 L 13,-1 L 20,6 L 2,3 Z" fill="#38bdf8" stroke="#0369a1" stroke-width="1.5" />
              </g>

              <!-- LONG UPPER BEAK with Hooked Tip (Pointing Right!) -->
              <path
                d="M 472,262
                   L 596,274
                   C 606,275, 610,283, 603,290
                   L 597,293
                   L 594,284
                   L 470,280 Z"
                fill="url(#beak-grad)"
                stroke="#9a3412"
                stroke-width="2.2"
                stroke-linejoin="round"
              />

              <!-- Pelican Eye & Cool Aviator Sunglasses -->
              <circle cx="464" cy="266" r="7.5" fill="#fef08a" stroke="#475569" stroke-width="1.8" />
              <circle cx="466" cy="266" r="3.5" fill="#0f172a" />
              <circle cx="467.5" cy="264.5" r="1.3" fill="#ffffff" />

              <!-- Aviator Captain Cap on Pelican's Head -->
              <g transform="translate(454, 246) rotate(-10)">
                <path d="M -18,4 C -16,-10, 12,-12, 18,2 Z" fill="#1e3a8a" stroke="#0f172a" stroke-width="1.8" />
                <path d="M -16,3 L 26,3 L 22,8 L -16,6 Z" fill="#0f172a" />
                <circle cx="2" cy="-2" r="3.5" fill="#fbbf24" />
              </g>

              <!-- Fluttering Red Aviator Scarf Streaming Left in the Wind -->
              <g id="pelican-scarf" transform="translate(432, 332)">
                <path
                  id="scarf-tail"
                  d="M 0,0 Q -38,-12 -72,4 Q -98,16 -122,2 Q -90,26 -56,16 Q -25,8 4,12 Z"
                  fill="#ef4444"
                  stroke="#991b1b"
                  stroke-width="1.8"
                />
                <ellipse cx="4" cy="6" rx="14" ry="7" transform="rotate(18)" fill="#dc2626" stroke="#991b1b" stroke-width="1.8" />
              </g>
            </g>

            <!-- Near Pedal Crank Arm (Right Crank in foreground) -->
            <g id="crank-right-group">
              <line id="crank-r-arm" x1="452" y1="538" x2="452" y2="510" stroke="#cbd5e1" stroke-width="7.5" stroke-linecap="round" />
              <rect id="pedal-r-body" x="438" y="506" width="28" height="8" rx="3" fill="#0f172a" stroke="#f59e0b" stroke-width="1.8" />
            </g>

            <!-- 6F. PELICAN NEAR LEG (Right Leg in foreground, dynamically driven by IK) -->
            <g id="pelican-right-leg">
              <!-- Fluffy White Upper Thigh -->
              <line id="leg-r-thigh" x1="382" y1="422" x2="442" y2="468" stroke="#ffffff" stroke-width="16" stroke-linecap="round" />
              <line id="leg-r-thigh-inner" x1="382" y1="422" x2="442" y2="468" stroke="#f1f5f9" stroke-width="12" stroke-linecap="round" />
              <!-- Orange Knee Joint -->
              <circle id="leg-r-knee" cx="442" cy="468" r="6.5" fill="#f97316" stroke="#9a3412" stroke-width="1.5" />
              <!-- Orange Lower Shin -->
              <line id="leg-r-shin" x1="442" y1="468" x2="452" y2="510" stroke="#f97316" stroke-width="9" stroke-linecap="round" />
              <!-- Webbed Orange Foot firmly pressing the Right Pedal -->
              <path id="leg-r-foot" d="M 442,510 L 474,506 L 468,516 L 442,515 Z" fill="#fb923c" stroke="#9a3412" stroke-width="1.8" />
            </g>

            <!-- 6G. PELICAN NEAR WING (Right Wing stretching forward to grip the Handlebar!) -->
            <g id="pelican-right-wing-group">
              <path
                id="pelican-right-wing"
                d="M 402,378
                   C 438,358, 488,342, 532,346
                   C 538,347, 540,355, 530,358
                   C 492,368, 448,398, 412,402
                   C 396,402, 392,386, 402,378 Z"
                fill="#ffffff"
                stroke="#475569"
                stroke-width="2.5"
                stroke-linejoin="round"
              />
              <!-- Wing Primary Feather Details gripping the handlebar -->
              <path d="M 442,384 Q 482,368 522,354" fill="none" stroke="#94a3b8" stroke-width="2" stroke-linecap="round" />
              <path d="M 426,392 Q 468,378 510,360" fill="none" stroke="#94a3b8" stroke-width="2" stroke-linecap="round" />
            </g>
          </g>

          <!-- Wheelie Balance Sparks / Tire Dust Particles behind Rear Wheel Contact Point -->
          <g id="wheel-dust-layer"></g>
        </g>

        <!-- 7. FOREGROUND WIND SPEED STREAKS (Moving Left to emphasize rightward motion) -->
        <g id="wind-lines-layer"></g>

        <!-- 8. ON-CANVAS VECTOR LABELS (Subtle callouts) -->
        <g id="hud-annotations" opacity="0.88" class="pointer-events-none">
          <!-- Callout badge near 747 Hump -->
          <g id="callout-747" transform="translate(880, 68)">
            <rect x="-95" y="-18" width="190" height="26" rx="13" fill="#0f172a" fill-opacity="0.72" stroke="#38bdf8" stroke-width="1.2" />
            <text x="0" y="-1" text-anchor="middle" fill="#e0f2fe" font-size="11" font-weight="700">✈️ 波音747 (可按住拖动位置)</text>
          </g>
        </g>
      </svg>

      <!-- Floating Boost Toast Notification -->
      <div
        id="boost-toast"
        class="pointer-events-none absolute top-4 left-4 bg-amber-500/95 text-slate-950 font-black text-xs sm:text-sm px-3.5 py-1.5 rounded-full shadow-lg opacity-0 transition-opacity duration-300"
      >
        🔥 涡轮蹬车加速!波音747拉升中!
      </div>
    </div>
  </main>

  <!-- Interactive Control Panel -->
  <footer class="w-full max-w-6xl mt-3 bg-slate-900/90 border border-slate-800 rounded-2xl p-3 sm:px-6 sm:py-3.5 flex flex-wrap items-center justify-between gap-4 shadow-xl">
    <!-- Sliders Group -->
    <div class="flex flex-wrap items-center gap-4 sm:gap-6">
      <!-- Speed Control -->
      <label class="flex items-center gap-2.5 text-xs sm:text-sm font-medium text-slate-300">
        <span>🚴 骑行速度</span>
        <input
          id="speed-slider"
          type="range"
          min="0.3"
          max="2.6"
          step="0.1"
          value="1.2"
          class="w-24 sm:w-32 cursor-pointer"
        />
      </label>

      <!-- Wheelie Pitch Bias Control -->
      <label class="flex items-center gap-2.5 text-xs sm:text-sm font-medium text-slate-300">
        <span>📐 翘头高度</span>
        <input
          id="wheelie-slider"
          type="range"
          min="-14"
          max="14"
          step="1"
          value="2"
          class="w-24 sm:w-32 cursor-pointer"
        />
      </label>

      <!-- Rope Length / Plane Altitude Control -->
      <label class="flex items-center gap-2.5 text-xs sm:text-sm font-medium text-slate-300">
        <span>🪢 放飞高度</span>
        <input
          id="altitude-slider"
          type="range"
          min="95"
          max="310"
          step="5"
          value="175"
          class="w-24 sm:w-32 cursor-pointer"
        />
      </label>
    </div>

    <!-- Action Buttons & Theme Switcher -->
    <div class="flex items-center gap-2.5">
      <!-- Sky Theme Buttons -->
      <div class="flex bg-slate-950 p-1 rounded-xl border border-slate-800">
        <button
          data-theme="day"
          class="theme-btn px-2.5 py-1 rounded-lg text-xs font-bold bg-sky-500 text-slate-950 transition"
        >
          ☀️ 晴空
        </button>
        <button
          data-theme="sunset"
          class="theme-btn px-2.5 py-1 rounded-lg text-xs font-bold text-slate-400 hover:text-white transition"
        >
          🌇 晚霞
        </button>
        <button
          data-theme="night"
          class="theme-btn px-2.5 py-1 rounded-lg text-xs font-bold text-slate-400 hover:text-white transition"
        >
          🌙 星夜
        </button>
      </div>

      <!-- Boost Stunt Action Button -->
      <button
        id="boost-btn"
        class="px-4 py-2 rounded-xl font-black text-xs sm:text-sm bg-gradient-to-r from-amber-400 via-orange-500 to-red-500 text-slate-950 shadow-lg shadow-orange-500/25 hover:brightness-110 active:scale-95 transition flex items-center gap-1.5"
      >
        <span>⚡ 猛踩特技拉升</span>
      </button>
    </div>
  </footer>

  <script>
    window.onload = function () {
      const svgNS = 'http://www.w3.org/2000/svg';

      // DOM Element References
      const mainSvg = document.getElementById('main-svg');
      const wheelieAssembly = document.getElementById('wheelie-assembly');
      const rearWheelSpin = document.getElementById('rear-wheel-spin');
      const frontWheelSpin = document.getElementById('front-wheel-spin');
      const chainringSpin = document.getElementById('chainring-spin');
      const bikeChain = document.getElementById('bike-chain');

      // Pelican & IK Leg elements
      const pelicanHeadGroup = document.getElementById('pelican-head-group');
      const pelicanPouch = document.getElementById('pelican-pouch');
      const pouchFish = document.getElementById('pouch-fish');
      const scarfTail = document.getElementById('scarf-tail');
      const pelicanRightWing = document.getElementById('pelican-right-wing');

      const crankRArm = document.getElementById('crank-r-arm');
      const pedalRBody = document.getElementById('pedal-r-body');
      const crankLArm = document.getElementById('crank-l-arm');
      const pedalLBody = document.getElementById('pedal-l-body');

      const legRThigh = document.getElementById('leg-r-thigh');
      const legRThighInner = document.getElementById('leg-r-thigh-inner');
      const legRKnee = document.getElementById('leg-r-knee');
      const legRShin = document.getElementById('leg-r-shin');
      const legRFoot = document.getElementById('leg-r-foot');

      const legLThigh = document.getElementById('leg-l-thigh');
      const legLKnee = document.getElementById('leg-l-knee');
      const legLShin = document.getElementById('leg-l-shin');
      const legLFoot = document.getElementById('leg-l-foot');

      // Boeing 747 & Tow Rope elements
      const boeingGroup = document.getElementById('boeing-747-group');
      const callout747 = document.getElementById('callout-747');
      const towRopeOutline = document.getElementById('tow-rope-outline');
      const towRopeMain = document.getElementById('tow-rope-main');
      const towRopeTwist = document.getElementById('tow-rope-twist');
      const ropePennant = document.getElementById('rope-pennant');
      const pennantShape = document.getElementById('pennant-shape');

      // Environment & Shadows
      const roadDashesGroup = document.getElementById('road-dashes');
      const roadPropsGroup = document.getElementById('road-props');
      const windLinesLayer = document.getElementById('wind-lines-layer');
      const wheelDustLayer = document.getElementById('wheel-dust-layer');
      const mountainsFar = document.getElementById('mountains-far');
      const mountainsNear = document.getElementById('mountains-near');
      const bikeGroundShadow = document.getElementById('bike-ground-shadow');
      const planeGroundShadow = document.getElementById('plane-ground-shadow');

      // Telemetry & Controls
      const pitchReadout = document.getElementById('pitch-readout');
      const tensionReadout = document.getElementById('tension-readout');
      const speedReadout = document.getElementById('speed-readout');
      const speedSlider = document.getElementById('speed-slider');
      const wheelieSlider = document.getElementById('wheelie-slider');
      const altitudeSlider = document.getElementById('altitude-slider');
      const boostBtn = document.getElementById('boost-btn');
      const boostToast = document.getElementById('boost-toast');

      // ============================================================================
      // 1. PROCEDURAL SCENE GENERATION (Road Dashes, Pebbles/Bushes, Wind Streaks)
      // ============================================================================
      const roadDashes = [];
      for (let i = 0; i < 12; i++) {
        const rect = document.createElementNS(svgNS, 'rect');
        const x = i * 120;
        rect.setAttribute('x', x);
        rect.setAttribute('y', 698);
        rect.setAttribute('width', 64);
        rect.setAttribute('height', 8);
        rect.setAttribute('rx', 4);
        rect.setAttribute('fill', '#facc15');
        rect.setAttribute('opacity', '0.88');
        roadDashesGroup.appendChild(rect);
        roadDashes.push({ el: rect, x: x });
      }

      const roadProps = [];
      for (let i = 0; i < 10; i++) {
        const g = document.createElementNS(svgNS, 'g');
        const x = i * 145 + (i % 2) * 30;
        const isBush = i % 3 === 0;
        if (isBush) {
          const bush = document.createElementNS(svgNS, 'path');
          bush.setAttribute('d', 'M-18,0 Q-14,-16 0,-12 Q10,-22 22,-10 Q32,-12 30,0 Z');
          bush.setAttribute('fill', '#15803d');
          g.appendChild(bush);
        } else {
          const pebble = document.createElementNS(svgNS, 'ellipse');
          pebble.setAttribute('cx', 0);
          pebble.setAttribute('cy', 0);
          pebble.setAttribute('rx', 7 + (i % 4) * 2);
          pebble.setAttribute('ry', 2.5);
          pebble.setAttribute('fill', '#64748b');
          g.appendChild(pebble);
        }
        const y = isBush ? 626 : 665 + (i % 5) * 22;
        g.setAttribute('transform', `translate(${x}, ${y})`);
        roadPropsGroup.appendChild(g);
        roadProps.push({ el: g, x: x, y: y, speedMult: isBush ? 0.92 : 1.05 });
      }

      const windLines = [];
      for (let i = 0; i < 9; i++) {
        const line = document.createElementNS(svgNS, 'line');
        const x = Math.random() * 1280;
        const y = 90 + i * 62;
        const len = 55 + (i % 3) * 35;
        line.setAttribute('x1', x);
        line.setAttribute('y1', y);
        line.setAttribute('x2', x + len);
        line.setAttribute('y2', y);
        line.setAttribute('stroke', '#ffffff');
        line.setAttribute('stroke-width', i % 2 === 0 ? '2' : '1.2');
        line.setAttribute('stroke-linecap', 'round');
        line.setAttribute('stroke-opacity', '0.28');
        windLinesLayer.appendChild(line);
        windLines.push({ el: line, x: x, y: y, len: len, speed: 1.3 + (i % 4) * 0.25 });
      }

      // Dust particles at rear wheel contact point (350, 642)
      const dustParticles = [];
      for (let i = 0; i < 8; i++) {
        const c = document.createElementNS(svgNS, 'circle');
        c.setAttribute('r', 4 + (i % 3) * 2.5);
        c.setAttribute('fill', i % 2 === 0 ? '#fde68a' : '#cbd5e1');
        wheelDustLayer.appendChild(c);
        dustParticles.push({
          el: c,
          phase: i / 8
        });
      }

      // ============================================================================
      // 2. ANALYTICAL 2-BONE INVERSE KINEMATICS (Pelican Hip -> Knee -> Pedal)
      // ============================================================================
      function solveTwoBoneIK(hipX, hipY, footX, footY, L1, L2) {
        const dx = footX - hipX;
        const dy = footY - hipY;
        let dist = Math.hypot(dx, dy);

        // Clamp reach so legs never detach
        const maxReach = (L1 + L2) * 0.992;
        const minReach = Math.abs(L1 - L2) * 1.05;
        if (dist > maxReach) dist = maxReach;
        if (dist < minReach) dist = minReach;

        // Law of cosines for knee bend (bending forward-right like a bird/cyclist knee)
        const cosAngle = (L1 * L1 + dist * dist - L2 * L2) / (2 * L1 * dist);
        const clampedCos = Math.max(-1, Math.min(1, cosAngle));
        const baseAngle = Math.atan2(dy, dx);
        const bendAngle = Math.acos(clampedCos);

        // Knee bends upward/rightward (subtract bendAngle)
        const thighAngle = baseAngle - bendAngle;
        const kneeX = hipX + L1 * Math.cos(thighAngle);
        const kneeY = hipY + L1 * Math.sin(thighAngle);

        return { kneeX, kneeY };
      }

      // Helper to transform a point (x, y) rotated around pivot (px, py) by angleDeg
      function rotatePointAround(x, y, px, py, angleDeg) {
        const rad = (angleDeg * Math.PI) / 180;
        const cos = Math.cos(rad);
        const sin = Math.sin(rad);
        const dx = x - px;
        const dy = y - py;
        return {
          x: px + dx * cos - dy * sin,
          y: py + dx * sin + dy * cos
        };
      }

      // ============================================================================
      // 3. ANIMATION STATE & INTERACTIVE DRAGGING FOR BOEING 747
      // ============================================================================
      const state = {
        time: 0,
        wheelAngle: 0,
        crankAngle: 0,
        roadOffset: 0,
        mountainFarOffset: 0,
        mountainNearOffset: 0,
        speedMultiplier: 1.2,
        wheelieBias: 2,
        boostRemaining: 0,
        // Boeing 747 base position in SVG coordinates
        planeBaseX: 925,
        planeBaseY: 175,
        isDraggingPlane: false
      };

      // Convert client mouse/touch coordinates into SVG viewBox coordinates
      function getSvgPoint(clientX, clientY) {
        const pt = mainSvg.createSVGPoint();
        pt.x = clientX;
        pt.y = clientY;
        const ctm = mainSvg.getScreenCTM();
        if (!ctm) return { x: 925, y: 175 };
        return pt.matrixTransform(ctm.inverse());
      }

      boeingGroup.addEventListener('pointerdown', (e) => {
        state.isDraggingPlane = true;
        boeingGroup.setPointerCapture(e.pointerId);
      });

      window.addEventListener('pointermove', (e) => {
        if (!state.isDraggingPlane) return;
        const svgPt = getSvgPoint(e.clientX, e.clientY);
        state.planeBaseX = Math.max(580, Math.min(1150, svgPt.x));
        state.planeBaseY = Math.max(75, Math.min(390, svgPt.y));
        altitudeSlider.value = Math.round(state.planeBaseY);
      });

      window.addEventListener('pointerup', () => {
        state.isDraggingPlane = false;
      });

      // UI Controls Event Listeners
      speedSlider.addEventListener('input', (e) => {
        state.speedMultiplier = parseFloat(e.target.value);
      });

      wheelieSlider.addEventListener('input', (e) => {
        state.wheelieBias = parseFloat(e.target.value);
      });

      altitudeSlider.addEventListener('input', (e) => {
        state.planeBaseY = parseFloat(e.target.value);
      });

      boostBtn.addEventListener('click', () => {
        state.boostRemaining = 2.6; // 2.6 seconds of turbo boost
        boostToast.style.opacity = '1';
        setTimeout(() => {
          boostToast.style.opacity = '0';
        }, 2200);
      });

      // Theme Switcher
      const skyRect = document.getElementById('sky-rect');
      const starsLayer = document.getElementById('stars-layer');
      const themeBtns = document.querySelectorAll('.theme-btn');

      themeBtns.forEach((btn) => {
        btn.addEventListener('click', () => {
          const theme = btn.getAttribute('data-theme');
          themeBtns.forEach((b) => {
            b.className = 'theme-btn px-2.5 py-1 rounded-lg text-xs font-bold text-slate-400 hover:text-white transition';
          });
          btn.className = 'theme-btn px-2.5 py-1 rounded-lg text-xs font-bold bg-sky-500 text-slate-950 transition';

          if (theme === 'day') {
            skyRect.setAttribute('fill', 'url(#sky-grad-day)');
            starsLayer.setAttribute('opacity', '0');
          } else if (theme === 'sunset') {
            skyRect.setAttribute('fill', 'url(#sky-grad-sunset)');
            starsLayer.setAttribute('opacity', '0.45');
          } else if (theme === 'night') {
            skyRect.setAttribute('fill', 'url(#sky-grad-night)');
            starsLayer.setAttribute('opacity', '0.95');
          }
        });
      });

      // Clouds array initialization
      const cloudItems = Array.from(document.querySelectorAll('.cloud-item')).map((el) => ({
        el,
        speed: parseFloat(el.getAttribute('data-speed')),
        x: parseFloat(el.getAttribute('data-x')),
        y: parseFloat(el.getAttribute('data-y')),
        scale: parseFloat(el.getAttribute('data-scale'))
      }));

      // ============================================================================
      // 4. MAIN ANIMATION LOOP (60fps Physics & SVG Synchronization)
      // ============================================================================
      let lastTimestamp = performance.now();

      function animate(now) {
        const dt = Math.min(0.05, (now - lastTimestamp) / 1000);
        lastTimestamp = now;

        // Handle Turbo Boost decay
        if (state.boostRemaining > 0) {
          state.boostRemaining = Math.max(0, state.boostRemaining - dt);
        }
        const boostFactor = state.boostRemaining > 0 ? 1.85 : 1.0;
        const effectiveSpeed = state.speedMultiplier * boostFactor;

        state.time += dt * effectiveSpeed;
        const t = state.time;

        // ------------------------------------------------------------------------
        // A. WHEEL ROTATION & CRANK PEDALING (Moving Forward to the Right -> Clockwise)
        // ------------------------------------------------------------------------
        state.wheelAngle = (state.wheelAngle + dt * effectiveSpeed * 420) % 360;
        state.crankAngle = (state.crankAngle + dt * effectiveSpeed * 5.2) % (Math.PI * 2);

        rearWheelSpin.setAttribute('transform', `rotate(${state.wheelAngle})`);
        frontWheelSpin.setAttribute('transform', `rotate(${state.wheelAngle * 0.92})`);
        chainringSpin.setAttribute('transform', `rotate(${(state.crankAngle * 180) / Math.PI})`);
        bikeChain.setAttribute('stroke-dashoffset', -(t * 45) % 20);

        // ------------------------------------------------------------------------
        // B. WHEELIE BALANCING PITCH OSCILLATION (Pivoting at Rear Axle (350, 576))
        // ------------------------------------------------------------------------
        // Positive angle tilts front wheel down, negative angle lifts front wheel higher!
        const altitudePull = (175 - state.planeBaseY) * 0.035;
        const boostWheelieLift = state.boostRemaining > 0 ? -4.5 : 0;
        const wheelieRockingDeg =
          -state.wheelieBias -
          altitudePull +
          boostWheelieLift +
          Math.sin(t * 3.2) * 2.8 +
          Math.cos(t * 1.7) * 1.2;

        wheelieAssembly.setAttribute(
          'transform',
          `rotate(${wheelieRockingDeg.toFixed(2)}, 350, 576)`
        );

        // Update ground shadow width based on wheelie pitch
        bikeGroundShadow.setAttribute('rx', (86 + wheelieRockingDeg * 0.9).toFixed(1));

        // ------------------------------------------------------------------------
        // C. PELICAN PEDALING INVERSE KINEMATICS (2 Legs + Cranks + Webbed Feet)
        // ------------------------------------------------------------------------
        const crankCenterX = 452;
        const crankCenterY = 538;
        const crankRadius = 26;

        // Right Pedal (Near side)
        const rPedalX = crankCenterX + crankRadius * Math.cos(state.crankAngle);
        const rPedalY = crankCenterY + crankRadius * Math.sin(state.crankAngle);
        crankRArm.setAttribute('x2', rPedalX.toFixed(1));
        crankRArm.setAttribute('y2', rPedalY.toFixed(1));
        pedalRBody.setAttribute('x', (rPedalX - 14).toFixed(1));
        pedalRBody.setAttribute('y', (rPedalY - 4).toFixed(1));

        // Left Pedal (Far side, 180 degrees opposite)
        const lPedalX = crankCenterX + crankRadius * Math.cos(state.crankAngle + Math.PI);
        const lPedalY = crankCenterY + crankRadius * Math.sin(state.crankAngle + Math.PI);
        crankLArm.setAttribute('x2', lPedalX.toFixed(1));
        crankLArm.setAttribute('y2', lPedalY.toFixed(1));
        pedalLBody.setAttribute('x', (lPedalX - 14).toFixed(1));
        pedalLBody.setAttribute('y', (lPedalY - 4).toFixed(1));

        // Solve IK for Right Leg (Hip at (382, 422))
        const rHipX = 382, rHipY = 422;
        const rIK = solveTwoBoneIK(rHipX, rHipY, rPedalX, rPedalY, 68, 66);
        legRThigh.setAttribute('x2', rIK.kneeX.toFixed(1));
        legRThigh.setAttribute('y2', rIK.kneeY.toFixed(1));
        legRThighInner.setAttribute('x2', rIK.kneeX.toFixed(1));
        legRThighInner.setAttribute('y2', rIK.kneeY.toFixed(1));
        legRKnee.setAttribute('cx', rIK.kneeX.toFixed(1));
        legRKnee.setAttribute('cy', rIK.kneeY.toFixed(1));
        legRShin.setAttribute('x1', rIK.kneeX.toFixed(1));
        legRShin.setAttribute('y1', rIK.kneeY.toFixed(1));
        legRShin.setAttribute('x2', rPedalX.toFixed(1));
        legRShin.setAttribute('y2', rPedalY.toFixed(1));
        legRFoot.setAttribute(
          'd',
          `M ${(rPedalX - 10).toFixed(1)},${rPedalY.toFixed(1)} L ${(rPedalX + 22).toFixed(1)},${(rPedalY - 5).toFixed(1)} L ${(rPedalX + 16).toFixed(1)},${(rPedalY + 5).toFixed(1)} L ${(rPedalX - 10).toFixed(1)},${(rPedalY + 4).toFixed(1)} Z`
        );

        // Solve IK for Left Leg (Hip at (374, 426))
        const lHipX = 374, lHipY = 426;
        const lIK = solveTwoBoneIK(lHipX, lHipY, lPedalX, lPedalY, 68, 66);
        legLThigh.setAttribute('x2', lIK.kneeX.toFixed(1));
        legLThigh.setAttribute('y2', lIK.kneeY.toFixed(1));
        legLKnee.setAttribute('cx', lIK.kneeX.toFixed(1));
        legLKnee.setAttribute('cy', lIK.kneeY.toFixed(1));
        legLShin.setAttribute('x1', lIK.kneeX.toFixed(1));
        legLShin.setAttribute('y1', lIK.kneeY.toFixed(1));
        legLShin.setAttribute('x2', lPedalX.toFixed(1));
        legLShin.setAttribute('y2', lPedalY.toFixed(1));
        legLFoot.setAttribute(
          'd',
          `M ${(lPedalX - 10).toFixed(1)},${lPedalY.toFixed(1)} L ${(lPedalX + 20).toFixed(1)},${(lPedalY - 5).toFixed(1)} L ${(lPedalX + 15).toFixed(1)},${(lPedalY + 5).toFixed(1)} L ${(lPedalX - 10).toFixed(1)},${(lPedalY + 4).toFixed(1)} Z`
        );

        // ------------------------------------------------------------------------
        // D. PELICAN SECONDARY ANIMATIONS (Head Bob, Throat Pouch Jiggle, Scarf)
        // ------------------------------------------------------------------------
        const headBobY = Math.sin(state.crankAngle * 2) * 3.2;
        const headTilt = Math.cos(state.crankAngle) * 2.2;
        pelicanHeadGroup.setAttribute(
          'transform',
          `translate(0, ${headBobY.toFixed(2)}) rotate(${headTilt.toFixed(2)}, 445, 310)`
        );

        // Throat pouch elastic jiggle
        const pouchSag = 342 + Math.sin(t * 7.5) * 6.5;
        pelicanPouch.setAttribute(
          'd',
          `M 472,278 L 598,282 C 592,${(pouchSag - 16).toFixed(1)}, 548,${pouchSag.toFixed(1)}, 504,${(pouchSag - 8).toFixed(1)} C 476,328, 464,304, 472,278 Z`
        );
        // Little fish tail wiggling in the pouch
        pouchFish.setAttribute(
          'transform',
          `translate(556, 280) rotate(${(Math.sin(t * 11) * 12).toFixed(1)})`
        );

        // Fluttering aviator scarf wave
        const scarfWave1 = -12 + Math.sin(t * 12) * 9;
        const scarfWave2 = 2 + Math.cos(t * 10) * 12;
        scarfTail.setAttribute(
          'd',
          `M 0,0 Q -38,${scarfWave1.toFixed(1)} -72,4 Q -98,16 -122,${scarfWave2.toFixed(1)} Q -90,26 -56,16 Q -25,8 4,12 Z`
        );

        // ------------------------------------------------------------------------
        // E. BOEING 747 SKY FLOATING MOTION & EXACT TOW ROPE PHYSICS
        // ------------------------------------------------------------------------
        const planeFloatX = state.planeBaseX + Math.sin(t * 1.4) * 16;
        const planeFloatY =
          state.planeBaseY +
          Math.sin(t * 2.3) * 14 -
          (state.boostRemaining > 0 ? 18 : 0);
        const planePitchDeg = -8.5 + Math.cos(t * 2.3) * 3.2 - (state.boostRemaining > 0 ? 4 : 0);

        boeingGroup.setAttribute(
          'transform',
          `translate(${planeFloatX.toFixed(2)}, ${planeFloatY.toFixed(2)}) rotate(${planePitchDeg.toFixed(2)})`
        );

        // Update callout badge above 747
        callout747.setAttribute(
          'transform',
          `translate(${(planeFloatX - 25).toFixed(1)}, ${(planeFloatY - 108).toFixed(1)})`
        );
        planeGroundShadow.setAttribute('cx', planeFloatX.toFixed(1));
        planeGroundShadow.setAttribute('rx', (155 - planeFloatY * 0.15).toFixed(1));

        // Compute Exact World Position of Bike Handlebar Knot (local (562, 342) rotated around (350, 576))
        const handlebarWorld = rotatePointAround(562, 342, 350, 576, wheelieRockingDeg);

        // Compute Exact World Position of Boeing 747 Tow Ring (local (125, 45) inside boeingGroup)
        const planeTowLocalRotated = rotatePointAround(125, 45, 0, 0, planePitchDeg);
        const planeTowWorld = {
          x: planeFloatX + planeTowLocalRotated.x,
          y: planeFloatY + planeTowLocalRotated.y
        };

        // Construct Quadratic/Cubic Bezier Rope Curve with realistic aerodynamic sag & vibration
        const midX = (handlebarWorld.x + planeTowWorld.x) * 0.5;
        const midY = (handlebarWorld.y + planeTowWorld.y) * 0.5;
        const ropeVibration = Math.sin(t * 14) * 4.5;
        const ropeSag = 26 - effectiveSpeed * 6 + ropeVibration;

        const ctrlX = midX + 18;
        const ctrlY = midY + ropeSag;

        const ropePathData = `M ${handlebarWorld.x.toFixed(1)},${handlebarWorld.y.toFixed(1)} Q ${ctrlX.toFixed(1)},${ctrlY.toFixed(1)} ${planeTowWorld.x.toFixed(1)},${planeTowWorld.y.toFixed(1)}`;
        towRopeOutline.setAttribute('d', ropePathData);
        towRopeMain.setAttribute('d', ropePathData);
        towRopeTwist.setAttribute('d', ropePathData);

        // Position the Red Warning Pennant at t = 0.5 on the quadratic Bezier curve
        const flagX = 0.25 * handlebarWorld.x + 0.5 * ctrlX + 0.25 * planeTowWorld.x;
        const flagY = 0.25 * handlebarWorld.y + 0.5 * ctrlY + 0.25 * planeTowWorld.y;
        const flagFlutter = Math.sin(t * 16) * 8;
        ropePennant.setAttribute(
          'transform',
          `translate(${flagX.toFixed(1)}, ${flagY.toFixed(1)}) rotate(${flagFlutter.toFixed(1)})`
        );

        // ------------------------------------------------------------------------
        // F. SCROLLING ROAD, PARALLAX MOUNTAINS, CLOUDS & DUST PARTICLES
        // ------------------------------------------------------------------------
        const scrollPixels = dt * effectiveSpeed * 340;

        // Road center dashes
        roadDashes.forEach((d) => {
          d.x -= scrollPixels;
          if (d.x < -80) d.x += 12 * 120;
          d.el.setAttribute('x', d.x.toFixed(1));
        });

        // Roadside bushes & pebbles
        roadProps.forEach((p) => {
          p.x -= scrollPixels * p.speedMult;
          if (p.x < -60) p.x += 10 * 145;
          p.el.setAttribute('transform', `translate(${p.x.toFixed(1)}, ${p.y})`);
        });

        // Foreground wind speed lines
        windLines.forEach((w) => {
          w.x -= scrollPixels * w.speed * 1.35;
          if (w.x < -150) w.x = 1320 + Math.random() * 120;
          w.el.setAttribute('x1', w.x.toFixed(1));
          w.el.setAttribute('x2', (w.x + w.len).toFixed(1));
        });

        // Parallax clouds
        cloudItems.forEach((c) => {
          c.x -= scrollPixels * c.speed * 0.22;
          if (c.x < -240) c.x = 1360;
          c.el.setAttribute(
            'transform',
            `translate(${c.x.toFixed(1)}, ${c.y}) scale(${c.scale})`
          );
        });

        // Parallax mountains
        state.mountainFarOffset = (state.mountainFarOffset - scrollPixels * 0.08) % 600;
        state.mountainNearOffset = (state.mountainNearOffset - scrollPixels * 0.18) % 600;
        mountainsFar.setAttribute('transform', `translate(${state.mountainFarOffset.toFixed(1)}, 0)`);
        mountainsNear.setAttribute('transform', `translate(${state.mountainNearOffset.toFixed(1)}, 0)`);

        // Rear tire dust puffs (kicked backward to the left from (336, 638))
        dustParticles.forEach((p) => {
          const progress = (t * 1.9 + p.phase) % 1;
          const px = 340 - progress * 115;
          const py = 638 - Math.sin(progress * Math.PI) * 24 - progress * 12;
          const scale = (1 - progress) * 1.3;
          p.el.setAttribute('cx', px.toFixed(1));
          p.el.setAttribute('cy', py.toFixed(1));
          p.el.setAttribute('opacity', ((1 - progress) * 0.65).toFixed(2));
          p.el.setAttribute('r', (3 + scale * 5).toFixed(1));
        });

        // ------------------------------------------------------------------------
        // G. UPDATE LIVE TELEMETRY BADGES
        // ------------------------------------------------------------------------
        const displayPitch = Math.abs(26 - wheelieRockingDeg);
        const ropeDist = Math.hypot(
          planeTowWorld.x - handlebarWorld.x,
          planeTowWorld.y - handlebarWorld.y
        );
        const displayTension = 35 + ropeDist * 0.045 + effectiveSpeed * 4.2;
        const displaySpeed = Math.round(effectiveSpeed * 32);

        pitchReadout.textContent = `${displayPitch.toFixed(1)}°`;
        tensionReadout.textContent = `${displayTension.toFixed(1)} kN`;
        speedReadout.textContent = `${displaySpeed} km/h`;

        requestAnimationFrame(animate);
      }

      requestAnimationFrame(animate);
    };
  </script>
</body>
</html>

你好啊,陌生人!

我的朋友,看起来你是新来的,如果想参与到讨论中,点击下面的按钮!

📈用户数目📈

目前论坛共有73059位seeker

🎉欢迎新用户🎉