Skip to content
All Taste components

Gradient heroes

Blended spotlight hero

A left-aligned opening section where a travelling spotlight and two companion fields mix where they overlap, tinting a light page and glowing on a dark one.

multiply + screen layers · travelling spotlight · light/dark aware · stat cards

Run-of-show for live events

Run the whole show from one screen.

Cues, speakers, lighting and the stream stay in step, and every crew member sees the next ten minutes on their phone.

1,240shows run last month
0.4 scue sync across devices
38crew on the largest show
import { ArrowRight } from "lucide-react";

/* The colour layer is opaque (bg-bg), so the fields blend with it:
   multiply tints a light page and disappears on a dark one, screen glows on a
   dark page and disappears on a light one — no dark: classes needed.
Add once to globals.css:
@keyframes spot { to { transform: translate(78%, 34%) scale(.92); } }
@keyframes spot-a { to { transform: translate(-46%, 42%) scale(1.15); } }
@keyframes spot-c { to { transform: translate(-52%, -26%) scale(.9); } }
*/

const field = "absolute aspect-square rounded-full will-change-transform motion-reduce:animate-none";
const spot = field + " -left-[12%] -top-[46%] w-[max(62%,420px)] animate-[spot_20s_ease-in-out_infinite_alternate]";
const a = field + " -right-[16%] -top-[20%] w-[max(48%,340px)] animate-[spot-a_26s_ease-in-out_infinite_alternate]";
const c = field + " -bottom-[54%] right-[10%] w-[max(52%,360px)] animate-[spot-c_23s_ease-in-out_infinite_alternate]";
const stats = [
  { value: "1,240", label: "shows run last month" },
  { value: "0.4 s", label: "cue sync across devices" },
  { value: "38", label: "crew on the largest show" },
];

export function HeroBlendSpotlight() {
  return (
    <section aria-labelledby="blend-title" className="relative isolate overflow-hidden bg-bg px-5 pb-24 pt-5 font-sans text-fg sm:px-10">
      <div aria-hidden className="absolute inset-0 -z-10 overflow-hidden bg-bg">
        {/* multiply: visible on light pages */}
        <span className={spot + " mix-blend-multiply bg-[radial-gradient(closest-side,var(--tst-brand-300),transparent)]"} />
        <span className={a + " mix-blend-multiply bg-[radial-gradient(closest-side,var(--tst-info-300),transparent)]"} />
        <span className={c + " mix-blend-multiply bg-[radial-gradient(closest-side,var(--tst-warning-300),transparent)]"} />
        {/* screen: visible on dark pages */}
        <span className={spot + " mix-blend-screen bg-[radial-gradient(closest-side,color-mix(in_srgb,var(--tst-brand-600)_85%,transparent),transparent)]"} />
        <span className={a + " mix-blend-screen bg-[radial-gradient(closest-side,color-mix(in_srgb,var(--tst-info-700)_80%,transparent),transparent)]"} />
        <span className={c + " mix-blend-screen bg-[radial-gradient(closest-side,color-mix(in_srgb,var(--tst-danger-700)_70%,transparent),transparent)]"} />
      </div>

      <nav aria-label="Main" className="mx-auto mb-16 flex max-w-[1080px] items-center justify-between gap-4 sm:mb-24">
        <a href="/" className="flex items-center gap-2 text-[15px] font-semibold">
          <span className="size-[22px] rounded-sm bg-gradient-to-br from-primary to-info" /> Stagehand
        </a>
        <a href="/signup" className="inline-flex h-8 items-center rounded bg-primary px-3 text-[13px] font-medium text-primary-fg hover:bg-primary-hover">Plan an event</a>
      </nav>

      <div className="mx-auto flex max-w-[1080px] flex-col items-start gap-5">
        <span className="text-xs font-medium uppercase tracking-[.1em] text-fg-muted animate-rise motion-reduce:animate-none">Run-of-show for live events</span>
        <h1 id="blend-title" className="max-w-[13ch] text-balance text-4xl font-medium leading-[1.02] tracking-[-0.04em] sm:text-6xl lg:text-[78px] animate-rise [animation-delay:80ms] motion-reduce:animate-none">
          Run the whole show from one screen.
        </h1>
        <p className="max-w-xl text-pretty text-base leading-relaxed text-fg-muted sm:text-lg animate-rise [animation-delay:160ms] motion-reduce:animate-none">
          Cues, speakers, lighting and the stream stay in step, and every crew member sees the next ten minutes on their phone.
        </p>
        <div className="flex flex-wrap gap-2.5 animate-rise [animation-delay:240ms] motion-reduce:animate-none">
          <a href="/signup" className="inline-flex h-11 items-center gap-1.5 rounded bg-primary px-5 font-medium text-primary-fg hover:bg-primary-hover active:scale-[.97]">
            Plan an event <ArrowRight className="size-4" aria-hidden />
          </a>
          <a href="/live" className="inline-flex h-11 items-center rounded border border-border-strong bg-bg px-5 font-medium hover:bg-surface active:scale-[.97]">Watch a live run</a>
        </div>
        <dl className="mt-4 grid w-full gap-2.5 sm:grid-cols-3">
          {stats.map((s) => (
            <div key={s.label} className="rounded-lg border border-fg/10 bg-bg/60 px-4 py-3.5">
              <dt className="sr-only">{s.label}</dt>
              <dd className="text-[22px] font-medium tabular-nums tracking-tight">{s.value}</dd>
              <dd className="text-[12.5px] text-fg-muted">{s.label}</dd>
            </div>
          ))}
        </dl>
      </div>
    </section>
  );
}

The code uses the Taste Tailwind preset. Make yours on the Taste page with Export my system.