Nimbus AI
aadmin2026-10-26 发布未分类4 阅读

Nimbus AI

类型: · 收录:2026-10-26 23:39:21 · 源码:会员可见

[hidecontent type="vip1"]
Build a single standalone index.html file (inline <style> and <script>, no build tools, no frameworks, no local assets) for a dark-mode, full-screen (100vh) hero section of an AI chat-assistant product called "Nimbus". The background is a video of a cute 3D cloud-shaped robot. The robot's head, visor and glowing eye rings never move; only its pupils move, and they point toward the mouse cursor in any direction. The video is scrubbed by the cursor, never played normally on desktop. Recreate it exactly as specified below. Do not redesign, simplify, or add content.

=====================================================================
1. ASSETS (use these exact CloudFront URLs, nothing local)
=====================================================================
- Poster image (first frame of the loop):
  https://d2ol7oe51mr4n9.cloudfront.net/user_38xzZboKViGWJOttwIXH07lWA1P/3fa3bdf2-233d-40fe-b028-dd6cd654f909.jpg
- Video 1080p (desktop / large screens), 1920x1080, 3.6 MB:
  https://d2ol7oe51mr4n9.cloudfront.net/user_38xzZboKViGWJOttwIXH07lWA1P/a6754e43-b755-4858-93ab-bf470232464f.mp4
- Video 720p (phones / small screens), 1280x720, 1.8 MB:
  https://d2ol7oe51mr4n9.cloudfront.net/user_38xzZboKViGWJOttwIXH07lWA1P/ca3d57b6-69b3-44ae-baf5-ab0dc31c451b.mp4

About the video: it is a 4.0-second seamless loop, exactly 96 frames at 24 fps, H.264, no audio, and EVERY frame is a keyframe (so seeking to any frame is instant). Content: deep navy-black starry sky; a glossy white cloud-shaped robot head with a black visor, two glowing blue eye rings and pink blush cheeks; a glowing blue neck ring; a white body with a glowing blue lightning bolt; a glowing blue-to-violet rounded bar across the bottom edge. Everything is frozen except the two dark pupils (each with one white highlight dot), which roll together through one full clockwise circle inside their fixed rings: up → right → down → left → back to up. The video contains NO text; all text is HTML. The CloudFront URLs allow cross-origin fetch.

=====================================================================
2. HEAD
=====================================================================
- <!doctype html>, <html lang="en">, meta charset utf-8
- meta viewport: "width=device-width, initial-scale=1, viewport-fit=cover"
- meta theme-color: #020811
- title: "Nimbus — your AI teammate"
- Google Fonts with preconnect to fonts.googleapis.com and fonts.gstatic.com (crossorigin):
  https://fonts.googleapis.com/css2?family=Inter+Tight:wght@500;600;700;800&family=Inter:wght@400;500;600&display=swap

=====================================================================
3. CSS (exact values)
=====================================================================
:root variables:
  --bg: #020811; --text: #f4f7ff; --muted: #a9b4cc; --accent: #4aa8ff; --gutter: clamp(16px, 4vw, 56px);

Reset: * { box-sizing: border-box; margin: 0; padding: 0; }
html, body: height 100%; background var(--bg); color var(--text).
body: font-family "Inter", system-ui, -apple-system, Segoe UI, Roboto, sans-serif; -webkit-font-smoothing: antialiased; overflow-x: hidden.

.hero (section#hero):
  position relative; height 100vh, then height 100svh; min-height 560px; overflow hidden; isolation isolate; background var(--bg); touch-action pan-y.

.stage (div, aria-hidden="true"): position absolute; inset 0; z-index -1; pointer-events none.
.stage video:
  position absolute; left 50%; bottom 0; transform translateX(-50%);
  width: max(100vw, calc(max(100svh, 560px) * 16 / 9));   /* acts like cover, anchored to the bottom so the robot is never cropped */
  height auto; aspect-ratio 16 / 9; object-fit cover;
  opacity 0; transition opacity .8s ease.
.stage video.ready { opacity: 1; }
.stage::after: content ""; position absolute; inset 0;
  background: radial-gradient(120% 70% at 50% 0%, rgba(2,8,17,.55) 0%, rgba(2,8,17,0) 60%);

.nav: position absolute; top 0; left 0; right 0; display flex; align-items center; justify-content space-between; padding clamp(16px, 3vw, 28px) var(--gutter); z-index 2.
.brand (a): inline-flex; align-items center; gap 10px; color var(--text); no underline; font-family "Inter Tight", sans-serif; font-weight 700; font-size clamp(18px, 2vw, 24px); letter-spacing -.01em.
.brand svg: width clamp(30px, 3.2vw, 42px); height auto.
.btn (a): inline-flex; align-items center; gap 8px; background #fff; color #050b16; no underline; font-weight 600; font-size clamp(13px, 1.1vw, 15px); padding 12px 22px; border-radius 999px;
  box-shadow: 0 0 0 1px rgba(255,255,255,.2), 0 8px 30px rgba(74,168,255,.18);
  transition transform .2s ease, box-shadow .2s ease; white-space nowrap.
.btn:hover: transform translateY(-1px); box-shadow: 0 0 0 1px rgba(255,255,255,.3), 0 10px 40px rgba(74,168,255,.35).

.copy: position relative; z-index 1; text-align center; padding clamp(96px, 14vh, 130px) var(--gutter) 0; max-width 1100px; margin 0 auto.
h1: font-family "Inter Tight", sans-serif; font-weight 800; font-size clamp(34px, 6.2vw, 86px); line-height .98; letter-spacing -.035em; text-wrap balance; text-shadow 0 2px 40px rgba(2,8,17,.6).
h1 span: display block (each line on its own row).
.sub (p): margin clamp(14px, 2vh, 24px) auto 0; max-width 34em; color var(--muted); font-size clamp(15px, 1.45vw, 19px); line-height 1.55; text-wrap balance.

Entrance animation:
  .fade { opacity 0; transform translateY(14px); animation: in .9s cubic-bezier(.2,.7,.2,1) forwards; }
  .d1 { animation-delay .05s } .d2 { animation-delay .18s } .d3 { animation-delay .3s }
  @keyframes in { to { opacity 1; transform none; } }

Responsive:
  @media (max-width: 640px): .btn padding 10px 16px; .btn .long display none (button reads "Add to workspace"); .copy padding-top 110px.
  @media (max-aspect-ratio: 4/5) (portrait phones): .stage video width: max(230vw, calc(62svh * 16 / 9));  this shows the robot larger, still bottom-anchored and centered, below the text.
  @media (prefers-reduced-motion: reduce): .fade animation none; opacity 1; transform none.
  No horizontal scroll at any width (verify at 375px).

=====================================================================
4. HTML STRUCTURE
=====================================================================
<section class="hero" id="hero">
  <div class="stage" aria-hidden="true">
    <video id="robot" poster="[POSTER URL above]" muted playsinline preload="auto" disablepictureinpicture></video>   (no src attribute; JS sets it)
  </div>
  <nav class="nav">
    <a class="brand" href="#" aria-label="Nimbus home">
      inline SVG cloud outline icon: viewBox="0 0 44 30" fill="none" aria-hidden="true", one path:
      d="M12 27h21a8 8 0 0 0 1.2-15.9A11 11 0 0 0 13.4 9.3 9 9 0 0 0 12 27Z" stroke="currentColor" stroke-width="3" stroke-linejoin="round"
      followed by the text "Nimbus"
    </a>
    <a class="btn" href="#">Add to <span class="long">your </span>workspace</a>
  </nav>
  <div class="copy">
    <h1 class="fade d1"><span>Meet Nimbus,</span><span>your AI teammate.</span></h1>
    <p class="sub fade d2">Nimbus floats through your team chat, answering questions, summarizing threads, and handling the busywork.</p>
  </div>
</section>

=====================================================================
5. JAVASCRIPT (inline, wrapped in an IIFE): cursor-to-pupil tracking
=====================================================================
a) Setup
   video = #robot
   reduceMq = matchMedia('(prefers-reduced-motion: reduce)')
   mobileMq = matchMedia('(max-width: 700px), (hover: none)');  isMobile = () => mobileMq.matches
   small = Math.max(screen.width, screen.height) * (devicePixelRatio || 1) < 1600 || innerWidth < 768
   SRC = small ? 720p URL : 1080p URL
   Constants: FPS = 24, FRAMES = 96, VIDEO_W = 1920, EYE_X = 958, EYE_Y = 702 (centre point between the two eyes, in source-video pixels), TAU = 2π.

b) Calibration table. These are [frame, gaze angle in degrees] anchors measured from the clip. Angles use screen coordinates (0° = right, 90° = down, 180° = left, 270° = up) and are unwrapped so they only increase. Use this exact array:
   ANCHORS = [[0,288],[4,292],[8,331.9],[12,350.1],[16,378.9],[20,384.5],[24,401.4],[28,409.2],[32,428.9],[36,435.3],
     [40,446.6],[44,450.2],[48,467.5],[52,473.4],[56,486.4],[60,491.5],[64,509.1],[68,513.5],[72,540],[76,550.8],
     [80,592.4],[84,605.1],[88,623.9],[92,633.2],[96,648]]
   Build SAMPLES for every frame f from 0 to 95 by linear interpolation between the two surrounding anchors:
     deg = d0 + (d1 - d0) * (f - f0) / (f1 - f0);  SAMPLES.push([ (deg % 360) * π / 180, f ])

c) Frames to skip. Nine interpolated frames in the clip are smeared and must never be shown while scrubbing. Build CLEAN as an identity array of length 96, then override:
   5→4, 6→8, 7→8, 77→76, 78→80, 79→80, 93→92, 94→0, 95→0

d) State: pointer = null, targetFrame = 0, pos = 0 (smoothed playhead in frames), lastSet = -1, ready = false.

e) retarget(): return if there is no pointer or isMobile().
   rect = video.getBoundingClientRect(); scale = rect.width / VIDEO_W
   eyeX = rect.left + EYE_X * scale;  eyeY = rect.top + EYE_Y * scale
   dx = pointer.x - eyeX; dy = pointer.y - eyeY; if hypot(dx, dy) < 8, return (ignore the dead centre).
   angle = atan2(dy, dx), normalised into 0..2π.
   Find the SAMPLES entry with the smallest circular angular distance (if dist > π, use 2π - dist) and set targetFrame to its frame.

f) tick(), run every requestAnimationFrame. Only when ready and not mobile:
   delta = targetFrame - pos; if delta > 48, subtract 96; if delta < -48, add 96 (take the shorter way round the loop, wrapping end to start).
   pos += delta * (reduceMq.matches ? 1 : 0.12);  pos = ((pos % 96) + 96) % 96
   maxT = (video.duration || 4) - 1/24
   t = min( CLEAN[ round(pos) % 96 ] / 24 + 1/240, maxT )
   If !video.seeking and |t - lastSet| > 1/48: video.currentTime = t; lastSet = t.
   Never call play() on desktop.

g) applyMode(): return if not ready.
   Mobile / touch: video.loop = true; if reduced motion, pause; otherwise play() and ignore promise rejection. No cursor scrubbing.
   Desktop: video.loop = false; pause(); pos = (video.currentTime * 24) % 96; lastSet = -1; retarget().

h) Events:
   window pointermove (passive): store pointer {x: clientX, y: clientY}, then retarget().
   window resize: if isMobile() changed since last time, applyMode(); then retarget().
   window scroll (passive): retarget().   window pageshow: applyMode().
   mobileMq 'change' and reduceMq 'change': applyMode().
   video 'loadeddata' (once): ready = true; add class "ready" (fades the video in); applyMode().

i) Loading: fetch(SRC) → if !r.ok throw → r.blob() → video.src = URL.createObjectURL(blob). On any error fall back to video.src = SRC. This holds the whole clip in memory so every seek is instant.

j) Start the loop with requestAnimationFrame(tick).

=====================================================================
6. RESULT
=====================================================================
A pitch-black/navy starry hero. Top left: a white cloud-outline logo with "Nimbus". Top right: a white pill button "Add to your workspace". A centered bold two-line headline "Meet Nimbus, / your AI teammate." with a muted blue-grey subline under it; both fade up on load. Below sits the glowing cloud robot on a blue-violet light bar. Its head and eye rings stay perfectly still while its pupils glide smoothly to point at the cursor wherever it moves. On phones and touch screens the pupils simply loop around on their own. Fully responsive from 320px phones to wide desktops, with no horizontal scrolling.
[/hidecontent]
← 返回首页