/* ============================================================
0. SESSION & PROTECTION
============================================================ */
session_start();
if (!isset($_SESSION['email'])) {
header("Location: login.php");
exit;
}
/* ============================================================
1. CONNEXION BDD (PDO $bdd)
============================================================ */
if (!isset($bdd)) {
$paths = [__DIR__ . '/db.php', __DIR__ . '/../db.php'];
foreach ($paths as $p) {
if (file_exists($p)) { require_once $p; break; }
}
}
if (!isset($bdd) || !($bdd instanceof PDO)) {
die('Configuration base de données introuvable.');
}
/* ============================================================
1b. HELPER — substr UTF-8 safe & chemin image
============================================================ */
if (!function_exists('safeSubstr')) {
function safeSubstr($s, $start, $len) {
if (function_exists('mb_substr')) return mb_substr($s, $start, $len, 'UTF-8');
return substr($s, 0, $len);
}
}
// ? CORRECTIF : Force le dossier d'upload à la racine du site public
$uploadDir = rtrim($_SERVER['DOCUMENT_ROOT'], '/') . '/images/resource/';
/* ============================================================
1c. MODE DIAGNOSTIC (Pour vérifier où vont les images)
============================================================ */
if (isset($_GET['debug'])) {
echo '
echo '
? Diagnostic Images
'; echo 'DOCUMENT_ROOT : ' . htmlspecialchars($_SERVER['DOCUMENT_ROOT']) . '
';
echo 'Dossier cible : ' . htmlspecialchars($uploadDir) . '
';
echo 'Le dossier existe : ' . (is_dir($uploadDir) ? '? OUI' : '? NON') . '
';
echo 'Accessible en écriture : ' . (is_writable($uploadDir) ? '? OUI' : '? NON') . '
';
echo 'Fichiers récents dans images/resource/ :
';
if (is_dir($uploadDir)) {
$files = array_diff(scandir($uploadDir), ['.', '..']);
$files = array_slice(array_reverse($files), 0, 5);
foreach ($files as $f) {
$full = $uploadDir . $f;
echo ' • ' . htmlspecialchars($f) . ' (' . number_format(filesize($full)) . ' bytes)
';
}
}
echo '
}
/* ============================================================
2. AJAX (save / get / delete)
============================================================ */
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) {
header('Content-Type: application/json; charset=utf-8');
$response = ['success' => false, 'message' => ''];
try {
// Créer le dossier si inexistant
if (!is_dir($uploadDir)) @mkdir($uploadDir, 0755, true);
if ($_POST['action'] === 'save') {
$id = !empty($_POST['id']) ? (int)$_POST['id'] : null;
$titre = trim($_POST['titre'] ?? '');
$categorie = trim($_POST['categorie'] ?? '');
$cat2 = trim($_POST['cat2'] ?? '');
$devel = $_POST['devel'] ?? '';
$date_pub = $_POST['date_publication'] ?? date('Y-m-d');
$date_ev = !empty($_POST['date_evenement']) ? $_POST['date_evenement'] : null;
$existing_img = trim($_POST['existing_img'] ?? '');
$editeur = $_SESSION['email'] ?? ($_SESSION['username'] ?? 'admin');
if ($titre === '') throw new Exception('Le titre est obligatoire.');
if (trim(strip_tags($devel)) === '') throw new Exception('Le contenu est obligatoire.');
if ($date_pub === '') $date_pub = date('Y-m-d');
$img_filename = $existing_img ?: null;
if (isset($_FILES['img_main']) && $_FILES['img_main']['error'] === UPLOAD_ERR_OK) {
$ext = strtolower(pathinfo($_FILES['img_main']['name'], PATHINFO_EXTENSION));
if (!in_array($ext, ['jpg','jpeg','png','gif','webp'], true)) {
throw new Exception('Format image non autorisé.');
}
// Nom de fichier sécurisé (sans espaces)
$baseName = preg_replace('/[^a-zA-Z0-9]/', '_', pathinfo($_FILES['img_main']['name'], PATHINFO_FILENAME));
$newName = 'actu_' . substr($baseName, 0, 20) . '_' . uniqid() . '.' . $ext;
if (!move_uploaded_file($_FILES['img_main']['tmp_name'], $uploadDir . $newName)) {
throw new Exception("Échec de l'upload vers : " . $uploadDir . $newName);
}
// Supprimer l'ancienne image si elle existe
if ($existing_img && file_exists($uploadDir . $existing_img)) {
@unlink($uploadDir . $existing_img);
}
$img_filename = $newName;
}
$img_short = $img_filename;
if ($id) {
$sql = "UPDATE news_events SET img_short=?, img_main=?, categorie=?, titre=?, devel=?, cat2=?,
editeur=?, date_publication=?, date_evenement=? WHERE id=?";
$stmt = $bdd->prepare($sql);
$stmt->execute([$img_short, $img_filename, $categorie, $titre, $devel, $cat2,
$editeur, $date_pub, $date_ev, $id]);
$response = ['success' => true, 'message' => 'Article modifié.', 'id' => $id];
} else {
$sql = "INSERT INTO news_events
(img_short, img_main, categorie, titre, devel, cat2, editeur, date_publication, date_evenement)
VALUES (?,?,?,?,?,?,?,?,?)";
$stmt = $bdd->prepare($sql);
$stmt->execute([$img_short, $img_filename, $categorie, $titre, $devel, $cat2,
$editeur, $date_pub, $date_ev]);
$response = ['success' => true, 'message' => 'Article créé.', 'id' => $bdd->lastInsertId()];
}
}
elseif ($_POST['action'] === 'get') {
$id = (int)($_POST['id'] ?? 0);
if (!$id) throw new Exception('ID manquant.');
$stmt = $bdd->prepare("SELECT * FROM news_events WHERE id=?");
$stmt->execute([$id]);
$row = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$row) throw new Exception('Article introuvable.');
$row['devel'] = html_entity_decode($row['devel'] ?? '', ENT_QUOTES | ENT_HTML5, 'UTF-8');
$response = ['success' => true, 'article' => $row];
}
elseif ($_POST['action'] === 'delete') {
$id = (int)($_POST['id'] ?? 0);
if (!$id) throw new Exception('ID manquant.');
$stmt = $bdd->prepare("SELECT img_main FROM news_events WHERE id=?");
$stmt->execute([$id]);
$img = $stmt->fetchColumn();
if ($img && file_exists($uploadDir . $img)) @unlink($uploadDir . $img);
$stmt = $bdd->prepare("DELETE FROM news_events WHERE id=?");
$stmt->execute([$id]);
$response = ['success' => true, 'message' => 'Article supprimé.'];
}
else throw new Exception('Action inconnue.');
} catch (Exception $e) {
$response = ['success' => false, 'message' => $e->getMessage()];
}
echo json_encode($response);
exit;
}
/* ============================================================
3. LECTURE — liste allégée
============================================================ */
$articles = [];
try {
$stmt = $bdd->query("SELECT id, img_main, titre, categorie, cat2, editeur, date_publication, date_evenement
FROM news_events ORDER BY date_publication DESC, id DESC");
$articles = $stmt->fetchAll(PDO::FETCH_ASSOC);
} catch (Exception $e) { error_log('Fetch: ' . $e->getMessage()); }
$totalArticles = count($articles);
$categories = [];
try {
$stmt = $bdd->query("SELECT DISTINCT categorie FROM news_events WHERE categorie IS NOT NULL AND categorie != '' ORDER BY categorie");
$categories = $stmt->fetchAll(PDO::FETCH_COLUMN);
} catch (Exception $e) {}
include 'menu.php';
?>
#custom-loader { position: fixed; inset: 0; background: #3B211B; z-index: 99999; display: flex; align-items: center; justify-content: center; transition: opacity 0.4s ease; }
#custom-loader .spinner { width: 50px; height: 50px; border: 3px solid rgba(181,138,42,0.2); border-top-color: #B58A2A; border-radius: 50%; animation: spin 1s linear infinite; }
@keyframes spin { 100% { transform: rotate(360deg); } }
h1, h2, h3, h4, h5, h6, .card-title { font-family: 'Playfair Display', serif; }
/* ===== Navbar ===== */
.profile-pic { display: flex; align-items: center; gap: 12px; padding: 5px 10px; border-radius: 8px; transition: background .2s; text-decoration: none !important; }
.profile-pic:hover { background: rgba(181,138,42,.08); }
.profile-avatar { width: 42px; height: 42px; border-radius: 50%; object-fit: cover; border: 2px solid #B58A2A; }
.profile-info { display: flex; flex-direction: column; line-height: 1.2; }
.profile-info .greeting { font-size: 11px; color: #706861; text-transform: uppercase; letter-spacing: .5px; }
.profile-info .name { font-size: 15px; font-weight: 600; color: #3B211B; }
.dropdown-user { min-width: 280px; padding: 0; border-radius: 10px; overflow: hidden; box-shadow: 0 10px 30px rgba(0,0,0,.1); border: 1px solid #E5DFD6; }
.dropdown-user .user-box { background: #F8F7F4; padding: 20px; display: flex; align-items: center; border-bottom: 1px solid #E5DFD6; }
.dropdown-user .user-box img { width: 50px; height: 50px; border-radius: 50%; border: 2px solid #B58A2A; margin-right: 15px; }
.dropdown-user .user-box .u-text h4 { margin: 0; font-size: 16px; color: #3B211B; }
.dropdown-user .user-box .u-text p { margin: 0; font-size: 12px; color: #706861; }
.dropdown-user .dropdown-item { padding: 12px 20px; font-size: 14px; color: #29231F; display: flex; align-items: center; gap: 10px; }
.dropdown-user .dropdown-item i { color: #B58A2A; width: 20px; }
.dropdown-user .dropdown-item:hover { background: #F0EDE6; }
.nav-link-notif { width: 42px; height: 42px; display: flex; align-items: center; justify-content: center; border-radius: 50%; background: #F8F7F4; color: #3B211B; position: relative; margin-right: 15px; transition: all .2s; }
.nav-link-notif:hover { background: #F0EDE6; color: #B83232; }
.nav-link-notif .notification { position: absolute; top: -2px; right: -2px; background: #B83232; color: #fff; font-size: 10px; font-weight: bold; width: 18px; height: 18px; display: flex; align-items: center; justify-content: center; border-radius: 50%; border: 2px solid #fff; }
/* ============================================================
TABLEAU PRO
============================================================ */
.articles-card { border-radius: 14px; border: 1px solid #E5DFD6; box-shadow: 0 2px 12px rgba(59,33,27,.04); overflow: hidden; background: #fff; }
.articles-toolbar { padding: 18px 22px; border-bottom: 1px solid #EDE8DF; background: #fff; display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.articles-toolbar .toolbar-title { font-family: 'Playfair Display', serif; font-size: 17px; font-weight: 700; color: #3B211B; margin: 0; display: flex; align-items: center; gap: 10px; }
.articles-toolbar .toolbar-title .count-badge { background: #F5F0E6; color: #9A7320; font-size: 12px; font-weight: 600; padding: 3px 10px; border-radius: 20px; font-family: 'Public Sans', sans-serif; }
.articles-toolbar .toolbar-controls { margin-left: auto; display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.search-wrap { position: relative; display: inline-block; }
.search-wrap i.fa-search { position: absolute; left: 13px; top: 50%; transform: translateY(-50%); color: #9A9187; font-size: 13px; pointer-events: none; }
.search-wrap input { padding: 9px 14px 9px 38px; border: 1.5px solid #E5DFD6; border-radius: 10px; font-size: 13.5px; width: 260px; transition: all .2s; background: #FBF9F5; color: #29231F; }
.search-wrap input::placeholder { color: #B8AFA3; }
.search-wrap input:focus { outline: none; border-color: #B58A2A; background: #fff; box-shadow: 0 0 0 3px rgba(181,138,42,.08); }
.search-clear { position: absolute; right: 10px; top: 50%; transform: translateY(-50%); width: 22px; height: 22px; border-radius: 50%; border: none; background: #E5DFD6; color: #706861; display: none; align-items: center; justify-content: center; font-size: 10px; cursor: pointer; }
.search-clear:hover { background: #D9D0C2; }
.search-wrap.has-value .search-clear { display: flex; }
.filter-select { padding: 9px 32px 9px 14px; border: 1.5px solid #E5DFD6; border-radius: 10px; font-size: 13.5px; background: #FBF9F5 url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23706861' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e") no-repeat right 12px center; background-size: 12px; appearance: none; color: #29231F; cursor: pointer; transition: all .2s; min-width: 180px; }
.filter-select:focus { outline: none; border-color: #B58A2A; background-color: #fff; box-shadow: 0 0 0 3px rgba(181,138,42,.08); }
.articles-table { margin: 0; width: 100%; border-collapse: separate; border-spacing: 0; }
.articles-table thead th { background: #F8F7F4; color: #706861; font-weight: 600; text-transform: uppercase; font-size: 11px; letter-spacing: .6px; padding: 14px 18px; border-bottom: 1px solid #E5DFD6; text-align: left; white-space: nowrap; }
.articles-table thead th:last-child { text-align: right; }
.articles-table tbody tr { border-bottom: 1px solid #F0EDE6; transition: background .15s; }
.articles-table tbody tr:last-child { border-bottom: none; }
.articles-table tbody tr:hover { background: #FBF9F5; }
.articles-table tbody td { padding: 16px 18px; vertical-align: middle; border: none; color: #29231F; font-size: 14px; }
.article-thumb { width: 68px; height: 48px; object-fit: cover; border-radius: 8px; border: 1px solid #E5DFD6; display: block; background: #F0EDE6; }
.article-thumb-empty { width: 68px; height: 48px; border-radius: 8px; background: #F5F0E6; display: flex; align-items: center; justify-content: center; color: #B8AFA3; font-size: 16px; border: 1px solid #E5DFD6; }
.article-thumb-error { width: 68px; height: 48px; border-radius: 8px; background: #FBEDED; display: flex; align-items: center; justify-content: center; color: #B83232; font-size: 16px; border: 1px solid #F5D5D5; cursor: help; }
.article-title { font-weight: 600; color: #3B211B; font-size: 14.5px; line-height: 1.4; margin-bottom: 4px; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.article-editor { font-size: 12px; color: #9A9187; display: flex; align-items: center; gap: 5px; }
.article-editor i { font-size: 10px; color: #B58A2A; }
.cat-badge { display: inline-block; padding: 4px 11px; border-radius: 20px; font-size: 11.5px; font-weight: 600; background: #F5F0E6; color: #9A7320; border: 1px solid #EDE3D3; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.date-cell { color: #706861; font-size: 13px; display: flex; align-items: center; gap: 6px; }
.date-cell i { color: #B58A2A; font-size: 11px; }
.actions-group { display: flex; justify-content: flex-end; gap: 4px; }
.btn-action { width: 34px; height: 34px; padding: 0; display: inline-flex; align-items: center; justify-content: center; border-radius: 8px; border: 1.5px solid #E5DFD6; background: #fff; color: #706861; transition: all .18s; }
.btn-action:hover { transform: translateY(-1px); }
.btn-action.view:hover { color: #2E7D9E; border-color: #2E7D9E; background: #EAF4F9; }
.btn-action.edit:hover { color: #B58A2A; border-color: #B58A2A; background: #FBF6EB; }
.btn-action.delete:hover { color: #B83232; border-color: #B83232; background: #FBEDED; }
.empty-state { padding: 60px 20px; text-align: center; color: #9A9187; }
.empty-state .empty-icon { width: 70px; height: 70px; border-radius: 50%; background: #F5F0E6; display: inline-flex; align-items: center; justify-content: center; color: #B58A2A; font-size: 26px; margin-bottom: 16px; }
.empty-state strong { display: block; color: #3B211B; font-size: 15px; margin-bottom: 6px; }
.empty-state p { margin: 0; font-size: 13px; }
.articles-footer { padding: 16px 22px; border-top: 1px solid #EDE8DF; background: #FBF9F5; display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.pagination-info { font-size: 13px; color: #706861; }
.pagination-info strong { color: #3B211B; }
.per-page-wrap { display: flex; align-items: center; gap: 8px; font-size: 13px; color: #706861; }
.per-page-wrap select { padding: 6px 26px 6px 10px; border: 1.5px solid #E5DFD6; border-radius: 8px; font-size: 12.5px; background: #fff url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23706861' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e") no-repeat right 8px center; background-size: 10px; appearance: none; color: #29231F; cursor: pointer; }
.pagination-nav { display: flex; gap: 4px; }
.pagination-nav .page-btn { min-width: 34px; height: 34px; padding: 0 10px; display: inline-flex; align-items: center; justify-content: center; border-radius: 8px; border: 1.5px solid #E5DFD6; background: #fff; color: #706861; font-size: 13px; font-weight: 600; cursor: pointer; transition: all .15s; text-decoration: none; }
.pagination-nav .page-btn:hover:not(.disabled):not(.active) { border-color: #B58A2A; color: #B58A2A; background: #FBF6EB; }
.pagination-nav .page-btn.active { background: #B58A2A; color: #fff; border-color: #B58A2A; }
.pagination-nav .page-btn.disabled { opacity: .4; cursor: not-allowed; }
.pagination-nav .page-ellipsis { min-width: 34px; height: 34px; display: inline-flex; align-items: center; justify-content: center; color: #9A9187; font-size: 13px; }
/* ============================================================
STRUCTURE MODALES
============================================================ */
#articleModal .modal-dialog,
#detailsModal .modal-dialog { margin: .5rem auto; max-width: calc(100% - 1rem); width: 100%; display: flex; align-items: center; min-height: calc(100% - 1rem); }
.article-modal, .details-modal { border: none; border-radius: 18px; overflow: hidden; box-shadow: 0 24px 60px rgba(0,0,0,.22); display: flex; flex-direction: column; max-height: calc(100vh - 1rem); max-height: calc(100dvh - 1rem); width: 100%; }
.article-modal form { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; overflow: hidden; }
.article-modal-header { flex: 0 0 auto; background: #3B211B; padding: clamp(14px, 2.5vw, 24px) clamp(16px, 3vw, 30px); display: flex; align-items: center; gap: clamp(10px, 2vw, 16px); position: relative; }
.header-icon { width: clamp(38px, 5vw, 50px); height: clamp(38px, 5vw, 50px); border-radius: 12px; background: #B58A2A; display: flex; align-items: center; justify-content: center; color: #fff; font-size: clamp(16px, 2.5vw, 20px); flex-shrink: 0; }
.article-modal-header > div:not(.header-icon) { flex: 1; min-width: 0; }
.article-modal-header h4 { color: #fff; font-family: 'Playfair Display', serif; font-size: clamp(16px, 2.5vw, 21px); font-weight: 700; margin: 0; line-height: 1.2; }
.article-modal-header p { color: rgba(255,255,255,.7); font-size: clamp(11px, 1.5vw, 13px); margin: 4px 0 0; }
.btn-close-custom { width: 40px; height: 40px; border-radius: 50%; background: rgba(255,255,255,.12); border: 1px solid rgba(255,255,255,.2); color: #fff; display: flex; align-items: center; justify-content: center; transition: all .2s; flex-shrink: 0; }
.btn-close-custom:hover { background: #B83232; border-color: #B83232; }
.article-modal-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; overflow-x: hidden; background: #FBF9F5; -webkit-overflow-scrolling: touch; overscroll-behavior: contain; }
.article-modal-body::-webkit-scrollbar, .details-body::-webkit-scrollbar { width: 8px; }
.article-modal-body::-webkit-scrollbar-track, .details-body::-webkit-scrollbar-track { background: #F5F0E6; }
.article-modal-body::-webkit-scrollbar-thumb, .details-body::-webkit-scrollbar-thumb { background: #D9D0C2; border-radius: 4px; }
.article-modal-body::-webkit-scrollbar-thumb:hover, .details-body::-webkit-scrollbar-thumb:hover { background: #B58A2A; }
.form-section { padding: clamp(16px, 3vw, 24px) clamp(16px, 3vw, 30px); border-bottom: 1px solid #EDE8DF; background: #fff; }
.form-section:last-child { border-bottom: none; }
.form-section:nth-child(even) { background: #FBF9F5; }
.section-header { display: flex; align-items: flex-start; gap: 12px; margin-bottom: 16px; }
.section-icon { width: 36px; height: 36px; border-radius: 10px; background: #F5F0E6; display: flex; align-items: center; justify-content: center; color: #B58A2A; font-size: 14px; flex-shrink: 0; border: 1px solid #EDE3D3; }
.section-title { font-size: 14.5px; font-weight: 700; color: #3B211B; margin: 0; font-family: 'Public Sans', sans-serif; }
.section-subtitle { font-size: 12px; color: #9A9187; margin: 2px 0 0; }
.article-modal .form-label { font-size: 13px; font-weight: 600; color: #3B211B; margin-bottom: 6px; }
.article-modal .form-control { border-radius: 10px; border: 1.5px solid #E5DFD6; padding: 10px 14px; font-size: 14px; transition: all .2s; background: #fff; }
.article-modal .form-control:focus { border-color: #B58A2A; box-shadow: 0 0 0 3px rgba(181,138,42,.1); }
.article-modal .form-control-lg { padding: 12px 15px; font-size: 15px; font-weight: 500; }
.image-upload-area { position: relative; border: 2px dashed #D9D0C2; border-radius: 12px; padding: clamp(20px, 3vw, 30px) 20px; text-align: center; cursor: pointer; transition: all .25s; background: #FAFAF7; min-height: 150px; display: flex; align-items: center; justify-content: center; overflow: hidden; }
.image-upload-area:hover, .image-upload-area.dragover { border-color: #B58A2A; background: #FBF6EB; }
.image-upload-area i.upload-icon { font-size: clamp(30px, 4vw, 40px); color: #B58A2A; margin-bottom: 10px; display: block; }
.image-upload-area strong { display: block; color: #3B211B; font-size: 14px; margin-bottom: 4px; }
.image-upload-area p { margin: 0; color: #9A9187; font-size: 12px; }
.image-upload-area #img-preview { max-height: 200px; max-width: 100%; border-radius: 8px; }
.btn-remove-img { position: absolute; top: 10px; right: 10px; width: 30px; height: 30px; border-radius: 50%; background: #B83232; color: #fff; border: none; display: flex; align-items: center; justify-content: center; z-index: 2; transition: all .2s; }
.btn-remove-img:hover { background: #9A1F1F; }
#editor-container { height: clamp(200px, 32vh, 300px); background: #fff; border-radius: 0 0 10px 10px; }
.ql-toolbar.ql-snow { border-color: #E5DFD6 !important; border-radius: 10px 10px 0 0; background: #F8F7F4; padding: 10px 14px; }
.ql-container.ql-snow { border-color: #E5DFD6 !important; font-family: 'Public Sans', sans-serif; font-size: 14px; border-radius: 0 0 10px 10px; }
.ql-editor { padding: 16px 18px; line-height: 1.7; }
.ql-editor.ql-blank::before { color: #B8AFA3; font-style: normal; }
.editor-footer { display: flex; justify-content: space-between; align-items: center; margin-top: 10px; padding: 0 4px; flex-wrap: wrap; gap: 6px; }
.char-counter { font-size: 11px; color: #9A9187; font-weight: 500; }
.char-counter.warn { color: #D97706; }
.char-counter.danger { color: #B83232; }
.article-modal-footer { flex: 0 0 auto; padding: clamp(12px, 2.5vw, 18px) clamp(16px, 3vw, 30px); background: #fff; border-top: 1px solid #EDE8DF; display: flex; justify-content: space-between; align-items: center; gap: 10px; }
.btn-premium { background: #B58A2A; border: none; border-radius: 10px; padding: 10px 24px; font-weight: 600; font-size: 14px; color: #fff; transition: all .2s; }
.btn-premium:hover { background: #9A7320; color: #fff; }
.btn-premium:disabled { opacity: .6; }
.article-modal-footer .btn-light { background: #F5F0E6; border: 1px solid #E5DFD6; border-radius: 10px; padding: 10px 24px; font-weight: 600; font-size: 14px; color: #3B211B; }
.article-modal-footer .btn-light:hover { background: #EDE8DF; }
.details-hero { flex: 0 0 auto; position: relative; min-height: clamp(200px, 28vh, 320px); background: #3B211B; background-size: cover; background-position: center; display: flex; align-items: flex-end; }
.details-hero.has-image::before { content: ''; position: absolute; inset: 0; background: rgba(42,24,16,.75); }
.hero-close { position: absolute; top: 16px; right: 16px; width: 40px; height: 40px; border-radius: 50%; background: rgba(0,0,0,.45); border: 1px solid rgba(255,255,255,.25); color: #fff; display: flex; align-items: center; justify-content: center; transition: all .2s; z-index: 3; }
.hero-close:hover { background: #B83232; border-color: #B83232; }
.hero-content { position: relative; z-index: 2; padding: clamp(20px, 3vw, 36px) clamp(16px, 3vw, 36px) clamp(16px, 2.5vw, 28px); width: 100%; }
.hero-category { display: inline-block; background: #B58A2A; color: #fff; padding: 5px 14px; border-radius: 20px; font-size: 11px; text-transform: uppercase; letter-spacing: 1.2px; font-weight: 700; margin-bottom: 12px; }
.hero-title { font-family: 'Playfair Display', serif; font-size: clamp(20px, 3vw, 30px); font-weight: 700; line-height: 1.25; color: #fff; margin: 0 0 14px; }
.hero-meta { display: flex; flex-wrap: wrap; gap: clamp(10px, 2vw, 22px); font-size: clamp(12px, 1.5vw, 13px); color: rgba(255,255,255,.85); }
.hero-meta span { display: flex; align-items: center; gap: 8px; }
.hero-meta i { color: #D4B45F; font-size: 14px; }
.details-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; overflow-x: hidden; background: #fff; -webkit-overflow-scrolling: touch; overscroll-behavior: contain; }
.details-content { padding: clamp(20px, 3vw, 36px) clamp(16px, 3vw, 36px); font-family: 'Public Sans', sans-serif; font-size: clamp(14px, 1.6vw, 15px); line-height: 1.75; color: #29231F; }
.details-content p { margin-bottom: 18px; }
.details-content h1, .details-content h2, .details-content h3, .details-content h4 { font-family: 'Playfair Display', serif; color: #3B211B; margin: 28px 0 16px; }
.details-content img { max-width: 100%; height: auto; border-radius: 10px; margin: 18px 0; }
.details-content blockquote { border-left: 4px solid #B58A2A; padding: 12px 20px; background: #FBF9F5; border-radius: 0 8px 8px 0; margin: 18px 0; font-style: italic; color: #706861; }
.details-content a { color: #B58A2A; text-decoration: underline; }
.details-content ul, .details-content ol { padding-left: 24px; margin-bottom: 18px; }
.details-footer { flex: 0 0 auto; padding: clamp(12px, 2.5vw, 18px) clamp(16px, 3vw, 36px); background: #FBF9F5; border-top: 1px solid #EDE8DF; display: flex; justify-content: space-between; align-items: center; gap: 10px; }
@media (min-width: 768px) {
#articleModal .modal-dialog, #detailsModal .modal-dialog { margin: 1.75rem auto; max-width: 90vw; min-height: calc(100% - 3.5rem); }
.article-modal, .details-modal { max-height: calc(100vh - 3.5rem); max-height: calc(100dvh - 3.5rem); }
.articles-toolbar { padding: 18px 24px; }
.articles-table thead th { padding: 14px 22px; }
.articles-table tbody td { padding: 16px 22px; }
}
@media (min-width: 1200px) {
#articleModal .modal-dialog, #detailsModal .modal-dialog { max-width: 1100px; }
}
@media (max-width: 767px) {
.articles-toolbar { flex-direction: column; align-items: stretch; }
.articles-toolbar .toolbar-controls { margin-left: 0; }
.search-wrap, .search-wrap input, .filter-select { width: 100%; min-width: 0; }
.articles-footer { flex-direction: column; align-items: stretch; text-align: center; }
.pagination-nav { justify-content: center; }
}
@media (max-width: 575px) {
#articleModal .modal-dialog, #detailsModal .modal-dialog { margin: 0; max-width: 100%; min-height: 100%; }
.article-modal, .details-modal { border-radius: 0; max-height: 100vh; max-height: 100dvh; height: 100vh; height: 100dvh; }
.article-modal-header { padding: 14px 16px; }
.article-modal-header p { display: none; }
.article-modal-header h4 { font-size: 16px; }
.header-icon { width: 38px; height: 38px; font-size: 16px; border-radius: 10px; }
.btn-close-custom { width: 36px; height: 36px; }
.form-section { padding: 16px; }
.section-header { gap: 10px; margin-bottom: 12px; }
.section-icon { width: 32px; height: 32px; font-size: 13px; }
.section-title { font-size: 14px; }
.image-upload-area { padding: 20px 14px; min-height: 130px; }
#editor-container { height: 200px; }
.ql-toolbar.ql-snow { padding: 6px 8px; }
.ql-editor { padding: 12px 14px; }
.article-modal-footer { padding: 12px 16px; flex-direction: column; gap: 8px; }
.article-modal-footer > small { display: none; }
.article-modal-footer .d-flex { width: 100%; }
.article-modal-footer .btn { flex: 1; padding: 10px 12px; font-size: 14px; }
.details-hero { min-height: 200px; }
.hero-content { padding: 16px; }
.hero-title { font-size: 19px; }
.details-content { padding: 20px 16px; }
.details-footer { padding: 12px 16px; flex-direction: column; gap: 8px; }
.details-footer > small { display: none; }
.details-footer .d-flex { width: 100%; }
.details-footer .btn { flex: 1; padding: 10px 12px; font-size: 14px; }
}
Actualités & Événements
Gérez les articles publiés sur le site.
Nouvel Article
| Image | Titre de l'article | Catégorie | Date | Actions |
|---|---|---|---|---|
Aucun article pour le moment Cliquez sur « Nouvel Article » pour commencer. | ||||
class="article-thumb" alt="" loading="lazy" onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';">
|
= htmlspecialchars(safeSubstr($title, 0, 100)) ?>
= htmlspecialchars($row['editeur'] ?: 'Admin ACE') ?>
| = htmlspecialchars($row['categorie'] ?: '—') ?> |
= !empty($row['date_publication']) ? date('d/m/Y', strtotime($row['date_publication'])) : '—' ?>
|
|