Privacy-Period-Tracker/docs/design
null 0451fbe00a feat: the real brand — Privacy:Period Tracker
The project owner supplied artwork and a full visual brand guide mid-session,
which answers #8: the three marks an agent must not fake now exist because a
person made them.

docs/data/img now holds icon.webp (512x512, 11 KB), logo.webp (1024 long edge,
28 KB) and banner.webp (2176x725, 20 KB) — all webp by magic bytes, all far
under the 512 KB ceiling. Produced from the supplied art rather than invented.

Two things had to be handled rather than converted blindly. The sources render
their rounded corners against black, so a naive crop carried black wedges into
the banner; the corners are flood-filled to the artwork's own ground first. And
the lockup is square, so a 3:1 crop would have cut the wordmark in half — the
banner is the whole lockup on a matching ground, which has no seam to see
because the artwork's edges ARE that ground.

The source PNGs and the guide moved to docs/design/: docs/data/img is for the
three marks the Command Center renders, and its README is explicit that
reference art and exported sources do not belong there.

THE PALETTE, AND ONE DELIBERATE CONFLICT

core/designsystem now carries the guide's colours — deep plum, rich purple,
period rose, lavender mist, and an eggplant dark theme that is never flat black.

§39 of the specification asks for a muted teal or sage fertile window, to hold
it apart from the period colour. The guide is plum and rose throughout and gives
fertility its own pink. The guide wins: it is newer, it is the owner's, and a
teal accent inside this identity would look borrowed from another app.

What §39 was protecting is kept by other means, and this is why the conflict is
safe to resolve that way: the calendar's states differ in SHAPE. A solid disc, a
dotted ring, a continuous ring and a star stay tellable apart in greyscale and
to a colourblind user, which is what §43 actually requires. The departure is
written down in docs/design/README.md rather than left to be discovered.

The launcher icon keeps its vector for now, in brand colours. The supplied
emblem has content close to its edges and an adaptive icon masks about a quarter
of the canvas away, so dropping it in unmodified would crop the shield. Fitting
it to the safe zone is Batch 08's final-artwork work.

closes #8
2026-08-18 15:31:52 -05:00
..
brand feat: the real brand — Privacy:Period Tracker 2026-08-18 15:31:52 -05:00
BRAND_GUIDE.md feat: the real brand — Privacy:Period Tracker 2026-08-18 15:31:52 -05:00
README.md feat: the real brand — Privacy:Period Tracker 2026-08-18 15:31:52 -05:00

README.md

Design

Status: Current
Owner: _null
Last reviewed: 2026-08-18
Governs: docs/design/**, the design tokens in core/designsystem, and the product's
         tone and interface copy
Review trigger: Any new user-facing screen or state; any change to the colour or
                type tokens; any change to notification copy or to a privacy or
                fertility disclaimer

Where the detail is

The screen-by-screen specification and the actual words are ../planning/PRODUCT_PLAN.md, and they are not repeated here — a second copy of interface copy is how two versions of a disclaimer come to exist.

Subject Section it owns
Onboarding, seven screens, with copy §19, §56
Navigation — four tabs §20
Today screen and its six dynamic states §21, §22
Period logging, period end, spotting §23, §24, §25
Calendar states and markers §26
Insights §27
Notification modes, types and flow §28, §29, §30
Incognito launcher §32
Look and feel, visual direction, colour, typography, motion §37§41
Artwork §42
Accessibility §43

This document holds what governs those: the tone, and the rules that decide an argument the specification did not anticipate.

Tone

Calm, private, intelligent, adult. The app is a good utility with warmth — it is not clinical, not childish, not gamified, and not stereotypically feminine as an identity. It never celebrates a period and never alarms about one.

One paragraph, and it settles most small arguments: the app speaks like someone competent who is not making a fuss. "Your period is late!" is out. "Not yet?" with an updated forecast is in.

Four rules that decide the arguments

1. The number is the hero. The forecast dominates the Today screen — §38. Anything competing with it for attention is wrong, including anything of ours.

2. Nothing asserts certainty the model does not have. A window and a confidence label, never a bare exact date presented as fact. "Estimated ovulation", never "you are ovulating today". Fertility copy carries the not-contraception line wherever it appears.

3. State is never colour alone. Confirmed period is a solid fill, predicted is dotted or outlined, fertile window is a ring, ovulation is its own small marker — distinguishable in greyscale, because that is also what makes them distinguishable to a colourblind user and to a screenshot in a bug report. Predicted and confirmed days must never look identical.

The banner space is reserved before there is an ad to put in it. §48 wants no layout jump when one loads and a graceful gap when one fails, and both are properties of the space existing whether or not it is filled. Retrofitting the reservation in Batch 07 means shipping the jump first and finding it in a QA round. It is empty and invisible now — deliberately not a "your ad here" box, which would be a placeholder for the thing a user pays to remove.

4. Ads never touch a health action. No banner in onboarding, in the period-start confirmation, in the period-end confirmation, or between steps of a health workflow — and never an interstitial after logging (§33). Banner space is reserved in the layout so a failed ad does not move the content.

Colour

The palette is BRAND_GUIDE.md, supplied by the project owner on 2026-08-18. It supersedes the sketch in ../planning/PRODUCT_PLAN.md §39 where the two differ, and one difference is worth stating rather than leaving to be discovered:

§39 asks for a muted teal or sage fertile window. The brand guide is plum and rose throughout, and gives fertility its own pink (#E891AE).

The guide wins — it is newer, it is the owner's, and a teal accent inside this identity would look borrowed from another app. What §39 was protecting is kept by other means, and this is the part that matters: the calendar's states differ in shape, not only in colour. A solid disc, a dotted ring, a continuous ring and a star stay tellable apart in greyscale and to a colourblind user, which is what §43 actually requires. Colour is the second signal here, never the only one.

The two rules from §39 that survive unchanged, because they are product decisions rather than colour preferences:

  • Period state is a sophisticated rose or plum — never graphic blood-red.
  • Nothing reads as "safe". The fertile window is pink rather than green for the same reason the labels say "Lower likelihood": this app never gives permission.

Everything goes through Material 3 colour roles and centralized tokens in core/designsystem. No hard-coded colours in a Composable — a colour literal outside the token file is a review failure.

Both themes, every time

Dark mode was broken for the whole of Batch 01 and nothing said so. PeriodTheme was not wrapping its content in a Surface, so any Text without an explicit colour inherited Material's default — black — and the app's own background never painted at all. In light mode that looked correct by accident, because dark text on cream is what was wanted anyway; in dark mode the onboarding headings were near-black on charcoal.

No test caught it and no test easily would. It was found by opening the app.

Two rules follow. Every screen gets a preview pair, light and dark — cheap, and it puts the failure in front of whoever is editing. And the Surface lives in the theme rather than in each screen, so a screen without a Scaffold cannot forget it.

The states most often left undesigned

Designed here on purpose, because they are the two most people meet first:

  • Empty — no periods logged yet. It has to make the next action obvious rather than apologise.
  • Learning — one or two cycles recorded. The app says it is still learning rather than showing a confident forecast it has not earned. "Getting to know your pattern", not a percentage.

The artwork is placeholder, and says so here

Every illustration and calendar marker in the app is a Compose vector path in core/designsystem/src/main/kotlin/dev/privacyllc/period/designsystem/art/, written as PRODUCT_PLAN.md §42 asks: polished placeholders behind replaceable names, so real artwork changes one function body and no call site.

The visual language is deliberately narrow — overlapping circular forms and nothing else. §42's forbidden list (blood drops, tampons, pads, uterus imagery, gender symbols, anatomy) is a product decision rather than squeamishness: this app gets opened in public, and somebody glancing over a shoulder should learn nothing. That is a property of the pictures as much as of the notification text.

Note the deliberate inconsistency with docs/data/img/, where a placeholder is forbidden. The rule there is that an image which looks finished outlives the issue that would have replaced it, because nobody files a ticket against something that appears done. In-app assets escape that because §42 asks for them explicitly and the replaceable-name mechanism is what keeps them replaceable — and because a screen with no illustration cannot be evaluated at all, while a project card with no icon simply shows initials.

Include the rejected version

For any decision that was genuinely close, record what was not chosen and why. Without it the same option is proposed again every few months and re-argued from nothing. The first entries belong to whoever makes those calls; the specification's Avoid: lists are already a partial record of them.

What does not belong here