Repository navigation
Diagrams and Data Visuals
This page sets the grammar for every diagram of a fiscal calendar in fiscalclock's documentation: the six diagram types, their shared rules and colour tokens, the reference year strip, how diagrams are produced and checked, and how they are delivered in light and dark themes.
Last reviewed: 1 Nov 2026
A diagram is a claim about dates, so it must be as exact as the library's output. This page fixes one visual language (a grammar: a small set of shapes and rules that every diagram reuses) so that a reader who learns one diagram can read all of them. Every diagram is drawn to scale, labels everything in text, never relies on colour alone, and gets its dates from an independent source, never from fiscalclock itself.
Status: the grammar below is Proposed in domain-visuals.md; its sizes and ratios are design judgements not yet tested with readers. The color.diagram.* tokens and the reference year strip are built and checked.
| Term | Meaning here |
|---|---|
| half-open interval | A span written [start, end_exclusive): start is included, end_exclusive is the first day not included. last_day is end_exclusive minus one day (spec/api-v1.md). |
| to scale | Lengths are proportional to days: twice as many days, twice as wide. |
| day axis | A horizontal line along which each day takes the same width. |
| boundary line | The line where one period ends and the next starts, drawn at the left edge of the next period's start day. |
| hatch | A pattern of thin diagonal lines, used to mark the extra week without relying on colour. |
| direct label | Text placed on or next to the thing it names, instead of in a separate key (legend). |
| small multiples | Several small diagrams with the same scale and alignment, placed side by side for comparison (Small multiple). |
| alt text | The text alternative a screen reader reads instead of the image. In SVG, title is the short name and desc the long description (MDN title, MDN desc). |
| contrast ratio | How much lighter one colour is than another, from 1:1 to 21:1, as WCAG 2.2 defines it. See Accessibility. |
| ID | Name | Question it answers | Layout | Minimum size (Proposed) |
|---|---|---|---|---|
| D1 | Year strip | How does a fiscal year divide into quarters, periods and weeks, and how long is each? | One band per level (quarters, periods with week ticks), then a day axis with the year's start and end_exclusive markers. Quarter start dates under the axis. |
2 px per day: 742 px for a 371-day year |
| D2 | Week grid | Which dates fall in which week and period? | One row per week, seven day columns from week.starts_on, week number on the left, rows grouped into labelled period blocks, heavier rule between quarters (after the NRF printed calendar). |
20 px day cells: about 140 px per year plus labels |
| D3 | Boundary detail | What do start, end_exclusive and last_day mean? |
About two weeks of labelled day cells around one boundary: filled marker at start, open marker at end_exclusive, last_day cell bracketed and labelled "derived", bracket notation printed beside it. |
32 px per day |
| D4 | 52 vs 53-week comparison | Where does the extra week go, and what does it change? | Two D1 strips of the same definition stacked, aligned on fiscal week 1, same pixels per day; a dashed guide marks the 52-week year's end. | As D1 |
| D5 | Two-calendar comparison | How do two calendars differ over the same dates? | Shared axis of real dates; calendar A above, calendar B below; guides join paired boundaries, labelled with the offset in days (for example +3 d). |
As D1 |
| D6 | Multi-year drift | How does a week-based year end move around its anchor date, and which years have 53 weeks? | Dot plot: one row per fiscal year, horizontal axis is the year end's offset in days from the anchor (−3 to +3 for nearest). 53-week years are rings labelled "53"; each row also shows the full last_day. |
One tick per day; no omitted days |
Full descriptions of each type, with layout, scale and alt-text patterns, are in domain visuals, "Proposed diagram grammar".
-
Days are cells, boundaries are lines. A date occupies the width from its left edge to the next date's left edge. A boundary is drawn once, at the left edge of the next period's
start, so tiling without gaps or overlaps is visible. - Linear scale, no truncation. Width is proportional to days, with the same pixels per day across one diagram and every panel of a set. No axis breaks, no omitted weeks.
-
Closed start, open end. Where a span's bounds are marked,
startgets a filled marker andend_exclusivean open marker, with the words "included" and "excluded" beside them.last_dayis never drawn as a boundary; when shown, it labels the last cell inside the span and says "derived". -
Dates. Full dates are ISO
YYYY-MM-DDwith tabular figures. In grids, the first day of each calendar month carries its month name. Fiscal labels follow the definition's templates, such asFY2023 Q4. A week-based year's label always gives its length in weeks. - Hierarchy without colour. Quarters: heavier, taller boundary lines. Periods: alternating fill with thin separators and a text label. Weeks: short ticks. Extra week: hatched, outlined and labelled. A greyscale print must still read correctly.
- Direct labels. Labels sit on or beside what they name. A legend is used only for the hatch, and the hatched element is labelled in place as well.
- Minimum sizes (Proposed). Text at least 11 px at rendered size (10 px for secondary notes); week ticks at least 6 px tall; markers at least 8 px across; the per-type minimums in the table above. Below a strip's minimum width, show the week grid instead of shrinking the strip.
-
Alt text.
title: " fiscal year : days, weeks".desc: the year'sstart(included),end_exclusive(excluded) andlast_day, each quarter's dates and weeks, the period lengths in order, and the extra week's dates and period. The page also shows the same numbers in a visible table under the figure (W3C complex images tutorial). - Every date is checked. The caption names the definition and the source or independent generator of its dates (see How diagrams are produced).
The research note proposed ten colour roles; the token build implements them as eight color.diagram.* tokens. Values are copied from tokens.light.json and tokens.dark.json; ratios from the build's contrast report, which fails the build if any pair drops below its minimum.
| Token | CSS variable | Light | Dark | Used for | Non-colour partner | Checked contrast (light / dark) |
|---|---|---|---|---|---|---|
color.diagram.surface |
--fc-color-diagram-surface |
#fdfdfc |
#121212 |
Diagram background | None | Background of the other checks |
color.diagram.ink |
--fc-color-diagram-ink |
#1a1a19 |
#ececea |
Labels, quarter boundaries, axis, start marker | Heavier, taller line for quarters | 17.11:1 / 15.83:1 on surface; 15.53:1 / 13.46:1 on period fill (4.5:1 text) |
color.diagram.ink-muted |
--fc-color-diagram-ink-muted |
#555552 |
#a5a5a1 |
Secondary labels, week ticks | Smaller size | 7.34:1 / 7.57:1 on surface; 6.67:1 / 6.44:1 on period fill (4.5:1 text) |
color.diagram.rule |
--fc-color-diagram-rule |
#7d7d79 |
#71716d |
Period separators, grid lines | Thin line | 4.06:1 / 3.82:1 on surface; 3.68:1 / 3.24:1 on period fill (3:1 line) |
color.diagram.period-fill |
--fc-color-diagram-period-fill |
#f2f2f0 |
#222221 |
Fill of alternate periods (the others show the surface) | Separators and text labels; never the only cue | Not checked: exempt because labels carry the information (Understanding 1.4.11) |
color.diagram.extra-week |
--fc-color-diagram-extra-week |
#0b6b69 |
#5cc6be |
Extra-week hatch, outline and its "week 53" label | Hatch pattern and a "week 53" label | 6.21:1 / 9.16:1 on surface; 5.64:1 / 7.79:1 on period fill (3:1 mark) |
color.diagram.open-end |
--fc-color-diagram-open-end |
#0b6b69 |
#5cc6be |
The open marker at end_exclusive, as in the logo's open parenthesis |
Open circle and the word "excluded" | 6.21:1 / 9.16:1 on surface (3:1 mark) |
color.diagram.calendar-b |
--fc-color-diagram-calendar-b |
#1f55a0 |
#8cb2f0 |
The second calendar in a comparison (D5) | Dashed separators and a row label | 7.20:1 / 8.69:1 on surface (4.5:1 text) |
color.diagram.reference-date |
--fc-color-diagram-reference-date |
#8c5600 |
#e9b65c |
A reference date supplied by the caller, if a diagram shows one | Labelled vertical line with its ISO date | 5.98:1 / 10.08:1 on surface (4.5:1 text) |
How the research roles map onto the tokens:
| Research role | Token |
|---|---|
surface, ink, ink-muted, rule, extra-week, open-end, calendar-b
|
Same names under color.diagram.*
|
period-fill-a, period-fill-b
|
One token, color.diagram.period-fill, alternating with color.diagram.surface
|
quarter-rule, boundary
|
color.diagram.ink, with a heavier line for quarters |
today-marker |
color.diagram.reference-date. fiscalclock reads no clock, so this date is always an input and its label prints it. |
Never use other colours in a diagram, and never use rainbow or red-green scales (trust research, section 6.4).
The year strip below is the reference D1 diagram. It shows NRF 4-5-4 fiscal 2023, an illustrative example: fiscalclock has no built-in calendars (ADR-0004).
Light theme:

Dark theme:

Definition: NRF 4-5-4 as in the README example (year ends on the Saturday nearest 31 January, weeks start on Sunday, extra week in period 12). Dates computed with Python's standard library in build_brand_assets.py, from the year start published in NRF's calendar.
The same numbers as a table, from the independent oracle vector nrf-4-5-4.json:
| Span | start |
end_exclusive |
last_day (derived) |
Weeks | Days |
|---|---|---|---|---|---|
| FY2023 | 2023-01-29 | 2024-02-04 | 2024-02-03 | 53 | 371 |
| Q1 | 2023-01-29 | 2023-04-30 | 2023-04-29 | 13 | 91 |
| Q2 | 2023-04-30 | 2023-07-30 | 2023-07-29 | 13 | 91 |
| Q3 | 2023-07-30 | 2023-10-29 | 2023-10-28 | 13 | 91 |
| Q4 | 2023-10-29 | 2024-02-04 | 2024-02-03 | 14 | 98 |
| P12 (holds the extra week) | 2023-12-31 | 2024-02-04 | 2024-02-03 | 5 | 35 |
| Week 53 (the extra week) | 2024-01-28 | 2024-02-04 | 2024-02-03 | 1 | 7 |
How the strip follows the grammar (from the drawing code in year_strip() of build_brand_assets.py):
| Rule | In the reference strip |
|---|---|
| Scale | 1040 px for 371 days, about 2.8 px per day (above the 2 px minimum). Every period is a whole number of weeks wide. |
| Quarters | 3 px lines in color.diagram.ink, extending 10 px above the strip; labels Q1 13 weeks and so on. |
| Periods | Odd-numbered periods filled with color.diagram.period-fill; 1.5 px separators in color.diagram.rule. |
| Weeks | 1 px ticks in color.diagram.ink-muted, 22 % of the strip's height (12.32 px at 56 px). |
| Extra week | Diagonal hatch and 2 px outline in color.diagram.extra-week, labelled "week 53" above the strip in the same colour. |
| Bounds | Filled 14 px circle at start in color.diagram.ink; open circle at end_exclusive with a 3 px color.diagram.open-end stroke, matching the logo's open parenthesis; dates in bold with "start, included" and "end_exclusive, excluded" below. |
| Labels | 17 px IBM Plex Sans, converted to outlines. |
The wiki version labels every period P1 to P12; the social cards omit period labels for space but keep the quarter labels, the "week 53" label and the dated bounds.
Rule: every diagram that shows dates is generated by a script; only diagrams with no dates may be drawn by hand. This follows the recommendation in domain visuals, "How to produce them" (Proposed).
| Step | Requirement | Why |
|---|---|---|
| Dates | Come from conformance/generators/fiscal_oracle.py, from a cited conformance vector, or from standard-library date arithmetic in the drawing script. Never from running fiscalclock. |
AGENTS.md: expected values never come from running fiscalclock. A diagram is an expected value drawn as a picture. |
| Cross-check | Where a published source exists, the script compares its dates with it and stops on any mismatch. | The research sample checked 14 dates against NRF's PDF (domain visuals, "Sample"). |
| Script | Python standard library for the arithmetic. The brand script also needs fontTools, uharfbuzz, Pillow and Inkscape 1.4 to draw text as outlines and render PNGs (requirements-brand.txt). |
Same habits as research/verification/. |
| Colours | Read from the token build, never typed in. | The brand script reads tokens.light.json and tokens.dark.json; check_brand.py fails on any non-palette colour in assets/brand/. |
| Output | Script and SVG committed together; each SVG names its definition, data source and script in a comment (Proposed). | Reproducible and reviewable. |
| CI | Reruns the scripts and fails on any difference (Proposed; not in CI yet). | Keeps diagrams in step with the oracle. |
| Caption | Names the definition and the source of the dates; marks example definitions as illustrative. |
Trust research, section 6.5; evidence rule 4 in AGENTS.md. |
To rebuild the reference strip and the other wiki illustrations, see Asset-Inventory.
Dark mode is equal to light (DD-005 in DECISIONS.md). How a diagram follows the theme depends on where it is shown:
| Where | Method | Notes |
|---|---|---|
| Docs site, diagram inline in the page | Inline <svg> whose colours are the color.diagram.* CSS variables, such as var(--fc-color-diagram-ink)
|
Follows the page theme, including a manual switch with data-theme (DD-018). No media query of its own. Text can stay live text in the page font (Proposed). |
Standalone .svg file loaded with <img>
|
Internal <style> with an @media (prefers-color-scheme: dark) override |
MDN's prefers-color-scheme page describes this pattern. An <img> SVG cannot load web fonts, so text must be converted to outlines (asset specs, section 4). favicon.svg uses the same pattern. |
| GitHub README and other GitHub Markdown | Two files, switched with <picture> and <source media="(prefers-color-scheme: dark)">
|
<picture> is supported (GitHub Docs). Whether GitHub honours a media query inside an <img> SVG was not tested, so two files are the safe choice. |
| GitHub wiki | Two PNGs | The wiki displays PNG, JPEG and GIF, not SVG (GitHub Docs). Whether the wiki honours <picture> was not tested, so this page shows both images one after the other. |
Inline SVG on the docs site:
<figure>
<svg role="img" aria-labelledby="fy23-title fy23-desc" viewBox="0 0 1200 250">
<title id="fy23-title">NRF 4-5-4 fiscal year 2023: 371 days, 53 weeks</title>
<desc id="fy23-desc">Starts 2023-01-29 (included); end_exclusive 2024-02-04 (excluded); last_day 2024-02-03 …</desc>
<rect width="1200" height="250" fill="var(--fc-color-diagram-surface)"/>
<rect x="80" y="60" width="78.49" height="56" fill="var(--fc-color-diagram-period-fill)"/>
<!-- … -->
</svg>
<figcaption>Illustrative example. Definition: NRF 4-5-4. Dates: conformance/vectors/oracle/nrf-4-5-4.json.</figcaption>
</figure>Standalone SVG file:
<style>
.ink { fill: #1a1a19 } .rule { fill: #7d7d79 } .extra { fill: #0b6b69 }
@media (prefers-color-scheme: dark) {
.ink { fill: #ececea } .rule { fill: #71716d } .extra { fill: #5cc6be }
}
</style>GitHub Markdown:
<picture>
<source media="(prefers-color-scheme: dark)" srcset="diagram-year-strip-dark.svg">
<img alt="NRF 4-5-4 fiscal year 2023: 371 days, 53 weeks …" src="diagram-year-strip-light.svg">
</picture>Forced colours (Windows High Contrast and similar): user agents keep an SVG's own fills, so give every diagram its own background rectangle and outlines, or restyle it under @media (forced-colors: active) with the system colours CanvasText and Canvas (accessibility research, section 6). Not yet tested in a browser.
| Rule | Applies to | Source |
|---|---|---|
| Same pixels per day in every row or panel. | D4, D5, D6 | Shared rule 2; Small multiple |
| Say what the rows are aligned on: fiscal week 1 (D4) or real dates (D5). | D4, D5 | Domain visuals, D4 and D5 |
| Each row label names the calendar and, for week-based years, its length in weeks, as annual reports write "(53 weeks)". | D4, D5, D6 | Domain visuals, "Annual reports" |
The second calendar uses color.diagram.calendar-b and dashed separators and a row label. |
D5 | Shared rule 5; WCAG 1.4.1 |
Label each offset between paired boundaries in days, for example +3 d. |
D5 | Domain visuals, D5 |
| A restated year is a third, labelled row; it never replaces the actual year. NRF publishes both a 53-week 2023 and a restated 52-week 2023, and both are labelled 2023. | D4 | Domain visuals, "NRF 4-5-4 calendar" |
| Example calendars, including the illustrative pairing of a 1 February fixed-date year with NRF 4-5-4, are labelled "Illustrative example". | All | Trust research, rule R4 |
The D6 example in the research note is computed, not looked up: for "Saturday nearest 31 January", fiscal years 2015 to 2030, the 53-week years are 2017, 2023 and 2028 (domain visuals, D6), which matches the NRF cited vector nrf-53-week-years.json for 2017 and 2023.
| Rule | Why | Source |
|---|---|---|
| Draw to scale. A 53-week year is exactly 7/364 longer than a 52-week year; the extra week is shown by label and outline, never by stretching it. | Tufte's "lie factor": the size of an effect in the graphic divided by its size in the data should be 1. | Trust research, section 6.1 |
| No truncated axes. Timelines start at a meaningful boundary, such as the fiscal year's start, and show whole periods. A zoomed view (D3) shows its context with dated boundaries. | Experiments found truncated axes exaggerate the perceived effect even when the truncation is marked. | Trust research, section 6.3 |
| No 3D, gradients, shadows or decorative fills. | Data-ink guidance; DD-019 also rules out shadows. | Trust research, section 6.2 |
| Never colour alone; no rainbow or red-green scales. | WCAG 1.4.1 and colour-vision deficiency. | Trust research, section 6.4 |
| Caption names the definition and the source of the dates. | Readers should be able to check and reproduce a figure. | Trust research, section 6.5 |
Dates as ISO YYYY-MM-DD; never a time of day, time zone or clock face. |
The results are civil dates; a time implies a timestamp. | Trust research, section 6.6 |
| Rule-level facts at the precision the rule supports, such as "71 long years in every 400" where computed and cited. | Precision the data does not have misleads. | Trust research, section 6.6 |
- The type is one of D1 to D6, or the page says why a new type is needed.
- Widths are proportional to days, with one scale per diagram or set.
- Every distinction has a non-colour cue (line weight, outline, hatch, dash or text).
- Only
color.diagram.*tokens are used, and both themes were viewed. - Dates come from the oracle, a cited vector or standard-library arithmetic, never from fiscalclock.
- The caption names the definition and the source; example definitions say "Illustrative example".
-
title,descand a visible table carry the same numbers. - Text is at least 11 px at the size it is shown.
- Filled and open circles as an endpoint convention were not confirmed in any teaching source; test them with readers and keep the words "included" and "excluded" (domain visuals, open questions).
- The minimum sizes and the 2 px per day scale are untested on small screens.
- Whether GitHub and the GitHub wiki honour
prefers-color-schemeinside an SVG, or<picture>in the wiki, is untested.
- Design-System, Colour-System, Typography, Design-Tokens, Accessibility, Iconography-and-Illustration, Docs-Components, Asset-Inventory, Design-Glossary, Design-Decisions
- Concepts: Semantics, Glossary, ADR-0007 (half-open intervals)
- Research:
domain-visuals.md,trust-and-credibility.md,accessibility.md,asset-specs.md - Code and data:
build_brand_assets.py,fiscal_oracle.py,nrf-4-5-4.json, token build
fiscalclock is licensed under MIT OR Apache-2.0 (MIT, Apache-2.0). Last reviewed: 31 Oct 2026. Found an error on this page? Report it with the documentation form.