Files
shd.build/docs/DESIGN_SYSTEM.md
T
jb 4777a3abd5
Validate and deploy production / validate (push) Canceled after 0s
Validate and deploy production / deploy (push) Canceled after 0s
Validate and deploy staging / validate (push) Successful in 44s
Validate and deploy staging / deploy (push) Successful in 1m14s
feat: refine builder skill chip flows
2026-08-06 01:00:15 -04:00

2762 lines
166 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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` |
| Armor surface | `--shd-armor-surface` | `#13211f` |
| Armor border | `--shd-armor-border` | `#71aaa5` |
| Armor label | `--shd-armor-label` | `#8eb9b4` |
| Armor text | `--shd-armor-text` | `#a5d1ca` |
| 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 compact matrix while one connected editor configures
the selected cell. The editor uses two lanes when its container has enough
width. Equipment identity and base values occupy the first lane; allocations,
rolls, Talents, and upgrades occupy the second. The lanes stack when either
would become too narrow. 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 show the slot and equipped item at rest. The selected cell reveals
its compact Talent, Attribute, Brand Set, or Skill Chip summary. This
progressive disclosure keeps the matrix scannable without replacing configured
choices with counts. Selecting an ability opens its three attached Skill Chip
positions. Selecting equipment opens the searchable real-data catalog and its
compatible configuration controls. Large Talent pools show the selected Talent
at rest and open their search grid through an explicit Change action. Do not
display a prototype option that the current loadout schema cannot save.
Builder cells use one leading icon track. Specializations, abilities, Skill
Chips, and OS Protocols use registered artwork; weapons and gear use static
category or slot fallbacks when no item artwork exists. Skill Chip slots keep
the icon beside the set name and quality so empty and configured slots share one
scan path. Visible builder labels stay short; full validation text remains
available through the cell's accessible name or title.
Each equipped gear or weapon Talent exposes two adjacent icon choices for Tier I
and Tier II. Both choices reuse the Talent artwork; Tier II applies a restrained
warm recolor so players can distinguish the pair before reading the labels.
Every tile retains `T1` or `T2`, its full tier name, and selected or unavailable
text. Disable Tier II when the canonical Talent has no authored Tier II data.
Weapon equipment tier and Talent tier are independent selections.
Equipment 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 totals rail summarizes deterministic
equipped-item totals. Separate panels label conditional Talent outcomes, weapon
and Skill DPS, encounter assumptions, activation profiles, rotations, and
simulation as `COMING SOON`; they do not report calculation-profile blockers as
current player errors.
The builder uses two primary workbench columns on wide screens: the compact
matrix and the two-lane editor. The live summary spans both columns below them.
Narrow screens stack the matrix, editor, and summary. 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. 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.
Guides and News use the shared structured article composer rather than the
compact Markdown editor. The composer treats the article as an editorial work
surface. The full-width title and deck match the published lede, while the
readable canvas stays near 76 characters. A publication bar above the canvas
groups visibility, News channel, publication state, and the primary action. The
sticky right inspector contains cover media, Guide tags, moderation context, and
deletion without narrowing the headline preview. The sticky toolbar uses native
buttons for paragraph, H2, H3, bold, italic, inline code, links, lists, quotes,
dividers, images, Build embeds, undo, and redo. On narrow screens, the 44-pixel
toolbar scrolls horizontally, followed by the publication bar and inspector in
document order.
Persist the versioned Tiptap JSON document, never generated editor HTML. The
server accepts only documented nodes, marks, attributes, HTTP or HTTPS links,
bounded depth, and bounded text. `ArticleContent` renders validated nodes with
Svelte elements. Inline article images require alternative text and may include
a caption. The reading page uses Source Serif 4 for prose and Barlow for
headings, metadata, controls, and embedded operational data.
`BuildEmbed` is the reusable article representation for a saved Build. A Guide
may contain several Build blocks, and a Build may appear in several Guides. Each
published revision stores the stable Build ID and a bounded display snapshot.
The component renders a connected weapon and gear matrix instead of an
interactive Builder. An author-owned private or unlisted Build displays as
`AUTHOR-SHARED`; the Guide makes that snapshot public without changing the Build
page visibility. A Build owned by another Agent displays only while the source
remains public.
Guide discovery separates three Community Oversight decisions. Pins form an
ordered group above the default feed, Featured Guides occupy a dedicated
editorial group, and Recommended Guides carry a textual badge and filter. Search
relevance is not overridden by curation. Guide cards pair a cover or
field-manual fallback with title, deck, author, publication date, tags, and the
rating count. Unlisted and private articles never enter discovery or search.
Official Ubisoft News cards use the validated source thumbnail through the
same-origin image proxy and link their cover and headline to the canonical
Ubisoft article. The `BY UBISOFT` metadata identifies the external destination
before activation. Internal News and all Guides continue to use SHD.build
article routes.
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
Place two shared configuration cards above the Skill Chip definition registry.
The `SHARED PRIMARY PROFILE` card contains the fixed Skill Duration, Skill
Radius, Skill Cooldown Recovery, and Skill Intensity rows, with direct minimum
and maximum fields for Standard, Specialized, Superior, and High-end. Its
summary shows the configured count for each quality and the `NOT YET DEFINED`
calculation state. The `SHARED SECONDARY POOL` card contains repeatable
searchable Attribute rows with direct minimum and maximum fields for
Specialized, Superior, and High-end. Its summary shows each quality's fixed
capacity and the shared option count. Each card opens its own editor and closes
that editor after a successful save. Validation keeps the affected editor open
with its values intact. Successful saves append
`game_data/skill_chip_primary_profile.updated` or
`game_data/skill_chip_secondary_pool.updated`.
State the fixed secondary capacities in the pool card and editor: Standard zero,
Specialized one, Superior two, and High-end two. Skill Chip fields never show an
item-level control or level-based preview. Quality labels use the global green,
blue, purple, and yellow treatments; orange remains reserved for actions and
selection. On narrow screens, profile summaries stack, endpoint matrices scroll
inside their cards, and actions retain 44-pixel targets.
Definition editors follow the dense staged pattern: ability assignment, identity
and icon, one per-set 2-piece bonus, then the optional 3-piece Talent. Place the
Talent assignment control before one disclosure that contains the entire Talent
workspace: identity, description, quality-mix preview, and
`MechanicProgramEditor`. The disclosure summary shows the configured Talent name
or `TALENT WORKSPACE`, the quality-scaled outcome count, and an explicit
`EXPAND` or `COLLAPSE` action. Existing Talents start collapsed when an operator
opens a definition. Assigning a Talent or receiving a Talent validation error
opens the workspace. Native disclosure semantics expose the expanded state, keep
draft state mounted while collapsed, and provide a 44-pixel mobile target.
Every equipped chip quality counts toward the two-piece threshold. The set-bonus
preview uses four steps for zero through three equipped High-end chips and the
formula `minimum + (maximum − minimum) × h / 3`; only High-end chips increase
`h`. Do not duplicate calculated values as editable fields.
### 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
totals 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 players can see loadout completeness.
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. Current Builder and shared Build pages stop at
these deterministic equipped-item totals. Conditional Talent outcomes, weapon
and Skill DPS, encounter assumptions, activation profiles, rotations, and
simulation remain planned. Render those capabilities as separate `COMING SOON`
panels, with visible text rather than color alone.
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 shared card renders a pinned Community
Note when the related record has one; quick views do not load the discussion
thread. 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.
Show each weapon's named Mod slots and slot pictograms between its performance
facts and Talent pools. Native T0 weapons display the complete T1/T2 slot set.
Mark the slot that is absent at T0 with the blue information state and an
explicit `T1+` label so the unlock does not rely on color alone. Other slots use
the neutral telemetry treatment. If ISAC has no slot data, show
`MOD SLOT DATA NOT CONFIGURED`. Do not show the weapon-category bonus count as
`BASE BONUSES`; that identical count does not help players compare weapon
definitions.
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.
Discussion and correction controls form a separate utility group at the footer's
trailing edge. These icon controls use neutral surfaces and borders at rest so
players do not mistake them for quality badges or primary actions. The
discussion control shows the visible-message count when the count is nonzero.
Both controls require accessible names and visible hover and focus states.
Opening a discussion displays a routed modal with the complete item card above
the thread. The modal keeps the record and conversation in one scroll region,
traps keyboard focus, closes through Escape or the backdrop, and fills the
viewport on narrow screens.
### Public comment threads
Use the Agent profile thread as the standard presentation for public comments.
Root comments sit directly on the page or modal surface without a card border,
fill, or shadow. Align comment bodies, actions, reply composers, and removal
tombstones with the author identity. Nested replies add one thin structural rail
and a small left inset; do not wrap replies in another panel. Limit visual
indentation on narrow screens while preserving the logical thread depth.
Pinned, removed, pending, and moderation states use explicit text. A pinned
label may use Signal Orange, but it must not add a border or background around
the whole comment. Removal tombstones retain reply context without recreating
the missing comment as a filled card.
Database Community Oversight and Agent profile owners may pin one visible root
comment on their respective threads. Render the pinned conversation first and
keep its replies attached in reading order. Place pin and unpin controls in the
comment overflow menu.
Pinned Community Note previews on database cards use the muted Armor palette
instead of action orange. Render their sanitized Markdown with the shared
`MarkdownContent` component so links, lists, paragraphs, and emphasis match the
full discussion message.
Each visible comment places `REPLY` and a low-chrome `...` overflow trigger in
the action row. The menu contains follow and report actions for signed-in Agents
who may use them, author or Community Oversight removal, and Community Oversight
pinning where the target supports a pinned note. Leaf removals delete the
message. A removed message with surviving replies becomes an unboxed tombstone
that identifies whether the poster or Community Oversight removed it. Scrollable
discussion modals reserve enough space after the final message for the complete
overflow menu to open above the scroll boundary.
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 Build Uplink after an Agent saves a Build. Public
and unlisted Builds expose its active controls; private Builds show the locked
state. Public and unlisted Build pages are read-only tactical summaries; owner
editing returns to the builder.
Build Uplink uses a compact tactical control surface. Use one bordered dark
panel with a raised telemetry header, a textual `PUBLIC LINK READY` or
`UNLISTED LINK READY` state, and a small orange signal marker. The primary
`SHARE BUILD` action opens the native Web Share sheet when the browser supports
it. Keep `COPY LINK` visible as a separate explicit action for every eligible
Build. When Web Share is unavailable, promote Copy Link to the primary action
instead of presenting a control that cannot run. Supporting copy may state that
Discord renders the Build preview after an Agent posts the link. It must not
imply that SHD.build posts to Discord or operates a bot.
Private and unsaved Builds use the locked Uplink state. Show `PRIVATE BUILD` or
`UNSAVED BUILD`, `PUBLIC LINK UNAVAILABLE`, and a short instruction to change
visibility or save. Render no active Share or Copy Link control in that state.
Do not expose a crawler-preview action or suggest that owner access makes a
private Build shareable.
Uplink actions retain textual pending, success, cancellation, unsupported, and
failure feedback. They use at least 44-pixel targets, orange focus-visible
treatment, pressed feedback, and disabled duplicate-action protection. Stack
Share above Copy Link at phone widths and remove pressed motion under
`prefers-reduced-motion`. On narrow layouts, persistence controls and
shared-loadout columns also 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.
Regular Weapon Mod definitions use a compact Level 1 and Level 20 primary-range
matrix for Standard, Specialized, Superior, and High-end quality. 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. Primary core type
remains builder-selected and appears as the three always-available core icons
rather than a persisted ISAC choice. Individual regular Weapon Mod editors also
retain triggerless Mod Effects with one or two Attribute references and fixed
per-quality values.
Configure one global secondary Attribute pool above the Weapon Mod registry.
Each repeatable row contains one searchable Attribute reference and Level 1 and
Level 20 minimum and maximum fields for Specialized, Superior, and High-end.
Values between those endpoints use linear interpolation. Do not render Standard
range fields because Standard has no secondary slot. State the fixed capacity in
the pool editor and builder: Standard zero, Specialized one, Superior two, and
High-end two. The builder requires distinct selections. Individual Weapon Mod
editors must not repeat or submit pool data. A successful pool save uses the
standard shared-profile lifecycle and creates the dedicated
`game_data/weapon_mod_secondary_pool.updated` audit event.
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 Level 1 and Level 20 primary-range matrix and level
preview established by regular 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 build instance selects the primary; the canonical definition does not store
that selection.
Configure the Gear Mod family’s global secondary Attribute pool above the
registry, separate from individual Gear Mod editors. Use the same three-quality
endpoint rows, linear interpolation, and distinct-selection rule as the Weapon
Mod pool. Capacity is zero for Standard, one for Specialized, and two each for
Superior and High-end. Individual Gear Mod edits must not repeat or submit this
pool. A successful pool save creates the dedicated
`game_data/gear_mod_secondary_pool.updated` audit event.
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.
The ability editor may pair the open ability with one active ability from the
same specialization for Skill Chip sharing. Present this as an explicit optional
relationship, exclude the current ability, and disable abilities that already
belong to another pair. Do not infer compatibility from names or Focus
membership. Saving either side updates the shared pair and includes it in the
ability audit snapshot. Archiving either ability clears the pair.
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 28 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. When the selected event publishes field
metadata, event-field conditions derive their available paths and scalar types
from that metadata. Events without a bounded field contract retain the explicit
field-path and value-type controls. Event-field conditions expose the comparison
operator 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.
Target-scoped direct-damage outcomes offer `HIT-TARGET EXPLOSION` in the Area
Targeting control. Selecting it creates an event-target-centered enemy area with
a five-meter starting radius, reveals the required radius field, and shows a
text readout for the center, valid-target policy, inclusive boundary, and
runtime evidence requirement. Only `ON EVENT` and `AFTER EVENT` remain available
for this mode; selecting it from another phase moves the outcome to
`AFTER EVENT`. Changing the outcome kind or target scope clears an incompatible
area definition. Keep `ENEMIES IN RADIUS · LEGACY` visible for saved descriptive
radius metadata, but do not present that mode as calculated explosion fan-out.
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 scenario assumptions for the planned
player simulation. ISAC authors choose toggle, slider, or numeric input and
provide a label, Agent guidance, default value, best-case value, and numeric
bounds when applicable. The current player UI does not render these controls or
read their saved values. It uses an explicit `COMING SOON` panel for the future
advanced scenario surface. The authored contract still requires the runtime to
report `REQUIRES ASSUMPTIONS` when a required cadence or environmental value is
missing; 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 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 current Builder and shared Build pages do not expose calculation modes or
combat assumptions. They show deterministic equipped-item totals and reserve
conditional Talent outcomes, weapon and Skill DPS, encounter assumptions,
activation profiles, rotations, and simulation behind explicit `COMING SOON`
panels.
Loadout schema version 6 retains `maximum`, `custom`, conditional state,
encounter-assumption, and per-ability activation fields. Version 4 is obsolete
prototype data rather than a compatibility format. The current player UI ignores
the simulation fields. When player simulation ships, one required two-option
`SegmentedChoice` will 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.
The planned interface selects `MAXIMUM POTENTIAL` for new loadouts and labels
its results as a modeled ceiling. Maximum will hide granular assumption fields
without deleting their saved values. Returning to Custom will restore those
values.
The planned 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.
The planned advanced scenario surface will let users override one effect without
changing the global Custom profile. It will show only the toggle, slider, and
numeric controls defined by that effect's owning source. The effect card will
show uptime, activation count, and applied stack state beside the mode. A
mechanic that needs an undefined cadence or another missing scenario input will
display `REQUIRES ASSUMPTIONS`; the simulation will withhold its contribution
until the author or player supplies that input.
The future Maximum and Custom control will use radio semantics, an explicit
selected label, keyboard arrow navigation, and the standard orange selected
rail. Results will repeat the active calculation mode in text. On mobile, the
global mode control and Custom assumption fields will stack into full-width
targets of at least 44 pixels. Mode changes will use the standard pressed
feedback; reduced-motion preferences will remove transitions without hiding the
state change.
The future combat result panels will show normal, critical, headshot, and
critical-headshot values with burst, sustained, and encounter DPS. Conditional
stack telemetry will list 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 will display
`INSUFFICIENT DATA` and a concrete remediation list. Until this interface ships,
the player pages show `COMING SOON` instead of combat numbers.
### 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 the ability's three definitions. When ISAC explicitly pairs that ability
with one compatible ability, the picker also shows the partner's three
definitions and labels shared entries. The relationship is bidirectional and
does not apply to other abilities in the same specialization. Players still
equip three chips in each ability panel. Skill Chips have no item-level control.
The editor uses the shared quality profiles for direct rolls. It labels the four
ability-scoped primary values `NOT YET DEFINED` and excludes them from current
Agent and combat totals. Shared-chip primary values and 3-piece Talent outcomes
target the ability represented by the panel. Secondary capacity is Standard
zero, Specialized one, Superior two, and High-end two; each equipped chip uses
distinct selections from the shared pool.
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.
Player ability panels currently expose equipped definitions and deterministic
item contributions. Planned simulation panels display `COMING SOON` instead of
activation controls or Skill DPS. The future interface will offer Off, On
Cooldown, or Custom Rate, with uses per minute and a target count for each
enabled ability. Future Skill result cards will show activation count,
single-target DPS, total-target DPS, and a combined summary. They will state
that Skills can critically hit and multi-shot but cannot headshot.
Version 5 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. Current player pages ignore the simulation
fields. The builder discards version 4 local drafts; a backed-up database
migration removes version 4 server records.
### 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.
ISAC keeps revision editing, calibration, assisted suggestions, publication, and
the calculation AI assistant available for continued model authoring. The
current Builder and shared Build pages do not consume their output.
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.
In the Weapon Mod registry, operators manage shared artwork for all eight
code-defined slots. The compact panel labels each slot `ICON REGISTERED` or
`ICON REQUIRED`. Selecting a slot opens the standard icon upload control. Keep
the slot name visible in ISAC after an operator uploads artwork.
On public weapon cards, a configured slot chip shows only its uploaded icon.
Keep the slot name in screen-reader and hover text. Retain the visible `T1+`
marker and blue information treatment for slots unlocked at Tier 1. When artwork
is missing, show the slot name instead of an invented glyph.