1079 lines
64 KiB
Markdown
1079 lines
64 KiB
Markdown
# SHD.build Design System
|
||
|
||
This document defines the visual language for SHD.build. New pages should feel like part of the same tactical data network as the admin dashboard, while public pages may use more space and larger editorial typography.
|
||
|
||
## Design principles
|
||
|
||
1. **Tactical, not military cosplay.** Use operational language, compact information density, restrained status indicators, and precise alignment. Avoid camouflage, distressed textures, or decorative weapon imagery in utility interfaces.
|
||
2. **Data first.** Hierarchy comes from grouping, typography, borders, and spacing. Admin tools should resemble a dependable control surface rather than a collection of marketing cards.
|
||
3. **Orange means action.** SHD orange identifies primary actions, active navigation, focus, and important values. It should not cover large areas.
|
||
4. **State is always visible.** Loading, disabled, active, archived, configured, error, and success states need both visual and textual indicators.
|
||
5. **Square and engineered.** Panels and controls use square corners, fine borders, tight spacing, and deliberate grid alignment.
|
||
6. **Links use interface feedback, not underlines.** Links do not use native text
|
||
underlines. Communicate hover and focus through SHD accent color, borders,
|
||
brightness, and the required focus-visible outline.
|
||
|
||
### Routed error console
|
||
|
||
Expected HTTP errors and unexpected server faults use one shared SHD exception
|
||
console inside the normal application shell. The console always displays the
|
||
numeric status, an operational title, a safe explanation, request path, node,
|
||
and context-appropriate recovery controls. Common statuses receive distinct
|
||
language: authentication for 401, clearance for 403, lost location for 404,
|
||
conflict for 409, saturation for 429, and service/fault language for 5xx.
|
||
|
||
Orange identifies recoverable request errors and actions; red identifies server
|
||
faults. Never display stack traces, database messages, credentials, request
|
||
queries, or raw unexpected exceptions to users. Unexpected server faults receive
|
||
a short reference ID from the global error handler for support correlation while
|
||
the complete error remains server-side. If the root application shell itself
|
||
cannot render, `src/error.html` provides a dependency-free SHD fallback surface.
|
||
Error controls retain square geometry, focus-visible treatment, pressed motion,
|
||
plain-language labels, and stacked mobile recovery actions.
|
||
|
||
### Contact relay and legal requests
|
||
|
||
Public support uses the SHD Contact Relay surface: a broad transmission form
|
||
paired with a compact destination guide. Two-to-six destinations use the shared
|
||
segmented-choice pattern. Signed-in identity details may be prefilled, but the
|
||
public form remains available to people who cannot sign in. Discord community
|
||
access is a distinct provider-colored card; it supplements rather than replaces
|
||
the durable contact channel.
|
||
|
||
The Contact hero explicitly resets the global site-header height: semantic page
|
||
`header` elements must use content-driven height and spacing rather than inherit
|
||
the 76-pixel navigation-shell constraint. Its title, description, and Discord
|
||
card align within a minimum 230-pixel desktop band before the form grid begins.
|
||
The Contact page itself remains content-height-driven so high-resolution browser
|
||
zoom does not multiply a viewport minimum into a large empty region above the
|
||
footer.
|
||
|
||
The application frame is a full-viewport vertical flex stack. The shared footer
|
||
uses automatic top margin, so it rests against the bottom edge on short routes
|
||
and follows normal document flow after longer content. Individual pages must
|
||
not add spacer heights solely to position the footer. The frame compensates for
|
||
`--shd-display-scale` when calculating its viewport minimum so high-resolution
|
||
browser zoom does not push a short-page footer below the visible edge.
|
||
|
||
Community access in the shared footer uses a compact Discord-branded action
|
||
with the official symbol, provider blue surface, explicit external-link text,
|
||
and visible hover, focus, and pressed feedback. Keep provider branding separate
|
||
from the orange links reserved for SHD navigation and legal resources. Support
|
||
and legal links form a compact horizontal rail that may wrap at intermediate
|
||
widths and becomes a two-column touch-friendly grid on narrow mobile screens.
|
||
|
||
The footer repeats the complete SHD brand lockup used by the global header:
|
||
double-ring SHD mark, white `SHD`, orange `.build`, and the restrained
|
||
`LOADOUT NETWORK` descriptor. Do not substitute a plain text wordmark or color
|
||
the complete product name orange.
|
||
|
||
Contact notifications use the mandatory ISAC visual identity because they are
|
||
operational inbound messages. The notification carries a concise preview and a
|
||
specific action to an authorization-checked full record. Full messages never
|
||
appear in URLs. Copyright requests add a yellow legal-detail subpanel, explicit
|
||
attestations, electronic signature, and a direct policy link. Do not visually
|
||
present a submission as a legal determination.
|
||
|
||
The DMCA policy reuses the legal-document/index layout. Copyright and takedown
|
||
links must remain visible in the global footer alongside Contact Us. On mobile,
|
||
contact columns stack, destination segments become full-width 44-pixel rows,
|
||
attestations remain readable, and reply/recovery actions occupy the available
|
||
width.
|
||
|
||
### Builder range controls
|
||
|
||
Configurable numeric rolls use the shared range-value control: a descriptive
|
||
label and current minimum/maximum above a synchronized range slider and direct
|
||
number input. The slider supports fast exploration while the number field
|
||
supports exact entry; both clamp to the currently calculated bounds. Focus uses
|
||
the SHD action border, active slider feedback uses the standard pressed
|
||
brightness treatment, and number fields retain the global select-all-on-focus
|
||
behavior.
|
||
|
||
When an equipment level changes, preserve the configured roll's relative
|
||
position within its previous range instead of resetting it arbitrarily. Mark
|
||
unverified portions of a level curve with both `ESTIMATED` text and the
|
||
High-end yellow caution treatment. Controls stack the slider and direct input
|
||
at narrow mobile widths and must never create horizontal page overflow.
|
||
|
||
Equipment level uses this same synchronized control rather than a standalone
|
||
number field. Changing level remaps base and rolled values to the equivalent
|
||
relative position in the newly calculated range.
|
||
|
||
Gear and weapons always expose exactly two required rolled-Attribute positions.
|
||
Render both positions as persistent numbered rows; do not offer add or remove
|
||
actions. Already selected Attributes are disabled in the other position.
|
||
|
||
Use compact segmented radio controls for the small finite weapon-tier set.
|
||
Use the shared builder radio grid for visually identified Brand Sets and weapon
|
||
talents: transparent icons lead each square engineered option, text remains
|
||
visible, and the selected state uses the orange action edge plus an explicit
|
||
radio state. Talent grids become searchable when their available pool is large.
|
||
On narrow viewports option grids reduce to two columns and then one column so
|
||
labels and 44-pixel-or-larger targets remain usable.
|
||
|
||
## Tokens
|
||
|
||
The canonical tokens live in `src/app.css` under `:root`.
|
||
|
||
| Purpose | Token | Value |
|
||
| --- | --- | --- |
|
||
| Page background | `--shd-bg` | `#0a0c0d` |
|
||
| Base surface | `--shd-surface` | `#111415` |
|
||
| Raised surface | `--shd-surface-raised` | `#141718` |
|
||
| Primary border | `--shd-border` | `#303536` |
|
||
| Main text | `--shd-text` | `#ecebe5` |
|
||
| Muted text | `--shd-text-muted` | `#858b8d` |
|
||
| SHD action orange | `--shd-orange` | `#f6a821` |
|
||
| Adaptive display scale | `--shd-display-scale` | `1` by default; stepped on high-resolution desktops |
|
||
|
||
### High-resolution display scaling
|
||
|
||
The application uses restrained, stepped interface scaling when the effective
|
||
CSS viewport is substantially wider than a conventional desktop. At 2200px the
|
||
complete interface scales to 115%, at 2800px to 130%, and at 3400px to 150%.
|
||
This preserves the established relationship between typography, controls,
|
||
tables, spacing, hit targets, and fixed-position surfaces instead of enlarging
|
||
text alone.
|
||
|
||
Use the shared `--shd-display-scale` token and the root-level `zoom` treatment;
|
||
do not add module-specific 4K font-size overrides. Responsive layouts below
|
||
2200px remain unchanged. Browser zoom and operating-system display scaling still
|
||
remain available to users and naturally change the effective CSS viewport.
|
||
High-resolution scaling must not introduce horizontal overflow, clipped fixed
|
||
surfaces, or a different semantic hierarchy. Test the standard desktop layout
|
||
and each affected wide breakpoint after changing this policy.
|
||
| Success | `--shd-success` | `#75c08c` |
|
||
| Destructive/error | `--shd-danger` | `#df8069` |
|
||
| Informational/defensive | `--shd-info` | `#70b9d6` |
|
||
|
||
Use the spacing tokens for new components. Prefer `8px`, `12px`, and `20px` gaps. Dashboard controls use the shared `40px` height when practical.
|
||
|
||
## Typography
|
||
|
||
- The current UI stack is `Arial, Helvetica, sans-serif`.
|
||
- Page and module headings are uppercase, heavy, and tightly spaced.
|
||
- Eyebrows and table labels use 7–10px text with 1–2px letter spacing.
|
||
- Body and form text should normally remain between 9–12px in dashboards.
|
||
- Public/editorial copy may use Georgia for a restrained field-manual character.
|
||
- Never use low-contrast tiny text for information required to complete a task.
|
||
|
||
## Layout patterns
|
||
|
||
### Global mobile navigation
|
||
|
||
At viewports up to 900px, replace the hidden desktop link rail and account
|
||
controls with a clearly labeled square `MENU` control in the shared site
|
||
header. Activating it opens a right-side SHD navigation panel over a dismissible
|
||
backdrop. The panel includes Home, Discover, Builder, Guides, Sign In or My
|
||
Profile, and ISAC when authorized; authenticated agents also receive identity
|
||
state and Sign Out inside the panel.
|
||
|
||
Use numbered full-width navigation rows, explicit active-route text styling,
|
||
orange action indicators, and minimum 44px interaction targets. Opening moves
|
||
keyboard focus to the first route. Escape, backdrop activation, route changes,
|
||
and the header Close control dismiss the panel. The toggle exposes
|
||
`aria-expanded` and `aria-controls`, the panel has a distinct navigation label,
|
||
and reduced-motion preferences remove icon transitions. Do not make mobile
|
||
users rely on the logo or desktop-only account controls to reach core routes.
|
||
|
||
On phone-sized viewports up to 700px, ISAC module toolbars stack their action
|
||
area beneath the module title. A single Add action spans the available width;
|
||
multiple creation actions share an equal responsive grid. These controls use a
|
||
minimum 48px height, centered labels, and the standard pressed, focus-visible,
|
||
pending, and disabled treatments. Do not leave desktop-sized Add buttons
|
||
squeezed beside long module headings on mobile.
|
||
|
||
### Public pages
|
||
|
||
- Maximum content width: approximately 1400–1640px.
|
||
- Larger headings and more generous vertical rhythm are appropriate.
|
||
- Preserve the grid background and orange accents.
|
||
- Catalogue and editorial pages use `catalogue-hero` for an angular introductory
|
||
panel and may pair it with a compact operational control bar.
|
||
- Community build cards retain the colored top rule, abstract loadout artwork,
|
||
concise tags, agent attribution, and a full-width terminal action.
|
||
|
||
### Agent and authentication surfaces
|
||
|
||
- Account pages should read as an agent dossier: identity and access at the top,
|
||
activity metrics beside it, archives in the primary column, and security
|
||
controls in a narrower console column.
|
||
- Dense account consoles use a tabbed control surface for profile, credentials,
|
||
linked identities, and account lifecycle actions. Only one panel is shown at
|
||
a time; validation failures reopen the panel containing the failed action.
|
||
Closely related mutually exclusive workflows, such as selecting a preset
|
||
portrait or uploading a custom portrait, use a compact secondary tab row.
|
||
Tabs retain native button semantics plus tablist, tab, and tabpanel roles,
|
||
textual selected state, keyboard focus, and pressed feedback.
|
||
- Account Access uses a secondary method navigation for passkeys, verified
|
||
email, local password fallback, and linked identity providers. Each tab shows
|
||
a compact configured-method count and routes failed actions back to the
|
||
relevant panel. External identity connections live inside Access rather than
|
||
competing with it as a top-level account domain.
|
||
- Future external providers may appear as non-interactive planned rows so the
|
||
intended identity architecture is visible before credentials are configured.
|
||
Placeholders must be visually subdued, explicitly labeled `PLANNED`, and must
|
||
not imitate enabled buttons. Provider-compliant assets and controls replace
|
||
these rows only when the corresponding OAuth application is implemented.
|
||
- Provider unlinking does not assume that a password exists. The unlink control
|
||
is the provider card’s `LINKED` status badge. Hover and keyboard focus turn it
|
||
red and replace the label with `UNLINK`; activation replaces the full card
|
||
surface with an explicit Cancel / Confirm Unlink decision. Confirmation uses
|
||
the square SHD primary action with the orange action accent, while Cancel
|
||
remains a dark outlined secondary control. The authenticated
|
||
session plus this deliberate second action authorizes the request; the shared
|
||
server-side last-method guard remains authoritative. Future provider cards
|
||
reuse this pattern rather than adding provider-specific credential prompts.
|
||
- Authentication pages use a split frame: contextual SHD network information on
|
||
the left and the actionable secure-access console on the right.
|
||
- OAuth providers appear as connection nodes with a recognizable provider color;
|
||
SHD orange remains reserved for the primary local action and navigation.
|
||
- Authentication prioritizes passkeys, followed by one-time email magic links.
|
||
Discord remains a prominent provider option, while username/password is an
|
||
explicitly labeled optional fallback in a collapsed control. Passkey controls
|
||
name the platform interaction rather than exposing WebAuthn terminology.
|
||
- Verified email identities and registered passkeys appear as compact method
|
||
rows in Account Access. Every method displays its verification or device state,
|
||
registration date where useful, and protected removal behavior that prevents
|
||
an agent from deleting their last usable sign-in method.
|
||
- Local username and password are one optional authentication method, separate
|
||
from the public display name and the immutable internal account identifier.
|
||
Agents may remove both local credentials together after adding another method,
|
||
and may restore them later with a new unique login username and password.
|
||
- The “at least one sign-in method” rule is a server-side invariant shared by
|
||
self-service and ISAC actions. Passkeys, verified magic-link email, Discord,
|
||
and a complete local username/password pair each count as usable methods.
|
||
Controls may disable unsafe removal for clarity, but server validation remains
|
||
authoritative. Intentional soft account deletion is the sole exception.
|
||
- Linked identity nodes show provider display name, account handle or stable ID,
|
||
and an explicit textual `LINKED` state. Unlink controls sit beneath the node,
|
||
require credential confirmation, and remain disabled with an explanation when
|
||
unlinking would remove the user's only sign-in method.
|
||
- ISAC user dossiers reuse the same linked-identity node. Administrative
|
||
unlinking requires a scoped identity-management capability, produces an audit
|
||
event, and must never remove the user's only available sign-in method.
|
||
- On small screens, the split frame becomes a single column and account controls
|
||
move before archival content.
|
||
- Public display names and private login usernames are distinct. Display names
|
||
support normalized Unicode and relaxed visible characters; login usernames
|
||
remain unique, ASCII-only credentials and must never appear on public-facing
|
||
community surfaces. Authorized ISAC user operations may show both.
|
||
|
||
### Third-party identity buttons
|
||
|
||
- Follow the identity provider's current official brand and sign-in guidelines.
|
||
- Use official, unmodified assets downloaded from the provider's brand resources.
|
||
- Discord sign-in uses the official white Discord symbol on Blurple `#5865F2`
|
||
with the explicit label “Continue with Discord.”
|
||
- Discord account connection controls use the same official symbol and Blurple
|
||
treatment with the explicit label “Link Discord.”
|
||
- Sign-in pages group external providers into a compact, equal-weight provider
|
||
rail. Keep a short visible provider name beneath each mark; accessible names
|
||
and hover text are supplementary and do not replace required brand wording.
|
||
- Google uses its standard multicolor G on a white icon field, Apple uses a
|
||
white Apple mark on black, Discord uses its unmodified white symbol on
|
||
Blurple, and Steam uses its white linked-circle mark on Steam navy.
|
||
- Providers that are not configured are disabled, desaturated, and marked
|
||
`PLANNED`; they must not navigate, submit, or visually imply availability.
|
||
- When each provider is implemented, replace its placeholder with the
|
||
provider-rendered control or current pre-approved sign-in artwork where the
|
||
provider requires it. In particular, use Google Identity Services or its
|
||
approved icon-mode asset and Steam's published sign-in image.
|
||
- Preserve the provider's required clearspace, logo proportions, approved color,
|
||
readable contrast, and text/logo alignment even when the surrounding surface
|
||
follows the SHD theme.
|
||
- Provider buttons still require SHD.build's focus-visible, pressed, pending, and
|
||
duplicate-interaction protection where those states do not conflict with the
|
||
provider's branding requirements.
|
||
- Authentication uses one unified access screen rather than separate sign-in and
|
||
registration destinations. Verified email and first-time OAuth identities may
|
||
create an account; returning identities sign into the matching account.
|
||
- Password access uses an explicit `SIGN IN` / `CREATE ACCOUNT` mode switch
|
||
inside the fallback panel. Account creation separates the public display name
|
||
from the private ASCII login username.
|
||
- Passkeys are a returning-user method on this screen. New agents first establish
|
||
an account through verified email, OAuth, or local credentials, then enroll a
|
||
passkey from Account Access.
|
||
|
||
### Footer and legal surfaces
|
||
|
||
- Every routed page ends with the global SHD footer containing Terms & Privacy,
|
||
data-retention access, and the unofficial Ubisoft fan-site disclaimer.
|
||
- Legal pages retain the command-console visual language but prioritize readable
|
||
serif body copy, anchored sections, and restrained line length.
|
||
- Login security metadata is operationally visible in ISAC for 30 days. After
|
||
that period, IP, user-agent, normalized client/device fields, and credential
|
||
references and proxy-supplied approximate location are scrubbed while
|
||
non-sensitive event facts, categorical risk flags, and session outcomes may remain.
|
||
|
||
### Admin dashboard
|
||
|
||
- Use `admin-page`, `admin-command`, `admin-dashboard`, `admin-sidebar`, and `admin-content`.
|
||
- The administrative system is named ISAC. Separate navigation into explicit
|
||
operational domains such as User Operations and Data Management; visibility
|
||
must reflect server-provided capabilities.
|
||
- User Operations shows every supported authentication method as operational
|
||
metadata: local credentials, verified email, passkeys, Discord, and planned
|
||
providers. Identity-removal controls require `users.identities`, create audit
|
||
records, and preserve at least one remaining sign-in method.
|
||
- The Agent Registry prioritizes assigned roles over authentication-method
|
||
summaries. Authentication details belong in the individual agent dossier.
|
||
- ISAC authentication-method removal is always a two-step interaction contained
|
||
within the affected method row. The confirmation state explains the impact and
|
||
provides explicit Cancel and orange Confirm actions before submission.
|
||
- Agent dossiers consolidate operational controls into full-width tabs for
|
||
Roles & Permissions, Authentication, and Moderation. Keep dense controls in
|
||
their relevant tab instead of allowing one dashboard column to grow far beyond
|
||
adjacent content.
|
||
- Avatar removal uses the same in-card, two-step confirmation interaction as
|
||
authentication-method removal.
|
||
- Role and permission changes require a modal review step that summarizes the
|
||
complete selected role and direct-permission sets. Only the modal's orange
|
||
Confirm action submits the assignment.
|
||
- Access-review summaries are diffs: retained assignments use a neutral `KEEP`
|
||
state, additions use green `ADD`, and removals use red `REMOVE` with struck
|
||
assignment text. Added and removed items appear together in their respective
|
||
role or direct-permission column.
|
||
- Login, build/guide, and comment histories are independent support registries.
|
||
Each provides context-appropriate filters and namespaced pagination controls
|
||
so changing one history page does not reset the others.
|
||
- Each module starts with `module-toolbar`, followed by `module-kpis`.
|
||
- Editors use `dashboard-editor` and appear before the affected table.
|
||
- Data collections use `dashboard-table`, `dashboard-row`, and `table-heading`.
|
||
- Keep tables dense and horizontally scrollable rather than wrapping columns unpredictably.
|
||
- User dossiers pair access controls and moderation in a two-column console,
|
||
followed by compact login and content-history streams. Restriction state must
|
||
be textual and use the danger color; inactivity remains a separate activity
|
||
classification rather than a punishment state.
|
||
- Role names describe durable organizational responsibility. `Admin` is the
|
||
unrestricted administrative role; `Community Oversight` is reserved for
|
||
community content moderation and does not imply ISAC access. Operational
|
||
ISAC access is delegated separately through scoped roles and permissions.
|
||
- Roles is a separate User Operations registry. Role definitions
|
||
compose discrete capabilities through a dense permission catalogue with an
|
||
explicit selected count and textual `GRANTED` / `NOT GRANTED` states. The
|
||
built-in Admin role is visible but system-protected. Delegated access managers
|
||
must never be able to grant `system.admin`; both option visibility and
|
||
server-side validation enforce this boundary. Role mutations are recorded in
|
||
the audit log with their previous and resulting permission sets.
|
||
- Audit History belongs to a separate `SYSTEM OVERSIGHT` navigation domain.
|
||
Audit records are append-only operational evidence and show the operator,
|
||
categorical action, target identifier, timestamp, and expandable before/after
|
||
JSON snapshots. Search and category/action filters run before pagination.
|
||
The Auditor role grants read-only `audit.view` access plus entry to ISAC;
|
||
audit visibility never implies mutation, user-management, or game-data access.
|
||
- Supported audit events may expose a permissioned compensating-action control.
|
||
Reversion uses a danger-styled `ATTEMPT REVERT` entry action followed by a
|
||
modal that explains the original action, operator, target, and conflict
|
||
checks. The orange Confirm action is the only submission path. ISAC compares
|
||
current state with the original event’s after-snapshot before restoring the
|
||
before-snapshot; newer work blocks the operation. Successful reversions append
|
||
a new `audit.reverted` event and never alter the original history. `audit.view`
|
||
remains read-only; `audit.revert` is independently assigned.
|
||
- System Metrics is the second read-only System Oversight surface. It uses a
|
||
compact KPI row for headline process health and a two-column grid of dense
|
||
runtime, host, database, and service-volume panels. Refresh is explicit and
|
||
duplicate-safe; optional auto-refresh is visibly selected and uses a
|
||
restrained ten-second interval. Metrics must not expose environment values,
|
||
credentials, full filesystem paths, or other deployment secrets. The
|
||
`metrics.view` permission is independent of mutation access and is included
|
||
in the read-only Auditor role.
|
||
- Account deletion uses a collapsed danger zone, explicit identity confirmation,
|
||
and plain-language retention guidance. Soft-deleted accounts retain authored
|
||
content under a deleted-agent identity while releasing credentials, usernames,
|
||
external identity links, sessions, roles, and permissions.
|
||
- Threshold-based set bonuses use compact `effect-band` groups. Each threshold is
|
||
displayed as a fixed piece-count marker followed by its mapped stat and value,
|
||
keeping progression readable in editors and table summaries.
|
||
- Multi-value compatibility fields use a dense `selection-grid` of checkbox
|
||
rows with a visible selected-count summary. Keep the entire row clickable and
|
||
preserve native checkbox semantics for keyboard and assistive-technology use.
|
||
- When compatibility is conditional on another field, show only valid choices,
|
||
clear stale selections when the controlling field changes, and state required
|
||
minimum selections in both the section label and validation feedback.
|
||
- Tiered records with shared structure use one shared selector and side-by-side
|
||
value columns rather than duplicating the entire editor. Template-driven copy
|
||
must show live previews for every tier and document its placeholder syntax.
|
||
|
||
### Forms
|
||
|
||
- Labels are uppercase and letter-spaced.
|
||
- Inputs use dark surfaces, one-pixel borders, and clear disabled styling.
|
||
- Related min/max fields remain visually paired.
|
||
- Small mutually exclusive option sets use a compact segmented radio control,
|
||
even when visually presented like selectable checkbox cells. Include an
|
||
explicit “None” option when the field is optional.
|
||
- Primary save actions sit at the lower right. Cancel is secondary.
|
||
- Destructive/archive actions are visually separated from save actions.
|
||
|
||
## Interaction rules
|
||
|
||
- Every interactive element needs a pointer cursor unless disabled.
|
||
- Buttons have hover, pressed, focus-visible, pending, and disabled states.
|
||
- Forms that send requests should use `PendingForm.svelte` or equivalent enhancement to prevent duplicate submissions.
|
||
- Pending buttons use `aria-busy="true"` and remain disabled until the request completes.
|
||
- Respect `prefers-reduced-motion`.
|
||
|
||
## Color semantics
|
||
|
||
- Orange: primary action, current location, selected operational value.
|
||
- Green: online, active, configured, or successful.
|
||
- Red: destructive action, error, or offensive classification when context requires it.
|
||
- Blue: defensive or informational classification.
|
||
- Gray: inactive, archived, unavailable, or supporting metadata.
|
||
|
||
Do not communicate state by color alone; include a label, icon, or pattern.
|
||
|
||
## Responsive behavior
|
||
|
||
- Collapse the dashboard sidebar into a two-column module grid below 900px.
|
||
- KPI tiles become two columns on small screens.
|
||
- Tier editors stack vertically on tablets.
|
||
- Tables retain a useful minimum width and scroll horizontally.
|
||
- Primary and secondary toolbar actions may expand equally on narrow screens.
|
||
|
||
## Adding a new admin module
|
||
|
||
1. Add the route beneath `src/routes/isac`.
|
||
2. Register it in the admin layout navigation.
|
||
3. Start with the module toolbar and KPI row.
|
||
4. Reuse dashboard editor and table classes.
|
||
5. Use the shared tokens instead of introducing near-duplicate colors.
|
||
6. Verify keyboard focus, pending behavior, empty states, mobile layout, and archived data behavior.
|
||
|
||
If a new interface needs a genuinely new pattern, document it here when introducing it.
|
||
|
||
## Design-system governance
|
||
|
||
Significant visual and interaction changes must update this document and the
|
||
shared implementation in the same change. A change is significant when it
|
||
introduces or materially revises a reusable token, component pattern, layout,
|
||
responsive rule, accessibility behavior, motion behavior, or state convention.
|
||
|
||
Small alignment corrections and isolated visual bug fixes do not require a
|
||
documentation change unless they establish a rule that other interfaces should
|
||
follow.
|
||
|
||
Repository agents and contributors should follow the maintenance checklist in
|
||
`AGENTS.md`.
|
||
|
||
### Agent avatars
|
||
|
||
Agent portraits use a circular crop in identity headers and square tactical
|
||
thumbnails in selectors. Preset choices appear in a compact four-column grid;
|
||
the active choice uses the orange action border and an explicit pressed state.
|
||
Custom images are normalized server-side to a metadata-free 256 × 256 WebP.
|
||
Selectors must retain visible hover, focus-visible, pressed, pending, and
|
||
disabled states, and collapse naturally with their containing account console.
|
||
ISAC user dossiers show the current portrait, distinguish preset and custom
|
||
sources textually, and place destructive custom-image removal behind the
|
||
existing moderation permission and pending-action pattern.
|
||
Moderation actions use full-width engineered controls: neutral outlined
|
||
buttons for reversible identity changes and muted red controls for destructive
|
||
or restrictive changes. Every control must expose pointer, hover,
|
||
focus-visible, pressed, disabled, and inline pending-spinner states; adjacent
|
||
navigation links use the same height, typography, and interaction motion.
|
||
|
||
### Weapon definition editor
|
||
|
||
Complex progression definitions use a stacked control-surface editor: identity
|
||
and fixed values first, then parallel tier cards, mutually exclusive talent
|
||
pools, fixed base bonuses, and the augmentation sequence. Tier cards retain
|
||
identical row ordering so values can be compared horizontally on wide screens
|
||
and stack without changing meaning on narrow screens. System-derived augment
|
||
steps appear as read-only numbered cells; editable effects use the shared
|
||
attribute/value row pattern. Exotic is a status layered onto a weapon family,
|
||
never a replacement for the family classification. Fixed base bonuses remain
|
||
visually separate from tactical augmentation effects. Exotic definitions add a
|
||
dedicated exotic-only talent after the two standard talent pools; their sixth
|
||
augmentation cell communicates that this talent advances to Tier II.
|
||
The exotic talent is owned by exactly one exotic weapon and is authored inline
|
||
inside that weapon editor, never selected from a shared global pool. Its
|
||
engineered sub-panel includes the talent name, shared description template,
|
||
Tier I/II previews, reusable triggers, and paired effect values. The Talent
|
||
Registry may display an owned exotic talent for discovery, but routes editing
|
||
back to its weapon rather than opening the shared-talent editor.
|
||
|
||
Large relationship sets use the searchable assignment control instead of
|
||
checkbox walls. It keeps assigned records visible as removable chips, filters
|
||
available records by name, renders at most thirty results at once, and exposes
|
||
counts for both assignments and matches. Mutually exclusive pools pass their
|
||
assigned IDs to one another as exclusions so invalid combinations cannot be
|
||
selected. Keyboard focus, pressed state, empty results, and overflow remain
|
||
explicit.
|
||
Where a relationship has a global slot invariant, filter each assignment
|
||
control at the data boundary instead of presenting cross-slot choices. Weapon
|
||
talents are classified once as Talent 1 / Top or Talent 2 / Bottom in the
|
||
talent registry; weapon editors only curate subsets from the matching slot.
|
||
|
||
### Game-semantic iconography
|
||
|
||
Canonical game icons are registered in `src/lib/game-icons.ts` and rendered
|
||
through `GameIcon.svelte`; do not repeat asset paths in individual features.
|
||
Use damage icons beside Blast, Pierce, and Shredding classifications, and core
|
||
attribute icons beside Firepower, Toughness, and Engineering values. The same
|
||
registry reserves the Bulwark, Combat Medic, Demolitionist, Tech Operator,
|
||
Vanguard, Legendary, and SHD-ticket assets for controls or data that explicitly
|
||
represent those concepts. Do not use semantic icons as unrelated decoration.
|
||
|
||
Interactive icon choices retain a visible text label, square engineered cells,
|
||
orange selected state, and hover, pressed, and focus-visible feedback. Icons
|
||
that repeat an adjacent visible label are decorative with an empty alternative;
|
||
standalone icons expose the registry's human-readable label. Preserve each
|
||
asset's aspect ratio with `object-fit: contain` and scale through the shared
|
||
`.game-icon` class rather than modifying source artwork.
|
||
|
||
### Item quality
|
||
|
||
Item quality is a global semantic scale: Standard uses
|
||
`--quality-standard` green, Specialized uses `--quality-specialized` blue,
|
||
Superior uses `--quality-superior` purple, and High-end uses
|
||
`--quality-high-end` yellow. Apply the matching `.quality-*` utility wherever
|
||
an item’s persisted quality is shown. Registry labels use `.quality-chip` so
|
||
quality remains explicit in text and never depends on color alone. These colors
|
||
identify item quality; orange remains reserved for actions and current
|
||
selection.
|
||
|
||
### OS Protocol editor
|
||
|
||
OS Protocol definitions separate shared secondary profiles from item-owned
|
||
progression. The twelve quality + attribute-type combinations are configured
|
||
once in a compact matrix and inherited by every matching protocol. Each profile
|
||
contains three fixed stat identities and editable values. Individual protocol
|
||
editors show the inherited profile read-only and store one unique primary stat
|
||
with a level-1 base value. That primary value scales linearly to exactly twice
|
||
its base at level 50.
|
||
|
||
Protocol identity forms stack the four-choice quality radio band above the
|
||
three-choice secondary-profile type band, with the protocol name occupying the
|
||
larger adjacent column. Quality choices use their global semantic color plus an
|
||
explicit text label and selected underline; profile types retain their
|
||
icon-backed labels. Both controls collapse below the name on narrow screens.
|
||
|
||
The shared secondary-profile matrix is collapsed by default because it is
|
||
configuration infrastructure rather than a frequent protocol-editing task. Its
|
||
disclosure header always exposes the configured total, uses a textual title,
|
||
and rotates the plus indicator when expanded. The full matrix remains keyboard
|
||
operable and follows the shared hover, focus-visible, and pressed states.
|
||
|
||
### Game-data icons
|
||
|
||
OS Protocols, brand sets, and talents use the shared game-data icon upload
|
||
control in their ISAC editors. Existing artwork is previewed and may be
|
||
replaced or explicitly removed. Registry identity cells render a compact
|
||
thumbnail before the record name and retain a neutral textual fallback when no
|
||
icon is configured.
|
||
|
||
Source artwork must be a transparent SVG, PNG, WebP, or AVIF no larger than
|
||
2 MiB. SVG is treated only as an upload source and never served directly.
|
||
Accepted images are normalized asynchronously to a metadata-free transparent
|
||
256 × 256 WebP with `contain`, preserving the full symbol without avatar-style
|
||
cropping. Image labels remain visible in the UI, so icons supplement rather
|
||
than replace textual identity. Upload, replace, remove, pending, validation,
|
||
focus-visible, and narrow-screen states follow the shared engineered form
|
||
language.
|
||
|
||
For compact editors such as brand sets, place the icon rail beside the record
|
||
name and its primary configuration rows instead of giving the upload control a
|
||
full-width band. Keep destructive archive controls isolated on the left side of
|
||
the action bar and use the established `.moderation-action.danger` treatment;
|
||
save and cancel remain grouped on the right.
|
||
|
||
Archived records that support restoration replace their destructive archive
|
||
control with a green outlined `.moderation-action.restore` control in the same
|
||
left-side position. The label must explicitly say “Unarchive” or “Restore”;
|
||
never communicate restoration by color or icon alone.
|
||
|
||
The dedicated unique-talent panel uses five interactive diamonds: no filled
|
||
diamonds is the base definition, and each selected upgrade adds one fifth of
|
||
the base until five upgrades show exactly twice the base effect.
|
||
|
||
Diamonds are both a progression preview and an explicit numeric state; expose
|
||
their upgrade number and `aria-pressed` state rather than relying on fill color.
|
||
Protocol talents own their effects but reuse the global stat and trigger
|
||
registries. Shared secondary values do not scale with the individual protocol’s
|
||
level. Store only the unique primary and talent base values, and derive their
|
||
progression consistently in calculation and display code.
|
||
|
||
### ISAC editor lifecycle
|
||
|
||
Successful saves have a consistent outcome throughout data management:
|
||
editing an existing record closes the editor and returns the user to the registry;
|
||
creating a new record keeps the editor open with a fresh blank definition for
|
||
rapid consecutive entry. Failed validation leaves the current editor and
|
||
entered values intact. Use a unique action result token so reactive handling
|
||
runs exactly once and does not create update loops.
|
||
|
||
Tiered-definition registries should show their rendered tier effects when the
|
||
text is operationally useful. Use compact wrapping description cells rather
|
||
than replacing meaningful data with a generic “configured” label; retain an
|
||
explicit textual missing state when a tier has no rendered description.
|
||
|
||
Talent mechanics are structured metadata, not free-form prose. Present optional
|
||
cooldown, duration, and maximum-stack inputs together in a compact three-column
|
||
mechanics strip that collapses to one column on narrow screens. Description
|
||
templates use numbered expressions (`{1}`, `{2}`) for tiered attribute effects
|
||
and named expressions (`{duration}`, `{max_stacks}`) for shared mechanics.
|
||
Named expressions are valid only when their corresponding value is defined.
|
||
Cooldown is never embedded in the description: render it consistently as
|
||
`Talent Cooldown: [value] seconds` beneath the talent identity or description.
|
||
Do not imply an absent mechanic with a zero value; show no cooldown line and
|
||
leave optional editor fields explicitly marked as not defined.
|
||
|
||
### Registry pagination
|
||
|
||
Every primary ISAC registry uses server-side pagination. The shared control
|
||
appears immediately above and visually attached to its table. It shows the
|
||
visible record range and total, previous/next navigation, a compact
|
||
window of page numbers, and row-count presets of 10, 25, 50, and 100. Existing
|
||
filter query parameters must survive page navigation, while changing page size
|
||
returns to page one. Summary metrics remain global or filter-global and must
|
||
never silently describe only the visible page. On narrow screens, retain
|
||
previous, next, current page, and page-size controls before optional page
|
||
numbers.
|
||
|
||
Registries with a meaningful name, title, or agent-identity column place the
|
||
shared server-side search inside this pagination rail. Submission resets the
|
||
page number while preserving the selected KPI filter and row-count preset;
|
||
page navigation preserves the query. Provide an explicit clear action whenever
|
||
a query is active. Search applies to the complete filtered registry before
|
||
pagination, including visible pending proposals, and never only to the current
|
||
page. Specialized oversight and history searches may remain in their richer
|
||
filter consoles when they search evidence beyond a single identity column.
|
||
|
||
At intermediate widths the search spans the pagination rail above its range
|
||
and navigation controls. At mobile widths all groups stack, the input retains a
|
||
usable width, and search, clear, previous, and next remain explicit keyboard
|
||
and touch targets.
|
||
|
||
### Registry metric filters
|
||
|
||
The KPI row above an ISAC registry is an operational filter surface, not passive
|
||
decoration. Use `KpiFilters.svelte` when each metric describes a meaningful
|
||
record subset. The first card returns to the complete current registry or search;
|
||
the remaining cards filter by useful classifications such as active state,
|
||
category, equipment behavior, or restriction state.
|
||
|
||
Filtering is server-backed and occurs before pagination. Filter links preserve
|
||
compatible search and page-size parameters, reset the page number, remain
|
||
bookmarkable, and expose the selected state with both orange emphasis and
|
||
`aria-current`. Cards require pointer, hover, focus-visible, pressed, and
|
||
textually identifiable active states. Counts describe the full search scope,
|
||
not merely the visible page. Do not use aggregate facts that cannot filter the
|
||
affected registry—replace them with actionable subsets.
|
||
|
||
### Image uploads
|
||
|
||
All image uploads use the shared SHD drop-zone treatment and expose three equivalent
|
||
selection paths: a file picker, drag and drop, and clipboard paste. The control shows
|
||
the selected filename and a local preview, but server-side format, size, transparency,
|
||
and normalization checks remain authoritative.
|
||
|
||
### Moderated data states
|
||
|
||
ISAC must clearly distinguish direct editing, contributor proposals, and read-only
|
||
access. Use a compact access banner above the module rather than changing the
|
||
registry layout. Pending proposal counts appear as orange numeric indicators in
|
||
data-navigation items. Proposal lifecycle states use text as well as color:
|
||
pending is orange/actionable, approved is green/configured, and rejected or
|
||
failed is red/archived. Review decisions always use the standard ISAC confirmation
|
||
surface and must never apply a proposal from a table-row click alone.
|
||
|
||
Eligible contributors enter ISAC data modules in read-only mode by default.
|
||
The access banner pairs the explicit `READ-ONLY DATA ACCESS` state with a compact
|
||
action that opens the versioned contributor guidelines. Contributor mode may
|
||
only be enabled after affirmative checkbox acceptance. Once enabled, the banner
|
||
changes to orange, explains that saves enter moderation, and offers a
|
||
`RETURN TO READ-ONLY` toggle. Disabling is immediate and reversible and does not
|
||
withdraw existing proposals. Use text for every mode state; color alone is
|
||
insufficient. At narrow widths, stack the explanation and full-width toggle.
|
||
Read-only mode is an inspection surface: hide add controls, row edit actions,
|
||
mutation forms, and editors opened through URL state. Do not merely dim or
|
||
disable them. Registry navigation, KPI filters, pagination, search, evidence,
|
||
and other non-mutating inspection controls remain visible and interactive.
|
||
|
||
The ISAC command-status cluster includes an explicit `DATA MODE` cell alongside
|
||
system, access, and environment. It reports the highest effective data authority
|
||
in this order: `ADMIN`, `OVERSIGHT`, `DATA MANAGER`, `CONTRIBUTOR`, then
|
||
`READ-ONLY`. Use a neutral treatment for read-only, orange for contributor,
|
||
blue for Oversight authority, and green for direct-management authority. The
|
||
label and value are mandatory because color is supplemental. At medium widths
|
||
the four cells become a two-column grid; on narrow screens the cluster spans
|
||
the command header width.
|
||
|
||
### Oversight proposal corrections
|
||
|
||
User-facing references to moderators and data approvers use the SHD term
|
||
`Oversight`. Distinguish `Community Oversight` from `Data Oversight` when a role
|
||
name must identify its operational domain.
|
||
|
||
Pending proposal review uses three equal decision controls: approve, correct,
|
||
and reject. `CORRECT` is limited to small text or numeric fixes. Present the
|
||
stored form fields in a compact two-column correction grid and identify their
|
||
original field names; long descriptions and structured JSON values use
|
||
textareas. Uploaded file evidence is visible but immutable. Every correction
|
||
must be separately saved and audit logged before approval, and material changes
|
||
should be rejected for contributor revision. Collapse the decision controls and
|
||
correction fields to one column on narrow screens.
|
||
|
||
Proposal evidence is reviewer-facing product data, not JSON-first diagnostics.
|
||
Open review in a wide, scroll-contained confirmation surface and present live
|
||
and proposed values side by side using the visual structure and terminology of
|
||
the source module's editor. Label the two states explicitly as `CURRENT LIVE /
|
||
BEFORE` and `PROPOSED / AFTER`; for additions, replace the empty live panel with
|
||
an explicit `NEW RECORD` state. Stack comparisons on narrow screens. Raw stored
|
||
payloads remain available in a collapsed technical-evidence disclosure for
|
||
troubleshooting and audit support, but must not be the primary review surface.
|
||
Each module should add a purpose-built preview as its editor matures; until then,
|
||
use compact labeled field cards rather than an exposed JSON document.
|
||
|
||
Data-navigation links with pending proposals use a dedicated four-column layout:
|
||
module code, flexible label, square orange count cell, then navigation arrow.
|
||
Never insert a count into the ordinary three-column link without changing its
|
||
grid, because the arrow will wrap to another row. The count includes textual
|
||
assistive labeling and strengthens its border and contrast on link hover or
|
||
active state.
|
||
|
||
Pending records may be used as dependencies in later proposals by any
|
||
contributor. Render these choices in the ordinary assignment control with a
|
||
restrained orange border/background and the explicit text `PENDING` plus the
|
||
proposer’s display name; never present them as live data. Approval is dependency
|
||
ordered: a dependent proposal stays pending until every referenced proposal is
|
||
approved, while rejected or failed dependencies block it. This state must be
|
||
conveyed by text as well as color and must remain legible in compact and
|
||
responsive editor layouts.
|
||
|
||
Large many-to-many selections use the shared searchable assignment control,
|
||
including weapon talent pools, gear talent compatibility, and compatible brand
|
||
sets. The control keeps assigned records visible as removable chips, filters
|
||
available records by name, limits the rendered result set, and submits canonical
|
||
hidden inputs. Configure its subject labels and empty-state copy for the entity
|
||
being assigned rather than embedding talent-specific language in the shared
|
||
component. Pending contributor records retain their orange treatment and named
|
||
proposer in both search results and dependency workflows.
|
||
|
||
Audit History may use a five-column KPI filter rail when all durable operational
|
||
domains need first-class visibility. It retains the standard compact KPI height
|
||
and collapses through the shared dashboard breakpoints; do not increase card
|
||
height or create a second row solely to accommodate the fifth domain.
|
||
|
||
Inherent permissions that cannot be removed through role or user assignment use
|
||
the compact blue information rail above the affected access controls. Always
|
||
name the baseline and enumerate its capabilities so operators do not mistake an
|
||
empty role assignment for an account with no effective access.
|
||
|
||
### Mobile registry detail targets
|
||
|
||
On narrow screens, a non-editing registry row with one canonical detail or
|
||
review destination becomes a full-row tap target. Use a real stretched link
|
||
when the destination is another route and a transparent button when it opens an
|
||
in-page detail surface. Keep the explicit desktop `VIEW`, `REVIEW`, or
|
||
`EVIDENCE` action, and add a visible mobile cue at the bottom of the row so the
|
||
interaction is discoverable.
|
||
|
||
The target must expose an accurate accessible name, show the standard orange
|
||
focus-visible outline, provide pressed feedback, and meet a minimum 48-pixel
|
||
tap height. Do not apply this pattern to edit, delete, approve, or other
|
||
mutating actions, and do not stretch a target across rows containing independent
|
||
interactive controls.
|
||
|
||
### Avatar Oversight
|
||
|
||
Custom avatars are active immediately and enter a separate Avatar Oversight
|
||
queue. The registry uses compact image-evidence cards rather than a text table:
|
||
portrait, explicit lifecycle state, agent identity, submission time, normalized
|
||
size, reviewer, and note stay visible together. Pending is orange, approved is
|
||
green, and removed is red; withdrawn and superseded remain neutral. State text
|
||
is mandatory.
|
||
|
||
Review uses the standard ISAC modal and two equal decision controls. Approval
|
||
records the review without changing the active image. Removal requires a reason
|
||
and explicit confirmation, deletes the custom file, and returns the account to
|
||
the default SHD portrait. A stale review must never act on a newer upload.
|
||
Historical entries retain metadata and audit evidence even when their image is
|
||
no longer available. At narrow widths cards become one column, retain a large
|
||
portrait preview, and expose a minimum 44-pixel review action.
|
||
|
||
### Notification network
|
||
|
||
Authenticated navigation exposes a compact inbox glyph with a numeric unread
|
||
badge; mobile navigation provides the same explicit `INBOX` destination and
|
||
count. Notifications live under the agent-profile namespace and use an explicit
|
||
profile context trail back to account controls. The inbox is a dense
|
||
communication registry with a source rail, category,
|
||
title, timestamp, body, destination, and textual read state. Unread messages use
|
||
the orange action rail. Mandatory ISAC notices use the blue operational rail and
|
||
must always remain visible in the in-app inbox.
|
||
|
||
Preferences are channel-by-category rather than global. Each category controls
|
||
in-app, browser, and email delivery independently. ISAC in-app delivery is
|
||
locked on, while its browser and email channels remain optional. Email defaults
|
||
to off and offers `OFF`, `IMMEDIATE`, and `DAILY DIGEST`; browser delivery must
|
||
follow an explicit browser permission gesture. Never imply background push when
|
||
only active-site browser polling is available. At narrow widths preference rows
|
||
stack their identity above channel controls and notification entries collapse
|
||
their source rail above the message.
|
||
|
||
The main Agent Profile surfaces the five most recent enabled inbox messages
|
||
before authored-content modules and includes unread count as a profile metric.
|
||
This preview preserves mandatory, unread, source, and category states, uses
|
||
single-line truncation at desktop density, and links to either the notification
|
||
destination or full profile inbox. On mobile, metadata becomes its own row and
|
||
message body copy may wrap.
|
||
|
||
Inbox messages use sender identity and semantic tone. ISAC sources use the SHD
|
||
system mark, blue system labeling, and an explicit `SYSTEM` descriptor;
|
||
community activity uses an agent portrait and `AGENT` descriptor. Positive
|
||
outcomes use green, adverse or corrective outcomes use red, and informational
|
||
content stays neutral. Message titles and body copy state the actual outcome;
|
||
do not expose internal sentiment labels such as `POSITIVE`, `NEGATIVE`, or
|
||
`NEUTRAL`. Reserve visible badges for operationally meaningful severity such as
|
||
`WARNING` or `ERROR`, while the message wording remains understandable without
|
||
depending on color alone.
|
||
|
||
The inbox command header pairs the page identity with a compact bordered unread
|
||
summary and a same-height preferences action. Filter selects and adjacent
|
||
actions share a 40-pixel control height and vertically centered labels. Within
|
||
each message, the tone/title/timestamp header uses modest vertical padding and a
|
||
subtle lower rule: keep it dense, but never collapse it into a text-height strip.
|
||
On mobile the unread summary and preferences action share one grid row, while
|
||
filter controls stack into full-width, minimum 44-pixel targets.
|
||
|
||
Page hierarchy uses the shared eyebrow breadcrumb rather than a separate
|
||
breadcrumb row above a command header. It retains the short orange rule, renders
|
||
ancestors as orange links, separates levels with a muted slash, and marks the
|
||
final item as the current page. A top-level page may use a single current item.
|
||
Do not duplicate the same hierarchy in both an eyebrow and a second contextual
|
||
navigation strip; this creates visual overlap and wastes vertical space. The
|
||
breadcrumb always uses intrinsic height and must not inherit the full-height
|
||
primary-navigation treatment. Likewise, in-page command and message headings
|
||
must use their named component classes rather than the global application
|
||
`header` element treatment.
|
||
|
||
`VIEW DETAILS` opens the standard in-page modal rather than navigating
|
||
immediately. The modal repeats sender, source, category, semantic tone, time,
|
||
full message body, read control, and optional related-page destination. This
|
||
keeps review context in the inbox and makes outbound navigation deliberate.
|
||
|
||
ISAC message content uses the structured system-transmission body. A compact
|
||
blue `ISAC TRANSMISSION` kicker precedes the summary, and recognized supporting
|
||
fields such as `OVERSIGHT REASON`, `REQUIRED ACTION`, or `DETAILS` become a
|
||
labeled detail row beneath a subtle divider. The expanded message view uses the
|
||
same hierarchy at reading size. Community messages remain conversational body
|
||
copy; do not apply the system-transmission frame to agent comments.
|
||
|
||
Inbox entries expose two distinct actions. `VIEW DETAILS` opens the complete
|
||
message when preview copy is truncated to two lines. A separate bordered orange
|
||
response action navigates directly to the known workflow and uses specific
|
||
language such as `UPLOAD NEW AVATAR`, `REVISE CONTRIBUTION`, or
|
||
`VIEW BUILD & REPLY`; never substitute a generic destination label when the
|
||
notification type is known. The same response label appears in the detail
|
||
modal. On mobile, response actions become full-width 44-pixel targets.
|
||
|
||
Inbox filtering uses additive segmented selectors derived from the OS Protocol
|
||
quality control. Channels and message states are independent checkbox-backed
|
||
segments, all selected by default, and each selection change applies
|
||
immediately without a submit button. Selected segments use the orange lower
|
||
rail and filled square indicator; deselected segments remain readable and
|
||
available. The channel rail collapses from six to three and then two columns as
|
||
space narrows, with minimum 44-pixel mobile targets.
|
||
|
||
Use the shared `SegmentedChoice` component for every static, scannable ISAC
|
||
choice set containing two through six options. Radio mode represents one
|
||
required choice; checkbox mode represents additive independent choices. This
|
||
rule applies equally to editors and registry filters: do not introduce a native
|
||
dropdown merely to save vertical space. Use the shared `SearchableAssignment`
|
||
component in single or multiple mode when there are seven or more options, when
|
||
the options come from a growing data registry, or when search materially helps
|
||
recognition. Compact mode is the standard treatment for filter bars and dense
|
||
repeated rows; full mode is used for primary relationships.
|
||
|
||
Native selects are not a default ISAC control. Retain one only when a documented
|
||
browser-native behavior cannot be represented accessibly by either shared
|
||
component. Such an exception must be called out in this design system in the
|
||
same change. Both shared choice patterns expose explicit selection, hover,
|
||
pressed, focus-visible, disabled, empty/all, responsive, and 44-pixel
|
||
mobile-target states so modules do not reimplement them.
|
||
|
||
Numeric inputs inside ISAC use overwrite-first focus behavior: focusing an
|
||
enabled `type="number"` control selects its complete current value so a
|
||
contributor can immediately type a replacement instead of appending to a
|
||
default zero. This behavior belongs to the shared ISAC layout boundary and must
|
||
not be reimplemented in individual modules. Disabled numeric controls remain
|
||
unfocusable and unchanged.
|
||
|
||
`SegmentedChoice` supports two restrained density variants. Icon-only segments
|
||
may omit visible text when a canonical, unambiguous game icon exists; they must
|
||
retain an accessible label and hover title. Text-only segments may omit the
|
||
default square indicator when the selected background, orange text, and lower
|
||
rail already communicate state clearly. Do not remove both visible text and an
|
||
icon from the same option.
|
||
|
||
### Skill Chip data console
|
||
|
||
Skill Chip editing follows the dense ISAC staged-definition pattern: identity
|
||
and icon first, the 2-piece numeric bonus second, mutually exclusive primary
|
||
and secondary roll pools next, and the 3-piece talent last. Superior blue and
|
||
High-end yellow communicate the only supported qualities; orange remains
|
||
reserved for actions and current interactive state. A four-step segmented
|
||
preview exposes the linear zero-to-three High-end interpolation without storing
|
||
duplicate values. At narrow widths the roll pools and talent columns stack,
|
||
preview segments become a two-by-two grid, and interactive targets remain at
|
||
least 44 pixels tall.
|
||
|
||
### ISAC record identity controls
|
||
|
||
Game-data icon editors use the shared `--isac-icon-editor-width` footprint
|
||
(150 pixels on desktop) regardless of module. Identity layouts allocate that
|
||
fixed column to `IconUploadField`, give the record name the flexible dominant
|
||
column, and stack both controls at mobile widths. Do not enlarge an upload
|
||
drop-zone to fill spare identity-row space.
|
||
|
||
Icon-enabled consecutive-entry editors pass a successful-add result token into
|
||
the shared upload control. Advancing that token clears the native file input,
|
||
temporary preview URL, filename, drag/paste feedback, and validation state.
|
||
This reset occurs only after a validated add succeeds; failed saves preserve
|
||
the selected image, and successful edits close the editor normally.
|
||
|
||
The primary `name` field in every ISAC data editor is a header-level input:
|
||
46 pixels tall with larger, heavier text. This creates a consistent first
|
||
reading point for long registries while keeping secondary metadata compact.
|
||
|
||
`SearchableAssignment` is the standard relationship picker for long attribute,
|
||
talent, trigger, and compatibility lists. Multiple mode manages additive sets;
|
||
single mode presents the same searchable selected/result treatment for one
|
||
relationship. Prefer these modes over native selects once a source registry is
|
||
large enough that scanning a dropdown is inefficient. The selected record,
|
||
pending-contribution state, keyboard focus, and remove interaction must remain
|
||
explicit in both modes.
|
||
|
||
Every ISAC relationship to an Attribute uses `SearchableAssignment`; native
|
||
attribute dropdowns are not permitted because the registry is expected to
|
||
contain hundreds of records. Use full mode for primary editor sections and
|
||
multi-value pools. Use compact single mode inside repeated effect, bonus, or
|
||
augmentation rows: its selected record and search field remain inline while
|
||
the filtered result registry opens as an anchored overlay. The compact overlay
|
||
must layer above adjacent rows, retain pending-record labels, and collapse to
|
||
one column on narrow screens.
|
||
|
||
Gear identity editing uses the shared segmented radio treatment for both Gear
|
||
slot and item tier. Show all six slots together and all three tiers together so
|
||
contributors can verify classification without opening a menu. The record name
|
||
remains the dominant text field; at medium widths it occupies a full row above
|
||
the two selectors. On narrow screens the slot selector becomes a three-by-two
|
||
grid, both selectors use at least 44-pixel targets, and changing slot clears
|
||
incompatible Talent relationships exactly as the former selector did. Gear
|
||
slot segments use icon-only controls with accessible slot names; registry labels
|
||
retain icon and text for rapid table scanning. Tier segments use the compact
|
||
game notation `T0`, `T1`, and `T2`, omit the redundant square indicator, and
|
||
rely on the selected rail and color; do not expand these to “Tier 0” inside
|
||
dense segmented controls. On desktop, icon-only Gear slot segments are square
|
||
32-pixel cells so their classification rail stays compact and the adjacent
|
||
record-name input receives the dominant width. Increase those cells to square
|
||
44-pixel targets at mobile sizes without reintroducing visible slot text.
|
||
|
||
Weapon-category editing follows the same compact icon-rail treatment: Shotgun,
|
||
Rifle, MMR, AR, LMG, and SMG use their canonical weapon silhouettes in square
|
||
32-pixel desktop cells and 44-pixel mobile cells, with accessible names and
|
||
hover titles retained. Exotic remains an independent icon-backed status because
|
||
an Exotic weapon must also retain its underlying weapon category. Weapon
|
||
Damage Type follows the same icon-only treatment when canonical Blast, Pierce,
|
||
and Shredding marks are available. Exotic status is a single square checkbox
|
||
whose icon, orange rail, and background show its checked state; no visible
|
||
“Exotic weapon” label is repeated inside the control. Weapon registry rows show
|
||
both the category silhouette and, when applicable, the Exotic mark alongside
|
||
the textual class for rapid scanning.
|
||
|
||
Weapon Tier Progression begins at the selected Native Tier. Lower tier cards
|
||
remain visible for orientation but are disabled, desaturated, and explicitly
|
||
labeled unavailable; their values are neither required nor persisted. Each
|
||
available tier has one Damage range labeled with the selected damage-type icon
|
||
and one shared Core range for Firepower, Toughness, and Engineering, represented
|
||
by all three primary-attribute icons. Registry completeness compares configured
|
||
tiers with the number possible from the weapon’s Native Tier. Archive Weapon
|
||
uses the standard separated ISAC destructive-action control on the left side of
|
||
the editor action band.
|
||
|
||
Root-level static PNGs are interface icons and use content-fitted transparent
|
||
bounds. Run `npm run assets:trim-icons` after adding or replacing them. The
|
||
normalizer trims fully transparent padding, restores a two-pixel transparent
|
||
safety margin so antialiased edges never touch the canvas, preserves RGBA PNG
|
||
output, and leaves portrait/avatar and SVG asset classes untouched.
|
||
|
||
### Shared equipment profiles
|
||
|
||
Configuration inherited by every item of a finite equipment type belongs in a
|
||
collapsible shared-profile registry above the item table. Each profile card
|
||
states its type, required slot count, configured state, and a compact summary;
|
||
selecting it opens a separate dense editor and closes the individual-record
|
||
editor. Successful saves close the profile editor and return to the registry.
|
||
|
||
Gear Tactical Augment profiles use this pattern for all six gear types.
|
||
Backpacks and Body Armor expose four required slots; Holsters, Gloves, Knee
|
||
Pads, and Masks expose three. Augment 01 contains one searchable Attribute,
|
||
one numeric effect value, and an unlock cost. Later slots expose only their
|
||
unlock cost because their effects are fixed base-item upgrades: three-slot
|
||
profiles use +50% and +100%, while four-slot profiles use +40%, +70%, and
|
||
+100%. Holsters, Masks, and Backpacks modify the equipped item's base Health;
|
||
Gloves, Knee Pads, and Body Armor modify that item's base Health and Armor.
|
||
These percentages never apply to the overall character total. Every augment
|
||
slot stores separate non-negative whole-number unlock costs for item Tiers 0,
|
||
1, and 2. Show all three costs together in registry summaries and in a compact
|
||
three-column cost fieldset within the editor; the builder shows only the cost
|
||
matching the equipped item's tier. Fixed upgrades
|
||
use a green inherited-value panel to distinguish governed data from editable
|
||
orange actions. At narrow widths profile cards and augment editor cards reduce
|
||
to a single column while retaining 44-pixel interactive targets.
|
||
|
||
### Loadout workbench
|
||
|
||
The builder is a three-rail tactical workbench: compact equipment positions on
|
||
the left, the currently selected item editor in the center, and a sticky live
|
||
calculation summary on the right. At medium widths the summary becomes a
|
||
full-width lower rail; on mobile all three rails stack, with equipment first,
|
||
editing second, and results third. Equipment positions remain explicit even
|
||
when empty so loadout completeness is always visible.
|
||
|
||
Use the shared `BuilderPicker` for builder catalogs and Attribute pools. It
|
||
combines an always-visible current selection with a searchable overlay, icon or
|
||
tactical fallback mark, classification metadata, selected state, and conflict
|
||
state. Conflicting catalog entries remain visible but disabled so restrictions
|
||
such as the single-exotic-weapon rule are explained rather than hidden.
|
||
|
||
Numeric instance values display their authoritative minimum and maximum beside
|
||
the field and clamp to that range on completion. Always-on item rolls, fixed
|
||
bonuses, inherited profiles, enabled augments, and activated set bonuses feed
|
||
the live totals immediately. Trigger-dependent talents remain explicitly
|
||
`CONDITIONAL` until the user enables `TRIGGER ACTIVE`; only then may their
|
||
effects enter combined totals. This textual distinction must remain clear
|
||
without relying on color.
|
||
|
||
### Pending ISAC registry records
|
||
|
||
Pending additions appear directly in the same paginated ISAC registry as live
|
||
records and in every compatible relationship picker. They use a restrained
|
||
orange-tinted row, an explicit `PENDING` state, and proposer attribution.
|
||
Pending rows are read-only in module registries; changes remain the authority
|
||
of the Data Oversight review interface. Successful contributor submissions
|
||
refresh the registry immediately and follow the same editor lifecycle as a
|
||
direct save. Never rely on the tint alone to communicate moderation state.
|
||
|
||
Gear and weapon level are builder-instance state, never part of an ISAC item
|
||
definition. Each equipped item stores its own level from 1–50 in the local or
|
||
persisted build. Range endpoints are calculated from the documented level
|
||
curve and stored reference level; provisional portions of that curve must be
|
||
identified in text as estimated.
|
||
|
||
### Registry relationship icon rails
|
||
|
||
When a table relationship contains a small bounded set of visually identified
|
||
records, show a compact icon rail instead of a numeric relationship count.
|
||
Rails use 30-pixel square cells with four-pixel spacing, uploaded transparent
|
||
icons, full accessible names, and native hover titles. Missing artwork falls
|
||
back to a short orange text mark rather than removing the relationship.
|
||
|
||
Use this pattern only for small bounded sets that remain scannable, such as the
|
||
two-to-four compatible Brand Sets on Gear. Long or unbounded relationships
|
||
continue to use counts, searchable inspection, or expanded detail views.
|