diff --git a/.prettierrc.json b/.prettierrc.json index 544138b..3baced4 100644 --- a/.prettierrc.json +++ b/.prettierrc.json @@ -1,3 +1,4 @@ { - "singleQuote": true + "singleQuote": true, + "endOfLine": "auto" } diff --git a/docs/design-tokens.md b/docs/design-tokens.md index 631dff4..8bf5b3b 100644 --- a/docs/design-tokens.md +++ b/docs/design-tokens.md @@ -46,7 +46,7 @@ Application rules: OpsNormal uses a small tracking scale instead of one-off component values. - `--ops-tracking-display`: `0.10em` for the product title and large display values -- `--ops-tracking-section`: `0.04em` for legacy compact headings +- `--ops-tracking-section`: `0.08em` for compact section headings - `--ops-tracking-eyebrow`: `0.14em` for standard eyebrows and compact labels - `--ops-tracking-eyebrow-strong`: `0.18em` for high-level shell metadata - `--ops-tracking-action`: `0.14em` for clipped action buttons @@ -62,21 +62,21 @@ Application rules: ## Core surfaces - `--color-ops-base`: `#0a0f0d` -- `--color-ops-surface-base`: `#0e1411` -- `--color-ops-surface-1`: `#121814` -- `--color-ops-surface-2`: `#1a221e` -- `--color-ops-surface-3`: `#222b27` -- `--color-ops-surface-raised`: `#1a221e` -- `--color-ops-surface-overlay`: `#222b27` -- `--color-ops-surface-interactive`: `#26342d` +- `--color-ops-surface-base`: `#101613` +- `--color-ops-surface-1`: `#151d1a` +- `--color-ops-surface-2`: `#1c2521` +- `--color-ops-surface-3`: `#24302a` +- `--color-ops-surface-raised`: `#18211d` +- `--color-ops-surface-overlay`: `#1f2a25` +- `--color-ops-surface-interactive`: `#28342e` - `--color-ops-text-primary`: `#e6ece9` - `--color-ops-text-secondary`: `#b4bfba` - `--color-ops-text-muted`: `#8b9691` -- `--color-ops-border-soft`: `#ffffff12` -- `--color-ops-border-struct`: `#ffffff26` -- `--color-ops-border-strong`: `#ffffff38` -- `--color-ops-panel-border`: `#ffffff12` -- `--color-ops-panel-border-strong`: `#ffffff26` +- `--color-ops-border-soft`: `#ffffff14` +- `--color-ops-border-struct`: `#ffffff29` +- `--color-ops-border-strong`: `#ffffff3a` +- `--color-ops-panel-border`: `#ffffff1a` +- `--color-ops-panel-border-strong`: `#ffffff24` - `--color-ops-accent`: `#6ee7b7` - `--color-ops-accent-muted`: `#b7f7da` - `--color-ops-accent-border`: `#6ee7b724` @@ -92,12 +92,12 @@ Application rules: ## Hover and elevation scale -- `--ops-hover-1-bg`: `rgba(255, 255, 255, 0.01)` -- `--ops-hover-2-bg`: `rgba(255, 255, 255, 0.025)` +- `--ops-hover-1-bg`: `rgba(255, 255, 255, 0.015)` +- `--ops-hover-2-bg`: `rgba(255, 255, 255, 0.035)` - `--ops-elevation-1`: standard card elevation - `--ops-elevation-2`: active or hovered panel elevation - `--ops-motion-standard`: `160ms ease-out` -- `--ops-motion-select`: `220ms cubic-bezier(0.2, 0.8, 0.2, 1)` +- `--ops-motion-select`: `cubic-bezier(0.2, 0, 0, 1)` Application rules: diff --git a/public/recovery-surfaces.css b/public/recovery-surfaces.css index 64615f2..28556fc 100644 --- a/public/recovery-surfaces.css +++ b/public/recovery-surfaces.css @@ -2,8 +2,15 @@ color-scheme: dark; --ops-fallback-panel-notch: 12px; --ops-fallback-chip-notch: 8px; - --ops-fallback-border-soft: rgba(255, 255, 255, 0.14); - --ops-fallback-border-strong: rgba(255, 255, 255, 0.22); + --ops-fallback-base: #0a0f0d; + --ops-fallback-surface-base: #101613; + --ops-fallback-surface-raised: #18211d; + --ops-fallback-surface-overlay: #1f2a25; + --ops-fallback-text-primary: #e6ece9; + --ops-fallback-text-secondary: #b4bfba; + --ops-fallback-text-muted: #8b9691; + --ops-fallback-border-soft: rgba(255, 255, 255, 0.08); + --ops-fallback-border-strong: rgba(255, 255, 255, 0.14); --ops-fallback-focus: rgba(183, 247, 218, 0.86); } @@ -12,8 +19,8 @@ min-height: 100vh; min-height: 100dvh; padding: 2rem; - background-color: #0a0f0d; - color: #e4e4e7; + background-color: var(--ops-fallback-base); + color: var(--ops-fallback-text-primary); font-family: system-ui, -apple-system, @@ -59,7 +66,7 @@ margin-top: 1rem; font-size: 0.875rem; line-height: 1.75; - color: #a1a1aa; + color: var(--ops-fallback-text-secondary); } .ops-boot-fallback-actions, @@ -153,12 +160,12 @@ border: 1px solid var(--ops-fallback-border-soft); background: linear-gradient(180deg, rgba(255, 255, 255, 0.035), transparent 30%), - rgba(0, 0, 0, 0.25); + var(--ops-fallback-surface-overlay); } .ops-crash-fallback-detail-label { letter-spacing: 0.16em; - color: #a1a1aa; + color: var(--ops-fallback-text-muted); } .ops-crash-fallback-detail { @@ -178,10 +185,10 @@ } .ops-crash-fallback-button-muted { - color: #e4e4e7; + color: var(--ops-fallback-text-primary); background: linear-gradient(180deg, rgba(255, 255, 255, 0.04), transparent 68%), - rgba(255, 255, 255, 0.05); + var(--ops-fallback-surface-raised); border-color: var(--ops-fallback-border-soft); } @@ -227,7 +234,7 @@ gap: 0.75rem; font-size: 0.8125rem; line-height: 1.5; - color: #e4e4e7; + color: var(--ops-fallback-text-primary); } .ops-crash-fallback-checkbox { diff --git a/src/App.tsx b/src/App.tsx index 48aea16..67c0b64 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -225,7 +225,7 @@ function App() {
-
+
-

+

OpsNormal

-

+

A local-only mirror for daily balance across work or school, household, relationships, body, and rest. No account. No cloud sync. No analytics layer.

-
- - - {databaseBlockedMessage ? ( - + + - ) : null} - + {databaseBlockedMessage ? ( + + ) : null} + +
-
-
-
-

- Boundary -

-

- OpsNormal is a personal status tracking tool. It is not a - medical device and does not diagnose, treat, cure, or - prevent any disease or condition. It does not provide - medical or psychological advice. -

-
- +
+
+

+ Boundary +

+

+ OpsNormal is a personal status tracking tool. It is not a + medical device and does not diagnose, treat, cure, or prevent + any disease or condition. It does not provide medical or + psychological advice. +

+
diff --git a/src/components/DomainCard.tsx b/src/components/DomainCard.tsx index 1b59e91..2a76383 100644 --- a/src/components/DomainCard.tsx +++ b/src/components/DomainCard.tsx @@ -14,6 +14,11 @@ interface DomainCardProps { } const STATUS_OPTIONS: UiStatus[] = ['nominal', 'degraded', 'unmarked']; +const STATUS_CONTROL_LABELS: Record = { + nominal: 'NOM', + degraded: 'DEG', + unmarked: 'NONE', +}; const RADIO_CONTROL_KEYS = new Set([ ' ', 'Enter', @@ -53,8 +58,8 @@ export function DomainCard({ : instructionId; const shellClassName = busy - ? 'panel-shadow clip-notched ops-notch-panel-outer bg-ops-border-strong p-px' - : 'ops-domain-card panel-shadow group clip-notched ops-notch-panel-outer bg-ops-border-strong p-px transition-colors hover:bg-ops-accent/25 focus-within:bg-ops-accent/25'; + ? 'panel-shadow clip-notched ops-notch-panel-outer h-full bg-ops-border-strong p-px' + : 'ops-domain-card panel-shadow group clip-notched ops-notch-panel-outer h-full bg-ops-border-strong p-px transition-colors hover:bg-ops-accent/25 focus-within:bg-ops-accent/25'; useEffect(() => { const pendingStatus = pendingKeyboardFocusStatusRef.current; @@ -148,7 +153,7 @@ export function DomainCard({
@@ -168,7 +173,7 @@ export function DomainCard({ /> {sector.shortLabel} -

+

{sector.label}

@@ -177,7 +182,7 @@ export function DomainCard({

-
+