Foundations

Warm neutral surfaces, one indigo accent, and meaning colours that are always paired with words or shapes. Every value and ratio below is read from app/tokens.css; apps/web/lib/tokens.test.ts enforces the same minimums (4.5:1 text, 3:1 controls and outlines).

Surfaces and borders

Surface and border tokens
SwatchTokenLightDarkContrast light / dark
Canvas--bgLight#f6f6f3Dark#121211Contrast5.48:1≥ 4.56.55:1--text-3 on it
Surface (panels)--surfaceLight#ffffffDark#1c1c1aContrast5.93:1≥ 4.55.97:1--text-3 on it
Surface 2 (headers)--surface-2Light#fafaf8Dark#232321Contrast5.67:1≥ 4.55.50:1--text-3 on it
Surface 3 (hover, selected)--surface-3Light#f0f0ecDark#2c2c29Contrast5.19:1≥ 4.54.89:1--text-3 on it
Border--borderLight#e6e5e0Dark#34332fContrastDecorative divider
Border strong--border-strongLight#d3d2cbDark#45443fContrastButton outline; buttons are named by text
Control border--border-controlLight#85847cDark#7d7c75Contrast3.75:1≥ 34.07:1on --surface
Skeleton--skeletonLight#e6e5dfDark#32322eContrastLoading placeholder

Text, accent and outlines

Text and accent tokens
SwatchTokenLightDarkContrast light / dark
Text--textLight#18181aDark#ededeaContrast17.73:1≥ 4.514.55:1on --surface
Text 2--text-2Light#4a4944Dark#b3b2abContrast9.02:1≥ 4.58.02:1on --surface
Text 3 (smallest allowed)--text-3Light#65645eDark#9a9992Contrast5.19:1≥ 4.54.89:1on --surface-3
Accent (white text on it)--accentLight#4b44d8Dark#5f5af0Contrast6.73:1≥ 4.54.99:1white on it
Accent text--accent-textLight#4038c9Dark#aba8ffContrast6.91:1≥ 4.56.91:1on --accent-subtle
Focus ring--focusLight#4b44d8Dark#8e8bffContrast6.73:1≥ 35.92:1on --surface
Event dates outline--event-inkLight#4a4944Dark#b3b2abContrast9.02:1≥ 38.02:1on --surface

Signals: preparation, timing and alerts

Each foreground is measured on its own tint. Red is reserved for cancelled items and destructive actions; amber explains problems such as missing schedules.

Signal tokens, foreground on tint
SwatchTokenLightDarkContrast light / dark
Warning--warn-bgLight#fff3dcDark#2e230fContrast5.33:1≥ 4.58.34:1--warn on it
Danger--danger-bgLight#fdeceeDark#3a1a1fContrast5.70:1≥ 4.56.91:1--danger on it
Success--success-bgLight#e1f4e8Dark#12301fContrast5.32:1≥ 4.57.80:1--success on it
Info--info-bgLight#e8efffDark#172340Contrast5.63:1≥ 4.57.34:1--info on it
Draft, cancelled--st-draft-bgLight#efefebDark#30302dContrast5.72:1≥ 4.55.88:1--st-draft on it
Preparation--st-draft-bgLight#efefebDark#30302dContrast7.82:1≥ 4.56.22:1--text-2 on it
Live--tm-live-bgLight#ddf4e6Dark#0f3321Contrast4.66:1≥ 4.57.94:1--tm-live on it
Archived--tm-archived-bgLight#efedf7Dark#262338Contrast5.99:1≥ 4.57.54:1--tm-archived on it

Typography

Inter for every working surface, with tabular numerals for dates and counts. Newsreader is used only for page titles, the Overview lede and large figures.

Display · 34/40 · Newsreader 500Lantern Festival
Page title · 28/34Overview
Lede · 18/29 · Newsreader10 launches in the next 14 days across 4 initiatives.
Body · 14/20 · Inter 400Keep each initiative and all its promotional collateral together.
Table · 13/18 · 550Billboard — Route 9 northbound · Thu Oct 1 · 31 days
Meta · 12/16Remove or swap on Sun Nov 1
Column header · 11/16 capsLast day live
Mono · keyboard hintsC⌘K

Spacing, radius and elevation

A 4px base in rem, so Meeting view (112.5%) scales everything. Three radii, clearly apart. Hierarchy comes from surface steps and 1px borders; shadows are minimal.

Spacing scale
TokenrempxSize
--space-0-50.1252
--space-10.254
--space-1-50.3756
--space-20.58
--space-2-50.62510
--space-30.7512
--space-4116
--space-51.2520
--space-61.524
--space-8232
--space-102.540
--space-12348
--space-16464
  • --radius-sm4px · bars, badges, entries
  • --radius-md6px · buttons, inputs
  • --radius-lg10px · panels, menus, dialogs
  • --shadow-1Panels, buttons
  • --shadow-2Menus, popovers
  • --shadow-3Dialogs, sheets

Icons

Inline SVG on a 16px grid with 1.5px strokes. Decorative by default; icon-only buttons take their name from a required label.

  • overview
  • initiatives
  • timeline
  • calendar
  • list
  • archive
  • archive-clock
  • settings
  • search
  • plus
  • minus
  • chevron-down
  • chevron-up
  • chevron-left
  • chevron-right
  • chevrons-up-down
  • check
  • close
  • alert
  • alert-circle
  • info
  • check-circle
  • clock
  • file
  • link
  • paperclip
  • user
  • more
  • filter
  • arrow-right
  • arrow-left
  • open
  • external
  • flag
  • megaphone
  • tag
  • folder
  • rocket
  • pulse
  • screen
  • sun
  • moon
  • contrast
  • sync
  • star
  • star-filled
  • copy
  • edit
  • sort
  • sort-ascending
  • sort-descending
  • log-out
  • keyboard
  • history
  • gantt-mark

Buttons

One primary action per view. Buttons are named by their text; icon buttons always carry a label.

Variants

Link styled as button

Sizes, keyboard hint, disabled and loading

Icon buttons and filter chips

Forms

Every field has a visible label; hints and errors are linked with aria-describedby. Dates are stored as calendar dates in the initiative timezone; the browser's date picker shows its own format, so each date field spells the date out underneath.

Shown on the activation and in search.

Give this activation a label so the team can tell instances apart.

Only editors can change owners.

Tentative dates belong here until they are confirmed.

Date fields

The line under each field echoes the date as the product writes it. “Last day live” is inclusive and explains the removal day (SCHEDULING.md); while a field has an error, that derived helper is withheld.

Sat, Oct 10, 2026 · Dates in Pacific Time

Sun, Nov 1, 2026 · Remove or swap on Mon Nov 2

Last day live can’t be before the launch (Sat Oct 10).

Mon, Oct 5, 2026

Checkbox, radio and switch

Group activations by

Status and labels

Three separate kinds of status, each glyph with one meaning. Preparation is stored (glyph + word). Timing is derived from dates and never stored (small glyph + word). Initiative state uses the badge anatomy with a state glyph.

Preparation status (stored)

Neutral on purpose: hue on a row always means channel, so the glyph’s shape and the word carry the status. Dashed ring, ring, half ring, check, cross. These describe readiness, not publication.

DraftPlannedIn progressCompletedCancelled
DraftPlannedIn progressCompletedCancelled

Timing (derived from dates, relative to today)

Filled dot: live. Ring: starts later. Short bar: ended. Square: archived. Diamond: no dates.

LiveLive · last dayStarts in 3 daysEndedNo datesArchived

Initiative state, kind and badges

One badge anatomy: 20px, 4px radius, sentence case and a 1px border mixed from the badge's own text colour. Draft uses the same dashed ring everywhere. Counts are the only pills.

ActiveDraftArchivedCampaignPromotionEventProject
NeutralAccentAuto-archive blockedFailedSavedInfoNew83 unread changes

Glyphs alone

draftplannedin_progresscompletedcancelled

Channels

Eight canonical swatches (blue, amber, green, rose, teal, orange, violet, slate), ordered so neighbours are far apart in hue. A channel stores one of them and a new channel takes the next, so the ninth below repeats the first. Organizations name and edit channels; a swatch only colours them, with the same values on iPhone. The name is always visible beside the colour and never truncates.

Channel colour slots
SlotDefault nameLight solid / tintDark solid / tintEdge on surfaceText 3 on tint
Slot 1Outdoor--ch1 / --ch1-tintLight#2f6fde / #e4ecfcDark#6fa0ff / #1a2b4aEdge on surface4.71:1≥ 36.62:1Text 3 on tint5.00:1≥ 4.54.93:1
Slot 2On-site signage--ch2 / --ch2-tintLight#b47714 / #fbf0dcDark#f2b54a / #3a2c12Edge on surface3.75:1≥ 39.33:1Text 3 on tint5.25:1≥ 4.54.74:1
Slot 3Wayfinding--ch3 / --ch3-tintLight#3f8f2f / #e5f2e0Dark#74c960 / #1b3317Edge on surface4.05:1≥ 38.34:1Text 3 on tint5.11:1≥ 4.54.79:1
Slot 4Print--ch4 / --ch4-tintLight#c8385a / #fae3e9Dark#ff7093 / #3f1a24Edge on surface5.03:1≥ 36.49:1Text 3 on tint4.86:1≥ 4.55.30:1
Slot 5Email--ch5 / --ch5-tintLight#0e8a86 / #ddf2f0Dark#3cc6bf / #103634Edge on surface4.20:1≥ 38.14:1Text 3 on tint5.09:1≥ 4.54.59:1
Slot 6Social--ch6 / --ch6-tintLight#d2572a / #fbe7dfDark#ff8c5e / #40221aEdge on surface4.08:1≥ 37.44:1Text 3 on tint4.97:1≥ 4.55.02:1
Slot 7Web--ch7 / --ch7-tintLight#7b4fd6 / #eee7fbDark#a98bff / #2a2145Edge on surface5.34:1≥ 36.35:1Text 3 on tint4.93:1≥ 4.55.23:1
Slot 8Partners--ch8 / --ch8-tintLight#5e6e80 / #e9edf1Dark#9daec0 / #252c33Edge on surface5.22:1≥ 37.51:1Text 3 on tint5.04:1≥ 4.54.94:1
Slot 1Press--ch1 / --ch1-tintLight#2f6fde / #e4ecfcDark#6fa0ff / #1a2b4aEdge on surface4.71:1≥ 36.62:1Text 3 on tint5.00:1≥ 4.54.93:1

Channel tag

OutdoorOn-site signageWayfindingPrintEmailSocialWebPartnersPress
OutdoorOn-site signageWayfindingPrintEmailSocialWebPartnersPress

Layout

Flat panels on the canvas. Never nest cards: use group rows, dividers or a key/value strip inside one panel.

Card title3

Description sits beside the title

Card body. Tables and lists usually run edge to edge instead of padding.

Footer notes explain rules, e.g. how counts are derived.Footer link

Attention card

An amber top rule marks panels that need attention without alarm.

Section header

Initiatives

Grouped by channel

A serif title over a 1px ink rule separates groups of panels.

Key/value facts strip

Equal columns of at least 10rem that wrap cleanly. Timezone appears only when an initiative's differs from the organization's (shown once, in the top bar). Secondary facts use the same component.

Owner
Maya Okafor
Event dates
Thu Nov 5 – Sun Nov 8
Promotion
Oct 1 – Nov 132 days
Activations
3in 3 channels · 2 files
Created
Aug 24, 2026
Auto-archive
On
Archive reason
Not archived

Data display

Fixed-layout tables with captions, scoped headers and explicit table roles. Low-priority columns drop first as space runs out; below 768px rows become list items, the header row stays available to screen readers and each cell carries its field name. Titles wrap to two lines; dates never truncate. Sortable headers expose aria-sort and draw an up or down arrow.

Sortable table

Sample activations, sortable by title or launch
PreparationOwner
Billboard — Route 9 northboundLantern FestivalLaunchPreparation: PlannedDaniel Reyes
Newsletter feature — Registration opensLantern FestivalLaunchPreparation: PlannedMaya Okafor
Bathroom flyer — East entranceLantern FestivalLaunchPreparation: PlannedPriya Natarajan
A-frame — Main gateLantern FestivalLaunchPreparation: In progressPriya Natarajan

Preparation mix

Drawn in one ink ramp (solid completed, half-tone in progress, outlined planned, dashed draft) so saturated colour always means a channel. The words carry the counts.

1/5 completed1 completed · 2 in progress · 2 planned3/4 completed3 completed · 1 planned0/4 completed4 draft

Avatars and people

Initials only; no photos. Decorative beside a visible name.

QCPriya NatarajanUnassigned

Activity feed

  1. Priya Natarajan moved the launch of A-frame — Main gate from Oct 18to Oct 20

    · Lantern Festival

  2. Open Studios Weekend archived automatically after its last promotion ended Sep 20

    · Files and dates kept in Archive

Feedback

Distinct loading, empty, no-results and error states. A failed request is never shown as an empty calendar.

Inline alerts

Banner

Empty states

A quiet icon, a serif title, one sentence and the next step. An empty month still looks like a calendar, so it never reads as a failure.

December 2026

No launches in December

Nothing starts this month. Items without dates are under Missing schedules.

Skeletons

Static placeholders for first load only, drawn at the real column widths and row heights with the real headers, so nothing jumps when data arrives. Nothing shimmers or animates on entry.

Upcoming launches

Recently changed

Toasts

Two regions exist before any toast: polite for confirmations, assertive for errors, so each message is announced once. Errors and toasts with an action (such as Undo) stay until dismissed; Alt+Shift+N moves focus to the newest toast. Keep the same undo in the page too.

Overlays

Native modal dialogs: the page behind is inert, focus stays inside, Escape closes, and focus returns to the trigger.

Change the last day live?

Moving A-frame — Main gate to end Nov 4 also moves the initiative’s archive date.

Archive forecast

Explains automatic archiving before it happens, in one typeface and without a clock time (the rule is date-only). The diagram is proportional: the promotion as a neutral range bar, the archive tick, and event dates in the ink outline, with end labels on the top line.

Archives — the day after the last day live, Nov 1

This event will archive after promotion ends on Nov 1. Event dates and preparation status don’t delay archiving.

Auto-archive is blocked

Social – Weekly workshop post and Web – Workshops page have no last day live.

Auto-archive is off

This initiative was restored on Sep 25. Turning auto-archive on with past dates may archive it straight away.

Create flow

The same sequence on web and phone. Step 3 in a sheet: search, All types / My favorites, per-person stars, a − / count / + stepper for several instances, and a shared ‘Add a collateral type’.

Create event · step 3 of 5

Lantern Festival

  1. Kind (done)
  2. Details (done)
  3. Collateral
  4. Schedules
  5. Review

4 types, 5 activations selected.

Which collateral does this event need?

Each selection adds one activation. Add another instance for a second location.

  • Billboard: 1 instance
  • Bathroom flyer: 2 instances
  • A-frame: 1 instance
  • Newsletter feature: 1 instance
Bathroom flyer: 2 instances

Schedule primitives

Documented building blocks for T05, not wired to data. One dataset, two lenses: bars show inclusive live ranges; the calendar lists each activation once, on its first live day.

Timeline bar encodings

Bounded range, one-day item, open-ended (flat edge + OPEN), started before the view (dashed edge + ‹), continues after the view, and event dates as an ink outline with a flag. Past days get a flat wash; nothing is hatched. Labels always state real dates, and each bar's accessible name contains its visible label followed by a full sentence.

Event dates· reference · not promotional
Outdoor Film NightsEvent · Oct 9 – 10
Event dates, Oct 9 – Oct 10. Outdoor Film Nights, reference only, not promotional
Lantern FestivalEvent · after this view
Event dates, Event Nov 5 – Nov 8, after this view. Lantern Festival.
Outdoor1
On-site signage1
Poster — Library branchPlanned · Autumn Clay & Print Workshops
Oct 8 – Nov 20 · 44 days. Autumn Clay & Print Workshops. Live Thu, Oct 8, 2026 to Fri, Nov 20, 2026, 44 days. continues after this view. Preparation: Planned
Wayfinding1
A-frame — Studio courtyardCompleted · Open Studios Weekend
Sep 1 – Sep 20 · 20 days. Open Studios Weekend. Live Tue, Sep 1, 2026 to Sun, Sep 20, 2026, 20 days. starts before this view. Preparation: Completed
Email1
Newsletter feature — Registration opensPlanned · Autumn Clay & Print Workshops
Oct 6 · one day. Autumn Clay & Print Workshops. Live one day, Tue, Oct 6, 2026. Preparation: Planned
Web1
Web banner — Homepage membership promptIn progress · Year-round Membership Drive
Sep 1 – open-ended. Year-round Membership Drive. Live from Tue, Sep 1, 2026, no last day set. starts before this view. Preparation: In progress
Billboard — Route 9 northboundOct 1 – Oct 31Outdoor · Lantern Festival
Newsletter feature — Registration opensOct 6 · one dayEmail · Autumn Clay & Print Workshops
Web banner — Homepage membership promptSep 1 – openWeb · open-ended
  • Live range, first to last day
  • One-day item
  • Open-ended or continues
  • Started before this view
  • Event dates (reference)
  • Today
5 activations · 0 hidden · 0 unscheduled

Narrow screens and assistive technology get the agenda equivalent (TimelineAgendaItem): title, dates and a proportional mini-track with a today tick.

Calendar entries

Channel tint with a 3px channel edge, a two-line title, and “Channel · Initiative”. The channel never truncates; only the initiative does. The event-start marker uses the same ink outline and flag as event dates on the timeline.

Bathroom flyer — East entrancePress release — Artist announcementNewsletter feature — Registration opens for the autumn sessions, a long title that wrapsEvent starts · Lantern Festival

Calendar day cells

Separate examples, each with its month. A cell shows the date (with the month on the 1st and after any gap), a visible launch count, at most two entries, then “+N more”. Today is the filled date chip and the word “Today”. Cells use static table semantics, with the full date and count as text for screen readers.

  • Today, no launches

    Monday, September 28, 2026, today, no launches

  • First of the month, three launches, “+1 more”

    Thursday, October 1, 2026, 3 launches

    • Billboard — Route 9 northbound
    • Poster — Studio corridor
  • One launch

    Saturday, October 10, 2026, 1 launch

    • Bathroom flyer — East entrance
  • Event layer on, no launches

    Thursday, November 5, 2026, no launches

    Event starts · Lantern Festival

App shell

AppShell is presentational: it takes organization, user, navigation, counts and sync state as props. T04 supplies data and routes.

Responsive behaviour

  • Desktop (≥1100px): 240px sidebar with the organization switcher, Create menu (C, which viewers can turn off in the account menu), primary navigation with counts, active initiatives, Settings, sync status and account menu. Opaque sticky top bar with breadcrumbs, search (⌘K), the timezone chip (the one place the timezone appears), Meeting view and theme.
  • Tablet (768–1099px): 72px rail with icon plus visible label for each destination and a short sync word; org tile and square Create keep accessible names.
  • Phone (<768px): opaque top app bar (organization with the timezone under it, sync status, search, Create) and a fixed bottom tab bar: Overview, Initiatives, Timeline, Calendar and More (Archive, Settings, display). Scroll padding keeps a focused control clear of both bars, and on short screens the bars stop sticking.

Sync status (role=status)

One persistent status per layout. Each state has its own shape: filled dot, open ring (turns only when motion is allowed), square, triangle. The phone top bar shows only the dot while synced and a short word otherwise; the tablet rail shows a short word.

Sidebar
All changes synced · just now
Saving 1 change…
Offline · reconnecting
1 item changed elsewhere
Phone top bar
All changes synced · just now
Saving 1 change…
Offline · reconnecting
1 item changed elsewhere