Every colour, size, radius and font in Kairon is a CSS variable, at the top of src/styles/template.css in three groups. Change a value once and every page follows.
01
Primitives
The raw palette (Cream, Ink, Ember, Gold, Sage, Dark and Alpha lines) plus the font families and weights. Theme tokens point to these, so retinting a primitive updates every token that uses it.
02
Theme
The semantic colours that classes use: Background, Text, Border and Accent. Point a token at another primitive to restyle the site without touching a single class.
03
Layout
Font sizes, spacing, radius, gutter, max width and nav height. It has Tablet, Mobile and Portrait modes that switch automatically at each breakpoint, so one value controls the whole responsive scale.
04
Type styles
Headings use the All H1–H6 tag styles, which read the Font Size variables. Add heading-style-h1 to heading-style-h3 to change how a heading looks without changing its level. Keep one H1 per page and add text-style-serif to one or two accent words.
VariableCollectionUsed for
Background/PrimaryThemePage background
Background/CardThemeCards, inputs, light buttons
Text/PrimaryThemeHeadings and body text
Text/SecondaryThemeLeads and secondary text
Border/PrimaryThemeRails, dividers, card borders
Accent/PrimaryThemeButtons, serif accents, dots
Accent/TextThemeSmall orange text (AA contrast)
Dark/900PrimitivesDark windows and the CTA card
02
Components & layout
Global pieces are Components in the Global group. Edit a component once and every page updates. Every page uses the same skeleton:
Body
Global UI· component
Navbar· component
page-wrapper
Rails· component
page-inner
main.main-wrapper→ your sections
Footer· component
01
Navbar
Logo, links and the Get started button. The menu button opens the full-screen menu with a GSAP click interaction (block G3, see 03).
02
Global UI
A fixed blur at the bottom of the viewport that softens content as it scrolls out. Delete the instance on a page to turn it off there.
03
Rails
The two vertical lines that frame the content. The width comes from Site/Max Width and the distance to the screen edge from Site/Rail Inset.
04
Footer
Links, the newsletter form, the large wordmark and the Powered by Astro link.
05
Sections
Each section starts with a divider block, the top line with plus marks where it meets the rails, then padding-global › container-large › padding-section-large. Edge-to-edge line grids use Site/Gutter Negative as side margins.
03
GSAP animations
All motion runs from one GSAP script (public/assets/js/kairon.js). The script is split into 36 numbered blocks, G1 to G36, and each block only runs on pages where its elements exist. Elements are found by a data-animate attribute, set in the section components (src/components/); a few blocks use a class or a helper attribute instead, listed in the element map below. Scrolling is native and sticky elements use CSS position: sticky.
Where the code livespublic/assets/js/kairon.js
01
Head code
GSAP, ScrollTrigger, SplitText and ScrambleText come from the gsap package on npm and load at the end of each page (src/components/CustomCode.astro). Nothing loads from a CDN. The head script only hides the page until the template script has set every start state, so nothing flashes; GSAP shows the page after 3 seconds at the latest, even if the footer script fails.
02
Footer code
Only the Kairon template script, with no script tags that load libraries. It registers the GSAP plugins (if one fails to load, the page simply shows its final, static state), then holds the settings object K, blocks G1 to G36 and init(), which starts once the fonts have loaded.
03
Preview
Run npm run dev to see the motion; add ?static=1 to any URL to see the final states.
Key variablesconst K
The settings object K sits at the top of the footer script. Change a value there to tune motion across the whole site.
PropertyDefaultWhat it does
ease'expo.out'Main easing for entrances: hero intro, reveals, split headings, counters, menu opening.
easeUI'power3.out'Easing for UI feedback: navbar, menu lines, accordion, tabs, toggles, hovers.
speed1Global duration multiplier for the main tweens. 0.8 = faster, 1.2 = slower.
navHidetrueHides the navbar when scrolling down and shows it when scrolling up (G2). false = navbar always visible.
marqueeSpeed40Seconds for one logo marquee loop (G7). Higher = slower.
testimonialSpeed80Seconds for one testimonial row loop (G7). Reverse rows run at ×1.12.
stackScale0.95How far a stacked card shrinks as the next one arrives (G9). 1 = no shrink.
demoLooptrueReplays the agent-run demo 6 seconds after it ends (G10). false = plays once.
parallax18Pixels of pointer parallax on hero visuals and step-card scenes (G19). 0 = off.
staticfalsetrue when the URL contains ?static=1: every motion block is skipped and final states show. Detected automatically from the URL.
Reduced motion: when a visitor's system is set to prefers-reduced-motion: reduce, or the URL ends in ?static=1 (handy for screenshots and reviews), the script skips every motion block, shows counters at their final value and reveals the page at once. Functional blocks still work, without animation: menu (G3), approval card (G13), pricing toggle (G14), FAQ (G15), tabs (G16), anchors (G20), keyboard support (G21) and article TOC (G32).
Element mapG1 – G36
One row per block, in script order: what it does, the data-animate value or selector it targets, and how to switch it off. Blocks marked Home 02 or Home 03 only find elements on those pages.
BlockEffectdata-animate / selectorTo disable
G1
Page ready
Reveals the page the head script hid, once fonts are loaded and every start state is set. If the footer script ever fails, the head script still shows the page after 3 seconds.
html (set by the head script)Keep it. To drop the fade-in, delete the head script; the page then shows at once.
G2
Navbar hide
Slides the navbar up when scrolling down (after 480px) and back when scrolling up. Paused while the menu is open.
.navbar_component (class)Set navHide: false in K; the navbar stays visible.
G3
Menu
GSAP click interaction (not IX3): the round button opens the full-width menu panel, the three bars morph into an X and the links stagger in. Escape or a menu link closes it.
menu-toggle, menuRemove menu-toggle or menu and the menu no longer opens. Edit timings in block G3 of the script.
G4
Hero intro
Split headings rise word by word out of a blur; hero items fade up; hero visuals settle from 94% scale.
split-heading, hero-in, hero-visualRemove the attribute; the element shows at once.
G5
Scroll reveals
Fades elements up 28px once as they enter the viewport, in batches.
revealRemove it; the element is always visible.
G6
Text scrub
Statement words light up from 14% to full opacity as you scroll through.
scrub-wordsRemove it; the text shows at full opacity.
G7
Marquees
Clones the first track once and loops the row forever; hover pauses it. Keep one track only.
Home 02 testimonial wall: each column duplicates its cards and scrolls up forever; hover pauses.
marquee-up + data-duration, data-directionRemove it; the column stays still.
G27
Constellation
Home 03 hero: a task types into the prompt, the core pulses and each tool it calls lights up with its call · result label, then the status shows Done.
constellation + data-node, data-wire, data-pulse, core-pulse, prompt-text, prompt-status, status-dot, status-text, connectorRemove constellation; the scene stays static.
G28
Scroll story
Home 03: the sticky step text, progress bars and panel rows follow the panel in view.
story + data-step, story-rows, verify-ringRemove story; the first step stays visible.
G29
Quote slider
Home 03: prev / next, a 01 / 03 counter, words blur in, auto-advance every 7 seconds.
quotes + data-slide, quote-count, quote-words, quote-prev, quote-nextRemove quotes; the first quote shows.
G30
Prompt caret
Any caret blinks like a terminal cursor.
caretRemove it; the caret stays solid.
G31
Row hovers
Role and list rows tint their title and nudge their arrow on hover (mouse only).
role-hoverRemove it; rows keep CSS hover only.
G32
Article TOC
Builds the table of contents from the article's H2s and highlights the one in view; copy-link and email share.
toc, copy-link, share-emailRemove toc and hide the TOC block.
G33
Overview cards
On the Overview page, hovering a homepage card scrolls its screenshot from top to bottom, lifts the thumbnail and turns the arrow circle ember (mouse only).
data-animate="thumb-scroll"Remove the attribute or delete G33_thumbScroll() in init()
G34
Blog filter
On the Blog page, the category pills filter the post grid by each card's category chip; All shows every post.
data-animate="filter" on the pills and data-animate="filter-item" on the collection itemRemove the attributes or delete G34_filter() in init()
G35
Logo hover
Mouse only: hovering the navbar or footer logo grows the ember dot with a soft spring, tightens the ring and turns the mark.
.nav_logo, .footer_logoDelete G35_logo() in init()
G36
Bottom blur
The fixed blur along the bottom of the screen. In Chrome and Edge each of its five layers uses an SVG filter (a soft blur with a slight colour split); other browsers keep the plain blur set on the layer classes.
.bottom-blur_layer in the Global UI component, filters #kb-0…#kb-4Delete G36_bottomBlur() in init() for the plain blur only
Menu open and closeGSAP · G3
01
Navbar menu button
The menu is a GSAP click interaction in block G3 of the script. Clicking the round button (menu-toggle) opens the full-width panel (menu) with a clip reveal, morphs the three bars into an X and staggers the links in. A second click, the Escape key or any menu link closes it, and the navbar stays put while it is open. Change timings or easing in block G3 of the footer script.
04
CMS collections
Two collections power the dynamic pages. Every list on the site reads one of them; each entry is a Markdown file in src/content/.
Blog Posts/blog/[slug]
NamePlain text
SlugSlug
SummaryPlain text
CategoryOption
Cover imageImage
Published dateDate
Read timePlain text
Author namePlain text
Author initialsPlain text
Author rolePlain text
BodyRich text
FeaturedSwitch
Category options: Product, Engineering, Guides and Company. Turn on Featured for the one post shown large at the top of the blog.
Jobs/careers/[slug]
NamePlain text
SlugSlug
TeamOption
LocationPlain text
Employment typeOption
Salary rangePlain text
SummaryPlain text
DescriptionRich text
Team options: Engineering, Design, Go-to-market and Operations. Employment type: Full-time, Part-time or Contract.
01
Add an item
Open the CMS panel, pick the collection and click New item. Fill every field so cards keep the same height in lists.
02
Change the order
Blog lists sort by Published date, newest first. Turn on Featured to pin a post at the top.
03
Keep images light
Upload covers as 1600×1000 WebP under 150 KB. Card links use Current Blog Post or Current Job, never a fixed page.
05
Icons & SVG
All icons are Phosphor duotone, placed inline as SVG. They use currentColor, so they take the text colour of their parent.
01
Find a replacement
Search phosphoricons.com, choose the Duotone weight and copy the SVG.
02
Swap it in
Paste the new SVG into a Code Embed where the old icon was. Keep viewBox="0 0 256 256" and fill="currentColor", and give it the same class as the icon it replaces.
03
Size it with the class
Icon classes set the width and height. Keep icons at 18, 22 or 28px so they match the rest of the template.
06
Accent colour
The ember accent comes from two Theme variables: one for fills and one for small text. Change both together.
Accent/Primary #D3420D
Accent/Text #B93A0B
Ember/300 #FF8A3D
01
Set the fill colour
Point Accent/Primary at a new primitive, or edit Ember/500. It drives primary buttons, serif accents, dots and active states.
02
Set a darker text shade
Use a slightly darker shade for Accent/Text (Ember/600). It must reach 4.5:1 contrast on Background/Primary for small text.
03
Update the glows
Soft glows behind heroes, the Pro plan and the CTA card use the same hue at low opacity. Search the Style Manager for classes ending in _glow and replace the gradient colour with your new hue.
07
Fonts
Kairon uses Instrument Sans, Newsreader italic and JetBrains Mono, self-hosted with the theme (src/styles/fonts.ts and public/assets/fonts).
01
Add your font
Add a Fontsource package or your own font files, then change the font variables in src/styles/template.css.
02
Update the font variables
Change Font/Primary and Font/Display in Primitives. The tag styles and every heading read these, so the whole site updates.
03
Swap the accent and mono fonts
Change Font/Serif and Font/Mono. Keep the serif light and italic so accent words still stand apart.
Need help? Check the style guide for every style in use, or reach us through the support link on the theme page.