feat(layout): shared tiled-panel page pattern across secondary pages

Calibrate all non-home pages to one layout language matching the Wix
design: the celtic-knot tile becomes the page background (shown in the
gutters), content floats in a single near-black rounded panel, and cards
inside are plain cards.

- Add PageShell (floating bg-panel card), PageSection (plain content
  block), and PageHero (centered hero; left grid w/ aside image) under
  src/components/layout/.
- Tile the body background and add a --panel token; the home page's
  fixed landscape sits above this layer, so home is unchanged.
- Re-skin the 11 secondary views through these primitives and unify
  headings to the font-display uppercase idiom.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Padreug 2026-06-14 16:43:27 +02:00
commit fe2a6912ce
15 changed files with 459 additions and 408 deletions

View file

@ -0,0 +1,58 @@
<script setup lang="ts">
// Top-of-page hero, the first block inside PageShell's panel. Centered to
// match the Wix layout; falls back to a left-aligned two-column grid when an
// `aside` slot (e.g. a hero image) is supplied. Title uses the Aboreto
// display face in the home page's uppercase / wide-tracking idiom.
import { useSlots } from 'vue'
withDefaults(
defineProps<{
kicker?: string
title: string
lede?: string
}>(),
{},
)
const slots = useSlots()
const hasAside = () => !!slots.aside
</script>
<template>
<section class="px-6 pt-16 pb-12 sm:px-10 lg:px-16 lg:pt-24 lg:pb-16">
<div
v-if="hasAside()"
class="grid items-center gap-10 lg:grid-cols-2 lg:gap-14"
>
<div class="max-w-3xl">
<p v-if="kicker" class="font-display text-xs uppercase tracking-[0.3em] text-accent">
{{ kicker }}
</p>
<h1 class="mt-3 font-display text-4xl uppercase leading-tight tracking-wider md:text-5xl">
{{ title }}
</h1>
<p v-if="lede" class="mt-6 max-w-prose text-lg leading-relaxed text-foreground/90">
{{ lede }}
</p>
<slot />
</div>
<slot name="aside" />
</div>
<div v-else class="mx-auto max-w-3xl text-center">
<h1 class="font-display text-4xl uppercase leading-tight tracking-wider md:text-6xl">
{{ title }}
</h1>
<p
v-if="kicker"
class="mt-6 font-display text-2xl uppercase tracking-wider text-accent md:text-3xl"
>
{{ kicker }}
</p>
<p v-if="lede" class="mx-auto mt-6 max-w-2xl text-base leading-relaxed text-foreground/90 md:text-lg">
{{ lede }}
</p>
<slot />
</div>
</section>
</template>

View file

@ -0,0 +1,33 @@
<script setup lang="ts">
// A content block inside PageShell's panel. No background of its own the
// near-black panel shows through; cards/images provide the contrast. Just
// constrains width and supplies the shared vertical rhythm and gutter.
withDefaults(
defineProps<{
/** Inner content max-width. `wide` fills the panel. */
width?: 'prose' | 'narrow' | 'wide'
/** Vertical rhythm. */
padding?: 'default' | 'compact'
}>(),
{ width: 'wide', padding: 'default' },
)
const widthClass = {
prose: 'max-w-3xl',
narrow: 'max-w-4xl',
wide: 'max-w-none',
} as const
const padClass = {
default: 'py-16 lg:py-20',
compact: 'py-12 lg:py-14',
} as const
</script>
<template>
<section class="px-6 sm:px-10 lg:px-16" :class="padClass[padding]">
<div :class="[widthClass[width], width !== 'wide' ? 'mx-auto' : '']">
<slot />
</div>
</section>
</template>

View file

@ -0,0 +1,14 @@
<script setup lang="ts">
// The floating content panel: a near-black rounded card that sits on the
// tiled celtic-knot page background, leaving a gutter of tile visible around
// it. Wrap every secondary page's content in this so they share the home
// page / Wix layout language. Sections go inside as plain blocks.
</script>
<template>
<div class="px-3 pt-3 pb-6 sm:px-4 sm:pt-4 lg:px-6">
<div class="mx-auto max-w-6xl overflow-hidden rounded-3xl bg-panel shadow-2xl">
<slot />
</div>
</div>
</template>

View file

@ -25,6 +25,8 @@
--border: hsl(151 50% 18%); --border: hsl(151 50% 18%);
--input: hsl(151 50% 18%); --input: hsl(151 50% 18%);
--ring: hsl(43 64% 50%); --ring: hsl(43 64% 50%);
/* Near-black green of the content panel that floats on the tiled bg. */
--panel: hsl(151 55% 4%);
--radius: 0.5rem; --radius: 0.5rem;
} }
@ -48,6 +50,7 @@
--border: hsl(151 50% 15%); --border: hsl(151 50% 15%);
--input: hsl(151 50% 15%); --input: hsl(151 50% 15%);
--ring: hsl(43 64% 52%); --ring: hsl(43 64% 52%);
--panel: hsl(151 55% 3%);
} }
@theme inline { @theme inline {
@ -70,6 +73,7 @@
--color-border: var(--border); --color-border: var(--border);
--color-input: var(--input); --color-input: var(--input);
--color-ring: var(--ring); --color-ring: var(--ring);
--color-panel: var(--panel);
--radius-lg: var(--radius); --radius-lg: var(--radius);
--radius-md: calc(var(--radius) - 2px); --radius-md: calc(var(--radius) - 2px);
--radius-sm: calc(var(--radius) - 4px); --radius-sm: calc(var(--radius) - 4px);
@ -85,6 +89,12 @@
} }
body { body {
@apply bg-background text-foreground; @apply bg-background text-foreground;
/* Celtic-knot tile is the page background; it shows in the gutters
around the floating content panel (see PageShell). The home page's
fixed landscape image sits above this layer, so home is unaffected. */
background-image: url('./assets/section-tile.webp');
background-repeat: repeat;
background-position: center top;
font-family: var(--font-sans); font-family: var(--font-sans);
font-weight: 300; font-weight: 300;
} }

View file

@ -4,6 +4,9 @@ import { RouterLink } from 'vue-router'
import { Button } from '@/components/ui/button' import { Button } from '@/components/ui/button'
import { Card, CardContent } from '@/components/ui/card' import { Card, CardContent } from '@/components/ui/card'
import { Badge } from '@/components/ui/badge' import { Badge } from '@/components/ui/badge'
import PageHero from '@/components/layout/PageHero.vue'
import PageSection from '@/components/layout/PageSection.vue'
import PageShell from '@/components/layout/PageShell.vue'
const { t, tm, rt } = useI18n() const { t, tm, rt } = useI18n()
@ -59,29 +62,21 @@ const exteriorItems = tm('accommodation.exterior.items') as string[]
</script> </script>
<template> <template>
<div> <PageShell>
<!-- Hero --> <!-- Hero -->
<section class="border-b border-border bg-secondary/40"> <PageHero
<div class="mx-auto max-w-4xl px-4 py-16 lg:px-6 lg:py-20"> :kicker="t('accommodation.hero.kicker')"
<p class="text-xs uppercase tracking-[0.2em] text-accent"> :title="t('accommodation.hero.title')"
{{ t('accommodation.hero.kicker') }} :lede="t('accommodation.hero.lede')"
</p> />
<h1 class="mt-3 font-serif text-5xl font-semibold leading-tight tracking-tight md:text-6xl">
{{ t('accommodation.hero.title') }}
</h1>
<p class="mt-6 max-w-prose text-lg leading-relaxed text-foreground/90">
{{ t('accommodation.hero.lede') }}
</p>
</div>
</section>
<!-- Rooms --> <!-- Rooms -->
<section class="mx-auto max-w-7xl px-4 py-16 lg:px-6"> <PageSection>
<div class="max-w-3xl"> <div class="max-w-3xl">
<h2 class="font-serif text-3xl font-semibold tracking-tight"> <h2 class="font-display text-2xl uppercase tracking-wider md:text-3xl">
{{ t('accommodation.rooms.title') }} {{ t('accommodation.rooms.title') }}
</h2> </h2>
<p class="mt-3 text-muted-foreground">{{ t('accommodation.rooms.subtitle') }}</p> <p class="mt-3 text-foreground/80">{{ t('accommodation.rooms.subtitle') }}</p>
</div> </div>
<ul class="mt-8 grid gap-6 md:grid-cols-2 lg:grid-cols-3"> <ul class="mt-8 grid gap-6 md:grid-cols-2 lg:grid-cols-3">
<li v-for="room in rooms" :key="room.key"> <li v-for="room in rooms" :key="room.key">
@ -94,7 +89,7 @@ const exteriorItems = tm('accommodation.exterior.items') as string[]
/> />
<CardContent class="p-5 pt-5"> <CardContent class="p-5 pt-5">
<div class="flex items-baseline justify-between gap-3"> <div class="flex items-baseline justify-between gap-3">
<h3 class="font-serif text-xl font-semibold"> <h3 class="font-display text-lg uppercase tracking-wider">
{{ t(`accommodation.rooms.${room.key}.name`) }} {{ t(`accommodation.rooms.${room.key}.name`) }}
</h3> </h3>
<Badge <Badge
@ -115,16 +110,15 @@ const exteriorItems = tm('accommodation.exterior.items') as string[]
</Card> </Card>
</li> </li>
</ul> </ul>
</section> </PageSection>
<!-- Cabins --> <!-- Cabins -->
<section class="border-y border-border bg-card"> <PageSection>
<div class="mx-auto max-w-7xl px-4 py-16 lg:px-6">
<div class="max-w-3xl"> <div class="max-w-3xl">
<h2 class="font-serif text-3xl font-semibold tracking-tight"> <h2 class="font-display text-2xl uppercase tracking-wider md:text-3xl">
{{ t('accommodation.cabins.title') }} {{ t('accommodation.cabins.title') }}
</h2> </h2>
<p class="mt-3 text-muted-foreground">{{ t('accommodation.cabins.subtitle') }}</p> <p class="mt-3 text-foreground/80">{{ t('accommodation.cabins.subtitle') }}</p>
</div> </div>
<ul class="mt-8 grid gap-6 md:grid-cols-3"> <ul class="mt-8 grid gap-6 md:grid-cols-3">
<li v-for="cabin in cabins" :key="cabin.key"> <li v-for="cabin in cabins" :key="cabin.key">
@ -136,7 +130,7 @@ const exteriorItems = tm('accommodation.exterior.items') as string[]
loading="lazy" loading="lazy"
/> />
<div class="flex items-baseline justify-between gap-3 p-5"> <div class="flex items-baseline justify-between gap-3 p-5">
<h3 class="font-serif text-xl font-semibold"> <h3 class="font-display text-lg uppercase tracking-wider">
{{ t(`accommodation.cabins.${cabin.key}`) }} {{ t(`accommodation.cabins.${cabin.key}`) }}
</h3> </h3>
<Badge <Badge
@ -149,16 +143,15 @@ const exteriorItems = tm('accommodation.exterior.items') as string[]
</Card> </Card>
</li> </li>
</ul> </ul>
</div> </PageSection>
</section>
<!-- Exterior, coming next --> <!-- Exterior, coming next -->
<section class="mx-auto max-w-7xl px-4 py-16 lg:px-6"> <PageSection>
<div class="max-w-3xl"> <div class="max-w-3xl">
<h2 class="font-serif text-3xl font-semibold tracking-tight"> <h2 class="font-display text-2xl uppercase tracking-wider md:text-3xl">
{{ t('accommodation.exterior.title') }} {{ t('accommodation.exterior.title') }}
</h2> </h2>
<p class="mt-3 text-muted-foreground">{{ t('accommodation.exterior.subtitle') }}</p> <p class="mt-3 text-foreground/80">{{ t('accommodation.exterior.subtitle') }}</p>
</div> </div>
<ul class="mt-8 grid gap-4 sm:grid-cols-2 lg:grid-cols-3"> <ul class="mt-8 grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
<li v-for="(item, i) in exteriorItems" :key="i"> <li v-for="(item, i) in exteriorItems" :key="i">
@ -167,11 +160,11 @@ const exteriorItems = tm('accommodation.exterior.items') as string[]
</Card> </Card>
</li> </li>
</ul> </ul>
</section> </PageSection>
<!-- CTAs --> <!-- CTAs -->
<section class="border-t border-border bg-secondary/30"> <PageSection padding="compact">
<div class="mx-auto flex max-w-7xl flex-wrap items-center gap-3 px-4 py-12 lg:px-6"> <div class="flex flex-wrap items-center gap-3">
<Button as-child> <Button as-child>
<a href="mailto:chateaudufaune@ariege.io?subject=R%C3%A9servation%20%E2%80%94%20Ch%C3%A2teau%20du%20Faune"> <a href="mailto:chateaudufaune@ariege.io?subject=R%C3%A9servation%20%E2%80%94%20Ch%C3%A2teau%20du%20Faune">
{{ t('accommodation.ctaReserve') }} {{ t('accommodation.ctaReserve') }}
@ -181,6 +174,6 @@ const exteriorItems = tm('accommodation.exterior.items') as string[]
<RouterLink to="/reservations"> {{ t('accommodation.ctaBack') }}</RouterLink> <RouterLink to="/reservations"> {{ t('accommodation.ctaBack') }}</RouterLink>
</Button> </Button>
</div> </div>
</section> </PageSection>
</div> </PageShell>
</template> </template>

View file

@ -2,6 +2,9 @@
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import { RouterLink } from 'vue-router' import { RouterLink } from 'vue-router'
import { Card } from '@/components/ui/card' import { Card } from '@/components/ui/card'
import PageHero from '@/components/layout/PageHero.vue'
import PageSection from '@/components/layout/PageSection.vue'
import PageShell from '@/components/layout/PageShell.vue'
const { t } = useI18n() const { t } = useI18n()
@ -13,35 +16,27 @@ const pillars = [
</script> </script>
<template> <template>
<div> <PageShell>
<!-- Hero --> <!-- Hero -->
<section class="border-b border-border bg-secondary/40"> <PageHero
<div class="mx-auto max-w-4xl px-4 py-16 lg:px-6 lg:py-24"> :kicker="t('concept.hero.kicker')"
<p class="text-xs uppercase tracking-[0.2em] text-accent"> :title="t('concept.hero.title')"
{{ t('concept.hero.kicker') }} :lede="t('concept.hero.lede')"
</p> />
<h1 class="mt-3 font-serif text-5xl font-semibold leading-tight tracking-tight md:text-6xl">
{{ t('concept.hero.title') }}
</h1>
<p class="mt-6 max-w-prose text-lg leading-relaxed text-foreground/90">
{{ t('concept.hero.lede') }}
</p>
</div>
</section>
<!-- Mission --> <!-- Mission -->
<section class="mx-auto max-w-4xl px-4 py-16 lg:px-6"> <PageSection width="narrow">
<h2 class="font-serif text-3xl font-semibold tracking-tight"> <h2 class="font-display text-2xl uppercase tracking-wider md:text-3xl">
{{ t('concept.mission.title') }} {{ t('concept.mission.title') }}
</h2> </h2>
<p class="mt-5 max-w-prose text-base leading-relaxed"> <p class="mt-5 max-w-prose text-base leading-relaxed">
{{ t('concept.mission.body') }} {{ t('concept.mission.body') }}
</p> </p>
</section> </PageSection>
<!-- Land art & residencies --> <!-- Land art & residencies -->
<section class="bg-card border-y border-border"> <PageSection>
<div class="mx-auto grid max-w-7xl gap-10 px-4 py-16 lg:grid-cols-2 lg:gap-14 lg:px-6"> <div class="grid items-center gap-10 lg:grid-cols-2 lg:gap-14">
<img <img
src="https://static.wixstatic.com/media/11062b_7c683da5bcbd44d7b0d2ddbaf4693625~mv2.jpg" src="https://static.wixstatic.com/media/11062b_7c683da5bcbd44d7b0d2ddbaf4693625~mv2.jpg"
alt="" alt=""
@ -49,7 +44,7 @@ const pillars = [
loading="lazy" loading="lazy"
/> />
<div> <div>
<h2 class="font-serif text-3xl font-semibold tracking-tight"> <h2 class="font-display text-2xl uppercase tracking-wider md:text-3xl">
{{ t('concept.landArt.title') }} {{ t('concept.landArt.title') }}
</h2> </h2>
<p class="mt-5 max-w-prose leading-relaxed">{{ t('concept.landArt.body') }}</p> <p class="mt-5 max-w-prose leading-relaxed">{{ t('concept.landArt.body') }}</p>
@ -61,13 +56,13 @@ const pillars = [
</RouterLink> </RouterLink>
</div> </div>
</div> </div>
</section> </PageSection>
<!-- Farmstand & boutique --> <!-- Farmstand & boutique -->
<section class="mx-auto max-w-7xl px-4 py-16 lg:px-6"> <PageSection>
<div class="grid gap-10 lg:grid-cols-2 lg:gap-14"> <div class="grid items-center gap-10 lg:grid-cols-2 lg:gap-14">
<div class="order-2 lg:order-1"> <div class="order-2 lg:order-1">
<h2 class="font-serif text-3xl font-semibold tracking-tight"> <h2 class="font-display text-2xl uppercase tracking-wider md:text-3xl">
{{ t('concept.farmstand.title') }} {{ t('concept.farmstand.title') }}
</h2> </h2>
<p class="mt-5 max-w-prose leading-relaxed">{{ t('concept.farmstand.body') }}</p> <p class="mt-5 max-w-prose leading-relaxed">{{ t('concept.farmstand.body') }}</p>
@ -85,20 +80,19 @@ const pillars = [
loading="lazy" loading="lazy"
/> />
</div> </div>
</section> </PageSection>
<!-- Slow farming --> <!-- Slow farming -->
<section class="bg-secondary/30 border-y border-border"> <PageSection>
<div class="mx-auto max-w-7xl px-4 py-16 lg:px-6">
<div class="max-w-3xl"> <div class="max-w-3xl">
<h2 class="font-serif text-3xl font-semibold tracking-tight"> <h2 class="font-display text-2xl uppercase tracking-wider md:text-3xl">
{{ t('concept.slowFarming.title') }} {{ t('concept.slowFarming.title') }}
</h2> </h2>
<p class="mt-3 text-muted-foreground">{{ t('concept.slowFarming.body') }}</p> <p class="mt-3 text-foreground/80">{{ t('concept.slowFarming.body') }}</p>
</div> </div>
<div class="mt-8 grid gap-6 md:grid-cols-3"> <div class="mt-8 grid gap-6 md:grid-cols-3">
<Card v-for="p in pillars" :key="p.key" class="p-6"> <Card v-for="p in pillars" :key="p.key" class="p-6">
<h3 class="font-serif text-xl font-semibold"> <h3 class="font-display text-lg uppercase tracking-wider">
{{ t(`concept.slowFarming.${p.key}Title`) }} {{ t(`concept.slowFarming.${p.key}Title`) }}
</h3> </h3>
<p class="mt-3 text-sm leading-relaxed text-foreground/85"> <p class="mt-3 text-sm leading-relaxed text-foreground/85">
@ -106,12 +100,11 @@ const pillars = [
</p> </p>
</Card> </Card>
</div> </div>
</div> </PageSection>
</section>
<!-- Events in nature --> <!-- Events in nature -->
<section class="mx-auto max-w-7xl px-4 py-16 lg:px-6"> <PageSection>
<div class="grid gap-10 lg:grid-cols-2 lg:gap-14"> <div class="grid items-center gap-10 lg:grid-cols-2 lg:gap-14">
<img <img
src="https://static.wixstatic.com/media/11062b_a56b905cae7c424c84cbaa1677d59ec5~mv2.jpg" src="https://static.wixstatic.com/media/11062b_a56b905cae7c424c84cbaa1677d59ec5~mv2.jpg"
alt="" alt=""
@ -119,7 +112,7 @@ const pillars = [
loading="lazy" loading="lazy"
/> />
<div> <div>
<h2 class="font-serif text-3xl font-semibold tracking-tight"> <h2 class="font-display text-2xl uppercase tracking-wider md:text-3xl">
{{ t('concept.events.title') }} {{ t('concept.events.title') }}
</h2> </h2>
<p class="mt-5 max-w-prose leading-relaxed">{{ t('concept.events.body') }}</p> <p class="mt-5 max-w-prose leading-relaxed">{{ t('concept.events.body') }}</p>
@ -131,6 +124,6 @@ const pillars = [
</RouterLink> </RouterLink>
</div> </div>
</div> </div>
</section> </PageSection>
</div> </PageShell>
</template> </template>

View file

@ -4,6 +4,9 @@ import { RouterLink } from 'vue-router'
import { Button } from '@/components/ui/button' import { Button } from '@/components/ui/button'
import { Card, CardContent } from '@/components/ui/card' import { Card, CardContent } from '@/components/ui/card'
import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert' import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'
import PageHero from '@/components/layout/PageHero.vue'
import PageSection from '@/components/layout/PageSection.vue'
import PageShell from '@/components/layout/PageShell.vue'
const { t } = useI18n() const { t } = useI18n()
@ -37,18 +40,12 @@ const events = [
</script> </script>
<template> <template>
<div> <PageShell>
<section class="border-b border-border bg-secondary/40"> <PageHero
<div class="mx-auto max-w-4xl px-4 py-16 lg:px-6 lg:py-20"> :kicker="t('events.page.kicker')"
<p class="text-xs uppercase tracking-[0.2em] text-accent"> :title="t('events.page.title')"
{{ t('events.page.kicker') }} :lede="t('events.page.lede')"
</p> >
<h1 class="mt-3 font-serif text-5xl font-semibold leading-tight tracking-tight md:text-6xl">
{{ t('events.page.title') }}
</h1>
<p class="mt-6 max-w-prose text-lg leading-relaxed text-foreground/90">
{{ t('events.page.lede') }}
</p>
<Alert class="mt-8 max-w-prose bg-card text-foreground/85"> <Alert class="mt-8 max-w-prose bg-card text-foreground/85">
<AlertTitle class="text-xs uppercase tracking-wider text-accent"> <AlertTitle class="text-xs uppercase tracking-wider text-accent">
{{ t('events.page.noteHeading') }} {{ t('events.page.noteHeading') }}
@ -57,10 +54,9 @@ const events = [
{{ t('events.page.calendarNote') }} {{ t('events.page.calendarNote') }}
</AlertDescription> </AlertDescription>
</Alert> </Alert>
</div> </PageHero>
</section>
<section class="mx-auto max-w-7xl px-4 py-16 lg:px-6"> <PageSection>
<ul class="grid gap-6 md:grid-cols-2 lg:grid-cols-3"> <ul class="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
<li v-for="e in events" :key="e.key"> <li v-for="e in events" :key="e.key">
<component <component
@ -79,7 +75,7 @@ const events = [
<p class="text-xs uppercase tracking-wider text-accent"> <p class="text-xs uppercase tracking-wider text-accent">
{{ t(`events.${e.key}.date`) }} {{ t(`events.${e.key}.date`) }}
</p> </p>
<h2 class="mt-1 font-serif text-xl font-semibold"> <h2 class="mt-1 font-display text-lg uppercase tracking-wider">
{{ t(`events.${e.key}.title`) }} {{ t(`events.${e.key}.title`) }}
</h2> </h2>
<p class="mt-1 text-xs text-muted-foreground"> <p class="mt-1 text-xs text-muted-foreground">
@ -99,6 +95,6 @@ const events = [
<RouterLink to="/symposium">{{ t('nav.symposium') }} </RouterLink> <RouterLink to="/symposium">{{ t('nav.symposium') }} </RouterLink>
</Button> </Button>
</div> </div>
</section> </PageSection>
</div> </PageShell>
</template> </template>

View file

@ -1,6 +1,9 @@
<script setup lang="ts"> <script setup lang="ts">
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import { Card } from '@/components/ui/card' import { Card } from '@/components/ui/card'
import PageHero from '@/components/layout/PageHero.vue'
import PageSection from '@/components/layout/PageSection.vue'
import PageShell from '@/components/layout/PageShell.vue'
const { t } = useI18n() const { t } = useI18n()
@ -33,20 +36,14 @@ const items = [
</script> </script>
<template> <template>
<div> <PageShell>
<section class="border-b border-border bg-secondary/40"> <PageHero
<div class="mx-auto max-w-4xl px-4 py-16 lg:px-6 lg:py-20"> :kicker="t('gallery.kicker')"
<p class="text-xs uppercase tracking-[0.2em] text-accent">{{ t('gallery.kicker') }}</p> :title="t('gallery.title')"
<h1 class="mt-3 font-serif text-5xl font-semibold leading-tight tracking-tight md:text-6xl"> :lede="t('gallery.lede')"
{{ t('gallery.title') }} />
</h1>
<p class="mt-6 max-w-prose text-lg leading-relaxed text-foreground/90">
{{ t('gallery.lede') }}
</p>
</div>
</section>
<section class="mx-auto max-w-7xl px-4 py-16 lg:px-6"> <PageSection>
<ul class="grid gap-4 sm:grid-cols-2 lg:grid-cols-3"> <ul class="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
<li v-for="item in items" :key="item.key" class="group"> <li v-for="item in items" :key="item.key" class="group">
<Card class="overflow-hidden"> <Card class="overflow-hidden">
@ -58,7 +55,7 @@ const items = [
loading="lazy" loading="lazy"
/> />
<figcaption <figcaption
class="border-t border-border px-4 py-3 font-serif text-sm text-foreground/85" class="border-t border-border px-4 py-3 text-sm text-foreground/85"
> >
{{ t(`gallery.captions.${item.key}`) }} {{ t(`gallery.captions.${item.key}`) }}
</figcaption> </figcaption>
@ -66,6 +63,6 @@ const items = [
</Card> </Card>
</li> </li>
</ul> </ul>
</section> </PageSection>
</div> </PageShell>
</template> </template>

View file

@ -3,6 +3,9 @@ import { useI18n } from 'vue-i18n'
import { RouterLink } from 'vue-router' import { RouterLink } from 'vue-router'
import { Button } from '@/components/ui/button' import { Button } from '@/components/ui/button'
import { Card } from '@/components/ui/card' import { Card } from '@/components/ui/card'
import PageHero from '@/components/layout/PageHero.vue'
import PageSection from '@/components/layout/PageSection.vue'
import PageShell from '@/components/layout/PageShell.vue'
const { t } = useI18n() const { t } = useI18n()
@ -10,30 +13,22 @@ const paths = ['exchange', 'rental', 'partial', 'funded'] as const
</script> </script>
<template> <template>
<div> <PageShell>
<!-- Hero --> <!-- Hero -->
<section class="border-b border-border bg-secondary/40"> <PageHero
<div class="mx-auto max-w-4xl px-4 py-16 lg:px-6 lg:py-20"> :kicker="t('longStays.hero.kicker')"
<p class="text-xs uppercase tracking-[0.2em] text-accent"> :title="t('longStays.hero.title')"
{{ t('longStays.hero.kicker') }} :lede="t('longStays.hero.lede')"
</p> />
<h1 class="mt-3 font-serif text-5xl font-semibold leading-tight tracking-tight md:text-6xl">
{{ t('longStays.hero.title') }}
</h1>
<p class="mt-6 max-w-prose text-lg leading-relaxed text-foreground/90">
{{ t('longStays.hero.lede') }}
</p>
</div>
</section>
<!-- Paths --> <!-- Paths -->
<section class="mx-auto max-w-7xl px-4 py-16 lg:px-6"> <PageSection>
<h2 class="font-serif text-3xl font-semibold tracking-tight"> <h2 class="font-display text-2xl uppercase tracking-wider md:text-3xl">
{{ t('longStays.pathsTitle') }} {{ t('longStays.pathsTitle') }}
</h2> </h2>
<div class="mt-8 grid gap-6 md:grid-cols-2"> <div class="mt-8 grid gap-6 md:grid-cols-2">
<Card v-for="key in paths" :key="key" class="p-6"> <Card v-for="key in paths" :key="key" class="p-6">
<h3 class="font-serif text-xl font-semibold"> <h3 class="font-display text-lg uppercase tracking-wider">
{{ t(`longStays.paths.${key}Title`) }} {{ t(`longStays.paths.${key}Title`) }}
</h3> </h3>
<p class="mt-3 text-base leading-relaxed text-foreground/85"> <p class="mt-3 text-base leading-relaxed text-foreground/85">
@ -41,11 +36,11 @@ const paths = ['exchange', 'rental', 'partial', 'funded'] as const
</p> </p>
</Card> </Card>
</div> </div>
</section> </PageSection>
<!-- Symposium teaser --> <!-- Symposium teaser -->
<section class="border-t border-border bg-secondary/30"> <PageSection>
<div class="mx-auto grid max-w-7xl items-center gap-10 px-4 py-16 lg:grid-cols-2 lg:gap-14 lg:px-6"> <div class="grid items-center gap-10 lg:grid-cols-2 lg:gap-14">
<img <img
src="https://static.wixstatic.com/media/11062b_322db9c671074a6cb3d76de93ac013f0~mv2.jpg" src="https://static.wixstatic.com/media/11062b_322db9c671074a6cb3d76de93ac013f0~mv2.jpg"
alt="" alt=""
@ -53,7 +48,7 @@ const paths = ['exchange', 'rental', 'partial', 'funded'] as const
loading="lazy" loading="lazy"
/> />
<div> <div>
<h2 class="font-serif text-3xl font-semibold tracking-tight"> <h2 class="font-display text-2xl uppercase tracking-wider md:text-3xl">
{{ t('longStays.symposiumTeaser.title') }} {{ t('longStays.symposiumTeaser.title') }}
</h2> </h2>
<p class="mt-5 max-w-prose leading-relaxed"> <p class="mt-5 max-w-prose leading-relaxed">
@ -69,6 +64,6 @@ const paths = ['exchange', 'rental', 'partial', 'funded'] as const
</div> </div>
</div> </div>
</div> </div>
</section> </PageSection>
</div> </PageShell>
</template> </template>

View file

@ -2,6 +2,9 @@
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import { Button } from '@/components/ui/button' import { Button } from '@/components/ui/button'
import { Card } from '@/components/ui/card' import { Card } from '@/components/ui/card'
import PageHero from '@/components/layout/PageHero.vue'
import PageSection from '@/components/layout/PageSection.vue'
import PageShell from '@/components/layout/PageShell.vue'
const { t } = useI18n() const { t } = useI18n()
@ -9,28 +12,20 @@ const categories = ['fresh', 'pantry', 'craft'] as const
</script> </script>
<template> <template>
<div> <PageShell>
<section class="border-b border-border bg-secondary/40"> <PageHero
<div class="mx-auto max-w-4xl px-4 py-16 lg:px-6 lg:py-20"> :kicker="t('marketplace.kicker')"
<p class="text-xs uppercase tracking-[0.2em] text-accent"> :title="t('marketplace.title')"
{{ t('marketplace.kicker') }} :lede="t('marketplace.lede')"
</p> />
<h1 class="mt-3 font-serif text-5xl font-semibold leading-tight tracking-tight md:text-6xl">
{{ t('marketplace.title') }}
</h1>
<p class="mt-6 max-w-prose text-lg leading-relaxed text-foreground/90">
{{ t('marketplace.lede') }}
</p>
</div>
</section>
<section class="mx-auto max-w-7xl px-4 py-16 lg:px-6"> <PageSection>
<h2 class="font-serif text-3xl font-semibold tracking-tight"> <h2 class="font-display text-2xl uppercase tracking-wider md:text-3xl">
{{ t('marketplace.categoriesTitle') }} {{ t('marketplace.categoriesTitle') }}
</h2> </h2>
<div class="mt-8 grid gap-6 md:grid-cols-3"> <div class="mt-8 grid gap-6 md:grid-cols-3">
<Card v-for="key in categories" :key="key" class="border-dashed p-6"> <Card v-for="key in categories" :key="key" class="border-dashed p-6">
<h3 class="font-serif text-xl font-semibold"> <h3 class="font-display text-lg uppercase tracking-wider">
{{ t(`marketplace.categories.${key}Title`) }} {{ t(`marketplace.categories.${key}Title`) }}
</h3> </h3>
<p class="mt-3 text-base leading-relaxed text-foreground/85"> <p class="mt-3 text-base leading-relaxed text-foreground/85">
@ -38,11 +33,11 @@ const categories = ['fresh', 'pantry', 'craft'] as const
</p> </p>
</Card> </Card>
</div> </div>
</section> </PageSection>
<section class="border-t border-border bg-secondary/30"> <PageSection width="narrow" padding="compact">
<div class="mx-auto max-w-4xl px-4 py-12 text-center lg:px-6"> <div class="text-center">
<p class="font-serif text-lg italic text-foreground/85"> <p class="text-lg italic text-foreground/85">
{{ t('marketplace.notice') }} {{ t('marketplace.notice') }}
</p> </p>
<Button as-child variant="outline" class="mt-6"> <Button as-child variant="outline" class="mt-6">
@ -51,6 +46,6 @@ const categories = ['fresh', 'pantry', 'craft'] as const
</a> </a>
</Button> </Button>
</div> </div>
</section> </PageSection>
</div> </PageShell>
</template> </template>

View file

@ -4,7 +4,7 @@ import { RouterLink } from 'vue-router'
<template> <template>
<article class="mx-auto max-w-3xl px-4 py-24 text-center"> <article class="mx-auto max-w-3xl px-4 py-24 text-center">
<h1 class="font-serif text-5xl font-semibold tracking-tight">404</h1> <h1 class="font-display text-6xl uppercase tracking-wider">404</h1>
<p class="mt-4 text-muted-foreground">Page introuvable / Page not found.</p> <p class="mt-4 text-muted-foreground">Page introuvable / Page not found.</p>
<RouterLink to="/" class="mt-8 inline-block text-sm underline hover:text-primary"> <RouterLink to="/" class="mt-8 inline-block text-sm underline hover:text-primary">
Château du Faune Château du Faune

View file

@ -3,6 +3,9 @@ import { useI18n } from 'vue-i18n'
import { RouterLink } from 'vue-router' import { RouterLink } from 'vue-router'
import { Button } from '@/components/ui/button' import { Button } from '@/components/ui/button'
import { Card } from '@/components/ui/card' import { Card } from '@/components/ui/card'
import PageHero from '@/components/layout/PageHero.vue'
import PageSection from '@/components/layout/PageSection.vue'
import PageShell from '@/components/layout/PageShell.vue'
const { t } = useI18n() const { t } = useI18n()
@ -19,34 +22,26 @@ const applyKeys = ['model', 'window', 'open'] as const
</script> </script>
<template> <template>
<div> <PageShell>
<!-- Hero --> <!-- Hero -->
<section class="border-b border-border bg-secondary/40"> <PageHero
<div class="mx-auto max-w-4xl px-4 py-16 lg:px-6 lg:py-20"> :kicker="t('opportunities.hero.kicker')"
<p class="text-xs uppercase tracking-[0.2em] text-accent"> :title="t('opportunities.hero.title')"
{{ t('opportunities.hero.kicker') }} :lede="t('opportunities.hero.lede')"
</p> />
<h1 class="mt-3 font-serif text-5xl font-semibold leading-tight tracking-tight md:text-6xl">
{{ t('opportunities.hero.title') }}
</h1>
<p class="mt-6 max-w-prose text-lg leading-relaxed text-foreground/90">
{{ t('opportunities.hero.lede') }}
</p>
</div>
</section>
<!-- Groups of positions --> <!-- Groups of positions -->
<section class="mx-auto max-w-7xl px-4 py-16 lg:px-6"> <PageSection>
<div class="max-w-3xl"> <div class="max-w-3xl">
<h2 class="font-serif text-3xl font-semibold tracking-tight"> <h2 class="font-display text-2xl uppercase tracking-wider md:text-3xl">
{{ t('opportunities.groupsTitle') }} {{ t('opportunities.groupsTitle') }}
</h2> </h2>
<p class="mt-3 text-muted-foreground">{{ t('opportunities.groupsSubtitle') }}</p> <p class="mt-3 text-foreground/80">{{ t('opportunities.groupsSubtitle') }}</p>
</div> </div>
<ul class="mt-8 grid gap-6 md:grid-cols-2 lg:grid-cols-3"> <ul class="mt-8 grid gap-6 md:grid-cols-2 lg:grid-cols-3">
<li v-for="key in groups" :key="key"> <li v-for="key in groups" :key="key">
<Card class="p-6"> <Card class="p-6">
<h3 class="font-serif text-xl font-semibold"> <h3 class="font-display text-lg uppercase tracking-wider">
{{ t(`opportunities.groups.${key}Title`) }} {{ t(`opportunities.groups.${key}Title`) }}
</h3> </h3>
<p class="mt-3 text-sm leading-relaxed text-foreground/85"> <p class="mt-3 text-sm leading-relaxed text-foreground/85">
@ -55,17 +50,16 @@ const applyKeys = ['model', 'window', 'open'] as const
</Card> </Card>
</li> </li>
</ul> </ul>
</section> </PageSection>
<!-- How we hire --> <!-- How we hire -->
<section class="border-t border-border bg-secondary/30"> <PageSection>
<div class="mx-auto max-w-7xl px-4 py-16 lg:px-6"> <h2 class="font-display text-2xl uppercase tracking-wider md:text-3xl">
<h2 class="font-serif text-3xl font-semibold tracking-tight">
{{ t('opportunities.applyTitle') }} {{ t('opportunities.applyTitle') }}
</h2> </h2>
<div class="mt-8 grid gap-6 md:grid-cols-3"> <div class="mt-8 grid gap-6 md:grid-cols-3">
<Card v-for="key in applyKeys" :key="key" class="p-6"> <Card v-for="key in applyKeys" :key="key" class="p-6">
<h3 class="font-serif text-lg font-semibold"> <h3 class="font-display text-lg uppercase tracking-wider">
{{ t(`opportunities.apply.${key}Title`) }} {{ t(`opportunities.apply.${key}Title`) }}
</h3> </h3>
<p class="mt-3 text-sm leading-relaxed text-foreground/85"> <p class="mt-3 text-sm leading-relaxed text-foreground/85">
@ -83,7 +77,6 @@ const applyKeys = ['model', 'window', 'open'] as const
<RouterLink to="/symposium">{{ t('opportunities.ctaSymposium') }}</RouterLink> <RouterLink to="/symposium">{{ t('opportunities.ctaSymposium') }}</RouterLink>
</Button> </Button>
</div> </div>
</div> </PageSection>
</section> </PageShell>
</div>
</template> </template>

View file

@ -3,6 +3,9 @@ import { useI18n } from 'vue-i18n'
import { RouterLink } from 'vue-router' import { RouterLink } from 'vue-router'
import { Button } from '@/components/ui/button' import { Button } from '@/components/ui/button'
import { Card } from '@/components/ui/card' import { Card } from '@/components/ui/card'
import PageHero from '@/components/layout/PageHero.vue'
import PageSection from '@/components/layout/PageSection.vue'
import PageShell from '@/components/layout/PageShell.vue'
const { t } = useI18n() const { t } = useI18n()
@ -10,30 +13,22 @@ const kinds = ['weekend', 'retreat', 'gathering', 'residency'] as const
</script> </script>
<template> <template>
<div> <PageShell>
<!-- Hero --> <!-- Hero -->
<section class="border-b border-border bg-secondary/40"> <PageHero
<div class="mx-auto max-w-4xl px-4 py-16 lg:px-6 lg:py-20"> :kicker="t('reservations.hero.kicker')"
<p class="text-xs uppercase tracking-[0.2em] text-accent"> :title="t('reservations.hero.title')"
{{ t('reservations.hero.kicker') }} :lede="t('reservations.hero.lede')"
</p> />
<h1 class="mt-3 font-serif text-5xl font-semibold leading-tight tracking-tight md:text-6xl">
{{ t('reservations.hero.title') }}
</h1>
<p class="mt-6 max-w-prose text-lg leading-relaxed text-foreground/90">
{{ t('reservations.hero.lede') }}
</p>
</div>
</section>
<!-- Kinds of stays --> <!-- Kinds of stays -->
<section class="mx-auto max-w-7xl px-4 py-16 lg:px-6"> <PageSection>
<h2 class="font-serif text-3xl font-semibold tracking-tight"> <h2 class="font-display text-2xl uppercase tracking-wider md:text-3xl">
{{ t('reservations.kindsTitle') }} {{ t('reservations.kindsTitle') }}
</h2> </h2>
<div class="mt-8 grid gap-6 sm:grid-cols-2 lg:grid-cols-4"> <div class="mt-8 grid gap-6 sm:grid-cols-2 lg:grid-cols-4">
<Card v-for="key in kinds" :key="key" class="p-6"> <Card v-for="key in kinds" :key="key" class="p-6">
<h3 class="font-serif text-xl font-semibold"> <h3 class="font-display text-lg uppercase tracking-wider">
{{ t(`reservations.kinds.${key}Title`) }} {{ t(`reservations.kinds.${key}Title`) }}
</h3> </h3>
<p class="mt-3 text-sm leading-relaxed text-foreground/85"> <p class="mt-3 text-sm leading-relaxed text-foreground/85">
@ -41,34 +36,32 @@ const kinds = ['weekend', 'retreat', 'gathering', 'residency'] as const
</p> </p>
</Card> </Card>
</div> </div>
</section> </PageSection>
<!-- Values --> <!-- Values -->
<section class="border-y border-border bg-card"> <PageSection width="narrow">
<div class="mx-auto max-w-4xl px-4 py-16 lg:px-6"> <h2 class="font-display text-2xl uppercase tracking-wider md:text-3xl">
<h2 class="font-serif text-3xl font-semibold tracking-tight">
{{ t('reservations.valuesTitle') }} {{ t('reservations.valuesTitle') }}
</h2> </h2>
<p class="mt-5 max-w-prose text-base leading-relaxed"> <p class="mt-5 max-w-prose text-base leading-relaxed">
{{ t('reservations.valuesBody') }} {{ t('reservations.valuesBody') }}
</p> </p>
</div> </PageSection>
</section>
<!-- Booking form placeholder + contact card --> <!-- Booking form placeholder + contact card -->
<section class="mx-auto max-w-7xl px-4 py-16 lg:px-6"> <PageSection>
<div class="grid gap-10 lg:grid-cols-5 lg:gap-14"> <div class="grid gap-10 lg:grid-cols-5 lg:gap-14">
<div class="lg:col-span-3"> <div class="lg:col-span-3">
<h2 class="font-serif text-3xl font-semibold tracking-tight"> <h2 class="font-display text-2xl uppercase tracking-wider md:text-3xl">
{{ t('reservations.formTitle') }} {{ t('reservations.formTitle') }}
</h2> </h2>
<p class="mt-3 max-w-prose text-muted-foreground"> <p class="mt-3 max-w-prose text-foreground/80">
{{ t('reservations.formSubtitle') }} {{ t('reservations.formSubtitle') }}
</p> </p>
<div <div
class="mt-6 flex aspect-[4/3] items-center justify-center rounded-lg border border-dashed border-border bg-secondary/30 p-6 text-center text-muted-foreground" class="mt-6 flex aspect-[4/3] items-center justify-center rounded-lg border border-dashed border-border bg-secondary/30 p-6 text-center text-muted-foreground"
> >
<p class="font-serif italic">{{ t('reservations.formPlaceholder') }}</p> <p class="italic">{{ t('reservations.formPlaceholder') }}</p>
</div> </div>
<div class="mt-6 flex flex-wrap items-center gap-3"> <div class="mt-6 flex flex-wrap items-center gap-3">
<Button as-child> <Button as-child>
@ -85,7 +78,7 @@ const kinds = ['weekend', 'retreat', 'gathering', 'residency'] as const
</div> </div>
<Card class="p-6 lg:col-span-2"> <Card class="p-6 lg:col-span-2">
<h3 class="font-serif text-xl font-semibold"> <h3 class="font-display text-lg uppercase tracking-wider">
{{ t('reservations.contactCard.title') }} {{ t('reservations.contactCard.title') }}
</h3> </h3>
<dl class="mt-4 space-y-4 text-sm"> <dl class="mt-4 space-y-4 text-sm">
@ -117,6 +110,6 @@ const kinds = ['weekend', 'retreat', 'gathering', 'residency'] as const
</dl> </dl>
</Card> </Card>
</div> </div>
</section> </PageSection>
</div> </PageShell>
</template> </template>

View file

@ -3,6 +3,9 @@ import { useI18n } from 'vue-i18n'
import { RouterLink } from 'vue-router' import { RouterLink } from 'vue-router'
import { Button } from '@/components/ui/button' import { Button } from '@/components/ui/button'
import { Card } from '@/components/ui/card' import { Card } from '@/components/ui/card'
import PageHero from '@/components/layout/PageHero.vue'
import PageSection from '@/components/layout/PageSection.vue'
import PageShell from '@/components/layout/PageShell.vue'
const { t } = useI18n() const { t } = useI18n()
@ -11,54 +14,44 @@ const applySteps = ['stepOne', 'stepTwo', 'stepThree'] as const
</script> </script>
<template> <template>
<div> <PageShell>
<!-- Hero --> <!-- Hero -->
<section class="border-b border-border bg-secondary/40"> <PageHero
<div class="mx-auto grid max-w-7xl gap-10 px-4 py-16 lg:grid-cols-2 lg:gap-14 lg:px-6 lg:py-20"> :kicker="t('symposium.hero.kicker')"
<div> :title="t('symposium.hero.title')"
<p class="text-xs uppercase tracking-[0.2em] text-accent"> :lede="t('symposium.hero.lede')"
{{ t('symposium.hero.kicker') }}
</p>
<h1
class="mt-3 font-serif text-5xl font-semibold leading-tight tracking-tight md:text-6xl"
> >
{{ t('symposium.hero.title') }} <p class="mt-6 inline-block rounded-md bg-card px-3 py-2 text-base">
</h1>
<p class="mt-6 max-w-prose text-lg leading-relaxed text-foreground/90">
{{ t('symposium.hero.lede') }}
</p>
<p class="mt-6 inline-block rounded-md bg-card px-3 py-2 font-serif text-base">
{{ t('symposium.hero.dates') }} {{ t('symposium.hero.dates') }}
</p> </p>
</div> <template #aside>
<img <img
src="https://static.wixstatic.com/media/f1cbb8_72455a57197944e2b3cd2d895d459ba0~mv2.jpg" src="https://static.wixstatic.com/media/f1cbb8_72455a57197944e2b3cd2d895d459ba0~mv2.jpg"
alt="" alt=""
class="aspect-[4/3] w-full rounded-lg object-cover" class="aspect-[4/3] w-full rounded-lg object-cover"
loading="lazy" loading="lazy"
/> />
</div> </template>
</section> </PageHero>
<!-- Overview --> <!-- Overview -->
<section class="mx-auto max-w-4xl px-4 py-16 lg:px-6"> <PageSection width="narrow">
<h2 class="font-serif text-3xl font-semibold tracking-tight"> <h2 class="font-display text-2xl uppercase tracking-wider md:text-3xl">
{{ t('symposium.overview.title') }} {{ t('symposium.overview.title') }}
</h2> </h2>
<p class="mt-5 max-w-prose text-base leading-relaxed"> <p class="mt-5 max-w-prose text-base leading-relaxed">
{{ t('symposium.overview.body') }} {{ t('symposium.overview.body') }}
</p> </p>
</section> </PageSection>
<!-- What's included --> <!-- What's included -->
<section class="border-y border-border bg-card"> <PageSection>
<div class="mx-auto max-w-7xl px-4 py-16 lg:px-6"> <h2 class="font-display text-2xl uppercase tracking-wider md:text-3xl">
<h2 class="font-serif text-3xl font-semibold tracking-tight">
{{ t('symposium.includedTitle') }} {{ t('symposium.includedTitle') }}
</h2> </h2>
<div class="mt-8 grid gap-6 sm:grid-cols-2 lg:grid-cols-4"> <div class="mt-8 grid gap-6 sm:grid-cols-2 lg:grid-cols-4">
<Card v-for="key in included" :key="key" class="bg-background p-6"> <Card v-for="key in included" :key="key" class="bg-background p-6">
<h3 class="font-serif text-lg font-semibold"> <h3 class="font-display text-lg uppercase tracking-wider">
{{ t(`symposium.included.${key}Title`) }} {{ t(`symposium.included.${key}Title`) }}
</h3> </h3>
<p class="mt-3 text-sm leading-relaxed text-foreground/85"> <p class="mt-3 text-sm leading-relaxed text-foreground/85">
@ -66,29 +59,27 @@ const applySteps = ['stepOne', 'stepTwo', 'stepThree'] as const
</p> </p>
</Card> </Card>
</div> </div>
</div> </PageSection>
</section>
<!-- Eligibility --> <!-- Eligibility -->
<section class="mx-auto max-w-4xl px-4 py-16 lg:px-6"> <PageSection width="narrow">
<h2 class="font-serif text-3xl font-semibold tracking-tight"> <h2 class="font-display text-2xl uppercase tracking-wider md:text-3xl">
{{ t('symposium.eligibility.title') }} {{ t('symposium.eligibility.title') }}
</h2> </h2>
<p class="mt-5 max-w-prose text-base leading-relaxed"> <p class="mt-5 max-w-prose text-base leading-relaxed">
{{ t('symposium.eligibility.body') }} {{ t('symposium.eligibility.body') }}
</p> </p>
</section> </PageSection>
<!-- How to apply --> <!-- How to apply -->
<section class="border-t border-border bg-secondary/30"> <PageSection>
<div class="mx-auto max-w-7xl px-4 py-16 lg:px-6"> <h2 class="font-display text-2xl uppercase tracking-wider md:text-3xl">
<h2 class="font-serif text-3xl font-semibold tracking-tight">
{{ t('symposium.applyTitle') }} {{ t('symposium.applyTitle') }}
</h2> </h2>
<ol class="mt-8 grid gap-6 md:grid-cols-3"> <ol class="mt-8 grid gap-6 md:grid-cols-3">
<li v-for="step in applySteps" :key="step"> <li v-for="step in applySteps" :key="step">
<Card class="p-6"> <Card class="p-6">
<h3 class="font-serif text-lg font-semibold"> <h3 class="font-display text-lg uppercase tracking-wider">
{{ t(`symposium.apply.${step}Title`) }} {{ t(`symposium.apply.${step}Title`) }}
</h3> </h3>
<p class="mt-3 text-sm leading-relaxed text-foreground/85"> <p class="mt-3 text-sm leading-relaxed text-foreground/85">
@ -105,7 +96,6 @@ const applySteps = ['stepOne', 'stepTwo', 'stepThree'] as const
<a href="mailto:chateaudufaune@ariege.io">{{ t('symposium.ctaContact') }}</a> <a href="mailto:chateaudufaune@ariege.io">{{ t('symposium.ctaContact') }}</a>
</Button> </Button>
</div> </div>
</div> </PageSection>
</section> </PageShell>
</div>
</template> </template>

View file

@ -1,6 +1,9 @@
<script setup lang="ts"> <script setup lang="ts">
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import { Card } from '@/components/ui/card' import { Card } from '@/components/ui/card'
import PageHero from '@/components/layout/PageHero.vue'
import PageSection from '@/components/layout/PageSection.vue'
import PageShell from '@/components/layout/PageShell.vue'
const { t } = useI18n() const { t } = useI18n()
@ -20,45 +23,36 @@ const team = ['patrick', 'coco', 'charlie'] as const
</script> </script>
<template> <template>
<div> <PageShell>
<!-- Hero --> <!-- Hero -->
<section class="border-b border-border bg-secondary/40"> <PageHero
<div class="mx-auto max-w-4xl px-4 py-16 lg:px-6 lg:py-24"> :kicker="t('vision.hero.kicker')"
<p class="text-xs uppercase tracking-[0.2em] text-accent"> :title="t('vision.hero.title')"
{{ t('vision.hero.kicker') }} :lede="t('vision.hero.lede')"
</p> />
<h1 class="mt-3 font-serif text-5xl font-semibold leading-tight tracking-tight md:text-6xl">
{{ t('vision.hero.title') }}
</h1>
<p class="mt-6 max-w-prose text-lg leading-relaxed text-foreground/90">
{{ t('vision.hero.lede') }}
</p>
</div>
</section>
<!-- Mission --> <!-- Mission -->
<section class="mx-auto max-w-4xl px-4 py-16 lg:px-6"> <PageSection width="narrow">
<h2 class="font-serif text-3xl font-semibold tracking-tight"> <h2 class="font-display text-2xl uppercase tracking-wider md:text-3xl">
{{ t('vision.mission.title') }} {{ t('vision.mission.title') }}
</h2> </h2>
<p class="mt-5 max-w-prose text-base leading-relaxed"> <p class="mt-5 max-w-prose text-base leading-relaxed">
{{ t('vision.mission.body') }} {{ t('vision.mission.body') }}
</p> </p>
</section> </PageSection>
<!-- Philosophy --> <!-- Philosophy -->
<section class="border-y border-border bg-card"> <PageSection>
<div class="mx-auto max-w-7xl px-4 py-16 lg:px-6">
<div class="max-w-3xl"> <div class="max-w-3xl">
<h2 class="font-serif text-3xl font-semibold tracking-tight"> <h2 class="font-display text-2xl uppercase tracking-wider md:text-3xl">
{{ t('vision.philosophyTitle') }} {{ t('vision.philosophyTitle') }}
</h2> </h2>
<p class="mt-3 text-muted-foreground">{{ t('vision.philosophySubtitle') }}</p> <p class="mt-3 text-foreground/80">{{ t('vision.philosophySubtitle') }}</p>
</div> </div>
<div class="mt-8 grid gap-6 sm:grid-cols-2 lg:grid-cols-5"> <div class="mt-8 grid gap-6 sm:grid-cols-2 lg:grid-cols-5">
<Card v-for="(p, i) in philosophy" :key="p" class="bg-background p-5"> <Card v-for="(p, i) in philosophy" :key="p" class="bg-background p-5">
<div class="font-serif text-2xl text-accent">{{ i + 1 }}</div> <div class="font-display text-2xl text-accent">{{ i + 1 }}</div>
<h3 class="mt-2 font-serif text-lg font-semibold"> <h3 class="mt-2 font-display text-lg uppercase tracking-wider">
{{ t(`vision.philosophy.${p}Title`) }} {{ t(`vision.philosophy.${p}Title`) }}
</h3> </h3>
<p class="mt-2 text-sm leading-relaxed text-foreground/85"> <p class="mt-2 text-sm leading-relaxed text-foreground/85">
@ -66,36 +60,34 @@ const team = ['patrick', 'coco', 'charlie'] as const
</p> </p>
</Card> </Card>
</div> </div>
</div> </PageSection>
</section>
<!-- Operational pillars --> <!-- Operational pillars -->
<section class="mx-auto max-w-7xl px-4 py-16 lg:px-6"> <PageSection>
<div class="max-w-3xl"> <div class="max-w-3xl">
<h2 class="font-serif text-3xl font-semibold tracking-tight"> <h2 class="font-display text-2xl uppercase tracking-wider md:text-3xl">
{{ t('vision.pillarsTitle') }} {{ t('vision.pillarsTitle') }}
</h2> </h2>
<p class="mt-3 text-muted-foreground">{{ t('vision.pillarsSubtitle') }}</p> <p class="mt-3 text-foreground/80">{{ t('vision.pillarsSubtitle') }}</p>
</div> </div>
<div class="mt-8 grid gap-6 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4"> <div class="mt-8 grid gap-6 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
<Card v-for="p in pillars" :key="p" class="p-6"> <Card v-for="p in pillars" :key="p" class="p-6">
<h3 class="font-serif text-xl font-semibold">{{ t(`vision.pillars.${p}Title`) }}</h3> <h3 class="font-display text-lg uppercase tracking-wider">{{ t(`vision.pillars.${p}Title`) }}</h3>
<p class="mt-3 text-sm leading-relaxed text-foreground/85"> <p class="mt-3 text-sm leading-relaxed text-foreground/85">
{{ t(`vision.pillars.${p}Body`) }} {{ t(`vision.pillars.${p}Body`) }}
</p> </p>
</Card> </Card>
</div> </div>
</section> </PageSection>
<!-- Team --> <!-- Team -->
<section class="border-t border-border bg-secondary/30"> <PageSection>
<div class="mx-auto max-w-7xl px-4 py-16 lg:px-6"> <h2 class="font-display text-2xl uppercase tracking-wider md:text-3xl">
<h2 class="font-serif text-3xl font-semibold tracking-tight">
{{ t('vision.teamTitle') }} {{ t('vision.teamTitle') }}
</h2> </h2>
<div class="mt-8 grid gap-6 md:grid-cols-3"> <div class="mt-8 grid gap-6 md:grid-cols-3">
<Card v-for="m in team" :key="m" class="p-6"> <Card v-for="m in team" :key="m" class="p-6">
<h3 class="font-serif text-xl font-semibold">{{ t(`vision.team.${m}Name`) }}</h3> <h3 class="font-display text-lg uppercase tracking-wider">{{ t(`vision.team.${m}Name`) }}</h3>
<p class="mt-1 text-xs uppercase tracking-wider text-accent"> <p class="mt-1 text-xs uppercase tracking-wider text-accent">
{{ t(`vision.team.${m}Role`) }} {{ t(`vision.team.${m}Role`) }}
</p> </p>
@ -104,7 +96,6 @@ const team = ['patrick', 'coco', 'charlie'] as const
</p> </p>
</Card> </Card>
</div> </div>
</div> </PageSection>
</section> </PageShell>
</div>
</template> </template>