Design languagePrinciples

Design language Overview

Principles

Four rules hold Zerone to account, and each one forces decisions in design. For every rule, this page shows the published text, the decisions it forces and whether a test or only review holds each decision. Then it shows the two registers the rules speak in.

Nothing is trusted for having been there yesterday.

#

Rule 01 of 04

The first scan weighs every binary, library and package already on the host against the original. A baseline records what is there; it does not bless it.

As published on the home page

The product does not take a file on trust because it was already there. A page does not take its content on trust from a script that is expected to run later: content earns its place from the HTML the server sends. That HTML is the finished state: every word readable, every visual drawn.

The shared reveal adds motion on top of that state only after its script has run, and only when the visitor has not asked for less motion. So a reveal is never the way content appears; it is the way content that is already there moves. The home hero and the two scroll scenes set their own starting pose instead, and return to the finished state when scripting is off or less motion is asked for.

  1. Script off

    html.no-js

    Final state, straight from the HTML.

  2. Reduced motion

    html

    Final state. No pre-state is written.

  3. Motion, not yet on screen

    html.motion [data-r]

    Pre-state, until the block enters the view or a fallback timer releases it after 3000 ms.

  4. Motion, on screen

    html.motion [data-r].in

    Final state, reached by transform alone.

One revealed block, drawn under four conditions. Three of them show the final state. The pre-state, 14px lower and with its rule not yet drawn, exists only under html.motion and resolves over 800 ms.
The reveal rule as shipped
html.motion [data-r] {
  transform: translateY(14px);
  transition: transform 0.8s var(--ease-out-quart);
}
html.motion [data-r].in { transform: none; }
html.motion [data-r="rule"] { transform: scaleX(0); transform-origin: left; }
html.motion [data-r="rule"].in { transform: none; }

What rule 01 forces in design

  • With scripting off, every page still shows every drawing, and no revealed block is left waiting in its pre-state.

    WhyA script can fail, be blocked or be switched off. The page still has to say everything it claims.

    TestEnforced by a test on every change.

  • Under reduced motion, no page adds html.motion, every revealed block sits in its final place and no loop starts, so nothing needs a pause control.

    WhyAsking for less motion is asking for the content without the choreography, not for a lesser page.

    TestEnforced by a test on every change.

  • The shared reveal writes its pre-state only under html.motion, a class that a script adds only when reduced motion is off.

    WhyIf that pre-state lived in the default styles, a script that never ran would leave content hidden.

    TestEnforced by a test on every change.

  • Nothing on the site animates opacity. Reveals move by transform, clip-path or a drawn stroke, so text stays at full contrast in every frame.

    WhyPartial opacity lowered measured contrast in the middle of a transition. Any frame a visitor can see is a frame that has to pass.

    TestEnforced by a test on every change.

DoWrite the finished state first, then put the reveal's pre-state under html.motion. With no script, the block is simply there.
Do notDo not write a reveal's pre-state in the default styles. If the script never runs, the visitor gets an empty frame.

Evidence checks out without us.

#

Rule 02 of 04

Evidence leaves as a signed bundle with its own verifier. It checks offline, with no account and no call to our servers.

As published on the home page

A design rule is held the way the product's evidence is: by a check that runs on every change, not by anyone's word. Every rule card on these pages says whether a test enforces it or only review keeps it. A guideline that nobody runs is a claim.

Numbers follow the same rule. Values on these pages are computed from their source files at build time, never typed, and a contrast ratio is cut to two decimals, never rounded up, so a pair just under a threshold never appears to pass it.

Contrast of the signal colours on paper, computed from the token file
PairComputed, cut to four decimalsShownSmall text
accent-deep on paper6.65976.65:1AA
ink-subtle on paper4.89794.89:1AA
accent on paper4.38554.38:1fail
raw on paper5.72325.72:1AA
Every inline script on this page matches a digest in its security header

The browser runs no inline script whose digest is missing from that list, including one injected after the page was served. The digests below were read from this page and are in the page source.

    Live: the integrity line from the Trust centre, running on this page. A script reads its count from this page's own security header; open the line to see the digests. Script files are allowed by origin, not by digest: this origin and the contact form's bot-check provider. With scripting off, the line states no count rather than an invented one.

    What rule 02 forces in design

    • A rule says what holds it: a test that runs on every change, or review. Where no test exists, the card says so.

      WhyA test fails the pipeline before deploy on the day the rule is broken; review catches only what a reviewer notices. This page checks its own cards: every card marked as tested is tied to a test that exists under that name, so renaming or deleting the test fails the pipeline too.

      TestEnforced by a test on every change.

    • Contrast ratios are computed from the token values and cut to two decimals, never rounded up.

      WhyA typed number drifts away from the token it describes. A rounded ratio can show a failing pair as a passing one.

      TestEnforced by a test on every change.

    • The percent sign is reserved for one contractual figure. The build fails on any other number written next to it, in visible text or in a text attribute such as alt, title or a meta description.

      WhyA percentage reads as a measurement. The one that appears is a commitment written into the contract; any other number next to the sign would be a claim.

      TestEnforced by a test on every change.

    • A visual that cannot measure says less, not more. Without its script, the integrity line shows no count and its dot stays unlit.

      WhyThe count comes from the page's own security header. A count from anywhere else would be a claim.

      TestEnforced by a test on every change.

    4.49:1fail
    DoCut the ratio. 4.4999 is shown as 4.49 and graded fail.
    4.50:1AA
    Do notDo not round it up. 4.4999 would be shown as 4.50 and graded AA, passing a pair that fails.

    Change is a question, not an alert.

    #

    Rule 03 of 04

    Every change is weighed first: is it the original, which package shipped it, which process wrote it, was it inside a change window. A Windows update folds into one alert per server.

    As published on the home page

    In the product, every change is weighed before it may become an alert, and most never do. On the site, colour is spent in the same order. The token file gives two colours a meaning: in the evidence scene on the home page, raw draws the raw, unverified changes and the accent draws the signal left after triage, one alert. Raw is a muted brick rather than an alarm red. In use elsewhere, the accent also marks scan lines, progress, link underlines and the focus ring, and raw marks flagged files and findings. Everything else is ink on warm paper.

    Motion follows the same economy. A visual moves to explain something, then holds its result, and a loop that keeps going never erases that result and can always be paused.

    • --color-accent#00847eThe signal left after triage; in use also for lines, rings, underlines and dots. Never small text.
      • 4.38:1 paper fail
      • 4.12:1 paper-2 fail
    • --color-accent-deep#006560The accent when it carries text, and fills behind paper text.
      • 6.65:1 paper AA
      • 6.26:1 paper-2 AA
    • --color-raw#a9432cRaw change and flagged findings. A muted brick, not an alarm red.
      • 5.72:1 paper AA
      • 5.38:1 paper-2 AA
    • --color-ink#0f1c26Everything that is not a signal: text, rules, the glyph.
      • 16.61:1 paper AAA
      • 15.62:1 paper-2 AAA

    What rule 03 forces in design

    • The palette is closed. Tailwind's default colours are wiped, so colour utilities exist only for the tokens in one file: the 11 colours, plus transparent and current.

      WhyA default Tailwind colour cannot arrive through a utility class. Arbitrary values and raw colours written into component styles are a matter for review, not for a test.

      TestEnforced by a test on every change.

    • In the evidence scene, raw draws every raw change and the accent draws only the signal left after triage.

      WhyA scene drawn in one colour reads as a single chart. Noise needs its own colour, and the token file keeps that colour a muted brick rather than an alarm red.

      ReviewKept by review, not by a test.

    • The accent never carries small text. Text in the accent's hue is set in accent-deep; the accent itself marks lines, rings and dots.

      WhyOn paper the accent computes to 4.38:1, below the AA minimum for small text. The accessibility scan runs on every page and fails on any text it can measure below the threshold.

      TestEnforced by a test on every change.

    • Every loop the reveal engine starts has a visible pause control on the same page.

      WhyA loop is noise unless the visitor wants it. The choice to pause carries to every page, and loops also stop off screen and in a background tab.

      TestEnforced by a test on every change.

    DoDraw the raw changes in raw and keep the accent for the one change left after triage.
    Do notDo not paint every change in the accent. When everything is signal, nothing is.

    Every detection runs behind your air gap.

    #

    Rule 04 of 04

    The self-hosted build is the same product: an offline signed licence, signed updates you carry in, a local copy of the legitimacy database. What needs a route out is named and off: reputation lookups and trusted timestamping.

    As published on the home page

    The product keeps every detection running with no route out, and the site holds itself to the same rule. A page needs nothing from another origin to render: both typeface families are files in this repository, share images are drawn at build time, and the token values, ratios and file sizes on this page are read from files during the build, not fetched from a service.

    One exception is written into the gate rather than hidden: the bot check on the contact form loads its script from its provider, on that page and no other. The policy on every page still names that provider for scripts, frames and connections; the gate is what keeps the script on the contact page.

    Typefaces this site serves itself
    Typeface and fileSize
    Geist Mono 400GeistMono-400.woff213.9 KB
    Geist Mono 500GeistMono-500.woff214.1 KB
    New Black 400NewBlack-400.woff210.8 KB
    New Black 500NewBlack-500.woff210.7 KB
    New Black 600NewBlack-600.woff210.7 KB
    New Black 700NewBlack-700.woff210.8 KB
    Total70.9 KB
    Security policy: the directives that name no other origin
    default-src 'self';
    img-src 'self' data:;
    font-src 'self';
    object-src 'none';
    base-uri 'self';

    What rule 04 forces in design

    • Type is served from this origin. Both families are local files, and the security policy allows fonts from this origin only, so a page could not load a font service even if it named one.

      WhyA page that waits on a font service renders differently, or not at all, where that service cannot be reached.

      TestEnforced by a test on every change.

    • Share images are drawn at build time, and every page's image has to exist in the build before the page can name it.

      WhyA preview card is part of the page. It is made from files in the repository, not requested from an image service.

      TestEnforced by a test on every change.

    • Pages include scripts from this origin only. The one exception is the contact form's bot check, and the build gate names it: that script, from that provider, on the contact page only.

      WhyA network behind an air gap cannot reach another origin. An exception the gate names cannot spread: the same script on a second page, or a script from a second provider, fails the build.

      TestEnforced by a test on every change.

    • This page asks nothing of another origin. Its own test records every request the page makes and fails on any that leaves.

      WhyA rule is checked where it is stated.

      TestEnforced by a test on every change.

    Two registers

    #

    One language speaks in two registers, and each is chosen for the people who read it.

    The console should be calm; the site should be assertive.

    The decision behind the two registers

    The site has a few seconds to make its case, so it speaks in the assertive register: display type at full weight, warm paper, one accent for the signal and motion that explains. Zero Door is a working tool, read for long stretches, so it speaks in the calm register: a dark theme by default, saturated colour kept for status, short motion that confirms an action and density for data.

    The registers differ on purpose, but they are one family. Under both sit the four rules, the glyph, the ease-out curve and the medium radius. The product's light theme also uses the site's neutral ramp of paper, hairlines and secondary text; its default dark theme does not. The tables below compare the two token files directly: every match is computed, not asserted.

    Both files are published: the site's token file and the Zero Door token snapshot.

    zeronesecurity.com · assertive

    Noise to signal

    A server produces thousands of changes a day. You should hear one voice.

    Package updates, log rotation, temp files, a real implant: they all look like change. Zero Door asks a different question of each one: is it legitimate? Signed by whom, shipped in which package, seen where before, and does what runs in memory match what sits on disk. It speaks only when the answer is no.

    Zero Door · calm

    • Critical3/etc/cron.d/backup-syncweb-01
    • High1/usr/local/bin/agent-updatedb-02
    • Medium12C:\ProgramData\Vendor\config.jsonws-114
    • Low2/var/www/html/index.phpweb-03

    Critical --signal-dangerHigh --signal-warningMedium --signal-infoLow, Info --fg-subtle

    Left: the assertive register, set with the home page's own copy. Right: the calm register, an alert list drawn with the product's dark theme tokens from the snapshot dated 2026-08-23: severity as a dot and a word, a count at the small radius, paths in mono, hairlines between rows. The rows are sample data, not a screenshot. Zero Door sets Inter, which this site does not ship, so the right panel is set in this site's own typefaces.

    What both registers share

    Shared values, compared with the product's light theme (token snapshot dated 2026-08-23)
    SiteZero DoorResult
    --color-paper#fdfaf6--surfaceoklch(0.985 0.006 75)= #fdfaf6Same
    --color-paper-2#f6f3ee--surface-subtleoklch(0.965 0.007 75)= #f6f3eeSame
    --color-hair#e2dfdb--zd-borderoklch(0.905 0.006 75)= #e2dfdbSame
    --color-hair-2#cdcac6--zd-border-strongoklch(0.840 0.006 75)= #cdcac6Same
    --color-ink-muted#5c5753--fg-mutedoklch(0.460 0.010 60)= #5c5753Same
    --color-ink-subtle#736d69--fg-subtleoklch(0.540 0.010 60)= #736d69Same
    --ease-out-quartcubic-bezier(0.23, 1, 0.32, 1)--ease-outcubic-bezier(0.23, 1, 0.32, 1)Same
    --radius-md8px--radius-md8pxSame
    Shared behaviour, as each codebase writes it
    BehaviourSiteZero Door
    Colour is never aloneA verdict or a contrast grade is a word; colour only marks itA severity is a dot beside its word
    Reduced motion is honouredNo motion class, no reveal offset and no loopEvery transition and animation is cut to 0.01 ms, and no animation repeats

    Where they differ on purpose

    Values that differ by design
    AspectSiteZero Door
    ThemeLight only; dark ink panels appear locally, around code and scenesDark by default and independent of the system setting; a light theme is available
    Surface in the default theme--color-paper#fdfaf6--surfaceoklch(0.190 0.008 250)= #111417
    Text colour--color-ink#0f1c26--fgoklch(0.235 0.010 60)= #221d19in the light theme
    Colour that carries meaningOne accent for the signal left after triage and raw for raw change --color-accent #00847e
    --color-raw #a9432c
    4 signal tokens, for severity and status
    TypefacesNew Black and Geist MonoInter and Geist Mono
    Small radius--radius-sm6px--radius-sm4px
    MotionReveal 800 ms; control feedback 160 msFeedback 130 ms, on almost every transition