{"id":28846,"date":"2026-07-08T17:43:22","date_gmt":"2026-07-08T08:43:22","guid":{"rendered":"https:\/\/www.hiro-clinic.or.jp\/beauty\/?page_id=28846"},"modified":"2026-07-22T15:57:07","modified_gmt":"2026-07-22T06:57:07","slug":"reserve-beauty","status":"publish","type":"page","link":"https:\/\/www.hiro-clinic.or.jp\/beauty\/reserve-beauty\/","title":{"rendered":"\u7f8e\u5bb9\u4e88\u7d04\u30da\u30fc\u30b8"},"content":{"rendered":"\n<style>\n  .hc-doctors{display:none;}\n  html.pc #side_col{display:none;}\n  html.pc #left_col {width:100%;}\n  *{box-sizing:border-box;margin:0;padding:0}\n  .hero h1{font-size:clamp(24px,5vw,32px);}\n.ic[data-img=\"concern-shimi\"]{ background-image:url(\"\/beauty\/wp-content\/uploads\/2026\/07\/shimi.webp\"); }\n.ic[data-img=\"concern-tarumi\"]{ background-image:url(\"\/beauty\/wp-content\/uploads\/2026\/07\/tarumi.webp\"); }\n.ic[data-img=\"concern-akara\"]{ background-image:url(\"\/beauty\/wp-content\/uploads\/2026\/07\/akara.webp\"); }\n.ic[data-img=\"concern-keana\"]{ background-image:url(\"\/beauty\/wp-content\/uploads\/2026\/07\/keana.webp\"); }\n.ic[data-img=\"concern-bihaku\"]{ background-image:url(\"\/beauty\/wp-content\/uploads\/2026\/07\/bihaku.webp\"); }\n.ic[data-img=\"concern-wakaranai\"]{ background-image:url(\"\/beauty\/wp-content\/uploads\/2026\/07\/nayami.webp\"); }\n.ic[data-img=\"clinic-ikebukuro\"]{ background-image:url(\"\/beauty\/wp-content\/uploads\/2026\/07\/\u75c5\u9662\u306e\u30a2\u30a4\u30b3\u30f3\u7d20\u6750-1.webp\"); }\n.ic[data-img=\"clinic-kawaguchi\"]{ background-image:url(\"\/beauty\/wp-content\/uploads\/2026\/07\/\u75c5\u9662\u306e\u30a2\u30a4\u30b3\u30f3\u7d20\u6750-1.webp\"); }\n.ic[data-img=\"clinic-hakata\"]{ background-image:url(\"\/beauty\/wp-content\/uploads\/2026\/07\/\u75c5\u9662\u306e\u30a2\u30a4\u30b3\u30f3\u7d20\u6750-1.webp\"); }\n.ic[data-img=\"clinic-sapporo\"]{ background-image:url(\"\/beauty\/wp-content\/uploads\/2026\/07\/\u75c5\u9662\u306e\u30a2\u30a4\u30b3\u30f3\u7d20\u6750-1.webp\"); }\n.ic[data-img=\"clinic-tokyo\"]{ background-image:url(\"\/beauty\/wp-content\/uploads\/2026\/07\/\u75c5\u9662\u306e\u30a2\u30a4\u30b3\u30f3\u7d20\u6750-1.webp\"); }\n.ic[data-img=\"clinic-omiya\"]{ background-image:url(\"\/beauty\/wp-content\/uploads\/2026\/07\/\u75c5\u9662\u306e\u30a2\u30a4\u30b3\u30f3\u7d20\u6750-1.webp\"); }\n.ic[data-img=\"clinic-yokohama\"]{ background-image:url(\"\/beauty\/wp-content\/uploads\/2026\/07\/\u75c5\u9662\u306e\u30a2\u30a4\u30b3\u30f3\u7d20\u6750-1.webp\"); }\n.ic[data-img=\"clinic-osaka\"]{ background-image:url(\"\/beauty\/wp-content\/uploads\/2026\/07\/\u75c5\u9662\u306e\u30a2\u30a4\u30b3\u30f3\u7d20\u6750-1.webp\"); }\n.ic[data-img=\"clinic-namba\"]{ background-image:url(\"\/beauty\/wp-content\/uploads\/2026\/07\/\u75c5\u9662\u306e\u30a2\u30a4\u30b3\u30f3\u7d20\u6750-1.webp\"); }\n.ic[data-img=\"clinic-nagoya\"]{ background-image:url(\"\/beauty\/wp-content\/uploads\/2026\/07\/\u75c5\u9662\u306e\u30a2\u30a4\u30b3\u30f3\u7d20\u6750-1.webp\"); }\n.ic[data-img=\"clinic-okayama\"]{ background-image:url(\"\/beauty\/wp-content\/uploads\/2026\/07\/\u75c5\u9662\u306e\u30a2\u30a4\u30b3\u30f3\u7d20\u6750-1.webp\"); }\n.thumb[data-img=\"treatment-photoRF\"]{ background-image:url(\"\/beauty\/wp-content\/uploads\/2026\/05\/other.webp\"); }\n.thumb[data-img=\"treatment-pico\"]{ background-image:url(\"\/beauty\/wp-content\/uploads\/2026\/05\/other.webp\"); }\n.thumb[data-img=\"treatment-3d\"]{ background-image:url(\"\/beauty\/wp-content\/uploads\/2026\/05\/other.webp\"); }\n.thumb[data-img=\"treatment-hifu\"]{ background-image:url(\"\/beauty\/wp-content\/uploads\/2026\/05\/other.webp\"); }\n<\/style>\n\n\n\n<style>\n  :root{\n    --rose:#e85a8a; --rose-deep:#d63e73; --rose-soft:#fbe6ef; --rose-softer:#fdf1f6;\n    --rose-border:#f2c6da; --ink:#544749; --ink-soft:#93878a; --ink-faint:#b9adb0;\n    --bg:#fffdfb; --card:#fff; --field:#f6efe9; --field-border:#ece0d8;\n    --line-green:#06c755; --radius:14px;\n  }\n  *{box-sizing:border-box;margin:0;padding:0}\n  body{\n    font-family:\"Hiragino Kaku Gothic ProN\",\"Hiragino Sans\",\"Yu Gothic\",YuGothic,\"Noto Sans JP\",Meiryo,sans-serif;\n    color:var(--ink);line-height:1.6;-webkit-font-smoothing:antialiased;\n    background:radial-gradient(140% 60% at 50% -10%, #fdeef4 0%, rgba(253,238,244,0) 55%), var(--bg);\n  }\n\n  \/* ===== IMAGE PLACEHOLDERS =====\n     Place an image in the div of the class below.\n     Method A) Specify background-image via CSS etc. (background-size:cover works)\n     Method B) Put an <img style=\"width:100%;height:100%;object-fit:cover\"> inside the div\n     The data-img attribute identifies which image slot it is. *\/\n  .ic,.ic-field,.thumb,.lthumb,.chip-ic,.line-ic{\n    background-color:#f4ece6;background-size:cover;background-position:center;background-repeat:no-repeat;\n  }\n  .ic{width:38px;height:38px;flex:none;background-size:contain;background-color: initial;}\n  .ic-field{width:20px;height:20px;border-radius:6px;flex:none}\n  .thumb{width:120px;min-height:96px;flex:none;align-self:stretch;background-size:contain;background-repeat:no-repeat;background-position:center;}\n  .lthumb{width:88px;height:64px;border-radius:10px;flex:none;background: url(https:\/\/www.hiro-clinic.or.jp\/beauty\/wp-content\/uploads\/2026\/07\/line_icon.webp);background-size: contain;background-repeat: no-repeat;background-position: center;}\n  .chip-ic{width:15px;height:15px;border-radius:4px;display:inline-block;vertical-align:-2px;margin-right:6px}\n  .line-ic{width:22px;height:22px;border-radius:6px;background-color:rgba(255,255,255,.4);background: url(https:\/\/www.hiro-clinic.or.jp\/beauty\/wp-content\/uploads\/2026\/07\/line_icon.webp);\n    background-size: contain;}\n\n  \/* Title *\/\n  .hero{text-align:center;margin-bottom:26px}\n  .hero h1{font-weight:700;letter-spacing:.16em;color:var(--ink)}\n  .hero p{margin-top:12px;font-size:14px;color:var(--ink-soft);letter-spacing:.02em}\n\n  \/* Tabs *\/\n  .tabs{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;margin:22px 0 30px}\n  .tab{\n    border:1px solid var(--field-border);background:var(--card);border-radius:12px;\n    padding:15px 8px;font-size:16px;font-weight:600;color:var(--ink-soft);cursor:pointer;\n    transition:.18s;letter-spacing:.04em;font-family:inherit;\n  }\n  .tab:hover{border-color:var(--rose-border)}\n  .tab.active{background:var(--rose-soft);border-color:var(--rose-border);color:var(--rose-deep);box-shadow:inset 0 0 0 1px var(--rose-border)}\n\n  \/* Step *\/\n  .step{margin-bottom:30px}\n  .step-head{display:flex;align-items:center;justify-content:center;gap:10px;margin-bottom:16px}\n  .step-num{width:26px;height:26px;border-radius:50%;background:var(--rose);color:#fff;font-size:14px;font-weight:700;display:grid;place-items:center;flex:none}\n  .step-title{font-size:18px;font-weight:600;color:var(--ink);letter-spacing:.04em}\n\n  .grid{display:grid;grid-template-columns:1fr 1fr;gap:12px}\n  @media(max-width:560px){.grid{grid-template-columns:1fr}}\n\n  .opt{position:relative;display:flex;align-items:center;gap:14px;border:1px solid var(--field-border);background:var(--card);border-radius:var(--radius);padding:16px 18px;cursor:pointer;transition:.16s;min-height:72px}\n  .opt:hover{border-color:var(--rose-border);background:var(--rose-softer)}\n  .opt .lbl{font-size:16px;font-weight:600;color:var(--ink);letter-spacing:.02em}\n  .opt .radio{margin-left:auto;width:20px;height:20px;border-radius:50%;border:2px solid var(--ink-faint);flex:none;transition:.16s;position:relative}\n  .opt .check{position:absolute;top:-9px;left:-9px;width:26px;height:26px;border-radius:50%;background:var(--rose);display:none;place-items:center;color:#fff;font-size:14px;font-weight:700;box-shadow:0 2px 6px rgba(214,62,115,.35)}\n  .opt .check::after{content:\"\u2713\"}\n  .opt.sel{background:var(--rose-soft);border-color:var(--rose);box-shadow:inset 0 0 0 1px var(--rose)}\n  .opt.sel .lbl{color:var(--rose-deep)}\n  .opt.sel .radio{border-color:var(--rose)}\n  .opt.sel .radio::after{content:\"\";position:absolute;inset:3px;border-radius:50%;background:var(--rose)}\n  .opt.sel .check{display:grid}\n\n  \/* Treatment cards *\/\n  .treatments{display:flex;flex-direction:column;gap:12px}\n  .tcard{display:flex;align-items:stretch;overflow:hidden;border:1px solid var(--field-border);background:var(--card);border-radius:var(--radius);cursor:pointer;transition:.16s}\n  .tcard:hover{border-color:var(--rose-border)}\n  .tcard.sel{border-color:var(--rose);box-shadow:inset 0 0 0 1px var(--rose)}\n  .tcard .body{flex:1;display:flex;align-items:center;gap:12px;padding:14px 18px}\n  .tcard .rank{width:24px;height:24px;border-radius:50%;flex:none;display:grid;place-items:center;font-size:13px;font-weight:700;color:#fff;background:#d9bd86}\n  .tcard.first .rank{background:var(--rose)}\n  .tcard .info{flex:1}\n  .tcard .tname{font-size:18px;font-weight:700;color:var(--ink)}\n  .tcard .tprice{font-size:14px;color:var(--rose-deep);font-weight:600;margin-top:2px}\n  .tcard .ttag{font-size:14px;color:var(--rose-deep);font-weight:600;margin-top:2px}\n  .tcard .tdesc{font-size:13px;color:var(--ink-soft);margin-top:3px}\n  .tcard .radio{width:22px;height:22px;border-radius:50%;border:2px solid var(--ink-faint);flex:none;position:relative;transition:.16s}\n  .tcard.sel .radio{border-color:var(--rose)}\n  .tcard.sel .radio::after{content:\"\";position:absolute;inset:3px;border-radius:50%;background:var(--rose)}\n  @media(max-width:560px){.thumb{width:92px}.tcard .body{padding:12px 14px}}\n\n  \/* Summary *\/\n  .summary{display:flex;flex-wrap:wrap;align-items:center;gap:10px;background:var(--rose-softer);border:1px solid var(--rose-border);border-radius:var(--radius);padding:14px 16px;margin-bottom:34px}\n  .summary .sum-label{font-size:14px;font-weight:600;color:var(--ink);margin-right:2px}\n  .chip{display:inline-flex;align-items:center;background:#fff;border:1px solid var(--rose-border);border-radius:999px;padding:7px 14px;font-size:13px;font-weight:600;color:var(--rose-deep)}\n  .chip.change{margin-left:auto;color:var(--ink-soft);border-color:var(--field-border);cursor:pointer}\n  .chip.change:hover{border-color:var(--rose-border);color:var(--rose-deep)}\n\n  .block-title{text-align:center;font-size:18px;font-weight:700;letter-spacing:.06em;margin:34px 0 16px}\n\n  \/* Form *\/\n  .form{border:1px solid var(--field-border);border-radius:var(--radius);overflow:hidden;background:#fff}\n  .frow{display:flex;flex-wrap:wrap;align-items:center;border-bottom:1px solid var(--field-border);transition:background .15s;position:relative}\n  .frow:last-child{border-bottom:none}\n  .flabel{display:flex;align-items:center;gap:10px;width:170px;flex:none;padding:16px 18px;background:var(--rose-softer);font-size:14px;font-weight:600;color:var(--ink)}\n  .frow input{flex:1;border:none;outline:none;background:transparent;padding:16px 34px 16px 18px;font-size:15px;color:var(--ink);font-family:inherit}\n  .frow input::placeholder{color:var(--ink-faint)}\n  .fsplit{display:flex;flex:1}\n  .finput-wrap{position:relative;flex:1;display:flex}\n  .finput-wrap:first-child{border-right:1px solid var(--field-border)}\n  @media(max-width:560px){.flabel{width:130px;font-size:13px;padding:14px}}\n\n  \/* Field errors \u2014 a warning icon inside each input, with the message as a hover tooltip, so nothing shifts the layout *\/\n  .frow.has-error{background:#fdf4f3}\n  .frow.has-error input{color:#c0392b}\n  .field-warn{position:absolute;right:14px;top:50%;transform:translateY(-50%);width:20px;height:20px;border-radius:50%;background:#e0554f;color:#fff;font-size:12px;font-weight:700;display:none;align-items:center;justify-content:center;cursor:help;flex:none}\n  .field-warn.show{display:flex}\n\n  \/* Preferences *\/\n  .pref{border:1px solid var(--field-border);border-radius:var(--radius);background:#fff;padding:6px 0 18px}\n  .modewrap{display:flex;gap:26px;justify-content:center;padding:16px;background:var(--rose-softer);border-radius:12px;margin:6px 14px 18px}\n  .mode{display:flex;align-items:center;gap:9px;cursor:pointer;font-size:15px;font-weight:600;color:var(--ink-soft)}\n  .mode .dot{width:20px;height:20px;border-radius:50%;border:2px solid var(--ink-faint);position:relative;transition:.16s}\n  .mode.on{color:var(--rose-deep)}\n  .mode.on .dot{border-color:var(--rose)}\n  .mode.on .dot::after{content:\"\";position:absolute;inset:3px;border-radius:50%;background:var(--rose)}\n\n  .cal{padding:0 6px}\n  .dt-block{margin-bottom:10px}\n  .dt-row{display:flex;align-items:stretch;gap:8px}\n  .dt-arrow{flex:0 0 auto;width:32px;border:1px solid var(--field-border);background:#fff;border-radius:10px;display:grid;place-items:center;cursor:pointer;color:var(--ink-soft);font-size:20px;line-height:1;font-family:inherit}\n  .dt-arrow:hover{border-color:var(--rose-border);color:var(--rose)}\n  .dt-arrow:disabled{opacity:.3;cursor:default;border-color:var(--field-border);color:var(--ink-faint)}\n  .dt-scroll{flex:1;min-width:0;display:flex;gap:8px;overflow-x:auto;scroll-behavior:smooth;-webkit-overflow-scrolling:touch;scrollbar-width:none}\n  .dt-scroll::-webkit-scrollbar{display:none}\n  .dt-item{flex:0 0 auto;border:1px solid var(--field-border);background:#fff;border-radius:10px;text-align:center;cursor:pointer;transition:.14s;font-family:inherit}\n  .dt-item:hover{border-color:var(--rose-border);background:var(--rose-softer)}\n  .dt-item.sel{border-color:var(--rose);background:var(--rose-soft);box-shadow:inset 0 0 0 1px var(--rose)}\n  .dt-date{min-width:66px;padding:8px 6px;line-height:1.25}\n  .dt-date .md{font-size:15px;font-weight:700;color:var(--ink)}\n  .dt-date .wd{font-size:11px;color:var(--ink-soft);margin-top:2px}\n  .dt-date.sat .wd{color:#3d7bd6}\n  .dt-date.sun .wd{color:#d64f4f}\n  .dt-date.sel .md{color:var(--rose-deep)}\n  .dt-time{min-width:74px;padding:12px 8px;font-size:14px;font-weight:600;color:var(--ink)}\n  .dt-time.sel{color:var(--rose-deep)}\n  .dt-time.disabled{opacity:.35;cursor:not-allowed;pointer-events:none}\n  .cal-note{font-size:12px;color:var(--ink-soft);margin-top:10px;padding:0 2px}\n  @media(max-width:560px){\n    .cal{padding:0 2px}\n    .dt-arrow{width:28px;font-size:18px}\n    .dt-date{min-width:56px;padding:7px 4px}\n    .dt-date .md{font-size:13px}\n    .dt-time{min-width:62px;font-size:13px;padding:11px 6px}\n  }\n  .note-label{font-size:13px;color:var(--ink-soft);margin:20px 14px 8px}\n  .note-wrap{padding:0 14px;position:relative}\n  .note-wrap textarea{width:100%;border:1px solid var(--field-border);border-radius:10px;padding:13px 14px;font-size:14px;font-family:inherit;color:var(--ink);resize:vertical;min-height:70px;outline:none}\n  .note-wrap textarea::placeholder{color:var(--ink-faint)}\n  .note-count{position:absolute;right:24px;bottom:10px;font-size:12px;color:var(--ink-faint)}\n  .consult-only{display:none;text-align:center;color:var(--ink-soft);font-size:14px;padding:24px 14px}\n\n  \/* LINE *\/\n  .line{display:flex;align-items:center;gap:16px;margin:26px 0 22px;background:linear-gradient(90deg,#eef8ee,#e6f6ea);border:1px solid #cfead4;border-radius:var(--radius);padding:16px 18px}\n  .line .ltxt{flex:1}\n  .line .ltxt b{font-size:16px;color:#2f7a3f}\n  .line .ltxt p{font-size:12.5px;color:#5f7a63;margin-top:3px}\n  .line .lbtn{display:inline-flex;align-items:center;gap:9px;background:var(--line-green);color:#fff;border:none;border-radius:10px;padding:13px 20px;font-size:15px;font-weight:700;cursor:pointer;font-family:inherit;white-space:nowrap;box-shadow:0 4px 12px rgba(6,199,85,.28)}\n  .line .lbtn:hover{filter:brightness(.96)}\n  @media(max-width:560px){.line{flex-wrap:wrap}.line .lbtn{width:100%;justify-content:center}}\n\n  \/* Submit *\/\n  .submit{width:100%;border:none;cursor:pointer;font-family:inherit;background:linear-gradient(90deg,var(--rose),var(--rose-deep));color:#fff;font-size:19px;font-weight:700;letter-spacing:.08em;border-radius:999px;padding:19px;position:relative;box-shadow:0 8px 22px rgba(214,62,115,.32);transition:.16s}\n  .submit:hover{filter:brightness(1.03);transform:translateY(-1px)}\n  .submit .arrow{position:absolute;right:26px;top:50%;transform:translateY(-50%);font-size:24px;line-height:1}\n  .disclaimer{text-align:center;font-size:12.5px;color:var(--ink-soft);margin-top:12px;letter-spacing:.04em}\n\n  \/* Preference\/time error *\/\n  .pref.has-error{border-color:#e0554f;box-shadow:inset 0 0 0 1px #e0554f}\n  .time-error{color:#c0392b;font-size:12.5px;line-height:1.4;padding:0 14px;margin-top:10px;display:none}\n  .pref.has-error .time-error{display:block}\n<\/style>\n\n<div class=\"page\">\n\n  <div class=\"hero\">\n    <h1>\u2726 \u3054\u4e88\u7d04\u30fb\u3054\u76f8\u8ac7 \u2726<\/h1>\n    <p>1\u30da\u30fc\u30b8\u3067\u3001\u5e0c\u671b\u306e\u65bd\u8853\u3068\u9662\u3092\u9078\u3093\u3067\u3054\u4e88\u7d04\u30fb\u3054\u76f8\u8ac7\u3044\u305f\u3060\u3051\u307e\u3059\u3002<\/p>\n  <\/div>\n\n  <div class=\"tabs\">\n    <button class=\"tab active\" data-tab=\"concern\">\u60a9\u307f\u304b\u3089<\/button>\n    <button class=\"tab\" data-tab=\"clinic\">\u9662\u304b\u3089<\/button>\n    <button class=\"tab\" data-tab=\"treatment\">\u65bd\u8853\u304b\u3089<\/button>\n  <\/div>\n\n  <div id=\"panels\"><\/div>\n  <div class=\"summary\" id=\"summary\"><\/div>\n\n  <!-- Basic info -->\n  <div class=\"block-title\">\u57fa\u672c\u60c5\u5831<\/div>\n  <div class=\"form\">\n    <div class=\"frow\" id=\"rowName\"><div class=\"flabel\"><div class=\"ic-field\" data-img=\"icon-name\"><\/div>\u304a\u540d\u524d<\/div><div class=\"fsplit\"><div class=\"finput-wrap\"><input type=\"text\" id=\"fLastName\" placeholder=\"\u4f8b\uff09\u5c71\u7530\" required><span class=\"field-warn\" id=\"lastNameWarn\">!<\/span><\/div><div class=\"finput-wrap\"><input type=\"text\" id=\"fFirstName\" placeholder=\"\u4f8b\uff09\u82b1\u5b50\" required><span class=\"field-warn\" id=\"firstNameWarn\">!<\/span><\/div><\/div><\/div>\n    <div class=\"frow\"><div class=\"flabel\"><div class=\"ic-field\" data-img=\"icon-kana\"><\/div>\u30d5\u30ea\u30ac\u30ca<\/div><div class=\"fsplit\"><input type=\"text\" id=\"fLastNameKana\" placeholder=\"\u4f8b\uff09\u30e4\u30de\u30c0\" required><input type=\"text\" id=\"fFirstNameKana\" placeholder=\"\u4f8b\uff09\u30cf\u30ca\u30b3\" required><\/div><\/div>\n    <div class=\"frow\" id=\"rowTel\"><div class=\"flabel\"><div class=\"ic-field\" data-img=\"icon-tel\"><\/div>\u96fb\u8a71\u756a\u53f7<\/div><input type=\"tel\" id=\"fTel\" inputmode=\"numeric\" maxlength=\"11\" placeholder=\"\u4f8b\uff0909012345678\" required><span class=\"field-warn\" id=\"telWarn\">!<\/span><\/div>\n    <div class=\"frow\" id=\"rowEmail\"><div class=\"flabel\"><div class=\"ic-field\" data-img=\"icon-mail\"><\/div>\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9<\/div><input type=\"email\" id=\"fEmail\" placeholder=\"\u4f8b\uff09example@gmail.com\" title=\"\u6709\u52b9\u306a\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\" required><span class=\"field-warn\" id=\"emailWarn\">!<\/span><\/div>\n  <\/div>\n\n  <!-- Preferences -->\n  <div class=\"block-title\">\u3054\u5e0c\u671b<\/div>\n  <div class=\"pref\" id=\"prefBlock\">\n    <div class=\"modewrap\">\n      <label class=\"mode on\" data-mode=\"reserve\"><span class=\"dot\"><\/span>\u4e88\u7d04\u65e5\u6642\u3092\u9078\u629e<\/label>\n      <label class=\"mode\" data-mode=\"consult\"><span class=\"dot\"><\/span>\u76f8\u8ac7\u306e\u307f<\/label>\n    <\/div>\n    <div id=\"reserveArea\">\n      <div class=\"cal\">\n        <div class=\"dt-block\">\n          <div class=\"dt-row\">\n            <button class=\"dt-arrow\" id=\"datePrev\" aria-label=\"\u524d\u306e\u65e5\u4ed8\">\u2039<\/button>\n            <div class=\"dt-scroll\" id=\"dateScroll\"><\/div>\n            <button class=\"dt-arrow\" id=\"dateNext\" aria-label=\"\u6b21\u306e\u65e5\u4ed8\">\u203a<\/button>\n          <\/div>\n        <\/div>\n        <div class=\"dt-block\">\n          <div class=\"dt-row\">\n            <button class=\"dt-arrow\" id=\"timePrev\" aria-label=\"\u524d\u306e\u6642\u9593\">\u2039<\/button>\n            <div class=\"dt-scroll\" id=\"timeScroll\"><\/div>\n            <button class=\"dt-arrow\" id=\"timeNext\" aria-label=\"\u6b21\u306e\u6642\u9593\">\u203a<\/button>\n          <\/div>\n        <\/div>\n        <p class=\"cal-note\">\u203b\u3054\u5e0c\u671b\u306e\u65e5\u6642\u304c\u57cb\u307e\u3063\u3066\u3044\u308b\u5834\u5408\u3082\u3054\u3056\u3044\u307e\u3059\u3002\u3054\u4e86\u627f\u304f\u3060\u3055\u3044\u3002<\/p>\n        <p class=\"time-error\" id=\"timeError\"><\/p>\n      <\/div>\n    <\/div>\n    <div class=\"consult-only\" id=\"consultArea\">\u65e5\u6642\u6307\u5b9a\u306a\u3057\u3067\u3001\u30ab\u30a6\u30f3\u30bb\u30e9\u30fc\u3088\u308a\u3054\u76f8\u8ac7\u5185\u5bb9\u306b\u5fdc\u3058\u3066\u3054\u9023\u7d61\u3044\u305f\u3057\u307e\u3059\u3002<\/div>\n    <div class=\"note-label\">\u305d\u306e\u4ed6\u3054\u5e0c\u671b\u304c\u3042\u308c\u3070\u304a\u77e5\u3089\u305b\u304f\u3060\u3055\u3044<\/div>\n    <div class=\"note-wrap\">\n      <textarea id=\"note\" maxlength=\"200\" placeholder=\"\u3054\u5e0c\u671b\u3084\u6c17\u306b\u306a\u308b\u70b9\u3092\u3042\u308c\u3070\u3054\u8a18\u5165\u304f\u3060\u3055\u3044\"><\/textarea>\n      <div class=\"note-count\"><span id=\"noteCount\">0<\/span>\/200<\/div>\n    <\/div>\n  <\/div>\n\n  <!-- LINE -->\n  <div class=\"line\">\n    <div class=\"lthumb\" data-img=\"line-thumb\"><\/div>\n    <div class=\"ltxt\">\n      <b>\u8ff7\u3063\u305f\u3089LINE\u76f8\u8ac7<\/b>\n      <p>\u65bd\u8853\u9078\u3073\u3084\u3054\u4e88\u7d04\u306e\u524d\u306bLINE\u3067\u3082\u3054\u76f8\u8ac7\u3044\u305f\u3060\u3051\u307e\u3059\u3002<\/p>\n    <\/div>\n    <button class=\"lbtn\"><div class=\"line-ic\" data-img=\"line-logo\"><\/div>LINE\u3067\u76f8\u8ac7\u3059\u308b<\/button>\n  <\/div>\n\n  <button class=\"submit\" id=\"submit\">\u78ba\u8a8d\u753b\u9762\u3078<span class=\"arrow\">\u203a<\/span><\/button>\n  <p class=\"disclaimer\">\u203b\u4e88\u7d04\u306f\u307e\u3060\u78ba\u5b9a\u3044\u305f\u3057\u307e\u305b\u3093<\/p>\n<\/div>\n\n\n\n<script>\n\/* ---------- DATA ---------- *\/\nconst concerns = [\n  {id:'shimi', label:'\u30b7\u30df\u30fb\u304f\u3059\u307f'},\n  {id:'tarumi', label:'\u305f\u308b\u307f\u30fb\u5c0f\u3058\u308f'},\n  {id:'akara', label:'\u8d64\u3089\u9854'},\n  {id:'keana', label:'\u6bdb\u7a74\u30fb\u808c\u8cea'},\n  {id:'bihaku', label:'\u7f8e\u767d\u30fb\u30a8\u30a4\u30b8\u30f3\u30b0\u30b1\u30a2'},\n  {id:'wakaranai', label:'\u81ea\u5206\u306b\u5408\u3046\u65bd\u8853\u304c\u5206\u304b\u3089\u306a\u3044'},\n];\n\/\/ officeId = external reservation system's clinic (office) ID\nconst clinics = [\n  {id:'ikebukuro', label:'\u6c60\u888b\u99c5\u524d\u9662', officeId:155},\n  {id:'kawaguchi', label:'\u5ddd\u53e3\u9662', officeId:141},\n  {id:'hakata', label:'\u535a\u591a\u9662', officeId:14},\n];\n\/\/ Each treatment holds its \"matching concerns\" and \"available clinics\" \u2192 all filtering is derived from this.\n\/\/ subDept = external system's sub-department ID for this treatment, keyed by clinic id.\n\/\/ duration = appointment length in minutes, per Inoue Yuta's Redmine note.\nconst treatments = [\n  {id:'photoRF', name:'\u30d5\u30a9\u30c8RF', price:'\u521d\u56de 7,700\u5186\u301c', desc:'\u5bfe\u5fdc\uff1a\u30b7\u30df\u30fb\u304f\u3059\u307f\u30fb\u8d64\u3089\u9854\u30fb\u6bdb\u7a74',\n   concerns:['shimi','akara','keana'], clinics:['ikebukuro','kawaguchi','hakata'],\n   subDept:{ikebukuro:10, kawaguchi:41, hakata:68}, duration:45},\n  {id:'pico', name:'\u30d4\u30b3\u30ec\u30fc\u30b6\u30fc', tag:'\u30b7\u30df\u30fb\u304f\u3059\u307f\u6539\u5584\u306b', desc:'\u5bfe\u5fdc\u9662\uff1a\u6c60\u888b\u99c5\u524d\u9662',\n   concerns:['shimi','bihaku'], clinics:['ikebukuro'],\n   subDept:{ikebukuro:66}, duration:30},\n  {id:'3d', name:'3D\u808c\u8a3a\u65ad', tag:'\u81ea\u5206\u306b\u5408\u3046\u65bd\u8853\u304c\u5206\u304b\u3089\u306a\u3044\u65b9\u3078', desc:'\u5bfe\u5fdc\uff1a\u808c\u8a3a\u65ad\u30fb\u65bd\u8853\u63d0\u6848',\n   \/\/ TODO: 3D Skin Diagnosis sub-department IDs aren't finalized by the design team yet.\n   concerns:['wakaranai','tarumi'], clinics:['ikebukuro','kawaguchi','hakata'],\n   subDept:{}, duration:5},\n  {id:'hifu', name:'\u30e1\u30c7\u30a3\u30ab\u30eb\u30cf\u30a4\u30d5', tag:'\u305f\u308b\u307f\u30fb\u5f15\u304d\u7de0\u3081\u306b', desc:'\u5bfe\u5fdc\u9662\uff1a\u6c60\u888b\u99c5\u524d\u9662\u30fb\u5ddd\u53e3\u9662\u30fb\u535a\u591a\u9662',\n   concerns:['tarumi'], clinics:['ikebukuro','kawaguchi','hakata'],\n   subDept:{ikebukuro:56, kawaguchi:57, hakata:62}, duration:75},\n];\n\nconst byId  = (list,id)=>list.find(x=>x.id===id);\nconst labelOf = (list,id)=>{const o=byId(list,id);return o?o.label:'';};\nconst treatmentName = id=>{const t=byId(treatments,id);return t?t.name:'';};\nconst officeIdOf = clinicId=>{const c=byId(clinics,clinicId);return c?c.officeId:null;};\nconst subDepartmentIdOf = (treatmentId,clinicId)=>{\n  const t=byId(treatments,treatmentId);\n  return (t && t.subDept && t.subDept[clinicId]!=null) ? t.subDept[clinicId] : null;\n};\nconst durationOf = treatmentId=>{const t=byId(treatments,treatmentId);return t?t.duration:15;};\n\n\/\/ Filtering logic\nfunction clinicsForConcern(cid){\n  const ids = new Set();\n  treatments.filter(t=>t.concerns.includes(cid)).forEach(t=>t.clinics.forEach(c=>ids.add(c)));\n  return clinics.filter(c=>ids.has(c.id));\n}\nfunction treatmentsForClinic(clid){ return treatments.filter(t=>t.clinics.includes(clid)); }\nfunction clinicsForTreatment(tid){ const t=byId(treatments,tid); return clinics.filter(c=>t.clinics.includes(c.id)); }\n\n\/* ---------- STATE ---------- *\/\nconst state = { tab:'concern', concern:'shimi', clinic:'ikebukuro', treatment:'photoRF', mode:'reserve', date:'7\/9', time:'10:00' };\n\n\/\/ Clamp the dependent selection back into a valid range to match the tab's primary selection\nfunction clamp(){\n  if(state.tab==='concern'){\n    const list=clinicsForConcern(state.concern);\n    if(!list.some(c=>c.id===state.clinic)) state.clinic=list[0].id;\n  }else if(state.tab==='clinic'){\n    const list=treatmentsForClinic(state.clinic);\n    if(!list.some(t=>t.id===state.treatment)) state.treatment=list[0].id;\n  }else{\n    const list=clinicsForTreatment(state.treatment);\n    if(!list.some(c=>c.id===state.clinic)) state.clinic=list[0].id;\n  }\n}\n\n\/* ---------- RENDER ---------- *\/\nconst $ = s=>document.querySelector(s);\n\/\/ Reads WordPress's own REST API discovery link so this works under any subdirectory install (e.g. \/beauty\/) without hardcoding it.\nconst restBase = ()=>{\n  const link = document.querySelector('link[rel=\"https:\/\/api.w.org\/\"]');\n  return link ? link.href.replace(\/\\\/$\/, '') : '\/wp-json';\n};\n\nfunction section(num, title, inner){\n  return `<div class=\"step\"><div class=\"step-head\"><span class=\"step-num\">${num}<\/span><span class=\"step-title\">${title}<\/span><\/div>${inner}<\/div>`;\n}\nfunction optionSection(num, title, list, kind, selId, imgKey){\n  const opts = list.map(o=>`\n    <div class=\"opt ${o.id===selId?'sel':''}\" data-kind=\"${kind}\" data-id=\"${o.id}\">\n      <span class=\"check\"><\/span>\n      <div class=\"ic\" data-img=\"${imgKey}-${o.id}\"><\/div>\n      <span class=\"lbl\">${o.label}<\/span>\n      <span class=\"radio\"><\/span>\n    <\/div>`).join('');\n  return section(num, title, `<div class=\"grid\">${opts}<\/div>`);\n}\nfunction treatmentSection(num, title, list){\n  const cards = list.map((t,i)=>`\n    <div class=\"tcard ${t.id===state.treatment?'sel':''} ${i===0?'first':''}\" data-kind=\"treatment\" data-id=\"${t.id}\">\n      <div class=\"thumb\" data-img=\"treatment-${t.id}\"><\/div>\n      <div class=\"body\">\n        <span class=\"rank\">${i+1}<\/span>\n        <div class=\"info\">\n          <div class=\"tname\">${t.name}<\/div>\n          ${t.price?`<div class=\"tprice\">${t.price}<\/div>`:''}\n          ${t.tag?`<div class=\"ttag\">${t.tag}<\/div>`:''}\n          <div class=\"tdesc\">${t.desc}<\/div>\n        <\/div>\n        <span class=\"radio\"><\/span>\n      <\/div>\n    <\/div>`).join('');\n  return section(num, title, `<div class=\"treatments\">${cards}<\/div>`);\n}\n\nfunction renderPanels(){\n  clamp();\n  let html='';\n  if(state.tab==='concern'){\n    html += optionSection(1,'\u304a\u60a9\u307f\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044', concerns, 'concern', state.concern, 'concern');\n    html += optionSection(2,'\u5bfe\u5fdc\u3059\u308b\u9662\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044', clinicsForConcern(state.concern), 'clinic', state.clinic, 'clinic');\n  }else if(state.tab==='clinic'){\n    html += optionSection(1,'\u9662\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044', clinics, 'clinic', state.clinic, 'clinic');\n    html += treatmentSection(2, `${labelOf(clinics,state.clinic)}\u3067\u53d7\u3051\u3089\u308c\u308b\u65bd\u8853`, treatmentsForClinic(state.clinic));\n  }else{\n    html += treatmentSection(1, '\u65bd\u8853\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044', treatments);\n    html += optionSection(2, '\u65bd\u8853\u53ef\u80fd\u306a\u9662\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044', clinicsForTreatment(state.treatment), 'clinic', state.clinic, 'clinic');\n  }\n  $('#panels').innerHTML = html;\n  document.querySelectorAll('#panels [data-kind]').forEach(el=>{\n    el.addEventListener('click',()=>{\n      const clinicChanged = el.dataset.kind==='clinic' && el.dataset.id!==state.clinic;\n      state[el.dataset.kind]=el.dataset.id;\n      renderPanels(); renderSummary();\n      if(clinicChanged) refreshTimeSlots();\n    });\n  });\n}\n\n\/\/ Returns the \"pair\" for the current tab = the 2 selected values\nfunction currentPair(){\n  if(state.tab==='concern') return [['\u60a9\u307f',labelOf(concerns,state.concern)],['\u9662',labelOf(clinics,state.clinic)]];\n  if(state.tab==='clinic')  return [['\u9662',labelOf(clinics,state.clinic)],['\u65bd\u8853',treatmentName(state.treatment)]];\n  return [['\u65bd\u8853',treatmentName(state.treatment)],['\u9662',labelOf(clinics,state.clinic)]];\n}\nfunction renderSummary(){\n  const chips = currentPair().map(([k,v])=>\n    `<span class=\"chip\"><span class=\"chip-ic\" data-img=\"chip-${k}\"><\/span>${k}\uff1a${v}<\/span>`).join('');\n  $('#summary').innerHTML =\n    `<span class=\"sum-label\">\u9078\u629e\u5185\u5bb9<\/span>${chips}<span class=\"chip change\" id=\"scrollTop\"><span class=\"chip-ic\" data-img=\"chip-change\"><\/span>\u5909\u66f4\u30fb\u8ffd\u52a0\u5909\u66f4<\/span>`;\n  $('#scrollTop').addEventListener('click',()=>window.scrollTo({top:0,behavior:'smooth'}));\n}\n\n\/* ---------- TABS ---------- *\/\ndocument.querySelectorAll('.tab').forEach(t=>{\n  t.addEventListener('click',()=>{\n    document.querySelectorAll('.tab').forEach(x=>x.classList.remove('active'));\n    t.classList.add('active');\n    const prevClinic = state.clinic;\n    state.tab=t.dataset.tab;\n    renderPanels(); renderSummary();\n    if(state.clinic!==prevClinic) refreshTimeSlots();\n  });\n});\n\n\/* ---------- PREFERENCES ---------- *\/\nconst WEEK=['\u65e5','\u6708','\u706b','\u6c34','\u6728','\u91d1','\u571f'];\nconst DATES=[];\n(function(){                       \/\/ Generate the available reservation dates (30 days starting from today)\n  const now=new Date();\n  const base=new Date(now.getFullYear(), now.getMonth(), now.getDate());\n  for(let i=0;i<30;i++){\n    const d=new Date(base); d.setDate(base.getDate()+i);\n    const iso = d.getFullYear()+'-'+String(d.getMonth()+1).padStart(2,'0')+'-'+String(d.getDate()).padStart(2,'0');\n    DATES.push({key:(d.getMonth()+1)+'\/'+d.getDate(), iso, wd:WEEK[d.getDay()], dow:d.getDay()});\n  }\n  state.date = DATES[0].key;\n})();\nconst dateLabel = key=>{const d=DATES.find(x=>x.key===key);return d?`${key}\uff08${d.wd}\uff09`:key;};\n\/\/ Y-m-d format required by the external reservation API\nconst dateIso = key=>{const d=DATES.find(x=>x.key===key);return d?d.iso:key;};\n\/\/ Computes the appointment's end time from its start time + treatment duration, for display purposes.\nfunction endTimeOf(startTime, durationMinutes){\n  const [h,m] = startTime.split(':').map(Number);\n  const total = h*60 + m + durationMinutes;\n  const eh = Math.floor(total\/60)%24, em = total%60;\n  return String(eh).padStart(2,'0') + ':' + String(em).padStart(2,'0');\n}\n\/\/ TODO: the external availability API always returns period_start = (requested date + 1 day) \u2014\n\/\/ e.g. requesting 2026-07-17 comes back with data for 2026-07-18, never for the day actually asked.\n\/\/ This should be reported\/fixed upstream. Until then, request one day earlier to compensate.\nfunction shiftIsoDate(isoStr, days){\n  const [y,mo,d] = isoStr.split('-').map(Number);\n  const dt = new Date(y, mo-1, d);\n  dt.setDate(dt.getDate()+days);\n  return dt.getFullYear()+'-'+String(dt.getMonth()+1).padStart(2,'0')+'-'+String(dt.getDate()).padStart(2,'0');\n}\n\nconst dateScroll=$('#dateScroll'), timeScroll=$('#timeScroll');\nlet calUpdaters=[];\nlet currentSlotsData=null;\n\nfunction buildDateCal(){\n  dateScroll.innerHTML = DATES.map(d=>{\n    const cls = d.dow===6?'sat':d.dow===0?'sun':'';\n    const sel = state.date===d.key?'sel':'';\n    return `<div class=\"dt-item dt-date ${cls} ${sel}\" data-date=\"${d.key}\"><div class=\"md\">${d.key}<\/div><div class=\"wd\">${d.wd}<\/div><\/div>`;\n  }).join('');\n\n  dateScroll.querySelectorAll('.dt-date').forEach(el=>el.addEventListener('click',()=>{\n    dateScroll.querySelectorAll('.sel').forEach(x=>x.classList.remove('sel'));\n    el.classList.add('sel'); state.date=el.dataset.date;\n    refreshTimeSlots();\n  }));\n}\n\n\/\/ Fetches this clinic's real-time availability (one call covers a multi-week period) via our WP proxy endpoint\nasync function fetchAvailableSlots(clinicKey, dateIsoStr){\n  try{\n    const res = await fetch(restBase() + '\/hiro\/v1\/available-slots', {\n      method:'POST',\n      headers:{'Content-Type':'application\/json'},\n      body: JSON.stringify({ office_id: officeIdOf(clinicKey), date: dateIsoStr })\n    });\n    const body = await res.json().catch(()=>null);\n    if(!res.ok || !body || !body.success) return null;\n    return body.data;\n  }catch(e){\n    return null;\n  }\n}\n\nfunction timeslotsForDate(data, dateIsoStr){\n  if(!data || !Array.isArray(data.days)) return null;\n  const day = data.days.find(d=>d.date===dateIsoStr);\n  return day ? day.timeslots : [];\n}\n\n\/\/ isToday: when true, slots at or before the current time are treated as unavailable too (can't book the past).\nfunction isSlotUnavailable(s, isToday){\n  if(s.is_closed || s.is_break || s.available_slots<=0) return true;\n  if(isToday){\n    const now = new Date();\n    const [sh,sm] = s.time.split(':').map(Number);\n    if(sh*60+sm <= now.getHours()*60+now.getMinutes()) return true;\n  }\n  return false;\n}\n\nfunction renderTimeSlots(timeslots){\n  if(!timeslots){\n    timeScroll.innerHTML = '<p class=\"cal-note\">\u73fe\u5728\u7a7a\u304d\u72b6\u6cc1\u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093\u3002\u3057\u3070\u3089\u304f\u3057\u3066\u304b\u3089\u518d\u5ea6\u304a\u8a66\u3057\u304f\u3060\u3055\u3044\u3002<\/p>';\n    return;\n  }\n  if(timeslots.length===0){\n    timeScroll.innerHTML = '<p class=\"cal-note\">\u3053\u306e\u65e5\u306e\u7a7a\u304d\u67a0\u306f\u3042\u308a\u307e\u305b\u3093\u3002<\/p>';\n    return;\n  }\n\n  const isToday = state.date===DATES[0].key;\n  const availableTimes = timeslots.filter(s=>!isSlotUnavailable(s,isToday));\n\n  \/\/ Keep the current selection if it's still valid for this date; otherwise auto-select the earliest available time.\n  if(!state.time || !availableTimes.some(s=>s.time===state.time)){\n    state.time = availableTimes.length ? availableTimes[0].time : '';\n  }\n\n  timeScroll.innerHTML = timeslots.map(s=>{\n    const unavailable = isSlotUnavailable(s,isToday);\n    const sel = (!unavailable && state.time===s.time) ? 'sel' : '';\n    return `<div class=\"dt-item dt-time ${sel} ${unavailable?'disabled':''}\" data-time=\"${s.time}\">${s.time}<\/div>`;\n  }).join('');\n\n  \/\/ Scroll the auto-selected (or restored) time into view, since it may fall outside the carousel's initial viewport.\n  const selEl = timeScroll.querySelector('.dt-time.sel');\n  if(selEl) selEl.scrollIntoView({behavior:'auto', inline:'center', block:'nearest'});\n\n  timeScroll.querySelectorAll('.dt-time:not(.disabled)').forEach(el=>el.addEventListener('click',()=>{\n    timeScroll.querySelectorAll('.sel').forEach(x=>x.classList.remove('sel'));\n    el.classList.add('sel'); state.time=el.dataset.time;\n    prefBlock.classList.remove('has-error');\n    $('#timeError').textContent='';\n  }));\n}\n\nasync function refreshTimeSlots(){\n  if(state.mode!=='reserve') return;\n  const iso = dateIso(state.date);\n  \/\/ See shiftIsoDate's TODO: compensate for the API's off-by-one before requesting, then match on the real date.\n  currentSlotsData = await fetchAvailableSlots(state.clinic, shiftIsoDate(iso, -1));\n  renderTimeSlots(timeslotsForDate(currentSlotsData, iso));\n  calUpdaters[1] && calUpdaters[1]();\n}\n\n\/\/ Controls the horizontal carousel's arrows (disabled at both ends, slides by the visible width)\nfunction wireArrows(scroll, prev, next){\n  const upd=()=>{\n    prev.disabled = scroll.scrollLeft<=1;\n    next.disabled = scroll.scrollLeft+scroll.clientWidth >= scroll.scrollWidth-1;\n  };\n  const amt=()=>Math.max(140, Math.round(scroll.clientWidth*0.8));\n  prev.addEventListener('click',()=>scroll.scrollBy({left:-amt(), behavior:'smooth'}));\n  next.addEventListener('click',()=>scroll.scrollBy({left: amt(), behavior:'smooth'}));\n  scroll.addEventListener('scroll',upd);\n  window.addEventListener('resize',upd);\n  setTimeout(upd,60);\n  return upd;\n}\n\nfunction renderCal(){\n  buildDateCal();\n  calUpdaters=[\n    wireArrows(dateScroll, $('#datePrev'), $('#dateNext')),\n    wireArrows(timeScroll, $('#timePrev'), $('#timeNext'))\n  ];\n  refreshTimeSlots();\n}\ndocument.querySelectorAll('.mode').forEach(m=>{\n  m.addEventListener('click',()=>{\n    document.querySelectorAll('.mode').forEach(x=>x.classList.remove('on'));\n    m.classList.add('on'); state.mode=m.dataset.mode;\n    $('#reserveArea').style.display = state.mode==='reserve'?'block':'none';\n    $('#consultArea').style.display = state.mode==='consult'?'block':'none';\n    if(state.mode==='reserve'){ calUpdaters.forEach(u=>u&&u()); refreshTimeSlots(); }\n  });\n});\nconst note=$('#note');\nnote.addEventListener('input',()=>$('#noteCount').textContent=note.value.length);\n\nconst telInput=$('#fTel');\ntelInput.addEventListener('input',()=>{ telInput.value = telInput.value.replace(\/\\D\/g,'').slice(0,11); });\n\n\/* ---------- INLINE VALIDATION ---------- *\/\nconst prefBlock = $('#prefBlock');\nfunction clearFieldErrors(){\n  document.querySelectorAll('.frow.has-error').forEach(el=>el.classList.remove('has-error'));\n  document.querySelectorAll('.field-warn').forEach(el=>{ el.title=''; el.classList.remove('show'); });\n  prefBlock.classList.remove('has-error');\n  $('#timeError').textContent='';\n}\nfunction setFieldError(rowEl, warnEl, message){\n  rowEl.classList.add('has-error');\n  warnEl.title = message;\n  warnEl.classList.add('show');\n}\nfunction clearWarn(rowEl, warnEl, otherWarnEl){\n  return ()=>{\n    warnEl.title = '';\n    warnEl.classList.remove('show');\n    if(!otherWarnEl || !otherWarnEl.classList.contains('show')) rowEl.classList.remove('has-error');\n  };\n}\n$('#fLastName').addEventListener('input', clearWarn($('#rowName'), $('#lastNameWarn'), $('#firstNameWarn')));\n$('#fFirstName').addEventListener('input', clearWarn($('#rowName'), $('#firstNameWarn'), $('#lastNameWarn')));\n$('#fTel').addEventListener('input', clearWarn($('#rowTel'), $('#telWarn')));\n$('#fEmail').addEventListener('input', clearWarn($('#rowEmail'), $('#emailWarn')));\n\n\/* ---------- SUBMIT ---------- *\/\nfunction validateForm(){\n  clearFieldErrors();\n  let firstInvalid = null;\n\n  const lastName = $('#fLastName').value.trim();\n  const firstName = $('#fFirstName').value.trim();\n  const tel  = $('#fTel').value.trim();\n  const email= $('#fEmail').value.trim();\n\n  if(!lastName){\n    setFieldError($('#rowName'), $('#lastNameWarn'), '\u59d3\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002');\n    firstInvalid = firstInvalid || $('#fLastName');\n  }\n  if(!firstName){\n    setFieldError($('#rowName'), $('#firstNameWarn'), '\u540d\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002');\n    firstInvalid = firstInvalid || $('#fFirstName');\n  }\n  if(!tel){\n    setFieldError($('#rowTel'), $('#telWarn'), '\u96fb\u8a71\u756a\u53f7\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002');\n    firstInvalid = firstInvalid || $('#fTel');\n  }else if(!\/^0\\d{9,10}$\/.test(tel)){\n    setFieldError($('#rowTel'), $('#telWarn'), '\u96fb\u8a71\u756a\u53f7\u306f\u30cf\u30a4\u30d5\u30f3\u306a\u3057\u306e\u534a\u89d2\u6570\u5b5710\u301c11\u6841\u3067\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002');\n    firstInvalid = firstInvalid || $('#fTel');\n  }\n  if(!email){\n    setFieldError($('#rowEmail'), $('#emailWarn'), '\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002');\n    firstInvalid = firstInvalid || $('#fEmail');\n  }\n  if(state.mode==='reserve' && !state.time){\n    prefBlock.classList.add('has-error');\n    $('#timeError').textContent = '\u3054\u5e0c\u671b\u306e\u6642\u9593\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044\u3002';\n    firstInvalid = firstInvalid || prefBlock;\n  }\n\n  if(firstInvalid){\n    firstInvalid.scrollIntoView({behavior:'smooth', block:'center'});\n    if(typeof firstInvalid.focus === 'function') firstInvalid.focus({preventScroll:true});\n    return false;\n  }\n  return true;\n}\nfunction buildRows(){\n  const rows = [];\n  const lastName = $('#fLastName').value.trim();\n  const firstName = $('#fFirstName').value.trim();\n  rows.push(['\u304a\u540d\u524d', `${lastName} ${firstName} \u69d8`]);\n  const lastKana = $('#fLastNameKana').value.trim();\n  const firstKana = $('#fFirstNameKana').value.trim();\n  if(lastKana || firstKana) rows.push(['\u30d5\u30ea\u30ac\u30ca', `${lastKana} ${firstKana}`]);\n  rows.push(['\u96fb\u8a71\u756a\u53f7', $('#fTel').value.trim()]);\n  rows.push(['\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9', $('#fEmail').value.trim()]);\n  currentPair().forEach(p=>rows.push(p));\n  \/\/ Shows the exact appointment window (start\u2013end), not just the hour the user picked in the coarser picker.\n  const schedule = state.mode==='reserve'\n    ? `${dateLabel(state.date)} ${state.time}\u301c${endTimeOf(state.time, durationOf(state.treatment))}`\n    : '\u76f8\u8ac7\u306e\u307f';\n  rows.push(['\u3054\u5e0c\u671b\u65e5\u6642', schedule]);\n  const noteVal = note.value.trim();\n  if(noteVal) rows.push(['\u3054\u8981\u671b', noteVal]);\n  return rows;\n}\n\/\/ Raw data for API submission (ids, etc.), not display labels\nfunction buildFields(){\n  return {\n    last_name: $('#fLastName').value.trim(),\n    first_name: $('#fFirstName').value.trim(),\n    last_name_kana: $('#fLastNameKana').value.trim(),\n    first_name_kana: $('#fFirstNameKana').value.trim(),\n    tel: $('#fTel').value.trim(),\n    email: $('#fEmail').value.trim(),\n    tab: state.tab,\n    concern: state.concern,\n    clinic: state.clinic,\n    treatment: state.treatment,\n    office_id: officeIdOf(state.clinic),\n    subdepartment_id: subDepartmentIdOf(state.treatment, state.clinic),\n    duration: durationOf(state.treatment),\n    mode: state.mode,\n    date: state.mode==='reserve' ? dateIso(state.date) : null,\n    time: state.mode==='reserve' ? state.time : null,\n    note: note.value.trim()\n  };\n}\n$('#submit').addEventListener('click',()=>{\n  if(!validateForm()) return;\n  sessionStorage.setItem('reservationConfirm', JSON.stringify({ rows: buildRows(), fields: buildFields() }));\n  window.location.href = '\/beauty\/reservation-confirmation\/';\n});\n\n\/* ---------- INIT ---------- *\/\nrenderPanels(); renderSummary(); renderCal();\n<\/script>\n","protected":false},"excerpt":{"rendered":"\u2726 \u3054\u4e88\u7d04\u30fb\u3054\u76f8\u8ac7 \u2726 1\u30da\u30fc\u30b8\u3067\u3001\u5e0c\u671b\u306e\u65bd\u8853\u3068\u9662\u3092\u9078\u3093\u3067\u3054\u4e88\u7d04\u30fb\u3054\u76f8\u8ac7\u3044\u305f\u3060\u3051\u307e\u3059\u3002 \u60a9\u307f\u304b\u3089 \u9662\u304b\u3089 \u65bd\u8853\u304b\u3089 \u57fa\u672c\u60c5\u5831 \u304a\u540d\u524d ! ! \u30d5\u30ea\u30ac\u30ca \u96fb\u8a71\u756a\u53f7 ! \u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9 ! \u3054\u5e0c\u671b \u4e88\u7d04\u65e5\u6642\u3092\u9078\u629e \u76f8\u8ac7\u306e\u307f  [&hellip;]","protected":false},"author":68,"featured_media":0,"parent":0,"menu_order":5,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_acf_changed":false,"footnotes":""},"class_list":["post-28846","page","type-page","status-publish","hentry"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.hiro-clinic.or.jp\/beauty\/wp-json\/wp\/v2\/pages\/28846","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.hiro-clinic.or.jp\/beauty\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.hiro-clinic.or.jp\/beauty\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.hiro-clinic.or.jp\/beauty\/wp-json\/wp\/v2\/users\/68"}],"replies":[{"embeddable":true,"href":"https:\/\/www.hiro-clinic.or.jp\/beauty\/wp-json\/wp\/v2\/comments?post=28846"}],"version-history":[{"count":38,"href":"https:\/\/www.hiro-clinic.or.jp\/beauty\/wp-json\/wp\/v2\/pages\/28846\/revisions"}],"predecessor-version":[{"id":29455,"href":"https:\/\/www.hiro-clinic.or.jp\/beauty\/wp-json\/wp\/v2\/pages\/28846\/revisions\/29455"}],"wp:attachment":[{"href":"https:\/\/www.hiro-clinic.or.jp\/beauty\/wp-json\/wp\/v2\/media?parent=28846"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}