summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/_static/css/custom.css24
-rw-r--r--docs/_templates/layout.html40
2 files changed, 64 insertions, 0 deletions
diff --git a/docs/_static/css/custom.css b/docs/_static/css/custom.css
index cdb036d2..c19f436b 100644
--- a/docs/_static/css/custom.css
+++ b/docs/_static/css/custom.css
@@ -532,4 +532,28 @@ html {
.closeButtonDivLine {
bottom: 85px;
}
+}
+
+/* Cookiebot consent dialog — safety net (defense-in-depth).
+ Cookiebot delivers its dialog styling as a constructed stylesheet on
+ document.adoptedStyleSheets. The adoptedStyleSheets shim in layout.html keeps that
+ sheet from being dropped by another library (e.g. ReadTheDocs' readthedocs-addons.js,
+ which reassigns the whole list with a destructive replace). As a backstop, these
+ rules live in a regular stylesheet — which cascades *before* adopted stylesheets, so
+ Cookiebot's own CSS overrides every one of them whenever its sheet is present, and
+ they have no effect on the normal styled banner. They only take effect if that sheet
+ is ever absent, keeping the dialog a contained, scrollable, centered panel instead of
+ falling back to position:static and expanding to full page height. Only properties
+ Cookiebot itself sets are used here, so there is verifiably no leak into the good state. */
+#CybotCookiebotDialog {
+ position: fixed;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ max-width: 920px;
+ max-height: 90vh;
+ overflow: auto;
+ background: #fff;
+ box-shadow: 0 0 24px rgba(0, 0, 0, 0.25);
+ z-index: 2147483631;
} \ No newline at end of file
diff --git a/docs/_templates/layout.html b/docs/_templates/layout.html
index adc6278d..0b8ee41b 100644
--- a/docs/_templates/layout.html
+++ b/docs/_templates/layout.html
@@ -2,6 +2,46 @@
{%- set current_version = "1.4.x sagitta" %}
{% block extrahead %}
{% if gtm_id and cookiebot_id %}
+ {# Keep Cookiebot's consent dialog from rendering unstyled and breaking the page.
+ Cookiebot delivers its dialog CSS as a constructed stylesheet via
+ document.adoptedStyleSheets. That property holds the *whole* sheet list, and
+ ReadTheDocs' readthedocs-addons.js reassigns it with a destructive replace; when
+ that lands after Cookiebot's (network-gated) adoption it drops Cookiebot's sheet,
+ leaving #CybotCookiebotDialog at position:static, expanded to full page height.
+ This shim makes assignment preserve Cookiebot's sheet specifically. It must run
+ before the first adoptedStyleSheets write, so it is the first thing in <head>. #}
+ <script>
+ (function () {
+ try {
+ var desc = Object.getOwnPropertyDescriptor(Document.prototype, "adoptedStyleSheets");
+ if (!desc || !desc.get || !desc.set) return;
+ var guarded = null;
+ var isCookiebot = function (sheet) {
+ try {
+ var rules = sheet.cssRules;
+ for (var i = 0; i < rules.length; i++) {
+ if (rules[i].selectorText && rules[i].selectorText.indexOf("CybotCookiebotDialog") !== -1) return true;
+ }
+ } catch (e) {}
+ return false;
+ };
+ Object.defineProperty(document, "adoptedStyleSheets", {
+ configurable: true,
+ get: function () { return desc.get.call(document); },
+ set: function (sheets) {
+ for (var i = 0; i < sheets.length; i++) {
+ if (isCookiebot(sheets[i])) { guarded = sheets[i]; break; }
+ }
+ if (guarded && Array.prototype.indexOf.call(sheets, guarded) === -1) {
+ sheets = Array.prototype.slice.call(sheets).concat(guarded);
+ }
+ desc.set.call(document, sheets);
+ }
+ });
+ } catch (e) {}
+ })();
+ </script>
+
{# Cookiebot CMP — must load first so its auto-blocker can scan/block other tags #}
<script id="Cookiebot"
src="https://consent.cookiebot.com/uc.js"