Skip to content
All Taste components

Gradient heroes

Midnight glow hero

An always-dark opening section with glowing colour fields rising on the right and an early-access email form on the left.

always dark · 4 glowing fields · side veil · email capture · avatar proof

Private betaNow with database branching

Every pull request gets its own production.

Kiln spins up a full copy of your stack for each branch — database, queues and all — and tears it down when you merge.

AKRMJSLP
Joined by 4,800 platform teams
import { ArrowRight } from "lucide-react";

/* Always dark: uses the brand/neutral scales, so it stays dark in light mode too.
Add once to globals.css:
@keyframes glow-1 { to { transform: translate(-16%, 20%) scale(1.1); } }
@keyframes glow-2 { to { transform: translate(20%, 14%) scale(.86); } }
@keyframes glow-3 { to { transform: translate(-22%, -18%) scale(1.14); } }
@keyframes glow-core { from { transform: scale(.8); opacity: .6; } to { transform: translate(-30%, 40%) scale(1.15); opacity: 1; } }
*/

const field = "absolute aspect-square rounded-full will-change-transform motion-reduce:animate-none";

export function HeroMidnight() {
  return (
    <section aria-labelledby="midnight-title" className="relative isolate overflow-hidden bg-neutral-950 px-5 pb-24 pt-5 font-sans text-neutral-50 sm:px-10">
      <div aria-hidden className="absolute inset-0 -z-10 overflow-hidden animate-fade motion-reduce:animate-none">
        <span className={field + " -right-[10%] -top-[36%] w-[max(54%,380px)] bg-[radial-gradient(closest-side,color-mix(in_srgb,var(--tst-brand-500)_78%,transparent),transparent)] animate-[glow-1_20s_ease-in-out_infinite_alternate]"} />
        <span className={field + " right-[16%] top-[4%] w-[max(38%,280px)] bg-[radial-gradient(closest-side,color-mix(in_srgb,var(--tst-info-500)_60%,transparent),transparent)] animate-[glow-2_26s_ease-in-out_infinite_alternate]"} />
        <span className={field + " -right-[16%] top-[34%] w-[max(42%,300px)] bg-[radial-gradient(closest-side,color-mix(in_srgb,var(--tst-danger-500)_46%,transparent),transparent)] animate-[glow-3_23s_ease-in-out_infinite_alternate]"} />
        <span className={field + " -top-[4%] right-[12%] w-[max(16%,130px)] bg-[radial-gradient(closest-side,color-mix(in_srgb,var(--tst-brand-200)_70%,transparent),transparent)] animate-[glow-core_9s_ease-in-out_infinite_alternate]"} />
      </div>
      {/* Veil: copy sits on near-black, the glow lives on the right */}
      <div aria-hidden className="absolute inset-0 -z-10 bg-[linear-gradient(180deg,transparent,color-mix(in_srgb,var(--tst-neutral-950)_70%,transparent)_40%,var(--tst-neutral-950)_85%)] md:bg-[linear-gradient(100deg,var(--tst-neutral-950)_22%,color-mix(in_srgb,var(--tst-neutral-950)_50%,transparent)_52%,transparent_78%)]" />

      <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-brand-300 to-brand-500" /> Kiln
        </a>
        <div className="hidden gap-6 text-[13.5px] text-neutral-400 sm:flex">
          {["Product", "Changelog", "Pricing", "Docs"].map((l) => <a key={l} href="#" className="hover:text-neutral-50">{l}</a>)}
        </div>
        <a href="/access" className="inline-flex h-8 items-center rounded bg-neutral-50 px-3 text-[13px] font-medium text-neutral-950 hover:bg-neutral-200">Get access</a>
      </nav>

      <div className="mx-auto flex max-w-[1080px] flex-col items-start gap-5">
        <a href="/changelog" className="inline-flex items-center gap-2 rounded-full border border-neutral-800 bg-neutral-900/70 py-0.5 pl-0.5 pr-3 text-[12.5px] text-neutral-300 animate-rise motion-reduce:animate-none">
          <span className="rounded-full bg-brand-400/20 px-2 py-0.5 text-xs font-medium text-brand-200">Private beta</span>
          Now with database branching <ArrowRight className="size-3.5" aria-hidden />
        </a>
        <h1 id="midnight-title" className="max-w-[13ch] text-balance text-4xl font-medium leading-[1.02] tracking-[-0.04em] sm:text-6xl lg:text-7xl animate-rise [animation-delay:80ms] motion-reduce:animate-none">
          Every pull request gets its own production.
        </h1>
        <p className="max-w-[500px] text-pretty text-base leading-relaxed text-neutral-400 sm:text-lg animate-rise [animation-delay:160ms] motion-reduce:animate-none">
          Kiln spins up a full copy of your stack for each branch — database, queues and all — and tears it down when you merge.
        </p>
        <form className="flex w-full max-w-[460px] flex-wrap gap-2 animate-rise [animation-delay:240ms] motion-reduce:animate-none" onSubmit={(e) => e.preventDefault()}>
          <label htmlFor="midnight-email" className="sr-only">Work email</label>
          <input id="midnight-email" type="email" autoComplete="email" placeholder="you@company.com"
            className="h-11 min-w-0 flex-[1_1_220px] rounded border border-neutral-700 bg-neutral-900/80 px-3 text-neutral-50 outline-none placeholder:text-neutral-500 focus:border-brand-400 focus:ring-[3px] focus:ring-brand-400/30" />
          <button type="submit" className="h-11 rounded bg-neutral-50 px-5 font-medium text-neutral-950 hover:bg-neutral-200 active:scale-[.97]">Get early access</button>
        </form>
        <div className="mt-2 flex items-center gap-3 text-[13px] text-neutral-400">
          <div className="flex">
            {["AK", "RM", "JS", "LP"].map((a, i) => (
              <span key={a} className={"grid size-7 place-items-center rounded-full border-2 border-neutral-950 bg-neutral-800 text-[11px] font-medium text-neutral-200" + (i ? " -ml-2" : "")}>{a}</span>
            ))}
          </div>
          Joined by 4,800 platform teams
        </div>
      </div>
    </section>
  );
}

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