import javax.swing.*;
import javax.swing.border.*;
import javax.swing.table.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;
import java.util.List;

/**
 * OHCS Reference Tool — SDG&E Overhead Construction Standards
 * ============================================================
 * Tracks publication dates and provides fast lookup of standards.
 *
 * TO ADD A NEW RELEASE: Add one line to CHANGE_LOG below:
 *   {"MM/DD/YY", "list of standards", "page qty", "filename.pdf"},
 *
 * To compile:  javac OHCSReference.java
 * To run:      java OHCSReference
 * To jar:      jar cfe OHCSReference.jar OHCSReference *.class && java -jar OHCSReference.jar
 */
public class OHCSReference extends JFrame {

    // ─────────────────────────────────────────────────────────────────────────
    // CHANGE LOG DATA  — add new releases here (newest last)
    // Columns: { Date, Standards Modified, Pages Changed, Filename }
    // ─────────────────────────────────────────────────────────────────────────
    static final String[][] CHANGE_LOG = {
        {"01/30/18", "NEW FORMAT RELEASE", "0", "OHCS2018v0130.pdf"},
        {"03/01/18", "103, 340.1, 340.2, 340.3, 631, 701, 711.1-711.2, 712.1-712.2, 713-718, 720.1-720.11, 755.1-755.2, 970.1-970.2, 1207.1-1207.2, 1218.1, 1231.1-1231.4, 1272.2-1272.11, 1320.1-1320.9, 1325.1-1325.9, 1356.1-1356.5, 1452.1-1452.10", "82", "OHCS2018v0301.pdf"},
        {"04/16/18", "303.1-303.6, (379.1-379.54 New Format), 546.1-546.3, 601, 701, 711-718, 755-755.2, 760-764.2, 1002.1-1002.6, 1145-1148.3, 1188.1-1188.3, 1212.1-1212.3, 1273.1-1273.7, 1325.1-1325.9, 1432.1-1432.5, 1442.1-1442.4, 1620.1-1620.8, 1640.1-1640.2", "90", "OHCS2018v0416.pdf"},
        {"05/15/18", "101.1, (379.1-379.54 Removed), 540.1-540.4, 581.1-581.2, 593.1-593.3, 793.1, 901, 967, 968.1-968.2, 1180.1-1180.4, 1271.1-1271.7, 1352.1-1352.4, 1355.1-1355.4", "35", "OHCS2018v0515.pdf"},
        {"06/11/18", "301.1, 331.1-331.3, 435.1-435.4, 576.1-576.3, 1194.1-1194.3, 1320.1-1320.9", "23", "OHCS2018v0611.pdf"},
        {"08/01/18", "102.1-102.9, 220-224.4, 389.1-389.2, 392.1-392.4, 401.1, 430.1-433.2, 435.1-440.3, 473.1-473.2, 565.1-565.2, 601, 720.1-720.11, 750.1-750.5, 941.1-941.2, 1004.1-1004.2, 1240.4-1240.6, 1620.1-1620.8, 1701-1710.1, 801, 805-824 (SAG TABLES)", "160", "OHCS2018v0801.pdf"},
        {"08/24/18", "392.1-392.4, 394.1, 577.1-577.3, 592.1-592.3, 594.1-594.3, 1002.1-1002.6, 1311.1", "7", "OHCS2018v0824.pdf"},
        {"08/30/18", "Special Release — 720.1-720.11, 1272.1-1272.11, 1325.1-1325.9", "3", "OHCS2018v0830.pdf"},
        {"09/21/18", "105.1-105.3, 401.1, 430.1-432.4, 590.1-591.4, 601, (635.4 moved to FMO), 750.1-750.5", "9", "OHCS2018v0921.pdf"},
        {"10/19/18", "301.1, 303.1-303.6, 720.7, 764.1-764.2, 1004.1-1004.2, 1272.1-1272.10, 1274.1-1274.9, 1352.4, SECTION 1100 REFORMATTED", "8", "OHCS2018v1019.pdf"},
        {"11/16/18", "101.1, 103.1, 392.1-392.5, 711.1-711.2, 712.1-712.3, 713-718, 927.1-927.3", "12", "OHCS2018v1116.pdf"},
        {"12/21/18", "1003.1-1003.2, SECTION 600 REFORMATTED", "1", "OHCS2018v1221.pdf"},
        {"01/24/19", "SECTIONS 1600 & 1700 REFORMATTED", "1", "OHCS2019v0124.pdf"},
        {"02/22/19", "432.1-432.4, 701.1, 783.1-783.16, 794.1, SECTIONS 200, 900, 1200, 1300, 1400, 1500 REFORMATTED", "10", "OHCS2019v0222.pdf"},
        {"03/20/19", "379, 430, 1201, (1208 TO FMO), 1212, 1276, 1401, (1432 TO FMO), SECTIONS 300 & 500 REFORMATTED", "8", "OHCS2019v0320.pdf"},
        {"04/22/19", "201, 207, 211, 213, 217, 220, 225, 229, 251, 262, 281, 285, 287, 396, 577, 760, 784, 1004, 1109, 1207, 1222, 1230, 1231, 1518, 1519, 1620, 1630, (433 TEMPORARILY REMOVED), SECTION 700 REFORMATTED", "29", "OHCS2019v0422.pdf"},
        {"05/23/19", "301, 303, 310, 311, 1309", "5", "OHCS2019v0523.pdf"},
        {"06/13/19", "310, 374, 711, 1004, 1640", "5", "OHCS2019v0613.pdf"},
        {"07/11/19", "1700, 1703, 1704, (1705 to FMO), 1706, 1707, 1708, 1710", "8", "OHCS2019v0711.pdf"},
        {"07/15/19", "501, (530 to FMO), 577, 750, 784, 1207", "6", "OHCS2019v0715.pdf"},
        {"08/20/19", "229, 301, (388 to FMO), 560, 1444", "5", "OHCS2019v0820.pdf"},
        {"09/20/19", "251, 396, 540, 760, 908, 1274, 1401, 1800", "8", "OHCS2019v0920.pdf"},
        {"10/25/19", "220, 310, 390, 709, 755, 788, 901, 930, 1206, 1271, 1570, 1571", "12", "OHCS2019v1025.pdf"},
        {"11/19/19", "220, 281, 396, 435, 576, 711, 784, 950, 1121, 1156, 1194, 1240, 1273, 1435, 1530, 1615", "16", "OHCS2019v1119.pdf"},
        {"12/20/19", "909, 1247", "2", "OHCS2019v1220.pdf"},
        {"01/24/20", "Cover Page, 208, 325, 330, 501, 546, 550, 579, 580, 591, 635, 731, 739, 1174, 1231, 1650, 1651, 1652, 1653, 1654, 1655", "21", "OHCS2020v0124.pdf"},
        {"02/19/20", "510, 1242, 1274", "3", "OHCS2020v0219.pdf"},
        {"03/20/20", "200, 207, 211, 217, 225, 228, 229, 262, 264, 281, 401, 474, 501, 560, 576, 783, 1002, 1116, 1207", "19", "OHCS2020v0320.pdf"},
        {"04/24/20", "331, 379, 433, 701, 750, 760, 784, 785, 1201, 1208, 1212, 1272, 1352, 1401, 1442, 1444, 1447, 1561, 1566, 1571, 2000", "21", "OHCS2020v0424.pdf"},
        {"05/22/20", "372, 378, 397, 614, 651, 929, 1168, 1230, 1251, INTERNAL SERVER UPGRADE", "10", "OHCS2020v0522.pdf"},
        {"06/19/20", "784, 1341", "2", "OHCS2020v0619.pdf"},
        {"07/24/20", "251, 320, 1116, 1501, (1511 to FMO), 1651, 1653", "7", "OHCS2020v0724.pdf"},
        {"08/21/20", "363, 474, 750, 789, 927, 928", "6", "OHCS2020v0821.pdf"},
        {"09/25/20", "540, 1122, 1630", "3", "OHCS2020v0925.pdf"},
        {"10/23/20", "501, 543, 1116, 1188, 1190, 1206, 1207, 1212, 1272, 1275, 1452, 2001, 2004, 2007, 2010, 2015, 2025, 2030, 2035, 2036, 2040", "21", "OHCS2020v1023.pdf"},
        {"10/28/20", "105", "1", "OHCS2020v1028.pdf"},
        {"11/20/20", "320, 390, 396, 577, 612, 720, 739, 745, 789, 975, 1000, 1274, 1440", "13", "OHCS2020v1120.pdf"},
        {"12/18/20", "540, 601, 602, 635, 1231, 1325, 1442", "7", "OHCS2020v1218.pdf"},
        {"01/22/21", "Cover Page, Disclaimer, 204, 211, 287", "5", "OHCS2021v0122.pdf"},
        {"02/19/21", "207, 210, 501, 530, 783, 789, 1101, (1194 TO FMO), 1115, 1121, 1141, 1402, 1403, 1435", "14", "OHCS2021v0219.pdf"},
        {"03/19/21", "251, 971, 1341, 1352, 2001, 2004, 2005, 2007, 2010, 2015, 2025, 2030, 2035, 2036, 2040", "15", "OHCS2021v0319.pdf"},
        {"04/23/21", "301, 320, 354, 388, 750", "5", "OHCS2021v0423.pdf"},
        {"05/21/21", "433, 1501, 1572", "3", "OHCS2021v0521.pdf"},
        {"06/25/21", "310", "1", "OHCS2021v0625.pdf"},
        {"07/23/21", "635, 739", "2", "OHCS2021v0723.pdf"},
        {"08/20/21", "206, 287, 303, 320, 432, 545, 546, 550, 612, 720, 908, 1101, 1184, (1192 to FMO), 1218, 1320, 1451, 1704", "19", "OHCS2021v0820.pdf"},
        {"09/24/21", "379, 435, 758, 1222, 1404, 1406, 1414, 1418, 1440, 1444, 1509, 1640", "12", "OHCS2021v0924.pdf"},
        {"10/22/21", "201, 208, 213, 220, 320, 430, 543, 1212, 1274, 1620, 1650, 1651", "12", "OHCS2021v1022.pdf"},
        {"11/19/21", "927, 1121, 1131, 1141, 1860, 1920", "6", "OHCS2021v1119.pdf"},
        {"12/17/21", "229, 262, 301, 315, 331, 354, 435, 474, 540, 711, 720, 739, 750, 784, 793, 1201, 1208, (1230 to FMO), 1231, 1242, 1247, 1271, 1301, 1309, 1311, 1320, 1404, 1801, 1821, 1822, 1830, 1831, 1832, 1840, 1850", "35", "OHCS2021v1217.pdf"},
        {"01/21/22", "Cover Page", "1", "OHCS2022v0121.pdf"},
        {"02/25/22", "401, 501, 1201, 1207, 1210, (1215 to FMO), 1314, 1401, 1402, 1406, 1501, 1510, 1512, 1514, 1570, 1571, 1573, 1630, 2025", "19", "OHCS2022v0225.pdf"},
        {"03/25/22", "101, 103, 105, 390, 801, 1002, 1414, 1812, 1820, 1920", "10", "OHCS2022v0325.pdf"},
        {"04/22/22", "102, 530, 1003, 1418, 1701, 1704, 1805, 1901", "8", "OHCS2022v0422.pdf"},
        {"05/20/22", "201, 290, 1001, 1206, 1301, (1316 to FMO), 1403, 1435, 1702", "9", "OHCS2022v0520.pdf"},
        {"06/24/22", "1610, 1615, 1821", "3", "OHCS2022v0624.pdf"},
        {"07/22/22", "331, 545, 575, 720, 739, 1406, 1444, 1451, 1830, 2004", "10", "OHCS2022v0722.pdf"},
        {"08/17/22", "432, 437, 576, 801, 1101, 1104, 1208, 1247, 1831", "9", "OHCS2022v0817.pdf"},
        {"09/23/22", "303, 1105, 1109, 1218, 1570, 1601, 1810, 2035, Disclaimer", "9", "OHCS2022v0923.pdf"},
        {"10/14/22", "1101, 1111, 1115, 1116, 1811", "5", "OHCS2022v1014.pdf"},
        {"11/22/22", "301, 379, 389, 397, 440, 590, 612, 701, 789, 941, 971, 1101, 1122, (1190 to FMO), 1206, 1440, 1601, (1660 to FMO)", "18", "OHCS2022v1122.pdf"},
        {"12/22/22", "540, 635, 1125, 1222, 1274, 1832", "6", "OHCS2022v1222.pdf"},
        {"01/20/23", "Cover Page, Disclaimer, 211, 1184", "4", "OHCS2023v0120.pdf"},
        {"02/07/23", "(1440 reverted to previous version)", "1", "OHCS2023v0207.pdf"},
        {"02/24/23", "208, 961, 2036", "3", "OHCS2023v0224.pdf"},
        {"03/24/23", "390, 602, 907, 1101, (1156 to FMO), 1231, 1444, 1571, 1822", "9", "OHCS2023v0324.pdf"},
        {"04/21/23", "346, 546, 581, 701, 739, 745, 783, 787, 901, (974 to FMO), 1170, 1201, (1243 to FMO), 1352, 2005, 1500", "15", "OHCS2023v0421.pdf"},
        {"05/19/23", "201, 204, 207, 216, 285, 287, 325, 430, 530, 579, 580, 590, 635, 760, 785, 962, 1121, 1222, 1601, 1610, (1650-1653 to FMO), 2004, 2025", "25", "OHCS2023v0519.pdf"},
        {"06/23/23", "210, 211, 220, 281, 380, 396, 511, 711, 784, 787, 908, 971, 1004, 1101, (1188 to FMO), 1247, 1276, 1452, 1620, 1830", "20", "OHCS2023v0623.pdf"},
        {"07/21/23", "374, 543, 969, 1174, 1201, (1204 to FMO), (1242 to FMO)", "7", "OHCS2023v0721.pdf"},
        {"07/27/23", "229, 354", "2", "OHCS2023v0727.pdf"},
        {"08/25/23", "432, 1141, 1435, 1501, (1510 to FMO)", "5", "OHCS2023v0825.pdf"},
        {"09/22/23", "201, 209, 218, 225, (264 to FMO), 303, 379, 401, 414, 415, 420, 421, 422, 581, 755, 1101, (1168 to FMO), 1201, 1231, (1273 to FMO), 1640, 2010", "21", "OHCS2023v0922.pdf"},
        {"10/20/23", "217, 750, 1703, 1706", "4", "OHCS2023v1020.pdf"},
        {"11/22/23", "301, 349, 350, 474, 1707, 1708, 1709, 2035", "8", "OHCS2023v1122.pdf"},
        {"12/21/23", "216, 228, 229, 330, 383, 760, 783, 788, 1003, 1170, 1174, 1309, 2005", "13", "OHCS2023v1221.pdf"},
        {"01/19/24", "397, 601, 701, 1247", "4", "OHCS2024v0119.pdf"},
        {"01/31/24", "Cover Page, 1247, 1444", "3", "OHCS2024v0131.pdf"},
        {"02/23/24", "209, 290, 379, 644, 720, 755, 928, 1212, 1352, 2015", "10", "OHCS2024v0223.pdf"},
        {"03/22/24", "340, 352, 373, 1121, 1207, 1271, 1301, 1355, 1570, 1573, 2035, 2036", "12", "OHCS2024v0322.pdf"},
        {"04/19/24", "103, 216, 225, 285, 331, 645, 731, 758, 773, 775, 777, 793, 901, 961, 1247, 1710, 1805", "17", "OHCS2024v0419.pdf"},
        {"06/07/24", "228, 315, 330, 376, 378, 380, 381, 473, 631, 646, 788, 920, 973, 1201, 1512, 1530, 1901", "17", "OHCS2024v0607.pdf"},
        {"06/21/24", "213, 346, 711, 1002, 1501, 1812", "6", "OHCS2024v0621.pdf"},
        {"08/23/24", "201, 303, 501, 592, 801, 1201, 1277, 2004", "8", "OHCS2024v0823.pdf"},
        {"09/20/24", "363, 401, 801, 901, 929, 969, (972 to FMO), 1401, 1519, 1701", "10", "OHCS2024v0920.pdf"},
        {"10/25/24", "382, 501, 975, 1401, 2010", "5", "OHCS2024v1025.pdf"},
        {"11/22/24", "201, 228, 1128, 1655, 2007", "5", "OHCS2024v1122.pdf"},
        {"12/13/24", "310, 433, 1401, 1418, 1850", "5", "OHCS2024v1213.pdf"},
        {"01/24/25", "101, 102, 105, 106, 311, 363, 433, 575, 591, 601, 930, 950, 1001, 1003, 1101, 1630, 1640, 2004", "18", "OHCS2025v0124.pdf"},
        {"02/21/25", "201, 228, 379, 397, 437, 1105, 1276, 1301, 1314, 1440, 1447, 1570, 2010", "13", "OHCS2025v0221.pdf"},
        {"03/21/25", "379, 1212", "2", "OHCS2025v0321.pdf"},
        {"05/23/25", "1271, 1272, 1341, 1442, 1620, 1654, 2004", "7", "OHCS2025v0523.pdf"},
        {"05/28/25", "739", "1", "OHCS2025v0528.pdf"},
        {"06/20/25", "218, 927, 929, 1101, (1104 REMOVED), 1274, 1352, 1435, 1452, 2005", "10", "OHCS2025v0620.pdf"},
        {"07/18/25", "208, 701, (2040 moved to 786), 739, 750, 1002, 1218, 1355, 2001, 2034", "11", "OHCS2025v0718.pdf"},
        {"08/22/25", "211, 217, 363, 711, 786, 1206, 1212, 1440, 1442, 1615", "10", "OHCS2025v0822.pdf"},
        {"09/19/25", "210, 1206, 1222, 1447", "4", "OHCS2025v0919.pdf"},
        {"10/24/25", "401, 480, 739, 783, 1207, 1440", "6", "OHCS2025v1024.pdf"},
        {"11/21/25", "207, 229, 311, 701, 782, 1247, 1620, 1640, 2005, 2025", "10", "OHCS2025v1121.pdf"},
        {"12/19/25", "379, 565, 617, 907", "4", "OHCS2025v1219.pdf"},
        {"01/23/26", "208, 315, 331, 390, 435, 440, 701, 750, 784, 909, 1141, 1709, 2004, 2015, 2030", "15", "OHCS2026v0123.pdf"},
        {"02/20/26", "908, 1630", "2", "OHCS2026v0220.pdf"},
        {"03/20/26", "229, 385, 581, 590, 1207, 1240, 1247, 1271, 1320, 1325, 1414", "11", "OHCS2026v0320.pdf"},
    };

    // ─────────────────────────────────────────────────────────────────────────
    // SECTION DESCRIPTIONS
    // ─────────────────────────────────────────────────────────────────────────
    static final String[][] SECTIONS = {
        {"100",  "General Information — Construction Standard Requests, Deviation Requests, Page Format"},
        {"200",  "Practices — Pole Marking, GFMS Maps, Working Space, G.O. Requirements"},
        {"300",  "Poles, Arms & Hardware — Pole Info, Loading Districts, Crossarms, Conductor Loading"},
        {"400",  "Distribution Pole Tops — Crossarm/Buckarm Construction, Flying Tap, Alley Arms"},
        {"500",  "Telecommunications, SCADA & Fiber Optics — Cable, SCADA Switch, Repeater, Load Monitor"},
        {"600",  "Secondaries, Services — 0-750V Cable, Mid-Span Services, Connections, Cathodic Protection"},
        {"700",  "Conductor Data & Accessories — Wire specs, connectors, accessories"},
        {"800",  "Sag — Sag tables, calculations, clearances"},
        {"900",  "Guying — Guy wire, anchors, dead-ends"},
        {"1000", "Grounding & Bonding — Ground rods, bonding conductors, electrode systems"},
        {"1100", "Transformers & Boosters — Distribution transformers, kVA sizing, boosters"},
        {"1200", "Sectionalizing & Arresters — Switches, fuses, reclosers, surge arresters"},
        {"1300", "Capacitors & Regulators — Shunt capacitors, voltage regulators"},
        {"1400", "Cable Poles — Joint cable poles, primary cable construction, risers"},
        {"1500", "Lighting — Street lighting, switching, photoelectric controls, clearances"},
        {"1600", "Wildlife Protection — Critical area maps, cover-up devices, avian safe construction"},
        {"1700", "Spacer Cable System — Cable/messenger, dead-ends, tangent, line angles"},
        {"1800", "Engineered Steel Poles — External risers, steel pole construction"},
        {"1900", "Miscellaneous Equipment — Various utility equipment and hardware"},
        {"2000", "Covered Conductor — Covered conductor system construction"},
    };

    // ─────────────────────────────────────────────────────────────────────────
    // COLORS
    // ─────────────────────────────────────────────────────────────────────────
    static final Color NAVY       = new Color(0x0D, 0x2B, 0x4E);
    static final Color ORANGE     = new Color(0xE0, 0x7B, 0x2A);
    static final Color LIGHT_BLUE = new Color(0xE8, 0xF2, 0xFB);
    static final Color ROW_ALT    = new Color(0xF5, 0xF8, 0xFC);
    static final Color WHITE      = Color.WHITE;

    // UI fields
    private JTextField searchField;
    private JTable changeTable;
    private DefaultTableModel changeModel;
    private JTable sectionTable;
    private JLabel statusLabel;
    private JTextArea detailArea;
    private String pdfPath = "";

    // ─────────────────────────────────────────────────────────────────────────
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); }
            catch (Exception ignored) {}
            new OHCSReference().setVisible(true);
        });
    }

    // ─────────────────────────────────────────────────────────────────────────
    public OHCSReference() {
        super("OHCS Reference — SDG&E Overhead Construction Standards");
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setSize(1100, 760);
        setMinimumSize(new Dimension(800, 560));
        setLocationRelativeTo(null);

        setLayout(new BorderLayout());
        add(buildHeader(), BorderLayout.NORTH);
        add(buildTabs(),   BorderLayout.CENTER);
        add(buildStatus(), BorderLayout.SOUTH);

        // Reverse change log so newest is first
        reverseChangeLog();
        refreshChangeTable("");
    }

    // ─────────────────────────────────────────────────────────────────────────
    // Reverse the change log so newest release is first
    // ─────────────────────────────────────────────────────────────────────────
    static String[][] reversedLog;
    static {
        reversedLog = new String[CHANGE_LOG.length][];
        for (int i = 0; i < CHANGE_LOG.length; i++) {
            reversedLog[i] = CHANGE_LOG[CHANGE_LOG.length - 1 - i];
        }
    }

    void reverseChangeLog() { /* data already reversed in static block */ }

    // ─────────────────────────────────────────────────────────────────────────
    // HEADER
    // ─────────────────────────────────────────────────────────────────────────
    JPanel buildHeader() {
        JPanel header = new JPanel(new BorderLayout());
        header.setBackground(NAVY);
        header.setBorder(BorderFactory.createMatteBorder(0, 0, 3, 0, ORANGE));

        // Title
        JPanel titlePanel = new JPanel(new GridLayout(2, 1, 0, 2));
        titlePanel.setBackground(NAVY);
        titlePanel.setBorder(new EmptyBorder(12, 18, 12, 18));

        JLabel title = new JLabel("SDG&E Overhead Construction Standards (OHCS)");
        title.setForeground(WHITE);
        title.setFont(new Font("Segoe UI", Font.BOLD, 16));

        String latestDate = reversedLog[0][0];
        String latestFile = reversedLog[0][3];
        JLabel sub = new JLabel("Current: " + latestFile + "  ·  Released: " + latestDate +
                "  ·  " + CHANGE_LOG.length + " releases tracked since 2018");
        sub.setForeground(new Color(0x90, 0xB8, 0xE0));
        sub.setFont(new Font("Segoe UI", Font.PLAIN, 11));

        titlePanel.add(title);
        titlePanel.add(sub);
        header.add(titlePanel, BorderLayout.CENTER);

        // Search + PDF button
        JPanel rightPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT, 10, 12));
        rightPanel.setBackground(NAVY);

        searchField = new JTextField(18);
        searchField.setFont(new Font("Segoe UI", Font.PLAIN, 13));
        searchField.putClientProperty("JTextField.placeholderText", "Search standard # or keyword…");
        searchField.addKeyListener(new KeyAdapter() {
            public void keyReleased(KeyEvent e) { doSearch(); }
        });

        JButton searchBtn = navButton("🔍 Search", ORANGE, WHITE);
        searchBtn.addActionListener(e -> doSearch());

        JButton pdfBtn = navButton("📂 Load PDF", new Color(0x1A, 0x4F, 0x8A), WHITE);
        pdfBtn.addActionListener(e -> loadPdf());

        rightPanel.add(new JLabel("  ") {{ setForeground(WHITE); }});
        rightPanel.add(searchField);
        rightPanel.add(searchBtn);
        rightPanel.add(pdfBtn);

        header.add(rightPanel, BorderLayout.EAST);
        return header;
    }

    JButton navButton(String text, Color bg, Color fg) {
        JButton btn = new JButton(text);
        btn.setBackground(bg);
        btn.setForeground(fg);
        btn.setFont(new Font("Segoe UI", Font.BOLD, 12));
        btn.setBorder(new EmptyBorder(7, 14, 7, 14));
        btn.setFocusPainted(false);
        btn.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
        return btn;
    }

    // ─────────────────────────────────────────────────────────────────────────
    // TABS
    // ─────────────────────────────────────────────────────────────────────────
    JTabbedPane buildTabs() {
        JTabbedPane tabs = new JTabbedPane();
        tabs.setFont(new Font("Segoe UI", Font.BOLD, 12));
        tabs.addTab("📋 Change Log", buildChangeLogTab());
        tabs.addTab("📁 Sections", buildSectionsTab());
        tabs.addTab("🔍 Standard Lookup", buildLookupTab());
        return tabs;
    }

    // ─────────────────────────────────────────────────────────────────────────
    // TAB 1: CHANGE LOG
    // ─────────────────────────────────────────────────────────────────────────
    JPanel buildChangeLogTab() {
        JPanel panel = new JPanel(new BorderLayout(0, 0));

        // Table
        String[] cols = {"Date", "Pages", "Filename", "Standards Modified"};
        changeModel = new DefaultTableModel(cols, 0) {
            public boolean isCellEditable(int r, int c) { return false; }
        };
        changeTable = new JTable(changeModel);
        changeTable.setFont(new Font("Segoe UI", Font.PLAIN, 12));
        changeTable.setRowHeight(22);
        changeTable.setShowGrid(false);
        changeTable.setIntercellSpacing(new Dimension(0, 0));
        changeTable.getTableHeader().setFont(new Font("Segoe UI", Font.BOLD, 12));
        changeTable.getTableHeader().setBackground(NAVY);
        changeTable.getTableHeader().setForeground(WHITE);

        // Column widths
        changeTable.getColumnModel().getColumn(0).setPreferredWidth(80);
        changeTable.getColumnModel().getColumn(1).setPreferredWidth(50);
        changeTable.getColumnModel().getColumn(2).setPreferredWidth(160);
        changeTable.getColumnModel().getColumn(3).setPreferredWidth(700);

        // Alternating row colors
        changeTable.setDefaultRenderer(Object.class, new DefaultTableCellRenderer() {
            public Component getTableCellRendererComponent(JTable t, Object v, boolean sel, boolean foc, int r, int c) {
                super.getTableCellRendererComponent(t, v, sel, foc, r, c);
                if (sel) {
                    setBackground(ORANGE); setForeground(WHITE);
                } else {
                    setBackground(r % 2 == 0 ? WHITE : ROW_ALT);
                    setForeground(Color.BLACK);
                }
                setBorder(new EmptyBorder(2, 8, 2, 8));
                // Highlight dates in orange
                if (c == 0 && !sel) { setForeground(new Color(0x1A, 0x4F, 0x8A)); setFont(getFont().deriveFont(Font.BOLD)); }
                // Filename in teal
                if (c == 2 && !sel) { setForeground(new Color(0x0D, 0x94, 0x88)); }
                return this;
            }
        });

        // Click row → show detail + open PDF button
        changeTable.getSelectionModel().addListSelectionListener(e -> {
            if (!e.getValueIsAdjusting()) showChangeDetail();
        });

        // Double-click → open PDF
        changeTable.addMouseListener(new MouseAdapter() {
            public void mouseClicked(MouseEvent e) {
                if (e.getClickCount() == 2) openPdf();
            }
        });

        JScrollPane scroll = new JScrollPane(changeTable);
        scroll.setBorder(BorderFactory.createEmptyBorder());

        // Detail panel at bottom
        detailArea = new JTextArea(4, 40);
        detailArea.setFont(new Font("Segoe UI", Font.PLAIN, 12));
        detailArea.setEditable(false);
        detailArea.setLineWrap(true);
        detailArea.setWrapStyleWord(true);
        detailArea.setBackground(LIGHT_BLUE);
        detailArea.setBorder(new EmptyBorder(10, 14, 10, 14));
        detailArea.setText("← Select a row to see full list of standards changed.   Double-click to open PDF.");

        JPanel bottomBar = new JPanel(new BorderLayout());
        bottomBar.setBorder(BorderFactory.createMatteBorder(2, 0, 0, 0, ORANGE));
        bottomBar.add(new JScrollPane(detailArea), BorderLayout.CENTER);

        JButton openBtn = navButton("📄 Open PDF", new Color(0x1A, 0x4F, 0x8A), WHITE);
        openBtn.addActionListener(e -> openPdf());
        JPanel btnPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT, 10, 8));
        btnPanel.setBackground(LIGHT_BLUE);
        btnPanel.add(openBtn);
        bottomBar.add(btnPanel, BorderLayout.EAST);

        JSplitPane split = new JSplitPane(JSplitPane.VERTICAL_SPLIT, scroll, bottomBar);
        split.setResizeWeight(0.75);
        split.setDividerSize(4);
        panel.add(split, BorderLayout.CENTER);
        return panel;
    }

    void showChangeDetail() {
        int row = changeTable.getSelectedRow();
        if (row < 0) return;
        String date  = (String) changeModel.getValueAt(row, 0);
        String pages = (String) changeModel.getValueAt(row, 1);
        String file  = (String) changeModel.getValueAt(row, 2);
        String stds  = (String) changeModel.getValueAt(row, 3);
        detailArea.setText("Release: " + file + "   |   Date: " + date + "   |   Pages changed: " + pages +
                "\n\nStandards modified:\n" + stds);
        detailArea.setCaretPosition(0);
        setStatus("Selected: " + file + " — " + date);
    }

    void refreshChangeTable(String filter) {
        changeModel.setRowCount(0);
        String q = filter.trim().toLowerCase();
        int count = 0;
        for (String[] row : reversedLog) {
            if (q.isEmpty() || row[0].contains(q) || row[1].toLowerCase().contains(q)
                    || row[2].toLowerCase().contains(q) || row[3].toLowerCase().contains(q)) {
                changeModel.addRow(new Object[]{row[0], row[1], row[2], row[3]});
                count++;
            }
        }
        setStatus(count + " release(s) shown" + (q.isEmpty() ? "" : " matching "" + q + """));
    }

    // ─────────────────────────────────────────────────────────────────────────
    // TAB 2: SECTIONS
    // ─────────────────────────────────────────────────────────────────────────
    JPanel buildSectionsTab() {
        JPanel panel = new JPanel(new BorderLayout());

        String[] cols = {"Section", "Description"};
        DefaultTableModel model = new DefaultTableModel(cols, 0) {
            public boolean isCellEditable(int r, int c) { return false; }
        };
        for (String[] s : SECTIONS) {
            model.addRow(new Object[]{s[0], s[1]});
        }

        JTable table = new JTable(model);
        table.setFont(new Font("Segoe UI", Font.PLAIN, 13));
        table.setRowHeight(26);
        table.setShowGrid(false);
        table.setIntercellSpacing(new Dimension(0, 0));
        table.getTableHeader().setFont(new Font("Segoe UI", Font.BOLD, 13));
        table.getTableHeader().setBackground(NAVY);
        table.getTableHeader().setForeground(WHITE);
        table.getColumnModel().getColumn(0).setPreferredWidth(70);
        table.getColumnModel().getColumn(1).setPreferredWidth(900);

        table.setDefaultRenderer(Object.class, new DefaultTableCellRenderer() {
            public Component getTableCellRendererComponent(JTable t, Object v, boolean sel, boolean foc, int r, int c) {
                super.getTableCellRendererComponent(t, v, sel, foc, r, c);
                if (sel) { setBackground(ORANGE); setForeground(WHITE); }
                else { setBackground(r % 2 == 0 ? WHITE : ROW_ALT); setForeground(Color.BLACK); }
                if (c == 0 && !sel) { setFont(getFont().deriveFont(Font.BOLD)); setForeground(NAVY); }
                setBorder(new EmptyBorder(4, 10, 4, 10));
                return this;
            }
        });

        // Click section → filter change log
        table.getSelectionModel().addListSelectionListener(e -> {
            if (!e.getValueIsAdjusting() && table.getSelectedRow() >= 0) {
                String sec = (String) model.getValueAt(table.getSelectedRow(), 0);
                searchField.setText(sec);
                doSearch();
                setStatus("Showing changes for Section " + sec);
            }
        });

        JLabel hint = new JLabel("  Click a section to filter the Change Log tab");
        hint.setFont(new Font("Segoe UI", Font.ITALIC, 11));
        hint.setForeground(Color.GRAY);
        hint.setBorder(new EmptyBorder(6, 10, 6, 10));

        panel.add(hint, BorderLayout.NORTH);
        panel.add(new JScrollPane(table), BorderLayout.CENTER);
        return panel;
    }

    // ─────────────────────────────────────────────────────────────────────────
    // TAB 3: STANDARD LOOKUP
    // ─────────────────────────────────────────────────────────────────────────
    JPanel buildLookupTab() {
        JPanel panel = new JPanel(new BorderLayout(10, 10));
        panel.setBorder(new EmptyBorder(18, 18, 18, 18));

        // Input row
        JPanel inputRow = new JPanel(new FlowLayout(FlowLayout.LEFT, 10, 0));
        JLabel lbl = new JLabel("Enter Standard Number:");
        lbl.setFont(new Font("Segoe UI", Font.BOLD, 13));
        JTextField stdInput = new JTextField(12);
        stdInput.setFont(new Font("Segoe UI", Font.PLAIN, 14));
        JButton lookupBtn = navButton("Find All Changes", ORANGE, WHITE);

        inputRow.add(lbl);
        inputRow.add(stdInput);
        inputRow.add(lookupBtn);

        // Results
        JTextArea results = new JTextArea();
        results.setFont(new Font("Courier New", Font.PLAIN, 12));
        results.setEditable(false);
        results.setBackground(LIGHT_BLUE);
        results.setBorder(new EmptyBorder(12, 14, 12, 14));
        results.setText("Enter a standard number above (e.g. 711, 1207, 379) and click Find.\n" +
                "Shows every release date that standard was modified.");

        Runnable doLookup = () -> {
            String q = stdInput.getText().trim();
            if (q.isEmpty()) return;
            StringBuilder sb = new StringBuilder();
            sb.append("Standard: ").append(q).append("\n");

            // Determine section
            try {
                int num = Integer.parseInt(q.replaceAll("[^0-9]", ""));
                int sec = (num / 100) * 100;
                for (String[] s : SECTIONS) {
                    if (s[0].equals(String.valueOf(sec))) {
                        sb.append("Section ").append(sec).append(": ").append(s[1]).append("\n");
                        break;
                    }
                }
            } catch (Exception ignored) {}

            sb.append("\n").append("─".repeat(60)).append("\n");
            sb.append(String.format("%-12s %-8s %s%n", "Date", "Pages", "File"));
            sb.append("─".repeat(60)).append("\n");

            int found = 0;
            // Search newest first
            for (String[] row : reversedLog) {
                // Match whole standard number (avoid 711 matching 1711)
                String stds = row[3];
                if (containsStandard(stds, q)) {
                    sb.append(String.format("%-12s %-8s %s%n", row[0], row[1], row[2]));
                    found++;
                }
            }

            if (found == 0) {
                sb.append("No changes found for standard ").append(q).append(".\n");
                sb.append("Try a partial number or check the Change Log tab.");
            } else {
                sb.append("\n").append(found).append(" release(s) modified this standard.");
            }

            results.setText(sb.toString());
            results.setCaretPosition(0);
            setStatus("Found " + found + " release(s) for standard " + q);
        };

        lookupBtn.addActionListener(e -> doLookup.run());
        stdInput.addKeyListener(new KeyAdapter() {
            public void keyPressed(KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_ENTER) doLookup.run(); }
        });

        panel.add(inputRow, BorderLayout.NORTH);
        panel.add(new JScrollPane(results), BorderLayout.CENTER);
        return panel;
    }

    /** Match exact standard number, avoiding false positives (e.g. 711 vs 1711) */
    boolean containsStandard(String haystack, String needle) {
        // Normalize
        String h = " " + haystack.replace(",", " ").replace("-", " ") + " ";
        // Look for the needle surrounded by non-digit chars
        return h.matches("(?i).*[^0-9]" + needle.replace(".", "\\.") + "[^0-9].*") ||
               haystack.toLowerCase().contains(needle.toLowerCase());
    }

    // ─────────────────────────────────────────────────────────────────────────
    // STATUS BAR
    // ─────────────────────────────────────────────────────────────────────────
    JPanel buildStatus() {
        JPanel bar = new JPanel(new BorderLayout());
        bar.setBackground(new Color(0x07, 0x15, 0x26));
        bar.setBorder(new EmptyBorder(4, 14, 4, 14));

        statusLabel = new JLabel("Ready — " + CHANGE_LOG.length + " releases loaded  |  " +
                "Current version: " + reversedLog[0][3] + "  (" + reversedLog[0][0] + ")");
        statusLabel.setForeground(new Color(0x90, 0xB8, 0xE0));
        statusLabel.setFont(new Font("Segoe UI", Font.PLAIN, 11));

        JLabel hint = new JLabel("Double-click a row to open PDF  |  Load PDF first with 📂 button");
        hint.setForeground(new Color(0x6A, 0x90, 0xB8));
        hint.setFont(new Font("Segoe UI", Font.PLAIN, 11));

        bar.add(statusLabel, BorderLayout.WEST);
        bar.add(hint, BorderLayout.EAST);
        return bar;
    }

    void setStatus(String msg) {
        statusLabel.setText(msg);
    }

    // ─────────────────────────────────────────────────────────────────────────
    // ACTIONS
    // ─────────────────────────────────────────────────────────────────────────
    void doSearch() {
        refreshChangeTable(searchField.getText());
    }

    void loadPdf() {
        JFileChooser fc = new JFileChooser();
        fc.setDialogTitle("Locate OHCS PDF file");
        fc.setFileFilter(new javax.swing.filechooser.FileNameExtensionFilter("PDF files", "pdf"));
        int result = fc.showOpenDialog(this);
        if (result == JFileChooser.APPROVE_OPTION) {
            pdfPath = fc.getSelectedFile().getAbsolutePath();
            setStatus("PDF loaded: " + fc.getSelectedFile().getName() + " — double-click a row to open");
        }
    }

    void openPdf() {
        if (pdfPath.isEmpty()) {
            JOptionPane.showMessageDialog(this,
                "No PDF loaded. Click the '📂 Load PDF' button first to point to your OHCS PDF file.",
                "Load PDF First", JOptionPane.INFORMATION_MESSAGE);
            return;
        }
        try {
            Desktop.getDesktop().open(new File(pdfPath));
        } catch (Exception ex) {
            JOptionPane.showMessageDialog(this, "Could not open PDF:\n" + ex.getMessage(),
                "Error", JOptionPane.ERROR_MESSAGE);
        }
    }
}
