Custom Color Palette
Why this exists
Left unspecified, AI-generated decks and documents default to the Tailwind CSS swatch set, and — worse — assign a different hue to every section or category (blue for one row, green for another, orange for a third). That rainbow-coded, default-blue-and-green look is the fastest way for a viewer to tell a document was AI-made. The fix: use ONE dominant hue family for the entire document, and differentiate sections by lightness/tint, not by switching hues.
Core rule to apply in every case below:
Use a single dominant color family for the whole document. Differentiate sections by lightness, not hue. Avoid the default Tailwind palette and avoid assigning a unique bright color per category — that pattern reads as AI-generated.
Checking contrast without guessing
"Dark enough for white text" and "≥4.5:1 contrast" aren't things to eyeball. Use this approximation: convert the hex to HSL and look at lightness (L).
- L below ~50% → safe for white/light text on top, treat as a dark-text/header candidate.
- L above ~55% → too light for white text; darken the same hue (reduce L, keep H and S) until L drops below 50% before using it for text or headers.
- L between 50-55% → borderline; darken slightly rather than risk it.
This is an approximation, not a WCAG-exact calculation, but it's specific enough to apply consistently instead of relying on visual judgement.
Exception: semantic/status indicators (red = at risk, green = on track, amber = caution) may use distinct, muted/desaturated colors. Everything else stays within the single hue family.
Step -2 — Check for a saved magic word first
Before anything else — before Step -1 — check references/named-palettes.md
for a saved magic word in the user's current message (e.g. "generate alpha,"
"make a deck, use ocean"). If found, apply that palette's saved hex table
directly and skip straight to Step 1 (format) then Step 3 (apply) — no
standing-preference check, no ask flow. If the word given doesn't match any
saved entry, continue to Step -1 as normal.
Step -1 — Check standing preferences first
Before anything else, check references/preferences.md for any standing
instructions the user has previously given (e.g. "always use the Forest
Professional palette," "stop asking me, just default to neutral," "our brand
color is always #0057B8"). If a standing preference exists and covers the
current request, apply it directly and skip the steps it makes redundant
(e.g. skip Step 2's question entirely if a standing palette preference is
recorded).
Whenever the user gives a new standing instruction (phrases like "always
use...", "from now on...", "remember that...", "stop asking and just..."),
add or update the relevant line in references/preferences.md so it persists
for future requests — don't just apply it once and let it be forgotten. Keep
entries short and specific (e.g. "Standing palette: Forest Professional,
apply without asking" or "Standing brand color: primary #0057B8, no
secondary"). If no such file exists yet, create it.
If the user's current message overrides a standing preference just for this one request (e.g. "just this once, use Steel Blue instead"), apply the one-off override without editing the standing preference file.
If the user gives a new color instruction without any standing language
(e.g. just "use #0057B8" or "use Steel Blue" with no "always"/"from now on"/
"remember" attached) — treat it as one-off by default. Apply it to the
current request only, and do NOT overwrite references/preferences.md,
even if a standing preference already exists there. Never silently replace a
recorded standing preference based on an ambiguous one-time-sounding request;
only update the file when the standing language is explicit.
After applying a one-off color instruction, briefly ask (as part of the
Step 3 confirmation, not a separate interruption) whether it should be saved
as a standing preference — e.g. "Applied #0057B8 for this one — want me to
remember it as your default going forward?" If the user says yes (now, or
later in the conversation, e.g. "actually yes, save that" or "add it to
memory"), update references/preferences.md at that point, even though it
wasn't saved automatically at the time.
Scope boundary: this skill and references/preferences.md are for color
palette instructions only — this includes font color, header/text color,
accent color, fill color, and border color, since those are all "color."
It does NOT include layout or structural instructions — e.g. "always add a
header and footer to Word docs," "always include a table of contents,"
"always use 11pt font size" — those are formatting/layout, not color, even
though they're both "standing preferences" in a general sense. Recognize
layout/structural asks as out of scope, don't record them here, and handle
them as a general document-formatting request instead (or point out that
it's a separate preference to track elsewhere, e.g. in Claude's own memory
system or a different skill). A "change the font color to X" instruction,
by contrast, belongs here and should be recorded the same way any other
standing color preference would be.
Step 0 — Override (skip this skill entirely)
If the user explicitly says something like "just generate it," "skip the color question," "don't ask about palette," "no need for colors," or any clear signal they want to bypass this process for the current request — do not ask anything from Step 2, do not apply any palette logic, and proceed with default/unstyled generation as if this skill did not exist. This override applies only to the current request; the skill still triggers normally on the next document/deck/spreadsheet request unless overridden again.
Step 1 — Determine the format
Identify which output is being created: PowerPoint/HTML artifact, Word (.docx),
or Excel (.xlsx). Each has a different reference file for HOW the palette gets
applied mechanically (theme slots vs. raw hex vs. cell fills) — read the
matching file in references/ before generating the file:
- PowerPoint or HTML/React artifact →
references/pptx-html.md - Word document →
references/docx.md - Excel spreadsheet →
references/xlsx.md
Safety check — stop here if the request is actually:
- A CV, resume, or cover letter (even as a .docx) — do not apply this skill; use standard neutral/ATS-safe formatting instead.
- A PDF or plain markdown output — do not apply this skill directly. If a PDF
is meant to come from a Word doc, apply the palette at the docx stage
(
references/docx.md) and let the PDF inherit it on conversion. - An HTML/React artifact that isn't styled like a slide or document (e.g. a game, a data-only dashboard, a utility tool) — this skill's document/deck conventions may not fit; use judgment rather than forcing the palette.
If none of these exceptions apply, continue to Step 2.
Step 2 — Determine the palette (ask, don't assume)
Never silently default to a palette, and never skip this step just because the user has used this skill before — they may forget to specify.
Check for an established palette in this conversation first. If the user already chose a palette for the file currently being worked on earlier in this same conversation (preset name, hex codes, or "neutral"), reuse it without asking again — this applies even if the current request is a new slide, section, or edit to the same document, not just the first draft. Only re-ask if the user starts a new, unrelated document, or explicitly asks to change the palette.
If no established palette applies, check whether the current message already answers this (e.g. they typed a hex code, said "use navy," or said "neutral is fine"). If the user has already given exact hex code(s) (e.g. "use #1C2B3A" or "our brand color is 0057B8"), skip both questions below and go straight to Step 2c (org-specific).
If a brand hex is already saved in references/preferences.md and the
user picks "Use my brand colors" without giving a fresh hex, apply the saved
brand hex directly — do not ask for it again. Only prompt for a hex if none
is saved yet.
If it's genuinely unstated, ask a single short question first, with four options:
"Which palette should I use — Neutral, a Different preset, your own brand colors, or Black & White?"
Use ask_user_input_v0 with four options: Neutral / Different preset
/ Use my brand colors / Black & White. If ask_user_input_v0 isn't
available in this environment (e.g. Claude Code or a plain API session), ask
the same four-way question as plain text instead and read the reply normally.
- Neutral → go to Step 2a.
- Different preset → go to Step 2b.
- Use my brand colors → check for a saved brand hex first (see above); if none, ask for the hex code(s) (primary required, secondary/neutral optional) or accept an attached image (see 2c). Then go to Step 2c. If the reply is a color name without a hex (e.g. "our brand navy," "company blue") rather than an actual hex code or image, ask for the exact hex — don't guess one from a name.
- Black & White → go to Step 2d.
2a — If "Neutral"
Apply the neutral/Palette-A table directly (given in each format's reference file). No further questions needed.
2b — If "Different"
Show the 5 alternate palettes as small numbered color swatches — one colored
square per palette, labeled with number and name — using the Visualizer
(visualize:show_widget, loading the diagram or mockup module via
read_me first). Use each palette's "dark text/header" hex as the
representative swatch color. The five options, in order:
- Navy Corporate —
1E2A38 - Forest Professional —
1F3A2E - Burgundy Enterprise —
3A1E26 - Warm Graphite —
2B2A28 - Steel Blue —
1B2E3D
If the Visualizer tool isn't available in this environment, skip the widget and list the five options as plain text instead, one line per palette: number, name, and the representative hex (e.g. "1. Navy Corporate — 1E2A38").
Full hex tables for all 5 are in references/pptx-html.md (source tables;
docx/xlsx reference files map these onto their own mechanics). Wait for the
user's reply, then apply that palette throughout.
Handling the reply — it may not be a clean number:
- A digit 1-5 → apply the matching palette directly.
- A palette name instead of a number (e.g. "the navy one," "steel blue") → match it to the corresponding option and apply it; no need to ask again.
- A change of mind toward giving exact hex codes instead (e.g. "actually, use #0057B8") → drop this flow and go to Step 2c (org-specific) with the hex given.
- Anything ambiguous or unclear (e.g. "the second-to-last one," or a reply that doesn't clearly map to any of the 5) → ask a single short follow-up to confirm which option was meant, rather than guessing.
2c — Org-specific (exact hex given, or image attached)
Take the 1-3 hex codes provided (primary required; secondary/neutral optional) and derive the rest of the role table. Two ways the primary color can be given:
- Typed hex (e.g. "use #1C2B3A") — use it directly.
- Attached image (a logo, slide, or photo) — identify the dominant color(s) in the image, then state the extracted hex back to the user for confirmation (e.g. "I'm reading this as #1C2B3A — is that right?") before proceeding. Extraction from an image is approximate, so always confirm before applying; if the user corrects it, use their correction instead.
Once a primary hex is confirmed (typed or image-derived):
- If the primary color is dark enough for white text on top (contrast ratio ≥ 4.5:1 — see "Checking contrast without guessing" above), use it directly for headers/dark text.
- If the primary is too light for a dark header/text role (this includes both: a color that's dark but needs darkening further, AND a color that's inherently light/pastel, e.g. a light logo hue) — do not force it into the dark-text role as-is. Instead, darken the same hue (reduce lightness, keep hue/saturation family) until it clears the 4.5:1 contrast threshold, and use that darkened version for headers/dark text/borders.
- Reserve the original, lighter brand hex for the light-fill role (90-95% lightness tint slot) — that's the closest match to what a light brand color naturally does in the palette. Only use it as a mid accent instead if the brand hex is already saturated enough to read clearly as an accent against white (avoid using a washed-out pastel as an accent color).
- Always tell the user the adjusted hex used and which original brand color it was derived from.
- Generate light tints (90-95% lightness) of the (possibly darkened) primary for section fills — do not introduce unrelated hues.
- Derive border color: a mid-lightness tint of the same hue, roughly halfway between the (possibly darkened) dark-text hex and the light-fill hex — visually distinct from both, never a separate hue.
- Derive near-white fill: a lighter tint than the light-fill hex, same hue, roughly 97-98% lightness, used the same way the preset palettes use it (outer panel backgrounds, subtle separation, secondary banding).
- This gives org-specific palettes the same seven-role set as the presets (header background, dark text, mid accent, border, light fill, near-white fill, text-on-dark) — don't stop at header and fill colors alone.
- Secondary brand color (if given) is used only as an accent, never blended into the main tint ladder.
- Stay within one hue family throughout, exactly as in the core rule above.
2d — Black & White
Apply true grayscale — no hue at all. Header/dark text: black or near-black
(000000 or 1A1A1A). Background: white (FFFFFF). Section fills, borders,
and mid accents: grayscale tints only (e.g. F5F5F5, E0E0E0, 9E9E9E,
616161), varied by lightness the same way the colored presets vary tint —
never introduce any hue. Text on dark: white. The semantic/status exception
(red/amber/green) still applies here if the document needs status indicators.
Step 3 — Apply and confirm
Generate the file using the format-specific mapping from the relevant reference file. Briefly state which palette was used (e.g. "Applied the Forest Professional palette") so the user can catch a mismatch early — this is not a place to over-explain, one line is enough.
Offer to save it as a named palette. Regardless of which Step 2 path was
used (Neutral, Different preset, Brand colors, or Black & White), as part of
this same confirmation ask whether the user wants to save this palette under
a one-word name for quick recall later — e.g. "Want to save this as a named
palette? Just give it a word, like 'alpha,' and next time you can say
'generate alpha' to use it without choosing again." If the user gives a
word, write word: <full hex table for the applied palette> to
references/named-palettes.md immediately. If they decline or don't
respond, don't save anything — this offer is separate from, and doesn't
replace, the Step -1 standing-preference save (that one is for a persistent
default; named palettes are for switching between several saved options by
word).
Test cases
This skill has objectively verifiable output (specific hex values applied to specific roles), so it benefits from test prompts rather than subjective review alone. Useful cases to check when evaluating this skill:
- "Create a PowerPoint about Q3 results" — no color mentioned → should ask the three-way choice (neutral / different preset / brand colors) before generating anything.
- "Make me a Word report, use the neutral palette" — should skip straight to applying the neutral table, no swatch question.
- "Build an Excel tracker, use our brand color #FDE9E9" (a pastel/light hex) — should trigger the Step 2c light-color fallback: darken for headers, keep the original for fills, and state both hexes used.
- "Different palette please" (after being asked) — should show the 5 numbered swatches via the Visualizer, then wait for a reply.
- "The navy one" (as the reply to the swatch prompt, not a number) — should correctly match to Navy Corporate without asking again.
- "Write me a cover letter" or "export this as a PDF" — should NOT trigger this skill at all, per the Step 1 safety-check exclusions.
- Any docx/xlsx/pptx request with zero mention of design at all — confirms the skill still triggers on silence, not just on explicit color asks.
- Ask for a PowerPoint with no palette mentioned, pick a preset, then ask for "one more slide" on the same deck later in the conversation — should reuse the chosen palette without re-asking.
- Give a brand primary hex only (no secondary) that's dark enough to use directly — should still produce all seven roles (border and near-white included), not just header and fill colors.
- "Make me a report in black and white" — should skip straight to Step 2d, true grayscale, no hue anywhere except any semantic status color used.
- "Use our brand color" with an image attached, no hex typed — should extract a dominant hex, state it back for confirmation, then proceed as Step 2c once confirmed.
- After a palette is applied and saved under a word (e.g. "ocean"), a new request says "generate ocean" — should skip Step -1 and Step 2 entirely and apply the saved palette directly, per Step -2.