motionsites中文站 / Frame Futures
Frame Futures
aadmin2026-10-17 发布Site模板0 阅读

Frame Futures

类型:Site模板 · 收录:2026-10-17 12:02:25 · 源码:会员可见

[hidecontent type="vip1"]
Build one standalone HTML document (index.html) for a single full-viewport hero. No frameworks, no build step, no extra sections. One semantic tree that restyles at breakpoints. Black page, white type, a looping background video, glass controls, six client marks, and one work-story link. Match every measurement, string, color, and behavior below. Do not invent copy, logos, or a different video.

DOCUMENT
- lang="en". charset utf-8. viewport: width=device-width, initial-scale=1, viewport-fit=cover. theme-color #000000.
- title: framefutures — Digital progress made simple
- All CSS in one <style> in the head. Two scripts at the end of the body, plus a tiny head script that only adds an intro class.
- Reset: border-box on everything. html,body margin 0, background #000, color #fff. body uses the text font, antialiased, optimizeLegibility. Links inherit color, no underline. ul has no list style, margin, or padding. h1 and p have margin 0 and inherit weight. img, svg, and video are display:block.
- :focus-visible outline 2px solid #ff6a45, offset 3px, radius 4px.

FONTS
- Display family "Urbanist", then ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif. CSS variable --display.
- Text family "Inter", then ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif. CSS variable --text.
- Embed both as variable faces, weight 100–900, font-display:block:
  @font-face Urbanist src assets/font-01-7981ef90c2.woff2
  @font-face Inter src assets/font-02-3100e775e8.woff2
- If those files are missing, load the same two families from Google Fonts at the full variable range, still font-display:block, and keep the same family names and stacks.

COLOR TOKENS
- --ink #ffffff (headline and brand)
- --ink-nav #fafafa (nav and button labels)
- --ink-lede #c3cbd9 (body)
- --ink-mark #cfd6e2 (client names)
- --ink-icon #caced9 (client icons)
- --ink-kicker #abb5c3 (story kicker)
- --ink-title #f6f5f5 (story title)
- --ember #c8260f (button stroke)
- --ember-arrow #dc6c52 (button arrow)
- --glass rgba(255,255,255,.10)
- --glass-line rgba(255,255,255,.28)

SCALE
Reference canvas is 1280×800.
- --vh is 100vh, and 100dvh where supported.
- --u = min(100vw/1280, var(--vh)/800). One reference pixel that always FITS the viewport.
- --c = max(100vw/1280, var(--vh)/800). One reference pixel that always COVERS the viewport.
- --ut = max(var(--u), .8px). Small UI text never drops below 80% of its reference size.
- .hero min-height is 100vh, 100svh, and 100dvh where supported.

BACKGROUND VIDEO
Do not use a local image or a downloaded file. The artwork is a <video class="art"> inside <div class="stage" aria-hidden="true">.
Exact src:
https://d8j0ntlcm91z4.cloudfront.net/user_38xzZboKViGWJOttwIXH07lWA1P/hf_20261005_174131_d7226c31-6939-41bb-a3a1-f1c68410bf74.mp4
Attributes: autoplay muted loop playsinline. No controls, no poster, no audio.
The picture is a pure-black field with a brushed-steel ribbon and an orange inner glow, occupying the right and bottom. Intrinsic frame is 1236×744 (ratio 0.6011, the original 972/1617 artwork). object-fit:fill.

Stage sits absolute, inset 0, z-index -1, pointer-events none, overflow hidden.
--ih = var(--artw) * 0.6011.
Mobile mask feathers the top so the ribbon never hard-cuts:
linear-gradient(to top, #000 0, #000 calc(var(--ih)*0.6), rgba(0,0,0,.35) calc(var(--ih)*0.82), transparent var(--ih))
Set both mask-image and -webkit-mask-image.

Video, mobile: position absolute, right 0, bottom 0, width var(--artw), height calc(var(--artw)*0.6011).

A legibility veil, .hero::after, absolute inset 0, z-index -1, pointer-events none:
linear-gradient(to bottom, rgba(0,0,0,.82) 0, rgba(0,0,0,.62) 38%, transparent 62%),
linear-gradient(to top, rgba(0,0,0,.66) 0, rgba(0,0,0,.4) 20%, transparent 40%).

MARKUP, IN THIS ORDER, INSIDE <main class="hero">
1. stage + video
2. header.topbar
3. section.copy
4. div.spacer aria-hidden
5. section.clients-wrap aria-label="Clients"
6. a.story

TOP BAR
- a.brand href="#" aria-label="framefutures home". Text: framefutures. Urbanist 400, 31.5px, letter-spacing -0.03em, line-height 1, color --ink.
- button.toggle, type button, aria-expanded false, aria-controls site-nav, aria-label "Open menu". 44×44 circle, 1.5px solid --ember, background --glass, color --ink-nav, backdrop-filter blur(14px) saturate(140%). Hover (only if hover:hover): background rgba(255,255,255,.16) and box-shadow 0 0 0 4px rgba(200,38,15,.18). Transition background-color and box-shadow 0.25s.
- Burger: span.burger 16×10 containing two <i>. Each bar is absolute, full width, 1.5px tall, radius 1px, currentColor. First top 1px, second top 7.5px. When .topbar.is-open, both move to top 4.25px; first rotates 45deg, second rotates -45deg. Transition transform and top 0.3s cubic-bezier(.2,.7,.2,1).
- nav#site-nav.nav aria-label="Primary". On small screens it is an absolute panel under the bar (top calc(100% + 12px), left 0, right 0, z-index 6), column, padding 8px, radius 20px, border 1px solid rgba(255,255,255,.12), background rgba(18,18,18,.72), blur 22px saturate 150%, shadow 0 24px 60px rgba(0,0,0,.55). Closed: opacity 0, visibility hidden, translateY(-6px), with visibility delayed 0.3s. Open: opacity 1, visible, no transform. Transition opacity 0.25s and transform 0.3s with the same curve.
- ul.menu links, exact text and hrefs: Practice #practice, Expertise #expertise, Made #made, Our team #team, Thinking #thinking. Mobile link: block, padding 14px, radius 12px, Inter 400 17px, line-height 1.2, letter-spacing -0.01em, color --ink-nav, nowrap. Hover color #fff.
- a.cta href="#work". Label "See us build" then an inline SVG, viewBox 0 0 14 11, aria-hidden. Path: M.5 5.5h12.6M8 .6l5 4.9-5 4.9, fill none, stroke var(--ember-arrow), stroke-width 1.3, round caps and joins. Pill: 147×41, padding-left 17px, gap 10px, radius 999px, border 1.5px solid --ember, background --glass, same blur as the toggle, Inter 400 15.5px/1, letter-spacing -0.01em, color --ink-nav. SVG 14×11. Inside the closed panel, margin 4px 6px 8px. Same hover as the toggle.

COPY
Headline is an h1.headline of three spans.ln, with the trailing spaces exactly as written:
"Digital progress made "
"simple, refined by people "
"for good."
Urbanist 400, color --ink, letter-spacing -0.045em.
Mobile: size clamp(38px, 6vw + 19px, 48px), line-height 1.05, max-width 7.6em, and the line spans stay inline so the phrase wraps as four lines: Digital progress / made simple, / refined by people / for good.

Lede is a p.lede of three spans.ln:
"Since 2019, crafting Web and Mobile innovations with "
"industry experts and next-gen innovators. We link human "
"expression with AI to test boundaries."
Mobile: spans inline, margin-top clamp(16px, 2.6svh, 24px), max-width 34em, color --ink-lede, 16px, line-height 1.5, letter-spacing -0.015em, text-wrap pretty.
Copy block margin-top clamp(24px, 6svh, 64px).

CLIENTS
Grid, at most three per row: repeat(auto-fit, minmax(max(100px, (100% - 20px) / 3), 1fr)), gap 18px 10px.
Each item is icon + name, flex, align center, gap calc(var(--k) * 12px), color --ink-mark. Names are nowrap, Inter, size calc(var(--k) * var(--fs) * 1px), weight var(--fw), tracking var(--ls).
Icons: width/height calc(var(--k) * var(--iw|ih) * 1px), color --ink-icon, and a horizontal margin of calc(var(--k) * (34 - var(--iw)) * 0.5px) so the icon column aligns.
Mobile --k is 0.72. Per brand, in order:
1 novafone — fs 19.5, fw 500, ls -0.01em, icon 31×30. viewBox 0 0 31 30. Open arc stroke currentColor width 5.6 round cap: M19.2 4.3A11.9 11.9 0 1 1 9.6 4.9. Leaf fill currentColor: M14.6 3.1c3.7-1.5 7.8-.9 10.3 1.2-2.6.1-4.9 1.2-6 3.3-.6-2.3-2.2-3.9-4.3-4.5z.
2 vertex — fs 20, fw 500, ls 0.01em, icon 25×27. viewBox 0 0 25 27. A mask id mvx: hexagon M12.5 .6 23.6 7v13L12.5 26.4 1.4 20V7z filled and stroked #fff width 1.2; inner hex M12.5 9.2 16.2 11.35v4.3L12.5 17.8 8.8 15.65v-4.3z fill #000; spokes from inner vertices to outer vertices stroked #000 width 1.3. Then a full rect 25×27 fill currentColor using that mask.
3 ClearWave — fs 18.75, fw 400, ls -0.02em, icon 31×22. viewBox 0 0 31 22. Two sine strokes, currentColor, width 3.9, round caps: M2.4 8.6C5.6 2.6 9.6 2.4 13.4 6.6s7.8 4.6 15.2-3.3 and M2.4 18.6c3.2-6 7.2-6.2 11-2s7.8 4.6 15.2-3.3.
4 forma — fs 22.5, fw 600, ls -0.01em, icon 26×27. viewBox 0 0 26 27. Four rounded rects, currentColor, rx 4.6, 11.8×12.2, at (.5,.5), (13.7,.5), (.5,14.3), (13.7,14.3).
5 orbitcloud — fs 18.75, fw 400, ls 0.01em, icon 28×28. viewBox 0 0 28 28. Two circles centered 14,14: r 12.3 stroke 3.1, r 6.9 stroke 2.7, no fill, currentColor.
6 nexora — fs 21.5, fw 600, ls 0, icon 33×23. viewBox 0 0 33 23. Stroke currentColor, round caps and joins: M4.4 19.2 10.6 4.2 and M10.6 4.2l9.4 14.6 width 6.4; M21.6 19 28.6 3.9 width 6.

WORK STORY
a.story href="#kite". Mobile grid: thumbnail beside two text rows, column-gap 14px, row-gap 7px, margin-top clamp(18px, 3svh, 26px), max-width 520px, justify-self start.
Image: src assets/image-04-766bc27fd0.jpg, alt "Team workshop around a table at the Delhi Tech Lab", width 103, height 68, object-fit cover, radius 8px, 1px solid --glass-line, background #111. It spans both rows.
Kicker "Our work story": Inter 500 13px/1, letter-spacing 0.026em, uppercase, color --ink-kicker, align-self end.
Title "Transforming KITE’s digital future through a Tech Lab in Delhi.": Inter 400 16px/1.35, letter-spacing -0.02em, color --ink-title, text-wrap balance. Hover underlines the title 1px, offset 3px.

MOBILE LAYOUT (base, under 480px)
Hero is a one-column grid: areas "top" "copy" "space" "clients" "story". Rows auto auto 1fr auto auto.
--pad = max(20px, safe-area left, safe-area right). --k 0.72. --artw 230vw.
Padding: max(18px, safe-area top) var(--pad) max(26px, safe-area bottom).
Top bar is flex, space-between, gap 16px, z-index 5.
Spacer min-height clamp(24px, 12svh - 24px, 300px).

TABLET, min-width 480px
--pad max(clamp(28px, 5vw, 48px), safe areas). --k 0.82. --artw 205vw.
Two columns: minmax(0,1fr) auto. Areas: "top top" / "copy copy" / "space space" / "story clients". Column gap clamp(24px, 5vw, 64px). Padding top max(24px, safe-area), bottom max(36px, safe-area).
Nav panel anchors right, width 300px.
Copy margin-top clamp(32px, 7svh, 112px).
Headline and lede line spans become display:block and nowrap. Headline max-width none, size min(84px, (100vw - 2*--pad)/10.7, max(44px, 11svh+10px)), line-height 1.0476. Three lines read: "Digital progress made" / "simple, refined by people" / "for good."
Lede margin-top clamp(18px, 2.4svh, 26px), size min(20.25px, (100vw - 2*--pad)/26.5), line-height 1.48, letter-spacing -0.02em.
Spacer min-height clamp(32px, 6svh, 360px).
Clients become a vertical column, gap clamp(14px, 2.6svh, var(--k)*32px), aligned to the end. Story aligns to the end, margin-top 0, title 16.3px.

SHORT LANDSCAPE PHONES, min-width 560px AND max-height 539px
--k 0.72. Single column again: top, copy, space, clients, story. Spacer min-height 32px.
Veil becomes: to bottom rgba(0,0,0,.82) 0, .66 62%, transparent 82%; to top .66 0, transparent 30%.
Clients in a wrapping row, space-between, gap 14px 20px. Story margin-top 18px.

TABLET LANDSCAPE / NEAR-SQUARE, min-width 560px AND min-aspect-ratio 5/6 AND min-height 540px
--gap clamp(32px, 5vw, 64px). --col = 100vw - 2*--pad - --gap - 120px.
Rows: auto 1fr auto. Areas: "top top" / "copy clients" / "story story". Column gap --gap.
Veil is a left scrim: linear-gradient(90deg, rgba(0,0,0,.72) 0, .5 50%, transparent 76%).
Remove the stage mask.
Video uses the desktop geometry: width calc(var(--c)*1366.4), height calc(var(--c)*821.4), left calc(100% - var(--c)*1357), top calc(50% - var(--c)*421). That is the same placement as background-position calc(100% + var(--c)*9.4) and calc(50% - var(--c)*10.3).
Copy and clients are vertically centered, margins 0. Hide the spacer.
Headline size max(34px, min(84px, var(--col)/10.7)), text-wrap balance.
Lede size max(14px, min(20.25px, var(--col)/26.5)), text-wrap pretty.
Story justify-self start, max-width none, margin-left max(0px, 26.5vw - var(--pad)).

INLINE NAV, min-width 900px
Hide the burger. Top bar gap 24px.
Nav becomes static, row, flex 1, space-between, gap 24px, no panel chrome (no border, radius, background, blur, shadow). Always visible, no transform.
Menu is a centered row, gap clamp(28px, 3.4vw, 44px). Links have no padding, 15px, line-height 1, and an invisible ::after hit area inset -12px -10px. CTA margin 0.

DESKTOP CANVAS, min-width 900px AND min-aspect-ratio 4/3 AND min-height 540px
This must be a 1:1 match at 1280×800 and must fill any larger viewport with no letterboxing. Every reference pixel below is multiplied by --u. Anchors: brand and nav to the top, copy and logos to the vertical center, story to the bottom, logos and CTA to the right.
Hero: height var(--vh), min-height 0, padding 0, display block, overflow hidden. Remove ::after.
Stage: not inset. right 0, top 50%, translateY(-50%), width calc(var(--c)*1280), height calc(var(--c)*800), overflow hidden, no mask.
Video: left calc(var(--c)*-77), top calc(var(--c)*-21), width calc(var(--c)*1366.4), height calc(var(--c)*821.4).
Absolutely position: brand, each menu li, cta, headline, lede, each client li, each client svg, each client span, the story, kicker, and title.
Brand: left calc(var(--u)*48), top calc(var(--u)*25), size calc(var(--u)*31.5), tracking -0.03em.
Menu items, top calc(var(--u)*33.5), left from center:
1: 50% + var(--u)*-237
2: 50% + var(--u)*-132
3: 50% + var(--u)*-20
4: 50% + var(--u)*60
5: 50% + var(--u)*168.5
Link size calc(var(--ut)*15), tracking -0.01em. Keep the invisible hit slop.
CTA: left calc(100% - var(--u)*197), top calc(var(--u)*21), width calc(var(--u)*147), height calc(var(--u)*41), font calc(var(--ut)*15.5), tracking -0.01em, padding-left calc(var(--u)*17), border-width calc(var(--u)*1.5), gap calc(var(--u)*10). Arrow calc(var(--u)*14) by calc(var(--u)*11).
Headline: left calc(var(--u)*41), top calc(50% + var(--u)*-188), size calc(var(--u)*84), line-height calc(var(--u)*88), tracking -0.045em, nowrap, lines are blocks. Line tracking: line 1 -0.048em, line 2 -0.042em, line 3 -0.045em.
Lede: left calc(var(--u)*43), top calc(50% + var(--u)*97), size calc(var(--ut)*20.25), line-height calc(var(--ut)*30), tracking -0.02em, nowrap, margin 0. Line tracking: line 1 -0.02em, line 2 -0.03em, line 3 -0.024em.
Client rows share left calc(100% - var(--u)*176). Each li is a 0×0 anchor; svg and span are absolute inside it. Tops from center, then icon box and name box:
1 top 50%+var(--u)*-171. svg left 3, top 0, 31×30. span left 45, top 4.5, 19.5px, weight 500, tracking -0.01em.
2 top 50%+var(--u)*-107. svg left 12, 25×27. span left 50, top 3.5, 20px, weight 500, tracking 0.01em.
3 top 50%+var(--u)*-42. svg left 3, 31×22. span left 46, top 3, 18.75px, weight 400, tracking -0.02em.
4 top 50%+var(--u)*19. svg left 7, 26×27. span left 47, top 3, 22.5px, weight 600, tracking -0.01em.
5 top 50%+var(--u)*80. svg left 6, 28×28. span left 46, top 5.5, 18.75px, weight 400, tracking 0.01em.
6 top 50%+var(--u)*142. svg left 3.5, 33×23. span left 48, top 1, 21.5px, weight 600, tracking 0.
All of those inner offsets and sizes are also multiplied by --u. Icon margins are 0. Names line-height 1 and overflow visible.
Story anchor: left calc(50% + var(--u)*-301), top calc(100% - var(--u)*115). Image calc(var(--u)*103) by calc(var(--u)*68), radius calc(var(--u)*8), border-width calc(var(--u)*1). Kicker left calc(var(--u)*126), top calc(var(--u)*14), size calc(var(--ut)*13), tracking 0.026em. Title left calc(var(--u)*126), top calc(var(--u)*37), size calc(var(--ut)*16.3), tracking -0.02em, weight 400. Both nowrap, line-height 1.
Hide the spacer. Headline and lede stay nowrap. Clients display block with no gap.

NARROWER DESKTOP, same canvas query plus max-aspect-ratio 3/2
Add .hero::before, absolute inset 0, z-index 0, pointer-events none, the same 90deg scrim: rgba(0,0,0,.72) 0, .5 50%, transparent 76%. It is absent at the 16:10 reference ratio.

ENTRANCE (once on load, then the page is static)
The video, masks, and veils never animate. Only UI does.
Head script, before paint: if Element.animate and matchMedia exist and prefers-reduced-motion is not reduce, add class "intro" on the documentElement and remove it after 4 seconds as a safety net. If JS never runs, nothing is hidden.
While .intro is present, opacity 0 on: brand, menu li, cta, toggle, headline, lede, client li, story img, kicker, title.
prefers-reduced-motion: reduce sets transition none on everything and skips the intro class and the timeline.

Timeline uses the Web Animations API only. Easings: expo cubic-bezier(.16,1,.3,1) and quint cubic-bezier(.22,1,.36,1). Fill backwards. Skip any element that is display none, visibility hidden, or has no client rect.
Wait for document.fonts.ready, but start anyway after 800ms. Start on the next animation frame. Remove .intro in that same start frame so the backwards fill holds the first keyframe and there is no flash.
Then:
- Brand settles from translateY(-6px) and opacity 0. Delay 0.10s, duration 0.80s, quint.
- Menu items the same, delay 0.30s + index*0.045s, duration 0.65s.
- Toggle the same, delay 0.40s, duration 0.80s.
- CTA the same, delay 0.64s, duration 0.80s. Do not scale the glass pills.
- If headline lines are display block, each rises with clip-path: from translateY(140%) and inset(-0.3em -0.3em calc(140% - 0.3em) -0.3em) to translateY(0) and inset(-0.3em). Delay 0.18s + index*0.10s, duration 1.10s, expo.
- If lines are inline (phones), sweep one feathered mask down the whole headline: linear-gradient(to bottom, #000 40%, transparent 60%), mask-size 100% 300%, from mask-position 0 100% plus translateY(0.18em) to mask-position 0 0 and no transform. Delay 0.18s, duration 1.30s, quint. Set both maskImage and webkitMaskImage.
- If lede lines are blocks, each rises 0.7em and fades in. Delay 0.62s + index*0.06s, duration 0.90s, quint. If inline, the whole lede rises 14px, delay 0.62s, duration 0.90s.
- Client items rise 10px and fade. Delay 0.82s + index*0.06s, duration 0.70s.
- Story image unmasks upward with clip-path inset(100% 0 0 0 round <its radius>) to inset(0), delay 1.00s, duration 1.00s, expo.
- Kicker rises 0.5em, delay 1.10s, duration 0.75s. Title the same, delay 1.17s.
When every animation finishes, cancel them all so only authored CSS remains, then force one paint invalidation by setting body outline to "0 solid transparent" and removing it on the second animation frame.

MENU BEHAVIOR
Below 900px: toggle flips .topbar.is-open and aria-expanded. Label switches between "Open menu" and "Close menu". Opening moves focus to the first link without scrolling. Closing via Escape returns focus to the button. A click on a link inside the nav closes it when not desktop. Pointerdown outside the top bar closes it. Focus leaving the top bar closes it. Crossing to min-width 900px closes it. Use matchMedia('(min-width:900px)') and addListener as the fallback.

OUTPUT
Return only the finished HTML document. Keep the class names, breakpoints, custom properties, SVG paths, and the CloudFront URL exactly as specified.
[/hidecontent]
← 返回首页