Claude Skill

brand-identity

Use when a project needs its visual foundation built or consolidated into one system: logo brief, color system in HEX/RGB/CMYK/OKLCH with proven AA contrast, type system, usage rules, and an exported W3C design-tokens.json that later skills consume. NOT the applied UI pixels (tha

LLM Mart · 0 points · 0 views 0 listing impressions 0 install-command copies
Virus-scanned Reviewed automatically before listing.

Full trust report

Download ericrisco-rsc-harness-skills_brand-identity-953fef5.zip · 15 KB
Part of ericrisco/rsc-harness — 46 skills

Install

skills CLI npx skills add https://github.com/ericrisco/rsc-harness/tree/main/skills/brand-identity
Claude Code claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install ericrisco-rsc-harness@llmmart
Git git clone https://github.com/ericrisco/rsc-harness.git

The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole ericrisco/rsc-harness collection as a plugin from our marketplace. Git is the plain clone.

Skill manifest

Brand Identity — Define the Foundation, Not the Pixels

This skill emits the brand book — logo brief, color system, type system, usage rules — and a machine-readable design-tokens.json that design consumes. You write the rules every later pixel must obey; you do not paint the live UI.

A brand identity with nothing checkable behind it is a mood board. The bar here is a brand book that compiles: roles named, every color carrying four channels, contrast pairs proven against WCAG, and a tokens file that scripts/verify.sh can validate.

All four parts ship together — logo brief, color system, type system, usage guidelines with the tokens export. A part missing its bar is incomplete, not "lite".

The one-line boundary test: "define what our brand looks like everywhere" → here. "make this surface look premium" → design.

Logo brief

Specify a system, not a single picture. The mark must survive from favicon to billboard, in color and in one ink.

  • Variation set — primary (horizontal lockup), stacked (vertical, for square/tight slots), mark-only (the symbol alone, for avatars/favicons), monochrome (single-ink: black, white-knockout). A logo with no mono version fails the moment it lands on a colored background or a fax. Test the mono version first; if it dies in one color, the design is too fragile.
  • Clear space — define it relative to the mark, not in fixed px, so it scales: clear space = the cap-height (or x-height of the mark) on all four sides. Nothing intrudes inside it.
  • Minimum size — below this, detail collapses. Defaults: 24px wide digital, 10mm wide print for the full lockup; the mark-only may go smaller (favicon).
  • File + favicon matrix — ship the formats below. SVG is the digital primary (scales, tiny); PNG carries transparency; JPEG is print-safe; 72 DPI digital / 300 DPI print.
Asset Format Notes
Logo (digital primary) SVG Vector, scales infinitely, smallest
Logo (raster, transparency) PNG @1x/@2x, transparent bg
Logo (print) JPEG/PDF 300 DPI, CMYK
Favicon (modern) favicon.svg <1KB, can embed prefers-color-scheme for dark mode
Favicon (legacy fallback) favicon.ico At site root
Favicon PNG favicon-16.png, favicon-32.png Tab/bookmark
Apple touch apple-touch-icon.png 180×180 iOS home screen
Android android-chrome-192.png, -512.png PWA/manifest
Manifest site.webmanifest Declares the icon set

Full variation grid, clear-space/min-size formulas, and the favicon HTML markup + prefers-color-scheme SVG snippet → references/logo-and-assets.md.

Color system

Assign roles first, values second. A color with no role is decoration waiting to be misused.

  • Role taxonomy — 2–3 primary (the brand's signature), 2–3 secondary (support), a neutral ramp (text, surfaces, borders), and exactly one accent reserved for CTAs/highlights. One accent keeps "click here" unambiguous.
  • Four channels, every color, no exceptions — HEX (web), RGB (screen math), CMYK (print), OKLCH (perceptual + wide-gamut). This one is absolute because a HEX-only palette silently breaks the two places nobody tests: print (no CMYK) and wide-gamut screens (no OKLCH). The W3C Design Tokens Color Module (2025.10) supports CSS Color 4 spaces including OKLCH and Display P3, so wide-gamut color lives in the token file natively — author in OKLCH and let HEX be the fallback.
  • AA contrast pairing — every text-on-background pair you document clears WCAG 2 AA: 4.5:1 normal text, 3:1 large text (≥18.66px bold or ≥24px). Not negotiable — it is a conformance threshold, not a taste call, and shipping under it ships an inaccessible product. AAA is 7:1 / 4.5:1 — reach for it on body text where you can. Pair colors explicitly ("fg on bg: 12.4:1 ✓").
  • Logo-text exemption caveat — WCAG 1.4.3 exempts logos and brand-name text from the contrast minimums. But a typed sub-brand or tagline that is plain text (not a graphical logo) IS subject to text-contrast rules. Mark logo-only tokens exempt; hold everything else to 4.5:1.
  • Light/dark roles — define the role in both schemes from day one (bg/fg invert, brand stays anchored). Retrofitting dark mode onto a light-only palette produces muddy, low-contrast surfaces.

Full role taxonomy, a fully worked palette in HEX/RGB/CMYK/OKLCH, the contrast-pair matrix with computed ratios, and the dark-mode token strategy → references/color-and-tokens.md.

Type system

Two to three typefaces, no more. Most brands need exactly two: one display (headlines, personality) and one text (body, ≤16px legibility); a third is justified only for monospace/data.

  • Scale — pick a modular ratio (1.2 minor third for dense UI, 1.25 major third for marketing) and ladder the sizes from it. Document the ladder; do not re-guess sizes per screen.
  • Weights — name which weights ship (e.g. 400 body, 500 UI, 600/700 display) and which are banned (no faux-bold, no faux-italic).
  • Pairing rationale — one line on why the pair works (contrast in structure: a geometric sans display over a humanist text face; or a serif display over a neutral sans body). "They both look nice" is not a rationale.
  • Variable-font note — prefer a variable font where available: one file spans the weight axis, cuts requests, and removes the faux-bold temptation. Pin the named instances you use.

Emit the tokens (the hand-off contract)

Ship design-tokens.json even when the client only asked for a PDF — it is the one artifact design can read, and without it the palette gets re-derived by eye and drifts. Use the W3C Design Tokens format, which reached its first stable version (2025.10) on 2025-10-28 — a vendor-neutral JSON for sharing design decisions, with light/dark and multi-brand themes via group inheritance / $extends.

{
  "$schema": "https://tokens.designtokens.org/2025.10/schema.json",
  "color": {
    "brand": {
      "$type": "color",
      "primary": {
        "$value": { "colorSpace": "oklch", "components": [0.55, 0.19, 256], "hex": "#3b5bdb" }
      },
      "accent": {
        "$value": { "colorSpace": "oklch", "components": [0.72, 0.17, 50], "hex": "#f08c00" }
      }
    },
    "bg": { "$type": "color", "$value": { "colorSpace": "oklch", "components": [0.99, 0, 0], "hex": "#fcfcfc" } },
    "fg": { "$type": "color", "$value": { "colorSpace": "oklch", "components": [0.21, 0.01, 256], "hex": "#1f2430" } }
  }
}

Map the tokens to CSS custom properties (and, if the consumer is Tailwind v4, an @theme block) so the values flow into utilities — author once, consume everywhere:

/* design consumes these — generated from design-tokens.json, never hand-edited */
:root {
  --color-brand-primary: oklch(0.55 0.19 256);
  --color-brand-accent:  oklch(0.72 0.17 50);
  --color-bg:            oklch(0.99 0 0);
  --color-fg:            oklch(0.21 0.01 256);
}

Full tokens file with light/dark via $extends, the Tailwind v4 @theme mapping, and the dark-mode strategy → references/color-and-tokens.md.

Usage guidelines + anti-patterns

State the misuse rules explicitly — the gap a brand book exists to close is the well-meaning teammate who stretches the logo to fit.

Misuse in the wild Why it breaks / Fix
"Stretch the logo to fill the space" Non-uniform scaling distorts the mark. Lock aspect ratio; pick the variation that fits (stacked vs primary).
"This blue is close enough" Off-palette colors fracture recognition. Use the token; if a need is unmet, add a role, don't eyeball one.
"HEX is enough, we're a web brand" Print and wide-gamut break. Every color carries HEX + RGB + CMYK + OKLCH or it is not in the system.
"Four fonts give us range" Reads as chaos and bloats load. Cap at 2–3; get range from weights + scale.
"We'll add dark mode later" Light-only palettes go muddy when inverted. Define light/dark roles from day one.
"Contrast is a design detail" It is a WCAG requirement. Document each text/bg pair at ≥4.5:1 before shipping.
"Drop the logo on any background" Color/photo backgrounds kill legibility. Provide and require the mono/knockout variation with clear space.
"The tokens file is optional, the PDF is the brand" A PDF can't be consumed by code; design will drift. The design-tokens.json is the contract.

Do/don't rules, the full misuse grid with examples, and lockup rules → references/logo-and-assets.md.

Verify

The skill emits a checkable artifact, so verify it before claiming done. Run against your tokens file:

./scripts/verify.sh path/to/design-tokens.json

It checks: the file parses as JSON; required color roles are present (primary, neutral, accent at minimum); every color token carries a HEX value; and, for each documented text/background pair (declared via $extensions["com.risco.contrast"] pairs), it computes the WCAG relative-luminance contrast ratio and fails any normal-text pair below 4.5:1. Logo-only tokens are exempt. On an empty or clean target it exits 0 — no false failures.

Boundary + hand-off

Request Route to Why
Tone of voice, tagline, naming, messaging pillars ../brand-voice/SKILL.md Verbal identity — the words, not the pixels. Pair it with this so copy and visuals agree.
Make this page premium, pick layout + motion, ship the Tailwind ../design/SKILL.md The applied UI layer: it reads design-tokens.json and builds the accessible, fast UI. This skill produces the brand study's visual half that design STOPS without.
Hero headline, value prop, CTA copy ../marketing/SKILL.md Page words, not the visual system.
Press kit — boilerplate, logos-for-press, fact sheet ../press-kit/SKILL.md Media packaging of finished assets, not system definition.
Investor pitch deck visuals ../presentations/SKILL.md Deck composition consuming the tokens, not the brand foundation.
Files (rsc-harness)
  • evals
    • cases.yaml 3.8 KB
      skill: brand-identity
      
      should_trigger:
        - prompt: "Build our brand identity — logo brief, colors, fonts, the whole brand book."
          why: "The core ask: all four deliverable parts (logo, color, type, usage) named explicitly. Exact center of the skill."
        - prompt: "Pick a color palette and document the hex, rgb, and cmyk values for our brand."
          why: "Color-system core; the four-channel value requirement (HEX/RGB/CMYK/OKLCH) is the skill's contract for colors."
        - prompt: "Define our type system: primary and secondary typefaces with a scale and weights."
          why: "Type-system core — 2-3 typefaces, scale, weights, pairing rationale are exactly this skill's bar."
        - prompt: "We've got random fonts and hex codes scattered across files — consolidate them into one system."
          why: "Non-obvious rebrand/consolidation trigger: no 'brand book' wording, but unifying ad-hoc colors/fonts into a system is precisely the rebrand path."
        - prompt: "Necesito una identidad de marca y la guia de marca con normas de uso del logo."
          why: "Spanish/Catalan trigger naming brand identity, brand guidelines, and logo usage rules — all owned here."
        - prompt: "Export a design-tokens.json with our brand colors so the dev team stops eyeballing the palette."
          why: "Non-obvious: phrased as a tokens export, but emitting the W3C design-tokens.json hand-off contract is this skill's machine-readable deliverable."
      
      should_not_trigger:
        - prompt: "Make this landing page look premium — pick the layout, motion, and ship the Tailwind."
          route_to: design
          why: "Applied UI layer (layout, motion, real code) consumes the brand foundation; it is not the foundation itself."
        - prompt: "Write our tone of voice and a tagline for the homepage."
          route_to: brand-voice
          why: "Verbal identity — words and tone — not the visual system."
        - prompt: "Write the hero headline and the CTA copy for our pricing page."
          route_to: marketing
          why: "Page words / conversion copy, not the logo/color/type system."
        - prompt: "Put together a press kit with our logos and boilerplate for journalists."
          route_to: press-kit
          why: "Media packaging of finished assets, not defining the brand system."
        - prompt: "Design the investor pitch deck slides for our seed round."
          route_to: presentations
          why: "Deck composition/visuals, not the brand foundation the deck would draw from."
      
      capability:
        - scenario: "We're a fintech startup 'Ledgerly'. Create our brand identity foundation."
          must_include:
            - "A logo brief with the full variation set (primary / stacked / mark-only / monochrome), a clear-space rule tied to the mark's cap/x-height, minimum sizes (e.g. ~24px digital / ~10mm print), and a file + favicon export matrix (SVG primary, PNG/ICO fallbacks, apple-touch 180, android 192/512, site.webmanifest)."
            - "Color roles assigned (2-3 primary, 2-3 secondary, a neutral ramp, exactly one accent), each color carrying HEX + RGB + CMYK + OKLCH — not HEX alone."
            - "At least one documented text-on-background pair meeting WCAG 2 AA (>= 4.5:1 normal text / 3:1 large), stated as an explicit pair (fg on bg with the ratio), and a note that logo/brand-name text is exempt under WCAG 1.4.3 while typed taglines are not."
            - "A type system of 2-3 typefaces max with a modular scale, named weights, and a one-line pairing rationale (plus a variable-font note)."
            - "A W3C-format design-tokens.json (2025.10) emitted with light/dark roles via group inheritance / $extends and OKLCH values, mapped to CSS custom properties / Tailwind v4 @theme."
            - "Usage/misuse rules (no stretching, no off-palette color, require the mono variation on busy backgrounds) plus an explicit hand-off note to design as the skill that applies the tokens."
            - "A pointer to run scripts/verify.sh on the emitted design-tokens.json to confirm roles, hex coverage, and AA contrast before claiming done."
      
    • README.md 1 KB
      # Evals — brand-identity
      
      `cases.yaml` is read by the harness eval runner. The `should_trigger` and
      `should_not_trigger` blocks check routing precision: that brand-foundation requests
      (logo brief, color/type system, tokens export, the Catalan/Spanish phrasings, and the
      non-obvious "consolidate scattered fonts/hex" rebrand case) select this skill, while
      adjacent asks correctly route to the real siblings — `design` (applied UI), `brand-voice`
      (words/tone), `marketing` (page copy), `press-kit` (media pack), `presentations` (deck).
      The `capability` block is a rubric scored against a real generation: the "Ledgerly" prompt
      must produce all four deliverable parts (logo brief, four-channel color roles, an AA-proven
      contrast pair, a 2-3 typeface system, a W3C `design-tokens.json` with light/dark) plus
      usage rules and the hand-off to `design`. Run it via the repo's eval command; no network is
      required. To sanity-check the verify gate by hand, run
      `scripts/verify.sh path/to/design-tokens.json` against a generated tokens file.
      
  • references
    • color-and-tokens.md 6.1 KB
      # Color system & design tokens
      
      Depth offloaded from SKILL.md: the full role taxonomy, a worked palette in all four
      channels, the contrast-pair matrix, the complete W3C `design-tokens.json` with light/dark,
      the Tailwind v4 `@theme` mapping, and the dark-mode strategy.
      
      ## Role taxonomy (assign roles before values)
      
      | Role | Count | Job | Example token |
      | --- | --- | --- | --- |
      | Primary | 2–3 | The brand's signature; the color people recall | `color.brand.primary` |
      | Secondary | 2–3 | Support; section accents, illustration | `color.brand.secondary` |
      | Neutral | a ramp (50→900) | Text, surfaces, borders, dividers | `color.neutral.*` |
      | Accent | exactly 1 | CTAs, highlights, the "click here" color | `color.brand.accent` |
      | Semantic | as needed | success / warning / danger / info states | `color.status.*` |
      
      One accent only. The moment a palette has two "primary action" colors, every button
      becomes a judgment call and the interface loses its one unambiguous next step.
      
      ## Worked palette — all four channels
      
      A color is not in the system until it carries HEX (web), RGB (screen), CMYK (print),
      and OKLCH (perceptual + wide-gamut). Author in OKLCH; let HEX be the fallback.
      
      | Token | HEX | RGB | CMYK | OKLCH |
      | --- | --- | --- | --- | --- |
      | brand.primary | `#3b5bdb` | 59, 91, 219 | 73, 58, 0, 14 | `oklch(0.55 0.19 256)` |
      | brand.accent | `#f08c00` | 240, 140, 0 | 0, 42, 100, 6 | `oklch(0.72 0.17 50)` |
      | bg (light) | `#fcfcfc` | 252, 252, 252 | 0, 0, 0, 1 | `oklch(0.99 0 0)` |
      | fg (light) | `#1f2430` | 31, 36, 48 | 35, 25, 0, 81 | `oklch(0.21 0.01 256)` |
      | bg (dark) | `#15171c` | 21, 23, 28 | 25, 18, 0, 89 | `oklch(0.18 0.01 256)` |
      | fg (dark) | `#e9ebf0` | 233, 235, 240 | 3, 2, 0, 6 | `oklch(0.93 0.005 256)` |
      
      CMYK is approximate — final print values come from the press profile (e.g. coated vs
      uncoated stock). Document the intent; let the printer's profile resolve the exact ink mix.
      
      ## Contrast-pair matrix (WCAG 2)
      
      Thresholds: AA 4.5:1 normal / 3:1 large (≥18.66px bold or ≥24px); AAA 7:1 / 4.5:1.
      Document every pair you ship as text-on-background.
      
      | Foreground | Background | Ratio | Normal AA | Large AA | AAA |
      | --- | --- | --- | --- | --- | --- |
      | fg `#1f2430` | bg `#fcfcfc` | ~12.4:1 | ✓ | ✓ | ✓ |
      | brand.primary `#3b5bdb` | bg `#fcfcfc` | ~5.0:1 | ✓ | ✓ | ✗ |
      | white `#ffffff` | brand.primary `#3b5bdb` | ~4.9:1 | ✓ | ✓ | ✗ |
      | brand.accent `#f08c00` | bg `#fcfcfc` | ~2.1:1 | ✗ | ✗ | ✗ |
      | fg(dark) `#e9ebf0` | bg(dark) `#15171c` | ~13.6:1 | ✓ | ✓ | ✓ |
      
      The accent on white fails — that is expected. An accent earns its saturation by being
      *reserved*; use it as a fill behind white/dark text or as a non-text highlight, never as
      body text on the page background. Verify each pair with a checker, not by eye.
      
      **Logo-text caveat:** WCAG 1.4.3 exempts logos and brand-name graphics from these minimums.
      A *typed* tagline or sub-brand that is plain text (not a graphical logo) is NOT exempt — hold
      it to 4.5:1. Mark only logo tokens exempt.
      
      ## Complete `design-tokens.json` (W3C 2025.10, light/dark via group inheritance)
      
      W3C Design Tokens reached first stable (2025.10) on 2025-10-28. The Color Module supports
      CSS Color 4 spaces (OKLCH, Display P3). Themes share a base and override via group
      inheritance / `$extends`.
      
      ```json
      {
        "$schema": "https://tokens.designtokens.org/2025.10/schema.json",
        "$description": "Brand tokens — single source consumed by the design skill.",
        "color": {
          "$type": "color",
          "brand": {
            "primary":   { "$value": { "colorSpace": "oklch", "components": [0.55, 0.19, 256], "hex": "#3b5bdb" } },
            "secondary": { "$value": { "colorSpace": "oklch", "components": [0.62, 0.12, 200], "hex": "#1c8ab0" } },
            "accent":    { "$value": { "colorSpace": "oklch", "components": [0.72, 0.17, 50],  "hex": "#f08c00" } }
          },
          "neutral": {
            "50":  { "$value": { "colorSpace": "oklch", "components": [0.98, 0, 0],     "hex": "#f5f6f8" } },
            "500": { "$value": { "colorSpace": "oklch", "components": [0.55, 0.01, 256], "hex": "#6b7280" } },
            "900": { "$value": { "colorSpace": "oklch", "components": [0.21, 0.01, 256], "hex": "#1f2430" } }
          },
          "theme": {
            "light": {
              "bg": { "$value": { "colorSpace": "oklch", "components": [0.99, 0, 0],     "hex": "#fcfcfc" } },
              "fg": { "$value": { "colorSpace": "oklch", "components": [0.21, 0.01, 256], "hex": "#1f2430" } }
            },
            "dark": {
              "bg": { "$value": { "colorSpace": "oklch", "components": [0.18, 0.01, 256], "hex": "#15171c" } },
              "fg": { "$value": { "colorSpace": "oklch", "components": [0.93, 0.005, 256], "hex": "#e9ebf0" } }
            }
          }
        },
        "$extensions": {
          "com.risco.contrast": [
            { "fg": "#1f2430", "bg": "#fcfcfc", "use": "body",  "logo": false },
            { "fg": "#ffffff", "bg": "#3b5bdb", "use": "button", "logo": false },
            { "fg": "#e9ebf0", "bg": "#15171c", "use": "body-dark", "logo": false }
          ]
        }
      }
      ```
      
      The `$extensions["com.risco.contrast"]` array is what `scripts/verify.sh` reads to prove
      each text/bg pair clears AA. `"logo": true` exempts a pair from the 4.5:1 floor.
      
      ## Tailwind v4 `@theme` + CSS custom-properties mapping
      
      Generate these from the tokens file; never hand-edit them — the JSON is the source.
      
      ```css
      @import "tailwindcss";
      
      @theme {
        --color-brand-primary:   oklch(0.55 0.19 256);
        --color-brand-secondary: oklch(0.62 0.12 200);
        --color-brand-accent:    oklch(0.72 0.17 50);
        --color-neutral-50:      oklch(0.98 0 0);
        --color-neutral-500:     oklch(0.55 0.01 256);
        --color-neutral-900:     oklch(0.21 0.01 256);
        --color-bg:              oklch(0.99 0 0);
        --color-fg:              oklch(0.21 0.01 256);
      }
      ```
      
      ## Dark-mode strategy
      
      - Define `bg`/`fg` per theme; keep `brand.*` anchored across both (recognition is constant).
      - Don't simply invert lightness — dark surfaces want slightly desaturated, slightly warmer
        neutrals to avoid the "pure black + pure white" vibration. Re-check contrast in dark too.
      - Switch with a `prefers-color-scheme` media query or a `.dark` class that re-points the
        `--color-bg`/`--color-fg` vars at the `theme.dark` token group.
      
    • logo-and-assets.md 4.4 KB
      # Logo brief & asset export
      
      Depth offloaded from SKILL.md: the variation grid with when-to-use each, clear-space and
      min-size formulas, the full export matrix with DPI, the favicon set with HTML markup and a
      `prefers-color-scheme` SVG snippet, and the file-naming convention.
      
      ## Variation grid
      
      A logo is a system of variations, each earning its place by the context it survives.
      
      | Variation | Form | When to use |
      | --- | --- | --- |
      | Primary | Horizontal lockup (mark + wordmark) | Default — headers, docs, most digital |
      | Stacked | Vertical (mark over wordmark) | Square/tight slots, social avatars, merch |
      | Mark-only | The symbol alone | Favicons, app icons, watermarks, ≤32px |
      | Monochrome | Single ink (black, or white knockout) | One-color print, dark/photo backgrounds, embossing |
      
      Build and test the **monochrome** version first. If the mark dies in one ink — needs its
      gradient or two colors to read — it is too fragile and must be simplified before color work.
      
      ## Clear-space formula
      
      Define clear space relative to the mark so it scales with the logo instead of breaking at
      small sizes:
      
      ```text
      clear space = cap-height of the wordmark (or x-height of the mark), on all four sides
      ```
      
      Nothing — text, other logos, page edges — intrudes inside that margin. Expressing it as a
      ratio (not a fixed px) means it stays correct from favicon to billboard.
      
      ## Minimum sizes
      
      Below these, detail collapses and the mark stops reading:
      
      | Variation | Digital min | Print min |
      | --- | --- | --- |
      | Primary lockup | 24px wide | 10mm wide |
      | Stacked | 32px wide | 12mm wide |
      | Mark-only | 16px wide (favicon territory) | 6mm wide |
      
      ## Export matrix
      
      Ship vector first; raster for the cases vector can't cover. 72 DPI digital, 300 DPI print.
      
      | Asset | Format | DPI | Notes |
      | --- | --- | --- | --- |
      | Logo, digital primary | SVG | n/a (vector) | Scales infinitely, smallest file |
      | Logo, raster transparency | PNG @1x/@2x | 72 | Transparent background |
      | Logo, print | PDF or JPEG | 300 | CMYK color, embed fonts/outline |
      | Mark, app icon | PNG | 72 | Square, safe-zone padded |
      
      ## Favicon set (2025 baseline)
      
      Modern baseline: an SVG primary that can carry a `prefers-color-scheme` dark variant, with
      PNG/ICO fallbacks for engines that don't render SVG favicons (notably older Safari).
      
      | File | Size | Purpose |
      | --- | --- | --- |
      | `favicon.svg` | vector, <1KB | Primary; can embed dark-mode CSS |
      | `favicon.ico` | 16/32 multi | Legacy root fallback |
      | `favicon-16.png`, `favicon-32.png` | 16, 32 | Tab/bookmark raster |
      | `apple-touch-icon.png` | 180×180 | iOS home screen |
      | `android-chrome-192.png`, `-512.png` | 192, 512 | Android / PWA |
      | `site.webmanifest` | — | Declares the icon set + theme color |
      
      ### HTML markup
      
      ```html
      <link rel="icon" href="/favicon.ico" sizes="32x32">
      <link rel="icon" href="/favicon.svg" type="image/svg+xml">
      <link rel="apple-touch-icon" href="/apple-touch-icon.png">
      <link rel="manifest" href="/site.webmanifest">
      ```
      
      ### Dark-mode favicon (SVG with `prefers-color-scheme`)
      
      An SVG favicon can flip its fill in dark UI chrome — one file, no extra requests:
      
      ```html
      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
        <style>
          path { fill: #1f2430; }
          @media (prefers-color-scheme: dark) { path { fill: #e9ebf0; } }
        </style>
        <path d="M6 6 H26 V26 H6 Z" />
      </svg>
      ```
      
      ## File-naming convention
      
      Predictable names keep the asset folder usable years later:
      
      ```text
      brand/
        logo-primary.svg        logo-primary@2x.png
        logo-stacked.svg        logo-stacked@2x.png
        logo-mark.svg           logo-mark@2x.png
        logo-mono-black.svg     logo-mono-white.svg
        logo-print.pdf
        favicon.svg  favicon.ico  favicon-16.png  favicon-32.png
        apple-touch-icon.png  android-chrome-192.png  android-chrome-512.png
        site.webmanifest
      ```
      
      Pattern: `logo-<variation>[-<modifier>][@<scale>].<ext>`. Lowercase, hyphenated, no spaces.
      
      ## Misuse rules (do / don't)
      
      - DON'T stretch, squash, or rotate the mark — scale uniformly only.
      - DON'T recolor the logo off-palette or apply gradients/shadows not in the brief.
      - DON'T place the color logo on a busy/low-contrast background — switch to the mono knockout.
      - DON'T violate clear space or drop below the minimum size.
      - DON'T recreate the lockup by hand-typing the wordmark — use the supplied files.
      - DO use the variation that fits the slot (stacked for square, mark-only for ≤32px).
      - DO keep the accent reserved; the logo is not a place to introduce new colors.
      
  • scripts
    • verify.sh 7.6 KB
      #!/usr/bin/env bash
      #
      # verify.sh — brand-token gate for the `brand-identity` skill.
      #
      # WHAT IT DOES (read-only; never writes or mutates anything)
      #   Given a W3C design-tokens.json path, validates the brand book's
      #   machine-readable artifact:
      #     1. File exists and parses as JSON (fail loud otherwise).
      #     2. Required color roles present: primary, neutral, accent (anywhere in
      #        the color tree).
      #     3. Every color token carries a HEX value (in its `$value.hex`).
      #     4. For each documented text/background pair under
      #        $extensions["com.risco.contrast"], computes the WCAG 2 relative-
      #        luminance contrast ratio and FAILS any normal-text pair < 4.5:1.
      #        Pairs flagged "logo": true are exempt (WCAG 1.4.3 logo exemption).
      #     5. Prints an ok/skip/warn/fail summary naming the failing pairs.
      #
      # HOW TO RUN (inside YOUR project, not the skills repo)
      #   ./verify.sh path/to/design-tokens.json
      #   ./verify.sh                  # no arg: auto-discovers design-tokens.json,
      #                                #   clean exit 0 if none found (no false fail)
      #   ./verify.sh --help
      #
      # EXIT CODES
      #   0  no failures (also: empty/clean target — nothing to check)
      #   1  a real failure (bad JSON, missing role, color w/o hex, AA pair < 4.5:1)
      #   2  bad usage
      #
      # Dependency-light: prefers python3 (stdlib only) for JSON + contrast math.
      # If python3 is absent, JSON-dependent checks are SKIPPED, never failed.
      
      set -euo pipefail
      
      if [ -z "${BASH_VERSION:-}" ]; then
        printf 'This script requires bash (any version >= 3.2). Run: bash %s\n' "$0" >&2
        exit 2
      fi
      
      if [ -t 1 ]; then
        RED=$'\033[31m'; GREEN=$'\033[32m'; YELLOW=$'\033[33m'; NC=$'\033[0m'
      else
        RED=''; GREEN=''; YELLOW=''; NC=''
      fi
      
      ok_count=0; skip_count=0; warn_count=0; fail_count=0
      ok()   { printf '%s[ ok ]%s %s\n' "$GREEN"  "$NC" "$*"; ok_count=$((ok_count + 1)); }
      skip() { printf '%s[skip]%s %s\n' "$YELLOW" "$NC" "$*"; skip_count=$((skip_count + 1)); }
      warn() { printf '%s[warn]%s %s\n' "$YELLOW" "$NC" "$*"; warn_count=$((warn_count + 1)); }
      fail() { printf '%s[fail]%s %s\n' "$RED"    "$NC" "$*"; fail_count=$((fail_count + 1)); }
      
      usage() { sed -n '2,40p' "$0" | sed 's/^# \{0,1\}//'; }
      
      have() { command -v "$1" >/dev/null 2>&1; }
      
      # --- arg parse --------------------------------------------------------------
      TOKENS=""
      while [ $# -gt 0 ]; do
        case "$1" in
          -h|--help) usage; exit 0 ;;
          -*) printf '%sUnknown argument: %s%s\n\n' "$RED" "$1" "$NC"; usage; exit 2 ;;
          *) TOKENS="$1"; shift ;;
        esac
      done
      
      # --- locate the tokens file (clean exit if none — no false failure) ---------
      if [ -z "$TOKENS" ]; then
        # search common spots; pick the first match. Never fail when absent.
        for cand in \
          ./design-tokens.json \
          ./tokens/design-tokens.json \
          ./02-DOCS/wiki/brand/design-tokens.json; do
          if [ -f "$cand" ]; then TOKENS="$cand"; break; fi
        done
        if [ -z "$TOKENS" ]; then
          found="$(find . -maxdepth 4 -name 'design-tokens.json' -type f 2>/dev/null | head -n1 || true)"
          [ -n "$found" ] && TOKENS="$found"
        fi
      fi
      
      if [ -z "$TOKENS" ]; then
        skip "no design-tokens.json found — nothing to verify (pass a path to check one)"
        printf '\nok=%d skip=%d warn=%d fail=%d\n' "$ok_count" "$skip_count" "$warn_count" "$fail_count"
        exit 0
      fi
      
      if [ ! -f "$TOKENS" ]; then
        fail "tokens file not found: $TOKENS"
        printf '\nok=%d skip=%d warn=%d fail=%d\n' "$ok_count" "$skip_count" "$warn_count" "$fail_count"
        exit 1
      fi
      
      # --- the JSON + contrast checks (python3 stdlib) ----------------------------
      if ! have python3; then
        skip "python3 not found — JSON/contrast checks skipped (install python3 to enable)"
        printf '\nok=%d skip=%d warn=%d fail=%d\n' "$ok_count" "$skip_count" "$warn_count" "$fail_count"
        exit 0
      fi
      
      # python prints lines prefixed OK:/FAIL:/WARN:/SKIP: which we route to the
      # bash counters so the summary + exit code stay in one place.
      REPORT="$(python3 - "$TOKENS" <<'PY'
      import json, sys
      
      path = sys.argv[1]
      out = []
      
      try:
          with open(path, encoding="utf-8") as fh:
              data = json.load(fh)
      except json.JSONDecodeError as e:
          print(f"FAIL:tokens file does not parse as JSON: {e}")
          sys.exit(0)
      except OSError as e:
          print(f"FAIL:cannot read tokens file: {e}")
          sys.exit(0)
      
      print("OK:tokens file parses as JSON")
      
      # --- walk: collect every color token (node with $type==color or $value w/ hex)
      colors = []          # (dotted_path, hex_or_None)
      role_names = set()   # leaf + group key names seen, lowercased
      
      def walk(node, trail, inherited_type=None):
          if not isinstance(node, dict):
              return
          ntype = node.get("$type", inherited_type)
          if "$value" in node:
              if ntype == "color" or isinstance(node["$value"], dict):
                  val = node["$value"]
                  hexv = val.get("hex") if isinstance(val, dict) else None
                  if isinstance(val, str) and val.startswith("#"):
                      hexv = val
                  if ntype == "color" or (isinstance(val, dict) and "colorSpace" in val):
                      colors.append((".".join(trail), hexv))
              return
          for k, v in node.items():
              if k.startswith("$"):
                  continue
              role_names.add(k.lower())
              walk(v, trail + [k], ntype)
      
      walk(data.get("color", {}), ["color"], None)
      
      # --- required roles present
      for role in ("primary", "neutral", "accent"):
          if role in role_names:
              print(f"OK:required color role present: {role}")
          else:
              print(f"FAIL:required color role missing: {role}")
      
      # --- every color token carries a hex
      if not colors:
          print("WARN:no color tokens found under 'color'")
      else:
          missing = [p for p, h in colors if not h]
          if missing:
              for p in missing:
                  print(f"FAIL:color token has no hex value: {p}")
          else:
              print(f"OK:all {len(colors)} color tokens carry a hex value")
      
      # --- WCAG 2 contrast on documented pairs
      def lin(c):
          c = c / 255.0
          return c / 12.92 if c <= 0.03928 else ((c + 0.055) / 1.055) ** 2.4
      
      def luminance(hexstr):
          h = hexstr.lstrip("#")
          if len(h) == 3:
              h = "".join(ch * 2 for ch in h)
          if len(h) != 6:
              return None
          try:
              r, g, b = (int(h[i:i+2], 16) for i in (0, 2, 4))
          except ValueError:
              return None
          return 0.2126 * lin(r) + 0.7152 * lin(g) + 0.0722 * lin(b)
      
      def ratio(fg, bg):
          lf, lb = luminance(fg), luminance(bg)
          if lf is None or lb is None:
              return None
          hi, lo = max(lf, lb), min(lf, lb)
          return (hi + 0.05) / (lo + 0.05)
      
      pairs = (data.get("$extensions", {}) or {}).get("com.risco.contrast", [])
      if not pairs:
          print("SKIP:no documented text/background pairs ($extensions.com.risco.contrast) — contrast not checked")
      else:
          for p in pairs:
              fg, bg = p.get("fg"), p.get("bg")
              use = p.get("use", "text")
              is_logo = bool(p.get("logo"))
              r = ratio(fg, bg) if fg and bg else None
              if r is None:
                  print(f"WARN:could not compute contrast for pair {fg} on {bg} ({use})")
                  continue
              if is_logo:
                  print(f"SKIP:logo-exempt pair {fg} on {bg} ({use}): {r:.2f}:1 (WCAG 1.4.3 logo exemption)")
              elif r < 4.5:
                  print(f"FAIL:contrast {r:.2f}:1 < 4.5:1 AA — {fg} on {bg} ({use})")
              else:
                  print(f"OK:contrast {r:.2f}:1 >= 4.5:1 AA — {fg} on {bg} ({use})")
      PY
      )"
      
      while IFS= read -r line; do
        [ -z "$line" ] && continue
        case "$line" in
          OK:*)   ok   "${line#OK:}" ;;
          FAIL:*) fail "${line#FAIL:}" ;;
          WARN:*) warn "${line#WARN:}" ;;
          SKIP:*) skip "${line#SKIP:}" ;;
          *)      printf '%s\n' "$line" ;;
        esac
      done <<EOF
      $REPORT
      EOF
      
      printf '\nverified: %s\n' "$TOKENS"
      printf 'ok=%d skip=%d warn=%d fail=%d\n' "$ok_count" "$skip_count" "$warn_count" "$fail_count"
      
      [ "$fail_count" -gt 0 ] && exit 1
      exit 0
      
  • SKILL.md 10.4 KB
    ---
    name: brand-identity
    description: "Use when a project needs its visual foundation built or consolidated into one system: logo brief, color system in HEX/RGB/CMYK/OKLCH with proven AA contrast, type system, usage rules, and an exported W3C design-tokens.json that later skills consume. NOT the applied UI pixels (that is design), NOT the words or tone (that is brand-voice)."
    tags: [brand, identity, logo, color, typography]
    recommends: [design, brand-voice, press-kit, presentations]
    origin: risco
    ---
    
    # Brand Identity — Define the Foundation, Not the Pixels
    
    *This skill emits the brand book — logo brief, color system, type system, usage rules — and a machine-readable `design-tokens.json` that `design` consumes. You write the rules every later pixel must obey; you do not paint the live UI.*
    
    A brand identity with nothing checkable behind it is a mood board. The bar here is a **brand book that compiles**: roles named, every color carrying four channels, contrast pairs proven against WCAG, and a tokens file that `scripts/verify.sh` can validate.
    
    All four parts ship together — logo brief, color system, type system, usage guidelines with the tokens export. A part missing its bar is incomplete, not "lite".
    
    The one-line boundary test: "define what our brand looks like everywhere" → here. "make *this surface* look premium" → `design`.
    
    ## Logo brief
    
    Specify a system, not a single picture. The mark must survive from favicon to billboard, in color and in one ink.
    
    - **Variation set** — primary (horizontal lockup), stacked (vertical, for square/tight slots), mark-only (the symbol alone, for avatars/favicons), monochrome (single-ink: black, white-knockout). A logo with no mono version fails the moment it lands on a colored background or a fax. Test the mono version first; if it dies in one color, the design is too fragile.
    - **Clear space** — define it relative to the mark, not in fixed px, so it scales: clear space = the cap-height (or x-height of the mark) on all four sides. Nothing intrudes inside it.
    - **Minimum size** — below this, detail collapses. Defaults: 24px wide digital, 10mm wide print for the full lockup; the mark-only may go smaller (favicon).
    - **File + favicon matrix** — ship the formats below. SVG is the digital primary (scales, tiny); PNG carries transparency; JPEG is print-safe; 72 DPI digital / 300 DPI print.
    
    | Asset | Format | Notes |
    | --- | --- | --- |
    | Logo (digital primary) | SVG | Vector, scales infinitely, smallest |
    | Logo (raster, transparency) | PNG | @1x/@2x, transparent bg |
    | Logo (print) | JPEG/PDF | 300 DPI, CMYK |
    | Favicon (modern) | `favicon.svg` | <1KB, can embed `prefers-color-scheme` for dark mode |
    | Favicon (legacy fallback) | `favicon.ico` | At site root |
    | Favicon PNG | `favicon-16.png`, `favicon-32.png` | Tab/bookmark |
    | Apple touch | `apple-touch-icon.png` 180×180 | iOS home screen |
    | Android | `android-chrome-192.png`, `-512.png` | PWA/manifest |
    | Manifest | `site.webmanifest` | Declares the icon set |
    
    Full variation grid, clear-space/min-size formulas, and the favicon HTML markup + `prefers-color-scheme` SVG snippet → `references/logo-and-assets.md`.
    
    ## Color system
    
    Assign roles first, values second. A color with no role is decoration waiting to be misused.
    
    - **Role taxonomy** — 2–3 primary (the brand's signature), 2–3 secondary (support), a neutral ramp (text, surfaces, borders), and exactly **one accent** reserved for CTAs/highlights. One accent keeps "click here" unambiguous.
    - **Four channels, every color, no exceptions** — HEX (web), RGB (screen math), CMYK (print), OKLCH (perceptual + wide-gamut). This one is absolute because a HEX-only palette silently breaks the two places nobody tests: print (no CMYK) and wide-gamut screens (no OKLCH). The W3C Design Tokens Color Module (2025.10) supports CSS Color 4 spaces including OKLCH and Display P3, so wide-gamut color lives in the token file natively — author in OKLCH and let HEX be the fallback.
    - **AA contrast pairing** — every text-on-background pair you document clears WCAG 2 AA: **4.5:1 normal text, 3:1 large text** (≥18.66px bold or ≥24px). Not negotiable — it is a conformance threshold, not a taste call, and shipping under it ships an inaccessible product. AAA is 7:1 / 4.5:1 — reach for it on body text where you can. Pair colors explicitly ("`fg` on `bg`: 12.4:1 ✓").
    - **Logo-text exemption caveat** — WCAG 1.4.3 exempts logos and brand-name text from the contrast minimums. But a *typed* sub-brand or tagline that is plain text (not a graphical logo) IS subject to text-contrast rules. Mark logo-only tokens exempt; hold everything else to 4.5:1.
    - **Light/dark roles** — define the role in both schemes from day one (`bg`/`fg` invert, brand stays anchored). Retrofitting dark mode onto a light-only palette produces muddy, low-contrast surfaces.
    
    Full role taxonomy, a fully worked palette in HEX/RGB/CMYK/OKLCH, the contrast-pair matrix with computed ratios, and the dark-mode token strategy → `references/color-and-tokens.md`.
    
    ## Type system
    
    Two to three typefaces, no more. Most brands need exactly two: one display (headlines, personality) and one text (body, ≤16px legibility); a third is justified only for monospace/data.
    
    - **Scale** — pick a modular ratio (1.2 minor third for dense UI, 1.25 major third for marketing) and ladder the sizes from it. Document the ladder; do not re-guess sizes per screen.
    - **Weights** — name which weights ship (e.g. 400 body, 500 UI, 600/700 display) and which are banned (no faux-bold, no faux-italic).
    - **Pairing rationale** — one line on *why* the pair works (contrast in structure: a geometric sans display over a humanist text face; or a serif display over a neutral sans body). "They both look nice" is not a rationale.
    - **Variable-font note** — prefer a variable font where available: one file spans the weight axis, cuts requests, and removes the faux-bold temptation. Pin the named instances you use.
    
    ## Emit the tokens (the hand-off contract)
    
    Ship `design-tokens.json` even when the client only asked for a PDF — it is the one artifact `design` can read, and without it the palette gets re-derived by eye and drifts. Use the **W3C Design Tokens format**, which reached its first stable version (2025.10) on 2025-10-28 — a vendor-neutral JSON for sharing design decisions, with light/dark and multi-brand themes via group inheritance / `$extends`.
    
    ```json
    {
      "$schema": "https://tokens.designtokens.org/2025.10/schema.json",
      "color": {
        "brand": {
          "$type": "color",
          "primary": {
            "$value": { "colorSpace": "oklch", "components": [0.55, 0.19, 256], "hex": "#3b5bdb" }
          },
          "accent": {
            "$value": { "colorSpace": "oklch", "components": [0.72, 0.17, 50], "hex": "#f08c00" }
          }
        },
        "bg": { "$type": "color", "$value": { "colorSpace": "oklch", "components": [0.99, 0, 0], "hex": "#fcfcfc" } },
        "fg": { "$type": "color", "$value": { "colorSpace": "oklch", "components": [0.21, 0.01, 256], "hex": "#1f2430" } }
      }
    }
    ```
    
    Map the tokens to CSS custom properties (and, if the consumer is Tailwind v4, an `@theme` block) so the values flow into utilities — author once, consume everywhere:
    
    ```css
    /* design consumes these — generated from design-tokens.json, never hand-edited */
    :root {
      --color-brand-primary: oklch(0.55 0.19 256);
      --color-brand-accent:  oklch(0.72 0.17 50);
      --color-bg:            oklch(0.99 0 0);
      --color-fg:            oklch(0.21 0.01 256);
    }
    ```
    
    Full tokens file with light/dark via `$extends`, the Tailwind v4 `@theme` mapping, and the dark-mode strategy → `references/color-and-tokens.md`.
    
    ## Usage guidelines + anti-patterns
    
    State the misuse rules explicitly — the gap a brand book exists to close is the well-meaning teammate who stretches the logo to fit.
    
    | Misuse in the wild | Why it breaks / Fix |
    | --- | --- |
    | "Stretch the logo to fill the space" | Non-uniform scaling distorts the mark. Lock aspect ratio; pick the variation that fits (stacked vs primary). |
    | "This blue is close enough" | Off-palette colors fracture recognition. Use the token; if a need is unmet, add a role, don't eyeball one. |
    | "HEX is enough, we're a web brand" | Print and wide-gamut break. Every color carries HEX + RGB + CMYK + OKLCH or it is not in the system. |
    | "Four fonts give us range" | Reads as chaos and bloats load. Cap at 2–3; get range from weights + scale. |
    | "We'll add dark mode later" | Light-only palettes go muddy when inverted. Define light/dark roles from day one. |
    | "Contrast is a design detail" | It is a WCAG requirement. Document each text/bg pair at ≥4.5:1 before shipping. |
    | "Drop the logo on any background" | Color/photo backgrounds kill legibility. Provide and require the mono/knockout variation with clear space. |
    | "The tokens file is optional, the PDF is the brand" | A PDF can't be consumed by code; `design` will drift. The `design-tokens.json` is the contract. |
    
    Do/don't rules, the full misuse grid with examples, and lockup rules → `references/logo-and-assets.md`.
    
    ## Verify
    
    The skill emits a checkable artifact, so verify it before claiming done. Run against your tokens file:
    
    ```bash
    ./scripts/verify.sh path/to/design-tokens.json
    ```
    
    It checks: the file parses as JSON; required color roles are present (primary, neutral, accent at minimum); every color token carries a HEX value; and, for each documented text/background pair (declared via `$extensions["com.risco.contrast"]` pairs), it computes the WCAG relative-luminance contrast ratio and **fails any normal-text pair below 4.5:1**. Logo-only tokens are exempt. On an empty or clean target it exits 0 — no false failures.
    
    ## Boundary + hand-off
    
    | Request | Route to | Why |
    | --- | --- | --- |
    | Tone of voice, tagline, naming, messaging pillars | `../brand-voice/SKILL.md` | Verbal identity — the words, not the pixels. Pair it with this so copy and visuals agree. |
    | Make this page premium, pick layout + motion, ship the Tailwind | `../design/SKILL.md` | The applied UI layer: it reads `design-tokens.json` and builds the accessible, fast UI. This skill produces the brand study's visual half that `design` STOPS without. |
    | Hero headline, value prop, CTA copy | `../marketing/SKILL.md` | Page words, not the visual system. |
    | Press kit — boilerplate, logos-for-press, fact sheet | `../press-kit/SKILL.md` | Media packaging of finished assets, not system definition. |
    | Investor pitch deck visuals | `../presentations/SKILL.md` | Deck composition consuming the tokens, not the brand foundation. |
    

Comments (0)

Sign in to join the conversation.

No comments yet.

Reviews (0)

No reviews yet.

Related