<main id="main-content" class="admin-main--toc">
    <?php include APP_ROOT . '/templates/admin/partials/admin-toc.php'; ?>

    <article>
    <h1>Accès</h1>

    <!-- ══════════════════════════════════════════════════════════════
         LIENS ÉTUDIANT·E
    ══════════════════════════════════════════════════════════════ -->
    <section aria-labelledby="acces-liens-title">
        <div class="admin-list-toolbar">
            <h2 id="acces-liens-title">Liens étudiant·e</h2>
            <div class="admin-list-toolbar__right">
                <button type="button" class="btn btn--primary btn--sm" id="open-create-dialog">
                    + Créer un lien
                </button>
            </div>
        </div>

        <?php if (empty($links)): ?>
            <p class="admin-empty">Aucun lien créé. Cliquez sur « Créer un lien » pour générer un lien partageable.</p>
        <?php else: ?>
        <table>
            <thead>
                <tr>
                    <th scope="col">Nom</th>
                    <th scope="col">Lien</th>
                    <th scope="col">Objet</th>
                    <th scope="col">Année</th>
                    <th scope="col">Statut</th>
                    <th scope="col">Mot de passe</th>
                    <th scope="col">Utilisations</th>
                    <th scope="col">Expiration</th>
                    <th scope="col">Créé le</th>
                    <th scope="col">Actions</th>
                </tr>
            </thead>
            <tbody>
                <?php foreach ($links as $link): ?>
                    <?php
                        $isExpired = $link['expires_at'] !== null && strtotime($link['expires_at']) < time();
                        $isActive  = (bool)$link['is_active'] && !$isExpired;
                        $statusLabel = $isExpired ? 'Expiré' : ($link['is_active'] ? 'Actif' : 'Désactivé');
                        $fullUrl = $baseUrl . '/partage/' . htmlspecialchars($link['slug']);
                        $created = date('d/m/Y H:i', strtotime($link['created_at']));
                        $expires = $link['expires_at'] ? date('d/m/Y H:i', strtotime($link['expires_at'])) : '-';
                        $hasLinkPassword = !empty($link['password_hash']);
                        $linkName = $link['name'] ?? '';
                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
                        $linkLockedYear = $link['locked_year'] ?? null;
%%%%%%% diff from: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
\\\\\\\        to: unnnvyqs 357a2fff "Admin mobile block: fix inline style beating media query" (rebased revision)
+                        $linkName = $link['name'] ?? '';
+                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%% diff from: unnnvyqs 357a2fff "Admin mobile block: fix inline style beating media query" (rebased revision)
\\\\\\\\\\\        to: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
-                        $linkName = $link['name'] ?? '';
-                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%% diff from: somsyvxz 14a3cd10 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebase destination)
\\\\\\\\\\\        to: szktqmnn bdcd30e9 "Error tests, FK violations fix" (rebased revision)
                         $linkName = $link['name'] ?? '';
                         $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
                         $linkLockedYear = $link['locked_year'] ?? null;
+%%%%%%% diff from: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
+\\\\\\\        to: szktqmnn 29b3397f "Error tests, FK violations fix" (rebased revision)
++                        $linkName = $link['name'] ?? '';
++                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%% diff from: szktqmnn 29b3397f "Error tests, FK violations fix" (rebased revision)
\\\\\\\\\\\\\\\        to: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
-                        $linkName = $link['name'] ?? '';
-                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%% diff from: somsyvxz 14a3cd10 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebase destination)
\\\\\\\\\\\\\\\        to: vpwuyvyv 1573e164 "Fix: email clearing in findOrCreateAuthor, htmlspecialchars(null) crash in old(), dead contact_interne field, access_type_id radio clearing" (rebased revision)
                         $linkName = $link['name'] ?? '';
                         $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
                         $linkLockedYear = $link['locked_year'] ?? null;
+%%%%%%% diff from: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
+\\\\\\\        to: vpwuyvyv f513921d "Fix: email clearing in findOrCreateAuthor, htmlspecialchars(null) crash in old(), dead contact_interne field, access_type_id radio clearing" (rebased revision)
++                        $linkName = $link['name'] ?? '';
++                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%% diff from: vpwuyvyv f513921d "Fix: email clearing in findOrCreateAuthor, htmlspecialchars(null) crash in old(), dead contact_interne field, access_type_id radio clearing" (rebased revision)
\\\\\\\\\\\\\\\\\\\        to: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
-                        $linkName = $link['name'] ?? '';
-                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%% diff from: somsyvxz 14a3cd10 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebase destination)
\\\\\\\\\\\\\\\\\\\        to: pntwsqvs baf8b60c "Rename author_email→contact_interne, author_show_contact→contact_public across view/controllers/templates" (rebased revision)
                         $linkName = $link['name'] ?? '';
                         $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
                         $linkLockedYear = $link['locked_year'] ?? null;
+%%%%%%% diff from: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
+\\\\\\\        to: pntwsqvs dd95b4d3 "Rename author_email→contact_interne, author_show_contact→contact_public across view/controllers/templates" (rebased revision)
++                        $linkName = $link['name'] ?? '';
++                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%% diff from: pntwsqvs dd95b4d3 "Rename author_email→contact_interne, author_show_contact→contact_public across view/controllers/templates" (rebased revision)
\\\\\\\\\\\\\\\\\\\\\\\        to: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
-                        $linkName = $link['name'] ?? '';
-                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%% diff from: somsyvxz 14a3cd10 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebase destination)
\\\\\\\\\\\\\\\\\\\\\\\        to: sttrwkly dc233066 "CSV importer: boolean and ap variants/typos" (rebased revision)
                         $linkName = $link['name'] ?? '';
                         $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
                         $linkLockedYear = $link['locked_year'] ?? null;
+%%%%%%% diff from: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
+\\\\\\\        to: sttrwkly ec5606f5 "CSV importer: boolean and ap variants/typos" (rebased revision)
++                        $linkName = $link['name'] ?? '';
++                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: sttrwkly ec5606f5 "CSV importer: boolean and ap variants/typos" (rebased revision)
\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
-                        $linkName = $link['name'] ?? '';
-                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: somsyvxz 14a3cd10 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebase destination)
\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: qxuprqpt da941497 "Add language-search component for Autre Langue input + active search in lists" (rebased revision)
                         $linkName = $link['name'] ?? '';
                         $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
                         $linkLockedYear = $link['locked_year'] ?? null;
+%%%%%%% diff from: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
+\\\\\\\        to: qxuprqpt a1b3064d "Add language-search component for Autre Langue input + active search in lists" (rebased revision)
++                        $linkName = $link['name'] ?? '';
++                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: qxuprqpt a1b3064d "Add language-search component for Autre Langue input + active search in lists" (rebased revision)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
-                        $linkName = $link['name'] ?? '';
-                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: somsyvxz 14a3cd10 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebase destination)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: sntroxlt a8d07458 "Move Formulaire settings to contenus, remove delete-all TFE" (rebased revision)
                         $linkName = $link['name'] ?? '';
                         $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
                         $linkLockedYear = $link['locked_year'] ?? null;
+%%%%%%% diff from: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
+\\\\\\\        to: sntroxlt 6a5b93f3 "Move Formulaire settings to contenus, remove delete-all TFE" (rebased revision)
++                        $linkName = $link['name'] ?? '';
++                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: sntroxlt 6a5b93f3 "Move Formulaire settings to contenus, remove delete-all TFE" (rebased revision)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
-                        $linkName = $link['name'] ?? '';
-                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: somsyvxz 14a3cd10 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebase destination)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: tyotlpxt ceaca548 "Add Mots-clés and Langues management to contenus page" (rebased revision)
                         $linkName = $link['name'] ?? '';
                         $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
                         $linkLockedYear = $link['locked_year'] ?? null;
+%%%%%%% diff from: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
+\\\\\\\        to: tyotlpxt f7b0f560 "Add Mots-clés and Langues management to contenus page" (rebased revision)
++                        $linkName = $link['name'] ?? '';
++                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: tyotlpxt f7b0f560 "Add Mots-clés and Langues management to contenus page" (rebased revision)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
-                        $linkName = $link['name'] ?? '';
-                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: somsyvxz 14a3cd10 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebase destination)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: xvqonoyt 25dc22e7 "Add sidebar TOC, simplify Données Secondaires section" (rebased revision)
                         $linkName = $link['name'] ?? '';
                         $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
                         $linkLockedYear = $link['locked_year'] ?? null;
+%%%%%%% diff from: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
+\\\\\\\        to: xvqonoyt a3f280bc "Add sidebar TOC, simplify Données Secondaires section" (rebased revision)
++                        $linkName = $link['name'] ?? '';
++                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: xvqonoyt a3f280bc "Add sidebar TOC, simplify Données Secondaires section" (rebased revision)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
-                        $linkName = $link['name'] ?? '';
-                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: somsyvxz 14a3cd10 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebase destination)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: moumuszm 68c0e60c "Fix language-search fragment" (rebased revision)
                         $linkName = $link['name'] ?? '';
                         $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
                         $linkLockedYear = $link['locked_year'] ?? null;
+%%%%%%% diff from: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
+\\\\\\\        to: moumuszm 1e2ae09f "Fix language-search fragment" (rebased revision)
++                        $linkName = $link['name'] ?? '';
++                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: moumuszm 1e2ae09f "Fix language-search fragment" (rebased revision)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
-                        $linkName = $link['name'] ?? '';
-                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: somsyvxz 14a3cd10 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebase destination)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: kvyyvksn fd0f6e32 "fix: add help email, preserve file names on validation error, license fix" (rebased revision)
                         $linkName = $link['name'] ?? '';
                         $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
                         $linkLockedYear = $link['locked_year'] ?? null;
+%%%%%%% diff from: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
+\\\\\\\        to: kvyyvksn c5873f06 "fix: add help email, preserve file names on validation error, license fix" (rebased revision)
++                        $linkName = $link['name'] ?? '';
++                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: kvyyvksn c5873f06 "fix: add help email, preserve file names on validation error, license fix" (rebased revision)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
-                        $linkName = $link['name'] ?? '';
-                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: somsyvxz 14a3cd10 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebase destination)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: roqtyzln d714ae9b "feat: obfuscate all email addresses and mailto links as HTML entities" (rebased revision)
                         $linkName = $link['name'] ?? '';
                         $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
                         $linkLockedYear = $link['locked_year'] ?? null;
+%%%%%%% diff from: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
+\\\\\\\        to: roqtyzln 34d91340 "feat: obfuscate all email addresses and mailto links as HTML entities" (rebased revision)
++                        $linkName = $link['name'] ?? '';
++                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: roqtyzln 34d91340 "feat: obfuscate all email addresses and mailto links as HTML entities" (rebased revision)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
-                        $linkName = $link['name'] ?? '';
-                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: somsyvxz 14a3cd10 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebase destination)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: yztqkpzz f3b3686c "fix: TFE and annexes files not saved, plus keyword validation and file preview CSS" (rebased revision)
                         $linkName = $link['name'] ?? '';
                         $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
                         $linkLockedYear = $link['locked_year'] ?? null;
+%%%%%%% diff from: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
+\\\\\\\        to: yztqkpzz 9c95f5ce "fix: TFE and annexes files not saved, plus keyword validation and file preview CSS" (rebased revision)
++                        $linkName = $link['name'] ?? '';
++                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: yztqkpzz 9c95f5ce "fix: TFE and annexes files not saved, plus keyword validation and file preview CSS" (rebased revision)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
-                        $linkName = $link['name'] ?? '';
-                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: somsyvxz 14a3cd10 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebase destination)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: uvnvvyny 8b83eae7 "fix: req annexes, add HTMX inline file validation (MIME/size)" (rebased revision)
                         $linkName = $link['name'] ?? '';
                         $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
                         $linkLockedYear = $link['locked_year'] ?? null;
+%%%%%%% diff from: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
+\\\\\\\        to: uvnvvyny 09c854ea "fix: req annexes, add HTMX inline file validation (MIME/size)" (rebased revision)
++                        $linkName = $link['name'] ?? '';
++                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: uvnvvyny 09c854ea "fix: req annexes, add HTMX inline file validation (MIME/size)" (rebased revision)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
-                        $linkName = $link['name'] ?? '';
-                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: somsyvxz 14a3cd10 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebase destination)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: mxvvqust 02efed58 "refactor: session-based incremental TFE upload via HTMX, drop SortableJS" (rebased revision)
                         $linkName = $link['name'] ?? '';
                         $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
                         $linkLockedYear = $link['locked_year'] ?? null;
+%%%%%%% diff from: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
+\\\\\\\        to: mxvvqust 0a424ac8 "refactor: session-based incremental TFE upload via HTMX, drop SortableJS" (rebased revision)
++                        $linkName = $link['name'] ?? '';
++                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: mxvvqust 0a424ac8 "refactor: session-based incremental TFE upload via HTMX, drop SortableJS" (rebased revision)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
-                        $linkName = $link['name'] ?? '';
-                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: somsyvxz 14a3cd10 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebase destination)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: yrpmtrsy b15e8131 "fix: scoped HTMX file validation, add validation to TFE/PeerTube inputs" (rebased revision)
                         $linkName = $link['name'] ?? '';
                         $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
                         $linkLockedYear = $link['locked_year'] ?? null;
+%%%%%%% diff from: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
+\\\\\\\        to: yrpmtrsy 21452e6f "fix: scoped HTMX file validation, add validation to TFE/PeerTube inputs" (rebased revision)
++                        $linkName = $link['name'] ?? '';
++                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: yrpmtrsy 21452e6f "fix: scoped HTMX file validation, add validation to TFE/PeerTube inputs" (rebased revision)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
-                        $linkName = $link['name'] ?? '';
-                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: somsyvxz 14a3cd10 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebase destination)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: utnzmtom dc313ab2 "Replace HTMX+PHP file upload queues with client-side JS" (rebased revision)
                         $linkName = $link['name'] ?? '';
                         $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
                         $linkLockedYear = $link['locked_year'] ?? null;
+%%%%%%% diff from: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
+\\\\\\\        to: ownwlmpo c4c4c8c2 "Replace HTMX+PHP file upload queues with client-side JS" (rebased revision)
++                        $linkName = $link['name'] ?? '';
++                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: ownwlmpo c4c4c8c2 "Replace HTMX+PHP file upload queues with client-side JS" (rebased revision)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
-                        $linkName = $link['name'] ?? '';
-                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: somsyvxz 14a3cd10 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebase destination)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: muzswpkw 732e19e8 "fix: repair form submission with queued files + add comprehensive debug logging" (rebased revision)
                         $linkName = $link['name'] ?? '';
                         $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
                         $linkLockedYear = $link['locked_year'] ?? null;
+%%%%%%% diff from: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
+\\\\\\\        to: muzswpkw dbe1ac28 "fix: repair form submission with queued files + add comprehensive debug logging" (rebased revision)
++                        $linkName = $link['name'] ?? '';
++                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: muzswpkw dbe1ac28 "fix: repair form submission with queued files + add comprehensive debug logging" (rebased revision)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
-                        $linkName = $link['name'] ?? '';
-                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: somsyvxz 14a3cd10 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebase destination)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: ymrzpvln f17c59a8 "fix: spurious HTMX console warnings from checkbox-list default hx-include" (rebased revision)
                         $linkName = $link['name'] ?? '';
                         $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
                         $linkLockedYear = $link['locked_year'] ?? null;
+%%%%%%% diff from: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
+\\\\\\\        to: ymrzpvln 01fd03c9 "fix: spurious HTMX console warnings from checkbox-list default hx-include" (rebased revision)
++                        $linkName = $link['name'] ?? '';
++                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: ymrzpvln 01fd03c9 "fix: spurious HTMX console warnings from checkbox-list default hx-include" (rebased revision)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
-                        $linkName = $link['name'] ?? '';
-                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: somsyvxz 14a3cd10 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebase destination)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: urrtosru f5c94076 "fix: stop checkbox click in admin index from navigating to recapitulatif" (rebased revision)
                         $linkName = $link['name'] ?? '';
                         $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
                         $linkLockedYear = $link['locked_year'] ?? null;
+%%%%%%% diff from: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
+\\\\\\\        to: urrtosru e83a3728 "fix: stop checkbox click in admin index from navigating to recapitulatif" (rebased revision)
++                        $linkName = $link['name'] ?? '';
++                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: urrtosru e83a3728 "fix: stop checkbox click in admin index from navigating to recapitulatif" (rebased revision)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
-                        $linkName = $link['name'] ?? '';
-                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: somsyvxz 14a3cd10 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebase destination)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: pnotuyzv a365f68a (rebased revision)
                         $linkName = $link['name'] ?? '';
                         $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
                         $linkLockedYear = $link['locked_year'] ?? null;
+%%%%%%% diff from: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
+\\\\\\\        to: pnotuyzv d7107da4 (rebased revision)
++                        $linkName = $link['name'] ?? '';
++                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: pnotuyzv d7107da4 (rebased revision)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
-                        $linkName = $link['name'] ?? '';
-                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: somsyvxz 14a3cd10 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebase destination)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: qwltvwqq 5899acf3 "Replace custom file-upload-queue.js with FilePond" (rebased revision)
                         $linkName = $link['name'] ?? '';
                         $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
                         $linkLockedYear = $link['locked_year'] ?? null;
+%%%%%%% diff from: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
+\\\\\\\        to: qwltvwqq 0c33e74c "Replace custom file-upload-queue.js with FilePond" (rebased revision)
++                        $linkName = $link['name'] ?? '';
++                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: qwltvwqq 0c33e74c "Replace custom file-upload-queue.js with FilePond" (rebased revision)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
-                        $linkName = $link['name'] ?? '';
-                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: somsyvxz 14a3cd10 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebase destination)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: ztztkrsu 223fb3b3 (rebased revision)
                         $linkName = $link['name'] ?? '';
                         $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
                         $linkLockedYear = $link['locked_year'] ?? null;
+%%%%%%% diff from: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
+\\\\\\\        to: ztztkrsu 4234ef1b (rebased revision)
++                        $linkName = $link['name'] ?? '';
++                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: ztztkrsu 4234ef1b (rebased revision)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
-                        $linkName = $link['name'] ?? '';
-                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: somsyvxz 14a3cd10 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebase destination)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: yuuqpnwp 806e0941 "Fix FilePond integration: decouple format extras from main file inputs" (rebased revision)
                         $linkName = $link['name'] ?? '';
                         $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
                         $linkLockedYear = $link['locked_year'] ?? null;
+%%%%%%% diff from: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
+\\\\\\\        to: yuuqpnwp 6a989604 "Fix FilePond integration: decouple format extras from main file inputs" (rebased revision)
++                        $linkName = $link['name'] ?? '';
++                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: yuuqpnwp 6a989604 "Fix FilePond integration: decouple format extras from main file inputs" (rebased revision)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
-                        $linkName = $link['name'] ?? '';
-                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: somsyvxz 14a3cd10 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebase destination)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: zmvkxops 2da46d51 (rebased revision)
                         $linkName = $link['name'] ?? '';
                         $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
                         $linkLockedYear = $link['locked_year'] ?? null;
+%%%%%%% diff from: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
+\\\\\\\        to: zmvkxops 23fecead (rebased revision)
++                        $linkName = $link['name'] ?? '';
++                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: zmvkxops 23fecead (rebased revision)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
-                        $linkName = $link['name'] ?? '';
-                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: somsyvxz 14a3cd10 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebase destination)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: rptplqsr 54c10953 "Add FilePond pools for couverture, note_intention, video, audio" (rebased revision)
                         $linkName = $link['name'] ?? '';
                         $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
                         $linkLockedYear = $link['locked_year'] ?? null;
+%%%%%%% diff from: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
+\\\\\\\        to: rptplqsr 5f9568bd "Add FilePond pools for couverture, note_intention, video, audio" (rebased revision)
++                        $linkName = $link['name'] ?? '';
++                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: rptplqsr 5f9568bd "Add FilePond pools for couverture, note_intention, video, audio" (rebased revision)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
-                        $linkName = $link['name'] ?? '';
-                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: somsyvxz 14a3cd10 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebase destination)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: wvkvvpmv 33919970 "fix annexe validation, FilePond type validation, and styling" (rebased revision)
                         $linkName = $link['name'] ?? '';
                         $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
                         $linkLockedYear = $link['locked_year'] ?? null;
+%%%%%%% diff from: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
+\\\\\\\        to: wvkvvpmv 5044078a "fix annexe validation, FilePond type validation, and styling" (rebased revision)
++                        $linkName = $link['name'] ?? '';
++                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: wvkvvpmv 5044078a "fix annexe validation, FilePond type validation, and styling" (rebased revision)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
-                        $linkName = $link['name'] ?? '';
-                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: somsyvxz 14a3cd10 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebase destination)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: tqwpzqtq 83c9c5ff (rebased revision)
                         $linkName = $link['name'] ?? '';
                         $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
                         $linkLockedYear = $link['locked_year'] ?? null;
+%%%%%%% diff from: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
+\\\\\\\        to: tqwpzqtq b2fcb530 (rebased revision)
++                        $linkName = $link['name'] ?? '';
++                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: tqwpzqtq b2fcb530 (rebased revision)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
-                        $linkName = $link['name'] ?? '';
-                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: somsyvxz 14a3cd10 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebase destination)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: stmuuwmv 679ece97 "add server-side video/audio size limits (2 GB) and fix missing annexe queue validation" (rebased revision)
                         $linkName = $link['name'] ?? '';
                         $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
                         $linkLockedYear = $link['locked_year'] ?? null;
+%%%%%%% diff from: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
+\\\\\\\        to: stmuuwmv 45c8d894 "add server-side video/audio size limits (2 GB) and fix missing annexe queue validation" (rebased revision)
++                        $linkName = $link['name'] ?? '';
++                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: stmuuwmv 45c8d894 "add server-side video/audio size limits (2 GB) and fix missing annexe queue validation" (rebased revision)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
-                        $linkName = $link['name'] ?? '';
-                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: somsyvxz 14a3cd10 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebase destination)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: wmzntpxp b9fa7c04 "add filepond-plugin-file-validate-type + server-side file warnings" (rebased revision)
                         $linkName = $link['name'] ?? '';
                         $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
                         $linkLockedYear = $link['locked_year'] ?? null;
+%%%%%%% diff from: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
+\\\\\\\        to: wmzntpxp aa25c473 "add filepond-plugin-file-validate-type + server-side file warnings" (rebased revision)
++                        $linkName = $link['name'] ?? '';
++                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: wmzntpxp aa25c473 "add filepond-plugin-file-validate-type + server-side file warnings" (rebased revision)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
-                        $linkName = $link['name'] ?? '';
-                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: somsyvxz 14a3cd10 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebase destination)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: rlqsxozn a2d3f72a "fix file validation: use extension-based check in beforeAddFile, drop plugin" (rebased revision)
                         $linkName = $link['name'] ?? '';
                         $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
                         $linkLockedYear = $link['locked_year'] ?? null;
+%%%%%%% diff from: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
+\\\\\\\        to: rlqsxozn e69b00bf "fix file validation: use extension-based check in beforeAddFile, drop plugin" (rebased revision)
++                        $linkName = $link['name'] ?? '';
++                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: rlqsxozn e69b00bf "fix file validation: use extension-based check in beforeAddFile, drop plugin" (rebased revision)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
-                        $linkName = $link['name'] ?? '';
-                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: somsyvxz 14a3cd10 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebase destination)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: vqnonzxp 9b795ebc "remove accept attributes from FilePond inputs, rely on beforeAddFile validation" (rebased revision)
                         $linkName = $link['name'] ?? '';
                         $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
                         $linkLockedYear = $link['locked_year'] ?? null;
+%%%%%%% diff from: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
+\\\\\\\        to: vqnonzxp fc15ae85 "remove accept attributes from FilePond inputs, rely on beforeAddFile validation" (rebased revision)
++                        $linkName = $link['name'] ?? '';
++                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: vqnonzxp fc15ae85 "remove accept attributes from FilePond inputs, rely on beforeAddFile validation" (rebased revision)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
-                        $linkName = $link['name'] ?? '';
-                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: somsyvxz 14a3cd10 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebase destination)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: xznsyswm ecbb6c5f "FilePond production hardening" (rebased revision)
                         $linkName = $link['name'] ?? '';
                         $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
                         $linkLockedYear = $link['locked_year'] ?? null;
+%%%%%%% diff from: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
+\\\\\\\        to: xznsyswm a408afdc "FilePond production hardening" (rebased revision)
++                        $linkName = $link['name'] ?? '';
++                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: xznsyswm a408afdc "FilePond production hardening" (rebased revision)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
-                        $linkName = $link['name'] ?? '';
-                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: somsyvxz 14a3cd10 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebase destination)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: vqxpnkox 1fba7167 "fix migration 028, promoteurice repopulation, DB bootstrap" (rebased revision)
                         $linkName = $link['name'] ?? '';
                         $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
                         $linkLockedYear = $link['locked_year'] ?? null;
+%%%%%%% diff from: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
+\\\\\\\        to: vqxpnkox f51d447c "fix migration 028, promoteurice repopulation, DB bootstrap" (rebased revision)
++                        $linkName = $link['name'] ?? '';
++                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: vqxpnkox f51d447c "fix migration 028, promoteurice repopulation, DB bootstrap" (rebased revision)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
-                        $linkName = $link['name'] ?? '';
-                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: somsyvxz 14a3cd10 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebase destination)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: zxryvzkv 9d3f6b53 "Improve recap page + fix CSV import for jury roles" (rebased revision)
                         $linkName = $link['name'] ?? '';
                         $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
                         $linkLockedYear = $link['locked_year'] ?? null;
+%%%%%%% diff from: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
+\\\\\\\        to: zxryvzkv 27814cea "Improve recap page + fix CSV import for jury roles" (rebased revision)
++                        $linkName = $link['name'] ?? '';
++                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: zxryvzkv 27814cea "Improve recap page + fix CSV import for jury roles" (rebased revision)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
-                        $linkName = $link['name'] ?? '';
-                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: somsyvxz 14a3cd10 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebase destination)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: wpspurnq 087c2119 "Make Auteur(s) and Accès columns sortable alphabetically in admin list" (rebased revision)
                         $linkName = $link['name'] ?? '';
                         $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
                         $linkLockedYear = $link['locked_year'] ?? null;
+%%%%%%% diff from: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
+\\\\\\\        to: wpspurnq 76964b90 "Make Auteur(s) and Accès columns sortable alphabetically in admin list" (rebased revision)
++                        $linkName = $link['name'] ?? '';
++                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: wpspurnq 76964b90 "Make Auteur(s) and Accès columns sortable alphabetically in admin list" (rebased revision)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
-                        $linkName = $link['name'] ?? '';
-                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: somsyvxz 14a3cd10 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebase destination)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: snsxswsz 1675e31b "fix: jury-fieldset.php calling old() with wrong signature for partage" (rebased revision)
                         $linkName = $link['name'] ?? '';
                         $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
                         $linkLockedYear = $link['locked_year'] ?? null;
+%%%%%%% diff from: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
+\\\\\\\        to: snsxswsz 5a33fb93 "fix: jury-fieldset.php calling old() with wrong signature for partage" (rebased revision)
++                        $linkName = $link['name'] ?? '';
++                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: snsxswsz 5a33fb93 "fix: jury-fieldset.php calling old() with wrong signature for partage" (rebased revision)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
-                        $linkName = $link['name'] ?? '';
-                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: somsyvxz 14a3cd10 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebase destination)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: ryqustol 90de0848 "import dialog: add Terminé button, fix padding, make success permanent, avoid POST resend" (rebased revision)
                         $linkName = $link['name'] ?? '';
                         $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
                         $linkLockedYear = $link['locked_year'] ?? null;
+%%%%%%% diff from: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
+\\\\\\\        to: ryqustol a5179270 "import dialog: add Terminé button, fix padding, make success permanent, avoid POST resend" (rebased revision)
++                        $linkName = $link['name'] ?? '';
++                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: ryqustol a5179270 "import dialog: add Terminé button, fix padding, make success permanent, avoid POST resend" (rebased revision)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
-                        $linkName = $link['name'] ?? '';
-                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: somsyvxz 14a3cd10 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebase destination)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: nqmqrqmo 2b244c73 "fix: obfuscate email in contact links, raise rate limits, make Libre toggleable" (rebased revision)
                         $linkName = $link['name'] ?? '';
                         $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
                         $linkLockedYear = $link['locked_year'] ?? null;
+%%%%%%% diff from: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
+\\\\\\\        to: nqmqrqmo dd511b0d "fix: obfuscate email in contact links, raise rate limits, make Libre toggleable" (rebased revision)
++                        $linkName = $link['name'] ?? '';
++                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: nqmqrqmo dd511b0d "fix: obfuscate email in contact links, raise rate limits, make Libre toggleable" (rebased revision)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
-                        $linkName = $link['name'] ?? '';
-                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: somsyvxz 14a3cd10 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebase destination)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: olzzwmwr 277c8ce4 "feat: require 3 mots-clés in partage, language asterisk toggle, admin auto-save checkboxes" (rebased revision)
                         $linkName = $link['name'] ?? '';
                         $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
                         $linkLockedYear = $link['locked_year'] ?? null;
+%%%%%%% diff from: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
+\\\\\\\        to: olzzwmwr 82533c5a "feat: require 3 mots-clés in partage, language asterisk toggle, admin auto-save checkboxes" (rebased revision)
++                        $linkName = $link['name'] ?? '';
++                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: olzzwmwr 82533c5a "feat: require 3 mots-clés in partage, language asterisk toggle, admin auto-save checkboxes" (rebased revision)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
-                        $linkName = $link['name'] ?? '';
-                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: somsyvxz 14a3cd10 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebase destination)
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\        to: nlvsnzkz bb34ea85 "fix: add hx-swap="none" to admin auto-save checkboxes to prevent page swap" (rebased revision)
                         $linkName = $link['name'] ?? '';
                         $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
                         $linkLockedYear = $link['locked_year'] ?? null;
+%%%%%%% diff from: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
+\\\\\\\        to: nlvsnzkz 0f4613f5 "fix: add hx-swap="none" to admin auto-save checkboxes to prevent page swap" (rebased revision)
++                        $linkName = $link['name'] ?? '';
++                        $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
                    ?>
                    <tr class="admin-table-row" onclick="event.stopPropagation(); window.open('/partage/<?= urlencode($link['slug']) ?>', '_blank')" style="cursor:pointer">
                        <td><?= htmlspecialchars($linkName ?: '—') ?></td>
                        <td>
                            <code style="font-size:var(--step--2);color:var(--text-secondary);"><?= htmlspecialchars($link['slug']) ?></code>
                            <input type="hidden" id="url-<?= $link['id'] ?>" value="<?= $fullUrl ?>">
                        </td>
                        <td>
                            <?php if ($link['objet_restriction']): ?>
                                <span class="status-badge"><?= htmlspecialchars($link['objet_restriction']) ?></span>
                            <?php else: ?>
                                <span style="color:var(--text-secondary);font-size:var(--step--2);">Tous</span>
                            <?php endif; ?>
                        </td>
                        <td>
                            <?php if ($link['locked_year']): ?>
                                <span class="status-badge" style="background:var(--accent-green-muted-bg, #e6f7ec);color:var(--accent-green, #1a7f4b);border:1px solid var(--accent-green, #1a7f4b);">🔒 <?= htmlspecialchars((string)$link['locked_year']) ?></span>
                            <?php else: ?>
                                <span style="color:var(--text-secondary);font-size:var(--step--2);">Libre</span>
                            <?php endif; ?>
                        </td>
                        <td>
                            <?php if ($isExpired): ?>
                                <span class="status-badge status-pending"><?= $statusLabel ?></span>
                            <?php elseif ($link['is_active']): ?>
                                <span class="status-badge status-published"><?= $statusLabel ?></span>
                            <?php else: ?>
                                <span style="display:inline-block;padding:var(--space-3xs) var(--space-2xs);border-radius:3px;font-size:var(--step--2);font-weight:500;letter-spacing:0.04em;background:var(--error-muted-bg);color:var(--error);"><?= $statusLabel ?></span>
                            <?php endif; ?>
                        </td>
                        <td><?= $hasLinkPassword ? 'Oui' : 'Non' ?></td>
                        <td style="text-align:center;"><?= intval($link['usage_count']) ?></td>
                        <td><?= $expires ?></td>
                        <td><?= $created ?></td>
                        <td class="admin-actions-col">
                            <div class="admin-actions">
                                <button type="button" class="admin-icon-btn admin-icon-btn--edit" title="Éditer"
                                        onclick="event.stopPropagation(); openEditDialog(<?= $link['id'] ?>, <?= htmlspecialchars(json_encode($linkName), ENT_QUOTES) ?>, <?= $hasLinkPassword ? 'true' : 'false' ?>, <?= htmlspecialchars(json_encode($linkExpiresVal), ENT_QUOTES) ?>)">
                                    <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="currentColor" viewBox="0 0 256 256"><path d="M248,92.68a15.86,15.86,0,0,0-4.69-11.31L174.63,12.68a16,16,0,0,0-22.63,0L123.57,41.11l-58,21.77A16.06,16.06,0,0,0,55.35,75.23L32.11,214.68A8,8,0,0,0,40,224a8.4,8.4,0,0,0,1.32-.11l139.44-23.24a16,16,0,0,0,12.35-10.17l21.77-58L243.31,104A15.87,15.87,0,0,0,248,92.68Zm-69.87,92.19L63.32,204l47.37-47.37a28,28,0,1,0-11.32-11.32L52,192.7,71.13,77.86,126,57.29,198.7,130ZM112,132a12,12,0,1,1,12,12A12,12,0,0,1,112,132Zm96-15.32L139.31,48l24-24L232,92.68Z"></path></svg>
                                </button>
                                <button type="button" class="admin-icon-btn admin-icon-btn--copy" title="Copier l'URL"
                                        onclick="event.stopPropagation(); copyUrl(<?= $link['id'] ?>)">
                                    <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="currentColor" viewBox="0 0 256 256"><path d="M216,32H88a8,8,0,0,0-8,8V80H40a8,8,0,0,0-8,8V216a8,8,0,0,0,8,8H168a8,8,0,0,0,8-8V176h40a8,8,0,0,0,8-8V40A8,8,0,0,0,216,32ZM160,208H48V96H160Zm48-48H176V88a8,8,0,0,0-8-8H96V48H208Z"></path></svg>
                                </button>
                                <form method="post" action="actions/acces-etudiante.php" class="publish-form" onclick="event.stopPropagation()">
                                    <input type="hidden" name="csrf_token" value="<?= htmlspecialchars($_SESSION['csrf_token']) ?>">
                                    <input type="hidden" name="action" value="toggle">
                                    <input type="hidden" name="id" value="<?= $link['id'] ?>">
                                    <button type="submit"
                                            class="admin-icon-btn <?= $link['is_active'] ? 'admin-icon-btn--unpublish' : 'admin-icon-btn--publish' ?>"
                                            title="<?= $link['is_active'] ? 'Désactiver' : 'Activer' ?>">
                                        <?php if ($link['is_active']): ?>
                                            <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="currentColor" viewBox="0 0 256 256"><path d="M200,32H160a16,16,0,0,0-16,16V208a16,16,0,0,0,16,16h40a16,16,0,0,0,16-16V48A16,16,0,0,0,200,32Zm0,176H160V48h40ZM96,32H56A16,16,0,0,0,40,48V208a16,16,0,0,0,16,16H96a16,16,0,0,0,16-16V48A16,16,0,0,0,96,32Zm0,176H56V48H96Z"></path></svg>
                                        <?php else: ?>
                                            <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="currentColor" viewBox="0 0 256 256"><path d="M232.4,114.49,88.32,26.35a16,16,0,0,0-16.2-.3A15.86,15.86,0,0,0,64,39.87V216.13A15.94,15.94,0,0,0,80,232a16.07,16.07,0,0,0,8.36-2.35L232.4,141.51a15.81,15.81,0,0,0,0-27ZM80,215.94V40l143.83,88Z"></path></svg>
                                        <?php endif; ?>
                                    </button>
                                </form>
                                <form method="post" action="actions/acces-etudiante.php" class="publish-form"
                                      id="archive-link-form-<?= $link['id'] ?>" onclick="event.stopPropagation()">
                                    <input type="hidden" name="csrf_token" value="<?= htmlspecialchars($_SESSION['csrf_token']) ?>">
                                    <input type="hidden" name="action" value="archive">
                                    <input type="hidden" name="id" value="<?= $link['id'] ?>">
                                    <button type="button" class="admin-icon-btn admin-icon-btn--archive" title="Archiver"
                                            onclick="openArchiveLinkDialog(<?= $link['id'] ?>)">
                                        <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="currentColor" viewBox="0 0 256 256"><path d="M224,48H32A16,16,0,0,0,16,64V88a16,16,0,0,0,16,16v88a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V104a16,16,0,0,0,16-16V64A16,16,0,0,0,224,48ZM208,192H48V104H208ZM224,88H32V64H224V88ZM96,136a8,8,0,0,1,8-8h48a8,8,0,0,1,0,16H104A8,8,0,0,1,96,136Z"></path></svg>
                                    </button>
                                </form>
                            </div>
                        </td>
                    </tr>
                <?php endforeach; ?>
            </tbody>
        </table>
        <?php endif; ?>

        <?php if (!empty($archivedLinks)): ?>
        <details style="margin-top:var(--space-m);">
            <summary style="cursor:pointer;font-weight:600;color:var(--text-secondary);font-size:var(--step--1);">
                Liens archivés (<?= count($archivedLinks) ?>)
            </summary>
            <table style="margin-top:var(--space-s);opacity:0.75;">
                <thead>
                    <tr>
                        <th scope="col">Nom</th>
                        <th scope="col">Lien</th>
                        <th scope="col">Objet</th>
                        <th scope="col">Utilisations</th>
                        <th scope="col">Expiration</th>
                        <th scope="col">Créé le</th>
                    </tr>
                </thead>
                <tbody>
                    <?php foreach ($archivedLinks as $link): ?>
                        <?php
                            $created = date('d/m/Y H:i', strtotime($link['created_at']));
                            $expires = $link['expires_at'] ? date('d/m/Y H:i', strtotime($link['expires_at'])) : '-';
                        ?>
                        <tr>
                            <td><?= htmlspecialchars($link['name'] ?? '—') ?></td>
                            <td>
                                <code style="font-size:var(--step--2);color:var(--text-secondary);text-decoration:line-through;"><?= htmlspecialchars($link['slug']) ?></code>
                            </td>
                            <td>
                                <?php if ($link['objet_restriction']): ?>
                                    <span class="status-badge"><?= htmlspecialchars($link['objet_restriction']) ?></span>
                                <?php else: ?>
                                    <span style="color:var(--text-secondary);font-size:var(--step--2);">Tous</span>
                                <?php endif; ?>
                            </td>
                            <td style="text-align:center;"><?= intval($link['usage_count']) ?></td>
                            <td><?= $expires ?></td>
                            <td><?= $created ?></td>
                        </tr>
                    <?php endforeach; ?>
                </tbody>
            </table>
        </details>
        <?php endif; ?>
    </section>

    <!-- ══════════════════════════════════════════════════════════════
         DEMANDES D'ACCÈS AUX FICHIERS
    ══════════════════════════════════════════════════════════════ -->
    <section aria-labelledby="acces-fichiers-title">
        <h2 id="acces-fichiers-title">Demandes d'accès aux fichiers</h2>

        <div class="access-req-stats">
            <div class="access-req-stat-card">
                <span class="access-req-stat-number"><?= $pendingCount ?></span>
                <span class="access-req-stat-label">En attente</span>
            </div>
            <div class="access-req-stat-card">
                <span class="access-req-stat-number"><?= $approvedCount ?></span>
                <span class="access-req-stat-label">Approuvées</span>
            </div>
            <div class="access-req-stat-card">
                <span class="access-req-stat-number"><?= $rejectedCount ?></span>
                <span class="access-req-stat-label">Rejetées</span>
            </div>
        </div>

        <nav class="access-req-tabs">
            <a href="?status=pending" class="access-req-tab <?= $status === 'pending' ? 'active' : '' ?>">
                En attente <?= $pendingCount > 0 ? "({$pendingCount})" : '' ?>
            </a>
            <a href="?status=approved" class="access-req-tab <?= $status === 'approved' ? 'active' : '' ?>">
                Approuvées
            </a>
            <a href="?status=rejected" class="access-req-tab <?= $status === 'rejected' ? 'active' : '' ?>">
                Rejetées
            </a>
        </nav>

        <?php if (empty($requests)): ?>
            <div class="access-req-empty">
                <p>Aucune demande <?= $status === 'pending' ? 'en attente' : ($status === 'approved' ? 'approuvée' : 'rejetée') ?>.</p>
            </div>
        <?php else: ?>
            <div class="access-req-list">
                <?php foreach ($requests as $req): ?>
                    <div class="access-req-card">
                        <div class="access-req-card__header">
                            <div class="access-req-card__thesis">
                                <h3><?= htmlspecialchars($req['title']) ?></h3>
                                <p class="access-req-card__authors">
                                    <?php if (!empty($req['authors'])): ?>
                                        par <?= htmlspecialchars($req['authors']) ?>
                                    <?php endif; ?>
                                    <?php if (!empty($req['year'])): ?>
                                        - <?= htmlspecialchars($req['year']) ?>
                                    <?php endif; ?>
                                </p>
                            </div>
                            <div class="access-req-card__meta">
                                <span class="access-req-badge access-req-badge--<?= $status ?>">
                                    <?= $status === 'pending' ? 'En attente' : ($status === 'approved' ? 'Approuvée' : 'Rejetée') ?>
                                </span>
                            </div>
                        </div>

                        <div class="access-req-card__body">
                            <div class="access-req-card__info">
                                <div>
                                    <strong>Email :</strong>
                                    <a href="<?= EmailObfuscator::mailto($req['email']) ?>"><?= htmlspecialchars($req['email']) ?></a>
                                </div>
                                <div>
                                    <strong>Date :</strong>
                                    <?= date('d/m/Y à H:i', strtotime($req['created_at'])) ?>
                                </div>
                                <?php if ($status === 'approved' && !empty($req['approved_at'])): ?>
                                    <div>
                                        <strong>Approuvée le :</strong>
                                        <?= date('d/m/Y à H:i', strtotime($req['approved_at'])) ?>
                                    </div>
                                <?php endif; ?>
                                <?php if ($status === 'rejected' && !empty($req['approved_at'])): ?>
                                    <div>
                                        <strong>Rejetée le :</strong>
                                        <?= date('d/m/Y à H:i', strtotime($req['approved_at'])) ?>
                                    </div>
                                <?php endif; ?>
                            </div>

                            <?php if (!empty($req['justification'])): ?>
                                <div class="access-req-card__justification">
                                    <strong>Justification :</strong>
                                    <p><?= nl2br(htmlspecialchars($req['justification'])) ?></p>
                                </div>
                            <?php endif; ?>

                            <?php if ($status === 'rejected' && !empty($req['admin_notes'])): ?>
                                <div class="access-req-card__admin-notes">
                                    <strong>Note de l'administrateur :</strong>
                                    <p><?= nl2br(htmlspecialchars($req['admin_notes'])) ?></p>
                                </div>
                            <?php endif; ?>

                            <?php if ($status === 'pending'): ?>
                                <div class="access-req-card__actions">
                                    <button type="button"
                                            class="btn btn--primary access-req-btn access-req-btn--approve"
                                            onclick="openApproveDialog(<?= $req['id'] ?>)">
                                        Approuver
                                    </button>
                                    <button type="button"
                                            class="btn btn--danger access-req-btn access-req-btn--reject"
                                            onclick="openRejectDialog(<?= $req['id'] ?>)">
                                        Rejeter
                                    </button>
                                </div>
                            <?php endif; ?>
                        </div>
                    </div>
                <?php endforeach; ?>
            </div>

            <?php if ($totalPages > 1): ?>
                <nav class="access-req-pagination">
                    <?php if ($page > 1): ?>
                        <a href="?status=<?= $status ?>&page=<?= $page - 1 ?>" class="access-req-pagination__link">
                            &larr; Précédent
                        </a>
                    <?php endif; ?>

                    <span class="access-req-pagination__info">
                        Page <?= $page ?> sur <?= $totalPages ?>
                    </span>

                    <?php if ($page < $totalPages): ?>
                        <a href="?status=<?= $status ?>&page=<?= $page + 1 ?>" class="access-req-pagination__link">
                            Suivant &rarr;
                        </a>
                    <?php endif; ?>
                </nav>
            <?php endif; ?>
        <?php endif; ?>
    </section>
    </article>
</main>

<!-- ═══════════════════════ CREATE DIALOG ═══════════════════════ -->
<dialog id="create-dialog" class="admin-dialog" aria-labelledby="create-dialog-title">
    <div class="admin-dialog__header">
        <h2 id="create-dialog-title">Créer un lien</h2>
        <button type="button" class="admin-dialog__close" aria-label="Fermer"
                onclick="document.getElementById('create-dialog').close()">&#x2715;</button>
    </div>
    <form method="post" action="actions/acces-etudiante.php" class="admin-form">
        <input type="hidden" name="csrf_token" value="<?= htmlspecialchars($_SESSION['csrf_token']) ?>">
        <input type="hidden" name="action" value="create">
        <fieldset>
            <legend>Nom (optionnel)</legend>
            <input type="text" name="name" placeholder="Ex: Lien promo 2025">
            <small>Donnez un nom pour identifier facilement ce lien.</small>
        </fieldset>
        <fieldset>
            <legend>Type d'objet</legend>
            <label style="display:flex;align-items:center;gap:var(--space-2xs);font-weight:400;">
                <input type="checkbox" name="objet_restriction[]" value="tfe" checked> TFE (par défaut)
            </label>
            <label style="display:flex;align-items:center;gap:var(--space-2xs);font-weight:400;">
                <input type="checkbox" name="objet_restriction[]" value="thèse"> Thèse
            </label>
            <label style="display:flex;align-items:center;gap:var(--space-2xs);font-weight:400;">
                <input type="checkbox" name="objet_restriction[]" value="frart"> Frart
            </label>
            <small>Le lien sera restreint aux types cochés. Par défaut : TFE uniquement.</small>
        </fieldset>
        <fieldset>
            <legend>Accès</legend>
            <div>
                <label for="create-password">Mot de passe (optionnel)</label>
                <input type="password" id="create-password" name="password" autocomplete="new-password">
            </div>
            <div>
                <label for="create-expires">Expiration (optionnel)</label>
                <input type="datetime-local" id="create-expires" name="expires_at">
            </div>
        </fieldset>
        <div class="admin-form-footer">
            <button type="submit" class="btn btn--primary">Créer le lien</button>
            <button type="button" class="btn btn--secondary"
                    onclick="document.getElementById('create-dialog').close()">Annuler</button>
        </div>
    </form>
</dialog>

<!-- ═══════════════════════ EDIT DIALOG ═══════════════════════ -->
<dialog id="edit-dialog" class="admin-dialog" aria-labelledby="edit-dialog-title">
    <div class="admin-dialog__header">
        <h2 id="edit-dialog-title">Modifier le lien</h2>
        <button type="button" class="admin-dialog__close" aria-label="Fermer"
                onclick="document.getElementById('edit-dialog').close()">&#x2715;</button>
    </div>
    <form method="post" action="actions/acces-etudiante.php" class="admin-form">
        <input type="hidden" name="csrf_token" value="<?= htmlspecialchars($_SESSION['csrf_token']) ?>">
        <input type="hidden" name="action" value="update">
        <input type="hidden" name="id" id="edit-link-id" value="">
        <div>
            <label for="edit-name">Nom</label>
            <input type="text" id="edit-name" name="name" placeholder="Ex: Lien promo 2025">
        </div>
        <div>
            <label for="edit-password">Mot de passe (laisser vide pour ne pas changer)</label>
            <input type="password" id="edit-password" name="password" autocomplete="new-password" placeholder="Laisser vide pour conserver">
            <small>Entrez un nouveau mot de passe ou laissez vide pour ne pas modifier.</small>
        </div>
        <div>
            <label for="edit-expires">Expiration</label>
            <input type="datetime-local" id="edit-expires" name="expires_at">
            <small>Laissez vide pour qu'il n'expire jamais.</small>
        </div>
        <div class="admin-form-footer">
            <button type="submit" class="btn btn--primary">Enregistrer</button>
            <button type="button" class="btn btn--secondary"
                    onclick="document.getElementById('edit-dialog').close()">Annuler</button>
        </div>
    </form>
</dialog>

<!-- ═══════════════════════ PASSWORD DIALOG (kept for backward compat) ═══════════════════════ -->
<dialog id="password-dialog" class="admin-dialog" aria-labelledby="password-dialog-title">
    <div class="admin-dialog__header">
        <h2 id="password-dialog-title">Mot de passe</h2>
        <button type="button" class="admin-dialog__close" aria-label="Fermer"
                onclick="document.getElementById('password-dialog').close()">&#x2715;</button>
    </div>
    <form method="post" action="actions/acces-etudiante.php" class="admin-form">
        <input type="hidden" name="csrf_token" value="<?= htmlspecialchars($_SESSION['csrf_token']) ?>">
        <input type="hidden" name="action" value="set_password">
        <input type="hidden" name="id" id="password-link-id" value="">
        <div>
            <label for="password-input">Nouveau mot de passe</label>
            <input type="password" id="password-input" name="password" autocomplete="new-password">
            <small>Laissez vide pour supprimer le mot de passe.</small>
            <p id="password-current-info" style="font-size:var(--step--2);color:var(--text-secondary);margin-top:var(--space-2xs);"></p>
        </div>
        <div class="admin-form-footer">
            <button type="submit" class="btn btn--primary">Enregistrer</button>
            <button type="button" class="btn btn--secondary"
                    onclick="document.getElementById('password-dialog').close()">Annuler</button>
        </div>
    </form>
</dialog>

<!-- ═══════════════════════ APPROVE DIALOG ═══════════════════════ -->
<dialog id="approve-dialog" class="admin-dialog">
    <div class="admin-dialog__header">
        <h2>Approuver la demande</h2>
        <button type="button" class="admin-dialog__close"
                onclick="document.getElementById('approve-dialog').close()">&times;</button>
    </div>
    <form method="post" action="/admin/actions/access-request.php">
        <input type="hidden" name="csrf_token" value="<?= htmlspecialchars($_SESSION['csrf_token']) ?>">
        <input type="hidden" name="request_id" id="approve-request-id">
        <input type="hidden" name="action" value="approve">
        <label for="approve-notes">Note optionnelle (inclus dans l'email) :</label>
        <textarea name="admin_notes" id="approve-notes" rows="3"
                  placeholder="Message personnalisé pour le demandeur..."></textarea>
        <div class="admin-form-footer">
            <button type="submit" class="btn btn--primary">Approuver et envoyer email</button>
            <button type="button" class="btn btn--secondary"
                    onclick="document.getElementById('approve-dialog').close()">Annuler</button>
        </div>
    </form>
</dialog>

<!-- ═══════════════════════ REJECT DIALOG ════════════════════════ -->
<dialog id="reject-dialog" class="admin-dialog">
    <div class="admin-dialog__header">
        <h2>Rejeter la demande</h2>
        <button type="button" class="admin-dialog__close"
                onclick="document.getElementById('reject-dialog').close()">&times;</button>
    </div>
    <form method="post" action="/admin/actions/access-request.php">
        <input type="hidden" name="csrf_token" value="<?= htmlspecialchars($_SESSION['csrf_token']) ?>">
        <input type="hidden" name="request_id" id="reject-request-id">
        <input type="hidden" name="action" value="reject">
        <label for="reject-notes">Raison du rejet (optionnel) :</label>
        <textarea name="admin_notes" id="reject-notes" rows="3"
                  placeholder="Raison du rejet..."></textarea>
        <div class="admin-form-footer">
            <button type="submit" class="btn btn--danger">Rejeter</button>
            <button type="button" class="btn btn--secondary"
                    onclick="document.getElementById('reject-dialog').close()">Annuler</button>
        </div>
    </form>
</dialog>

<script>
document.getElementById('open-create-dialog').addEventListener('click', () => {
    document.getElementById('create-dialog').showModal();
});

function copyUrl(id) {
    const input = document.getElementById('url-' + id);
    navigator.clipboard.writeText(input.value).then(() => {
        const btn = event.target.closest('button');
        if (btn) { const orig = btn.getAttribute('title') || ''; btn.setAttribute('title', '✓ Copié'); setTimeout(() => btn.setAttribute('title', orig), 1200); }
    });
}

function openEditDialog(id, name, hasPassword, expiresVal) {
    document.getElementById('edit-link-id').value = id;
    document.getElementById('edit-name').value = name || '';
    document.getElementById('edit-password').value = '';
    document.getElementById('edit-password').placeholder = hasPassword ? 'Laisser vide pour conserver' : 'Laisser vide pour ne pas en mettre';
    document.getElementById('edit-expires').value = expiresVal || '';
    document.getElementById('edit-dialog').showModal();
}

function openPasswordDialog(id, hasPassword) {
    document.getElementById('password-link-id').value = id;
    const info = document.getElementById('password-current-info');
    info.textContent = hasPassword
        ? 'Un mot de passe est actuellement configuré. Entrez-en un nouveau ou laissez vide pour le supprimer.'
        : 'Aucun mot de passe configuré.';
    document.getElementById('password-dialog').showModal();
}

function openApproveDialog(requestId) {
    document.getElementById('approve-request-id').value = requestId;
    document.getElementById('approve-dialog').showModal();
}

function openRejectDialog(requestId) {
    document.getElementById('reject-request-id').value = requestId;
    document.getElementById('reject-dialog').showModal();
}

let _pendingArchiveLinkId = null;
function openArchiveLinkDialog(id) {
    _pendingArchiveLinkId = id;
    document.getElementById('archive-link-dialog').showModal();
}
function _executeArchiveLink() {
    const form = document.getElementById('archive-link-form-' + _pendingArchiveLinkId);
    if (form) form.submit();
}
</script>

<!-- Archive link confirm -->
<dialog id="archive-link-dialog" class="admin-dialog admin-dialog--sm" aria-labelledby="archive-link-title">
    <div class="admin-dialog__header">
        <h2 id="archive-link-title">Archiver ce lien</h2>
        <button type="button" class="admin-dialog__close" aria-label="Fermer"
                onclick="this.closest('dialog').close()">&#x2715;</button>
    </div>
    <div class="admin-dialog__alert">
        <p>Archiver ce lien ? Il ne sera plus accessible, mais les statistiques seront conservées.</p>
    </div>
    <div class="admin-dialog__footer">
        <button type="button" class="btn btn--warning" onclick="this.closest('dialog').close(); _executeArchiveLink()">Archiver</button>
        <button type="button" class="btn btn--secondary" onclick="this.closest('dialog').close()">Annuler</button>
    </div>
</dialog>
