Compare commits

...

2 commits

Author SHA1 Message Date
a26f42fb79 copy: drop redundant "Recent work." H2 on the home selected section
The eyebrow already labels the section "Selected work" — repeating
the same idea as a large H2 underneath ("Recent work.") was
redundant and gave the strip more vertical chrome than it needed.
Section now reads as a single quiet label next to the View-all
link, with the project cards doing the actual work. Removes the
unused home.selected.headline key from all three locales.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 20:20:15 +02:00
c44ed31cdd feat: stacked EARTH WALKER / DESIGN wordmark
Carries forward the original site's wordmark — EARTH WALKER set in
serif semibold over a smaller, lighter, wider-tracked DESIGN —
adapted to use Fraunces from our type system. Centered stack, no
frame, themed via currentColor so it inverts cleanly on the dark
hero overlay and follows the active palette and theme.

Two sizes: 'sm' (header, footer, mobile drawer) scales text-sm →
text-base at md; 'lg' (home hero overlay) scales text-2xl → text-3xl
→ text-4xl across breakpoints. Whitespace-nowrap holds the shape
together regardless of container width.

Used in:
  - SiteHeader logo slot (sm)
  - Mobile Sheet drawer header (sm)
  - SiteFooter brand block (sm)
  - HomeView hero overlay above the headline (lg)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 20:19:47 +02:00
7 changed files with 61 additions and 27 deletions

View file

@ -1,6 +1,7 @@
<script setup lang="ts">
import { RouterLink } from 'vue-router'
import { useI18n } from 'vue-i18n'
import Wordmark from './Wordmark.vue'
const { t } = useI18n({ useScope: 'global' })
const year = new Date().getFullYear()
@ -11,8 +12,8 @@ const year = new Date().getFullYear()
<div
class="mx-auto flex max-w-[1400px] flex-col items-start justify-between gap-6 px-6 py-12 md:flex-row md:items-center md:px-10"
>
<div class="space-y-1">
<p class="font-serif text-base tracking-[0.18em] uppercase">{{ t('brand') }}</p>
<div class="space-y-3">
<Wordmark size="sm" class="text-foreground" />
<p class="text-muted-foreground text-xs">{{ t('footer.tagline') }}</p>
</div>
<div class="flex items-center gap-8">

View file

@ -12,6 +12,7 @@ import {
} from '@/components/ui/sheet'
import ThemeToggle from './ThemeToggle.vue'
import LocaleSwitcher from './LocaleSwitcher.vue'
import Wordmark from './Wordmark.vue'
const { t } = useI18n({ useScope: 'global' })
@ -32,9 +33,10 @@ const mobileOpen = ref(false)
>
<RouterLink
to="/"
class="text-foreground font-serif text-lg tracking-[0.18em] uppercase"
class="text-foreground inline-flex items-center"
:aria-label="t('brand')"
>
{{ t('brand') }}
<Wordmark size="sm" />
</RouterLink>
<nav class="hidden items-center gap-8 md:flex">
@ -63,9 +65,8 @@ const mobileOpen = ref(false)
</SheetTrigger>
<SheetContent side="right" class="w-full sm:max-w-sm">
<SheetHeader>
<SheetTitle class="font-serif tracking-[0.18em] uppercase">
{{ t('brand') }}
</SheetTitle>
<SheetTitle class="sr-only">{{ t('brand') }}</SheetTitle>
<Wordmark size="sm" class="text-foreground" />
</SheetHeader>
<nav class="mt-10 flex flex-col gap-6 px-4">
<RouterLink

View file

@ -0,0 +1,43 @@
<script setup lang="ts">
type Size = 'sm' | 'lg'
const props = withDefaults(
defineProps<{
/** Visual size — controls type scale. 'sm' for header/footer, 'lg' for hero. */
size?: Size
}>(),
{ size: 'sm' },
)
const earthClasses: Record<Size, string> = {
sm: 'text-sm tracking-[0.22em] md:text-base md:tracking-[0.24em]',
lg: 'text-2xl tracking-[0.24em] md:text-3xl lg:text-4xl md:tracking-[0.26em]',
}
const designClasses: Record<Size, string> = {
sm: 'text-[0.55rem] tracking-[0.42em] md:text-[0.65rem] md:tracking-[0.46em]',
lg: 'text-xs tracking-[0.46em] md:text-sm md:tracking-[0.5em] lg:text-base',
}
const gapClasses: Record<Size, string> = {
sm: 'gap-[0.2em]',
lg: 'gap-[0.25em]',
}
</script>
<template>
<span
:class="[
'inline-flex flex-col items-center whitespace-nowrap uppercase leading-none',
gapClasses[props.size],
]"
aria-label="Earth Walker Design"
>
<span :class="['font-serif font-semibold', earthClasses[props.size]]">
Earth Walker
</span>
<span :class="['font-serif font-light opacity-90', designClasses[props.size]]">
Design
</span>
</span>
</template>

View file

@ -26,8 +26,7 @@
"body": "The studio works closely with a small number of homes each year, slowly and intentionally — letting the architecture, the light, and the people who live there set the brief."
},
"selected": {
"eyebrow": "Selected work",
"headline": "Recent work."
"eyebrow": "Selected work"
},
"cta": {
"eyebrow": "Inquiries",

View file

@ -26,8 +26,7 @@
"body": "El estudio trabaja de cerca con un pequeño número de hogares cada año, despacio y con intención — dejando que la arquitectura, la luz y las personas que viven allí marquen el rumbo."
},
"selected": {
"eyebrow": "Obra seleccionada",
"headline": "Proyectos recientes."
"eyebrow": "Obra seleccionada"
},
"cta": {
"eyebrow": "Consultas",

View file

@ -26,8 +26,7 @@
"body": "Le studio accompagne chaque année quelques maisons, lentement et avec intention — en laissant l'architecture, la lumière, et les personnes qui y vivent guider la démarche."
},
"selected": {
"eyebrow": "Œuvre sélectionnée",
"headline": "Projets récents."
"eyebrow": "Œuvre sélectionnée"
},
"cta": {
"eyebrow": "Demandes",

View file

@ -4,6 +4,7 @@ import { RouterLink } from 'vue-router'
import { useI18n } from 'vue-i18n'
import { AspectRatio } from '@/components/ui/aspect-ratio'
import { Button } from '@/components/ui/button'
import Wordmark from '@/components/layout/Wordmark.vue'
import { projects } from '@/data/projects'
const { t } = useI18n({ useScope: 'global' })
@ -34,11 +35,9 @@ const projectCards = computed(() =>
<div
class="absolute right-0 bottom-14 left-0 mx-auto max-w-[1400px] px-6 text-white md:bottom-20 md:px-10"
>
<p class="text-xs uppercase tracking-[0.22em] text-white/80">
{{ t('home.hero.eyebrow') }}
</p>
<Wordmark size="lg" class="text-white/95" />
<h1
class="mt-4 max-w-3xl font-serif text-4xl font-light leading-[1.05] tracking-tight md:text-6xl lg:text-7xl"
class="mt-6 max-w-3xl font-serif text-4xl font-light leading-[1.05] tracking-tight md:text-6xl lg:text-7xl"
>
{{ t('home.hero.headline') }}<br />{{ t('home.hero.headline2') }}
</h1>
@ -63,15 +62,8 @@ const projectCards = computed(() =>
<!-- Projects teaser -->
<section class="border-border/60 border-t px-6 py-20 md:px-10 md:py-28">
<div class="mx-auto max-w-[1400px]">
<div class="flex items-baseline justify-between">
<div>
<p class="eyebrow">{{ t('home.selected.eyebrow') }}</p>
<h2
class="mt-3 font-serif text-3xl font-light tracking-tight md:text-5xl"
>
{{ t('home.selected.headline') }}
</h2>
</div>
<div class="flex items-center justify-between">
<p class="eyebrow">{{ t('home.selected.eyebrow') }}</p>
<RouterLink
to="/portfolio"
class="text-foreground/70 hover:text-foreground hidden text-xs uppercase tracking-[0.22em] transition-colors md:inline-flex"
@ -80,7 +72,7 @@ const projectCards = computed(() =>
</RouterLink>
</div>
<div class="mt-12 grid gap-10 md:grid-cols-2 md:gap-14">
<div class="mt-10 grid gap-10 md:grid-cols-2 md:gap-14">
<RouterLink
v-for="project in projectCards"
:key="project.slug"