feat(marketing): redesign landing as "trusted infrastructure"
ci / gates (push) Has been cancelled
ci / rust (push) Has been cancelled
ci / sandbox-k8s (push) Has been cancelled
ci / frontend (push) Has been cancelled
ci / e2e (push) Has been cancelled

Re-skins the playful/consumer feel into disciplined agent-infrastructure,
keeping the animated hero canvas (re-themed) and adding the hierarchy story.

- Palette: re-point coral→ember (#E0584A); add ink/surface/mist/slate-light/
  azure/teal tokens. One accent per viewport; retire the black/coral split-
  headline pattern across all 8 headings (single ink color).
- Typography: hero/section weights 800→~650-675, tighter tracking, smaller
  hero size; uppercase eyebrow label.
- Hero: dark ink base with glowing azure/indigo + faint ember canvas blooms;
  light copy; new positioning ("Build safe, scalable agentic systems" + the
  single-agent-to-company subhead); ember primary CTA + ghost "Read the docs".
- Imagery overhaul (code-built, no mascots): AgentToken chips (CrewStrip,
  OneClick card, footer), AlwaysOn rebuilt as a terminal/log with an approval
  line, SkillsShowcase as duotone lucide cards on Mist, Security as a shield/
  lock motif.
- New HierarchyDiagram section ("One agent, or a whole org chart"): SVG org
  chart with an azure active path and teal human-approval checkpoints on
  sandbox-leaving actions.
- Tests: dark-hero/terminal/eyebrow contrast fixed to AA; refreshed the
  marketing @visual baseline (hero masked).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
Omar Sobh
2026-06-15 15:56:58 -07:00
co-authored by Claude Opus 4.8
parent 4b55c4d81e
commit 44512a744f
8 changed files with 436 additions and 150 deletions
@@ -6,8 +6,8 @@ import { useEffect, useRef } from "react";
* (js/shift.js): a few dozen large circles drift at random, their hue driven by
* 3D simplex noise at their position + time; everything is drawn to an offscreen
* buffer, then blurred and composited onto the visible canvas over a flat base.
* Re-tuned to a light, brand palette (pale periwinkle base; soft blue→violet→coral
* blooms) so the dark hero copy stays readable. Scoped to its container, not the
* Re-themed to a dark, infrastructure palette (deep-ink base; glowing azure/indigo
* blooms with a faint ember). Light hero copy sits on top. Scoped to its container, not the
* window. Respects prefers-reduced-motion and pauses when scrolled out of view. */
// --- tunables (all easy to tweak) ---------------------------------------
@@ -16,16 +16,19 @@ const BASE_SPEED = 0.06;
const RANGE_SPEED = 0.7;
const BASE_TTL = 180;
const RANGE_TTL = 260;
const BASE_RADIUS = 120;
const RANGE_RADIUS = 240;
const BASE_RADIUS = 140;
const RANGE_RADIUS = 260;
const NOISE_OFF = 0.0015; // x/y/z noise sampling step
const BLUR_PX = 50;
const BASE_COLOR = "#edf3fc"; // pale periwinkle base (matches the hero fill)
const HUE_MIN = 205; // blue
const HUE_MAX = 360; // → indigo / violet / magenta / coral
const SAT = 70;
const LIGHT = 74;
const ALPHA = 0.5; // peak blob opacity (scaled by fade-in/out)
const BLUR_PX = 55;
const BASE_COLOR = "#0b1220"; // deep ink — blooms read as glowing light sources
const ALPHA = 1; // global multiplier on each blob's peak alpha
// Cool glow palette on dark [r, g, b, peakAlpha]. Azure + indigo dominate; a
// faint ember adds warmth (re-themed from the original hue-band approach).
const PALETTE: [number, number, number, number][] = [
[59, 130, 246, 0.22], // azure #3B82F6
[79, 70, 229, 0.18], // indigo #4F46E5
[224, 88, 74, 0.12], // ember #E0584A (faint, rare)
];
const TAU = Math.PI * 2;
const rand = (n: number) => n * Math.random();
@@ -152,17 +155,18 @@ export function HeroAmbient() {
const simplex = new SimplexNoise();
const circles = new Float32Array(CIRCLE_COUNT * PROPS);
let baseHue = HUE_MIN;
let tick = 0;
let raf = 0;
let running = true;
function initCircle(i: number) {
const x = rand(a.width);
const y = rand(a.height);
const n = simplex.noise3D(x * NOISE_OFF, y * NOISE_OFF, baseHue * NOISE_OFF);
const n = simplex.noise3D(x * NOISE_OFF, y * NOISE_OFF, tick * NOISE_OFF);
const ang = rand(TAU);
const speed = BASE_SPEED + rand(RANGE_SPEED);
const hue = HUE_MIN + ((n + 1) / 2) * (HUE_MAX - HUE_MIN);
// Noise picks the glow color: azure dominant, indigo next, ember rare.
const colorIndex = n > 0.05 ? 0 : n > -0.4 ? 1 : 2;
circles.set(
[
x,
@@ -172,7 +176,7 @@ export function HeroAmbient() {
0,
BASE_TTL + rand(RANGE_TTL),
BASE_RADIUS + rand(RANGE_RADIUS),
hue,
colorIndex,
],
i,
);
@@ -184,10 +188,11 @@ export function HeroAmbient() {
life: number,
ttl: number,
radius: number,
hue: number,
colorIndex: number,
) {
const [r, g, b, peak] = PALETTE[colorIndex] ?? PALETTE[0];
actx.save();
actx.fillStyle = `hsla(${hue},${SAT}%,${LIGHT}%,${fadeInOut(life, ttl) * ALPHA})`;
actx.fillStyle = `rgba(${r},${g},${b},${fadeInOut(life, ttl) * peak * ALPHA})`;
actx.beginPath();
actx.arc(x, y, radius, 0, TAU);
actx.fill();
@@ -216,8 +221,7 @@ export function HeroAmbient() {
actx.clearRect(0, 0, a.width, a.height);
bctx.fillStyle = BASE_COLOR;
bctx.fillRect(0, 0, b.width, b.height);
baseHue += 0.05; // slow drift keeps the band gently shifting
if (baseHue > HUE_MAX) baseHue = HUE_MIN;
tick++; // advances the noise field used when respawning circles
for (let i = 0; i < circles.length; i += PROPS) updateCircle(i);
bctx.save();
bctx.filter = `blur(${BLUR_PX}px)`;