# Showcase: Logo reveal

The brand wordmark itself, on a seamless loop: the colored E-bars ignite out of shadow, the cream
letterforms rise behind them, three specular shines rake across the locked lockup, then it settles
back and repeats. Where the other four showcases carry heavy custom *simulation or procedural
generation* on a thin engine seam, this one asks the opposite question — how **little** do you need? —
and answers it with a pure,
unit-tested timeline and one hand-written Skia shader. It's the taste-over-spectacle piece, and the
smallest engine footprint of the five.

<Aside type="note" title="Read Foundations first">
This guide builds on [Foundations](/guides/foundations) — the contract, the post-FX surface and its
frame shape, the palette, and the engine-liftable pure-module discipline.
</Aside>

## What the engine provides here

The least of all five: just `GameLoop` (`@flare-engine/core`) for a pause-correct clock, and the
post-FX finish (`@flare-engine/postfx`). No ECS, no particles, no simulation — not even the math
package. **Everything else is yours** — the geometry, the timeline, the shader, and the compositing.
It's the proof that the same seam that carries an N-body merger also carries a three-rect logo
without ceremony.

## The wordmark as Skia geometry

No raster asset goes through Skia. The cream letterforms are a single `Path.MakeFromSVGString` of the
wordmark's `d`; the six EƎ bars are rects. A small `Mark` bundles the viewBox, the (optional) letter
path, and the cream/colored bars, so one renderer drives either the full lockup or the compact
monogram:

```ts
const letterPath = mark.letterPathD ? kit.Path.MakeFromSVGString(mark.letterPathD) : null;
// six bars: left column cream, right column cyan / magenta / lime — drawn as rects, tintable per-bar
```

Colors come from the frozen palette that mirrors `tokens.css`, and a fit transform centres the mark
in the canvas. One detail matters: keep Skia's default **Winding** fill rule, or the counters of the
A/R/E letterforms invert.

## A pure timeline, seamless by construction

`timeline.ts` is a pure function, `logoState(t)` — no Skia, no mutable state, just numbers. The loop
is seamless **by construction**: it opens and closes on a flat "ember" rest (every reveal envelope
saturated or zero, with zero slope), so value *and* velocity match across the wrap. That invariant is
unit-tested, not eyeballed:

```ts
// the visible state matches across the seam (position + velocity), so the hero never hitches
expect(visible(LOOP_PERIOD - 1e-6)).toBeCloseTo(visible(0));
```

The beats: colored bars ignite staggered (cyan → magenta → lime), the cream emerges from shadow
(blur → 0 as it sharpens), three shines sweep across (R→L, L→R, R→L), then it drains back to ember.
`logoState` returns the bar alphas, the cream alpha/blur, and the active shine's position, direction,
and strength — the renderer knows nothing about timing, and the tests know nothing about Skia.

## The bespoke shine: a hand-written Skia shader

The star of the piece. The specular sheen is a real `RuntimeEffect` (SkSL) — not a moving gradient.
It rakes a feathered band along a diagonal axis and samples that band at ±`uDisp` per channel, so the
edges throw a cyan/magenta **prism fringe** that peaks with the flash and collapses to nothing at
rest — the engine's own light-split brand, expressed in a fragment shader:

```glsl
half4 main(float2 coord) {
  float base = dot(coord - uPivot, uDir) - uOffset;  // signed distance along the sweep axis
  float r = bandAt(base - uDisp);                    // R/G/B sampled with a dispersion offset
  float g = bandAt(base);
  float b = bandAt(base + uDisp);
  half3 col = half3(r, g, b) * uStrength;
  return half4(col, max(col.r, max(col.g, col.b)));  // additive light, premultiplied
}
```

Because a runtime shader is evaluated in *local* space, `coord` arrives in the mark's own viewBox
units — the sweep is resolution-independent and looks identical at any canvas size. And if the shader
won't compile on a given GPU driver, the renderer falls back to an equivalent linear-gradient band:
the shine degrades, it never breaks.

## Hue-preserving bars, and the flash

A white sheen drawn over the cyan bar would wash it toward white. So the white shine is clipped to the
**cream only**; each colored bar instead brightens in its **own palette color** as the band crosses
it — an analytic copy of the shader's band falloff, evaluated at the bar's projection on the sweep
axis. Additive `Plus` blending keeps the hue: the bar shines *bluer*, never whiter.

The flash is just the composite intensity. `composite(baseBloom + bloom · sheenStrength)` spikes the
engine bloom as each shine crosses centre, and a heavily-blurred additive re-draw of the lit mark
spreads a real halo outward — the stock bloom only boosts bright pixels in place, so the spread is
worth the extra pass.

## Wiring: the thinnest instance

No simulation means no `onFixedUpdate`, no ECS, no pool — just a clock and a draw:

```ts
const loop = new GameLoop({ fixedDt: 1 / 60, maxDt: 0.1 });
let t = 0;
loop.onUpdate.add((dt) => { t = (t + dt) % period; }); // pause-correct: dt only accrues while running
loop.onPreRender.add(() => renderer.draw(t));
```

The instance exposes only the six required contract members plus a handful of live dev-panel knobs
(shine glow, width, prism split, bloom, and shine speed). And the details that make it *ship*: it
renders at up to **2× device pixels** so the letters stay crisp on retina (backing store only — the
canvas CSS size is untouched), swaps to the **compact monogram** below 480 px, and — like every hero
— is never instantiated under `prefers-reduced-motion`, where the static wordmark already in the page
DOM is the reduced story.

## Recap

<Steps>

1. The brand wordmark as Skia geometry — a parsed letter path + six tintable rects, no raster asset.
2. A pure, unit-tested `logoState(t)` — seamless by construction, with an ember rest at both ends.
3. A bespoke SkSL `RuntimeEffect` for the specular sweep + prism dispersion, with a gradient fallback.
4. Hue-preserving per-bar shine (own-colour additive) + a spreading bloom halo for the flash.
5. The thinnest engine seam of the five: just `GameLoop` and the post-FX finish.

</Steps>

No simulation, a pure timeline, and one hand-written shader — the light showcase that proves the same
seam carrying the heavy pieces carries this too.

<Aside type="note">
See it live in the [hero](/) (pick "Logo") and press the backtick key to open the dev panel. Back to
the [Foundations](/guides/foundations) overview, the other showcases, or the
[package catalog](/reference/packages).
</Aside>
