EUR 59per month · excl. VAT
Amili Kit
Amili Interface Guidelines
One calm, honest default for every Amili surface: the app, amili.ai and every site built with the Amili Kit. Brands change the accent and a few details; the rest stays, so every Amili-built product is fast, readable and fair by default.
Version 1.0 · 2026-10-21 · Machine-readable: guidelines.md
Preview this page
Principles
Five ideas behind every decision below. When two rules seem to clash, the principle decides.
p-1Calm
The interface serves the content. One accent colour, quiet surfaces, motion only as feedback. Nothing blinks, autoplays or covers what someone is reading.
p-2One voice, an honest one
Every surface looks and sounds like the same product: the same tokens, the same mark, the same word for the same action. No dark patterns: saying no is as easy as saying yes, nothing is pre-ticked, prices and affiliate links are labelled, and nothing is called live before it ships.
p-3One clear next step
Each screen says what it is for, puts the answer first and ends with one next step for the reader. One primary button per view; everything else is quieter.
p-4Fast and solid
Rendered on the server, no framework, no font download, no layout shift. The default state is already in the HTML; scripts only add to it.
p-5For everyone
Targets of at least 44px, a visible focus ring, real labels, contrast checked against WCAG 2.2 AA in every theme, usable at 200% zoom and with reduced motion.
Foundations
Colour
Colours are roles, not values. A page names the role (page, card, text, action) and the Kit decides the value for light, dark and Warm night.
- col-1Use the short role names in page CSS:
--bg,--panel,--panel2,--line,--txt,--dim,--accent,--on-acc,--acc-soft,--err,--input-bg. Never write a colour value in a page; the build refuses a page-local colour token. - col-2The accent means "you can act here" or "you are here": the primary button, links, the current tab, the selected card. Do not use it for decoration or to emphasise plain text.
- col-3Text and icons on an accent fill use
--on-acc. Never put--dimor--txton--accent. - col-4
--erris for errors only, and always comes with words that say what is wrong. Colour alone never carries meaning. - col-5Show state by shade, not by loud blocks: selected is an
--acc-softfill with an accent edge; hover is a small opacity or border change. - col-6Surfaces step:
--bgfor the page,--panelfor cards, menus and fields,--panel2for a band or a quiet fill,--line(1px) to separate. Cards carry no shadow at rest; only things that float (a menu, a sheet) get--shadow. - col-7Check every colour pair in light, dark and Warm night, and with each accent from the picker.
- col-8Amili's own pages use the evergreen accent. Blue, graphite, amber and Warm night are the user's choice in the app, never the default of a page.
Do background:var(--accent); color:var(--on-acc)
Don't background:var(--accent); color:var(--txt)
Do Error: "Enter an email address, like name@company.nl" in --err
Don't A red border with no words
Do A selected card: --acc-soft fill and an accent edge
Don't A selected card painted fully in the accent
Live from the Kit tokens: switch the preview at the top to see each theme
--bg--ak-s0Page background--panel--ak-s1Cards, menus, raised surfaces--panel2--ak-s2Bands, quiet fills--elev--ak-s3The most raised surface--line--ak-lineHairlines and borders (1px)--txt--ak-inkText and icons--dim--ak-dimSecondary text, labels, meta--accent--ak-accActions, links, current item, selection--on-acc--ak-onText and icons on the accent--acc-soft--ak-softSelected and highlighted fills--err--ak-errErrors only, always with words--input-bg--ak-typingText field background--shadow--ak-shadowOnly for things that float
| Pair | Light | Dark | Warm night |
|---|---|---|---|
| Text on page | 17.2:1 | 19.7:1 | 13.0:1 |
| Secondary text on page | 6.0:1 | 8.2:1 | 6.3:1 |
| Secondary text on card | 6.5:1 | 7.5:1 | 5.8:1 |
| Accent (links) on page | 5.6:1 | 10.5:1 | 8.0:1 |
| Text on accent | 6.2:1 | 10.5:1 | 8.0:1 |
| Error text on page | 5.5:1 | 8.7:1 | 7.7:1 |
Typography
Two families with clear jobs and a short scale. The serif speaks; the sans works.
- typ-1
--serifis for headings, the wordmark and Amili's own voice (an answer, a quote).--sansis for everything people read to operate the page: body, labels, buttons, menus, tables. - typ-2Use the scale:
--t-xsfor meta only (never body),--t-smfor captions and kickers,--t-mdfor secondary text and menus,--t-lgfor body,--t-xlfor a lead or a card title. Display headings above that use clamp() at page level. - typ-3Body is
--t-lgat line-height 1.6. Text in a form field is at least 16px so phones do not zoom in. - typ-4Two weights: 400 and 600. Serif headings at 400, buttons and labels in the sans at 600. No light or thin weights.
- typ-5Sentence case everywhere. Uppercase only for a short kicker in
--t-smwith letter-spacing .08em. - typ-6Keep running text between 34 and 44em wide; balance headings with text-wrap:balance.
- typ-7System fonts only (the
--serifand--sansstacks). No web-font download on Amili sites.
Do h2 in --serif at 400, body in --sans at --t-lg
Don't Buttons in the serif, or body text in --t-xs
Do A kicker: HOW IT WORKS in --t-sm, 600, spaced
Don't A whole heading in capitals
The type scale, live
--t-xsMeta: updated 21 October 2026--t-smCaption, kicker, table note--t-mdSecondary text and menu items--t-lgBody text. Say it, Amili does it.--t-xlA lead line or a card title
A serif heading at 400
A sans button label at 600
Layout and spacing
Designed at 390px first, then widened. Space does most of the grouping.
- lay-1Design at 390px first. There is never horizontal scroll at 390px; wide tables and chip rows scroll inside their own box.
- lay-2Spacing comes from
--s-1to--s-6(4px, 8px, 12px, 16px, 24px, 32px). Gaps between page sections are multiples of 8 (48, 56, 72). - lay-3The side gutter is
--s-4(16px) and respects the safe area: padding-left:max(16px, env(safe-area-inset-left)), the same on the right. - lay-4Widths: running text 34 to 44em, page content up to 1080px, header and footer up to 1240px.
- lay-5Most important first: the intro says in one sentence what the page is for; the answer comes before the detail.
- lay-6Group with space and hairlines first. Use a card only for a unit people act on or compare (a plan, a product, a contact).
- lay-7Break by content, not by device: one column on phones, two from about 760px, a side table of contents from about 960px, the full menu from 48rem.
- lay-8Anything fixed to the bottom (a consent bar, a buy bar) adds env(safe-area-inset-bottom) and pads the page so it never hides the end of it.
Do gap:var(--s-3); padding:var(--s-5)
Don't gap:13px; padding:22px
Do A list of facts separated by hairlines
Don't Every paragraph in its own card
The spacing scale
--s-1--s-2--s-3--s-4--s-5--s-6
Shape
A small set of corner radii, each with one job.
- shp-1Every border-radius is a
--r-* token or 0. The design lint refuses anything else. - shp-2Buttons, text fields and chips are pills (
--r-pill). Cards use--r-card; menus, popovers and inner panels--r-md; tabs--r-tab; small controls in dense parts--r-sm; the focus ring and tiny tags--r-xs. - shp-3Nested corners get smaller inside: an inner panel in a card uses
--r-md, not--r-card. - shp-4A card is
--panel, a 1px--lineborder,--r-cardcorners and--s-5padding. No shadow at rest. - shp-5Keep a control group consistent: do not mix pill and square corners in one row of buttons.
Do A card with the --r-card corner token
Don't A card with a typed 18px corner
Corner radii and what each is for
--r-hairHairline marks--r-xsFocus ring, tags--r-smSmall controls--r-tabTabs--r-mdMenus, inner panels--r-cardCards--r-pillButtons, fields, chips
Motion
Motion confirms that something happened. It is short, it never moves the layout, and it disappears when people ask for less.
- mot-1Animate state, not decoration: colour and opacity changes over
--dur-fast(hover, press) or--dur(open, copied) with--ease. - mot-2Never animate size or position of controls. Buttons never grow; a text field may get taller, the buttons next to it stay 44px.
- mot-3Under prefers-reduced-motion: reduce, changes happen at once. Smooth scrolling only under no-preference.
- mot-4Nothing autoplays. Video plays on tap. Nothing flashes more than three times a second.
- mot-5The mark's asterisk may breathe by opacity only; it stops under reduced motion.
- mot-6Do not animate transform on text or the logo: it blurs on some screens.
Do transition:opacity var(--dur-fast) var(--ease)
Don't transition:all .6s; transform:scale(1.05) on hover
Feedback motion: a fade over --dur with --ease (instant under reduced motion)
Accessibility
Built in from the first line, then checked. We say "checked against WCAG 2.2 AA", never "compliant": an automated check finds part of the problems, not all.
- a11y-1Every target is at least 44 by 44px. Primary buttons are 52px tall; booking and buy buttons may be 56px. Inline links in running text get a 44px tap area with padding, without moving the lines.
- a11y-2Contrast: at least 4.5:1 for text, 3:1 for large text and for the edges of controls, in every theme and accent.
- a11y-3Focus is always visible: :focus-visible gets outline:2px solid var(
--accent), outline-offset:2px, radius--r-xs. Never remove an outline without a replacement. - a11y-4Every control has a visible label or an aria-label. A placeholder is never the label. An icon inside a labelled control is aria-hidden.
- a11y-5Status and results are announced: put them in an element with role="status" or aria-live="polite". An error names the field and the fix, and focus moves to it.
- a11y-6Structure: html lang set, header, nav with aria-label, main, footer; one h1; headings in order; the current page marked with aria-current="page".
- a11y-7The page works at 200% zoom and with larger text: nothing is clipped and nothing needs horizontal scroll.
- a11y-8Check with axe-core at 390 and 1280px in light and dark, plus a keyboard pass. Fix every critical and serious issue before launch, and say "checked against WCAG 2.2 AA".
Do <label for="email">Email</label><input id="email" type="email">
Don't <input placeholder="Email">
Do "Checked against WCAG 2.2 AA"
Don't "Fully accessible" or "WCAG compliant"
Press Tab: every control shows the same focus ring
Writing
Plain words, said once, in the voice of someone who is helping.
- wri-1Plain words, active voice, short sentences. Read it aloud; cut every word that does not change the meaning.
- wri-2Buttons start with a verb and say what will happen: "Request a site", "Save choice", "Copy". Not "Submit", "OK" or "Let's go!".
- wri-3End a page or an answer with one next step for the reader, said to them: "For you: …" (Dutch: "Voor jou: …").
- wri-4No hype, no superlatives, no invented numbers. A number is measured and dated, or it is left out.
- wri-5What is not built yet is tagged "Coming". Never claim an integration, a result or a price before it exists.
- wri-6An error says what happened, whose side it is on and what to do: "That didn't save. The problem is on our side. Try again in a moment?"
- wri-7One language per page, never mixed. English is the base; Dutch uses je and jij.
- wri-8The same word for the same thing everywhere: Say, Do and Know; Decline and Allow; Request a site.
- wri-9Sentence case for headings, buttons and menu items. No emoji as icons or bullets.
Do "Request a site"
Don't "Get started now!"
Do "Coming: sending tasks to your calendar"
Don't "Works with your calendar" (when it does not yet)
Do "For you: pick a plan, we reply within one working day."
Don't Three equal buttons at the end of the page
Icons
Simple line icons that sit next to words, drawn the same way everywhere.
- ico-1Inline SVG on a 24 by 24 grid: fill none, stroke currentColor, stroke-width var(
--stroke) (1.75 as an SVG attribute, where CSS variables do not work), round caps and joins. - ico-2Sizes: 18px inside text and table cells, 22px in lists, 26px on cards and in the side rail. Match the weight of the text next to it.
- ico-3An icon next to words is aria-hidden="true". An icon-only button has an aria-label and a 44px target.
- ico-4No emoji as icons, no icon fonts, no third-party logos as decoration.
- ico-5One style per page: do not mix filled and outlined icons.
Do <svg aria-hidden="true" stroke-width="1.75">… + the word "Prices"
Don't A price-tag emoji with no text
Line icons at 18, 22 and 26px, stroke 1.75, next to their words
- Prices
- Request
- Examples
- Search
- Copy
Dark mode and Warm night
Websites follow the system setting. The app adds a choice: Light, Dark, Warm night and an accent.
- drk-1Pages follow prefers-color-scheme. Websites get no theme toggle of their own; the app's settings offer Light, Dark, Warm night and the accent (data-theme and data-acc on html).
- drk-2Dark is not inverted light. Surfaces get lighter as they come forward (
--bg, then--panel,--panel2,--elev); the accent gets lighter and text on it turns dark. - drk-3Every page sets color-scheme:light dark and the two theme-color metas (light and dark page colour) from the Kit.
- drk-4Images and screenshots work on both: supply a dark version or choose one without a white box around it.
- drk-5Warm night is a dark theme with warm ink and an amber accent; the accent picker does not apply under it.
Do Colours from tokens, so dark comes for free
Don't A @media (prefers-color-scheme:dark) block with page-local colours
Preview this page in each theme with the switch at the top. The live site follows your system setting.
Patterns
Navigation
People should always know where they are and get back in one move.
Do Menu: Home, Pricing, How we work, Contact
Don't A menu with eight items and a second row
Forms and entering data
Ask for little, explain it clearly, and never lose what someone typed.
- frm-1The label sits above the field and stays visible. Help text goes under the label. A placeholder is only an example.
- frm-2Fields are pills, at least 52px tall, 16px text, background var(
--input-bg), a 1px--lineborder and an accent focus outline. - frm-3Ask only what is needed now. Use the right type, inputmode and autocomplete; offer a choice instead of typing when the answers are known.
- frm-4Check on submit or when leaving a field, not on every key. Keep what was typed, put the message next to the field and move focus there.
- frm-5The submit button says what happens and reads "One moment…" while sending. It is disabled only while sending.
- frm-6Say "done" only after the server confirmed it. If it failed, say so and keep the form filled.
- frm-7A text area grows with its text; the buttons next to it keep their size.
Do type="email" autocomplete="email" inputmode="email"
Don't type="text" for an email address
Do "You're on the list." after the server said 200
Don't "Thanks!" before the request returned
Demo form: nothing is sent
Feedback
Every action gets an answer, in place and sized to the action.
- fbk-1Confirm in place: the button that copied says "Copied ✓", the field that saved says "Saved". No toast for a small thing, no alert for something that is not critical.
- fbk-2"Was this page helpful?" offers Yes and No, the same size and weight. After a choice, an optional text field ("What would have helped?") with Send and Skip. Thank once and do not ask again on that page.
- fbk-3Ask for confirmation only before something that cannot be undone, and say exactly what will be lost.
- fbk-4When something cannot be done, say why and what the person can do instead.
Do Yes and No as two equal buttons
Don't A big green Yes and a small grey "no thanks"
Demo: nothing is sent
Was this page helpful?
Thank you. That helps us make the next page better.
Loading and empty states
Something useful is on screen at once, and nothing jumps when the rest arrives.
- lod-1Render the default state on the server: a calculator shows its default result, a list shows its first items. Scripts add to the page; they do not build it.
- lod-2Reserve space for what arrives later: width and height on images, a min-height on result areas. No layout shift.
- lod-3A wait of more than about a second says so in words ("One moment…"); a long one says what is happening.
- lod-4An empty state says what is missing and offers the one next step. Never an empty box.
- lod-5Keep the rest of the page usable while something loads.
Do "No answers shared yet. Ask Amili something and share the answer."
Don't A blank area
Consent
The Kit consent bar: one sentence, two equal buttons, nothing loads before a yes.
- cns-1Nothing that measures or tracks loads before Allow. Use the Kit consent bar (Consent Mode defaults to denied where the law asks).
- cns-2Decline comes first. Decline and Allow have the same size, style and weight. Nothing is pre-selected or focused when the bar appears.
- cns-3One plain sentence that names the tools (Google Analytics, Microsoft Clarity) and links to the privacy page.
- cns-4A "Cookie settings" button in the footer reopens the bar. The choice is kept for 12 months; Escape means Decline.
- cns-5While open, the bar pads the page so it never hides the end of it.
Do [Decline] [Allow], equal
Don't [Accept all] big and coloured, "manage" as a small link
Buying and affiliate links
A buy button is labelled as one, kept apart from advice, and never pushes.
- buy-1An affiliate link says so next to the button ("Affiliate link") and in the footer, and carries rel="sponsored nofollow noopener".
- buy-2Never place a paid or affiliate link inside an editorial list or ranking.
- buy-3A price is live or absent. Never a stale or invented price.
- buy-4The sticky buy bar (Kit buybar) sits in the flow, is 56px tall with a 44px button, respects the safe area, and appears once per page.
- buy-5No fake scarcity, countdowns or confirmshaming ("No, I don't like saving money").
Do "Check price on Amazon" + "Affiliate link"
Don't "Only 2 left!" with no source
Onboarding and choosing a plan
Let people see what they get, side by side, and choose without pressure.
- pln-1Plan choice uses the Kit plan-compare: the same labelled rows, in the same order, in every card.
- pln-2Mark at most one advised plan with a ribbon. The visitor chooses; no add-on is pre-ticked.
- pln-3Each price shows the currency, the period and whether VAT is included. A struck-through old price only for a real discount.
- pln-4Minimum term and how to cancel are visible before paying. Cancelling is as easy as signing up. A trial that turns paid is announced 3 days before.
- pln-5Let people try before asking for setup; ask for a permission or a detail only when the feature needs it; every onboarding step can be skipped.
- pln-6Rows past the fold hide behind "Show all" but stay in the HTML.
Do "EUR 59 per month, excl. VAT, 12 months minimum"
Don't "From EUR 59*" with the terms in a footnote
The Kit plan-compare, live, with example rows (the real plans are on Pricing)
EUR 149per month · excl. VAT
EUR 299per month · excl. VAT
Components
Every module in the Kit (kit/*.mjs, listed from the folder itself), what it is for, what it exports and where to see it. Use a Kit module before writing your own.
Brand tokens and mark
brand-amili.mjsColour roles (light, dark, Warm night, accent picker), type, radius, spacing, motion, the wordmark and the icon. Every page includes it first.
TOKEN_CSS, TOKEN_SOURCE, BRAND_CSS, MARK_HTML, ICON_SVG, THEME_COLOR, BRAND_JSConsent bar
consent.mjsCookie choice before any measuring tag; Decline and Allow equal.
EEA_UK_CH_CA, ASK_ZONES, KEEP_MS, STRINGS, langOf, settingsLabel, consentHead, renderConsent, CONSENT_CSS, CONSENT_JSAmili Search
search.mjsSite search over a prebuilt index; full-screen sheet on phones.
engine, brandMark, renderSearch, BRAND_CSS, SEARCH_CSS, LAUNCHER_CSS, searchScript, SEARCH_JSSearch index builder
search-build-index.mjsBuild step: writes the search index from the built pages.
pageRow, buildIndexSearch injector
search-inject.mjsBuild step: adds search to every built page.
strip, injectHtml, runTable of contents
toc.mjsJump list on long pages, chips on phones, current section marked.
slugify, shortLabel, brandMark, collectHeadings, renderToc, addToc, BRAND_CSS, TOC_CSS, TOC_JSFAQ
faq.mjsQuestions and answers that fold, with FAQPage data.
jsonForScript, brandMark, validateFaq, faqJsonLd, renderFaq, BRAND_CSS, FAQ_CSSComparison table
compare.mjsProducts or plans in a table with a sticky header and pinned first column.
validateCompare, bestCells, renderCompare, COMPARE_CSS, COMPARE_JSCalculator shell
calculator.mjsLabelled inputs and an announced result, default result already in the HTML.
brandMark, formatNumber, validateCalculator, renderCalculator, BRAND_CSS, CALC_CSS, CALC_JSSticky buy bar
buybar.mjsOne labelled buy action that stays in reach on long product pages.
validateBuyBar, renderBuyBar, BUYBAR_CSS, BUYBAR_JSAmazon product card
amazon-ad.mjsProduct image, live price and a clear, labelled affiliate button.
VARIANTS, CACHE_TTL_S, MAX_AGE_MS, DISCLAIMER, hash32, utcDay, candidatesFor, pickProducts, validatePool, parseItem, API_RESOURCES, makeItemsHandler, makeGateHandler, validateAdConfig, renderAd, renderAdSlots, AD_HEAD_JS, RANK_JS, AD_JS, AD_CSSClick beacon
beacon.mjsCookie-free click counts per position, for choosing placements.
beaconScript, makeBeaconHandler, kvCounterPlan choice
plan-compare.mjsThe choose-a-plan step of onboarding: cards with the same rows, one advised.
renderPlanCompare, PLAN_COMPARE_CSS, PLAN_COMPARE_JSCopy block
copy-block.mjsA ready-to-paste text with one copy button that confirms in place.
renderCopyBlock, COPY_BLOCK_CSS, COPY_BLOCK_JSHeading fold
heading-fold.mjsA section that folds behind its heading, with a count of what is inside.
renderHeadingFold, HEADING_FOLD_CSS, HEADING_FOLD_JSNo demo yet
Contact card
contact-card.mjsAn organisation as a card with big call, mail and open buttons.
HALF_MAX, renderContactCard, renderContactCards, CONTACT_CARD_CSS, CONTACT_CARD_JSNo demo yet
Page from Markdown
page-md.mjsMarkdown with Kit blocks (folds, copy blocks, contact cards, checklists, tables) as one page; used by amili.ai/p/.
keyOf, inline, renderPageMarkdown, PAGE_MD_CSS, PAGE_MD_JS, PAGE_MD_ALL_CSS, PAGE_MD_ALL_JSNo demo yet
Side rail
side-rail.mjsSticky actions at the right edge (request, prices, examples, WhatsApp); steps aside over text.
ICONS, renderSideRail, SIDE_RAIL_CSS, SIDE_RAIL_JSLive on every indexable amili.ai page
Session bar
session-bar.mjs"Signed in as …" and a real Log out, for pages behind a sign-in.
renderSessionBar, SESSION_BAR_CSSNo demo yet
Showcase
showcase.mjsThe agency layout of amili.ai: display hero, device frames, work grid, plan columns.
pic, browser, phone, sitePreview, sitePreviews, eyebrow, offerBadge, factChips, vsRow, SHOWCASE_CSS, SHOWCASE_JSSay deck
say-deck.mjsThe app's Say view: one message at a time, Amili's answer in the serif, and the composer.
ICON, sayIcon, sayDeckModel, SAY_DECK_CSS, sayDeckHtml, sayNavHtml, sayToolsHtmlNo demo yet
Gaps: what the Kit does not have yet
- Buttons and text fields: no Kit module yet. Pages write them from tokens (pill, 52px,
--accent/--input-bg), as shown on this page. - Header and menu: amili.ai's header is written by scripts/chrome.mjs, not a Kit module, and it does not yet slide away and come back on scroll-up (nav-3); the fleet header does.
- "Was this page helpful?": no Kit module and no endpoint yet. The demo on this page sends nothing.
- Dialog or sheet, status message (toast), tabs or segmented control, switch and checkbox: no Kit module yet.
- Empty state and loading placeholder: no Kit module yet (pattern only).
- Display heading sizes are clamp() values per page, not tokens; a
--t-displaytoken is still to come. - No Dutch edition of these guidelines yet.
Theming for brands
A brand built with the Kit changes its colour, type families and corners by overriding --ak-* values after the Kit CSS. The rest is the system and stays.
A brand may change
- thm-1The accent family, in light and dark:
--ak-acc,--ak-soft,--ak-on(text on the accent),--ak-mine,--ak-wash. Text on the accent must reach 4.5:1 and the accent on the page 3:1. - thm-2The surfaces
--ak-s0to--ak-s3and--ak-line, if text keeps 4.5:1 on every one of them, in light and dark. - thm-3The two font families
--serifand--sans(system stacks or one self-hosted family; no layout-shifting web-font swap). - thm-4Corner radii as a set:
--r-card,--r-mdand--r-smmay become squarer or rounder together.--r-pillstays a pill for buttons and fields. - thm-5The mark: a brand uses its own logo in place of the Amili mark.
Stays the same
- thm-6The spacing scale
--s-1to--s-6and the type scale--t-xsto--t-xl. - thm-7The role names (
--bg,--panel,--txt,--accent…): override the--ak-* values, never rename or bypass the roles. - thm-844px targets, the focus ring rule, the contrast minimums and reduced motion.
- thm-9
--stroke(1.75),--dur-fast(.15s),--dur(.2s) and--ease(ease-in-out). - thm-10The honest patterns: consent, affiliate labels, plan choice and "Coming" tags.
Example override
/* Brand override: put it AFTER the Kit's brand CSS. Example values for an imaginary bakery. */
:root{
--ak-acc:#8A3B12; --ak-soft:rgba(138,59,18,.11); --ak-on:#FFFFFF; --ak-mine:#8A3B12; --ak-wash:#C46A3A;
--serif:"Iowan Old Style",Charter,Georgia,serif;
--r-card:12px; --r-md:10px; --r-sm:8px;
}
@media (prefers-color-scheme:dark){:root:where(:not([data-theme=light])){
--ak-acc:#F0A57A; --ak-soft:rgba(240,165,122,.16); --ak-on:#1A0F08; --ak-mine:#5A2A10; --ak-wash:#A8552A;
}}
:root:where([data-theme=dark]){
--ak-acc:#F0A57A; --ak-soft:rgba(240,165,122,.16); --ak-on:#1A0F08; --ak-mine:#5A2A10; --ak-wash:#A8552A;
}For LLMs and Kit builders
The same rules as a compact file for machines: guidelines.md (rule ids, token values, do and don't, components). Paste the block below into the system prompt of Claude, ChatGPT or any builder that writes Amili UI. Every rule on this page has a stable id (for example col-3) to cite.
System prompt block, 39 lines
Build UI with the Amili Kit and follow the Amili Interface Guidelines (https://amili.ai/guidelines.md). Tokens - Include the Kit brand CSS (kit/brand-amili.mjs BRAND_CSS) first. Use only its short names in page CSS: colour --bg --panel --panel2 --elev --line --txt --dim --accent --on-acc --acc-soft --err --input-bg --shadow; space --s-1 4px, --s-2 8px, --s-3 12px, --s-4 16px, --s-5 24px, --s-6 32px; type --t-xs 12px, --t-sm 13px, --t-md 15px, --t-lg 17px, --t-xl 22px; radius --r-hair 2px, --r-xs 6px, --r-sm 10px, --r-tab 12px, --r-md 14px, --r-card 20px, --r-pill 999px; motion --dur-fast .15s, --dur .2s, --ease ease-in-out; icons stroke var(--stroke) = 1.75; fonts --serif, --sans. - Never write a hex colour, a raw radius or another stroke width in page CSS. Brands override --ak-* values only. - Light, dark and Warm night come from the tokens; never add page-local dark-mode colours. Look - Calm: one accent, used only for actions, links, the current item and the selection. Text on accent = --on-acc. - Serif (400) for headings and Amili's own voice; sans for body (--t-lg/1.6), labels and buttons (600). - Sentence case. No emoji as icons. Inline SVG line icons, 24 grid, currentColor, aria-hidden next to text. - Cards only for units people act on: --panel, 1px --line, --r-card, padding --s-5, no shadow at rest. - Phone first at 390px, gutter max(16px, env(safe-area-inset-left/right)), no horizontal scroll. - Text 34-44em wide; content max 1080px; header/footer max 1240px. Behaviour - Every target at least 44x44px; primary buttons 52px tall, pill shaped (--r-pill). - :focus-visible = 2px solid var(--accent), offset 2px. Never remove focus. - Real <label> above every field; placeholder is only an example; inputs 16px, background var(--input-bg). - Status in role="status"/aria-live="polite". Errors: what happened, whose side, what to do. - Render the default state in HTML; reserve space; no layout shift; no framework, no web fonts. - Motion only as feedback (opacity/colour); none under prefers-reduced-motion; nothing autoplays. - A header that hides on scroll-down returns on scroll-up and never covers content. Honesty (no dark patterns) - Decline and Allow equal (Kit consent bar); nothing tracks before Allow. - Affiliate links labelled "Affiliate link", rel="sponsored nofollow noopener", never inside editorial lists. - No fake scarcity, countdowns, confirmshaming or pre-ticked add-ons. Cancel as easy as sign-up. - Prices show currency, period and VAT; never invent a price, a number or an integration. Unbuilt = "Coming". Writing - Plain, active, short. Buttons start with a verb ("Request a site"). One language per page. - End with one next step for the reader ("For you: …" / "Voor jou: …"). No hype. Components (kit/*.mjs): amazon-ad, beacon, brand-amili, breadcrumbs, buybar, calculator, compare, consent, contact-card, copy-block, faq, footer, heading-fold, page-md, plan-compare, related, say-deck, search, search-build-index, search-inject, session-bar, showcase, side-rail, toc. Use a Kit module before writing your own. Check: axe-core at 390 and 1280px, light and dark; say "checked against WCAG 2.2 AA", never "compliant". Cite rules by id (e.g. col-3, a11y-1) from https://amili.ai/guidelines.md.
Sources and versions
- Version 1.0, 2026-10-21. Rule ids are stable and only ever added; a retired rule keeps its id.
- Token values come from
kit/brand-amili.mjs, which copies the app's own tokens; this page reads them when it is built. - Inspired by the structure and principles of Apple's Human Interface Guidelines. Everything here is written for Amili, in our own words.
- Accessibility targets follow WCAG 2.2 level AA.
For you: building a page? Start from the Kit, paste the prompt block into your builder, and check it at 390px in light and dark.