Implement static design into Kirby templates and add deploy workflow
Some checks failed
Deploy / Deploy to Production (push) Failing after 5s

- Migrate CSS, fonts, logo, icons from static prototype to assets/
- Implement header, footer, nav, card snippets
- Implement home (catalog) and card (detail) templates
- Expand card blueprint with identification, metadata and text fields
- Add Forgejo CI/CD deploy workflow via FTP

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
isUnknown 2026-07-01 09:00:55 +02:00
parent 8e81736a94
commit 34ea7591de
44 changed files with 1711 additions and 34 deletions

View file

@ -0,0 +1,39 @@
name: Deploy
on:
push:
branches:
- main
jobs:
deploy:
name: Deploy to Production
runs-on: docker
container:
image: forgejo-ci-php:latest
steps:
- name: Checkout code
run: |
git clone --depth 1 --branch main https://oauth2:${{ github.token }}@forge.studio-variable.com/${{ github.repository }}.git .
- name: Install dependencies
run: |
composer install --no-dev --optimize-autoloader
- name: Deploy via FTP
env:
USERNAME: ${{ secrets.USERNAME }}
PASSWORD: ${{ secrets.PASSWORD }}
HOST: ${{ secrets.HOST }}
run: |
cat > /tmp/lftp-script.txt <<SCRIPT
set ftp:ssl-allow no
open -u $USERNAME,$PASSWORD $HOST
mirror --reverse --verbose --ignore-time --parallel=10 -x local/ -x '.*\.scss' -x src/ assets assets
mirror --reverse --verbose --ignore-time --parallel=10 -x accounts/ -x cache/ -x sessions/ site site
mirror --reverse --verbose --ignore-time --parallel=10 kirby kirby
mirror --reverse --verbose --ignore-time --parallel=10 content content
mirror --reverse --verbose --ignore-time --parallel=10 vendor vendor
quit
SCRIPT
lftp -f /tmp/lftp-script.txt

53
assets/css/01-fonts.css Normal file
View file

@ -0,0 +1,53 @@
@font-face {
font-family: 'Volkhov';
src: url('/assets/fonts/Volkhov/Volkhov-BoldItalic.woff2') format('woff2');
font-weight: bold;
font-style: italic;
font-display: swap;
}
@font-face {
font-family: 'Volkhov';
src: url('/assets/fonts/Volkhov/Volkhov-Bold.woff2') format('woff2');
font-weight: bold;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Volkhov';
src: url('/assets/fonts/Volkhov/Volkhov-Italic.woff2') format('woff2');
font-weight: normal;
font-style: italic;
font-display: swap;
}
@font-face {
font-family: 'Volkhov';
src: url('/assets/fonts/Volkhov/Volkhov-Regular.woff2') format('woff2');
font-weight: normal;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Open Sans';
src: url('/assets/fonts/OpenSans/OpenSans-VariableFont_wdth,wght.woff2') format('woff2');
font-weight: 300 800;
font-stretch: 75% 100%;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Open Sans';
src: url('/assets/fonts/OpenSans/OpenSans-Italic-VariableFont_wdth,wght.woff2') format('woff2');
font-weight: 300 800;
font-stretch: 75% 100%;
font-style: italic;
font-display: swap;
}

34
assets/css/02-colors.css Normal file
View file

@ -0,0 +1,34 @@
:root{
--grey-200: #e8e2db;
--grey-400: #ccc;
--grey-500: #b0a498;
--grey-800: rgb(40, 40, 40);
--color-bg: white;
--color-text: #111;
--orange: #C16023;
--orange-light: #D9A171;
--blue: #003399;
--blue-light: #9FAEE5;
--blue-green: #59af9c;
--yellow: #FFCC00;
--c-ink: var(--color-text);
--bg: #fff;
--bg-muted: #f0ece7;
--c-placeholder: #b0a498;
--c-text-faint: var(--grey-500);
}

View file

@ -0,0 +1,35 @@
:root {
--font: "Open Sans", sans-serif;
--font-serif: "Volkhov", serif;
font-family: var(--font);
--fs-card: 1.1rem;
--fs-tags: 0.7rem;
--fs-xsmall: 0.7rem;
--fs-small: 0.85rem;
--fs-display: 4rem;
--padding-inline-page: 2rem;
--radius-card: 0.75rem;
--radius-block: 0.5rem;
--radius-small: 4px;
--padding-cards: 0.75rem;
--placeholder-bg:
linear-gradient(to bottom right,
transparent calc(50% - .6px), var(--grey-500) calc(50% - .6px),
var(--grey-500) calc(50% + .6px), transparent calc(50% + .6px)),
linear-gradient(to bottom left,
transparent calc(50% - .6px), var(--grey-500) calc(50% - .6px),
var(--grey-500) calc(50% + .6px), transparent calc(50% + .6px));
}
@media screen and (max-width: 640px) {}

82
assets/css/04-base.css Normal file
View file

@ -0,0 +1,82 @@
* {
margin: 0;
padding: 0;
-webkit-font-smoothing: antialiased;
-moz-font-smoothing: antialiased;
-o-font-smoothing: antialiased;
font-optical-sizing: auto;
}
*,
*::after,
*::before {
box-sizing: border-box;
}
a {
color: currentColor;
text-decoration: none;
}
button,
input,
select,
textarea {
font-family: inherit;
font-size: inherit;
}
button {
border: none;
width: auto;
overflow: visible;
background: transparent;
color: inherit;
font: inherit;
line-height: normal;
-webkit-appearance: none;
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-size: 1rem;
font-weight: normal;
}
html {
background-color: var(--bg);
color: var(--color-text);
font-weight: 500;
scroll-behavior: smooth;
}
:target {
/* scroll-margin-top: calc(var(--header-h) + var(--breadcrumb-h)); */
}
a:hover {
color: currentColor;
text-decoration: underline 1px;
text-underline-offset: 3px;
cursor: pointer;
}
figure,
img {
width: 100%;
display: flex;
}

140
assets/css/05-header.css Normal file
View file

@ -0,0 +1,140 @@
/* ── Header ─────────────────────────────────────────────── */
.site-header {
position: sticky;
top: 0;
z-index: var(--z-header);
background: var(--bg);
border-bottom: 1px solid var(--grey-500);
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 var(--padding-inline-page);
height: var(--header-h);
}
.site-logo {
display: flex;
align-items: center;
flex-shrink: 0;
}
.site-logo img {
height: 56px;
width: auto;
display: block;
}
.header-actions {
display: flex;
align-items: center;
gap: var(--sp-3);
flex-shrink: 0;
}
.header-nav {
margin-left: auto;
margin-right: 6ch;
}
.header-nav ul {
list-style: none;
display: flex;
font-size: 12px;
font-weight: 700;
gap: 4ch;
color: #111;
}
.header-nav ul li:hover {
color: var(--orange);
cursor: pointer;
}
.search-wrap {
display: flex;
align-items: center;
gap: var(--sp-2);
border: 1px solid var(--grey-400);
border-radius: 4rem;
padding: var(--p-btn);
}
.search-wrap svg {
display: none;
}
.search-wrap input {
background: none;
border: none;
outline: none;
color: #111;
width: 160px;
font-size: var(--fs-xsmall);
}
.search-wrap input::placeholder {
color: #999;
}
.lang-select-wrap {
display: flex;
align-items: center;
/* gap: var(--sp-2); */
border: 1px solid var(--blue);
border-radius: 4rem;
padding-left: 1ch;
}
.lang-select-wrap .icon img {
width: 14px;
height: 14px;
filter: brightness(0) saturate(100%) invert(16%) sepia(94%) saturate(1600%) hue-rotate(213deg) brightness(96%);
}
.lang-select {
/* border: 1px solid var(--grey-400);
border-radius: 4rem; */
font-weight: 600;
border: none;
padding: var(--p-btn);
background: none;
color: var(--blue);
font-size: var(--fs-xsmall);
cursor: pointer;
outline: none;
appearance: none;
padding-right: 1.6em;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23003399'/%3E%3C/svg%3E");
background-repeat: no-repeat;
background-position: right 0.6em center;
}
.lang-select:hover {
border-color: #111;
}
.btn-account {
border: 1px solid #111;
border-radius: 4rem;
background: none;
color: #111;
padding: var(--p-btn);
cursor: pointer;
font-size: var(--fs-xsmall);
}
.btn-account svg {
display: none;
}
.btn-account--primary {
background: var(--blue);
border-color: var(--blue);
color: var(--color-bg);
font-weight: 600;
}
.btn-account--primary:hover {
background: var(--blue-light);
border-color: var(--blue-light);
}

9
assets/css/06-footer.css Normal file
View file

@ -0,0 +1,9 @@
.site-footer {
border-top: 1px solid #111; padding: 1.5rem var(--padding-inline-page);
display: flex; align-items: center; justify-content: space-between;
flex-wrap: wrap; gap: 12px;
font-size: var(--fs-xsmall); color: #111; margin-top: 60px;
}
.footer-logo { font-family: var(--font-serif); font-size: 18px; font-weight: 700; color: #111; }
.footer-links { display: flex; gap: 20px; }
.footer-links a:hover { color: var(--orange); }

View file

@ -0,0 +1,62 @@
.piece-card {
border-radius: var(--radius-card);
border: 1px solid var(--grey-400);
overflow: hidden;
cursor: pointer;
display: flex;
flex-direction: column;
transition: border-color .15s;
position: relative;
}
.piece-card:hover {
border-color: var(--orange);
}
.card-image {
display: block;
aspect-ratio: 1;
position: relative;
overflow: hidden;
background: var(--grey-200);
border-bottom: 1px solid var(--grey-500);
}
.card-image::before {
content: '';
position: absolute;
inset: 0;
background: var(--placeholder-bg);
z-index: 0;
}
.card-image img {
z-index: 10;
width: 100%;
height: 100%;
object-fit: cover;
display: none;
}
.card-body {
padding: 1.25rem 0.75rem;
flex: 1;
display: flex;
flex-direction: column;
}
.card-name {
font-family: var(--font);
font-size: var(--fs-card);
color: var(--grey-800);
line-height: 1.2;
font-weight: 600;
margin-bottom: 0.75rem;
}

View file

@ -0,0 +1,15 @@
/* Les composants réutilisables de l'interface : boutons, cartes, formulaires, menus, modales, badges, etc. */
*:has(.link-block){
position: relative;
}
.link-block {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: block;
cursor: pointer;
}

View file

@ -0,0 +1,27 @@
.active-filters {
display: flex;
gap: 0.5rem;
flex-wrap: wrap;
}
.filter-tag {
display: flex;
align-items: center;
gap: 0.75ch;
border: 1px solid var(--grey-500);
border-radius: 4rem;
padding: 3px 10px 3px 12px;
font-size: var(--fs-xsmall);
}
.filter-tag button {
background: none;
border: none;
cursor: pointer;
color: var(--grey-500);
line-height: 1;
padding: 0;
font-size: 1rem;
}

View file

@ -0,0 +1,23 @@
.meta-list-tags {
display: flex;
flex-wrap: wrap;
gap: 0.25em;
}
.meta-tag {
font-size: var(--fs-tags);
line-height: 1;
color: var(--grey-500);
border: 1px solid currentColor;
border-radius: 4rem;
padding: 0.3rem 0.6rem;
}
.meta-tag.is-selected {
color: var(--color-text);
border-color: var(--color-text);
}
.meta-tag--more {
border: 1.5px dashed currentColor;
}

View file

@ -0,0 +1,31 @@
.catalog-wrap {
display: flex;
align-items: flex-start;
padding-inline: var(--padding-inline-page);
padding-bottom: 1.5rem;
gap: 1.5rem;
}
.catalog-wrap .sidebar,
.catalog-main{
padding-top: 1.5rem;
}
.catalog-main {
flex: 1;
min-width: 0;
}
.catalog-toolbar,
.active-filters{
margin-bottom: 1.25rem;
}
.pieces-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 1rem;
}

19
assets/css/main.css Normal file
View file

@ -0,0 +1,19 @@
@import url("01-fonts.css");
@import url("02-colors.css");
@import url("03-variables.css");
@import url("04-base.css");
@import url("05-header.css");
@import url("06-footer.css");
@import url("components/components.css");
@import url("components/tag.css");
@import url("components/filter-tag.css");
@import url("components/card.css");
@import url("utilities/hero.css");
@import url("utilities/section-switcher.css");
@import url("utilities/sidebar-filters.css");
@import url("utilities/catalog-toolbar.css");
@import url("utilities/pagination.css");
@import url("layout/catalog.css");

270
assets/css/object.css Normal file
View file

@ -0,0 +1,270 @@
:root {
/* ── Ceramic+ — couleurs & fontes (via 01-variables.css) ── */
/* --orange, --orange-light, --blue, --grey-500, --blue-green,
--font, --font-serif déjà chargés par style/main.css */
--fs-xsmall: 11px;
--text-base: 15px;
--text-title: 17px;
--text-hero: 32px;
/* Layout */
--header-h: 60px;
--subnav-h: 44px;
--sidebar-w: 260px;
--info-panel-w: 300px;
/* Espacement */
--sp-1: 4px;
--sp-2: 6px;
--sp-3: 8px;
--p-section: 32px;
--p-btn: 5px 14px;
--p-tag: 4px 12px;
/* Border-radius */
--r-pill: 100px;
--r-sm: 6px;
--r-xs: 5px;
--r-mini: 3px;
/* Z-index */
--z-header: 100;
--z-subnav: 90;
--border: 1px solid var(--grey-500);
}
/*
PAGE FICHE OBJET round-object.html
*/
/* ── Barre de retour / navigation ───────────────────────── */
.obj-nav {
display: flex; align-items: center; gap: 1rem;
padding: 0 var(--padding-inline-page); height: var(--subnav-h);
border-bottom: 1px solid var(--grey-500);
position: sticky; top: var(--header-h); z-index: var(--z-subnav);
background: var(--bg);
}
.obj-back {
display: flex; align-items: center; gap: var(--sp-2);
font-size: var(--fs-xsmall); color: #111; flex-shrink: 0;
border: 1px solid #111; border-radius: 4rem; padding: var(--p-tag);
}
.obj-back:hover { color: var(--orange); border-color: var(--orange); }
.obj-nav-context { display: flex; align-items: center; gap: 10px; flex: 1; min-width: 0; }
.obj-nav-path {
display: flex; align-items: center; gap: var(--sp-2);
font-size: var(--fs-xsmall); color: #111; flex-shrink: 0;
}
.bc-sep { opacity: .4; }
.obj-nav-filters { display: flex; gap: var(--sp-1); flex-wrap: nowrap; overflow: hidden; }
.result-nav-filters {
display: flex; align-items: center; gap: 5px;
color: var(--color-text); font-size: var(--fs-xsmall);
}
.result-nav-filters .filter::after { content: ', '; padding-right: 0.5ch; }
.result-nav-filters .filter:last-of-type::after { content: '…'; }
.obj-nav-arrows { display: flex; align-items: center; gap: var(--sp-2); flex-shrink: 0; margin-left: auto; }
.obj-arrow {
width: 26px; height: 26px;
display: flex; align-items: center; justify-content: center;
border: 1px solid #111; border-radius: 4rem;
background: none; color: #111; cursor: pointer;
}
.obj-arrow:hover { border-color: var(--orange); color: var(--orange); }
.obj-position { font-size: var(--fs-xsmall); color: #111; white-space: nowrap; }
/* ── Conteneur principal ─────────────────────────────────── */
.obj-wrap { padding: 0 var(--padding-inline-page); }
/* ── En-tête objet ───────────────────────────────────────── */
.obj-header {
display: flex; align-items: flex-start; justify-content: space-between;
gap: 1rem; padding: 24px 0 20px; margin-bottom: 1.5rem;
}
.obj-ref { font-size: var(--fs-xsmall); color: var(--grey-500); letter-spacing: .1em; text-transform: uppercase; display: block; margin-bottom: var(--sp-1); }
.obj-title {
font-family: var(--font-serif);
font-size: var(--text-hero); font-weight: 400; color: var(--orange); line-height: 1.1;
margin-top: 0.5em;
}
.obj-header-actions { display: flex; gap: var(--sp-2); flex-shrink: 0; margin-top: var(--sp-1); }
.btn-action {
display: flex; align-items: center; gap: var(--sp-2);
border: 1px solid #111; border-radius: 4rem;
background: none; color: #111;
padding: var(--p-btn); cursor: pointer; font-size: var(--fs-xsmall);
}
.btn-action:hover { border-color: var(--orange); color: var(--orange); }
/* ── Corps : médias + panneau info ───────────────────────── */
.obj-body { display: grid; grid-template-columns: 1fr var(--info-panel-w); gap: 28px; }
/* ── Section médias ──────────────────────────────────────── */
.obj-media { display: flex; flex-direction: column; min-width: 0; }
.media-tabs {
display: flex;
border: var(--border); border-radius: var(--radius-block) var(--radius-block) 0 0;
overflow: hidden; border-bottom: none;
}
.media-tab {
flex: 1; display: flex; align-items: center; justify-content: center; gap: var(--sp-2);
padding: 8px 10px; background: none; border: none; border-right: var(--border);
font-family: inherit; font-size: var(--fs-xsmall); color: var(--c-ink); cursor: pointer;
}
.media-tab:last-child { border-right: none; }
/* aplat orange — onglet actif */
.media-tab.is-active { background: var(--orange); color: white; }
.media-count {
display: inline-flex; align-items: center; justify-content: center;
width: 16px; height: 16px; border-radius: 4rem;
border: 1px solid currentColor; font-size: var(--fs-xsmall); line-height: 1;
}
.media-viewer {
position: relative; aspect-ratio: 16 / 9;
border: 1.5px solid var(--orange-light); overflow: hidden;
background: var(--grey-200);
}
.media-viewer::before { content: ''; position: absolute; inset: 0; background: var(--placeholder-bg); }
.media-viewer-inner {
position: absolute; inset: 0;
display: flex; flex-direction: column; align-items: center; justify-content: center;
gap: var(--sp-2); pointer-events: none;
}
.media-type-label { font-size: var(--text-base); color: var(--orange); font-family: var(--font); }
.media-hint { font-size: var(--fs-xsmall); color: #111; }
.media-controls { position: absolute; bottom: 10px; right: 10px; display: flex; gap: var(--sp-1); }
.ctrl-btn {
width: 28px; height: 28px;
display: flex; align-items: center; justify-content: center;
border: var(--border); border-radius: var(--r-sm);
background: white; color: var(--c-ink); cursor: pointer;
}
.ctrl-btn--sep { margin-left: var(--sp-1); }
/* ── Vignettes ───────────────────────────────────────────── */
.media-thumbs {
display: flex; gap: var(--sp-2); overflow-x: auto; scrollbar-width: none;
padding: 10px 12px;
border: 1.5px solid var(--orange-light); border-top: none;
border-radius: 0 0 var(--radius-block) var(--radius-block);
}
.media-thumbs::-webkit-scrollbar { display: none; }
.thumb {
position: relative; flex-shrink: 0; height: 64px; width: 84px;
border: 1px solid var(--orange-light); border-radius: var(--r-xs); overflow: hidden;
cursor: pointer; display: flex; flex-direction: column;
align-items: center; justify-content: center; gap: 3px;
}
.thumb::before { content: ''; position: absolute; inset: 0; background: var(--placeholder-bg); }
.thumb-icon { position: relative; z-index: 1; }
.thumb-label {
position: relative; z-index: 1;
font-size: var(--fs-xsmall); color: var(--orange); text-align: center;
background: rgba(255,255,255,.85); padding: 1px 5px; border-radius: var(--r-mini);
}
.thumb.is-active { border: 2px solid var(--orange); }
.thumb--portrait { width: 44px; }
.thumb--pdf { width: 52px; }
.thumb--3d::before { display: none; }
.thumb--3d { background: var(--grey-200); }
/* ── Panneau d'informations ──────────────────────────────── */
.obj-info {
display: flex; flex-direction: column;
border: 1.5px solid var(--orange-light); border-radius: var(--radius-block); overflow: hidden;
align-self: flex-start;
position: sticky; top: calc(var(--header-h) + var(--subnav-h));
}
.info-list { list-style: none; }
.info-row { padding: 14px 16px; display: flex; flex-direction: column; gap: var(--sp-1); }
.info-row dt {
font-size: var(--fs-xsmall); color: var(--orange);
text-transform: uppercase; letter-spacing: .08em; font-weight: 700;
}
.info-row dd { font-size: var(--text-base); color: #111; line-height: 1.5; margin: 0; }
.info-sub { font-size: var(--fs-xsmall); color: var(--orange-light); }
.info-divider { border: none; border-top: 1px solid var(--orange-light); margin: 0; }
/* aplat orange — CTA principal de la fiche */
.btn-contact-cta {
display: flex; align-items: center; justify-content: center; gap: var(--sp-2);
width: 100%; padding: var(--padding-cards) 16px;
background: var(--orange); border: none;
color: white; font-family: inherit; font-size: var(--fs-xsmall); cursor: pointer;
}
.btn-contact-cta:hover { background: #a8511c; }
/* ── Sections ────────────────────────────────────────────── */
.obj-section { padding: var(--p-section) 0; }
.obj-section-title {
font-family: var(--font-serif);
font-size: 22px; font-weight: 400; color: var(--orange);
margin-bottom: 1rem;
}
.obj-description { display: flex; flex-direction: column; gap: 12px; margin-bottom: 1rem; }
.obj-description p { font-size: var(--text-base); color: #111; line-height: 1.75; max-width: 680px; }
.obj-keywords { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin-top: var(--sp-3); }
.keyword-tag {
font-size: var(--fs-xsmall); color: var(--color-text);
border: 1px solid var(--grey-500); border-radius: 4rem; padding: 3px 10px;
}
/* ── Formulaire de contact ───────────────────────────────── */
.contact-form { display: flex; flex-direction: column; gap: 14px; max-width: 640px; }
.form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.form-group { display: flex; flex-direction: column; gap: var(--sp-2); }
.form-label { font-size: var(--fs-xsmall); color: var(--c-ink); text-transform: uppercase; letter-spacing: .06em; }
.form-required { color: var(--orange); }
.form-input {
border: var(--border); border-radius: var(--r-sm); padding: 8px 10px;
background: var(--bg); color: var(--c-ink);
font-family: inherit; font-size: var(--text-base);
outline: none; width: 100%;
}
.form-input:focus { border-color: var(--orange); }
.form-input[readonly] { background: var(--bg-muted); color: var(--grey-500); }
.form-input::placeholder { color: var(--c-text-faint); }
.form-textarea { resize: vertical; min-height: 100px; }
.form-footer-row {
display: flex; align-items: center; justify-content: space-between;
gap: 1rem; flex-wrap: wrap; margin-top: var(--sp-1);
}
.form-note { font-size: var(--fs-xsmall); color: var(--grey-500); }
/* aplat orange — bouton envoi */
.btn-submit {
border: none; border-radius: 4rem;
background: var(--orange); color: white;
padding: 8px 24px; font-family: inherit; font-size: var(--fs-xsmall); cursor: pointer;
}
.btn-submit:hover { background: #a8511c; }
/* ── Pièces similaires ───────────────────────────────────── */
.obj-related-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; }

View file

View file

@ -0,0 +1,30 @@
.catalog-toolbar {
display: flex;
align-items: center;
justify-content: space-between;
flex-wrap: wrap;
gap: 0.5rem;
}
.toolbar-section {
display: flex;
align-items: baseline;
gap: 0.5ch
}
.toolbar-section-name {
font-weight: 700;
}
.toolbar-section svg {
opacity: .35;
flex-shrink: 0;
}
.num-results {
font-size: var(--fs-xsmall);
}
.num-results span {
font-weight: 700;
}

View file

@ -0,0 +1,15 @@
.page-hero {
padding: 48px var(--padding-inline-page) 44px;
display: flex;
align-items: flex-end;
justify-content: space-between;
gap: 1.5rem;
}
.page-hero h1 {
font-family: var(--font-serif);
font-size: var(--fs-display);
color: var(--orange);
line-height: .95;
font-weight: 400;
}

View file

@ -0,0 +1,13 @@
.pagination {
display: flex; align-items: center; justify-content: center; gap: var(--sp-1);
margin-top: var(--p-section); padding-top: 20px;
}
.page-btn {
min-width: 34px; height: 34px;
display: flex; align-items: center; justify-content: center;
border: 1px solid var(--grey-400); border-radius: 4rem;
background: none; color: #999; font-size: var(--text-base); cursor: pointer;
}
.page-btn.active { background: #f5f5f5; color: #111; border-color: #111; }
.page-btn.ellipsis { border: none; cursor: default; pointer-events: none; color: var(--grey-400); }
.page-btn:hover:not(.active):not(.ellipsis) { border-color: #999; color: #111; }

View file

@ -0,0 +1,93 @@
.section-switcher {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 10px;
padding: 14px var(--padding-inline-page);
}
.section-tile {
display: flex;
flex-direction: column;
padding-inline: 1rem;
padding-block-start: 1rem;
padding-block-end: 1.5rem;
background: none;
border: 1.5px solid var(--orange-light);
border-radius: var(--radius-block);
position: relative;
overflow: hidden;
}
.section-tile:hover {
border-color: var(--orange);
text-decoration: none;
}
.tile-name {
font-family: var(--font-serif);
font-size: var(--text-title);
color: var(--orange);
font-weight: 700;
padding-left: 1rem;
}
.tile-items {
list-style: none;
margin-top: var(--sp-3);
display: flex;
flex-direction: column;
}
.tile-item-sub a {
font-size: var(--fs-small);
color: var(--orange);
padding-inline: 1rem;
padding-block: 2px;
position: relative;
display: block;
}
.tile-item-sub a::before{
content: "+";
position: absolute;
left: 5px;
opacity: 0;
}
.section-tile.active {
background: rgba(217, 161, 113, 0.12);
}
.section-tile.active .tile-name {
color: var(--orange);
}
.section-tile.active .tile-item-sub a{
color: var(--orange);
border-radius: var(--radius-small);
}
.section-tile.active .tile-item-sub.active a {
color: var(--orange);
border-color: var(--orange);
font-weight: 700;
background: rgba(217, 161, 113, 0.2);
}
.section-tile.active .tile-item-sub.active a::before{
opacity: 1;
}
.section-tile .tile-item-sub a:hover{
background: rgba(217, 161, 113, 0.2);
text-decoration: none;
}

View file

@ -0,0 +1,132 @@
.sidebar {
width: var(--sidebar-w);
flex-shrink: 0;
position: sticky;
top: var(--header-h);
max-height: calc(100vh - var(--header-h));
overflow-y: auto;
}
.sidebar-title {
font-size: var(--fs-small);
font-weight: 700;
letter-spacing: .025em;
margin-bottom: 1em;
padding-bottom: 0.75em;
border-bottom: 1px solid var(--grey-500);
}
.filter-accordion {
border: none;
}
.filter-accordion-title {
list-style: none;
display: flex;
align-items: center;
justify-content: space-between;
font-size: var(--fs-xsmall);
font-weight: 700;
letter-spacing: .025em;
cursor: pointer;
padding: 6px 0;
user-select: none;
}
.filter-accordion-title::-webkit-details-marker {
display: none;
}
.filter-accordion-title::after {
content: '+';
font-weight: 400;
color: var(--color-text);
}
.filter-accordion[open] .filter-accordion-title::after {
content: '';
}
.filter-accordion-body {
padding: 8px 0 4px;
display: flex;
flex-direction: column;
gap: 7px;
}
.filter-subgroup-label {
font-size: var(--fs-xsmall);
color: var(--grey-500);
font-style: italic;
margin-top: 10px;
margin-bottom: 7px;
}
.filter-checkbox-list {
list-style: none;
display: flex;
flex-direction: column;
gap: var(--sp-1);
}
.filter-checkbox-list label {
display: flex;
align-items: center;
gap: var(--sp-3);
cursor: pointer;
font-size: var(--fs-xsmall);
color: var(--c-ink);
}
.filter-checkbox-list input[type="checkbox"] {
accent-color: var(--color-text);
width: 12px;
height: 12px;
flex-shrink: 0;
}
.filter-checkbox-list--sub {
margin-top: 0.5rem;
}
.filter-checkbox-list--sub label {
padding-left: 1rem;
font-style: italic;
}
.filter-select {
width: 100%;
border: var(--border);
border-radius: var(--r-sm);
padding: 6px 8px;
background: var(--bg);
color: var(--c-ink);
font-size: var(--fs-xsmall);
outline: none;
}
.sidebar-divider {
border: none;
border-top: var(--border);
border-color: var(--grey-500);
margin: 10px 0;
}
/* aplat orange — bouton d'action secondaire */
.btn-reset {
width: 100%;
padding: 8px;
background: none;
border: 1px solid var(--color-text);
border-radius: 4rem;
color: var(--color-text);
cursor: pointer;
font-size: var(--fs-xsmall);
letter-spacing: .04em;
}
.btn-reset:hover {
background: var(--color-text);
color: white;
}

View file

@ -0,0 +1 @@
/* Les classes utilitaires qui ne représentent pas un composant mais une seule propriété ou un petit groupe de propriétés. */

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,53 @@
@font-face {
font-family: 'Volkhov';
src: url('Volkhov-BoldItalic.woff2') format('woff2'),
url('Volkhov-BoldItalic.woff') format('woff');
font-weight: bold;
font-style: italic;
font-display: swap;
}
@font-face {
font-family: 'Volkhov';
src: url('Volkhov-Bold.woff2') format('woff2'),
url('Volkhov-Bold.woff') format('woff');
font-weight: bold;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Volkhov';
src: url('Volkhov-Italic.woff2') format('woff2'),
url('Volkhov-Italic.woff') format('woff');
font-weight: normal;
font-style: italic;
font-display: swap;
}
@font-face {
font-family: 'Volkhov';
src: url('Volkhov-Regular.woff2') format('woff2'),
url('Volkhov-Regular.woff') format('woff');
font-weight: normal;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Open Sans';
src: url('OpenSans-Italic.woff2') format('woff2');
font-weight: normal;
font-style: italic;
font-display: swap;
}
@font-face {
font-family: 'Open Sans';
src: url('OpenSans-Regular.woff2') format('woff2');
font-weight: normal;
font-style: normal;
font-display: swap;
}

12
assets/js/script.js Normal file
View file

@ -0,0 +1,12 @@
// +N pills sur les meta-list-tags
document.querySelectorAll('.meta-list-tags').forEach(meta => {
const pills = Array.from(meta.querySelectorAll('.meta-tag'));
const max = 3;
if (pills.length > max) {
pills.slice(max).forEach(p => p.hidden = true);
const more = document.createElement('span');
more.className = 'meta-tag meta-tag--more';
more.textContent = `+${pills.length - max}`;
meta.appendChild(more);
}
});

BIN
assets/logo-ceramic.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

1
assets/svg/lang.svg Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free v7.3.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2026 Fonticons, Inc.--><path d="M192 64C209.7 64 224 78.3 224 96L224 128L352 128C369.7 128 384 142.3 384 160C384 177.7 369.7 192 352 192L342.4 192L334 215.1C317.6 260.3 292.9 301.6 261.8 337.1C276 345.9 290.8 353.7 306.2 360.6L356.6 383L418.8 243C423.9 231.4 435.4 224 448 224C460.6 224 472.1 231.4 477.2 243L605.2 531C612.4 547.2 605.1 566.1 589 573.2C572.9 580.3 553.9 573.1 546.8 557L526.8 512L369.3 512L349.3 557C342.1 573.2 323.2 580.4 307.1 573.2C291 566 283.7 547.1 290.9 531L330.7 441.5L280.3 419.1C257.3 408.9 235.3 396.7 214.5 382.7C193.2 399.9 169.9 414.9 145 427.4L110.3 444.6C94.5 452.5 75.3 446.1 67.4 430.3C59.5 414.5 65.9 395.3 81.7 387.4L116.2 370.1C132.5 361.9 148 352.4 162.6 341.8C148.8 329.1 135.8 315.4 123.7 300.9L113.6 288.7C102.3 275.1 104.1 254.9 117.7 243.6C131.3 232.3 151.5 234.1 162.8 247.7L173 259.9C184.5 273.8 197.1 286.7 210.4 298.6C237.9 268.2 259.6 232.5 273.9 193.2L274.4 192L64.1 192C46.3 192 32 177.7 32 160C32 142.3 46.3 128 64 128L160 128L160 96C160 78.3 174.3 64 192 64zM448 334.8L397.7 448L498.3 448L448 334.8z"/></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View file

@ -6,17 +6,74 @@ tabs:
columns:
- width: 1/2
sections:
mediaSection:
identification:
type: fields
fields:
vue3DSection:
type: files
label: Vue 3D
multiple: false
layout: cards
gallerySection:
type: files
label: Galerie
layout: cards
technique:
type: text
label: Technique principale
category:
type: text
label: Catégorie
material:
type: text
label: Matériau
period:
type: text
label: Période / Siècle
country:
type: text
label: Pays
region:
type: text
label: Région
- width: 1/2
sections:
metadata:
type: fields
fields:
cardAuthor:
type: text
label: Auteur de la fiche
partners:
type: textarea
label: Partenaires
datePublication:
type: date
label: Date de publication
dateUpdate:
type: date
label: Date de mise à jour
partnerLink:
type: url
label: Lien vers la fiche partenaire
- width: 1/1
sections:
textSection:
type: fields
fields:
text:
type: writer
label: Description
media:
label: Médias
sections:
mediaSection:
type: fields
fields:
objFile:
type: files
label: Vue 3D
multiple: false
layout: cards
help: Fichier .obj
accept:
extension: obj
gallery:
type: files
label: Galerie
layout: cards
files: tabs/files
seo: seo/page

View file

@ -1,8 +1,29 @@
<!--
- titre
- date
- image
- tags (cf. assets/materials/taxinomie.png)
- début description ?
- auteur de la fiche ?
-->
<?php /** @var \Kirby\Cms\Page $card */ ?>
<article class="piece-card">
<figure class="card-image">
<?php if ($image = $card->image()): ?>
<img src="<?= $image->url() ?>" alt="<?= $image->alt()->or($card->title()) ?>">
<?php endif ?>
</figure>
<div class="card-body">
<h2 class="card-name"><?= $card->title() ?></h2>
<div class="meta-list-tags">
<?php if ($card->technique()->isNotEmpty()): ?>
<div class="meta-tag is-selected"><?= $card->technique() ?></div>
<?php endif ?>
<?php if ($card->category()->isNotEmpty()): ?>
<div class="meta-tag"><?= $card->category() ?></div>
<?php endif ?>
<?php if ($card->country()->isNotEmpty()): ?>
<div class="meta-tag country"><?= $card->country() ?></div>
<?php endif ?>
<?php if ($card->period()->isNotEmpty()): ?>
<div class="meta-tag"><?= $card->period() ?></div>
<?php endif ?>
<?php if ($card->material()->isNotEmpty()): ?>
<div class="meta-tag"><?= $card->material() ?></div>
<?php endif ?>
</div>
</div>
<a href="<?= $card->url() ?>" class="link-block"></a>
</article>

View file

@ -1,4 +1,14 @@
<footer class="site-footer">
<span class="footer-logo">CERAMIQ+</span>
<div class="footer-links">
<a href="#">Mentions légales</a>
<a href="#">RGPD</a>
<a href="#">Contact</a>
</div>
</footer>
<?php snippet('seo/schemas'); ?>
<script src="<?= url('assets/js/script.js') ?>"></script>
<?php snippet('seo/schemas') ?>
</body>
</html>
</html>

View file

@ -1,10 +1,60 @@
<!DOCTYPE html>
<html lang="en">
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<?php snippet('seo/head'); ?>
<title><?= $page->title() ?> — CERAMIC+</title>
<link rel="preload" as="font" type="font/woff2" crossorigin href="<?= url('assets/fonts/OpenSans/OpenSans-VariableFont_wdth,wght.woff2') ?>">
<link rel="preload" as="font" type="font/woff2" crossorigin href="<?= url('assets/fonts/OpenSans/OpenSans-Italic-VariableFont_wdth,wght.woff2') ?>">
<link rel="preload" as="font" type="font/woff2" crossorigin href="<?= url('assets/fonts/Volkhov/Volkhov-Regular.woff2') ?>">
<link rel="preload" as="font" type="font/woff2" crossorigin href="<?= url('assets/fonts/Volkhov/Volkhov-Italic.woff2') ?>">
<link rel="preload" as="font" type="font/woff2" crossorigin href="<?= url('assets/fonts/Volkhov/Volkhov-Bold.woff2') ?>">
<link rel="preload" as="font" type="font/woff2" crossorigin href="<?= url('assets/fonts/Volkhov/Volkhov-BoldItalic.woff2') ?>">
<link rel="stylesheet" href="<?= url('assets/css/main.css') ?>">
<link rel="stylesheet" href="<?= url('assets/css/object.css') ?>">
<?php snippet('seo/head') ?>
</head>
<body>
<?php snippet('nav') ?>
<header class="site-header">
<a href="<?= $site->homePage()->url() ?>" class="site-logo">
<img src="<?= url('assets/logo-ceramic.png') ?>" alt="CERAMIC+">
</a>
<nav class="header-nav">
<ul>
<li>Bibliothèque</li>
<li>Écosystème</li>
<li>Évènements</li>
</ul>
</nav>
<div class="header-actions">
<div class="search-wrap">
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<circle cx="11" cy="11" r="8"/><path d="m21 21-4.35-4.35"/>
</svg>
<input type="text" placeholder="Rechercher une publication…">
</div>
<div class="lang-select-wrap">
<span class="icon"><img src="<?= url('assets/svg/lang.svg') ?>" alt=""></span>
<select class="lang-select">
<option value="fr" selected>Français</option>
<option value="en">English</option>
<option value="es">Español</option>
<option value="pt">Português</option>
</select>
</div>
<button class="btn-account btn-account--primary">
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/>
</svg>
Se connecter
</button>
</div>
</header>

View file

@ -1,4 +1,39 @@
<!--
- logo
- menu
-->
<nav class="obj-nav">
<a href="<?= $page->parent() ? $page->parent()->url() : $site->homePage()->url() ?>" class="obj-back">
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<polyline points="15 18 9 12 15 6"/>
</svg>
Retour aux résultats
</a>
<div class="obj-nav-context">
<?php if ($page->parent() && $page->parent()->isNot($site->homePage())): ?>
<span class="obj-nav-path">
<a href="<?= $page->parent()->url() ?>"><?= $page->parent()->title() ?></a>
</span>
<?php endif ?>
</div>
<div class="obj-nav-arrows">
<?php $prev = $page->prevListed() ?>
<<?= $prev ? 'a href="' . $prev->url() . '"' : 'button disabled' ?> class="obj-arrow" title="Fiche précédente">
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<polyline points="15 18 9 12 15 6"/>
</svg>
</<?= $prev ? 'a' : 'button' ?>>
<?php
$siblings = $page->parent() ? $page->parent()->children()->listed() : $site->children()->listed();
$position = $siblings->indexOf($page) + 1;
$total = $siblings->count();
?>
<span class="obj-position"><?= $position ?> / <?= $total ?></span>
<?php $next = $page->nextListed() ?>
<<?= $next ? 'a href="' . $next->url() . '"' : 'button disabled' ?> class="obj-arrow" title="Fiche suivante">
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<polyline points="9 18 15 12 9 6"/>
</svg>
</<?= $next ? 'a' : 'button' ?>>
</div>
</nav>

View file

@ -1,2 +1,190 @@
<?php snippet('header') ?>
<?php snippet('footer') ?>
<?php snippet('nav') ?>
<div class="obj-wrap">
<header class="obj-header">
<div>
<h1 class="obj-title"><?= $page->title() ?></h1>
<div class="meta-list-tags" style="margin-top:10px">
<?php if ($page->technique()->isNotEmpty()): ?>
<div class="meta-tag technique"><?= $page->technique() ?></div>
<?php endif ?>
<?php if ($page->category()->isNotEmpty()): ?>
<div class="meta-tag"><?= $page->category() ?></div>
<?php endif ?>
<?php if ($page->country()->isNotEmpty()): ?>
<div class="meta-tag country"><?= $page->country() ?></div>
<?php endif ?>
<?php if ($page->material()->isNotEmpty()): ?>
<div class="meta-tag"><?= $page->material() ?></div>
<?php endif ?>
<?php if ($page->period()->isNotEmpty()): ?>
<div class="meta-tag"><?= $page->period() ?></div>
<?php endif ?>
</div>
</div>
<div class="obj-header-actions">
<button class="btn-action" onclick="window.print()">
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<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>
Imprimer
</button>
</div>
</header>
<div class="obj-body">
<section class="obj-media">
<div class="media-viewer">
<div class="media-viewer-inner">
<svg width="52" height="52" viewBox="0 0 24 24" fill="none" stroke="#111" stroke-width="1">
<path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"/>
<polyline points="3.27 6.96 12 12.01 20.73 6.96"/><line x1="12" y1="22.08" x2="12" y2="12"/>
</svg>
<span class="media-type-label">Rendu 3D interactif</span>
<span class="media-hint">Glisser pour faire pivoter · Molette pour zoomer · Double-clic pour recentrer</span>
</div>
<div class="media-controls">
<button class="ctrl-btn" title="Réinitialiser la vue">
<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<polyline points="1 4 1 10 7 10"/>
<path d="M3.51 15a9 9 0 1 0 .49-4.75"/>
</svg>
</button>
<button class="ctrl-btn" title="Zoom avant">
<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/>
<line x1="11" y1="8" x2="11" y2="14"/><line x1="8" y1="11" x2="14" y2="11"/>
</svg>
</button>
<button class="ctrl-btn" title="Zoom arrière">
<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/>
<line x1="8" y1="11" x2="14" y2="11"/>
</svg>
</button>
<button class="ctrl-btn ctrl-btn--sep" title="Plein écran">
<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<polyline points="15 3 21 3 21 9"/><polyline points="9 21 3 21 3 15"/>
<line x1="21" y1="3" x2="14" y2="10"/><line x1="3" y1="21" x2="10" y2="14"/>
</svg>
</button>
</div>
</div>
<?php $gallery = $page->gallery()->toFiles() ?>
<?php if ($gallery->count()): ?>
<div class="media-thumbs">
<div class="thumb thumb--3d is-active">
<svg class="thumb-icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#111" stroke-width="1.5">
<path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"/>
<polyline points="3.27 6.96 12 12.01 20.73 6.96"/><line x1="12" y1="22.08" x2="12" y2="12"/>
</svg>
<span class="thumb-label">3D</span>
</div>
<?php foreach ($gallery as $i => $img): ?>
<div class="thumb">
<span class="thumb-label">IMG <?= $i + 1 ?></span>
</div>
<?php endforeach ?>
</div>
<?php endif ?>
</section>
<aside class="obj-info">
<dl class="info-list">
<?php if ($page->country()->isNotEmpty() || $page->region()->isNotEmpty()): ?>
<div class="info-row">
<dt>Pays / Région</dt>
<dd>
<?= $page->country() ?>
<?php if ($page->region()->isNotEmpty()): ?>
<br><span class="info-sub"><?= $page->region() ?></span>
<?php endif ?>
</dd>
</div>
<hr class="info-divider">
<?php endif ?>
<?php if ($page->partners()->isNotEmpty()): ?>
<div class="info-row">
<dt>Partenaires</dt>
<dd><?= $page->partners()->kt() ?></dd>
</div>
<hr class="info-divider">
<?php endif ?>
<?php if ($page->cardAuthor()->isNotEmpty()): ?>
<div class="info-row">
<dt>Auteur de la fiche</dt>
<dd><?= $page->cardAuthor() ?></dd>
</div>
<hr class="info-divider">
<?php endif ?>
<?php if ($page->datePublication()->isNotEmpty()): ?>
<div class="info-row">
<dt>Date de publication</dt>
<dd>
<?= $page->datePublication()->toDate('d F Y') ?>
<?php if ($page->dateUpdate()->isNotEmpty()): ?>
<br><span class="info-sub">Mise à jour : <?= $page->dateUpdate()->toDate('d F Y') ?></span>
<?php endif ?>
</dd>
</div>
<hr class="info-divider">
<?php endif ?>
<?php if ($page->partnerLink()->isNotEmpty()): ?>
<div class="info-row">
<dt>Lien vers la fiche partenaire</dt>
<dd>
<a href="<?= $page->partnerLink() ?>" target="_blank" rel="noopener">
<?= $page->partnerLink() ?>
</a>
</dd>
</div>
<?php endif ?>
</dl>
<button class="btn-contact-cta">
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"/>
<polyline points="22,6 12,13 2,6"/>
</svg>
Contacter l'auteur de la fiche
</button>
</aside>
</div>
<?php if ($page->text()->isNotEmpty()): ?>
<section class="obj-section">
<h2 class="obj-section-title">Description</h2>
<div class="obj-description">
<?= $page->text()->kt() ?>
</div>
</section>
<?php endif ?>
<?php $similar = $page->siblings()->listed()->shuffle()->limit(4) ?>
<?php if ($similar->count()): ?>
<section class="obj-section">
<h2 class="obj-section-title">Pièces similaires</h2>
<div class="obj-related-grid">
<?php foreach ($similar as $card): ?>
<?php snippet('card', ['card' => $card]) ?>
<?php endforeach ?>
</div>
</section>
<?php endif ?>
</div>
<?php snippet('footer') ?>

View file

@ -1,8 +1,135 @@
<?php snippet('header') ?>
<!--
- section recherche / filtres
- grille d'éléments (card.php)
-->
<div class="page-hero">
<h1><?= $page->title() ?></h1>
</div>
<?php snippet('footer') ?>
<div class="section-switcher">
<div class="section-tile active">
<strong class="tile-name">Matériaux</strong>
<ul class="tile-items">
<li class="tile-item-sub active"><a href="#">Terre cuite</a></li>
<li class="tile-item-sub"><a href="#">Porcelaine</a></li>
<li class="tile-item-sub"><a href="#">Faïence</a></li>
<li class="tile-item-sub"><a href="#">Grès</a></li>
<li class="tile-item-sub"><a href="#">Plâtre</a></li>
<li class="tile-item-sub"><a href="#">Silicone</a></li>
<li class="tile-item-sub"><a href="#">Résines</a></li>
</ul>
</div>
<div class="section-tile">
<strong class="tile-name">Techniques traditionnelles</strong>
<ul class="tile-items">
<li class="tile-item-sub"><a href="#">Moulage</a></li>
<li class="tile-item-sub"><a href="#">Coulage</a></li>
<li class="tile-item-sub"><a href="#">Décoration</a></li>
<li class="tile-item-sub"><a href="#">Estampage</a></li>
</ul>
</div>
<div class="section-tile">
<strong class="tile-name">Technologies innovantes</strong>
<ul class="tile-items">
<li class="tile-item-sub"><a href="#">Numérisation 3D</a></li>
<li class="tile-item-sub"><a href="#">Cobots</a></li>
<li class="tile-item-sub"><a href="#">Impression jet d'encre</a></li>
<li class="tile-item-sub"><a href="#">Impression 3D</a></li>
<li class="tile-item-sub"><a href="#">Robocasting</a></li>
<li class="tile-item-sub"><a href="#">Usinage CNC</a></li>
</ul>
</div>
</div>
<div class="catalog-wrap">
<aside class="sidebar">
<p class="sidebar-title">Filtres avancés</p>
<details class="filter-accordion" open>
<summary class="filter-accordion-title">Typologie</summary>
<div class="filter-accordion-body">
<ul class="filter-checkbox-list">
<li><label><input type="checkbox"> Arts de la table</label></li>
<li><label><input type="checkbox"> Carreaux</label></li>
</ul>
</div>
</details>
<hr class="sidebar-divider">
<details class="filter-accordion" open>
<summary class="filter-accordion-title">Tutoriels</summary>
<div class="filter-accordion-body">
<ul class="filter-checkbox-list">
<li><label><input type="checkbox"> Conception d'un moule</label></li>
<li><label><input type="checkbox"> Moulage céramique</label></li>
<li><label><input type="checkbox"> Coulage céramique</label></li>
<li>
<label><input type="checkbox"> Décorations traditionnelles</label>
<ul class="filter-checkbox-list filter-checkbox-list--sub">
<li><label><input type="checkbox"> Au pinceau</label></li>
<li><label><input type="checkbox"> Coulée robotisée</label></li>
<li><label><input type="checkbox"> Émaillage au pinceau</label></li>
</ul>
</li>
</ul>
</div>
</details>
<hr class="sidebar-divider">
<details class="filter-accordion" open>
<summary class="filter-accordion-title">Témoignages</summary>
<div class="filter-accordion-body">
<ul class="filter-checkbox-list">
<li><label><input type="checkbox"> Artisans de la faïence ancienne</label></li>
<li><label><input type="checkbox"> Craft design</label></li>
</ul>
</div>
</details>
<hr class="sidebar-divider">
<details class="filter-accordion" open>
<summary class="filter-accordion-title">Pays</summary>
<div class="filter-accordion-body">
<ul class="filter-checkbox-list">
<li><label><input type="checkbox"> Espagne</label></li>
<li><label><input type="checkbox"> Portugal</label></li>
<li><label><input type="checkbox"> France</label></li>
</ul>
</div>
</details>
<hr class="sidebar-divider">
<button class="btn-reset">Réinitialiser les filtres</button>
</aside>
<main class="catalog-main">
<?php $cards = $page->children()->listed() ?>
<div class="catalog-toolbar">
<div class="toolbar-section">
<span class="toolbar-section-name">Matériaux</span>
<svg width="10" height="10" viewBox="0 0 10 10" fill="none">
<path d="M3 2l3 3-3 3" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
<span class="toolbar-section-sub">Terre cuite</span>
</div>
<div class="num-results">
<p><span><?= $cards->count() ?></span> résultats</p>
</div>
</div>
<div class="active-filters"></div>
<div class="pieces-grid">
<?php foreach ($cards as $card): ?>
<?php snippet('card', ['card' => $card]) ?>
<?php endforeach ?>
</div>
</main>
</div>
<?php snippet('footer') ?>