RIVE PRODUCTION SPEC

Documentation for Vitto

Vitto Rive Production Specification

Complete Guide for Building the .riv File in Rive.app

Version: 1.0 — Production Ready Target: Rive Editor (rive.app) + @rive-app/canvas runtime Date: March 2026 Based on: Vitto Animation Bible v8, SVG Prototype v9


1. Overview

This document specifies exactly how to build Vitto's animated avatar in Rive's editor. The character is a steampunk aviator cat with 14 emotional states, each with unique continuous micro-animations, color palettes, and personality behaviors.

Key deliverable: A single .riv file containing:


2. Artboard Setup

Canvas

Layer Order (back to front)

1. tail              — Bone-driven path, stroke only
2. ears_group        — Left/right ear pairs (outer + inner)
3. head              — Main ellipse with fur texture fill
4. cheek_bumps       — Two subtle ellipses for face volume
5. goggles           — Forehead goggles group (frames, lenses, bridge, rivets)
6. headphones        — Headband arc + ear pads group
7. scarf             — Patterned neck scarf with tassels
8. blush_spots       — Two pink ellipses (opacity animated)
9. eyes_group        — Left/right eye assemblies
10. nose             — Small triangular path
11. mouth_group      — Mouth curves, open mouth, tongue, teeth
12. whiskers         — 6 line elements (3 per side)
13. eyebrows         — 2 curved paths (opacity animated)
14. particles_layer  — Emitter system for sparkles/stars

3. Character Construction

3.1 Head & Body

Head ellipse: cx:130, cy:152, rx:82, ry:76

Cheek bumps: Two ellipses for volume

3.2 Ears (Bone-Driven)

Each ear = outer triangular path + inner triangular path. Use bones so ears can be rotated/translated independently.

Left ear bone at (68, 100):

Right ear bone at (192, 100):

Per-mood ear positions (expressed as path target shapes — see Section 5 for full data).

3.3 Eyes (Critical — 80% of Emotional Work)

Each eye is a complex assembly. Use clipping masks for eyelid closure.

Eye structure (left eye at translate(98, 136), right at translate(162, 136)):

eye_assembly/
├── clip_mask (ellipse: rx:26, ry:22 — animated for blink/squint)
├── eye_white (ellipse: rx:24, ry:22)
│   └── Fill: radial gradient rgba(248,244,255,0.98) → rgba(235,230,250,0.85)
├── iris (ellipse: rx:14.5, ry:17)
│   ├── Fill: radial gradient #4488cc → #1a3060
│   └── Inner ring detail: stroke rgba(255,255,255,0.15), 0.8w
├── pupil (ellipse: rx:5, ry:12, fill: #06060c)
│   └── Cat slit shape — vertical ellipse
├── shine_primary (circle: r:3.5, cx:-7, cy:-7, white, opacity 0.95)
├── shine_secondary (circle: r:1.8, cx:5, cy:3, white, opacity 0.4)
└── shine_tertiary (circle: r:0.8, cx:-2, cy:8, white, opacity 0.6)

Eye animation properties (all must be independently animatable):

Property Range What It Controls
ewRy 0-24 Eye white vertical radius (blink/squint)
irRx, irRy 8-18 Iris size
puRx, puRy 2-8 / 6-16 Pupil size (dilation)
puCx, puCy -6 to +6 Pupil position (gaze direction)
clip_ry 0-22 Clip mask height (eyelid closure)
shine_scale 0-1.5 Eye shine size multiplier

Eye shine rules:

3.4 Goggles (Static with Subtle Animation)

Aviator goggles rest on forehead. Mostly static but shift with head tilt.

Left goggle: Circle frames at (90, 92), r:13, stroke #8b7355, 2.8w

Right goggle: Circle frames at (170, 92), r:13

Bridge: Line from (103,92) to (157,92), stroke #8b7355, 2.2w

Straps: Short lines connecting to head edges

3.5 Headphones (Bone-Driven)

Slight bounce with head movement.

Headband: Arc path M80,75 Q130,40 180,75

Ear pads: Ellipses at (65,140) and (195,140), rx:11, ry:14

Connection bands: Lines from headband endpoints to ear pads

3.6 Scarf

Patterned neck scarf with tassels.

Main shape: Path defining curved collar area

Tassels: Triangular path hanging below

3.7 Mouth

Resting: Two curved paths forming a subtle cat smile

Open mouth group (opacity animated):

Tongue (opacity animated):

Teeth (opacity animated):

3.8 Whiskers

6 line elements, 3 per side. Starting points fixed, endpoints animated.

Whisker Start Default End
w1 (top-left) (75, 155) (45, 148)
w2 (mid-left) (75, 168) (40, 170)
w3 (bot-left) (75, 181) (45, 192)
w4 (top-right) (185, 155) (215, 148)
w5 (mid-right) (185, 168) (220, 170)
w6 (bot-right) (185, 181) (215, 192)

3.9 Tail

Bone-driven curved path, stroke only (8w, round cap).


4. State Machine: MoodController

4.1 Inputs

Input Name Type Range Purpose
moodIndex Number 0-13 Primary mood selector
gazeX Number -1 to 1 Mouse/gaze horizontal position
gazeY Number -1 to 1 Mouse/gaze vertical position
intensity Number 0-1 Animation intensity (reduced motion support)
isSpeaking Boolean — Triggers mouth movement overlay

4.2 Mood Index Mapping

Index Mood Description
0 neutral Relaxed idle — ear flicks, gentle sway
1 focused Hunting mode — scanning pupils, still body
2 cheerful Happy purring — body bounce, love-blinks
3 empathetic Gentle concern — slow nods, leaning in
4 curious Head tilt — dramatic tilts, darting pupils
5 analytical Processing — micro-nods, reading pupils
6 celebratory PARTY — full bounce, ear wiggles, sparkles
7 apologetic Guilt — drooping head, guilty peeks
8 inspired Lightbulb — growing excitement, pulsing
9 urgent Alert — rapid vibration, adrenaline pupils
10 playful Wiggly — figure-8 sway, tongue pops, winks
11 confused Tilted — extreme tilts, asymmetric eyes
12 proud Smug — chin up, slow blinks, chest puff
13 sleepy Drowsy — progressive closing, snap-awakes

4.3 State Machine Architecture

                    ┌─────────────┐
                    │   Entry     │
                    └──────┬──────┘
                           │
                    ┌──────▼──────┐
                    │  Neutral    │ ← Default state
                    │  (Idle Loop)│
                    └──────┬──────┘
                           │
              ┌────────────┼────────────┐
              │            │            │
        moodIndex    moodIndex    moodIndex
        changes      changes      changes
              │            │            │
     ┌────────▼──┐  ┌─────▼────┐  ┌───▼─────────┐
     │ ProcessBeat│  │ProcessBeat│  │ ProcessBeat │ ... (for all 14)
     │ → Focused │  │→ Cheerful │  │→ Celebratory│
     │ (Idle Loop)│  │(Idle Loop)│  │ (Idle Loop) │
     └───────────┘  └──────────┘  └─────────────┘

Each state transition goes through a Processing Beat blend:

  1. NOTICE (0-80ms): Eyes widen briefly
  2. PROCESS (80-200ms): Slight head squash
  3. REACT (200-400ms): Eyes move to new expression
  4. COMMIT (400-520ms): Ears, mouth, head tilt follow
  5. SETTLE (520-700ms): Whiskers, blush, tail settle

4.4 Transition Blend Times

From → To Blend Duration Easing
Any → Any (default) 700ms Ease-in-out
Any → Urgent 300ms Spring
Any → Celebratory 500ms Bounce
Any → Sleepy 1200ms Ease-out (slow fade)
Sleepy → Any 400ms Spring (snap awake)

5. Per-Mood Animation Specifications

5.1 Color Palettes Per Mood

Each mood has 4 gradient systems that transition together:

Mood Face Gradient Ear Inner Iris Gradient Scarf Gradient
neutral #b8a898→#7a6a5a→#3a2a1a #d4a8a0→#a87070 #4488cc→#1a3060 #8b6f47→#5a4a3a
focused #a0a8b8→#5a6a7a→#1a2a3a #bcc8d8→#7a8aa8 #3366aa→#0a2040 #6a7a8a→#3a5060
cheerful #d4b888→#b8864a→#6a4020 #f0d4c8→#d8a894 #55aadd→#2a5080 #c89860→#a05a30
empathetic #c0a8b8→#8a6a7a→#3a1a2a #e4d0e0→#b8a8c0 #5577bb→#1a2a55 #9a7a9a→#6a5a7a
curious #a8c8b8→#5a8a7a→#1a4a3a #c8ffe8→#80c8a8 #44aaaa→#1a4050 #6a9a8a→#3a6a5a
analytical #a8b8c8→#5a6a8a→#1a2a4a #c0d0e0→#8898b0 #3366bb→#0a2050 #6a7a9a→#3a5070
celebratory #e8d088→#c8a040→#7a6010 #fff0c0→#e0c880 #cc8833→#804010 #d4a840→#a07a20
apologetic #c0b0c8→#8a7a9a→#3a2a4a #d8c8e0→#a898b8 #7766aa→#3a2a60 #8a7a9a→#5a4a6a
inspired #c8a8d8→#8a5aaa→#3a1a5a #e8d0f0→#c0a0d8 #8855cc→#4a1a80 #a870c8→#7a40a0
urgent #d8a0a0→#aa4040→#5a1010 #f0c0c0→#d08080 #cc3333→#801010 #c04040→#8a2020
playful #a8d8b8→#5aaa7a→#1a5a3a #c8f0d8→#80c8a0 #33aa66→#105030 #6aaa7a→#3a7a5a
confused #d8c0a0→#aa8850→#5a4a10 #f0e0c0→#d0b880 #aa7733→#604010 #c0a050→#8a7030
proud #e0d0a0→#b8a050→#6a5a10 #f8f0c8→#d8c880 #aa8833→#604810 #c8a850→#8a7830
sleepy #b8b0c0→#7a7088→#2a2030 #d0c8d8→#a098b0 #6660aa→#2a2050 #8a8098→#5a5068

5.2 Eye Geometry Per Mood

Mood ewRy (openness) irRx/irRy puRx/puRy Notes
neutral 22 14.5/17 5/12 Default relaxed
focused 11 13.5/10 2.5/8 Narrowed slits, small pupils
cheerful 10 12.5/8 4/6 Squinted with joy, lower lid up
empathetic 24 15.5/20 8.5/16 Wide, huge dilated pupils
curious 23 (L), 19 (R) 14.5/18 6.5/14 Asymmetric! Left wider
analytical 14 (L), 20 (R) 13/12 3/9 Left squinted, right open
celebratory 6 11/5 5/4 Nearly shut with joy
apologetic 18 13/15 5/11 Looking down/away
inspired 25 16/19 7/15 Wide and getting wider
urgent 24 14/18 3/14 Wide, pinpoint pupils
playful 20 (L), 14 (R) 14/16 5/12 Right eye winking
confused 22 (L), 16 (R) 14/17 5.5/12 Asymmetric sizes
proud 14 13/11 4/9 Half-closed, smug
sleepy 8 12/6 4.5/5 Nearly closed, heavy lids

5.3 Continuous Micro-Animation Loops (Per State)

Each mood state in Rive should contain a looping timeline with these behaviors:

neutral (Idle Loop)

0.0s: Ear flick left (sharp 5px up, settle over 200ms)
2.0s: Gentle head sway (2.5deg sine at 0.4Hz, continuous)
3.0s: Ear flick right (mirror of left)
4.0s: Slow blink (both eyes, 200ms down, 200ms up)
6.0s: Chin stretch (head lifts 2px, settles over 500ms)
8.0s: Loop
Continuous: Tail sway at 0.8x speed, whisker 1.5px oscillation

focused (Idle Loop)

0.0s: Pupil scan start (linear left-to-right, 5px range, 1s duration)
1.0s: Pupil scan return (linear right-to-left, 1s)
2.0s: Ear burst twitch (both ears 3px, 6x rapid, 500ms total)
4.0s: Loop
Continuous: Body PERFECTLY still, whiskers pushed forward (3.5 value), blink rate near zero

cheerful (Idle Loop)

0.0s: Body bounce starts (5px vertical at 3Hz)
0.0s: Purring vibration (0.6px horizontal at 16Hz, continuous)
0.8s: Love-blink (both eyes to 0.7 closure, 400ms cycle)
1.5s: Head tilt peak left (7deg)
2.0s: Ears alternate (left up 4px, right down, 2.2Hz/2.8Hz)
2.5s: Love-blink again
3.0s: Head tilt peak right
3.3s: Loop
Continuous: Tail fast 2.5x speed

empathetic (Idle Loop)

0.0s: Slow understanding nod begins (3px down over 1s)
1.0s: Nod returns (1s up)
1.5s: Head tilt (4deg to left, 800ms)
2.0s: Pupils drift to center-down (-0.5 X, 1.5 Y)
3.0s: Head tilt (4deg to right, 800ms)
4.0s: Loop
Continuous: Slow breathing (0.85 base + 0.1 amp at 0.4Hz), body lean 1.5px forward, tail 0.4x

curious (Idle Loop)

0.0s: Head tilt peak right (10deg, snappy)
0.3s: Pupil dart (5px right, snap)
0.5s: Hold (pupils pause 300ms)
0.8s: Double-blink (two quick blinks, 100ms each)
1.0s: Head tilt peak left (10deg, snappy)
1.3s: Pupil dart (5px left, snap)
1.5s: Hold
1.8s: Loop
Continuous: Ears independent (left forward 8px, right back), body leans with tilt 2.5px, tail 1.5x

analytical (Idle Loop)

0.0s: Micro-nod (1.5px down, sharp, 250ms)
0.25s: Micro-nod return (250ms)
0.5s: Reading pupil sweep (left→right 4px, 400ms)
0.9s: Reading pupil drop (2px down, 100ms)
1.0s: Reading pupil return (left→right again, 400ms)
1.5s: Left eye squint cycle begins (winkL to 0.5 over 1.5s)
3.0s: Left eye opens (500ms)
3.5s: Loop
Continuous: Head perfectly level, whiskers forward (3px), tail dead still (0x)

celebratory (Idle Loop)

0.0s: Full body bounce UP (8px, bounce easing, 83ms)
0.08s: Body bounce DOWN (squash: headRx+3, headRy-3)
0.17s: Eyes pop open/shut (0.85 closure, spring easing, 167ms cycle)
0.0s: Ear wiggle (6px, independent L/R at 8Hz)
0.0s: Head sway (6deg, synced with bounce)
0.5s: Sparkle particle burst (3 particles from top)
1.0s: Sparkle burst again
1.5s: Sparkle burst again
2.0s: Loop
Continuous: Eye shines pulse (0.4 amplitude), tail maximum 3.5x speed

apologetic (Idle Loop)

0.0s: Start drooping (head drops 1px)
1.0s: Continue drooping (head at -2px, ears flatten -1px)
2.0s: Guilty peek up (pupils snap to center-up for 500ms)
2.5s: Eyes dart back down-left (pupils to -3, 2.5)
3.0s: Nervous whisker twitch (2px, 200ms burst)
4.0s: Head at -3px, ears at -2px
5.0s: Another guilty peek (briefer, 300ms)
6.0s: Loop (droop resets gently)
Continuous: breathScale 0.92, tail barely moving 0.15x

inspired (Idle Loop — Progressive)

NOTE: This is PROGRESSIVE — values build over time, don't reset each loop!
0.0s: Begin pupil dilation increase (+0.05/s)
0.0s: Begin head lift increase (+0.3px/s)
0.0s: Begin ear perk increase (+0.2px/s)
2.0s: Building vibration starts (grows from 0 to 0.4px)
0.0s: Eye shine pulse (0.5 amplitude at 3.5Hz, continuous)
Caps: pupilDilation max 1.5, headLift max 3, earPerk max 2, vibration max 0.4
Continuous: Tail 1.8x speed

urgent (Idle Loop)

0.0s: Rapid vibration (1.2px X at 22Hz, 1.2px Y at 20Hz)
0.0s: Pupil surge (dilation 0.8→1.3 at 10Hz)
0.0s: Ear swivel (5px at 12/11Hz L/R)
0.0s: Head sharp tilt (3deg at 3Hz)
0.0s: Whisker splay (3px wide + 2px twitch at 18Hz)
All continuous — no distinct phases, pure controlled chaos
Continuous: Breath held tense (0.95), tail 2.8x speed

playful (Idle Loop)

0.0s: Body figure-8 starts (4px X at 2Hz, 4px Y at 2.5Hz)
0.0s: Tilt wiggle (5deg at 1.5Hz)
1.5s: Tongue pop (0.8 opacity, 300ms)
2.0s: Left eye wink (full close 0.95, hold 400ms, open over 300ms)
2.5s: Butt-wiggle (2px side-lean, 500ms)
3.5s: Loop
Continuous: Ears jaunty angles (4px oscillation), tail fast whip 2.5x

confused (Idle Loop)

0.0s: Extreme tilt right (13deg, 600ms)
0.0s: Left eye squints (winkL 0.4), right eye wide
0.6s: SNAP — tilt left (13deg, 200ms — fast!)
0.6s: Switch — right eye squints, left wide
0.8s: Head micro-shake (2deg at 8Hz, 400ms burst)
1.2s: Pupils drift independently (X at 1.5Hz, Y at 2Hz)
1.5s: SNAP back right
2.0s: Loop
Continuous: One ear up one down (5px, switching), tail slow 0.4x

proud (Idle Loop — Progressive)

0.0s: Chin begins rising (builds to 5px headLift over 4s)
1.5s: First slow deliberate blink (0.7 closure, 800ms total — SLOW)
3.5s: Smug tilt settles (constant 3deg offset)
5.0s: Second deliberate blink
Caps: headLift max 5px
Continuous: breathScale 1.05 (chest puff), whiskers forward 2px, tail dignified 0.5x

sleepy (Idle Loop — Progressive)

NOTE: Eyes progressively CLOSE over time!
0.0s: Eyes begin closing (winkL/winkR climb toward 0.95)
0.0s: Head nodding begins (2.5px oscillation at 0.5Hz)
3.0s: Nodding amplitude grows (to 4.5px)
5.0s: SNAP-AWAKE! Eyes suddenly open (wink drops to 0.1), hold 500ms
5.5s: Eyes begin slowly closing again (2s to return to near-shut)
7.0s: Yawn (mouth opens, tongue flash 0.6 for 400ms)
7.5s: Continue drowsy cycle
Continuous: Slow breathing (0.3Hz), ears droop (-3px progressive), tail barely moving 0.08x

6. Gaze Tracking System

Input Processing

The runtime provides gazeX and gazeY as normalized values from -1 to 1 (mouse position relative to avatar center).

Pupil Response

pupil_offset_x = gazeX * 5 * (1 - mood_intensity)
pupil_offset_y = gazeY * 4 * (1 - mood_intensity)

Where mood_intensity reduces gaze tracking when the mood's own pupil animation is strong:

Eye Shine Tracking

Shines offset in the OPPOSITE direction of pupil movement (light reflection):

shine_offset_x = -pupil_offset_x * 0.3
shine_offset_y = -pupil_offset_y * 0.3

7. Speaking Overlay

When isSpeaking is true, overlay a mouth animation:


8. Particle System (Rive Emitters)

Celebratory Sparkles

Inspired Stars

Playful Bounces


9. Aura/Glow System

Each mood has an ambient glow around the character:

Implementation: Radial gradient behind the character, animated opacity.

Mood Aura Color Glow Color Pulse Speed
neutral rgba(122,106,90,.28) rgba(122,106,90,.2) 3s
focused rgba(90,106,122,.3) rgba(90,106,122,.22) 2.5s
cheerful rgba(184,134,74,.38) rgba(200,160,100,.28) 2s
celebratory rgba(200,160,64,.45) rgba(220,180,80,.35) 1.2s
urgent rgba(200,80,80,.4) rgba(220,60,60,.32) 1.2s
sleepy rgba(100,90,120,.2) rgba(80,70,100,.15) 5s

Aura animation: Scale oscillation (1.0 → 1.13) with opacity fade (0.15 → 0.45), at mood-specific pulse speed.


10. Reduced Motion Support

When intensity input is set to 0:

Intermediate values (0-1) scale all animation amplitudes proportionally.


11. Export Requirements

File Spec

Runtime Integration

The Angular component will:

  1. Load the .riv file
  2. Create a Rive instance with the "MoodController" state machine
  3. Set moodIndex input when mood changes
  4. Update gazeX/gazeY on mouse move
  5. Toggle isSpeaking during AI responses
  6. Set intensity based on prefers-reduced-motion media query

12. Testing Checklist

Before shipping, verify: