diff --git a/.gitignore b/.gitignore
index 646ac519..7bc6d2df 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,4 @@
.DS_Store
node_modules/
+build/
+.npmrc
diff --git a/package.json b/package.json
index 68f558bb..e7752c23 100644
--- a/package.json
+++ b/package.json
@@ -116,5 +116,8 @@
"src/**/*.{js,jsx,ts,tsx,json,css,scss,md}": [
"prettier --write"
]
+ },
+ "volta": {
+ "node": "18.20.8"
}
}
diff --git a/public/frames/index.html b/public/frames/index.html
index 0ef96e66..87156cf2 100644
--- a/public/frames/index.html
+++ b/public/frames/index.html
@@ -1,4 +1,4 @@
-
+
diff --git a/public/mixed-nesting/deep-level-2.html b/public/mixed-nesting/deep-level-2.html
new file mode 100644
index 00000000..f6e94993
--- /dev/null
+++ b/public/mixed-nesting/deep-level-2.html
@@ -0,0 +1,54 @@
+
+
+
+ Deep Nesting — Level 2 iframe document
+
+
+
+
+Level 2 — Iframe
+
+
+
+
+
+
diff --git a/public/mixed-nesting/deep-level-4.html b/public/mixed-nesting/deep-level-4.html
new file mode 100644
index 00000000..e620610b
--- /dev/null
+++ b/public/mixed-nesting/deep-level-4.html
@@ -0,0 +1,106 @@
+
+
+
+ Deep Nesting — Level 4 iframe document
+
+
+
+
+Level 4 — Iframe
+
+
+
+
+
+
+
diff --git a/public/mixed-nesting/deep-level-6.html b/public/mixed-nesting/deep-level-6.html
new file mode 100644
index 00000000..9824b3af
--- /dev/null
+++ b/public/mixed-nesting/deep-level-6.html
@@ -0,0 +1,47 @@
+
+
+
+ Deep Nesting — Level 6 final content
+
+
+
+
+Level 6 — Iframe (deepest)
+You reached the deepest level. Path from the top:
+
+ Level 1 — Shadow Root
+ Level 2 — Iframe
+ Level 3 — Shadow Root
+ Level 4 — Iframe
+ Level 5 — Shadow Root
+ Level 6 — Iframe (this document)
+
+Deepest Button
+
+
diff --git a/public/mixed-nesting/deep-nested.html b/public/mixed-nesting/deep-nested.html
new file mode 100644
index 00000000..0edf752a
--- /dev/null
+++ b/public/mixed-nesting/deep-nested.html
@@ -0,0 +1,60 @@
+
+
+
+ 6 Levels Deep — Shadow + Iframe
+
+
+
+
+
+6-Level Nested: Shadow ➜ Iframe ➜ Shadow ➜ Iframe ➜ Shadow ➜ Iframe
+Each step alternates between a Shadow Root and an Iframe. Click into the deepest
+ iframe to see content rendered at nesting depth 6.
+
+
+
+Shadow root mode:
+ (toggle via ?modeOpen=true or ?modeOpen=false — propagates through all 6 levels).
+
+
+
+
+
diff --git a/public/mixed-nesting/iframe-in-shadow.html b/public/mixed-nesting/iframe-in-shadow.html
new file mode 100644
index 00000000..3fbf16da
--- /dev/null
+++ b/public/mixed-nesting/iframe-in-shadow.html
@@ -0,0 +1,60 @@
+
+
+
+ Iframe in Shadow Root
+
+
+
+
+
+Iframe in Shadow Root
+The host below has a shadow root, and inside that shadow root there is an iframe
+ loading a separate document.
+
+
+
+Shadow root mode:
+ (toggle via ?modeOpen=true or ?modeOpen=false — propagates into the iframe).
+
+
+
+
+
diff --git a/public/mixed-nesting/index.html b/public/mixed-nesting/index.html
new file mode 100644
index 00000000..ec6eb913
--- /dev/null
+++ b/public/mixed-nesting/index.html
@@ -0,0 +1,22 @@
+
+
+
+
+
+ Mixed Nesting test page
+
+
+
+
+
+
diff --git a/public/mixed-nesting/shadow-iframe-content.html b/public/mixed-nesting/shadow-iframe-content.html
new file mode 100644
index 00000000..5ab92bf7
--- /dev/null
+++ b/public/mixed-nesting/shadow-iframe-content.html
@@ -0,0 +1,51 @@
+
+
+
+ Inner Iframe Content
+
+
+
+
+I am the iframe inside a shadow root
+This document is loaded inside an iframe that lives in the parent page's shadow root.
+Iframe Button
+
+
+
diff --git a/public/mixed-nesting/shadow-in-iframe-content.html b/public/mixed-nesting/shadow-in-iframe-content.html
new file mode 100644
index 00000000..9e0fccee
--- /dev/null
+++ b/public/mixed-nesting/shadow-in-iframe-content.html
@@ -0,0 +1,85 @@
+
+
+
+ Iframe Body with Shadow Root
+
+
+
+
+I am the iframe document
+This paragraph lives in the iframe's light DOM and is styled red.
+
+
+
+
+
+
+
diff --git a/public/mixed-nesting/shadow-in-iframe.html b/public/mixed-nesting/shadow-in-iframe.html
new file mode 100644
index 00000000..c240b178
--- /dev/null
+++ b/public/mixed-nesting/shadow-in-iframe.html
@@ -0,0 +1,42 @@
+
+
+
+ Shadow Root in Iframe
+
+
+
+
+
+Shadow Root in Iframe
+The iframe below loads a separate document. That document attaches a shadow root
+ to a host element inside its own body.
+Shadow root mode:
+ (toggle via ?modeOpen=true or ?modeOpen=false — propagates into the iframe).
+
+
+
+
+
+
diff --git a/public/shadow-dom/_mode.js b/public/shadow-dom/_mode.js
new file mode 100644
index 00000000..ad597c52
--- /dev/null
+++ b/public/shadow-dom/_mode.js
@@ -0,0 +1,13 @@
+// Reads ?modeOpen=true|false from the URL (default: 'open') and, when a
+// #mode-indicator element is present, writes the resolved value into its
+// text and data-mode attribute. Returns the resolved mode.
+window.resolveShadowMode = function () {
+ const params = new URLSearchParams(window.location.search);
+ const mode = params.get('modeOpen') === 'false' ? 'closed' : 'open';
+ const indicator = document.getElementById('mode-indicator');
+ if (indicator) {
+ indicator.textContent = mode;
+ indicator.dataset.mode = mode;
+ }
+ return mode;
+};
diff --git a/public/shadow-dom/index.html b/public/shadow-dom/index.html
new file mode 100644
index 00000000..69becf5b
--- /dev/null
+++ b/public/shadow-dom/index.html
@@ -0,0 +1,19 @@
+
+
+
+
+
+ Shadow DOM test page
+
+
+
+
+
+
diff --git a/public/shadow-dom/nested-shadow-root.html b/public/shadow-dom/nested-shadow-root.html
new file mode 100644
index 00000000..ded5fc6c
--- /dev/null
+++ b/public/shadow-dom/nested-shadow-root.html
@@ -0,0 +1,142 @@
+
+
+
+ Nested Shadow Root Example
+
+
+
+
+
+Nested Shadow Root Example
+The widget below has an outer shadow root, and inside that shadow root
+ there is another host element with its own shadow root.
+ Three style boundaries: page, outer shadow, inner shadow.
+
+
+
+Shadow root mode:
+ (toggle via ?modeOpen=true or ?modeOpen=false in the URL — applies to both nested levels).
+
+
+
+
+
diff --git a/public/shadow-dom/shadow-root.html b/public/shadow-dom/shadow-root.html
new file mode 100644
index 00000000..fc506d56
--- /dev/null
+++ b/public/shadow-dom/shadow-root.html
@@ -0,0 +1,120 @@
+
+
+
+ Shadow Root Example
+
+
+
+
+
+Shadow Root Example
+Both cards below use the SAME class name (.card) and the same tags (p, button).
+ The page stylesheet styles .card as red/dashed. If encapsulation works, only the LIGHT DOM card
+ picks up those red styles — the SHADOW DOM card stays blue because page CSS cannot pierce the shadow boundary.
+
+
+
+
I am the LIGHT DOM card. Page CSS reaches me — I'm red.
+
Light Button
+
+
+
+
+
+Shadow root mode:
+ (toggle via ?modeOpen=true or ?modeOpen=false in the URL).
+
+
+
+
+