Modernize and streamline Sketch top bar UI

Comprehensive improvements to the top bar interface:

Removed Elements:
- Poll checkbox and all polling UI controls
- Network status indicator and all status messages
- Dotted underlines from tooltip elements

Button Improvements:
- Added SVG icons to Restart and Stop buttons
- Made buttons responsive (text hides below 1400px)
- Stop button now disabled when no active calls

Layout Simplification:
- Simplified hostname display (outside hostname only)
- Simplified working directory display (outside directory only)
- Repositioned tab chooser for better layout
- Improved responsive behavior across viewport sizes

Enhanced Features:
- Added GitHub repo auto-detection with clickable links
- Improved VSCode integration with button styling
- Changed 'SSH Connection' to 'Connect to Container'
- Enhanced tooltips with more descriptive text

The UI is now cleaner, more responsive, and provides a better user experience
across different screen sizes.

Co-Authored-By: sketch <hello@sketch.dev>
diff --git a/webui/src/web-components/sketch-app-shell.ts b/webui/src/web-components/sketch-app-shell.ts
index 7c618aa..157f2f2 100644
--- a/webui/src/web-components/sketch-app-shell.ts
+++ b/webui/src/web-components/sketch-app-shell.ts
@@ -230,7 +230,8 @@
       margin-right: 50px;
     }
 
-    .restart-button {
+    .restart-button,
+    .stop-button {
       background: #2196f3;
       color: white;
       border: none;
@@ -239,6 +240,9 @@
       cursor: pointer;
       font-size: 12px;
       margin-right: 5px;
+      display: flex;
+      align-items: center;
+      gap: 6px;
     }
 
     .restart-button:hover {
@@ -251,28 +255,43 @@
       opacity: 0.6;
     }
 
-    .refresh-button {
-      background: #4caf50;
+    .stop-button {
+      background: #dc3545;
       color: white;
-      border: none;
-      padding: 4px 10px;
-      border-radius: 4px;
-      cursor: pointer;
-      font-size: 12px;
-      margin-right: 5px;
     }
 
-    .stop-button:hover {
-      background-color: #c82333 !important;
+    .stop-button:hover:not(:disabled) {
+      background-color: #c82333;
     }
 
-    .poll-updates {
-      display: flex;
-      align-items: center;
-      font-size: 12px;
-      margin-right: 10px;
+    .stop-button:disabled {
+      background-color: #e9a8ad;
+      cursor: not-allowed;
+      opacity: 0.7;
     }
 
+    .stop-button:disabled:hover {
+      background-color: #e9a8ad;
+    }
+
+    .button-icon {
+      width: 16px;
+      height: 16px;
+    }
+
+    @media (max-width: 1400px) {
+      .button-text {
+        display: none;
+      }
+
+      .restart-button,
+      .stop-button {
+        padding: 6px;
+      }
+    }
+
+    /* Removed poll-updates class */
+
     .notifications-toggle {
       display: flex;
       align-items: center;
@@ -320,9 +339,6 @@
   @property()
   connectionErrorMessage: string = "";
 
-  @property()
-  messageStatus: string = "";
-
   // Chat messages
   @property({ attribute: false })
   messages: AgentMessage[] = [];
@@ -729,18 +745,8 @@
   private handleDataChanged(eventData: {
     state: State;
     newMessages: AgentMessage[];
-    isFirstFetch?: boolean;
   }): void {
-    const { state, newMessages, isFirstFetch } = eventData;
-
-    // Check if this is the first data fetch or if there are new messages
-    if (isFirstFetch) {
-      this.messageStatus = "Initial messages loaded";
-    } else if (newMessages && newMessages.length > 0) {
-      this.messageStatus = "Updated just now";
-    } else {
-      this.messageStatus = "No new messages";
-    }
+    const { state, newMessages } = eventData;
 
     // Update state if we received it
     if (state) {
@@ -768,7 +774,7 @@
     this.updateLastCommitInfo(newMessages);
 
     // Check for agent messages with end_of_turn=true and show notifications
-    if (newMessages && newMessages.length > 0 && !isFirstFetch) {
+    if (newMessages && newMessages.length > 0) {
       for (const message of newMessages) {
         if (
           message.type === "agent" &&
@@ -858,10 +864,9 @@
         );
       }
 
-      this.messageStatus = "Stop request sent";
+      // Stop request sent
     } catch (error) {
       console.error("Error stopping operation:", error);
-      this.messageStatus = "Failed to stop operation";
     }
   }
 
@@ -927,14 +932,14 @@
           <h2 id="chatTitle" class="chat-title">${this.title}</h2>
         </div>
 
-        <!-- Views section with tabs -->
-        <sketch-view-mode-select></sketch-view-mode-select>
-
-        <!-- Container status info -->
+        <!-- Container status info moved above tabs -->
         <sketch-container-status
           .state=${this.containerState}
         ></sketch-container-status>
 
+        <!-- Views section with tabs - repositioned -->
+        <sketch-view-mode-select></sketch-view-mode-select>
+
         ${this.lastCommit
           ? html`
               <div
@@ -963,23 +968,49 @@
             ?disabled=${this.containerState.message_count === 0}
             @click=${this.openRestartModal}
           >
-            Restart
+            <svg
+              class="button-icon"
+              xmlns="http://www.w3.org/2000/svg"
+              viewBox="0 0 24 24"
+              fill="none"
+              stroke="currentColor"
+              stroke-width="2"
+              stroke-linecap="round"
+              stroke-linejoin="round"
+            >
+              <path d="M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8" />
+              <path d="M3 3v5h5" />
+            </svg>
+            <span class="button-text">Restart</span>
           </button>
-          <button id="stopButton" class="refresh-button stop-button">
-            Stop
+          <button
+            id="stopButton"
+            class="stop-button"
+            ?disabled=${(this.containerState?.outstanding_llm_calls || 0) ===
+              0 &&
+            (this.containerState?.outstanding_tool_calls || []).length === 0}
+          >
+            <svg
+              class="button-icon"
+              xmlns="http://www.w3.org/2000/svg"
+              viewBox="0 0 24 24"
+              fill="none"
+              stroke="currentColor"
+              stroke-width="2"
+              stroke-linecap="round"
+              stroke-linejoin="round"
+            >
+              <rect x="6" y="6" width="12" height="12" />
+            </svg>
+            <span class="button-text">Stop</span>
           </button>
 
-          <div class="poll-updates">
-            <input type="checkbox" id="pollToggle" checked />
-            <label for="pollToggle">Poll</label>
-          </div>
-
           <div
             class="notifications-toggle"
             @click=${this._handleNotificationsToggle}
             title="${this.notificationsEnabled
               ? "Disable"
-              : "Enable"} notifications"
+              : "Enable"} notifications when the agent completes its turn"
           >
             <div
               class="bell-icon ${!this.notificationsEnabled
@@ -1002,7 +1033,6 @@
           </div>
 
           <sketch-network-status
-            message=${this.messageStatus}
             connection=${this.connectionStatus}
             error=${this.connectionErrorMessage}
           ></sketch-network-status>
@@ -1096,18 +1126,8 @@
       }
     });
 
-    const pollToggleCheckbox = this.renderRoot?.querySelector(
-      "#pollToggle",
-    ) as HTMLInputElement;
-    pollToggleCheckbox?.addEventListener("change", () => {
-      this.dataManager.setPollingEnabled(pollToggleCheckbox.checked);
-      if (!pollToggleCheckbox.checked) {
-        this.connectionStatus = "disabled";
-        this.messageStatus = "Polling stopped";
-      } else {
-        this.messageStatus = "Polling for updates...";
-      }
-    });
+    // Always enable polling by default
+    this.dataManager.setPollingEnabled(true);
 
     // Process any existing messages to find commit information
     if (this.messages && this.messages.length > 0) {
diff --git a/webui/src/web-components/sketch-container-status.ts b/webui/src/web-components/sketch-container-status.ts
index f4c0f25..ba745cc 100644
--- a/webui/src/web-components/sketch-container-status.ts
+++ b/webui/src/web-components/sketch-container-status.ts
@@ -74,8 +74,7 @@
     }
 
     [title] {
-      cursor: help;
-      text-decoration: underline dotted;
+      cursor: default;
     }
 
     .cost {
@@ -180,11 +179,33 @@
     }
 
     .vscode-link {
+      color: white;
+      text-decoration: none;
+      background-color: #0066b8;
+      padding: 4px 8px;
+      border-radius: 4px;
+      display: flex;
+      align-items: center;
+      gap: 6px;
+      font-size: 12px;
+      transition: all 0.2s ease;
+    }
+
+    .vscode-link:hover {
+      background-color: #005091;
+    }
+
+    .vscode-icon {
+      width: 16px;
+      height: 16px;
+    }
+
+    .github-link {
       color: #2962ff;
       text-decoration: none;
     }
 
-    .vscode-link:hover {
+    .github-link:hover {
       text-decoration: underline;
     }
   `;
@@ -212,33 +233,25 @@
   }
 
   formatHostname() {
+    // Only display outside hostname
     const outsideHostname = this.state?.outside_hostname;
-    const insideHostname = this.state?.inside_hostname;
 
-    if (!outsideHostname || !insideHostname) {
+    if (!outsideHostname) {
       return this.state?.hostname;
     }
 
-    if (outsideHostname === insideHostname) {
-      return outsideHostname;
-    }
-
-    return `${outsideHostname}:${insideHostname}`;
+    return outsideHostname;
   }
 
   formatWorkingDir() {
+    // Only display outside working directory
     const outsideWorkingDir = this.state?.outside_working_dir;
-    const insideWorkingDir = this.state?.inside_working_dir;
 
-    if (!outsideWorkingDir || !insideWorkingDir) {
+    if (!outsideWorkingDir) {
       return this.state?.working_dir;
     }
 
-    if (outsideWorkingDir === insideWorkingDir) {
-      return outsideWorkingDir;
-    }
-
-    return `${outsideWorkingDir}:${insideWorkingDir}`;
+    return outsideWorkingDir;
   }
 
   getHostnameTooltip() {
@@ -298,6 +311,33 @@
     return `sketch-${this.state?.session_id}`;
   }
 
+  // Format GitHub repository URL to org/repo format
+  formatGitHubRepo(url) {
+    if (!url) return null;
+
+    // Common GitHub URL patterns
+    const patterns = [
+      // HTTPS URLs
+      /https:\/\/github\.com\/([^/]+)\/([^/\s.]+)(?:\.git)?/,
+      // SSH URLs
+      /git@github\.com:([^/]+)\/([^/\s.]+)(?:\.git)?/,
+      // Git protocol
+      /git:\/\/github\.com\/([^/]+)\/([^/\s.]+)(?:\.git)?/,
+    ];
+
+    for (const pattern of patterns) {
+      const match = url.match(pattern);
+      if (match) {
+        return {
+          formatted: `${match[1]}/${match[2]}`,
+          url: `https://github.com/${match[1]}/${match[2]}`,
+        };
+      }
+    }
+
+    return null;
+  }
+
   renderSSHSection() {
     // Only show SSH section if we're in a Docker container and have session ID
     if (!this.state?.session_id) {
@@ -312,7 +352,7 @@
     if (!this.state?.ssh_available) {
       return html`
         <div class="ssh-section">
-          <h3>SSH Connection</h3>
+          <h3>Connect to Container</h3>
           <div class="ssh-warning">
             SSH connections are not available:
             ${this.state?.ssh_error || "SSH configuration is missing"}
@@ -323,7 +363,7 @@
 
     return html`
       <div class="ssh-section">
-        <h3>SSH Connection</h3>
+        <h3>Connect to Container</h3>
         <div class="ssh-command">
           <div class="ssh-command-text">${sshCommand}</div>
           <button
@@ -343,7 +383,23 @@
           </button>
         </div>
         <div class="ssh-command">
-          <a href="${vscodeURL}" class="vscode-link">${vscodeURL}</a>
+          <a href="${vscodeURL}" class="vscode-link" title="${vscodeURL}">
+            <svg
+              class="vscode-icon"
+              xmlns="http://www.w3.org/2000/svg"
+              viewBox="0 0 24 24"
+              fill="none"
+              stroke="white"
+              stroke-width="2"
+              stroke-linecap="round"
+              stroke-linejoin="round"
+            >
+              <path
+                d="M16.5 9.4 7.55 4.24a.35.35 0 0 0-.41.01l-1.23.93a.35.35 0 0 0-.14.29v13.04c0 .12.07.23.17.29l1.24.93c.13.1.31.09.43-.01L16.5 14.6l-6.39 4.82c-.16.12-.38.12-.55.01l-1.33-1.01a.35.35 0 0 1-.14-.28V5.88c0-.12.07-.23.18-.29l1.23-.93c.14-.1.32-.1.46 0l6.54 4.92-6.54 4.92c-.14.1-.32.1-.46 0l-1.23-.93a.35.35 0 0 1-.18-.29V5.88c0-.12.07-.23.17-.29l1.33-1.01c.16-.12.39-.11.55.01l6.39 4.81z"
+              />
+            </svg>
+            <span>Open in VSCode</span>
+          </a>
         </div>
       </div>
     `;
@@ -381,9 +437,30 @@
             ${this.state?.git_origin
               ? html`
                   <div class="info-item">
-                    <span id="gitOrigin" class="info-value"
-                      >${this.state?.git_origin}</span
-                    >
+                    ${(() => {
+                      const github = this.formatGitHubRepo(
+                        this.state?.git_origin,
+                      );
+                      if (github) {
+                        return html`
+                          <a
+                            href="${github.url}"
+                            target="_blank"
+                            rel="noopener noreferrer"
+                            class="github-link"
+                            title="${this.state?.git_origin}"
+                          >
+                            ${github.formatted}
+                          </a>
+                        `;
+                      } else {
+                        return html`
+                          <span id="gitOrigin" class="info-value"
+                            >${this.state?.git_origin}</span
+                          >
+                        `;
+                      }
+                    })()}
                   </div>
                 `
               : ""}
diff --git a/webui/src/web-components/sketch-network-status.test.ts b/webui/src/web-components/sketch-network-status.test.ts
index 45882a0..5c968d4 100644
--- a/webui/src/web-components/sketch-network-status.test.ts
+++ b/webui/src/web-components/sketch-network-status.test.ts
@@ -1,61 +1,26 @@
 import { test, expect } from "@sand4rt/experimental-ct-web";
 import { SketchNetworkStatus } from "./sketch-network-status";
 
-test("displays the correct connection status when connected", async ({
+// Test for when no error message is present - component should not render
+test("does not display anything when no error is provided", async ({
   mount,
 }) => {
   const component = await mount(SketchNetworkStatus, {
     props: {
       connection: "connected",
-      message: "Connected to server",
     },
   });
 
-  await expect(component.locator(".polling-indicator")).toBeVisible();
-  await expect(component.locator(".status-text")).toBeVisible();
-  await expect(component.locator(".polling-indicator.active")).toBeVisible();
-  await expect(component.locator(".status-text")).toContainText(
-    "Connected to server",
-  );
+  // The component should be empty
+  await expect(component.locator(".status-container")).not.toBeVisible();
 });
 
-test("displays the correct connection status when disconnected", async ({
-  mount,
-}) => {
-  const component = await mount(SketchNetworkStatus, {
-    props: {
-      connection: "disconnected",
-      message: "Disconnected",
-    },
-  });
-
-  await expect(component.locator(".polling-indicator")).toBeVisible();
-  await expect(component.locator(".polling-indicator.error")).toBeVisible();
-});
-
-test("displays the correct connection status when disabled", async ({
-  mount,
-}) => {
-  const component = await mount(SketchNetworkStatus, {
-    props: {
-      connection: "disabled",
-      message: "Disabled",
-    },
-  });
-
-  await expect(component.locator(".polling-indicator")).toBeVisible();
-  await expect(component.locator(".polling-indicator.error")).not.toBeVisible();
-  await expect(
-    component.locator(".polling-indicator.active"),
-  ).not.toBeVisible();
-});
-
+// Test that error message is displayed correctly
 test("displays error message when provided", async ({ mount }) => {
   const errorMsg = "Connection error";
   const component = await mount(SketchNetworkStatus, {
     props: {
       connection: "disconnected",
-      message: "Disconnected",
       error: errorMsg,
     },
   });
diff --git a/webui/src/web-components/sketch-network-status.ts b/webui/src/web-components/sketch-network-status.ts
index 2a0e455..cf168fd 100644
--- a/webui/src/web-components/sketch-network-status.ts
+++ b/webui/src/web-components/sketch-network-status.ts
@@ -7,9 +7,6 @@
   connection: string;
 
   @property()
-  message: string;
-
-  @property()
   error: string;
 
   // See https://lit.dev/docs/components/styles/ for how lit-element handles CSS.
@@ -23,37 +20,6 @@
       align-items: center;
     }
 
-    .polling-indicator {
-      display: inline-block;
-      width: 8px;
-      height: 8px;
-      border-radius: 50%;
-      margin-right: 4px;
-      background-color: #ccc;
-    }
-
-    .polling-indicator.active {
-      background-color: #4caf50;
-      animation: pulse 1.5s infinite;
-    }
-
-    .polling-indicator.error {
-      background-color: #f44336;
-      animation: pulse 1.5s infinite;
-    }
-
-    @keyframes pulse {
-      0% {
-        opacity: 1;
-      }
-      50% {
-        opacity: 0.5;
-      }
-      100% {
-        opacity: 1;
-      }
-    }
-
     .status-text {
       font-size: 11px;
       color: #666;
@@ -74,23 +40,15 @@
     super.disconnectedCallback();
   }
 
-  indicator() {
-    if (this.connection === "disabled") {
-      return "";
-    }
-    return this.connection === "connected" ? "active" : "error";
-  }
-
   render() {
+    // Only render if there's an error to display
+    if (!this.error) {
+      return html``;
+    }
+
     return html`
       <div class="status-container">
-        <span
-          id="pollingIndicator"
-          class="polling-indicator ${this.indicator()}"
-        ></span>
-        <span id="statusText" class="status-text"
-          >${this.error || this.message}</span
-        >
+        <span id="statusText" class="status-text">${this.error}</span>
       </div>
     `;
   }
diff --git a/webui/src/web-components/sketch-view-mode-select.ts b/webui/src/web-components/sketch-view-mode-select.ts
index 4c3c91f..3b94303 100644
--- a/webui/src/web-components/sketch-view-mode-select.ts
+++ b/webui/src/web-components/sketch-view-mode-select.ts
@@ -35,6 +35,16 @@
       white-space: nowrap;
     }
 
+    @media (max-width: 1400px) {
+      .tab-btn span:not(.tab-icon) {
+        display: none;
+      }
+
+      .tab-btn {
+        padding: 8px 10px;
+      }
+    }
+
     .tab-btn:not(:last-child) {
       border-right: 1px solid #eee;
     }