{% extends '@Contao/fragment/_container.html.twig' %}

{# Canonical confirmation / status page for one attendance ("Anmeldebestätigung").
   Rendered by both the authenticated owner and — via a signed URL / consent token —
   an unauthenticated visitor. `access` is 'auth' or 'anon'. #}

{% block container %}
    <div class="mx-auto max-w-2xl py-8 sm:py-10">

        {# ── team-created review banner ── #}
        {% if isCreatedByAdmin and not attendance.withdrawn %}
            <div class="mb-5 flex items-start gap-3 rounded-2xl border border-primary-200 bg-primary-50 px-4 py-3.5 dark:border-primary-900/50 dark:bg-primary-900/20">
                <span class="grid size-9 flex-none place-items-center rounded-lg bg-white text-primary-700 dark:bg-primary-950 dark:text-primary-300">
                    <twig:ux:icon name="lucide:pencil-line" class="size-[18px]" />
                </span>
                <div>
                    <b class="block text-sm font-semibold text-gray-900 dark:text-gray-100">{{ 'attendanceShow.reviewBanner.title'|trans({}, 'cms') }}</b>
                    <span class="text-[13px] leading-relaxed text-gray-600 dark:text-gray-300">{{ 'attendanceShow.reviewBanner.text'|trans({}, 'cms') }}</span>
                </div>
            </div>
        {% endif %}

        {# ── hero tone / copy per status ── #}
        {% set name = participant.firstname|default('') %}
        {% if attendance.withdrawn %}
            {% set heroWrap = 'bg-gray-50 dark:bg-gray-800/40' %}
            {% set heroBadge = 'bg-gray-400 text-white dark:bg-gray-500' %}
            {% set heroKick = 'text-gray-500 dark:text-gray-400' %}
            {% set heroIcon = 'lucide:x' %}
            {% set heroKicker = 'attendanceShow.hero.withdrawn.kicker'|trans({}, 'cms') %}
            {% set heroTitle = 'attendanceShow.hero.withdrawn.title'|trans({name: name}, 'cms') %}
            {% set heroText = 'attendanceShow.hero.withdrawn.text'|trans({offer: offer.name}, 'cms') %}
        {% elseif attendance.confirmed or attendance.participated %}
            {% set heroWrap = 'bg-green-50 dark:bg-green-900/20' %}
            {% set heroBadge = 'bg-green-600 text-white' %}
            {% set heroKick = 'text-green-700 dark:text-green-400' %}
            {% set heroIcon = 'lucide:check' %}
            {% set heroKicker = 'attendanceShow.hero.confirmed.kicker'|trans({}, 'cms') %}
            {% set heroTitle = 'attendanceShow.hero.confirmed.title'|trans({name: name}, 'cms') %}
            {% set heroText = 'attendanceShow.hero.confirmed.text'|trans({offer: offer.name}, 'cms') %}
            {% set heroMeta = 'attendanceShow.hero.confirmed.meta'|trans({}, 'cms') %}
        {% elseif attendance.waitlisted %}
            {% set heroWrap = 'bg-yellow-50 dark:bg-yellow-900/20' %}
            {% set heroBadge = 'bg-yellow-500 text-white' %}
            {% set heroKick = 'text-yellow-700 dark:text-yellow-400' %}
            {% set heroIcon = 'lucide:list' %}
            {% set heroKicker = 'attendanceShow.hero.waitlisted.kicker'|trans({}, 'cms') %}
            {% set heroTitle = 'attendanceShow.hero.waitlisted.title'|trans({name: name}, 'cms') %}
            {% set heroText = 'attendanceShow.hero.waitlisted.text'|trans({name: name, offer: offer.name}, 'cms') %}
        {% elseif attendance.awaitingConsents or attendance.consentOutstanding %}
            {% set heroWrap = 'bg-amber-50 dark:bg-amber-900/20' %}
            {% set heroBadge = 'bg-white text-amber-600 ring-2 ring-inset ring-amber-500 dark:bg-transparent' %}
            {% set heroKick = 'text-amber-700 dark:text-amber-400' %}
            {% set heroIcon = 'lucide:shield-alert' %}
            {% set heroKicker = 'attendanceShow.hero.consents.kicker'|trans({}, 'cms') %}
            {% set heroTitle = 'attendanceShow.hero.consents.title'|trans({}, 'cms') %}
            {% set heroText = 'attendanceShow.hero.consents.text'|trans({name: name}, 'cms') %}
        {% elseif attendance.rejected %}
            {% set heroWrap = 'bg-red-50 dark:bg-red-900/20' %}
            {% set heroBadge = 'bg-red-600 text-white' %}
            {% set heroKick = 'text-red-700 dark:text-red-400' %}
            {% set heroIcon = 'lucide:x' %}
            {% set heroKicker = 'attendanceShow.hero.rejected.kicker'|trans({}, 'cms') %}
            {% set heroTitle = 'attendanceShow.hero.rejected.title'|trans({name: name}, 'cms') %}
            {% set heroText = 'attendanceShow.hero.rejected.text'|trans({offer: offer.name}, 'cms') %}
        {% elseif attendance.unfulfilled %}
            {% set heroWrap = 'bg-gray-50 dark:bg-gray-800/40' %}
            {% set heroBadge = 'bg-gray-400 text-white dark:bg-gray-500' %}
            {% set heroKick = 'text-gray-500 dark:text-gray-400' %}
            {% set heroIcon = 'lucide:circle-slash' %}
            {% set heroKicker = 'attendanceShow.hero.unfulfilled.kicker'|trans({}, 'cms') %}
            {% set heroTitle = 'attendanceShow.hero.unfulfilled.title'|trans({name: name}, 'cms') %}
            {% set heroText = 'attendanceShow.hero.unfulfilled.text'|trans({offer: offer.name}, 'cms') %}
        {% else %}
            {# waiting / email_unconfirmed → "in Prüfung" #}
            {% set heroWrap = 'bg-blue-50 dark:bg-blue-900/20' %}
            {% set heroBadge = 'bg-blue-600 text-white' %}
            {% set heroKick = 'text-blue-700 dark:text-blue-400' %}
            {% set heroIcon = 'lucide:clock' %}
            {% set heroKicker = 'attendanceShow.hero.waiting.kicker'|trans({}, 'cms') %}
            {% set heroTitle = 'attendanceShow.hero.waiting.title'|trans({}, 'cms') %}
            {% set heroText = 'attendanceShow.hero.waiting.text'|trans({offer: offer.name}, 'cms') %}
        {% endif %}

        <div class="overflow-hidden rounded-3xl border border-gray-200 bg-white shadow-lg dark:border-gray-700 dark:bg-gray-800">

            {# ═══ STATUS HERO ═══ #}
            <div class="border-b border-gray-200 px-6 py-8 text-center sm:px-8 dark:border-gray-700 {{ heroWrap }}">
                <div class="mx-auto mb-4 grid size-16 place-items-center rounded-full {{ heroBadge }}">
                    <twig:ux:icon name="{{ heroIcon }}" class="size-8" />
                </div>
                <p class="mb-2 text-[11px] font-bold uppercase tracking-widest {{ heroKick }}">{{ heroKicker }}</p>
                <h1 class="text-2xl font-semibold tracking-tight text-gray-900 sm:text-[28px] dark:text-gray-50">{{ heroTitle }}</h1>
                <p class="mx-auto mt-2 max-w-md text-sm leading-6 text-gray-600 dark:text-gray-300">{{ heroText }}</p>
                {% if heroMeta is defined and heroMeta %}
                    <p class="mt-3.5 inline-flex items-center gap-2 rounded-full bg-white/70 px-3.5 py-1.5 text-[13px] font-semibold text-gray-600 dark:bg-white/10 dark:text-gray-300">
                        <twig:ux:icon name="lucide:mail-check" class="size-4 flex-none" />
                        {{ heroMeta }}
                    </p>
                {% endif %}
            </div>

            {# ═══ SUMMARY: WER / WAS / WANN ═══ #}
            <div class="px-6 sm:px-8">
                {# Wer #}
                <div class="flex items-start gap-4 border-t border-gray-100 py-4 first:border-t-0 dark:border-gray-700/60">
                    <div class="w-16 flex-none pt-1 text-[11px] font-bold uppercase tracking-wider text-gray-400 dark:text-gray-500">{{ 'attendanceShow.summary.who'|trans({}, 'cms') }}</div>
                    <div class="flex min-w-0 flex-1 items-center gap-3">
                        <span class="grid size-11 flex-none place-items-center rounded-xl bg-primary-600 text-sm font-bold text-white">{{ name|slice(0, 1)|upper }}</span>
                        <div class="min-w-0">
                            <b class="block text-[15px] font-semibold text-gray-900 dark:text-gray-100">{{ participant.name }}</b>
                            {% if participant.age is not null or participant.dateOfBirth %}
                                <span class="block text-[13px] text-gray-500 dark:text-gray-400">
                                    {%- if participant.age is not null %}{{ 'attendanceShow.summary.years'|trans({count: participant.age}, 'cms') }}{% endif -%}
                                    {%- if participant.age is not null and participant.dateOfBirth %} · {% endif -%}
                                    {%- if participant.dateOfBirth %}{{ 'attendanceShow.summary.bornOn'|trans({date: participant.dateOfBirth|date('d.m.Y')}, 'cms') }}{% endif -%}
                                </span>
                            {% endif %}
                        </div>
                    </div>
                </div>

                {# Was #}
                <div class="flex items-start gap-4 border-t border-gray-100 py-4 dark:border-gray-700/60">
                    <div class="w-16 flex-none pt-1 text-[11px] font-bold uppercase tracking-wider text-gray-400 dark:text-gray-500">{{ 'attendanceShow.summary.what'|trans({}, 'cms') }}</div>
                    <div class="flex min-w-0 flex-1 items-center gap-3">
                        <span class="grid size-11 flex-none place-items-center rounded-xl bg-primary-50 text-primary-600 dark:bg-primary-900/40 dark:text-primary-300">
                            <twig:ux:icon name="lucide:ticket" class="size-5" />
                        </span>
                        <div class="min-w-0">
                            <b class="block text-[15px] font-semibold text-gray-900 dark:text-gray-100">
                                {% if offer.published and offer.edition and offer.edition.findCurrentTask('show_offers') %}
                                    <a class="text-primary-700 hover:underline dark:text-primary-300" href="{{ path('cms', { to: 'offer_list', edition: offer.edition, auto_item: offer_auto_item(offer) }) }}">{{ offer.name }}</a>
                                {% else %}
                                    {{ offer.name }}
                                {% endif %}
                            </b>
                            <span class="block text-[13px] text-gray-500 dark:text-gray-400">
                                {%- if offer.hosts|length %}{{ offer.hosts|map(h => h.name)|join(', ') }}{% endif -%}
                                {%- if offer.hosts|length %} · {% endif -%}
                                {% if offer.fee %}{{ (offer.fee / 100)|number_format(2, ',', '.') }} €{% else %}{{ 'attendanceShow.summary.free'|trans({}, 'cms') }}{% endif %}
                            </span>
                        </div>
                    </div>
                </div>

                {# Wann #}
                {% if offer.dates|length %}
                    <div class="flex items-start gap-4 border-t border-gray-100 py-4 dark:border-gray-700/60">
                        <div class="w-16 flex-none pt-1 text-[11px] font-bold uppercase tracking-wider text-gray-400 dark:text-gray-500">{{ 'attendanceShow.summary.when'|trans({}, 'cms') }}</div>
                        <div class="min-w-0 flex-1 space-y-1.5 pt-0.5">
                            <div class="flex items-center gap-2 text-[13px] text-gray-700 dark:text-gray-200">
                                <twig:ux:icon name="lucide:calendar" class="size-4 flex-none text-gray-400" />
                                <span><twig:Cms:OfferDate :dates="offer.dates" /></span>
                            </div>
                            {% if offer.meetingPoint %}
                                <div class="flex items-center gap-2 text-[13px] text-gray-700 dark:text-gray-200">
                                    <twig:ux:icon name="lucide:map-pin" class="size-4 flex-none text-gray-400" />
                                    <span>{{ offer.meetingPoint }}{% if offer.meetingAddress %}, {{ offer.meetingAddress }}{% endif %}</span>
                                </div>
                            {% endif %}
                        </div>
                    </div>
                {% endif %}
            </div>

            {# ═══ MAP — full-bleed (breaks out of the summary padding), consent-gated
                 exactly like the offer detail page ═══ #}
            {% if offer.meetingLat and offer.meetingLng %}
                <div data-controller="ferienpass--cms-mapbox-consent" class="border-t border-gray-200 dark:border-gray-700">
                    <div data-ferienpass--cms-mapbox-consent-target="map"
                         class="hidden h-56 w-full bg-gray-100 sm:h-64 dark:bg-gray-900"
                         data-controller="ferienpass--cms-mapbox-view"
                         data-ferienpass--cms-mapbox-view-token-value="{{ mapboxToken }}"
                         data-ferienpass--cms-mapbox-view-lat-value="{{ offer.meetingLat }}"
                         data-ferienpass--cms-mapbox-view-lng-value="{{ offer.meetingLng }}"
                         data-ferienpass--cms-mapbox-view-zoom-value="14"></div>
                    <div data-ferienpass--cms-mapbox-consent-target="placeholder"
                         class="hidden h-56 w-full flex-col items-center justify-center bg-gray-50 p-6 text-center sm:h-64 dark:bg-gray-800/40">
                        <p class="mb-5 max-w-md text-[13px] leading-relaxed text-gray-600 dark:text-gray-400">{{ 'offerDetails.mapboxConsent.text'|trans({}, 'cms') }}</p>
                        <div class="flex flex-col gap-2.5 sm:flex-row">
                            <twig:Cms:Button variant="primary" data-action="click->ferienpass--cms-mapbox-consent#giveConsent">
                                {{ 'offerDetails.mapboxConsent.button'|trans({}, 'cms') }}
                            </twig:Cms:Button>
                            <button type="button" data-action="click->ferienpass--cms-mapbox-consent#toggleInfo"
                                    class="inline-flex items-center justify-center rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 transition hover:bg-gray-50 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-300 dark:hover:bg-gray-700">
                                {{ 'offerDetails.mapboxConsent.infoButton'|trans({}, 'cms') }}
                            </button>
                        </div>
                        <div data-ferienpass--cms-mapbox-consent-target="info" class="mt-5 hidden max-w-2xl text-xs text-gray-500 dark:text-gray-400">{{ 'offerDetails.mapboxConsent.infoText'|trans({}, 'cms')|nl2br }}</div>
                    </div>
                </div>
            {% endif %}

            {# ═══ CONSENTS & ANSWERS ═══ #}
            {% if not attendance.withdrawn and (consents|length or questions|length) %}
                {{ block('consents_section') }}
            {% endif %}

            {# ═══ FOOTER ACTIONS ═══ #}
            {% if not attendance.withdrawn %}
                <div class="flex flex-col-reverse items-stretch justify-between gap-4 border-t border-gray-200 px-6 py-4 sm:flex-row sm:items-center sm:px-8 dark:border-gray-700">
                    <div class="flex flex-wrap items-center gap-1">
                        <a href="{{ path('cms', { to: 'offer_list' }) }}" class="inline-flex items-center gap-2 rounded-lg px-2.5 py-2 text-[13px] font-semibold text-gray-600 transition hover:bg-gray-100 hover:text-gray-900 dark:text-gray-300 dark:hover:bg-gray-700/60">
                            <twig:ux:icon name="lucide:home" class="size-[15px] text-gray-400" />
                            {{ 'attendanceShow.footer.moreOffers'|trans({}, 'cms') }}
                        </a>
                        {% if 'auth' == access %}
                            <a href="{{ path('cms', { to: 'applications' }) }}" class="inline-flex items-center gap-2 rounded-lg px-2.5 py-2 text-[13px] font-semibold text-gray-600 transition hover:bg-gray-100 hover:text-gray-900 dark:text-gray-300 dark:hover:bg-gray-700/60">
                                <twig:ux:icon name="lucide:list-checks" class="size-[15px] text-gray-400" />
                                {{ 'attendanceShow.footer.myApplications'|trans({}, 'cms') }}
                            </a>
                        {% endif %}
                    </div>

                    {% if workflow_can(attendance, 'withdraw') %}
                        {% if 'auth' == access %}
                            {# Authenticated owner → reuse the existing "Meine Anmeldungen" withdraw modal. #}
                            <a href="{{ path('cms', { to: 'applications', action: 'abmelden', id: attendance.id }) }}"
                               data-turbo-frame="modal"
                               class="inline-flex items-center justify-center gap-2 rounded-lg border border-red-200 bg-white px-3.5 py-2.5 text-sm font-semibold text-red-600 transition hover:bg-red-50 dark:border-red-900/50 dark:bg-transparent dark:text-red-400 dark:hover:bg-red-900/20">
                                <twig:ux:icon name="lucide:x" class="size-4" />
                                {{ (attendance.awaitingConsents ? 'attendanceShow.withdraw.buttonConsent' : 'attendanceShow.withdraw.button')|trans({}, 'cms') }}
                            </a>
                        {% else %}
                            {{ block('anon_withdraw') }}
                        {% endif %}
                    {% endif %}
                </div>
            {% endif %}
        </div>

        {% if 'anon' == access and not attendance.withdrawn and workflow_can(attendance, 'withdraw') %}
            <div class="mt-4 flex items-start gap-3 rounded-2xl border border-gray-200 bg-gray-50 px-4 py-3.5 text-[13px] leading-relaxed text-gray-600 dark:border-gray-700 dark:bg-gray-800/60 dark:text-gray-300">
                <twig:ux:icon name="lucide:mail" class="mt-0.5 size-4 flex-none text-gray-400" />
                <span>{{ 'attendanceShow.withdraw.anonHint'|trans({}, 'cms') }}</span>
            </div>
        {% endif %}

        <p class="mt-6 text-center text-[13px] text-gray-500 dark:text-gray-400">
            {{ 'attendanceShow.footnote'|trans({}, 'cms') }}
        </p>
    </div>
{% endblock %}


{# ─────────── CONSENTS & ANSWERS SECTION ─────────── #}
{% block consents_section %}
    {% set editing = needsConsents %}
    <section class="border-t border-gray-200 bg-gray-50/60 px-6 py-6 sm:px-8 dark:border-gray-700 dark:bg-gray-800/40">
        <div class="mb-1 flex items-center gap-3">
            <span class="grid size-9 flex-none place-items-center rounded-lg {{ editing ? 'bg-amber-50 text-amber-600 dark:bg-amber-900/30 dark:text-amber-400' : 'bg-green-50 text-green-600 dark:bg-green-900/30 dark:text-green-400' }}">
                <twig:ux:icon name="{{ editing ? 'lucide:shield-alert' : 'lucide:shield-check' }}" class="size-[18px]" />
            </span>
            <h2 class="text-lg font-semibold tracking-tight text-gray-900 dark:text-gray-50">{{ (editing ? 'attendanceShow.section.consents.titleTodo' : 'attendanceShow.section.consents.title')|trans({}, 'cms') }}</h2>
        </div>
        <p class="mb-4 ml-12 text-[13px] leading-relaxed text-gray-500 dark:text-gray-400">{{ (editing ? 'attendanceShow.section.consents.ledeTodo' : 'attendanceShow.section.consents.lede')|trans({}, 'cms') }}</p>

        {% if editing %}
            {{ block('consents_form') }}
        {% endif %}

        {% if (not editing and consents|length) or questions|length %}
        <div class="space-y-2.5{{ editing ? ' mt-5' : '' }}">
            {% if not editing %}
                {% for state in consents %}
                <div class="overflow-hidden rounded-xl border border-gray-200 bg-white dark:border-gray-700 dark:bg-gray-800">
                    <div class="flex items-center gap-3 px-4 py-3.5">
                        <span class="grid size-9 flex-none place-items-center rounded-lg bg-green-50 text-green-600 dark:bg-green-900/30 dark:text-green-400">
                            <twig:ux:icon name="lucide:shield" class="size-[18px]" />
                        </span>
                        <div class="min-w-0 flex-1">
                            <b class="block text-sm font-semibold text-gray-900 dark:text-gray-100">{{ state.title|default('consents.label'|trans({}, 'cms'))|machine_translate }}</b>
                            <span class="mt-0.5 inline-flex items-center gap-1.5 text-xs font-medium {{ state.isCompulsory ? 'text-red-600 dark:text-red-400' : 'text-gray-500 dark:text-gray-400' }}">
                                {{ (state.isCompulsory ? 'attendanceShow.consent.required' : 'attendanceShow.consent.voluntary')|trans({}, 'cms') }}
                            </span>
                        </div>
                        {% if state.isOutstanding %}
                            <span class="inline-flex flex-none items-center gap-1.5 rounded-full bg-amber-50 px-2.5 py-1 text-xs font-semibold text-amber-700 dark:bg-amber-900/30 dark:text-amber-400">{{ 'attendanceShow.consent.outstanding'|trans({}, 'cms') }}</span>
                        {% elseif state.isDisagreed %}
                            <span class="inline-flex flex-none items-center gap-1.5 rounded-full bg-gray-100 px-2.5 py-1 text-xs font-semibold text-gray-500 dark:bg-gray-700 dark:text-gray-300">{{ 'attendanceShow.consent.declined'|trans({}, 'cms') }}</span>
                        {% else %}
                            <span class="inline-flex flex-none items-center gap-1.5 rounded-full bg-green-50 px-2.5 py-1 text-xs font-semibold text-green-700 dark:bg-green-900/30 dark:text-green-400">
                                <twig:ux:icon name="lucide:check" class="size-3.5" />
                                {{ 'attendanceShow.consent.given'|trans({}, 'cms') }}
                            </span>
                        {% endif %}
                    </div>
                </div>
                {% endfor %}
            {% endif %}

            {% if questions|length %}
                {{ answersEditable|default(false) ? block('answers_form') : block('answers_readonly') }}
            {% endif %}
        </div>
        {% endif %}

        {% if editing and shareUrl %}
            {{ block('guardian_share') }}
        {% endif %}
    </section>
{% endblock %}


{# ─────────── CONSENT SIGNING FORM (supersedes /einwilligung/{token}) ─────────── #}
{% block consents_form %}
    {% set green_check = 'has-checked:border-[#2f6f57] has-checked:ring-1 has-checked:ring-[#2f6f57] has-checked:bg-[#e5efe9] has-checked:text-[#1f4a3a] dark:has-checked:border-[#3d8064] dark:has-checked:ring-[#3d8064] dark:has-checked:bg-[#2f6f57]/20 dark:has-checked:text-[#cce0d4]' %}
    <form method="post" action="{{ formAction }}" class="space-y-6">
        <input type="hidden" name="REQUEST_TOKEN" value="{{ contao_request_token() }}">
        <input type="hidden" name="action" value="sign-consents">

        {% if consentError %}
            <div class="rounded-lg border border-red-300 bg-red-50 px-4 py-3 text-sm text-red-700 dark:border-red-700 dark:bg-red-900/20 dark:text-red-300">
                {{ consentError|trans({}, 'cms') }}
            </div>
        {% endif %}

        <div class="overflow-hidden rounded-xl border border-gray-200 bg-white dark:border-gray-700 dark:bg-gray-800">
            {# Only the still-open consents carry an input. Ones the team already
               recorded on behalf of the guardian are signed, so they must not be
               asked again (and signConsents mirrors this — it requires a decision
               only for outstanding states). #}
            {% for state in consents|filter(s => s.isOutstanding) %}
                {% set form = state.consentForm %}
                {% set mode = form.compulsory %}
                {% set name = 'decisions[' ~ form.id ~ ']' %}
                <div class="border-t border-gray-100 p-4 first:border-t-0 dark:border-gray-700/60">
                    <p class="text-sm font-semibold text-gray-900 dark:text-gray-100">{{ form.title|default('consents.label'|trans({}, 'cms'))|machine_translate }}</p>

                    {% if form.text %}
                        <div class="prose prose-sm dark:prose-invert mt-1.5 max-h-40 max-w-none overflow-y-auto overscroll-contain rounded-lg bg-gray-50 p-3 pr-3 text-[13px] leading-relaxed text-gray-600 dark:bg-gray-900/40 dark:text-gray-400">
                            {{ form.text|markdown_to_html|machine_translate }}
                        </div>
                    {% endif %}

                    <div class="mt-3 flex flex-wrap items-center justify-between gap-3">
                        {% if mode == 'compulsory' %}
                            <span class="inline-flex items-center gap-1.5 text-xs font-semibold text-amber-600 dark:text-amber-400">
                                <twig:ux:icon name="lucide:shield-alert" class="size-4" />
                                {{ 'applicationForm.consent.required'|trans({}, 'cms') }}
                            </span>
                            <label class="group/req inline-flex cursor-pointer select-none items-center gap-2.5 rounded-lg border border-gray-300 py-2 pl-2.5 pr-3.5 text-sm font-semibold text-gray-700 transition hover:border-gray-400 dark:border-gray-600 dark:text-gray-200 dark:hover:border-gray-500 {{ green_check }}">
                                <input type="checkbox" name="{{ name }}" value="1" required class="peer sr-only">
                                <span class="grid size-5 flex-none place-items-center rounded border-2 border-gray-300 transition peer-checked:border-[#2f6f57] peer-checked:bg-[#2f6f57] peer-checked:text-white dark:border-gray-500">
                                    <twig:ux:icon name="lucide:check" class="size-3.5 opacity-0 transition-opacity group-has-[input:checked]/req:opacity-100" />
                                </span>
                                <span class="peer-checked:hidden">{{ 'applicationForm.consent.accept'|trans({}, 'cms') }}</span>
                                <span class="hidden peer-checked:inline">{{ 'applicationForm.consent.accepted'|trans({}, 'cms') }}</span>
                            </label>
                        {% elseif mode == 'force_decision' %}
                            {% set pill = 'flex cursor-pointer select-none items-center justify-center gap-2 rounded-md px-3 py-2 text-sm font-semibold text-gray-500 transition dark:text-gray-400' %}
                            <span class="inline-flex items-center gap-1.5 text-xs font-semibold text-amber-600 dark:text-amber-400">
                                <twig:ux:icon name="lucide:shield-alert" class="size-4" />
                                {{ 'applicationForm.pleaseDecide'|trans({}, 'cms') }}
                            </span>
                            <span class="inline-grid grid-cols-2 gap-1.5 rounded-lg bg-gray-100 p-1 dark:bg-gray-700">
                                <label class="{{ pill }} has-checked:bg-white has-checked:text-[#245a46] has-checked:shadow-sm dark:has-checked:bg-gray-800 dark:has-checked:text-[#9cc4ae]">
                                    <input type="radio" name="{{ name }}" value="1" required class="sr-only">
                                    {{ 'applicationForm.agree'|trans({}, 'cms') }}
                                </label>
                                <label class="{{ pill }} has-checked:bg-white has-checked:text-red-600 has-checked:shadow-sm dark:has-checked:bg-gray-800 dark:has-checked:text-red-400">
                                    <input type="radio" name="{{ name }}" value="0" required class="sr-only">
                                    {{ 'applicationForm.revoke'|trans({}, 'cms') }}
                                </label>
                            </span>
                        {% else %}
                            <span class="text-xs text-gray-500 dark:text-gray-400">
                                {{ (mode == 'opt-out' ? 'consentSign.optOutHint' : 'consentSign.optInHint')|trans({}, 'cms') }}
                            </span>
                            <label class="inline-flex cursor-pointer select-none items-center gap-2.5">
                                <input type="checkbox" name="{{ name }}" value="1" class="peer sr-only" {{ mode == 'opt-out' ? 'checked' }}>
                                <span class="text-xs font-semibold text-gray-500 peer-checked:hidden dark:text-gray-400">{{ 'applicationForm.consentDenied'|trans({}, 'cms') }}</span>
                                <span class="hidden text-xs font-semibold text-[#245a46] peer-checked:inline dark:text-[#9cc4ae]">{{ 'applicationForm.consentGranted'|trans({}, 'cms') }}</span>
                                <span class="relative inline-flex h-6 w-11 flex-none rounded-full bg-gray-300 transition-colors after:absolute after:left-0.5 after:top-0.5 after:size-5 after:rounded-full after:bg-white after:shadow after:transition-transform peer-checked:bg-[#2f6f57] peer-checked:after:translate-x-5 dark:bg-gray-600"></span>
                            </label>
                        {% endif %}
                    </div>
                </div>
            {% endfor %}
        </div>

        <div class="space-y-3 rounded-xl border border-gray-200 bg-white p-4 dark:border-gray-700 dark:bg-gray-800">
            <div>
                <label for="consent-signee" class="mb-1 block text-sm font-medium text-gray-700 dark:text-gray-100">{{ 'consentSign.signeeLabel'|trans({}, 'cms') }}</label>
                <input type="text" id="consent-signee" name="signedBy" required autocomplete="name"
                       class="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-primary-600 dark:bg-gray-900 dark:text-gray-100 sm:text-sm">
                <p class="mt-1 text-xs text-gray-500 dark:text-gray-400">{{ 'consentSign.signeeHint'|trans({ name: participant.name }, 'cms') }}</p>
            </div>
            <div class="flex justify-end">
                <twig:Cms:Button variant="primary" type="submit" size="lg" class="gap-2">
                    {{ 'consentSign.submit'|trans({}, 'cms') }}
                    <twig:ux:icon name="lucide:check" class="size-4" />
                </twig:Cms:Button>
            </div>
        </div>
    </form>
{% endblock %}


{# ─────────── GUARDIAN SHARE (forward the durable consent link) ─────────── #}
{% block guardian_share %}
    <div class="mt-5 rounded-xl border border-amber-200 bg-amber-50 px-4 py-3.5 dark:border-amber-900/50 dark:bg-amber-900/20">
        <p class="flex items-center gap-2 text-sm font-semibold text-amber-900 dark:text-amber-300">
            <twig:ux:icon name="lucide:share-2" class="size-4 flex-none" />
            {{ 'attendanceShow.guardianShare.title'|trans({}, 'cms') }}
        </p>
        <p class="mt-1 text-[13px] leading-relaxed text-amber-900/90 dark:text-amber-200/90">{{ 'attendanceShow.guardianShare.text'|trans({}, 'cms') }}</p>
        <div class="mt-3 flex items-stretch gap-2" x-data="{ copied: false }">
            <input type="text" readonly value="{{ shareUrl }}" onclick="this.select()"
                   class="block w-full min-w-0 rounded-md border-0 bg-white px-3 py-2 font-mono text-xs text-gray-700 ring-1 ring-inset ring-amber-200 dark:bg-gray-900 dark:text-gray-300 dark:ring-amber-900/50">
            <button type="button"
                    @click="navigator.clipboard.writeText('{{ shareUrl }}'); copied = true; setTimeout(() => copied = false, 2000)"
                    class="inline-flex flex-none items-center gap-1.5 rounded-md bg-white px-3 py-2 text-xs font-semibold text-gray-700 ring-1 ring-inset ring-amber-200 transition hover:bg-amber-100 dark:bg-gray-900 dark:text-gray-200 dark:ring-amber-900/50">
                <twig:ux:icon name="lucide:copy" class="size-3.5" />
                <span x-text="copied ? '{{ 'attendanceShow.guardianShare.copied'|trans({}, 'cms') }}' : '{{ 'attendanceShow.guardianShare.copy'|trans({}, 'cms') }}'">{{ 'attendanceShow.guardianShare.copy'|trans({}, 'cms') }}</span>
            </button>
        </div>
    </div>
{% endblock %}


{# ─────────── ANONYMOUS WITHDRAW (Alpine confirm modal → e-mail confirmation) ─────────── #}
{% block anon_withdraw %}
    <div x-data="{ open: false }" class="sm:flex-none">
        <button type="button" @click="open = true"
                class="inline-flex w-full items-center justify-center gap-2 rounded-lg border border-red-200 bg-white px-3.5 py-2.5 text-sm font-semibold text-red-600 transition hover:bg-red-50 sm:w-auto dark:border-red-900/50 dark:bg-transparent dark:text-red-400 dark:hover:bg-red-900/20">
            <twig:ux:icon name="lucide:x" class="size-4" />
            {{ (attendance.awaitingConsents ? 'attendanceShow.withdraw.buttonConsent' : 'attendanceShow.withdraw.button')|trans({}, 'cms') }}
        </button>

        <div class="fixed inset-0 z-50 flex items-center justify-center px-4" x-show="open" x-cloak>
            <div class="fixed inset-0 bg-gray-900/50 backdrop-blur-sm"
                 x-show="open" x-transition.opacity @click="open = false"></div>
            <div class="relative w-full max-w-md overflow-hidden rounded-2xl border border-gray-200 bg-white shadow-xl dark:border-gray-700 dark:bg-gray-800"
                 x-show="open"
                 x-transition:enter="ease-out duration-200"
                 x-transition:enter-start="opacity-0 translate-y-2 scale-95"
                 x-transition:enter-end="opacity-100 translate-y-0 scale-100"
                 role="dialog" aria-modal="true">
                <form method="post" action="{{ formAction }}" class="p-6">
                    <input type="hidden" name="REQUEST_TOKEN" value="{{ contao_request_token() }}">
                    <input type="hidden" name="action" value="request-withdraw">

                    <span class="mb-3.5 grid size-11 place-items-center rounded-xl bg-primary-50 text-primary-600 dark:bg-primary-900/40 dark:text-primary-300">
                        <twig:ux:icon name="lucide:mail" class="size-[22px]" />
                    </span>
                    <h3 class="mb-2 text-lg font-semibold tracking-tight text-gray-900 dark:text-gray-50">{{ 'attendanceShow.withdraw.anonModal.title'|trans({}, 'cms') }}</h3>
                    <p class="mb-4 text-sm leading-relaxed text-gray-600 dark:text-gray-300">{{ 'attendanceShow.withdraw.anonModal.text'|trans({}, 'cms') }}</p>
                    {% if participant.email %}
                        <div class="mb-5 inline-flex items-center gap-2 rounded-lg bg-gray-100 px-3 py-2 text-[13px] font-semibold text-gray-700 dark:bg-gray-700 dark:text-gray-200">
                            <twig:ux:icon name="lucide:at-sign" class="size-4 flex-none text-gray-400" />
                            {{ participant.email }}
                        </div>
                    {% endif %}
                    <div class="flex flex-col-reverse gap-2.5 sm:flex-row sm:justify-end">
                        <button type="button" @click="open = false"
                                class="inline-flex items-center justify-center rounded-lg border border-gray-300 bg-white px-4 py-2.5 text-sm font-semibold text-gray-700 transition hover:bg-gray-50 dark:border-gray-600 dark:bg-transparent dark:text-gray-200 dark:hover:bg-gray-700">
                            {{ 'attendanceShow.withdraw.anonModal.cancel'|trans({}, 'cms') }}
                        </button>
                        <twig:Cms:Button variant="primary" type="submit" size="lg" class="gap-2">
                            <twig:ux:icon name="lucide:send" class="size-4" />
                            {{ 'attendanceShow.withdraw.anonModal.confirm'|trans({}, 'cms') }}
                        </twig:Cms:Button>
                    </div>
                </form>
            </div>
        </div>
    </div>
{% endblock %}


{# ─────────── EXTRA QUESTIONS: read-only review ─────────── #}
{% block answers_readonly %}
    {% for q in questions %}
        <div class="overflow-hidden rounded-xl border border-gray-200 bg-white dark:border-gray-700 dark:bg-gray-800">
            <div class="flex items-center gap-3 px-4 py-3.5">
                <span class="grid size-9 flex-none place-items-center rounded-lg bg-blue-50 text-blue-600 dark:bg-blue-900/30 dark:text-blue-400">
                    <twig:ux:icon name="{{ 'file' == q.type ? 'lucide:paperclip' : 'lucide:message-circle-question' }}" class="size-[18px]" />
                </span>
                <div class="min-w-0 flex-1">
                    <b class="block text-sm font-semibold text-gray-900 dark:text-gray-100">{{ q.question }}</b>
                    <span class="mt-0.5 block text-[13px] text-gray-600 dark:text-gray-300">
                        {%- if 'yn' == q.type -%}
                            {%- if q.answer in ['y', 'yes', '1', 1, true] %}{{ 'attendanceShow.answer.positive'|trans({}, 'cms') }}{% elseif q.answer in ['n', 'no', '0', 0] %}{{ 'attendanceShow.answer.negative'|trans({}, 'cms') }}{% else %}<span class="text-gray-400">{{ 'attendanceShow.answer.none'|trans({}, 'cms') }}</span>{% endif -%}
                        {%- elseif 'file' == q.type -%}
                            {%- if q.file %}<a href="{{ q.fileUrl }}" target="_blank" rel="noopener" class="font-semibold text-[#245a46] underline decoration-[#9cc4ae] underline-offset-2 dark:text-[#9cc4ae]">{{ q.file.name }}</a>{% else %}<span class="text-gray-400">{{ 'attendanceShow.answer.none'|trans({}, 'cms') }}</span>{% endif -%}
                        {%- else -%}
                            {%- if q.answer is not empty %}{{ q.answer }}{% else %}<span class="text-gray-400">{{ 'attendanceShow.answer.none'|trans({}, 'cms') }}</span>{% endif -%}
                        {%- endif -%}
                    </span>
                </div>
            </div>
        </div>
    {% endfor %}
{% endblock %}


{# ─────────── EXTRA QUESTIONS: correctable form ─────────── #}
{# A plain multipart POST (no live component on this page): the answers — including
   a re-taken photo or a replaced PDF — go back to
   AttendanceShowController::saveAnswers(), which re-validates the whole set and
   writes nothing unless it passes. #}
{% block answers_form %}
    <form method="post" action="{{ formAction }}" enctype="multipart/form-data"
          class="overflow-hidden rounded-xl border border-gray-200 bg-white dark:border-gray-700 dark:bg-gray-800">
        <input type="hidden" name="REQUEST_TOKEN" value="{{ contao_request_token() }}">
        <input type="hidden" name="action" value="save-answers">

        {% if answersError|default(null) %}
            <div class="border-b border-red-200 bg-red-50 px-4 py-3 text-sm text-red-700 dark:border-red-900/50 dark:bg-red-900/20 dark:text-red-300">
                {{ answersError|trans({ max: 10 }, 'cms') }}
            </div>
        {% endif %}

        <div class="divide-y divide-dashed divide-gray-200 dark:divide-gray-700">
            {% for q in questions %}
                {% set inputId = 'answer_' ~ loop.index %}
                <div class="px-4 py-4">
                    <label for="{{ inputId }}" class="block text-sm font-semibold text-gray-900 dark:text-gray-100">
                        {{ q.question }}
                        {% if not q.required %}
                            <span class="ml-1 text-xs font-medium text-gray-400 dark:text-gray-500">{{ 'applicationForm.extra.optional'|trans({}, 'cms') }}</span>
                        {% endif %}
                    </label>

                    <div class="mt-2.5">
                        {% if 'yn' == q.type %}
                            {% set yes = q.answer in ['y', 'yes', '1', 1, true] %}
                            {% set no = q.answer in ['n', 'no', '0', 0] %}
                            <span class="inline-grid grid-cols-2 gap-1.5 rounded-lg bg-gray-100 p-1 dark:bg-gray-700">
                                <label class="flex cursor-pointer select-none items-center justify-center gap-2 rounded-md px-3 py-2 text-sm font-semibold text-gray-500 transition has-checked:bg-white has-checked:text-[#245a46] dark:text-gray-400 dark:has-checked:bg-gray-800 dark:has-checked:text-[#9cc4ae]">
                                    <input type="radio" id="{{ inputId }}" name="answers[{{ q.uuid }}]" value="y" class="sr-only" {{ yes ? 'checked' }}>
                                    {{ 'applicationForm.extra.yes'|trans({}, 'cms') }}
                                </label>
                                <label class="flex cursor-pointer select-none items-center justify-center gap-2 rounded-md px-3 py-2 text-sm font-semibold text-gray-500 transition has-checked:bg-white has-checked:text-red-600 dark:text-gray-400 dark:has-checked:bg-gray-800 dark:has-checked:text-red-400">
                                    <input type="radio" name="answers[{{ q.uuid }}]" value="n" class="sr-only" {{ no ? 'checked' }}>
                                    {{ 'applicationForm.extra.no'|trans({}, 'cms') }}
                                </label>
                            </span>
                        {% elseif 'int' == q.type %}
                            <input type="number" step="1" id="{{ inputId }}" name="answers[{{ q.uuid }}]" value="{{ q.answer }}"
                                   class="block w-full max-w-40 rounded-md border-0 py-2 text-sm text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset focus:ring-primary-600 dark:bg-gray-900 dark:text-gray-100 dark:ring-gray-600">
                        {% elseif 'file' == q.type %}
                            {% set kinds = q.fileTypes|default(['image', 'pdf']) %}
                            {% set accept = 'image' in kinds ? ('pdf' in kinds ? 'image/*,application/pdf' : 'image/*') : 'application/pdf' %}
                            {% if q.file %}
                                <div class="flex flex-wrap items-center gap-3 rounded-lg border border-gray-200 bg-gray-50 p-3 dark:border-gray-700 dark:bg-gray-800/60">
                                    {% if q.file.isImage %}
                                        <img src="{{ q.fileUrl }}" alt="{{ q.file.name }}" class="size-14 flex-none rounded-md object-cover">
                                    {% else %}
                                        <span class="grid size-14 flex-none place-items-center rounded-md bg-white text-gray-500 dark:bg-gray-900 dark:text-gray-300">
                                            <twig:ux:icon name="lucide:file-text" class="size-6" />
                                        </span>
                                    {% endif %}
                                    <span class="min-w-0 flex-1 text-sm leading-5">
                                        <a href="{{ q.fileUrl }}" target="_blank" rel="noopener" class="block truncate font-semibold text-gray-900 underline decoration-gray-300 underline-offset-2 dark:text-gray-100">{{ q.file.name }}</a>
                                        <span class="text-xs font-medium text-gray-500 dark:text-gray-400">{{ (q.file.size / 1024 / 1024)|round(2) }} MB</span>
                                    </span>
                                    <a href="{{ q.fileUrl }}{{ '?' in q.fileUrl ? '&' : '?' }}download=1"
                                       class="flex-none rounded-md bg-white px-2.5 py-1.5 text-xs font-semibold text-gray-700 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50 dark:bg-gray-800 dark:text-gray-200 dark:ring-gray-600">
                                        {{ 'attendanceShow.answers.download'|trans({}, 'cms') }}
                                    </a>
                                </div>
                            {% endif %}

                            <label class="mt-2.5 inline-flex cursor-pointer items-center gap-2 rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-700 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50 dark:bg-gray-800 dark:text-gray-200 dark:ring-gray-600">
                                <twig:ux:icon name="{{ q.file ? 'lucide:refresh-cw' : 'lucide:paperclip' }}" class="size-4" />
                                {{ (q.file ? 'applicationForm.extra.file.replace' : 'applicationForm.extra.file.pick')|trans({}, 'cms') }}
                                <input type="file" id="{{ inputId }}" name="answerFiles[{{ q.uuid }}]" class="sr-only" accept="{{ accept }}">
                            </label>
                            {% if 'image' in kinds %}
                                {# Straight to the camera on a phone; ignored on the desktop,
                                   which is why it is a second input. #}
                                <label class="mt-2.5 ml-2 inline-flex cursor-pointer items-center gap-2 rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-700 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50 sm:hidden dark:bg-gray-800 dark:text-gray-200 dark:ring-gray-600">
                                    <twig:ux:icon name="lucide:camera" class="size-4" />
                                    {{ 'applicationForm.extra.file.capture'|trans({}, 'cms') }}
                                    <input type="file" name="answerFiles[{{ q.uuid }}]" class="sr-only" accept="image/*" capture="environment">
                                </label>
                            {% endif %}
                            <p class="mt-1.5 text-xs leading-5 text-gray-500 dark:text-gray-400">
                                {{ 'applicationForm.extra.file.hint'|trans({ types: ('image' in kinds ? ('pdf' in kinds ? 'applicationForm.extra.file.types.both' : 'applicationForm.extra.file.types.image') : 'applicationForm.extra.file.types.pdf')|trans({}, 'cms'), max: 10 }, 'cms') }}
                            </p>
                        {% else %}
                            <textarea rows="2" id="{{ inputId }}" name="answers[{{ q.uuid }}]"
                                      class="block w-full resize-y rounded-md border-0 py-2 text-sm leading-6 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset focus:ring-primary-600 dark:bg-gray-900 dark:text-gray-100 dark:ring-gray-600">{{ q.answer }}</textarea>
                        {% endif %}
                    </div>
                </div>
            {% endfor %}
        </div>

        <div class="flex flex-wrap items-center justify-between gap-3 border-t border-gray-200 bg-gray-50/60 px-4 py-3 dark:border-gray-700 dark:bg-gray-800/40">
            <span class="text-xs text-gray-500 dark:text-gray-400">{{ 'attendanceShow.answers.hint'|trans({}, 'cms') }}</span>
            <twig:Cms:Button variant="primary" type="submit">{{ 'attendanceShow.answers.save'|trans({}, 'cms') }}</twig:Cms:Button>
        </div>
    </form>
{% endblock %}
