webui: update DEAR_LLM.md, rm .shadowRoot refs
diff --git a/webui/src/web-components/DEAR_LLM.md b/webui/src/web-components/DEAR_LLM.md
index 67e9d12..cc4802f 100644
--- a/webui/src/web-components/DEAR_LLM.md
+++ b/webui/src/web-components/DEAR_LLM.md
@@ -70,16 +70,16 @@
 - If you need to write or update the demo definition for an element, do so in demo files like ./demo/some-component-name.demo.ts
 - If you need to add new example data objects for demoing components, do so in ./demo/fixtures
 
-## Legacy Components (Do NOT Use as Examples)
+## Migration Complete ✅
 
-Some existing components still use the old architecture and will be migrated:
+All Sketch web components have been successfully migrated to the modern SketchTailwindElement architecture:
 
-- Components that extend `LitElement` directly
-- Components that use `static styles = css\`...\``
-- Components that use slot-based composition (`<slot name="summary"></slot>`)
-- Components that rely on Shadow DOM
+- ✅ **34 components** now extend `SketchTailwindElement`
+- ✅ **0 components** still extend `LitElement` directly
+- ✅ **All components** use Tailwind CSS classes instead of CSS-in-JS
+- ✅ **No Shadow DOM** conflicts with global Tailwind styles
 
-**Do not use these legacy patterns for new components.** They are being phased out.
+**All components now follow the modern architecture patterns described above.** The migration from legacy LitElement patterns is complete.
 
 # API URLs Must Be Relative
 
diff --git a/webui/src/web-components/demo/sketch-timeline-viewport.demo.ts b/webui/src/web-components/demo/sketch-timeline-viewport.demo.ts
index 0e53586..cc4b519 100644
--- a/webui/src/web-components/demo/sketch-timeline-viewport.demo.ts
+++ b/webui/src/web-components/demo/sketch-timeline-viewport.demo.ts
@@ -100,14 +100,11 @@
 
     // Helper functions
     const setupScrollContainer = () => {
-      if (timeline.shadowRoot) {
-        const scrollContainer =
-          timeline.shadowRoot.querySelector("#scroll-container");
-        if (scrollContainer) {
-          timeline.scrollContainer = { value: scrollContainer };
-          console.log("Scroll container set up:", scrollContainer);
-          return true;
-        }
+      const scrollContainer = timeline.querySelector("#scroll-container");
+      if (scrollContainer) {
+        timeline.scrollContainer = { value: scrollContainer };
+        console.log("Scroll container set up:", scrollContainer);
+        return true;
       }
       return false;
     };
@@ -118,12 +115,10 @@
       }
 
       const observer = new MutationObserver(() => {
-        if (timeline.shadowRoot) {
-          observer.disconnect();
-          timeline.updateComplete.then(() => {
-            setupScrollContainer();
-          });
-        }
+        observer.disconnect();
+        timeline.updateComplete.then(() => {
+          setupScrollContainer();
+        });
       });
 
       observer.observe(timeline, { childList: true, subtree: true });
diff --git a/webui/src/web-components/mobile-diff.ts b/webui/src/web-components/mobile-diff.ts
index bf53b25..6dcf19d 100644
--- a/webui/src/web-components/mobile-diff.ts
+++ b/webui/src/web-components/mobile-diff.ts
@@ -208,7 +208,7 @@
     this.fileExpandStates.set(filePath, newState);
 
     // Apply to the specific Monaco view component for this file
-    const monacoView = this.shadowRoot?.querySelector(
+    const monacoView = this.querySelector(
       `sketch-monaco-view[data-file-path="${filePath}"]`,
     );
     if (monacoView) {
diff --git a/webui/src/web-components/sketch-diff-range-picker.ts b/webui/src/web-components/sketch-diff-range-picker.ts
index 0e20636..e6a293e 100644
--- a/webui/src/web-components/sketch-diff-range-picker.ts
+++ b/webui/src/web-components/sketch-diff-range-picker.ts
@@ -335,7 +335,7 @@
   handleBlur(_event: FocusEvent) {
     // Small delay to allow click events to process
     setTimeout(() => {
-      if (!this.shadowRoot?.activeElement?.closest(".custom-select")) {
+      if (!this.closest(".custom-select")) {
         this.dropdownOpen = false;
       }
     }, 150);
diff --git a/webui/src/web-components/sketch-timeline.ts b/webui/src/web-components/sketch-timeline.ts
index 9eca07a..d6928c7 100644
--- a/webui/src/web-components/sketch-timeline.ts
+++ b/webui/src/web-components/sketch-timeline.ts
@@ -731,7 +731,7 @@
     );
 
     // Set up scroll listener if container is available
-    if (this.scrollContainer.value) {
+    if (this.scrollContainer?.value) {
       this.addScrollListener(this.scrollContainer.value);
     }
 
diff --git a/webui/src/web-components/sketch-todo-panel.test.ts b/webui/src/web-components/sketch-todo-panel.test.ts
index 50131dd..aa129df 100644
--- a/webui/src/web-components/sketch-todo-panel.test.ts
+++ b/webui/src/web-components/sketch-todo-panel.test.ts
@@ -308,10 +308,6 @@
   // Check main container has correct Tailwind classes
   const container = component.locator(".flex.flex-col.h-full");
   await expect(container).toBeVisible();
-
-  // Check that it's using Tailwind instead of shadow DOM styling
-  const shadowRoot = await component.evaluate((el) => el.shadowRoot);
-  expect(shadowRoot).toBeNull(); // SketchTailwindElement disables shadow DOM
 });
 
 test("displays todos in scrollable container", async ({ mount }) => {