diff --git a/client/1120_server.html b/client/1120_server.html
index af8fc72..cfd462b 100644
--- a/client/1120_server.html
+++ b/client/1120_server.html
@@ -6,10 +6,11 @@
     <title>HTTP Messages - SERVER</title>
     <link rel="stylesheet" href="./styles.css">
     <link rel="stylesheet" href="./styles/event-list.css">
+    <link rel="stylesheet" href="./styles/http-messages-table.css">
     <script defer src="./server.bundle.js"></script>
     <!-- Additional chunks will be loaded automatically -->
 </head>
-<body>
+<body class="server-page">
     <!-- Navigation bar container - content will be injected by navbar.ts -->
     <div id="navbarContainer" class="top-nav">
         <!-- Navbar content will be injected here -->
@@ -95,50 +96,57 @@
                 <div id="rawInputStatus" class="status-message"></div>
             </div>
         </div>
-        
-        <h2>Received Events</h2>
+        <h2>HTTP Messages</h2>
         <div class="received-events">
-            <div class="events-container">
-                <div class="events-sidebar">
-                    <div id="eventsList" class="events-list">
-                        <div class="empty-state">
-                            No events received yet. Use one of the methods above to receive events.
-                        </div>
-                        <!-- Events will be displayed here -->
+            <!-- Table-based view for HTTP messages with expandable rows -->
+            <div id="httpMessagesTableContainer"></div>
+
+            <!-- Keep the event details and responses sections for compatibility with existing code -->
+            <div style="display: none;">
+                <div id="eventDetails" class="event-details">
+                    <div class="empty-state">
+                        Select a request to view details
                     </div>
                 </div>
                 
-                <div class="events-content">
-                    <div id="eventDetails" class="event-details">
+                <div id="relatedResponses" class="related-responses-section">
+                    <h3>Responses</h3>
+                    <div id="responsesList" class="responses-list">
                         <div class="empty-state">
-                            Select an event to view details
+                            No responses available
                         </div>
-                        <!-- Selected event details will be shown here -->
                     </div>
-                    
-                    <!-- HTTP Response Modal -->
-                    <div id="httpResponseModal" class="http-response-modal" style="display: none;">
-                        <div class="http-response-container">
-                            <div class="http-response-header">
-                                <h3>HTTP Response</h3>
-                                <button class="close-modal-btn">&times;</button>
-                            </div>
-                            <div class="http-response-tabs">
-                                <button class="tab-btn active" data-tab="formatted-response">Formatted</button>
-                                <button class="tab-btn" data-tab="raw-response">Raw</button>
-                            </div>
-                            <div class="http-response-content">
-                                <div class="tab-content active" id="formatted-response">
-                                    <div class="http-formatted-container">
-                                        <!-- Formatted HTTP response will be shown here -->
-                                    </div>
-                                </div>
-                                <div class="tab-content" id="raw-response">
-                                    <pre><!-- Raw HTTP response will be shown here --></pre>
-                                </div>
-                            </div>
+                </div>
+            </div>
+        </div>
+        
+        <!-- Move the 21121 Response JSON container to be completely hidden -->
+        <div id="response21121Json" class="response-json-container" style="display: none; position: absolute; visibility: hidden; z-index: -9999;">
+            <pre class="json-content">
+                <!-- 21121 response JSON content will be stored here but displayed in the modal -->
+            </pre>
+        </div>
+        
+        <!-- HTTP Response Modal -->
+        <div id="httpResponseModal" class="http-response-modal" style="display: none;">
+            <div class="http-response-container">
+                <div class="http-response-header">
+                    <h3>HTTP Response</h3>
+                    <button class="close-modal-btn">&times;</button>
+                </div>
+                <div class="http-response-tabs">
+                    <button class="tab-btn active" data-tab="formatted-response">Formatted</button>
+                    <button class="tab-btn" data-tab="raw-response">Raw</button>
+                </div>
+                <div class="http-response-content">
+                    <div class="tab-content active" id="formatted-response">
+                        <div class="http-formatted-container">
+                            <!-- Formatted HTTP response will be shown here -->
                         </div>
                     </div>
+                    <div class="tab-content" id="raw-response">
+                        <pre><!-- Raw HTTP response will be shown here --></pre>
+                    </div>
                 </div>
             </div>
         </div>
diff --git a/client/src/components/EventList.ts b/client/src/components/EventList.ts
index e655228..9238be3 100644
--- a/client/src/components/EventList.ts
+++ b/client/src/components/EventList.ts
@@ -71,6 +71,15 @@ export class EventList {
       this.container.classList.add(this.options.className);
     }
     
+    // Check if this is the requests-only sidebar
+    const isRequestsSidebar = this.container.classList.contains('requests-only');
+    if (isRequestsSidebar) {
+      console.log('Initializing EventList in requests-only mode');
+      // Force filtering to only show 21120 events
+      this.eventTypeFilters.set('21120', true);
+      this.eventTypeFilters.set('21121', false);
+    }
+    
     // Create the UI structure
     this.createUIStructure();
     
@@ -805,6 +814,7 @@ export class EventList {
       const eventItem = document.createElement('div');
       eventItem.className = 'event-item';
       eventItem.dataset.id = eventId;
+      eventItem.dataset.kind = event.kind.toString();
       
       // Add tabindex for keyboard navigation
       eventItem.tabIndex = 0;
@@ -968,6 +978,11 @@ export class EventList {
       // Add click handler to select this event
       eventItem.addEventListener('click', () => {
         this.eventManager.selectEvent(eventId);
+        
+        // If this is a 21120 event (request), also show its responses
+        if (event.kind === 21120) {
+          this.displayResponsesForRequest(eventId);
+        }
       });
       
       // Add keyboard handling for accessibility
@@ -976,6 +991,11 @@ export class EventList {
         if (e.key === 'Enter' || e.key === ' ') {
           e.preventDefault();
           this.eventManager.selectEvent(eventId);
+          
+          // If this is a 21120 event (request), also show its responses
+          if (event.kind === 21120) {
+            this.displayResponsesForRequest(eventId);
+          }
         }
         
         // Navigate with arrow keys
@@ -1144,4 +1164,105 @@ export class EventList {
       this.allEventIds = [];
       this.filteredEventIds = [];
     }
-}
+    
+    /**
+     * Display response events for a given request event
+     * @param requestId The ID of the 21120 request event
+     */
+    private displayResponsesForRequest(requestId: string): void {
+      // Find the responses list container
+      const responsesListContainer = document.getElementById('responsesList');
+      if (!responsesListContainer) return;
+      
+      // Get related response events from EventManager
+      const responses = this.eventManager.getResponsesForRequest(requestId);
+      
+      // Clear existing content
+      responsesListContainer.innerHTML = '';
+      
+      // Show empty state if no responses
+      if (responses.length === 0) {
+        responsesListContainer.innerHTML = `
+          <div class="empty-state">
+            No responses available for this request
+          </div>
+        `;
+        return;
+      }
+      
+      // Create a response item for each related response
+      responses.forEach(response => {
+        const responseItem = document.createElement('div');
+        responseItem.className = 'response-item';
+        responseItem.dataset.id = response.id;
+        
+        // Format timestamp
+        const timestamp = new Date(response.event.created_at * 1000).toLocaleTimeString();
+        
+        // Check if decrypted
+        const isDecrypted = response.decrypted;
+        
+        // Extract status code if decrypted
+        let statusInfo = '';
+        if (isDecrypted && response.decryptedContent) {
+          const statusMatch = response.decryptedContent.match(/^HTTP\/[\d.]+ (\d+)/);
+          if (statusMatch) {
+            const statusCode = statusMatch[1];
+            let statusClass = '';
+            
+            if (statusCode.startsWith('2')) statusClass = 'status-success';
+            else if (statusCode.startsWith('3')) statusClass = 'status-redirect';
+            else if (statusCode.startsWith('4')) statusClass = 'status-client-error';
+            else if (statusCode.startsWith('5')) statusClass = 'status-server-error';
+            
+            statusInfo = `<span class="status-code ${statusClass}">Status: ${statusCode}</span>`;
+          }
+        }
+        
+        // Set HTML content
+        responseItem.innerHTML = `
+          <div class="response-header">
+            <div class="response-time">${timestamp}</div>
+            ${statusInfo}
+            <div class="encryption-status ${isDecrypted ? 'decrypted' : 'encrypted'}">
+              ${isDecrypted ? '🔓 Decrypted' : '🔒 Encrypted'}
+            </div>
+          </div>
+          <div class="response-id">ID: ${response.id.substring(0, 8)}...</div>
+        `;
+        
+        // Add click handler to select this response event
+        responseItem.addEventListener('click', () => {
+          this.eventManager.selectEvent(response.id);
+        });
+        
+        // Add to container
+        responsesListContainer.appendChild(responseItem);
+      });
+      
+      // Also update JSON display for most recent response
+      if (responses.length > 0) {
+        const mostRecentResponse = responses[0];
+        this.displayResponseJson(mostRecentResponse.event);
+      }
+    }
+    
+    /**
+     * Display raw JSON for a 21121 response event
+     * @param event The 21121 response event
+     */
+    private displayResponseJson(event: NostrEvent): void {
+      const jsonContainer = document.getElementById('response21121Json');
+      if (!jsonContainer) return;
+      
+      // Make container visible
+      jsonContainer.style.display = 'block';
+      
+      // Get the pre element
+      const pre = jsonContainer.querySelector('pre.json-content');
+      if (!pre) return;
+      
+      // Format JSON with indentation
+      pre.textContent = JSON.stringify(event, null, 2);
+    }
+  }
diff --git a/client/src/components/HttpMessagesTable.ts b/client/src/components/HttpMessagesTable.ts
new file mode 100644
index 0000000..a4503e2
--- /dev/null
+++ b/client/src/components/HttpMessagesTable.ts
@@ -0,0 +1,593 @@
+/**
+ * HttpMessagesTable Component
+ * Handles the table view for HTTP messages with simple rows
+ * Shows only basic information (sender npub, timestamp, event ID) in each row
+ * Includes a modal dialog to show detailed information when a row is clicked
+ */
+
+import { EventChangeType, EventKind } from '../services/EventManager';
+import type { EventManager } from '../services/EventManager';
+import { nip19 } from 'nostr-tools';
+import { HttpFormatter } from '../services/HttpFormatter';
+
+export class HttpMessagesTable {
+  private container: HTMLElement | null = null;
+  private eventManager: EventManager;
+  private tableBody: HTMLElement | null = null;
+  private unregisterListener: (() => void) | null = null;
+  private modal: HTMLElement | null = null;
+  private modalContent: HTMLElement | null = null;
+  private currentEventId: string | null = null;
+  
+  /**
+   * Create a new HttpMessagesTable component
+   */
+  constructor(eventManager: EventManager, containerId: string) {
+    this.eventManager = eventManager;
+    this.container = document.getElementById(containerId);
+  }
+  
+  /**
+   * Initialize the component and render the initial UI
+   */
+  public initialize(): void {
+    if (!this.container) {
+      console.error('HTTP messages table container not found');
+      return;
+    }
+    
+    // Create the table structure
+    this.createTableStructure();
+    
+    // Create the modal dialog
+    this.createModalDialog();
+    
+    // Register for event changes
+    this.unregisterListener = this.eventManager.registerListener((eventId, changeType) => {
+      const event = this.eventManager.getEvent(eventId);
+      
+      switch (changeType) {
+        case EventChangeType.Added:
+          // If it's a 21120 event, render it
+          if (event && event.event.kind === EventKind.HttpRequest) {
+            this.renderEventRow(eventId);
+          }
+          // If it's a 21121 event, update indicators for related request
+          if (event && event.event.kind === EventKind.HttpResponse) {
+            this.updateResponseIndicators();
+            // If the modal is currently open, refresh its content
+            this.refreshModalIfNeeded(eventId);
+          }
+          break;
+        case EventChangeType.Removed:
+          this.removeEventRow(eventId);
+          break;
+        case EventChangeType.Updated:
+          this.updateEventRow(eventId);
+          // If it's a 21121 event update, refresh indicators
+          if (event && event.event.kind === EventKind.HttpResponse) {
+            this.updateResponseIndicators();
+            // If the modal is currently open, refresh its content
+            this.refreshModalIfNeeded(eventId);
+          }
+          break;
+        case EventChangeType.Selected:
+          this.highlightSelectedRow(eventId);
+          break;
+      }
+    });
+    
+    // Render existing events
+    this.renderExistingEvents();
+  }
+  
+  /**
+   * Create the table structure
+   */
+  private createTableStructure(): void {
+    if (!this.container) { return; }
+    
+    const tableHtml = `
+      <table class="http-messages-table">
+        <thead>
+          <tr>
+            <th>Sender</th>
+            <th>Time</th>
+            <th>Event ID</th>
+            <th>Response</th>
+          </tr>
+        </thead>
+        <tbody id="httpMessagesTableBody">
+          <tr class="table-empty-state">
+            <td colspan="4">No HTTP messages received yet. Use one of the methods above to receive events.</td>
+          </tr>
+        </tbody>
+      </table>
+    `;
+    
+    this.container.innerHTML = tableHtml;
+    this.tableBody = document.getElementById('httpMessagesTableBody');
+  }
+  
+  /**
+   * Render all existing events from the EventManager
+   */
+  private renderExistingEvents(): void {
+    if (!this.tableBody) { return; }
+    
+    // Clear existing content
+    this.tableBody.innerHTML = '';
+    
+    // Get all events from the EventManager
+    const events = this.eventManager.getAllEvents();
+    
+    // Filter to only show kind 21120 events
+    const filteredEvents = events.filter(e => e.event.kind === 21120);
+    
+    // If no events, show the empty state
+    if (filteredEvents.length === 0) {
+      this.tableBody.innerHTML = `
+        <tr class="table-empty-state">
+          <td colspan="4">No HTTP messages received yet. Use one of the methods above to receive events.</td>
+        </tr>
+      `;
+      return;
+    }
+    
+    // Sort events by received time (newest first)
+    filteredEvents.sort((a, b) => b.receivedAt - a.receivedAt);
+    
+    // Render each event
+    filteredEvents.forEach(event => {
+      this.renderEventRow(event.id);
+    });
+  }
+  
+  /**
+   * Render a single event row
+   */
+  private renderEventRow(eventId: string): HTMLElement | null {
+    if (!this.tableBody) { return null; }
+    
+    // Get the event from EventManager
+    const managedEvent = this.eventManager.getEvent(eventId);
+    if (!managedEvent || managedEvent.event.kind !== 21120) { return null; }
+    
+    const event = managedEvent.event;
+    
+    // Check if the row already exists
+    const existingRow = document.getElementById(`event-row-${eventId}`);
+    if (existingRow) {
+      // If it exists, just update it
+      this.updateEventRow(eventId);
+      return existingRow as HTMLElement;
+    }
+    
+    // Create a new row for the event
+    const row = document.createElement('tr');
+    row.id = `event-row-${eventId}`;
+    row.dataset.eventId = eventId;
+    row.className = 'event-row';
+    // Format sender (pubkey) as npub
+    const senderPubkey = event.pubkey;
+    let npubSender;
+    
+    try {
+      // Use nip19 from nostr-tools to encode the pubkey to npub format
+      const fullNpub = nip19.npubEncode(senderPubkey);
+      // Shorten the npub for display
+      npubSender = `${fullNpub.substring(0, 8)}...${fullNpub.substring(fullNpub.length - 4)}`;
+    } catch (e) {
+      console.error('Error encoding npub:', e);
+      npubSender = senderPubkey.substring(0, 8) + '...';
+    }
+    
+    // Format timestamp
+    const timestamp = new Date(event.created_at * 1000).toLocaleTimeString();
+    
+    // Format event ID
+    const shortEventId = event.id ? (event.id.substring(0, 8) + '...') : 'Unknown ID';
+    
+    // Set row HTML
+    // Check if this event has responses
+    const hasResponses = this.eventManager.hasRelatedEvents(eventId);
+    const responseIndicator = hasResponses
+      ? '<span class="response-indicator has-response" title="Has 21121 response">●</span>'
+      : '<span class="response-indicator no-response" title="No 21121 response">○</span>';
+    
+    row.innerHTML = `
+      <td class="sender-cell" title="${senderPubkey}">${npubSender}</td>
+      <td class="time-cell">${timestamp}</td>
+      <td class="event-id-cell" title="${event.id}">${shortEventId}</td>
+      <td class="response-cell">${responseIndicator}</td>
+    `;
+    
+    // Add click handler for row selection
+    row.addEventListener('click', () => {
+      // Select the event in the event manager and highlight the row
+      this.eventManager.selectEvent(eventId);
+      this.highlightSelectedRow(eventId);
+      
+      // Show the modal with event details
+      this.showModal(eventId);
+    });
+    
+    // Remove any empty state row if present
+    const emptyStateRow = this.tableBody.querySelector('.table-empty-state');
+    if (emptyStateRow) {
+      emptyStateRow.remove();
+    }
+    
+    // Add to table at the top for new events
+    if (this.tableBody.firstChild) {
+      this.tableBody.insertBefore(row, this.tableBody.firstChild);
+    } else {
+      this.tableBody.appendChild(row);
+    }
+    
+    return row;
+  }
+  
+  /**
+   * Create the modal dialog structure
+   */
+  private createModalDialog(): void {
+    // Create modal element
+    this.modal = document.createElement('div');
+    this.modal.className = 'http-messages-modal';
+    this.modal.style.display = 'none';
+    
+    // Create close button
+    const closeButton = document.createElement('button');
+    closeButton.className = 'modal-close-button';
+    closeButton.innerHTML = '&times;';
+    closeButton.addEventListener('click', () => this.hideModal());
+    
+    // Create modal content
+    this.modalContent = document.createElement('div');
+    this.modalContent.className = 'modal-content';
+    
+    // Create tabs
+    const tabsContainer = document.createElement('div');
+    tabsContainer.className = 'modal-tabs';
+    
+    const tabs = [
+      { id: 'tab-21120-json', label: '21120 Raw JSON' },
+      { id: 'tab-21120-http', label: '21120 HTTP Request' },
+      { id: 'tab-21121-http', label: '21121 HTTP Response' },
+      { id: 'tab-21121-json', label: '21121 Raw JSON' }
+    ];
+    
+    // Create tab elements
+    tabs.forEach(tab => {
+      const tabButton = document.createElement('button');
+      tabButton.className = 'modal-tab';
+      tabButton.id = tab.id;
+      tabButton.textContent = tab.label;
+      tabButton.dataset.tabId = tab.id + '-content';
+      tabButton.addEventListener('click', (e) => this.switchTab(e));
+      tabsContainer.appendChild(tabButton);
+    });
+    
+    // Create tab content containers
+    const tabContentsContainer = document.createElement('div');
+    tabContentsContainer.className = 'modal-tab-contents';
+    
+    tabs.forEach(tab => {
+      const tabContent = document.createElement('div');
+      tabContent.className = 'modal-tab-content';
+      tabContent.id = tab.id + '-content';
+      tabContentsContainer.appendChild(tabContent);
+    });
+    
+    // Assemble the modal
+    this.modalContent.appendChild(tabsContainer);
+    this.modalContent.appendChild(tabContentsContainer);
+    this.modal.appendChild(closeButton);
+    this.modal.appendChild(this.modalContent);
+    
+    // Add modal to document body
+    document.body.appendChild(this.modal);
+    
+    // Add event listener to close modal when clicking outside
+    window.addEventListener('click', (event) => {
+      if (event.target === this.modal) {
+        this.hideModal();
+      }
+    });
+  }
+  
+  /**
+   * Show the modal dialog with event details
+   * @param eventId The ID of the event to show details for
+   */
+  private showModal(eventId: string): void {
+    if (!this.modal) return;
+    
+    this.currentEventId = eventId;
+    
+    // Load data for all tabs
+    this.loadEventData(eventId);
+    
+    // Show the modal
+    this.modal.style.display = 'block';
+    
+    // Select the first tab by default
+    const firstTab = this.modal?.querySelector('.modal-tab') as HTMLElement;
+    if (firstTab) {
+      firstTab.click();
+    }
+  }
+  
+  /**
+   * Hide the modal dialog
+   */
+  private hideModal(): void {
+    if (!this.modal) return;
+    
+    this.modal.style.display = 'none';
+    this.currentEventId = null;
+  }
+  
+  /**
+   * Switch between tabs in the modal
+   * @param event The click event
+   */
+  private switchTab(event: Event): void {
+    const clickedTab = event.currentTarget as HTMLElement;
+    if (!clickedTab || !clickedTab.dataset.tabId) return;
+    
+    // Hide all tab contents
+    const tabContents = document.querySelectorAll('.modal-tab-content');
+    tabContents.forEach(content => {
+      (content as HTMLElement).style.display = 'none';
+    });
+    
+    // Remove active class from all tabs
+    const tabs = document.querySelectorAll('.modal-tab');
+    tabs.forEach(tab => {
+      tab.classList.remove('active');
+    });
+    
+    // Show selected tab content
+    const selectedContent = document.getElementById(clickedTab.dataset.tabId);
+    if (selectedContent) {
+      selectedContent.style.display = 'block';
+    }
+    
+    // Add active class to clicked tab
+    clickedTab.classList.add('active');
+  }
+  
+  /**
+   * Load event data for the modal tabs
+   * @param eventId The ID of the 21120 event to load data for
+   */
+  private loadEventData(eventId: string): void {
+    // Get the 21120 event data
+    const requestEvent = this.eventManager.getEvent(eventId);
+    if (!requestEvent || requestEvent.event.kind !== EventKind.HttpRequest) {
+      console.error('Invalid or missing request event');
+      return;
+    }
+    
+    // Load 21120 Raw JSON tab content
+    const requestJsonTab = document.getElementById('tab-21120-json-content');
+    if (requestJsonTab) {
+      requestJsonTab.innerHTML = `<pre class="json-content">${JSON.stringify(requestEvent.event, null, 2)}</pre>`;
+    }
+    
+    // Load 21120 HTTP Request tab content
+    const requestHttpTab = document.getElementById('tab-21120-http-content');
+    if (requestHttpTab) {
+      // Get the HTTP request content from the event
+      const requestContent = requestEvent.decryptedContent || requestEvent.event.content;
+      const formattedRequest = HttpFormatter.formatHttpContent(requestContent, true, false);
+      requestHttpTab.innerHTML = formattedRequest;
+    }
+    
+    // Try to find related 21121 response event
+    const responseEventIds = this.eventManager.getRelatedEventIds(eventId);
+    
+    if (responseEventIds.length > 0) {
+      // Get the first response
+      const responseEvent = this.eventManager.getEvent(responseEventIds[0]);
+      
+      if (responseEvent && responseEvent.event.kind === EventKind.HttpResponse) {
+        // Load 21121 HTTP Response tab content
+        const responseHttpTab = document.getElementById('tab-21121-http-content');
+        if (responseHttpTab) {
+          const responseContent = responseEvent.decryptedContent || responseEvent.event.content;
+          const formattedResponse = HttpFormatter.formatHttpContent(responseContent, false, true);
+          responseHttpTab.innerHTML = formattedResponse;
+        }
+        
+        // Load 21121 Raw JSON tab content
+        const responseJsonTab = document.getElementById('tab-21121-json-content');
+        if (responseJsonTab) {
+          // First check if there's a pre-processed JSON in the response21121Json container
+          const responseJsonContainer = document.getElementById('response21121Json');
+          const preElement = responseJsonContainer?.querySelector('pre.json-content');
+          
+          if (preElement && preElement.textContent && preElement.textContent.trim() !== '') {
+            // Use the pre-processed JSON if available
+            responseJsonTab.innerHTML = `<pre class="json-content">${preElement.textContent}</pre>`;
+          } else {
+            // Otherwise, format it here
+            responseJsonTab.innerHTML = `<pre class="json-content">${JSON.stringify(responseEvent.event, null, 2)}</pre>`;
+          }
+        }
+      } else {
+        this.setNoResponseContent();
+      }
+    } else {
+      this.setNoResponseContent();
+    }
+  }
+  
+  /**
+   * Set content for when no response is available
+   */
+  private setNoResponseContent(): void {
+    // Set empty content for response tabs
+    const responseHttpTab = document.getElementById('tab-21121-http-content');
+    if (responseHttpTab) {
+      responseHttpTab.innerHTML = '<div class="no-response">No HTTP response available for this request</div>';
+    }
+    
+    const responseJsonTab = document.getElementById('tab-21121-json-content');
+    if (responseJsonTab) {
+      responseJsonTab.innerHTML = '<div class="no-response">No 21121 event available for this request</div>';
+    }
+  }
+  
+  /**
+   * Update an existing event row
+   */
+  private updateEventRow(eventId: string): void {
+    const row = document.getElementById(`event-row-${eventId}`);
+    if (!row) {
+      // If row doesn't exist, create it
+      this.renderEventRow(eventId);
+      return;
+    }
+    
+    const managedEvent = this.eventManager.getEvent(eventId);
+    if (!managedEvent || managedEvent.event.kind !== 21120) { return; }
+    
+    const event = managedEvent.event;
+    
+    // Update timestamp
+    const timeCell = row.querySelector('.time-cell');
+    if (timeCell) {
+      timeCell.textContent = new Date(event.created_at * 1000).toLocaleTimeString();
+    }
+    
+    // Update response indicator
+    const responseCell = row.querySelector('.response-cell');
+    if (responseCell) {
+      const hasResponses = this.eventManager.hasRelatedEvents(eventId);
+      const responseIndicator = hasResponses
+        ? '<span class="response-indicator has-response" title="Has 21121 response">●</span>'
+        : '<span class="response-indicator no-response" title="No 21121 response">○</span>';
+      responseCell.innerHTML = responseIndicator;
+    }
+  }
+  
+  /**
+   * Remove an event row
+   */
+  private removeEventRow(eventId: string): void {
+    const row = document.getElementById(`event-row-${eventId}`);
+    
+    if (row) { row.remove(); }
+    
+    // No need to handle expandable rows or expandedRowId anymore
+    
+    // Check if we need to show the empty state
+    if (this.tableBody && !this.tableBody.querySelector('.event-row')) {
+      this.tableBody.innerHTML = `
+        <tr class="table-empty-state">
+          <td colspan="4">No HTTP messages received yet. Use one of the methods above to receive events.</td>
+        </tr>
+      `;
+    }
+  }
+  
+  /**
+   * Highlight the selected row
+   */
+  private highlightSelectedRow(eventId: string): void {
+    // Remove selected class from all rows
+    const rows = document.querySelectorAll('.event-row');
+    rows.forEach(row => row.classList.remove('selected'));
+    
+    // Add selected class to the specified row
+    const selectedRow = document.getElementById(`event-row-${eventId}`);
+    if (selectedRow) {
+      selectedRow.classList.add('selected');
+      // This highlights the row to indicate selection
+      // Detailed content will be shown in a separate panel by the event manager
+    }
+  }
+  
+  /**
+   * Clean up resources when component is destroyed
+   */
+  public dispose(): void {
+    // Unregister event manager listener
+    if (this.unregisterListener) {
+      this.unregisterListener();
+      this.unregisterListener = null;
+    }
+    
+    // Remove modal from document
+    if (this.modal && document.body.contains(this.modal)) {
+      document.body.removeChild(this.modal);
+      this.modal = null;
+    }
+  }
+  
+  /**
+   * Refresh modal content if it's currently open and the event is related to the displayed request
+   * @param responseEventId The ID of the response event that was added or updated
+   */
+  private refreshModalIfNeeded(responseEventId: string): void {
+    // Only proceed if modal is open and we have a current event
+    if (!this.modal || this.modal.style.display === 'none' || !this.currentEventId) {
+      return;
+    }
+    
+    // Get the request event ID that this response is for
+    const requestEventId = this.eventManager.getRequestIdForResponse(responseEventId);
+    
+    // If the response is for the currently displayed request, refresh the modal
+    if (requestEventId === this.currentEventId) {
+      this.loadEventData(this.currentEventId);
+      
+      // Show notification in the modal that content was updated
+      const notification = document.createElement('div');
+      notification.className = 'modal-update-notification';
+      notification.textContent = 'Response data updated!';
+      this.modalContent?.appendChild(notification);
+      
+      // Remove notification after 3 seconds
+      setTimeout(() => {
+        if (notification.parentNode) {
+          notification.parentNode.removeChild(notification);
+        }
+      }, 3000);
+    }
+  }
+  
+  /**
+   * Update response indicators for all rows
+   * This can be called when a new 21121 response is received
+   */
+  public updateResponseIndicators(): void {
+    if (!this.tableBody) return;
+    
+    const rows = this.tableBody.querySelectorAll('.event-row');
+    rows.forEach(row => {
+      const eventId = row.getAttribute('data-event-id');
+      if (eventId) {
+        const hasResponses = this.eventManager.hasRelatedEvents(eventId);
+        const indicatorElement = row.querySelector('.response-indicator');
+        
+        if (indicatorElement) {
+          if (hasResponses) {
+            indicatorElement.classList.add('has-response');
+            indicatorElement.classList.remove('no-response');
+            indicatorElement.setAttribute('title', 'Has 21121 response');
+            indicatorElement.textContent = '●';
+          } else {
+            indicatorElement.classList.add('no-response');
+            indicatorElement.classList.remove('has-response');
+            indicatorElement.setAttribute('title', 'No 21121 response');
+            indicatorElement.textContent = '○';
+          }
+        }
+      }
+    });
+  }
+}
\ No newline at end of file
diff --git a/client/src/components/ServerUI.ts b/client/src/components/ServerUI.ts
index 4486669..447d159 100644
--- a/client/src/components/ServerUI.ts
+++ b/client/src/components/ServerUI.ts
@@ -14,6 +14,9 @@ import { HttpRequestExecutor } from './HttpRequestExecutor';
 import { ResponseViewer } from './ResponseViewer';
 import { EventList } from './EventList';
 import { EventDetail } from './EventDetail';
+import { HttpMessagesTable } from './HttpMessagesTable';
+import { Nostr21121EventHandler } from '../services/Nostr21121EventHandler';
+import { NostrService } from '../services/NostrService';
 
 
 /**
@@ -38,14 +41,17 @@ export class ServerUI {
   private relayService: NostrRelayService;
   private cacheService: NostrCacheService;
   private nostrEventService: NostrEventService;
+  private nostrService: NostrService;
   private httpService: HttpService;
   private httpClient: HttpClient;
+  private nostr21121EventHandler: Nostr21121EventHandler;
   
   // UI components
   private eventList: EventList;
   private eventDetail: EventDetail;
   private httpRequestExecutor: HttpRequestExecutor;
   private responseViewer: ResponseViewer;
+  private httpMessagesTable: HttpMessagesTable;
   
   /**
    * Create a new ServerUI component
@@ -77,6 +83,16 @@ export class ServerUI {
       updateStatusCallback
     );
     
+    // Create a NostrService instance for the 21121 event handler
+    this.nostrService = new NostrService(updateStatusCallback);
+    
+    // Initialize the Nostr21121EventHandler for automatic responses
+    this.nostr21121EventHandler = new Nostr21121EventHandler(
+      this.nostrService,
+      this.eventManager,
+      this.httpClient
+    );
+    
     // Initialize UI components
     this.eventList = new EventList(this.eventManager, {
       container: this.options.eventListContainer
@@ -86,6 +102,9 @@ export class ServerUI {
       container: this.options.eventDetailContainer
     });
     
+    // Initialize the HTTP Messages Table
+    this.httpMessagesTable = new HttpMessagesTable(this.eventManager, 'httpMessagesTableContainer');
+    
     // Initialize HTTP components
     this.httpRequestExecutor = new HttpRequestExecutor({
       eventManager: this.eventManager,
@@ -111,9 +130,14 @@ export class ServerUI {
     // Initialize UI components
     this.eventList.initialize();
     this.eventDetail.initialize();
+    this.httpMessagesTable.initialize();
     this.httpRequestExecutor.initialize();
     this.responseViewer.initialize();
     
+    // Initialize the 21121 event handler for automatic responses
+    this.nostr21121EventHandler.initialize();
+    console.log('Nostr21121EventHandler initialized for automatic responses');
+    
     // Set up event listeners
     this.setupEventListeners();
     
@@ -304,6 +328,7 @@ export class ServerUI {
     // Clean up UI components
     this.eventList.dispose();
     this.eventDetail.dispose();
+    this.httpMessagesTable.dispose();
     
     // No dispose method needed for HttpRequestExecutor and ResponseViewer
     // as they don't have persistent resources to clean up
@@ -317,6 +342,9 @@ export class ServerUI {
     }
     // Close WebSocket connections
     this.relayService.getWebSocketManager().close();
+    
+    // Anything specific to the 21121 event handler cleanup could go here
+    // Currently there's no explicit dispose method needed
   }
   
   /**
diff --git a/client/src/services/EventDetailsRenderer.ts b/client/src/services/EventDetailsRenderer.ts
index e1c19d3..d97e2c3 100644
--- a/client/src/services/EventDetailsRenderer.ts
+++ b/client/src/services/EventDetailsRenderer.ts
@@ -92,13 +92,13 @@ export class EventDetailsRenderer {
         <span class="event-id-display">ID: ${event.id?.substring(0, 8) || 'Unknown'}...</span>
       </div>
       
-      <div class="event-type-info">
+      <div class="event-type-info" style="padding-left: 15px;">
         <span class="event-kind">Kind: ${event.kind}</span>
         <span class="event-type">${isRequest ? 'HTTP Request' : (isResponse ? 'HTTP Response' : 'Unknown')}</span>
         <span class="event-time">Time: ${eventTime}</span>
       </div>
       
-      <div class="event-metadata">
+      <div class="event-metadata" style="padding-left: 15px;">
         <div class="pubkey">Pubkey: ${event.pubkey}</div>
         <div class="tags">
           <h3>Tags</h3>
@@ -106,46 +106,98 @@ export class EventDetailsRenderer {
         </div>
       </div>
       
-      <div id="related-events-container">
+      <div id="related-events-container" style="padding-left: 15px;">
         <div class="loading-indicator">
           <div class="spinner"></div>
           <span>Loading related events...</span>
         </div>
       </div>
       
-      <div class="http-actions" id="http-actions-${eventId}">
+      <div class="http-actions" id="http-actions-${eventId}" style="padding-left: 15px;">
         <!-- Action buttons will be added here -->
       </div>
       
-      <div class="http-content-tabs">
-        <div class="tab-buttons">
-          <button class="tab-btn" data-tab="raw-http">Raw HTTP</button>
-          <button class="tab-btn active" data-tab="formatted-http">Formatted HTTP</button>
+      <!-- Enhanced tabbed interface for event details -->
+      <div class="event-details-tabs" style="margin-top: 20px;">
+        <div class="tab-buttons" style="border-bottom: 2px solid var(--border-color); margin-bottom: 15px; padding-bottom: 2px;">
+          ${isRequest ? `
+            <button class="tab-btn" data-tab="request-json" style="padding: 8px 15px; border: none; background: none; border-bottom: 2px solid transparent; cursor: pointer; font-weight: 500; margin-right: 10px; margin-bottom: -2px; transition: all 0.3s ease;">21120 Raw JSON</button>
+            <button class="tab-btn active" data-tab="request-http" style="padding: 8px 15px; border: none; background: none; border-bottom: 2px solid var(--accent-color); cursor: pointer; font-weight: 500; margin-right: 10px; margin-bottom: -2px; transition: all 0.3s ease; color: var(--accent-color);">21120 HTTP Request</button>
+          ` : ''}
+          ${isResponse ? `
+            <button class="tab-btn" data-tab="response-json" style="padding: 8px 15px; border: none; background: none; border-bottom: 2px solid transparent; cursor: pointer; font-weight: 500; margin-right: 10px; margin-bottom: -2px; transition: all 0.3s ease;">21121 Raw JSON</button>
+            <button class="tab-btn active" data-tab="response-http" style="padding: 8px 15px; border: none; background: none; border-bottom: 2px solid var(--accent-color); cursor: pointer; font-weight: 500; margin-right: 10px; margin-bottom: -2px; transition: all 0.3s ease; color: var(--accent-color);">21121 HTTP Response</button>
+          ` : ''}
+          ${!isRequest && !isResponse ? `
+            <button class="tab-btn active" data-tab="event-json" style="padding: 8px 15px; border: none; background: none; border-bottom: 2px solid var(--accent-color); cursor: pointer; font-weight: 500; margin-right: 10px; margin-bottom: -2px; transition: all 0.3s ease; color: var(--accent-color);">Event Raw JSON</button>
+          ` : ''}
         </div>
         
-        <div class="tab-content" id="raw-http">
-          <div class="loading-container" id="raw-loading-${eventId}">
+        <!-- Request JSON tab content -->
+        ${isRequest ? `
+      <div class="tab-content" id="request-json">
+        <h3 style="padding-left: 20px; margin-top: 20px; margin-bottom: 15px; color: var(--accent-color);">21120 Raw JSON</h3>
+        <pre class="json-content" style="margin: 20px; padding: 15px; background-color: var(--bg-tertiary); border-left: 4px solid var(--accent-color); border-radius: 4px;">
+${JSON.stringify(event, null, 2)}
+        </pre>
+      </div>
+      ` : ''}
+      
+      <!-- Request HTTP tab content -->
+        ${isRequest ? `
+        <div class="tab-content active" id="request-http">
+          <h3 style="padding-left: 20px; margin-top: 20px; margin-bottom: 15px; color: var(--accent-color);">21120 HTTP Request</h3>
+          <div class="loading-container" id="raw-loading-${eventId}" style="padding: 20px; text-align: center;">
             <div class="spinner"></div>
             <span>Loading content...</span>
           </div>
-          <pre class="http-content" id="raw-content-${eventId}" style="display: none;"></pre>
-          <div class="decryption-status" id="decryption-status-raw-${eventId}">
+          <pre class="http-content" id="raw-content-${eventId}" style="display: none; margin: 20px; padding: 15px; border-left: 4px solid var(--accent-color); border-radius: 4px; background-color: var(--bg-tertiary);"></pre>
+          <div class="http-formatted-container" id="formatted-content-${eventId}" style="display: none; margin: 20px; padding: 15px; border-radius: 4px; background-color: var(--bg-tertiary);">
+          </div>
+          <div class="decryption-status" id="decryption-status-raw-${eventId}" style="margin: 20px; padding: 10px; text-align: center; border-radius: 4px;">
             <div class="spinner"></div>
             <span>Processing encryption...</span>
           </div>
         </div>
-        <div class="tab-content active" id="formatted-http">
-          <div class="loading-container" id="formatted-loading-${eventId}">
+        ` : ''}
+        
+        <!-- Response JSON tab content -->
+        ${isResponse ? `
+        <div class="tab-content" id="response-json">
+          <h3 style="padding-left: 20px; margin-top: 20px; margin-bottom: 15px; color: var(--accent-color);">21121 Raw JSON</h3>
+          <pre class="json-content" style="margin: 20px; padding: 15px; background-color: var(--bg-tertiary); border-left: 4px solid var(--accent-color); border-radius: 4px;">
+${JSON.stringify(event, null, 2)}
+          </pre>
+        </div>
+        ` : ''}
+        
+        <!-- Response HTTP tab content -->
+        ${isResponse ? `
+        <div class="tab-content active" id="response-http">
+          <h3 style="padding-left: 20px; margin-top: 20px; margin-bottom: 15px; color: var(--accent-color);">21121 HTTP Response</h3>
+          <div class="loading-container" id="raw-loading-${eventId}" style="padding: 20px; text-align: center;">
             <div class="spinner"></div>
-            <span>Formatting content...</span>
+            <span>Loading content...</span>
           </div>
-          <div class="http-formatted-container" id="formatted-content-${eventId}" style="display: none;">
+          <pre class="http-content" id="raw-content-${eventId}" style="display: none; margin: 20px; padding: 15px; border-left: 4px solid var(--accent-color); border-radius: 4px; background-color: var(--bg-tertiary);"></pre>
+          <div class="http-formatted-container" id="formatted-content-${eventId}" style="display: none; margin: 20px; padding: 15px; border-radius: 4px; background-color: var(--bg-tertiary);">
           </div>
-          <div class="decryption-status" id="decryption-status-formatted-${eventId}">
+          <div class="decryption-status" id="decryption-status-raw-${eventId}" style="margin: 20px; padding: 10px; text-align: center; border-radius: 4px;">
             <div class="spinner"></div>
             <span>Processing encryption...</span>
           </div>
         </div>
+        ` : ''}
+        
+        <!-- Generic event JSON tab content -->
+        ${!isRequest && !isResponse ? `
+        <div class="tab-content active" id="event-json">
+          <h3 style="padding-left: 20px; margin-top: 20px; margin-bottom: 15px; color: var(--accent-color);">Event Raw JSON</h3>
+          <pre class="json-content" style="margin: 20px; padding: 15px; background-color: var(--bg-tertiary); border-left: 4px solid var(--accent-color); border-radius: 4px;">
+${JSON.stringify(event, null, 2)}
+          </pre>
+        </div>
+        ` : ''}
       </div>
     `;
     
@@ -160,25 +212,63 @@ export class EventDetailsRenderer {
     if (!this.eventDetails) return;
     
     const tabButtons = this.eventDetails.querySelectorAll('.tab-btn');
+    if (tabButtons.length === 0) return;
+    
     tabButtons.forEach(button => {
       button.addEventListener('click', (e) => {
-        // Remove active class from all buttons and content
-        tabButtons.forEach(btn => btn.classList.remove('active'));
+        // Remove active class from all buttons in the same tab group
+        const tabGroup = button.closest('.tab-buttons');
+        if (tabGroup) {
+          const groupButtons = tabGroup.querySelectorAll('.tab-btn');
+          groupButtons.forEach(btn => btn.classList.remove('active'));
+        } else {
+          // Fallback to the old behavior
+          tabButtons.forEach(btn => btn.classList.remove('active'));
+        }
         
-        const tabContents = this.eventDetails!.querySelectorAll('.tab-content');
-        tabContents.forEach(content => content.classList.remove('active'));
+        // Find the parent tab container
+        let tabContainer = button.closest('.event-details-tabs');
+        if (!tabContainer) {
+          tabContainer = button.closest('.http-content-tabs');
+        }
         
-        // Add active class to clicked button
-        button.classList.add('active');
-        
-        // Show corresponding content
-        const tabId = (button as HTMLElement).dataset.tab || '';
-        const tabContent = this.eventDetails!.querySelector(`#${tabId}`);
-        if (tabContent) {
-          tabContent.classList.add('active');
+        if (tabContainer) {
+          // Remove active class from all tab contents in this container
+          const tabContents = tabContainer.querySelectorAll('.tab-content');
+          tabContents.forEach(content => content.classList.remove('active'));
+          
+          // Add active class to clicked button
+          button.classList.add('active');
+          
+          // Show corresponding content
+          const tabId = (button as HTMLElement).dataset.tab || '';
+          const tabContent = tabContainer.querySelector(`#${tabId}`);
+          if (tabContent) {
+            tabContent.classList.add('active');
+          }
         }
       });
     });
+    
+    // Ensure at least one tab is active in each tab group
+    const tabGroups = this.eventDetails.querySelectorAll('.tab-buttons');
+    tabGroups.forEach(group => {
+      const hasActiveButton = group.querySelector('.tab-btn.active');
+      if (!hasActiveButton) {
+        const firstButton = group.querySelector('.tab-btn');
+        if (firstButton) {
+          firstButton.classList.add('active');
+          const tabId = (firstButton as HTMLElement).dataset.tab || '';
+          const tabContainer = group.closest('.event-details-tabs') || group.closest('.http-content-tabs');
+          if (tabContainer) {
+            const tabContent = tabContainer.querySelector(`#${tabId}`);
+            if (tabContent) {
+              tabContent.classList.add('active');
+            }
+          }
+        }
+      }
+    });
   }
   
   /**
@@ -221,6 +311,22 @@ export class EventDetailsRenderer {
       
       // 5. Update formatted content (most expensive operation)
       this.updateFormattedContent(eventId, httpContent, isRequest, isResponse || is21121Event, receivedEvent.decrypted);
+      
+      // 6. For 21121 response events, display the raw JSON
+      if (is21121Event) {
+        this.displayResponse21121Json(event);
+      } else if (isRequest) {
+        // For request events, check if there are related responses
+        const relatedIds = event.id ? (this.relatedEvents.get(event.id) || []) : [];
+        if (relatedIds.length > 0) {
+          // Get the first related response event
+          const responseId = relatedIds[0];
+          const responseEvent = this.receivedEvents.get(responseId)?.event;
+          if (responseEvent && responseEvent.kind === 21121) {
+            this.displayResponse21121Json(responseEvent);
+          }
+        }
+      }
     } catch (error) {
       console.error("Error loading event details:", error);
       this.showErrorState(eventId, String(error));
@@ -316,26 +422,37 @@ export class EventDetailsRenderer {
     content: string,
     decrypted: boolean
   ): void {
-    // Get elements
-    const loadingElement = document.getElementById(`raw-loading-${eventId}`);
-    const contentElement = document.getElementById(`raw-content-${eventId}`);
-    const statusElement = document.getElementById(`decryption-status-raw-${eventId}`);
+    // Get elements - look for multiple possible IDs due to new tabbed structure
+    const loadingElements = document.querySelectorAll(`[id^="raw-loading-${eventId}"]`);
+    const contentElements = document.querySelectorAll(`[id^="raw-content-${eventId}"]`);
+    const statusElements = document.querySelectorAll(`[id^="decryption-status-raw-${eventId}"]`);
     
-    if (!loadingElement || !contentElement || !statusElement) return;
-    
-    // Update content
-    contentElement.textContent = content;
-    
-    // Update encryption status
-    if (decrypted) {
-      statusElement.innerHTML = '<div class="decryption-status success">Decryption successful ✓</div>';
-    } else {
-      statusElement.innerHTML = '<div class="decryption-status error">Decryption failed or not attempted</div>';
+    if (loadingElements.length === 0 || contentElements.length === 0 || statusElements.length === 0) {
+      console.warn('Could not find all required elements for updating raw content');
+      return;
     }
     
-    // Hide loading, show content
-    loadingElement.style.display = 'none';
-    contentElement.style.display = 'block';
+    // Update all instances of the content
+    contentElements.forEach(element => {
+      element.textContent = content;
+      (element as HTMLElement).style.display = 'block';
+    });
+    
+    // Update all encryption status elements
+    statusElements.forEach(element => {
+      if (decrypted) {
+        element.innerHTML = '<div class="decryption-status success">Decryption successful ✓</div>';
+      } else {
+        element.innerHTML = '<div class="decryption-status error">Decryption failed or not attempted</div>';
+      }
+    });
+    
+    // Hide all loading elements
+    loadingElements.forEach(element => {
+      (element as HTMLElement).style.display = 'none';
+    });
+    
+    console.log(`[EventDetailsRenderer] Updated raw content for event ${eventId}`);
   }
   
   /**
@@ -348,26 +465,56 @@ export class EventDetailsRenderer {
     isResponse: boolean,
     decrypted: boolean
   ): void {
-    // Get elements
-    const loadingElement = document.getElementById(`formatted-loading-${eventId}`);
-    const contentElement = document.getElementById(`formatted-content-${eventId}`);
-    const statusElement = document.getElementById(`decryption-status-formatted-${eventId}`);
+    // Get elements - look for multiple possible IDs due to new tabbed structure
+    const loadingElements = document.querySelectorAll(`[id^="formatted-loading-${eventId}"]`);
+    const contentElements = document.querySelectorAll(`[id^="formatted-content-${eventId}"]`);
+    const statusElements = document.querySelectorAll(`[id^="decryption-status-formatted-${eventId}"]`);
     
-    if (!loadingElement || !contentElement || !statusElement) return;
-    
-    // Format and update content
-    contentElement.innerHTML = HttpFormatter.formatHttpContent(content, isRequest, isResponse);
-    
-    // Update encryption status
-    if (decrypted) {
-      statusElement.innerHTML = '<div class="decryption-status success">Decryption successful ✓</div>';
-    } else {
-      statusElement.innerHTML = '<div class="decryption-status error">Decryption failed or not attempted</div>';
+    // If we don't find the standard elements, look for the ones in the new structure
+    if (contentElements.length === 0) {
+      console.log('[EventDetailsRenderer] Using fallback to update formatted content');
+      
+      // Try to find the formatted container in the HTTP tab
+      let tabContainer;
+      if (isRequest) {
+        tabContainer = document.getElementById('request-http');
+      } else if (isResponse) {
+        tabContainer = document.getElementById('response-http');
+      }
+      
+      if (tabContainer) {
+        const formattedContainer = tabContainer.querySelector('.http-formatted-container');
+        if (formattedContainer) {
+          formattedContainer.innerHTML = HttpFormatter.formatHttpContent(content, isRequest, isResponse);
+          (formattedContainer as HTMLElement).style.display = 'block';
+          console.log('[EventDetailsRenderer] Updated formatted content using fallback');
+        }
+      }
+      
+      return;
     }
     
-    // Hide loading, show content
-    loadingElement.style.display = 'none';
-    contentElement.style.display = 'block';
+    // Format and update all instances of the content
+    contentElements.forEach(element => {
+      element.innerHTML = HttpFormatter.formatHttpContent(content, isRequest, isResponse);
+      (element as HTMLElement).style.display = 'block';
+    });
+    
+    // Update all encryption status elements
+    statusElements.forEach(element => {
+      if (decrypted) {
+        element.innerHTML = '<div class="decryption-status success">Decryption successful ✓</div>';
+      } else {
+        element.innerHTML = '<div class="decryption-status error">Decryption failed or not attempted</div>';
+      }
+    });
+    
+    // Hide all loading elements
+    loadingElements.forEach(element => {
+      (element as HTMLElement).style.display = 'none';
+    });
+    
+    console.log(`[EventDetailsRenderer] Updated formatted content for event ${eventId}`);
   }
   
   /**
@@ -387,6 +534,30 @@ export class EventDetailsRenderer {
     }
   }
   
+  /**
+   * Display 21121 response event's raw JSON
+   * @param event The 21121 response event
+   */
+  private displayResponse21121Json(event: NostrEvent): void {
+    // Get the JSON container
+    const jsonContainer = document.getElementById('response21121Json');
+    if (!jsonContainer) return;
+    
+    // Get the pre element within the container
+    const preElement = jsonContainer.querySelector('pre.json-content');
+    if (!preElement) return;
+    
+    // Format the JSON prettily
+    const formattedJson = JSON.stringify(event, null, 2);
+    preElement.textContent = formattedJson;
+    
+    // Show the container
+    jsonContainer.style.display = 'block';
+    
+    // Add a log for debugging
+    console.log('[EventDetailsRenderer] Displayed 21121 response JSON', event.id);
+  }
+  
   /**
    * Get the event details element
    * @returns The event details element or null
diff --git a/client/src/services/Nostr21121EventHandler.ts b/client/src/services/Nostr21121EventHandler.ts
index 6beae7e..966dc66 100644
--- a/client/src/services/Nostr21121EventHandler.ts
+++ b/client/src/services/Nostr21121EventHandler.ts
@@ -1,24 +1,173 @@
 /**
  * Nostr21121EventHandler.ts
  * Handles NIP-21121 HTTP response events
+ * Automatically processes incoming 21120 requests to generate 21121 responses
  */
 
 import { NostrEvent } from '../relay';
 import { NostrService } from './NostrService';
+import { EventManager, EventChangeType, EventKind } from './EventManager';
+import { HttpClient } from './HttpClient';
+import { ToastNotifier } from './ToastNotifier';
+import { Nostr21121Service } from './Nostr21121Service';
 
 /**
  * Class for handling NIP-21121 HTTP response events
  */
 export class Nostr21121EventHandler {
   private nostrService: NostrService;
+  private eventManager: EventManager;
+  private httpClient: HttpClient;
+  private nostr21121Service: Nostr21121Service;
   private responseEventMap: Map<string, string[]> = new Map();
   
   /**
    * Constructor
    * @param nostrService The NostrService instance
+   * @param eventManager The EventManager instance
+   * @param httpClient The HttpClient instance
    */
-  constructor(nostrService: NostrService) {
+  constructor(
+    nostrService: NostrService, 
+    eventManager: EventManager,
+    httpClient: HttpClient
+  ) {
     this.nostrService = nostrService;
+    this.eventManager = eventManager;
+    this.httpClient = httpClient;
+    
+    // Initialize the 21121 service
+    // We pass the nostrService as relayService and null as cacheService
+    this.nostr21121Service = new Nostr21121Service(this.nostrService, null);
+  }
+
+  /**
+   * Initialize the handler
+   */
+  public initialize(): void {
+    console.log('[Nostr21121EventHandler] Initialized - Auto-response mode enabled');
+    
+    // Set up event listeners
+    this.setupEventListeners();
+  }
+  
+  /**
+   * Set up event listeners
+   */
+  private setupEventListeners(): void {
+    // Listen for new 21120 events
+    this.eventManager.registerListener((eventId, changeType) => {
+      if (changeType === EventChangeType.Added) {
+        this.handleNewEvent(eventId);
+      }
+    });
+  }
+  
+  /**
+   * Handle a new event
+   * @param eventId The ID of the new event
+   */
+  private async handleNewEvent(eventId: string): Promise<void> {
+    const managedEvent = this.eventManager.getEvent(eventId);
+    if (!managedEvent) return;
+    
+    const event = managedEvent.event;
+    
+    // Check if this is a 21120 event
+    if (event.kind === EventKind.HttpRequest) {
+      console.log(`[Nostr21121EventHandler] Processing new 21120 event: ${eventId}`);
+      
+      // Check if we already have a 21121 response for this request
+      const existingResponses = this.eventManager.getResponsesForRequest(eventId);
+      if (existingResponses.length > 0) {
+        console.log(`[Nostr21121EventHandler] Found existing 21121 response for ${eventId}. Skipping.`);
+        return;
+      }
+      
+      // Process the 21120 event to generate a 21121 response
+      this.processRequestEvent(event);
+    }
+  }
+  
+  /**
+   * Process a 21120 request event to generate a 21121 response
+   * @param event The 21120 request event
+   */
+  private async processRequestEvent(event: NostrEvent): Promise<void> {
+    try {
+      if (!event.id) {
+        console.error(`[Nostr21121EventHandler] Event has no ID, cannot process`);
+        return;
+      }
+      
+      console.log(`[Nostr21121EventHandler] Processing 21120 request event ${event.id}`);
+      
+      // Check if the event is decrypted by checking for decryptedContent
+      const managedEvent = this.eventManager.getEvent(event.id);
+      if (!managedEvent || !managedEvent.decrypted || !managedEvent.decryptedContent) {
+        console.log(`[Nostr21121EventHandler] Event ${event.id} is not decrypted yet. Cannot process.`);
+        return;
+      }
+      
+      const httpRequest = managedEvent.decryptedContent;
+      console.log(`[Nostr21121EventHandler] Executing HTTP request for event ${event.id}`);
+      console.log(`[Nostr21121EventHandler] Request: ${httpRequest.split('\n')[0]}`);
+      
+      // Execute the HTTP request
+      const httpResponse = await this.httpClient.sendHttpRequest(httpRequest);
+      console.log(`[Nostr21121EventHandler] Got HTTP response: ${httpResponse.split('\n')[0]}`);
+      
+      // Get relay information for publishing
+      const relayService = this.nostrService.getRelayService();
+      const relayUrl = relayService.getActiveRelayUrl();
+      if (!relayUrl) {
+        console.error('[Nostr21121EventHandler] No active relay URL available');
+        ToastNotifier.show('Failed to create 21121 response: No active relay', 'error', 5000);
+        return;
+      }
+      
+      // Get server private key (in a real implementation)
+      // Here we just use a placeholder as the actual key handling is beyond scope
+      const serverPrivateKey = 'placeholder_private_key';
+      
+      // Create a 21121 response event
+      console.log(`[Nostr21121EventHandler] Creating 21121 response for request ${event.id}`);
+      
+      const response = await this.nostr21121Service.createAndPublish21121Event(
+        event, 
+        httpResponse, 
+        serverPrivateKey,
+        relayUrl
+      );
+      
+      if (!response || !response.id) {
+        console.error('[Nostr21121EventHandler] Failed to create response event');
+        ToastNotifier.show('Failed to create 21121 response event', 'error', 5000);
+        return;
+      }
+      
+      console.log(`[Nostr21121EventHandler] Created 21121 response: ${response.id}`);
+      
+      // Add the relationship to our map
+      this.addRelatedEvent(event.id, response.id);
+      
+      // Add the event to EventManager
+      this.eventManager.addEvent(response);
+      
+      // Display the raw JSON in the response JSON container
+      this.displayRawResponseJson(response);
+      
+      // Display success notification
+      ToastNotifier.show('Created 21121 response event', 'success', 3000);
+      
+      // Debug log the response event
+      console.log(`[Nostr21121EventHandler] Response event:`, JSON.stringify(response, null, 2));
+      
+    } catch (error: any) {
+      const errorMessage = error instanceof Error ? error.message : String(error);
+      console.error(`[Nostr21121EventHandler] Error processing request:`, error);
+      ToastNotifier.show(`Failed to create 21121 response: ${errorMessage}`, 'error', 5000);
+    }
   }
   
   /**
@@ -33,6 +182,16 @@ export class Nostr21121EventHandler {
         return null;
       }
       
+      // First check our local map
+      const related = this.getRelatedEvents(requestEventId);
+      if (related.length > 0) {
+        const responseId = related[0]; // Get the first response
+        const managedEvent = this.eventManager.getEvent(responseId);
+        if (managedEvent) {
+          return managedEvent.event;
+        }
+      }
+      
       // Get active relay
       const relayService = this.nostrService.getRelayService();
       const relayUrl = relayService.getActiveRelayUrl();
@@ -42,16 +201,8 @@ export class Nostr21121EventHandler {
         return null;
       }
       
-      // Simplified implementation - instead of actual relay queries
-      console.log(`Searching for response event for request ${requestEventId} on relay ${relayUrl}`);
-      
-      // Simulate searching for events - in a real implementation this would query relays
-      return new Promise((resolve) => {
-        setTimeout(() => {
-          console.log('No response event found - this is a simplified implementation');
-          resolve(null);
-        }, 1000);
-      });
+      // Try to find a response event using the 21121 service
+      return await this.nostr21121Service.findResponseForRequest(requestEventId, relayUrl);
     } catch (error) {
       console.error('Error finding 21121 response:', error);
       return null;
@@ -80,6 +231,37 @@ export class Nostr21121EventHandler {
     return this.responseEventMap.get(eventId) || [];
   }
   
+  /**
+   * Display raw response JSON in the UI
+   * @param response The 21121 response event to display
+   */
+  private displayRawResponseJson(response: NostrEvent): void {
+    // Get the JSON container
+    const jsonContainer = document.getElementById('response21121Json');
+    if (!jsonContainer) {
+      console.warn('[Nostr21121EventHandler] response21121Json container not found');
+      return;
+    }
+    
+    // Get the pre element within the container
+    const preElement = jsonContainer.querySelector('pre.json-content');
+    if (!preElement) {
+      console.warn('[Nostr21121EventHandler] json-content element not found');
+      return;
+    }
+    
+    // Format the JSON prettily
+    const formattedJson = JSON.stringify(response, null, 2);
+    preElement.textContent = formattedJson;
+    
+    // We don't automatically show the container anymore as it appears in the wrong place
+    // The response should be shown in the modal when a row is clicked instead
+    // jsonContainer.style.display = 'block';
+    
+    // Add a log for debugging
+    console.log('[Nostr21121EventHandler] Updated 21121 response JSON content', response.id);
+  }
+  
   /**
    * Check if an event has related 21121 responses
    * @param eventId The event ID to check
diff --git a/client/src/services/NostrEventService.updated.ts b/client/src/services/NostrEventService.updated.ts
index 4ca2d2a..d6edec5 100644
--- a/client/src/services/NostrEventService.updated.ts
+++ b/client/src/services/NostrEventService.updated.ts
@@ -201,6 +201,10 @@ export class NostrEventService {
                           contentLength: decryptedContent?.length,
                           eventId: receivedEvent.id?.substring(0, 8) + '...'
                         });
+                        
+                        // After successful decryption, check if we already have a 21121 response
+                        // If not, create one by executing the HTTP request
+                        this.checkAndCreateResponse(receivedEvent, decryptedContent);
                       } catch (decryptError) {
                         console.error("Failed to decrypt event content:", decryptError);
                         console.error("Decryption error details:", {
@@ -335,6 +339,225 @@ export class NostrEventService {
    * @param statusMessage The status message
    * @param statusClass The CSS class for styling the status
    */
+  /**
+   * Check if we already have a 21121 response for a 21120 request
+   * If not, automatically create one by executing the HTTP request
+   * @param requestEvent The 21120 request event
+   * @param decryptedContent The decrypted HTTP request content
+   */
+  private async checkAndCreateResponse(requestEvent: NostrEvent, decryptedContent?: string): Promise<void> {
+    if (!requestEvent.id || !decryptedContent) {
+      console.log("Cannot process request: missing ID or decrypted content");
+      return;
+    }
+
+    try {
+      console.log(`Checking for existing 21121 response for request ${requestEvent.id.substring(0, 8)}...`);
+      
+      // Check if we already have a response for this request in the EventManager
+      const hasResponse = this.eventManager.hasRelatedEvents(requestEvent.id);
+      
+      if (hasResponse) {
+        console.log(`Found existing 21121 response for request ${requestEvent.id.substring(0, 8)}`);
+        return;
+      }
+      
+      console.log(`No existing 21121 response found for request ${requestEvent.id.substring(0, 8)}, executing HTTP request...`);
+      
+      // Get server's private key for signing the response
+      const serverNsec = localStorage.getItem('serverNsec');
+      if (!serverNsec) {
+        console.error("Cannot create 21121 response: Server private key (nsec) not found");
+        return;
+      }
+      
+      // Get the relay URL
+      const relayUrl = this.relayService.getActiveRelayUrl();
+      if (!relayUrl) {
+        console.error("Cannot create 21121 response: No active relay connection");
+        return;
+      }
+      
+      // Create HttpClient dynamically
+      const { HttpService } = await import('./HttpService');
+      const { HttpClient } = await import('./HttpClient');
+      const httpService = new HttpService();
+      const httpClient = new HttpClient(httpService);
+      
+      try {
+        // Execute the HTTP request
+        console.log("Executing HTTP request...");
+        const httpResponse = await httpClient.sendHttpRequest(decryptedContent);
+        console.log("HTTP request executed successfully, creating 21121 response...");
+        
+        // Import crypto utilities for encryption
+        const cryptoUtils = await import('../utils/crypto-utils');
+        const nostrTools = await import('nostr-tools');
+        
+        // Generate a random key for content encryption
+        const randomKey = Array.from(crypto.getRandomValues(new Uint8Array(32)))
+          .map(b => b.toString(16).padStart(2, '0'))
+          .join('');
+        
+        // Encrypt the response content with the random key
+        const encryptedContent = await cryptoUtils.encryptWithWebCrypto(httpResponse, randomKey);
+        
+        // Get the server pubkey from the nsec
+        const decoded = nostrTools.nip19.decode(serverNsec);
+        if (decoded.type !== 'nsec') {
+          throw new Error("Invalid server nsec format");
+        }
+        
+        const serverPrivateKeyBytes = decoded.data as Uint8Array;
+        const serverPubkey = nostrTools.getPublicKey(serverPrivateKeyBytes);
+        
+        // Create tags for the 21121 event
+        const tags: string[][] = [
+          ["e", requestEvent.id as string],
+          ["key", randomKey],  // Store the key directly for now, we'll handle encryption differently
+          ["expiration", (Math.floor(Date.now() / 1000) + 3600).toString()] // 1 hour expiration
+        ];
+        
+        // Create the 21121 event
+        const eventBody = {
+          kind: EventKind.HttpResponse,
+          created_at: Math.floor(Date.now() / 1000),
+          tags: tags,
+          content: encryptedContent,
+          pubkey: serverPubkey
+        };
+        
+        // Compute the event ID (hash)
+        const id = nostrTools.getEventHash(eventBody as any);
+        
+        // Sign the event
+        let sig: string;
+        
+        // Try to use window.nostr if available, otherwise use a simulated signature
+        if (window.nostr && window.nostr.signEvent) {
+          try {
+            const signResult = await window.nostr.signEvent(eventBody);
+            sig = typeof signResult === 'object' && signResult.sig
+                ? signResult.sig
+                : 'simulated_signature_for_21121_response';
+          } catch (signError) {
+            console.error("Error signing with window.nostr:", signError);
+            sig = 'simulated_signature_for_21121_response';
+          }
+        } else {
+          sig = 'simulated_signature_for_21121_response';
+        }
+        
+        // Create the complete signed event
+        const responseEvent: NostrEvent = {
+          ...eventBody,
+          id,
+          sig
+        };
+        
+        // Ensure ID is defined for logging
+        const shortId = responseEvent.id ? responseEvent.id.substring(0, 8) + '...' : 'undefined';
+        
+        console.log("Created 21121 response event:", {
+          id: shortId,
+          tags: responseEvent.tags.length,
+          contentLength: responseEvent.content.length
+        });
+        
+        // Display the raw JSON in the console for debugging
+        console.log("21121 raw JSON:", JSON.stringify(responseEvent, null, 2));
+        
+        // Create a DOM element to display the raw JSON in the UI
+        this.displayRawJsonInUI(responseEvent);
+        
+        // Publish the event to the relay if we have valid IDs
+        if (responseEvent.id && requestEvent.id) {
+          const relayPool = this.relayService.getRelayPool();
+          if (relayPool) {
+            try {
+              // Use relayPool.send instead of publish for better type compatibility
+              const pub = relayPool.publish([relayUrl], responseEvent as any);
+              await pub;
+              console.log(`Published 21121 response event to ${relayUrl}`);
+              
+              // Add the event to our EventManager for tracking
+              this.processEvent(responseEvent);
+              
+              // Store relationship between request and response
+              this.eventManager.associateResponseWithRequest(responseEvent.id, requestEvent.id);
+            } catch (pubError) {
+              console.error("Error publishing 21121 response:", pubError);
+            }
+          } else {
+            console.error("Cannot publish 21121 response: Relay pool not available");
+          }
+        }
+        
+        // Show success notification
+        const event = new CustomEvent('21121-response-created', {
+          detail: {
+            requestId: requestEvent.id,
+            responseId: responseEvent.id,
+            responseJson: JSON.stringify(responseEvent, null, 2)
+          }
+        });
+        document.dispatchEvent(event);
+      } catch (error) {
+        console.error("Error creating 21121 response:", error);
+      }
+    } catch (error) {
+      console.error("Error checking for existing 21121 response:", error);
+    }
+  }
+  
+  /**
+   * Display the raw JSON of a 21121 event in the UI
+   * @param event The 21121 event to display
+   */
+  private displayRawJsonInUI(event: NostrEvent): void {
+    try {
+      // Create or get a container for displaying the JSON
+      let jsonContainer = document.getElementById('response21121Json');
+      
+      if (!jsonContainer) {
+        // Create the container if it doesn't exist
+        jsonContainer = document.createElement('div');
+        jsonContainer.id = 'response21121Json';
+        jsonContainer.className = 'response-json-container';
+        
+        // Add a header
+        const header = document.createElement('h3');
+        header.textContent = '21121 Response JSON';
+        jsonContainer.appendChild(header);
+        
+        // Create a pre element for the JSON
+        const pre = document.createElement('pre');
+        pre.className = 'json-content';
+        jsonContainer.appendChild(pre);
+        
+        // Add to the page in a suitable location (find a good container)
+        const container = document.querySelector('.event-details') ||
+                          document.querySelector('.content') ||
+                          document.body;
+        
+        if (container) {
+          container.appendChild(jsonContainer);
+        }
+      }
+      
+      // Update the JSON content
+      const pre = jsonContainer.querySelector('pre');
+      if (pre) {
+        pre.textContent = JSON.stringify(event, null, 2);
+      }
+      
+      // Make the container visible
+      jsonContainer.style.display = 'block';
+    } catch (uiError) {
+      console.error("Error displaying 21121 JSON in UI:", uiError);
+    }
+  }
+
   private updateStatus(statusMessage: string, statusClass: string): void {
     if (this.statusCallback) {
       this.statusCallback(statusMessage, statusClass);
diff --git a/client/styles.css b/client/styles.css
index 0189a64..2176fd6 100644
--- a/client/styles.css
+++ b/client/styles.css
@@ -403,13 +403,27 @@ body[data-theme="dark"] {
 /* General layout */
 body {
     font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
-    max-width: 900px;
-    margin: 0 auto;
-    padding: 20px;
+    margin: 0;
+    padding: 0;
     background-color: var(--bg-primary);
     color: var(--text-primary);
     line-height: 1.6;
     transition: all 0.3s ease;
+    width: 100%;
+    min-height: 100vh;
+    max-width: 100vw;
+    overflow-x: hidden;
+    border: none;
+}
+
+/* Content container for wrapping everything except the navbar */
+.content {
+    padding: 0 20px;
+    width: 100%;
+    max-width: 100%;
+    box-sizing: border-box;
+    border: none;
+    background-color: var(--bg-primary);
 }
 
 /* Make sure all elements using CSS vars also transition smoothly */
@@ -448,11 +462,13 @@ h3 {
     box-shadow: 0 2px 4px rgba(0,0,0,0.05);
     height: 50px;
     display: flex;
-    width: 100%;
+    width: 100vw;
+    max-width: 100%;
 }
 
 body {
     padding-top: 70px; /* Added padding to account for fixed navbar */
+    overflow-x: hidden; /* Prevent horizontal scrolling */
 }
 
 .nav-left {
@@ -634,7 +650,7 @@ code {
 
 /* Content */
 .content {
-    margin-bottom: 40px;
+    margin-bottom: 0;
 }
 
 /* Footer */
@@ -649,7 +665,7 @@ footer {
 /* Responsive adjustments */
 @media (max-width: 768px) {
     body {
-        padding-top: 60px;
+        padding-top: 45px;
         padding-left: 10px;
         padding-right: 10px;
     }
@@ -1095,40 +1111,54 @@ footer {
     display: none !important;
 }
 
-/* Receiver page styles */
+/* Receiver page styles - Enhanced */
 .relay-connection {
-    margin-bottom: 20px;
-    padding: 15px;
+    margin-bottom: 25px;
+    padding: 20px;
     background-color: var(--bg-secondary);
     display: flex;
     flex-direction: column;
-    gap: 15px;
+    gap: 18px;
+    border-radius: 10px;
+    box-shadow: 0 3px 10px rgba(0, 0, 0, 0.08);
+    border: 1px solid var(--border-color);
 }
 
-/* Server info styles */
+/* Server info styles - Enhanced */
 .server-info-container {
-    margin-bottom: 10px;
-    padding-bottom: 15px;
+    margin-bottom: 15px;
+    padding-bottom: 18px;
     border-bottom: 1px solid var(--border-color);
+    transition: all 0.3s ease;
 }
 
 .server-npub-container {
     display: flex;
     align-items: center;
     flex-wrap: wrap;
-    gap: 10px;
+    gap: 12px;
+    padding: 5px;
+    background-color: var(--bg-tertiary);
+    border-radius: 6px;
 }
 
-/* Server section styles */
+/* Server section styles - Enhanced */
 .server-section {
-    margin-bottom: 20px;
-    padding: 15px;
+    margin-bottom: 25px;
+    padding: 20px;
     background-color: var(--bg-secondary);
-    border-radius: 8px;
+    border-radius: 10px;
     border: 1px solid var(--border-color);
     display: flex;
     flex-direction: column;
-    gap: 15px;
+    gap: 18px;
+    box-shadow: 0 3px 10px rgba(0, 0, 0, 0.08);
+    transition: transform 0.2s ease, box-shadow 0.2s ease;
+}
+
+.server-section:hover {
+    transform: translateY(-2px);
+    box-shadow: 0 5px 15px rgba(0, 0, 0, 0.12);
 }
 
 .server-npub-container label {
@@ -1192,64 +1222,88 @@ footer {
 .relay-input-container {
     display: flex;
     align-items: center;
-    margin-bottom: 10px;
+    margin-bottom: 15px;
+    background-color: var(--bg-tertiary);
+    border-radius: 8px;
+    padding: 12px 15px;
+    box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05);
 }
 
 .relay-input-container label {
-    margin-right: 10px;
-    min-width: 80px;
+    margin-right: 15px;
+    min-width: 85px;
+    font-weight: 600;
+    color: var(--text-secondary);
 }
 
 .relay-input-container input {
     flex: 1;
-    margin-right: 10px;
-    padding: 8px;
+    margin-right: 15px;
+    padding: 10px 12px;
     border: 1px solid var(--border-color);
-    border-radius: 4px;
+    border-radius: 6px;
+    background-color: var(--bg-secondary);
+    font-size: 0.95em;
+    transition: border-color 0.2s ease, box-shadow 0.2s ease;
+}
+
+.relay-input-container input:focus {
+    border-color: var(--accent-color);
+    box-shadow: 0 0 0 2px rgba(var(--accent-color-rgb, 13, 110, 253), 0.25);
+    outline: none;
 }
 
 .relay-connect-button {
     background-color: var(--button-primary);
     color: white;
     border: none;
-    border-radius: 4px;
-    padding: 8px 15px;
+    border-radius: 6px;
+    padding: 10px 18px;
     cursor: pointer;
+    font-weight: 500;
+    transition: all 0.2s ease;
+    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
 }
 
 .relay-connect-button:hover {
     background-color: var(--button-hover);
+    transform: translateY(-2px);
+    box-shadow: 0 3px 6px rgba(0, 0, 0, 0.15);
 }
 
 .relay-status {
-    margin-top: 10px;
-    padding: 5px 10px;
-    border-radius: 4px;
+    margin-top: 12px;
+    padding: 8px 15px;
+    border-radius: 6px;
     display: inline-block;
+    font-weight: 500;
+    text-align: center;
+    transition: all 0.3s ease;
+    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
 }
 
 .relay-status.connected {
-    background-color: var(--bg-info);
+    background-color: rgba(40, 167, 69, 0.15);
     color: var(--button-success);
     border: 1px solid var(--button-success);
 }
 
 .relay-status.connecting {
-    background-color: var(--bg-info);
-    color: var(--text-secondary);
-    border: 1px solid var(--border-color);
+    background-color: rgba(255, 193, 7, 0.15);
+    color: #ffc107;
+    border: 1px solid #ffc107;
 }
 
 .relay-status.error {
-    background-color: var(--bg-info);
+    background-color: rgba(231, 76, 60, 0.15);
     color: #e74c3c;
     border: 1px solid #e74c3c;
 }
 
 .relay-status.notice {
     background-color: var(--bg-info);
-    color: var(--text-secondary);
-    border: 1px solid var(--border-color);
+    color: var(--accent-color);
+    border: 1px solid var(--accent-color);
 }
 
 .subscription-settings {
@@ -1262,27 +1316,39 @@ footer {
 
 .filter-options {
     margin: 15px 0;
-    padding: 8px 10px;
+    padding: 12px 15px;
     background-color: var(--bg-tertiary);
-    border-radius: 4px;
+    border-radius: 8px;
     display: flex;
     align-items: center;
+    border: 1px solid var(--border-color);
+    box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05);
 }
 
 .filter-options label {
     margin-right: 15px;
     display: inline-block;
     cursor: pointer;
+    font-weight: 500;
+    transition: color 0.2s ease;
+}
+
+.filter-options label:hover {
+    color: var(--accent-color);
 }
 
 .filter-checkbox {
     display: flex;
     align-items: center;
-    gap: 8px;
+    gap: 10px;
 }
 
 .filter-checkbox input[type="checkbox"] {
     margin-right: 5px;
+    width: 18px;
+    height: 18px;
+    accent-color: var(--accent-color);
+    cursor: pointer;
 }
 
 .key-input {
@@ -1565,29 +1631,114 @@ footer {
     color: var(--text-tertiary);
     cursor: not-allowed;
 }
-/* Events container for side-by-side layout */
-.events-container {
+/* Main App Layout with sidebar */
+.app-layout {
     display: flex;
-    gap: 20px;
-    margin-top: 15px;
+    gap: 0;
+    margin: 0;
+    width: 100%;
+    background-color: var(--bg-secondary);
+    border-radius: 8px;
+    overflow: hidden;
+    border: 1px solid var(--border-color);
+    max-width: 100%;
 }
 
-.events-sidebar {
+/* Sidebar for 21120 requests */
+.requests-sidebar {
     flex: 0 0 300px;
+    display: flex;
+    flex-direction: column;
+    border-right: 1px solid var(--border-color);
+    border-radius: 0;
+    background-color: var(--bg-secondary);
+    overflow: hidden;
 }
 
-.events-content {
+.sidebar-header {
+    padding: 15px;
+    border-bottom: 1px solid var(--border-color);
+    background-color: var(--bg-tertiary);
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+}
+
+.sidebar-header h3 {
+    margin: 0;
+    font-size: 16px;
+    color: var(--text-primary);
+}
+
+.sidebar-controls {
+    display: flex;
+    gap: 10px;
+}
+
+.icon-button {
+    background: none;
+    border: none;
+    font-size: 16px;
+    cursor: pointer;
+    color: var(--text-secondary);
+    transition: color 0.2s;
+}
+
+.icon-button:hover {
+    color: var(--accent-color);
+}
+
+/* Main content area */
+.main-content {
     flex: 1;
+    display: flex;
+    flex-direction: column;
+    padding: 0 20px;
+    gap: 20px;
+    overflow-y: auto;
+    padding-right: 10px;
 }
 
-.events-list {
-    max-height: 600px;
-    overflow-y: auto;
+/* Related responses section */
+.related-responses-section {
     border: 1px solid var(--border-color);
     border-radius: 8px;
     background-color: var(--bg-secondary);
+    overflow: hidden;
+    margin-top: 20px;
+}
+
+.related-responses-section h3 {
+    margin: 0;
+    padding: 15px;
+    border-bottom: 1px solid var(--border-color);
+    background-color: var(--bg-tertiary);
+    font-size: 16px;
+    color: var(--text-primary);
+}
+
+.responses-list {
+    padding: 15px;
+    max-height: 300px;
+    overflow-y: auto;
+}
+
+/* Events list styling - updated for sidebar */
+.events-list {
+    flex: 1;
+    overflow-y: auto;
     background-color: var(--bg-secondary);
 }
+
+/* When events list is in the requests-only mode */
+.events-list.requests-only .event-item:not([data-kind="21120"]) {
+    display: none;
+}
+
+.events-list.requests-only {
+    max-height: none; /* Allow it to fill the sidebar */
+}
+
 .event-item {
     padding: 15px;
     border-bottom: 1px solid var(--border-color);
@@ -1903,26 +2054,51 @@ footer {
 
 .json-content {
     margin-top: 10px;
-    padding: 15px;
-    border-radius: 4px;
+    padding: 20px;
+    border-radius: 6px;
     background-color: var(--bg-tertiary);
     min-height: 200px;
     max-height: 400px;
     overflow-y: auto;
-    font-family: 'Courier New', monospace;
-    font-size: 13px;
-    line-height: 1.4;
+    font-family: 'Consolas', 'Courier New', monospace;
+    font-size: 14px;
+    line-height: 1.5;
     white-space: pre-wrap;
     border-left: 4px solid var(--accent-color);
+    box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1);
+    color: var(--text-primary);
+}
+
+/* Syntax highlighting for JSON */
+.json-string {
+    color: #25c2a0;
+}
+
+.json-number {
+    color: #f5a623;
+}
+
+.json-boolean {
+    color: #7e57c2;
+}
+
+.json-null {
+    color: #bc4749;
+}
+
+.json-key {
+    color: #0088cc;
+    font-weight: 500;
 }
 
 /* Event debug output for 31120 events */
 .event-debug-output {
     margin: 15px 0;
-    padding: 15px;
+    padding: 18px;
     background-color: var(--bg-tertiary);
-    border-radius: 8px;
+    border-radius: 10px;
     border: 1px solid var(--accent-color);
+    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
 }
 
 .event-debug-output h3 {
@@ -2108,24 +2284,30 @@ footer {
 }
 /* Dark mode is already handled by CSS variables */
 
-/* Responsive adjustments for the events container */
+/* Responsive adjustments for the app layout */
 @media (max-width: 768px) {
-    .events-container {
+    .app-layout {
         flex-direction: column;
+        height: auto;
     }
     
-    .events-sidebar {
+    .requests-sidebar {
         flex: auto;
         width: 100%;
+        height: 300px;
     }
     
-    .events-list {
-        max-height: 300px;
+    .main-content {
+        width: 100%;
     }
     
     .event-details {
         min-height: 400px;
     }
+    
+    .responses-list {
+        max-height: 200px;
+    }
 }
 
 /* Clear events button */
diff --git a/client/styles/event-list.css b/client/styles/event-list.css
index 91f9615..0f8b61c 100644
--- a/client/styles/event-list.css
+++ b/client/styles/event-list.css
@@ -367,4 +367,116 @@
 .status-server-error {
   background-color: rgba(156, 39, 176, 0.1);
   color: #9c27b0;
+}
+
+/* Response Items in the related responses section */
+.response-item {
+  padding: 12px;
+  border-bottom: 1px solid var(--border-color);
+  cursor: pointer;
+  transition: background-color 0.2s ease;
+}
+
+.response-item:last-child {
+  border-bottom: none;
+}
+
+.response-item:hover {
+  background-color: var(--bg-tertiary);
+}
+
+.response-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 8px;
+}
+
+.response-time {
+  font-size: 12px;
+  color: var(--text-secondary);
+}
+
+.response-id {
+  font-size: 12px;
+  color: var(--accent-color);
+  font-family: monospace;
+}
+
+.status-code {
+  font-size: 12px;
+  padding: 2px 6px;
+  border-radius: 4px;
+  background-color: var(--bg-tertiary);
+  font-weight: bold;
+}
+
+.status-code.status-success {
+  background-color: rgba(40, 167, 69, 0.1);
+  color: #28a745;
+}
+
+.status-code.status-redirect {
+  background-color: rgba(255, 193, 7, 0.1);
+  color: #ffc107;
+}
+
+.status-code.status-client-error {
+  background-color: rgba(255, 152, 0, 0.1);
+  color: #ff9800;
+}
+
+.status-code.status-server-error {
+  background-color: rgba(231, 76, 60, 0.1);
+  color: #e74c3c;
+}
+
+.encryption-status {
+  font-size: 12px;
+  padding: 2px 6px;
+  border-radius: 4px;
+}
+
+.encryption-status.encrypted {
+  background-color: rgba(255, 152, 0, 0.1);
+  color: #ff9800;
+}
+
+.encryption-status.decrypted {
+  background-color: rgba(40, 167, 69, 0.1);
+  color: #28a745;
+}
+
+/* 21121 Response JSON Container */
+.response-json-container {
+  margin: 15px 0;
+  padding: 15px;
+  border: 1px solid var(--border-color);
+  border-radius: 4px;
+  background-color: var(--bg-secondary);
+  max-width: 100%;
+  overflow: auto;
+}
+
+.response-json-container h3 {
+  margin-top: 0;
+  color: var(--text-primary);
+  font-size: 16px;
+  border-bottom: 1px solid var(--border-color);
+  padding-bottom: 8px;
+  margin-bottom: 12px;
+}
+
+.response-json-container pre.json-content {
+  background-color: var(--bg-tertiary);
+  border: 1px solid var(--border-color);
+  border-radius: 3px;
+  padding: 10px;
+  max-height: 300px;
+  overflow: auto;
+  font-family: monospace;
+  font-size: 13px;
+  white-space: pre-wrap;
+  word-break: break-word;
+  color: var(--text-primary);
 }
\ No newline at end of file
diff --git a/client/styles/http-messages-table.css b/client/styles/http-messages-table.css
new file mode 100644
index 0000000..39d5507
--- /dev/null
+++ b/client/styles/http-messages-table.css
@@ -0,0 +1,566 @@
+/* Table styles for HTTP Messages section */
+.http-messages-table {
+  width: 100%;
+  border-collapse: separate;
+  border-spacing: 0;
+  margin-bottom: 25px;
+  background-color: var(--bg-secondary);
+  border-radius: 10px;
+  overflow: hidden;
+  border: 1px solid var(--border-color);
+  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
+}
+
+.http-messages-table thead th {
+  background-color: var(--accent-color);
+  color: white;
+  font-weight: 600;
+  text-align: left;
+  padding: 14px 18px;
+  border-bottom: 2px solid rgba(255, 255, 255, 0.1);
+  position: relative;
+}
+
+/* Add subtle highlight to table header */
+.http-messages-table thead:after {
+  content: '';
+  position: absolute;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  height: 1px;
+  background: linear-gradient(to right, transparent, rgba(255, 255, 255, 0.3), transparent);
+}
+
+.http-messages-table tbody tr {
+  border-bottom: 1px solid var(--border-color);
+  transition: background-color 0.2s ease;
+  cursor: pointer;
+}
+
+.http-messages-table tbody tr:hover {
+  background-color: var(--bg-tertiary);
+}
+
+.http-messages-table tbody tr.selected {
+  background-color: var(--bg-tertiary);
+  border-left: 4px solid var(--accent-color);
+}
+
+.http-messages-table tbody tr:last-child {
+  border-bottom: none;
+}
+
+.http-messages-table td {
+  padding: 14px 18px;
+  vertical-align: middle;
+  transition: all 0.25s ease;
+}
+
+.http-messages-table tbody tr:hover td {
+  color: var(--text-primary);
+}
+
+.http-messages-table .sender-cell {
+  max-width: 200px;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+  font-family: 'Consolas', 'Courier New', monospace;
+  color: var(--text-secondary);
+  background-color: rgba(0, 0, 0, 0.02);
+  transition: all 0.25s ease;
+}
+
+.http-messages-table tr:hover .sender-cell {
+  color: var(--accent-color);
+}
+
+.http-messages-table .time-cell {
+  white-space: nowrap;
+  color: var(--text-tertiary);
+  font-size: 0.9em;
+}
+
+.http-messages-table .event-id-cell {
+  font-family: 'Consolas', 'Courier New', monospace;
+  color: var(--accent-color);
+  font-size: 0.9em;
+  font-weight: 500;
+  padding: 6px 8px;
+  background-color: rgba(var(--accent-color-rgb, 13, 110, 253), 0.05);
+  border-radius: 4px;
+  display: inline-block;
+}
+
+.http-messages-table .response-cell {
+  text-align: center;
+  width: 80px;
+}
+
+.response-indicator {
+  display: inline-flex;
+  align-items: center;
+  justify-content: center;
+  font-size: 14px;
+  width: 24px;
+  height: 24px;
+  line-height: 1;
+  text-align: center;
+  border-radius: 50%;
+  transition: all 0.3s ease;
+}
+
+.response-indicator.has-response {
+  color: white;
+  background-color: var(--accent-color);
+  font-weight: bold;
+  box-shadow: 0 2px 5px rgba(var(--accent-color-rgb, 13, 110, 253), 0.4);
+}
+
+.response-indicator.no-response {
+  color: var(--text-tertiary);
+  opacity: 0.7;
+  background-color: var(--bg-tertiary);
+  border: 1px solid var(--border-color);
+}
+
+.http-messages-table tr:hover .response-indicator.has-response {
+  transform: scale(1.1);
+}
+
+/* Expandable content styles */
+.expandable-content {
+  display: none;
+  padding: 0;
+  background-color: var(--bg-tertiary);
+  border-top: 1px solid var(--border-color);
+  box-shadow: inset 0 4px 6px rgba(0, 0, 0, 0.05);
+  transition: all 0.3s ease;
+}
+
+.expandable-content.expanded {
+  display: table-row;
+  animation: expandFade 0.3s ease-in-out;
+}
+
+@keyframes expandFade {
+  from {
+    opacity: 0;
+    transform: translateY(-10px);
+  }
+  to {
+    opacity: 1;
+    transform: translateY(0);
+  }
+}
+
+.expandable-cell {
+  padding: 0 !important;
+}
+
+.expandable-inner {
+  padding: 20px;
+}
+
+/* Tab styles inside expandable content */
+.details-tabs {
+  border-bottom: 1px solid var(--border-color);
+  display: flex;
+  padding: 10px 20px 0;
+  background-color: var(--bg-tertiary);
+  flex-wrap: wrap;
+  gap: 5px;
+}
+
+.details-tab {
+  padding: 10px 15px;
+  cursor: pointer;
+  border: 1px solid var(--border-color);
+  border-bottom: none;
+  margin-right: 5px;
+  transition: all 0.3s ease;
+  border-radius: 4px 4px 0 0;
+  background-color: var(--bg-secondary);
+  font-weight: 500;
+  position: relative;
+  bottom: -1px;
+  outline: none;
+}
+
+.details-tab:hover {
+  color: var(--accent-color);
+  background-color: var(--bg-tertiary);
+}
+
+.details-tab.active {
+  color: var(--accent-color);
+  border-bottom-color: var(--bg-tertiary);
+  background-color: var(--bg-tertiary);
+  z-index: 2;
+}
+.details-tab-content {
+  display: none;
+  padding: 20px;
+  border-top: 1px solid var(--border-color);
+  background-color: var(--bg-tertiary);
+}
+
+.details-tab-content.active {
+  display: block;
+}
+
+/* Styling for the HTTP Response and Request tabs */
+.details-tab-content h3 {
+  margin-top: 0;
+  color: var(--accent-color);
+  margin-bottom: 15px;
+  padding-bottom: 10px;
+  border-bottom: 1px solid var(--border-color);
+}
+
+.details-tab-content pre {
+  background-color: var(--bg-secondary);
+  padding: 18px;
+  border-radius: 6px;
+  max-height: 300px;
+  overflow-y: auto;
+  border: 1px solid var(--border-color);
+  font-family: 'Consolas', 'Courier New', monospace;
+  font-size: 14px;
+  line-height: 1.5;
+  color: var(--text-primary);
+  box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05);
+}
+
+/* Loading indicator and no responses message */
+.loading-response, .no-responses {
+  padding: 20px;
+  text-align: center;
+  color: var(--text-tertiary);
+  background-color: var(--bg-secondary);
+  border-radius: 8px;
+  border: 1px solid var(--border-color);
+  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.05);
+  font-style: italic;
+}
+
+/* Empty state */
+.table-empty-state {
+  padding: 30px;
+  text-align: center;
+  color: var(--text-tertiary);
+  font-style: italic;
+}
+
+/* Responsive adjustments */
+@media (max-width: 768px) {
+  .http-messages-table {
+    display: block;
+    overflow-x: auto;
+  }
+  
+  .http-messages-table td.event-id-cell {
+    max-width: 100px;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+  }
+}
+
+/* Modal styles */
+.http-messages-modal {
+  display: none;
+  position: fixed;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  background-color: rgba(0, 0, 0, 0.5);
+  z-index: 1000;
+  overflow: auto;
+}
+
+.modal-content {
+  position: relative;
+  background-color: var(--bg-secondary);
+  margin: 5% auto;
+  padding: 0;
+  width: 90%;
+  max-width: 1000px;
+  border-radius: 8px;
+  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
+  max-height: 85vh;
+  display: flex;
+  flex-direction: column;
+}
+
+.modal-close-button {
+  position: absolute;
+  top: 10px;
+  right: 15px;
+  font-size: 24px;
+  font-weight: bold;
+  color: var(--text-tertiary);
+  background: none;
+  border: none;
+  cursor: pointer;
+  z-index: 2;
+}
+
+.modal-close-button:hover {
+  color: var(--accent-color);
+}
+
+/* Modal tabs */
+.modal-tabs {
+  display: flex;
+  padding: 15px 15px 0;
+  border-bottom: 1px solid var(--border-color);
+  background-color: var(--bg-tertiary);
+  border-radius: 8px 8px 0 0;
+  flex-wrap: wrap;
+  gap: 5px;
+}
+
+.modal-tab {
+  padding: 10px 15px;
+  cursor: pointer;
+  border: 1px solid var(--border-color);
+  border-bottom: none;
+  margin-right: 5px;
+  transition: all 0.3s ease;
+  border-radius: 4px 4px 0 0;
+  background-color: var(--bg-secondary);
+  color: var(--text-primary);
+  font-weight: 500;
+  position: relative;
+  bottom: -1px;
+  outline: none;
+}
+
+.modal-tab:hover {
+  color: var(--accent-color);
+  background-color: var(--bg-tertiary);
+}
+
+.modal-tab.active {
+  color: var(--accent-color);
+  border-bottom-color: var(--bg-tertiary);
+  background-color: var(--bg-tertiary);
+  z-index: 2;
+}
+
+/* Modal tab contents */
+.modal-tab-contents {
+  padding: 20px;
+  background-color: var(--bg-tertiary);
+  overflow-y: auto;
+  flex: 1;
+  border-radius: 0 0 8px 8px;
+}
+
+.modal-tab-content {
+  display: none;
+  max-height: 60vh;
+  overflow-y: auto;
+}
+
+.modal-tab-content pre {
+  background-color: var(--bg-secondary);
+  padding: 15px;
+  border-radius: 4px;
+  overflow-x: auto;
+  border: 1px solid var(--border-color);
+  margin: 0;
+}
+
+.json-content {
+  font-family: 'Consolas', 'Courier New', monospace;
+  font-size: 14px;
+  white-space: pre-wrap;
+  line-height: 1.5;
+  color: var(--text-primary);
+}
+
+/* Add syntax highlighting for JSON content */
+.json-content .string { color: #25c2a0; }
+.json-content .number { color: #f5a623; }
+.json-content .boolean { color: #7e57c2; }
+.json-content .null { color: #bc4749; }
+.json-content .key { color: #0088cc; font-weight: 500; }
+
+/* Modal update notification */
+.modal-update-notification {
+  position: absolute;
+  top: 15px;
+  left: 50%;
+  transform: translateX(-50%);
+  background-color: var(--accent-color);
+  color: white;
+  padding: 8px 16px;
+  border-radius: 4px;
+  font-weight: 500;
+  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
+  z-index: 3;
+  animation: fadeInOut 3s ease-in-out;
+}
+
+@keyframes fadeInOut {
+  0% { opacity: 0; transform: translateX(-50%) translateY(-10px); }
+  15% { opacity: 1; transform: translateX(-50%) translateY(0); }
+  85% { opacity: 1; transform: translateX(-50%) translateY(0); }
+  100% { opacity: 0; transform: translateX(-50%) translateY(-10px); }
+}
+
+.no-response {
+  padding: 15px;
+  text-align: center;
+  color: var(--text-tertiary);
+  background-color: var(--bg-secondary);
+  border-radius: 4px;
+  border: 1px solid var(--border-color);
+  margin: 20px 0;
+}
+
+/* HTTP content formatting - Enhanced */
+.http-first-line {
+  font-weight: bold;
+  margin-bottom: 12px;
+  padding: 12px 15px;
+  border-bottom: 1px solid var(--border-color);
+  background-color: rgba(var(--accent-color-rgb, 13, 110, 253), 0.05);
+  border-radius: 6px 6px 0 0;
+}
+
+.http-method {
+  color: #0088cc;
+  font-weight: bold;
+  margin-right: 12px;
+  background-color: rgba(0, 136, 204, 0.1);
+  padding: 2px 8px;
+  border-radius: 4px;
+}
+
+.http-path {
+  color: var(--text-primary);
+  margin-right: 12px;
+  font-family: 'Consolas', 'Courier New', monospace;
+}
+
+.http-version {
+  color: var(--text-tertiary);
+  background-color: var(--bg-tertiary);
+  padding: 2px 6px;
+  border-radius: 4px;
+  font-size: 0.9em;
+}
+
+.http-status {
+  padding: 3px 8px;
+  border-radius: 6px;
+  margin: 0 12px;
+  font-weight: 600;
+  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
+}
+
+.http-status.success {
+  background-color: rgba(40, 167, 69, 0.9);
+  color: white;
+}
+
+.http-status.error {
+  background-color: rgba(220, 53, 69, 0.9);
+  color: white;
+}
+
+.http-status.redirect {
+  background-color: rgba(253, 126, 20, 0.9);
+  color: white;
+}
+
+.http-status-text {
+  color: var(--text-primary);
+  font-weight: 500;
+}
+
+.http-headers {
+  margin-bottom: 20px;
+  padding: 15px;
+  border-bottom: 1px dashed var(--border-color);
+  background-color: var(--bg-secondary);
+  border-radius: 4px;
+}
+
+.http-header {
+  margin-bottom: 8px;
+  padding-bottom: 8px;
+  border-bottom: 1px dotted rgba(var(--border-color-rgb, 222, 226, 230), 0.5);
+  display: flex;
+  flex-wrap: wrap;
+}
+
+.http-header:last-child {
+  margin-bottom: 0;
+  padding-bottom: 0;
+  border-bottom: none;
+}
+
+.http-header-name {
+  color: #0088cc;
+  font-weight: 600;
+  margin-right: 10px;
+  min-width: 120px;
+  font-family: 'Consolas', 'Courier New', monospace;
+}
+
+.http-header-value {
+  color: var(--text-primary);
+  flex: 1;
+  font-family: 'Consolas', 'Courier New', monospace;
+  word-break: break-all;
+}
+
+.http-body {
+  font-family: 'Consolas', 'Courier New', monospace;
+  white-space: pre-wrap;
+  word-break: break-all;
+  padding: 15px;
+  background-color: var(--bg-secondary);
+  border-radius: 4px;
+  border: 1px solid var(--border-color);
+  box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05);
+}
+
+.http-body.json {
+  color: var(--accent-color);
+}
+
+/* Add a label before the body content */
+.http-body-label {
+  display: block;
+  margin-bottom: 10px;
+  font-weight: 600;
+  color: var(--text-secondary);
+  border-bottom: 1px dotted var(--border-color);
+  padding-bottom: 8px;
+}
+
+/* Responsive modal */
+@media (max-width: 768px) {
+  .modal-content {
+    width: 95%;
+    margin: 10% auto;
+  }
+  
+  .modal-tabs {
+    flex-direction: column;
+    padding: 10px 10px 0;
+  }
+  
+  .modal-tab {
+    margin-bottom: 5px;
+    width: 100%;
+    text-align: left;
+  }
+}
\ No newline at end of file