admin.css: replace .admin-main, .admin-page-title, .admin-table, .admin-fieldset with semantic selectors

Replace four presentational class names in admin.css with structural selectors
that target native HTML elements already present in every admin template:

  .admin-main           → .admin-body main
  .admin-page-title     → .admin-body main > h1
  .admin-table          → .admin-body table
  .admin-fieldset       → .admin-body fieldset
  .admin-fieldset-legend → .admin-body legend

Also migrate the .admin-main > section / h2 / dl / dt / dd block to
.admin-body main > section so the thanks-page section styles survive.

Add .admin-body main > table { margin-top: 1.5rem } to absorb the inline
style="margin-top:1.5rem" that was on tags.php's <table class="admin-table">.

All 10 affected admin templates updated (add, edit, account, index, import,
pages, pages-edit, tags, system, thanks) — class attributes removed where
the element alone is now the selector.  Zero visual changes.
This commit is contained in:
Pontoporeia
2026-04-02 12:16:59 +02:00
parent cb1ced535b
commit 0ab08f3aa0
12 changed files with 52 additions and 47 deletions

View File

@@ -3,15 +3,15 @@
## Template Simplification — Remove Custom Classes Where Semantic HTML Suffices ## Template Simplification — Remove Custom Classes Where Semantic HTML Suffices
### CSS class audit: replace with semantic selectors ### CSS class audit: replace with semantic selectors
- [ ] **`admin.css`**: Replace `.admin-main` with `.admin-body main` — only one `<main>` per page - [x] **`admin.css`**: Replace `.admin-main` with `.admin-body main` — only one `<main>` per page
- [ ] **`admin.css`**: Replace `.admin-page-title` with `.admin-body main > h1` — always the first `h1` in `<main>` - [x] **`admin.css`**: Replace `.admin-page-title` with `.admin-body main > h1` — always the first `h1` in `<main>`
- [ ] **`admin.css`**: Replace `.admin-alert` / `.admin-alert--error` / `.admin-alert--success` with `[role="alert"]` or `.admin-body main > .alert` using `data-type="error|success"` attribute instead of modifier classes - [ ] **`admin.css`**: Replace `.admin-alert` / `.admin-alert--error` / `.admin-alert--success` with `[role="alert"]` or `.admin-body main > .alert` using `data-type="error|success"` attribute instead of modifier classes
- [ ] **`admin.css`**: Replace `.admin-form-row` with `.admin-body form > div` or `.admin-body form > .row` — form rows are always direct `<div>` children of `<form>` - [ ] **`admin.css`**: Replace `.admin-form-row` with `.admin-body form > div` or `.admin-body form > .row` — form rows are always direct `<div>` children of `<form>`
- [ ] **`admin.css`**: Replace `.admin-label` with `.admin-body form label` — every label in admin forms - [ ] **`admin.css`**: Replace `.admin-label` with `.admin-body form label` — every label in admin forms
- [ ] **`admin.css`**: Replace `.admin-input` / `.admin-select` / `.admin-textarea` with `.admin-body form input[type="text"]`, `.admin-body form select`, `.admin-body form textarea` — leverage native element selectors - [ ] **`admin.css`**: Replace `.admin-input` / `.admin-select` / `.admin-textarea` with `.admin-body form input[type="text"]`, `.admin-body form select`, `.admin-body form textarea` — leverage native element selectors
- [x] **`admin.css`**: Replace `.admin-hint` with `.admin-body form small` — use `<small>` instead of `<p class="admin-hint">` - [x] **`admin.css`**: Replace `.admin-hint` with `.admin-body form small` — use `<small>` instead of `<p class="admin-hint">`
- [ ] **`admin.css`**: Replace `.admin-table` with `.admin-body table` — only one table per admin page - [x] **`admin.css`**: Replace `.admin-table` with `.admin-body table` — only one table per admin page
- [ ] **`admin.css`**: Replace `.admin-fieldset` / `.admin-fieldset-legend` with `.admin-body fieldset` / `.admin-body legend` - [x] **`admin.css`**: Replace `.admin-fieldset` / `.admin-fieldset-legend` with `.admin-body fieldset` / `.admin-body legend`
- [x] **`main.css`**: Replace `.card__caption` with `.home-body .cards-container li p` or target `li > a > p` directly - [x] **`main.css`**: Replace `.card__caption` with `.home-body .cards-container li p` or target `li > a > p` directly
- [x] **`main.css`**: Replace `.card__media` with `.home-body figure` — already uses `<figure>` elements - [x] **`main.css`**: Replace `.card__media` with `.home-body figure` — already uses `<figure>` elements
- [x] **`tfe.css`**: Replace `.tfe-meta-list` selectors with `article dl`, `article dt`, `article dd` — already using `<dl>` inside `<article>` - [x] **`tfe.css`**: Replace `.tfe-meta-list` selectors with `article dl`, `article dt`, `article dd` — already using `<dl>` inside `<article>`

View File

@@ -19,8 +19,8 @@ if (empty($_SESSION['csrf_token'])) {
<?php $isAdmin = true; $bodyClass = 'admin-body'; require_once APP_ROOT . '/templates/head.php'; ?> <?php $isAdmin = true; $bodyClass = 'admin-body'; require_once APP_ROOT . '/templates/head.php'; ?>
<?php include APP_ROOT . '/templates/header.php'; ?> <?php include APP_ROOT . '/templates/header.php'; ?>
<main class="admin-main" id="main-content"> <main id="main-content">
<h1 class="admin-page-title">Compte administrateur</h1> <h1>Compte administrateur</h1>
<?php if ($error): ?> <?php if ($error): ?>
<div class="admin-alert admin-alert--error">⚠ <?= htmlspecialchars($error) ?></div> <div class="admin-alert admin-alert--error">⚠ <?= htmlspecialchars($error) ?></div>

View File

@@ -42,8 +42,8 @@ function wasSelected($key, $value) {
<?php $isAdmin = true; $bodyClass = 'admin-body'; require_once APP_ROOT . '/templates/head.php'; ?> <?php $isAdmin = true; $bodyClass = 'admin-body'; require_once APP_ROOT . '/templates/head.php'; ?>
<?php include APP_ROOT . '/templates/header.php'; ?> <?php include APP_ROOT . '/templates/header.php'; ?>
<main class="admin-main" id="main-content"> <main id="main-content">
<h1 class="admin-page-title">Ajouter un TFE</h1> <h1>Ajouter un TFE</h1>
<?php if ($error): ?> <?php if ($error): ?>
<div class="admin-alert admin-alert--error">⚠ <?= htmlspecialchars($error) ?></div> <div class="admin-alert admin-alert--error">⚠ <?= htmlspecialchars($error) ?></div>
@@ -81,8 +81,8 @@ function wasSelected($key, $value) {
</div> </div>
<!-- Composition du jury --> <!-- Composition du jury -->
<fieldset class="admin-fieldset"> <fieldset>
<legend class="admin-fieldset-legend">Composition du jury</legend> <legend>Composition du jury</legend>
<!-- Président·e --> <!-- Président·e -->
<div class="admin-form-row"> <div class="admin-form-row">

View File

@@ -64,8 +64,8 @@ try {
<?php $isAdmin = true; $bodyClass = 'admin-body'; require_once APP_ROOT . '/templates/head.php'; ?> <?php $isAdmin = true; $bodyClass = 'admin-body'; require_once APP_ROOT . '/templates/head.php'; ?>
<?php include APP_ROOT . '/templates/header.php'; ?> <?php include APP_ROOT . '/templates/header.php'; ?>
<main class="admin-main" id="main-content"> <main id="main-content">
<h1 class="admin-page-title">Modifier un TFE</h1> <h1>Modifier un TFE</h1>
<?php if ($error): ?> <?php if ($error): ?>
<div class="admin-alert admin-alert--error">⚠ <?= htmlspecialchars($error) ?></div> <div class="admin-alert admin-alert--error">⚠ <?= htmlspecialchars($error) ?></div>
@@ -148,8 +148,8 @@ try {
} }
} }
?> ?>
<fieldset class="admin-fieldset"> <fieldset>
<legend class="admin-fieldset-legend">Composition du jury</legend> <legend>Composition du jury</legend>
<div class="admin-form-row"> <div class="admin-form-row">
<label class="admin-label" for="jury_president">Président·e :</label> <label class="admin-label" for="jury_president">Président·e :</label>

View File

@@ -320,8 +320,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['csv_file'])) {
<?php $isAdmin = true; $bodyClass = 'admin-body'; require_once APP_ROOT . '/templates/head.php'; ?> <?php $isAdmin = true; $bodyClass = 'admin-body'; require_once APP_ROOT . '/templates/head.php'; ?>
<?php include APP_ROOT . '/templates/header.php'; ?> <?php include APP_ROOT . '/templates/header.php'; ?>
<main class="admin-main" id="main-content"> <main id="main-content">
<h1 class="admin-page-title">Importer une liste de TFE</h1> <h1>Importer une liste de TFE</h1>
<?php if (!empty($errors)): ?> <?php if (!empty($errors)): ?>
<div class="admin-alert admin-alert--error"> <div class="admin-alert admin-alert--error">

View File

@@ -64,8 +64,8 @@ document.addEventListener('DOMContentLoaded', () => {
}); });
</script> </script>
<main class="admin-main" id="main-content"> <main id="main-content">
<h1 class="admin-page-title">Liste des TFE</h1> <h1>Liste des TFE</h1>
<?php if (isset($_SESSION['error'])): ?> <?php if (isset($_SESSION['error'])): ?>
<div class="admin-alert admin-alert--error">⚠ <?= htmlspecialchars($_SESSION['error']); unset($_SESSION['error']); ?></div> <div class="admin-alert admin-alert--error">⚠ <?= htmlspecialchars($_SESSION['error']); unset($_SESSION['error']); ?></div>
@@ -157,7 +157,7 @@ document.addEventListener('DOMContentLoaded', () => {
<?php if (empty($theses)): ?> <?php if (empty($theses)): ?>
<p style="color:var(--admin-text-muted);padding:1rem 0;">Aucun TFE trouvé.</p> <p style="color:var(--admin-text-muted);padding:1rem 0;">Aucun TFE trouvé.</p>
<?php else: ?> <?php else: ?>
<table class="admin-table"> <table>
<thead> <thead>
<tr> <tr>
<th scope="col"><input type="checkbox" onchange="toggleAll(this)"></th> <th scope="col"><input type="checkbox" onchange="toggleAll(this)"></th>

View File

@@ -81,8 +81,8 @@ JS;
<?php $isAdmin = true; $bodyClass = 'admin-body'; require_once APP_ROOT . '/templates/head.php'; ?> <?php $isAdmin = true; $bodyClass = 'admin-body'; require_once APP_ROOT . '/templates/head.php'; ?>
<?php include APP_ROOT . '/templates/header.php'; ?> <?php include APP_ROOT . '/templates/header.php'; ?>
<main class="admin-main" id="main-content"> <main id="main-content">
<h1 class="admin-page-title">Éditer : <?= htmlspecialchars($page['title']) ?></h1> <h1>Éditer : <?= htmlspecialchars($page['title']) ?></h1>
<form action="/admin/actions/page.php" method="post" class="admin-form"> <form action="/admin/actions/page.php" method="post" class="admin-form">
<input type="hidden" name="csrf_token" value="<?= htmlspecialchars($_SESSION['csrf_token']) ?>"> <input type="hidden" name="csrf_token" value="<?= htmlspecialchars($_SESSION['csrf_token']) ?>">

View File

@@ -21,14 +21,14 @@ unset($_SESSION['success']);
<?php $isAdmin = true; $bodyClass = 'admin-body'; require_once APP_ROOT . '/templates/head.php'; ?> <?php $isAdmin = true; $bodyClass = 'admin-body'; require_once APP_ROOT . '/templates/head.php'; ?>
<?php include APP_ROOT . '/templates/header.php'; ?> <?php include APP_ROOT . '/templates/header.php'; ?>
<main class="admin-main" id="main-content"> <main id="main-content">
<h1 class="admin-page-title">Pages statiques</h1> <h1>Pages statiques</h1>
<?php if ($success): ?> <?php if ($success): ?>
<div class="admin-alert admin-alert--success">✓ <?= htmlspecialchars($success) ?></div> <div class="admin-alert admin-alert--success">✓ <?= htmlspecialchars($success) ?></div>
<?php endif; ?> <?php endif; ?>
<table class="admin-table"> <table>
<thead> <thead>
<tr> <tr>
<th scope="col">Slug</th> <th scope="col">Slug</th>

View File

@@ -372,8 +372,8 @@ require_once APP_ROOT . '/templates/head.php';
<main class="admin-main" id="main-content"> <main id="main-content">
<h1 class="admin-page-title">Système</h1> <h1>Système</h1>
<p class="sys-refresh-note"> <p class="sys-refresh-note">
Affiché le <?= date('d/m/Y à H:i:s') ?> — Affiché le <?= date('d/m/Y à H:i:s') ?> —

View File

@@ -25,8 +25,8 @@ unset($_SESSION['admin_error'], $_SESSION['admin_success']);
<?php $isAdmin = true; $bodyClass = 'admin-body'; require_once APP_ROOT . '/templates/head.php'; ?> <?php $isAdmin = true; $bodyClass = 'admin-body'; require_once APP_ROOT . '/templates/head.php'; ?>
<?php include APP_ROOT . '/templates/header.php'; ?> <?php include APP_ROOT . '/templates/header.php'; ?>
<main class="admin-main" id="main-content"> <main id="main-content">
<h1 class="admin-page-title">Mots-clés (<?= count($tags) ?>)</h1> <h1>Mots-clés (<?= count($tags) ?>)</h1>
<?php if ($error): ?> <?php if ($error): ?>
<div class="admin-alert admin-alert--error">⚠ <?= htmlspecialchars($error) ?></div> <div class="admin-alert admin-alert--error">⚠ <?= htmlspecialchars($error) ?></div>
@@ -35,7 +35,7 @@ unset($_SESSION['admin_error'], $_SESSION['admin_success']);
<div class="admin-alert admin-alert--success">✓ <?= htmlspecialchars($success) ?></div> <div class="admin-alert admin-alert--success">✓ <?= htmlspecialchars($success) ?></div>
<?php endif; ?> <?php endif; ?>
<table class="admin-table" style="margin-top:1.5rem;"> <table>
<thead> <thead>
<tr> <tr>
<th scope="col" style="width:40%;">Nom</th> <th scope="col" style="width:40%;">Nom</th>

View File

@@ -65,8 +65,8 @@ $pageTitle = "Récapitulatif TFE";
<?php $isAdmin = true; $bodyClass = 'admin-body'; require_once APP_ROOT . '/templates/head.php'; ?> <?php $isAdmin = true; $bodyClass = 'admin-body'; require_once APP_ROOT . '/templates/head.php'; ?>
<?php include APP_ROOT . '/templates/header.php'; ?> <?php include APP_ROOT . '/templates/header.php'; ?>
<main class="admin-main" id="main-content"> <main id="main-content">
<h1 class="admin-page-title">Récapitulatif TFE</h1> <h1>Récapitulatif TFE</h1>
<?php if ($error): ?> <?php if ($error): ?>
<div class="admin-alert admin-alert--error">⚠ <?= htmlspecialchars($error) ?></div> <div class="admin-alert admin-alert--error">⚠ <?= htmlspecialchars($error) ?></div>
@@ -122,7 +122,7 @@ $pageTitle = "Récapitulatif TFE";
<?php if (!empty($files)): ?> <?php if (!empty($files)): ?>
<section> <section>
<h2>Fichiers</h2> <h2>Fichiers</h2>
<table class="admin-table"> <table>
<thead><tr><th scope="col">Type</th><th scope="col">Fichier</th><th scope="col">Taille</th><th scope="col">Date</th></tr></thead> <thead><tr><th scope="col">Type</th><th scope="col">Fichier</th><th scope="col">Taille</th><th scope="col">Date</th></tr></thead>
<tbody> <tbody>
<?php foreach ($files as $f): ?> <?php foreach ($files as $f): ?>

View File

@@ -87,14 +87,14 @@
} }
/* Main content area */ /* Main content area */
.admin-main { .admin-body main {
flex: 1; flex: 1;
padding: 2.5rem 2rem 4rem; padding: 2.5rem 2rem 4rem;
max-width: 1100px; max-width: 1100px;
width: 100%; width: 100%;
} }
.admin-page-title { .admin-body main > h1 {
font-size: 1.8rem; font-size: 1.8rem;
font-weight: 600; font-weight: 600;
letter-spacing: 0.08em; letter-spacing: 0.08em;
@@ -375,13 +375,18 @@
} }
/* ---- Table ---- */ /* ---- Table ---- */
.admin-table { .admin-body table {
width: 100%; width: 100%;
border-collapse: collapse; border-collapse: collapse;
font-size: 0.88rem; font-size: 0.88rem;
} }
.admin-table th { /* margin-top for the tags table (only table not immediately after stats/filters) */
.admin-body main > table {
margin-top: 1.5rem;
}
.admin-body table th {
text-align: left; text-align: left;
font-size: 0.75rem; font-size: 0.75rem;
letter-spacing: 0.08em; letter-spacing: 0.08em;
@@ -393,23 +398,23 @@
white-space: nowrap; white-space: nowrap;
} }
.admin-table td { .admin-body table td {
padding: 0.65rem 0.75rem; padding: 0.65rem 0.75rem;
border-bottom: 1px solid var(--admin-border); border-bottom: 1px solid var(--admin-border);
color: var(--admin-text); color: var(--admin-text);
vertical-align: top; vertical-align: top;
} }
.admin-table tr:hover td { .admin-body table tr:hover td {
background: var(--admin-bg-alt); background: var(--admin-bg-alt);
} }
.admin-table .thesis-title { .admin-body table .thesis-title {
font-weight: 500; font-weight: 500;
color: var(--admin-text); color: var(--admin-text);
} }
.admin-table .thesis-subtitle { .admin-body table .thesis-subtitle {
font-size: 0.82rem; font-size: 0.82rem;
color: var(--admin-text-muted); color: var(--admin-text-muted);
font-style: italic; font-style: italic;
@@ -521,33 +526,33 @@
} }
/* Thesis info sections (thanks page) */ /* Thesis info sections (thanks page) */
.admin-main > section { .admin-body main > section {
border: 1px solid var(--admin-border); border: 1px solid var(--admin-border);
border-radius: 6px; border-radius: 6px;
padding: 1.5rem; padding: 1.5rem;
margin-bottom: 1.5rem; margin-bottom: 1.5rem;
} }
.admin-main > section h2 { .admin-body main > section h2 {
margin: 0 0 1rem; margin: 0 0 1rem;
font-size: 1.2rem; font-size: 1.2rem;
border-bottom: 1px solid var(--admin-border); border-bottom: 1px solid var(--admin-border);
padding-bottom: 0.5rem; padding-bottom: 0.5rem;
} }
.admin-main > section dl { .admin-body main > section dl {
display: grid; display: grid;
grid-template-columns: 180px 1fr; grid-template-columns: 180px 1fr;
gap: 0.4rem 1rem; gap: 0.4rem 1rem;
} }
.admin-main > section dt { .admin-body main > section dt {
font-weight: 600; font-weight: 600;
font-size: 0.88rem; font-size: 0.88rem;
color: var(--admin-text-muted); color: var(--admin-text-muted);
} }
.admin-main > section dd { .admin-body main > section dd {
margin: 0; margin: 0;
font-size: 0.9rem; font-size: 0.9rem;
} }
@@ -622,7 +627,7 @@
} }
/* Jury fieldset */ /* Jury fieldset */
.admin-fieldset { .admin-body fieldset {
border: 1px solid #333; border: 1px solid #333;
border-radius: 4px; border-radius: 4px;
padding: 1rem 1.25rem; padding: 1rem 1.25rem;
@@ -630,7 +635,7 @@
background: rgba(255, 255, 255, 0.02); background: rgba(255, 255, 255, 0.02);
} }
.admin-fieldset-legend { .admin-body legend {
font-size: 0.82rem; font-size: 0.82rem;
font-weight: 600; font-weight: 600;
letter-spacing: 0.04em; letter-spacing: 0.04em;