diff --git a/CLAUDE.md b/CLAUDE.md index 22fd693..026a3b4 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -79,7 +79,7 @@ Since 2026-09-25, one install serves several physical gyms: the `gyms` table, on folder per gym (`/3070/`, `//`), content rows carry `gym_id`, and the backoffice has an "a editar" gym switcher (`admin_gym_id()` / `admin_gym()` in `config/functions_gyms.php`). `/` and `/home` 301 to the default gym (`is_default`); the other published gyms appear as highlighted buttons (`.gym-switch-btn`) at the right end of the public navbar (`site/includes/navbar.php`). `site/gym_chooser.php` is no longer used. -Each gym has a brand colour (`gyms.brand_color`, `#RRGGBB`, migration `migration_20261013_gym_brand_color.sql`; gym 1 = green `#C2D500`, gym 2 = red): set in Gestão → Ginásios, emitted as `:root` overrides by `gym_brand_css()` in `site/includes/include.php`. New components must use `--fitme-accent*` / `--fitme-on-accent`, never a hard-coded colour; the CrossFit nav pill follows the brand colour too. The public navbar's bottom edge is an always-on, slow (14s) sweep in the brand colour (`.header-section::before/::after`, `nav-sweep`, static with reduced motion). On the home page (`$nav_center_logo` set in `site/index.php`, shared by `_open.php`) the header starts with the logo big (240px) and centred on its own row (`.has-center-logo.is-top`, desktop >= 992px only) and docks back to the 150px left logo once `scrollY >= 40` (script in `navbar.php`); the logo width lives in CSS (`.navbar-brand img`), not inline. The nav underline (`.nav-link:after`) is a 4px bar 3px under the text with slashed ends (`clip-path`, like the "in" box of the FitMe in logo). The hero event card (`.hero-event`) is square (no radius on card, badge or button), taller (88px min) and has a defocus gradient: `::after` is a `backdrop-filter: blur()` layer masked left->right, sharp on the left and most blurred on the right; the card itself must not get filter/backdrop-filter/opacity/mask or the blur stops reaching the hero photo. Each gym can have a `logo` (same migration, plus `migration_20261026_gym_logo.sql`: the column was added to the 2026-10-13 file after it had already run on dev, so dev had no `logo` column until 2026-10-26 — never edit a migration that has run, add a new one); the header image and the logo are uploaded in Gestão → Ginásios (`gyms_save_image()` → `uploads/gyms/`, validated by content, SVG through `svg_is_safe()`), not typed as paths; `db_gyms_create/update` skip `brand_color`/`logo` while the migration isn't applied (`_gyms_cols()`); the navbar button for another gym is drawn in that gym's brand colour (`gym_brand_vars()` inline); with a logo (`gym_logo()`: the gym's own, or for the default gym the bundled `logo_black.svg`) the button shows the logo in full colour straight on the frosted navbar, with no face and no darkening on hover (`.gym-switch-btn--logo`: thin brand outline, hover = spinning ring only, no glow, a thin dark `drop-shadow` outline on the image for contrast (a white halo washed out the lime FitMe 3070 logo); name as alt), without one it shows the name. The navbar brand on each gym's page uses that gym's logo too. Uploads (header + logo) also accept JPEG XL (`.jxl`, detected by signature in `upload_image_ext()` when the caller allows `'jxl'`; the gyms form and gallery photos (`db_gallery_image_upload()`) do; `AddType image/jxl` in `.htaccess`; GD can't resize it, so it is stored as uploaded; Chrome/Firefox may not display JXL, Safari does). The public gallery lists its folder by extension (`site/includes/gallery.php`, `site/index.php`: jpg/jpeg/png/gif/webp/jxl; before 2026-10-26 it only listed `*.jpg`, so PNG/WebP uploads never showed). Gallery photos are not in the scroll "hover" (`.is-centered`, main.js) any more; only a real hover lights them. Mensalidades (`.pricing-section::before`) has a slow (26s) drifting brand-colour glow over the metal texture (`pricing-drift`, static with reduced motion). +Each gym has a brand colour (`gyms.brand_color`, `#RRGGBB`, migration `migration_20261013_gym_brand_color.sql`; gym 1 = green `#C2D500`, gym 2 = red): set in Gestão → Ginásios, emitted as `:root` overrides by `gym_brand_css()` in `site/includes/include.php`. New components must use `--fitme-accent*` / `--fitme-on-accent`, never a hard-coded colour; the CrossFit nav pill follows the brand colour too. The public navbar's bottom edge is an always-on, slow (14s) sweep in the brand colour (`.header-section::before/::after`, `nav-sweep`, static with reduced motion). On the home page (`$nav_center_logo` set in `site/index.php`, shared by `_open.php`) the header starts taller with the logo big (240px) and centred (`.has-center-logo.is-top`, desktop >= 992px only) and glides back (0.5s on padding-top/left/top/transform/width) to the 150px left logo once `scrollY >= 40` (script in `navbar.php`). On desktop the brand and the other-gym buttons (`.gym-switch`) are absolutely positioned (brand left, switch right and vertically centred on the whole header, even when tall), so the links are centred on the full bar width; nav padding and logo width live in CSS, not inline. Logos (`.navbar-brand img`, `.gym-switch-logo`) get the same `#pt-noise` grain filter as h1/h2, and `.hero-event-go`, `.cta-btn`, `.btn-primary` joined the `--noise` button list. Section-title underlines (`.section-title.deco h2:after`) use the same slashed 4px bar as the nav underline. The hero event button text uses `--fitme-on-accent` (white on red). The nav underline (`.nav-link:after`) is a 4px bar 3px under the text with slashed ends (`clip-path`, like the "in" box of the FitMe in logo). The hero event card (`.hero-event`) is square (no radius on card, badge or button), taller (88px min) and has a defocus gradient: `::after` is a `backdrop-filter: blur()` layer masked left->right, sharp on the left and most blurred on the right; the card itself must not get filter/backdrop-filter/opacity/mask or the blur stops reaching the hero photo. Each gym can have a `logo` (same migration, plus `migration_20261026_gym_logo.sql`: the column was added to the 2026-10-13 file after it had already run on dev, so dev had no `logo` column until 2026-10-26 — never edit a migration that has run, add a new one); the header image and the logo are uploaded in Gestão → Ginásios (`gyms_save_image()` → `uploads/gyms/`, validated by content, SVG through `svg_is_safe()`), not typed as paths; `db_gyms_create/update` skip `brand_color`/`logo` while the migration isn't applied (`_gyms_cols()`); the navbar button for another gym is drawn in that gym's brand colour (`gym_brand_vars()` inline); with a logo (`gym_logo()`: the gym's own, or for the default gym the bundled `logo_black.svg`) the button shows the logo in full colour straight on the frosted navbar, with no face and no darkening on hover (`.gym-switch-btn--logo`: thin brand outline, hover = spinning ring only, no glow, a thin dark `drop-shadow` outline on the image for contrast (a white halo washed out the lime FitMe 3070 logo); name as alt), without one it shows the name. The navbar brand on each gym's page uses that gym's logo too. Uploads (header + logo) also accept JPEG XL (`.jxl`, detected by signature in `upload_image_ext()` when the caller allows `'jxl'`; the gyms form and gallery photos (`db_gallery_image_upload()`) do; `AddType image/jxl` in `.htaccess`; GD can't resize it, so it is stored as uploaded; Chrome/Firefox may not display JXL, Safari does). The public gallery lists its folder by extension (`site/includes/gallery.php`, `site/index.php`: jpg/jpeg/png/gif/webp/jxl; before 2026-10-26 it only listed `*.jpg`, so PNG/WebP uploads never showed). Gallery photos are not in the scroll "hover" (`.is-centered`, main.js) any more; only a real hover lights them. Mensalidades (`.pricing-section::before`) has a slow (26s) drifting brand-colour glow over the metal texture (`pricing-drift`, static with reduced motion). An unpublished gym 404s publicly but previews for staff. ## Imagens / JPEG XL (2026-10-26) diff --git a/site/assets/css/style.css b/site/assets/css/style.css index c1c45c6..56a99a1 100644 --- a/site/assets/css/style.css +++ b/site/assets/css/style.css @@ -543,7 +543,7 @@ section[id] { .gym-switch-btn--logo::after, .gym-switch-btn--logo:is(:hover, :focus-visible)::after { display: none; } /* Thin dark outline, not a white halo: a white glow washed out the lime FitMe 3070 logo. */ -.gym-switch-btn--logo .gym-switch-logo { filter: drop-shadow(0 0 .6px rgba(0, 0, 0, .55)) drop-shadow(0 1px 1px rgba(0, 0, 0, .18)); } +.gym-switch-btn--logo .gym-switch-logo { filter: url(#pt-noise) drop-shadow(0 0 .6px rgba(0, 0, 0, .55)) drop-shadow(0 1px 1px rgba(0, 0, 0, .18)); } /* ── Sticky Navbar ─────────────────────────────────────────────────────────── */ .navbar-toggler { @@ -593,24 +593,53 @@ section[id] { to { background-position: 150% 0; } } -/* Brand logo: 150px in the bar. On the home page (.has-center-logo) it starts - bigger on its own centred row (.is-top) and docks back on scroll (navbar.php). */ +/* Bar layout. Desktop: the links are centred on the full bar width, the logo + sits out of flow at the left and the other-gym buttons out of flow at the + right, vertically centred on the whole header. On the home page + (.has-center-logo) the header starts taller with the logo bigger and centred + (.is-top); on scroll everything glides back (navbar.php toggles .is-top). */ +.header-section .navbar { padding: 0 0 0 1rem; } .navbar-brand img { width: 150px; height: auto; - transition: width .35s ease; + transition: width .5s cubic-bezier(.4, 0, .2, 1); } @media (min-width: 992px) { - .header-section.is-top .navbar { flex-wrap: wrap; } - .header-section.is-top .navbar-brand { - flex: 0 0 100%; - display: flex; - justify-content: center; + .header-section .navbar { + padding: 0; + transition: padding-top .5s cubic-bezier(.4, 0, .2, 1); + } + .header-section .navbar-brand { + position: absolute; + z-index: 1; + left: 1rem; + top: 50%; margin: 0; - padding: 14px 1rem 0 0; /* 1rem offsets the nav's left padding: true centre */ + transform: translate(0, -50%); + transition: left .5s cubic-bezier(.4, 0, .2, 1), top .5s cubic-bezier(.4, 0, .2, 1), transform .5s cubic-bezier(.4, 0, .2, 1); + } + .header-section .navbar-collapse { + min-height: 58px; + align-items: center; + } + .header-section .gym-switch { + position: absolute; + right: 1rem; + top: 50%; + transform: translateY(-50%); + padding: 0 !important; + } + .header-section.is-top .navbar { padding-top: 96px; } /* room for the 240px logo */ + .header-section.is-top .navbar-brand { + left: 50%; + top: 14px; + transform: translate(-50%, 0); } .header-section.is-top .navbar-brand img { width: 240px; } } +@media (prefers-reduced-motion: reduce) { + .header-section .navbar, .header-section .navbar-brand, .navbar-brand img { transition: none; } +} @media (prefers-reduced-motion: reduce) { .header-section::before, .header-section::after { animation: none; } @@ -2542,9 +2571,9 @@ h3.contact-title { bottom: 0; transform: translateX(-50%); width: 64px; - height: 3px; - border-radius: 2px; + height: 4px; background: var(--fitme-accent); + clip-path: polygon(4px 0, 100% 0, calc(100% - 4px) 100%, 0 100%); /* slashed ends, as .nav-link:after */ } .section-subtitle { @@ -3364,7 +3393,7 @@ h3.contact-title { font-size: .92rem; font-weight: 700; white-space: nowrap; - color: var(--fitme-dark); + color: var(--fitme-on-accent); /* white on the red gym, dark on lime */ background: var(--ev-accent); } .hero-event-go i { transition: transform var(--fitme-transition); } @@ -4777,9 +4806,16 @@ a:where(:not(.site-btn, .gym-switch-btn, .gal-link, .skip-link, .splide__arrow, } .site-btn, .gym-switch-btn, -.crossfit-nav-link { +.crossfit-nav-link, +.hero-event-go, +.cta-btn, +.btn-primary { background-image: var(--noise) !important; background-size: 155px 155px !important; background-blend-mode: overlay !important; } -h1, h2 { filter: url(#pt-noise); } +/* Logos get the same grain as the headings (the logo gym buttons add their + drop-shadow after it, see .gym-switch-btn--logo). */ +h1, h2, +.navbar-brand img, +.gym-switch-logo { filter: url(#pt-noise); } diff --git a/site/includes/navbar.php b/site/includes/navbar.php index defa519..615037b 100644 --- a/site/includes/navbar.php +++ b/site/includes/navbar.php @@ -14,7 +14,7 @@ $logo_dims = svg_img_dims_attr(dirname(__DIR__, 2) . '/' . $logo_rel); $center_logo = !empty($nav_center_logo); ?>