diff --git a/scripts/site_gates.py b/scripts/site_gates.py
new file mode 100644
index 0000000..10a936b
--- /dev/null
+++ b/scripts/site_gates.py
@@ -0,0 +1,128 @@
+# -*- coding: utf-8 -*-
+"""TASK-D3 site gates — mechanical checks against the static site's known failure mode:
+silent per-page drift. Run from the repo root: python scripts/site_gates.py
+
+Gates (all must pass; non-zero exit on any failure):
+ 1. BOM — every website/*.html begins with EF BB BF (byte-checked)
+ 2. emoji — zero emoji/pictographs in website/*.html (codepoint ranges; NEVER grep —
+ Windows grep false-negatives multibyte emoji, proven in D0)
+ 3. nav — the and blocks of all pages are identical
+ after stripping the active-link marker
+ 4. analytics — the umami snippet is present on every public page (nonpublic draft exempt)
+ 5. no-CDN — zero fonts.googleapis.com / fonts.gstatic.com references
+ 6. banned — zero legacy hexes / 999px radius / box-shadow in pages + site.css
+ 7. style — zero embedded