{# Vendor assets via asset() helper. Default mode = CDN (jsDelivr) with SRI; #} {# when `ntasker assets fetch` ran and `assets_mode=local|auto`, they come from #} {# the user-data dir under /static/vendor instead. SRI is emitted in both modes #} {# (local mode: tamper detection). `crossorigin` is only required for CDN loading. #} {# Frontend i18n bridge: js_strings is built server-side per request. #} {# Alpine magic property `$i18n('key')` is registered just below. #}
{# Sidebar: project + tag filter (full-width checkboxes). Hidden on mobile (<768px). #} {# Sticky-positioned aside outside the .page wrapper. Tabler/Bootstrap surface vars #} {# drive the bg so dark-mode behaves. Sidebar has its own scroll context; the main #} {# page-wrapper scrolls independently. #} {# Main content (full-width inside its column) #}
{# Tabler page-header: title left, actions (tag cleanup) right #}
{# Banner: projects_dir not configured. Auto-hidden once set. #} {# CAVE: x-show MUST sit on a wrapper without Bootstrap display utility #} {# (`d-flex`, `d-block`, ...). AlpineJS sets `style="display: none"` without #} {# `!important`; Tabler/Bootstrap sets `.d-flex { display: flex !important }`. #} {# On the same element the utility wins and the banner stays visible even #} {# though projectsDirMissing === false. Fix: wrapper carries x-show + x-cloak, #} {# inner div carries the d-flex. #}
{{ t('Please configure the projects directory -- otherwise the project list stays empty.') }}
{{ t('Go to settings') }}
{# New-task form #}

{{ t('New task') }}

{# Tag-Input: AlpineJS-driven combobox. Tags as badges, free-text input, autocomplete dropdown. #}
{# Filter bar: search only -- project, tag, phase filters live in the sidebar. #}
{# Tabs #} {# Task list #}

{{ t('No tasks') }}

{# Edit modal #}
{# Toast container (Tabler/Bootstrap-compatible). Toasts injected by app.js. #}