Commit graph

219 commits

Author SHA1 Message Date
Jan-Henrik Bruhn
0e57ade95f Separate GitHub Pages publishing to only run on release publish
Move GitHub Pages deployment to a separate workflow that triggers only
when a release is published, not when drafts are created or updated.
The new workflow downloads release assets directly from the published
release to deploy alongside the web app.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-11 13:42:17 +01:00
Jan-Henrik Bruhn
675bb2a6cc Remove readme, for now 2025-12-11 13:40:24 +01:00
Jan-Henrik Bruhn
3d57853928 Add update electron app handler 2025-12-11 13:33:47 +01:00
Jan-Henrik Bruhn
7d7d17f918 Build web app with correct base path for GitHub Pages
Set Vite base path to /respira/ when building for GitHub Pages
so assets load correctly from the repository subdirectory.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-11 13:30:11 +01:00
Jan-Henrik Bruhn
3760f05c29 Add web app build and deploy to GitHub Pages root
- Add build-web job that builds the web app
- Publish web app to GitHub Pages root directory
- Keep auto-update files in /update/ subdirectory
- Web app accessible at https://jhbruhn.github.io/respira/
- Auto-update files at /update/win32/x64/ and /update/darwin/arm64/

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-11 13:24:17 +01:00
Jan-Henrik Bruhn
e28761f127 Fix auto-update structure and macOS manifest URL
- Organize files in correct directory structure for auto-updater
- Windows files → update/win32/x64/
- macOS files → update/darwin/arm64/ (ZIP + RELEASES.json only)
- Fix macOS update manifest URL from x64 to arm64
- Exclude Linux packages and macOS DMG (not used for auto-updates)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-11 13:22:38 +01:00
Jan-Henrik Bruhn
6a53f86aea Add GitHub Pages deployment and consolidate release uploads
- Upload build outputs as workflow artifacts (windows/macos/linux)
- Add upload-to-release job that consolidates all platform uploads
- Add publish-to-pages job that deploys to GitHub Pages
- Add required permissions for Pages deployment

Build artifacts are now available in two places:
- GitHub Release for manual downloads
- GitHub Pages /update/ for auto-update systems

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-11 13:06:43 +01:00
Jan-Henrik Bruhn
a60f9c801f make build include releases.json for macos 2025-12-11 12:54:48 +01:00
Jan-Henrik Bruhn
8026a8977d Include RELEASES.json in macOS build assets upload
Add RELEASES.json to the release artifacts for macOS builds,
which is needed for auto-update functionality.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-11 12:50:38 +01:00
Jan-Henrik Bruhn
4a8127e5fb Increase left column width from 400px to 480px
Provides more breathing room for controls and progress monitor
in the left column on wide screens.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-11 12:44:33 +01:00
Jan-Henrik Bruhn
675b0f2b4e Set minimum Electron window size to prevent layout breaks
- Set minWidth to 1024px (matches Tailwind lg breakpoint)
- Set minHeight to 700px for adequate vertical space
- Prevents window from being resized to mobile single-column layout

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-11 12:43:10 +01:00
Jan-Henrik Bruhn
0c15f67ef0 Add Home Machine step to workflow for Initial state
- Add step 2: "Home Machine" to initialize hoop position
- Shift all subsequent workflow steps by 1 (now 8 steps total)
- Detect MachineStatus.Initial and show homing instructions
- Reuse existing InitialHoopError guidance for step content
- Update getCurrentStep logic to return step 2 when homing needed

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-11 12:38:51 +01:00
Jan-Henrik Bruhn
efc712995b Move error display to header with clickable popover
- Replace content-pushing error banners with header status indicator
- Add categorized error labels (Python Error, Connection Error, etc.)
- Show detailed error info with solutions in 600px popover on click
- Fix layout shift by always rendering error button (invisible when no error)
- Clear machineError state on disconnect
- Fix TypeScript error in WorkflowStepper ref callback

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-11 12:31:57 +01:00
Jan-Henrik Bruhn
bf3e397ddb Redesign UI for fixed-size window with floating guide overlay
- Convert NextStepGuide to collapsible floating overlay in bottom-right
- Implement fixed viewport layout (no page scrolling on desktop)
- Make color blocks scrollable with dynamic gradient indicator
- Add responsive behavior: scrollable on mobile, fixed on desktop
- Increase overlay opacity for better readability
- Enable full-height columns that expand to fill available space

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-10 21:56:19 +01:00
Jan-Henrik Bruhn
0dbfc751cb Improve responsive design and simplify typography system
Implemented comprehensive responsive design improvements for tablet support
and simplified typography from 12 different font sizes to a clean 5-level
hierarchy using only standard Tailwind classes.

Responsive improvements:
- Canvas height now adapts: 400px (mobile) → 500px (tablet) → 600px (desktop)
- Header stacks vertically on tablets, side-by-side on desktop (1024px+)
- WorkflowStepper scales appropriately for smaller screens
- Canvas overlays are more compact on mobile/tablet
- All components use responsive spacing and padding

Typography system redesign:
- Reduced from 12 sizes to 5 levels (Display, Heading, Subheading, Body, Label)
- Removed arbitrary pixel values (text-[7px], text-[9px], text-[10px], etc.)
- All text now uses standard Tailwind classes (text-xs, text-sm, text-base, text-lg, text-xl)
- Minimum text size is now 12px (text-xs) for better accessibility
- Buttons upgraded to text-sm (14px) for improved touch targets
- Consistent responsive scaling for top-level headers only

Added docs/TYPOGRAPHY_SYSTEM.md with usage guidelines and component mapping.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-10 16:56:43 +01:00
Jan-Henrik Bruhn
39d4df6a74 Fix zoom race condition and adjust zoom limits
- Fix race condition by using functional state updates in all zoom handlers
- Prevents negative or invalid zoom values from rapid scroll events
- Change zoom range from 10%-1000% to 10%-200% for more reasonable limits
- All zoom operations (wheel, buttons) now safely constrained
- Ensures consistent behavior even with fast mouse wheel scrolling

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-10 14:32:27 +01:00
Jan-Henrik Bruhn
6534684967 Add pre-upload validation for pattern bounds vs hoop size
- Validate pattern (with offset) fits within hoop bounds before upload
- Calculate precise overflow in each direction (left, right, top, bottom)
- Display detailed error message showing exact measurements
- Disable upload button when pattern exceeds hoop bounds
- Position error messages below buttons with smooth slide animation
- Set button sizing: file select (2/3), upload (1/3) for consistent layout
- Pass machineInfo to FileUpload component for hoop dimensions

Prevents uploading patterns that would exceed machine working area and
provides clear feedback on how to adjust pattern position.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-10 14:18:45 +01:00
Jan-Henrik Bruhn
eadbecc401 Add thread metadata display and unique color handling
- Fix PyStitch threadlist interpretation: threads = color blocks, not unique colors
- Add uniqueColors array to PesPatternData with proper deduplication at data layer
- Display thread metadata (brand, catalog number, chart, description) across all components
- Show unique colors vs thread blocks (e.g., "5 / 12" colors/blocks)
- Improve null value handling for missing thread metadata
- Reorder metadata display: brand + catalog # • chart + description
- Add metadata to pattern preview legend, tooltips, and color swatches

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-10 14:10:27 +01:00
Jan-Henrik Bruhn
501a7e8538 Move ai docs to separate folder 2025-12-08 18:54:37 +01:00
Jan-Henrik Bruhn
be48af7274 Upload rpm assets 2025-12-08 16:59:24 +01:00
Jan-Henrik Bruhn
ba3ef6030e Build AppImage 2025-12-08 16:35:25 +01:00
22577af745 Now fix path to dmg? 2025-12-08 00:29:19 +01:00
77652b8127 Remove darwin from dmg path 2025-12-08 00:24:46 +01:00
855a472293 Icons 2025-12-08 00:21:31 +01:00
044c7f4906 Change application name 2025-12-07 23:45:34 +01:00
0a7e0e652d Shell bash 2025-12-07 23:20:36 +01:00
f05aa8d5a3 Fix release asset upload to support glob patterns
Remove duplicate upload step using actions/upload-release-asset@v1
which doesn't support wildcards. Keep only the gh CLI upload which
properly handles multiple files.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-07 23:11:28 +01:00
27d84aa895 add license 2025-12-07 22:58:02 +01:00
ca89658e80 Fix Linux packaging by specifying executable name
Add executableName to packagerConfig to ensure consistent binary naming
across platforms. Fixes DEB and RPM maker errors on Linux.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-07 22:54:17 +01:00
80a9558c5d Fix Electron Forge packaging error on macOS
Remove extraResource configuration that was trying to copy non-existent
dist/assets directory. The Vite plugin handles all assets automatically.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-07 22:52:16 +01:00
17d7fb6b12 Add GitHub Actions workflows for CI/CD and releases
- Add build.yml workflow for continuous integration
  - Builds web app on Ubuntu
  - Packages Electron app for Windows, macOS, and Linux
  - Uploads artifacts for each platform

- Add release.yml workflow with release-drafter integration
  - Automatically creates draft releases on push to main
  - Auto-calculates version based on PR labels (major/minor/patch)
  - Updates package.json version during build for proper installers
  - Uploads platform-specific installers to draft releases

- Add release-drafter.yml configuration
  - Organizes changelog by categories (Features, Bug Fixes, Maintenance)
  - Supports semantic versioning via PR labels

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-07 22:49:36 +01:00
f80cabc5f2 Add Electron desktop application support with Electron Forge
Major changes:
- Add Electron main process and preload scripts with Web Bluetooth support
- Implement platform abstraction layer for storage and file services
- Create BluetoothDevicePicker component for device selection UI
- Migrate from electron-builder to Electron Forge for packaging
- Configure Vite for dual browser/Electron builds
- Add native file dialogs and persistent storage via electron-store
- Hide menu bar for cleaner desktop app appearance

The app now works in both browser (npm run dev) and Electron (npm run start).
Package with 'npm run package' or create installers with 'npm run make'.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-07 22:39:38 +01:00
60ebd858ef Move upload progress bar below buttons in FileUpload component
Improve visual hierarchy by displaying the upload progress bar after the action buttons instead of before them.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-07 13:54:42 +01:00
45c3f2ee07 Add dark mode support to skeleton loaders
Update all skeleton components to properly support dark mode with appropriate color variants for backgrounds, borders, and gradients.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-07 13:52:08 +01:00
8ee7d0ce7b Add Bluetooth pairing error detection and automatic disconnect handling
Detect when device is not paired at OS level and handle automatic disconnections. The app now properly updates UI state when the device is disconnected by the OS.

Changes:
- Add BluetoothPairingError custom error class in BrotherPP1Service
- Track isInitialConnection state to differentiate pairing issues from disconnects
- Detect pairing issues in sendCommand() only during initial connection
- Add onDisconnect() subscription method to BrotherPP1Service
- Listen for 'gattserverdisconnected' events and update state automatically
- Add isPairingError state to useBrotherMachine hook
- Display pairing errors with blue info styling instead of red error styling
- Include step-by-step pairing instructions: long-press Bluetooth button on machine, then pair in OS settings
- Automatically reset connection state when device disconnects

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-07 13:49:34 +01:00
651fa35a77 Fix lint errors in Vite config and MachineConnection
- Add proper TypeScript types for PyPI API response
- Remove unused isPolling prop from MachineConnection interface
- Remove unused imports from vite.config.ts

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-07 13:35:02 +01:00
775a8b19d1 Add Vite plugin to download Python wheels from PyPI during build
Remove pystitch wheel from source control and implement automatic downloading via custom Vite plugin. The plugin fetches wheels from PyPI API and serves them in both dev and production builds.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-07 13:32:15 +01:00
3ef9ca14c1 Add icons to action buttons and improve button styling
FileUpload:
- Added FolderOpenIcon to "Choose PES File" button

ProgressMonitor:
- Start Sewing button takes 2x space (flex-[2]) as primary action
- Trace Again button takes 1x space (flex-1) as secondary action
- Added PlayIcon to Start/Resume Sewing buttons
- Added ArrowPathIcon to Trace Again button
- Buttons fill full width with proper flex distribution
- Sizing consistent with rest of UI (text-xs, px-3 py-2)

Header:
- Disconnect button turns red on hover for clear destructive action

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-07 13:17:51 +01:00
c573c6414c Add machine info tooltip to serial number in header
Show detailed machine information when hovering over serial number:
- Serial number
- MAC address
- Total stitches sewn by machine
- Stitches since last service

Tooltip dynamically includes only available information.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-07 13:12:08 +01:00
9d9f71c543 Fix missing isDeleting prop destructuring in ProgressMonitor
Add isDeleting to destructured props with default value of false.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-07 13:10:19 +01:00
72641c0fb6 Fix button states to prevent actions during ongoing operations
- FileUpload: Disable "Choose PES File" button during upload
- ProgressMonitor: Disable Start/Resume/Trace buttons during pattern deletion
- Add disabled states with opacity-50 and cursor-not-allowed styling

Prevents race conditions and confusing UI states when operations are in progress.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-07 13:09:50 +01:00
77c4c2fcdb Improve header typography hierarchy and layout
- Increased title size from text-sm to text-lg for better prominence
- Moved serial number to upper row next to title (prevents truncation)
- Improved font sizes: serial (text-sm), controls (text-xs), not connected (text-sm)
- Enlarged icons and padding for better touch targets and readability
- Increased vertical spacing between rows for better breathing room

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-07 13:06:12 +01:00
7346526cdc Integrate machine connection into header with fixed-width layout
- Redesigned header with grid layout (300px fixed + flexible columns)
- Moved machine connection status to header with connection indicator
- Added disconnect button and status badge to header
- Moved connect button to "Get Started" card in left column
- Workflow stepper now always visible in dedicated column
- Fixed layout shifts by using fixed-width column and flex-shrink-0
- Connection status truncates within fixed width to prevent pushing

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-07 13:02:54 +01:00
99ed1adb68 Implement unified compact card design system across all UI components
Replace inconsistent card layouts with a cohesive, space-efficient design
pattern featuring color-coded borders, icon headers, and compact spacing.
This redesign significantly reduces vertical space usage while improving
visual hierarchy and scannability.

UI/UX improvements:
- Apply consistent card design with border-left accent colors
- Add icon + title + subtitle header pattern to all cards
- Reduce padding from p-6 to p-4 for more compact layout
- Use smaller, tighter font sizes (text-xs, text-sm)
- Implement color-coded borders for quick visual identification

Component-specific changes:
- MachineConnection: Green/gray border, WiFi icon, compact status display
- PatternSummaryCard: Blue border, Document icon (new component)
- FileUpload: Orange/gray border, Document icon, inline button layout
- ProgressMonitor: Purple border, Chart icon, single-column layout
- PatternCanvas: Teal/gray border, Photo icon, dimensions in header

Conditional rendering optimizations:
- Show FileUpload OR PatternSummaryCard based on upload state
- Move ProgressMonitor to left column with PatternSummary
- Relocate NextStepGuide below PatternCanvas for better space usage
- Remove duplicate delete button from ProgressMonitor

Space savings: ~40-50% reduction in vertical space usage across all cards

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-07 12:37:08 +01:00
9b536e9deb Migrate to official @types/web-bluetooth package
Replace custom Web Bluetooth type declarations with the official
@types/web-bluetooth package from npm. This provides better
maintained and more comprehensive type definitions for the
Web Bluetooth API.

Changes:
- Add @types/web-bluetooth dependency
- Update tsconfig to include web-bluetooth types
- Remove custom src/web-bluetooth.d.ts declarations

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-07 12:18:27 +01:00
b7ea024df3 Improve polling indicator with service-level communication state
Previously, isPolling was manually set in individual refresh functions,
which didn't cover all BLE communication and could have race conditions.

Now the communication indicator is driven by the service layer:
- Added isCommunicating state to BrotherPP1Service
- setCommunicating() called at queue processing boundaries
- onCommunicationChange() callback subscription pattern
- Hook subscribes to service communication state automatically

Benefits:
- Indicator shows for ALL BLE commands (status, progress, service count, etc)
- Prevents race conditions from overlapping command queue processing
- More accurate representation of actual BLE communication
- Cleaner code - no manual setIsPolling in each function

The indicator now properly shows whenever the command queue is being
processed, regardless of which specific command triggered it.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-07 00:02:22 +01:00
37f80051e0 Fix build and lint errors, refactor embroidery constants
- Remove unused imports and variables across multiple files
- Fix TypeScript 'any' type annotations with proper types
- Fix React setState in effect warnings
- Create shared embroidery constants file (embroideryConstants.ts)
- Replace magic number 0x10 with named MOVE constant
- Map PyStitch constants to JS constants using registerJsModule
- Ensure PEN encoding constants remain separate and valid

All build and lint checks now pass successfully.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-06 23:55:10 +01:00
4428b8472c Properly preserve pattern filename after deletion for re-upload
Improve the previous fix by actually preserving the original filename
from the cache instead of using a generic fallback. This is a cleaner
solution that maintains the actual pattern name.

Changes:
- Add currentFileName state to App.tsx to track pattern filename
- When loading cached pattern, preserve resumeFileName in currentFileName
- When loading new pattern, pass fileName to handlePatternLoaded callback
- Pass currentFileName to FileUpload component as prop
- Use currentFileName in displayFileName logic (prioritized first)
- Remove generic 'pattern.pes' fallback

Now when you delete a cached pattern and re-upload it, the original
filename (e.g., "mypattern.pes") is preserved instead of using a
generic fallback name. This maintains better traceability.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-06 23:42:47 +01:00
085ac1a5f7 Fix pattern re-upload after deletion by preserving filename
Fix bug where deleting a cached pattern prevented re-uploading because
the filename was lost. After deletion, the pattern remains visible in
the UI for re-editing and re-uploading, but the upload would silently
fail because displayFileName was empty.

The issue occurred because:
1. Pattern loaded from cache uses resumeFileName (from hook)
2. Local fileName state in FileUpload was never set (empty string)
3. After deletion, resumeFileName is cleared to null
4. displayFileName becomes empty, preventing upload

Solution:
- Add fallback to 'pattern.pes' when pesDataProp exists but no filename
- This ensures re-upload works after deletion while keeping pattern visible
- Pattern data (pesData) persists in App.tsx state for re-editing

Now users can delete a cached pattern and immediately re-upload it
with position adjustments or other modifications.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-06 23:39:31 +01:00
3d51992581 Fix missing status icons in Machine Connection panel
Add proper Heroicon components to display status indicators in the
Machine Connection panel. The icons were referenced but not rendered,
causing weird padding next to status text.

Changes:
- Import CheckCircleIcon, BoltIcon, PauseCircleIcon, ExclamationTriangleIcon
- Create stateIcons mapping from iconName to Heroicon components
- Fix reference from stateVisual.icon (doesn't exist) to stateVisual.iconName
- Render icon component dynamically based on machine state

Icon mapping:
- ready/complete: CheckCircle (✓)
- active: Bolt (lightning)
- waiting/interrupted: PauseCircle
- error: ExclamationTriangle

This fixes the TypeScript error and displays proper status indicators.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-06 23:35:16 +01:00