{# Shared render macros. State language + cards reuse mgf-brand-web instrument classes (.status-chip, .level-badge, .pill, .detail-block, .empty); the small app-specific bits (.tstate task-state chip, .derived-tag) live in app.css. #} {# Sync-state chip — the brand state-chip; CHECKING/SYNCING swap the dot for a spinner. #} {%- macro sync_chip(state) -%} {%- if state in ('CHECKING', 'SYNCING') %}{% else %}{% endif -%} {{ state }} {%- endmacro -%} {# The violet "derived" tag — web-inferred, never a project-reported fact (spec §5.2). #} {%- macro derived() -%} derived {%- endmacro -%} {# Task / stage workflow-state chip (done, in_progress, next, blocked, …). #} {%- macro tstate(state) -%} {{ state|replace('_', ' ') }} {%- endmacro -%} {# A work-unit card (In progress / Decisions). `age` is derived (now − started_at). #} {%- macro task_card(t, age=None) -%}
{{ t.id }} {{ t.title }} {% if t.owner %}{{ t.owner }}{% endif %}
{{ tstate(t.state) }} {% if t.impact %}impact {{ t.impact }}{% endif %} {% if t.effort %}effort {{ t.effort }}{% endif %} {% if t.eta %}eta {{ t.eta }}{% endif %} {% if t.stage %}{{ t.stage }}{% endif %} {% if age %}started {{ age }} ago{{ derived() }} {% elif t.state == 'in_progress' %}age not reported{% endif %}
{% if t.reason %}
⚠ why
{{ t.reason }}
{% endif %} {% if t.evidence %}

evidence · {{ t.evidence }}

{% endif %}
{%- endmacro -%} {# Honest-absence block — every absence is an explicit state + reason (spec §1.6). #} {%- macro absence(view) -%} {%- set kind = 'unreadable' if view.state == 'UNREADABLE' else ('unknown' if view.state == 'UNKNOWN' else 'no-data') -%}
{{ '!' if view.state == 'UNREADABLE' else '?' }}

{{ view.title }}

{{ view.reason }}

{{ sync_chip(view.state) }}{% if view.action %} {{ view.action }}{% endif %}

{% if view.errors %}{% endif %}
{%- endmacro -%} {# An inline "nothing here" empty card (data present but the slice is empty). #} {%- macro empty_inline(title, reason) -%}

{{ title }}

{{ reason }}

{%- endmacro -%}