{"id":87660,"date":"2026-02-18T05:00:01","date_gmt":"2026-02-18T05:00:01","guid":{"rendered":"https:\/\/dgshape.com\/simulator\/"},"modified":"2026-10-19T06:13:17","modified_gmt":"2026-10-19T06:13:17","slug":"simulator","status":"publish","type":"page","link":"https:\/\/dgshape.com\/zh-hans\/simulator\/","title":{"rendered":"DWX \u7cfb\u5217\u6295\u8d44\u56de\u62a5\u7387 (ROI) \u6a21\u62df\u5668"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"87660\" class=\"elementor elementor-87660 elementor-81283\" data-elementor-post-type=\"page\">\n\t\t\t\t<div class=\"elementor-element elementor-element-51e3838e e-flex e-con-boxed e-con e-parent\" data-id=\"51e3838e\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-3b020ef elementor-widget elementor-widget-html\" data-id=\"3b020ef\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t  <style>\r\n    .roi-simulator-page .roi-simulator-form-toggle__button,\r\n    .roi-simulator-page .roi-simulator-form-toggle__button:hover,\r\n    .roi-simulator-page .roi-simulator-form-toggle__button:focus,\r\n    .roi-simulator-page .roi-simulator-form-toggle__button:focus-visible,\r\n    .roi-simulator-page .roi-simulator-form-toggle__button:active {\r\n      border: none !important;\r\n      outline: none !important;\r\n      box-shadow: none !important;\r\n      background: transparent !important;\r\n    }\r\n  <\/style>\r\n  <div class=\"roi-simulator-page\">\r\n    <div class=\"roi-simulator-page__wrapper\">\r\n      <div class=\"roi-simulator-body\">\r\n        <form id=\"roi-simulator-form\" class=\"roi-simulator-form\">\r\n          <select id=\"select-currency\" hidden aria-hidden=\"true\">\r\n            <option value=\"\u00a5\" selected>\u00a5<\/option>\r\n          <\/select>\r\n          <section>\r\n            <h2 class=\"roi-simulator-form__title-mini\">\u521d\u59cb\u6295\u8d44\u8d39\u7528<\/h2>\r\n            <div class=\"roi-simulator-form-investment-cost\">\r\n              <div class=\"roi-simulator-form-investment-cost-box\">\r\n                <label for=\"input-dwx-price\">DWX \u4ef7\u683c*<\/label>\r\n                <span data-currency=\"\">\u00a5<\/span>\r\n                <input id=\"input-dwx-price\" required=\"\" type=\"text\" value=\"\" aria-label=\"DWX \u4ef7\u683c\" data-max=\"10000000\" data-min=\"0\" \/>\r\n                <p class=\"roi-error-message\" style=\"display: none\" data-required=\"input-dwx-price\">*\u6b64\u9879\u4e3a\u5fc5\u586b\u9879\u3002<\/p>\r\n                <p class=\"roi-error-message\" style=\"display: none\" data-max-min=\"input-dwx-price\">*\u8bf7\u8f93\u5165 0 \u81f3 10,000,000 \u4e4b\u95f4\u7684\u6570\u503c<\/p>\r\n              <\/div>\r\n              <div class=\"roi-simulator-form-investment-cost-box\">\r\n                <label for=\"input-other-expenses\">\u5176\u4ed6\u8d39\u7528<\/label>\r\n                <span data-currency=\"\">\u00a5<\/span>\r\n                <input id=\"input-other-expenses\" type=\"text\" value=\"\" aria-label=\"\u5176\u4ed6\u8d39\u7528\" data-max=\"10000000\" data-min=\"0\" \/>\r\n                <p class=\"roi-error-message\" style=\"display: none\" data-max-min=\"input-other-expenses\">*\u8bf7\u8f93\u5165 0 \u81f3 10,000,000 \u4e4b\u95f4\u7684\u6570\u503c<\/p>\r\n              <\/div>\r\n            <\/div>\r\n            <div class=\"roi-simulator-form-total\">\r\n              \u5408\u8ba1\r\n              <p class=\"dollar-box\"><span data-currency=\"\">\u00a5<\/span><span id=\"total-initial-investment\"><\/span><\/p>\r\n            <\/div>\r\n          <\/section>\r\n          <section>\r\n            <h2 class=\"roi-simulator-form__title-mini\">\u6708\u5ea6\u9500\u552e\u8ba1\u5212<\/h2>\r\n            <h3>\u9500\u552e\u5355\u4ef7*<\/h3>\r\n            <p id=\"sales-price-error-message\" class=\"roi-error-message\" style=\"display: none\">*\u8bf7\u81f3\u5c11\u5b8c\u6574\u586b\u5199\u4e00\u7ec4\uff1a\u6c27\u5316\u9506\uff08\u9500\u552e\u5355\u4ef7 + \u9500\u552e\u6570\u91cf\uff09\u3001\u73bb\u7483\u9676\u74f7\uff08\u9500\u552e\u5355\u4ef7 + \u9500\u552e\u6570\u91cf\uff09\u6216\u5176\u4ed6\u6750\u6599\uff08\u9500\u552e\u5355\u4ef7 + \u9500\u552e\u6570\u91cf\uff09\u3002<\/p>\r\n\r\n            <div class=\"roi-simulator-form-sales-plan roi-simulator-form-sales-plan-top\">\r\n              <div>\r\n                <label for=\"input-zirconia-price\">\u6c27\u5316\u9506<\/label>\r\n                <div class=\"roi-simulator-form-sales-plan-price\"><span data-currency=\"\">\u00a5<\/span> <input id=\"input-zirconia-price\" type=\"text\" value=\"\" aria-label=\"\u6c27\u5316\u9506\" data-max=\"1000000\" data-min=\"0\" \/><\/div>\r\n                <p class=\"roi-error-message\" style=\"display: none\" data-max-min=\"input-zirconia-price\">*\u8bf7\u8f93\u5165 0 \u81f3 1,000,000 \u4e4b\u95f4\u7684\u6570\u503c<\/p>\r\n              <\/div>\r\n              <div>\r\n                <label for=\"input-zirconia-units\">\u9500\u552e\u6570\u91cf<\/label>\r\n                <div class=\"roi-simulator-form-sales-plan-price roi-simulator-form-sales-unit\"><input id=\"input-zirconia-units\" type=\"text\" value=\"\" aria-label=\"\u9500\u552e\u6570\u91cf\" data-max=\"100000\" data-min=\"0\" \/> <span class=\"roi-simulator-form-sales-unit-pcs\">\u4ef6<\/span><\/div>\r\n                <p class=\"roi-error-message\" style=\"display: none\" data-max-min=\"input-zirconia-units\">*\u8bf7\u8f93\u5165 0 \u81f3 100,000 \u4e4b\u95f4\u7684\u6570\u503c<\/p>\r\n              <\/div>\r\n            <\/div>\r\n            <div class=\"roi-simulator-form-sales-plan\">\r\n              <div>\r\n                <label for=\"input-glass-ceramics-price\">\u73bb\u7483\u9676\u74f7<span>*\u4ec5\u9002\u7528\u4e8e\u6e7f\u5f0f\u5207\u524a\u673a<\/span><\/label>\r\n                <div class=\"roi-simulator-form-sales-plan-price\"><span data-currency=\"\">\u00a5<\/span> <input id=\"input-glass-ceramics-price\" type=\"text\" value=\"\" aria-label=\"\u73bb\u7483\u9676\u74f7\" data-max=\"1000000\" data-min=\"0\" \/><\/div>\r\n                <p class=\"roi-error-message\" style=\"display: none\" data-max-min=\"input-glass-ceramics-price\">*\u8bf7\u8f93\u5165 0 \u81f3 1,000,000 \u4e4b\u95f4\u7684\u6570\u503c<\/p>\r\n              <\/div>\r\n              <div>\r\n                <label for=\"input-glass-ceramics-units\">\u9500\u552e\u6570\u91cf<\/label>\r\n                <div class=\"roi-simulator-form-sales-plan-price roi-simulator-form-sales-unit\"><input id=\"input-glass-ceramics-units\" type=\"text\" value=\"\" aria-label=\"\u9500\u552e\u6570\u91cf\" data-max=\"100000\" data-min=\"0\" \/> <span class=\"roi-simulator-form-sales-unit-pcs\">\u4ef6<\/span><\/div>\r\n                <p class=\"roi-error-message\" style=\"display: none\" data-max-min=\"input-glass-ceramics-units\">*\u8bf7\u8f93\u5165 0 \u81f3 100,000 \u4e4b\u95f4\u7684\u6570\u503c<\/p>\r\n              <\/div>\r\n            <\/div>\r\n            <div class=\"roi-simulator-form-sales-plan roi-simulator-form-sales-plan-bottom\">\r\n              <div>\r\n                <label for=\"input-other-materials-price\">\u5176\u4ed6\u6750\u6599<\/label>\r\n                <div class=\"roi-simulator-form-sales-plan-price\"><span data-currency=\"\">\u00a5<\/span> <input id=\"input-other-materials-price\" type=\"text\" value=\"\" aria-label=\"\u5176\u4ed6\u6750\u6599\" data-max=\"1000000\" data-min=\"0\" \/><\/div>\r\n                <p class=\"roi-error-message\" style=\"display: none\" data-max-min=\"input-other-materials-price\">*\u8bf7\u8f93\u5165 0 \u81f3 1,000,000 \u4e4b\u95f4\u7684\u6570\u503c<\/p>\r\n              <\/div>\r\n              <div>\r\n                <label for=\"input-other-materials-units\">\u9500\u552e\u6570\u91cf<\/label>\r\n                <div class=\"roi-simulator-form-sales-plan-price roi-simulator-form-sales-unit\"><input id=\"input-other-materials-units\" type=\"text\" value=\"\" aria-label=\"\u9500\u552e\u6570\u91cf\" data-max=\"100000\" data-min=\"0\" \/> <span class=\"roi-simulator-form-sales-unit-pcs\">\u4ef6<\/span><\/div>\r\n                <p class=\"roi-error-message\" style=\"display: none\" data-max-min=\"input-other-materials-units\">*\u8bf7\u8f93\u5165 0 \u81f3 100,000 \u4e4b\u95f4\u7684\u6570\u503c<\/p>\r\n              <\/div>\r\n            <\/div>\r\n            <div class=\"roi-simulator-form-total\">\r\n              \u9500\u552e\u5408\u8ba1\r\n              <p class=\"dollar-box\"><span data-currency=\"\">\u00a5<\/span><span id=\"total-sales\"><\/span><\/p>\r\n            <\/div>\r\n          <\/section>\r\n          <section class=\"roi-simulator-form-sales-milling-cost\">\r\n            <h2 class=\"roi-simulator-form__title-mini\">\u6708\u5ea6\u5185\u90e8\u5207\u524a\u6210\u672c<\/h2>\r\n            <div>\r\n              <label for=\"input-material-cost-zirconia\">\u6750\u6599\u6210\u672c \/ \u4ef6<br class=\"pc-none\" \/><span>\uff08\u6c27\u5316\u9506\uff09<\/span><\/label>\r\n              <div class=\"roi-simulator-form-sales-milling-cost-box\"><span data-currency=\"\">\u00a5<\/span> <input id=\"input-material-cost-zirconia\" type=\"text\" value=\"\" aria-label=\"\u6750\u6599\u6210\u672c \/ \u4ef6\" data-max=\"100000\" data-min=\"0\" \/><\/div>\r\n              <p class=\"roi-error-message\" style=\"display: none\" data-max-min=\"input-material-cost-zirconia\">*\u8bf7\u8f93\u5165 0 \u81f3 100,000 \u4e4b\u95f4\u7684\u6570\u503c<\/p>\r\n            <\/div>\r\n            <div class=\"roi-simulator-form-toggle is-open\">\r\n              <button class=\"roi-simulator-form-toggle__button\" type=\"button\">\r\n                <span class=\"roi-simulator-form-toggle__text\">\u8be6\u60c5<\/span>\r\n                <span class=\"roi-simulator-form-toggle__arrow\"><img decoding=\"async\" src=\"https:\/\/dgshape.com\/wp-content\/uploads\/2026\/02\/arrow-right-blue.png\" alt=\"\" width=\"8\" height=\"4\" \/><\/span>\r\n              <\/button>\r\n              <div class=\"roi-simulator-form-toggle__content\">\r\n                <div class=\"roi-simulator-form-toggle__content-inner\">\u5047\u8bbe 1 \u7247\u6c27\u5316\u9506\u76d8\u7684\u4ef7\u683c\u4e3a 100 \u5143\uff0c\u53ef\u5236\u4f5c 20 \u4ef6\u4e49\u9f7f\uff0c\u5219\u5355\u4ef6\u6210\u672c\u4e3a 5 \u5143\uff08100 \u5143 \/ 20 \u4ef6\uff09\u3002<\/div>\r\n              <\/div>\r\n            <\/div>\r\n            <div class=\"u-mb-22\">\r\n              <label for=\"input-units-to-mill-zirconia\">\u5207\u524a\u6570\u91cf<span>\uff08\u6c27\u5316\u9506\uff09<\/span><\/label>\r\n              <div class=\"roi-simulator-form-sales-milling-cost-box roi-simulator-form-sales-unit\"><input id=\"input-units-to-mill-zirconia\" type=\"text\" value=\"\" aria-label=\"\u5207\u524a\u6570\u91cf\" data-max=\"100000\" data-min=\"0\" \/> <span class=\"roi-simulator-form-sales-unit-pcs\">\u4ef6<\/span><\/div>\r\n              <p class=\"roi-error-message\" style=\"display: none\" data-max-min=\"input-units-to-mill-zirconia\">*\u8bf7\u8f93\u5165 0 \u81f3 100,000 \u4e4b\u95f4\u7684\u6570\u503c<\/p>\r\n            <\/div>\r\n            <div class=\"roi-simulator-form-sales-milling-cost-sp-wrap\">\r\n              <label for=\"input-material-cost-glass\">\u6750\u6599\u6210\u672c \/ \u4ef6<span>\uff08\u73bb\u7483\u9676\u74f7\uff09<\/span> <span class=\"input-material-cost-glass-mini\">*\u4ec5\u9002\u7528\u4e8e\u6e7f\u5f0f\u5207\u524a\u673a<\/span><\/label>\r\n              <div class=\"roi-simulator-form-sales-milling-cost-box\"><span data-currency=\"\">\u00a5<\/span> <input id=\"input-material-cost-glass\" type=\"text\" value=\"\" aria-label=\"\u6750\u6599\u6210\u672c \/ \u4ef6\" data-max=\"100000\" data-min=\"0\" \/><\/div>\r\n              <p class=\"roi-error-message\" style=\"display: none\" data-max-min=\"input-material-cost-glass\">*\u8bf7\u8f93\u5165 0 \u81f3 100,000 \u4e4b\u95f4\u7684\u6570\u503c<\/p>\r\n            <\/div>\r\n            <div class=\"roi-simulator-form-toggle\">\r\n              <button class=\"roi-simulator-form-toggle__button\" type=\"button\">\r\n                <span class=\"roi-simulator-form-toggle__text\">\u8be6\u60c5<\/span>\r\n                <span class=\"roi-simulator-form-toggle__arrow\"><img decoding=\"async\" src=\"https:\/\/dgshape.com\/wp-content\/uploads\/2026\/02\/arrow-right-blue.png\" alt=\"\" width=\"8\" height=\"4\" \/><\/span>\r\n              <\/button>\r\n              <div class=\"roi-simulator-form-toggle__content\">\r\n                <div class=\"roi-simulator-form-toggle__content-inner\">\u5047\u8bbe 1 \u5305\u73bb\u7483\u9676\u74f7\u6750\u6599\u7684\u4ef7\u683c\u4e3a 100 \u5143\uff0c\u5185\u542b 5 \u4e2a\u5757\u6750\uff0c\u5219\u5355\u4ef6\u6210\u672c\u4e3a 20 \u5143\uff08100 \u5143 \/ 5 \u4e2a\u5757\u6750\uff09\u3002<\/div>\r\n              <\/div>\r\n            <\/div>\r\n            <div class=\"roi-simulator-form-sales-milling-cost-mb-margin u-mb-22\">\r\n              <label for=\"input-units-to-mill-glass\">\u5207\u524a\u6570\u91cf<span>\uff08\u73bb\u7483\u9676\u74f7\uff09<\/span><\/label>\r\n              <div class=\"roi-simulator-form-sales-milling-cost-box roi-simulator-form-sales-unit\"><input id=\"input-units-to-mill-glass\" type=\"text\" value=\"\" aria-label=\"\u5207\u524a\u6570\u91cf\" data-max=\"100000\" data-min=\"0\" \/> <span class=\"roi-simulator-form-sales-unit-pcs\">\u4ef6<\/span><\/div>\r\n              <p class=\"roi-error-message\" style=\"display: none\" data-max-min=\"input-units-to-mill-glass\">*\u8bf7\u8f93\u5165 0 \u81f3 100,000 \u4e4b\u95f4\u7684\u6570\u503c<\/p>\r\n            <\/div>\r\n            <div class=\"u-mb-22\">\r\n              <label for=\"input-material-cost-other-materials\">\u6750\u6599\u6210\u672c \/ \u4ef6<br\/><span>\uff08\u5176\u4ed6\u6750\u6599\uff09<\/span><\/label>\r\n              <div class=\"roi-simulator-form-sales-milling-cost-box\"><span data-currency=\"\">\u00a5<\/span> <input id=\"input-material-cost-other-materials\" type=\"text\" value=\"\" aria-label=\"\u6750\u6599\u6210\u672c \/ \u4ef6\" data-max=\"100000\" data-min=\"0\" \/><\/div>\r\n              <p class=\"roi-error-message\" style=\"display: none\" data-max-min=\"input-material-cost-other-materials\">*\u8bf7\u8f93\u5165 0 \u81f3 100,000 \u4e4b\u95f4\u7684\u6570\u503c<\/p>\r\n            <\/div>\r\n            <div class=\"u-mb-22\">\r\n              <label for=\"input-units-to-mill-other-materials\">\u5207\u524a\u6570\u91cf<span>\uff08\u5176\u4ed6\u6750\u6599\uff09<\/span><\/label>\r\n              <div class=\"roi-simulator-form-sales-milling-cost-box roi-simulator-form-sales-unit\"><input id=\"input-units-to-mill-other-materials\" type=\"text\" value=\"\" aria-label=\"\u5207\u524a\u6570\u91cf\" data-max=\"100000\" data-min=\"0\" \/> <span class=\"roi-simulator-form-sales-unit-pcs\">\u4ef6<\/span><\/div>\r\n              <p class=\"roi-error-message\" style=\"display: none\" data-max-min=\"input-units-to-mill-other-materials\">*\u8bf7\u8f93\u5165 0 \u81f3 100,000 \u4e4b\u95f4\u7684\u6570\u503c<\/p>\r\n            <\/div>\r\n            <div class=\"roi-simulator-form-sales-milling-cost-mb-margin\">\r\n              <label for=\"input-labor-cost\">\u4eba\u5de5\u6210\u672c \/ \u5c0f\u65f6<\/label>\r\n              <div class=\"roi-simulator-form-sales-milling-cost-box\"><span data-currency=\"\">\u00a5<\/span> <input id=\"input-labor-cost\" type=\"text\" value=\"\" aria-label=\"\u4eba\u5de5\u6210\u672c \/ \u5c0f\u65f6\" data-max=\"100000\" data-min=\"0\" \/><\/div>\r\n              <p class=\"roi-error-message\" style=\"display: none\" data-max-min=\"input-labor-cost\">*\u8bf7\u8f93\u5165 0 \u81f3 100,000 \u4e4b\u95f4\u7684\u6570\u503c<\/p>\r\n            <\/div>\r\n            <div class=\"roi-simulator-form-total roi-simulator-form-sales-milling-cost-total\">\r\n              <div>\r\n                \u6750\u6599\u6210\u672c\u5408\u8ba1\r\n                <p class=\"dollar-box\"><span data-currency=\"\">\u00a5<\/span><span id=\"total-material-cost\"><\/span><\/p>\r\n              <\/div>\r\n              <div>\r\n                \u4eba\u5de5\u6210\u672c\u5408\u8ba1\r\n                <p class=\"dollar-box\"><span data-currency=\"\">\u00a5<\/span><span id=\"total-labor-cost\"><\/span><\/p>\r\n              <\/div>\r\n              <div>\r\n                \u5185\u90e8\u5207\u524a\u6210\u672c\u5408\u8ba1\r\n                <p class=\"dollar-box\"><span data-currency=\"\">\u00a5<\/span><span id=\"total-milling-cost\"><\/span><\/p>\r\n              <\/div>\r\n            <\/div>\r\n          <\/section>\r\n          <section class=\"roi-simulator-form-sales-loan\">\r\n            <h2 class=\"roi-simulator-form__title-mini\">\u8d37\u6b3e<\/h2>\r\n            <div class=\"roi-simulator-form-sales-loan-button\">\r\n              <label>\r\n                \u4f7f\u7528\u8d37\u6b3e\r\n                <input id=\"input-use-loan\" checked=\"checked\" type=\"checkbox\" \/>\r\n              <\/label>\r\n            <\/div>\r\n            <div>\r\n              <label for=\"input-down-payment\">\u9996\u4ed8\u6b3e<\/label>\r\n              <div class=\"roi-simulator-form-sales-loan-box\"><span data-currency=\"\">\u00a5<\/span> <input id=\"input-down-payment\" type=\"text\" value=\"\" aria-label=\"\u9996\u4ed8\u6b3e\" data-max=\"10000000\" data-min=\"0\" \/><\/div>\r\n              <p class=\"roi-error-message\" style=\"display: none\" data-max-min=\"input-down-payment\">*\u8bf7\u8f93\u5165 0 \u81f3 10,000,000 \u4e4b\u95f4\u7684\u6570\u503c<\/p>\r\n            <\/div>\r\n            <div>\r\n              <label for=\"input-annual-interest-rate\">\u5e74\u5229\u7387<\/label>\r\n              <div class=\"roi-simulator-form-sales-loan-box roi-simulator-form-sales-loan-second-box\"><input id=\"input-annual-interest-rate\" type=\"text\" value=\"\" aria-label=\"\u5e74\u5229\u7387\" data-max=\"50\" data-min=\"0\" \/> %<\/div>\r\n              <p class=\"roi-error-message\" style=\"display: none\" data-max-min=\"input-annual-interest-rate\">*\u8bf7\u8f93\u5165 0 \u81f3 50 \u4e4b\u95f4\u7684\u6570\u503c<\/p>\r\n            <\/div>\r\n            <div>\r\n              <label for=\"input-repayment-period\">\u8fd8\u6b3e\u671f\u9650\uff08\u6708\uff09<\/label>\r\n              <div class=\"roi-simulator-form-sales-loan-box\"><input id=\"input-repayment-period\" type=\"text\" value=\"\" aria-label=\"\u8fd8\u6b3e\u671f\u9650\uff08\u6708\uff09\" data-max=\"240\" data-min=\"0\" \/><\/div>\r\n              <p class=\"roi-error-message\" style=\"display: none\" data-max-min=\"input-repayment-period\">*\u8bf7\u8f93\u5165 0 \u81f3 240 \u4e4b\u95f4\u7684\u6570\u503c<\/p>\r\n            <\/div>\r\n            <div class=\"roi-simulator-form-total\">\r\n              \u6708\u8fd8\u6b3e\u989d\r\n              <p class=\"dollar-box\"><span data-currency=\"\">\u00a5<\/span><span id=\"monthly-loan-payment\"><\/span><\/p>\r\n            <\/div>\r\n          <\/section>\r\n          <button id=\"button-calculate\" class=\"roi-error\" type=\"button\">\u67e5\u770b\u7ed3\u679c<\/button>\r\n          <button id=\"button-reset\" type=\"reset\">\u91cd\u7f6e<\/button>\r\n        <\/form>\r\n        <div id=\"summary-wrapper\" class=\"roi-simulator-summary\">\r\n          <h2 class=\"roi-simulator-summary-title\">\u6c47\u603b<\/h2>\r\n          <div id=\"summary-before-calculate\">\u8bf7\u8f93\u5165\u6570\u503c\u5e76\u67e5\u770b\u7ed3\u679c<\/div>\r\n          <div id=\"summary-after-calculate\">\r\n            <section class=\"summary-after-calculate-first\">\r\n              <dl class=\"summary-after-calculate-top summary-after-calculate-initial-cost\">\r\n                <dt>\u521d\u59cb\u8d39\u7528<\/dt>\r\n                <dd class=\"dollar-box\"><span data-currency=\"\">\u00a5<\/span><span id=\"summary-initial-cost\"><\/span><\/dd>\r\n              <\/dl>\r\n              <dl class=\"summary-after-calculate-top summary-after-calculate-payback-period\">\r\n                <dt>\u56de\u6536\u671f<\/dt>\r\n                <dd><span id=\"summary-payback-period\"><\/span>\u4e2a\u6708<\/dd>\r\n              <\/dl>\r\n              <div class=\"summary-after-calculate-bottom summary-after-calculate-blue\">\r\n                <dl id=\"summary-monthly-profit-during-repaying-loan-wrapper\">\r\n                  <dt>\u8fd8\u6b3e\u671f\u95f4\u7684\u6708\u5229\u6da6<\/dt>\r\n                  <dd class=\"dollar-box\"><span data-currency=\"\">\u00a5<\/span><span id=\"summary-monthly-profit-during-repaying-loan\"><\/span><\/dd>\r\n                <\/dl>\r\n                <dl>\r\n                  <dt id=\"summary-monthly-profit-title\"><span data-use-loan=\"true\">\u6708\u5229\u6da6<\/span> <span data-use-loan=\"false\">\u65e0\u8d37\u6b3e\u65f6\u7684\u6708\u5229\u6da6<\/span><\/dt>\r\n                  <dd class=\"dollar-box\"><span data-currency=\"\">\u00a5<\/span><span id=\"summary-monthly-profit-without-loan\"><\/span><\/dd>\r\n                <\/dl>\r\n                <dl>\r\n                  <dt>\u6708\u9500\u552e\u5408\u8ba1<\/dt>\r\n                  <dd class=\"dollar-box\"><span data-currency=\"\">\u00a5<\/span><span id=\"summary-monthly-total-sales\"><\/span><\/dd>\r\n                <\/dl>\r\n              <\/div>\r\n              <div class=\"summary-after-calculate-bottom summary-after-calculate-red\">\r\n                <dl>\r\n                  <dt>\u6708\u5ea6\u5185\u90e8\u5207\u524a\u6210\u672c<\/dt>\r\n                  <dd class=\"dollar-box\"><span data-currency=\"\">\u00a5<\/span><span id=\"summary-monthly-milling-cost\"><\/span><\/dd>\r\n                <\/dl>\r\n                <dl>\r\n                  <dt>\u6708\u8fd8\u6b3e\u989d<\/dt>\r\n                  <dd class=\"dollar-box\"><span data-currency=\"\">\u00a5<\/span><span id=\"summary-monthly-loan-payment\"><\/span><\/dd>\r\n                <\/dl>\r\n              <\/div>\r\n            <\/section>\r\n            <section class=\"summary-after-calculate-chart\">\r\n              <div id=\"chart-section\"><\/div>\r\n            <\/section>\r\n            <section class=\"summary-after-calculate-last\">\r\n              <h3>\u8ba1\u7b97\u7ed3\u679c\u4ec5\u4f9b\u53c2\u8003\uff0c\u53ef\u80fd\u56e0\u5404\u56fd\u6216\u5730\u533a\u7684\u6cd5\u5f8b\u3001\u7a0e\u5236\u548c\u91d1\u878d\u5236\u5ea6\u800c\u6709\u6240\u4e0d\u540c\u3002<\/h3>\r\n            <\/section>\r\n          <\/div>\r\n        <\/div>\r\n      <\/div>\r\n    <\/div>\r\n  <\/div>\r\n\r\n\r\n  <script>\r\n(function () {\r\n  const init = () => {\r\n    const _triggerWindowWidth = 375;\r\n    const elmMetaViewport = document.querySelector('meta[name=\"viewport\"]');\r\n    if (elmMetaViewport) {\r\n      const updateViewport = () => {\r\n        const viewportValue =\r\n          window.outerWidth < _triggerWindowWidth\r\n            ? `width=${_triggerWindowWidth}, user-scalable=no, target-densitydpi=device-dpi`\r\n            : 'width=device-width, initial-scale=1';\r\n        elmMetaViewport.setAttribute('content', viewportValue);\r\n      };\r\n      updateViewport();\r\n      window.addEventListener('resize', updateViewport);\r\n    }\r\n\r\n    const bindToggles = () => {\r\n      document.querySelectorAll('.roi-simulator-form-toggle').forEach((toggle) => {\r\n        const currentButton = toggle.querySelector('.roi-simulator-form-toggle__button');\r\n        const content = toggle.querySelector('.roi-simulator-form-toggle__content');\r\n        const inner = toggle.querySelector('.roi-simulator-form-toggle__content-inner');\r\n        if (!currentButton || !content || !inner) return;\r\n\r\n        const button = currentButton.cloneNode(true);\r\n        currentButton.replaceWith(button);\r\n        content.style.overflow = 'hidden';\r\n\r\n        if (toggle.classList.contains('is-open')) {\r\n          content.style.height = inner.scrollHeight + 'px';\r\n          content.style.marginBottom = '10px';\r\n        } else {\r\n          content.style.height = '0px';\r\n          content.style.marginBottom = '0px';\r\n        }\r\n\r\n        button.addEventListener('click', (event) => {\r\n          event.preventDefault();\r\n          event.stopImmediatePropagation();\r\n          const isOpen = toggle.classList.contains('is-open');\r\n\r\n          if (isOpen) {\r\n            content.style.height = inner.scrollHeight + 'px';\r\n            content.style.marginBottom = '10px';\r\n            content.offsetHeight;\r\n            content.style.height = '0px';\r\n            content.style.marginBottom = '0px';\r\n            toggle.classList.remove('is-open');\r\n          } else {\r\n            content.style.height = inner.scrollHeight + 'px';\r\n            content.style.marginBottom = '10px';\r\n            toggle.classList.add('is-open');\r\n          }\r\n        });\r\n      });\r\n    };\r\n\r\n    bindToggles();\r\n    window.addEventListener('load', bindToggles);\r\n  };\r\n\r\n  if (document.readyState === 'loading') {\r\n    document.addEventListener('DOMContentLoaded', init);\r\n  } else {\r\n    init();\r\n  }\r\n})();\r\n<\/script>\r\n\r\n<script>\r\n  \/**\r\n   * \u30b0\u30e9\u30d5\u306e\u4e0b\u9650\u306f\u5ea7\u6a19\u306e\u6700\u5c0f\u5024\u3001\u6700\u5927\u5024\u306f\u6700\u5c0f\u5024\u306e\u30d7\u30e9\u30b9\u5024\u306b\u3057\u305f\u30b7\u30df\u30e5\u30ec\u30fc\u30bf\u30fc\r\n   *\/\r\n  \r\n  addEventListener('DOMContentLoaded', () => {\r\n  \r\n    \/\/ \u753b\u9762\u5e45\u304c768\u672a\u6e80\u304b\u30c1\u30a7\u30c3\u30af\r\n    const IS_MOBILE = window.innerWidth < 768;\r\n  \r\n    \/\/ \u5165\u529b\u6b04\u306e\u80cc\u666f\u8272\r\n    const INPUT_BACKGROUND_COLOR_NORMAL = '#F5F5F5';\r\n    const INPUT_BACKGROUND_COLOR_ERROR = '#FFEFEF';\r\n  \r\n    \/\/ \u30c7\u30d5\u30a9\u30eb\u30c8\u306e\u8fd4\u6e08\u671f\u9593\uff08\u6708\uff09\r\n    const REPAYMENT_PERIOD_MONTH_DEFAULT = 36;\r\n  \r\n    \/\/ Sales Price\u30d5\u30a3\u30fc\u30eb\u30c9\u306e\u521d\u56de\u5165\u529b\u30d5\u30e9\u30b0\uff08\u521d\u56de\u5165\u529b\u6642\u306e\u307f\u30c1\u30a7\u30c3\u30af\u3057\u306a\u3044\uff09\r\n    \/\/ \uff08\u3053\u306e\u5165\u529b\u6b04\u306f\u30bb\u30c3\u30c8\u3067\u5165\u529b\u3059\u308b\u5fc5\u8981\u304c\u3042\u308b\u305f\u3081\u3001\u6700\u521d\u306e1\u3064\u76ee\u3092\u5165\u529b\u3057\u305f\u3089\u5fc5\u305a\u30a8\u30e9\u30fc\u306b\u306a\u308b\u305f\u3081\uff09\r\n    let isFirstSalesPriceInput = true;\r\n  \r\n    \/\/ Unit\u7cfb\u306e\u5165\u529b\u30d5\u30a3\u30fc\u30eb\u30c9\u306e\u9023\u52d5\u51e6\u7406\u4e2d\u30d5\u30e9\u30b0\uff08\u7121\u9650\u30eb\u30fc\u30d7\u9632\u6b62\uff09\r\n    let isSyncingZirconia = false;\r\n    let isSyncingGlass = false;\r\n    let isSyncingOtherMaterials = false;\r\n  \r\n    \/\/ ====================================================================================================================================\r\n    \/\/ \u8981\u7d20\u306e\u53d6\u5f97\r\n    \/\/ ====================================================================================================================================\r\n  \r\n    \/\/ \u30d5\u30a9\u30fc\u30e0\r\n    const roiSimulatorForm = document.getElementById('roi-simulator-form');\r\n    const allInputs = roiSimulatorForm.querySelectorAll('input[type=\"text\"]');\r\n  \r\n    \/\/ \u901a\u8ca8\u9078\u629e\r\n    const selectCurrency = document.getElementById('select-currency'); \/\/ \u30bb\u30ec\u30af\u30c8\u30dc\u30c3\u30af\u30b9\r\n    const currencyLabels = document.querySelectorAll('[data-currency]'); \/\/ \u901a\u8ca8\u30e9\u30d9\u30eb\r\n  \r\n    \/\/ \u5165\u529b\u7cfb\r\n    const inputDwxPrice = document.getElementById('input-dwx-price');\r\n    const inputOtherExpenses = document.getElementById('input-other-expenses');\r\n    const inputZirconiaPrice = document.getElementById('input-zirconia-price');\r\n    const inputZirconiaUnits = document.getElementById('input-zirconia-units');\r\n    const inputGlassCeramicsPrice = document.getElementById('input-glass-ceramics-price');\r\n    const inputGlassCeramicsUnits = document.getElementById('input-glass-ceramics-units');\r\n    const inputOtherMaterialsPrice = document.getElementById('input-other-materials-price');\r\n    const inputOtherMaterialsUnits = document.getElementById('input-other-materials-units');\r\n    const inputMaterialCostZirconia = document.getElementById('input-material-cost-zirconia');\r\n    const inputUnitsToMillZirconia = document.getElementById('input-units-to-mill-zirconia');\r\n    const inputMaterialCostGlass = document.getElementById('input-material-cost-glass');\r\n    const inputUnitsToMillGlass = document.getElementById('input-units-to-mill-glass');\r\n    const inputMaterialCostOtherMaterials = document.getElementById('input-material-cost-other-materials');\r\n    const inputUnitsToMillOtherMaterials = document.getElementById('input-units-to-mill-other-materials');\r\n    const inputLaborCost = document.getElementById('input-labor-cost');\r\n    const inputUseLoan = document.getElementById('input-use-loan');\r\n    const inputDownPayment = document.getElementById('input-down-payment');\r\n    const inputAnnualInterestRate = document.getElementById('input-annual-interest-rate');\r\n    const inputRepaymentPeriod = document.getElementById('input-repayment-period');\r\n  \r\n    \/\/ \u30dc\u30bf\u30f3\u7cfb\r\n    const buttonCalculate = document.getElementById('button-calculate');\r\n    const buttonReset = document.getElementById('button-reset');\r\n  \r\n    \/\/ \u7d50\u679c\u8868\u793a\u8981\u7d20\uff08\u30d5\u30a9\u30fc\u30e0\u5185\uff09\r\n    const totalInitialInvestment = document.getElementById('total-initial-investment');\r\n    const totalSales = document.getElementById('total-sales');\r\n    const totalMaterialCost = document.getElementById('total-material-cost');\r\n    const totalLaborCost = document.getElementById('total-labor-cost');\r\n    const totalMillingCost = document.getElementById('total-milling-cost');\r\n    const monthlyLoanPayment = document.getElementById('monthly-loan-payment');\r\n  \r\n    \/\/ \u7d50\u679c\u8868\u793a\u8981\u7d20\uff08Summary\u30bb\u30af\u30b7\u30e7\u30f3\uff09\r\n    const summaryWrapper = document.getElementById('summary-wrapper');\r\n    const summaryBeforeCalculate = document.getElementById('summary-before-calculate');\r\n    const summaryAfterCalculate = document.getElementById('summary-after-calculate');\r\n    const summaryInitialCost = document.getElementById('summary-initial-cost');\r\n    const summaryPaybackPeriod = document.getElementById('summary-payback-period');\r\n    const summaryMonthlyProfitDuringRepayingLoan = document.getElementById('summary-monthly-profit-during-repaying-loan');\r\n    const summaryMonthlyProfitDuringRepayingLoanWrapper = document.getElementById('summary-monthly-profit-during-repaying-loan-wrapper');\r\n    const summaryMonthlyProfitWithoutLoan = document.getElementById('summary-monthly-profit-without-loan');\r\n    const summaryMonthlyTotalSales = document.getElementById('summary-monthly-total-sales');\r\n    const summaryMonthlyMillingCost = document.getElementById('summary-monthly-milling-cost');\r\n    const summaryMonthlyLoanPayment = document.getElementById('summary-monthly-loan-payment');\r\n    const summaryTitle = document.querySelector('.roi-simulator-summary-title');\r\n    const summaryMonthlyProfitTitle = document.getElementById('summary-monthly-profit-title');\r\n    const summaryMonthlyProfitTitleWithLoan = summaryMonthlyProfitTitle?.querySelector('[data-use-loan=\"true\"]');\r\n    const summaryMonthlyProfitTitleWithoutLoan = summaryMonthlyProfitTitle?.querySelector('[data-use-loan=\"false\"]');\r\n  \r\n    \/\/ \u30b0\u30e9\u30d5\r\n    const chartSection = document.getElementById('chart-section');\r\n  \r\n    \/\/ ====================================================================================================================================\r\n    \/\/ \u5404\u7a2e\u51e6\u7406\u306e\u5b9a\u7fa9\uff08\u95a2\u6570\u5b9a\u7fa9\uff09\r\n    \/\/ ====================================================================================================================================\r\n  \r\n    \/**\r\n     * \u5168\u89d2\u6570\u5b57\u3092\u534a\u89d2\u306b\u5909\u63db\r\n     *\/\r\n    const convertFullWidthToHalfWidth = (str) => {\r\n      return str.replace(\/[\uff10-\uff19]\/g, (s) => {\r\n        return String.fromCharCode(s.charCodeAt(0) - 0xFEE0);\r\n      });\r\n    };\r\n  \r\n    \/**\r\n     * \u6570\u5024\u306e\u307f\u3092\u62bd\u51fa\uff08\u5c0f\u6570\u70b9\u542b\u3080\uff09\r\n     *\/\r\n    const extractNumbers = (str) => {\r\n      \/\/ \u5168\u89d2\u3092\u534a\u89d2\u306b\u5909\u63db\r\n      const halfWidth = convertFullWidthToHalfWidth(str);\r\n      \/\/ \u6570\u5024\u3068\u5c0f\u6570\u70b9\u306e\u307f\u3092\u62bd\u51fa\r\n      let numeric = halfWidth.replace(\/[^\\d.]\/g, '');\r\n      \/\/ \u6700\u521d\u306e\u5c0f\u6570\u70b9\u306e\u307f\u3092\u6b8b\u3057\u3001\u305d\u308c\u4ee5\u964d\u306e\u5c0f\u6570\u70b9\u306f\u524a\u9664\r\n      const firstDotIndex = numeric.indexOf('.');\r\n      if (firstDotIndex !== -1) {\r\n        const beforeDot = numeric.substring(0, firstDotIndex + 1);\r\n        const afterDot = numeric.substring(firstDotIndex + 1).replace(\/\\.\/g, '');\r\n        numeric = beforeDot + afterDot;\r\n      }\r\n      \/\/ \u5148\u982d\u304c\u5c0f\u6570\u70b9\u3067\u59cb\u307e\u308b\u5834\u5408\u30010\u3092\u5148\u982d\u306b\u8ffd\u52a0\r\n      if (numeric.startsWith('.')) {\r\n        numeric = '0' + numeric;\r\n      }\r\n      \/\/ \u5148\u982d\u304c0\u3067\u59cb\u307e\u308a\u3001\u305d\u306e\u5f8c\u306b\u6570\u5b57\u304c\u7d9a\u304f\u5834\u5408\uff08\u4f8b: \"01\", \"02\"\uff09\u3001\u5165\u529b\u3092\u7121\u8996\u3057\u30660\u306e\u307e\u307e\u306b\u3059\u308b\r\n      \/\/ \u305f\u3060\u3057 \"0.\" \u3084 \"0\" \u5358\u4f53\u306f\u8a31\u53ef\r\n      if (numeric.length > 1 && numeric.startsWith('0') && numeric[1] !== '.') {\r\n        numeric = '0';\r\n      }\r\n      return numeric;\r\n    };\r\n  \r\n    \/**\r\n     * \u30ab\u30f3\u30de\u3092\u524a\u9664\u3057\u3066\u6570\u5024\u6587\u5b57\u5217\u3092\u8fd4\u3059\r\n     *\/\r\n    const removeCommas = (str) => {\r\n      return str.replace(\/,\/g, '');\r\n    };\r\n  \r\n    \/**\r\n     * \u6570\u5024\u6587\u5b57\u5217\u306b\u30ab\u30f3\u30de\u3092\u8ffd\u52a0\r\n     *\/\r\n    const addCommas = (str) => {\r\n      \/\/ \u30ab\u30f3\u30de\u3092\u524a\u9664\r\n      const withoutCommas = removeCommas(str);\r\n      \/\/ \u5c0f\u6570\u70b9\u3067\u5206\u5272\r\n      const parts = withoutCommas.split('.');\r\n      \/\/ \u6574\u6570\u90e8\u5206\u306b\u30ab\u30f3\u30de\u3092\u8ffd\u52a0\r\n      parts[0] = parts[0].replace(\/\\B(?=(\\d{3})+(?!\\d))\/g, ',');\r\n      \/\/ \u7d50\u5408\u3057\u3066\u8fd4\u3059\r\n      return parts.join('.');\r\n    };\r\n  \r\n    \/**\r\n     * \u73fe\u5728\u306e\u901a\u8ca8\u3092\u53cd\u6620\r\n     *\/\r\n    const reflectCurrentCurrency = () => {\r\n      const selectedCurrency = selectCurrency.value;\r\n      currencyLabels.forEach(label => {\r\n        label.textContent = selectedCurrency;\r\n      });\r\n    };\r\n  \r\n    \/**\r\n     * Initial Investment Cost \u306e\u8a08\u7b97\r\n     *\/\r\n    const calculateTotalInitialInvestment = () => {\r\n      \/\/ \u30a8\u30e9\u30fc\u30c1\u30a7\u30c3\u30af\uff1a\u95a2\u9023\u3059\u308b\u5165\u529b\u30d5\u30a3\u30fc\u30eb\u30c9\u306b\u30a8\u30e9\u30fc\u304c\u3042\u308b\u5834\u5408\u306f\u8a08\u7b97\u3092\u30b9\u30ad\u30c3\u30d7\r\n      if (hasErrorForInputs([inputDwxPrice, inputOtherExpenses])) {\r\n        return;\r\n      }\r\n      const dwxPrice = Number(removeCommas(inputDwxPrice.value)) || 0;\r\n      const otherExpenses = Number(removeCommas(inputOtherExpenses.value)) || 0;\r\n      const total = dwxPrice + otherExpenses;\r\n      totalInitialInvestment.textContent = total.toLocaleString();\r\n      \/\/ Monthly Loan Payment\u3082\u518d\u8a08\u7b97\r\n      calculateMonthlyLoanPayment();\r\n    };\r\n  \r\n    \/**\r\n     * Monthly Sales Plan \u306e\u8a08\u7b97\r\n     *\/\r\n    const calculateTotalMonthlySalesPlan = () => {\r\n      \/\/ \u30a8\u30e9\u30fc\u30c1\u30a7\u30c3\u30af\uff1aSales Price\u30bb\u30c3\u30c8\u306e\u30a8\u30e9\u30fc\u30e1\u30c3\u30bb\u30fc\u30b8\u304c\u8868\u793a\u3055\u308c\u3066\u3044\u308b\u5834\u5408\u3001\u307e\u305f\u306f\u95a2\u9023\u3059\u308b\u5165\u529b\u30d5\u30a3\u30fc\u30eb\u30c9\u306b\u30a8\u30e9\u30fc\u304c\u3042\u308b\u5834\u5408\u306f\u8a08\u7b97\u3092\u30b9\u30ad\u30c3\u30d7\r\n      const salesPriceErrorMessage = document.getElementById('sales-price-error-message');\r\n      const hasSalesPriceError = salesPriceErrorMessage && salesPriceErrorMessage.style.display === 'block';\r\n      if (hasSalesPriceError || hasErrorForInputs([inputZirconiaPrice, inputZirconiaUnits, inputGlassCeramicsPrice, inputGlassCeramicsUnits, inputOtherMaterialsPrice, inputOtherMaterialsUnits])) {\r\n        return;\r\n      }\r\n      const zirconiaPrice = Number(removeCommas(inputZirconiaPrice.value)) || 0;\r\n      const zirconiaUnits = Number(removeCommas(inputZirconiaUnits.value)) || 0;\r\n      const glassCeramicsPrice = Number(removeCommas(inputGlassCeramicsPrice.value)) || 0;\r\n      const glassCeramicsUnits = Number(removeCommas(inputGlassCeramicsUnits.value)) || 0;\r\n      const otherMaterialsPrice = Number(removeCommas(inputOtherMaterialsPrice.value)) || 0;\r\n      const otherMaterialsUnits = Number(removeCommas(inputOtherMaterialsUnits.value)) || 0;\r\n      const total = (zirconiaPrice * zirconiaUnits) + (glassCeramicsPrice * glassCeramicsUnits) + (otherMaterialsPrice * otherMaterialsUnits);\r\n      totalSales.textContent = total.toLocaleString();\r\n    };\r\n  \r\n    \/**\r\n     * Total Material Cost \u306e\u8a08\u7b97\r\n     *\/\r\n    const calculateTotalMaterialCost = () => {\r\n      \/\/ \u30a8\u30e9\u30fc\u30c1\u30a7\u30c3\u30af\uff1a\u95a2\u9023\u3059\u308b\u5165\u529b\u30d5\u30a3\u30fc\u30eb\u30c9\u306b\u30a8\u30e9\u30fc\u304c\u3042\u308b\u5834\u5408\u306f\u8a08\u7b97\u3092\u30b9\u30ad\u30c3\u30d7\r\n      if (hasErrorForInputs([inputMaterialCostZirconia, inputUnitsToMillZirconia, inputMaterialCostGlass, inputUnitsToMillGlass, inputMaterialCostOtherMaterials, inputUnitsToMillOtherMaterials])) {\r\n        return;\r\n      }\r\n      const materialCostZirconia = Number(removeCommas(inputMaterialCostZirconia.value)) || 0;\r\n      const unitsToMillZirconia = Number(removeCommas(inputUnitsToMillZirconia.value)) || 0;\r\n      const materialCostGlass = Number(removeCommas(inputMaterialCostGlass.value)) || 0;\r\n      const unitsToMillGlass = Number(removeCommas(inputUnitsToMillGlass.value)) || 0;\r\n      const materialCostOtherMaterials = Number(removeCommas(inputMaterialCostOtherMaterials.value)) || 0;\r\n      const unitsToMillOtherMaterials = Number(removeCommas(inputUnitsToMillOtherMaterials.value)) || 0;\r\n      const total = (materialCostZirconia * unitsToMillZirconia) + (materialCostGlass * unitsToMillGlass) + (materialCostOtherMaterials * unitsToMillOtherMaterials);\r\n      totalMaterialCost.textContent = total.toLocaleString();\r\n      \/\/ Total In-house Milling Cost\u3082\u518d\u8a08\u7b97\r\n      calculateTotalMillingCost();\r\n    };\r\n  \r\n    \/**\r\n     * Total Labor Cost \u306e\u8a08\u7b97\r\n     *\/\r\n    const calculateTotalLaborCost = () => {\r\n      \/\/ \u30a8\u30e9\u30fc\u30c1\u30a7\u30c3\u30af\uff1a\u95a2\u9023\u3059\u308b\u5165\u529b\u30d5\u30a3\u30fc\u30eb\u30c9\u306b\u30a8\u30e9\u30fc\u304c\u3042\u308b\u5834\u5408\u306f\u8a08\u7b97\u3092\u30b9\u30ad\u30c3\u30d7\r\n      if (hasErrorForInputs([inputLaborCost, inputUnitsToMillZirconia, inputUnitsToMillGlass, inputUnitsToMillOtherMaterials])) {\r\n        return;\r\n      }\r\n      const laborCost = Number(removeCommas(inputLaborCost.value)) || 0;\r\n      const unitsToMillZirconia = Number(removeCommas(inputUnitsToMillZirconia.value)) || 0;\r\n      const unitsToMillGlass = Number(removeCommas(inputUnitsToMillGlass.value)) || 0;\r\n      const unitsToMillOtherMaterials = Number(removeCommas(inputUnitsToMillOtherMaterials.value)) || 0;\r\n      const total = laborCost * (unitsToMillZirconia + unitsToMillGlass + unitsToMillOtherMaterials) * 2;\r\n      totalLaborCost.textContent = total.toLocaleString();\r\n      \/\/ Total In-house Milling Cost\u3082\u518d\u8a08\u7b97\r\n      calculateTotalMillingCost();\r\n    };\r\n  \r\n    \/**\r\n     * Total In-house Milling Cost \u306e\u8a08\u7b97\r\n     *\/\r\n    const calculateTotalMillingCost = () => {\r\n      \/\/ \u30a8\u30e9\u30fc\u30c1\u30a7\u30c3\u30af\uff1a\u95a2\u9023\u3059\u308b\u5165\u529b\u30d5\u30a3\u30fc\u30eb\u30c9\u306b\u30a8\u30e9\u30fc\u304c\u3042\u308b\u5834\u5408\u306f\u8a08\u7b97\u3092\u30b9\u30ad\u30c3\u30d7\r\n      if (hasErrorForInputs([inputMaterialCostZirconia, inputUnitsToMillZirconia, inputMaterialCostGlass, inputUnitsToMillGlass, inputMaterialCostOtherMaterials, inputUnitsToMillOtherMaterials, inputLaborCost])) {\r\n        return;\r\n      }\r\n      const materialCost = Number(removeCommas(totalMaterialCost.textContent)) || 0;\r\n      const laborCost = Number(removeCommas(totalLaborCost.textContent)) || 0;\r\n      const total = materialCost + laborCost;\r\n      totalMillingCost.textContent = total.toLocaleString();\r\n    };\r\n  \r\n    \/**\r\n     * Monthly Loan Payment \u306e\u8a08\u7b97\r\n     *\/\r\n    const calculateMonthlyLoanPayment = () => {\r\n      \/\/ \u30ed\u30fc\u30f3\u3092\u4f7f\u7528\u3057\u306a\u3044\u5834\u5408\u306f0\u3092\u8fd4\u3059\r\n      if (!inputUseLoan.checked) {\r\n        monthlyLoanPayment.textContent = '0';\r\n        return;\r\n      }\r\n      \/\/ \u30a8\u30e9\u30fc\u30c1\u30a7\u30c3\u30af\uff1a\u95a2\u9023\u3059\u308b\u5165\u529b\u30d5\u30a3\u30fc\u30eb\u30c9\u306b\u30a8\u30e9\u30fc\u304c\u3042\u308b\u5834\u5408\u306f\u8a08\u7b97\u3092\u30b9\u30ad\u30c3\u30d7\r\n      if (hasErrorForInputs([inputDwxPrice, inputOtherExpenses, inputDownPayment, inputAnnualInterestRate, inputRepaymentPeriod])) {\r\n        return;\r\n      }\r\n      const initialInvestment = Number(removeCommas(totalInitialInvestment.textContent)) || 0;\r\n      const downPayment = Number(removeCommas(inputDownPayment.value)) || 0;\r\n      const loanAmount = initialInvestment - downPayment; \/\/ \u30ed\u30fc\u30f3\u91d1\u984d = \u521d\u671f\u6295\u8cc7\u984d - \u982d\u91d1\r\n      const annualInterestRate = Number(removeCommas(inputAnnualInterestRate.value)) || 0;\r\n      const repaymentPeriodMonthInputValue = Number(removeCommas(inputRepaymentPeriod.value)) || 0;\r\n      const repaymentPeriodMonth = repaymentPeriodMonthInputValue > 0 ? repaymentPeriodMonthInputValue : REPAYMENT_PERIOD_MONTH_DEFAULT;\r\n  \r\n      if (loanAmount <= 0 || annualInterestRate <= 0 || repaymentPeriodMonth <= 0) {\r\n        monthlyLoanPayment.textContent = '0';\r\n        return;\r\n      }\r\n      \/\/ \u5e74\u5229\u3092\u6708\u5229\u306b\u5909\u63db\r\n      \/\/   Math.round(...) \u2192 \u5c0f\u6570\u70b9\u7b2c2\u4f4d\u307e\u3067\u56db\u6368\u4e94\u5165\r\n      \/\/   \/ 100 \/ 100 \u2192     \u6700\u521d\u306e\/100\u3067%\u306b\u5909\u63db\u3057\u3066\u3001\u6b21\u306e\/100\u3067\u8a08\u7b97\u7528\u306e\u6570\u5024\u306b\u5909\u63db\r\n      const monthlyInterestRate = Math.round(annualInterestRate \/ 12 * 100) \/ 100 \/ 100;\r\n      const getMonthlyLoanPaymentValue = () => {\r\n        const value1_1 = (initialInvestment - downPayment) * monthlyInterestRate;\r\n        const value1_2 = (1 + monthlyInterestRate) ** repaymentPeriodMonth;\r\n        const value1 = value1_1 * value1_2;\r\n        const value2 = ((1 + monthlyInterestRate) ** repaymentPeriodMonth) - 1;\r\n        return value1 \/ value2;\r\n      }\r\n      const monthlyLoanPaymentValue = getMonthlyLoanPaymentValue();\r\n      monthlyLoanPayment.textContent = Math.round(monthlyLoanPaymentValue).toLocaleString();\r\n    };\r\n  \r\n    \/**\r\n     * Use Loan \u30c1\u30a7\u30c3\u30af\u30dc\u30c3\u30af\u30b9\u306b\u5fdc\u3058\u3066\u30ed\u30fc\u30f3\u95a2\u9023\u5165\u529b\u6b04\u306e\u6709\u52b9\/\u7121\u52b9\u3092\u5207\u308a\u66ff\u3048\r\n     *\/\r\n    const toggleLoanInputsDisabled = () => {\r\n      const isEnabled = inputUseLoan.checked;\r\n      inputDownPayment.disabled = !isEnabled;\r\n      inputAnnualInterestRate.disabled = !isEnabled;\r\n      inputRepaymentPeriod.disabled = !isEnabled;\r\n      \/\/ \u7121\u52b9\u5316\u3055\u308c\u305f\u5834\u5408\u306f\u8a08\u7b97\u3092\u5b9f\u884c\r\n      calculateMonthlyLoanPayment();\r\n    };\r\n  \r\n    \/**\r\n     * Summary\u30bb\u30af\u30b7\u30e7\u30f3\u306e\u8a08\u7b97\r\n     *\/\r\n    const calculateSummary = () => {\r\n      \/\/ summary-monthly-total-sales = total-sales\r\n      const totalSalesValue = Number(removeCommas(totalSales.textContent)) || 0;\r\n      summaryMonthlyTotalSales.textContent = totalSalesValue.toLocaleString();\r\n  \r\n      \/\/ summary-monthly-milling-cost = total-milling-cost\r\n      const totalMillingCostValue = Number(removeCommas(totalMillingCost.textContent)) || 0;\r\n      summaryMonthlyMillingCost.textContent = totalMillingCostValue.toLocaleString();\r\n  \r\n      \/\/ summary-monthly-loan-payment = monthly-loan-payment\r\n      const monthlyLoanPaymentValue = Number(removeCommas(monthlyLoanPayment.textContent)) || 0;\r\n      summaryMonthlyLoanPayment.textContent = monthlyLoanPaymentValue.toLocaleString();\r\n  \r\n      \/\/ summary-monthly-profit-during-repaying-loan = summary-monthly-total-sales - summary-monthly-loan-payment\r\n      const monthlyProfitWithLoan = (totalSalesValue - totalMillingCostValue) - monthlyLoanPaymentValue;\r\n      summaryMonthlyProfitDuringRepayingLoan.textContent = monthlyProfitWithLoan.toLocaleString();\r\n  \r\n      \/\/ summary-monthly-profit-without-loan = summary-monthly-total-sales - summary-monthly-milling-cost\r\n      const monthlyProfitWithoutLoan = totalSalesValue - totalMillingCostValue;\r\n      summaryMonthlyProfitWithoutLoan.textContent = monthlyProfitWithoutLoan.toLocaleString();\r\n  \r\n      \/\/ summary-monthly-profit-title\u306e\u8868\u793a\/\u975e\u8868\u793a\u3092\u5207\u308a\u66ff\u3048\r\n      if (summaryMonthlyProfitTitleWithLoan) {\r\n        summaryMonthlyProfitTitleWithLoan.style.display = inputUseLoan.checked ? 'inline' : 'none';\r\n      }\r\n      if (summaryMonthlyProfitTitleWithoutLoan) {\r\n        summaryMonthlyProfitTitleWithoutLoan.style.display = inputUseLoan.checked ? 'none' : 'inline';\r\n      }\r\n  \r\n      \/\/ summary-monthly-profit-during-repaying-loan-wrapper\u306e\u8868\u793a\/\u975e\u8868\u793a\u3092\u5207\u308a\u66ff\u3048\r\n      if (summaryMonthlyProfitDuringRepayingLoanWrapper) {\r\n        summaryMonthlyProfitDuringRepayingLoanWrapper.style.display = inputUseLoan.checked ? 'flex' : 'none';\r\n      }\r\n  \r\n      \/\/ summary-initial-cost\r\n      \/\/ \u30ed\u30fc\u30f3\u304cON\u306e\u3068\u304d\u306finput-down-payment\u3001OFF\u306e\u3068\u304d\u306ftotal-initial-investment\u3092\u8868\u793a\r\n      let summaryInitialCostValue = 0;\r\n      if (inputUseLoan.checked) {\r\n        \/\/ \u30ed\u30fc\u30f3\u304cON\u306e\u3068\u304d\u306f\u982d\u91d1\u3092\u8868\u793a\r\n        summaryInitialCostValue = Number(removeCommas(inputDownPayment.value)) || 0;\r\n      } else {\r\n        \/\/ \u30ed\u30fc\u30f3\u304cOFF\u306e\u3068\u304d\u306f\u521d\u671f\u6295\u8cc7\u984d\u3092\u8868\u793a\r\n        summaryInitialCostValue = Number(removeCommas(totalInitialInvestment.textContent)) || 0;\r\n      }\r\n      summaryInitialCost.textContent = summaryInitialCostValue.toLocaleString();\r\n  \r\n      \/\/ summary-payback-period\u306e\u8a08\u7b97\u7528\u306b\u521d\u671f\u6295\u8cc7\u984d\u3092\u53d6\u5f97\r\n      const initialInvestmentValue = Number(removeCommas(totalInitialInvestment.textContent)) || 0;\r\n  \r\n      \/\/ summary-payback-period\r\n      let paybackPeriod = 0;\r\n      if (inputUseLoan.checked) {\r\n        \/\/ \u30ed\u30fc\u30f3\u306b\u30c1\u30a7\u30c3\u30af\u304c\u5165\u3063\u3066\u308b\u306a\u3089: total-initial-investment \/ summary-monthly-profit-during-repaying-loan\r\n        if (monthlyProfitWithLoan > 0) {\r\n          paybackPeriod = initialInvestmentValue \/ monthlyProfitWithLoan;\r\n        }\r\n      } else {\r\n        \/\/ \u30ed\u30fc\u30f3\u306b\u30c1\u30a7\u30c3\u30af\u304c\u5165\u3063\u3066\u3044\u306a\u3044\u306a\u3089: total-initial-investment \/ summary-monthly-profit-without-loan\r\n        if (monthlyProfitWithoutLoan > 0) {\r\n          paybackPeriod = initialInvestmentValue \/ monthlyProfitWithoutLoan;\r\n        }\r\n      }\r\n      summaryPaybackPeriod.textContent = paybackPeriod.toFixed(1);\r\n    };\r\n  \r\n    \/**\r\n     * Summary\u8868\u793a\u3092\u5207\u308a\u66ff\u3048\r\n     *\/\r\n    const showSummaryBeforeCalculate = () => {\r\n      summaryBeforeCalculate.style.display = 'block';\r\n      summaryAfterCalculate.style.display = 'none';\r\n      summaryTitle.classList.add('roi-simulator-summary-title-before');\r\n      summaryTitle.classList.remove('roi-simulator-summary-title-after');\r\n    };\r\n    const showSummaryAfterCalculate = () => {\r\n      summaryBeforeCalculate.style.display = 'none';\r\n      summaryAfterCalculate.style.display = 'block';\r\n      summaryTitle.classList.remove('roi-simulator-summary-title-before');\r\n      summaryTitle.classList.add('roi-simulator-summary-title-after');\r\n    };\r\n  \r\n    \/**\r\n     * \u7279\u5b9a\u306e\u5165\u529b\u30d5\u30a3\u30fc\u30eb\u30c9\u306b\u95a2\u9023\u3059\u308b\u30a8\u30e9\u30fc\u304c\u3042\u308b\u304b\u3069\u3046\u304b\u3092\u30c1\u30a7\u30c3\u30af\r\n     * @param {Array<HTMLElement>} inputs - \u30c1\u30a7\u30c3\u30af\u3059\u308b\u5165\u529b\u30d5\u30a3\u30fc\u30eb\u30c9\u306e\u914d\u5217\r\n     * @returns {boolean} \u30a8\u30e9\u30fc\u304c\u3042\u308b\u5834\u5408true\r\n     *\/\r\n    const hasErrorForInputs = (inputs) => {\r\n      for (const input of inputs) {\r\n        \/\/ required\u5c5e\u6027\u306e\u30a8\u30e9\u30fc\u30c1\u30a7\u30c3\u30af\r\n        if (input.hasAttribute('required')) {\r\n          const inputId = input.id;\r\n          const errorMessage = document.querySelector(`[data-required=\"${inputId}\"]`);\r\n          if (errorMessage && errorMessage.style.display === 'block') {\r\n            return true;\r\n          }\r\n        }\r\n        \/\/ data-max\u3068data-min\u306e\u30a8\u30e9\u30fc\u30c1\u30a7\u30c3\u30af\r\n        if (input.hasAttribute('data-max') && input.hasAttribute('data-min')) {\r\n          const inputId = input.id;\r\n          const errorMessage = document.querySelector(`[data-max-min=\"${inputId}\"]`);\r\n          if (errorMessage && errorMessage.style.display === 'block') {\r\n            return true;\r\n          }\r\n        }\r\n      }\r\n      return false;\r\n    };\r\n  \r\n    \/**\r\n     * \u30a8\u30e9\u30fc\u6570\u3092\u30ab\u30a6\u30f3\u30c8\u3057\u3001\u8a08\u7b97\u30dc\u30bf\u30f3\u306b\u30af\u30e9\u30b9\u3092\u4ed8\u4e0e\/\u524a\u9664\r\n     *\/\r\n    const toggleButtonCalculateClass = () => {\r\n      let errorCount = 0;\r\n  \r\n      \/\/ .roi-error-message\u8981\u7d20\u3092\u53d6\u5f97\u3057\u3066\u3001\u8868\u793a\u3055\u308c\u3066\u3044\u308b\u30a8\u30e9\u30fc\u3092\u30ab\u30a6\u30f3\u30c8\r\n      const errorMessages = document.querySelectorAll('.roi-error-message');\r\n      errorMessages.forEach(msg => {\r\n        if (msg.style.display === 'block') {\r\n          errorCount++;\r\n        }\r\n      });\r\n  \r\n      \/\/ \u30dc\u30bf\u30f3\u306b\u30af\u30e9\u30b9\u3092\u4ed8\u4e0e\/\u524a\u9664\r\n      if (errorCount > 0) {\r\n        buttonCalculate.classList.add('roi-error');\r\n      } else {\r\n        buttonCalculate.classList.remove('roi-error');\r\n      }\r\n    };\r\n  \r\n    \/**\r\n     * \u30a8\u30e9\u30fc\u30e1\u30c3\u30bb\u30fc\u30b8\u306e\u8868\u793a\/\u975e\u8868\u793a\u3092\u5236\u5fa1\uff08\u5229\u7528\u7b87\u6240\u4f8b\uff1a#input-dwx-price\uff09\r\n     * @param {HTMLElement} input - \u5165\u529b\u8981\u7d20\r\n     * @param {boolean} showError - \u30a8\u30e9\u30fc\u3092\u8868\u793a\u3059\u308b\u304b\u3069\u3046\u304b\r\n     *\/\r\n    const toggleErrorMessage = (input, showError) => {\r\n      if (input.hasAttribute('required')) {\r\n        const inputId = input.id;\r\n        const errorMessage = document.querySelector(`[data-required=\"${inputId}\"]`);\r\n        if (errorMessage) {\r\n          errorMessage.style.display = showError ? 'block' : 'none';\r\n          input.style.background = showError ? INPUT_BACKGROUND_COLOR_ERROR : INPUT_BACKGROUND_COLOR_NORMAL;\r\n          toggleButtonCalculateClass();\r\n        }\r\n      }\r\n    };\r\n  \r\n    \/**\r\n     * data-max\u3068data-min\u306e\u7bc4\u56f2\u30c1\u30a7\u30c3\u30af\r\n     * @param {HTMLElement} input - \u5165\u529b\u8981\u7d20\r\n     * @returns {boolean} \u30a8\u30e9\u30fc\u304c\u3042\u308b\u5834\u5408true\r\n     *\/\r\n    const validateMaxMin = (input) => {\r\n      if (!input.hasAttribute('data-max') || !input.hasAttribute('data-min')) {\r\n        return false;\r\n      }\r\n      const value = input.value;\r\n      const hasValue = value && value.trim() !== '';\r\n      \/\/ \u5024\u304c\u7a7a\u306e\u5834\u5408\u306f\u30a8\u30e9\u30fc\u306a\u3057\uff08required\u5c5e\u6027\u3067\u30c1\u30a7\u30c3\u30af\u3059\u308b\u305f\u3081\uff09\r\n      if (!hasValue) {\r\n        return false;\r\n      }\r\n      const numericValue = Number(removeCommas(value));\r\n      const maxValue = Number(input.getAttribute('data-max'));\r\n      const minValue = Number(input.getAttribute('data-min'));\r\n      \/\/ \u7bc4\u56f2\u5916\u306e\u5834\u5408\u30a8\u30e9\u30fc\r\n      return numericValue < minValue || numericValue > maxValue;\r\n    };\r\n  \r\n    \/**\r\n     * data-max\u3068data-min\u306e\u30a8\u30e9\u30fc\u30e1\u30c3\u30bb\u30fc\u30b8\u306e\u8868\u793a\/\u975e\u8868\u793a\u3092\u5236\u5fa1\r\n     * @param {HTMLElement} input - \u5165\u529b\u8981\u7d20\r\n     * @param {boolean} showError - \u30a8\u30e9\u30fc\u3092\u8868\u793a\u3059\u308b\u304b\u3069\u3046\u304b\r\n     *\/\r\n    const toggleMaxMinErrorMessage = (input, showError) => {\r\n      if (input.hasAttribute('data-max') && input.hasAttribute('data-min')) {\r\n        const inputId = input.id;\r\n        const errorMessage = document.querySelector(`[data-max-min=\"${inputId}\"]`);\r\n        if (errorMessage) {\r\n          errorMessage.style.display = showError ? 'block' : 'none';\r\n          input.style.background = showError ? INPUT_BACKGROUND_COLOR_ERROR : INPUT_BACKGROUND_COLOR_NORMAL;\r\n          toggleButtonCalculateClass();\r\n        }\r\n      }\r\n    };\r\n  \r\n    \/**\r\n     * Sales Price\u30bb\u30c3\u30c8\u306e\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\r\n     * Zirconia\u3068Glass Ceramics\u306e\u30bb\u30c3\u30c8\u3067\u3001price\u3068units\u306f\u4e21\u65b9\u5165\u529b\u3059\u308b\u5fc5\u8981\u304c\u3042\u308b\r\n     * \u3069\u3061\u3089\u304b\u306e\u30bb\u30c3\u30c8\u304c\u5b8c\u5168\u306b\u5165\u529b\u3055\u308c\u3066\u3044\u308c\u3070OK\r\n     * @returns {boolean} \u30a8\u30e9\u30fc\u304c\u3042\u308b\u5834\u5408true\r\n     *\/\r\n    const validateSalesPriceSets = () => {\r\n      \/\/ \u521d\u56de\u5165\u529b\u6642\u306e\u307f\u30c1\u30a7\u30c3\u30af\u3057\u306a\u3044\r\n      if (isFirstSalesPriceInput) {\r\n        return false;\r\n      }\r\n  \r\n      \/\/ Zirconia\u30bb\u30c3\u30c8\u306e\u30c1\u30a7\u30c3\u30af\uff1a\u4e21\u65b9\u5165\u529b\u3055\u308c\u3066\u3044\u308b\u3001\u307e\u305f\u306f\u4e21\u65b9\u3068\u3082\u7a7a\r\n      const zirconiaPriceHasValue = inputZirconiaPrice.value && inputZirconiaPrice.value.trim() !== '';\r\n      const zirconiaUnitsHasValue = inputZirconiaUnits.value && inputZirconiaUnits.value.trim() !== '';\r\n      const zirconiaSetValid = (zirconiaPriceHasValue && zirconiaUnitsHasValue) || (!zirconiaPriceHasValue && !zirconiaUnitsHasValue);\r\n  \r\n      \/\/ Glass Ceramics\u30bb\u30c3\u30c8\u306e\u30c1\u30a7\u30c3\u30af\uff1a\u4e21\u65b9\u5165\u529b\u3055\u308c\u3066\u3044\u308b\u3001\u307e\u305f\u306f\u4e21\u65b9\u3068\u3082\u7a7a\r\n      const glassPriceHasValue = inputGlassCeramicsPrice.value && inputGlassCeramicsPrice.value.trim() !== '';\r\n      const glassUnitsHasValue = inputGlassCeramicsUnits.value && inputGlassCeramicsUnits.value.trim() !== '';\r\n      const glassSetValid = (glassPriceHasValue && glassUnitsHasValue) || (!glassPriceHasValue && !glassUnitsHasValue);\r\n  \r\n      \/\/ Other Materials\u30bb\u30c3\u30c8\u306e\u30c1\u30a7\u30c3\u30af\uff1a\u4e21\u65b9\u5165\u529b\u3055\u308c\u3066\u3044\u308b\u3001\u307e\u305f\u306f\u4e21\u65b9\u3068\u3082\u7a7a\r\n      const otherMaterialsPriceHasValue = inputOtherMaterialsPrice.value && inputOtherMaterialsPrice.value.trim() !== '';\r\n      const otherMaterialsUnitsHasValue = inputOtherMaterialsUnits.value && inputOtherMaterialsUnits.value.trim() !== '';\r\n      const otherMaterialsSetValid = (otherMaterialsPriceHasValue && otherMaterialsUnitsHasValue) || (!otherMaterialsPriceHasValue && !otherMaterialsUnitsHasValue);\r\n  \r\n      \/\/ \u3069\u3061\u3089\u304b\u306e\u30bb\u30c3\u30c8\u304c\u5b8c\u5168\u306b\u5165\u529b\u3055\u308c\u3066\u3044\u308b\u5fc5\u8981\u304c\u3042\u308b\r\n      const hasValidSet = (zirconiaPriceHasValue && zirconiaUnitsHasValue) || (glassPriceHasValue && glassUnitsHasValue) || (otherMaterialsPriceHasValue && otherMaterialsUnitsHasValue);\r\n  \r\n      \/\/ \u30a8\u30e9\u30fc\u304c\u3042\u308b\u5834\u5408\uff1a\u30bb\u30c3\u30c8\u304c\u7121\u52b9\u3001\u307e\u305f\u306f\u6709\u52b9\u306a\u30bb\u30c3\u30c8\u304c\u306a\u3044\r\n      const hasError = !zirconiaSetValid || !glassSetValid || !otherMaterialsSetValid || !hasValidSet;\r\n  \r\n      const errorMessage = document.getElementById('sales-price-error-message');\r\n      if (errorMessage) {\r\n        errorMessage.style.display = hasError ? 'block' : 'none';\r\n        toggleButtonCalculateClass();\r\n  \r\n        \/\/ \u30a8\u30e9\u30fc\u304c\u3042\u308b\u5834\u5408\u3001\u8a72\u5f53\u3059\u308binput\u306e\u80cc\u666f\u8272\u3092\u5909\u66f4\r\n        if (hasError) {\r\n          if (!zirconiaSetValid) {\r\n            inputZirconiaPrice.style.background = INPUT_BACKGROUND_COLOR_ERROR;\r\n            inputZirconiaUnits.style.background = INPUT_BACKGROUND_COLOR_ERROR;\r\n          }\r\n          if (!glassSetValid) {\r\n            inputGlassCeramicsPrice.style.background = INPUT_BACKGROUND_COLOR_ERROR;\r\n            inputGlassCeramicsUnits.style.background = INPUT_BACKGROUND_COLOR_ERROR;\r\n          }\r\n          if (!otherMaterialsSetValid) {\r\n            inputOtherMaterialsPrice.style.background = INPUT_BACKGROUND_COLOR_ERROR;\r\n            inputOtherMaterialsUnits.style.background = INPUT_BACKGROUND_COLOR_ERROR;\r\n          }\r\n        } else {\r\n          \/\/ \u30a8\u30e9\u30fc\u304c\u306a\u3044\u5834\u5408\u3001\u80cc\u666f\u8272\u3092\u30ea\u30bb\u30c3\u30c8\r\n          inputZirconiaPrice.style.background = '';\r\n          inputZirconiaUnits.style.background = '';\r\n          inputGlassCeramicsPrice.style.background = '';\r\n          inputGlassCeramicsUnits.style.background = '';\r\n          inputOtherMaterialsPrice.style.background = '';\r\n          inputOtherMaterialsUnits.style.background = '';\r\n        }\r\n      }\r\n  \r\n      return hasError;\r\n    };\r\n  \r\n  \r\n  \r\n  \r\n  \r\n    \/\/ ********************************************************************\r\n    \/\/ *****************************************************\r\n    \/\/ *****************************************\r\n    \/\/ \u3053\u3053\u304b\u3089\u30b0\u30e9\u30d5\u95a2\u9023\u306e\u51e6\u7406\r\n  \r\n    \/**\r\n     * x\u8ef8\u306e\u30e1\u30e2\u30ea\u9593\u9694\u3092\u53d6\u5f97\uff08\u8868\u793a\u3059\u308b\u6700\u5927\u6708\u6570\u306b\u5fdc\u3058\u3066\u5909\u52d5\uff09\r\n     * @param {number} maxMonths - \u8868\u793a\u3059\u308b\u6700\u5927\u6708\u6570\r\n     * @returns {number} \u30e1\u30e2\u30ea\u9593\u9694\uff08\u6708\u5358\u4f4d\uff09\r\n     *\/\r\n    const getXAxisTickInterval = (maxMonths) => {\r\n      const maxTicks = 10; \/\/ \u30e1\u30e2\u30ea\u6570\u306e\u4e0a\u9650\r\n      \/\/ \u30e1\u30e2\u30ea\u6570 = Math.floor(maxMonths \/ interval) + 1 <= maxTicks\r\n      \/\/ Math.floor(maxMonths \/ interval) <= maxTicks - 1\r\n      \/\/ maxMonths \/ interval <= maxTicks - 1\r\n      \/\/ interval >= maxMonths \/ (maxTicks - 1)\r\n      const minInterval = maxMonths \/ (maxTicks - 1);\r\n  \r\n      if (maxMonths <= 12) {\r\n        \/\/ 12\u30f6\u6708\u4ee5\u4e0b\u306e\u5834\u5408\u30011\u30f6\u6708\u3054\u3068\u3092\u512a\u5148\uff08\u305f\u3060\u3057\u4e0a\u9650\u3092\u8d85\u3048\u306a\u3044\u3088\u3046\u306b\uff09\r\n        const interval = Math.ceil(minInterval);\r\n        return Math.max(1, interval);\r\n      } else if (maxMonths <= 59) {\r\n        \/\/ 59\u30f6\u6708\u4ee5\u4e0b\u306e\u5834\u5408\u30013\u306e\u500d\u6570\u3067\u5207\u308a\u4e0a\u3052\r\n        return Math.ceil(minInterval \/ 3) * 3;\r\n      } else if (maxMonths <= 119) {\r\n        \/\/ 119\u30f6\u6708\u4ee5\u4e0b\u306e\u5834\u5408\u30016\u306e\u500d\u6570\u3067\u5207\u308a\u4e0a\u3052\r\n        return Math.ceil(minInterval \/ 6) * 6;\r\n      } else {\r\n        \/\/ 120\u30f6\u6708\u4ee5\u4e0a\u306e\u5834\u5408\u300112\u306e\u500d\u6570\u3067\u5207\u308a\u4e0a\u3052\uff08\u5e74\u5358\u4f4d\uff09\r\n        return Math.ceil(minInterval \/ 12) * 12;\r\n      }\r\n    };\r\n  \r\n    \/**\r\n     * x\u8ef8\u306e\u30e9\u30d9\u30eb\u3092\u751f\u6210\r\n     * @param {number} maxMonths - \u8868\u793a\u3059\u308b\u6700\u5927\u6708\u6570\r\n     * @returns {Array<string>} x\u8ef8\u306e\u30e9\u30d9\u30eb\u914d\u5217\r\n     *\/\r\n    const generateXAxisLabels = (maxMonths) => {\r\n      const interval = getXAxisTickInterval(maxMonths);\r\n      const labels = [];\r\n      const tickValues = [];\r\n      \/\/ 0\u30f6\u6708\u304b\u3089\u958b\u59cb\u3057\u3066\u3001\u9593\u9694\u3054\u3068\u306b\u30e9\u30d9\u30eb\u3092\u751f\u6210\r\n      \/\/ \u9593\u9694\u304c12\u306e\u500d\u6570\u306e\u5834\u5408\u306f\u5e74\u5358\u4f4d\u3067\u8868\u793a\r\n      const isYearInterval = interval % 12 === 0 && interval >= 12;\r\n      for (let month = 0; month <= maxMonths; month += interval) {\r\n        tickValues.push(month);\r\n        if (isYearInterval) {\r\n          \/\/ \u5e74\u5358\u4f4d\u306e\u5834\u5408\r\n          const years = Math.floor(month \/ 12);\r\n          labels.push(`${years}\u5e74`);\r\n        } else {\r\n          \/\/ \u6708\u5358\u4f4d\u306e\u5834\u5408\r\n          labels.push(`${month}\u30f6\u6708`);\r\n        }\r\n      }\r\n      return labels;\r\n    };\r\n  \r\n    \/**\r\n     * x\u8ef8\u306e\u8a2d\u5b9a\u3092\u8a08\u7b97\r\n     * @returns {Object} x\u8ef8\u306e\u8a2d\u5b9a\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\r\n     *\/\r\n    const calculateXAxisConfig = () => {\r\n      \/\/ \u5229\u76ca\u306e\u7d2f\u7a4d\u304c0\u306b\u306a\u308b\u6708\uff08Payback Period\uff09\u3092\u53d6\u5f97\r\n      const paybackPeriod = parseFloat(summaryPaybackPeriod.textContent) || 0;\r\n  \r\n      \/\/ \u7d2f\u7a4d\u5229\u76ca\u304c\u521d\u671f\u6295\u8cc7\u984d\u3092\u4e0a\u56de\u308b\u6708\u3092\u8a08\u7b97\r\n      const initialCost = Number(removeCommas(totalInitialInvestment.textContent)) || 0;\r\n      const monthlySales = Number(removeCommas(summaryMonthlyTotalSales.textContent)) || 0;\r\n      const monthlyCost = Number(removeCommas(summaryMonthlyMillingCost.textContent)) || 0;\r\n      const monthlyLoanPayment = Number(removeCommas(summaryMonthlyLoanPayment.textContent)) || 0;\r\n      const repaymentPeriodInput = Number(removeCommas(inputRepaymentPeriod.value)) || 0;\r\n      const repaymentPeriod = repaymentPeriodInput > 0 ? repaymentPeriodInput : REPAYMENT_PERIOD_MONTH_DEFAULT;\r\n      const useLoan = inputUseLoan.checked;\r\n  \r\n      let cumulativeProfit = -initialCost;\r\n      let monthWhenExceedsInitialCost = null;\r\n  \r\n      \/\/ \u7d2f\u7a4d\u5229\u76ca\u304c\u521d\u671f\u6295\u8cc7\u984d\u3092\u4e0a\u56de\u308b\u6708\u3092\u898b\u3064\u3051\u308b\uff08\u6700\u59271000\u30f6\u6708\u307e\u3067\u691c\u7d22\uff09\r\n      for (let month = 0; month <= 1000; month++) {\r\n        if (month === 0) {\r\n          cumulativeProfit = -initialCost;\r\n        } else {\r\n          let monthlyProfit = monthlySales - monthlyCost;\r\n          if (useLoan && month >= 1 && month <= repaymentPeriod) {\r\n            monthlyProfit -= monthlyLoanPayment;\r\n          }\r\n          cumulativeProfit += monthlyProfit;\r\n        }\r\n  \r\n        \/\/ \u7d2f\u7a4d\u5229\u76ca\u304c\u521d\u671f\u6295\u8cc7\u984d\u3092\u4e0a\u56de\u3063\u305f\u5834\u5408\r\n        if (cumulativeProfit > initialCost) {\r\n          monthWhenExceedsInitialCost = month;\r\n          break;\r\n        }\r\n      }\r\n  \r\n      \/\/ x\u8ef8\u306e\u6700\u5927\u5024\uff1a\u7d2f\u7a4d\u5229\u76ca\u304c\u521d\u671f\u6295\u8cc7\u984d\u3092\u4e0a\u56de\u308b\u6708\u304c\u3042\u308b\u5834\u5408\u306f\u305d\u306e\u6708\u3001\u306a\u3044\u5834\u5408\u306fPayback Period + 12\u30f6\u6708\r\n      let maxMonths;\r\n      if (monthWhenExceedsInitialCost !== null) {\r\n        maxMonths = monthWhenExceedsInitialCost;\r\n      } else {\r\n        maxMonths = Math.ceil(paybackPeriod) + 12;\r\n      }\r\n  \r\n      \/\/ \u30e1\u30e2\u30ea\u9593\u9694\u3092\u53d6\u5f97\r\n      const tickInterval = getXAxisTickInterval(maxMonths);\r\n      \/\/ x\u8ef8\u306e\u30e9\u30d9\u30eb\u3092\u751f\u6210\r\n      const labels = generateXAxisLabels(maxMonths);\r\n      return {\r\n        maxMonths: maxMonths,\r\n        tickInterval: tickInterval,\r\n        labels: labels,\r\n        paybackPeriod: paybackPeriod\r\n      };\r\n    };\r\n  \r\n    \/**\r\n     * y\u8ef8\u306e\u30e9\u30d9\u30eb\u3092\u751f\u6210\uff08\u6700\u5c0f\u5024\u30010\u3001\u6700\u5927\u5024\u306e3\u3064\u306e\u307f\uff09\r\n     * @param {number} minValue - y\u8ef8\u306e\u6700\u5c0f\u5024\uff08\u30de\u30a4\u30ca\u30b9\u5024\uff09\r\n     * @param {number} maxValue - y\u8ef8\u306e\u6700\u5927\u5024\uff08\u30d7\u30e9\u30b9\u5024\uff09\r\n     * @returns {Array<string>} y\u8ef8\u306e\u30e9\u30d9\u30eb\u914d\u5217\r\n     *\/\r\n    const generateYAxisLabels = (minValue, maxValue) => {\r\n      const labels = [];\r\n      \/\/ \u6700\u5c0f\u5024\u30010\u3001\u6700\u5927\u5024\u306e3\u3064\u306e\u307f\r\n      labels.push(minValue.toLocaleString());\r\n      labels.push(0);\r\n      labels.push(maxValue.toLocaleString());\r\n      return labels;\r\n    };\r\n  \r\n    \/**\r\n     * \u30b0\u30e9\u30d5\u3092\u8868\u793a\r\n     *\/\r\n    const displayChart = () => {\r\n      const xAxisConfig = calculateXAxisConfig();\r\n  \r\n      \/\/ \u307e\u305a\u7d2f\u7a4d\u5229\u76ca\u306e\u6700\u5c0f\u5024\u3092\u8a08\u7b97\u3059\u308b\u305f\u3081\u306b\u3001\u3059\u3079\u3066\u306e\u6708\u306e\u7d2f\u7a4d\u5229\u76ca\u3092\u8a08\u7b97\r\n      const initialCost = Number(removeCommas(totalInitialInvestment.textContent)) || 0;\r\n      const monthlySales = Number(removeCommas(summaryMonthlyTotalSales.textContent)) || 0;\r\n      const monthlyCost = Number(removeCommas(summaryMonthlyMillingCost.textContent)) || 0;\r\n      const monthlyLoanPayment = Number(removeCommas(summaryMonthlyLoanPayment.textContent)) || 0;\r\n      const repaymentPeriodInput = Number(removeCommas(inputRepaymentPeriod.value)) || 0;\r\n      const repaymentPeriod = repaymentPeriodInput > 0 ? repaymentPeriodInput : REPAYMENT_PERIOD_MONTH_DEFAULT;\r\n      const useLoan = inputUseLoan.checked;\r\n      const maxMonths = xAxisConfig.maxMonths;\r\n  \r\n      \/\/ \u7d2f\u7a4d\u5229\u76ca\u306e\u6700\u5c0f\u5024\u3092\u8a08\u7b97\r\n      let cumulativeProfit = -initialCost;\r\n      let minCumulativeProfit = cumulativeProfit;\r\n      for (let month = 0; month <= maxMonths; month++) {\r\n        if (month === 0) {\r\n          cumulativeProfit = -initialCost;\r\n        } else {\r\n          let monthlyProfit = monthlySales - monthlyCost;\r\n          if (useLoan && month >= 1 && month <= repaymentPeriod) {\r\n            monthlyProfit -= monthlyLoanPayment;\r\n          }\r\n          cumulativeProfit += monthlyProfit;\r\n        }\r\n        if (cumulativeProfit < minCumulativeProfit) {\r\n          minCumulativeProfit = cumulativeProfit;\r\n        }\r\n      }\r\n  \r\n      \/\/ y\u8ef8\u306e\u8a2d\u5b9a\uff1a\u6700\u5c0f\u5024\u306f\u7d2f\u7a4d\u5229\u76ca\u306e\u6700\u5c0f\u5024\u3001\u6700\u5927\u5024\u306f\u6700\u5c0f\u5024\u306e\u7d76\u5bfe\u5024\uff08\u5bfe\u79f0\uff09\r\n      const yAxisMinValue = minCumulativeProfit;\r\n      const yAxisMaxValue = Math.abs(minCumulativeProfit);\r\n      const yAxisLabels = generateYAxisLabels(yAxisMinValue, yAxisMaxValue);\r\n      const yAxisConfig = {\r\n        minValue: yAxisMinValue,\r\n        maxValue: yAxisMaxValue,\r\n        labels: yAxisLabels,\r\n        initialCost: initialCost\r\n      };\r\n  \r\n      \/\/ \u30b0\u30e9\u30d5\u306e\u30b5\u30a4\u30ba\u8a2d\u5b9a\r\n      const chartWidth = chartSection.clientWidth;\r\n      const chartHeight = 400;\r\n  \r\n      \/\/ \u521d\u671f\u6295\u8cc7\u984d\u306e\u6841\u6570\u306b\u5fdc\u3058\u3066\u30b0\u30e9\u30d5\u306e\u5de6\u5074\u306e\u4f59\u767d\u3092\u52d5\u7684\u306b\u8a08\u7b97\uff085\u6841\u306770px\u3092\u57fa\u6e96\uff09\r\n      const getLeftMargin = () => {\r\n        const initialCost = yAxisConfig.initialCost;\r\n        const digitCount = initialCost > 0 ? Math.floor(Math.log10(Math.abs(initialCost))) + 1 : 1;\r\n        if (IS_MOBILE) {\r\n          \/\/ \u30e2\u30d0\u30a4\u30eb\u3067\u306f\u30e9\u30d9\u30eb\u3092\u56de\u8ee2\u3055\u305b\u308b\u306e\u3067\u3001\u6841\u6570\u306f\u8003\u616e\u3057\u306a\u304f\u3066\u3044\u3044\uff08\u6a2a\u5e45\u304c\u6841\u6570\u306b\u5fdc\u3058\u3066\u5909\u308f\u3089\u306a\u3044\u304b\u3089\uff09\r\n          return 20;\r\n        } else {\r\n          \/\/ 5\u6841\u306770px\u306b\u306a\u308b\u3088\u3046\u306b\u8a08\u7b97: leftMargin = 50 + (\u6841\u6570 - 3) * 10\uff08\u6700\u5c0f\u5024\u306f40px\u3001\u6700\u5927\u5024\u306f\u5236\u9650\u306a\u3057\uff09\r\n          return Math.max(40, 50 + (digitCount - 3) * 10);\r\n        }\r\n      };\r\n      const leftMargin = getLeftMargin();\r\n      const bottomMargin = 50; \/\/ x\u8ef8\u30e9\u30d9\u30eb\u306e\u30b9\u30da\u30fc\u30b9\r\n      const topMargin = 20;\r\n      const rightMargin = 20;\r\n      const graphWidth = chartWidth - leftMargin - rightMargin;\r\n      const graphHeight = chartHeight - topMargin - bottomMargin;\r\n  \r\n      \/\/ x\u8ef8\u306e0\u5730\u70b9\u306e\u4f4d\u7f6e\uff08\u30b0\u30e9\u30d5\u30a8\u30ea\u30a2\u5185\u3067\u306e\u4f4d\u7f6e\uff09\r\n      const xAxisZeroX = leftMargin;\r\n      const tickInterval = xAxisConfig.tickInterval;\r\n      \/\/ \u9593\u9694\u304c12\u306e\u500d\u6570\u306e\u5834\u5408\u306f\u5e74\u5358\u4f4d\u3067\u8868\u793a\r\n      const xAxisLabelType = (tickInterval % 12 === 0 && tickInterval >= 12) ? 'Year' : 'Month';\r\n  \r\n      \/\/ SVG\u8981\u7d20\u3092\u4f5c\u6210\r\n      let svg = `\r\n        <svg width=\"${chartWidth}\" height=\"${chartHeight}\">\r\n          <!-- \u30b0\u30ea\u30c3\u30c9\u7dda -->\r\n      `;\r\n  \r\n      \/\/ x\u8ef8\u306e0\u5730\u70b9\u304b\u3089\u4e0a\u306b\u5411\u304b\u3063\u3066\u7e26\u7dda\u3092\u5f15\u304f\r\n      svg += `<line x1=\"${xAxisZeroX}\" y1=\"${topMargin}\" x2=\"${xAxisZeroX}\" y2=\"${topMargin + graphHeight}\" stroke=\"#D9D9D9\" stroke-width=\"1\"\/>`;\r\n  \r\n      \/\/ y\u8ef8\u306e3\u3064\u306e\u30e1\u30e2\u30ea\u304b\u3089\u53f3\u306b\u5411\u304b\u3063\u3066\u6a2a\u7dda\u3092\u5f15\u304f\r\n      const yValues = [yAxisConfig.minValue, 0, yAxisConfig.maxValue];\r\n      yValues.forEach((value) => {\r\n        \/\/ y\u8ef8\u306e\u5024\u304b\u3089\u30b0\u30e9\u30d5\u5185\u306ey\u5ea7\u6a19\u3092\u8a08\u7b97\r\n        const ratio = (value - yAxisConfig.minValue) \/ (yAxisConfig.maxValue - yAxisConfig.minValue);\r\n        const y = topMargin + graphHeight - (ratio * graphHeight);\r\n        \/\/ \u53f3\u7aef\u307e\u3067\u7dda\u3092\u5f15\u304f\r\n        svg += `<line x1=\"${leftMargin}\" y1=\"${y}\" x2=\"${leftMargin + graphWidth}\" y2=\"${y}\" stroke=\"#D9D9D9\" stroke-width=\"1\"\/>`;\r\n      });\r\n  \r\n      \/\/ y\u8ef8\u306e\u30e1\u30e2\u30ea\u30e9\u30d9\u30eb\uff08\u5de6\u5074\uff09\r\n      yValues.forEach((value, index) => {\r\n        const ratio = (value - yAxisConfig.minValue) \/ (yAxisConfig.maxValue - yAxisConfig.minValue);\r\n        let y = topMargin + graphHeight - (ratio * graphHeight);\r\n        const label = yAxisConfig.labels[index];\r\n  \r\n        if (IS_MOBILE && value !== 0) {\r\n          \/\/ \u30e2\u30d0\u30a4\u30eb\u6642\u306f0\u4ee5\u5916\u306e\u30e9\u30d9\u30eb\u309290\u5ea6\u56de\u8ee2\r\n          if (value === yAxisConfig.minValue) {\r\n            \/\/ \u30de\u30a4\u30ca\u30b9\u306e\u5024\u30e9\u30d9\u30eb\uff1a\u6700\u5927\u6841\u6570\u306e\u6570\u5b57\u304cx\u8ef8\u306e\u6a2a\u7dda\u306e\u4f4d\u7f6e\u306b\u6765\u308b\u3088\u3046\u306b\u8abf\u6574\r\n            \/\/ x\u8ef8\u306e\u6a2a\u7dda\u306e\u4f4d\u7f6e\u306f topMargin + graphHeight\r\n            \/\/ \u30e9\u30d9\u30eb\u304b\u3089\u6700\u5927\u6841\u6570\u306e\u6570\u5b57\uff08\u6700\u521d\u306e\u6570\u5b57\uff09\u306e\u4f4d\u7f6e\u3092\u8a08\u7b97\r\n            \/\/ \u30e9\u30d9\u30eb\u306f \"-100,000\" \u306e\u3088\u3046\u306a\u5f62\u5f0f\u3067\u3001\u6700\u5927\u6841\u6570\u306e\u6570\u5b57\u306f \"-\" \u306e\u6b21\u306e\u6587\u5b57\r\n            const firstDigitIndex = label.search(\/\\d\/); \/\/ \u6700\u521d\u306e\u6570\u5b57\u306e\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\r\n            const xAxisY = topMargin + graphHeight; \/\/ x\u8ef8\u306e\u6a2a\u7dda\u306e\u4f4d\u7f6e\r\n            \/\/ \u56de\u8ee2\u306e\u4e2d\u5fc3\u70b9\u3092\u6700\u5927\u6841\u6570\u306e\u6570\u5b57\u306e\u4f4d\u7f6e\u306b\u8a2d\u5b9a\r\n            \/\/ text-anchor=\"start\"\u306b\u3057\u3066\u3001\u6700\u5927\u6841\u6570\u306e\u6570\u5b57\u304c\u56de\u8ee2\u306e\u4e2d\u5fc3\u70b9\u306b\u6765\u308b\u3088\u3046\u306b\u3059\u308b\r\n            \/\/ \u30d5\u30a9\u30f3\u30c8\u30b5\u30a4\u30ba10px\u3001\u6587\u5b57\u9593\u9694\u3092\u8003\u616e\uff08\u7d046px\uff09\r\n            const rotationCenterX = leftMargin - 5;\r\n            const rotationCenterY = xAxisY;\r\n            \/\/ \u30c6\u30ad\u30b9\u30c8\u306e\u4f4d\u7f6e\u3092\u8abf\u6574\uff08\u6700\u5927\u6841\u6570\u306e\u6570\u5b57\u304c\u56de\u8ee2\u306e\u4e2d\u5fc3\u70b9\u306b\u6765\u308b\u3088\u3046\u306b\uff09\r\n            const textX = rotationCenterX - firstDigitIndex * 6; \/\/ \u5de6\u306b\u79fb\u52d5\r\n            svg += `<text x=\"${textX}\" y=\"${rotationCenterY}\" text-anchor=\"start\" font-size=\"10px\" fill=\"#000\" transform=\"rotate(-90 ${rotationCenterX} ${rotationCenterY})\">${label}<\/text>`;\r\n          } else {\r\n            \/\/ \u30d7\u30e9\u30b9\u306e\u5024\u30e9\u30d9\u30eb\uff1a\u901a\u5e38\u306e\u51e6\u7406\r\n            svg += `<text x=\"${leftMargin - 5}\" y=\"${y + 4}\" text-anchor=\"end\" font-size=\"10px\" fill=\"#000\" transform=\"rotate(-90 ${leftMargin - 5} ${y + 4})\">${label}<\/text>`;\r\n          }\r\n        } else {\r\n          \/\/ \u901a\u5e38\u6642\u307e\u305f\u306f0\u306e\u30e9\u30d9\u30eb\r\n          \/\/ \u30de\u30a4\u30ca\u30b9\u306e\u5024\u30e9\u30d9\u30eb\u306f\u4e0a\u306b\u79fb\u52d5\r\n          if (value === yAxisConfig.minValue) {\r\n            y = y - 5;\r\n          }\r\n          svg += `<text x=\"${leftMargin - 10}\" y=\"${y + 4}\" text-anchor=\"end\" font-size=\"10px\" fill=\"#000\">${label}<\/text>`;\r\n        }\r\n      });\r\n  \r\n      \/\/ x\u8ef8\u306e\u30e1\u30e2\u30ea\u30e9\u30d9\u30eb\uff08\u4e0b\u5074\uff09\r\n      \/\/ 0\u30f6\u6708\u304b\u3089maxMonths\u307e\u3067\u3001tickInterval\u3054\u3068\u306b\u30e9\u30d9\u30eb\u3092\u8868\u793a\r\n      \/\/ \u9593\u9694\u304c12\u306e\u500d\u6570\u306e\u5834\u5408\u306f\u5e74\u5358\u4f4d\u3067\u8868\u793a\r\n      const isYearTickInterval = tickInterval % 12 === 0 && tickInterval >= 12;\r\n      for (let month = 0; month <= maxMonths; month += tickInterval) {\r\n        const ratio = month \/ maxMonths;\r\n        const x = leftMargin + (ratio * graphWidth);\r\n        let label = '';\r\n        if (isYearTickInterval) {\r\n          const years = Math.floor(month \/ 12);\r\n          label = `${years}`;\r\n        } else {\r\n          label = `${month}`;\r\n        }\r\n        svg += `<text x=\"${x}\" y=\"${topMargin + graphHeight + 20}\" text-anchor=\"middle\" font-size=\"10px\" fill=\"#000\">${label}<\/text>`;\r\n      }\r\n  \r\n      \/\/ x\u8ef8\u306e\u30e9\u30d9\u30eb\uff08Month or Year\uff09\r\n      svg += `<text x=\"${leftMargin + graphWidth \/ 2}\" y=\"${topMargin + graphHeight + 40}\" text-anchor=\"middle\" font-size=\"10px\" fill=\"#000\">${xAxisLabelType}<\/text>`;\r\n  \r\n      \/\/ \u8a08\u7b97\u7d50\u679c\u3092\u3082\u3068\u306b\u3059\u3079\u3066\u306e\u6708\u306e\u7d2f\u7a4d\u5229\u76ca\u3092\u8a08\u7b97\u3057\u3066\u70b9\u3092\u914d\u7f6e\r\n      const pointSize = 4; \/\/ \u70b9\u306e\u30b5\u30a4\u30ba\uff08\u534a\u5f84\uff09\r\n      const pointColor = '#0073CD';\r\n  \r\n      \/\/ 0\u30f6\u6708\u76ee\u304b\u3089maxMonths\u307e\u3067\u3001\u3059\u3079\u3066\u306e\u6708\u306e\u7d2f\u7a4d\u5229\u76ca\u3092\u8a08\u7b97\u3057\u3066\u5ea7\u6a19\u3092\u53d6\u5f97\r\n      cumulativeProfit = -initialCost; \/\/ 0\u30f6\u6708\u76ee\u306e\u7d2f\u7a4d\u5229\u76ca\uff08\u521d\u671f\u6295\u8cc7\u984d\u306e\u30de\u30a4\u30ca\u30b9\u5024\uff09\r\n      const points = []; \/\/ \u70b9\u306e\u5ea7\u6a19\u3092\u4fdd\u5b58\u3059\u308b\u914d\u5217\r\n      for (let month = 0; month <= maxMonths; month++) {\r\n        if (month === 0) {\r\n          \/\/ 0\u30f6\u6708\u76ee\u306f\u521d\u671f\u6295\u8cc7\u984d\u306e\u30de\u30a4\u30ca\u30b9\u5024\r\n          cumulativeProfit = -initialCost;\r\n        } else {\r\n          \/\/ \u6708\u6b21\u5229\u76ca\u3092\u8a08\u7b97\r\n          let monthlyProfit = monthlySales - monthlyCost;\r\n          \/\/ \u30ed\u30fc\u30f3\u304c\u3042\u308b\u5834\u5408\u3001\u8fd4\u6e08\u671f\u9593\u4e2d\uff081\u30f6\u6708\u76ee\u304b\u3089repaymentPeriod\u30f6\u6708\u76ee\u307e\u3067\uff09\u306f\u30ed\u30fc\u30f3\u8fd4\u6e08\u984d\u3092\u5dee\u3057\u5f15\u304f\r\n          const isInRepaymentPeriod = useLoan && month >= 1 && month <= repaymentPeriod;\r\n          if (isInRepaymentPeriod) {\r\n            monthlyProfit -= monthlyLoanPayment;\r\n          }\r\n          \/\/ \u7d2f\u7a4d\u5229\u76ca\u3092\u66f4\u65b0\r\n          cumulativeProfit += monthlyProfit;\r\n        }\r\n        \/\/ \u70b9\u306e\u5ea7\u6a19\u3092\u8a08\u7b97\r\n        const x = leftMargin + (month \/ maxMonths) * graphWidth;\r\n        const ratio = (cumulativeProfit - yAxisConfig.minValue) \/ (yAxisConfig.maxValue - yAxisConfig.minValue);\r\n        const y = topMargin + graphHeight - (ratio * graphHeight);\r\n        \/\/ \u5ea7\u6a19\u3092\u914d\u5217\u306b\u4fdd\u5b58\r\n        points.push({ x, y });\r\n      }\r\n      \/\/ \u70b9\u3068\u70b9\u3092\u7dda\u3067\u7e4b\u3050\r\n      const linePoints = points.map(p => `${p.x},${p.y}`).join(' ');\r\n      svg += `<polyline points=\"${linePoints}\" fill=\"none\" stroke=\"${pointColor}\" stroke-width=\"2\"\/>`;\r\n      \/\/ \u5404\u70b9\u3092\u914d\u7f6e\uff08\u5c06\u6765\u7528\u306b\u4eca\u306f\u900f\u660e\u306b\uff09\r\n      points.forEach(point => {\r\n        svg += `<circle cx=\"${point.x}\" cy=\"${point.y}\" r=\"${pointSize}\" fill=\"${pointColor}\" style=\"opacity: 0;\"\/>`;\r\n      });\r\n  \r\n      \/\/ \u30b0\u30e9\u30d5\u306e\u4e0a\u90e8\u306b\u9577\u65b9\u5f62\u3092\u914d\u7f6e\uff08\u7dda\u3088\u308a\u4e0a\u306b\u914d\u7f6e\u3057\u3066\u7dda\u304c\u306f\u307f\u51fa\u305f\u90e8\u5206\u3092\u96a0\u3059\uff09\r\n      svg += `<rect x=\"${leftMargin - 1}\" y=\"-1\" width=\"${graphWidth + 1}\" height=\"${topMargin}\" fill=\"#fff\"\/>`;\r\n      svg += `\r\n        <\/svg>\r\n      `;\r\n      chartSection.innerHTML = svg;\r\n    };\r\n  \r\n    \/\/ \u3053\u3053\u307e\u3067\u30b0\u30e9\u30d5\u95a2\u9023\u306e\u51e6\u7406\r\n    \/\/ *****************************************\r\n    \/\/ *****************************************************\r\n    \/\/ ********************************************************************\r\n  \r\n  \r\n  \r\n  \r\n  \r\n    \/\/ ====================================================================================================================================\r\n    \/\/ \u30a4\u30d9\u30f3\u30c8\u30cf\u30f3\u30c9\u30e9\u30fc\r\n    \/\/ ====================================================================================================================================\r\n  \r\n    \/**\r\n     * \u753b\u9762\u8aad\u8fbc\u6642\r\n     *\/\r\n    (() => {\r\n      reflectCurrentCurrency();\r\n      calculateTotalInitialInvestment();\r\n      calculateTotalMonthlySalesPlan();\r\n      calculateTotalMaterialCost();\r\n      calculateTotalLaborCost();\r\n      calculateTotalMillingCost();\r\n      calculateMonthlyLoanPayment();\r\n      toggleLoanInputsDisabled();\r\n      showSummaryBeforeCalculate();\r\n    })();\r\n  \r\n    \/**\r\n     * \u901a\u8ca8\u9078\u629e\u6642\r\n     *\/\r\n    selectCurrency.addEventListener('change', (e) => {\r\n      reflectCurrentCurrency();\r\n    });\r\n  \r\n    \/**\r\n     * Input\u5165\u529b\u6642\r\n     *\/\r\n    allInputs.forEach(input => {\r\n      \/\/ \u30d5\u30a9\u30fc\u30ab\u30b9\u6642\uff1a\u30ab\u30f3\u30de\u3092\u524a\u9664\r\n      input.addEventListener('focus', (e) => {\r\n        const value = e.target.value;\r\n        e.target.value = removeCommas(value);\r\n      });\r\n  \r\n      \/\/ \u5165\u529b\u6642\uff1a\u30a8\u30e9\u30fc\u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u975e\u8868\u793a\u306b\u3059\u308b\r\n      input.addEventListener('input', (e) => {\r\n        const value = e.target.value;\r\n        const hasValue = value && value.trim() !== '';\r\n        if (hasValue) {\r\n          toggleErrorMessage(input, false);\r\n          \/\/ data-max\u3068data-min\u306e\u30a8\u30e9\u30fc\u30e1\u30c3\u30bb\u30fc\u30b8\u3082\u975e\u8868\u793a\u306b\u3059\u308b\r\n          toggleMaxMinErrorMessage(input, false);\r\n        }\r\n  \r\n        \/\/ \u5165\u529b\u30d5\u30a3\u30fc\u30eb\u30c9\u306e\u9023\u52d5\u51e6\u7406\r\n        \/\/ - input-zirconia-units \u3068 input-units-to-mill-zirconia \u3092\u9023\u52d5\r\n        if (input === inputZirconiaUnits && !isSyncingZirconia) {\r\n          isSyncingZirconia = true;\r\n          inputUnitsToMillZirconia.value = value;\r\n          isSyncingZirconia = false;\r\n        } else if (input === inputUnitsToMillZirconia && !isSyncingZirconia) {\r\n          isSyncingZirconia = true;\r\n          inputZirconiaUnits.value = value;\r\n          isSyncingZirconia = false;\r\n        }\r\n        \/\/ - input-glass-ceramics-units \u3068 input-units-to-mill-glass \u3092\u9023\u52d5\r\n        if (input === inputGlassCeramicsUnits && !isSyncingGlass) {\r\n          isSyncingGlass = true;\r\n          inputUnitsToMillGlass.value = value;\r\n          isSyncingGlass = false;\r\n        } else if (input === inputUnitsToMillGlass && !isSyncingGlass) {\r\n          isSyncingGlass = true;\r\n          inputGlassCeramicsUnits.value = value;\r\n          isSyncingGlass = false;\r\n        }\r\n        \/\/ - input-other-materials-units \u3068 input-units-to-mill-other-materials \u3092\u9023\u52d5\r\n        if (input === inputOtherMaterialsUnits && !isSyncingOtherMaterials) {\r\n          isSyncingOtherMaterials = true;\r\n          inputUnitsToMillOtherMaterials.value = value;\r\n          isSyncingOtherMaterials = false;\r\n        } else if (input === inputUnitsToMillOtherMaterials && !isSyncingOtherMaterials) {\r\n          isSyncingOtherMaterials = true;\r\n          inputOtherMaterialsUnits.value = value;\r\n          isSyncingOtherMaterials = false;\r\n        }\r\n  \r\n        \/\/ Sales Price\u30bb\u30c3\u30c8\u306e\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\uff08\u5165\u529b\u6642\uff09\r\n        if (input === inputZirconiaPrice || input === inputZirconiaUnits || input === inputGlassCeramicsPrice || input === inputGlassCeramicsUnits || input === inputOtherMaterialsPrice || input === inputOtherMaterialsUnits) {\r\n          validateSalesPriceSets();\r\n        }\r\n      });\r\n  \r\n      \/\/ \u30d5\u30a9\u30fc\u30ab\u30b9\u30a2\u30a6\u30c8\u6642\uff1a\u6570\u5024\u306e\u307f\u8a31\u53ef\u3001\u5168\u89d2\u3092\u534a\u89d2\u306b\u5909\u63db\u3001\u30ab\u30f3\u30de\u3092\u8ffd\u52a0\u3001\u518d\u8a08\u7b97\u3001\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\r\n      input.addEventListener('blur', (e) => {\r\n        const value = e.target.value;\r\n        const hasValue = value && value.trim() !== '';\r\n  \r\n        if (hasValue) {\r\n          \/\/ \u6570\u5024\u306e\u307f\u8a31\u53ef\u3001\u5168\u89d2\u3092\u534a\u89d2\u306b\u5909\u63db\r\n          const numericValue = extractNumbers(value);\r\n          e.target.value = numericValue;\r\n          \/\/ \u30ab\u30f3\u30de\u3092\u8ffd\u52a0\r\n          if (numericValue && numericValue.trim() !== '') {\r\n            e.target.value = addCommas(numericValue);\r\n          }\r\n        }\r\n  \r\n        \/\/ \u5165\u529b\u30d5\u30a3\u30fc\u30eb\u30c9\u306e\u9023\u52d5\u51e6\u7406\uff08blur\u6642\uff1a\u30ab\u30f3\u30de\u4ed8\u304d\u306e\u5024\u3092\u540c\u671f\uff09\r\n        \/\/ - input-zirconia-units \u3068 input-units-to-mill-zirconia \u3092\u9023\u52d5\r\n        if (input === inputZirconiaUnits && !isSyncingZirconia) {\r\n          isSyncingZirconia = true;\r\n          const finalValue = e.target.value;\r\n          if (finalValue && finalValue.trim() !== '') {\r\n            inputUnitsToMillZirconia.value = finalValue;\r\n          }\r\n          isSyncingZirconia = false;\r\n        } else if (input === inputUnitsToMillZirconia && !isSyncingZirconia) {\r\n          isSyncingZirconia = true;\r\n          const finalValue = e.target.value;\r\n          if (finalValue && finalValue.trim() !== '') {\r\n            inputZirconiaUnits.value = finalValue;\r\n          }\r\n          isSyncingZirconia = false;\r\n        }\r\n        \/\/ - input-glass-ceramics-units \u3068 input-units-to-mill-glass \u3092\u9023\u52d5\r\n        if (input === inputGlassCeramicsUnits && !isSyncingGlass) {\r\n          isSyncingGlass = true;\r\n          const finalValue = e.target.value;\r\n          if (finalValue && finalValue.trim() !== '') {\r\n            inputUnitsToMillGlass.value = finalValue;\r\n          }\r\n          isSyncingGlass = false;\r\n        } else if (input === inputUnitsToMillGlass && !isSyncingGlass) {\r\n          isSyncingGlass = true;\r\n          const finalValue = e.target.value;\r\n          if (finalValue && finalValue.trim() !== '') {\r\n            inputGlassCeramicsUnits.value = finalValue;\r\n          }\r\n          isSyncingGlass = false;\r\n        }\r\n        \/\/ - input-other-materials-units \u3068 input-units-to-mill-other-materials \u3092\u9023\u52d5\r\n        if (input === inputOtherMaterialsUnits && !isSyncingOtherMaterials) {\r\n          isSyncingOtherMaterials = true;\r\n          const finalValue = e.target.value;\r\n          if (finalValue && finalValue.trim() !== '') {\r\n            inputUnitsToMillOtherMaterials.value = finalValue;\r\n          }\r\n          isSyncingOtherMaterials = false;\r\n        } else if (input === inputUnitsToMillOtherMaterials && !isSyncingOtherMaterials) {\r\n          isSyncingOtherMaterials = true;\r\n          const finalValue = e.target.value;\r\n          if (finalValue && finalValue.trim() !== '') {\r\n            inputOtherMaterialsUnits.value = finalValue;\r\n          }\r\n          isSyncingOtherMaterials = false;\r\n        }\r\n  \r\n        \/\/ required\u5c5e\u6027\u304c\u3042\u308b\u5834\u5408\u306e\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\r\n        if (input.hasAttribute('required')) {\r\n          const finalValue = e.target.value;\r\n          const finalHasValue = finalValue && finalValue.trim() !== '';\r\n          const numericValue = finalHasValue ? Number(removeCommas(finalValue)) : 0;\r\n          const showError = !finalHasValue || numericValue === 0;\r\n          toggleErrorMessage(input, showError);\r\n        }\r\n  \r\n        \/\/ data-max\u3068data-min\u306e\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\r\n        if (input.hasAttribute('data-max') && input.hasAttribute('data-min')) {\r\n          const hasError = validateMaxMin(input);\r\n          toggleMaxMinErrorMessage(input, hasError);\r\n        }\r\n  \r\n        \/\/ Initial Investment Cost \u95a2\u9023\u306e\u5165\u529b\u30d5\u30a3\u30fc\u30eb\u30c9\u304c\u5909\u66f4\u3055\u308c\u305f\u3089\u518d\u8a08\u7b97\r\n        if (input === inputDwxPrice || input === inputOtherExpenses) {\r\n          calculateTotalInitialInvestment();\r\n        }\r\n  \r\n        \/\/ Monthly Sales Plan \u95a2\u9023\u306e\u5165\u529b\u30d5\u30a3\u30fc\u30eb\u30c9\u304c\u5909\u66f4\u3055\u308c\u305f\u3089\u518d\u8a08\u7b97\r\n        if (input === inputZirconiaPrice || input === inputZirconiaUnits || input === inputGlassCeramicsPrice || input === inputGlassCeramicsUnits || input === inputOtherMaterialsPrice || input === inputOtherMaterialsUnits) {\r\n          \/\/ Sales Price\u30bb\u30c3\u30c8\u306e\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\r\n          validateSalesPriceSets();\r\n          \/\/ \u521d\u56de\u5165\u529b\u30d5\u30e9\u30b0\u3092\u66f4\u65b0\uff08\u5024\u304c\u5165\u529b\u3055\u308c\u3066\u3044\u308b\u5834\u5408\u3001\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u5f8c\u306b\u66f4\u65b0\uff09\r\n          if (hasValue && isFirstSalesPriceInput) {\r\n            isFirstSalesPriceInput = false;\r\n          }\r\n          \/\/ \u8a08\u7b97\r\n          calculateTotalMonthlySalesPlan();\r\n        }\r\n  \r\n        \/\/ Total Material Cost \u95a2\u9023\u306e\u5165\u529b\u30d5\u30a3\u30fc\u30eb\u30c9\u304c\u5909\u66f4\u3055\u308c\u305f\u3089\u518d\u8a08\u7b97\r\n        if (input === inputMaterialCostZirconia || input === inputUnitsToMillZirconia || input === inputMaterialCostGlass || input === inputUnitsToMillGlass || input === inputMaterialCostOtherMaterials || input === inputUnitsToMillOtherMaterials) {\r\n          calculateTotalMaterialCost();\r\n        }\r\n  \r\n        \/\/ Total Labor Cost \u95a2\u9023\u306e\u5165\u529b\u30d5\u30a3\u30fc\u30eb\u30c9\u304c\u5909\u66f4\u3055\u308c\u305f\u3089\u518d\u8a08\u7b97\r\n        if (input === inputLaborCost || input === inputUnitsToMillZirconia || input === inputUnitsToMillGlass || input === inputUnitsToMillOtherMaterials) {\r\n          calculateTotalLaborCost();\r\n        }\r\n  \r\n        \/\/ Monthly Loan Payment \u95a2\u9023\u306e\u5165\u529b\u30d5\u30a3\u30fc\u30eb\u30c9\u304c\u5909\u66f4\u3055\u308c\u305f\u3089\u518d\u8a08\u7b97\r\n        if (input === inputDownPayment || input === inputAnnualInterestRate || input === inputRepaymentPeriod) {\r\n          calculateMonthlyLoanPayment();\r\n        }\r\n      });\r\n    });\r\n  \r\n    \/**\r\n     * Use Loan \u30c1\u30a7\u30c3\u30af\u30dc\u30c3\u30af\u30b9\u5909\u66f4\u6642\r\n     *\/\r\n    inputUseLoan.addEventListener('change', () => {\r\n      toggleLoanInputsDisabled();\r\n    });\r\n  \r\n    \/**\r\n     * \u8a08\u7b97\u30dc\u30bf\u30f3\u62bc\u4e0b\u6642\r\n     *\/\r\n    buttonCalculate.addEventListener('click', (e) => {\r\n      e.preventDefault();\r\n  \r\n      \/\/ \u3059\u3079\u3066\u306erequired\u5c5e\u6027\u304c\u3042\u308binput\u3092\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\r\n      let hasError = false;\r\n      allInputs.forEach(input => {\r\n        if (input.hasAttribute('required')) {\r\n          const value = input.value;\r\n          const hasValue = value && value.trim() !== '';\r\n          const numericValue = hasValue ? Number(removeCommas(value)) : 0;\r\n          const showError = !hasValue || numericValue === 0;\r\n          toggleErrorMessage(input, showError);\r\n          if (showError) {\r\n            hasError = true;\r\n          }\r\n        }\r\n      });\r\n  \r\n      \/\/ Sales Price\u30bb\u30c3\u30c8\u306e\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\uff08\u8a08\u7b97\u30dc\u30bf\u30f3\u62bc\u4e0b\u6642\u306f\u5e38\u306b\u30c1\u30a7\u30c3\u30af\uff09\r\n      isFirstSalesPriceInput = false; \/\/ \u8a08\u7b97\u30dc\u30bf\u30f3\u62bc\u4e0b\u6642\u306f\u521d\u56de\u30d5\u30e9\u30b0\u3092\u7121\u52b9\u5316\r\n      const salesPriceError = validateSalesPriceSets();\r\n      if (salesPriceError) {\r\n        hasError = true;\r\n      }\r\n  \r\n      \/\/ data-max\u3068data-min\u306e\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\r\n      allInputs.forEach(input => {\r\n        if (input.hasAttribute('data-max') && input.hasAttribute('data-min')) {\r\n          const maxMinError = validateMaxMin(input);\r\n          toggleMaxMinErrorMessage(input, maxMinError);\r\n          if (maxMinError) {\r\n            hasError = true;\r\n          }\r\n        }\r\n      });\r\n  \r\n      \/\/ \u30a8\u30e9\u30fc\u304c\u3042\u308b\u5834\u5408\u306f\u51e6\u7406\u3092\u4e2d\u65ad\u3057\u3001\u6700\u521d\u306e\u30a8\u30e9\u30fc\u30e1\u30c3\u30bb\u30fc\u30b8\u306b\u30b9\u30af\u30ed\u30fc\u30eb\r\n      if (hasError) {\r\n        \/\/ \u3059\u3079\u3066\u306e\u30a8\u30e9\u30fc\u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u53d6\u5f97\r\n        const errorMessages = document.querySelectorAll('.roi-error-message');\r\n        \/\/ \u6700\u521d\u306b\u8868\u793a\u3055\u308c\u3066\u3044\u308b\u30a8\u30e9\u30fc\u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u898b\u3064\u3051\u308b\r\n        for (const errorMsg of errorMessages) {\r\n          if (errorMsg.style.display === 'block') {\r\n            errorMsg.scrollIntoView({ behavior: 'smooth', block: 'center' });\r\n            break;\r\n          }\r\n        }\r\n        return;\r\n      }\r\n  \r\n      calculateSummary();\r\n      showSummaryAfterCalculate();\r\n      displayChart();\r\n  \r\n      \/\/ summaryWrapper\u306b\u30b9\u30af\u30ed\u30fc\u30eb\r\n      if (summaryWrapper) {\r\n        summaryWrapper.scrollIntoView({ behavior: 'smooth', block: 'start' });\r\n      }\r\n    });\r\n  \r\n    \/**\r\n     * RESET\u30dc\u30bf\u30f3\u62bc\u4e0b\u6642\r\n     *\/\r\n    buttonReset.addEventListener('click', () => {\r\n      \/\/ \u8a08\u7b97\u7d50\u679c\u3092\u30af\u30ea\u30a2\r\n      totalInitialInvestment.textContent = '0';\r\n      totalSales.textContent = '0';\r\n      totalMaterialCost.textContent = '0';\r\n      totalLaborCost.textContent = '0';\r\n      totalMillingCost.textContent = '0';\r\n      monthlyLoanPayment.textContent = '0';\r\n  \r\n      \/\/ Summary\u30bb\u30af\u30b7\u30e7\u30f3\u306e\u8a08\u7b97\u7d50\u679c\u3092\u30af\u30ea\u30a2\r\n      summaryInitialCost.textContent = '0';\r\n      summaryPaybackPeriod.textContent = '0.0';\r\n      summaryMonthlyProfitDuringRepayingLoan.textContent = '0';\r\n      summaryMonthlyProfitWithoutLoan.textContent = '0';\r\n      summaryMonthlyTotalSales.textContent = '0';\r\n      summaryMonthlyMillingCost.textContent = '0';\r\n      summaryMonthlyLoanPayment.textContent = '0';\r\n  \r\n      \/\/ \u30b0\u30e9\u30d5\u3092\u30af\u30ea\u30a2\r\n      if (chartSection) {\r\n        chartSection.innerHTML = '';\r\n      }\r\n  \r\n      \/\/ \u30a8\u30e9\u30fc\u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u975e\u8868\u793a\r\n      const errorMessages = document.querySelectorAll('.roi-error-message');\r\n      errorMessages.forEach(msg => {\r\n        msg.style.display = 'none';\r\n      });\r\n  \r\n      \/\/ \u5165\u529b\u6b04\u306e\u80cc\u666f\u8272\u3092\u30ea\u30bb\u30c3\u30c8\r\n      allInputs.forEach(input => {\r\n        input.style.background = '';\r\n      });\r\n  \r\n      \/\/ \u521d\u56de\u5165\u529b\u30d5\u30e9\u30b0\u3092\u30ea\u30bb\u30c3\u30c8\r\n      isFirstSalesPriceInput = true;\r\n  \r\n      \/\/ Summary\u8868\u793a\u3092\u521d\u671f\u72b6\u614b\u306b\u623b\u3059\r\n      showSummaryBeforeCalculate();\r\n  \r\n      \/\/ \u30d5\u30a9\u30fc\u30e0\u30ea\u30bb\u30c3\u30c8\u5f8c\u306b\u901a\u8ca8\u8868\u793a\u3092\u66f4\u65b0\uff08\u6b21\u306e\u30a4\u30d9\u30f3\u30c8\u30eb\u30fc\u30d7\u3067\u5b9f\u884c\uff09\r\n      setTimeout(() => {\r\n        reflectCurrentCurrency();\r\n      }, 0);\r\n    });\r\n  \r\n  });\r\n  <\/script>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-216ca72 e-flex e-con-boxed e-con e-parent\" data-id=\"216ca72\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-ea34d9f elementor-widget elementor-widget-html\" data-id=\"ea34d9f\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<script>\n    addEventListener('DOMContentLoaded', () => {\n\n  \/\/ 375px\u4ee5\u4e0b\u306e\u6642\u306f\u30d3\u30e5\u30fc\u30dd\u30fc\u30c8\u3092\u56fa\u5b9a\n  (()=>{\n    const _triggerWindowWidth = 375;\n    const elmMetaViewport = document.querySelector('meta[name=\"viewport\"]');\n    const updateViewport = () => {\n      const viewportValue =\n      window.outerWidth < _triggerWindowWidth\n        ? `width=${_triggerWindowWidth}, user-scalable=no, target-densitydpi=device-dpi`\n        : 'width=device-width, initial-scale=1';\n      elmMetaViewport.setAttribute('content', viewportValue);\n    };\n    \/\/ \u521d\u56de\u5b9f\u884c\n    updateViewport();\n    \/\/ \u30ea\u30b5\u30a4\u30ba\u6642\u306b\u3082\u5b9f\u884c\n    window.addEventListener('resize', updateViewport);\n  })();\n\n  (() => {\n    document.querySelectorAll('.roi-simulator-form-toggle').forEach(toggle => {\n      const button = toggle.querySelector('.roi-simulator-form-toggle__button');\n      const content = toggle.querySelector('.roi-simulator-form-toggle__content');\n      const inner = toggle.querySelector('.roi-simulator-form-toggle__content-inner');\n\n      \/\/ \u521d\u671f\u72b6\u614b\n      if (toggle.classList.contains('is-open')) {\n        content.style.height = inner.scrollHeight + 'px';\n        content.style.marginBottom = '10px';\n      } else {\n        content.style.height = '0';\n        content.style.marginBottom = '0';\n      }\n\n      button.addEventListener('click', () => {\n        const isOpen = toggle.classList.contains('is-open');\n\n        if (isOpen) {\n          \/\/ \u9589\u3058\u308b\n          content.style.height = inner.scrollHeight + 'px';\n          content.style.marginBottom = '10px';\n          requestAnimationFrame(() => {\n            content.style.height = '0';\n            content.style.marginBottom = '0';\n          });\n          toggle.classList.remove('is-open');\n        } else {\n          \/\/ \u958b\u304f\n          content.style.height = inner.scrollHeight + 'px';\n          content.style.marginBottom = '10px';\n          toggle.classList.add('is-open');\n        }\n      });\n    });\n  })();\n\n});\n<\/script>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-55d43c2 elementor-widget elementor-widget-html\" data-id=\"55d43c2\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<script>\n\/**\n * \u30b0\u30e9\u30d5\u306e\u4e0b\u9650\u306f\u5ea7\u6a19\u306e\u6700\u5c0f\u5024\u3001\u6700\u5927\u5024\u306f\u6700\u5c0f\u5024\u306e\u30d7\u30e9\u30b9\u5024\u306b\u3057\u305f\u30b7\u30df\u30e5\u30ec\u30fc\u30bf\u30fc\n *\/\n\naddEventListener('DOMContentLoaded', () => {\n\n  \/\/ \u753b\u9762\u5e45\u304c768\u672a\u6e80\u304b\u30c1\u30a7\u30c3\u30af\n  const IS_MOBILE = window.innerWidth < 768;\n\n  \/\/ \u5165\u529b\u6b04\u306e\u80cc\u666f\u8272\n  const INPUT_BACKGROUND_COLOR_NORMAL = '#F5F5F5';\n  const INPUT_BACKGROUND_COLOR_ERROR = '#FFEFEF';\n\n  \/\/ \u30c7\u30d5\u30a9\u30eb\u30c8\u306e\u8fd4\u6e08\u671f\u9593\uff08\u6708\uff09\n  const REPAYMENT_PERIOD_MONTH_DEFAULT = 36;\n\n  \/\/ Sales Price\u30d5\u30a3\u30fc\u30eb\u30c9\u306e\u521d\u56de\u5165\u529b\u30d5\u30e9\u30b0\uff08\u521d\u56de\u5165\u529b\u6642\u306e\u307f\u30c1\u30a7\u30c3\u30af\u3057\u306a\u3044\uff09\n  \/\/ \uff08\u3053\u306e\u5165\u529b\u6b04\u306f\u30bb\u30c3\u30c8\u3067\u5165\u529b\u3059\u308b\u5fc5\u8981\u304c\u3042\u308b\u305f\u3081\u3001\u6700\u521d\u306e1\u3064\u76ee\u3092\u5165\u529b\u3057\u305f\u3089\u5fc5\u305a\u30a8\u30e9\u30fc\u306b\u306a\u308b\u305f\u3081\uff09\n  let isFirstSalesPriceInput = true;\n\n  \/\/ Unit\u7cfb\u306e\u5165\u529b\u30d5\u30a3\u30fc\u30eb\u30c9\u306e\u9023\u52d5\u51e6\u7406\u4e2d\u30d5\u30e9\u30b0\uff08\u7121\u9650\u30eb\u30fc\u30d7\u9632\u6b62\uff09\n  let isSyncingZirconia = false;\n  let isSyncingGlass = false;\n  let isSyncingOtherMaterials = false;\n\n  \/\/ ====================================================================================================================================\n  \/\/ \u8981\u7d20\u306e\u53d6\u5f97\n  \/\/ ====================================================================================================================================\n\n  \/\/ \u30d5\u30a9\u30fc\u30e0\n  const roiSimulatorForm = document.getElementById('roi-simulator-form');\n  const allInputs = roiSimulatorForm.querySelectorAll('input[type=\"text\"]');\n\n  \/\/ \u901a\u8ca8\u9078\u629e\n  const selectCurrency = document.getElementById('select-currency'); \/\/ \u30bb\u30ec\u30af\u30c8\u30dc\u30c3\u30af\u30b9\n  const currencyLabels = document.querySelectorAll('[data-currency]'); \/\/ \u901a\u8ca8\u30e9\u30d9\u30eb\n\n  \/\/ \u5165\u529b\u7cfb\n  const inputDwxPrice = document.getElementById('input-dwx-price');\n  const inputOtherExpenses = document.getElementById('input-other-expenses');\n  const inputZirconiaPrice = document.getElementById('input-zirconia-price');\n  const inputZirconiaUnits = document.getElementById('input-zirconia-units');\n  const inputGlassCeramicsPrice = document.getElementById('input-glass-ceramics-price');\n  const inputGlassCeramicsUnits = document.getElementById('input-glass-ceramics-units');\n  const inputOtherMaterialsPrice = document.getElementById('input-other-materials-price');\n  const inputOtherMaterialsUnits = document.getElementById('input-other-materials-units');\n  const inputMaterialCostZirconia = document.getElementById('input-material-cost-zirconia');\n  const inputUnitsToMillZirconia = document.getElementById('input-units-to-mill-zirconia');\n  const inputMaterialCostGlass = document.getElementById('input-material-cost-glass');\n  const inputUnitsToMillGlass = document.getElementById('input-units-to-mill-glass');\n  const inputMaterialCostOtherMaterials = document.getElementById('input-material-cost-other-materials');\n  const inputUnitsToMillOtherMaterials = document.getElementById('input-units-to-mill-other-materials');\n  const inputLaborCost = document.getElementById('input-labor-cost');\n  const inputUseLoan = document.getElementById('input-use-loan');\n  const inputDownPayment = document.getElementById('input-down-payment');\n  const inputAnnualInterestRate = document.getElementById('input-annual-interest-rate');\n  const inputRepaymentPeriod = document.getElementById('input-repayment-period');\n\n  \/\/ \u30dc\u30bf\u30f3\u7cfb\n  const buttonCalculate = document.getElementById('button-calculate');\n  const buttonReset = document.getElementById('button-reset');\n\n  \/\/ \u7d50\u679c\u8868\u793a\u8981\u7d20\uff08\u30d5\u30a9\u30fc\u30e0\u5185\uff09\n  const totalInitialInvestment = document.getElementById('total-initial-investment');\n  const totalSales = document.getElementById('total-sales');\n  const totalMaterialCost = document.getElementById('total-material-cost');\n  const totalLaborCost = document.getElementById('total-labor-cost');\n  const totalMillingCost = document.getElementById('total-milling-cost');\n  const monthlyLoanPayment = document.getElementById('monthly-loan-payment');\n\n  \/\/ \u7d50\u679c\u8868\u793a\u8981\u7d20\uff08Summary\u30bb\u30af\u30b7\u30e7\u30f3\uff09\n  const summaryWrapper = document.getElementById('summary-wrapper');\n  const summaryBeforeCalculate = document.getElementById('summary-before-calculate');\n  const summaryAfterCalculate = document.getElementById('summary-after-calculate');\n  const summaryInitialCost = document.getElementById('summary-initial-cost');\n  const summaryPaybackPeriod = document.getElementById('summary-payback-period');\n  const summaryMonthlyProfitDuringRepayingLoan = document.getElementById('summary-monthly-profit-during-repaying-loan');\n  const summaryMonthlyProfitDuringRepayingLoanWrapper = document.getElementById('summary-monthly-profit-during-repaying-loan-wrapper');\n  const summaryMonthlyProfitWithoutLoan = document.getElementById('summary-monthly-profit-without-loan');\n  const summaryMonthlyTotalSales = document.getElementById('summary-monthly-total-sales');\n  const summaryMonthlyMillingCost = document.getElementById('summary-monthly-milling-cost');\n  const summaryMonthlyLoanPayment = document.getElementById('summary-monthly-loan-payment');\n  const summaryTitle = document.querySelector('.roi-simulator-summary-title');\n  const summaryMonthlyProfitTitle = document.getElementById('summary-monthly-profit-title');\n  const summaryMonthlyProfitTitleWithLoan = summaryMonthlyProfitTitle?.querySelector('[data-use-loan=\"true\"]');\n  const summaryMonthlyProfitTitleWithoutLoan = summaryMonthlyProfitTitle?.querySelector('[data-use-loan=\"false\"]');\n\n  \/\/ \u30b0\u30e9\u30d5\n  const chartSection = document.getElementById('chart-section');\n\n  \/\/ ====================================================================================================================================\n  \/\/ \u5404\u7a2e\u51e6\u7406\u306e\u5b9a\u7fa9\uff08\u95a2\u6570\u5b9a\u7fa9\uff09\n  \/\/ ====================================================================================================================================\n\n  \/**\n   * \u5168\u89d2\u6570\u5b57\u3092\u534a\u89d2\u306b\u5909\u63db\n   *\/\n  const convertFullWidthToHalfWidth = (str) => {\n    return str.replace(\/[\uff10-\uff19]\/g, (s) => {\n      return String.fromCharCode(s.charCodeAt(0) - 0xFEE0);\n    });\n  };\n\n  \/**\n   * \u6570\u5024\u306e\u307f\u3092\u62bd\u51fa\uff08\u5c0f\u6570\u70b9\u542b\u3080\uff09\n   *\/\n  const extractNumbers = (str) => {\n    \/\/ \u5168\u89d2\u3092\u534a\u89d2\u306b\u5909\u63db\n    const halfWidth = convertFullWidthToHalfWidth(str);\n    \/\/ \u6570\u5024\u3068\u5c0f\u6570\u70b9\u306e\u307f\u3092\u62bd\u51fa\n    let numeric = halfWidth.replace(\/[^\\d.]\/g, '');\n    \/\/ \u6700\u521d\u306e\u5c0f\u6570\u70b9\u306e\u307f\u3092\u6b8b\u3057\u3001\u305d\u308c\u4ee5\u964d\u306e\u5c0f\u6570\u70b9\u306f\u524a\u9664\n    const firstDotIndex = numeric.indexOf('.');\n    if (firstDotIndex !== -1) {\n      const beforeDot = numeric.substring(0, firstDotIndex + 1);\n      const afterDot = numeric.substring(firstDotIndex + 1).replace(\/\\.\/g, '');\n      numeric = beforeDot + afterDot;\n    }\n    \/\/ \u5148\u982d\u304c\u5c0f\u6570\u70b9\u3067\u59cb\u307e\u308b\u5834\u5408\u30010\u3092\u5148\u982d\u306b\u8ffd\u52a0\n    if (numeric.startsWith('.')) {\n      numeric = '0' + numeric;\n    }\n    \/\/ \u5148\u982d\u304c0\u3067\u59cb\u307e\u308a\u3001\u305d\u306e\u5f8c\u306b\u6570\u5b57\u304c\u7d9a\u304f\u5834\u5408\uff08\u4f8b: \"01\", \"02\"\uff09\u3001\u5165\u529b\u3092\u7121\u8996\u3057\u30660\u306e\u307e\u307e\u306b\u3059\u308b\n    \/\/ \u305f\u3060\u3057 \"0.\" \u3084 \"0\" \u5358\u4f53\u306f\u8a31\u53ef\n    if (numeric.length > 1 && numeric.startsWith('0') && numeric[1] !== '.') {\n      numeric = '0';\n    }\n    return numeric;\n  };\n\n  \/**\n   * \u30ab\u30f3\u30de\u3092\u524a\u9664\u3057\u3066\u6570\u5024\u6587\u5b57\u5217\u3092\u8fd4\u3059\n   *\/\n  const removeCommas = (str) => {\n    return str.replace(\/,\/g, '');\n  };\n\n  \/**\n   * \u6570\u5024\u6587\u5b57\u5217\u306b\u30ab\u30f3\u30de\u3092\u8ffd\u52a0\n   *\/\n  const addCommas = (str) => {\n    \/\/ \u30ab\u30f3\u30de\u3092\u524a\u9664\n    const withoutCommas = removeCommas(str);\n    \/\/ \u5c0f\u6570\u70b9\u3067\u5206\u5272\n    const parts = withoutCommas.split('.');\n    \/\/ \u6574\u6570\u90e8\u5206\u306b\u30ab\u30f3\u30de\u3092\u8ffd\u52a0\n    parts[0] = parts[0].replace(\/\\B(?=(\\d{3})+(?!\\d))\/g, ',');\n    \/\/ \u7d50\u5408\u3057\u3066\u8fd4\u3059\n    return parts.join('.');\n  };\n\n  \/**\n   * \u73fe\u5728\u306e\u901a\u8ca8\u3092\u53cd\u6620\n   *\/\n  const reflectCurrentCurrency = () => {\n    const selectedCurrency = selectCurrency.value;\n    currencyLabels.forEach(label => {\n      label.textContent = selectedCurrency;\n    });\n  };\n\n  \/**\n   * Initial Investment Cost \u306e\u8a08\u7b97\n   *\/\n  const calculateTotalInitialInvestment = () => {\n    \/\/ \u30a8\u30e9\u30fc\u30c1\u30a7\u30c3\u30af\uff1a\u95a2\u9023\u3059\u308b\u5165\u529b\u30d5\u30a3\u30fc\u30eb\u30c9\u306b\u30a8\u30e9\u30fc\u304c\u3042\u308b\u5834\u5408\u306f\u8a08\u7b97\u3092\u30b9\u30ad\u30c3\u30d7\n    if (hasErrorForInputs([inputDwxPrice, inputOtherExpenses])) {\n      return;\n    }\n    const dwxPrice = Number(removeCommas(inputDwxPrice.value)) || 0;\n    const otherExpenses = Number(removeCommas(inputOtherExpenses.value)) || 0;\n    const total = dwxPrice + otherExpenses;\n    totalInitialInvestment.textContent = total.toLocaleString();\n    \/\/ Monthly Loan Payment\u3082\u518d\u8a08\u7b97\n    calculateMonthlyLoanPayment();\n  };\n\n  \/**\n   * Monthly Sales Plan \u306e\u8a08\u7b97\n   *\/\n  const calculateTotalMonthlySalesPlan = () => {\n    \/\/ \u30a8\u30e9\u30fc\u30c1\u30a7\u30c3\u30af\uff1aSales Price\u30bb\u30c3\u30c8\u306e\u30a8\u30e9\u30fc\u30e1\u30c3\u30bb\u30fc\u30b8\u304c\u8868\u793a\u3055\u308c\u3066\u3044\u308b\u5834\u5408\u3001\u307e\u305f\u306f\u95a2\u9023\u3059\u308b\u5165\u529b\u30d5\u30a3\u30fc\u30eb\u30c9\u306b\u30a8\u30e9\u30fc\u304c\u3042\u308b\u5834\u5408\u306f\u8a08\u7b97\u3092\u30b9\u30ad\u30c3\u30d7\n    const salesPriceErrorMessage = document.getElementById('sales-price-error-message');\n    const hasSalesPriceError = salesPriceErrorMessage && salesPriceErrorMessage.style.display === 'block';\n    if (hasSalesPriceError || hasErrorForInputs([inputZirconiaPrice, inputZirconiaUnits, inputGlassCeramicsPrice, inputGlassCeramicsUnits, inputOtherMaterialsPrice, inputOtherMaterialsUnits])) {\n      return;\n    }\n    const zirconiaPrice = Number(removeCommas(inputZirconiaPrice.value)) || 0;\n    const zirconiaUnits = Number(removeCommas(inputZirconiaUnits.value)) || 0;\n    const glassCeramicsPrice = Number(removeCommas(inputGlassCeramicsPrice.value)) || 0;\n    const glassCeramicsUnits = Number(removeCommas(inputGlassCeramicsUnits.value)) || 0;\n    const otherMaterialsPrice = Number(removeCommas(inputOtherMaterialsPrice.value)) || 0;\n    const otherMaterialsUnits = Number(removeCommas(inputOtherMaterialsUnits.value)) || 0;\n    const total = (zirconiaPrice * zirconiaUnits) + (glassCeramicsPrice * glassCeramicsUnits) + (otherMaterialsPrice * otherMaterialsUnits);\n    totalSales.textContent = total.toLocaleString();\n  };\n\n  \/**\n   * Total Material Cost \u306e\u8a08\u7b97\n   *\/\n  const calculateTotalMaterialCost = () => {\n    \/\/ \u30a8\u30e9\u30fc\u30c1\u30a7\u30c3\u30af\uff1a\u95a2\u9023\u3059\u308b\u5165\u529b\u30d5\u30a3\u30fc\u30eb\u30c9\u306b\u30a8\u30e9\u30fc\u304c\u3042\u308b\u5834\u5408\u306f\u8a08\u7b97\u3092\u30b9\u30ad\u30c3\u30d7\n    if (hasErrorForInputs([inputMaterialCostZirconia, inputUnitsToMillZirconia, inputMaterialCostGlass, inputUnitsToMillGlass, inputMaterialCostOtherMaterials, inputUnitsToMillOtherMaterials])) {\n      return;\n    }\n    const materialCostZirconia = Number(removeCommas(inputMaterialCostZirconia.value)) || 0;\n    const unitsToMillZirconia = Number(removeCommas(inputUnitsToMillZirconia.value)) || 0;\n    const materialCostGlass = Number(removeCommas(inputMaterialCostGlass.value)) || 0;\n    const unitsToMillGlass = Number(removeCommas(inputUnitsToMillGlass.value)) || 0;\n    const materialCostOtherMaterials = Number(removeCommas(inputMaterialCostOtherMaterials.value)) || 0;\n    const unitsToMillOtherMaterials = Number(removeCommas(inputUnitsToMillOtherMaterials.value)) || 0;\n    const total = (materialCostZirconia * unitsToMillZirconia) + (materialCostGlass * unitsToMillGlass) + (materialCostOtherMaterials * unitsToMillOtherMaterials);\n    totalMaterialCost.textContent = total.toLocaleString();\n    \/\/ Total In-house Milling Cost\u3082\u518d\u8a08\u7b97\n    calculateTotalMillingCost();\n  };\n\n  \/**\n   * Total Labor Cost \u306e\u8a08\u7b97\n   *\/\n  const calculateTotalLaborCost = () => {\n    \/\/ \u30a8\u30e9\u30fc\u30c1\u30a7\u30c3\u30af\uff1a\u95a2\u9023\u3059\u308b\u5165\u529b\u30d5\u30a3\u30fc\u30eb\u30c9\u306b\u30a8\u30e9\u30fc\u304c\u3042\u308b\u5834\u5408\u306f\u8a08\u7b97\u3092\u30b9\u30ad\u30c3\u30d7\n    if (hasErrorForInputs([inputLaborCost, inputUnitsToMillZirconia, inputUnitsToMillGlass, inputUnitsToMillOtherMaterials])) {\n      return;\n    }\n    const laborCost = Number(removeCommas(inputLaborCost.value)) || 0;\n    const unitsToMillZirconia = Number(removeCommas(inputUnitsToMillZirconia.value)) || 0;\n    const unitsToMillGlass = Number(removeCommas(inputUnitsToMillGlass.value)) || 0;\n    const unitsToMillOtherMaterials = Number(removeCommas(inputUnitsToMillOtherMaterials.value)) || 0;\n    const total = laborCost * (unitsToMillZirconia + unitsToMillGlass + unitsToMillOtherMaterials) * 2;\n    totalLaborCost.textContent = total.toLocaleString();\n    \/\/ Total In-house Milling Cost\u3082\u518d\u8a08\u7b97\n    calculateTotalMillingCost();\n  };\n\n  \/**\n   * Total In-house Milling Cost \u306e\u8a08\u7b97\n   *\/\n  const calculateTotalMillingCost = () => {\n    \/\/ \u30a8\u30e9\u30fc\u30c1\u30a7\u30c3\u30af\uff1a\u95a2\u9023\u3059\u308b\u5165\u529b\u30d5\u30a3\u30fc\u30eb\u30c9\u306b\u30a8\u30e9\u30fc\u304c\u3042\u308b\u5834\u5408\u306f\u8a08\u7b97\u3092\u30b9\u30ad\u30c3\u30d7\n    if (hasErrorForInputs([inputMaterialCostZirconia, inputUnitsToMillZirconia, inputMaterialCostGlass, inputUnitsToMillGlass, inputMaterialCostOtherMaterials, inputUnitsToMillOtherMaterials, inputLaborCost])) {\n      return;\n    }\n    const materialCost = Number(removeCommas(totalMaterialCost.textContent)) || 0;\n    const laborCost = Number(removeCommas(totalLaborCost.textContent)) || 0;\n    const total = materialCost + laborCost;\n    totalMillingCost.textContent = total.toLocaleString();\n  };\n\n  \/**\n   * Monthly Loan Payment \u306e\u8a08\u7b97\n   *\/\n  const calculateMonthlyLoanPayment = () => {\n    \/\/ \u30ed\u30fc\u30f3\u3092\u4f7f\u7528\u3057\u306a\u3044\u5834\u5408\u306f0\u3092\u8fd4\u3059\n    if (!inputUseLoan.checked) {\n      monthlyLoanPayment.textContent = '0';\n      return;\n    }\n    \/\/ \u30a8\u30e9\u30fc\u30c1\u30a7\u30c3\u30af\uff1a\u95a2\u9023\u3059\u308b\u5165\u529b\u30d5\u30a3\u30fc\u30eb\u30c9\u306b\u30a8\u30e9\u30fc\u304c\u3042\u308b\u5834\u5408\u306f\u8a08\u7b97\u3092\u30b9\u30ad\u30c3\u30d7\n    if (hasErrorForInputs([inputDwxPrice, inputOtherExpenses, inputDownPayment, inputAnnualInterestRate, inputRepaymentPeriod])) {\n      return;\n    }\n    const initialInvestment = Number(removeCommas(totalInitialInvestment.textContent)) || 0;\n    const downPayment = Number(removeCommas(inputDownPayment.value)) || 0;\n    const loanAmount = initialInvestment - downPayment; \/\/ \u30ed\u30fc\u30f3\u91d1\u984d = \u521d\u671f\u6295\u8cc7\u984d - \u982d\u91d1\n    const annualInterestRate = Number(removeCommas(inputAnnualInterestRate.value)) || 0;\n    const repaymentPeriodMonthInputValue = Number(removeCommas(inputRepaymentPeriod.value)) || 0;\n    const repaymentPeriodMonth = repaymentPeriodMonthInputValue > 0 ? repaymentPeriodMonthInputValue : REPAYMENT_PERIOD_MONTH_DEFAULT;\n\n    if (loanAmount <= 0 || annualInterestRate <= 0 || repaymentPeriodMonth <= 0) {\n      monthlyLoanPayment.textContent = '0';\n      return;\n    }\n    \/\/ \u5e74\u5229\u3092\u6708\u5229\u306b\u5909\u63db\n    \/\/   Math.round(...) \u2192 \u5c0f\u6570\u70b9\u7b2c2\u4f4d\u307e\u3067\u56db\u6368\u4e94\u5165\n    \/\/   \/ 100 \/ 100 \u2192     \u6700\u521d\u306e\/100\u3067%\u306b\u5909\u63db\u3057\u3066\u3001\u6b21\u306e\/100\u3067\u8a08\u7b97\u7528\u306e\u6570\u5024\u306b\u5909\u63db\n    const monthlyInterestRate = Math.round(annualInterestRate \/ 12 * 100) \/ 100 \/ 100;\n    const getMonthlyLoanPaymentValue = () => {\n      const value1_1 = (initialInvestment - downPayment) * monthlyInterestRate;\n      const value1_2 = (1 + monthlyInterestRate) ** repaymentPeriodMonth;\n      const value1 = value1_1 * value1_2;\n      const value2 = ((1 + monthlyInterestRate) ** repaymentPeriodMonth) - 1;\n      return value1 \/ value2;\n    }\n    const monthlyLoanPaymentValue = getMonthlyLoanPaymentValue();\n    monthlyLoanPayment.textContent = Math.round(monthlyLoanPaymentValue).toLocaleString();\n  };\n\n  \/**\n   * Use Loan \u30c1\u30a7\u30c3\u30af\u30dc\u30c3\u30af\u30b9\u306b\u5fdc\u3058\u3066\u30ed\u30fc\u30f3\u95a2\u9023\u5165\u529b\u6b04\u306e\u6709\u52b9\/\u7121\u52b9\u3092\u5207\u308a\u66ff\u3048\n   *\/\n  const toggleLoanInputsDisabled = () => {\n    const isEnabled = inputUseLoan.checked;\n    inputDownPayment.disabled = !isEnabled;\n    inputAnnualInterestRate.disabled = !isEnabled;\n    inputRepaymentPeriod.disabled = !isEnabled;\n    \/\/ \u7121\u52b9\u5316\u3055\u308c\u305f\u5834\u5408\u306f\u8a08\u7b97\u3092\u5b9f\u884c\n    calculateMonthlyLoanPayment();\n  };\n\n  \/**\n   * Summary\u30bb\u30af\u30b7\u30e7\u30f3\u306e\u8a08\u7b97\n   *\/\n  const calculateSummary = () => {\n    \/\/ summary-monthly-total-sales = total-sales\n    const totalSalesValue = Number(removeCommas(totalSales.textContent)) || 0;\n    summaryMonthlyTotalSales.textContent = totalSalesValue.toLocaleString();\n\n    \/\/ summary-monthly-milling-cost = total-milling-cost\n    const totalMillingCostValue = Number(removeCommas(totalMillingCost.textContent)) || 0;\n    summaryMonthlyMillingCost.textContent = totalMillingCostValue.toLocaleString();\n\n    \/\/ summary-monthly-loan-payment = monthly-loan-payment\n    const monthlyLoanPaymentValue = Number(removeCommas(monthlyLoanPayment.textContent)) || 0;\n    summaryMonthlyLoanPayment.textContent = monthlyLoanPaymentValue.toLocaleString();\n\n    \/\/ summary-monthly-profit-during-repaying-loan = summary-monthly-total-sales - summary-monthly-loan-payment\n    const monthlyProfitWithLoan = (totalSalesValue - totalMillingCostValue) - monthlyLoanPaymentValue;\n    summaryMonthlyProfitDuringRepayingLoan.textContent = monthlyProfitWithLoan.toLocaleString();\n\n    \/\/ summary-monthly-profit-without-loan = summary-monthly-total-sales - summary-monthly-milling-cost\n    const monthlyProfitWithoutLoan = totalSalesValue - totalMillingCostValue;\n    summaryMonthlyProfitWithoutLoan.textContent = monthlyProfitWithoutLoan.toLocaleString();\n\n    \/\/ summary-monthly-profit-title\u306e\u8868\u793a\/\u975e\u8868\u793a\u3092\u5207\u308a\u66ff\u3048\n    if (summaryMonthlyProfitTitleWithLoan) {\n      summaryMonthlyProfitTitleWithLoan.style.display = inputUseLoan.checked ? 'inline' : 'none';\n    }\n    if (summaryMonthlyProfitTitleWithoutLoan) {\n      summaryMonthlyProfitTitleWithoutLoan.style.display = inputUseLoan.checked ? 'none' : 'inline';\n    }\n\n    \/\/ summary-monthly-profit-during-repaying-loan-wrapper\u306e\u8868\u793a\/\u975e\u8868\u793a\u3092\u5207\u308a\u66ff\u3048\n    if (summaryMonthlyProfitDuringRepayingLoanWrapper) {\n      summaryMonthlyProfitDuringRepayingLoanWrapper.style.display = inputUseLoan.checked ? 'flex' : 'none';\n    }\n\n    \/\/ summary-initial-cost\n    \/\/ \u30ed\u30fc\u30f3\u304cON\u306e\u3068\u304d\u306finput-down-payment\u3001OFF\u306e\u3068\u304d\u306ftotal-initial-investment\u3092\u8868\u793a\n    let summaryInitialCostValue = 0;\n    if (inputUseLoan.checked) {\n      \/\/ \u30ed\u30fc\u30f3\u304cON\u306e\u3068\u304d\u306f\u982d\u91d1\u3092\u8868\u793a\n      summaryInitialCostValue = Number(removeCommas(inputDownPayment.value)) || 0;\n    } else {\n      \/\/ \u30ed\u30fc\u30f3\u304cOFF\u306e\u3068\u304d\u306f\u521d\u671f\u6295\u8cc7\u984d\u3092\u8868\u793a\n      summaryInitialCostValue = Number(removeCommas(totalInitialInvestment.textContent)) || 0;\n    }\n    summaryInitialCost.textContent = summaryInitialCostValue.toLocaleString();\n\n    \/\/ summary-payback-period\u306e\u8a08\u7b97\u7528\u306b\u521d\u671f\u6295\u8cc7\u984d\u3092\u53d6\u5f97\n    const initialInvestmentValue = Number(removeCommas(totalInitialInvestment.textContent)) || 0;\n\n    \/\/ summary-payback-period\n    let paybackPeriod = 0;\n    if (inputUseLoan.checked) {\n      \/\/ \u30ed\u30fc\u30f3\u306b\u30c1\u30a7\u30c3\u30af\u304c\u5165\u3063\u3066\u308b\u306a\u3089: total-initial-investment \/ summary-monthly-profit-during-repaying-loan\n      if (monthlyProfitWithLoan > 0) {\n        paybackPeriod = initialInvestmentValue \/ monthlyProfitWithLoan;\n      }\n    } else {\n      \/\/ \u30ed\u30fc\u30f3\u306b\u30c1\u30a7\u30c3\u30af\u304c\u5165\u3063\u3066\u3044\u306a\u3044\u306a\u3089: total-initial-investment \/ summary-monthly-profit-without-loan\n      if (monthlyProfitWithoutLoan > 0) {\n        paybackPeriod = initialInvestmentValue \/ monthlyProfitWithoutLoan;\n      }\n    }\n    summaryPaybackPeriod.textContent = paybackPeriod.toFixed(1);\n  };\n\n  \/**\n   * Summary\u8868\u793a\u3092\u5207\u308a\u66ff\u3048\n   *\/\n  const showSummaryBeforeCalculate = () => {\n    summaryBeforeCalculate.style.display = 'block';\n    summaryAfterCalculate.style.display = 'none';\n    summaryTitle.classList.add('roi-simulator-summary-title-before');\n    summaryTitle.classList.remove('roi-simulator-summary-title-after');\n  };\n  const showSummaryAfterCalculate = () => {\n    summaryBeforeCalculate.style.display = 'none';\n    summaryAfterCalculate.style.display = 'block';\n    summaryTitle.classList.remove('roi-simulator-summary-title-before');\n    summaryTitle.classList.add('roi-simulator-summary-title-after');\n  };\n\n  \/**\n   * \u7279\u5b9a\u306e\u5165\u529b\u30d5\u30a3\u30fc\u30eb\u30c9\u306b\u95a2\u9023\u3059\u308b\u30a8\u30e9\u30fc\u304c\u3042\u308b\u304b\u3069\u3046\u304b\u3092\u30c1\u30a7\u30c3\u30af\n   * @param {Array<HTMLElement>} inputs - \u30c1\u30a7\u30c3\u30af\u3059\u308b\u5165\u529b\u30d5\u30a3\u30fc\u30eb\u30c9\u306e\u914d\u5217\n   * @returns {boolean} \u30a8\u30e9\u30fc\u304c\u3042\u308b\u5834\u5408true\n   *\/\n  const hasErrorForInputs = (inputs) => {\n    for (const input of inputs) {\n      \/\/ required\u5c5e\u6027\u306e\u30a8\u30e9\u30fc\u30c1\u30a7\u30c3\u30af\n      if (input.hasAttribute('required')) {\n        const inputId = input.id;\n        const errorMessage = document.querySelector(`[data-required=\"${inputId}\"]`);\n        if (errorMessage && errorMessage.style.display === 'block') {\n          return true;\n        }\n      }\n      \/\/ data-max\u3068data-min\u306e\u30a8\u30e9\u30fc\u30c1\u30a7\u30c3\u30af\n      if (input.hasAttribute('data-max') && input.hasAttribute('data-min')) {\n        const inputId = input.id;\n        const errorMessage = document.querySelector(`[data-max-min=\"${inputId}\"]`);\n        if (errorMessage && errorMessage.style.display === 'block') {\n          return true;\n        }\n      }\n    }\n    return false;\n  };\n\n  \/**\n   * \u30a8\u30e9\u30fc\u6570\u3092\u30ab\u30a6\u30f3\u30c8\u3057\u3001\u8a08\u7b97\u30dc\u30bf\u30f3\u306b\u30af\u30e9\u30b9\u3092\u4ed8\u4e0e\/\u524a\u9664\n   *\/\n  const toggleButtonCalculateClass = () => {\n    let errorCount = 0;\n\n    \/\/ .roi-error-message\u8981\u7d20\u3092\u53d6\u5f97\u3057\u3066\u3001\u8868\u793a\u3055\u308c\u3066\u3044\u308b\u30a8\u30e9\u30fc\u3092\u30ab\u30a6\u30f3\u30c8\n    const errorMessages = document.querySelectorAll('.roi-error-message');\n    errorMessages.forEach(msg => {\n      if (msg.style.display === 'block') {\n        errorCount++;\n      }\n    });\n\n    \/\/ \u30dc\u30bf\u30f3\u306b\u30af\u30e9\u30b9\u3092\u4ed8\u4e0e\/\u524a\u9664\n    if (errorCount > 0) {\n      buttonCalculate.classList.add('roi-error');\n    } else {\n      buttonCalculate.classList.remove('roi-error');\n    }\n  };\n\n  \/**\n   * \u30a8\u30e9\u30fc\u30e1\u30c3\u30bb\u30fc\u30b8\u306e\u8868\u793a\/\u975e\u8868\u793a\u3092\u5236\u5fa1\uff08\u5229\u7528\u7b87\u6240\u4f8b\uff1a#input-dwx-price\uff09\n   * @param {HTMLElement} input - \u5165\u529b\u8981\u7d20\n   * @param {boolean} showError - \u30a8\u30e9\u30fc\u3092\u8868\u793a\u3059\u308b\u304b\u3069\u3046\u304b\n   *\/\n  const toggleErrorMessage = (input, showError) => {\n    if (input.hasAttribute('required')) {\n      const inputId = input.id;\n      const errorMessage = document.querySelector(`[data-required=\"${inputId}\"]`);\n      if (errorMessage) {\n        errorMessage.style.display = showError ? 'block' : 'none';\n        input.style.background = showError ? INPUT_BACKGROUND_COLOR_ERROR : INPUT_BACKGROUND_COLOR_NORMAL;\n        toggleButtonCalculateClass();\n      }\n    }\n  };\n\n  \/**\n   * data-max\u3068data-min\u306e\u7bc4\u56f2\u30c1\u30a7\u30c3\u30af\n   * @param {HTMLElement} input - \u5165\u529b\u8981\u7d20\n   * @returns {boolean} \u30a8\u30e9\u30fc\u304c\u3042\u308b\u5834\u5408true\n   *\/\n  const validateMaxMin = (input) => {\n    if (!input.hasAttribute('data-max') || !input.hasAttribute('data-min')) {\n      return false;\n    }\n    const value = input.value;\n    const hasValue = value && value.trim() !== '';\n    \/\/ \u5024\u304c\u7a7a\u306e\u5834\u5408\u306f\u30a8\u30e9\u30fc\u306a\u3057\uff08required\u5c5e\u6027\u3067\u30c1\u30a7\u30c3\u30af\u3059\u308b\u305f\u3081\uff09\n    if (!hasValue) {\n      return false;\n    }\n    const numericValue = Number(removeCommas(value));\n    const maxValue = Number(input.getAttribute('data-max'));\n    const minValue = Number(input.getAttribute('data-min'));\n    \/\/ \u7bc4\u56f2\u5916\u306e\u5834\u5408\u30a8\u30e9\u30fc\n    return numericValue < minValue || numericValue > maxValue;\n  };\n\n  \/**\n   * data-max\u3068data-min\u306e\u30a8\u30e9\u30fc\u30e1\u30c3\u30bb\u30fc\u30b8\u306e\u8868\u793a\/\u975e\u8868\u793a\u3092\u5236\u5fa1\n   * @param {HTMLElement} input - \u5165\u529b\u8981\u7d20\n   * @param {boolean} showError - \u30a8\u30e9\u30fc\u3092\u8868\u793a\u3059\u308b\u304b\u3069\u3046\u304b\n   *\/\n  const toggleMaxMinErrorMessage = (input, showError) => {\n    if (input.hasAttribute('data-max') && input.hasAttribute('data-min')) {\n      const inputId = input.id;\n      const errorMessage = document.querySelector(`[data-max-min=\"${inputId}\"]`);\n      if (errorMessage) {\n        errorMessage.style.display = showError ? 'block' : 'none';\n        input.style.background = showError ? INPUT_BACKGROUND_COLOR_ERROR : INPUT_BACKGROUND_COLOR_NORMAL;\n        toggleButtonCalculateClass();\n      }\n    }\n  };\n\n  \/**\n   * Sales Price\u30bb\u30c3\u30c8\u306e\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\n   * Zirconia\u3068Glass Ceramics\u306e\u30bb\u30c3\u30c8\u3067\u3001price\u3068units\u306f\u4e21\u65b9\u5165\u529b\u3059\u308b\u5fc5\u8981\u304c\u3042\u308b\n   * \u3069\u3061\u3089\u304b\u306e\u30bb\u30c3\u30c8\u304c\u5b8c\u5168\u306b\u5165\u529b\u3055\u308c\u3066\u3044\u308c\u3070OK\n   * @returns {boolean} \u30a8\u30e9\u30fc\u304c\u3042\u308b\u5834\u5408true\n   *\/\n  const validateSalesPriceSets = () => {\n    \/\/ \u521d\u56de\u5165\u529b\u6642\u306e\u307f\u30c1\u30a7\u30c3\u30af\u3057\u306a\u3044\n    if (isFirstSalesPriceInput) {\n      return false;\n    }\n\n    \/\/ Zirconia\u30bb\u30c3\u30c8\u306e\u30c1\u30a7\u30c3\u30af\uff1a\u4e21\u65b9\u5165\u529b\u3055\u308c\u3066\u3044\u308b\u3001\u307e\u305f\u306f\u4e21\u65b9\u3068\u3082\u7a7a\n    const zirconiaPriceHasValue = inputZirconiaPrice.value && inputZirconiaPrice.value.trim() !== '';\n    const zirconiaUnitsHasValue = inputZirconiaUnits.value && inputZirconiaUnits.value.trim() !== '';\n    const zirconiaSetValid = (zirconiaPriceHasValue && zirconiaUnitsHasValue) || (!zirconiaPriceHasValue && !zirconiaUnitsHasValue);\n\n    \/\/ Glass Ceramics\u30bb\u30c3\u30c8\u306e\u30c1\u30a7\u30c3\u30af\uff1a\u4e21\u65b9\u5165\u529b\u3055\u308c\u3066\u3044\u308b\u3001\u307e\u305f\u306f\u4e21\u65b9\u3068\u3082\u7a7a\n    const glassPriceHasValue = inputGlassCeramicsPrice.value && inputGlassCeramicsPrice.value.trim() !== '';\n    const glassUnitsHasValue = inputGlassCeramicsUnits.value && inputGlassCeramicsUnits.value.trim() !== '';\n    const glassSetValid = (glassPriceHasValue && glassUnitsHasValue) || (!glassPriceHasValue && !glassUnitsHasValue);\n\n    \/\/ Other Materials\u30bb\u30c3\u30c8\u306e\u30c1\u30a7\u30c3\u30af\uff1a\u4e21\u65b9\u5165\u529b\u3055\u308c\u3066\u3044\u308b\u3001\u307e\u305f\u306f\u4e21\u65b9\u3068\u3082\u7a7a\n    const otherMaterialsPriceHasValue = inputOtherMaterialsPrice.value && inputOtherMaterialsPrice.value.trim() !== '';\n    const otherMaterialsUnitsHasValue = inputOtherMaterialsUnits.value && inputOtherMaterialsUnits.value.trim() !== '';\n    const otherMaterialsSetValid = (otherMaterialsPriceHasValue && otherMaterialsUnitsHasValue) || (!otherMaterialsPriceHasValue && !otherMaterialsUnitsHasValue);\n\n    \/\/ \u3069\u3061\u3089\u304b\u306e\u30bb\u30c3\u30c8\u304c\u5b8c\u5168\u306b\u5165\u529b\u3055\u308c\u3066\u3044\u308b\u5fc5\u8981\u304c\u3042\u308b\n    const hasValidSet = (zirconiaPriceHasValue && zirconiaUnitsHasValue) || (glassPriceHasValue && glassUnitsHasValue) || (otherMaterialsPriceHasValue && otherMaterialsUnitsHasValue);\n\n    \/\/ \u30a8\u30e9\u30fc\u304c\u3042\u308b\u5834\u5408\uff1a\u30bb\u30c3\u30c8\u304c\u7121\u52b9\u3001\u307e\u305f\u306f\u6709\u52b9\u306a\u30bb\u30c3\u30c8\u304c\u306a\u3044\n    const hasError = !zirconiaSetValid || !glassSetValid || !otherMaterialsSetValid || !hasValidSet;\n\n    const errorMessage = document.getElementById('sales-price-error-message');\n    if (errorMessage) {\n      errorMessage.style.display = hasError ? 'block' : 'none';\n      toggleButtonCalculateClass();\n\n      \/\/ \u30a8\u30e9\u30fc\u304c\u3042\u308b\u5834\u5408\u3001\u8a72\u5f53\u3059\u308binput\u306e\u80cc\u666f\u8272\u3092\u5909\u66f4\n      if (hasError) {\n        if (!zirconiaSetValid) {\n          inputZirconiaPrice.style.background = INPUT_BACKGROUND_COLOR_ERROR;\n          inputZirconiaUnits.style.background = INPUT_BACKGROUND_COLOR_ERROR;\n        }\n        if (!glassSetValid) {\n          inputGlassCeramicsPrice.style.background = INPUT_BACKGROUND_COLOR_ERROR;\n          inputGlassCeramicsUnits.style.background = INPUT_BACKGROUND_COLOR_ERROR;\n        }\n        if (!otherMaterialsSetValid) {\n          inputOtherMaterialsPrice.style.background = INPUT_BACKGROUND_COLOR_ERROR;\n          inputOtherMaterialsUnits.style.background = INPUT_BACKGROUND_COLOR_ERROR;\n        }\n      } else {\n        \/\/ \u30a8\u30e9\u30fc\u304c\u306a\u3044\u5834\u5408\u3001\u80cc\u666f\u8272\u3092\u30ea\u30bb\u30c3\u30c8\n        inputZirconiaPrice.style.background = '';\n        inputZirconiaUnits.style.background = '';\n        inputGlassCeramicsPrice.style.background = '';\n        inputGlassCeramicsUnits.style.background = '';\n        inputOtherMaterialsPrice.style.background = '';\n        inputOtherMaterialsUnits.style.background = '';\n      }\n    }\n\n    return hasError;\n  };\n\n\n\n\n\n  \/\/ ********************************************************************\n  \/\/ *****************************************************\n  \/\/ *****************************************\n  \/\/ \u3053\u3053\u304b\u3089\u30b0\u30e9\u30d5\u95a2\u9023\u306e\u51e6\u7406\n\n  \/**\n   * x\u8ef8\u306e\u30e1\u30e2\u30ea\u9593\u9694\u3092\u53d6\u5f97\uff08\u8868\u793a\u3059\u308b\u6700\u5927\u6708\u6570\u306b\u5fdc\u3058\u3066\u5909\u52d5\uff09\n   * @param {number} maxMonths - \u8868\u793a\u3059\u308b\u6700\u5927\u6708\u6570\n   * @returns {number} \u30e1\u30e2\u30ea\u9593\u9694\uff08\u6708\u5358\u4f4d\uff09\n   *\/\n  const getXAxisTickInterval = (maxMonths) => {\n    const maxTicks = 10; \/\/ \u30e1\u30e2\u30ea\u6570\u306e\u4e0a\u9650\n    \/\/ \u30e1\u30e2\u30ea\u6570 = Math.floor(maxMonths \/ interval) + 1 <= maxTicks\n    \/\/ Math.floor(maxMonths \/ interval) <= maxTicks - 1\n    \/\/ maxMonths \/ interval <= maxTicks - 1\n    \/\/ interval >= maxMonths \/ (maxTicks - 1)\n    const minInterval = maxMonths \/ (maxTicks - 1);\n\n    if (maxMonths <= 12) {\n      \/\/ 12\u30f6\u6708\u4ee5\u4e0b\u306e\u5834\u5408\u30011\u30f6\u6708\u3054\u3068\u3092\u512a\u5148\uff08\u305f\u3060\u3057\u4e0a\u9650\u3092\u8d85\u3048\u306a\u3044\u3088\u3046\u306b\uff09\n      const interval = Math.ceil(minInterval);\n      return Math.max(1, interval);\n    } else if (maxMonths <= 59) {\n      \/\/ 59\u30f6\u6708\u4ee5\u4e0b\u306e\u5834\u5408\u30013\u306e\u500d\u6570\u3067\u5207\u308a\u4e0a\u3052\n      return Math.ceil(minInterval \/ 3) * 3;\n    } else if (maxMonths <= 119) {\n      \/\/ 119\u30f6\u6708\u4ee5\u4e0b\u306e\u5834\u5408\u30016\u306e\u500d\u6570\u3067\u5207\u308a\u4e0a\u3052\n      return Math.ceil(minInterval \/ 6) * 6;\n    } else {\n      \/\/ 120\u30f6\u6708\u4ee5\u4e0a\u306e\u5834\u5408\u300112\u306e\u500d\u6570\u3067\u5207\u308a\u4e0a\u3052\uff08\u5e74\u5358\u4f4d\uff09\n      return Math.ceil(minInterval \/ 12) * 12;\n    }\n  };\n\n  \/**\n   * x\u8ef8\u306e\u30e9\u30d9\u30eb\u3092\u751f\u6210\n   * @param {number} maxMonths - \u8868\u793a\u3059\u308b\u6700\u5927\u6708\u6570\n   * @returns {Array<string>} x\u8ef8\u306e\u30e9\u30d9\u30eb\u914d\u5217\n   *\/\n  const generateXAxisLabels = (maxMonths) => {\n    const interval = getXAxisTickInterval(maxMonths);\n    const labels = [];\n    const tickValues = [];\n    \/\/ 0\u30f6\u6708\u304b\u3089\u958b\u59cb\u3057\u3066\u3001\u9593\u9694\u3054\u3068\u306b\u30e9\u30d9\u30eb\u3092\u751f\u6210\n    \/\/ \u9593\u9694\u304c12\u306e\u500d\u6570\u306e\u5834\u5408\u306f\u5e74\u5358\u4f4d\u3067\u8868\u793a\n    const isYearInterval = interval % 12 === 0 && interval >= 12;\n    for (let month = 0; month <= maxMonths; month += interval) {\n      tickValues.push(month);\n      if (isYearInterval) {\n        \/\/ \u5e74\u5358\u4f4d\u306e\u5834\u5408\n        const years = Math.floor(month \/ 12);\n        labels.push(`${years}\u5e74`);\n      } else {\n        \/\/ \u6708\u5358\u4f4d\u306e\u5834\u5408\n        labels.push(`${month}\u30f6\u6708`);\n      }\n    }\n    return labels;\n  };\n\n  \/**\n   * x\u8ef8\u306e\u8a2d\u5b9a\u3092\u8a08\u7b97\n   * @returns {Object} x\u8ef8\u306e\u8a2d\u5b9a\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\n   *\/\n  const calculateXAxisConfig = () => {\n    \/\/ \u5229\u76ca\u306e\u7d2f\u7a4d\u304c0\u306b\u306a\u308b\u6708\uff08Payback Period\uff09\u3092\u53d6\u5f97\n    const paybackPeriod = parseFloat(summaryPaybackPeriod.textContent) || 0;\n\n    \/\/ \u7d2f\u7a4d\u5229\u76ca\u304c\u521d\u671f\u6295\u8cc7\u984d\u3092\u4e0a\u56de\u308b\u6708\u3092\u8a08\u7b97\n    const initialCost = Number(removeCommas(totalInitialInvestment.textContent)) || 0;\n    const monthlySales = Number(removeCommas(summaryMonthlyTotalSales.textContent)) || 0;\n    const monthlyCost = Number(removeCommas(summaryMonthlyMillingCost.textContent)) || 0;\n    const monthlyLoanPayment = Number(removeCommas(summaryMonthlyLoanPayment.textContent)) || 0;\n    const repaymentPeriodInput = Number(removeCommas(inputRepaymentPeriod.value)) || 0;\n    const repaymentPeriod = repaymentPeriodInput > 0 ? repaymentPeriodInput : REPAYMENT_PERIOD_MONTH_DEFAULT;\n    const useLoan = inputUseLoan.checked;\n\n    let cumulativeProfit = -initialCost;\n    let monthWhenExceedsInitialCost = null;\n\n    \/\/ \u7d2f\u7a4d\u5229\u76ca\u304c\u521d\u671f\u6295\u8cc7\u984d\u3092\u4e0a\u56de\u308b\u6708\u3092\u898b\u3064\u3051\u308b\uff08\u6700\u59271000\u30f6\u6708\u307e\u3067\u691c\u7d22\uff09\n    for (let month = 0; month <= 1000; month++) {\n      if (month === 0) {\n        cumulativeProfit = -initialCost;\n      } else {\n        let monthlyProfit = monthlySales - monthlyCost;\n        if (useLoan && month >= 1 && month <= repaymentPeriod) {\n          monthlyProfit -= monthlyLoanPayment;\n        }\n        cumulativeProfit += monthlyProfit;\n      }\n\n      \/\/ \u7d2f\u7a4d\u5229\u76ca\u304c\u521d\u671f\u6295\u8cc7\u984d\u3092\u4e0a\u56de\u3063\u305f\u5834\u5408\n      if (cumulativeProfit > initialCost) {\n        monthWhenExceedsInitialCost = month;\n        break;\n      }\n    }\n\n    \/\/ x\u8ef8\u306e\u6700\u5927\u5024\uff1a\u7d2f\u7a4d\u5229\u76ca\u304c\u521d\u671f\u6295\u8cc7\u984d\u3092\u4e0a\u56de\u308b\u6708\u304c\u3042\u308b\u5834\u5408\u306f\u305d\u306e\u6708\u3001\u306a\u3044\u5834\u5408\u306fPayback Period + 12\u30f6\u6708\n    let maxMonths;\n    if (monthWhenExceedsInitialCost !== null) {\n      maxMonths = monthWhenExceedsInitialCost;\n    } else {\n      maxMonths = Math.ceil(paybackPeriod) + 12;\n    }\n\n    \/\/ \u30e1\u30e2\u30ea\u9593\u9694\u3092\u53d6\u5f97\n    const tickInterval = getXAxisTickInterval(maxMonths);\n    \/\/ x\u8ef8\u306e\u30e9\u30d9\u30eb\u3092\u751f\u6210\n    const labels = generateXAxisLabels(maxMonths);\n    return {\n      maxMonths: maxMonths,\n      tickInterval: tickInterval,\n      labels: labels,\n      paybackPeriod: paybackPeriod\n    };\n  };\n\n  \/**\n   * y\u8ef8\u306e\u30e9\u30d9\u30eb\u3092\u751f\u6210\uff08\u6700\u5c0f\u5024\u30010\u3001\u6700\u5927\u5024\u306e3\u3064\u306e\u307f\uff09\n   * @param {number} minValue - y\u8ef8\u306e\u6700\u5c0f\u5024\uff08\u30de\u30a4\u30ca\u30b9\u5024\uff09\n   * @param {number} maxValue - y\u8ef8\u306e\u6700\u5927\u5024\uff08\u30d7\u30e9\u30b9\u5024\uff09\n   * @returns {Array<string>} y\u8ef8\u306e\u30e9\u30d9\u30eb\u914d\u5217\n   *\/\n  const generateYAxisLabels = (minValue, maxValue) => {\n    const labels = [];\n    \/\/ \u6700\u5c0f\u5024\u30010\u3001\u6700\u5927\u5024\u306e3\u3064\u306e\u307f\n    labels.push(minValue.toLocaleString());\n    labels.push(0);\n    labels.push(maxValue.toLocaleString());\n    return labels;\n  };\n\n  \/**\n   * \u30b0\u30e9\u30d5\u3092\u8868\u793a\n   *\/\n  const displayChart = () => {\n    const xAxisConfig = calculateXAxisConfig();\n\n    \/\/ \u307e\u305a\u7d2f\u7a4d\u5229\u76ca\u306e\u6700\u5c0f\u5024\u3092\u8a08\u7b97\u3059\u308b\u305f\u3081\u306b\u3001\u3059\u3079\u3066\u306e\u6708\u306e\u7d2f\u7a4d\u5229\u76ca\u3092\u8a08\u7b97\n    const initialCost = Number(removeCommas(totalInitialInvestment.textContent)) || 0;\n    const monthlySales = Number(removeCommas(summaryMonthlyTotalSales.textContent)) || 0;\n    const monthlyCost = Number(removeCommas(summaryMonthlyMillingCost.textContent)) || 0;\n    const monthlyLoanPayment = Number(removeCommas(summaryMonthlyLoanPayment.textContent)) || 0;\n    const repaymentPeriodInput = Number(removeCommas(inputRepaymentPeriod.value)) || 0;\n    const repaymentPeriod = repaymentPeriodInput > 0 ? repaymentPeriodInput : REPAYMENT_PERIOD_MONTH_DEFAULT;\n    const useLoan = inputUseLoan.checked;\n    const maxMonths = xAxisConfig.maxMonths;\n\n    \/\/ \u7d2f\u7a4d\u5229\u76ca\u306e\u6700\u5c0f\u5024\u3092\u8a08\u7b97\n    let cumulativeProfit = -initialCost;\n    let minCumulativeProfit = cumulativeProfit;\n    for (let month = 0; month <= maxMonths; month++) {\n      if (month === 0) {\n        cumulativeProfit = -initialCost;\n      } else {\n        let monthlyProfit = monthlySales - monthlyCost;\n        if (useLoan && month >= 1 && month <= repaymentPeriod) {\n          monthlyProfit -= monthlyLoanPayment;\n        }\n        cumulativeProfit += monthlyProfit;\n      }\n      if (cumulativeProfit < minCumulativeProfit) {\n        minCumulativeProfit = cumulativeProfit;\n      }\n    }\n\n    \/\/ y\u8ef8\u306e\u8a2d\u5b9a\uff1a\u6700\u5c0f\u5024\u306f\u7d2f\u7a4d\u5229\u76ca\u306e\u6700\u5c0f\u5024\u3001\u6700\u5927\u5024\u306f\u6700\u5c0f\u5024\u306e\u7d76\u5bfe\u5024\uff08\u5bfe\u79f0\uff09\n    const yAxisMinValue = minCumulativeProfit;\n    const yAxisMaxValue = Math.abs(minCumulativeProfit);\n    const yAxisLabels = generateYAxisLabels(yAxisMinValue, yAxisMaxValue);\n    const yAxisConfig = {\n      minValue: yAxisMinValue,\n      maxValue: yAxisMaxValue,\n      labels: yAxisLabels,\n      initialCost: initialCost\n    };\n\n    \/\/ \u30b0\u30e9\u30d5\u306e\u30b5\u30a4\u30ba\u8a2d\u5b9a\n    const chartWidth = chartSection.clientWidth;\n    const chartHeight = 400;\n\n    \/\/ \u521d\u671f\u6295\u8cc7\u984d\u306e\u6841\u6570\u306b\u5fdc\u3058\u3066\u30b0\u30e9\u30d5\u306e\u5de6\u5074\u306e\u4f59\u767d\u3092\u52d5\u7684\u306b\u8a08\u7b97\uff085\u6841\u306770px\u3092\u57fa\u6e96\uff09\n    const getLeftMargin = () => {\n      const initialCost = yAxisConfig.initialCost;\n      const digitCount = initialCost > 0 ? Math.floor(Math.log10(Math.abs(initialCost))) + 1 : 1;\n      if (IS_MOBILE) {\n        \/\/ \u30e2\u30d0\u30a4\u30eb\u3067\u306f\u30e9\u30d9\u30eb\u3092\u56de\u8ee2\u3055\u305b\u308b\u306e\u3067\u3001\u6841\u6570\u306f\u8003\u616e\u3057\u306a\u304f\u3066\u3044\u3044\uff08\u6a2a\u5e45\u304c\u6841\u6570\u306b\u5fdc\u3058\u3066\u5909\u308f\u3089\u306a\u3044\u304b\u3089\uff09\n        return 20;\n      } else {\n        \/\/ 5\u6841\u306770px\u306b\u306a\u308b\u3088\u3046\u306b\u8a08\u7b97: leftMargin = 50 + (\u6841\u6570 - 3) * 10\uff08\u6700\u5c0f\u5024\u306f40px\u3001\u6700\u5927\u5024\u306f\u5236\u9650\u306a\u3057\uff09\n        return Math.max(40, 50 + (digitCount - 3) * 10);\n      }\n    };\n    const leftMargin = getLeftMargin();\n    const bottomMargin = 50; \/\/ x\u8ef8\u30e9\u30d9\u30eb\u306e\u30b9\u30da\u30fc\u30b9\n    const topMargin = 20;\n    const rightMargin = 20;\n    const graphWidth = chartWidth - leftMargin - rightMargin;\n    const graphHeight = chartHeight - topMargin - bottomMargin;\n\n    \/\/ x\u8ef8\u306e0\u5730\u70b9\u306e\u4f4d\u7f6e\uff08\u30b0\u30e9\u30d5\u30a8\u30ea\u30a2\u5185\u3067\u306e\u4f4d\u7f6e\uff09\n    const xAxisZeroX = leftMargin;\n    const tickInterval = xAxisConfig.tickInterval;\n    \/\/ \u9593\u9694\u304c12\u306e\u500d\u6570\u306e\u5834\u5408\u306f\u5e74\u5358\u4f4d\u3067\u8868\u793a\n    const xAxisLabelType = (tickInterval % 12 === 0 && tickInterval >= 12) ? 'Year' : 'Month';\n\n    \/\/ SVG\u8981\u7d20\u3092\u4f5c\u6210\n    let svg = `\n      <svg width=\"${chartWidth}\" height=\"${chartHeight}\">\n        <!-- \u30b0\u30ea\u30c3\u30c9\u7dda -->\n    `;\n\n    \/\/ x\u8ef8\u306e0\u5730\u70b9\u304b\u3089\u4e0a\u306b\u5411\u304b\u3063\u3066\u7e26\u7dda\u3092\u5f15\u304f\n    svg += `<line x1=\"${xAxisZeroX}\" y1=\"${topMargin}\" x2=\"${xAxisZeroX}\" y2=\"${topMargin + graphHeight}\" stroke=\"#D9D9D9\" stroke-width=\"1\"\/>`;\n\n    \/\/ y\u8ef8\u306e3\u3064\u306e\u30e1\u30e2\u30ea\u304b\u3089\u53f3\u306b\u5411\u304b\u3063\u3066\u6a2a\u7dda\u3092\u5f15\u304f\n    const yValues = [yAxisConfig.minValue, 0, yAxisConfig.maxValue];\n    yValues.forEach((value) => {\n      \/\/ y\u8ef8\u306e\u5024\u304b\u3089\u30b0\u30e9\u30d5\u5185\u306ey\u5ea7\u6a19\u3092\u8a08\u7b97\n      const ratio = (value - yAxisConfig.minValue) \/ (yAxisConfig.maxValue - yAxisConfig.minValue);\n      const y = topMargin + graphHeight - (ratio * graphHeight);\n      \/\/ \u53f3\u7aef\u307e\u3067\u7dda\u3092\u5f15\u304f\n      svg += `<line x1=\"${leftMargin}\" y1=\"${y}\" x2=\"${leftMargin + graphWidth}\" y2=\"${y}\" stroke=\"#D9D9D9\" stroke-width=\"1\"\/>`;\n    });\n\n    \/\/ y\u8ef8\u306e\u30e1\u30e2\u30ea\u30e9\u30d9\u30eb\uff08\u5de6\u5074\uff09\n    yValues.forEach((value, index) => {\n      const ratio = (value - yAxisConfig.minValue) \/ (yAxisConfig.maxValue - yAxisConfig.minValue);\n      let y = topMargin + graphHeight - (ratio * graphHeight);\n      const label = yAxisConfig.labels[index];\n\n      if (IS_MOBILE && value !== 0) {\n        \/\/ \u30e2\u30d0\u30a4\u30eb\u6642\u306f0\u4ee5\u5916\u306e\u30e9\u30d9\u30eb\u309290\u5ea6\u56de\u8ee2\n        if (value === yAxisConfig.minValue) {\n          \/\/ \u30de\u30a4\u30ca\u30b9\u306e\u5024\u30e9\u30d9\u30eb\uff1a\u6700\u5927\u6841\u6570\u306e\u6570\u5b57\u304cx\u8ef8\u306e\u6a2a\u7dda\u306e\u4f4d\u7f6e\u306b\u6765\u308b\u3088\u3046\u306b\u8abf\u6574\n          \/\/ x\u8ef8\u306e\u6a2a\u7dda\u306e\u4f4d\u7f6e\u306f topMargin + graphHeight\n          \/\/ \u30e9\u30d9\u30eb\u304b\u3089\u6700\u5927\u6841\u6570\u306e\u6570\u5b57\uff08\u6700\u521d\u306e\u6570\u5b57\uff09\u306e\u4f4d\u7f6e\u3092\u8a08\u7b97\n          \/\/ \u30e9\u30d9\u30eb\u306f \"-100,000\" \u306e\u3088\u3046\u306a\u5f62\u5f0f\u3067\u3001\u6700\u5927\u6841\u6570\u306e\u6570\u5b57\u306f \"-\" \u306e\u6b21\u306e\u6587\u5b57\n          const firstDigitIndex = label.search(\/\\d\/); \/\/ \u6700\u521d\u306e\u6570\u5b57\u306e\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\n          const xAxisY = topMargin + graphHeight; \/\/ x\u8ef8\u306e\u6a2a\u7dda\u306e\u4f4d\u7f6e\n          \/\/ \u56de\u8ee2\u306e\u4e2d\u5fc3\u70b9\u3092\u6700\u5927\u6841\u6570\u306e\u6570\u5b57\u306e\u4f4d\u7f6e\u306b\u8a2d\u5b9a\n          \/\/ text-anchor=\"start\"\u306b\u3057\u3066\u3001\u6700\u5927\u6841\u6570\u306e\u6570\u5b57\u304c\u56de\u8ee2\u306e\u4e2d\u5fc3\u70b9\u306b\u6765\u308b\u3088\u3046\u306b\u3059\u308b\n          \/\/ \u30d5\u30a9\u30f3\u30c8\u30b5\u30a4\u30ba10px\u3001\u6587\u5b57\u9593\u9694\u3092\u8003\u616e\uff08\u7d046px\uff09\n          const rotationCenterX = leftMargin - 5;\n          const rotationCenterY = xAxisY;\n          \/\/ \u30c6\u30ad\u30b9\u30c8\u306e\u4f4d\u7f6e\u3092\u8abf\u6574\uff08\u6700\u5927\u6841\u6570\u306e\u6570\u5b57\u304c\u56de\u8ee2\u306e\u4e2d\u5fc3\u70b9\u306b\u6765\u308b\u3088\u3046\u306b\uff09\n          const textX = rotationCenterX - firstDigitIndex * 6; \/\/ \u5de6\u306b\u79fb\u52d5\n          svg += `<text x=\"${textX}\" y=\"${rotationCenterY}\" text-anchor=\"start\" font-size=\"10px\" fill=\"#000\" transform=\"rotate(-90 ${rotationCenterX} ${rotationCenterY})\">${label}<\/text>`;\n        } else {\n          \/\/ \u30d7\u30e9\u30b9\u306e\u5024\u30e9\u30d9\u30eb\uff1a\u901a\u5e38\u306e\u51e6\u7406\n          svg += `<text x=\"${leftMargin - 5}\" y=\"${y + 4}\" text-anchor=\"end\" font-size=\"10px\" fill=\"#000\" transform=\"rotate(-90 ${leftMargin - 5} ${y + 4})\">${label}<\/text>`;\n        }\n      } else {\n        \/\/ \u901a\u5e38\u6642\u307e\u305f\u306f0\u306e\u30e9\u30d9\u30eb\n        \/\/ \u30de\u30a4\u30ca\u30b9\u306e\u5024\u30e9\u30d9\u30eb\u306f\u4e0a\u306b\u79fb\u52d5\n        if (value === yAxisConfig.minValue) {\n          y = y - 5;\n        }\n        svg += `<text x=\"${leftMargin - 10}\" y=\"${y + 4}\" text-anchor=\"end\" font-size=\"10px\" fill=\"#000\">${label}<\/text>`;\n      }\n    });\n\n    \/\/ x\u8ef8\u306e\u30e1\u30e2\u30ea\u30e9\u30d9\u30eb\uff08\u4e0b\u5074\uff09\n    \/\/ 0\u30f6\u6708\u304b\u3089maxMonths\u307e\u3067\u3001tickInterval\u3054\u3068\u306b\u30e9\u30d9\u30eb\u3092\u8868\u793a\n    \/\/ \u9593\u9694\u304c12\u306e\u500d\u6570\u306e\u5834\u5408\u306f\u5e74\u5358\u4f4d\u3067\u8868\u793a\n    const isYearTickInterval = tickInterval % 12 === 0 && tickInterval >= 12;\n    for (let month = 0; month <= maxMonths; month += tickInterval) {\n      const ratio = month \/ maxMonths;\n      const x = leftMargin + (ratio * graphWidth);\n      let label = '';\n      if (isYearTickInterval) {\n        const years = Math.floor(month \/ 12);\n        label = `${years}`;\n      } else {\n        label = `${month}`;\n      }\n      svg += `<text x=\"${x}\" y=\"${topMargin + graphHeight + 20}\" text-anchor=\"middle\" font-size=\"10px\" fill=\"#000\">${label}<\/text>`;\n    }\n\n    \/\/ x\u8ef8\u306e\u30e9\u30d9\u30eb\uff08Month or Year\uff09\n    svg += `<text x=\"${leftMargin + graphWidth \/ 2}\" y=\"${topMargin + graphHeight + 40}\" text-anchor=\"middle\" font-size=\"10px\" fill=\"#000\">${xAxisLabelType}<\/text>`;\n\n    \/\/ \u8a08\u7b97\u7d50\u679c\u3092\u3082\u3068\u306b\u3059\u3079\u3066\u306e\u6708\u306e\u7d2f\u7a4d\u5229\u76ca\u3092\u8a08\u7b97\u3057\u3066\u70b9\u3092\u914d\u7f6e\n    const pointSize = 4; \/\/ \u70b9\u306e\u30b5\u30a4\u30ba\uff08\u534a\u5f84\uff09\n    const pointColor = '#0073CD';\n\n    \/\/ 0\u30f6\u6708\u76ee\u304b\u3089maxMonths\u307e\u3067\u3001\u3059\u3079\u3066\u306e\u6708\u306e\u7d2f\u7a4d\u5229\u76ca\u3092\u8a08\u7b97\u3057\u3066\u5ea7\u6a19\u3092\u53d6\u5f97\n    cumulativeProfit = -initialCost; \/\/ 0\u30f6\u6708\u76ee\u306e\u7d2f\u7a4d\u5229\u76ca\uff08\u521d\u671f\u6295\u8cc7\u984d\u306e\u30de\u30a4\u30ca\u30b9\u5024\uff09\n    const points = []; \/\/ \u70b9\u306e\u5ea7\u6a19\u3092\u4fdd\u5b58\u3059\u308b\u914d\u5217\n    for (let month = 0; month <= maxMonths; month++) {\n      if (month === 0) {\n        \/\/ 0\u30f6\u6708\u76ee\u306f\u521d\u671f\u6295\u8cc7\u984d\u306e\u30de\u30a4\u30ca\u30b9\u5024\n        cumulativeProfit = -initialCost;\n      } else {\n        \/\/ \u6708\u6b21\u5229\u76ca\u3092\u8a08\u7b97\n        let monthlyProfit = monthlySales - monthlyCost;\n        \/\/ \u30ed\u30fc\u30f3\u304c\u3042\u308b\u5834\u5408\u3001\u8fd4\u6e08\u671f\u9593\u4e2d\uff081\u30f6\u6708\u76ee\u304b\u3089repaymentPeriod\u30f6\u6708\u76ee\u307e\u3067\uff09\u306f\u30ed\u30fc\u30f3\u8fd4\u6e08\u984d\u3092\u5dee\u3057\u5f15\u304f\n        const isInRepaymentPeriod = useLoan && month >= 1 && month <= repaymentPeriod;\n        if (isInRepaymentPeriod) {\n          monthlyProfit -= monthlyLoanPayment;\n        }\n        \/\/ \u7d2f\u7a4d\u5229\u76ca\u3092\u66f4\u65b0\n        cumulativeProfit += monthlyProfit;\n      }\n      \/\/ \u70b9\u306e\u5ea7\u6a19\u3092\u8a08\u7b97\n      const x = leftMargin + (month \/ maxMonths) * graphWidth;\n      const ratio = (cumulativeProfit - yAxisConfig.minValue) \/ (yAxisConfig.maxValue - yAxisConfig.minValue);\n      const y = topMargin + graphHeight - (ratio * graphHeight);\n      \/\/ \u5ea7\u6a19\u3092\u914d\u5217\u306b\u4fdd\u5b58\n      points.push({ x, y });\n    }\n    \/\/ \u70b9\u3068\u70b9\u3092\u7dda\u3067\u7e4b\u3050\n    const linePoints = points.map(p => `${p.x},${p.y}`).join(' ');\n    svg += `<polyline points=\"${linePoints}\" fill=\"none\" stroke=\"${pointColor}\" stroke-width=\"2\"\/>`;\n    \/\/ \u5404\u70b9\u3092\u914d\u7f6e\uff08\u5c06\u6765\u7528\u306b\u4eca\u306f\u900f\u660e\u306b\uff09\n    points.forEach(point => {\n      svg += `<circle cx=\"${point.x}\" cy=\"${point.y}\" r=\"${pointSize}\" fill=\"${pointColor}\" style=\"opacity: 0;\"\/>`;\n    });\n\n    \/\/ \u30b0\u30e9\u30d5\u306e\u4e0a\u90e8\u306b\u9577\u65b9\u5f62\u3092\u914d\u7f6e\uff08\u7dda\u3088\u308a\u4e0a\u306b\u914d\u7f6e\u3057\u3066\u7dda\u304c\u306f\u307f\u51fa\u305f\u90e8\u5206\u3092\u96a0\u3059\uff09\n    svg += `<rect x=\"${leftMargin - 1}\" y=\"-1\" width=\"${graphWidth + 1}\" height=\"${topMargin}\" fill=\"#fff\"\/>`;\n    svg += `\n      <\/svg>\n    `;\n    chartSection.innerHTML = svg;\n  };\n\n  \/\/ \u3053\u3053\u307e\u3067\u30b0\u30e9\u30d5\u95a2\u9023\u306e\u51e6\u7406\n  \/\/ *****************************************\n  \/\/ *****************************************************\n  \/\/ ********************************************************************\n\n\n\n\n\n  \/\/ ====================================================================================================================================\n  \/\/ \u30a4\u30d9\u30f3\u30c8\u30cf\u30f3\u30c9\u30e9\u30fc\n  \/\/ ====================================================================================================================================\n\n  \/**\n   * \u753b\u9762\u8aad\u8fbc\u6642\n   *\/\n  (() => {\n    reflectCurrentCurrency();\n    calculateTotalInitialInvestment();\n    calculateTotalMonthlySalesPlan();\n    calculateTotalMaterialCost();\n    calculateTotalLaborCost();\n    calculateTotalMillingCost();\n    calculateMonthlyLoanPayment();\n    toggleLoanInputsDisabled();\n    showSummaryBeforeCalculate();\n  })();\n\n  \/**\n   * \u901a\u8ca8\u9078\u629e\u6642\n   *\/\n  selectCurrency.addEventListener('change', (e) => {\n    reflectCurrentCurrency();\n  });\n\n  \/**\n   * Input\u5165\u529b\u6642\n   *\/\n  allInputs.forEach(input => {\n    \/\/ \u30d5\u30a9\u30fc\u30ab\u30b9\u6642\uff1a\u30ab\u30f3\u30de\u3092\u524a\u9664\n    input.addEventListener('focus', (e) => {\n      const value = e.target.value;\n      e.target.value = removeCommas(value);\n    });\n\n    \/\/ \u5165\u529b\u6642\uff1a\u30a8\u30e9\u30fc\u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u975e\u8868\u793a\u306b\u3059\u308b\n    input.addEventListener('input', (e) => {\n      const value = e.target.value;\n      const hasValue = value && value.trim() !== '';\n      if (hasValue) {\n        toggleErrorMessage(input, false);\n        \/\/ data-max\u3068data-min\u306e\u30a8\u30e9\u30fc\u30e1\u30c3\u30bb\u30fc\u30b8\u3082\u975e\u8868\u793a\u306b\u3059\u308b\n        toggleMaxMinErrorMessage(input, false);\n      }\n\n      \/\/ \u5165\u529b\u30d5\u30a3\u30fc\u30eb\u30c9\u306e\u9023\u52d5\u51e6\u7406\n      \/\/ - input-zirconia-units \u3068 input-units-to-mill-zirconia \u3092\u9023\u52d5\n      if (input === inputZirconiaUnits && !isSyncingZirconia) {\n        isSyncingZirconia = true;\n        inputUnitsToMillZirconia.value = value;\n        isSyncingZirconia = false;\n      } else if (input === inputUnitsToMillZirconia && !isSyncingZirconia) {\n        isSyncingZirconia = true;\n        inputZirconiaUnits.value = value;\n        isSyncingZirconia = false;\n      }\n      \/\/ - input-glass-ceramics-units \u3068 input-units-to-mill-glass \u3092\u9023\u52d5\n      if (input === inputGlassCeramicsUnits && !isSyncingGlass) {\n        isSyncingGlass = true;\n        inputUnitsToMillGlass.value = value;\n        isSyncingGlass = false;\n      } else if (input === inputUnitsToMillGlass && !isSyncingGlass) {\n        isSyncingGlass = true;\n        inputGlassCeramicsUnits.value = value;\n        isSyncingGlass = false;\n      }\n      \/\/ - input-other-materials-units \u3068 input-units-to-mill-other-materials \u3092\u9023\u52d5\n      if (input === inputOtherMaterialsUnits && !isSyncingOtherMaterials) {\n        isSyncingOtherMaterials = true;\n        inputUnitsToMillOtherMaterials.value = value;\n        isSyncingOtherMaterials = false;\n      } else if (input === inputUnitsToMillOtherMaterials && !isSyncingOtherMaterials) {\n        isSyncingOtherMaterials = true;\n        inputOtherMaterialsUnits.value = value;\n        isSyncingOtherMaterials = false;\n      }\n\n      \/\/ Sales Price\u30bb\u30c3\u30c8\u306e\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\uff08\u5165\u529b\u6642\uff09\n      if (input === inputZirconiaPrice || input === inputZirconiaUnits || input === inputGlassCeramicsPrice || input === inputGlassCeramicsUnits || input === inputOtherMaterialsPrice || input === inputOtherMaterialsUnits) {\n        validateSalesPriceSets();\n      }\n    });\n\n    \/\/ \u30d5\u30a9\u30fc\u30ab\u30b9\u30a2\u30a6\u30c8\u6642\uff1a\u6570\u5024\u306e\u307f\u8a31\u53ef\u3001\u5168\u89d2\u3092\u534a\u89d2\u306b\u5909\u63db\u3001\u30ab\u30f3\u30de\u3092\u8ffd\u52a0\u3001\u518d\u8a08\u7b97\u3001\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\n    input.addEventListener('blur', (e) => {\n      const value = e.target.value;\n      const hasValue = value && value.trim() !== '';\n\n      if (hasValue) {\n        \/\/ \u6570\u5024\u306e\u307f\u8a31\u53ef\u3001\u5168\u89d2\u3092\u534a\u89d2\u306b\u5909\u63db\n        const numericValue = extractNumbers(value);\n        e.target.value = numericValue;\n        \/\/ \u30ab\u30f3\u30de\u3092\u8ffd\u52a0\n        if (numericValue && numericValue.trim() !== '') {\n          e.target.value = addCommas(numericValue);\n        }\n      }\n\n      \/\/ \u5165\u529b\u30d5\u30a3\u30fc\u30eb\u30c9\u306e\u9023\u52d5\u51e6\u7406\uff08blur\u6642\uff1a\u30ab\u30f3\u30de\u4ed8\u304d\u306e\u5024\u3092\u540c\u671f\uff09\n      \/\/ - input-zirconia-units \u3068 input-units-to-mill-zirconia \u3092\u9023\u52d5\n      if (input === inputZirconiaUnits && !isSyncingZirconia) {\n        isSyncingZirconia = true;\n        const finalValue = e.target.value;\n        if (finalValue && finalValue.trim() !== '') {\n          inputUnitsToMillZirconia.value = finalValue;\n        }\n        isSyncingZirconia = false;\n      } else if (input === inputUnitsToMillZirconia && !isSyncingZirconia) {\n        isSyncingZirconia = true;\n        const finalValue = e.target.value;\n        if (finalValue && finalValue.trim() !== '') {\n          inputZirconiaUnits.value = finalValue;\n        }\n        isSyncingZirconia = false;\n      }\n      \/\/ - input-glass-ceramics-units \u3068 input-units-to-mill-glass \u3092\u9023\u52d5\n      if (input === inputGlassCeramicsUnits && !isSyncingGlass) {\n        isSyncingGlass = true;\n        const finalValue = e.target.value;\n        if (finalValue && finalValue.trim() !== '') {\n          inputUnitsToMillGlass.value = finalValue;\n        }\n        isSyncingGlass = false;\n      } else if (input === inputUnitsToMillGlass && !isSyncingGlass) {\n        isSyncingGlass = true;\n        const finalValue = e.target.value;\n        if (finalValue && finalValue.trim() !== '') {\n          inputGlassCeramicsUnits.value = finalValue;\n        }\n        isSyncingGlass = false;\n      }\n      \/\/ - input-other-materials-units \u3068 input-units-to-mill-other-materials \u3092\u9023\u52d5\n      if (input === inputOtherMaterialsUnits && !isSyncingOtherMaterials) {\n        isSyncingOtherMaterials = true;\n        const finalValue = e.target.value;\n        if (finalValue && finalValue.trim() !== '') {\n          inputUnitsToMillOtherMaterials.value = finalValue;\n        }\n        isSyncingOtherMaterials = false;\n      } else if (input === inputUnitsToMillOtherMaterials && !isSyncingOtherMaterials) {\n        isSyncingOtherMaterials = true;\n        const finalValue = e.target.value;\n        if (finalValue && finalValue.trim() !== '') {\n          inputOtherMaterialsUnits.value = finalValue;\n        }\n        isSyncingOtherMaterials = false;\n      }\n\n      \/\/ required\u5c5e\u6027\u304c\u3042\u308b\u5834\u5408\u306e\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\n      if (input.hasAttribute('required')) {\n        const finalValue = e.target.value;\n        const finalHasValue = finalValue && finalValue.trim() !== '';\n        const numericValue = finalHasValue ? Number(removeCommas(finalValue)) : 0;\n        const showError = !finalHasValue || numericValue === 0;\n        toggleErrorMessage(input, showError);\n      }\n\n      \/\/ data-max\u3068data-min\u306e\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\n      if (input.hasAttribute('data-max') && input.hasAttribute('data-min')) {\n        const hasError = validateMaxMin(input);\n        toggleMaxMinErrorMessage(input, hasError);\n      }\n\n      \/\/ Initial Investment Cost \u95a2\u9023\u306e\u5165\u529b\u30d5\u30a3\u30fc\u30eb\u30c9\u304c\u5909\u66f4\u3055\u308c\u305f\u3089\u518d\u8a08\u7b97\n      if (input === inputDwxPrice || input === inputOtherExpenses) {\n        calculateTotalInitialInvestment();\n      }\n\n      \/\/ Monthly Sales Plan \u95a2\u9023\u306e\u5165\u529b\u30d5\u30a3\u30fc\u30eb\u30c9\u304c\u5909\u66f4\u3055\u308c\u305f\u3089\u518d\u8a08\u7b97\n      if (input === inputZirconiaPrice || input === inputZirconiaUnits || input === inputGlassCeramicsPrice || input === inputGlassCeramicsUnits || input === inputOtherMaterialsPrice || input === inputOtherMaterialsUnits) {\n        \/\/ Sales Price\u30bb\u30c3\u30c8\u306e\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\n        validateSalesPriceSets();\n        \/\/ \u521d\u56de\u5165\u529b\u30d5\u30e9\u30b0\u3092\u66f4\u65b0\uff08\u5024\u304c\u5165\u529b\u3055\u308c\u3066\u3044\u308b\u5834\u5408\u3001\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u5f8c\u306b\u66f4\u65b0\uff09\n        if (hasValue && isFirstSalesPriceInput) {\n          isFirstSalesPriceInput = false;\n        }\n        \/\/ \u8a08\u7b97\n        calculateTotalMonthlySalesPlan();\n      }\n\n      \/\/ Total Material Cost \u95a2\u9023\u306e\u5165\u529b\u30d5\u30a3\u30fc\u30eb\u30c9\u304c\u5909\u66f4\u3055\u308c\u305f\u3089\u518d\u8a08\u7b97\n      if (input === inputMaterialCostZirconia || input === inputUnitsToMillZirconia || input === inputMaterialCostGlass || input === inputUnitsToMillGlass || input === inputMaterialCostOtherMaterials || input === inputUnitsToMillOtherMaterials) {\n        calculateTotalMaterialCost();\n      }\n\n      \/\/ Total Labor Cost \u95a2\u9023\u306e\u5165\u529b\u30d5\u30a3\u30fc\u30eb\u30c9\u304c\u5909\u66f4\u3055\u308c\u305f\u3089\u518d\u8a08\u7b97\n      if (input === inputLaborCost || input === inputUnitsToMillZirconia || input === inputUnitsToMillGlass || input === inputUnitsToMillOtherMaterials) {\n        calculateTotalLaborCost();\n      }\n\n      \/\/ Monthly Loan Payment \u95a2\u9023\u306e\u5165\u529b\u30d5\u30a3\u30fc\u30eb\u30c9\u304c\u5909\u66f4\u3055\u308c\u305f\u3089\u518d\u8a08\u7b97\n      if (input === inputDownPayment || input === inputAnnualInterestRate || input === inputRepaymentPeriod) {\n        calculateMonthlyLoanPayment();\n      }\n    });\n  });\n\n  \/**\n   * Use Loan \u30c1\u30a7\u30c3\u30af\u30dc\u30c3\u30af\u30b9\u5909\u66f4\u6642\n   *\/\n  inputUseLoan.addEventListener('change', () => {\n    toggleLoanInputsDisabled();\n  });\n\n  \/**\n   * \u8a08\u7b97\u30dc\u30bf\u30f3\u62bc\u4e0b\u6642\n   *\/\n  buttonCalculate.addEventListener('click', (e) => {\n    e.preventDefault();\n\n    \/\/ \u3059\u3079\u3066\u306erequired\u5c5e\u6027\u304c\u3042\u308binput\u3092\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\n    let hasError = false;\n    allInputs.forEach(input => {\n      if (input.hasAttribute('required')) {\n        const value = input.value;\n        const hasValue = value && value.trim() !== '';\n        const numericValue = hasValue ? Number(removeCommas(value)) : 0;\n        const showError = !hasValue || numericValue === 0;\n        toggleErrorMessage(input, showError);\n        if (showError) {\n          hasError = true;\n        }\n      }\n    });\n\n    \/\/ Sales Price\u30bb\u30c3\u30c8\u306e\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\uff08\u8a08\u7b97\u30dc\u30bf\u30f3\u62bc\u4e0b\u6642\u306f\u5e38\u306b\u30c1\u30a7\u30c3\u30af\uff09\n    isFirstSalesPriceInput = false; \/\/ \u8a08\u7b97\u30dc\u30bf\u30f3\u62bc\u4e0b\u6642\u306f\u521d\u56de\u30d5\u30e9\u30b0\u3092\u7121\u52b9\u5316\n    const salesPriceError = validateSalesPriceSets();\n    if (salesPriceError) {\n      hasError = true;\n    }\n\n    \/\/ data-max\u3068data-min\u306e\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\n    allInputs.forEach(input => {\n      if (input.hasAttribute('data-max') && input.hasAttribute('data-min')) {\n        const maxMinError = validateMaxMin(input);\n        toggleMaxMinErrorMessage(input, maxMinError);\n        if (maxMinError) {\n          hasError = true;\n        }\n      }\n    });\n\n    \/\/ \u30a8\u30e9\u30fc\u304c\u3042\u308b\u5834\u5408\u306f\u51e6\u7406\u3092\u4e2d\u65ad\u3057\u3001\u6700\u521d\u306e\u30a8\u30e9\u30fc\u30e1\u30c3\u30bb\u30fc\u30b8\u306b\u30b9\u30af\u30ed\u30fc\u30eb\n    if (hasError) {\n      \/\/ \u3059\u3079\u3066\u306e\u30a8\u30e9\u30fc\u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u53d6\u5f97\n      const errorMessages = document.querySelectorAll('.roi-error-message');\n      \/\/ \u6700\u521d\u306b\u8868\u793a\u3055\u308c\u3066\u3044\u308b\u30a8\u30e9\u30fc\u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u898b\u3064\u3051\u308b\n      for (const errorMsg of errorMessages) {\n        if (errorMsg.style.display === 'block') {\n          errorMsg.scrollIntoView({ behavior: 'smooth', block: 'center' });\n          break;\n        }\n      }\n      return;\n    }\n\n    calculateSummary();\n    showSummaryAfterCalculate();\n    displayChart();\n\n    \/\/ summaryWrapper\u306b\u30b9\u30af\u30ed\u30fc\u30eb\n    if (summaryWrapper) {\n      summaryWrapper.scrollIntoView({ behavior: 'smooth', block: 'start' });\n    }\n  });\n\n  \/**\n   * RESET\u30dc\u30bf\u30f3\u62bc\u4e0b\u6642\n   *\/\n  buttonReset.addEventListener('click', () => {\n    \/\/ \u8a08\u7b97\u7d50\u679c\u3092\u30af\u30ea\u30a2\n    totalInitialInvestment.textContent = '0';\n    totalSales.textContent = '0';\n    totalMaterialCost.textContent = '0';\n    totalLaborCost.textContent = '0';\n    totalMillingCost.textContent = '0';\n    monthlyLoanPayment.textContent = '0';\n\n    \/\/ Summary\u30bb\u30af\u30b7\u30e7\u30f3\u306e\u8a08\u7b97\u7d50\u679c\u3092\u30af\u30ea\u30a2\n    summaryInitialCost.textContent = '0';\n    summaryPaybackPeriod.textContent = '0.0';\n    summaryMonthlyProfitDuringRepayingLoan.textContent = '0';\n    summaryMonthlyProfitWithoutLoan.textContent = '0';\n    summaryMonthlyTotalSales.textContent = '0';\n    summaryMonthlyMillingCost.textContent = '0';\n    summaryMonthlyLoanPayment.textContent = '0';\n\n    \/\/ \u30b0\u30e9\u30d5\u3092\u30af\u30ea\u30a2\n    if (chartSection) {\n      chartSection.innerHTML = '';\n    }\n\n    \/\/ \u30a8\u30e9\u30fc\u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u975e\u8868\u793a\n    const errorMessages = document.querySelectorAll('.roi-error-message');\n    errorMessages.forEach(msg => {\n      msg.style.display = 'none';\n    });\n\n    \/\/ \u5165\u529b\u6b04\u306e\u80cc\u666f\u8272\u3092\u30ea\u30bb\u30c3\u30c8\n    allInputs.forEach(input => {\n      input.style.background = '';\n    });\n\n    \/\/ \u521d\u56de\u5165\u529b\u30d5\u30e9\u30b0\u3092\u30ea\u30bb\u30c3\u30c8\n    isFirstSalesPriceInput = true;\n\n    \/\/ Summary\u8868\u793a\u3092\u521d\u671f\u72b6\u614b\u306b\u623b\u3059\n    showSummaryBeforeCalculate();\n\n    \/\/ \u30d5\u30a9\u30fc\u30e0\u30ea\u30bb\u30c3\u30c8\u5f8c\u306b\u901a\u8ca8\u8868\u793a\u3092\u66f4\u65b0\uff08\u6b21\u306e\u30a4\u30d9\u30f3\u30c8\u30eb\u30fc\u30d7\u3067\u5b9f\u884c\uff09\n    setTimeout(() => {\n      reflectCurrentCurrency();\n    }, 0);\n  });\n\n});\n<\/script>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>\u00a5 \u521d\u59cb\u6295\u8d44\u8d39\u7528 DWX \u4ef7\u683c* \u00a5 *\u6b64\u9879\u4e3a\u5fc5\u586b\u9879\u3002 *\u8bf7\u8f93\u5165 0 \u81f3 10,000,000 \u4e4b\u95f4\u7684\u6570\u503c \u5176 [&hellip;]<\/p>\n","protected":false},"author":27,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-87660","page","type-page","status-publish","hentry"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.3 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u00a5 \u521d\u59cb\u6295\u8d44\u8d39\u7528 DWX \u4ef7\u683c* \u00a5 *\u6b64\u9879\u4e3a\u5fc5\u586b\u9879\u3002 *\u8bf7\u8f93\u5165 0 \u81f3 10,000,000 \u4e4b\u95f4\u7684\u6570\u503c \u5176\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"google-site-verification\" content=\"Eodkz-nqydu_Mnxtc81Q6rbKIHsq2jmAaqHbwxWt99U\" \/>\n\t<meta name=\"msvalidate.01\" content=\"D2995FD42F502D07257424BCCFC4E9CF\" \/>\n\t<link rel=\"canonical\" href=\"https:\/\/dgshape.com\/zh-hans\/simulator\/\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.3\" \/>\n\t\t<meta property=\"og:locale\" content=\"zh_CN\" \/>\n\t\t<meta property=\"og:site_name\" content=\"DGSHAPE - Empowering People To Shape The Future\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"DWX \u7cfb\u5217\u6295\u8d44\u56de\u62a5\u7387 (ROI) \u6a21\u62df\u5668 - DGSHAPE\" \/>\n\t\t<meta property=\"og:description\" content=\"\u00a5 \u521d\u59cb\u6295\u8d44\u8d39\u7528 DWX \u4ef7\u683c* \u00a5 *\u6b64\u9879\u4e3a\u5fc5\u586b\u9879\u3002 *\u8bf7\u8f93\u5165 0 \u81f3 10,000,000 \u4e4b\u95f4\u7684\u6570\u503c \u5176\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/dgshape.com\/zh-hans\/simulator\/\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/dgshape.com\/wp-content\/uploads\/2025\/06\/cropped-dgshapelogo.png\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/dgshape.com\/wp-content\/uploads\/2025\/06\/cropped-dgshapelogo.png\" \/>\n\t\t<meta property=\"og:image:width\" content=\"218\" \/>\n\t\t<meta property=\"og:image:height\" content=\"47\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2026-02-18T05:00:01+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2026-10-19T06:13:17+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/rolanddgshapeeurope\" \/>\n\t\t<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n\t\t<meta name=\"twitter:title\" content=\"DWX \u7cfb\u5217\u6295\u8d44\u56de\u62a5\u7387 (ROI) \u6a21\u62df\u5668 - DGSHAPE\" \/>\n\t\t<meta name=\"twitter:description\" content=\"\u00a5 \u521d\u59cb\u6295\u8d44\u8d39\u7528 DWX \u4ef7\u683c* \u00a5 *\u6b64\u9879\u4e3a\u5fc5\u586b\u9879\u3002 *\u8bf7\u8f93\u5165 0 \u81f3 10,000,000 \u4e4b\u95f4\u7684\u6570\u503c \u5176\" \/>\n\t\t<meta name=\"twitter:image\" content=\"https:\/\/dgshape.com\/wp-content\/uploads\/2025\/06\/cropped-dgshapelogo.png\" \/>\n\t\t<script type=\"application\/ld+json\" class=\"aioseo-schema\">\n\t\t\t{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/dgshape.com\\\/zh-hans\\\/simulator\\\/#breadcrumblist\",\"itemListElement\":[{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/dgshape.com\\\/zh-hans\\\/#listItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/dgshape.com\\\/zh-hans\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/dgshape.com\\\/zh-hans\\\/simulator\\\/#listItem\",\"name\":\"DWX \\u7cfb\\u5217\\u6295\\u8d44\\u56de\\u62a5\\u7387 (ROI) \\u6a21\\u62df\\u5668\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/dgshape.com\\\/zh-hans\\\/simulator\\\/#listItem\",\"position\":2,\"name\":\"DWX \\u7cfb\\u5217\\u6295\\u8d44\\u56de\\u62a5\\u7387 (ROI) \\u6a21\\u62df\\u5668\",\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/dgshape.com\\\/zh-hans\\\/#listItem\",\"name\":\"Home\"}}]},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/dgshape.com\\\/zh-hans\\\/#organization\",\"name\":\"DGSHAPE A Roland DG Group Company\",\"description\":\"Believing that its technologies and know-how related to 3D milling could contribute to improving the workflow of dental laboratories, Roland DG entered the market in 2010. In 2017, Roland DG transferred its 3D business to a newly-established, wholly-owned subsidiary, DGSHAPE Corporation, to dedicate more time, energy, and staff solely toward the development of innovative dental and other 3D solutions. Today, DGSHAPE continues to expand its customer base by offering solutions to dental laboratories all over the world. Going forward, the company intends to extend the scope of its business to include dental clinics.\",\"url\":\"https:\\\/\\\/dgshape.com\\\/zh-hans\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https:\\\/\\\/dgshape.com\\\/wp-content\\\/uploads\\\/2025\\\/06\\\/cropped-dgshapelogo.png\",\"@id\":\"https:\\\/\\\/dgshape.com\\\/zh-hans\\\/simulator\\\/#organizationLogo\",\"width\":218,\"height\":47},\"image\":{\"@id\":\"https:\\\/\\\/dgshape.com\\\/zh-hans\\\/simulator\\\/#organizationLogo\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/rolanddgshapeeurope\",\"https:\\\/\\\/www.instagram.com\\\/dgshapeeurope\\\/\",\"https:\\\/\\\/www.linkedin.com\\\/company\\\/dgshapeemea\\\/\"]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/dgshape.com\\\/zh-hans\\\/simulator\\\/#webpage\",\"url\":\"https:\\\/\\\/dgshape.com\\\/zh-hans\\\/simulator\\\/\",\"name\":\"DWX \\u7cfb\\u5217\\u6295\\u8d44\\u56de\\u62a5\\u7387 (ROI) \\u6a21\\u62df\\u5668 - DGSHAPE\",\"description\":\"\\u00a5 \\u521d\\u59cb\\u6295\\u8d44\\u8d39\\u7528 DWX \\u4ef7\\u683c* \\u00a5 *\\u6b64\\u9879\\u4e3a\\u5fc5\\u586b\\u9879\\u3002 *\\u8bf7\\u8f93\\u5165 0 \\u81f3 10,000,000 \\u4e4b\\u95f4\\u7684\\u6570\\u503c \\u5176\",\"inLanguage\":\"zh-CN\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/dgshape.com\\\/zh-hans\\\/#website\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/dgshape.com\\\/zh-hans\\\/simulator\\\/#breadcrumblist\"},\"datePublished\":\"2026-02-18T05:00:01+00:00\",\"dateModified\":\"2026-10-19T06:13:17+00:00\"},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/dgshape.com\\\/zh-hans\\\/#website\",\"url\":\"https:\\\/\\\/dgshape.com\\\/zh-hans\\\/\",\"name\":\"DGSHAPE - Dental Milling Machines\",\"alternateName\":\"DGSHAPE\",\"description\":\"Empowering People To Shape The Future\",\"inLanguage\":\"zh-CN\",\"publisher\":{\"@id\":\"https:\\\/\\\/dgshape.com\\\/zh-hans\\\/#organization\"}}]}\n\t\t<\/script>\n\t\t<script type=\"text\/javascript\">\n\t\t\t(function(c,l,a,r,i,t,y){\n\t\t\tc[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)};t=l.createElement(r);t.async=1;\n\t\t\tt.src=\"https:\/\/www.clarity.ms\/tag\/\"+i+\"?ref=aioseo\";y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y);\n\t\t})(window, document, \"clarity\", \"script\", \"nfnfkxhewy\");\n\t\t<\/script>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"DWX \u7cfb\u5217\u6295\u8d44\u56de\u62a5\u7387 (ROI) \u6a21\u62df\u5668 - DGSHAPE","description":"\u00a5 \u521d\u59cb\u6295\u8d44\u8d39\u7528 DWX \u4ef7\u683c* \u00a5 *\u6b64\u9879\u4e3a\u5fc5\u586b\u9879\u3002 *\u8bf7\u8f93\u5165 0 \u81f3 10,000,000 \u4e4b\u95f4\u7684\u6570\u503c \u5176","canonical_url":"https:\/\/dgshape.com\/zh-hans\/simulator\/","robots":"max-image-preview:large","keywords":"","webmasterTools":{"google-site-verification":"Eodkz-nqydu_Mnxtc81Q6rbKIHsq2jmAaqHbwxWt99U","msvalidate.01":"D2995FD42F502D07257424BCCFC4E9CF","miscellaneous":""},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"BreadcrumbList","@id":"https:\/\/dgshape.com\/zh-hans\/simulator\/#breadcrumblist","itemListElement":[{"@type":"ListItem","@id":"https:\/\/dgshape.com\/zh-hans\/#listItem","position":1,"name":"Home","item":"https:\/\/dgshape.com\/zh-hans\/","nextItem":{"@type":"ListItem","@id":"https:\/\/dgshape.com\/zh-hans\/simulator\/#listItem","name":"DWX \u7cfb\u5217\u6295\u8d44\u56de\u62a5\u7387 (ROI) \u6a21\u62df\u5668"}},{"@type":"ListItem","@id":"https:\/\/dgshape.com\/zh-hans\/simulator\/#listItem","position":2,"name":"DWX \u7cfb\u5217\u6295\u8d44\u56de\u62a5\u7387 (ROI) \u6a21\u62df\u5668","previousItem":{"@type":"ListItem","@id":"https:\/\/dgshape.com\/zh-hans\/#listItem","name":"Home"}}]},{"@type":"Organization","@id":"https:\/\/dgshape.com\/zh-hans\/#organization","name":"DGSHAPE A Roland DG Group Company","description":"Believing that its technologies and know-how related to 3D milling could contribute to improving the workflow of dental laboratories, Roland DG entered the market in 2010. In 2017, Roland DG transferred its 3D business to a newly-established, wholly-owned subsidiary, DGSHAPE Corporation, to dedicate more time, energy, and staff solely toward the development of innovative dental and other 3D solutions. Today, DGSHAPE continues to expand its customer base by offering solutions to dental laboratories all over the world. Going forward, the company intends to extend the scope of its business to include dental clinics.","url":"https:\/\/dgshape.com\/zh-hans\/","logo":{"@type":"ImageObject","url":"https:\/\/dgshape.com\/wp-content\/uploads\/2025\/06\/cropped-dgshapelogo.png","@id":"https:\/\/dgshape.com\/zh-hans\/simulator\/#organizationLogo","width":218,"height":47},"image":{"@id":"https:\/\/dgshape.com\/zh-hans\/simulator\/#organizationLogo"},"sameAs":["https:\/\/www.facebook.com\/rolanddgshapeeurope","https:\/\/www.instagram.com\/dgshapeeurope\/","https:\/\/www.linkedin.com\/company\/dgshapeemea\/"]},{"@type":"WebPage","@id":"https:\/\/dgshape.com\/zh-hans\/simulator\/#webpage","url":"https:\/\/dgshape.com\/zh-hans\/simulator\/","name":"DWX \u7cfb\u5217\u6295\u8d44\u56de\u62a5\u7387 (ROI) \u6a21\u62df\u5668 - DGSHAPE","description":"\u00a5 \u521d\u59cb\u6295\u8d44\u8d39\u7528 DWX \u4ef7\u683c* \u00a5 *\u6b64\u9879\u4e3a\u5fc5\u586b\u9879\u3002 *\u8bf7\u8f93\u5165 0 \u81f3 10,000,000 \u4e4b\u95f4\u7684\u6570\u503c \u5176","inLanguage":"zh-CN","isPartOf":{"@id":"https:\/\/dgshape.com\/zh-hans\/#website"},"breadcrumb":{"@id":"https:\/\/dgshape.com\/zh-hans\/simulator\/#breadcrumblist"},"datePublished":"2026-02-18T05:00:01+00:00","dateModified":"2026-10-19T06:13:17+00:00"},{"@type":"WebSite","@id":"https:\/\/dgshape.com\/zh-hans\/#website","url":"https:\/\/dgshape.com\/zh-hans\/","name":"DGSHAPE - Dental Milling Machines","alternateName":"DGSHAPE","description":"Empowering People To Shape The Future","inLanguage":"zh-CN","publisher":{"@id":"https:\/\/dgshape.com\/zh-hans\/#organization"}}]},"og:locale":"zh_CN","og:site_name":"DGSHAPE - Empowering People To Shape The Future","og:type":"article","og:title":"DWX \u7cfb\u5217\u6295\u8d44\u56de\u62a5\u7387 (ROI) \u6a21\u62df\u5668 - DGSHAPE","og:description":"\u00a5 \u521d\u59cb\u6295\u8d44\u8d39\u7528 DWX \u4ef7\u683c* \u00a5 *\u6b64\u9879\u4e3a\u5fc5\u586b\u9879\u3002 *\u8bf7\u8f93\u5165 0 \u81f3 10,000,000 \u4e4b\u95f4\u7684\u6570\u503c \u5176","og:url":"https:\/\/dgshape.com\/zh-hans\/simulator\/","og:image":"https:\/\/dgshape.com\/wp-content\/uploads\/2025\/06\/cropped-dgshapelogo.png","og:image:secure_url":"https:\/\/dgshape.com\/wp-content\/uploads\/2025\/06\/cropped-dgshapelogo.png","og:image:width":218,"og:image:height":47,"article:published_time":"2026-02-18T05:00:01+00:00","article:modified_time":"2026-10-19T06:13:17+00:00","article:publisher":"https:\/\/www.facebook.com\/rolanddgshapeeurope","twitter:card":"summary_large_image","twitter:title":"DWX \u7cfb\u5217\u6295\u8d44\u56de\u62a5\u7387 (ROI) \u6a21\u62df\u5668 - DGSHAPE","twitter:description":"\u00a5 \u521d\u59cb\u6295\u8d44\u8d39\u7528 DWX \u4ef7\u683c* \u00a5 *\u6b64\u9879\u4e3a\u5fc5\u586b\u9879\u3002 *\u8bf7\u8f93\u5165 0 \u81f3 10,000,000 \u4e4b\u95f4\u7684\u6570\u503c \u5176","twitter:image":"https:\/\/dgshape.com\/wp-content\/uploads\/2025\/06\/cropped-dgshapelogo.png"},"aioseo_meta_data":{"post_id":"87660","title":null,"description":null,"keywords":null,"keyphrases":{"focus":{"keyphrase":"","score":0,"analysis":{"keyphraseInTitle":{"score":0,"maxScore":9,"error":1}}},"additional":[]},"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":"","og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"WebPage","isEnabled":true},"graphs":[]},"schema_type":"default","schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":"-1","robots_max_videopreview":"-1","robots_max_imagepreview":"large","priority":null,"frequency":"default","local_seo":null,"breadcrumb_settings":null,"limit_modified_date":false,"ai":{"faqs":[],"keyPoints":[],"schemas":[],"titles":[],"descriptions":[],"socialPosts":{"email":{"subject":"","preview":"","content":""},"linkedin":[],"twitter":[],"facebook":[],"instagram":[]}},"created":"2026-10-19 05:52:50","updated":"2026-10-19 06:44:12","seo_analyzer_scan_date":null,"focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"aioseo_breadcrumb":"<div class=\"aioseo-breadcrumbs\"><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/dgshape.com\/zh-hans\/\" title=\"Home\">Home<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">\u00bb<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\tDWX \u7cfb\u5217\u6295\u8d44\u56de\u62a5\u7387 (ROI) \u6a21\u62df\u5668\n\t\t<\/span><\/div>","aioseo_breadcrumb_json":[{"label":"Home","link":"https:\/\/dgshape.com\/zh-hans\/"},{"label":"DWX \u7cfb\u5217\u6295\u8d44\u56de\u62a5\u7387 (ROI) \u6a21\u62df\u5668","link":"https:\/\/dgshape.com\/zh-hans\/simulator\/"}],"_links":{"self":[{"href":"https:\/\/dgshape.com\/zh-hans\/wp-json\/wp\/v2\/pages\/87660","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dgshape.com\/zh-hans\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/dgshape.com\/zh-hans\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/dgshape.com\/zh-hans\/wp-json\/wp\/v2\/users\/27"}],"replies":[{"embeddable":true,"href":"https:\/\/dgshape.com\/zh-hans\/wp-json\/wp\/v2\/comments?post=87660"}],"version-history":[{"count":5,"href":"https:\/\/dgshape.com\/zh-hans\/wp-json\/wp\/v2\/pages\/87660\/revisions"}],"predecessor-version":[{"id":87676,"href":"https:\/\/dgshape.com\/zh-hans\/wp-json\/wp\/v2\/pages\/87660\/revisions\/87676"}],"wp:attachment":[{"href":"https:\/\/dgshape.com\/zh-hans\/wp-json\/wp\/v2\/media?parent=87660"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}