From 286bb9cab1f4c41bbf08f6b72ff594bc54c97b9c Mon Sep 17 00:00:00 2001 From: Kevin Bataille Date: Wed, 22 Jul 2026 02:24:51 +0200 Subject: [PATCH] Add local agent workspace files and skills Includes .agents/, additional .claude/skills/, and skills-lock.json. --- .agents/skills/caveman/README.md | 48 ++ .agents/skills/caveman/SKILL.md | 78 +++ .agents/skills/fuck-slop/SKILL.md | 86 +++ .agents/skills/fuck-slop/references/tells.md | 171 +++++ .agents/skills/fuck-slop/references/voices.md | 61 ++ .agents/skills/grill-me/SKILL.md | 209 ++++++ .agents/skills/interface-kit/SKILL.md | 582 +++++++++++++++++ .../references/accessibility-checklist.md | 425 ++++++++++++ .../references/animation-playbook.md | 545 ++++++++++++++++ .../references/component-patterns.md | 604 ++++++++++++++++++ .../references/review-checklist.md | 204 ++++++ .claude/skills/caveman/README.md | 48 ++ .claude/skills/caveman/SKILL.md | 78 +++ .claude/skills/fuck-slop/SKILL.md | 86 +++ .claude/skills/fuck-slop/references/tells.md | 171 +++++ .claude/skills/fuck-slop/references/voices.md | 61 ++ .claude/skills/grill-me/SKILL.md | 209 ++++++ .claude/skills/interface-kit/SKILL.md | 582 +++++++++++++++++ .../references/accessibility-checklist.md | 425 ++++++++++++ .../references/animation-playbook.md | 545 ++++++++++++++++ .../references/component-patterns.md | 604 ++++++++++++++++++ .../references/review-checklist.md | 204 ++++++ skills-lock.json | 29 + 23 files changed, 6055 insertions(+) create mode 100644 .agents/skills/caveman/README.md create mode 100644 .agents/skills/caveman/SKILL.md create mode 100644 .agents/skills/fuck-slop/SKILL.md create mode 100644 .agents/skills/fuck-slop/references/tells.md create mode 100644 .agents/skills/fuck-slop/references/voices.md create mode 100644 .agents/skills/grill-me/SKILL.md create mode 100644 .agents/skills/interface-kit/SKILL.md create mode 100644 .agents/skills/interface-kit/references/accessibility-checklist.md create mode 100644 .agents/skills/interface-kit/references/animation-playbook.md create mode 100644 .agents/skills/interface-kit/references/component-patterns.md create mode 100644 .agents/skills/interface-kit/references/review-checklist.md create mode 100644 .claude/skills/caveman/README.md create mode 100644 .claude/skills/caveman/SKILL.md create mode 100644 .claude/skills/fuck-slop/SKILL.md create mode 100644 .claude/skills/fuck-slop/references/tells.md create mode 100644 .claude/skills/fuck-slop/references/voices.md create mode 100644 .claude/skills/grill-me/SKILL.md create mode 100644 .claude/skills/interface-kit/SKILL.md create mode 100644 .claude/skills/interface-kit/references/accessibility-checklist.md create mode 100644 .claude/skills/interface-kit/references/animation-playbook.md create mode 100644 .claude/skills/interface-kit/references/component-patterns.md create mode 100644 .claude/skills/interface-kit/references/review-checklist.md create mode 100644 skills-lock.json diff --git a/.agents/skills/caveman/README.md b/.agents/skills/caveman/README.md new file mode 100644 index 0000000..d749b83 --- /dev/null +++ b/.agents/skills/caveman/README.md @@ -0,0 +1,48 @@ +# caveman + +Talk like smart caveman. Same brain, fewer tokens. + +## What it does + +Compress every model response to caveman-style prose. Drops articles, filler, pleasantries, and hedging. Keeps every technical detail, code block, error string, and symbol exact. Cuts ~65-75% of output tokens with full accuracy preserved. Mode persists for the whole session until changed or stopped. + +Six intensity levels: + +| Level | What change | +|-------|-------------| +| `lite` | Drop filler/hedging. Sentences stay full. Professional but tight. | +| `full` | Default. Drop articles, fragments OK, short synonyms. | +| `ultra` | Bare fragments. Abbreviations (DB, auth, fn). Arrows for causality. | +| `wenyan-lite` | Classical Chinese register, light compression. | +| `wenyan-full` | Maximum 文言文. 80-90% character reduction. | +| `wenyan-ultra` | Extreme classical compression. | + +Auto-clarity rule: caveman drops to normal prose for security warnings, irreversible-action confirmations, multi-step sequences where fragment ambiguity risks misread, and when user repeats a question. Resumes after the clear part. + +## How to invoke + +``` +/caveman # full mode (default) +/caveman lite # lighter compression +/caveman ultra # extreme compression +/caveman wenyan # classical Chinese +stop caveman # back to normal prose +``` + +## Example output + +Question: "Why does my React component re-render?" + +Normal prose: +> Your component re-renders because you create a new object reference each render. Wrapping it in `useMemo` will fix the issue. + +Caveman (full): +> New object ref each render. Inline object prop = new ref = re-render. Wrap in `useMemo`. + +Caveman (ultra): +> Inline obj prop → new ref → re-render. `useMemo`. + +## See also + +- [`SKILL.md`](./SKILL.md) — full LLM-facing instructions +- [Caveman README](../../README.md) — repo overview, install, benchmarks diff --git a/.agents/skills/caveman/SKILL.md b/.agents/skills/caveman/SKILL.md new file mode 100644 index 0000000..8792c1a --- /dev/null +++ b/.agents/skills/caveman/SKILL.md @@ -0,0 +1,78 @@ +--- +name: caveman +description: > + Ultra-compressed communication mode. Cuts token usage ~75% by speaking like caveman + while keeping full technical accuracy. Supports intensity levels: lite, full (default), ultra, + wenyan-lite, wenyan-full, wenyan-ultra. + Use when user says "caveman mode", "talk like caveman", "use caveman", "less tokens", + "be brief", or invokes /caveman. Also auto-triggers when token efficiency is requested. +--- + +Respond terse like smart caveman. All technical substance stay. Only fluff die. + +## Persistence + +ACTIVE EVERY RESPONSE. No revert after many turns. No filler drift. Still active if unsure. Off only: "stop caveman" / "normal mode". + +Default: **full**. Switch: `/caveman lite|full|ultra`. + +## Rules + +Drop: articles (a/an/the), filler (just/really/basically/actually/simply), pleasantries (sure/certainly/of course/happy to), hedging. Fragments OK. Short synonyms (big not extensive, fix not "implement a solution for"). No tool-call narration, no decorative tables/emoji, no dumping long raw error logs unless asked — quote shortest decisive line. Standard well-known tech acronyms OK (DB/API/HTTP); never invent new abbreviations reader can't decode. Technical terms exact. Code blocks unchanged. Errors quoted exact. + +Preserve user's dominant language. User write Portuguese → reply Portuguese caveman. User write Spanish → reply Spanish caveman. Compress the style, not the language. No forced English openings or status phrases. ALWAYS keep technical terms, code, API names, CLI commands, commit-type keywords (feat/fix/...), and exact error strings verbatim — unless user explicitly ask for translation. + +No self-reference. Never name or announce the style. No "caveman mode on", "me caveman think", no third-person caveman tags. Output caveman-only — never normal answer plus "Caveman:" recap. Exception: user explicitly ask what the mode is. + +Pattern: `[thing] [action] [reason]. [next step].` + +Not: "Sure! I'd be happy to help you with that. The issue you're experiencing is likely caused by..." +Yes: "Bug in auth middleware. Token expiry check use `<` not `<=`. Fix:" + +## Intensity + +| Level | What change | +|-------|------------| +| **lite** | No filler/hedging. Keep articles + full sentences. Professional but tight | +| **full** | Drop articles, fragments OK, short synonyms. Classic caveman. No tool-call narration, no decorative tables/emoji, no long raw error-log dumps unless asked. Standard acronyms OK; no invented abbreviations | +| **ultra** | Abbreviate prose words (DB/auth/config/req/res/fn/impl) — prose words only, never real code symbols/function names. Strip conjunctions, arrows for causality (X → Y), one word when one word enough. Code symbols, function names, API names, error strings: never abbreviate | +| **wenyan-lite** | Semi-classical. Drop filler/hedging but keep grammar structure, classical register | +| **wenyan-full** | Maximum classical terseness. Fully 文言文. 80-90% character reduction. Classical sentence patterns, verbs precede objects, subjects often omitted, classical particles (之/乃/為/其) | +| **wenyan-ultra** | Extreme abbreviation while keeping classical Chinese feel. Maximum compression, ultra terse | + +Example — "Why React component re-render?" +- lite: "Your component re-renders because you create a new object reference each render. Wrap it in `useMemo`." +- full: "New object ref each render. Inline object prop = new ref = re-render. Wrap in `useMemo`." +- ultra: "Inline obj prop → new ref → re-render. `useMemo`." +- wenyan-lite: "組件頻重繪,以每繪新生對象參照故。以 useMemo 包之。" +- wenyan-full: "每繪新生對象參照,故重繪;以 useMemo 包之則免。" +- wenyan-ultra: "新參照→重繪。useMemo Wrap。" + +Example — "Explain database connection pooling." +- lite: "Connection pooling reuses open connections instead of creating new ones per request. Avoids repeated handshake overhead." +- full: "Pool reuse open DB connections. No new connection per request. Skip handshake overhead." +- ultra: "Pool = reuse DB conn. Skip handshake → fast under load." +- wenyan-full: "池reuse open connection。不每req新開。skip handshake overhead。" +- wenyan-ultra: "池reuse conn。skip handshake → fast。" + +## Auto-Clarity + +Drop caveman when: +- Security warnings +- Irreversible action confirmations +- Multi-step sequences where fragment order or omitted conjunctions risk misread +- Compression itself creates technical ambiguity (e.g., `"migrate table drop column backup first"` — order unclear without articles/conjunctions) +- User asks to clarify or repeats question + +Resume caveman after clear part done. + +Example — destructive op: +> **Warning:** This will permanently delete all rows in the `users` table and cannot be undone. +> ```sql +> DROP TABLE users; +> ``` +> Caveman resume. Verify backup exist first. + +## Boundaries + +Code/commits/PRs: write normal. "stop caveman" or "normal mode": revert. Level persist until changed or session end. \ No newline at end of file diff --git a/.agents/skills/fuck-slop/SKILL.md b/.agents/skills/fuck-slop/SKILL.md new file mode 100644 index 0000000..6153b95 --- /dev/null +++ b/.agents/skills/fuck-slop/SKILL.md @@ -0,0 +1,86 @@ +--- +name: fuck-slop +description: > + De-slop pass for any text: detects and erases the statistical fingerprints of + AI writing (negative parallelism / "not X but Y", em-dash abuse, rule-of-three, + false ranges, puffery vocabulary, uniform cadence, hedged both-sidesing) and + rewrites the text into its target register — academic article, tweet, reddit + post, email, blog, anything between. Use when the user says "fuck slop", + "f*ck slop", "deslop", "de-slop this", "remove the AI tells", "humanize this", + "make this not sound like AI", or invokes /fuck-slop. Also use before + publishing any agent-drafted prose. +--- + +# F*ck Slop + +Strip every mark of AI writing from a text and make it good in its genre. Not "make it pass a detector" — make it read like a specific person with a specific point wrote it for a specific audience. + +## Why this is a loop, not a style guide + +The worst tells — above all the **"not X but Y"** family — are not vocabulary mistakes. They are emergent properties of how LLMs generate text: preference tuning rewards balanced, contrastive, comprehensive-sounding framing, so the contrast move is baked into the model's priors. Two consequences drive this skill's architecture: + +1. **You cannot reliably see your own slop.** The same priors that produce the pattern make it invisible on re-read. Detection must be mechanical — regex against a fixed catalog — never "does this look AI to me?" +2. **Rewriting reintroduces slop.** Ask a model to remove "it's not just X, it's Y" and it produces "this is less about X than Y" — the same move in a wig. So every rewrite gets re-scanned, and the loop runs until the scan is clean. + +Workflow: **Scan → Diagnose → Rewrite by meaning → Re-scan → (repeat) → Register check.** + +## Phase 0: Fix the target + +Before touching the text, establish: + +- **Genre and venue** — academic article, tweet, reddit post, LinkedIn, email, blog, docs, marketing. If not stated and not obvious from the text, ask. Genre decides which tells are fatal and what "good" means; see [references/voices.md](references/voices.md). +- **Audience and stance** — who reads it, and what the author actually claims. Slop is what fills the space where a claim should be; you cannot remove it without knowing the claim. +- **Constraints** — length limits, required citations, house style. + +## Phase 1: Mechanical scan + +Run the detection patterns from [references/tells.md](references/tells.md) against the text. If the text is in a file (or you can write it to a temp file), run the grep commands in that reference literally — the catalog is written as runnable `grep -Ein` patterns. Otherwise apply each pattern by hand, line by line. + +Produce a finding list: line/sentence, matched pattern, tell category. Also run the two structural checks that regex can't fully catch: + +- **Cadence**: flag any run of 3+ consecutive sentences within ±4 words of the same length, and any paragraph where every sentence has the same shape (subject–verb–elaboration). +- **Formatting**: bold scattered through prose, emoji-decorated headers or bullets, "**Term:** definition" bullet lists, headers on a text too short to need them, a tidy intro–three-points–conclusion skeleton. + +Report the findings to the user as a short table before rewriting (category, count, worst example). This is the diagnosis; the user should see what was wrong. + +## Phase 2: Rewrite by meaning, not by frame + +Go finding by finding. The cardinal rule: **never fix a pattern by paraphrasing the pattern.** Fix it by deciding what the sentence actually asserts, then asserting that. + +### The "not X but Y" family — three-way triage + +Every negative parallelism gets exactly one of these treatments: + +1. **The negation is a strawman** (nobody believes X). Delete the X half entirely and assert Y directly, with whatever evidence the text has. + - *"It's not just a tool, it's a fundamental shift in how teams work"* → *"Teams that adopted it stopped holding standups within a month."* +2. **The contrast is real** (people genuinely hold X). Then earn it: name who holds X, say concretely why Y beats it. A real contrast survives being made specific; slop doesn't. +3. **The sentence asserts nothing** (the contrast is decoration on an empty claim). Delete the whole sentence. Most cases are this one. + +Banned escape hatches — these are the same move and count as new findings: "less about X than Y", "X matters, but Y matters more", "the real X is Y", "the question isn't X, it's Y", "X? Y." (rhetorical-question variant), and the em-dash variant "— not X, but Y". + +### Everything else + +- **Puffery and inflated vocabulary** (pivotal, seismic, testament, tapestry, landscape, delve…): replace with the plain word, or with the concrete fact the puffery was hiding. "Plays a vital role in" → "does". +- **Rule-of-three lists**: keep the strongest item, cut the rest — unless all three carry distinct information, in which case keep them and break the rhythm (different lengths, different syntax). +- **False ranges** ("from X to Y"): if you can't name a meaningful midpoint between X and Y, it's not a range — name the two things or cut one. +- **Hedged both-sidesing** ("it's worth noting", auto-counterpoints, "while X, it's also true that Y"): commit. One opinion, stated, owned. A counterpoint stays only if the author genuinely concedes it. +- **Uniform cadence**: vary deliberately. Follow a long sentence with a short one. Fragments are legal. Don't apply a formula (alternating long/short is its own tell) — read the paragraph aloud and break wherever the rhythm is metronomic. +- **Low specificity**: replace "many companies" / "studies show" / "recent research" with the actual names, numbers, and dates — **only from the source text, the conversation, or verifiable research you actually do**. Never invent specifics. If the author needs to supply one, leave a marked placeholder: `[ADD: which study?]`. +- **Stock skeleton**: kill throat-clearing openers ("In today's fast-paced world…"), summary conclusions ("In conclusion… Ultimately…"), and engagement-bait endings ("What do you think?"). Start where the point starts; stop when it's made. + +### What not to do — overcorrection is also slop + +- No fake typos, forced slang, or manufactured "voice". Humanizer-tool output is its own genre of slop. +- Em dashes are not banned. Humans use them. The tell is density and the double-dash "— not X, but —" move. Budget: at most one em dash per ~150 words, never two in a sentence. +- Don't trade precision for personality in academic or technical text. There, de-slopping means cutting puffery and committing to claims — not adding attitude. +- Preserve the author's meaning, claims, and facts exactly. This is a style pass, not a content edit. Flag, don't silently fix, anything that looks factually wrong. + +## Phase 3: Verify loop + +Re-run the full Phase 1 scan **on your rewritten text**. This step is not optional and not a formality — expect your own rewrite to contain new tells, because the model writing it has the same priors that created them. Fix and re-scan until a pass produces zero pattern hits and the cadence check passes. Cap at 4 passes; if a pattern survives 4 passes, rewrite that sentence from scratch starting from its bare claim ("what fact or opinion is this sentence for?"). + +## Phase 4: Register check + +Check the clean text against its genre profile in [references/voices.md](references/voices.md): right length, right formality, right person, genre-specific tells gone (e.g. on reddit: no bold, no bullet essay; in academic prose: no first-person hot takes added). Then the final test — read it aloud. Anywhere you wouldn't say it to the actual audience, rewrite that sentence. + +Deliver: the rewritten text, plus a brief change log (categories fixed, counts, and number of verify passes it took). diff --git a/.agents/skills/fuck-slop/references/tells.md b/.agents/skills/fuck-slop/references/tells.md new file mode 100644 index 0000000..9d6417f --- /dev/null +++ b/.agents/skills/fuck-slop/references/tells.md @@ -0,0 +1,171 @@ +# AI-Writing Tell Catalog + +Detection patterns for the F*ck Slop scan. Patterns are written for `grep -Ein` (extended regex, case-insensitive, line numbers) so they can be run literally against a file: + +```bash +grep -Ein -f /dev/stdin draft.txt <<'PATTERNS' + +PATTERNS +``` + +When the text only exists in conversation, apply each pattern by hand. A match is a *finding*, not an automatic deletion — every finding goes through the Phase 2 triage in SKILL.md. Density matters: one em dash is nothing; one em dash plus a negative parallelism plus "delve" in the same paragraph is a verdict. + +## 1. Negative parallelism — the "not X but Y" family + +The highest-priority category. LLMs reach for the negation-then-assertion move roughly once a paragraph; humans use it occasionally and deliberately. It is an emergent generative habit, so expect it to reappear in paraphrased form after every rewrite pass — that is why the scan loops. + +``` +not (just|only|merely|simply|solely) [^.;]{2,80}(but|it'?s| — ) +isn'?t (just|only|merely|simply|about) +it'?s not (a|an|the|that|about|just) [^.;]{2,80}(it'?s|but) +(is|was|are|were)n'?t about [^.;]{2,60}\. (it|this|that)'?s about +less about [^.;]{2,60}(than|and more about) +more than (just|a mere|simply) +not because [^.;]{2,80}but because +the (question|point|issue|problem|goal|real [a-z]+) is(n'?t| not) (whether|about|just|if) +(doesn'?t|don'?t|didn'?t|won'?t) (just|merely|simply) [^.;]{2,80}(it|they|he|she|we) +no [a-z]+, no [a-z]+(, no [a-z]+)?[,.]? just +— not [^—.;]{2,60}, but +not only [^.;]{2,80}but (also )? +we'?re not (just )?(talking about|looking at|dealing with) +gone are the days +(here|this)'?s the (thing|kicker|catch|twist) +``` + +Rhetorical-question variant (regex-resistant; check by hand): a one-line question immediately answered by a one-word or one-clause sentence. *"The result? Chaos."* / *"Sound familiar?"* + +## 2. Puffery and inflated vocabulary + +Single words that spike in LLM output. Each is fine in isolation; two or more per page is a finding. The fix is the plain word or the concrete fact the word was hiding. + +``` +\b(delve|delving)\b +\btapestry\b +\b(testament|stands as)\b +\bseamless(ly)?\b +\b(pivotal|paramount|crucial)\b +\bunderscore(s|d)?\b +\b(landscape|realm|sphere) of\b +\bnavigat(e|ing) the\b +\bfoster(s|ing)?\b +\bleverage(s|d)?\b +\bmeticulous(ly)?\b +\bintricate\b +\bboasts\b +\bgame.?chang(er|ing)\b +\b(seismic|monumental|transformative) (shift|change)\b +\bunwavering\b +\bcommendable\b +\belevate(s|d)? (the|your)\b +\bshowcas(e|es|ing)\b +\bresonate(s|d)?\b +\bcompelling\b +\brich (cultural )?(heritage|history|tradition)\b +\bvibrant\b +\bplays? a (vital|key|crucial|pivotal) role\b +\bdeep(er)? dive\b +\bunlock(s|ing)? (the|your)\b +\bharness(es|ing)? the\b +\bembark(s|ed|ing)? on\b +\bever.?(evolving|changing)\b +\bfast.?paced (world|environment)\b +\bin today'?s\b +\bat the end of the day\b +\bwhen it comes to\b +\bcutting.?edge\b +\brobust\b +\bholistic\b +\bsynergy\b +\bempower(s|ing|ment)?\b +``` + +## 3. Hedging, both-sidesing, throat-clearing + +The tell is reflexive balance: every claim gets a softener, every opinion gets a counterpoint. Commit or cut. + +``` +it'?s (worth|important) (to note|noting|to remember|to consider) +(that|it) (being )?said, +while (it'?s|this is) (true|important) +arguably +in many ways +to some (extent|degree) +on the other hand +at its core +in essence +essentially, +ultimately, +in conclusion +in summary +to sum(marize| up) +overall, +in the end, +needless to say +as (we|you) (can see|know|all know) +let'?s (dive|unpack|explore|take a (look|closer look)) +whether you('re| are) [^.;]{2,60} or +``` + +## 4. False ranges and rule-of-three + +**False range** — a "from X to Y" with no actual spectrum between X and Y: + +``` +from [^.;]{3,50} to [^.;]{3,50} +``` + +Triage by hand: if you can name a meaningful midpoint, it's a real range and stays. If X and Y are just two loosely related examples, name them plainly or cut one. + +**Rule of three** — LLMs default to triplets to make thin analysis look thorough. Regex only catches the simplest shape; check lists by hand too. + +``` +\b\w+, \w+, and \w+[.!?] +\b(\w+ \w+), (\w+ \w+), and (\w+ \w+) +``` + +Triage: keep the strongest item, cut the rest — or keep all three only if each carries distinct information, and then break the rhythm. + +## 5. Punctuation and formatting + +Em dash: not banned — humans use it. Findings are about **density** and the contrast move: + +- More than ~1 em dash per 150 words. +- Two em dashes in one sentence. +- `— not X, but Y` (already in section 1). +- Em dash used for punchy emphasis where a comma works: `[a-z] — [a-z][^—]{1,25}\.$` + +Other formatting tells (check by hand; most regexes here are layout-dependent): + +- **Bold scattered through prose** like a textbook highlighting itself: `\*\*[^*]{2,40}\*\*` appearing more than ~once per 3 paragraphs of body prose. +- **"Term: definition" bullets**: `^[-*] +\*\*[^*]+:?\*\*:? ` — the signature LLM list shape. +- **Emoji headers/bullets** (🚀, ✅, 💡): needs PCRE, not `-E` — `LC_ALL=C.UTF-8 grep -Pn '^\s*[-*#]+\s.*[\x{1F300}-\x{1FAFF}\x{2600}-\x{27BF}]' draft.txt`. +- **Headers on short texts** — section headers on anything under ~400 words. +- **The tidy skeleton** — intro that previews three points, three matched sections, conclusion that restates them. Resolves too neatly; real writing has loose ends. +- **Numbered lists where a paragraph would do.** +- Curly quotes/apostrophes in a context where the author types straight ones (mixed within one text is the stronger tell). + +## 6. Cadence and statistical shape + +No regex; measure or eyeball. + +- **Uniform sentence length** (the single strongest current tell): a run of 3+ consecutive sentences within ±4 words of each other, paragraph after paragraph of 18–24-word sentences. Quick measurement on a file: + + ```bash + tr '\n' ' ' < draft.txt | sed 's/[.!?] /\n/g' | awk '{print NF}' + ``` + + Human prose mixes 4-word sentences with 30-word sentences. Variance should be obvious at a glance. +- **Uniform sentence shape**: every sentence opens subject-first; no fragments, no questions, no inversions. +- **Uniform paragraph length**: every paragraph 3–4 sentences. +- **Low specificity**: "many companies", "studies show", "experts agree", "recent research", "various factors" — generic where a human who knew the material would name names, numbers, dates. (Fix only with real specifics; never invented ones.) +- **No friction**: nothing colloquial, no aside, no opinion held without a softener, nothing that risks being disagreed with. + +## 7. Genre-specific instant tells + +Covered in detail in [voices.md](voices.md); the headline items: + +- **Reddit/forums**: bold mid-comment, bullet-pointed comments, "Hope this helps!", perfectly balanced takes. +- **Tweets/X**: "🧵", "Let that sink in", line-broken one-clause-per-line cadence, ending on a question to drive engagement. +- **LinkedIn**: one-sentence paragraphs stacked vertically, "Agree?", the not-X-but-Y move (its natural habitat). +- **Academic**: "delve", "novel insights", puffed significance claims ("crucial implications for the field"), citation-free superlatives. +- **Email**: "I hope this email finds you well", restating the recipient's question back at them, three-paragraph symmetry for a one-line answer. diff --git a/.agents/skills/fuck-slop/references/voices.md b/.agents/skills/fuck-slop/references/voices.md new file mode 100644 index 0000000..4e99fe3 --- /dev/null +++ b/.agents/skills/fuck-slop/references/voices.md @@ -0,0 +1,61 @@ +# Register Guide + +What "good" means per genre, what tells are fatal there, and what the de-slopped text should sound like. Use in Phase 0 (fix the target) and Phase 4 (register check). Two universal rules first: + +1. **Voice comes from commitment, not decoration.** A text sounds human when it asserts specific things a specific person believes, at the level of detail only someone who did the work would know. Slang, typos, and "personality" sprinkled on top do not produce this and read as humanizer-tool output. +2. **Match the author, not a persona.** If the user supplied earlier writing or a draft with their own phrasing in it, keep their words wherever they survive the scan. De-slopping someone into a generic "casual" voice is just different slop. + +## Academic article / paper + +- **Goal**: precise claims, honest hedges, dense information. Formality stays; puffery goes. +- **Fatal tells here**: "delve", "novel", inflated significance ("crucial implications", "paradigm shift"), rule-of-three in abstracts, negative parallelism in intros ("X is not merely a tool but a fundamental…"), em-dash chains. +- **De-slop moves**: replace significance puffery with the actual finding and effect size. Hedges must be calibrated, not reflexive — "may" because the evidence is genuinely uncertain, not as seasoning. Keep passive voice where the venue expects it; do not inject first person or attitude. Numbers, conditions, and citations beat adjectives. +- **Cadence**: long sentences are fine and normal; the tell is uniformity, not length. Vary clause structure. + +## Tweet / X post + +- **Goal**: one idea, said like a person, under the limit. +- **Fatal tells here**: "🧵", "Let that sink in", "Read that again", one-clause-per-line stacking, ending on an engagement question, hashtag clusters, the not-X-but-Y move compressed into 200 characters. +- **De-slop moves**: cut to the single claim. Lowercase is fine if that's the author's habit. No setup ("Hot take:") — just the take. A tweet that states an opinion without insurance reads human; a tweet that balances itself does not. + +## Reddit post / comment + +- **Goal**: reads like a knowledgeable person typing in a text box, because that's what reddit is. +- **Fatal tells here** (reddit users are the most slop-sensitive audience on the internet): **any** bold in a comment, bullet-point essays, headers, "Hope this helps!", "Great question!", symmetric pro/con framing, em-dash density, perfect paragraphing. +- **De-slop moves**: plain paragraphs, contractions, direct answers first. Mild hedges are human here ("iirc", "I might be wrong but") — but only the author's own. Concrete personal detail ("ran into this on a 2019 Outback") is the strongest human marker; never fabricate it, ask the author or drop it. + +## LinkedIn post + +- **Goal**: professional but specific. The platform's native style is so slop-adjacent that the bar is: would a colleague forward this without cringing? +- **Fatal tells here**: stacked one-line paragraphs, "Agree?", "Let's connect", broetry rhythm, negative parallelism (this is its natural habitat — scan twice), rule-of-three value statements, "I'm humbled to announce". +- **De-slop moves**: write actual paragraphs. Lead with the concrete event or number, not the lesson. One lesson max, stated once, not echoed in a closer. + +## Email + +- **Goal**: shortest text that's still warm enough for the relationship. +- **Fatal tells here**: "I hope this email finds you well", restating the recipient's email back to them, three symmetric paragraphs wrapping a one-line answer, "Please don't hesitate to reach out". +- **De-slop moves**: answer in the first sentence. Greeting and sign-off match the existing thread's register. Cut every sentence whose only job is politeness padding except one, if the relationship needs it. + +## Blog post / newsletter / essay + +- **Goal**: a person with a view, walking the reader through it. +- **Fatal tells here**: "In today's fast-paced world" openers, intro-that-previews-three-sections skeleton, "In conclusion", bold-scattered prose, section headers every two paragraphs, engagement-bait closers. +- **De-slop moves**: open inside the subject (a scene, a number, a claim). Let structure follow the argument instead of a template — real essays have asymmetric sections and loose ends. First person and digressions are allowed; they are how essays sound human. Keep headers only when the piece is long enough to need navigation. + +## Marketing / landing copy + +- **Goal**: concrete benefit, named audience, zero filler. +- **Fatal tells here**: "seamless", "unlock", "empower", "game-changing", "effortless", rule-of-three feature triplets, false ranges ("from startups to enterprises"), every header a not-X-but-Y. +- **De-slop moves**: replace each abstraction with the mechanism or the number ("Set up in 4 minutes" beats "seamless onboarding"). One verb per claim. Specificity is the whole game; if no specifics exist, that's a product-marketing problem the text can't fix — say so. + +## Technical docs / README + +- **Goal**: the reader gets unblocked fast. +- **Fatal tells here**: "robust", "powerful", "blazingly fast" without benchmarks, "simply"/"just" before steps that aren't, marketing voice in reference material, emoji section headers. +- **De-slop moves**: imperative mood, exact commands, exact versions, expected output. Adjectives almost to zero. Lists are fine here — docs are the one genre where "Term: definition" bullets are legitimate structure, so don't strip them; strip the puffery inside them. + +## Academic-adjacent: cover letters, statements, grant prose + +- **Goal**: claims about the author backed by evidence, in formal register. +- **Fatal tells here**: "passionate", "deeply committed", "unique perspective", testament/tapestry vocabulary, rule-of-three trait lists, every paragraph ending with a not-X-but-Y synthesis. +- **De-slop moves**: every trait claim becomes an event ("I led X, which produced Y"). Keep formality; cut self-puffery. The reader has read ten thousand of these — only specifics differentiate. diff --git a/.agents/skills/grill-me/SKILL.md b/.agents/skills/grill-me/SKILL.md new file mode 100644 index 0000000..86c30da --- /dev/null +++ b/.agents/skills/grill-me/SKILL.md @@ -0,0 +1,209 @@ +--- +name: grill-me +description: Calibrated grilling session for stress-testing a plan, design, idea, or decision. First assesses the user's topic knowledge, confidence, and desired pressure level, then asks one question at a time with recommended answers. Use when user says "grill me", "stress-test this", "challenge my plan", "interview me", or wants a plan probed without being overwhelmed. +--- + +# Grill Me + +Interview the user until the plan is clear, defensible, and ready for action. + +This is not hostile debate. It is calibrated pressure. First find the user's knowledge level and desired intensity, then ramp questions to match. + +## Core Rules + +- Ask one question at a time. +- Give a recommended answer for every question. +- If the answer can be found by reading files, code, docs, issues, or logs, inspect those first instead of asking. +- Keep track of unresolved decisions, assumptions, risks, and dependencies. +- Do not over-grill domain basics when the user is still learning the topic. Teach the missing frame briefly, then ask the next useful question. +- Do not under-grill confident experts. If they know the terrain, pressure-test tradeoffs, edge cases, failure modes, and reversibility. +- Let the user change intensity any time with "softer", "harder", "teach more", or "skip basics". + +## Phase 1: Frame The Target + +Identify what should be grilled before asking about comfort. If the topic is not clear, ask: + +> What plan, design, or decision should I grill? +> +> Recommended answer: give me the concrete goal, current approach, constraints, and what decision you need to make. + +If context already contains the plan, summarize it in 3-6 bullets and ask for correction: + +> I think target is: [...] +> +> Recommended answer: "Yes, grill that" or "Adjust: ..." + +## Phase 2: Calibration + +Before grilling the topic, ask a short calibration question unless the user's level is already obvious from context. + +Ask: + +> Before I grill the plan: what is your current comfort with this topic, and how hard do you want the pressure? +> +> Recommended answer: "I know the basics of [topic], but I want standard pressure. Explain missing concepts briefly, then keep pushing." + +Use the user's answer to set two dials: + +### Knowledge Level + +- **New** - user lacks core vocabulary or model of the domain. +- **Working** - user understands basics and can discuss tradeoffs. +- **Expert** - user knows domain deeply and wants sharper critique. + +### Pressure Level + +- **Light** - clarify goals, constraints, and missing context. +- **Standard** - challenge assumptions, tradeoffs, and execution path. +- **Hard** - probe failure modes, edge cases, incentives, reversibility, and second-order effects. + +If the user does not answer calibration, default to: + +- Knowledge: **Working** +- Pressure: **Standard** + +## Phase 3: Build The Decision Map + +Create a private decision map while asking questions one at a time: + +- Goal - what success means. +- User or customer - who this affects. +- Constraints - time, money, stack, team, policy, risk. +- Options - obvious alternatives and why current option wins. +- Dependencies - what must be true first. +- Risks - what breaks, gets expensive, or becomes irreversible. +- Validation - how user will know it worked. +- Rollback - how to undo or recover. + +Do not dump the full map unless user asks. Use it to choose the next question. + +## Phase 4: Question Ladder + +Move through this ladder. Stop early if the plan becomes clear enough or user asks to stop. + +### 1. Goal Fit + +Questions: + +- What outcome matters most? +- What would make this not worth doing? +- What problem are we solving, and for whom? + +### 2. Constraint Reality + +Questions: + +- What hard constraint cannot move? +- What resource bottleneck decides the plan? +- What assumption would kill the plan if false? + +### 3. Option Pressure + +Questions: + +- What are the top two alternatives? +- Why this approach over the boring one? +- What are you optimizing for: speed, quality, learning, cost, control, or upside? + +### 4. Execution Path + +Questions: + +- What is the smallest useful version? +- What has to happen first? +- What can be deferred without harming the goal? + +### 5. Failure Modes + +Questions: + +- How does this fail in production or real use? +- What edge case would embarrass the plan? +- What part is hardest to observe once it breaks? + +### 6. Validation + +Questions: + +- What test, metric, screenshot, demo, or user behavior proves this works? +- What would you check before trusting it? +- What does done mean in observable terms? + +### 7. Reversibility + +Questions: + +- What decision here is hardest to undo? +- What backup, migration, rollback, or escape hatch exists? +- What should be logged as an ADR or explicit tradeoff? + +## Pressure Adaptation + +### If Knowledge Is New + +- Define one missing concept in 2-4 sentences before asking. +- Avoid jargon unless you define it. +- Ask fewer branching questions. +- Focus on goals, constraints, and first principles. +- Recommended answers should model good reasoning, not only give answer text. + +### If Knowledge Is Working + +- Ask normal tradeoff questions. +- Surface alternatives. +- Push for validation and smallest useful version. +- Challenge vague words like "simple", "scalable", "good", "clean", or "fast". + +### If Knowledge Is Expert + +- Skip basics. +- Ask sharper counterfactuals. +- Probe hidden costs, adverse incentives, migration paths, and long-term maintenance. +- Ask what evidence would change their mind. + +### If Pressure Is Light + +- Keep questions clarifying. +- Use supportive framing. +- Stop after top ambiguities are resolved. + +### If Pressure Is Standard + +- Challenge assumptions and tradeoffs. +- Keep moving until implementation path is concrete. + +### If Pressure Is Hard + +- Be direct. +- Name weak reasoning. +- Ask about unpleasant edge cases. +- Demand observable validation. +- Still ask one question at a time. + +## Recommended Answer Format + +Every question includes: + +```text +Question: ... +Recommended answer: ... +Why it matters: ... +``` + +Keep "Why it matters" to one sentence. + +## When To Stop + +Stop grilling when one of these is true: + +- User says stop. +- Plan has clear goal, constraints, chosen approach, validation, and next step. +- Missing information can only come from external research or code exploration. +- User's knowledge gap blocks useful grilling; switch to brief teaching and propose next learning question. + +End with: + +- Final decision or current best plan. +- Remaining open questions. +- Next concrete action. +- Risks to watch. diff --git a/.agents/skills/interface-kit/SKILL.md b/.agents/skills/interface-kit/SKILL.md new file mode 100644 index 0000000..621f732 --- /dev/null +++ b/.agents/skills/interface-kit/SKILL.md @@ -0,0 +1,582 @@ +--- +name: interface-kit +description: | + Authoritative guide for implementing stunning, accessible, performant UI. Synthesizes + design engineering philosophy, accessibility standards, animation principles, spatial design, + typography, color systems, and component craft into a single actionable reference. + Complements the design-system skill (which covers DESIGN.md spec writing) by covering + the HOW of implementation. + Trigger phrases: "build UI", "create component", "landing page", "make it look good", + "frontend", "design", "polish UI", "implement design", "make it beautiful", + "UI implementation", "component styling", "animation", "accessibility" +--- + +# Interface Kit: Implementation Guide for Exceptional Interfaces + +> If a DESIGN.md exists at the project root, its tokens and specifications override all defaults in this skill. This skill provides sensible defaults for when no design system exists, and implementation guidance that applies regardless. + +> For deep dives on any section, see the reference files in this skill's `references/` directory. + +--- + +## 1. Core Philosophy + +Taste is trained, not innate. Study why great interfaces feel right. Deconstruct apps you admire — the spacing, the timing, the weight of a shadow. The gap between "fine" and "exceptional" is built from hundreds of micro-decisions that users feel but never consciously notice. + +**Unseen details compound.** A single rounded corner, a single eased transition, a single well-chosen shadow — none of these matter alone. Together they become "a thousand barely audible voices singing in tune." The cumulative effect is what separates craft from output. + +**Beauty is leverage.** Polish is not vanity. Good defaults, considered typography, and intentional motion are real differentiators. Users trust interfaces that feel cared for. Investors notice. Competitors can't easily replicate taste. + +**Intentionality over intensity.** Both bold maximalism and refined minimalism work — what fails is the absence of a clear point of view. Every visual decision should trace back to a deliberate conceptual direction. If you can't articulate WHY a choice was made, reconsider it. + +**Choose a direction and execute with precision.** Don't hedge between styles. A brutalist page committed fully will always outperform a page that's "a little bit of everything." Commit, then refine. + +**NEVER produce generic "AI slop" aesthetics.** No gratuitous gradients on white backgrounds. No cookie-cutter hero sections with stock illustrations. No safe, forgettable layouts that could belong to any product. Every interface should have a point of view that makes it recognizable. + +--- + +## 2. The Priority Stack + +When implementing UI, work through these priorities in order. Higher priorities are non-negotiable; lower priorities are polish that compounds quality. + +| Priority | Level | What It Means | +|----------|-------|---------------| +| **Accessibility** | CRITICAL | Contrast 4.5:1, keyboard nav, ARIA semantics, visible focus rings. Ship nothing that excludes users. | +| **Performance** | HIGH | WebP/AVIF images, lazy loading below fold, CLS < 0.1, transform-only animations on the compositor thread. | +| **Typography** | HIGH | Font smoothing, text-wrap balance/pretty, tabular-nums for data, 65ch max line length. | +| **Layout & Spatial** | HIGH | 4/8px grid, concentric border radius, optical alignment over geometric. | +| **Color & Theme** | MEDIUM | HSL custom properties, semantic tokens, dark mode pairs tested separately. | +| **Motion & Interaction** | MEDIUM | Frequency-based animation decisions, 150-300ms durations, ease-out default. | +| **Polish & Details** | LOW | Layered shadows over borders, press feedback on buttons, staggered enter animations. | + +Never skip a CRITICAL/HIGH item to chase a LOW item. A beautifully animated button that fails keyboard navigation is a net negative. + +--- + +## 3. Aesthetic Direction + +Before writing a single line of CSS, commit to a bold aesthetic direction. The most common failure mode in AI-generated UI is convergence on the same safe, forgettable look. + +### Pick a Tone + +Choose one and commit fully: + +- **Brutally minimal** — generous whitespace, monospace type, stark contrast, near-zero decoration +- **Maximalist chaos** — layered textures, clashing type scales, dense information, intentional visual noise +- **Retro-futuristic** — CRT glow effects, monospace terminals, scan lines, neon on dark +- **Organic / natural** — earth tones, rounded shapes, paper textures, hand-drawn accents +- **Luxury / refined** — serif headlines, muted palettes, ample negative space, subtle gold or cream accents +- **Editorial / magazine** — dramatic type hierarchy, full-bleed imagery, grid-breaking layouts +- **Playful / bold** — bright primaries, chunky borders, exaggerated shadows, bouncy motion + +### Match Complexity to Vision + +Maximalist design demands elaborate code — layered backgrounds, complex grid structures, multiple font stacks. Minimalist design demands surgical precision — every pixel of spacing matters more when there's nothing to hide behind. + +### The Ban List (When No DESIGN.md Exists) + +When building without an existing design system, avoid these overused defaults that signal "AI-generated": + +- **Fonts**: Inter, Roboto, Arial, system-ui as display fonts, Space Grotesk +- **Colors**: Purple-to-blue gradients on white backgrounds +- **Patterns**: Generic hero with centered text + CTA + stock illustration + +Vary between light and dark themes, different font pairings, different aesthetic directions. Never converge on the same choices across projects. + +### Visual Texture + +Add depth through: gradient meshes, noise/grain overlays (`filter: url(#noise)`), layered transparencies, subtle background patterns, duotone image treatments. + +**DESIGN.md overrides this entire section.** If DESIGN.md specifies Inter, use Inter. If it specifies purple gradients, use them. The ban list only applies when no design system exists and you're making aesthetic choices from scratch. + +--- + +## 4. Typography Essentials + +Typography is the single highest-leverage design element. Get it right and mediocre layouts still feel good. Get it wrong and nothing else saves it. + +### Root Setup + +```css +html { + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + text-rendering: optimizeLegibility; +} +``` + +Apply font smoothing to the root layout. On macOS, the default sub-pixel rendering makes text appear heavier than the designer intended. + +### Text Wrapping + +```css +h1, h2, h3, h4, h5, h6 { + text-wrap: balance; +} + +p, li, dd, blockquote { + text-wrap: pretty; +} +``` + +`balance` distributes heading lines evenly. `pretty` avoids orphaned words in body text. + +### Numeric Display + +```css +.data-value, .price, .counter, [data-numeric] { + font-variant-numeric: tabular-nums; +} +``` + +Use `tabular-nums` for any number that updates dynamically — prices, counters, table columns. Without it, layout shifts as digit widths change. + +### Scale and Rhythm + +- **Base size**: 16px minimum for body text. Never go below 14px for any readable content. +- **Line height**: 1.5-1.75 for body text, 1.1-1.3 for large headings. +- **Max line length**: `max-width: 65ch` for body text. Long lines destroy readability. +- **Type scale**: Pick a consistent scale and stick to it: 12 / 14 / 16 / 18 / 24 / 32 / 48 / 64. + +### Font Pairing + +Pair a distinctive display font with a refined body font. The display font carries personality; the body font carries readability. Use `font-weight` for hierarchy within a family: + +- **Headings**: 600-700 (semibold to bold) +- **Body**: 400 (regular) +- **Labels / UI**: 500 (medium) + +Always include font stack fallbacks: + +```css +--font-display: "Instrument Serif", "Georgia", serif; +--font-body: "Söhne", "Helvetica Neue", sans-serif; +--font-mono: "JetBrains Mono", "Fira Code", monospace; +``` + +--- + +## 5. Color & Theme + +### HSL Custom Properties (shadcn Pattern) + +```css +:root { + --background: 0 0% 100%; + --foreground: 222.2 84% 4.9%; + --primary: 222.2 47.4% 11.2%; + --primary-foreground: 210 40% 98%; + --secondary: 210 40% 96.1%; + --secondary-foreground: 222.2 47.4% 11.2%; + --muted: 210 40% 96.1%; + --muted-foreground: 215.4 16.3% 46.9%; + --accent: 210 40% 96.1%; + --accent-foreground: 222.2 47.4% 11.2%; + --destructive: 0 84.2% 60.2%; + --destructive-foreground: 210 40% 98%; + --border: 214.3 31.8% 91.4%; + --ring: 222.2 84% 4.9%; + --radius: 0.5rem; +} +``` + +Define semantic tokens: primary, secondary, destructive, muted, accent, background, foreground. Reference colors by semantic name — never hardcode hex values in components. + +### Dark Mode + +```css +.dark { + --background: 222.2 84% 4.9%; + --foreground: 210 40% 98%; + /* ... desaturated, lighter tonal variants — NOT simply inverted */ +} +``` + +Dark mode is not "invert colors." Use desaturated, lighter tonal variants. Backgrounds go dark but not pure black (`#000`). Text goes light but not pure white (`#fff`). Test contrast separately for dark mode — what passes in light may fail in dark. + +### Contrast Requirements + +- **WCAG AA minimum**: 4.5:1 for normal text, 3:1 for large text (18px+ bold or 24px+ regular) +- Never convey information by color alone — always pair with an icon, label, or pattern +- Test with browser devtools contrast checker or axe-core + +### Color Confidence + +Dominant colors with sharp accents outperform timid, evenly-distributed palettes. Pick one or two hero colors and let the rest of the palette recede. A confident palette has clear hierarchy; an uncertain palette spreads color evenly and feels flat. + +--- + +## 6. Spatial Design + +### Concentric Border Radius + +This is the single most common thing that makes nested UI elements feel "off": + +``` +outer_radius = inner_radius + padding +``` + +```css +/* Correct: concentric */ +.card { border-radius: 16px; padding: 8px; } +.card-inner { border-radius: 8px; } /* 16 - 8 = 8 */ + +/* Wrong: same radius on parent and child */ +.card { border-radius: 12px; } +.card-inner { border-radius: 12px; } /* Looks bloated */ +``` + +When geometric centering looks off, align optically. Play/pause icons, dropdown carets, and asymmetric glyphs often need 1-2px manual nudges to look centered. + +### Shadows Over Borders + +Layer multiple transparent `box-shadow` values for natural depth instead of using borders: + +```css +.elevated { + box-shadow: + 0 1px 2px rgba(0, 0, 0, 0.04), + 0 2px 4px rgba(0, 0, 0, 0.04), + 0 4px 8px rgba(0, 0, 0, 0.04); +} +``` + +Multiple shadows at different spreads mimic how light works. A single hard shadow looks artificial. + +### Image Outlines + +Add a subtle inset outline to images and media for consistent depth against varied backgrounds: + +```css +img, video { + outline: 1px solid rgba(0, 0, 0, 0.06); + outline-offset: -1px; +} +``` + +### Spacing Scale + +Use a 4px / 8px base incremental system. Every spacing value should be a multiple of 4: + +`4 / 8 / 12 / 16 / 24 / 32 / 48 / 64 / 96 / 128` + +### Hit Areas + +Minimum 44x44px for all interactive elements. If the visual element is smaller, extend the hit area with a pseudo-element: + +```css +.small-button::before { + content: ""; + position: absolute; + inset: -8px; +} +``` + +### Z-Index Scale + +Define a layered scale and never use arbitrary values: + +```css +--z-base: 0; +--z-dropdown: 10; +--z-sticky: 20; +--z-overlay: 40; +--z-modal: 100; +--z-toast: 1000; +``` + +--- + +## 7. Motion & Interaction + +### The Frequency-Based Decision Framework + +This is the most important mental model for animation decisions: + +| Frequency | Examples | Animation | +|-----------|----------|-----------| +| **100+ times/day** | Keyboard shortcuts, command palette actions, tab switches | **None.** Zero animation. Instant. | +| **Tens of times/day** | Hover effects, list item navigation, toggles | **Remove or drastically reduce.** 50-100ms max. | +| **Occasional** | Modals, drawers, toasts, page transitions | **Standard animation.** 150-300ms. | +| **Rare / first-time** | Onboarding, celebrations, empty states | **Can add delight.** 300-500ms, more elaborate. | + +High-frequency animations feel sluggish. Low-frequency animations without motion feel jarring. Match the animation budget to usage frequency. + +### Custom Easing Curves + +Built-in CSS easings (`ease`, `ease-in-out`) are too weak. Define custom curves: + +```css +:root { + --ease-out: cubic-bezier(0.23, 1, 0.32, 1); + --ease-in-out: cubic-bezier(0.77, 0, 0.175, 1); + --ease-drawer: cubic-bezier(0.32, 0.72, 0, 1); + --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1); +} +``` + +### Duration Guide + +| Element | Duration | +|---------|----------| +| Buttons, toggles | 100-160ms | +| Tooltips | 125-200ms | +| Dropdowns, popovers | 150-250ms | +| Modals, drawers | 200-500ms | +| Page transitions | 250-400ms | + +UI animations should stay under 300ms. Never use `ease-in` for UI animations — it front-loads the pause and feels sluggish. + +### Enter/Exit Asymmetry + +Exits should be softer and faster than enters. An enter animation at 250ms should have its exit at 150-200ms. + +### Split and Stagger Enter Animations + +When multiple elements enter the viewport, stagger them by semantic chunks with ~50-100ms delay: + +```css +.stagger-item { + animation: fadeSlideIn 300ms var(--ease-out) both; +} +.stagger-item:nth-child(1) { animation-delay: 0ms; } +.stagger-item:nth-child(2) { animation-delay: 60ms; } +.stagger-item:nth-child(3) { animation-delay: 120ms; } +``` + +### Scale Animations + +Never animate from `scale(0)`. Start from `scale(0.9)` or higher, combined with opacity: + +```css +@keyframes scaleIn { + from { opacity: 0; transform: scale(0.95); } + to { opacity: 1; transform: scale(1); } +} +``` + +### Press Feedback + +Every pressable element should scale down slightly on `:active`: + +```css +button:active { + transform: scale(0.97); +} +``` + +### Interruptibility + +Use CSS transitions (not keyframe animations) for interactive state changes. Transitions can be interrupted mid-way; keyframes cannot. This matters for hover states, toggles, and any element the user might interact with rapidly. + +### Popover Origin + +Make popovers transform-origin aware — they should grow from their trigger element, not from center. Exception: modals always originate from center. + +### Tooltip Hover Delay + +Skip the tooltip delay on subsequent hovers. If the user has already waited for one tooltip, show the next one immediately. + +### Reduced Motion + +```css +@media (prefers-reduced-motion: reduce) { + *, *::before, *::after { + animation-duration: 0.01ms !important; + transition-duration: 0.01ms !important; + } +} +``` + +Respect `prefers-reduced-motion`. Reduce animations — don't eliminate opacity and color transitions entirely, as those provide important feedback. + +### Hover Gate + +Gate hover animations behind a media query so touch devices don't trigger stuck hover states: + +```css +@media (hover: hover) and (pointer: fine) { + .card:hover { transform: translateY(-2px); } +} +``` + +> Reference `references/animation-playbook.md` for deep dives on spring physics, gesture-driven animation, and complex choreography. + +--- + +## 8. Component Craft + +### Primitives + +Use Radix UI primitives for accessible, unstyled foundations. Use CVA (class-variance-authority) for type-safe component variants: + +```tsx +import { cva } from "class-variance-authority"; + +const buttonVariants = cva( + "inline-flex items-center justify-center rounded-md font-medium transition-colors focus-visible:outline-none focus-visible:ring-2", + { + variants: { + variant: { + default: "bg-primary text-primary-foreground hover:bg-primary/90", + destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90", + outline: "border border-input hover:bg-accent hover:text-accent-foreground", + ghost: "hover:bg-accent hover:text-accent-foreground", + }, + size: { + sm: "h-9 px-3 text-sm", + default: "h-10 px-4 py-2", + lg: "h-11 px-8 text-lg", + }, + }, + defaultVariants: { variant: "default", size: "default" }, + } +); +``` + +### Button + +- Scale on press (`transform: scale(0.97)` on `:active`) +- Visible focus ring (never `outline: none` without replacement) +- Loading state with spinner replacing label, maintaining button dimensions +- Disabled state at `opacity: 0.5` with `pointer-events: none` + +### Card + +- Concentric border radius between card and inner elements +- Layered shadows (not borders) for depth +- Hover state: subtle elevation change (`translateY(-1px)` + shadow increase) + +### Dialog / Modal + +- Focus trap (keyboard cannot escape to elements behind) +- ESC to close, click outside overlay to close +- `transform-origin: center`, fade + scale enter animation +- `aria-modal="true"`, `role="dialog"`, `aria-labelledby` + +### Form + +- Visible labels always — never placeholder-only inputs +- Error messages near the field with `aria-live="polite"` for screen readers +- Progressive disclosure: show advanced fields only when needed +- Use React Hook Form + Zod for validation + +### Theming + +Use shadcn CSS variable pattern (HSL format) for all component colors. Wrap client-interactive components in server components for Next.js App Router compatibility. + +> Reference `references/component-patterns.md` for the full component catalog with copy-paste implementations. + +--- + +## 9. Accessibility Essentials + +### Semantic HTML First + +Use `` +- `aria-labelledby` to associate headings with sections +- `aria-describedby` to link help text or error messages to inputs +- `aria-live="polite"` for dynamic content updates (toast messages, form errors) +- `aria-hidden="true"` for decorative elements (icons next to text labels) +- `aria-expanded` for toggleable elements (dropdowns, accordions) + +### Color and Contrast + +- WCAG AA: 4.5:1 for normal text, 3:1 for large text +- Never use color as the sole indicator — pair with icons, text, or patterns +- Test in both light and dark modes + +### Images and Media + +- Descriptive `alt` text for meaningful images: `alt="Dashboard showing 23% revenue growth"` +- Empty `alt=""` for purely decorative images +- Captions for video, transcripts for audio + +### Navigation Aids + +- **Skip link**: first focusable element, hidden until focused: + +```html + + Skip to main content + +``` + +- **Heading hierarchy**: sequential h1 through h6, no level skips. One `

` per page. + +### Touch Targets + +- Minimum 44x44px interactive area +- 8px minimum spacing between adjacent touch targets +- Extend small visual elements with invisible padding or pseudo-elements + +### Testing + +- **Automated**: axe-core in CI, Lighthouse accessibility score 90+ +- **Manual**: full keyboard-only navigation test +- **Screen reader**: test with VoiceOver (macOS) or NVDA (Windows) +- **Visual**: zoom to 200%, check nothing breaks or overlaps + +> Reference `references/accessibility-checklist.md` for the full audit guide with pass/fail criteria. + +--- + +## 10. Pre-Delivery Review + +Run through this checklist before considering any UI implementation complete: + +### Typography +- [ ] Font smoothing applied (`-webkit-font-smoothing: antialiased`) +- [ ] Headings use `text-wrap: balance` +- [ ] Dynamic numbers use `font-variant-numeric: tabular-nums` + +### Color +- [ ] All colors referenced via semantic tokens, no hardcoded hex in components +- [ ] Color contrast meets WCAG AA (4.5:1 normal text, 3:1 large text) +- [ ] Dark mode tested separately for contrast + +### Spatial +- [ ] Nested rounded elements use concentric border radius +- [ ] Spacing follows 4px / 8px scale consistently +- [ ] Interactive elements have 44x44px minimum hit area +- [ ] Shadows used instead of borders where appropriate + +### Motion +- [ ] Animation frequency matches usage frequency (no animation on high-frequency actions) +- [ ] No `transition: all` anywhere — specific properties only +- [ ] Enter animations split and staggered where multiple elements appear +- [ ] `prefers-reduced-motion` respected + +### Accessibility +- [ ] All interactive elements keyboard accessible +- [ ] Focus rings visible on keyboard navigation (never `outline: none` without replacement) +- [ ] Semantic HTML used before ARIA +- [ ] `aria-live` on dynamic content updates + +> Reference `references/review-checklist.md` for the extended 30-item checklist with severity ratings and automated testing commands. diff --git a/.agents/skills/interface-kit/references/accessibility-checklist.md b/.agents/skills/interface-kit/references/accessibility-checklist.md new file mode 100644 index 0000000..d576ac5 --- /dev/null +++ b/.agents/skills/interface-kit/references/accessibility-checklist.md @@ -0,0 +1,425 @@ +# WCAG 2.1 AA Accessibility Audit Guide + +Comprehensive checklist for building accessible web interfaces. Every requirement maps to WCAG 2.1 Level AA success criteria. + +--- + +## 1. Semantic HTML Priority + +ALWAYS use semantic HTML before reaching for ARIA. Native elements carry built-in keyboard behavior, focus management, and screen reader announcements that ARIA can only approximate. + +### Element Selection Rules + +| Instead of | Use | +|---|---| +| `
` | `