31 components, rendered live from the package. Each one appears twice: once inside data-theme="light" and once inside data-theme="dark".
Actions
Button
Actions
The G8N•AI button in three weights: primary (Laser), quiet (Scanner) and ghost (an Edge outline).
Light
Tab to a button to see the double focus ring; press it to see the drop and the inset.
Dark
Tab to a button to see the double focus ring; press it to see the drop and the inset.
<Button>Start building</Button>
<Button variant="quiet">Read the notes</Button>
<Button variant="ghost">Skip for now</Button>
<Button loading>Starting</Button>
<Button as="a" href="https://tally.so/r/J9aR5r" size="lg">Request a Call</Button>
One primary per view. Laser marks the one thing to do next. A second action is quiet, a third is ghost (rule 5).
States are CSS. Hover adds a faint light edge; pressed drops 1px with a dark inset (accent-press, quiet-press); focus is the double ring, 2px accent inside 2px partner, with a 2px gap in --focus-gap (default surface-0; set it to the card color when a button sits on a card); disabled is surface-3 with text-3, no red (rule 14).
Loading keeps the label, adds the Sweep B head and sets aria-busy. Do not swap the label for a spinner.
Sentence case labels, verbs first. On g8n.ai the call button reads Request a Call and opens the inquiry form; it never implies a confirmed booking.
The consumer provides the label, an onClick or href, and type="submit" inside forms.
Badge
Actions
A small label in 11px bold capitals: New, Live, Draft, or a status (Failed, Sent, Note, Check) with an icon and a word.
new is accent-fill with accent-ink; live is accent-quiet with quiet-ink. Both are brand labels, not status.
error (an error border), success (done is the same badge), info and warning always carry an icon and a word; the color never carries the meaning alone (rule 10). The three status hues use success, info and warning with their -text and -tint, and only for status.
Never smaller than 11px (fs-badge), never lighter than bold.
Menu
Actions
An actions menu: a ghost trigger with a chevron opens a list with an icon, a label and an optional Courier shortcut per item.
Use it for headers, footers of documents and title slides. In tight spots use the wordmark or the mark alone, never a squeezed lockup.
Keep one node diameter of clear space around it.
Mark
Brand
The G8N•AI mark: three open nodes on a Laser line that climbs left to right to one solid Ember node.
Light
Light: Ink rings and an Ink outline on the Ember node, no glow. Second row: one color in Ink, and the dark roundel.
Dark
Dark: Frost rings, a soft Scanner glow, a faint Ember halo. Second row: one color in Frost, and the light roundel.
<Mark size={48} /> // follows the theme
<Mark form="roundel" size={64} /> // the badge
<Mark variant="mono-ink" size={32} /> // one color, for light grounds
The shape is the 1.1 System mark, unchanged. Never stretch, rotate, recolor the line, or add a second Ember node.
On dark (auto or dark): Frost rings, Void node fills, a soft Scanner glow under the line, a faint Ember halo. On light: Ink rings, Sheet fills, an Ink outline on the Ember node, no glow (Ember alone is 2.9:1 on Paper).
One-color files: mono-ink for stamps, receipts and light grounds; mono-frost reversed out of photos and dark grounds.
Clear space is one node diameter. Minimum: glyph 24px bare (16px only as the tab icon on its tile), roundel 24px.
Screen readers hear "Generation AI". The uploaded files in assets/mark/ are the same drawing for places React cannot reach.
Wordmark
Brand
The logotype G8N•AI: Verdana bold, tracked ls-wordmark, the letters in text-1, the 8 and the dot in Laser.
G8N•AI is the written mark everywhere it is seen; "Generation AI" is the spoken name, page titles and alt text. The component sets role="img" and aria-label="Generation AI".
No spark, no outline, no other colors. For the mark and wordmark together use <Logo>.
Content
AccentHeadline
Content
A Georgia bold headline in text-1 with one emphasized phrase in italic Laser, underlined by a straight rule or one smooth curve.
Light
The barrier to building has collapsed.
Every follower you have belongs to the platform. Not to you.
Dark
The barrier to building has collapsed.
Every follower you have belongs to the platform. Not to you.
<AccentHeadline accent="collapsed.">The barrier to building has</AccentHeadline>
<AccentHeadline as="h3" size="28px" underline="curve" accent="Not to you.">Every follower you have belongs to the platform.</AccentHeadline>
Laser text is display only: 24px or larger, or 18.7px bold. Below that, emphasize with italic in text-1.
One phrase per headline. The italic carries the emphasis, so the sentence reads without the color (red-blind viewers).
In email and in 100px thumbnails, drop the red: italic only.
Eyebrow
Content
A section kicker: 12px bold capitals tracked at ls-eyebrow, in text-3, after a 28px Laser tick.
Light
Signal · Issue 04
The AI Workflow Audit
No tick
Dark
Signal · Issue 04
The AI Workflow Audit
No tick
<Eyebrow>Signal · Issue 04</Eyebrow>
<Eyebrow tone="ink">The AI Workflow Audit</Eyebrow>
The red is the tick, never the words: small Laser text fails on dark (rule 1). The same pattern is used on light so the component never changes between modes.
QuoteCard
Content
The social quote card: a Void tile with the 1px tile-edge, a Courier series label, a Frost Georgia statement and the wordmark.
Light
SIGNAL / 04
Every follower you have belongs to the platform. Not to you.
G8N•AI
The tile is Void in both themes, so it reads in dark and light feeds.
Dark
SIGNAL / 04
Every follower you have belongs to the platform. Not to you.
G8N•AI
The tile is Void in both themes, so it reads in dark and light feeds.
<QuoteCard label="SIGNAL / 04" accent="Not to you.">Every follower you have belongs to the platform.</QuoteCard>
Always the dark tile: the feed test showed it is the only treatment that holds in both dark and light feeds. The edge keeps it visible in a dark feed.
At most one italic Laser phrase, and only where it shows at 24px or more. Never in 100px thumbnails. Body text is Mist; lit figures are Amber.
Type scales with the card's width; render it at the export size (1080 × 1350) when making the image.
1.x variants (ink, board, paper) all render the dark tile now.
Stat
Content
A data point: a big Georgia figure in text-1, its unit in lit-text, and a short label in text-2.
Light
19%slower
They felt faster with AI. Measured, they were slower.
Dark
19%slower
They felt faster with AI. Measured, they were slower.
<Stat value="19%" unit="slower" label="They felt faster with AI. Measured, they were slower." sublabel="Source: [study]" />
Numbers are evidence, never decoration. Cite the study in sublabel when the figure comes from one; never invent a figure.
The unit is a lit word: Burnt on light, Amber on dark (rule 9). When a figure must pop on light, set Ink on an Ember highlight instead of Ember text (rule 17).
Data
Avatar
Data
A person or account: their photo, otherwise initials in quiet-ink on a Scanner disc, otherwise the brand roundel.
Label sample rows as samples; never show invented client data as real.
Feedback
Alert
Feedback
An inline status message: an icon, a status word (Note, Done, Check, Error), a title and a line of detail, on surface-1 with an edge border.
Light
Note: Your Map is on its way
It arrives within five business days of the session.
Done: Inquiry sent
Ahad replies by email.
Check: One field is blank
The intake is easier with a real example.
Error: The form did not send
Check your connection and send it again.
Dark
Note: Your Map is on its way
It arrives within five business days of the session.
Done: Inquiry sent
Ahad replies by email.
Check: One field is blank
The intake is easier with a real example.
Error: The form did not send
Check your connection and send it again.
<Alert title="Your Map is on its way">It arrives within five business days of the session.</Alert>
<Alert variant="danger" title="The form did not send">Check your connection and send it again.</Alert>
Only errors are red (rule 18).danger gets a 2px error border and the word Error. Success, info and warning take their status hue (success, info, warning) on the border, the icon and the word, and are still told apart by that icon and word.
info and success use role="status"; warning and danger use role="alert".
EmptyState
Feedback
What a list or page shows before it has content: the mark, a short Georgia title, one sentence and one action, in a dashed edge box.
Light
No workflows mapped yet.
Add the first recurring task and the Map starts to fill in.
Dark
No workflows mapped yet.
Add the first recurring task and the Map starts to fill in.
<EmptyState title="No workflows mapped yet." action={<Button size="sm">Add a workflow</Button>}>
Add the first recurring task and the Map starts to fill in.
</EmptyState>
State the situation and the next step. No apology, no illustration of sadness, no emoji.
Skeleton
Feedback
A static placeholder card while content loads, with a Courier line that says in words what is loading.
Light
Loading your Map…
Dark
Loading your Map…
<Skeleton label="Loading your Map…" />
It does not shimmer. If the wait is long, pair it with a Sweep. role="status" announces the words.
Spinner
Feedback
A small busy indicator: a Laser arc with an Ember tip on a line track, for tight spots where a Sweep does not fit.
Light
Loading…Loading…Loading…Loading your Map…
Dark
Loading…Loading…Loading…Loading your Map…
<Spinner label="Loading your Map…" />
role="status" with a visually hidden label. Under reduced motion it stops turning.
Sweep
Feedback
The brand's loading and progress light: a head of light that sweeps back and forth along a track.
Light
Sweep B · loading your notes1.6s
Frost only · refreshing the map1.6s
Uploading 3 of 560%
Sweep A · decoration2s
On light the track is a dark slot: light never glows on paper.
Dark
Sweep B · loading your notes1.6s
Frost only · refreshing the map1.6s
Uploading 3 of 560%
Sweep A · decoration2s
On dark the track is Deck.
<Sweep label="Loading your notes" />
<Sweep variant="frost" label="Refreshing the map" />
<Sweep value={60} label="Uploading 3 of 5" />
<Sweep variant="ambient" height={6} />
Sweep by context (rule 11). Sweep B (signal), Ember with a Frost core, is the default for loading, progress and the signal, at dur-sweep (1.6s). The frost head is for loading on a screen where Ember already marks a result, so two lights do not compete. Sweep A (ambient) is decoration at dur-sweep-ambient (2s), under display type only, and hidden from assistive tech. Never a sweep beside body text.
On light the track is a dark slot (well with a rail edge): light never glows on paper. On dark it is surface-1 with a line edge.
Determinate progress fills from Scanner to Laser with an Ember head and a Frost tip at the leading edge (rule 15).
Reduced motion: the head holds still in the middle. Always say in words what is happening next to it (rule 16).
Email gets a GIF whose first frame has the light in the middle; print gets an Ember point with a white ink core.
Toast
Feedback
A short confirmation that floats above the page: an icon, a status word (Note, Done, Check, Error), one line, an optional action and a close button, on inverse-surface.
Only errors are red (rule 18): the 2px error border. The status word carries the meaning for everyone.
It does not time out or position itself: put it in a .g8n-toast-region with aria-live="polite" that is on the page from load, so new toasts are announced, and remove it on dismiss. Keep anything important on the page too.
A request is not a booking: say "Inquiry sent", never "Call booked".
Forms
Checkbox
Forms
A native checkbox drawn as a 20px box: a 2px edge border, filled accent with an accent-ink tick when checked.
Light
Error: please confirm
Dark
Error: please confirm
<Checkbox label="Email me the Map when it is ready" />
<Checkbox label="I have read the terms" error="please confirm" />
Focus is the double ring. Errors print an icon and the word Error. Disabled is surface-3 with a line border and text-3 label.
Input
Forms
A text field in a box: 44px tall, a 2px edge border on surface-1, radius-md.
Light
Ahad replies to this address.
Error: enter a full email address
Dark
Ahad replies to this address.
Error: enter a full email address
<Input label="Email" type="email" hint="Ahad replies to this address." />
<Input label="Email" defaultValue="ahad@g8n" error="enter a full email address" />
Focus turns the border accent and adds a 2px partner ring. Invalid fields get the error border.
Errors carry an icon and the word Error (rule 6); error renders both and wires aria-describedby. The red border alone never carries the message.
The label is wired with htmlFor; an id is generated when none is passed. Placeholders are text-3 and never replace the label.
On the inquiry form, keep the live line under the button: submitting does not commit anyone to paid work and does not subscribe them to a newsletter.
RadioGroup
Forms
One choice from a short list: a fieldset with a legend and 20px radios, edge rings, a Laser ring and dot on the chosen one.
Light
Dark
<RadioGroup name="start" legend="How would you like to start?" defaultValue="fit"
options={[{ value: "fit", label: "Free fit conversation" }, { value: "audit", label: "The $297 audit" }]} />
Native radios give the full keyboard contract. Errors print an icon and the word Error.
Where the free conversation and the paid audit both appear, present them as alternatives; never claim the paid audit performs better.
Select
Forms
A native <select> in the same box as Input, with a text-1 chevron.
Light
Error: choose one option
Dark
Error: choose one option
<Select label="What kind of help?" placeholder="Choose one" options={[{ value: "find", label: "Find what to automate first" }]} />
Same focus, error and disabled rules as Input.
Switch
Forms
An instant on/off setting: a track that fills Laser when on, a sliding thumb, and the word On or Off in Courier.
Light
Dark
<Switch label="Weekly digest" defaultChecked />
Use it only for settings that apply immediately; use a Checkbox inside forms that are submitted.
Textarea
Forms
The multiline field, in the same box as Input, at least 96px tall.
Light
A real example is more useful than a perfect explanation.
Dark
A real example is more useful than a perfect explanation.
<Textarea label="The problem" hint="A real example is more useful than a perfect explanation." />
Same focus, error and disabled rules as Input.
Layout
Card
Layout
A container: raised for cards and lists, flat for grouping without weight, well for anything that gives off light on a light page.
raised: surface-1, a line hairline and shadow-md, radius-lg.
flat: transparent with an edge outline.
well: well (Void) and data-theme="dark" on the card, so everything inside uses the dark tokens. This is where the mark at hero size, the trace and the sweep go on a light page (rule 8).
glow adds shadow-glow, the soft Scanner glow; it is empty in the light theme because light never glows on paper.
Cards set --focus-gap to their own surface so focus rings inside them stay clean.
Navigation
Accordion
Navigation
A stack of questions and answers on native <details>, separated by line hairlines, with a chevron that turns down when open.
Light
Do I need to prepare anything?
Just the intake, honestly answered. Rough and honest beats tidy and polished.
Can't I just do this myself with ChatGPT?
[Answer · Alfred drafts, Ahad approves]
What if you don't find anything?
[Answer · Alfred drafts, Ahad approves]
Dark
Do I need to prepare anything?
Just the intake, honestly answered. Rough and honest beats tidy and polished.
Can't I just do this myself with ChatGPT?
[Answer · Alfred drafts, Ahad approves]
What if you don't find anything?
[Answer · Alfred drafts, Ahad approves]
<Accordion items={[{ id: "prep", summary: "Do I need to prepare anything?", content: "Just the intake, honestly answered." }]} />
Questions are text-1 bold; answers text-2 at 13px. The summary gets the double focus ring.
Use it for FAQs. Answers that need new wording are drafted by Alfred and approved by Ahad; mark them until then.
SiteFooter
Navigation
The footer for g8n.ai pages: the wordmark and a note, then link columns with Courier capital titles.
The call to action is a quiet button: the page's one primary button lives in the hero (rule 5). On g8n.ai it reads "Request a Call" and opens the inquiry form; never a calendar, never "confirmed".
The current page is text-1 bold with a 2px Laser underline and aria-current="page".
Below 768px the links fold into a Menu button that opens a panel. Give the page's main element the id the skip link targets.
Tabs
Navigation
Tabs: text-3 labels on a line rule; the chosen tab is text-1 bold over a 3px Laser bar.
Light
A 60-minute working session and a Map you keep.
The ranked list, the effort and impact matrix, and a 30-day plan.
Sixty minutes on your real workflows.
Answers to the common questions.
Dark
A 60-minute working session and a Map you keep.
The ranked list, the effort and impact matrix, and a 30-day plan.
Arrow keys move focus, Enter and Space choose (manual activation, roving tabindex).
Overlays
Dialog
Overlays
A modal on the native <dialog>: a surface-1 panel with a Georgia title, a short description and an action row, over the scrim.
Light
Dark
<Dialog open={open} onClose={() => setOpen(false)} title="Send this inquiry?"
description="Ahad will review it and reply by email; submitting does not commit you to paid work. You will not be subscribed to a newsletter."
footer={<><Button variant="ghost" size="sm">Keep editing</Button><Button size="sm">Send inquiry</Button></>} />
The browser owns the focus trap, Esc, the top layer and returning focus. Keep it short: one question, one primary action.
Tooltip
Overlays
A short supplemental label on hover and focus, on inverse-surface with an arrow.
Light
Delivered within five business days
Shown open here; it opens on hover and on focus, and Esc closes it.
Dark
Delivered within five business days
Shown open here; it opens on hover and on focus, and Esc closes it.
<Tooltip content="Delivered within five business days"><button>When does the Map arrive?</button></Tooltip>
Dismissible with Esc, hoverable and persistent (WCAG 1.4.13). Never put the only copy of important information in a tooltip.