Skip to main content
Revision 2026-10

Brand Kit

The working reference for emanuelmallia.com, set like a technical journal: one ember signal on calm surfaces, with authority from type, alignment and restraint.

Colour

Near-monochrome surfaces in two registers carrying one accent. Light is the default; dark appears only when a visitor chooses it.
  • Background

    --color-background

    The page surface. One per theme.

    Light

    Dark

  • Background alt

    --color-background-alt

    Raised surface, only where elevation is genuinely needed.

    Light

    Dark

  • Foreground

    --color-foreground

    Headings and primary text.

    Light

    Dark

  • Prose

    --color-prose

    Long-form article text, a step softer than headings.

    Light

    Dark

  • Foreground muted

    --color-foreground-muted

    Ledes and secondary copy.

    Light

    Dark

  • Muted

    --color-muted

    Labels and metadata.

    Light

    Dark

  • Border

    --color-border

    Hairlines between sections and rows.

    Light

    Dark

  • Border strong

    --color-border-strong

    Control outlines.

    Light

    Dark

  • Accent

    --color-accent

    Ember. Ember-deep on light clears AA at 5.26:1; hot ember on ink.

    Light

    Dark

  • Accent hover

    --color-accent-hover

    Hover state of accent links.

    Light

    Dark

The One Signal Rule

Ember marks the surname, in-copy links, focus rings, list markers and at most one deliberate signal per fold. Primary buttons are ink and turn ember on hover.

One surface per theme

Sections are separated by hairlines and spacing. No alternating background fills, no forced-dark bands inside a light page.

Semantic colours

Success, warning and error stay out of brand surfaces. Article callouts use the neutral surface with a labelled rule.

Typography

Three families, one scale. Every role has a class in globals.css; use the class, not an ad-hoc size. A one-off size is a bug unless it is a documented exception.

Archivo

Display and headings

500 / 600 / 700

Hanken Grotesk

Text

400 to 700, with italic

Spline Sans Mono

Labels and data

400 / 500

Display

Archivo 600 / 60 to 132px / 0.92

The homepage name. Once on the site.

Emanuel Mallia

Page title

Archivo 600 / 40 to 76px / 1

The single H1 of every inner page.

Let's Collaborate

Article title

Archivo 600 / 34 to 56px / 1.05

Article H1s, long headlines.

Permission-Aware RAG: Propagating ACLs into a Vector Index

Section heading

Archivo 600 / 30 to 48px / 1.06

Section H2s.

Latest Insights

Sub-section

Archivo 600 / 21 to 27px / 1.2

Entries, role titles, list items with a heading.

Data & Database Architecture

Compact title

Archivo 600 / 17px / 1.35

Index rows, small entries.

Building the Work Brain

Statement

Archivo 500 / 24 to 36px / 1.18

A positioning sentence in the display face.

Leading enterprise Data & AI mandates from strategy through production.

Manifesto

Archivo 500 / 38 to 84px / 1

The homepage principle. Once on the site.

Working systems over presentations.

Evidence value

Archivo 500 / 30 to 44px / tabular

Key figures.

4

Functions Led

Lede

Hanken 400 / 18 to 21px / 1.6

The paragraph under a title. Muted.

Thoughts on AI delivery, data architecture, and technical leadership.

Body

Hanken 400 / 17px / 1.7

UI copy.

Data platforms, governance and AI systems built for regulated businesses in fintech, telecoms, iGaming and payments.

Small

Hanken 400 / 15px / 1.6

Secondary copy, lists.

Connect professionally and follow updates.

Label

Spline Mono 500 / 12px / caps

Labels inside a section. Never above every H2.

Working stack

Meta

Spline Mono 400 / 13px / tabular

Dates, reading time, periods, counts.

17 August 2026

Long-form

Hanken 400 / 17 to 19px / 1.72

Article body, on a 42rem measure.

Article body is set at 17px, stepping up to 19px from tablet, on a 1.72 leading and a 42rem measure. Links read in ember with a hairline underline that firms up on hover.

Emphasis
Inside a headline, emphasis is colour (ember) in the same face, used sparingly. Never a second family, never Hanken italic dropped into an Archivo headline.
Kickers
A label above a title appears only when it carries information the title does not: a status, a series, a count. A kicker that restates the H1 is deleted.

Shape

One radius, 2px, on every surface and control. Circles are reserved for portraits and the live-clock dot. Cards are avoided: rules and spacing do the grouping.
rounded-sm

Surfaces and controls

2px corners. Where elevation is genuinely needed: a 1px hairline, no resting shadow.

border, rules
border-strong, outlines

Hairlines

Rules sit inside the container, on the grid, never edge to edge.

rounded-full, 6px

The exception

A 6px circle on the footer clock, and portraits. Nothing else is round.

Components

One button, two link styles, one icon set. Every call to action renders through Button, so shape, weight and states stay identical everywhere.

Button

primary

Ink fill, bone in dark. Turns ember on hover: the accent is the response, not the resting state.

secondary

Hairline outline on the page surface.

LinkedIn

ghost

Text only, for low-emphasis actions inside dense UI.

Sizes sm, md, lg. arrow appends a nudging arrow; external links get the diagonal arrow automatically. Labels are Title Case, one label per intent per page.

Links and focus

In copy, links read in ember with a hairline underline that firms up on hover, like this one to the Insights index.
All insightsLinkedInStandalone navigation, sentence case. The arrow nudges 3px on hover.
:focus-visible
A 2px ember ring, offset 2px from whatever surface the control sits on.

Icons

Phosphor, imported only through components/ui/icons.tsx. Regular weight by default, bold where a glyph has to hold up at 12 to 14px. No hand-drawn paths, no icons in tinted squares.

  • ArrowLeft
  • ArrowRight
  • ArrowUp
  • ArrowUpRight
  • Check
  • Copy
  • Envelope
  • LinkIcon
  • LinkedinLogo
  • ListBullets
  • Moon
  • Plus
  • Sun
  • X
  • XLogo

Layout

One container and one 12-column grid for everything. Every multi-column layout states its below-lg fallback, single column unless noted.
col-span-12 lg:col-span-7
lg:col-span-4 lg:col-start-9
lg:col-span-4
lg:col-span-7 lg:col-start-6

The split and the heading rail, live. Below 1024px both stack to a single column.

Max 80rem. Gutters 20 / 32 / 40px. Every page's left edge lines up with the wordmark.
12 columns, gap 20 / 32 / 40px. Children opt into explicit spans and state their below-lg fallback.
clamp(4rem, 2.6rem + 4.6vw, 7rem) top and bottom. The vertical rhythm of a section band.
Patterns
Each at most once per page: masthead, evidence ledger, heading rail, statement, front page, index, chronology, closing split.

Motion

Intensity four out of ten. Entrances are CSS and run on first paint; scroll reveals are opt-in and leave content visible with JavaScript off.
.mask
A display line rising out of its own line box. Transform only, so the text paints at full opacity and LCP is never gated. 1.05s.
.enter
A fade and 14px rise for supporting copy above the fold, staggered with an inline --d delay. 0.9s.
data-reveal
Scroll reveal, played with Web Animations by the head script, optional delay in ms. Below the fold only, never nested.
Easing
cubic-bezier(0.16, 1, 0.3, 1), expo-out, for every entrance, reveal and hover.
Hover
Colour and a 3px arrow nudge over 200 to 350ms. Buttons press down 1px.
Reduced motion
Every entrance and reveal collapses to its end state.
.live-dot
The one perpetual animation on the site, on the footer clock, because it marks a genuinely live value.

Entrance

Kicker

Working systems over presentations.

Supporting copy follows the line on a short stagger.

.enter 40ms / .mask 90ms / .enter 220ms

Not used: parallax, scroll-linked fades of content, pointer physics, cursor effects, floating particles, marquees, and counters that count up to single digits.

Do and don't

The short version of everything above.

Do

  • Use the type roles.
  • Align to the grid.
  • Let hairlines organise content.
  • Keep ember rare.
  • Verify both themes at 375, 768 and 1440 widths.
  • Keep content server-rendered and visible without JavaScript.

Don't

  • Add cards to group text.
  • Put an eyebrow above every heading.
  • Mix type families inside a headline.
  • Use em-dashes or bold in body copy.
  • Reintroduce cream backgrounds, aurora, glass or WebGL.