# GALTON — full brand bundle

> Never invent a colour, font, radius or component. The accent is ALWAYS #FFD700 (colors.primary), never red, blue or green. H1/display headlines and section titles (H2) are UPPERCASE. Every text colour is SOLID: no opacity, no alpha, no grey type, and no em dash in any copy. Anything undefined: derive via the fallback contract, or ask.

Brand version 2.21.1 — last updated 02.10.2026.
This file is self-contained: everything below is here in full, and no URL in it needs fetching. The only URLs you ever open are the asset files themselves, and only to place them.
A one-sentence request is enough: section 1 (GUIDED MODE) tells you which parameters to fill from defaults, what to ask, and how to report the choices back. Read it before producing anything.

The brand below is 321 KB, ~82k tokens. It is one document on purpose: the sections cross-reference each other constantly, and splitting it is how a reader ends up with the tokens but not the rule that governs them.

Contents:
1. GUIDED MODE: how to take a request and report back
2. DESIGN SPEC: tokens and rules
3. BRAND GUIDE — identity, voice, logo policy
4. VERBAL IDENTITY — brand voice + AI brief
5. LINKEDIN PLAYBOOK
6. SOUND BRANDING: the audio identity
7. LAYOUT CATALOG — slide canvas + archetypes
8. PRESENTATION CATALOG: 16:9 deck canvas + slide types
9. ASSETS + ICONS: every hotlinkable file

## Reading this without MCP

The sections below are this brand's own source files, unedited, so they sometimes name a tool or a sibling file. Everything they name is IN THIS FILE. Translate as you read:

- `get_intake`, `intake.md` = section 1, GUIDED MODE: how to take a request and report back
- `get_design_spec`, `list_tokens`, `get_component`, `get_section`, `get_fallback`, `get_chart_palette`, `get_agent_rules`, `get_brand_overview`, `design.md`, `brand.css`, `snippets.json` = section 2, DESIGN SPEC: tokens and rules
- `brand.md` = section 3, BRAND GUIDE — identity, voice, logo policy
- `get_voice_guide`, `verbal-identity.md`, `voice.md` = section 4, VERBAL IDENTITY — brand voice + AI brief
- `get_linkedin_playbook`, `linkedin.md` = section 5, LINKEDIN PLAYBOOK
- `get_sound_guide`, `sound.md` = section 6, SOUND BRANDING: the audio identity
- `get_layout`, `list_layouts`, `list_carousel_recipes`, `layouts.md`, `layouts.json` = section 7, LAYOUT CATALOG — slide canvas + archetypes
- `list_presentation_slides`, `get_presentation_slide`, `presentations.json` = section 8, PRESENTATION CATALOG: 16:9 deck canvas + slide types
- `list_assets`, `list_icons`, `brand.json`, `icons.json`, `assets.json` = section 9, ASSETS + ICONS: every hotlinkable file

Two rules follow from that. Never answer that you need to call a tool or open a link before you can help: you already have everything. And where a passage says a tool computes something for you, compute it yourself from the rules stated beside it, which is why those rules are written out rather than left to the tool.

---

# GUIDED MODE: how to take a request and report back (source: https://galton-ai-assets.vercel.app/intake.md)

---
# Guided mode — the interaction protocol an agent follows BEFORE it produces an
# asset. This file exists because a short, human prompt ("make me a poster")
# leaves most brand parameters unspecified, and an agent that guesses silently
# is exactly how output drifts off-brand.
#
# It is brand data (it names this brand's defaults), so it lives here. The
# framework only projects it: /intake.md, get_intake, the skill, llms-full.txt.
#
# Parameter values below are DEFAULTS, never new brand values: everything
# concrete (colours, type, components, canvases, icon sets) is resolved from
# design.md, layouts.md, icons.json and verbal-identity.md.
version: 1

# guided  = fill defaults, ask only for blocking parameters, then produce + report
# ask-all = ask every parameter first (slower; not the default here)
# off     = produce immediately from defaults, report afterwards
mode: guided

# Never ask more than this many questions in one turn.
maxQuestions: 3

# If the user replies with any of these, stop asking and use the defaults.
goWords: ["go", "choď", "chod", "ok", "poď", "just do it", "urob to"]

protocol:
  - "Identify the output type from the request (see `outputs` below, matching on `match` keywords). If nothing matches, use the closest type and say which one you used."
  - "Fill every parameter of that type from its `default`. Defaults are a starting point, never an invention: resolve each one to a real value from the brand spec (design.md, layouts.md, icons.json, verbal-identity.md)."
  - "Ask for parameters marked `blocking` that the request has not already answered, at most `maxQuestions` of them, in one message. Give each question a suggested answer in brackets, and end with: reply `go` to accept all suggestions."
  - "The parameter list is a floor, not a ceiling. You may add your own question when `ownQuestions` allows it: use your judgement about what this specific request needs, inside the boundary that block sets. It comes out of the same `maxQuestions` budget."
  - "If the user replies with a `goWord`, or already gave the content, produce the asset immediately. Never ask twice about the same thing."
  - "After the asset, append the `brandChoices` block: every parameter you resolved, the value you used, and the one-word alternative. Then offer the `nextStep` of that output type as a single question."
  - "If the user answers with one of those words, redo only what that word changes. Keep everything else identical."
  - "Run the `selfCheck` list before you deliver. Anything on the `locked` list is not a parameter and is never offered as a choice."
  - "Write the questions and the report in the language the user is writing in, whatever the brand's own default language for the copy is."

brandChoices:
  title: "Brand choices"
  hint: "reply with one word to change any of these"
  lockedNote: "Fixed by the brand, not offered as a choice: the accent, the typeface, the logo colours and the UPPERCASE headline rule."
  example: |-
    Brand choices (reply with one word to change any of these):
    • Surface: dark          (want "light"?)
    • Format: 4:5            (want "1:1" or "16:9"?)
    • Icons: none            (want "line icons" or "3d icons"?)
    • Logo: wordmark lockup  (want "symbol"?)
    • Language: Slovak       (want "English"?)
    The accent stays the signature yellow and the headline stays UPPERCASE. Those are fixed.
    Want the Instagram 1080x1350 version of this too?

# The licence to ask something nobody wrote down here, and its boundary.
#
# The parameter list above covers what recurs. It cannot cover what is specific
# to one request: a launch date, whose logo goes beside ours, which of three
# products this is about. Without this block an agent that spots a genuine gap
# has two bad options, guess or interrogate, and the whole point of guided mode
# is that it does neither. `when` is the licence, `never` is the boundary, and
# both are read as judgement prompts, not as a checklist to work through.
ownQuestions:
  allowed: true
  # How many of the maxQuestions budget may be your own. The rest stay for the
  # blocking parameters.
  max: 1
  when:
    - "The request needs a fact only the user has: a date, a number, a price, a client or product name, a market, an audience, an event."
    - "Two readings of the request would produce materially different assets and the brand prefers neither. Ask which, do not average them."
    - "The request implies something the brand genuinely does not cover, and the fallback contract would change the outcome rather than just fill a gap."
    - "Something in the request contradicts the brand and the way out is a real choice: a format the catalogue does not have, a claim the voice rules will not carry, a channel with its own constraints. Name the conflict and ask which way to go. If the conflict is with a `locked` value (a different accent colour, a recoloured logo), do NOT ask: say plainly what the brand does instead, then carry on. Asking would imply it was negotiable."
  never:
    - "Anything on the `locked` list. Those are not choices and asking implies they are."
    - "Anything that already has a `default`. Fill it and report it in the `brandChoices` block; the user changes it in one word if they want to."
    - "A preference you can infer from the request, the brand, or what was already said in this conversation."
    - "Confirmation of something already agreed, or a question you have asked once. Never ask twice."
    - "A question you cannot act on differently depending on the answer. If both answers lead to the same asset, do not ask it."

# Not parameters. Never offer these as a choice, never ask about them.
locked:
  - "The accent colour. It is always the brand primary, on every surface, in every state."
  - "The typeface and the type scale. Both come from the design spec."
  - "The logo. White or black only, never recoloured, never retyped as text."
  - "The UPPERCASE rule for H1/display headlines and section titles (H2)."
  - "The chart palette. Charts never use a library-default rainbow."
  - "Status colours (success/warning/error/info). Functional feedback only, never decoration."

# The last gate before delivering. Cheap to run, catches the usual drift.
selfCheck:
  - "The accent is the brand primary, used for emphasis only, never as a large fill."
  - "The case follows `typeRules.case`."
  - "The logo is white or black, hotlinked from its real asset URL, not redrawn or retyped."
  - "Every text colour came from a role or a `.bl-text-*` class and satisfies `colorRules.text`; on a light surface it came from the `lightSurface` map, not from a dark-tuned token."
  - "Every colour, size, radius and component came from the spec, or from `fallback` where the spec is silent."
  - "Any chart uses the chart palette; any icon comes from the icon library, in the variant that matches the surface."
  - "Copy follows the verbal identity (register, lexicon, mechanics), not generic marketing language, and contains no em dash."
  - "Anything the spec does not define went through the fallback contract."

outputs:
  - id: poster
    name: "Poster / out-of-home"
    match: ["poster", "plagát", "plagat", "billboard", "citylight", "print ad", "flyer"]
    nextStep: "a social version of the same poster on the portrait canvas"
    params:
      - id: headline
        question: "What is the headline?"
        blocking: true
        default: "a short brand line drawn from the verbal identity"
        note: "One line, UPPERCASE, with a single word carrying the accent."
      - id: surface
        question: "Dark or light version?"
        default: "dark"
        options: ["dark", "light"]
      - id: format
        question: "Which format?"
        default: "4:5 portrait"
        options: ["4:5 portrait", "1:1 square", "A3 print", "16:9 landscape"]
        note: "Poster formats are print sizes, not slide canvases: only 4:5 and 1:1 have a measured equivalent in the layout catalog (1080x1350 and 1080x1080). For A3 and 16:9 there is no measured geometry, so derive it from the canvas rules and say so in the brand-choices block."
      - id: icons
        question: "Use an icon or a geometric motif?"
        default: "none"
        options: ["none", "line icons", "3d icons", "geometric motif"]
      - id: image
        question: "Use a photograph?"
        default: "no"
        options: ["no", "yes"]
      - id: logo
        question: "Which logo variant?"
        default: "primary wordmark lockup"
        options: ["primary wordmark lockup", "wordmark", "symbol"]
      - id: language
        question: "Which language?"
        default: "Slovak"
        options: ["Slovak", "English"]

  - id: social
    name: "Social post (visual + caption)"
    match: ["instagram", "social", "post", "facebook", "linkedin post", "carousel", "story"]
    nextStep: "the rest of the carousel using the recipe for this post type"
    params:
      - id: topic
        question: "What is the post about?"
        blocking: true
        default: "the brand's central idea from the verbal identity"
      - id: surface
        question: "Dark or light version?"
        default: "dark"
        options: ["dark", "light"]
      - id: canvas
        question: "Which canvas?"
        default: "1080x1350"
        options: ["1080x1350", "1080x1080"]
        note: "These are the two MEASURED canvases and the exact strings `get_layout { id, ratio }` accepts: pass the value as it stands here. Call them portrait and square when you talk to the user, never when you call the tool. Resolve the geometry from the layout catalog, never by hand."
      - id: layout
        question: "Which layout archetype?"
        default: "cover"
        note: "Pick from the layout catalog; follow that layout's slot schema exactly."
      - id: icons
        question: "Use icons?"
        default: "none"
        options: ["none", "line icons", "3d icons"]
      - id: image
        question: "Use a photograph?"
        default: "no"
        options: ["no", "yes"]
      - id: caption
        question: "Write the caption too?"
        default: "yes"
        options: ["yes", "no"]
      - id: language
        question: "Which language?"
        default: "Slovak"
        options: ["Slovak", "English"]

  - id: deck
    name: "Presentation / deck"
    match: ["deck", "presentation", "prezentácia", "prezentacia", "slides", "slajd", "pitch"]
    nextStep: "a PDF export, or a PPTX you can edit in PowerPoint"
    params:
      - id: topic
        question: "What is the deck about?"
        blocking: true
        default: "the brand's positioning story from the verbal identity"
      - id: slides
        question: "How many slides?"
        default: "10"
      - id: surface
        question: "Dark, light, or a mix?"
        default: "mixed"
        options: ["dark", "light", "mixed"]
        note: "Mixed means dark throughout with one light section in the middle, so the inversion reads as deliberate."
      - id: ratio
        question: "Which aspect ratio?"
        default: "16:9"
        options: ["16:9", "4:3", "1080x1350"]
        note: "16:9 is the presentation catalog (`list_presentation_slides`, `get_presentation_slide`): a 1920x1080 canvas with its own type scale and footer, and a slide type for each job. Plan the deck from it slide by slide. 1080x1350 is the social layout catalog (`get_layout`). 4:3 has NO catalog: build it from the 16:9 canvas rules and say in the brand-choices block that the canvas is derived, not measured."
      - id: sequence
        question: "Which slide types, in which order?"
        default: "picked from the presentation catalog by the content: cover-main, agenda, a divider per chapter, the content slides, cover-closing"
        note: "Never a question to the user: derive it. Pick each slide by its intent, density and limits, obey the deck rules, and list the chosen ids in the report block."
      - id: format
        question: "Which file format?"
        default: "HTML"
        options: ["HTML", "PPTX", "PDF"]
        note: "HTML first: it renders anywhere and both PDF and PPTX can follow from it."
      - id: icons
        question: "Use icons on the pillar slides?"
        default: "line icons"
        options: ["none", "line icons", "3d icons"]
      - id: chart
        question: "Include a data slide?"
        default: "yes"
        options: ["yes", "no"]
      - id: language
        question: "Which language?"
        default: "Slovak"
        options: ["Slovak", "English"]

  - id: table
    name: "Table / data sheet"
    match: ["table", "tabuľka", "tabulka", "spreadsheet", "matrix", "comparison"]
    nextStep: "a chart of the same data"
    params:
      - id: data
        question: "What data goes in it?"
        blocking: true
        default: "a plausible sample set, clearly labelled as sample data"
      - id: size
        question: "How many columns and rows?"
        default: "5 columns, 5 rows"
      - id: surface
        question: "Dark or light version?"
        default: "light"
        options: ["dark", "light"]
      - id: tags
        question: "Use status tags in a column?"
        default: "no"
        options: ["no", "yes"]
        note: "Status colours are functional only. A tag is a state, never decoration."
      - id: language
        question: "Which language?"
        default: "Slovak"
        options: ["Slovak", "English"]

  - id: chart
    name: "Chart / data visualization"
    match: ["chart", "graf", "graph", "plot", "dashboard", "kpi"]
    nextStep: "a second chart type on the same data, or a stat-tile row above it"
    params:
      - id: data
        question: "What data should it show?"
        blocking: true
        default: "a plausible sample series, clearly labelled as sample data"
      - id: type
        question: "Which chart type?"
        default: "bar chart"
        options: ["bar chart", "line chart", "donut", "stacked bar", "stat tiles"]
      - id: surface
        question: "Dark or light version?"
        default: "dark"
        options: ["dark", "light"]
      - id: series
        question: "How many series?"
        default: "1"
        note: "One highlight per chart: the accent marks the series that matters, the rest are neutrals."
      - id: language
        question: "Which language?"
        default: "Slovak"
        options: ["Slovak", "English"]

  - id: copy
    name: "Copy / text"
    match: ["copy", "text", "post text", "email", "ad", "claim", "article", "script"]
    nextStep: "a visual to go with the copy"
    params:
      - id: subject
        question: "What is it about, and who reads it?"
        blocking: true
        default: "the brand's positioning, addressed to a C-level reader"
      - id: register
        question: "Which register?"
        default: "consultative"
        note: "Pick from the registers in the verbal identity, by channel and audience."
      - id: length
        question: "How long?"
        default: "short"
        options: ["short", "medium", "long"]
      - id: cta
        question: "Which call to action?"
        default: "one soft next step"
      - id: language
        question: "Which language?"
        default: "Slovak"
        options: ["Slovak", "English"]

  - id: web
    name: "Web page / UI"
    match: ["landing", "page", "web", "site", "ui", "dashboard ui", "form", "component"]
    nextStep: "the light-surface inversion of the same page"
    params:
      - id: purpose
        question: "What is the page for, and what should it say?"
        blocking: true
        default: "a single-message landing page built on the brand's positioning"
      - id: surface
        question: "Dark or light version?"
        default: "dark"
        options: ["dark", "light"]
      - id: sections
        question: "Which sections?"
        default: "hero, three content sections, footer"
      - id: components
        question: "Take the markup from the component snippets?"
        default: "yes"
        options: ["yes", "no"]
        note: "Link the hotlinkable brand stylesheet and use the component classes; do not restyle by hand."
      - id: language
        question: "Which language?"
        default: "Slovak"
        options: ["Slovak", "English"]
---

## Why guided mode exists

A brand system only holds if the person using it does not have to know it. Most
real prompts are one sentence long ("make me a poster, black version"), and one
sentence cannot carry a surface, a format, a logo variant, an icon set and a
language. Something has to fill the gaps. Left alone, a model fills them with
its own defaults, which is exactly the drift this knowledge base exists to
prevent.

Guided mode makes the gap-filling explicit and reversible. The agent fills every
missing parameter from the defaults above, asks only about what it genuinely
cannot infer (usually the content itself), produces the asset, and then reports
what it chose in one short block, with the one-word way to change each choice.
The user gets a result on the first turn and still keeps control of every
decision that was made for them.

## What is a parameter and what is not

A parameter is a legitimate fork in the road: dark or light, portrait or square,
icons or no icons, Slovak or English. The `locked` list is the other kind: the
accent, the typeface, the logo colours, the UPPERCASE headline rule, the chart
palette. Those are not preferences. Offering them as choices would turn a brand
system back into a mood board, so the protocol never puts them in the report and
never asks about them.

The defaults themselves are conservative on purpose. They point at the safest
on-brand answer, never at a new value: "dark", "4:5", "no icons", "wordmark
lockup" all resolve to something the spec already defines.

## Room for judgement

A fixed list of questions can only cover what recurs. It cannot cover the
launch date, the client whose logo sits beside ours, or which of three products
a post is actually about. So the protocol carries a licence: the agent may ask
one question of its own when the request genuinely needs a fact only the person
asking has, when two readings would produce materially different assets, or
when the request contradicts the brand.

The boundary matters as much as the licence. It may not ask about anything on
the locked list, anything that already has a default, anything it could infer,
or anything whose answer would not change what it makes. The test is simple: if
both answers lead to the same asset, the question is noise. One good question
beats three polite ones, and no question at all beats a guess in a report the
user can read.

---

# DESIGN SPEC: tokens and rules (source: https://galton-ai-assets.vercel.app/design.md)

---
version: "2.21.1"
name: galton-design-system
description: >-
  A confident, editorial, high-contrast brand interface built dark-first on a
  near-black canvas (#1A1A1A) with white text and a single signature
  primary-yellow (#FFD700) used sparingly for emphasis. Everything is set in one
  typeface, GALTON, at Light (300) weight, with Montserrat as the official
  substitute. Hierarchy comes from size, weight and case: display headlines and
  section titles are UPPERCASE, everything below them is Sentence case, and type
  is never dimmed to make it secondary. The logo is white or black only, never
  coloured. Components are pill-and-flat: pill-shaped UPPERCASE Bold buttons,
  flat bottom-border-only inputs with a yellow focus, and a strict palette with
  no invented shades.

# The one rule to read before anything else — surfaced to agents verbatim.
criticalRule: >-
  Never invent a colour, font, radius or component. The accent is ALWAYS
  {colors.primary}, never red, blue or green. H1/display headlines and section
  titles (H2) are UPPERCASE. Every text colour is SOLID: no opacity, no alpha,
  no grey type, and no em dash in any copy. Anything undefined: derive via the
  fallback contract, or ask.

colors:
  primary: "#FFD700"              # signature yellow — CTAs, highlights, focus, hero accent. Never a large fill.
  on-primary: "#1A1A1A"           # text/icons on a yellow surface (always black)
  ink: "#FFFFFF"                  # primary text + headlines on dark
  on-dark: "#FFFFFF"              # anything sitting on the dark canvas
  # ink / body / body-soft / muted are the SAME white on purpose. See `colorRules.text`.
  body: "#FFFFFF"                 # running body text
  body-soft: "#FFFFFF"            # secondary paragraphs / leads
  muted: "#FFFFFF"                # captions, labels, placeholders, disabled
  canvas: "#1A1A1A"               # dark-first page floor (the brand default)
  surface-raised: "rgba(255,255,255,0.04)" # cards / raised panels — built from white at low opacity, never a new hex
  hairline: "rgba(255,255,255,0.12)"       # 1px borders, dividers, table rows
  on-light: "#1A1A1A"             # text/marks on a white/light surface
  light-canvas: "#FFFFFF"         # light-surface floor (cards on light, print)
  link: "#FFD700"                 # hover/focus link color (signature yellow)
  # ── Functional UI colours — NOT brand colours ──────────────────────────
  # Status/feedback only: form validation, alerts, semantic chart deltas. These
  # are utilitarian, never expressive: never an accent, never decoration, never a
  # large fill. The brand accent is ALWAYS `primary` (yellow). They exist so an
  # agent has an on-brand status hue to reach for instead of inventing a garish
  # red/green (see the `fallback` contract). Tuned muted for the dark canvas.
  success: "#5FB87A"              # muted green — positive / confirmation status only
  warning: "#FFD700"              # = primary; caution / attention (the accent doubles here)
  error: "#E0664E"                # muted clay-red — error / destructive status only
  info: "#7FB2D4"                 # muted slate-blue — neutral informational status only

# HOW a colour may be applied. Values alone cannot carry a constraint, and a YAML
# comment dies in the parser, so anything that limits the USE of a colour lives
# here as data: `list_tokens`, `get_brand_overview` and `get_agent_rules` attach
# this block to every colour payload, and it is printed at the top of brand.css.
# Rule of thumb for editing this file: if a rule constrains a token, it belongs
# next to the token, not only in the prose below.
colorRules:
  text: >-
    Every text colour is SOLID. `ink`, `body`, `body-soft` and `muted` are the
    same #FFFFFF on purpose: hierarchy comes from size, weight and case, never
    opacity. Never put `opacity`, alpha or `color-mix(..., transparent)` on
    type, and never hand-roll a text colour: use the `.bl-text-*` classes.
  alpha: >-
    Alpha is legal only on non-text structure: `surface-raised` panels,
    `hairline` lines and dividers, chart marks. Never a new hex.
  onLight: >-
    The light surface is the `lightSurface` map: which roles change, which do
    not, and why. Never derive an inversion by hand and never reuse a token
    tuned for the dark canvas.

# THE LIGHT SURFACE, as data. The brand is dark-first, so every role in `colors`
# above is tuned for the dark canvas. On a light surface these roles take the
# values below and nothing else changes. This exists because `surface: light` is
# an offered choice for posters, social, decks and tables, while brand.css used
# to ship exactly one, dark, rendering of every component: an agent asked for a
# light table had to invent the inversion. It no longer has to.
lightSurface:
  note: >-
    Wrap the light area in `.bl-light` and keep using the SAME `.bl-{component}`
    classes: brand.css emits the overrides from this map. Greys are derived from
    `{colors.on-light}`, never reused from the dark-tuned tokens.
  colors:
    canvas: "{colors.light-canvas}"         # the floor inverts
    light-canvas: "{colors.canvas}"         # and so does its opposite
    ink: "{colors.on-light}"
    on-dark: "{colors.on-light}"
    body: "{colors.on-light}"
    body-soft: "{colors.on-light}"
    muted: "{colors.on-light}"
    on-light: "{colors.ink}"
    surface-raised: "rgba(26,26,26,0.04)"   # the same 4%, derived from THIS surface's ink
    hairline: "rgba(26,26,26,0.12)"         # the same 12%, derived from THIS surface's ink
    link: "{colors.on-light}"               # not the yellow: see the rules below
  # Roles that are identical on both surfaces. Listed so nobody has to ask.
  unchanged: ["primary", "on-primary", "success", "warning", "error", "info"]
  rules:
    - "The accent never inverts. {colors.primary} is the same yellow on both surfaces, and type on a yellow surface is {colors.on-primary} on both."
    - "A link on a light surface is {colors.on-light}, not the yellow: yellow on white is approved for large graphic marks only, never for text (see `combinations`). The accent still carries the focus ring and the active underline."
    - "Status hues are tuned to read on both surfaces and do not change."
    - "Text stays solid on both surfaces. The value changes, the method never does (see `colorRules.text`)."

# Brand palette (per the official manual) — the actual brand colors, grouped.
# `colors` above are the SEMANTIC ROLES that apply these; `palette` is the source.
palette:
  primary:
    - { name: White, hex: "#FFFFFF", rgb: "255/255/255", cmyk: "0/0/0/0", pms: "Not specified C" }
    - { name: Black, hex: "#1A1A1A", rgb: "26/26/26", cmyk: "0/0/0/95", pms: "Not specified C" }
  secondary:
    - { name: Yellow, hex: "#FFD700", rgb: "255/215/0", cmyk: "0/10/100/0", pms: "Not specified C" }

# Approved colour combinations — foreground on background.
combinations:
  note: >-
    Some colors are not suitable to be used in combination with others. The
    following diagram demonstrates approved color combinations.
  approved:
    - { fg: "#1A1A1A", bg: "#FFFFFF", label: "Black on white" }
    - { fg: "#FFFFFF", bg: "#1A1A1A", label: "White on black" }
    - { fg: "#FFD700", bg: "#FFFFFF", label: "Yellow on white — large graphic marks only, never text (fails contrast)" }
    - { fg: "#FFD700", bg: "#1A1A1A", label: "Yellow on black" }

# Data-visualization palette. Charts are dark-first: a `{colors.canvas}` plot
# floor, `{colors.hairline}` gridlines, `{colors.muted}` axis labels. The
# CATEGORICAL series ramp leads with the single yellow accent (the series you want
# read first), then white and greys at descending opacity — it is NEVER a rainbow
# or a chart-library default palette. Use the functional `semantic` hues ONLY when
# the chart encodes good/bad (deltas, pass/fail). This block is the answer to
# "what colours do I use in a chart" so an agent never invents red/blue/green.
chart:
  background: "{colors.canvas}"
  grid: "{colors.hairline}"
  axis: "{colors.muted}"
  label: "{colors.body}"
  # Categorical series, in order. Cap meaningful categories at ~5; beyond that use
  # small multiples rather than more colours.
  categorical:
    - "{colors.primary}"            # 1 — primary / highlight series (the signature accent)
    - "{colors.ink}"                # 2 — white
    - "rgba(255,255,255,0.62)"      # 3
    - "rgba(255,255,255,0.40)"      # 4
    - "rgba(255,255,255,0.24)"      # 5
  # Sequential / intensity ramp (low → high).
  sequential: ["rgba(255,255,255,0.10)", "rgba(255,255,255,0.40)", "{colors.primary}"]
  # Semantic deltas — only when the chart literally means good vs bad.
  semantic:
    positive: "{colors.success}"
    negative: "{colors.error}"
    neutral: "{colors.muted}"
  rules:
    - The default series colour is the single yellow accent; add white, then whites at alpha, for more series.
    - "`axis` and `label` are the SAME solid value on purpose: a charting library asks for both, the brand does not distinguish them. Same reason `body`, `body-soft` and `muted` are one white (`colorRules.text`)."
    - The alpha ramp above applies to MARKS ONLY (bars, lines, areas, the sequential fill). Every axis tick, data label, legend entry and title is solid {colors.muted}. See `colorRules.text`.
    - Never use a chart-library default palette (the rainbow), and never red/blue/green as decorative series colours.
    - Use `semantic` hues ONLY when the chart encodes good/bad (deltas, pass/fail) — otherwise stay in the categorical ramp.
    - Plot background is {colors.canvas}; gridlines are {colors.hairline}.
    - One highlight per chart — set the series you want read first in yellow and keep the rest neutral.

# Typeface source — WHICH font to use and WHERE to load it from. The `typography`
# tokens below carry the font stack; this block carries the files, the @font-face
# and the fallback so an agent can actually embed the brand typeface.
fonts:
  brand:
    family: GALTON
    stack: "GALTON, Montserrat, ui-sans-serif, system-ui, sans-serif"
    defaultWeight: 300
    case: Sentence case
    weights: "100 Thin · 300 Light (default) · 400 Regular · 500 Medium · 600 Bold · 700 Extrabold · 800 Black"
    baseUrl: "https://galton-ai-assets.vercel.app/brand/"
    files:
      - { weight: "100–900", file: "fonts/GaltonVariable.woff2", format: "woff2-variations", note: "the single web font — variable, covers every weight" }
    fontFace: |-
      @font-face {
        font-family: "GALTON";
        src: url("https://galton-ai-assets.vercel.app/brand/fonts/GaltonVariable.woff2") format("woff2-variations");
        font-weight: 100 900;
        font-style: normal;
        font-display: swap;
        /* Vertical-metric correction — KEEP these three lines. The variable woff2
           sets USE_TYPO_METRICS with an asymmetric 750/-250 typo ascent/descent,
           which floats UPPERCASE labels ~0.1em high in tight (line-height:1) boxes
           like buttons and badges. These overrides pin the webfont to the desktop
           masters' metrics (ascent−descent ≈ the cap height) so text centres
           correctly everywhere — no per-button padding hacks needed. */
        ascent-override: 96%;
        descent-override: 24%;
        line-gap-override: 0%;
      }
  fallback:
    family: Montserrat
    source: Google Fonts
    url: "https://fonts.google.com/specimen/Montserrat"
    note: "Official substitute wherever GALTON can't be embedded; last in the stack."

# Leading + hierarchy reference. The RATIO is the rule (leading = size × ratio);
# the point sizes are examples only. Keep leading consistent across applications.
# HOW THE TYPE TOKENS MAY BE APPLIED, the same way `colorRules` governs the
# colours. The two type systems carry a level called Headline at two different
# sizes, which reads as a contradiction until you know they describe two
# different artefacts. That sentence belongs next to the values.
typeRules:
  domains: >-
    THREE type systems, one typeface, and only two of them are a source of sizes.
    `typography` is the WEB set: real px, responsive, and the source of the
    `.bl-*` classes; a web section title is `typography.headline`, 64px.
    `canvas.type` in the layout catalog is the SLIDE set: px on the 1080 canvas,
    reached through `get_layout`; a slide headline is 100px UPPERCASE at leading
    1.2. `typeScale` is neither: it is the brand manual's hierarchy and LEADING
    reference, its sizes are illustrative by its own wording, and its ratios are
    the web ones. Take sizes from `typography` for a page and from `canvas.type`
    for a slide; take leading ratios from `typeScale`. Never mix two leading
    ratios inside one artefact.
  responsive: >-
    A WEB type token's `fontSize` is the DESKTOP step. Slide sizes in
    `canvas.type` are absolute and do not resize: the canvas is a fixed pixel
    frame. Where a token changes across
    breakpoints it carries the whole ladder in `responsive`, keyed by the
    `breakpoints` block, and brand.css emits the media queries, so the
    `.bl-text-*` classes resize on their own. Never invent an intermediate size.
  case: >-
    H1/display headlines and section titles (H2) are UPPERCASE; H3 and below and
    body are Sentence case; uppercase elsewhere only for eyebrow, button and
    badge. Hierarchy is size, weight and case, never a faded colour
    (`colorRules.text`).

typeScale:
  note: >-
    The brand manual's hierarchy and LEADING reference, NOT a source of sizes:
    the sizes below are illustrative (see `hierarchyNote`) and the ratios are the
    web ones. Real sizes come from `typography` for the web and from
    `canvas.type` for a slide (see `typeRules.domains`).
    When setting type, the leading should be consistent within an application
    (the slide scale uses ×1.2 for headlines, the web headline ×1.1 — don't mix
    them in one artefact). Leading refers to the space between lines of text.
    Leading = type size × ratio.
  hierarchyNote: >-
    Size, scale and position all play a factor in how information is read. Always
    ensure there is a purposeful difference between type sizes. Type sizes are
    examples only.
  levels:
    - { name: Headline, plural: Headlines, font: "GALTON Light", case: "UPPERCASE", size: 80, leading: 88, ratio: 1.1 }
    - { name: Subhead, plural: Subheads, font: "GALTON Light", case: "Sentence case", size: 30, leading: 36, ratio: 1.2 }
    - { name: Body, plural: "Body copy", font: "GALTON Light", case: "Sentence case", size: 18, leading: 27, ratio: 1.5 }

# Case rule (canonical): H1/display headlines and section titles (H2) are
# UPPERCASE; H3+ and body are Sentence case; uppercase elsewhere only for
# eyebrow, button and badge.
# THE BREAKPOINTS the responsive type ladder below is measured at. Data, not just
# the table in the Responsive Behavior section, because brand.css emits the media
# queries from these and an agent should not have to read prose to get a number.
breakpoints:
  mobile:  { max: "767px" }
  tablet:  { min: "768px", max: "1023px" }
  desktop: { min: "1024px", max: "1279px" }
  wide:    { min: "1280px" }

# HOW TO READ A TYPE TOKEN. `fontSize` is the DESKTOP step, the value to use when
# there is one size. A token that changes across breakpoints carries the whole
# ladder in `responsive`; brand.css emits the media queries for it, so the
# `.bl-text-*` classes are responsive without anyone copying numbers. See
# `typeRules` for which token set applies to which artefact.
typography:
  display-lg:
    fontFamily: "GALTON, Montserrat, ui-sans-serif, system-ui, sans-serif"
    fontSize: 136px               # the desktop step; UPPERCASE (H1/display)
    responsive: { mobile: "56px", tablet: "88px", desktop: "136px", wide: "180px" }
    fontWeight: 300
    lineHeight: 1.05
    letterSpacing: 0
  display:
    fontFamily: "GALTON, Montserrat, ui-sans-serif, system-ui, sans-serif"
    fontSize: 96px                # the desktop step; UPPERCASE (H1/display)
    responsive: { mobile: "48px", tablet: "72px", desktop: "96px", wide: "120px" }
    fontWeight: 300
    lineHeight: 1.1
    letterSpacing: 0
  headline:
    fontFamily: "GALTON, Montserrat, ui-sans-serif, system-ui, sans-serif"
    fontSize: 64px                # the desktop step; UPPERCASE (H1/H2 section titles)
    responsive: { mobile: "40px", tablet: "52px", desktop: "64px", wide: "80px" }
    fontWeight: 300
    lineHeight: 1.1
    letterSpacing: 0
  subhead:
    fontFamily: "GALTON, Montserrat, ui-sans-serif, system-ui, sans-serif"
    fontSize: 30px                # the desktop step
    responsive: { mobile: "22px", tablet: "24px", desktop: "30px", wide: "30px" }
    fontWeight: 300
    lineHeight: 1.2
    letterSpacing: 0
  body:
    fontFamily: "GALTON, Montserrat, ui-sans-serif, system-ui, sans-serif"
    fontSize: 18px                # web/body minimum — reading text is never below 18px
    fontWeight: 300
    lineHeight: 1.5
    letterSpacing: 0
  body-strong:
    fontFamily: "GALTON, Montserrat, ui-sans-serif, system-ui, sans-serif"
    fontSize: 18px
    fontWeight: 500
    lineHeight: 1.4
    letterSpacing: 0
  caption:
    fontFamily: "GALTON, Montserrat, ui-sans-serif, system-ui, sans-serif"
    fontSize: 15px                # captions, notes, metadata (the global minimum size)
    fontWeight: 300
    lineHeight: 1.5
    letterSpacing: 0
  eyebrow:
    fontFamily: "GALTON, Montserrat, ui-sans-serif, system-ui, sans-serif"
    fontSize: 15px                 # section label — the uppercase overline above headlines
    fontWeight: 500
    lineHeight: 1.4
    letterSpacing: 3.3px           # 0.22em — uppercase
  button:
    fontFamily: "GALTON, Montserrat, ui-sans-serif, system-ui, sans-serif"
    fontSize: 18px                # web/body minimum — button labels are never below 18px
    fontWeight: 600                # GALTON Bold (the live site's `.btn` weight — Galton-Bold = 600)
    lineHeight: 1
    letterSpacing: 0               # uppercase, no extra tracking
  label:
    fontFamily: "GALTON, Montserrat, ui-sans-serif, system-ui, sans-serif"
    fontSize: 18px                # form labels; 18px at every breakpoint, like the rest of the reading text
    fontWeight: 300
    lineHeight: 1.4
    letterSpacing: 0
  badge:
    fontFamily: "GALTON, Montserrat, ui-sans-serif, system-ui, sans-serif"
    fontSize: 15px                 # the global minimum size — nothing renders below 15px
    fontWeight: 400
    lineHeight: 1
    letterSpacing: 1.2px           # 0.08em — uppercase

rounded:
  none: 0px                        # inputs, selects — always flat
  component: 10px                  # small UI elements
  card: 20px                       # standard card / media container
  card-lg: 28px                    # large panel / select dropdown (galton.sk)
  pill: 100px                      # buttons, tags, chips

# Spacing rhythm (desktop values; see Responsive Behavior for the mobile/tablet steps).
spacing:
  sectionRhythm: 104px             # vertical rhythm between sections (~56px mobile)
  gutter: 4rem                     # page gutter (2.5rem tablet)
  contentMax: 1080px               # content max-width on wide screens
  cardPadding: 28px                # standard card inner padding

# Motion — the standard transition durations and easing.
motion:
  fast: "0.2s"                     # micro interactions — chevrons, small fades
  base: "0.3s"                     # default — links, accordion open/close
  slow: "0.5s"                     # large surfaces — button hover, index-row wipe
  easing: ease

# ── THE FALLBACK CONTRACT ──────────────────────────────────────────────
# Read this whenever you meet an element, component, state or colour this system
# does not explicitly define. Do NOT invent values — DERIVE them from these
# primitives. This is the single rule that stops off-brand output: an undefined
# slider must not become a red slider, an unknown chip must not become a red chip.
# `colors`/`radius` are the primitives to fall back to; `protocol` is the order of
# operations. Exposed to agents via the get_fallback MCP tool and /brand.json.
fallback:
  note: >-
    When something isn't defined here, resolve it from these primitives — never
    invent a colour, font, radius or component. The brand accent is ALWAYS the yellow
    primary. Restraint — ink + greys + a single yellow accent — is always on-brand.
  colors:
    surface: "{colors.canvas}"
    surfaceRaised: "{colors.surface-raised}"
    ink: "{colors.ink}"
    body: "{colors.body}"
    muted: "{colors.muted}"
    border: "{colors.hairline}"
    accent: "{colors.primary}"
    onAccent: "{colors.on-primary}"
    focus: "{colors.primary}"
  radius:
    control: "{rounded.none}"
    pill: "{rounded.pill}"
    container: "{rounded.card}"
  protocol:
    - "Accent: every highlighted / active / selected state, slider fill, toggle-on, link, focus ring and progress fill is {colors.primary} (yellow). NEVER red, blue, green or any other hue as an accent."
    - "Surfaces: build any new panel from {colors.surface-raised} (white at low opacity) over {colors.canvas}. Never introduce a new hex."
    - "Lines: borders, dividers, slider/track rules and table rules are {colors.hairline}."
    - "Text: {colors.ink} for headings/strong, {colors.body} for running text, {colors.muted} for captions / placeholders / disabled, under `colorRules.text`."
    - "Form controls: flat ({rounded.none}), transparent, bottom-border only; focus turns the border {colors.primary} — exactly like text-input."
    - "Pills & buttons: {rounded.pill}, uppercase, GALTON Bold. Content containers: {rounded.card}."
    - "Status hues: success / warning / error / info come ONLY from `colors` and ONLY for genuine semantic feedback (validation, alerts, deltas) — never decoration, never an accent, never a fill."
    - "Charts: use the `chart` palette (yellow + neutrals), never a chart-library default rainbow."
    - "Type: one typeface, GALTON Light, under `typeRules`. Sizes come from `typography` for the web and `canvas.type` for a slide; case comes from `typeRules.case`."
    - "When in doubt, go monochrome with one yellow accent. If you still cannot resolve it on-brand, ASK THE HUMAN — do not guess."

components:
  # ── Text styles ───────────────────────────────────────────────────────
  # The sanctioned way to colour type: every one of these carries a SOLID
  # textColor, so `.bl-text-body` / `.bl-text-caption` are always on-brand.
  # If you are picking a text colour and no class here fits, you are about to
  # invent one. Stop and read `colorRules.text`.
  text-display:
    textColor: "{colors.ink}"
    typography: "{typography.display}"
  text-headline:
    textColor: "{colors.ink}"
    typography: "{typography.headline}"
  text-subhead:
    textColor: "{colors.ink}"
    typography: "{typography.subhead}"
  text-body:
    textColor: "{colors.body}"
    typography: "{typography.body}"
  text-caption:
    textColor: "{colors.muted}"
    typography: "{typography.caption}"

  button-yellow:
    backgroundColor: "{colors.primary}"
    textColor: "{colors.on-primary}"
    typography: "{typography.button}"
    rounded: "{rounded.pill}"
    padding: "15px 30px"
    border: "1px solid {colors.canvas}"
  button-primary:
    backgroundColor: "{colors.ink}"
    textColor: "{colors.on-light}"
    typography: "{typography.button}"
    rounded: "{rounded.pill}"
    padding: "15px 30px"
    border: "1px solid {colors.canvas}"
  button-secondary:
    backgroundColor: transparent
    textColor: "{colors.ink}"
    typography: "{typography.button}"
    rounded: "{rounded.pill}"
    padding: "15px 30px"
    border: "1px solid {colors.ink}"
  # Hover states (the spec pairs `<name>-hover` with its base).
  button-yellow-hover:
    backgroundColor: "{colors.canvas}"
    textColor: "{colors.ink}"
    border: "1px solid {colors.ink}"
  button-primary-hover:
    backgroundColor: "{colors.canvas}"
    textColor: "{colors.ink}"
    border: "1px solid {colors.ink}"
  button-secondary-hover:
    backgroundColor: "{colors.ink}"
    textColor: "{colors.on-light}"
    border: "1px solid {colors.ink}"
  text-input:
    backgroundColor: transparent
    textColor: "{colors.ink}"
    typography: "{typography.body}"
    rounded: "{rounded.none}"
    padding: "0"
    height: 53px
    border: "0 0 1px 0 solid {colors.ink}"
  textarea:
    backgroundColor: transparent
    textColor: "{colors.ink}"
    typography: "{typography.body}"
    rounded: "{rounded.none}"
    padding: "12px 0"
    height: 120px
    border: "0 0 1px 0 solid {colors.hairline}"
  select:
    backgroundColor: transparent
    textColor: "{colors.muted}"
    typography: "{typography.label}"
    rounded: "{rounded.none}"
    padding: "0 30px 0 0"
    height: 53px
    border: "0 0 1px 0 solid {colors.ink}"
  checkbox:
    backgroundColor: transparent
    textColor: "{colors.ink}"
    rounded: "{rounded.none}"
    size: 30px
    border: "1px solid {colors.ink}"
  text-link:
    backgroundColor: transparent
    textColor: "{colors.ink}"
    typography: "{typography.body}"
  eyebrow:
    backgroundColor: transparent
    textColor: "{colors.primary}"
    typography: "{typography.eyebrow}"
  badge:
    backgroundColor: transparent
    textColor: "{colors.muted}"
    typography: "{typography.badge}"
    rounded: "{rounded.pill}"
    padding: "5.6px 13.6px"
    border: "1px solid {colors.hairline}"
  card:
    backgroundColor: "{colors.surface-raised}"
    textColor: "{colors.ink}"
    rounded: "{rounded.card}"
    padding: "28px"
    border: "1px solid {colors.hairline}"
  top-nav:
    backgroundColor: "{colors.canvas}"
    textColor: "{colors.ink}"
    typography: "{typography.body}"
    height: 56px
    border: "none"
  footer:
    backgroundColor: "{colors.canvas}"
    textColor: "{colors.muted}"
    typography: "{typography.body}"
    padding: "72px"
    border: "none"

  # ── Selection controls ────────────────────────────────────────────────
  # radio is the round sibling of `checkbox`; both fill with a white mark on select.
  radio:
    backgroundColor: transparent
    textColor: "{colors.ink}"
    rounded: "{rounded.pill}"
    size: 30px
    border: "1px solid {colors.ink}"
  toggle:
    backgroundColor: "{colors.hairline}"      # OFF track
    textColor: "{colors.ink}"
    rounded: "{rounded.pill}"
    width: 52px
    height: 30px
    border: "1px solid {colors.hairline}"
  toggle-on:
    backgroundColor: "{colors.primary}"       # ON track — small accent fill (allowed)
    border: "1px solid {colors.primary}"
  # Slider / range — the FILLED portion is the yellow accent; never red.
  slider-track:
    backgroundColor: "{colors.hairline}"
    rounded: "{rounded.pill}"
    height: 4px
  slider-fill:
    backgroundColor: "{colors.primary}"
    rounded: "{rounded.pill}"
    height: 4px
  slider-thumb:
    backgroundColor: "{colors.ink}"
    rounded: "{rounded.pill}"
    size: 18px
    border: "1px solid {colors.canvas}"

  # ── Text entry (beyond the base form set) ─────────────────────────────
  # stepper = numeric input with −/+ controls; field stays flat like text-input.
  stepper:
    backgroundColor: transparent
    textColor: "{colors.ink}"
    typography: "{typography.body}"
    rounded: "{rounded.none}"
    height: 53px
    border: "0 0 1px 0 solid {colors.ink}"
  stepper-button:
    backgroundColor: transparent
    textColor: "{colors.muted}"
    rounded: "{rounded.component}"
    size: 30px
    border: "1px solid {colors.hairline}"
  search:
    backgroundColor: transparent
    textColor: "{colors.ink}"
    typography: "{typography.body}"
    rounded: "{rounded.none}"
    height: 53px
    padding: "0 0 0 32px"                     # room for the leading search icon
    border: "0 0 1px 0 solid {colors.ink}"

  # ── Tags / chips (interactive, removable) ─────────────────────────────
  # Distinct from `badge` (badge is static meta). A selected filter chip goes
  # ink-filled — NOT yellow, NOT red (yellow stays the single CTA accent).
  tag:
    backgroundColor: "{colors.surface-raised}"
    textColor: "{colors.ink}"
    typography: "{typography.badge}"
    rounded: "{rounded.pill}"
    padding: "6px 12px"
    border: "1px solid {colors.hairline}"
  tag-active:
    backgroundColor: "{colors.ink}"
    textColor: "{colors.on-light}"
    border: "1px solid {colors.ink}"

  # ── Tabs ──────────────────────────────────────────────────────────────
  tab:
    backgroundColor: transparent
    textColor: "{colors.muted}"
    typography: "{typography.body}"
    rounded: "{rounded.none}"
    padding: "0 0 12px"
    border: "0 0 1px 0 solid {colors.hairline}"
  tab-active:
    textColor: "{colors.ink}"
    border: "0 0 2px 0 solid {colors.primary}"   # active underline = accent

  # ── Breadcrumbs ───────────────────────────────────────────────────────
  breadcrumb:
    backgroundColor: transparent
    textColor: "{colors.muted}"
    typography: "{typography.body}"
  breadcrumb-current:
    textColor: "{colors.ink}"

  # ── Pagination ────────────────────────────────────────────────────────
  pagination-item:
    backgroundColor: transparent
    textColor: "{colors.ink}"
    typography: "{typography.body}"
    rounded: "{rounded.pill}"
    size: 44px
    border: "1px solid {colors.hairline}"
  pagination-item-active:
    backgroundColor: "{colors.ink}"
    textColor: "{colors.on-light}"
    border: "1px solid {colors.ink}"

  # ── Menus / dropdowns (popover; distinct from the native `select`) ─────
  menu:
    backgroundColor: "{colors.surface-raised}"
    textColor: "{colors.ink}"
    rounded: "{rounded.component}"
    padding: "8px"
    border: "1px solid {colors.hairline}"
  menu-item:
    backgroundColor: transparent
    textColor: "{colors.body}"
    typography: "{typography.body}"
    rounded: "{rounded.component}"
    padding: "10px 14px"

  # ── Modal / dialog (sits on a {colors.canvas} @ ~70% scrim) ────────────
  modal:
    backgroundColor: "{colors.surface-raised}"
    textColor: "{colors.ink}"
    rounded: "{rounded.card}"
    padding: "32px"
    border: "1px solid {colors.hairline}"

  # ── Tooltip — inverted for high contrast over the dark canvas ──────────
  tooltip:
    backgroundColor: "{colors.ink}"
    textColor: "{colors.on-light}"
    typography: "{typography.badge}"
    rounded: "{rounded.component}"
    padding: "6px 10px"

  # ── Accordion / FAQ (replicated from galton.sk) ───────────────────────
  # A stack of rows divided by hairlines; each header is a question with a chevron
  # that rotates 180° on open. Single-open by default. The token carries the row
  # (header divider + title type); the open/closed animation + chevron live in CSS.
  accordion:
    backgroundColor: transparent
    textColor: "{colors.ink}"
    typography: "{typography.subhead}"           # the question title — GALTON Light
    rounded: "{rounded.none}"
    padding: "24px 0"                            # vertical rhythm of the header row
    border: "0 0 1px 0 solid {colors.hairline}"  # divider between items
  accordion-content:
    backgroundColor: transparent
    textColor: "{colors.body}"
    typography: "{typography.body}"
    padding: "0 0 24px"

  # ── Alerts / notifications ────────────────────────────────────────────
  # Neutral surface + hairline; the status colour appears ONLY as a 3px left rule
  # and the icon — never as a fill. Variants override that left border.
  alert:
    backgroundColor: "{colors.surface-raised}"
    textColor: "{colors.body}"
    rounded: "{rounded.card}"
    padding: "16px 20px"
    border: "1px solid {colors.hairline}"
  alert-success:
    border: "0 0 0 3px solid {colors.success}"
  alert-warning:
    border: "0 0 0 3px solid {colors.warning}"
  alert-error:
    border: "0 0 0 3px solid {colors.error}"
  alert-info:
    border: "0 0 0 3px solid {colors.info}"

  # ── Progress ──────────────────────────────────────────────────────────
  progress-track:
    backgroundColor: "{colors.hairline}"
    rounded: "{rounded.pill}"
    height: 6px
  progress-fill:
    backgroundColor: "{colors.primary}"        # the fill is the accent — never red
    rounded: "{rounded.pill}"
    height: 6px

  # ── Tables ────────────────────────────────────────────────────────────
  table:
    backgroundColor: transparent
    textColor: "{colors.body}"
    rounded: "{rounded.card}"
    border: "1px solid {colors.hairline}"
  table-header:
    backgroundColor: "{colors.surface-raised}"
    textColor: "{colors.muted}"
    typography: "{typography.badge}"
    border: "0 0 1px 0 solid {colors.hairline}"
  table-cell:
    backgroundColor: transparent
    textColor: "{colors.body}"
    typography: "{typography.body}"
    border: "0 0 1px 0 solid {colors.hairline}"

  # ── Side navigation (vertical nav / app shell) ────────────────────────
  side-nav:
    backgroundColor: transparent
    textColor: "{colors.body}"
    rounded: "{rounded.none}"
    border: "0 1px 0 0 solid {colors.hairline}"
  side-nav-item:
    backgroundColor: transparent
    textColor: "{colors.muted}"
    typography: "{typography.body}"
    rounded: "{rounded.component}"
    padding: "10px 14px"
  side-nav-item-active:
    backgroundColor: "{colors.surface-raised}"
    textColor: "{colors.ink}"
    border: "0 0 0 2px solid {colors.primary}"   # active marker = accent rule

  # ── Index row ─────────────────────────────────────────────────────────
  # A large editorial line-item for indexes, menus and directories (optional
  # oversized number + uppercase title + optional blurb + trailing icon). On
  # hover the WHOLE row fills with the accent and inverts to black — the brand's
  # one-accent-per-view rule applied to a list. Drives the homepage index.
  index-row:
    backgroundColor: transparent
    textColor: "{colors.ink}"
    typography: "{typography.display}"
    padding: "32px 28px"
    border: "0 0 1px 0 solid {colors.hairline}"
  index-row-hover:
    backgroundColor: "{colors.primary}"
    textColor: "{colors.on-primary}"

# How the component library is presented & exercised on the front end. The token
# values live in `components` above; this groups them into sub-sections and adds
# rendering hints (labels, placeholders, options) so the showcase can render real,
# interactive examples. `<name>-hover` token entries drive the live hover states.
componentGroups:
  - id: text
    title: Text styles
    description: >-
      The type system as classes: each one binds a type token to its colour role,
      so there is never a reason to pick a text colour by hand. A lead paragraph
      uses `.bl-text-subhead`. The rule the colours follow is `colorRules.text`.
    items:
      - { name: text-display }
      - { name: text-headline }
      - { name: text-subhead }
      - { name: text-body }
      - { name: text-caption }
  - id: buttons
    title: Buttons
    description: >-
      Pill, UPPERCASE, GALTON Bold (600), symmetric padding. Three variants; hover
      inverts toward the canvas. Use for submit / save / buy / continue / cancel.
      Labels centre correctly because the @font-face pins GALTON's vertical metrics
      (no per-button padding nudge needed).
    kind: button
    items: [button-yellow, button-primary, button-secondary]
  - id: inputs
    title: Text fields & inputs
    description: >-
      Dark-first: transparent, flat (radius 0), bottom-border only; focus turns the
      border the signature yellow. For names, emails, passwords, search and numbers.
    items:
      - { name: text-input, kind: input, label: Email, placeholder: "you@brand.com", inputType: email }
      - { name: textarea, kind: textarea, label: Message, placeholder: "Tell us about the project…" }
      - { name: select, kind: select, label: Service, options: [Branding, Marketing, Web design, Other] }
      - { name: search, kind: search, label: Search, placeholder: "Search…" }
      - { name: stepper, kind: stepper, label: Quantity, value: 25 }
  - id: selection
    title: Selection controls
    description: >-
      Checkbox (square) and radio (round) fill with a white mark on select; the
      toggle's ON track and the slider's filled range are the yellow accent — never
      red or green. Single-choice, multi-choice, on/off, and ranges.
    items:
      - { name: checkbox, kind: checkbox, label: "I agree to the privacy policy" }
      - { name: radio, kind: radio, label: Billing, options: [Monthly, Yearly] }
      - { name: toggle, kind: toggle, label: "Email notifications" }
      - { name: slider, kind: slider, label: Budget, value: 60 }
  - id: tags
    title: Tags, chips & multi-select
    description: >-
      Interactive filter chips — distinct from the static badge. A selected chip goes
      ink-filled (white on black); the brand never tints a chip red. The × removes it.
    items:
      - { name: tag, kind: tag, options: [Bratislava, Žilina, Nitra, Trnava, Košice] }
  - id: navigation
    title: Tabs, breadcrumbs & pagination
    description: >-
      In-page navigation. The active tab carries a yellow underline; the current
      breadcrumb segment and the current page are ink, everything else muted.
    items:
      - { name: tab, kind: tabs, options: [Overview, Activity, Settings] }
      - { name: breadcrumb, kind: breadcrumb, options: [Home, Services, Branding] }
      - { name: pagination-item, kind: pagination }
  - id: header-footer
    title: Header & footer
    description: >-
      The two persistent pieces of the page chrome. The header is a sticky bar with a
      blurred canvas backdrop and no border: the white wordmark lockup (with the ® +
      BRANDS tagline) at left, the nav links at right, no button. The footer is the
      canvas with a hairline top border: the big lockup centered over the copy lines.
      Both use the lockup white-on-dark, and neither ever inverts.
    items:
      - { name: top-nav, kind: nav, options: [Foundations, Components, Verbal identity, Layouts] }
      - { name: footer, kind: nav }
  - id: side-nav
    title: Side navigation
    description: >-
      A vertical in-app nav with a hairline right edge. Items are muted, brightening to
      ink on hover; the active item carries a 2px yellow left rule on a raised row. Pair
      it with the header for an app shell; collapse to a hamburger on mobile.
    items:
      - { name: side-nav, kind: sidenav, options: [Dashboard, Projects, Reports, Settings] }
  - id: overlays
    title: Menus, modals & tooltips
    description: >-
      Raised surfaces over the canvas — a dropdown menu, a dialog on a dimmed scrim,
      and the inverted (black-on-white) tooltip for high contrast on dark content.
    items:
      - { name: menu, kind: menu, options: [Edit, Duplicate, Archive] }
      - { name: modal, kind: modal }
      - { name: tooltip, kind: tooltip }
  - id: disclosure
    title: Accordion & FAQ
    description: >-
      Replicated from galton.sk: a stack of rows divided by hairlines, each a question
      with a chevron that rotates 180° on open. Single-open — opening one closes the
      rest. For FAQs, long-form Q&A and progressive disclosure of dense content.
    kind: accordion
    items:
      - { name: accordion, kind: accordion }
  - id: feedback
    title: Alerts, progress & badges
    description: >-
      System feedback: success / info / warning / error. Alerts are neutral surfaces
      with a 3px status rule + icon — the status hue is never a fill. Progress fills
      in the yellow accent.
    items:
      - { name: alert, kind: alert }
      - { name: progress-track, kind: progress, value: 64 }
      - { name: badge, kind: badge }
  - id: data
    title: Tables
    description: "Structured data, admin panels and reports: a muted uppercase header on a raised row, hairline row rules, body at 18px."
    items:
      - { name: table, kind: table }
  - id: cards
    title: Cards & surfaces
    description: >-
      Raised from white at low opacity over the canvas, hairline border, 20px radius —
      no drop shadows. Depth comes from contrast, not material elevation.
    items:
      - { name: card, kind: card }
  - id: labels
    title: Links & eyebrow
    description: "Small text utilities. Links hover to yellow; the eyebrow is the uppercase overline above headlines."
    items:
      - { name: text-link, kind: link }
      - { name: eyebrow, kind: eyebrow }
  - id: index-rows
    title: Index rows
    description: >-
      A large editorial line-item for indexes, section menus and directories: an
      optional oversized number, an uppercase title, an optional blurb and a trailing
      icon. On hover the whole row fills with the yellow accent in a single left-to-right
      wipe and the content inverts to black — the brand's one-accent-per-view rule
      applied to a list. This is the homepage "Explore the system" pattern, reusable
      anywhere a prominent list of destinations is needed.
    kind: index-row
    items:
      - { name: index-row, kind: index-row }

# Ready-to-use agent prompts. Deliberately value-free — they describe intent and
# reference roles ("the signature accent", "the display headline") so the agent
# resolves exact colours, type and components from this spec. `{{brand}}` is filled
# with the brand name at render time, so this stays universal across brands.
# These feed the MCP `get_agent_rules` tool; the human-facing catalog of TESTED
# prompts with their real artefacts lives in prompts.md (the /prompts page).
agentPrompts:
  intro: >-
    Starting prompts at the length a person actually types. `prompt` is the
    whole ask: guided mode (intake.md) fills every parameter it leaves out and
    reports the choices back. `directorPrompt` is the same request fully art
    directed, for when the outcome is already decided. Executed versions with
    their real results live on the brand site's /prompts page.
  prompts:
    - title: Landing hero
      prompt: Build an on-brand {{brand}} hero.
      directorPrompt: >-
        Build an on-brand {{brand}} hero. Dark-first canvas; a large display headline
        in Sentence case with the final word in the signature accent; a short body
        lead beneath; and the primary call-to-action button. Place the wordmark
        top-left. Pull every colour, type size and component from the design system —
        don't invent values.
    - title: Contact form
      prompt: Create an on-brand {{brand}} contact form.
      directorPrompt: >-
        Create an on-brand contact form. Stack labelled fields — a text input, a
        select and a textarea — then a consent checkbox and the primary CTA. Use the
        form component tokens: flat fields, bottom-border only, focus in the accent.
        Keep it dark-first.
    - title: Full landing page
      prompt: Compose a full {{brand}} landing page.
      directorPrompt: >-
        Compose a full {{brand}} landing page: a hero, two or three content sections
        and a footer. Use the design system's type scale, spacing rhythm and
        components throughout; keep the dark-first canvas and reserve the accent for
        emphasis. Pull every value from the spec — don't invent any.
    - title: Rebrand a page
      prompt: Restyle this page to match {{brand}}.
      directorPrompt: >-
        Restyle this page to match {{brand}}. Map every colour, font and component to
        the design system's tokens and replace ad-hoc values with the brand's. Keep
        the logo white or black only.
    - title: Dashboard / data UI
      prompt: Build an on-brand {{brand}} dashboard.
      directorPrompt: >-
        Build an on-brand {{brand}} dashboard. Dark-first canvas; a side-nav, cards,
        a data table, and form controls (sliders, toggles, steppers, multi-select
        chips). Every interactive/selected state — slider fill, toggle-on, active
        chip, focus ring — is the single yellow accent; never red, blue or green.
        Pull every value from the design system; for anything undefined, follow the
        fallback contract.
    - title: Chart / data visualization
      prompt: Build an on-brand {{brand}} chart.
      directorPrompt: >-
        Build an on-brand chart. Use the `chart` palette: a {{brand}} canvas plot
        floor, hairline gridlines, solid white axis and data labels, and the
        categorical series ramp (yellow highlight first, then white, then whites at
        alpha). The alpha ramp is for the marks, never for the labels. Never use a
        chart library's default rainbow; use the semantic good/bad hues only for real
        deltas.
  rules:
    - "A one-sentence request is a complete brief. Run guided mode (intake.md / get_intake) before producing: fill the unset parameters from the defaults, ask at most the blocking one, report every choice back."
    - Describe intent and structure; let the agent resolve exact values from the spec.
    - Reference roles — "primary CTA", "the accent", "display headline" — not hex codes.
    - Keep the logo white or black only; never recolour it.
    - Don't use the accent as a large fill, and set the case from `typeRules.case`.
    - The accent is ALWAYS the yellow primary. Never introduce red, blue or green as an accent, selected state, slider fill, link or focus ring.
    - Apply `colorRules.text` to every text colour, and `colorRules.alpha` to everything that is not text.
    - "Never invent a value: `criticalRule` is the short form, `fallback` is the contract for deriving one, and asking the human is always allowed."
    - Status hues (success/warning/error/info) are functional only — semantic feedback, never decoration or a brand accent.
    - In charts, use the `chart` palette (yellow + neutrals), not a library-default rainbow.
---

## Overview

GALTON Brands is a **dark-first**, editorial, high-contrast brand system. The page floor is a near-black canvas (`{colors.canvas}` — #1A1A1A), text is white (`{colors.ink}`), and a single signature **primary yellow** (`{colors.primary}` — #FFD700) carries every accent — CTAs, highlights, focus rings, the hero word. Yellow is never a large fill; on a yellow surface text is always black (`{colors.on-primary}`).

Everything is set in **one typeface — GALTON** — at **Light (300)**. Weight steps up to Medium (500) / Bold (600) only for emphasis. H1/display headlines and section titles (H2) are UPPERCASE; H3+ and body are Sentence case; uppercase elsewhere only for eyebrow, button and badge. Where GALTON can't be embedded (email, Google Docs/Slides, system contexts), **Montserrat** is the official substitute — it is last in every font stack. Hierarchy is created by **size and a leading ratio** (Headline ×1.1, Subhead ×1.2, Body ×1.5), not by heavy weights.

The component language is **pill-and-flat**: buttons are full pills (`{rounded.pill}`), uppercase, GALTON Bold; inputs are **flat** (`{rounded.none}`), transparent, bottom-border only, with a primary-yellow focus. The palette is fixed — no invented shades; raised surfaces are built from white at low opacity (`{colors.surface-raised}`), never a new hex.

> **If this system doesn't define something, do not invent it.** Derive it from the
> primitives in the **Fallbacks & unknown elements** section (the `fallback` block):
> monochrome surfaces and text, hairline lines, and a single yellow accent — never a
> red/blue/green you reached for by default. This one rule prevents most off-brand output.

## Colors

### Brand palette
The brand has three colours, in two groups:
- **Primary palette** — **White** (#FFFFFF) and **Black** (#1A1A1A). The base of the system: black is the dark-first canvas, white is the ink.
- **Secondary palette** — **Yellow** (#FFD700). The single accent: CTAs, highlights, focus rings, the hero word. Used sparingly, never a large fill; on a yellow surface, foreground is always black (#1A1A1A).

**Text is always solid:** white (`{colors.ink}`) on dark, near-black (`{colors.on-light}`) on light. Only non-text structure (`{colors.hairline}` dividers, `{colors.surface-raised}` panels, chart marks) is derived from white at low opacity. The canonical statement of this, and the one agents receive with every colour payload, is the `colorRules` block in the token frontmatter.

### Surface
- **Canvas** (`{colors.canvas}` — #1A1A1A): The default page floor on every dark surface. The brand is dark-first.
- **Surface Raised** (`{colors.surface-raised}` — white @4%): Cards, modals, raised panels. Built from white at low opacity over the canvas — never a new hex. Pair with a `{colors.hairline}` border.
- **Hairline** (`{colors.hairline}` — white @12%): 1px dividers, table rows, card outlines, the top/bottom bars.
- **Light Canvas** (`{colors.light-canvas}` — #FFFFFF): The floor for light surfaces (cards on light, print, email).

The full light rendering is the `lightSurface` block in the token frontmatter: which roles change, which do not, and the rules that go with it. `brand.css` emits it as a `.bl-light` scope, so a light area uses the SAME `.bl-{component}` classes and nobody derives an inversion by hand.

### Text
Four roles, one value. `{colors.ink}` (headlines, primary text), `{colors.body}` (running text), `{colors.body-soft}` (secondary paragraphs, leads) and `{colors.muted}` (captions, metadata, placeholders, disabled) are all #FFFFFF on the dark canvas. The names mark editorial role, not a different colour. On a light surface all four become `{colors.on-light}` (#1A1A1A).

The `.bl-text-*` classes in brand.css bind each role to its type token, so `.bl-text-caption` is the caption size AND the caption colour in one class. Dividers and borders use `{colors.hairline}`, never a grey text colour.

### Usage Rules
- Default page = `{colors.canvas}` background, `{colors.ink}` text.
- `{colors.primary}` is for emphasis only — never a large fill. On a primary surface, text is always black.
- Need a raised surface? Build it from white/grey at low opacity (`{colors.surface-raised}`) — do not introduce a new hex.
- Selection highlight is primary-on-black.
- **Text is never translucent.** See `colorRules.text`: solid values only, hierarchy from size, weight and case. On a primary surface text is solid `{colors.on-primary}`.
- Text contrast meets WCAG AA at all sizes; the yellow accent is never used for text on white.

## Typography

### Font Family
The system runs **one typeface — GALTON** — for both headings and body, from a **single variable woff2** that covers every weight 100–900 (the only web font). The default is **Light (300)**, set in **Sentence case** at normal tracking.

**Montserrat** is the **official substitute**: use it wherever GALTON can't be embedded (email, Google Docs/Slides, system contexts). It is last in every font stack: `GALTON, Montserrat, ui-sans-serif, system-ui, sans-serif`. There is no second brand face — GALTON does everything.

Weights — the GALTON named cuts: 100 Thin · **300 Light (default)** · 400 Regular · 500 Medium · **600 Bold** · 700 Extrabold · 800 Black. The single variable woff2 covers 100–900 continuously, so any in-between weight is available. **Buttons use Bold (600)** — the same `Galton-Bold` weight the live site renders its `.btn` at.

### Font source & embedding
The GALTON typeface ships with this package — don't substitute a lookalike. Load the **variable woff2** (one file, weights 100–900):

- **File:** `https://galton-ai-assets.vercel.app/brand/fonts/GaltonVariable.woff2` — the single web font (variable, weights 100–900). Embed this and nothing else.
- **Base URL:** `https://galton-ai-assets.vercel.app/brand/` (resolved to wherever this is deployed)
- **Hotlink these absolute URLs exactly as given** — the files are served with permissive CORS (`Access-Control-Allow-Origin: *`), so a cross-origin `@font-face` works. Do **not** relativise them to `/brand/fonts/…` (that resolves against *your* host and 404s, silently falling back to Montserrat) and don't copy the file locally. One exception: in the unzipped offline package (`https://galton-ai-assets.vercel.app/bundle.zip`), `./brand/fonts/GaltonVariable.woff2` **is** this file, so an offline build points `src` there.

```css
@font-face {
  font-family: "GALTON";
  src: url("https://galton-ai-assets.vercel.app/brand/fonts/GaltonVariable.woff2") format("woff2-variations");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
  /* Vertical-metric correction — KEEP these. The variable woff2 ships with
     USE_TYPO_METRICS and an asymmetric 750/-250 typo ascent/descent, so the glyphs
     sit ~0.1em high in tight (line-height:1) boxes — UPPERCASE buttons and badges
     look floated up and off-centre. These overrides pin the webfont to the desktop
     masters' metrics (ascent−descent ≈ cap height) so labels centre correctly. */
  ascent-override: 96%;
  descent-override: 24%;
  line-gap-override: 0%;
}
```

> **Why the three `*-override` lines matter.** Without them, GALTON's UPPERCASE
> labels float ~0.1em above the optical centre of any pill/badge (the font reserves
> empty descender space it never uses). The overrides re-declare the metrics the
> browser lays text out with — so you center buttons and badges with plain symmetric
> padding, never an asymmetric "push the text down" hack. Embed the `@font-face`
> exactly as given, descriptors included.

Then use the stack `GALTON, Montserrat, ui-sans-serif, system-ui, sans-serif`. **Montserrat** is the substitute and loads from Google Fonts (`https://fonts.google.com/specimen/Montserrat`) — it is last in the stack and only kicks in where GALTON can't be embedded. The full `fonts` block in the frontmatter lists every file, format and the ready-to-paste `@font-face`.

### Hierarchy

All GALTON Light (300). **H1/display headlines and section titles (H2) are UPPERCASE; H3+ and body are Sentence case; uppercase elsewhere only for eyebrow, button and badge** (matching the slide system). Leading (line-height) is a ratio of the type size. Display sizes are responsive: the token value is the desktop step and the full ladder is the token's own `responsive` map, keyed by the `breakpoints` block. `brand.css` emits the media queries, so the `.bl-text-*` classes resize on their own.

| Token | Size (responsive) | Weight | Line Height | Letter Spacing | Use |
|---|---|---|---|---|---|
| `{typography.display-lg}` | 56 → 88 → 136 → 180px | 300 | 1.05 | 0 | Jumbotron / extreme display |
| `{typography.display}` | 48 → 72 → 96 → 120px | 300 | 1.1 | 0 | Large hero headline |
| `{typography.headline}` | 40 → 52 → 64 → 80px | 300 | 1.1 | 0 | Headline (size ×1.1) |
| `{typography.subhead}` | 22 → 24 → 30px | 300 | 1.2 | 0 | Subhead (size ×1.2) |
| `{typography.body}` | 18px | 300 | 1.5 | 0 | Body — the web/body minimum (never below 18px) |
| `{typography.body-strong}` | 18px | 500 | 1.4 | 0 | Emphasis inside body |
| `{typography.eyebrow}` | 15px | 500 | 1.4 | 0.22em | Section label — uppercase overline above headlines, primary color |
| `{typography.button}` | 18px | 600 | 1.0 | 0 | Uppercase button labels (GALTON Bold = 600, the live `.btn` weight) |
| `{typography.label}` | 18 → 24px | 300 | 1.4 | 0 | Form labels |
| `{typography.badge}` | 15px | 400 | 1.0 | 0.08em | Uppercase pill chip (the global 15px minimum) |

### Principles
Emphasis comes from **size and leading**, then a small step in **weight** (300 → 500/600) — never from uppercase body copy. The rule of thumb for any new size: Headline ×1.1, Subhead ×1.2, Body ×1.5 leading, with a purposeful jump between levels.

H1/display headlines and section titles (H2) are UPPERCASE; H3+ and body are Sentence case; uppercase elsewhere only for eyebrow, button and badge. Never uppercase body copy.

### Note on Font Substitutes
If GALTON is unavailable, fall back to **Montserrat** (Google Fonts) — the official substitute, already last in every stack. Montserrat is a geometric sans close to GALTON in proportion; keep the Light (300) default and Sentence case. Do not substitute a serif or a condensed face.

## Elevation & Depth

| Level | Treatment | Use |
|---|---|---|
| Flat | No shadow, no border | Body, top nav, footer, most sections |
| Hairline | 1px `{colors.hairline}` border | Section dividers, table rows, card outlines |
| Raised surface | `{colors.surface-raised}` (white @4%) + hairline border | Cards, modals, panels — no drop shadow |
| Accent glow | Radial primary tint at very low opacity | Optional hover halo on a feature panel only |

The system avoids drop shadows and gradients. Depth comes from the contrast between the near-black canvas and a barely-raised white-at-opacity surface, plus the hairline. Do not add material-style elevation shadows.

## Shapes

### Border Radius Scale

| Token | Value | Use |
|---|---|---|
| `{rounded.none}` | 0px | Inputs, textareas, selects, checkboxes — always flat |
| `{rounded.component}` | 10px | Small UI elements |
| `{rounded.card}` | 20px | Standard card / media container — the signature radius (galton.sk uses 20px on nearly every card, image and media block) |
| `{rounded.card-lg}` | 28px | Large panel / floating select dropdown (galton.sk `.nice-select-dropdown`) |
| `{rounded.pill}` | 100px | Buttons, tags, chips, the badge |
| `50%` (not a token) | 50% | True circles only — avatars, status dots, the custom cursor (galton.sk) |

The radius language is intentional and matches the live site: **form controls are flat (0px); interactive pills are fully round (100px); content containers and media are softly rounded (20px), with large floating panels at 28px; true circles use 50%**. Avoid arbitrary in-between radii — galton.sk's one-off `5/12/15/25/30px` values are page-specific and not part of the system.

## Components

> Interaction note: transitions use the `motion` tokens — standard `ease` at 0.3s (`{motion.base}`) for links and small state changes, 0.5s (`{motion.slow}`) for button hover and large surfaces. Hover states are tokens too: each `<name>-hover` entry pairs with its base component and drives the live hover state; the YAML is the source of truth for default, focus and hover alike.

### Top Navigation
**`top-nav`** — A sticky bar on `{colors.canvas}` with a blurred backdrop and **no border** (galton.sk's header separates by the blur alone — no rule): the canvas at ~70% opacity behind a `blur(16px)`, **56px tall** (the token's `height`). Carries the **white wordmark lockup** — the full mark with the ® and the letter-spaced BRANDS tagline (`galton-wordmark-white-tagline-tight.png`, ~46px tall) — at left, and the nav links at right. **No button lives in the persistent nav** — keep `{component.button-yellow}` (and any outline CTA) for the in-page calls to action (hero, forms). Links are **`{typography.body}` — 18px, weight 300, `{colors.ink}`** — with a **45px** gap, brightening to `{colors.primary}` (the accent) on hover; the lockup never recolours (white or black only). Below ~1400px the links collapse to a hamburger that opens a full-screen overlay.

### Logo lockup
The **GALTON wordmark** with a superscript ® and a letter-spaced "BRANDS" tagline beneath — this is the lockup the header and footer carry (`galton-wordmark-white-tagline-tight.png`, white-on-dark; a black-on-light twin exists for inverted surfaces). The wordmark on its own ships as a `fill="currentColor"` SVG. **White or black only** — the lockup never turns yellow, even on hover. See "Logo & Iconography".

### Buttons
All buttons: pill (`{rounded.pill}`), UPPERCASE, GALTON Bold (`{typography.button}`), `inline-flex` centered, **symmetric** padding (`15px 30px` desktop), border `1px solid`, transition `all 0.5s ease`. Labels sit dead-centre because the `@font-face` pins GALTON's vertical metrics (see Typography → "Why the three `*-override` lines matter") — **do not** re-introduce an asymmetric "less padding at the bottom" hack; that was a workaround for the un-corrected webfont and is no longer needed. Responsive padding follows the live site: mobile `10px 25px` · ≤991px `12px 20px` · desktop `15px 30px`.

- **`button-yellow`** — The signature CTA (galton.sk `.btn-yellow`). `{colors.primary}` background, `{colors.on-primary}` text, `{colors.canvas}` border. Hover → `{colors.canvas}` background, `{colors.ink}` text, `{colors.ink}` border.
- **`button-primary`** — A solid light button (galton.sk `.btn-primary`). `{colors.ink}` background, `{colors.on-light}` text, `{colors.canvas}` border. Hover → `{colors.canvas}` background, `{colors.ink}` text, `{colors.ink}` border.
- **`button-secondary`** — The outline/ghost pill on dark (galton.sk `.btn-transparent-white`): transparent with a `{colors.ink}` border and text. Hover → `{colors.ink}` background, `{colors.on-light}` text. On a dark canvas this is also how the source's solid `.btn-secondary` (dark fill + white border) reads, so the two collapse into this one token.

> **Source mapping (galton.sk).** The WordPress theme defines five pill variants on a *light* page; this dark-first system realises the same set with three tokens. `btn-yellow → button-yellow`, `btn-primary → button-primary`, and both `btn-secondary` (solid dark) and `btn-transparent-white` (transparent) → `button-secondary` (they're visually identical on the `{colors.canvas}` floor). The fifth, `btn-transparent` (black border + text, hover → yellow text), is a **light-surface-only** outline — on light, override `button-secondary`'s white border/text to `{colors.on-light}`, exactly as the form note describes.

### Inputs & Forms
Dark-first: transparent background, bottom-border only, primary-yellow focus. On light surfaces, override the white border/text to black.

- **`text-input`** — Flat (`{rounded.none}`), transparent, `{colors.ink}` bottom border, height 53px, `{typography.body}`/300, placeholder `{colors.muted}`. Focus → border `{colors.primary}`.
- **`textarea`** — Flat, hairline (`{colors.hairline}`) bottom border, min-height 120px, vertically resizable. Focus → `{colors.primary}`.
- **`select`** — Flat, `{colors.ink}` bottom border, height 53px, `appearance: none`. The native arrow is replaced by the brand chevron (grey "V") at the right, padding-right 30px, weight 300, `{colors.muted}` text. Focus → `{colors.primary}`. (Sourced from the galton.sk contact form.)
- **`checkbox`** — Flat square (`{rounded.none}`), `{colors.ink}` border, 30px → 45px@1024, fills with a white square on `:checked`, focus → `{colors.primary}`. Pair with a label in `{typography.body}`/300 inside a flex `form-check` row.
- **`label`** — `{typography.label}` (GALTON Light), `{colors.ink}`, block, 8px bottom margin.

### Links, Eyebrow & Badge
- **`text-link`** — `color: inherit`, no underline, hover/focus → `{colors.link}` (primary). Transition `color 0.3s ease`.
- **`eyebrow`** — Small uppercase label above headlines: `{typography.eyebrow}`, `{colors.primary}`.
- **`badge`** — Neutral pill chip for meta/status/version on dark: `{typography.badge}`, `{colors.muted}`, `{colors.hairline}` border, `{rounded.pill}`.

### Cards & Containers
**`card`** — `{colors.surface-raised}` background, `{colors.hairline}` border, `{rounded.card}` (20px), ~28px padding, no drop shadow. (Detailed card patterns are not yet fully specified — see Known Gaps.)

### Footer
**`footer`** — `{colors.canvas}` with a `{colors.hairline}` top border, everything centered: the **white wordmark lockup big** (~80px tall) above two copy lines in **`{colors.ink}` at 18px** — the © line and the brand/website line. ~80px vertical padding. The footer never inverts.

### Selection controls
The choice family shares the flat, dark-first language. The accent (`{colors.primary}`) marks the *chosen* state — never red or green.

- **`checkbox`** — Flat square (`{rounded.none}`), `{colors.ink}` border, 30px; fills with a white square on `:checked`. Multi-choice, consent, filters.
- **`radio`** — The round sibling: a circle (`{rounded.pill}`), `{colors.ink}` border, 30px; fills with a white dot on select. Single-choice from a set.
- **`toggle`** / **`toggle-on`** — A 52×30 pill switch. OFF = `{colors.hairline}` track; ON = `{colors.primary}` track (`toggle-on`) with a white knob. On/off preferences and settings.
- **`slider-track`** / **`slider-fill`** / **`slider-thumb`** — A 4px `{colors.hairline}` track; the **filled portion is `{colors.primary}`** (yellow, never red); a 18px white thumb. Ranges, budgets, percentages.

### Steppers & search
- **`stepper`** — A numeric input with `−`/`+` controls (`stepper-button`: ghost, `{colors.hairline}` border, `{rounded.component}`). The field stays flat (bottom-border only) like `text-input`. Quantities, counts.
- **`search`** — A flat bottom-border input with a leading search icon (32px left padding). Focus → `{colors.primary}`. In content-heavy chrome a `{rounded.pill}` contained variant is allowed.

### Tags, chips & multi-select
- **`tag`** — An interactive, removable filter chip: `{rounded.pill}`, `{colors.surface-raised}` background, `{colors.hairline}` border, `{colors.ink}` text, a muted `×`. Distinct from the static `badge`.
- **`tag-active`** — The selected state goes **ink-filled** (white background, black text) — **never tinted red/green**. A multi-select is a row of tags plus the input.

### Tabs, breadcrumbs & pagination
- **`tab`** / **`tab-active`** — Underline tabs. Inactive = `{colors.muted}` with a `{colors.hairline}` rule; **active = `{colors.ink}` text with a 2px `{colors.primary}` underline**. Switch sections without leaving the page.
- **`breadcrumb`** / **`breadcrumb-current`** — Muted segments separated by a chevron; the current page is `{colors.ink}`. Shows position in a hierarchy.
- **`pagination-item`** / **`pagination-item-active`** — 44px pill buttons, `{colors.hairline}` border; the current page is **ink-filled** (not yellow — yellow stays the single CTA). For lists, search results and feeds.

### Menus, modals & tooltips
- **`menu`** / **`menu-item`** — A dropdown/popover panel: `{colors.surface-raised}`, `{colors.hairline}` border, `{rounded.component}`; items hover to a raised row. An *actions* menu, distinct from the native `select`.
- **`modal`** — A dialog panel: `{colors.surface-raised}`, `{colors.hairline}` border, `{rounded.card}`, 32px padding, over a `{colors.canvas}`-at-~70% scrim. Confirmations, forms, prompts. No drop shadow.
- **`tooltip`** — **Inverted** for contrast over dark content: `{colors.ink}` (white) background, `{colors.on-light}` (black) text, `{rounded.component}`, badge-size text. Short hover/tap explanations.

### Accordion & FAQ
**`accordion`** / **`accordion-content`** — Replicated from galton.sk. A vertical stack of rows divided by `{colors.hairline}` rules (no card, no fill); each header is a question in `{typography.subhead}` (GALTON Light) with a **chevron that rotates 180°** when open, tinting to `{colors.primary}`. **Single-open** by default — opening one row closes the rest (match the source). The body (`accordion-content`) is `{typography.body}`. Height animates open/closed (~0.3s); the header is a real `<button>` with `aria-expanded`/`aria-controls` for accessibility (the source had none — this is the on-brand, accessible version). Use for FAQs, long-form Q&A, and progressive disclosure of dense content (e.g. the per-tool setup guides on the "For AI agents" page). On a light surface, the dividers and chevron flip to `{colors.on-light}`.

### Alerts, progress & tables
- **`alert`** (+ `alert-success` / `-warning` / `-error` / `-info`) — A neutral `{colors.surface-raised}` notification with a **3px left rule + icon in the status colour** — the hue is never a fill. Success / error / warning / info messages. See "Status & feedback colours".
- **`progress-track`** / **`progress-fill`** — A 6px `{colors.hairline}` track with a **`{colors.primary}` fill** (never red). For a spinner, rotate a single-arc ring in `{colors.primary}`; for steps, a row of `{colors.hairline}` rules with the current step in yellow.
- **`table`** / **`table-header`** / **`table-cell`** — `{colors.hairline}` outline (`{rounded.card}`); header is `{colors.surface-raised}` with `{colors.muted}` uppercase 15px labels; cells are `{colors.body}` at 18px with hairline row rules. Structured data, admin panels, reports.

### Side navigation
- **`side-nav`** / **`side-nav-item`** / **`side-nav-item-active`** — A vertical nav with a `{colors.hairline}` right edge. Items are `{colors.muted}`, brightening to `{colors.ink}` on hover; the **active item carries a 2px `{colors.primary}` left rule** on a `{colors.surface-raised}` row. Pair with a top-nav for an app shell; collapse to a hamburger on mobile.

## Data visualization

Charts are **dark-first and monochrome-led**, exactly like the rest of the system: a near-black plot floor, hairline gridlines, muted labels, and **one yellow accent** carrying the series you want read first. The full palette is the `chart` block in the frontmatter (read it via `get_chart_palette` or `list_tokens` → `chart`).

### Colour rules
- **Categorical series** use the ramp in order: the signature yellow first (the highlight), then white, then white at 62% / 40% / 24%. **Five distinguishable categories is the practical ceiling** — beyond that, prefer small multiples over more colours.
- **Never** reach for a chart library's default palette (the rainbow), and **never** use red / blue / green as a decorative series colour. This is the most common way a generated chart goes off-brand.
- The **plot background** is `{colors.canvas}`, **gridlines** are `{colors.hairline}`, **axis ticks and labels** are `{colors.muted}`, data labels `{colors.body}`.
- **Semantic** good/bad colouring (`{colors.success}` / `{colors.error}`) is used **only** when the chart literally encodes positive vs negative — a delta, a target met/missed. Otherwise stay in the yellow-and-neutral ramp.
- **One highlight per chart.** Put the series that matters in yellow and keep the rest neutral; that single accent does the work a rainbow only pretends to.

### Sequential / intensity
For a heat ramp or single-measure intensity, go `white @10% → white @40% → yellow` (low → high). Keep the steps few and legible.

## Status & feedback colours

The brand palette is fixed — **black, white, yellow**. But real products must signal success, warning, error and information, and an agent with no sanctioned status colour will invent a garish one (the red sliders and green box that prompted this work). So the system defines four **functional** status hues, muted for the dark canvas:

| Role | Token | Hex | Use |
|---|---|---|---|
| Success | `{colors.success}` | #5FB87A | Confirmation, valid input, positive delta |
| Warning | `{colors.warning}` | #FFD700 | Caution / attention (this is the brand yellow) |
| Error | `{colors.error}` | #E0664E | Error, destructive action, failed validation |
| Info | `{colors.info}` | #7FB2D4 | Neutral, informational |

**These are functional, not brand, colours.** Hard rules:
- They signal **status only** — form validation, alerts/notifications, semantic chart deltas. Never decoration, never a heading colour, never a button fill.
- They are **never the accent.** The accent is always `{colors.primary}` (yellow). An active tab, a selected chip, a slider fill, a focus ring — all yellow, never `success`/`error`.
- They appear **minimally**: a 3px rule on an alert, an icon, a 1px error border on an input — never a large coloured panel.

## Fallbacks & unknown elements

**This is the most important section for an AI agent.** Almost all off-brand output comes from one move: the agent meets something the system doesn't spell out — a slider, a stepper, a multi-select chip, a chart colour — and **fills the gap with a tool default** (a red accent, a rainbow chart, a material drop-shadow). The fix is a contract: *when in doubt, derive — never invent.* The machine-readable version is the `fallback` block (read it via `get_fallback`).

### The fallback colour set
Resolve any undefined colour from these primitives — and only these:
- **Surface** → `{colors.canvas}`; **raised surface** → `{colors.surface-raised}` (white at low opacity, never a new hex).
- **Text** → `{colors.ink}` (headings/strong), `{colors.body}` (running text), `{colors.muted}` (captions/placeholders/disabled).
- **Lines** (borders, dividers, tracks, table rules) → `{colors.hairline}`.
- **Accent / focus** (any active, selected, highlighted, filled-progress, slider-fill or link state) → `{colors.primary}` (yellow). **Never red, blue or green.**

### The protocol
1. **Look for a defined token or component first** (the components and token tables in this spec; over MCP, `get_component` with no name lists every one of them, and `list_tokens`). Use it as-is.
2. **No exact match? Inherit the nearest defined sibling's language** — a new form control behaves like `text-input` (flat, transparent, bottom-border, yellow focus); a new pill behaves like a button; a new container behaves like `card`.
3. **Still undefined? Compose from the fallback colour set + the radius scale** — monochrome surface and text, hairline lines, a single yellow accent; `{rounded.none}` for controls, `{rounded.pill}` for pills, `{rounded.card}` for containers.
4. **Need a status hue?** Use `success` / `warning` / `error` / `info` — and only for genuine semantic feedback.
5. **Need chart colours?** Use the `chart` palette.
6. **If you still can't resolve it on-brand, ask the human.** A question beats a hallucinated red slider.

> The default move: **monochrome plus one yellow accent.** An output that is black, white, grey and a little yellow is on-brand; an output with an invented colour is not.

## Logo & Iconography

### Two marks
All logo files are served at `https://galton-ai-assets.vercel.app/brand/logos/` — **hotlink them by their absolute URL** (CORS is open). In a header/footer lockup, embed the wordmark SVG, e.g. `<img src="https://galton-ai-assets.vercel.app/brand/logos/galton-wordmark-white.svg" alt="GALTON">` — **never retype "GALTON" as text** to fake the logo. Fetch any file by name below.

- **Symbol — the "G"**: `galton-symbol.svg` (`fill="currentColor"`, inherits text colour) — favicon, app icon, avatar, loader, compact mark. Explicit-fill copies `galton-symbol-white.svg` / `galton-symbol-black.svg` for raster/email.
- **Wordmark — "GALTON"**: `galton-wordmark.svg` (vector, `fill="currentColor"`) — the primary digital logo. Explicit `galton-wordmark-white.svg` / `galton-wordmark-black.svg` for raster; the full **GALTON® + BRANDS tagline lockup** as `galton-wordmark-white-tagline.png` / `galton-wordmark-black-tagline.png` for formal/print.

### The hard color rule
**The logo is white or black ONLY — never yellow/primary or any other color.** When using a `currentColor` mark, ensure the inherited color is white or black, never `{colors.primary}`. White on dark; black on light (or on a primary-yellow surface, where the mark is black). Never recolor, add shadows/gradients/outlines, stretch, rotate, or re-typeset the wordmark.

### Favicons
The "G" symbol as a site/app icon (white on transparent), served at `https://galton-ai-assets.vercel.app/brand/icons/`:
- `galton-favicon-32x32.png` (browser tab), `galton-favicon-192x192.png` (Android/high-DPI), `galton-favicon-180x180.png` (Apple touch icon).

> **Complete asset manifest:** every logo, font and icon — with formats, usage notes and direct URLs — is served as JSON at `https://galton-ai-assets.vercel.app/brand.json` and indexed at `https://galton-ai-assets.vercel.app/llms.txt`. This spec carries enough to fetch the brand directly; the manifest is the exhaustive list.

## Do's and Don'ts

### Do
- Build dark-first: `{colors.canvas}` floor, `{colors.ink}` text, `{colors.primary}` for accents only.
- Set everything in GALTON Light (300), Sentence case. Step to 500/600 only for emphasis.
- **Nothing renders below 15px** on the web — 15px is the hard minimum (section-label `eyebrow`, `badge`, captions, code, table headers). Body/reading text (body, buttons, form labels, links, nav) is **18px**.
- Keep the leading ratios: Headline ×1.1, Subhead ×1.2, Body ×1.5.
- Use `{component.button-yellow}` for the signature CTA; keep all buttons pill + uppercase + Bold.
- Keep inputs flat (`{rounded.none}`), transparent, bottom-border only, focus → `{colors.primary}`.
- Build raised surfaces from white/grey at low opacity (`{colors.surface-raised}`).
- Colour type with the `.bl-text-*` classes; they carry the solid colour and the type token together.
- Build a light surface by wrapping it in `.bl-light` and keeping the same component classes. The accent never inverts.
- Keep the logo white or black, always.
- Hotlink fonts and logos by their absolute `https://galton-ai-assets.vercel.app/brand/…` URLs (CORS is open); embed the wordmark SVG for any lockup.
- Make every active / selected / focused / filled state the yellow accent — sliders, toggles, tabs, chips, progress, focus rings.
- For anything undefined, derive from the `fallback` contract: monochrome + one yellow accent; ask the human before inventing.
- In charts, use the `chart` palette (yellow + neutrals); reserve `success`/`error` for genuine good-vs-bad deltas.
- H1/display headlines and section titles (H2) are UPPERCASE; H3+ and body are Sentence case; uppercase elsewhere only for eyebrow, button and badge.

### Don't
- Don't color the logo yellow/primary or any color other than white/black. (Hard rule.)
- Don't introduce a new hex for surfaces — derive from white/grey at opacity.
- **Don't hand-invert the palette for a light surface**, and don't reuse a dark-tuned value on it: the `lightSurface` map and the `.bl-light` scope already say what changes. A link on light is ink, never the yellow.
- **Don't apply `opacity`, `rgba()` alpha or `color-mix(..., transparent)` to text**, and don't hand-roll a text colour when a `.bl-text-*` class exists. Translucency is for borders, dividers, surfaces and chart marks only. (Fade/grey secondary text = off-brand.)
- Don't use `{colors.primary}` as a large fill, or put primary type on white (low contrast).
- Don't uppercase body copy — outside H1/display headlines and H2 section titles, uppercase is for eyebrow, buttons and badge only.
- Don't add drop shadows or gradients for depth; use the canvas/hairline/raised-surface stack.
- Don't round inputs or square the buttons — form controls are 0px, buttons are 100px.
- Don't substitute a serif or condensed face for GALTON — fall back to Montserrat only.
- Don't relativise asset URLs to `/brand/…` or copy fonts/logos locally — hotlink the absolute `https://galton-ai-assets.vercel.app/brand/…` URL, or the font silently falls back to Montserrat off-site. (Inside the unzipped offline package, `./brand/…` is that same file rather than a local copy, so an offline build uses it.)
- Don't fake the logo by retyping "GALTON" as styled text — embed the wordmark SVG.
- Don't put any button — yellow or outline — in the persistent top nav; keep CTAs (the yellow primary and any outline secondary) for the in-page calls to action (hero, forms).
- **Don't invent a colour, font, radius or component when the system is silent — derive it from the `fallback` contract, or ask.** (This is the rule that stops the red-slider / rainbow-chart output.)
- Don't use red, blue or green as an accent, selected state, slider fill, link or focus ring — the accent is always the yellow primary.
- Don't use the functional status hues (`success`/`error`/`info`) as decoration, headings or fills; they signal status only.
- Don't colour a chart with a library-default rainbow — use the `chart` palette (yellow + neutrals).

## Responsive Behavior

### Breakpoints

| Name | Width | Key Changes |
|---|---|---|
| Mobile | < 768px | Single column; display type drops to the smallest step; section rhythm ~56px; form rows go 1-up |
| Tablet | 768–1024px | Wider gutters (2.5rem); subhead/headline step up; 2-up form rows |
| Desktop | 1024–1280px | Full type scale; gutter 4rem; section rhythm ~104px |
| Wide | > 1280px | Display-lg/display reach their max (180/120px); content max 1080px |

### Touch Targets
- Buttons render at a comfortable tap height (≥44px effective).
- `{component.text-input}` and `{component.select}` are 53px tall.
- `{component.checkbox}` is 30px (mobile) → 45px (desktop).

### Collapsing Strategy
- The top-nav links collapse into a full-screen hamburger overlay below ~1400px (secondary pages already sit under an "Others" dropdown); the wordmark lockup stays.
- `form-row` two-column grids collapse to one column below ~640px.
- Display headlines step down one size per breakpoint; body stays 18px throughout (the web/body minimum).

### Image / Mark Behavior
- SVG marks scale crisply at any size; prefer the vector wordmark for digital and the tagline PNG only for formal/print.

---

# BRAND GUIDE — identity, voice, logo policy (source: brand.md)

## About GALTON

GALTON is a confident, editorial, high-contrast brand house. This file carries the
brand's **identity and logo policy**; the full visual system (colour, type,
components) lives in the design spec and the writing voice in the voice guide —
read those rather than restating them here.

## Voice & tone

See the **verbal identity** for essence, personality, registers, lexicon, the
do/don't principles and a ready-to-paste AI brief (`verbal-identity.md`, or
`get_voice_guide` over MCP).

## Logo policy

The logo is white or black ONLY — never the primary yellow or any other color. White on dark, black on light or on a yellow surface. Never recolor, rotate, stretch, add shadows/gradients, or re-typeset the wordmark.

---

# VERBAL IDENTITY — brand voice + AI brief (source: https://galton-ai-assets.vercel.app/verbal-identity.md)

---
# Verbal identity — the human + machine record of HOW GALTON Brands writes.
# Source of truth, authored verbatim (Slovak) from the internal verbal-identity manual.
# Brand-specific: edit this (with brand.md / design.md / layouts.md / icons.json)
# to rebrand; touch no application code.
updated: "2026-06-20"
languages: [sk, en]
purpose: "Zdroj pravdy pre to, ako značka GALTON Brands hovorí. Platí pre web, LinkedIn, e-maily, pitch, prezentácie, prípadové štúdie, blogy, náborové aj interné texty. Verbálna identita je jedna z troch rovnocenných vrstiev značky (vizuálna, zvuková, verbálna) a nikdy nesmie protirečiť ostatným dvom. Pri práci s AI nástrojmi vlož do nich AI brief."
essence: "Sebavedomý stratég s dušou tvorcu, ktorý hovorí veci na rovinu a baví ho to."

centralIdea:
  idea: "Celá značka stojí na myšlienke jedinečnosti a odlíšiteľnosti. Názov vznikol z myšlienky odtlačku prsta ako unikátneho znaku každého človeka. Z toho plynie esencia toho, aké značky GALTON buduje a aký je sám: odvážne, unikátne a jasne identifikovateľné. Ak text nie je odvážny, unikátny a jasne rozpoznateľný ako GALTON, nie je hotový."
  story: "Príbeh dopĺňa cesta poctivého rebrandingu zo ZoneMedia na GALTON Brands (trval takmer dva roky, lebo k nemu pristúpili poctivo) a 15+ rokov vedenia značiek cez výzvy trhu. GALTON si tým, čo predáva, prešiel sám."
  governance: "Historická osoba Francisa Galtona je spojená aj s eugenikou (citlivá medzinárodná asociácia). Origin story preto vždy rámcuj okolo myšlienky odtlačku prsta a jedinečnosti, nie okolo osoby."

personality:
  - name: "Stratég-Challenger"
    note: "Vedie, pýta sa „prečo“, reframuje problém, argumentuje dátami a skúsenosťou. Nerobí mechanicky to, čo klient povie, ak to nedáva zmysel."
  - name: "Partner pre vizionárov"
    note: "Hovorí s lídrami (C-level) ako rovný s rovným. Nikdy nie servisný dodávateľ čakajúci na zadanie."
  - name: "Sebavedomý, no bez ega"
    note: "Istota stojí na dátach a faktoch, nie na pozérstve. Dovolí si povedať „toto nevieme, zistíme to“."
  - name: "Odvážny tvorca"
    note: "Mení pravidlá hry, hľadá inakosť, dovolí si vtip a prekvapenie tam, kde to funguje."
  - name: "Ľudský a zodpovedný"
    note: "„Na konci dňa ide o ľudí.“ Hrdý na tím, empatický ku klientovi pod tlakom, zodpovedný za dlhodobý dopad."

positioning:
  we: "Sme strategický partner pre značky, ktoré chcú dlhodobo napredovať. Pracujeme v horizonte 3 až 10 rokov a značku budujeme komplexne (stratégia, naming, vizuálna/zvuková/verbálna identita, technológie, exekúcia, interná aj externá komunikácia)."
  notWe: "Nie sme digitálna, webová ani „full-service“ agentúra na jednorazové projekty. S nimi sa neporovnávame, fungujeme v inom kontexte."
  valueProp: "Prepájame stratégiu, technologickú silu a ľudský potenciál a budujeme značky zvnútra von, ktoré dlhodobo víťazia v meniacom sa svete kultúr a technológií, ako najcennejšie aktívum firmy s merateľným dopadom na biznis."

messagingPillars:
  - name: "Brand as business"
    note: "Značka je najcennejšie aktívum, strategická investícia, nie položka v marketingovom rozpočte."
  - name: "Zvnútra von"
    note: "Značka žije v mysliach ľudí; externý obraz musí sedieť s internou kultúrou, lebo každý zamestnanec je nositeľom značky a každý zákazník je médiom. Značku vnímajú cez mikromomenty, nie cez brandbooky."
  - name: "Konzistentní v jadre, flexibilní v prejave"
    note: "Relevancia značky stojí na rovnováhe medzi konzistenciou (naratív, kľúčové prvky, brand kódy) a schopnosťou prispôsobiť sa dobe."
  - name: "Emócia pred racionalitou"
    note: "Ľudia reagujú najprv na emóciu a tú si potom obhajujú rozumom; hľadáme nezameniteľné emočné atribúty, nielen funkčné benefity."
  - name: "Dlhodobé partnerstvo a merateľný dopad"
    note: "Nepredávame výstupy (logo, web), predávame dopad. Cieľ nie je uzavrieť obchod, ale začať partnerstvo."
  - name: "Jedinečnosť a odvaha"
    note: "Odlíšiteľnosť je základný stavebný prvok; značka musí byť dosť odvážna robiť veci inak."

pitch:
  whyUs: "Prečo my: strategické ukotvenie + kombinácia stratégie a dizajnu, 15+ rokov skúseností."
  whyNow: "Prečo teraz: reálne trhové okno a cena odkladu, vždy podložené situáciou klienta."
  whyYou: "Prečo vy: riešenie napasované na ciele a metriky klienta."
  pyramid: "Argumentačná pyramída (poradie v každom dlhšom texte): najprv inšpiruj (emócia, vízia, zmysel) → potom potvrď (dôvera, konzistentný tón, dôkaz) → nakoniec podlož (fakty, proces, metodika). Zákazník nekupuje logiku, kupuje presvedčenie, ktoré si vie obhájiť."
  evolution: "Evolúcia vs revolúcia: pri rebrandingu etablovaných značiek rešpektujeme vybudované brand equity — meníme to, čo nefunguje, a chránime to, čo si zákazníci pamätajú („žiadna revolúcia, ale premyslená evolúcia“)."

registers:
  - name: "Konzultatívny"
    where: "web „o nás“, sales, e-maily, pitch, PR"
    note: "Vecný, jasný, zrelý, partnerský, podložený dátami. Krátke úderné vety striedané s vysvetľujúcimi. Priame „vy“. Žiadny hype."
  - name: "Edukačný"
    where: "blog, how-to, thought leadership"
    note: "Mentor, ktorý učí štedro, ale s autoritou; mýtus → reframe, rečnícke otázky, listicles, vtipné medzinadpisy, učenie cez svetové príklady, inline tipy, mäkké CTA na záver."
  - name: "Case-study produkčný"
    where: "referencie na webe"
    note: "Naratívny oblúk, vtipné sekčné headery, výzva pomenovaná otázkou, klient = hrdina."
  - name: "Claimy a kampane"
    where: "taglines, kampaňové linky, social hooky, medzinárodné claimy"
    note: "Odvážny, hravý, úderný. Puny, anglické hooky, antitéza/paralelizmus, prekvapenie."

tensions:
  - name: "Gravitas ↔ hra"
    note: "Vážnosť experta verzus tvorivá odvaha. Bližšie k stratégii triezvejšie, bližšie ku kampani odvážnejšie. Hravosť nikdy nesmie podkopať dôveryhodnosť."
  - name: "Priamosť ↔ empatia (radical candor)"
    note: "Povedz aj nepríjemnú pravdu (navýšenie budgetu, nereálny termín, „len logo nestačí“), ale vždy s rešpektom a partnersky — nikdy apologeticky ani arogantne."

channels:
  - channel: "Web „o nás“ / služby"
    register: "Konzultatívny"
    note: "Sebavedomý, zrelý, žiadny hype."
  - channel: "Blog / thought leadership"
    register: "Edukačný"
    note: "Mentor; dovolí si kontrariánsky názor a sebairóniu."
  - channel: "Prípadové štúdie"
    register: "Case-study produkčný"
    note: "Naratívny oblúk, vtipné headery, výsledok ako dopad."
  - channel: "LinkedIn"
    register: "Konzultatívny / hravý"
    note: "Hrdý, ľudský, energický; emoji striedmo."
  - channel: "Instagram"
    register: "Hravý (na doplnenie)"
    note: "Najuvoľnenejší, vizuálne vedený — reálny obsah ešte treba zladiť."
  - channel: "E-mail / sales"
    register: "Konzultatívny"
    note: "Partnerský, nikdy apologetický; prvý kontakt nepredáva — dáva hodnotu a kladie otázku."
  - channel: "Recruitment / employer branding"
    register: "Konzultatívny / hravý"
    note: "Postav na EVP a „prečo u nás a prečo teraz“, nie na zozname benefitov."
  - channel: "Kampaňové linky a claimy"
    register: "Claimy a kampane"
    note: "Odvážne, hravé, úderné."

principles:
  do:
    - "Hovoríme na rovinu, krátko, bez prázdnych fráz."
    - "Každé tvrdenie podložíme „prečo“ — dátami alebo skúsenosťou."
    - "Oslovujeme priamo; klient je hrdina, my sme sprievodca."
    - "Myslíme dlhodobo — budovanie, konzistencia, progres."
    - "Dovolíme si vtip tam, kde funguje."
    - "Priznáme, čo nevieme."
    - "Sme partneri — povieme aj nepríjemnú pravdu."
  dont:
    - "Žiadny hype a sľuby zázrakov („revolučný“, „zaručene“, „number one“)."
    - "Buzzwordy bez obsahu ani žargón bez vysvetlenia."
    - "Neosobný, korporátne chladný tón."
    - "Nesľubujeme rýchle zázraky ani jednorazové „opravy“."
    - "Vtip v citlivých či krízových témach."
    - "Nehráme sa na vševedúcich."
    - "Nie sme servilní ani apologetickí."

lexicon:
  own:
    - "budovanie značky"
    - "príbeh"
    - "transformácia"
    - "jedinečnosť / odlíšenie / inakosť"
    - "dôvera"
    - "dopad"
    - "hodnota"
    - "investícia (nie náklad)"
    - "partner (nie dodávateľ)"
    - "zvnútra von"
    - "konzistencia"
    - "relevancia"
    - "dlhodobo / kontinuálne"
    - "kultúry a technológie"
    - "brand as business"
    - "brand idea"
    - "brand tagline"
    - "brand kódy"
    - "distinctive brand asset"
    - "fluent device"
    - "touchpoint"
    - "mentálna a fyzická dostupnosť"
    - "mikromomenty"
    - "discovery workshop"
    - "sound branding / zvuková identita"
    - "naming / neologizmus"
    - "evolúcia"
    - "najcennejšie aktívum"
  specialized:
    employerBranding:
      - "EVP"
      - "Employee/Candidate Experience (EX/CX)"
      - "social recruiting"
      - "brand ambasádori"
      - "talent/performance management"
      - "Total Rewards"
      - "Workplace Wellness"
      - "employee lifecycle"
      - "stay interview"
      - "offboarding"
      - "D&I"
    realEstate:
      - "Place Value Proposition (PVP)"
      - "Category Entry Points (CEPs)"
      - "proof points"
  avoid:
    - "„náklad na branding“ (vždy „investícia“)"
    - "„len logo / farbičky / dizajn“"
    - "lacné urgencie a FOMO"
    - "„zaručene / revolučné / number one“"
    - "agresívne CTA"
    - "apologetický tón"
    - "woke washing"
  framing:
    - "investícia, nie náklad"
    - "partnerstvo, nie projekt"
    - "dopad, nie výstup"
    - "strategický systém, nie redizajn"
    - "optimalizujeme rozsah, nie hodnotu"
    - "nezľavujeme — vysvetľujeme"

# Zákazy, ktoré platia vždy a v každom výstupe. Boli súčasťou `mechanics`, kde
# ich štandardná odpoveď `get_voice_guide` nevracala; sú hore, lebo pravidlo
# musí cestovať spolu s tým, čo tvaruje vetu, nie sedieť v podsekcii.
# V akom jazyku vzniká výstup. Pravidlo bolo v intake protokole, teda dve volania
# od hlasu, ktorého sa týka. Cestuje spolu s hlasom, lebo ho potrebuje každý, kto
# píše čokoľvek.
languageRule: >-
  Píš v jazyku, v ktorom píše používateľ. Keď to z požiadavky nevidno, píš po
  slovensky: slovenčina je základný jazyk značky. To isté platí pre otázky
  guided mode aj pre report na konci. Angličtinu používaj zámerne, podľa
  `bilingual`, nie ako náhradu za slovenčinu.

hardRules:
  - "Nepoužívaj „em dash“ (pomlčku —) nikde: ani v copy, ani v nadpisoch, ani v popiskoch. Namiesto nej čiarka, dvojbodka, zátvorka alebo nová veta."
  - "Nepoužívaj vetnú konštrukciu „Nie X, ale Y“."
  - "Text nikdy nezosvetľuj priehľadnosťou. Farba písma je vždy plná (`colorRules.text` v design.md)."

mechanics:
  name: "„GALTON Brands“; „GALTON“ verzálkami. V bežnom texte je prijateľné aj samotné „GALTON“."
  address: "Vykanie, zdvorilé a partnerské."
  quotes: "Smart quotes „…“."
  emoji: "Striedmo a len na LinkedIn/Instagram; nie na webe, v dokumentoch a pitch materiáloch."
  hashtags: "Len na sociálnych sieťach."
  numbers: "Vlastné výsledky len overené; externé štatistiky vždy so zdrojom (kurzívou, „Zdroj: …“)."

bilingual: "Slovenčina je základný jazyk. Angličtinu používame dvojako: (1) v claimoch a názvoch (case studies, kampane); (2) ako odborné marketingové termíny vpletené priamo do slovenského textu — prirodzene a bežne (brand idea, touchpoint, discovery workshop, sound branding, positioning, EVP, funnel, KPI, ROI). Pravidlo: zámerne a zrozumiteľne, nie samoúčelne. (Pozn.: španielsky trh ani pobočku v komunikácii neuvádzame — aktivity sú pozastavené.)"

storytelling:
  heroGuide: "Klient = hrdina, GALTON = sprievodca („Spojili sme sily“, „Spoločne sme zadefinovali“)."
  caseStudyRule: "Case study nikdy nekončí pri výstupe: nie „odovzdali sme web“, ale „klientovi vďaka tomu stúpli predaje“."
  rhetoric:
    - "Paralela viacerých svetových ikon odhaľujúca spoločný princíp (model Mercedes-Benz / Heinz / Fjällräven)."
    - "Učenie cez svetové príklady vrátane varovných (GAP, woke-washing State Street)."
    - "Príbeh transformácie."
    - "Future pacing („Predstavte si, že o 6 mesiacov…“)."
    - "Ľudové úslovie ako rámec myšlienky („Keď dvaja robia to isté, nie je to to isté“)."
    - "Anafora a rečnícke otázky."

caseStudyTemplate:
  steps:
    - step: "Klient + situácia"
      note: "„Pre [klienta], [stručný popis], sme zrealizovali…“ / „Spoločnosť X nás oslovila s požiadavkou na…“."
    - step: "Výzva ako otázka"
      note: "Pomenuj klientov problém rečníckou otázkou („Ako však zaujať náročnú klientelu…?“)."
    - step: "Discovery"
      note: "Discovery workshop, hĺbkové rozhovory, analýza trhu a konkurencie."
    - step: "Stratégia + brand idea + tagline"
    - step: "Identita a brand kódy"
      note: "Vizuálne (a podľa potreby zvukové) prevedenie, distinctive brand asset."
    - step: "Aplikácia naprieč touchpointami"
      note: "„Od cenovky po kamión“: online aj offline."
    - step: "Výsledok"
      note: "Dopad, nie výstup; čísla len overené."
  headerRule: "Sekčné headery píš ako malé claimy — nikdy generické."
  headerExamples:
    - "Od cenovky po kamión"
    - "Naming bez hádaniek"
    - "Kampaň, ktorú je dobre počuť"
    - "Zoznámte sa s Majsterboxom"

blogFormat: "Otvor mýtom a reframe-om, veď čitateľa rečníckymi otázkami, štruktúruj listicle/how-to (číslované kroky, dôvody, checklisty), uč cez svetové príklady (úspechy aj varovania), pridaj inline tipy kurzívou a zakonči mäkkým CTA s prelinkom na službu/kontakt. Tón: mentor, ktorý si dovolí čitateľa aj opraviť („Chyba, vážení. Nehľadáte nových ľudí. Hľadáte správnych.“)."

examples:
  - lang: sk
    off: "Sme špičková agentúra s revolučnými riešeniami, ktoré zaručene posunú vašu značku na vrchol."
    on: "Značka nie je logo. Je to prísľub, ktorý musí svojím správaním a komunikáciou kontinuálne a konzistentne napĺňať. Už viac ako 15 rokov pomáhame značkám tento prísľub napĺňať, krok po kroku."
  - lang: sk
    off: "Pripravíme vám nový moderný dizajn a logo."
    on: "Začíname významom a obchodným dopadom, až potom dizajnom. Pekný vizuál je dôsledok. Cieľom je dlhodobý efekt značky."
  - lang: sk
    off: "Rebranding vyrieši vaše problémy."
    on: "Rebranding je závažné rozhodnutie. Z nesprávneho dôvodu narobí viac škody než úžitku, preto sa najprv pýtame prečo."

governance:
  rules:
    - "Pravidlo pravdivosti (záväzné): žiadne číslo, referencia ani urgencia, ktoré neobstoja, keď ich klient overí. Vlastné výsledky musia byť overené; externé štatistiky sa uvádzajú so zdrojom. Mená a logá klientov len so súhlasom a v súlade s NDA. Dôveryhodnosť je naše najdrahšie aktívum."
    - "Žiadne woke washing: komunikované hodnoty musia sedieť s realitou vnútri firmy. Inak sa to obráti proti značke."
    - "Rozsah pravidla o urgencii: v našom vlastnom hlase (sales, pitch, web) žiadne lacné urgencie ani FOMO. V konverznej copy, ktorú tvoríme pre klienta (najmä B2C), sú legitímne behaviorálne nudge nástrojom — ale len ak sú pravdivé (reálna dostupnosť, reálny termín)."
    - "GALTON naming: origin story rámcovať okolo odtlačku prsta a jedinečnosti, nie okolo osoby."
  checklist:
    - "Stojí text aspoň na jednom pilieri?"
    - "Je register správny pre kanál?"
    - "Sú obe napätia ustrážené (dôveryhodnosť + rešpekt)?"
    - "Sú všetky čísla overené / zdrojované?"
    - "Znie to odvážne, unikátne a jasne ako GALTON?"
    - "Nepoužil som zakázaný slovník?"

aiBrief: |
  Píš ako GALTON Brands — strategická brandingová agentúra. Hlas: sebavedomý stratég s dušou tvorcu, ktorý hovorí na rovinu. Si partner pre vizionárskych lídrov (C-level), nie dodávateľ. Veď, pýtaj sa „prečo“, argumentuj dátami; buď sebavedomý, ale priznaj, čo nevieš (bez ega). Píš krátko a jasne, striedaj úderné a vysvetľujúce vety, oslovuj priamo (vykanie). Najprv emócia a zmysel, potom dôkaz a fakty. Rámcuj: investícia (nie náklad), partnerstvo (nie projekt), dopad (nie výstup). Stoj na pilieroch: brand as business, budovanie zvnútra von, konzistencia v jadre + flexibilita v prejave, emócia pred racionalitou, dlhodobé partnerstvo, jedinečnosť a odvaha. Centrálna idea je jedinečnosť — výstup musí byť odvážny, unikátny a jasne rozpoznateľný. Registre podľa kontextu: konzultatívny (web/sales), edukačný/mentor (blog — mýtus→reframe, rečnícke otázky, listicles, svetové príklady, mäkké CTA), case-study (klient ako hrdina, dopad nie výstup), claimy/kampane (hravé, na antitéze či pun-e). Vyhýbaj sa: hype („zaručene/revolučné/number one“), buzzwordom, lacným urgenciám/FOMO vo vlastnom hlase, apologetickému aj arogantnému tónu, woke washingu. Nikdy neuvádzaj nepodložené čísla; externé štatistiky cituj so zdrojom. Origin story rámcuj okolo myšlienky odtlačku prsta a jedinečnosti, nie osoby Francisa Galtona. Píš primárne po slovensky; angličtinu používaj zámerne v claimoch, názvoch a odborných termínoch. Tón vždy partnerský, nikdy apologetický. Nepoužívaj „em dash“. Nepoužívaj vetnú konštrukciu „Nie X, ale Y“.
---

## Verbal identity

GALTON Brands má jeden hlas v rôznych polohách. Tento dokument je zdrojom pravdy
pre to, ako značka hovorí — naprieč webom, LinkedInom, e-mailmi, pitchom,
prezentáciami, prípadovými štúdiami, blogmi aj internými textami. Verbálna
identita je jedna z troch rovnocenných vrstiev značky (vizuálna, zvuková,
verbálna) a nikdy nesmie protirečiť ostatným dvom.

### Centrálna idea

Celá značka stojí na myšlienke jedinečnosti a odlíšiteľnosti. Názov vznikol
z myšlienky odtlačku prsta ako unikátneho znaku každého človeka. Z toho plynie,
aké značky GALTON buduje a aký je sám: odvážne, unikátne a jasne
identifikovateľné. Ak text nie je odvážny, unikátny a jasne rozpoznateľný ako
GALTON, nie je hotový.

Príbeh dopĺňa cesta poctivého rebrandingu zo ZoneMedia na GALTON Brands a 15+
rokov vedenia značiek cez výzvy trhu. GALTON si tým, čo predáva, prešiel sám.

**Governance:** historická osoba Francisa Galtona je spojená aj s eugenikou.
Origin story preto vždy rámcuj okolo myšlienky odtlačku prsta a jedinečnosti,
nie okolo osoby.

### Bilingválne pravidlá

Slovenčina je základný jazyk. Angličtinu používame zámerne v claimoch a názvoch
(case studies, kampane) a ako odborné marketingové termíny vpletené priamo do
slovenského textu (brand idea, touchpoint, discovery workshop, sound branding,
positioning, EVP, funnel, KPI, ROI) — prirodzene a zrozumiteľne, nie samoúčelne.
Španielsky trh ani pobočku v komunikácii neuvádzame (aktivity sú pozastavené).

---

# LINKEDIN PLAYBOOK (source: https://galton-ai-assets.vercel.app/linkedin.md)

---
# LinkedIn playbook — post types, anatomy, rules and examples (SK + EN).
# Brand-specific. Each post type maps to a carousel recipe in layouts.md.
updated: "2026-06-13"
postTypes:
  - { id: educational, name: "Educational carousel", intent: "Teach one concept across slides.", recipe: educational-carousel, copyAnatomy: [hook, context, payoff, cta], length: { chars: [600, 1200] } }
  - { id: insight, name: "Single insight", intent: "One sharp idea, one image.", recipe: single-insight, copyAnatomy: [hook, payoff], length: { chars: [300, 700] } }
  - { id: announcement, name: "Announcement", intent: "Ship / launch news.", recipe: announcement, copyAnatomy: [hook, what, cta] }
  - { id: event, name: "Event / speaker", intent: "Promote a talk or event.", recipe: event-post, copyAnatomy: [hook, details, cta] }
  - { id: naming, name: "Naming showcase", intent: "Show a naming case.", recipe: naming-carousel, copyAnatomy: [hook, cases, cta] }
hashtags:
  policy: "3–5, lowercase, brand + topic; never a wall of tags."
  always: [galtonbrands]
hooks:
  - "Problem → promise"
  - "Counter-intuitive claim"
  - "Number + outcome"
formatting:
  firstLine: "The hook must stand alone — LinkedIn truncates after ~2 lines."
  lineBreaks: "Short paragraphs, one idea each; a blank line between."
  cta: "End with a single clear call to action."
examples:
  - { lang: en, type: educational, text: "New product, new market, new challenge.\n\nMost launches fail on positioning, not product.\n\nHere's how a go-to-market strategy fixes that ↓\n\n#galtonbrands #gtm #branding" }
  - { lang: en, type: insight, text: "Your brand isn't your logo.\n\nIt's the deliberate gap between you and everyone else.\n\n#galtonbrands #branding" }
  - { lang: sk, type: educational, text: "Nový produkt, nový trh, nová výzva.\n\nVäčšina launchov padne na pozícii, nie na produkte.\n\nAko to rieši go-to-market stratégia ↓\n\n#galtonbrands #gtm #branding" }
  - { lang: sk, type: insight, text: "Vaša značka je viac než logo.\n\nJe to premyslený rozdiel medzi vami a všetkými ostatnými.\n\n#galtonbrands #branding" }
---

## How GALTON writes on LinkedIn

Open with a hook that stands alone — LinkedIn truncates after about two lines,
so the first line has to earn the click. Keep one idea per paragraph with a blank
line between. End with a single clear call to action.

Pair the post with a carousel built from the **recipe named on its post type** —
the copy and the slides tell the same story. An educational post leads into an
educational carousel; a naming showcase into the naming carousel; a single
insight needs only one statement slide.

Hashtags stay lowercase and few (3–5), always including the brand tag. The voice
is the same as everywhere else: confident, editorial, plain — in Slovak or
English. See the verbal identity (`verbal-identity.md`, or `get_voice_guide`
over MCP) for tone, vocabulary and the do/don't rules.

---

# SOUND BRANDING: the audio identity (source: https://galton-ai-assets.vercel.app/sound.md)

---
# Sound branding: the official GALTON Brands audio identity.
# Brand-specific and optional, like linkedin.md. The files live in
# public/brand/sound/; durations and waveform peaks are NOT written here, they are
# measured from the files by `npm run sound:peaks` into sound.peaks.json, so the
# numbers can never drift from the audio.
updated: "2026-10-01"
tempo: 120
intro: >-
  The GALTON sound is built around the Branding Anthem. The sound logo, the
  cuts, the loop and the ambients all come from it, and all but one run at
  120 BPM, so a piece can follow another on the bar without a new edit.
principles:
  - key: "Sign-off"
    title: "The sound logo signs off"
    text: "It closes a film, a reel or a presentation. Nothing plays over it and nothing follows it."
  - key: "120 BPM"
    title: "One tempo"
    text: "Everything except Ambient 3 runs at 120 BPM, so one bar lasts 2 seconds. Cut picture on the bar and it lands on the music."
  - key: "Under the voice"
    title: "Music sits under the voice"
    text: "Under narration, use an instrumental or an ambient and keep it well below the voice. The versions with spoken words never go under a voiceover."
  - key: "Loop it"
    title: "Loop, do not stretch"
    text: "For a longer piece, repeat the Loop or an ambient from bar to bar. Never time-stretch the anthem."
# Pick by job: what to reach for, per kind of work. `asset` is an id from `assets`.
jobs:
  - job: "Film with a narrator"
    asset: anthem-instrumental
    note: "Or an ambient. Key moment on the drop at 0:26."
  - job: "Film without a narrator"
    asset: anthem
    note: "The spoken words carry the story."
  - job: "30 second spot"
    asset: anthem-30s
    note: "The voice version if nothing else speaks."
  - job: "Social cut, bumper, pre-roll"
    asset: anthem-15s-voice
    note: "The shortest complete statement."
  - job: "Screen that runs for hours"
    asset: loop
    note: "32 bars, seamless. Loop it on the bar."
  - job: "Event walk-in"
    asset: ambient-emergence
    note: "Builds for minutes, lands on the sound logo."
  - job: "Waiting screen, transition"
    asset: ambient-5-no-beat
    note: "Pads only, no rhythm."
  - job: "The last second of anything"
    asset: sound-logo
    note: "Nothing plays after it."
# An example 60 second film, drawn as an edit timeline on the page.
anatomy:
  length: 60
  music: anthem-instrumental
  drop: 26
  logo: sound-logo
  logoAt: 56
  voice: [[2, 9], [11, 19], [28, 35], [38, 46], [48, 54]]
groups:
  - id: signature
    title: "Signature"
    note: "The two pieces that say GALTON on their own."
  - id: anthem
    title: "The anthem"
    note: "GALTON Branding Anthem, 120 BPM, in full and cut to length."
  - id: beds
    title: "Loops and ambients"
    note: "Beds for film, events, product demos and presentations."
assets:
  - id: sound-logo
    group: signature
    title: "Sound logo"
    file: sound/galton-sound-logo.mp3
    kind: sound logo
    vocals: none
    loop: false
    offline: true
    description: "The GALTON sonic signature, three seconds long. It does in sound what the G symbol does on screen."
    use: "The last sound of a film, a reel, a presentation or an event opener. Always alone, never under a voice."
  - id: ambient-emergence
    group: signature
    title: "Emergence"
    file: sound/galton-ambient-emergence.mp3
    kind: ambient with sound logo
    vocals: none
    loop: false
    description: "A four and a half minute ambient that builds slowly and ends on the sound logo."
    use: "Event walk-ins, installations, long openers, the moments before a talk starts."
  - id: anthem
    group: anthem
    title: "Anthem"
    file: sound/galton-anthem.mp3
    kind: anthem, full
    vocals: spoken
    loop: false
    bpm: 120
    description: "The full GALTON Branding Anthem with spoken words: Vision. Strategy. Identity. Creativity. Prosperity. Communication. It opens and closes on the line Building brands from the inside out."
    use: "Brand films and showreels without a narrator, where the anthem carries the story."
  - id: anthem-instrumental
    group: anthem
    title: "Anthem, instrumental"
    file: sound/galton-anthem-instrumental.mp3
    kind: anthem, full
    vocals: none
    loop: false
    bpm: 120
    description: "The same anthem without the voice. A quiet intro, a steady groove from 0:08, and the full drop at 0:26."
    use: "Any film with a voiceover. Put the key moment of your cut on the drop at 0:26."
  - id: anthem-30s
    group: anthem
    title: "Anthem, 30 s"
    file: sound/galton-anthem-30s.mp3
    kind: anthem, cut
    vocals: none
    loop: false
    bpm: 120
    description: "A 30 second edit of the anthem, instrumental, with a natural ending."
    use: "30 second spots, social video and product reels."
  - id: anthem-30s-voice
    group: anthem
    title: "Anthem, 30 s with voice"
    file: sound/galton-anthem-30s-voice.mp3
    kind: anthem, cut
    vocals: spoken
    loop: false
    bpm: 120
    description: "The 30 second edit ending on the spoken line Building brands from the inside out."
    use: "Spots that end on the GALTON line, with no other voiceover."
  - id: anthem-15s
    group: anthem
    title: "Anthem, short"
    file: sound/galton-anthem-15s.mp3
    kind: anthem, cut
    vocals: none
    loop: false
    bpm: 120
    description: "The short edit of the anthem, instrumental, with its natural decay left in."
    use: "Short social cuts, bumpers and pre-rolls."
  - id: anthem-15s-voice
    group: anthem
    title: "Anthem, 15 s with voice"
    file: sound/galton-anthem-15s-voice.mp3
    kind: anthem, cut
    vocals: spoken
    loop: false
    bpm: 120
    description: "The 15 second edit that closes on the spoken line Building brands from the inside out."
    use: "The shortest complete GALTON statement: bumpers and stories."
  - id: loop
    group: beds
    title: "Loop"
    file: sound/galton-loop.mp3
    kind: loop
    vocals: none
    loop: true
    bpm: 120
    description: "Exactly 32 bars at 120 BPM. The end runs back into the start without a seam."
    use: "Product demos, LinkedIn videos, trade fair screens, anything that needs a steady pulse of any length."
  - id: ambient-3
    group: beds
    title: "Ambient 3"
    file: sound/galton-ambient-3.mp3
    kind: ambient
    vocals: none
    loop: true
    bpm: 102
    description: "An ambient on a slower pulse, the one bed that is not on the 120 BPM grid."
    use: "Calm explainers and case studies where the picture sets the pace."
  - id: ambient-4
    group: beds
    title: "Ambient 4"
    file: sound/galton-ambient-4.mp3
    kind: ambient
    vocals: none
    loop: true
    bpm: 120
    description: "Exactly 32 bars of ambient on the house tempo."
    use: "Under narration, behind interviews and in presentations."
  - id: ambient-5
    group: beds
    title: "Ambient 5"
    file: sound/galton-ambient-5.mp3
    kind: ambient
    vocals: none
    loop: true
    bpm: 120
    description: "48 bars of the ambient with its full arrangement, including the bleep layer."
    use: "Tech and product stories, interfaces on screen."
  - id: ambient-5-no-bleep
    group: beds
    title: "Ambient 5, no bleep"
    file: sound/galton-ambient-5-no-bleep.mp3
    kind: ambient
    vocals: none
    loop: true
    bpm: 120
    description: "The same 48 bars without the bleep, so it sits softer under a voice."
    use: "Under a voiceover when Ambient 5 feels too busy."
  - id: ambient-5-no-beat
    group: beds
    title: "Ambient 5, no beat"
    file: sound/galton-ambient-5-no-beat.mp3
    kind: ambient
    vocals: none
    loop: true
    bpm: 120
    description: "Only the pads, no rhythm. The quietest bed in the system."
    use: "Transitions, reflective moments, waiting screens and the pause before a reveal."
---

## Using the GALTON sound

Choose the track by the job it has to do. A film with a narrator takes the instrumental anthem
or an ambient. A film without one takes the anthem with its spoken words. A
screen that runs for hours takes the loop. Every piece ends in silence or in
the sound logo, never in a fade under someone talking.

Cut the picture on the 2 second bar and the edit locks to the music. The anthem
drops at 0:26: that is where the key moment of a 60 second film belongs.

---

# LAYOUT CATALOG — slide canvas + archetypes (source: layouts.md)

---
# Layout catalog — the finalized GALTON slide system (1080×1350 social canvas).
# This is REFERENCE KNOWLEDGE, not a generator: `canvas` documents the shared
# canvas (size, padding, colours, composition, slide type scale, furniture,
# header/footer anatomy); each `layout` is a SLOT SCHEMA plus MEASURED GEOMETRY
# (absolute px on the 1080×1350 canvas, read out of the design source) with an
# example image. A WIDTH IS RARELY A CONSTRAINT: any box holding a label, a
# supplied logo or copy you are replacing is sized by that content, and the
# number given is what the EXAMPLE measured. Read `sizing` on every box.
# example image. An agent reads it via MCP and rebuilds the slide on-brand in its
# own tool. The framework never renders or generates a slide. A carousel is a
# recipe — an ordered list of layout ids.
updated: "2026-08-31"

# ── Provenance ─────────────────────────────────────────────────────────
source:
  rule: >-
    The design source is the source of truth. Every number below was measured in
    it, not estimated from the example image. If a description here and the
    example image ever disagree, the image is right and this catalog is the bug —
    report it rather than reconciling it yourself.

# ── The shared slide canvas ──────────────────────
canvas:
  ratios: ["1080x1350", "1080x1080"]
  default: "1080x1350"
  padding: 64                       # px, all four sides
  # The content box every element lives inside. Nothing may cross these edges.
  content: { x: 64, y: 64, w: 952, h: 1222 }
  # The three brand colours, by the SAME role names design.md uses. They were
  # `black` / `white` / `yellow` here and `canvas` / `ink` / `primary` there,
  # two vocabularies for three hexes with a "keep in sync" comment as the only
  # link. These are refs now, resolved at load, so there is one name and nothing
  # to keep in sync.
  colors:
    canvas: "{colors.canvas}"
    ink: "{colors.ink}"
    primary: "{colors.primary}"
  # ── Surface contract: how the canvas inverts ──────────────────────
  # `dark` is the default. `light` is the SAME geometry with the roles swapped.
  # Nothing else changes: the yellow is identical, the type scale is identical,
  # every x/y/w/h below is identical.
  surfaces:
    dark:
      background: "{colors.canvas}"
      ink: "{colors.ink}"
      rule: "{colors.ink}"
      accent: "{colors.primary}"
      logo: white
    light:
      background: "{colors.light-canvas}"
      ink: "{colors.on-light}"
      rule: "{colors.on-light}"
      accent: "{colors.primary}"
      logo: black
      note: "The inversion is the `lightSurface` map in design.md, and text follows `colorRules.text` on both surfaces. Nothing else changes: the yellow is identical and every measured number below is identical."
  composition:
    note: >-
      The canvas distributes its blocks vertically-centred with an automatic gap.
      A Top Block hugs the top and is top-left aligned; a Bottom Block hugs the
      bottom and is bottom-left aligned. Each block stacks its own children with a
      fixed 60px gap. Header sits in the Top Block, Footer in the Bottom Block.
      Every layout below also carries measured `geometry`, so you never have to
      derive a position from this description — use the numbers.
    align: vertical-central
    gap: auto
    blocks:
      - { name: top, align: top-left, gap: 60 }
      - { name: bottom, align: bottom-left, gap: 60 }
  # HOW TO READ THE GEOMETRY. Text boxes in the source are trimmed to cap height,
  # so a slot's `y` is the top of the CAPITAL LETTERS of the first line, not the
  # top of the line box, and `h` is that trimmed height.
  metrics:
    unit: "px on the 1080×1350 canvas"
    origin: "top-left of the canvas; every x/y below is absolute, not relative to a parent"
    leading: 1.2
    textBox: "cap-height trimmed (CSS: line-height 1.2 + text-box-trim: trim-both + text-box-edge: cap alphabetic)"
    capHeight: 0.7                  # GALTON cap height as a fraction of the type size, measured across every layout
    boxHeight: "(lines − 1) × size × 1.2 + 0.70 × size, for Latin without diacritics; accents above cap height (á, ľ, š) make it taller"
    baseline: "baseline of line k = y + 0.70 × size + (k − 1) × 1.2 × size"
    fallback: "If your tool cannot cap-trim, position by that baseline formula. Aligning the line BOX to y instead drops the block about 0.25 × size too low."
    # WHAT A NUMBER MEANS. Read `sizing` before you trust a w or an h.
    sizing:
      fixed: "The box is exactly this size. Rules, safe areas and columns are fixed."
      hug: "The box is sized BY ITS CONTENT. The w and h given are the example measurement, not a constraint. Keep the edge named by `anchor` and grow the other way. Never shrink the type to fit the example width, and never let the box cross the content edge."
      wrap: "Text wraps inside this width. The w is a real constraint; the h is the example height for the example copy, and your copy will be taller or shorter."
      default: "A box with no `sizing` is fixed. Anything holding a label whose text you are replacing is hug, and keeping a hug box at its example width is the commonest single mistake made with this catalog."
    # WHICH BOX FILLS WHICH SLOT. Slot names and geometry keys are not always the
    # same word, so the resolution is stated here rather than left to guesswork.
    # Read this before you look for a slot's coordinates.
    slotMapping:
      byName: "A geometry box whose key equals a slot name fills that slot. This is the common case."
      bySlot: "A box with a different key carries `slot: <slotName>`. SEVERAL boxes may name the same slot: a pill and its label, or the four boxes of a two-person row."
      furniture: "A box carrying `furniture` belongs to the frame (rule, logo, url, wordmark) and fills no slot. Its values come from `canvas.furniture`."
      within: "A slot carrying `within: <slotName>` has NO box of its own. It is a treatment applied inside that other slot, for example one line of the headline set in the accent."
      enum: "A slot of type `enum` is a choice, not a box, unless a box of the same name exists (`graphic`, `cta`) in which case the box is where the chosen value is drawn."
    # WHAT `verified` MEANS on a layout. It ships on every one of them and used
    # to be defined nowhere, so `type: false` read as "do not trust this".
      rule: "Every non-enum slot resolves to at least one box, or says `within`. If you cannot find one, it is a bug in this catalog, not a licence to place the element by eye."
    # WHAT `verified` MEANS on a layout. It ships on every one of them and was
    # defined nowhere, so `type: false` read as "do not trust any of this".
    verified:
      geometry: "true means every x/y/w/h was measured off the reference source, not estimated. Trust the numbers."
      type: "true means the type sizes were read off the source as well. FALSE means the boxes are measured but the sizes come from the shared `canvas.type` scale rather than from that layout's own artwork: take the size from the box `role`, and never invent one to fill the box."
      absent: "A layout carrying no `verified` block has been neither measured nor checked. Treat its numbers as a sketch and say so in the brand-choices block."
  # ── Other canvas heights ───────────────────────────────────────────
  # EVERY number in this catalog was measured on 1080x1350, and every box says
  # which edge it is anchored to, so another height needs arithmetic and no
  # judgement. Nothing horizontal ever changes: width is always 1080 and the
  # content box is always x 64 to 1016.
  ratioAdaptation:
    measuredAt: "1080x1350"
    top: "y is unchanged. The box is measured from the TOP edge."
    bottom: "y becomes H − fromBottom, where fromBottom is on the box and H is the canvas height. On 1080x1080 that is 270 less than the measured y."
    center: "The box stays centred on the canvas: y = (H − h) / 2."
    free: "The box stays centred in the space between the top and bottom blocks, which is what the canvas composition does with its automatic gap. Resolve the two blocks first, then centre the box in what is left."
    cover: "The box IS the canvas: x 0, y 0, full width, full height. A full-bleed image or its treatment. It ignores the padding, and on another ratio it becomes 1080 by H."
    note: "Apply the four rules above yourself: they are written out precisely so that a reader without tools can resolve any canvas from the measured one. On MCP you do not have to, because `get_layout { ratio }` returns the geometry already computed. Either way, never scale the numbers proportionally: the padding, the type scale and the 70px chrome bands are constant, only the free height changes."

  # THE SLIDE TYPE SET (px on the 1080 canvas; leading is a % of size). One of
  # three type systems in this brand and the only one a slide uses: the web
  # tokens are `typography` in design.md and `typeScale` there is a leading
  # reference, not a source of sizes. `get_layout` ships `typeRules` beside this
  # block so the distinction arrives with the values rather than dying here in a
  # comment. SLIDE headlines are GALTON Light UPPERCASE; the running subtitle is
  # GALTON Light Sentence case.
  type:
    - { role: display,  font: "GALTON Light",  case: UPPERCASE,     size: 150, leading: 120 }
    - { role: title,    font: "GALTON Light",  case: UPPERCASE,     size: 120, leading: 120 }
    - { role: headline, font: "GALTON Light",  case: UPPERCASE,     size: 100, leading: 120 }
    - { role: section,  font: "GALTON Light",  case: UPPERCASE,     size: 80,  leading: 120 }
    - { role: subtitle, font: "GALTON Light",  case: "Sentence case", size: 60, leading: 120 }
    - { role: lead,     font: "GALTON Light",  case: "Sentence case", size: 50, leading: 120 }
    - { role: body,     font: "GALTON Light",  case: "Sentence case", size: 40, leading: 120 }
    - { role: name,     font: "GALTON Medium", case: UPPERCASE,     size: 36,  leading: 120 }
    - { role: caption,  font: "GALTON Light",  case: UPPERCASE,     size: 36,  leading: 120 }
    - { role: meta,     font: "GALTON Light",  case: "Sentence case", size: 30, leading: 120 }
    - { role: folio,    font: "GALTON Medium", case: UPPERCASE,     size: 24,  leading: 120 }
    - { role: url,      font: "GALTON Medium", case: lowercase,     size: 24,  leading: 120 }
    - { role: numeral,  font: "GALTON Thin",   case: digits,        size: 500, leading: 100, color: "{colors.primary}", specimen: "1 2 3 4", note: "The step figure. It is the ONE place GALTON Thin is used and the ONE piece of type that is always the accent. Three sizes are measured (500 for a full-width figure, 260 for a step row, 150 for a compact row), so a numeral box always carries its own `size`. Its leading is 100, not 120: the glyph is set solid." }
  # A box may carry `size` when its layout sets a size the shared role does not.
  # The role still names the font, the case and the colour; only the size moves.
  typeNote: "A box's `size` overrides the size on its `role`. No box may invent a size that is not written down here or on the box itself."
  # ── Furniture: the parts that are NOT content and are never omitted ──
  # A slide missing its rule, its logo or its URL is off-brand even when every
  # word is right. Resolve these from here; never retype, redraw or recolour them.
  furniture:
    rule:
      thickness: 2                  # px — a solid 2px line, NOT the web {colors.hairline}
      width: 952                    # the full content width
      color: { dark: "{colors.ink}", light: "{colors.on-light}" }
      note: "The web hairline token (white @12%) is for UI. On a slide the rule is solid and 2px."
    symbol:
      w: 37
      h: 36
      file:
        dark:  "https://galton-ai-assets.vercel.app/brand/logos/galton-symbol-white.svg"
        light: "https://galton-ai-assets.vercel.app/brand/logos/galton-symbol-black.svg"
    wordmark:
      w: 277
      h: 70
      note: "The full lockup: wordmark + ® + the BRANDS tagline."
      file:
        dark:  "https://galton-ai-assets.vercel.app/brand/logos/galton-wordmark-white-tagline-tight.png"
        light: "https://galton-ai-assets.vercel.app/brand/logos/galton-wordmark-black-tagline-tight.png"
    url:
      text: "galton.sk"
      role: url
      note: "Lowercase. It is the one piece of slide type that is NOT uppercased."
      # Which domain the slide signs off with follows the LANGUAGE OF THE COPY
      # ON THE SLIDE, not the audience or the channel. This is guidance, not a
      # rule: galton.sk is the primary domain and the default under any doubt.
      byLanguage:
        default: "galton.sk"
        sk: "galton.sk"
        en: "galtonbrands.com"
        note: "The same map as `identity.websiteByLanguage` in brand.md. Slovak copy signs off galton.sk; English copy may sign off galtonbrands.com; mixed or unclear copy uses galton.sk. One domain per slide, and the same domain across every slide of one carousel."
    # ── The pill ───────────────────────────────────────────────────
    # A rounded label used for a tag, a status or a category. It exists in two
    # finishes and nothing else: a filled accent pill and an outlined pill.
    # It HUGS its label in both. The label is never shrunk to fit a pill.
    pill:
      radius: full
      paddingX: 25
      label: { role: folio, case: UPPERCASE }
      width: "label width + 50"
      variants:
        - id: filled
          height: 67
          fill: "{colors.primary}"
          border: none
          labelColor: { dark: "{colors.canvas}", light: "{colors.canvas}" }
          note: "Accent floor, ink label. The label is the canvas colour on BOTH surfaces because it sits on the yellow, not on the slide."
        - id: outline
          height: 71
          fill: none
          border: 2
          borderColor: { dark: "{colors.ink}", light: "{colors.on-light}" }
          labelColor: { dark: "{colors.ink}", light: "{colors.on-light}" }
          note: "2px stroke, no fill. The 4px height difference from the filled pill is measured, not a rounding error."
    # ── Corner marks ───────────────────────────────────────────────
    # The four crop marks that sit on the corners of a bordered panel. They are
    # part of the frame, like the rule: never redraw them and never move them
    # inside the panel edge.
    cornerMarks:
      w: 48
      h: 48
      count: 4
      placement: "one centred on each corner of the panel it marks, half in and half out"
      shape: "A solid 48px square of ink with an 26px square of the background knocked out of its middle, so it reads as a thick 11px bracket. It is NOT an outline and it is NOT a cross."
      color: { dark: "{colors.ink}", light: "{colors.on-light}" }
    # ── A supplied logo in the HEADER ──────────────────────────────
    # The footer already has `partner` for a supplied logo. Some layouts put the
    # supplied logo in the header band instead, in the wordmark's place.
    headerLogo:
      h: 70
      sizing: hug
      note: "The HEIGHT 70 is the constraint; the width follows the supplied logo's own aspect ratio. It replaces the GALTON lockup: the two never appear in the same band."
  # ── Type over an image ─────────────────────────────────────────────
  # Guidance, not a restriction. When type sits over a picture and does not read
  # cleanly, the fix goes on the IMAGE, not on the words.
  imageTreatment:
    when: "Type sits over an image and the contrast is not enough to read it."
    do: "Darken the image itself, or lay a flat overlay of the canvas colour over the whole image panel, until the type reads."
    keep: "Treat the WHOLE panel and keep the treatment even. A backing band or a soft fade sitting only behind the words is not the house solution: it draws a shape the layout does not have."
    type: "The type is left alone, under `colorRules.text`: solid ink at its full size, no reduced opacity. No shadow and no outline either, because the system builds depth from contrast rather than from material effects."

  # Both chrome bands are a fixed 70px tall and carry a 2px rule.
  headers:
    - id: folio
      height: 70
      rule: bottom
      desc: "Two small folio labels — left + right — at the top of the band, with the 2px rule along its bottom edge."
    - id: wordmark
      height: 70
      rule: none
      desc: "The full GALTON lockup at left; an optional event-tag pill at right. No rule."
    - id: wordmark-center
      height: 70
      rule: none
      desc: "The same lockup, centred on the band instead of left-aligned. No rule. Used by the layouts whose whole composition is centred."
    - id: partner-logo
      height: 70
      rule: none
      desc: "A SUPPLIED partner / event logo in the lockup's place, scaled to 70 tall. No rule, and no GALTON lockup: the two never share the band."
    - id: none
      desc: "No header band at all. The top block starts at y 64 with the layout's own first element."
  footers:
    - id: symbol
      height: 70
      rule: top
      desc: "The 2px rule along the top edge, then the G symbol at left and the website URL at right."
    - id: partner
      height: 70
      rule: top
      desc: "Same band, but a supplied partner / award logo replaces the G symbol at left. Used when the slide represents GALTON at someone else's event."
    - id: none
      desc: "No footer band, and therefore no rule, no symbol and no URL. This is a DELIBERATE choice on a handful of layouts whose bottom edge carries a centred pill or a closing line instead, and every one of them says so in its `must`. It is never a licence to drop the footer from a layout that has one."

# ── The finalized base layouts ─────────────────────────────────────────
layouts:
  - id: cover
    name: "Cover / title"
    ratios: ["1080x1350", "1080x1080"]
    surfaces: [dark, light]
    header: folio
    footer: symbol
    verified: { geometry: true, type: true }
    must:
      - "The header rule and the footer rule are both present, 2px, 952 wide."
      - "The G symbol sits bottom-left, the lowercase URL bottom-right."
      - "The headline is UPPERCASE."
      - "At most ONE headline line is yellow."
    slots:
      folioLeft:  { type: text, optional: true, case: upper, note: "left header label, e.g. 'Naming folio'" }
      folioRight: { type: text, optional: true, case: upper, note: "right header label, e.g. 'Selected works'" }
      headline:   { type: lines, required: true, case: upper, note: "Top block — GALTON Light 100, UPPERCASE" }
      accent:     { type: text, optional: true, within: headline, note: "NOT a box of its own: one line INSIDE the headline block, set in the yellow accent, e.g. 'VOL.1'. It takes the headline geometry, the headline size and the headline case; only the colour changes." }
      subtitle:   { type: text, optional: true, note: "Bottom block — GALTON Light 60, Sentence case" }
      surface:    { type: enum, values: [dark, light], default: dark }
    geometry:
      folioLeft:   { x: 64,  y: 64,   w: 400,  h: 17,  align: left,  role: folio, sizing: hug, anchor: left, note: "HUG. Left edge stays at 64.", block: top }
      folioRight:  { x: 616, y: 64,   w: 400,  h: 17,  align: right, role: folio, sizing: hug, anchor: right, note: "HUG. Right edge stays at 1016. The two folio labels must not collide: shorten the copy, never the type.", block: top }
      headerRule:  { x: 64,  y: 132,  w: 952,  h: 2,   furniture: rule, block: top }
      headline:    { x: 64,  y: 194,  w: 952,  h: 430, align: left,  role: headline, maxLines: 4, sizing: wrap, note: "WRAP at 952. h 430 is the example four lines; your copy changes it.", block: top }
      subtitle:    { x: 64,  y: 1042, w: 952,  h: 114, align: left,  role: subtitle, maxLines: 2, sizing: wrap, note: "WRAP at 952. The BOTTOM of the bottom block is fixed: the subtitle sits above the footer, so extra lines grow upwards.", block: bottom, fromBottom: 308.0 }
      footerRule:  { x: 64,  y: 1214, w: 952,  h: 2,   furniture: rule, block: bottom, fromBottom: 136.0 }
      footerLogo:  { x: 64,  y: 1250, w: 37,   h: 36,  furniture: symbol, sizing: hug, anchor: left, note: "HUG. The height 36 is the constraint; the width follows the symbol aspect.", block: bottom, fromBottom: 100.0 }
      footerUrl:   { x: 799, y: 1259, w: 217,  h: 17,  align: right, role: url, furniture: url, sizing: hug, anchor: right, note: "HUG. The right edge stays at 1016.", block: bottom, fromBottom: 91.0 }
    exampleImage: "https://galton-ai-assets.vercel.app/brand/layouts/cover.png"
    referenceSource: "https://galton-ai-assets.vercel.app/brand/layouts/cover.svg"

  - id: profile
    name: "Profile / speaker card"
    ratios: ["1080x1350"]
    surfaces: [dark]
    header: wordmark
    footer: partner
    verified: { geometry: true, type: false }
    must:
      - "The full GALTON lockup sits top-left; it is an image file, never retyped as text."
      - "The footer rule is present, 2px, 952 wide."
      - "The footer logo is the SUPPLIED partner / award logo, not the G symbol."
      - "Name is GALTON Medium 36 UPPERCASE; role is GALTON Light 36 UPPERCASE."
      - "The photo is centred inside photoSafeArea and never crosses the header band, the footer rule or the padding. Any aspect ratio is fine; cropping the image to fill the area is not."
      - "The tag pill HUGS its label. Keep its right edge at 1016 and grow it leftwards; never keep the example width and never shrink the 24px label to fit."
    slots:
      tag:         { type: text, optional: true, case: upper, note: "event-tag pill at top-right, e.g. 'EVENT'. Two boxes: `tagPill` is the outline, `tagLabel` is the text inside it." }
      photo:       { type: image, required: true, note: "One box: `photoSafeArea`. Any aspect ratio, portrait or landscape. Masked into a rounded panel, scaled to FIT inside photoSafeArea and centred in it. It must never cross the header band, the footer rule or the 64px padding. The people row sits over it: if the names do not read, darken the image (see canvas.imageTreatment), not the names." }
      people:      { type: stages, required: true, note: "Four boxes: person1Name/person1Role are column 1, person2Name/person2Role are column 2 (omit both when there is one person). 1–2 people as 'Name|Role' — Name is GALTON Medium 36 UPPERCASE, Role is GALTON Light 36 UPPERCASE" }
      partnerLogo: { type: image, required: true, note: "the event / award logo shown in the footer, supplied with the brief — the brand does not ship it" }
      surface:     { type: enum, values: [dark], default: dark }
    geometry:
      wordmark:    { x: 64,   y: 64,   w: 277, h: 70,  furniture: wordmark, sizing: hug, anchor: left, note: "HUG. The HEIGHT 70 is the constraint; the width follows the lockup own aspect ratio. The left edge stays at 64.", block: top }
      tagPill:     { x: 877,  y: 76,   w: 139, h: 47,  slot: tag, radius: full, border: 2, sizing: hug, anchor: right, paddingX: 30, note: "HUG. w 139 is the example, measured around the label EVENT. Width = label width + 60. The RIGHT edge stays at 1016 and the pill grows leftwards, so a longer tag like REAL ESTATE starts further left. Height stays 47 and the label stays 24px: never shrink the type to fit.", block: top }
      tagLabel:    { x: 907,  y: 91,   w: 79,  h: 17,  slot: tag, align: center, role: folio, sizing: hug, anchor: center, note: "HUG. Centred in the pill with 30px clear on each side.", block: top }
      photoSafeArea: { x: 64, y: 180,  w: 952, h: 990, slot: photo, radius: 16, fit: contain, align: center, sizing: fixed, note: "The AREA is fixed, the picture inside it is not. Scale the image to fit inside it, keep its own aspect ratio, centre it on both axes. The example portrait lands at 635 x 990; a landscape crop lands at 952 wide and shorter. The people row sits ON TOP of the image by design.", block: inset, insetTop: 180.0, insetBottom: 180.0 }
      person1Name: { x: 64,   y: 642,  w: 393, h: 25,  slot: people, align: left,  role: name,    sizing: hug, anchor: left, note: "HUG. Column 1 starts at x 64; the w is the example name.", block: center, offsetFromCenter: -33.0 }
      person1Role: { x: 64,   y: 683,  w: 393, h: 25,  slot: people, align: left,  role: caption, sizing: hug, anchor: left, block: center, offsetFromCenter: 8.0 }
      person2Name: { x: 640,  y: 642,  w: 376, h: 25,  slot: people, align: left,  role: name,    sizing: hug, anchor: left, note: "HUG. Column 2 starts at x 640. Omit both column-2 boxes when there is one person.", block: center, offsetFromCenter: -33.0 }
      person2Role: { x: 640,  y: 683,  w: 376, h: 25,  slot: people, align: left,  role: caption, sizing: hug, anchor: left, block: center, offsetFromCenter: 8.0 }
      footerRule:  { x: 64,   y: 1214, w: 952, h: 2,   furniture: rule, block: bottom, fromBottom: 136.0 }
      footerLogo:  { x: 64,   y: 1244, w: 274, h: 42,  slot: partnerLogo, sizing: hug, anchor: left, note: "HUG. The HEIGHT is the constraint: scale the supplied logo to 42px tall and let its width follow its own aspect ratio. The w 274 is the example logo.", block: bottom, fromBottom: 106.0 }
      footerUrl:   { x: 799,  y: 1256, w: 217, h: 17,  align: right, role: url, furniture: url, sizing: hug, anchor: right, note: "HUG. The right edge stays at 1016.", block: bottom, fromBottom: 94.0 }
    exampleImage: "https://galton-ai-assets.vercel.app/brand/layouts/profile.png"
    referenceSource: "https://galton-ai-assets.vercel.app/brand/layouts/profile.svg"

  - id: concept
    name: "Concept + supporting graphic"
    ratios: ["1080x1350", "1080x1080"]
    surfaces: [dark, light]
    footer: symbol
    verified: { geometry: true, type: true }
    must:
      - "There is NO header on this layout."
      - "The footer rule is present, 2px, 952 wide, with the G symbol and the lowercase URL."
      - "BOTH text blocks are GALTON Light 100 UPPERCASE. The lower one is a second headline, not a 60px subtitle."
    slots:
      headline:    { type: lines, required: true, case: upper, note: "Top block — GALTON Light 100, UPPERCASE" }
      subheadline: { type: lines, optional: true, case: upper, note: "Bottom-left — ALSO GALTON Light 100 UPPERCASE, max 2 lines" }
      graphic:     { type: iconRef, optional: true, note: "supporting icon or geometric cluster, bottom-right" }
      surface:     { type: enum, values: [dark, light], default: dark }
    geometry:
      headline:    { x: 64,  y: 64,   w: 952, h: 310, align: left, role: headline, maxLines: 3, sizing: wrap, note: "WRAP at 952. h 310 is the example three lines.", block: top }
      subheadline: { x: 64,  y: 966,  w: 463, h: 190, align: left, role: headline, maxLines: 2, sizing: wrap, note: "WRAP at 463: the left column beside the graphic. Do not widen it into the graphic.", block: bottom, fromBottom: 384.0 }
      graphic:     { x: 527, y: 665,  w: 489, h: 491, align: right, sizing: fixed, fit: contain, note: "Fixed column, bottom-aligned with the subheadline. Fit the graphic inside it; do not crop it to fill.", block: bottom, fromBottom: 685.0 }
      footerRule:  { x: 64,  y: 1214, w: 952, h: 2,   furniture: rule, block: bottom, fromBottom: 136.0 }
      footerLogo:  { x: 64,  y: 1250, w: 37,  h: 36,  furniture: symbol, sizing: hug, anchor: left, note: "HUG. The height 36 is the constraint; the width follows the symbol aspect.", block: bottom, fromBottom: 100.0 }
      footerUrl:   { x: 799, y: 1259, w: 217, h: 17,  align: right, role: url, furniture: url, sizing: hug, anchor: right, note: "HUG. The right edge stays at 1016.", block: bottom, fromBottom: 91.0 }
    exampleImage: "https://galton-ai-assets.vercel.app/brand/layouts/concept.png"
    referenceSource: "https://galton-ai-assets.vercel.app/brand/layouts/concept.svg"

  - id: statement
    name: "Statement + centred graphic + CTA"
    ratios: ["1080x1350", "1080x1080"]
    surfaces: [dark, light]
    verified: { geometry: true, type: false }
    must:
      - "There is NO header and NO footer on this layout, and therefore NO rule, NO logo and NO URL."
      - "The Venn graphic is three equal circles, 2px stroke, with ONLY the three-way intersection filled yellow."
      - "The CTA arrow is yellow and sits on the same baseline band as the subtitle, at the right edge."
    slots:
      headline: { type: lines, required: true, case: upper, note: "Top block — GALTON Light 100, UPPERCASE" }
      graphic:  { type: enum, values: [venn, icon, none], default: venn, note: "centred geometric graphic — the 3-circle Venn with a yellow intersection" }
      subtitle: { type: text, optional: true, note: "Bottom block — GALTON Light 60, Sentence case" }
      cta:      { type: enum, values: [arrow, none], default: arrow, note: "yellow arrow at bottom-right" }
      surface:  { type: enum, values: [dark, light], default: dark }
    geometry:
      headline: { x: 64,    y: 64,    w: 952,   h: 190,   align: left, role: headline, maxLines: 2, sizing: wrap, note: "WRAP at 952. h 190 is the example two lines.", block: top }
      graphic:  { x: 240.5, y: 420.7, w: 599,   h: 570.8, align: center, sizing: fixed, block: free }
      subtitle: { x: 64,    y: 1158,  w: 736,   h: 128,   align: left, role: subtitle, maxLines: 2, sizing: wrap, note: "WRAP at 736: it must clear the CTA arrow on its right.", block: bottom, fromBottom: 192.0 }
      cta:      { x: 910,   y: 1158,  w: 110,   h: 128,   align: right, color: "{colors.primary}", sizing: hug, anchor: right, fit: contain, note: "Yellow on the dark surface, ink on the light one, per the reference art. Hotlink the arrow from the arrows icon set rather than drawing it.", block: bottom, fromBottom: 192.0 }
    graphicSpec:
      venn:
        circles:
          - { cx: 540.1, cy: 601.6, d: 361.9 }
          - { cx: 421.4, cy: 811.0, d: 361.9 }
          - { cx: 658.6, cy: 809.8, d: 361.9 }
        stroke: { width: 2, color: { dark: "{colors.ink}", light: "{colors.on-light}" } }
        fill: { area: "the three-way intersection only", color: "{colors.primary}" }
    exampleImage: "https://galton-ai-assets.vercel.app/brand/layouts/statement.png"
    referenceSource: "https://galton-ai-assets.vercel.app/brand/layouts/statement.svg"

  # The same frame on the inverted canvas. `inheritsFrom` copies the geometry,
  # the graphic spec and the slots at load time, so there is ONE set of measured
  # numbers and the two can never drift apart.
  - id: statement-light
    name: "Statement, light surface"
    inheritsFrom: statement
    ratios: ["1080x1350", "1080x1080"]
    surfaces: [light]
    verified: { geometry: true, type: false }
    must:
      - "White floor, near-black ink. The yellow intersection is UNCHANGED: the accent never inverts."
      - "There is NO header and NO footer, and therefore NO rule, NO logo and NO URL."
      - "The Venn stroke is near-black, and so is the CTA arrow, unlike the dark frame where the arrow is yellow."
    slots: {}
    exampleImage: "https://galton-ai-assets.vercel.app/brand/layouts/statement-light.png"
    referenceSource: "https://galton-ai-assets.vercel.app/brand/layouts/statement-light.svg"

  # ── The editorial layouts ──────────────────────────────────────────────
  # Measured off the "Autolayouts 2" board in the design source. They share the
  # canvas, the padding, the 70px chrome bands and the furniture with the five
  # base layouts above; what they add is a longer set of text roles (150 down to
  # 30), the numeral, the pill, and the two-column and stepped compositions a
  # carousel needs in its middle. Every one of them is on the dark surface in the
  # source; a layout carrying `surfaces: [dark, light]` inverts by the surface
  # contract and nothing else changes.

  - id: cover-image
    name: "Cover, full-bleed image"
    ratios: ["1080x1350", "1080x1080"]
    surfaces: [dark]
    header: none
    footer: symbol
    verified: { geometry: true, type: true }
    must:
      - "The image is FULL BLEED: it fills the whole 1080x1350 canvas and runs under the padding, the headline and the footer."
      - "There is NO header on this layout. The headline starts at y 64."
      - "The footer rule is present, 2px, 952 wide, with the G symbol and the lowercase URL."
      - "If the headline does not read over the picture, treat the WHOLE image per canvas.imageTreatment. Never put a band or a fade behind the words."
    slots:
      image:    { type: image, required: true, note: "The full-bleed background. One box: `image`. It is cropped to FILL the canvas, unlike the profile photo which is fitted." }
      headline: { type: lines, required: true, case: upper, note: "Top block, GALTON Light 100 UPPERCASE" }
      accent:   { type: text, optional: true, within: headline, note: "NOT a box of its own: one line INSIDE the headline set in the accent. It takes the headline geometry, size and case; only the colour changes." }
      surface:  { type: enum, values: [dark], default: dark }
    geometry:
      image:      { x: 0,   y: 0,    w: 1080, h: 1350, slot: image, fit: cover, sizing: fixed, note: "Full bleed. Crop to fill; do not letterbox it inside the content box.", block: cover }
      headline:   { x: 64,  y: 64,   w: 952,  h: 310,  align: left, role: headline, maxLines: 4, sizing: wrap, note: "WRAP at 952. h 310 is the example three lines.", block: top }
      footerRule: { x: 64,  y: 1214, w: 952,  h: 2,    furniture: rule, block: bottom, fromBottom: 136.0 }
      footerLogo: { x: 64,  y: 1250, w: 37,   h: 36,   furniture: symbol, sizing: hug, anchor: left, block: bottom, fromBottom: 100.0 }
      footerUrl:  { x: 799, y: 1259, w: 217,  h: 17,   align: right, role: url, furniture: url, sizing: hug, anchor: right, block: bottom, fromBottom: 91.0 }
    exampleImage: "https://galton-ai-assets.vercel.app/brand/layouts/cover-image.png"
    referenceSource: "https://galton-ai-assets.vercel.app/brand/layouts/cover-image.svg"

  - id: cover-image-half
    name: "Cover, image on the lower half"
    ratios: ["1080x1350"]
    surfaces: [dark]
    header: none
    footer: symbol
    verified: { geometry: true, type: true }
    must:
      - "The image occupies the LOWER HALF of the canvas, full width, and bleeds off the left, right and bottom edges."
      - "The image's top edge is a hard horizontal cut at y 675. It is not faded, feathered or rounded."
      - "There is NO header. The footer rule, the G symbol and the lowercase URL sit ON TOP of the image."
    slots:
      image:    { type: image, required: true, note: "One box: `image`. Cropped to FILL the 1080x675 band." }
      headline: { type: lines, required: true, case: upper, note: "Top block, GALTON Light 100 UPPERCASE" }
      surface:  { type: enum, values: [dark], default: dark }
    geometry:
      image:      { x: 0,   y: 675,  w: 1080, h: 675, slot: image, fit: cover, sizing: fixed, note: "Full-width band on the lower half. Crop to fill.", block: bottom, fromBottom: 675.0 }
      headline:   { x: 64,  y: 64,   w: 952,  h: 310, align: left, role: headline, maxLines: 3, sizing: wrap, note: "WRAP at 952. The headline must clear the image cut at y 675.", block: top }
      footerRule: { x: 64,  y: 1214, w: 952,  h: 2,   furniture: rule, block: bottom, fromBottom: 136.0 }
      footerLogo: { x: 64,  y: 1250, w: 37,   h: 36,  furniture: symbol, sizing: hug, anchor: left, block: bottom, fromBottom: 100.0 }
      footerUrl:  { x: 799, y: 1259, w: 217,  h: 17,  align: right, role: url, furniture: url, sizing: hug, anchor: right, block: bottom, fromBottom: 91.0 }
    exampleImage: "https://galton-ai-assets.vercel.app/brand/layouts/cover-image-half.png"
    referenceSource: "https://galton-ai-assets.vercel.app/brand/layouts/cover-image-half.svg"

  - id: statement-cta
    name: "Long statement with a swipe arrow"
    ratios: ["1080x1350", "1080x1080"]
    surfaces: [dark, light]
    header: folio
    footer: symbol
    verified: { geometry: true, type: true }
    must:
      - "The headline is GALTON Light 80 UPPERCASE, not 100. This layout carries more words than `cover` and the smaller size is what makes them fit."
      - "The header rule and the footer rule are both present, 2px, 952 wide."
      - "The arrow is the `arrow-right` icon from the arrows set, hotlinked, never redrawn. It is the accent on the dark surface and the ink on the light one."
      - "The subtitle wraps at 847 so it clears the arrow. Do not run it under the arrow."
    slots:
      folioLeft:  { type: text, optional: true, case: upper, note: "left header label" }
      folioRight: { type: text, optional: true, case: upper, note: "right header label" }
      headline:   { type: lines, required: true, case: upper, note: "Top block, GALTON Light 80 UPPERCASE, up to 6 lines" }
      subtitle:   { type: text, optional: true, note: "Bottom block, GALTON Light 60, Sentence case" }
      cta:        { type: iconRef, optional: true, default: arrow-right, note: "the swipe arrow at bottom-right" }
      surface:    { type: enum, values: [dark, light], default: dark }
    geometry:
      folioLeft:  { x: 64,  y: 64,   w: 187, h: 17,  align: left,  role: folio, sizing: hug, anchor: left, block: top }
      folioRight: { x: 800, y: 64,   w: 216, h: 17,  align: right, role: folio, sizing: hug, anchor: right, block: top }
      headerRule: { x: 64,  y: 132,  w: 952, h: 2,   furniture: rule, block: top }
      headline:   { x: 64,  y: 194,  w: 952, h: 536, align: left, role: headline, size: 80, maxLines: 6, sizing: wrap, note: "WRAP at 952 at SIZE 80. h 536 is the example six lines.", block: top }
      subtitle:   { x: 64,  y: 1042, w: 847, h: 114, align: left, role: subtitle, maxLines: 2, sizing: wrap, note: "WRAP at 847, not 952: the arrow owns the right end of this band.", block: bottom, fromBottom: 308.0 }
      cta:        { x: 911, y: 1042, w: 105, h: 114, slot: cta, align: right, fit: contain, sizing: hug, anchor: right, color: { dark: "{colors.primary}", light: "{colors.on-light}" }, block: bottom, fromBottom: 308.0 }
      footerRule: { x: 64,  y: 1214, w: 952, h: 2,   furniture: rule, block: bottom, fromBottom: 136.0 }
      footerLogo: { x: 64,  y: 1250, w: 37,  h: 36,  furniture: symbol, sizing: hug, anchor: left, block: bottom, fromBottom: 100.0 }
      footerUrl:  { x: 799, y: 1259, w: 217, h: 17,  align: right, role: url, furniture: url, sizing: hug, anchor: right, block: bottom, fromBottom: 91.0 }
    exampleImage: "https://galton-ai-assets.vercel.app/brand/layouts/statement-cta.png"
    referenceSource: "https://galton-ai-assets.vercel.app/brand/layouts/statement-cta.svg"

  - id: step-numeral
    name: "Carousel step with a full-width numeral"
    ratios: ["1080x1350"]
    surfaces: [dark, light]
    header: folio
    footer: symbol
    verified: { geometry: true, type: true }
    must:
      - "The numeral is GALTON Thin 500 in the accent, right-aligned to 1016. It is the only Thin weight on any slide and it is never white."
      - "The heading is GALTON Light 80 UPPERCASE; the running copy under it is GALTON Light 40 Sentence case at 600 wide, NOT the 60px subtitle."
      - "The header rule and the footer rule are both present, 2px, 952 wide."
      - "One numeral per slide. The step number is the whole graphic; do not add an icon beside it."
    slots:
      folioLeft:  { type: text, optional: true, case: upper }
      folioRight: { type: text, optional: true, case: upper }
      heading:    { type: lines, required: true, case: upper, note: "GALTON Light 80 UPPERCASE, 1 to 2 lines" }
      body:       { type: text, required: true, note: "GALTON Light 40 Sentence case, wraps at 600" }
      step:       { type: text, required: true, note: "the step number, 1 to 9. GALTON Thin 500 in the accent." }
      surface:    { type: enum, values: [dark, light], default: dark }
    geometry:
      folioLeft:  { x: 64,  y: 64,   w: 187, h: 17,  align: left,  role: folio, sizing: hug, anchor: left, block: top }
      folioRight: { x: 800, y: 64,   w: 216, h: 17,  align: right, role: folio, sizing: hug, anchor: right, block: top }
      headerRule: { x: 64,  y: 132,  w: 952, h: 2,   furniture: rule, block: top }
      heading:    { x: 64,  y: 194,  w: 952, h: 152, slot: heading, align: left, role: headline, size: 80, maxLines: 2, sizing: wrap, note: "WRAP at 952 at SIZE 80. h 152 is the example two lines.", block: top }
      body:       { x: 64,  y: 406,  w: 600, h: 412, slot: body, align: left, role: body, maxLines: 10, sizing: wrap, note: "WRAP at 600, a narrow measure by design. h 412 is the example nine lines.", block: top }
      step:       { x: 64,  y: 806,  w: 952, h: 350, slot: step, align: right, role: numeral, size: 500, sizing: fixed, color: "{colors.primary}", note: "Right-aligned to 1016. The 350 height is the measured cap height of a 500px Thin figure set solid.", block: bottom, fromBottom: 544.0 }
      footerRule: { x: 64,  y: 1214, w: 952, h: 2,   furniture: rule, block: bottom, fromBottom: 136.0 }
      footerLogo: { x: 64,  y: 1250, w: 37,  h: 36,  furniture: symbol, sizing: hug, anchor: left, block: bottom, fromBottom: 100.0 }
      footerUrl:  { x: 799, y: 1259, w: 217, h: 17,  align: right, role: url, furniture: url, sizing: hug, anchor: right, block: bottom, fromBottom: 91.0 }
    exampleImage: "https://galton-ai-assets.vercel.app/brand/layouts/step-numeral.png"
    referenceSource: "https://galton-ai-assets.vercel.app/brand/layouts/step-numeral.svg"

  - id: title-image
    name: "Headline over a full-bleed image"
    ratios: ["1080x1350", "1080x1080"]
    surfaces: [dark]
    header: folio
    footer: symbol
    verified: { geometry: true, type: true }
    must:
      - "The image is FULL BLEED and runs under the header rule, the headline and the footer."
      - "This is the `cover-image` frame WITH the folio header. Both rules are present, 2px, 952 wide."
      - "The headline is GALTON Light 80 UPPERCASE, sized down from 100 to leave the picture room."
      - "If the type does not read, treat the WHOLE image per canvas.imageTreatment."
    slots:
      image:      { type: image, required: true, note: "One box: `image`. Cropped to FILL the canvas." }
      folioLeft:  { type: text, optional: true, case: upper }
      folioRight: { type: text, optional: true, case: upper }
      headline:   { type: lines, required: true, case: upper, note: "GALTON Light 80 UPPERCASE, up to 4 lines" }
      surface:    { type: enum, values: [dark], default: dark }
    geometry:
      image:      { x: 0,   y: 0,    w: 1080, h: 1350, slot: image, fit: cover, sizing: fixed, block: cover }
      folioLeft:  { x: 64,  y: 64,   w: 187,  h: 17,  align: left,  role: folio, sizing: hug, anchor: left, block: top }
      folioRight: { x: 800, y: 64,   w: 216,  h: 17,  align: right, role: folio, sizing: hug, anchor: right, block: top }
      headerRule: { x: 64,  y: 132,  w: 952,  h: 2,   furniture: rule, block: top }
      headline:   { x: 64,  y: 194,  w: 952,  h: 344, align: left, role: headline, size: 80, maxLines: 4, sizing: wrap, note: "WRAP at 952 at SIZE 80. h 344 is the example four lines.", block: top }
      footerRule: { x: 64,  y: 1214, w: 952,  h: 2,   furniture: rule, block: bottom, fromBottom: 136.0 }
      footerLogo: { x: 64,  y: 1250, w: 37,   h: 36,  furniture: symbol, sizing: hug, anchor: left, block: bottom, fromBottom: 100.0 }
      footerUrl:  { x: 799, y: 1259, w: 217,  h: 17,  align: right, role: url, furniture: url, sizing: hug, anchor: right, block: bottom, fromBottom: 91.0 }
    exampleImage: "https://galton-ai-assets.vercel.app/brand/layouts/title-image.png"
    referenceSource: "https://galton-ai-assets.vercel.app/brand/layouts/title-image.svg"

  - id: rule-list
    name: "Ruled list of terms"
    ratios: ["1080x1350"]
    surfaces: [dark, light]
    header: folio
    footer: symbol
    verified: { geometry: true, type: true }
    must:
      - "Every item is GALTON Light 80 UPPERCASE on ONE line. An item that wraps is too long: shorten the word, never the type."
      - "A 2px rule sits BETWEEN items and never above the first or below the last. Six items therefore carry five rules."
      - "The pitch is fixed at 176: item cap height 56, then the rule 114 below the item's top, then the next item 176 below."
      - "The header rule and the footer rule are both present, 2px, 952 wide."
    slots:
      folioLeft:  { type: text, optional: true, case: upper }
      folioRight: { type: text, optional: true, case: upper }
      items:      { type: lines, required: true, case: upper, note: "3 to 6 one-line terms. Six boxes are measured: item1 through item6, each with the divider `itemRule` that follows it." }
      surface:    { type: enum, values: [dark, light], default: dark }
    geometry:
      folioLeft:  { x: 64,  y: 64,   w: 187, h: 17, align: left,  role: folio, sizing: hug, anchor: left, block: top }
      folioRight: { x: 800, y: 64,   w: 216, h: 17, align: right, role: folio, sizing: hug, anchor: right, block: top }
      headerRule: { x: 64,  y: 132,  w: 952, h: 2,  furniture: rule, block: top }
      item1:      { x: 64,  y: 194,  w: 952, h: 56, slot: items, align: left, role: headline, size: 80, maxLines: 1, sizing: hug, anchor: left, block: top }
      itemRule1:  { x: 64,  y: 308,  w: 952, h: 2,  slot: items, furniture: rule, block: top }
      item2:      { x: 64,  y: 370,  w: 952, h: 56, slot: items, align: left, role: headline, size: 80, maxLines: 1, sizing: hug, anchor: left, block: top }
      itemRule2:  { x: 64,  y: 484,  w: 952, h: 2,  slot: items, furniture: rule, block: top }
      item3:      { x: 64,  y: 546,  w: 952, h: 56, slot: items, align: left, role: headline, size: 80, maxLines: 1, sizing: hug, anchor: left, block: top }
      itemRule3:  { x: 64,  y: 660,  w: 952, h: 2,  slot: items, furniture: rule, block: top }
      item4:      { x: 64,  y: 722,  w: 952, h: 56, slot: items, align: left, role: headline, size: 80, maxLines: 1, sizing: hug, anchor: left, block: top }
      itemRule4:  { x: 64,  y: 836,  w: 952, h: 2,  slot: items, furniture: rule, block: top }
      item5:      { x: 64,  y: 898,  w: 952, h: 56, slot: items, align: left, role: headline, size: 80, maxLines: 1, sizing: hug, anchor: left, block: top }
      itemRule5:  { x: 64,  y: 1012, w: 952, h: 2,  slot: items, furniture: rule, block: top }
      item6:      { x: 64,  y: 1074, w: 952, h: 56, slot: items, align: left, role: headline, size: 80, maxLines: 1, sizing: hug, anchor: left, block: top }
      footerRule: { x: 64,  y: 1214, w: 952, h: 2,  furniture: rule, block: bottom, fromBottom: 136.0 }
      footerLogo: { x: 64,  y: 1250, w: 37,  h: 36, furniture: symbol, sizing: hug, anchor: left, block: bottom, fromBottom: 100.0 }
      footerUrl:  { x: 799, y: 1259, w: 217, h: 17, align: right, role: url, furniture: url, sizing: hug, anchor: right, block: bottom, fromBottom: 91.0 }
    exampleImage: "https://galton-ai-assets.vercel.app/brand/layouts/rule-list.png"
    referenceSource: "https://galton-ai-assets.vercel.app/brand/layouts/rule-list.svg"

  - id: person-round
    name: "Person card, round portrait"
    ratios: ["1080x1350"]
    surfaces: [dark]
    header: none
    footer: symbol
    verified: { geometry: true, type: true }
    must:
      - "The portrait is a 450px CIRCLE at top-right, cropped to fill. It is the only circular mask in the system."
      - "The arrow above the name is `arrow-up-right` from the arrows set, 254px, in the accent. Hotlink it; never redraw it."
      - "The name is GALTON Light 120 UPPERCASE. The handle under it is GALTON Light 40 Sentence case and keeps its own capitalisation."
      - "There is NO header. The footer rule, the G symbol and the lowercase URL are present."
    slots:
      photo:   { type: image, required: true, note: "One box: `photo`. Square crop, masked to a full-radius circle, cropped to FILL." }
      graphic: { type: iconRef, optional: true, default: arrow-up-right, note: "the accent arrow above the name" }
      name:    { type: lines, required: true, case: upper, note: "GALTON Light 120 UPPERCASE, 1 to 2 lines" }
      handle:  { type: text, optional: true, note: "GALTON Light 40, printed exactly as supplied" }
      surface: { type: enum, values: [dark], default: dark }
    geometry:
      photo:      { x: 566, y: 64,   w: 450, h: 450, slot: photo, radius: full, fit: cover, sizing: fixed, note: "Right edge at 1016. Crop the picture to fill the circle; do not fit it inside and leave a gap.", block: top }
      graphic:    { x: 64,  y: 526,  w: 254, h: 254, slot: graphic, fit: contain, sizing: fixed, color: "{colors.primary}", block: bottom, fromBottom: 824.0 }
      name:       { x: 64,  y: 840,  w: 952, h: 228, align: left, role: title, maxLines: 2, sizing: wrap, note: "WRAP at 952. h 228 is the example two lines at 120.", block: bottom, fromBottom: 510.0 }
      handle:     { x: 64,  y: 1128, w: 600, h: 28,  align: left, role: body, maxLines: 1, sizing: hug, anchor: left, block: bottom, fromBottom: 222.0 }
      footerRule: { x: 64,  y: 1214, w: 952, h: 2,   furniture: rule, block: bottom, fromBottom: 136.0 }
      footerLogo: { x: 64,  y: 1250, w: 37,  h: 36,  furniture: symbol, sizing: hug, anchor: left, block: bottom, fromBottom: 100.0 }
      footerUrl:  { x: 799, y: 1259, w: 217, h: 17,  align: right, role: url, furniture: url, sizing: hug, anchor: right, block: bottom, fromBottom: 91.0 }
    exampleImage: "https://galton-ai-assets.vercel.app/brand/layouts/person-round.png"
    referenceSource: "https://galton-ai-assets.vercel.app/brand/layouts/person-round.svg"

  - id: person-image
    name: "Person card, full-bleed portrait"
    inheritsFrom: person-round
    ratios: ["1080x1350"]
    surfaces: [dark]
    header: none
    footer: symbol
    verified: { geometry: true, type: true }
    must:
      - "The portrait is FULL BLEED across the whole 1080x1350 canvas, not a circle. The `photo` box becomes 0,0,1080,1350."
      - "Everything else is `person-round` unchanged: the same arrow, the same 120 name, the same 40 handle, the same footer."
      - "The name sits over the picture. If it does not read, darken the WHOLE image per canvas.imageTreatment."
    slots: {}
    geometry:
      photo: { x: 0, y: 0, w: 1080, h: 1350, slot: photo, fit: cover, sizing: fixed, note: "Overrides the inherited circle. Full bleed, cropped to fill.", block: cover }
    exampleImage: "https://galton-ai-assets.vercel.app/brand/layouts/person-image.png"
    referenceSource: "https://galton-ai-assets.vercel.app/brand/layouts/person-image.svg"

  - id: graphic-statement
    name: "Centred graphic over a closing line"
    ratios: ["1080x1350"]
    surfaces: [dark, light]
    header: none
    footer: symbol
    verified: { geometry: true, type: true }
    must:
      - "The graphic is a 735px square centred on the canvas width, top-aligned at y 64. Fit the artwork inside it; do not crop it to fill."
      - "The line under it is GALTON Light 120 UPPERCASE, up to 2 lines."
      - "There is NO header. The footer rule, the G symbol and the lowercase URL are present."
    slots:
      graphic:  { type: image, required: true, note: "One box: `graphic`. A 3D object or an icon from the sets, fitted inside the square." }
      headline: { type: lines, required: true, case: upper, note: "GALTON Light 120 UPPERCASE, 1 to 2 lines" }
      surface:  { type: enum, values: [dark, light], default: dark }
    geometry:
      graphic:    { x: 172.5, y: 64,   w: 735, h: 735, slot: graphic, align: center, fit: contain, sizing: fixed, note: "Centred on the canvas, not on the content box: 172.5 left and right. It is wider than the content box is tall in the square ratio, so check it before reusing this layout at 1080x1080.", block: top }
      headline:   { x: 64,    y: 928,  w: 952, h: 228, align: left, role: title, maxLines: 2, sizing: wrap, note: "WRAP at 952. h 228 is the example two lines at 120.", block: bottom, fromBottom: 422.0 }
      footerRule: { x: 64,    y: 1214, w: 952, h: 2,   furniture: rule, block: bottom, fromBottom: 136.0 }
      footerLogo: { x: 64,    y: 1250, w: 37,  h: 36,  furniture: symbol, sizing: hug, anchor: left, block: bottom, fromBottom: 100.0 }
      footerUrl:  { x: 799,   y: 1259, w: 217, h: 17,  align: right, role: url, furniture: url, sizing: hug, anchor: right, block: bottom, fromBottom: 91.0 }
    exampleImage: "https://galton-ai-assets.vercel.app/brand/layouts/graphic-statement.png"
    referenceSource: "https://galton-ai-assets.vercel.app/brand/layouts/graphic-statement.svg"

  - id: body-cta
    name: "Running copy with a swipe arrow"
    ratios: ["1080x1350"]
    surfaces: [dark, light]
    header: folio
    footer: symbol
    verified: { geometry: true, type: true }
    must:
      - "The copy is GALTON Light 60 Sentence case across the full 952 measure. It is the only element in the top block: there is no headline above it."
      - "Individual PHRASES may be set in the accent. They stay the same size, the same weight and the same case; only the colour changes, and the colour is solid."
      - "The arrow is `arrow-right` from the arrows set, bottom-right, hotlinked."
      - "The header rule and the footer rule are both present, 2px, 952 wide."
    slots:
      folioLeft:  { type: text, optional: true, case: upper }
      folioRight: { type: text, optional: true, case: upper }
      body:       { type: text, required: true, note: "GALTON Light 60 Sentence case, wraps at 952, up to 6 lines" }
      accent:     { type: text, optional: true, within: body, note: "NOT a box of its own: the phrases INSIDE the copy that are set in the accent. Same size, same weight, solid colour." }
      cta:        { type: iconRef, optional: true, default: arrow-right, note: "the swipe arrow at bottom-right" }
      surface:    { type: enum, values: [dark, light], default: dark }
    geometry:
      folioLeft:  { x: 64,  y: 64,   w: 187, h: 17,  align: left,  role: folio, sizing: hug, anchor: left, block: top }
      folioRight: { x: 800, y: 64,   w: 216, h: 17,  align: right, role: folio, sizing: hug, anchor: right, block: top }
      headerRule: { x: 64,  y: 132,  w: 952, h: 2,   furniture: rule, block: top }
      body:       { x: 64,  y: 194,  w: 952, h: 402, slot: body, align: left, role: subtitle, maxLines: 8, sizing: wrap, note: "WRAP at 952. h 402 is the example six lines at 60.", block: top }
      cta:        { x: 911, y: 1042, w: 105, h: 114, slot: cta, align: right, fit: contain, sizing: hug, anchor: right, color: { dark: "{colors.primary}", light: "{colors.on-light}" }, block: bottom, fromBottom: 308.0 }
      footerRule: { x: 64,  y: 1214, w: 952, h: 2,   furniture: rule, block: bottom, fromBottom: 136.0 }
      footerLogo: { x: 64,  y: 1250, w: 37,  h: 36,  furniture: symbol, sizing: hug, anchor: left, block: bottom, fromBottom: 100.0 }
      footerUrl:  { x: 799, y: 1259, w: 217, h: 17,  align: right, role: url, furniture: url, sizing: hug, anchor: right, block: bottom, fromBottom: 91.0 }
    exampleImage: "https://galton-ai-assets.vercel.app/brand/layouts/body-cta.png"
    referenceSource: "https://galton-ai-assets.vercel.app/brand/layouts/body-cta.svg"

  - id: bullets-logo
    name: "Bulleted list closing on a client logo"
    ratios: ["1080x1350"]
    surfaces: [dark, light]
    header: folio
    footer: symbol
    verified: { geometry: true, type: true }
    must:
      - "The bullet is the `arrow-right` icon at 37px, in the accent, 25px clear of its text. It is never a dot, a dash or a typed character."
      - "Bullet copy is GALTON Light 60 Sentence case, wrapping at 890 beside the icon."
      - "A 2px rule closes the list, then the supplied client logo is centred in the panel below it. The logo is supplied with the brief: the brand does not ship it."
      - "The header rule and the footer rule are both present, 2px, 952 wide."
    slots:
      folioLeft:  { type: text, optional: true, case: upper }
      folioRight: { type: text, optional: true, case: upper }
      heading:    { type: lines, required: true, case: upper, note: "GALTON Light 80 UPPERCASE, one line" }
      bullets:    { type: stages, required: true, note: "3 bullets. Six boxes: bullet1Icon and bullet1Text through bullet3Icon and bullet3Text." }
      accent:     { type: text, optional: true, within: bullets, note: "NOT a box of its own: the words INSIDE a bullet set in the accent." }
      clientLogo: { type: image, required: true, note: "the supplied client or partner logo, centred in `logoPanel`" }
      surface:    { type: enum, values: [dark, light], default: dark }
    geometry:
      folioLeft:   { x: 64,    y: 64,   w: 187,   h: 17,  align: left,  role: folio, sizing: hug, anchor: left, block: top }
      folioRight:  { x: 800,   y: 64,   w: 216,   h: 17,  align: right, role: folio, sizing: hug, anchor: right, block: top }
      headerRule:  { x: 64,    y: 132,  w: 952,   h: 2,   furniture: rule, block: top }
      heading:     { x: 64,    y: 194,  w: 952,   h: 56,  slot: heading, align: left, role: headline, size: 80, maxLines: 1, sizing: hug, anchor: left, block: top }
      bullet1Icon: { x: 64,    y: 310,  w: 37,    h: 37,  slot: bullets, fit: contain, sizing: fixed, color: "{colors.primary}", block: top }
      bullet1Text: { x: 125.8, y: 310,  w: 890.2, h: 114, slot: bullets, align: left, role: subtitle, maxLines: 2, sizing: wrap, note: "WRAP at 890.2. The icon column is fixed; the text column is what stretches.", block: top }
      bullet2Icon: { x: 64,    y: 484,  w: 37,    h: 37,  slot: bullets, fit: contain, sizing: fixed, color: "{colors.primary}", block: top }
      bullet2Text: { x: 125.8, y: 484,  w: 890.2, h: 114, slot: bullets, align: left, role: subtitle, maxLines: 2, sizing: wrap, block: top }
      bullet3Icon: { x: 64,    y: 658,  w: 37,    h: 37,  slot: bullets, fit: contain, sizing: fixed, color: "{colors.primary}", block: top }
      bullet3Text: { x: 125.8, y: 658,  w: 890.2, h: 114, slot: bullets, align: left, role: subtitle, maxLines: 2, sizing: wrap, block: top }
      listRule:    { x: 64,    y: 830,  w: 952,   h: 2,   furniture: rule, block: top }
      logoPanel:   { x: 64,    y: 892,  w: 952,   h: 324, slot: clientLogo, align: center, fit: contain, sizing: fixed, note: "The PANEL is fixed; the logo inside it is not. Centre the supplied logo on both axes and fit it inside. The example logo lands at 487 x 91.", block: free }
      footerRule:  { x: 64,    y: 1214, w: 952,   h: 2,   furniture: rule, block: bottom, fromBottom: 136.0 }
      footerLogo:  { x: 64,    y: 1250, w: 37,    h: 36,  furniture: symbol, sizing: hug, anchor: left, block: bottom, fromBottom: 100.0 }
      footerUrl:   { x: 799,   y: 1259, w: 217,   h: 17,  align: right, role: url, furniture: url, sizing: hug, anchor: right, block: bottom, fromBottom: 91.0 }
    exampleImage: "https://galton-ai-assets.vercel.app/brand/layouts/bullets-logo.png"
    referenceSource: "https://galton-ai-assets.vercel.app/brand/layouts/bullets-logo.svg"

  - id: compare-columns
    name: "Two columns split by a vertical rule"
    ratios: ["1080x1350"]
    surfaces: [dark, light]
    header: folio
    footer: symbol
    verified: { geometry: true, type: true }
    must:
      - "The divider is a VERTICAL 2px rule, the same weight and colour as every horizontal rule in the system. It runs the full height of the columns and no further."
      - "Both columns are GALTON Light 40 Sentence case at 420 wide. The left column is a single prompt; the right column is a list of one-line answers."
      - "Right-column items are on a fixed 78px pitch: cap height 28, then 50 of air. Do not close the gaps to fit an eleventh item."
      - "Items may be set in the accent to mark a selection. The colour is the only thing that changes, and it is solid."
      - "The header rule and the footer rule are both present, 2px, 952 wide."
    slots:
      folioLeft:  { type: text, optional: true, case: upper }
      folioRight: { type: text, optional: true, case: upper }
      intro:      { type: text, required: true, note: "GALTON Light 60 Sentence case across the full 952 measure" }
      prompt:     { type: text, required: true, note: "the left column, GALTON Light 40, wraps at 420" }
      options:    { type: stages, required: true, note: "the right column. Ten boxes are measured: option1 through option10. Use as many as the content needs and leave the rest out." }
      accent:     { type: text, optional: true, within: options, note: "NOT a box of its own: the options set in the accent." }
      surface:    { type: enum, values: [dark, light], default: dark }
    geometry:
      folioLeft:  { x: 64,  y: 64,   w: 187, h: 17,  align: left,  role: folio, sizing: hug, anchor: left, block: top }
      folioRight: { x: 800, y: 64,   w: 216, h: 17,  align: right, role: folio, sizing: hug, anchor: right, block: top }
      headerRule: { x: 64,  y: 132,  w: 952, h: 2,   furniture: rule, block: top }
      intro:      { x: 64,  y: 194,  w: 952, h: 114, slot: intro, align: left, role: subtitle, maxLines: 2, sizing: wrap, block: top }
      prompt:     { x: 64,  y: 368,  w: 420, h: 220, slot: prompt, align: left, role: body, maxLines: 5, sizing: wrap, note: "WRAP at 420. h 220 is the example box, taller than its three lines of copy because it is top-aligned against a 730-high column.", block: top }
      columnRule: { x: 539, y: 368,  w: 2,   h: 730, furniture: rule, orientation: vertical, note: "The one VERTICAL rule in the catalog. Same 2px, same colour, full column height.", block: top }
      option1:    { x: 596, y: 368,  w: 420, h: 28,  slot: options, align: left, role: body, maxLines: 1, sizing: hug, anchor: left, block: top }
      option2:    { x: 596, y: 446,  w: 420, h: 28,  slot: options, align: left, role: body, maxLines: 1, sizing: hug, anchor: left, block: top }
      option3:    { x: 596, y: 524,  w: 420, h: 28,  slot: options, align: left, role: body, maxLines: 1, sizing: hug, anchor: left, block: top }
      option4:    { x: 596, y: 602,  w: 420, h: 28,  slot: options, align: left, role: body, maxLines: 1, sizing: hug, anchor: left, block: top }
      option5:    { x: 596, y: 680,  w: 420, h: 28,  slot: options, align: left, role: body, maxLines: 1, sizing: hug, anchor: left, block: top }
      option6:    { x: 596, y: 758,  w: 420, h: 28,  slot: options, align: left, role: body, maxLines: 1, sizing: hug, anchor: left, block: top }
      option7:    { x: 596, y: 836,  w: 420, h: 28,  slot: options, align: left, role: body, maxLines: 1, sizing: hug, anchor: left, block: top }
      option8:    { x: 596, y: 914,  w: 420, h: 28,  slot: options, align: left, role: body, maxLines: 1, sizing: hug, anchor: left, block: top }
      option9:    { x: 596, y: 992,  w: 420, h: 28,  slot: options, align: left, role: body, maxLines: 1, sizing: hug, anchor: left, block: top }
      option10:   { x: 596, y: 1070, w: 420, h: 28,  slot: options, align: left, role: body, maxLines: 1, sizing: hug, anchor: left, block: top }
      footerRule: { x: 64,  y: 1214, w: 952, h: 2,   furniture: rule, block: bottom, fromBottom: 136.0 }
      footerLogo: { x: 64,  y: 1250, w: 37,  h: 36,  furniture: symbol, sizing: hug, anchor: left, block: bottom, fromBottom: 100.0 }
      footerUrl:  { x: 799, y: 1259, w: 217, h: 17,  align: right, role: url, furniture: url, sizing: hug, anchor: right, block: bottom, fromBottom: 91.0 }
    exampleImage: "https://galton-ai-assets.vercel.app/brand/layouts/compare-columns.png"
    referenceSource: "https://galton-ai-assets.vercel.app/brand/layouts/compare-columns.svg"

  - id: body-payoff
    name: "Running copy closing on a payoff line"
    ratios: ["1080x1350"]
    surfaces: [dark, light]
    header: folio
    footer: symbol
    verified: { geometry: true, type: true }
    must:
      - "The copy is GALTON Light 60 Sentence case at the full 952 measure; the payoff under it is GALTON Light 120 UPPERCASE. The size jump is the whole idea of this layout."
      - "Words inside the copy may be set in the accent. The payoff is NOT: it stays solid ink."
      - "The header rule and the footer rule are both present, 2px, 952 wide."
    slots:
      folioLeft:  { type: text, optional: true, case: upper }
      folioRight: { type: text, optional: true, case: upper }
      body:       { type: text, required: true, note: "GALTON Light 60 Sentence case, wraps at 952, up to 8 lines" }
      accent:     { type: text, optional: true, within: body, note: "NOT a box of its own: the words INSIDE the copy set in the accent." }
      payoff:     { type: lines, required: true, case: upper, note: "GALTON Light 120 UPPERCASE, 1 to 2 lines" }
      surface:    { type: enum, values: [dark, light], default: dark }
    geometry:
      folioLeft:  { x: 64,  y: 64,   w: 187, h: 17,  align: left,  role: folio, sizing: hug, anchor: left, block: top }
      folioRight: { x: 800, y: 64,   w: 216, h: 17,  align: right, role: folio, sizing: hug, anchor: right, block: top }
      headerRule: { x: 64,  y: 132,  w: 952, h: 2,   furniture: rule, block: top }
      body:       { x: 64,  y: 194,  w: 952, h: 546, slot: body, align: left, role: subtitle, maxLines: 8, sizing: wrap, note: "WRAP at 952. h 546 is the example eight lines at 60.", block: top }
      payoff:     { x: 64,  y: 928,  w: 952, h: 228, slot: payoff, align: left, role: title, maxLines: 2, sizing: wrap, block: bottom, fromBottom: 422.0 }
      footerRule: { x: 64,  y: 1214, w: 952, h: 2,   furniture: rule, block: bottom, fromBottom: 136.0 }
      footerLogo: { x: 64,  y: 1250, w: 37,  h: 36,  furniture: symbol, sizing: hug, anchor: left, block: bottom, fromBottom: 100.0 }
      footerUrl:  { x: 799, y: 1259, w: 217, h: 17,  align: right, role: url, furniture: url, sizing: hug, anchor: right, block: bottom, fromBottom: 91.0 }
    exampleImage: "https://galton-ai-assets.vercel.app/brand/layouts/body-payoff.png"
    referenceSource: "https://galton-ai-assets.vercel.app/brand/layouts/body-payoff.svg"

  - id: steps-numbered
    name: "Two numbered steps"
    ratios: ["1080x1350"]
    surfaces: [dark, light]
    header: folio
    footer: symbol
    verified: { geometry: true, type: true }
    must:
      - "Each numeral is GALTON Thin 260 in the accent inside a fixed 150-wide column. The copy column starts at x 289 and never runs under the numeral."
      - "Copy is GALTON Light 60 Sentence case. Two steps per slide: a third does not fit and the answer is another slide, not smaller type."
      - "The two rows are distributed in the free space between the heading and the footer, so their y moves with the copy. The measured y values are the example."
      - "The header rule and the footer rule are both present, 2px, 952 wide."
    slots:
      folioLeft:  { type: text, optional: true, case: upper }
      folioRight: { type: text, optional: true, case: upper }
      heading:    { type: lines, required: true, case: upper, note: "GALTON Light 80 UPPERCASE, one line" }
      steps:      { type: stages, required: true, note: "2 steps. Four boxes: step1Number and step1Text, step2Number and step2Text." }
      surface:    { type: enum, values: [dark, light], default: dark }
    geometry:
      folioLeft:   { x: 64,  y: 64,   w: 187, h: 17,  align: left,  role: folio, sizing: hug, anchor: left, block: top }
      folioRight:  { x: 800, y: 64,   w: 216, h: 17,  align: right, role: folio, sizing: hug, anchor: right, block: top }
      headerRule:  { x: 64,  y: 132,  w: 952, h: 2,   furniture: rule, block: top }
      heading:     { x: 64,  y: 194,  w: 952, h: 56,  slot: heading, align: left, role: headline, size: 80, maxLines: 1, sizing: hug, anchor: left, block: top }
      step1Number: { x: 64,  y: 449,  w: 150, h: 182, slot: steps, align: left, role: numeral, size: 260, sizing: fixed, color: "{colors.primary}", block: free }
      step1Text:   { x: 289, y: 449,  w: 666, h: 186, slot: steps, align: left, role: subtitle, maxLines: 3, sizing: wrap, note: "WRAP at 666. The copy is TOP-aligned with the numeral, not centred on it.", block: free }
      step2Number: { x: 64,  y: 835,  w: 150, h: 182, slot: steps, align: left, role: numeral, size: 260, sizing: fixed, color: "{colors.primary}", block: free }
      step2Text:   { x: 289, y: 835,  w: 727, h: 114, slot: steps, align: left, role: subtitle, maxLines: 3, sizing: wrap, block: free }
      footerRule:  { x: 64,  y: 1214, w: 952, h: 2,   furniture: rule, block: bottom, fromBottom: 136.0 }
      footerLogo:  { x: 64,  y: 1250, w: 37,  h: 36,  furniture: symbol, sizing: hug, anchor: left, block: bottom, fromBottom: 100.0 }
      footerUrl:   { x: 799, y: 1259, w: 217, h: 17,  align: right, role: url, furniture: url, sizing: hug, anchor: right, block: bottom, fromBottom: 91.0 }
    exampleImage: "https://galton-ai-assets.vercel.app/brand/layouts/steps-numbered.png"
    referenceSource: "https://galton-ai-assets.vercel.app/brand/layouts/steps-numbered.svg"

  - id: steps-arrow
    name: "Numbered stages with arrows"
    ratios: ["1080x1350"]
    surfaces: [dark, light]
    header: folio
    footer: symbol
    verified: { geometry: true, type: true }
    must:
      - "Every row is number, arrow, label, in that order and on those three fixed columns: the numeral at 64, the arrow at 239, the label at 419."
      - "The numeral is GALTON Thin 150 in the accent; the arrow is `arrow-right` from the arrows set; the label is GALTON Light 80 UPPERCASE on ONE line."
      - "The four rows are on a fixed 189px pitch and are centred as a block in the space between the header and the footer."
      - "The header rule and the footer rule are both present, 2px, 952 wide. There is no headline: the rows are the whole slide."
    slots:
      folioLeft:  { type: text, optional: true, case: upper }
      folioRight: { type: text, optional: true, case: upper }
      stages:     { type: stages, required: true, case: upper, note: "4 stages. Twelve boxes: stage1Number, stage1Arrow, stage1Label through stage4." }
      surface:    { type: enum, values: [dark, light], default: dark }
    geometry:
      folioLeft:    { x: 64,  y: 64,    w: 187, h: 17,  align: left,  role: folio, sizing: hug, anchor: left, block: top }
      folioRight:   { x: 800, y: 64,    w: 216, h: 17,  align: right, role: folio, sizing: hug, anchor: right, block: top }
      headerRule:   { x: 64,  y: 132,   w: 952, h: 2,   furniture: rule, block: top }
      stage1Number: { x: 64,  y: 339,   w: 100, h: 105, slot: stages, align: left, role: numeral, size: 150, sizing: fixed, color: "{colors.primary}", block: free }
      stage1Arrow:  { x: 239, y: 334.5, w: 105, h: 114, slot: stages, fit: contain, sizing: fixed, color: "{colors.primary}", block: free }
      stage1Label:  { x: 419, y: 363.5, w: 597, h: 56,  slot: stages, align: left, role: headline, size: 80, maxLines: 1, sizing: hug, anchor: left, block: free }
      stage2Number: { x: 64,  y: 528,   w: 100, h: 105, slot: stages, align: left, role: numeral, size: 150, sizing: fixed, color: "{colors.primary}", block: free }
      stage2Arrow:  { x: 239, y: 523.5, w: 105, h: 114, slot: stages, fit: contain, sizing: fixed, color: "{colors.primary}", block: free }
      stage2Label:  { x: 419, y: 552.5, w: 597, h: 56,  slot: stages, align: left, role: headline, size: 80, maxLines: 1, sizing: hug, anchor: left, block: free }
      stage3Number: { x: 64,  y: 717,   w: 100, h: 105, slot: stages, align: left, role: numeral, size: 150, sizing: fixed, color: "{colors.primary}", block: free }
      stage3Arrow:  { x: 239, y: 712.5, w: 105, h: 114, slot: stages, fit: contain, sizing: fixed, color: "{colors.primary}", block: free }
      stage3Label:  { x: 419, y: 741.5, w: 597, h: 56,  slot: stages, align: left, role: headline, size: 80, maxLines: 1, sizing: hug, anchor: left, block: free }
      stage4Number: { x: 64,  y: 906,   w: 100, h: 105, slot: stages, align: left, role: numeral, size: 150, sizing: fixed, color: "{colors.primary}", block: free }
      stage4Arrow:  { x: 239, y: 901.5, w: 105, h: 114, slot: stages, fit: contain, sizing: fixed, color: "{colors.primary}", block: free }
      stage4Label:  { x: 419, y: 930.5, w: 597, h: 56,  slot: stages, align: left, role: headline, size: 80, maxLines: 1, sizing: hug, anchor: left, block: free }
      footerRule:   { x: 64,  y: 1214,  w: 952, h: 2,   furniture: rule, block: bottom, fromBottom: 136.0 }
      footerLogo:   { x: 64,  y: 1250,  w: 37,  h: 36,  furniture: symbol, sizing: hug, anchor: left, block: bottom, fromBottom: 100.0 }
      footerUrl:    { x: 799, y: 1259,  w: 217, h: 17,  align: right, role: url, furniture: url, sizing: hug, anchor: right, block: bottom, fromBottom: 91.0 }
    exampleImage: "https://galton-ai-assets.vercel.app/brand/layouts/steps-arrow.png"
    referenceSource: "https://galton-ai-assets.vercel.app/brand/layouts/steps-arrow.svg"

  - id: definitions-stack
    name: "Two defined terms, stacked"
    ratios: ["1080x1350"]
    surfaces: [dark, light]
    header: none
    footer: symbol
    verified: { geometry: true, type: true }
    must:
      - "Each block is three parts in a fixed order: an accent eyebrow at 50 UPPERCASE, the term at GALTON Light 100 UPPERCASE, then the description at 50."
      - "The description is INDENTED to x 266 and runs to 1016. The eyebrow and the term stay flush left at 64. That step is the layout."
      - "The eyebrow is the ONLY accent on the slide. The term and the description are solid ink."
      - "There is NO header. The footer rule, the G symbol and the lowercase URL are present."
    slots:
      terms:   { type: stages, required: true, note: "2 terms. Six boxes: term1Eyebrow, term1, term1Body and the same three for term2." }
      surface: { type: enum, values: [dark, light], default: dark }
    geometry:
      term1Eyebrow: { x: 64,  y: 64,   w: 952, h: 35,  slot: terms, align: left, role: lead, case: upper, maxLines: 1, sizing: hug, anchor: left, color: "{colors.primary}", block: top }
      term1:        { x: 64,  y: 159,  w: 952, h: 70,  slot: terms, align: left, role: headline, maxLines: 1, sizing: hug, anchor: left, block: top }
      term1Body:    { x: 266, y: 289,  w: 750, h: 95,  slot: terms, align: left, role: lead, maxLines: 3, sizing: wrap, note: "WRAP at 750, indented to 266. The right edge stays at 1016.", block: top }
      term2Eyebrow: { x: 64,  y: 640,  w: 952, h: 35,  slot: terms, align: left, role: lead, case: upper, maxLines: 1, sizing: hug, anchor: left, color: "{colors.primary}", block: free }
      term2:        { x: 64,  y: 735,  w: 952, h: 70,  slot: terms, align: left, role: headline, maxLines: 1, sizing: hug, anchor: left, block: free }
      term2Body:    { x: 266, y: 865,  w: 750, h: 95,  slot: terms, align: left, role: lead, maxLines: 3, sizing: wrap, block: free }
      footerRule:   { x: 64,  y: 1214, w: 952, h: 2,   furniture: rule, block: bottom, fromBottom: 136.0 }
      footerLogo:   { x: 64,  y: 1250, w: 37,  h: 36,  furniture: symbol, sizing: hug, anchor: left, block: bottom, fromBottom: 100.0 }
      footerUrl:    { x: 799, y: 1259, w: 217, h: 17,  align: right, role: url, furniture: url, sizing: hug, anchor: right, block: bottom, fromBottom: 91.0 }
    exampleImage: "https://galton-ai-assets.vercel.app/brand/layouts/definitions-stack.png"
    referenceSource: "https://galton-ai-assets.vercel.app/brand/layouts/definitions-stack.svg"

  - id: event-speaker
    name: "Event announcement, one speaker"
    ratios: ["1080x1350"]
    surfaces: [dark]
    header: wordmark
    footer: symbol
    verified: { geometry: true, type: true }
    must:
      - "The full GALTON lockup sits top-left. It is an image file, never retyped as text."
      - "The portrait is FULL BLEED. Everything below the lockup sits on top of it; if the type does not read, darken the WHOLE image per canvas.imageTreatment."
      - "The event title is GALTON Light 60 UPPERCASE. It is the 60px size in UPPERCASE, which is the one place the subtitle size is uppercased."
      - "Every meta field is a pair: a 24 Medium UPPERCASE label with its value 42 below it. Values are GALTON Light 50, and the speaker note under a value is GALTON Light 30."
      - "The footer rule, the G symbol and the lowercase URL are present."
    slots:
      photo:      { type: image, required: true, note: "One box: `photo`. Full bleed, cropped to fill." }
      title:      { type: lines, required: true, case: upper, note: "GALTON Light 60 UPPERCASE, up to 4 lines" }
      speaker:    { type: stages, required: true, note: "the left meta column. Three boxes: speakerLabel, speakerName, speakerRole." }
      details:    { type: stages, optional: true, note: "the right meta column, two stacked pairs. Four boxes: detail1Label and detail1Value, detail2Label and detail2Value." }
      surface:    { type: enum, values: [dark], default: dark }
    geometry:
      photo:        { x: 0,     y: 0,    w: 1080,  h: 1350, slot: photo, fit: cover, sizing: fixed, block: cover }
      wordmark:     { x: 64,    y: 64,   w: 277,   h: 70,   furniture: wordmark, sizing: hug, anchor: left, note: "HUG. The HEIGHT 70 is the constraint; the width follows the lockup's own aspect ratio.", block: top }
      title:        { x: 64,    y: 643,  w: 952,   h: 258,  slot: title, align: left, role: subtitle, case: upper, maxLines: 4, sizing: wrap, note: "WRAP at 952. h 258 is the example four lines at 60.", block: bottom, fromBottom: 707.0 }
      speakerLabel: { x: 64,    y: 961,  w: 444.5, h: 17,   slot: speaker, align: left, role: folio, sizing: hug, anchor: left, block: bottom, fromBottom: 389.0 }
      speakerName:  { x: 64,    y: 1003, w: 444.5, h: 35,   slot: speaker, align: left, role: lead, maxLines: 1, sizing: hug, anchor: left, block: bottom, fromBottom: 347.0 }
      speakerRole:  { x: 64,    y: 1063, w: 444.5, h: 93,   slot: speaker, align: left, role: meta, maxLines: 3, sizing: wrap, note: "WRAP at 444.5, the left column measure.", block: bottom, fromBottom: 287.0 }
      detail1Label: { x: 571.5, y: 961,  w: 444.5, h: 17,   slot: details, align: left, role: folio, sizing: hug, anchor: left, block: bottom, fromBottom: 389.0 }
      detail1Value: { x: 571.5, y: 1003, w: 444.5, h: 35,   slot: details, align: left, role: lead, maxLines: 1, sizing: hug, anchor: left, block: bottom, fromBottom: 347.0 }
      detail2Label: { x: 571.5, y: 1079, w: 444.5, h: 17,   slot: details, align: left, role: folio, sizing: hug, anchor: left, block: bottom, fromBottom: 271.0 }
      detail2Value: { x: 571.5, y: 1121, w: 444.5, h: 35,   slot: details, align: left, role: lead, maxLines: 1, sizing: hug, anchor: left, block: bottom, fromBottom: 229.0 }
      footerRule:   { x: 64,    y: 1214, w: 952,   h: 2,    furniture: rule, block: bottom, fromBottom: 136.0 }
      footerLogo:   { x: 64,    y: 1250, w: 37,    h: 36,   furniture: symbol, sizing: hug, anchor: left, block: bottom, fromBottom: 100.0 }
      footerUrl:    { x: 799,   y: 1259, w: 217,   h: 17,   align: right, role: url, furniture: url, sizing: hug, anchor: right, block: bottom, fromBottom: 91.0 }
    exampleImage: "https://galton-ai-assets.vercel.app/brand/layouts/event-speaker.png"
    referenceSource: "https://galton-ai-assets.vercel.app/brand/layouts/event-speaker.svg"

  - id: event-panel
    name: "Event announcement, panel of participants"
    ratios: ["1080x1350"]
    surfaces: [dark]
    header: partner-logo
    footer: symbol
    verified: { geometry: true, type: true }
    must:
      - "The header carries the SUPPLIED event logo scaled to 70 tall, in the GALTON lockup's place. The two never share the band."
      - "The category pill is the FILLED accent pill: yellow floor, canvas-coloured 24 Medium UPPERCASE label, left edge at 64, hugging its label."
      - "The portrait is FULL BLEED under everything. If the type does not read, darken the WHOLE image per canvas.imageTreatment."
      - "Participants are a bulleted list at GALTON Light 30 with a 45px marker indent, under a 24 Medium UPPERCASE label."
      - "The footer rule, the G symbol and the lowercase URL are present."
    slots:
      photo:       { type: image, required: true, note: "One box: `photo`. Full bleed, cropped to fill." }
      partnerLogo: { type: image, required: true, note: "the supplied event logo in the header, 70 tall" }
      tag:         { type: text, optional: true, case: upper, note: "the pill label. Two boxes: `tagPill` is the filled shape, `tagLabel` is the text inside it." }
      title:       { type: lines, required: true, case: upper, note: "GALTON Light 60 UPPERCASE, 1 to 2 lines" }
      participants: { type: stages, required: true, note: "Two boxes: `participantsLabel` and the list box `participants`." }
      surface:     { type: enum, values: [dark], default: dark }
    geometry:
      photo:             { x: 0,   y: 0,    w: 1080, h: 1350, slot: photo, fit: cover, sizing: fixed, block: cover }
      headerLogo:        { x: 64,  y: 64,   w: 341,  h: 70,   slot: partnerLogo, furniture: headerLogo, sizing: hug, anchor: left, note: "HUG. Scale the supplied logo to 70 tall and let the width follow. w 341 is the example logo.", block: top }
      tagPill:           { x: 64,  y: 720,  w: 284,  h: 67,   slot: tag, radius: full, paddingX: 25, fill: "{colors.primary}", sizing: hug, anchor: left, note: "HUG. Width is the label width plus 50. The LEFT edge stays at 64 and the pill grows rightwards. Height stays 67 and the label stays 24: never shrink the type to fit.", block: bottom, fromBottom: 630.0 }
      tagLabel:          { x: 89,  y: 745,  w: 234,  h: 17,   slot: tag, align: center, role: folio, color: "{colors.canvas}", sizing: hug, anchor: center, note: "HUG. Centred in the pill with 25px clear on each side. Canvas colour, because it sits on the yellow.", block: bottom, fromBottom: 605.0 }
      title:             { x: 64,  y: 847,  w: 952,  h: 114,  slot: title, align: left, role: subtitle, case: upper, maxLines: 2, sizing: wrap, block: bottom, fromBottom: 503.0 }
      participantsLabel: { x: 64,  y: 1021, w: 952,  h: 17,   slot: participants, align: left, role: folio, sizing: hug, anchor: left, block: bottom, fromBottom: 329.0 }
      participants:      { x: 64,  y: 1063, w: 952,  h: 93,   slot: participants, align: left, role: meta, maxLines: 4, sizing: wrap, markerIndent: 45, note: "A bulleted list. The marker sits 45px in from x 64; h 93 is the example three items.", block: bottom, fromBottom: 287.0 }
      footerRule:        { x: 64,  y: 1214, w: 952,  h: 2,    furniture: rule, block: bottom, fromBottom: 136.0 }
      footerLogo:        { x: 64,  y: 1250, w: 37,   h: 36,   furniture: symbol, sizing: hug, anchor: left, block: bottom, fromBottom: 100.0 }
      footerUrl:         { x: 799, y: 1259, w: 217,  h: 17,   align: right, role: url, furniture: url, sizing: hug, anchor: right, block: bottom, fromBottom: 91.0 }
    exampleImage: "https://galton-ai-assets.vercel.app/brand/layouts/event-panel.png"
    referenceSource: "https://galton-ai-assets.vercel.app/brand/layouts/event-panel.svg"

  - id: recruitment
    name: "Recruitment, framed centre panel"
    ratios: ["1080x1350"]
    surfaces: [dark, light]
    header: wordmark-center
    footer: none
    verified: { geometry: true, type: true }
    must:
      - "This layout has NO footer, and therefore NO rule, NO G symbol and NO URL. The closing line at the bottom is what stands in for the footer, and that is deliberate."
      - "The GALTON lockup is CENTRED on the header band, not left-aligned."
      - "Two frames sit on the same 808px square: a 2px circle inscribed in it, and four 48px corner marks straddling its corners. Both are present or neither is."
      - "Inside the circle, in this order: the FILLED accent pill, the headline at GALTON Light 100 UPPERCASE centred, then the OUTLINE pill."
      - "Everything on this layout is centred on the canvas axis: the lockup, the panel, the pills, the headline and the closing line."
    slots:
      tag:       { type: text, optional: true, case: upper, note: "the top pill label, filled accent. Two boxes: `tagPill` and `tagLabel`." }
      headline:  { type: lines, required: true, case: upper, note: "GALTON Light 100 UPPERCASE, centred, up to 3 lines" }
      badge:     { type: text, optional: true, case: upper, note: "the lower pill label, outline. Two boxes: `badgePill` and `badgeLabel`." }
      closing:   { type: text, optional: true, case: upper, note: "GALTON Light 40 UPPERCASE, centred, at the bottom edge in the footer's place" }
      surface:   { type: enum, values: [dark, light], default: dark }
    geometry:
      wordmark:     { x: 401.7, y: 64,   w: 276.6, h: 70,  furniture: wordmark, sizing: hug, anchor: center, note: "HUG, CENTRED. The HEIGHT 70 is the constraint and the lockup stays on the canvas axis.", block: top }
      panelFrame:   { x: 136,   y: 268,  w: 808,   h: 808, border: 2, align: center, sizing: fixed, note: "The 808 SQUARE. 2px stroke, no fill. The corner marks straddle its four corners.", block: free }
      panel:        { x: 136,   y: 268,  w: 808,   h: 808, radius: full, border: 2, align: center, sizing: fixed, note: "The circle inscribed in that square. 2px stroke, no fill. Square and circle are both drawn.", block: free }
      cornerMarkTL: { x: 112,   y: 244,  w: 48,    h: 48,  furniture: cornerMarks, sizing: fixed, block: free }
      cornerMarkTR: { x: 920,   y: 244,  w: 48,    h: 48,  furniture: cornerMarks, sizing: fixed, block: free }
      cornerMarkBL: { x: 112,   y: 1052, w: 48,    h: 48,  furniture: cornerMarks, sizing: fixed, block: free }
      cornerMarkBR: { x: 920,   y: 1052, w: 48,    h: 48,  furniture: cornerMarks, sizing: fixed, block: free }
      tagPill:      { x: 421,   y: 398,  w: 238,   h: 67,  slot: tag, radius: full, paddingX: 25, fill: "{colors.primary}", align: center, sizing: hug, anchor: center, note: "HUG and CENTRED. Width is the label plus 50.", block: free }
      tagLabel:     { x: 446,   y: 423,  w: 188,   h: 17,  slot: tag, align: center, role: folio, color: "{colors.canvas}", sizing: hug, anchor: center, block: free }
      headline:     { x: 244.5, y: 515,  w: 591,   h: 310, align: center, role: headline, maxLines: 3, sizing: hug, anchor: center, note: "HUG and CENTRED, not wrapped: each line is set to its own width and centred. h 310 is the example three lines at 100.", block: free }
      badgePill:    { x: 628.5, y: 875,  w: 177,   h: 71,  slot: badge, radius: full, paddingX: 25, border: 2, align: center, sizing: hug, anchor: center, note: "HUG and CENTRED. The OUTLINE pill is 71 tall, 4 more than the filled one.", block: free }
      badgeLabel:   { x: 653.5, y: 902,  w: 127,   h: 17,  slot: badge, align: center, role: folio, sizing: hug, anchor: center, block: free }
      closing:      { x: 64,    y: 1210, w: 952,   h: 76,  slot: closing, align: center, role: body, case: upper, maxLines: 2, sizing: wrap, note: "Centred. Its BOTTOM edge is the content edge at 1286, where the footer would otherwise start.", block: bottom, fromBottom: 140.0 }
    exampleImage: "https://galton-ai-assets.vercel.app/brand/layouts/recruitment.png"
    referenceSource: "https://galton-ai-assets.vercel.app/brand/layouts/recruitment.svg"

  - id: partnership
    name: "Partnership lockup over a portrait"
    ratios: ["1080x1350"]
    surfaces: [dark]
    header: none
    footer: none
    verified: { geometry: true, type: true }
    must:
      - "This layout has NO header and NO footer, and therefore NO rule, NO G symbol and NO URL. The centred pill at the bottom is what closes it, and that is deliberate."
      - "The lockup is a CENTRED vertical stack in one fixed order: the supplied partner logo, the cross mark, then the GALTON lockup. A 50px gap between each."
      - "The GALTON lockup is an image file, never retyped as text, and it is never smaller than the partner logo beside it in the pairing."
      - "The picture treatment is the whole panel: a colour wash over the portrait and a flat gradient into the canvas colour at the bottom. Never a band behind the words."
    slots:
      photo:       { type: image, required: true, note: "One box: `photo`. Full bleed, cropped to fill, then treated per canvas.imageTreatment." }
      partnerLogo: { type: image, required: true, note: "the supplied partner logo at the top of the stack" }
      badge:       { type: text, optional: true, case: upper, note: "the closing pill label, outline. Two boxes: `badgePill` and `badgeLabel`." }
      surface:     { type: enum, values: [dark], default: dark }
    geometry:
      photo:       { x: 0,     y: 0,    w: 1080, h: 1350, slot: photo, fit: cover, sizing: fixed, block: cover }
      overlay:     { x: 0,     y: 310,  w: 1080, h: 1040, fill: "{colors.canvas}", sizing: fixed, note: "The flat gradient into the canvas colour that carries the lower half of the picture. It is part of the IMAGE treatment, not a backing band for type.", block: inset, insetTop: 310.0, insetBottom: 0.0 }
      partnerLogo: { x: 411,   y: 476,  w: 258,  h: 100,  slot: partnerLogo, align: center, fit: contain, sizing: hug, anchor: center, note: "HUG and CENTRED. The example logo lands at 258 x 100.", block: free }
      crossMark:   { x: 472.5, y: 626,  w: 135,  h: 128,  align: center, fit: contain, sizing: fixed, note: "The multiplication mark that joins the two brands. It is a supplied vector, not a typed x.", block: free }
      lockup:      { x: 324.5, y: 804,  w: 431,  h: 69,   furniture: wordmark, align: center, sizing: hug, anchor: center, note: "HUG and CENTRED. The HEIGHT is the constraint; the width follows the lockup's own aspect ratio.", block: free }
      badgePill:   { x: 447.5, y: 1215, w: 185,  h: 71,   slot: badge, radius: full, paddingX: 27, border: 2, align: center, sizing: hug, anchor: center, block: bottom, fromBottom: 135.0 }
      badgeLabel:  { x: 474.5, y: 1242, w: 131,  h: 17,   slot: badge, align: center, role: folio, sizing: hug, anchor: center, block: bottom, fromBottom: 108.0 }
    exampleImage: "https://galton-ai-assets.vercel.app/brand/layouts/partnership.png"
    referenceSource: "https://galton-ai-assets.vercel.app/brand/layouts/partnership.svg"

  - id: guide-cover
    name: "Guide cover with a 3D cluster"
    ratios: ["1080x1350"]
    surfaces: [dark]
    header: none
    footer: symbol
    verified: { geometry: true, type: true }
    must:
      - "The headline is GALTON Light 150 UPPERCASE and CENTRED. It is the largest type in the system and the only layout that uses it."
      - "The pill above it is the OUTLINE pill, centred, hugging its 24 Medium UPPERCASE label."
      - "The 3D cluster sits in a fixed 952 x 518 band directly above the footer rule. Fit the artwork inside it; do not crop it to fill."
      - "There is NO header. The footer rule, the G symbol and the lowercase URL are present."
    slots:
      tag:      { type: text, optional: true, case: upper, note: "the outline pill at the top. Two boxes: `tagPill` and `tagLabel`." }
      headline: { type: lines, required: true, case: upper, note: "GALTON Light 150 UPPERCASE, centred, 1 to 2 lines" }
      graphic:  { type: image, optional: true, note: "the 3D cluster in the lower band" }
      surface:  { type: enum, values: [dark], default: dark }
    geometry:
      tagPill:    { x: 411.5, y: 64,   w: 257, h: 71,  slot: tag, radius: full, paddingX: 27, border: 2, align: center, sizing: hug, anchor: center, note: "HUG and CENTRED. Width is the label plus 54 on the measured example.", block: top }
      tagLabel:   { x: 438.5, y: 91,   w: 203, h: 17,  slot: tag, align: center, role: folio, sizing: hug, anchor: center, block: top }
      headline:   { x: 64,    y: 195,  w: 952, h: 285, align: center, role: display, maxLines: 2, sizing: wrap, note: "WRAP at 952, CENTRED. h 285 is the example two lines at 150.", block: top }
      graphic:    { x: 64,    y: 758,  w: 952, h: 518, slot: graphic, align: center, fit: contain, sizing: fixed, note: "Fixed band directly above the footer rule. Fit the cluster inside it.", block: bottom, fromBottom: 592.0 }
      footerRule: { x: 64,    y: 1214, w: 952, h: 2,   furniture: rule, block: bottom, fromBottom: 136.0 }
      footerLogo: { x: 64,    y: 1250, w: 37,  h: 36,  furniture: symbol, sizing: hug, anchor: left, block: bottom, fromBottom: 100.0 }
      footerUrl:  { x: 799,   y: 1259, w: 217, h: 17,  align: right, role: url, furniture: url, sizing: hug, anchor: right, block: bottom, fromBottom: 91.0 }
    exampleImage: "https://galton-ai-assets.vercel.app/brand/layouts/guide-cover.png"
    referenceSource: "https://galton-ai-assets.vercel.app/brand/layouts/guide-cover.svg"


# ── Carousel recipes — one ordered sequence per LinkedIn post type ──────
recipes:
  - { id: educational-carousel, forPostType: educational, slides: [cover, statement, concept, concept, statement] }
  - { id: single-insight,       forPostType: insight,     slides: [statement] }
  - { id: announcement,         forPostType: announcement, slides: [cover, statement] }
  - { id: event-post,           forPostType: event,       slides: [profile] }
  - { id: naming-carousel,      forPostType: naming,      slides: [cover, statement, concept] }
  # The editorial recipes. They use the layouts measured off "Autolayouts 2",
  # and they are the ones to reach for when a post has more than one idea in it.
  - { id: process-carousel,     forPostType: educational, slides: [cover-image, statement-cta, step-numeral, step-numeral, body-payoff] }
  - { id: framework-carousel,   forPostType: educational, slides: [title-image, rule-list, compare-columns, steps-arrow, graphic-statement] }
  - { id: guide-carousel,       forPostType: educational, slides: [guide-cover, body-cta, bullets-logo, steps-numbered, definitions-stack, graphic-statement] }
  - { id: speaker-post,         forPostType: event,       slides: [event-speaker] }
  - { id: panel-post,           forPostType: event,       slides: [event-panel] }
  - { id: partnership-post,     forPostType: announcement, slides: [partnership] }
  - { id: recruitment-post,     forPostType: announcement, slides: [recruitment] }
  - { id: team-post,            forPostType: insight,     slides: [person-round] }
---

## Layout catalog

This catalog is **reference knowledge**, not a generator. It documents the
finalized GALTON slide system so an agent can
rebuild any slide on-brand in its own tool — the framework never renders,
screenshots or generates an image.

Every layout carries **measured geometry**: absolute x/y/w/h in px on the
1080×1350 canvas, read out of the design source. Use the numbers. Do not derive a
position from an adjective like "bottom-right", and do not measure the example
image by eye.

### The canvas

Every slide is built on one shared canvas (read it via `get_layout` with no id):

- **Size** — `1080×1350` (portrait) or `1080×1080` (square), **64px padding** on
  all sides, so the content box is `x 64, y 64, 952 × 1222`.
- **Colours** — near-black `#1A1A1A` floor, white `#FFFFFF` ink, a single
  `#FFD700` yellow accent (never a large fill). On a light surface the system
  inverts to black-on-white; the yellow is unchanged.
- **Composition** — the canvas distributes its blocks **vertically-centred** with
  an automatic gap. A **Top Block** is top-left aligned and a **Bottom Block** is
  bottom-left aligned; each stacks its children with a fixed **60px gap**.
- **Slide type scale** — Headline `GALTON Light 100 UPPERCASE`, Subtitle
  `GALTON Light 60 Sentence case`, Name `GALTON Medium 36 UPPERCASE`, Caption
  `GALTON Light 36 UPPERCASE`, Folio `GALTON Medium 24 UPPERCASE`, URL
  `GALTON Medium 24 lowercase` — all at 120% leading. (This is the **slide**
  scale; the responsive web scale lives in design.md and stays Sentence case.)

### Reading the geometry

Text boxes in the source are **trimmed to cap height**. A text slot's `y` is the
top of the capital letters of the first line, not the top of the line box, and
`h` is that trimmed height: `lines × size × 1.2 − size × 0.5` for Latin without
diacritics. In CSS that is `line-height: 1.2` plus `text-box-trim: trim-both`
and `text-box-edge: cap alphabetic`. If your tool cannot cap-trim, align the
first line by its **baseline** rather than by the top of the box, otherwise the
whole block sits about a quarter of the type size too low.

### A width is rarely a constraint

Every box carries `sizing`. Only `fixed` boxes are exactly the size given: the
rules, the image safe area and the column widths. Anything holding a label, a
supplied logo or copy you are replacing is **`hug`**, and its `w` and `h` are
what the example measured, nothing more. Keep the edge named by `anchor`, let the
box grow the other way, and never shrink the type or squeeze a logo to make it
fit a number. Text blocks are **`wrap`**: the width is real, the height belongs
to the example copy.

The tag pill is the clearest case. Its 139px is the width of the word `EVENT`. A
tag reading `REAL ESTATE` is a wider pill that starts further left, with the same
47px height and the same 24px label.

### Type over an image

The `profile` people row sits on top of the picture, and any layout with an image
slot can end up the same way. When the type does not read, **treat the image, not
the words**: darken the picture itself, or lay a flat overlay of the canvas colour
across the whole panel. Keep the treatment even over the entire panel rather than
putting a band or a fade behind the words alone, which draws a shape the layout
does not have. The type itself stays exactly as specified: solid ink, full size,
no shadow, no outline, no reduced opacity. Read `canvas.imageTreatment`.

### Furniture — the part that gets forgotten

`canvas.furniture` holds the pieces that are not content and are **never
omitted**: the rule, the symbol, the wordmark lockup and the URL. A slide with
the right words but no footer rule, or with the black symbol on a dark surface,
is off-brand.

- **The rule is a solid 2px line, 952px wide** — not the web `{colors.hairline}`
  token (white at 12%), which is a UI border and disappears at slide scale.
- **The logo variant is decided by the surface, not by you.** Dark surface takes
  the white file, light surface takes the black file; both absolute URLs are in
  `canvas.furniture`. Hotlink them, never retype a wordmark as text.
- **The footer URL is lowercase.** It is the only slide type that is not
  uppercased. Which domain it carries follows the **language of the copy on the
  slide**: Slovak signs off `galton.sk`, English may sign off
  `galtonbrands.com`. This is guidance rather than a rule, and `galton.sk` is
  the primary domain and the default whenever the language is mixed or unclear.
  One domain per slide, and the same domain across every slide of a carousel.
- Header and footer bands are both a fixed **70px** tall.

There are four headers (`folio`, `wordmark`, `wordmark-center`, `partner-logo`)
and three footers (`symbol`, `partner`, `none`). The `partner` footer swaps the G
symbol for a supplied event or award logo; the `partner-logo` header does the
same in the top band, in the lockup's place. That file comes with the brief, the
brand does not ship it. `none` on either band is a deliberate choice made by two
layouts and stated in their `must`; it is never a licence to drop a band from a
layout that has one.

### The base layouts

Each layout is a **slot schema** plus its measured geometry, a `must` list of the
things that are never dropped, and an example image.

1. **cover** — folio header (two labels + rule) + a big Light UPPERCASE headline
   (optionally one yellow accent line) over a Sentence-case subtitle; symbol footer.
2. **profile** — wordmark lockup + optional event pill, an image in a rounded
   panel, one or two `Name | Role` people, **partner footer** carrying the
   supplied event or award logo. The image slot is a **safe area**, not a fixed
   box: any aspect ratio, scaled to fit inside it and centred, never touching the
   header band, the footer rule or the padding.
3. **concept** — no header. A big Light UPPERCASE headline up top; a **second
   Light UPPERCASE headline** bottom-left beside a supporting icon or geometric
   cluster bottom-right; symbol footer.
4. **statement** — **no header and no footer at all**. A big headline up top, a
   centred 3-circle Venn with only its three-way intersection in yellow, a
   Sentence-case subtitle and a yellow arrow CTA at the bottom.
5. **statement-light** — the same frame on the white canvas. It inherits every
   measured number from `statement`, so only the colours change: near-black ink,
   a near-black Venn stroke and a near-black arrow. The yellow intersection is
   unchanged, because the accent never inverts.

### The editorial layouts

Twenty one more layouts are measured off the same design source. They share the
canvas, the padding, the chrome bands and the furniture with the five above;
what they add is the rest of the type scale and the compositions a carousel
needs in its middle. They group into six families:

- **Covers** (`cover-image`, `cover-image-half`, `title-image`, `guide-cover`) put
  a picture or a 3D cluster behind or under the headline. The image is cropped to
  **fill**, unlike `profile`'s safe area, which fits. When type does not read over
  a picture, treat the whole image, never band the words.
- **Statements** (`statement-cta`, `body-cta`, `body-payoff`, `graphic-statement`)
  carry one block of copy and close on an arrow, a payoff line or a graphic. The
  arrows come from the arrows icon set; hotlink them, never redraw them.
- **Lists** (`rule-list`, `bullets-logo`, `compare-columns`, `definitions-stack`)
  are the ruled, bulleted, two-column and defined-term structures. `compare-columns`
  carries the one **vertical** rule in the catalog.
- **Steps** (`step-numeral`, `steps-numbered`, `steps-arrow`) are the numbered
  slides. The numeral is the only use of **GALTON Thin** in the whole system and
  the only type that is always the accent, at 500, 260 or 150 depending on the row.
- **People and events** (`person-round`, `person-image`, `event-speaker`,
  `event-panel`) put a portrait behind or beside a name, a talk or a panel. The
  round 450px crop on `person-round` is the only circular mask in the system.
- **Announcements** (`recruitment`, `partnership`) are the two layouts with **no
  footer**. They close on a centred pill instead, and both say so in their `must`.

Three more pieces of furniture arrive with them: the **pill** (a filled accent
finish 67 tall, an outlined finish 71 tall, hugging its 24px label with 25px of
padding), the **corner mark** (a 48px solid square with a 26px square knocked out
of its middle, straddling the corner of a bordered panel), and a **supplied logo
in the header band**.

A carousel is a **recipe** — an ordered list of layout ids, one per LinkedIn post
type (read via `list_carousel_recipes`). The framework
hands you the structure and the brand data; you build the slide.

---

# PRESENTATION CATALOG: 16:9 deck canvas + slide types (source: presentations.md)

---
# Presentation catalog: the GALTON 16:9 deck system.
# REFERENCE KNOWLEDGE, not a generator. Each slide type says what it is FOR
# (intent), how much it may carry (density), when to pick it, and the hard
# limits that keep a deck on-brand. Each variant has an example image under
# public/brand/presentations/. Each slide type also carries its slots, its
# `must` list and, where the design source is a live layout, measured geometry
# in absolute px on the 1920x1080 canvas. Where it is not, rebuild from the
# canvas and the example image, never from a guess.
# Source: the GALTON slide examples and the usage document by the design team
# (2026-10). The 1080x1350 social slide system is a separate catalog (layouts.md).
updated: "2026-10-02"

intro: "Every slide type in a GALTON deck has one job. Pick the type by what the content has to do, not by how it looks: the intent, the density and the limits below decide it."

canvas:
  ratio: "16:9"
  size: "1920x1080"
  padding: 50                        # px, all four sides
  # The content box every element lives inside. Only a full-bleed background
  # (a split half, a dark band, a grid that runs edge to edge) may cross it.
  content: { x: 50, y: 50, w: 1820, h: 980 }
  # The deck palette, by the roles design.md already defines, plus two neutrals
  # the deck design uses for FILLS ONLY. Text is always solid ink or on-light.
  colors:
    dark: "{colors.canvas}"
    on-dark: "{colors.ink}"
    light: "{colors.light-canvas}"
    on-light: "{colors.on-light}"
    accent: "{colors.primary}"
    on-accent: "{colors.on-primary}"
    card-grey: "#F1F1F1"
    line-grey: "#A1A1A1"
  colorRule: "card-grey is a card or panel fill, line-grey is a rule, a grid line, a chart mark or a decorative shape. Neither is ever a TEXT colour: every word on a slide is solid on-dark (white) or on-light (black), including numbers, sources and captions. No opacity on type either."
  surfaces:
    dark: "Black canvas, white type, yellow accent."
    light: "White canvas, black type, yellow accent."
    yellow: "Full yellow canvas, black type. Reserved for emphasis."
    split: "Half black, half white, side by side. For contrast between two sides."
  # Spacing, radius and line tokens, by the names the design source uses.
  spacing: { xs: 8, s: 24, m: 40, l: 60, xl: 80, xxl: 120 }
  radius: { card: 40, pill: 40 }
  lines: { rule: 1, divider: 1 }
  # THE DECK TYPE SET (px on the 1920 canvas; leading is a multiple of size).
  # Separate from the social slide set in layouts.md and from the web tokens.
  # Light roles are UPPERCASE. Regular, Medium and Bold roles are Sentence case.
  type:
    - { role: numeral,         font: "GALTON Light",   size: 300, leading: 1.2, case: UPPERCASE, note: "Step numbers 01 02 03." }
    - { role: banner,          font: "GALTON Light",   size: 250, leading: 1.2, case: UPPERCASE, note: "One word in a full-width yellow bar." }
    - { role: statement,       font: "GALTON Light",   size: 200, leading: 1.2, case: UPPERCASE, note: "The huge statement over half the slide." }
    - { role: display,         font: "GALTON Light",   size: 150, leading: 1.2, case: UPPERCASE, note: "Divider titles, row terms, an archetype name." }
    - { role: title,           font: "GALTON Light",   size: 100, leading: 1.2, case: UPPERCASE, note: "Agenda chapters, a process headline." }
    - { role: heading,         font: "GALTON Light",   size: 70,  leading: 1.2, case: UPPERCASE, note: "THE standard slide title, top-left at x 50, y 50." }
    - { role: figure,          font: "GALTON Light",   size: 70,  leading: 1.2, case: UPPERCASE, note: "A data value inside a card." }
    - { role: statement-xl,    font: "GALTON Bold",    size: 120, leading: 1.2, case: "Sentence case", note: "A bold statement filling the slide." }
    - { role: statement-medium, font: "GALTON Medium", size: 100, leading: 1.2, case: "Sentence case" }
    - { role: statement-bold,  font: "GALTON Bold",    size: 70,  leading: 1.2, case: "Sentence case" }
    - { role: card-heading,    font: "GALTON Regular", size: 50,  leading: 1.2, case: "Sentence case" }
    - { role: lead,            font: "GALTON Medium",  size: 50,  leading: 1.2, case: "Sentence case" }
    - { role: label,           font: "GALTON Medium",  size: 36,  leading: 1.2, case: "Sentence case", note: "Diagram labels, value labels, short descriptions." }
    - { role: body-large,      font: "GALTON Regular", size: 36,  leading: 1.2, case: "Sentence case" }
    - { role: body,            font: "GALTON Regular", size: 32,  leading: 1.2, case: "Sentence case", note: "Running text. Its bold cut (GALTON Bold 32) leads a paragraph or an item." }
    - { role: subhead,         font: "GALTON Medium",  size: 30,  leading: 1.5, case: "Sentence case" }
    - { role: caption,         font: "GALTON Light",   size: 30,  leading: 1.2, case: UPPERCASE }
    - { role: small,           font: "GALTON Medium",  size: 24,  leading: 1.5, case: "Sentence case", note: "Table cells, sources, step bodies. Its Regular cut sets descriptions at leading 1.2." }
    - { role: pill,            font: "GALTON Light",   size: 24,  leading: 1.2, case: UPPERCASE, note: "The label inside a pill." }
    - { role: micro,           font: "GALTON Medium",  size: 16,  leading: 1.5, case: "Sentence case", note: "The smallest size. Card bullets and status lines only." }
    - { role: footer,          font: "GALTON Medium",  size: 18,  leading: 1.2, case: UPPERCASE }
  typeNote: "A box's `size` overrides the size of its role where the design sets its own (a word fitted to the full width, a giant figure). The role still names the font, the case and the colour. Never invent a size that is not written here or on the box."
  # HOW TO READ THE GEOMETRY. Identical to the social layout catalog.
  metrics:
    unit: "px on the 1920x1080 canvas, origin top-left, every x/y absolute"
    textBox: "cap-height trimmed (CSS: text-box-trim: trim-both; text-box-edge: cap alphabetic)"
    capHeight: 0.7
    boxHeight: "(lines - 1) x size x leading + 0.70 x size"
    baseline: "baseline of line k = y + 0.70 x size + (k - 1) x leading x size"
    fallback: "If your tool cannot cap-trim, position each text by that baseline formula. Aligning the line box to y drops the text about 0.25 x size too low."
    sizing: "A text box's w is a wrap width unless the box says hug. Its h is the example copy: yours will be taller or shorter. Never shrink the type to fit a box."
    fill: "A box's `fill` names a colour role in `colors` above (accent, dark, light, card-grey), never a hex of its own."
    repeat: "A box with `repeat` stands for `count` boxes, each moved by dx and dy from the one before."
    verified: "geometry true: every number was measured in the design source, on the variant named by `measuredOn`. type true: the sizes were read off it too. A slide type with no `geometry` is not measured yet: build it from the canvas and its example image and say so in the brand-choices block."
  # Furniture: on every slide, never omitted.
  furniture:
    - "Footer row at the bottom of the content box: © COPYRIGHT 2026 GALTON bottom-left, the page number bottom-right, both in the `footer` role."
    - "On dark structure slides (agenda, dividers, big statements, rows, the dark process) a 1px rule spans the content width 60px above the footer row."
    - "An optional source line sits above the footer whenever the slide shows data, in the `small` role and the solid ink of the surface."
  footer:
    copyright: { x: 50,   y: 1017, w: 300, h: 13, role: footer, sizing: hug, note: "HUG, left edge 50. The cap top of an 18px line is 1017, so the cap bottom lands on 1030, the bottom of the content box." }
    pageNumber: { x: 1820, y: 1017, w: 50,  h: 13, role: footer, sizing: hug, note: "HUG, right edge 1870." }
    rule:      { x: 50,   y: 957,  w: 1820, h: 1, furniture: rule, note: "Only on the slides whose `must` names it." }
  measured: partial
# The order and frequency rules for a whole deck. Each one also sits as a
# `limits` entry on the slide type it constrains.
deckRules:
  - "The deck opens with Cover main and closes with Cover closing. Neither is used anywhere else."
  - "Agenda follows the cover and lists 3 to 6 chapters."
  - "Each chapter opens with a Divider. The yellow divider is for the single most important section."
  - "Statement inside full box is the most important sentence of the deck and appears at most once."
  - "A slide type with a stated item count is never stretched past it. Split the content over two slides instead."

densities:
  - { id: minimal, label: "Minimal", note: "A title or a few words." }
  - { id: low, label: "Low", note: "One sentence or one dominant word." }
  - { id: low-medium, label: "Low to medium", note: "A headline with one emphasised term." }
  - { id: medium, label: "Medium", note: "A headline plus 3 to 6 short items." }
  - { id: medium-high, label: "Medium to high", note: "Several items, each with a line of text." }
  - { id: high, label: "High", note: "Paragraphs, grids or combined blocks." }

categories:
  - { id: structure, name: "Structure", intent: "Opening, closing and the transitions between topics. Use only for those." }
  - { id: text, name: "Text & statements", intent: "Key ideas, quotes, messages and paragraphs." }
  - { id: layout, name: "Layout & grid", intent: "Complex information arranged in clear blocks, columns and boxes." }
  - { id: diagram, name: "Charts, process & diagrams", intent: "Data, sequence, dependencies and relationships." }
  - { id: framework, name: "Frameworks & brand", intent: "Specific marketing and brand methods." }
  - { id: media, name: "Media", intent: "Slides built around a real image." }

slides:
  # ── Structure ─────────────────────────────────────────────
  - id: cover-main
    name: "Cover main"
    category: structure
    intent: "The title slide of the presentation."
    density: minimal
    use: "The very first slide only. Needs the project name, a subtitle and the metadata (date, contacts)."
    limits: ["First slide only.", "Project name, subtitle and metadata are all required."]
    verified: { geometry: false, type: false }
    must:
      - "The GALTON wordmark is the logo file, set huge across the top, never retyped as text."
      - "Project name, subtitle and the metadata block (web, email, phone) are all present."
      - "The date sits under the wordmark at right, led by a yellow arrow."
      - "No page number and no footer row: this slide is the only one without them."
    slots:
      wordmark:  { type: logo, required: true, note: "The white GALTON wordmark from list_assets, scaled to the full content width over the key visual." }
      keyVisual: { type: image, required: false, note: "The yellow and black ribbon image behind the wordmark, top-left, bleeding off the canvas." }
      date:      { type: text, required: true, role: caption, note: "e.g. MAJ 2026, after a yellow arrow icon." }
      project:   { type: text, required: true, role: lead, note: "Bold project or client name, one line." }
      subtitle:  { type: lines, required: true, role: title, maxLines: 2, note: "What the deck is, UPPERCASE Light." }
      metadata:  { type: list, required: true, role: small, count: [2, 3], note: "Label and value pairs: WEB, EMAIL, PHONE, bottom-right." }
    variants:
      - { id: cover-main, surface: dark, image: "https://galton-ai-assets.vercel.app/brand/presentations/cover-main.jpg" }

  - id: cover-closing
    name: "Cover closing"
    category: structure
    intent: "The closing slide, the thank you."
    density: minimal
    use: "The very last slide only."
    limits: ["Last slide only."]
    verified: { geometry: false, type: false }
    must:
      - "The GALTON wordmark top-left as the logo file."
      - "The closing line is one word or two, display size, UPPERCASE."
      - "The contact row under the rule: social icons and handle left, web, email and phone right."
    slots:
      wordmark: { type: logo, required: true }
      keyVisual: { type: image, required: false, note: "The yellow and black ribbon image, top-right." }
      closing:  { type: text, required: true, role: statement, maxWords: 2, note: "THANK YOU, or its translation." }
      contacts: { type: list, required: true, role: footer, count: [3, 5], note: "Handle, web, email, phone in the footer row." }
    variants:
      - { id: cover-closing, surface: dark, image: "https://galton-ai-assets.vercel.app/brand/presentations/cover-closing.jpg" }

  - id: agenda
    name: "Agenda"
    category: structure
    intent: "The contents of the presentation."
    density: medium
    use: "Right after the cover, to summarise the main chapters."
    limits: ["3 to 6 chapters."]
    verified: { geometry: true, type: true }
    must:
      - "Each chapter is one row: the title left and its two-digit number right, both in the `title` role."
      - "A 1px rule runs the full canvas width (x 0 to 1920) under every row but the last."
      - "The footer rule is present."
      - "The numbers are solid white like the titles. The design source sets them grey; do not copy that."
    slots:
      chapters: { type: list, required: true, role: title, count: [3, 6], note: "One row per chapter: TITLE and 01, 02, 03 at right. Keep each title to one line." }
    geometry:
      chapterTitle:  { x: 50,   y: 50,  w: 711,  h: 70, slot: chapters, role: title, sizing: hug, repeat: { count: 5, dx: 0, dy: 196 }, note: "Row pitch 196 for five rows over 854px. For fewer rows keep the pitch and leave the space at the bottom." }
      chapterNumber: { x: 1773, y: 50,  w: 97,   h: 70, slot: chapters, role: title, sizing: hug, repeat: { count: 5, dx: 0, dy: 196 }, note: "HUG, right edge 1870." }
      rowRule:       { x: 0,    y: 160, w: 1920, h: 1,  furniture: rule, repeat: { count: 4, dx: 0, dy: 196 }, note: "Full bleed, 110 under each title row." }
    variants:
      - { id: agenda, surface: dark, image: "https://galton-ai-assets.vercel.app/brand/presentations/agenda.jpg" }

  - id: divider-black
    name: "Divider (black)"
    category: structure
    intent: "The move to a new chapter, as a dark visual break."
    density: minimal
    use: "At every change of topic. Carries only the short section name."
    limits: ["Section name of 1 to 4 words."]
    verified: { geometry: true, type: true }
    must:
      - "The section name is 1 to 4 words in the `display` role, bottom-left, growing upward."
      - "The arrow sits bottom-right, aligned to the bottom of the title."
      - "The footer rule is present."
    slots:
      section: { type: lines, required: true, role: display, maxWords: 4, maxLines: 2 }
      arrow:   { type: icon, required: true, note: "The brand arrow from list_icons, white on dark, pointing up-right." }
    geometry:
      section: { x: 50,   y: 632, w: 950, h: 285, role: display, sizing: wrap, note: "Bottom-anchored: the last line's cap bottom sits at 917, 40 above the footer rule. Extra lines grow upward." }
      arrow:   { x: 1785, y: 832, w: 85, h: 85, note: "The visible arrow, right edge 1870, bottom aligned with the title's last cap line at 917." }
    variants:
      - { id: divider-black, surface: dark, image: "https://galton-ai-assets.vercel.app/brand/presentations/divider-black.jpg" }

  - id: divider-yellow
    name: "Divider (yellow)"
    category: structure
    intent: "A highlighted move to a new or key chapter."
    density: minimal
    use: "For the most important section of the presentation, for example the strategy proposal or the business model."
    limits: ["Section name of 1 to 4 words.", "Only for the key section of the deck."]
    verified: { geometry: true, type: true }
    must:
      - "Same geometry as Divider (black) with the yellow canvas and black type, arrow and rule."
      - "Used once, for the key section of the deck."
    slots:
      section: { type: lines, required: true, role: display, maxWords: 4, maxLines: 2 }
      arrow:   { type: icon, required: true, note: "The brand arrow, black on yellow." }
    geometry:
      section: { x: 50,   y: 632, w: 698, h: 285, role: display, sizing: wrap, note: "Bottom-anchored, as on the black divider." }
      arrow:   { x: 1785, y: 832, w: 85, h: 85, note: "Right edge 1870, bottom 917." }
    variants:
      - { id: divider-yellow, surface: yellow, image: "https://galton-ai-assets.vercel.app/brand/presentations/divider-yellow.jpg" }

  # ── Text & statements ─────────────────────────────────────
  - id: dynamic-tagline
    name: "Dynamic tagline"
    category: text
    intent: "A short, punchy slogan or claim."
    density: low
    use: "To present one main slogan that can be varied."
    limits: ["One sentence."]
    verified: { geometry: true, type: true }
    must:
      - "One sentence: a fixed lead in a yellow pill, a fixed connector, then a column of alternative endings."
      - "Every ending is solid black at full strength. The design source fades the outer words with opacity; never do that, the brand forbids opacity on type."
      - "The ending column is vertically centred on the lead line."
    slots:
      lead:      { type: text, required: true, role: statement-bold, maxWords: 3, note: "Inside a yellow pill, radius 40, 24px horizontal and 40px vertical padding." }
      connector: { type: text, required: true, role: statement-bold, maxWords: 3 }
      endings:   { type: list, required: true, role: statement-bold, count: [5, 9], note: "Two-word endings stacked 40px apart, the middle one aligned with the lead line." }
    geometry:
      lead:      { x: 250, y: 509, w: 437, h: 49, role: statement-bold, sizing: hug, note: "Pill box x 226 y 469 w 485 h 129; text inside it." }
      connector: { x: 735, y: 509, w: 364, h: 49, role: statement-bold, sizing: hug }
      endings:   { x: 1123, y: 153, w: 571, h: 49, role: statement-bold, repeat: { count: 9, dx: 0, dy: 89 } }
    variants:
      - { id: dynamic-tagline, surface: light, image: "https://galton-ai-assets.vercel.app/brand/presentations/dynamic-tagline.jpg" }

  - id: headline-icon
    name: "Headline + icon"
    category: text
    intent: "A strong headline with a visual icon or arrow."
    density: low
    use: "To introduce a key point, with the accent on the icon."
    measuredOn: headline-icon-white
    verified: { geometry: true, type: true }
    must:
      - "The headline is the `statement-xl` role, Sentence case, three lines at most."
      - "One phrase of it sits in a yellow pill."
      - "The visual (an icon, an arrow or a small diagram) sits bottom-right and never overlaps the headline."
    slots:
      headline:  { type: lines, required: true, role: statement-xl, maxLines: 3 }
      highlight: { type: text, required: true, role: statement-xl, note: "One phrase of the headline set in a yellow pill, radius 40, padding 40 by 24." }
      visual:    { type: icon, required: true, note: "Bottom-right. On the white variant it is a small diagram, on the black one the brand arrow in yellow." }
    geometry:
      line1:     { x: 50, y: 50,  w: 1820, h: 84, slot: headline, role: statement-xl, sizing: wrap }
      line2:     { x: 50, y: 214, w: 1499, h: 84, slot: highlight, role: statement-xl, note: "The highlighted line: pill box x 462 y 174 w 1087 h 164." }
      line3:     { x: 50, y: 378, w: 1820, h: 84, slot: headline, role: statement-xl }
      visual:    { x: 1143, y: 534, w: 727, h: 411, radius: 40 }
    variants:
      - { id: headline-icon-black, label: "Black", surface: dark, image: "https://galton-ai-assets.vercel.app/brand/presentations/headline-icon-black.jpg" }
      - { id: headline-icon-white, label: "White", surface: light, image: "https://galton-ai-assets.vercel.app/brand/presentations/headline-icon-white.jpg" }

  - id: big-headline-two-columns
    name: "Big headline + 2 columns"
    category: text
    intent: "A detailed explanation, a manifesto, two columns."
    density: high
    use: "A strong main headline with 2 longer paragraphs of running text, for example a problem description or a manifesto."
    limits: ["Exactly 2 paragraphs."]
    verified: { geometry: true, type: true }
    must:
      - "The big headline is ONE word set across the full content width."
      - "Two columns under it: a bold lead on the left, running body on the right, the right column starting 60px lower."
    slots:
      headline: { type: text, required: true, role: display, maxWords: 1, note: "Sized to fill 1820px: 365px for MANIFEST. Scale to the width, never wrap." }
      lead:     { type: text, required: true, role: body-large, note: "GALTON Bold 36, up to 4 lines." }
      body:     { type: text, required: true, role: body-large, note: "Two paragraphs, GALTON Regular 36, one blank line between." }
    geometry:
      headline: { x: 50,   y: 50,  w: 1820, h: 256, role: display, size: 365, note: "Fit to width." }
      lead:     { x: 170,  y: 389, w: 727,  h: 154, role: body-large }
      body:     { x: 1000, y: 449, w: 823,  h: 498, role: body-large }
    variants:
      - { id: big-headline-two-columns, surface: light, image: "https://galton-ai-assets.vercel.app/brand/presentations/big-headline-two-columns.jpg" }

  - id: big-headline-list-icon
    name: "Big headline + list with icon"
    category: text
    intent: "A dominant idea plus a list."
    density: medium
    use: "A strong headline followed by short points or sentences, led by an icon."
    limits: ["3 to 4 points."]
    verified: { geometry: false, type: false }
    must:
      - "The headline is display size, UPPERCASE, one or two lines."
      - "A yellow arrow circle leads the list; the 3 to 4 lines sit to its right."
    slots:
      headline: { type: lines, required: true, role: display, maxLines: 2 }
      icon:     { type: icon, required: true, note: "The arrow in a yellow circle." }
      items:    { type: list, required: true, role: label, count: [3, 4] }
    variants:
      - { id: big-headline-list-icon, surface: light, image: "https://galton-ai-assets.vercel.app/brand/presentations/big-headline-list-icon.jpg" }

  - id: big-headline-icon-subtitle
    name: "Big headline with icon + subtitle"
    category: text
    intent: "A big headline with a subtitle placed in the corner."
    density: low
    use: "To build contrast: one dominant word or sentence plus a supporting comment in the corner of the slide."
    verified: { geometry: false, type: false }
    must:
      - "The dominant headline top-left with a yellow arrow circle after its last word."
      - "The subtitle bottom-right, UPPERCASE, right-aligned."
    slots:
      headline: { type: lines, required: true, role: display, maxLines: 2 }
      icon:     { type: icon, required: true, note: "The arrow in a yellow circle, at the end of the headline." }
      subtitle: { type: lines, required: true, role: caption, maxLines: 2 }
    variants:
      - { id: big-headline-icon-subtitle, surface: light, image: "https://galton-ai-assets.vercel.app/brand/presentations/big-headline-icon-subtitle.jpg" }

  - id: headline-big-statement-caps
    name: "Headline + big statement caps"
    category: text
    intent: "A dark slide with the main idea and massive type."
    density: low
    use: "A dark accent slide for a key idea the audience has to catch at once."
    verified: { geometry: false, type: false }
    must:
      - "Dark canvas. A short Sentence case headline top-left with a small yellow icon, and one massive word across the bottom."
    slots:
      headline:  { type: lines, required: true, role: lead, maxLines: 2 }
      icon:      { type: icon, required: false, note: "A small yellow arrow circle after the headline." }
      statement: { type: text, required: true, role: statement, maxWords: 1, note: "Fills the full content width at the bottom, sized to the width." }
    variants:
      - { id: headline-big-statement-caps, surface: dark, image: "https://galton-ai-assets.vercel.app/brand/presentations/headline-big-statement-caps.jpg" }

  - id: headline-box
    name: "Headline + box (yellow)"
    category: text
    intent: "A headline with a yellow pill box highlighting one term."
    density: low-medium
    use: "To single out one keyword or term inside the text."
    limits: ["One highlighted term per slide."]
    verified: { geometry: false, type: false }
    must:
      - "One term only sits in a yellow pill, never two."
      - "The black variant sits in a rounded black panel; the white variant on the white canvas."
    slots:
      headline: { type: lines, required: true, role: title, maxLines: 3 }
      term:     { type: text, required: true, role: pill, note: "The highlighted term in a yellow pill, tilted on the black variant." }
      secondary: { type: lines, required: false, role: title, maxLines: 2, note: "A second statement bottom-right (black variant)." }
    variants:
      - { id: headline-box-black, label: "Black", surface: dark, image: "https://galton-ai-assets.vercel.app/brand/presentations/headline-box-black.jpg" }
      - { id: headline-box-white, label: "White", surface: light, image: "https://galton-ai-assets.vercel.app/brand/presentations/headline-box-white.jpg" }

  - id: bullets-arrows
    name: "Headline + bullet points with arrow icons"
    category: text
    intent: "The standard bullet slide, with arrows."
    density: medium-high
    use: "A classic list of separate ideas or arguments."
    limits: ["3 to 5 points."]
    verified: { geometry: true, type: true }
    must:
      - "Each point is a yellow arrow circle with a bold first line and a regular body under it."
      - "3 to 5 points, 40px apart."
    slots:
      heading: { type: text, required: true, role: heading }
      items:   { type: list, required: true, role: body, count: [3, 5], note: "Each item: a GALTON Bold 32 lead line and a body of up to 3 lines in the `body` role." }
    geometry:
      heading: { x: 50,  y: 50,  w: 859,  h: 49,  role: heading, sizing: hug }
      icon:    { x: 50,  y: 219, w: 79,   h: 79,  slot: items, radius: full, fill: "accent", repeat: { count: 4, dx: 0, dy: 176 } }
      item:    { x: 169, y: 219, w: 1076, h: 136, slot: items, role: body, sizing: wrap, repeat: { count: 4, dx: 0, dy: 176 } }
    variants:
      - { id: bullets-arrows, surface: light, image: "https://galton-ai-assets.vercel.app/brand/presentations/bullets-arrows.jpg" }

  - id: headline-paragraphs
    name: "Headline + paragraphs"
    category: text
    intent: "A text slide for running copy."
    density: high
    use: "When the text cannot be broken into bullets and needs paragraphs."
    measuredOn: headline-paragraphs-white
    verified: { geometry: true, type: true }
    must:
      - "Paragraphs, never bullets. The text column stays at most 1078 wide on white."
      - "The black variant is a different composition: the headline itself is the statement (statement-medium), the body in the `lead` role, 1635 wide."
    slots:
      heading: { type: text, required: true, role: heading }
      lead:    { type: text, required: false, role: body, note: "A first paragraph in GALTON Bold 32." }
      body:    { type: text, required: true, role: body, note: "1 to 3 paragraphs, 40px apart." }
    geometry:
      heading: { x: 50, y: 50,  w: 538,  h: 49,  role: heading, sizing: hug }
      lead:    { x: 50, y: 219, w: 1078, h: 98,  role: body, sizing: wrap }
      body:    { x: 50, y: 357, w: 1078, h: 136, role: body, sizing: wrap }
    variants:
      - { id: headline-paragraphs-black, label: "Black", surface: dark, image: "https://galton-ai-assets.vercel.app/brand/presentations/headline-paragraphs-black.jpg" }
      - { id: headline-paragraphs-white, label: "White", surface: light, image: "https://galton-ai-assets.vercel.app/brand/presentations/headline-paragraphs-white.jpg" }

  - id: statement-big-caps
    name: "Statement big caps"
    category: text
    intent: "The emotional peak, a quote or the main thesis."
    density: minimal
    use: "One huge statement across half the slide."
    limits: ["Up to 8 words."]
    verified: { geometry: true, type: true }
    must:
      - "Up to 8 words, centred, in the `statement` role."
      - "The footer rule is present."
    slots:
      statement: { type: lines, required: true, role: statement, maxWords: 8, maxLines: 2 }
    geometry:
      statement: { x: 370, y: 300, w: 1179, h: 380, role: statement, sizing: hug, note: "Centred on the content width. Two lines; the design starts it 250px below the top padding." }
    variants:
      - { id: statement-big-caps, surface: dark, image: "https://galton-ai-assets.vercel.app/brand/presentations/statement-big-caps.jpg" }

  - id: statement-bold
    name: "Statement bold"
    category: text
    intent: "A clean statement on a white background."
    density: low
    use: "An important conclusion or the main argument, put in 1 to 2 sentences."
    limits: ["1 to 2 sentences."]
    verified: { geometry: true, type: true }
    must:
      - "1 to 2 sentences in the `statement-bold` role, one phrase in a yellow pill."
      - "The big yellow arrow circle bottom-right."
    slots:
      statement: { type: lines, required: true, role: statement-bold, maxLines: 4 }
      highlight: { type: text, required: true, role: statement-bold, note: "One phrase in a yellow pill, padding 40 by 24." }
      arrow:     { type: icon, required: true, note: "The arrow in a 255px yellow circle." }
    geometry:
      statement: { x: 50,   y: 50,  w: 1400, h: 49,  role: statement-bold, repeat: { count: 4, dx: 0, dy: 89 }, note: "One line per text box, 40 apart; the pill line is taller." }
      arrow:     { x: 1615, y: 715, w: 255,  h: 255, radius: full, fill: "accent" }
    variants:
      - { id: statement-bold, surface: light, image: "https://galton-ai-assets.vercel.app/brand/presentations/statement-bold.jpg" }

  - id: statement-caps-arrow
    name: "Statement caps + arrow"
    category: text
    intent: "A short statement with a directional arrow."
    density: minimal
    use: "To emphasise a question or a message."
    verified: { geometry: false, type: false }
    must:
      - "A short UPPERCASE statement, display size, and the arrow at the end of its last line."
    slots:
      statement: { type: lines, required: true, role: display, maxWords: 6, maxLines: 3 }
      arrow:     { type: icon, required: true, note: "Yellow circle with the arrow (black variant); on white the term sits in a yellow pill instead." }
    variants:
      - { id: statement-caps-arrow-black, label: "Black", surface: dark, image: "https://galton-ai-assets.vercel.app/brand/presentations/statement-caps-arrow-black.jpg" }
      - { id: statement-caps-arrow-white, label: "White", surface: light, image: "https://galton-ai-assets.vercel.app/brand/presentations/statement-caps-arrow-white.jpg" }

  - id: statement-caps-list
    name: "Statement caps + list (yellow box)"
    category: text
    intent: "A prominent word in a box, plus bullets."
    density: medium
    use: "When the main topic stands in a yellow box and explanatory points follow under it."
    limits: ["3 to 4 points."]
    verified: { geometry: true, type: true }
    must:
      - "One word in a full-width yellow bar, centred, in the `banner` role."
      - "3 to 4 points under it, right-aligned block, each led by a black triangle."
    slots:
      word:  { type: text, required: true, role: banner, maxWords: 1 }
      items: { type: list, required: true, role: body, count: [3, 4], note: "Bold opening phrase allowed inside each item." }
    geometry:
      bar:   { x: 50,  y: 50,  w: 1820, h: 295, slot: word, radius: 40, fill: "accent", note: "Padding 60." }
      word:  { x: 82,  y: 110, w: 1757, h: 175, role: banner }
      items: { x: 605, y: 400, w: 1205, h: 98, role: body, repeat: { count: 4, dx: 0, dy: 138 }, note: "Item text; the triangle sits 24 before it at x 567. Items 40 apart." }
    variants:
      - { id: statement-caps-list, surface: light, image: "https://galton-ai-assets.vercel.app/brand/presentations/statement-caps-list.jpg" }

  - id: statement-centered
    name: "Statement centered"
    category: text
    intent: "A statement centred on the slide."
    density: low
    use: "For an elegant summary, or the text of a mission, vision or purpose."
    verified: { geometry: true, type: true }
    must:
      - "The small UPPERCASE eyebrow centred at the top, the statement centred in the middle."
    slots:
      eyebrow:   { type: text, required: true, role: heading, note: "e.g. MISSION, VISION, PURPOSE." }
      statement: { type: lines, required: true, role: statement-medium, maxLines: 3 }
    geometry:
      eyebrow:   { x: 790, y: 50,  w: 339,  h: 49,  role: heading, sizing: hug, note: "Centred." }
      statement: { x: 320, y: 403, w: 1281, h: 310, role: statement-medium, sizing: hug, note: "Centred on both axes of the free space." }
    variants:
      - { id: statement-centered, surface: light, image: "https://galton-ai-assets.vercel.app/brand/presentations/statement-centered.jpg" }

  - id: statement-full-box
    name: "Statement inside full box (yellow)"
    category: text
    intent: "A statement nobody can miss."
    density: low
    use: "The most important sentence of the whole presentation."
    limits: ["Up to 15 words.", "At most once per deck."]
    verified: { geometry: true, type: true }
    must:
      - "The yellow box fills the content area (1820 x 920, radius 40)."
      - "Up to 15 words, top-left inside an 80px padding. Once per deck."
    slots:
      statement: { type: lines, required: true, role: statement-xl, maxWords: 15, maxLines: 4 }
    geometry:
      box:       { x: 50,  y: 50,  w: 1820, h: 920, radius: 40, fill: "accent" }
      statement: { x: 130, y: 130, w: 1232, h: 372, role: statement-xl, sizing: wrap }
    variants:
      - { id: statement-full-box, surface: yellow, image: "https://galton-ai-assets.vercel.app/brand/presentations/statement-full-box.jpg" }

  - id: statement-values
    name: "Statement with values"
    category: text
    intent: "Values or concepts, put into words."
    density: medium
    use: "To present key words together with their definitions."
    limits: ["3 to 4 key words."]
    verified: { geometry: true, type: true }
    must:
      - "3 to 4 values, each a short UPPERCASE word centred over its own shape."
      - "The shapes are line-grey fills, the labels solid white."
    slots:
      backdrop: { type: text, required: false, note: "The brand word drawn as giant grey letter shapes behind the labels (RIDE in the example)." }
      values:   { type: list, required: true, role: label, count: [3, 4], note: "UPPERCASE in this slide." }
    geometry:
      row:    { x: 50,  y: 200, w: 1820, h: 560, note: "Four cells of widths 443, 354, 508, 362, space-between." }
      value1: { x: 50,  y: 200, w: 443,  h: 560, slot: values, role: label }
      value2: { x: 544, y: 200, w: 354,  h: 560, slot: values, role: label }
      value3: { x: 949, y: 200, w: 508,  h: 560, slot: values, role: label }
      value4: { x: 1508, y: 200, w: 362, h: 560, slot: values, role: label }
    variants:
      - { id: statement-values, surface: dark, image: "https://galton-ai-assets.vercel.app/brand/presentations/statement-values.jpg" }

  # ── Layout & grid ─────────────────────────────────────────
  - id: four-columns
    name: "4 columns"
    category: layout
    intent: "A parallel comparison of 4 items."
    density: medium-high
    use: "When there are exactly 4 equal categories, pillars or descriptions."
    limits: ["Exactly 4 columns."]
    measuredOn: four-columns-grey
    verified: { geometry: true, type: true }
    must:
      - "Exactly 4 cards, 440 x 513, radius 40, 20 apart, bottom-aligned to the content box."
      - "Grey: card-grey fills. Data: the first card yellow, the second black (white type), the rest card-grey, each ending in a figure. White: outlined cards on white."
      - "Card text never runs smaller than the `micro` role."
    slots:
      heading: { type: lines, required: true, role: heading, maxLines: 2 }
      cards:   { type: list, required: true, count: [4, 4], note: "Each card: a heading (card-heading role, up to 3 lines) and up to 3 bullets (micro role, black triangle 14px, 16 gap). Data variant: a status line and a figure (figure role) under a small label." }
    geometry:
      heading:     { x: 50,  y: 50,  w: 492, h: 133, role: heading, sizing: wrap }
      card:        { x: 50,  y: 457, w: 440, h: 513, slot: cards, radius: 40, fill: "card-grey", repeat: { count: 4, dx: 460, dy: 0 }, note: "Padding 40; inner column 359 x 435, heading at top, bullets at bottom." }
      cardHeading: { x: 90,  y: 497, w: 359, h: 105, slot: cards, role: card-heading, repeat: { count: 4, dx: 460, dy: 0 } }
      cardBullets: { x: 120, y: 802, w: 329, h: 130, slot: cards, role: micro, repeat: { count: 4, dx: 460, dy: 0 }, note: "Up to 3 bullets, bottom-aligned in the card, 24 apart; the 14px triangle sits at x 90, 16 before the text." }
    variants:
      - { id: four-columns-data, label: "Data", surface: light, image: "https://galton-ai-assets.vercel.app/brand/presentations/four-columns-data.jpg" }
      - { id: four-columns-grey, label: "Grey", surface: light, image: "https://galton-ai-assets.vercel.app/brand/presentations/four-columns-grey.jpg" }
      - { id: four-columns-white, label: "White", surface: light, image: "https://galton-ai-assets.vercel.app/brand/presentations/four-columns-white.jpg" }

  - id: four-rows
    name: "4 horizontal rows + description"
    category: layout
    intent: "Values or arguments in rows, divided by a rule."
    density: medium
    use: "For 4 separate rows, a big term on the left and its description on the right."
    limits: ["Exactly 4 rows."]
    verified: { geometry: true, type: true }
    must:
      - "Exactly 4 rows: a big term left in the `display` role, its two-line description to the right."
      - "All descriptions start on one shared column at x 1438, not right after each term."
      - "A 1px full-bleed rule under rows 1 to 3, and the footer rule."
    slots:
      rows: { type: list, required: true, count: [4, 4], note: "Term (display, one word) and a 2-line description (label role)." }
    geometry:
      term:        { x: 50,   y: 72,  w: 1188, h: 105, slot: rows, role: display, sizing: hug, repeat: { count: 4, dx: 0, dy: 235 } }
      description: { x: 1438, y: 91,  w: 420,  h: 68,  slot: rows, role: label, repeat: { count: 4, dx: 0, dy: 235 }, note: "Two lines, vertically centred on the term." }
      rowRule:     { x: 0,    y: 240, w: 1920, h: 1,   furniture: rule, repeat: { count: 3, dx: 0, dy: 235 } }
    variants:
      - { id: four-rows, surface: dark, image: "https://galton-ai-assets.vercel.app/brand/presentations/four-rows.jpg" }

  - id: four-quarters
    name: "4 quarters grid"
    category: layout
    intent: "A four-quadrant matrix."
    density: high
    use: "For category entry points (CEPs), a split of situations, or 4 independent scenarios."
    limits: ["Exactly 4 quadrants."]
    verified: { geometry: true, type: true }
    must:
      - "Exactly 4 quarters in a 2 x 2 grid divided by a 1px cross, no outer border."
      - "Each quarter: an UPPERCASE title with one bold word, then up to 4 detail lines led by triangles."
    slots:
      heading:  { type: lines, required: true, role: heading, maxLines: 2 }
      quarters: { type: list, required: true, count: [4, 4], note: "Title in the `caption` role (one word may be GALTON Bold), details in the micro role with a bold label: Situation, Frequency, Competition, Ideas." }
    geometry:
      heading: { x: 50,  y: 50,  w: 729, h: 133, role: heading, sizing: wrap }
      quarter: { x: 50,  y: 307, w: 910, h: 331, slot: quarters, note: "Padding 50 top and bottom, 135 right; quarters 2 and 4 start 40 in from the cross.", repeat: { count: 2, dx: 910, dy: 0 } }
      quarterRow2: { x: 50, y: 638, w: 910, h: 332, slot: quarters, repeat: { count: 2, dx: 910, dy: 0 } }
    variants:
      - { id: four-quarters, surface: light, image: "https://galton-ai-assets.vercel.app/brand/presentations/four-quarters.jpg" }

  - id: big-stat-three-steps
    name: "Big stat + 3 steps process"
    category: layout
    intent: "An argument or statistic as a number, followed by 3 steps."
    density: high
    use: "When one dominant percentage or figure leads the slide and 3 action steps follow under it."
    limits: ["One figure.", "Exactly 3 steps."]
    verified: { geometry: true, type: true }
    must:
      - "A dark band across the top 700px with one giant yellow figure and its explanation; white below with exactly 3 steps joined by arrows."
      - "The figure is the ONE yellow type on the slide."
      - "The source line is solid white. The design source sets it grey; do not copy that."
    slots:
      figure:      { type: number, required: true, note: "GALTON Bold 600, yellow, e.g. 5%." }
      explanation: { type: text, required: true, role: subhead, note: "Up to 6 lines, 561 wide." }
      source:      { type: text, required: false, role: small }
      steps:       { type: list, required: true, role: lead, count: [3, 3], note: "Up to 3 lines each, 304 wide." }
    geometry:
      band:        { x: 0,    y: 0,   w: 1920, h: 700, fill: "dark", note: "Full bleed. Padding 80 top and bottom, 50 sides; content bottom-aligned." }
      figure:      { x: 50,   y: 227, w: 974,  h: 393, role: statement-xl, size: 600 }
      explanation: { x: 1064, y: 227, w: 561,  h: 201, role: subhead }
      source:      { x: 1064, y: 488, w: 561,  h: 53,  role: small }
      step:        { x: 50,   y: 795, w: 304,  h: 155, slot: steps, role: lead, repeat: { count: 3, dx: 758, dy: 0 }, note: "Arrows 205 wide between the steps." }
    variants:
      - { id: big-stat-three-steps, surface: split, image: "https://galton-ai-assets.vercel.app/brand/presentations/big-stat-three-steps.jpg" }

  - id: paragraph-highlight-stat
    name: "Paragraph + highlight box + data stat"
    category: layout
    intent: "Text, a highlight and a number, combined."
    density: high
    use: "To present context, a key term in the yellow box, and a supporting figure with a percentage."
    verified: { geometry: false, type: false }
    must:
      - "Dark canvas: a paragraph top-left, one key phrase in a yellow pill at its end, a yellow arrow circle and a figure bottom-right."
    slots:
      paragraph: { type: lines, required: true, role: lead, maxLines: 4 }
      highlight: { type: text, required: true, role: lead, note: "In a yellow pill." }
      figure:    { type: number, required: true, role: statement, note: "e.g. 5.5 %, with a short caption to its right." }
      source:    { type: text, required: false, role: small }
    variants:
      - { id: paragraph-highlight-stat, surface: dark, image: "https://galton-ai-assets.vercel.app/brand/presentations/paragraph-highlight-stat.jpg" }

  - id: split-screen
    name: "Split screen (B&W)"
    category: layout
    intent: "A black and white contrast split screen."
    density: high
    use: "To compare two sides: before and after, problem and solution, functional and emotional."
    limits: ["Exactly 2 sides."]
    measuredOn: split-screen-bullets
    verified: { geometry: true, type: true }
    must:
      - "Exactly two halves, 960 wide each: white left, black right, edge to edge."
      - "Each half has its own pill label at the top (black pill on white, yellow pill on black)."
      - "The footer splits too: copyright on the white half, page number on the black half."
    slots:
      left:  { type: list, required: true, note: "Pill label (pill role), a question (label role), then 4 to 6 bullets (body-large role)." }
      right: { type: list, required: true, note: "Same anatomy as left." }
    geometry:
      leftHalf:   { x: 0,    y: 0,   w: 960, h: 1080, fill: "light" }
      rightHalf:  { x: 960,  y: 0,   w: 960, h: 1080, fill: "dark" }
      leftPill:   { x: 50,   y: 50,  w: 254, h: 77,  slot: left, radius: 40, note: "Padding 30 by 70." }
      leftQuestion: { x: 50, y: 167, w: 476, h: 25,  slot: left, role: label }
      leftList:   { x: 50,   y: 272, w: 838, h: 393, slot: left, role: body-large, note: "Items 40 apart, triangle 24 before text." }
      rightPill:  { x: 1010, y: 50,  w: 254, h: 77,  slot: right, radius: 40 }
      rightQuestion: { x: 1010, y: 167, w: 522, h: 25, slot: right, role: label }
      rightList:  { x: 1010, y: 272, w: 838, h: 436, slot: right, role: body-large }
    variants:
      - { id: split-screen-text, label: "Text", surface: split, image: "https://galton-ai-assets.vercel.app/brand/presentations/split-screen-text.jpg" }
      - { id: split-screen-bullets, label: "Bullets", surface: split, image: "https://galton-ai-assets.vercel.app/brand/presentations/split-screen-bullets.jpg" }
      - { id: split-screen-data, label: "Data", surface: split, image: "https://galton-ai-assets.vercel.app/brand/presentations/split-screen-data.jpg" }
      - { id: split-screen-list, label: "List", surface: split, image: "https://galton-ai-assets.vercel.app/brand/presentations/split-screen-list.jpg" }

  # ── Charts, process & diagrams ────────────────────────────
  - id: donut-ring
    name: "Donut ring"
    category: diagram
    intent: "A comparison of shares, for example 70% against 30%."
    use: "For a circular ratio indicator of two partial values."
    limits: ["Exactly 2 values."]
    verified: { geometry: false, type: false }
    must:
      - "Dark canvas. One ring split in two arcs: the larger share yellow, the smaller white, in that order clockwise from the top."
      - "The two percentages sit left and right of the ring, each with a short caption."
      - "The source line bottom-right above the footer."
    slots:
      center:  { type: lines, required: true, role: title, maxLines: 3, note: "UPPERCASE claim in the middle of the ring." }
      values:  { type: list, required: true, count: [2, 2], note: "Figure (heading role) and caption (small role) for each share; the two add up to 100." }
      source:  { type: text, required: false, role: small }
    variants:
      - { id: donut-ring, surface: dark, image: "https://galton-ai-assets.vercel.app/brand/presentations/donut-ring.jpg" }

  - id: pie-chart
    name: "Pie chart"
    category: diagram
    intent: "A split of the whole, for example a budget."
    use: "For budget allocation, or the percentage share of markets or areas."
    limits: ["3 to 4 segments."]
    verified: { geometry: true, type: true }
    must:
      - "Text column left, chart card right: a card-grey panel radius 40 holding the pie and its legend."
      - "The slices take the chart palette from get_chart_palette, the yellow slice first and largest."
      - "The legend is a pill-outlined block under the pie, one dot and label per slice."
    slots:
      heading: { type: text, required: true, role: heading }
      body:    { type: text, required: true, role: body, note: "1 to 2 paragraphs, 874 wide." }
      slices:  { type: list, required: true, count: [3, 4], note: "Label (subhead role) and share for each slice." }
    geometry:
      heading: { x: 50,   y: 50,  w: 750, h: 49,  role: heading, sizing: hug }
      body:    { x: 50,   y: 219, w: 874, h: 326, role: body, sizing: wrap }
      card:    { x: 960,  y: 50,  w: 910, h: 923, radius: 40, fill: "card-grey", note: "Padding 50 vertical, 135 horizontal." }
      pie:     { x: 1095, y: 102, w: 640, h: 640 }
      legend:  { x: 1095, y: 782, w: 640, h: 140, radius: 80, note: "1px outline, padding 30 by 60, two columns." }
    variants:
      - { id: pie-chart, surface: light, image: "https://galton-ai-assets.vercel.app/brand/presentations/pie-chart.jpg" }

  - id: three-columns
    name: "3 columns + text"
    category: diagram
    intent: "3 cards or columns."
    use: "For 3 separate offers, packages or option cards."
    limits: ["Exactly 3 cards."]
    verified: { geometry: true, type: true }
    must:
      - "Exactly 3 cards, 596 x 926, radius 40, spread across the content width: black, yellow, card-grey in that order."
      - "Type is white on the black card and black on the other two."
    slots:
      cards: { type: list, required: true, count: [3, 3], note: "Each card: a heading (card-heading role, up to 3 lines) and up to 3 points (subhead role) led by triangles." }
    geometry:
      card:        { x: 50,  y: 50,  w: 596, h: 926, slot: cards, radius: 40, repeat: { count: 3, dx: 612, dy: 0 }, note: "Padding 40 top and sides, 120 bottom; heading at top, points at the bottom." }
      cardHeading: { x: 90,  y: 90,  w: 516, h: 155, slot: cards, role: card-heading, repeat: { count: 3, dx: 612, dy: 0 } }
      cardPoints:  { x: 122, y: 578, w: 481, h: 278, slot: cards, role: subhead, repeat: { count: 3, dx: 612, dy: 0 }, note: "Points 40 apart, triangle 16 before text." }
    variants:
      - { id: three-columns, surface: light, image: "https://galton-ai-assets.vercel.app/brand/presentations/three-columns.jpg" }

  - id: three-data-circles
    name: "3 data circles"
    category: diagram
    intent: "3 dominant KPIs or figures."
    use: "For three big metrics, for example 3M, 480K, 80K."
    limits: ["Exactly 3 metrics."]
    verified: { geometry: false, type: false }
    must:
      - "Dark canvas. Three circles in a row: outlined, yellow filled (the middle, the headline metric), outlined."
      - "Each circle holds one big figure and a short caption; a label sits under each circle above the rule."
    slots:
      heading: { type: text, required: true, role: heading }
      metrics: { type: list, required: true, count: [3, 3], note: "Figure (statement role, short: 3M, 480K), caption (small role), label under the circle." }
    variants:
      - { id: three-data-circles, surface: dark, image: "https://galton-ai-assets.vercel.app/brand/presentations/three-data-circles.jpg" }

  - id: five-items-list
    name: "5 items list"
    category: diagram
    intent: "A vertical step list."
    use: "For 5 sequential points with labels. Works with fewer."
    limits: ["Never more than 5 items."]
    verified: { geometry: true, type: true }
    must:
      - "An intro paragraph left, the list right: each row a yellow label block joined to a card-grey description block, 8 apart."
      - "Never more than 5 rows. Fewer is fine: drop rows from the bottom."
    slots:
      heading: { type: lines, required: true, role: heading, maxLines: 2 }
      intro:   { type: text, required: true, role: body, note: "Up to 7 lines, 559 wide." }
      rows:    { type: list, required: true, count: [1, 5], note: "Label (subhead, one word in the yellow block), question (subhead) and example (small) in the grey block." }
    geometry:
      heading:  { x: 50,  y: 50,  w: 492, h: 133, role: heading, sizing: wrap }
      intro:    { x: 50,  y: 257, w: 559, h: 212, role: body, sizing: wrap }
      rowLabel: { x: 921, y: 257, w: 217, h: 139, slot: rows, radius: 40, fill: "accent", repeat: { count: 5, dx: 0, dy: 147 } }
      rowBody:  { x: 1138, y: 257, w: 732, h: 139, slot: rows, fill: "card-grey", note: "Radius 0 40 40 0. Padding 39 top, 50 left.", repeat: { count: 5, dx: 0, dy: 147 } }
    variants:
      - { id: five-items-list, surface: light, image: "https://galton-ai-assets.vercel.app/brand/presentations/five-items-list.jpg" }

  - id: concentric-arcs
    name: "Concentric arcs"
    category: diagram
    intent: "Layered half circles."
    use: "For fulfilling goals or a hierarchy, for example mission, vision, purpose."
    verified: { geometry: true, type: true }
    must:
      - "Three nested half-rings from the bottom left: the outer two outlined, the inner one yellow."
      - "Each ring carries its label inside; a 1px leader line runs from it to its description on the right."
    slots:
      heading: { type: lines, required: true, role: heading, maxLines: 2 }
      levels:  { type: list, required: true, count: [3, 3], note: "Outer to inner: label (label role, UPPERCASE) and a 2-line description (body role)." }
    geometry:
      heading:     { x: 50,   y: 50,  w: 394, h: 133, role: heading, sizing: wrap }
      arcs:        { x: 50,   y: 408, w: 944, h: 472, note: "Outer radius 472, middle 312, inner half-disc 260 x 130." }
      label1:      { x: 468,  y: 468, w: 107, h: 25, slot: levels, role: label }
      label2:      { x: 473,  y: 631, w: 97,  h: 25, slot: levels, role: label }
      label3:      { x: 431,  y: 815, w: 181, h: 25, slot: levels, role: label }
      description: { x: 1345, y: 450, w: 392, h: 60, slot: levels, role: body, repeat: { count: 3, dx: 0, dy: 164 }, note: "Leader lines 650 long end 40 before the text." }
    variants:
      - { id: concentric-arcs, surface: light, image: "https://galton-ai-assets.vercel.app/brand/presentations/concentric-arcs.jpg" }

  - id: intersecting-circles
    name: "Intersecting circles"
    category: diagram
    intent: "2 overlapping circles with no text in the overlap."
    use: "A visual hint of two connected topics."
    limits: ["Exactly 2 circles.", "No text in the overlap."]
    verified: { geometry: false, type: false }
    must:
      - "Dark canvas. Two large outlined circles overlapping in the middle, each with its label; nothing in the overlap."
      - "The title runs across the top as one line, with its first word in yellow."
    slots:
      title:  { type: text, required: true, role: display, note: "One line, first word yellow." }
      labels: { type: list, required: true, count: [2, 2], role: title }
    variants:
      - { id: intersecting-circles, surface: dark, image: "https://galton-ai-assets.vercel.app/brand/presentations/intersecting-circles.jpg" }

  - id: pyramid-pillars
    name: "Pyramid pillars"
    category: diagram
    intent: "A pyramid of foundational pillars."
    use: "For a three-level architecture or strategy."
    limits: ["Exactly 3 levels."]
    verified: { geometry: true, type: true }
    must:
      - "Exactly 3 levels, top to bottom: yellow apex, then two card-grey tiers getting lighter, each label centred in its tier."
      - "The headline sits top-left beside the pyramid."
    slots:
      headline: { type: lines, required: true, role: statement-medium, maxLines: 2, note: "GALTON Medium 200 Sentence case in the design: set the size on the box." }
      levels:   { type: list, required: true, role: label, count: [3, 3], note: "UPPERCASE labels, apex first." }
    geometry:
      headline: { x: 50,  y: 50, w: 1158, h: 380, role: statement-medium, size: 200 }
      pyramid:  { x: 916, y: 77, w: 954,  h: 953, note: "Apex triangle, then two trapezoids; label tops at about y 445, 672 and 953 on the tier centres." }
    variants:
      - { id: pyramid-pillars, surface: light, image: "https://galton-ai-assets.vercel.app/brand/presentations/pyramid-pillars.jpg" }

  - id: venn
    name: "Venn"
    category: diagram
    intent: "A Venn diagram, the overlap of values or groups."
    use: "When talking about the synergy or overlap of 2 to 3 concepts."
    limits: ["2 to 3 concepts."]
    verified: { geometry: false, type: false }
    must:
      - "Dark canvas. Outlined circles; the overlap is the one yellow fill and holds the synthesis."
      - "2 to 3 concepts. On the 3-circle variant each circle carries a title and up to 4 lines."
    slots:
      heading:  { type: text, required: false, role: heading }
      concepts: { type: list, required: true, count: [2, 3], note: "Title (small role, UPPERCASE) and up to 4 lines (micro role) per circle." }
      overlap:  { type: text, required: true, note: "The synthesis in the yellow overlap." }
    variants:
      - { id: venn-three-circles, label: "3 circles", surface: dark, image: "https://galton-ai-assets.vercel.app/brand/presentations/venn-three-circles.jpg" }
      - { id: venn-text, label: "With text", surface: dark, image: "https://galton-ai-assets.vercel.app/brand/presentations/venn-text.jpg" }

  - id: process-three-steps
    name: "Process: 3 steps"
    category: diagram
    intent: "A 3 step process or a communication funnel."
    use: "When the content is a sequence: phase 1, phase 2, phase 3."
    limits: ["Exactly 3 steps."]
    measuredOn: process-three-steps-black
    verified: { geometry: true, type: true }
    must:
      - "Exactly 3 steps left to right: a numeral 01 02 03 joined by 1px lines, a title, then a body."
      - "Black and White share this geometry. Funnel and Funnel data are a different composition: three stacked bands narrowing downward, the right column carrying the data per band."
      - "The footer rule is present on the dark variants."
    slots:
      headline: { type: text, required: true, role: title }
      steps:    { type: list, required: true, count: [3, 3], note: "Numeral (numeral role), title (subhead, up to 2 lines), body (small, up to 5 lines)." }
    geometry:
      headline: { x: 50,   y: 50,  w: 1635, h: 70,  role: title, sizing: wrap }
      numeral:  { x: 50,   y: 270, w: 293,  h: 210, slot: steps, role: numeral, sizing: hug, note: "Steps start at x 50, 714, 1379." }
      title:    { x: 50,   y: 520, w: 633,  h: 66,  slot: steps, role: subhead, note: "Width 633, 633, 464." }
      body:     { x: 50,   y: 646, w: 491,  h: 161, slot: steps, role: small }
    variants:
      - { id: process-three-steps-black, label: "Black", surface: dark, image: "https://galton-ai-assets.vercel.app/brand/presentations/process-three-steps-black.jpg" }
      - { id: process-three-steps-white, label: "White", surface: light, image: "https://galton-ai-assets.vercel.app/brand/presentations/process-three-steps-white.jpg" }
      - { id: process-funnel, label: "Funnel", surface: dark, image: "https://galton-ai-assets.vercel.app/brand/presentations/process-funnel.jpg" }
      - { id: process-funnel-data, label: "Funnel data", surface: dark, image: "https://galton-ai-assets.vercel.app/brand/presentations/process-funnel-data.jpg" }

  # ── Frameworks & brand ────────────────────────────────────
  - id: swot
    name: "SWOT"
    category: framework
    intent: "A SWOT analysis, one quadrant highlighted per slide."
    use: "Exclusively for presenting a SWOT analysis and its 4 parts."
    limits: ["SWOT only, never another four-part model."]
    verified: { geometry: false, type: false }
    must:
      - "One slide per quadrant: the S W O T letters across the top, the active letter on a yellow rounded square."
      - "The whole slide sits in a 1px outlined panel, radius 40."
      - "Four groups in a 2 x 2 grid under the letters, each a label and up to 3 points."
    slots:
      active: { type: enum, required: true, values: [strength, weakness, opportunity, threat], note: "Which letter is highlighted: pick the variant." }
      groups: { type: list, required: true, count: [2, 4], note: "Label (small role) and up to 3 points (micro role) each." }
    variants:
      - { id: swot-strength, label: "Strength", surface: light, image: "https://galton-ai-assets.vercel.app/brand/presentations/swot-strength.jpg" }
      - { id: swot-weakness, label: "Weakness", surface: light, image: "https://galton-ai-assets.vercel.app/brand/presentations/swot-weakness.jpg" }
      - { id: swot-opportunity, label: "Opportunity", surface: light, image: "https://galton-ai-assets.vercel.app/brand/presentations/swot-opportunity.jpg" }
      - { id: swot-threat, label: "Threat", surface: light, image: "https://galton-ai-assets.vercel.app/brand/presentations/swot-threat.jpg" }

  - id: brand-archetype
    name: "Brand archetype"
    category: framework
    intent: "The brand archetype, as a detail or on the wheel."
    use: "When defining a brand, its archetypes and its personality."
    measuredOn: brand-archetype-detail
    verified: { geometry: true, type: true }
    must:
      - "Detail: the archetype name in the `display` role, its essence as a quote in a yellow box, three columns of motivations under it, and an outlined side card with traits and reference brands."
      - "Wheel: the twelve-archetype wheel centred, the brand's archetypes filled, the inner ring yellow, the shares at left and right."
      - "Spell the archetype correctly (Caregiver). The design source has a typo."
    slots:
      name:     { type: text, required: true, role: display, maxWords: 1 }
      quote:    { type: lines, required: true, role: statement-bold, maxLines: 2 }
      columns:  { type: list, required: true, count: [3, 3], note: "Label (subhead, UPPERCASE) and up to 4 points (micro role)." }
      traits:   { type: list, required: true, role: label, count: [2, 4] }
      brands:   { type: logo, required: false, note: "Up to 3 reference brand logos, supplied." }
    geometry:
      name:   { x: 50,   y: 50,  w: 843, h: 105, role: display, sizing: hug }
      quote:  { x: 50,   y: 236, w: 990, h: 293, radius: 40, fill: "accent", note: "Box with 40 by 80 padding; the quote text at x 91, y 316, 949 wide, role statement-bold." }
      columns: { x: 50,  y: 610, w: 990, h: 141, note: "Three columns, space-between; label then points 40 below." }
      sideCard: { x: 1129, y: 276, w: 741, h: 535, radius: 40, note: "1px outline, padding 40, 80 bottom." }
    variants:
      - { id: brand-archetype-detail, label: "Detail", surface: light, image: "https://galton-ai-assets.vercel.app/brand/presentations/brand-archetype-detail.jpg" }
      - { id: brand-archetype-wheel, label: "Wheel", surface: light, image: "https://galton-ai-assets.vercel.app/brand/presentations/brand-archetype-wheel.jpg" }

  - id: brand-purpose-grid
    name: "Brand purpose grid"
    category: framework
    intent: "A grid of example brands and what they contribute."
    use: "For a grid of brand examples and their purpose."
    verified: { geometry: true, type: true }
    must:
      - "A full-bleed 2 x 3 grid of cells divided by 1px line-grey rules."
      - "Each cell: a brand image or logo, then the purpose word (heading role) and its category under it."
      - "The category is solid black. The design source sets it grey; do not copy that."
    slots:
      cells: { type: list, required: true, count: [4, 6], note: "Logo or image 330 x 180, title (heading), subtitle (subhead)." }
    geometry:
      cell:     { x: 0,   y: 0,   w: 960, h: 323, slot: cells, note: "Full bleed: two columns of 960, three rows over the 970 above the footer.", repeat: { count: 2, dx: 960, dy: 0 } }
      image:    { x: 51,  y: 69,  w: 330, h: 180, slot: cells, note: "Vertically centred on the title and subtitle block." }
      title:    { x: 441, y: 112, w: 363, h: 49,  slot: cells, role: heading }
      subtitle: { x: 441, y: 185, w: 363, h: 21,  slot: cells, role: subhead }
    variants:
      - { id: brand-purpose-grid, surface: light, image: "https://galton-ai-assets.vercel.app/brand/presentations/brand-purpose-grid.jpg" }

  - id: competitor-analysis
    name: "Competitor analysis"
    category: framework
    intent: "A table comparing competitors."
    use: "For a tabular comparison with the competition."
    verified: { geometry: true, type: true }
    must:
      - "A table across the content width: column headers, a 1px rule, then one row per competitor with a 1px rule under it."
      - "Visual columns use marks, not words: colour dots, a check for active campaigns, social icons in a row."
      - "The footnote top-right is solid black. The design source sets it grey; do not copy that."
    slots:
      heading:  { type: text, required: true, role: heading }
      footnote: { type: text, required: false, role: small }
      columns:  { type: list, required: true, count: [3, 6], role: small, note: "Header labels." }
      rows:     { type: list, required: true, count: [3, 7], note: "Name (small role) and description (small Regular, 2 lines) plus the mark columns." }
    geometry:
      heading:  { x: 50,   y: 50,  w: 543,  h: 49, role: heading, sizing: hug }
      footnote: { x: 1327, y: 50,  w: 543,  h: 17, role: small, note: "Right-aligned." }
      header:   { x: 50,   y: 219, w: 1820, h: 41, note: "Column x: 50, 280, 1074, 1295, 1612." }
      rows:     { x: 50,   y: 300, w: 1820, h: 540, slot: rows, note: "Rows of 90: 24 top padding, cells, 24 to the rule." }
    variants:
      - { id: competitor-analysis, surface: light, image: "https://galton-ai-assets.vercel.app/brand/presentations/competitor-analysis.jpg" }

  - id: tone-of-voice
    name: "Tone of voice (sliders)"
    category: framework
    intent: "Communication scales set on sliders."
    use: "For setting the scales of communication, for example formal against informal."
    verified: { geometry: true, type: true }
    must:
      - "Up to 7 sliders, 80 apart: a pole label left, a 1272px track with ticks, a yellow knob, the opposite pole right."
      - "The knob is a yellow pill 65 x 40 with a 1px black outline."
    slots:
      heading: { type: text, required: true, role: heading }
      scales:  { type: list, required: true, count: [3, 7], note: "Left pole, right pole (caption role) and a position from 0 to 100." }
    geometry:
      heading:   { x: 50,   y: 50,  w: 538,  h: 49, role: heading, sizing: hug }
      leftPole:  { x: 50,   y: 188, w: 245,  h: 21, slot: scales, role: caption, repeat: { count: 7, dx: 0, dy: 120 } }
      track:     { x: 324,  y: 178, w: 1272, h: 40, slot: scales, note: "Knob at x 921 on the track in the example; place it by the scale value.", repeat: { count: 7, dx: 0, dy: 120 } }
      rightPole: { x: 1625, y: 188, w: 245,  h: 21, slot: scales, role: caption, repeat: { count: 7, dx: 0, dy: 120 } }
    variants:
      - { id: tone-of-voice, surface: light, image: "https://galton-ai-assets.vercel.app/brand/presentations/tone-of-voice.jpg" }

  # ── Media ─────────────────────────────────────────────────
  - id: content-image
    name: "Content + image"
    category: media
    intent: "A visual sample, a script next to a photograph."
    use: "When the slide carries a real product photo, a moodboard or a visual example."
    verified: { geometry: true, type: true }
    must:
      - "Text column left (559 wide), image right (1168 x 920, radius 40)."
      - "A yellow arrow circle sits at the bottom of the text column."
    slots:
      heading: { type: lines, required: true, role: heading, maxLines: 2 }
      body:    { type: text, required: true, role: body, note: "Labelled paragraphs allowed (VISUAL:, VOICEOVER: in GALTON Bold 32)." }
      image:   { type: image, required: true, note: "A real photo, cover-fitted, radius 40." }
    geometry:
      heading: { x: 50,  y: 50,  w: 289,  h: 133, role: heading, sizing: wrap }
      body:    { x: 50,  y: 263, w: 559,  h: 478, role: body, sizing: wrap }
      arrow:   { x: 534, y: 895, w: 75,   h: 75,  radius: full, fill: "accent" }
      image:   { x: 702, y: 50,  w: 1168, h: 920, radius: 40 }
    variants:
      - { id: content-image, surface: light, image: "https://galton-ai-assets.vercel.app/brand/presentations/content-image.jpg" }
---

## How to build a GALTON deck

Choose each slide by its job. Structure slides frame the deck, text slides carry
the ideas, layout and diagram slides organise information, and framework slides
are reserved for the methods they are named after.

Build a slide from its spec, not by tracing its picture: the slots say what
goes in, the type roles say how it is set, the measured boxes say where. Where a
slide type has no measured geometry, rebuild it from the canvas and its example
image and say so. Never invent a colour, a font, a size or a new slide type, and
never set a word in grey or at reduced opacity, whatever an example shows.

---

# ASSETS + ICONS: every hotlinkable file (source: https://galton-ai-assets.vercel.app/brand.json)

Hotlink these by the absolute URL below. Never download them, never relativise the path, never retype a wordmark as text.

Reading this from the unzipped offline package? Then every URL below is also here as a file: drop the origin and you have its path, so `https://galton-ai-assets.vercel.app/brand/X` is `./brand/X`. Same file, not a copy. Use it when the machine has no network.

## Logos
- primary lockup (dark surfaces): https://galton-ai-assets.vercel.app/brand/logos/galton-wordmark-white-tagline-tight.png
- primary lockup (light surfaces): https://galton-ai-assets.vercel.app/brand/logos/galton-wordmark-black-tagline-tight.png
- Symbol — the “G”, on dark: https://galton-ai-assets.vercel.app/brand/logos/galton-symbol-white.svg (White on dark)
- Symbol — the “G”, on light: https://galton-ai-assets.vercel.app/brand/logos/galton-symbol-black.svg (Black on light)
- Symbol — the “G”, on primary: https://galton-ai-assets.vercel.app/brand/logos/galton-symbol.svg (Black on primary)
- Wordmark — “GALTON”, on dark: https://galton-ai-assets.vercel.app/brand/logos/galton-wordmark-white.svg (White on dark)
- Wordmark — “GALTON”, on light: https://galton-ai-assets.vercel.app/brand/logos/galton-wordmark-black.svg (Black on light)
- Wordmark — “GALTON”, on primary: https://galton-ai-assets.vercel.app/brand/logos/galton-wordmark.svg (Black on primary)

## Typeface
- family: GALTON; stack: GALTON, Montserrat, ui-sans-serif, system-ui, sans-serif
- webfont file: https://galton-ai-assets.vercel.app/brand/fonts/GaltonVariable.woff2
- @font-face: @font-face { font-family: "GALTON"; src: url("https://galton-ai-assets.vercel.app/brand/fonts/GaltonVariable.woff2") format("woff2-variations"); font-weight: 100 900; font-style: normal; font-display: swap; /* Vertical-metric correction — KEEP these three lines. The variable woff2 sets USE_TYPO_METRICS with an asymmetric 750/-250 typo ascent/descent, which floats UPPERCASE labels ~0.1em high in tight (line-height:1) boxes like buttons and badges. These overrides pin the webfont to the desktop masters' metrics (ascent−descent ≈ the cap height) so text centres correctly everywhere — no per-button padding hacks needed. */ ascent-override: 96%; descent-override: 24%; line-gap-override: 0%; }

## Fonts
- GALTON Variable: https://galton-ai-assets.vercel.app/brand/fonts/GaltonVariable.woff2 (The web font — variable, covers every weight. Embed this and nothing else.)

## Favicons
- Favicon 32: https://galton-ai-assets.vercel.app/brand/icons/galton-favicon-32x32.png (Browser-tab favicon.)
- Favicon 192: https://galton-ai-assets.vercel.app/brand/icons/galton-favicon-192x192.png (Android / high-DPI.)
- Apple touch: https://galton-ai-assets.vercel.app/brand/icons/galton-favicon-180x180.png (Apple touch icon (iOS home screen).)

## Sound (MP3)
> Hotlink by URL like every other asset. The offline package carries only the tracks marked (offline); the rest need the network.
- Sound logo (offline): https://galton-ai-assets.vercel.app/brand/sound/galton-sound-logo.mp3 (3 s)
- Emergence: https://galton-ai-assets.vercel.app/brand/sound/galton-ambient-emergence.mp3 (276 s)
- Anthem: https://galton-ai-assets.vercel.app/brand/sound/galton-anthem.mp3 (176 s, 120 BPM, spoken words)
- Anthem, instrumental: https://galton-ai-assets.vercel.app/brand/sound/galton-anthem-instrumental.mp3 (176 s, 120 BPM)
- Anthem, 30 s: https://galton-ai-assets.vercel.app/brand/sound/galton-anthem-30s.mp3 (32 s, 120 BPM)
- Anthem, 30 s with voice: https://galton-ai-assets.vercel.app/brand/sound/galton-anthem-30s-voice.mp3 (30 s, 120 BPM, spoken words)
- Anthem, short: https://galton-ai-assets.vercel.app/brand/sound/galton-anthem-15s.mp3 (24 s, 120 BPM)
- Anthem, 15 s with voice: https://galton-ai-assets.vercel.app/brand/sound/galton-anthem-15s-voice.mp3 (15 s, 120 BPM, spoken words)
- Loop: https://galton-ai-assets.vercel.app/brand/sound/galton-loop.mp3 (64 s, 120 BPM, loops)
- Ambient 3: https://galton-ai-assets.vercel.app/brand/sound/galton-ambient-3.mp3 (75 s, 102 BPM, loops)
- Ambient 4: https://galton-ai-assets.vercel.app/brand/sound/galton-ambient-4.mp3 (64 s, 120 BPM, loops)
- Ambient 5: https://galton-ai-assets.vercel.app/brand/sound/galton-ambient-5.mp3 (96 s, 120 BPM, loops)
- Ambient 5, no bleep: https://galton-ai-assets.vercel.app/brand/sound/galton-ambient-5-no-bleep.mp3 (96 s, 120 BPM, loops)
- Ambient 5, no beat: https://galton-ai-assets.vercel.app/brand/sound/galton-ambient-5-no-beat.mp3 (96 s, 120 BPM, loops)

## Presentation slide examples (JPG, 1920x1080)
> Reference pictures of each 16:9 slide type and variant. Build from the spec, not by tracing the picture.
- Cover main `cover-main`: https://galton-ai-assets.vercel.app/brand/presentations/cover-main.jpg
- Cover closing `cover-closing`: https://galton-ai-assets.vercel.app/brand/presentations/cover-closing.jpg
- Agenda `agenda`: https://galton-ai-assets.vercel.app/brand/presentations/agenda.jpg
- Divider (black) `divider-black`: https://galton-ai-assets.vercel.app/brand/presentations/divider-black.jpg
- Divider (yellow) `divider-yellow`: https://galton-ai-assets.vercel.app/brand/presentations/divider-yellow.jpg
- Dynamic tagline `dynamic-tagline`: https://galton-ai-assets.vercel.app/brand/presentations/dynamic-tagline.jpg
- Headline + icon (Black) `headline-icon-black`: https://galton-ai-assets.vercel.app/brand/presentations/headline-icon-black.jpg
- Headline + icon (White) `headline-icon-white`: https://galton-ai-assets.vercel.app/brand/presentations/headline-icon-white.jpg
- Big headline + 2 columns `big-headline-two-columns`: https://galton-ai-assets.vercel.app/brand/presentations/big-headline-two-columns.jpg
- Big headline + list with icon `big-headline-list-icon`: https://galton-ai-assets.vercel.app/brand/presentations/big-headline-list-icon.jpg
- Big headline with icon + subtitle `big-headline-icon-subtitle`: https://galton-ai-assets.vercel.app/brand/presentations/big-headline-icon-subtitle.jpg
- Headline + big statement caps `headline-big-statement-caps`: https://galton-ai-assets.vercel.app/brand/presentations/headline-big-statement-caps.jpg
- Headline + box (yellow) (Black) `headline-box-black`: https://galton-ai-assets.vercel.app/brand/presentations/headline-box-black.jpg
- Headline + box (yellow) (White) `headline-box-white`: https://galton-ai-assets.vercel.app/brand/presentations/headline-box-white.jpg
- Headline + bullet points with arrow icons `bullets-arrows`: https://galton-ai-assets.vercel.app/brand/presentations/bullets-arrows.jpg
- Headline + paragraphs (Black) `headline-paragraphs-black`: https://galton-ai-assets.vercel.app/brand/presentations/headline-paragraphs-black.jpg
- Headline + paragraphs (White) `headline-paragraphs-white`: https://galton-ai-assets.vercel.app/brand/presentations/headline-paragraphs-white.jpg
- Statement big caps `statement-big-caps`: https://galton-ai-assets.vercel.app/brand/presentations/statement-big-caps.jpg
- Statement bold `statement-bold`: https://galton-ai-assets.vercel.app/brand/presentations/statement-bold.jpg
- Statement caps + arrow (Black) `statement-caps-arrow-black`: https://galton-ai-assets.vercel.app/brand/presentations/statement-caps-arrow-black.jpg
- Statement caps + arrow (White) `statement-caps-arrow-white`: https://galton-ai-assets.vercel.app/brand/presentations/statement-caps-arrow-white.jpg
- Statement caps + list (yellow box) `statement-caps-list`: https://galton-ai-assets.vercel.app/brand/presentations/statement-caps-list.jpg
- Statement centered `statement-centered`: https://galton-ai-assets.vercel.app/brand/presentations/statement-centered.jpg
- Statement inside full box (yellow) `statement-full-box`: https://galton-ai-assets.vercel.app/brand/presentations/statement-full-box.jpg
- Statement with values `statement-values`: https://galton-ai-assets.vercel.app/brand/presentations/statement-values.jpg
- 4 columns (Data) `four-columns-data`: https://galton-ai-assets.vercel.app/brand/presentations/four-columns-data.jpg
- 4 columns (Grey) `four-columns-grey`: https://galton-ai-assets.vercel.app/brand/presentations/four-columns-grey.jpg
- 4 columns (White) `four-columns-white`: https://galton-ai-assets.vercel.app/brand/presentations/four-columns-white.jpg
- 4 horizontal rows + description `four-rows`: https://galton-ai-assets.vercel.app/brand/presentations/four-rows.jpg
- 4 quarters grid `four-quarters`: https://galton-ai-assets.vercel.app/brand/presentations/four-quarters.jpg
- Big stat + 3 steps process `big-stat-three-steps`: https://galton-ai-assets.vercel.app/brand/presentations/big-stat-three-steps.jpg
- Paragraph + highlight box + data stat `paragraph-highlight-stat`: https://galton-ai-assets.vercel.app/brand/presentations/paragraph-highlight-stat.jpg
- Split screen (B&W) (Text) `split-screen-text`: https://galton-ai-assets.vercel.app/brand/presentations/split-screen-text.jpg
- Split screen (B&W) (Bullets) `split-screen-bullets`: https://galton-ai-assets.vercel.app/brand/presentations/split-screen-bullets.jpg
- Split screen (B&W) (Data) `split-screen-data`: https://galton-ai-assets.vercel.app/brand/presentations/split-screen-data.jpg
- Split screen (B&W) (List) `split-screen-list`: https://galton-ai-assets.vercel.app/brand/presentations/split-screen-list.jpg
- Donut ring `donut-ring`: https://galton-ai-assets.vercel.app/brand/presentations/donut-ring.jpg
- Pie chart `pie-chart`: https://galton-ai-assets.vercel.app/brand/presentations/pie-chart.jpg
- 3 columns + text `three-columns`: https://galton-ai-assets.vercel.app/brand/presentations/three-columns.jpg
- 3 data circles `three-data-circles`: https://galton-ai-assets.vercel.app/brand/presentations/three-data-circles.jpg
- 5 items list `five-items-list`: https://galton-ai-assets.vercel.app/brand/presentations/five-items-list.jpg
- Concentric arcs `concentric-arcs`: https://galton-ai-assets.vercel.app/brand/presentations/concentric-arcs.jpg
- Intersecting circles `intersecting-circles`: https://galton-ai-assets.vercel.app/brand/presentations/intersecting-circles.jpg
- Pyramid pillars `pyramid-pillars`: https://galton-ai-assets.vercel.app/brand/presentations/pyramid-pillars.jpg
- Venn (3 circles) `venn-three-circles`: https://galton-ai-assets.vercel.app/brand/presentations/venn-three-circles.jpg
- Venn (With text) `venn-text`: https://galton-ai-assets.vercel.app/brand/presentations/venn-text.jpg
- Process: 3 steps (Black) `process-three-steps-black`: https://galton-ai-assets.vercel.app/brand/presentations/process-three-steps-black.jpg
- Process: 3 steps (White) `process-three-steps-white`: https://galton-ai-assets.vercel.app/brand/presentations/process-three-steps-white.jpg
- Process: 3 steps (Funnel) `process-funnel`: https://galton-ai-assets.vercel.app/brand/presentations/process-funnel.jpg
- Process: 3 steps (Funnel data) `process-funnel-data`: https://galton-ai-assets.vercel.app/brand/presentations/process-funnel-data.jpg
- SWOT (Strength) `swot-strength`: https://galton-ai-assets.vercel.app/brand/presentations/swot-strength.jpg
- SWOT (Weakness) `swot-weakness`: https://galton-ai-assets.vercel.app/brand/presentations/swot-weakness.jpg
- SWOT (Opportunity) `swot-opportunity`: https://galton-ai-assets.vercel.app/brand/presentations/swot-opportunity.jpg
- SWOT (Threat) `swot-threat`: https://galton-ai-assets.vercel.app/brand/presentations/swot-threat.jpg
- Brand archetype (Detail) `brand-archetype-detail`: https://galton-ai-assets.vercel.app/brand/presentations/brand-archetype-detail.jpg
- Brand archetype (Wheel) `brand-archetype-wheel`: https://galton-ai-assets.vercel.app/brand/presentations/brand-archetype-wheel.jpg
- Brand purpose grid `brand-purpose-grid`: https://galton-ai-assets.vercel.app/brand/presentations/brand-purpose-grid.jpg
- Competitor analysis `competitor-analysis`: https://galton-ai-assets.vercel.app/brand/presentations/competitor-analysis.jpg
- Tone of voice (sliders) `tone-of-voice`: https://galton-ai-assets.vercel.app/brand/presentations/tone-of-voice.jpg
- Content + image `content-image`: https://galton-ai-assets.vercel.app/brand/presentations/content-image.jpg

## Slide layout sources (SVG)
> Rebuildable sources, not pictures. Copy one, swap the text, and every position, rule, logo and URL is already correct.
- Cover / title (`cover`): https://galton-ai-assets.vercel.app/brand/layouts/cover.svg
- Profile / speaker card (`profile`): https://galton-ai-assets.vercel.app/brand/layouts/profile.svg
- Concept + supporting graphic (`concept`): https://galton-ai-assets.vercel.app/brand/layouts/concept.svg
- Statement + centred graphic + CTA (`statement`): https://galton-ai-assets.vercel.app/brand/layouts/statement.svg
- Statement, light surface (`statement-light`): https://galton-ai-assets.vercel.app/brand/layouts/statement-light.svg
- Cover, full-bleed image (`cover-image`): https://galton-ai-assets.vercel.app/brand/layouts/cover-image.svg
- Cover, image on the lower half (`cover-image-half`): https://galton-ai-assets.vercel.app/brand/layouts/cover-image-half.svg
- Long statement with a swipe arrow (`statement-cta`): https://galton-ai-assets.vercel.app/brand/layouts/statement-cta.svg
- Carousel step with a full-width numeral (`step-numeral`): https://galton-ai-assets.vercel.app/brand/layouts/step-numeral.svg
- Headline over a full-bleed image (`title-image`): https://galton-ai-assets.vercel.app/brand/layouts/title-image.svg
- Ruled list of terms (`rule-list`): https://galton-ai-assets.vercel.app/brand/layouts/rule-list.svg
- Person card, round portrait (`person-round`): https://galton-ai-assets.vercel.app/brand/layouts/person-round.svg
- Person card, full-bleed portrait (`person-image`): https://galton-ai-assets.vercel.app/brand/layouts/person-image.svg
- Centred graphic over a closing line (`graphic-statement`): https://galton-ai-assets.vercel.app/brand/layouts/graphic-statement.svg
- Running copy with a swipe arrow (`body-cta`): https://galton-ai-assets.vercel.app/brand/layouts/body-cta.svg
- Bulleted list closing on a client logo (`bullets-logo`): https://galton-ai-assets.vercel.app/brand/layouts/bullets-logo.svg
- Two columns split by a vertical rule (`compare-columns`): https://galton-ai-assets.vercel.app/brand/layouts/compare-columns.svg
- Running copy closing on a payoff line (`body-payoff`): https://galton-ai-assets.vercel.app/brand/layouts/body-payoff.svg
- Two numbered steps (`steps-numbered`): https://galton-ai-assets.vercel.app/brand/layouts/steps-numbered.svg
- Numbered stages with arrows (`steps-arrow`): https://galton-ai-assets.vercel.app/brand/layouts/steps-arrow.svg
- Two defined terms, stacked (`definitions-stack`): https://galton-ai-assets.vercel.app/brand/layouts/definitions-stack.svg
- Event announcement, one speaker (`event-speaker`): https://galton-ai-assets.vercel.app/brand/layouts/event-speaker.svg
- Event announcement, panel of participants (`event-panel`): https://galton-ai-assets.vercel.app/brand/layouts/event-panel.svg
- Recruitment, framed centre panel (`recruitment`): https://galton-ai-assets.vercel.app/brand/layouts/recruitment.svg
- Partnership lockup over a portrait (`partnership`): https://galton-ai-assets.vercel.app/brand/layouts/partnership.svg
- Guide cover with a 3D cluster (`guide-cover`): https://galton-ai-assets.vercel.app/brand/layouts/guide-cover.svg

## Icons: Line icons (svg)
> GALTON uses three icon families. (1) LINE — a detailed monoline service-icon library, ~2px stroke, square-ish viewBox, one or more #FFD700 accent blocks. Each line icon ships in TWO finishes: `file` is the WHITE-stroke icon for dark surfaces (the brand default, dark-first), and `fileLight` is the same icon with BLACK strokes for light/white surfaces. The yellow accent is identical in both. (2) 3D — soft-shaded white objects on a single yellow base, transparent PNG; works on dark and light. Match a family's stroke weight and the one-accent rule when extending. (3) ARROWS — the directional set used for a call to action, drawn as an open chevron plus a shaft at a 2.5px stroke, no fill and no arrowhead fill. `file` is the accent finish in #FFD700, which is the default and reads on both surfaces; `fileLight` is the same arrow in #1A1A1A ink, for the case where the arrow must read as ink rather than accent, as the statement CTA does on a light surface. Never recolour an arrow to anything else, and never fill the head.
- tvorba-loga-identity-farby-typo: https://galton-ai-assets.vercel.app/brand/icons-line/tvorba-loga-identity-farby-typo.svg | light surface: https://galton-ai-assets.vercel.app/brand/icons-line-light/tvorba-loga-identity-farby-typo.svg | branding, colors, typography, identity
- tvorba-loga-identity-vizualita: https://galton-ai-assets.vercel.app/brand/icons-line/tvorba-loga-identity-vizualita.svg | light surface: https://galton-ai-assets.vercel.app/brand/icons-line-light/tvorba-loga-identity-vizualita.svg | branding, visual identity, identity, style
- tvorba-loga-identity-logo: https://galton-ai-assets.vercel.app/brand/icons-line/tvorba-loga-identity-logo.svg | light surface: https://galton-ai-assets.vercel.app/brand/icons-line-light/tvorba-loga-identity-logo.svg | branding, logo, identity, mark
- tvorba-loga-identity-sound: https://galton-ai-assets.vercel.app/brand/icons-line/tvorba-loga-identity-sound.svg | light surface: https://galton-ai-assets.vercel.app/brand/icons-line-light/tvorba-loga-identity-sound.svg | branding, sound, audio, identity
- tvorba-webstranok-animacie: https://galton-ai-assets.vercel.app/brand/icons-line/tvorba-webstranok-animacie.svg | light surface: https://galton-ai-assets.vercel.app/brand/icons-line-light/tvorba-webstranok-animacie.svg | web, animation, motion, interaction
- tvorba-webstranok-bezpecnost: https://galton-ai-assets.vercel.app/brand/icons-line/tvorba-webstranok-bezpecnost.svg | light surface: https://galton-ai-assets.vercel.app/brand/icons-line-light/tvorba-webstranok-bezpecnost.svg | web, security, protection, safety
- tvorba-webstranok-dizajn: https://galton-ai-assets.vercel.app/brand/icons-line/tvorba-webstranok-dizajn.svg | light surface: https://galton-ai-assets.vercel.app/brand/icons-line-light/tvorba-webstranok-dizajn.svg | web, design, ui, layout
- tvorba-webstranok-skalovatelnost: https://galton-ai-assets.vercel.app/brand/icons-line/tvorba-webstranok-skalovatelnost.svg | light surface: https://galton-ai-assets.vercel.app/brand/icons-line-light/tvorba-webstranok-skalovatelnost.svg | web, scalability, growth, performance
- employer-branding-atraktivna-firemna-kultura: https://galton-ai-assets.vercel.app/brand/icons-line/employer-branding-atraktivna-firemna-kultura.svg | light surface: https://galton-ai-assets.vercel.app/brand/icons-line-light/employer-branding-atraktivna-firemna-kultura.svg | employer branding, culture, workplace, team
- employer-branding-znizenie-nakladov: https://galton-ai-assets.vercel.app/brand/icons-line/employer-branding-znizenie-nakladov.svg | light surface: https://galton-ai-assets.vercel.app/brand/icons-line-light/employer-branding-znizenie-nakladov.svg | employer branding, cost reduction, savings, efficiency
- employer-branding-zvysenie-lojality: https://galton-ai-assets.vercel.app/brand/icons-line/employer-branding-zvysenie-lojality.svg | light surface: https://galton-ai-assets.vercel.app/brand/icons-line-light/employer-branding-zvysenie-lojality.svg | employer branding, loyalty, retention, engagement
- employer-branding-rychlejsi-hiring: https://galton-ai-assets.vercel.app/brand/icons-line/employer-branding-rychlejsi-hiring.svg | light surface: https://galton-ai-assets.vercel.app/brand/icons-line-light/employer-branding-rychlejsi-hiring.svg | employer branding, hiring, speed, recruiting
- employer-branding-zvysenie-brand-awareness: https://galton-ai-assets.vercel.app/brand/icons-line/employer-branding-zvysenie-brand-awareness.svg | light surface: https://galton-ai-assets.vercel.app/brand/icons-line-light/employer-branding-zvysenie-brand-awareness.svg | employer branding, brand awareness, reach, visibility
- employer-branding-podpora-angazovanosti-timu: https://galton-ai-assets.vercel.app/brand/icons-line/employer-branding-podpora-angazovanosti-timu.svg | light surface: https://galton-ai-assets.vercel.app/brand/icons-line-light/employer-branding-podpora-angazovanosti-timu.svg | employer branding, team engagement, motivation, culture
- employer-branding-efektivnejsi-proces-hiringu: https://galton-ai-assets.vercel.app/brand/icons-line/employer-branding-efektivnejsi-proces-hiringu.svg | light surface: https://galton-ai-assets.vercel.app/brand/icons-line-light/employer-branding-efektivnejsi-proces-hiringu.svg | employer branding, hiring process, efficiency, recruiting
- employer-branding-efektivnejsi-proces-hiringu-2: https://galton-ai-assets.vercel.app/brand/icons-line/employer-branding-efektivnejsi-proces-hiringu-2.svg | light surface: https://galton-ai-assets.vercel.app/brand/icons-line-light/employer-branding-efektivnejsi-proces-hiringu-2.svg | employer branding, hiring process, efficiency, recruiting
- interna-komunikacia-zvysenie-angazovanosti: https://galton-ai-assets.vercel.app/brand/icons-line/interna-komunikacia-zvysenie-angazovanosti.svg | light surface: https://galton-ai-assets.vercel.app/brand/icons-line-light/interna-komunikacia-zvysenie-angazovanosti.svg | internal comms, engagement, involvement, team
- interna-komunikacia-znizenie-fluktuacie: https://galton-ai-assets.vercel.app/brand/icons-line/interna-komunikacia-znizenie-fluktuacie.svg | light surface: https://galton-ai-assets.vercel.app/brand/icons-line-light/interna-komunikacia-znizenie-fluktuacie.svg | internal comms, turnover, retention, stability
- interna-komunikacia-zvysenie-produktivity: https://galton-ai-assets.vercel.app/brand/icons-line/interna-komunikacia-zvysenie-produktivity.svg | light surface: https://galton-ai-assets.vercel.app/brand/icons-line-light/interna-komunikacia-zvysenie-produktivity.svg | internal comms, productivity, efficiency, output
- interna-komunikacia-narast-inovacneho-potencialu: https://galton-ai-assets.vercel.app/brand/icons-line/interna-komunikacia-narast-inovacneho-potencialu.svg | light surface: https://galton-ai-assets.vercel.app/brand/icons-line-light/interna-komunikacia-narast-inovacneho-potencialu.svg | internal comms, innovation, ideas, potential
- socialne-siete-report: https://galton-ai-assets.vercel.app/brand/icons-line/socialne-siete-report.svg | light surface: https://galton-ai-assets.vercel.app/brand/icons-line-light/socialne-siete-report.svg | social media, report, analytics, metrics
- socialne-siete-komunikacia: https://galton-ai-assets.vercel.app/brand/icons-line/socialne-siete-komunikacia.svg | light surface: https://galton-ai-assets.vercel.app/brand/icons-line-light/socialne-siete-komunikacia.svg | social media, communication, messaging, engagement
- socialne-siete-komunita: https://galton-ai-assets.vercel.app/brand/icons-line/socialne-siete-komunita.svg | light surface: https://galton-ai-assets.vercel.app/brand/icons-line-light/socialne-siete-komunita.svg | social media, community, audience, followers
- socialne-siete-obsah: https://galton-ai-assets.vercel.app/brand/icons-line/socialne-siete-obsah.svg | light surface: https://galton-ai-assets.vercel.app/brand/icons-line-light/socialne-siete-obsah.svg | social media, content, posts, creative
- foto-video-produkcia-live-action-videa: https://galton-ai-assets.vercel.app/brand/icons-line/foto-video-produkcia-live-action-videa.svg | light surface: https://galton-ai-assets.vercel.app/brand/icons-line-light/foto-video-produkcia-live-action-videa.svg | production, video, live action, film
- foto-video-produkcia-postprodukcia: https://galton-ai-assets.vercel.app/brand/icons-line/foto-video-produkcia-postprodukcia.svg | light surface: https://galton-ai-assets.vercel.app/brand/icons-line-light/foto-video-produkcia-postprodukcia.svg | production, post-production, editing, video
- foto-video-produkcia-fotografie: https://galton-ai-assets.vercel.app/brand/icons-line/foto-video-produkcia-fotografie.svg | light surface: https://galton-ai-assets.vercel.app/brand/icons-line-light/foto-video-produkcia-fotografie.svg | production, photography, photo, shoot
- foto-video-produkcia-animacie: https://galton-ai-assets.vercel.app/brand/icons-line/foto-video-produkcia-animacie.svg | light surface: https://galton-ai-assets.vercel.app/brand/icons-line-light/foto-video-produkcia-animacie.svg | production, animation, motion, video
- content-marketing-podpora-predaja: https://galton-ai-assets.vercel.app/brand/icons-line/content-marketing-podpora-predaja.svg | light surface: https://galton-ai-assets.vercel.app/brand/icons-line-light/content-marketing-podpora-predaja.svg | content marketing, sales, conversion, support
- content-marketing-zvysenie-konverzii: https://galton-ai-assets.vercel.app/brand/icons-line/content-marketing-zvysenie-konverzii.svg | light surface: https://galton-ai-assets.vercel.app/brand/icons-line-light/content-marketing-zvysenie-konverzii.svg | content marketing, conversions, growth, performance
- content-marketing-narast-zakaznikov: https://galton-ai-assets.vercel.app/brand/icons-line/content-marketing-narast-zakaznikov.svg | light surface: https://galton-ai-assets.vercel.app/brand/icons-line-light/content-marketing-narast-zakaznikov.svg | content marketing, customers, acquisition, growth
- content-marketing-budovanie-dovery: https://galton-ai-assets.vercel.app/brand/icons-line/content-marketing-budovanie-dovery.svg | light surface: https://galton-ai-assets.vercel.app/brand/icons-line-light/content-marketing-budovanie-dovery.svg | content marketing, trust, credibility, authority
- marketing-advertising-report: https://galton-ai-assets.vercel.app/brand/icons-line/marketing-advertising-report.svg | light surface: https://galton-ai-assets.vercel.app/brand/icons-line-light/marketing-advertising-report.svg | marketing, advertising, report, analytics
- marketing-advertising-media: https://galton-ai-assets.vercel.app/brand/icons-line/marketing-advertising-media.svg | light surface: https://galton-ai-assets.vercel.app/brand/icons-line-light/marketing-advertising-media.svg | marketing, advertising, media, channels
- marketing-advertising-meranie-efektivity: https://galton-ai-assets.vercel.app/brand/icons-line/marketing-advertising-meranie-efektivity.svg | light surface: https://galton-ai-assets.vercel.app/brand/icons-line-light/marketing-advertising-meranie-efektivity.svg | marketing, advertising, measurement, effectiveness
- marketing-advertising-tvorba-strategie: https://galton-ai-assets.vercel.app/brand/icons-line/marketing-advertising-tvorba-strategie.svg | light surface: https://galton-ai-assets.vercel.app/brand/icons-line-light/marketing-advertising-tvorba-strategie.svg | marketing, advertising, strategy, planning

## Icons: 3D icons (png)
> GALTON uses three icon families. (1) LINE — a detailed monoline service-icon library, ~2px stroke, square-ish viewBox, one or more #FFD700 accent blocks. Each line icon ships in TWO finishes: `file` is the WHITE-stroke icon for dark surfaces (the brand default, dark-first), and `fileLight` is the same icon with BLACK strokes for light/white surfaces. The yellow accent is identical in both. (2) 3D — soft-shaded white objects on a single yellow base, transparent PNG; works on dark and light. Match a family's stroke weight and the one-accent rule when extending. (3) ARROWS — the directional set used for a call to action, drawn as an open chevron plus a shaft at a 2.5px stroke, no fill and no arrowhead fill. `file` is the accent finish in #FFD700, which is the default and reads on both surfaces; `fileLight` is the same arrow in #1A1A1A ink, for the case where the arrow must read as ink rather than accent, as the statement CTA does on a light surface. Never recolour an arrow to anything else, and never fill the head.
- magnifier: https://galton-ai-assets.vercel.app/brand/icons-3d/magnifier.png | analysis, research, audit, discovery, search
- strategy: https://galton-ai-assets.vercel.app/brand/icons-3d/strategy.png | strategy, chess, planning, positioning
- magnet: https://galton-ai-assets.vercel.app/brand/icons-3d/magnet.png | attraction, acquisition, leads, recruiting
- thumb-up: https://galton-ai-assets.vercel.app/brand/icons-3d/thumb-up.png | approval, engagement, social, like
- camera: https://galton-ai-assets.vercel.app/brand/icons-3d/camera.png | content, photo, video, production
- bubbles: https://galton-ai-assets.vercel.app/brand/icons-3d/bubbles.png | communication, conversation, messaging, comms
- user-heart: https://galton-ai-assets.vercel.app/brand/icons-3d/user-heart.png | loyalty, community, people, retention
- pencil: https://galton-ai-assets.vercel.app/brand/icons-3d/pencil.png | writing, copy, content, editing, design
- vr: https://galton-ai-assets.vercel.app/brand/icons-3d/vr.png | vr, immersive, technology, innovation, future
- hand: https://galton-ai-assets.vercel.app/brand/icons-3d/hand.png | care, support, offer, trust, service
- thunder: https://galton-ai-assets.vercel.app/brand/icons-3d/thunder.png | speed, energy, power, fast, impact
- tag: https://galton-ai-assets.vercel.app/brand/icons-3d/tag.png | price, offer, label, promotion, deal
- register: https://galton-ai-assets.vercel.app/brand/icons-3d/register.png | signup, form, registration, onboarding
- house: https://galton-ai-assets.vercel.app/brand/icons-3d/house.png | home, property, place, real-estate
- graph: https://galton-ai-assets.vercel.app/brand/icons-3d/graph.png | growth, analytics, results, data, performance
- horse-shoe: https://galton-ai-assets.vercel.app/brand/icons-3d/horse-shoe.png | luck, brand, fortune, identity

## Icons: Arrows (svg)
> GALTON uses three icon families. (1) LINE — a detailed monoline service-icon library, ~2px stroke, square-ish viewBox, one or more #FFD700 accent blocks. Each line icon ships in TWO finishes: `file` is the WHITE-stroke icon for dark surfaces (the brand default, dark-first), and `fileLight` is the same icon with BLACK strokes for light/white surfaces. The yellow accent is identical in both. (2) 3D — soft-shaded white objects on a single yellow base, transparent PNG; works on dark and light. Match a family's stroke weight and the one-accent rule when extending. (3) ARROWS — the directional set used for a call to action, drawn as an open chevron plus a shaft at a 2.5px stroke, no fill and no arrowhead fill. `file` is the accent finish in #FFD700, which is the default and reads on both surfaces; `fileLight` is the same arrow in #1A1A1A ink, for the case where the arrow must read as ink rather than accent, as the statement CTA does on a light surface. Never recolour an arrow to anything else, and never fill the head.
- arrow-right: https://galton-ai-assets.vercel.app/brand/arrows/arrow-right.svg | light surface: https://galton-ai-assets.vercel.app/brand/arrows-ink/arrow-right.svg | next, forward, continue, cta, swipe
- arrow-left: https://galton-ai-assets.vercel.app/brand/arrows/arrow-left.svg | light surface: https://galton-ai-assets.vercel.app/brand/arrows-ink/arrow-left.svg | back, previous, return
- arrow-up-right: https://galton-ai-assets.vercel.app/brand/arrows/arrow-up-right.svg | light surface: https://galton-ai-assets.vercel.app/brand/arrows-ink/arrow-up-right.svg | growth, increase, outbound, external, rise
- arrow-down-right: https://galton-ai-assets.vercel.app/brand/arrows/arrow-down-right.svg | light surface: https://galton-ai-assets.vercel.app/brand/arrows-ink/arrow-down-right.svg | decrease, decline, drill down, inbound
- check: https://galton-ai-assets.vercel.app/brand/arrows/check.svg | light surface: https://galton-ai-assets.vercel.app/brand/arrows-ink/check.svg | done, confirmed, approved, complete, tick