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 *));
|
@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 {
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue