Skip to content

Commit bc578a5

Browse files
[feat](ui): calm text gradients, left-nav/right-controls app bar, compass brand v5, slim guided hint
Fase 2e-2g (owner feedback): - Gradient TEXT ("evidence", "Always explains why") moved to muted theme-tuned --aa-grad-text (deeper on light, pastel on dark) — never glares; decorative fills keep the vivid accent. - Modern app bar: ONE sticky glass bar — nav tabs top-LEFT (segmented icon badges), compact controls + brand docked RIGHT; wraps into two tidy right-aligned rows on mid widths (no horizontal scroll, e2e-verified). App title returns as a wordmark beside the compass (desktop). - Guided "New here?" strip: slim calm inline hint (no card), power-user note right with a small ]K key cap; fixed the inline-display footgun so .aa-hide-phone wins on phones (360px overflow caught by e2e). - Brand mark v5: minimal monochrome COMPASS on transparent bg via currentColor (black on light, auto-light on dark; favicon uses prefers-color-scheme); PWA icons regenerated (black compass on soft-white tile, maskable-safe). - CHANGELOG for the whole Fase 2. lint, tsc, build, 119 unit + 14 e2e, all 6 guards green; visual QA dark/light, EN/ID, 1440/360. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 0b3826c commit bc578a5

11 files changed

Lines changed: 149 additions & 180 deletions

File tree

CHANGELOG.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,27 @@ The decision **model** carries its own version, recorded in the
99

1010
## [Unreleased]
1111

12+
### Added / Changed (Fase 2 — richer scenarios & guidance, full-feature Guide, calm chrome — 2026-07-16)
13+
14+
- **10 scenario presets** — five new helper scenarios (B2B SaaS, consumer mobile, data platform,
15+
legacy modernization, real-time collaboration) marked `calibrated: false`; the five ADR-0002
16+
presets stay bit-exact and guard-pinned. `check-app-config.mjs` extended accordingly; a new
17+
unit test pins each helper's engine outcome per dimension (drift guard).
18+
- **Per-level factor examples** — every one of the 14 factors shows a bilingual real-world
19+
example for the selected level in guided mode (pure UI copy; the frozen model is untouched).
20+
- **Guide = full feature map** — section 7 now covers Home, the guided/expert Advisor toolset,
21+
all seven Insights lenses, save/export/share, the command palette & shortcuts, EN/ID, themes,
22+
mobile chrome, and PWA install/offline.
23+
- **Calm text gradients** — gradient text ("evidence", "Always explains why") moved to a muted,
24+
theme-tuned `--aa-grad-text` (deeper on light, pastel on dark) — decorative fills keep the
25+
vivid accent, text never glares.
26+
- **Modern app bar** — one sticky glass bar: nav tabs (futuristic segmented badges) in the
27+
top-left corner, compact controls + brand mark docked right; the app title lives on the Home
28+
hero. The guided "New here?" strip is now a slim, calm inline hint with a ⌘K key cap.
29+
- **Brand mark v5 "compass"** — a minimal monochrome compass on a transparent background:
30+
black in the light theme, auto-inverting via `currentColor` (app) and `prefers-color-scheme`
31+
(favicon); PWA icons regenerated as a black compass on a soft-white tile.
32+
1233
### Changed (Fase 1 — "Aurora Glass" borderless evolution + identity — 2026-07-16)
1334

1435
- **Component tree grouped by feature area**`src/components/` reorganised into

public/favicon.svg

Lines changed: 16 additions & 47 deletions
Loading

public/icons/apple-touch-icon.png

-27.6 KB
Loading

public/icons/icon-192.png

-29 KB
Loading

public/icons/icon-512.png

-163 KB
Loading

public/icons/icon-maskable-512.png

-134 KB
Loading

src/App.tsx

Lines changed: 38 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -217,40 +217,44 @@ export default function App() {
217217
canvas; the header/nav are glass. The extra wrapper div is gone with the frame. */}
218218
<div>
219219
<div id="f-app" className={mode} style={{ position: 'relative' }}>
220-
<Header
221-
mode={mode}
222-
onToggleMode={setMode}
223-
onCmdK={() => setOverlay('palette')}
224-
onHelp={() => setOverlay('shortcuts')}
225-
onManual={() => setOverlay('manual')}
226-
theme={theme}
227-
onToggleTheme={toggleTheme}
228-
saveSig={saveSig}
229-
/>
230-
231-
<nav aria-label={t('m.primaryNav')} className="screen-only aa-topnav aa-glass">
232-
{(
233-
[
234-
{ v: 'home', key: 'nav.home', Icon: IconHome },
235-
{ v: 'advisor', key: 'nav.advisor', Icon: IconCompass },
236-
{ v: 'learn', key: 'nav.learn', Icon: IconBulb },
237-
] as const
238-
).map(({ v, key, Icon }) => {
239-
const active = mainView === v;
240-
return (
241-
<button
242-
key={v}
243-
type="button"
244-
aria-current={active ? 'page' : undefined}
245-
onClick={() => navigate(v)}
246-
className={'aa-topnav-tab' + (active ? ' on' : '')}
247-
>
248-
<Icon size={15} aria-hidden />
249-
{t(key)}
250-
</button>
251-
);
252-
})}
253-
</nav>
220+
{/* Modern app bar (Fase 2, DECISIONS.md): ONE sticky glass bar — nav tabs in the
221+
top-LEFT corner, controls + brand docked RIGHT. The app title lives on the Home
222+
hero and the document title, keeping the bar a single calm row. */}
223+
<div className="aa-appbar aa-glass">
224+
<nav aria-label={t('m.primaryNav')} className="screen-only aa-topnav">
225+
{(
226+
[
227+
{ v: 'home', key: 'nav.home', Icon: IconHome },
228+
{ v: 'advisor', key: 'nav.advisor', Icon: IconCompass },
229+
{ v: 'learn', key: 'nav.learn', Icon: IconBulb },
230+
] as const
231+
).map(({ v, key, Icon }) => {
232+
const active = mainView === v;
233+
return (
234+
<button
235+
key={v}
236+
type="button"
237+
aria-current={active ? 'page' : undefined}
238+
onClick={() => navigate(v)}
239+
className={'aa-topnav-tab' + (active ? ' on' : '')}
240+
>
241+
<Icon size={15} aria-hidden />
242+
{t(key)}
243+
</button>
244+
);
245+
})}
246+
</nav>
247+
<Header
248+
mode={mode}
249+
onToggleMode={setMode}
250+
onCmdK={() => setOverlay('palette')}
251+
onHelp={() => setOverlay('shortcuts')}
252+
onManual={() => setOverlay('manual')}
253+
theme={theme}
254+
onToggleTheme={toggleTheme}
255+
saveSig={saveSig}
256+
/>
257+
</div>
254258

255259
{mainView === 'home' ? (
256260
<div className="aa-panel">
Lines changed: 16 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,25 @@
11
/**
2-
* The brand glyph v4 (Fase 1): the "neural radar" — a luminous decision core linked to five
3-
* glowing dimension nodes (5 dimensions → 1 recommendation), thin neon lines with real glow.
4-
* Mirrors `public/favicon.svg` (the single source); self-contained (renders its own tile),
5-
* so it works on any header background in both themes. Decorative: parents provide the
6-
* accessible name.
2+
* The brand glyph v5 (Fase 2, DECISIONS.md): a minimal modern COMPASS — ring, needle, hub —
3+
* in a single color on a TRANSPARENT background. Drawn with `currentColor`, so it is black in
4+
* the light theme (the owner's elegant default) and automatically light in dark contexts.
5+
* Mirrors `public/favicon.svg` (the single source). Decorative: parents provide the
6+
* accessible name and the color context.
77
*/
88
export function BrandMark({ size = 34 }: Readonly<{ size?: number }>) {
99
return (
1010
<svg width={size} height={size} viewBox="0 0 100 100" aria-hidden focusable="false" style={{ display: 'block' }}>
11-
<defs>
12-
<linearGradient id="aa-bm-ln" x1="0" y1="0" x2="1" y2="1">
13-
<stop offset="0" stopColor="#8b7cff" />
14-
<stop offset="0.55" stopColor="#38e1ff" />
15-
<stop offset="1" stopColor="#7cf5c8" />
16-
</linearGradient>
17-
<radialGradient id="aa-bm-tile" cx="0.5" cy="0.32" r="0.9">
18-
<stop offset="0" stopColor="#151a33" />
19-
<stop offset="1" stopColor="#05060f" />
20-
</radialGradient>
21-
<radialGradient id="aa-bm-core" cx="0.5" cy="0.5" r="0.5">
22-
<stop offset="0" stopColor="#ffffff" />
23-
<stop offset="0.5" stopColor="#c9d4ff" />
24-
<stop offset="1" stopColor="#8b7cff" />
25-
</radialGradient>
26-
<filter id="aa-bm-glow" x="-60%" y="-60%" width="220%" height="220%">
27-
<feGaussianBlur stdDeviation="3.2" result="b" />
28-
<feMerge>
29-
<feMergeNode in="b" />
30-
<feMergeNode in="SourceGraphic" />
31-
</feMerge>
32-
</filter>
33-
</defs>
34-
<rect width="100" height="100" rx="23" fill="url(#aa-bm-tile)" />
35-
<g filter="url(#aa-bm-glow)">
36-
<polygon points="50,20 81.4,42.8 69.4,79.7 30.6,79.7 18.6,42.8" fill="none" stroke="url(#aa-bm-ln)" strokeWidth="1.6" strokeLinejoin="round" opacity="0.5" />
37-
<g stroke="url(#aa-bm-ln)" strokeWidth="2" strokeLinecap="round" opacity="0.9">
38-
<line x1="50" y1="53" x2="50" y2="20" />
39-
<line x1="50" y1="53" x2="81.4" y2="42.8" />
40-
<line x1="50" y1="53" x2="69.4" y2="79.7" />
41-
<line x1="50" y1="53" x2="30.6" y2="79.7" />
42-
<line x1="50" y1="53" x2="18.6" y2="42.8" />
43-
</g>
44-
<circle cx="50" cy="20" r="4.2" fill="#38e1ff" />
45-
<circle cx="81.4" cy="42.8" r="3.4" fill="#7cf5c8" />
46-
<circle cx="69.4" cy="79.7" r="3.4" fill="#8b7cff" />
47-
<circle cx="30.6" cy="79.7" r="3.4" fill="#ff7ac3" />
48-
<circle cx="18.6" cy="42.8" r="3.4" fill="#a99bff" />
49-
<circle cx="50" cy="53" r="9" fill="url(#aa-bm-core)" />
11+
<circle cx="50" cy="50" r="38" fill="none" stroke="currentColor" strokeWidth="6" />
12+
{/* cardinal ticks */}
13+
<circle cx="50" cy="21" r="2.4" fill="currentColor" opacity="0.55" />
14+
<circle cx="79" cy="50" r="2.4" fill="currentColor" opacity="0.55" />
15+
<circle cx="50" cy="79" r="2.4" fill="currentColor" opacity="0.55" />
16+
<circle cx="21" cy="50" r="2.4" fill="currentColor" opacity="0.55" />
17+
{/* needle: solid north blade, outlined south blade (one color, two weights) */}
18+
<g transform="rotate(40 50 50)">
19+
<polygon points="50,19 58.5,50 41.5,50" fill="currentColor" />
20+
<polygon points="50,81 56.5,50 43.5,50" fill="none" stroke="currentColor" strokeWidth="4.6" strokeLinejoin="round" />
5021
</g>
22+
<circle cx="50" cy="50" r="6" fill="currentColor" />
5123
</svg>
5224
);
5325
}

src/components/chrome/GuidedBanner.tsx

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,32 @@
11
import { IconSparkles, IconCommand } from '@tabler/icons-react';
22
import { useI18n } from '../../i18n/I18nContext';
33

4-
// The "New here?" orientation banner — guided mode only (hidden in expert via .guided-only).
5-
// Modern treatment (Fase 1 polish): a floating glass card with badge pills + a ⌘K key cap,
6-
// replacing the old full-width info strip.
4+
// The "New here?" orientation hint — guided mode only (hidden in expert via .guided-only).
5+
// Fase 2 (owner feedback): a SLIM, calm inline strip — no card, no glass, muted colors; the
6+
// power-user hint sits quietly on the right with a small ⌘K key cap.
77
export function GuidedBanner() {
88
const { t } = useI18n();
99
return (
1010
<div
11-
className="guided-only aa-glass"
11+
className="guided-only"
1212
style={{
1313
display: 'flex',
1414
flexWrap: 'wrap',
15-
gap: '10px 14px',
16-
alignItems: 'center',
17-
padding: '12px 16px',
18-
margin: 'var(--aa-space-3) var(--aa-panel-pad) 0',
19-
borderRadius: 'var(--border-radius-xl)',
15+
gap: '6px 14px',
16+
alignItems: 'baseline',
17+
padding: 'var(--aa-space-2) var(--aa-panel-pad)',
18+
fontSize: '12.5px',
19+
lineHeight: 1.55,
20+
color: 'var(--color-text-tertiary)',
2021
}}
2122
>
22-
<span className="aa-badge aa-badge-accent">
23-
<IconSparkles size={13} aria-hidden />
23+
<span style={{ display: 'inline-flex', alignItems: 'center', gap: '5px', fontWeight: 600, color: 'var(--color-text-secondary)', whiteSpace: 'nowrap' }}>
24+
<IconSparkles size={13} aria-hidden style={{ opacity: 0.7 }} />
2425
{t('banner.new')}
2526
</span>
26-
<span style={{ fontSize: '12.5px', color: 'var(--color-text-secondary)', lineHeight: 1.55, flex: '1 1 260px' }}>
27-
{t('banner.body')}
28-
</span>
29-
<span className="aa-hide-phone" style={{ display: 'inline-flex', alignItems: 'center', gap: '7px', fontSize: '12px', color: 'var(--color-text-tertiary)' }}>
27+
<span style={{ flex: '1 1 300px', minWidth: 0 }}>{t('banner.body')}</span>
28+
{/* Layout via .aa-wrap (class, NOT inline display) so .aa-hide-phone can win on phones. */}
29+
<span className="aa-hide-phone aa-wrap" style={{ whiteSpace: 'nowrap' }}>
3030
<span style={{ fontWeight: 600, color: 'var(--color-text-secondary)' }}>{t('banner.power')}</span>
3131
<span className="aa-kbd">
3232
<IconCommand size={11} aria-hidden />K

src/components/chrome/Header.tsx

Lines changed: 12 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -35,34 +35,9 @@ export function Header({ mode, onToggleMode, onCmdK, onHelp, onManual, theme, on
3535
}, [saveSig]);
3636

3737
return (
38-
<div
39-
className="aa-glass"
40-
style={{
41-
display: 'flex',
42-
alignItems: 'center',
43-
justifyContent: 'space-between',
44-
padding: 'var(--aa-space-4) var(--aa-panel-pad)',
45-
borderRadius: 'var(--border-radius-xl)',
46-
flexWrap: 'wrap',
47-
gap: '10px',
48-
}}
49-
>
50-
<div style={{ display: 'flex', alignItems: 'center', gap: '12px', minWidth: 0, flex: '0 1 auto' }}>
51-
{/* BrandMark is self-contained (own dark tile + neon glyph) — no chip behind it. */}
52-
<div style={{ borderRadius: '9px', boxShadow: '0 0 16px -4px rgba(56, 225, 255, 0.5)', flex: 'none' }}>
53-
<BrandMark size={36} />
54-
</div>
55-
<div style={{ minWidth: 0 }}>
56-
<div style={{ fontFamily: 'var(--font-display)', fontSize: '16px', fontWeight: 600, letterSpacing: '-0.01em', lineHeight: 1.25, whiteSpace: 'nowrap' }}>{t('app.title')}</div>
57-
{/* The tagline shrinks with ellipsis instead of pushing the controls to wrap. */}
58-
<div style={{ fontSize: '12px', color: 'var(--color-text-tertiary)', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{t('app.tagline')}</div>
59-
</div>
60-
</div>
61-
62-
{/* Controls cluster: ONE horizontal row, right-aligned — never stacks. Compact pieces
63-
(icon-only save status, segmented toggles) keep it narrow enough for laptops; on
64-
mid widths the whole row drops under the title as a single tidy line. */}
65-
<div style={{ display: 'flex', alignItems: 'center', gap: '8px', flexWrap: 'nowrap', flex: '0 0 auto', marginLeft: 'auto' }}>
38+
// The RIGHT side of the app bar (Fase 2): one horizontal row of compact controls with the
39+
// brand mark docked at the far right. The app title lives on the Home hero + document title.
40+
<div style={{ display: 'flex', alignItems: 'center', gap: '8px', flexWrap: 'nowrap', marginLeft: 'auto', minWidth: 0 }}>
6641
{/* Save status: compact icon-only badge — the full text lives in title/aria-label. */}
6742
<output
6843
className="aa-hide-phone aa-badge aa-badge-soft"
@@ -130,7 +105,15 @@ export function Header({ mode, onToggleMode, onCmdK, onHelp, onManual, theme, on
130105
</button>
131106
</div>
132107
</div>
133-
</div>
108+
109+
{/* Brand — far right: monochrome compass (transparent, theme-aware) + wordmark.
110+
The wordmark hides on phones (MobileChrome carries navigation labels there). */}
111+
<span style={{ display: 'flex', alignItems: 'center', gap: '8px', flex: 'none', color: 'var(--color-text-primary)' }}>
112+
<BrandMark size={30} />
113+
<span className="aa-hide-phone" style={{ fontFamily: 'var(--font-display)', fontSize: '14px', fontWeight: 600, letterSpacing: '-0.01em', whiteSpace: 'nowrap' }}>
114+
{t('app.title')}
115+
</span>
116+
</span>
134117
</div>
135118
);
136119
}

0 commit comments

Comments
 (0)