From c1a62de9a571cf4d42c61aa4c495e6d3b7e47d36 Mon Sep 17 00:00:00 2001 From: Muhammad Dzakwan Najmi Date: Thu, 8 Oct 2026 14:39:46 +0800 Subject: [PATCH] feat(site): the ticker shows the six marks, the stack strip draws who runs where The ticker under the hero scrolled words. It now scrolls the marks of the two protocols Wasit checks and the four chains it reads the settlement from, in their own colours on the page's dark: x402 and MPP alone, since their marks are their names, and Stellar, Base, Ethereum and Solana each followed by its name. Stellar's mark is white there. The stack strip had three cells and Stellar only. It now joins x402 and MPP to the four chains with a line wherever a protocol runs on a chain: x402 to all four testnets, MPP to Stellar's, as 0.7.0 tests them, with a dot running each line from protocol to chain. It is one SVG with a wide and a narrow drawing, so lines meet boxes exactly; every box links to the project's site and says in its label what runs there. The marks live in one sprite (components/BrandMarks.tsx): x402 and MPP from their brand files, Stellar, Ethereum and Solana from simple-icons (CC0), Base's Square drawn from its brand guide. The Stellar bitmap the old strip used is gone. Co-Authored-By: Claude Opus 5.5 --- frontend/app/globals.css | 111 +++++------ frontend/app/page.tsx | 41 +++-- frontend/components/BrandMarks.tsx | 96 ++++++++++ frontend/components/StackStrip.tsx | 235 ++++++++++++++++++------ frontend/public/brand/stellar-white.png | Bin 47675 -> 0 bytes 5 files changed, 347 insertions(+), 136 deletions(-) create mode 100644 frontend/components/BrandMarks.tsx delete mode 100644 frontend/public/brand/stellar-white.png diff --git a/frontend/app/globals.css b/frontend/app/globals.css index f88b080..785c1e5 100644 --- a/frontend/app/globals.css +++ b/frontend/app/globals.css @@ -677,31 +677,34 @@ mark { color: inherit; background: none; } } .copy-btn:hover { color: var(--accent); border-color: var(--accent); } -/* Ticker band: the accent, full bleed, one line of facts scrolling. */ +/* Ticker band: the marks of the two protocols Wasit checks and the four + chains it reads, each in its own colour on the page's dark, one line + scrolling. The protocols' marks carry their names; the chains' are small + glyphs, so their names follow them. */ .ticker { overflow: hidden; - background: var(--accent); - color: var(--on-accent); - border-bottom: 1px solid var(--border); + background: var(--bg); + color: var(--fg); + border-block: 1px solid var(--border-strong); } .ticker-track { display: flex; width: max-content; animation: ticker 38s linear infinite; } -.ticker-group { display: flex; flex: none; } +.ticker-group { display: flex; flex: none; align-items: center; } .ticker-item { display: inline-flex; align-items: center; - gap: 22px; - padding: 11px 0 11px 22px; - font-family: var(--font-code); - font-size: 12px; - font-weight: 700; - letter-spacing: 0.14em; + gap: 9px; + padding: 13px 0 13px 30px; + font-size: 14px; + font-weight: 600; + color: var(--muted); white-space: nowrap; } -.ticker-square { width: 7px; height: 7px; background: var(--on-accent); } +.ticker-item svg { display: block; flex: none; fill: currentColor; } +.ticker-dot { width: 4px; height: 4px; margin-left: 30px; background: var(--dim); flex: none; } @keyframes ticker { to { transform: translateX(-50%); } } @@ -710,21 +713,11 @@ mark { color: inherit; background: none; } } /* The stack strip under the ticker (components/StackStrip.tsx): a short - line, then one cell per project — the two protocols Wasit checks and - the chain it trusts — each with its logo in the page's own colour. */ + line, then the protocols joined by a line to each chain they run on. + Two drawings of it; CSS shows the wide one from 1100px. */ .stack { border-bottom: 1px solid var(--border); } -.stack-grid { - display: grid; - grid-template-columns: minmax(0, 1.25fr) repeat(3, minmax(0, 1fr)); -} -.stack-intro { - display: flex; - flex-direction: column; - justify-content: center; - gap: 10px; - padding: 32px 28px 32px 0; - border-right: 1px solid var(--border-strong); -} +.stack-fan { display: flex; flex-direction: column; gap: 24px; padding-block: 40px 44px; } +.stack-intro { display: flex; flex-direction: column; gap: 10px; } .stack-kicker { display: inline-flex; align-items: center; @@ -737,41 +730,37 @@ mark { color: inherit; background: none; } } .stack-kicker::before { content: ""; width: 7px; height: 7px; background: var(--accent); } .stack-title { margin: 0; font-size: clamp(19px, 1.7vw, 24px); font-weight: 600; line-height: 1.3; letter-spacing: -0.01em; } -.stack-cell { - display: flex; - flex-direction: column; - gap: 10px; - padding: 28px 24px; - border-right: 1px solid var(--border-strong); - color: var(--fg); - transition: background 160ms ease; -} -.stack-cell:last-child { border-right: none; } -.stack-cell:hover { color: var(--fg); background: color-mix(in oklab, var(--accent), transparent 90%); } -.stack-role { - font-family: var(--font-code); - font-size: 10.5px; - letter-spacing: 0.16em; - text-transform: uppercase; - color: var(--accent); -} -.stack-role::before { content: "// "; color: var(--dim); } -.stack-mark { display: flex; align-items: center; height: 48px; margin: 6px 0 4px; color: var(--fg); opacity: 0.85; transition: opacity 160ms ease; } -.stack-cell:hover .stack-mark { opacity: 1; } -.stack-logo { display: block; width: auto; fill: currentColor; } -.stack-logo--x402 { height: 40px; } -.stack-logo--mpp { height: 26px; } -.stack-logo--stellar { height: 36px; } -.stack-name { font-size: 14.5px; font-weight: 600; } -.stack-meta { font-family: var(--font-code); font-size: 11.5px; letter-spacing: 0.04em; color: var(--muted); } -@media (max-width: 960px) { - .stack-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } - .stack-intro { grid-column: 1 / -1; padding: 28px 0 20px; border-right: none; border-bottom: 1px solid var(--border-strong); } -} -@media (max-width: 600px) { - .stack-grid { grid-template-columns: minmax(0, 1fr); } - .stack-cell { border-right: none; border-bottom: 1px solid var(--border-strong); padding: 22px 0; } - .stack-cell:last-child { border-bottom: none; } +.stack-diagram { min-width: 0; } +.fan { display: block; width: 100%; height: auto; } +.fan--narrow { display: none; max-width: 560px; } +@media (max-width: 1099px) { + .fan--wide { display: none; } + .fan--narrow { display: block; } +} +.fan-box { fill: var(--surface); stroke: var(--border-strong); stroke-width: 1; transition: fill 160ms ease, stroke 160ms ease; } +.fan-node:hover .fan-box, +.fan-node:focus-visible .fan-box { fill: color-mix(in oklab, var(--accent), var(--surface) 88%); stroke: var(--accent); } +.fan-node:focus-visible { outline: none; } +.fan-role { font-family: var(--font-code); font-size: 11.5px; letter-spacing: 0.16em; text-transform: uppercase; fill: var(--accent); } +.fan-role--sm { font-size: 9.5px; } +.fan-slash { fill: var(--dim); } +.fan-name { font-family: var(--font-body); font-size: 17px; font-weight: 600; fill: var(--fg); } +.fan-name--sm { font-size: 15px; } +.fan-name--xs { font-size: 12.5px; } +.fan-meta { font-family: var(--font-code); font-size: 13px; letter-spacing: 0.03em; fill: var(--muted); } +.fan-meta--sm { font-size: 10px; } +.fan-mark { fill: var(--fg); opacity: 0.88; transition: opacity 160ms ease; } +.fan-node:hover .fan-mark { opacity: 1; } +.fan-line { fill: none; stroke-width: 1.5; } +.fan-line--x { stroke: var(--accent); } +.fan-line--m { stroke: var(--accent-2); } +.fan-joint { stroke: var(--bg); stroke-width: 2; } +.fan-joint--x { fill: var(--accent); } +.fan-joint--m { fill: var(--accent-2); } +.fan-flow--x { fill: var(--fg); } +.fan-flow--m { fill: var(--accent-2); } +@media (prefers-reduced-motion: reduce) { + .fan-flow { display: none; } } /* Bands: every section below the hero. */ diff --git a/frontend/app/page.tsx b/frontend/app/page.tsx index 41625d8..e54832c 100644 --- a/frontend/app/page.tsx +++ b/frontend/app/page.tsx @@ -9,6 +9,7 @@ import { FaqList, type FaqEntry } from "@/components/FaqList"; import { McpSession } from "@/components/McpSession"; import { SequenceFlow } from "@/components/SequenceFlow"; import { StackStrip } from "@/components/StackStrip"; +import { BrandSprite, Mark, type MarkId } from "@/components/BrandMarks"; import { StrokeText } from "@/components/StrokeText"; import { TechText } from "@/components/TechText"; import { ScrollReveal } from "@/components/ScrollReveal"; @@ -24,17 +25,19 @@ import { CHECK_COUNT, WASIT_VERSION } from "@/lib/site-facts"; const INSTALL_CMD = "npx @wasit-dev/cli test --target --read-only"; const GITHUB_URL = "https://github.com/wasit-dev/wasit"; -// Words for the ticker band under the hero. Every item is a fact the page -// makes elsewhere; the band repeats them, it does not add to them. Set in -// capitals here rather than by CSS, which would also capitalise "x402". -const TICKER_ITEMS = [ - "VERIFY THE SETTLEMENT", - "x402", - "MPP", - "STELLAR · BASE · ETHEREUM · SOLANA", - `${CHECK_COUNT} CHECKS`, - "CLI · MCP · CORE", - "APACHE-2.0", +// The ticker band under the hero: the two protocols Wasit checks and the +// four chains it reads the settlement from, as their marks. x402's and MPP's +// marks are their names, so they stand alone; the chains' are glyphs, so +// each is followed by its name. Brand colours, except Stellar's mark, which +// is white on this dark band. +type TickerMark = { id: MarkId; height: number; label?: string; style: React.CSSProperties } +const TICKER_MARKS: TickerMark[] = [ + { id: "x402", height: 19, style: { color: "var(--fg)" } }, + { id: "mpp", height: 13, style: { color: "var(--fg)" } }, + { id: "stellar", height: 20, label: "Stellar", style: { color: "var(--fg)" } }, + { id: "base", height: 18, label: "Base", style: { color: "#3d5afe" } }, + { id: "ethereum", height: 21, label: "Ethereum", style: { color: "#8a92f2" } }, + { id: "solana", height: 19, label: "Solana", style: { fill: "url(#wm-solana-gradient)" } }, ]; type CompareRow = { without: string; with: string }; @@ -244,16 +247,20 @@ export default function Home() { +