9966ec3616
- trainings.ts: da 4 a 6 riquadri (One to One, Small Group max 4, Rehab, Holistic Class ex Performance Class, Reformer Class nuova, Coaching ex Fit Remote); anche in Homepage. CTA "Scopri" verso le pagine dettaglio. - services.ts: aggiunte pagine dettaglio rehab/holistic-class/reformer-class con flag grid:false (fuori dalla griglia /services ma raggiungibili come approfondimento dai riquadri Training). Rehab torna consultabile su /services/rehab. - index/[slug] servizi filtrano grid!==false; rimosso redirect /services/rehab. - Footer Training portato a 6 voci con ancore aggiornate; TrainingCards tone-safe. - Foto Reformer dal documento cliente; card Rehab/Holistic/Coaching con immagini placeholder (da confermare). Migrazione DB idempotente per label/meta. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017rUFjLYZ1TZ7DgxwTR5q9K
51 lines
2.7 KiB
Plaintext
51 lines
2.7 KiB
Plaintext
---
|
|
import type { ImageMetadata } from 'astro';
|
|
import { trainings } from '../../data/trainings';
|
|
import T from '../content/T.astro';
|
|
import TImg from '../content/TImg.astro';
|
|
import { t } from '../../lib/content';
|
|
const images = import.meta.glob<{ default: ImageMetadata }>('../../assets/img/training-*.{jpg,png}', { eager: true });
|
|
const imgOf = (name: string) => Object.entries(images).find(([p]) => p.includes(name))?.[1].default;
|
|
const tones = ['taupe', 'tan', 'dark', 'charcoal'];
|
|
// riga 1 (training 0-1): card, foto | riga 2 (training 2-3): foto, card
|
|
const isSwapRow = (i: number) => Math.floor(i / 2) % 2 === 1;
|
|
---
|
|
<section class="tcards">
|
|
{trainings.map((tr, i) => {
|
|
const img = imgOf(tr.image);
|
|
const card = (
|
|
<div class:list={['tcards__cell', `tcards__cell--${tones[i % tones.length]}`]} data-reveal="fade" style={`--reveal-delay:${(i % 2) * 0.15}s`}>
|
|
<T tag={`training.${tr.id}.title`} as="h3" />
|
|
<T tag={`training.${tr.id}.caption`} as="p" />
|
|
<a class="tcards__link" href={tr.cta.href}><T tag="home.training-cards.link-label" as="span" /> →</a>
|
|
</div>
|
|
);
|
|
const photo = img ? (
|
|
<div class="tcards__photo" data-reveal="fade" style={`--reveal-delay:${((i % 2) * 0.15 + 0.1).toFixed(2)}s`}>
|
|
<TImg tag={`training.${tr.id}.image`} src={img} alt={t(`training.${tr.id}.title`)} class="tcards__img" widths={[400, 700]} sizes="(max-width: 767px) 50vw, 25vw" />
|
|
</div>
|
|
) : null;
|
|
return isSwapRow(i) ? <>{photo}{card}</> : <>{card}{photo}</>;
|
|
})}
|
|
</section>
|
|
|
|
<style>
|
|
.tcards { display: grid; grid-template-columns: repeat(4, 1fr); }
|
|
.tcards__cell { padding: 48px 36px; display: flex; flex-direction: column; justify-content: center; aspect-ratio: 1; }
|
|
.tcards__cell--taupe { background: #6b5d5b; }
|
|
.tcards__cell--dark { background: var(--c-dark); }
|
|
.tcards__cell--charcoal { background: #27252a; }
|
|
.tcards__cell--taupe h3, .tcards__cell--taupe p,
|
|
.tcards__cell--dark h3, .tcards__cell--dark p,
|
|
.tcards__cell--charcoal h3, .tcards__cell--charcoal p { color: #efe9e3; }
|
|
.tcards__cell--tan { background: var(--c-accent); }
|
|
.tcards__cell--tan h3, .tcards__cell--tan p { color: #fff; }
|
|
.tcards__cell h3 { text-transform: uppercase; letter-spacing: .12em; }
|
|
.tcards__cell p { font-size: .88rem; }
|
|
.tcards__link { color: #fff; font-family: var(--font-heading); font-size: .7rem; letter-spacing: .2em; text-transform: uppercase; text-decoration: none; margin-top: 18px; }
|
|
.tcards__photo { overflow: hidden; }
|
|
.tcards__img { width: 100%; height: 100%; object-fit: cover; aspect-ratio: 1; transition: transform .5s ease; }
|
|
.tcards__photo:hover .tcards__img { transform: scale(1.06); }
|
|
@media (max-width: 767px) { .tcards { grid-template-columns: repeat(2, 1fr); } }
|
|
</style>
|