Site theme: visual design
Reference kit dated 2026-09-13. The canonical sheets are 01–08 in this folder; files ending in -v1 preserve superseded attempts. This is the executable summary: a developer should be able to make ordinary drawing and layout decisions from this document without reopening a sheet.
Authority: the values and rules below take precedence over generated pixels, specimen microcopy, and approximate thumbnail geometry. L means read from the live renderer, R means explicitly requested or established by the accepted round-two references, and I means an inferred design decision made here. Raster images establish character and relationships, not a recoverable font family, pixel dimension, timing, or implementation capability. Every new numerical component, layout, state, and motion value below is I unless marked otherwise.
All dimensions are CSS px at 1x. The renderer applies DPR once. Font size and line-box height are separate quantities. Hex with eight digits is #RRGGBBAA, not ARGB.
Source baseline: renderer/theme.lua, SHA-256 90adab81fed2283d89bdcad7c395de05da14513065afcaf8cd715bf49fd1afce. Also inspected main.lua, elements.lua, and canvas.lua for layout, text and role behavior. Visual sources are accepted redesign images 22–51, with 22, 28, 36 and 49 re-examined for this codification. The Ricochet reference folder supplied eleven sheet images, including dotted variants, and ricochet-design.md; only the dotted version of sheet 06 was present. Its numbered manual format is the exemplar. Its fonts, paper, dots and game identity are not imported.
Overall direction
A dark reading surface with bounded works, quiet controls, and real content. The field is flat #111. Proportional near-white text carries the page. Space and hairlines separate material; a rectangle is reserved for an actual control, media object, or overlay. A notebook entry is a piece of writing, not a dashboard tile.
Blue is the interaction accent. Gold locates: numeric entry IDs, the current reading item or place, and progress. It is not the default color for buttons, artifacts, replay filenames, headings, filter counts or large surfaces. Role and status colors retain their specific meaning. Source images, covers and games retain their own colors.
There is one top header and, in paginated views, one shared navigation footer. No sidebar, repeated application headers on facing pages, paper curl, decorative page shadow, background texture, gradient, glow, or dot motif. Page-stack marks, if used, are thin neutral progress cues, not simulated paper.
Choosing and reading have different densities. Front doors and collections expose enough real material to judge an entry; readers give continuous text a stable measure and a visible end. Reader, notebook and optional paginated-log views share page geometry. Consultation logs can still scroll. Do not force every surface into pagination as a consequence of installing color and type tokens.
The current family choice is Arial, with the already bundled Segoe UI for tweet content and section labels, and Cascadia Code for technical text. The reference images' attractive proportional sans treatment is codified through size, leading, weight and spacing. It is not evidence that an identifiable new font was used. A serif for long book prose is an optional future slot, not a current dependency or active face.
Palette
| Token | Hex RGBA | Role | theme.lua mapping |
Basis |
|---|---|---|---|---|
field |
#111111 |
Page background | colors.bg |
L |
panel |
#181818 |
Popover/card surface | NEW panel |
I |
recess |
#0D0D0D |
Input and player well | NEW recess |
I |
hairline |
#FFFFFF14 |
Decorative dividers | colors.rule |
L |
control_border |
#FFFFFF26 |
Neutral boundaries | colors.rule2 |
L |
off_surface |
#FFFFFF0A |
Subtle on/hover surface | colors.off_bg |
L |
text_primary |
#E6E6E6 |
Body and main labels | colors.text / colors.ink / colors.code |
L |
text_secondary |
#FFFFFFA8 |
Supporting labels | colors.medium |
L |
text_dim |
#FFFFFF80 |
Inactive/secondary metadata | colors.dim |
L |
quote |
#BBBBBB |
Quotation text | colors.quote |
L |
link |
#8CB4FF |
Interaction accent | colors.link |
L |
link_hover |
#B2CEFF |
Hovered actions | NEW link_hover |
I |
link_pressed |
#6F9FE8 |
Pressed actions | NEW link_pressed |
I |
current |
#FFCB5C |
Current item, entry IDs, progress | NEW current; live artifact value |
L value / R use |
selection |
#8CB4FF40 |
Text selection wash | colors.selection |
L |
focus |
#8CB4FF |
Keyboard focus ring | NEW focus; alias colors.link |
L value / I use |
hover_wash |
#8CB4FF1F |
Interactive hover fill | NEW hover_wash |
I |
current_wash |
#FFCB5C26 |
Current location fill | NEW current_wash |
I |
find_all |
#8CB4FF26 |
Non-current search hits | colors.find (changed) |
I |
find_current |
#FFCB5C40 |
Current search hit | colors.find_cur (changed) |
I |
artifact_link |
#8CB4FF |
Unselected artifact/replay links | colors.artifact (changed) |
I |
role_owner |
#8CB4FF |
Owner turn bar | colors.link |
L |
role_fable |
#D97757 |
Fable/driver turn bar | colors.driver |
L value / R extension |
positive |
#78C878 |
Confirmed positive state/additions | colors.add |
L |
danger |
#EB6E6E |
Errors/removals/destructive state | colors.del |
L |
warning |
#E6E6E6 |
Warning icon + explicit label, no extra hue | NEW warning; alias text |
I |
overlay |
#000000B3 |
Modal scrim, alpha179/255 | NEW overlay |
I |
on_accent |
#111111 |
Text/icons on filled blue | NEW on_accent; alias field |
I |
spoiler_bg |
#FFFFFF |
Existing inverse spoiler island only | colors.spoiler_bg |
L |
spoiler_text |
#000000 |
Existing spoiler foreground | colors.spoiler_text |
L |
spoiler_link |
#3054EB |
Existing spoiler link | colors.spoiler_link |
L |
The table's NEW names are proposed semantic roles. A mapping to an existing key means use that key's stable color object; an alias need not allocate a separate object. colors.* are theme specification keys, exposed as prose.color.* at runtime. Mutate existing color objects through the theme path instead of replacing objects cached layouts hold.
Preserve alpha. On #111, the live hairline is approximately #242424, neutral control border #343434, off-surface #1A1A1A, secondary text #AEAEAE and dim text #888888. These composites are explanatory, not replacement tokens. panel is an opaque #181818 surface; off_surface is a white wash over its actual parent. They are different operations.
Use field for pages and large reading areas, panel for popovers and owned tweet/media cards, and recess for input wells and player letterboxing. No elevation shadow is required. Use hairline for dividers and control_border for neutral control boundaries. A blue action label, icon, focus cue, or explicit control shape must make interaction understandable; a faint hairline alone is insufficient.
Gold is limited to these uses:
- Numeric entry IDs such as
#529, including IDs on non-current entries. - Current chapter, month/date, saved reading position, or currently consulted result. Prefer a label, a 2 px mark, or
current_wash, not an opaque gold panel. - Actual reading or replay progress. Do not draw fabricated completion amounts.
A selected filter, active tab, or chosen Single/Spread mode uses blue. Those are control selections, not reading locations. Non-current find matches use find_all; the current match uses find_current, retaining the normal foreground. A text selection uses selection. Keep a gold location marker visible beside a selected row without changing its selection color.
Positive and danger retain the live addition/removal colors. Use them for explicit status, a diff, or a destructive action with a label; do not turn them into alternate decorative accents. Warnings use a neutral triangle and explicit text. There is no additional amber warning token. The owner bar retains link blue. Fable's bar uses the existing driver terra-cotta value; the extension from delegated prompter to identified Fable assistant turns is a new rule, discussed below.
The three inverse spoiler tokens preserve the existing exceptional spoiler treatment. They do not define a white modal style or authorize any change to hiding, reveal, privacy, or gating behavior.
Measured contrast pairs, using standard sRGB luminance and alpha compositing over the named background:
| Foreground / background | Ratio |
|---|---|
| text_primary / field | 15.13:1 |
| text_secondary / field | 8.49:1 |
| text_dim / field | 5.36:1 |
| text_primary / panel | 14.23:1 |
| text_secondary / panel | 8.20:1 |
| text_dim / panel | 5.28:1 |
| link / field | 9.07:1 |
| link_hover / field | 11.84:1 |
| current / field | 12.54:1 |
| on_accent / link | 9.07:1 |
| on_accent / link_pressed | 7.01:1 |
| role_fable / field | 6.05:1 |
| positive / field | 9.29:1 |
| danger / field | 6.28:1 |
These are calculated color pairs, not a claim that an implementation has passed an accessibility audit. Target at least 4.5:1 for ordinary text and 3:1 for meaningful focus/control cues. Decorative hairlines intentionally have lower contrast.
Typography
Use bundled files so desktop and web use the same faces:
| Family | Files | Basis |
|---|---|---|
| Arial regular / bold / italic | assets/arial.ttf, assets/arialbd.ttf, assets/ariali.ttf |
L |
| Segoe UI regular / bold / italic / semibold | assets/segoeui.ttf, assets/segoeuib.ttf, assets/segoeuii.ttf, assets/seguisb.ttf |
L |
| Cascadia Code regular | assets/CascadiaCode-Regular.ttf |
L |
| Optional book serif | No file selected; do not register or fetch a face | R |
The following scale is normative. Existing h1–h3, code, metadata and tweet sizes are retained; new roles, body size, section/tag sizes, all explicit line boxes and tracking assignments are I.
| Role | Family / face | Size | Line box | Weight | Tracking | Mapping |
|---|---|---|---|---|---|---|
page_title |
Arial | 32 | 40 | 700 | 0 | NEW page_title |
section_label |
Segoe UI Semibold | 12 | 16 | 600 | 1.2 | fonts.banner (changed) |
item_title |
Arial | 18 | 24 | 700 | 0 | NEW item_title |
running_head |
Arial | 12 | 16 | 400 | 0 | NEW running_head; small alias |
body |
Arial | 16 | 24 | 400 | 0 | fonts.body (changed) |
body_bold |
Arial | 16 | 24 | 700 | 0 | fonts.bold (changed) |
ui |
Arial | 14 | 20 | 400 | 0 | NEW ui |
ui_bold |
Arial | 14 | 20 | 700 | 0 | NEW ui_bold |
meta |
Arial | 12 | 16 | 400 | 0 | fonts.small; upright small_italic alias |
tag |
Arial | 12 | 16 | 400 | 0.8 | fonts.tag (changed) |
id_path |
Cascadia Code | 12 | 16 | 400 | 0 | NEW mono_small |
code |
Cascadia Code | 14 | 20 | 400 | 0 | fonts.code size/family retained; new line height |
h1 |
Arial | 28 | 36 | 700 | 0 | fonts.h1; new line height |
h2 |
Arial | 21 | 28 | 700 | 0 | fonts.h2; new line height |
h3 |
Arial | 16 | 24 | 700 | 0 | fonts.h3; new line height |
blockquote |
Arial Italic | 16 | 24 | 400 italic | 0 | fonts.italic / quote context |
caption |
Arial | 12 | 16 | 400 | 0 | fonts.small |
tweet |
Segoe UI | 15 | 22 | 400 | 0 | fonts.tweet; new line height |
tweet_name |
Segoe UI Bold | 15 | 22 | 700 | 0 | fonts.tweet_bold; new line height |
The italic role is Arial Italic 16/24, matching body. tweet_italic remains Segoe UI Italic 15/22. The table's blockquote role uses the existing quote-context italic behavior, rather than silently changing quotations to upright text. Dates and captions are proportional Arial; timestamps, IDs and addresses use Cascadia. Do not infer monospaced dates from the generated sheets.
Section labels are uppercase letters with 1.2 px tracking, using the real Segoe semibold face. “Small caps” here describes the label treatment, not synthesized small-cap glyphs. Tags use uppercase Arial regular at 0.8 px tracking. Arial has real 400 and 700 faces; do not synthesize 600. The 600 weight is specific to Segoe semibold.
Normal prose wraps at words and retains authored emphasis. No automatic letter spacing in body text. Inline code is Cascadia 14/20, aligned within the surrounding body line box; a mixed line must accommodate its tallest run without clipping. A blockquote is 16/24 italic in quote, with a 1 px neutral left rule and 16 px inset. Do not italicize log-owner turns merely because they use a quote-like container.
Lists use body 16/24, a 24 px hanging indent, 16 px marker slot, 8 px marker-to-text gap, and 8 px between items. Each nested level adds 24 px. Captions are 12/16, with 8 px separation from their object. Long paths wrap at sensible separators; code blocks preserve whitespace and may use an explicitly scrollable horizontal region.
Paragraph separation is 16 px, retaining metrics.element_gap. Heading and block gaps:
| Block | Before | After | Live mapping / basis |
|---|---|---|---|
| h1 | 24 | 12 | gap_before.h1 changes 22 to 24; after NEW |
| h2 | 24 | 12 | gap_before.h2 changes 18 to 24; after NEW |
| h3 | 16 | 12 | Before retained; after NEW |
| Image or video | 16 | 16 | Before retained; after follows element gap |
| Quote | 24 | 16 | Before retained; after follows element gap |
Adjacent block gaps collapse to their maximum, not their sum. At a page start, suppress an unnecessary leading paragraph gap. Keep a heading with at least two following text lines. Keep at least two lines of a paragraph on either side of a page boundary when its length permits. A long paragraph continues across pages; it is not scaled down or replaced with an excerpt.
Retain treat.heading_rule = false and metrics.head_overflow = 0. Do not add underlines to all prose headings. A page title is the 32/40 application/title role, distinct from an authored h1 at 28/36.
Sizing controls (I): default reading size 16 px; range 14–22 in 1 px steps. Reading scale is chosen size / 16. Apply it to prose, prose headings, quotes, code and tweet content. Navigation, controls, page numbers and metadata remain at their UI sizes. Normal line spacing uses the table above; Compact multiplies reading line boxes by 0.9, Relaxed by 1.1, without changing glyph size. Round at physical-pixel layout time and never below the tallest glyph run. Width changes reflow, rather than scaling glyphs to fit.
This separation requires implementation work: live font_scale currently affects registered theme fonts broadly, and text layout uses a shared line gap. Use explicit role/context line boxes and separate reading scale from UI scale. For the base body, 16/24 corresponds to body_line_height = 1.5, but that multiplier alone does not implement the full table. Preserve lazy CJK, Hangul and symbol fallbacks, reflow when they arrive, and extend bold fallback-role classification to new bold roles. Reuse equal face/size font handles and existing unload/cache logic; do not exceed the engine's 64 registered-font limit by creating a font per component. No new font download is needed for this theme.
Specimen forms:
- Entry ID:
#529. - Date:
Sep 10, 2026; do not omit spaces. Retain source date semantics instead of silently converting dates to a new timezone. - Timestamp:
10:05:06, using available source precision; omit unavailable seconds rather than invent them. - Proposed citation address:
/posts/luck#b-0003. This illustrates an essay slug plus stable block ID, not an existing resolved route. Page numbers cannot be durable addresses after reflow. Persistent block IDs and resolver support are separate work; do not claim a sequential index survives content edits. Until supported, copy the actual page URL and existing heading anchor.
Spacing and layout
Use the scale 4, 8, 12, 16, 24, 32, 48. It is I, consistent with the accepted references; 16 px paragraph spacing is L. Larger layout dimensions and control heights below are deliberate exceptions, not extra general-purpose spacing tokens.
Shared shell and collections
| Token / rule | Value at 1x | Basis |
|---|---|---|
| Main content maximum | 1440 | I |
| Desktop outer margin | 32 | I |
| Phone outer margin | 16 | L value, generalized |
| Desktop top nav | 64 high | I |
| Phone top nav | 56 high | I; live mobile topbar is 44 |
| Phone breakpoint | W < 768 | L MOBILE_BP |
| Front-door split | W >= 1024 | I |
| Front-door split widths | 38% works / 62% notebook after subtracting gap | I |
| Front-door gap | 32 | I |
| Collection columns | 1 below 768; 2 from 768–1199; 3 at 1200+ | I |
| Collection gap | 24 | I |
Main content width is min(1440, W - 2 * margin), centered. Nav uses the same maximum. Desktop brand is Arial bold 18/24; links are UI 14/20 with 24 px between items. Keep Works, Notebook, Essays, Experiments, AI Logs and Search in the top line. Current section uses a blue 2 px underline; this is navigation selection. Reading views can replace this full link row with brand, work identity, Contents/Dates and Aa in the same header.
Phone nav is one 56 px bar with brand or Back, current identity, Search and an explicit menu control. Secondary sections open in a popover, not a persistent sidebar. Reserve 44 px hit areas. At intermediate widths, collapse optional header text before letting controls collide.
Below the front-door split, works become a horizontal row above the notebook; on phone use 224 px work cards with 16 px gaps and sideways browsing. Source covers remain proportionally contained. Collection items have intrinsic height and align at their row's top; do not truncate titles into an artificial equal-height text box.
Reading geometry
The live scroll-article column_w = 800 and text_w = 704 remain available. Do not globally replace 704 with the reader measure. The following is a new paginated layout, used by the reader, notebook and optional paginated log.
| Reader token | Value |
|---|---|
| Spread breakpoint | 1120 |
| Maximum page width | 624 |
| Spread gutter | 32 |
| Maximum spread width | 1280 = 624 + 32 + 624 |
| Maximum prose measure per page | 528 |
| Minimum page padding, W >= 1280 | 48 |
| Minimum page padding, 768 <= W < 1280 | 32 |
| Phone page padding | 16 |
| Chapter strip | 64 high |
| Month strip | 48 high |
| Log role/session strip | 48 high |
| Gap below header/strip to page | 24 desktop; 16 phone |
| Reader footer | 48 desktop; 56 phone |
| Gap between page bottom and footer | 24 desktop; 16 phone |
| Running-head top relative to page top | 24 desktop; 16 phone |
| Body top relative to page top | 64 desktop; 48 phone |
| Body bottom inset | 48 desktop; 40 phone |
| Page-number line top before page bottom | 32 desktop; 24 phone |
A view uses zero or one strip. Chapter, month and role strips are alternatives, not a stacked set. The chapter strip contains real chapter titles, a gold current label/mark and actual per-chapter progress. The month strip has previous/next month controls, month label and a Dates action. It does not manufacture dates for empty days. When tabs overflow, scroll that strip horizontally and expose its end controls; do not squeeze labels into unreadable type.
Let W and H be the available application viewport in CSS px. The desktop available reading width is A = W - 64. At W >= 1120 in Spread mode, each page width is min(624, (A - 32) / 2). Total spread width is twice that plus 32, centered. Single mode has one page of width min(624, A), centered. Below 768, the page width is min(624, W), centered without adding a second outer margin.
Text width is min(528, page_width - 2 * minimum_padding), centered within the page. Padding is a minimum: a 624 px page with a 528 px measure leaves 48 px on each side even when the compact minimum is 32.
Vertical positions:
page_top = nav_height + visible_strip_height + top_gap
page_bottom = H - footer_height - bottom_gap
body_top = page_top + body_top_inset
body_bottom = page_bottom - body_bottom_inset
Running heads and page numbers use 12/16, with the line-box top at the offsets in the table. Center a number under each page's text column. Page numbers derive from the current reflow and are never persisted as an address. A shared footer holds Previous at left and Next at right; do not repeat them per page.
Worked examples, all with one indicated strip:
| Viewport | Strip | Page widths / gutter | Text per page | Page top / bottom | Body top / bottom |
|---|---|---|---|---|---|
| 1440 x 900 | Chapter 64 | 624 / 32 / 624 | 528 | 152 / 828 | 216 / 780 |
| 1120 x 900 | Chapter 64 | 512 / 32 / 512 | 448 | 152 / 828 | 216 / 780 |
| 900 x 900 | Chapter 64 | Single 624 | 528 | 152 / 828 | 216 / 780 |
| 390 x 844 | Month 48 | Single 390 | 358 | 120 / 772 | 168 / 732 |
At H < 640, collapse the strip into Contents/Dates in the header and use 16 px top/bottom gaps. Clamp popovers to the available viewport. Never generate a negative text area or clip text to preserve decorative furniture; in an exceptionally short viewport, expose the existing scroll view as a fallback.
Pages are field-colored reading regions with zero corner radius and no enclosing frame. Diagram frames on sheet 06 are measurement guides. A spread may use one subtle center hairline if it helps distinguish pages; it is not required around the outside. Source content, not a prescribed word count, determines page fullness. Short notebook entries can leave space. Media can occupy a whole page or spread with an explicit entry/exit control; it is not stretched to create apparent fullness.
Preserve reading position by content location when size, width, orientation or line spacing changes. Keep heading context, selection and find anchored to the ordered text stream. These are functional requirements for a reader implementation, not behavior supplied by theme tokens.
Strokes and radii
Use 1 px hairlines, 1.5 px icon strokes, 2 px focus rings with 2 px offset, 2 px current/active marks, and 3 px role bars. Snap strokes to suitable physical-pixel edges after DPR conversion; a 1 CSS px stroke is not forcibly reduced to one device pixel at high DPR. Use radius 0 for prose/pages/ordinary rows, 4 for collapsed tool rows, 6 for rectangular buttons/dropdowns, 8 for panels/media/popovers, and half the height for pills. No blur shadow.
Components
Dimensions below describe outer border boxes. Borders draw inward and do not silently enlarge the specified height. Text line boxes are vertically centered in fixed-height controls. A label may increase width; ordinary content rows grow vertically. Touch targets reserve layout space rather than overlapping neighbors.
Controls and overlays
| Component | Dimensions and construction |
|---|---|
| Filter chip | Desktop 28 high; UI 14/20; horizontal padding 12; count gap 8; count Cascadia 12/16; radius 14; 1 px border. Desktop hit target at least 32 high. Phone visual 32 high, reserved target at least 44 x 44; chip-row gap 8. |
| Text-link button | UI 14/20, action color, no box; 36 high reserved desktop target, 44 phone. Optional 16 px icon, gap 8. Inline prose links instead follow body metrics and retain text selection. |
| Outlined pill button | 36 high, minimum width 80, padding 16, radius 18, 1 px blue border, transparent fill, UI 14/20. Phone 44 high and radius 22. |
| Filled button | Same 36 high/minimum 80/padding 16; radius 6; flat blue fill; dark on_accent label in UI bold 14/20. Phone 44 high. One primary filled action per local decision group is sufficient. |
| Toggle | 40 x 24 track, radius 12; 16 px thumb. Off: recess, control border, secondary thumb. On: blue track and dark thumb. Label gap 8; phone reserved target 44 high. |
| Tabs | 40 high, padding 16 each side, UI 14/20; active blue 2 px bottom mark. No enclosing card. Phone hit area 44 high. |
| Segmented control | 36 high, radius 8, 1 px neutral border, minimum cell width 72, horizontal padding 12. Chosen segment is blue with dark text. Phone 44 high. |
| Dropdown | 36 high, minimum width 160, padding 12, radius 6, 16 px chevron; UI 14/20; recess and neutral border. Phone 44 high. |
| Search field | 40 high desktop, 44 phone; radius 8; padding 12; 16 px magnifier with gap 8; input Arial 16/24; recess and control border. |
| Popover | Width 320, clamped to viewport minus two outer margins; padding 16; radius 8; 1 px control border; panel; anchor gap 8. Maximum height min(480, viewport minus two margins); internal scroll if needed. |
| Toast | Width intrinsic, min 160/max 320; minimum height 40; padding 12 horizontal/8 vertical; radius 8; UI 14/20; optional 16 px icon, gap 8. Only confirm an action that actually succeeded. |
| Previous / Next | One pair in the shared footer. 36 high desktop/44 phone; text link or outlined pill. Disable only the unavailable direction, not the page's text. |
| Page-turn edge | Desktop outer margin only, width min(48, actual free margin); blue hover wash, 2 px outer edge and 16 px chevron. No hit area over text, links, media or the entire page half. Phone uses explicit controls/swipe. |
| Edge preview | Maximum 280 wide, 96 high, padding 12, radius 8, panel and 1 px border; positioned within viewport. Shows the next page's actual first line. Clip at line boundary, not fabricated continuation. |
Filter On uses off-surface, neutral border and primary text. Off is transparent, hairline and dim text. Solo is the derived state when exactly one filter is enabled: blue fill, dark label/count. This specification does not add a new solo gesture or alter existing toggle semantics.
The Aa popover is 320 wide and 424 high at default UI size, with 16 padding. Use a 24 px heading; four groups separated by 16: Typeface (16 label, 8 gap, 36 control), Text size (16 label, 8 gap, 24 slider), Line spacing (16 label, 8 gap, 36 control), Layout (16 label, 8 gap, 36 control). Finish with a 36 high Done action, 8 gap and a 16 high status line. The total includes the header-to-first-group gap of 16. Clamp and scroll on small screens.
Sans is selected. A shown Serif option is disabled and labeled Future; it must not silently substitute a system serif. Text size starts at 16; Normal spacing is selected. Spread is unavailable below 1120; preserve the preference for a wider viewport. A status such as “Reading position kept” appears only after the actual operation. The illustrative state on sheet 02 is not permission to report success before it occurs.
Content objects
| Object | Rules |
|---|---|
| Notebook entry | Gold mono ID, proportional date and tag in a 12/16 meta row; gap 12 to 16/24 body. Intrinsic height; no invented title or summary. Separate entries with a hairline and 16 px on each side, for 32 px total separation. |
| Video share | Entry text plus native-ratio poster. Default play disk 64; compact 40, with at least a 44 hit area. Disk uses overlay black, primary triangle 20 and a blue focus/hover cue. Controls 40 desktop/44 phone; seek track 4, thumb 12. Actual played progress gold; volume and actions blue. |
| Owned tweet card | Panel, radius 8, 1 px control border, padding 16. Avatar 32; name Segoe bold 15/22; body Segoe 15/22; handle/date 12/16; vertical group gaps 12. Preserve attribution and real media; no fabricated badges. |
| Link line | Body 16/24 blue with a 1 px underline; optional external icon 12, gap 4. Wrap actual label or URL. A thumbnail is not mandatory. |
| Essay row | Unboxed, 16 vertical padding, minimum height 112 with content-driven growth. Title 18/24, meta 12/16, real opening sentence 16/24, gaps 8. No automatic cover image, even if old metadata contains a thumbnail. Estimated reading time may be ceil(indexed word count / 200), labeled as an estimate; omit if unavailable. |
| Work row | Unboxed, padding 16, minimum height 128. Cover bounding box 64 x 96, contain without distortion; gap 16. Title 18/24, type/year 12/16, actual Read or Play action. A game's action must not inherit “Read” from a generic specimen. |
| Log turn | Speaker UI bold 14/20; timestamp mono 12/16; gap 8 to body 16/24. A 3 px role bar with 12 px gap to text spans the turn's content. Owner blue; identified Fable terra-cotta; unknown assistant neutral. Do not box every turn. |
| Collapsed tool call | Minimum 32 high desktop/44 phone, padding 12 horizontally, radius 4, recess, 1 px hairline; 12 px chevron, gap 8; UI 14/20, optional mono timestamp. Show only actual tool name, counts and metadata. |
| Media/replay card | Minimum height 64, padding 12, radius 8, 1 px border; 20 px icon, gap 12; title 18/24 or filename mono 12/16, metadata 12/16. Grow for wrapped names. Unselected attachment actions and filenames are blue. |
| Expanded replay | Same attachment identity as its collapsed card. Header 40 with Collapse replay/Open larger; source-ratio viewport; controls 40 desktop/44 phone. Preserve game geometry, letterbox in recess, and use real duration/progress when available. |
| Chip row | 8 px between chips and wrapped rows; counts derive from current data. Role chips share geometry but may use an explicit role-colored mark/outline. Their selected control state remains blue. |
| Continue band item | Minimum height 80, padding 16; title 18/24, actual saved-position label 12/16 with gap 4; 12 px gold bookmark, Resume control. Wide band: up to three items with gap 16; phone: horizontal items minimum 240 wide. Hide absent saved states. |
| Search result | Unboxed, 16 vertical padding; title 18/24, metadata 12/16, actual indexed snippet 16/24. Highlight all hits with blue wash and current hit with gold wash. Selected row uses blue wash plus a 2 px gold current mark; keyboard focus remains a separate outer blue ring. |
Preserve image, video and playable-board aspect ratios. Only a deliberately authored cover slot may crop cover artwork; the default work row uses contain. Never crop a game board to satisfy a card shape. A poster is an existing asset, not an invitation to generate new visual content at runtime. Inline video expansion keeps the entry's location and provides Return to entry and Esc. Expanded replays, transcript synchronization, and Take control are capability-dependent; the theme does not make them available.
Template usage
| Surface | Objects and navigation |
|---|---|
| Front door | Works plus real notebook material; section modules for Essays, Experiments and AI Logs. Continue is conditional on saved state. Section routes retain distinct destinations; no sidebar. |
| Reader | Shared header, optional chapter strip, continuous text on one/two pages, contents/Aa, stable content position, one footer and a real chapter/work ending. Do not auto-flow into unrelated work. |
| Notebook | Same reader geometry; month/date navigation replaces chapter identity. Keep entry IDs and native tweet/video/link forms. Multiple entries may share a spread; one-entry-per-page is a presentation option, not a forced content length. |
| Work home | Real cover/title/type, actual Read/Play entry points, source chapter list, conditional Resume and real related records. No invented synopsis or assumed project relationships. |
| Log | Session identity, real summary when present, attachments, role-labeled turns, collapsed tools and Find. Consultation defaults to scroll; the same content may be paginated if explicitly chosen. |
| Phone reader/notebook | One page, one compact header, retained date/contents access, 16 px text padding, explicit navigation and native-ratio media. |
| Collections/search | Real rows or cards grouped by existing type, year or project. Only actual matching snippets and dates; Open at match requires a resolvable text target, while a work result uses Open work. |
Fixtures used in the sheets are examples, not production content constants. Source posts/2026-09-10-102337.md for #529 and posts/2026-09-10-103225.md for #530; use their real body text rather than the Luck sentence accidentally repeated beneath notebook IDs on sheets 01/04. The Luck specimen comes from posts/luck.md: “Your body and your mind are you and you are them.” Its source date is June 14, 2022. The quoted tweet sentence is cado/@cocadonv's, not the owner's. Use the site's cached tweet and attribution.
The real #530 poster is renderer/media-cache/posters/DtB5c_Qou6Q.jpg, with the full 16:9 frame and its side pillars. The representative Horse Game capture is renderer/media-cache/posters/_media_messages_2026-07-21-021047_knight-vs-pawns_mp4.jpg. The shown 20260901-234821.apr is a Horse Game 21 attachment; the representative capture is not a decoded frame from that replay. The Fable sentence beginning “Docs read. Now let me look at how sounds are recorded…” is from Horse Game 22 at 10:05:06. The sheet-08 related placement is explicitly illustrative. Do not create cross-project relationships from the sheet.
Counts 260 posts, 274 logs, 1 story and 2 prototypes were a source-index snapshot during this task. They are not hardcoded theme values. Generated reading totals such as 3/28 and 12/28 are illustrative and must not be copied.
States
Use normal, hover, pressed and focus feedback where the object is interactive. “Selected” is a control/query selection; “current” is a reading location. A plain prose page itself has neither a disabled nor a visited style.
| State | Links/buttons | Chips/tabs/modes | Content rows/pages |
|---|---|---|---|
| Normal | Blue action; body links underlined | Neutral filter On/Off; blue chosen mode | Neutral prose/row; explicit action visible |
| Hover | link_hover; outlined controls add hover wash |
Hover wash, not opaque fill unless already selected | Interactive row wash; page edge only |
| Pressed | link_pressed; filled label stays dark |
Pressed blue border/fill as applicable | Recess or pressed edge; never shift text layout |
| Focus | 2 px blue ring, offset 2 | Same visible ring | Focus the row/control, not an enclosing prose canvas |
| Selected | N/A for ordinary link | Blue; filter Solo clearly distinguished | Query selection blue; text selection only behind selected runs |
| Disabled | Dim label; neutral off-surface/border where boxed | Dim label; no active hover | Only unavailable controls dim; prose remains readable |
| Current | Location links may be gold | Current date/chapter gold; ordinary filters N/A | Gold mark/label/progress; keep selection/focus separate |
| Visited | Same blue, no new purple | N/A | Do not dim previously read prose |
No extra global opacity multiplier on disabled components: the dim token already defines their contrast. Disable input and expose the state semantically. Focus never depends on hover. A current gold item can simultaneously have a blue keyboard ring. Do not use gold-filled filter chips, including the superseded sheet-07 attempt.
Do not create additional browsing-history tracking just to implement a visited color. Keep selection, copy, find and actual URL behavior consistent with the existing site. In paginated content, text selection must cross the same ordered text pieces as in the scroll renderer.
Cursor forms: default arrow for the page, pointer for actions, I-beam for selectable text, grab/grabbing only for a draggable timeline or explicit draggable object. A whole paragraph must not become a pointer because the reader supports page turns.
Input ownership comes before global shortcuts. Left/Right, PageUp/PageDown, Space and Shift+Space turn only while the reading surface has focus and no input, text operation, video or game has claimed the event. Esc closes the topmost popover/media overlay, restores focus to its opener, and preserves the reading position. A game that captures controls must expose Return to page. Do not globally translate the mouse wheel into page turns; scrolling surfaces and popovers retain scroll behavior.
Touch swipe (I): at least 48 px horizontal displacement and absolute horizontal displacement at least 1.5 times vertical, only when the gesture was not claimed by text, a slider, media or game. Explicit Previous/Next remains available. Do not trigger both swipe and tap navigation for one gesture.
Motion
Default page turn is a cut, 0 ms. The location changes once and text is immediately readable. There is no curl, simulated paper, bounce, long traversal, parallax, or decorative camera move.
| Event | Duration | Property / easing |
|---|---|---|
| Hover | 100 ms | Color/fill; ease-out |
| Pressed | 0 ms | Immediate feedback |
| Release | 80 ms | Return to hover/normal |
| Popover open / close | 100 / 80 ms | Opacity and at most 4 px rise; ease-out |
| Modal overlay open / close | 120 / 120 ms | Opacity only |
| Toast in / out | 100 / 120 ms | Opacity; visible lifetime 2400 ms |
| Default page cut | 0 ms | No interpolation |
| Optional page slide | 120 ms | 32 px horizontal displacement plus crossfade; ease-out |
| Reduced-motion UI transitions | 0 ms | No translation or fade |
Use ease_out(t) = 1 - (1 - t)^3 for normalized t in [0,1]. The optional slide is off by default. Forward moves the outgoing surface toward the left and the incoming one from the right by at most 32 px; backward reverses it. Both are clipped to the reader, input advances one target at a time, and the content anchor updates once. Do not move a playable scene as an active simulation without its explicit container handoff.
Reduced motion makes all these UI state changes immediate, including popovers and overlays. Toast lifetime remains 2400 ms. User-controlled video or game motion keeps its own play/pause controls; do not silently alter the source work as a theme effect.
All durations, distances and gesture thresholds in this section are I. No animation timing is inferred as an existing feature from a screenshot.
Deviations from the live site
- Body size and leading: live site_dark body/bold/italic are 14 px with a 1.35 body-line multiplier. This kit uses 16/24 and explicit role line boxes. It preserves compact 14/20 UI text so increasing prose does not inflate navigation. Exact values are I, chosen to capture round two's readable density without treating generated large type as a measurement.
- Typeface interpretation: Arial, Segoe UI and Cascadia remain the actual bundled families. No new sans is claimed from a raster. The existing 9 px Segoe semibold banner becomes a 12/16 tracked section label; 10 px italic tags become 12/16 upright tracked Arial. Metadata becomes upright. New title/item/UI/ID roles are added. h1–h3 sizes 28/21/16, code14, metadata12 and tweet15 are retained. A serif remains an unloaded future slot.
- Reading scale and layout support: live global font scaling/shared line-gap logic does not provide this kit's separate UI scale or role-specific leading. New role aliases, layout line boxes and fallback classification are needed. This is not achievable by changing only the
body_line_heightnumber. - Spacing: paragraph16, image-before16, quote-before24, h3-before16, head_overflow0 and heading_rule=false stay. h1-before22 becomes24, h2-before18 becomes24, and heading-after12 plus gap-collapsing rules are explicit additions.
- Color roles: live field, primary/secondary/dim, link, alpha neutrals, selection, quote, role and diff values stay. Panel/recess, hover/pressed, focus aliases, washes, scrim and neutral-warning semantics are new exact choices. These new tokens are flat colors, regardless of generated gloss or texture.
- Gold scope: live
artifactis #FFCB5C; ordinary artifact/replay links become #8CB4FF. The gold value is retained in a newcurrentrole for IDs, location and progress. Live amber/orange search washes change to blue for all matches and gold for the current match. This is a deliberate semantic change, not a faithful copy of every old use of gold. - Fable identity: live
colors.driveris already #D97757, butcanvas.luaapplies it to a delegated-run prompter whencurrent_driver == 'fable'. Applying that color to an identified Fable assistant turn is an extension. Do not color every generic Claude/assistant turn orange without identity metadata. - Shell and reader geometry: no sidebar, top-line navigation, the 1440 maximum, 64 desktop nav, new 56 phone nav, 1120 spread breakpoint, 624 pages/528 measure, strips and collection grids are new layout rules. Existing MOBILE_BP768, phone padding16 and scrolling article800/704 are retained. New reader measures do not silently replace every existing article measure.
- Components: current tweet padding14 becomes16; chips and role controls receive standardized dimensions; outlined/filled buttons, edge preview, settings and Continue geometry are explicit new specifications. Artwork, real content and attachment data are preserved. The sheets do not implement these objects.
- Theme scope: site_light and site_dark currently share font, metric, gap and treatment tables. Separate the dark specification where necessary; do not accidentally change light mode by mutating shared tables. Legacy
posts_oldhas its own Source Sans/Source Code and 800/760 metrics. Do not silently rewrite that theme. New dark reader/templates explicitly select the codified identity; changing legacy route/theme dispatch is a separate migration decision. - Behavior and timing: cut0, optional slide120/32, motion timings, touch thresholds, input ownership and content-address persistence are I requirements. Stable block citations, replay synchronization, inline game handoff and reader pagination require feature work beyond a theme-table edit. Display only controls backed by actual capability.
- Raster limitations: sheet microcopy, font substitutions, extra row borders, gradients, gold-colored poster mistakes, approximate proportions and invented page totals are not design tokens. The canonical written values above resolve those errors. Do not reuse generated media as source captures, infer related content from a template arrangement, or attribute a copied Luck sentence to notebook #529/#530.