// sections.jsx — All page sections for Repos top page.
// Components are made global at the end of this file so app.jsx can use them.

// ────────────────────────────────────────────────────────────
// Top nav (sticky)
// ────────────────────────────────────────────────────────────
function Nav() {
  const [open, setOpen] = React.useState(false);
  const links = [
  ["#concept", "コンセプト"],
  ["#first", "はじめての方へ"],
  ["#service", "サービス"],
  ["#shop", "ホームケア"],
  ["#training", "養成講座"],
  ["#voice", "お客様の声"],
  ["#availability", "空席案内"],
  ["#access", "アクセス"]];

  // Drawer menu mirrors the footer (Menu / Shop / Reserve)
  const drawerGroups = [
  ["Menu", [
  ["#service-shaving", "シェービング"],
  ["#service-facial", "フェイシャル"],
  ["#service-headspa", "ヘッドスパ"],
  ["#service-body", "ボディエステ"],
  ["#service-bridal", "ブライダル"]]],
  ["Shop", [
  ["#shop", "ホームケア商品"],
  ["#wellness", "機能性下着"],
  ["#training", "バザルト養成講座"]]],
  ["Reserve", [
  ["#availability", "空席案内"],
  ["#campaign", "キャンペーン"],
  ["#access", "アクセス"]]]];

  React.useEffect(() => {
    document.body.style.overflow = open ? "hidden" : "";
    return () => {document.body.style.overflow = "";};
  }, [open]);

  return (
    <React.Fragment>
    <header className="nav">
      <div className="nav-inner">
        <a href="#top" className="brand" onClick={() => setOpen(false)}>
          Repos
          <small>Shaving &amp; Esthetic Salon</small>
        </a>
        <nav className="nav-desktop">
          <ul className="nav-links">
            {links.map(([h, t]) =>
            <li key={h}><a href={h}>{t}</a></li>
            )}
          </ul>
        </nav>
        <a className="nav-cta" href={window.LINE_RESERVE_URL} target="_blank" rel="noopener noreferrer">
          <LineIcon />
          LINEで予約
        </a>
        <button
          className={`nav-toggle ${open ? "is-open" : ""}`}
          aria-label="メニュー"
          aria-expanded={open}
          onClick={() => setOpen(!open)}>
          <span></span><span></span><span></span>
        </button>
      </div>
    </header>
      <div
        className={`nav-scrim ${open ? "is-open" : ""}`}
        onClick={() => setOpen(false)}>
      </div>
      <nav className={`nav-drawer ${open ? "is-open" : ""}`}>
        <div className="nav-drawer-groups">
          {drawerGroups.map(([heading, items]) =>
          <div className="nav-drawer-group" key={heading}>
            <h5>{heading}</h5>
            <ul>
              {items.map(([h, t], i) =>
              <li key={h + i}>
                  <a
                  href={h}
                  onClick={(e) => {
                    setOpen(false);
                    if (h.indexOf("#service-") === 0) {
                      // The Services accordion re-flows the whole menu
                      // (one panel collapses while another expands), so its
                      // final position isn't known at click time. Letting
                      // the browser do its own native fragment-jump means it
                      // can (and does) re-scroll to the stale pre-collapse
                      // position once it finally locates the target element
                      // — arriving AFTER our own JS has already corrected
                      // the scroll, silently undoing it. Drive the jump
                      // entirely ourselves instead: update the URL without
                      // the native jump, then let Services' own hashchange
                      // handler do the (correct, re-checked) scroll.
                      e.preventDefault();
                      if (window.location.hash !== h) {
                        history.pushState(null, "", h);
                      }
                      window.dispatchEvent(new Event("hashchange"));
                    }
                  }}>

                    {t}
                  </a>
                </li>
              )}
            </ul>
          </div>
          )}
        </div>
        <a
          className="nav-drawer-cta"
          href={window.LINE_RESERVE_URL}
          target="_blank"
          rel="noopener noreferrer"
          onClick={() => setOpen(false)}>
          <LineIcon />
          LINEで予約
        </a>
        <p className="nav-drawer-note">
          お一人おひとりのご希望やお肌の状態をしっかり確認するため、公式LINEでのやり取りを通して予約のお受けを推奨しています。ご相談・ご質問お気軽にどうぞ。
        </p>
      </nav>
    </React.Fragment>);
}

function LineIcon({ size = 16, color = "#fff" }) {
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill={color} aria-hidden="true" style={{ flex: "0 0 auto" }}>
      <path d="M12 2C6.48 2 2 5.85 2 10.6c0 4.27 3.57 7.84 8.4 8.5.33.07.77.21.88.49.1.25.06.65.03.91l-.14.86c-.04.25-.2.99.87.54 1.07-.45 5.78-3.4 7.88-5.83C21.36 14.31 22 12.55 22 10.6 22 5.85 17.52 2 12 2z" />
    </svg>);

}

// ────────────────────────────────────────────────────────────
// Hero
// ────────────────────────────────────────────────────────────
function Hero() {
  return (
    <section className="hero" id="top">
      <Placeholder id="photo-hero" className="hero-bg" label="HERO / 店内・施術カット" />
      <div className="hero-scrim"></div>
      <div className="wrap hero-content">
        <div className="hero-eyebrow-row">
          <span className="line"></span>
          <span className="eyebrow">Total Care Salon for Skin &amp; Scalp</span>
        </div>
        <h1>
          肌と頭皮の<br />
          両方を<span className="em">ととのえる</span><br />
          女性のための<span style={{ whiteSpace: "nowrap" }}>ケア時間</span>
        </h1>
        <p className="hero-sub">
          シェービングを軸に、頭皮ケア・バザルトストーン・ホームケアまで。肌悩みのあるあなたが、迷わず安心して相談できる場所へ。
        </p>
        <div className="btn-row">
          <a href={window.LINE_RESERVE_URL} target="_blank" rel="noopener noreferrer" className="btn btn-line">
            <LineIcon size={16} />
            LINEで予約・相談する
          </a>
          <a href="#first" className="btn btn-ghost btn-on-photo">
            はじめての方へ <span className="arrow"></span>
          </a>
        </div>
        <dl className="hero-meta">
          <div>
            <dt>OPEN</dt>
            <dd>水〜金 9:30–17:30 ／ 土日 9:00–17:00</dd>
          </div>
          <div>
            <dt>CLOSED</dt>
            <dd>月・火（第３日曜）</dd>
          </div>
          <div>
            <dt>RESERVATION</dt>
            <dd>LINE 24h 受付</dd>
          </div>
        </dl>
        <a href="#availability" className="hero-avail-link">
          <span className="hero-avail-dot"></span>
          空席案内はこちら
          <span className="arrow"></span>
        </a>
      </div>
    </section>);
}

// ────────────────────────────────────────────────────────────
// Concept
// ────────────────────────────────────────────────────────────
function Concept() {return (
    <section className="concept" id="concept">
      <span className="sec-num">01</span>
      <div className="wrap concept-grid">
        <div>
          <div className="section-head" style={{ marginBottom: 32 }}>
            <p className="eyebrow">Concept — 01</p>
            <h2 className="h-section" style={{ fontSize: "25px" }}>肌のことも、髪のことも<br />まとめて、ルポへ</h2>
          </div>
          <p className="concept-quote" style={{ fontSize: "15px" }}>
            シェービング＆エステサロン ルポ は、
            <em>シェービングと頭皮ケアの両方を専門に扱う</em>サロンです｡肌悩みのある女性が､ご自宅では手の届きにくい部分まで
            丁寧に手をかけられる時間を用意しています。<br /><br />
            ご来店ごとに､その日の肌や頭皮･髪の様子に合わせて施術を<br />
            組み立て､ご自宅で続けられるホームケアまでご一緒に考えます。
          </p>
        </div>
        <Placeholder id="photo-concept" className="concept-photo" fit="contain" label="CONCEPT / 理容椅子のカット" ratio="3 / 4" tone="cream" />
      </div>
    </section>);

}

// ────────────────────────────────────────────────────────────
// First-visit reassurance
// ────────────────────────────────────────────────────────────
function FirstVisit() {
  const cards = [
  {
    n: "01",
    title: "はじめてでも、迷わず。",
    body: "ご来店前にLINEで簡単なカウンセリングが可能です。気になる肌悩みや希望の仕上がりを、当日までにじっくりお聞かせください。"
  },
  {
    n: "02",
    title: "肌に触れる前に、まず対話を。",
    body: "施術前のカウンセリングで、肌・頭皮の状態を確認。お一人おひとりに合わせた進め方をご相談してから始めます。"
  },
  {
    n: "03",
    title: "おうちまで、ご一緒に。",
    body: "ご来店後の数日間が大切な時間。ご自宅で続けていただけるホームケアもサロンと同じものをお渡しできます。"
  }];

  return (
    <section id="first">
      <span className="sec-num">03</span>
      <div className="wrap">
        <div className="section-head">
          <div className="row">
            <p className="eyebrow">For Your First Visit — 03</p>
            <span className="mono">three things to know</span>
          </div>
          <h2 className="h-section" style={{ fontSize: "25px" }}>はじめての方へ<br />お伝えしたい3つのこと</h2>
        </div>
        <div className="reassure-grid">
          {cards.map((c) =>
          <article className="reassure-card" key={c.n}>
              <span className="reassure-num">{c.n}</span>
              <h3>{c.title}</h3>
              <p>{c.body}</p>
            </article>
          )}
        </div>
      </div>
    </section>);

}

function FAQ() {
  const items = [
  {
    q: "シェービングは初めてですが、痛くないですか？",
    a: "産毛・うぶ毛をやわらかく整えるシェービングのため、お肌への負担を最小限に。\nスチームや保湿の工程をはさみながら、ゆっくりと進めますので、初めての方も安心していらしてください。"
  },
  {
    q: "肌が敏感でも受けられますか？",
    a: "ご来店前のLINEカウンセリングで肌状態をうかがい、当日も施術前にもう一度確認します。\nコンディションによっては内容を調整したり、頭皮ケアやホームケアのご相談のみのご来店も承っています。"
  },
  {
    q: "メニューの所要時間はどのくらい？",
    a: "シェービング単体で約60〜80分、バザルトストーンや頭皮ケアを組み合わせる場合は90〜120分ほどが目安です。\nご予約時にお時間の希望もお知らせください。"
  },
  {
    q: "予約はLINEだけですか？",
    a: "メインはLINE予約（24時間受付）です。\nお電話でも承りますが、施術中はつながりにくい時間帯があるため、はじめての方はLINEからのご連絡がおすすめです。"
  },
  {
    q: "男性も来店できますか？",
    a: "現在は女性のお客様を中心にご案内しています。\n男性のご来店についてはご紹介制で承っておりますので、まずはLINEからお問い合わせください。"
  }];

  return (
    <div className="faq">
      {items.map((it, i) =>
      <details key={i} open={i === 0}>
          <summary>
            <span className="q">Q{String(i + 1).padStart(2, "0")}</span>
            <span>{it.q}</span>
            <span className="toggle" />
          </summary>
          <div className="a">{it.a}</div>
        </details>
      )}
    </div>);

}

// FAQ as its own section (placed between Voice and Staff).
function FAQSection() {
  return (
    <section id="faq">
      <span className="sec-num">FAQ</span>
      <div className="wrap">
        <div className="section-head" style={{ marginBottom: 32 }}>
          <div className="row">
            <p className="eyebrow">FAQ</p>
            <span className="mono">questions &amp; answers</span>
          </div>
          <h2 className="h-section" style={{ fontSize: "25px" }}>よくいただくご質問</h2>
        </div>
        <FAQ />
      </div>
    </section>);

}

// ────────────────────────────────────────────────────────────
// Services — three display modes (cards / story / tabs)
// ────────────────────────────────────────────────────────────
const SERVICE_MENU = [
{
  id: "shaving",
  title: "シェービング",
  en: "Shaving Esthetic",
  tagline: "お顔そり・お背中を、肌悩みに合わせて。オイルとパックでしっとり仕上げる多彩なコース。",
  from: "8,800円〜",
  courses: [
  { name: "お顔剃りベーシックコース", tag: "シンプルケア", time: "50分", price: "8,800円", desc: "オイルでお肌を整えながらゆっくりシェービング。初めての方・敏感肌の方におすすめ。",
    flow: ["カウンセリング", "オイルケアクレンジング", "ツボ押し（デトックスリンパ）", "保湿パック", "お顔・耳のシェービング", "眉デザインカット", "スキンケア", "頭皮・耳マッサージ"] },
  { name: "モイスチャーシェービング", tag: "保湿ケア", time: "60分", price: "11,000円", desc: "トリプルパックで保湿に特化。乾燥が気になる方に、もっちりとした仕上がり。",
    flow: ["カウンセリング", "オイルケアクレンジング", "フェイシャルマッサージ", "小顔リンパケア", "保湿パック", "お顔・耳のシェービング", "眉デザインカット", "モイスチャーパック", "スキンケア", "頭皮・耳マッサージ"] },
  { name: "お背中・美うなじシェービング", tag: "背中ケア", time: "60分", price: "8,800円", desc: "毛穴ケアをしてからシェービング（肩甲骨まで）。ウエストラインまでは +2,200円。",
    flow: ["カウンセリング", "背中クレンジング", "背中シェービング", "うなじシェービング", "保湿パック"],
    note: "ウエストラインまでの方は +2,200円で承ります。" },
  { name: "成人式シェービング", tag: "成人式限定", time: "70分", price: "9,900円", desc: "振袖に似合う美しいうなじに。土日祝は 11,000円で承ります。",
    flow: ["カウンセリング", "オイルケアクレンジング", "お顔シェービング", "眉カット", "深め襟足シェービング", "ヘッドマッサージ", "鎮静パック", "お仕上げ"] },
  { name: "プレミアムエステシェービング", tag: "乾燥・デリケート肌", time: "70分", price: "13,200円", desc: "ベーシック＋デコルテリンパ＋フェイシャルトリートメント＋トリプルパック。",
    flow: ["お顔剃りベーシックコースの内容一式", "デコルテリンパマッサージ", "フェイシャルトリートメント", "トリプルパック"] },
  { name: "毛穴レスエステシェービング", tag: "毛穴ケア", time: "60分", price: "13,200円", desc: "デコルテ／フェイシャルリンパに毛穴吸引をプラス。引き締まった肌へ。",
    flow: ["お顔剃りベーシックコースの内容一式", "デコルテ・フェイシャルリンパトリートメント＋毛穴吸引", "トリプルパック"] },
  { name: "美白エステシェービング", tag: "美肌仕上げ", time: "70分", price: "13,200円", desc: "漢方配合クリームでシェービング＆パック。なめらかで美白の肌に。",
    flow: ["お顔剃りベーシックコースの内容一式", "漢方配合クリームでシェービング＆パック", "フェイシャルリンパトリートメント", "トリプルパック"] },
  { name: "天使の肌シェービングエステ", tag: "エイジングケア", time: "90分", price: "16,500円", desc: "高濃度プラセンタ＋バザルト®ストーンフェイシャル。透明感とキメを整える。",
    flow: ["カウンセリング", "オイルケアクレンジング", "高濃度プラセンタエキス", "バザルト®ストーンフェイシャルトリートメント", "クリームパック", "高保湿クリームシェービング", "眉デザインカット", "プレミアムスキンケアパック", "お仕上げ"] },
  { name: "スペシャルシェービングエステ", tag: "NEW・最強小顔", time: "120分", price: "22,000円", desc: "天使の肌＋バザルト®ストーンヘッドスパの最強リフトケアコース。",
    flow: ["カウンセリング", "オイルケアクレンジング", "高濃度プラセンタエキス", "バザルト®ストーンフェイシャルトリートメント", "バザルト®ストーンヘッドスパトリートメント", "クリームパック", "高保湿クリームシェービング", "眉デザインカット", "プレミアムスキンケアパック", "お仕上げ"] }],

  options: [
  ["美うなじ（襟足）", "2,200円"],
  ["美うなじ（深襟足）", "2,750円"],
  ["デコルテ", "2,750円"],
  ["背中（肩甲骨まで）", "3,850円"],
  ["背中（腰まで）", "6,050円"],
  ["上腕〜ひじ上", "3,850円"],
  ["ひじ下〜指先", "3,850円"]]
},
{
  id: "facial",
  title: "フェイシャル",
  en: "Facial",
  tagline: "バザルト®温石で巡りを整える、リフトケア。お顔も頭皮も一体で。",
  from: "12,000円〜",
  courses: [
  { name: "バザルト温石 ヘッド&フェイシャル", tag: "1番人気・リフトケア", time: "80分", price: "16,500円", desc: "頭皮・顔・首・デコルテを一体で整える当店1番人気。内側から引き上がるフェイスラインへ。",
    flow: ["カウンセリング", "オイルケア", "デコルテケア", "バザルト®ストーンフェイシャル", "バザルト®ストーンヘッドスパ", "保湿パック", "耳・頭マッサージ", "スキンケア"] },
  { name: "リフトアップ小顔フェイシャル", tag: "ベーシックリフト", time: "80分", price: "12,000円", desc: "足元から巡りを整え、くすみや疲れを和らげる基本のフェイシャルケア。",
    flow: ["カウンセリング", "足湯", "オイルクレンジング", "バザルト®ストーンフェイシャル", "保湿パック", "スキンケア"] }]
},
{
  id: "headspa",
  title: "ヘッドスパ",
  en: "Head Spa",
  tagline: "頭皮を土台から整える、温石ヘッドスパ。髪のハリ・まとまりまで。",
  from: "9,900円〜",
  courses: [
  { name: "極上 頭皮リセット温石小顔スパ", tag: "最上級ケア", time: "120分", price: "19,800円", desc: "頭皮洗浄と温石で首・肩・頭をゆるめ、フェイスラインと髪まで整えるRepos最上級スパ。",
    flow: ["カウンセリング", "足湯", "マイクロスコープ頭皮カメラ", "オイルケア", "バザルト®ストーンヘッドスパ", "乳化トリートメント", "頭皮洗浄", "頭皮マッサージ", "お仕上げ"] },
  { name: "頭皮リフト美髪スパ", tag: "月1ケア・人気", time: "100分", price: "16,800円", desc: "疲れと髪を同時に整える。ハリ・まとまりを引き出す、毎月のケアに。",
    flow: ["カウンセリング", "足湯", "マイクロスコープ頭皮カメラ", "オイルケア", "バザルト®ストーンヘッドスパ", "乳化トリートメント", "頭皮マッサージ", "お仕上げ"] },
  { name: "頭皮リセットうるおいスパ", tag: "土台ケア", time: "90分", price: "11,000円", desc: "匂い・ベタつきが気になる方に。たっぷり栄養補給でさらさらの髪へ。",
    flow: ["カウンセリング", "マイクロスコープ頭皮カメラ", "オイルケア", "乳化トリートメント", "頭皮マッサージ", "頭皮洗浄", "お仕上げ"] },
  { name: "温石 小顔リフトスパ（ドライ）", tag: "リラックス", time: "80分", price: "9,900円", desc: "頭・首・肩をじんわりほぐすドライヘッドスパ。眼精疲労・首肩こり・睡眠に。+2,200円で腕・肩ケア。",
    flow: ["カウンセリング", "足湯", "バザルト®ストーンヘッドスパ", "ツボ押しデトックスリンパ", "肩・首マッサージ"],
    note: "プラス2,200円で腕・肩リフレッシュケアも承ります。" }]
},
{
  id: "body",
  title: "ボディエステ",
  en: "Body Esthetic",
  tagline: "温めたバザルト®ストーンの遠赤外線で芯から巡らせる、温活ボディトリートメント。冷え・むくみ・肩こり・姿勢のお悩みに。",
  from: "16,500円〜",
  courses: [
  { name: "マシュマロバストトリートメント", tag: "バストライン", time: "120分", price: "22,000円", desc: "足先からデコルテまでしっかりトリートメント。女性らしいデコルテ＆ふっくらバストでメリハリボディに。ウエストはくびれ、バストはふわふわに。",
    flow: ["カウンセリング", "足湯", "バザルト®ストーンふわふわバストトリートメント"] },
  { name: "スペシャルボディトリートメント", tag: "美姿勢・引き締め", time: "100分", price: "19,800円", desc: "温活ボディに肋間筋ケアをプラス。呼吸がしやすく姿勢も美しく、太りにくく痩せやすい身体へ。",
    flow: ["カウンセリング", "足湯", "バザルト®ストーンスペシャルボディトリートメント"] },
  { name: "温石ボディトリートメント", tag: "婦人科医推奨", time: "90分", price: "16,500円", desc: "遠赤外線の天然石で芯から温め基礎体温を上げる極上ケア。冷え・便秘・むくみ・肩こり・腰痛に。お顔のツボ押し付き。",
    flow: ["カウンセリング", "足湯", "バザルト®ストーンボディトリートメント"],
    note: "お顔のツボ押し付きです。" },
  { name: "背中すっきり&温石ヘッドスパ", tag: "慢性肩こり", time: "90分", price: "16,500円", desc: "寝てしまう人続出。根本原因の背中からしっかりほぐし、羽が生えたように軽く。落ちにくい背中のお肉もスッキリ。",
    flow: ["カウンセリング", "足湯", "バザルト®ストーンヘッドスパ＆背面トリートメント"] }]
},
{
  id: "bridal",
  title: "ブライダル",
  en: "Bridal",
  tagline: "挙式当日、最高の自信と輝きを。ドレスから見える上半身を美肌に整える、花嫁様のためのシェービング＆トリートメント。",
  from: "8,800円〜",
  courses: [
  { name: "お試しシェービングコース", tag: "肌質改善", time: "70分", price: "8,800円", desc: "くすみ・乾燥・毛穴・黒ずみをケアして美肌に仕上げる肌質改善シェービング。本番に向けた最適な日取りやホームケアもアドバイス。〔顔・首〕",
    flow: ["カウンセリング", "保湿クレンジング", "肌質改善ケア（くすみ・乾燥・毛穴ケア）", "お顔・耳のシェービング", "保湿パック", "スキンケア"] },
  { name: "ベーシックコース", tag: "基本", time: "90分", price: "22,000円", desc: "産毛や古い角質を除去して肌のトーンを明るく。ドレスから露出する上半身を美しく整える基本コース。〔顔・首・デコルテ・背中・うなじ〕",
    flow: ["カウンセリング", "背中ケア", "襟足・背中（肩甲骨まで）シェービング", "お顔オイルケアクレンジング", "デコルテフェイシャルトリートメント", "美姿勢ツボケア", "保湿パック", "お顔・デコルテシェービング", "眉デザインカット", "鎮静パック", "スキンケア", "お仕上げ"] },
  { name: "スペシャルケアコース", tag: "二の腕ケア付き", time: "120分", price: "27,500円", desc: "ベーシックに上腕シェービングをプラス。二の腕の老廃物を流し、すっきり引き締まった印象に。〔顔・首・デコルテ・背中・うなじ・上腕〕",
    flow: ["カウンセリング", "背中ケア", "襟足・背中（肩甲骨まで）シェービング", "上腕（上腕からひじ上まで）シェービング", "お顔オイルケアクレンジング", "デコルテフェイシャルトリートメント", "美姿勢ツボケア", "上腕トリートメント", "保湿パック", "お顔・デコルテシェービング", "眉デザインカット", "鎮静パック", "スキンケア", "お仕上げ"] },
  { name: "エレガントラインコース", tag: "人気No.1", time: "180分", price: "36,300円", desc: "スペシャルに加えバザルト®ストーンで深部のコリをほぐし、美しいフェイス〜首・デコルテラインへ。満足度・人気No.1コース。",
    flow: ["スペシャルケアコースの内容一式", "首スッキリトリートメント", "バザルト®ストーン フェイシャルケア", "バザルト®ストーン 二の腕ケア"] },
  { name: "美姿勢ラインコース", tag: "極上", time: "210分", price: "44,000円", desc: "フェイシャル・背中・二の腕のバザルト®ストーンをご一緒に。肩甲骨からほぐし、巻き肩のお悩みもスッキリ。後ろ姿まで美しい花嫁へ。",
    flow: ["スペシャルケアコースの内容一式", "バザルト®ストーン フェイシャルケア", "バザルト®ストーン 背中ケア", "バザルト®ストーン 二の腕ケア"] }]
}];


function CourseItem({ c }) {
  const [open, setOpen] = React.useState(false);
  const hasFlow = c.flow && c.flow.length > 0;
  return (
    <li className={`svc-course ${open ? "is-open" : ""}`}>
      <button
        type="button"
        className="svc-course-top"
        aria-expanded={open}
        disabled={!hasFlow}
        onClick={() => hasFlow && setOpen((v) => !v)}>
        <span className="svc-course-name">
          {c.name}
          {hasFlow && <span className="svc-course-more" aria-hidden="true"></span>}
        </span>
        <span className="svc-course-price">{c.price}</span>
      </button>
      <div className="svc-course-sub">
        {c.tag && <span className="svc-course-tag">{c.tag}</span>}
        <span className="svc-course-time">{c.time}</span>
      </div>
      <p className="svc-course-desc">{c.desc}</p>
      {hasFlow &&
      <div className="svc-course-detail">
          <div className="svc-course-detail-inner">
            <p className="svc-course-flow-label">施術の流れ</p>
            <ol className="svc-course-flow">
              {c.flow.map((step, i) => <li key={i}>{step}</li>)}
            </ol>
            {c.note && <p className="svc-course-note">※{c.note}</p>}
          </div>
        </div>
      }
    </li>);

}

function Services() {
  const [open, setOpen] = React.useState("shaving");

  // Open the matching menu when arriving via a #service-<id> deep link
  // (from the hamburger menu), then scroll it into view.
  React.useEffect(() => {
    var pendingId = null;
    var finalizeTimer = null;
    var safetyTimer = null;
    var fixedTimers = [];
    var ro = null;

    function snap(id) {
      var el = document.getElementById("service-" + id);
      if (!el) return;
      el.scrollIntoView({ block: "start" });
    }

    function finalize() {
      if (!pendingId) return;
      snap(pendingId); // one last correction before we stop watching
      pendingId = null;
      document.documentElement.style.scrollBehavior = ""; // restore smooth
      if (ro) { ro.disconnect(); ro = null; }
    }

    function bump() {
      if (!pendingId) return;
      snap(pendingId);
      clearTimeout(finalizeTimer);
      finalizeTimer = setTimeout(finalize, 450);
    }

    // Layout can settle via a CSS transition ending, a non-transition size
    // change (ResizeObserver), or — in case neither fires reliably — a
    // handful of fixed-delay checks. Any one of these is enough; they're
    // all idempotent (snapping to an already-correct position is a no-op).
    function onTransitionEnd(e) {
      if (e.propertyName !== "grid-template-rows") return;
      bump();
    }

    function openFromHash() {
      const m = (window.location.hash || "").match(/^#service-(.+)$/);
      if (!m) return;
      const id = decodeURIComponent(m[1]);
      if (!SERVICE_MENU.some((s) => s.id === id)) return;
      pendingId = id;
      // Clicking a hamburger-drawer link both navigates AND closes the
      // drawer; the drawer's own body scroll-lock (overflow:hidden) is only
      // released once React re-renders, which can lag a tick behind this
      // handler. While locked, scrollIntoView is a no-op — clear it directly
      // here so scrolling is never blocked.
      document.body.style.overflow = "";
      // Disable global smooth-scroll for the whole open sequence so the
      // browser's native hash jump doesn't animate toward the panel's
      // pre-collapse position and fight our snaps. Restored once settled.
      document.documentElement.style.scrollBehavior = "auto";
      setOpen(id);

      fixedTimers.forEach(clearTimeout);
      fixedTimers = [0, 60, 150, 300, 500, 750, 1050, 1500, 2200, 3200].map(
        function (ms) {
          return setTimeout(function () { snap(id); }, ms);
        }
      );
      requestAnimationFrame(function () { snap(id); });

      clearTimeout(finalizeTimer);
      finalizeTimer = setTimeout(finalize, 2400);

      if (ro) ro.disconnect();
      ro = new ResizeObserver(bump);
      ro.observe(document.body);
      ro.observe(document.documentElement);

      clearTimeout(safetyTimer);
      safetyTimer = setTimeout(finalize, 7000);
    }

    var menu = document.querySelector(".svc-menu");
    if (menu) menu.addEventListener("transitionend", onTransitionEnd);
    openFromHash();
    window.addEventListener("hashchange", openFromHash);
    return () => {
      window.removeEventListener("hashchange", openFromHash);
      if (menu) menu.removeEventListener("transitionend", onTransitionEnd);
      clearTimeout(finalizeTimer);
      clearTimeout(safetyTimer);
      fixedTimers.forEach(clearTimeout);
      if (ro) ro.disconnect();
    };
  }, []);

  return (
    <section id="service">
      <span className="sec-num">04</span>
      <div className="wrap">
        <div className="section-head">
          <div className="row">
            <p className="eyebrow">Our Care — 04</p>
            <span className="mono">menu &amp; price</span>
          </div>
          <h2 className="h-section" style={{ fontSize: "25px" }}>
            シェービングを軸にした<br />
            5つのケアメニュー
          </h2>
        </div>

        <div className="svc-menu">
          {SERVICE_MENU.map((s) => {
            const isOpen = open === s.id;
            return (
              <div className={`svc-acc ${isOpen ? "is-open" : ""}`} key={s.id} id={`service-${s.id}`}>
                <button
                  className="svc-acc-head"
                  aria-expanded={isOpen}
                  onClick={() => setOpen(isOpen ? "" : s.id)}>
                  <span className="svc-acc-en">{s.en}</span>
                  <span className="svc-acc-title">{s.title}</span>
                  {s.from && <span className="svc-acc-from">{s.from}</span>}
                  <span className="svc-acc-toggle" aria-hidden="true" />
                </button>
                <div className="svc-acc-body">
                  <div className="svc-acc-inner">
                    <div className="svc-acc-top">
                      <p className="svc-acc-tagline">{s.tagline}</p>
                      <image-slot
                        id={`svc-photo-${s.id}`}
                        class="svc-acc-photo"
                        shape="rounded"
                        radius="4"
                        placeholder="写真をドラッグ／クリックで選択">
                      </image-slot>
                    </div>
                    {s.courses.length > 0 &&
                    <ul className="svc-courses">
                        {s.courses.map((c, i) => <CourseItem c={c} key={i} />)}
                      </ul>
                    }
                    {s.options &&
                    <div className="svc-options">
                        <p className="mono svc-options-label">オプションシェービング</p>
                        <ul>
                          {s.options.map((o, i) =>
                        <li key={i}><span>{o[0]}</span><span>{o[1]}</span></li>
                        )}
                        </ul>
                      </div>
                    }
                  </div>
                </div>
              </div>);
          })}
        </div>
        <p className="svc-note">表示はすべて税込価格です。コース内容は当日の体調・肌状態に合わせて調整いたします。ご予約・ご相談はLINEから承ります。</p>
      </div>
    </section>);
}

Object.assign(window, {
  Nav, LineIcon, Hero, Concept, FirstVisit, FAQ, FAQSection, Services
});