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:
parent
43b83d28dc
commit
ee5b927ba2
6 changed files with 106 additions and 5 deletions
BIN
src/assets/fonts/sketch-gothic-school.woff
Normal file
BIN
src/assets/fonts/sketch-gothic-school.woff
Normal file
Binary file not shown.
BIN
src/assets/fonts/sketch-gothic-school.woff2
Normal file
BIN
src/assets/fonts/sketch-gothic-school.woff2
Normal file
Binary file not shown.
BIN
src/assets/title-wordmark-poster.jpg
Normal file
BIN
src/assets/title-wordmark-poster.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 53 KiB |
BIN
src/assets/title-wordmark.mp4
Normal file
BIN
src/assets/title-wordmark.mp4
Normal file
Binary file not shown.
|
|
@ -3,8 +3,20 @@
|
|||
|
||||
@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 {
|
||||
/* 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. */
|
||||
--background: hsl(151 100% 8%);
|
||||
--foreground: hsl(200 32% 94%);
|
||||
|
|
@ -86,6 +98,7 @@
|
|||
'Roboto', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif;
|
||||
--font-display: 'Aboreto', 'Cormorant Garamond', Georgia, serif;
|
||||
--font-script: 'Tangerine', 'Allura', cursive;
|
||||
--font-blackletter: 'Sketch Gothic School', 'UnifrakturMaguntia', serif;
|
||||
}
|
||||
|
||||
@layer base {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
<script setup lang="ts">
|
||||
import { computed, nextTick, onMounted, ref } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { RouterLink } from 'vue-router'
|
||||
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 heroLandscape from '@/assets/hero-landscape.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 = {
|
||||
backgroundImage: `url(${sectionTile})`,
|
||||
|
|
@ -17,6 +20,43 @@ const tileStyle = {
|
|||
|
||||
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 = [
|
||||
{ key: 'dayVisit' as const, to: '/reservations' },
|
||||
{ key: 'activity' as const, to: '/events' },
|
||||
|
|
@ -69,11 +109,50 @@ const featuredEvents = [
|
|||
>
|
||||
{{ t('common.tagline') }}
|
||||
</p>
|
||||
<h1
|
||||
class="mt-4 font-script font-bold text-6xl leading-none text-foreground drop-shadow-md md:text-7xl lg:text-8xl"
|
||||
<h1 class="sr-only">Château du Faune</h1>
|
||||
<!-- 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"
|
||||
>
|
||||
<defs>
|
||||
<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
|
||||
</h1>
|
||||
</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
|
||||
autoplay
|
||||
muted
|
||||
|
|
@ -236,3 +315,12 @@ const featuredEvents = [
|
|||
</section>
|
||||
</div>
|
||||
</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>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue