{% include "layouts/_head_init.html" %} {% include "layouts/_head_branding.html" %} {# Inter is the body font in pyvelm.css. Loaded from Google Fonts so the build pipeline doesn't have to ship font files. #} {# Compiled CSS — Tailwind v4 + Flowbite plugin + the theme tokens defined in pyvelm.css. Built via `npm run build`. #} {% include "layouts/_head_theme.html" %} {# Behavior. HTMX for in-page swaps; Alpine.js for the sidebar / theme / dropdown / dialog interactions; Flowbite ships a few data-attribute-driven components we'll lean on. All deferred so inline scripts below can attach handlers safely. #} {# Before Alpine so pvHtmlEditor registers on alpine:init. Build: npm run build:editor #} {% block head_extra %}{% endblock %} {% set use_sidebar = use_sidebar if use_sidebar is defined else true %} {% if use_sidebar %} {# ───── Mobile backdrop ───── #}
{# ───── Sidebar ───── #} {% endif %} {# ───── Main column ───── #}
{# Topbar. #}
{% if use_sidebar %} {% endif %} {# page_title: filled by child templates; visible in sidebar header or topnav bar. #} {% block page_title %}{% endblock %} {% if use_sidebar %} {% else %} {% set topnav_page_title = self.page_title() %} {% include "layouts/_topnav_brand.html" %} {% endif %}
{# Company switcher. #} {% if companies %}
  • {% for c in companies %}
  • {% endfor %}
{% endif %} {# Theme toggle. #} {# User menu. #} {% if current_user_name %}

{{ current_user_name }}

{{ current_user_login or '' }}

{% endif %}
{# Flash slot reserved — used for future toast/notification injection. #}
{% block flash %}{% endblock %}
{# Unified page-heading region. The layout draws a single header strip per page: breadcrumb on top, title (h1) + subtitle below, page actions on the right. Pages override the title / subtitle by setting variables (or overriding the matching block); the actions go in `{% block page_actions %}`. Pages that need a fully custom heading override `{% block page_heading %}` entirely. The breadcrumb auto-derives from `breadcrumbs` (built by `render.layout_context`). Pages can replace `breadcrumbs` to suppress it, or override `{% block page_breadcrumb %}` for a custom layout. #} {% block page_heading_region %} {% if use_sidebar and (breadcrumbs or subtitle is defined or self.page_actions()) %}
{% block page_breadcrumb %} {% if breadcrumbs %} {% endif %} {% endblock %}
{% block page_heading %} {% if subtitle is defined and subtitle %}

{{ subtitle }}

{% endif %} {% endblock %}
{% block page_actions %}{% endblock %}
{% endif %} {% endblock %} {# Page content. #}
{% block content %}{% endblock %}
{% include "layouts/_footer_branding.html" %}
{# ───── Toast stack ───── #} {# Non-blocking notifications. Dispatch ``pv-toast-request`` or call ``window.pvToast(message, { title, variant, duration })``. HTMX ``HX-Trigger: pv-toast`` is routed here via the listener below. #}
{# ───── Floating draggable form dialog ───── #} {# Mounted once globally; opened imperatively via `window.PvDialog.open(...)` or declaratively by clicking any element carrying `data-pv-dialog` (the element's `href` or `data-pv-dialog-url` is loaded into the body via HTMX). Inspired by Odoo's draggable record dialogs — drag the title bar to reposition without losing the in-flight form. The body wraps loaded content in a `[data-pv-form-shell]` div so the standard form-body buttons (Save / Cancel / Edit) target the dialog's own shell via `hx-target="closest [data-pv-form-shell]"` rather than the page form behind us. #}
{% block scripts %}{% endblock %}