page projet.php
All checks were successful
Deploy / Build and Deploy to Production (push) Successful in 22s

This commit is contained in:
sarahgarcin1 2026-02-26 09:11:39 +01:00
parent 95efcac454
commit 99a924010f
5 changed files with 552 additions and 53 deletions

View file

@ -0,0 +1,366 @@
/*
projet.css
Grille des récits template projet.php
Ce fichier utilise UNIQUEMENT les variables définies dans
style.css --color-*, --sans-serif, --mono, --border-radius, --space-*
web.css --nw-font-display, --nw-font-body, --nw-font-ui,
--nw-ink, --nw-ink-soft, --nw-ink-muted,
--nw-paper, --nw-paper-warm, --nw-rule,
--nw-accent, --nw-transition
Toutes les règles sont préfixées .pj-
*/
/*
BASE BODY
*/
body[data-template="projet"] {
background-color: var(--nw-paper);
color: var(--nw-ink);
min-height: 100vh;
}
/*
EN-TÊTE PROJET
*/
.pj-header {
position: relative;
min-height: 46vh;
display: flex;
align-items: flex-end;
overflow: hidden;
background: var(--nw-ink);
margin-bottom: 4rem;
}
.pj-header__bg {
position: absolute;
inset: 0;
background-size: cover;
background-position: center;
filter: grayscale(25%) brightness(0.75);
transform: scale(1.03);
transition: transform 10s ease-out;
}
.pj-header:hover .pj-header__bg {
transform: scale(1);
}
.pj-header__overlay {
position: absolute;
inset: 0;
background: linear-gradient(
160deg,
rgba(26,26,24,0.05) 0%,
rgba(26,26,24,0.72) 100%
);
}
/* Header sans image : fond plein avec accent subtil */
.pj-header:not(:has(.pj-header__bg)) {
min-height: 28vh;
background: var(--nw-ink);
}
.pj-header:not(:has(.pj-header__bg))::before {
content: '';
position: absolute;
top: 0; left: 0;
width: 4px;
height: 100%;
background: var(--nw-accent);
}
.pj-header__content {
position: relative;
z-index: 2;
padding: 3rem 3rem 3.5rem;
max-width: 1360px;
margin: 0 auto;
width: 100%;
}
.pj-header__eyebrow {
font-family: var(--sans-serif);
font-size: 0.7rem;
font-weight: 600;
letter-spacing: 0.14em;
text-transform: uppercase;
color: var(--nw-accent);
margin: 0 0 0.6rem;
opacity: 0.9;
}
.pj-header__title {
font-family: var(--nw-font-display);
font-size: clamp(2rem, 4.5vw, 4rem);
font-weight: 800;
color: #fff;
line-height: 1.1;
letter-spacing: -0.015em;
margin: 0 0 0.9rem;
text-shadow: 0 2px 20px rgba(0,0,0,0.25);
}
.pj-header__subtitle {
font-family: var(--nw-font-body);
font-size: clamp(1rem, 1.6vw, 1.25rem);
color: rgba(255,255,255,0.78);
font-style: italic;
margin: 0;
max-width: 60ch;
line-height: 1.6;
}
/*
MAIN
*/
.pj-main {
max-width: 1360px;
margin: 0 auto;
padding: 0 2rem 6rem;
}
/*
GRILLE
*/
.pj-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(340px, 1fr));
gap: 20px;
}
/*
CARTE RÉCIT
*/
.pj-card {
display: flex;
flex-direction: column;
position: relative;
overflow: hidden;
transition: transform var(--nw-transition), box-shadow var(--nw-transition);
border: 1px solid var(--nw-rule);
/* Animation d'entrée en cascade */
opacity: 0;
transform: translateY(12px);
animation: pj-fadeIn 0.5s ease forwards;
animation-delay: calc(var(--card-index, 0) * 0.07s);
}
.pj-card:hover {
z-index: 2;
transform: translateY(-3px);
box-shadow: 0 12px 40px rgba(0,0,0,0.14);
}
@keyframes pj-fadeIn {
to { opacity: 1; transform: translateY(0); }
}
/* ── Cover ── */
.pj-card__cover-link {
display: block;
overflow: hidden;
text-decoration: none;
flex-shrink: 0;
}
.pj-card__cover {
height: 250px;
overflow: hidden;
background: var(--color-interface-200);
position: relative;
}
.pj-card__cover img {
width: 100%;
height: 100%;
object-fit: cover;
display: block;
filter: grayscale(8%);
transition: transform 0.6s ease, filter 0.4s ease;
}
.pj-card:hover .pj-card__cover img {
transform: scale(1.04);
filter: grayscale(0%);
}
/* Placeholder quand pas d'image */
.pj-card__cover-placeholder {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
background: var(--color-interface-100);
}
.pj-card__cover-placeholder span {
font-family: var(--nw-font-display);
font-size: 5rem;
font-weight: 800;
color: var(--color-interface-300);
line-height: 1;
user-select: none;
}
/* ── Corps ── */
.pj-card__body {
padding: 1.5rem 1.75rem 1rem;
flex: 1;
display: flex;
flex-direction: column;
gap: 0.6rem;
}
.pj-card__author {
font-family: var(--sans-serif);
font-size: 0.7rem;
font-weight: 600;
letter-spacing: 0.08em;
text-transform: uppercase;
color: var(--nw-accent);
margin: 0;
}
.pj-card__author-label {
color: var(--nw-ink-muted);
font-weight: 400;
margin-right: 0.3ch;
}
.pj-card__title {
font-family: var(--nw-font-display);
font-size: clamp(1.1rem, 1.6vw, 1.35rem);
font-weight: 700;
line-height: 1.25;
color: var(--nw-ink);
margin: 0;
}
.pj-card__title a {
text-decoration: none;
color: inherit;
transition: color var(--nw-transition);
}
.pj-card__title a:hover {
color: var(--nw-accent);
}
.pj-card__intro {
font-family: var(--nw-font-body);
font-size: 0.9rem;
line-height: 1.7;
color: var(--nw-ink-soft);
margin: 0;
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
}
.pj-card__meta {
font-family: var(--sans-serif);
font-size: 0.68rem;
font-weight: 500;
letter-spacing: 0.05em;
color: var(--nw-ink-muted);
text-transform: uppercase;
margin: auto 0 0;
padding-top: 0.5rem;
border-top: 1px solid var(--nw-rule);
}
/* ── Footer / boutons ── */
.pj-card__footer {
padding: 0.75rem 1.75rem 1.5rem;
display: flex;
gap: 0.6rem;
align-items: center;
}
/*
BOUTONS
*/
.pj-btn {
display: inline-flex;
align-items: center;
gap: 0.4rem;
font-family: var(--sans-serif);
font-size: 0.72rem;
font-weight: 600;
letter-spacing: 0.05em;
text-decoration: none;
padding: 0.4rem 0.9rem;
border-radius: var(--border-radius);
transition:
background-color var(--nw-transition),
color var(--nw-transition),
border-color var(--nw-transition),
box-shadow var(--nw-transition);
white-space: nowrap;
cursor: pointer;
line-height: 1.4;
}
/* Ghost : contour */
.pj-btn--ghost {
color: var(--nw-ink-soft);
border: 1px solid var(--nw-rule);
background: transparent;
}
.pj-btn--ghost:hover {
border-color: var(--nw-ink-soft);
color: var(--nw-ink);
background: var(--color-interface-100);
}
/* Solid : accent plein */
.pj-btn--solid {
color: #fff;
background: var(--nw-accent);
border: 1px solid var(--nw-accent);
}
.pj-btn--solid:hover {
background: var(--nw-accent-dark, color-mix(in srgb, var(--nw-accent) 80%, #000));
border-color: var(--nw-accent-dark, color-mix(in srgb, var(--nw-accent) 80%, #000));
box-shadow: 0 2px 10px color-mix(in srgb, var(--nw-accent) 35%, transparent);
}
/*
ÉTAT VIDE
*/
.pj-empty {
text-align: center;
padding: 6rem 2rem;
color: var(--nw-ink-muted);
font-family: var(--nw-font-body);
font-style: italic;
font-size: 1.1rem;
}
/*
RESPONSIVE
*/
@media (max-width: 900px) {
.pj-header__content { padding: 2rem 1.5rem 2.5rem; }
.pj-main { padding: 0 0 4rem; }
.pj-grid { grid-template-columns: 1fr; gap: 1px; }
}
@media (max-width: 600px) {
.pj-card__cover { height: 180px; }
.pj-card__footer { flex-direction: column; align-items: stretch; }
.pj-btn { justify-content: center; }
}
@media (min-width: 901px) and (max-width: 1100px) {
.pj-grid { grid-template-columns: repeat(2, 1fr); }
}

View file

@ -1,29 +1,17 @@
/*/* /*/*
narrative-web.css
Style storytelling éditorial inspiré des grandes enquêtes
journalistiques (NYT, Le Monde, The Guardian)
Ce fichier COMPLÈTE style.css sans l'écraser. Ce fichier COMPLÈTE style.css sans l'écraser.
Toutes les règles sont préfixées .nw- ou [data-template="narrative-web"] Toutes les règles sont préfixées .nw- ou [data-template="narrative-web"]
*/ */
/*
VARIABLES LOCALES
(surcharge possible via customCss du panel)
*/
:root { :root {
/* --nw-font-display : 'Playfair Display', 'Georgia', 'Times New Roman', serif;
--nw-font-body : 'Source Serif 4', 'Georgia', serif;
--nw-font-ui : 'DM Sans', 'Helvetica Neue', sans-serif;*/
--nw-ink : #1a1a18; --nw-ink : #1a1a18;
--nw-ink-soft : #3d3d38; --nw-ink-soft : #3d3d38;
--nw-ink-muted : #7a7a72; --nw-ink-muted : #7a7a72;
--nw-paper : var(--color-panel-bg); --nw-paper : var(--color-panel-bg);
--nw-paper-warm : #f4f1eb; --nw-paper-warm : #f4f1eb;
--nw-rule : #d8d4cc; --nw-rule : #d8d4cc;
--nw-accent : rgb(93, 40, 230); --nw-accent : #5D28E6;
--nw-accent-dark : #96261e; --nw-accent-dark : #361192;
--nw-tag-bg : #e9e5dc; --nw-tag-bg : #e9e5dc;
--nw-max-w : 1280px; --nw-max-w : 1280px;
@ -33,16 +21,6 @@
--nw-transition : 0.25s ease; --nw-transition : 0.25s ease;
} }
/*
BASE BODY (narrative-web uniquement)
*/
/*body[data-template="narrative-web"] {
background-color: var(--nw-paper);
color: var(--nw-ink);
font-family: var(--nw-font-body);
line-height: 1.75;
-webkit-font-smoothing: antialiased;
}*/
/* /*
NAVIGATION LATÉRALE NAVIGATION LATÉRALE
@ -956,29 +934,6 @@
display: block; display: block;
} }
/*
ANIMATIONS D'ENTRÉE
*/
/*@keyframes nw-fadeUp {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
.nw-hero__content {
animation: nw-fadeUp 0.9s ease 0.15s both;
}
.nw-section {
opacity: 0;
transform: translateY(16px);
transition: opacity 0.6s ease, transform 0.6s ease;
}
.nw-section.is-visible {
opacity: 1;
transform: translateY(0);
}*/
/* /*
RESPONSIVE RESPONSIVE
*/ */
@ -997,8 +952,3 @@
.nw-section { padding: 3rem 0; } .nw-section { padding: 3rem 0; }
} }
/*
INTERSECTION OBSERVER (sections visibles)
*/
/* Le JS d'en bas de page gère les classes is-visible */

View file

@ -14,4 +14,36 @@ Introduction: <p>Je devais seulement faire les courses. Voilà que le chemin emp
---- ----
Customcss:
@page {
size: A4;
margin: 20mm 15mm 26mm 15mm;
background: rgb(255, 255, 255);
}
p {
font-size: 16px;
margin-top: 0mm;
margin-right: 0mm;
margin-bottom: 5mm;
margin-left: 0mm;
font-family: Times New Roman;
color: rgb(28, 0, 0);
}
h1 {
font-family: Alegreya;
font-style: normal;
font-weight: 700;
font-size: 60px;
text-align: start;
color: rgb(255, 0, 0);
background: rgba(113, 54, 255, 0.1);
margin: 32.16px;
padding: 0px;
}
----
Uuid: lgafsp7bt5ljb31a Uuid: lgafsp7bt5ljb31a

View file

@ -97,7 +97,7 @@ foreach ($subpages as $subpage) {
<?php endif ?> <?php endif ?>
<!-- ═══════════════════════════════════════════ <!-- ═══════════════════════════════════════════
HERO / INTRODUCTION BANDEAU / INTRODUCTION
════════════════════════════════════════════ --> ════════════════════════════════════════════ -->
<header class="nw-hero" id="nw-intro"> <header class="nw-hero" id="nw-intro">
<?php if ($original->cover()->isNotEmpty() && $cover = $original->cover()->toFile()): ?> <?php if ($original->cover()->isNotEmpty() && $cover = $original->cover()->toFile()): ?>

View file

@ -0,0 +1,151 @@
<?php
/**
* Template: projet.php
* Affichage de la liste des récits
*/
?>
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><?= e($page->isHomePage() != true, $page->title() . ' ') . $site->title() ?></title>
<!-- Styles globaux existants -->
<link rel="stylesheet" href="<?= url('assets/css/style.css') ?>">
<!-- Styles web -->
<link rel="stylesheet" href="<?= url('assets/css/web.css') ?>">
<!-- Styles projet -->
<link rel="stylesheet" href="<?= url('assets/css/projet.css') ?>">
<!-- À SUPPRIMER EN PRODUCTION -->
<meta name="robots" content="noindex, nofollow, noarchive">
<?php if ($kirby->user()): ?>
<meta name="csrf" content="<?= csrf() ?>">
<?php endif ?>
</head>
<body data-template="<?= $page->template() ?>">
<!-- ═══════════════════════════════════════════
EN-TÊTE PROJET
════════════════════════════════════════════ -->
<header class="pj-header">
<?php if ($page->cover()->isNotEmpty() && $cover = $page->cover()->toFile()): ?>
<div class="pj-header__bg" style="background-image: url('<?= $cover->url() ?>')"></div>
<div class="pj-header__overlay"></div>
<?php endif ?>
<div class="pj-header__content">
<p class="pj-header__eyebrow"><?= html($site->title()) ?></p>
<h1 class="pj-header__title"><?= html($page->title()) ?></h1>
<?php if ($page->subtitle()->isNotEmpty()): ?>
<p class="pj-header__subtitle"><?= html($page->subtitle()) ?></p>
<?php endif ?>
</div>
</header>
<!-- ═══════════════════════════════════════════
GRILLE DES RÉCITS
════════════════════════════════════════════ -->
<main class="pj-main">
<?php $narratives = $page->children()->listed()->filterBy('intendedTemplate', 'narrative'); ?>
<?php if ($narratives->isEmpty()): ?>
<div class="pj-empty">
<p>Aucun récit publié pour l'instant.</p>
</div>
<?php else: ?>
<div class="pj-grid">
<?php foreach ($narratives as $i => $narrative): ?>
<?php
$cover = $narrative->cover()->toFile();
$intro = $narrative->introduction()->excerpt(180, true, '…');
$printUrl = $narrative->url(); // Version imprimée = URL native Kirby (narrative.php)
$webUrl = $narrative->url() . '/web'; // Version web = narrative-web.php via route ou suffix
?>
<article class="pj-card" style="--card-index: <?= $i ?>">
<!-- Cover -->
<a class="pj-card__cover-link" href="<?= $webUrl ?>" tabindex="-1" aria-hidden="true">
<div class="pj-card__cover">
<?php if ($cover): ?>
<img
src="<?= $cover->url() ?>"
alt="<?= html($narrative->title()) ?>"
loading="lazy"
>
<?php else: ?>
<div class="pj-card__cover-placeholder">
<span><?= mb_substr($narrative->title(), 0, 1) ?></span>
</div>
<?php endif ?>
</div>
</a>
<!-- Corps -->
<div class="pj-card__body">
<!-- Méta : auteur·ice -->
<?php if ($narrative->author()->isNotEmpty()): ?>
<p class="pj-card__author">
<span class="pj-card__author-label">Par</span>
<?= html($narrative->author()) ?>
</p>
<?php endif ?>
<!-- Titre -->
<h2 class="pj-card__title">
<a href="<?= $webUrl ?>"><?= html($narrative->title()) ?></a>
</h2>
<!-- Début de l'intro -->
<?php if ($intro): ?>
<p class="pj-card__intro"><?= $intro ?></p>
<?php endif ?>
<!-- Compteur sous-pages (optionnel, indicatif) -->
<?php $subCount = $narrative->children()->listed()->count(); ?>
<?php if ($subCount > 0): ?>
<p class="pj-card__meta">
<?= $subCount ?> <?= $subCount > 1 ? 'sections' : 'section' ?>
</p>
<?php endif ?>
</div>
<!-- Actions -->
<footer class="pj-card__footer">
<a
href="<?= $narrative->url() ?>"
class="pj-btn pj-btn--ghost"
target="_blank"
rel="noopener"
title="Ouvrir la version imprimée de « <?= html($narrative->title()) ?> »"
>
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<polyline points="6 9 6 2 18 2 18 9"/><path d="M6 18H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2"/><rect x="6" y="14" width="12" height="8"/>
</svg>
Version imprimée
</a>
<a
href="<?= $webUrl ?>"
class="pj-btn pj-btn--solid"
title="Lire la version web de « <?= html($narrative->title()) ?> »"
>
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/>
</svg>
Version web
</a>
</footer>
</article>
<?php endforeach ?>
</div>
<?php endif ?>
</main>
<?php snippet('footer') ?>
</body>
</html>