Files
InsanityLab-web/src/components/home/TrainingCards.astro
T
Adriano 9966ec3616 Training: 6 riquadri (Rehab, Holistic Class, Reformer Class, Coaching)
- 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
2026-07-11 13:26:58 +02:00

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>