2522 lines
150 KiB
Markdown
2522 lines
150 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.
|
||
|
||
### Command Grid builder
|
||
|
||
The production builder uses Command Grid as its loadout workbench. Keep the
|
||
entire build visible in a dense matrix while one connected editor configures
|
||
the selected cell. The full-width Specialization and Focus cell is the root
|
||
choice. Its three supplied abilities appear directly below it, followed by two
|
||
weapons, six gear positions, and one full-width OS Protocol.
|
||
|
||
Matrix cells summarize selected Talent names, Attribute names and values,
|
||
Brand Sets, or Skill Chips. Do not replace those choices with configuration
|
||
counts. Selecting an ability opens its three attached Skill Chip positions.
|
||
Selecting equipment opens the searchable real-data catalog and its compatible
|
||
configuration controls. Do not display a prototype option that the current
|
||
loadout schema cannot save.
|
||
|
||
Calculation readiness belongs at the point of resolution. Mark an incomplete
|
||
matrix cell with a compact red text indicator and status rail, then let the
|
||
cell open the editor that resolves it. The live calculation rail summarizes
|
||
blocked output in one compact row. Do not repeat every missing slot in a large
|
||
error panel. Keep system-owned blockers, such as an unpublished calculation
|
||
profile, visible in that compact summary because the player cannot resolve
|
||
them from a loadout cell.
|
||
|
||
The builder uses three workbench columns on wide screens, moves the live
|
||
summary below the matrix and editor at intermediate widths, and stacks all
|
||
three regions on narrow screens. Every grid track and editor child must accept
|
||
content shrinkage. At 560px and below, stack attribute picker/value pairs and
|
||
section headings; keep the command actions in two equal columns. Validation
|
||
markers use short visible labels while their full messages remain available
|
||
to assistive technology and pointer users.
|
||
|
||
Use `--shd-builder-canvas` for recessed equipment fields. Use
|
||
`--shd-builder-selection` with `--shd-builder-selection-border` for the
|
||
selected cell. Preserve button semantics, `aria-pressed`, focus-visible
|
||
outlines, pressed feedback, and textual readiness states. At narrower desktop
|
||
widths, keep the matrix and editor together and move live results below them.
|
||
On mobile, stack the matrix, editor, and live results in that order.
|
||
|
||
The command header contains the required build name, local and account save
|
||
actions, account visibility, and optional sharing notes. Sharing notes include
|
||
a short strengths summary and a Markdown usage guide. Persist them separately
|
||
from the validated loadout payload and render them on the shared build page.
|
||
|
||
### 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 collapsible command panels for Launch Gate, Account
|
||
Creation, Public Sections, moderation policy groups, thresholds, and the term
|
||
registry. Build these panels with `CollapsibleSection`. The disclosure button
|
||
must expose `aria-expanded` and `aria-controls`, retain its title and textual
|
||
status while closed, show a focus-visible outline, and provide at least a
|
||
44-pixel touch target. Keep panel content in the document and hide it while
|
||
closed so draft form state survives expansion changes. Disable motion under
|
||
`prefers-reduced-motion`.
|
||
|
||
Each command panel owns its save action, validation feedback, pending state,
|
||
and success notice. Do not place a page-wide review or save banner between
|
||
panels. Disable a panel's save button until that panel differs from saved
|
||
state. Saving one panel must update only its fields, retain the panel's open
|
||
state, and leave unsaved drafts in other panels unchanged. Keep `PREVIEW PAGE`
|
||
inside the Launch Gate save row 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
|
||
|
||
- The canonical signed-in account surface is the owner’s public Agent profile at
|
||
`/agents/{slug}`. `/account` is a compatibility route that redirects there;
|
||
the full notification inbox remains at `/account/notifications`.
|
||
- Owners see the same dossier and conversation that visitors see, plus inline
|
||
bio editing and a compact Account Control widget in the right rail. Do not
|
||
create a separate profile-editing dashboard or remove community context while
|
||
the owner manages their profile.
|
||
- 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 one column. Show the public dossier
|
||
and archives first, followed by Account Control, notifications, and Recent
|
||
Discussion. Place Profile Messages at the bottom. Give owners a mobile-only
|
||
header link to Account Control.
|
||
- Public display names and private login usernames are distinct. Display names
|
||
support normalized Unicode and relaxed visible characters. They are unique
|
||
under the product's normalized identity key and generate readable,
|
||
collision-safe public-profile slugs. New accounts receive the next available
|
||
`Agent N` placeholder until the owner chooses a name. Login usernames remain
|
||
unique, ASCII-only credentials and must never appear on public-facing
|
||
community surfaces. Authorized ISAC user operations may show both.
|
||
|
||
### Public Agent profiles
|
||
|
||
Public Agent profiles are community dossiers. The owner view extends the same
|
||
page with account controls without changing its public hierarchy. Lead with the
|
||
shared `AgentIdentityLink` in its large state: circular portrait, display name,
|
||
and assigned role badges. Place role badges to the right of the display name on
|
||
desktop and below the name on mobile. Show role names only, in alphabetical
|
||
order, and omit the list when the Agent has no assigned roles. Badges use the
|
||
shared raised surface, explicit role text, and a small orange
|
||
diamond; they wrap without truncating long or multiple role names. Never expose
|
||
role descriptions, permissions, direct grants, or access scopes on public
|
||
profiles. The owner header contains the visibility switch, its information
|
||
control, and a mobile-only Account Control link. Present the primary identity
|
||
and its actions directly on the page canvas
|
||
without a card surface, border, or decorative accent rule. Give the identity and
|
||
actions content-sized responsive tracks so long names, multiple roles, and
|
||
mobile actions cannot overlap the public content totals. Keep those totals in a
|
||
compact telemetry strip below the identity header. Use four columns on desktop
|
||
and two columns on mobile. Place the field bio in the primary column and keep
|
||
its mobile Edit Bio action compact within the section header. Put Public Builds
|
||
and Published Guides side by side directly
|
||
beneath the bio; stack them on narrow screens. Their cards stay within their own
|
||
half of the primary column. Profile Messages follow the archive pair within the
|
||
same column and must not inherit height from the right rail.
|
||
|
||
Recent Discussion occupies the narrower activity rail. Owner-only Account
|
||
Control and notification-preview widgets appear above it. The profile preview
|
||
shows unread notifications only; the full inbox retains notification history.
|
||
Recent-discussion
|
||
entries use compact destination cards because each entry links to content
|
||
elsewhere on the site. Show only the discussion type, destination title, comment
|
||
date, and open action; do not repeat the message body in this rail. Reset nested
|
||
card headers to content height and align the destination identity with its date;
|
||
do not inherit the application header's fixed height or surface treatment.
|
||
Profile messages continue directly
|
||
beneath the biography in the primary column so the conversation begins without
|
||
dead space.
|
||
|
||
Use `AgentIdentityLink` for author attribution on builds, guides, comments, and
|
||
other community records. Its compact and default states combine the circular
|
||
portrait, public display name, assigned public role badges, and optional
|
||
contextual metadata. Role badges remain beside the display name in comment
|
||
headers and other author attributions; an empty role list renders no badge. The
|
||
display name supplies the link affordance through its hover and focus-visible
|
||
states; do not add a trailing arrow. Use the primary orange token for the
|
||
portrait border, with a two-pixel edge that remains legible against the page
|
||
canvas. The default author portrait is 44 pixels; compact identities may use 30
|
||
pixels. The portrait remains circular at every size; selectors may use square
|
||
tactical thumbnails only where the avatar rules explicitly allow them.
|
||
|
||
Public-profile links use the stored readable slug, URL-encoded as one path
|
||
segment. A display-name change updates the canonical slug. Legacy UUID routes
|
||
remain valid and redirect to the canonical address; UUIDs remain the internal
|
||
identity for mutations, relationships, and audit evidence.
|
||
|
||
Public biographies use the shared `MarkdownEditor` and `MarkdownContent` pair.
|
||
The editor supplies formatting controls, a remaining-character count, concise
|
||
help, and a readable editorial typeface. Profile messages and replies use the
|
||
compact `CommentComposer`: one textarea, a Markdown notice, a character count,
|
||
and submit or cancel actions. Rendered Markdown supports headings, lists,
|
||
quotes, links, bold, italics, and inline code. Load the required editorial font
|
||
weights and italic face because the global type system disables synthetic font
|
||
styles. Raw HTML is escaped.
|
||
|
||
Profile conversations begin with a collapsed `LEAVE A MESSAGE` action. A reply
|
||
opens the same editor beneath the selected message, and only one editor remains
|
||
open. Comments sit on the page canvas without cards, section surfaces, or
|
||
detached author headers. Align each body and action row with the username rather
|
||
than the avatar gutter. Keep Reply visible below the message. Place Follow or
|
||
Unfollow, Report, and the author-only Remove action in a shared ellipsis menu
|
||
beside Reply. The menu uses a 44-pixel trigger, returns focus when
|
||
closed, supports Escape and directional-key navigation, and becomes a fixed
|
||
bottom panel on narrow screens. Keep destructive actions neutral at rest and use
|
||
the danger color on hover or keyboard focus. Render conversations
|
||
in depth-first reading order: newest root conversations first and each branch
|
||
oldest-first. Use one-pixel guide lines and restrained indentation for replies,
|
||
then cap visual indentation on narrow screens while retaining the logical
|
||
parent chain. If an author or moderator removes a message that has replies, show
|
||
a bodyless `MESSAGE REMOVED` placeholder so readers can follow the remaining
|
||
conversation. Following applies to the top-level conversation and sends inbox
|
||
notifications for visible descendant replies, excluding the reply author and
|
||
any recipient already receiving the direct-reply notification. Send reply
|
||
notifications to the direct parent author and link to the specific reply.
|
||
Recent-discussion links target the exact comment anchor instead of the
|
||
containing profile or content page.
|
||
|
||
Public user-generated content uses the shared `ContentReport` control when the
|
||
viewer is authenticated and does not own the content. Keep the control visually
|
||
secondary to reading and reply actions. Its disclosure names the concern,
|
||
accepts optional bounded context, and states that a report requests human review
|
||
without removing content immediately. On narrow screens, present the report
|
||
form as a fixed bottom panel with full-width touch controls.
|
||
|
||
Submission forms for public user-generated text and custom images use the
|
||
shared `ModerationDisclosure` notice. Place it after the input and before
|
||
validation or submission controls. The always-visible notice states that
|
||
automated safety review may occur and links to the Terms & Privacy section for
|
||
the details. Do not hide this disclosure in a hover-only tooltip.
|
||
|
||
Automated moderation is exception-based. Clean content publishes without an
|
||
Oversight task when policy permits. Flagged comments remain hidden with an
|
||
explicit pending state; flagged long-form edits leave the last approved version
|
||
public. Flagged custom avatars use the default avatar publicly until approval.
|
||
Community Oversight shows automated evidence and Agent reports in one pending
|
||
queue, but labels their sources separately. Human approval, rejection, removal,
|
||
and report dismissal require a reason and confirmation.
|
||
|
||
The Site Controls term registry supports single-rule editing and an inline bulk
|
||
editor. The bulk editor accepts pasted lists, applies one effect and scope set
|
||
to the batch, previews the unique-entry count, and states the 250-rule limit.
|
||
Keep it inline because operators need the registry for context. Show exact-word
|
||
behavior beside the textarea, preserve pasted values after validation errors,
|
||
and clear the textarea while keeping the editor open after a successful import.
|
||
Search the registry on the server across term text, normalized text, rule type,
|
||
match mode, and operational note. Use the shared pagination rail with
|
||
namespaced URL parameters and 25 rows by default. Search applies before
|
||
pagination. Distinguish an empty registry from a search with no matches. The
|
||
registry toolbar, editors, search, and pagination stay inside the term
|
||
disclosure.
|
||
Only HTTP and HTTPS links are active; rendered links open separately with UGC,
|
||
nofollow, and opener-isolation attributes. `MarkdownContent` must receive HTML
|
||
from the server renderer, never raw user input or client-rendered Markdown.
|
||
|
||
Rendered biography copy uses the editorial typeface and a restrained reading
|
||
measure. Compact comment rendering uses the same hierarchy at a denser scale.
|
||
Comment cards identify the author and date before the message. Activity cards
|
||
identify the content type and title, render a useful excerpt, and provide a
|
||
specific action such as `OPEN DISCUSSION`. Empty states state which public
|
||
record is absent without implying an error.
|
||
|
||
Profile visibility is an explicit public or hidden account setting. A hidden
|
||
profile is excluded from public discovery and cannot receive new profile
|
||
messages. Hiding it does not remove the Agent's display name or portrait from
|
||
public builds, guides, or comments they authored. Put the compact textual
|
||
`PUBLIC` or `HIDDEN` switch in the owner’s identity header and explain the
|
||
consequence in an adjacent information popover. Display-name restrictions use
|
||
the same popover pattern instead of persistent instructional copy.
|
||
|
||
Community forms use `PendingForm` to block duplicate submissions. Pending
|
||
actions retain their label context, validation errors preserve entered text,
|
||
and success or error feedback appears beside the affected form. All editor,
|
||
link, and button controls require the shared orange focus-visible treatment.
|
||
Message removal is a two-step, in-card confirmation: the first action reveals a
|
||
red danger panel, then separate Cancel and Confirm Remove actions complete or
|
||
abandon the request. Only an authorized author receives the removal control.
|
||
|
||
Below 1000px, move profile communications beneath the primary content and stop
|
||
using the sticky position. Below 650px, stack the identity header, telemetry,
|
||
section headers, and content cards into one column. Expand owner actions,
|
||
submission controls, and deletion controls to 44px touch targets. Keep the
|
||
Cancel and Confirm Remove actions side by side when both labels fit. Respect
|
||
`prefers-reduced-motion` without removing static hover, focus, pending, success,
|
||
error, or danger indicators.
|
||
|
||
### 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
|
||
core Admin role is deletion-protected because it provides the system's
|
||
unrestricted access mechanism. Full administrators may edit every role and
|
||
delete seeded operational roles; deletion records a persistent tombstone so
|
||
migrations do not recreate the role. Delegated access managers may edit
|
||
seeded operational roles but may delete only custom roles. Every deletion
|
||
requires an exact-name confirmation that states how many agents will
|
||
immediately lose the role. Keep Delete separated from Edit and use the danger
|
||
treatment only inside this confirmed path.
|
||
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 and assignment evidence.
|
||
- 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.
|
||
- Server validation returns errors for specific editor areas. Show a focused
|
||
error summary with links to each affected area, mark invalid native controls
|
||
with `aria-invalid`, and place the error text beside the relevant field or
|
||
section. Preserve all entered values. Color supports the text and border
|
||
treatment; it never carries the error state alone.
|
||
|
||
## 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. Account Control shows the current portrait first and
|
||
keeps preset and upload controls behind an explicit Edit Avatar action. 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, 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. 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 authored in the Talent Registry under the `Exotic Weapon`
|
||
category. The weapon editor uses the shared searchable assignment pattern to
|
||
reference one registered exotic talent. Each option states whether another
|
||
weapon owns it and whether contributors have documented Tier II. Assigned
|
||
talents remain visible but unavailable to other weapon records. The selected
|
||
talent stays removable from its current weapon.
|
||
|
||
The Talent Registry owns the exotic talent name, icon, description template,
|
||
Tier previews, and mechanic program. Its explicit Tier II documentation choice
|
||
uses `DOCUMENTED` and `NOT YET DOCUMENTED`. Tier I remains required in both
|
||
states. The registry shows `NOT YET DOCUMENTED` in the Tier II column instead
|
||
of a zero value or synthesized description.
|
||
|
||
Place shared weapon-category bonuses above the weapon registry in one collapsed
|
||
profile console. Its six category buttons show the three inherited Attribute
|
||
values and open one category editor. The editor keeps Attribute identities
|
||
fixed and exposes only their positive numeric values. Saving closes the editor;
|
||
validation preserves its values and error state. Standard and Exotic weapons
|
||
inherit the profile for their underlying Shotgun, Rifle, MMR, AR, LMG, or SMG
|
||
category. Do not repeat these controls inside individual weapon editors.
|
||
|
||
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.
|
||
|
||
### Weapon and gear renders
|
||
|
||
Weapon and gear editors offer an optional item-render upload separate from the
|
||
icon system. Operators may save a definition without artwork, then add, replace,
|
||
or remove the render in a later edit. The upload accepts JPEG, PNG, WebP, and
|
||
AVIF up to 5 MiB. The server center-crops each upload to 1000 × 1000 and stores
|
||
it as WebP. It does not call remove.bg, trim the scene, or add transparency.
|
||
|
||
Show the current square render in the upload control and as a compact square
|
||
thumbnail before the item name in ISAC registry rows. Keep the image decorative
|
||
when the adjacent text identifies the item. The control states the crop and
|
||
format contract so contributors do not confuse a render with a transparent
|
||
game-data icon.
|
||
|
||
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 mechanic programs and reuse the global Attribute
|
||
registry. 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. Author
|
||
cooldowns on event branches, durations and maximum stacks on state pools, and
|
||
tier values on outcomes through `MechanicProgramEditor`. Description templates
|
||
use numbered expressions (`{1}`, `{2}`) for ordered outcomes and named
|
||
expressions (`{duration}`, `{max_stacks}`) for defined pool mechanics. Named
|
||
expressions are valid only when their corresponding value exists. 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; omit the cooldown line when no
|
||
branch defines one.
|
||
|
||
### 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 and never only 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. Dimming or disabling
|
||
those controls is insufficient. 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, event, 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.
|
||
|
||
Records with established visual identity may supply an optional square icon.
|
||
Standard assignment lists show it at 32 pixels in result rows and 24 pixels in
|
||
selected chips. An icon-first multiselect may use the `visual-grid` presentation
|
||
for a finite visual registry. Its compact tiles use a 38-pixel icon without
|
||
persistent tile text. Hover and keyboard focus reveal the record name, while
|
||
the accessible label includes the name and assignment state. The orange inset
|
||
edge marks selected tiles. Weapon Talent 1 and Talent 2 pools and the Backpack
|
||
and Body Armor talent pools use this grid. Use the shared missing-item artwork
|
||
when a record lacks an icon. Render the full eligible set without a search,
|
||
result-count row, item cap, or internal scroll region; the section header owns
|
||
the selected count. Reflow tiles without changing keyboard order.
|
||
|
||
Use the `toggle-grid` presentation for a small fixed registry whose text labels
|
||
are the primary recognition aid. Each 44-pixel-or-taller option uses checkbox
|
||
semantics and shows only the record name. The orange action edge marks the
|
||
selected state, and the accessible label includes that state. Weapon mod slot
|
||
selectors use this presentation so an operator can toggle each slot by clicking
|
||
its name. Keep all options visible and preserve DOM order as the grid reflows.
|
||
|
||
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. Conditional mechanics state their calculation
|
||
mode and readiness. Maximum Potential uses their best-case state; Custom
|
||
Scenario uses the source-defined advanced assumptions saved with the loadout.
|
||
Exclude a mechanic that lacks a required assumption and label it `REQUIRES
|
||
ASSUMPTIONS`. This distinction must remain clear without relying on color.
|
||
|
||
Loadout summaries name selected Talents, Attributes and their exact values,
|
||
nodes, and Skill Chips. Do not replace these selections with configured
|
||
item counts. Build identity includes a required name plus optional strengths
|
||
summary and usage guide. Shared build views include those author-written fields
|
||
so another player can understand the build's role and operating sequence.
|
||
|
||
### 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 with the shared
|
||
database card component and the same facts, tier hierarchy, mechanic rows, and
|
||
actions shown in that record's public registry. The overlay traps keyboard
|
||
focus, returns focus to its trigger when closed, and 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 one shared set of five Weapon Mod slots for T1 and T2.
|
||
T0 uses the same set minus one explicitly selected slot. A T2-native weapon
|
||
shows only its applicable shared-slot control, and tiers below the native tier
|
||
remain unavailable. Operators may save an unverified shared set or T0 exclusion
|
||
when they cannot inspect the weapon in-game. Mark an active weapon `CONFIG
|
||
REQUIRED` until every available tier has its full slot count, and keep verified
|
||
assignments editable. Reject unknown slot types and counts above the tier limit.
|
||
Weapon Mod definitions then configure one slot plus one or more compatible
|
||
weapon categories. The UI and validation must require both dimensions to match
|
||
once the weapon definition is complete.
|
||
|
||
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 mechanics metadata
|
||
below both descriptions. Use 16px semibold sans-serif text for tier effects so
|
||
players can scan them before supporting facts. Do not use the serif,
|
||
quote-like prose treatment. Use compact fixed tier labels 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.
|
||
Render duration and stack limits as detail rows with activation and cooldown
|
||
data. Keep calculation effects out of public Talent cards because the tier
|
||
descriptions already state the player-facing values. Omit a stack limit of one
|
||
because a single active instance is the default. 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.
|
||
|
||
End each Talent card with a compatibility action. Gear Talent actions navigate
|
||
to the Gear registry with the Talent filter selected. Weapon Talent actions
|
||
navigate to the Weapons registry with the Talent Pool filter selected. Keep
|
||
this action in shared cards and relationship quick views so both contexts use
|
||
the same destination and label.
|
||
|
||
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.
|
||
|
||
### Source-owned mechanic program editor
|
||
|
||
Use `MechanicProgramEditor` for every calculation-ready standard or exotic
|
||
Talent, OS Protocol Talent, Skill Chip Talent, and Specialization tree-rank
|
||
effect. The program stays inside its owning source editor and contribution
|
||
payload. Do not create a standalone Trigger registry, Trigger assignment
|
||
control, or shared Trigger lifecycle.
|
||
|
||
Each source supplies the value columns required by its progression:
|
||
|
||
- Standard Talents show Tier I and Tier II. Exotic Talents show Tier I and an
|
||
explicit Tier II documentation state; the editor adds the Tier II value
|
||
column only when contributors select `DOCUMENTED`.
|
||
- OS Protocol Talents show a base value and may scale an outcome through the
|
||
protocol's zero-to-five upgrade expression.
|
||
- Skill Chip Talents show minimum and maximum values.
|
||
- Specialization tree ranks show the rank's base value.
|
||
|
||
The editor is one layered control surface. Start with a compact program heading
|
||
and the explicit `READY`, `REQUIRES ASSUMPTIONS`, or `CAPTURED ONLY` state.
|
||
Follow it with Builder Controls, Recipe Starter, State Pools, ordered event
|
||
branches, ordered outcomes, and the generated read-only script. Use connected
|
||
panels and restrained borders to preserve the hierarchy; do not present the
|
||
typed graph as an undifferentiated form.
|
||
|
||
Talent editors place that surface inside the shared `modeling-disclosure`
|
||
pattern. New `CAPTURED ONLY` Talents start with an empty program and a collapsed
|
||
`COMBAT MODELING` summary so authors can record identity, image, and source
|
||
description first. Existing modeled Talents open the disclosure when edited.
|
||
Mechanic validation errors open it and keep the relevant error text visible.
|
||
The summary reports `CAPTURE ONLY · MODEL LATER` or the configured branch count
|
||
in text. Its native disclosure semantics preserve keyboard and assistive
|
||
technology support; mobile targets remain at least 44 pixels tall.
|
||
|
||
The direct-event picker reads the 19 normalized events from the code-defined
|
||
event registry. Use searchable single-assignment because the vocabulary exceeds
|
||
the compact segmented-choice limit. Each branch presents its event, match
|
||
policy and parameters, optional cooldown, condition, state mutations, and
|
||
outcomes. The branch condition offers `ALWAYS`, `HEALTH BAND`, `EVENT FIELD`,
|
||
and `STATE THRESHOLD` for manual authoring. Event-field conditions expose the
|
||
field path, comparison operator, scalar type, and typed value. State thresholds
|
||
compare an agent-scoped pool with a numeric value. Health bands expose an
|
||
optional inclusive lower Health percentage and a required exclusive upper
|
||
percentage; helper text states how exact thresholds resolve. Predicates outside
|
||
these manual patterns remain preserved, display `ADVANCED`, and stay visible in
|
||
the generated script. State rows expose
|
||
label, agent or target scope, initial value, bounds,
|
||
best-case value, and optional expiry. A state change that writes a target pool
|
||
uses a `STATE OWNER` segmented control with `EVENT TARGET` and `EVENT ACTOR`;
|
||
the selected owner remains visible in the generated script. Outcome rows expose
|
||
kind, target scope, Attribute or resource when applicable, value basis, state
|
||
scaling, phase, and every source-specific value column. The Value Model control
|
||
supports static values, live Attribute totals, percentage-normalized Attribute
|
||
values, event fields, reducer output, source-defined scenario controls, and OS
|
||
Protocol upgrade scaling where the source permits it. Selecting either
|
||
Attribute model uses the shared searchable single-assignment pattern and
|
||
displays the Attribute's unit. Label the direct model `LIVE ATTRIBUTE`. Label
|
||
the percentage-normalized model `ATTRIBUTE ÷ 100` so authors can see the
|
||
transform applied to the stored value.
|
||
Restoration outcomes also expose an
|
||
`INSTANT` or `CONTINUOUS` segmented choice. Continuous delivery reveals one
|
||
required duration field and describes the configured value as the total
|
||
delivered across that duration; switching back to instant clears the duration.
|
||
|
||
Action Family recipes are optional authoring starters. Present the recipe
|
||
catalog as a searchable assignment with only the parameters required by the
|
||
selected family. `ADD RECIPE BRANCH` copies typed branches into the current
|
||
source program, where authors may edit its exposed branch, state, and outcome
|
||
controls. The recipe label records provenance only. `REPLACE PROGRAM` requires
|
||
an inline confirmation that states all existing branches will be discarded.
|
||
|
||
Builder Controls define source-specific advanced scenario assumptions. Authors
|
||
choose toggle, slider, or numeric input and provide a label, Agent guidance,
|
||
default value, best-case value, and numeric bounds when applicable. Group these
|
||
controls behind the builder's advanced scenario surface. Maximum Potential
|
||
uses best-case values. Custom Scenario uses saved Agent values. A required
|
||
cadence or environmental value with no supplied assumption keeps the mechanic
|
||
out of the calculation and displays `REQUIRES ASSUMPTIONS`; the editor and
|
||
runtime never invent a cadence.
|
||
|
||
Use `--shd-model-surface` and `--shd-model-border` for mechanic programs,
|
||
calculation revisions, and field calibration. The blue information rail marks
|
||
modeled behavior. Orange remains reserved for selection and activation. Name
|
||
events, branches, state, cooldowns, durations, stack limits, outcomes, phases,
|
||
and per-stack values in text so the model remains legible without color.
|
||
|
||
At narrow widths, stack panels, branch controls, state rows, variant columns,
|
||
and outcomes without changing their order. Keep add, remove, replace, and help
|
||
controls at least 44 pixels tall. Every disclosure and confirmation exposes
|
||
its state to assistive technology. Focus remains in the active field when the
|
||
generated script refreshes, and reduced-motion preferences remove expansion
|
||
and replacement transitions.
|
||
|
||
The recipe starter opens with no recipe selected. Keep its count, duration,
|
||
distance, and Health-band parameters hidden until the author chooses a recipe.
|
||
Health-band recipes expose ordered strict upper thresholds and editable band
|
||
labels. Stack each band row on narrow screens and keep its remove action at
|
||
least 44 pixels tall. Disable `ADD RECIPE BRANCH` while the selection is empty,
|
||
and show `REPLACE PROGRAM` only after the author selects a recipe and the
|
||
current program contains a branch.
|
||
|
||
#### AI mechanic drafting
|
||
|
||
`MechanicProgramEditor` keeps its complete manual authoring controls available
|
||
to every authorized data author. Place the optional AI drafting panel inside
|
||
that editor, after the source description and before the structured mechanic
|
||
controls. AI assistance must never replace, hide, lock, or reset the manual
|
||
workflow.
|
||
|
||
The panel uses one compact modeled-data surface with a blue information rail.
|
||
Its heading names `AI MECHANIC DRAFTING` and identifies the output as a draft.
|
||
An author submits the exact in-game mechanic text and optional context. Keep the
|
||
source text editable during clarification and preview. Use the standard pending
|
||
button treatment while a request runs and block duplicate submissions.
|
||
|
||
Agents without `ai.mechanic.generate` still see the collapsed panel. Disable
|
||
its request control, label the state `PERMISSION REQUIRED`, and direct
|
||
the agent to request permission from an administrator. The disabled state must
|
||
not expose API configuration, internal prompt content, model controls, or a
|
||
working form submission.
|
||
|
||
The panel presents five explicit states:
|
||
|
||
- `READY FOR INPUT` shows the source-text field and Generate Draft action.
|
||
- `DRAFTING` keeps the submitted text visible, announces progress through a
|
||
polite live region, and disables repeat actions.
|
||
- `CLARIFICATION REQUIRED` lists each focused question with its reason and
|
||
bounded answer control. The author may answer, revise the source text, or
|
||
return to manual authoring.
|
||
- `CAPABILITY GAP` names the unsupported behavior and displays the developer
|
||
handoff, supported approximation, and optional workaround in separate
|
||
labeled blocks. Do not present a capability gap as validation failure.
|
||
- `DRAFT PREVIEW` shows assumptions, warnings, readiness, and the generated
|
||
script before an explicit `APPLY TO EDITOR` action.
|
||
|
||
The capability-gap state offers `COPY DEVELOPER PROMPT` and `SUBMIT TO ADMIN
|
||
TEAM` beside `REVISE SOURCE WORDING`. The copied prompt includes the exact
|
||
analyzed wording, clarification answers, gap evidence, and implementation
|
||
acceptance criteria. Submission sends one mandatory ISAC notification to each
|
||
active full administrator and records the report in the `ai_assistance` audit
|
||
history. Disable duplicate submission for the current assistant request.
|
||
Clipboard or network failures keep the handoff visible and show a specific
|
||
recovery message. Neither action changes the mechanic editor or saves the
|
||
parent record.
|
||
|
||
Applying a draft fills the structured fields in the current unsaved editor.
|
||
It does not save, publish, submit a proposal, close the editor, or discard
|
||
manual changes without confirmation. Show a concise before-and-after summary
|
||
when applying the draft would replace configured branches, pools, controls, or
|
||
outcomes. The standard ISAC save lifecycle begins only after the author reviews
|
||
and saves the resulting form.
|
||
|
||
Use text labels with status colors. Orange marks Generate, Answer, and Apply
|
||
actions. Blue identifies modeled information, yellow marks assumptions or
|
||
unsupported coverage, and red marks request or validation failures. Never use
|
||
model confidence as the only acceptance signal.
|
||
|
||
On narrow screens, stack questions, answers, preview metadata, and actions in
|
||
source order. Keep controls at least 44 pixels tall and keep the draft preview
|
||
inside the viewport. Focus moves to the first clarification question, the
|
||
capability-gap heading, or the draft-preview heading when a result arrives.
|
||
Return focus to the initiating control when the author closes or resets the
|
||
panel. Announce the result state without reading the complete generated script.
|
||
Reduced-motion preferences remove pending, disclosure, and preview
|
||
transitions while preserving textual state changes.
|
||
|
||
#### Generated mechanic script
|
||
|
||
The shared `PseudoScript` component gives authors and builders a readable
|
||
transcription of the typed mechanic or combat calculation. The typed event,
|
||
predicate, reducer, state-pool, outcome, and calculation-stage data remain
|
||
authoritative. The interface generates the script from that data; authors do
|
||
not edit or execute the displayed text.
|
||
|
||
Render generated script on `--shd-model-surface` with
|
||
`--shd-model-border`, a blue information rail, restrained green syntax
|
||
keywords, line numbers, and the shared monospaced typeface. Give the panel an
|
||
explicit `GENERATED SCRIPT · READ ONLY` label and show its calculation
|
||
readiness in text. Reserve orange for adjacent actions and selected controls.
|
||
Do not style the panel as an editable textarea or show a caret, resize handle,
|
||
or save action.
|
||
|
||
Use semantic code content inside the panel. Treat line numbers as structural
|
||
decoration and ensure assistive technology reads each statement once. Preserve
|
||
indentation and keep type at the telemetry floor. Long statements may wrap at
|
||
token boundaries or use horizontal scrolling on narrow widths. Keep the panel
|
||
within its parent grid with `min-width: 0`. Script regeneration must not move
|
||
focus or announce the complete script after each field change. Place validation
|
||
and readiness messages beside the panel with ordinary status semantics.
|
||
|
||
Use the shared `MechanicLanguageHelp` control wherever an author can configure
|
||
mechanics or calculation stages. The compact `SCRIPT REFERENCE` button opens a
|
||
native help dialog with syntax, event, timing, state, and outcome references.
|
||
Long registry-level references may use a labeled disclosure with the same
|
||
content. The help trigger remains near the generated preview so authors do not
|
||
need to leave the editor to interpret it. Point every full-reference action to
|
||
`/isac/mechanic-reference`, with a stable section anchor when the source has a
|
||
specific topic. Do not point full-reference actions to collapsed same-page
|
||
anchors.
|
||
|
||
Help triggers and disclosure summaries use native button semantics,
|
||
focus-visible treatment, and explicit expanded or dialog state. Opening a
|
||
dialog moves focus to its close control; Escape and the close action dismiss
|
||
it and return focus to the trigger. On mobile, the dialog fits the viewport,
|
||
scrolls its body, and keeps its close action available. Reduced-motion
|
||
preferences remove dialog and disclosure transitions. Syntax color and motion
|
||
never carry meaning without text.
|
||
|
||
#### Mechanic reference surface
|
||
|
||
`/isac/mechanic-reference` is the dedicated read surface for the mechanic and
|
||
combat-calculation languages. It contains no mutation controls. Give the page a
|
||
compact section index beside the reference body and keep that index sticky when
|
||
the available width and viewport height support it. Assign a stable heading
|
||
anchor to each major section so editor dialogs can link to the relevant
|
||
definition.
|
||
|
||
Present bounded syntax, state, phase, outcome, and calculation-stage
|
||
vocabularies as connected reference matrices with shared borders and aligned
|
||
columns. Generate the 19-event registry and Action Family recipe catalog from
|
||
code-defined metadata so the reference matches the available editor controls.
|
||
Explain that events are runtime contracts and recipes only seed editable source
|
||
branches. Pair complex mechanics with a worked `PseudoScript` example. Keep
|
||
labels and descriptions visible; color, abbreviations, and script keywords
|
||
cannot carry the explanation alone.
|
||
|
||
Include a live-searchable Attribute variable glossary sourced from the active
|
||
ISAC Attribute registry. Search matches Attribute names, stored descriptions,
|
||
types, categories, calculation types, units, source ranges, and caps. Display
|
||
each stored Attribute description verbatim. Show type, category, calculation
|
||
type, unit, applicable Gear, Weapon, and Skill Chip ranges, and optional cap as
|
||
supporting metadata. Mark a missing description as `DOCUMENTATION NEEDED` and
|
||
link authorized authors to the Attribute record; do not generate substitute
|
||
copy. Search operates on the full active glossary before any result limit and
|
||
keeps its visible label, clear action, keyboard focus, and textual result count.
|
||
|
||
Section-index links and anchored headings use visible keyboard focus. In-page
|
||
navigation must place the target below the application header. At narrow
|
||
widths, move the index into document flow above the content and stack reference
|
||
sections in one column. Allow connected matrices to scroll within their own
|
||
boundaries, and prevent horizontal page overflow. Reduced-motion preferences
|
||
remove smooth anchor scrolling and sticky-state transitions.
|
||
|
||
#### Builder calculation modes
|
||
|
||
The loadout builder places one required two-option `SegmentedChoice` above
|
||
combat assumptions. The persisted `maximum` and `custom` values use these
|
||
visible labels:
|
||
|
||
- `MAXIMUM POTENTIAL` calculates a configured ceiling. It applies conditional
|
||
effects at peak state and treats selected abilities as firing on cooldown
|
||
against their maximum configured target count.
|
||
- `CUSTOM SCENARIO` exposes encounter assumptions and source-defined advanced
|
||
controls for a player-defined scenario.
|
||
|
||
New loadouts select `MAXIMUM POTENTIAL`. The interface labels Maximum results
|
||
as a modeled ceiling so players do not read them as typical encounter
|
||
performance. Maximum hides granular assumption fields without deleting their
|
||
saved values. Returning to Custom restores those values.
|
||
|
||
Custom mode gives each unlocked conditional effect three state controls:
|
||
|
||
- `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 Custom profile. Open the advanced scenario surface to show only the
|
||
toggle, slider, and numeric controls defined by that effect's owning source.
|
||
The effect card shows uptime, activation count, and applied stack state beside
|
||
the mode. A mechanic that needs an undefined cadence or another missing
|
||
scenario input displays `REQUIRES ASSUMPTIONS`; the builder withholds its
|
||
calculated contribution until the author or player supplies that input.
|
||
|
||
Maximum and Custom use radio semantics, an explicit selected label, keyboard
|
||
arrow navigation, and the standard orange selected rail. Results repeat the
|
||
active calculation mode in text. On mobile, the global mode control and Custom
|
||
assumption fields stack into full-width targets of at least 44 pixels.
|
||
Mode changes use the standard pressed feedback; reduced-motion preferences
|
||
remove transitions without hiding the state change.
|
||
|
||
Combat result panels show normal, critical, headshot, and critical-headshot
|
||
values with burst, sustained, and encounter DPS. Conditional stack telemetry
|
||
lists the mode, uptime, activations, average and peak stacks, ending stacks,
|
||
buildup time, and maintained state. 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 presents Specialization and Focus as the first loadout decision.
|
||
The Focus sets the primary Attribute, progression tree, and three ordered
|
||
abilities. Its identity combines Specialization artwork and the primary
|
||
Attribute mark. 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.
|
||
|
||
Each ability panel exposes one compact activation control: Off, On Cooldown, or
|
||
Custom Rate. Custom Rate adds uses per minute. Every enabled
|
||
ability has its own target count. Skill result cards show the ability name,
|
||
activation count, single-target DPS, total-target DPS, and a combined summary.
|
||
They state that Skills can critically hit and multi-shot but cannot headshot.
|
||
|
||
Saved loadouts store focus, node ranks, nine Skill Chips, conditional modes,
|
||
encounter assumptions, and per-ability activation profiles. The builder accepts
|
||
only the current complete structure. Invalid local drafts are discarded;
|
||
invalid server records are 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.
|
||
|
||
Keep weapon and Skill Attribute profiles in separate compact registries inside
|
||
the same revision editor. A Skill profile shows the Attribute, one of the
|
||
bounded Skill stages, Add or Multiply, and its weight. Use searchable
|
||
assignment for the ten-stage vocabulary and a segmented control for the
|
||
two-value operator. Reject duplicate Attribute and stage pairs. Revision
|
||
cloning, proposal review, publication evidence, and audit snapshots must
|
||
include both profile registries.
|
||
|
||
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.
|
||
|
||
Calculation revision editors include the optional AI drafting panel after the
|
||
revision identity and before the manual stage and profile controls. Reuse the
|
||
`READY FOR INPUT`, `DRAFTING`, `CLARIFICATION REQUIRED`, `CAPABILITY GAP`, and
|
||
`DRAFT PREVIEW` states from AI mechanic drafting. The panel uses calculation
|
||
language, identifies the active or edited base revision, and previews changes
|
||
to stages, weapon profiles, and Skill profiles.
|
||
|
||
Agents without `ai.calculation.generate` see the collapsed
|
||
`PERMISSION REQUIRED` state. Agents with the permission may request and apply a
|
||
draft, but the panel leaves every manual calculation control available.
|
||
Applying a draft fills the open unsaved revision form. It does not save the
|
||
revision, activate it, grant `calculation.publish`, or bypass the activation
|
||
confirmation. Before applying, show current and proposed counts for stages,
|
||
weapon profiles, and Skill profiles beside assumptions, warnings, and the
|
||
generated script.
|
||
|
||
Use the same pending, duplicate-request, focus, live-region, mobile stacking,
|
||
44-pixel target, and reduced-motion rules as the mechanic assistant. A
|
||
calculation capability gap names the unsupported stage, operator, binding,
|
||
curve, or runtime behavior and keeps the manual revision editor available.
|
||
|
||
### 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.
|
||
Each library card offers `DOWNLOAD`, `EDIT`, and `DELETE` in a connected action
|
||
rail. `DELETE` opens a focused confirmation that names the asset and states that
|
||
the change is permanent. For assigned icons, the confirmation names the owning
|
||
entity type. ISAC clears that source icon assignment before it removes the
|
||
shared file. General library uploads retain the `ICON` or `IMAGE` state.
|