---
name: visual-competitive-analysis
description: Create visual competitive analysis pages that break down competitor brands by color palette, typography, layout patterns, positioning, and strategic threat level. Use when asked to analyze a competitor's visual identity, build a competitive landscape page, create brand DNA comparisons, or research competitor design systems. Triggers on "competitive analysis," "competitor research," "brand analysis," "visual research," "brand DNA," "competitive landscape," or "competition page." Produces CE-styleguide-compliant HTML pages with structured sections.
---

# Visual Competitive Analysis

Build structured, CE-styleguide-compliant competitive analysis pages that dissect competitor brands across visual identity, positioning, and strategic dimensions.

## Output Types

1. **Single brand deep-dive** — Full-page analysis of one competitor
2. **Index page** — Card grid showing all competitors at a glance, linking to individual pages

## Page Structure — Single Brand

Every brand page follows this structure. Sections 1-10 are always present. Image sections (A, B, C) are inserted when agency source images are available — they act as visual anchors, not galleries.

| # | Section | Component | Content |
|---|---------|-----------|---------|
| **A** | **Hero Image** | `image-hero` | **One single large image** — full container width (1100px), 480px height, object-fit cover. Must be reflective of the brand identity (not a campaign photo). Use one large image, NOT a mosaic or collage. This is the first thing the viewer sees — it must immediately say "this is [Brand]." Choose the most brand-representative image available: the signature color, the product, the identity system in context. |
| 1 | Quick Facts | `facts-grid` (4-col, 4-8 cells) | Revenue, margin, users, AUM, avg balance, growth, founded |
| 2 | Positioning | Narrative + `callout` + `tags` | Market position, mission, recent pivots, key exec quotes |
| 3 | Brand Evolution | `timeline` | Chronological brand moments: founding → rebrands → crises → current |
| 4 | Color Palette | `palette-grid` (5-col) + `image-alongside` | 3-6 swatches: hex, role name, extracted from live CSS. One agency image alongside showing palette in actual use. |
| 5 | Typography | `type-specimen` + `type-details` + `image-alongside` | Font family, weights, character. One agency image showing the headline typeface in context. |
| **B** | **Brand in Practice** | `image-grid` (3-col) | 6 agency images in a 3-col grid. No captions. Placed after Typography, before Layout. Shows the identity system in real-world application. |
| 6 | Layout & UX | `two-col` (2 rows) | Density, theme posture, grid structure, interaction patterns |
| 7 | Assessment | `table` (accordion) | What works / what doesn't. **Accordion — summary row always visible, click to expand full table.** |
| 8 | Strategic Verdict | `verdict-grid` (4-col) | Borrow / Reject / Watch / Threat Level |
| 9 | Brand Personality | `three-col` (accordion) | Archetype, voice, target audience signal. **Accordion — collapsed by default.** |
| 10 | vs Client | `table` + `callout` (accordion) | Head-to-head comparison + strategic implication. **Accordion — collapsed by default.** |
| **C** | **More from Agency** | `image-strip` (horizontal scroll) | 4-6 remaining agency images in a horizontal scroll strip. Source credit: "Via [Agency Name]" in `--light` color. |
| 11 | Social Strategy | `platform-grid` + `content-pillars` | Platform presence (followers, frequency, tone per channel: IG/TikTok/X/YouTube/LinkedIn). Content pillar breakdown with % split. Top-performing formats. Paid vs organic signals. **Instagram grid: match native format — posts = 1:1 square containers, stories/reels = 9:16 portrait containers. Never force one format into the other.** **Accordion — open by default.** |
| 12 | Content & Campaign | `campaign-card` + `timeline-row` | Hero campaigns (name, agency, year, media mix, notable talent). OOH, TV, digital, creator collabs. Campaign visual language assessment. **Accordion — collapsed by default.** |
| 13 | Audience & Community | `three-col` + `callout` | Who engages (demographics, psychographics). Sentiment signals. UGC behavior. Community management style — how they reply, handle complaints, reward advocates. **Accordion — collapsed by default.** |

## Page UX — Sticky Nav + Accordions

Every single-brand page MUST include:

### Sticky Section Nav
A fixed bar at the top (appears after scrolling past the page header) with pill-links to each section. Active section highlights in `--black`. Implementation:

```html
<nav class="section-nav" id="section-nav">
  <div class="container">
    <div class="nav-pills">
      <a href="#quick-facts" class="nav-pill active">Facts</a>
      <a href="#positioning" class="nav-pill">Positioning</a>
      <a href="#brand-evolution" class="nav-pill">Evolution</a>
      <a href="#color" class="nav-pill">Color</a>
      <a href="#typography" class="nav-pill">Type</a>
      <a href="#brand-in-practice" class="nav-pill">In Practice</a>
      <a href="#layout" class="nav-pill">Layout</a>
      <a href="#assessment" class="nav-pill">Assessment</a>
      <a href="#verdict" class="nav-pill">Verdict</a>
      <a href="#social" class="nav-pill">Social</a>
      <a href="#campaigns" class="nav-pill">Campaigns</a>
      <a href="#audience" class="nav-pill">Audience</a>
      <a href="#vs-client" class="nav-pill">vs eToro</a>
    </div>
  </div>
</nav>
```

CSS: `position: sticky; top: 0; z-index: 100; background: #fff; border-bottom: 1px solid #eee; padding: 12px 0;`
Active detection: IntersectionObserver on each section, update `.active` class on corresponding pill.

### Accordions (3 sections)
Assessment, Brand Personality, and vs Client sections use accordion pattern:

```html
<div class="accordion-section" data-section="assessment">
  <div class="accordion-header" onclick="toggleAccordion(this)">
    <span class="accordion-summary">7 dimensions assessed — 4 strong, 3 weak</span>
    <span class="accordion-icon">+</span>
  </div>
  <div class="accordion-body">
    <!-- full table content -->
  </div>
</div>
```

JS: toggle `open` class, animate `max-height` from 0 to content height.
Default state: Assessment = **open** (most used), Personality + vs Client = **closed**.

## Image Integration Patterns

Agency images are **design elements**, not a gallery. Three placement modes:

### A — Hero Image (full-width anchor)
```html
<div class="image-hero">
  <img src="[agency-img-01.jpg]" alt="[Brand] — [Agency] 2024" loading="lazy">
</div>
```
CSS: `width: 100%; height: 480px; object-fit: cover; object-position: center;`
Place: immediately after `<header>`, before section 1.
Use: the most compositionally strong image — usually the identity system overview shot.

### B — Image Alongside (paired with section content)
```html
<div class="section-with-image">
  <div class="section-content"><!-- palette or type specimen --></div>
  <div class="section-image">
    <img src="[agency-img]" alt="" loading="lazy">
  </div>
</div>
```
CSS: `display: grid; grid-template-columns: 1fr 1fr; gap: 40px; align-items: start;`
Use in: Color Palette section (shows palette in use), Typography section (shows typeface in context).

### C — Brand in Practice Grid (3-col, 6 images)
```html
<section id="brand-in-practice">
  <p class="section-label">Brand in Practice</p>
  <p class="agency-credit">Via Porto Rocha, 2024</p>
  <div class="image-grid">
    <img src="img-02.jpg" loading="lazy">
    <img src="img-03.jpg" loading="lazy">
    <img src="img-04.jpg" loading="lazy">
    <img src="img-05.jpg" loading="lazy">
    <img src="img-06.jpg" loading="lazy">
    <img src="img-07.jpg" loading="lazy">
  </div>
</section>
```
CSS: `display: grid; grid-template-columns: repeat(3, 1fr); gap: 2px;` — no padding, images flush to each other. Each image: `aspect-ratio: 16/9; object-fit: cover; width: 100%;`

### D — Horizontal Image Strip (end of page)
```html
<section class="image-strip-section">
  <p class="section-label">More from Porto Rocha</p>
  <div class="image-strip">
    <img src="img-08.jpg" loading="lazy">
    <img src="img-09.jpg" loading="lazy">
    <!-- ... -->
  </div>
</section>
```
CSS: `display: flex; gap: 2px; overflow-x: auto; scroll-snap-type: x mandatory;` Each image: `flex: 0 0 380px; height: 240px; object-fit: cover; scroll-snap-align: start;`

**Rules for all image placements:**
- `alt` text: `"[Brand] — [Agency] [Year]"` or empty for purely decorative
- No captions below images — let visuals speak
- No borders, shadows, border-radius on images
- Agency credit in `--light` color, 10px, uppercase
- Images from `/assets/[brand]/` folder (copy from agency-images dir after download)

## CE Style Guide Compliance

Every page must pass the CE quality gate. Non-negotiable rules:

- **Background:** white (`#fff`) — never dark
- **Fonts:** Larken (display/headings), Inter (body), JetBrains Mono (data/code)
- **Larken:** Load via Typekit `https://use.typekit.net/ffj8sbd.css`
- **Colors:** Only 6 values — `--red: #cc0000`, `--black: #1a1a1a`, `--grey: #666`, `--light: #999`, `--border: #eee`, `--bg: #fff`
- **Container:** `max-width: 1100px` (index pages may use 1400px for card grids)
- **Section labels:** 10px, uppercase, 0.1em tracking, `--red`
- **Headings:** Larken, 400 weight, -0.02em letter-spacing
- **Max text width:** 680px for body paragraphs
- **Borders:** 1px solid `#eee` only — no thicker, no `#e5e5e5`
- **No:** gradients, box-shadows, bold (700), border-radius > 4px, emojis, stock photos

## Template

Start from `assets/brand-page-template.html`. It contains all CSS and component markup patterns. Replace `{{PLACEHOLDERS}}` with real content.

## Research Process

Read `references/research-methodology.md` for the full data collection checklist per brand. Summary:

### Step 0 — Agency Source Extraction (ALWAYS first)

Before touching the live site, identify who did the brand work and extract primary visual assets directly from their case study.

**How to identify the agency:**
```bash
web_search "[Brand Name] rebrand agency case study"
# Common outputs: Porto Rocha, Collins, Koto, Wolff Olins, DixonBaxi, Pentagram, Character
```

**Extract images from the agency case study:**

| Agency CMS | Extraction method |
|---|---|
| **Prismic** (Porto Rocha, many studios) | Hit `https://[studio].cdn.prismic.io/api/v2` → get master ref → query `case_study` type by uid |
| **Sanity CDN** (Koto, Wolff Olins) | `extract-images.sh` handles automatically |
| **Mux video** (Collins, W+K) | `extract-images.sh` handles automatically — pulls `.webp` thumbnails |
| **Cloudinary / imgix** | `extract-images.sh` handles automatically |
| **Standard HTML** | `extract-images.sh "https://agency.com/case-study/brand" ./output 15` |

**Prismic API pattern (Porto Rocha example):**
```bash
# 1. Get master ref
MASTER_REF=$(curl -sL "https://[studio].cdn.prismic.io/api/v2" | python3 -c "import json,sys; d=json.load(sys.stdin); print([r['ref'] for r in d['refs'] if r.get('isMasterRef')][0])")

# 2. Get all case studies, find the brand
curl -sL "https://[studio].cdn.prismic.io/api/v2/documents/search?ref=${MASTER_REF}&q=%5B%5Bat(document.type%2C%22case_study%22)%5D%5D&pageSize=100"

# 3. Pull images for specific uid
curl -sL "https://[studio].cdn.prismic.io/api/v2/documents/search?ref=${MASTER_REF}&q=%5B%5Bat(my.case_study.uid%2C%22[brand-uid]%22)%5D%5D" | python3 -c "
import json,sys
data=json.load(sys.stdin)
def find_imgs(obj,depth=0,imgs=[]):
    if depth>15: return imgs
    if isinstance(obj,dict):
        url=obj.get('url','')
        if url and 'prismic' in url and any(e in url.lower() for e in ['.jpg','.png','.webp']):
            imgs.append(url)
        [find_imgs(v,depth+1,imgs) for v in obj.values()]
    elif isinstance(obj,list):
        [find_imgs(i,depth+1,imgs) for i in obj]
    return imgs
[print(i) for i in find_imgs(data.get('results',[{}])[0].get('data',{}))]
"
```

**Download at 1400px:**
```bash
# Add &w=1400 to any Prismic URL
curl -sL "https://images.prismic.io/[studio]/[hash]_[name].jpg?auto=format,compress&w=1400" -o brand-01.jpg
```

**Output:** 10-20 production-quality images saved to `./agency-images/[brand]/`

---

### Step 1 — Existing project data
Check the project's `brand/strategy/` folder and any prior research files before searching externally.

### Step 2 — Live site inspection
Extract actual colors, fonts, copy from the live site CSS:
```bash
nohup pinchtab --headless > /tmp/pinchtab.log 2>&1 &
sleep 3
pinchtab nav "https://brand.com" && sleep 5
pinchtab text > /tmp/brand-text.txt
```
For CSS values: use `scrapling` or `curl` + grep for hex values, font-family declarations.

### Step 3 — Financial data
Public filings, earnings, investor materials.

### Step 4 — Recent brand moves
`web_search` for rebrands, acquisitions, pivots in last 90 days.

### Step 5 — Compile into sections
Fill each of the 10 sections + image sections with sourced data.

## Index Page

When building the index/overview page with all competitors, read `references/index-page-structure.md` for card grid format and tier organization.

## Deployment

Place completed pages in the project's `visual-research/` folder:
```
visual-research/
├── index.html          ← All-brands index
├── robinhood/index.html
├── revolut/index.html
├── coinbase/index.html
└── ...
```

For staging deployment: copy to `public/{{project}}-competition/{{brand}}/index.html`, commit, push.

## Quality Checklist

Before delivering any page, verify:

- [ ] Typekit loaded (`ffj8sbd`)
- [ ] Only Larken / Inter / JetBrains Mono
- [ ] Only 6 CE colors used
- [ ] `grep -i "gradient"` → 0 results
- [ ] `grep "box-shadow"` → 0 results
- [ ] `grep "font-weight.*[6-9]00"` → 0 results
- [ ] Container max-width correct
- [ ] All 10 sections present (or explicitly omitted with reason)
- [ ] Responsive at 600px and 900px breakpoints
- [ ] Data sourced and current (note dates on financial figures)
- [ ] Sticky section nav present and scrollspy working
- [ ] Assessment accordion open by default; Personality + vs Client closed
- [ ] Agency source images present (Step 0 was run)
- [ ] Hero image placed (Section A) — ONE large brand-representative image, NOT a mosaic/collage
- [ ] Brand in Practice grid present (Section B) with agency credit
- [ ] Horizontal image strip present (Section C)
- [ ] Image assets copied to `assets/[brand]/` folder (not hotlinked from tmp)

## Visual QA Gate — MANDATORY

**No page deploys without passing visual QA.** This is a hard gate, not optional.

### Process
1. Deploy page to staging
2. Run `python3 scripts/visual-qa/section-audit.py <staging-url>`
   - Playwright scrolls full page (triggers lazy-load), captures screenshot
   - ImageMagick slices into 900px sections
   - Vision model audits each section against 7 criteria
3. **All FAILs must be fixed** before reporting complete
4. WARNs are flagged but don't block deploy
5. Re-run audit after fixes to confirm resolution

### 7 Criteria (locked)
1. **Image fit** — no stretching, no overflow, no cropping that loses subject
2. **Image visibility** — actually loads, no broken refs, no alt-text showing
3. **Aspect ratio** — natural for subject, consistent within grids
4. **Content relevance** — right image in right section context
5. **Spacing & alignment** — no dead space, balanced columns, no mismatched heights
6. **Text readability** — sufficient contrast, no clipping, no orphan lines
7. **Visual hierarchy** — clear section flow, hero prominence, proper label/heading/body order

### Sub-agent briefs
Every build brief MUST include: "Run visual QA (`scripts/visual-qa/section-audit.py`) before reporting done. All FAILs must be resolved."
