{% extends "base.html" %} {% block title %}{{ _("Billing & Plan") }}{% endblock %} {% block content %}

{{ _("Billing & Plan") }}

{{ _("Manage your ModuleDesk subscription and AI credits.") }}

{# ── Flash banners ── #} {% if topup_success %}
check_circle {{ _("Top-up purchased — your extra credits have been added.") }}
{% elif topup_cancelled %}
info {{ _("Top-up cancelled — no charge was made.") }}
{% endif %} {# ── Trial banner ── #} {% if is_trialing %}
rocket_launch

{{ _("MAX trial active") }} — {% if days_left == 0 %}{{ _("last day today") }}{% else %}{% trans count=days_left %}{{ count }} day remaining{% pluralize %}{{ count }} days remaining{% endtrans %}{% endif %}

{% trans %}You have full MAX access during your trial. After it ends, the account moves to the Free plan unless you subscribe.{% endtrans %}

{% trans count=days_left %}{{ count }} day left{% pluralize %}{{ count }} days left{% endtrans %}
{% endif %} {# ── Stripe not configured notice ── #} {% if not stripe_ok %}
warning {% trans %}Stripe is not configured — payment buttons are disabled. Set STRIPE_SECRET_KEY and price IDs to enable billing.{% endtrans %}
{% endif %} {# ── Current plan + usage cards ── #}
{# Current plan #}

{{ _("Current Plan") }}

{% if effective_plan == 'max' or effective_plan == 'internal' %} MAX {% elif effective_plan == 'premium' %} Premium {% else %} Free {% endif %} {% if is_trialing and stored_plan != 'max' and stored_plan != 'internal' %} {{ _("(trial)") }} {% endif %}
{% if effective_plan == 'premium' %}

€{{ plan_prices.premium }}{{ _("/mo") }}

{% elif effective_plan in ('max', 'internal') %}

{% if effective_plan == 'internal' %}Internal{% else %}€{{ plan_prices.max }}{{ _("/mo") }}{% endif %}

{% else %}

Free

{% endif %}
{# AI Credits #}

{{ _("AI Credits") }}

{% if ai_limit is none %}

{{ _("Unlimited") }}

{{ _("BYOK or internal plan") }}

{% else %}

{{ ai_used }} / {{ ai_limit }}

{# Progress bar #} {% set pct = [(ai_used / ai_limit * 100)|int, 100]|min %}
{% if ai_extra > 0 %}

{% trans ai_extra=ai_extra %}+{{ ai_extra }} extra credits purchased{% endtrans %}

{% else %}

{{ _("resets monthly") }}

{% endif %} {% endif %}
{# Module slots #}

{{ _("Module Slots") }}

{% if module_limit is none %}

{{ modules_used }} / {{ _("Unlimited") }}

{% else %}

{{ modules_used }} / {{ module_limit }}

{% set mpct = [(modules_used / module_limit * 100)|int, 100]|min %}
{% endif %} {% if extra_slots > 0 %} {% set n_units = addon_units %}

{% trans extra=extra_slots, count=n_units %}+{{ extra }} extra slots ({{ count }} add-on unit){% pluralize %}+{{ extra }} extra slots ({{ count }} add-on units){% endtrans %}

{% endif %}
{# ── Plan cards ── #}

{{ _("Choose a Plan") }}

{# ── Free ── #} {% set is_current_free = effective_plan == 'free' and not is_trialing %}
{% if is_current_free %}
{{ _("Current plan") }}
{% endif %}

Free

€0{{ _("/mo") }}

  • check{{ _("2 modules connected") }}
  • check{{ _("1 team member") }}
  • check{{ _("30 AI credits/month") }}
  • check{{ _("Basic inbox features") }}
  • close{{ _("Sync every 24h only") }}
{% if effective_plan not in ('free',) or is_trialing %} {% if stored_plan in ('premium', 'max') and not is_trialing %} {% endif %} {% else %}
{{ _("Current plan") }}
{% endif %}
{# ── Premium ── #} {% set is_current_premium = effective_plan == 'premium' and not is_trialing %}
{% if is_current_premium %}
{{ _("Current plan") }}
{% endif %}

Premium workspace_premium

€{{ plan_prices.premium }}{{ _("/mo") }}

  • check{{ _("6 modules (+€5/mo per 5 extra)") }}
  • check{{ _("1 team member (solo)") }}
  • check{{ _("300 AI credits/month") }}
  • check{{ _("30-min sync + semantic search") }}
  • check{{ _("All 6 AI composer actions") }}
{% if is_current_premium %}
{{ _("Current plan") }}
{% elif effective_plan == 'max' and not is_trialing %} {% else %} {% endif %}
{# ── MAX ── #} {% set is_current_max = effective_plan in ('max', 'internal') and not is_trialing %}
{% if is_current_max %}
{{ _("Current plan") }}
{% endif %}

MAX MAX

€{{ plan_prices.max }}{{ _("/mo") }}

  • check{{ _("Unlimited modules") }}
  • check{{ _("Unlimited team + roles") }}
  • check{% trans %}1,000 AI credits + BYOK{% endtrans %}
  • check{{ _("Credential vault + audit log") }}
  • check{{ _("Website health checks + URL safety") }}
{% if is_current_max %}
{{ _("Current plan") }}
{% else %} {% endif %}
{# ── AI Credit Top-Up ── #} {% if effective_plan in ('premium', 'max', 'internal') or is_trialing %}

bolt {{ _("AI Credit Top-Up") }}

{{ _("Extra credits are added immediately, persist across billing cycles and never expire.") }}

{% if not stripe_ok or not prices_ok.topup %}

{% if not stripe_ok %}{{ _("Payments are not configured yet.") }}{% else %}{{ _("Top-up packs are not configured yet.") }}{% endif %}

{% else %} {# Three packs as a row of cards. The largest is marked "Best value" because its per-credit price genuinely is the lowest — the label is not decoration. #}
{% for pack in topup_packs %} {% endfor %}
{% endif %}
{% endif %} {# ── EU VAT Number ── #}

receipt_long {{ _("EU VAT Number") }}

{{ _("If you are an EU business, enter your VAT ID for reverse-charge invoicing. We verify it via VIES.") }}

{% if vat_number %} {% if vat_validated %} verified {{ _("Verified") }} {% else %} pending {{ _("Not verified") }} {% endif %} {% endif %}
{# ── Module Add-On (Premium only, active subscription) ── #} {% if stored_plan == 'premium' and has_subscription and not is_trialing %}

extension {{ _("Extra Module Slots") }}

{{ _("Add 5 extra module slots per unit for €5/month (recurring). Current base: 6 slots.") }}

{% set slot_count = extra_slots %} {% set addon_price_val = addon_units * 5 %} {% trans slot_count=slot_count, addon_price_val=addon_price_val %}= {{ slot_count }} extra slots · €{{ addon_price_val }}/mo add-on{% endtrans %}
{% endif %}
{# ── Confirm dialog (downgrade) ── #} {% endblock %}