# 6.1 — Mobile Experience

**Previous Step:** ← [Theme System](../../05-theming/5.1-theme-system/5.1-theme-system.md)

---

## Page Metadata

| Property | Value |
|----------|-------|
| **Scenario** | 06 — Mobile Experience |
| **Page Number** | 6.1 |
| **Platform** | Web (PWA) — mobile viewport |
| **Page Type** | Responsive Adaptation (all app shell components) |
| **Viewport** | < 768px |
| **Interaction** | Touch-first |

---

## Overview

**Page Purpose:** Define how the entire CalcText workspace adapts to mobile. This is NOT a separate app — it's the same app intelligently restructured for touch and small screens. Every feature remains accessible; nothing is hidden or removed.

**Current Problem:** The existing web app hides results, toolbar, and divider on mobile — effectively removing the product's value on the most common device type.

**Success Criteria:**
- All features accessible on mobile (calculations, results, file management, themes)
- Touch targets >= 44px
- One-handed operation possible for core flow (type → see result)
- Feels like a native mobile app when installed as PWA

---

## Mobile Layout (< 768px)

```
┌─────────────────────────────┐
│  Header   [≡]  CalcText [🎨]│  44px (touch-sized)
├─────────────────────────────┤
│  Tab Bar (horizontal scroll) │  40px
├─────────────────────────────┤
│                              │
│                              │
│  Editor                      │
│  (full width)                │
│                              │
│                              │
│                              │
├─────────────────────────────┤
│  ═══  Results Tray           │  48px collapsed
│  Last: $4,300                │
├─────────────────────────────┤
│  Status (simplified)         │  24px
└─────────────────────────────┘
```

---

## Component Adaptations

### Header (Mobile)

| Property | Desktop | Mobile |
|----------|---------|--------|
| Height | 40px | 44px (touch target) |
| Left content | Logo + "CalcText" | [≡] hamburger + "CalcText" |
| Right content | Theme + Settings + ⌘ | [🎨] theme only |
| Padding | 12px 12px | 8px 12px |
| Hamburger | N/A | 44px × 44px touch target, opens sidebar drawer |

### Tab Bar (Mobile)

| Property | Desktop | Mobile |
|----------|---------|--------|
| Height | 36px | 40px |
| Tab min width | 100px | 80px (more compact) |
| Close button | Visible on hover/active | Hidden — swipe left to reveal |
| New tab (+) | After last tab | Sticky far-right |
| Scroll | Mouse wheel | Touch swipe horizontal |
| Active indicator | Top 2px accent border | Bottom 2px accent border (thumb reachable) |

### Editor (Mobile)

| Property | Desktop | Mobile |
|----------|---------|--------|
| Width | Flex (shared with results) | 100vw |
| Line padding | 12px | 12px |
| Gutter | 40px (line numbers) | 32px (compact numbers) |
| Font size | 15px | 15px (same — readable on mobile) |
| Line height | 24px | 24px (same) |
| Keyboard | Physical | Virtual — editor scrolls above keyboard |

#### Virtual Keyboard Handling

| Property | Value |
|----------|-------|
| Viewport | Uses `100dvh` (dynamic viewport height) to account for keyboard |
| Scroll | Editor auto-scrolls to keep cursor visible above keyboard |
| Results tray | Hides when keyboard is open (not enough space) |
| Status bar | Hides when keyboard is open |

### Results Tray (Mobile)

Replaces the side panel with a bottom tray.

| State | Height | Content |
|-------|--------|---------|
| **Collapsed** | 48px | Drag handle + last non-empty result |
| **Expanded** | 40vh (max 60vh) | Full scrollable results list |
| **Hidden** | 0px | When virtual keyboard is open |

#### Collapsed Tray

| Property | Value |
|----------|-------|
| Background | var(--bg-secondary) |
| Border top | 1px solid var(--border) |
| Drag handle | 32px × 4px pill, var(--border), centered |
| Content | "Last: {value}" — last non-empty result, text-xs |
| Tap | Expand tray |
| Swipe up | Expand tray |

#### Expanded Tray

| Property | Value |
|----------|-------|
| Content | All results paired with expressions |
| Item format | Line number + expression snippet + result value |
| Item height | 44px (touch-friendly) |
| Active line | var(--accent-bg) highlight |
| Tap result | Copy to clipboard + brief feedback |
| Swipe down | Collapse tray |
| Tap drag handle | Collapse |
| Scroll | Independent vertical scroll |

#### Tray Interaction

```
┌──────────────────────────────┐
│  ═══  (drag handle)          │  Swipe up to expand
│  Last: $4,300                │
├──────────────────────────────┤  ← expanded state below
│  5  salary          5,000    │
│  6  freelance       1,200    │
│  7  total_income    6,200    │  ← highlighted (active line)
│  9  rent            1,500    │
│ 10  groceries         400    │
│ 13  total_expenses  1,900    │
│ 14  savings         4,300    │
└──────────────────────────────┘
```

### Sidebar Drawer (Mobile)

| Property | Value |
|----------|-------|
| Trigger | Hamburger [≡] in header |
| Width | 85vw, max 320px |
| Position | Fixed left, full height |
| Background | var(--bg) |
| Backdrop | rgba(0, 0, 0, 0.5) — tap to close |
| Animation | translateX(-100%) → translateX(0), 200ms ease-out |
| Close | Tap backdrop, swipe left, × button (top-right, 44px target) |
| Content | Same sections as desktop sidebar (search, recent, favorites, files, templates) |
| File tap | Opens document → auto-closes drawer |
| Search | Full width, 44px height (touch target) |
| File items | 44px height (touch target, up from 28px desktop) |

### Theme Picker (Mobile)

| Property | Value |
|----------|-------|
| Trigger | [🎨] button in header |
| Style | Bottom sheet (slides from bottom) |
| Height | Auto (content-driven), max 60vh |
| Border radius | 12px 12px 0 0 |
| Drag handle | 32px × 4px pill, centered |
| Items | 48px height per theme (touch targets) |
| Accent swatches | 32px circles, 8px gap (larger for touch) |
| Close | Swipe down, tap backdrop |

### Status Bar (Mobile)

| Property | Value |
|----------|-------|
| Height | 24px (same) |
| Content | Cursor position + engine status dot only |
| Hidden items | Line count, theme indicator (accessible elsewhere) |
| Hidden | When virtual keyboard is open |

---

## Touch Gestures

| Gesture | Context | Action |
|---------|---------|--------|
| Swipe left on tab | Tab bar | Reveal close button |
| Swipe up on results tray | Results | Expand tray |
| Swipe down on results tray | Results | Collapse tray |
| Swipe left from right edge | Sidebar drawer | Close drawer |
| Swipe down on bottom sheet | Theme picker | Close sheet |
| Long press on file | Sidebar | Show context menu |
| Long press on tab | Tab bar | Drag to reorder |
| Tap result | Results tray | Copy to clipboard |
| Pinch | Editor | Zoom font size (optional) |

---

## Breakpoint Details

| Width | Classification | Key Adaptations |
|-------|---------------|-----------------|
| **>= 1024px** | Desktop | Full 3-panel layout |
| **768–1023px** | Tablet | Sidebar → overlay drawer. Editor + results side-by-side. |
| **480–767px** | Mobile | Single column. Results tray. Sidebar drawer. Touch targets 44px. |
| **< 480px** | Small mobile | Same as mobile. Tab labels may truncate. Logo text hidden. |

### Tablet Specifics (768–1023px)

| Component | Behavior |
|-----------|----------|
| Sidebar | Overlay drawer (hamburger toggle) instead of persistent panel |
| Editor + Results | Side-by-side with divider (same as desktop) |
| Tab bar | Same as desktop (enough width) |
| Header | Show hamburger [≡] instead of persistent sidebar |
| Theme picker | Dropdown (same as desktop) |

---

## PWA Mobile Enhancements

| Feature | Implementation |
|---------|---------------|
| Standalone display | `display: standalone` — no browser chrome |
| Status bar color | `theme-color` meta tag updates per theme |
| Safe areas | `env(safe-area-inset-*)` for notched devices |
| Splash screen | Theme-colored background + CalcText logo |
| Home screen icon | App icon with accent color ring |
| Orientation | Portrait preferred, landscape supported |

### Safe Area Padding

```css
.calcpad-app {
  padding-top: env(safe-area-inset-top);
  padding-bottom: env(safe-area-inset-bottom);
  padding-left: env(safe-area-inset-left);
  padding-right: env(safe-area-inset-right);
}
```

---

## Page States (Mobile-Specific)

| State | When | Behavior |
|-------|------|----------|
| **Keyboard open** | User tapped editor | Results tray + status bar hide. Editor fills available space. |
| **Keyboard closed** | User tapped outside or pressed Done | Results tray + status bar reappear. |
| **Drawer open** | Hamburger tapped | Sidebar overlays. Backdrop captures tap to close. |
| **Tray expanded** | User swiped up | 40vh results list. Editor partially visible above. |
| **Offline** | No network | Status bar shows offline indicator. All features work. |

---

## Technical Notes

- **Viewport units:** Use `dvh` (dynamic viewport height) not `vh` to handle mobile browser chrome and virtual keyboard.
- **Touch events:** Use `touchstart`/`touchmove`/`touchend` for swipe gestures. Consider `passive: true` for scroll performance.
- **Overscroll:** Disable `overscroll-behavior: none` on app container to prevent pull-to-refresh interference.
- **iOS safe areas:** Test with iPhone notch and dynamic island. Apply `env(safe-area-inset-*)`.
- **Android back button:** In PWA mode, back button should close drawers/sheets before navigating back.
- **Font scaling:** Respect system font size on mobile. Use relative units where possible.
- **Cross-platform:** Mobile web layout does NOT need to port to native mobile (that's a separate app). But interaction patterns (swipe, long-press) inform native mobile design if built later.

---

_Created using Whiteport Design Studio (WDS) methodology_
