Chrome Outline Wordmark
A giant outlined wordmark to close the page: a dark main stroke layered with offset red and blue chromatic strokes, receding 3D outlines and a floor reflection, with a silver-gray spotlight inside the letters that follows the pointer like a glass mirror. Without a pointer the spotlight wanders on its own.
Taken from the page template Houtu Creative Studio Home. Use it on its own, or combine it with the other components from the same template to rebuild the full page.
Plain HTML, CSS and a little vanilla JS, with no framework dependency. Copy the prompt into Claude Code, Cursor, Trae or Codex and the model adds Chrome Outline Wordmark to your project in your colors.
Where to use it
Scroll, hover and entrance motion that gives a page rhythm; animation uses only transform and opacity.
Install
With Builder, install it with the 8pt CLI or call it directly from an editor connected to 8pt MCP.
Code
Source for Chrome Outline Wordmark. Motion uses only transform and opacity and respects the Reduce motion setting.
<div class="x-cwm"><p class="x-cwm__word" aria-label="厚土"><span class="x-cwm__l1">厚土</span><span class="x-cwm__l4" aria-hidden="true">厚土</span><span class="x-cwm__l2" aria-hidden="true">厚土</span><span class="x-cwm__l3" aria-hidden="true">厚土</span><span class="x-cwm__l5" aria-hidden="true">厚土</span><span class="x-cwm__d" aria-hidden="true">厚土</span><span class="x-cwm__d x-cwm__d2" aria-hidden="true">厚土</span><span class="x-cwm__d x-cwm__d3" aria-hidden="true">厚土</span></p><p class="x-cwm__refl" aria-hidden="true">厚土</p></div>
@import url("https://fonts.googleapis.com/css2?family=Fragment+Mono&family=Inter+Tight:wght@500;600;700&family=Noto+Sans+SC:wght@400;500;700;900&family=Noto+Serif+SC:wght@400;600&family=ZCOOL+QingKe+HuangYou&display=swap");.x-cwm{width:100%;max-width:1200px;box-sizing:border-box;padding:10px 0;background:#FFFFFF;overflow:hidden;user-select:none;--mx:50%;--my:40%}.x-cwm__word{position:relative;width:calc(100% - 40px);margin:0 auto;text-align:center;font-family:"ZCOOL QingKe HuangYou","Noto Sans SC",sans-serif;font-size:540px;line-height:1;letter-spacing:-.02em}.x-cwm__word span{display:block}.x-cwm__word span:not(:first-child){position:absolute;inset:0}.x-cwm__l1{color:transparent;-webkit-text-stroke:3px #2a2c33}.x-cwm__l2{color:transparent;-webkit-text-stroke:2px rgba(255,40,90,.55);transform:translate(-3px,1px);mix-blend-mode:multiply}.x-cwm__l3{color:transparent;-webkit-text-stroke:2px rgba(40,110,255,.55);transform:translate(3px,-1px);mix-blend-mode:multiply}.x-cwm__l4{color:transparent;background:radial-gradient(circle at var(--mx) var(--my),rgba(255,255,255,.95) 0,rgba(170,176,192,.85) 14%,rgba(255,255,255,0) 36%),linear-gradient(172deg,#f7f8fb 0%,#c9ced9 18%,#ffffff 30%,#aeb4c2 46%,#eef0f5 58%,#d7c9e6 70%,#ffffff 80%,#b9c3d6 100%);-webkit-background-clip:text;background-clip:text}.x-cwm__l5{color:transparent;-webkit-text-stroke:1px rgba(255,255,255,.95);transform:translateY(-2px)}.x-cwm__word{z-index:0}.x-cwm__d{z-index:-1;color:transparent;-webkit-text-stroke:1.5px rgba(42,44,51,.28);transform:translate(5px,7px)}.x-cwm__d2{-webkit-text-stroke:1px rgba(120,90,200,.25);transform:translate(10px,14px)}.x-cwm__d3{-webkit-text-stroke:1px rgba(42,44,51,.14);transform:translate(15px,21px)}.x-cwm__refl{height:190px;margin:-6px 0 0;overflow:hidden;text-align:center;font-family:"ZCOOL QingKe HuangYou","Noto Sans SC",sans-serif;font-size:540px;line-height:1;letter-spacing:-.02em;color:transparent;-webkit-text-stroke:2px rgba(42,44,51,.5);background:linear-gradient(172deg,#f7f8fb 0%,#c9ced9 18%,#ffffff 30%,#aeb4c2 46%,#eef0f5 58%,#d7c9e6 70%,#ffffff 80%,#b9c3d6 100%);-webkit-background-clip:text;background-clip:text;transform:scaleY(-1);transform-origin:50% 50%;opacity:.35;-webkit-mask-image:linear-gradient(to top,#000,transparent 85%);mask-image:linear-gradient(to top,#000,transparent 85%)}(root) => {
const box = root.querySelector(".x-cwm") || root;
let raf = 0, t = 0, idle = true;
const reduce = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
const set = (x, y) => { box.style.setProperty("--mx", x + "%"); box.style.setProperty("--my", y + "%"); };
const loop = () => { if (idle) { t += 0.006; set(50 + Math.sin(t) * 34, 45 + Math.cos(t * 1.3) * 22); } raf = requestAnimationFrame(loop); };
const move = (e) => { idle = false; const r = box.getBoundingClientRect(); set((e.clientX - r.left) / r.width * 100, (e.clientY - r.top) / r.height * 100); };
const leave = () => { idle = true; };
box.addEventListener("pointermove", move);
box.addEventListener("pointerleave", leave);
if (!reduce) raf = requestAnimationFrame(loop);
return () => { cancelAnimationFrame(raf); box.removeEventListener("pointermove", move); box.removeEventListener("pointerleave", leave); };
…