"""Cascade behavior verification harness. Tests four scenarios with Playwright Chromium: 1. CORE_UNLAYERED + THEME_UNLAYERED (status quo: file order wins) 2. CORE_UNLAYERED + THEME_LAYERED (the v3 question: does theme lose to core?) 3. CORE_UNLAYERED + THEME_LAYERED_WITH_IMPORTANT 4. CORE_UNLAYERED + THEME_HIGHER_SPECIFICITY The CSS Cascading and Inheritance Module Level 5 says: > Note: declarations in named layers lose to declarations in the implicit > "unlayered" group, when they have the same origin and importance. This script empirically confirms or refutes that for our actual Chromium target. If (2) shows core winning even when theme has higher specificity, then `@layer` is unusable for our theme. If (4) shows specificity beating layering, then the spec note is wrong (it is not — but the test exists to surface it). """ from __future__ import annotations import sys from pathlib import Path ROOT = Path(__file__).resolve().parents[2] OUT_DIR = ROOT / "dev" / "v3" / "cascade-probe" CORE_CSS = """ /* Pretend Obsidian core (unlayered). */ body { color: rgb(136, 136, 136); } p { font-size: 12px; color: rgb(136, 136, 136); } .cm-line p { font-size: 12px; color: rgb(136, 136, 136); } """ SCENARIOS = [ # (id, theme_css) ( "1-theme-unlayered-same-specificity", """ /* Theme: unlayered, same specificity, declared later. */ body { color: rgb(255, 0, 0); } p { font-size: 20px; color: rgb(255, 0, 0); } """, ), ( "2-theme-layered-same-specificity", """ @layer theme; @layer theme { body { color: rgb(255, 0, 0); } p { font-size: 20px; color: rgb(255, 0, 0); } } """, ), ( "3-theme-layered-with-important", """ @layer theme; @layer theme { body { color: rgb(255, 0, 0) !important; } p { font-size: 20px !important; color: rgb(255, 0, 0) !important; } } """, ), ( "4-theme-layered-higher-specificity", """ @layer theme; @layer theme { /* Higher specificity than the unlayered core selectors. */ body.theme-light { color: rgb(255, 0, 0); } .cm-line p { color: rgb(255, 0, 0); font-size: 20px; } } """, ), ( "5-theme-unlayered-equal-specificity-later", """ /* Same specificity as core's `.cm-line p`, declared later in cascade order. No @layer, no !important. This is the v2.30.14 / v3 default strategy. */ .cm-line p { color: rgb(255, 0, 0); font-size: 20px; } """, ), ( "6-theme-unlayered-higher-specificity", """ /* Higher specificity than core's `.cm-line p` (0,1,1 vs 0,2,1). Mirrors the `body.theme-light :is(.cm-line) p` pattern v2.30.14 uses. */ body.theme-light .cm-line p { color: rgb(255, 0, 0); font-size: 20px; } """, ), ] HTML_TEMPLATE = """\
x