GCash Business (Management, Audit, and Accounting System) in Light and Dark Neumorphism UI

After
Before

GCash Management System

Powered by Gervic Programs

Managing a high-volume GCash business requires more than just a notebook and a pen. In this post, I’m unveiling a custom project designed to completely transform your financial operations.

If you are looking to move away from manual tracking and need a system that offers professional auditing, accounting, and security, you’re in the right place. We are powering this application with a Google Sheets backend and Google Apps Script, all wrapped in a modern UI for a premium experience.


Executive Summary

This system is a comprehensive, web-based financial management suite designed specifically for GCash, remittance, and lending businesses. It replaces manual logbooks with a digital ledger that automates calculations, enforces financial balancing, and generates professional accounting reports in real-time.

1. Core Features (What the System Does)

Centralized Transaction Processing:
Records day-to-day operations: Cash In, Cash Out, Load, and Bill Payments. It handles internal fund movements like Replenishments and Wallet-to-Wallet transfers, while also recording owner Investments and Withdrawals.

Smart Credit & Loan Management:
Tracks "Load/Cash In on account" via Customer Credits, automatically flagging overdue accounts (3+ days) with penalties. Includes distinct tracking for cash loans with support for partial payments.

Wallet Inventory System:
Tracks balances for specific GCash accounts individually. You will always know exactly how much funds are in which phone or account at any moment.

Automated Accounting:
Generates a Double-Entry General Journal and real-time Financial Statements (Income Statement and Balance Sheet). It also calculates Daily Profit Sharing based on individual capital contributions relative to the transaction date.

2. Key Benefits (Why It Helps You)

A. Financial Integrity & Accuracy: Our "Force Balance" logic ensures digital records match physical cash to the centavo. Zero-Sum Accounting prevents "floating" money.

B. Operational Efficiency: Auto-Calculation eliminates manual errors in service fees. Instant Search allows you to find any transaction by Name or Ref No without flipping through paper logs.

C. Loss Prevention & Debt Recovery: The dashboard highlights overdue credits in VIBRANT PINK. Penalty automation prevents revenue leakage from late payers.

D. Security & Control: Role-Based Access limits staff to specific wallets while Admins control sensitive settings. A full Audit Trail logs every action with a user timestamp.

System Setup & Implementation

Step 1, 2 & 3: Database Initialization

Open sheets.new and create 8 tabs: Users, Settings, Wallets, Capital, System, Transactions, Journal, ProfitShare. Enter the following headers in Row 1:

Sheet Name Column Headers (Row 1)
UsersUsername | Password | Role | Full Name | Profile Image
SettingsKey | Value
WalletsWallet Name | Owner | Status | Notes
CapitalOwner Name | Capital Amount | Share % | Status
SystemMetric | Value (GCash Balance, Cash on Hand, AR-Borrowings, AR-Customers)
TransactionsDate | ID | Type | Customer | Source | Ref No | Amount | Fee | Total | Paid | Change | User
JournalDate | Txn ID | Account Name | Debit | Credit | Description
ProfitShareDate | Owner | Capital Balance | Share % | Daily Net Income | Profit Allocation

Step 4 & 5: Scripts & Deployment

Navigate to Extensions > Apps Script. Create four files (Code.gs, index.html, css.html, js.html) and paste the corresponding codes below:

1. Code.gs

var SHEET_ID = 'YOUR_SHEET_ITEM_ID';

function doGet() {
  return HtmlService.createTemplateFromFile('index')
    .evaluate()
    .setTitle('GCASH SYSTEM')
    .addMetaTag('viewport', 'width=device-width, initial-scale=1')
    .setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);
}

function include(filename) {
  return HtmlService.createHtmlOutputFromFile(filename).getContent();
}

// ==========================================
// --- DATA FETCHING & DASHBOARD ---
// ==========================================

function getSystemBalance() {
  var ss = SpreadsheetApp.openById(SHEET_ID);
  var sheet = ss.getSheetByName('System');
  
  // Default values if sheet is broken/missing
  var def = { gcash: "₱0.00", cash: "₱0.00", ar_borrow: "₱0.00", ar_cust: "₱0.00" };
  if (!sheet) return def;

  var lastRow = sheet.getLastRow();
  if (lastRow < 2) return def;
  
  // Fetch values from System Sheet (Ledger Balances)
  var data = sheet.getRange(2, 2, Math.min(lastRow, 5), 1).getValues(); 

  // --- FIX: CALCULATE TRUE CREDITS (INCLUDING PENALTIES) ---
  // Instead of reading the static ledger value for Credits (ar_cust), 
  // we calculate the live value including time-based penalties.
  var creditList = getOutstandingCredits();
  var totalCreditsWithPenalty = 0;
  
  if (creditList && creditList.length > 0) {
    creditList.forEach(function(item) {
      totalCreditsWithPenalty += item.remainingBalance;
    });
  }

  return {
    gcash: parseFloat(data[0] ? data[0][0] : 0).toLocaleString('en-PH', {style: 'currency', currency: 'PHP'}),
    cash: parseFloat(data[1] ? data[1][0] : 0).toLocaleString('en-PH', {style: 'currency', currency: 'PHP'}),
    ar_borrow: parseFloat(data[2] ? data[2][0] : 0).toLocaleString('en-PH', {style: 'currency', currency: 'PHP'}),
    
    // OVERRIDE: Use the calculated total that includes penalties
    ar_cust: totalCreditsWithPenalty.toLocaleString('en-PH', {style: 'currency', currency: 'PHP'})
  };
}

function getCustomerList() {
  var ss = SpreadsheetApp.openById(SHEET_ID);
  var data = [];
  
  var sheet = ss.getSheetByName('Transactions');
  if (sheet && sheet.getLastRow() > 1) {
    var raw = sheet.getRange(2, 4, sheet.getLastRow() - 1, 1).getValues();
    raw.forEach(function(r) { if(r[0]) data.push(r[0]); });
  }

  var capSheet = ss.getSheetByName('Capital');
  if (capSheet && capSheet.getLastRow() > 1) {
    var capData = capSheet.getRange(2, 1, capSheet.getLastRow() - 1, 1).getValues();
    capData.forEach(function(r) { if(r[0]) data.push(r[0]); });
  }
  
  var unique = {};
  data.forEach(function(i) { unique[i] = true; });
  return Object.keys(unique).sort();
}

// ==========================================
// --- USER MANAGEMENT (PROFILE IMAGE FIX) ---
// ==========================================

function loginUser(username, password) {
  var ss = SpreadsheetApp.openById(SHEET_ID);
  var sheet = ss.getSheetByName('Users');
  var data = sheet.getDataRange().getValues();
  
  for (var i = 1; i < data.length; i++) {
    if (data[i][0] == username && data[i][1] == password) {
      
      // RECONSTRUCT IMAGE FROM CHUNKS (Col E onwards)
      var fullImage = "";
      // Loop from index 4 (Column E) to the end of the row
      for (var c = 4; c < data[i].length; c++) {
        fullImage += data[i][c];
      }
      
      return { 
        status: 'success', 
        role: data[i][2], 
        name: data[i][3],
        // If string is empty, return null
        image: (fullImage && fullImage.length > 50) ? fullImage : null 
      };
    }
  }
  return { status: 'error', message: 'Invalid credentials' };
}

function saveUserProfileImage(username, base64String) {
  var ss = SpreadsheetApp.openById(SHEET_ID);
  var sheet = ss.getSheetByName('Users');
  var data = sheet.getDataRange().getValues();
  
  for (var i = 1; i < data.length; i++) {
    if (data[i][0] == username) {
      
      // 1. Clear old image data (From Col E to end of row)
      var lastCol = sheet.getLastColumn();
      if (lastCol > 4) {
        sheet.getRange(i + 1, 5, 1, lastCol - 4).clearContent();
      }
      
      // 2. CHUNK THE STRING (50k chars per cell)
      var CHUNK_SIZE = 50000;
      var chunks = [];
      for (var k = 0; k < base64String.length; k += CHUNK_SIZE) {
        chunks.push(base64String.substring(k, k + CHUNK_SIZE));
      }
      
      // 3. SAVE CHUNKS (Starting at Column 5 / Column E)
      if (chunks.length > 0) {
        sheet.getRange(i + 1, 5, 1, chunks.length).setValues([chunks]);
      }
      
      return { status: 'success' };
    }
  }
  return { status: 'error', message: 'User not found' };
}

// ==========================================
// --- WALLET MANAGEMENT (ROLE BASED) ---
// ==========================================

// Helper: Get a map of Admin Usernames { 'admin1': true }
function getAdminUserMap(ss) {
  var sheet = ss.getSheetByName('Users');
  var data = sheet.getDataRange().getValues();
  var map = {};
  for (var i = 1; i < data.length; i++) {
    if (data[i][2] === 'Admin') {
      map[data[i][0]] = true;
    }
  }
  // Keep 'System' as legacy fallback
  map['System'] = true; 
  return map;
}

// 1. Fetch Wallets for Transaction Dropdowns (Source/Target)
function getUserWallets(username) {
  var ss = SpreadsheetApp.openById(SHEET_ID);
  var wSheet = ss.getSheetByName('Wallets');
  if (!wSheet) return [];

  var adminMap = getAdminUserMap(ss);
  var isRequesterAdmin = adminMap[username];

  var data = wSheet.getDataRange().getValues();
  var allowedWallets = [];

  for (var i = 1; i < data.length; i++) {
    var walletName = data[i][0];
    var owner = data[i][1];
    var status = data[i][2];

    if (status === 'Active') {
      // --- STRICTER LOGIC ---
      // 1. If User is Admin: Show ALL Active Wallets.
      // 2. If User is Staff: Show ONLY wallets owned by them.
      // (We removed the logic that automatically shared Admin wallets)
      
      if (isRequesterAdmin || owner === username) {
        allowedWallets.push(walletName);
      }
    }
  }
  return allowedWallets;
}

// 2. Fetch Wallets for "My Wallets" Dashboard (With Balances)
function getUserDetailedWallets(username) {
  var ss = SpreadsheetApp.openById(SHEET_ID);
  
  var adminMap = getAdminUserMap(ss);
  var isRequesterAdmin = adminMap[username];

  var wSheet = ss.getSheetByName('Wallets');
  var userWallets = {}; 
  
  if (wSheet) {
    var wData = wSheet.getDataRange().getValues();
    for (var i = 1; i < wData.length; i++) {
      var wName = wData[i][0];
      var wOwner = wData[i][1];
      var wStatus = wData[i][2];

      if (isRequesterAdmin || wOwner === username) {
        userWallets[wName] = { 
          status: wStatus, 
          balance: 0, 
          owner: wOwner,
          isShared: !!adminMap[wOwner]
        };
      }
    }
  }

  // Calculate Balances
  var tSheet = ss.getSheetByName('Transactions');
  if (tSheet) {
    var tData = tSheet.getDataRange().getValues();
    for (var i = 1; i < tData.length; i++) {
      var row = tData[i];
      var type = String(row[2]);
      var customer = String(row[3]); 
      var source = String(row[4]);   
      var amount = Number(row[6]) || 0;
      var fee = Number(row[7]) || 0;
      var total = Number(row[8]) || 0;
      var settlement = String(row[9]);

      // Logic for Source Wallet
      if (userWallets[source]) {
        if (type === 'Cash In' || type === 'Load') userWallets[source].balance -= amount;
        else if (type === 'Transfer') userWallets[source].balance -= (amount + fee);
        else if (type === 'Cash Out') userWallets[source].balance += total;
        else if (type === 'Add GCash') userWallets[source].balance += amount;
        else if (type === 'Import Wallet') userWallets[source].balance += amount;
        
        // --- THIS IS THE CRITICAL FIX ---
        // If Customer Pays Debt via GCash, the "Source" column holds the receiving wallet.
        // We MUST ADD the total to this wallet.
        else if ((type === 'Pay Credit' || type === 'Pay Borrowing') && settlement === 'GCash') {
           userWallets[source].balance += total;
        }
        // --------------------------------
      }

      // Logic for Destination Wallet (Transfers)
      if (type === 'Transfer' && userWallets[customer]) {
        userWallets[customer].balance += amount;
      }
    }
  }

  var result = [];
  for (var name in userWallets) {
    result.push({
      name: name,
      status: userWallets[name].status,
      balance: userWallets[name].balance,
      owner: userWallets[name].owner,
      isShared: userWallets[name].isShared
    });
  }
  
  result.sort(function(a, b) {
    if (a.isShared && !b.isShared) return -1;
    if (!a.isShared && b.isShared) return 1;
    return a.name.localeCompare(b.name);
  });
  
  return result;
}

// 3. Public Wallet Breakdown (Login Screen) - Shows ALL Active Wallets
function getWalletBreakdown() {
  var ss = SpreadsheetApp.openById(SHEET_ID);
  var txnSheet = ss.getSheetByName('Transactions');
  var walletSheet = ss.getSheetByName('Wallets'); 
  
  if (!txnSheet) return [];

  var activeWallets = {};

  // 1. Initialize Active Wallets
  if (walletSheet) {
    var wData = walletSheet.getDataRange().getValues();
    for (var i = 1; i < wData.length; i++) {
      if (wData[i][2] === 'Active') {
        activeWallets[wData[i][0]] = 0; 
      }
    }
  }

  // 2. Calculate Balances
  var data = txnSheet.getDataRange().getValues();
  for (var i = 1; i < data.length; i++) {
    var row = data[i];
    var type = String(row[2]);
    var customer = String(row[3]); 
    var source = String(row[4]);   
    var amount = Number(row[6]) || 0;
    var fee = Number(row[7]) || 0;
    var total = Number(row[8]) || 0;
    var settlement = String(row[9]);

    if (activeWallets.hasOwnProperty(source)) {
      if (['Cash In', 'Load'].includes(type)) activeWallets[source] -= amount;
      else if (type === 'Transfer') activeWallets[source] -= (amount + fee);
      else if (type === 'Cash Out') activeWallets[source] += total;
      else if (type === 'Add GCash') activeWallets[source] += amount;
      else if (type === 'Import Wallet') activeWallets[source] += amount;
      
      // --- ADD THIS LOGIC HERE TOO ---
      else if ((type === 'Pay Credit' || type === 'Pay Borrowing') && settlement === 'GCash') {
         activeWallets[source] += total;
      }
      // -------------------------------
    }
    
    if (type === 'Transfer' && activeWallets.hasOwnProperty(customer)) {
      activeWallets[customer] += amount;
    }
  }

  // 3. Convert to Array
  var result = [];
  for (var key in activeWallets) {
    result.push({ name: key, balance: activeWallets[key] });
  }
  
  result.sort(function(a, b) { return a.name.localeCompare(b.name); });
  
  return result;
}

// 4. Request New Wallet
function requestNewWallet(form) {
  var ss = SpreadsheetApp.openById(SHEET_ID);
  var sheet = ss.getSheetByName('Wallets');
  
  var data = sheet.getDataRange().getValues();
  for (var i = 1; i < data.length; i++) {
    if (data[i][0].toLowerCase() === form.walletName.toLowerCase()) {
      return { status: 'error', message: 'Wallet name already exists.' };
    }
  }

  sheet.appendRow([form.walletName, form.username, 'Pending', 'Created via App']);
  return { status: 'success', message: 'Wallet requested. Wait for Admin approval.' };
}

// 5. Get Wallet History (Ledger)
function getWalletHistory(walletName) {
  var ss = SpreadsheetApp.openById(SHEET_ID);
  var sheet = ss.getSheetByName('Transactions');
  var data = sheet.getDataRange().getValues();
  var history = [];
  
  var targetRaw = String(walletName);
  var targetClean = targetRaw.trim().toLowerCase();
  
  var rowsScanned = 0;
  var lastSourcesSeen = [];

  if (data.length > 1) {
    for (var i = data.length - 1; i >= 1; i--) {
      var row = data[i];
      rowsScanned++;
      
      var type = String(row[2] || "");
      var customerRaw = String(row[3] || ""); 
      var sourceRaw = String(row[4] || "");   
      
      var sourceClean = sourceRaw.trim().toLowerCase();
      var customerClean = customerRaw.trim().toLowerCase();

      if (rowsScanned <= 5) lastSourcesSeen.push("[" + sourceRaw + "]");

      var isSource = (sourceClean.indexOf(targetClean) > -1);
      var isTarget = (type === 'Transfer' && customerClean.indexOf(targetClean) > -1);
      
      if (isSource || isTarget) {
        var dateStr = "--";
        try { 
           if (row[0]) {
             // --- CHANGED HERE: Date Only (e.g. "Jul 11, 2025") ---
             dateStr = Utilities.formatDate(new Date(row[0]), "Asia/Manila", "MMM dd, yyyy"); 
           }
        } catch(e) {
           dateStr = "Invalid Date";
        }
        
        var effect = 0;
        var amount = Number(row[6]) || 0;
        var fee = Number(row[7]) || 0;
        var total = Number(row[8]) || 0;

        if (type === 'Cash In' || type === 'Load') effect = -amount;
        else if (type === 'Transfer' && isSource) effect = -(amount + fee);
        else if (type === 'Transfer' && isTarget) effect = amount;
        else if (type === 'Cash Out') effect = total;
        else if (type === 'Add GCash') effect = amount;

        history.push({
          date: dateStr,
          id: row[1],
          type: type,
          customer: (type === 'Transfer' && isSource) ? "To: " + customerRaw : customerRaw,
          amount: Math.abs(effect),
          fee: fee,
          total: effect,
          isCredit: (effect > 0)
        });
        
        if (history.length >= 50) break; 
      }
    }
  }
  
  if (history.length === 0) {
    return [{
      debug: true,
      msg: "Searching for: '" + targetRaw + "'",
      scanned: rowsScanned,
      recent: lastSourcesSeen.join(", ")
    }];
  }

  return history;
}

// 6. Get ALL Active Wallets (For Transfer Destinations)
function getAllActiveWallets() {
  var ss = SpreadsheetApp.openById(SHEET_ID);
  var sheet = ss.getSheetByName('Wallets');
  if (!sheet) return [];
  
  var data = sheet.getDataRange().getValues();
  var wallets = [];
  
  for (var i = 1; i < data.length; i++) {
    // Return all wallets that are 'Active', regardless of owner
    if (data[i][2] === 'Active') {
      wallets.push(data[i][0]);
    }
  }
  return wallets.sort();
}

// ==========================================
// --- ADMIN APPROVALS ---
// ==========================================

function getPendingWalletRequests(username) {
  if (!isAdmin(username)) return { status: 'error', message: 'Unauthorized' };

  var ss = SpreadsheetApp.openById(SHEET_ID);
  var sheet = ss.getSheetByName('Wallets');
  if (!sheet) return { status: 'success', data: [] };

  var data = sheet.getDataRange().getValues();
  var pending = [];

  for (var i = 1; i < data.length; i++) {
    if (data[i][2] === 'Pending') {
      pending.push({
        walletName: data[i][0],
        owner: data[i][1],
        notes: data[i][3]
      });
    }
  }
  return { status: 'success', data: pending };
}

function processWalletRequest(adminUser, walletName, action) {
  if (!isAdmin(adminUser)) return { status: 'error', message: 'Unauthorized' };

  var ss = SpreadsheetApp.openById(SHEET_ID);
  var sheet = ss.getSheetByName('Wallets');
  var data = sheet.getDataRange().getValues();
  var found = false;

  for (var i = 1; i < data.length; i++) {
    if (data[i][0] === walletName) {
      if (action === 'approve') {
        sheet.getRange(i + 1, 3).setValue('Active');
      } else if (action === 'reject') {
        sheet.deleteRow(i + 1);
      }
      found = true;
      break;
    }
  }
  if (found) return { status: 'success' };
  return { status: 'error', message: 'Wallet not found' };
}

// ==========================================
// --- BUSINESS LOGIC: WITHDRAWAL LIMITS ---
// ==========================================

function getOwnerLimit(ownerName) {
  var ss = SpreadsheetApp.openById(SHEET_ID);
  var capSheet = ss.getSheetByName('Capital');
  if (!capSheet) return { found: false, limit: 0, msg: "Capital tab missing" };
  
  var capData = capSheet.getDataRange().getValues();
  var ownerCapital = 0, ownerShare = 0, found = false;

  for (var i = 1; i < capData.length; i++) {
    if (capData[i][0] === ownerName && capData[i][3] === 'Active') {
      ownerCapital = Number(capData[i][1]);
      ownerShare = Number(capData[i][2]);
      found = true;
      break;
    }
  }
  if (!found) return { found: false, limit: 0, msg: "Owner not found" };

  var txnSheet = ss.getSheetByName('Transactions');
  var totalFees = 0;
  if (txnSheet && txnSheet.getLastRow() > 1) {
    var feeData = txnSheet.getRange(2, 8, txnSheet.getLastRow() - 1, 1).getValues();
    feeData.forEach(function(row) { totalFees += Number(row[0] || 0); });
  }
  
  return { found: true, limit: ownerCapital + (totalFees * ownerShare) };
}

// ==========================================
// --- VIEW: TRANSACTION LISTS ---
// ==========================================

function getTransactionsByType(type, limit) {
  var ss = SpreadsheetApp.openById(SHEET_ID);
  var sheet = ss.getSheetByName('Transactions');
  if (!sheet) return [];

  var data = sheet.getDataRange().getValues();
  var results = [];
  
  // Clean the requested type for comparison (e.g. "add gcash")
  var targetType = String(type).trim().toLowerCase();
  
  // Loop backwards (Newest first)
  for (var i = data.length - 1; i >= 1; i--) {
    var row = data[i];
    var rowType = String(row[2] || "").trim().toLowerCase();

    if (rowType === targetType) {
      var dateStr = "--";
      var rawDate = null;
      var rawVal = row[0];

      // 1. DATE PARSING (With Philippines Timezone)
      if (rawVal) {
        try { 
          // Format: "Jul 11, 2025" (Date Only)
          dateStr = Utilities.formatDate(new Date(rawVal), "Asia/Manila", "MMM dd, yyyy");
          rawDate = new Date(rawVal).getTime(); 
        } catch (e) {
          dateStr = "Invalid Date";
        }
      }
      if (!rawDate) rawDate = new Date().getTime();

      // 2. SMART DISPLAY NAME (Customer/Source Column)
      var displayStr = row[3]; // Default: Customer Name
      
      // For "Add GCash", show: "Fund Source → Target Wallet"
      if (targetType === 'add gcash') {
        var fundSource = row[3] || "Source";
        var targetWallet = row[4] || "Wallet";
        displayStr = fundSource + " → " + targetWallet;
      }
      // For "Transfer", show: "Source → Target"
      else if (targetType === 'transfer') {
        var sourceW = row[4] || "Wallet A";
        var targetW = row[3] || "Wallet B";
        displayStr = sourceW + " → " + targetW;
      }

      results.push({
        date: dateStr,
        rawDate: rawDate,
        id: row[1],
        customer: displayStr, // We inject the smarter name here
        source: row[4],   
        ref: row[5],      
        amount: Number(row[6]),
        fee: Number(row[7]),
        total: Number(row[8]),
        type: row[2], // Return original casing
        settlement: row[9], 
        amountPaid: row[10] 
      });

      if (limit > 0 && results.length >= limit) break;
    }
  }
  return results;
}

// ==========================================
// --- VIEW: HISTORY & AUDIT ---
// ==========================================

function getHistoryForID(originalId) {
  try {
    var ss = SpreadsheetApp.openById(SHEET_ID);
    var sheet = ss.getSheetByName('Transactions');
    if (!sheet) return [{debug: true, msg: "Transactions tab not found"}]; 

    var data = sheet.getDataRange().getValues();
    if (data.length < 2) return [{debug: true, msg: "Database is empty."}];

    var headers = data[0]; 
    var colId = -1, colType = -1, colRef = -1, colAmount = -1, colFee = -1, colTotal = -1, colDate = 0;

    for (var h = 0; h < headers.length; h++) {
      var header = String(headers[h]).toLowerCase().trim();
      if (colId === -1 && (header === "transaction id" || header === "id" || header === "txn id")) colId = h;
      else if (colType === -1 && (header === "type" || header === "transaction type")) colType = h;
      else if (colRef === -1 && (header === "ref no" || header === "reference" || header === "ref")) colRef = h;
      else if (colAmount === -1 && (header === "amount" || header === "principal")) colAmount = h;
      else if (colTotal === -1 && (header === "total" || header === "total due")) colTotal = h;
      else if (colFee === -1 && (header === "fee" || header === "charge")) colFee = h;
      else if (colDate === 0 && (header === "date")) colDate = h;
    }

    if (colId === -1) colId = 1; 
    if (colType === -1) colType = 2;
    if (colRef === -1) colRef = 5;
    if (colAmount === -1) colAmount = 6; 
    if (colFee === -1) colFee = 7;       
    if (colTotal === -1) colTotal = 8;   

    var history = [];
    var targetId = String(originalId).trim();
    var originalFound = false;
    var originalTimestamp = 0;
    var originalFee = 0;

    for (var i = 1; i < data.length; i++) {
      var row = data[i];
      var rowId = String(row[colId] || "").trim();
      var rowType = String(row[colType] || "").trim();
      var rowRef = String(row[colRef] || "").trim();
      
      var rowPrincipal = Number(row[colAmount]) || 0; 
      var rowFee = Number(row[colFee]) || 0;
      var rowTotal = Number(row[colTotal]) || 0;

      var rawDate = row[colDate];
      var txnTime = new Date().getTime(); 
      if (rawDate instanceof Date) txnTime = rawDate.getTime();
      else if (typeof rawDate === 'string' && rawDate !== "") {
        var parsed = new Date(rawDate);
        if (!isNaN(parsed.getTime())) txnTime = parsed.getTime();
      }

      if (rowId === targetId) {
        originalFound = true;
        originalTimestamp = txnTime;
        originalFee = rowFee;
        
        history.push({
          timestamp: txnTime, 
          priority: 1, 
          activity: "Principal Amount", 
          amount: rowPrincipal,
          type: 'debit'
        });

        if (rowFee > 0) {
          history.push({
            timestamp: txnTime, 
            priority: 2, 
            activity: "Service Charge",
            amount: rowFee,
            type: 'debit'
          });
        }
      }

      if ((rowType === 'Pay Credit' || rowType === 'Pay Borrowing') && rowRef === targetId) {
        history.push({
          timestamp: txnTime,
          priority: 3, 
          activity: "Payment",
          amount: rowTotal,
          type: 'credit'
        });
      }
    }

    if (!originalFound && history.length === 0) {
      return [{
        debug: true, 
        msg: "Transaction ID not found.",
        target: targetId,
        colIdName: "Index " + colId,
        seen: "N/A"
      }];
    }

    if (originalFound && originalFee > 0) {
      var now = new Date().getTime();
      var penaltyThreshold = originalTimestamp + (3 * 24 * 60 * 60 * 1000); 

      if (now > penaltyThreshold) {
        history.push({
          timestamp: penaltyThreshold + 1000, 
          priority: 4, 
          activity: "Late Penalty",
          amount: originalFee,
          type: 'debit'
        });
      }
    }

    history.sort(function(a, b) { 
      if (a.timestamp !== b.timestamp) return a.timestamp - b.timestamp;
      return a.priority - b.priority;
    });
    
    var calcBal = 0;
    return history.map(function(h) {
      if (h.type === 'debit') calcBal += h.amount; else calcBal -= h.amount;
      var d = new Date(h.timestamp);
      var dateStr = Utilities.formatDate(d, Session.getScriptTimeZone(), "MMM dd, yyyy");
      return {
        dateStr: dateStr,
        activity: h.activity,
        amount: h.amount,
        type: h.type,
        balance: calcBal
      };
    });
  } catch (e) {
    return [{ debug: true, msg: "SCRIPT ERROR: " + e.toString() }];
  }
}

// ==========================================
// --- CREDIT & BORROWING LISTS ---
// ==========================================

function getOutstandingCredits() {
  return getOutstandingDebts('Cash In', 'Load', 'Pay Credit');
}

function getOutstandingBorrowings() {
  return getOutstandingDebts('Borrow', null, 'Pay Borrowing');
}

function getOutstandingDebts(type1, type2, payType) {
  var ss = SpreadsheetApp.openById(SHEET_ID);
  var sheet = ss.getSheetByName('Transactions');
  if (!sheet) return [];

  var data = sheet.getDataRange().getValues();
  var debts = {}; 
  var paymentsMap = {}; 
  
  for (var i = 1; i < data.length; i++) {
    var row = data[i];
    var id = row[1];
    var type = row[2];
    var settlement = row[9]; 
    var refNo = row[5];
    var total = Number(row[8]);
    
    var isCredit = ((type === type1 || type === type2) && settlement === 'On Account');
    var isBorrow = (type === 'Borrow' && type1 === 'Borrow'); 

    if (isCredit || isBorrow) {
      debts[id] = {
        date: row[0],
        id: id,
        customer: row[3], 
        type: type,
        originalFee: Number(row[7]),
        originalTotal: total
      };
    }
    
    if (type === payType) {
      if (!paymentsMap[refNo]) paymentsMap[refNo] = 0;
      paymentsMap[refNo] += total;
    }
  }
  
  var result = [];
  var today = new Date();
  
  for (var key in debts) {
    var txn = debts[key];
    var txnDate = new Date(txn.date);
    
    var penalty = 0;
    var isOverdue = false;
    var diffDays = 0;

    if (txn.type !== 'Borrow') {
      var diffTime = Math.abs(today - txnDate);
      diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24)); 
      isOverdue = diffDays > 3;
      penalty = isOverdue ? txn.originalFee : 0; 
    }
    
    var grossAmount = txn.originalTotal + penalty;
    var totalPaid = paymentsMap[txn.id] || 0;
    var remainingBalance = grossAmount - totalPaid;
    
    if (remainingBalance > 0.01) {
      result.push({
        id: txn.id,
        date: Utilities.formatDate(txnDate, Session.getScriptTimeZone(), "MMM dd, yyyy"),
        customer: txn.customer,
        type: txn.type,
        
        // NEW: This is the AR amount (505.00)
        originalTotal: txn.originalTotal, 
        
        // This is what they owe NOW with penalty (510.00)
        grossAmount: grossAmount, 
        
        paidSoFar: totalPaid,
        remainingBalance: remainingBalance,
        daysOpen: diffDays,
        isOverdue: isOverdue,
        penalty: penalty
      });
    }
  }

  result.sort(function(a, b) {
    if (a.id < b.id) return 1;
    if (a.id > b.id) return -1;
    return 0;
  });

  return result;
}

// ==========================================
// --- SAVING & UPDATING ---
// ==========================================

function saveTransaction(form) {
  var ss = SpreadsheetApp.openById(SHEET_ID);
  var sheet = ss.getSheetByName('Transactions');
  
  // 1. Generate ID
  var prefix = "TXN";
  if (form.type === 'Cash In') prefix = "CI";
  else if (form.type === 'Cash Out') prefix = "CO";
  else if (form.type === 'Load') prefix = "LD";
  else if (form.type === 'Invest') prefix = "IV";
  else if (form.type === 'Borrow') prefix = "BR";
  else if (form.type === 'Withdraw') prefix = "WD";
  else if (form.type === 'Add GCash') prefix = "RP";
  else if (form.type === 'Transfer') prefix = "TF";
  else if (form.type === 'Pay Credit') prefix = "PY"; 
  else if (form.type === 'Pay Borrowing') prefix = "PB";

  var dateSequence = Utilities.formatDate(new Date(), Session.getScriptTimeZone(), "yyyyMMdd-HHmmss");
  var id = prefix + "-" + dateSequence;
  
  // 2. Save to Transactions Sheet
  sheet.appendRow([
    form.date, id, form.type, form.customer, form.source,
    form.refNo, form.amount, form.fee, form.total,
    form.settlement, form.amountPaid, form.tip, form.change,
    form.processedBy, new Date()
  ]);
  
  // Formatting
  var lastRow = sheet.getLastRow();
  var pesoFormat = '₱ #,##0.00'; 
  sheet.getRange(lastRow, 7, 1, 3).setNumberFormat(pesoFormat);
  sheet.getRange(lastRow, 11, 1, 3).setNumberFormat(pesoFormat);
  
  // 3. Update Balances
  updateBalancesV2(form.type, form.amount, form.fee, form.total, form.settlement);
  
  if (form.type === 'Withdraw') {
     var check = getOwnerLimit(form.customer);
     if (check.found) updateOwnerCapital(form.customer, form.amount, check.limit);
  }
  else if (form.type === 'Invest') {
     increaseOwnerCapital(form.customer, form.amount);
  }

  // --- CRITICAL FIX: Add the generated ID to the form object ---
  form.id = id; 

  // 4. Generate Journal Entries
  generateJournalEntries(form);

  return { status: 'success', id: id };
}

function updateOwnerCapital(ownerName, withdrawAmount, maxLimit) {
  var ss = SpreadsheetApp.openById(SHEET_ID);
  var sheet = ss.getSheetByName('Capital');
  var data = sheet.getDataRange().getValues();
  var amount = Number(withdrawAmount);

  for (var i = 1; i < data.length; i++) {
    if (data[i][0] === ownerName) {
      var currentCapital = Number(data[i][1]);
      var newCapital = currentCapital - amount;
      if (newCapital < 0) newCapital = 0;
      sheet.getRange(i + 1, 2).setValue(newCapital);
      
      if (Math.abs(amount - maxLimit) < 1.00) {
        sheet.getRange(i + 1, 4).setValue("Inactive");
      }
      break;
    }
  }
}

function increaseOwnerCapital(ownerName, amount) {
  var ss = SpreadsheetApp.openById(SHEET_ID);
  var sheet = ss.getSheetByName('Capital');
  var data = sheet.getDataRange().getValues();
  var val = Number(amount);
  var found = false;

  for (var i = 1; i < data.length; i++) {
    if (data[i][0] === ownerName) {
      var currentCap = Number(data[i][1]);
      sheet.getRange(i + 1, 2).setValue(currentCap + val);
      if(data[i][3] !== 'Active') sheet.getRange(i+1, 4).setValue("Active");
      found = true;
      break;
    }
  }
  
  if (!found) sheet.appendRow([ownerName, val, 0, "Active"]);
}

function updateBalancesV2(type, amount, fee, total, settlement) {
  var ss = SpreadsheetApp.openById(SHEET_ID);
  var sheet = ss.getSheetByName('System');
  
  var gcashCell = sheet.getRange(2, 2);
  var cashCell = sheet.getRange(3, 2);
  var arBorrowCell = sheet.getRange(4, 2);
  var arCustCell = sheet.getRange(5, 2);
  
  var currentGCash = Number(gcashCell.getValue());
  var currentCash = Number(cashCell.getValue());
  var currentARBorrow = Number(arBorrowCell.getValue());
  var currentARCust = Number(arCustCell.getValue());
  
  var valPrincipal = Number(amount);
  var valFee = Number(fee);
  var valTotal = Number(total);

  if (type === 'Cash In' || type === 'Load') {
    currentGCash -= valPrincipal; 
    if (settlement === 'On Account') currentARCust += valTotal;
    else currentCash += valTotal;
  }
  else if (type === 'Cash Out') {
    currentGCash += valTotal;
    currentCash -= valPrincipal;
  }
  else if (type === 'Invest') {
    currentCash += valPrincipal;
  }
  else if (type === 'Borrow') {
    currentCash -= valPrincipal;
    currentARBorrow += valPrincipal;
  }
  else if (type === 'Withdraw') {
    currentCash -= valPrincipal;
  }
  else if (type === 'Add GCash') {
    currentGCash += valPrincipal;
    currentCash -= (valPrincipal + valFee); 
  }
  else if (type === 'Transfer') {
    currentGCash -= valFee; 
  }
  else if (type === 'Pay Credit') {
    // --- UPDATED ---
    if (settlement === 'GCash') currentGCash += valTotal;
    else currentCash += valTotal; 
    
    currentARCust -= valPrincipal; 
  }
  else if (type === 'Pay Borrowing') {
    // --- UPDATED ---
    if (settlement === 'GCash') currentGCash += valTotal;
    else currentCash += valTotal;

    currentARBorrow -= valPrincipal; 
  }

  gcashCell.setValue(currentGCash).setNumberFormat('₱ #,##0.00');
  cashCell.setValue(currentCash).setNumberFormat('₱ #,##0.00');
  arBorrowCell.setValue(currentARBorrow).setNumberFormat('₱ #,##0.00');
  arCustCell.setValue(currentARCust).setNumberFormat('₱ #,##0.00');
}

// ==========================================
// --- USER MANAGEMENT ---
// ==========================================

function registerUser(form) {
  var ss = SpreadsheetApp.openById(SHEET_ID);
  var sheet = ss.getSheetByName('Users');
  var data = sheet.getDataRange().getValues();
  for (var i = 1; i < data.length; i++) {
    if (data[i][0].toString().toLowerCase() === form.username.toLowerCase()) {
      return { status: 'error', message: 'Username already taken' };
    }
  }
  sheet.appendRow([form.username, form.password, 'Staff', form.name]);
  return { status: 'success' };
}

function changePassword(username, newPassword) {
  var ss = SpreadsheetApp.openById(SHEET_ID);
  var sheet = ss.getSheetByName('Users');
  var data = sheet.getDataRange().getValues();
  
  for (var i = 1; i < data.length; i++) {
    if (data[i][0] === username) {
      sheet.getRange(i + 1, 2).setValue(newPassword); 
      return { status: 'success' };
    }
  }
  return { status: 'error', message: 'User not found' };
}

function isAdmin(username) {
  var ss = SpreadsheetApp.openById(SHEET_ID);
  var sheet = ss.getSheetByName('Users');
  var data = sheet.getDataRange().getValues();
  for (var i = 1; i < data.length; i++) {
    if (data[i][0] == username) {
      return data[i][2] === 'Admin';
    }
  }
  return false;
}

// ==========================================
// --- ADMIN: EDIT & DELETE & RECALCULATE ---
// ==========================================

function deleteTransaction(id, username) {
  var ss = SpreadsheetApp.openById(SHEET_ID);
  if (!isAdmin(username)) return { status: 'error', message: 'Unauthorized. Admins only.' };

  var sheet = ss.getSheetByName('Transactions');
  var data = sheet.getDataRange().getValues();
  var rowIndex = -1;

  for (var i = 1; i < data.length; i++) {
    if (data[i][1] === id) {
      rowIndex = i + 1; 
      var row = data[i];
      reverseBalances(row[2], Number(row[6]), Number(row[7]), Number(row[8]), row[9]);
      sheet.deleteRow(rowIndex);
      return { status: 'success' };
    }
  }

  // NEW: Remove from Journal
      generateJournalEntries({ id: id, action: 'delete' });
      
  return { status: 'error', message: 'Transaction ID not found.' };
}

function editTransaction(form) {
  var ss = SpreadsheetApp.openById(SHEET_ID);
  if (!isAdmin(form.username)) return { status: 'error', message: 'Unauthorized. Admins only.' };

  var sheet = ss.getSheetByName('Transactions');
  var data = sheet.getDataRange().getValues();
  
  for (var i = 1; i < data.length; i++) {
    if (data[i][1] === form.id) { 
      var oldRow = data[i];
      reverseBalances(oldRow[2], Number(oldRow[6]), Number(oldRow[7]), Number(oldRow[8]), oldRow[9]);
      updateBalancesV2(form.type, form.amount, form.fee, form.total, form.settlement);
      
      var range = sheet.getRange(i + 1, 1, 1, 14); 
      range.setValues([[
        form.date, form.id, form.type, form.customer, form.source,
        form.refNo, form.amount, form.fee, form.total,
        form.settlement, form.amountPaid, form.tip, form.change,
        form.processedBy 
      ]]);
      
      sheet.getRange(i + 1, 7, 1, 3).setNumberFormat('₱ #,##0.00');
      return { status: 'success', id: form.id };
    }
  }

  // NEW: Update Journal (Deletes old, adds new)
  generateJournalEntries(form);

  return { status: 'error', message: 'ID not found for editing' };
}

function reverseBalances(type, amount, fee, total, settlement) {
  var ss = SpreadsheetApp.openById(SHEET_ID);
  var sheet = ss.getSheetByName('System');
  
  var gcashCell = sheet.getRange(2, 2);
  var cashCell = sheet.getRange(3, 2);
  var arBorrowCell = sheet.getRange(4, 2);
  var arCustCell = sheet.getRange(5, 2);
  
  var currentGCash = Number(gcashCell.getValue());
  var currentCash = Number(cashCell.getValue());
  var currentARBorrow = Number(arBorrowCell.getValue());
  var currentARCust = Number(arCustCell.getValue());
  
  if (type === 'Cash In' || type === 'Load') {
    currentGCash += amount; 
    if (settlement === 'On Account') currentARCust -= total; 
    else currentCash -= total; 
  }
  else if (type === 'Cash Out') {
    currentGCash -= total;
    currentCash += amount;
  }
  else if (type === 'Invest') {
    currentCash -= amount;
  }
  else if (type === 'Borrow') {
    currentCash += amount;
    currentARBorrow -= amount;
  }
  else if (type === 'Withdraw') {
    currentCash += amount;
  }
  else if (type === 'Add GCash') {
    currentGCash -= amount;
    currentCash += (amount + fee);
  }
  else if (type === 'Transfer') {
    currentGCash += fee; 
  }
  else if (type === 'Pay Credit') {
    // --- UPDATED ---
    if (settlement === 'GCash') currentGCash -= total;
    else currentCash -= total;
    currentARCust += amount;
  }
  else if (type === 'Pay Borrowing') {
    // --- UPDATED ---
    if (settlement === 'GCash') currentGCash -= total;
    else currentCash -= total;
    currentARBorrow += amount;
  }

  gcashCell.setValue(currentGCash);
  cashCell.setValue(currentCash);
  arBorrowCell.setValue(currentARBorrow);
  arCustCell.setValue(currentARCust);
}

function recalculateAllBalances() {
  var ss = SpreadsheetApp.openById(SHEET_ID);
  var txnSheet = ss.getSheetByName('Transactions');
  var sysSheet = ss.getSheetByName('System');
  var capSheet = ss.getSheetByName('Capital');
  var journalSheet = ss.getSheetByName('Journal');

  if (!txnSheet || !sysSheet || !capSheet) return { status: 'error', message: 'Missing Sheets' };

  var data = txnSheet.getDataRange().getValues();
  var calcGCash = 0, calcCash = 0, calcARBorrow = 0, calcARCust = 0;
  var ownerCapitals = {};
  var allJournalEntries = [];

  for (var i = 1; i < data.length; i++) {
    var row = data[i];
    var date = row[0];
    var id = row[1];
    var type = String(row[2]);      
    var customer = String(row[3]); 
    var source = String(row[4]); 
    var amount = Number(row[6]) || 0; 
    var fee = Number(row[7]) || 0;    
    var total = Number(row[8]) || 0;  
    var settlement = String(row[9]);  
    
    // 1. SYSTEM BALANCES
    if (type === 'Cash In' || type === 'Load') {
      calcGCash -= amount; 
      if (settlement === 'On Account') calcARCust += total; else calcCash += total;
    }
    else if (type === 'Cash Out') { calcGCash += total; calcCash -= amount; }
    else if (type === 'Invest') { calcCash += amount; if (!ownerCapitals[customer]) ownerCapitals[customer] = 0; ownerCapitals[customer] += amount; }
    else if (type === 'Borrow') { calcCash -= amount; calcARBorrow += amount; }
    else if (type === 'Withdraw') { calcCash -= amount; if (!ownerCapitals[customer]) ownerCapitals[customer] = 0; ownerCapitals[customer] -= amount; }
    else if (type === 'Add GCash') { calcGCash += amount; calcCash -= (amount + fee); }
    else if (type === 'Import Wallet') { calcGCash += amount; }
    else if (type === 'Transfer') { calcGCash -= fee; }
    
    // --- UPDATED SECTIONS ---
    else if (type === 'Pay Credit') { 
        if (settlement === 'GCash') calcGCash += total; 
        else calcCash += total; 
        calcARCust -= amount; 
    }
    else if (type === 'Pay Borrowing') { 
        if (settlement === 'GCash') calcGCash += total;
        else calcCash += total; 
        calcARBorrow -= amount; 
    }

    // 2. JOURNAL REBUILD
    if (journalSheet) {
        var desc = type + " - " + customer;
        
        if (['Cash In', 'Load'].includes(type)) {
            if (settlement === 'On Account') {
                allJournalEntries.push([date, id, 'A/R - Customers', total, 0, desc]);
                allJournalEntries.push([date, id, 'GCash Wallet', 0, amount, desc]);
                allJournalEntries.push([date, id, 'Service Revenue', 0, fee, desc]);
            } else {
                allJournalEntries.push([date, id, 'Cash on Hand', total, 0, desc]);
                allJournalEntries.push([date, id, 'GCash Wallet', 0, amount, desc]);
                allJournalEntries.push([date, id, 'Service Revenue', 0, fee, desc]);
            }
        }
        else if (type === 'Cash Out') {
            allJournalEntries.push([date, id, 'GCash Wallet', total, 0, desc]);
            allJournalEntries.push([date, id, 'Cash on Hand', 0, amount, desc]);
            allJournalEntries.push([date, id, 'Service Revenue', 0, fee, desc]);
        }
        else if (type === 'Add GCash') {
            allJournalEntries.push([date, id, 'GCash Wallet', amount, 0, desc]);
            allJournalEntries.push([date, id, 'Expenses (Txn Costs)', fee, 0, desc]);
            allJournalEntries.push([date, id, 'Cash on Hand', 0, total, desc]);
        }
        else if (type === 'Transfer') {
            allJournalEntries.push([date, id, 'GCash Wallet', amount, 0, "Transfer To: " + customer]);
            if (fee > 0) allJournalEntries.push([date, id, 'Expenses (Txn Costs)', fee, 0, desc]);
            allJournalEntries.push([date, id, 'GCash Wallet', 0, amount + fee, "Transfer From: " + source]);
        }
        // --- UPDATED JOURNAL FOR GCASH PAYMENTS ---
        else if (type === 'Pay Credit' || type === 'Pay Borrowing') {
            var arAccount = (type === 'Pay Borrowing') ? 'A/R - Loans' : 'A/R - Customers';
            var penalty = total - amount; 
            var assetAccount = (settlement === 'GCash') ? 'GCash Wallet' : 'Cash on Hand';
            
            allJournalEntries.push([date, id, assetAccount, total, 0, desc]);
            allJournalEntries.push([date, id, arAccount, 0, amount, desc]);
            if (penalty > 0.01) allJournalEntries.push([date, id, 'Other Income (Penalties)', 0, penalty, desc]);
        }
        else if (type === 'Borrow') {
            allJournalEntries.push([date, id, 'A/R - Loans', amount, 0, desc]);
            allJournalEntries.push([date, id, 'Cash on Hand', 0, amount, desc]);
        }
        else if (['Withdraw', 'Invest'].includes(type)) {
            var isInvest = (type === 'Invest');
            allJournalEntries.push([date, id, isInvest?'Cash on Hand':'Capital', amount, 0, desc]);
            allJournalEntries.push([date, id, isInvest?'Capital':'Cash on Hand', 0, amount, desc]);
        }
    }
  }

  // SAVE SYSTEM
  sysSheet.getRange(2, 2).setValue(calcGCash).setNumberFormat('₱ #,##0.00');
  sysSheet.getRange(3, 2).setValue(calcCash).setNumberFormat('₱ #,##0.00');
  sysSheet.getRange(4, 2).setValue(calcARBorrow).setNumberFormat('₱ #,##0.00');
  sysSheet.getRange(5, 2).setValue(calcARCust).setNumberFormat('₱ #,##0.00');

  // SAVE CAPITAL
  var capData = capSheet.getDataRange().getValues();
  var handledOwners = {};
  for (var c = 1; c < capData.length; c++) {
    var ownerName = capData[c][0];
    var computedBal = ownerCapitals[ownerName] || 0;
    capSheet.getRange(c + 1, 2).setValue(computedBal).setNumberFormat('₱ #,##0.00');
    capSheet.getRange(c + 1, 4).setValue(computedBal > 0.01 ? "Active" : "Inactive");
    handledOwners[ownerName] = true;
  }
  for (var owner in ownerCapitals) {
    if (!handledOwners[owner] && Math.abs(ownerCapitals[owner]) > 0.01) {
       capSheet.appendRow([owner, ownerCapitals[owner], 0, "Active"]);
       capSheet.getRange(capSheet.getLastRow(), 2).setNumberFormat('₱ #,##0.00');
    }
  }

  // SAVE JOURNAL
  if (journalSheet && allJournalEntries.length > 0) {
    if (journalSheet.getLastRow() > 1) {
      journalSheet.getRange(2, 1, journalSheet.getLastRow() - 1, 6).clearContent();
    }
    journalSheet.getRange(2, 1, allJournalEntries.length, 6).setValues(allJournalEntries);
    journalSheet.getRange(2, 4, allJournalEntries.length, 2).setNumberFormat('₱ #,##0.00');
  }

  generateProfitShareLogs(); 

  return { 
    status: 'success', 
    message: 'System, Journal & Profit Shares Recalculated',
    newBalances: { gcash: calcGCash, cash: calcCash, ar_borrow: calcARBorrow, ar_cust: calcARCust }
  };
}

// ==========================================
// --- ACCOUNTING & REPORTS MODULE ---
// ==========================================

// Updated to accept date parameter
function getAccountingData(selectedDateStr) {
  var ss = SpreadsheetApp.openById(SHEET_ID);
  var txnSheet = ss.getSheetByName('Transactions');
  var sysSheet = ss.getSheetByName('System');
  var capSheet = ss.getSheetByName('Capital');
  var walletSheet = ss.getSheetByName('Wallets');
  
  if (!txnSheet || !sysSheet || !capSheet) return { error: "Required sheets are missing." };

  var data = txnSheet.getDataRange().getValues();
  
  // --- DATE SETUP ---
  var targetDate;
  if (selectedDateStr) {
    targetDate = new Date(selectedDateStr);
  } else {
    targetDate = new Date();
  }

  var startOfDay = new Date(targetDate.getFullYear(), targetDate.getMonth(), targetDate.getDate()).getTime();
  var endOfDay = new Date(targetDate.getFullYear(), targetDate.getMonth(), targetDate.getDate() + 1).getTime();
  var currentYear = targetDate.getFullYear();
  
  var stats = {
    dailyIncome: 0, cashSales: 0, creditSales: 0,
    cashFlowIn: 0, cashFlowOut: 0, gcashFlowIn: 0, gcashFlowOut: 0
  };
  var sci = { revenue: { serviceFees: 0, otherIncome: 0 }, expenses: { transactionCosts: 0 } };

  var walletBalances = {};
  if (walletSheet) {
    var wData = walletSheet.getDataRange().getValues();
    for (var w = 1; w < wData.length; w++) {
      if (wData[w][2] === 'Active') walletBalances[wData[w][0]] = 0;
    }
  }

  // --- NEW: FETCH DAILY SHARES FROM LOGS ---
  var dailyShareBreakdown = [];
  var psSheet = ss.getSheetByName('ProfitShare');
  
  if (psSheet && selectedDateStr) {
     var psData = psSheet.getDataRange().getValues();
     for (var p = 1; p < psData.length; p++) {
        var rowDate = psData[p][0];
        if (rowDate instanceof Date) {
            var rowDateStr = Utilities.formatDate(rowDate, Session.getScriptTimeZone(), "yyyy-MM-dd");
            if (rowDateStr === selectedDateStr) {
                dailyShareBreakdown.push({
                    owner: psData[p][1],
                    share: Number(psData[p][5])
                });
            }
        }
     }
  }

  // --- PROCESS TRANSACTIONS ---
  for (var i = 1; i < data.length; i++) {
    var row = data[i];
    if (!row[0]) continue;

    var rDate = new Date(row[0]);
    var rTime = rDate.getTime();
    
    var type = String(row[2]);
    var customer = String(row[3]); 
    var source = String(row[4]);   
    var amount = Number(row[6]) || 0;
    var fee = Number(row[7]) || 0;
    var total = Number(row[8]) || 0;
    var settlement = String(row[9]);
    
    var isSelectedDay = (rTime >= startOfDay && rTime < endOfDay);
    var isYearToDate = (rDate.getFullYear() === currentYear && rTime < endOfDay);
    var isPastOrPresent = (rTime < endOfDay); 

    // 1. REVENUE (SCI - YTD)
    if (isYearToDate) {
        if (['Cash In', 'Cash Out', 'Load'].includes(type)) sci.revenue.serviceFees += fee;
        if (type === 'Pay Credit' || type === 'Pay Borrowing') {
            var penalty = total - amount;
            if (penalty > 0.01) sci.revenue.otherIncome += penalty;
        }
        if (['Transfer', 'Add GCash'].includes(type)) sci.expenses.transactionCosts += fee;
    }

    // 2. DAILY STATS
    if (isSelectedDay) {
      if (['Cash In', 'Cash Out', 'Load'].includes(type)) stats.dailyIncome += fee;
      if (type === 'Pay Credit' || type === 'Pay Borrowing') {
          var penalty = total - amount;
          if (penalty > 0.01) stats.dailyIncome += penalty;
      }

      if (type === 'Cash In' || type === 'Load') {
        if (settlement === 'On Account') stats.creditSales += total; else stats.cashSales += total;
      }
      if ((['Cash In', 'Load'].includes(type) && settlement !== 'On Account') || ['Pay Credit', 'Pay Borrowing'].includes(type) || type === 'Invest') {
          stats.cashFlowIn += total;
      }
      if (['Cash Out', 'Withdraw', 'Borrow'].includes(type)) stats.cashFlowOut += amount;
      if (type === 'Add GCash') stats.cashFlowOut += (amount + fee);

      if (['Cash Out', 'Add GCash'].includes(type)) stats.gcashFlowIn += (type==='Cash Out'?total:amount);
      if (['Cash In', 'Load'].includes(type)) stats.gcashFlowOut += amount;
      if (type === 'Transfer') stats.gcashFlowOut += (amount + fee);
    }

    // 3. BALANCE SHEET
    if (isPastOrPresent) {
        if (walletBalances.hasOwnProperty(source)) {
          if (['Cash In', 'Load'].includes(type)) walletBalances[source] -= amount;
          else if (type === 'Transfer') walletBalances[source] -= (amount + fee);
          else if (type === 'Cash Out') walletBalances[source] += total;
          else if (type === 'Add GCash') walletBalances[source] += amount;
        }
        if (type === 'Transfer' && walletBalances.hasOwnProperty(customer)) {
          walletBalances[customer] += amount;
        }
    }
  }

  var sysData = sysSheet.getRange(2, 2, 4, 1).getValues(); 
  
  var walletBreakdown = [];
  var calculatedGCashTotal = 0;
  for (var wName in walletBalances) {
    if (Math.abs(walletBalances[wName]) > 0.001) {
      walletBreakdown.push({ name: wName, amount: walletBalances[wName] });
      calculatedGCashTotal += walletBalances[wName];
    }
  }

  var assets = {
    gcashWallet: calculatedGCashTotal, 
    cashOnHand: Number(sysData[1][0]) || 0,
    receivablesBorrow: Number(sysData[2][0]) || 0,
    receivablesCust: Number(sysData[3][0]) || 0,
    wallets: walletBreakdown
  };
  var totalAssets = assets.cashOnHand + assets.gcashWallet + assets.receivablesCust + assets.receivablesBorrow;

  // --- EQUITY CORRECTION ---
  var capData = capSheet.getDataRange().getValues();
  var ownerList = [];
  var totalPrincipal = 0;
  
  for (var i = 1; i < capData.length; i++) {
    var ownerName = capData[i][0];
    
    // *** FIX: Ignore 'Retained Earnings' from the Owner List ***
    // This ensures it doesn't show up as "Cap: Retained Earnings"
    if (ownerName === 'Retained Earnings') continue; 

    if (capData[i][3] === 'Active' || Number(capData[i][1]) > 0) {
        ownerList.push({ name: ownerName, amount: Number(capData[i][1]) });
        totalPrincipal += Number(capData[i][1]);
    }
  }
  
  // By not adding the "Retained Earnings" row to totalPrincipal, 
  // the subtraction (Total Assets - Principal) effectively pushes 
  // that 13k amount into the Calculated Retained Earnings result.
  var retainedEarnings = totalAssets - totalPrincipal;

  return {
    today: stats, sci: sci,
    dailyShares: dailyShareBreakdown,
    bs: { assets: totalAssets, details: assets, equity: { total: totalAssets, principal: totalPrincipal, retained: retainedEarnings, owners: ownerList } }
  };
}

// ==========================================
// --- TRIAL BALANCE MODULE ---
// ==========================================

function getTrialBalanceReport() {
  var ss = SpreadsheetApp.openById(SHEET_ID);
  var txnSheet = ss.getSheetByName('Transactions');
  var capSheet = ss.getSheetByName('Capital');
  
  if (!txnSheet) return { error: "Transaction sheet missing" };

  var data = txnSheet.getDataRange().getValues();
  
  // 1. INITIALIZE ACCOUNTS (0.00)
  var accounts = {
    'Cash on Hand': 0,
    'GCash Wallet': 0,
    'A/R - Customers': 0,
    'A/R - Loans': 0,
    'Capital': 0,
    'Service Revenue': 0,
    'Other Income (Penalties)': 0,
    'Expenses (Txn Costs)': 0
  };

  // 2. CALCULATE CAPITAL (Credit Balance)
  // We fetch this directly from Capital sheet initial entries + Invest transactions
  // Actually, let's calculate purely from transactions + initial capital to be safe.
  var capData = capSheet.getDataRange().getValues();
  for (var i = 1; i < capData.length; i++) {
     // Initial Capital injection that might not be in transactions
     // (Assuming Capital Sheet Col B is the running balance, we actually need the initial inputs)
     // For simplicity in this system, let's treat the 'System' sheet start point as 0 and rely on 'Invest' transactions,
     // BUT usually, Capital sheet has manual entries. Let's use the Capital Sheet total as the baseline Credit.
     accounts['Capital'] += Number(capData[i][1]); 
     // Note: This is a hybrid approach. Ideally, Capital entries should be in Transactions as 'Invest'.
     // If your 'Invest' transactions update the Capital sheet, we might double count if we sum both.
     // DECISION: In your system, 'Invest' updates Capital Sheet. So let's just use Capital Sheet total.
  }

  // 3. PROCESS TRANSACTIONS (The Double Entry Logic)
  for (var i = 1; i < data.length; i++) {
    var row = data[i];
    if (!row[0]) continue;

    var type = String(row[2]);
    var amount = Number(row[6]) || 0; // Principal
    var fee = Number(row[7]) || 0;
    var total = Number(row[8]) || 0;  // Total
    var settlement = String(row[9]);

    // --- MAPPING LOGIC ---

    if (type === 'Cash In' || type === 'Load') {
       if (settlement === 'On Account') {
         // Debit A/R, Credit GCash, Credit Revenue
         accounts['A/R - Customers'] += total;
         accounts['GCash Wallet'] -= amount;
         accounts['Service Revenue'] += fee;
       } else {
         // Debit Cash, Credit GCash, Credit Revenue
         accounts['Cash on Hand'] += total;
         accounts['GCash Wallet'] -= amount;
         accounts['Service Revenue'] += fee;
       }
    }
    else if (type === 'Cash Out') {
       // Debit GCash (Total), Credit Cash (Principal), Credit Revenue (Fee)
       // *Correction based on your business logic:
       // Customer sends GCash (Principal + Fee). You give Cash (Principal). Fee is income.
       accounts['GCash Wallet'] += total;
       accounts['Cash on Hand'] -= amount;
       accounts['Service Revenue'] += fee;
    }
    else if (type === 'Add GCash') {
       // Debit GCash (Amount), Debit Expense (Fee), Credit Cash (Total)
       accounts['GCash Wallet'] += amount;
       accounts['Expenses (Txn Costs)'] += fee;
       accounts['Cash on Hand'] -= (amount + fee);
    }
    else if (type === 'Transfer') {
       // Debit Expense (Fee), Credit GCash (Fee)
       // Principal moves wallet-to-wallet (Net 0 for GCash total)
       accounts['Expenses (Txn Costs)'] += fee;
       accounts['GCash Wallet'] -= fee;
    }
    else if (type === 'Withdraw') {
       // Debit Capital, Credit Cash
       accounts['Capital'] -= amount;
       accounts['Cash on Hand'] -= amount;
    }
    else if (type === 'Invest') {
       // Debit Cash, Credit Capital
       // NOTE: Since we pre-loaded Capital from sheet, avoid double counting if sheet updates dynamically.
       // However, for Trial Balance flow, we show the movement.
       // For this specific report, let's assume Capital Sheet is the Source of Truth and ignore 'Invest' here
       // OR handle it if Capital Sheet is static. 
       // SAFE BET: Use Transaction movement for Cash, but don't add to Capital Account if pre-loaded.
       accounts['Cash on Hand'] += amount;
       // We already summed Capital from sheet, so we assume that sheet is updated.
    }
    else if (type === 'Borrow') {
       // Debit A/R Loans, Credit Cash
       accounts['A/R - Loans'] += amount;
       accounts['Cash on Hand'] -= amount;
    }
    else if (type === 'Pay Credit') {
       // Debit Cash (Total Paid), Credit A/R (Principal), Credit Other Income (Excess)
       var principalPaid = amount; 
       var penalty = total - amount; // Cash Basis penalty
       
       accounts['Cash on Hand'] += total;
       accounts['A/R - Customers'] -= principalPaid;
       if (penalty > 0) accounts['Other Income (Penalties)'] += penalty;
    }
    else if (type === 'Pay Borrowing') {
       // Debit Cash, Credit A/R Loans, Credit Other Income
       var principalPaid = amount; 
       var penalty = total - amount;

       accounts['Cash on Hand'] += total;
       accounts['A/R - Loans'] -= principalPaid;
       if (penalty > 0) accounts['Other Income (Penalties)'] += penalty;
    }
  }

  // 4. FORMAT FOR FRONTEND (Separating Debits and Credits)
  var trialBalance = [];
  var grandDebit = 0;
  var grandCredit = 0;

  // Helper to push row
  function addRow(name, val, isDebitNormal) {
    if (Math.abs(val) < 0.01) return; // Hide zero accounts
    
    // Determine if it falls on Debit or Credit side based on value sign and normal balance
    // Assets/Expenses = Debit Normal (+)
    // Liab/Equity/Revenue = Credit Normal (-) in math terms, but we display absolute.
    
    var dr = 0; 
    var cr = 0;

    if (isDebitNormal) {
        if (val >= 0) dr = val; else cr = Math.abs(val);
    } else {
        if (val >= 0) cr = val; else dr = Math.abs(val); // Capital/Revenue are usually positive numbers in our object
    }

    trialBalance.push({ name: name, dr: dr, cr: cr });
    grandDebit += dr;
    grandCredit += cr;
  }

  addRow('Cash on Hand', accounts['Cash on Hand'], true);
  addRow('GCash Wallet', accounts['GCash Wallet'], true);
  addRow('A/R - Customers', accounts['A/R - Customers'], true);
  addRow('A/R - Loans', accounts['A/R - Loans'], true);
  
  addRow('Capital', accounts['Capital'], false);
  addRow('Service Revenue', accounts['Service Revenue'], false);
  addRow('Other Income (Penalties)', accounts['Other Income (Penalties)'], false);
  
  addRow('Expenses (Txn Costs)', accounts['Expenses (Txn Costs)'], true);

  return {
    rows: trialBalance,
    total: { dr: grandDebit, cr: grandCredit },
    balanced: Math.abs(grandDebit - grandCredit) < 1.00 // Allow small floating point margin
  };
}

// ==========================================
// --- JOURNAL ENTRY ENGINE (DOUBLE ENTRY) ---
// ==========================================

function generateJournalEntries(txn) {
  var ss = SpreadsheetApp.openById(SHEET_ID);
  var sheet = ss.getSheetByName('Journal');
  if (!sheet) return; 

  var data = sheet.getDataRange().getValues();
  for (var i = data.length - 1; i >= 1; i--) {
    if (data[i][1] === txn.id) sheet.deleteRow(i + 1);
  }

  if (txn.action === 'delete') return;

  var entries = [];
  var date = txn.date;
  var id = txn.id;
  var desc = txn.type + " - " + txn.customer;
  var amount = Number(txn.amount) || 0; 
  var fee = Number(txn.fee) || 0;
  var total = Number(txn.total) || 0; 
  
  // A. CASH IN / LOAD
  if (txn.type === 'Cash In' || txn.type === 'Load') {
    if (txn.settlement === 'On Account') {
       entries.push([date, id, 'A/R - Customers', total, 0, desc]);
       entries.push([date, id, 'GCash Wallet', 0, amount, desc]);
       entries.push([date, id, 'Service Revenue', 0, fee, desc]);
    } else {
       entries.push([date, id, 'Cash on Hand', total, 0, desc]);
       entries.push([date, id, 'GCash Wallet', 0, amount, desc]);
       entries.push([date, id, 'Service Revenue', 0, fee, desc]);
    }
  }
  // B. CASH OUT
  else if (txn.type === 'Cash Out') {
     entries.push([date, id, 'GCash Wallet', total, 0, desc]);
     entries.push([date, id, 'Cash on Hand', 0, amount, desc]);
     entries.push([date, id, 'Service Revenue', 0, fee, desc]);
  }
  // C. ADD GCASH
  else if (txn.type === 'Add GCash') {
     entries.push([date, id, 'GCash Wallet', amount, 0, desc]);
     entries.push([date, id, 'Expenses (Txn Costs)', fee, 0, desc]);
     entries.push([date, id, 'Cash on Hand', 0, total, desc]);
  }
  // D. TRANSFER
  else if (txn.type === 'Transfer') {
     entries.push([date, id, 'GCash Wallet', amount, 0, "Transfer To: " + txn.customer]);
     if (fee > 0) entries.push([date, id, 'Expenses (Txn Costs)', fee, 0, desc]);
     entries.push([date, id, 'GCash Wallet', 0, amount + fee, "Transfer From: " + txn.source]);
  }
  // E. PAY CREDIT / PAY BORROWING
  else if (txn.type === 'Pay Credit' || txn.type === 'Pay Borrowing') {
     var arAccount = (txn.type === 'Pay Borrowing') ? 'A/R - Loans' : 'A/R - Customers';
     
     var cashReceived = total; 
     var principalSettled = amount; 
     var penaltyIncome = total - amount;
     
     // --- UPDATED LOGIC ---
     var assetAccount = (txn.settlement === 'GCash') ? 'GCash Wallet' : 'Cash on Hand';
     
     // Dr. Asset
     entries.push([date, id, assetAccount, cashReceived, 0, desc]);
     // ---------------------

     // Cr. AR
     entries.push([date, id, arAccount, 0, principalSettled, desc]);
     
     // Cr. Income
     if (penaltyIncome > 0.01) {
       entries.push([date, id, 'Other Income (Penalties)', 0, penaltyIncome, desc]);
     }
  }
  // F. BORROW
  else if (txn.type === 'Borrow') {
     entries.push([date, id, 'A/R - Loans', amount, 0, desc]);
     entries.push([date, id, 'Cash on Hand', 0, amount, desc]);
  }
  // G. WITHDRAW / INVEST
  else if (txn.type === 'Withdraw') {
     entries.push([date, id, 'Capital', amount, 0, desc]);
     entries.push([date, id, 'Cash on Hand', 0, amount, desc]);
  }
  else if (txn.type === 'Invest') {
     entries.push([date, id, 'Cash on Hand', amount, 0, desc]);
     entries.push([date, id, 'Capital', 0, amount, desc]);
  }

  if (entries.length > 0) {
    var lastRow = sheet.getLastRow();
    sheet.getRange(lastRow + 1, 1, entries.length, 6).setValues(entries);
    sheet.getRange(lastRow + 1, 4, entries.length, 2).setNumberFormat('₱ #,##0.00');
  }
}

// Helper: Get Journal Data for Frontend
function getJournalLogs() {
  var ss = SpreadsheetApp.openById(SHEET_ID);
  var sheet = ss.getSheetByName('Journal');
  if(!sheet || sheet.getLastRow() < 2) return [];
  
  var data = sheet.getDataRange().getValues(); 
  var logs = [];
  
  // Loop backwards to show newest first
  for (var i = data.length - 1; i >= 1; i--) {
     var row = data[i];
     
     // 1. SAFE DATE PARSING
     var dateVal = row[0];
     var dateStr = "";
     
     if (dateVal instanceof Date) {
       // Format: "Jul 16, 2025"
       dateStr = Utilities.formatDate(dateVal, "Asia/Manila", "MMM dd, yyyy");
     } else {
       // Fallback if cell is text
       dateStr = String(dateVal); 
     }

     logs.push({
       date: dateStr,
       id: row[1],
       account: row[2],
       debit: Number(row[3]),
       credit: Number(row[4]),
       desc: row[5] 
     });
     if (logs.length >= 100) break;
  }
  return logs;
}

// ==========================================
// --- PROFIT SHARING ENGINE (TIME-WEIGHTED) ---
// ==========================================

function generateProfitShareLogs() {
  var ss = SpreadsheetApp.openById(SHEET_ID);
  var txnSheet = ss.getSheetByName('Transactions');
  var psSheet = ss.getSheetByName('ProfitShare');
  
  if (!txnSheet || !psSheet) return;

  var data = txnSheet.getDataRange().getValues();
  
  // 1. ORGANIZE DATA BY DATE
  // Map: "YYYY-MM-DD" -> { income: 0, capitalMoves: [{owner, amount}] }
  var dailyMap = {};
  var minDate = new Date().getTime(); // Track start of time
  var maxDate = new Date().getTime(); 

  for (var i = 1; i < data.length; i++) {
    var row = data[i];
    if (!row[0]) continue;

    var rDate = new Date(row[0]);
    // Normalize to Midnight
    var dateKey = rDate.getFullYear() + "-" + 
                  String(rDate.getMonth() + 1).padStart(2, '0') + "-" + 
                  String(rDate.getDate()).padStart(2, '0');
    
    var time = rDate.getTime();
    if (time < minDate) minDate = time;
    
    if (!dailyMap[dateKey]) dailyMap[dateKey] = { income: 0, moves: [] };

    var type = String(row[2]);
    var customer = String(row[3]); 
    var amount = Number(row[6]) || 0;
    var fee = Number(row[7]) || 0;
    var total = Number(row[8]) || 0;
    
    // A. CALCULATE DAILY NET INCOME (Cash Basis Logic)
    // Revenue
    if (['Cash In', 'Cash Out', 'Load'].includes(type)) {
       dailyMap[dateKey].income += fee;
    }
    else if (type === 'Pay Credit' || type === 'Pay Borrowing') {
       // Logic: Check Fee column first (explicit), else calculate
       // We use the same robust logic we added to submitTransaction
       var penalty = 0;
       if (fee > 0) penalty = fee; // If explicitly saved
       else penalty = total - amount; // Calculated
       
       if (penalty > 0.01) dailyMap[dateKey].income += penalty;
    }
    
    // Expenses
    if (['Transfer', 'Add GCash'].includes(type)) {
       dailyMap[dateKey].income -= fee;
    }

    // B. TRACK CAPITAL MOVES
    if (type === 'Invest') {
       dailyMap[dateKey].moves.push({ owner: customer, val: amount });
    }
    else if (type === 'Withdraw') {
       dailyMap[dateKey].moves.push({ owner: customer, val: -amount });
    }
  }

  // 2. SIMULATE HISTORY DAY-BY-DAY
  var logs = [];
  var currentCapital = {}; // { 'Owner A': 5000, 'Owner B': 10000 }
  var grandTotalCapital = 0;

  // Create date iterator
  var startDate = new Date(minDate);
  var endDate = new Date(); // Today
  
  // Iterate from First Transaction -> Today
  for (var d = new Date(startDate); d <= endDate; d.setDate(d.getDate() + 1)) {
      
      var dKey = d.getFullYear() + "-" + 
                 String(d.getMonth() + 1).padStart(2, '0') + "-" + 
                 String(d.getDate()).padStart(2, '0');
      
      var dayData = dailyMap[dKey] || { income: 0, moves: [] };

      // 2.1 Apply Capital Changes FIRST (Before profit distribution)
      // Logic: If I invest today, I get a share of today's profit.
      if (dayData.moves.length > 0) {
          dayData.moves.forEach(function(m) {
              if (!currentCapital[m.owner]) currentCapital[m.owner] = 0;
              currentCapital[m.owner] += m.val;
              grandTotalCapital += m.val;
          });
      }

      // 2.2 Distribute Profit (If there is income and capital)
      if (dayData.income !== 0 && grandTotalCapital > 0) {
          for (var owner in currentCapital) {
              var cap = currentCapital[owner];
              if (cap > 0) { // Only share if positive balance
                  var ratio = cap / grandTotalCapital;
                  var share = dayData.income * ratio;
                  
                  // Store Log: [Date, Owner, CapBal, %, Income, Share]
                  logs.push([
                      dKey, 
                      owner, 
                      cap, 
                      ratio, 
                      dayData.income, 
                      share
                  ]);
              }
          }
      }
  }

  // 3. WRITE TO SHEET
  // Clear old
  if (psSheet.getLastRow() > 1) {
      psSheet.getRange(2, 1, psSheet.getLastRow() - 1, 6).clearContent();
  }
  
  if (logs.length > 0) {
      psSheet.getRange(2, 1, logs.length, 6).setValues(logs);
      // Formats
      psSheet.getRange(2, 3, logs.length, 1).setNumberFormat('₱ #,##0.00'); // Cap
      psSheet.getRange(2, 4, logs.length, 1).setNumberFormat('0.00%');      // %
      psSheet.getRange(2, 5, logs.length, 2).setNumberFormat('₱ #,##0.00'); // Income/Share
  }
}

// Helper: Fetch Summary for Frontend
function getProfitShareSummary() {
  var ss = SpreadsheetApp.openById(SHEET_ID);
  var sheet = ss.getSheetByName('ProfitShare');
  if (!sheet || sheet.getLastRow() < 2) return [];

  var data = sheet.getDataRange().getValues();
  var summary = {};

  // Aggregation
  for (var i = 1; i < data.length; i++) {
      var owner = data[i][1];
      var capital = Number(data[i][2]); // This is daily balance, we want Current Capital
      var share = Number(data[i][5]);
      
      if (!summary[owner]) summary[owner] = { totalShare: 0, currentCap: 0 };
      summary[owner].totalShare += share;
      // We overwrite currentCap constantly so the last entry (latest date) wins
      summary[owner].currentCap = capital; 
  }

  var result = [];
  for (var k in summary) {
      // Calculate ROI
      var roi = 0;
      if (summary[k].currentCap > 0) {
          roi = (summary[k].totalShare / summary[k].currentCap);
      }
      
      result.push({
          owner: k,
          capital: summary[k].currentCap,
          share: summary[k].totalShare,
          roi: roi
      });
  }
  return result;
}

// ==========================================
// --- COMPANY SETTINGS (WITH THEME COLORS) ---
// ==========================================

function getCompanySettings() {
  var ss = SpreadsheetApp.openById(SHEET_ID);
  var sheet = ss.getSheetByName('Settings');
  
  // Default Colors (The original ones)
  var defaults = { 
    name: "2DLR GV", 
    sub: "GCASH LTD", 
    status: "System Online",
    address: "City, Philippines",
    email: "admin@example.com",
    contact: "0900-000-0000",
    logo: "https://lh3.googleusercontent.com/d/1Dltghw9r1Dg98lLsut5DpBqDGXa0URRc",
    
    // Default Theme Colors
    col_maroon: "#800000", // Primary
    col_gold: "#facc15",   // Accent
    col_green: "#2ecc71",  // Success
    col_red: "#e74c3c",    // Danger
    col_blue: "#3498db"    // Info
  };
  
  if (!sheet) return defaults;
  
  var data = sheet.getDataRange().getValues();
  var settings = {};
  
  for (var i = 1; i < data.length; i++) {
    var key = data[i][0];
    if (key === 'CompanyLogo') {
      var fullString = "";
      for (var c = 1; c < data[i].length; c++) fullString += data[i][c];
      settings['CompanyLogo'] = fullString;
    } else {
      settings[key] = data[i][1];
    }
  }
  
  return {
    name: settings['CompanyName'] || defaults.name,
    sub: settings['CompanySub'] || defaults.sub,
    status: settings['SystemStatus'] || defaults.status,
    address: settings['CompanyAddress'] || defaults.address,
    email: settings['CompanyEmail'] || defaults.email,
    contact: settings['CompanyContact'] || defaults.contact,
    logo: (settings['CompanyLogo'] && settings['CompanyLogo'].length > 50) ? settings['CompanyLogo'] : defaults.logo,
    
    // Return Colors
    colors: {
      maroon: settings['ThemeMaroon'] || defaults.col_maroon,
      gold: settings['ThemeGold'] || defaults.col_gold,
      green: settings['ThemeGreen'] || defaults.col_green,
      red: settings['ThemeRed'] || defaults.col_red,
      blue: settings['ThemeBlue'] || defaults.col_blue
    }
  };
}

function saveCompanyLogo(base64String) {
  var ss = SpreadsheetApp.openById(SHEET_ID);
  var sheet = ss.getSheetByName('Settings');
  
  if (!sheet) {
    sheet = ss.insertSheet('Settings');
    sheet.appendRow(['Key', 'Value']);
  }
  
  var data = sheet.getDataRange().getValues();
  var rowIndex = -1;
  
  // 1. Find the row index for 'CompanyLogo'
  for (var i = 1; i < data.length; i++) {
    if (data[i][0] === 'CompanyLogo') {
      rowIndex = i + 1; // 1-based index
      break;
    }
  }
  
  // 2. Clear the old row if it exists, or create a new one
  if (rowIndex !== -1) {
    // Clear content from Column B to the end of the row
    var lastCol = sheet.getLastColumn();
    if (lastCol > 1) {
      sheet.getRange(rowIndex, 2, 1, lastCol - 1).clearContent();
    }
  } else {
    // Append a new row
    sheet.appendRow(['CompanyLogo']);
    rowIndex = sheet.getLastRow();
  }
  
  // 3. CHUNKING LOGIC: Split string into 50k char chunks
  var CHUNK_SIZE = 50000;
  var chunks = [];
  for (var k = 0; k < base64String.length; k += CHUNK_SIZE) {
    chunks.push(base64String.substring(k, k + CHUNK_SIZE));
  }
  
  // 4. Save chunks across columns (B, C, D...)
  // getRange(row, col, numRows, numCols)
  sheet.getRange(rowIndex, 2, 1, chunks.length).setValues([chunks]);
  
  return { status: 'success' };
}

function saveCompanySettings(form) {
  try {
    var ss = SpreadsheetApp.openById(SHEET_ID);
    var sheet = ss.getSheetByName('Settings');
    
    if (!sheet) {
      sheet = ss.insertSheet('Settings');
      sheet.appendRow(['Key', 'Value']);
    }
    
    var data = sheet.getDataRange().getValues();
    
    // Prepare updates
    var updates = {
      'CompanyName': form.name,
      'CompanySub': form.sub,
      'SystemStatus': form.status,
      'CompanyAddress': form.address,
      'CompanyEmail': form.email,
      'CompanyContact': form.contact
    };

    // Safely add colors only if they were sent
    if (form.colors) {
      updates['ThemeMaroon'] = form.colors.maroon;
      updates['ThemeGold'] = form.colors.gold;
      updates['ThemeGreen'] = form.colors.green;
      updates['ThemeRed'] = form.colors.red;
      updates['ThemeBlue'] = form.colors.blue;
    }

    // 1. Update existing rows
    for (var i = 1; i < data.length; i++) {
      var key = String(data[i][0]).trim();
      if (updates.hasOwnProperty(key)) {
        sheet.getRange(i + 1, 2).setValue(updates[key]);
        delete updates[key];
      }
    }

    // 2. Append new rows
    for (var key in updates) {
      sheet.appendRow([key, updates[key]]);
    }
    
    return { status: 'success' };
    
  } catch (e) {
    // Return the error to the frontend instead of hanging
    return { status: 'error', message: e.toString() };
  }
}

2. index.html

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>GCASH SYSTEM</title>
    <!-- Google Fonts -->
    <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600&display=swap" rel="stylesheet">
    <!-- Bootstrap Icons CDN -->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
    <!-- Load CSS -->
    <?!= include('css'); ?>
  </head>
  <body>

    <!-- LOADING SPINNER -->
    <div id="loader" class="loader-container">
      <div class="spinner"></div>
    </div>

    <!-- LANDING / LOGIN PAGE -->
    <div id="login-section" class="main-container">

      <!-- LOGIN FORM CONTAINER -->
      <div id="form-login" class="login-box fade-in">
        <!-- IMPORTANT: Class 'brand-logo' allows the script to update this image -->
        <img src="https://lh3.googleusercontent.com/d/1Dltghw9r1Dg98lLsut5DpBqDGXa0URRc" class="brand-logo" alt="Logo">
        
        <h3 style="margin-top: 40px;">Staff Access</h3>
        
        <div class="input-group">
          <label>Username</label>
          <input type="text" id="username" placeholder="Enter username">
        </div>
        <div class="input-group">
          <label>Password</label>
          <input type="password" id="password" placeholder="Enter password">
        </div>
        
        <button onclick="handleLogin()" id="btn-login" class="btn-primary">LOGIN</button>
        
        <p id="login-msg" class="error-msg"></p>
        
        <div style="text-align:center; margin-top:15px; margin-bottom: 20px; font-size:12px; color:#888;">
          No account? <span onclick="toggleAuthMode('register')" class="link-text">Register here</span>
        </div>

        <!-- INTEGRATED WALLET SECTION -->
        <div class="login-divider"></div>
        <div class="internal-wallet-wrapper">
          <div class="internal-wallet-header" onclick="toggleWalletList()">
            <div style="display:flex; align-items:center; gap:8px;">
              <i class="bi bi-wallet2" style="color:var(--gold);"></i>
              <span>GCash Balances</span>
            </div>
            <i id="wallet-arrow" class="bi bi-chevron-down" style="font-size:12px;"></i>
          </div>
          <div id="public-wallet-list" class="internal-wallet-content">
             <div style="padding:10px; text-align:center;">
                <div class="spinner" style="width:15px; height:15px; border-width:2px; margin:0 auto;"></div>
             </div>
          </div>
        </div>
      </div>

      <!-- REGISTER FORM CONTAINER -->
      <div id="form-register" class="login-box fade-in" style="display:none;">
         <!-- IMPORTANT: Class 'brand-logo' allows the script to update this image too -->
         <img src="https://lh3.googleusercontent.com/d/1Dltghw9r1Dg98lLsut5DpBqDGXa0URRc" class="brand-logo" alt="Logo">
         
         <h3 style="margin-top: 40px;">New Registration</h3>
         
         <div class="input-group">
          <label>Display Name</label>
          <input type="text" id="reg-name" placeholder="e.g. Juan Cruz">
        </div>
        <div class="input-group">
          <label>Username</label>
          <input type="text" id="reg-username" placeholder="Choose a username">
        </div>
        <div class="input-group">
          <label>Password</label>
          <input type="password" id="reg-password" placeholder="Create password">
        </div>
        
        <button onclick="handleRegister()" id="btn-register" class="btn-primary" style="background:var(--bg-page); border:1px solid var(--border-color);">REGISTER</button>
        
        <p id="reg-msg" class="error-msg"></p>
        
        <div style="text-align:center; margin-top:15px; font-size:12px; color:var(--text-sub);">
          Have an account? <span onclick="toggleAuthMode('login')" class="link-text">Login here</span>
        </div>
      </div>

    </div>

    <!-- DASHBOARD -->
    <div id="dashboard-section" class="dashboard-container" style="display:none;">
      
      <!-- Navbar -->
      <nav class="navbar">
        <div class="nav-brand">
          <img src="https://lh3.googleusercontent.com/d/1Dltghw9r1Dg98lLsut5DpBqDGXa0URRc" 
               class="nav-logo" alt="2DLR" 
               onclick="openCompanyModal()" 
               style="cursor:pointer;" 
               title="Company Info">
        </div>
        <div class="nav-user">
          <div id="user-display-container" style="text-align:right; line-height:1.2;">
             <div id="user-name" style="font-weight:600; font-size:13px; color:var(--text-main);">User</div>
             <div id="user-role" style="font-size:10px; color:var(--gold); letter-spacing:0.5px;">Role</div>
          </div>
          
          <button onclick="triggerMasterRefresh(this)" class="btn-small" title="Recalculate System" style="color:var(--gold);">
            <i id="sync-icon" class="bi bi-arrow-repeat"></i>
          </button>

          <button onclick="openProfileModal()" class="btn-small" title="Settings">
            <i class="bi bi-gear-fill"></i>
          </button>

          <button onclick="toggleTheme()" class="btn-small" title="Switch Theme">
            <i id="theme-icon" class="bi bi-moon-fill"></i>
          </button>

          <button onclick="logout()" class="btn-small" title="Logout" style="color:var(--red);">
            <i class="bi bi-box-arrow-right"></i>
          </button>
        </div>
      </nav>

      <div class="content-wrapper">
        <!-- WELCOME BANNER -->
        <div class="welcome-banner" style="display: flex; align-items: center; gap: 20px; text-align: left; padding: 20px;">
          <div class="profile-display-wrapper" style="margin: 0; width: 70px; height: 70px; flex-shrink: 0;">
            <img id="dashboard-profile-img" src="" onerror="this.style.display='none'">
            <div id="dashboard-profile-placeholder">
                <i class="bi bi-person-fill" style="font-size: 2rem;"></i>
            </div>
          </div>
          <div style="flex-grow: 1;">
            <h2 id="welcome-text" style="margin: 0; font-size: 1.1rem; color: var(--text-main);">Loading...</h2>
            <div id="banner-role-display" style="font-size: 10px; color: var(--gold); letter-spacing: 1px; font-weight: 600; margin-bottom: 5px; text-transform: uppercase;">...</div>
            <div style="display: flex; align-items: center; gap: 8px; color: var(--text-sub); font-size: 11px;">
              <i class="bi bi-calendar3"></i>
              <span id="live-date">...</span>
              <span style="opacity: 0.3;">|</span>
              <i class="bi bi-clock"></i>
              <span id="live-time">...</span>
            </div>
          </div>
        </div>
        
        <!-- Quad Balance Card -->
        <div class="balance-card">
          <div class="bal-row">
            <small>GCASH</small>
            <h2 id="gcash-bal">...</h2>
          </div>
          <div class="bal-divider"></div>
          <div class="bal-row">
            <small>CASH</small>
            <h2 id="cash-bal">...</h2>
          </div>
          <div class="bal-divider"></div>
          <div class="bal-row">
            <small>BORROWINGS</small>
            <h2 id="ar-bal">...</h2>
          </div>
          <div class="bal-divider"></div>
          <div class="bal-row">
            <small>CREDITS</small>
            <h2 id="ar-cust-bal">...</h2>
          </div>
        </div>
        
        <!-- TAB NAVIGATION -->
        <div class="tab-bar">
          <button class="tab-btn active" onclick="switchTab('tab-customer', this)">Customer</button>
          <button class="tab-btn" onclick="switchTab('tab-management', this)">Management</button>
          <button class="tab-btn" onclick="switchTab('tab-account', this)">Account</button>
          <button class="tab-btn" onclick="switchTab('tab-accounting', this)">Accounting</button>
        </div>
        
        <!-- 1. CUSTOMER TAB -->
        <div id="tab-customer" class="tab-content fade-in" style="display:block;">
          <div class="action-grid">
            <div class="action-card" onclick="openModal('Cash In')">
              <div class="card-view-btn" onclick="event.stopPropagation(); openViewList('Cash In')"><i class="bi bi-clock-history"></i></div>
              <div class="icon"><i class="bi bi-send-fill"></i></div>
              <h3>Cash In</h3>
              <p>Send GCash</p>
            </div>
            <div class="action-card" onclick="openModal('Cash Out')">
              <div class="card-view-btn" onclick="event.stopPropagation(); openViewList('Cash Out')"><i class="bi bi-clock-history"></i></div>
              <div class="icon"><i class="bi bi-wallet2"></i></div>
              <h3>Cash Out</h3>
              <p>Receive GCash</p>
            </div>
            <div class="action-card" onclick="openModal('Load')">
              <div class="card-view-btn" onclick="event.stopPropagation(); openViewList('Load')"><i class="bi bi-clock-history"></i></div>
              <div class="icon"><i class="bi bi-phone-vibrate"></i></div>
              <h3>Load</h3>
              <p>Airtime / Data</p>
            </div>
          </div>
          <div class="credit-section" style="margin-top: 10px;">
            <hr class="neu-divider">
            <h3 style="font-size: 14px; color: var(--text-sub); margin-bottom: 15px; text-transform: uppercase; letter-spacing: 1px;">Outstanding Customer Credits</h3>
            
            <div class="search-row">
              <input type="text" id="search-credits" class="search-input" placeholder="Search Customer..." onkeyup="filterCredits()">
              <button class="btn-history-log" onclick="openViewList('Pay Credit')" title="View All Credit Payments"><i class="bi bi-clipboard-data-fill"></i></button>
            </div>
            
            <!-- NEW: DYNAMIC TOTAL DISPLAY -->
            <div id="cred-summary" style="text-align: right; font-size: 13px; font-weight: bold; color: var(--red); margin-bottom: 10px; padding-right: 5px;">
               Total: ₱ 0.00
            </div>

            <div id="credit-list-container">
              <p style="text-align:center; font-size:12px; color:#666;">Loading credits...</p>
            </div>
          </div>
        </div>

        <!-- 2. MANAGEMENT TAB -->
        <div id="tab-management" class="tab-content fade-in">
          <div class="action-grid">
            <div class="action-card" onclick="openModal('Invest')">
              <div class="card-view-btn" onclick="event.stopPropagation(); openViewList('Invest')"><i class="bi bi-clock-history"></i></div>
              <div class="icon"><i class="bi bi-graph-up-arrow"></i></div>
              <h3>Invest</h3>
              <p>Add Capital</p>
            </div>
            <div class="action-card" onclick="openModal('Borrow')">
              <div class="card-view-btn" onclick="event.stopPropagation(); openViewList('Borrow')"><i class="bi bi-clock-history"></i></div>
              <div class="icon"><i class="bi bi-bank2"></i></div>
              <h3>Borrow</h3>
              <p>Loan Request</p>
            </div>
            <div class="action-card" onclick="openModal('Withdraw')">
              <div class="card-view-btn" onclick="event.stopPropagation(); openViewList('Withdraw')"><i class="bi bi-clock-history"></i></div>
              <div class="icon"><i class="bi bi-cash-coin"></i></div>
              <h3>Withdraw</h3>
              <p>Take Out Cash</p>
            </div>
          </div> 
          <div class="credit-section">
            <hr class="neu-divider">
            <h3 style="font-size: 14px; color: var(--text-sub); margin-bottom: 15px; text-transform: uppercase; letter-spacing: 1px;">Outstanding Borrowings</h3>
            
            <div class="search-row">
              <input type="text" id="search-borrowings" class="search-input" placeholder="Search Borrower..." onkeyup="filterBorrowings()">
              <button class="btn-history-log" onclick="openViewList('Pay Borrowing')" title="View All Loan Payments"><i class="bi bi-clipboard-data-fill"></i></button>
            </div>
            
            <!-- NEW: DYNAMIC TOTAL DISPLAY -->
            <div id="borrow-summary" style="text-align: right; font-size: 13px; font-weight: bold; color: var(--blue); margin-bottom: 10px; padding-right: 5px;">
               Total: ₱ 0.00
            </div>

            <div id="borrowing-list-container">
              <p style="text-align:center; font-size:12px; color:#666;">Loading borrowings...</p>
            </div>
          </div>
        </div>

        <!-- 3. ACCOUNT TAB -->
        <div id="tab-account" class="tab-content fade-in">
          <div class="action-grid">
            <div class="action-card" onclick="openModal('Add GCash')">
              <div class="card-view-btn" onclick="event.stopPropagation(); openViewList('Add GCash')"><i class="bi bi-clock-history"></i></div>
              <div class="icon"><i class="bi bi-plus-circle-dotted"></i></div>
              <h3>Add GCash</h3>
              <p>Top-up Wallet</p>
            </div>
            <div class="action-card" onclick="openModal('Transfer')">
              <div class="card-view-btn" onclick="event.stopPropagation(); openViewList('Transfer')"><i class="bi bi-clock-history"></i></div>
              <div class="icon"><i class="bi bi-arrow-left-right"></i></div>
              <h3>Transfer</h3>
              <p>Wallet to Wallet</p>
            </div>
            <div class="action-card" onclick="openWalletModal()">
              <div class="icon"><i class="bi bi-wallet-fill"></i></div>
              <h3>My Wallets</h3>
              <p>Add/Request</p>
            </div>
            <div id="btn-admin-wallets" class="action-card" onclick="openAdminWalletModal()" style="display:none; border-color: #e67e22;">
              <div class="icon" style="color:#e67e22;"><i class="bi bi-shield-check"></i></div>
              <h3 style="color:#e67e22;">Approvals</h3>
              <p>Wallet Requests</p>
            </div>
          </div>
        </div>

        <!-- 4. ACCOUNTING TAB -->
        <div id="tab-accounting" class="tab-content fade-in">
          <div class="action-grid">
            <div class="action-card" onclick="openReportModal('journal')">
              <div class="icon" style="color:#7f8c8d;"><i class="bi bi-book"></i></div>
              <h3>Journal</h3>
              <p>General Ledger</p>
            </div>
            <div class="action-card" onclick="openReportModal('tb')">
              <div class="icon" style="color:#9b59b6;"><i class="bi bi-clipboard-check"></i></div>
              <h3>Audit</h3>
              <p>Trial Balance</p>
            </div>
            <div class="action-card" onclick="openReportModal('bs')">
              <div class="icon" style="color:var(--blue);"><i class="bi bi-journal-check"></i></div>
              <h3>Assets</h3>
              <p>Balance Sheet</p>
            </div>
            <div class="action-card" onclick="openReportModal('sci')">
              <div class="icon" style="color:var(--green);"><i class="bi bi-file-earmark-bar-graph"></i></div>
              <h3>Income</h3>
              <p>Profit & Loss</p>
            </div>
            <div class="action-card" onclick="openReportModal('profit')">
              <div class="icon" style="color:#e67e22;"><i class="bi bi-pie-chart-fill"></i></div>
              <h3>Dividends</h3>
              <p>Profit Sharing</p>
            </div>
            <div class="action-card" onclick="openReportModal('daily')">
              <div class="icon" style="color:var(--gold);"><i class="bi bi-calendar-date"></i></div>
              <h3>Daily</h3>
              <p>Today's Stats</p>
            </div>            
          </div>
        </div>
      </div>
    </div>

    <!-- TRANSACTION MODAL -->
    <div id="txn-modal" class="modal">
      <div class="modal-content">
        <div class="modal-header">
          <h2 id="modal-title">New Transaction</h2>
          <span class="close-btn" onclick="closeModal()">&times;</span>
        </div>
        <div class="modal-body">
          <form id="txn-form" onsubmit="submitTransaction(event)">
            <input type="hidden" id="t-edit-id" value=""> 
            <div class="form-row" style="position: relative; z-index: 20;">
              <div class="form-group">
                <label>Date</label>
                <input type="date" id="t-date" required>
              </div>
              <div class="form-group" id="grp-source">
                <label id="lbl-source">Source Account</label>
                <div class="custom-select-wrapper" id="wrapper-source">
                  <input type="hidden" id="t-source">
                  <div class="custom-select-trigger" onclick="toggleCustomSelect('wrapper-source')">
                    <span id="display-source">Select Account</span>
                    <i class="bi bi-chevron-down"></i>
                  </div>
                  <div class="custom-options" id="list-source"></div>
                </div>
              </div>
              <div class="form-group" id="grp-target" style="display:none;">
                <label>Target Account (To)</label>
                <div class="custom-select-wrapper" id="wrapper-target">
                  <input type="hidden" id="t-target">
                  <div class="custom-select-trigger" onclick="toggleCustomSelect('wrapper-target')">
                    <span id="display-target">Select Account</span>
                    <i class="bi bi-chevron-down"></i>
                  </div>
                  <div class="custom-options" id="list-target"></div>
                </div>
              </div>
            </div>

            <div class="form-group" id="grp-fund-source" style="display:none; margin-bottom:15px; position:relative; z-index:19;">
              <label>Source of Funds</label>
              <div class="custom-select-wrapper" id="wrapper-fund">
                <input type="hidden" id="t-fund-select" value="7/11">
                <div class="custom-select-trigger" onclick="toggleCustomSelect('wrapper-fund')">
                  <span id="display-fund">7/11 Cliqq</span>
                  <i class="bi bi-chevron-down"></i>
                </div>
                <div class="custom-options">
                  <div class="custom-option" onclick="selectCustomOption('wrapper-fund', 't-fund-select', 'display-fund', '7/11', '7/11 Cliqq')"><i class="bi bi-shop"></i> 7/11 Cliqq</div>
                  <div class="custom-option" onclick="selectCustomOption('wrapper-fund', 't-fund-select', 'display-fund', 'Bank Account', 'Bank Account')"><i class="bi bi-bank"></i> Bank Account</div>
                  <div class="custom-option" onclick="selectCustomOption('wrapper-fund', 't-fund-select', 'display-fund', 'Customers', 'Customers')"><i class="bi bi-people-fill"></i> Customers</div>
                </div>
              </div>
            </div>

            <div class="form-group" id="grp-customer">
              <label id="lbl-customer">Customer Name</label>
              <input type="text" id="t-customer" list="customer-list" placeholder="Type or select..." onchange="checkOwnerLimit()" required>
              <datalist id="customer-list"></datalist>
              <small id="limit-display" style="color: #4ade80; display:none; margin-top:5px; font-weight:bold;"></small>
            </div>

            <div id="grp-bank-details" style="display:none;">
              <div class="form-row">
                <div class="form-group">
                  <label>Bank Name</label>
                  <input type="text" id="t-bank-name" placeholder="e.g. BDO, BPI">
                </div>
                <div class="form-group">
                  <label>Account Number</label>
                  <input type="text" id="t-bank-acc" list="bank-list" placeholder="Type or select...">
                  <datalist id="bank-list"></datalist>
                </div>
              </div>
            </div>

            <div class="form-group" id="grp-ref">
              <label>Reference No. (Optional)</label>
              <input type="text" id="t-ref" placeholder="Reference Number">
            </div>

            <!-- NEW: Interest Option for Borrowing -->
            <div class="form-group" id="grp-interest-option" style="display:none; margin-bottom: 15px;">
              <label>Interest Option</label>
              <div class="custom-select-wrapper" id="wrapper-interest-opt">
                <input type="hidden" id="t-interest-opt" value="No Interest">
                <div class="custom-select-trigger" onclick="toggleCustomSelect('wrapper-interest-opt')">
                  <span id="display-interest-opt">No Interest</span>
                  <i class="bi bi-chevron-down"></i>
                </div>
                <div class="custom-options">
                  <div class="custom-option" onclick="selectCustomOption('wrapper-interest-opt', 't-interest-opt', 'display-interest-opt', 'No Interest', 'No Interest')">No Interest</div>
                  <div class="custom-option" onclick="selectCustomOption('wrapper-interest-opt', 't-interest-opt', 'display-interest-opt', 'With Interest', 'With Interest')">With Interest</div>
                </div>
              </div>
            </div>

            <div class="money-section" id="money-section">
              <div class="form-row">
                <div class="form-group">
                  <label>Amount</label>
                  <input type="number" id="t-amount" step="0.01" placeholder="0.00" oninput="calculateTotals()" required>
                </div>
                <div class="form-group" id="grp-fee">
                  <label>Charge/Fee</label>
                  <input type="number" id="t-fee" step="0.01" readonly class="readonly-input">
                </div>
              </div>
              <div class="total-display">
                <label id="lbl-total">TOTAL TO PAY</label>
                <div id="t-total-display">0.00</div>
                <input type="hidden" id="t-total">
              </div>
            </div>

            <div id="payment-details-wrapper">
              <div class="payment-section">
                <div class="form-row">
                  <div class="form-group">
                    <label>Settlement</label>
                    <div class="custom-select-wrapper" id="wrapper-settlement">
                      <input type="hidden" id="t-settlement" value="Cash">
                      <div class="custom-select-trigger" onclick="toggleCustomSelect('wrapper-settlement')">
                        <span id="display-settlement">Cash</span>
                        <i class="bi bi-chevron-down"></i>
                      </div>
                      <div class="custom-options">
                        <div class="custom-option" onclick="selectCustomOption('wrapper-settlement', 't-settlement', 'display-settlement', 'Cash', 'Cash')"><i class="bi bi-cash-stack"></i> Cash</div>
                        <div class="custom-option" onclick="selectCustomOption('wrapper-settlement', 't-settlement', 'display-settlement', 'On Account', 'On Account (Credit)')"><i class="bi bi-journal-text"></i> On Account (Credit)</div>
                      </div>
                    </div>
                  </div>
                  <div class="form-group" id="grp-paid-container">
                    <label id="lbl-paid">Cash Received</label>
                    <input type="number" id="t-paid" step="0.01" placeholder="0.00" oninput="calculateChange()">
                  </div>
                </div>
                <div id="tip-change-row" class="form-row" style="display:none;">
                  <div class="form-group">
                    <label>Tip (Optional)</label>
                    <input type="number" id="t-tip" step="0.01" placeholder="0.00" oninput="calculateChange()">
                  </div>
                  <div class="form-group">
                    <label>Change</label>
                    <input type="number" id="t-change" step="0.01" readonly class="readonly-input">
                  </div>
                </div>
              </div>
            </div>

            <div class="form-actions">
              <button type="button" class="btn-cancel" onclick="closeModal()">Cancel</button>
              <button type="submit" class="btn-submit">PROCESS TRANSACTION</button>
            </div>
          </form>
        </div>
      </div>
    </div>

    <!-- VIEW TRANSACTIONS MODAL -->
    <div id="view-txn-modal" class="modal">
      <div class="modal-content" style="max-width: 900px;">
        <div class="modal-header" style="display:flex; justify-content:space-between; align-items:center;">
          <div><h2 id="view-txn-title" style="margin:0; font-size:1.1rem;">History</h2></div>
          <div style="display:flex; align-items:center; gap:10px;">
            <div class="custom-select-wrapper" id="wrapper-limit" style="width:130px;">
              <input type="hidden" id="view-limit-select" value="50">
              <div class="custom-select-trigger" onclick="toggleCustomSelect('wrapper-limit')" style="padding: 8px 12px; font-size: 12px;">
                <span id="display-limit">Last 50</span>
                <i class="bi bi-chevron-down" style="font-size: 10px;"></i>
              </div>
              <div class="custom-options">
                <div class="custom-option" onclick="selectCustomOption('wrapper-limit', 'view-limit-select', 'display-limit', '50', 'Last 50')">Last 50</div>
                <div class="custom-option" onclick="selectCustomOption('wrapper-limit', 'view-limit-select', 'display-limit', '100', 'Last 100')">Last 100</div>
                <div class="custom-option" onclick="selectCustomOption('wrapper-limit', 'view-limit-select', 'display-limit', '500', 'Last 500')">Last 500</div>
                <div class="custom-option" onclick="selectCustomOption('wrapper-limit', 'view-limit-select', 'display-limit', '0', 'Show All')">Show All</div>
              </div>
            </div>
            <span class="close-btn" onclick="closeViewModal()" style="line-height:1;">&times;</span>
          </div>
        </div>
        <div class="modal-body" style="padding: 0;">
          <div style="overflow-x: auto; max-height: 400px;">
            <table class="data-table">
              <thead><tr><th>Date</th><th>ID</th><th>Customer/Source</th><th class="txt-right">Amount</th><th class="txt-right">Fee</th><th class="txt-right">Total</th><th id="th-action" style="text-align:center;">Action</th></tr></thead>
              <tbody id="view-txn-body"></tbody>
            </table>
          </div>
        </div>
      </div>
    </div>

    <!-- HISTORY DETAILS MODAL -->
    <div id="history-modal" class="modal">
      <div class="modal-content" style="max-width: 600px;">
        <div class="modal-header">
          <h2>Transaction History</h2>
          <span class="close-btn" onclick="closeHistoryModal()">&times;</span>
        </div>
        <div class="modal-body">
          <h3 id="hist-customer" style="margin-top:0; font-size:14px; color:var(--text-grey);">Customer</h3>
          <h4 id="hist-ref" style="margin:0 0 15px; font-size:12px; color:#666;">Ref: ...</h4>
          <div class="history-list-header"><span>DATE</span><span>ACTIVITY</span><span style="text-align:right">AMOUNT</span><span style="text-align:right">BALANCE</span></div>
          <div id="history-list-content"></div>
        </div>
      </div>
    </div>

    <!-- PROFILE SETTINGS MODAL -->
    <div id="profile-modal" class="modal">
      <div class="modal-content" style="max-width: 350px;">
        <div class="modal-header">
          <h2>Account Settings</h2>
          <span class="close-btn" onclick="document.getElementById('profile-modal').style.display='none'">&times;</span>
        </div>
        <div class="modal-body" style="text-align:center;">
          <div style="margin-bottom:25px;">
             <div class="profile-upload-preview">
                <img id="settings-profile-img" src="" style="display:none;">
                <i id="settings-profile-icon" class="bi bi-person-circle" style="font-size:4rem; color:var(--text-sub);"></i>
             </div>
             <input type="file" id="profile-upload-input" accept="image/*" style="display:none;" onchange="handleImageSelection(this)">
             <button onclick="document.getElementById('profile-upload-input').click()" class="btn-small" style="width:auto; padding:5px 15px; font-size:11px; border-radius:20px; margin-top:10px;"><i class="bi bi-camera-fill"></i> Change Photo</button>
          </div>
          <hr class="neu-divider">
          <p style="color:#aaa; font-size:12px; margin-bottom:15px; text-align:left;">Update Password</p>
          <div class="form-group"><input type="password" id="p-new-pass" placeholder="Enter new password"></div>
          <div class="form-group" style="margin-bottom:20px;"><input type="password" id="p-confirm-pass" placeholder="Repeat password"></div>
          <button onclick="submitPasswordChange()" class="btn-primary">UPDATE PASSWORD</button>
        </div>
      </div>
    </div>

    <!-- USER WALLET MANAGER MODAL -->
    <div id="wallet-modal" class="modal">
      <div class="modal-content" style="max-width: 450px;">
        <div class="modal-header">
          <h2>My Wallets</h2>
          <span class="close-btn" onclick="document.getElementById('wallet-modal').style.display='none'">&times;</span>
        </div>
        <div class="modal-body" style="padding: 0;">
          <div id="user-wallet-list" style="padding: 15px; background: var(--bg-page); max-height: 300px; overflow-y: auto;">
            <p style="text-align:center; color:#888;">Loading your wallets...</p>
          </div>
          <div style="padding: 20px; border-top: 1px solid var(--border-color); background: var(--bg-card);">
            <h4 style="margin:0 0 10px; font-size:12px; color:var(--text-sub); text-transform:uppercase;">Request New Wallet</h4>
            <div style="display:flex; gap:10px;">
              <input type="text" id="w-name" placeholder="Wallet Name (e.g. My GCash)" style="flex:1;">
              <button onclick="submitNewWallet()" class="btn-primary" style="width:auto; padding:0 20px;">ADD</button>
            </div>
          </div>
        </div>
      </div>
    </div>

    <!-- ADMIN WALLET APPROVAL MODAL -->
    <div id="admin-wallet-modal" class="modal">
      <div class="modal-content" style="max-width: 400px;">
        <div class="modal-header" style="background: #e67e22;">
          <h2>Pending Approvals</h2>
          <span class="close-btn" onclick="document.getElementById('admin-wallet-modal').style.display='none'">&times;</span>
        </div>
        <div class="modal-body"><div id="admin-wallet-list"></div></div>
      </div>
    </div>

    <!-- REPORT MODAL: DAILY -->
    <div id="modal-daily" class="modal">
      <div class="modal-content">
        <div class="modal-header" style="flex-direction:column; align-items:stretch; gap:10px; padding-bottom:10px;">
          <div style="display:flex; justify-content:space-between; align-items:center;"><h2>Daily Report</h2><span class="close-btn" onclick="closeReportModal('daily')">&times;</span></div>
          <div class="date-nav-bar" style="display:flex; justify-content:center; align-items:center; gap:10px;">
              <button onclick="changeReportDate(-1)" class="btn-small" style="width:35px; height:35px;"><i class="bi bi-chevron-left"></i></button>
              <input type="date" id="accounting-date-picker" onchange="loadAccountingData()" style="width:auto; text-align:center; font-weight:bold; color:var(--gold); border:1px solid var(--border-color);">
              <button onclick="changeReportDate(1)" class="btn-small" style="width:35px; height:35px;"><i class="bi bi-chevron-right"></i></button>
          </div>
        </div>
        <div class="modal-body">
          <div class="balance-card" style="flex-direction: column; align-items: stretch; gap: 15px; margin-top:0;">
            <div style="text-align:center;"><small style="color:var(--text-sub); letter-spacing:1px;">TOTAL INCOME</small><h1 id="acc-daily-income" style="margin:5px 0; color:var(--gold); font-size:2.5rem;">₱0.00</h1></div>
            <hr class="neu-divider">
            <div style="display:flex; justify-content:space-between; text-align:center;">
                <div><small style="color:var(--text-sub);">CASH SALES</small><div id="acc-cash-sales" style="color:var(--green); font-weight:bold;">₱0.00</div></div>
                <div style="width:1px; background:var(--border-color);"></div>
                <div><small style="color:var(--text-sub);">CREDIT SALES</small><div id="acc-credit-sales" style="color:var(--red); font-weight:bold;">₱0.00</div></div>
            </div>
          </div>
          <div class="acct-table-wrapper" style="margin-bottom: 20px; border: 1px solid var(--border-color);">
            <table class="acct-table">
                <thead><tr><th style="text-align:left; color:var(--text-sub); padding-left:10px;">PROFIT SHARE (EST.)</th><th style="text-align:right; color:var(--text-sub); padding-right:10px;">AMOUNT</th></tr></thead>
                <tbody id="daily-share-rows"></tbody>
            </table>
          </div>
          <h3 class="section-title">Cash Flow</h3>
          <div class="flow-container">
            <div class="flow-box"><div class="flow-icon in"><i class="bi bi-arrow-down-left"></i></div><div><small>In</small><div id="flow-cash-in">₱0.00</div></div></div>
            <div class="flow-box"><div class="flow-icon out"><i class="bi bi-arrow-up-right"></i></div><div><small>Out</small><div id="flow-cash-out">₱0.00</div></div></div>
          </div>
          <h3 class="section-title">GCash Flow</h3>
          <div class="flow-container">
            <div class="flow-box"><div class="flow-icon in-blue"><i class="bi bi-phone"></i></div><div><small>In</small><div id="flow-gcash-in">₱0.00</div></div></div>
            <div class="flow-box"><div class="flow-icon out-blue"><i class="bi bi-send"></i></div><div><small>Out</small><div id="flow-gcash-out">₱0.00</div></div></div>
          </div>
        </div>
      </div>
    </div>

    <!-- REPORT MODAL: INCOME STATEMENT -->
    <div id="modal-sci" class="modal">
      <div class="modal-content">
        <div class="modal-header"><h2>Income Statement (YTD)</h2><span class="close-btn" onclick="closeReportModal('sci')">&times;</span></div>
        <div class="modal-body">
          <div class="acct-table-wrapper">
            <table class="acct-table">
                <tr><td colspan="2" style="font-weight:bold; color:var(--text-sub); padding-top:10px;">REVENUE</td></tr>
                <tr><td style="padding-left:15px;">Service Fees</td><td class="txt-right" id="sci-rev-fees">₱0.00</td></tr>
                <tr><td style="padding-left:15px;">Other Income (Penalties)</td><td class="txt-right" id="sci-rev-other">₱0.00</td></tr>
                <tr class="total-row"><td>TOTAL REVENUE</td><td class="txt-right" id="sci-rev-total" style="color:var(--green);">₱0.00</td></tr>
                <tr><td colspan="2" style="font-weight:bold; color:var(--text-sub); padding-top:15px;">OPERATING EXPENSES</td></tr>
                <tr><td style="padding-left:15px;">Transaction Costs</td><td class="txt-right" id="sci-exp-costs">₱0.00</td></tr>
                <tr class="total-row"><td>TOTAL EXPENSES</td><td class="txt-right" id="sci-exp-total" style="color:var(--red);">₱0.00</td></tr>
                <tr class="total-row equity" style="border-top: 3px double var(--border-color);"><td style="font-size:14px; padding-top:15px;">NET INCOME</td><td class="txt-right" id="sci-net-income" style="font-size:14px; padding-top:15px;">₱0.00</td></tr>
            </table>
          </div>
        </div>
      </div>
    </div>

    <!-- REPORT MODAL: BALANCE SHEET -->
    <div id="modal-bs" class="modal">
      <div class="modal-content">
        <div class="modal-header"><h2>Balance Sheet</h2><span class="close-btn" onclick="closeReportModal('bs')">&times;</span></div>
        <div class="modal-body">
          <div class="acct-table-wrapper">
            <table class="acct-table">
                <tr><td colspan="2" style="font-weight:bold; color:var(--text-sub); padding-top:5px;">ASSETS</td></tr>
                <tr><td>Cash on Hand</td><td class="txt-right" id="bs-cash">₱0.00</td></tr>
                <tr><td>GCash Wallet (Total)</td><td class="txt-right" id="bs-gcash" style="font-weight:bold;">₱0.00</td></tr>
                <tbody id="bs-wallet-rows"></tbody>
                <tr><td>Accts. Receivable (Cust)</td><td class="txt-right" id="bs-ar-cust">₱0.00</td></tr>
                <tr><td>Accts. Receivable (Loans)</td><td class="txt-right" id="bs-ar-loan">₱0.00</td></tr>
                <tr class="total-row"><td>TOTAL ASSETS</td><td class="txt-right" id="bs-total">₱0.00</td></tr>
                <tr><td colspan="2" style="font-weight:bold; color:var(--text-sub); padding-top:15px;">OWNER'S EQUITY</td></tr>
                <tbody id="bs-equity-rows"></tbody>
                <tr class="total-row equity"><td>TOTAL EQUITY</td><td class="txt-right" id="bs-equity">₱0.00</td></tr>
            </table>
          </div>
        </div>
      </div>
    </div>

    <!-- REPORT MODAL: TRIAL BALANCE -->
    <div id="modal-tb" class="modal">
      <div class="modal-content">
        <div class="modal-header"><h2>Trial Balance</h2><span class="close-btn" onclick="closeReportModal('tb')">&times;</span></div>
        <div class="modal-body">
          <div class="acct-table-wrapper">
            <table class="acct-table">
                <thead><tr><th style="text-align:left; color:var(--text-sub);">ACCOUNT</th><th style="text-align:right; color:var(--text-sub);">DEBIT</th><th style="text-align:right; color:var(--text-sub);">CREDIT</th></tr></thead>
                <tbody id="tb-rows"></tbody>
                <tr class="total-row"><td>TOTAL</td><td class="txt-right" id="tb-total-dr">₱0.00</td><td class="txt-right" id="tb-total-cr">₱0.00</td></tr>
            </table>
            <div id="tb-status" style="text-align:center; margin-top:15px; font-weight:bold; font-size:12px;">Checking...</div>
          </div>
        </div>
      </div>
    </div>

    <!-- REPORT MODAL: GENERAL JOURNAL -->
    <div id="modal-journal" class="modal">
      <div class="modal-content" style="max-width: 750px;">
        <div class="modal-header"><h2>General Journal</h2><span class="close-btn" onclick="closeReportModal('journal')">&times;</span></div>
        <div class="modal-body" style="padding:0;">
          <!-- INCREASED HEIGHT HERE: Changed max-height: 400px to height: 65vh -->
          <div style="height: 65vh; overflow-y: auto;">
            <table class="data-table">
                <thead style="position:sticky; top:0; background:var(--bg-page); z-index:10;">
                    <tr><th style="padding-left:15px;">Date / ID</th><th>Account</th><th>Description</th><th class="txt-right">Debit</th><th class="txt-right" style="padding-right:15px;">Credit</th></tr>
                </thead>
                <tbody id="journal-rows"></tbody>
            </table>
          </div>
        </div>
      </div>
    </div>

    <!-- REPORT MODAL: PROFIT SHARING -->
    <div id="modal-profit" class="modal">
      <div class="modal-content">
        <div class="modal-header"><h2>Profit Sharing (P/L)</h2><span class="close-btn" onclick="closeReportModal('profit')">&times;</span></div>
        <div class="modal-body">
          <div class="acct-table-wrapper">
            <table class="acct-table">
                <thead><tr><th style="text-align:left; color:var(--text-sub);">OWNER</th><th style="text-align:right; color:var(--text-sub);">CAPITAL</th><th style="text-align:right; color:var(--text-sub);">SHARE</th><th style="text-align:right; color:var(--text-sub);">ROI</th></tr></thead>
                <tbody id="profit-rows"></tbody>
            </table>
            <p style="font-size:10px; color:var(--text-sub); text-align:center; margin-top:20px;">* Share is calculated daily based on capital ratio at that specific date.</p>
          </div>
        </div>
      </div>
    </div>

    <!-- CONFIRMATION MODAL -->
    <div id="modal-confirm" class="modal" style="z-index: 3000;">
      <div class="modal-content" style="max-width: 320px; text-align: center; padding: 25px;">
        <div style="font-size: 3rem; color: var(--gold); margin-bottom: 10px;"><i class="bi bi-exclamation-circle-fill"></i></div>
        <h3 id="confirm-title" style="margin: 0; color: var(--text-main);">Confirm Action</h3>
        <p id="confirm-msg" style="color: var(--text-sub); font-size: 13px; margin: 10px 0 25px;">Are you sure?</p>
        <div style="display: flex; gap: 15px;">
          <button onclick="closeConfirm()" class="btn-cancel" style="border:1px solid var(--border-color); border-radius:50px; padding:10px;">Cancel</button>
          <button onclick="executeConfirm()" id="btn-confirm-yes" class="btn-primary" style="padding:10px; font-size:12px;">CONFIRM</button>
        </div>
      </div>
    </div>

    <!-- COMPANY INFO MODAL -->
    <div id="modal-company" class="modal">
      <div class="modal-content" style="max-width: 350px; max-height: 95vh; height: auto; display: flex; flex-direction: column; transition: max-width 0.3s ease;">
        
        <!-- HEADER -->
        <div style="padding: 15px; text-align: right; border-bottom: 1px solid var(--border-color); flex-shrink: 0;">
             <span class="close-btn" onclick="document.getElementById('modal-company').style.display='none'" style="cursor:pointer;">&times;</span>
        </div>

        <!-- BODY -->
        <div class="modal-body" style="padding: 20px; overflow-y: auto;">
            
            <!-- LOGO SECTION -->
            <div style="position:relative; width:80px; margin:0 auto 15px auto;">
               <img id="company-logo-img" src="https://lh3.googleusercontent.com/d/1Dltghw9r1Dg98lLsut5DpBqDGXa0URRc" style="width:80px; height:80px; object-fit:contain; filter: drop-shadow(0 5px 10px rgba(0,0,0,0.3));">
               <input type="file" id="company-logo-upload" accept="image/*" style="display:none;" onchange="handleLogoSelection(this)">
               <div id="logo-edit-overlay" onclick="document.getElementById('company-logo-upload').click()" style="display:none; position:absolute; bottom:0; right:-5px; background:var(--gold); color:black; width:25px; height:25px; border-radius:50%; align-items:center; justify-content:center; cursor:pointer; box-shadow:var(--outer-shadow);">
                 <i class="bi bi-camera-fill" style="font-size:12px;"></i>
               </div>
            </div>

            <!-- VIEW MODE (Narrow & Stacked) -->
            <div id="view-mode-company">
                <h2 id="disp-comp-name" style="color:var(--primary-maroon); margin:0; letter-spacing:1px; font-size: 1.2rem; text-align:center;">Loading...</h2>
                <h3 id="disp-comp-sub" style="color:var(--text-main); margin:5px 0 15px; font-size:0.9rem; text-align:center;">...</h3>
                
                <div style="width:40px; height:2px; background:var(--gold); margin:0 auto 15px;"></div>
                
                <div style="text-align:left; background:var(--bg-input); padding:12px; border-radius:12px; font-size:11px; color:var(--text-sub); border:1px solid var(--border-color); margin-bottom:15px;">
                   <div style="display:flex; align-items:center; gap:10px; margin-bottom:8px;">
                     <i class="bi bi-geo-alt-fill" style="color:var(--gold);"></i>
                     <span id="disp-comp-address">...</span>
                   </div>
                   <div style="display:flex; align-items:center; gap:10px; margin-bottom:8px;">
                     <i class="bi bi-telephone-fill" style="color:var(--gold);"></i>
                     <span id="disp-comp-contact">...</span>
                   </div>
                   <div style="display:flex; align-items:center; gap:10px;">
                     <i class="bi bi-envelope-fill" style="color:var(--gold);"></i>
                     <span id="disp-comp-email">...</span>
                   </div>
                </div>

                <div id="disp-comp-status" style="text-align:center; padding:8px; background:rgba(46, 204, 113, 0.1); border-radius:12px; font-size:10px; color:var(--green); border:1px solid var(--green); font-weight:bold;"><i class="bi bi-wifi"></i> ...</div>
                
                <div id="admin-edit-btn" style="text-align:center; display:none; margin-top:20px;">
                    <button onclick="toggleCompanyEdit(true)" class="btn-small" style="width:auto; padding:5px 15px; font-size:10px; border-radius:20px;">
                        <i class="bi bi-pencil"></i> Edit Info
                    </button>
                </div>
            </div>

            <!-- EDIT MODE (Wide & Side-by-Side) -->
            <div id="edit-mode-company" style="display:none; text-align:left;">
                <p style="text-align:center; font-size:9px; color:var(--gold); margin-bottom:15px;">Tap logo to change</p>

                <!-- ROW 1: Name & Subtitle -->
                <div class="form-row" style="margin-bottom:10px;">
                    <div class="form-group">
                        <label>Company Name</label>
                        <input type="text" id="edit-comp-name">
                    </div>
                    <div class="form-group">
                        <label>Subtitle</label>
                        <input type="text" id="edit-comp-sub">
                    </div>
                </div>
                
                <!-- ROW 2: Address & Status -->
                <div class="form-row" style="margin-bottom:10px;">
                    <div class="form-group">
                        <label>Address</label>
                        <input type="text" id="edit-comp-address">
                    </div>
                    <div class="form-group">
                        <label>System Status</label>
                        <input type="text" id="edit-comp-status">
                    </div>
                </div>
                
                <!-- ROW 3: Contact & Email -->
                <div class="form-row" style="margin-bottom:10px;">
                    <div class="form-group">
                        <label>Contact No.</label>
                        <input type="text" id="edit-comp-contact">
                    </div>
                    <div class="form-group">
                        <label>Email</label>
                        <input type="text" id="edit-comp-email">
                    </div>
                </div>
                
                <!-- THEME COLORS -->
                <div style="margin-top:10px; padding-top:10px; border-top:1px solid var(--border-color);">
                   <label style="margin-bottom:10px; display:block; color:var(--text-main); font-weight:bold; font-size:11px;">Theme Colors</label>
                   
                   <div style="display:flex; flex-wrap:wrap; justify-content:space-around; gap:10px;">
                      
                      <div style="text-align:center;">
                        <input type="color" id="col-maroon" title="Primary" style="width:40px; height:40px; padding:0; border:2px solid var(--bg-page); outline:1px solid var(--border-color); border-radius:10px; cursor:pointer;">
                        <div style="font-size:9px; color:var(--text-sub); margin-top:3px;">Primary</div>
                      </div>

                      <div style="text-align:center;">
                        <input type="color" id="col-gold" title="Accent" style="width:40px; height:40px; padding:0; border:2px solid var(--bg-page); outline:1px solid var(--border-color); border-radius:10px; cursor:pointer;">
                        <div style="font-size:9px; color:var(--text-sub); margin-top:3px;">Accent</div>
                      </div>

                      <div style="text-align:center;">
                        <input type="color" id="col-green" title="Success" style="width:40px; height:40px; padding:0; border:2px solid var(--bg-page); outline:1px solid var(--border-color); border-radius:10px; cursor:pointer;">
                        <div style="font-size:9px; color:var(--text-sub); margin-top:3px;">Success</div>
                      </div>

                      <div style="text-align:center;">
                        <input type="color" id="col-red" title="Danger" style="width:40px; height:40px; padding:0; border:2px solid var(--bg-page); outline:1px solid var(--border-color); border-radius:10px; cursor:pointer;">
                        <div style="font-size:9px; color:var(--text-sub); margin-top:3px;">Danger</div>
                      </div>

                      <div style="text-align:center;">
                        <input type="color" id="col-blue" title="Info" style="width:40px; height:40px; padding:0; border:2px solid var(--bg-page); outline:1px solid var(--border-color); border-radius:10px; cursor:pointer;">
                        <div style="font-size:9px; color:var(--text-sub); margin-top:3px;">Info</div>
                      </div>
                   </div>
                   
                   <div style="text-align:center; margin-top:10px;">
                       <span onclick="resetThemeColors()" class="link-text" style="font-size:10px; opacity:0.8;">Reset Defaults</span>
                   </div>
                </div>
                
                <!-- BUTTONS -->
                <div style="display:flex; gap:15px; margin-top:20px;">
                    <button onclick="toggleCompanyEdit(false)" class="btn-cancel" style="flex:1; border:1px solid var(--border-color); border-radius:50px; padding:10px; font-size:11px;">Cancel</button>
                    <button onclick="saveCompanyInfo()" class="btn-primary" style="flex:1; padding:10px; font-size:11px;">SAVE CHANGES</button>
                </div>
            </div>

            <p style="color:var(--text-sub); font-size:9px; margin-top:15px; opacity:0.4;">System v2.2</p>
        </div>
      </div>
    </div>

    
    <!-- TOAST CONTAINER -->
    <div id="toast-container"></div>

    <!-- Load JS -->
    <?!= include('js'); ?>
  </body>
</html>

3. css.html

4. js.html

Final Step: Deployment

Click Deploy > New deployment. Select Web app, set "Execute as" to Me, and "Who has access" to Anyone.

View Live Demo

Congratulations! Your GCash Management System is now live.

Gervic

I was born on the cold quiet evening on May 5, 1993 at Naghalin, Novalls, Tanjay, Philippines. At age 27, I am now more than what you will find on my birth record. I consider myself a dreamer, a writer, a designer, an artist, a programmer – but not to the maximum extent. I dabble on a wee bit of all those aforementioned. I can write, draw and sketch, do digital design, understand and do HTML, create landscapes, and others that I find interesting to do. Read my full bio at https://flecksofvariedcolors.blogspot.com/p/about.html

Post a Comment

Previous Post Next Post