Appearance
Cavai Theme Branding Enhancement
Date: 2026-03-28 Scope: Enhance the Cavai theme with brand personality — mascot (Bubbles), star decorations, gradient accents, and micro-animations. One theme, not two. Professional enough for daily use, but with character.
1. Design Decisions
All decisions made during brainstorming:
| Question | Decision |
|---|---|
| Scope level | B (Merkbart) — one Cavai theme with personality |
| Mascot placements | All 7 locations |
| Stars usage | B (decorative accents in fixed places) + future vision of per-session wandering |
| Gradient usage | D (mix — full on small accents, subtle on surfaces, never on text backgrounds) |
| Animation intensity | B (behagelig levende — 3-5s cycles, moderate mascot animations) |
| Implementation | C (Hybrid — CSS for decorative, one CavaiMascot.vue for interactive mascot) |
2. Architecture
2.1 New Files
src/
├── components/common/CavaiMascot/
│ └── CavaiMascot.vue # Single mascot component, mode-driven
├── styles/
│ └── _cavai-decorations.scss # Stars, gradients, animations (cavai-only, SCSS for $size-* vars)2.2 Modified Files
src/styles/theme.css # New cavai gradient/star tokens
src/styles/_pages.scss # Login page enhancements
src/pages/.../Configuration/ConfigurationPanel.vue # Use CavaiMascot instead of raw <img>
src/pages/Chatbots/components/BuildProgress.vue # Publish celebration
src/pages/Chatbots/components/CavaiFlow/CavaiFlow.vue # Flow editor empty state
src/components/common/FileUploader.vue # Upload mascot
src/components/common/ImageInput.vue # Upload mascot (image variant)
src/components/common/MainTable.vue # Empty list mascot
src/pages/Authorization/SignInPage/index.vue # Login page (only if template changes needed beyond CSS)2.3 Conditional Loading
_cavai-decorations.scss is imported in the app's SCSS entry point alongside other style partials. All rules are scoped under [data-theme="cavai"]. No CSS reaches other themes. This follows the existing pattern — the codebase uses _partialname.scss convention for imported style fragments.
3. New Tokens
Added to [data-theme="cavai"] in theme.css:
css
/* Cavai gradient tokens — decoration-layer, not semantic. Prefixed cavai- to signal theme-exclusive use. */
--cavai-gradient: linear-gradient(135deg, #FF6B9E, #FFA07A, #FFDB58);
--cavai-gradient-subtle: linear-gradient(135deg, rgba(255,107,158,.06), rgba(255,160,122,.04), rgba(255,219,88,.02));
--cavai-gradient-accent: linear-gradient(135deg, rgba(255,107,158,.15), rgba(255,160,122,.10), rgba(255,219,88,.06));
/* Cavai decorative tokens — distinct from semantic --brand-coral (#e8606a, used for UI accents).
These are the brighter brand colors from cavai.com, used only for decorative elements. */
--cavai-star-color: #FFDB58;
--cavai-star-glow: rgba(255,219,88,.3);Note: The existing --brand-coral token (#e8606a) is used for interactive UI accents. No new --cavai-coral token is needed — decorative elements that need coral use --brand-coral directly.
4. Gradient Usage
Following the "D (mix)" decision:
| Strength | Token | Where |
|---|---|---|
| Full | --cavai-gradient | Tab-stripe/active tab underline, small badges, active button accents |
| Accent | --cavai-gradient-accent | Card header accents, sidebar hover highlights, selected state backgrounds |
| Subtle | --cavai-gradient-subtle | Flow editor background wash, config panel background, large surfaces |
Never on text backgrounds where readability matters. Only decorative or small accent surfaces.
5. Star Decorations (CSS-only)
Stars use the ✦ character placed via ::before/::after pseudo-elements on selected components, scoped to [data-theme="cavai"].
Placement Targets
.title-sectioninCard.vue(1-2 stars near card section titles).empty-stateinConfigurationPanel.vue(around mascot).signin_pagein_pages.scss(login page hero area)- Empty state areas in
MainTable.vue
Animation
css
@keyframes cavai-twinkle {
0%, 100% { opacity: 0.3; }
50% { opacity: 1; }
}
@keyframes cavai-glow-pulse {
0%, 100% { filter: drop-shadow(0 0 2px var(--cavai-star-glow)); }
50% { filter: drop-shadow(0 0 6px var(--cavai-star-glow)); }
}Timing: 3-5s infinite ease-in-out, staggered with animation-delay for natural feel.
Reduced Motion
All animations in _cavai-decorations.scss must respect prefers-reduced-motion:
scss
@media (prefers-reduced-motion: reduce) {
[data-theme="cavai"] {
*, *::before, *::after {
animation-duration: 0s !important;
animation-delay: 0s !important;
transition-duration: 0s !important;
}
}
}Future Extension
Stars can eventually "wander" — different elements get stars on different sessions. This is a future enhancement, not in initial scope.
6. CavaiMascot.vue Component
Interface
vue
<CavaiMascot mode="peek" size="md" :opacity="0.18" />Props
| Prop | Type | Default | Description |
|---|---|---|---|
mode | String | 'peek' | Pose and animation behavior |
size | String | 'md' | sm (32px), md (64px), lg (128px) |
opacity | Number | 1 | Override opacity (config panel uses 0.18) |
dragState | String | 'idle' | Only for upload mode: 'idle', 'over', or 'dropped' |
Modes
| Mode | Animation | Auto-hide | Use Case |
|---|---|---|---|
peek | Bob up-down (4s cycle), peeking over edge | No | Config empty, empty lists |
celebrate | Slide-in from bottom + star-burst | Yes (3-4s) | Publish success |
wave | Waving motion, pointing toward action | No | Flow editor empty |
think | Pulsing glow + thinking animation | No | Loading spinner |
upload | Reacts to dragState prop: idle=peek, over=bounce, dropped=celebrate | No | Upload/drag zones |
Theme Detection
Uses the existing useTheme composable (src/composables/useTheme.ts) to reactively access the current theme. Renders nothing (v-if="isCavaiTheme") when theme is not cavai.
Implementation
- Uses existing
bubbles.pngasset (src/assets/images/bubbles.png) - CSS
transform+opacityanimations for poses — no sprite sheets - Auto-hide modes use
setTimeout+ fade-out transition - Emits
hiddenevent when auto-hide completes (for parent cleanup) - Respects
prefers-reduced-motion— skips animations, shows static pose
Pattern Compliance
Follows existing component patterns:
- Lives in
src/components/common/CavaiMascot/ - Standard Vue 2 SFC with
<script lang="ts">and<style scoped lang="scss"> - Props-driven, no Vuex dependency
- Scoped styles only
7. The 7 Mascot Placements
7.1 Config Panel Empty State
File: src/pages/Chatbots/components/BuilderVisuals/Configuration/ConfigurationPanel.vueCurrent: Raw <img> of bubbles.png at 18% opacity with mascot-bob animation (local @keyframes in scoped styles). Change: Replace <img> with <CavaiMascot mode="peek" size="lg" :opacity="0.18" />. Remove the .mascot-peek, .mascot-img, and @keyframes mascot-bob CSS from the component's scoped styles (these move into CavaiMascot). Add 2-3 twinkle stars around mascot via _cavai-decorations.scss.
7.2 Publish Success Celebration
File: src/pages/Chatbots/components/BuildProgress.vueBehavior: When build completes successfully, show <CavaiMascot mode="celebrate" size="md" /> alongside the existing progress bar completion. Auto-hides after 3-4 seconds. Non-blocking — appears as an overlay near the progress indicator.
7.3 Flow Editor Empty State
File: src/pages/Chatbots/components/CavaiFlow/CavaiFlow.vueBehavior: <CavaiMascot mode="wave" size="lg" /> shown when the operator list is empty (no operators on canvas). Centered in the canvas area with helper text. Disappears when first operator is added.
7.4 Upload / Drag-and-Drop Zone
Files: src/components/common/FileUploader.vue, src/components/common/ImageInput.vueBehavior: <CavaiMascot mode="upload" size="md" :drag-state="dragState" /> placed in the drop zone area. Parent tracks drag events and passes state as prop:
idle→ subtle peekover(dragover) → bounce updropped(file dropped) → short celebrate
7.5 Empty Lists (Creatives, Campaigns)
File: src/components/common/MainTable.vue (uses Vuetify v-data-table) Behavior: In the no-data slot of v-data-table, add <CavaiMascot mode="peek" size="sm" /> with encouraging text. Only shown when Cavai theme is active — other themes see standard empty text.
7.6 Loading Spinner
Files: Components using v-progress-circular (e.g., ChatbotBuilder.vue, BulkDeliveryExportDialog.vue) Behavior: Wrap existing v-progress-circular usage with a conditional: when Cavai theme is active, show <CavaiMascot mode="think" size="md" /> instead. Other themes see the normal spinner. Start with the main builder loading state in ChatbotBuilder.vue.
7.7 Login Page
Files: src/styles/_pages.scss, src/pages/Authorization/SignInPage/index.vueCurrent: bubbles.svg as CSS background-image in .signin_page__bubbles. Change: Add twinkle stars via pseudo-elements on .signin_page (scoped to [data-theme="cavai"]), subtle gradient wash over hero area. CSS-only enhancement — no component swap needed.
8. Animation Keyframes
All defined in _cavai-decorations.scss, scoped under [data-theme="cavai"]:
css
@keyframes cavai-twinkle {
0%, 100% { opacity: 0.3; }
50% { opacity: 1; }
}
@keyframes cavai-bob {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-4px); }
}
@keyframes cavai-glow-pulse {
0%, 100% { filter: drop-shadow(0 0 2px var(--cavai-star-glow)); }
50% { filter: drop-shadow(0 0 6px var(--cavai-star-glow)); }
}
@keyframes cavai-slide-in {
from { transform: translateY(100%); opacity: 0; }
to { transform: translateY(0); opacity: 1; }
}
@keyframes cavai-star-burst {
0% { transform: scale(0); opacity: 1; }
70% { transform: scale(1.2); opacity: 0.8; }
100% { transform: scale(1); opacity: 0; }
}Timing (B — behagelig levende):
- Ambient loops (twinkle, bob, glow):
3-5s infinite ease-in-out - One-shot transitions (slide-in):
0.4s ease-out - Effects (star-burst):
0.6s ease-out forwards - Celebrate auto-hide: 3-4s total, fade-out in last 0.5s
9. Constraints
- Commit first: All existing ~71 file changes must be committed in small, logical commits before any Cavai theme implementation begins. Clean git state for easy rollback.
- Cavai-only: All new CSS and components render nothing / apply no styles outside
[data-theme="cavai"]. - No performance impact: CSS animations use
transformandopacityonly (GPU-composited). No layout thrash. - Existing patterns: Follow Vue 2 SFC conventions, scoped SCSS, semantic token usage. No new architectural patterns.
- Asset reuse: Use existing
bubbles.pngandbubbles.svg. No new image assets unless SVG modifications are needed. - Reduced motion: All animations respect
prefers-reduced-motion: reduce. Static poses shown instead. - Cleanup: When replacing existing mascot implementations (ConfigurationPanel), remove the old CSS entirely — no dead code.
10. Implementation Priority
Phase 1 (well-defined, refactoring existing code):
- Tokens in
theme.css _cavai-decorations.scsswith keyframes and star decorationsCavaiMascot.vuecomponent- 7.1 Config panel (refactor existing mascot)
- 7.7 Login page (enhance existing SVG)
Phase 2 (new integrations):
- 7.2 Publish celebration
- 7.3 Flow editor empty state
- 7.5 Empty lists
Phase 3 (interactive):
- 7.4 Upload drag-and-drop
- 7.6 Loading spinner replacement
- Gradient accents on UI elements (tab-stripes, card headers, etc.)