# AI Styling Pattern

**Source:** `docs/ai-styling-mockup.html` (rendered preview of the full pattern)
**Purpose:** One consistent visual language — the **sparkle** — signals "this is AI" wherever it appears in a FieldInsight / Open Claw product. Users learn it once and recognise it everywhere: menu items, tooltips, empty states, hero badges, CTA buttons.

---

## Decisions locked

These two choices are recorded here so any future agent, contractor, or collaborator knows what was picked and why. Don't revisit without a specific reason to.

| Decision | Choice | Date locked |
|---|---|---|
| **Canonical mark** | **Two-Star** at ≥ 16 px · **Single Sparkle** as the fallback at ≤ 14 px. Both SVGs live in "The sparkle mark" section below. | 2026-04-24 |
| **Approved placements** | **Three, no more:** (1) inline icon, (2) circular badge — max one per page, (3) `.ai-pill-btn` CTA button. Anything else is a pattern violation. | 2026-04-24 |

Changes to these decisions must be pushed through this file (workspace root `ai-styling-pattern.md`) and the dual copy at `fi-ai-styling-guide/public/ai-styling-pattern.md`, then synced across every project's cursor rule.

### Decision history

Alternative marks considered during the canonical selection, kept here for provenance:

- **Two-Star** — **chosen 2026-04-24.** Main 4-point star + accent top-left. Added shimmer without busy-ness, subtle differentiation from single-sparkle AI marks used by every other AI brand. Canonical at ≥ 16 px.
- **Single Sparkle** — retained as the fallback at ≤ 14 px, where the second star muddies.
- **Southern Cross** — considered, declined 2026-04-24. Five 4-point stars in the Australian flag constellation. Culturally distinctive but busier at small sizes and harder to centre in circular badges. Not retired in principle — if the brand ever needs a more heritage-grounded mark, this is still the leading alternative.

---

## The principle

**One icon. Three placements. Always the same brand purple.**

| Placement | Where | Size | Treatment |
|---|---|---|---|
| **Inline icon** | Menu items, tooltips, list badges, small labels | 12–16 px | Sparkle only, `currentColor` |
| **Circular badge** | Section headers, empty states, hero illustrations, onboarding | 48–80 px circle | White sparkle on brand-purple disc |
| **CTA button** | Primary AI entry-point on any screen ("Ask AI", "Re-read", "Scan bill") | 13–15 px text | Solid brand-purple pill with sparkle + label |

Never mix other icons in place of the sparkle when indicating AI. Do **not** use robot heads, chat bubbles, lightning bolts, or magic wands.

---

## Design tokens (CSS variables)

Add these to the `:root` of any project that uses the pattern. The only value that is **non-negotiable** is `--brand: #39006B` — FieldInsight's purple is the AI colour.

```css
:root {
  --brand: #39006B;        /* AI purple — do not substitute */
  --brand-hover: #4a0a82;  /* hover state */
  --brand-light: #f5eeff;  /* soft tint backgrounds, hero badges, sparkle-mini */
  --brand-border: #e4d4f5; /* 1px borders on AI-tinted surfaces */
}
```

---

## The sparkle mark — canonical SVG

**Two marks, one family.** The FieldInsight AI glyph is a dual system:

| Mark | When to use | Path |
|---|---|---|
| **Two-Star (canonical)** | Any sparkle ≥ **16 px** — favicon, nav logo, AI pill buttons, circular badges, hero panels, sparkle-mini tiles at 28 px+ | Big 4-point star + small accent star top-left |
| **Single Sparkle (fallback)** | Any sparkle ≤ **14 px** — inline chips, tooltip icons, compact menu items, table row provenance | Single 4-point star |

The accent star top-left in the canonical mark is deliberate — it gives the mark shimmer and subtly leads the eye in reading direction. That's its only job; do not repeat or re-position it.

### Canonical Two-Star (use this at ≥16 px)

<div class="preview" style="color: var(--brand);">
  <div class="preview-label">Canonical · ≥ 16 px</div>
  <div class="preview-stack">
    <svg viewBox="-50 -50 100 100" width="16" height="16" fill="currentColor">
      <path d="M 0 -36 L 8 -8 L 36 0 L 8 8 L 0 36 L -8 8 L -36 0 L -8 -8 Z"/>
      <path d="M -32 -32 L -29 -22 L -19 -20 L -29 -18 L -32 -8 L -35 -18 L -45 -20 L -35 -22 Z"/>
    </svg>
    <svg viewBox="-50 -50 100 100" width="24" height="24" fill="currentColor">
      <path d="M 0 -36 L 8 -8 L 36 0 L 8 8 L 0 36 L -8 8 L -36 0 L -8 -8 Z"/>
      <path d="M -32 -32 L -29 -22 L -19 -20 L -29 -18 L -32 -8 L -35 -18 L -45 -20 L -35 -22 Z"/>
    </svg>
    <svg viewBox="-50 -50 100 100" width="40" height="40" fill="currentColor">
      <path d="M 0 -36 L 8 -8 L 36 0 L 8 8 L 0 36 L -8 8 L -36 0 L -8 -8 Z"/>
      <path d="M -32 -32 L -29 -22 L -19 -20 L -29 -18 L -32 -8 L -35 -18 L -45 -20 L -35 -22 Z"/>
    </svg>
    <svg viewBox="-50 -50 100 100" width="72" height="72" fill="currentColor">
      <path d="M 0 -36 L 8 -8 L 36 0 L 8 8 L 0 36 L -8 8 L -36 0 L -8 -8 Z"/>
      <path d="M -32 -32 L -29 -22 L -19 -20 L -29 -18 L -32 -8 L -35 -18 L -45 -20 L -35 -22 Z"/>
    </svg>
  </div>
</div>

```html
<svg viewBox="-50 -50 100 100" fill="currentColor">
  <path d="M 0 -36 L 8 -8 L 36 0 L 8 8 L 0 36 L -8 8 L -36 0 L -8 -8 Z"/>
  <path d="M -32 -32 L -29 -22 L -19 -20 L -29 -18 L -32 -8 L -35 -18 L -45 -20 L -35 -22 Z"/>
</svg>
```

### Fallback Single Sparkle (use this at ≤14 px)

Below ~16 px the accent star muddies. The single-star variant reads cleaner at chip / inline / tooltip sizes.

<div class="preview" style="color: var(--brand);">
  <div class="preview-label">Fallback · ≤ 14 px</div>
  <div class="preview-stack">
    <svg viewBox="0 0 24 24" width="10" height="10" fill="currentColor"><path d="M12 0 L14 9 L24 12 L14 15 L12 24 L10 15 L0 12 L10 9 Z"/></svg>
    <svg viewBox="0 0 24 24" width="12" height="12" fill="currentColor"><path d="M12 0 L14 9 L24 12 L14 15 L12 24 L10 15 L0 12 L10 9 Z"/></svg>
    <svg viewBox="0 0 24 24" width="14" height="14" fill="currentColor"><path d="M12 0 L14 9 L24 12 L14 15 L12 24 L10 15 L0 12 L10 9 Z"/></svg>
  </div>
</div>

```html
<svg viewBox="0 0 24 24" fill="currentColor">
  <path d="M12 0 L14 9 L24 12 L14 15 L12 24 L10 15 L0 12 L10 9 Z"/>
</svg>
```

Rule: use `fill="currentColor"` on both marks so colour is controlled by the parent's `color`. The same markup renders purple on white and white on brand-purple. Never mix fills inside the SVG.

---

## Variant 1 — Inline icon

For menus, tooltips, list row badges, and any "this value was AI-generated" microcopy.

<div class="preview">
  <div class="preview-label">Preview</div>
  <div class="preview-stack">
    <span style="color: var(--brand); display: inline-flex; align-items: center; gap: 6px; font-weight: 500; font-size: 14px;">
      <svg viewBox="0 0 24 24" width="12" height="12" fill="currentColor"><path d="M12 0 L14 9 L24 12 L14 15 L12 24 L10 15 L0 12 L10 9 Z"/></svg>
      AI parsed this value
    </span>
  </div>
</div>

```html
<span style="color: var(--brand); display: inline-flex; align-items: center; gap: 6px;">
  <svg viewBox="0 0 24 24" width="12" height="12" fill="currentColor">
    <path d="M12 0 L14 9 L24 12 L14 15 L12 24 L10 15 L0 12 L10 9 Z"/>
  </svg>
  AI parsed this value
</span>
```

A common "sparkle-mini" tile (feature list, empty state, callout):

<div class="preview">
  <div class="preview-label">Preview</div>
  <div class="preview-stack">
    <span class="sparkle-mini"><svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 0 L14 9 L24 12 L14 15 L12 24 L10 15 L0 12 L10 9 Z"/></svg></span>
    <span style="display: flex; align-items: center; gap: 12px; font-size: 14px; color: var(--ink-soft);">
      <span class="sparkle-mini"><svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 0 L14 9 L24 12 L14 15 L12 24 L10 15 L0 12 L10 9 Z"/></svg></span>
      <span><strong style="color: var(--ink); display: block;">Bill capture</strong>Snap a supplier invoice — AI reads it.</span>
    </span>
  </div>
</div>

```css
.sparkle-mini {
  width: 28px; height: 28px;
  background: var(--brand-light);
  border-radius: 6px;
  display: flex; align-items: center; justify-content: center;
}
.sparkle-mini svg { width: 16px; height: 16px; color: var(--brand); }
```

---

## Variant 2 — Circular badge

For hero sections, large feature cards, empty states, onboarding tiles. Gives AI moments genuine presence.

<div class="preview">
  <div class="preview-label">Preview</div>
  <div class="preview-stack">
    <div class="ai-badge-circle" style="width: 48px; height: 48px;">
      <svg viewBox="-50 -50 100 100" fill="white" style="width: 24px; height: 24px;">
        <path d="M 0 -40 L 8 -8 L 40 0 L 8 8 L 0 40 L -8 8 L -40 0 L -8 -8 Z"/>
        <path d="M 32 -32 L 35 -22 L 45 -20 L 35 -18 L 32 -8 L 29 -18 L 19 -20 L 29 -22 Z"/>
      </svg>
    </div>
    <div class="ai-badge-circle" style="width: 64px; height: 64px;">
      <svg viewBox="-50 -50 100 100" fill="white" style="width: 32px; height: 32px;">
        <path d="M 0 -40 L 8 -8 L 40 0 L 8 8 L 0 40 L -8 8 L -40 0 L -8 -8 Z"/>
        <path d="M 32 -32 L 35 -22 L 45 -20 L 35 -18 L 32 -8 L 29 -18 L 19 -20 L 29 -22 Z"/>
      </svg>
    </div>
    <div class="ai-badge-circle">
      <svg viewBox="-50 -50 100 100" fill="white">
        <path d="M 0 -40 L 8 -8 L 40 0 L 8 8 L 0 40 L -8 8 L -40 0 L -8 -8 Z"/>
        <path d="M 32 -32 L 35 -22 L 45 -20 L 35 -18 L 32 -8 L 29 -18 L 19 -20 L 29 -22 Z"/>
      </svg>
    </div>
  </div>
</div>

```html
<div class="ai-badge-circle">
  <svg viewBox="-50 -50 100 100" fill="white">
    <path d="M 0 -40 L 8 -8 L 40 0 L 8 8 L 0 40 L -8 8 L -40 0 L -8 -8 Z"/>
    <path d="M 32 -32 L 35 -22 L 45 -20 L 35 -18 L 32 -8 L 29 -18 L 19 -20 L 29 -22 Z"/>
  </svg>
</div>
```

```css
.ai-badge-circle {
  width: 80px; height: 80px; border-radius: 50%;
  background: var(--brand);
  display: inline-flex; align-items: center; justify-content: center;
}
.ai-badge-circle svg { width: 40px; height: 40px; }
```

On dark/brand-purple backgrounds use `rgba(255,255,255,0.15)` as the disc fill so the sparkle glows instead of clashing.

---

## Variant 3 — CTA button (the "AI pill")

The primary AI entry-point on any screen. **Same look, same copy patterns, every time.**

<div class="preview">
  <div class="preview-label">Preview</div>
  <div class="preview-stack">
    <button class="ai-pill-btn" type="button">
      <svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 0 L14 9 L24 12 L14 15 L12 24 L10 15 L0 12 L10 9 Z"/></svg>
      Ask AI
    </button>
    <button class="ai-pill-btn" type="button">
      <svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 0 L14 9 L24 12 L14 15 L12 24 L10 15 L0 12 L10 9 Z"/></svg>
      Re-read
    </button>
    <button class="ai-pill-btn" type="button">
      <svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 0 L14 9 L24 12 L14 15 L12 24 L10 15 L0 12 L10 9 Z"/></svg>
      Scan bill
    </button>
    <button class="ai-pill-btn" type="button">
      <svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 0 L14 9 L24 12 L14 15 L12 24 L10 15 L0 12 L10 9 Z"/></svg>
      Post to Xero →
    </button>
  </div>
</div>

```html
<button class="ai-pill-btn">
  <svg viewBox="0 0 24 24" fill="currentColor">
    <path d="M12 0 L14 9 L24 12 L14 15 L12 24 L10 15 L0 12 L10 9 Z"/>
  </svg>
  Ask AI
</button>
```

```css
.ai-pill-btn {
  background: var(--brand); color: #fff;
  border: none;
  padding: 8px 14px;
  border-radius: 6px;
  font-family: inherit;
  font-size: 13px; font-weight: 500;
  cursor: pointer;
  display: inline-flex; align-items: center; gap: 7px;
  transition: background 0.15s;
}
.ai-pill-btn:hover { background: var(--brand-hover); }
.ai-pill-btn svg  { width: 14px; height: 14px; }
```

Approved button labels (choose the one that matches the action):

- `Ask AI` — open a chat / prompt
- `Re-read` — re-run extraction on the current document
- `Re-generate` — re-run output (quote, report, draft)
- `Scan bill`, `Scan receipt` — capture-and-extract entry-points
- `Post to job →`, `Post to Xero →` — confirmation after AI-assisted match

Never label an AI button with the model name ("Ask Claude", "Run GPT") or a vague verb ("Do it").

---

## Inline AI suggestion strip

For contextual nudges mid-page — "AI matched this bill to Job #2847". Use this treatment when AI is _proposing_ something the user can accept/reject inline.

<div class="preview" style="display: block;">
  <div class="preview-label">Preview</div>
  <div class="ai-suggest">
    <svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 0 L14 9 L24 12 L14 15 L12 24 L10 15 L0 12 L10 9 Z"/></svg>
    <div><strong>AI matched this bill</strong> to Job #2847 — Bayside Apts coil replacement. Post to Xero?</div>
  </div>
</div>

```html
<div class="ai-suggest">
  <svg viewBox="0 0 24 24" fill="currentColor">
    <path d="M12 0 L14 9 L24 12 L14 15 L12 24 L10 15 L0 12 L10 9 Z"/>
  </svg>
  <div><strong>AI matched this bill</strong> to Job #2847 — post to Xero?</div>
</div>
```

```css
.ai-suggest {
  background: linear-gradient(90deg, var(--brand-light) 0%, #fff 100%);
  border-left: 3px solid var(--brand);
  padding: 10px 14px;
  margin: 12px 0;
  border-radius: 4px;
  display: flex; align-items: center; gap: 10px;
  font-size: 13px;
}
.ai-suggest svg    { width: 16px; height: 16px; color: var(--brand); flex-shrink: 0; }
.ai-suggest strong { color: var(--brand); }
```

---

## "AI parsed" section label

For areas where AI populated field values (extracted bill items, generated quote lines, auto-filled customer data). Tells the user _why_ those values are there.

<div class="preview" style="display: block;">
  <div class="preview-label">Preview</div>
  <div class="items-label">
    <svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 0 L14 9 L24 12 L14 15 L12 24 L10 15 L0 12 L10 9 Z"/></svg>
    AI parsed these bill items
  </div>
</div>

```html
<div class="items-label">
  <svg viewBox="0 0 24 24" fill="currentColor">
    <path d="M12 0 L14 9 L24 12 L14 15 L12 24 L10 15 L0 12 L10 9 Z"/>
  </svg>
  AI parsed these bill items
</div>
```

```css
.items-label {
  display: flex; align-items: center; gap: 7px;
  font-size: 11px; font-weight: 700;
  color: var(--brand);
  text-transform: uppercase; letter-spacing: 0.7px;
  margin-top: 2px;
}
.items-label svg { width: 12px; height: 12px; }
```

---

## Do / Don't

**Do:**
- Always use `--brand` (#39006B) as the AI colour, even if your app has a different primary
- Keep the sparkle SVG byte-identical across projects — this is a brand mark, not a decorative icon
- Put the sparkle on the left of any AI button/label; label on the right
- Use the circular badge sparingly — 1 per page maximum
- Show the sparkle wherever AI-derived values are displayed, so the user always knows provenance

**Don't:**
- Don't substitute a different icon ("brain", "robot", "wand") for AI actions
- Don't animate the sparkle by default — it's a quiet signal, not a loading spinner
- Don't use the sparkle for non-AI features (e.g. "Premium", "New") — it must mean AI
- Don't place the sparkle inside destructive-action buttons (delete, cancel)
- Don't combine the sparkle with a model-name label
- **Don't put the sparkle (or any `AI` / `Manual` chip) on line-level rows in a table.** Provenance is a *group-level* signal: one banner below the set, one `Mixed provenance` pill on the header, and a split in the totals panel. Per-row chips are glitter — banned. Visual parity inside the table body is the rule.

---

## When to use which variant — decision table

| Context | Variant |
|---|---|
| Menu item, small label, field caption | Inline icon (12–14 px) |
| Feature-list row with icon tile | sparkle-mini (28 px tile, 16 px sparkle) |
| Primary screen action ("Ask AI", "Scan bill") | `.ai-pill-btn` CTA button |
| Mid-page suggestion / nudge | `.ai-suggest` strip |
| Section labelling AI-populated data | `.items-label` |
| Hero / empty state / onboarding moment | `.ai-badge-circle` (80 px) |
| Hero eyebrow chip ("New — ...") | brand-light pill + 14 px sparkle |

---

## Reference implementation

`docs/ai-styling-mockup.html` — open it in a browser for the full rendered pattern (hero, mock window, icon showcase, feature strip, spotlight card).

When adding AI features to any project in this workspace, open the mockup as your visual source-of-truth before writing new CSS.
