Refonte décors home + texte vert lisible

- home: chapo agrandi, flower-1 collée à gauche, oiseau droite retiré
- oiseau projets lauréats -> bird-3 (plus petit, repositionné)
- frise verte parallax au niveau de la carte projets
- suppression décors footer + système page-decor (code mort inclus)
- /projets: texte à gauche de la carte agrandi en desktop
- texte vert #33ffc4 -> #0c8461 (sidebars, contenus projets, etc.)
- icône dropdown sidebar au même vert que le texte
This commit is contained in:
2026-07-08 15:29:55 +02:00
parent 8e5a0c936e
commit 5adc79ac4b
16 changed files with 129 additions and 186 deletions

View File

@@ -595,88 +595,6 @@
document.body.dataset.colDecorScrollWired = 'true';
}
//
// Décor aléatoire en haut à droite de chaque .fullpage. Tirage
// parmi drawings/ (excluant flower-2 + bird-3 déjà au footer).
// Bas de l'image overlap le haut de l'ancre (20%, sauf flower-3
// à 40% car tige fine). Mobile : ancre = .page-header-outside.
// Largeur par breakpoint.
//
const PAGE_DECOR_POOL = ['bird-1.png', 'bird-2.png', 'flower-1.png', 'flower-3.png'];
const pageDecorState = [];
function pageDecorWidthVw() {
const w = window.innerWidth;
if (w < 1080) return 22; // mobile + tablette
return 10; // desktop
}
function setupPageDecor() {
if (!layoutContainer) return;
layoutContainer.querySelectorAll('.page-decor').forEach(n => n.remove());
pageDecorState.length = 0;
document.querySelectorAll('.fullpage').forEach(col => {
// Exclure les .fullpage situées dans une sidebar (vue projets
// imbriquée). On ne décore que les colonnes de contenu.
if (col.closest('aside')) return;
// Tirage déterministe par colonne : on stocke l'index sur le
// dataset pour qu'un resize ne change pas l'image affichée.
let idx = col.dataset.pageDecorIdx;
if (idx == null) {
idx = Math.floor(Math.random() * PAGE_DECOR_POOL.length);
col.dataset.pageDecorIdx = String(idx);
} else {
idx = parseInt(idx, 10);
}
const img = document.createElement('img');
img.className = 'page-decor';
img.setAttribute('aria-hidden', 'true');
img.setAttribute('alt', '');
img.src = `/themes/erabletheme/assets/drawings/${PAGE_DECOR_POOL[idx]}`;
img.style.cssText = 'position:absolute;width:auto;height:auto;pointer-events:none;z-index:0;';
layoutContainer.appendChild(img);
pageDecorState.push({ img, col });
});
positionPageDecor();
}
function positionPageDecor() {
if (!pageDecorState.length) return;
const lcRect = layoutContainer.getBoundingClientRect();
const lcTopAbs = lcRect.top + window.scrollY;
const lcLeftAbs = lcRect.left + window.scrollX;
const widthVw = pageDecorWidthVw();
const widthPx = (widthVw / 100) * window.innerWidth;
const isMobile = window.innerWidth < 760;
for (const entry of pageDecorState) {
const img = entry.img;
if (!img.naturalWidth) {
img.addEventListener('load', positionPageDecor, { once: true });
continue;
}
const heightPx = widthPx * (img.naturalHeight / img.naturalWidth);
// Mobile : ancre = .page-header-outside (titre/retour) si présent,
// sinon la colonne elle-même.
let anchorEl = entry.col;
if (isMobile) {
const layoutContent = entry.col.closest('.layout-content');
const phOutside = layoutContent && layoutContent.querySelector('.page-header-outside');
if (phOutside) anchorEl = phOutside;
}
const r = anchorEl.getBoundingClientRect();
const anchorTopAbs = r.top + window.scrollY;
const anchorRightAbs = r.right + window.scrollX;
// flower-3 a une tige fine en haut → on la pousse plus dans
// l'ancre (40%) pour qu'elle ne soit pas perdue dans la marge.
const overlapRatio = img.src.includes('flower-3') ? 0.4 : 0.2;
const top = anchorTopAbs + heightPx * overlapRatio - heightPx;
const left = anchorRightAbs - widthPx * 0.7; // 30% dépasse à droite
img.style.width = widthPx + 'px';
img.style.top = (top - lcTopAbs) + 'px';
img.style.left = (left - lcLeftAbs) + 'px';
}
}
//
// Décors home-diapo-{right,left} : ancrés aux bords droit/gauche
// du viewport, leur haut dépassant au-dessus du haut des cards
@@ -747,14 +665,16 @@
}
//
// Décors home-above : flower-1 (gauche) et bird-1 (droite),
// au-dessus des cards, leur bas débordant de `overlap` px sur le
// haut des cards. offsetVw : décalage horizontal vers l'intérieur.
// Décor home-above : flower-1 (gauche), au-dessus des cards, son bas
// débordant de `overlap` px sur le haut des cards. offsetVw décale
// horizontalement : négatif = déborde à gauche du viewport, si bien
// que la fleur semble « sortir de sous » une card. offsetVwDesktop
// (optionnel) surcharge offsetVw à partir de $breakpoint_desktop :
// ici un léger décalage à droite du bouquet en desktop uniquement.
// Pas de parallax.
//
const HOME_ABOVE_CONFIGS = [
{ side: 'left', file: 'drawings/flower-1.png', widthVw: 15, overlap: 40, offsetVw: 8 },
{ side: 'right', file: 'drawings/bird-1.png', widthVw: 15, overlap: 40, offsetVw: 4 },
{ side: 'left', file: 'drawings/flower-1.png', widthVw: 15, overlap: 40, offsetVw: -3, offsetVwDesktop: 0 },
];
const homeAboveState = [];
@@ -770,9 +690,9 @@
img.setAttribute('aria-hidden', 'true');
img.setAttribute('alt', '');
img.src = `/themes/erabletheme/assets/${cfg.file}`;
img.style.cssText = `position:absolute;${cfg.side}:${cfg.offsetVw}vw;width:auto;height:auto;pointer-events:none;z-index:0;`;
img.style.cssText = 'position:absolute;width:auto;height:auto;pointer-events:none;z-index:0;';
layoutContainer.appendChild(img);
homeAboveState.push({ img, widthVw: cfg.widthVw, overlap: cfg.overlap, cardsBox });
homeAboveState.push({ img, side: cfg.side, widthVw: cfg.widthVw, overlap: cfg.overlap, offsetVw: cfg.offsetVw, offsetVwDesktop: cfg.offsetVwDesktop, cardsBox });
}
positionHomeAboveDecor();
}
@@ -793,19 +713,25 @@
const bottomFromLcBottom = (lcTopAbs + lcHeight) - imgBottom;
entry.img.style.width = widthPx + 'px';
entry.img.style.bottom = bottomFromLcBottom + 'px';
// Décalage horizontal responsive : offsetVwDesktop surcharge
// offsetVw à partir de 1080px (léger recentrage du bouquet).
const isDesktop = window.innerWidth >= 1080;
const offsetVw = (isDesktop && entry.offsetVwDesktop != null)
? entry.offsetVwDesktop : entry.offsetVw;
entry.img.style[entry.side] = offsetVw + 'vw';
}
}
//
// Décors home-projet, ancrés au bloc .map-projets :
// - bird-2 en haut à gauche, débordant à gauche du bloc en
// - bird-3 en haut à gauche, débordant à gauche du bloc en
// desktop, ou collé à -3vw du viewport en mobile/tablette.
// - flower-3 collée au bord droit du viewport (tronquée), centre
// vertical à 1/3 depuis le haut du bloc.
// Pas de parallax.
//
const HOME_PROJET_CONFIGS = [
{ file: 'drawings/bird-2.png', widthVw: 15, anchor: 'block-left-top' },
{ file: 'drawings/bird-3.png', widthVw: 11, anchor: 'block-left-top' },
{ file: 'drawings/flower-3.png', widthVw: 7, anchor: 'viewport-right' },
];
const homeProjetState = [];
@@ -849,12 +775,17 @@
const blockHeightPx = bRect.height;
img.style.width = widthPx + 'px';
if (entry.anchor === 'block-left-top') {
// bird-2 remontée de 0.6× sa hauteur au-dessus du bloc.
const top = blockTopAbs - heightPx * 0.6;
// bird-3 remontée de 0.75× sa hauteur au-dessus du bloc,
// puis redescendue de 20px (toutes vues).
const top = blockTopAbs - heightPx * 0.75 + 20;
if (window.innerWidth < 1080) {
img.style.left = '-3vw';
// tablette : collée au bord gauche (léger décalage vers la
// droite par rapport à l'ancien -3vw).
img.style.left = '0';
} else {
img.style.left = (blockLeftAbs - widthPx * 0.5 - lcLeftAbs) + 'px';
// desktop : moins de débord à gauche du bloc (0.25 au lieu
// de 0.5) → l'oiseau est décalé vers la droite.
img.style.left = (blockLeftAbs - widthPx * 0.25 - lcLeftAbs) + 'px';
}
img.style.top = (top - lcTopAbs) + 'px';
img.style.right = '';
@@ -902,6 +833,34 @@
}
}
// Frise verte fluo à gauche, au niveau de la carte des projets
// lauréats. Injectée comme .bgImg dans #background (donc animée par
// Rellax comme les autres frises), dimensionnée en vh comme elles
// (largeur auto → pas d'effet « zoomé »), positionnée au centre
// vertical du bloc .map-projets. Doit être appelée AVANT initRellax.
function setupMapDecor() {
if (!bgRoot) return;
bgRoot.querySelectorAll('.map-decor').forEach(n => n.remove());
const block = document.querySelector('.map-projets');
if (!block) return;
const bgRect = bgRoot.getBoundingClientRect();
const bgTopAbs = bgRect.top + window.scrollY;
const bRect = block.getBoundingClientRect();
const blockCenterAbs = bRect.top + window.scrollY + bRect.height / 2;
const img = document.createElement('img');
// .bgImg → capté par Rellax ; .decor-left → collé à left:0 ;
// .map-decor → sélecteur de nettoyage.
img.className = 'bgImg decor-left map-decor';
img.setAttribute('data-rellax-speed', '-3');
img.setAttribute('aria-hidden', 'true');
img.setAttribute('alt', '');
img.src = '/themes/erabletheme/assets/new-bg-shapes/left-3.png';
// height en vh (comme les frises) ; top centré sur la carte.
img.style.cssText = 'position:absolute;left:0;width:auto;height:32vh;'
+ 'pointer-events:none;top:' + (blockCenterAbs - bgTopAbs - (0.16 * window.innerHeight)) + 'px;';
bgRoot.appendChild(img);
}
function initRellax() {
if (rellax) { try { rellax.destroy(); } catch (e) { /* noop */ } }
rellax = new Rellax('.bgImg', { wrapper: 'body' });
@@ -923,7 +882,7 @@
setupHomeDiapoDecor();
setupHomeAboveDecor();
setupHomeProjetDecor();
setupPageDecor();
setupMapDecor();
initRellax();
});
@@ -938,7 +897,7 @@
setupHomeDiapoDecor();
setupHomeAboveDecor();
setupHomeProjetDecor();
setupPageDecor();
setupMapDecor();
initRellax();
}, 200);
});