{"id":24,"date":"2025-10-23T05:41:56","date_gmt":"2025-10-23T05:41:56","guid":{"rendered":"https:\/\/price.ho-shi.com\/?page_id=24"},"modified":"2026-04-17T21:59:16","modified_gmt":"2026-04-17T21:59:16","slug":"block-work-quotation","status":"publish","type":"page","link":"https:\/\/price.ho-shi.com\/?page_id=24","title":{"rendered":"\u0e43\u0e1a\u0e40\u0e2a\u0e19\u0e2d\u0e23\u0e32\u0e04\u0e32\u0e07\u0e32\u0e19\u0e1a\u0e25\u0e47\u0e2d\u0e04"},"content":{"rendered":"<div class=\"wpb-content-wrapper\"><p>[vc_row][vc_column][vc_column_text css=&#8221;&#8221;]<\/p>\n<p style=\"text-align: center;\">    <style>\n.hoshi-ssc-wrap {\n  --bg: #07110c;\n  --panel: #0d1812;\n  --bd: #1f3a2d;\n  --txt: #ecfff3;\n  --mut: #9cc9b1;\n  --accent: #1ecb6b;\n  --warn: #ffd54f;\n  --danger: #ff6b6b;\n  margin: 0;\n  color: var(--txt);\n  font-family: ui-sans-serif,system-ui,-apple-system,Segoe UI,Roboto,\"Helvetica Neue\",Arial;\n}\n.hoshi-ssc-wrap, .hoshi-ssc-wrap * { box-sizing: border-box; }\n.hoshi-ssc-wrap .container{max-width:1200px;margin:24px auto;padding:0 16px}\n.hoshi-ssc-wrap h1{margin:0 0 12px;font-size:26px;color:var(--accent)}\n.hoshi-ssc-wrap .card{background:linear-gradient(180deg, rgba(16,30,23,0.98) 0%, rgba(11,22,17,0.98) 100%);border:1px solid var(--bd);border-radius:16px;padding:16px;margin-bottom:16px;box-shadow:0 10px 30px rgba(0,0,0,0.28)}\n.hoshi-ssc-wrap .row{display:grid;grid-template-columns:repeat(12,1fr);gap:12px}\n.hoshi-ssc-wrap .col-12{grid-column:span 12}.hoshi-ssc-wrap .col-8{grid-column:span 8}.hoshi-ssc-wrap .col-6{grid-column:span 6}.hoshi-ssc-wrap .col-4{grid-column:span 4}.hoshi-ssc-wrap .col-3{grid-column:span 3}.hoshi-ssc-wrap .col-2{grid-column:span 2}\n.hoshi-ssc-wrap label{display:block;color:var(--mut);font-size:12px;margin-bottom:6px}\n.hoshi-ssc-wrap select,\n.hoshi-ssc-wrap input[type=number],\n.hoshi-ssc-wrap input[type=text]{\n  width:100%;\n  background:#0a1410 !important;\n  border:1px solid var(--bd) !important;\n  color:var(--txt) !important;\n  -webkit-text-fill-color: var(--txt) !important;\n  caret-color: var(--txt) !important;\n  border-radius:10px;\n  padding:9px 10px;\n  opacity:1 !important;\n}\n.hoshi-ssc-wrap select option{\n  background:#0a1410;\n  color:var(--txt);\n}\n.hoshi-ssc-wrap input::placeholder,\n.hoshi-ssc-wrap textarea::placeholder{\n  color:#9cc9b1 !important;\n  opacity:1;\n}\n.hoshi-ssc-wrap input:-webkit-autofill,\n.hoshi-ssc-wrap input:-webkit-autofill:hover,\n.hoshi-ssc-wrap input:-webkit-autofill:focus,\n.hoshi-ssc-wrap select:-webkit-autofill{\n  -webkit-text-fill-color: var(--txt) !important;\n  -webkit-box-shadow: 0 0 0px 1000px #0a1410 inset !important;\n  transition: background-color 9999s ease-in-out 0s;\n}\n.hoshi-ssc-wrap .muted{color:var(--mut);font-size:12px}\n.hoshi-ssc-wrap table{width:100%;border-collapse:collapse}\n.hoshi-ssc-wrap th,.hoshi-ssc-wrap td{border-bottom:1px solid var(--bd);padding:8px;text-align:center}\n.hoshi-ssc-wrap th{background:#102117;color:#dffff0}\n.hoshi-ssc-wrap .btn{background:linear-gradient(180deg,#1fd16e 0%, #15924d 100%);color:#04100a;border:none;padding:10px 14px;border-radius:12px;font-weight:800;cursor:pointer;transition:.2s;box-shadow:0 8px 18px rgba(30,203,107,.25)}\n.hoshi-ssc-wrap .btn:hover{background:linear-gradient(180deg,#27e07a 0%, #18a856 100%)}\n.hoshi-ssc-wrap .btn.secondary{background:#13231a;color:#d9ffe9}\n.hoshi-ssc-wrap .pill{display:inline-block;padding:2px 8px;border:1px solid #2d5b43;border-radius:999px;background:#0f2218;font-size:12px;color:#ccffe0}\n.hoshi-ssc-wrap .point{border:1px dashed #2d5b43;border-radius:14px;padding:12px;background:#0b1511}\n.hoshi-ssc-wrap select:focus,\n.hoshi-ssc-wrap input[type=number]:focus,\n.hoshi-ssc-wrap input[type=text]:focus{outline:none;border-color:var(--accent)!important;box-shadow:0 0 0 3px rgba(30,203,107,.18)}\n.hoshi-ssc-wrap .total{font-weight:900;font-size:22px;color:var(--accent);text-shadow:0 0 12px rgba(30,203,107,.18)}\n.hoshi-ssc-wrap .right{text-align:right}\n.hoshi-ssc-wrap .hr{height:1px;background:linear-gradient(90deg,transparent, #29573f, transparent);margin:8px 0;border:0}\n@media(max-width:900px){.hoshi-ssc-wrap .col-8,.hoshi-ssc-wrap .col-6,.hoshi-ssc-wrap .col-4,.hoshi-ssc-wrap .col-3,.hoshi-ssc-wrap .col-2{grid-column:span 12}}\n    <\/style>\n    <div class=\"hoshi-ssc-wrap\"><div class=\"container\">\n    <h1>HOSHI SILK SCREEN CALCULATOR<\/h1>\n\n    <!-- STEP 1: Garment type + Sizes table (auto pricing) -->\n    <div class=\"card\">\n      <div class=\"row\">\n        <div class=\"col-4\">\n          <label>\u0e1b\u0e23\u0e30\u0e40\u0e20\u0e17\u0e40\u0e2a\u0e37\u0e49\u0e2d<\/label>\n          <select id=\"garmentType\">\n            <option value=\"oversize\">\u0e40\u0e2a\u0e37\u0e49\u0e2d\u0e42\u0e2d\u0e40\u0e27\u0e2d\u0e23\u0e4c\u0e44\u0e0b\u0e2a\u0e4c<\/option>\n            <option value=\"cottonpoly\">\u0e40\u0e2a\u0e37\u0e49\u0e2d\u0e04\u0e2d\u0e15\u0e15\u0e2d\u0e19\u0e42\u0e1e\u0e25\u0e35<\/option>\n            <option value=\"cotton100\">\u0e40\u0e2a\u0e37\u0e49\u0e2d\u0e04\u0e2d\u0e15\u0e15\u0e2d\u0e19 100%<\/option>\n            <option value=\"own\">\u0e25\u0e39\u0e01\u0e04\u0e49\u0e32\u0e19\u0e33\u0e40\u0e2a\u0e37\u0e49\u0e2d\u0e21\u0e32\u0e40\u0e2d\u0e07 (BYO)<\/option>\n          <\/select>\n        <\/div>\n        <div class=\"col-3\">\n          <label>\u0e42\u0e2b\u0e21\u0e14\u0e23\u0e32\u0e04\u0e32<\/label>\n          <select id=\"priceMode\">\n            <option value=\"auto\">\u0e43\u0e0a\u0e49\u0e10\u0e32\u0e19\u0e23\u0e32\u0e04\u0e32\u0e2d\u0e31\u0e15\u0e42\u0e19\u0e21\u0e31\u0e15\u0e34<\/option>\n            <option value=\"manual\">\u0e01\u0e33\u0e2b\u0e19\u0e14\u0e23\u0e32\u0e04\u0e32\u0e15\u0e48\u0e2d\u0e44\u0e0b\u0e2a\u0e4c\u0e40\u0e2d\u0e07<\/option>\n          <\/select>\n        <\/div>\n        <div class=\"col-3\">\n          <label>\u0e08\u0e33\u0e19\u0e27\u0e19\u0e08\u0e38\u0e14\u0e2a\u0e01\u0e23\u0e35\u0e19<\/label>\n          <input id=\"numPoints\" type=\"number\" min=\"1\" max=\"8\" value=\"1\" \/>\n        <\/div>\n        <div class=\"col-2\" style=\"align-self:end\">\n          <button id=\"btnBuildPoints\" class=\"btn\">\u0e2a\u0e23\u0e49\u0e32\u0e07\u0e01\u0e23\u0e2d\u0e1a\u0e08\u0e38\u0e14\u0e2a\u0e01\u0e23\u0e35\u0e19<\/button>\n        <\/div>\n      <\/div>\n\n      <div class=\"hr\"><\/div>\n\n      <div class=\"row\">\n        <div class=\"col-12\">\n          <h3 style=\"margin:0 0 8px\">\u0e15\u0e32\u0e23\u0e32\u0e07\u0e08\u0e33\u0e19\u0e27\u0e19 & \u0e23\u0e32\u0e04\u0e32\u0e40\u0e2a\u0e37\u0e49\u0e2d<\/h3>\n          <div class=\"muted\">\u2022 \u0e40\u0e25\u0e37\u0e2d\u0e01\u0e1b\u0e23\u0e30\u0e40\u0e20\u0e17\u0e40\u0e2a\u0e37\u0e49\u0e2d \u2192 \u0e23\u0e30\u0e1a\u0e1a\u0e2a\u0e23\u0e49\u0e32\u0e07\u0e41\u0e16\u0e27\u0e44\u0e0b\u0e2a\u0e4c\u0e43\u0e2b\u0e49\u0e15\u0e23\u0e07\u0e0a\u0e19\u0e34\u0e14\u0e40\u0e2a\u0e37\u0e49\u0e2d \u2022 \u0e42\u0e2b\u0e21\u0e14 <b>\u0e2d\u0e31\u0e15\u0e42\u0e19\u0e21\u0e31\u0e15\u0e34<\/b>: \u0e23\u0e30\u0e1a\u0e1a\u0e01\u0e33\u0e2b\u0e19\u0e14\u0e23\u0e32\u0e04\u0e32\u0e15\u0e48\u0e2d\u0e44\u0e0b\u0e2a\u0e4c\u0e15\u0e32\u0e21\u0e0a\u0e48\u0e27\u0e07\u0e08\u0e33\u0e19\u0e27\u0e19\u0e23\u0e27\u0e21 (Q) \u2022 \u0e42\u0e2b\u0e21\u0e14 <b>manual<\/b>: \u0e1e\u0e34\u0e21\u0e1e\u0e4c\u0e23\u0e32\u0e04\u0e32\u0e40\u0e2d\u0e07<\/div>\n          <table id=\"sizeTable\">\n            <thead><tr id=\"sizeHead\"><\/tr><\/thead>\n            <tbody id=\"sizeBody\"><\/tbody>\n            <tfoot>\n              <tr>\n                <th class=\"right\" colspan=\"100\">\u0e08\u0e33\u0e19\u0e27\u0e19\u0e23\u0e27\u0e21 (Q): <span id=\"sumQty\">0<\/span><\/th>\n              <\/tr>\n              <tr>\n                <th class=\"right\" colspan=\"100\">\u0e23\u0e32\u0e04\u0e32\u0e23\u0e27\u0e21\u0e40\u0e2a\u0e37\u0e49\u0e2d: <span id=\"sumShirt\">0<\/span><\/th>\n              <\/tr>\n            <\/tfoot>\n          <\/table>\n        <\/div>\n      <\/div>\n    <\/div>\n\n    <!-- STEP 2\u20133: Screen points -->\n    <div class=\"card\">\n      <h3 style=\"margin:0 0 8px\">\u0e08\u0e38\u0e14\u0e2a\u0e01\u0e23\u0e35\u0e19 (\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e02\u0e19\u0e32\u0e14 + \u0e08\u0e33\u0e19\u0e27\u0e19\u0e2a\u0e35 1\u201312)<\/h3>\n      <div id=\"points\" class=\"row\"><\/div>\n    <\/div>\n\n    <!-- SUMMARY -->\n    <div class=\"card\">\n      <h3 style=\"margin:0 0 8px\">\u0e2a\u0e23\u0e38\u0e1b\u0e1c\u0e25<\/h3>\n      <div class=\"row\">\n        <div class=\"col-6\">\n          <table>\n            <tbody>\n              <tr><td class=\"right\">\u0e08\u0e33\u0e19\u0e27\u0e19\u0e40\u0e2a\u0e37\u0e49\u0e2d\u0e23\u0e27\u0e21 (Q)<\/td><td id=\"outQ\">0<\/td><\/tr>\n              <tr><td class=\"right\">\u0e23\u0e32\u0e04\u0e32\u0e23\u0e27\u0e21\u0e40\u0e2a\u0e37\u0e49\u0e2d<\/td><td id=\"outShirt\">0<\/td><\/tr>\n              <tr><td class=\"right\">\u0e04\u0e48\u0e32\u0e2a\u0e01\u0e23\u0e35\u0e19\u0e23\u0e27\u0e21 (\u0e17\u0e38\u0e01\u0e08\u0e38\u0e14)<\/td><td id=\"outScreen\">0<\/td><\/tr>\n              <tr><td class=\"right\">\u0e04\u0e48\u0e32\u0e1a\u0e25\u0e47\u0e2d\u0e04\u0e23\u0e27\u0e21<\/td><td id=\"outBlock\">0<\/td><\/tr>\n            <\/tbody>\n            <tfoot>\n              <tr><th class=\"right\">\u0e22\u0e2d\u0e14\u0e23\u0e27\u0e21\u0e17\u0e31\u0e49\u0e07\u0e2b\u0e21\u0e14<\/th><th id=\"outGrand\" class=\"total\">0<\/th><\/tr>\n              <tr><th class=\"right\">\u0e23\u0e32\u0e04\u0e32\u0e40\u0e09\u0e25\u0e35\u0e48\u0e22\u0e15\u0e48\u0e2d\u0e15\u0e31\u0e27<\/th><th id=\"outAvg\" class=\"total\">0<\/th><\/tr>\n            <\/tfoot>\n          <\/table>\n          <div id=\"warnings\" class=\"muted\" style=\"margin-top:6px\"><\/div>\n        <\/div>\n        <div class=\"col-6\">\n          <h4 style=\"margin:0 0 6px\">\u0e23\u0e32\u0e22\u0e25\u0e30\u0e40\u0e2d\u0e35\u0e22\u0e14\u0e23\u0e32\u0e04\u0e32<\/h4>\n          <div id=\"breakdown\" class=\"muted\"><\/div>\n        <\/div>\n      <\/div>\n    <\/div>\n  <\/div>\n    <script>\n\/\/ ====== PRICE DATABASE (from your latest update) ======\nconst PRICE_DB = {\n  oversize: {\n    sizes: [\"F\/M\",\"L\",\"XL\",\"2XL\"],\n    bands: [ [1,11],[12,48],[49,100],[101,300],[301,500],[501,Infinity] ],\n    rows: [\n      {\"F\/M\":145, L:155, XL:165, \"2XL\":185},\n      {\"F\/M\":135, L:145, XL:155, \"2XL\":175},\n      {\"F\/M\":130, L:140, XL:150, \"2XL\":170},\n      {\"F\/M\":120, L:130, XL:140, \"2XL\":160},\n      {\"F\/M\":110, L:120, XL:130, \"2XL\":150},\n      {\"F\/M\":105, L:115, XL:125, \"2XL\":145}\n    ]\n  },\n  cottonpoly: {\n    sizes: [\"S\",\"M\",\"L\",\"XL\",\"2XL\",\"3XL\"],\n    bands: [ [1,11],[12,48],[49,100],[101,300],[301,500],[501,Infinity] ],\n    rows: [\n      {S:95, M:105, L:115, XL:120, \"2XL\":140, \"3XL\":170},\n      {S:92, M:102, L:112, XL:117, \"2XL\":137, \"3XL\":167},\n      {S:87, M:97, L:107, XL:112, \"2XL\":132, \"3XL\":162},\n      {S:83, M:93, L:103, XL:108, \"2XL\":128, \"3XL\":158},\n      {S:79, M:89, L:99, XL:104, \"2XL\":124, \"3XL\":154},\n      {S:65, M:75, L:85, XL:90, \"2XL\":110, \"3XL\":140}\n    ]\n  },\n  cotton100: {\n    sizes: [\"S\",\"M\",\"L\",\"XL\",\"2XL\",\"3XL\",\"4XL\",\"5XL\",\"6XL\"],\n    bands: [ [1,11],[12,48],[49,100],[101,300],[301,500],[501,Infinity] ],\n    rows: [\n      {S:83,M:93,L:103,XL:113,\"2XL\":123,\"3XL\":153,\"4XL\":183,\"5XL\":243,\"6XL\":245},\n      {S:79,M:89,L:99,XL:109,\"2XL\":116,\"3XL\":149,\"4XL\":179,\"5XL\":209,\"6XL\":239},\n      {S:70,M:80,L:90,XL:100,\"2XL\":107,\"3XL\":140,\"4XL\":170,\"5XL\":200,\"6XL\":230},\n      {S:63,M:73,L:83,XL:93,\"2XL\":100,\"3XL\":133,\"4XL\":163,\"5XL\":193,\"6XL\":223},\n      {S:56,M:66,L:76,XL:86,\"2XL\":93,\"3XL\":126,\"4XL\":156,\"5XL\":186,\"6XL\":216},\n      {S:50,M:60,L:70,XL:80,\"2XL\":90,\"3XL\":120,\"4XL\":150,\"5XL\":180,\"6XL\":210}\n    ]\n  },\n  own: {\n    \/\/ Use cottonpoly size grid for convenience, but price = 0\n    sizes: [\"S\",\"M\",\"L\",\"XL\",\"2XL\",\"3XL\"],\n    bands: [ [1,Infinity] ],\n    rows: [ {S:0,M:0,L:0,XL:0,\"2XL\":0,\"3XL\":0} ]\n  }\n};\n\n\/\/ ====== SCREEN RATES (Group A\/B) ======\n\/\/ A: Cotton Poly + Oversize\n\/\/ B: Cotton 100% + Own\nconst SCREEN_RATES = {\n  B: [\n    {min:1,max:9,    A4:{first:85,next:30},  A3:{first:105,next:35}},\n    {min:10,max:23,  A4:{first:65,next:25},  A3:{first:80,next:25}},\n    {min:24,max:50,  A4:{first:40,next:25},  A3:{first:50,next:25}},\n    {min:51,max:99,  A4:{first:35,next:20},  A3:{first:45,next:20}},\n    {min:100,max:300,A4:{first:30,next:15},  A3:{first:40,next:15}},\n    {min:301,max:Infinity,A4:{first:25,next:10}, A3:{first:30,next:10}}\n  ]\n};\n\nfunction groupKeyByGarment(type){\n  return 'B';\n}\n\nfunction getScreenRate(groupKey, qty, size){\n  const table = SCREEN_RATES.B;\n  for (const band of table) {\n    if (qty >= band.min && qty <= band.max) {\n      if (size === 'A4') return band.A4;\n      if (size === 'A3') return band.A3;\n      return null;\n    }\n  }\n  return null;\n}\n\nfunction blockFeePerColor(qty, size){\n  const blockRateTable = [\n    { min: 1,   max: 9,        A4: 800, A3: 1200 },\n    { min: 10,  max: 23,       A4: 450, A3: 500 },\n    { min: 24,  max: 100,      A4: 350, A3: 400 },\n    { min: 101, max: Infinity, A4: 250, A3: 300 }\n  ];\n\n  for (const row of blockRateTable) {\n    if (qty >= row.min && qty <= row.max) {\n      if (size === 'A4') return row.A4;\n      if (size === 'A3') return row.A3;\n      return null;\n    }\n  }\n\n  return null;\n}\n\n\/\/ ====== UI: Size table build & calc ======\nconst sizeHead = document.getElementById('sizeHead');\nconst sizeBody = document.getElementById('sizeBody');\nconst sumQtyEl = document.getElementById('sumQty');\nconst sumShirtEl = document.getElementById('sumShirt');\n\nfunction th(html){ const th=document.createElement('th'); th.innerHTML=html; return th }\nfunction td(html){ const td=document.createElement('td'); td.innerHTML=html; return td }\n\nfunction currentSizes(){\n  const type = document.getElementById('garmentType').value;\n  return PRICE_DB[type].sizes;\n}\n\nfunction currentBandIndex(q){\n  const type = document.getElementById('garmentType').value;\n  const bands = PRICE_DB[type].bands;\n  for(let i=0;i<bands.length;i++){\n    const [lo,hi] = bands[i];\n    if(q>=lo && q<=hi) return i;\n  }\n  return 0;\n}\n\nfunction buildSizeTable(){\n  const sizes = currentSizes();\n  sizeHead.innerHTML='';\n  sizeBody.innerHTML='';\n  sizeHead.appendChild(th('Size'));\n  sizeHead.appendChild(th('\u0e08\u0e33\u0e19\u0e27\u0e19 (Q)'));\n  sizeHead.appendChild(th('\u0e23\u0e32\u0e04\u0e32\u0e15\u0e48\u0e2d\u0e44\u0e0b\u0e2a\u0e4c'));\n  sizeHead.appendChild(th('\u0e23\u0e27\u0e21'));\n\n  sizes.forEach(sz=>{\n    const tr=document.createElement('tr');\n    tr.innerHTML = `\n      <td><span class=\"pill\">${sz}<\/span><\/td>\n      <td><input type=\"number\" min=\"0\" value=\"0\" data-q data-size=\"${sz}\"\/><\/td>\n      <td><input type=\"number\" min=\"0\" value=\"0\" data-price data-size=\"${sz}\"\/><\/td>\n      <td class=\"right\" data-sub data-size=\"${sz}\">0<\/td>\n    `;\n    sizeBody.appendChild(tr);\n  });\n\n  sizeBody.querySelectorAll('input').forEach(el=> el.addEventListener('input', ()=>{ calcShirt(); calcAll(); }));\n  autoFillPrices();\n  calcShirt();\n}\n\nfunction autoFillPrices(){\n  const mode = document.getElementById('priceMode').value;\n  if(mode!==\"auto\") return; \/\/ manual mode\n  const q = getTotalQty();\n  const type = document.getElementById('garmentType').value;\n  const idx = currentBandIndex(Math.max(1,q||1));\n  const row = PRICE_DB[type].rows[idx];\n  sizeBody.querySelectorAll('[data-price]').forEach(input=>{\n    const sz = input.getAttribute('data-size');\n    const price = row[sz] ?? 0;\n    input.value = price;\n  });\n}\n\nfunction getTotalQty(){\n  let total=0;\n  sizeBody.querySelectorAll('[data-q]').forEach(inp=> total += (parseFloat(inp.value)||0));\n  return total;\n}\n\nfunction calcShirt(){\n  const qTotal = getTotalQty();\n  sumQtyEl.textContent = new Intl.NumberFormat('th-TH').format(qTotal);\n\n  \/\/ If in auto mode, refetch prices when Q band changes\n  if(document.getElementById('priceMode').value==='auto'){\n    autoFillPrices();\n  }\n\n  let shirtTotal = 0;\n  sizeBody.querySelectorAll('tr').forEach(tr=>{\n    const q = parseFloat(tr.querySelector('[data-q]').value)||0;\n    const p = parseFloat(tr.querySelector('[data-price]').value)||0;\n    const sub = q*p;\n    tr.querySelector('[data-sub]').textContent = currency(sub);\n    shirtTotal += sub;\n  });\n  sumShirtEl.textContent = currency(shirtTotal);\n  return { qTotal, shirtTotal };\n}\n\nfunction currency(n){ return new Intl.NumberFormat('th-TH',{style:'currency',currency:'THB',maximumFractionDigits:0}).format(n||0) }\nfunction number(n){ return new Intl.NumberFormat('th-TH').format(n||0) }\n\n\/\/ ====== Points (dynamic) ======\nconst pointsWrap = document.getElementById('points');\nfunction buildPoints(){\n  const n = Math.max(1, Math.min(8, parseInt(document.getElementById('numPoints').value||'1',10)));\n  document.getElementById('numPoints').value = n;\n  pointsWrap.innerHTML = '';\n  for(let i=1;i<=n;i++){\n    const div = document.createElement('div');\n    div.className = 'col-6';\n    div.innerHTML = `\n      <div class=\"point\">\n        <div class=\"row\">\n          <div class=\"col-12\" style=\"margin-bottom:6px\"><strong>\u0e08\u0e38\u0e14\u0e17\u0e35\u0e48 ${i}<\/strong><\/div>\n          <div class=\"col-6\">\n            <label>\u0e02\u0e19\u0e32\u0e14\u0e2a\u0e01\u0e23\u0e35\u0e19<\/label>\n            <select data-size>\n              <option value=\"A4\">A4<\/option>\n              <option value=\"A3\">A3<\/option>\n            <\/select>\n          <\/div>\n          <div class=\"col-6\">\n            <label>\u0e08\u0e33\u0e19\u0e27\u0e19\u0e2a\u0e35 (1\u201312)<\/label>\n            <input type=\"number\" min=\"1\" max=\"12\" value=\"1\" data-colors \/>\n          <\/div>\n          <div class=\"col-12 muted\" data-note><\/div>\n        <\/div>\n      <\/div>\n    `;\n    pointsWrap.appendChild(div);\n  }\n\n  pointsWrap.querySelectorAll('.point').forEach(point => {\n    const sizeInput = point.querySelector('[data-size]');\n    const colorInput = point.querySelector('[data-colors]');\n    const noteEl = point.querySelector('[data-note]');\n\n    sizeInput.addEventListener('input', () => {\n      calcAll();\n    });\n\n    colorInput.addEventListener('input', function () {\n      let v = parseInt(this.value || '1', 10);\n\n      if (v > 12) {\n        this.value = 12;\n        noteEl.textContent = '\u26a0\ufe0f \u0e01\u0e23\u0e2d\u0e01\u0e08\u0e33\u0e19\u0e27\u0e19\u0e2a\u0e35\u0e44\u0e14\u0e49\u0e2a\u0e39\u0e07\u0e2a\u0e38\u0e14 12 \u0e2a\u0e35';\n      } else if (v < 1 || isNaN(v)) {\n        this.value = 1;\n        noteEl.textContent = '\u26a0\ufe0f \u0e08\u0e33\u0e19\u0e27\u0e19\u0e2a\u0e35\u0e15\u0e48\u0e33\u0e2a\u0e38\u0e14\u0e04\u0e37\u0e2d 1 \u0e2a\u0e35';\n      } else {\n        noteEl.textContent = '';\n      }\n\n      calcAll();\n    });\n  });\n}\n\n\/\/ ====== Summary calc (screen + block + totals) ======\nconst outQ = document.getElementById('outQ');\nconst outShirt = document.getElementById('outShirt');\nconst outScreen = document.getElementById('outScreen');\nconst outBlock = document.getElementById('outBlock');\nconst outGrand = document.getElementById('outGrand');\nconst outAvg = document.getElementById('outAvg');\nconst breakdown = document.getElementById('breakdown');\nconst warnings = document.getElementById('warnings');\n\nfunction calcAll(){\n  const { qTotal: Q, shirtTotal } = calcShirt();\n  const type = document.getElementById('garmentType').value;\n  const groupKey = groupKeyByGarment(type);\n\n  let screenTotal = 0;\n  let blockTotal = 0;\n  let rows = [];\n  let warns = [];\n\n  pointsWrap.querySelectorAll('.point').forEach((p, idx)=>{\n    const size = p.querySelector('[data-size]').value; \/\/ A4\/A3\n    const colors = Math.max(1, Math.min(12, parseInt(p.querySelector('[data-colors]').value||'1',10)));\n    const rate = getScreenRate(groupKey, Q, size);\n    const blk = blockFeePerColor(Q, size);\n    let perShirt = 0, scrSum = 0, blkSum = 0; let note = '';\n\n    if(!rate){ note = '\u26a0\ufe0f \u0e22\u0e31\u0e07\u0e44\u0e21\u0e48\u0e01\u0e33\u0e2b\u0e19\u0e14\u0e40\u0e23\u0e17\u0e2a\u0e01\u0e23\u0e35\u0e19\u0e2a\u0e33\u0e2b\u0e23\u0e31\u0e1a Q < 20'; warns.push('\u0e40\u0e23\u0e17\u0e2a\u0e01\u0e23\u0e35\u0e19\u0e44\u0e21\u0e48\u0e04\u0e23\u0e2d\u0e1a\u0e04\u0e25\u0e38\u0e21 Q < 20'); }\n    else { perShirt = rate.first + (colors-1)*rate.next; scrSum = perShirt * (Q||0); }\n\n    if(blk == null){\n      if(Q === 0){\n        note += (note ? ' | ' : '') + '\u0e01\u0e23\u0e2d\u0e01\u0e08\u0e33\u0e19\u0e27\u0e19\u0e40\u0e2a\u0e37\u0e49\u0e2d\u0e40\u0e1e\u0e37\u0e48\u0e2d\u0e04\u0e33\u0e19\u0e27\u0e13\u0e04\u0e48\u0e32\u0e1a\u0e25\u0e47\u0e2d\u0e04';\n      } else {\n        note += (note ? ' | ' : '') + '\u26a0\ufe0f \u0e44\u0e21\u0e48\u0e1e\u0e1a\u0e40\u0e23\u0e17\u0e04\u0e48\u0e32\u0e1a\u0e25\u0e47\u0e2d\u0e04\u0e2a\u0e33\u0e2b\u0e23\u0e31\u0e1a\u0e02\u0e19\u0e32\u0e14\u0e19\u0e35\u0e49';\n        warns.push('\u0e44\u0e21\u0e48\u0e1e\u0e1a\u0e40\u0e23\u0e17\u0e04\u0e48\u0e32\u0e1a\u0e25\u0e47\u0e2d\u0e04\u0e2a\u0e33\u0e2b\u0e23\u0e31\u0e1a\u0e02\u0e19\u0e32\u0e14\u0e17\u0e35\u0e48\u0e40\u0e25\u0e37\u0e2d\u0e01');\n      }\n    } else {\n      blkSum = blk * colors;\n    }\n\n    screenTotal += scrSum; blockTotal += blkSum;\n    p.querySelector('[data-note]').textContent = note;\n    rows.push({i:idx+1,size,colors,perShirt,scrSum,blkSum,blkRate: blk});\n  });\n\n  const grand = shirtTotal + screenTotal + blockTotal;\n  const avg = (Q>0)? (grand\/Q) : 0;\n\n  outQ.textContent = number(Q);\n  outShirt.textContent = currency(shirtTotal);\n  outScreen.textContent = currency(screenTotal);\n  outBlock.textContent = currency(blockTotal);\n  outGrand.textContent = currency(grand);\n  outAvg.textContent = currency(avg);\n\n  breakdown.innerHTML = rows.map(r=>`\n    <div class=\"card\" style=\"padding:10px;margin:8px 0\">\n      <div><strong>\u0e08\u0e38\u0e14\u0e17\u0e35\u0e48 ${r.i}<\/strong> \u2022 ${r.size} \u2022 ${r.colors} \u0e2a\u0e35<\/div>\n      <div class=\"muted\">\u0e40\u0e23\u0e17\u0e2a\u0e01\u0e23\u0e35\u0e19\u0e15\u0e48\u0e2d\u0e40\u0e2a\u0e37\u0e49\u0e2d: ${currency(r.perShirt)} \/ \u0e15\u0e31\u0e27<\/div>\n      <div class=\"muted\">\u0e04\u0e33\u0e19\u0e27\u0e13\u0e04\u0e48\u0e32\u0e2a\u0e01\u0e23\u0e35\u0e19: ${currency(r.perShirt)} \u00d7 ${number(Q)} \u0e15\u0e31\u0e27 = <b>${currency(r.scrSum)}<\/b><\/div>\n      <div class=\"muted\">\u0e04\u0e48\u0e32\u0e2a\u0e35: \u0e2a\u0e35\u0e41\u0e23\u0e01 + \u0e2a\u0e35\u0e16\u0e31\u0e14\u0e44\u0e1b ${Math.max(0, r.colors - 1)} \u0e2a\u0e35<\/div>\n      <div class=\"muted\">\u0e40\u0e23\u0e17\u0e04\u0e48\u0e32\u0e1a\u0e25\u0e47\u0e2d\u0e04: ${r.blkRate ? currency(r.blkRate) + ' \/ \u0e2a\u0e35' : '-'}<\/div>\n      <div class=\"muted\">\u0e04\u0e33\u0e19\u0e27\u0e13\u0e04\u0e48\u0e32\u0e1a\u0e25\u0e47\u0e2d\u0e04: ${r.blkRate ? currency(r.blkRate) + ' \u00d7 ' + r.colors + ' \u0e2a\u0e35 = ' + currency(r.blkSum) : '-'}<\/div>\n      <div>\u0e23\u0e27\u0e21\u0e15\u0e48\u0e2d\u0e08\u0e38\u0e14: <b>${currency(r.scrSum + r.blkSum)}<\/b><\/div>\n    <\/div>\n  `).join('');\n\n  const notes=[]; if(warns.length){ notes.push('<span style=\"color:var(--warn)\">\u0e04\u0e33\u0e40\u0e15\u0e37\u0e2d\u0e19:<\/span> '+Array.from(new Set(warns)).join(' | ')); }\n  warnings.innerHTML = notes.join('<br\/>');\n}\n\n\/\/ ====== Events ======\nfunction rebuildAll(){ buildSizeTable(); buildPoints(); calcAll(); }\n\ndocument.getElementById('garmentType').addEventListener('change', rebuildAll);\ndocument.getElementById('priceMode').addEventListener('change', ()=>{ autoFillPrices(); calcShirt(); calcAll(); });\ndocument.getElementById('btnBuildPoints').addEventListener('click', ()=>{ buildPoints(); calcAll(); });\ndocument.getElementById('numPoints').addEventListener('input', ()=>{ \/*clamped in buildPoints*\/ });\n\n\/\/ Init\nrebuildAll();\n    <\/script>\n<\/div>\n<p>[\/vc_column_text][\/vc_column][\/vc_row]<\/p>\n<\/div>","protected":false},"excerpt":{"rendered":"<p>[vc_row][vc_column][vc_column_text css=&#8221;&#8221;] [\/vc_column_text][\/vc_column][\/vc_row]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-24","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/price.ho-shi.com\/index.php?rest_route=\/wp\/v2\/pages\/24","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/price.ho-shi.com\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/price.ho-shi.com\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/price.ho-shi.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/price.ho-shi.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=24"}],"version-history":[{"count":1,"href":"https:\/\/price.ho-shi.com\/index.php?rest_route=\/wp\/v2\/pages\/24\/revisions"}],"predecessor-version":[{"id":206,"href":"https:\/\/price.ho-shi.com\/index.php?rest_route=\/wp\/v2\/pages\/24\/revisions\/206"}],"wp:attachment":[{"href":"https:\/\/price.ho-shi.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=24"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}