Source of truth for the MarketingUpgrade.pro brand. Refrain, POV, ICP, voice, color, typography, components, and entity graph in one document. Edit this file when any brand decision changes; everything else in the codebase should derive from here.
Strategy is folklore. I ship operating systems.
Seven words, two clauses. The first clause names the problem (consultant industry sells folklore). The second clause names the alternative (a working system, not a deck). Repeat this on every hero, every CTA exit, every footer strap, every OG image alt, every email subject A/B variant, and every sales reply until it is the first thing every prospect can recall about the brand.
A marketing engagement turns into folklore when someone reads a deck back to a board, the retainer renews and growth does not move. The alternative is a working marketing operating system the team owns after the engagement ends.
€5M to €100M revenue businesses across four sectors (E-commerce, Financial Services, B2B SaaS, Marketplaces). Stage: post-PMF, pre-Series C. Decision-maker: founder, CEO, or board chair.
Project sprints of 2 to 6 weeks, interim leadership of 3 to 12 months, or fractional ongoing. €5,000 to €25,000 per month, 30-day exit clause. Operational from day one. Never a retainer-for-vibes.
A marketing function that runs without me, documented, when the engagement ends.
Seven brand colors. Two operational accents (neon green for action, neon purple for brand). Black foundation, off-white text. Two greys for hierarchy. Danger red only on legal and regulatory pages. Click a swatch to copy the hex.
Primary action. CTAs, accents, success state, positive signal.
Brand primary. Borders, secondary accents, attention markers.
Page background, foundation.
Body text, primary readable content.
Muted secondary text, captions, metadata.
Body copy on dark cards.
Hard warning, destructive states, error borders.
Four typefaces. Display (Black Ops One) for every heading. Mono (Space Mono) for everything else. Hand (Permanent Marker) for one rotated accent per section. Sans (Space Grotesk) as the long-form fallback. Never use Google's default sans serifs.
All H1-H6. All hero text. ALL CAPS with 0.05em letter-spacing.
Weights: 400 (single weight)
Body text, paragraphs, navigation, tags, code, fine print.
Weights: 400, 700 (regular + bold)
Pull quotes, slight rotation accents (.rotate-slight class), human moments. Use sparingly — max one per section.
Weights: 400
Body fallback when Space Mono is too dense. Long-form articles.
Weights: 400, 500, 600, 700
Six rules. Apply to every surface: homepage hero, blog posts, CTA copy, email subject lines, social posts. A voice violation is brand drift; this section is the merge gate.
Strategy is folklore. I ship operating systems.
We deliver strategic, results-driven marketing transformation.
Why: Two short clauses are memorable. They survive translation, voice search, AEO snippet selection.
I do the diagnosis and the work myself.
Our team does the diagnosis and the work.
Why: Solo operator. A plural pronoun fakes scale I don't have.
8% of CMOs run campaigns where multiple agents operate autonomously (BCG, 300 CMOs, June 2026).
Acquisition costs have become more challenging.
Why: A figure carries its source, and a figure with no source does not ship. Name the mechanism when there is no figure.
No 90-day onboarding. No PowerPoint. No retainer-for-vibes. Operational from day one.
We focus on quick wins and long-term value delivery.
Why: Three negatives sharpen the contrast. One positive lands the punch. Rhythm matters.
Engagements are structured to satisfy Dutch Wet DBA.
Compliant with relevant European regulations.
Why: Specifics signal expertise. Vague signals consultancy.
Use a comma, a colon, or split the sentence.
Em-dashes — they are inconsistent across keyboards.
Why: House rule, enforced by the copy linter in CI.
Every above-fold hero uses these four lines, in this order. Eyebrow names the category. H1 is the refrain. Sub places the offer in context. Eyebrow2 sharpens with three negatives and one positive.
Enterprise interim CMO leadership for €5M to €100M businesses across e-commerce, fintech, SaaS, and marketplaces. Embedded from week one.
NO 90-DAY ONBOARDING. NO POWERPOINT. NO RETAINER-FOR-VIBES. ONE OPERATOR, OPERATIONAL FROM DAY ONE.
The visual vocabulary of the TFS (Tactical Field Scrapbook / Brutalist) language. Every page mixes these six elements in some combination. Adding a new element requires updating this section first.
border-2 border-[#00ff00] borderStyle:dashedPrimary container for any structured content (KPIs, stack lists, pricing tiers).
border-radius: 0 (TFS --radius: 0rem)All buttons, cards, inputs. Never round corners. Brutalist baseline.
textShadow: 0 0 10px <color> — usually 10-20px blurHero text, brand strap, critical accents. Reserve for ~1-2 surfaces per page.
repeating-linear-gradient(0deg, transparent, transparent 2px, rgba(0,255,0,0.015) 2px, rgba(0,255,0,0.015) 4px)Overlaid on hero sections as low-opacity ambient texture. Never on text.
.rotate-slight (animation: wiggle 1s ease-in-out infinite)Apply to font-hand accents (Permanent Marker). One per section max.
text-xs tracking-widest uppercase — usually with font-black or font-displaySection eyebrows, category labels, badge/chip copy.

For the primary conversion action on every page. One per surface. Always “Start an intake” or a refrain-flavoured variant. Never “Get in touch”, “Learn more”, or any passive CTA.
For the not-ready-yet visitor. Always leads to a content surface (verticals, blog, whitepaper, glossary). Never leads to a calendar or form.
The brand operates as two linked schema.org entities: a Person (the operator) and an Organization (the brand). Both share a cross-referenced sameAs graph. Any new platform presence must be added to both arrays and shipped on the same commit.
When adding a new platform (e.g., Substack, Mastodon, Wikidata Q-number, YouTube channel), update: client/index.html Person.sameAs, client/index.html Organization.sameAs, client/index.html LocalBusiness.sameAs, /client/public/.well-known/agent.json, /client/public/humans.txt, /client/public/llms.txt, /client/public/llms-full.txt, AND this brandbook. All in one PR.
Every indexable page MUST satisfy this checklist. The seo:lint script enforces it in CI. Pages that fail are blocked from merge.
From €5,000 to €25,000 per month, set by how much of the function I take on and how many days a week that takes; €25,000 is a full mandate with P&L ownership. Monthly cycles with a 30-day exit clause.
Every brand color exposes a 50-950 step scale for nuanced UI usage (hover states, alert backgrounds, gradient stops, data visualization). The 500 step is the canonical hex. Lower numbers are lighter; higher numbers are darker. Generated programmatically; OKLCH-tuned source of truth lives in client/src/index.css.
Every brand-color foreground × background pairing measured against WCAG 2.2. AA threshold: 4.5:1 for normal text, 3:1 for large text (18pt regular or 14pt bold). AAA: 7:1 normal / 4.5:1 large. Pairings marked “Fail” must not be used for text. Use them for decorative-only surfaces (borders, dividers, icons with adjacent labels).
| FG / BG | Black | Off-white | Card #0a0a0a | Card #1a1a1a |
|---|---|---|---|---|
| White | 21.00:1 N:AAA · L:AAA | 1.12:1 N:Fail · L:Fail | 19.80:1 N:AAA · L:AAA | 17.40:1 N:AAA · L:AAA |
| Off-white | 18.76:1 N:AAA · L:AAA | 1.00:1 N:Fail · L:Fail | 17.68:1 N:AAA · L:AAA | 15.55:1 N:AAA · L:AAA |
| Grey 80 | 13.08:1 N:AAA · L:AAA | 1.43:1 N:Fail · L:Fail | 12.33:1 N:AAA · L:AAA | 10.84:1 N:AAA · L:AAA |
| Grey 60 | 7.37:1 N:AAA · L:AAA | 2.54:1 N:Fail · L:Fail | 6.95:1 N:AA · L:AAA | 6.11:1 N:AA · L:AAA |
| Neon Green | 15.30:1 N:AAA · L:AAA | 1.23:1 N:Fail · L:Fail | 14.43:1 N:AAA · L:AAA | 12.68:1 N:AAA · L:AAA |
| Neon Purple | 8.85:1 N:AAA · L:AAA | 2.12:1 N:Fail · L:Fail | 8.35:1 N:AAA · L:AAA | 7.34:1 N:AAA · L:AAA |
| Danger Red | 5.25:1 N:AA · L:AAA | 3.57:1 N:Fail · L:AA | 4.95:1 N:AA · L:AAA | 4.35:1 N:Fail · L:AA |
N = normal text grade · L = large text grade. AAA = ideal, AA = minimum, Fail = decorative only.
The full responsive type ramp, mobile-first. All sizes use rem so they respect user font-size preferences. Line heights are tuned per step; display sizes are tight (0.9-1.1) while body sits at 1.6 for long-form readability.
| Token | Size (rem) | Size (px) | Line-height | Use |
|---|---|---|---|---|
| display-xl | 5.625 | 90 | 0.9 | Hero H1 desktop |
| display-lg | 4.5 | 72 | 0.95 | Hero H1 tablet |
| display | 3.5 | 56 | 1.0 | Hero H1 mobile / Section H2 desktop |
| h1 | 3.0 | 48 | 1.05 | Section H2 mobile |
| h2 | 2.25 | 36 | 1.1 | Subsection H3 |
| h3 | 1.875 | 30 | 1.15 | Card title |
| h4 | 1.5 | 24 | 1.2 | Inline emphasis |
| lead | 1.25 | 20 | 1.5 | Sub-hero / lede paragraph |
| body-lg | 1.125 | 18 | 1.6 | Long-form blog body |
| body | 1.0 | 16 | 1.6 | Default paragraph |
| body-sm | 0.875 | 14 | 1.55 | Card body, FAQ |
| caption | 0.75 | 12 | 1.5 | Meta, byline, fine print |
| mono-sm | 0.6875 | 11 | 1.4 | Code, hex, technical refs |
| eyebrow | 0.625 | 10 | 1.3 | All-caps tracking-widest |
Everything in the layout uses 4px increments. Tailwind's default scale maps cleanly: spacing-1 = 4px, spacing-2 = 8px, spacing-4 = 16px. Component padding, gap, and margin must come from this scale. Adding a one-off value (e.g., 13px) requires a design-token RFC.
Lucide React. Stroke-based, single weight (1.5px at 24px size). Always pair with a text label for accessibility. Never use an icon alone as a button without an aria-label.
Motion serves communication, not decoration. Hero text uses staggered letter reveal with a cinematic ease curve. Scroll-driven parallax for hero sections only. Always respect prefers-reduced-motion.
cubic-bezier(0.25, 0.46, 0.45, 0.94)Hero text reveal, section entrances, anything narrative
cubic-bezier(0.16, 1, 0.3, 1)Button hover, popover entry, anything reactive
linearProgress bars, scanline overlays, infinite loops only
rotate(-3deg) → rotate(3deg), 1s loopPermanent Marker accents, .rotate-slight class
Choreographed motion — entrances, count-ups, staggers, loops — is built with GSAP 3.15+ (free for commercial use since 3.13, all plugins included). Gesture-bound motion that tracks a pointer or spring-physics UI state (card tilt, flip, drag) stays on framer-motion. One engine per job; never both on the same property of the same element.
Every page wraps its tweens in gsap.context(() => {...}, rootRef) and returns ctx.revert() on unmount. No global selectors, no leaked tweens.
Markup renders the FINAL state (SEO- and no-JS-safe); gsap.from() animates toward it. prefers-reduced-motion? Skip the whole context — the DOM is already correct.
back.out(1.4) for hero/card entrances · power2.out for reveals & counters · power3.out for bars/meters · power2.inOut for loops (sheens, sweeps).
Number count-ups: gsap.from with innerText: 0 + snap. Grid staggers 0.08–0.12s. Loops repeat with repeatDelay ≥ 6s — ambience, not noise.
useLayoutEffect(() => {
if (matchMedia("(prefers-reduced-motion: reduce)").matches) return;
const ctx = gsap.context(() => {
gsap.from(".hero-card", { autoAlpha: 0, y: 48, scale: 0.92, duration: 1, ease: "back.out(1.4)" });
gsap.from(".stat-num", { innerText: 0, snap: { innerText: 1 }, duration: 1.5, ease: "power2.out", stagger: 0.09 });
gsap.from(".stat-bar", { scaleX: 0, transformOrigin: "0% 50%", duration: 1.1, ease: "power3.out", stagger: 0.09 });
}, pageRef);
return () => ctx.revert();
}, []);Reference implementation: fifacv.marketingupgrade.pro — entrance swing, stat count-ups, bar fills, below-fold reveals, and an 8-second sheen loop, all in one reverted context.
No formal external accessibility standard has been set. Two working rules are enforced in the codebase and should hold: every image carries a descriptive alt attribute, and arcade green (#00ff00) is used only on obsidian surfaces, where it clears 15:1. On the light canvas the accent is the darkened pink (#9b2fa3), because the green fails contrast there. The list below borrows from WCAG 2.2 as targets for new pages. It is a set of goals, not a claim of conformance.
Canonical token export. CSS variables (drop into any project), Tailwind config snippet, and a JSON payload for Figma / Style Dictionary. Source of truth: client/src/index.css. When tokens change, update there first, then this brandbook.
:root {
/* color */
--green-500: #00ff00;
--purple-500: #e386e9;
--red-500: #ff0000;
--white: #ffffff;
--off-white: #f2f2f2;
--grey-50: #f0f0f0;
--grey-60: #999999;
--grey-80: #cccccc;
--bg-base: #000000;
--bg-card: #0a0a0a;
/* fonts */
--font-display: "Black Ops One", system-ui;
--font-mono: "Space Mono", monospace;
--font-hand: "Permanent Marker", cursive;
--font-sans: "Space Grotesk", system-ui, sans-serif;
/* radius */
--radius: 0;
/* motion */
--ease-cinematic: cubic-bezier(.25,.46,.45,.94);
--ease-snap: cubic-bezier(.16,1,.3,1);
--duration-fast: 150ms;
--duration-base: 300ms;
--duration-slow: 600ms;
}{
"color": {
"green": { "500": "#00ff00" },
"purple": { "500": "#e386e9" },
"red": { "500": "#ff0000" },
"neutral": {
"0": "#000000",
"10": "#0a0a0a",
"60": "#999999",
"80": "#cccccc",
"95": "#f2f2f2",
"100": "#ffffff"
}
},
"font": {
"display": "Black Ops One",
"mono": "Space Mono",
"hand": "Permanent Marker",
"sans": "Space Grotesk"
},
"radius": { "default": 0 },
"motion": {
"ease": {
"cinematic": "cubic-bezier(.25,.46,.45,.94)",
"snap": "cubic-bezier(.16,1,.3,1)"
},
"duration": {
"fast": "150ms",
"base": "300ms",
"slow": "600ms"
}
}
}Canonical hosted assets. Use the absolute URL; never duplicate or re-host. Adding a new asset requires landing the file in client/public/images and registering it here.
The brandbook is the source of truth. Changes to colors, typography, voice, or component vocabulary require a documented RFC. Quick fixes (typos, formatting) can ship freely.
Examples: Fixing a typo, updating an asset URL, adding a new entry to an existing list.
Process: Open PR, merge after self-review. No external sign-off.
Examples: Adding a new shade step to an existing color scale. Adding a new icon to the library. Adding a new spacing token.
Process: Open PR with rationale + 2 example use cases. Merge after 1 reviewer approves.
Examples: Adding a new brand color. Adding a new typeface. Adding a new component pattern. Adding a new voice rule.
Process: Open RFC issue first. 7-day comment window. Implement only if no veto. Update brandbook + every reference in the codebase in the same PR.
Examples: Changing the refrain. Changing the ICP. Changing the POV.
Process: Synchronous workshop with the operator + a trusted external advisor. Cannot be done in a PR alone.
Initial publication. Refrain locked: 'Strategy is folklore. I ship operating systems.' ICP: stay broad across six verticals. Brand graph (Person + Organization + LocalBusiness) cross-references LinkedIn, Reddit, and Interactive CV subdomain.