diff --git a/markitect/static/js/components/debug-panel.js b/markitect/static/js/components/debug-panel.js
new file mode 100644
index 00000000..d22706a0
--- /dev/null
+++ b/markitect/static/js/components/debug-panel.js
@@ -0,0 +1,191 @@
+/**
+ * DebugPanel Component
+ *
+ * Extracted from monolithic editor.js as part of architecture refactoring.
+ * Handles debug message display and management for client-side debugging.
+ *
+ * Dependencies:
+ * - None (standalone component)
+ */
+
+/**
+ * DebugPanel - Manages debug message display and interaction
+ */
+class DebugPanel {
+ constructor() {
+ this.messages = [];
+ this.isActive = false;
+ this.maxMessages = 1000; // Keep last 1000 messages
+ }
+
+ /**
+ * Add a debug message
+ */
+ addMessage(message, category = 'INFO') {
+ const messageObj = {
+ message,
+ category,
+ timestamp: new Date().toLocaleTimeString()
+ };
+
+ this.messages.push(messageObj);
+
+ // Keep only last maxMessages
+ if (this.messages.length > this.maxMessages) {
+ this.messages = this.messages.slice(-this.maxMessages);
+ }
+
+ // Auto-update if panel is visible
+ if (this.isActive) {
+ this.update();
+ }
+ }
+
+ /**
+ * Toggle the debug panel on/off
+ */
+ toggle() {
+ const debugContainer = document.getElementById('debug-messages-container');
+ const debugButton = document.getElementById('toggle-debug');
+
+ if (!debugContainer || !debugButton) {
+ console.warn('DebugPanel: Required DOM elements not found');
+ return;
+ }
+
+ if (this.isActive) {
+ this.hide();
+ } else {
+ this.show();
+ }
+ }
+
+ /**
+ * Show the debug panel
+ */
+ show() {
+ const debugContainer = document.getElementById('debug-messages-container');
+ const debugButton = document.getElementById('toggle-debug');
+
+ if (!debugContainer || !debugButton) {
+ console.warn('DebugPanel: Required DOM elements not found');
+ return;
+ }
+
+ debugContainer.style.display = 'block';
+ debugButton.textContent = '🔍 Debug (ON)';
+ debugButton.style.background = '#28a745';
+ this.isActive = true;
+ this.update();
+ }
+
+ /**
+ * Hide the debug panel
+ */
+ hide() {
+ const debugContainer = document.getElementById('debug-messages-container');
+ const debugButton = document.getElementById('toggle-debug');
+
+ if (!debugContainer || !debugButton) {
+ console.warn('DebugPanel: Required DOM elements not found');
+ return;
+ }
+
+ debugContainer.style.display = 'none';
+ debugButton.textContent = '🔍 Debug';
+ debugButton.style.background = '#6c757d';
+ this.isActive = false;
+ }
+
+ /**
+ * Update the debug panel with current messages
+ */
+ update() {
+ const debugContainer = document.getElementById('debug-messages-container');
+ if (!debugContainer || !this.isActive) {
+ return;
+ }
+
+ if (this.messages.length === 0) {
+ debugContainer.innerHTML = '
No debug messages yet. Click sections to generate debug output.
';
+ return;
+ }
+
+ // Show the last 50 messages in reverse order (newest first)
+ const recentMessages = this.messages.slice(-50).reverse();
+
+ const messagesHtml = recentMessages.map(msg => {
+ const categoryColor = {
+ 'INFO': '#17a2b8',
+ 'WARNING': '#ffc107',
+ 'ERROR': '#dc3545',
+ 'SUCCESS': '#28a745',
+ 'DEBUG': '#6f42c1'
+ }[msg.category] || '#6c757d';
+
+ return `
+
+ [${msg.timestamp}]
+ ${msg.category}:
+ ${msg.message}
+
+ `;
+ }).join('');
+
+ debugContainer.innerHTML = `
+
+ Debug Messages (${this.messages.length} total, showing last ${recentMessages.length})
+
+
+
+ ${messagesHtml}
+
+ `;
+
+ // Add event listener for clear button
+ const clearBtn = debugContainer.querySelector('#debug-clear-btn');
+ if (clearBtn) {
+ clearBtn.addEventListener('click', () => {
+ this.clear();
+ });
+ }
+
+ // Auto-scroll to bottom to show newest messages
+ const scrollContainer = debugContainer.querySelector('div[style*="overflow-y"]');
+ if (scrollContainer) {
+ scrollContainer.scrollTop = scrollContainer.scrollHeight;
+ }
+ }
+
+ /**
+ * Clear all debug messages
+ */
+ clear() {
+ this.messages = [];
+ this.update();
+ }
+
+ /**
+ * Get the number of messages
+ */
+ getMessageCount() {
+ return this.messages.length;
+ }
+
+ /**
+ * Get recent messages
+ */
+ getRecentMessages(count = 10) {
+ return this.messages.slice(-count);
+ }
+}
+
+// Export for use in tests and other modules
+if (typeof module !== 'undefined' && module.exports) {
+ module.exports = { DebugPanel };
+}
+
+// Export for browser use
+if (typeof window !== 'undefined') {
+ window.DebugPanel = DebugPanel;
+}
\ No newline at end of file
diff --git a/markitect/static/js/components/document-controls.js b/markitect/static/js/components/document-controls.js
new file mode 100644
index 00000000..fb83ebd8
--- /dev/null
+++ b/markitect/static/js/components/document-controls.js
@@ -0,0 +1,279 @@
+/**
+ * DocumentControls Component
+ *
+ * Extracted from monolithic editor.js as part of architecture refactoring.
+ * Handles the floating control panel and document-level actions.
+ *
+ * Dependencies:
+ * - None (standalone component)
+ */
+
+/**
+ * DocumentControls - Manages the floating control panel and its buttons
+ */
+class DocumentControls {
+ constructor() {
+ this.controlPanel = null;
+ this.buttons = new Map();
+ this.eventHandlers = new Map();
+ this.isVisible = true;
+ }
+
+ /**
+ * Create the control panel and add it to the DOM
+ */
+ create() {
+ if (this.controlPanel) {
+ this.destroy(); // Remove existing panel
+ }
+
+ // Also remove any existing panel with the same ID in the DOM
+ const existingPanel = document.getElementById('markitect-global-controls');
+ if (existingPanel && existingPanel.parentNode) {
+ existingPanel.parentNode.removeChild(existingPanel);
+ }
+
+ // Create the floating control panel
+ this.controlPanel = document.createElement('div');
+ this.controlPanel.id = 'markitect-global-controls';
+ this.controlPanel.style.cssText = `
+ position: fixed;
+ top: 20px;
+ right: 20px;
+ background: rgba(248, 249, 250, 0.95);
+ border: 1px solid #dee2e6;
+ border-radius: 8px;
+ padding: 12px;
+ box-shadow: 0 4px 12px rgba(0,0,0,0.15);
+ z-index: 1000;
+ backdrop-filter: blur(8px);
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
+ font-size: 14px;
+ min-width: 200px;
+ `;
+
+ // Add title
+ const title = document.createElement('div');
+ title.style.cssText = `
+ font-weight: 600;
+ margin-bottom: 8px;
+ color: #495057;
+ border-bottom: 1px solid #dee2e6;
+ padding-bottom: 4px;
+ `;
+ title.textContent = 'Document Controls';
+
+ // Create button container
+ const buttonContainer = document.createElement('div');
+ buttonContainer.id = 'button-container';
+ buttonContainer.style.cssText = `
+ display: flex;
+ flex-direction: column;
+ gap: 6px;
+ `;
+
+ this.controlPanel.appendChild(title);
+ this.controlPanel.appendChild(buttonContainer);
+
+ // Add default buttons
+ this.addDefaultButtons();
+
+ // Add debug messages container
+ this.addDebugContainer();
+
+ // Add to DOM
+ document.body.appendChild(this.controlPanel);
+ }
+
+ /**
+ * Add default buttons to the control panel
+ */
+ addDefaultButtons() {
+ // Save Document button
+ this.addButton('save-document', '💾 Save Document', '#28a745');
+
+ // Reset All button
+ this.addButton('reset-all', '🔄 Reset All', '#ffc107', '#212529');
+
+ // Show Status button
+ this.addButton('show-status', '📊 Show Status', '#17a2b8');
+
+ // Debug button
+ this.addButton('toggle-debug', '🔍 Debug', '#6c757d');
+ }
+
+ /**
+ * Add debug container to the control panel
+ */
+ addDebugContainer() {
+ const debugContainer = document.createElement('div');
+ debugContainer.id = 'debug-messages-container';
+ debugContainer.style.cssText = `
+ margin-top: 12px;
+ max-height: 300px;
+ overflow-y: auto;
+ border: 1px solid #dee2e6;
+ border-radius: 4px;
+ background: #f8f9fa;
+ padding: 8px;
+ font-family: 'Courier New', monospace;
+ font-size: 12px;
+ line-height: 1.4;
+ display: none;
+ `;
+
+ this.controlPanel.appendChild(debugContainer);
+ }
+
+ /**
+ * Add a button to the control panel
+ */
+ addButton(id, text, backgroundColor, textColor = 'white') {
+ const buttonContainer = this.controlPanel.querySelector('#button-container');
+ if (!buttonContainer) {
+ throw new Error('Button container not found. Call create() first.');
+ }
+
+ const button = document.createElement('button');
+ button.id = id;
+ button.textContent = text;
+ button.style.cssText = `
+ background: ${backgroundColor};
+ color: ${textColor};
+ border: none;
+ padding: 8px 12px;
+ border-radius: 4px;
+ cursor: pointer;
+ font-size: 13px;
+ font-weight: 500;
+ transition: background-color 0.2s;
+ `;
+
+ buttonContainer.appendChild(button);
+ this.buttons.set(id, button);
+
+ return button;
+ }
+
+ /**
+ * Remove a button from the control panel
+ */
+ removeButton(id) {
+ const button = this.buttons.get(id);
+ if (button && button.parentNode) {
+ button.parentNode.removeChild(button);
+ this.buttons.delete(id);
+ this.eventHandlers.delete(id);
+ }
+ }
+
+ /**
+ * Set event handlers for buttons
+ */
+ setEventHandlers(handlers) {
+ for (const [buttonId, handler] of Object.entries(handlers)) {
+ const button = this.buttons.get(buttonId);
+ if (button) {
+ // Remove existing handler if any
+ if (this.eventHandlers.has(buttonId)) {
+ button.removeEventListener('click', this.eventHandlers.get(buttonId));
+ }
+
+ // Add new handler
+ button.addEventListener('click', handler);
+ this.eventHandlers.set(buttonId, handler);
+ }
+ }
+ }
+
+ /**
+ * Show the control panel
+ */
+ show() {
+ if (this.controlPanel) {
+ this.controlPanel.style.display = 'block';
+ this.isVisible = true;
+ }
+ }
+
+ /**
+ * Hide the control panel
+ */
+ hide() {
+ if (this.controlPanel) {
+ this.controlPanel.style.display = 'none';
+ this.isVisible = false;
+ }
+ }
+
+ /**
+ * Update status display (can be extended as needed)
+ */
+ updateStatus(status) {
+ // This method can be extended to show status information
+ // For now, it just stores the status for potential display
+ this.lastStatus = status;
+
+ // Could update a status indicator in the panel if needed
+ if (status && this.controlPanel) {
+ const title = this.controlPanel.querySelector('div');
+ if (title) {
+ const statusText = `Document Controls (${status.totalSections} sections, ${status.editingSections} editing)`;
+ // Could update title or add status indicator
+ }
+ }
+ }
+
+ /**
+ * Get the control panel element
+ */
+ getControlPanel() {
+ return this.controlPanel;
+ }
+
+ /**
+ * Destroy the control panel and clean up
+ */
+ destroy() {
+ if (this.controlPanel && this.controlPanel.parentNode) {
+ this.controlPanel.parentNode.removeChild(this.controlPanel);
+ }
+
+ // Clean up references
+ this.controlPanel = null;
+ this.buttons.clear();
+ this.eventHandlers.clear();
+ this.isVisible = true;
+ }
+
+ /**
+ * Check if the control panel is visible
+ */
+ isVisible() {
+ return this.isVisible && this.controlPanel && this.controlPanel.style.display !== 'none';
+ }
+
+ /**
+ * Get all button IDs
+ */
+ getButtonIds() {
+ return Array.from(this.buttons.keys());
+ }
+
+ /**
+ * Get a specific button by ID
+ */
+ getButton(id) {
+ return this.buttons.get(id);
+ }
+}
+
+// Export for use in tests and other modules
+if (typeof module !== 'undefined' && module.exports) {
+ module.exports = { DocumentControls };
+}
+
+// Export for browser use
+if (typeof window !== 'undefined') {
+ window.DocumentControls = DocumentControls;
+}
\ No newline at end of file