Cosmos hook — keystone-unlocks-quest visual spec
Cosmos hook — keystone-unlocks-quest visual spec
Design intent document for the frame-change moment at the centre of D-006 Pillar 3: a Walker allocates a keystone and a quest that was previously invisible to them becomes visible. Phase 13-10 shipped the minimum viable UX (snackbar with action label, HiddenCountHint composable). This spec captures the fuller visual treatment for a future polish pass, before quest content multiplies and ad-hoc treatments accumulate.
1. Cosmos hook definition
The cosmos hook is not an achievement. It is not a level-up. It is not a reward notification. It is a frame change — the Walker’s relationship to the world shifts, and as a consequence, the world reveals something that was already there.
Quest 005 (“Niemilknacy kurier”) gives the canonical account: Stary Marno Niedoczas has walked the outer circuit of Plenny for one hundred and twelve years. Many Walkers have passed through those gates. None stayed long enough to see the seal. The Walker who allocates Unshaken Step — keystone.unshaken-step — no longer refills in rest. For the first time in one hundred and twelve years, there is a Walker who can hold Marno’s pace. The quest was not locked behind a door. It was visible from the beginning, as a margin notation in the Spis — a line in mid-submission, not yet in print. The keystone does not unlock a door. It changes the angle from which the Walker reads the world, and from this new angle, the margin notation resolves into a full entry.
This is what the visual language must make specific. Not “you have earned a new quest.” Not “new content unlocked.” The visual treatment should communicate: the world noticed you differently. The screen does not congratulate. It registers.
What this is NOT:
- Not a XP bar fill (there is no XP in WalkRPG; progression is tree points from quests and keystones per D-016).
- Not a confetti burst or particle shower.
- Not a power-up sound or fanfare.
- Not a generic push notification pattern.
- Not a modal that demands the Walker stop and read.
The keystone is a frame change. The visual response is quiet acknowledgment, not celebration.
2. Trigger surface state machine
The cosmos hook moment occurs on the TreeViewer screen. The state sequence from Walker action to revealed quest:
STATE 1: IDLE Walker is on TreeViewer screen, browsing or tapping nodes.
STATE 2: KEYSTONE_CONFIRMATION Walker taps unlocked keystone node. Confirmation dialog appears (per wireframe tree-viewer.mdx §Allocation confirm modal). Walker taps "Confirm".
STATE 3: POST_200_KEYSTONE_ALLOCATED [~0-50ms after 200 response] POST /tree/allocate-keystone returns HTTP 200. Keystone tile: allocated visual state takes effect. Allocation echo animation fires (see §3). QuestRefreshBus.signal() fires.
STATE 4: AWAITING_QUEST_DELTA [~50-450ms] GET /quest/available refetch triggered by QuestRefreshBus subscriber. Screen content unchanged — TreeViewer remains fully interactive. No loading indicator; no visible intermediate state. The margin-line flash fires during this window (see §3).
STATE 5A: DELTA_EMPTY [~450-800ms] No new quests in the diff. Standard flow resumes. No cosmos hook moment.
STATE 5B: DELTA_NON_EMPTY [~450-800ms] New quest(s) detected in diff. Quest-revelation chip slides up from bottom (see §3). Cosmos hook moment is live.
STATE 6: CHIP_ACTIVE Chip persists for 12000ms or until dismissed. Walker may continue interacting with TreeViewer. Chip is touch-passthrough for the tree canvas except its own tap target.
STATE 7A: CHIP_TAP Walker taps chip. Navigate to QuestDetail of revealed quest (deep link). Chip dismisses without animation (instant).
STATE 7B: CHIP_TIMEOUT or CHIP_SWIPE_AWAY 12000ms elapsed or Walker swipes chip downward. Chip slides out bottom: 200ms, cubic-bezier(0.4, 0.0, 0.2, 1). TreeViewer returns to fully-normal-idle state.The window between STATE 3 and STATE 5B (total ~400-800ms) is the critical design space. During this window the screen is not in a loading state — the Walker is looking at the TreeViewer, which now shows the keystone as allocated. The cosmos hook moment begins with the allocation echo and completes when the chip arrives.
This treatment lives on the TreeViewer screen. The chip provides continuity into QuestLog navigation (see §7). The 13-10 snackbar is replaced for the cosmos hook specifically; regular node allocation snackbars (non-keystone, non-quest-revealing) retain snackbar treatment.
3. Motion vocabulary
All durations are exact. Easing curves are cubic-bezier notation. Reduce-motion variants are in §6.
3.1 Allocation echo (STATE 3, fires on POST 200)
Element: A single ring radiates outward from the keystone tile’s centre point.
| Property | Value |
|---|---|
| Trigger | Within 50ms of POST /tree/allocate-keystone 200 response |
| Shape | Circle |
| Starting radius | Matches keystone visual tile radius (40dp / 2 = 20dp) |
| Ending radius | 80dp |
| Starting opacity | 0.60 |
| Ending opacity | 0.00 |
| Border width | 1.5dp, dissolving with opacity |
| Color | Region accent of the keystone’s cluster (--color-region-plenny = #c9a04a for keystone.unshaken-step; future keystones use their own region accent token) |
| Duration | 600ms |
| Easing | cubic-bezier(0.4, 0.0, 0.2, 1) (Material 3 “emphasized”) |
| Count | 1 ring only — not a repeating pulse |
| Layering | Drawn above tree canvas, below confirmation dialogs, below chip |
The ring does not repeat. It is not a celebration pulse. It is the single resonant moment of the stone being set.
3.2 Margin-line flash (STATE 4, fires ~50ms after echo starts)
Element: A 1dp hairline at the top edge of the screen (above the status bar safe area, flush with the physical screen top edge). The diegetic reading: a margin annotation in the Spis briefly becomes legible to the Walker.
| Property | Value |
|---|---|
| Trigger | 50ms after POST 200 (overlaps with echo start) |
| Position | Top edge of screen, full width |
| Height | 1dp |
| Color | Region accent of the keystone (#c9a04a for unshaken-step) |
| Appear | Instant (0ms fade-in) |
| Hold duration | 300ms at full opacity |
| Fade-out duration | 200ms |
| Fade-out easing | cubic-bezier(0.0, 0.0, 1.0, 1.0) (linear — the notation receding without drama) |
| Total duration | 500ms (300ms hold + 200ms fade) |
| Layering | Topmost layer, drawn above everything including status bar overlay |
Total margin-line sequence: appears at T+50ms, fully visible T+50ms to T+350ms, fully faded by T+550ms.
3.3 Quest-revelation chip (STATE 5B, fires when delta detected)
Element: A chip that slides up from below the bottom of the screen. This replaces the Phase 13-10 snackbar for the cosmos hook moment. Regular snackbars (non-cosmos-hook) remain unchanged.
Chip geometry
| Property | Value |
|---|---|
| Width | 80% of screen width, horizontally centred |
| Min height | 64dp |
| Max height | Unbounded — expands to fit text at 200% font scale |
| Corner radius | 12dp |
| Bottom margin | 16dp above the bottom navigation bar top edge |
| Tap target | The full chip face (minimum 64dp height satisfies 48dp minimum) |
Chip appearance
| Property | Value |
|---|---|
| Background color | Region accent at alpha 0.18 (e.g. #c9a04a at 18% opacity over --color-surface) |
| Background at high-contrast mode | Region accent at alpha 0.70 minimum (see §6) |
| Left border | 3dp solid, region accent at full opacity |
| Content: line 1 | Quest name.en (per D-011: system surfaces always use name.en) at --type-body-lg (16px), --color-on-surface |
| Content: line 2 | Short revelation line (see §3.4 for copy spec) at --type-body (14px), --color-on-surface-muted |
| Inner padding | 12dp horizontal, 14dp vertical |
Chip slide-in animation
| Property | Value |
|---|---|
| Start position | Chip bottom edge at screen bottom edge + chip height (fully off-screen below) |
| End position | Chip at its resting position (16dp above bottom nav) |
| Duration | 320ms |
| Easing | cubic-bezier(0.4, 0.0, 0.2, 1) (Material 3 “emphasized”) |
Chip parallax breathing (while chip is active, not during slide)
A slow vertical oscillation on the chip background layer only — the text content does not move. The effect communicates that the chip is alive, not static. This is not excitement; it is the suggestion of something present.
| Property | Value |
|---|---|
| Axis | Vertical only |
| Amplitude | +2dp / -2dp (peak-to-peak: 4dp) |
| Period | 6000ms per complete cycle |
| Easing | cubic-bezier(0.45, 0.05, 0.55, 0.95) (symmetric ease-in-out) |
| Starts | Immediately after slide-in completes (T+320ms after chip fires) |
| Stops | On dismiss or tap (no mid-animation snap — interpolates to rest) |
| At 200% font scale | Amplitude collapses to 0dp (no breathing; see §6) |
| With reduce-motion | Amplitude collapses to 0dp (see §6) |
Chip auto-dismiss
| Property | Value |
|---|---|
| Auto-dismiss delay | 12000ms from chip appearance |
| Dismiss animation (timeout or swipe-down) | Chip slides out bottom: 200ms, cubic-bezier(0.4, 0.0, 0.2, 1) |
| Dismiss on tap | Instant (navigate away; no dismiss animation needed) |
The 12000ms duration is deliberate and longer than any standard snackbar (which is typically 4000-10000ms). The cosmos hook is not a notification that needs clearing. It is the world offering the Walker something. 12 seconds gives the Walker who is mid-walk, glancing at the screen, time to register what appeared and decide whether to engage or continue walking.
3.4 Chip revelation copy
The chip carries two text lines. Line 1 is the quest’s name.en (D-011 canon). Line 2 is a short system-generated revelation line — not prose, not lore, but the quietest possible acknowledgment.
Line 2 copy:
- EN: “A path you could not see before.”
- PL:
Ścieżka, której wcześniej nie widziałeś.
This line is static (same for all cosmos hook reveals). It does not name the keystone. It does not say “unlocked” or “new quest.” It says: the world changed its angle.
This line is rendered via R.string.cosmos_hook_revelation_line with appropriate PL variant in strings.xml, subject to locale override per 13-11’s walkrpg.locale.override.
4. Audio language
Audio production is deferred. These are design specifications for a future audio pass. Each block is marked as a placeholder.
Keystone-allocated tone
- Character: a single soft tone, not a chime. Imagine a stone being placed in a deep well — the resonance of the setting, not the impact.
- Fundamental frequency: 400Hz.
- Attack: 200ms.
- Sustain: 0ms (no hold after peak).
- Release: 600ms.
- Peak amplitude: -18dBFS (quiet — this is confirmation, not emphasis).
- Timbre: sine with slight second harmonic (800Hz at -12dB relative to fundamental) for warmth.
- Spatial: mono (no stereo positioning).
- Fires: within 50ms of POST /tree/allocate-keystone 200 response (same trigger as allocation echo animation).
Cosmos-hook-reveal sound
- Character: a 1.5-2.0 second sound. NOT a fanfare. NOT a success chime. The world noticing the Walker differently — quiet recognition, not triumph.
- Structure: a low fundamental (110Hz, bass register) enters at full amplitude over 300ms. At 600ms, a high overtone (880Hz) begins to emerge, fading in over 400ms. Both tones peak around 1000ms. Both fade together over 500-800ms, the high overtone fading faster.
- Peak amplitude: -16dBFS (slightly louder than keystone-allocated because this is the moment, but still restrained).
- Timbre: the low note should have slight room reverb (simulated stone chamber). The high overtone is cleaner, more direct.
- The two tones should not feel like a chord progression or musical resolution — they should feel like two separate things briefly occupying the same space.
- Spatial: mono.
- Fires: when chip begins slide-in (STATE 5B).
Chip dismiss sound
- Silent. No sound on timeout dismiss or swipe-away.
- Optional: on Walker tap-to-navigate, a single very short (80ms) low-amplitude click at -28dBFS as tactile confirmation. This is the only case where a dismiss sound is acceptable, and it is optional — the navigation itself is the confirmation.
5. Haptic spec
Haptic implementation is deferred. Design intent is specified here. Each block is marked as a placeholder.
Keystone-allocated haptic
- Pattern:
HapticFeedbackType.LongPress(Jetpack ComposeLocalHapticFeedback). - Character: a single firm tick. Solid, brief. Not heavy — the stone is set, not slammed.
- Fires: within 50ms of POST 200 (same trigger as audio and echo animation).
- Acceptance: distinguishable from the
LightImpactused for step-count delta (design-system §5.6). Firmer than light, not as heavy as the cosmos hook reveal.
Cosmos-hook-reveal haptic
- Pattern: custom waveform via
Vibrator.vibrate(VibrationEffect.createWaveform(...))on Android. - Waveform:
timings = [0, 200, 300, 80],amplitudes = [0, 220, 0, 160].- At T+0ms: begin heavy impact, amplitude 220/255, duration 200ms.
- At T+200ms: silence, 300ms.
- At T+500ms: medium tick, amplitude 160/255, duration 80ms.
- Total duration: 580ms.
- Character: the heavy impact is the frame change registering in the body. The silence is the Walker absorbing it. The medium tick is the world confirming the Walker heard correctly.
- Acceptance: must be distinguishable from the standard
HapticFeedbackType.LongPress(keystone-allocated) and from the system “new notification” pattern. The pause-then-confirmation structure is the distinctive element. - Fires: when chip begins slide-in (simultaneously with cosmos-hook-reveal audio).
- iOS equivalent:
UIImpactFeedbackGenerator(style: .heavy)followed by 300ms delay followed byUIImpactFeedbackGenerator(style: .medium). Phase 15 (iOS) mobile-developer implements this mapping.
The Phase 13-10 mobile-developer log raised haptics as deferred (haptic infra not wired in Phase 13; per design-system §5.6, “Keystone unlocked: heavy impact + distinctive sound”). This spec gives the deferred haptic a concrete waveform target so it is a defined work item, not an open-ended deferral.
6. Accessibility
6.1 Reduce-motion
When LocalAccessibilityManager.isReduceMotionEnabled == true (or WindowInsetsControllerCompat / UiModeManager reports reduce-motion preference):
| Element | Standard | Reduce-motion |
|---|---|---|
| Allocation echo | 600ms ring expansion | Instant: ring appears at full radius at opacity 0.30, fades in 100ms, fades out 100ms. Total: 200ms |
| Margin-line flash | 300ms hold + 200ms fade | Instant appear, 200ms hold, instant disappear |
| Chip slide-in | 320ms slide from off-screen | Chip appears at resting position, 150ms fade-in from opacity 0 to 1 |
| Chip parallax breathing | ±2dp oscillation, 6s loop | None (amplitude 0dp) |
| Chip auto-dismiss | 200ms slide-out | 100ms fade-out |
All content is identical with reduce-motion active. Only transition mechanics are affected. The chip still appears, the text is still present, the 12000ms auto-dismiss still applies.
6.2 TalkBack
When the chip appears, TalkBack focus MUST move to the chip. This is an assertive live region.
Modifier.semantics { liveRegion = LiveRegionMode.Assertive contentDescription = "${quest.name.en} unlocked — tap to open."}Assertive is justified here. The cosmos hook is explicitly a “stop what you are doing” moment — not a background update. Unlike routine quest-progress updates (which use LiveRegionMode.Polite per phase-13-11-acceptance.md §2 QuestLog row), the cosmos hook is the event that Pillar 3 is built around. Its interruption is intentional.
Announcement text: “{quest.name.en} unlocked — tap to open.”
Do not include the revelation line (“A path you could not see before”) in the TalkBack announcement — it is visual atmosphere, not actionable information.
If the Walker does not interact with the chip and it auto-dismisses, TalkBack does NOT announce the dismissal. The chip disappearing is not information; only its arrival was.
6.3 Color contrast
| Surface | Foreground | Background | Required ratio | Verified |
|---|---|---|---|---|
| Chip text line 1 (quest name) | --color-on-surface (#f0ece3) | Chip background (region accent at 18% alpha over --color-surface #1a1916) | 4.5:1 | PASS — the low-alpha tint barely shifts surface color; effective bg is ~#1d1b14 for Plenny gold tint; #f0ece3 against that is ~14:1 |
| Chip text line 2 (revelation line) | --color-on-surface-muted (#a09880) | Same chip background | 4.5:1 | PASS — #a09880 against #1d1b14 is ~6.0:1 |
| Chip left border | #c9a04a (Plenny) | --color-surface (#1a1916) | 3:1 (UI component) | PASS — ~5.8:1 |
| Margin-line flash | #c9a04a | Screen content beneath | 3:1 (large, 1dp decorative) | Note: margin-line flash is a decorative accent, not carrying text; contrast requirement is decorative-element 3:1 against the dark bg. At #c9a04a against #0f0e0c, ratio is ~6.9:1. PASS |
High-contrast mode: chip background alpha minimum 70% (not 18%). At 70% alpha of Plenny gold over --color-surface, the effective background is #9b7a3d (blended). --color-on-surface #f0ece3 against that is ~6.2:1. PASS. The left border remains at full opacity.
For other region accents: Mglica #6b8f7a and Targosie #d65a5a are the two borderline accents per design-system §1.5. When these accents apply to a keystone’s chip, the chip left border must be rendered at full opacity (not alpha-blended), and the text must use --color-on-surface (not the muted variant) to preserve contrast. No special exception needed for the background tint — the tint is so light (18% alpha) that the text contrast derives from the surface, not the tint.
6.4 Font scale 200%
| Element | Standard behavior | At 200% font scale |
|---|---|---|
| Chip line 1 (16px) | Single line, ~24ch budget | Scales to 32px effective; wraps within chip width; chip height expands via wrapContentHeight |
| Chip line 2 (14px) | Single line, ~36ch budget | Scales to 28px effective; wraps; chip height expands |
| Chip height minimum | 64dp | Expands to fit; no minimum override |
| Chip parallax breathing | ±2dp | Disabled (amplitude 0dp) at 200% font scale regardless of reduce-motion setting |
The 200% font-scale breathing disable is independent of the reduce-motion disable. Both conditions separately suppress breathing. At 200%, the text is large enough that minor background oscillation can create uncomfortable visual conflict with the text. The chip at 200% is already a large element; stillness is appropriate.
Chip auto-dismiss at 200% still fires at 12000ms. Extended duration is even more appropriate at large text — the Walker needs more time to parse the chip content when text is large.
6.5 One-handed use while walking
The chip tap target is the chip face — 80% screen width, minimum 64dp tall. This is well above the 48dp minimum. The chip rests in the lower portion of the screen, within thumb reach without grip adjustment. The Walker can:
- Tap the chip to navigate to QuestDetail with one thumb.
- Ignore the chip and continue using TreeViewer — the chip does not block tree interaction (pass-through except its own face).
- The chip auto-dismisses after 12000ms with no interaction required.
No primary action in the cosmos hook moment is in the top 40% of the screen.
6.6 Glance legibility (2-second comprehension)
A Walker glancing at the screen during the cosmos hook moment must immediately understand: something new appeared and I can tap it to learn more.
The chip design achieves this through:
- High contrast quest name at body-large size (dominant text element).
- Region accent left border providing color-coded context.
- Chip geometry (distinct from the tree canvas — rounded rectangle floating above).
- The chip’s own slightly-elevated appearance (alpha tint over dark surface) makes it visually distinct without competing with tree nodes.
7. Continuity into QuestLog
When the Walker taps the chip and navigates to QuestDetail of the newly-revealed quest, two continuity treatments apply in the QuestLog screen beneath:
7.1 New-quest row highlight
When the Walker navigates back from QuestDetail to QuestLog after the cosmos hook event, or if QuestLog is opened directly after the event:
The newly-revealed quest row receives a brief highlight:
- Duration: 2000ms total.
- Visual: the quest row gets a 1dp border using the keystone’s region accent color. The border appears instantly at full opacity, then fades linearly over the last 800ms of the 2000ms window.
- The highlight is not shown at moment of chip-tap — it is shown when the QuestLog becomes visible (either via back-navigation or direct tab switch).
- If reduce-motion is enabled: the border appears for 2000ms at full opacity then disappears instantly (no fade).
7.2 HiddenCountHint decrement animation
The HiddenCountHint composable on QuestLog (shipped in 13-10) shows the count of hidden quests. When the cosmos hook fires and one hidden quest is revealed, the count decrements by 1.
The decrement is not a snap. It is a 200ms count-down animation — the visible number decreases over 200ms via a slot-machine style vertical scroll of the digit. If the count decrements from “1 hidden quest” to “0 hidden quests,” the composable transitions to the zero-state copy (“Some quests unlock when you allocate keystones in the tree.” per the empty-state from faction-and-quest-log.md §3.2). The transition from hint to zero-state is a 200ms cross-fade.
7.3 Multiple simultaneous reveals (future-spec)
Currently impossible: one keystone allocation can only gate one quest (current game content; keystoneRequirement is a single-field gate per the schema). This section specs the case for future-proofing.
If multiple quests become available in a single /quest/available delta:
- Chips are stacked: chip 1 (closest to bottom nav, first revealed quest), chip 2 (above chip 1, 8dp gap), chip 3 (above chip 2, 8dp gap).
- If more than 3 quests: show 3 chips only. The topmost chip reads: ”+ N more — open Quest Log” instead of a quest name.
- Each chip is independently tappable.
- Slide-in animation is staggered: chip 1 at T+0, chip 2 at T+80ms, chip 3 at T+160ms.
- All chips share the same 12000ms auto-dismiss clock (from first chip appearance).
- The cosmos-hook-reveal audio and haptic fire once only, regardless of how many chips appear.
8. Out of scope
The following items are explicitly deferred and are NOT part of this spec’s acceptance matrix:
- Multi-keystone simultaneous allocation — the current UX allocates one keystone at a time. Multi-stack animation is out of scope.
- Achievement-style overlay — explicitly NOT this design. No full-screen overlay, no “Unlocked: [quest name]” badge.
- Audio production — placeholders only (§4). Actual sound design is post-Phase-13.
- Haptic infra wiring — the haptic patterns are specified (§5) but the infra is not wired in Phase 13. This is a polish-pass target.
- Tablet / large-screen layout — Phase 13 is phone-only. Chip geometry on tablets is undefined.
- iOS implementation — Phase 15. The spec is written with Android (Compose) as the implementation target for the first pass. iOS equivalents are noted where the platform APIs differ (§5 haptic iOS note).
- The 13-10 snackbar — the Phase 13-10 snackbar remains in place until the polish pass ships. This spec does not remove it; it defines what replaces it.
9. Acceptance matrix
Numbered checklist for the future polish-pass implementer. Each item is testable to pass or fail.
- 1. Keystone-allocated echo ring fires within 50ms of POST /tree/allocate-keystone 200 response.
- 2. Echo ring expands from 20dp to 80dp radius in exactly 600ms using cubic-bezier(0.4, 0.0, 0.2, 1).
- 3. Echo ring opacity transitions from 0.60 to 0.00 over 600ms (synchronized with radius expansion).
- 4. Echo ring fires exactly once per allocation — not a repeating pulse.
- 5. Margin-line flash appears at exactly T+50ms after POST 200. Holds at full opacity for 300ms. Fades to zero over 200ms (linear easing). Total duration 500ms.
- 6. Margin-line flash color matches the keystone’s region accent token (not a hardcoded gold — future keystones inherit their region color).
- 7. Cosmos hook chip fires only when
/quest/availabledelta is non-empty (no chip on echo-only path). - 8. Chip slide-in duration is exactly 320ms using cubic-bezier(0.4, 0.0, 0.2, 1).
- 9. Chip rests at 16dp above the bottom navigation bar top edge, 80% screen width, horizontally centred.
- 10. Chip parallax breathing oscillates ±2dp vertically over a 6000ms cycle, beginning after slide-in completes.
- 11. Chip auto-dismisses at exactly 12000ms from chip appearance (not from POST 200).
- 12. Chip dismiss animation (timeout or swipe-down) is 200ms using cubic-bezier(0.4, 0.0, 0.2, 1).
- 13. With
isReduceMotionEnabled == true: echo ring is instant-to-rest (200ms total max); chip is a 150ms fade-in; chip parallax breathing is suppressed (amplitude 0dp). - 14. With 200% OS font scale: chip height expands to fit text (no clipping, no truncation); parallax breathing is suppressed (amplitude 0dp) independently of reduce-motion setting.
- 15. TalkBack chip announcement uses
LiveRegionMode.Assertiveand reads: “{quest.name.en} unlocked — tap to open.” - 16. Chip background alpha in high-contrast mode is 70% minimum (default is 18%).
- 17. QuestLog new-quest row highlight (1dp region-accent border, 2000ms with 800ms fade) fires when QuestLog becomes visible after a cosmos hook event.
- 18. HiddenCountHint decrement is a 200ms count-down animation (not a snap); zero-state transition is a 200ms cross-fade.
10. State diagram
Mermaid diagram of the cosmos hook state machine from keystone-tap to chip-resolved:
stateDiagram-v2 [*] --> IDLE : Walker on TreeViewer
IDLE --> KEYSTONE_CONFIRMATION : Walker taps unlocked keystone KEYSTONE_CONFIRMATION --> IDLE : Walker taps Cancel KEYSTONE_CONFIRMATION --> POST_200_KEYSTONE_ALLOCATED : Walker confirms, POST 200
POST_200_KEYSTONE_ALLOCATED --> AWAITING_QUEST_DELTA : QuestRefreshBus.signal() fires POST_200_KEYSTONE_ALLOCATED --> POST_200_KEYSTONE_ALLOCATED : echo ring animating (600ms)\nmargin-line flash animating (500ms)
AWAITING_QUEST_DELTA --> DELTA_EMPTY : /quest/available diff is empty AWAITING_QUEST_DELTA --> DELTA_NON_EMPTY : /quest/available diff has new quest(s)
DELTA_EMPTY --> IDLE : Standard flow, no chip DELTA_NON_EMPTY --> CHIP_ACTIVE : chip slides up (320ms)
CHIP_ACTIVE --> CHIP_ACTIVE : parallax breathing (6s cycle)\n12s countdown
CHIP_ACTIVE --> QUEST_DETAIL : Walker taps chip → navigate
CHIP_ACTIVE --> DISMISSED : 12000ms elapsed CHIP_ACTIVE --> DISMISSED : Walker swipes chip down
DISMISSED --> IDLE : chip slides out (200ms)
QUEST_DETAIL --> QUEST_LOG : Walker navigates back QUEST_LOG --> QUEST_LOG : new-quest row highlight (2s)\nHiddenCountHint decrement (200ms)
note right of POST_200_KEYSTONE_ALLOCATED echo ring: 600ms (cubic-bezier 0.4,0,0.2,1) margin-line flash: 500ms (300ms hold + 200ms linear fade) haptic: keystone-allocated (LongPress) audio: keystone-allocated tone (400Hz, 800ms total) end note
note right of CHIP_ACTIVE chip: 80% width, 64dp min-height, 12dp corners background: region accent at 18% alpha left border: 3dp region accent line 1: quest.name.en (--type-body-lg) line 2: "A path you could not see before." (--type-body) haptic: cosmos-hook-reveal pattern (200ms heavy → 300ms silence → 80ms medium) audio: cosmos-hook-reveal sound (1.5-2.0s low+high overtone) end noteThis spec is W-level autonomous. Decisions made within ui-designer authority: chip duration (12000ms), revelation copy (“A path you could not see before.”), audio cue character (low fundamental + emerging overtone, not fanfare), haptic pattern character (heavy-pause-medium — distinguishable from notification and from keystone-allocated), reduce-motion fallback behavior (instant + 150ms fade-in for chip), font-scale parallax-disable threshold (200% = 0dp amplitude regardless of reduce-motion), high-contrast chip alpha minimum (70%). Logged to ops/decisions/2026-05-20-ui-cosmos-hook-spec.md.