Wimbledon 2025 WTA Bracket

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Wimbledon 2025 WTA Bracket</title>
  <style>
    body { font-family: Arial, sans-serif; padding: 20px; background: #f9f9f9; }
    .bracket { display: flex; gap: 20px; overflow-x: auto; }
    .round { min-width: 180px; }
    .round h3 { text-align: center; margin-bottom: 10px; }
    .match { background: white; border: 1px solid #ccc; margin-bottom: 10px; border-radius: 5px; overflow: hidden; }
    .player {
      padding: 6px 8px;
      cursor: pointer;
      border-top: 1px solid #eee;
    }
    .player:first-child { border-top: none; }
    .player.selected { background: #cce5ff; font-weight: bold; }
  </style>
</head>
<body>
  <h1>Wimbledon 2025 WTA Bracket</h1>
  <button onclick="resetBracket()">🔄 Reset Bracket</button>
  <div class="bracket" id="bracket"></div>

  <script>
    function resetBracket() {
      localStorage.clear();
      location.reload();
    }

    const bracketData = {
      version: "wta-v2",
      players: [
        ["Aryna Sabalenka", "Carson Branstine"],
        ["Lulu Sun", "Marie Bouzkova"],
        ["Emma Raducanu", "Mimi Xu"],
        ["Marketa Vondrousova", "McCartney Kessler"],
        ["Elise Mertens", "Linda Fruhvitova"],
        ["Ann Li", "Viktoria Golubic"],
        ["Varvara Gracheva", "A. Sasnovich"],
        ["Anna Bondar", "Elina Svitolina"],
        ["Paula Badosa", "Katie Boulter"],
        ["S. Sierra", "Olivia Gadecki"],
        ["A. Todoni", "C. Bucsa"],
        ["K. Birrel", "Donna Vekic"],
        ["Leylah Fernandez", "Hannah Klugman"],
        ["Peyton Stearns", "Laura Siegemund"],
        ["Olga Danilovic", "Shuai Zhang"],
        ["Elena Ruse", "Madison Keys"],
        ["Jasmine Paolini", "A. Sevastova"],
        ["K. Rakimova", "Aoi Ito"],
        ["Eva Lys", "Yue Yuan"],
        ["Bernarda Pera", "Linda Noskova"],
        ["Beatrice Haddad Maia", "Rebecca Sramkova"],
        ["Harriet Dart", "Dalma Galfi"],
        ["Yanina Wickmayer", "Renata Zarazua"],
        ["Yulia Putintseva", "Amanda Anisimova"],
        ["Diana Schnaider", "Moyuka Uchijima"],
        ["Diane Parry", "Petra Martic"],
        ["Viktoria Tomova", "Ons Jabeur"],
        ["Sonay Kartal", "Jelena Ostapenko"],
        ["Ashlyn Krueger", "Mika Stojsavljevic"],
        ["Anastasia Pavlyuchenkova", "Aijla Tomlajanovic"],
        ["Naomi Osaka", "Talia Gibson"],
        ["Katerina Siniakova", "Qinwen Zheng"],
        ["Mirra Andreeva", "Mayar Sherif"],
        ["Jil Teichmann", "Lucia Bronzetti"],
        ["Hailey Baptiste", "Sorana Cirstea"],
        ["Anastasia Potapova", "Magdalena Frech"],
        ["Barbora Krejcikova", "Alexandra Eala"],
        ["Caroline Dolehide", "Arantxa Rus"],
        ["V. Kudermetova", "Lin Zhu"],
        ["Petra Kvitova", "Emma Navarro"],
        ["Karolina Muchova", "Xinyu Wang"],
        ["Zeynep Sonmez", "J. Cristian"],
        ["Suzan Lamens", "Iva Jovic"],
        ["Priscilla Hon", "Ekatarina Alexandrova"],
        ["Magda Linette", "Elsa Jacquemot"],
        ["Alycia Parks", "Belinda Bencic"],
        ["Katie Volynets", "Tatjana Maria"],
        ["E. Cocciaretto", "Jessica Pegula"],
        ["Iga Swiatek", "Polina Kudermetova"],
        ["Caty Mcnally", "Jodie Burrage"],
        ["C. Osorio", "Danielle Collins"],
        ["V. Erjavec", "Marta Kostyuk"],
        ["Clara Tauson", "Heather Watson"],
        ["Anna Kalinskaya", "Nina Stojanovich"],
        ["Maria Sakkari", "Anna Blinkova"],
        ["Elina Avanesyan", "Elena Rybakina"],
        ["Daria Kasatkina", "Emiliana Arango"],
        ["Irina C. Begu", "Kaja Juvan"],
        ["Yulia Starodubtseva", "Francesca Jones"],
        ["Maya Joint", "Liudmila Samsonova"],
        ["Sofia Kenin", "Taylor Townsend"],
        ["Maneiro Bouzas", "Ella Seidel"],
        ["Viktoria Azarenka", "Anastasia Zakarova"],
        ["D. Yastremska", "Coco Gauff"]
        // Total of 64 matches = 128 players
      ]
    };

    const savedVersion = localStorage.getItem("wta_bracketVersion");

    if (savedVersion !== bracketData.version) {
      localStorage.removeItem("wta_selectedMap");
      localStorage.removeItem("wta_rounds");
      localStorage.setItem("wta_bracketVersion", bracketData.version);
    }

    const rounds = [bracketData.players];
    for (let i = 1; i < 7; i++) {
      const prev = rounds[i - 1];
      rounds.push(Array.from({ length: prev.length / 2 }, () => ["", ""]));
    }

    const selectedMap = JSON.parse(localStorage.getItem("wta_selectedMap") || "{}");
    const savedRounds = JSON.parse(localStorage.getItem("wta_rounds") || "null");
    if (savedRounds) {
      for (let i = 0; i < rounds.length; i++) {
        if (savedRounds[i]) {
          rounds[i] = savedRounds[i];
        }
      }
    }

    function render() {
      const bracket = document.getElementById("bracket");
      bracket.innerHTML = "";
      rounds.forEach((round, rIdx) => {
        const roundDiv = document.createElement("div");
        roundDiv.className = "round";
        const title = document.createElement("h3");
        title.textContent = ["Round of 128", "Round of 64", "Round of 32", "Round of 16", "Quarterfinals", "Semifinals", "Final"][rIdx];
        roundDiv.appendChild(title);
        round.forEach((match, mIdx) => {
          const matchDiv = document.createElement("div");
          matchDiv.className = "match";
          match.forEach((playerName, pIdx) => {
            const playerDiv = document.createElement("div");
            playerDiv.className = "player";
            playerDiv.textContent = playerName || "(empty)";
            const key = `${rIdx}-${mIdx}`;
            if (selectedMap[key] === pIdx) {
              playerDiv.classList.add("selected");
            }
            playerDiv.addEventListener("click", () => {
              selectedMap[key] = pIdx;
              if (rounds[rIdx + 1]) {
                const nextIdx = Math.floor(mIdx / 2);
                rounds[rIdx + 1][nextIdx][mIdx % 2 === 0 ? 0 : 1] = playerName;
              }
              save();
              render();
            });
            matchDiv.appendChild(playerDiv);
          });
          roundDiv.appendChild(matchDiv);
        });
        bracket.appendChild(roundDiv);
      });
    }

    function save() {
      localStorage.setItem("wta_selectedMap", JSON.stringify(selectedMap));
      localStorage.setItem("wta_rounds", JSON.stringify(rounds));
    }

    render();
  </script>
</body>
</html>

Mindblown: a blog about philosophy.

Got any book recommendations?