- KeyboardHints: switch from fixed positioning to absolute, mounted inside the main content column. The column is now relative-positioned so the hints overlay centers against the timeline area instead of the raw viewport (which was off-center because of the sidebars). - AppFooter: tiny "Built with hubris • <YEAR in roman>" pinned to the bottom-right corner of the main column. Year is computed at render time and converted via a small toRoman helper. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
44 lines
895 B
TypeScript
44 lines
895 B
TypeScript
/**
|
|
* Tiny corner footer pinned to the bottom-right of the main column.
|
|
* Renders "Built with hubris • <year in roman numerals>", refreshed
|
|
* once per page load.
|
|
*/
|
|
|
|
const ROMAN_PAIRS: [number, string][] = [
|
|
[1000, 'M'],
|
|
[900, 'CM'],
|
|
[500, 'D'],
|
|
[400, 'CD'],
|
|
[100, 'C'],
|
|
[90, 'XC'],
|
|
[50, 'L'],
|
|
[40, 'XL'],
|
|
[10, 'X'],
|
|
[9, 'IX'],
|
|
[5, 'V'],
|
|
[4, 'IV'],
|
|
[1, 'I'],
|
|
]
|
|
|
|
function toRoman(n: number): string {
|
|
let result = ''
|
|
for (const [value, symbol] of ROMAN_PAIRS) {
|
|
while (n >= value) {
|
|
result += symbol
|
|
n -= value
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
|
|
export function AppFooter() {
|
|
const year = new Date().getFullYear()
|
|
return (
|
|
<div className="pointer-events-none absolute bottom-2 right-3 z-10 text-[10px] text-text-faint">
|
|
<span className="pointer-events-auto">
|
|
Built with hubris • {toRoman(year)}
|
|
</span>
|
|
</div>
|
|
)
|
|
}
|