Every asset @helikona/brand ships, on one page, for visual review — no consuming app required. Rendered from the real sources: these are the shipped stylesheets and the actual Icon component, not a copy of either.
Primary brand. Gravity (deep) → approachability (light).
--deep-jungle#0B3D2E--jungle-mid#1A6B47--leaf-light#5DC48A--leaf-pale#E8F2ECAccent & emphasis. Use sparingly.
--iron-oxide#6B2A14--rust-mid#B84C2A--rust-light#D4896A--rust-pale#F5EDE7Warning / pending states.
--amber-mid#9E5E00Neutrals with character, in place of flat greys.
--temple-stone#5A5C50--stone-pale#EAEAE2Page and panel grounds, plus the two tappable washes.
--off-white#F2F3EE--dark#080D09--page-bg#F2F3EE--surface#ffffff--surface-hoverrgba(26, 107, 71, 0.06)--surface-activergba(26, 107, 71, 0.18)--text#181A16--text-muted#4A4D44--border#E2E4DASit above the palette — these are the ones that flip in dark mode.
--heading#0B3D2E--link#1A6B47--action-bg#F5EDE7--action-text#6B2A14--leaf-strong#1A6B47--focus-ring#1A6B47--press-fill#1A6B47--press-text#F2F3EE--font-display'DM Sans', -apple-system, BlinkMacSystemFont, sans-serif
Heliconia DM Sans 700 / 48px
The brand, set large DM Sans 700 / 32px
A section heading DM Sans 600 / 24px
A card title DM Sans 600 / 17px
--font-body'Inter', -apple-system, BlinkMacSystemFont, sans-serif
The heliconia grows toward the light it can reach. Inter 400
The heliconia grows toward the light it can reach. Inter 500
The heliconia grows toward the light it can reach. Inter 600
apple-touch-icon.png
180×180
@helikona/brand/apple-touch-icon
favicon.ico
@helikona/brand/favicon
helikona_lockup-jungle.png
1082×467
@helikona/brand/lockup-jungle-png
helikona_lockup-jungle.svg
144×62
@helikona/brand/lockup-jungle
helikona_lockup-jungle@2x.png
2164×934
@helikona/brand/lockup-jungle-png-2x
helikona_lockup.png
871×256 · shown on a dark ground
@helikona/brand/lockup-png
helikona_lockup.svg
116×34 · shown on a dark ground
@helikona/brand/lockup
helikona_lockup@2x.png
1742×512 · shown on a dark ground
@helikona/brand/lockup-png-2x
helikona_logomark.png
120×120
@helikona/brand/logomark-png
helikona_logomark.svg
2000×2000
@helikona/brand/logomark
helikona_logomark@2x.png
240×240
not exported
icon-512.png
512×512
@helikona/brand/icon-512
icon-bloom-1024.png
1024×1024
@helikona/brand/icon-bloom-1024
icon-bloom-512.png
512×512
@helikona/brand/icon-bloom-512
icon-bloom-maskable-512.png
512×512
@helikona/brand/icon-bloom-maskable-512
icon-bloom-maskable.svg
1024×1024
@helikona/brand/icon-bloom-maskable-svg
icon-bloom-touch.png
180×180
@helikona/brand/icon-bloom-touch
icon-bloom.svg
1024×1024
@helikona/brand/icon-bloom-svg
icon-maskable-512.png
512×512
@helikona/brand/icon-maskable-512
icon-square.svg
1500×1500
@helikona/brand/icon-square-svg
icon.svg
2000×2000
@helikona/brand/icon-svg

photography/helikona-hero-cutout.pngnot exported
photography/woman-organic.pngnot exported24×24, fill: none, stroked in currentColor at 2 — so one component serves a leaf-green icon button and a muted table cell alike. Shown here at 24px.
alert-trianglearrow-leftarrow-rightarrow-upbanbellbook-openbriefcasebuildingcalendarcheckcheck-circlechevron-downchevron-leftchevron-rightchevron-upclockcompasscopycredit-carddollar-signdotexternal-linkeyefile-plusfile-textflaggridhelp-circlehomeinboxkeylinklistlog-inlog-outmailmessage-circlemessage-squaremicpaperclippencilperson-plusphoneplayplugplusprinterreplysendsettingsshieldstartrending-upuploaduseruser-plususersxThe platforms' own solid logos, in their own colours rather than currentColor. Where a UI names a channel, the logo is the thing you scan for — a generic speech bubble does not read as one.
linkedinmessengerslackwhatsappThe same three glyphs, drawn inside three different colours. Nothing is passed to the component — it takes the colour of whatever it sits in.
var(--leaf-light)var(--text-muted)var(--action-text)
A single size number, defaulting to 14.
141620243248
The shared vocabulary every agent rail draws on — @helikona/brand/chat.css for the layout and @helikona/brand/chat-markdown's <ChatMarkdown> for rendering a reply. This section doubles as the regression check for the two things ChatMarkdown exists to fix: a GFM table rendering as an actual table, and a reply mid-stream surviving an unterminated ** as literal text rather than breaking.
The user's message is a bubble; the assistant's is bare text — the reply is the page, not a log entry. The flag affordance sits at the assistant turn's left edge, at rest (opacity: .6) — hover it to see it sharpen.
Forms — 1 total
| Field | Type |
|---|---|
| Name | text |
The exact failure mode a streamed reply hits before its closing ** arrives. This must read as literal asterisks, never throw.
Checking the Landing Pages config… **almost do
Only a clean success may read in the past tense — .is-failed and .is-declined exist so a failed or declined call never looks like it happened.
.hk-chat-composer, .hk-chat-icon-btn and .hk-chat-send — the input row every rail assembles the same way.
The brand's answer to a generic spinner. Two nested rotations make the sway read as wind rather than a rocking icon — the whole plant pivots at the base of the stem, and the upper bracts pivot on the same period but phase-shifted, so the tip lags the stem and catches up. Purely decorative (aria-hidden); pair it with your own visible status text.
1.5em2em3em5emIn context, at the size it's usually drawn:
Working…
It respects prefers-reduced-motion on its own — under that setting the sway is replaced by a slow breathe. Toggle it in your OS to check.
Email clients mostly strip custom properties, so the templates carry literal hex. These are the same brand values, flattened — and light-mode only: don't attempt dark-mode switching in email.
deepJungle#0B3D2EjungleMid#1A6B47leafLight#5DC48AleafPale#E8F2ECoffWhite#F2F3EEdark#080D09text#181A16textMuted#4A4D44border#E2E4DAironOxide#6B2A14rustMid#B84C2ArustPale#F5EDE7templeStone#5A5C50stonePale#EAEAE2Table-based, inline styles only, for pasting straight into Gmail's signature settings. Rendered below in an iframe on a white ground, which is what a mail client will give them.
email/signature.htmlfullemail/signature-reply.htmlminimal reply sign-offMeasured on this build from the token values themselves, not asserted. Ratios are WCAG 2.2 relative luminance. The threshold applied depends on what the pair is for: 4.5:1 under 1.4.3 Contrast (Minimum) for body text, 3:1 under 1.4.11 Non-text Contrast for borders, glyphs and other interface parts. AAA marks a text pair clearing 1.4.6's 7:1.
Only pairings the shipped CSS actually draws are listed. A full cross-product would be noise, and would imply the package endorses combinations it never puts on screen.
| Where | Tokens | Ratio | WCAG 2.2 |
|---|---|---|---|
| Body text on the page | --text on --page-bg |
15.72:1 | AAA |
| Body text on a card or panel | --text on --surface |
17.53:1 | AAA |
| Muted text on the page | --text-muted on --page-bg |
7.73:1 | AAA |
| Muted text on a card — .btn-ghost's label | --text-muted on --surface |
8.62:1 | AAA |
| Headings on the page | --heading on --page-bg |
10.94:1 | AAA |
| Text links, .link | --link on --page-bg |
5.82:1 | AA (4.5:1) |
| Text links on a card | --link on --surface |
6.49:1 | AA (4.5:1) |
| .btn-primary — label on its fill | --deep-jungle on --leaf-light |
5.65:1 | AA (4.5:1) |
| .btn-primary:active — label on the press fill | --press-text on --press-fill |
5.82:1 | AA (4.5:1) |
| .btn-danger-outline label, .btn-quiet-danger | --action-text on --surface |
10.68:1 | AAA |
| .btn-danger — label on its fill | --surface on --action-text |
10.68:1 | AAA |
| .btn-outline label and border | --leaf-strong on --surface |
6.49:1 | AA (4.5:1) |
| .icon-outline-btn glyph and border | --leaf-strong on --page-bg |
5.82:1 | AA (3:1) |
| .btn-outline label on its own hover wash | --leaf-strong on --leaf-pale |
5.67:1 | AA (4.5:1) |
| Keyboard focus ring against the page | --focus-ring on --page-bg |
5.82:1 | AA (3:1) |
| Keyboard focus ring against a card | --focus-ring on --surface |
6.49:1 | AA (3:1) |
| .btn-secondary's border against its ground | --border on --surface |
1.28:1 | fails 3:1 |
| Warning / pending text | --amber-mid on --surface |
5.18:1 | AA (4.5:1) |
| Eyebrow labels and muted chrome | --temple-stone on --page-bg |
6.11:1 | AA (4.5:1) |
| Where | Tokens | Ratio | WCAG 2.2 |
|---|---|---|---|
| Body text on the page | --text on --page-bg |
14.57:1 | AAA |
| Body text on a card or panel | --text on --surface |
13.27:1 | AAA |
| Muted text on the page | --text-muted on --page-bg |
5.48:1 | AA (4.5:1) |
| Muted text on a card — .btn-ghost's label | --text-muted on --surface |
4.99:1 | AA (4.5:1) |
| Headings on the page | --heading on --page-bg |
8.60:1 | AAA |
| Text links, .link | --link on --page-bg |
8.60:1 | AAA |
| Text links on a card | --link on --surface |
7.83:1 | AAA |
| .btn-primary — label on its fill | --deep-jungle on --leaf-light |
5.65:1 | AA (4.5:1) |
| .btn-primary:active — label on the press fill | --press-text on --press-fill |
5.65:1 | AA (4.5:1) |
| .btn-danger-outline label, .btn-quiet-danger | --action-text on --surface |
6.11:1 | AA (4.5:1) |
| .btn-danger — label on its fill | --surface on --action-text |
6.11:1 | AA (4.5:1) |
| .btn-outline label and border | --leaf-strong on --surface |
7.83:1 | AAA |
| .icon-outline-btn glyph and border | --leaf-strong on --page-bg |
8.60:1 | AA (3:1) |
| .btn-outline label on its own hover wash | --leaf-strong on --leaf-pale |
7.48:1 | AAA |
| Keyboard focus ring against the page | --focus-ring on --page-bg |
8.60:1 | AA (3:1) |
| Keyboard focus ring against a card | --focus-ring on --surface |
7.83:1 | AA (3:1) |
| .btn-secondary's border against its ground | --border on --surface |
1.17:1 | fails 3:1 |
| Warning / pending text | --amber-mid on --surface |
7.83:1 | AAA |
| Eyebrow labels and muted chrome | --temple-stone on --page-bg |
7.15:1 | AAA |
Light: 18 pass, 1 fail — .btn-secondary's border against its ground (1.28:1). Dark: 18 pass, 1 fail — .btn-secondary's border against its ground (1.17:1).
Two defects this analysis found on its first run have since been fixed, and one entry remains listed deliberately:
--leaf-light is a mid-tone green drawn to sit on --deep-jungle, and it does that well, but .btn-outline also used it for its text on --surface, at 2.16:1 against a 4.5:1 requirement — and for .icon-outline-btn's glyph, which missed the looser 3:1 bar too. Both now take --leaf-strong, which is --jungle-mid in light mode and --leaf-light again in dark. The control looks unchanged on a dark ground and merely becomes legible on a light one. The palette token itself was not touched: it is a brand colour, and it was never wrong — it was being asked to do a job it was not drawn for.--off-white on dark mode's --jungle-mid was 2.52:1. The press now runs through --press-fill / --press-text, which flip: in light mode it darkens to jungle green with a pale label as before, and in dark it inverts to --deep-jungle with a --leaf-light label. Both clear 4.5:1, and both still read unmistakably as a press, because each is a change of hue rather than of lightness.--border on --surface. 1.4.11 asks 3:1 of visual information required to identify a control. .btn-secondary carries a full-contrast text label, so its border is not doing that work alone, and a heavier rule would cost the quiet that makes it read as secondary in the first place. It stays in the table because the number is real — but it does mean a border must never be the only thing marking a control.Both fixes were made as semantic tokens rather than as a prefers-color-scheme block inside buttons.css. That is deliberate: Turbopack is documented in two consuming repos as dropping @media blocks from a package's imported CSS, so a theme-dependent rule written there would have failed silently in exactly the apps that need it.
Contrast is the part a page can measure itself. These are the rest of the accessibility decisions baked into the shipped CSS and components — stated plainly, including where they fall short.
.icon-outline-btn / .icon-solid-btn, which grow from 36px to 44px below 640px, and by .btn-tall. Not met by .btn-sm (29px) or .btn-icon (26px) if they are the only way to reach a function. 2.5.8 asks for 24×24 CSS px as a floor, which both clear — but the 44×44 of 2.5.5 (AAA) is the target worth hitting on touch. Reach for .btn-tall on anything a thumb has to find.:hover rule is decorative and gated behind @media (hover: hover), so a touch device never enters a hover state it cannot leave. Nothing here requires a drag, a path gesture, or a multi-point gesture.--amber-mid text or a bare dot glyph conveys its meaning by colour alone. Pair any colour-carried status with a word or a distinct glyph.Icon renders aria-hidden="true", which is correct: the glyph is decorative and the surrounding text is the label. But an icon-only button has no surrounding text, so .btn-icon, .icon-outline-btn and .icon-solid-btn are inaccessible until the caller supplies aria-label. The package cannot enforce this; every example on this page does it.buttons.css takes a 2px --focus-ring outline on :focus-visible, at a 2px offset. :focus-visible rather than :focus, so a mouse press leaves no ring behind — that is the reason rings get deleted from stylesheets, and the fix for it rather than an excuse to ship none. The offset is what lets one colour serve all six looks: drawn on .btn-primary itself the ring would be leaf-on-leaf, but two pixels out it lands on the page. outline rather than box-shadow, so it follows the border radius, takes no part in layout, and survives a forced-colours mode where a shadow is discarded. Tab through this page to see it. Measured against both grounds in the table above.BrandSway honours prefers-reduced-motion on its own, replacing the sway with a slow breathe. Button transitions are 180ms opacity and colour changes, below the threshold at which motion becomes a vestibular concern, and press deliberately drops its transition entirely.px, which browser zoom scales but a user's minimum-font-size setting does not. Buttons carry white-space: nowrap, so a long label in an enlarged font will overflow its container rather than wrap. Worth reviewing on any button whose label is user- or locale-supplied.--surface-hover and --surface-active are translucent greens (6% and 18% light; 7% and 20% dark) composited over whatever sits behind them. They carry no information on their own — they are feedback layered on a control that is already distinguishable — so 1.4.11 does not apply to them directly. They are excluded from the table above rather than silently given a number.This is a static analysis of the design tokens and the shipped CSS. It is not an audit of any application built from them: focus order, heading structure, form labelling, live regions and keyboard traps are all properties of the assembled page, and none of them can be settled here.