403Webshell
Server IP : 121.121.20.254  /  Your IP : 216.73.217.51
Web Server : Microsoft-IIS/10.0
System : Windows NT WEB-SERVER 10.0 build 20348 (Windows Server 2022) AMD64
User : IUSR ( 0)
PHP Version : 8.3.28
Disable Function : NONE
MySQL : ON  |  cURL : ON  |  WGET : OFF  |  Perl : OFF  |  Python : OFF  |  Sudo : OFF  |  Pkexec : OFF
Directory :  C:/Program Files/MariaDB 10.6/data/inventorysearch/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : C:/Program Files/MariaDB 10.6/data/inventorysearch/wpstg0_xyz_ips_short_code.ibd
���������L����@���������������������������&&�����������������������������������������������L��.|`����������t��t�>_���������L���������������������������������i������������������������������������������������������������������������������������������������������������������������������������������������i�	

���������������������������������������������������� !"#�L��"����������L��E��F�7�������2 infimumsupremum(�|��aed-syarikat-display�&x�[xyz-ips snippet="aed-syarikat-display"]����*�|��MYSQL-Connection-Check<?php
echo '<pre style="font-family: Consolas, monospace;">';

// ========================
// Test SQL Server 2016
// ========================
echo "Testing MSSQL 2016 (AED_SYARIKAT)...\n";

$conn2016 = get_mssql_2016();

if ($conn2016) {
    echo "✅ MSSQL 2016 connected successfully.\n\n";
} else {
    echo "❌ MSSQL 2016 connection FAILED.\n";
    print_r(sqlsrv_errors());
    echo "\n";
}

// ========================
// Test SQL Server 2019
// ========================
echo "Testing MSSQL 2019 (AED_YTL09122025)...\n";

$conn2019 = get_mssql_2019();

if ($conn2019) {
    echo "✅ MSSQL 2019 connected successfully.\n\n";
} else {
    echo "❌ MSSQL 2019 connection FAILED.\n";
    print_r(sqlsrv_errors());
    echo "\n";
}

echo "</pre>";[xyz-ips snippet="MYSQL-Connection-Check"]���� c��PHP-Info<?php phpinfo(); ?>[xyz-ips snippet="PHP-Info"]���� �(q��check-sqlsrv<?php
// Quick check for SQLSRV extension
echo "<pre>";

if (extension_loaded('sqlsrv')) {
    echo "✅ sqlsrv extension is LOADED.\n";
} else {
    echo "❌ sqlsrv extension is NOT loaded.\n";
}

// Optional: show only modules info from phpinfo
phpinfo(INFO_MODULES);[xyz-ips snippet="check-sqlsrv"]����+�0���aed-ytl09122025-display�&f+[xyz-ips snippet="aed-ytl09122025-display"]����"��8��Server-Checker<?php
if (!current_user_can('manage_options')) return;

    $server = "192.168.100.225,19416\\MSSQL2016SERVER";
    $conn = @sqlsrv_connect($server, [
        "Database" => "AED_SYARIKAT",
        "UID" => "sa",
        "PWD" => "user2025**",
        "Encrypt" => "yes",
        "TrustServerCertificate" => "yes",
        "LoginTimeout" => 2,
    ]);

    if ($conn) {
        echo '<div class="notice notice-success"><p>✅ WP can connect to SQL Server.</p></div>';
        sqlsrv_close($conn);
    } else {
        echo '<div class="notice notice-error"><p>❌ WP cannot connect to SQL Server (expected for public hosting).</p></div>';
    }[xyz-ips snippet="Server-Checker"]�����@j��sales-order�&@v[xyz-ips snippet="sales-order"]����,�H��	�aed-syarikat-display-new�
&=B[xyz-ips snippet="aed-syarikat-display-new"]����/�P��
�aed-syarikat-display-detail�&`e[xyz-ips snippet="aed-syarikat-display-detail"]����(��X&��Elementor-PopUp-Test<button id="test-btn" style="padding:8px 14px;">
  Open Elementor Content
</button>

<div id="test-box" style="display:none; margin-top:15px;">
  <?php echo do_shortcode('[elementor-template id="73"]'); ?>
</div>

<script>
document.getElementById('test-btn').addEventListener('click', function () {
  const box = document.getElementById('test-box');
  box.style.display = box.style.display === 'none' ? 'block' : 'none';
});
</script>[xyz-ips snippet="Elementor-PopUp-Test"]����"{`��Login-Redirect<?php

    if (is_user_logged_in()) {
        wp_redirect( home_url('/inventory-search/') );
        exit;
    }

?>[xyz-ips snippet="Login-Redirect"]������h&�px��AC-Cash-Sales-List�&�[xyz-ips snippet="AC-Cash-Sales-List"]����'�xz��AC-Cash-Sale-Create�"&��[xyz-ips snippet="AC-Cash-Sale-Create"]����%���r��AC-Cash-Sale-Edit�B&��[xyz-ips snippet="AC-Cash-Sale-Edit"]����������
�Logout<?php
$target = 'https://website.ipohserver.com/ECOSalesInventorySearch/index.php/';

if (!is_user_logged_in()) {
  echo '<script>location.replace('.json_encode($target).');</script>';
  echo '<noscript><meta http-equiv="refresh" content="0;url='.esc_attr($target).'"></noscript>';
  return;
}

$user = wp_get_current_user();

// Admin: do NOT logout, but still redirect away (so you don't get stuck here)
if (in_array('administrator', (array) $user->roles)) {
  echo '<script>location.replace('.json_encode($target).');</script>';
  echo '<noscript><meta http-equiv="refresh" content="0;url='.esc_attr($target).'"></noscript>';
  return;
}

// Non-admin: logout
wp_logout();

// Redirect (JS + noscript meta refresh)
echo '<script>location.replace('.json_encode($target).');</script>';
echo '<noscript><meta http-equiv="refresh" content="0;url='.esc_attr($target).'"></noscript>';
return;[xyz-ips snippet="Logout"]����p
,�c�L��������������w�
�?�<?php
if (!is_user_logged_in()) {
    wp_redirect(wp_login_url());
    exit;
}

// ─────────────────────────────────────────────
// 0) SMALL HELPER
// ─────────────────────────────────────────────
if (!function_exists('ac_bool_from_text')) {
    function ac_bool_from_text($val, $default = null)
    {
        if ($val === null) return $default;
        $norm = strtolower(trim((string)$val));
        if ($norm === '') return $default;

        // "true-ish"
        if (in_array($norm, ['active', 'available', 'yes', 'y', '1', 'true', 'on'], true)) {
            return 1;
        }

        // "false-ish"
        if (in_array($norm, ['inactive', 'not available', 'no', 'n', '0', 'false', 'off'], true)) {
            return 0;
        }

        return $default;
    }
}

// ─────────────────────────────────────────────
// 1) UPDATE HANDLER + CONNECTION
// ─────────────────────────────────────────────
$updateStatus = '';   // "success" | "error" | ""
$updateText   = '';   // message text

// Get connection
$conn = get_mssql_2016();

if (!$conn) {
    echo "<p style='color:red'>Database connection error.</p>";
    return;
}

// If user submitted the edit form
if (
    $_SERVER['REQUEST_METHOD'] === 'POST' &&
    isset($_POST['ac_update']) &&
    $_POST['ac_update'] === '1'
) {
    $itemCode = $_POST['ac_item_code'] ?? '';
    $uom      = $_POST['ac_uom'] ?? ''; // original UOM (hidden field)

    // Editable fields (empty string -> NULL)
    $description = (isset($_POST['ac_description']) && $_POST['ac_description'] !== '') ? $_POST['ac_description'] : null;
    $itemGroup   = (isset($_POST['ac_item_group'])  && $_POST['ac_item_group']  !== '') ? $_POST['ac_item_group']  : null;
    $itemType    = (isset($_POST['ac_item_type'])   && $_POST['ac_item_type']   !== '') ? $_POST['ac_item_type']   : null;

    $desc2    = (isset($_POST['ac_desc2'])    && $_POST['ac_desc2']    !== '') ? $_POST['ac_desc2']    : null;
    $brand    = (isset($_POST['ac_brand'])    && $_POST['ac_brand']    !== '') ? $_POST['ac_brand']    : null;
    $category = (isset($_POST['ac_category']) && $_POST['ac_category'] !== '') ? $_POST['ac_category'] : null;
    $leadtime = (isset($_POST['ac_leadtime']) && $_POST['ac_leadtime'] !== '') ? (int)$_POST['ac_leadtime'] : null;
    $barcode  = (isset($_POST['ac_barcode'])  && $_POST['ac_barcode']  !== '') ? $_POST['ac_barcode']  : null;
    $supplier = (isset($_POST['ac_supplier']) && $_POST['ac_supplier'] !== '') ? $_POST['ac_supplier'] : null;

    // Weight
    $weight = (isset($_POST['ac_weight']) && $_POST['ac_weight'] !== '') ? (float)$_POST['ac_weight'] : null;

    // Price from form → clean and format for DECIMAL(25,8)
    $price = null;
    if (!empty($_POST['ac_price'])) {

        // Remove everything except digits and dot
        $clean = preg_replace('/[^0-9.]/', '', $_POST['ac_price']);

        // If empty or invalid, treat as null
        if ($clean === '' || $clean === '.' ) {
            $price = null;
        } else {
            // Convert to float and format as DECIMAL(25,8)
            $price = number_format((float)$clean, 8, '.', '');
        }
    }

    // Display UOM (may be changed)
    $uomDisplay = $_POST['ac_uom_display'] ?? '';
    $uomNew     = ($uomDisplay !== '') ? $uomDisplay : $uom;

    // Dropdowns send 'T' or 'F' directly
    $stockControl = (isset($_POST['ac_stockcontrol']) && $_POST['ac_stockcontrol'] === 'T') ? 'T' : 'F';
    $isActive     = (isset($_POST['ac_isactive'])     && $_POST['ac_isactive']     === 'T') ? 'T' : 'F';

    // Bonus text box ("Yes"/"No") → 'T' / 'F'
    $bonusTextInput = $_POST['ac_bonus'] ?? '';
    $bonusBit       = ac_bool_from_text($bonusTextInput, 0); // 1 or 0
    $isBonusFlag    = $bonusBit ? 'T' : 'F';

    if ($itemCode !== '') {
        // Clear any previous errors
        sqlsrv_errors();

        // UPDATE dbo.Item  (NO BarCode column here)
        $sqlItem = "
            UPDATE dbo.Item
            SET 
                Description      = ?,
                ItemGroup        = ?,
                ItemType         = ?,
                Desc2            = ?,
                ItemBrand        = ?,
                ItemCategory     = ?,
                LeadTimeDay      = ?,
                MainSupplier     = ?,
                IsActive         = ?,
                StockControl     = ?,
                IsCalcBonusPoint = ?
            WHERE ItemCode = ?
        ";

        $paramsItem = [
            $description,
            $itemGroup,
            $itemType,
            $desc2,
            $brand,
            $category,
            $leadtime,
            $supplier,
            $isActive,
            $stockControl,
            $isBonusFlag,
            $itemCode
        ];

        $okItem = sqlsrv_query($conn, $sqlItem, $paramsItem);

        // UPDATE dbo.ItemUOM (weight + price + UOM + barcode)
        $okUom = true;
        if ($uom !== '') {
            $sqlUom = "
                UPDATE dbo.ItemUOM
                SET 
                    Weight = ?,
                    Price  = ?,
                    UOM    = ?,
                    BarCode = ?
                WHERE ItemCode = ? AND UOM = ?
            ";
            $paramsUom = [$weight, $price, $uomNew, $barcode, $itemCode, $uom];
            $okUom = sqlsrv_query($conn, $sqlUom, $paramsUom);
        }

        // Check if SQL Server logged any errors
        $errors = sqlsrv_errors();

        if (empty($errors) && $okItem && $okUom) {
            $updateStatus = 'success';
            $updateText   = 'Item updated successfully.';
        } else {
            $updateStatus = 'error';
            $updateText   = "Update failed:\n" . print_r($errors, true);
        }

    } else {
        $updateStatus = 'error';
        $updateText   = 'Missing ItemCode; cannot update.';
    }
}

// ─────────────────────────────────────────────
//  2) SEARCH HANDLING
// ─────────────────────────────────────────────
$search = isset($_GET['ac_q']) ? $_GET['ac_q'] : '';

$where     = '';
$params    = [];
$topClause = ($search === '') ? 'TOP 100' : ''; // Only first 100 when no search

if ($search !== '') {
    $where = "
    WHERE 
        REPLACE(REPLACE(REPLACE(REPLACE(LOWER(i.ItemCode),'-',''),' ',''),'/',''),':','') 
            LIKE REPLACE(REPLACE(REPLACE(REPLACE(LOWER(?),'-',''),' ',''),'/',''),':','')
     OR LOWER(i.Description) LIKE LOWER(?)
     OR LOWER(i.Desc2)       LIKE LOWER(?)
    ";

    $likeClean = '%' . strtolower(preg_replace('/[-\/:\s]/', '', $search)) . '%';
    $likeText  = '%' . strtolower($search) . '%';

    $params = [$likeClean, $likeText, $likeText];
}

// ─────────────────────────────────────────────
//  3) MAIN QUERY
// ─────────────────────────────────────────────
$sqlSelect = "
    SELECT $topClause
        i.ItemCode,
        i.Description,
        i.Desc2,
        i.ItemGroup,
        i.ItemType,
        i.ItemBrand,
        i.ItemCategory,
        i.LeadTimeDay,
        i.IsCalcBonusPoint,
        i.MainSupplier,
        i.IsActive,
        i.StockControl,
        u.UOM,
        u.Price,
        u.BarCode,
        u.Weight,
        u.WeightUOM,
        u.Volume,
        u.VolumeUOM,
        u.Shelf
    FROM dbo.Item i
    LEFT JOIN dbo.ItemUOM u
        ON u.ItemCode = i.ItemCode
    $where
    ORDER BY i.ItemCode ASC
";

$stmtSelect = sqlsrv_query($conn, $sqlSelect, $params);

if ($stmtSelect === false) {
    echo "<pre>Select Failed:\n" . print_r(sqlsrv_errors(), true) . "</pre>";
    return;
}

// One-time CSS flag if you need it elsewhere
if (!defined('AC_ITEM_LAYOUT_CSS')) {
    define('AC_ITEM_LAYOUT_CSS', true);
}
?>

<div class="ac-page-layout">
    <div class="ac-page-header">
        <div class="ac-page-title-icon">📦</div>
        <h2 class="ac-page-title">Inventory Search</h2>
    </div>

    <!-- Top: search bar -->
    <div class="ac-top-bar">
        <h2>Item List</h2>
        <div class="ac-search-row">
            <form method="get" class="ac-search-form" style="display:flex; gap:8px; flex-wrap:wrap; margin:0;">
                <input
                    id="ac_q_input"
                    class="ac-search-input"
                    type="text"
                    name="ac_q"
                    placeholder="Global Search (ItemCode / Description / Desc2)"
                    value="<?= htmlspecialchars($search) ?>"
                >

                <?php foreach ($_GET as $key => $value) :
                    if ($key === 'ac_q') continue; ?>
                    <input type="hidden" name="<?= htmlspecialchars($key) ?>" value="<?= htmlspecialchars($value) ?>">
                <?php endforeach; ?>

                <button type="submit" class="ac-btn ac-btn-primary">Search</button>
                <button
                    type="button"
                    class="ac-btn ac-btn-secondary"
                    onclick="document.getElementById('ac_q_input').value=''; this.form.submit();"
                >
                    Clear
                </button>
            </form>
        </div>
    </div>

    <!-- Middle: table (scroll) -->
    <div class="ac-table-wrapper">
        <table class="ac-item-table">
            <thead>
                <tr>
                    <th>ItemCode</th>
                    <th>Product Name</th>
                    <th>Group</th>
                    <th>Type</th>
                    <th>Unit</th>
                    <th>Price</th>
                    <th>Stock Status</th>
                    <th>Status</th>
                </tr>
            </thead>
            <tbody>
                <?php while ($row = sqlsrv_fetch_array($stmtSelect, SQLSRV_FETCH_ASSOC)) :
                    // Raw price from DB
                    $rawPrice = $row['Price'];

                    // Exact string with 8 decimals for editing
                    $priceRawStr = is_null($rawPrice)
                        ? ''
                        : number_format((float)$rawPrice, 8, '.', '');

                    // Pretty display for table, e.g. "RM 2.00"
                    $priceDisplay = is_null($rawPrice)
                        ? '-'
                        : 'RM ' . number_format((float)$rawPrice, 2);

                    // Flags
                    $isActiveRaw     = $row['IsActive'];
                    $stockControlRaw = $row['StockControl'];
                    $bonusFlagRaw    = $row['IsCalcBonusPoint'];

                    $activeFlag = ($isActiveRaw === 'T' || $isActiveRaw === 1 || $isActiveRaw === true) ? 'T' : 'F';
                    $stockFlag  = ($stockControlRaw === 'T' || $stockControlRaw === 1 || $stockControlRaw === true) ? 'T' : 'F';
                    $bonusFlag  = ($bonusFlagRaw === 'T' || $bonusFlagRaw === 1 || $bonusFlagRaw === true) ? 'T' : 'F';

                    $statusText  = ($activeFlag === 'T') ? 'Active'      : 'Inactive';
                    $stockStatus = ($stockFlag  === 'T') ? 'Available'   : 'Not available';
                    $bonusText   = ($bonusFlag  === 'T') ? 'Yes'         : 'No';

                    $weightStr = is_null($row['Weight']) ? '' : (float)$row['Weight'];
                    $volumeStr = is_null($row['Volume']) ? '' : (float)$row['Volume'];
                ?>
                    <tr class="ac-item-row"
                        data-item-code="<?= htmlspecialchars($row['ItemCode']) ?>"
                        data-product-name="<?= htmlspecialchars($row['Description']) ?>"
                        data-group="<?= htmlspecialchars($row['ItemGroup']) ?>"
                        data-type="<?= htmlspecialchars($row['ItemType']) ?>"
                        data-uom="<?= htmlspecialchars($row['UOM']) ?>"
                        data-price="<?= htmlspecialchars($priceRawStr) ?>"
                        data-stock-status="<?= htmlspecialchars($stockStatus) ?>"
                        data-status="<?= htmlspecialchars($statusText) ?>"
                        data-isactive="<?= htmlspecialchars($activeFlag) ?>"
                        data-stockcontrol="<?= htmlspecialchars($stockFlag) ?>"
                        data-desc2="<?= htmlspecialchars($row['Desc2']) ?>"
                        data-brand="<?= htmlspecialchars($row['ItemBrand']) ?>"
                        data-category="<?= htmlspecialchars($row['ItemCategory']) ?>"
                        data-leadtime="<?= htmlspecialchars($row['LeadTimeDay']) ?>"
                        data-barcode="<?= htmlspecialchars($row['BarCode']) ?>"
                        data-bonus="<?= htmlspecialchars($bonusText) ?>"
                        data-supplier="<?= htmlspecialchars($row['MainSupplier']) ?>"
                        data-weight="<?= htmlspecialchars($weightStr) ?>"
                        data-weight-uom="<?= htmlspecialchars($row['WeightUOM']) ?>"
                        data-volume="<?= htmlspecialchars($volumeStr) ?>"
                        data-volume-uom="<?= htmlspecialchars($row['VolumeUOM']) ?>"
                        data-shelf="<?= htmlspecialchars($row['Shelf']) ?>"
                    >
                        <td><?= htmlspecialchars($row['ItemCode']) ?></td>
                        <td><?= htmlspecialchars($row['Description']) ?></td>
                        <td><?= htmlspecialchars($row['ItemGroup']) ?></td>
                        <td><?= htmlspecialchars($row['ItemType']) ?></td>
                        <td><?= htmlspecialchars($row['UOM']) ?></td>
                        <td><?= $priceDisplay ?></td>
                        <td><span class="badge badge-green"><?= $stockStatus ?></span></td>
                        <td><span class="badge badge-green"><?= $statusText ?></span></td>
                    </tr>
                <?php endwhile; ?>
            </tbody>
        </table>
    </div>

    <?php
    sqlsrv_free_stmt($stmtSelect);
    sqlsrv_close($conn);
    ?>

    <!-- Bottom: detail panel (desktop) - all editable -->
    <div class="ac-detail-panel">
        <div class="ac-detail-header">
            <div class="ac-detail-title" id="acDetailTitle">Item Detail</div>
            <div class="ac-detail-subtitle" id="acDetailSubtitle"></div>
        </div>

        <form method="post" id="acDetailForm" class="ac-detail-form">
            <input type="hidden" name="ac_update" value="1">
            <input type="hidden" name="ac_item_code" id="acDetailItemCodeHidden" value="">
            <input type="hidden" name="ac_uom" id="acDetailUOMHidden" value="">

            <div class="ac-detail-grid">
                <div class="ac-detail-cell">
                    <div class="ac-detail-label">Description</div>
                    <input type="text" name="ac_description" id="acDetailProductName" class="ac-detail-input">
                </div>
                <div class="ac-detail-cell">
                    <div class="ac-detail-label">Item Group</div>
                    <input type="text" name="ac_item_group" id="acDetailGroup" class="ac-detail-input">
                </div>
                <div class="ac-detail-cell">
                    <div class="ac-detail-label">Item Type</div>
                    <input type="text" name="ac_item_type" id="acDetailType" class="ac-detail-input">
                </div>
                <div class="ac-detai�w��St ���������w�
�8��l-cell">
                    <div class="ac-detail-label">Unit</div>
                    <input type="text" name="ac_uom_display" id="acDetailUOM" class="ac-detail-input">
                </div>
                <div class="ac-detail-cell">
                    <div class="ac-detail-label">Price</div>
                    <div class="ac-currency-wrapper">
                        <span class="ac-currency-prefix">RM</span>
                        <input
                            type="text"
                            name="ac_price"
                            id="acDetailPrice"
                            class="ac-detail-input ac-currency-input"
                            inputmode="decimal"
                            placeholder="0.00"
                        >
                    </div>
                </div>
                <div class="ac-detail-cell">
                    <div class="ac-detail-label">Stock Status</div>
                    <select name="ac_stockcontrol" id="acDetailStockStatus" class="ac-detail-input">
                        <option value="T">Available</option>
                        <option value="F">Not Available</option>
                    </select>
                </div>
                <div class="ac-detail-cell">
                    <div class="ac-detail-label">Status</div>
                    <select name="ac_isactive" id="acDetailStatus" class="ac-detail-input">
                        <option value="T">Active</option>
                        <option value="F">Inactive</option>
                    </select>
                </div>

                <div class="ac-detail-cell">
                    <div class="ac-detail-label">Alternative Name (Desc2)</div>
                    <input type="text" name="ac_desc2" id="acDetailDesc2" class="ac-detail-input">
                </div>
                <div class="ac-detail-cell">
                    <div class="ac-detail-label">Brand</div>
                    <input type="text" name="ac_brand" id="acDetailBrand" class="ac-detail-input">
                </div>
                <div class="ac-detail-cell">
                    <div class="ac-detail-label">Category</div>
                    <input type="text" name="ac_category" id="acDetailCategory" class="ac-detail-input">
                </div>
                <div class="ac-detail-cell">
                    <div class="ac-detail-label">Lead Time (days)</div>
                    <input type="number" name="ac_leadtime" id="acDetailLeadTime" class="ac-detail-input">
                </div>
                <div class="ac-detail-cell">
                    <div class="ac-detail-label">Barcode</div>
                    <input type="text" name="ac_barcode" id="acDetailBarcode" class="ac-detail-input">
                </div>
                <div class="ac-detail-cell">
                    <div class="ac-detail-label">Bonus Eligible</div>
                    <input type="text" name="ac_bonus" id="acDetailBonus" class="ac-detail-input">
                </div>
                <div class="ac-detail-cell">
                    <div class="ac-detail-label">Supplier</div>
                    <input type="text" name="ac_supplier" id="acDetailSupplier" class="ac-detail-input">
                </div>
                <div class="ac-detail-cell">
                    <div class="ac-detail-label">Weight</div>
                    <input type="number" step="0.001" name="ac_weight" id="acDetailWeight" class="ac-detail-input">
                </div>
            </div>

            <div class="ac-detail-actions">
                <button type="submit" class="ac-btn ac-btn-primary">Save Changes</button>
            </div>
        </form>
    </div>

    <!-- Mobile popup markup (view-only) -->
    <div id="acItemModalOverlay" class="ac-modal-overlay">
        <div class="ac-modal">
            <button type="button" id="acModalClose" class="ac-modal-close">&times;</button>
            <h3 class="ac-modal-header-title" id="acModalTitle">Item Detail</h3>
            <p class="ac-modal-header-subtitle" id="acModalSubtitle"></p>

            <div class="ac-modal-grid">
                <div class="ac-modal-cell">
                    <div class="ac-modal-label">Description</div>
                    <div class="ac-modal-value" id="acModalProductName">-</div>
                </div>
                <div class="ac-modal-cell">
                    <div class="ac-modal-label">Item Group</div>
                    <div class="ac-modal-value" id="acModalGroup">-</div>
                </div>
                <div class="ac-modal-cell">
                    <div class="ac-modal-label">Item Type</div>
                    <div class="ac-modal-value" id="acModalType">-</div>
                </div>
                <div class="ac-modal-cell">
                    <div class="ac-modal-label">Unit</div>
                    <div class="ac-modal-value" id="acModalUOM">-</div>
                </div>
                <div class="ac-modal-cell">
                    <div class="ac-modal-label">Price</div>
                    <div class="ac-modal-value" id="acModalPrice">-</div>
                </div>
                <div class="ac-modal-cell">
                    <div class="ac-modal-label">Stock Status</div>
                    <div class="ac-modal-value" id="acModalStockStatus">-</div>
                </div>
                <div class="ac-modal-cell">
                    <div class="ac-modal-label">Status</div>
                    <div class="ac-modal-value" id="acModalStatus">-</div>
                </div>
                <div class="ac-modal-cell">
                    <div class="ac-modal-label">Alternative Name (Desc2)</div>
                    <div class="ac-modal-value" id="acModalDesc2">-</div>
                </div>
                <div class="ac-modal-cell">
                    <div class="ac-modal-label">Brand</div>
                    <div class="ac-modal-value" id="acModalBrand">-</div>
                </div>
                <div class="ac-modal-cell">
                    <div class="ac-modal-label">Category</div>
                    <div class="ac-modal-value" id="acModalCategory">-</div>
                </div>
                <div class="ac-modal-cell">
                    <div class="ac-modal-label">Lead Time (days)</div>
                    <div class="ac-modal-value" id="acModalLeadTime">-</div>
                </div>
                <div class="ac-modal-cell">
                    <div class="ac-modal-label">Barcode</div>
                    <div class="ac-modal-value" id="acModalBarcode">-</div>
                </div>
                <div class="ac-modal-cell">
                    <div class="ac-modal-label">Bonus Eligible</div>
                    <div class="ac-modal-value" id="acModalBonus">-</div>
                </div>
                <div class="ac-modal-cell">
                    <div class="ac-modal-label">Supplier</div>
                    <div class="ac-modal-value" id="acModalSupplier">-</div>
                </div>
                <div class="ac-modal-cell">
                    <div class="ac-modal-label">Weight</div>
                    <div class="ac-modal-value" id="acModalWeight">-</div>
                </div>
            </div>
        </div>
    </div>
</div> <!-- end .ac-page-layout -->

<!-- SweetAlert2 -->
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>

<!-- Pass PHP update result to JS -->
<script>
var acUpdateStatus = <?= json_encode($updateStatus) ?>; // "success" | "error" | ""
var acUpdateText   = <?= json_encode($updateText) ?>;   // message text
</script>

<!-- Main JS -->
<script>
document.addEventListener("DOMContentLoaded", function () {
    const f  = function(id){ return document.getElementById(id); };
    const mq = window.matchMedia("(max-width: 1024px)");
    const isMobile = () => mq.matches;

    // 1. Show SweetAlert result after POST
    if (typeof acUpdateStatus !== "undefined" && acUpdateStatus) {
        Swal.fire({
            icon: acUpdateStatus === "success" ? "success" : "error",
            title: acUpdateStatus === "success" ? "Update Successful" : "Update Failed",
            text: acUpdateText || ""
        });
    }

    // 2. Table row → detail panel / modal
    const rows     = document.querySelectorAll(".ac-item-table tbody .ac-item-row");
    const overlay  = document.getElementById("acItemModalOverlay");
    const closeBtn = document.getElementById("acModalClose");

    if (!rows.length) { return; }

    function setField(id, val, fallbackDash = true) {
        const el = f(id);
        if (!el) return;

        const value = (val !== undefined && val !== null && val !== "")
            ? val
            : (fallbackDash ? "-" : "");

        if (el.tagName === "INPUT" || el.tagName === "TEXTAREA" || el.tagName === "SELECT") {
            el.value = value;
        } else {
            el.textContent = value;
        }
    }

    function fillPanel(ds) {
        if (f("acDetailTitle")) {
            f("acDetailTitle").textContent = (ds.itemCode || "") + (ds.productName ? " - " + ds.productName : "");
        }
        if (f("acDetailSubtitle")) {
            f("acDetailSubtitle").textContent = (ds.group || "") + (ds.type ? " | " + ds.type : "");
        }

        const itemHidden = f("acDetailItemCodeHidden");
        if (itemHidden) itemHidden.value = ds.itemCode || "";

        const uomHidden = f("acDetailUOMHidden");
        if (uomHidden) uomHidden.value = ds.uom || "";

        // Basic info
        setField("acDetailProductName", ds.productName);
        setField("acDetailGroup",       ds.group);
        setField("acDetailType",        ds.type);
        setField("acDetailUOM",         ds.uom);
        setField("acDetailPrice",       ds.price);

        // dropdowns use T / F values from data-isactive / data-stockcontrol
        const stockFlag  = ds.stockcontrol || "T";
        const activeFlag = ds.isactive || "T";

        setField("acDetailStockStatus", stockFlag, false);
        setField("acDetailStatus",      activeFlag, false);

        // Editable fields
        setField("acDetailDesc2",       ds.desc2, false);
        setField("acDetailBrand",       ds.brand, false);
        setField("acDetailCategory",    ds.category, false);
        setField("acDetailLeadTime",    ds.leadtime, false);
        setField("acDetailBarcode",     ds.barcode, false);
        setField("acDetailBonus",       ds.bonus, false);
        setField("acDetailSupplier",    ds.supplier, false);

        let weight = ds.weight || "";
        setField("acDetailWeight", weight, false);
    }

    function fillModal(ds) {
        if (f("acModalTitle")) {
            f("acModalTitle").textContent = (ds.itemCode || "") + (ds.productName ? " - " + ds.productName : "");
        }
        if (f("acModalSubtitle")) {
            f("acModalSubtitle").textContent = (ds.group || "") + (ds.type ? " | " + ds.type : "");
        }

        setField("acModalProductName", ds.productName);
        setField("acModalGroup",       ds.group);
        setField("acModalType",        ds.type);
        setField("acModalUOM",         ds.uom);
        setField("acModalPrice",       ds.price);
        setField("acModalStockStatus", ds.stockStatus);
        setField("acModalStatus",      ds.status);

        setField("acModalDesc2",       ds.desc2, false);
        setField("acModalBrand",       ds.brand, false);
        setField("acModalCategory",    ds.category, false);
        setField("acModalLeadTime",    ds.leadtime, false);
        setField("acModalBarcode",     ds.barcode, false);
        setField("acModalBonus",       ds.bonus, false);
        setField("acModalSupplier",    ds.supplier, false);

        let weight  = ds.weight || "";
        let weightU = ds.weightUom || "";
        if (f("acModalWeight")) {
            f("acModalWeight").textContent = weight ? weight + (weightU ? " " + weightU : "") : "";
        }
    }

    function applyRow(row, opts) {
        const showModal = opts && opts.showModal;
        const ds = row.dataset;

        rows.forEach(r => r.classList.remove("is-selected"));
        row.classList.add("is-selected");

        fillPanel(ds);
        fillModal(ds);

        if (showModal && isMobile() && overlay) {
            overlay.style.display = "flex";
        }
    }

    rows.forEach(function(row) {
        row.addEventListener("click", function () {
            applyRow(row, { showModal: true });
        });
    });

    if (!isMobile() && rows.length > 0) {
        applyRow(rows[0], { showModal: false });
    }

    function closeModal() {
        if (overlay) {
            overlay.style.display = "none";
        }
    }

    if (closeBtn) {
        closeBtn.addEventListener("click", closeModal);
    }
    if (overlay) {
        overlay.addEventListener("click", function(e) {
            if (e.target === overlay) {
                closeModal();
            }
        });
    }

    mq.addEventListener("change", function() {
        if (!isMobile()) {
            closeModal();
        }
    });

    // 3. SweetAlert2 confirm on update
    const detailForm = document.getElementById("acDetailForm");
    if (detailForm && typeof Swal !== "undefined") {
        detailForm.addEventListener("submit", function(e) {
            e.preventDefault();

            Swal.fire({
                title: "Confirm update?",
                text: "Are you sure you want to save these changes for this item?",
                icon: "warning",
                showCancelButton: true,
                confirmButtonText: "Yes, save",
                cancelButtonText: "Cancel"
            }).then((result) => {
                if (result.isConfirmed) {
                    detailForm.submit();
                }
            });
        });
    }
});
</script>

<script>
// Prevent letters inside the price field
document.addEventListener("DOMContentLoaded", function () {
    const priceInput = document.getElementById("acDetailPrice");

    if (priceInput) {
        priceInput.addEventListener("input", function () {
            // Allow only digits, dot, and minus
            this.value = this.value.replace(/[^0-9.]/g, "");
        });
    }
});
</script>�w�h)�Y����������
�?�<?php
// Get connection
$conn = get_mssql_2019();

if (!$conn) {
    echo "<p style='color:red'>Database connection error.</p>";
    return;
}

// ─────────────────────────────────────────────
//  Search handling
// ─────────────────────────────────────────────
$search = isset($_GET['ac_q']) ? $_GET['ac_q'] : '';

$where     = '';
$params    = [];
$topClause = ($search === '') ? 'TOP 100' : ''; // 👉 Only first 100 when no search

if ($search !== '') {
    $where = "
    WHERE 
        REPLACE(REPLACE(REPLACE(REPLACE(LOWER(i.ItemCode),'-',''),' ',''),'/',''),':','') 
            LIKE REPLACE(REPLACE(REPLACE(REPLACE(LOWER(?),'-',''),' ',''),'/',''),':','')
     OR LOWER(i.Description) LIKE LOWER(?)
     OR LOWER(i.Desc2)       LIKE LOWER(?)
    ";

    $likeClean = '%' . strtolower(preg_replace('/[-\/:\s]/', '', $search)) . '%';
    $likeText  = '%' . strtolower($search) . '%';

    $params = [$likeClean, $likeText, $likeText];
}

// ─────────────────────────────────────────────
//  Main query (TOP 100 only when no search)
// ─────────────────────────────────────────────
$sqlSelect = "
    SELECT $topClause
        i.ItemCode,
        i.Description,
        i.Desc2,
        i.ItemGroup,
        i.ItemType,
        i.ItemBrand,
        i.ItemCategory,
        i.LeadTimeDay,
        i.IsCalcBonusPoint,
        i.MainSupplier,
        i.IsActive,
        i.StockControl,
        u.UOM,
        u.Price,
        u.BarCode,
        u.Weight,
        u.WeightUOM,
        u.Volume,
        u.VolumeUOM,
        u.Shelf
    FROM dbo.Item i
    LEFT JOIN dbo.ItemUOM u
        ON u.ItemCode = i.ItemCode
    $where
    ORDER BY i.ItemCode ASC
";

$stmtSelect = sqlsrv_query($conn, $sqlSelect, $params);

if ($stmtSelect === false) {
    echo "<pre>Select Failed:\n" . print_r(sqlsrv_errors(), true) . "</pre>";
    return;
}

// ─────────────────────────────────────────────
//  One-time CSS
// ─────────────────────────────────────────────
if (!defined('AC_ITEM_LAYOUT_CSS')) {
    define('AC_ITEM_LAYOUT_CSS', true);
    echo '
    <style>
      .ac-page-layout {
          display: flex;
          flex-direction: column;
          height: 100vh;          /* tuned for your WP header 73 */
          max-height: 100vh;
          box-sizing: border-box;
      }
      .ac-top-bar {
          flex: 0 0 auto;
          padding: 12px 16px;
          background: #ffffff;
          border-bottom: 1px solid #e5e7eb;
      }
      .ac-top-bar h2 {
          margin: 0 0 8px;
          font-size: 18px;
          font-weight: 600;
          color: #111827;
      }
      .ac-search-row {
          display: flex;
          flex-wrap: wrap;
          gap: 8px;
          align-items: center;
      }
      .ac-table-wrapper {
          flex: 1 1 auto;
          min-height: 0;
          overflow: auto;             /* 👉 table scrolls */
          background: #f3f4f6;
          padding: 12px 16px;
      }
      .ac-item-table {
          width: 100%;
          border-collapse: collapse;
          background: #ffffff;
          border-radius: 8px;
          overflow: hidden;
          font-size: 14px;
      }
      .ac-item-table thead {
          background: #059669; /* green */
          color: #ffffff;
      }
      .ac-item-table th,
      .ac-item-table td {
          padding: 6px 8px;
          border-bottom: 1px solid #e5e7eb;
          border-right: 1px solid #e5e7eb;
          white-space: nowrap;
      }
      .ac-item-table th:last-child,
      .ac-item-table td:last-child {
          border-right: none;
      }
      .ac-item-row {
          cursor: pointer;
      }
      .ac-item-row:nth-child(even) {
          background: #f9fafb;
      }
      .ac-item-row:hover {
          background: #e0f2fe;
      }
      .ac-item-row.is-selected {
          background: #d1fae5 !important; /* soft green */
      }

      .ac-detail-panel {
          flex: 0 0 auto;
          padding: 12px 16px 16px;
          background: #f9fafb;
          border-top: 1px solid #e5e7eb;
      }
      .ac-detail-header {
          display: flex;
          flex-direction: column;
          gap: 2px;
          margin-bottom: 8px;
      }
      .ac-detail-title {
          font-size: 16px;
          font-weight: 600;
          color: #111827;
      }
      .ac-detail-subtitle {
          font-size: 13px;
          color: #6b7280;
      }

      .ac-detail-grid {
          display: grid;
          grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
          gap: 8px;
      }
      .ac-detail-cell {
          background: #ffffff;
          border-radius: 10px;
          padding: 8px 10px;
          border: 1px solid #e5e7eb;
      }
      .ac-detail-label {
          font-size: 11px;
          text-transform: uppercase;
          letter-spacing: 0.04em;
          color: #6b7280;
          margin-bottom: 2px;
      }
      .ac-detail-value {
          font-size: 13px;
          color: #111827;
          min-height: 1.2em;
      }

      .ac-search-input {
          padding: 6px 10px;
          min-width: 260px;
          border-radius: 6px;
          border: 1px solid #d1d5db;
          font-size: 14px;
      }
      .ac-search-input:focus {
          outline: none;
          border-color: #059669;
          box-shadow: 0 0 0 1px #05966933;
      }
      .ac-btn {
          padding: 6px 14px;
          border-radius: 6px;
          border: 1px solid transparent;
          font-size: 14px;
          cursor: pointer;
      }
      .ac-btn-primary {
          background: #059669;
          color: #ffffff;
          border-color: #059669;
      }
      .ac-btn-primary:hover {
          background: #047857;
      }
      .ac-btn-secondary {
          background: #f3f4f6;
          color: #111827;
          border-color: #d1d5db;
      }
      .ac-btn-secondary:hover {
          background: #e5e7eb;
      }

      /* Mobile: hide bottom panel, we will use popup instead */
      @media (max-width: 767px) {
        .ac-detail-panel {
            display: none;
        }
      }

      /* Popup (mobile) */
      .ac-modal-overlay {
          position: fixed;
          inset: 0;
          background: rgba(0,0,0,0.45);
          z-index: 9999;
          display: none;               /* JS will set to flex on mobile */
          align-items: flex-end;       /* bottom sheet style */
          justify-content: center;
      }
      .ac-modal {
          background: #ffffff;
          width: 100%;
          max-width: 480px;
          max-height: 80vh;
          border-radius: 16px 16px 0 0;
          padding: 14px 16px 18px;
          box-shadow: 0 -8px 25px rgba(0,0,0,0.25);
          overflow-y: auto;
      }
      .ac-modal-close {
          position: absolute;
          right: 14px;
          top: 8px;
          border: none;
          background: none;
          font-size: 20px;
          cursor: pointer;
      }
      .ac-modal-header-title {
          font-size: 15px;
          font-weight: 600;
          margin: 0 0 2px;
      }
      .ac-modal-header-subtitle {
          font-size: 12px;
          color: #6b7280;
          margin: 0 0 10px;
      }
      .ac-modal-grid {
          display: grid;
          grid-template-columns: 1fr;
          gap: 8px;
      }
      .ac-modal-cell {
          background: #f9fafb;
          border-radius: 10px;
          padding: 8px 10px;
          border: 1px solid #e5e7eb;
      }
      .ac-modal-label {
          font-size: 11px;
          text-transform: uppercase;
          letter-spacing: 0.04em;
          color: #6b7280;
          margin-bottom: 2px;
      }
      .ac-modal-value {
          font-size: 13px;
          color: #111827;
          min-height: 1.2em;
      }
    </style>
    ';
}

// ─────────────────────────────────────────────
//  Layout start
// ─────────────────────────────────────────────
echo '<div class="ac-page-layout">';

// Top: search bar
echo '<div class="ac-top-bar">';
echo '  <h2>Item List</h2>';
echo '  <div class="ac-search-row">';
echo '      <form method="get" class="ac-search-form" style="display:flex; gap:8px; flex-wrap:wrap; margin:0;">';
echo '          <input id="ac_q_input" class="ac-search-input" type="text" name="ac_q" placeholder="Global Search (ItemCode / Description / Desc2)" value="' . htmlspecialchars($search) . '">';

// preserve other query vars
foreach ($_GET as $key => $value) {
    if ($key === "ac_q") continue;
    echo '<input type="hidden" name="'.htmlspecialchars($key).'" value="'.htmlspecialchars($value).'">';
}

echo '          <button type="submit" class="ac-btn ac-btn-primary">Search</button>';
echo '          <button type="button" class="ac-btn ac-btn-secondary"
                        onclick="document.getElementById(\'ac_q_input\').value=\'\'; this.form.submit();">
                    Clear
                </button>';
echo '      </form>';
echo '  </div>';
echo '</div>';

// Middle: table (scroll)
echo '<div class="ac-table-wrapper">';
echo '<table class="ac-item-table">';
echo '  <thead>
            <tr>
                <th>ItemCode</th>
                <th>Product Name</th>
                <th>Group</th>
                <th>Type</th>
                <th>Unit</th>
                <th>Price</th>
                <th>Stock Status</th>
                <th>Status</th>
            </tr>
        </thead>
        <tbody>';

while ($row = sqlsrv_fetch_array($stmtSelect, SQLSRV_FETCH_ASSOC)) {
    $price = is_null($row['Price']) ? '-' : 'RM ' . number_format((float)$row['Price'], 2);

    $statusText  = ($row['IsActive']) ? 'Active' : 'Inactive';
    $stockStatus = ($row['IsActive'] && $row['StockControl'])
        ? 'Available'
        : 'Not available';

    $bonusText = $row['IsCalcBonusPoint'] ? 'Yes' : 'No';

    $weightStr = is_null($row['Weight']) ? '' : (float)$row['Weight'];
    $volumeStr = is_null($row['Volume']) ? '' : (float)$row['Volume'];

    echo '<tr class="ac-item-row"
              data-item-code="'.htmlspecialchars($row['ItemCode']).'"
              data-product-name="'.htmlspecialchars($row['Description']).'"
              data-group="'.htmlspecialchars($row['ItemGroup']).'"
              data-type="'.htmlspecialchars($row['ItemType']).'"
              data-uom="'.htmlspecialchars($row['UOM']).'"
              data-price="'.htmlspecialchars($price).'"
              data-stock-status="'.htmlspecialchars($stockStatus).'"
              data-status="'.htmlspecialchars($statusText).'"
              data-desc2="'.htmlspecialchars($row['Desc2']).'"
              data-brand="'.htmlspecialchars($row['ItemBrand']).'"
              data-category="'.htmlspecialchars($row['ItemCategory']).'"
              data-leadtime="'.htmlspecialchars($row['LeadTimeDay']).'"
              data-barcode="'.htmlspecialchars($row['BarCode']).'"
              data-bonus="'.htmlspecialchars($bonusText).'"
              data-supplier="'.htmlspecialchars($row['MainSupplier']).'"
              data-weight="'.htmlspecialchars($weightStr).'"
              data-weight-uom="'.htmlspecialchars($row['WeightUOM']).'"
              data-volume="'.htmlspecialchars($volumeStr).'"
              data-volume-uom="'.htmlspecialchars($row['VolumeUOM']).'"
              data-shelf="'.htmlspecialchars($row['Shelf']).'">';

    echo '  <td>'.htmlspecialchars($row['ItemCode']).'</td>';
    echo '  <td>'.htmlspecialchars($row['Description']).'</td>';
    echo '  <td>'.htmlspecialchars($row['ItemGroup']).'</td>';
    echo '  <td>'.htmlspecialchars($row['ItemType']).'</td>';
    echo '  <td>'.htmlspecialchars($row['UOM']).'</td>';
    echo '  <td>'.$price.'</td>';
    echo '  <td>'.$stockStatus.'</td>';
    echo '  <td>'.$statusText.'</td>';

    echo '</tr>';
}

echo '  </tbody>';
echo '</table>';
echo '</div>'; // end table wrapper

sqlsrv_free_stmt($stmtSelect);
sqlsrv_close($conn);

// Bottom: detail panel (desktop)
echo '
<div class="ac-detail-panel">
  <div class="ac-detail-header">
    <div class="ac-detail-title" id="acDetailTitle">Item Detail</div>
    <div class="ac-detail-subtitle" id="acDetailSubtitle"></div>
  </div>

  <div class="ac-detail-grid">
    <div class="ac-detail-cell">
      <div class="ac-detail-label">Description</div>
      <div class="ac-detail-value" id="acDetailProductName">-</div>
    </div>
    <div class="ac-detail-cell">
      <div class="ac-detail-label">Item Group</div>
      <div class="ac-detail-value" id="acDetailGroup">-</div>
    </div>
    <div class="ac-detail-cell">
      <div class="ac-detail-label">Item Type</div>
      <div class="ac-detail-value" id="acDetailType">-</div>
    </div>
    <div class="ac-detail-cell">
      <div class="ac-detail-label">Unit</div>
      <div class="ac-detail-value" id="acDetailUOM">-</div>
    </div>
    <div class="ac-detail-cell">
      <div class="ac-detail-label">Price</div>
      <div class="ac-detail-value" id="acDetailPrice">-</div>
    </div>
    <div class="ac-detail-cell">
      <div class="ac-detail-label">Stock Status</div>
      <div class="ac-detail-value" id="acDetailStockStatus">-</div>
    </div>
    <div class="ac-detail-cell">
      <div class="ac-detail-label">Status</div>
      <div class="ac-detail-value" id="acDetailStatus">-</div>
    </div>
    <div class="ac-detail-cell">
      <div class="ac-detail-label">Alternative Name (Desc2)</div>
      <div class="ac-detail-value" id="acDetailDesc2">-</div>
    </div>
    <div class="ac-detail-cell">
      <div class="ac-detail-label">Brand</div>
      <div class="ac-detail-value" id="acDetailBrand">-</div>
    </div>
    <div class="ac-detail-cell">
      <div class="ac-detail-label">Category</div>
      <div class="ac-detail-value" id="acDetailCategory">-</div>
    </div>
    <div class="ac-detail-cell">
      <div class="ac-detail-label">Lead Time (days)</div>
      <div class="ac-detail-value" id="acDetailLeadTime">-</div>
    </div>
    <div class="ac-detail-cell">
      <div class="ac-detail-label">Barcode</div>
      <div class="ac-detail-value" id="acDetailBarcode">-</div>
    </div>
    <div class="ac-detail-cell">
      <div class="ac-detail-label">Bonus Eligible</div>
      <div class="ac-detail-value" id="acDetailBonus">-</div>
    </div>
    <div class="ac-detail-cell">
      <div class="ac-detail-label">Supplier</div>
      <div class="ac-detail-value" id="acDetailSupplier">-</div>
    </div>
    <div class="ac-detail-cell">
      <div class="ac-detail-label">Weight</div>
      <div class="ac-detail-value" id="acDetailWeight">-</div>
    </div>
    <div class="ac-detail-cell">
      <div class="ac-detail-label">Volume</div>
      <div class="ac-detail-value" id="acDetailVolume">-</div>
    </div>
    <div class="ac-detail-cell">
      <div class="ac-detail-label">Shelf Location</div>
      <div class="ac-detail-value" id="acDetailShelf">-</div>
    </div>
  </div>
</div>
';

// Mobile popup markup
echo '
<div id="acItemModalOverlay" class="ac-modal-overlay">
  <div class="ac-modal">
    <button type="button" id="acModalClose" class="ac-modal-close">&times;</button>
    <h3 class="ac-modal-header-title" id="acModalTitle">Item Detail</h3>
    <p class="ac-modal-header-subtitle" i��ҿ�-����������
�&a����d="acModalSubtitle"></p>

    <div class="ac-modal-grid">
      <div class="ac-modal-cell">
        <div class="ac-modal-label">Description</div>
        <div class="ac-modal-value" id="acModalProductName">-</div>
      </div>
      <div class="ac-modal-cell">
        <div class="ac-modal-label">Item Group</div>
        <div class="ac-modal-value" id="acModalGroup">-</div>
      </div>
      <div class="ac-modal-cell">
        <div class="ac-modal-label">Item Type</div>
        <div class="ac-modal-value" id="acModalType">-</div>
      </div>
      <div class="ac-modal-cell">
        <div class="ac-modal-label">Unit</div>
        <div class="ac-modal-value" id="acModalUOM">-</div>
      </div>
      <div class="ac-modal-cell">
        <div class="ac-modal-label">Price</div>
        <div class="ac-modal-value" id="acModalPrice">-</div>
      </div>
      <div class="ac-modal-cell">
        <div class="ac-modal-label">Stock Status</div>
        <div class="ac-modal-value" id="acModalStockStatus">-</div>
      </div>
      <div class="ac-modal-cell">
        <div class="ac-modal-label">Status</div>
        <div class="ac-modal-value" id="acModalStatus">-</div>
      </div>
      <div class="ac-modal-cell">
        <div class="ac-modal-label">Alternative Name (Desc2)</div>
        <div class="ac-modal-value" id="acModalDesc2">-</div>
      </div>
      <div class="ac-modal-cell">
        <div class="ac-modal-label">Brand</div>
        <div class="ac-modal-value" id="acModalBrand">-</div>
      </div>
      <div class="ac-modal-cell">
        <div class="ac-modal-label">Category</div>
        <div class="ac-modal-value" id="acModalCategory">-</div>
      </div>
      <div class="ac-modal-cell">
        <div class="ac-modal-label">Lead Time (days)</div>
        <div class="ac-modal-value" id="acModalLeadTime">-</div>
      </div>
      <div class="ac-modal-cell">
        <div class="ac-modal-label">Barcode</div>
        <div class="ac-modal-value" id="acModalBarcode">-</div>
      </div>
      <div class="ac-modal-cell">
        <div class="ac-modal-label">Bonus Eligible</div>
        <div class="ac-modal-value" id="acModalBonus">-</div>
      </div>
      <div class="ac-modal-cell">
        <div class="ac-modal-label">Supplier</div>
        <div class="ac-modal-value" id="acModalSupplier">-</div>
      </div>
      <div class="ac-modal-cell">
        <div class="ac-modal-label">Weight</div>
        <div class="ac-modal-value" id="acModalWeight">-</div>
      </div>
      <div class="ac-modal-cell">
        <div class="ac-modal-label">Volume</div>
        <div class="ac-modal-value" id="acModalVolume">-</div>
      </div>
      <div class="ac-modal-cell">
        <div class="ac-modal-label">Shelf Location</div>
        <div class="ac-modal-value" id="acModalShelf">-</div>
      </div>
    </div>
  </div>
</div>
';

echo '</div>'; // end page-layout

// ─────────────────────────────────────────────
//  JS – row click → desktop bottom panel OR mobile popup
// ─────────────────────────────────────────────
echo '
<script>
document.addEventListener("DOMContentLoaded", function () {
    const rows = document.querySelectorAll(".ac-item-table tbody .ac-item-row");
    if (!rows.length) { return; }

    const overlay  = document.getElementById("acItemModalOverlay");
    const closeBtn = document.getElementById("acModalClose");

    const f  = function(id){ return document.getElementById(id); };
    const mq = window.matchMedia("(max-width: 767px)");
    const isMobile = () => mq.matches;

    function fillPanel(ds) {
        if (f("acDetailTitle"))       f("acDetailTitle").textContent   = (ds.itemCode || "") + (ds.productName ? " - " + ds.productName : "");
        if (f("acDetailSubtitle"))    f("acDetailSubtitle").textContent= (ds.group || "") + (ds.type ? " | " + ds.type : "");

        if (f("acDetailProductName")) f("acDetailProductName").textContent = ds.productName || "-";
        if (f("acDetailGroup"))       f("acDetailGroup").textContent       = ds.group || "-";
        if (f("acDetailType"))        f("acDetailType").textContent        = ds.type || "-";
        if (f("acDetailUOM"))         f("acDetailUOM").textContent         = ds.uom || "-";
        if (f("acDetailPrice"))       f("acDetailPrice").textContent       = ds.price || "-";
        if (f("acDetailStockStatus")) f("acDetailStockStatus").textContent = ds.stockStatus || "-";
        if (f("acDetailStatus"))      f("acDetailStatus").textContent      = ds.status || "-";

        if (f("acDetailDesc2"))       f("acDetailDesc2").textContent       = ds.desc2 || "";
        if (f("acDetailBrand"))       f("acDetailBrand").textContent       = ds.brand || "";
        if (f("acDetailCategory"))    f("acDetailCategory").textContent    = ds.category || "";
        if (f("acDetailLeadTime"))    f("acDetailLeadTime").textContent    = ds.leadtime || "";
        if (f("acDetailBarcode"))     f("acDetailBarcode").textContent     = ds.barcode || "";
        if (f("acDetailBonus"))       f("acDetailBonus").textContent       = ds.bonus || "";
        if (f("acDetailSupplier"))    f("acDetailSupplier").textContent    = ds.supplier || "";

        let weight  = ds.weight || "";
        let weightU = ds.weightUom || "";
        if (f("acDetailWeight")) {
            f("acDetailWeight").textContent = weight ? weight + (weightU ? " " + weightU : "") : "";
        }

        let volume  = ds.volume || "";
        let volumeU = ds.volumeUom || "";
        if (f("acDetailVolume")) {
            f("acDetailVolume").textContent = volume ? volume + (volumeU ? " " + volumeU : "") : "";
        }

        if (f("acDetailShelf")) {
            f("acDetailShelf").textContent = ds.shelf || "";
        }
    }

    function fillModal(ds) {
        if (f("acModalTitle"))    f("acModalTitle").textContent    = (ds.itemCode || "") + (ds.productName ? " - " + ds.productName : "");
        if (f("acModalSubtitle")) f("acModalSubtitle").textContent = (ds.group || "") + (ds.type ? " | " + ds.type : "");

        if (f("acModalProductName")) f("acModalProductName").textContent = ds.productName || "-";
        if (f("acModalGroup"))       f("acModalGroup").textContent       = ds.group || "-";
        if (f("acModalType"))        f("acModalType").textContent        = ds.type || "-";
        if (f("acModalUOM"))         f("acModalUOM").textContent         = ds.uom || "-";
        if (f("acModalPrice"))       f("acModalPrice").textContent       = ds.price || "-";
        if (f("acModalStockStatus")) f("acModalStockStatus").textContent = ds.stockStatus || "-";
        if (f("acModalStatus"))      f("acModalStatus").textContent      = ds.status || "-";

        if (f("acModalDesc2"))       f("acModalDesc2").textContent       = ds.desc2 || "";
        if (f("acModalBrand"))       f("acModalBrand").textContent       = ds.brand || "";
        if (f("acModalCategory"))    f("acModalCategory").textContent    = ds.category || "";
        if (f("acModalLeadTime"))    f("acModalLeadTime").textContent    = ds.leadtime || "";
        if (f("acModalBarcode"))     f("acModalBarcode").textContent     = ds.barcode || "";
        if (f("acModalBonus"))       f("acModalBonus").textContent       = ds.bonus || "";
        if (f("acModalSupplier"))    f("acModalSupplier").textContent    = ds.supplier || "";

        let weight  = ds.weight || "";
        let weightU = ds.weightUom || "";
        if (f("acModalWeight")) {
            f("acModalWeight").textContent = weight ? weight + (weightU ? " " + weightU : "") : "";
        }

        let volume  = ds.volume || "";
        let volumeU = ds.volumeUom || "";
        if (f("acModalVolume")) {
            f("acModalVolume").textContent = volume ? volume + (volumeU ? " " + volumeU : "") : "";
        }

        if (f("acModalShelf")) {
            f("acModalShelf").textContent = ds.shelf || "";
        }
    }

    function applyRow(row, opts) {
        const showModal = opts && opts.showModal;
        const ds = row.dataset;

        // Highlight selected
        rows.forEach(r => r.classList.remove("is-selected"));
        row.classList.add("is-selected");

        // Always fill desktop panel (even if hidden on mobile)
        fillPanel(ds);

        // Fill modal fields
        fillModal(ds);

        // Open modal only on mobile + when requested
        if (showModal && isMobile() && overlay) {
            overlay.style.display = "flex";
        }
    }

    // Click handlers
    rows.forEach(function(row) {
        row.addEventListener("click", function () {
            applyRow(row, { showModal: true });
        });
    });

    // Auto-select first row on desktop only (no popup)
    if (!isMobile()) {
        applyRow(rows[0], { showModal: false });
    }

    function closeModal() {
        if (overlay) {
            overlay.style.display = "none";
        }
    }

    if (closeBtn) {
        closeBtn.addEventListener("click", closeModal);
    }
    if (overlay) {
        overlay.addEventListener("click", function(e){
            if (e.target === overlay) {
                closeModal();
            }
        });
    }

    // If orientation / width changes (rotate phone), you can adjust behaviour if needed
    mq.addEventListener("change", function() {
        // On switching to desktop, close modal if open
        if (!isMobile()) {
            closeModal();
        }
    });
});
</script>
';���NF���������L3
�?�	<?php
// ─────────────────────────────────────────────
// 1) GET DEBTORS
// ─────────────────────────────────────────────
if (!function_exists('wp_ac_get_debtors')) {
    function wp_ac_get_debtors()
    {
        $conn = get_mssql_2016();
        if (!$conn) return [];

        $sql = "
            SELECT DebtorCode, CompanyName
            FROM WPINT.vDebtorList
            WHERE IsActive = 'T'
            ORDER BY DebtorCode
        ";

        $stmt = sqlsrv_query($conn, $sql);

        if (!$stmt) {
            // Show error ONLY to admins
            if (function_exists('current_user_can') && current_user_can('manage_options')) {
                echo '<pre style="background:#fff3cd;border:1px solid #ffeeba;padding:10px;border-radius:8px;white-space:pre-wrap">';
                echo "Debtor query failed:\n";
                print_r(sqlsrv_errors(SQLSRV_ERR_ERRORS));
                echo "</pre>";
            }
            return [];
        }

        $rows = [];
        while ($r = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
            $rows[] = $r;
        }
        return $rows;
    }
}

// ─────────────────────────────────────────────
// 2) POST SALES ORDER (STAGING + SP)
// ─────────────────────────────────────────────
if (!function_exists('wp_ac_post_sales_order')) {
    function wp_ac_post_sales_order($debtorCode, $docDateYmd, $remark, $lines)
    {
        $conn = get_mssql_2016();
        if (!$conn) return ['ok' => false, 'error' => 'DB connection failed'];

        $debtorCode = trim((string) $debtorCode);
        $docDateYmd = trim((string) $docDateYmd);
        $remark     = (string) $remark;

        if ($debtorCode === '' || $docDateYmd === '') {
            return ['ok' => false, 'error' => 'DebtorCode/DocDate is required'];
        }
        if (!is_array($lines) || count($lines) < 1) {
            return ['ok' => false, 'error' => 'At least 1 line is required'];
        }

        // Idempotency key: prevents duplicates
        $externalRefNo = 'WP-SO-' . gmdate('Ymd-His') . '-' . wp_generate_password(6, false, false);

        sqlsrv_begin_transaction($conn);

        try {
            // Insert stage header & get inserted Id
            $sqlH = "
                INSERT INTO WPINT.SoStageHeader (ExternalRefNo, DebtorCode, DocDate, Remark)
                OUTPUT INSERTED.Id AS NewId
                VALUES (?, ?, ?, ?);
            ";

            $stmtH = sqlsrv_query($conn, $sqlH, [$externalRefNo, $debtorCode, $docDateYmd, $remark]);
            if (!$stmtH) {
                $errs = sqlsrv_errors(SQLSRV_ERR_ERRORS);
                throw new Exception('Insert stage header failed: ' . print_r($errs, true));
            }

            $rowH = sqlsrv_fetch_array($stmtH, SQLSRV_FETCH_ASSOC);
            $headerId = (int) ($rowH['NewId'] ?? 0);
            if ($headerId <= 0) {
                throw new Exception('Failed to get stage header id');
            }

            // Insert stage lines
            $sqlL = "
                INSERT INTO WPINT.SoStageLine (HeaderId, [LineNo], ItemCode, Qty, UnitPrice, UOM, Remark)
                VALUES (?, ?, ?, ?, ?, ?, ?);
            ";

            $lineNo = 1;
            foreach ($lines as $ln) {
                $itemCode  = trim((string) ($ln['itemCode'] ?? ''));
                $qty       = (int) ($ln['qty'] ?? 0);
                $unitPrice = (float) ($ln['unitPrice'] ?? 0);
                $uom       = isset($ln['uom']) ? trim((string) $ln['uom']) : '';
                $lnRemark  = (string) ($ln['remark'] ?? '');

                if ($itemCode === '' || $qty <= 0) {
                    throw new Exception('Invalid line: ItemCode required and Qty must be > 0');
                }

                $uomParam = ($uom === '') ? null : $uom;

                $ok = sqlsrv_query($conn, $sqlL, [$headerId, $lineNo, $itemCode, $qty, $unitPrice, $uomParam, $lnRemark]);
                if (!$ok) {
                    $errs = sqlsrv_errors(SQLSRV_ERR_ERRORS);
                    throw new Exception('Insert stage line failed: ' . print_r($errs, true));
                }

                $lineNo++;
            }

            // Execute posting SP
            $stmtP = sqlsrv_query($conn, "EXEC WPINT.PostSalesOrderFromStage @ExternalRefNo = ?", [$externalRefNo]);
            if (!$stmtP) {
                throw new Exception('Execute PostSalesOrderFromStage failed');
            }

            $res = sqlsrv_fetch_array($stmtP, SQLSRV_FETCH_ASSOC);

            sqlsrv_commit($conn);

            return [
                'ok'            => true,
                'externalRefNo'  => $externalRefNo,
                'docNo'          => $res['NewDocNo'] ?? null,
                'docKey'         => $res['NewDocKey'] ?? null,
            ];
        } catch (Throwable $e) {
            sqlsrv_rollback($conn);
            return ['ok' => false, 'error' => $e->getMessage()];
        }
    }
}

// ─────────────────────────────────────────────
// 3) FORM HANDLER
// ─────────────────────────────────────────────
$errors  = [];
$success = null;

if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['ac_so_submit'])) {
    // Basic CSRF (WordPress nonce)
    if (!isset($_POST['_wpnonce']) || !wp_verify_nonce($_POST['_wpnonce'], 'ac_so_submit')) {
        $errors[] = 'Security check failed. Please refresh and try again.';
    } else {
        $debtorCode = $_POST['debtorCode'] ?? '';
        $docDate    = $_POST['docDate'] ?? '';
        $remark     = $_POST['remark'] ?? '';

        // Selected item comes from hidden fields (filled by JS)
        $itemCode  = trim((string) ($_POST['itemCode'] ?? ''));
        $uom       = trim((string) ($_POST['uom'] ?? ''));
        $priceRaw  = $_POST['unitPrice'] ?? '';
        $qtyRaw    = $_POST['qty'] ?? '';

        $priceNum = is_numeric($priceRaw) ? (float) $priceRaw : 0;
        $qtyNum   = is_numeric($qtyRaw) ? (int) $qtyRaw : 0;

        if ($itemCode === '') $errors[] = 'Please select an item.';
        if ($qtyNum <= 0)     $errors[] = 'Qty must be an integer > 0';

        if (!$errors) {
            $result = wp_ac_post_sales_order(
                $debtorCode,
                $docDate,
                $remark,
                [[
                    'itemCode'   => $itemCode,
                    'qty'        => $qtyNum,
                    'unitPrice'  => $priceNum,
                    'uom'        => $uom,
                    'remark'     => '',
                ]]
            );

            if (!empty($result['ok'])) {
                $success = $result;
            } else {
                $errors[] = $result['error'] ?? 'Unknown error';
            }
        }
    }
}

$debtors = wp_ac_get_debtors();
?>

<div class="ac-so-wrap">
    <h3 class="ac-so-title">Create Sales Order (AutoCount)</h3>

    <?php if ($errors): ?>
        <div class="ac-so-msg ac-so-err">
            <?php echo implode('<br>', array_map('esc_html', $errors)); ?>
        </div>
    <?php endif; ?>

    <?php if ($success): ?>
        <div class="ac-so-msg ac-so-ok">
            ✅ Posted to AutoCount! <b>DocNo:</b> <?php echo esc_html($success['docNo'] ?? '-'); ?><br>
            <small><b>ExternalRefNo:</b> <?php echo esc_html($success['externalRefNo'] ?? '-'); ?></small>
        </div>
    <?php endif; ?>

    <form method="post" class="ac-so-form">
        <?php wp_nonce_field('ac_so_submit'); ?>

        <div class="ac-so-row">
            <div>
                <div class="ac-so-label">Debtor Code</div>
                <select class="ac-so-input" name="debtorCode" required>
                    <option value="">-- Select Debtor --</option>
                    <?php foreach ($debtors as $d): ?>
                        <?php
                            $code = $d['DebtorCode'];
                            $name = $d['CompanyName'];
                            $selected = (isset($_POST['debtorCode']) && $_POST['debtorCode'] === $code) ? 'selected' : '';
                        ?>
                        <option value="<?php echo esc_attr($code); ?>" <?php echo $selected; ?>>
                            <?php echo esc_html($code . ' — ' . $name); ?>
                        </option>
                    <?php endforeach; ?>
                </select>

                <small class="ac-so-muted">Debtors loaded: <?php echo count($debtors); ?></small>
            </div>

            <div>
                <div class="ac-so-label">Doc Date</div>
                <input
                    class="ac-so-input"
                    type="date"
                    name="docDate"
                    value="<?php echo esc_attr($_POST['docDate'] ?? date('Y-m-d')); ?>"
                    required
                >
            </div>
        </div>

        <div class="ac-so-row one">
            <div>
                <div class="ac-so-label">Remark</div>
                <input class="ac-so-input" name="remark" value="<?php echo esc_attr($_POST['remark'] ?? ''); ?>">
            </div>
        </div>

        <div class="ac-so-divider"></div>

        <div class="ac-so-row">
            <div>
                <div class="ac-so-label">Item Code (type to search)</div>

                <input
                    class="ac-so-input"
                    id="ac_item_search"
                    placeholder="Type ItemCode e.g. P or PSO..."
                    autocomplete="off"
                >

                <div id="ac_item_results" class="ac-so-results" style="display:none"></div>

                <small class="ac-so-muted" id="ac_item_hint">
                    Start typing ItemCode (prefix search). Example: <b>P</b> shows items starting with P; <b>PSO</b> narrows faster.
                </small>

                <!-- Hidden real fields used for posting -->
                <input type="hidden" name="itemCode" id="ac_itemCode" value="<?php echo esc_attr($_POST['itemCode'] ?? ''); ?>">
                <input type="hidden" name="uom" id="ac_uom" value="<?php echo esc_attr($_POST['uom'] ?? ''); ?>">
                <input type="hidden" name="unitPrice" id="ac_unitPrice" value="<?php echo esc_attr($_POST['unitPrice'] ?? ''); ?>">
            </div>

            <div class="ac-so-selected-panel">
                <div class="ac-so-label">Selected Item</div>
                <input class="ac-so-input" id="ac_item_selected" value="" readonly>

                <div class="ac-so-label" style="margin-top:10px">UOM (auto)</div>
                <input class="ac-so-input" id="ac_uom_show" value="" readonly>

                <div class="ac-so-label" style="margin-top:10px">Unit Price (RM) (auto)</div>
                <input class="ac-so-input" id="ac_price_show" value="" readonly>
            </div>
        </div>

        <div class="ac-so-row">
            <div>
                <div class="ac-so-label">Qty</div>
                <input
                    class="ac-so-input"
                    type="number"
                    name="qty"
                    min="1"
                    step="1"
                    value="<?php echo esc_attr($_POST['qty'] ?? '1'); ?>"
                    required
                >
            </div>
            <div></div>
        </div>

        <button class="ac-so-btn primary" type="submit" name="ac_so_submit" value="1">
            Post Sales Order
        </button>
    </form>

    <p class="ac-so-footnote">
        This posts via WPINT staging + stored procedure. No direct write to SO/SODTL.
    </p>
</div>

<script>
(function () {
    const ajaxUrl = "<?php echo admin_url('admin-ajax.php'); ?>";
    const nonce   = "<?php echo wp_create_nonce('ac_item_search'); ?>";

    const inp = document.getElementById('ac_item_search');
    const box = document.getElementById('ac_item_results');

    const hCode = document.getElementById('ac_itemCode');
    const hUom  = document.getElementById('ac_uom');
    const hPr   = document.getElementById('ac_unitPrice');

    const showSel = document.getElementById('ac_item_selected');
    const showUom = document.getElementById('ac_uom_show');
    const showPr  = document.getElementById('ac_price_show');

    function fmtRM(n) {
        const x = Number(n || 0);
        return 'RM ' + x.toFixed(2);
    }

    function render(items) {
        box.innerHTML = '';

        if (!items || !items.length) {
            box.style.display = 'none';
            return;
        }

        const frag = document.createDocumentFragment();

        items.forEach((it, idx) => {
            const div = document.createElement('div');
            div.className = 'ac-so-result-item';
            div.setAttribute('role', 'button');
            div.setAttribute('tabindex', '0');
            div.dataset.index = String(idx);

            div.innerHTML = `
                <div class="ac-so-result-code">${it.ItemCode || ''}</div>
                <div class="ac-so-result-desc">${it.Description || ''}</div>
            `;

            function pick() {
                hCode.value = it.ItemCode || '';
                hUom.value  = it.UOM || '';
                hPr.value   = (it.Price ?? 0);

                showSel.value = `${it.ItemCode || ''} — ${it.Description || ''}`;
                showUom.value = it.UOM || '';
                showPr.value  = fmtRM(it.Price ?? 0);

                box.style.display = 'none';
            }

            div.addEventListener('click', pick);
            div.addEventListener('keydown', (e) => {
                if (e.key === 'Enter' || e.key === ' ') {
                    e.preventDefault();
                    pick();
                }
            });

            frag.appendChild(div);
        });

        box.appendChild(frag);
        box.style.display = 'block';
    }

    let t = null;

    async function search() {
        const q = (inp.value || '')
            .toUpperCase()
            .replace(/[ \-\/()'+]/g, '') // ignore whitespace, -, /, (, ), ', +
            .trim();

        if (!q || q.length < 1) {
            render([]);
            return;
        }

        const form = new FormData();
        form.append('action', 'ac_item_search');
        form.append('nonce', nonce);
        form.append('q', q);

        let txt = '';

        try {
            const res = await fetch(ajaxUrl, { method: 'POST', body: form });
            txt = await res.text();

            // If handler not registered, WP returns "0"
            if (txt.trim() === '0') {
                console.error('AJAX returned 0 (handler not registered / snippet not global)');
                render([]);
                return;
            }

            const data = JSON.parse(txt);

            if (data && data.success) {
                render(data.data.items || []);
            } else {
                console.error('AJAX error:', data);
                render([]);
            }
        } catch (e) {
            console.error('AJAX failed:', e, txt);
            render([]);
        }
    }

    inp.addEventListener('input', () => {
        clearTimeout(t);
        t = setTimeout(search, 250);
    });

    // close results when clicking outside
    document.addEventListener('click', (e) => {
        if (!box.contains(e.target) && e.target !== inp) {
            box.style.display = 'none';
        }
    });

    // If page reloaded with POST values, show them
    �L3)Ǖ�	���������L3
������if (hCode.value) {
        showSel.value = hCode.value;
        showUom.value = hUom.value || '';
        showPr.value  = fmtRM(hPr.value || 0);
    }
})();
</script>�L3wz�o
����������
�?�<?php
// =====================================================
// SITE / ROUTE CONFIG (EDIT ONLY HERE)
// =====================================================

// Inventory list page
$URL_INVENTORY_LIST = home_url('/index.php/yong_tai_lie_data/');

// Inventory detail (More Info) page
$URL_INVENTORY_DETAIL = home_url('/index.php/yong_tai_lie_data_details/');

// Site root (used for safety checks & back links)
$URL_SITE_ROOT = home_url('/');

// AJAX endpoint (WordPress)
$URL_AJAX = admin_url('admin-ajax.php');

// =========================================================
// AutoCount Inventory Search (SQLSRV) - UI like screenshot
// Requires: get_mssql_2019() returning a valid sqlsrv connection
// =========================================================

// Optional: block public access
// if (!is_user_logged_in()) { echo "<p>Please login.</p>"; return; }

// ---------------------------
// AJAX handler for images (keep your existing implementation)
// ---------------------------
add_action('wp_ajax_ac_get_images', 'ac_ajax_get_images');
add_action('wp_ajax_nopriv_ac_get_images', 'ac_ajax_get_images');

// Your existing image handler – replace with your actual code
function ac_ajax_get_images() {
    // Your implementation here
    wp_send_json([]);
}

// ---------------------------
// ❌ No local ac_itemcode_suggest handler – the Master AJAX handles it.
// ---------------------------

// ---------------------------
// 1) Helpers
// ---------------------------
function ac_h($s) { return htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8'); }

function ac_rtf_to_text($rtf)
{
  $text = (string)$rtf;
  if ($text === '') return '';

  if (stripos($text, '{\\rtf') === false) {
    return trim($text);
  }

  $text = preg_replace_callback("/\\\\'([0-9a-fA-F]{2})/", function ($m) {
    return chr(hexdec($m[1]));
  }, $text);

  $text = preg_replace_callback('/\\\\u(-?\d+)\??/', function ($m) {
    $c = (int)$m[1];
    if ($c < 0) $c += 65536;
    return mb_convert_encoding(pack('n', $c), 'UTF-8', 'UTF-16BE');
  }, $text);

  $text = str_ireplace(['\\par', '\\line', '\\tab'], ["\n", "\n", ' '], $text);

  $text = preg_replace('/\{\\\*?\\\\fonttbl.*?\}/si', '', $text);
  $text = preg_replace('/\{\\\*?\\\\colortbl.*?\}/si', '', $text);
  $text = preg_replace('/\{\\\*?\\\\stylesheet.*?\}/si', '', $text);

  $text = preg_replace('/\\\\[a-zA-Z]+\d* ?/', '', $text);

  $text = str_replace(['{', '}', '\\'], '', $text);

  $lines = array_filter(array_map('trim', explode("\n", $text)), function ($line) {
    if ($line === '') return false;
    if (preg_match('/^;+$/', $line)) return false;
    if (preg_match('/^[A-Za-z]+;[A-Za-z;]*$/', $line)) return false;
    return true;
  });

  $text = implode("\n", $lines);
  $text = preg_replace("/[ \t]+/", ' ', $text);
  $text = preg_replace("/\n{3,}/", "\n\n", $text);

  return trim($text);
}

function ac_get($key, $default = '') { return isset($_GET[$key]) ? trim((string)$_GET[$key]) : $default; }
function ac_like($s) { return '%' . $s . '%'; }

// ---------------------------
// ✅ Stop rendering the whole page during admin-ajax.php
// ---------------------------
if (function_exists('wp_doing_ajax') && wp_doing_ajax()) {
  return;
}

// ✅ Normal page render DB connection
$conn = get_mssql_2019();
if (!$conn) {
  echo "<div style='color:#b91c1c;font-weight:600'>Database connection error (get_mssql_2019).</div>";
  return;
}

// ---------------------------
// 2) Read search inputs
// ---------------------------
$q_itemcode  = ac_get('ac_itemcode');
$q_itemtype  = ac_get('ac_itemtype');
$q_varmodel  = ac_get('ac_varmodel');
$q_qty       = ac_get('ac_qty');
$q_price     = ac_get('ac_price');
$q_desc      = ac_get('ac_desc');
$q_desc2     = ac_get('ac_desc2');

// ✅ FIX: Item Code now lives in advanced fields, so it should trigger + More
$hasAdvancedSearch = ($q_itemcode !== '' || $q_itemtype !== '' || $q_varmodel !== '' || $q_qty !== '' || $q_price !== '');

if (isset($_GET['ac_clear'])) {
  $baseUrl = strtok($_SERVER["REQUEST_URI"], '?');
  echo "<script>location.href=" . json_encode($baseUrl) . ";</script>";
  return;
}

// ---------------------------
// 3) Build WHERE + params
// ---------------------------
$whereParts = [];
$params     = [];

if ($q_itemcode !== '') {
  $cleanItemCode = strtolower($q_itemcode);
  $cleanItemCode = str_replace([' ', '-', '/', '(', ')', '*', '.'], '', $cleanItemCode);

  $globalLike = ac_like($q_itemcode);
  $cleanLike  = ac_like($cleanItemCode);

  $whereParts[] = "
    (
      LOWER(
        REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(ISNULL(i.ItemCode,''),' ',''),'-',''),'/',''),'(',''),')',''),'*',''),'.','')
      ) LIKE ?
      OR ISNULL(i.ItemCode,'') LIKE ?
      OR ISNULL(i.Description,'') LIKE ?
      OR ISNULL(i.ItemType,'') LIKE ?
      OR ISNULL(i.UDF_varModel,'') LIKE ?
      OR CONVERT(varchar(50), ISNULL(qty.TotalQty, 0)) LIKE ?
      OR CONVERT(varchar(50), ISNULL(uom.PlainP1, 0)) LIKE ?
      OR ISNULL(i.Desc2,'') LIKE ?
    )
  ";

  $params[] = $cleanLike;
  $params[] = $globalLike;
  $params[] = $globalLike;
  $params[] = $globalLike;
  $params[] = $globalLike;
  $params[] = $globalLike;
  $params[] = $globalLike;
  $params[] = $globalLike;
}

if ($q_desc !== '')     { $whereParts[] = "ISNULL(i.Description,'') LIKE ?"; $params[] = ac_like($q_desc); }
if ($q_itemtype !== '') { $whereParts[] = "ISNULL(i.ItemType,'') LIKE ?"; $params[] = ac_like($q_itemtype); }
if ($q_varmodel !== '') { $whereParts[] = "ISNULL(i.UDF_varModel,'') LIKE ?"; $params[] = ac_like($q_varmodel); }
if ($q_qty !== '')      { $whereParts[] = "CONVERT(varchar(50), ISNULL(qty.TotalQty, 0)) LIKE ?"; $params[] = ac_like($q_qty); }
if ($q_price !== '')    { $whereParts[] = "CONVERT(varchar(50), ISNULL(uom.PlainP1, 0)) LIKE ?"; $params[] = ac_like($q_price); }
if ($q_desc2 !== '')    { $whereParts[] = "ISNULL(i.Desc2,'') LIKE ?"; $params[] = ac_like($q_desc2); }

$whereSql = '';
if (!empty($whereParts)) $whereSql = "WHERE " . implode(" AND ", $whereParts);

$hasFilter = !empty($whereParts);

// ---------------------------
// 4) Count total rows
// ---------------------------
$needQtyJoinForCount = ($q_itemcode !== '' || $q_qty !== '');
$needUomJoinForCount = ($q_itemcode !== '' || $q_price !== '');

$countSql = "
  SELECT COUNT(1) AS TotalRows
  FROM dbo.Item i
  " . ($needQtyJoinForCount ? "
  OUTER APPLY (
    SELECT SUM(CAST(b.BalQty AS decimal(18,4))) AS TotalQty
    FROM dbo.ItemBatchBalQty b
    WHERE b.ItemCode = i.ItemCode
  ) qty
  " : "") . "
  " . ($needUomJoinForCount ? "
  OUTER APPLY (
    SELECT TOP 1
      u.BarCode,
      u.UOM,
      u.Shelf,
      u.Price AS PlainP1
    FROM dbo.ItemUOM u
    WHERE u.ItemCode = i.ItemCode
    ORDER BY u.UOM
  ) uom
  " : "") . "
  $whereSql
";

$stmtCount = sqlsrv_query($conn, $countSql, $params);
$totalRows = 0;
if ($stmtCount && ($r = sqlsrv_fetch_array($stmtCount, SQLSRV_FETCH_ASSOC))) {
  $totalRows = (int)$r['TotalRows'];
}

// ---------------------------
// 5) Main query
//    ✅ We now fetch BOTH plain + encrypted
// ---------------------------
$topClause = $hasFilter ? "TOP 200" : "TOP 20";

$dataSql = "
SELECT $topClause
  i.ItemCode,
  i.Description,
  i.ItemGroup,
  i.ItemType,
  i.Desc2,
  i.UDF_varLongModel,
  i.UDF_varModel,
  i.Note,

  ISNULL(qty.TotalQty, 0) AS TotalQty,
  ISNULL(loc.TopLocation, '') AS TopLocation,
  ISNULL(uom.Shelf,'') AS ShelfLocation,

  uom.BarCode,
  uom.UOM,

  -- encrypted (char/varchar)
  uom.EncCost  AS Cost,
  uom.EncP1    AS Price,
  uom.EncP2    AS Price2,
  uom.EncP3    AS Price3,
  uom.EncP4    AS Price4,
  uom.EncP5    AS Price5,
  uom.EncP6    AS Price6,

  -- plain (numeric)
  uom.PlainCost AS PlainCost,
  uom.PlainP1   AS PlainPrice,
  uom.PlainP2   AS PlainPrice2,
  uom.PlainP3   AS PlainPrice3,
  uom.PlainP4   AS PlainPrice4,
  uom.PlainP5   AS PlainPrice5,
  uom.PlainP6   AS PlainPrice6

FROM dbo.Item i

OUTER APPLY (
  SELECT SUM(CAST(b.BalQty AS decimal(18,4))) AS TotalQty
  FROM dbo.ItemBatchBalQty b
  WHERE b.ItemCode = i.ItemCode
) qty

OUTER APPLY (
  SELECT TOP 1 b.Location AS TopLocation
  FROM dbo.ItemBatchBalQty b
  WHERE b.ItemCode = i.ItemCode
  ORDER BY b.Location
) loc

OUTER APPLY (
  SELECT TOP 1
    u.UOM,
    u.Shelf,
    u.BarCode,

    -- encrypted fields
    u.UDF_EncryptedCost   AS EncCost,
    u.UDF_EncryptedPrice  AS EncP1,
    u.UDF_EncryptedPrice2 AS EncP2,
    u.UDF_EncryptedPrice3 AS EncP3,
    u.UDF_EncryptedPrice4 AS EncP4,
    u.UDF_EncryptedPrice5 AS EncP5,
    u.UDF_EncryptedPrice6 AS EncP6,

    -- plain fields
    u.Cost  AS PlainCost,
    u.Price AS PlainP1,
    u.Price2 AS PlainP2,
    u.Price3 AS PlainP3,
    u.Price4 AS PlainP4,
    u.Price5 AS PlainP5,
    u.Price6 AS PlainP6

  FROM dbo.ItemUOM u
  WHERE u.ItemCode = i.ItemCode
  ORDER BY
    CASE WHEN u.UOM = i.BaseUOM THEN 0 ELSE 1 END,
    CASE WHEN NULLIF(LTRIM(RTRIM(u.UDF_EncryptedPrice)), '') IS NULL THEN 1 ELSE 0 END,
    u.UOM
) uom

$whereSql
ORDER BY i.ItemCode
";

$stmt = sqlsrv_query($conn, $dataSql, $params);
if (!$stmt) {
  $errs = print_r(sqlsrv_errors(), true);
  echo "<div style='padding:.75rem;margin:.75rem 0;border:.0625rem solid #fecaca;background:#fff1f2;color:#991b1b;font-weight:700;border-radius:.75rem;'>
          Query failed (dataSql).
        </div>";
  echo "<pre style='padding:.75rem;border:.0625rem solid #e5e7eb;background:#fff;border-radius:.75rem;white-space:pre-wrap;'>" . ac_h($errs) . "</pre>";
  return;
}

// ---------------------------
// 6) Buffer rows
// ---------------------------
$rowsArr = [];
while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
  $rowsArr[] = $row;
}

?>
<script>
  window.AC_AJAX_URL = <?= json_encode($URL_AJAX) ?>;
  window.AC_SUG_NONCE = <?= json_encode(wp_create_nonce('ac_itemcode_suggest')) ?>;
  window.AC_IMG_NONCE = <?= json_encode(wp_create_nonce('ac_get_images')) ?>;
</script>

<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;500;600;700&display=swap" rel="stylesheet">

<style>
  :root{
    --bg:#f6f8fc;
    --card:#ffffff;
    --line:#e5eaf2;
    --line2:#cfd8e3;
    --text:#111827;
    --muted:#64748b;
    --brand:#2563eb;
    --brand2:#0f5fd1;
    --info:#0f6f96;
    --soft:#f8fbff;
    --radius:.875rem;
    --radius-sm:.625rem;
    --shadow-soft:0 .5rem 1.25rem rgba(15,23,42,.06);
    --shadow-pop:0 1rem 3rem rgba(15,23,42,.24);
    --ring:0 0 0 .1875rem rgba(37,99,235,.12);
    --fs-base:.75rem;
    --fs-sm:.6875rem;
    --fs-xs:.625rem;
    --fs-lg:.875rem;
    --control-h:1.875rem;
  }

  .ac-wrap,
  .ac-wrap *{
    box-sizing:border-box;
  }

  .ac-wrap{
    position:relative;
    z-index:1;
    width:100%;
    min-width:0;
    font-family:"Nunito", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
    font-size:var(--fs-base);
    line-height:1.35;
    color:var(--text);
    background:var(--bg);
    border:.0625rem solid var(--line2);
    border-radius:var(--radius);
    overflow:hidden;
  }

  .ac-topbar{
    background:var(--card);
    border-bottom:.0625rem solid var(--line);
    position:sticky;
    top:0;
    z-index:50;
  }

  .ac-topbar-head{
    display:flex;
    align-items:center;
    justify-content:space-between;
    gap:.75rem;
    padding:.5rem .75rem;
  }

  .ac-title{display:flex;flex-direction:column;gap:.125rem;min-width:0;padding:0;}
  .ac-title h3,.ac-title .sub{display:none;}

  .ac-iconbtn{
    width:2.5rem;
    height:2.5rem;
    border:.0625rem solid var(--line2);
    background:#fff;
    border-radius:.75rem;
    cursor:pointer;
    display:flex;
    align-items:center;
    justify-content:center;
    padding:0;
    font-size:1.125rem;
    color:var(--text);
  }

  .ac-search{
    border-top:.0625rem solid var(--line);
    padding:.375rem .625rem;
    background:rgba(255,255,255,.92);
    backdrop-filter:blur(.375rem);
    display:none;
  }
  .ac-search.open{display:block;}

  .ac-form{display:grid;grid-template-columns:1fr;gap:.4375rem;}
  /* ✅ FIXED DESKTOP GRID AREAS */
  .ac-form.ac-form-aps{
    display:grid;
    grid-template-columns:minmax(0,1fr) minmax(0,1fr);
    gap:.375rem .5rem;
    align-items:end;
    grid-template-areas:
      "desc desc2"
      "advanced advanced"
      "results results";
  }
  .ac-f-desc{grid-area:desc;}
  .ac-f-supercede{grid-area:desc2;}
  .ac-f-itemcode{grid-area:auto;}

  .ac-advanced-fields{
    grid-area:advanced;
    display:none;
    grid-template-columns:minmax(0,1fr) minmax(0,1fr);
    gap:.375rem .5rem;
    align-items:end;
  }
  .ac-advanced-fields.open{display:grid;}
  .ac-results-head{grid-area:results;}
  .ac-actions{align-items:center;}
  .ac-btn.filter{background:#eff6ff;border-color:#bfdbfe;color:var(--brand);}

  .ac-field,.ac-field-suggest{position:relative;min-width:0;}
  .ac-field label,
  .ac-float > label{
    position:absolute;
    left:.75rem;
    top:.5rem;
    font-size:var(--fs-xs);
    font-weight:700;
    color:var(--muted);
    padding:0 .375rem;
    pointer-events:none;
    transition:all .12s ease;
    opacity:.9;
  }

  .ac-field input,
  .ac-float input,
  .ac-line input,
  .ac-line textarea{
    width:100%;
    border:.0625rem solid var(--line2);
    background:#fff;
    border-radius:.75rem;
    color:var(--text);
    font-family:inherit;
    font-size:var(--fs-base);
    outline:none;
    transition:border-color .15s ease, box-shadow .15s ease, background .15s ease;
  }

  .ac-field input,
  .ac-float input{
    height:var(--control-h);
    padding:.8125rem .5rem .25rem;
  }
  .ac-field.has-clear input{padding-right:2.375rem;}
  .ac-clear-btn{
    position:absolute;
    right:.375rem;
    top:.3125rem;
    width:1.25rem;
    height:1.25rem;
    border:.0625rem solid #bfdbfe;
    background:#eff6ff;
    color:var(--brand);
    border-radius:.375rem;
    cursor:pointer;
    display:none;
    align-items:center;
    justify-content:center;
    padding:0;
    font-size:1rem;
    line-height:1;
    font-family:inherit;
    font-weight:900;
    transition:background .15s ease, border-color .15s ease, color .15s ease, box-shadow .15s ease;
  }
  .ac-clear-btn.show{display:flex;}
  .ac-clear-btn:hover{
    background:#dbeafe;
    border-color:#93c5fd;
    color:var(--brand2);
    box-shadow:0 .25rem .625rem rgba(37,99,235,.16);
  }
  .ac-clear-btn:active{
    background:#bfdbfe;
    transform:scale(.94);
  }
  .ac-clear-wrap{position:relative;width:100%;}
  .ac-clear-wrap input{padding-right:2.375rem !important;}

  .ac-line input{height:1.875rem;padding:.3125rem .5rem;text-align:right;font-variant-numeric:tabular-nums;font-weight:700;}
  .ac-line textarea{min-height:2.25rem;padding:.375rem .5rem;resize:none;line-height:1.35;font-weight:600;white-space:pre-wrap;}

  .ac-field input:hover,
  .ac-float input:hover,
  .ac-line input:hover,
  .ac-line textarea:hover{border-color:#b8c4d4;}

  .ac-field input:focus,
  .ac-float input:focus,
  .ac-line input:focus,
  .ac-line textarea:focus{
    border-color:var(--brand);
    box-shadow:var(--ring);
  }

  @supports(selector(:has(*))){
    .ac-field:has(input:focus) label,
    .ac-field:has(input:not(:placeholder-shown)) label,
    .ac-float:has(input:focus) label,
    .ac-float:has(input:not(:placeholder-shown)) label{
      top:.1875rem;
      font-size:.625rem;
      opacity:1;
    }
  }

  .ac-actions{display:flex;gap:.375rem;flex-wrap:wrap;}
  .ac-btn{
    border:.0625rem solid var(--line2);
    background:#fff;
    padding:.25rem .625rem;
    height:1.75rem;
    border-radius:.625rem;
    cursor:pointer;
    font-weight:800;
    font-size:var(--fs-sm);
    line-height:1;
    transition:filter .15s ease, transform .12s��=ʿ���������4
�?� ease, box-shadow .12s ease;
  }
  .ac-btn:hover{transform:translateY(-.0625rem);box-shadow:0 .5rem 1rem rgba(15,23,42,.10);}
  .ac-btn:active{transform:translateY(0);box-shadow:none;}
  .ac-btn.primary{background:var(--brand);border-color:var(--brand);color:#fff;}
  .ac-btn.secondary{background:#f1f5f9;color:#374151;}

  .ac-results-head{
    grid-column:1 / -1;
    display:flex;
    align-items:center;
    justify-content:space-between;
    gap:.625rem;
    background:transparent;
    border:0;
    margin:0;
    padding:.125rem .25rem 0;
  }
  .ac-results-head .count{font-size:var(--fs-sm);font-weight:700;color:var(--muted);}

  .ac-cards{padding:.75rem;display:grid;grid-template-columns:1fr;gap:.625rem;background:var(--bg);}
  .ac-card{background:var(--card);border:.0625rem solid var(--line2);border-radius:.875rem;padding:.75rem;cursor:pointer;transition:background .15s ease, box-shadow .15s ease;}
  .ac-card:hover{box-shadow:var(--shadow-soft);}
  .ac-card.active{outline:.1875rem solid rgba(37,99,235,.16);border-color:#93c5fd;}
  .ac-card-top{display:flex;align-items:flex-start;justify-content:space-between;gap:.625rem;}
  .ac-code{font-weight:900;font-size:var(--fs-base);color:var(--text);white-space:normal;word-break:break-word;}
  .ac-qty{font-weight:900;font-size:var(--fs-sm);color:var(--text);background:#f3f6ff;border:.0625rem solid #dbeafe;padding:.375rem .625rem;border-radius:999rem;white-space:nowrap;}
  .ac-desc{margin-top:.375rem;font-size:var(--fs-sm);color:#1f2937;white-space:normal;word-break:break-word;}
  .ac-meta{margin-top:.625rem;display:grid;grid-template-columns:1fr 1fr;gap:.5rem;}
  .ac-meta .kv{background:#f9fafb;border:.0625rem solid var(--line);border-radius:.75rem;padding:.5rem .625rem;min-width:0;}
  .ac-meta .k{font-size:var(--fs-xs);color:var(--muted);margin-bottom:.25rem;}
  .ac-meta .v{font-size:var(--fs-sm);color:var(--text);white-space:normal;word-break:break-word;}

  .ac-desktop-aps{display:none;}
  .ac-table-scroll{background:#fff;border:.0625rem solid rgba(148,163,184,.35);border-radius:var(--radius);overflow:hidden;box-shadow:var(--shadow-soft);}
  .ac-table-body{overflow:auto;max-height:40vh;min-height:0;}

  table.ac-table{width:100%;border-collapse:collapse;font-size:var(--fs-sm);table-layout:fixed;}
  .ac-table th,.ac-table td{border-bottom:.0625rem solid #eef2f7;padding:.25rem .375rem;line-height:1.18;vertical-align:top;}
  .ac-table th{position:sticky;top:0;background:linear-gradient(180deg,#f7f9ff,#eef3ff);color:#1f2937;text-align:left;z-index:2;font-size:var(--fs-sm);font-weight:800;}
  .ac-table td{white-space:normal;word-break:break-word;}
  .ac-row{cursor:pointer;transition:background-color .12s ease, box-shadow .12s ease;}
  .ac-row:hover{background:rgba(37,99,235,.06);}
  .ac-row.active{background:rgba(37,99,235,.12);box-shadow:inset .25rem 0 0 rgba(37,99,235,.55);}
  .ac-table th.col-code,.ac-table td.col-code{width:8.5rem;white-space:nowrap;}
  .ac-table th:nth-child(2),.ac-table td:nth-child(2){width:26rem;}
  .ac-table th.col-brand,.ac-table td.col-brand{width:5rem;white-space:nowrap;text-align:center;font-weight:700;}
  .ac-table th:nth-child(4),.ac-table td:nth-child(4){width:22.5rem;}
  .ac-table th.col-qty,.ac-table td.col-qty{width:4.5rem;white-space:nowrap;text-align:right;font-variant-numeric:tabular-nums;}
  .ac-table th.col-price,.ac-table td.col-price{width:5rem;white-space:nowrap;text-align:right;font-variant-numeric:tabular-nums;color:#374151;}
  .ac-table th.col-desc2,.ac-table td.col-desc2{width:27rem;}
  .ac-table td:nth-child(2),.ac-table td.col-desc2,.ac-table td:nth-child(4){overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}

  .ac-bot.ac-bot-mock{display:block;overflow:hidden;}
  .ac-panel-mock{border-radius:var(--radius);overflow:hidden;background:rgba(255,255,255,.94);border:.0625rem solid rgba(148,163,184,.35);box-shadow:var(--shadow-soft);height:auto;}
  .ac-mock-wrap{padding:.4375rem .625rem;overflow:hidden;}
  .ac-mock-title{font-weight:900;font-size:var(--fs-base);color:#111827;margin-bottom:.3125rem;}
  .ac-mock-subtitle{font-weight:900;font-size:var(--fs-sm);color:#111827;margin:.25rem 0 .1875rem;}
  .ac-line{display:grid;grid-template-columns:5.75rem 1fr;gap:.4375rem;align-items:center;margin:.1875rem 0;}
  .ac-line .lbl{font-weight:900;font-size:var(--fs-sm);color:#111827;white-space:nowrap;}
  .ac-line .val{min-width:0;}
  .ac-line-block{align-items:start;}
  .ac-sp-grid-mock{display:grid;grid-template-columns:1fr;gap:.625rem;}
  .ac-float{position:relative;min-width:0;}
  .ac-float .ac-switch{position:relative;left:auto;top:auto;padding:0;}

  .ac-imgbox{margin-top:.625rem;}
  .ac-img-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:.375rem;}
  .ac-img-thumb{position:relative;width:100%;aspect-ratio:1 / 1;max-height:3.5rem;border:.0625rem solid rgba(148,163,184,.35);border-radius:.75rem;background:#fff;overflow:hidden;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:transform .15s ease, box-shadow .15s ease;}
  .ac-img-thumb:hover{transform:translateY(-.0625rem);box-shadow:0 .75rem 1.625rem rgba(15,23,42,.14);}
  .ac-img-thumb:active{transform:translateY(0) scale(.99);}
  .ac-img-thumb img{width:100%;height:100%;object-fit:cover;}
  .ac-img-thumb.empty{background:rgba(255,255,255,.65);color:#6b7280;font-weight:700;font-size:var(--fs-xs);}
  .ac-img-empty{color:#6b7280;font-weight:700;font-size:var(--fs-sm);padding:.625rem;text-align:center;}
  .ac-img-more{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:rgba(17,24,39,.55);color:#fff;font-weight:900;font-size:1rem;letter-spacing:.01875rem;}

  .ac-lightbox{position:fixed;inset:0;background:rgba(17,24,39,.60);display:none;align-items:center;justify-content:center;padding:1rem;}
  .ac-lightbox.open{display:flex;z-index:2147483647 !important;}
  .ac-lightbox-card{position:relative;width:min(92vw,61.25rem);height:min(86vh,47.5rem);background:#fff;border-radius:1rem;overflow:hidden;box-shadow:0 1.125rem 3.75rem rgba(0,0,0,.25);padding-top:.5rem;}
  .ac-lightbox-body{height:calc(100% - 3.25rem);padding:.75rem;overflow:auto;display:flex;align-items:flex-start;justify-content:center;}
  #acLightboxImg{max-width:100%;max-height:100%;object-fit:contain;display:block;}
  .ac-lightbox-card.zoom #acLightboxImg{max-width:none;max-height:none;object-fit:unset;}
  .ac-lightbox-nav{position:absolute;top:50%;transform:translateY(-50%);width:2.5rem !important;height:2.5rem !important;display:flex;align-items:center;justify-content:center;border:0;border-radius:999rem !important;background:rgba(17,24,39,.78) !important;color:#fff !important;box-shadow:0 .625rem 1.5rem rgba(0,0,0,.22) !important;font-size:1.375rem !important;line-height:1;cursor:pointer;z-index:10 !important;}
  .ac-lightbox-nav.prev{left:.75rem !important;}
  .ac-lightbox-nav.next{right:.75rem !important;}
  .ac-lightbox-foot{position:absolute;left:0;right:0;bottom:0;height:2.25rem !important;display:flex;align-items:center;justify-content:space-between;padding:0 .625rem !important;background:rgba(17,24,39,.92) !important;color:#fff !important;border-top:0 !important;font-weight:700;z-index:9 !important;}
  .ac-lightbox-fit{border:.0625rem solid rgba(255,255,255,.35) !important;background:transparent !important;color:#fff !important;border-radius:.5rem !important;padding:.25rem .5rem !important;font-size:var(--fs-xs) !important;font-weight:700 !important;cursor:pointer;}
  #acLightbox .ac-lightbox-close{position:absolute !important;top:.75rem !important;right:.75rem !important;left:auto !important;width:2.125rem !important;height:2.125rem !important;display:flex !important;align-items:center;justify-content:center;border-radius:999rem !important;border:0 !important;background:rgba(17,24,39,.85) !important;color:#fff !important;font-size:1.25rem !important;font-weight:900 !important;line-height:1 !important;cursor:pointer;z-index:9999 !important;box-shadow:0 .375rem 1rem rgba(0,0,0,.25);}
  .ac-lightbox-close:active,.ac-lightbox-nav:active{transform:scale(.92);}

  .ac-field-suggest{position:relative;}
  .ac-suggest{position:absolute;left:0;right:0;top:calc(100% + .375rem);background:#fff;border:.0625rem solid var(--line2);border-radius:.875rem;box-shadow:0 .625rem 1.75rem rgba(0,0,0,.10);max-height:18.75rem;overflow:auto;z-index:9999;}
  .ac-suggest .it{padding:.625rem .75rem;border-bottom:.0625rem solid #eef2f7;cursor:pointer;}
  .ac-suggest .it:last-child{border-bottom:none;}
  .ac-suggest .it:hover{background:#f8fafc;}
  .ac-suggest .code{font-weight:900;font-size:var(--fs-sm);}
  .ac-suggest .desc{color:var(--muted);margin-top:.125rem;font-size:var(--fs-xs);white-space:normal;word-break:break-word;}

  .ac-mdetail{position:fixed;inset:0;background:rgba(17,24,39,.60);display:none;align-items:flex-end;justify-content:center;padding:.75rem;}
  .ac-mdetail.open{display:flex;z-index:2147483646 !important;}
  .ac-mdetail-card{width:100%;max-width:45rem;background:#fff;border-radius:1.125rem;overflow:hidden;box-shadow:var(--shadow-pop);max-height:86vh;display:flex;flex-direction:column;}
  .ac-mdetail-head{display:flex;align-items:center;justify-content:space-between;gap:.625rem;padding:.625rem .75rem;border-bottom:.0625rem solid rgba(148,163,184,.35);font-weight:900;background:#f9fafb;}
  .ac-mdetail-body{padding:.75rem;overflow:auto;}
  .ac-mdetail-kv{display:grid;grid-template-columns:6.875rem 1fr;gap:.625rem;align-items:start;margin:.5rem 0;}
  .ac-mdetail-kv .k{font-weight:900;color:#111827;}
  .ac-mdetail-kv .v{font-weight:700;color:#111827;word-break:break-word;}
  .ac-mdetail-close{width:2.375rem;height:2.375rem;display:flex;align-items:center;justify-content:center;border-radius:999rem;border:0;background:rgba(17,24,39,.12);backdrop-filter:blur(.375rem);color:#111827;font-size:1.375rem;font-weight:900;line-height:1;cursor:pointer;box-shadow:0 .375rem 1rem rgba(0,0,0,.18);transition:transform .12s ease, background .12s ease;}
  .ac-mdetail-close:active{transform:scale(.92);background:#000;color:#fff;}
  .ac-mdetail.open .ac-mdetail-close,.ac-lightbox.open .ac-lightbox-close{position:relative;z-index:1000000 !important;}

  .ac-header{position:relative;z-index:1000 !important;}
  .ac-header .elementor-nav-menu__container,.ac-header .elementor-nav-menu--dropdown{position:relative;z-index:1001 !important;}

  .ac-price-toggle{display:flex;align-items:center;gap:.625rem;margin-bottom:.5rem;}
  .ac-switch{position:relative;display:inline-block;width:2.625rem;height:1.375rem;}
  .ac-switch input{opacity:0;width:0;height:0;}
  .ac-slider{position:absolute;inset:0;background:#cbd5f5;border-radius:999rem;cursor:pointer;transition:.2s;}
  .ac-slider:before{content:"";position:absolute;height:1.125rem;width:1.125rem;left:.125rem;top:.125rem;background:white;border-radius:50%;transition:.2s;}
  .ac-switch:active .ac-slider:before{transform:scale(.92);}
  .ac-switch input:checked + .ac-slider{background:var(--brand);}
  .ac-switch input:checked + .ac-slider:before{transform:translateX(1.25rem);}
  .ac-toggle-label{font-size:var(--fs-sm);font-weight:800;color:#374151;}
  .ac-float-row{display:flex;align-items:center;gap:.625rem;}
  .ac-float-has-toggle input.ac-price-field{flex:1 1 auto;}
  .ac-switch-inline{flex:0 0 auto;margin-top:.125rem;}
  .ac-sp-grid-mock .ac-float-has-toggle{width:100%;}
  .ac-sp-grid-mock .ac-float-has-toggle .ac-float-row{display:grid !important;grid-template-columns:1fr auto !important;align-items:center !important;gap:.625rem !important;}
  .ac-sp-grid-mock .ac-float-has-toggle .ac-price-field{width:100% !important;min-width:0 !important;}
  .ac-sp-grid-mock .ac-float-has-toggle .ac-switch-inline{margin-top:0 !important;justify-self:end !important;align-self:center !important;}
  .ac-toggle-cell{display:flex;align-items:center;justify-content:flex-end;gap:.5rem;}
  .ac-toggle-text{font-size:var(--fs-xs);font-weight:800;color:#374151;white-space:nowrap;}

  .ac-price-toggle-mobile{display:flex;align-items:center;gap:.5rem;font-size:var(--fs-sm);font-weight:800;color:#374151;}
  .ac-price-toggle-mobile input{display:none;}
  .ac-price-toggle-mobile .ac-slider{width:2.625rem;height:1.375rem;background:#cbd5f5;border-radius:999rem;position:relative;cursor:pointer;}
  .ac-price-toggle-mobile .ac-slider:before{content:"";position:absolute;width:1.125rem;height:1.125rem;left:.125rem;top:.125rem;background:#fff;border-radius:50%;transition:.2s;}
  .ac-price-toggle-mobile input:checked + .ac-slider{background:var(--brand);}
  .ac-price-toggle-mobile input:checked + .ac-slider:before{transform:translateX(1.25rem);}

  .ac-mobile-inventory,.ac-mobile-filter-modal{display:none;}

  /* ✅ MOBILE DETAIL SUMMARY – COMPACT CARD STYLE (FIXED SPACING) */
  .ac-mobile-title-line{
    background:#fff;
    border:.0625rem solid var(--line2);
    border-radius:.625rem;
    padding:.625rem .75rem;
    margin:0 0 .625rem;
    box-shadow:0 .25rem .75rem rgba(15,23,42,.04);
  }

  .ac-mobile-title-grid{
    display:grid;
    grid-template-columns:minmax(0,1fr) minmax(0,1fr);
    gap:.25rem 1rem;
    font-size:var(--fs-base);
    line-height:1.35;
    color:#111827;
  }

  .ac-mobile-title-grid .full{
    grid-column:1 / -1;
  }

  .ac-mobile-title-grid > div{
    min-width:0;
    display:flex;
    align-items:baseline;
    gap:.35rem;
  }

  .ac-mobile-title-grid .k{
    flex:0 0 auto;
    color:var(--info);
    font-weight:900;
  }

  .ac-mobile-title-grid span:not(.k){
    min-width:0;
    font-weight:700;
    color:#111827;
    word-break:break-word;
  }

  @media (max-width:40rem){
    .ac-mobile-title-grid{
      grid-template-columns:1fr;
      gap:.1875rem;
      font-size:var(--fs-sm);
    }
  }

  @media (min-width:56.3125rem){
    .ac-search{display:block !important;}
    .ac-actions{justify-content:flex-end;}
    .ac-desktop-aps{display:flex;flex-direction:column;gap:.4375rem;padding:.4375rem .625rem;background:var(--bg);min-height:0;height:auto;overflow:visible;}
    .ac-cards{display:none;}
    #acToggleSearch{display:none;}
    .ac-topbar-head{display:none;}
    .ac-table-body{max-height:46vh;}
    .ac-mock-grid{display:grid;grid-template-columns:1.05fr .7fr 1.15fr;gap:.625rem;align-items:start;}
    .ac-sp-grid-mock{grid-template-columns:1fr 1fr;gap:.375rem .5rem;}
  }

  @media (max-width:56.25rem){
    .ac-topbar{
      display:block !important;
      position:sticky;
      top:0;
      z-index:80;
      background:#fff;
      border-bottom:.0625rem solid var(--line);
    }

    .ac-search{
      display:block !important;
      padding:.5rem .625rem .625rem;
      background:#fff;
      border-top:0;
    }

    .ac-topbar-head{
      display:none !important;
    }

    .ac-form.ac-form-aps{
      grid-template-columns:minmax(0,1fr) minmax(0,1fr);
      gap:.375rem .5rem;
      grid-template-areas:
        "desc desc2"
        "advanced advanced"
        "results results";
    }

    .ac-advanced-fields{
      grid-template-columns:minmax(0,1fr) minmax(0,1fr);
      gap:.375rem .5rem;
    }

    .ac-results-head{
      display:flex;
      align-items:center;
      justify-content:space-between;
      gap:.5rem;
      padding:.125rem .125rem 0;
    }

    .ac-actions{
      justify-content:flex-end;
      flex-wrap:nowrap;
    }

    .ac-btn{
      height:1.75rem;
      padding:.25rem .5625rem;
      font-size:var(--fs-sm);
      border-radius:.5625rem;
    }

    .ac-field input{
      height:var(--control-h);
      font-size:var(--fs-base);
      border-radius:.75rem;
    }

    .ac-field label{
      left:.75rem;
      top:.5rem;
    }

    .ac-wrap{
      background:var(--bg);
      border:0;
      border-radius:0;
      overflow:visible;
    }

    .ac-bot.ac-bot-mock{
      display:none !important;
    }

    .ac-cards{
      display:none;
    }

    .ac-mobile-inventory{display:block;padding:.75rem .625rem 1rem;background:var(--bg);}

    .ac-mobile-table-shell{width:100%;overflow-x:auto;overflow-y:hidden;border-radius:var(--radius);backgr�4FOeR���������UU
�?�
ound:#fff;border:.0625rem solid rgba(148,163,184,.35);box-shadow:var(--shadow-soft);-webkit-overflow-scrolling:touch;}
    .ac-mobile-table{width:max-content;min-width:55rem;border-collapse:collapse;table-layout:fixed;font-size:var(--fs-sm);line-height:1.25;}
    .ac-mobile-table th{background:linear-gradient(180deg,#f7f9ff,#eef3ff);color:#1f2937;text-align:left;font-weight:800;padding:.5rem .625rem;border-right:.0625rem solid #e5eaf2;border-bottom:.0625rem solid #dbe3ee;white-space:nowrap;position:sticky;top:0;z-index:1;}
    .ac-mobile-table td{padding:.5rem .625rem;border-right:.0625rem solid #eef2f7;border-bottom:.0625rem solid #eef2f7;color:#111827;font-weight:600;vertical-align:top;background:#fff;}
    .ac-mobile-table tbody tr:nth-child(odd) td{background:#fff;}
    .ac-mobile-table tbody tr:nth-child(even) td{background:#f8fbff;}
    .ac-mobile-table tbody tr:hover td{background:rgba(37,99,235,.06);}
    .ac-mobile-table tbody tr.active td{background:rgba(37,99,235,.12) !important;box-shadow:inset .25rem 0 0 rgba(37,99,235,.55);}
    .ac-mobile-table .m-code{width:10.5rem;}
    .ac-mobile-table .m-desc{width:14rem;}
    .ac-mobile-table .m-type{width:6rem;}
    .ac-mobile-table .m-model{width:9rem;}
    .ac-mobile-table .m-qty{width:4.5rem;text-align:right;font-variant-numeric:tabular-nums;}
    .ac-mobile-table .m-price{width:5.5rem;text-align:right;font-variant-numeric:tabular-nums;}
    .ac-mobile-table .m-desc2{width:9rem;}
    .ac-mobile-empty{text-align:center;padding:.875rem;color:#64748b;font-size:var(--fs-sm);}

    .ac-mdetail{
      position:fixed !important;
      left:0 !important;
      right:0 !important;
      bottom:0 !important;
      top:0 !important;
      align-items:center;
      justify-content:center;
      padding:1rem;
      background:rgba(15,23,42,.55);
      z-index:2147483646 !important;
    }

    body.admin-bar .ac-mdetail{
      top:2rem !important;
    }

    .ac-mdetail.open{
      display:flex !important;
    }

    .ac-mdetail-card{
      width:min(56rem,94vw);
      height:auto;
      max-height:calc(100vh - 4rem);
      border-radius:var(--radius);
      box-shadow:var(--shadow-pop);
      background:var(--bg);
      overflow:hidden;
    }
    body.admin-bar .ac-mdetail-card{
      max-height:calc(100vh - 6rem);
    }
    .ac-mdetail-head{
      padding:.5rem .625rem;
      background:#fff;
      border-bottom:.0625rem solid var(--line2);
    }
    .ac-mdetail-head-title{
      display:flex;
      justify-content:space-between;
      align-items:center;
      width:100%;
      gap:.75rem;
    }
    .ac-back-mobile{
      background:linear-gradient(180deg,var(--brand) 0%,var(--brand2) 100%);
      color:#fff;
      border:0;
      border-radius:.5rem;
      font-size:var(--fs-sm);
      font-weight:900;
      padding:.4375rem .75rem;
      cursor:pointer;
    }
    .ac-mdetail-close{
      display:none !important;
    }
    .ac-mdetail-body{
      padding:.75rem;
      overflow:auto;
    }
    .ac-mobile-section-title{
      font-size:var(--fs-sm);
      font-weight:1000;
      color:#111827;
      margin:.75rem 0 .375rem;
      text-transform:uppercase;
      letter-spacing:.03em;
    }
    .ac-mobile-box{
      background:#fff;
      border:.0625rem solid var(--line2);
      border-radius:.625rem;
      padding:.5rem .625rem;
      margin-bottom:.625rem;
      box-shadow:0 .25rem .75rem rgba(15,23,42,.04);
    }
    .ac-mobile-stock-line,.ac-mobile-info-line,.ac-mobile-price-line{
      display:grid;
      grid-template-columns:6.25rem 1fr;
      gap:.5rem;
      font-size:var(--fs-sm);
      line-height:1.35;
      color:#111827;
      margin:.1875rem 0;
    }
    .ac-mobile-stock-line b,.ac-mobile-info-line b,.ac-mobile-price-line b{
      font-weight:900;
      color:#111827;
    }
    .ac-mobile-main-img{
      width:100%;
      background:#fff;
      border:.0625rem solid var(--line2);
      border-radius:.625rem;
      padding:.5rem;
      margin-bottom:.5rem;
      min-height:7rem;
      display:flex;
      align-items:center;
      justify-content:center;
      box-shadow:0 .25rem .75rem rgba(15,23,42,.04);
    }
    .ac-mobile-main-img img{
      width:100%;
      max-height:12rem;
      object-fit:contain;
      display:block;
    }
    #mImgGrid{
      display:grid;
      grid-template-columns:repeat(4,1fr);
      gap:.5rem;
      margin:0 0 .75rem;
    }
    #mImgGrid .ac-img-thumb{
      max-height:5.25rem;
      aspect-ratio:1 / 1;
      border:.0625rem solid var(--line2);
      border-radius:.5rem;
    }
    #mImgGrid .ac-img-thumb:first-child{
      border-color:var(--brand);
      border-width:.125rem;
    }

    .ac-mobile-section-title-row{
      display:flex;
      align-items:center;
      justify-content:space-between;
      gap:0.75rem;
    }

    .ac-price-toggle-mobile{
      display:flex !important;
      align-items:center;
      gap:0.5rem;
      font-size:0.75rem;
      font-weight:800;
      color:#374151;
      white-space:nowrap;
    }
    .ac-price-toggle-mobile input{
      display:none;
    }
    .ac-price-toggle-mobile .ac-slider{
      width:2.625rem;
      height:1.375rem;
      background:#cbd5e1;
      border-radius:999rem;
      position:relative;
      cursor:pointer;
      flex:0 0 auto;
    }
    .ac-price-toggle-mobile .ac-slider:before{
      content:"";
      position:absolute;
      width:1.125rem;
      height:1.125rem;
      left:0.125rem;
      top:0.125rem;
      background:#fff;
      border-radius:50%;
      transition:.2s;
    }
    .ac-price-toggle-mobile input:checked + .ac-slider{
      background:#2563eb;
    }
    .ac-price-toggle-mobile input:checked + .ac-slider:before{
      transform:translateX(1.25rem);
    }
  }

  /* ✅ FIXED MOBILE (≤40rem) GRID AREAS */
  @media (max-width:40rem){
    .ac-form.ac-form-aps{
      grid-template-columns:minmax(0,1fr);
      grid-template-areas:
        "desc"
        "desc2"
        "advanced"
        "results";
    }

    .ac-advanced-fields{
      grid-template-columns:minmax(0,1fr);
    }

    .ac-results-head{
      align-items:flex-start;
      gap:.375rem;
    }

    .ac-results-head .count{
      padding-top:.4375rem;
    }

    .ac-actions{
      gap:.3125rem;
    }

    .ac-mobile-inventory{padding:.625rem .5rem .875rem;}
    .ac-mobile-table{min-width:55rem;font-size:var(--fs-sm);}
    .ac-mobile-table th,.ac-mobile-table td{padding:.4375rem .5rem;}
    .ac-mdetail{padding:.5rem;}
    body.admin-bar .ac-mdetail{top:2rem;}
    .ac-mdetail-card{width:100%;max-height:calc(100vh - 3rem);border-radius:.75rem;}
    body.admin-bar .ac-mdetail-card{max-height:calc(100vh - 5rem);}
    .ac-mobile-stock-line,.ac-mobile-info-line,.ac-mobile-price-line{grid-template-columns:5.75rem 1fr;}
  }

  /* ===== MOBILE DETAIL MODAL — FORCE ABOVE SITE HEADER ===== */
  @media (max-width:56.25rem){
    body.ac-mobile-detail-open{
      overflow:hidden !important;
    }

    body.ac-mobile-detail-open .ac-header,
    body.ac-mobile-detail-open header,
    body.ac-mobile-detail-open .elementor-location-header,
    body.ac-mobile-detail-open .elementor-sticky,
    body.ac-mobile-detail-open .site-header{
      visibility:hidden !important;
      pointer-events:none !important;
    }

    body.ac-mobile-detail-open #acMobileDetail{
      position:fixed !important;
      inset:0 !important;
      display:flex !important;
      align-items:center !important;
      justify-content:center !important;
      padding:1rem !important;
      background:rgba(15,23,42,.58) !important;
      z-index:2147483647 !important;
    }

    body.admin-bar.ac-mobile-detail-open #acMobileDetail{
      top:2rem !important;
    }

    body.ac-mobile-detail-open #acMobileDetail .ac-mdetail-card{
      position:relative !important;
      z-index:2147483647 !important;
      width:min(56rem,94vw) !important;
      max-height:calc(100vh - 4rem) !important;
      overflow:hidden !important;
    }

    body.admin-bar.ac-mobile-detail-open #acMobileDetail .ac-mdetail-card{
      max-height:calc(100vh - 6rem) !important;
    }

    body.ac-mobile-detail-open #acMobileDetail .ac-mdetail-body{
      overflow:auto !important;
      max-height:calc(100vh - 7rem) !important;
    }
  }

  /* ===== DESKTOP COMPACT FULL-VIEW TUNING ===== */
  @media (min-width:56.3125rem){
    .ac-wrap{font-size:var(--fs-base);}
    .ac-field label,
    .ac-float > label{left:.5rem;top:.375rem;}
    .ac-table th.col-code,.ac-table td.col-code{width:8.5rem;}
    .ac-table th:nth-child(2),.ac-table td:nth-child(2){width:26rem;}
    .ac-table th.col-brand,.ac-table td.col-brand{width:5rem;}
    .ac-table th:nth-child(4),.ac-table td:nth-child(4){width:22.5rem;}
    .ac-table th.col-qty,.ac-table td.col-qty{width:4.5rem;}
    .ac-table th.col-price,.ac-table td.col-price{width:5rem;}
    .ac-table th.col-desc2,.ac-table td.col-desc2{width:27rem;}
    .ac-results-head{padding:0 .125rem;}
    .ac-panel-mock{border-radius:.625rem;}
    .ac-table-scroll{border-radius:.625rem;}
  }

</style>


<div class="ac-wrap">

  <!-- TOP BAR -->
  <div class="ac-topbar">
    <div class="ac-topbar-head">
      <div class="ac-title">
        <div class="sub">Tap 🔍 to filter (mobile). Tap an item to view details.</div>
      </div>
      <button type="button" id="acToggleSearch" class="ac-iconbtn" aria-label="Toggle search">🔍</button>
    </div>

    <!-- SEARCH -->
    <div id="acSearchPanel" class="ac-search<?= $hasFilter ? ' open' : '' ?>">
      <form method="get">
        <div class="ac-form ac-form-aps">

          <div class="ac-field ac-f-desc">
            <label>Description 1</label>
            <input name="ac_desc" value="<?= ac_h($q_desc) ?>" placeholder=" ">
          </div>

          <div class="ac-field ac-f-supercede">
            <label>Description 2</label>
            <input name="ac_desc2" value="<?= ac_h($q_desc2) ?>" placeholder=" ">
          </div>

          <div id="acAdvancedFields" class="ac-advanced-fields<?= $hasAdvancedSearch ? ' open' : '' ?>">
            <div class="ac-field ac-field-suggest ac-f-itemcode">
              <label>Item Code</label>
              <input id="acItemCodeInput" autocomplete="off" name="ac_itemcode" value="<?= ac_h($q_itemcode) ?>" placeholder=" ">
              <div id="acItemCodeSuggest" class="ac-suggest" style="display:none"></div>
            </div>

            <div class="ac-field ac-f-brand">
              <label>Item Type</label>
              <input name="ac_itemtype" value="<?= ac_h($q_itemtype) ?>" placeholder=" ">
            </div>

            <div class="ac-field ac-f-varmodel">
              <label>VarModel</label>
              <input name="ac_varmodel" value="<?= ac_h($q_varmodel) ?>" placeholder=" ">
            </div>

            <div class="ac-field ac-f-qty">
              <label>Qty</label>
              <input name="ac_qty" value="<?= ac_h($q_qty) ?>" placeholder=" ">
            </div>

            <div class="ac-field ac-f-price">
              <label>Price</label>
              <input name="ac_price" value="<?= ac_h($q_price) ?>" placeholder=" ">
            </div>
          </div>

          <!-- RESULTS HEADER -->
          <div class="ac-results-head">
            <div class="count">Search Result (<?= (int)$totalRows ?>)</div>
            <div class="ac-actions ac-f-actions">
              <button type="button" id="acAdvancedToggle" class="ac-btn filter" aria-controls="acAdvancedFields" aria-expanded="<?= $hasAdvancedSearch ? 'true' : 'false' ?>"><?= $hasAdvancedSearch ? '− Less' : '+ More' ?></button>
              <button class="ac-btn primary" type="submit">Search</button>
              <button class="ac-btn secondary" type="submit" name="ac_clear" value="1">Clear</button>
            </div>
          </div>

        </div>
      </form>
    </div>
  </div>

  <!-- MOBILE: table only, search is shared with desktop -->
  <div class="ac-mobile-inventory" id="acCards">

    <div class="ac-mobile-table-shell">
      <table class="ac-mobile-table">
        <thead>
          <tr>
            <th class="m-code">Item Code</th>
            <th class="m-desc">Description 1</th>
            <th class="m-type">Item Type</th>
            <th class="m-model">VarModel</th>
            <th class="m-qty">Qty</th>
            <th class="m-price">Price</th>
            <th class="m-desc2">Description 2</th>
          </tr>
        </thead>
        <tbody>
          <?php
          if (empty($rowsArr)) {
            echo '<tr><td colspan="7" class="ac-mobile-empty">No results.</tr></tr>';
          } else {
            foreach ($rowsArr as $row) {
              $model = ($row['UDF_varLongModel'] ?: $row['UDF_varModel']);

              $ds = [
                'ItemCode' => $row['ItemCode'],
                'Description' => $row['Description'],
                'Model' => $model,
                'UOM' => $row['UOM'],
                'Brand' => $row['ItemType'],
                'Qty' => $row['TotalQty'],
                'Barcode' => $row['BarCode'],

                'Category' => $row['ItemGroup'],
                'Supercede' => $row['Desc2'],
                'Location' => $row['ShelfLocation'],
                'Note' => ac_rtf_to_text($row['Note']),

                'Cost' => $row['Cost'],
                'Price' => $row['Price'],
                'Price2' => $row['Price2'],
                'Price3' => $row['Price3'],
                'Price4' => $row['Price4'],
                'Price5' => $row['Price5'],
                'Price6' => $row['Price6'],

                'PlainCost'   => $row['PlainCost'],
                'PlainPrice'  => $row['PlainPrice'],
                'PlainPrice2' => $row['PlainPrice2'],
                'PlainPrice3' => $row['PlainPrice3'],
                'PlainPrice4' => $row['PlainPrice4'],
                'PlainPrice5' => $row['PlainPrice5'],
                'PlainPrice6' => $row['PlainPrice6'],

                'StockOnHand' => $row['TotalQty'],
              ];

              $json = ac_h(json_encode($ds, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
          ?>
              <tr class="ac-mobile-row" data-row="<?= $json ?>">
                <td class="m-code"><?= ac_h($row['ItemCode']) ?></td>
                <td class="m-desc"><?= ac_h($row['Description']) ?></td>
                <td class="m-type"><?= ac_h($row['ItemType']) ?></td>
                <td class="m-model"><?= ac_h($row['UDF_varModel']) ?></td>
                <td class="m-qty"><?= number_format((float)$row['TotalQty'], 2) ?></td>
                <td class="m-price ac-row-price" data-encrypted="<?= ac_h($row['Price']) ?>" data-plain="<?= ac_h($row['PlainPrice']) ?>"><?= ac_h($row['Price']) ?></td>
                <td class="m-desc2"><?= ac_h($row['Desc2']) ?></td>
              </tr>
          <?php
            }
          }
          ?>
        </tbody>
      </table>
    </div>
  </div>

  <!-- DESKTOP: table + bottom panels -->
  <div class="ac-desktop-aps">

    <!-- TABLE -->
    <div class="ac-table-scroll">
      <div class="ac-table-body">
        <table class="ac-table">
          <thead>
            <tr>
              <th class="col-code">Item Code</th>
              <th>Description 1</th>
              <th class="col-brand">Item Type</th>
              <th>VarModel</th>
              <th class="col-qty">Qty.</th>
              <th class="col-price">Price</th>
              <th class="col-desc2">Description 2</th>
            </tr>
          </thead>
          <tbody>
            <?php
            if (empty($rowsArr)) {
              echo "<tr><td colspan='7' style='padding:.875rem;color:#6b7280'>No results.</td></table>";
            } else {
              foreach ($rowsArr as $row) {
                $model = ($row['UDF_varLongModel'] ?: $row['UDF_varModel']);

                static $ac_img_i = 0;
                $i�UU�~
��������옕�
�?�mgs = [];

                if (!$hasFilter && $ac_img_i < 10 && function_exists('ac_fetch_images_base64')) {
                  $imgs = ac_fetch_images_base64($conn, $row['ItemCode'], 16);
                }

                $ac_img_i++;

                $ds = [
                  'ItemCode' => $row['ItemCode'],
                  'Description' => $row['Description'],
                  'Model' => $model,
                  'UOM' => $row['UOM'],
                  'Brand' => $row['ItemType'],
                  'Qty' => $row['TotalQty'],
                  'Barcode' => $row['BarCode'],

                  'Category' => $row['ItemGroup'],
                  'Supercede' => $row['Desc2'],
                  'Location' => $row['ShelfLocation'],
                  'Note' => ac_rtf_to_text($row['Note']),

                  'Cost' => $row['Cost'],
                  'Price' => $row['Price'],
                  'Price2' => $row['Price2'],
                  'Price3' => $row['Price3'],
                  'Price4' => $row['Price4'],
                  'Price5' => $row['Price5'],
                  'Price6' => $row['Price6'],

                  'PlainCost'   => $row['PlainCost'],
                  'PlainPrice'  => $row['PlainPrice'],
                  'PlainPrice2' => $row['PlainPrice2'],
                  'PlainPrice3' => $row['PlainPrice3'],
                  'PlainPrice4' => $row['PlainPrice4'],
                  'PlainPrice5' => $row['PlainPrice5'],
                  'PlainPrice6' => $row['PlainPrice6'],

                  'StockOnHand' => $row['TotalQty'],
                  'Images' => $imgs
                ];

                $json = ac_h(json_encode($ds, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
            ?>
                <tr class="ac-row" data-row="<?= $json ?>">
                  <td class="col-code"><?= ac_h($row['ItemCode']) ?></td>
                  <td><?= ac_h($row['Description']) ?></td>
                  <td class="col-brand"><?= ac_h($row['ItemType']) ?></td>
                  <td><?= ac_h($row['UDF_varModel']) ?></td>
                  <td class="col-qty"><?= number_format((float)$row['TotalQty'], 2) ?></td>
                  <td class="col-price ac-row-price" data-encrypted="<?= ac_h($row['Price']) ?>" data-plain="<?= ac_h($row['PlainPrice']) ?>"><?= ac_h($row['Price']) ?></td>
                  <td class="col-desc2"><?= ac_h($row['Desc2']) ?></td>
                </tr>
            <?php
              }
            }
            ?>
          </tbody>
        </table>
      </div>
    </div>

    <!-- BOTTOM -->
    <div class="ac-bot ac-bot-mock">
      <div class="ac-panel ac-panel-mock">
        <div class="ac-panel-body ac-mock-wrap">

          <div class="ac-mock-grid">

            <!-- LEFT -->
            <div class="ac-mock-col">
              <div class="ac-mock-title">Other Info &amp; Stock</div>

              <div class="ac-line">
                <div class="lbl">Item Code:</div>
                <div class="val"><input id="d_itemcode" readonly></div>
              </div>

              <div class="ac-line">
                <div class="lbl">Location:</div>
                <div class="val"><input id="d_location" readonly></div>
              </div>

              <div class="ac-line ac-line-block">
                <div class="lbl">Note:</div>
                <div class="val"><textarea id="d_note" readonly></textarea></div>
              </div>
            </div>

            <!-- MIDDLE -->
            <div class="ac-mock-col">
              <div class="ac-mock-title">Images</div>
              <div id="acImgGrid" class="ac-img-grid"></div>
            </div>

            <!-- RIGHT -->
            <div class="ac-mock-col">
              <div class="ac-mock-title">Pricing</div>

              <div class="ac-line">
                <div class="lbl">Std Cost:</div>
                <div class="val">
                  <input id="d_cost" class="ac-price-field" data-encrypted="" data-plain="" readonly>
                </div>
              </div>

              <div class="ac-line">
                <div class="lbl">List Price:</div>
                <div class="val">
                  <input id="d_price" class="ac-price-field" data-encrypted="" data-plain="" readonly>
                </div>
              </div>

              <div class="ac-mock-subtitle">Selling Price:</div>
              <div class="ac-sp-grid-mock">
                <div class="sp ac-float">
                  <label for="d_price2">S.Price 1</label>
                  <input id="d_price2" class="ac-price-field" data-encrypted="" data-plain="" readonly placeholder=" ">
                </div>

                <div class="sp ac-float">
                  <label for="d_price3">S.Price 2</label>
                  <input id="d_price3" class="ac-price-field" data-encrypted="" data-plain="" readonly placeholder=" ">
                </div>

                <div class="sp ac-float">
                  <label for="d_price4">S.Price 3</label>
                  <input id="d_price4" class="ac-price-field" data-encrypted="" data-plain="" readonly placeholder=" ">
                </div>

                <div class="sp ac-float">
                  <label for="d_price5">S.Price 4</label>
                  <input id="d_price5" class="ac-price-field" data-encrypted="" data-plain="" readonly placeholder=" ">
                </div>

                <div class="sp ac-float">
                  <label for="d_price6">S.Price 5</label>
                  <input id="d_price6" class="ac-price-field" data-encrypted="" data-plain="" readonly placeholder=" ">
                </div>

                <div class="sp ac-toggle-cell">
                  <span class="ac-toggle-text">Show decrypted</span>
                  <label class="ac-switch ac-switch-inline" title="Toggle encrypted / decrypted price">
                    <input type="checkbox" id="acPriceToggle">
                    <span class="ac-slider"></span>
                  </label>
                </div>
              </div>
            </div>

          </div>

        </div>
      </div>
    </div>

  </div>

</div>

<!-- ✅ Lightbox HTML -->
<div id="acLightbox" class="ac-lightbox" aria-hidden="true">
  <div class="ac-lightbox-card" role="dialog" aria-modal="true">
    <button type="button" id="acLightboxClose" class="ac-lightbox-close" aria-label="Close">×</button>
    <button type="button" id="acLightboxPrev" class="ac-lightbox-nav prev" aria-label="Previous">‹</button>
    <button type="button" id="acLightboxNext" class="ac-lightbox-nav next" aria-label="Next">›</button>
    <div class="ac-lightbox-body" id="acLightboxBody">
      <img id="acLightboxImg" alt="">
    </div>
    <div class="ac-lightbox-foot">
      <span id="acLightboxCount">0 / 0</span>
      <button type="button" id="acLightboxFit" class="ac-lightbox-fit">Fit</button>
    </div>
  </div>
</div>

<!-- ✅ Mobile Details Modal -->
<div id="acMobileDetail" class="ac-mdetail" aria-hidden="true">
  <div class="ac-mdetail-card" role="dialog" aria-modal="true">
    <div class="ac-mdetail-head">
      <div class="ac-mdetail-head-title">
        <button type="button" id="acMobileDetailClose" class="ac-back-mobile">&lt; Back to List</button>
      </div>
    </div>
    <div class="ac-mdetail-body">
      <!-- ✅ Compact summary grid with all fields -->
<div class="ac-mobile-title-line ac-mobile-title-grid">
  <div><span class="k">Item Code:</span> <span id="m_itemcode">—</span></div>
  <div><span class="k">Item Type:</span> <span id="m_top_type">—</span></div>

  <div><span class="k">Description 1:</span> <span id="m_desc">—</span></div>
  <div><span class="k">Description 2:</span> <span id="m_top_desc2">—</span></div>

  <div><span class="k">Qty:</span> <span id="m_top_qty">—</span></div>
  <div><span class="k">Price:</span> <span id="m_top_price">—</span></div>

  <div class="full"><span class="k">VarModel:</span> <span id="m_top_model">—</span></div>
</div>

      <div class="ac-mobile-section-title">Product Images</div>
      <div class="ac-mobile-main-img" id="mMainImg">
        <span style="color:#6b7280;font-weight:800;">No image</span>
      </div>
      <div id="mImgGrid" class="ac-img-grid"></div>
      <div class="ac-mobile-section-title">Inventory &amp; Stock</div>
      <div class="ac-mobile-box">
        <div class="ac-mobile-stock-line"><b>Qty on Hand:</b> <span id="m_qty">—</span></div>
        <div class="ac-mobile-stock-line"><b>Location:</b> <span id="m_location">—</span></div>
      </div>

      <div class="ac-mobile-section-title ac-mobile-section-title-row">
        <span>Pricing</span>
        <label class="ac-price-toggle-mobile" title="Toggle encrypted / decrypted price">
          <span>Show decrypted</span>
          <input type="checkbox" id="acMobilePriceToggle">
          <span class="ac-slider"></span>
        </label>
      </div>
      <div class="ac-mobile-box">
        <div class="ac-mobile-price-line"><b>Std Cost:</b> <span id="m_cost">—</span></div>
        <div class="ac-mobile-price-line"><b>List Price:</b> <span id="m_price">—</span></div>
        <div class="ac-mobile-price-line"><b>S.Price 1:</b> <span id="m_price2">—</span></div>
        <div class="ac-mobile-price-line"><b>S.Price 2:</b> <span id="m_price3">—</span></div>
        <div class="ac-mobile-price-line"><b>S.Price 3:</b> <span id="m_price4">—</span></div>
        <div class="ac-mobile-price-line"><b>S.Price 4:</b> <span id="m_price5">—</span></div>
        <div class="ac-mobile-price-line"><b>S.Price 5:</b> <span id="m_price6">—</span></div>
      </div>

      <div class="ac-mobile-section-title">Additional Information</div>
      <div class="ac-mobile-box">
        <div class="ac-mobile-info-line"><b>Group:</b> <span id="m_group">—</span></div>
        <div class="ac-mobile-info-line"><b>Type:</b> <span id="m_type">—</span></div>
        <div class="ac-mobile-info-line"><b>Barcode:</b> <span id="m_barcode">—</span></div>
        <div class="ac-mobile-info-line"><b>UOM:</b> <span id="m_uom">—</span></div>
        <div class="ac-mobile-info-line"><b>Note:</b> <span id="m_note">—</span></div>
      </div>
    </div>
  </div>
</div>

<script>
(function () {
  "use strict";

  function qsa(sel, root){ return Array.prototype.slice.call((root || document).querySelectorAll(sel)); }
  function isMobileWidth(){ return window.matchMedia("(max-width: 56.25rem)").matches; }
  function safeJsonParse(s){ try { return JSON.parse(s || "{}"); } catch(e){ return {}; } }

  function toNum(v){
    if (v === null || v === undefined) return null;
    let s = String(v).trim();
    if (!s) return null;
    s = s.replace(/RM/gi, '').replace(/,/g, '').replace(/\s+/g, '');
    s = s.replace(/[^0-9.\-]/g, '');
    if (!s || s === '-' || s === '.' || s === '-.') return null;
    const n = Number(s);
    return Number.isFinite(n) ? n : null;
  }

  function fmtNum(v){
    const n = toNum(v);
    return (n === null) ? '—' : n.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 });
  }

  function fmtText(v){
    if (v === null || v === undefined) return "—";
    const s = String(v).trim();
    return s ? s : "—";
  }

  function fmtPlain(v){ return fmtNum(v); }
  function fmtEnc(v){ return fmtText(v); }

  function renderImages(images, gridId){
    var grid = document.getElementById(gridId || "acImgGrid");
    if (!grid) return;

    images = Array.isArray(images) ? images.filter(Boolean) : [];
    grid.innerHTML = "";

    var first = images.slice(0, 3);

    function makeThumb(src, label){
      var box = document.createElement("div");
      box.className = "ac-img-thumb" + (src ? "" : " empty");
      if (src){
        box.innerHTML = '<img src="'+ src +'" alt="">';
      } else {
        box.textContent = label || "No Image";
      }
      return box;
    }

    for (var i=0; i<3; i++){
      var src = first[i] || "";
      var t = makeThumb(src, "No Image");
      if (src){
        t.addEventListener("click", (function(s){ return function(){ openGallery(images, images.indexOf(s)); };})(src));
      }
      grid.appendChild(t);
    }

    var fourthSrc = images[3] || "";
    var fourth = makeThumb(fourthSrc, "No Image");

    if (images.length > 4){
      var overlay = document.createElement("div");
      overlay.className = "ac-img-more";
      overlay.textContent = "+" + (images.length - 4);
      fourth.appendChild(overlay);
      fourth.addEventListener("click", function(){ openGallery(images, 0); });
    } else if (fourthSrc){
      fourth.addEventListener("click", function(){ openGallery(images, 3); });
    }

    grid.appendChild(fourth);
  }

  function fetchImagesForItem(itemCode){
    if (!itemCode) return Promise.resolve([]);

    var url =
      (window.AC_AJAX_URL || "") +
      ((String(window.AC_AJAX_URL || "").indexOf("?") >= 0) ? "&" : "?") +
      "action=ac_get_images" +
      "&nonce=" + encodeURIComponent(window.AC_IMG_NONCE || "") +
      "&item=" + encodeURIComponent(itemCode);

    return fetch(url, { credentials: "same-origin" })
      .then(function(r){
        return r.text().then(function(t){
          try { return JSON.parse(t); } catch(e){ return t; }
        });
      })
      .then(function(payload){
        if (!payload || typeof payload === "string") return [];
        if (payload.success && Array.isArray(payload.data)) return payload.data;
        if (Array.isArray(payload)) return payload;
        return [];
      })
      .catch(function(){ return []; });
  }

  // ✅ applyPriceMode with forceShowPlain
  function applyPriceMode(ds, forceShowPlain){
    var toggle = document.getElementById("acPriceToggle");
    var mobileToggle = document.getElementById("acMobilePriceToggle");

    var showPlain;

    if (typeof forceShowPlain === "boolean") {
      showPlain = forceShowPlain;
    } else {
      showPlain = !!(
        (toggle && toggle.checked) ||
        (mobileToggle && mobileToggle.checked)
      );
    }

    if (toggle) toggle.checked = showPlain;
    if (mobileToggle) mobileToggle.checked = showPlain;

    document.querySelectorAll(".ac-price-field").forEach(function(el){
      el.value = showPlain ? (el.dataset.plain || "—") : (el.dataset.encrypted || "—");
    });

    document.querySelectorAll(".ac-row-price").forEach(function(el){
      el.textContent = showPlain ? fmtPlain(el.dataset.plain) : fmtEnc(el.dataset.encrypted);
    });

    var setTxt = function(id, txt){
      var el = document.getElementById(id);
      if (el) el.textContent = txt;
    };

    if (ds){
      setTxt("m_cost",  showPlain ? fmtPlain(ds.PlainCost)   : fmtEnc(ds.Cost));
      setTxt("m_price", showPlain ? fmtPlain(ds.PlainPrice)  : fmtEnc(ds.Price));
      setTxt("m_price2",showPlain ? fmtPlain(ds.PlainPrice2) : fmtEnc(ds.Price2));
      setTxt("m_price3",showPlain ? fmtPlain(ds.PlainPrice3) : fmtEnc(ds.Price3));
      setTxt("m_price4",showPlain ? fmtPlain(ds.PlainPrice4) : fmtEnc(ds.Price4));
      setTxt("m_price5",showPlain ? fmtPlain(ds.PlainPrice5) : fmtEnc(ds.Price5));
      setTxt("m_price6",showPlain ? fmtPlain(ds.PlainPrice6) : fmtEnc(ds.Price6));
      // ✅ also update the top summary price
      setTxt("m_top_price", showPlain ? fmtPlain(ds.PlainPrice) : fmtEnc(ds.Price));
    }
  }

  function fillDesktop(ds) {
    if (!ds) return;
    var el;

    el = document.getElementById("d_itemcode");  if (el) el.value = ds.ItemCode || "";
    el = document.getElementById("d_location"); if (el) el.value = ds.Location || "";
    el = document.getElementById("d_note");     if (el) el.value = ds.Note || "";

    function setPriceInput(id, encVal, plainVal){
      var x = document.getElementById(id);
      if (!x) return;
      x.dataset.encrypted = fmtEnc(encVal);
      x.dataset.plain     = fmtPlain(plainVal);
    }

    setPriceInput("d_cost",   ds.Cost,   ds.PlainCost);
 옕�^���������옕�
�>����   setPriceInput("d_price",  ds.Price,  ds.PlainPrice);
    setPriceInput("d_price2", ds.Price2, ds.PlainPrice2);
    setPriceInput("d_price3", ds.Price3, ds.PlainPrice3);
    setPriceInput("d_price4", ds.Price4, ds.PlainPrice4);
    setPriceInput("d_price5", ds.Price5, ds.PlainPrice5);
    setPriceInput("d_price6", ds.Price6, ds.PlainPrice6);

    applyPriceMode(ds);

    var imgs = Array.isArray(ds.Images) ? ds.Images : [];
    if (imgs.length) {
      renderImages(imgs);
    } else {
      renderImages([]);
      fetchImagesForItem(ds.ItemCode).then(function(list){
        var current = document.getElementById("d_itemcode");
        if (!current) return;
        if ((current.value || "") !== (ds.ItemCode || "")) return;
        renderImages(list);
      });
    }
  }

  function openMobileDetail(){
    var m = document.getElementById("acMobileDetail");
    if (!m) return;

    if (m.parentNode !== document.body) {
      document.body.appendChild(m);
    }

    var card = m.querySelector(".ac-mdetail-card");
    var body = m.querySelector(".ac-mdetail-body");

    m.scrollTop = 0;
    if (card) card.scrollTop = 0;
    if (body) body.scrollTop = 0;

    m.classList.add("open");
    m.setAttribute("aria-hidden", "false");

    document.body.classList.add("ac-popup-open");
    document.body.classList.add("ac-mobile-detail-open");

    requestAnimationFrame(function(){
      m.scrollTop = 0;
      if (card) card.scrollTop = 0;
      if (body) body.scrollTop = 0;
    });
  }

  function closeMobileDetail(){
    var m = document.getElementById("acMobileDetail");
    if (!m) return;

    m.classList.remove("open");
    m.setAttribute("aria-hidden","true");

    document.body.classList.remove("ac-popup-open");
    document.body.classList.remove("ac-mobile-detail-open");
  }

  (function wireMobileDetailClose(){
    var m = document.getElementById("acMobileDetail");
    var closeBtn = document.getElementById("acMobileDetailClose");
    if (closeBtn) closeBtn.addEventListener("click", closeMobileDetail);
    if (m) m.addEventListener("click", function(e){
      if (e.target === m) closeMobileDetail();
    });
  })();

  function fillMobile(ds){
    if (!ds) return;

    function setText(id, value){
      var el = document.getElementById(id);
      if (el) el.textContent = fmtText(value);
    }

    setText("m_itemcode", ds.ItemCode);
    setText("m_desc", ds.Description);
    setText("m_qty", fmtNum(ds.StockOnHand || ds.Qty));
    setText("m_location", ds.Location);
    setText("m_group", ds.Category);
    setText("m_type", ds.Brand);
    setText("m_barcode", ds.Barcode);
    setText("m_uom", ds.UOM);
    setText("m_note", ds.Note);

    // Fill the extra summary fields
    setText("m_top_type", ds.Brand);
    setText("m_top_model", ds.Model);
    setText("m_top_qty", fmtNum(ds.StockOnHand || ds.Qty));
    setText("m_top_desc2", ds.Supercede);

    // Encrypted prices initially (will be toggled later)
    setText("m_cost", fmtEnc(ds.Cost));
    setText("m_price", fmtEnc(ds.Price));
    setText("m_price2", fmtEnc(ds.Price2));
    setText("m_price3", fmtEnc(ds.Price3));
    setText("m_price4", fmtEnc(ds.Price4));
    setText("m_price5", fmtEnc(ds.Price5));
    setText("m_price6", fmtEnc(ds.Price6));
    setText("m_top_price", fmtEnc(ds.Price));

    renderImages([], "mImgGrid");

    var main = document.getElementById("mMainImg");
    if (main) {
      main.innerHTML = '<span style="color:#6b7280;font-weight:800;">Loading image...</span>';
    }

    function applyMobileImages(list){
      list = Array.isArray(list) ? list.filter(Boolean) : [];

      if (main) {
        if (list.length) {
          main.innerHTML = '<img src="' + list[0] + '" alt="">';
        } else {
          main.innerHTML = '<span style="color:#6b7280;font-weight:800;">No image</span>';
        }
      }

      renderImages(list, "mImgGrid");
    }

    var imgs = Array.isArray(ds.Images) ? ds.Images : [];
    if (imgs.length){
      applyMobileImages(imgs);
    } else {
      fetchImagesForItem(ds.ItemCode).then(function(list){
        var cur = document.getElementById("m_itemcode");
        if (!cur) return;
        if ((cur.textContent || "") !== (ds.ItemCode || "")) return;
        applyMobileImages(list);
      });
    }

    openMobileDetail();
  }

  var AC_GALLERY = { list: [], idx: 0 };
  function openGallery(list, startIndex){
    var lb = document.getElementById("acLightbox");
    var img = document.getElementById("acLightboxImg");
    var countEl = document.getElementById("acLightboxCount");
    var card = lb ? lb.querySelector(".ac-lightbox-card") : null;
    if (!lb || !img) return;

    AC_GALLERY.list = Array.isArray(list) ? list.filter(Boolean) : [];
    AC_GALLERY.idx = Math.max(0, Math.min(startIndex || 0, AC_GALLERY.list.length - 1));
    if (card) card.classList.remove("zoom");

    img.src = AC_GALLERY.list[AC_GALLERY.idx] || "";
    if (countEl) countEl.textContent = (AC_GALLERY.idx + 1) + " / " + (AC_GALLERY.list.length || 0);

    lb.classList.add("open");
    lb.setAttribute("aria-hidden", "false");
    document.documentElement.classList.add("ac-modal-open");
    document.body.classList.add("ac-popup-open");
  }
  function galleryNext(){
    if (!AC_GALLERY.list.length) return;
    AC_GALLERY.idx = (AC_GALLERY.idx + 1) % AC_GALLERY.list.length;
    var img = document.getElementById("acLightboxImg");
    var countEl = document.getElementById("acLightboxCount");
    var lb = document.getElementById("acLightbox");
    var card = lb ? lb.querySelector(".ac-lightbox-card") : null;
    if (card) card.classList.remove("zoom");
    if (img) img.src = AC_GALLERY.list[AC_GALLERY.idx];
    if (countEl) countEl.textContent = (AC_GALLERY.idx + 1) + " / " + AC_GALLERY.list.length;
    var body = document.getElementById("acLightboxBody");
    if (body) body.scrollTop = 0;
  }
  function galleryPrev(){
    if (!AC_GALLERY.list.length) return;
    AC_GALLERY.idx = (AC_GALLERY.idx - 1 + AC_GALLERY.list.length) % AC_GALLERY.list.length;
    var img = document.getElementById("acLightboxImg");
    var countEl = document.getElementById("acLightboxCount");
    var lb = document.getElementById("acLightbox");
    var card = lb ? lb.querySelector(".ac-lightbox-card") : null;
    if (card) card.classList.remove("zoom");
    if (img) img.src = AC_GALLERY.list[AC_GALLERY.idx];
    if (countEl) countEl.textContent = (AC_GALLERY.idx + 1) + " / " + AC_GALLERY.list.length;
    var body = document.getElementById("acLightboxBody");
    if (body) body.scrollTop = 0;
  }

  (function wireLightbox(){
    var lb = document.getElementById("acLightbox");
    if (!lb) return;
    var img = document.getElementById("acLightboxImg");
    var closeBtn = document.getElementById("acLightboxClose");
    var prevBtn  = document.getElementById("acLightboxPrev");
    var nextBtn  = document.getElementById("acLightboxNext");
    var fitBtn   = document.getElementById("acLightboxFit");
    var countEl  = document.getElementById("acLightboxCount");
    var card     = lb.querySelector(".ac-lightbox-card");
    document.body.classList.remove("ac-popup-open");

    function close(){
      lb.classList.remove("open");
      lb.setAttribute("aria-hidden", "true");
      if (img) img.src = "";
      document.documentElement.classList.remove("ac-modal-open");
      document.body.classList.remove("ac-popup-open");
      if (card) card.classList.remove("zoom");
    }

    if (closeBtn) closeBtn.addEventListener("click", close);
    lb.addEventListener("click", function(e){ if (e.target === lb) close(); });
    if (prevBtn) prevBtn.addEventListener("click", galleryPrev);
    if (nextBtn) nextBtn.addEventListener("click", galleryNext);

    if (fitBtn && card){
      fitBtn.addEventListener("click", function(){
        card.classList.toggle("zoom");
        fitBtn.textContent = card.classList.contains("zoom") ? "Zoom" : "Fit";
      });
    }

    if (img && card){
      img.style.cursor = "zoom-in";
      img.addEventListener("click", function(){
        card.classList.toggle("zoom");
        img.style.cursor = card.classList.contains("zoom") ? "zoom-out" : "zoom-in";
        if (fitBtn) fitBtn.textContent = card.classList.contains("zoom") ? "Zoom" : "Fit";
      });
    }

    document.addEventListener("keydown", function(e){
      if (!lb.classList.contains("open")) return;
      if (e.key === "Escape") close();
      if (e.key === "ArrowLeft") galleryPrev();
      if (e.key === "ArrowRight") galleryNext();
    });

    window.__acLightboxClose = close;
  })();

  (function wireResultsClick(){
    var items = qsa(".ac-row, .ac-card, .ac-mobile-row");
    if (!items.length) return;

    function clearActive(){
      qsa(".ac-row.active, .ac-card.active, .ac-mobile-row.active").forEach(function(x){ x.classList.remove("active"); });
    }

    items.forEach(function (el) {
      el.addEventListener("click", function () {
        clearActive();
        el.classList.add("active");
        var ds = safeJsonParse(el.getAttribute("data-row"));
        if (isMobileWidth()) fillMobile(ds);
        else fillDesktop(ds);
      });
    });

    items[0].classList.add("active");
    if (!isMobileWidth()) {
      fillDesktop(safeJsonParse(items[0].getAttribute("data-row")));
    }
  })();

  function escapeHtml(s){
    return String(s)
      .replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")
      .replace(/"/g,"&quot;").replace(/'/g,"&#039;");
  }

  (function wireSuggest(){
    var input = document.getElementById("acItemCodeInput");
    var box   = document.getElementById("acItemCodeSuggest");
    if (!input || !box) return;

    var t = null;
    var controller = null;
    var lastQ = "";

    function hide(){
      box.style.display = "none";
      box.innerHTML = "";
    }

    function show(items){
      if (!items || !items.length) {
        hide();
        return;
      }

      box.innerHTML = items.map(function(x){
        var code = x.code || x.ItemCode || "";
        var desc = x.desc || x.description || x.Description || "";

        return (
          '<div class="it" data-code="'+ escapeHtml(code) +'">' +
            '<div class="code">'+ escapeHtml(code) +'</div>' +
            (desc ? '<div class="desc">'+ escapeHtml(desc) +'</div>' : '') +
          '</div>'
        );
      }).join("");

      box.style.display = "block";
    }

    function buildSuggestUrl(term){
      var u = new URL(window.AC_AJAX_URL);
      u.searchParams.set("action", "ac_itemcode_suggest");
      u.searchParams.set("nonce", window.AC_SUG_NONCE || "");
      u.searchParams.set("term", term);
      return u.toString();
    }

    input.addEventListener("input", function(){
      var qTrim = (input.value || "").trim();
      if (qTrim.length < 1) {
        hide();
        return;
      }

      clearTimeout(t);

      t = setTimeout(function(){
        if (qTrim === lastQ) return;
        lastQ = qTrim;

        if (controller) controller.abort();
        controller = new AbortController();

        fetch(buildSuggestUrl(qTrim), {
          credentials: "same-origin",
          signal: controller.signal
        })
        .then(function(r){ return r.json(); })
        .then(function(payload){
          var items = [];

          if (payload && payload.ok === true && Array.isArray(payload.items)) {
            items = payload.items;
          }
          else if (payload && payload.success && Array.isArray(payload.data)) {
            items = payload.data;
          }
          else if (Array.isArray(payload)) {
            items = payload;
          }

          if ((input.value || "").trim() !== qTrim) return;

          show(items);
        })
        .catch(function(err){
          if (err && err.name === "AbortError") return;
          hide();
        });

      }, 250);
    });

    box.addEventListener("click", function(e){
      var it = e.target.closest(".it");
      if (!it) return;

      input.value = it.getAttribute("data-code") || "";
      hide();
      input.focus();
    });

    input.addEventListener("keydown", function(e){
      if (e.key === "Escape") hide();
    });

    input.addEventListener("blur", function(){
      setTimeout(hide, 150);
    });
  })();

  (function wireToggleSearch(){
    var btn = document.getElementById("acToggleSearch");
    var panel = document.getElementById("acSearchPanel");
    if (!btn || !panel) return;

    function setOpen(open){
      panel.classList.toggle("open", !!open);
      btn.setAttribute("aria-expanded", open ? "true" : "false");
    }

    setOpen(panel.classList.contains("open"));
    btn.addEventListener("click", function(){ setOpen(!panel.classList.contains("open")); });
  })();

  (function wireAdvancedSearch(){
    var btn = document.getElementById("acAdvancedToggle");
    var panel = document.getElementById("acAdvancedFields");
    if (!btn || !panel) return;

    function setOpen(open){
      panel.classList.toggle("open", !!open);
      btn.setAttribute("aria-expanded", open ? "true" : "false");
      btn.textContent = open ? "− Less" : "+ More";
    }

    setOpen(panel.classList.contains("open"));
    btn.addEventListener("click", function(){
      setOpen(!panel.classList.contains("open"));
    });
  })();

  (function wireSearchClearButtons(){
    var inputs = qsa('input[name^="ac_"]').filter(function(input){
      return input.type !== "hidden" && input.type !== "checkbox";
    });

    inputs.forEach(function(input){
      var host = input.closest(".ac-field, .ac-mobile-searchbox");

      if (!host) {
        host = document.createElement("span");
        host.className = "ac-clear-wrap";
        input.parentNode.insertBefore(host, input);
        host.appendChild(input);
      } else {
        host.classList.add("has-clear");
      }

      if (host.querySelector(".ac-clear-btn")) return;

      var btn = document.createElement("button");
      btn.type = "button";
      btn.className = "ac-clear-btn";
      btn.setAttribute("aria-label", "Clear field");
      btn.textContent = "×";
      host.appendChild(btn);

      function sync(){
        btn.classList.toggle("show", (input.value || "").length > 0);
      }

      btn.addEventListener("mousedown", function(e){
        e.preventDefault();
      });

      btn.addEventListener("click", function(){
        input.value = "";
        input.dispatchEvent(new Event("input", { bubbles:true }));
        input.dispatchEvent(new Event("change", { bubbles:true }));
        input.focus();
        sync();
      });

      input.addEventListener("input", sync);
      input.addEventListener("change", sync);
      sync();
    });
  })();

  var AC_LAST_DS = null;

  var _fillDesktop = fillDesktop;
  fillDesktop = function(ds){ AC_LAST_DS = ds || null; _fillDesktop(ds); };

  var _fillMobile = fillMobile;
  fillMobile = function(ds){ AC_LAST_DS = ds || null; _fillMobile(ds); };

  (function wirePriceToggle(){
    var toggle = document.getElementById("acPriceToggle");
    if (!toggle) return;

    toggle.addEventListener("change", function(){
      applyPriceMode(AC_LAST_DS, toggle.checked);
    });
  })();

  (function wireMobilePriceToggle(){
    var mobileToggle = document.getElementById("acMobilePriceToggle");
    if (!mobileToggle) return;

    mobileToggle.addEventListener("change", function(){
      applyPriceMode(AC_LAST_DS, mobileToggle.checked);
    });
  })();

})();
</script>옕�0ϳ����������J8)
�?�<?php
// =====================================================
// Inventory Item Detail (Elementor)
// URL: /index.php/inventory-more-details/?item=ITEMCODE&back=...
// View + Edit + Save
// - Images: SHOW (NOT editable)
// - Encrypted price/cost: SHOW (NOT editable)
// Requires: get_mssql_2019() exists
// =====================================================

/* =====================================================
   Helpers (MUST be defined BEFORE use)
===================================================== */
function h($v){ return htmlspecialchars((string)$v, ENT_QUOTES, 'UTF-8'); }

function fix_invsearch_double_path($url){
  return str_replace('/InventorySearch/InventorySearch/', '/InventorySearch/', (string)$url);
}

function detect_mime_from_bytes($bytes){
  if ($bytes === null || $bytes === '') return 'application/octet-stream';
  $b = (string)$bytes;

  // JPEG FF D8
  if (strlen($b) >= 2 && ord($b[0]) === 0xFF && ord($b[1]) === 0xD8) return 'image/jpeg';
  // PNG 89 50 4E 47
  if (strlen($b) >= 4 && ord($b[0]) === 0x89 && $b[1]==="P" && $b[2]==="N" && $b[3]==="G") return 'image/png';
  // GIF "GIF"
  if (strlen($b) >= 3 && $b[0]==="G" && $b[1]==="I" && $b[2]==="F") return 'image/gif';

  return 'application/octet-stream';
}

/* =====================================================
   SITE / ROUTE CONFIG (EDIT ONLY HERE)
===================================================== */
$APP_BASE_URL = 'https://website.ipohserver.com/ECOSalesInventorySearch';

// Inventory list page (main list)
$URL_INVENTORY_LIST = fix_invsearch_double_path($APP_BASE_URL . '/index.php/yong_tai_lie_data/');

// Inventory detail page (THIS PAGE URL)
$URL_INVENTORY_DETAIL = fix_invsearch_double_path($APP_BASE_URL . '/index.php/yong_tai_lie_data_details/');

// Home root for safety checks
$URL_SITE_ROOT = $APP_BASE_URL . '/';

// Only allow edit for logged-in users with capability
$EDIT_CAPABILITY = 'manage_options'; // change to 'edit_posts' if you want Editors to edit

/* =====================================================
   Access Guard
   - Allow POST (Save)
   - Allow referrer from list page OR same page
===================================================== */
$allowedBase = $URL_INVENTORY_LIST;

$ref = function_exists('wp_get_referer') ? (wp_get_referer() ?: '') : ($_SERVER['HTTP_REFERER'] ?? '');
$isPost = (($_SERVER['REQUEST_METHOD'] ?? '') === 'POST');

$selfUrl = (is_ssl() ? 'https://' : 'http://') . ($_SERVER['HTTP_HOST'] ?? '') . ($_SERVER['REQUEST_URI'] ?? '');
$selfBase = strtok($selfUrl, '#');

$detailsBase = fix_invsearch_double_path($APP_BASE_URL . '/index.php/yong_tai_lie_data_details/');

$refOk = (
  $ref !== '' &&
  (
    strpos($ref, $allowedBase) === 0 ||   // list
    strpos($ref, $detailsBase) === 0 ||   // details page
    strpos($ref, $selfBase) === 0         // same page (edit/save)
  )
);

if (!$isPost && !$refOk) {
  if (!headers_sent() && function_exists('wp_safe_redirect')) {
    wp_safe_redirect($allowedBase);
    exit;
  }
  echo '<script>window.location.replace(' . json_encode($allowedBase) . ');</script>';
  echo '<noscript><meta http-equiv="refresh" content="0;url=' . h($allowedBase) . '"></noscript>';
  return;
}

/* =====================================================
   1) Read item code from URL
===================================================== */
$item = isset($_GET['item']) ? trim((string)$_GET['item']) : '';

if ($item === '') {
  echo "<div style='padding:12px;border:1px solid #e5e7eb;background:#f9fafb;border-radius:10px'>
          No item selected.
        </div>";
  return;
}

// allowlist safety (allow # and * like your other pages)
if (!preg_match('/^[A-Z0-9 #\*\-\/\(\)\.\_]+$/', $item)) {
  echo "<div style='padding:12px;border:1px solid #fecaca;background:#fff1f2;color:#991b1b;border-radius:10px'>
          Invalid item code.
        </div>";
  return;
}

$isEdit = isset($_GET['edit']) && $_GET['edit'] === '1';

// ✅ Correct capability
$canEdit = function_exists('is_user_logged_in') && is_user_logged_in()
  && function_exists('current_user_can') && current_user_can($EDIT_CAPABILITY);

/* =====================================================
   2) Connect to MSSQL
===================================================== */
$conn = get_mssql_2019();
if (!$conn) {
  echo "<div style='padding:12px;border:1px solid #fecaca;background:#fff1f2;color:#991b1b;border-radius:10px'>
          Database connection failed.
        </div>";
  return;
}

/* =====================================================
   3) Handle Save (POST)
   - Update dbo.Item (text fields)
   - Update dbo.ItemUOM (barcode + shelf) for BaseUOM row
===================================================== */
if ($isPost && isset($_POST['ac_action']) && $_POST['ac_action'] === 'save') {

  if (!$canEdit) {
    wp_die('No permission.');
  }

  if (!isset($_POST['ac_nonce']) || !function_exists('wp_verify_nonce') || !wp_verify_nonce($_POST['ac_nonce'], 'ac_item_edit')) {
    wp_die('Security check failed.');
  }

  // ✅ Correct POST reading
  $p_item = trim((string)($_POST['item'] ?? ''));
  if ($p_item === '' || $p_item !== $item) {
    wp_die('Invalid item.');
  }

  $p_desc   = trim((string)($_POST['Description'] ?? ''));
  $p_desc2  = trim((string)($_POST['Desc2'] ?? ''));
  $p_group  = trim((string)($_POST['ItemGroup'] ?? ''));
  $p_type   = trim((string)($_POST['ItemType'] ?? ''));
  $p_model  = trim((string)($_POST['UDF_varModel'] ?? ''));
  $p_lmodel = trim((string)($_POST['UDF_varLongModel'] ?? ''));

  $p_barcode = trim((string)($_POST['BarCode'] ?? ''));
  $p_shelf   = trim((string)($_POST['Shelf'] ?? ''));

  // Get BaseUOM
  $sqlBase = "SELECT TOP 1 BaseUOM FROM dbo.Item WHERE ItemCode = ?";
  $stmtBase = sqlsrv_query($conn, $sqlBase, [$p_item]);
  $baseRow = $stmtBase ? sqlsrv_fetch_array($stmtBase, SQLSRV_FETCH_ASSOC) : null;
  $baseUOM = (string)($baseRow['BaseUOM'] ?? '');

  // Update dbo.Item
  $sqlUpItem = "
    UPDATE dbo.Item
    SET Description = ?,
        Desc2 = ?,
        ItemGroup = ?,
        ItemType = ?,
        UDF_varModel = ?,
        UDF_varLongModel = ?
    WHERE ItemCode = ?
  ";
  $ok1 = sqlsrv_query($conn, $sqlUpItem, [$p_desc, $p_desc2, $p_group, $p_type, $p_model, $p_lmodel, $p_item]);

  if (!$ok1) {
    echo "<pre style='white-space:pre-wrap'>" . h(print_r(sqlsrv_errors(), true)) . "</pre>";
    return;
  }

  // Update dbo.ItemUOM (BaseUOM row)
  if ($baseUOM !== '') {
    $sqlUpUom = "
      UPDATE dbo.ItemUOM
      SET BarCode = ?,
          Shelf = ?
      WHERE ItemCode = ?
        AND UOM = ?
    ";
    $ok2 = sqlsrv_query($conn, $sqlUpUom, [$p_barcode, $p_shelf, $p_item, $baseUOM]);

    if (!$ok2) {
      echo "<pre style='white-space:pre-wrap'>" . h(print_r(sqlsrv_errors(), true)) . "</pre>";
      return;
    }
  }

  // Redirect to GET (prevents double submit), keep item/back, exit edit mode
  $redirect = $URL_INVENTORY_DETAIL . '?item=' . rawurlencode($item) . '&updated=1';
  if (!empty($_GET['back'])) $redirect .= '&back=' . rawurlencode((string)$_GET['back']);
  if (!headers_sent() && function_exists('wp_safe_redirect')) {
    wp_safe_redirect($redirect);
    exit;
  }
  echo '<script>window.location.replace(' . json_encode($redirect) . ');</script>';
  return;
}

/* =====================================================
   4) Query item (includes encrypted + images)
===================================================== */
$sql = "
SELECT TOP 1
  i.ItemCode,
  i.Description,
  i.Desc2,
  i.ItemGroup,
  i.ItemType,
  i.UDF_varModel,
  i.UDF_varLongModel,
  i.BaseUOM,

  u.BarCode,
  u.Shelf,
  u.UDF_EncryptedPrice,
  u.UDF_EncryptedPrice2,
  u.UDF_EncryptedPrice3,
  u.UDF_EncryptedPrice4,
  u.UDF_EncryptedPrice5,
  u.UDF_EncryptedPrice6,
  u.UDF_EncryptedCost
FROM dbo.Item i
LEFT JOIN dbo.ItemUOM u
  ON u.ItemCode = i.ItemCode
 AND u.UOM = i.BaseUOM
WHERE i.ItemCode = ?
";

$stmt = sqlsrv_query($conn, $sql, [$item]);
if (!$stmt) {
  echo "<pre style='white-space:pre-wrap'>" . h(print_r(sqlsrv_errors(), true)) . "</pre>";
  return;
}

$row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
if (!$row) {
  echo "<div style='padding:12px;border:1px solid #e5e7eb;background:#f9fafb;border-radius:10px'>
          Item not found: <b>" . h($item) . "</b>
        </div>";
  return;
}

/* =====================================================
   5) Close button back URL
===================================================== */
$backUrl = '';
if (!empty($_GET['back'])) {
  $candidate = rawurldecode((string)$_GET['back']);
  if (strpos($candidate, $URL_SITE_ROOT) === 0) $backUrl = $candidate;
}
if ($backUrl === '') $backUrl = ($ref ?: $URL_INVENTORY_LIST);
if (strpos($backUrl, $URL_SITE_ROOT) !== 0) $backUrl = $URL_INVENTORY_LIST;
$backUrl = fix_invsearch_double_path($backUrl);

/* =====================================================
   6) Images panel (keep 16 slots)
   Table: dbo.Web_StockImages  Column: ImageData  WHERE ItemCode = ?
===================================================== */
$thumbs = array_fill(0, 16, '');

$sqlImg = "
  SELECT TOP 16
    ImageData
  FROM dbo.Web_StockImages
  WHERE ItemCode = ?
    AND ImageData IS NOT NULL
  ORDER BY (SELECT NULL)
";

$stmtImg = sqlsrv_query($conn, $sqlImg, [$row['ItemCode']]);
if ($stmtImg) {
  $idx = 0;
  while (($r = sqlsrv_fetch_array($stmtImg, SQLSRV_FETCH_ASSOC)) && $idx < 16) {
    $bin = $r['ImageData'];
    if (is_resource($bin)) $bin = stream_get_contents($bin);
    if ($bin === null || $bin === '') continue;

    $mime = detect_mime_from_bytes($bin);
    $b64  = base64_encode($bin);
    $thumbs[$idx] = "data:{$mime};base64,{$b64}";
    $idx++;
  }
} else {
  error_log('Web_StockImages query failed: ' . print_r(sqlsrv_errors(), true));
}
?>
<style>
  .aps-wrap{
    max-width:1100px;
    margin:16px auto;
    padding:10px;
    border:1px solid #c9d2dd;
    border-radius:6px;
    background:#fff;
    font-family:"Nunito", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  }
  .aps-top{
    display:flex; align-items:center; justify-content:space-between; gap:10px;
    padding:6px 6px 10px;
    border-bottom:1px solid #dbe3ee;
  }
  .aps-title{ font-size:14px; font-weight:700; color:#0f172a; }
  .aps-sub{ font-size:12px; color:#475569; margin-top:2px; }
  .aps-btn{
    text-decoration:none;
    font-size:12px;
    padding:7px 10px;
    border:1px solid #c9d2dd;
    border-radius:4px;
    background:#f3f6fb;
    color:#111827;
    display:inline-block;
    cursor:pointer;
  }

  .aps-grid{
    display:grid;
    grid-template-columns: 1fr 360px 260px;
    gap:12px;
    padding:10px 6px 6px;
    align-items:start;
  }
  @media (max-width: 980px){
    .aps-grid{ grid-template-columns:1fr; }
  }

  .aps-row{
    display:grid;
    grid-template-columns: 140px 1fr;
    gap:8px;
    align-items:center;
    margin-top:8px;
  }
  .aps-lbl{ font-size:12px; color:#0f172a; }
  .aps-inp{
    width:100%;
    border:1px solid #b9c6d6;
    background:#f7f7f7;
    border-radius:2px;
    padding:6px 7px;
    font-size:12px;
    color:#111827;
  }
  .aps-inp.editable{
    background:#fff;
  }

  .aps-block{
    border:1px solid #c9d2dd;
    border-radius:4px;
    padding:8px;
    background:#fff;
    margin-bottom:10px;
  }

  .aps-imgpanel{
    border:1px solid #c9d2dd;
    border-radius:4px;
    background:#fff;
    padding:8px;
  }
  .aps-preview{
    width:100%;
    height:150px;
    border:1px solid #b9c6d6;
    background:#f7f7f7;
    border-radius:2px;
    display:flex;
    align-items:center;
    justify-content:center;
    font-size:12px;
    color:#64748b;
    margin-bottom:10px;
    overflow:hidden;
    cursor: zoom-in;
  }
  .aps-preview img{
    width:100%;
    height:100%;
    object-fit:contain;
    display:block;
  }
  .aps-thumbs{
    display:grid;
    grid-template-columns: repeat(4, 1fr);
    gap:6px;
  }
  .aps-thumb{
    aspect-ratio:1/1;
    border:1px solid #b9c6d6;
    background:#ffffff;
    border-radius:2px;
    cursor:pointer;
    overflow:hidden;
    display:flex;
    align-items:center;
    justify-content:center;
    font-size:11px;
    color:#94a3b8;
  }
  .aps-thumb img{
    width:100%;
    height:100%;
    object-fit:cover;
    display:block;
  }
  .aps-thumb.is-active{
    outline:2px solid #2563eb;
    outline-offset:1px;
  }

  /* Lightbox */
  .aps-lightbox{
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,.75);
    display: none;
    align-items: center;
    justify-content: center;
    z-index: 999999;
    padding: 20px;
  }
  .aps-lightbox.is-open{ display:flex; }
  .aps-lightbox-inner{
    position: relative;
    max-width: min(1100px, 95vw);
    max-height: 90vh;
    background: #0b1220;
    border-radius: 10px;
    overflow: hidden;
    box-shadow: 0 10px 30px rgba(0,0,0,.35);
  }
  .aps-lightbox img{
    display:block;
    width:100%;
    height:auto;
    max-height: 90vh;
    object-fit: contain;
    background: #0b1220;
  }
  .aps-lightbox-close{
    position:absolute;
    top:10px;
    right:10px;
    width:36px;
    height:36px;
    border-radius:999px;
    border:1px solid rgba(255,255,255,.25);
    background: rgba(0,0,0,.35);
    color:#fff;
    font-size:18px;
    line-height:34px;
    text-align:center;
    cursor:pointer;
    user-select:none;
  }
  .aps-lightbox-close:hover{ background: rgba(0,0,0,.55); }
</style>

<div class="aps-wrap">
  <div class="aps-top">
    <div>
      <div class="aps-title">More Info, Item Code: <?=h($row['ItemCode'])?></div>
      <div class="aps-sub"><?=h($row['Description'] ?? '')?></div>
    </div>

    <div style="display:flex; gap:8px; align-items:center;">
      <?php if ($canEdit && !$isEdit): ?>
        <?php
        $editHref = $URL_INVENTORY_DETAIL . '?item=' . rawurlencode($row['ItemCode']);
        if (!empty($_GET['back'])) $editHref .= '&back=' . rawurlencode((string)$_GET['back']);
        $editHref .= '&edit=1';
        ?>
        <a href="<?=h($editHref)?>" class="aps-btn">Edit</a>
      <?php endif; ?>

      <?php if ($canEdit && $isEdit): ?>
        <button type="submit" form="acEditForm" class="aps-btn" style="background:#e0f2fe;border-color:#7dd3fc;">Save</button>
        <a class="aps-btn" href="<?=h(remove_query_arg('edit'))?>">Cancel</a>
      <?php endif; ?>

      <a class="aps-btn" href="<?=h($backUrl)?>">Close</a>
    </div>
  </div>

  <?php if ($canEdit && $isEdit): ?>
    <form id="acEditForm" method="post">
      <?php wp_nonce_field('ac_item_edit', 'ac_nonce'); ?>
      <input type="hidden" name="ac_action" value="save">
      <input type="hidden" name="item" value="<?=h($row['ItemCode'])?>">
  <?php endif; ?>

  <div class="aps-grid">
    <!-- LEFT -->
    <div>
      <div class="aps-block">

        <div class="aps-row">
          <div class="aps-lbl">Description</div>
          <input class="aps-inp <?=($canEdit && $isEdit?'editable':'')?>" name="Description"
                  <?=($canEdit && $isEdit?'':'readonly')?>
                  value="<?=h($row['Description'] ?? '')?>"
                  data-original="<?=h($row['Description'] ?? '')?>">
        </div>

        <div class="aps-row">
          <div class="aps-lbl">Description 2</div>
          <input class="aps-inp <?=($canEdit && $isEdit?'editable':'')?>" name="Desc2"
                <?=($canEdit && $isEdit?'':'readonly')?> value="<?=h($row['Desc2'] ?? '')?>"
                data-original="<?=h($row['Desc2'] ?? '')?>">
        </div>

        <div class="aps-row">
          <div class="aps-lbl">Barcode</div>
          <input class="aps-inp <?=($canEdit && $isEdit?'editable':'')?>" name="BarCode"
                <?=($canEdit && $isEdit?'':'readonly')?> value="<?=h($row['BarCode'] ?? '')?>"
                data-original="<?=h($row['BarCode'] ?? '')?>">
        </div>

        <div class="aps-row">
          <div class="ap�J8)N�:����������J8)
� �����s-lbl">Location</div>
          <input class="aps-inp <?=($canEdit && $isEdit?'editable':'')?>" name="Shelf"
                <?=($canEdit && $isEdit?'':'readonly')?> value="<?=h($row['Shelf'] ?? '')?>"
                data-original="<?=h($row['Shelf'] ?? '')?>">
        </div>

        <div class="aps-row">
          <div class="aps-lbl">Item Group</div>
          <input class="aps-inp <?=($canEdit && $isEdit?'editable':'')?>" name="ItemGroup"
                <?=($canEdit && $isEdit?'':'readonly')?> value="<?=h($row['ItemGroup'] ?? '')?>"
                data-original="<?=h($row['ItemGroup'] ?? '')?>">
        </div>

        <div class="aps-row">
          <div class="aps-lbl">Item Type</div>
          <input class="aps-inp <?=($canEdit && $isEdit?'editable':'')?>" name="ItemType"
                <?=($canEdit && $isEdit?'':'readonly')?> value="<?=h($row['ItemType'] ?? '')?>"
                data-original="<?=h($row['ItemType'] ?? '')?>">
        </div>

        <div class="aps-row">
          <div class="aps-lbl">varModel</div>
          <input class="aps-inp <?=($canEdit && $isEdit?'editable':'')?>" name="UDF_varModel"
                <?=($canEdit && $isEdit?'':'readonly')?> value="<?=h($row['UDF_varModel'] ?? '')?>"
                data-original="<?=h($row['UDF_varModel'] ?? '')?>">
        </div>

        <div class="aps-row">
          <div class="aps-lbl">varLongModel</div>
          <input class="aps-inp <?=($canEdit && $isEdit?'editable':'')?>" name="UDF_varLongModel"
                <?=($canEdit && $isEdit?'':'readonly')?> value="<?=h($row['UDF_varLongModel'] ?? '')?>"
                data-original="<?=h($row['UDF_varLongModel'] ?? '')?>">
        </div>

      </div>
    </div>

    <!-- MIDDLE (encrypted - readonly always) -->
    <div>
      <div class="aps-block">
        <div class="aps-row">
          <div class="aps-lbl">Encrypted Price</div>
          <input class="aps-inp" readonly value="<?=h($row['UDF_EncryptedPrice'] ?? '')?>">
        </div>
        <div class="aps-row">
          <div class="aps-lbl">Encrypted Price 2</div>
          <input class="aps-inp" readonly value="<?=h($row['UDF_EncryptedPrice2'] ?? '')?>">
        </div>
        <div class="aps-row">
          <div class="aps-lbl">Encrypted Price 3</div>
          <input class="aps-inp" readonly value="<?=h($row['UDF_EncryptedPrice3'] ?? '')?>">
        </div>
        <div class="aps-row">
          <div class="aps-lbl">Encrypted Price 4</div>
          <input class="aps-inp" readonly value="<?=h($row['UDF_EncryptedPrice4'] ?? '')?>">
        </div>
        <div class="aps-row">
          <div class="aps-lbl">Encrypted Price 5</div>
          <input class="aps-inp" readonly value="<?=h($row['UDF_EncryptedPrice5'] ?? '')?>">
        </div>
        <div class="aps-row">
          <div class="aps-lbl">Encrypted Price 6</div>
          <input class="aps-inp" readonly value="<?=h($row['UDF_EncryptedPrice6'] ?? '')?>">
        </div>
        <div class="aps-row">
          <div class="aps-lbl">Encrypted Cost</div>
          <input class="aps-inp" readonly value="<?=h($row['UDF_EncryptedCost'] ?? '')?>">
        </div>
      </div>
    </div>

    <!-- RIGHT (images) -->
    <div class="aps-imgpanel" data-itemcode="<?=h($row['ItemCode'])?>">
      <div class="aps-preview" id="apsPreview">No Image</div>
      <div class="aps-thumbs" id="apsThumbs">
        <?php foreach ($thumbs as $idx => $url): ?>
          <div class="aps-thumb" data-url="<?=h($url)?>" title="Image <?=($idx+1)?>">
            <?php if ($url): ?><img src="<?=h($url)?>" alt=""><?php endif; ?>
          </div>
        <?php endforeach; ?>
      </div>
    </div>
  </div> <!-- end .aps-grid -->

  <?php if ($canEdit && $isEdit): ?>
    </form>
  <?php endif; ?>

  </div> <!-- end .aps-wrap -->


<div class="aps-lightbox" id="apsLightbox" aria-hidden="true">
  <div class="aps-lightbox-inner" role="dialog" aria-modal="true">
    <div class="aps-lightbox-close" id="apsLightboxClose" title="Close">✕</div>
    <img id="apsLightboxImg" src="" alt="">
  </div>
</div>

<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>

<script>
(function(){
  const preview = document.getElementById('apsPreview');
  const thumbs  = document.getElementById('apsThumbs');
  if(!preview || !thumbs) return;

  const lb      = document.getElementById('apsLightbox');
  const lbImg   = document.getElementById('apsLightboxImg');
  const lbClose = document.getElementById('apsLightboxClose');

  let currentUrl = '';

  function setPreview(url, el){
    thumbs.querySelectorAll('.aps-thumb').forEach(x => x.classList.remove('is-active'));
    if(el) el.classList.add('is-active');

    currentUrl = (url || '').trim();

    if(!currentUrl){
      preview.style.cursor = 'default';
      preview.innerHTML = 'No Image';
      return;
    }

    preview.style.cursor = 'zoom-in';
    preview.innerHTML = '';
    const img = document.createElement('img');
    img.src = currentUrl;
    img.alt = '';
    preview.appendChild(img);
  }

  thumbs.addEventListener('click', function(e){
    const t = e.target.closest('.aps-thumb');
    if(!t) return;
    const url = (t.getAttribute('data-url') || '').trim();
    setPreview(url, t);
  });

  preview.addEventListener('click', function(){
    if(!currentUrl) return;
    lbImg.src = currentUrl;
    lb.classList.add('is-open');
    lb.setAttribute('aria-hidden', 'false');
  });

  function closeLightbox(){
    lb.classList.remove('is-open');
    lb.setAttribute('aria-hidden', 'true');
    lbImg.src = '';
  }

  if (lbClose) lbClose.addEventListener('click', closeLightbox);

  if (lb) lb.addEventListener('click', function(e){
    if (e.target === lb) closeLightbox();
  });

  document.addEventListener('keydown', function(e){
    if (e.key === 'Escape' && lb.classList.contains('is-open')) closeLightbox();
  });

  const firstWithUrl = Array.from(thumbs.querySelectorAll('.aps-thumb'))
    .find(el => (el.getAttribute('data-url') || '').trim() !== '');
  if(firstWithUrl){
    setPreview(firstWithUrl.getAttribute('data-url'), firstWithUrl);
  }
})();
</script>

<script>
(function(){
  const form = document.getElementById('acEditForm');
  if (!form) return;

  const saveBtn = document.querySelector('button[form="acEditForm"]');
  if (!saveBtn) return;

  saveBtn.addEventListener('click', function(e){
    e.preventDefault(); // ⛔ stop normal submit

    const changes = [];
    form.querySelectorAll('input[data-original]').forEach(input => {
      const original = input.dataset.original ?? '';
      const current  = input.value ?? '';

      if (original !== current) {
        const label = input.closest('.aps-row')?.querySelector('.aps-lbl')?.innerText || input.name;
        changes.push(`<b>${label}</b><br>${original || '(empty)'} → <b>${current || '(empty)'}</b>`);
      }
    });

    if (changes.length === 0) {
      Swal.fire({
        icon: 'info',
        title: 'No changes detected',
        text: 'Nothing to update.'
      });
      return;
    }

    Swal.fire({
      title: 'Confirm update?',
      html: `
        <div style="text-align:left;font-size:13px;max-height:300px;overflow:auto">
          ${changes.join('<hr style="margin:6px 0">')}
        </div>
      `,
      icon: 'warning',
      showCancelButton: true,
      confirmButtonText: 'Yes, update',
      cancelButtonText: 'Cancel',
      confirmButtonColor: '#2563eb'
    }).then(result => {
      if (result.isConfirmed) {
        form.submit(); // ✅ now submit to PHP
      }
    });
  });
})();
</script>

<script>
(function(){
  const params = new URLSearchParams(window.location.search);
  if (params.get('updated') !== '1') return;

  Swal.fire({
    icon: 'success',
    title: 'Updated',
    text: 'Your changes have been saved.',
    confirmButtonText: 'OK'
  }).then(() => {
    // remove updated=1 from URL so refresh won’t show again
    params.delete('updated');
    const cleanUrl = window.location.pathname + (params.toString() ? '?' + params.toString() : '');
    window.history.replaceState({}, '', cleanUrl);
  });
})();
</script>�J8)������������Jƨ
�?�<?php
/**
 * RESPONSIVE CASH SALES TABLE — REDESIGN ONLY
 * - Desktop: Premium table view
 * - Tablet/Mobile: Modern accordion cards
 * - AJAX Search with dropdown suggestions (searches by DEBTOR NAME)
 * - Shows 50 latest records by default, all when searching
 * - Primary color: #0082ff
 * 
 * FIX: Alias formatted date as DocDateDisplay to avoid confusion with original DocDate used in ORDER BY.
 *      Sorting is by DocDate DESC, DocNo DESC (date then document number).
 */

if (!defined('ABSPATH')) exit;

// ===== ACCESS CONTROL =====
if (!is_user_logged_in()) {
    echo '<p style="text-align:center;padding:20px;">Please log in to view this page.</p>';
    return;
}

// ===== GET SEARCH TERM =====
$search = isset($_GET['search']) ? trim(sanitize_text_field($_GET['search'])) : '';

// ===== BUILD QUERY =====
$conn = null;
$rows = [];

// FIXED: use the correct function name in the check
if (function_exists('get_mssql_cash_sale_test_db')) {
    $conn = get_mssql_cash_sale_test_db();
    if ($conn) {
        $sql = "SELECT 
                    DocNo,
                    CONVERT(varchar, DocDate, 103) as DocDateDisplay,  -- formatted for display
                    DebtorCode,
                    DebtorName,
                    SalesLocation,
                    PaymentMode,
                    FinalTotal,
                    Remark1
                FROM dbo.CS 
                WHERE ISNULL(Cancelled, 'F') <> 'T'";
        
        $params = [];
        
        if (!empty($search)) {
            $sql .= " AND DebtorName LIKE ?";
            $searchParam = "%$search%";
            $params = [$searchParam];
        }
        
        // Sort by date descending, then by document number descending
        $sql .= " ORDER BY DocDate DESC, DocNo DESC";
        
        if (empty($search)) {
            $sql .= " OFFSET 0 ROWS FETCH NEXT 50 ROWS ONLY";
        }
        
        $stmt = sqlsrv_query($conn, $sql, $params);
        
        if ($stmt) {
            while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
                $rows[] = $row;
            }
            sqlsrv_free_stmt($stmt);
        }
        sqlsrv_close($conn);
    }
}

// ----- UPDATED FUNCTION -----
function format_payment_mode($mode) {
    if ($mode === null || $mode === '' || $mode === false) {
        return 'Not Paid';
    }

    $mode = trim((string)$mode);

    $map = [
        '0' => 'Not Paid',
        '1' => 'Cash',
        '2' => 'Credit',
    ];

    return $map[$mode] ?? $mode;
}
// ---------------------------

$ajax_url = admin_url('admin-ajax.php');
// CORRECT: debtor search nonce (UPDATED)
$search_nonce = wp_create_nonce('wst_cashsale_debtor_search_testdb');

$create_url = 'https://website.ipohserver.com/ECOSalesInventorySearch/index.php/cash-sale-new/';
$edit_base = 'https://website.ipohserver.com/ECOSalesInventorySearch/index.php/cash-sale-edit/';

$refresh_qs = !empty($search) ? 'search=' . urlencode($search) : '';
$refresh_url = '?' . $refresh_qs;
?>

<div class="ac-cs-app">
    <style>
        /* ===== MODIFIED: .ac-cs-app now allows Elementor to control sizing ===== */
        .ac-cs-app{
            --ac-primary:#0082ff;
            --ac-primary-dark:#0068cc;
            --ac-primary-soft:#e8f3ff;
            --ac-bg:#f4f8fc;
            --ac-card:#ffffff;
            --ac-text:#0f172a;
            --ac-muted:#64748b;
            --ac-line:#dbe7f3;
            --ac-success:#16a34a;
            --ac-success-soft:#ecfdf3;
            --ac-warn:#b45309;
            --ac-warn-soft:#fff7ed;
            --ac-shadow:0 10px 30px rgba(15, 23, 42, 0.08);
            --ac-radius:20px;
            --ac-radius-sm:14px;

            font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Inter,Arial,sans-serif;
            color:var(--ac-text);

            /* Let Elementor control dimensions */
            width:100%;
            max-width:100%;
            min-width:0;
            height:100%;
            min-height:0;

            margin:0;
            padding:0;
            background:transparent;
            box-sizing:border-box;
            overflow:visible;
        }

        .ac-cs-app *,
        .ac-cs-app *::before,
        .ac-cs-app *::after{
            box-sizing:border-box;
        }

        /* ===== MODIFIED: .ac-cs-shell no longer enforces fixed width ===== */
        .ac-cs-shell{
            width:100%;
            max-width:100%;
            min-width:0;
            height:100%;
            min-height:0;

            margin:0;
            padding:0;
            box-sizing:border-box;
        }

        /* ===== COMPACT HERO STYLES ===== */
        /* --- FIX: Allow dropdown to overflow and not clip --- */
        .ac-cs-hero{
            position:relative;
            overflow: visible !important;   /* was hidden */
            background:
                radial-gradient(circle at top right, rgba(255,255,255,.18), transparent 28%),
                linear-gradient(135deg, #0082ff 0%, #1f96ff 50%, #66c4ff 100%);
            border-radius:24px;
            padding:16px 18px;
            color:#fff;
            box-shadow:0 14px 30px rgba(0,130,255,.18);
            margin-bottom:12px;
            isolation: auto !important;      /* was isolate */
            z-index:20;
        }

        .ac-cs-hero::before{
            content:"";
            position:absolute;
            inset:0;
            background:
                linear-gradient(180deg, rgba(255,255,255,.08) 0%, rgba(255,255,255,0) 40%),
                radial-gradient(circle at 18% 18%, rgba(255,255,255,.10), transparent 22%);
            pointer-events:none;
            z-index:0;
        }

        .ac-cs-hero::after{
            content:"";
            position:absolute;
            inset:auto -40px -60px auto;
            width:180px;
            height:180px;
            border-radius:50%;
            background:rgba(255,255,255,.10);
            filter:blur(2px);
            z-index:0;
        }

        .ac-cs-hero-top{
            position:relative;
            z-index:1;
            display:flex;
            align-items:flex-start;
            justify-content:space-between;
            gap:14px;
            flex-wrap:wrap;
            margin-bottom:14px;
        }

        .ac-cs-title-wrap{
            min-width:0;
        }

        .ac-cs-kicker{
            display:inline-flex;
            align-items:center;
            gap:7px;
            font-size:11px;
            font-weight:800;
            letter-spacing:.08em;
            text-transform:uppercase;
            padding:6px 10px;
            border-radius:999px;
            background:rgba(255,255,255,.14);
            backdrop-filter:blur(6px);
            margin-bottom:10px;
            color:#fff;
        }

        /* .ac-cs-title and .ac-cs-subtitle kept for compatibility (not used) */
        .ac-cs-title{
            margin:0;
            font-size:24px;
            line-height:1.02;
            font-weight:900;
            letter-spacing:-.03em;
            color:#fff;
            text-shadow:0 1px 2px rgba(0,0,0,.10);
        }

        .ac-cs-subtitle{
            margin:8px 0 0;
            max-width:680px;
            font-size:13px;
            line-height:1.5;
            color:rgba(255,255,255,.93);
        }

        .ac-cs-hero-actions{
            display:flex;
            gap:10px;
            flex-wrap:wrap;
        }

        /* ===== HERO SEARCH STYLES ===== */
        .ac-cs-hero-search{
            position:relative;
            z-index:30;
        }

        .ac-cs-hero-search .ac-cs-search-form{
            gap:0;
        }

        .ac-cs-hero-search .ac-cs-search-row{
            display:flex;
            flex-direction:row;
            align-items:stretch;
            gap:10px;
        }

        .ac-cs-hero-search .ac-cs-search-wrapper{
            flex:1;
            min-width:0;
            position:relative;
            z-index:9999;          /* extra high to stay above table */
        }

        .ac-cs-hero-search .ac-cs-search-input{
            height:50px;
            border:none;
            background:rgba(255,255,255,.96);
            color:var(--ac-text);
            box-shadow:0 8px 24px rgba(0,0,0,.10);
        }

        .ac-cs-hero-search .ac-cs-search-input::placeholder{
            color:#7c8da3;
        }

        .ac-cs-hero-search .ac-cs-search-input:focus{
            box-shadow:
                0 0 0 4px rgba(255,255,255,.18),
                0 8px 24px rgba(0,0,0,.10);
        }

        .ac-cs-hero-search .ac-cs-search-actions{
            flex-wrap:nowrap;
        }

        .ac-cs-hero-search .ac-cs-search-btn,
        .ac-cs-hero-search .ac-cs-clear-btn{
            min-height:50px;
            border-radius:14px;
        }

        .ac-cs-hero-search .ac-cs-search-btn{
            background:#ffffff;
            color:var(--ac-primary);
            box-shadow:0 8px 20px rgba(0,0,0,.10);
        }

        .ac-cs-hero-search .ac-cs-search-btn:hover{
            background:#f8fbff;
            color:var(--ac-primary-dark);
        }

        .ac-cs-hero-search .ac-cs-clear-btn{
            border:1px solid rgba(255,255,255,.32);
            background:rgba(255,255,255,.14);
            color:#fff;
            backdrop-filter:blur(8px);
        }

        .ac-cs-hero-search .ac-cs-clear-btn:hover{
            background:rgba(255,255,255,.22);
            color:#fff;
            border-color:rgba(255,255,255,.45);
        }

        .ac-cs-btn{
            appearance:none;
            border:none;
            text-decoration:none;
            display:inline-flex;
            align-items:center;
            justify-content:center;
            gap:8px;
            min-height:46px;
            padding:0 16px;
            border-radius:14px;
            font-size:14px;
            font-weight:800;
            cursor:pointer;
            transition:transform .16s ease, box-shadow .16s ease, background .16s ease, border-color .16s ease;
            white-space:nowrap;
        }

        .ac-cs-btn:hover{ transform:translateY(-1px); }
        .ac-cs-btn:active{ transform:translateY(0); }

        .ac-cs-btn-primary{
            background:#fff;
            color:var(--ac-primary);
            box-shadow:0 8px 18px rgba(0,0,0,.12);
        }

        .ac-cs-btn-primary:hover{
            background:#f8fbff;
            color:var(--ac-primary-dark);
        }

        .ac-cs-btn-glass{
            background:rgba(255,255,255,.14);
            color:#fff;
            border:1px solid rgba(255,255,255,.22);
            backdrop-filter:blur(8px);
        }

        .ac-cs-btn-glass:hover{
            background:rgba(255,255,255,.22);
            color:#fff;
        }

        /* ===== SEARCH DROPDOWN ===== */
        .ac-cs-search-form{
            display:flex;
            flex-direction:column;
            gap:10px;
        }

        .ac-cs-search-row{
            display:flex;
            flex-direction:column;
            gap:10px;
        }

        .ac-cs-search-wrapper{
            position:relative;
            flex:1;
            min-width:0;
        }

        .ac-cs-search-input{
            width:100%;
            height:48px;
            border:1px solid var(--ac-line);
            border-radius:14px;
            padding:0 16px;
            font-size:14px;
            color:var(--ac-text);
            background:#fff;
            box-shadow:inset 0 1px 0 rgba(255,255,255,.8);
            transition:border-color .16s ease, box-shadow .16s ease, background .16s ease;
        }

        .ac-cs-search-input::placeholder{
            color:#94a3b8;
        }

        .ac-cs-search-input:focus{
            outline:none;
            border-color:rgba(0,130,255,.55);
            box-shadow:0 0 0 4px rgba(0,130,255,.12);
        }

        .ac-cs-search-actions{
            display:flex;
            gap:10px;
            flex-wrap:wrap;
        }

        .ac-cs-search-btn,
        .ac-cs-clear-btn{
            min-height:48px;
            border-radius:14px;
            padding:0 16px;
            font-size:13px;
            font-weight:800;
            text-decoration:none;
            display:inline-flex;
            align-items:center;
            justify-content:center;
        }

        .ac-cs-search-btn{
            border:none;
            background:linear-gradient(135deg, var(--ac-primary) 0%, #2aa3ff 100%);
            color:#fff;
            box-shadow:0 10px 22px rgba(0,130,255,.2);
            cursor:pointer;
        }

        .ac-cs-search-btn:hover{
            background:linear-gradient(135deg, var(--ac-primary-dark) 0%, #158cff 100%);
        }

        .ac-cs-clear-btn{
            border:1px solid var(--ac-line);
            background:#fff;
            color:var(--ac-muted);
        }

        .ac-cs-clear-btn:hover{
            border-color:#bfd8f1;
            background:#f8fbff;
            color:var(--ac-primary-dark);
        }

        .ac-cs-search-dropdown{
            position:absolute;
            top:calc(100% + 8px);
            left:0;
            right:0;
            z-index:10000;          /* Ensure it sits above everything */
            display:none;
            overflow:hidden;
            background:#fff;
            border:1px solid var(--ac-line);
            border-radius:18px;
            box-shadow:0 24px 38px rgba(15,23,42,.14);
            max-height:320px;
            overflow-y:auto;
        }

        .ac-cs-search-dropdown.active{ display:block; }

        .ac-cs-dropdown-item{
            padding:14px 16px;
            cursor:pointer;
            border-bottom:1px solid #eef4fa;
            transition:background .16s ease;
        }

        .ac-cs-dropdown-item:last-child{ border-bottom:none; }

        .ac-cs-dropdown-item:hover,
        .ac-cs-dropdown-item.active{
            background:var(--ac-primary-soft);
        }

        .ac-cs-dropdown-item strong{
            display:block;
            font-size:15px;
            line-height:1.3;
            color:var(--ac-text);
            margin-bottom:4px;
        }

        .ac-cs-dropdown-item small{
            color:var(--ac-muted);
            font-size:12px;
        }

        .ac-cs-dropdown-empty,
        .ac-cs-dropdown-error{
            padding:15px 16px;
            text-align:center;
            font-size:13px;
            color:var(--ac-muted);
        }

        .ac-cs-dropdown-error{ color:#b91c1c; }

        .ac-cs-search-info{
            display:flex;
            align-items:center;
            gap:10px;
            margin-top:12px;
            padding:12px 14px;
            border-radius:16px;
            background:var(--ac-primary-soft);
            color:var(--ac-primary-dark);
            font-size:14px;
            font-weight:700;
        }

        .ac-cs-search-info-badge{
            display:inline-flex;
            align-items:center;
            justify-content:center;
            width:28px;
            height:28px;
            border-radius:999px;
            background:#fff;
            color:var(--ac-primary);
            font-weight:900;
            flex:0 0 auto;
        }

        .ac-cs-data-wrap{
            margin-top:16px;
            position:relative;
            z-index:1;
        }

        /* ===== TABLE STYLES (removed table-head and footer) ===== */
        .ac-cs-table-card,
        .ac-cs-empty-state{
            background:rgba(255,255,255,.94);
            border:1px solid rgba(219,231,243,.95);
            border-radius:24px;
            box-shadow:var(--ac-shadow);
            overflow:hidden;
        }

        /* Exact height for 10 rows (header 50px + 10 rows of 44px = 490px) */
        .ac-cs-table-wrapper{
           �Jƨ0E����������K�
�?�  overflow-x:auto;
            overflow-y:auto;
            height:490px;
            max-height:490px;
            scrollbar-width:thin;
        }

        .ac-cs-table{
            width:100%;
            min-width:980px;
            border-collapse:separate;
            border-spacing:0;
        }

        .ac-cs-table thead th{
            position:sticky;
            top:0;
            z-index:2;
            height:50px;
            padding:11px 14px;
            text-align:left;
            font-size:11px;
            font-weight:900;
            letter-spacing:.08em;
            text-transform:uppercase;
            color:#fff;
            background:linear-gradient(135deg, var(--ac-primary) 0%, #2aa3ff 100%);
        }

        .ac-cs-table tbody tr{
            height:44px;
            transition:background .14s ease;
        }

        .ac-cs-table tbody td{
            height:44px;
            padding:10px 14px;
            border-bottom:1px solid #edf3f9;
            vertical-align:middle;
            color:#1e293b;
            font-size:13px;
            background:#fff;
        }

        .ac-cs-table tbody tr:hover td{
            background:#f9fcff;
        }

        .ac-cs-doc-link{
            color:var(--ac-primary-dark);
            text-decoration:none;
            font-weight:900;
        }

        .ac-cs-doc-link:hover{
            color:var(--ac-primary);
            text-decoration:underline;
        }

        .ac-cs-debtor-name{
            font-weight:900;
            color:var(--ac-text);
        }

        .ac-cs-code{
            display:inline-flex;
            align-items:center;
            padding:5px 9px;
            border-radius:999px;
            background:#f1f7ff;
            color:#285b8f;
            font-size:11px;
            font-weight:800;
        }

        .ac-cs-payment-chip,
        .ac-cs-location-chip{
            display:inline-flex;
            align-items:center;
            padding:6px 9px;
            border-radius:999px;
            font-size:11px;
            font-weight:800;
            line-height:1;
            white-space:nowrap;
        }

        .ac-cs-payment-chip{
            background:#eef7ff;
            color:#0b63b6;
        }

        .ac-cs-location-chip{
            background:#f8fafc;
            color:#475569;
        }

        .ac-cs-remark{
            max-width:180px;
            overflow:hidden;
            text-overflow:ellipsis;
            white-space:nowrap;
            color:#64748b;
            font-size:12px;
        }

        .ac-cs-accordion{
            display:none;
        }

        .ac-cs-card-list{
            display:flex;
            flex-direction:column;
            gap:10px;
            max-height:calc(10 * 86px);
            overflow-y:auto;
            padding-right:4px;
            scrollbar-width:thin;
        }

        .ac-cs-card{
            background:rgba(255,255,255,.96);
            border:1px solid rgba(219,231,243,.95);
            border-radius:18px;
            box-shadow:var(--ac-shadow);
            overflow:hidden;
        }

        .ac-cs-card-head{
            padding:13px 14px;
            cursor:pointer;
            display:flex;
            align-items:center;
            justify-content:space-between;
            gap:10px;
            transition:background .16s ease;
            border-left:4px solid var(--ac-primary);
        }

        .ac-cs-card-head:hover{
            background:#f9fcff;
        }

        .ac-cs-card-head.active{
            background:linear-gradient(180deg, #ffffff 0%, #f5faff 100%);
        }

        .ac-cs-card-main{
            min-width:0;
            flex:1;
        }

        .ac-cs-card-name{
            font-size:15px;
            font-weight:900;
            color:var(--ac-text);
            line-height:1.25;
            margin-bottom:6px;
            word-break:break-word;
        }

        .ac-cs-card-meta{
            display:flex;
            flex-wrap:wrap;
            gap:6px;
            color:var(--ac-muted);
            font-size:11px;
            font-weight:700;
        }

        .ac-cs-card-meta span{
            display:inline-flex;
            align-items:center;
            gap:5px;
            padding:5px 8px;
            border-radius:999px;
            background:#f8fbff;
            border:1px solid #e7f0f9;
        }

        .ac-cs-card-right{
            display:flex;
            align-items:center;
            gap:10px;
            flex:0 0 auto;
        }

        .ac-cs-card-total{
            font-size:16px;
            font-weight:900;
            color:var(--ac-success);
            text-align:right;
            white-space:nowrap;
        }

        .ac-cs-card-icon{
            width:32px;
            height:32px;
            border-radius:999px;
            background:var(--ac-primary-soft);
            color:var(--ac-primary);
            display:inline-flex;
            align-items:center;
            justify-content:center;
            font-size:14px;
            font-weight:900;
            transition:transform .24s ease;
        }

        .ac-cs-card-head.active .ac-cs-card-icon{
            transform:rotate(180deg);
        }

        .ac-cs-card-body{
            display:none;
            padding:0 14px 14px;
        }

        .ac-cs-card-body.active{
            display:block;
        }

        .ac-cs-card-panel{
            background:#fbfdff;
            border:1px solid #edf3f9;
            border-radius:15px;
            padding:12px;
        }

        .ac-cs-grid{
            display:grid;
            grid-template-columns:1fr;
            gap:12px;
        }

        .ac-cs-field{
            display:flex;
            flex-direction:column;
            gap:5px;
        }

        .ac-cs-field-label{
            font-size:11px;
            line-height:1.2;
            text-transform:uppercase;
            letter-spacing:.08em;
            font-weight:900;
            color:#94a3b8;
        }

        .ac-cs-field-value{
            font-size:14px;
            color:var(--ac-text);
            font-weight:700;
            line-height:1.45;
            word-break:break-word;
        }

        .ac-cs-field-value.remark{
            background:var(--ac-warn-soft);
            color:var(--ac-warn);
            border-radius:14px;
            padding:10px 12px;
            font-weight:700;
        }

        .ac-cs-doc-pill{
            display:inline-flex;
            align-items:center;
            padding:8px 12px;
            border-radius:999px;
            background:#eef7ff;
            font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;
            font-size:13px;
            font-weight:800;
        }

        .ac-cs-empty-state{
            text-align:center;
            padding:42px 20px;
        }

        .ac-cs-empty-icon{
            width:78px;
            height:78px;
            margin:0 auto 18px;
            border-radius:22px;
            display:flex;
            align-items:center;
            justify-content:center;
            background:linear-gradient(135deg, #eef7ff 0%, #f7fbff 100%);
            color:var(--ac-primary);
        }

        .ac-cs-empty-state h3{
            margin:0 0 8px;
            font-size:20px;
            font-weight:900;
            color:var(--ac-text);
        }

        .ac-cs-empty-state p{
            margin:0;
            color:var(--ac-muted);
            font-size:14px;
        }

        .ac-desktop-only,
        .ac-tablet-only,
        .ac-mobile-only{
            display:none;
        }

        @media (min-width: 1024px){
            .ac-desktop-only{ display:inline-flex; }
            .ac-cs-table-card{ display:block; }
            .ac-cs-accordion{ display:none; }

            .ac-cs-search-row{
                flex-direction:row;
                align-items:stretch;
            }

            .ac-cs-search-actions{
                flex-wrap:nowrap;
            }
        }

        @media (min-width: 768px) and (max-width: 1023px){
            .ac-tablet-only{ display:inline-flex; }
            .ac-cs-table-card{ display:none; }
            .ac-cs-accordion{ display:block; }

            .ac-cs-search-row{
                flex-direction:row;
                align-items:stretch;
            }

            .ac-cs-grid{
                grid-template-columns:repeat(2, minmax(0,1fr));
            }

            .ac-cs-field--full{
                grid-column:1 / -1;
            }
        }

        @media (min-width: 768px){
            .ac-cs-shell{ padding:0; }
        }

        @media (max-width: 767px){
            .ac-desktop-only{ display:none; }
            .ac-tablet-only{ display:none; }
            .ac-mobile-only{ display:inline-flex; }

            .ac-cs-table-card{ display:none; }
            .ac-cs-accordion{ display:block; }

            .ac-cs-shell{
                padding:0;
            }

            .ac-cs-hero{
                border-radius:20px;
                padding:14px;
            }

            .ac-cs-title{
                font-size:21px;
            }

            .ac-cs-subtitle{
                font-size:12px;
            }

            .ac-cs-hero-top{
                margin-bottom:12px;
            }

            .ac-cs-hero-search .ac-cs-search-row{
                flex-direction:column;
            }

            .ac-cs-hero-search .ac-cs-search-actions{
                width:100%;
                flex-wrap:wrap;
            }

            .ac-cs-hero-search .ac-cs-search-btn,
            .ac-cs-hero-search .ac-cs-clear-btn{
                min-height:44px;
                width:100%;
            }

            .ac-cs-hero-search .ac-cs-search-input{
                height:44px;
                font-size:13px;
            }

            .ac-cs-search-input{
                height:44px;
                font-size:13px;
            }

            .ac-cs-search-btn,
            .ac-cs-clear-btn{
                min-height:44px;
                font-size:13px;
            }

            .ac-cs-hero-actions{
                width:100%;
            }

            .ac-cs-btn,
            .ac-cs-search-btn,
            .ac-cs-clear-btn{
                min-height:50px;
            }

            .ac-cs-btn{
                flex:1 1 calc(50% - 5px);
            }

            .ac-cs-card-head{
                align-items:flex-start;
            }

            .ac-cs-card-right{
                flex-direction:column;
                align-items:flex-end;
                gap:8px;
            }

            .ac-cs-card-total{
                font-size:16px;
            }

            .ac-cs-card-name{
                font-size:15px;
            }

            .ac-cs-card-meta{
                gap:6px;
            }

            .ac-cs-card-meta span{
                font-size:11px;
                padding:5px 8px;
            }
        }

        .ac-cs-table-wrapper::-webkit-scrollbar,
        .ac-cs-card-list::-webkit-scrollbar{
            width:8px;
            height:8px;
        }

        .ac-cs-table-wrapper::-webkit-scrollbar-thumb,
        .ac-cs-card-list::-webkit-scrollbar-thumb{
            background:#c9dcee;
            border-radius:999px;
        }

        .ac-cs-table-wrapper::-webkit-scrollbar-track,
        .ac-cs-card-list::-webkit-scrollbar-track{
            background:transparent;
        }

        /* These classes are no longer used but kept for safety */
        .ac-cs-table-head,
        .ac-cs-table-title,
        .ac-cs-table-note,
        .ac-cs-footer{
            display:none;
        }

        /* ===== RESPONSIVE FIX: keep table on tablet/desktop, cards only on phone ===== */

        /* Desktop + tablet (≥768px): use table */
        @media (min-width: 768px) {
            .ac-cs-table-card {
                display: block !important;
            }

            .ac-cs-accordion {
                display: none !important;
            }

            .ac-cs-table-wrapper {
                height: auto !important;
                max-height: calc(100vh - 260px) !important;
                min-height: 420px;
                overflow: auto;
            }

            .ac-cs-table {
                min-width: 900px;
            }

            .ac-cs-hero-top {
                align-items: center;
            }

            .ac-cs-hero-actions {
                flex-wrap: nowrap;
            }

            .ac-cs-hero-search .ac-cs-search-row {
                display: flex;
                flex-direction: row;
                gap: 10px;
            }

            .ac-cs-hero-search .ac-cs-search-wrapper {
                flex: 1 1 auto;
                min-width: 0;
            }

            .ac-cs-hero-search .ac-cs-search-actions {
                flex: 0 0 auto;
                display: flex;
                flex-wrap: nowrap;
            }
        }

        /* Phone only (<768px): use accordion cards */
        @media (max-width: 767px) {
            .ac-cs-table-card {
                display: none !important;
            }

            .ac-cs-accordion {
                display: block !important;
            }

            .ac-cs-hero {
                padding: 14px;
                border-radius: 18px;
            }

            .ac-cs-hero-top {
                flex-direction: column;
                align-items: stretch;
            }

            .ac-cs-hero-actions {
                width: 100%;
                display: grid;
                grid-template-columns: 1fr 1fr;
                gap: 8px;
            }

            .ac-cs-btn {
                width: 100%;
                min-height: 44px;
                padding: 0 10px;
                font-size: 13px;
            }

            .ac-cs-hero-search .ac-cs-search-row {
                flex-direction: column;
            }

            .ac-cs-hero-search .ac-cs-search-actions {
                width: 100%;
            }

            .ac-cs-card-list {
                max-height: none;
                overflow: visible;
                padding-right: 0;
            }

            .ac-cs-card-head {
                min-height: 82px;
            }
        }
    </style>

    <div class="ac-cs-shell">
        <section class="ac-cs-hero">
            <div class="ac-cs-hero-top">
                <div class="ac-cs-title-wrap">
                    <div class="ac-cs-kicker">💠 Sales Dashboard</div>
                </div>

                <div class="ac-cs-hero-actions">
                    <a href="<?php echo esc_url($create_url); ?>" class="ac-cs-btn ac-cs-btn-primary" title="Create New Cash Sale">
                        <span>+</span><span>New Cash Sale</span>
                    </a>
                    <a href="<?php echo esc_url($refresh_url); ?>" class="ac-cs-btn ac-cs-btn-glass" id="refreshBtn" title="Refresh">
                        <span>↻</span><span>Refresh</span>
                    </a>
                </div>
            </div>

            <div class="ac-cs-hero-search">
                <div class="ac-cs-search-form">
                    <div class="ac-cs-search-row">
                        <div class="ac-cs-search-wrapper"
                             id="acSearchWrapper"
                             data-ajax-url="<?php echo esc_attr($ajax_url); ?>"
                             data-nonce="<?php echo esc_attr($search_nonce); ?>">

                            <!-- CORRECT: placeholder "Search debtor name..." -->
                            <input type="text"
                                   id="acSearchInput"
                                   class=�K�	< ���������K&
�?�!"ac-cs-search-input"
                                   placeholder="Search debtor name..."
                                   value="<?php echo htmlspecialchars($search); ?>"
                                   autocomplete="off" />

                            <input type="hidden"
                                   name="search"
                                   id="acSearchHidden"
                                   value="<?php echo htmlspecialchars($search); ?>" />

                            <div class="ac-cs-search-dropdown" id="acSearchDropdown"></div>
                        </div>

                        <div class="ac-cs-search-actions">
                            <button type="button" id="acSearchBtn" class="ac-cs-search-btn">Search</button>
                            <?php if (!empty($search)): ?>
                                <a href="?" class="ac-cs-clear-btn" id="acClearBtn">Clear</a>
                            <?php endif; ?>
                        </div>
                    </div>

                    <?php if (!empty($search)): ?>
                        <div class="ac-cs-search-info">
                            <span class="ac-cs-search-info-badge">i</span>
                            <span>Showing results for “<?php echo htmlspecialchars($search); ?>”</span>
                        </div>
                    <?php endif; ?>
                </div>
            </div>
        </section>

        <section class="ac-cs-data-wrap">
            <?php if (!empty($rows)): ?>

                <!-- Desktop (table header removed, footer removed) -->
                <div class="ac-cs-table-card">
                    <div class="ac-cs-table-wrapper">
                        <table class="ac-cs-table">
                            <thead>
                                <tr>
                                    <th>Date</th>
                                    <th>Doc No</th>
                                    <th>Debtor Code</th>
                                    <th>Debtor Name</th>
                                    <th>Location</th>
                                    <th>Payment</th>
                                    <th>Total (RM)</th>
                                    <th>Remark</th>
                                </tr>
                            </thead>
                            <tbody>
                                <?php foreach ($rows as $row): ?>
                                    <?php $edit_url = $edit_base . '?docno=' . rawurlencode((string)$row['DocNo']); ?>
                                    <tr>
                                        <td><?php echo htmlspecialchars($row['DocDateDisplay']); ?></td>
                                        <td>
                                            <a class="ac-cs-doc-link" href="<?php echo esc_url($edit_url); ?>">
                                                <?php echo htmlspecialchars($row['DocNo']); ?>
                                            </a>
                                        </td>
                                        <td>
                                            <span class="ac-cs-code"><?php echo htmlspecialchars($row['DebtorCode'] ?? '—'); ?></span>
                                        </td>
                                        <td class="ac-cs-debtor-name"><?php echo htmlspecialchars($row['DebtorName'] ?? 'CASH SALE'); ?></td>
                                        <td>
                                            <span class="ac-cs-location-chip"><?php echo htmlspecialchars($row['SalesLocation'] ?? '—'); ?></span>
                                        </td>
                                        <td>
                                            <span class="ac-cs-payment-chip"><?php echo htmlspecialchars(format_payment_mode($row['PaymentMode'] ?? null)); ?></span>
                                        </td>
                                        <td class="ac-cs-total"><?php echo number_format((float)($row['FinalTotal'] ?? 0), 2); ?></td>
                                        <td class="ac-cs-remark" title="<?php echo htmlspecialchars($row['Remark1'] ?? ''); ?>">
                                            <?php echo htmlspecialchars($row['Remark1'] ?? '—'); ?>
                                        </td>
                                    </tr>
                                <?php endforeach; ?>
                            </tbody>
                        </table>
                    </div>
                </div>

                <!-- Tablet + Mobile (unchanged) -->
                <div class="ac-cs-accordion">
                    <div class="ac-cs-card-list">
                        <?php foreach ($rows as $row): ?>
                            <?php $edit_url = $edit_base . '?docno=' . rawurlencode((string)$row['DocNo']); ?>
                            <div class="ac-cs-card">
                                <div class="ac-cs-card-head" onclick="toggleAccordion(this)">
                                    <div class="ac-cs-card-main">
                                        <div class="ac-cs-card-name">
                                            <?php echo htmlspecialchars($row['DebtorName'] ?? 'CASH SALE'); ?>
                                        </div>

                                        <div class="ac-cs-card-meta ac-tablet-only">
                                            <span>📅 <?php echo htmlspecialchars($row['DocDateDisplay']); ?></span>
                                            <span>📄 <?php echo htmlspecialchars($row['DocNo']); ?></span>
                                            <span>💳 <?php echo htmlspecialchars(format_payment_mode($row['PaymentMode'] ?? null)); ?></span>
                                        </div>

                                        <div class="ac-cs-card-meta ac-mobile-only">
                                            <span>📅 <?php echo htmlspecialchars($row['DocDateDisplay']); ?></span>
                                            <span>💳 <?php echo htmlspecialchars(format_payment_mode($row['PaymentMode'] ?? null)); ?></span>
                                        </div>
                                    </div>

                                    <div class="ac-cs-card-right">
                                        <div class="ac-cs-card-total">
                                            RM <?php echo number_format((float)($row['FinalTotal'] ?? 0), 2); ?>
                                        </div>
                                        <div class="ac-cs-card-icon">⌄</div>
                                    </div>
                                </div>

                                <div class="ac-cs-card-body">
                                    <div class="ac-cs-card-panel">
                                        <div class="ac-cs-grid">
                                            <div class="ac-cs-field ac-mobile-only">
                                                <span class="ac-cs-field-label">Document No.</span>
                                                <span class="ac-cs-field-value">
                                                    <span class="ac-cs-doc-pill">
                                                        <a class="ac-cs-doc-link" href="<?php echo esc_url($edit_url); ?>">
                                                            <?php echo htmlspecialchars($row['DocNo']); ?>
                                                        </a>
                                                    </span>
                                                </span>
                                            </div>

                                            <div class="ac-cs-field">
                                                <span class="ac-cs-field-label">Debtor Code</span>
                                                <span class="ac-cs-field-value"><?php echo htmlspecialchars($row['DebtorCode'] ?? '—'); ?></span>
                                            </div>

                                            <div class="ac-cs-field">
                                                <span class="ac-cs-field-label">Location</span>
                                                <span class="ac-cs-field-value"><?php echo htmlspecialchars($row['SalesLocation'] ?? '—'); ?></span>
                                            </div>

                                            <div class="ac-cs-field">
                                                <span class="ac-cs-field-label">Payment</span>
                                                <span class="ac-cs-field-value"><?php echo htmlspecialchars(format_payment_mode($row['PaymentMode'] ?? null)); ?></span>
                                            </div>

                                            <div class="ac-cs-field ac-tablet-only">
                                                <span class="ac-cs-field-label">Document No.</span>
                                                <span class="ac-cs-field-value">
                                                    <span class="ac-cs-doc-pill">
                                                        <a class="ac-cs-doc-link" href="<?php echo esc_url($edit_url); ?>">
                                                            <?php echo htmlspecialchars($row['DocNo']); ?>
                                                        </a>
                                                    </span>
                                                </span>
                                            </div>

                                            <div class="ac-cs-field">
                                                <span class="ac-cs-field-label">Date</span>
                                                <span class="ac-cs-field-value"><?php echo htmlspecialchars($row['DocDateDisplay']); ?></span>
                                            </div>

                                            <?php if (!empty($row['Remark1'])): ?>
                                                <div class="ac-cs-field ac-cs-field--full">
                                                    <span class="ac-cs-field-label">Remark</span>
                                                    <span class="ac-cs-field-value remark"><?php echo htmlspecialchars($row['Remark1']); ?></span>
                                                </div>
                                            <?php endif; ?>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        <?php endforeach; ?>
                    </div>
                </div>

            <?php else: ?>
                <div class="ac-cs-empty-state">
                    <div class="ac-cs-empty-icon">
                        <svg fill="none" stroke="currentColor" viewBox="0 0 24 24" width="40" height="40">
                            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.6"
                                  d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10" />
                        </svg>
                    </div>
                    <h3>No records found</h3>
                    <p>
                        <?php if (!empty($search)): ?>
                            No results for “<?php echo htmlspecialchars($search); ?>”
                        <?php else: ?>
                            No cash sales in database
                        <?php endif; ?>
                    </p>
                </div>
            <?php endif; ?>

            <!-- Footer removed -->
        </section>
    </div>

    <script>
    (function() {
        const wrapper = document.getElementById('acSearchWrapper');
        if (!wrapper) return;

        const AJAX_URL = wrapper.dataset.ajaxUrl;
        const NONCE = wrapper.dataset.nonce;

        const searchInput = document.getElementById('acSearchInput');
        const hiddenInput = document.getElementById('acSearchHidden');
        const dropdown = document.getElementById('acSearchDropdown');
        const searchBtn = document.getElementById('acSearchBtn');
        const clearBtn = document.getElementById('acClearBtn');

        let searchItems = [];
        let activeIndex = -1;
        let abortController = null;
        let searchTimeout = null;

        const escapeHtml = (str) => {
            const div = document.createElement('div');
            div.textContent = str;
            return div.innerHTML;
        };

        const showDropdown = () => dropdown.classList.add('active');
        const hideDropdown = () => {
            dropdown.classList.remove('active');
            activeIndex = -1;
        };

        const renderEmpty = (msg) => {
            dropdown.innerHTML = `<div class="ac-cs-dropdown-empty">${escapeHtml(msg)}</div>`;
            showDropdown();
        };

        const renderError = (msg) => {
            dropdown.innerHTML = `<div class="ac-cs-dropdown-error">⚠️ ${escapeHtml(msg)}</div>`;
            showDropdown();
        };

        // CORRECT: renderResults for debtors – shows name (strong) and code (small)
        const renderResults = (items) => {
            if (!items || items.length === 0) {
                return renderEmpty('No customers found');
            }

            dropdown.innerHTML = items.map((item, idx) => `
                <div class="ac-cs-dropdown-item" data-index="${idx}">
                    <strong>${escapeHtml(item.name || '')}</strong>
                    <small>${escapeHtml(item.code || '')}</small>
                </div>
            `).join('');

            showDropdown();
            activeIndex = -1;
        };

        // CORRECT: selectItem uses item.name
        const selectItem = (idx) => {
            if (idx < 0 || idx >= searchItems.length) return;
            const item = searchItems[idx];

            searchInput.value = item.name || '';
            hiddenInput.value = item.name || '';

            hideDropdown();
            performSearchSubmit();
        };

        const performSearch = async (query) => {
            if (abortController) abortController.abort();
            abortController = new AbortController();

            const trimmedQuery = query.trim();

            if (trimmedQuery === '') {
                hideDropdown();
                return;
            }

            renderEmpty('Searching...');

            try {
                // UPDATED: action name now matches new AJAX handler
                const url = `${AJAX_URL}?action=wst_cashsale_debtor_search_testdb&nonce=${encodeURIComponent(NONCE)}&q=${encodeURIComponent(trimmedQuery)}`;
                const response = await fetch(url, { signal: abortController.signal });
                const text = await response.text();
                let data;

                try {
                    data = JSON.parse(text);
                } catch (e) {
                    throw new Error('Server error: Invalid JSON response');
                }

                if (!data.success) {
                    throw new Error(data.data?.error || 'Search failed');
                }

                searchItems = data.data?.items || [];
                renderResults(searchItems);

            } catch (error) {
                if (error.name === 'AbortError') return;
                renderError('Failed to load results');
            }
        };

        const debounceSearch = () => {
            clearTimeout(searchTimeout);
            searchTimeout = setTimeout(() => performSearch(searchInput.value), 300);
        };

        const performSearchSubmit = () => {
            const searchTerm = hiddenInput.value || searchInput.value.trim();
            if (searchTerm) {
                window.location.href = `?sear�K&��/E!���������K&
������ch=${encodeURIComponent(searchTerm)}`;
            } else {
                window.location.href = '?';
            }
        };

        searchInput.addEventListener('input', debounceSearch);

        searchInput.addEventListener('focus', () => {
            if (searchInput.value.trim() !== '') debounceSearch();
        });

        searchInput.addEventListener('keydown', (e) => {
            if (!dropdown.classList.contains('active')) return;

            const items = dropdown.querySelectorAll('.ac-cs-dropdown-item');
            if (!items.length) return;

            if (e.key === 'ArrowDown') {
                e.preventDefault();
                activeIndex = (activeIndex + 1) % items.length;
                items.forEach((item, i) => item.classList.toggle('active', i === activeIndex));
            } else if (e.key === 'ArrowUp') {
                e.preventDefault();
                activeIndex = activeIndex > 0 ? activeIndex - 1 : items.length - 1;
                items.forEach((item, i) => item.classList.toggle('active', i === activeIndex));
            } else if (e.key === 'Enter' && activeIndex >= 0) {
                e.preventDefault();
                selectItem(activeIndex);
            } else if (e.key === 'Enter') {
                e.preventDefault();
                performSearchSubmit();
            } else if (e.key === 'Escape') {
                hideDropdown();
            }
        });

        dropdown.addEventListener('click', (e) => {
            const item = e.target.closest('.ac-cs-dropdown-item');
            if (!item) return;
            selectItem(parseInt(item.dataset.index, 10));
        });

        searchBtn.addEventListener('click', () => {
            performSearchSubmit();
        });

        if (clearBtn) {
            clearBtn.addEventListener('click', () => {});
        }

        document.addEventListener('click', (e) => {
            if (!wrapper.contains(e.target)) {
                hideDropdown();
            }
        });

        const searchForm = document.querySelector('.ac-cs-search-form');
        if (searchForm) {
            searchForm.addEventListener('submit', (e) => {
                e.preventDefault();
                performSearchSubmit();
            });
        }
    })();

    function toggleAccordion(header) {
        document.querySelectorAll('.ac-cs-card-head.active').forEach(h => {
            if (h !== header) {
                h.classList.remove('active');
                h.nextElementSibling.classList.remove('active');
            }
        });

        header.classList.toggle('active');
        header.nextElementSibling.classList.toggle('active');
    }

    document.getElementById('refreshBtn')?.addEventListener('click', function() {
        this.style.transform = 'rotate(180deg)';
        setTimeout(() => {
            this.style.transform = '';
        }, 350);
    });
    </script>
</div>�K&��Y"���������K�
�?�#<?php
/**
 * CASH SALES CREATE PAGE — CLEAN BUSINESS STYLE WITH BOTTOM TOTAL
 */

if (!defined('ABSPATH')) exit;

if (!is_user_logged_in()) {
  echo '<div style="padding:14px;border:1px solid #fecaca;background:#fff1f2;border-radius:12px;color:#991b1b;">
    Please log in to create Cash Sale.
  </div>';
  return;
}

$rest_nonce = wp_create_nonce('wp_rest');

$list_url  = 'https://website.ipohserver.com/ECOSalesInventorySearch/index.php/cash-sales/';
$edit_base = 'https://website.ipohserver.com/ECOSalesInventorySearch/index.php/cash-sale-edit/';

$REST_JOB_POST = rest_url('ac/v1/job');
$REST_JOB_BASE = rest_url('ac/v1/job/');

$ajax_url           = admin_url('admin-ajax.php');
$debtor_nonce       = wp_create_nonce('ac_cs_debtor_search');
$item_suggest_nonce = wp_create_nonce('ac_itemcode_suggest');
$price_history_nonce = wp_create_nonce('ac_item_price_history');
$purchase_price_history_nonce = wp_create_nonce('ac_item_purchase_price_history');
?>

<script>
window.AC_SUGGEST = window.AC_SUGGEST || {};
window.AC_SUGGEST.ajaxUrl = "<?php echo esc_js($ajax_url); ?>";
window.AC_SUGGEST.nonce   = "<?php echo esc_js($item_suggest_nonce); ?>";
window.AC_SUGGEST.priceHistoryNonce = "<?php echo esc_js($price_history_nonce); ?>";
window.AC_SUGGEST.purchasePriceHistoryNonce = "<?php echo esc_js($purchase_price_history_nonce); ?>";
</script>

<!-- CLEAN BUSINESS LAYOUT WITH BOTTOM TOTAL -->
<div class="ac-so-wrap"
     data-rest-nonce="<?php echo esc_attr($rest_nonce); ?>"
     data-edit-base="<?php echo esc_attr($edit_base); ?>"
     data-rest-job-post="<?php echo esc_attr($REST_JOB_POST); ?>"
     data-rest-job-base="<?php echo esc_attr($REST_JOB_BASE); ?>">

  <!-- PAGE HEADER (combined back button and title) -->
  <div class="ac-so-pagehead ac-so-pagehead-inline">
    <a class="ac-so-btn ghost" href="<?php echo esc_url($list_url); ?>">← Back to List</a>
    <h1>Create Cash Sale</h1>
  </div>

  <!-- MAIN CARD (NO SUMMARY BAR) -->
  <div class="ac-so-card ac-so-main-card">

    <div class="ac-so-row2 ac-so-row-single">
      <div class="ac-so-field">
        <label>Date</label>
        <input id="ac_so_date" type="date" />
      </div>
    </div>

    <!-- Hidden base, final name, and sales agent fields -->
    <input type="hidden" id="ac_so_customer_base" value="" />
    <input type="hidden" id="ac_so_customer_final_name" value="" />
    <input type="hidden" id="ac_so_sales_agent" value="" />
    <input type="hidden" id="ac_so_sales_agent_code" value="" />

    <!-- Two‑column row: Debtor search + Walk‑in Name -->
    <div class="ac-so-row2" style="margin-top:10px;">
      <div class="ac-so-field">
        <label>Customer</label>

        <div class="ac-search-wrapper"
             id="acSoDebtorWrapper"
             data-ajax-url="<?php echo esc_attr($ajax_url); ?>"
             data-nonce="<?php echo esc_attr($debtor_nonce); ?>">

          <input type="text"
                 id="acSoDebtorInput"
                 class="ac-search-input"
                 placeholder="Search by customer name..."
                 autocomplete="off" />

          <input type="hidden" id="ac_so_customer" value="" />
          <div class="ac-search-dropdown" id="acSoDebtorDropdown"></div>
        </div>

        <!-- HINT REMOVED -->
      </div>

      <div class="ac-so-field">
        <label>Extra Name</label>
        <input id="ac_so_customer_suffix" type="text" placeholder="e.g. ABANG SAYAN" value="" />
        <!-- HINT REMOVED -->
      </div>
    </div>

    <div class="ac-so-row2" style="margin-top:10px;">
      <div class="ac-so-field">
        <label>Payment Method</label>
        <select id="ac_so_payment_method">
          <option value="CASH">Cash</option>
          <option value="CARD">Card</option>
          <option value="CHEQUE">Cheque</option>
          <option value="BANK">Bank Transfer</option>
        </select>
      </div>

      <div class="ac-so-field">
        <label>Payment Amount</label>
        <input id="ac_so_payment_amount" type="number" min="0" step="0.01" value="0.00">
      </div>
    </div>

    <div id="ac_so_status" class="ac-so-status"></div>
  </div>

  <!-- ITEMS CARD (WITH BOTTOM TOTAL) -->
  <div class="ac-so-card ac-so-items-card">
    <!-- ========== TITLE REMOVED ========== -->

    <div class="ac-so-line-entry">
      <!-- ========== MODIFIED: item field with wrapper for absolute dropdown ========== -->
      <div class="ac-so-field">
        <label>Item</label>
        <div class="ac-item-search-wrap">
          <input id="ac_so_item_name" type="text" placeholder="Search by item name (e.g. timing) or code..." autocomplete="off">
          <input id="ac_so_item" type="hidden" value="">
          <input id="ac_so_item_display" type="hidden" value="">
          <input id="ac_so_uom" type="hidden" value="">
          <input id="ac_so_price_hidden" type="hidden" value="">
          <div class="ac-dd" id="ac_so_item_dd" style="display:none;"></div>
          <div class="ac-line-preview" id="ac_so_line_preview" style="display:none;"></div>
        </div>
      </div>
      <!-- ========== END MODIFICATION ========== -->

      <div class="ac-so-field mini">
        <label>Qty</label>
        <input id="ac_so_qty" type="number" min="1" step="1" value="1">
      </div>

      <div class="ac-so-field mini ac-so-add-wrap">
        <button id="ac_so_addline" class="ac-so-btn small" type="button">Add</button>
      </div>
    </div>

    <div class="ac-so-table-wrap">
      <table class="ac-so-table">
        <thead>
          <tr>
            <th>Item</th>
            <th class="r">Qty</th>
            <th class="r">Price</th>
            <th class="r">Total</th>
            <th class="r"></th>
          </tr>
        </thead>
        <tbody id="ac_so_lines">
          <tr><td colspan="5" class="empty">No lines added yet.</td></tr>
        </tbody>
      </table>
    </div>

    <!-- BOTTOM TOTAL BOX -->
    <div class="ac-so-items-footer">
      <div class="ac-so-total-inline">
        <div class="lbl">Final Total</div>
        <div class="amt" id="ac_so_final_total">0.00</div>
      </div>
    </div>
  </div>

  <!-- NORMAL ACTION BAR (NO STICKY) -->
  <div class="ac-so-actions">
    <button class="ac-so-btn" id="ac_so_submit" type="button">Save Cash Sale</button>
  </div>

</div> <!-- .ac-so-wrap -->

<style>
  /* ===== CLEAN BUSINESS STYLES — FULL WIDTH VERSION ===== */
  .ac-so-wrap{
    --ac-primary:#1677ff;
    --ac-primary-dark:#0f5fd1;
    --ac-bg:#f3f6fb;
    --ac-card:#ffffff;
    --ac-line:#dbe5f0;
    --ac-line-strong:#c8d6e5;
    --ac-text:#142133;
    --ac-muted:#6b7a90;
    --ac-success:#16a34a;
    --ac-shadow:0 8px 22px rgba(15,23,42,.05);

    font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Arial,sans-serif;
    background:transparent;
    padding:0;
    border-radius:0;

    width:100%;
    min-width:0;
    max-width:100%;

    margin:0;
    color:var(--ac-text);
    box-sizing:border-box;
    overflow:visible;
  }

  /* top navigation (hidden) */
  .ac-so-topnav{
    display:none;
  }

  /* page header — full width */
  .ac-so-pagehead{
    display:flex;
    align-items:center;
    gap:12px;
    margin-bottom:14px;
    flex:0 0 auto;
    width:100%;
    max-width:100%;
    box-sizing:border-box;
  }

  .ac-so-pagehead-inline{
    justify-content:flex-start;
    flex-wrap:wrap;
  }

  .ac-so-pagehead h1{
    margin:0;
    font-size:24px;
    line-height:1.05;
    font-weight:900;
    color:#0f172a;
  }

  .ac-so-pagehead p{
    display:none;
  }

  /* optional polish for back button height */
  .ac-so-pagehead .ac-so-btn{
    height:40px;
  }

  /* cards — full width */
  .ac-so-card,
  .ac-so-last{
    background:var(--ac-card);
    border:1px solid var(--ac-line);
    box-shadow:var(--ac-shadow);
    backdrop-filter:none;
    -webkit-backdrop-filter:none;
  }

  .ac-so-card{
    border-radius:16px;
    padding:14px 16px;
    width:100%;
    max-width:100%;
    box-sizing:border-box;
  }

  .ac-so-main-card{
    padding-top:14px;
    margin-bottom:0;
    flex:0 0 auto;
    overflow:visible;
    width:100%;
    max-width:100%;
  }

  .ac-so-items-card{
    margin-top:0;
    min-height:0;
    display:flex;
    flex-direction:column;
    overflow:visible;
    width:100%;
    max-width:100%;
  }

  /* ===== compact form fields: label beside field ===== */
  .ac-so-field{
    display:grid;
    grid-template-columns:130px minmax(0,1fr);
    align-items:center;
    column-gap:12px;
    row-gap:4px;
  }

  .ac-so-field label{
    display:block;
    font-size:11px;
    font-weight:900;
    color:#596b84;
    margin:0;
    text-transform:uppercase;
    letter-spacing:.08em;
    line-height:1.2;
  }

  .ac-so-field > input,
  .ac-so-field > select,
  .ac-so-field > .ac-search-wrapper,
  .ac-so-field > .ac-search-input{
    grid-column:2;
  }

  .ac-so-field > .ac-hint,
  .ac-so-field > .ac-dd,
  .ac-so-field > .ac-line-preview{
    grid-column:2;
  }

  .ac-so-field input,
  .ac-so-field select,
  .ac-search-input{
    width:100%;
    height:40px;
    border:1px solid var(--ac-line-strong);
    border-radius:10px;
    padding:0 12px;
    font-size:14px;
    background:#fff;
    color:var(--ac-text);
    transition:border-color .16s ease, box-shadow .16s ease;
    box-sizing:border-box;
  }

  .ac-so-field input:hover,
  .ac-so-field select:hover,
  .ac-search-input:hover{
    border-color:#b0c4dc;
  }

  .ac-so-field input:focus,
  .ac-so-field select:focus,
  .ac-search-input:focus{
    outline:none;
    border-color:var(--ac-primary);
    box-shadow:0 0 0 3px rgba(22,119,255,.10);
    transform:none;
  }

  /* Two‑column row adjustments */
  .ac-so-row2{
    display:grid;
    grid-template-columns:minmax(0,1.45fr) minmax(0,0.95fr);
    gap:12px;
    align-items:start;
    width:100%;
  }

  .ac-so-row-single{
    grid-template-columns:1fr;   /* full width */
  }

  /* Ensure full width for the debtor wrapper and walk‑in input */
  #acSoDebtorWrapper,
  #ac_so_customer_suffix{
    width:100%;
  }

  .ac-hint{
    font-size:11px;
    color:#94a3b8;
    margin-top:2px;
    line-height:1.35;
  }

  /* items header — tightened (now unused) */
  .ac-so-card-hd{
    font-weight:900;
    font-size:16px;
    margin-bottom:6px;
    color:#0f172a;
    letter-spacing:-.01em;
    line-height:1.1;
  }

  .ac-so-items-title{
    display:flex;
    align-items:center;
    justify-content:space-between;
    min-height:auto;
    padding:0 2px 2px;
  }

  /* item entry row — full width */
  .ac-so-line-entry{
    display:grid;
    grid-template-columns:minmax(0,1fr) 120px 120px;
    gap:12px;
    align-items:end;
    margin-bottom:8px;
    padding:10px 12px;
    border-radius:12px;
    background:#f8fbff;
    border:1px solid #e2ebf5;
    flex:0 0 auto;
    width:100%;
    max-width:100%;
    box-sizing:border-box;
  }

  .ac-so-field.mini{
    grid-template-columns:46px minmax(0,1fr);
  }

  .ac-so-add-wrap{
    display:flex;
    align-items:stretch;
  }

  .ac-so-add-wrap .ac-so-btn{
    width:100%;
    height:40px;
  }

  /* ===== NEW: wrapper for item search to enable absolute dropdown ===== */
  .ac-item-search-wrap{
    position: relative;
    grid-column: 2;
  }

  /* ===== UPDATED .ac-dd: absolute within wrapper ===== */
  .ac-dd{
    position: absolute;
    top: calc(100% + 6px);
    left: 0;
    right: 0;
    margin-top: 0;
    border: 1px solid #dbe7f3;
    border-radius: 12px;
    background: #fff;
    max-height: 240px;
    overflow: auto;
    box-shadow: 0 8px 16px rgba(0,0,0,.06);
    z-index: 1000;
  }

  .ac-line-preview{
    margin-top:8px;
    border:1px dashed #c8dcef;
    background:#fcfdff;
    border-radius:12px;
    padding:8px 10px;
    font-size:12px;
    color:#334155;
    display:flex;
    gap:10px;
    justify-content:space-between;
    align-items:center;
    flex-wrap:wrap;
  }

  .ac-line-preview b{color:#0f172a;}

  /* ===== items table — full width + vertical scroll for ~5 rows ===== */
  .ac-so-table-wrap{
    margin-top:4px;
    border-radius:14px;
    overflow-x:auto;
    overflow-y:auto;
    border:1px solid var(--ac-line);
    background:#fff;
    box-shadow:none;
    flex:1 1 auto;
    min-height:0;
    width:100%;
    max-width:100%;
    min-width:0;
    max-height:245px;
  }

  .ac-so-table{
    width:100%;
    border-collapse:collapse;
    font-size:13px;
  }

  .ac-so-table thead{
    background:#eaf2fb;
    color:#16304f;
    position:sticky;
    top:0;
    z-index:1;
  }

  .ac-so-table th{
    padding:8px 10px;
    text-align:left;
    font-weight:800;
    font-size:11px;
    letter-spacing:.04em;
    text-transform:uppercase;
    border-bottom:1px solid var(--ac-line);
    white-space:nowrap;
  }

  .ac-so-table td{
    padding:8px 10px;
    border-top:1px solid #edf2f8;
    vertical-align:middle;
    background:#fff;
  }

  .ac-so-table tbody tr:hover td{
    background:#f8fbff;
  }

  .ac-so-table td.r,
  .ac-so-table th.r{
    text-align:right;
  }

  .ac-so-table td.empty{
    text-align:center;
    color:#94a3b8;
    padding:18px 12px;
  }

  .ac-x{
    height:32px;
    width:32px;
    border-radius:10px;
    border:1px solid var(--ac-line-strong);
    background:#fff;
    color:#0f172a;
    cursor:pointer;
    font-weight:800;
    font-size:15px;
    line-height:1;
    display:inline-flex;
    align-items:center;
    justify-content:center;
    transition:background .16s, border-color .16s;
  }

  .ac-x:hover{
    background:#fff1f2;
    border-color:#fecaca;
    color:#b91c1c;
  }

  .ac-x:active{transform:translateY(0);}

  /* dropdowns (keep original for customer dropdown) */
  .ac-dd .item{
    padding:9px 12px;
    border-top:1px solid #f1f5f9;
    cursor:pointer;
  }

  .ac-dd .item:first-child{border-top:none;}
  .ac-dd .item:hover{background:#eef7ff;}
  .ac-dd .item strong{display:block;color:#0f172a;font-size:13px;}
  .ac-dd .item small{display:block;color:#64748b;margin-top:2px;font-size:12px;}

  .ac-search-wrapper{
    position:relative;
    z-index:20;
  }

  .ac-search-dropdown{
    position:absolute;
    top:calc(100% + 6px);
    left:0;
    right:0;
    background:#fff;
    border:1px solid #dbe7f3;
    border-radius:14px;
    max-height:260px;
    overflow-y:auto;
    z-index:1000;
    display:none;
    box-shadow:0 10px 22px rgba(15,23,42,.08);
  }

  .ac-search-dropdown.active{display:block;}

  .ac-dropdown-item{
    padding:10px 12px;
    cursor:pointer;
    border-bottom:1px solid #eef4fb;
    transition:background .2s;
  }

  .ac-dropdown-item:last-child{border-bottom:none;}
  .ac-dropdown-item:hover,
  .ac-dropdown-item.active{background:#eef7ff;}
  .ac-dropdown-item strong{display:block;font-size:14px;color:#0f172a;margin-bottom:3px;}
  .ac-dropdown-item small{font-size:12px;color:#64748b;}

  .ac-dropdown-empty,
  .ac-dropdown-error{
    padding:14px;
    text-align:center;
    color:#94a3b8;
    font-size:12px;
  }

  .ac-dropdown-error{color:#c62828;}

  /* status messages — hidden, using toasts instead */
  .ac-so-status{
    display:none !important;
  }

  /* buttons */
  .ac-so-btn{
    background:linear-gradient(180deg,var(--ac-primary) 0%, var(--ac-primary-dark) 100%);
    color:#fff;
    border:none;
    border-radius:10px;
    height:42px;
    padding:0 16px;
    font-weight:800;
    font-size:14px;
    cursor:pointer;
    text-decoration:none;
    display:inline-flex;
    align-items:center;
    justify-content:center;
    transition:filter .16s ease, transform .12s ease;
    box-shadow:none;
  }

  .ac-so-btn:hover{
    filter:brightness(1.04);
    transform:translateY(-1px);
  }

  .ac-so-btn:active{transform:translateY(0);}

  .ac-so-btn.ghost{
    background:#�K����#���������K�
�?�@fff;
    color:var(--ac-primary);
    border:1px solid var(--ac-line-strong);
    box-shadow:none;
  }

  .ac-so-btn.small{
    height:40px;
    border-radius:8px;
    padding:0 14px;
  }

  .ac-so-btn:disabled{
    opacity:.65;
    cursor:not-allowed;
    transform:none !important;
    filter:none;
  }

  /* bottom total box */
  .ac-so-items-footer{
    display:flex;
    justify-content:flex-end;
    align-items:stretch;
    margin-top:10px;
    flex:0 0 auto;
    width:100%;
  }

  .ac-so-total-inline{
    width:280px;
    max-width:100%;
    background:linear-gradient(180deg,#1d8bff 0%, #1677ff 100%);
    color:#fff;
    border-radius:14px;
    padding:12px 14px;
    box-shadow:none;
  }

  .ac-so-total-inline .lbl{
    font-size:11px;
    font-weight:800;
    text-transform:uppercase;
    letter-spacing:.05em;
    color:rgba(255,255,255,.92);
    margin-bottom:6px;
  }

  .ac-so-total-inline .amt{
    font-size:32px;
    line-height:1;
    font-weight:1000;
    text-align:right;
    letter-spacing:-.04em;
  }

  /* normal save bar — full width */
  .ac-so-actions{
    margin-top:10px;
    display:flex;
    justify-content:flex-end;
    gap:10px;
    padding:0;
    width:100%;
    max-width:100%;
    box-sizing:border-box;
  }

  #ac_so_submit{
    min-width:160px;
  }

  /* hide old elements */
  .ac-so-side,
  .ac-so-note,
  .ac-so-topbar{
    display:none !important;
  }

  /* ===== NEW STYLES FOR PRICE HISTORY TABS ===== */
  .ac-line-click{
    cursor:pointer;
    display:block;
    width:100%;
  }

  .ac-line-row.is-open td{
    background:#f8fbff;
  }

  .ac-history-row td{
    padding:0 !important;
    background:#f7fbff;
    border-top:none;
    width:100%;
    max-width:100%;
  }

  /* ===== COMPACT HISTORY PANEL ===== */
  .ac-history-panel{
    padding:0;
    border-top:1px solid #dbe5f0;
    background:#f8fbff;
    width:100%;
    max-width:100%;
    min-width:0;
    overflow-x:auto;
    overflow-y:hidden;
  }

  .ac-history-box{
    border:1px solid #d9e6f2;
    border-radius:12px;
    background:#fff;
    width:100%;
    max-width:100%;
    min-width:0;
    overflow:hidden;
  }

  /* history table wrap with vertical scroll */
  .ac-history-table-wrap{
    width:100%;
    max-width:100%;
    min-width:0;
    overflow-x:auto;
    overflow-y:auto;
    max-height:230px;
  }

  .ac-history-table{
    width:max-content;
    min-width:980px;
    border-collapse:collapse;
    font-size:12px;
  }

  .ac-history-table th{
    background:#f6f9fc;
    color:#304760;
    font-size:10px;
    font-weight:800;
    text-transform:uppercase;
    letter-spacing:.04em;
    padding:7px 9px;
    border-bottom:1px solid #e3ebf4;
    white-space:nowrap;
    text-align:left;
  }

  .ac-history-table td{
    padding:7px 9px;
    border-top:1px solid #eef3f8;
    background:#fff;
    vertical-align:middle;
    white-space:nowrap;
  }

  .ac-history-table td.r,
  .ac-history-table th.r{
    text-align:right;
  }

  .ac-history-loading,
  .ac-history-error,
  .ac-history-empty{
    padding:12px;
    font-size:13px;
  }

  .ac-history-loading{ color:#35506f; }
  .ac-history-error{ color:#991b1b; }
  .ac-history-empty{ color:#64748b; }

  /* tabs inside history panel — compact */
  .ac-history-tabs-panel{
    padding:0;
    overflow:hidden;
  }

  .ac-history-tabs{
    display:flex;
    gap:0;
    border-bottom:1px solid #dbe5f0;
    background:#edf4fb;
    overflow-x:auto;
  }

  .ac-history-tab{
    appearance:none;
    border:none;
    background:transparent;
    color:#48627f;
    font-size:11px;
    font-weight:900;
    letter-spacing:.02em;
    padding:8px 12px;
    cursor:pointer;
    white-space:nowrap;
    border-bottom:2px solid transparent;
    line-height:1.1;
  }

  .ac-history-tab:hover{
    background:#e6f0fa;
  }

  .ac-history-tab.is-active{
    background:#fff;
    color:#163a63;
    border-bottom-color:#1677ff;
  }

  .ac-history-tabbody{
    display:none;
    padding:8px;
    background:#f8fbff;
  }

  .ac-history-tabbody.is-active{
    display:block;
  }

  /* item line metadata: code + UOM inline */
  .ac-line-meta{
    color:#94a3b8;
    font-size:12px;
    margin-top:2px;
    line-height:1.2;
  }

  .ac-line-uom{
    color:#64748b;
    font-weight:600;
  }

  /* ===== editable price input ===== */
  .ac-price-input{
    width:72px;
    max-width:100%;
    height:32px;
    border:1px solid var(--ac-line-strong);
    border-radius:8px;
    padding:0 8px;
    font-size:13px;
    text-align:right;
    background:#fff;
    color:var(--ac-text);
    box-sizing:border-box;
  }

  .ac-price-input:focus{
    outline:none;
    border-color:var(--ac-primary);
    box-shadow:0 0 0 3px rgba(22,119,255,.10);
  }

  /* ===== EXTRA NAME UPPERCASE ===== */
  #ac_so_customer_suffix{
    text-transform: uppercase;
  }

  /* ===== ADDITIONAL FIXES FOR LAYOUT STABILITY ===== */
  .ac-so-card,
  .ac-so-main-card,
  .ac-so-items-card,
  .ac-so-table-wrap,
  .ac-history-panel,
  .ac-history-box,
  .ac-history-table-wrap{
    width:100%;
    min-width:0;
    max-width:100%;
    box-sizing:border-box;
  }

  .ac-so-row2,
  .ac-so-line-entry,
  .ac-so-field,
  .ac-item-search-wrap,
  .ac-line-main-cell{
    min-width:0;
  }

  /* ===== TABLET ===== */
  @media (max-width: 980px){
    .ac-so-wrap{
      padding:12px;
      overflow-x:hidden;
      overflow-y:visible;
    }

    .ac-so-pagehead{
      flex-direction:column;
      align-items:flex-start;
    }

    .ac-so-row2,
    .ac-so-row-single{
      grid-template-columns:1fr;
    }

    .ac-so-field{
      grid-template-columns:110px minmax(0,1fr);
    }

    .ac-so-line-entry{
      grid-template-columns:1fr 1fr;
    }

    .ac-so-add-wrap{
      grid-column:1 / -1;
    }

    .ac-so-add-wrap .ac-so-btn{
      width:100%;
    }

    .ac-so-items-card{
      min-height:unset;
      overflow:visible;
    }

    .ac-so-table-wrap{
      max-height:none;
      flex:unset;
    }

    .ac-so-actions{
      justify-content:stretch;
    }

    .ac-so-actions .ac-so-btn{
      flex:1 1 auto;
    }

    .ac-so-items-footer{
      justify-content:stretch;
    }

    .ac-so-total-inline{
      width:100%;
      min-width:0;
    }

    .ac-so-total-inline .amt{
      font-size:30px;
    }
  }

  /* ===== MOBILE ===== */
  @media (max-width: 640px){
    .ac-so-wrap{
      padding:10px;
      border-radius:14px;
    }

    .ac-so-pagehead h1{
      font-size:22px;
    }

    .ac-so-card{
      padding:12px;
      border-radius:14px;
    }

    .ac-so-items-card{
      padding:12px;
    }

    .ac-so-field{
      grid-template-columns:1fr;
      align-items:stretch;
      row-gap:6px;
    }

    .ac-so-field > input,
    .ac-so-field > select,
    .ac-so-field > .ac-search-wrapper,
    .ac-so-field > .ac-search-input,
    .ac-so-field > .ac-hint,
    .ac-so-field > .ac-dd,
    .ac-so-field > .ac-line-preview{
      grid-column:auto;
    }

    .ac-so-field label{
      margin-bottom:0;
    }

    .ac-so-line-entry{
      grid-template-columns:1fr;
      gap:8px;
      padding:10px;
    }

    .ac-so-table{
      font-size:12px;
    }

    .ac-so-table th,
    .ac-so-table td{
      padding:9px 8px;
    }

    .ac-so-total-inline .amt{
      font-size:28px;
    }

    .ac-so-actions{
      margin-top:8px;
    }
  }
</style>

<!-- SweetAlert2 for toasts and modals -->
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>

<script>
(function(){
  const wrap = document.querySelector('.ac-so-wrap');
  if(!wrap) return;

  const REST_NONCE    = wrap.dataset.restNonce;
  const EDIT_BASE     = wrap.dataset.editBase;
  const REST_JOB_POST = wrap.dataset.restJobPost;
  const REST_JOB_BASE = wrap.dataset.restJobBase;

  const $ = (id) => document.getElementById(id);
  const state = { lines: [], jobFinished: false };

  // ----- flag to detect manual editing of payment amount -----
  let paymentManuallyEdited = false;

  function escapeHtml(s){
    if(s===null || s===undefined) return '';
    return String(s).replace(/[&<>"']/g, c => ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#039;'}[c]));
  }

  function setStatus(msg, type='info'){
    const toastType =
      type === 'success' ? 'success' :
      type === 'error'   ? 'error' :
      type === 'warning' ? 'warning' :
      'info';

    if (window.Swal) {
      Swal.fire({
        toast: true,
        position: 'top-end',
        icon: toastType,
        title: msg.replace(/<[^>]*>/g, ''),
        showConfirmButton: false,
        timer: 1800,
        timerProgressBar: true
      });
    }
  }

  function fmtMoney(n){
    const x = parseFloat(n);
    return isNaN(x) ? '0.00' : x.toFixed(2);
  }

  // ===== recalc =====
  function recalc(){
    let total = 0;
    state.lines.forEach(l => total += (parseFloat(l.qty)||0) * (parseFloat(l.unitPrice)||0));
    $('ac_so_final_total').textContent = fmtMoney(total);

    const payEl = $('ac_so_payment_amount');
    if (payEl && !paymentManuallyEdited) {
      payEl.value = fmtMoney(total);
    }
  }

  function setLastChange(text){
    // intentionally left blank
  }

  // ===== helper to render sales history table =====
  function renderHistoryTable(rows){
    if (!rows || !rows.length) {
      return `<div class="ac-history-empty">No sales price history found.</div>`;
    }

    return `
      <div class="ac-history-box">
        <div class="ac-history-table-wrap">
          <table class="ac-history-table">
            <thead>
              <tr>
                <th>Item Code</th>
                <th>UOM</th>
                <th>T</th>
                <th>Date</th>
                <th>Doc. No.</th>
                <th>Company Name</th>
                <th>Description</th>
                <th class="r">Qty</th>
                <th class="r">Unit Price</th>
                <th class="r">SubTotal</th>
              </tr>
            </thead>
            <tbody>
              ${rows.map(r => `
                <tr>
                  <td>${escapeHtml(r.itemCode || '')}</td>
                  <td>${escapeHtml(r.uom || '')}</td>
                  <td>${escapeHtml(r.t || '')}</td>
                  <td>${escapeHtml(r.date || '')}</td>
                  <td>${escapeHtml(r.docNo || '')}</td>
                  <td>${escapeHtml(r.companyName || '')}</td>
                  <td>${escapeHtml(r.description || '')}</td>
                  <td class="r">${fmtMoney(r.qty || 0)}</td>
                  <td class="r">${fmtMoney(r.unitPrice || 0)}</td>
                  <td class="r">${fmtMoney(r.subTotal || 0)}</td>
                </tr>
              `).join('')}
            </tbody>
          </table>
        </div>
      </div>
    `;
  }

  // ===== helper to render purchase history table =====
  function renderPurchaseHistoryTable(rows){
    if (!rows || !rows.length) {
      return `<div class="ac-history-empty">No purchase price history found.</div>`;
    }

    return `
      <div class="ac-history-box">
        <div class="ac-history-table-wrap">
          <table class="ac-history-table">
            <thead>
              <tr>
                <th>Acc. No.</th>
                <th>Company Name</th>
                <th>Item Code</th>
                <th>UOM</th>
                <th>T</th>
                <th>Date</th>
                <th>Doc. No.</th>
                <th>Description</th>
                <th>Location</th>
                <th class="r">Qty</th>
                <th class="r">Unit Price</th>
                <th>Discount</th>
                <th class="r">SubTotal</th>
              </tr>
            </thead>
            <tbody>
              ${rows.map(r => `
                <tr>
                  <td>${escapeHtml(r.accNo || '')}</td>
                  <td>${escapeHtml(r.companyName || '')}</td>
                  <td>${escapeHtml(r.itemCode || '')}</td>
                  <td>${escapeHtml(r.uom || '')}</td>
                  <td>${escapeHtml(r.t || '')}</td>
                  <td>${escapeHtml(r.date || '')}</td>
                  <td>${escapeHtml(r.docNo || '')}</td>
                  <td>${escapeHtml(r.description || '')}</td>
                  <td>${escapeHtml(r.location || '')}</td>
                  <td class="r">${fmtMoney(r.qty || 0)}</td>
                  <td class="r">${fmtMoney(r.unitPrice || 0)}</td>
                  <td>${escapeHtml(r.discount || '')}</td>
                  <td class="r">${fmtMoney(r.subTotal || 0)}</td>
                </tr>
              `).join('')}
            </tbody>
          </table>
        </div>
      </div>
    `;
  }

  // ===== fetch sales price history =====
  async function fetchPriceHistory(itemCode){
    const cfg = window.AC_SUGGEST || {};
    const ajaxUrl = cfg.ajaxUrl || '';
    const nonce = cfg.priceHistoryNonce || '';

    if (!ajaxUrl || !nonce || !itemCode) return [];

    const customerCode = (($('ac_so_customer')?.value) || '').trim();
    const customerName = (buildFinalCustomerName() || '').trim();
    const extraName    = (($('ac_so_customer_suffix')?.value) || '').trim();

    const url =
      ajaxUrl +
      '?action=ac_item_price_history' +
      '&nonce=' + encodeURIComponent(nonce) +
      '&itemCode=' + encodeURIComponent(itemCode) +
      '&customerCode=' + encodeURIComponent(customerCode) +
      '&customerName=' + encodeURIComponent(customerName) +
      '&extraName=' + encodeURIComponent(extraName);

    const res = await fetch(url, {
      method: 'GET',
      credentials: 'same-origin'
    });

    const text = await res.text();
    let data = null;

    try {
      data = JSON.parse(text);
    } catch (e) {
      throw new Error('Invalid JSON response');
    }

    if (!data.success) {
      throw new Error((data.data && data.data.error) ? data.data.error : 'Failed to load sales price history');
    }

    return (data.data && Array.isArray(data.data.items)) ? data.data.items : [];
  }

  // ===== fetch purchase price history =====
  async function fetchPurchasePriceHistory(itemCode){
    const cfg = window.AC_SUGGEST || {};
    const ajaxUrl = cfg.ajaxUrl || '';
    const nonce = cfg.purchasePriceHistoryNonce || '';

    if (!ajaxUrl || !nonce || !itemCode) return [];

    const url =
      ajaxUrl +
      '?action=ac_item_purchase_price_history' +
      '&nonce=' + encodeURIComponent(nonce) +
      '&itemCode=' + encodeURIComponent(itemCode);

    const res = await fetch(url, {
      method: 'GET',
      credentials: 'same-origin'
    });

    const text = await res.text();
    let data = null;

    try {
      data = JSON.parse(text);
    } catch (e) {
      throw new Error('Invalid JSON response');
    }

    if (!data.success) {
      throw new Error((data.data && data.data.error) ? data.data.error : 'Failed to load purchase price history');
    }

    return (data.data && Array.isArray(data.data.items)) ? data.data.items : [];
  }

  // ===== renderLines with editable price =====
  function renderLines(){
    const tbody = $('ac_so_lines');
    tbody.innerHTML = '';

    if(!state.lines.length){
      tbody.innerHTML = '<tr><td colspan="5" class="empty">No lines added yet.</td></tr>';
      recalc();
      return;
    }

    state.lines.forEach((l, idx) => {
      const qtyVal = parseFloat(l.qty) || 0;
      const unitPriceVal = parseFloat(l.unitPrice) || 0;
      const lineTotal = qtyVal * unitPriceVal;
      const expanded = !!l.showHistoryPanel;

      const tr = document.createElement('tr');
      tr.className = 'ac-line-row' + (expanded ? ' is-open' : '');
      tr.setAttribute('data-idx', idx);

      tr.innerHTML = `
        <td class="ac-line-main-cell">
          <div class="ac-line-click" data-role="toggle-history-panel" data-idx=�K�>��q@���������L�
�?�A"${idx}">
            <b>${escapeHtml(l.itemName || l.itemCode)}</b>
            ${
              l.itemName && l.itemCode
                ? `<div class="ac-line-meta">${escapeHtml(l.itemCode)}${l.uom ? ` <span class="ac-line-uom">(${escapeHtml(l.uom)})</span>` : ''}</div>`
                : (l.uom ? `<div class="ac-line-meta"><span class="ac-line-uom">(${escapeHtml(l.uom)})</span></div>` : '')
            }
          </div>
        </td>
        <td class="r">
          <div class="ac-line-click" data-role="toggle-history-panel" data-idx="${idx}">
            ${escapeHtml(l.qty)}
          </div>
        </td>
        <td class="r">
          <input
            type="number"
            class="ac-price-input"
            data-role="edit-price"
            data-idx="${idx}"
            min="0"
            step="0.01"
            value="${fmtMoney(unitPriceVal)}"
          >
        </td>
        <td class="r" data-role="line-total" data-idx="${idx}">
          ${fmtMoney(lineTotal)}
        </td>
        <td class="r">
          <button type="button" class="ac-x" data-idx="${idx}" title="Remove">✕</button>
        </td>
      `;
      tbody.appendChild(tr);

      if (expanded) {
        const activeTab = l.activeHistoryTab || 'sales';

        const salesContent = l.historyLoading
          ? '<div class="ac-history-loading">Loading sales price history...</div>'
          : l.historyError
            ? `<div class="ac-history-error">${escapeHtml(l.historyError)}</div>`
            : Array.isArray(l.historyData)
              ? renderHistoryTable(l.historyData)
              : '<div class="ac-history-empty">No sales price history loaded.</div>';

        const purchaseContent = l.purchaseHistoryLoading
          ? '<div class="ac-history-loading">Loading purchase price history...</div>'
          : l.purchaseHistoryError
            ? `<div class="ac-history-error">${escapeHtml(l.purchaseHistoryError)}</div>`
            : Array.isArray(l.purchaseHistoryData)
              ? renderPurchaseHistoryTable(l.purchaseHistoryData)
              : '<div class="ac-history-empty">No purchase price history loaded.</div>';

        const historyRow = document.createElement('tr');
        historyRow.className = 'ac-history-row';
        historyRow.innerHTML = `
          <td colspan="5">
            <div class="ac-history-panel ac-history-tabs-panel">
              <div class="ac-history-tabs">
                <button type="button"
                        class="ac-history-tab ${activeTab === 'sales' ? 'is-active' : ''}"
                        data-role="history-tab"
                        data-tab="sales"
                        data-idx="${idx}">
                  Sales Price History
                </button>
                <button type="button"
                        class="ac-history-tab ${activeTab === 'purchase' ? 'is-active' : ''}"
                        data-role="history-tab"
                        data-tab="purchase"
                        data-idx="${idx}">
                  Purchase Price History
                </button>
              </div>

              <div class="ac-history-tabbody ${activeTab === 'sales' ? 'is-active' : ''}" data-tabbody="sales">
                ${salesContent}
              </div>

              <div class="ac-history-tabbody ${activeTab === 'purchase' ? 'is-active' : ''}" data-tabbody="purchase">
                ${purchaseContent}
              </div>
            </div>
          </td>
        `;
        tbody.appendChild(historyRow);
      }
    });

    recalc();
  }

  // ===== ensure functions =====
  async function ensureSalesHistoryLoaded(idx){
    const line = state.lines[idx];
    if (!line) return;

    if (Array.isArray(line.historyData) || line.historyLoading) return;

    line.historyLoading = true;
    line.historyError = '';
    renderLines();

    try {
      const rows = await fetchPriceHistory(line.itemCode);
      line.historyData = rows;
    } catch (err) {
      line.historyError = err.message || 'Failed to load sales price history';
    } finally {
      line.historyLoading = false;
      renderLines();
    }
  }

  async function ensurePurchaseHistoryLoaded(idx){
    const line = state.lines[idx];
    if (!line) return;

    if (Array.isArray(line.purchaseHistoryData) || line.purchaseHistoryLoading) return;

    line.purchaseHistoryLoading = true;
    line.purchaseHistoryError = '';
    renderLines();

    try {
      const rows = await fetchPurchasePriceHistory(line.itemCode);
      line.purchaseHistoryData = rows;
    } catch (err) {
      line.purchaseHistoryError = err.message || 'Failed to load purchase price history';
    } finally {
      line.purchaseHistoryLoading = false;
      renderLines();
    }
  }

  // ===== openHistoryPanel =====
  async function openHistoryPanel(idx, tab){
    const line = state.lines[idx];
    if (!line) return;

    line.showHistoryPanel = true;
    line.activeHistoryTab = tab === 'purchase' ? 'purchase' : 'sales';
    renderLines();

    if (line.activeHistoryTab === 'sales') {
      await ensureSalesHistoryLoaded(idx);
    } else {
      await ensurePurchaseHistoryLoaded(idx);
    }
  }

  // ===== toggleHistoryPanel =====
  async function toggleHistoryPanel(idx){
    const line = state.lines[idx];
    if (!line) return;

    if (line.showHistoryPanel) {
      line.showHistoryPanel = false;
      renderLines();
      return;
    }

    line.showHistoryPanel = true;
    if (!line.activeHistoryTab) {
      line.activeHistoryTab = 'sales';
    }

    renderLines();

    if (line.activeHistoryTab === 'purchase') {
      await ensurePurchaseHistoryLoaded(idx);
    } else {
      await ensureSalesHistoryLoaded(idx);
    }
  }

  // ----- SweetAlert2 helpers -----
  function showToast(icon, title, text = '') {
    if (window.Swal) {
      Swal.fire({
        toast: true,
        position: 'top-end',
        icon,
        title,
        text,
        showConfirmButton: false,
        timer: 2600,
        timerProgressBar: true
      });
    }
  }

  function showModal(icon, title, html) {
    if (window.Swal) {
      Swal.fire({
        icon,
        title,
        html,
        confirmButtonText: 'OK'
      });
    }
  }

  // ----- Improved apiGet with nonce and cache control -----
  async function apiGet(url){
    const res = await fetch(url, {
      method: 'GET',
      credentials: 'same-origin',
      headers: {
        'Accept': 'application/json',
        'X-WP-Nonce': REST_NONCE
      },
      cache: 'no-store'
    });

    const text = await res.text();
    let data = null;

    try {
      data = text ? JSON.parse(text) : null;
    } catch (e) {
      throw new Error('Invalid JSON from job status endpoint: ' + text.slice(0, 200));
    }

    if (!res.ok) {
      throw new Error((data && (data.message || data.error)) || `HTTP ${res.status}`);
    }

    return data;
  }

  async function apiPost(url, body){
    const res = await fetch(url, {
      method:'POST',
      credentials:'same-origin',
      headers:{
        'Content-Type':'application/json',
        'Accept':'application/json',
        'X-WP-Nonce': REST_NONCE
      },
      body: JSON.stringify(body)
    });
    return await res.json();
  }

  // ----- Robust polling function -----
  async function pollJob(jobId){
    const max = 45;

    for (let i = 0; i < max; i++) {
      await new Promise(r => setTimeout(r, 2000));

      let r;
      try {
        r = await apiGet(REST_JOB_BASE + jobId + '?_t=' + Date.now());
      } catch (err) {
        console.log('[CS DEBUG] pollJob fetch error:', err);
        setStatus('Polling error: ' + err.message || String(err), 'error');
        showToast('error', 'Polling failed', err.message || 'Unable to read job status');
        return false;
      }

      console.log('[CS DEBUG] pollJob raw response:', r);

      const job = r?.job || r?.data?.job || r;
      const st = String(job?.status || '').toUpperCase();

      if (!st) {
        console.log('[CS DEBUG] pollJob: no status found in response');
        continue;
      }

      setStatus(`Job #${jobId}: ${st}`, (
        st === 'SUCCESS' ? 'success' :
        (st === 'FAILED' || st === 'FAILED_FINAL') ? 'error' :
        st === 'CANCELLED' ? 'warning' :
        'info'
      ));

      setLastChange(`Queue status: ${st}`);

      if (st === 'SUCCESS') {
        if (state.jobFinished) return true;
        state.jobFinished = true;

        let result = job.result || {};
        if (typeof result === 'string') {
          try { result = JSON.parse(result); } catch(e) {}
        }

        const docNo =
          result.docNo ||
          result.DocNo ||
          job.docNo ||
          '';

        if (docNo) {
          const editUrl = EDIT_BASE + '?docno=' + encodeURIComponent(docNo);
          setStatus(`Cash Sale created: ${docNo}`, 'success');

          showModal(
            'success',
            'Cash Sale Created',
            `Document <b>${escapeHtml(docNo)}</b> was saved successfully.<br><br>
             <a href="${editUrl}" target="_blank" rel="noopener">Open Cash Sale</a>`
          );
        } else {
          setStatus('Cash Sale created successfully.', 'success');
          showToast('success', 'Cash Sale created');
        }

        return true;
      }

      if (st === 'FAILED' || st === 'FAILED_FINAL') {
        if (state.jobFinished) return false;
        state.jobFinished = true;

        let result = job.result || {};
        if (typeof result === 'string') {
          try { result = JSON.parse(result); } catch(e) {}
        }

        const err =
          job.error_message ||
          job.error ||
          result.error ||
          'Job failed';

        setStatus(err, 'error');
        showModal('error', 'Cash Sale Failed', escapeHtml(err));
        return false;
      }

      if (st === 'CANCELLED') {
        if (state.jobFinished) return false;
        state.jobFinished = true;
        setStatus('Job was cancelled.', 'warning');
        showToast('warning', 'Job cancelled');
        return false;
      }
    }

    setStatus('Job timed out. BridgeWorker might be offline.', 'warning');
    showModal(
      'warning',
      'Queue Timeout',
      'The page did not receive a final status in time.<br><br>Check the Jobs table to confirm whether it already completed.'
    );
    return false;
  }

  // ========== MODIFIED attachSearch TO ALLOW 1-CHARACTER SEARCH ==========
  function attachSearch(inputEl, ddEl, fetchFn, onPick){
    let t = null;
    function hide(){ ddEl.style.display='none'; ddEl.innerHTML=''; }
    function show(){ ddEl.style.display='block'; }

    inputEl.addEventListener('input', () => {
      clearTimeout(t);
      const q = inputEl.value.trim();

      // CHANGE: allow 1-letter search
      if(q.length < 1){ hide(); return; }

      t = setTimeout(async () => {
        ddEl.innerHTML = '<div class="item"><small>Searching...</small></div>';
        show();
        try{
          const items = await fetchFn(q);
          if(!items.length){
            ddEl.innerHTML = '<div class="item"><small>No result</small></div>';
            return;
          }
          ddEl.innerHTML = items.map((it, idx) => `
            <div class="item" data-idx="${idx}">
              <strong>${escapeHtml(it.name || it.code)}</strong>
              <small>${escapeHtml(it.code)}</small>
              <small>${escapeHtml(it.sub || '')}</small>
            </div>
          `).join('');

          ddEl.querySelectorAll('.item[data-idx]').forEach(node => {
            node.addEventListener('click', () => {
              const i = parseInt(node.dataset.idx, 10);
              onPick(items[i]);
              hide();
            });
          });
        }catch(e){
          ddEl.innerHTML = '<div class="item"><small>Failed to load</small></div>';
        }
      }, 200);
    });

    document.addEventListener('click', (e) => {
      if(!ddEl.contains(e.target) && e.target !== inputEl) hide();
    });
  }

  async function searchItemsLive(q){
    const cfg = window.AC_SUGGEST || {};
    const ajaxUrl = cfg.ajaxUrl || "";
    const nonce = cfg.nonce || "";
    if(!ajaxUrl || !nonce) return [];

    const fd = new FormData();
    fd.append("action", "ac_itemcode_suggest");
    fd.append("nonce", nonce);
    fd.append("term", q);

    const res = await fetch(ajaxUrl, {
      method: "POST",
      credentials: "same-origin",
      body: fd
    });

    const data = await res.json().catch(()=>null);
    const arr = (data && data.ok && Array.isArray(data.items)) ? data.items : [];

    return arr.map(it => {
      let priceVal = it.unitPrice !== undefined ? it.unitPrice : it.price;
      if (priceVal === null || priceVal === undefined) priceVal = 0;

      const name = (it.desc || it.name || it.description || it.code || '').trim();

      return {
        code: it.code || '',
        name: name,
        uom: it.uom || '',
        price: parseFloat(priceVal),
        sub: [it.desc2 || '', it.code ? ('Code: ' + it.code) : ''].filter(Boolean).join(' | ')
      };
    });
  }

  function updateLinePreview(){
    const pv = $('ac_so_line_preview');
    const code = ($('ac_so_item').value || '').trim();
    const name = ($('ac_so_item_display').value || '').trim();
    const uom  = ($('ac_so_uom').value || '').trim();
    const qty  = parseFloat(($('ac_so_qty').value || '0')) || 0;
    const price= parseFloat(($('ac_so_price_hidden').value || '0')) || 0;

    if(!code){
      pv.style.display = 'none';
      pv.innerHTML = '';
      return;
    }

    const shown = name || code;
    const total = qty * price;

    pv.style.display = 'flex';
    pv.innerHTML = `
      <div><b>${escapeHtml(shown)}</b> ${uom ? `<span style="color:#64748b;">(${escapeHtml(uom)})</span>` : ``}</div>
      <div><span style="color:#64748b;">Unit:</span> <b>${fmtMoney(price)}</b> &nbsp; | &nbsp; <span style="color:#64748b;">Total:</span> <b>${fmtMoney(total)}</b></div>
    `;
  }

  function makeClientRequestId(prefix='CS'){
    const rnd = Math.random().toString(36).slice(2,10);
    const ts  = Date.now().toString(36);
    return `${prefix}-${ts}-${rnd}`;
  }

  // ===== buildFinalCustomerName with uppercase suffix =====
  function buildFinalCustomerName(){
    const baseEl = document.getElementById('ac_so_customer_base');
    const sufEl  = document.getElementById('ac_so_customer_suffix');
    const hidEl  = document.getElementById('ac_so_customer_final_name');

    const base = (baseEl ? baseEl.value : '').trim();
    let suf    = (sufEl ? sufEl.value : '').trim();

    // force uppercase in value itself
    suf = suf.toUpperCase();
    if (sufEl) sufEl.value = suf;

    const finalName = (base + ' ' + suf).trim();
    if (hidEl) hidEl.value = finalName;

    return finalName;
  }

  (function initCustomerDropdown(){
    const wrapper = document.getElementById('acSoDebtorWrapper');
    if (!wrapper) return;

    const AJAX_URL = wrapper.dataset.ajaxUrl;
    const NONCE = wrapper.dataset.nonce;

    const input = document.getElementById('acSoDebtorInput');
    const dropdown = document.getElementById('acSoDebtorDropdown');
    const hiddenCode = document.getElementById('ac_so_customer');

    let items = [];
    let activeIndex = -1;
    let abortController = null;
    let searchTimeout = null;

    const show = () => dropdown.classList.add('active');
    const hide = () => { dropdown.classList.remove('active'); activeIndex = -1; };

    const renderEmpty = (msg) => {
      dropdown.innerHTML = `<div class="ac-dropdown-empty">${escapeHtml(msg)}</div>`;
      show();
    };

    const renderError = (msg) => {
      dropdown.innerHTML = `<div class="ac-dropdown-error">⚠️ ${escapeHtml(msg)}</div>`;
      show();
    };

    const renderResults = (arr) => {
      if (!arr || �L�s�hA���������L�
�<�����arr.length === 0) return renderEmpty('No customers found');
      dropdown.innerHTML = arr.map((it, idx) => {
        const name = it.name || it.debtorName || it.description || '';
        const code = it.code || it.debtorCode || it.id || '';
        const sa   = (it.salesAgent || it.sales_agent || it.sa || '').trim();
        return `
          <div class="ac-dropdown-item" data-index="${idx}">
            <strong>${escapeHtml(name)}</strong>
            <small>${escapeHtml(code)}${sa ? ' • SA: ' + escapeHtml(sa) : ''}</small>
          </div>
        `;
      }).join('');
      show();
      activeIndex = -1;
    };

    const selectItem = (idx) => {
      if (idx < 0 || idx >= items.length) return;
      const it = items[idx];

      const name = it.name || it.debtorName || it.description || '';
      const code = it.code || it.debtorCode || it.id || '';
      const salesAgent = (it.salesAgent || it.sales_agent || it.sa || '').trim();

      input.value = name;
      hiddenCode.value = code;
      hide();

      // Update hidden base and visible suffix
      const baseEl = document.getElementById('ac_so_customer_base');
      const sufEl  = document.getElementById('ac_so_customer_suffix');

      if (baseEl) baseEl.value = name || '';
      if (sufEl)  sufEl.value  = '';

      // --- Handle both CASH SALE and CASH SALES ---
      let suffix = '';
      const m = String(name || '').match(/^(CASH SALE[S]?)\s+(.+)$/i);
      if (m) {
          const base = m[1];           // "CASH SALE" or "CASH SALES"
          suffix = m[2].trim();         // the remaining part after the space
          if (baseEl) baseEl.value = base;
          if (sufEl) sufEl.value = suffix;
      }
      // ----------------------------------------------------

      // Update hidden sales agent fields
      const saEl = document.getElementById('ac_so_sales_agent');
      const saCodeEl = document.getElementById('ac_so_sales_agent_code');
      if (saEl) saEl.value = salesAgent || '';
      if (saCodeEl) saCodeEl.value = salesAgent || '';

      const finalName = buildFinalCustomerName();
      setLastChange('Customer: ' + (finalName || code || ''));

      console.log('[CS DEBUG] Debtor selected:', { code, name, salesAgent, finalName });
    };

    const performSearch = async (query) => {
      if (abortController) abortController.abort();
      abortController = new AbortController();

      const q = (query || '').trim();
      if (q.length < 1) { hide(); return; }

      renderEmpty('Searching...');

      try {
        const url = `${AJAX_URL}?action=ac_cs_debtor_search&nonce=${encodeURIComponent(NONCE)}&q=${encodeURIComponent(q)}`;
        const response = await fetch(url, { signal: abortController.signal, credentials:'same-origin' });
        const text = await response.text();

        let data;
        try { data = JSON.parse(text); }
        catch (e) { throw new Error('Invalid JSON response'); }

        if (!data.success) throw new Error((data.data && data.data.error) ? data.data.error : 'Search failed');

        items = (data.data && data.data.items) ? data.data.items : [];
        renderResults(items);

      } catch (err) {
        if (err.name === 'AbortError') return;
        renderError('Failed to load results');
      }
    };

    const debounceSearch = () => {
      clearTimeout(searchTimeout);
      searchTimeout = setTimeout(() => performSearch(input.value), 300);
    };

    input.addEventListener('input', () => {
      hiddenCode.value = '';

      const baseEl = document.getElementById('ac_so_customer_base');
      const sufEl  = document.getElementById('ac_so_customer_suffix');
      const saEl   = document.getElementById('ac_so_sales_agent');
      const saCodeEl = document.getElementById('ac_so_sales_agent_code');
      if (baseEl) baseEl.value = '';
      if (sufEl) sufEl.value = '';
      if (saEl) saEl.value = '';
      if (saCodeEl) saCodeEl.value = '';

      debounceSearch();
    });

    input.addEventListener('focus', () => {
      if (input.value.trim() !== '') debounceSearch();
    });

    input.addEventListener('keydown', (e) => {
      if (!dropdown.classList.contains('active')) return;
      const nodes = dropdown.querySelectorAll('.ac-dropdown-item');
      if (!nodes.length) return;

      if (e.key === 'ArrowDown') {
        e.preventDefault();
        activeIndex = (activeIndex + 1) % nodes.length;
        nodes.forEach((n, i) => n.classList.toggle('active', i === activeIndex));
      } else if (e.key === 'ArrowUp') {
        e.preventDefault();
        activeIndex = activeIndex > 0 ? activeIndex - 1 : nodes.length - 1;
        nodes.forEach((n, i) => n.classList.toggle('active', i === activeIndex));
      } else if (e.key === 'Enter' && activeIndex >= 0) {
        e.preventDefault();
        selectItem(activeIndex);
      } else if (e.key === 'Escape') {
        hide();
      }
    });

    dropdown.addEventListener('click', (e) => {
      const node = e.target.closest('.ac-dropdown-item');
      if (!node) return;
      selectItem(parseInt(node.dataset.index, 10));
    });

    document.addEventListener('click', (e) => {
      if (!wrapper.contains(e.target)) hide();
    });
  })();

  (function init(){
    const d = new Date();
    $('ac_so_date').value = `${d.getFullYear()}-${String(d.getMonth()+1).padStart(2,'0')}-${String(d.getDate()).padStart(2,'0')}`;

    attachSearch($('ac_so_item_name'), $('ac_so_item_dd'), searchItemsLive, (it) => {
      $('ac_so_item_name').value = it.name || it.code || '';
      $('ac_so_item').value = it.code || '';
      $('ac_so_item_display').value = it.name || it.code || '';
      $('ac_so_uom').value = it.uom || '';
      $('ac_so_price_hidden').value = (it.price || 0);

      setLastChange('Item: ' + ($('ac_so_item_display').value || it.code || ''));

      if(!it.price && it.price !== 0){
        setStatus('This item returned no price. Check ItemUOM.Price for SalesUOM/BaseUOM.', 'warning');
      }

      updateLinePreview();
    });

    $('ac_so_qty').addEventListener('input', updateLinePreview);
    $('ac_so_item_name').addEventListener('input', () => {
      $('ac_so_item').value = '';
      $('ac_so_item_display').value = '';
      $('ac_so_uom').value = '';
      $('ac_so_price_hidden').value = '';
      updateLinePreview();
    });

    // ===== suffix input with uppercase conversion =====
    const sufEl = document.getElementById('ac_so_customer_suffix');
    if (sufEl){
      sufEl.addEventListener('input', () => {
        const pos = sufEl.selectionStart;
        sufEl.value = (sufEl.value || '').toUpperCase();

        try {
          sufEl.setSelectionRange(pos, pos);
        } catch(e) {}

        const finalName = buildFinalCustomerName();
        if(finalName) setLastChange('Customer: ' + finalName);
      });

      sufEl.addEventListener('blur', () => {
        sufEl.value = (sufEl.value || '').toUpperCase();
        buildFinalCustomerName();
      });
    }

    const paymentInput = document.getElementById('ac_so_payment_amount');
    if (paymentInput) {
      paymentInput.addEventListener('input', function() {
        paymentManuallyEdited = true;
      });
    }

    renderLines();
    updateLinePreview();
  })();

  // ===== ADD LINE HANDLER WITH MERGE =====
  $('ac_so_addline').addEventListener('click', () => {
    const itemCode = ($('ac_so_item').value || '').trim();
    const itemName = ($('ac_so_item_display').value || '').trim();
    const qty = parseFloat(($('ac_so_qty').value || '0')) || 0;

    const unitPrice = parseFloat(($('ac_so_price_hidden').value || '0'));
    const uom = ($('ac_so_uom').value || '').trim();

    if(!itemCode){
      setStatus('Please select Item from dropdown (so price is loaded).', 'error');
      return;
    }
    if(qty <= 0){
      setStatus('Qty must be > 0.', 'error');
      return;
    }
    if(isNaN(unitPrice)){
      setStatus('Price not loaded. Check ItemUOM.Price for SalesUOM/BaseUOM.', 'error');
      return;
    }

    // Merge same item into existing row instead of adding new row
    const existing = state.lines.find(l =>
      String(l.itemCode || '').trim().toUpperCase() === itemCode.toUpperCase()
    );

    if (existing) {
      existing.qty = (parseFloat(existing.qty) || 0) + qty;

      // keep latest visible values tidy
      existing.itemName = itemName || existing.itemName;
      existing.uom = uom || existing.uom;
      existing.unitPrice = unitPrice;

      const shown = (existing.itemName || existing.itemCode);
      setLastChange(`Updated ${shown} qty to ${existing.qty}`);
      setStatus(`Updated: ${shown} total qty = ${existing.qty}`, 'success');
    } else {
      state.lines.push({
        itemCode,
        itemName,
        qty,
        unitPrice,
        uom,

        showHistoryPanel: false,
        activeHistoryTab: 'sales',

        historyLoading: false,
        historyError: '',
        historyData: null,

        purchaseHistoryLoading: false,
        purchaseHistoryError: '',
        purchaseHistoryData: null
      });

      const shown = (itemName || itemCode);
      setLastChange(`Added ${shown} x${qty}`);
      setStatus(`Added: ${shown} x${qty}`, 'success');
    }

    $('ac_so_item_name').value = '';
    $('ac_so_item').value = '';
    $('ac_so_item_display').value = '';
    $('ac_so_uom').value = '';
    $('ac_so_price_hidden').value = '';
    $('ac_so_qty').value = 1;

    renderLines();
    updateLinePreview();
  });

  // ===== click listener (remove, panel toggle, and tab clicks) =====
  $('ac_so_lines').addEventListener('click', async (e) => {
    const removeBtn = e.target.closest('button[data-idx]');
    if (removeBtn && !removeBtn.matches('[data-role]')) {
      const idx = parseInt(removeBtn.dataset.idx, 10);
      if (isNaN(idx)) return;

      const removed = state.lines[idx];
      state.lines.splice(idx, 1);

      const shown = removed && (removed.itemName || removed.itemCode) ? (removed.itemName || removed.itemCode) : '';
      setLastChange(`Removed ${shown}`);
      setStatus(`Removed: ${shown}`, 'warning');

      renderLines();
      return;
    }

    const panelToggle = e.target.closest('[data-role="toggle-history-panel"]');
    if (panelToggle) {
      const idx = parseInt(panelToggle.dataset.idx, 10);
      if (isNaN(idx)) return;
      await toggleHistoryPanel(idx);
      return;
    }

    const tabBtn = e.target.closest('[data-role="history-tab"]');
    if (tabBtn) {
      const idx = parseInt(tabBtn.dataset.idx, 10);
      const tab = tabBtn.dataset.tab || 'sales';
      if (isNaN(idx)) return;
      await openHistoryPanel(idx, tab);
    }
  });

  // ===== price edit listeners =====
  $('ac_so_lines').addEventListener('input', (e) => {
    const priceInput = e.target.closest('[data-role="edit-price"]');
    if (!priceInput) return;

    const idx = parseInt(priceInput.dataset.idx, 10);
    if (isNaN(idx) || !state.lines[idx]) return;

    let newPrice = parseFloat(priceInput.value);
    if (isNaN(newPrice) || newPrice < 0) {
      newPrice = 0;
    }

    state.lines[idx].unitPrice = newPrice;

    const qty = parseFloat(state.lines[idx].qty) || 0;
    const totalCell = $('ac_so_lines').querySelector(`[data-role="line-total"][data-idx="${idx}"]`);
    if (totalCell) {
      totalCell.textContent = fmtMoney(qty * newPrice);
    }

    recalc();
  });

  $('ac_so_lines').addEventListener('change', (e) => {
    const priceInput = e.target.closest('[data-role="edit-price"]');
    if (!priceInput) return;

    let newPrice = parseFloat(priceInput.value);
    if (isNaN(newPrice) || newPrice < 0) {
      newPrice = 0;
    }

    priceInput.value = fmtMoney(newPrice);

    const idx = parseInt(priceInput.dataset.idx, 10);
    if (!isNaN(idx) && state.lines[idx]) {
      const shown = state.lines[idx].itemName || state.lines[idx].itemCode || 'Item';
      setStatus(`Updated price: ${shown} = ${fmtMoney(newPrice)}`, 'success');
    }
  });

  // ----- Submit handler (with uom and description added) -----
  $('ac_so_submit').addEventListener('click', async () => {
    const submitBtn = $('ac_so_submit');

    state.jobFinished = false;

    try {
      submitBtn.disabled = true;
      submitBtn.textContent = 'Saving...';

      const customerCode = ($('ac_so_customer').value || '').trim();
      const docDate = ($('ac_so_date').value || '').trim();

      const paymentMethod = ($('ac_so_payment_method')?.value || 'CASH').trim();
      const paymentAmount = parseFloat(($('ac_so_payment_amount')?.value || '0')) || 0;

      if(!customerCode){ setStatus('Please select Customer from dropdown.', 'error'); return; }
      if(!docDate){ setStatus('Please enter Date.', 'error'); return; }
      if(!state.lines.length){ setStatus('Please add at least 1 line item.', 'error'); return; }

      setStatus('Submitting job...', 'info');

      const customerName = buildFinalCustomerName();
      const salesAgent = (document.getElementById('ac_so_sales_agent_code')?.value || '').trim();

      const payload = {
        customerCode,
        customerName,
        salesAgent,

        debtorCode: customerCode,
        DebtorCode: customerCode,
        debtorName: customerName,
        DebtorName: customerName,
        SalesAgent: salesAgent,

        docDate,
        remark: '',
        displayTerm: 'C.O.D.',
        paymentMethod,
        paymentAmount,

        lines: state.lines.map(l => ({
          itemCode: l.itemCode,
          qty: l.qty,
          uom: l.uom || '',
          unitPrice: l.unitPrice,
          description: l.itemName || ''
        }))
      };

      console.log('[CS DEBUG] SUBMIT payload:', payload);

      const body = {
        type: 'CASH_SALE',
        client_request_id: makeClientRequestId('CS'),
        source: 'wp-ui',
        payload
      };

      console.log('[CS DEBUG] JOB body:', body);

      const r = await apiPost(REST_JOB_POST, body);
      console.log('[CS DEBUG] JOB create response:', r);

      if (!r || r.ok === false) {
        const errMsg = (r && (r.message || r.error)) ? (r.message || r.error) : 'Submit failed.';
        setStatus(errMsg, 'error');
        showModal('error', 'Submit failed', escapeHtml(errMsg));
        return;
      }

      const jobId = r.jobId || r.id || (r.job && r.job.id);
      if (!jobId) {
        setStatus('Job created but jobId missing in response.', 'warning');
        showToast('warning', 'Job created, but jobId missing');
        setLastChange('Submitted to queue');
        return;
      }

      setStatus(`Job queued: #${jobId}. Waiting BridgeWorker...`, 'info');
      showToast('info', 'Job queued', `Job #${jobId}`);
      setLastChange('Submitted to queue');

      await pollJob(jobId);

    } catch(err) {
      console.log('[CS DEBUG] SUBMIT error:', err);
      setStatus('Submit error: ' + (err.message || String(err)), 'error');
      showModal('error', 'Submit error', escapeHtml(err.message || String(err)));
    } finally {
      submitBtn.disabled = false;
      submitBtn.textContent = 'Save Cash Sale';
    }
  });

})();
</script>�L�����B���������L��
�?�C<?php
/**
 * CASH SALES EDIT PAGE — REDESIGN MATCHING CREATE PAGE
 * - Cleaner layout
 * - No "Header" title
 * - Items moved to separate section
 * - Remark removed
 * - Mobile-friendly
 */

if (!defined('ABSPATH')) exit;

if (!is_user_logged_in()) {
  echo '<div style="padding:14px;border:1px solid #fecaca;background:#fff1f2;border-radius:12px;color:#991b1b;">
    Please log in to edit Cash Sale.
  </div>';
  return;
}

$rest_nonce = wp_create_nonce('wp_rest');

$list_url  = 'https://website.ipohserver.com/ECOSalesInventorySearch/index.php/cash-sales/';
$edit_base = 'https://website.ipohserver.com/ECOSalesInventorySearch/index.php/cash-sale-edit/';

$REST_JOB_POST   = rest_url('ac/v1/job');
$REST_JOB_BASE   = rest_url('ac/v1/job/');
$REST_CS_UPDATE  = rest_url('ac/v1/cash-sale/update');

$ajax_url             = admin_url('admin-ajax.php');
$debtor_nonce         = wp_create_nonce('ac_cs_debtor_search');
$item_suggest_nonce   = wp_create_nonce('ac_itemcode_suggest');
$get_doc_nonce        = wp_create_nonce('ac_cs_get_by_docno');
?>

<script>
window.AC_SUGGEST = window.AC_SUGGEST || {};
window.AC_SUGGEST.ajaxUrl = "<?php echo esc_js($ajax_url); ?>";
window.AC_SUGGEST.nonce   = "<?php echo esc_js($item_suggest_nonce); ?>";
</script>

<div class="ac-so-wrap"
     data-rest-nonce="<?php echo esc_attr($rest_nonce); ?>"
     data-edit-base="<?php echo esc_attr($edit_base); ?>"
     data-rest-job-post="<?php echo esc_attr($REST_JOB_POST); ?>"
     data-rest-job-base="<?php echo esc_attr($REST_JOB_BASE); ?>"
     data-rest-cs-update="<?php echo esc_attr($REST_CS_UPDATE); ?>"
     data-ajax-url="<?php echo esc_attr($ajax_url); ?>"
     data-get-doc-nonce="<?php echo esc_attr($get_doc_nonce); ?>">

  <div class="ac-so-pagehead ac-so-pagehead-inline">
    <a class="ac-so-btn ghost" href="<?php echo esc_url($list_url); ?>">← Back to List</a>
    <div class="ac-so-pagehead-copy">
      <h1>Edit Cash Sale</h1>
      <div class="ac-so-docno-row">DocNo: <span id="ac_cs_docno_label">—</span></div>
    </div>
  </div>

  <div class="ac-so-card ac-so-main-card">

    <div class="ac-so-row2 ac-so-row-single">
      <div class="ac-so-field">
        <label>Date</label>
        <input id="ac_so_date" type="date" />
      </div>
    </div>

    <input type="hidden" id="ac_so_customer_base" value="" />
    <input type="hidden" id="ac_so_customer_final_name" value="" />
    <input type="hidden" id="ac_so_sales_agent" value="" />
    <input type="hidden" id="ac_so_sales_agent_code" value="" />
    <div id="ac_so_last_change" style="display:none;"></div>

    <div class="ac-so-row2" style="margin-top:10px;">
      <div class="ac-so-field">
        <label>Customer</label>

        <div class="ac-search-wrapper"
             id="acSoDebtorWrapper"
             data-ajax-url="<?php echo esc_attr($ajax_url); ?>"
             data-nonce="<?php echo esc_attr($debtor_nonce); ?>">

          <input type="text"
                 id="acSoDebtorInput"
                 class="ac-search-input"
                 placeholder="Search by customer name..."
                 autocomplete="off" />

          <input type="hidden" id="ac_so_customer" value="" />
          <div class="ac-search-dropdown" id="acSoDebtorDropdown"></div>
        </div>
      </div>

      <div class="ac-so-field">
        <label>Extra Name</label>
        <input id="ac_so_customer_suffix" type="text" placeholder="e.g. ABANG SAYAN" value="" />
      </div>
    </div>

    <div class="ac-so-row2" style="margin-top:10px;">
      <div class="ac-so-field">
        <label>Payment Method</label>
        <select id="ac_so_payment_method">
          <option value="CASH">Cash</option>
          <option value="CARD">Card</option>
          <option value="CHEQUE">Cheque</option>
          <option value="BANK">Bank Transfer</option>
        </select>
      </div>

      <div class="ac-so-field">
        <label>Payment Amount</label>
        <input id="ac_so_payment_amount" type="number" min="0" step="0.01" value="0.00" />
      </div>
    </div>

    <div id="ac_so_status" class="ac-so-status"></div>
  </div>

  <div class="ac-so-card ac-so-items-card">
    <div class="ac-so-line-entry">
      <div class="ac-so-field">
        <label>Item</label>
        <div class="ac-item-search-wrap">
          <input id="ac_so_item_name" type="text" placeholder="Search by item name (e.g. timing) or code..." autocomplete="off">
          <input id="ac_so_item" type="hidden" value="">
          <input id="ac_so_item_display" type="hidden" value="">
          <input id="ac_so_uom" type="hidden" value="">
          <input id="ac_so_price_hidden" type="hidden" value="">
          <div class="ac-dd" id="ac_so_item_dd" style="display:none;"></div>
          <div class="ac-line-preview" id="ac_so_line_preview" style="display:none;"></div>
        </div>
      </div>

      <div class="ac-so-field mini">
        <label>Qty</label>
        <input id="ac_so_qty" type="number" min="1" step="1" value="1">
      </div>

      <div class="ac-so-field mini ac-so-add-wrap">
        <button id="ac_so_addline" class="ac-so-btn small" type="button">Add</button>
      </div>
    </div>

    <div class="ac-so-table-wrap">
      <table class="ac-so-table">
        <thead>
          <tr>
            <th>Item</th>
            <th class="r">Qty</th>
            <th class="r">Price</th>
            <th class="r">Total</th>
            <th class="r"></th>
          </tr>
        </thead>
        <tbody id="ac_so_lines">
          <tr><td colspan="5" class="empty">Loading…</td></tr>
        </tbody>
      </table>
    </div>

    <div class="ac-so-items-footer">
      <div class="ac-so-total-inline">
        <div class="lbl">Final Total</div>
        <div class="amt" id="ac_so_final_total">0.00</div>
      </div>
    </div>
  </div>

  <div class="ac-so-actions">
    <button class="ac-so-btn" id="ac_so_submit" type="button">Update Cash Sale</button>
  </div>

</div>

<style>
  /* ===== CLEAN BUSINESS STYLES — FULL WIDTH VERSION ===== */
  .ac-so-wrap{
    --ac-primary:#1677ff;
    --ac-primary-dark:#0f5fd1;
    --ac-bg:#f3f6fb;
    --ac-card:#ffffff;
    --ac-line:#dbe5f0;
    --ac-line-strong:#c8d6e5;
    --ac-text:#142133;
    --ac-muted:#6b7a90;
    --ac-success:#16a34a;
    --ac-shadow:0 8px 22px rgba(15,23,42,.05);

    font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Arial,sans-serif;
    background:transparent;
    padding:0;
    border-radius:0;

    width:100%;
    min-width:0;
    max-width:100%;

    margin:0;
    color:var(--ac-text);
    box-sizing:border-box;
    overflow:visible;
  }

  /* top navigation (hidden) */
  .ac-so-topnav{
    display:none;
  }

  /* page header — full width */
  .ac-so-pagehead{
    display:flex;
    align-items:center;
    gap:12px;
    margin-bottom:14px;
    flex:0 0 auto;
    width:100%;
    max-width:100%;
    box-sizing:border-box;
  }

  .ac-so-pagehead-inline{
    justify-content:flex-start;
    flex-wrap:wrap;
  }

  .ac-so-pagehead h1{
    margin:0;
    font-size:24px;
    line-height:1.05;
    font-weight:900;
    color:#0f172a;
  }

  .ac-so-pagehead p{
    display:none;
  }

  /* optional polish for back button height */
  .ac-so-pagehead .ac-so-btn{
    height:40px;
  }

  /* cards — full width */
  .ac-so-card,
  .ac-so-last{
    background:var(--ac-card);
    border:1px solid var(--ac-line);
    box-shadow:var(--ac-shadow);
    backdrop-filter:none;
    -webkit-backdrop-filter:none;
  }

  .ac-so-card{
    border-radius:16px;
    padding:14px 16px;
    width:100%;
    max-width:100%;
    box-sizing:border-box;
  }

  .ac-so-main-card{
    padding-top:14px;
    margin-bottom:0;
    flex:0 0 auto;
    overflow:visible;
    width:100%;
    max-width:100%;
  }

  .ac-so-items-card{
    margin-top:0;
    min-height:0;
    display:flex;
    flex-direction:column;
    overflow:visible;
    width:100%;
    max-width:100%;
  }

  /* ===== compact form fields: label beside field ===== */
  .ac-so-field{
    display:grid;
    grid-template-columns:130px minmax(0,1fr);
    align-items:center;
    column-gap:12px;
    row-gap:4px;
  }

  .ac-so-field label{
    display:block;
    font-size:11px;
    font-weight:900;
    color:#596b84;
    margin:0;
    text-transform:uppercase;
    letter-spacing:.08em;
    line-height:1.2;
  }

  .ac-so-field > input,
  .ac-so-field > select,
  .ac-so-field > .ac-search-wrapper,
  .ac-so-field > .ac-search-input{
    grid-column:2;
  }

  .ac-so-field > .ac-hint,
  .ac-so-field > .ac-dd,
  .ac-so-field > .ac-line-preview{
    grid-column:2;
  }

  .ac-so-field input,
  .ac-so-field select,
  .ac-search-input{
    width:100%;
    height:40px;
    border:1px solid var(--ac-line-strong);
    border-radius:10px;
    padding:0 12px;
    font-size:14px;
    background:#fff;
    color:var(--ac-text);
    transition:border-color .16s ease, box-shadow .16s ease;
    box-sizing:border-box;
  }

  .ac-so-field input:hover,
  .ac-so-field select:hover,
  .ac-search-input:hover{
    border-color:#b0c4dc;
  }

  .ac-so-field input:focus,
  .ac-so-field select:focus,
  .ac-search-input:focus{
    outline:none;
    border-color:var(--ac-primary);
    box-shadow:0 0 0 3px rgba(22,119,255,.10);
    transform:none;
  }

  /* Two‑column row adjustments */
  .ac-so-row2{
    display:grid;
    grid-template-columns:minmax(0,1.45fr) minmax(0,0.95fr);
    gap:12px;
    align-items:start;
    width:100%;
  }

  .ac-so-row-single{
    grid-template-columns:1fr;   /* full width */
  }

  /* Ensure full width for the debtor wrapper and walk‑in input */
  #acSoDebtorWrapper,
  #ac_so_customer_suffix{
    width:100%;
  }

  .ac-hint{
    font-size:11px;
    color:#94a3b8;
    margin-top:2px;
    line-height:1.35;
  }

  /* items header — tightened (now unused) */
  .ac-so-card-hd{
    font-weight:900;
    font-size:16px;
    margin-bottom:6px;
    color:#0f172a;
    letter-spacing:-.01em;
    line-height:1.1;
  }

  .ac-so-items-title{
    display:flex;
    align-items:center;
    justify-content:space-between;
    min-height:auto;
    padding:0 2px 2px;
  }

  /* item entry row — full width */
  .ac-so-line-entry{
    display:grid;
    grid-template-columns:minmax(0,1fr) 120px 120px;
    gap:12px;
    align-items:end;
    margin-bottom:8px;
    padding:10px 12px;
    border-radius:12px;
    background:#f8fbff;
    border:1px solid #e2ebf5;
    flex:0 0 auto;
    width:100%;
    max-width:100%;
    box-sizing:border-box;
  }

  .ac-so-field.mini{
    grid-template-columns:46px minmax(0,1fr);
  }

  .ac-so-add-wrap{
    display:flex;
    align-items:stretch;
  }

  .ac-so-add-wrap .ac-so-btn{
    width:100%;
    height:40px;
  }

  /* ===== NEW: wrapper for item search to enable absolute dropdown ===== */
  .ac-item-search-wrap{
    position: relative;
    grid-column: 2;
  }

  /* ===== UPDATED .ac-dd: absolute within wrapper ===== */
  .ac-dd{
    position: absolute;
    top: calc(100% + 6px);
    left: 0;
    right: 0;
    margin-top: 0;
    border: 1px solid #dbe7f3;
    border-radius: 12px;
    background: #fff;
    max-height: 240px;
    overflow: auto;
    box-shadow: 0 8px 16px rgba(0,0,0,.06);
    z-index: 1000;
  }

  .ac-line-preview{
    margin-top:8px;
    border:1px dashed #c8dcef;
    background:#fcfdff;
    border-radius:12px;
    padding:8px 10px;
    font-size:12px;
    color:#334155;
    display:flex;
    gap:10px;
    justify-content:space-between;
    align-items:center;
    flex-wrap:wrap;
  }

  .ac-line-preview b{color:#0f172a;}

  /* ===== items table — full width + vertical scroll for ~5 rows ===== */
  .ac-so-table-wrap{
    margin-top:4px;
    border-radius:14px;
    overflow-x:auto;
    overflow-y:auto;
    border:1px solid var(--ac-line);
    background:#fff;
    box-shadow:none;
    flex:1 1 auto;
    min-height:0;
    width:100%;
    max-width:100%;
    min-width:0;
    max-height:245px;
  }

  .ac-so-table{
    width:100%;
    border-collapse:collapse;
    font-size:13px;
  }

  .ac-so-table thead{
    background:#eaf2fb;
    color:#16304f;
    position:sticky;
    top:0;
    z-index:1;
  }

  .ac-so-table th{
    padding:8px 10px;
    text-align:left;
    font-weight:800;
    font-size:11px;
    letter-spacing:.04em;
    text-transform:uppercase;
    border-bottom:1px solid var(--ac-line);
    white-space:nowrap;
  }

  .ac-so-table td{
    padding:8px 10px;
    border-top:1px solid #edf2f8;
    vertical-align:middle;
    background:#fff;
  }

  .ac-so-table tbody tr:hover td{
    background:#f8fbff;
  }

  .ac-so-table td.r,
  .ac-so-table th.r{
    text-align:right;
  }

  .ac-so-table td.empty{
    text-align:center;
    color:#94a3b8;
    padding:18px 12px;
  }

  .ac-x{
    height:32px;
    width:32px;
    border-radius:10px;
    border:1px solid var(--ac-line-strong);
    background:#fff;
    color:#0f172a;
    cursor:pointer;
    font-weight:800;
    font-size:15px;
    line-height:1;
    display:inline-flex;
    align-items:center;
    justify-content:center;
    transition:background .16s, border-color .16s;
  }

  .ac-x:hover{
    background:#fff1f2;
    border-color:#fecaca;
    color:#b91c1c;
  }

  .ac-x:active{transform:translateY(0);}

  /* dropdowns (keep original for customer dropdown) */
  .ac-dd .item{
    padding:9px 12px;
    border-top:1px solid #f1f5f9;
    cursor:pointer;
  }

  .ac-dd .item:first-child{border-top:none;}
  .ac-dd .item:hover{background:#eef7ff;}
  .ac-dd .item strong{display:block;color:#0f172a;font-size:13px;}
  .ac-dd .item small{display:block;color:#64748b;margin-top:2px;font-size:12px;}

  .ac-search-wrapper{
    position:relative;
    z-index:20;
  }

  .ac-search-dropdown{
    position:absolute;
    top:calc(100% + 6px);
    left:0;
    right:0;
    background:#fff;
    border:1px solid #dbe7f3;
    border-radius:14px;
    max-height:260px;
    overflow-y:auto;
    z-index:1000;
    display:none;
    box-shadow:0 10px 22px rgba(15,23,42,.08);
  }

  .ac-search-dropdown.active{display:block;}

  .ac-dropdown-item{
    padding:10px 12px;
    cursor:pointer;
    border-bottom:1px solid #eef4fb;
    transition:background .2s;
  }

  .ac-dropdown-item:last-child{border-bottom:none;}
  .ac-dropdown-item:hover,
  .ac-dropdown-item.active{background:#eef7ff;}
  .ac-dropdown-item strong{display:block;font-size:14px;color:#0f172a;margin-bottom:3px;}
  .ac-dropdown-item small{font-size:12px;color:#64748b;}

  .ac-dropdown-empty,
  .ac-dropdown-error{
    padding:14px;
    text-align:center;
    color:#94a3b8;
    font-size:12px;
  }

  .ac-dropdown-error{color:#c62828;}


  .ac-so-pagehead-copy{
    display:flex;
    flex-direction:column;
    gap:4px;
  }

  .ac-so-docno-row{
    font-size:13px;
    color:var(--ac-muted);
    font-weight:800;
  }

  .ac-so-status{
    margin-top:10px;
  }

  .ac-status{
    padding:10px 12px;
    border-radius:12px;
    font-weight:800;
    border:1px solid transparent;
    font-size:13px;
  }
  .ac-status-info{background:#eff6ff;border-color:#bfdbfe;color:#1e3a8a;}
  .ac-status-success{background:#ecfdf5;border-color:#bbf7d0;color:#166534;}
  .ac-status-error{background:#fff1f2;border-color:#fecaca;color:#991b1b;}
  .ac-status-warning{background:#fffbeb;border-color:#fde68a;color:#92400e;}

  /* buttons */
  .ac-so-btn{
    background:linear-gradient(180deg,var(--ac-primary) 0%, var(--ac-primary-dark) 100%);
    color:#fff;
    border:none;
    border-radius:10px;
    height:42px;
    padding:0 16px;
    font-weight:800;
    font-size:14px;
    cursor:pointer;
    text-decoration:none;
    display:inline-flex;
    align-items:center;
    justify-content:center;
    transition:filter .16s ease, transform .12s ease;
 �L����
C���������L׎
�?�D   box-shadow:none;
  }

  .ac-so-btn:hover{
    filter:brightness(1.04);
    transform:translateY(-1px);
  }

  .ac-so-btn:active{transform:translateY(0);}

  .ac-so-btn.ghost{
    background:#fff;
    color:var(--ac-primary);
    border:1px solid var(--ac-line-strong);
    box-shadow:none;
  }

  .ac-so-btn.small{
    height:40px;
    border-radius:8px;
    padding:0 14px;
  }

  .ac-so-btn:disabled{
    opacity:.65;
    cursor:not-allowed;
    transform:none !important;
    filter:none;
  }

  /* bottom total box */
  .ac-so-items-footer{
    display:flex;
    justify-content:flex-end;
    align-items:stretch;
    margin-top:10px;
    flex:0 0 auto;
    width:100%;
  }

  .ac-so-total-inline{
    width:280px;
    max-width:100%;
    background:linear-gradient(180deg,#1d8bff 0%, #1677ff 100%);
    color:#fff;
    border-radius:14px;
    padding:12px 14px;
    box-shadow:none;
  }

  .ac-so-total-inline .lbl{
    font-size:11px;
    font-weight:800;
    text-transform:uppercase;
    letter-spacing:.05em;
    color:rgba(255,255,255,.92);
    margin-bottom:6px;
  }

  .ac-so-total-inline .amt{
    font-size:32px;
    line-height:1;
    font-weight:1000;
    text-align:right;
    letter-spacing:-.04em;
  }

  /* normal save bar — full width */
  .ac-so-actions{
    margin-top:10px;
    display:flex;
    justify-content:flex-end;
    gap:10px;
    padding:0;
    width:100%;
    max-width:100%;
    box-sizing:border-box;
  }

  #ac_so_submit{
    min-width:160px;
  }

  /* hide old elements */
  .ac-so-side,
  .ac-so-note,
  .ac-so-topbar{
    display:none !important;
  }

  /* ===== NEW STYLES FOR PRICE HISTORY TABS ===== */
  .ac-line-click{
    cursor:pointer;
    display:block;
    width:100%;
  }

  .ac-line-row.is-open td{
    background:#f8fbff;
  }

  .ac-history-row td{
    padding:0 !important;
    background:#f7fbff;
    border-top:none;
    width:100%;
    max-width:100%;
  }

  /* ===== COMPACT HISTORY PANEL ===== */
  .ac-history-panel{
    padding:0;
    border-top:1px solid #dbe5f0;
    background:#f8fbff;
    width:100%;
    max-width:100%;
    min-width:0;
    overflow-x:auto;
    overflow-y:hidden;
  }

  .ac-history-box{
    border:1px solid #d9e6f2;
    border-radius:12px;
    background:#fff;
    width:100%;
    max-width:100%;
    min-width:0;
    overflow:hidden;
  }

  /* history table wrap with vertical scroll */
  .ac-history-table-wrap{
    width:100%;
    max-width:100%;
    min-width:0;
    overflow-x:auto;
    overflow-y:auto;
    max-height:230px;
  }

  .ac-history-table{
    width:max-content;
    min-width:980px;
    border-collapse:collapse;
    font-size:12px;
  }

  .ac-history-table th{
    background:#f6f9fc;
    color:#304760;
    font-size:10px;
    font-weight:800;
    text-transform:uppercase;
    letter-spacing:.04em;
    padding:7px 9px;
    border-bottom:1px solid #e3ebf4;
    white-space:nowrap;
    text-align:left;
  }

  .ac-history-table td{
    padding:7px 9px;
    border-top:1px solid #eef3f8;
    background:#fff;
    vertical-align:middle;
    white-space:nowrap;
  }

  .ac-history-table td.r,
  .ac-history-table th.r{
    text-align:right;
  }

  .ac-history-loading,
  .ac-history-error,
  .ac-history-empty{
    padding:12px;
    font-size:13px;
  }

  .ac-history-loading{ color:#35506f; }
  .ac-history-error{ color:#991b1b; }
  .ac-history-empty{ color:#64748b; }

  /* tabs inside history panel — compact */
  .ac-history-tabs-panel{
    padding:0;
    overflow:hidden;
  }

  .ac-history-tabs{
    display:flex;
    gap:0;
    border-bottom:1px solid #dbe5f0;
    background:#edf4fb;
    overflow-x:auto;
  }

  .ac-history-tab{
    appearance:none;
    border:none;
    background:transparent;
    color:#48627f;
    font-size:11px;
    font-weight:900;
    letter-spacing:.02em;
    padding:8px 12px;
    cursor:pointer;
    white-space:nowrap;
    border-bottom:2px solid transparent;
    line-height:1.1;
  }

  .ac-history-tab:hover{
    background:#e6f0fa;
  }

  .ac-history-tab.is-active{
    background:#fff;
    color:#163a63;
    border-bottom-color:#1677ff;
  }

  .ac-history-tabbody{
    display:none;
    padding:8px;
    background:#f8fbff;
  }

  .ac-history-tabbody.is-active{
    display:block;
  }

  /* item line metadata: code + UOM inline */
  .ac-line-meta{
    color:#94a3b8;
    font-size:12px;
    margin-top:2px;
    line-height:1.2;
  }

  .ac-line-uom{
    color:#64748b;
    font-weight:600;
  }

  /* ===== editable price input ===== */
  .ac-price-input{
    width:72px;
    max-width:100%;
    height:32px;
    border:1px solid var(--ac-line-strong);
    border-radius:8px;
    padding:0 8px;
    font-size:13px;
    text-align:right;
    background:#fff;
    color:var(--ac-text);
    box-sizing:border-box;
  }

  .ac-price-input:focus{
    outline:none;
    border-color:var(--ac-primary);
    box-shadow:0 0 0 3px rgba(22,119,255,.10);
  }

  /* ===== EXTRA NAME UPPERCASE ===== */
  #ac_so_customer_suffix{
    text-transform: uppercase;
  }

  /* ===== ADDITIONAL FIXES FOR LAYOUT STABILITY ===== */
  .ac-so-card,
  .ac-so-main-card,
  .ac-so-items-card,
  .ac-so-table-wrap,
  .ac-history-panel,
  .ac-history-box,
  .ac-history-table-wrap{
    width:100%;
    min-width:0;
    max-width:100%;
    box-sizing:border-box;
  }

  .ac-so-row2,
  .ac-so-line-entry,
  .ac-so-field,
  .ac-item-search-wrap,
  .ac-line-main-cell{
    min-width:0;
  }

  /* ===== TABLET ===== */
  @media (max-width: 980px){
    .ac-so-wrap{
      padding:12px;
      overflow-x:hidden;
      overflow-y:visible;
    }

    .ac-so-pagehead{
      flex-direction:column;
      align-items:flex-start;
    }

    .ac-so-row2,
    .ac-so-row-single{
      grid-template-columns:1fr;
    }

    .ac-so-field{
      grid-template-columns:110px minmax(0,1fr);
    }

    .ac-so-line-entry{
      grid-template-columns:1fr 1fr;
    }

    .ac-so-add-wrap{
      grid-column:1 / -1;
    }

    .ac-so-add-wrap .ac-so-btn{
      width:100%;
    }

    .ac-so-items-card{
      min-height:unset;
      overflow:visible;
    }

    .ac-so-table-wrap{
      max-height:none;
      flex:unset;
    }

    .ac-so-actions{
      justify-content:stretch;
    }

    .ac-so-actions .ac-so-btn{
      flex:1 1 auto;
    }

    .ac-so-items-footer{
      justify-content:stretch;
    }

    .ac-so-total-inline{
      width:100%;
      min-width:0;
    }

    .ac-so-total-inline .amt{
      font-size:30px;
    }
  }

  /* ===== MOBILE ===== */
  @media (max-width: 640px){
    .ac-so-wrap{
      padding:10px;
      border-radius:14px;
    }

    .ac-so-pagehead h1{
      font-size:22px;
    }

    .ac-so-card{
      padding:12px;
      border-radius:14px;
    }

    .ac-so-items-card{
      padding:12px;
    }

    .ac-so-field{
      grid-template-columns:1fr;
      align-items:stretch;
      row-gap:6px;
    }

    .ac-so-field > input,
    .ac-so-field > select,
    .ac-so-field > .ac-search-wrapper,
    .ac-so-field > .ac-search-input,
    .ac-so-field > .ac-hint,
    .ac-so-field > .ac-dd,
    .ac-so-field > .ac-line-preview{
      grid-column:auto;
    }

    .ac-so-field label{
      margin-bottom:0;
    }

    .ac-so-line-entry{
      grid-template-columns:1fr;
      gap:8px;
      padding:10px;
    }

    .ac-so-table{
      font-size:12px;
    }

    .ac-so-table th,
    .ac-so-table td{
      padding:9px 8px;
    }

    .ac-so-total-inline .amt{
      font-size:28px;
    }

    .ac-so-actions{
      margin-top:8px;
    }
  }
</style>

<script>
(function(){
  const wrap = document.querySelector('.ac-so-wrap');
  if(!wrap) return;

  const REST_NONCE     = wrap.dataset.restNonce;
  const EDIT_BASE      = wrap.dataset.editBase;
  const REST_JOB_POST  = wrap.dataset.restJobPost;
  const REST_JOB_BASE  = wrap.dataset.restJobBase;
  const REST_CS_UPDATE = wrap.dataset.restCsUpdate;

  const AJAX_URL      = wrap.dataset.ajaxUrl;
  const GETDOC_NONCE  = wrap.dataset.getDocNonce;

  const $ = (id) => document.getElementById(id);
  const state = { lines: [], docNo: '' };

  function escapeHtml(s){
    if(s===null || s===undefined) return '';
    return String(s).replace(/[&<>"']/g, c => ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#039;'}[c]));
  }

  function setStatus(msg, type='info'){
    const el = $('ac_so_status');
    if(!el) return;
    const icon = type==='success'?'✅':type==='error'?'❌':type==='warning'?'⚠️':'ℹ️';
    el.innerHTML = '<div class="ac-status ac-status-'+type+'">'+icon+' '+msg+'</div>';
  }

  function fmtMoney(n){
    const x = parseFloat(n);
    return isNaN(x) ? '0.00' : x.toFixed(2);
  }

  function recalc(){
    let total = 0;
    state.lines.forEach(l => {
      const computed = (parseFloat(l.qty)||0) * (parseFloat(l.unitPrice)||0);
      const use = (l.subTotal !== undefined && !isNaN(parseFloat(l.subTotal)))
        ? parseFloat(l.subTotal)
        : computed;
      total += use;
    });

    $('ac_so_final_total').textContent = fmtMoney(total);

    const payEl = $('ac_so_payment_amount');
    if (payEl && (!payEl.value || parseFloat(payEl.value) === 0)) {
      payEl.value = fmtMoney(total);
    }
  }

  function setLastChange(text){
    const el = $('ac_so_last_change');
    if(el) el.textContent = text || '—';
  }

  function renderLines(){
    const tbody = $('ac_so_lines');
    tbody.innerHTML = '';

    if(!state.lines.length){
      tbody.innerHTML = '<tr><td colspan="5" class="empty">No lines.</td></tr>';
      recalc();
      return;
    }

    state.lines.forEach((l, idx) => {
      const computed = (parseFloat(l.qty)||0) * (parseFloat(l.unitPrice)||0);
      const lineTotal = (l.subTotal !== undefined && !isNaN(parseFloat(l.subTotal)))
        ? parseFloat(l.subTotal)
        : computed;

      const tr = document.createElement('tr');
      tr.innerHTML = `
        <td>
          <b>${escapeHtml(l.itemName || l.itemCode)}</b>
          ${l.itemName && l.itemCode ? `<div style="color:#94a3b8;font-size:12px;margin-top:2px;">${escapeHtml(l.itemCode)}</div>` : ``}
          ${l.uom ? `<small style="color:#64748b;">(${escapeHtml(l.uom)})</small>` : ``}
        </td>
        <td class="r">${escapeHtml(l.qty)}</td>
        <td class="r">${fmtMoney(l.unitPrice)}</td>
        <td class="r">${fmtMoney(lineTotal)}</td>
        <td class="r"><button type="button" class="ac-x" data-idx="${idx}" title="Remove">✕</button></td>
      `;
      tbody.appendChild(tr);
    });

    recalc();
  }

  async function apiGet(url){
    const res = await fetch(url, {
      method:'GET',
      credentials:'same-origin',
      headers:{'Accept':'application/json'}
    });
    return await res.json();
  }

  async function apiPost(url, body){
    const res = await fetch(url, {
      method:'POST',
      credentials:'same-origin',
      headers:{
        'Content-Type':'application/json',
        'Accept':'application/json',
        'X-WP-Nonce': REST_NONCE
      },
      body: JSON.stringify(body)
    });
    return await res.json();
  }

  function buildFinalCustomerName(){
    const baseEl = $('ac_so_customer_base');
    const sufEl  = $('ac_so_customer_suffix');
    const hidEl  = $('ac_so_customer_final_name');

    const base = (baseEl ? baseEl.value : '').trim();
    const suf  = (sufEl ? sufEl.value : '').trim();
    const finalName = (base + ' ' + suf).trim();

    if (hidEl) hidEl.value = finalName;
    return finalName;
  }

  function makeClientRequestId(prefix='CSU'){
    const rnd = Math.random().toString(36).slice(2,10);
    const ts  = Date.now().toString(36);
    return `${prefix}-${ts}-${rnd}`;
  }

  async function pollJob(jobId){
    const max = 45;
    for(let i=0;i<max;i++){
      await new Promise(r => setTimeout(r, 2000));
      const r = await apiGet(REST_JOB_BASE + jobId);
      if(!r || !r.ok || !r.job) continue;

      const st = r.job.status;
      setStatus(`Job #${jobId}: ${escapeHtml(st)}`, (st==='SUCCESS'?'success':(st==='FAILED'||st==='FAILED_FINAL'?'error':'info')));

      if(st === 'SUCCESS'){
        setStatus(`Cash Sale updated: <b>${escapeHtml(state.docNo)}</b>`, 'success');
        return true;
      }
      if(st === 'FAILED' || st === 'FAILED_FINAL'){
        const err = r.job.error_message || (r.job.result && r.job.result.error) || 'Job failed';
        setStatus(escapeHtml(err), 'error');
        return false;
      }
    }
    setStatus('Job timed out. BridgeWorker might be offline.', 'warning');
    return false;
  }

  function attachSearch(inputEl, ddEl, fetchFn, onPick){
    let t = null;
    function hide(){ ddEl.style.display='none'; ddEl.innerHTML=''; }
    function show(){ ddEl.style.display='block'; }

    inputEl.addEventListener('input', () => {
      clearTimeout(t);
      const q = inputEl.value.trim();
      if(q.length < 2){ hide(); return; }

      t = setTimeout(async () => {
        ddEl.innerHTML = '<div class="item"><small>Searching...</small></div>';
        show();
        try{
          const items = await fetchFn(q);
          if(!items.length){
            ddEl.innerHTML = '<div class="item"><small>No result</small></div>';
            return;
          }
          ddEl.innerHTML = items.map((it, idx) => `
            <div class="item" data-idx="${idx}">
              <strong>${escapeHtml(it.name || it.code)}</strong>
              <small>${escapeHtml(it.code)}</small>
              <small>${escapeHtml(it.sub || '')}</small>
            </div>
          `).join('');

          ddEl.querySelectorAll('.item[data-idx]').forEach(node => {
            node.addEventListener('click', () => {
              const i = parseInt(node.dataset.idx, 10);
              onPick(items[i]);
              hide();
            });
          });
        }catch(e){
          ddEl.innerHTML = '<div class="item"><small>Failed to load</small></div>';
        }
      }, 200);
    });

    document.addEventListener('click', (e) => {
      if(!ddEl.contains(e.target) && e.target !== inputEl) hide();
    });
  }

  async function searchItemsLive(q){
    const cfg = window.AC_SUGGEST || {};
    const ajaxUrl = cfg.ajaxUrl || "";
    const nonce = cfg.nonce || "";
    if(!ajaxUrl || !nonce) return [];

    const fd = new FormData();
    fd.append("action", "ac_itemcode_suggest");
    fd.append("nonce", nonce);
    fd.append("term", q);

    const res = await fetch(ajaxUrl, {
      method: "POST",
      credentials: "same-origin",
      body: fd
    });

    const data = await res.json().catch(()=>null);
    const arr = (data && data.ok && Array.isArray(data.items)) ? data.items : [];

    return arr.map(it => {
      let priceVal = it.unitPrice !== undefined ? it.unitPrice : it.price;
      if (priceVal === null || priceVal === undefined) priceVal = 0;

      const name = (it.desc || it.name || it.description || it.code || '').trim();

      return {
        code: it.code || '',
        name: name,
        uom: it.uom || '',
        price: parseFloat(priceVal),
        sub: [it.desc2 || '', it.code ? ('Code: ' + it.code) : ''].filter(Boolean).join(' | ')
      };
    });
  }

  function updateLinePreview(){
    const pv = $('ac_so_line_preview');
    const code = ($('ac_so_item').value || '').trim();
    const name = ($('ac_so_item_display').value || '').trim();
    const uom  = ($('ac_so_uom').value || '').trim();
    const qty  = parseFloat(($('ac_so_qty').value || '0')) || 0;
    const price= parseFloat(($('ac_so_price_hidden').value || '0')) || 0;

    if(!code){
      pv.style.display = 'none';
      pv.innerHTML = '';
      return;
    }

    const shown = name || code;
    const total = qty * price;

    pv.style.display = 'flex';
    pv.innerHTML = `
      <div><b>�L׎�1�D���������L׎
�3����${escapeHtml(shown)}</b> ${uom ? `<span style="color:#64748b;">(${escapeHtml(uom)})</span>` : ``}</div>
      <div><span style="color:#64748b;">Unit:</span> <b>${fmtMoney(price)}</b> &nbsp; | &nbsp; <span style="color:#64748b;">Total:</span> <b>${fmtMoney(total)}</b></div>
    `;
  }

  (function initCustomerDropdown(){
    const wrapper = $('acSoDebtorWrapper');
    if (!wrapper) return;

    const AJAX_URL2 = wrapper.dataset.ajaxUrl;
    const NONCE = wrapper.dataset.nonce;

    const input = $('acSoDebtorInput');
    const dropdown = $('acSoDebtorDropdown');
    const hiddenCode = $('ac_so_customer');

    let items = [];
    let activeIndex = -1;
    let abortController = null;
    let searchTimeout = null;

    const show = () => dropdown.classList.add('active');
    const hide = () => { dropdown.classList.remove('active'); activeIndex = -1; };

    const renderEmpty = (msg) => {
      dropdown.innerHTML = `<div class="ac-dropdown-empty">${escapeHtml(msg)}</div>`;
      show();
    };

    const renderError = (msg) => {
      dropdown.innerHTML = `<div class="ac-dropdown-error">⚠️ ${escapeHtml(msg)}</div>`;
      show();
    };

    const renderResults = (arr) => {
      if (!arr || arr.length === 0) return renderEmpty('No customers found');
      dropdown.innerHTML = arr.map((it, idx) => {
        const name = it.name || it.debtorName || it.description || '';
        const code = it.code || it.debtorCode || it.id || '';
        const sa   = (it.salesAgent || it.sales_agent || it.sa || '').trim();
        return `
          <div class="ac-dropdown-item" data-index="${idx}">
            <strong>${escapeHtml(name)}</strong>
            <small>${escapeHtml(code)}${sa ? ' • SA: ' + escapeHtml(sa) : ''}</small>
          </div>
        `;
      }).join('');
      show();
      activeIndex = -1;
    };

    const selectItem = (idx) => {
      if (idx < 0 || idx >= items.length) return;
      const it = items[idx];

      const name = it.name || it.debtorName || it.description || '';
      const code = it.code || it.debtorCode || it.id || '';
      const salesAgent = (it.salesAgent || it.sales_agent || it.sa || '').trim();

      input.value = name;
      hiddenCode.value = code;
      hide();

      $('ac_so_customer_base').value = name || '';
      $('ac_so_customer_suffix').value = '';

      let suffix = '';
      const m = String(name || '').match(/^CASH SALES\s+(.+)$/i);
      if (m && m[1]) suffix = m[1].trim();

      if (m) $('ac_so_customer_base').value = 'CASH SALES';
      $('ac_so_customer_suffix').value = suffix;

      $('ac_so_sales_agent').value = salesAgent || '';
      $('ac_so_sales_agent_code').value = salesAgent || '';

      const finalName = buildFinalCustomerName();
      setLastChange('Customer: ' + (finalName || code || ''));
    };

    const performSearch = async (query) => {
      if (abortController) abortController.abort();
      abortController = new AbortController();

      const q = (query || '').trim();
      if (q.length < 1) { hide(); return; }

      renderEmpty('Searching...');
      try {
        const url = `${AJAX_URL2}?action=ac_cs_debtor_search&nonce=${encodeURIComponent(NONCE)}&q=${encodeURIComponent(q)}`;
        const response = await fetch(url, { signal: abortController.signal, credentials:'same-origin' });
        const data = await response.json().catch(()=>null);
        if (!data || !data.success) throw new Error('Search failed');
        items = (data.data && data.data.items) ? data.data.items : [];
        renderResults(items);
      } catch (err) {
        if (err.name === 'AbortError') return;
        renderError('Failed to load results');
      }
    };

    const debounceSearch = () => {
      clearTimeout(searchTimeout);
      searchTimeout = setTimeout(() => performSearch(input.value), 300);
    };

    input.addEventListener('input', () => {
      hiddenCode.value = '';
      $('ac_so_customer_base').value = '';
      $('ac_so_customer_suffix').value = '';
      $('ac_so_sales_agent').value = '';
      $('ac_so_sales_agent_code').value = '';
      debounceSearch();
    });

    input.addEventListener('focus', () => {
      if (input.value.trim() !== '') debounceSearch();
    });

    input.addEventListener('keydown', (e) => {
      if (!dropdown.classList.contains('active')) return;
      const nodes = dropdown.querySelectorAll('.ac-dropdown-item');
      if (!nodes.length) return;

      if (e.key === 'ArrowDown') {
        e.preventDefault();
        activeIndex = (activeIndex + 1) % nodes.length;
        nodes.forEach((n, i) => n.classList.toggle('active', i === activeIndex));
      } else if (e.key === 'ArrowUp') {
        e.preventDefault();
        activeIndex = activeIndex > 0 ? activeIndex - 1 : nodes.length - 1;
        nodes.forEach((n, i) => n.classList.toggle('active', i === activeIndex));
      } else if (e.key === 'Enter' && activeIndex >= 0) {
        e.preventDefault();
        selectItem(activeIndex);
      } else if (e.key === 'Escape') {
        hide();
      }
    });

    dropdown.addEventListener('click', (e) => {
      const node = e.target.closest('.ac-dropdown-item');
      if (!node) return;
      selectItem(parseInt(node.dataset.index, 10));
    });

    document.addEventListener('click', (e) => {
      if (!wrapper.contains(e.target)) hide();
    });
  })();

  function getQueryParam(name){
    const u = new URL(window.location.href);
    return u.searchParams.get(name) || '';
  }

  async function loadCashSale(docno){
    if(!docno){
      setStatus('Missing ?docno= in URL', 'error');
      $('ac_so_lines').innerHTML = '<tr><td colspan="5" class="empty">Missing docno</td></tr>';
      return;
    }

    state.docNo = docno;
    $('ac_cs_docno_label').textContent = docno;

    setStatus('Loading Cash Sale...', 'info');

    const url = `${AJAX_URL}?action=ac_cs_get_by_docno&nonce=${encodeURIComponent(GETDOC_NONCE)}&docno=${encodeURIComponent(docno)}`;
    const res = await fetch(url, { credentials:'same-origin' });
    const data = await res.json().catch(()=>null);

    if(!data || !data.success){
      const msg = (data && data.data && data.data.error) ? data.data.error : 'Failed to load cash sale';
      setStatus(msg, 'error');
      $('ac_so_lines').innerHTML = `<tr><td colspan="5" class="empty">${escapeHtml(msg)}</td></tr>`;
      return;
    }

    const h = data.data.header || {};
    const lines = Array.isArray(data.data.lines) ? data.data.lines : [];

    $('ac_so_date').value = h.docDate || '';

    $('acSoDebtorInput').value = h.debtorName || '';
    $('ac_so_customer').value = h.debtorCode || '';

    $('ac_so_customer_base').value = h.debtorName || '';
    $('ac_so_customer_suffix').value = '';
    const m = String(h.debtorName || '').match(/^CASH SALES\s+(.+)$/i);
    if (m && m[1]) {
      $('ac_so_customer_base').value = 'CASH SALES';
      $('ac_so_customer_suffix').value = m[1].trim();
    }
    buildFinalCustomerName();

    if (h.paymentMethod) $('ac_so_payment_method').value = h.paymentMethod;
    if (h.paymentAmount !== undefined && h.paymentAmount !== null) {
      $('ac_so_payment_amount').value = fmtMoney(h.paymentAmount);
    }

    if (h.salesAgent) {
      $('ac_so_sales_agent').value = h.salesAgent;
      $('ac_so_sales_agent_code').value = h.salesAgent;
    }

    state.lines = lines.map(l => ({
      itemCode: l.itemCode,
      itemName: l.itemName || l.itemCode,
      uom: l.uom || '',
      qty: parseFloat(l.qty) || 0,
      unitPrice: parseFloat(l.unitPrice) || 0,
      subTotal: parseFloat(l.subTotal) || 0
    }));

    renderLines();
    setLastChange('Loaded ' + docno);
    setStatus('Loaded ✅ Now you can edit and press Update.', 'success');
  }

  (function init(){
    attachSearch($('ac_so_item_name'), $('ac_so_item_dd'), searchItemsLive, (it) => {
      $('ac_so_item_name').value = it.name || it.code || '';
      $('ac_so_item').value = it.code || '';
      $('ac_so_item_display').value = it.name || it.code || '';
      $('ac_so_uom').value = it.uom || '';
      $('ac_so_price_hidden').value = (it.price || 0);
      setLastChange('Item: ' + ($('ac_so_item_display').value || it.code || ''));
      updateLinePreview();
    });

    $('ac_so_qty').addEventListener('input', updateLinePreview);

    $('ac_so_item_name').addEventListener('input', () => {
      $('ac_so_item').value = '';
      $('ac_so_item_display').value = '';
      $('ac_so_uom').value = '';
      $('ac_so_price_hidden').value = '';
      updateLinePreview();
    });

    $('ac_so_customer_suffix').addEventListener('input', () => {
      const finalName = buildFinalCustomerName();
      if(finalName) setLastChange('Customer: ' + finalName);
    });

    renderLines();
    updateLinePreview();

    const docno = getQueryParam('docno');
    loadCashSale(docno);
  })();

  $('ac_so_addline').addEventListener('click', () => {
    const itemCode = ($('ac_so_item').value || '').trim();
    const itemName = ($('ac_so_item_display').value || '').trim();
    const qty = parseFloat(($('ac_so_qty').value || '0')) || 0;
    const unitPrice = parseFloat(($('ac_so_price_hidden').value || '0'));
    const uom = ($('ac_so_uom').value || '').trim();

    if(!itemCode){ setStatus('Please select Item from dropdown (so price is loaded).', 'error'); return; }
    if(qty <= 0){ setStatus('Qty must be > 0.', 'error'); return; }
    if(isNaN(unitPrice)){ setStatus('Price not loaded.', 'error'); return; }

    const subTotal = qty * unitPrice;
    state.lines.push({ itemCode, itemName, qty, unitPrice, uom, subTotal });

    $('ac_so_item_name').value = '';
    $('ac_so_item').value = '';
    $('ac_so_item_display').value = '';
    $('ac_so_uom').value = '';
    $('ac_so_price_hidden').value = '';
    $('ac_so_qty').value = 1;

    setLastChange(`Added ${itemName || itemCode} x${qty}`);
    setStatus(`Added ✅ <b>${escapeHtml(itemName || itemCode)}</b> x${escapeHtml(qty)}`, 'success');

    renderLines();
    updateLinePreview();
  });

  $('ac_so_lines').addEventListener('click', (e) => {
    const btn = e.target.closest('button[data-idx]');
    if(!btn) return;
    const idx = parseInt(btn.dataset.idx, 10);
    if(isNaN(idx)) return;

    const removed = state.lines[idx];
    state.lines.splice(idx, 1);

    setLastChange(`Removed ${(removed && (removed.itemName || removed.itemCode)) ? (removed.itemName || removed.itemCode) : ''}`);
    setStatus('Removed 🗑️', 'warning');
    renderLines();
  });

  $('ac_so_submit').addEventListener('click', async () => {
    const customerCode = ($('ac_so_customer').value || '').trim();
    const docDate = ($('ac_so_date').value || '').trim();
    const paymentMethod = ($('ac_so_payment_method')?.value || 'CASH').trim();
    const paymentAmount = parseFloat(($('ac_so_payment_amount')?.value || '0')) || 0;

    if(!state.docNo){ setStatus('Missing docNo.', 'error'); return; }
    if(!customerCode){ setStatus('Please select Customer from dropdown.', 'error'); return; }
    if(!docDate){ setStatus('Please enter Date.', 'error'); return; }
    if(!state.lines.length){ setStatus('Please add at least 1 line item.', 'error'); return; }

    setStatus('Submitting update job...', 'info');

    const customerName = buildFinalCustomerName();
    const salesAgent = ($('ac_so_sales_agent_code')?.value || '').trim();

    const payload = {
      docNo: state.docNo,

      customerCode,
      customerName,
      salesAgent,

      debtorCode: customerCode,
      DebtorCode: customerCode,
      debtorName: customerName,
      DebtorName: customerName,
      SalesAgent: salesAgent,

      docDate,
      remark: '',
      paymentMethod,
      paymentAmount,

      lines: state.lines.map(l => ({
        itemCode: l.itemCode,
        qty: l.qty,
        unitPrice: l.unitPrice
      })),

      action: 'UPDATE'
    };

    try{
      const body = {
        client_request_id: makeClientRequestId('CSU'),
        source: 'wp-ui',
        payload
      };

      const r = await apiPost(REST_CS_UPDATE, body);

      if(!r || !r.ok){
        setStatus(escapeHtml((r && (r.message || r.error)) ? (r.message || r.error) : 'Submit failed.'), 'error');
        return;
      }

      const jobId = r.jobId || (r.job && r.job.id);
      if(!jobId){
        setStatus('Job created but jobId missing in response.', 'warning');
        setLastChange('Submitted to queue');
        return;
      }

      setStatus(`Update job queued: #${escapeHtml(jobId)}. Waiting BridgeWorker...`, 'info');
      setLastChange('Submitted update to queue');

      await pollJob(jobId);

    }catch(err){
      setStatus('Submit error: ' + escapeHtml(err.message || String(err)), 'error');
    }
  });

})();
</script>�L׎FP�

Youez - 2016 - github.com/yon3zu
LinuXploit