---
version: alpha
name: Inventory / Warehouse Admin
description: A calm, precise pharmacy warehouse administration system for non-technical internal operations staff.

colors:
  primary: "#126C63"
  on-primary: "#FFFFFF"
  secondary: "#0B5952"
  on-secondary: "#FFFFFF"
  background: "#F3F7F6"
  on-background: "#173331"
  surface: "#FFFFFF"
  on-surface: "#173331"
  surface-container: "#F8FBFA"
  surface-container-high: "#E5F2EF"
  outline: "#DBE6E3"
  outline-variant: "#EAF0EE"
  text-secondary: "#4B6461"
  text-muted: "#738783"
  success: "#217A53"
  on-success: "#FFFFFF"
  success-container: "#E8F5EE"
  warning: "#9B5A0A"
  on-warning: "#FFFFFF"
  warning-container: "#FFF3D9"
  error: "#B23B3B"
  on-error: "#FFFFFF"
  error-container: "#FDEAEA"
  info: "#126C63"
  on-info: "#FFFFFF"
  info-container: "#F1F8F6"

typography:
  display:
    fontFamily: "DM Sans, ui-sans-serif, system-ui, sans-serif"
    fontSize: 32px
    fontWeight: 700
    lineHeight: 1.15
    letterSpacing: -0.035em
  headline-lg:
    fontFamily: "DM Sans, ui-sans-serif, system-ui, sans-serif"
    fontSize: 24px
    fontWeight: 700
    lineHeight: 1.2
    letterSpacing: -0.025em
  headline-md:
    fontFamily: "DM Sans, ui-sans-serif, system-ui, sans-serif"
    fontSize: 20px
    fontWeight: 700
    lineHeight: 1.3
  title-lg:
    fontFamily: "DM Sans, ui-sans-serif, system-ui, sans-serif"
    fontSize: 16px
    fontWeight: 700
    lineHeight: 1.35
  body-lg:
    fontFamily: "DM Sans, ui-sans-serif, system-ui, sans-serif"
    fontSize: 16px
    fontWeight: 400
    lineHeight: 1.55
  body-md:
    fontFamily: "DM Sans, ui-sans-serif, system-ui, sans-serif"
    fontSize: 14px
    fontWeight: 400
    lineHeight: 1.5
  body-sm:
    fontFamily: "DM Sans, ui-sans-serif, system-ui, sans-serif"
    fontSize: 12px
    fontWeight: 400
    lineHeight: 1.45
  label-md:
    fontFamily: "DM Sans, ui-sans-serif, system-ui, sans-serif"
    fontSize: 13px
    fontWeight: 700
    lineHeight: 1.4
  label-sm:
    fontFamily: "DM Sans, ui-sans-serif, system-ui, sans-serif"
    fontSize: 10px
    fontWeight: 700
    lineHeight: 1.3
    letterSpacing: 0.09em
  code:
    fontFamily: "ui-monospace, SFMono-Regular, Menlo, Consolas, monospace"
    fontSize: 12px
    fontWeight: 600
    lineHeight: 1.4

rounded:
  none: 0
  sm: 7px
  md: 10px
  lg: 14px
  xl: 16px
  full: 9999px

spacing:
  base: 4px
  xs: 4px
  sm: 8px
  md: 12px
  lg: 16px
  xl: 24px
  2xl: 32px
  3xl: 56px
  gutter: 32px
  mobile-gutter: 16px

layout:
  sidebar-expanded: 248px
  sidebar-collapsed: 68px
  topbar: 64px
  content-max: 1600px
  table-min: 1030px
  breakpoint-mobile-nav: 820px

components:
  button-primary:
    backgroundColor: "{colors.primary}"
    textColor: "{colors.on-primary}"
    typography: "{typography.label-md}"
    rounded: "{rounded.md}"
    height: 40px
    paddingInline: "{spacing.lg}"
  button-primary-hover:
    backgroundColor: "{colors.secondary}"
  button-secondary:
    backgroundColor: "{colors.surface}"
    textColor: "{colors.on-surface}"
    borderColor: "{colors.outline}"
    typography: "{typography.label-md}"
    rounded: "{rounded.md}"
    height: 40px
  card:
    backgroundColor: "{colors.surface}"
    textColor: "{colors.on-surface}"
    borderColor: "{colors.outline}"
    rounded: "{rounded.lg}"
    padding: "{spacing.lg}"
  input-field:
    backgroundColor: "{colors.surface}"
    textColor: "{colors.on-surface}"
    borderColor: "{colors.outline}"
    typography: "{typography.body-md}"
    rounded: "{rounded.md}"
    height: 40px
  dropdown:
    backgroundColor: "{colors.surface}"
    selectedBackground: "{colors.surface-container-high}"
    selectedText: "{colors.primary}"
    rounded: "{rounded.md}"
  badge:
    backgroundColor: "{colors.surface-container-high}"
    textColor: "{colors.primary}"
    typography: "{typography.label-sm}"
    rounded: "{rounded.full}"
    height: 24px
  data-table:
    backgroundColor: "{colors.surface}"
    headerBackground: "{colors.surface-container}"
    dividerColor: "{colors.outline-variant}"
    rowHeight: 58px
    rounded: "{rounded.xl}"
  focus-ring:
    color: "rgba(18, 108, 99, 0.28)"
    width: 3px
    offset: 2px
---

# design.md — Inventory / Warehouse Admin

> This file is the source of truth for the theme. Tokens are normative; prose explains why those values exist and how to apply them without losing the product's character.

## Overview

Inventory / Warehouse Admin is an internal pharmacy retail operations interface for tracking stock across a central warehouse and store locations. It is built for focused, interruption-heavy work: people compare physical labels with table rows, filter large lists, investigate exceptions, and take small operational actions throughout a shift.

The base implementation is `index.html`, a single self-contained HTML/CSS file that renders this design in full. `components.html` isolates the reusable components. Both are what an agent reads to build, and this document explains the tokens, layout, and reasoning behind them.

**Personality**: precise, calm, dependable, operational, quietly distinctive.

**Style direction**: **Clinical Control**—mineral teal, cool clinical surfaces, restrained ambient depth, compact information, and highly explicit status language. It must never resemble a bank portal with pharmacy nouns pasted into it, nor a futuristic command center disconnected from everyday warehouse work.

### What the website is about

The product answers four operational questions:

1. What stock is available now?
2. Where is the correct item, batch, and storage bin?
3. Which items are low, expiring, quarantined, or unavailable?
4. What should staff receive, transfer, count, or reorder next?

The primary surface is a products table rather than an executive analytics dashboard. Summary cards orient the user, but product search, filters, stock rows, and exception states carry the work. “Inventory” is the main menu because staff maintain a shared product catalog; stock quantity, batches, and expiry remain attributes of each product at a location.

### Business and organizational context

- **Organization type**: multi-location pharmacy retailer with a central distribution warehouse and store-level stock rooms.
- **Business users**: inventory coordinators, warehouse supervisors, pharmacy operations managers, receiving staff, and cycle-count staff.
- **Not the audience**: software engineers, database administrators, or customers shopping for medicine.
- **Business value**: fewer stockouts, less expired inventory, faster item lookup, safer batch handling, and a clearer audit trail for transfers and quarantines.
- **Typical session**: a staff member keeps the list open for hours, repeatedly searching SKUs, changing warehouse scope, checking expiry, and launching a row action.

### UX personas

#### Primary — Maya Chen, inventory coordinator

Maya is a non-technical internal employee who understands suppliers, SKUs, batches, bins, and reorder points. She works on a desktop near the receiving area, is interrupted often, and may be comparing a carton or handheld scanner with the screen. She needs to find an exact item in seconds and must never confuse available stock with quarantined stock.

**Goals**: locate stock, verify a batch, spot exceptions, and start a reorder or transfer with minimal navigation.

**Failure risks**: wrong batch selection, missed expiry, stale filter context, or an action applied to the wrong warehouse.

#### Secondary — Daniel Ortiz, warehouse supervisor

Daniel reviews the exception queue, inbound work, transfer demand, and cycle-count accuracy. He values density and an honest result count more than decorative charts. He needs the same interface as Maya with enough context to oversee multiple sites.

#### Occasional — Priya Shah, pharmacy operations manager

Priya visits periodically to review stock health and export filtered records. The interface must remain understandable without frequent-use muscle memory or technical vocabulary.

### Core user journeys

- **Locate**: search by item, SKU, or batch → narrow by warehouse → open details.
- **Triage**: filter to low stock, out of stock, or quarantined → review relevant rows → initiate reorder or transfer.
- **Expiry review**: scan the batch/expiry column → distinguish warning from urgent dates → inspect a batch.
- **Shift scope**: collapse the sidebar for more table width → keep location and filter context visible → paginate without losing query state.
- **Mobile lookup**: open the navigation drawer only when needed; use the horizontally scrollable data table for exact values rather than hiding critical columns.

## Colors

Mineral teal signals controlled healthcare operations without leaning on generic finance blue. Cool green-gray neutrals lower glare during long shifts; status colors appear only when they carry an operational meaning.

- **Primary** (`#126C63`): active navigation, primary actions, selected filters, links, and focus accents.
- **Secondary** (`#0B5952`): primary hover and pressed states; do not use as a separate decorative brand color.
- **Background** (`#F3F7F6`): the persistent application canvas.
- **Surface** (`#FFFFFF`): sidebar, topbar, cards, menus, and table body.
- **Surface container** (`#F8FBFA`): table headers and quiet grouped regions.
- **On-surface** (`#173331`): primary text.
- **Text secondary** (`#4B6461`): descriptions and ordinary cell values.
- **Text muted** (`#738783`): metadata and supporting labels; never use below 12px for essential information.
- **Outline** (`#DBE6E3`): component borders and structural dividers.

Status colors are semantic and always paired with words or an icon:

- **Success** (`#217A53` on `#E8F5EE`): healthy stock and confirmed completion.
- **Warning** (`#9B5A0A` on `#FFF3D9`): low stock and approaching expiry.
- **Error** (`#B23B3B` on `#FDEAEA`): out of stock, quarantine, urgent expiry, destructive actions.
- **Info** (`#126C63` on `#F1F8F6`): selected context and neutral guidance.

Do not use a purple gradient, saturated dashboard rainbow, or decorative status colors. A screen with no operational exception should be mostly neutral.

## Typography

The system uses **DM Sans** because its open counters and steady proportions remain readable in compact tables while feeling less mechanical than a typical enterprise system font. Use the system fallback stack when the web font is unavailable; layout must not depend on exact font metrics.

- **Display/headlines**: Bold 700 with restrained negative tracking. Page titles should orient, not dominate the work surface.
- **Body**: Regular 400 at 14px for controls and common copy; 12px is reserved for table metadata.
- **Labels**: Bold 700 for actions and uppercase micro-labels. Uppercase is limited to navigation groups, eyebrows, metrics, and table headers.
- **Operational codes**: use the mono stack for SKUs, batch IDs, bin labels, and dates where character comparison matters.

Regular 400 and Bold 700 anchor the hierarchy; Medium 500 and Semibold 600 support compact controls and metadata only.

## Layout

The desktop shell uses a fixed left sidebar, sticky utility topbar, and fluid content canvas capped at 1600px. Density is balanced-to-dense: a 70px table row carries two-line item and batch information without turning the page into a spreadsheet wall.

- **Sidebar**: 248px expanded and 68px collapsed. The collapse control lives in the brand row; collapsed mode hides the logo and leaves a right-facing expand chevron.
- **Topbar**: 64px high and sticky; keep global context and notification affordances here.
- **Main gutter**: 28px on desktop, 22px on tablet, 16px on mobile.
- **Metrics**: four columns on wide screens, two on medium screens, one on narrow phones.
- **Table**: minimum 1030px with horizontal scroll when necessary. Data integrity wins over hiding critical columns.
- **Spacing**: built on a 4px base with common steps at 8, 12, 16, 24, and 32px. Use 56px only for major page endings.

The information order is compact page identity and product actions → stock-health summary → search/filter controls → active filter context → table → result count/pagination.

## Elevation & Depth

Use **Tonal Layers with Ambient Shadows**. Most grouping comes from surface tone and a `1px` outline; only the data container, menus, mobile drawer, and transient overlays receive a diffused shadow.

Hover states change border or surface tone before adding elevation. Avoid stacked card shadows and never shadow every KPI card—the screen should feel stable, not floaty.

## Shapes

The shape language is softly rectangular, not bubbly.

- **Buttons, inputs, dropdown triggers**: 10px radius.
- **Metric cards and menu surfaces**: 14px radius.
- **Primary data container**: 16px radius.
- **Status badges, filter chips, live indicators**: full radius.
- **Item initials and icon tiles**: 10–12px radius; avatars alone may be circular.

Do not turn standard buttons into pills. Full rounding is a semantic cue for compact state, not a universal decoration.

## Components

### App shell and collapsible sidebar

The active navigation row uses a teal-tinted surface, teal label, and a 3px leading indicator. Expanded and collapsed states must retain the same item order. Navigation groups use labelled accordion controls with rotating chevrons; the navigation region scrolls independently when its content exceeds the available height, while the brand and profile remain fixed. In expanded mode the logo sits left and the collapse chevron sits inside the brand row; in collapsed mode the logo disappears and a centered expand chevron becomes the first clear affordance. At widths below 820px the sidebar becomes a modal drawer with a scrim, Escape-to-close behavior, and focusable controls.

### Page header

Use a compact 24px title and a 12px one-line purpose statement with no eyebrow. The title block should align vertically with the 40px action row. “Add product” is primary; “Bulk upload” and “Export” are secondary.

### Summary metrics

Metrics provide orientation, not analysis. Each card contains one icon tile, uppercase label, prominent value, and optional short note. Warning or error color belongs to the icon tile only when the metric represents an exception.

### Search and custom dropdowns

Search covers item name, SKU, and batch. Custom dropdowns show their current value in the trigger, a rotating chevron, checked selected option, hover/focus state, and a dismissible popup. Selecting a filter resets pagination to page one and creates a visible removable filter chip. Active filter chips use a compact 28px height, balanced 9px row padding, an 8px inter-chip gap, and a dedicated 20px close target so labels and icons share one baseline.

Dropdowns must support keyboard entry, visible focus, and Escape. Never rely on placeholder text to communicate a selected scope.

### Products table

Keep the item identity as the strongest cell: item tile, product name, SKU, and category. Pair warehouse with bin; stock amount with unit and reorder point; batch with expiry; state with a labeled badge. Row actions live in a compact overflow menu and repeat the item name in the button's accessible label.

Rows are 58px with quiet dividers and a tonal hover. Avoid zebra stripes; the compact two-line cell structure provides rhythm without extra noise.

### Pagination

The footer states the visible range and total, defaults to 5 rows per page, and provides First, Previous, bounded page numbers, Next, and Last. Page-size options are 5, 10, and 20. Use ellipses when the page set is long. Filters and page-size changes reset to page one; moving pages preserves filters.

### Status badges

Badges combine a colored dot and explicit text. Allowed stock states in the reference theme are Healthy, Low stock, Out of stock, and Quarantined. Never shorten these to unexplained codes.

### Feedback and non-default states

- **Empty filtered result**: explain that filters—not missing inventory—caused the empty state, and offer Clear filters.
- **Toast**: short confirmation for prototype actions, `role="status"`, auto-dismissed without blocking work.
- **Dialog**: use for destructive or scope-changing confirmation, or a focused create form with no more than six fields. Title the outcome, identify the affected record, preserve visible labels and helper text, and provide a clear escape. Longer workflows belong on a dedicated page.
- **Loading**: use row-shaped skeletons if integrated into a real data source; preserve table geometry.
- **Error**: keep the user's filters, explain what failed, and expose Retry.

### Selective component showcase

`components.html` demonstrates the reusable visual grammar outside the main products screen: buttons, form fields, open dropdown, badges, notices, empty state, pagination, a focused Add product form dialog, and a destructive stock-adjustment dialog. It is intentionally selective. Do not expand it into an exhaustive design-system site; new components should be documented only when the actual product requires them.

## Do's and Don'ts

- Do prioritize the exact item, batch, location, and stock state over decorative analytics.
- Do show the current warehouse and active filters close to the table.
- Do use mono type for codes that staff compare character by character.
- Do reset to page one after any filter or page-size change.
- Do pair every status color with an explicit label or icon.
- Do keep at least 44px interaction targets for primary controls and mobile navigation.
- Do let staff collapse the sidebar without losing navigation order or session state.
- Don't reuse bank terminology, bank-blue branding, or asset-acquisition concepts.
- Don't hide expiry, batch, or quarantine data merely to avoid horizontal scrolling.
- Don't use cards for each table row on desktop; scanning alignment matters.
- Don't add charts unless a decision cannot be made from a summary value or table.
- Don't invent new colors, radii, or badge states without updating this file first.

## Iconography

Use one inline outline icon family with rounded joins and an approximately `1.8px` stroke. Icons inherit `currentColor`; they support labels rather than replace them, except for universal compact controls such as menu, close, notification, pagination arrows, and row overflow.

| Size | Value | Use |
|---|---:|---|
| Small | 15–16px | Pagination, chips, inline metadata |
| Default | 18–20px | Controls and navigation |
| Large | 22–24px | Brand mark and metric tiles |

## Tone & Voice

The voice is professional, direct, and operational. Use plain English that a warehouse employee recognizes: “Low stock,” “Central warehouse,” “Create transfer,” and “Rows per page.”

- Use sentence case for buttons and labels.
- Prefer verbs for actions: Add product, Bulk upload, Export, View details, Create transfer.
- State quantities with their units.
- Avoid software terms such as record, entity, query, mutation, or database.
- Error copy explains the correction, not just the failure.

## Responsive Behavior

| Range | Behavior |
|---|---|
| Below 560px | Single-column metrics, stacked header actions, two-column filter controls, compact pager |
| 560–820px | Two-column metrics, mobile navigation drawer, fluid toolbar controls |
| 821–1180px | Persistent collapsible sidebar, two-column metrics, reduced content gutters |
| Above 1180px | Four-column metrics, full topbar context, wide data table |

Mobile keeps the real table horizontally scrollable instead of converting every row into an unrelated card. This preserves column comparison and batch accuracy. Make the scroll region obvious, retain the sticky page shell, and avoid locking body scroll after the drawer closes.

## Accessibility

- Maintain WCAG AA contrast for all essential text and controls.
- Use a visible 3px teal focus ring with 2px offset.
- Keep every action keyboard reachable in source order.
- Dropdown triggers expose `aria-haspopup="listbox"` and `aria-expanded`; selected options expose `aria-selected`.
- Row overflow triggers name their item; menus use menu and menuitem roles.
- Status meaning is expressed in text and color.
- The mobile drawer closes with Escape and has a dismissible scrim.
- Toasts use a polite live region.
- Respect `prefers-reduced-motion` by removing menu, sidebar, toast, and scrolling animation.
- Touch targets are at least 44px for primary mobile interactions; compact desktop pager buttons may be 34px when adjacent spacing remains clear.

## Adaptation boundaries

This theme may be adapted from pharmacy to ordinary retail, food distribution, parts, or supplies by changing categories, units, and batch fields. Preserve the operational model: item identity, exact location, available quantity, reorder context, exception state, filters, and bounded pagination.

Do not adapt it into fixed-asset lifecycle management without revisiting the information model. Acquisition dates, depreciation, ownership, and disposal are different workflows from stock movement, batches, expiry, and replenishment.

---

**Last updated**: 2026-07-23

**How AI agents should read this**: YAML tokens are normative and should be used verbatim. Prose defines the business and UX intent. When prose and tokens disagree, tokens win; when a requested feature conflicts with the personas or task model, preserve task clarity and document the exception.
