ER Tech
Design system · 2026.11-v2

ER Tech design

One system for every report, one-pager and deck we send. Geist type, hairlines, an ink cover and one coral accent. Everything on this page is read from the live stylesheet.

reference/ertech-report.css · ertech_design.py · SKILL.md
Version
2026.11-v2from ertech_design.py DESIGN_VERSION
Approved
5 Nov 2026design v2
Fonts
Geist, Geist MonoSIL Open Font License
At a glance
35Colour tokens
10Type roles
6Radius steps
3Document kinds
One accent. No shadows.

Coral is the only accent and green only means pass or live. Reports open dark with a light and dark toggle, print light, and carry their fonts with them.

01 · Colour

Colour

Every swatch below is read from reference/ertech-report.css. The left half is the dark theme, the right half the light theme and print.

Surfaces

--bg
dark #0E0C0B · light #F6F4F1
Page
--panel
dark #151311 · light #FFFFFF
Panels and cards
--raised
dark #1E1B18 · light #F1EEE9
Raised rows, open findings
--track
dark #2A2622 · light #ECE8E2
Bar tracks

Text and lines

--t1
dark #FFFFFF · light #151311
Primary text
--t2
dark #C9CCD4 · light #5C5752
Secondary text
--t3
dark #8C9099 · light #8A847D
Labels, captions
--hair
dark #2A2622 · light #E4E1DC
Hairline
--hair2
dark #38332E · light #D3CFC8
Stronger hairline, controls

Coral accent ramp

One accent, in five steps: border, tint, solid and two text tones. The steps are tuned per theme for contrast.

or-wash
or-dim
or3
or2
or
--or
#E0664C
The accent: eyebrows, figures, rules
--or2
dark #EB8A74 · light #C4432A
Accent text and hover
--or3
dark #F2B3A3 · light #8A3E2E
Accent on tint
--or-dim
dark #7A3322 · light #F0C9BD
Accent border
--or-wash
dark rgba(224,102,76,.12) · light rgba(224,102,76,.10)
Accent tint, open rows
--on-or
dark #FFFFFF · light #fff
Text on solid coral

Status

CriticalHighMediumLowPass
--crit
dark #E0664C · light #C4432A
Critical, solid coral
--high
#E0664C
High, coral tint
--med
dark #D49A2C · light #B8860B
Medium
--low
dark #8C9099 · light #8A847D
Low
--info
dark #6E727A · light #8A847D
Info
--pass
dark #5FBF9A · light #14674F
Pass, live, good. Green only here
--crit-t
dark #F08A72 · light #C4432A
Critical text
--med-t
dark #E8B85A · light #8A6414
Medium text
--pass-t
dark #5FBF9A · light #14674F
Pass text

Cover band

The cover is always the ink band with white text, in both themes. It is never the page black.

--bg
#16181d
Ink cover band
--panel
#1c1e24
Panel on the cover
--raised
#23262d
Raised on the cover
--hair
#2c2f37
Hairline on the cover
--hair2
#3a3d46
Control border on the cover

Diagrams

The --dg-* tokens colour SVG diagrams, so a diagram follows the theme.

--dg-box
dark #1E1B18 · light #FFFFFF
Diagram
--dg-line
dark #38332E · light #D3CFC8
Diagram
--dg-core
dark #5C5752 · light #8A847D
Diagram
--dg-t1
dark #F5F2EE · light #151311
Diagram
--dg-t2
dark #ADA8A2 · light #5C5752
Diagram
--dg-warn
dark #2A1A0E · light #FFF1E6
Diagram
--dg-warn-l
dark #8A3E00 · light #FFB36B
Diagram
--dg-warn-t
dark #FFB36B · light #8A3E00
Diagram
--dg-good
dark #0F2A1C · light #E6F6ED
Diagram
--dg-good-l
dark #1F6B44 · light #9ADBB6
Diagram
--dg-pad
dark #151311 · light #F6F4F1
Diagram

Roles

  • In code use the CSS variables, never the hex. A hex colour is right in one theme and wrong in the other.
  • Coral is the only accent; green appears only on Pass / Live / "good" states.
  • Depth comes from 1px hairlines and stepped surfaces, no shadows; the one exception is the coral halo on the executive-summary card.
02 · Type

Type

Geist, weights 400 / 500 / 600. Roles and sizes are read from the Type section of SKILL.md; tracking values in use: -.04em · -.03em · -.02em · -.01em · .16em · .2em · .26em.

Roles

Body
We looked at your server, your code and every website you run.
14px · 400 · 0
Cover h1
Sentence case, short and plain
clamp(38px,4.8vw,62px) · 600 · -.04em
Section h2
Sentence case, short and plain
clamp(24px,2vw,30px) · 600 · -.03em
Card h3
Sentence case, short and plain
17px · 600 · -.02em
Area h3
Sentence case, short and plain
17px · 600 · -.02em
Finding title
Sentence case, short and plain
14px · 500 · 0
Description
Nothing was changed. This report shows what we found.
13.5px · 400 · 0
Labels
How to fix
10–12px · 500 · .16em
Summary figures
57
clamp(28px,2.3vw,40px) · 600 · -.03em
Stat figure
57
24px · 600 · -.03em
Mono
example-shop.test · /var/www/app · ssh -p 22
Geist Mono 12-12.5px · 400
Eyebrow
Action plan
12px · 600 · .2em · uppercase

Do

  • Use Geist for everything and Geist Mono for hosts, paths, evidence lists and inputs.
  • Use weights 400 / 500 / 600 only. Headings are 600 with tight negative tracking.
  • Write titles, pills, buttons and table cells in sentence case.
  • Keep uppercase with .16 to .26em tracking for the signature labels: the wordmark, section eyebrows, labels inside cards and the footer strip.
  • Embed the fonts as data so a page looks the same offline, in a mail preview and in the PDF.

Do not

  • Do not add a Google Fonts link or any other network font.
  • Do not enlarge the approved compact scale.
  • Do not set body copy, titles or buttons in uppercase.
  • Do not use a bullet dot on an eyebrow; it takes the 10px coral square.
03 · Space and shape

Space and shape

Radius and gap values as they occur in the report stylesheet and its extensions, with how often each is used.

Layout

--w:1240px (1380 at ≥1800px), gutter clamp(20px,3vw,48px), section gap 38px, panels radius 16px with 14-18px padding, cards 12px, controls 10px, pills full round with a leading dot.

Width--w:1240pxGutter--gut:clamp(20px,3vw,48px)

Radius

8px · 3x
10px · 8x
12px · 8x
16px · 4x
50% · 3x
999px · pills

Spacing

2px
4x
6px
6x
7px
1x
8px
3x
9px
1x
10px
5x
12px
13x
16px
1x
20px
2x
32px
1x
40px
1x
44px
1x
04 · Depth

Depth

Depth comes from 1px hairlines and stepped surfaces. There are no drop shadows.

Stepped surfaces

Page--bg
Panel--panel
Raised--raised

Lines

--hair
--hair2
Coral rule
Hairline1px, between rows and around panelsRule180 by 3px coral, once, on the cover

The one exception

Executive summary
A coral halo, not a shadow.

The executive summary card on the cover carries a 1px coral ring and a soft coral glow. Nothing else does.

  • Focus rings use a 3px --or-wash ring.
  • Selectors with a box-shadow in the stylesheet: .search:focus-within, .sum.
  • No drop shadows on cards, panels, buttons or images.
05 · Documents

Documents

Three kinds of document share the tokens on this page. The previews are the reference examples, rendered from the kit.

Reference report cover, dark themeReference report cover, light theme
Reports

Interactive reports

Security audits, IT assessments, findings reports, digests and usage reports. One self-contained HTML file that opens dark, carries a light and dark toggle, and prints light.

Sticky nav, ink cover with an executive summary, the action plan before the evidence, findings by area with search, filters and deep links.

Buildgenerate_report() or document()Ships as.html, read in any browser, offline
Reference one-pager, A4
One-pagers

A4 one-pagers

Status reports, phase outlines and scope pages. One A4 page, always light, no script, delivered as a PDF.

Ink header band, a title with the key word in coral, then rows of white panels: figures, timelines, progress, systems and next steps. It must fit one page; the QA harness fails it if it does not.

Buildonepager_document() and the op_* componentsShips asPDF, from report_qa.js --pdf
ER Tech01 / 08
Example Co · Phase 1 review

Phase 1 is live. Now we pick what it does next.

Six systems connected, five people using it, and one decision to agree today.

ertech.aiExample Co · Phase 1 review
Decks

Slide decks

Reviews, proposals and decision meetings. 16:9 PowerPoint (13.333 by 7.5 in), built with deck_pptx.py on python-pptx.

Every slide gets the wordmark, a page counter and the footer strip. Components stack top to bottom on the current slide: cover(), section(), stats(), rows(), numbered(), steps(), chips(), columns(), band(), closing(), save(). save() runs a layout check.

ThemeLight content slides, ink cover and section slidesFontsGeist installed on the machine that renders; Inter is the documented fallbackShips as.pptx, or PDF exported from PowerPoint
06 · Use it

Use it

The kit is the skill folder: the Python library, the stylesheets, the fonts, the QA harness and the reference examples.

The Python library

ertech_design.py is stdlib only. It embeds the stylesheet and fonts and renders every component.

import sys; sys.path.insert(0, "ertech-design")
import ertech_design as ed

# Findings report: start from scripts/build_example.py
html = ed.generate_report(data)        # data: findings[], action plan, meta

# Anything else: document() plus components
# document(title, cover_html, body_html, nav_links, str]], footer_html, findings_script, lang)
ed.section("usage", "Usage", "How the month went", ed.card("Requests", ed.data_table(...)))

# One-pager: start from scripts/build_onepager_example.py
ed.onepager_document(...)

The skill for Claude and Hermes

Unzip the kit as a skill folder named ertech-design. SKILL.md tells the agent when to use the system and how to build, check and ship.

  • Claude.ai / Claude Desktop: bash infra/scripts/export-skill-desktop.sh builds the zip to
  • Claude Code: this folder is picked up automatically inside the repo.
  • Hermes: copy the folder into your skills directory; it loads by name, ertech-design.
python report_delivery.py check  <report.html>
node report_qa.js <report.html> <outDir>     # must print PASS and write <report.html>.qa.json
python report_delivery.py verify <report.html>

Before it ships

  1. Generated, not hand-written. Built through ertech_design.py with the embedded stylesheet; no second style block.
  2. Short titles. Finding titles are headings, not sentences: "One shared root key used from five countries".
  3. Fixes are procedures. Render 1. 2. 3. as <ol>, Today: / Then: as labelled phases, sentence-per-step prose as a numbered list, WHEN / EFFORT / EXPECTED GAIN / Verify as a small key-value footer. ertech_design.format_fix() does this.
  4. Impact lines must not overstate the evidence. "Published vulnerabilities", not "exploits", unless an exploit is confirmed.
  5. Counts must reconcile. If passes are counted separately say so: "57 findings and 2 passed checks · 59 items".
  6. Client-facing round numbering starts at 1. Strip every trace of internal rounds ("re-rated", "round one credited…", "Rubric (round 3)") from copy and from finding text.
  7. Owners are roles. Dates are urgency bands.
  8. Source rules pass. python report_delivery.py check prints no issues.
  9. Browser QA passes. node report_qa.js <file> <outDir> prints PASS and writes the .qa.json proof.
  10. Proof verified. python report_delivery.py verify matches the file hash; any edit means run all three again.
  11. Looked at. Screenshots checked in both themes: cover band intact, nothing clipped, no label collisions.
  12. No client data in public. A client report goes to the client's folder, never into a public place.

Download the kit

Version 2026.11-v2 · 24 files · 431 KB zip. Fonts are Geist and Geist Mono under the SIL Open Font License.

Download the kit

In the kit

  • SKILL.md
  • README.md
  • ertech_design.py
  • report_qa.js
  • report_delivery.py
  • canonical.css
  • onepager.css
  • deck_pptx.py
  • reference/ertech-onepager.css
  • reference/ertech-report-extensions.css
  • reference/ertech-report.css
  • reference/ertech-report.js
  • reference/example-onepager-status.html
  • reference/example-onepager-status.html.qa.json
  • reference/example-security-audit.html
  • reference/example-security-audit.html.qa.json
  • scripts/build_example.py
  • scripts/build_onepager_example.py
  • scripts/diagrams.py
  • fonts/Geist-latin-ext.woff2
  • fonts/Geist-latin.woff2
  • fonts/GeistMono-latin-ext.woff2
  • fonts/GeistMono-latin.woff2
  • fonts/manifest.json