{# Page title and meta #} {{ title }} {% if description %} {% endif %} {# Favicon — module-specific, fallback to default #} {# Public page CSS — wrapper layout only (content CSS comes from DB) #} {# All content classes (content.css, blocks/*.css) use these variables. Without them, styles fall back to nothing. Independent from base/css/00_variables.css (admin UI): admin theme changes do NOT affect page content. #} {# Content CSS — shared classes (.btn, .card, .grid, .h1, .text, ...). All rules are scoped under .core-engine-lib-word-blocks. #} {# Block-specific CSS — list is generated by the route handler (CoreEngineLibPagesPublicService.get_block_css_urls scans the blocks/ directory). Must load AFTER content.css so block rules can override shared rules at equal specificity. To add a new block's CSS: just drop the .css file into core/engine/lib/word/editor/blocks/ — no template change needed. #} {% for css in block_css_urls %} {% endfor %} {# Page-specific CSS — from Page.css (source of truth in DB), served as /static/pages/.css?v=. MUST load AFTER content.css and block CSS, so page rules override shared and block defaults at equal specificity. page_css_url is built by the route handler via ensure_css_file() — includes ?v=, so no |static filter is needed here. None for pages without CSS. #} {% if page_css_url %} {% endif %} {# .core-engine-lib-word-blocks is the single scope wrapper for the whole page content — all content classes (.btn, .hero, .card, ...) are defined under this class. The same class is added to the iframe inside the editor (see GrapesLoader._applyScopeClass), so styles work identically in the editor and on the public page. #}
{# Header — title + date (optional) #} {% if title %}
{% if logo %} {% endif %}

{{ title }}

{% if datetime %} {% endif %}
{% endif %} {# Content — HTML only (no