{"id":2779,"date":"2026-04-29T22:33:11","date_gmt":"2026-04-29T15:33:11","guid":{"rendered":"https:\/\/thaichristian.ac.th\/?p=2779"},"modified":"2026-05-12T14:12:07","modified_gmt":"2026-05-12T07:12:07","slug":"after-school","status":"publish","type":"post","link":"https:\/\/thaichristian.ac.th\/zh\/after-school.html","title":{"rendered":"After School Programs FORM [1\/2026]"},"content":{"rendered":"<h1>After School Programs [1\/2026]<\/h1>\n<p><span style=\"color: #5c5c5c;\">\u0e02\u0e49\u0e2d\u0e41\u0e19\u0e30\u0e19\u0e33 \u0e2b\u0e32\u0e01\u0e17\u0e48\u0e32\u0e19\u0e15\u0e49\u0e2d\u0e07\u0e01\u0e32\u0e23\u0e23\u0e32\u0e22\u0e25\u0e30\u0e40\u0e2d\u0e35\u0e22\u0e14\u0e40\u0e1e\u0e34\u0e48\u0e21\u0e40\u0e15\u0e34\u0e21 \u0e2a\u0e32\u0e21\u0e32\u0e23\u0e16\u0e15\u0e34\u0e14\u0e15\u0e48\u0e2d :<\/span><br \/>\n<span style=\"color: #5c5c5c;\">\u0e40\u0e08\u0e49\u0e32\u0e2b\u0e19\u0e49\u0e32\u0e17\u0e35\u0e48\u0e18\u0e38\u0e23\u0e01\u0e32\u0e23\/\u0e1d\u0e48\u0e32\u0e22\u0e27\u0e34\u0e0a\u0e32\u0e01\u0e32\u0e23 \u0e42\u0e17\u0e23\u0e28\u0e31\u0e1e\u0e17\u0e4c 02 713 0922-4<\/span><br \/>\n<span style=\"color: #5c5c5c;\">For assistance, contact Reception or the Academic Department at 02 713 0922-4<\/span><\/p>\n<p><strong><span style=\"color: #ff0000;\">\u0e25\u0e07\u0e17\u0e30\u0e40\u0e1a\u0e35\u0e22\u0e19\u0e2a\u0e21\u0e31\u0e04\u0e23\u0e20\u0e32\u0e22\u0e43\u0e19: \u0e27\u0e31\u0e19\u0e08\u0e31\u0e19\u0e17\u0e23\u0e4c\u0e17\u0e35\u0e48 18 \u0e1e\u0e24\u0e29\u0e20\u0e32\u0e04\u0e21 2569<\/span><\/strong><br \/>\n* \u0e2b\u0e32\u0e01\u0e25\u0e07\u0e17\u0e30\u0e40\u0e1a\u0e35\u0e22\u0e19\u0e41\u0e25\u0e30\u0e0a\u0e33\u0e23\u0e30\u0e40\u0e07\u0e34\u0e19\u0e40\u0e01\u0e34\u0e19\u0e01\u0e33\u0e2b\u0e19\u0e14\u0e40\u0e27\u0e25\u0e32 \u0e23\u0e32\u0e04\u0e32\u0e08\u0e30\u0e40\u0e1e\u0e34\u0e48\u0e21\u0e02\u0e36\u0e49\u0e19 500.- \u0e1a\u0e32\u0e17 *<br \/>\n<strong><span style=\"color: #ff0000;\">Application deadline: MONDAY, 18 MAY 2026<\/span><\/strong><br \/>\n* Prices are for early applications. The cost is \u0e3f500 higher after the deadline. *<\/p>\n<p>&nbsp;<\/p>\n<style>\r\n  .spinner { \r\n    border: 4px solid #f3f3f3; border-top: 4px solid #494BB3; border-radius: 50%; \r\n    width: 24px; height: 24px; animation: spin 1s linear infinite; display: inline-block; vertical-align: middle; margin-right: 8px; \r\n  }\r\n  @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }\r\n  \r\n  \/* OVERRIDE THEME HEADING SIZES *\/\r\n  #main-form-title, #success-container h2 {\r\n    font-size: 1.8em !important;\r\n    line-height: 1.3 !important;\r\n  }\r\n\r\n  \/* BASE QUESTION CONTAINER *\/\r\n  .question-container {\r\n    padding: 15px;\r\n    border: 2px solid transparent; \r\n    border-radius: 8px;\r\n    transition: background-color 0.3s, border-color 0.3s;\r\n    margin-bottom: 15px !important; \r\n  }\r\n\r\n  \/* OVERRIDE THEME INPUT\/SELECT FONT SIZES *\/\r\n  .question-container input[type=\"text\"],\r\n  .question-container input[type=\"email\"],\r\n  .question-container input[type=\"number\"],\r\n  .question-container select {\r\n    font-size: 16px !important; \r\n    font-family: inherit !important;\r\n    padding: 10px !important;\r\n    box-sizing: border-box !important;\r\n    height: auto !important;\r\n  }\r\n  \r\n  \/* SUBTLE BOX FOR MULTIPLE SELECTION GROUPS *\/\r\n  .checkbox-group-box {\r\n    background-color: #f8f9fa;\r\n    border: 1px solid #dee2e6;\r\n    border-radius: 6px;\r\n    padding: 12px;\r\n    margin-top: 8px;\r\n  }\r\n\r\n  \/* INDIVIDUAL OPTION WRAPPERS *\/\r\n  .opt-wrapper {\r\n    margin-bottom: 4px;\r\n    padding: 4px 6px; \r\n    border-radius: 6px;\r\n    border: 1px solid transparent;\r\n    transition: all 0.2s ease;\r\n    font-size: 16px !important; \r\n    line-height: 1.4 !important;\r\n    display: flex !important;           \r\n    align-items: flex-start !important; \r\n    justify-content: flex-start !important;\r\n    gap: 10px !important;               \r\n  }\r\n  \r\n  \/* FORCE CHECKBOX\/RADIO STYLES *\/\r\n  .opt-wrapper input[type=\"checkbox\"],\r\n  .opt-wrapper input[type=\"radio\"] {\r\n    margin: 3px 0 0 0 !important; \r\n    flex-shrink: 0 !important;    \r\n    width: 18px !important;       \r\n    height: 18px !important;      \r\n    min-width: 18px !important;\r\n    display: block !important;\r\n    appearance: auto !important;\r\n    cursor: pointer;\r\n  }\r\n\r\n  .selected-opt {\r\n    background-color: #d4edda !important; \r\n    border-color: #c3e6cb !important;\r\n  }\r\n\r\n  .disabled-option { color: #a0a0a0; font-style: italic; }\r\n  .disabled-option input { cursor: not-allowed; }\r\n  \r\n  \/* ERROR HIGHLIGHT *\/\r\n  .persistent-highlight {\r\n    background-color: #fff3cd !important; \r\n    border-color: #ffb300 !important;\r\n  }\r\n  \r\n  .custom-file-upload {\r\n    display: inline-block; padding: 10px 20px; cursor: pointer;\r\n    background-color: #f0f0f0; border: 1px solid #ccc; border-radius: 5px;\r\n    font-weight: bold; color: #333; transition: background 0.2s;\r\n  }\r\n  .custom-file-name { margin-left: 10px; color: #555; font-style: italic; font-size: 0.9em; }\r\n  \r\n  .submit-btn {\r\n    padding: 12px 35px; font-size: 1.2em; background-color: #28a745; color: white;\r\n    border: none; border-radius: 8px; cursor: pointer; font-weight: bold;\r\n    transition: background-color 0.3s, transform 0.1s;\r\n  }\r\n  .submit-btn:hover:not(.looks-disabled) { background-color: #218838; transform: scale(1.02); }\r\n  \r\n  \/* Pseudo-disabled state (allows clicking for validation jumping) *\/\r\n  .submit-btn.looks-disabled { \r\n    background-color: #9e9e9e; \r\n    transform: none; \r\n  }\r\n<\/style>\r\n\r\n<div id=\"custom-alert-modal\" style=\"display:none; position:fixed !important; z-index:999999 !important; top:0 !important; left:0 !important; width:100vw !important; height:100vh !important; max-width:none !important; margin:0 !important; padding:0 !important; box-sizing:border-box !important; background:rgba(0,0,0,0.6); align-items:center; justify-content:center;\">\r\n  <div style=\"background:white; padding:30px; border-radius:8px; max-width:400px; width:90%; text-align:center; box-shadow:0 10px 25px rgba(0,0,0,0.3); font-family:sans-serif;\">\r\n    <h3 style=\"color:#d9534f; margin-top:0; border-bottom: 2px solid #eee; padding-bottom: 10px;\">Selection Unavailable<\/h3>\r\n    <p id=\"custom-alert-msg\" style=\"font-size:1.1em; color:#333; margin:20px 0;\"><\/p>\r\n    <button id=\"custom-alert-btn\" style=\"background:#494BB3; color:white; border:none; padding:12px 25px; border-radius:5px; font-size:1em; font-weight:bold; cursor:pointer;\">OK<\/button>\r\n  <\/div>\r\n<\/div>\r\n\r\n<div id=\"lightbox-modal\" style=\"display:none; position:fixed !important; z-index:999999 !important; top:0 !important; left:0 !important; width:100vw !important; height:100vh !important; max-width:none !important; margin:0 !important; padding:0 !important; background:rgba(0,0,0,0.9); align-items: center; justify-content: center; overflow: hidden;\">\r\n  <div id=\"lightbox-close\" style=\"position:absolute; top:20px; right:30px; color:white; font-size:30px; font-weight:bold; cursor:pointer; background:rgba(0,0,0,0.7); border-radius:50%; width:45px; height:45px; display:flex; align-items:center; justify-content:center; z-index:1000000; box-shadow: 0 0 10px rgba(0,0,0,0.5);\">&times;<\/div>\r\n  <img id=\"lightbox-img\" style=\"max-width:98% !important; max-height:98% !important; object-fit:contain; transition: transform 0.3s ease; cursor: zoom-in;\">\r\n<\/div>\r\n\r\n<form id=\"data-form\" style=\"max-width: 600px; margin: auto;\">\r\n  \r\n  <div id=\"form-header-container\" style=\"text-align:center; margin-bottom: 20px;\">\r\n    <h2 id=\"main-form-title\" style=\"margin-bottom: 5px; color: #494BB3;\"><\/h2>\r\n    <div id=\"closed-message\" style=\"display:none; color: red; font-weight: bold; font-size: 1.2em; margin-top: 20px;\">Sorry. This form is currently not open.<\/div>\r\n  <\/div>\r\n\r\n  <div id=\"form-error-banner\" style=\"color:red; font-weight:bold; margin-bottom: 15px;\"><\/div>\r\n\r\n  <div id=\"form-body-wrapper\" style=\"display:none;\">\r\n    <div class=\"fixed-field question-container\">\r\n      <label style=\"font-weight: bold;\">Email address<\/label><br>\r\n      <input type=\"email\" name=\"Email address\" required style=\"width: 100%;\">\r\n    <\/div>\r\n    \r\n    <div class=\"fixed-field question-container\">\r\n      <label style=\"font-weight: bold;\">Parent's name<\/label>\r\n      <p style=\"font-size:0.9em; color:black; margin:2px 0 8px 0; white-space: pre-wrap;\">(Please type in English)<\/p>\r\n      <input type=\"text\" name=\"Parent's name\" required style=\"width: 100%;\">\r\n    <\/div>\r\n\r\n    <div class=\"fixed-field question-container\">\r\n      <label style=\"font-weight: bold;\">Phone number<\/label><br>\r\n      <input type=\"text\" name=\"Phone number\" required style=\"width: 100%;\">\r\n    <\/div>\r\n\r\n    <div class=\"fixed-field question-container\">\r\n      <label for=\"grade-select\" style=\"font-weight: bold;\">Grade<\/label><br>\r\n      <p id=\"grade-desc\" style=\"font-size:0.9em; color:black; margin:2px 0 8px 0; white-space: pre-wrap; display:none;\"><\/p>\r\n      <select id=\"grade-select\" name=\"Grade\" required style=\"width: 100%;\">\r\n        <option value=\"\">--Select--<\/option>\r\n      <\/select>\r\n    <\/div>\r\n\r\n    <div id=\"dynamic-loader\" style=\"text-align: center; padding: 20px; color: #555; font-weight: bold; font-size: 1.1em; background: #f9f9f9; border-radius: 8px; border: 1px dashed #ccc; margin-top: 40px; min-height: 85px; display: flex; align-items: center; justify-content: center; box-sizing: border-box;\">\r\n      <div id=\"loader-content\" style=\"display:flex; align-items:center; justify-content:center;\">\r\n        <div class=\"spinner\"><\/div> LOADING FORM...\r\n      <\/div>\r\n    <\/div>\r\n\r\n    <div id=\"dynamic-questions-container\"><\/div>\r\n\r\n    <div id=\"global-error-warning\" style=\"display:none; color:red; font-weight:bold; margin-bottom: 10px; margin-top: 20px; padding:10px; border:1px solid red; background-color:#ffe6e6; border-radius: 4px;\">\r\n      ERROR: PLEASE REVIEW THE FORM ABOVE AND FIX HIGHLIGHTED ISSUES.\r\n    <\/div>\r\n\r\n    <div style=\"display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px; margin-top: 35px; margin-bottom: 20px;\">\r\n      <button type=\"submit\" id=\"submit-button\" class=\"submit-btn looks-disabled\">&#10003; Submit<\/button>\r\n      <span id=\"incomplete-warning\" style=\"color: gray; font-size: 0.95em; font-weight: bold;\">(Please complete all questions)<\/span>\r\n    <\/div>\r\n    \r\n    <div id=\"status-message\" style=\"margin-top: 15px; font-weight: bold; color: #494BB3; text-align: center;\"><\/div>\r\n  <\/div>\r\n<\/form>\r\n\r\n<div id=\"success-container\" style=\"display:none; border: 2px solid #4CAF50; padding: 20px; max-width: 600px; margin: auto; border-radius: 8px; font-family: sans-serif;\">\r\n  <h2 style=\"color: #4CAF50; margin-top: 0;\">\u2713 Submission Successful!<\/h2>\r\n  <p>Your form has been received. (Click below to save a copy for your own records.)<\/p>\r\n  <div id=\"receipt-text\" style=\"background: #f4f4f4; border: 1px solid #ddd; padding: 15px; margin-bottom: 15px; font-family: sans-serif; font-size: 15px; max-height: 400px; overflow-y: auto;\"><\/div>\r\n  \r\n  <div style=\"display: flex; flex-direction: column; gap: 10px; align-items: center;\">\r\n    <button id=\"save-receipt-btn\" style=\"background: #008CBA; color: white; padding: 10px 15px; border: none; border-radius: 4px; cursor: pointer; font-size: 1.1em; font-weight:bold; width: 100%; max-width: 300px;\">\r\n      <span style=\"font-size:1.2em; vertical-align:middle;\">\ud83d\udce5<\/span> Save Receipt as Image\r\n    <\/button>\r\n    \r\n    <button id=\"new-form-btn\" style=\"background: #6c757d; color: white; padding: 10px 15px; border: none; border-radius: 4px; cursor: pointer; font-size: 1.1em; font-weight:bold; width: 100%; max-width: 300px; display: none;\">\r\n      <span style=\"font-size:1.2em; vertical-align:middle;\">\ud83d\udcc4<\/span> NEW FORM\r\n    <\/button>\r\n  <\/div>\r\n<\/div>\r\n\r\n<script>\r\n  \/\/ ================= CONFIGURATION =================\r\n  const SCRIPT_URL = \"https:\/\/script.google.com\/macros\/s\/AKfycbyTEDgjuS9fXTmsQqttAI2IBiSeJhvGp0pj6nkROjP1vRbs1jwEyGn809vFNIR4oX_s\/exec\";\r\n  \r\n  let FORM_TITLE = \"Form Registration\"; \/\/ Set dynamically below\r\n  const FORM_STATUS = \"OPEN\"; \r\n  \r\n  const FORM_GRADES = [\"G.1\", \"G.2\", \"G.3\", \"G.4\", \"G.5\", \"G.6\", \"G.7\", \"G.8\", \"G.9\"];\r\n  const GRADE_DESC = \"\"; \r\n  \/\/ =================================================\r\n\r\n  let formConfig = {}; \r\n  window.currentReceiptData = { total: 0, subtotal: 0, discount: 0, mainItems: [], adjustingItems: [] };\r\n\r\n  async function fetchWithRetry(url, options = {}, retries = 3, delay = 2000) {\r\n    for (let i = 0; i < retries; i++) {\r\n      try {\r\n        const res = await fetch(url, options);\r\n        return await res.json();\r\n      } catch (err) {\r\n        if (i === retries - 1) throw err;\r\n        await new Promise(r => setTimeout(r, delay));\r\n      }\r\n    }\r\n  }\r\n\r\n  function getFormattedDate() {\r\n    const d = new Date();\r\n    const day = String(d.getDate()).padStart(2, '0');\r\n    const month = d.toLocaleString('en-US', { month: 'short' });\r\n    const year = d.getFullYear();\r\n    const time = d.toLocaleTimeString('en-GB', { hour12: false }); \r\n    return `${day}-${month}-${year} ${time}`;\r\n  }\r\n\r\ndocument.addEventListener('DOMContentLoaded', async () => {\r\n    \r\n    let extractedTitle = \"\";\r\n\r\n    \/\/ 1. Priority: Find the first plain <h1> tag without any class attributes\r\n    const plainH1s = document.querySelectorAll('h1:not([class])');\r\n    for (let i = 0; i < plainH1s.length; i++) {\r\n      const txt = plainH1s[i].textContent.trim();\r\n      if (txt.length > 0) {\r\n        extractedTitle = txt;\r\n        break;\r\n      }\r\n    }\r\n\r\n    \/\/ 2. Fallback: Try standard WordPress\/Elementor title classes if no plain H1 exists\r\n    if (!extractedTitle) {\r\n      const wpTitleEl = document.querySelector('h1.entry-title, h1.page-title, h1.post-title, h1.elementor-heading-title, .wp-block-post-title');\r\n      if (wpTitleEl && wpTitleEl.textContent.trim()) {\r\n        extractedTitle = wpTitleEl.textContent.trim();\r\n      }\r\n    }\r\n\r\n    \/\/ 3. Final Fallback: Use Document Title and slice off the appended WordPress site name\r\n    if (!extractedTitle && document.title && document.title.trim() !== \"\") {\r\n      const cleanTitle = document.title.split(\/[-|]\/)[0].trim();\r\n      extractedTitle = cleanTitle ? cleanTitle : document.title.trim();\r\n    }\r\n\r\n    \/\/ Apply the title if we found one\r\n    if (extractedTitle) {\r\n      FORM_TITLE = extractedTitle;\r\n    }\r\n    \r\n    document.getElementById('main-form-title').textContent = FORM_TITLE;\r\n    if (FORM_STATUS.toUpperCase() === 'CLOSED') {\r\n      document.getElementById('closed-message').style.display = 'block';\r\n      return; \r\n    }\r\n\r\n    const form = document.getElementById('data-form');\r\n    const formBody = document.getElementById('form-body-wrapper');\r\n    const gradeSelect = document.getElementById('grade-select');\r\n    const dynamicContainer = document.getElementById('dynamic-questions-container');\r\n    const dynamicLoader = document.getElementById('dynamic-loader');\r\n    const loaderContent = document.getElementById('loader-content');\r\n    const submitBtn = document.getElementById('submit-button');\r\n    const warningSpan = document.getElementById('incomplete-warning');\r\n    const globalError = document.getElementById('global-error-warning');\r\n    \r\n    document.getElementById('new-form-btn').addEventListener('click', () => { window.location.reload(); });\r\n\r\n    if (GRADE_DESC) {\r\n      const gDesc = document.getElementById('grade-desc');\r\n      gDesc.textContent = GRADE_DESC; gDesc.style.display = 'block';\r\n    }\r\n    FORM_GRADES.forEach(grade => {\r\n      const opt = document.createElement('option');\r\n      opt.value = grade; opt.textContent = grade; gradeSelect.appendChild(opt);\r\n    });\r\n\r\n    formBody.style.display = 'block'; \r\n\r\n    const customAlert = document.getElementById('custom-alert-modal');\r\n    const customAlertMsg = document.getElementById('custom-alert-msg');\r\n    document.getElementById('custom-alert-btn').addEventListener('click', () => { customAlert.style.display = 'none'; });\r\n\r\n    const lightbox = document.getElementById('lightbox-modal');\r\n    const lightboxImg = document.getElementById('lightbox-img');\r\n    const lightboxClose = document.getElementById('lightbox-close');\r\n    let isZoomed = false;\r\n\r\n    const closeLightbox = (e) => {\r\n      if(e) e.stopPropagation(); lightbox.style.display = 'none'; isZoomed = false;\r\n      lightboxImg.style.transform = 'scale(1)'; lightboxImg.style.cursor = 'zoom-in';\r\n    };\r\n    lightboxClose.addEventListener('click', closeLightbox);\r\n    lightbox.addEventListener('click', closeLightbox); \r\n    lightboxImg.addEventListener('click', (e) => {\r\n      e.stopPropagation(); \r\n      if(!isZoomed) { lightboxImg.style.transform = 'scale(1.5)'; lightboxImg.style.cursor = 'zoom-out'; isZoomed = true; } \r\n      else { lightboxImg.style.transform = 'scale(1)'; lightboxImg.style.cursor = 'zoom-in'; isZoomed = false; }\r\n    });\r\n    \r\n    try {\r\n      const result = await fetchWithRetry(`${SCRIPT_URL}?action=getConfig`);\r\n      if (result.status !== 'success') throw new Error(result.message);\r\n      formConfig = result.config;\r\n\r\n      loaderContent.innerHTML = '<span style=\"font-size: 1.2em; margin-right: 8px;\">\u23f3<\/span> Waiting for answers above \/ \u0e01\u0e33\u0e25\u0e31\u0e07\u0e23\u0e2d\u0e04\u0e33\u0e15\u0e2d\u0e1a\u0e14\u0e49\u0e32\u0e19\u0e1a\u0e19';\r\n      dynamicLoader.style.color = '#888';\r\n      dynamicLoader.style.cursor = 'not-allowed';\r\n      \r\n      buildDynamicQuestions();\r\n      validateMasterFormState();\r\n      \r\n    } catch (err) {\r\n      dynamicLoader.style.display = 'none';\r\n      document.getElementById('form-error-banner').innerHTML = `<h3>ERROR: Configuration error. Please refresh or inform the school. (${err.message})<\/h3>`;\r\n    }\r\n\r\n    form.addEventListener('input', validateMasterFormState);\r\n    form.addEventListener('change', () => {\r\n      let total = 0; let subtotal = 0; let discount = 0; \r\n      const mItems = []; const adjItems = [];\r\n      \r\n      const activeInputs = form.querySelectorAll('input[type=\"radio\"]:checked, input[type=\"checkbox\"]:checked, option:checked');\r\n      activeInputs.forEach(el => {\r\n        let text = el.tagName === 'OPTION' ? el.textContent : el.value;\r\n        const match = text.match(\/\u0e3f\\s?(-?[\\d,]+)\/); \r\n        if (match) {\r\n          const val = parseInt(match[1].replace(\/,\/g, ''), 10);\r\n          total += val;\r\n          const cleanDesc = text.replace(\/\\[UNAVAILABLE\\\/FULL\\]\/gi, '').trim();\r\n          \r\n          if (val < 0) {\r\n            discount += val;\r\n            adjItems.push({ price: `\u0e3f${val.toLocaleString()}`, desc: cleanDesc, isNegative: true });\r\n          } else if (text.toLowerCase().includes('deadline')) {\r\n            adjItems.push({ price: `\u0e3f${val.toLocaleString()}`, desc: cleanDesc, isNegative: false });\r\n          } else {\r\n            subtotal += val;\r\n            mItems.push({ price: `\u0e3f${val.toLocaleString()}`, desc: cleanDesc });\r\n          }\r\n        }\r\n      });\r\n\r\n      window.currentReceiptData = {\r\n          total: total, subtotal: subtotal, discount: discount, mainItems: mItems, adjustingItems: adjItems\r\n      };\r\n\r\n      document.querySelectorAll('.opt-wrapper').forEach(wrapper => {\r\n        const input = wrapper.querySelector('input');\r\n        if (input && input.checked) {\r\n          wrapper.classList.add('selected-opt');\r\n        } else {\r\n          wrapper.classList.remove('selected-opt');\r\n        }\r\n      });\r\n\r\n      document.querySelectorAll('.calculated-total-val').forEach(el => {\r\n        const displayTotal = total < 0 ? 0 : total;\r\n        el.textContent = displayTotal.toLocaleString();\r\n        \r\n        let parent = el.closest('.total-box-container'); \r\n        if(!parent) return;\r\n\r\n        let note = parent.querySelector('.discount-note');\r\n        if(!note) { note = document.createElement('div'); note.className = 'discount-note'; note.style.fontSize = '0.7em'; note.style.fontWeight = 'normal'; note.style.marginTop = '5px'; note.style.color = '#555'; parent.appendChild(note); }\r\n        if (discount < 0) { note.textContent = `(Discount applied: \u0e3f${discount.toLocaleString()})`; } \r\n        else { note.textContent = ''; }\r\n\r\n        let itemizedContainer = parent.querySelector('.itemized-receipt');\r\n        if (itemizedContainer) {\r\n            if (mItems.length > 0 || adjItems.length > 0) {\r\n                itemizedContainer.style.display = 'block';\r\n                let html = '<table style=\"width: 100%; border-collapse: collapse; font-size:0.9em; margin-bottom: 8px;\">';\r\n                \r\n                mItems.forEach(item => {\r\n                    html += `<tr>\r\n                        <td style=\"width: 85px; vertical-align: top; padding-bottom: 6px;\"><strong>${item.price}<\/strong><\/td>\r\n                        <td style=\"vertical-align: top; padding-bottom: 6px;\">${item.desc}<\/td>\r\n                    <\/tr>`;\r\n                });\r\n                \r\n                if (mItems.length > 0 || adjItems.length > 0) {\r\n                    html += `<tr>\r\n                        <td colspan=\"2\" style=\"text-align: right; border-top: 1px dashed #ccc; padding-top: 6px; padding-bottom: 6px; font-weight: bold; color: #555;\">Subtotal: \u0e3f${subtotal.toLocaleString()}<\/td>\r\n                    <\/tr>`;\r\n                }\r\n\r\n                adjItems.forEach(item => {\r\n                    const colorStyle = item.isNegative ? 'color: #28a745;' : 'color: #333;';\r\n                    html += `<tr>\r\n                        <td style=\"width: 85px; vertical-align: top; padding-bottom: 6px; ${colorStyle}\"><strong>${item.price}<\/strong><\/td>\r\n                        <td style=\"vertical-align: top; padding-bottom: 6px; ${colorStyle}\">${item.desc}<\/td>\r\n                    <\/tr>`;\r\n                });\r\n\r\n                html += '<\/table>';\r\n                itemizedContainer.innerHTML = html;\r\n            } else {\r\n                itemizedContainer.style.display = 'none';\r\n                itemizedContainer.innerHTML = '';\r\n            }\r\n        }\r\n      });\r\n      validateMasterFormState();\r\n    });\r\n\r\n    function buildDynamicQuestions() {\r\n      if (!formConfig.questions) return;\r\n      for (const [title, configData] of Object.entries(formConfig.questions)) {\r\n        const wrapper = document.createElement('div');\r\n        wrapper.className = 'question-container';\r\n        wrapper.setAttribute('data-qtitle', title);\r\n        wrapper.style.display = 'none'; \r\n\r\n        const rawType = configData.type;\r\n\r\n        if (rawType === 'Section_Heading') {\r\n          wrapper.style.marginTop = '40px'; \r\n          wrapper.style.padding = '0';\r\n          wrapper.style.border = 'none';\r\n          wrapper.innerHTML = `<div style=\"background-color: #494BB3; color: white; padding: 12px; border-radius: 8px; font-weight: bold; font-size: 1.1em; width: 100%; box-sizing: border-box;\">${title}<\/div>`;\r\n          if (configData.desc) wrapper.innerHTML += `<p style=\"font-size:0.9em; color:black; margin-top:5px; white-space: pre-wrap;\">${configData.desc}<\/p>`;\r\n          wrapper.classList.add('ui-element');\r\n          dynamicContainer.appendChild(wrapper);\r\n          continue;\r\n        }\r\n\r\n        if (rawType === 'Display_Total') {\r\n          wrapper.style.padding = '0'; wrapper.style.border = 'none';\r\n          wrapper.style.marginTop = '45px'; \r\n          wrapper.innerHTML = `<div class=\"total-box-container\" style=\"padding: 15px; border: 2px dashed #494BB3; border-radius: 8px; text-align: center; background: #f9f9f9;\">\r\n            <div class=\"itemized-receipt\" style=\"display:none; font-size: 0.85em; font-weight: normal; margin-bottom: 12px; text-align: left; border-bottom: 1px solid #ccc; padding-bottom: 8px; color: #333;\"><\/div>\r\n            <div style=\"font-size: 1.3em; font-weight: bold; color: #000;\">${title}: \u0e3f<span class=\"calculated-total-val\">0<\/span><\/div>\r\n          <\/div>`;\r\n          wrapper.classList.add('ui-element');\r\n          dynamicContainer.appendChild(wrapper);\r\n          continue;\r\n        }\r\n\r\n        if (rawType === 'Image') {\r\n          wrapper.innerHTML = `<h3 style=\"margin-bottom: 5px;\">${title}<\/h3>`;\r\n          if (configData.desc) wrapper.innerHTML += `<p style=\"font-size:0.9em; color:black; margin-top:0; white-space: pre-wrap;\">${configData.desc}<\/p>`;\r\n          \r\n          configData.options.forEach(opt => {\r\n            if(opt.text) {\r\n              const imgEl = document.createElement('img');\r\n              imgEl.src = opt.text;\r\n              imgEl.style.width = '100%'; imgEl.style.height = 'auto'; imgEl.style.borderRadius = '8px';\r\n              imgEl.style.marginBottom = '10px'; imgEl.style.cursor = 'zoom-in'; imgEl.style.border = '1px solid #ccc';\r\n              imgEl.onclick = () => { document.getElementById('lightbox-img').src = opt.text; lightbox.style.display = 'flex'; };\r\n              wrapper.appendChild(imgEl);\r\n            }\r\n          });\r\n          wrapper.classList.add('ui-element');\r\n          dynamicContainer.appendChild(wrapper);\r\n          continue;\r\n        }\r\n\r\n        const label = document.createElement('label');\r\n        label.textContent = title; label.style.fontWeight = 'bold';\r\n        wrapper.appendChild(label);\r\n\r\n        if (configData.desc) {\r\n          const desc = document.createElement('p');\r\n          desc.textContent = configData.desc;\r\n          desc.style.fontSize = '0.9em'; desc.style.color = 'black'; desc.style.margin = '2px 0 8px 0'; desc.style.whiteSpace = 'pre-wrap'; \r\n          wrapper.appendChild(desc);\r\n        }\r\n\r\n        const inputContainer = document.createElement('div');\r\n        inputContainer.className = 'q-input-container';\r\n        wrapper.appendChild(inputContainer);\r\n\r\n        dynamicContainer.appendChild(wrapper);\r\n      }\r\n    }\r\n\r\n    gradeSelect.addEventListener('change', (e) => {\r\n      const selectedGradeStr = e.target.value;\r\n      const gradeNumMatch = selectedGradeStr.match(\/\\d+\/);\r\n      const gradeNum = gradeNumMatch ? gradeNumMatch[0] : \"\";\r\n      \r\n      if (gradeNum) { dynamicLoader.style.display = 'none'; } \r\n      else { dynamicLoader.style.display = 'flex'; }\r\n\r\n      const qContainers = dynamicContainer.querySelectorAll('.question-container');\r\n      \r\n      qContainers.forEach(container => {\r\n        const title = container.getAttribute('data-qtitle');\r\n        const configData = formConfig.questions[title];\r\n        \r\n        let showQuestion = true;\r\n        if (configData.gradesAllowed.length > 0) { showQuestion = configData.gradesAllowed.includes(gradeNum); }\r\n        container.style.display = showQuestion ? 'block' : 'none';\r\n\r\n        if (!container.classList.contains('ui-element')) {\r\n          if (showQuestion) renderInputForQuestion(container, configData, title, gradeNum);\r\n          else container.querySelector('.q-input-container').innerHTML = '';\r\n        }\r\n      });\r\n      validateMasterFormState(); \r\n      form.dispatchEvent(new Event('change')); \r\n    });\r\n\r\n    function renderInputForQuestion(container, configData, title, currentGradeNum) {\r\n      const inputWrapper = container.querySelector('.q-input-container');\r\n      inputWrapper.innerHTML = ''; \r\n      inputWrapper.className = 'q-input-container'; \r\n      \r\n      let qType = configData.type;\r\n      \r\n      if (qType === 'Attach_Image') {\r\n        const uploadWrapper = document.createElement('div');\r\n        \r\n        const fileLabel = document.createElement('label');\r\n        fileLabel.className = 'custom-file-upload';\r\n        fileLabel.innerHTML = '\ud83d\udce4 Choose File...';\r\n        \r\n        const input = document.createElement('input');\r\n        input.type = 'file'; \r\n        input.name = title; \r\n        input.accept = \".jpg, .jpeg, .png, image\/jpeg, image\/png\";\r\n        input.style.display = 'none'; \r\n\r\n        const fileNameDisplay = document.createElement('span');\r\n        fileNameDisplay.className = 'custom-file-name';\r\n        fileNameDisplay.textContent = 'No file chosen';\r\n\r\n        input.addEventListener('change', (e) => {\r\n          fileNameDisplay.textContent = e.target.files[0] ? e.target.files[0].name : 'No file chosen';\r\n          validateMasterFormState();\r\n        });\r\n\r\n        fileLabel.appendChild(input);\r\n        uploadWrapper.appendChild(fileLabel);\r\n        uploadWrapper.appendChild(fileNameDisplay);\r\n        inputWrapper.appendChild(uploadWrapper);\r\n        return;\r\n      }\r\n\r\n      let regexPattern = null;\r\n      if (qType.startsWith('Input_Text')) {\r\n        const match = qType.match(\/Input_Text\\((.+)\\)\/);\r\n        if (match) regexPattern = match[1]; qType = 'Input_Text'; \r\n      }\r\n\r\n      if (['Input_Text', 'Input_Number'].includes(qType)) {\r\n        const input = document.createElement('input');\r\n        input.type = qType === 'Input_Number' ? 'number' : 'text';\r\n        input.name = title; input.style.width = '100%';\r\n        inputWrapper.appendChild(input);\r\n\r\n        if (regexPattern) {\r\n          const errorSpan = document.createElement('div');\r\n          errorSpan.className = 'regex-error'; errorSpan.style.color = 'red'; errorSpan.style.fontWeight = 'bold'; errorSpan.style.fontSize = '0.85em';\r\n          errorSpan.style.marginTop = '4px'; errorSpan.style.display = 'none'; errorSpan.textContent = `ERROR: Please match the required format.`;\r\n          inputWrapper.appendChild(errorSpan);\r\n\r\n          input.addEventListener('focus', function() { errorSpan.style.display = 'none'; this.classList.remove('is-invalid'); });\r\n          input.addEventListener('blur', function() {\r\n            if (this.value) {\r\n              try {\r\n                const isValid = new RegExp(regexPattern).test(this.value);\r\n                if (!isValid) { errorSpan.style.display = 'block'; this.classList.add('is-invalid'); } \r\n                else { errorSpan.style.display = 'none'; this.classList.remove('is-invalid'); }\r\n              } catch(e) {}\r\n            } else { errorSpan.style.display = 'none'; this.classList.remove('is-invalid'); }\r\n            validateMasterFormState();\r\n          });\r\n        }\r\n        return;\r\n      }\r\n\r\n      if (qType === 'Select_Dropdown') {\r\n        const select = document.createElement('select');\r\n        select.name = title; select.style.width = '100%';\r\n        const defaultOpt = document.createElement('option'); defaultOpt.value = \"\"; defaultOpt.textContent = \"--Select--\";\r\n        select.appendChild(defaultOpt);\r\n        \r\n        configData.options.forEach(opt => {\r\n          if (opt.optGradeLimits.length > 0 && !opt.optGradeLimits.includes(currentGradeNum)) return;\r\n          const optionEl = document.createElement('option'); \r\n          optionEl.value = opt.text; \r\n          \r\n          let isOptDisabled = opt.isDisabled || \/\\[UNAVAILABLE\\\/FULL\\]\/i.test(opt.text);\r\n          let optString = opt.text;\r\n          if (isOptDisabled && !optString.includes('[UNAVAILABLE\/FULL]')) { optString += \" (FULL)\"; }\r\n          \r\n          optionEl.textContent = optString;\r\n          if (isOptDisabled) { optionEl.disabled = true; }\r\n          \r\n          select.appendChild(optionEl);\r\n        });\r\n        inputWrapper.appendChild(select);\r\n        return;\r\n      }\r\n\r\n      if (['Select_Radio', 'Multiple_Selection', 'Checkbox'].includes(qType)) {\r\n        const isMultiple = qType === 'Multiple_Selection' || qType === 'Checkbox';\r\n        inputWrapper.classList.add('checkbox-group-box'); \r\n\r\n        configData.options.forEach(opt => {\r\n          if (opt.optGradeLimits.length > 0 && !opt.optGradeLimits.includes(currentGradeNum)) return;\r\n          \r\n          const optDiv = document.createElement('div'); \r\n          optDiv.className = 'opt-wrapper'; \r\n          \r\n          const input = document.createElement('input');\r\n          input.type = isMultiple ? 'checkbox' : 'radio'; \r\n          input.name = title; \r\n          input.value = opt.text; \r\n          \r\n          let extractedDays = [];\r\n          const bracketMatches = opt.text.match(\/\\[(.*?)\\]\/g);\r\n          if (bracketMatches) {\r\n            bracketMatches.forEach(bracket => {\r\n              const dayMatch = bracket.match(\/\\b(MON|TUE|WED|THU|FRI)\\b\/g);\r\n              if (dayMatch) extractedDays.push(...dayMatch);\r\n            });\r\n          }\r\n          extractedDays = [...new Set(extractedDays)];\r\n          if (extractedDays.length > 0) {\r\n            input.dataset.days = extractedDays.join(',');\r\n          }\r\n          \r\n          const lbl = document.createElement('label'); \r\n          lbl.style.cursor = 'pointer';\r\n          \r\n          let highlightedText = opt.text.replace(\/(\\{.*?\\})\/g, '<span style=\"color: #007bff; font-weight: bold;\">$1<\/span>');\r\n          highlightedText = highlightedText.replace(\/\\[UNAVAILABLE\\\/FULL\\]\/gi, '<span style=\"color: darkred; font-weight: normal;\">[UNAVAILABLE\/FULL]<\/span>');\r\n          \r\n          lbl.innerHTML = highlightedText; \r\n          \r\n          let isOptDisabled = opt.isDisabled || \/\\[UNAVAILABLE\\\/FULL\\]\/i.test(opt.text);\r\n          if (isOptDisabled) { \r\n            input.disabled = true; \r\n            lbl.classList.add('disabled-option'); \r\n            optDiv.style.cursor = 'not-allowed';\r\n            lbl.style.cursor = 'not-allowed';\r\n          }\r\n          \r\n          optDiv.appendChild(input); optDiv.appendChild(lbl); inputWrapper.appendChild(optDiv);\r\n        });\r\n      }\r\n    }\r\n\r\n    function validateMasterFormState() {\r\n      let isFormValid = true; let isIncomplete = false; \r\n\r\n      document.querySelectorAll('.question-container.skipped-highlight').forEach(c => c.classList.remove('skipped-highlight', 'persistent-highlight'));\r\n      \r\n      document.querySelectorAll('.day-warning-box').forEach(el => el.remove());\r\n      document.querySelectorAll('.question-container.clash-error').forEach(c => c.classList.remove('clash-error', 'persistent-highlight'));\r\n\r\n      const visibleContainers = Array.from(document.querySelectorAll('.question-container:not(.ui-element)')).filter(c => c.style.display !== 'none');\r\n      let firstAnsweredIdx = -1;\r\n      let lastAnsweredIdx = -1;\r\n\r\n      const statuses = visibleContainers.map((container, idx) => {\r\n        let answered = false;\r\n        const inputs = container.querySelectorAll('input, select');\r\n        if (inputs.length > 0) {\r\n          const type = inputs[0].type;\r\n          const tag = inputs[0].tagName.toUpperCase();\r\n          if (type === 'radio' || type === 'checkbox') {\r\n            if (container.querySelectorAll('input:checked').length > 0) answered = true;\r\n          } else {\r\n            if (inputs[0].value.trim() !== '') answered = true;\r\n          }\r\n        }\r\n        \r\n        if (answered) {\r\n          if (firstAnsweredIdx === -1) firstAnsweredIdx = idx;\r\n          lastAnsweredIdx = idx;\r\n        } else {\r\n          isIncomplete = true;\r\n        }\r\n        return { container, answered, idx };\r\n      });\r\n\r\n      statuses.forEach(status => {\r\n          if (status.answered) {\r\n              status.container.classList.remove('submit-highlight', 'skipped-highlight', 'persistent-highlight');\r\n          } else {\r\n              if (firstAnsweredIdx !== -1 && lastAnsweredIdx !== -1 && status.idx > firstAnsweredIdx && status.idx < lastAnsweredIdx) {\r\n                  status.container.classList.add('skipped-highlight', 'persistent-highlight');\r\n              }\r\n          }\r\n      });\r\n\r\n      const dayMap = {};\r\n      const allDayCheckboxes = document.querySelectorAll('input[type=\"checkbox\"]:checked, input[type=\"radio\"]:checked');\r\n\r\n      allDayCheckboxes.forEach(cb => {\r\n        if (cb.dataset.days) {\r\n          const daysArr = cb.dataset.days.split(',');\r\n          const container = cb.closest('.question-container');\r\n          daysArr.forEach(day => {\r\n            if (!dayMap[day]) dayMap[day] = [];\r\n            dayMap[day].push({ cb: cb, container: container, text: cb.value });\r\n          });\r\n        }\r\n      });\r\n\r\n      const containersWithErrors = new Map();\r\n\r\n      for (const [day, items] of Object.entries(dayMap)) {\r\n        if (items.length > 1) { \r\n          isFormValid = false;\r\n          items.forEach(item => {\r\n            if (!containersWithErrors.has(item.container)) {\r\n              containersWithErrors.set(item.container, new Set());\r\n            }\r\n            items.forEach(clashingItem => {\r\n                containersWithErrors.get(item.container).add(clashingItem.text);\r\n            });\r\n          });\r\n        }\r\n      }\r\n\r\n      containersWithErrors.forEach((clashingTexts, container) => {\r\n        container.classList.add('clash-error', 'persistent-highlight');\r\n        \r\n        const wDiv = document.createElement('div');\r\n        wDiv.className = 'day-warning-box';\r\n        wDiv.style.color = '#721c24';\r\n        wDiv.style.backgroundColor = '#f8d7da';\r\n        wDiv.style.border = '2px solid #f5c6cb';\r\n        wDiv.style.padding = '12px';\r\n        wDiv.style.marginTop = '15px';\r\n        wDiv.style.borderRadius = '5px';\r\n        wDiv.style.fontWeight = 'bold';\r\n        \r\n        let errorHtml = `ERROR: SAME DAYS! PLEASE CHOOSE AGAIN.<br><div style=\"margin-top: 8px; font-weight: normal;\">`;\r\n        clashingTexts.forEach(optText => {\r\n           errorHtml += `<div style=\"padding: 3px 0;\">\u2022 ${optText.replace(\/\\[UNAVAILABLE\\\/FULL\\]\/gi, '').trim()}<\/div>`;\r\n        });\r\n        errorHtml += `<\/div>`;\r\n        \r\n        wDiv.innerHTML = errorHtml;\r\n        container.querySelector('.q-input-container').appendChild(wDiv);\r\n      });\r\n\r\n      const invalidRegexInputs = document.querySelectorAll('.is-invalid');\r\n      if (invalidRegexInputs.length > 0) isFormValid = false;\r\n\r\n      if (!isFormValid || isIncomplete) { \r\n        submitBtn.classList.add('looks-disabled'); \r\n        if (!isFormValid) {\r\n            warningSpan.style.display = 'none'; globalError.style.display = 'block'; \r\n        } else {\r\n            warningSpan.style.display = 'inline'; globalError.style.display = 'none'; \r\n        }\r\n      } else { \r\n        submitBtn.classList.remove('looks-disabled'); \r\n        warningSpan.style.display = 'none'; globalError.style.display = 'none'; \r\n      }\r\n    }\r\n\r\n    submitBtn.addEventListener('click', (e) => {\r\n        if (submitBtn.classList.contains('looks-disabled')) {\r\n            e.preventDefault(); \r\n            \r\n            const visibleContainers = Array.from(document.querySelectorAll('.question-container:not(.ui-element)')).filter(c => c.style.display !== 'none');\r\n            let firstIssue = null;\r\n            \r\n            for (const container of visibleContainers) {\r\n                let answered = false;\r\n                const inputs = container.querySelectorAll('input, select');\r\n                if (inputs.length > 0) {\r\n                    const type = inputs[0].type;\r\n                    if (type === 'radio' || type === 'checkbox') {\r\n                        if (container.querySelectorAll('input:checked').length > 0) answered = true;\r\n                    } else {\r\n                        if (inputs[0].value.trim() !== '') answered = true;\r\n                    }\r\n                }\r\n                \r\n                if (!answered) {\r\n                    container.classList.add('submit-highlight', 'persistent-highlight');\r\n                    if (!firstIssue) firstIssue = container;\r\n                }\r\n            }\r\n            \r\n            const explicitError = document.querySelector('.is-invalid, .clash-error');\r\n            if (explicitError && !firstIssue) {\r\n                firstIssue = explicitError.closest('.question-container') || explicitError;\r\n            }\r\n            \r\n            if (firstIssue) {\r\n                const scrollTarget = firstIssue.closest('.question-container') || firstIssue;\r\n                scrollTarget.scrollIntoView({ behavior: 'smooth', block: 'center' });\r\n            }\r\n        }\r\n    });\r\n\r\n    form.addEventListener('submit', async (e) => {\r\n      e.preventDefault();\r\n      \r\n      submitBtn.classList.add('looks-disabled');\r\n      document.getElementById('status-message').style.color = '#494BB3';\r\n      document.getElementById('status-message').innerHTML = '<div class=\"spinner\"><\/div> Please wait (confirming availability)...';\r\n\r\n      const formData = new FormData(form); const answers = {};\r\n      \r\n      for (const [key, rawValue] of formData.entries()) {\r\n        if (rawValue instanceof File) continue; \r\n        \r\n        let value = rawValue;\r\n        if (typeof value === 'string' && value.startsWith('0')) {\r\n          value = \"'\" + value;\r\n        }\r\n\r\n        if (answers[key]) { \r\n          if (!Array.isArray(answers[key])) answers[key] = [answers[key]]; \r\n          answers[key].push(value); \r\n        } else { \r\n          answers[key] = value; \r\n        }\r\n      }\r\n\r\n      \/\/ --- FRONTEND PRE-CHECK ---\r\n      try {\r\n        const checkResult = await fetchWithRetry(`${SCRIPT_URL}?action=getConfig`);\r\n        if (checkResult.status === 'success') {\r\n          const latestConfig = checkResult.config;\r\n          let hasUnavailable = false;\r\n          let badQuestion = \"\";\r\n\r\n          for (const [qTitle, valArray] of Object.entries(answers)) {\r\n            const configQ = latestConfig.questions[qTitle];\r\n            if (!configQ) continue;\r\n            \r\n            const qType = configQ.type;\r\n            if (!['Select_Dropdown', 'Select_Radio', 'Multiple_Selection', 'Checkbox'].includes(qType)) {\r\n                continue; \r\n            }\r\n\r\n            const latestOptions = configQ.options;\r\n            if (!latestOptions || latestOptions.length === 0) continue;\r\n\r\n            const vals = Array.isArray(valArray) ? valArray : [valArray];\r\n            \r\n            for (let v of vals) {\r\n              if (v.startsWith(\"'0\")) {\r\n                v = v.substring(1);\r\n              }\r\n              const cleanSubmitted = v.replace(\/\\[UNAVAILABLE\\\/FULL\\]\/gi, '').trim();\r\n              \r\n              const matchedOpt = latestOptions.find(o => {\r\n                const cleanLatest = o.text.replace(\/\\[UNAVAILABLE\\\/FULL\\]\/gi, '').trim();\r\n                return cleanLatest === cleanSubmitted;\r\n              });\r\n\r\n              if (!matchedOpt || matchedOpt.isDisabled || \/\\[UNAVAILABLE\\\/FULL\\]\/i.test(matchedOpt.text)) {\r\n                hasUnavailable = true;\r\n                badQuestion = qTitle;\r\n                break;\r\n              }\r\n            }\r\n            if (hasUnavailable) break;\r\n          }\r\n\r\n          if (hasUnavailable) {\r\n            document.getElementById('status-message').innerHTML = ''; \r\n            const container = document.querySelector(`.question-container[data-qtitle=\"${CSS.escape(badQuestion)}\"]`);\r\n            if (container) {\r\n              container.classList.add('persistent-highlight');\r\n              container.scrollIntoView({ behavior: 'smooth', block: 'center' });\r\n              container.addEventListener('change', () => { container.classList.remove('persistent-highlight'); }, {once: true});\r\n            }\r\n            \r\n            customAlertMsg.innerHTML = `One of your selections is no longer available for:<br><br><b>\"${badQuestion}\"<\/b><br><br>Please choose again.`;\r\n            customAlert.style.display = 'flex';\r\n            \r\n            formConfig = latestConfig;\r\n            if (container) {\r\n              const gradeNumMatch = gradeSelect.value.match(\/\\d+\/); \r\n              const currentGradeNum = gradeNumMatch ? gradeNumMatch[0] : \"\";\r\n              renderInputForQuestion(container, formConfig.questions[badQuestion], badQuestion, currentGradeNum);\r\n              \r\n              const warningDiv = document.createElement('div');\r\n              warningDiv.style.color = 'red'; warningDiv.style.fontWeight = 'bold'; warningDiv.style.marginTop = '8px'; warningDiv.textContent = 'Please choose again.';\r\n              container.querySelector('.q-input-container').appendChild(warningDiv);\r\n            }\r\n            \r\n            globalError.innerHTML = `ERROR: One of your selections is no longer available for \"${badQuestion}\".`;\r\n            globalError.style.display = 'block'; \r\n            validateMasterFormState();\r\n            \r\n            return; \r\n          }\r\n        }\r\n      } catch(err) {\r\n        console.warn(\"Pre-check failed, continuing submission attempt.\", err);\r\n      }\r\n      \/\/ --- END FRONTEND PRE-CHECK ---\r\n\r\n      const payload = { answers: answers };\r\n      const fileInput = document.querySelector('input[type=\"file\"]');\r\n      if (fileInput && fileInput.files.length > 0) {\r\n        const file = fileInput.files[0]; payload.fileName = file.name; payload.fileType = file.type;\r\n        payload.fileData = await new Promise((resolve, reject) => {\r\n          const reader = new FileReader(); reader.onload = () => resolve(reader.result); reader.onerror = reject; reader.readAsDataURL(file);\r\n        });\r\n      }\r\n      \r\n      try {\r\n        const submitResult = await fetchWithRetry(SCRIPT_URL, { method: 'POST', mode: 'cors', body: JSON.stringify(payload) });\r\n        \r\n        if (submitResult.status === 'success') {\r\n          form.style.display = 'none';\r\n          const successContainer = document.getElementById('success-container');\r\n          const receiptTextDiv = document.getElementById('receipt-text');\r\n\r\n          let rHTML = `<div style=\"text-align:center; font-size:1.3em; font-weight:bold; margin-bottom:10px; color:#494BB3;\">${FORM_TITLE}<\/div>`;\r\n          rHTML += `<div style=\"text-align:center; margin-bottom:20px; color:#555;\">======== SUBMISSION RECEIPT ========<\/div>`;\r\n          rHTML += `<div>Date: ${getFormattedDate()}<\/div><br><br>`;\r\n          \r\n          for (const [key, value] of Object.entries(payload.answers)) {\r\n            let cleanVal = Array.isArray(value) ? value.map(v => v.startsWith(\"'0\") ? v.substring(1) : v) : (value.startsWith(\"'0\") ? value.substring(1) : value);\r\n            let valStr = Array.isArray(cleanVal) ? cleanVal.join('<br>') : cleanVal;\r\n            rHTML += `<div style=\"margin-bottom: 12px; color:#555;\">${key}:<br><strong style=\"color:#000; font-size:1.1em;\">${valStr}<\/strong><\/div>`;\r\n          }\r\n          \r\n          if (window.currentReceiptData && (window.currentReceiptData.mainItems.length > 0 || window.currentReceiptData.adjustingItems.length > 0)) {\r\n              rHTML += `<div style=\"margin-top: 15px; border-top:1px solid #ccc; padding-top:15px; color:#555;\">`;\r\n              rHTML += `<div style=\"margin-bottom: 10px;\"><strong>Itemized Summary:<\/strong><\/div>`;\r\n              rHTML += `<table style=\"width:100%; font-size: 0.95em; margin-bottom: 15px;\">`;\r\n              \r\n              window.currentReceiptData.mainItems.forEach(item => {\r\n                  rHTML += `<tr><td style=\"width:75px; vertical-align:top;\"><strong>${item.price}<\/strong><\/td><td style=\"vertical-align:top;\">${item.desc}<\/td><\/tr>`;\r\n              });\r\n              \r\n              if (window.currentReceiptData.mainItems.length > 0 || window.currentReceiptData.adjustingItems.length > 0) {\r\n                 rHTML += `<tr><td colspan=\"2\" style=\"text-align:right; border-top:1px dashed #aaa; padding-top:6px; padding-bottom:6px;\"><strong>Subtotal: \u0e3f${window.currentReceiptData.subtotal.toLocaleString()}<\/strong><\/td><\/tr>`;\r\n              }\r\n              \r\n              window.currentReceiptData.adjustingItems.forEach(item => {\r\n                  const colorStyle = item.isNegative ? 'color:#28a745;' : 'color:#333;';\r\n                  rHTML += `<tr><td style=\"width:75px; vertical-align:top; ${colorStyle}\"><strong>${item.price}<\/strong><\/td><td style=\"vertical-align:top; ${colorStyle}\">${item.desc}<\/td><\/tr>`;\r\n              });\r\n              \r\n              rHTML += `<\/table>`;\r\n              rHTML += `TOTAL CALCULATED:<br><strong style=\"color:#000; font-size:1.3em;\">\u0e3f${window.currentReceiptData.total.toLocaleString()}<\/strong>`;\r\n              if (window.currentReceiptData.discount < 0) {\r\n                  rHTML += `<div style=\"font-size:0.85em; color:#555;\">(Discount applied: \u0e3f${window.currentReceiptData.discount.toLocaleString()})<\/div>`;\r\n              }\r\n              rHTML += `<\/div>`;\r\n          }\r\n\r\n          receiptTextDiv.innerHTML = rHTML;\r\n          successContainer.style.display = 'block';\r\n\r\n          window.scrollTo({ top: 0, behavior: 'smooth' });\r\n\r\n          document.getElementById('save-receipt-btn').onclick = () => {\r\n            const linesToDraw = [];\r\n            linesToDraw.push({text: FORM_TITLE, type: 'title'});\r\n            linesToDraw.push({text: \"======== SUBMISSION RECEIPT ========\", type: 'header'});\r\n            linesToDraw.push({text: `Date: ${getFormattedDate()}`, type: 'normal'});\r\n            linesToDraw.push({text: \"\", type: 'normal'});\r\n            \r\n            for (const [key, value] of Object.entries(payload.answers)) {\r\n              linesToDraw.push({text: key + \":\", type: 'normal'});\r\n              let cleanVal = Array.isArray(value) ? value.map(v => v.startsWith(\"'0\") ? v.substring(1) : v) : (value.startsWith(\"'0\") ? value.substring(1) : value);\r\n              const valArr = Array.isArray(cleanVal) ? cleanVal : [cleanVal];\r\n              valArr.forEach(v => {\r\n                const vLines = v.split('\\n');\r\n                vLines.forEach(vl => linesToDraw.push({text: vl, type: 'bold'}));\r\n              });\r\n              linesToDraw.push({text: \"\", type: 'normal'});\r\n            }\r\n            \r\n            if (window.currentReceiptData && (window.currentReceiptData.mainItems.length > 0 || window.currentReceiptData.adjustingItems.length > 0)) {\r\n                linesToDraw.push({text: \"======== ITEMIZED SUMMARY ========\", type: 'header'});\r\n                linesToDraw.push({text: \"\", type: 'normal'});\r\n                window.currentReceiptData.mainItems.forEach(item => {\r\n                     linesToDraw.push({text: `${item.price}  ${item.desc}`, type: 'normal'});\r\n                });\r\n                \r\n                if (window.currentReceiptData.mainItems.length > 0 || window.currentReceiptData.adjustingItems.length > 0) {\r\n                   linesToDraw.push({text: `Subtotal: \u0e3f${window.currentReceiptData.subtotal.toLocaleString()}`, type: 'bold'});\r\n                }\r\n                \r\n                window.currentReceiptData.adjustingItems.forEach(item => {\r\n                     linesToDraw.push({text: `${item.price}  ${item.desc}`, type: 'normal'});\r\n                });\r\n                linesToDraw.push({text: \"\", type: 'normal'});\r\n                linesToDraw.push({text: `TOTAL CALCULATED: \u0e3f${window.currentReceiptData.total.toLocaleString()}`, type: 'title'});\r\n                if (window.currentReceiptData.discount < 0) {\r\n                    linesToDraw.push({text: `(Discount applied: \u0e3f${window.currentReceiptData.discount.toLocaleString()})`, type: 'normal'});\r\n                }\r\n            }\r\n\r\n            \/\/ Calculate precise canvas height\r\n            let expectedCanvasHeight = 50;\r\n            linesToDraw.forEach(item => {\r\n              const maxChars = item.type === 'title' ? 45 : 70;\r\n              if (item.text.length > maxChars) {\r\n                const words = item.text.split(' '); let tempLine = '';\r\n                words.forEach(word => {\r\n                  if ((tempLine + word).length < maxChars) { tempLine += word + ' '; }\r\n                  else { expectedCanvasHeight += 24; tempLine = word + ' '; }\r\n                });\r\n                expectedCanvasHeight += 24;\r\n              } else { expectedCanvasHeight += 24; }\r\n            });\r\n            expectedCanvasHeight += 40; \/\/ Add margin bottom\r\n\r\n            const canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d');\r\n            canvas.width = 650; canvas.height = expectedCanvasHeight; \r\n            ctx.fillStyle = \"#ffffff\"; ctx.fillRect(0, 0, canvas.width, canvas.height);\r\n            \r\n            let y = 50;\r\n            linesToDraw.forEach(item => {\r\n              if (item.type === 'title') { ctx.font = \"bold 20px sans-serif\"; ctx.fillStyle = \"#494BB3\"; }\r\n              else if (item.type === 'header') { ctx.font = \"bold 16px monospace\"; ctx.fillStyle = \"#555\"; }\r\n              else if (item.type === 'bold') { ctx.font = \"bold 16px sans-serif\"; ctx.fillStyle = \"#000\"; }\r\n              else { ctx.font = \"15px sans-serif\"; ctx.fillStyle = \"#555\"; }\r\n              \r\n              const maxChars = item.type === 'title' ? 45 : 70; \r\n              if (item.text.length > maxChars) {\r\n                const words = item.text.split(' '); let tempLine = '';\r\n                words.forEach(word => {\r\n                  if ((tempLine + word).length < maxChars) { tempLine += word + ' '; } \r\n                  else { ctx.fillText(tempLine, 25, y); y += 24; tempLine = word + ' '; }\r\n                });\r\n                ctx.fillText(tempLine, 25, y);\r\n              } else { ctx.fillText(item.text, 25, y); }\r\n              y += 24;\r\n            });\r\n            const link = document.createElement(\"a\"); link.download = \"Registration_Receipt.png\";\r\n            link.href = canvas.toDataURL(\"image\/png\"); link.click();\r\n            \r\n            \/\/ Show the \"NEW FORM\" button after generating and downloading the receipt\r\n            document.getElementById('new-form-btn').style.display = 'block';\r\n          };\r\n\r\n        } else if (submitResult.status === 'unavailable') {\r\n          const badQuestion = submitResult.question; document.getElementById('status-message').innerHTML = ''; \r\n          \r\n          const container = document.querySelector(`.question-container[data-qtitle=\"${CSS.escape(badQuestion)}\"]`);\r\n          if (container) {\r\n            container.classList.add('persistent-highlight');\r\n            container.scrollIntoView({ behavior: 'smooth', block: 'center' });\r\n            container.addEventListener('change', () => { container.classList.remove('persistent-highlight'); }, {once: true});\r\n          }\r\n          \r\n          customAlertMsg.innerHTML = `One of your selections is no longer available for:<br><br><b>\"${badQuestion}\"<\/b><br><br>Please choose again.`;\r\n          customAlert.style.display = 'flex';\r\n          \r\n          const updatedResult = await fetchWithRetry(`${SCRIPT_URL}?action=getConfig`);\r\n          if (updatedResult.status === 'success') {\r\n            formConfig = updatedResult.config;\r\n            if (container) {\r\n              const gradeNumMatch = gradeSelect.value.match(\/\\d+\/); const currentGradeNum = gradeNumMatch ? gradeNumMatch[0] : \"\";\r\n              renderInputForQuestion(container, formConfig.questions[badQuestion], badQuestion, currentGradeNum);\r\n              \r\n              const warningDiv = document.createElement('div');\r\n              warningDiv.style.color = 'red'; warningDiv.style.fontWeight = 'bold'; warningDiv.style.marginTop = '8px'; warningDiv.textContent = 'Please choose again.';\r\n              container.querySelector('.q-input-container').appendChild(warningDiv);\r\n            }\r\n            globalError.innerHTML = `ERROR: One of your selections is no longer available for \"${badQuestion}\".`;\r\n            globalError.style.display = 'block'; validateMasterFormState(); \r\n          }\r\n        } else { throw new Error(submitResult.message); }\r\n      } catch (err) {\r\n        document.getElementById('status-message').style.color = 'red';\r\n        document.getElementById('status-message').textContent = `Error: Cannot reach server. Please try submitting again.`;\r\n        submitBtn.classList.remove('looks-disabled'); \r\n      }\r\n    });\r\n  });\r\n<\/script>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>After School Programs [1\/2026] \u0e02\u0e49\u0e2d\u0e41\u0e19\u0e30\u0e19\u0e33 \u0e2b\u0e32\u0e01\u0e17\u0e48\u0e32\u0e19\u0e15\u0e49\u0e2d\u0e07\u0e01\u0e32\u0e23\u0e23 [&hellip;]<\/p>\n","protected":false},"author":8,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[5],"tags":[],"class_list":["post-2779","post","type-post","status-publish","format-standard","hentry","category-after-school-camps-teams"],"acf":[],"_links":{"self":[{"href":"https:\/\/thaichristian.ac.th\/zh\/wp-json\/wp\/v2\/posts\/2779","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/thaichristian.ac.th\/zh\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/thaichristian.ac.th\/zh\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/thaichristian.ac.th\/zh\/wp-json\/wp\/v2\/users\/8"}],"replies":[{"embeddable":true,"href":"https:\/\/thaichristian.ac.th\/zh\/wp-json\/wp\/v2\/comments?post=2779"}],"version-history":[{"count":19,"href":"https:\/\/thaichristian.ac.th\/zh\/wp-json\/wp\/v2\/posts\/2779\/revisions"}],"predecessor-version":[{"id":2825,"href":"https:\/\/thaichristian.ac.th\/zh\/wp-json\/wp\/v2\/posts\/2779\/revisions\/2825"}],"wp:attachment":[{"href":"https:\/\/thaichristian.ac.th\/zh\/wp-json\/wp\/v2\/media?parent=2779"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/thaichristian.ac.th\/zh\/wp-json\/wp\/v2\/categories?post=2779"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/thaichristian.ac.th\/zh\/wp-json\/wp\/v2\/tags?post=2779"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}