A filtered-out directory card stayed visible. The card is targeted by an
id-based ready-state selector (`.js #directory[data-dir-state="ready"]
#dirGrid > .dev-card`, two ids), which outranked the old per-element patch
`.dev-card[hidden] { display:none }` — so `card.hidden = true` set the
attribute and every card stayed on screen while the count line correctly
read "Showing 1 of 4".
Fix: one rule, `[hidden] { display:none !important }`, early in /style.css.
A class- or id-based `display` can no longer beat the attribute, so this
cannot recur with the next class that sets `display`. The per-element
`[hidden]` patches are removed so a single mechanism governs:
- odoo-community-developers: cards + filter row + pager + modal
(load-bearing — each sets `display`); focus-sliders/noscript (redundant)
- index/de/es `.hero-notice[hidden]`, odoo-black-friday `.ads-consent[hidden]`
(redundant — those elements set no `display`)
Re-fingerprint local assets (style.css changed): /style.css?v 3332fbba93 ->
061517baef across 51 pages.
Measured in a real browser (local harness, stubbed webhook; no record created,
no probe write) — computed display + geometry, never the `hidden` property:
- filtered to one card: the other three report display:none and height 0;
the visible set (1) equals the count line ("Showing 1 of 4") — 1 == 1
- HEAD (pre-fix) reproduces the defect: 3 cards hidden=true yet display:flex,
height 599.38 each; 4 visible vs the count's 1
- pager: display:none height 0 with one page; display:flex height 66.83 with
12 cards (Page 1 of 2); page 2 hides page-1 cards (display:none)
- modals closed: display:none height 0; load state: cards 0, pager/empty
display:none, filter row visibility:hidden by design
- 375 px: same result, no horizontal overflow; avatar ask-row top identical
across a row (2053.97 / links 2086.91)
- blog/posts/odoo-19-to-20-invoice-migration-with-n8n-and-mcp.html: in-post image
much.png + og:image
- blog/posts/track-the-oca-modules-you-actually-use.html: in-post image
oca_module_status.png + og:image
- blog/index.json: optional "image" key on those two entries only (text splice)
- script.js: renderBlog() draws .blog-thumb only when the entry carries an image
- style.css: .blog-thumb rule
- sitemap.xml: lastmod 2026-10-24 for the invoice-migration post
Built by profile webmaster (run 20261024_094206_5c4f28, verified PROBLEMS: 0 /
node --check OK); committed by olchi after that run died on an OpenRouter 402.
- Dark text (#171c26) for all form fields in modal on ivory background
- Explicit colors for labels, inputs, placeholders
- Close button (X) now visible with midnight background
- Add email input field after textareas, before checkboxes
- Email required via both HTML 'required' attribute and JS validation
- POST email field to webhook as 'email' key
- Add .biz-field input[type='email'] CSS (inline + external) matching textarea style
- Update success message: 'We will email you the report once it is ready. AI generation typically takes 1-2 minutes.'
- Remove reference to new window / auto-download (no longer opens window)
- Add 3 checkboxes between textareas and submit button:
- I already have a homepage (bizHasHomepage)
- I already use ODOO (bizUsesOdoo)
- I already have a developer for modules (bizHasDeveloper)
- POST to /webhook/report instead of old webhook UUID
- Include checkbox boolean values in request body
- Add .biz-checkbox-group and .biz-checkbox CSS (inline + external)
- Replace .final-cta section with .biz-wizard section
- Three textarea fields: Business Description, My Goals, Current Challenges
- On submit, POSTs to webhook endpoint that triggers AI Agent to
generate a personalized Odoo project plan PDF
- On success, shows download button if webhook returns download_url
- Inline + external CSS: midnight background, brass-accented form fields
- Scroll animation observer updated to target .biz-wizard .container
- Remove all .final-cta CSS from style.css and inline critical styles
- Remove billing-toggle-wrap HTML (switch + labels)
- Update all 4 pricing cards to show yearly prices by default
with / year period and save percentage
- Simplify openOrderWidget() to always use yearly pricing only
- Remove billing toggle JS block (updatePrices, setBilling, event listeners)
- Remove billing toggle CSS (billing-toggle-wrap, .toggle-*, .toggle-switch)
- Update order widget default display to / year
- Update CTA note to 'Save money, less administration'
- features-grid changed to repeat(3, 1fr) for 2x3 layout
- 6th cell is a Free Trial card with midnight bg, brass border
- Email input, location dropdown (preselected to best ping server),
brass Send button
- POST to webhook as JSON {email, location}
- On success: form hides, success message shown
- Responsive: 3col -> 2col -> 1col
- Header changed to 'Our Server Locations'
- Cards hardcoded in HTML with just city name + region
- Removed all ping JS (IIFE, pingServer, markBest, etc.)
- Removed server-ping-wrap, best-badge, server-best, ping-spinner,
status-dot, server-optimal CSS
- Removed empty server-optimal div
- Removed card entrance animation (static display)
- Added GSAP 3.12.5 from CDN
- Card stagger entrance now uses gsap.fromTo with 0.6s duration, 0.09 stagger
- Carousel slide uses gsap.timeline: old slides out right (3s), new slides
in from right (3s), label slides in (2.5s after 0.3s offset)
- All animations use power2.out easing
- Image brightness: opacity 0.12→0.25, filter brightness(1.15) saturate(1.1)
- ::after overlay changed from solid midnight @ 0.6 to gradient
(midnight→transparent @ 0.5) — brighter image with smooth falloff
- ::after is now a dark overlay only (no bg image)
- .hero-bg container created on first swap
- Old slide (Amsterdam default) starts at translateX(0), animates to
translateX(100%) — slides out to the right
- New slide (winning city) starts at translateX(100%), animates to
translateX(0) — slides in from the right
- Both fire simultaneously via requestAnimationFrame, same easing
- Old slide removed after 1.2s cleanup timeout
- Label 'Our <City> server fits your location' slides in from right
alongside the carousel animation
- Preloads the best server's city image via new Image() before showing
- Reveal overlay uses clip-path: inset(0 100% ...) → inset(0) for smooth
left-to-right slide over the default Amsterdam background
- Label 'Our <City> server fits your location' slides in from right
simultaneously with backdrop-blur and brass border
- Both animations start and end together via requestAnimationFrame
- Maps each server to a city image (holland, brazil, india, england,
boston/sydney from Wikimedia Commons CC-BY-SA)
- CSS var --hero-bg controls ::after background, falls back to Amsterdam
- 0.8s ease-out transition when the image swaps
- Uses local webp for Odoo-sourced images, JPG for Wikimedia imports
- Replaced city placards with a full server status banner
- Grid of 6 server cards (Amsterdam, Boston, Manchester, Mumbai, São Paulo, Sydney)
- JS pings each server via Image() timing, shows ms latency
- Best server highlighted with brass glow, shadow, and 'Best' badge
- 'Your optimal server location: <city> (<ms> ms)' with bounce animation
- Staggered card entrance animation on page load
- Responsive: 6-col -> 3-col -> 2-col grid