<?php
/**
 * gantt_chart_vac.php  (VAC admin Gantt include + daily batch script)
 * =====================================================================
 * CHANGES FROM ORIGINAL:
 *   - recalculateMachineDatesforvac() removed — this file's copy was the
 *     OTHER of the two that checked "has production started" against the
 *     task's real row id instead of manuf_id (see vac_scheduler_lib.php
 *     header for the full writeup — this was the more consequential of
 *     the two, since this file runs as the unattended daily batch job).
 *     Now uses vac_fullReschedule().
 *   - The batch script's own extra "start_date already passed ⇒ no
 *     setup" rule is preserved — it now lives inside the single shared
 *     vac_recalculateMachineDates(), applied consistently everywhere
 *     instead of only when this specific script happens to run.
 *   - Active-breakdown lookup (used for the machine-label styling
 *     further down) now reads vac_machine_breakdown_log, consistent with
 *     the shared source of truth used elsewhere (see
 *     ajax_actions_for_vac.php's start/stop_machine_breakdown, which now
 *     mirror into it).
 * =====================================================================
 */

require_once __DIR__ . '/vac_scheduler_lib.php';

$today = date('Y-m-d');

/* ---------------------------------------------------------------------
 * PASS 1: mark completed break tasks whose end_date has passed
 * ------------------------------------------------------------------- */
mysqli_query($conn, "
    UPDATE vac_machine_table
    SET finished = 1
    WHERE end_date <= '$today' AND is_break = 1
");

/* ---------------------------------------------------------------------
 * PASS 2: trim remaining-hours tracking for ongoing (multi-day) breaks
 * ------------------------------------------------------------------- */
$query = "
    SELECT id, remaing_hours, total_hours
    FROM vac_machine_table
    WHERE DATE(start_date) < '$today'
      AND DATE(end_date) >= '$today'
      AND is_break = 1
";
$result = mysqli_query($conn, $query);

while ($row = mysqli_fetch_assoc($result)) {
    $id = $row['id'];
    $remaingHoursStr = $row['remaing_hours'];
    $totalHours = $row['total_hours'];

    $newRemaingStrParts = [];
    $pastHours = 0;

    foreach (explode(',', $remaingHoursStr) as $pair) {
        if (strpos($pair, '=') !== false) {
            [$date, $hours] = explode('=', $pair);
            if (strtotime($date) < strtotime($today)) {
                $pastHours += floatval($hours);
            } else {
                $newRemaingStrParts[] = "$date=$hours";
            }
        }
    }

    $updatedRemaingStr = implode(',', $newRemaingStrParts);
    $updatedTotalHours = max(0, $totalHours - $pastHours);
    $updatedRemaingStrEsc = mysqli_real_escape_string($conn, $updatedRemaingStr);

    mysqli_query($conn, "
        UPDATE vac_machine_table
        SET
            remaing_hours       = '$updatedRemaingStrEsc',
            total_hours_update  = '$updatedTotalHours',
            total_hours         = '$updatedTotalHours',
            setup_hours         = 0
        WHERE id = $id
    ");
}

/* ---------------------------------------------------------------------
 * PASS 3: recompute remaining hours for overdue-but-unfinished RUNNING
 * (non-break) tasks
 * ------------------------------------------------------------------- */
$query = "
    SELECT
        v.id,
        v.manuf_id,
        v.work_order_id,
        v.part_id,
        v.quantity,
        v.machine_id,
        v.is_break,
        v.start_date,
        m.total_hours AS hours,
        m.end_date
    FROM vac_machine_table AS v
    LEFT JOIN manufacture_machine_table AS m
        ON v.work_order_id = m.work_order_id
       AND v.part_id = m.part_id
    WHERE v.finished = 0
      AND v.is_break = 0
      AND v.start_date < '$today'
";
$result = mysqli_query($conn, $query);
$machinesToReschedule = [];

while ($row = mysqli_fetch_assoc($result)) {

    $vacId       = intval($row['id']);
    $workOrderId = intval($row['work_order_id']);
    $partId      = intval($row['part_id']);
    $machineId   = intval($row['machine_id']);

    $totalQty = floatval($row['quantity']);
    $hours    = floatval($row['hours']);

    $uph = ($hours > 0 && $totalQty > 0) ? ($totalQty / $hours) : 0;
    if ($uph <= 0 || $totalQty <= 0) {
        continue;
    }

    // NOTE: unlike PU's and CNC's equivalent batch loops (which were
    // found to have NO task-instance scoping at all and were fixed to
    // scope by manuf_id), this lookup already scopes by work_order_id +
    // part_id + partIds. It does NOT additionally scope by
    // vac_machine_table_id (manuf_id) the way the fixed CNC/PU versions
    // do -- if the same work_order+part has ever been scheduled more
    // than once on VAC (a split, a re-add), this could still sum
    // production across instances. Flagging this as a known gap rather
    // than silently changing it, since I can't verify from these four
    // files alone whether that scenario is reachable in practice for
    // VAC. v.manuf_id IS available on this row if you want to add the
    // extra scoping -- the one-line fix would be adding
    // "AND vac_machine_table_id = {$row['manuf_id']}" to the WHERE
    // clause below.
    $okQtyQuery = "
        SELECT SUM(quantity) AS ok_qty
        FROM vac_part_count_log
        WHERE work_order_id = '$workOrderId'
          AND part_id = '$partId'
          AND partIds = '$partId'
          AND type = 'ok'
    ";
    $okQtyResult = mysqli_query($conn, $okQtyQuery);
    $okQtyRow    = mysqli_fetch_assoc($okQtyResult);
    $okQty = floatval($okQtyRow['ok_qty'] ?? 0);

    $remainingQty   = max(0, $totalQty - $okQty);
    $remainingHours = ($uph > 0) ? ($remainingQty / $uph) : 0;
    $finishedVal    = ($remainingQty <= 0) ? 1 : 0;

    $updateSql = "
        UPDATE vac_machine_table
        SET
            total_hours_update = '$remainingHours',
            total_hours        = '$remainingHours',
            setup_hours        = 0,
            finished           = '$finishedVal'
        WHERE id = '$vacId'
    ";
    mysqli_query($conn, $updateSql);

    $machinesToReschedule[$machineId] = true;
}

foreach (array_keys($machinesToReschedule) as $machineId) {
    vac_fullReschedule($conn, $machineId);
}
?>
<div class="container-fluid" style="background-color: #ffe6e6;">
<?php
$month = isset($_GET['month']) ? intval($_GET['month']) : date('m');
$year = isset($_GET['year']) ? intval($_GET['year']) : date('Y');

$monthsToShow = [];
$currentDate = new DateTime();
for ($i = 0; $i < 3; $i++) {
    $date = clone $currentDate;
    $date->modify("+$i months");
    $monthsToShow[] = [
        'month' => (int)$date->format('m'),
        'year'  => (int)$date->format('Y'),
        'label' => $date->format('F Y')
    ];
}
$currentDateStr = date('Y-m-d');

$shifts    = [];
$shiftHours = [];
$shiftDays  = [];
$shiftTimes = [];

$dayMap = [
    0 => "Sunday", 1 => "Monday", 2 => "Tuesday",
    3 => "Wednesday", 4 => "Thursday", 5 => "Friday", 6 => "Saturday"
];

$sql    = "SELECT shift_name, day_shifts, start_time, end_time, hours FROM working_hours";
$result = $conn->query($sql);
if ($result->num_rows > 0) {
    while ($row = $result->fetch_assoc()) {
        $shiftName = $row['shift_name'];
        $shifts[]  = $shiftName;
        $shiftHours[$shiftName] = (float)$row['hours'];
        $shiftDays[$shiftName]  = $dayMap[(int)$row['day_shifts']];
        $shiftTimes[$shiftName] = [
            'start' => $row['start_time'],
            'end'   => $row['end_time'],
            'hours' => (float)$row['hours']
        ];
    }
}

$intervalCache = [];
function generateTimeIntervals($startTime, $endTime) {
    global $intervalCache;
    $cacheKey = $startTime . '-' . $endTime;
    if (isset($intervalCache[$cacheKey])) return $intervalCache[$cacheKey];
    $intervals = [];
    $current   = new DateTime($startTime);
    $end       = new DateTime($endTime);
    $intervalStart = $current->format('H:i');
    $current->add(new DateInterval('PT30M'));
    while ($current <= $end) {
        $intervalEnd = $current->format('H:i');
        $intervals[] = ['start' => $intervalStart, 'end' => $intervalEnd,
                        'minutes' => (strtotime($intervalEnd) - strtotime($intervalStart)) / 60];
        $intervalStart = $intervalEnd;
        $current->add(new DateInterval('PT30M'));
    }
    if ($intervalStart !== $end->format('H:i')) {
        $intervals[] = ['start' => $intervalStart, 'end' => $end->format('H:i'),
                        'minutes' => (strtotime($end->format('H:i')) - strtotime($intervalStart)) / 60];
    }
    $intervalCache[$cacheKey] = $intervals;
    return $intervals;
}

function generateCalendar($month, $year, $shifts, $shiftDays, $shiftTimes) {
    $calendar      = [];
    $daysInMonth   = cal_days_in_month(CAL_GREGORIAN, $month, $year);
    $validWeekdays = array_unique(array_values($shiftDays));
    $today         = new DateTime();
    $currentYear   = (int)$today->format('Y');
    $currentMonth  = (int)$today->format('m');
    $currentDay    = (int)$today->format('d');
    $startDay      = ($year == $currentYear && $month == $currentMonth) ? $currentDay : 1;

    for ($day = $startDay; $day <= $daysInMonth; $day++) {
        $date      = sprintf("%04d-%02d-%02d", $year, $month, $day);
        $timestamp = strtotime($date);
        $dayOfWeek = date("l", $timestamp);

        if (in_array($dayOfWeek, $validWeekdays)) {
            $dayShifts = [];
            foreach ($shifts as $shift) {
                if ($shiftDays[$shift] === $dayOfWeek) $dayShifts[] = $shift;
            }
            usort($dayShifts, function ($a, $b) use ($shiftTimes) {
                return strtotime($shiftTimes[$a]['start']) <=> strtotime($shiftTimes[$b]['start']);
            });

            foreach ($dayShifts as $shift) {
                $intervals    = generateTimeIntervals($shiftTimes[$shift]['start'], $shiftTimes[$shift]['end']);
                $totalMinutes = array_sum(array_column($intervals, 'minutes'));
                $calendar[]   = [
                    "date" => $date, "day" => $day, "dayOfWeek" => $dayOfWeek, "month" => $month,
                    "shift" => $shift, "start_time" => $shiftTimes[$shift]['start'],
                    "end_time" => $shiftTimes[$shift]['end'], "hours" => $shiftTimes[$shift]['hours'],
                    "intervals" => $intervals, "total_intervals" => count($intervals),
                    "total_minutes" => $totalMinutes
                ];
            }
        }
    }
    return $calendar;
}

$calendarDays = [];
foreach ($monthsToShow as $m) {
    $calendarDays = array_merge($calendarDays, generateCalendar($m['month'], $m['year'], $shifts, $shiftDays, $shiftTimes));
}

$totalWidth   = 0;
$dayPositions = [];
$dayWidths    = [];
$dayMinutes   = [];
foreach ($calendarDays as $day) {
    $dayWidth = count($day['intervals']) * 40;
    $key      = $day['date'] . '-' . $day['shift'];
    $dayPositions[$key] = $totalWidth;
    $dayWidths[$key]    = $dayWidth;
    $dayMinutes[$key]   = $day['total_minutes'];
    $totalWidth        += $dayWidth;
}

$taskNames    = [];
$machineQuery = mysqli_query($conn, "SELECT id, resource_code FROM station_detail_table WHERE machine_type = 1 AND hide = 0");
while ($row = mysqli_fetch_assoc($machineQuery)) {
    $taskNames[$row['id']] = $row['resource_code'];
}

// FIX: active-breakdown lookup now reads vac_machine_breakdown_log (the
// shared source of truth — see vac_scheduler_lib.php) instead of the
// separate machine_breakdown table, so this admin view and the tablet
// dashboard can never disagree about which machines are down.
$activeBreakdowns = [];
$breakdownQuery = "
    SELECT machine_id, breakdown_reason FROM vac_machine_breakdown_log b1
    WHERE status = 'active' AND created_at = (
        SELECT MAX(created_at) FROM vac_machine_breakdown_log b2 WHERE b2.machine_id = b1.machine_id
    )
";
$breakdownResult = mysqli_query($conn, $breakdownQuery);
while ($breakdown = mysqli_fetch_assoc($breakdownResult)) {
    $activeBreakdowns[$breakdown['machine_id']] = $breakdown['breakdown_reason'];
}

$colorPalette = [
    '#e6f5f5','#f5e6f5','#e6ffe6','#fff2e6','#f0e6ff',
    '#e6ffff','#ffe6f2','#f5f5e6','#e6f5f5','#f5e6ff',
    '#e6ffec','#fff0e6','#e6f0ff','#ffe6ff','#e6ffe6',
    '#f5e6e6','#e6e6f5','#f5f5e6','#e6f5f5','#f5e6f5'
];
$machineColors = [];
$colorIndex    = 0;
foreach ($taskNames as $machineId => $taskName) {
    $machineColors[$machineId] = $colorPalette[$colorIndex % count($colorPalette)];
    $colorIndex++;
}
?>

<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
<style>
    :root {
        --primary-color: #3498db;
        --secondary-color: #2c3e50;
        --accent-color: #e74c3c;
        --light-bg: #f8f9fa;
        --dark-bg: #343a40;
        --success-color: #2ecc71;
        --warning-color: #f39c12;
        --danger-color: #e74c3c;
        --info-color: #3498db;
        --current-time-color: #e74c3c;
        --time-marker-color: #fff3cd;
        --shift-highlight: #d4edda;
        --time-interval-width: 40px;
        --task-bar-height: 130px;
        --grid-line-color: rgba(0,0,0,0.1);
        --breakdown-color: #ff4444;
    }
	html {
    font-size: 14px;
}
    .gantt-container { position:relative; width:100%; overflow-x:auto; margin-top:20px; display:flex; background-color:white; box-shadow:0 2px 10px rgba(0,0,0,0.1); border-radius:8px; }
    .gantt-labels { position:sticky; left:0; top:0; width:270px; background:#f9f9f9; padding:15px; border-right:1px solid #ddd; z-index:20; height:fit-content; flex-shrink:0; }
    .gantt-scrollable-content { flex:1; min-width:0; overflow-x:auto; position:relative; }
    .gantt-grid { display:inline-block; min-width:<?php echo $totalWidth; ?>px; position:relative; }
    .gantt-header { display:inline-flex; background:#f5f5f5; border-bottom:1px solid #ddd; position:sticky; top:0; z-index:15; }
    .gantt-day { display:inline-flex; flex-direction:column; text-align:center; background-color:#fff; float:none; vertical-align:top; position:relative; }
    .gantt-day strong { font-size:12px; color:#333; background:#f3f3f3; padding:3px; border-radius:3px; margin-bottom:5px; }
    .gantt-time-intervals { display:flex; flex-wrap:nowrap; justify-content:flex-start; width:100%; background-color:#f8f9fa; border-top:1px solid #dee2e6; }
    .gantt-time-interval { flex:0 0 var(--time-interval-width); text-align:center; font-size:10px; color:#555; border-right:1px solid var(--grid-line-color); height:30px; position:relative; }
    .gantt-time-interval-label { position:absolute; font-size: clamp(8px, 0.7vw, 11px); transform:rotate(-45deg); transform-origin:left center; white-space:nowrap; left:0%; bottom:-15px; color:#000; }
    .gantt-row { display:block; border-bottom:1px solid #000; min-height:var(--task-bar-height); position:relative; white-space:nowrap; background-image:linear-gradient(to right,var(--grid-line-color) 1px,transparent 1px); background-size:var(--time-interval-width) 1px; background-position:left center; }
    .gantt-task { position:absolute; height:100%; top:0; background:#3498db; color:white; text-align:center; border-radius:5px; padding:5px; line-height:1.2; font-size:12px; cursor:grab; transition:background-color 0.3s ease; box-shadow:1px 1px 3px rgba(0,0,0,0.2); z-index:1; overflow:hidden; box-sizing:border-box; border-right:3px solid rgba(255,255,255,0.5); }
    .gantt-task .task-content { padding:1px; font-size: clamp(10px, 0.8vw, 13px); height:calc(100% - 20px); overflow:hidden; }
    .gantt-task .task-hours { position:absolute; bottom:0; left:0; right:0; background:rgba(0,0,0,0.2); text-align:center; font-size:9px; padding:1px 0; border-radius:0 0 4px 4px; }
    .no-tasks { color:#999; font-style:italic; padding:10px; text-align:center; width:100%; }
    .breakdown-task { background-color:var(--breakdown-color) !important; border-left:3px solid #cc0000 !important; border-right:3px solid #cc0000 !important; color:white !important; }
    .breakdown-affected { background:repeating-linear-gradient(45deg,#ff6b6b,#ff6b6b 10px,#ff8e8e 10px,#ff8e8e 20px) !important; border:2px dashed #ff0000 !important; }
    .machine-with-breakdown { background-color:#ffe6e6 !important; border-left:4px solid var(--breakdown-color) !important; }
    .breakdown-indicator { position:absolute; top:5px; right:5px; width:12px; height:12px; background-color:var(--breakdown-color); border-radius:50%; animation:pulse 1.5s infinite; }
    @keyframes pulse { 0%{opacity:1} 50%{opacity:0.5} 100%{opacity:1} }
    .dot-indicator { position:absolute; top:4px; right:4px; width:40px; height:40px; border-radius:50%; border:3px solid black; z-index:5; }
    .green-dot-indicator { background-color:#00cc66; }
    .red-dot-indicator   { background-color:#ff3333; }
    .blue-dot-indicator  { background-color:#3399ff; }
    .hour-indicator { position:absolute; bottom:0; left:0; right:0; font-size:0.65rem; text-align:center; background:rgba(0,0,0,0.15); padding:1px 0; border-radius:0 0 4px 4px; }
    .machine-list { display:flex; flex-direction:column; gap:10px; }
    .controls { background:white; padding:15px; border-radius:8px; margin-bottom:20px; box-shadow:0 2px 5px rgba(0,0,0,0.1); }
    .machine-section { margin-bottom:15px; }
    .card { border-radius:8px; box-shadow:0 2px 5px rgba(0,0,0,0.1); transition:transform 0.2s; }
    .card:hover { transform:translateY(-2px); }
    .card-header { font-weight:500; padding:8px 12px; }
    .form-control { font-size:0.85rem; padding:0.25rem 0.5rem; }
    .gantt-task.dragging { opacity:0.5; background-color:#f39c12; }
    .gantt-row.drop-target { outline:2px dashed #007bff; background-color:#e6f7ff; }
    .gantt-day.today { background-color:#fff3cd; box-shadow:0 0 0 2px #ffc107; }
    .gantt-day.today strong { background-color:#ffc107; color:#000; font-weight:bold; }
    .gantt-task.filter-highlight {
    outline: 3px solid yellow;
    box-shadow: 0 0 15px yellow;
    z-index: 10;
}    .gantt-task.drag-highlight {
    outline: 2px dashed #007bff;
}
    .gantt-task.late-task    { background-color:#ff6b6b !important; border-left:3px solid #ff0000 !important; border-right:3px solid #ff0000 !important; }
    .gantt-task.on-time-task { background-color:#78c679 !important; border-left:3px solid #2ecc71 !important; border-right:3px solid #2ecc71 !important; }
    .gantt-task.break-task   { background-color:#999 !important; border-left:3px dashed #fff !important; border-right:3px dashed #fff !important; color:#fff !important; }
    .modal-dialog { max-width:1200px; }
    .modal-content { border-radius:10px; border:none; box-shadow:0 5px 20px rgba(0,0,0,0.2); }
    .modal-header { background-color:var(--secondary-color); color:white; border-radius:10px 10px 0 0; padding:15px 20px; }
    .modal-title  { font-weight:600; }
    .modal-body   { padding:20px; }
    .modal-footer { border-top:1px solid #e9ecef; padding:15px 20px; }
    .custom-scroll { max-height:600px; overflow-y:auto; }
    /* Work order modal table */
    .form-check-input { width:24px !important; height:24px !important; cursor:pointer; border:2px solid #6c757d; border-radius:4px; }
    .form-check-input:checked { background-color:#0d6efd; border-color:#0d6efd; }
    #workOrderTableBody tr { cursor:pointer; }
    #workOrderTableBody tr:hover { background-color:#f8f9fa; }
    .sortable { cursor:pointer; user-select:none; position:relative; padding-right:25px !important; }
    .sortable:hover { background-color:#e9ecef !important; }
    .sortable::after  { content:'⇅'; position:absolute; right:8px; opacity:0.3; font-size:14px; }
    .sortable.asc::after  { content:'↑'; opacity:1; color:#0d6efd; }
    .sortable.desc::after { content:'↓'; opacity:1; color:#0d6efd; }
    .setting-instruction { max-width:300px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
    .materials-column { max-width:250px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; cursor:help; }
    .no-materials { color:#999; font-style:italic; font-size:11px; }
    .materials-available { color:#28a745; }
    /* Gantt rows loading state */
    #gantt-rows-loading { padding:40px; text-align:center; color:#666; }
</style>

<div class="container-fluid">
    <div class="controls">

        <div class="row align-items-center mb-3">

    <!-- LEFT SIDE -->
    <div class="col-md-4">
        <h3 class="mb-0">
            <i class="fas fa-calendar-day me-2"></i>VAC Gantt Chart
        </h3>
        <h5 class="text-muted"><?php echo date('l, F j, Y'); ?></h5>
    </div>

    <!-- RIGHT SIDE -->
    <div class="col-md-8">

        <!-- FILTER ROW -->
        <div class="row g-2 mb-2">
            <div class="col-md-3">
                <input type="text" id="filter_part" class="form-control" placeholder="Part Number">
            </div>
            <div class="col-md-3">
                <input type="text" id="filter_wo" class="form-control" placeholder="Work Order">
            </div>
            <div class="col-md-3">
                <input type="text" id="filter_setting" class="form-control" placeholder="Setting Instruction">
            </div>
            <div class="col-md-3">
                <button class="btn btn-success w-100" onclick="applyFilters()">
                    Apply
                </button>
            </div>
        </div>

        <!-- ACTION BUTTONS -->
        <div class="d-flex justify-content-end flex-wrap gap-2">
            <button type="button" class="btn btn-primary show-work-order-button" data-bs-toggle="modal" data-bs-target="#workOrderModal">
                <i class="fas fa-list-check me-1"></i> Work Orders
            </button>

            <button class="btn btn-primary" onclick="loadGanttRows()">
                <i class="fas fa-sync-alt me-1"></i> Refresh
            </button>

            <button class="btn btn-warning" id="addBreakBtn">
                <i class="fas fa-clock me-1"></i> Add Break
            </button>

            <button class="btn btn-danger d-none" id="startBreakdownBtn">
                <i class="fas fa-exclamation-triangle me-1"></i> Start Breakdown
            </button>

            <button class="btn btn-success d-none" id="stopBreakdownBtn">
                <i class="fas fa-check me-1"></i> Stop Breakdown
            </button>
        </div>

    </div>

</div>
    </div>

    <div class="gantt-container">
        <!-- ── Sticky machine labels (unchanged) ── -->
        <div class="gantt-labels">
            <h5><i class="fas fa-server me-2"></i>Machine Detail</h5>
            <div style="margin-bottom:20px;"></div>
            <div class="machine-list">
                <?php
                $renderedMachines = [];
                foreach ($taskNames as $machineId => $taskName):
                    if (!in_array($machineId, $renderedMachines)):
                        $hasBreakdown     = isset($activeBreakdowns[$machineId]);
                        $renderedMachines[] = $machineId;
                ?>
                    <div class="machine-section mb-0" style="width:200px;" data-machine-id="<?php echo $machineId; ?>">
                        <div class="row" style="margin-bottom:1px; height:120px;">
                            <div class="card <?php echo $hasBreakdown ? 'machine-with-breakdown' : ''; ?>"
                                 style="background-color:#e6f2ff; margin-left:12px; position:relative;">
                                <?php if ($hasBreakdown): ?>
                                    <div class="breakdown-indicator" title="Machine Breakdown Active"></div>
                                <?php endif; ?>
                                <div style="display:flex; justify-content:center; align-items:center; height:100%; font-weight:bold;">
                                    <?php echo $taskName; ?>
                                    <?php if ($hasBreakdown): ?>
                                        <br/><small style="color:#ff0000; font-size:10px;">BREAKDOWN</small>
                                    <?php endif; ?>
                                </div>
                            </div>
                        </div>
                    </div>
                <?php
                    endif;
                endforeach;
                ?>
            </div>
        </div>

        <!-- ── Scrollable Gantt content ── -->
        <div class="gantt-scrollable-content">
            <div class="gantt-grid">

                <!-- Time header (unchanged PHP) -->
                <div class="gantt-header">
                    <?php foreach ($calendarDays as $day):
                        $dayWidth = count($day['intervals']) * 40;
                        $isToday  = $day['date'] == date('Y-m-d');
                    ?>
                        <div class="gantt-day <?php echo $isToday ? 'today' : ''; ?>"
                             data-date="<?php echo $day['date']; ?>"
                             data-shift="<?php echo $day['shift']; ?>"
                             style="min-width:<?php echo $dayWidth; ?>px;">
                            <div><strong><?php echo $day['date'] . ' (' . $day['shift'] . ')'; ?></strong></div>
                            <div class="gantt-time-intervals">
                                <?php foreach ($day['intervals'] as $interval): ?>
                                    <div class="gantt-time-interval"
                                         data-interval="<?php echo $interval['start'] . '-' . $interval['end']; ?>">
                                        <div class="gantt-time-interval-label"><?php echo $interval['start']; ?></div>
                                    </div>
                                <?php endforeach; ?>
                            </div>
                        </div>
                    <?php endforeach; ?>
                </div>

                <!-- ── TASK ROWS: loaded via AJAX ── -->
                <div id="gantt-rows-container">
                    <div id="gantt-rows-loading">
                        <div class="spinner-border text-primary" role="status"></div>
                        <p class="mt-2">Loading schedule...</p>
                    </div>
                </div>

            </div><!-- /.gantt-grid -->
        </div><!-- /.gantt-scrollable-content -->
    </div><!-- /.gantt-container -->
</div><!-- /.container-fluid -->


<!-- ══════════════════════════════════════════════════════════════════
     MODALS (all unchanged from your original)
     ══════════════════════════════════════════════════════════════════ -->

<!-- Work Order Detail Modal -->
<div class="modal fade" id="workOrderDetailModal" tabindex="-1" aria-hidden="true">
    <div class="modal-dialog modal-lg">
        <div class="modal-content">
            <div class="modal-header bg-primary text-white">
                <h5 class="modal-title"><i class="fas fa-info-circle me-2"></i>Work Order Details</h5>
                <button type="button" class="close" data-dismiss="modal"><span>&times;</span></button>
            </div>
            <div class="modal-body">
                <div id="detailLoadingSpinner" class="text-center py-5">
                    <div class="spinner-border text-primary" role="status"></div>
                    <p class="mt-2">Loading details...</p>
                </div>
                <div id="workOrderDetailContent" style="display:none;">
                    <div class="card mb-3">
                        <div class="card-header bg-light"><h6 class="mb-0"><i class="fas fa-clipboard-list me-2"></i>Order Information</h6></div>
                        <div class="card-body">
                            <div class="row">
                                <div class="col-md-6">
                                    <p><strong>Customer Order:</strong> <span id="detail_customer_order"></span></p>
                                    <p><strong>Work Order Name:</strong> <span id="detail_wo_name"></span></p>
                                    <p><strong>Status:</strong> <span id="detail_status" class="badge"></span></p>
                                </div>
                                <div class="col-md-6">
                                    <p><strong>Final Part:</strong> <span id="detail_final_part"></span></p>
                                    <p><strong>Customer code:</strong> <span id="detail_customer_code"></span></p>
                                    <p><strong>RefSalescode:</strong> <span id="detail_RefSalesCode"></span></p>
                                </div>
                            </div>
                        </div>
                    </div>
                    <div class="card mb-3">
                        <div class="card-header bg-light"><h6 class="mb-0"><i class="fas fa-cog me-2"></i>Part Information</h6></div>
                        <div class="card-body">
                            <div class="row">
                                <div class="col-md-6">
                                    <p><strong>Part/Set Name:</strong> <span id="detail_part_name"></span></p>
                                    <p><strong>Desc:</strong> <span id="detail_desc"></span></p>
                                    <p><strong>Quantity:</strong> <span id="detail_quantity"></span></p>
									<p><strong>Produced (OK) Qty:</strong> <span id="detail_produced_qty"></span></p>
									
                                </div>
                                <div class="col-md-6">
									<p><strong>Setup Hours:</strong> <span id="detail_setup_hours"></span></p>
									<p><strong>Total Hours:</strong> <span id="detail_total_hours"></span></p>
									<p><strong>Due Date:</strong> <span id="detail_due_date"></span></p>
									
									<p class="hide"><strong>Live UPH:</strong> <span id="detail_live_uph"></span></p>
								</div>
                            </div>
                        </div>
                    </div>
                    <div class="card mb-3">
                        <div class="card-header bg-light"><h6 class="mb-0"><i class="fas fa-cubes me-2"></i>Raw Materials</h6></div>
                        <div class="card-body">
                            <div id="detail_bought_in_materials" class="alert alert-info mb-0">
                                <i class="fas fa-box me-2"></i>
                                <span id="materials_list">Loading...</span>
                            </div>
                        </div>
                    </div>
                    <div class="card mb-3">
                        <div class="card-header bg-light"><h6 class="mb-0"><i class="fas fa-wrench me-2"></i>Production Details</h6></div>
                        <div class="card-body">
                            <p><strong>Setting Instruction:</strong> <span id="detail_setting_instruction"></span></p>
                            <p><strong>Description:</strong> <span id="detail_route_desc"></span></p>
                            <div id="breakdown_info" style="display:none;" class="alert alert-danger">
                                <strong><i class="fas fa-exclamation-triangle me-2"></i>Breakdown Impact:</strong>
                                <span id="detail_breakdown_hours"></span> hours delay
                            </div>
                        </div>
                    </div>
                    <div class="card mb-3">
                        <div class="card-header bg-light"><h6 class="mb-0"><i class="fas fa-edit me-2"></i>Notes / Remarks</h6></div>
                        <div class="card-body">
                            <textarea id="task_note" class="form-control" rows="4" placeholder="Enter notes here..."></textarea>
                            <input type="hidden" id="note_task_id">
                            <input type="hidden" id="note_work_order_id">
                            <input type="hidden" id="note_part_id">
                            <button class="btn btn-success mt-2" onclick="saveTaskNote()">Save Note</button>
                        </div>
                    </div>
                </div>
                <div id="detailErrorMessage" class="alert alert-danger d-none" role="alert">
                    Failed to load work order details. Please try again.
                </div>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-secondary" data-dismiss="modal"><i class="fas fa-times me-2"></i>Close</button>
                <button type="button" class="btn btn-warning hide" id="editWorkOrderBtn"><i class="fas fa-edit me-2"></i>Edit</button>
                <button type="button" class="btn btn-info" id="splitWorkOrderBtn" style="display:none;"><i class="fas fa-cut me-2"></i>Split Work Order</button>
                <button type="button" class="btn btn-danger" id="deleteWorkOrderBtn"><i class="fas fa-trash me-2"></i>Delete</button>
            </div>
        </div>
    </div>
</div>

<!-- Edit Work Order Modal -->
<div class="modal fade" id="editWorkOrderModal" tabindex="-1" aria-hidden="true">
    <div class="modal-dialog modal-lg">
        <div class="modal-content">
            <div class="modal-header bg-warning">
                <h5 class="modal-title"><i class="fas fa-edit me-2"></i>Edit Work Order</h5>
                <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
            </div>
            <div class="modal-body">
                <form id="editWorkOrderForm">
                    <input type="hidden" id="edit_task_id" name="task_id">
                    <div class="row mb-3">
                        <div class="col-md-6">
                            <label for="edit_priority" class="form-label">Priority</label>
                            <input type="number" class="form-control" id="edit_priority" name="priority" min="1">
                        </div>
                        <div class="col-md-6">
                            <label for="edit_machine" class="form-label">Machine</label>
                            <select class="form-control" id="edit_machine" name="machine_id">
                                <?php foreach ($taskNames as $machineId => $taskName): ?>
                                    <option value="<?php echo $machineId; ?>"><?php echo $taskName; ?></option>
                                <?php endforeach; ?>
                            </select>
                        </div>
                    </div>
                    <div class="row mb-3">
                        <div class="col-md-6">
                            <label for="edit_setup_hours" class="form-label">Setup Hours</label>
                            <input type="number" class="form-control" id="edit_setup_hours" name="setup_hours" step="0.5" min="0">
                        </div>
                        <div class="col-md-6">
                            <label for="edit_total_hours" class="form-label">Total Hours</label>
                            <input type="number" class="form-control" id="edit_total_hours" name="total_hours" step="0.5" min="0">
                        </div>
                    </div>
                    <div class="mb-3">
                        <label for="edit_setting_instruction" class="form-label">Setting Instruction</label>
                        <textarea class="form-control" id="edit_setting_instruction" name="setting_instruction" rows="3"></textarea>
                    </div>
                    <div class="row mb-3">
                        <div class="col-md-6">
                            <label for="edit_start_date" class="form-label">Start Date</label>
                            <input type="date" class="form-control" id="edit_start_date" name="start_date">
                        </div>
                        <div class="col-md-6">
                            <label for="edit_quantity" class="form-label">Quantity</label>
                            <input type="number" class="form-control" id="edit_quantity" name="quantity" min="1">
                        </div>
                    </div>
                </form>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
                <button type="button" class="btn btn-primary" id="saveEditBtn"><i class="fas fa-save me-2"></i>Save Changes</button>
            </div>
        </div>
    </div>
</div>

<!-- Split Work Order Modal -->
<div class="modal fade" id="splitWorkOrderModal" tabindex="-1" aria-hidden="true">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header bg-info text-white">
                <h5 class="modal-title"><i class="fas fa-cut me-2"></i>Split Work Order</h5>
                <button type="button" class="close" data-dismiss="modal"><span>&times;</span></button>
            </div>
            <div class="modal-body">
                <div class="alert alert-info"><i class="fas fa-info-circle me-2"></i>Split this work order into two based on quantity.</div>
                <form id="splitWorkOrderForm">
                    <input type="hidden" id="split_task_id" name="task_id">
                    <div class="mb-3">
                        <label class="form-label"><strong>Current Quantity:</strong></label>
                        <p id="split_current_quantity" class="form-control-plaintext">-</p>
                    </div>
                    <div class="mb-3">
                        <label for="split_quantity" class="form-label">Split Quantity <span class="text-danger">*</span></label>
                        <input type="number" class="form-control" id="split_quantity" name="split_quantity" min="1" step="1" required>
                        <small class="form-text text-muted">Enter the quantity for the new work order</small>
                    </div>
                    <div id="split_preview" style="display:none;" class="mt-3">
                        <h6 class="border-bottom pb-2">Preview:</h6>
                        <div class="row">
                            <div class="col-md-6">
                                <div class="card bg-light"><div class="card-body">
                                    <h6 class="card-title text-primary">Original WO</h6>
                                    <p class="mb-1"><strong>Quantity:</strong> <span id="preview_remaining_qty">-</span></p>
                                    <p class="mb-0"><strong>Hours:</strong> <span id="preview_remaining_hours">-</span></p>
                                </div></div>
                            </div>
                            <div class="col-md-6">
                                <div class="card bg-light"><div class="card-body">
                                    <h6 class="card-title text-success">New WO</h6>
                                    <p class="mb-1"><strong>Quantity:</strong> <span id="preview_split_qty">-</span></p>
                                    <p class="mb-0"><strong>Hours:</strong> <span id="preview_split_hours">-</span></p>
                                </div></div>
                            </div>
                        </div>
                    </div>
                    <div id="split_error" class="alert alert-danger mt-3" style="display:none;"></div>
                </form>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
                <button type="button" class="btn btn-info" id="confirmSplitBtn"><i class="fas fa-check me-2"></i>Confirm Split</button>
            </div>
        </div>
    </div>
</div>

<!-- Start Breakdown Modal -->
<div class="modal fade" id="startBreakdownModal" tabindex="-1" aria-hidden="true">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title">Start Machine Breakdown</h5>
                <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
            </div>
            <div class="modal-body">
                <form id="startBreakdownForm">
                    <div class="mb-3">
                        <label for="startBreakdownMachine" class="form-label">Machine</label>
                        <select class="form-select" id="startBreakdownMachine" required>
                            <option value="">Select Machine</option>
                            <?php foreach ($taskNames as $machineId => $taskName): ?>
                                <option value="<?php echo $machineId; ?>"><?php echo $taskName; ?></option>
                            <?php endforeach; ?>
                        </select>
                    </div>
                    <div class="mb-3">
                        <label class="form-label">Breakdown Reason</label>
                        <?php echo Keycode::getKeycodeListValue("breakdown_reason","","100%","Please Select","id","code","breakdown_reason","","form-select",false,"required"); ?>
                    </div>
                </form>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
                <button type="button" class="btn btn-danger" id="confirmStartBreakdownBtn">Start Breakdown</button>
            </div>
        </div>
    </div>
</div>

<!-- Stop Breakdown Modal -->
<div class="modal fade" id="stopBreakdownModal" tabindex="-1" aria-hidden="true">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title">Stop Machine Breakdown</h5>
                <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
            </div>
            <div class="modal-body">
                <form id="stopBreakdownForm">
                    <div class="mb-3">
                        <label for="stopBreakdownMachine" class="form-label">Machine</label>
                        <select class="form-select" id="stopBreakdownMachine" required>
                            <option value="">Select Machine</option>
                            <?php
                            $abResult = mysqli_query($conn,
                                "SELECT DISTINCT mb.machine_id, sd.resource_code
                                 FROM machine_breakdown mb
                                 JOIN station_detail_table sd ON mb.machine_id = sd.id
                                 WHERE mb.is_active = 1");
                            while ($row = mysqli_fetch_assoc($abResult)): ?>
                                <option value="<?php echo $row['machine_id']; ?>"><?php echo $row['resource_code']; ?> (Active Breakdown)</option>
                            <?php endwhile; ?>
                        </select>
                    </div>
                    <div class="alert alert-warning"><i class="fas fa-exclamation-triangle"></i> This will stop the breakdown and recalculate affected work orders.</div>
                </form>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
                <button type="button" class="btn btn-success" id="confirmStopBreakdownBtn">Stop Breakdown</button>
            </div>
        </div>
    </div>
</div>

<!-- Add Break Modal -->
<div class="modal fade" id="breakModal" tabindex="-1" aria-hidden="true">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title">Add Machine Break</h5>
                <button type="button" class="close" data-dismiss="modal"><span>&times;</span></button>
            </div>
            <div class="modal-body">
                <form id="breakForm">
                    <div class="mb-3">
                        <label for="breakMachine" class="form-label">Machine</label>
                        <select class="form-select" id="breakMachine" required>
                            <option value="">Select Machine</option>
                            <?php foreach ($taskNames as $machineId => $taskName): ?>
                                <option value="<?php echo $machineId; ?>"><?php echo $taskName; ?></option>
                            <?php endforeach; ?>
                        </select>
                    </div>
                    <div class="mb-3">
                        <label for="breakDuration" class="form-label">Duration (hours)</label>
                        <input type="number" class="form-control" id="breakDuration" min="1" max="10" step="1" required>
                        <div class="form-text">Minimum 1 hour, Maximum 10 hours</div>
                    </div>
                    <div class="mb-3">
                        <label for="breakReason" class="form-label">Reason</label>
                        <textarea class="form-control" id="breakReason" rows="2"></textarea>
                    </div>
                </form>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
                <button type="button" class="btn btn-primary" id="saveBreakBtn">Save Break</button>
            </div>
        </div>
    </div>
</div>

<!-- Work Orders List Modal -->
<div class="modal fade" id="workOrderModal" tabindex="-1" aria-hidden="true">
    <div class="modal-dialog modal-xl">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title">Work Orders</h5>
                <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
            </div>
            <div class="modal-body custom-scroll">
                <div id="loadingSpinner" class="text-center py-5">
                    <div class="spinner-border text-primary" role="status"></div>
                    <p class="mt-2">Loading work orders...</p>
                </div>
                <div id="workOrderContent" style="display:none;">
                    <form id="workOrderForm">
                        <table class="table table-striped" id="workOrderTable">
                            <thead>
                                <tr>
                                    <th class="sortable" data-column="work_order_name" data-type="string">WO Number</th>
                                    <th class="sortable" data-column="product_name" data-type="string">Part Number</th>
                                    <th class="sortable" data-column="product_description" data-type="string">Part Description</th>
                                    <th class="sortable" data-column="end_date" data-type="date">Due Date</th>
                                    <th class="sortable" data-column="quantity" data-type="number">Qty</th>
                                    <th class="sortable" data-column="total_hours" data-type="number">Std Hours</th>
                                    <th class="sortable" data-column="setting_instruction" data-type="string">Setting Instruction</th>
                                    <th class="sortable" data-column="bought_in_materials" data-type="string">Raw Materials</th>
                                    <th>Machine</th>
                                    <th>Select</th>
                                </tr>
                            </thead>
                            <tbody id="workOrderTableBody"></tbody>
                        </table>
                    </form>
                </div>
                <div id="errorMessage" class="alert alert-danger d-none" role="alert">Failed to load work orders.</div>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
                <button type="button" id="submitWorkOrdersBtn" class="btn btn-primary" onclick="showSelectedWorkOrders()" disabled>
                    <span class="btn-text">Show Selected</span>
                    <span id="spinner" class="spinner-border spinner-border-sm ms-2 d-none" role="status"></span>
                </button>
            </div>
        </div>
    </div>
</div>


<!-- ══════════════════════════════════════════════════════════════════
     SCRIPTS  —  single unified block at the very bottom
     ══════════════════════════════════════════════════════════════════ -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script>
$('body').addClass('sidebar-collapse');

// ─────────────────────────────────────────────────────────────────────────────
// 1.  LOAD GANTT ROWS VIA AJAX
// ─────────────────────────────────────────────────────────────────────────────
function loadGanttRows() {
    $('#gantt-rows-container').html(
        '<div id="gantt-rows-loading" style="padding:40px;text-align:center;color:#666;">' +
        '<div class="spinner-border text-primary" role="status"></div>' +
        '<p class="mt-2">Loading schedule...</p></div>'
    );

    $.ajax({
        url: site_url + '/modules/machines_management/index.php?page=ajax_actions&action=get_gantt_rows',
        method: 'GET',
        dataType: 'json',

        success: function(response) {
            console.log('AJAX success:', response); // ADD THIS
            if (response.success) {
                $('#gantt-rows-container').html(response.html);
                setTimeout(() => {
                    document.querySelectorAll('.gantt-task').forEach(t => {
                        t.classList.remove('drag-highlight', 'filter-highlight');
                    });
                    if (
                        document.getElementById('filter_part').value ||
                        document.getElementById('filter_wo').value ||
                        document.getElementById('filter_setting').value
                    ) {
                        applyFilters();
                    }
                }, 100);
            } else {
                console.error('Response not success:', response); // ADD THIS
                $('#gantt-rows-container').html(
                    '<div class="alert alert-danger m-3">Failed to load schedule rows: ' + (response.message || 'Unknown error') + '</div>'
                );
            }
        },

        error: function(xhr, status, error) {
            // ADD ALL OF THIS
            console.error('AJAX error:', status, error);
            console.error('Response text:', xhr.responseText);
            console.error('Status code:', xhr.status);
            $('#gantt-rows-container').html(
                '<div class="alert alert-danger m-3">Error loading schedule rows.<br>' +
                'Status: ' + xhr.status + '<br>' +
                'Error: ' + error + '<br>' +
                '<pre>' + xhr.responseText.substring(0, 500) + '</pre>' +
                '</div>'
            );
        }
    });
}
// Auto-load on page ready
$(document).ready(function () {
    loadGanttRows();
});


// ─────────────────────────────────────────────────────────────────────────────
// 2.  WORK ORDER DETAIL MODAL  (delegated click — works on AJAX rows)
// ─────────────────────────────────────────────────────────────────────────────
let currentTaskDetails = null;

// Delegated: listens on document, matches any .gantt-task that isn't a break
$(document).on('click', '.gantt-task:not(.break-task):not(.dragging)', function () {
    loadWorkOrderDetails(
        $(this).data('task-id'),
        $(this).data('work-order-id'),
        $(this).data('part-id'),
        $(this).data('current-machine')
    );
});

function loadWorkOrderDetails(taskId, workOrderId, partId, machineId) {
    const modal = new bootstrap.Modal(document.getElementById('workOrderDetailModal'));
    modal.show();
    $('#detailLoadingSpinner').show();
    $('#workOrderDetailContent').hide();
    $('#detailErrorMessage').addClass('d-none');

    $.ajax({
        url: site_url + '/modules/machines_management/index.php?page=ajax_actions&action=get_vac_task_details',
        method: 'POST',
        data: { task_id: taskId, work_order_id: workOrderId, part_id: partId, machine_id: machineId },
        dataType: 'json',
        success: function(response) {
            if (response.success) {
                currentTaskDetails = response.data;
                displayWorkOrderDetails(response.data);
                $('#detailLoadingSpinner').hide();
                $('#workOrderDetailContent').show();
            } else {
                $('#detailLoadingSpinner').hide();
                $('#detailErrorMessage').text(response.message || 'Failed to load details').removeClass('d-none');
            }
        },
        error: function() {
            $('#detailLoadingSpinner').hide();
            $('#detailErrorMessage').removeClass('d-none');
        }
    });
}

function displayWorkOrderDetails(data) {
    $('#detail_wo_no').text(data.work_order_no || '-');
    $('#detail_customer_order').text(data.customer_order_nos || '-');
    $('#detail_wo_name').text(data.work_order_name || '-');
    $('#detail_final_part').text(data.parent_part_number || '-');
    $('#detail_customer_code').text(data.customer_code || '-');
    $('#detail_RefSalesCode').text(data.RefSalesCode || '-');
    $('#task_note').val(data.task_note || '');
    $('#note_task_id').val(data.task_id);
    $('#note_work_order_id').val(data.work_order_id);
    $('#note_part_id').val(data.part_id);

    const statusBadge = $('#detail_status');
    if (data.is_late) {
        statusBadge.text('Late').removeClass().addClass('badge bg-danger');
    } else {
        statusBadge.text('On Time').removeClass().addClass('badge bg-success');
    }

    $('#detail_part_name').text(data.product_name || '-');
    $('#detail_quantity').text(data.quantity || '-');
    $('#detail_desc').text(data.manufacture_description || '-');
    $('#detail_setup_hours').text(data.setup_hours || '-');
    $('#detail_total_hours').text(data.total_hours || '-');
    $('#detail_due_date').text(data.end_date || '-');
	$('#detail_produced_qty').text(
    (data.produced_qty !== undefined && data.produced_qty !== null) ? data.produced_qty : '-'
);

const liveUph = data.live_uph;
const plannedUph = data.planned_uph;
let uphHtml = '-';
if (liveUph !== undefined && liveUph !== null) {
    if (plannedUph > 0) {
        const color = data.is_uph_green ? '#28a745' : '#dc3545';
        uphHtml = `<span style="color:${color}; font-weight:700;">${liveUph} / ${plannedUph}</span>`;
    } else {
        uphHtml = `<span style="color:#6c757d;">${liveUph}</span>`;
    }
}
$('#detail_live_uph').html(uphHtml);

    const materialsDiv = $('#detail_bought_in_materials');
    if (data.bought_in_materials && data.bought_in_materials !== 'None') {
        materialsDiv.removeClass('alert-info alert-warning').addClass('alert-success');
        $('#materials_list').html('<strong>' + data.bought_in_materials + '</strong>');
    } else {
        materialsDiv.removeClass('alert-info alert-success').addClass('alert-warning');
        $('#materials_list').html('<em>No bought-in materials required</em>');
    }

    $('#detail_setting_instruction').text(data.setting_instruction || '-');
    $('#detail_route_desc').text(data.route_desc || '-');

    if (data.is_breakdown_affected && data.breakdown_hours > 0) {
        $('#breakdown_info').show();
        $('#detail_breakdown_hours').text(data.breakdown_hours);
    } else {
        $('#breakdown_info').hide();
    }

    $('#detail_start_date').text(data.start_date || '-');
    $('#detail_start_time').text(data.start_time || '-');
    $('#detail_end_date').text(data.end_date || '-');
    $('#detail_shift').text(data.shift_name || '-');

    if (data.is_break == 1 || data.quantity <= 1) {
        $('#splitWorkOrderBtn').hide();
    } else {
        $('#splitWorkOrderBtn').show();
    }
}

// Edit
$('#editWorkOrderBtn').on('click', function () {
    if (!currentTaskDetails) return;
    $('#workOrderDetailModal').modal('hide');
    $('#edit_task_id').val(currentTaskDetails.task_id);
    $('#edit_priority').val(currentTaskDetails.priority);
    $('#edit_machine').val(currentTaskDetails.machine_id);
    $('#edit_setup_hours').val(currentTaskDetails.setup_hours);
    $('#edit_total_hours').val(currentTaskDetails.total_hours);
    $('#edit_setting_instruction').val(currentTaskDetails.setting_instruction);
    $('#edit_start_date').val(currentTaskDetails.start_date);
    $('#edit_quantity').val(currentTaskDetails.quantity);
    new bootstrap.Modal(document.getElementById('editWorkOrderModal')).show();
});

$('#saveEditBtn').on('click', function () {
    const $btn = $(this);
    $btn.prop('disabled', true).html('<span class="spinner-border spinner-border-sm me-2"></span>Saving...');
    $.ajax({
        url: site_url + '/modules/machines_management/index.php?page=ajax_actions&action=update_vac_task',
        method: 'POST',
        data: {
            task_id: $('#edit_task_id').val(), priority: $('#edit_priority').val(),
            machine_id: $('#edit_machine').val(), setup_hours: $('#edit_setup_hours').val(),
            total_hours: $('#edit_total_hours').val(), setting_instruction: $('#edit_setting_instruction').val(),
            start_date: $('#edit_start_date').val(), quantity: $('#edit_quantity').val()
        },
        dataType: 'json',
        success: function(response) {
            if (response.success) {
                alert('Work order updated successfully!');
                $('#editWorkOrderModal').modal('hide');
                loadGanttRows();
            } else {
                alert('Error: ' + (response.message || 'Failed to update'));
                $btn.prop('disabled', false).html('<i class="fas fa-save me-2"></i>Save Changes');
            }
        },
        error: function() {
            alert('Error updating work order');
            $btn.prop('disabled', false).html('<i class="fas fa-save me-2"></i>Save Changes');
        }
    });
});

// Delete
$('#deleteWorkOrderBtn').on('click', function () {
    if (!currentTaskDetails) return;
    if (!confirm('Are you sure you want to delete this work order? This cannot be undone.')) return;
    const $btn = $(this);
    $btn.prop('disabled', true).html('<span class="spinner-border spinner-border-sm me-2"></span>Deleting...');
    $.ajax({
        url: site_url + '/modules/machines_management/index.php?page=ajax_actions&action=delete_vac_task',
        method: 'POST',
        data: { task_id: currentTaskDetails.task_id, work_order_id: currentTaskDetails.work_order_id, part_id: currentTaskDetails.part_id },
        dataType: 'json',
        success: function(response) {
            if (response.success) {
                alert('Work order deleted successfully!');
                $('#workOrderDetailModal').modal('hide');
                  window.location.reload();
            } else {
                alert('Error: ' + (response.message || 'Failed to delete'));
                $btn.prop('disabled', false).html('<i class="fas fa-trash me-2"></i>Delete');
            }
        },
        error: function() {
            alert('Error deleting work order');
            $btn.prop('disabled', false).html('<i class="fas fa-trash me-2"></i>Delete');
        }
    });
});

// Split
$('#splitWorkOrderBtn').on('click', function () {
    if (!currentTaskDetails) return;
    $('#workOrderDetailModal').modal('hide');
    $('#split_task_id').val(currentTaskDetails.task_id);
    $('#split_current_quantity').text(currentTaskDetails.quantity);
    const maxSplitQty = currentTaskDetails.quantity - 1;
    if (maxSplitQty < 1) {
        $('#split_quantity').prop('disabled', true);
        $('#split_error').text('This work order cannot be split (quantity is 1)').show();
    } else {
        $('#split_quantity').prop('disabled', false).attr('max', maxSplitQty);
    }
    $('#split_quantity').val('');
    $('#split_preview').hide();
    $('#split_error').hide();
    $('#splitWorkOrderModal').modal('show');
});

$('#split_quantity').on('input', function () {
    const splitQty   = parseFloat($(this).val());
    const currentQty = parseFloat(currentTaskDetails.quantity);
    const setupHours = parseFloat(currentTaskDetails.setup_hours);
    const totalHours = parseFloat(currentTaskDetails.total_hours);
    $('#split_error').hide();
    if (!splitQty || splitQty <= 0) { $('#split_preview').hide(); return; }
    if (splitQty >= currentQty) { $('#split_error').text('Split quantity must be less than current quantity (' + currentQty + ')').show(); $('#split_preview').hide(); return; }
    if (splitQty < 1)           { $('#split_error').text('Split quantity must be at least 1').show(); $('#split_preview').hide(); return; }
    const hoursPerUnit     = (totalHours - setupHours) / currentQty;
    const remainingQty     = currentQty - splitQty;
    $('#preview_remaining_qty').text(remainingQty.toFixed(0));
    $('#preview_remaining_hours').text(((remainingQty * hoursPerUnit) + setupHours).toFixed(2) + 'h');
    $('#preview_split_qty').text(splitQty.toFixed(0));
    $('#preview_split_hours').text(((splitQty * hoursPerUnit) + setupHours).toFixed(2) + 'h');
    $('#split_preview').show();
});

$('#confirmSplitBtn').on('click', function () {
    const splitQty = parseFloat($('#split_quantity').val());
    if (!splitQty || splitQty <= 0) { $('#split_error').text('Please enter a valid split quantity').show(); return; }
    const $btn = $(this);
    $btn.prop('disabled', true).html('<span class="spinner-border spinner-border-sm me-2"></span>Splitting...');
    $.ajax({
        url: site_url + '/modules/machines_management/index.php?page=ajax_actions&action=split_vac_work_order',
        method: 'POST',
        data: { task_id: $('#split_task_id').val(), split_quantity: splitQty },
        dataType: 'json',
        success: function(response) {
            if (response.success) {
                alert('Work order split successfully!\n\nOriginal WO: ' + response.original_quantity + ' units (' + response.original_hours + 'h)\nNew WO: ' + response.split_quantity + ' units (' + response.split_hours + 'h)');
                $('#splitWorkOrderModal').modal('hide');
                loadGanttRows();
            } else {
                $('#split_error').text(response.message || 'Failed to split work order').show();
                $btn.prop('disabled', false).html('<i class="fas fa-check me-2"></i>Confirm Split');
            }
        },
        error: function() {
            $('#split_error').text('Error splitting work order').show();
            $btn.prop('disabled', false).html('<i class="fas fa-check me-2"></i>Confirm Split');
        }
    });
});


// ─────────────────────────────────────────────────────────────────────────────
// 3.  DRAG & DROP  (all delegated to document — works on AJAX rows)
// ─────────────────────────────────────────────────────────────────────────────
let draggedTask         = null;
let highlightedNeighbor = null;

// dragstart — delegated via document
document.addEventListener('dragstart', function (e) {
    const task = e.target.closest('.gantt-task');
    if (!task) return;
    draggedTask = task;
    task.classList.add('dragging');
});

document.addEventListener('dragend', function (e) {
    const task = e.target.closest('.gantt-task');
    if (!task) return;
    task.classList.remove('dragging');
    if (highlightedNeighbor) {
        highlightedNeighbor.classList.remove('drag-highlight');
        highlightedNeighbor = null;
    }
    draggedTask = null;
});

document.addEventListener('dragover', function (e) {
    // ── auto-scroll ──
    const ganttScrollable = document.querySelector('.gantt-scrollable-content');
    if (draggedTask && ganttScrollable) {
        const sr = ganttScrollable.getBoundingClientRect();
        const xPos = e.clientX - sr.left;
        if (xPos < 50)                  ganttScrollable.scrollLeft -= 20;
        else if (xPos > sr.width - 50)  ganttScrollable.scrollLeft += 20;
    }

    // ── highlight left-neighbour ──
    const row = e.target.closest('.gantt-row');
    if (!row || !draggedTask) return;
    e.preventDefault();
    row.classList.add('drop-target');

    const dropX      = e.clientX - row.getBoundingClientRect().left;
    const otherTasks = [...row.querySelectorAll('.gantt-task')]
        .filter(t => t !== draggedTask)
        .sort((a, b) => parseFloat(a.style.left) - parseFloat(b.style.left));

    if (highlightedNeighbor) {
        highlightedNeighbor.classList.remove('drag-highlight');
        highlightedNeighbor = null;
    }
    for (let t of otherTasks) {
        if (parseFloat(t.style.left) + parseFloat(t.style.width) < dropX) highlightedNeighbor = t;
        else break;
    }
    if (highlightedNeighbor) highlightedNeighbor.classList.add('drag-highlight');
});

document.addEventListener('dragleave', function (e) {
    const row = e.target.closest('.gantt-row');
    if (!row) return;
    if (!row.contains(e.relatedTarget)) {
        row.classList.remove('drop-target');
        if (highlightedNeighbor) {
            highlightedNeighbor.classList.remove('drag-highlight');
            highlightedNeighbor = null;
        }
    }
});

document.addEventListener('drop', function (e) {
    const row = e.target.closest('.gantt-row');
    if (!row || !draggedTask) return;
    e.preventDefault();
    row.classList.remove('drop-target');
    if (highlightedNeighbor) {
        highlightedNeighbor.classList.remove('drag-highlight');
        highlightedNeighbor = null;
    }

    const dropX      = e.clientX - row.getBoundingClientRect().left;
    const otherTasks = [...row.querySelectorAll('.gantt-task')]
        .filter(t => t !== draggedTask)
        .sort((a, b) => parseFloat(a.style.left) - parseFloat(b.style.left));

    let leftNeighbor = null;
    for (let t of otherTasks) {
        if (parseFloat(t.style.left) + parseFloat(t.style.width) < dropX) leftNeighbor = t;
        else break;
    }

    $.ajax({
        url: site_url + '/modules/machines_management/index.php?page=ajax_actions&action=update_vac_task_priority',
        method: 'POST',
        data: {
            task_id:                draggedTask.dataset.taskId,
            new_machine_id:         row.dataset.machineId,
            part_id:                draggedTask.dataset.partId,
            work_order_id:          draggedTask.dataset.workOrderId,
            left_neighbor_priority: leftNeighbor ? leftNeighbor.dataset.priority : null,
            left_neighbor_task_id:  leftNeighbor ? leftNeighbor.dataset.taskId   : null,
            new_position:           dropX
        },
        dataType: 'json',
        success: function(response) {
            if (response.status === 'success') {
                loadGanttRows();          // reload rows only — no full page refresh
            } else {
                alert('Error updating task: ' + response.message);
            }
        },
        error: function(xhr, status, error) { alert('Error updating task: ' + error); }
    });
});


// ─────────────────────────────────────────────────────────────────────────────
// 4.  ADD BREAK
// ─────────────────────────────────────────────────────────────────────────────
document.getElementById('addBreakBtn').addEventListener('click', function () {
    new bootstrap.Modal(document.getElementById('breakModal')).show();
});

document.getElementById('saveBreakBtn').addEventListener('click', function () {
    const machineId = document.getElementById('breakMachine').value;
    const duration  = parseFloat(document.getElementById('breakDuration').value);
    const reason    = document.getElementById('breakReason').value;

    if (!machineId || isNaN(duration) || duration < 0.5 || duration > 10) {
        alert('Please fill all fields with valid values');
        return;
    }

    const tasks            = [...document.querySelectorAll('.gantt-task')];
    const machineTasks     = tasks
        .filter(t => t.dataset.currentMachine === machineId)
        .sort((a, b) => a.dataset.priority - b.dataset.priority);
    const highestPriorityTask = machineTasks[0] || null;

    $.ajax({
        url: site_url + '/modules/machines_management/index.php?page=ajax_actions&action=add_vac_break',
        method: 'POST',
        data: {
            machine_id:               machineId,
            duration:                 duration,
            reason:                   reason,
            highest_priority_task_id: highestPriorityTask ? highestPriorityTask.dataset.taskId  : null,
            highest_priority:         highestPriorityTask ? highestPriorityTask.dataset.priority : null
        },
        dataType: 'json',
        success: function(response) {
            if (response.status === 'success') {
                alert('Break added successfully');
                $('#breakModal').modal('hide');
                loadGanttRows();
            } else {
                alert('Error adding break: ' + response.message);
            }
        },
        error: function(xhr, status, error) { alert('Error adding break: ' + error); }
    });
});


// ─────────────────────────────────────────────────────────────────────────────
// 5.  BREAKDOWN START / STOP
// ─────────────────────────────────────────────────────────────────────────────
document.getElementById('startBreakdownBtn').addEventListener('click', function () {
    new bootstrap.Modal(document.getElementById('startBreakdownModal')).show();
});
document.getElementById('stopBreakdownBtn').addEventListener('click', function () {
    new bootstrap.Modal(document.getElementById('stopBreakdownModal')).show();
});

$('#startBreakdownModal').on('show.bs.modal', function () {
    document.getElementById('startBreakdownForm').reset();
});

document.getElementById('confirmStartBreakdownBtn').addEventListener('click', function () {
    const machineId = document.getElementById('startBreakdownMachine').value;
    const reason    = document.getElementById('breakdown_reason').value;
    if (!machineId || !reason) { alert('Please select a machine and breakdown reason'); return; }
    $.ajax({
        url: site_url + '/modules/machines_management/index.php?page=ajax_actions&action=start_machine_breakdown',
        method: 'POST',
        data: { machine_id: machineId, breakdown_reason: reason },
        dataType: 'json',
        success: function(response) {
            if (response.status === 'success') {
                alert('Breakdown started successfully');
                $('#startBreakdownModal').modal('hide');
                document.getElementById('startBreakdownForm').reset();
                loadGanttRows();
            } else { alert('Error: ' + response.message); }
        },
        error: function(xhr, status, error) { alert('Error: ' + error); }
    });
});

document.getElementById('confirmStopBreakdownBtn').addEventListener('click', function () {
    const machineId = document.getElementById('stopBreakdownMachine').value;
    if (!machineId) { alert('Please select a machine with active breakdown'); return; }
    $.ajax({
        url: site_url + '/modules/machines_management/index.php?page=ajax_actions&action=stop_machine_breakdown',
        method: 'POST',
        data: { machine_id: machineId },
        dataType: 'json',
        success: function(response) {
            if (response.status === 'success') {
                alert('Breakdown stopped successfully');
                $('#stopBreakdownModal').modal('hide');
                loadGanttRows();
            } else { alert('Error: ' + response.message); }
        },
        error: function(xhr, status, error) { alert('Error: ' + error); }
    });
});

setInterval(function () {
    $.ajax({
        url: site_url + '/modules/machines_management/index.php?page=ajax_actions&action=get_breakdown_status',
        method: 'GET', dataType: 'json',
        success: function(response) { console.log('Breakdown status updated', response); }
    });
}, 120000);


// ─────────────────────────────────────────────────────────────────────────────
// 6.  WORK ORDERS LIST MODAL
// ─────────────────────────────────────────────────────────────────────────────
$('#workOrderModal').on('show.bs.modal', loadWorkOrders);
$('#workOrderModal').on('hidden.bs.modal', function () {
    $('#workOrderTableBody').empty();
    $('#workOrderContent').hide();
    $('#loadingSpinner').show();
    $('#errorMessage').addClass('d-none');
    $('#submitWorkOrdersBtn').prop('disabled', true);
});

function loadWorkOrders() {
    $('#loadingSpinner').show();
    $('#workOrderContent').hide();
    $('#errorMessage').addClass('d-none');
    $.ajax({
        url: site_url + '/modules/machines_management/index.php?page=ajax_actions&action=get_work_orders_vac',
        method: 'GET',
        dataType: 'json',
        success: function(response) {
            if (response.success && response.data.length > 0) {
                renderWorkOrders(response.data);
                $('#loadingSpinner').hide();
                $('#workOrderContent').show();
                $('#submitWorkOrdersBtn').prop('disabled', false);
                $('.select2').select2({ dropdownParent: $('#workOrderModal'), width: '100%' });
                initTableSort();
            } else {
                $('#loadingSpinner').hide();
                $('#errorMessage').text(response.message || 'No work orders found.').removeClass('d-none');
            }
        },
        error: function() {
            $('#loadingSpinner').hide();
            $('#errorMessage').removeClass('d-none');
        }
    });
}

function renderWorkOrders(workOrders) {
    const tbody = $('#workOrderTableBody');
    tbody.empty();
    workOrders.forEach(function(wo) {
        let materialsHtml = '';
        if (wo.bought_in_materials && wo.bought_in_materials.trim() !== '') {
            const mats    = wo.bought_in_materials.split(',');
            const display = mats.slice(0, 2).map(m => m.trim()).join(', ');
            const extra   = mats.length - 2;
            materialsHtml = extra > 0
                ? `<span class="materials-column materials-available" title="${wo.bought_in_materials}">${display} <small>(+${extra} more)</small></span>`
                : `<span class="materials-column materials-available" title="${wo.bought_in_materials}">${display}</span>`;
        } else {
            materialsHtml = '<span class="no-materials">No materials</span>';
        }
        tbody.append(`
            <tr data-part-id="${wo.part_id}" data-wo-id="${wo.work_order_id}" data-set-id="${wo.set_id || 0}">
                <td>${wo.work_order_name || '-'}</td>
                <td>${wo.product_name}</td>
                <td>${wo.product_description}</td>
                <td>${wo.end_date}</td>
                <td>${wo.quantity}</td>
                <td>${wo.total_hours}</td>
                <td class="setting-instruction" title="${wo.setting_instruction || ''}">${wo.setting_instruction || '-'}</td>
                <td>${materialsHtml}</td>
                <td>${wo.machine_dropdown}</td>
                <td class="checkbox-cell">
                    <input class="form-check-input" type="checkbox" name="workOrder[]"
                           value="${wo.work_order_id}"
                           id="workOrder${wo.work_order_id}_${wo.id}"
                           data-machine-id="${wo.machine_id}"
                           data-id="${wo.id}">
                </td>
            </tr>`
        );
    });
    // row-click toggles checkbox
    $('#workOrderTableBody tr').on('click', function(e) {
        if ($(e.target).is('input[type="checkbox"]') || $(e.target).is('select') ||
            $(e.target).closest('.select2').length || $(e.target).closest('select').length) return;
        const cb = $(this).find('input[type="checkbox"]');
        cb.prop('checked', !cb.prop('checked'));
    });
}

function initTableSort() {
    const table   = document.getElementById('workOrderTable');
    const headers = table.querySelectorAll('th.sortable');
    headers.forEach(function(header) {
        header.addEventListener('click', function() {
            const column      = this.dataset.column;
            const type        = this.dataset.type;
            const tbody       = table.querySelector('tbody');
            const rows        = Array.from(tbody.querySelectorAll('tr'));
            const direction   = this.classList.contains('asc') ? 'desc' : 'asc';
            headers.forEach(h => h.classList.remove('asc', 'desc'));
            this.classList.add(direction);
            const colIdx = Array.from(this.parentElement.children).indexOf(this);
            rows.sort((a, b) => {
                let av = a.children[colIdx].textContent.trim();
                let bv = b.children[colIdx].textContent.trim();
                if (type === 'number') { av = parseFloat(av) || 0; bv = parseFloat(bv) || 0; }
                else if (type === 'date') { av = new Date(av); bv = new Date(bv); }
                if (av < bv) return direction === 'asc' ? -1 : 1;
                if (av > bv) return direction === 'asc' ?  1 : -1;
                return 0;
            });
            rows.forEach(r => tbody.appendChild(r));
            if (typeof $('.select2').select2 === 'function') {
                $('.select2').select2('destroy');
                $('.select2').select2({ dropdownParent: $('#workOrderModal'), width: '100%' });
            }
            // re-attach row click after sort
            $('#workOrderTableBody tr').off('click').on('click', function(e) {
                if ($(e.target).is('input[type="checkbox"]') || $(e.target).is('select') ||
                    $(e.target).closest('.select2').length || $(e.target).closest('select').length) return;
                $(this).find('input[type="checkbox"]').prop('checked', function(i, v) { return !v; });
            });
        });
    });
}

function showSelectedWorkOrders() {
    const workOrders = [];
    $('input[name="workOrder[]"]:checked').each(function () {
        const row = $(this).closest('tr');
        workOrders.push({
            id:            $(this).data('id'),
            work_order_id: $(this).val(),
            part_id:       row.data('part-id'),
            machine_id:    $('#machine_id_' + $(this).data('id')).val()
        });
    });
    if (!workOrders.length) { alert('Please select at least one work order.'); return; }
    const $btn = $('#submitWorkOrdersBtn');
    $btn.prop('disabled', true);
    $('#spinner').removeClass('d-none');
    $btn.find('.btn-text').text('Submitting...');
    $.ajax({
        url: site_url + '/modules/machines_management/index.php?page=ajax_actions&action=select_order_for_vac',
        method: 'POST',
        data: { work_orders: JSON.stringify(workOrders) },
        success: function() {
            alert('Work orders submitted successfully!');
            $('#workOrderModal').modal('hide');
            loadGanttRows();
        },
        error: function() { loadGanttRows(); },
        complete: function() {
            $btn.prop('disabled', false);
            $('#spinner').addClass('d-none');
            $btn.find('.btn-text').text('Show Selected');
        }
    });
}


// ─────────────────────────────────────────────────────────────────────────────
// 7.  SAVE NOTE
// ─────────────────────────────────────────────────────────────────────────────
function saveTaskNote() {
    const $btn = $('button[onclick="saveTaskNote()"]');
    $btn.prop('disabled', true).html('<span class="spinner-border spinner-border-sm me-1"></span>Saving...');
    $.ajax({
        url: site_url + '/modules/machines_management/index.php?page=ajax_actions&action=save_task_note',
        type: 'POST',
        data: {
            task_id:      $('#note_task_id').val(),
            work_order_id: $('#note_work_order_id').val(),
            part_id:      $('#note_part_id').val(),
            note:         $('#task_note').val()
        },
        success: function(res) {
            const data = (typeof res === 'string') ? JSON.parse(res) : res;
            if (data.status === 'success') {
                $btn.html('<i class="fas fa-check me-1"></i>Saved!');
                setTimeout(() => $btn.html('Save Note').prop('disabled', false), 2000);
            } else {
                $btn.html('Save Note').prop('disabled', false);
                alert('Failed to save note.');
            }
        },
        error: function() { $btn.html('Save Note').prop('disabled', false); alert('Error saving note.'); }
    });
}
</script>
<script>
function applyFilters() {
    let partFilter = document.getElementById('filter_part').value.trim().toLowerCase();
    let woFilter = document.getElementById('filter_wo').value.trim().toLowerCase();
    let settingFilter = document.getElementById('filter_setting').value.trim().toLowerCase();

    let tasks = document.querySelectorAll('.gantt-task');

    // If no filters → remove all highlights and exit
    if (!partFilter && !woFilter && !settingFilter) {
        tasks.forEach(task => {
            task.classList.remove('filter-highlight');
        });
        // Reset all machine cards
        document.querySelectorAll('.gantt-labels .card').forEach(card => {
            card.style.outline = '';
            card.style.boxShadow = '';
            card.style.backgroundColor = '';
        });
        return;
    }

    // Collect matched machine IDs
    let matchedMachineIds = new Set();

    tasks.forEach(task => {
        let part    = (task.dataset.part    || '').toLowerCase();
        let wo      = (task.dataset.wo      || '').toLowerCase();
        let setting = (task.dataset.setting || '').toLowerCase();

        let match = true;
        if (partFilter    && !part.includes(partFilter))       match = false;
        if (woFilter      && !wo.includes(woFilter))           match = false;
        if (settingFilter && !setting.includes(settingFilter)) match = false;

        if (match) {
            task.classList.add('filter-highlight');
            // Collect the machine ID from the task's row
            let row = task.closest('.gantt-row');
            if (row && row.dataset.machineId) {
                matchedMachineIds.add(row.dataset.machineId);
            }
        } else {
            task.classList.remove('filter-highlight');
        }
    });

    // Highlight / dim machine label cards
    document.querySelectorAll('.machine-section').forEach(section => {
        let card = section.querySelector('.card');
        if (!card) return;

        // Get machine ID from the gantt row that shares the same index
        // Machine sections and gantt rows are rendered in the same order
        let machineId = section.dataset.machineId;

        if (matchedMachineIds.has(machineId)) {
            card.style.outline         = '3px solid #f5c518';
            card.style.boxShadow       = '0 0 12px rgba(245, 197, 24, 0.8)';
            card.style.backgroundColor = '#fffbe6';
        } else {
            card.style.outline         = '';
            card.style.boxShadow       = '';
            card.style.backgroundColor = '';
        }
    });
}
</script>
</div><!-- /.container-fluid (outer) -->