Apply 45% opacity to all column cells where stay_date < today —
date header, category fill, occupancy, and all tariff cells —
matching the same visual treatment as the Direct Rates table.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Schema: migrate newbook_occupancy_report_data from single-row upsert to
snapshot model (drop unique constraint, add valid_from / last_verified_at)
matching the pattern used by newbook_current_rates.
Backend: sync_occupancy now inserts a new row only when occupied/available/
maintenance figures change, otherwise bumps last_verified_at. New endpoint
GET /bookability/occupancy-history/{category_id}/{date} returns the timeline.
Rate matrix query updated to DISTINCT ON for the multi-row table.
Frontend: clicking any cell in the Bookability matrix opens a modal with
two stacked Plotly charts — rate history per tariff (step lines, green/red
markers for available/unavailable) and occupancy pick-up over time.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Separate verified_at (last checked) from valid_from (last rate change)
in the matrix response. Column headers show when rates were last checked;
hovering shows both "Checked: X" and "Changed: Y" so users can distinguish
a manual refresh that verified unchanged rates from one that found new prices.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>