release: promote beta to main (gyms, brand colours, JPEG XL, SEO per gym) #3

Merged
andre merged 74 commits from beta into main 2026-10-26 19:47:48 +00:00
2 changed files with 65 additions and 21 deletions
Showing only changes of commit 14dbabcad5 - Show all commits

No files matched your search

+59 -16
View File
@@ -437,14 +437,7 @@ section[id] {
.gym-switch-btn { display: inline-flex; align-items: center; gap: .5rem; } .gym-switch-btn { display: inline-flex; align-items: center; gap: .5rem; }
/* With a logo the button shows the gym's wordmark in its own colours on a
light face, framed by the brand colour; the name is the image's alt. The
hover face stays light too, so dark parts of the logo never vanish. */
.gym-switch-btn--logo {
--btn-face: #fff;
background: #fff;
padding: 4px 12px;
}
.gym-switch-logo { .gym-switch-logo {
display: block; display: block;
height: 30px; height: 30px;
@@ -520,6 +513,34 @@ section[id] {
.gym-switch-btn:is(:hover, :focus-visible)::before, .gym-switch-btn:is(:hover, :focus-visible)::after { animation: none; } .gym-switch-btn:is(:hover, :focus-visible)::before, .gym-switch-btn:is(:hover, :focus-visible)::after { animation: none; }
} }
/* With a logo the button shows the gym's wordmark in its own colours straight
on the navbar (no face, like the main logo), framed by a thin brand-colour
outline; the name is the image's alt. On hover nothing fills in behind the
logo: ::before is masked down to just its ring, so only the spinning edge
shows. */
.gym-switch-btn--logo,
.gym-switch-btn--logo:is(:hover, :focus-visible) {
background: transparent;
}
.gym-switch-btn--logo {
padding: 4px 12px;
border-width: 1px;
}
.gym-switch-btn--logo::before {
background: conic-gradient(from var(--pc-a), rgba(var(--fitme-accent-rgb), 0) 0deg, rgba(var(--fitme-accent-rgb), 0) 150deg,
var(--fitme-accent) 250deg, #f4ff9c 300deg, var(--fitme-accent) 330deg,
rgba(var(--fitme-accent-rgb), 0) 360deg) border-box;
-webkit-mask: linear-gradient(#000 0 0) padding-box, linear-gradient(#000 0 0);
-webkit-mask-composite: xor;
mask: linear-gradient(#000 0 0) padding-box exclude, linear-gradient(#000 0 0);
}
/* No glow either: blurred brand colour behind a dark-red wordmark muddies it.
A thin light halo keeps the logo legible over whatever shows through the
frosted navbar. */
.gym-switch-btn--logo::after,
.gym-switch-btn--logo:is(:hover, :focus-visible)::after { display: none; }
.gym-switch-btn--logo .gym-switch-logo { filter: drop-shadow(0 0 1.5px rgba(255, 255, 255, .9)); }
/* ── Sticky Navbar ─────────────────────────────────────────────────────────── */ /* ── Sticky Navbar ─────────────────────────────────────────────────────────── */
.navbar-toggler { .navbar-toggler {
min-width: 44px; min-width: 44px;
@@ -3836,6 +3857,33 @@ h3.contact-title {
background-image: var(--metal-layers); background-image: var(--metal-layers);
background-size: var(--metal-sizes); background-size: var(--metal-sizes);
color: var(--fitme-ash); color: var(--fitme-ash);
position: relative;
isolation: isolate;
}
/* Slow brand-colour light drifting over the metal: three soft blobs in the
current gym's colour (and a paler tint of it) on a 200% layer whose position
eases back and forth. Sits above the section background, below the content. */
.pricing-section::before {
content: '';
position: absolute;
inset: 0;
z-index: -1;
pointer-events: none;
background:
radial-gradient(38% 50% at 18% 28%, rgba(var(--fitme-accent-rgb), .4), transparent 70%),
radial-gradient(34% 46% at 82% 72%, color-mix(in srgb, color-mix(in srgb, var(--fitme-accent) 55%, #fff) 26%, transparent), transparent 70%),
radial-gradient(30% 42% at 55% 105%, rgba(var(--fitme-accent-rgb), .32), transparent 70%);
background-size: 200% 200%;
animation: pricing-drift 26s ease-in-out infinite alternate;
}
@keyframes pricing-drift {
0% { background-position: 0% 0%; }
50% { background-position: 100% 40%; }
100% { background-position: 30% 100%; }
}
@media (prefers-reduced-motion: reduce) {
.pricing-section::before { animation: none; }
} }
.pricing-section .section-title h2 { color: #fff; } .pricing-section .section-title h2 { color: #fff; }
@@ -4610,14 +4658,10 @@ h3.contact-title {
} }
/* ── "In the middle of the screen" = hovered ───────────────────────────────────── /* ── "In the middle of the screen" = hovered ─────────────────────────────────────
main.js adds .is-centered to the photo / card / icon that sits on the vertical main.js adds .is-centered to the trainer photo / card / icon that sits on the vertical
middle of the viewport (and, inside the sliding strips, on the horizontal middle of the viewport (and, inside the Modalidades strip, on the horizontal
middle too), so scrolling past shows the same state as a hover. These mirror middle too; the gallery photos only react to a real hover), so scrolling past shows the same state as a hover. These mirror
the :hover rules above. ─────────────────────────────────────────────────── */ the :hover rules above. ─────────────────────────────────────────────────── */
.gal-tile.is-centered .gal-link img { transform: scale(1.06); filter: saturate(1) brightness(1.05); }
.gal-tile.is-centered .gal-link::before { opacity: 1; }
.gal-tile.is-centered .gal-link::after { opacity: 1; animation: pc-spin 3.2s linear infinite; }
.trainer-item .trainer-pic.is-centered, .trainer-item .trainer-pic.is-centered,
#powerRotation>div:nth-child(even) .trainer-pic.is-centered { #powerRotation>div:nth-child(even) .trainer-pic.is-centered {
transform: rotate(0deg) translateY(-8px) scale(1.05); transform: rotate(0deg) translateY(-8px) scale(1.05);
@@ -4658,7 +4702,6 @@ h3.contact-title {
} }
.price-card.is-centered::after { opacity: .75; animation: pc-spin 3.2s linear infinite; } .price-card.is-centered::after { opacity: .75; animation: pc-spin 3.2s linear infinite; }
@media (prefers-reduced-motion: reduce) { @media (prefers-reduced-motion: reduce) {
.gal-tile.is-centered .gal-link::after,
.trainer-item .trainer-pic.is-centered, .trainer-item .trainer-pic.is-centered,
.icon-box-item.is-centered .ib-icon::after, .icon-box-item.is-centered .ib-icon::after,
.price-card.is-centered::before, .price-card.is-centered::after { animation: none; } .price-card.is-centered::before, .price-card.is-centered::after { animation: none; }
+6 -5
View File
@@ -759,16 +759,17 @@ document.addEventListener('DOMContentLoaded', function () {
}); });
/* ── Scroll "hover": what sits in the middle of the screen looks hovered ─────── /* ── Scroll "hover": what sits in the middle of the screen looks hovered ───────
Photos, cards and icons get .is-centered while their box crosses the middle Trainer photos, cards and icons get .is-centered while their box crosses the
of the viewport (±12% of its height); inside a sliding strip (gallery, middle of the viewport (±12% of its height); inside a sliding strip
Modalidades) they must also cross the horizontal middle. Throttled, paused (Modalidades) they must also cross the horizontal middle. Gallery photos are
left out: they only light up on a real hover. Throttled, paused
while the tab is hidden, skipped with "reduce motion". The CSS mirrors the while the tab is hidden, skipped with "reduce motion". The CSS mirrors the
:hover rules (style.css, "In the middle of the screen"). */ :hover rules (style.css, "In the middle of the screen"). */
document.addEventListener('DOMContentLoaded', function () { document.addEventListener('DOMContentLoaded', function () {
if (window.matchMedia && matchMedia('(prefers-reduced-motion: reduce)').matches) return; if (window.matchMedia && matchMedia('(prefers-reduced-motion: reduce)').matches) return;
var items = Array.prototype.slice.call(document.querySelectorAll( var items = Array.prototype.slice.call(document.querySelectorAll(
'.gal-tile, .trainer-item .trainer-pic, .icon-box-item, .price-card')).map(function (el) { '.trainer-item .trainer-pic, .icon-box-item, .price-card')).map(function (el) {
return { el: el, strip: !!el.closest('.gal-marquee, .mod-scroll'), on: false }; return { el: el, strip: !!el.closest('.mod-scroll'), on: false };
}); });
if (!items.length) return; if (!items.length) return;
var last = 0; var last = 0;