| name | html-mckinsey-style |
| description | McKinsey Blue genre — consulting/strategy authority. Use when: strategy, roadmap, transformation, operating model, capability map, recommendation, board report, CEO briefing, board deck, decision memo, strategic options, investment case, go/no-go. Trigger: strategy / roadmap / transformation / operating model / recommendation / board report / consulting / CEO briefing / board deck / decision memo / go-no-go / 战略 / 咨询 / 路线图 / 董事会. Inherits typography-system. NOT for: raw data dashboards (bloomberg). |
name: html-mckinsey-style
description: "Use when generating strategic/prescriptive HTML documents: strategy plans, board decks, executive recommendations, transformation roadmaps, operating model designs. Trigger: document purpose is to RECOMMEND, STRATEGIZE, or DRIVE DECISIONS for C-suite audience. Routed by html-style-router — do not invoke directly unless router has already selected this style."
combo-tags: [html-rendering]
HTML Document Style -- McKinsey Blue (Management Consulting)
Typography base (inherited): this skill composes ON TOP of the shared
typography-system foundation — link/inline
tokens/typography.css FIRST, then layer this skill for color + accent +
brand font-family ONLY. Never re-declare the type scale, vertical rhythm,
measure, page frame, or CJK rules; keep mixed CJK+Latin stacks Latin-first.
Verify: python3 scripts/audit-genre-typography.py.
The strategy and decision-making style for board presentations, consulting
deliverables, transformation plans, CEO briefings, and any document whose primary
function is driving executive action.
Apply this style when generating single-file HTML deliverables of type:
strategy plan, transformation roadmap, board report, consulting deliverable,
executive recommendation, business case, operating model, capability assessment,
or any document structured as "conclusion first, then supporting evidence".
For documentation/guides, use html-document-style (Claude).
For research reports/briefings, use html-economist-style (Economist).
Universal Layout Frame (MUST inject before any other CSS)
This block is non-negotiable. It satisfies pre-tool-style-router-gate.py dual-verify
(identifier + canonical token signature --mck-) AND prevents the hero/body
misalignment bug Gotcha #6+#13 by giving cover and body content one shared
reference frame at any viewport width.
:root{
--mck-page-max:1280px;
--mck-page-gutter-total:clamp(32px,6vw,96px);
}
.frame{
width:min(var(--mck-page-max),calc(100% - var(--mck-page-gutter-total)));
margin-inline:auto;
}
.cover{padding:96px 0 80px;}
main.frame{padding:64px 0 80px;}
<section class="cover">
<div class="frame">
<h2>Section · Date · McKinsey Blue</h2>
<h1>Document Title</h1>
<p class="subtitle">…</p>
<div class="meta">…</div>
</div>
</section>
<main class="frame">
<h2 class="section">…</h2>
…
</main>
Why this is the contract, not a suggestion:
- the cover background fills viewport (
background: var(--mckinsey-navy)) but its
visible content lives inside .frame, sharing the SAME width: min(--mck-page-max, …)
computation as <main class="frame">. Hero text and first body section share x=0 at any viewport.
- the asymmetric
padding-inline: 8vw on .cover combined with max-width: 1280px; margin: 0 auto
on <main> is the exact bug that breaks alignment on wide screens (>1480px). Never use that pattern.
- the
--mck- prefix satisfies the PreToolUse style-router gate without needing an
escape hatch. Use it consistently with verbose tokens (e.g. --mckinsey-navy) in the same :root.
Design Philosophy
- Conclusion-first: Every section leads with a "so what" statement
- Framework-driven: 2x2 matrices, numbered pillars, phased roadmaps
- Blue authority: Deep blue conveys institutional trust and seniority
- Hierarchical numbering: Rigid 1.1 / 1.2 / 1.2.1 structure
- Action-oriented: Every section ends with implications or next steps
- Minimal decoration: No ornament that doesn't serve the argument
Color Palette (CSS Custom Properties)
:root {
--blue-900: #002855;
--blue-700: #003A70;
--blue-500: #0066B3;
--blue-100: #E8F0FE;
--blue-50: #F4F7FB;
--green: #1B7F4B;
--green-light: #E6F4EC;
--amber: #D4850D;
--amber-light: #FEF3E0;
--red: #C4281C;
--red-light: #FDECEB;
--ink: #1A1A2E;
--body: #2D2D3F;
--secondary: #5A5A72;
--muted: #8E8EA0;
--rule: #D4D4DC;
--rule-strong: #1A1A2E;
--bg: #FFFFFF;
--bg-gray: #F5F5F8;
--bg-dark: #002855;
--font-headline: 'Inter', 'Noto Sans SC', 'PingFang SC', 'Microsoft YaHei', sans-serif;
--font-body: 'Inter', 'Noto Sans SC', 'PingFang SC', 'Microsoft YaHei', sans-serif;
--font-mono: 'JetBrains Mono', 'SF Mono', monospace;
}
Typography Rules
Font Loading (Google Fonts)
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&family=Noto+Sans+SC:wght@400;500;700&display=swap" rel="stylesheet">
Key: Single Font Family
Unlike Claude (serif+sans) or Economist (sans+serif), McKinsey uses a single
sans-serif family throughout. Hierarchy is achieved through weight, size, and
color contrast alone. This creates a "corporate uniform" feel.
| Element | Weight | Size | Color | Usage |
|---|
| Page title (h1) | 900 | 2.5rem | white on --bg-dark | Hero banner |
| Section title (h2) | 800 | 1.5rem | --ink | Section headings |
| Subsection (h3) | 700 | 1.15rem | --ink | Card/pillar titles |
| Body text | 400 | 15px | --body | Paragraphs |
| Section number | 700 | 13px | --blue-700 | "01 / 02 / 03" labels |
| Key message | 600 | 1.1rem | white on --blue-700 | Action bar callouts |
| Data labels | 600 | 12px | --secondary | KPI labels, table headers |
| Footnotes | 400 | 12px | --muted | Sources, disclaimers |
CJK Optimization
body {
-webkit-font-smoothing: antialiased;
}
Structural Elements
Hero Banner (Dark Blue, Inverted)
Full-width dark blue banner with white text. This is the consulting "title slide".
Critical: Always use a single .hero-inner wrapper to constrain content. Never use .hero > * with margin: auto — it causes each child's max-width to center independently, misaligning elements that have different max-widths (e.g., tag vs h1 vs subtitle).
.hero {
background: var(--bg-dark);
color: #fff;
padding: 56px 0;
}
.hero-inner {
max-width: 1400px;
margin: 0 auto;
padding: 0 4vw;
}
.hero h1 {
font-weight: 900;
font-size: 2.5rem;
line-height: 1.15;
color: #fff;
margin-bottom: 16px;
max-width: 900px;
}
.hero .subtitle {
color: rgba(255,255,255,0.75);
font-size: 1.1rem;
font-weight: 400;
max-width: 720px;
}
<div class="hero">
<div class="hero-inner">
<div class="hero-tag">REPORT TITLE</div>
<h1>Document Title Here</h1>
<div class="subtitle">Subtitle text...</div>
</div>
</div>
Section Numbers
Every section gets a formatted number label above the h2:
.section-num {
font-family: var(--font-headline);
font-size: 13px;
font-weight: 700;
color: var(--blue-700);
letter-spacing: 2px;
margin-bottom: 6px;
}
Key Message Bar
A full-width blue bar containing the section's "so what" conclusion:
.key-message {
background: var(--blue-700);
color: #fff;
padding: 16px 24px;
font-weight: 600;
font-size: 1.05rem;
line-height: 1.6;
margin: 20px 0;
}
Pillars (Numbered Columns)
The classic consulting "3 pillars" or "4 levers" layout:
.pillar-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 0;
border: 1px solid var(--rule);
}
.pillar {
padding: 24px;
border-right: 1px solid var(--rule);
}
.pillar:last-child { border-right: none; }
.pillar-num {
font-size: 2rem;
font-weight: 900;
color: var(--blue-700);
margin-bottom: 8px;
}
.pillar h3 {
border-bottom: 2px solid var(--blue-700);
padding-bottom: 8px;
margin-bottom: 12px;
}
Cards (Flat, Blue Top Border)
.card {
background: var(--bg);
border: 1px solid var(--rule);
border-top: 3px solid var(--blue-700);
padding: 24px;
}
KPI Grid (Data Strip)
.kpi-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 1px;
background: var(--rule);
border: 1px solid var(--rule);
}
.kpi {
padding: 20px 24px;
background: var(--bg);
}
.kpi .label {
font-size: 12px;
font-weight: 600;
color: var(--secondary);
text-transform: uppercase;
letter-spacing: 1.5px;
margin-bottom: 8px;
}
.kpi .value {
font-size: 1.6rem;
font-weight: 800;
color: var(--blue-700);
line-height: 1.2;
}
.kpi .context {
font-size: 13px;
color: var(--secondary);
margin-top: 4px;
}
Framework Box (2x2 Matrix)
The quintessential consulting visual:
.matrix-2x2 {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 0;
border: 2px solid var(--blue-700);
}
.matrix-cell {
padding: 24px;
border: 1px solid var(--rule);
}
.matrix-cell.top-right { background: var(--blue-100); }
.matrix-cell.bottom-left { background: var(--bg-gray); }
Traffic Light Status
.status-green { color: var(--green); }
.status-amber { color: var(--amber); }
.status-red { color: var(--red); }
.status-tag {
display: inline-block;
font-size: 11px;
font-weight: 700;
padding: 4px 12px;
text-transform: uppercase;
letter-spacing: 1px;
}
.status-tag.green { background: var(--green-light); color: var(--green); }
.status-tag.amber { background: var(--amber-light); color: var(--amber); }
.status-tag.red { background: var(--red-light); color: var(--red); }
Tables (Corporate Clean)
th {
background: var(--blue-900);
color: #fff;
font-weight: 600;
font-size: 12px;
text-transform: uppercase;
letter-spacing: 0.08em;
padding: 12px 16px;
}
td {
padding: 12px 16px;
border-bottom: 1px solid var(--rule);
font-size: 14px;
}
tr:nth-child(even) td { background: var(--blue-50); }
Timeline / Phased Roadmap
.phase-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 0;
border: 1px solid var(--rule);
}
.phase {
padding: 24px;
border-right: 1px solid var(--rule);
}
.phase:last-child { border-right: none; }
.phase-header {
background: var(--blue-700);
color: #fff;
padding: 10px 16px;
font-weight: 700;
font-size: 14px;
margin: -24px -24px 20px;
}
.phase-header.phase-2 { background: var(--blue-500); }
.phase-header.phase-3 { background: #0088CC; }
Callouts
.callout {
background: var(--blue-100);
border-left: 4px solid var(--blue-700);
padding: 20px 24px;
font-size: 0.95rem;
}
.callout-risk {
background: var(--red-light);
border-left: 4px solid var(--red);
padding: 20px 24px;
}
.callout-action {
background: var(--amber-light);
border-left: 4px solid var(--amber);
padding: 20px 24px;
}
Implication Box (Section Closer)
Every section should close with an implication or action box:
.implication {
background: var(--bg-gray);
border: 1px solid var(--rule);
border-left: 4px solid var(--blue-700);
padding: 20px 24px;
margin-top: 24px;
}
.implication-label {
font-size: 11px;
font-weight: 700;
color: var(--blue-700);
text-transform: uppercase;
letter-spacing: 2px;
margin-bottom: 8px;
}
Layout Principles
- Max-width: 1040px centered container
- Padding: 40px horizontal
- Section spacing: 48px between sections, separated by 1px rules
- No border-radius: 0px everywhere (corporate precision)
- No box-shadow: Flat surfaces (print-ready)
- No hover animations: Static document feel
- Alternating section backgrounds: White and --bg-gray for visual rhythm
- Full-width hero: Hero extends edge-to-edge (container inside)
Grid Rules
.grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 24px; }
.grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 24px; }
.grid-4 { display: grid; grid-template-columns: repeat(4, 1fr); gap: 24px; }
@media (max-width: 960px) {
.grid-3, .grid-4, .pillar-grid, .phase-grid { grid-template-columns: 1fr; }
.grid-2, .matrix-2x2 { grid-template-columns: 1fr; }
}
Content Structure Pattern
McKinsey documents follow a rigid "pyramid principle" structure:
HERO: Title + one-sentence recommendation
│
├── EXECUTIVE SUMMARY (conclusion first)
│ ├── KPI grid (4 metrics)
│ └── Key message bar ("so what")
│
├── SECTION 01: [Finding/Pillar]
│ ├── Section number + title
│ ├── Key message bar
│ ├── Supporting evidence (cards/tables/charts)
│ └── Implication box
│
├── SECTION 02: [Finding/Pillar]
│ └── (same structure)
│
├── SECTION 03: [Finding/Pillar]
│ └── (same structure)
│
├── RECOMMENDATION / ROADMAP
│ ├── Phase grid (3 phases)
│ └── Key actions with owners
│
├── RISKS & MITIGATIONS
│ ├── Traffic light status table
│ └── Risk callouts
│
└── APPENDIX / SOURCES
Footer
<footer class="site-footer">
<p>[ProjectName] -- [Document Type]</p>
<p>Your Name | your@email.com</p>
<p class="attr">[Confidentiality notice + generation date]</p>
</footer>
Dark blue top border on footer. For consulting deliverables, add:
CONFIDENTIAL -- For internal use only in the attr line.
Gotchas
-
Hero padding collapses on mobile — add responsive override. The hero uses padding: 56px 48px which looks fine on desktop but wastes horizontal space on mobile. Without @media (max-width: 640px) { .hero { padding: 32px 20px; } }, the title will be cramped on narrow screens. Every McKinsey doc gets opened on iPads in meetings.
-
Section number "01" gets parsed as an ordered list by some Markdown renderers. If you're generating the HTML from Markdown intermediate, 01 at line start triggers <ol> rendering. Always generate the section number as a <span class="section-num"> directly in HTML, never as raw text.
-
KPI grid breaks at exactly 3 items — use grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)) only for variable counts. The default repeat(4, 1fr) leaves an empty cell when you have 3 KPIs. Either always use 4 KPIs, or switch to repeat(3, 1fr) explicitly. Never use auto-fit for KPIs — it produces unpredictable widths at different viewport sizes.
-
Traffic light colors fail WCAG on white backgrounds. --amber: #D4850D and --green: #1B7F4B as text-on-white have contrast ratios of ~3.5:1 and ~4.2:1. For text labels, always pair traffic light colors with their *-light background variants (e.g., green text on --green-light background), or use them only for .status-tag badges with sufficient padding.
-
Phase grid headers use negative margin hack — breaks when container has overflow: hidden. The .phase-header uses margin: -24px -24px 20px to bleed into the .phase padding. If any parent has overflow: hidden or overflow: auto, the header clips. When nesting phases inside scrollable containers, switch to a separate <div> outside the padded area instead.
-
Hero/cover padding eats child percentage width — content misaligns with body sections. If .cover has padding: 0 Xvw and .cover-inner uses width: 92%, the 92% is relative to the cover's content box (100vw - 2*Xvw), NOT the viewport. Body sections with width: 92% are relative to body (100vw). Fix: set hero horizontal padding to 0 and center .cover-inner with width: 92%; max-width: 1040px; margin: 0 auto (or use flexbox align-items: center). The hero background stays full-width; only the content is constrained.
-
Partial-width pseudo-element overlays create visible color seams on dark hero backgrounds. A ::before with width: 40vw positioned at one side creates a hard color boundary where the overlay starts. On gradient backgrounds this appears as a vertical "stripe". Fix: either use full-width radial-gradient that fades to transparent, or just remove the overlay entirely (content: none) — if the base gradient is well-designed, the overlay adds zero value and only introduces risk. Less is more on dark hero backgrounds.
-
Mixed CJK/Latin proper names break at word boundaries in narrow containers. In Chinese-dominant text, English proper names like "Air Canada" get split across two lines at the space ("Air" on line 1, "Canada..." on line 2). word-break: keep-all only prevents CJK mid-word breaks — it does NOT prevent English word-level wrapping. Fix: always use between words of proper names that must stay together (Air Canada, Amazon Kiro, Replit AI). Also ensure card containers have minmax(340px, 1fr) minimum — 300px is too narrow for mixed CJK/English content.
-
Flex-wrap flow diagrams with >5 nodes overflow unpredictably. A single .flow-row with flex-wrap: wrap holding 5+ nodes + arrows will wrap the last node(s) to a second row at certain viewport widths, creating an ugly orphan node. Fix: never put >4 flow nodes in a single flex row. For 5-6 node pipelines, explicitly split into two .flow-row divs (3+3 or 3+2) with a vertical connector arrow between them. Set flex-wrap: nowrap on each row to prevent any further wrapping. Also reduce min-width on .flow-node to 110px and allow flex-shrink: 1.
-
overflow-x: auto on ANY container is a scrollbar risk — audit all containers. Not just .table-wrapper — also .flow-container, .decision-tree, .case-grid, and any container with dynamic content. In single-file HTML documents for executive reading, horizontal scrollbars are never acceptable. Fix: use overflow-x: hidden globally on html, body as a safety net, AND set overflow-x: hidden on every container that previously used auto. Ensure table-layout: fixed on all tables so content wraps instead of expanding.
-
Never present large directory trees or IA maps as one giant dark pre block. In strategic documents, a full-screen monospace block destroys scanability: readers only see white bars, not architecture. Fix: present filesystem or taxonomy structures as (1) domain cards or grouped pillars, (2) a role/ownership table, and only then (3) an optional appendix details block with the raw tree. Raw trees are evidence, not the primary visual.
-
Table first-column numbers wrap on table-layout: fixed with percentage widths. A width: 3% column holding row numbers like "10", "11", "13" will wrap each digit to a separate line when table-layout: fixed is active. Fix: use width: 40px (absolute, not percentage) on narrow ID/number columns, AND add white-space: nowrap to tbody td:first-child. Never use percentage widths below 5% with fixed table layout — the rounding produces sub-character widths.
-
.hero > * with margin: auto misaligns children with different max-widths. When the hero tag has no max-width (spans full container) but h1 has max-width: 900px and subtitle has max-width: 720px, each element centers independently at its own width. The tag appears left-aligned while the title appears centered — visual chaos. Fix: ALWAYS wrap hero content in a single .hero-inner div (max-width + margin: 0 auto + padding: 0 4vw). Children inside .hero-inner are naturally left-aligned. Their individual max-width limits line length without affecting alignment. The hero background stays full-width; only the inner wrapper constrains content.
-
Table label columns break CJK compound terms mid-phrase. A label column narrower than ~120px will split "模型切换" into "模型切 / 换", "成本可预测性" into "成本可 / 预测性", or "Claude Code 文档" across 3 lines. Fix: set white-space: nowrap; min-width: 120px on th:first-child, td:first-child (or any label column). Data columns with long content should use word-break: break-word. Rule: label columns never wrap; data columns may wrap.
-
Multi-column comparison tables overflow the container. A table with 1 label + 4 data columns, all white-space: nowrap, will clip the last column on any screen under ~1600px. Fix: use table-layout: fixed; width: 100% with explicit percentage widths — label column ~12%, each data column gets equal share of the rest (~22% each for 4 columns). Add word-break: break-word on data cells so long content wraps instead of overflowing. Never apply white-space: nowrap globally to all td in wide tables.
-
Hero subtitle and meta text disappear on dark gradient backgrounds. Using opacity: 0.7 or opacity: 0.85 on hero subtitle/meta text makes it unreadable on deep blue gradient backgrounds — the effective contrast ratio drops below WCAG AA (4.5:1). Fix: never use opacity for text on dark backgrounds. Instead use explicit rgba(255,255,255,0.85) for subtitle and rgba(255,255,255,0.85) for meta. The minimum acceptable alpha for white text on #002855 is 0.82. Prefer color over opacity because opacity affects the entire element including children.
-
Diagram / code block content hugs borders. ASCII art diagrams and pre blocks inside .diagram containers need generous top padding because the floating label badge (.diagram::before) overlaps the first line. Fix: always set .diagram { padding: 36px 40px 28px } (extra 8px top for label clearance). For pre blocks outside .diagram, ensure padding: 20px 24px minimum. Never go below padding: 16px on any code/diagram container.
-
Content container max-width 960px feels narrow on modern wide screens. At 960px, CJK-heavy documents with tables and diagrams look cramped on 1440px+ displays — tables truncate and code blocks scroll horizontally. Fix: use max-width: 1100px as the default container width for McKinsey-style documents. This provides comfortable reading width for CJK text, prevents table overflow, and still looks good on 1280px screens. Also apply the same max-width consistently to .container, .section, .toc, and any other max-width-constrained element — mismatched widths cause visual misalignment between sections.
-
A counter-driven numbered-list class cannot be downgraded to a bullet list by inline overrides — the number circle still paints and overlaps the text. An ordered-list style (e.g. .ol) that draws its number via li::before { content: counter(step); position: absolute; left: 0; width: 26px } also reserves matching left padding (padding-left: 42px) so the text clears the circle. If you reuse that same class for a non-numbered list and try to neutralize it inline with counter-reset: none; list-style: none + padding-left: 0, the circle STILL renders on top of the first characters of every line. WHY: counter-reset: none does not stop counter-increment (the counter keeps advancing), and list-style: none only governs the native list marker — it has no effect on a ::before pseudo-element. So the two properties people reach for to "turn off the number" cannot reach the marker, which lives in ::before. Removing the padding then drops the persistent circle straight onto the text. Fix: define a SEPARATE non-numbered list class and use it for honest-limits / caveats / plain bullets — e.g. .flatlist { list-style: none; padding: 0 } .flatlist li { position: relative; padding-left: 22px } .flatlist li::before { content: "—"; position: absolute; left: 0; color: var(--mck-blue) }. Rule: never repurpose a counter-driven list class for bullets; pick numbered (.ol) when the order is the message, bullets (.flatlist) when it is not. (Real failure: a §"honest limits" section reused .ol with counter-reset:none;padding-left:0; numbers 1–6 overlapped the caveat text.)
Anti-Patterns (Never Do)
- No rounded corners (0px everywhere -- consulting precision)
- No box shadows (flat print-ready surfaces)
- No serif fonts (single sans-serif family throughout)
- No warm/cream backgrounds (pure white + cool grays only)
- No decorative gradients (solid blocks of color only)
- No hover animations (static document, not an app)
- No emoji (per project rules)
- No content without hierarchy (everything needs section numbers)
- No sections without "so what" (every section needs a key message)
- No multiple accent colors beyond blue + traffic lights
- No grid columns > 3 for CJK text-heavy cards (Chinese text in 4+ columns overflows on 1040px container; use
repeat(3, 1fr) max for pillar cards, switch to 2-column or stacked on mobile)
- No
word-break: break-all on body (conflicts with CJK keep-all; always use word-break: keep-all; overflow-wrap: break-word for Chinese documents)
- No fixed-width grids without overflow protection (always add
min-width: 0 or overflow: hidden to grid children when content may exceed cell width)
- No
white-space: nowrap on table headers with CJK content (Chinese column headers + content easily exceed container width; use table-layout: fixed; white-space: normal; word-break: break-word and overflow-x: hidden on .table-wrapper — scrollbars are never acceptable)
- No decorative pseudo-element overlays on dark hero backgrounds (even subtle
::before gradients create visible color seams on linear-gradient backgrounds; if the base gradient is well-designed, content: none the overlay — less is more)
- No giant monospace tree block as the main architecture visual (for filesystem structures, show grouped domains + ownership table first; raw tree can only appear as appendix/evidence)
Comparison with Other Styles
| Dimension | Claude | Economist | McKinsey |
|---|
| Accent | Terracotta | Red | Deep Blue |
| Headlines | Serif | Sans | Sans (heavy) |
| Body | Sans | Serif | Sans |
| Page bg | Cream | White | White + gray alternating |
| Hero | White card | Navy masthead | Full-width dark blue |
| Cards | Shadow + radius | Top-rule flat | Blue-top-border flat |
| Section closer | Quote box | Pull quote | Implication box |
| Content model | Narrative | Editorial argument | Pyramid principle |
| Density | Spacious | Dense | Structured/medium |
| Feel | Academic book | Newspaper | Boardroom deck |