Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions layouts/_default/baseof.html
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
<link rel="stylesheet" href="/css/fonts.css">
<!-- Custom styles for this template -->
<link rel="stylesheet" href="/css/design-system.css">
<link rel="stylesheet" href="/css/resume.css">
<link rel="stylesheet" href="/css/resume.css?v=2">
<link rel="stylesheet" href="/css/tweaks.css">
<link rel="stylesheet" href="/css/resume-override.css?v=2">
<link rel="stylesheet" href="/css/background.css">
Expand Down Expand Up @@ -82,7 +82,7 @@
<!-- <script defer src="/js/name-field.js"></script> -->
<script defer src="/js/name-disturbance.js"></script>
<script defer src="/js/achievements.js"></script>
<script defer src="/js/coin-flip.js"></script>
<script defer src="/js/coin-flip.js?v=2"></script>
<script defer src="/js/nav-scroll-reveal.js"></script>
<script defer src="/js/external-links.js"></script>
<script defer src="/js/interactive-embed.js?v=2"></script>
Expand Down
1 change: 1 addition & 0 deletions layouts/partials/nav.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
</div>
<div class="d-none d-lg-block">
<div id="profileCoin" class="mx-auto mb-2">
<div class="coin-ripple" aria-hidden="true"><span></span><span></span><span></span></div>
<div class="coin-side coin-front" style="background-image: image-set(url('{{ $frontWebp }}') type('image/webp'), url('{{ $frontImg }}') type('image/png'))"></div>
<div class="coin-side coin-back" style="background-image: image-set(url('/img/me-photo.webp') type('image/webp'), url('/img/me-photo.png') type('image/png'))"></div>
</div>
Expand Down
17 changes: 17 additions & 0 deletions static/js/coin-flip.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,19 @@ const coin = document.getElementById("profileCoin");
const mobileCoin = document.getElementById("mobileCoin");
const frontFace = coin?.querySelector(".coin-front");
const backFace = coin?.querySelector(".coin-back");
const ripple = coin?.querySelector(".coin-ripple");

// Water ripple behind the coin once it lands
function fireRipple() {
if (!ripple || (window.FIELD && window.FIELD.prefersReducedMotion())) return;
ripple.classList.remove("is-rippling");
void ripple.offsetWidth; // restart CSS animation
ripple.classList.add("is-rippling");
}

let flipping = false;
let showingReal = true; // front = real, back = generative
let rippleTimer = null;

function randomRange(min, max) {
return Math.random() * (max - min) + min;
Expand All @@ -34,6 +44,13 @@ function flipCoin() {
setTimeout(() => {
flipping = false;
}, lockDuration);

// Ripple lands slightly after the 600ms flip settles; reschedule if a
// second flip sneaks in between unlock (600ms) and ripple (700ms)
if (lockDuration) {
clearTimeout(rippleTimer);
rippleTimer = setTimeout(fireRipple, 700);
}
}

// Click handler (count only real clicks; auto-flips don't increment)
Expand Down
77 changes: 77 additions & 0 deletions themes/resume/static/css/resume.css
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,83 @@ a:hover, a:focus, a:active {
}
}

/* Water ripple — rings spread out from under the coin after it lands (triggered by
coin-flip.js). Rings paint above the faces (z-index 3) because the coin's ::before
drop shadow would otherwise bury them; starting at scale(1) hides the ring under
the coin's dark rim so it reads as emerging from behind. Transform/opacity only;
rings expand past the sidebar and fade to nothing, clipped at the blue edge. */
@media (min-width: 992px) {
#sideNav {
overflow: hidden; /* clip ripple rings to the blue sidebar */
}
}

.coin-ripple {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border-radius: 50%;
pointer-events: none;
z-index: 3;
}

/* Soft shadow-toned bands (not hairlines): thick low-alpha border + baked-in
box-shadow blur, painted once then transform-scaled — the blur diffuses as
the ring grows, reading as the coin's shadow dissolving into the water.
Colors sit between the coin's black drop shadow and the --brand teal. */
.coin-ripple span {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border-radius: 50%;
border: 8px solid rgba(16, 45, 66, 0.3);
box-shadow: 0 0 10px rgba(16, 45, 66, 0.25), inset 0 0 10px rgba(16, 45, 66, 0.25);
opacity: 0;
transform: scale(1);
}

.coin-ripple span:first-child {
/* impact band — blacker, the coin shadow "leaking" outward */
border-color: rgba(6, 20, 30, 0.35);
box-shadow: 0 0 10px rgba(6, 20, 30, 0.3), inset 0 0 10px rgba(6, 20, 30, 0.3);
}

.coin-ripple.is-rippling span {
animation: coin-ripple 1.5s cubic-bezier(0.15, 0.55, 0.45, 1) forwards;
}

.coin-ripple.is-rippling span:nth-child(2) {
animation-delay: 0.12s;
}

.coin-ripple.is-rippling span:nth-child(3) {
animation-delay: 0.24s;
}

@keyframes coin-ripple {
from {
opacity: 0.55;
transform: scale(1);
}
55% {
opacity: 0.18;
}
to {
opacity: 0;
transform: scale(4.75);
}
}

@media (prefers-reduced-motion: reduce) {
.coin-ripple span {
animation: none !important;
}
}

/* Nav scroll-reveal — mobile only */
@media (max-width: 991px) {
#sideNav {
Expand Down