feat(home/hero): blackletter wordmark title with video clipped through letters

Replace the script-font title with the brand blackletter ("Sketch Gothic
School", self-hosted) rendered as SVG text that clips a looping
forest/cloud video, so the texture drifts through the letterforms. The
viewBox auto-fits the measured glyph box (one line at any width, ~92vw),
with a gold drop-shadow for the engraved edge. Plain <h1> kept for SEO.

Video re-encoded to ~3.1MB with a light poster.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Padreug 2026-06-14 18:20:24 +02:00
commit ee5b927ba2
6 changed files with 106 additions and 5 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

View file

@ -3,8 +3,20 @@
@custom-variant dark (&:is(.dark *)); @custom-variant dark (&:is(.dark *));
/* Self-hosted blackletter used for the hero title ("Sketch Gothic School").
Only needed to shape the SVG clip glyphs the hero video shows through. */
@font-face {
font-family: 'Sketch Gothic School';
src:
url('./assets/fonts/sketch-gothic-school.woff2') format('woff2'),
url('./assets/fonts/sketch-gothic-school.woff') format('woff');
font-weight: normal;
font-style: normal;
font-display: swap;
}
:root { :root {
/* Wix-inspired palette: deep forest green dominant background, cream /* Brand palette: deep forest green dominant background, cream
foreground, gold (Aboreto/calligraphic spirit) for CTAs and accents. */ foreground, gold (Aboreto/calligraphic spirit) for CTAs and accents. */
--background: hsl(151 100% 8%); --background: hsl(151 100% 8%);
--foreground: hsl(200 32% 94%); --foreground: hsl(200 32% 94%);
@ -86,6 +98,7 @@
'Roboto', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif; 'Roboto', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif;
--font-display: 'Aboreto', 'Cormorant Garamond', Georgia, serif; --font-display: 'Aboreto', 'Cormorant Garamond', Georgia, serif;
--font-script: 'Tangerine', 'Allura', cursive; --font-script: 'Tangerine', 'Allura', cursive;
--font-blackletter: 'Sketch Gothic School', 'UnifrakturMaguntia', serif;
} }
@layer base { @layer base {

View file

@ -1,4 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed, nextTick, onMounted, ref } from 'vue'
import { useI18n } from 'vue-i18n' 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'
@ -7,6 +8,8 @@ import cosmicStagMorphWebm from '@/assets/cosmic-stag-morph-1024.webm'
import cosmicStagMorphFallback from '@/assets/cosmic-stag-morph-fallback.webp' import cosmicStagMorphFallback from '@/assets/cosmic-stag-morph-fallback.webp'
import heroLandscape from '@/assets/hero-landscape.webp' import heroLandscape from '@/assets/hero-landscape.webp'
import sectionTile from '@/assets/section-tile.webp' import sectionTile from '@/assets/section-tile.webp'
import titleWordmark from '@/assets/title-wordmark.mp4'
import titleWordmarkPoster from '@/assets/title-wordmark-poster.jpg'
const tileStyle = { const tileStyle = {
backgroundImage: `url(${sectionTile})`, backgroundImage: `url(${sectionTile})`,
@ -17,6 +20,43 @@ const tileStyle = {
const { t } = useI18n() const { t } = useI18n()
// The hero title is SVG text (Sketch Gothic School) used as a clip over the
// wordmark video. Measure the rendered glyph box once the font loads and fit
// the viewBox/foreignObject to it, so the wordmark fills the SVG width without
// clipping regardless of the font's metrics.
const titleSvg = ref<SVGSVGElement | null>(null)
const titleText = ref<SVGTextElement | null>(null)
const titleBox = ref({ x: 0, y: 0, w: 1100, h: 200 })
const titleViewBox = computed(
() => `${titleBox.value.x} ${titleBox.value.y} ${titleBox.value.w} ${titleBox.value.h}`,
)
onMounted(async () => {
try {
await (document as Document & { fonts?: FontFaceSet }).fonts?.ready
} catch {
/* fonts API unavailable — keep the default box */
}
await nextTick()
const el = titleText.value
if (!el) return
let bb: DOMRect
try {
bb = el.getBBox()
} catch {
return
}
if (!bb.width) return
const padX = bb.height * 0.08
const padY = bb.height * 0.16
titleBox.value = {
x: Math.round(bb.x - padX),
y: Math.round(bb.y - padY),
w: Math.round(bb.width + padX * 2),
h: Math.round(bb.height + padY * 2),
}
})
const pathways = [ const pathways = [
{ key: 'dayVisit' as const, to: '/reservations' }, { key: 'dayVisit' as const, to: '/reservations' },
{ key: 'activity' as const, to: '/events' }, { key: 'activity' as const, to: '/events' },
@ -69,11 +109,50 @@ const featuredEvents = [
> >
{{ t('common.tagline') }} {{ t('common.tagline') }}
</p> </p>
<h1 <h1 class="sr-only">Château du Faune</h1>
class="mt-4 font-script font-bold text-6xl leading-none text-foreground drop-shadow-md md:text-7xl lg:text-8xl" <!-- Hero title: blackletter text clips the forest/cloud video so it
appears to drift through the letters. The SVG scales by viewBox
(always one line); a gold drop-shadow gives the engraved edge. -->
<svg
ref="titleSvg"
class="hero-title mt-2 block w-[min(92vw,52rem)] sm:mt-4"
:viewBox="titleViewBox"
aria-hidden="true"
> >
Château du Faune <defs>
</h1> <clipPath id="hero-title-clip">
<text
ref="titleText"
x="550"
y="122"
text-anchor="middle"
font-family="'Sketch Gothic School', 'UnifrakturMaguntia', serif"
font-size="120"
>
Château du Faune
</text>
</clipPath>
</defs>
<foreignObject
:x="titleBox.x"
:y="titleBox.y"
:width="titleBox.w"
:height="titleBox.h"
clip-path="url(#hero-title-clip)"
>
<video
xmlns="http://www.w3.org/1999/xhtml"
autoplay
muted
loop
playsinline
:poster="titleWordmarkPoster"
class="h-full w-full object-cover"
>
<source :src="titleWordmark" type="video/mp4" />
</video>
</foreignObject>
</svg>
<video <video
autoplay autoplay
muted muted
@ -236,3 +315,12 @@ const featuredEvents = [
</section> </section>
</div> </div>
</template> </template>
<style scoped>
/* Gold engraved edge + soft shadow on the video-filled title, for the
engraved look and to keep it legible on the bright sky. */
.hero-title {
filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.55)) drop-shadow(0 0 1px #ffe87b);
overflow: visible;
}
</style>