|
| 1 | +# Rule: Responsive Device Sizing (Tailwind 4 based) |
| 2 | + |
| 3 | +## Description |
| 4 | +When a user requests a video for a specific device class (mobile, tablet, desktop), all component dimensions must be scaled appropriately. rustmotion pixel values are **absolute render pixels**, NOT CSS logical pixels. A phone screen renders 1080px across ~375 CSS points — so everything is at ~3x density. A 48px font renders as ~16pt on screen, which is body text size, not a headline. |
| 5 | + |
| 6 | +## Conversion formula |
| 7 | + |
| 8 | +The scaling factor from rustmotion pixels to perceived CSS-like size: |
| 9 | +- **Mobile 1080×1920**: divide by 3 to get equivalent CSS px (e.g., 96px render = 32px CSS = `text-3xl`) |
| 10 | +- **Desktop 1920×1080**: divide by ~1.5 (e.g., 48px render = 32px CSS = `text-3xl`) |
| 11 | +- **Square 1080×1080**: divide by ~2.5 |
| 12 | + |
| 13 | +**Always think in Tailwind 4 type scale first, then multiply by the device factor.** |
| 14 | + |
| 15 | +## Device aliases |
| 16 | + |
| 17 | +| User says | Device class | Resolution | |
| 18 | +|---|---|---| |
| 19 | +| "mobile", "phone", "portrait", "story", "reel", "TikTok" | **Mobile 9:16** | 1080×1920 | |
| 20 | +| "desktop", "landscape", "YouTube", "presentation" | **Desktop 16:9** | 1920×1080 | |
| 21 | +| "tablet", "iPad" | **Tablet** | 1080×1440 or 1200×1600 | |
| 22 | +| "square", "Instagram", "LinkedIn" | **Square 1:1** | 1080×1080 | |
| 23 | + |
| 24 | +## Tailwind 4 type scale → rustmotion pixels |
| 25 | + |
| 26 | +Reference: Tailwind CSS default font sizes. |
| 27 | + |
| 28 | +| Tailwind class | CSS size | Mobile (×3) | Desktop (×1.5) | Square (×2.5) | Usage | |
| 29 | +|---|---|---|---|---|---| |
| 30 | +| `text-sm` | 14px | 42 | 21 | 35 | Micro labels | |
| 31 | +| `text-base` | 16px | 48 | 24 | 40 | Small / label text | |
| 32 | +| `text-lg` | 18px | 54 | 27 | 45 | Card labels | |
| 33 | +| `text-xl` | 20px | 60 | 30 | 50 | Body text | |
| 34 | +| `text-2xl` | 24px | 72 | 36 | 60 | Large body | |
| 35 | +| `text-3xl` | 30px | 90 | 45 | 75 | Subtitle | |
| 36 | +| `text-4xl` | 36px | 108 | 54 | 90 | Title | |
| 37 | +| `text-5xl` | 48px | 144 | 72 | 120 | Big title | |
| 38 | +| `text-6xl` | 60px | 180 | 90 | 150 | Hero headline | |
| 39 | +| `text-7xl` | 72px | 216 | 108 | 180 | Impact counter | |
| 40 | +| `text-8xl` | 96px | 288 | 144 | 240 | Full-screen number | |
| 41 | +| `text-9xl` | 128px | 384 | 192 | 320 | Giant display | |
| 42 | + |
| 43 | +## Tailwind 4 spacing scale → rustmotion pixels |
| 44 | + |
| 45 | +Reference: Tailwind CSS default spacing (4px base unit). |
| 46 | + |
| 47 | +| Tailwind | CSS size | Mobile (×3) | Desktop (×1.5) | Usage | |
| 48 | +|---|---|---|---|---| |
| 49 | +| `4` | 16px | 48 | 24 | Small gap | |
| 50 | +| `6` | 24px | 72 | 36 | Medium gap | |
| 51 | +| `8` | 32px | 96 | 48 | Card padding | |
| 52 | +| `10` | 40px | 120 | 60 | Large gap | |
| 53 | +| `12` | 48px | 144 | 72 | Section gap | |
| 54 | +| `16` | 64px | 192 | 96 | Scene layout gap | |
| 55 | + |
| 56 | +## Complete sizing reference per device |
| 57 | + |
| 58 | +### Mobile Portrait (1080×1920) |
| 59 | + |
| 60 | +| Element | Size | Tailwind equivalent | |
| 61 | +|---|---|---| |
| 62 | +| **Title text** | font-size: 108–144 | `text-4xl` to `text-5xl` | |
| 63 | +| **Subtitle text** | font-size: 72–90 | `text-2xl` to `text-3xl` | |
| 64 | +| **Body text** | font-size: 54–72 | `text-lg` to `text-2xl` | |
| 65 | +| **Label / small text** | font-size: 42–48 | `text-sm` to `text-base` | |
| 66 | +| **Icon (hero/standalone)** | 160–200px | Large and impactful | |
| 67 | +| **Icon (in card)** | 72–96px | Clear and recognizable | |
| 68 | +| **Icon (inline/small)** | 48–60px | Chevrons, decorative | |
| 69 | +| **Card width** | 960–1020px | ~90% of viewport | |
| 70 | +| **Card padding** | 40–48px | Tailwind `p-10` to `p-12` | |
| 71 | +| **Card border-radius** | 28–36px | Generously rounded | |
| 72 | +| **Card row** | max 3 cols | More = unreadable | |
| 73 | +| **Counter** | font-size: 180–288 | `text-6xl` to `text-8xl` | |
| 74 | +| **Badge** | badge_size: "lg" + **font-size: 36–42** | Built-in "lg" = only 18px font (tiny on mobile!). MUST override with `style.font-size` | |
| 75 | +| **Terminal font-size** | 28–32px | Readable monospace | |
| 76 | +| **Terminal width** | 980–1020px | Near full width | |
| 77 | +| **Chart size** | width: 940, height: 400+ | Fill the space | |
| 78 | +| **Timeline width** | 940–980px | Near full width | |
| 79 | +| **Timeline node_radius** | 36–44px | Visible nodes | |
| 80 | +| **Timeline font_size** | 32–36px | Readable labels | |
| 81 | +| **Scene layout gap** | 48–72px | Tailwind `gap-12` to `gap-16` | |
| 82 | +| **CTA button** | width: 720–900px, padding: 36 | Thumb-friendly | |
| 83 | +| **max_width (text)** | 960–1000px | Almost full width | |
| 84 | +| **Glow radius** | 32–44px | Visible halo | |
| 85 | +| **Particle (halo) size_range** | {min: 60, max: 140} | Visible blobs | |
| 86 | + |
| 87 | +### Desktop Landscape (1920×1080) |
| 88 | + |
| 89 | +| Element | Size | Tailwind equivalent | |
| 90 | +|---|---|---| |
| 91 | +| **Title text** | font-size: 54–72 | `text-4xl` to `text-5xl` | |
| 92 | +| **Subtitle text** | font-size: 36–45 | `text-2xl` to `text-3xl` | |
| 93 | +| **Body text** | font-size: 24–30 | `text-base` to `text-lg` | |
| 94 | +| **Label / small text** | font-size: 21–24 | `text-sm` to `text-base` | |
| 95 | +| **Icon (hero)** | 72–96px | | |
| 96 | +| **Icon (in card)** | 40–56px | | |
| 97 | +| **Card width** | 800–1400px | 40-70% of viewport | |
| 98 | +| **Card padding** | 24–36px | | |
| 99 | +| **Counter** | font-size: 90–144 | | |
| 100 | +| **Badge** | badge_size: "md" | Default font-size OK for desktop | |
| 101 | +| **Terminal font-size** | 18–22px | | |
| 102 | +| **Scene layout gap** | 24–36px | | |
| 103 | +| **max_width (text)** | 800–1200px | | |
| 104 | + |
| 105 | +### Square (1080×1080) |
| 106 | + |
| 107 | +| Element | Size | Tailwind equivalent | |
| 108 | +|---|---|---| |
| 109 | +| **Title text** | font-size: 90–120 | `text-4xl` to `text-5xl` | |
| 110 | +| **Subtitle text** | font-size: 60–75 | `text-2xl` to `text-3xl` | |
| 111 | +| **Body text** | font-size: 40–50 | `text-base` to `text-lg` | |
| 112 | +| **Icon (hero)** | 120–150px | | |
| 113 | +| **Card width** | 920–1020px | ~90% of viewport | |
| 114 | +| **Counter** | font-size: 120–180 | | |
| 115 | +| **Badge** | badge_size: "lg" + **font-size: 32–36** | Override font-size for readability | |
| 116 | +| **Scene layout gap** | 36–48px | | |
| 117 | + |
| 118 | +## Key principle |
| 119 | + |
| 120 | +**Think in Tailwind classes first, then scale.** If your title should be `text-4xl` (36px CSS), multiply by 3 for mobile = 108px in rustmotion. This ensures consistent, readable results across devices. |
| 121 | + |
| 122 | +## Layout adjustments per device |
| 123 | + |
| 124 | +- **Mobile**: Prefer vertical stacking (column). Max 2–3 items per row. Cards should be nearly full-width (90%+). Use larger gaps. Break horizontal flows into stacked layouts. **CRITICAL: Add scene-level `padding` (48–60px) to prevent elements from touching screen edges.** All child widths (cards, timelines, terminals) must account for this padding: max child width = video width − 2 × scene padding. For 1080px with 48px padding → max child width = 984px. |
| 125 | +- **Desktop**: Can use horizontal rows with 3–5 items. Cards at 50–70% width. Tighter gaps. Scene padding optional (24px). |
| 126 | +- **Square**: Hybrid — 2–3 items per row, 85–95% width cards. Scene padding 36–48px. |
| 127 | + |
| 128 | +## BAD: Using desktop sizes on mobile |
| 129 | + |
| 130 | +```json |
| 131 | +{ |
| 132 | + "type": "text", |
| 133 | + "content": "Title", |
| 134 | + "style": { "font-size": 48, "color": "#FFFFFF" } |
| 135 | +} |
| 136 | +``` |
| 137 | +48px ÷ 3 = 16px CSS → `text-base` → body text, NOT a title! |
| 138 | + |
| 139 | +## GOOD: Mobile-scaled title |
| 140 | + |
| 141 | +```json |
| 142 | +{ |
| 143 | + "type": "text", |
| 144 | + "content": "Title", |
| 145 | + "style": { "font-size": 108, "color": "#FFFFFF" } |
| 146 | +} |
| 147 | +``` |
| 148 | +108px ÷ 3 = 36px CSS → `text-4xl` → proper title size! |
| 149 | + |
| 150 | +## BAD: 4-column card layout on mobile |
| 151 | + |
| 152 | +```json |
| 153 | +{ |
| 154 | + "type": "card", |
| 155 | + "size": { "width": 920, "height": "auto" }, |
| 156 | + "style": { "flex-direction": "row" }, |
| 157 | + "children": [ |
| 158 | + { "size": { "width": 180 } }, |
| 159 | + { "size": { "width": 180 } }, |
| 160 | + { "size": { "width": 180 } }, |
| 161 | + { "size": { "width": 180 } } |
| 162 | + ] |
| 163 | +} |
| 164 | +``` |
| 165 | +4 × 180px = 60px CSS each → cramped, unreadable. |
| 166 | + |
| 167 | +## GOOD: Stacked or 2-col on mobile |
| 168 | + |
| 169 | +```json |
| 170 | +{ |
| 171 | + "type": "card", |
| 172 | + "size": { "width": 1000, "height": "auto" }, |
| 173 | + "style": { "flex-direction": "column", "gap": 24 }, |
| 174 | + "children": [ |
| 175 | + { |
| 176 | + "type": "card", |
| 177 | + "size": { "width": 1000, "height": "auto" }, |
| 178 | + "style": { "flex-direction": "row", "align-items": "center", "gap": 24 }, |
| 179 | + "children": [ |
| 180 | + { "type": "icon", "size": { "width": 72, "height": 72 } }, |
| 181 | + { "type": "text", "style": { "font-size": 48 } } |
| 182 | + ] |
| 183 | + } |
| 184 | + ] |
| 185 | +} |
| 186 | +``` |
0 commit comments