1928 lines
113 KiB
Markdown
1928 lines
113 KiB
Markdown
# SHD.build Design System
|
||
|
||
This document defines the visual language for SHD.build, an independent
|
||
Division Resurgence data-and-tools site for builds, guides, game data, news,
|
||
and discussion. New pages use the same tactical intelligence network as the
|
||
admin dashboard. Public pages may use more space and larger editorial
|
||
typography.
|
||
|
||
## Design principles
|
||
|
||
1. **Tactical.** Use operational language, compact information density, restrained status indicators, and precise alignment. Avoid camouflage, distressed textures, and decorative weapon imagery in utility interfaces.
|
||
2. **Data first.** Grouping, typography, borders, and spacing establish hierarchy. Admin tools use a dependable control surface.
|
||
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.
|
||
|
||
## Brand identity
|
||
|
||
SHD.build uses the two-color Core Segments identity. The emblem combines the
|
||
orange Division signal with ISAC's analytic role in the product:
|
||
|
||
- Three unequal Signal Orange arc segments form the outer circle. Each segment
|
||
has square ends.
|
||
- The widest break sits in the upper-right quadrant and contains one detached
|
||
Signal Orange square, which represents a data packet.
|
||
- A Field Manual White open square forms the ISAC core at the center.
|
||
|
||
Keep the emblem in Signal Orange and Field Manual White on Operations Black,
|
||
Terminal Black, or another approved dark surface. SHD.build has no one-color
|
||
emblem. Do not close the arc gaps, equalize the segments, remove the data
|
||
packet, fill the ISAC core, add letters to the emblem, or recolor either part.
|
||
Use a dark holding surface or omit the emblem when a placement cannot reproduce
|
||
both colors.
|
||
|
||
The standard lockup pairs the emblem with the heavy angular `SHD.build`
|
||
wordmark. Set `SHD` in Field Manual White and `.build` in Signal Orange. Place
|
||
the uppercase descriptor `RESURGENCE DATA & TOOLS` below the wordmark in
|
||
restrained telemetry type. Do not substitute another descriptor.
|
||
|
||
Use the complete lockup in the 76px global header and shared footer. The header
|
||
uses a 38px emblem; keep the wordmark and descriptor compact enough to preserve
|
||
the navigation grid. Mobile headers may use the emblem alone when the complete
|
||
lockup would crowd navigation. Favicons and app icons use the emblem without
|
||
text. Small-size artwork must retain both colors, widen the arc gaps where the
|
||
pixel grid requires it, and keep the packet and open core distinct.
|
||
|
||
Treat the emblem as decorative when visible `SHD.build` text names the product.
|
||
Give an emblem-only home link the accessible name `SHD.build home`. Preserve
|
||
the approved colors and full opacity in focus, disabled, and compact contexts;
|
||
use text or control styling to communicate state instead of fading the mark.
|
||
The Field Manual White core and Signal Orange arcs must remain distinct from
|
||
their background at every delivered size.
|
||
|
||
### Routed error console
|
||
|
||
Expected HTTP errors and unexpected server faults use one shared SHD exception
|
||
console inside the application shell. The console 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. Do not display stack traces, database messages, credentials, request
|
||
queries, or raw unexpected exceptions. The global error handler gives each
|
||
unexpected server fault a short support reference ID and keeps the full error
|
||
server-side. If the root application shell 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: a broad transmission form and a
|
||
compact destination guide. Two-to-six destinations use the shared
|
||
segmented-choice pattern. Signed-in identity details may be prefilled; people
|
||
who cannot sign in retain access to the public form. Discord community access
|
||
uses a distinct provider-colored card alongside the durable contact channel.
|
||
|
||
The Contact hero resets the global site-header height: semantic page `header`
|
||
elements use content-driven height and spacing instead of 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 uses a full-viewport vertical flex stack. The shared
|
||
footer uses automatic top margin. It rests against the bottom edge on short
|
||
routes and follows document flow after longer content. Do not add spacer heights
|
||
only 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 Core Segments lockup used by the global header:
|
||
two-color emblem, Field Manual White `SHD`, Signal Orange `.build`, and the
|
||
`RESURGENCE DATA & TOOLS` descriptor. Do not substitute a plain text wordmark,
|
||
drop either emblem color, or color the complete product name orange.
|
||
|
||
### Platform positioning
|
||
|
||
SHD.build provides Division Resurgence data and tools for players. Primary
|
||
product language and global navigation represent five durable channels: News,
|
||
Database, Builds, Guides, and Builder. Loadout-specific terms remain
|
||
appropriate inside build routes. The global brand descriptor, homepage
|
||
metadata, hero, sign-in introduction, and footer describe the broader toolset.
|
||
|
||
The homepage uses a community-channel grid to establish this information
|
||
architecture. Each channel has an operational code, plain-language purpose,
|
||
and explicit destination. New channels should extend this reusable pattern
|
||
rather than turning the navigation into an undifferentiated list. Honest
|
||
launch-state pages may describe planned capability, but must distinguish queued
|
||
features from live data. Database landing metrics use approved active records,
|
||
not invented activity counts.
|
||
|
||
On desktop the five public destinations remain visible in the global
|
||
navigation. Mobile navigation numbers destinations dynamically so adding a
|
||
channel cannot collide with Inbox, Profile, or ISAC codes. Community channel
|
||
cards collapse from four columns to two and then one; hover color alone never
|
||
replaces their textual destination labels, focus-visible treatment, or pressed
|
||
feedback.
|
||
|
||
Authenticated desktop account destinations are consolidated into one
|
||
agent-status menu at the right edge of the global header. Its trigger combines
|
||
the agent avatar, display name, online state, unread count, and an explicit
|
||
expanded marker. The menu contains My Profile, Notifications, and Sign Out;
|
||
these actions are not duplicated as standalone desktop header links. The menu
|
||
uses the same square, compact control-surface treatment as the rest of the
|
||
header, with orange reserved for the open/current state and unread count and
|
||
danger color reserved for the Sign Out hover state.
|
||
|
||
The account trigger exposes its expanded and controlled-menu state. Opening the
|
||
menu moves keyboard focus to its first destination; Escape closes it and
|
||
returns focus to the trigger, while an outside click dismisses it. Mobile keeps
|
||
Profile, Notifications, and Sign Out as explicit navigation actions and shows
|
||
the avatar in the signed-in identity block. Avatar imagery supplements rather
|
||
than replaces the textual identity, state, and unread indicators. User avatars
|
||
are always rendered as circular portraits with the restrained orange SHD ring
|
||
used by the Agent Profile; the source image remains square and uses
|
||
`object-fit: cover` so authenticated surfaces crop it consistently.
|
||
|
||
When unread notifications exist on mobile, repeat the compact orange count on
|
||
both the menu trigger and the Notifications destination. The trigger badge sits
|
||
outside the upper-right control edge without changing the hamburger geometry.
|
||
Its accessible name includes the full unread count; the visible badge is hidden
|
||
from assistive technology to avoid announcing the count twice.
|
||
|
||
Oversight reviewers receive a permission-aware cadence console inside
|
||
Notification Preferences. Each available review queue is shown independently
|
||
and uses the shared segmented radio pattern for Immediate, 15-minute, one-hour,
|
||
or daily delivery. Do not expose categories the agent cannot review.
|
||
Consolidated delivery groups queue items rather than issuing repeated messages;
|
||
daily delivery targets 10:00 AM in `America/New_York` so the Eastern wall-clock
|
||
time remains stable across daylight-saving transitions. On mobile, cadence
|
||
segments wrap to two columns and each review category becomes its own row.
|
||
|
||
ISAC System Configuration is a distinct navigation domain from System
|
||
Oversight. It contains operational configuration such as Automated Messages and
|
||
read-only observability such as System Metrics. Automated-message editors use
|
||
the standard horizontal edit lifecycle: successful edits close the editor,
|
||
validation preserves it, and event triggers remain explicit. Content, enabled
|
||
state, post-event delay, primary destination, and up to eight action callouts
|
||
are displayed as structured fields rather than raw JSON.
|
||
|
||
Automated ISAC messages may expose multiple square action callouts in the
|
||
notification inbox and detail view. Callouts wrap on desktop and become
|
||
full-width touch targets on mobile. Each retains a specific verb and
|
||
destination; do not replace the set with a generic “open” action. External
|
||
community actions such as Discord use secure HTTPS destinations while internal
|
||
actions use routed paths.
|
||
|
||
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` |
|
||
| Modeled-data surface | `--shd-model-surface` | `#0d1213` |
|
||
| Subordinate border | `--shd-border-soft` | `#272c2d` |
|
||
| Primary border | `--shd-border` | `#303536` |
|
||
| Modeled-data border | `--shd-model-border` | `#3b4648` |
|
||
| Interactive boundary | `--shd-border-strong` | `#424849` |
|
||
| Main text | `--shd-text` | `#ecebe5` |
|
||
| Muted text | `--shd-text-muted` | `#858b8d` |
|
||
| SHD action orange | `--shd-orange` | `#f6a821` |
|
||
| Telemetry text floor | `--shd-type-telemetry` | `12px` |
|
||
| Supporting copy floor | `--shd-type-supporting` | `14px` |
|
||
| Ordinary body floor | `--shd-type-body` | `16px` |
|
||
| Adaptive display scale | `--shd-display-scale` | `1` by default; stepped on high-resolution desktops |
|
||
| Monospaced data | `--shd-font-mono` | Cascadia Mono with system monospace fallbacks |
|
||
|
||
### High-resolution display scaling
|
||
|
||
The application uses restrained stepped interface scaling on wide CSS
|
||
viewports. At 2200px, the interface scales to 115%; at 2800px, to 130%; and at
|
||
3400px, to 150%. This maintains the established relationship among typography,
|
||
controls, tables, spacing, hit targets, and fixed-position surfaces.
|
||
|
||
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
|
||
|
||
SHD.build self-hosts two type voices through Fontsource packages:
|
||
|
||
- **Barlow** is the operational family for display headings, navigation,
|
||
controls, data, labels, metadata, and general interface copy. Use the shared
|
||
`--shd-font-sans` token instead of declaring local sans-serif stacks.
|
||
- **Source Serif 4** is the editorial family for explanations, introductions,
|
||
guide-like prose, and longer descriptive passages. Use
|
||
`--shd-font-editorial`; do not apply it to controls, tables, metrics, or
|
||
telemetry labels.
|
||
|
||
Load Barlow weights 400, 600, 700, 800, and 900, plus Source Serif 4 weights
|
||
400 and 600. Both families are self-hosted, keep fallback stacks, and render
|
||
without a third-party font request. Barlow operates the system; Source Serif 4
|
||
explains it.
|
||
|
||
- Page and module headings are uppercase, heavy, and tightly spaced.
|
||
- Short operational labels, metadata, statuses, and compact actions use the
|
||
shared 12px telemetry floor. Their tracking must not exceed `0.1em`.
|
||
- Supporting descriptions use at least 14px with normal tracking. Ordinary
|
||
body and form copy uses the 16px body floor.
|
||
- High-resolution workspace scaling never justifies smaller source sizes:
|
||
density comes from spacing, connected borders, tone, and weight.
|
||
- Public/editorial copy uses Source Serif 4 for its restrained field-manual
|
||
character and stays within a 45–75 character reading measure.
|
||
- 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 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, each enabled public destination, Sign In or
|
||
My Profile, and ISAC when authorized. Authenticated agents also receive identity
|
||
state and Sign Out inside the panel. Section availability controls both desktop
|
||
and mobile navigation.
|
||
|
||
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.
|
||
- Public pages may use larger headings and more generous vertical rhythm.
|
||
- 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.
|
||
|
||
### Prelaunch network shell
|
||
|
||
Use the standalone prelaunch shell for `/coming-soon`. It replaces the global
|
||
application shell while the public launch gate is active, so visitors see one
|
||
clear deployment message instead of navigation into gated sections. Keep the
|
||
SHD.build mark, a visible network-state block, one primary access action, the
|
||
Discord community action, the deployment manifest, and legal links. Signed-out
|
||
visitors receive `AGENT SIGN IN`; an authenticated operator previewing the page
|
||
receives `ENTER FULL SITE`.
|
||
|
||
The desktop composition pairs the launch statement with a technical network
|
||
visual. Use the shared grid background, square borders, restrained orange
|
||
emphasis, and telemetry labels. Orange identifies the primary action and active
|
||
signal paths. Green may reinforce a staged or available state; red may reinforce
|
||
an unavailable channel. Every state also needs a text label.
|
||
|
||
The deployment manifest lists News, Database, Builds, Guides, and Builder with
|
||
plain-language descriptions. A visitor who follows a disabled-section URL sees
|
||
the affected section name in a status notice. The page must state whether new
|
||
agent registration is open without implying that sign-in for existing accounts
|
||
has closed. The manifest uses the saved section controls as its source of truth
|
||
and marks unavailable sections in text. An authenticated preview follows the
|
||
same availability states.
|
||
|
||
At widths below 900px, stack the launch statement above the network visual and
|
||
collapse the manifest to one column as space requires. Preserve 44px action
|
||
targets and keep status text within the viewport. Reduce the radar sweep and
|
||
other ambient motion under `prefers-reduced-motion`; retain the static rings,
|
||
nodes, and labels.
|
||
|
||
ISAC Site Controls use three connected command panels: Launch Gate, Account
|
||
Creation, and Public Sections. Use `SegmentedChoice` for each finite state.
|
||
Display the pending-change count outside the panels and require a confirmation
|
||
modal that lists every changed setting as previous state, arrow, and proposed
|
||
state. A successful save closes the modal and refreshes the network-state
|
||
summary. Keep a `PREVIEW PAGE` link in the command toolbar so authenticated
|
||
operators can inspect the promotional page without ending their session.
|
||
Operators need text for enabled, disabled, coming-soon, and public states; color
|
||
supports those labels.
|
||
|
||
The Launch Gate controls signed-out entry to the application. Public Section
|
||
controls apply to everyone. When an operator disables News, Database, Builds,
|
||
Guides, or Builder, remove that destination from global navigation for signed-in
|
||
and signed-out users and block its route family on the server. The promotional
|
||
page identifies a disabled destination when a user follows an old bookmark or
|
||
direct URL. Do not present authentication as a way around a disabled section.
|
||
|
||
### 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 imply availability through
|
||
styling.
|
||
- 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.
|
||
- With account creation disabled, keep returning-agent methods available, hide
|
||
the password `CREATE ACCOUNT` mode, and show a concise registration-state
|
||
notice. Provider and email controls must explain that unknown identities
|
||
cannot create an account without suggesting that existing identities lost
|
||
access.
|
||
- 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.
|
||
- In the ISAC rail, operational-domain headers are compact disclosure bars, not
|
||
module destinations. Give them a stronger surface, bold uppercase text, a
|
||
count, and a short leading status rail that turns orange while expanded.
|
||
Module destinations sit on the darker recessed surface below, use sentence
|
||
case and an additional left inset, and reserve the full orange rail for the
|
||
current module. Preserve this hierarchy when the rail becomes a mobile grid.
|
||
- ISAC module navigation uses complete, game-facing names such as `Weapons`,
|
||
`Talents`, and `OS Protocols`. Do not expose internal abbreviations such as
|
||
`WPN`, `TLNT`, or `OSPR`. Canonical game icons may supplement visible labels
|
||
inside module content and editor controls, but the navigation rail must not
|
||
invent iconography merely to replace clear language.
|
||
- 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`. New-record editors appear before the affected
|
||
table. Editing an existing record expands the same editor directly beneath
|
||
its selected row, which gains an orange selection rail and an explicit
|
||
expanded relationship for assistive technology. Inline editors stay aligned
|
||
to the visible registry viewport when the table scrolls horizontally. A
|
||
short clipped reveal confirms the expansion; reduced-motion preferences
|
||
remove that animation.
|
||
- Optional record descriptions use a full-width narrative field beneath the
|
||
identity controls. Preserve the same full-width placement in Oversight
|
||
before/after previews so reviewers can compare meaning without reading raw
|
||
proposal data.
|
||
- 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. External-service capacity reuses the same
|
||
metric panel: show distinct provider pools, the last authoritative check,
|
||
configured alert thresholds, and explicit `OK`, `WARNING`, `CRITICAL`, or
|
||
unavailable text. Green, orange, and red reinforce these states but never
|
||
replace their labels.
|
||
- 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.
|
||
- Text selection uses the SHD orange selection token with dark contrasting text;
|
||
never rely on the browser's white or platform-blue highlight. Focused text,
|
||
number, search, select, and textarea controls use a one-pixel orange border,
|
||
while keyboard `focus-visible` adds a restrained one-pixel external orange
|
||
ring with a one-pixel offset. Do not stack inset accent edges with this focus
|
||
treatment. Carets and native checkbox, radio, and range accents use orange.
|
||
Browser-autofilled fields retain the dark SHD surface and light text.
|
||
- 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.
|
||
|
||
Document a new interface pattern here when you introduce it.
|
||
|
||
## Design-system governance
|
||
|
||
Update this document and the shared implementation with each significant visual
|
||
or interaction change. A change qualifies when it introduces or revises a
|
||
reusable token, component pattern, layout, responsive rule, accessibility
|
||
behavior, motion behavior, or state convention.
|
||
|
||
Small alignment corrections and isolated visual bug fixes need no documentation
|
||
change unless they establish a reusable rule.
|
||
|
||
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 identity, renders at most thirty results at once, and
|
||
exposes counts for both assignments and matches. When records can share a name,
|
||
show the identity-defining qualifier below it in both selected chips and search
|
||
results. Attribute assignments use `UNIT · %`, `UNIT · s`, or `UNIT · FLAT`;
|
||
search and accessible names include that unit. 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.
|
||
|
||
The row-count presets remain available even when the current result fits on one
|
||
page. Omit only the page navigation when there is no second page. Do not render
|
||
disabled pagination controls merely to preserve the rail's shape.
|
||
|
||
Registries with a meaningful name, title, or agent-identity column place the
|
||
shared server-side search inside this pagination rail. Results update after a
|
||
short typing debounce, so do not place a redundant Search button beside the
|
||
field or label the field as live search. Show `SEARCHING…` only while navigation
|
||
is pending, and provide an explicit clear action whenever a query is active.
|
||
Search resets the page number while preserving the selected KPI filter and
|
||
row-count preset; page navigation preserves the query. 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.
|
||
|
||
### Sortable registry columns
|
||
|
||
Every meaningful data column in an ISAC table uses the shared sortable-column
|
||
header. The first activation sorts a new column in its most useful default
|
||
direction; later activations reverse the direction. Place a neutral
|
||
bidirectional indicator immediately before each inactive column label and an
|
||
orange directional indicator immediately before the active column label.
|
||
Action columns do not sort.
|
||
|
||
Sorting applies on the server before pagination. Store the selected column and
|
||
direction in the URL, preserve active search, filters, and row-count settings,
|
||
and return to page one when the sort changes. Server loaders must map public
|
||
sort keys to fixed, allowlisted SQL expressions or in-memory comparators. Never
|
||
interpolate a query-string value into SQL. Composite columns use a documented,
|
||
stable primary value and deterministic tie-breaker. Pending contribution rows
|
||
remain ahead of published records unless the registry explicitly defines a
|
||
different moderation order.
|
||
|
||
Sortable headers must expose column-header semantics and `aria-sort`, remain
|
||
keyboard operable, and show visible hover, focus, active, and selected states.
|
||
At narrow widths, retain the table's existing horizontal overflow behavior so
|
||
labels and sort state do not collapse into ambiguous controls.
|
||
|
||
### 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. Every card explicitly says `FILTER →`
|
||
or `SELECTED`; do not rely on KPI-card styling alone to communicate that the
|
||
metrics are controls. Counts describe the full search scope,
|
||
not merely the visible page. Replace aggregate facts that cannot filter the
|
||
affected registry with actionable subsets.
|
||
|
||
### Registry row interaction
|
||
|
||
Desktop registry rows are passive data containers unless the entire row opens
|
||
a detail view. Do not apply a whole-row hover surface when only
|
||
the trailing Edit or View action is interactive. Render that action as a
|
||
compact bordered control with hover, focus-visible, and pressed states so its
|
||
interaction boundary is unmistakable.
|
||
|
||
On mobile, a row may become a full-width detail target when the route provides
|
||
an intentional mobile detail interaction. In that case retain the explicit
|
||
`TAP TO VIEW` or `TAP TO REVIEW` text, full-row focus treatment, and minimum
|
||
touch target; do not infer full-row behavior from desktop hover styling.
|
||
|
||
### 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 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.
|
||
Show contributor access banners only on Data Management modules. Show the
|
||
`DATA MODE` status on those modules and the contributor-guidelines page. Omit
|
||
data-mode controls and language from User Operations, System Oversight, and
|
||
System Configuration because their permissions govern access independently.
|
||
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 system state, access state, the themed
|
||
ISAC node identifier, the CI build number, and an explicit `DATA MODE` cell.
|
||
The data-mode cell reports the highest effective 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. Every cell requires a
|
||
label and value because color provides supplemental information. At medium
|
||
widths, arrange the cells in a two-column grid and let the data-mode cell span
|
||
both columns. 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.
|
||
|
||
The same compact count cell identifies actionable work in System Oversight
|
||
navigation. Show it only for queues with unresolved items, such as pending data
|
||
proposals or avatar reviews, and calculate it within the viewer's permissions.
|
||
Do not add zero badges or counts to informational registries such as Audit
|
||
History and System Metrics. Badge text must expose an `awaiting review` label to
|
||
assistive technology; color supplements that meaning rather than replacing it.
|
||
|
||
Registry name search is server-backed and updates as the user types after a
|
||
short debounce; it must search the complete filtered registry rather than only
|
||
the visible page. Preserve active filters and row-count settings, reset results
|
||
to page one, keep input focus, avoid scrolling, and replace browser history so
|
||
each keystroke does not create a navigation entry. Retain an explicit Search
|
||
button for immediate submission and keyboard/accessibility fallback. During
|
||
navigation, expose a textual pending state and suppress duplicate submissions.
|
||
|
||
Builder option grids support an icon-only square mode for small, icon-led
|
||
catalogs such as a gear item's two-to-four compatible Brand Sets. In this mode,
|
||
the compact 58-pixel cells reset the ordinary text-and-icon grid to a single
|
||
centered track, and the transparent icon fills that square. Align the fieldset
|
||
with adjacent compact controls rather than inheriting the standard radio-grid
|
||
top margin. Visible truncated names are omitted. Preserve the complete name as
|
||
the radio control's accessible label and
|
||
as hover text. Selection, hover, pressed, and keyboard-focus states remain on
|
||
the square perimeter; missing icons fall back to the entity initials.
|
||
|
||
Builder level controls enforce item availability without changing the scaling
|
||
curve's origin. T0 and T1 gear and weapons allow levels 1–50; T2 gear and
|
||
weapons allow levels 40–50 because lower-level T2 items are not found in game.
|
||
Their base-value progression still follows the same level-1-based curve.
|
||
Selecting T2 on a weapon below level 40 raises the configured level to 40 and
|
||
calculates the ordinary level-40 curve value; never rebase level 40 as T2 level
|
||
1. Slider bounds, direct-input validation, displayed bounds, and clamping must
|
||
all enforce the same availability minimum.
|
||
|
||
ISAC ranges that represent observed values retain their explicit reference
|
||
level. The progression curve still has a level-1 origin, but builder scaling
|
||
must calculate the ratio between the target level and the stored observation's
|
||
`reference_level`. Do not treat every observed endpoint as a level-1 value
|
||
merely because the curve begins there.
|
||
|
||
Weapon damage is the exception to reference-observation scaling: each
|
||
weapon-tier damage range is stored as a hidden base and must be multiplied
|
||
directly by `weaponMultiplier(selectedLevel)`. Changing weapon level remaps the
|
||
selected damage value into the newly calculated range. Shared core attributes
|
||
remain level-50 reference profiles and use ratio scaling independently.
|
||
|
||
Gear base Health and Armor follow the same hidden-base principle. Multiply
|
||
their stored per-item endpoints directly by `gearMultiplier(selectedLevel)`,
|
||
truncate only for display, and remap the user's selected value proportionally
|
||
when gear level changes. Do not apply this rule to rolled Attributes or the
|
||
shared core-allocation profile, which retain independent reference semantics.
|
||
|
||
### Shared core allocation
|
||
|
||
Firepower, Toughness, and Engineering use one system-wide tier profile shared
|
||
by gear and weapons. Maintain the T0/T1/T2 nominal ranges in ISAC Global
|
||
Configuration rather than repeating them on every item editor. The initial
|
||
level-50 profiles are T0 `30–78`, T1 `36–94`, and T2 `44–112`. Global
|
||
configuration mutations follow ordinary contributor moderation and append-only
|
||
ISAC audit rules.
|
||
|
||
The three nominal ranges define a combined allocation pool, not three hard
|
||
per-stat clamps. At a given level, the valid total lies between three times the
|
||
scaled nominal minimum and three times the scaled nominal maximum. An
|
||
individual core may be zero or exceed the nominal maximum when points are
|
||
redistributed, up to the entire pool maximum. Builder gear and weapon editors
|
||
show three sliders/direct inputs plus an explicit current-total versus
|
||
valid-pool readout; out-of-pool totals use textual red/restricted feedback.
|
||
Both equipment families contribute their configured cores to the build summary.
|
||
Treat this redistribution model as empirical and keep it configurable as more
|
||
in-game edge cases are observed.
|
||
|
||
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 their displayed identity, limits the rendered result set,
|
||
and submits canonical hidden inputs. Configure its subject labels, qualifiers,
|
||
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 related-page destinations. Keep the sender
|
||
header and utility footer fixed while the message and action area scrolls.
|
||
Group destination actions beneath an `AVAILABLE ACTIONS` label in a regular
|
||
grid; reserve the footer for message state and closing the modal. Opening the
|
||
modal moves focus to its close control. Trap keyboard focus inside it, support
|
||
Escape and backdrop dismissal, and return focus to the originating `VIEW
|
||
DETAILS` control after closing. Inbox cards show up to four lines of body copy
|
||
at reading size before truncation. Place the per-message read control beside the
|
||
timestamp so message state remains separate from workflow actions.
|
||
|
||
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 its four-line preview truncates longer copy. A separate bordered
|
||
orange response action opens 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.
|
||
Lay out these controls in an auto-fitting grid so each label remains intact.
|
||
The detail modal uses the same response labels in a three-column grid where
|
||
space permits. On mobile, response actions become full-width 44-pixel targets.
|
||
|
||
Inbox query controls use two compact radio-backed segmented selectors. `SHOW`
|
||
switches between all, unread, and read messages. `SORT` offers newest, oldest,
|
||
and unread-first order. Give both selectors the same compact width. Each
|
||
selection applies without a submit button. Live search matches message titles,
|
||
bodies, and sources across the paginated result set. At narrow widths, the
|
||
selectors stack and retain 44-pixel 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. Do not render generic dots, squares,
|
||
checkbox facsimiles, or radio facsimiles inside segments. The selected
|
||
background, orange text, and lower rail communicate state. Keep visible text or
|
||
an icon in every option.
|
||
|
||
### Skill Chip data console
|
||
|
||
Skill Chip editing uses the dense ISAC staged-definition pattern: identity and
|
||
icon, 2-piece numeric bonus, mutually exclusive primary and secondary roll
|
||
pools, then 3-piece talent. Superior blue and High-end yellow identify the
|
||
supported qualities; reserve orange for actions and the current interactive
|
||
state. A four-step segmented preview shows the linear zero-to-three High-end
|
||
interpolation without duplicate values. At narrow widths, stack roll-pool and
|
||
talent columns, use a two-by-two preview grid, and retain 44-pixel targets.
|
||
|
||
### 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.
|
||
Reset only after a validated add succeeds. Failed saves preserve the selected
|
||
image; successful edits close the editor.
|
||
|
||
The primary `name` field in each ISAC data editor is a 46-pixel header-level
|
||
input with larger, heavier text. It gives long registries a consistent first
|
||
reading point 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`, 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.
|
||
Public Gear cards use the same rail for compatible Brand Sets and available
|
||
Talents so players can identify actual options instead of reading a count.
|
||
Each icon retains its accessible name and hover title, and missing artwork uses
|
||
the shared placeholder without suppressing the relationship. Relationship
|
||
icons are buttons: activating one opens a modal quick view using the same card
|
||
facts as that record's public database category. The overlay closes through
|
||
its explicit close action, backdrop, or Escape key. Do not render an empty
|
||
Talent rail on item types that cannot equip Talents.
|
||
|
||
### Public game-database registries
|
||
|
||
The public Database is a player-facing reference surface, separate from the
|
||
ISAC editing workflow. Its index exposes eight durable categories: Gear,
|
||
Weapons, Weapon Mods, Gear Mods, OS Protocols, Talents, Brands, and Skill
|
||
Chips. Attributes are implementation vocabulary resolved into the facts and
|
||
effects shown on those records; do not promote Attributes to a public
|
||
top-level category.
|
||
|
||
Each index category is a fully interactive square registry card with its full
|
||
player-facing category name as the first and strongest element. Record count
|
||
and availability are supporting metadata in the footer; operational states
|
||
such as “active registry” or “intake” must never compete with the category
|
||
identity. Use the larger display-weight category name with a short orange
|
||
identity rail; render any adjacent count in muted telemetry styling. Cards
|
||
retain a concise scope statement, visible hover/focus state, and pressed
|
||
feedback. A category page uses the shared compact category rail,
|
||
live name search, pagination, and a responsive card grid. Record cards use the
|
||
same hierarchy:
|
||
|
||
- a fixed icon cell and compact identity header;
|
||
- small textual badges for quality, tier, or exceptional state;
|
||
- bordered fact cells for primary values;
|
||
- relationship lines and tier descriptions only when applicable.
|
||
|
||
When a record represents an ordered progression rather than independent facts,
|
||
use the stacked fact treatment. Brand Set bonuses are shown vertically in
|
||
two-, three-, then four-piece order; do not add a redundant “3/3 bonuses”
|
||
badge when all three rows are already visible.
|
||
|
||
Weapon cards also use stacked facts. Their level-50 Damage range is the primary
|
||
fact: a taller orange-railed row with enlarged values and the Damage Type in
|
||
the label. Public damage is calculated from the stored level-1 endpoints using
|
||
the same `weaponBaseRange` curve as the builder; never label the configured
|
||
base endpoints as level-50 values. Weapon Talent 1 and Talent 2 pools use
|
||
separate clickable icon rails and the standard Talent quick view.
|
||
|
||
Record cards may end with contextual actions that connect related public
|
||
registries. Actions use the compact orange tactical-button treatment and
|
||
encode their destination filter in the URL. Brand cards provide a “find Gear”
|
||
action that opens the Gear registry with that Brand selected; the same action
|
||
must remain available in Brand quick views.
|
||
|
||
Cards display canonical active data only. Attribute references must be
|
||
resolved to readable names, values, and units instead of exposing IDs or raw
|
||
JSON. Missing uploaded art uses the standard missing-item placeholder.
|
||
Desktop layouts use three record columns, intermediate layouts use two, and
|
||
narrow layouts use one. The eight-category rail reduces from eight to four to
|
||
two columns. Preserve keyboard focus, pressed feedback, reduced-motion
|
||
behavior, and readable textual state in every layout.
|
||
|
||
Category-specific discovery uses the shared `DatabaseDiscoveryConsole`. It
|
||
joins the tactical filter matrix, live registry search, result range,
|
||
pagination, and page-size controls inside one connected instrument; do not
|
||
stack separate bordered filter and pagination bars. Categories without facets
|
||
retain the same console with search and pagination alone.
|
||
|
||
The matrix is a disclosure inside that console. It starts expanded on desktop
|
||
and collapsed on viewports at or below 700px when no filters are active. Active
|
||
filters make the initial state expanded. Its header always exposes the active
|
||
filter count and an explicit `SHOW FILTERS` or `HIDE FILTERS` action, while
|
||
search and pagination remain visible when the matrix is closed. Preserve the
|
||
user's manual disclosure choice in session storage rather than carrying it
|
||
between unrelated browser sessions.
|
||
|
||
Filters apply immediately, remain encoded in the URL, reset pagination, and
|
||
compose with name search. Multiple selections inside one facet are inclusive (`OR`);
|
||
active facet groups combine restrictively (`AND`). For example, selecting two
|
||
Brands and four Talents returns Gear matching any selected Brand and any
|
||
selected Talent. Never implement multi-select facets as an implicit match-all
|
||
within the same group.
|
||
|
||
Use segmented icon choices for bounded visual vocabularies of six or fewer,
|
||
such as Gear slots. Use the matching searchable multi-select list for growing
|
||
sets such as Brands and Talents. Always expose selected counts, a single clear
|
||
action, `aria-pressed` state, keyboard focus, and explicit text explaining the
|
||
combination rule. At intermediate width, the bounded facet spans the row above
|
||
two searchable facets; on narrow screens all facet groups stack vertically.
|
||
Weapon discovery applies this pattern to weapon-family icons, damage-type
|
||
icons, and the searchable pool of compatible Talents. Talent facet rows show
|
||
the rendered Tier I description beneath the name. Talent searches match both
|
||
fields case-insensitively so mechanical phrases can discover talents even when
|
||
the talent name is unknown. Brand facets similarly index the names of all
|
||
set-bonus Attributes, allowing players to search by the desired mechanic
|
||
without exposing that metadata as extra visual clutter.
|
||
|
||
Public database command headers are content-sized and must explicitly override
|
||
the global 76-pixel site-header rule. Their eyebrow, title, description, count,
|
||
and index action remain inside the bordered command surface at every scale.
|
||
Children use `min-width: 0`, long titles may wrap, and category navigation
|
||
tracks use zero-minimum grid columns so translated or enlarged text cannot
|
||
force horizontal page overflow.
|
||
|
||
### Build persistence and sharing
|
||
|
||
The builder distinguishes device persistence from account persistence. `SAVE
|
||
LOCALLY` writes a working draft to the current browser. Signed-in agents also
|
||
receive one account-save action paired with an explicit visibility selector:
|
||
|
||
- `PRIVATE` is owner-only.
|
||
- `UNLISTED` is accessible by direct link but excluded from discovery.
|
||
- `PUBLIC` is accessible by direct link and included in the public archive.
|
||
|
||
Keep visibility adjacent to the account-save action and explain its selected
|
||
state in plain language. Show a share-page action only after a non-private
|
||
build has been saved. Public and unlisted build pages are read-only tactical
|
||
summaries; owner editing returns to the builder. On narrow layouts,
|
||
persistence controls and shared-loadout columns stack vertically.
|
||
|
||
### Tiered compatibility editors
|
||
|
||
When compatibility depends on two independent dimensions, keep those
|
||
dimensions explicit rather than presenting a flattened list. Weapon
|
||
definitions configure their available Weapon Mod slots per tier. T0 requires
|
||
four distinct slots; T1 and T2 require five. Weapon Mod definitions then
|
||
configure one slot plus one or more compatible weapon categories. The UI and
|
||
validation must require both dimensions to match.
|
||
|
||
Weapon Mod definitions use the shared segmented-choice control for the bounded
|
||
eight-slot vocabulary, with a full-width row on desktop and two columns on
|
||
narrow screens. Weapon category compatibility uses the same control in
|
||
checkbox mode with weapon icons and retained accessible names. Show configured
|
||
versus required slot counts in text. Disabled tiers remain visibly unavailable
|
||
and must not submit slot assignments.
|
||
|
||
Quality-scaled registry editors use a compact matrix when the same numeric
|
||
shape repeats across all four quality levels. Apply global quality colors only
|
||
to the quality labels, retain textual quality names, and keep numeric fields
|
||
neutral. On narrow screens the matrix may scroll horizontally while its
|
||
surrounding editor and previews stack.
|
||
|
||
When two item slots draw from the same canonical option pool, edit that pool
|
||
once rather than rendering two duplicated selectors. Weapon Mods use a
|
||
repeatable secondary-attribute row: one searchable attribute reference plus
|
||
four quality range pairs. Show that the builder selects two distinct options
|
||
from the pool. Primary core type is likewise builder-selected and is displayed
|
||
as the three always-available core icons rather than a persisted ISAC choice.
|
||
|
||
Exotic Weapon Mod status is a separate single-icon toggle using the exotic
|
||
icon and the standard pressed, focus-visible, and selected states. Selecting
|
||
it must switch the editor immediately, before a weapon is assigned. Exotic is
|
||
its own unique quality: reveal only the required exotic-weapon assignment,
|
||
remove weapon-category and regular-quality controls, and replace random ranges
|
||
with fixed level-1 and level-20 attribute values. Keep an explicit Exotic
|
||
Quality state panel visible so the change in data semantics is unmistakable.
|
||
|
||
### Gear Mod registry
|
||
|
||
Gear Mods reuse the compact quality matrix, level preview, and pooled
|
||
secondary-attribute rows established by Weapon Mods. Do not render exotic,
|
||
weapon-category, slot-type, or Mod Effect controls in this simpler editor.
|
||
Present the five primary options as an always-visible informational band
|
||
because the actual primary is selected on the build instance, not persisted on
|
||
the canonical definition.
|
||
|
||
Use explicit textual tier capacity wherever Gear tier is summarized: `1 MOD
|
||
SLOT` for T0 and `2 MOD SLOTS` for T1/T2. On narrow screens the identity band
|
||
and preview controls stack, while repeated quality data may scroll rather than
|
||
compressing numeric controls below usable sizes.
|
||
|
||
### Deferred game-data icons
|
||
|
||
Game-data icons are optional enrichment, never a blocker for creating or
|
||
proposing a canonical item. Upload fields must state that an icon may be
|
||
contributed later and show the shared `/missing-item-icon.svg` artwork when no
|
||
upload exists. Registries, relationship rails, and builder selection controls
|
||
use the same placeholder instead of initials, empty boxes, or ad hoc glyphs.
|
||
Application code references that asset through the shared
|
||
`MISSING_ITEM_ICON_URL` constant and renders it through `ItemIcon`; do not
|
||
duplicate its path or introduce module-specific missing-icon artwork.
|
||
|
||
Treat the placeholder as an explicit incomplete-data state: keep its subdued
|
||
SHD styling and useful alternative text where the surrounding item name is not
|
||
already available. Do not persist placeholder metadata or copy the placeholder
|
||
into per-item storage. A later contributor replaces it through the normal icon
|
||
upload proposal, preserving the canonical record and audit history. The upload
|
||
itself retains all transparent-format, size, SVG-safety, focus, drag/drop, and
|
||
paste validation requirements.
|
||
|
||
### Public database performance facts
|
||
|
||
Use the shared `DatabaseFacts` renderer for registry-card performance data and
|
||
quick views. Weapon identity headers keep the native tier beside the category
|
||
identity as a compact textual `T0`, `T1`, or `T2` marker. Place tier and the
|
||
smaller damage-type icon in a dedicated top-right status cluster; do not
|
||
interrupt the readable `category // damage type` metadata with icons. Reserve
|
||
the emphasized first fact for the weapon's damage range, pair it with the
|
||
canonical damage-type icon, and render the calculated level as a subdued
|
||
annotation rather than part of the primary label. Public level-50 damage must
|
||
be calculated from the stored level-1 endpoints with `weaponBaseRange`; never
|
||
relabel raw source values.
|
||
|
||
Represent bounded handling values such as Accuracy and Stability with compact
|
||
horizontal meters. Always retain the numeric value and an accessible
|
||
`value out of 100` label so the graphic does not carry meaning alone. Use the
|
||
stable sequence `label → meter → exact value`, with the exact number aligned in
|
||
a dedicated column to the right of the graphic. Clamp display values to
|
||
`0–100`, use orange only for the filled measure, and keep the unfilled track
|
||
neutral. Stack meter labels and tracks on narrow cards rather than shrinking
|
||
them below a reliably readable width.
|
||
|
||
Talent registry cards treat the two tier descriptions as their primary
|
||
content; never replace them with configured/missing summary facts. Render Tier
|
||
I and Tier II as distinct structured data blocks, then place optional cooldown
|
||
metadata below both descriptions. Do not use the serif, quote-like prose
|
||
treatment for tier effects. Use compact fixed tier labels, sans-serif effect
|
||
text, and engineered borders. Tier I is the neutral baseline; Tier II uses the
|
||
orange rail, label, and subtly elevated surface to communicate that it is the
|
||
improved version. Duration and stack limits may remain compact badges. The
|
||
top-right header status uses the applicable Backpack or Body Armor icon for
|
||
gear talents and the SMG icon as the generic Weapon Talent symbol. Weapon
|
||
Talent headers pair that icon with an explicit `1 · TOP` or `2 · BOTTOM`
|
||
status badge; never rely on the slot number alone.
|
||
|
||
When a public registry needs only one small bounded filter vocabulary, use the
|
||
compact facet-panel form: one full-width group with all options visible in a
|
||
single row on wide screens. Talent slot filtering uses Backpack, Body Armor,
|
||
Weapon 1 · Top, and Weapon 2 · Bottom. Always include the Top/Bottom context
|
||
when presenting numbered Weapon Talent slots to users. The filter remains
|
||
additive within the group and wraps to two columns on narrow screens; do not
|
||
introduce search or dropdown controls for this four-option set.
|
||
|
||
Notification delivery preferences are a temporary profile control surface.
|
||
After a successful save, close the interface and return focus to the inbox
|
||
context. Consume a unique server result token only once so later actions or
|
||
reopening the panel do not close it again. Validation and server errors keep
|
||
the interface open with the submitted controls available for correction.
|
||
|
||
### Global toast feedback
|
||
|
||
Use the root-mounted `ToastViewport` and the shared API in `src/lib/toast.ts`
|
||
for transient action feedback. Enhanced server mutations should normally use
|
||
`PendingForm`, which derives success and failure feedback from the action
|
||
result. Client-only operations call `toast.success`, `toast.error`,
|
||
`toast.warning`, or `toast.info` directly. Do not create page-specific toast
|
||
implementations.
|
||
|
||
Toasts occupy the top-right safe area below the global header and show no more
|
||
than four messages. Each uses a textual state label, tone-colored top and left
|
||
rails, a concise title, optional supporting text, and an explicit dismiss
|
||
control. Success is green, errors use danger red, warnings use SHD orange, and
|
||
informational feedback uses restrained blue-gray. Color never carries state
|
||
alone.
|
||
|
||
Use success to confirm completed mutations, error for failed requests, warning
|
||
when attention is required, and info for neutral client or system state. Keep
|
||
inline validation beside affected fields even when an error toast is also
|
||
emitted. Avoid toasts for passive navigation, filtering, hover, unpersisted
|
||
selection changes, and background refreshes. Toasts automatically dismiss
|
||
according to severity, remain keyboard dismissible, use `status` or `alert`
|
||
semantics, and disable entrance motion with reduced motion. On mobile they span
|
||
the safe viewport width below the header without obscuring navigation.
|
||
|
||
### ISAC progressive disclosure
|
||
|
||
The ISAC rail shows every module the current operator is authorized to access,
|
||
but groups modules behind collapsible operational categories. The category
|
||
containing the current route opens on first use; subsequent open and closed
|
||
choices are remembered locally for that browser. Searching the rail temporarily
|
||
reveals matching modules across all authorized categories without changing the
|
||
remembered category state.
|
||
|
||
Use the compact command-status strip for persistent system, access, ISAC node,
|
||
and CI build number context. Add the data-mode cell only in the Data Management
|
||
context defined above. Keep each label above its value so the visible cells
|
||
share one alignment. Text must communicate every state without relying on
|
||
color. Registry search remains available for a single page of results, while
|
||
page navigation and row-count controls appear only when the result set spans
|
||
multiple pages. This keeps expert lookup fast without presenting inactive
|
||
controls to contributors and first-time Oversight operators.
|
||
|
||
Sidebar category headers are real buttons with `aria-expanded` and controlled
|
||
navigation regions. Search fields have visible or accessible labels, keyboard
|
||
focus uses Signal Orange, and collapsed state must remain understandable
|
||
without motion.
|
||
|
||
### Managed image library
|
||
|
||
Reusable uploaded visuals belong in the ISAC Image Library under System
|
||
Configuration. Present assets as a dense responsive registry of preview cards:
|
||
the artwork is primary, while name, assignment category, tags, dimensions, and
|
||
file size remain compact operational metadata. A checkerboard preview surface
|
||
may make transparency legible without changing the asset.
|
||
|
||
Image intake uses the shared picker, drop-zone, and clipboard control. The
|
||
`Normalize as icon` option trims transparent outer margins and standardizes the
|
||
canvas. When the source has no usable transparency, the server requests
|
||
preview-resolution background removal before local normalization and reports
|
||
configuration, credit, rate-limit, foreground-detection, or network failures
|
||
with a specific recovery. Its dependent `Force white` option converts visible pixels to the
|
||
canonical neutral icon color while preserving alpha. Both controls state their
|
||
processing consequence in text, expose checked and disabled states, and remain
|
||
keyboard accessible. Metadata edits preserve the stable asset identity, close
|
||
after a successful save, and use the shared toast and editor lifecycle.
|
||
|
||
Use controlled assignment categories for broad placement and free-form,
|
||
normalized tags for discovery. Names are unique and human-readable. Search
|
||
covers names, categories, and tags. On narrow screens, processing controls
|
||
stack vertically and cards reduce to one column so previews and actions retain
|
||
usable sizes.
|
||
|
||
### ISAC mutation consequence
|
||
|
||
Every writable game-data module states what Save will do before the operator
|
||
opens an editor, and the statement remains visible while the editor is open.
|
||
The message is derived from effective permissions rather than copied into each
|
||
module:
|
||
|
||
- `OVERSIGHT REVIEW` means saving creates a proposal and does not change live
|
||
data until Oversight approves it.
|
||
- `DIRECT PUBLISH` means the change becomes live immediately and creates an
|
||
append-only audit event.
|
||
|
||
Pair the short state label with a complete consequence sentence. Contributors
|
||
must not have to infer this behavior from their role name, data-mode color, or a
|
||
success message shown after saving. Read-only operators do not see a mutation
|
||
statement because their mutation controls are absent. At narrow widths the
|
||
message becomes its own compact row above the module toolbar. A toolbar with
|
||
multiple actions must reserve the complete action group width in the inline
|
||
desktop strip so the consequence sentence never runs beneath a button.
|
||
|
||
### Public database index
|
||
|
||
The public Database is a lookup surface first and a contribution gateway
|
||
second. Use a compact angular command band rather than a cinematic display
|
||
hero: keep the archive identity, state how many registries are online, state the
|
||
record total, and present contribution as a bordered secondary action.
|
||
|
||
Place one discovery bar below the command band. Its label gives users two equal
|
||
paths: select a registry or search all data. Its search field searches across
|
||
all public registry names and useful
|
||
descriptive data such as Talent text, Damage Types, item slots, qualities, and
|
||
Brand bonus Attributes. Do not stack a separate registry-heading bar above or
|
||
below it. Results name both the matching record and its registry, then link into
|
||
that registry with the record name applied as its local search. Keep the search
|
||
and results dense, keyboard accessible, responsive, and URL-addressable.
|
||
|
||
Registry selection begins immediately after the shared discovery bar. Do not
|
||
place stewardship, status, promotional, or redundant instructional panels
|
||
between it and the registry grid. At wide desktop widths, eight registries form a
|
||
four-by-two matrix; the grid reduces to two columns and then one as available
|
||
space narrows. Registry cards lead with complete category names. Counts and
|
||
availability remain quiet footer metadata, and internal abbreviations or
|
||
workflow-centric states are not exposed as primary public labels.
|
||
|
||
### ISAC progression-tree composer
|
||
|
||
Use the Specialization workbench pattern for ordered game systems that depend
|
||
on hierarchy and spatial placement. Keep the registry, selected parent identity,
|
||
child navigation, readiness telemetry, and visual tree in one operational
|
||
surface. Editors open above the registry and follow the standard ISAC lifecycle.
|
||
Use the workbench for navigation and context.
|
||
|
||
The tree uses a stable 12-column track per row. Row and column are explicit
|
||
numeric fields so placement is keyboard operable, auditable, and portable;
|
||
never make drag-and-drop the only authoring method. On narrow screens, retain
|
||
the geometry in a horizontally scrollable canvas instead of squeezing nodes
|
||
until their names and state are unreadable. Controls outside the canvas stack
|
||
and maintain at least a 44-pixel touch target.
|
||
|
||
Each row header states its derived gate in plain language. Specialization gates
|
||
count all available Rank 1 and Rank 2 unlocks in preceding rows, including the
|
||
two immediately available ability nodes displayed in the first row. Do not
|
||
store or manually edit a second gate value that could diverge. Free nodes use
|
||
the orange identity rail plus the explicit `1 / 1 · FREE` state; pending,
|
||
archived, incomplete, and builder-ready states must remain textual as well as
|
||
colored.
|
||
|
||
Show allocation scope as first-class telemetry. A specialization unlocks once;
|
||
each focus receives its own full point allocation. Show the point total and
|
||
scope near the tree. A focus becomes builder-ready after it has three distinct
|
||
active abilities, each ability has exactly three active Skill Chip definitions,
|
||
tree rows are contiguous, at least one paid node exists, and the tree uses the
|
||
configured available point total.
|
||
|
||
Compose focus identity from uploaded specialization artwork and the canonical
|
||
Firepower, Toughness, or Engineering icon. Keep the specialization art primary
|
||
and place the attribute mark in a smaller corner badge. Mirror ability slots 1
|
||
and 3 as free tree nodes. Label slot 2 Combat Skills-only and exclude it from
|
||
the upgrade tree. Universal grenade and medical-kit actions are outside the
|
||
specialization ability set.
|
||
|
||
Use `StructuredEffectEditor` whenever an ISAC record needs an ordered set of
|
||
calculation-ready effects. It provides Attribute, Ability when applicable, and
|
||
Custom targets; a numeric value; and the shared bounded unit vocabulary. Keep
|
||
the target searchable, show all bounded type and unit choices with segmented
|
||
controls, and preserve explicit custom labels for mechanics that calculations
|
||
do not yet support. Oversight previews must render effect and rank summaries as
|
||
structured cards. Serialized JSON belongs only in the expandable raw-evidence
|
||
panel.
|
||
|
||
Exclusive child-record relationships use a searchable assignment block directly
|
||
after the record identity. The header names the parent type, states the
|
||
relationship and capacity in plain language, and shows current usage as `N / N`.
|
||
The registry repeats the assigned parent beside each child so exclusivity can be
|
||
audited without opening the editor. Records that require an exclusive parent
|
||
must always have a valid active assignment. Capacity rules are enforced on the
|
||
server and never communicated by color alone.
|
||
|
||
Rank cards present the complete rank description, structured effects, point
|
||
cost, Credits, and material cost together. Specialized Alpha, Beta, and Gamma
|
||
components use the shared blue quality treatment and may be combined in any
|
||
positive whole-number quantities for Rank 2. Rank 3 uses the yellow High-end
|
||
Omega treatment and exactly one component. Color is supporting hierarchy;
|
||
quality names and quantities always remain visible.
|
||
|
||
### Conditional combat modeling
|
||
|
||
ISAC authors define a combat effect once per Specialization and attach it to
|
||
one or more tree-node ranks. Each rank attachment owns its hit trigger, stack
|
||
duration, stack limit, and Attribute modifiers. Keep the lifecycle rules in a
|
||
compact fact rail: trigger counters reset after a proc, each stack gain refreshes
|
||
the timer, and expiry clears the complete stack. The shared definition provides
|
||
one effect name and description to every attached rank.
|
||
|
||
Use `--shd-model-surface` and `--shd-model-border` for conditional mechanics,
|
||
calculation revisions, and field calibration. The blue information rail marks
|
||
modeled behavior. Orange remains reserved for selection and activation. Every
|
||
effect card names its trigger, duration, maximum stacks, and value per stack in
|
||
text so the mechanic remains clear without color.
|
||
|
||
The loadout builder gives each unlocked conditional effect three calculation
|
||
modes:
|
||
|
||
- `OFF` excludes the effect.
|
||
- `PEAK` applies its configured maximum stacks.
|
||
- `ENCOUNTER` models stack buildup and expiry from weapon RPM, magazine size,
|
||
reload time, hit rate, firing activity, and encounter duration.
|
||
|
||
Users may override encounter assumptions on one effect without changing the
|
||
global combat profile. The effect card shows the applied stack state beside the
|
||
mode. On mobile, assumption fields and effect controls stack into full-width
|
||
44-pixel targets.
|
||
|
||
Combat result panels show normal, critical, headshot, and critical-headshot
|
||
values with burst, sustained, and encounter DPS. Conditional stack telemetry
|
||
lists the mode, average and peak stacks, ending stacks, buildup time, and
|
||
maintained state that produced the result. A result with missing equipment,
|
||
Attribute bindings, rules, or assumptions displays `INSUFFICIENT DATA` and a
|
||
concrete remediation list. The interface withholds combat numbers until it has
|
||
the required inputs.
|
||
|
||
### Specialization loadout composer
|
||
|
||
The builder places Specialization focus selection after equipment
|
||
configuration. The focus identity combines Specialization artwork and the
|
||
primary Attribute mark, followed by three ability panels. Each ability panel
|
||
contains three fixed Skill Chip positions. A chip picker shows definitions
|
||
assigned to that ability and excludes definitions assigned elsewhere.
|
||
|
||
The focus tree groups nodes by row and uses segmented rank controls. Disabled
|
||
ranks remain visible with their lock state. The builder permits a row after the
|
||
user buys every available Rank 1 and Rank 2 in preceding rows and enforces the
|
||
49-point limit. Cost telemetry lists Credits and components beside each rank.
|
||
|
||
Saved loadouts store focus, node ranks, nine Skill Chips, effect modes, and
|
||
combat assumptions. The builder accepts only the current complete structure.
|
||
Invalid local drafts are discarded; invalid server records are unavailable and
|
||
removed through a backed-up database migration.
|
||
|
||
### Calculation revision controls
|
||
|
||
Combat rules use immutable active and retired revisions. ISAC editors may
|
||
change draft revisions, ordered stages, and Attribute profiles. Activation
|
||
requires `calculation.publish`, an explicit review state, and a confirmation
|
||
that saved builds will recalculate. Successful activation closes the
|
||
confirmation surface and records the revision in the audit history.
|
||
|
||
Calibration cases pair a loadout snapshot with measured hit and timing values.
|
||
Ready cases require the four hit values, magazine time, and reload time.
|
||
Assisted suggestions create a draft revision for review and leave activation
|
||
to an authorized operator. Use monospaced text for raw loadout and prediction
|
||
snapshots; labels, findings, and errors stay in the standard operational
|
||
typeface.
|
||
|
||
### Image Library assignment state
|
||
|
||
An ISAC game-data editor registers each uploaded icon in the Image Library. The
|
||
library record and editor share one processed file. Its card uses `ASSIGNED
|
||
ICON`, names the owning entity type beside the category, and carries searchable
|
||
tags for `isac`, `game data`, the module, the entity name, and entity context
|
||
such as quality, focus, ability, or Talent category.
|
||
|
||
Operators may rename, recategorize, and add tags to the library record. Replacing
|
||
the icon from its game-data editor keeps that metadata and refreshes the context
|
||
tags and file facts. Removing the source icon removes its linked library record.
|
||
General library uploads retain the `ICON` or `IMAGE` state.
|