Skip to content
2 changes: 1 addition & 1 deletion docs/design-tokens.md
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ Guidance:
- Default size is 44px minimum height. Use `ops-action-button-sm` for compact alert actions and `ops-action-button-lg` for high-emphasis recovery actions.
- Use semantic tone modifiers rather than ad hoc border and background values.
- Use emerald for primary affirmative actions, amber for caution, and red or rose for destructive paths.
- `success`, `success-solid`, `warning`, and `danger` are compatibility aliases. New JSX should use the canonical tone class names above.
- Legacy action tone aliases were removed. JSX should use the canonical tone class names above.
- Keep focus indication inside the clipped geometry with the shared inset focus treatment.
- Avoid rounded button chrome inside primary tactical panels.

Expand Down
12 changes: 2 additions & 10 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -234,15 +234,7 @@ function App() {
>
<header>
<div className="grid gap-4 lg:gap-6">
<div className="flex max-w-4xl gap-4">
<div
className="hidden w-3 shrink-0 flex-col items-center self-stretch sm:flex"
aria-hidden="true"
>
<span className="h-16 w-0.5 bg-ops-accent/75 shadow-[0_0_16px_rgba(110,231,183,0.22)]" />
<span className="mt-2 h-8 w-px bg-ops-accent-border" />
<span className="mt-2 h-full w-px flex-1 bg-ops-border-struct" />
</div>
<div className="flex max-w-4xl">
<div className="min-w-0">
<div className="flex flex-wrap items-center gap-3">
<span
Expand All @@ -255,7 +247,7 @@ function App() {
Personal Readiness Tracker
</p>
</div>
<h1 className="ops-tracking-display mt-3 text-3xl font-semibold text-ops-text-primary uppercase sm:mt-4 sm:text-4xl lg:text-5xl">
<h1 className="ops-display-lockup-title mt-3 text-3xl font-semibold text-ops-text-primary uppercase sm:mt-4 sm:text-4xl lg:text-5xl">
OpsNormal
</h1>
<p className="mt-3 max-w-2xl text-sm leading-7 text-ops-text-secondary sm:text-base">
Expand Down
9 changes: 2 additions & 7 deletions src/components/DomainCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -182,12 +182,7 @@ export function DomainCard({
</div>
</div>

<div className="mt-5">
<div
className="ops-sector-caption border-t border-ops-border-soft pt-3"
aria-hidden="true"
/>

<div className="mt-5 border-t border-ops-border-soft pt-4">
{busy ? (
<span id={busyHintId} className="sr-only">
Saving local write. Stand by.
Expand All @@ -198,7 +193,7 @@ export function DomainCard({
role="radiogroup"
aria-label={`${sector.label} status`}
aria-describedby={describedBy}
className="mt-3 grid grid-cols-3 gap-2"
className="grid grid-cols-3 gap-2"
>
{STATUS_OPTIONS.map((option, optionIndex) => {
const content = getStatusContent(option);
Expand Down
8 changes: 4 additions & 4 deletions src/components/HeaderTelemetry.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -118,20 +118,20 @@ function TelemetryChip({
toneClassNameByTone[tone],
].join(' ')}
>
<span className="ops-eyebrow text-[10px] font-semibold tracking-[0.14em] text-ops-text-muted">
<span className="ops-eyebrow text-[10px] font-semibold text-ops-text-muted">
{label}
</span>
<span
className={[
'mt-2 leading-none font-semibold tracking-[0.04em] uppercase [font-variant-numeric:tabular-nums]',
'ops-tracking-table mt-2 leading-none font-semibold uppercase [font-variant-numeric:tabular-nums]',
isPrimary ? 'text-3xl sm:text-4xl' : 'text-xl sm:text-2xl',
].join(' ')}
>
{value}
</span>
{sparkline ? <TelemetrySparkline states={sparkline} /> : null}
{detail ? (
<span className="mt-2 text-[10px] leading-4 tracking-[0.12em] text-ops-text-muted uppercase">
<span className="ops-eyebrow mt-2 text-[10px] leading-4 text-ops-text-muted">
{detail}
</span>
) : null}
Expand All @@ -148,7 +148,7 @@ function TelemetryHorizon({ children }: { children: ReactNode }) {
<p className="ops-eyebrow-strong ops-mono text-xs font-semibold text-ops-accent-muted">
Status horizon
</p>
<p className="mt-1 text-[10px] leading-4 tracking-[0.12em] text-ops-text-muted uppercase">
<p className="ops-eyebrow mt-1 text-[10px] leading-4 text-ops-text-muted">
30-day local picture
</p>
</div>
Expand Down
13 changes: 11 additions & 2 deletions src/features/checkin/TodayPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -245,9 +245,18 @@ export function TodayPanel({
totalCount={completion.totalCount}
/>

<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-5 lg:gap-5">
<div className="grid gap-4 sm:grid-cols-2 md:grid-cols-6 xl:grid-cols-5 xl:gap-5">
{SECTORS.map((sector, index) => (
<div key={sector.id} className="h-full">
<div
key={sector.id}
className={[
'h-full md:col-span-2 xl:col-span-1',
index === SECTORS.length - 1
? 'sm:col-span-2 md:col-span-3 xl:col-span-1'
: '',
index === SECTORS.length - 2 ? 'md:col-span-3 xl:col-span-1' : '',
].join(' ')}
>
<DomainCard
sector={sector}
sectorSigil={`S${index + 1}`}
Expand Down
2 changes: 1 addition & 1 deletion src/features/export/ExportBackupSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export function ExportBackupSection({
<button
type="button"
onClick={() => void onJsonExport()}
className={`${actionButtonClasses} ops-action-button-lg ops-action-button-success-solid`}
className={`${actionButtonClasses} ops-action-button-lg ops-action-button-emerald-solid`}
>
Export JSON
</button>
Expand Down
2 changes: 1 addition & 1 deletion src/features/history/DesktopHistoryGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ export function DesktopHistoryGrid({ model }: DesktopHistoryGridProps) {
role="row"
className={[
'ops-history-row',
isSelectedRow ? 'bg-white/[0.035]' : '',
isSelectedRow ? 'ops-history-row-selected' : '',
].join(' ')}
>
<th
Expand Down
24 changes: 19 additions & 5 deletions src/features/history/MobileHistoryGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -267,11 +267,16 @@ export function MobileHistoryGrid({ model }: MobileHistoryGridProps) {
);
})}

{SECTORS.map((sector) => {
{SECTORS.map((sector, sectorIndex) => {
const isAlternateRow = sectorIndex % 2 === 1;

return [
<div
key={`${sector.id}:label`}
className="sticky left-0 z-10 flex min-h-11 items-center gap-2 bg-ops-surface-2 px-2 text-[11px] font-semibold uppercase tracking-[0.12em] text-ops-text-primary"
className={[
'ops-history-mobile-sector-label sticky left-0 z-10 flex min-h-11 items-center gap-2 bg-ops-surface-2 px-2 text-[11px] font-semibold uppercase tracking-[0.12em] text-ops-text-primary',
isAlternateRow ? 'ops-history-mobile-row-even' : '',
].join(' ')}
>
<span
className="text-ops-text-muted"
Expand All @@ -295,15 +300,24 @@ export function MobileHistoryGrid({ model }: MobileHistoryGridProps) {
<div
key={`${sector.id}:${dateKey}`}
className={[
'ops-grid-cell min-h-10 transition [font-variant-numeric:tabular-nums]',
'flex min-h-10 items-center px-0.5 py-1',
isSelectedDay
? 'outline outline-1 -outline-offset-1 outline-[var(--ops-focus-ring)]'
: '',
getCellClassName(status),
isAlternateRow
? 'ops-history-mobile-row-even'
: '',
].join(' ')}
title={cellLabel}
>
{getStatusCellText(status)}
<div
className={[
'ops-grid-cell transition [font-variant-numeric:tabular-nums]',
getCellClassName(status),
].join(' ')}
>
{getStatusCellText(status)}
</div>
</div>
);
}),
Expand Down
3 changes: 1 addition & 2 deletions src/features/install/InstallBanner.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { useEffect, useState } from 'react';

import { AlertSurface } from '../../components/AlertSurface';
import { getAlertSurfaceActionToneClass } from '../../components/alertSurfaceTone';
import {
clearInstallBannerDismissal,
hasDismissedInstallBanner,
Expand Down Expand Up @@ -45,7 +44,7 @@ export function InstallBanner({ compact = false }: InstallBannerProps) {
<button
type="button"
onClick={() => void promptInstall()}
className={getAlertSurfaceActionToneClass('success')}
className="ops-action-button ops-action-button-sm ops-action-button-emerald"
>
Install now
</button>
Expand Down
78 changes: 36 additions & 42 deletions src/styles/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -180,11 +180,6 @@ body {
transparent 0 31px,
rgba(255, 255, 255, 0.012) 31px 32px
),
radial-gradient(
circle at 50% 80px,
rgba(110, 231, 183, 0.05),
transparent 34%
),
linear-gradient(180deg, rgba(255, 255, 255, 0.02), transparent 22%),
var(--color-ops-base);
}
Expand Down Expand Up @@ -288,6 +283,16 @@ h3,
letter-spacing: var(--ops-tracking-display);
}

.ops-display-lockup-title {
letter-spacing: var(--ops-tracking-section);
}

@media (min-width: 640px) {
.ops-display-lockup-title {
letter-spacing: var(--ops-tracking-display);
}
}

.ops-tracking-section {
letter-spacing: var(--ops-tracking-section);
}
Expand Down Expand Up @@ -345,21 +350,21 @@ h3,
inset: 0;
pointer-events: none;
background:
linear-gradient(rgba(110, 231, 183, 0.16), rgba(110, 231, 183, 0.16)) top
linear-gradient(rgba(110, 231, 183, 0.1), rgba(110, 231, 183, 0.1)) top
left / 8px 1px no-repeat,
linear-gradient(rgba(110, 231, 183, 0.16), rgba(110, 231, 183, 0.16)) top
linear-gradient(rgba(110, 231, 183, 0.1), rgba(110, 231, 183, 0.1)) top
left / 1px 8px no-repeat,
linear-gradient(rgba(110, 231, 183, 0.16), rgba(110, 231, 183, 0.16)) top
linear-gradient(rgba(110, 231, 183, 0.1), rgba(110, 231, 183, 0.1)) top
right / 8px 1px no-repeat,
linear-gradient(rgba(110, 231, 183, 0.16), rgba(110, 231, 183, 0.16)) top
linear-gradient(rgba(110, 231, 183, 0.1), rgba(110, 231, 183, 0.1)) top
right / 1px 8px no-repeat,
linear-gradient(rgba(110, 231, 183, 0.16), rgba(110, 231, 183, 0.16)) bottom
linear-gradient(rgba(110, 231, 183, 0.1), rgba(110, 231, 183, 0.1)) bottom
left / 8px 1px no-repeat,
linear-gradient(rgba(110, 231, 183, 0.16), rgba(110, 231, 183, 0.16)) bottom
linear-gradient(rgba(110, 231, 183, 0.1), rgba(110, 231, 183, 0.1)) bottom
left / 1px 8px no-repeat,
linear-gradient(rgba(110, 231, 183, 0.16), rgba(110, 231, 183, 0.16)) bottom
linear-gradient(rgba(110, 231, 183, 0.1), rgba(110, 231, 183, 0.1)) bottom
right / 8px 1px no-repeat,
linear-gradient(rgba(110, 231, 183, 0.16), rgba(110, 231, 183, 0.16)) bottom
linear-gradient(rgba(110, 231, 183, 0.1), rgba(110, 231, 183, 0.1)) bottom
right / 1px 8px no-repeat;
}

Expand Down Expand Up @@ -1065,10 +1070,28 @@ h3,
transition: background-color 120ms ease;
}

.ops-history-row:nth-child(even) {
background: var(--ops-hover-1-bg);
}

.ops-history-row-selected {
background: var(--ops-hover-2-bg);
}

.ops-history-row:hover {
background: var(--ops-hover-2-bg);
}

.ops-history-mobile-row-even {
background: var(--ops-hover-1-bg);
}

.ops-history-mobile-sector-label.ops-history-mobile-row-even {
background:
linear-gradient(var(--ops-hover-1-bg), var(--ops-hover-1-bg)),
var(--color-ops-surface-2);
}

.ops-history-cell {
transition:
background-color 120ms ease,
Expand Down Expand Up @@ -1281,34 +1304,6 @@ h3,
--ops-button-text: #e0f2fe;
}

.ops-action-button-success {
--ops-button-border: rgba(110, 231, 183, 0.4);
--ops-button-bg: rgba(16, 185, 129, 0.16);
--ops-button-bg-hover: rgba(16, 185, 129, 0.24);
--ops-button-text: #ecfdf5;
}

.ops-action-button-success-solid {
--ops-button-border: rgba(110, 231, 183, 0.45);
--ops-button-bg: rgba(16, 185, 129, 0.85);
--ops-button-bg-hover: rgba(16, 185, 129, 0.94);
--ops-button-text: #ffffff;
}

.ops-action-button-warning {
--ops-button-border: rgba(251, 191, 36, 0.36);
--ops-button-bg: rgba(245, 158, 11, 0.14);
--ops-button-bg-hover: rgba(245, 158, 11, 0.22);
--ops-button-text: #fef3c7;
}

.ops-action-button-danger {
--ops-button-border: rgba(248, 113, 113, 0.38);
--ops-button-bg: rgba(239, 68, 68, 0.14);
--ops-button-bg-hover: rgba(239, 68, 68, 0.24);
--ops-button-text: #fee2e2;
}

.ops-action-button-neutral {
--ops-button-border: rgba(255, 255, 255, 0.16);
--ops-button-bg: rgba(255, 255, 255, 0.05);
Expand Down Expand Up @@ -1337,7 +1332,6 @@ h3,
--ops-button-text: #ffffff;
}

.ops-action-button-success-solid:focus-visible,
.ops-action-button-emerald-solid:focus-visible {
box-shadow:
inset 0 0 0 1px var(--ops-focus-ring-solid-edge),
Expand Down
Loading