<link rel="stylesheet" href="design-system.css">.
All colors are CSS custom properties defined in :root. Use the variable names, never raw hex values.
--gray-500 or darker for any text that conveys information; --gray-400 is reserved for placeholder text and decorative elements only.
Primary font: Inter (400, 500, 600, 700) — matching the Gateway app's stack exactly. Monospace for manuscript IDs: the system ui-monospace stack.
Changed from Roboto on 28 Sept 2026. The design system previously specified Roboto and forbade Inter; that rule predated Gateway and was enforcing the prototype's choice against the product's. 600 is available in Inter and is legal — existing 700s were left alone, since under Roboto they already rendered at 700.
Used in queue tables and manuscript lists. Classes: .status-badge + .urgent | .warning | .info | .success
Inline colored dot + descriptive text. Used in Gateway table STATUS columns as an alternative to the pill-style status badges. Class: .status-dot + state modifier.
.status-dot) are used in Gateway table rows where space is tight and the status text itself is descriptive. Status badges (.status-badge) are the pill-style indicators used in prototypes and contexts where a compact label is needed. Both use the same semantic color tokens.
Pill badges for journal health indicators on the analytics dashboard. Used inline with section titles. Classes: .gw-health-badge + .critical / .warning / .good
Comparing submission counts between quarters
Acceptance rate stability indicates healthy editorial process
Time to decision trends affect author satisfaction
Recent submission activity indicates declining engagement
Used in queue rows. Classes: .article-type-badge + type modifier.
Used in reviewer tables and grid cards. Semantic coloring based on quality tier.
Used in decisions page and manuscript detail.
Two sizes: compact for table rows, standard for flyout panels.
General purpose and flyout action buttons.
Search across manuscripts and filter results by urgency, status, type, and other attributes.
Horizontal tabs with underline indicator, icons, and count badges. Matches the live Gateway Editor Center and Dashboard tabs. Classes: .gw-tab-bar, .gw-tab, .gw-tab-count
480px wide panel that slides from the right. Used for reviewer details, manuscript previews, and decision forms.
Centered overlay dialog for confirmations, forms, and detail views. Includes backdrop, header with close button, scrollable body, and action footer. Classes: .gw-modal-backdrop, .gw-modal, .gw-modal-header
Fixed bottom-center. Dark background with success icon.
Switch between table and grid/card views. Used in invite-reviewers and all-manuscripts.
Navigate between pages of results. The prototype uses numbered page buttons; the live Gateway app uses a summary + per-page dropdown + page navigation pattern. Both are valid; use whichever matches your context.
Uppercase column headers with bi-directional sort arrows. Active sort column highlights in blue. Classes: .gw-table, .gw-th.sortable, .sorted-asc / .sorted-desc
White background, 220px wide, text + icon labels, blue active state with left border. Matches the live Gateway app layout. Classes: .gw-sidebar, .gw-nav-item, .gw-beta-badge
Full-width gradient banner with icon, title, document count, and subtitle. Used at the top of each Gateway center page. Classes: .gw-hero, .gw-hero-icon, .gw-hero-title
Manage manuscripts in your queue
Track your submitted manuscripts
Metric cards for the Analytics dashboard. Each shows a label, large value, trend arrow with delta, comparison text, and a colored progress bar. Classes: .gw-kpi-grid, .gw-kpi-card, .gw-kpi-trend
Placeholder for tables or pages with no data. Centered layout with icon, title, description, and optional action button. Class: .gw-empty-state
Skeleton shimmer placeholders and spinner for content loading. Apply .gw-skeleton to any element for the shimmer effect. Classes: .gw-skeleton-text, .gw-skeleton-heading, .gw-spinner
A journal-configured label an office puts on a manuscript. Two facts drive every rule
here: flags are multi-select (a manuscript carries a set, possibly
empty — “unflagged” is the empty set, not a list member), and their
meaning is configured per journal, so no component may hard-code a
label, colour or icon. All three come from the journal’s list
(components/ms-flags.js).
Colour is never the only difference between two flags — every flag has a distinct glyph as well, because the queue row renders some flags icon-only and colour alone would fail WCAG 1.4.1.
The twelve shapes legacy actually ships, redrawn as vectors. Legacy offers 22 flag
slots, but those are these twelve repeated in different colours with the colour baked
into a 12×12 bitmap. Abstract by design: a purple dot means whatever the journal
typed into its label. Shown at 26px and at 14px — the size a flag is read at in a
queue row. Foundry, with a colour picker and copyable SVG:
lab/flag-shapes.html.
The production set. Material Symbols outlined at FILL 1 — the same
family the design system already loads, so a flag and a nav icon are the same typeface
rather than two icon languages in one app. Semantic rather than abstract, which lowers
the memory burden when an office runs a dozen flags. Again at 24px and 14px.
Class: .flag-chip, with --flag-color set per chip from the
flag record. The chip body stays neutral and the icon carries the colour —
colouring the whole chip spends the reader’s alarm on “Special
Collection”. .blocking is reserved for flags that literally instruct
people to stop.
Classes: .ms-flag-chip wrapping .ms-flag-prefix,
.flag-chip-group and .flag-edit-btn. Sits with the manuscript
ID and type badges, not in the status row — a flag labels the manuscript, it
isn’t a stage of it. The empty state is an add control, not the
words “No flags”: the control must exist when there are none, or the first
flag is unaddable.
The hard case: a row has space for one flag and may hold many. Show the first with its
label, the rest icon-only, collapse past three into .q-flag-more. Order the
set so blocking flags come first — if a manuscript is blocked,
truncation must never be what hides it. Never wrap: a row that grows a second line when
someone adds a flag makes every row below it jump.
Required on every icon-only chip: role="img" plus an
aria-label carrying the full label, and aria-hidden on the icon
span. Material Symbols render from ligature text, so without both a screen reader
announces the glyph name (“mail”) instead of the flag. The
+N chip needs an aria-label naming what it hides.
Flags are shared office state, so editing is batched behind an explicit Save
rather than committed per click — a half-made selection should not reach another
editor mid-click, and Cancel has to mean cancel. Save stays disabled until the draft
differs from what is stored. The opt-out is a radio outside the checkbox
list, mirroring legacy’s DO_NOT_CONSIDER_MS_FLAG; it is not
one of the flags. A label search is required once a journal configures more than about
ten. Classes: .flag-selected, .flag-search,
.flag-unflag, .flag-list, .flag-row,
.flag-rail-footer.
The surface every full-page view sits on. Token:
--gradient-page. Applied by
components/gateway-shell.css to .content-area,
so a page gets it by doing nothing — a page that sets its own
.content-area background is opting out, and should say so in a comment.
background-attachment: fixed is part of the pattern, not decoration:
it holds the gradient still while content scrolls. Without it the gradient travels
with the page and the colour under the header shifts as you move.
This is the part that keeps getting re-decided, so it is settled here.
A page title goes in a white card (.gw-page-header), never as text placed
straight onto the gradient. Dark text directly on this background is unreadable
(#111 on #2d1b4e), and light text is fragile because the gradient runs from dark purple
to mid teal — contrast changes across the width of the screen. A card sidesteps
both, and it is what the Editor dashboard has always done.
Who is holding what, and where the load is uneven.
A page that genuinely wants a flat surface uses
.gw-page-bg-flat rather than hardcoding a colour, so the decision reads
as deliberate instead of looking like an oversight.