// The History page — The Timeline They Didn't Teach You.
//
// A scrubbable horizontal timeline spanning ~12,800 years, with the deep
// past compressed into bands of equal visual width so events from the
// Younger Dryas, the Library of Alexandria, the Renaissance, the World
// Wars and the present can all be seen on one screen.
//
// Each event has a category (cataclysm / hidden civilization / burned
// knowledge / false flag / suppression), an "official" line, and what
// independent research suggests instead. Click an event for the full card.

(function () {
  const root = document.getElementById("timeline");
  if (!root) return;
  const view = document.querySelector('.view[data-view="history"]');
  if (!view) return;

  const t = (k, fb) => (window.i18n && window.i18n.t) ? window.i18n.t(k, fb) : fb;

  // Era bands — each rendered as 1/5 of the timeline width, so even
  // 11,000 BCE is visible alongside 2020. Linear within each band.
  const ERAS = [
    { id: "ice",  from: -12800, to: -3000, label: "Ice Age" },
    { id: "ant",  from: -3000,  to: 500,   label: "Antiquity" },
    { id: "med",  from: 500,    to: 1500,  label: "Middle Ages" },
    { id: "emod", from: 1500,   to: 1900,  label: "Early Modern" },
    { id: "mod",  from: 1900,   to: 2025,  label: "Modern" }
  ];

  const CATEGORIES = {
    cataclysm:    { color: "#ef4444", label: "Cataclysm" },
    civilization: { color: "#eab308", label: "Hidden Civilization" },
    knowledge:    { color: "#a855f7", label: "Burned Knowledge" },
    "false-flag": { color: "#f97316", label: "False Flag" },
    suppression:  { color: "#3b82f6", label: "Suppression / Control" }
  };

  const EVENTS = [
    { year: -10800, cat: "cataclysm", titleK: "tl_e1_t",  officialK: "tl_e1_o", hiddenK: "tl_e1_h" },
    { year: -9600,  cat: "civilization", titleK: "tl_e2_t",  officialK: "tl_e2_o", hiddenK: "tl_e2_h" },
    { year: -9000,  cat: "civilization", titleK: "tl_e3_t",  officialK: "tl_e3_o", hiddenK: "tl_e3_h" },
    { year: -5500,  cat: "cataclysm",    titleK: "tl_e4_t",  officialK: "tl_e4_o", hiddenK: "tl_e4_h" },
    { year: -2580,  cat: "civilization", titleK: "tl_e5_t",  officialK: "tl_e5_o", hiddenK: "tl_e5_h" },
    { year: -1200,  cat: "cataclysm",    titleK: "tl_e6_t",  officialK: "tl_e6_o", hiddenK: "tl_e6_h" },
    { year: -48,    cat: "knowledge",    titleK: "tl_e7_t",  officialK: "tl_e7_o", hiddenK: "tl_e7_h" },
    { year: 391,    cat: "knowledge",    titleK: "tl_e8_t",  officialK: "tl_e8_o", hiddenK: "tl_e8_h" },
    { year: 415,    cat: "knowledge",    titleK: "tl_e9_t",  officialK: "tl_e9_o", hiddenK: "tl_e9_h" },
    { year: 529,    cat: "knowledge",    titleK: "tl_e10_t", officialK: "tl_e10_o", hiddenK: "tl_e10_h" },
    { year: 535,    cat: "cataclysm",    titleK: "tl_e11_t", officialK: "tl_e11_o", hiddenK: "tl_e11_h" },
    { year: 1209,   cat: "knowledge",    titleK: "tl_e12_t", officialK: "tl_e12_o", hiddenK: "tl_e12_h" },
    { year: 1307,   cat: "suppression",  titleK: "tl_e13_t", officialK: "tl_e13_o", hiddenK: "tl_e13_h" },
    { year: 1521,   cat: "knowledge",    titleK: "tl_e14_t", officialK: "tl_e14_o", hiddenK: "tl_e14_h" },
    { year: 1600,   cat: "knowledge",    titleK: "tl_e15_t", officialK: "tl_e15_o", hiddenK: "tl_e15_h" },
    { year: 1633,   cat: "knowledge",    titleK: "tl_e16_t", officialK: "tl_e16_o", hiddenK: "tl_e16_h" },
    { year: 1815,   cat: "civilization", titleK: "tl_e17_t", officialK: "tl_e17_o", hiddenK: "tl_e17_h" },
    { year: 1865,   cat: "false-flag",   titleK: "tl_e18_t", officialK: "tl_e18_o", hiddenK: "tl_e18_h" },
    { year: 1881,   cat: "false-flag",   titleK: "tl_e19_t", officialK: "tl_e19_o", hiddenK: "tl_e19_h" },
    { year: 1893,   cat: "civilization", titleK: "tl_e20_t", officialK: "tl_e20_o", hiddenK: "tl_e20_h" },
    { year: 1913,   cat: "suppression",  titleK: "tl_e21_t", officialK: "tl_e21_o", hiddenK: "tl_e21_h" },
    { year: 1914,   cat: "false-flag",   titleK: "tl_e22_t", officialK: "tl_e22_o", hiddenK: "tl_e22_h" },
    { year: 1917,   cat: "false-flag",   titleK: "tl_e23_t", officialK: "tl_e23_o", hiddenK: "tl_e23_h" },
    { year: 1929,   cat: "suppression",  titleK: "tl_e24_t", officialK: "tl_e24_o", hiddenK: "tl_e24_h" },
    { year: 1933,   cat: "suppression",  titleK: "tl_e25_t", officialK: "tl_e25_o", hiddenK: "tl_e25_h" },
    { year: 1944,   cat: "suppression",  titleK: "tl_e26_t", officialK: "tl_e26_o", hiddenK: "tl_e26_h" },
    { year: 1947,   cat: "suppression",  titleK: "tl_e27_t", officialK: "tl_e27_o", hiddenK: "tl_e27_h" },
    { year: 1948,   cat: "suppression",  titleK: "tl_e28_t", officialK: "tl_e28_o", hiddenK: "tl_e28_h" },
    { year: 1963,   cat: "false-flag",   titleK: "tl_e29_t", officialK: "tl_e29_o", hiddenK: "tl_e29_h" },
    { year: 1964,   cat: "false-flag",   titleK: "tl_e30_t", officialK: "tl_e30_o", hiddenK: "tl_e30_h" },
    { year: 1971,   cat: "suppression",  titleK: "tl_e31_t", officialK: "tl_e31_o", hiddenK: "tl_e31_h" },
    { year: 1975,   cat: "knowledge",    titleK: "tl_e32_t", officialK: "tl_e32_o", hiddenK: "tl_e32_h" },
    { year: 2001,   cat: "false-flag",   titleK: "tl_e33_t", officialK: "tl_e33_o", hiddenK: "tl_e33_h" },
    { year: 2008,   cat: "suppression",  titleK: "tl_e34_t", officialK: "tl_e34_o", hiddenK: "tl_e34_h" },
    { year: 2013,   cat: "knowledge",    titleK: "tl_e35_t", officialK: "tl_e35_o", hiddenK: "tl_e35_h" },
    { year: 2020,   cat: "suppression",  titleK: "tl_e36_t", officialK: "tl_e36_o", hiddenK: "tl_e36_h" },
    { year: 2023,   cat: "suppression",  titleK: "tl_e37_t", officialK: "tl_e37_o", hiddenK: "tl_e37_h" },

    // ============ Expansion: ~75 additional events ============
    // Antiquity additions
    { year: -7500,  cat: "civilization", titleK: "tl_e38_t", officialK: "tl_e38_o", hiddenK: "tl_e38_h" },
    { year: -5500,  cat: "cataclysm",    titleK: "tl_e39_t", officialK: "tl_e39_o", hiddenK: "tl_e39_h" },
    { year: -3200,  cat: "civilization", titleK: "tl_e40_t", officialK: "tl_e40_o", hiddenK: "tl_e40_h" },
    { year: -3000,  cat: "civilization", titleK: "tl_e41_t", officialK: "tl_e41_o", hiddenK: "tl_e41_h" },
    { year: -3600,  cat: "civilization", titleK: "tl_e42_t", officialK: "tl_e42_o", hiddenK: "tl_e42_h" },
    { year: -2500,  cat: "civilization", titleK: "tl_e43_t", officialK: "tl_e43_o", hiddenK: "tl_e43_h" },
    { year: -2500,  cat: "civilization", titleK: "tl_e44_t", officialK: "tl_e44_o", hiddenK: "tl_e44_h" },
    { year: -1600,  cat: "cataclysm",    titleK: "tl_e45_t", officialK: "tl_e45_o", hiddenK: "tl_e45_h" },
    { year: -200,   cat: "civilization", titleK: "tl_e46_t", officialK: "tl_e46_o", hiddenK: "tl_e46_h" },
    { year: -100,   cat: "civilization", titleK: "tl_e47_t", officialK: "tl_e47_o", hiddenK: "tl_e47_h" },
    { year: 325,    cat: "knowledge",    titleK: "tl_e48_t", officialK: "tl_e48_o", hiddenK: "tl_e48_h" },
    { year: 367,    cat: "knowledge",    titleK: "tl_e49_t", officialK: "tl_e49_o", hiddenK: "tl_e49_h" },

    // Medieval additions
    { year: 541,    cat: "cataclysm",    titleK: "tl_e50_t", officialK: "tl_e50_o", hiddenK: "tl_e50_h" },
    { year: 1054,   cat: "knowledge",    titleK: "tl_e51_t", officialK: "tl_e51_o", hiddenK: "tl_e51_h" },
    { year: 1193,   cat: "knowledge",    titleK: "tl_e52_t", officialK: "tl_e52_o", hiddenK: "tl_e52_h" },
    { year: 1258,   cat: "knowledge",    titleK: "tl_e53_t", officialK: "tl_e53_o", hiddenK: "tl_e53_h" },
    { year: 1346,   cat: "cataclysm",    titleK: "tl_e54_t", officialK: "tl_e54_o", hiddenK: "tl_e54_h" },
    { year: 1453,   cat: "knowledge",    titleK: "tl_e55_t", officialK: "tl_e55_o", hiddenK: "tl_e55_h" },
    { year: 1499,   cat: "knowledge",    titleK: "tl_e56_t", officialK: "tl_e56_o", hiddenK: "tl_e56_h" },

    // Early Modern additions
    { year: 1546,   cat: "knowledge",    titleK: "tl_e57_t", officialK: "tl_e57_o", hiddenK: "tl_e57_h" },
    { year: 1666,   cat: "cataclysm",    titleK: "tl_e58_t", officialK: "tl_e58_o", hiddenK: "tl_e58_h" },
    { year: 1755,   cat: "cataclysm",    titleK: "tl_e59_t", officialK: "tl_e59_o", hiddenK: "tl_e59_h" },
    { year: 1773,   cat: "suppression",  titleK: "tl_e60_t", officialK: "tl_e60_o", hiddenK: "tl_e60_h" },
    { year: 1791,   cat: "suppression",  titleK: "tl_e61_t", officialK: "tl_e61_o", hiddenK: "tl_e61_h" },
    { year: 1816,   cat: "suppression",  titleK: "tl_e62_t", officialK: "tl_e62_o", hiddenK: "tl_e62_h" },
    { year: 1836,   cat: "suppression",  titleK: "tl_e63_t", officialK: "tl_e63_o", hiddenK: "tl_e63_h" },
    { year: 1859,   cat: "cataclysm",    titleK: "tl_e64_t", officialK: "tl_e64_o", hiddenK: "tl_e64_h" },
    { year: 1873,   cat: "suppression",  titleK: "tl_e65_t", officialK: "tl_e65_o", hiddenK: "tl_e65_h" },
    { year: 1883,   cat: "cataclysm",    titleK: "tl_e66_t", officialK: "tl_e66_o", hiddenK: "tl_e66_h" },
    { year: 1898,   cat: "false-flag",   titleK: "tl_e67_t", officialK: "tl_e67_o", hiddenK: "tl_e67_h" },

    // Modern additions
    { year: 1908,   cat: "cataclysm",    titleK: "tl_e68_t", officialK: "tl_e68_o", hiddenK: "tl_e68_h" },
    { year: 1910,   cat: "suppression",  titleK: "tl_e69_t", officialK: "tl_e69_o", hiddenK: "tl_e69_h" },
    { year: 1915,   cat: "false-flag",   titleK: "tl_e70_t", officialK: "tl_e70_o", hiddenK: "tl_e70_h" },
    { year: 1918,   cat: "cataclysm",    titleK: "tl_e71_t", officialK: "tl_e71_o", hiddenK: "tl_e71_h" },
    { year: 1923,   cat: "civilization", titleK: "tl_e72_t", officialK: "tl_e72_o", hiddenK: "tl_e72_h" },
    { year: 1933,   cat: "false-flag",   titleK: "tl_e73_t", officialK: "tl_e73_o", hiddenK: "tl_e73_h" },
    { year: 1941,   cat: "false-flag",   titleK: "tl_e74_t", officialK: "tl_e74_o", hiddenK: "tl_e74_h" },
    { year: 1945,   cat: "knowledge",    titleK: "tl_e75_t", officialK: "tl_e75_o", hiddenK: "tl_e75_h" },
    { year: 1947,   cat: "knowledge",    titleK: "tl_e76_t", officialK: "tl_e76_o", hiddenK: "tl_e76_h" },
    { year: 1953,   cat: "suppression",  titleK: "tl_e77_t", officialK: "tl_e77_o", hiddenK: "tl_e77_h" },
    { year: 1954,   cat: "suppression",  titleK: "tl_e78_t", officialK: "tl_e78_o", hiddenK: "tl_e78_h" },
    { year: 1961,   cat: "suppression",  titleK: "tl_e79_t", officialK: "tl_e79_o", hiddenK: "tl_e79_h" },
    { year: 1962,   cat: "false-flag",   titleK: "tl_e80_t", officialK: "tl_e80_o", hiddenK: "tl_e80_h" },
    { year: 1965,   cat: "false-flag",   titleK: "tl_e81_t", officialK: "tl_e81_o", hiddenK: "tl_e81_h" },
    { year: 1967,   cat: "false-flag",   titleK: "tl_e82_t", officialK: "tl_e82_o", hiddenK: "tl_e82_h" },
    { year: 1968,   cat: "false-flag",   titleK: "tl_e83_t", officialK: "tl_e83_o", hiddenK: "tl_e83_h" },
    { year: 1968,   cat: "false-flag",   titleK: "tl_e84_t", officialK: "tl_e84_o", hiddenK: "tl_e84_h" },
    { year: 1971,   cat: "suppression",  titleK: "tl_e85_t", officialK: "tl_e85_o", hiddenK: "tl_e85_h" },
    { year: 1973,   cat: "suppression",  titleK: "tl_e86_t", officialK: "tl_e86_o", hiddenK: "tl_e86_h" },
    { year: 1973,   cat: "suppression",  titleK: "tl_e87_t", officialK: "tl_e87_o", hiddenK: "tl_e87_h" },
    { year: 1973,   cat: "suppression",  titleK: "tl_e88_t", officialK: "tl_e88_o", hiddenK: "tl_e88_h" },
    { year: 1986,   cat: "suppression",  titleK: "tl_e89_t", officialK: "tl_e89_o", hiddenK: "tl_e89_h" },
    { year: 1990,   cat: "false-flag",   titleK: "tl_e90_t", officialK: "tl_e90_o", hiddenK: "tl_e90_h" },
    { year: 1993,   cat: "false-flag",   titleK: "tl_e91_t", officialK: "tl_e91_o", hiddenK: "tl_e91_h" },
    { year: 1995,   cat: "suppression",  titleK: "tl_e92_t", officialK: "tl_e92_o", hiddenK: "tl_e92_h" },
    { year: 1997,   cat: "false-flag",   titleK: "tl_e93_t", officialK: "tl_e93_o", hiddenK: "tl_e93_h" },
    { year: 1999,   cat: "suppression",  titleK: "tl_e94_t", officialK: "tl_e94_o", hiddenK: "tl_e94_h" },
    { year: 2001,   cat: "suppression",  titleK: "tl_e95_t", officialK: "tl_e95_o", hiddenK: "tl_e95_h" },
    { year: 2001,   cat: "false-flag",   titleK: "tl_e96_t", officialK: "tl_e96_o", hiddenK: "tl_e96_h" },
    { year: 2003,   cat: "false-flag",   titleK: "tl_e97_t", officialK: "tl_e97_o", hiddenK: "tl_e97_h" },
    { year: 2005,   cat: "false-flag",   titleK: "tl_e98_t", officialK: "tl_e98_o", hiddenK: "tl_e98_h" },
    { year: 2009,   cat: "civilization", titleK: "tl_e99_t", officialK: "tl_e99_o", hiddenK: "tl_e99_h" },
    { year: 2010,   cat: "suppression",  titleK: "tl_e100_t", officialK: "tl_e100_o", hiddenK: "tl_e100_h" },
    { year: 2011,   cat: "suppression",  titleK: "tl_e101_t", officialK: "tl_e101_o", hiddenK: "tl_e101_h" },
    { year: 2012,   cat: "suppression",  titleK: "tl_e102_t", officialK: "tl_e102_o", hiddenK: "tl_e102_h" },
    { year: 2014,   cat: "false-flag",   titleK: "tl_e103_t", officialK: "tl_e103_o", hiddenK: "tl_e103_h" },
    { year: 2016,   cat: "knowledge",    titleK: "tl_e104_t", officialK: "tl_e104_o", hiddenK: "tl_e104_h" },
    { year: 2019,   cat: "suppression",  titleK: "tl_e105_t", officialK: "tl_e105_o", hiddenK: "tl_e105_h" },
    { year: 2019,   cat: "false-flag",   titleK: "tl_e106_t", officialK: "tl_e106_o", hiddenK: "tl_e106_h" },
    { year: 2021,   cat: "suppression",  titleK: "tl_e107_t", officialK: "tl_e107_o", hiddenK: "tl_e107_h" },
    { year: 2022,   cat: "knowledge",    titleK: "tl_e108_t", officialK: "tl_e108_o", hiddenK: "tl_e108_h" },
    { year: 2022,   cat: "suppression",  titleK: "tl_e109_t", officialK: "tl_e109_o", hiddenK: "tl_e109_h" },
    { year: 2023,   cat: "cataclysm",    titleK: "tl_e110_t", officialK: "tl_e110_o", hiddenK: "tl_e110_h" },
    { year: 2024,   cat: "suppression",  titleK: "tl_e111_t", officialK: "tl_e111_o", hiddenK: "tl_e111_h" },
    { year: 2024,   cat: "false-flag",   titleK: "tl_e112_t", officialK: "tl_e112_o", hiddenK: "tl_e112_h" },

    // ============ Second expansion: ~40 more — secret societies, Rockefeller medicine,
    // suppressed inventors, UAP disclosure, modern mass-casualty + geopolitical events
    { year: 1694,   cat: "suppression",  titleK: "tl_e113_t", officialK: "tl_e113_o", hiddenK: "tl_e113_h" },
    { year: 1720,   cat: "suppression",  titleK: "tl_e114_t", officialK: "tl_e114_o", hiddenK: "tl_e114_h" },
    { year: 1776,   cat: "suppression",  titleK: "tl_e115_t", officialK: "tl_e115_o", hiddenK: "tl_e115_h" },
    { year: 1815,   cat: "suppression",  titleK: "tl_e116_t", officialK: "tl_e116_o", hiddenK: "tl_e116_h" },
    { year: 1832,   cat: "suppression",  titleK: "tl_e117_t", officialK: "tl_e117_o", hiddenK: "tl_e117_h" },
    { year: 1872,   cat: "suppression",  titleK: "tl_e118_t", officialK: "tl_e118_o", hiddenK: "tl_e118_h" },
    { year: 1880,   cat: "knowledge",    titleK: "tl_e119_t", officialK: "tl_e119_o", hiddenK: "tl_e119_h" },
    { year: 1891,   cat: "suppression",  titleK: "tl_e120_t", officialK: "tl_e120_o", hiddenK: "tl_e120_h" },
    { year: 1903,   cat: "knowledge",    titleK: "tl_e121_t", officialK: "tl_e121_o", hiddenK: "tl_e121_h" },
    { year: 1910,   cat: "suppression",  titleK: "tl_e122_t", officialK: "tl_e122_o", hiddenK: "tl_e122_h" },
    { year: 1917,   cat: "suppression",  titleK: "tl_e123_t", officialK: "tl_e123_o", hiddenK: "tl_e123_h" },
    { year: 1921,   cat: "suppression",  titleK: "tl_e124_t", officialK: "tl_e124_o", hiddenK: "tl_e124_h" },
    { year: 1934,   cat: "knowledge",    titleK: "tl_e125_t", officialK: "tl_e125_o", hiddenK: "tl_e125_h" },
    { year: 1945,   cat: "suppression",  titleK: "tl_e126_t", officialK: "tl_e126_o", hiddenK: "tl_e126_h" },
    { year: 1948,   cat: "suppression",  titleK: "tl_e127_t", officialK: "tl_e127_o", hiddenK: "tl_e127_h" },
    { year: 1952,   cat: "civilization", titleK: "tl_e128_t", officialK: "tl_e128_o", hiddenK: "tl_e128_h" },
    { year: 1956,   cat: "knowledge",    titleK: "tl_e129_t", officialK: "tl_e129_o", hiddenK: "tl_e129_h" },
    { year: 1962,   cat: "suppression",  titleK: "tl_e130_t", officialK: "tl_e130_o", hiddenK: "tl_e130_h" },
    { year: 1971,   cat: "suppression",  titleK: "tl_e131_t", officialK: "tl_e131_o", hiddenK: "tl_e131_h" },
    { year: 1978,   cat: "false-flag",   titleK: "tl_e132_t", officialK: "tl_e132_o", hiddenK: "tl_e132_h" },
    { year: 1979,   cat: "suppression",  titleK: "tl_e133_t", officialK: "tl_e133_o", hiddenK: "tl_e133_h" },
    { year: 1980,   cat: "civilization", titleK: "tl_e134_t", officialK: "tl_e134_o", hiddenK: "tl_e134_h" },
    { year: 1986,   cat: "suppression",  titleK: "tl_e135_t", officialK: "tl_e135_o", hiddenK: "tl_e135_h" },
    { year: 1989,   cat: "suppression",  titleK: "tl_e136_t", officialK: "tl_e136_o", hiddenK: "tl_e136_h" },
    { year: 1996,   cat: "suppression",  titleK: "tl_e137_t", officialK: "tl_e137_o", hiddenK: "tl_e137_h" },
    { year: 1997,   cat: "civilization", titleK: "tl_e138_t", officialK: "tl_e138_o", hiddenK: "tl_e138_h" },
    { year: 1998,   cat: "knowledge",    titleK: "tl_e139_t", officialK: "tl_e139_o", hiddenK: "tl_e139_h" },
    { year: 2012,   cat: "false-flag",   titleK: "tl_e140_t", officialK: "tl_e140_o", hiddenK: "tl_e140_h" },
    { year: 2013,   cat: "false-flag",   titleK: "tl_e141_t", officialK: "tl_e141_o", hiddenK: "tl_e141_h" },
    { year: 2013,   cat: "suppression",  titleK: "tl_e142_t", officialK: "tl_e142_o", hiddenK: "tl_e142_h" },
    { year: 2014,   cat: "false-flag",   titleK: "tl_e143_t", officialK: "tl_e143_o", hiddenK: "tl_e143_h" },
    { year: 2014,   cat: "false-flag",   titleK: "tl_e144_t", officialK: "tl_e144_o", hiddenK: "tl_e144_h" },
    { year: 2017,   cat: "civilization", titleK: "tl_e145_t", officialK: "tl_e145_o", hiddenK: "tl_e145_h" },
    { year: 2017,   cat: "false-flag",   titleK: "tl_e146_t", officialK: "tl_e146_o", hiddenK: "tl_e146_h" },
    { year: 2018,   cat: "suppression",  titleK: "tl_e147_t", officialK: "tl_e147_o", hiddenK: "tl_e147_h" },
    { year: 2021,   cat: "suppression",  titleK: "tl_e148_t", officialK: "tl_e148_o", hiddenK: "tl_e148_h" },
    { year: 2022,   cat: "false-flag",   titleK: "tl_e149_t", officialK: "tl_e149_o", hiddenK: "tl_e149_h" },
    { year: 2023,   cat: "false-flag",   titleK: "tl_e150_t", officialK: "tl_e150_o", hiddenK: "tl_e150_h" },
    { year: 2023,   cat: "civilization", titleK: "tl_e151_t", officialK: "tl_e151_o", hiddenK: "tl_e151_h" },
    { year: 2024,   cat: "suppression",  titleK: "tl_e152_t", officialK: "tl_e152_o", hiddenK: "tl_e152_h" }
  ];

  // Piecewise mapping — every era gets 1/N of the horizontal space.
  function yearToPct(y) {
    for (let i = 0; i < ERAS.length; i++) {
      const e = ERAS[i];
      if (y >= e.from && y <= e.to) {
        const within = (y - e.from) / (e.to - e.from);
        return ((i + within) / ERAS.length) * 100;
      }
    }
    return y < ERAS[0].from ? 0 : 100;
  }

  function formatYear(y) {
    if (y < 0) return Math.abs(y).toLocaleString("en-US") + " BCE";
    return y.toLocaleString("en-US") + " CE";
  }

  // --- DOM build ---
  const filtersEl = root.querySelector(".tl-filters");
  const bandsEl   = root.querySelector(".tl-bands");
  const labelsEl  = root.querySelector(".tl-yearmarks");
  const trackEl   = root.querySelector(".tl-track");
  const dotsEl    = root.querySelector(".tl-dots");
  const detailsEl = root.querySelector(".tl-details");
  const placeholderEl = root.querySelector(".tl-placeholder");

  // Filter chips — "all" + each category. Use data-i18n so labels are
  // filled in by the i18n system when translations finish loading.
  const filters = ["all"].concat(Object.keys(CATEGORIES));
  let activeFilter = "all";
  filters.forEach((id) => {
    const chip = document.createElement("button");
    chip.type = "button";
    chip.className = "tl-chip" + (id === "all" ? " active" : "");
    chip.dataset.filter = id;
    chip.style.setProperty("--c", id === "all" ? "#cbd5e1" : CATEGORIES[id].color);
    const i18nKey = id === "all" ? "page.history.tl_all" : "page.history.tl_cat_" + id;
    chip.setAttribute("data-i18n", i18nKey);
    chip.textContent = id === "all" ? "All" : CATEGORIES[id].label;
    filtersEl.appendChild(chip);
  });
  filtersEl.addEventListener("click", (e) => {
    const chip = e.target.closest(".tl-chip");
    if (!chip) return;
    activeFilter = chip.dataset.filter;
    filtersEl.querySelectorAll(".tl-chip").forEach((c) =>
      c.classList.toggle("active", c === chip));
    applyFilter();
  });
  function applyFilter() {
    root.classList.toggle("tl-filtered", activeFilter !== "all");
    dotsEl.querySelectorAll(".tl-dot").forEach((d) => {
      d.classList.toggle("dim", activeFilter !== "all" && d.dataset.cat !== activeFilter);
    });
  }

  // Era band backgrounds.
  ERAS.forEach((era, i) => {
    const band = document.createElement("div");
    band.className = "tl-band tl-band-" + era.id;
    band.style.left = (i / ERAS.length) * 100 + "%";
    band.style.width = (100 / ERAS.length) + "%";
    const label = document.createElement("span");
    label.className = "tl-band-label";
    label.setAttribute("data-i18n", "page.history.tl_era_" + era.id);
    label.textContent = era.label;
    band.appendChild(label);
    bandsEl.appendChild(band);
  });

  // Year tick marks. Generated dynamically based on zoom level — more zoom,
  // more granular ticks. Each era contributes its boundaries plus interior
  // ticks at "nice" round-year intervals chosen for the zoom level.
  function niceStep(rawStep) {
    const s = Math.abs(rawStep);
    if (s > 3000) return 2000;
    if (s > 1500) return 1000;
    if (s > 750)  return 500;
    if (s > 350)  return 250;
    if (s > 150)  return 100;
    if (s > 75)   return 50;
    if (s > 35)   return 25;
    if (s > 15)   return 10;
    return 5;
  }
  function getTicks(zoom) {
    const out = new Set();
    ERAS.forEach((era) => {
      out.add(era.from);
      out.add(era.to);
      // ~2 ticks at zoom 1, ~4 at zoom 2, ~8 at zoom 4, ~16 at zoom 8...
      const targetTicks = Math.max(1, zoom * 2);
      const step = niceStep((era.to - era.from) / targetTicks);
      // Start from first multiple of step >= era.from
      const first = Math.ceil(era.from / step) * step;
      for (let y = first; y <= era.to; y += step) {
        if (y > era.from && y < era.to) out.add(y);
      }
    });
    return Array.from(out).sort((a, b) => a - b);
  }
  function renderTicks(zoom) {
    while (labelsEl.firstChild) labelsEl.removeChild(labelsEl.firstChild);
    getTicks(zoom).forEach((y) => {
      const tick = document.createElement("div");
      tick.className = "tl-yearmark";
      tick.style.left = yearToPct(y) + "%";
      tick.innerHTML = '<span>' + formatYear(y) + '</span>';
      labelsEl.appendChild(tick);
    });
  }
  renderTicks(1);

  // Zoom controls.
  const ZOOM_LEVELS = [1, 2, 4, 8, 16];
  let zoomIdx = 0;
  const zoomEl  = root.querySelector(".tl-zoom");
  const zoomLbl = zoomEl.querySelector(".tl-zoom-label");
  const canvasEl = root.querySelector(".tl-canvas");
  const scrollEl = root.querySelector(".tl-scroll");
  function setZoom(idx) {
    zoomIdx = Math.max(0, Math.min(ZOOM_LEVELS.length - 1, idx));
    const z = ZOOM_LEVELS[zoomIdx];
    // Preserve the scroll center across the zoom change.
    const center = (scrollEl.scrollLeft + scrollEl.clientWidth / 2) / canvasEl.offsetWidth;
    canvasEl.dataset.zoom = String(z);
    zoomLbl.textContent = z + "×";
    zoomEl.querySelector('[data-zoom="out"]').disabled   = zoomIdx === 0;
    zoomEl.querySelector('[data-zoom="in"]').disabled    = zoomIdx === ZOOM_LEVELS.length - 1;
    zoomEl.querySelector('[data-zoom="reset"]').disabled = zoomIdx === 0;
    renderTicks(z);
    // Re-center after layout settles.
    requestAnimationFrame(() => {
      scrollEl.scrollLeft = (center * canvasEl.offsetWidth) - scrollEl.clientWidth / 2;
    });
  }
  zoomEl.addEventListener("click", (e) => {
    const btn = e.target.closest("[data-zoom]");
    if (!btn) return;
    const action = btn.dataset.zoom;
    if (action === "in")    setZoom(zoomIdx + 1);
    else if (action === "out")   setZoom(zoomIdx - 1);
    else if (action === "reset") setZoom(0);
  });
  setZoom(0);

  // Event dots — distribute vertically to avoid overlap of close events.
  // Sort by year; assign rows greedily.
  const sorted = EVENTS.slice().sort((a, b) => a.year - b.year);
  const ROWS = 4;
  const lastX = new Array(ROWS).fill(-Infinity);
  sorted.forEach((ev, idx) => {
    const x = yearToPct(ev.year);
    let row = 0;
    for (let r = 0; r < ROWS; r++) {
      if (x - lastX[r] > 3) { row = r; break; }
      if (r === ROWS - 1) row = idx % ROWS;
    }
    lastX[row] = x;
    const dot = document.createElement("button");
    dot.type = "button";
    dot.className = "tl-dot";
    dot.dataset.idx = String(idx);
    dot.dataset.cat = ev.cat;
    dot.style.left = x + "%";
    dot.style.top  = (row / ROWS) * 100 + "%";
    dot.style.setProperty("--c", CATEGORIES[ev.cat].color);
    const titleSpan = document.createElement("span");
    titleSpan.className = "tl-dot-title";
    titleSpan.setAttribute("data-i18n", "page.history." + ev.titleK);
    titleSpan.textContent = ev.titleK; // overwritten by i18n.applyTranslations()
    dot.appendChild(titleSpan);
    dot.setAttribute("aria-label", formatYear(ev.year));
    dotsEl.appendChild(dot);
  });

  // Once i18n loads (or language changes), it scans the DOM for [data-i18n]
  // and fills them in. We dispatched data-i18n above, so nothing else needed.
  // But for elements built AFTER initial i18n.applyTranslations() runs (e.g.,
  // the chips/dots created in this IIFE on first load), we need to nudge it.
  function applyI18nNow() {
    if (!window.i18n || !window.i18n.t) return;
    root.querySelectorAll("[data-i18n]").forEach((el) => {
      const k = el.getAttribute("data-i18n");
      const v = window.i18n.t(k, null);
      if (v && v !== k) el.innerHTML = v;
    });
  }
  // Try immediately (translations may already be loaded).
  applyI18nNow();
  // Re-apply on every language switch.
  window.addEventListener("langchange", applyI18nNow);
  // And if i18n loads after we've built the DOM, catch up when it's ready.
  if (document.readyState === "loading") {
    document.addEventListener("DOMContentLoaded", () => setTimeout(applyI18nNow, 0));
  }

  // Click → show details.
  let selected = null;
  function showEvent(idx) {
    const ev = sorted[idx];
    detailsEl.innerHTML =
      '<div class="tl-d-head" style="border-color:' + CATEGORIES[ev.cat].color + '">' +
        '<div class="tl-d-year">' + formatYear(ev.year) + '</div>' +
        '<div class="tl-d-cat" style="color:' + CATEGORIES[ev.cat].color + '">'
          + t("page.history.tl_cat_" + ev.cat, CATEGORIES[ev.cat].label) + '</div>' +
      '</div>' +
      '<div class="tl-d-title">' + t("page.history." + ev.titleK, ev.titleK) + '</div>' +
      '<div class="tl-d-block tl-d-official">' +
        '<div class="tl-d-block-label">' + t("page.history.tl_official", "What they say") + '</div>' +
        '<div class="tl-d-block-body">' + t("page.history." + ev.officialK, "") + '</div>' +
      '</div>' +
      '<div class="tl-d-block tl-d-hidden">' +
        '<div class="tl-d-block-label">' + t("page.history.tl_hidden", "What we know") + '</div>' +
        '<div class="tl-d-block-body">' + t("page.history." + ev.hiddenK, "") + '</div>' +
      '</div>';
    detailsEl.classList.add("visible");
    if (placeholderEl) placeholderEl.style.display = "none";
  }
  dotsEl.addEventListener("click", (e) => {
    const dot = e.target.closest(".tl-dot");
    if (!dot) return;
    if (selected) selected.classList.remove("active");
    selected = dot;
    dot.classList.add("active");
    showEvent(+dot.dataset.idx);
    // Scroll details into view (mobile-friendly).
    detailsEl.scrollIntoView({ behavior: "smooth", block: "nearest" });
  });

  // Re-render the open details card on language change. Chips, bands, and
  // dot titles are handled by applyI18nNow() above via [data-i18n].
  window.addEventListener("langchange", () => {
    if (selected) showEvent(+selected.dataset.idx);
  });

  // Pause / resume isn't strictly needed (no animation loop), but we
  // hide selection when leaving the view to keep state clean.
  function isActive() { return view.classList.contains("active"); }
  function stop() {
    if (selected) selected.classList.remove("active");
    selected = null;
    detailsEl.classList.remove("visible");
    if (placeholderEl) placeholderEl.style.display = "";
  }
  if ("MutationObserver" in window) {
    new MutationObserver(() => { if (!isActive()) stop(); })
      .observe(view, { attributes: true, attributeFilter: ["class"] });
  }
})();
