Persönlichkeitscoach-Zertifikat über Greator Speaker

Anelias neues Greator-Zertifikat (Persönlichkeitscoach, 09.10.2026) steht
in „Über Anelia“ über dem Speaker-Abzeichen, im selben Lorbeerkranz mit
freigestelltem Siegel, Hover und Vorschau-Overlay. Das Siegel ist aus dem
PDF freigestellt (Kreis, 150-dpi-Raster), Farbe und Form unverändert.

getCertificate() wird zu getCertificates(): eine Liste, das neueste oben.
Ein einzelnes Abzeichen klebt weiter auf Höhe der „04“. Zwei passen dort
nicht ins Bild, also steht der Stapel still und beginnt auf Höhe der
Eyebrow. Unter lg stehen sie nebeneinander, auf dem Handy untereinander.

Der Abzeichen-Titel darf umbrechen (Zeilenhöhe 1,4, Ränder ausgeglichen;
einzeilig unverändert). Der Dialog-Titel trennt Silben, damit
„Persönlichkeitscoach“ auf dem Handy „Schließen“ nicht aus dem Bild
schiebt. Jeder Dialog bekommt seine eigene Titel-ID (useId).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
knsoandClaude Opus 5.5 committed 2026-10-21 17:01:12 +00:00
1 parent 30e9151de4
commit 1e7b84b27c
10 files changed
+124 -60

No files matched your search

+6 -2
View File
@@ -63,11 +63,15 @@ export function Certificate({ content, asset, className }: CertificateProps) {
</span>
</span>
<span className="mt-6 block font-mono text-xs uppercase leading-none tracking-[0.18em] text-accent">
{/* Zeilenhöhe 1,4 statt 1, damit ein umbrechender Titel („Greator
Persönlichkeitscoach“) nicht zusammenklebt. Die Ränder davor und danach
sind um den halben Durchschuss (0,15 rem) kürzer – einzeilig steht alles
wie zuvor mit `leading-none`, `mt-6` und `mt-5`. */}
<span className="mt-[1.35rem] block font-mono text-xs uppercase leading-[1.4] tracking-[0.18em] text-accent">
{content.title}
</span>
<span aria-hidden="true" className="rule-gold mt-5 block h-px w-full" />
<span aria-hidden="true" className="rule-gold mt-[1.1rem] block h-px w-full" />
<span className="mt-5 block font-sans text-[0.875rem] leading-[1.5] text-fg [hyphens:auto]">
{content.description}
+10 -8
View File
@@ -1,14 +1,11 @@
"use client";
import { useEffect, useLayoutEffect, useRef, useState } from "react";
import { useEffect, useId, useLayoutEffect, useRef, useState } from "react";
import { createPortal } from "react-dom";
import type { CertificateAsset } from "@/lib/assets";
import type { CertificateCopy } from "@/content/home";
import { gsap, DUR, EASE, MM, getLenis, refreshSoon } from "@/lib/gsap";
/** Die Überschrift benennt den Dialog (`aria-labelledby`) – es gibt genau einen. */
const TITLE_ID = "zertifikat-titel";
/**
* Kopf, Blatt und Fußzeile teilen sich eine Breite, sonst stehen sie versetzt.
* Auf dem Desktop richtet sie sich nach der Höhe: das Blatt soll ganz ins Bild
@@ -39,6 +36,8 @@ export interface CertificateDialogProps {
* Dialog in seinem eigenen toten Bereich.
*/
export function CertificateDialog({ open, onClose, content, asset }: CertificateDialogProps) {
/* Die Überschrift benennt den Dialog (`aria-labelledby`) – je Zertifikat ein Dialog. */
const titleId = useId();
const panel = useRef<HTMLDivElement>(null);
const onCloseRef = useRef(onClose);
@@ -138,7 +137,7 @@ export function CertificateDialog({ open, onClose, content, asset }: Certificate
ref={panel}
role="dialog"
aria-modal="true"
aria-labelledby={TITLE_ID}
aria-labelledby={titleId}
data-theme="dark"
data-lenis-prevent=""
onClick={(e) => {
@@ -148,12 +147,15 @@ export function CertificateDialog({ open, onClose, content, asset }: Certificate
className="fixed inset-0 z-50 flex flex-col items-center overflow-y-auto overscroll-contain bg-ink px-5 py-[calc(var(--header-h,60px)/2+16px)] text-fg lg:px-10"
>
<div className={`mb-8 flex items-start justify-between gap-6 ${COLUMN}`}>
<div>
{/* `min-w-0` + Silbentrennung: „Persönlichkeitscoach“ ist auf dem Handy
breiter als der Platz neben „Schließen“ und schöbe den Knopf sonst
aus dem Bild. */}
<div className="min-w-0">
<p className="font-mono text-xs uppercase tracking-[0.12em] text-accent">{content.eyebrow}</p>
{/* Playfair hat hier den Platz für seine 28-px-Untergrenze – im Abzeichen selbst nicht. */}
<h2
id={TITLE_ID}
className="mt-3 font-display text-[clamp(1.75rem,1.2rem+1vw,2.25rem)] font-normal leading-none tracking-[-0.01em] text-fg"
id={titleId}
className="mt-3 font-display text-[clamp(1.75rem,1.2rem+1vw,2.25rem)] font-normal leading-none tracking-[-0.01em] text-fg [hyphens:auto]"
>
{content.title}
</h2>