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
Text and lines
Coral accent ramp
One accent, in five steps: border, tint, solid and two text tones. The steps are tuned per theme for contrast.
Status
Cover band
The cover is always the ink band with white text, in both themes. It is never the page black.
Diagrams
The --dg-* tokens colour SVG diagrams, so a diagram follows the theme.
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.
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
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.
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.
--w:1240pxGutter--gut:clamp(20px,3vw,48px)Radius
Spacing
Depth
Depth comes from 1px hairlines and stepped surfaces. There are no drop shadows.
Stepped surfaces
--bg--panel--raisedLines
--hair--hair2The one exception
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-washring. - Selectors with a box-shadow in the stylesheet:
.search:focus-within, .sum. - No drop shadows on cards, panels, buttons or images.
Documents
Three kinds of document share the tokens on this page. The previews are the reference examples, rendered from the kit.
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.
generate_report() or document()Ships as.html, read in any browser, offlineA4 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.
onepager_document() and the op_* componentsShips asPDF, from report_qa.js --pdfPhase 1 is live. Now we pick what it does next.
Six systems connected, five people using it, and one decision to agree today.
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.
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.shbuilds 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
- Generated, not hand-written. Built through
ertech_design.pywith the embedded stylesheet; no second style block. - Short titles. Finding titles are headings, not sentences: "One shared root key used from five countries".
- 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 / Verifyas a small key-value footer.ertech_design.format_fix()does this. - Impact lines must not overstate the evidence. "Published vulnerabilities", not "exploits", unless an exploit is confirmed.
- Counts must reconcile. If passes are counted separately say so: "57 findings and 2 passed checks · 59 items".
- 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.
- Owners are roles. Dates are urgency bands.
- Source rules pass.
python report_delivery.py checkprints no issues. - Browser QA passes.
node report_qa.js <file> <outDir>prints PASS and writes the.qa.jsonproof. - Proof verified.
python report_delivery.py verifymatches the file hash; any edit means run all three again. - Looked at. Screenshots checked in both themes: cover band intact, nothing clipped, no label collisions.
- 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.
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