- Add Forgejo workflow for automated build and deploy
- Build creates dist/ from public/ then adds Vue app build
- Configure Vite to build to dist/assets/dist with fixed filenames
- Deploy entire dist/ directory to production via FTP
- Add workflow documentation with FTP setup instructions
The workflow mirrors the GitLab CI approach: dist/ is created during build
and synchronized to production root on every push to main.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Replace MarginEditor component with individual fields (top/bottom/left/right)
- Add link/unlink button with SVG icons to sync margin values
- When linked, all fields share the same value
- Auto-detect linked state when loading from stylesheet
- Match PageSettings UI pattern for consistency
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove containers (section, div, article, etc.) from selectable elements
- Remove media elements (img, figure, ul, ol, table) from selection
- Keep text elements: headings, paragraphs, links, formatting tags
- Add figcaption as selectable, remove span
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Change popup width from 800px to 71rem for better scaling
- Add DM Sans as default body font
- Set h1 font-size to 3rem
- Reduce paragraph bottom margin from 10mm to 5mm
- Add link styles (purple color, no underline)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Preview now includes all field values, not filtering defaults
- Commented CSS shows what would be applied with current field values
- Applies to both ElementPopup and PagePopup
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Unlocking now creates CSS block with current field values
- Locking removes CSS block to restore general styles
- Show commented CSS preview when inheritance is locked
- Preview displays what would be applied if unlocked
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Store unlock state in data-inheritance-unlocked attribute on DOM element
- Each element/page now remembers its own inheritance state
- Re-locking removes element-specific CSS block to restore inheritance
- Elements revert to general styles from TextSettings/PageSettings
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
updateCssValue now handles three cases:
- Selector doesn't exist: creates the full block with property
- Selector exists but property missing: adds property to block
- Property exists: updates the value
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Create useDebounce composable to avoid code duplication
- Apply debounce to TextSettings margin/padding inputs
- Harmonize debounce delay to 500ms across all components
- Fix input lag when typing values like "30mm"
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add JSON content representation template (recit.json.php)
- Create virtual /print page plugin for recit pages
- Add recit.php base template for content representation
- Create Pinia store for recit data management
- Add block components (text, heading, image, list, quote, video, map)
- Update PagedJsWrapper for dynamic content rendering with data-page-type
- Modify header.php to pass recit JSON URL via data attribute
- Update App.vue to load recit data on mount
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add visual feedback for hovered page templates:
- Display "@page {templateName}" label on page edge hover
- Label positioned at top-left of page with 30% opacity
- Orange background matching page highlight color
- Automatically removed when hovering elements or clicking
Ensures consistent UX between page and element hover states.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Fix element label positioning using getBoundingClientRect + scroll offset
- Filter out state classes from element selectors (element-hovered, etc.)
- Add cursor pointer on hovered elements and pages
- Prevent elements from having both hovered and selected classes
- Fix issue where closing popup left previous element in hovered state
Ensures only one visual state per element at a time and cleaner
selector display in labels.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add visual feedback for hovered elements:
- Display element selector label (e.g., "p", "h1.title") on hover
- Label positioned at top-left of element with 30% opacity
Refactor all hover/selection styles to use CSS classes instead of inline styles:
- .page-hovered, .page-selected for page states
- .element-hovered, .element-selected for element states
- .element-hover-label for the floating label
This improves maintainability and separation of concerns by moving
styling logic to CSS files instead of JavaScript.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add --color-purple variable (#7136ff)
- Hover: dashed purple outline on content elements
- Selected: purple background with 30% opacity
- ElementPopup: purple label and instance count
- Track hovered and selected elements separately from pages
- Clear element selection when popup closes
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Instead of trying to print iframe directly, the print button:
1. Collects all styles from the iframe
2. Replaces the main page content with iframe content
3. Triggers window.print()
4. Reloads the page to restore the app
This ensures the PagedJS rendered content prints correctly.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Collect all CSS (inline styles and stylesheet rules) and embed
them directly in the print document. This ensures styles are
available even when printed from a new window.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Open iframe content in a new window for printing to avoid
blank page issues with srcdoc iframes. The window opens,
prints, then closes automatically.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add @media print styles to hide EditorPanel, popups, and loader.
Only the preview iframe content is visible during print.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Override default print behavior to print the active iframe
content (PagedJS rendered preview) instead of the main page.
Works with both Cmd+P (Mac) and Ctrl+P (Windows/Linux).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Filter clicks to only trigger ElementPopup for semantic content
elements (paragraphs, headings, images, lists, tables, etc.).
Clicking on generic divs or structural PagedJS elements now
closes popups instead of opening ElementPopup.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add templateName extracted from data-page-type attribute
- When unlocked: edits create/update @page <templateName> block
- When re-locked: remove template block, preview returns to @page
- Fields retain their values when re-locking (for user convenience)
- Display dynamic template name in popup header
- Show template-specific CSS block when unlocked
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Use the same regex parsing logic as PageSettings to extract margin
and background values from the @page CSS block. This ensures
PagePopup displays the correct inherited values when the inheritance
is locked.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>