Bon-po Counter

Design system for the calm prototype. The same tokens and components power this page and the practice screens: quiet book typography, muted maroon, complete images and a fine double rule.

Working extraction · 1 November 2026. English interface, original sacred texts. Prototype components; React Native adaptation remains a separate step.

Foundations

Roles come from the current calm source. Changing the theme changes these shared values everywhere; text and actions keep their meaning.

Required font families

Use only the existing calm fonts, through shared tokens. A different family or role requires the owner's explicit design decision before implementation.

RoleFont & token
Controls, labels, dates, metadataPlatform system UI; SF on Apple
font.ui / --font-ui
Reading in Cyrillic/Latin, titles and book rolesGentium Book Plus; local alias Book
font.book / --font-book
Tibetan source text and namesJomolhari; local alias Uchen
font.tibetan / --font-tibetan

New and edited text uses type.*.family or font.* tokens. No component-specific font stack, new font file or external font import. Older Inter / Literata / Noto proposals do not replace this stack. Generic serif/sans-serif fallbacks are recovery only: verify the fonts actually rendered, including Cyrillic and Tibetan, rather than the CSS family list alone.

Text-size controls change existing reading size/line-height pairs, never the font family or sacred text. These fonts apply to control labels and letter samples too; letter icons stay in the shared icon family. Check local font loading, both themes, narrow and large-text states. Native shaping and system text scaling remain separate checks. Full contract: redesign/DESIGN.md, “Font contract”.

Token source, values and provenance

One authored source: system/tokens.json. CSS and JavaScript are generated from it. Tibetan row headings use the approved 15 pt size.

Actions

+N remains the main counting action. A compact visual control can have a larger touch area. Every example below is a call to the shared component library.

Buttons

Button · IconButton · IncrementButton. Focus with Tab; press and hold to inspect the active state.

Speed & Loop

The visible cycling button is accepted. 1x → 1.5x → 1.2x is the owner's example; the final multiplier list is still open.

The examples do not add to practice history.

Spacing & form actions

One owner per space: the container supplies the outer inset, the component supplies its inner padding, and the group supplies the gap. Compact forms share 12px between groups, 6px from label to field and 8px from field to suggestions. Cancel and Save share equal columns, target size, padding and typography; Save keeps the primary action colour.

Container20px · screen and sheet edges
Component12px · field / plain chip inset
8px · illustrated chip inset
16px · action / compact player inset
Group6px · label
8px · suggestions
12px · fields and actions
18px · section / footer separation

These are incumbent measurements and semantic aliases of shared tokens. Border compensation stays inside the component. Sheet footer safe-area is applied once. Reading controls retain their adaptive inset; slider-thumb alignment is geometry, not spacing.

Equal actions · long labels

A long label wraps inside its column; both buttons grow to the same height. The footer stays outside the form scroll area.

Forms

A label names the value; the error sits beside its field. All quick-fill chips share a light contour, including material, date, Count and Step. Chip labels use neutral text in both themes: selection is shown by fill, a stronger contour or a check, never red lettering. Disabled quick values use secondary text. This rule covers material, date, Count, Step and sound choices through the shared components. This example exercises presentation and validation feedback without storing an entry.

Add count

Disabled & selected

Disabled field, switch, choice and button states use the same primitives as the prototype.

Material choice

The Diary entry form and this specimen share MaterialChoice: whole artwork, full source name with a personal display name, and whole-row single selection without radio circles. A check marks only the current value. MaterialSelect retains that same whole preview after selection. Four MaterialSuggestions reuse the Date/Count quick-fill treatment. Each chip follows its name width: short names share a row, long names wrap naturally without an ellipsis. MaterialSelect and MaterialChoice keep the full name, a whole preview and a separate trailing control. The anchored MaterialPicker keeps name search and a single scrolling result list.

Collapsed field → choose → return

Tap a row to select and close. Arrow keys move focus; Enter selects. Escape closes without changing the value. The form is saved separately.

Errors & recovery

ErrorState owns error codes and field state. ErrorMessage owns presentation, accessibility and placement. These are explicit fixtures: no data is saved and no network request is made.

Independent field errors

Save failure

Recording & image recovery

CoverImage

Full covers fill their own column with natural proportions. Portrait, square and landscape sources share the same component; thumbnails retain their compact slot. A tall cover scrolls inside a short player while its transport stays fixed. No crop or distortion.

The existing responsive candidates may not meet 2×/3× density at full width, especially for portrait sources. Display size is not a claim of extra source detail.

Practice & dates

Opening a material, recording a step and opening its menu are separate actions. Today and Total stay light. A prayer never acquires a +N button. Display Name follows the original title in parentheses and replaces the Tibetan duplicate in that row.

Practice rows

The long-title stress fixture has no supplied image.

Tibetan row titles are approved at 15 pt. A personal Display Name replaces the Tibetan duplicate in that row.

Selected day

Open Day count to read the full composition.

Diary row

Audio

One source identity, Play/Pause, timeline, visible speed and Loop. Photographs are used only for verified sources; missing photos have initials.

Compact player · 2×2 controls

One line per name, ellipsis on narrow screens. Text / Thangka and Repeat above Play / Speed. The source row chevron opens Cover. All four controls are borderless44px targets.

Open interactive stand →

Ready, loading, playing, paused, buffering, interrupted, error, ended and empty use the shared phase contract. Each is an explicit visual fixture. No sound, downloads, device callbacks or real cache.

Recording sources

Nam Par Gyal Wei Yig Gya · these three sources belong to this material.

Source grouping and identity are accepted. Selecting a source here only inspects its selected state; each recording launches on its material page with its own Play/Pause.

Recording launch

On a material page, every recording has its own Play/Pause. Teachers use portraits; song versions show the material artwork with title and performer below it. The same RecordingLaunch factory renders this specimen and the interactive stand.

Material recordings

Loading & error

Visual specimens only. This page does not load or play audio.

Panels

Reusable containers and action rows. These specimens are shown in the document so their contents remain easy to inspect.

Practice actions

Audio panel

Now playing above practice and explicit Play after picker selection are accepted. Additional-screen visibility and Close remain open. This specimen does not navigate.

Entry sheet

Diary opens a partial-height sheet above the list. Date, a collapsed mantra choice and Count stay compact; the same BottomSheet shell keeps the header and actions outside the scrollable body. The controller owns yesterday, ranking and Save.

Reading

Approved 4 November: one 44 px row with independent languages and a neutral numeric font size between minus/plus. No size caption or additional line; settings disclose to the left without moving the source text.

Icon controls and the material title stay outside the double rule. The rule contains only the source text, including its original headings. Tibetan, Transliteration and Russian are independent layers.

Ngo Wa Monlam

Reading icons

Tibetan · Aa for transliteration · RU for Russian · text size. A small filled mark means the layer is shown; an unfilled mark means hidden. Minus/plus change size. The neutral number shows the visible book size, or Tibetan size when only Tibetan is visible. Text settings reveals the row to its left over the section heading, keeping the text and trigger stationary.

Text and layers

Book: Gentium Book Plus, Latin and Cyrillic. Uchen: Jomolhari. Source words are read directly from the current material-layers.js; Cyrillic transliteration is not mistaken for Russian.

The existing four text sizes are preserved. Try the largest size and scroll through the complete original text.

Reading size is shared; languages are remembered per prayer, with available text as fallback. Source-edition questions remain open. This page keeps only temporary specimen state.

Shared component imports
<link rel="stylesheet" href="system/tokens.css">
<link rel="stylesheet" href="system/components.css">
<script src="system/tokens.js"></script>
<script src="system/icons.js"></script>
<script src="system/components.js"></script>

Reuse & native

The catalogue imports the library used by calm. It never imports the prototype's counters, accounts or audio state machine. HTML is a visual and interaction reference, not ready-to-ship TSX.

Shared partCurrent React Native starting pointAdaptation still needed
Tokens, type & themessrc/theme/tokens.ts · global.css · ui/TextTheme adapter, native fonts and glyph/licence verification.
Buttons & fieldsui/Button · Input · Label · Switch · IconVariants, native targets, state and text scaling.
Rows & datesMy Practice · Diary · existing repositoriesShared rows, selected date and genuine local counts.
Panels & readingui/Dialog · DropdownMenu · catalogue/[id]Native focus/return behaviour, Aa, layers and scroll.
AudioAudioPlayer · audio-cache serviceOne real session owner, rate/loop callbacks, offline and OS behaviour.
Example of a shared call
CalmSystem.incrementButton({ count: 100 });
CalmSystem.speedButton({ value: "1x", next: "1.5x" });
CalmSystem.practiceRow({ name, displayName, image, today, total, step });

PracticeSkeleton

Initial account load, accepted 9 November 2026. Static placeholders use PracticeRow columns and keep unknown totals hidden. Date and tabs are paused; Profile stays available. Three decorative rows do not predict the number of practices.

ContentSkeleton / LoadingRegion

Accepted 10 November 2026. Unknown content only; known controls and email stay visible. Ready uses the control crossfade; Reduced Motion is immediate. These are live shared factories.

Diary

Source text — no ReadingFrame

Unknown Profile name

Account delivery & review

Author’s account steps 1–8, accepted 11 November 2026. These specimens call the shared templates. Data and account results remain with the host.

Delivery

Transfer

Older history