style(motion): add strict animations and fix layout properties

- Change ReadingProgress and RouteTable to use transform (scaleX/scaleY) instead of width/height
- Convert existing easing functions to 200ms cubic-bezier(.2,0,0,1)
- Document animation purpose with CSS comments
- Add guide panel swap, review desk detail swap, and tally pop animations
- Implement prefers-reduced-motion for all new states
This commit is contained in:
Marcos Paulo
2026-09-05 23:13:59 +00:00
parent 71c74fb7f1
commit 9ca3f48def
10 changed files with 66 additions and 12 deletions
+6 -2
View File
@@ -437,10 +437,14 @@ function previewMarkup(entry, available) {
function renderDetail() {
const entry = state.selected;
const available = packageFiles(entry);
$('#detail').innerHTML =
const detailPanel = $('#detail');
detailPanel.innerHTML =
`<header><div><span class="status">${escape(entry.status)}</span><h2>${escape(entry.title)}</h2><p>Submitted by <a class="author-link" href="?author=${encodeURIComponent(entry.author)}">${escape(entry.author)}</a> · <a class="share-link" href="?author=${encodeURIComponent(entry.author)}&skill=${encodeURIComponent(entry.id)}&view=${state.preview}">share review ↗</a></p></div><div class="switch" role="group" aria-label="Preview version"><button class="${state.preview === 'original' ? 'active' : ''}" data-preview="original">Original</button><button class="${state.preview === 'improved' ? 'active' : ''}" data-preview="improved">Improved draft</button></div></header><div class="purpose"><span>THE JOB</span><p>${escape(entry.focus)}</p></div><div id="vote-widget"></div><div class="review-grid"><section><span>WHAT'S ALREADY WORKING</span><ul>${entry.wins.map((item) => `<li>${escape(item)}</li>`).join('')}</ul></section><section><span>HIGHEST-VALUE IMPROVEMENTS</span><ul>${entry.improve.map((item) => `<li>${escape(item)}</li>`).join('')}</ul></section></div><aside class="extras"><span>GOOD NEXT ADDITION</span><p>${escape(entry.extras)}</p></aside>${previewMarkup(entry, available)}`;
detailPanel.classList.remove('is-swapping');
void detailPanel.offsetWidth;
detailPanel.classList.add('is-swapping');
renderVoteWidget($('#vote-widget'), entry.id);
$('#detail')
detailPanel
.querySelectorAll('[data-file]')
.forEach((button) =>
button.addEventListener('click', () => {