From f04e8c8463c7ce5864b13944f7d0eaa0fbd3f355 Mon Sep 17 00:00:00 2001
From: Marc Mintel
Date: Sun, 4 Oct 2026 14:47:11 +0200
Subject: [PATCH] feat: contact address with a sheen and a light on its
underline
The address is the one thing to act on in the contact section, but it was a
plain underlined line next to a glowing message card. A slow sheen now runs
through the letters and a light travels along the underline; on hover the
whole line lights up.
Co-Authored-By: Claude Opus 5.5
---
apps/web/app/globals.css | 81 +++++++++++++++++++++
apps/web/src/components/home/ClosingCta.tsx | 2 +-
2 files changed, 82 insertions(+), 1 deletion(-)
diff --git a/apps/web/app/globals.css b/apps/web/app/globals.css
index faa4d0d..e574f24 100644
--- a/apps/web/app/globals.css
+++ b/apps/web/app/globals.css
@@ -1224,6 +1224,87 @@ pre:has(code[class*="language-"]) {
}
}
+/*
+ * The contact address on a dark surface: a slow sheen runs through the letters
+ * and a light travels along the underline. On hover the whole line lights up.
+ */
+.bit-mail {
+ position: relative;
+ display: inline-block;
+ padding-bottom: 0.42em;
+ background: linear-gradient(
+ 100deg,
+ #ffffff 0 38%,
+ #a5b4fc 50%,
+ #ffffff 62% 100%
+ );
+ background-size: 260% 100%;
+ -webkit-background-clip: text;
+ background-clip: text;
+ color: transparent;
+ -webkit-text-fill-color: transparent;
+ animation: bit-mail-sheen 7s ease-in-out infinite;
+ transition: filter 300ms ease;
+}
+.bit-mail::before,
+.bit-mail::after {
+ content: "";
+ position: absolute;
+ left: 0;
+ right: 0;
+ border-radius: 4px;
+ pointer-events: none;
+}
+/* The resting underline. */
+.bit-mail::before {
+ bottom: 1px;
+ height: 2px;
+ background: rgba(255, 255, 255, 0.26);
+}
+/* The light travelling along it. */
+.bit-mail::after {
+ bottom: 0;
+ height: 4px;
+ background: linear-gradient(
+ 90deg,
+ transparent,
+ #818cf8 30%,
+ #ffffff 50%,
+ #818cf8 70%,
+ transparent
+ )
+ no-repeat;
+ background-size: 42% 100%;
+ filter: drop-shadow(0 0 8px rgba(129, 140, 248, 0.95));
+ animation: bit-mail-run 3.8s ease-in-out infinite alternate;
+ transition: background-size 400ms ease;
+}
+@media (hover: hover) {
+ .bit-mail:hover {
+ filter: drop-shadow(0 0 18px rgba(129, 140, 248, 0.7));
+ }
+ .bit-mail:hover::after {
+ background-size: 100% 100%;
+ }
+}
+@keyframes bit-mail-sheen {
+ 0%,
+ 100% {
+ background-position: 100% 0;
+ }
+ 50% {
+ background-position: 0% 0;
+ }
+}
+@keyframes bit-mail-run {
+ from {
+ background-position: -30% 0;
+ }
+ to {
+ background-position: 130% 0;
+ }
+}
+
/* Slow light drifting over a dark picture (see PortraitSection). */
.bit-aurora {
position: absolute;
diff --git a/apps/web/src/components/home/ClosingCta.tsx b/apps/web/src/components/home/ClosingCta.tsx
index ff67661..5e7b792 100644
--- a/apps/web/src/components/home/ClosingCta.tsx
+++ b/apps/web/src/components/home/ClosingCta.tsx
@@ -38,7 +38,7 @@ export const ClosingCta: React.FC<{ contact: Content["contact"] }> = ({
{contact.lead}
-
+