img_optimize() decodes .jxl with djxl or Imagick, resizes with GD, re-encodes
with cjxl and writes foto.jxl.webp beside it; skips cleanly without a decoder.
Gallery, hero, navbar logos and JSON-LD serve the JXL with the fallback, and
trash/removal move the fallback with its .jxl.
- "Ver Horário das aulas" desaparece assim que o acordeão abre (clique no
próprio botão ou o link "Horário" da navbar a abrir por JS) — deixa de
ficar um botão grande por cima da grelha já visível.
- Setas ‹ › junto ao dia em foco também no desktop (vista de 3 dias): só o
dia central as mostra, os laterais continuam sem elas (já são clicáveis
diretamente).
- Deslizar no telemóvel/tablet muda de dia, com o mesmo efeito das setas —
só reage a arrastos maioritariamente horizontais, para não roubar o
scroll vertical da página.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Informações e contactos: os ícones fas ao lado do texto saem (desalinhavam
em layout centrado — fa-envelope é mais largo que os outros e o texto ficava
a começar em posições diferentes). Horário de Funcionamento deixa de ser
cartões (dt/dd com barra escura) e passa a texto simples centrado, uma
linha por dia, a condizer com o resto da coluna.
- Textarea "Mensagem" deixa de esticar até à base do mapa (chegava a 763px
de altura, vazio) — volta ao min-height:150px + resize:vertical do CSS.
- CrossFit: removida a secção "A nossa Localização" duplicada, agora que a
página tem a sua própria secção de Contactos com mapa incluído.
- Reviews: "Ver todas no Google" passa a link de texto simples (sublinhado);
"Deixa a tua review" mantém-se o botão em destaque.
- api/health.php, api/hub_ops.php, api/hub_pair.php: stubs de uma linha para
o platform-tools (mesmo padrão da fotografia/design/dance) — preparam a
entrada do fitme3070 na Frota do hub.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Horário de aulas (home e CrossFit, mesmo componente partilhado): removida
a barra de botões Seg/Ter/Qua/Qui/Sex/Sab acima da grelha — o próprio
cabeçalho do dia (já existente) passa a ser sempre visível (antes só em
desktop, 3 dias) e ganha setas ‹ › ao lado do nome do dia para mudar de
dia em ecrãs de telemóvel/tablet. No desktop (3 dias lado a lado) as
setas ficam escondidas — clicar no dia lateral já muda o dia em foco.
CSS/JS morto do botão-filtro removido.
- Informações e contactos extraído para site/includes/contactos.php,
partilhado pela home e pelo CrossFit — a página CrossFit ganha a mesma
secção de contactos (localização, telefone, e-mail, horário de
funcionamento, mapa, formulário) em vez de só linkar de volta à home.
Hero e restantes secções do CrossFit não foram tocados.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Auditoria: "Site público em Bootstrap 4.3.1 (EOL); backoffice em
5.3.3" — o backoffice já usa a 5.3.3 vendorizada (assets/vendor/bootstrap5/),
o site público passa a usar a mesma cópia em vez da 4.3.1.
Levantamento antes de mexer: a folha de estilo própria (style.css)
quase não usa classes utilitárias cruas do Bootstrap (grep confirma
zero ml-/mr-/pl-/pr-/float-left/float-right/custom-select/
custom-control/badge-/sr-only/font-weight-/text-left/text-right —
tudo classes próprias como .site-btn). O que precisava de mudar:
- CSS/JS: assets/vendor/bootstrap/ -> assets/vendor/bootstrap5/
(bundle, inclui Popper).
- Os 7 atributos data-toggle/data-target/data-dismiss (BS4) ->
data-bs-toggle/data-bs-target/data-bs-dismiss (BS5): toggle da nav
mobile, os dois modais (aula experimental, inscrição), o botão de
fechar do alerta. O seletor em main.js que lê data-target também
mudou para não parar de encontrar os botões.
- .close -> .btn-close (BS5 renomeou o componente; markup sem o
× interno, que o BS5 desenha via CSS).
- .form-row -> .row (BS4 tinha form-row com gutters menores; BS5 não
tem, style.css não tinha overrides para form-row, confirmado).
- O apanhado maior: dois <script> inline chamavam
jQuery('#trialModal').modal('show') ao estilo de plugin jQuery do
BS4 (para reabrir o modal depois de um erro de submissão) — o BS5
não regista plugins jQuery nenhuns, isto ficava morto em silêncio.
Trocado por new bootstrap.Modal(...).show(), a API JS nativa do
BS5. grep confirma zero outras chamadas .modal()/.collapse()/etc.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Modalidades: reduce gap between cards
- Horário: drop the day-title above the grid in single-day mode (the active
day-filter button already names it); restyle "Guardar horário" as a plain
link and drop the "(JPG)" suffix
- Mensalidades: give "Escolhe o teu plano" the same dark hammered-metal
background as the reviews/footer sections instead of the plain light one
- «Conhece as nossas instalações» (e a galeria do CrossFit) passa de slider
Splide a masonry: layout próprio em JS (sem biblioteca), fotos com a
proporção original, coluna mais baixa primeiro e algumas a ocupar duas
colunas (só quando não deixam buraco). Reorganiza ao mudar de largura
(ResizeObserver + resize) e as fotos entram em cascata ao aparecer.
Sem JS fica uma grelha CSS.
- Clicar abre a foto num <dialog>: anterior/seguinte, setas, Esc, deslizar.
- O Splide deixa de ser carregado (CSS e JS).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Ícones novos (Bootcamp, YourFit Core, Run3070, Total Workout, On Ramp, Jump)
do mesmo conjunto; só o LPO continua sem ícone no ficheiro de design.
- Os ícones fitme-*.svg passam a ir embutidos (modalidade_icon_html): cada
traço tem pathLength=1 e desenha-se ao aparecer, no hover e ao abrir o
cartão; cada família tem um movimento (levantar, soco, respirar, saltar,
chama, pedalar, correr). Outros ícones continuam <img>.
- No cartão de detalhe (desktop) o ícone e o nome deslizam até ao centro
vertical da coluna.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Mensalidades: ao passar o rato, a borda do cartão ganha um brilho verde num
conic-gradient que roda (@property --pc-a animável), centrado no cursor; o
cartão inclina-se e desliza para o rato como os da equipa.
- «O que dizem de nós» e rodapé: textura discreta de metal preto mate (grão de
pintura eletrostática, brilho difuso, riscas quase invisíveis), em SVG/CSS.
- Contactos: o site lê só fitme3070_info (Gestão → Contactos). Os campos
contact_*/social_* de Sistema → Definições não eram usados e foram editados
por engano — saem do formulário, com um aviso a apontar para Contactos.
site_info() deixa o WhatsApp só com dígitos (wa.me não aceita + nem espaços).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- A faixa de modalidades passa a ser um scroller a sério: toque, trackpad,
roda do rato, arrastar e setas; continua a deslizar sozinha (~20px/s) e
pára enquanto alguém interage, retomando 2,5s depois. Loop infinito sobre
uma cópia do conjunto (a posição é mantida em float — scrollLeft += 0.3
arredondava para zero).
- Em vez do «Saber mais», o cartão com descrição abre um painel que nasce do
próprio cartão e estica para o lado (para a esquerda junto à margem
direita), com inclinação 3D a seguir o rato; no telemóvel voa para o
centro com o fundo escurecido. O painel vive fora do scroller para o
overflow não o cortar.
- 14 ícones novos (SVG, traço 3) em uploads/modalidades/icons/fitme-*.svg.
- Títulos dos cartões em <h3>, h2#modalidades-title + aria-labelledby; sem
ícone não se gera <img> vazio.
- #modalidades entra só com opacidade: o transform deixado pela animação de
entrada prendia o fundo escurecido (position:fixed) dentro da secção.
- prefers-reduced-motion: os cartões de detalhe (equipa e modalidades)
ficam fora da regra global que reduzia as transições a 0,01ms — com ela
(ativa por defeito em Remote Desktop / Windows sem animações) o cartão
aparecia de repente em vez de esticar.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Horário de aulas: cartões mais pequenos e estreitos; a partir de 992px mostra
o dia anterior, hoje ao centro e o seguinte (a dar a volta à semana), com as
horas alinhadas e os dias laterais esbatidos. O JPG continua a semana toda.
- Horário de funcionamento: cartões compactos numa <dl>, ordenados por hora.
- Equipa: fundo no cinzento da parede do ginásio com juntas de blocos e grão
muito discretos (SVG inline).
- Tira o «FitMe 3070» do header e esconde a newsletter.
- Estrutura: um <main> em todas as páginas públicas (skip link aponta-lhe),
h2 por secção com aria-labelledby, h3 nos itens em vez de h4, sem secções
aninhadas, alts distintos na galeria e no h1 do CrossFit.
- robots.txt e sitemap.xml gerados com o domínio da instalação; SEO_NOINDEX
no .env tira uma cópia de staging dos motores de pesquisa.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
O cartão abre por cima da própria foto (mesmo sítio, tamanho e inclinação),
endireita-se e estica para o lado — para a esquerda nas fotos da ponta
direita — com o texto a entrar por trás. Aberto, inclina-se em 3D e desliza
uns píxeis na direção do rato; ao sair volta a dobrar-se para dentro da foto.
No telemóvel voa da foto para o centro (FLIP) e volta ao fechar.
- clip-path em px calculados no JS: o Chrome não interpola inset() com
calc(100% - …) e o recorte saltava em vez de esticar.
- O cartão é posicionado sem transição antes de abrir; senão a transição do
estado fechado arrancava primeiro e a abertura partia de valores antigos.
- Tira o «Saber mais» do cartão da equipa.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Contactos: nova página no backoffice (fitme3070_info) e 964 201 137 como
telefone principal; o telefone secundário só aparece quando existe.
- Equipa: título, aptidões/funções e formações; o cartão mostra foto, nome e
título e abre um cartão horizontal de detalhe (hover no desktop, toque no
telemóvel) sem mexer na grelha.
- Mensalidades: cartões editáveis com um destaque, modal de inscrição que
guarda o pedido (RGPD + estado + campos reservados para o CRM) e avisa o
ginásio por e-mail; lista de pedidos com estados, notas e CSV.
- Reviews Google via Places API (New), filtradas por classificação mínima e
em cache configurável; página de configuração com pesquisa do Place ID.
- Assets com ?v=<mtime>: site/assets é servido com cache imutável de 1 ano.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Plain-PHP fleet platform with id.andmore.pt SSO. Wires shared/platform-tools
as a submodule (platform_update, backups, git/migration tools) like the other
platforms.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>