Shorex Design System

Principles · 6

One vocabulary, two contexts · numbers in mono · show the math · cost models named & colored · don't invent mechanisms · informational blue accent (never status)
One vocabulary, two contextsAtoms, type, spacing, principles shared. Palettes split by context. Track colors carry semantic across both.
Numbers in monoJetBrains Mono = readouts & labels. Inter = titles & prose.
Show the mathCalcs render as visible arithmetic, not a single number.
Cost models named, typed, coloredEvery tour has exactly one; the colored pill anchors it.
Don't invent business mechanismsUI visualizes the data model. New field needed? Extend canonical model.
Informational blue for accent · never statusSelected/active states use --track-content (#4f7cac). Status colors stay reserved for state (healthy / warn / critical / refund).

Export prompt · canonical source · paste into another LLM

B Business export b Backend export
What's in itAll canonical CSS variables (Business + Backend palettes, semantic, tracks, cost-model, accents). Type ramp. Scoping vocabulary (3 axes). 6-app roster with primary tracks. Strict page structure (topbar / tool switcher / sidebar chrome / page head) with full HTML examples + rules. Within-screen atoms list. Entity names + don't-invent rules. 6 principles. 5 anti-patterns.
How to useCopy → paste as system prompt → ask the LLM to build screens. It will use canonical class names, follow page structure rules, respect principles + anti-patterns.

Tokens · 41 · 8 groups

surfaces · borders · text · semantic · accents · cost-model · warm · tracks  ·  flip to Detail to browse + copy individually
surfaces 5 · navy
--bg
#0c1521
--elev
#142033
--elev-2
#1a2942
--card
#16223a
--card-hi
#1d2c47
borders 3 · navy
--border
#243246
--border-soft
#1d2a3c
--border-hi
#324562
text 4 · navy
--text
#e7eef9
--text-mid
#95a4bb
--text-dim
#5e7090
--text-faint
#3e526e
semantic 5 · state colors
--healthy
#46d28a
--warn
#f5b95a
--critical
#f47272
--info
#5fb4ff
--refund
#c98ee5
accents 3 · CTAs & chart
--accent-yellow
#f5c247
--accent-cyan
#5fd6cc
--accent-coral
#ff9a6a
cost-model pills 5 · brown family · cousins of --track-cost
--cm-flat-pax
#a8957a tan
--cm-tiered-pax
#9a8c5f olive-br
--cm-base-pax
#b07b56 brown
--cm-per-vehicle
#c89554 ochre
--cm-per-pax-min
#a36a52 red-br
warm surfaces + text 8 · via .theme-warm
--bg
#f0eee6 cream
--elev
#faf9f5
--elev-2
#f5f3eb
--card
#ffffff
--border
#d4d4cf
--text
#2a2a26 ink
--text-mid
#6a6a64
--text-dim
#999992
track colors 5 · shared semantic
--track-revenue
#7a8f4a olive
--track-cost
#c08552 brown
--track-capacity
#5e8a9c steel
--track-content
#4f7cac cool
--track-dispatch
#8a5e7e plum

Scoping vocabulary · tracks · lifecycle · viewing context

Three axes that classify what a surface is for. Components carry these as tags; the Business tab uses them as filters. The Data Adaptor's scoping picker (built in-app from the atoms on the Backend tab →) is its user-facing realization.

Tracks · 5 concerns · same color, two forms

What aspect of the data. .tag.tag--track-* as passive label · .concern-pill.concern-pill--* as in-picker toggle (warm cream context). Both use the same 5 track colors.

As tag · passive label
revenue cost capacity content dispatch

used on component cards · filter chips · tag rows

As concern pill · selectable

idle · selected (filled) · hover (thicker border)   add .concern-pill--selected for active fill

revenue · what guests paid   cost · vendor charge   capacity · seats / utilization   content · descriptions, media, info-flow   dispatch · physical ops

Lifecycle level · 5 levels of zoom

How wide the lens is. Drives what the surface aggregates over.

season voyage tour day departure bus

Fleet view rolls up season · voyage. Operations live at tour day · departure. Dispatch lives at bus (the brief, data-intensive moment of execution).

Viewing context · 2 audiences

Who the surface is built for. Drives information density, vocabulary, and what's exposed.

guest experience operator detail

guest experience · what the guest paid for · tour name, time, price, simple state (Front Desk Portfolio, Folio line items)  ·  operator detail · what the ops team needs to run the day · financials, vendor cost, manifests, dispatch (tty, Planner, Folio Resolver)

How this gets used

Every Business component carries data-tracks · data-levels · data-contexts · data-surfaces. The Business tab's filter row uses these to narrow what's shown. The Data Adaptor's in-app scoping picker is the user-facing realization of the same vocabulary — picking lifecycle level + concern tells the adaptor what to surface. The Backend tab catalogs its building blocks (lifecycle cards, concern pills, numbered step header, concern group).

Type · shape · spacing

Page title
INTER 22/600 -0.005em
Section heading
INTER 15/500
Body prose — explanations, tour names
INTER 14/400 --text-mid
$1,360
MONO 28/600 -0.01em · readout
STAT LABEL
MONO 11/600 +0.14em --text-dim
Radii--r-card 10 · --r-pill 6 · --r-badge 4 · --r-circle 999
Spacing4 · 8 · 12 · 16 · 24 · 32 — vars --s-1--s-6
Topbar height56px standard

Atomic primitives

LABEL
.pill
LABEL
$1,360
secondary
.metric-card
40 pax × $34 = $1,360
.calc-line
min
.fill-bar
[Title]
meta · line
.identity-strip
.btn · .btn--primary · .btn--primary-alt · 3 variants × 3 states
.btn
.btn--primary
.btn--primary-alt
columns: idle · hover · focus   rows: ghost · solid yellow · outlined yellow
.toggle-group · .toggle
Port today
[Port name] 08:00–17:00
.topbar-slot
84°F · Sunny · NE 6 kt
.weather-pill
9:04AM
WED · MAR 18
.live-time
JM
[User name]
Shorex Manager
.user-chip
Spot Market Soon
.soon-badge
No guest records
.warn-chip

Surface atoms · page-head · frame-card · timeline-row · tour-card

Mid-level compositions extracted from the Manager Dashboard. All use var() tokens — adapt to either context via cascade.
.page-head · .page-head-title · .page-head-sub · .page-head-actions

[Page title]

[sub line · context · counts]

.frame-card · .frame-head · .frame-label · .frame-collapse
[Card title] · [context line]
[Card body — any composition]
.timeline-axis · .timeline-row · .timeline-track · .timeline-bar
08:0010:0012:0014:0016:00
8:30 AM[Item A]
36/40 At gate
10:00 AM[Item B]
28/30
.tour-card · .tour-time · .tour-mgn-badge · .tour-cap-bar
8:30 AM
4H
AT GATE
MGN $1.5k55%

[Tour name]

[Vendor] · ★ 4.8 · TIERED / PAX

.page-metric-strip · .page-metric · .walkup-bar
Metric 1
180
[sub]
Metric 2
$19.0k
[sub]
Metric 3
$10.7k
[sub]
Projection
+$0.0k
[sub]
.dev-source-block · .dev-source-label · .dev-source-pick · .dev-source-link + warn-chip · user-chip
Data source
View / export test data
No guest records
JM
[User name]
Shorex Manager
.date-nav · .date-link · .is-active
.page-headTop of every Business page. h1 + sub + right-aligned actions. Actions: 0–4 buttons; last 1–2 may be primary.
.frame-cardTitled section wrapper. Used for Day at a glance, Day P&L, Tours today, anything that needs a labeled boundary.
.timeline-rowTime-axis + per-item rows with positioned bars. Active state via the .at-gate nested chip on the bar.
.tour-card2-col grid item. Time/duration/state on left, margin badge top-right, capacity bar at bottom. Drop in any Business surface that lists tours.
.page-metric-strip4-card grid with 1px-gap (border shows through). Smaller than .metric-card — page-level summary, not detail. Variant value colors: --healthy, --accent.
.walkup-barSegmented projection bar that nests inside a .page-metric. Two segments: .seg-pos green + .seg-warn red.
.date-nav / .date-linkPer-app sidebar date selector with left-border active accent (yellow). Used in Manager Dashboard for Today / Tomorrow / Yesterday / Overall.
.dev-source-blockSidebar-bottom dev affordance — Mockup/Test toggle, "view/export test data" link, warn-chip, user-chip. Hidden in production builds. The .ide-link (inline < > SVG next to "Data source") opens the IDE in a new tab — subtle (50% opacity), brightens on hover. Plain <a> with target="_blank" rel="noopener noreferrer".

Filter chip row · chips × dimensions · used at top of tab panes

Multi-dimensional filter chip row. Each chip carries data-filter-dim + data-filter-value. Sections being filtered carry data-{dim} with space-separated values. AND across dimensions · OR within. Untagged sections in a given dimension are permissive (always pass).

Track Level showing 3 of 8

3 chip states · idle · pressed (aria-pressed="true") · hover (3rd Track chip)

AnatomyGroup label + chips, repeated per dimension. Optional result count + clear button. One filter-row per tab pane.
Active statearia-pressed="true". Border + text adopt the dimension's accent color (track family carries its semantic).
Match logicAND across dimensions (cost AND tour-day). OR within (cost OR revenue). Untagged dimension on a section = permissive.
CountLive "showing X of Y" appears when any filter is active. Hidden when cleared.
PersistencePer-scope localStorage key (shorex-ds-filter-{scope}) so the filter sticks across sessions and tab switches.
A11yEach chip is a button with aria-pressed. Clear is a separate button. Keyboard nav follows the source order.
When to use

When a tab pane has more than ~5 sections AND those sections cleanly partition along the scoping vocabulary. Below that threshold, a flat ladder is fine — filters add cognitive overhead, only earn it when there's enough material. Realized today on the Business tab; ready to drop onto Backend when it grows past 3 sections.

Streamline | Detail toggle · per-card density axis · variant of .toggle-group

.toggle-group.level-group
streamline default · expert-first
[Card name]
essentials · always shown
rare info · hidden until Detail picked
[Card name]
essentials · always shown
rare info · visible in Detail
PurposeSecond density axis, separate from the collapse accordion. Streamline = at-a-glance essentials for an expert daily. Detail = useful-but-rare info.
Defaultstreamline — experts want essentials first.
Active accent--track-content (#4f7cac), informational blue. NEVER a status color.
Mount → injectOne template (levelToggleHTML()) so the toggle never drifts. Card carries data-level="streamline|detail"; CSS hides .detail-only when streamline.
AccessibilityContainer role="radiogroup" aria-label. Each button role="radio" aria-checked. Tooltip on :hover + :focus-visible. No native title=.
PersistencelocalStorage['shorex-level-<cardId>']. Distinct from collapse accordion's shorex-density-<cardId>.
IconsRect-bar motif. Streamline = 2 bars · Detail = 3 bars. More rows → more detail.
Variation worth knowing — minimal-by-health

In the Connections card, Streamline goes further than hiding .detail-only: a healthy feed collapses to a one-glance pill (dot · name · freshness · status), while a feed needing attention (attn) stays fully expanded. "Streamline" there means show me only what's wrong, not uniform trim. Per-card override of the default behavior — document explicitly when used.

per-card · drop in via .level-mount · let JS inject the template use across both Business and Backend cards hand-write the two buttons (template drift) color active with a status color · use only --track-content conflate with collapse accordion (different storage key, different axis)

Guidelines

Use whenA card mixes expert-essentials with useful-but-rare info. Streamline hides the rare; Detail reveals it on demand.
Don't pair withSurfaces where every field is workflow-critical. If hiding any breaks the task, the toggle is wrong — restructure the card instead.
Distinct from collapseCollapse = "is the card open?" Density = "how much shows when it is?" Both can coexist on one card with separate persistence keys.
One template, many mountsDrop a single <span class="level-mount"> at the desired position. initCardLevel() injects buttons from levelToggleHTML() — never hand-write them.
Cross-contextSame markup in Business and Backend. The cascade adapts surfaces / borders / text; the active accent (--track-content) is globally locked.
NamingBase atom = .toggle-group. Density variant = .level-group. Future variants (period, sort, scale) get their own .foo-group modifier — don't pile semantics onto the base.
When the variation mattersIf "what's worth showing" depends on a card's data (e.g. health), document that override explicitly — see Connections callout. Otherwise the structural .detail-only hide is the default.

Cross-app exports · 6-app suite · the contract

Six apps share one shell. Every primitive listed here renders identically across the suite — that's what makes the apps feel like one product instead of six. The catalog is the contract.

The 6 apps · primary track per app

Track assignment is editorial — drives the dot color in the tool switcher and informs analytic groupings. Adjust as apps evolve.

Financial & Hospitality Hub revenueFront-of-house · payments · guest experience
Resolver costFolio cost reconciliation · shorex-side credits
Shorex Dispatch dispatchPhysical operations · vendor handoff · day-of
Budgeting & Forecasting capacityFleet utilization · year-view treemap
Sales Rate Management revenueRate setup · pricing strategy
Data Adaptor contentData plumbing · system-of-record sync · Backend context

What's shared · index of cross-app primitives

Topbar56px standard · brand + crumb + actions → spec ↓
Tool switcherSidebar app list with track-dot per app → spec ↓
Sign-in / HelpBottom-of-sidebar chrome → spec ↓
Scoping vocabularyTracks · lifecycle · viewing context →
PaletteTrack colors · both context palettes →
Type · shape · spacingOne ramp, one spacing scale →
AtomsPill · metric-card · calc-line · fill-bar · identity-strip · btn · toggle →
Streamline | DetailPer-card density toggle →
Filter chip rowMulti-dim filtering pattern →
Canonical data model17 entities · GO-DaniShorex adaptor →
Drift is the enemy

If two apps render the topbar at different heights, or the tool switcher uses different dot colors, the suite stops feeling like one product. Audit every release. Any inline style that duplicates a token gets migrated, not tolerated — see Commitments · Drift.

Tool switcher · sidebar-bottom · 6-app list

Same component, both contexts. Active row replaces the arrow with "YOU'RE HERE"; others are external links to sibling apps.

Anatomy.tool-switcher wraps a uppercase mono .tool-switcher-label + a vertical .tool-switcher-list of .tool-link rows.
Each rowtrack-colored .tool-link-dot + app name + right-aligned arrow (or YOU'RE HERE).
Active state.tool-link.is-here — no hover bg, arrow replaced by mono YOU'RE HERE, dot gets a ring (own color over card bg).
Order is fixedSame 6, same order, every app. Order = roughly the cruise lifecycle (sales → resolution → dispatch → analysis → admin).
Dot = primary trackFrom the roster above. If an app's primary track changes, update once here; every app's switcher inherits.
A11yThe active row is not a link (no href); it's a <a> with aria-current="page". Other rows are external links → render with to signal off-app navigation.
Anti-pattern

Don't reorder per-app, don't hide the current app from its own list, don't swap the dot color based on state (e.g. red for "needs attention"). Status belongs on the destination app, not on the switcher row — keep the switcher boring and predictable.

Topbar · 72px multi-slot · canonical

Brand chip · labeled info slots · spacer · weather pill (cruise context) · live time. 72px tall. Built from .topbar-slot + .weather-pill + .live-time atoms.

Business · navy
M
SHOREX
[Cruise itinerary]
Ship
[Ship name]
Voyage
Day 4 of 8 · 2,650 pax
Port today
[Port name] 08:00–17:00
84°F · Sunny · NE 6 kt
9:04AM
WED · MAR 18
Height72px standard. Tall enough for label + value per slot.
Brand chip28×28 mark + 2-line label (app name caps + cruise-itinerary sub). Mark uses the app's accent color (Manager = yellow). Bordered right edge separates from the next slot.
Info slots0–4 labeled .topbar-slot blocks (ship / voyage / port / etc.). Each is label (mono caps, dim) + value. Right-bordered for visual rhythm. Actions don't live here — they live in the page header.
Weather + timeRight-aligned chrome. Weather pill is a cruise-app pattern (shipboard ops care about conditions). Live time shows current local time + date.
BordersBottom border + per-slot vertical borders, all --border. Background is --elev.
Per-app brand colorMark color is the app's accent — Manager yellow, future apps get their own. Don't reuse the same accent across two apps.
Cross-app contract

The topbar is the strongest signal of "this is the same suite" — every app uses the same height, slot pattern, brand chip placement, and right-chrome layout. Apps with no port/voyage context can drop those slots; the slot pattern remains. Actions live in the page header (h1 + right-aligned action group), never in the topbar.

Sidebar-bottom chrome · user chip · data source · sign-in (alt)

Lives at the bottom of every app's sidebar. Logged-in is the canonical state — user chip + (dev) data-source affordance. Logged-out shows the sign-in button instead.

Logged-in · canonical
Data source
View / export test data
No guest records
JM
[User name]
Shorex Manager

Logged-out · alternate state

Sign-in screen only
User chip28×28 initials avatar + name + role (mono caps). Clicking opens the account popover (tool switcher + sign out + settings).
Data source toggleMockup / Test segmented control. Dev/staging affordance — hidden in production builds. Uses the base .toggle-group with tight (5×12 padding) sizing.
IDE shortcutInline .ide-link next to the "Data source" label — small < > SVG chevron at 50% opacity, brightens on hover. Real <a>, target="_blank" rel="noopener noreferrer". Subtle by design — devs find it when they need it, end users don't see it.
Warn chipInline state surfacing — dot + caps label on a tinted bg. Use for system-level conditions (missing data, stale sync) not user actions. See .warn-chip atom.
Sign-in (logged-out)Inverted fill — background: var(--text); color: var(--bg);. Only renders on the login screen. Once authenticated → user chip replaces it.
Help buttonOptional. Lives next to sign-in in the logged-out state; in logged-in, help lives in the account popover.
Tool switcher lives in the account popover

Per the v0.16 design, the sidebar-bottom is data-source + user chip — there's no real estate for the 6-app tool switcher. Clicking the user chip opens an account popover that contains the tool switcher + sign-out + settings. See Tool switcher for the list spec.

Entity names · 17 canonical · use these in copy & field names

canonical-model.json →

When a label refers to one of these things, use the canonical name. Tour, not "excursion." Voyage, not "cruise." Vendor, not "operator" or "supplier." Designers don't need the full schema — owners, source-limited fields, mappings live in canonical-model.json for when engineers wire it up.

lifecycleseason · voyage · port_call · tour_product · tour_instance
operationsvendor · dispatch_unit · guide · guide_assignment
peopleguest
bookingsbooking · tender
moneyrate · cost_rate · discount · credit_ledger · fx_rate
When to reach for these

Any time a screen displays or labels a real-world thing — a tour, a vendor, a guest, a payment. Use the canonical name in copy AND in the data-* hooks on components. Inventing freeform field names (excursion_id, supplier, passenger) breaks the contract with the data layer. If a label feels like it needs a new entity, that's a flag — extend the canonical model, don't fork it.

Commitments · 10 · how this catalog stays sane

Tools, not pagesThe catalog houses primitives (atoms, patterns, page chrome). Pages live in apps, built from these. Don't paste rendered page demos here — extract the atoms, then delete the page.
Lift before forkSee a pattern in 2+ surfaces? Lift to a canonical class name immediately. No namespace prefixes (no .md-*, no .biz-*). Atoms scope by purpose, not by app.
Bg color tells contextApps don't know they're "Business" or "Backend" — those are designer mental models. Navy :root vs warm .theme-warm IS the signal. Don't add explicit context labels in app UI.
Streamline by defaultThe catalog defaults to streamline mode for experts. Mark explainer content .detail-only — anatomy callouts, when-to-use, anti-pattern callouts, spec dense-lists. Renders + tag rows + class names always stay visible.
Catalog + prompt update togetherThe spec lives once as <pre id="ds-prompt-source"> in the catalog; prompt.html mirrors it for standalone export. When the design system changes, update both.
DriftAudit surfaces each release. Inline styles that duplicate tokens get migrated, not tolerated. Use var() tokens, not literal hexes.
PromotionA pattern earns "component" status after 3+ uses in 2+ surfaces. Until then it stays a pattern — no abstract API, no public class name commitment.
Token sprawlNo literal-color tokens. Semantic (--healthy), domain (--cm-per-vehicle), or track (--track-cost) wrappers only.
A11yFocus rings + contrast verification when a component reaches v1.0. Don't ship visual without keyboard. role + aria-* on interactive groups (toggle-group, filter chips, concern pills).
IntentEach component states why it exists, not just what it is. Why is in the description + when-to-use callout. No intent → rejected.

Anti-patterns · 4

Plain text cost-model captionUse .pill.pill--cm-flat-pax, not COST MODEL · FLAT PER-PAX caption.
Bucket as per-seat dead weightvehicle_flat = flat per vehicle. Empty seats = unsold capacity, not cost. Phantom pax lives on PER-PAX-W-MIN.
Invented business mechanicsNo fictional wallets / flows / tour names. Use [Tour name] placeholders + structural language.
Context confusionNo dark-navy Data Adaptor. No warm-beige Planner. Visual context is part of the affordance.

Business

Track Level
View Surface

Ways cost can show · 7

cost operator detail
01 Calc line show the math, scales across all cost models
FLAT/PAX40 pax × $34 = $1,360
TIERED/PAX36 pax → tiered = $1,218
BASE+/PAX$1,100 base + 44 × $22 = $2,068
PER-VEHICLE2 vehicles × $1,100 = $2,200
PER-PAX-W-MINmax(15, 20) × $40 = $800

tty modal · Planner per-tour row · budget-forecast tile

02 Vendor cost card middle of the 3-card strip
VENDOR COST
$1,360
$34/pax

tty modal · Planner expanded panel · budget-forecast tile

03 Cost-vs-pax sparkline thumbnail showing cost-model shape, right of a tour row
PER-VEHICLE TIERED/PAX FLAT/PAX

Planner per-tour row · budget-forecast tile compact

04 Big cost-vs-pax chart cost + revenue lines, break-even, min-guarantee, current-booking marker
MIN GTEE you are here 0 $ pax →
revenue cost min guarantee

Planner expanded tour panel

05 Port-day aggregate COMMITTED/FIXED + VARIABLE + TOTAL · vendor cost at port-day level
COMMITTED / FIXED
$5,362
sum of min guarantees
VARIABLE (ABOVE MIN)
$2,888
pax-driven, at current booking
TOTAL · CURRENT
$8,250
at 180 booked pax

Planner port-day header strip

06 Fixed / variable split bar base portion vs variable portion of one tour's cost
FIXED VS VARIABLE SPLIT
base $1,100
+$968 var

Planner expanded tour panel

07 Cost line item sale-side reference · guest amount, not vendor cost
[Tour name] $129.00

Folio Resolver · Front Desk · Booking Ledger

Ways revenue can show · 5

revenue operator detail
01 Revenue card first of the 3-card strip
REVENUE
$3,000
avg $75/pax

tty modal · Planner expanded panel · budget-forecast tile

02 Sell rate stat inline SELL $X/pax on per-tour row
SELL$75/pax

Planner per-tour row

03 Revenue calc line pax × sell
40 pax × $75 = $3,000

tty modal · Planner expanded panel

04 Revenue line on chart olive line, always paired with cost — never alone

Planner expanded tour panel

05 Port-day aggregate REVENUE · CURRENT, sell price × booked pax
REVENUE · CURRENT
$18,980
sell price × booked pax

Planner port-day header strip

Ways a tour can go · 6

revenue cost capacity tour day departure guest experience operator detail
01 Per-tour row dense horizontal — see composition

Planner port-day view

02 Tour modal full operational + financial detail — see TDF — operational

tty shipboard view

03 Tour tile treemap rectangle · sized by revenue/capacity, colored by cost model
[Tour]
$2,700
[Tour]
$2,200
[Tour]
$890

budget-forecast treemap

04 Folio line item single-row sale-side reference on a guest folio

Folio Resolver · Front Desk Portfolio

05 Ledger booking entry sold + price stack + tenders, audit-oriented

Booking Ledger

06 Tour node card with 5-bar fidelity strip — confidence, not financial

shorex_canvas overview

Cost-model pill · 5 variants · one per tour

cost atom · cross-surface
.pill.pill--cm-*
FLAT / PAX TIERED / PAX BASE + / PAX PER-VEHICLE PER-PAX-W-MIN
first slot in head row, every tour non-tour entities · status (use semantic pill)
FLAT / PAXper_pax, no min_guarantee_pax
TIERED / PAXper_pax with tier breakpoints
BASE + / PAXfixed_per_departure + per_pax
PER-VEHICLEvehicle_flat (+ optional per_pax)
PER-PAX-W-MINper_pax + min_guarantee_pax · spoken "PAX + FLOOR"

Semantic pill · 5 states · same shape as cost-model

atom · cross-track · cross-surface
.pill.pill--{state}
CONFIRMED PENDING VENDOR CANCELLED SCHEDULED REFUND DUE AT GATE
after cost-model pill in head row categorical (use cost-model pill) · new state colors

AT GATE is an operational state (time-bound, day-of-execution) — distinct from the lifecycle states above. Future operational states (PRE-BOARDING, BOARDED, DEPARTED, RETURNED) will join the same family using --accent-cyan variants.

Per-tour row · 4 states

revenue cost capacity tour day operator detail Planner
① HEALTHY · ABOVE MIN, CONFIRMED
TIERED / PAX [Tour name] [Vendor] CONFIRMED
1-15 @ $38 · 16-30 @ $32 · 31-∞ @ $28
36 pax → tiered rate = $1,218
SELL$75/pax REV$2,700 GROSS$1,482 MARGIN55% FILL36/40
② AT-RISK · BELOW MIN GUARANTEE
PER-PAX-W-MIN [Tour name] [Vendor] BELOW MIN
$40/pax · min 20 pax
max(14, 20) × $40 = $800
SELL$65/pax REV$910 GROSS$110 MARGIN12% FILL14/40 · below min 20
③ PENDING VENDOR · NOT YET CONFIRMED
PER-VEHICLE [Tour name] [Vendor] PENDING VENDOR
$1,100 per vehicle · 20 cap
2 vehicles × $1,100 = $2,200
SELL$99/pax REV$4,356 GROSS$2,156 MARGIN50% FILL28/40
④ CANCELLED
FLAT / PAX [Tour name] [Vendor] CANCELLED
$34/pax
0 pax × $34 = $0
SELL$75/pax REV$0 GROSS$0 FILL

Planner port-day view

Tour Departure Financials — operational · tty shipboard modal

revenue cost capacity dispatch departure operator detail tty
identity
[Tour name]
8:30 AM · 4h · [Vendor]
FLAT / PAX CONFIRMED
booking
BOOKING
40 / 40
min 20
min 20
flags
FLAGGED GUESTS
ANNEX REPEAT +4
cost calc
FLAT / PAX 40 pax × $34 = $1,360
financials
REVENUE
$3,000
avg $75/pax
VENDOR COST
$1,360
$34/pax
GROSS MARGIN
$1,640
54.7% · be 18 pax
manifest
MANIFEST (12 OF 40)
1
[Guest]
[Cabin]
checked-in
2
[Guest]
[Cabin]
checked-in
3
[Guest]
[Cabin]
pending
actions

tty modal · shipboard SHX manager view

Tour Departure Financials — aggregate · Planner expanded panel

revenue cost capacity tour day departure operator detail Planner
identity
[Tour name]
[Vendor]
BASE + / PAX
cost calc
$1,100 base + $22/pax
$1,100 base + 44 × $22 = $2,068
chart
MIN GTEE 20 BREAK-EVEN 16 44 pax 0 50 pax →
revenue cost min guarantee break-even
scrubber
PAX SCRUBBER
044 pax50
financials
COST
$2,068
$1,100 fixed
REVENUE
$4,356
$99/pax
GROSS
$2,288
min gtee $1,584
MARGIN
53%
above break-even
split
FIXED VS VARIABLE SPLIT
base $1,100
+$968

Planner expanded tour panel · fleet SHX manager view

Streamline | Detail · on a real card · both contexts

operator detail tty · Folio · Front Desk · Manager
Business · tour card
[Tour name]
[Vendor] · 40/40 · CONFIRMED · 40 × $34 = $1,360
[meeting point] · [last vendor contact] · [contract notes]
Backend · feed card
[Adaptor feed]
[Feed name] · [last sync] · HEALTHY
[mapping rules] · [schema version] · [retry count]
When to use

Tour cards, manifest entries, vendor cards, adaptor feeds — anywhere a card mixes always-relevant essentials with sometimes-needed depth. Same template, same color rules (active = --track-content), same persistence key namespace (shorex-level-<cardId>).

Backend atoms

Atoms used to build the Data Adaptor's scoping picker. The assembled picker lives in-app; these are the deconstructed pieces it composes from.

Lifecycle card · 4 variants · upper-tier & operational + structural

SEASON
[Name]
[count]
DEPARTURE
[Name]
[count]
+ more
--blueUpper-tier: season, voyage. Border uses --track-content.
--greenOperational: tour_day, departure, bus. Border uses --track-revenue.
--ghostInvisible spacer for indent / column alignment in hierarchical rows.
--moreDashed-border overflow indicator. Used when N siblings collapse behind a "+ more" affordance.

Numbered step header · step number + title (+ optional caption)

1 Where in the lifecycle?

Optional caption · helper sub-text describing what this step asks

Anatomy.scoping-header wraps a .scoping-num (filled circle) + title text.
Optional sub.scoping-sub below for caption / instruction.
Use forWizard or multi-pane forms with ordered steps. Number circle is filled, not outlined — distinguishes from inline list markers.

Concern group · label + note + pill cluster

GROUP LABEL

optional helper text — how these are usually used together

Anatomy.scoping-group wraps .scoping-group-label + optional .scoping-group-note + a .concern-pills row.
When to useWhen you need to group choice pills under a heading — e.g. "Money & seats" (usually-together) vs "Rarely needed" (lone pill).

Shorex Design System · Export

Paste this as a system prompt into another LLM. Tokens · page structure · atoms · entity names · principles · anti-patterns.

← Catalog

Copied