{"name":"aliabbas.net design tokens","description":"Read from the CSS and the code of the site. Use the Tailwind names in components. Follow the rules.","page":"https://aliabbas.net/design","sources":{"css":"https://github.com/alivault/aliabbas.net/blob/master/src/styles/globals.css","motion":"https://github.com/alivault/aliabbas.net/blob/master/src/lib/design/motion.ts","titles":"https://github.com/alivault/aliabbas.net/blob/master/src/components/Title.tsx","rules":"https://github.com/alivault/aliabbas.net/blob/master/src/lib/design/rules.ts","agents":"https://github.com/alivault/aliabbas.net/blob/master/AGENTS.md"},"colorSchemes":{"light":"Default.","dark":"From prefers-color-scheme: dark. There is no manual switch."},"color":{"background":{"group":"Surface","use":"The page.","light":"oklch(0.955 0.009 94)","dark":"oklch(0.121 0.0039 245.5)","tailwind":"bg-background"},"foreground":{"group":"Text","use":"All text. Lower its opacity for less important text.","light":"oklch(0.155 0.006 85)","dark":"oklch(0.915 0.009 94)","tailwind":"text-foreground"},"fg-secondary":{"group":"Text","use":"Supporting text next to primary text. APCA Lc 75 or more.","light":"oklch(0.36 0.008 85)","dark":"oklch(0.85 0.009 94)","tailwind":"text-fg-secondary"},"fg-muted":{"group":"Text","use":"Descriptions, metadata and hints. APCA Lc 60 or more.","light":"oklch(0.46 0.008 85)","dark":"oklch(0.77 0.008 94)","tailwind":"text-fg-muted"},"fg-faint":{"group":"Text","use":"Disabled text and decoration only.","light":"oklch(0.62 0.008 85)","dark":"oklch(0.59 0.007 94)","tailwind":"text-fg-faint"},"card":{"group":"Surface","use":"Cards and panels that sit on the page.","light":"oklch(0.98 0.005 94)","dark":"oklch(0.165 0.004 245.5)","tailwind":"bg-card"},"card-foreground":{"group":"Text","use":"Text on a card.","light":"oklch(0.155 0.006 85)","dark":"var(--foreground)","tailwind":"text-card-foreground"},"popover":{"group":"Surface","use":"Hover cards, menus and drawers.","light":"oklch(0.98 0.005 94)","dark":"oklch(0.165 0.004 245.5)","tailwind":"bg-popover"},"popover-foreground":{"group":"Text","use":"Text on a popover.","light":"oklch(0.155 0.006 85)","dark":"var(--foreground)","tailwind":"text-popover-foreground"},"primary":{"group":"Action","use":"The main button of a view.","light":"oklch(0.155 0.006 85)","dark":"var(--foreground)","tailwind":"bg-primary"},"primary-foreground":{"group":"Action","use":"Text on a primary fill.","light":"oklch(0.97 0.01 94)","dark":"var(--background)","tailwind":"text-primary-foreground"},"secondary":{"group":"Surface","use":"Quiet filled controls.","light":"oklch(0.91 0.012 94)","dark":"oklch(0.21 0.005 245.5)","tailwind":"bg-secondary"},"secondary-foreground":{"group":"Text","use":"Text on a secondary fill.","light":"oklch(0.155 0.006 85)","dark":"var(--foreground)","tailwind":"text-secondary-foreground"},"muted":{"group":"Surface","use":"Wells and hover fills.","light":"oklch(0.91 0.012 94)","dark":"oklch(0.21 0.005 245.5)","tailwind":"bg-muted"},"muted-foreground":{"group":"Text","use":"Text on a muted fill.","light":"var(--fg-muted)","dark":"var(--fg-muted)","tailwind":"text-muted-foreground"},"accent":{"group":"Action","use":"Hover fill of menu items.","light":"color-mix(in oklab, var(--foreground) 10%, transparent)","dark":"color-mix(in oklab, var(--foreground) 10%, transparent)","tailwind":"bg-accent"},"accent-foreground":{"group":"Action","use":"Text on an accent fill.","light":"var(--foreground)","dark":"var(--foreground)","tailwind":"text-accent-foreground"},"destructive":{"group":"Status","use":"Errors and actions that delete.","light":"oklch(0.58 0.22 27)","dark":"oklch(0.79 0.12 27)","tailwind":"bg-destructive"},"verified":{"group":"Status","use":"The claim checker: verified.","light":"oklch(0.52 0.12 152)","dark":"oklch(0.76 0.13 152)","tailwind":"bg-verified"},"partial":{"group":"Status","use":"The claim checker: partly verified.","light":"oklch(0.58 0.13 70)","dark":"oklch(0.8 0.13 80)","tailwind":"bg-partial"},"contradicted":{"group":"Status","use":"The claim checker: contradicted.","light":"oklch(0.55 0.2 27)","dark":"oklch(0.79 0.12 25)","tailwind":"bg-contradicted"},"border":{"group":"Line","use":"Dividers and card edges.","light":"oklch(0.82 0.012 94)","dark":"oklch(0.28 0.006 245.5)","tailwind":"border-border"},"input":{"group":"Line","use":"Edges of fields.","light":"oklch(0.82 0.012 94)","dark":"oklch(0.28 0.006 245.5)","tailwind":"border-input"},"ring":{"group":"Action","use":"The focus ring. Every control shows it.","light":"color-mix(in oklab, var(--foreground) 50%, transparent)","dark":"color-mix(in oklab, var(--foreground) 50%, transparent)","tailwind":"bg-ring"},"brand":{"group":"Action","use":"Selection, the active citation and emphasis in headings.","light":"oklch(0.44 0.008 85)","dark":"oklch(0.8 0.008 94)","tailwind":"bg-brand"},"brand-foreground":{"group":"Action","use":"Text on a brand fill.","light":"var(--background)","dark":"var(--background)","tailwind":"text-brand-foreground"},"page-base":{"group":"Surface","use":"Behind the page cards during a page transition.","light":"oklch(0.8 0.014 94)","dark":"oklch(0.05 0.002 245.5)","tailwind":"bg-page-base"}},"text":{"fonts":{"sans":{"family":"DM Sans Variable","use":"All text. Weight 400 for titles."},"mono":{"family":"JetBrains Mono","use":"Code, file paths and ids only. Never for labels."}},"minimumSize":"14px","tones":[{"name":"Primary","className":"text-foreground","use":"Headings and body text."},{"name":"Secondary","className":"text-fg-secondary","use":"Supporting text next to primary text."},{"name":"Muted","className":"text-fg-muted","use":"Descriptions, metadata and hints."},{"name":"Faint","className":"text-fg-faint","use":"Disabled text and decoration. Never for text that people must read."}],"titles":[{"variant":"page","role":"Page title (h1)","size":"44–88px","lineHeight":1.08},{"variant":"section","role":"Section title","size":"32–56px","lineHeight":1.15},{"variant":"card","role":"Card and project title","size":"24–32px","lineHeight":1.2},{"variant":"subsection","role":"Subsection title","size":"20–24px","lineHeight":1.3},{"variant":"detail","role":"Detail title","size":"18px","lineHeight":1.4}],"body":[{"className":"text-lg","size":"18px","lineHeight":"32px","use":"Lead paragraphs."},{"className":"text-base","size":"16px","lineHeight":"28px","use":"Body text."},{"className":"text-sm","size":"14px","lineHeight":"24px","use":"Controls, metadata and hints. The smallest size."}]},"layout":{"breakpoints":{"sm":"40rem","lg":"64rem"},"tokens":[{"name":"section-padding","use":"Space above and below a page section.","base":"3rem","sm":"4rem","lg":"5rem"},{"name":"section-content-gap","use":"Space between a section title and its content.","base":"2rem","sm":"2.5rem","lg":"3rem"},{"name":"radius","use":"Corner radius of controls. Cards use radius + 4px, pills use full.","base":"0.5rem"}]},"motion":{"springs":{"layout":{"type":"spring","stiffness":380,"damping":36},"settle":{"type":"spring","stiffness":420,"damping":34},"pop":{"type":"spring","stiffness":540,"damping":27},"bloom":{"type":"spring","stiffness":220,"damping":18},"hover":{"type":"spring","stiffness":320,"damping":18}},"easeOut":[0.22,1,0.36,1],"easeIn":[0.64,0,0.78,0],"durations":{"enter":0.28,"exit":0.2,"page":0.55,"reveal":0.7,"showcase":1.1}},"rules":[{"id":"tokens-only","rule":"Use the color tokens (bg-background, text-fg-muted, border-border, text-brand). Do not write a color value in a component.","why":"Light and dark mode then change together, and one edit changes the site."},{"id":"text-size","rule":"No text under 14px, and no capitals made with CSS. Use text-sm (14px) as the smallest size.","why":"Small capital labels are hard to read and add noise without meaning.","checkedBy":"e2e/pages.spec.ts"},{"id":"no-eyebrows","rule":"Do not put a small label above a heading. Put the meaning in the heading, or number the heading.","why":"A label above a heading repeats it, and screen readers read it as a separate line."},{"id":"mono-for-code","rule":"Use the mono font only for code, file paths and ids, at 14px or more.","why":"Mono marks text that a reader can copy into a terminal or an editor."},{"id":"titles","rule":"Make headings with Title, PageHeading or SectionHeading. Use className for layout only, not for size or weight.","why":"One scale for the whole site. To change a size, change the variant in Title.tsx."},{"id":"text-tones","rule":"Show less important text with text-fg-secondary or text-fg-muted. Do not lower the opacity of text-foreground. Use text-fg-faint only for decoration and disabled text.","why":"One opacity looks much dimmer on a dark background. Each tone has its own light and dark value, tested for APCA contrast in both schemes.","checkedBy":"src/lib/design/tokens.test.ts"},{"id":"color-not-alone","rule":"Never show a state with color alone. Add an icon and a text label.","why":"WCAG 1.4.1. The claim checker grades each have an icon, a label and a color."},{"id":"focus","rule":"Every control shows the focus ring. When an overlay closes, focus goes back to the control that opened it.","why":"Keyboard users must always know where they are.","checkedBy":"e2e/lab.spec.ts"},{"id":"states","rule":"A view that waits for the network has these states: idle, pending, streaming, complete, stopped and failed. Esc stops it, and the text that arrived stays.","why":"A stream can be slow, stop or fail at any point. Each case needs a clear screen.","checkedBy":"e2e/chat.spec.ts, e2e/check.spec.ts, e2e/lab.spec.ts"},{"id":"stale-events","rule":"Every stream event carries the attempt it belongs to. A reducer ignores events from an attempt that is not active.","why":"A stopped answer must not write into a new one.","checkedBy":"src/lib/chat/chat-machine.test.ts"},{"id":"motion-tokens","rule":"Animate with a spring, ease and duration from src/lib/design/motion.ts. Do not write new values in a component.","why":"The same kind of change then moves the same way on every page."},{"id":"reduced-motion","rule":"Respect reduced motion. Motion does this through MotionConfig at the root. CSS animations need a prefers-reduced-motion block.","why":"Large movement can make some people feel sick."},{"id":"targets","rule":"Make click and touch targets at least 24 by 24px. Buttons are 32px high.","why":"WCAG 2.5.8. Small targets are hard to hit on a phone."},{"id":"components","rule":"Build on the shadcn/ui base-nova components in src/components/ui, on Base UI. Merge classes with cn from the cn package. Use Lucide icons.","why":"The primitives handle focus, keyboard and ARIA. Do not rebuild them."}]}