/* global React */
/* eslint-disable */

// ─────────────────────────────────────────────
// 住宅最適設計ビジュアライザー — 共有コンポーネント
// ─────────────────────────────────────────────

const { useState, useEffect, useRef, useMemo } = React;

// ── データ ──────────────────────────────────
const DECK_COLORS = [
  { id: 'wood_natural', name: '天然木 ナチュラル', hex: '#a67848' },
  { id: 'wood_dark',    name: '天然木 ダーク',     hex: '#6a4828' },
  { id: 'composite',    name: '樹脂木 グレー',     hex: '#8a8478' },
];
const LAWN_COLORS = [
  { id: 'artificial', name: '人工芝',     hex: '#4a8c2a' },
  { id: 'gravel',     name: '砂利',       hex: '#b8b0a0' },
  { id: 'concrete',   name: 'コンクリ',   hex: '#c4c0b4' },
];

// より広い壁色パレット (元リポジトリのDCP_COLORSに準拠)
const WALL_COLORS_FULL = [
  { id: 't101', name: 'T101 純白',          hex: '#e8e5df' },
  { id: 't102', name: 'T102 アイボリー',     hex: '#ece7dd' },
  { id: 't103', name: 'T103 ライトグレー',   hex: '#d1d2cb' },
  { id: 't104', name: 'T104 ベージュ',       hex: '#cbc4ba' },
  { id: 't107', name: 'T107 シルバー',       hex: '#a1a39f' },
  { id: 't108', name: 'T108 テラコッタ',     hex: '#b29784' },
  { id: 't110', name: 'T110 グレージュ',     hex: '#949894' },
  { id: 't111', name: 'T111 ストーン',       hex: '#9b968c' },
  { id: 't112', name: 'T112 ブラウン',       hex: '#89796c' },
  { id: 't113', name: 'T113 ダークグレー',   hex: '#565856' },
  { id: 't115', name: 'T115 チャコール',     hex: '#394247' },
  { id: 't117', name: 'T117 オフホワイト',   hex: '#e0e0da' },
  { id: 't119', name: 'T119 ペール',         hex: '#d1d2d0' },
  { id: 't121', name: 'T121 ライトモカ',     hex: '#ccbeb7' },
  { id: 't123', name: 'T123 ブラック',       hex: '#3f423c' },
  { id: 't124', name: 'T124 イエローオークル', hex: '#d7c59a' },
  { id: 't125', name: 'T125 サーモン',       hex: '#c0a991' },
  { id: 't126', name: 'T126 ライトシルバー', hex: '#9c9a95' },
  { id: 't127', name: 'T127 ベージュグレー', hex: '#a69b94' },
  { id: 't128', name: 'T128 ダークオリーブ', hex: '#3a4636' },
  { id: 'olive_warm', name: 'ウォームオリーブ', hex: '#6b7a44', tag: '玄関用' },
];

// より広い屋根色パレット (ニチハ いぶき シリーズ含む)
const ROOF_COLORS_FULL = [
  { id: 'dkgray',         name: '濃グレー ガルバ',  hex: '#3a3835' },
  { id: 'blkbr',          name: 'ブラック 金属板',  hex: '#1f1d1b' },
  { id: 'bronze',         name: 'ブロンズ ガルバ',  hex: '#4a3828' },
  { id: 'slate',          name: 'スレートグレー',   hex: '#595a55' },
  { id: 'ge24_beige',     name: 'GE-24',            hex: '#c8b894', sub: 'ベージュ' },
  { id: 'ge29_white',     name: 'GE-29',            hex: '#d6cfb7', sub: 'サンドホワイト' },
  { id: 'ge83_silver',    name: 'GE-83',            hex: '#a8a8a4', sub: 'シルバー' },
  { id: 'ge82_champagne', name: 'GE-82',            hex: '#b0a07a', sub: 'シャンパンゴールド' },
  { id: 'ge38_seagreen',  name: 'GE-38',            hex: '#6a9088', sub: 'ロクショウ' },
  { id: 'ge31_moss',      name: 'GE-31',            hex: '#4a5d44', sub: 'モスグリーン' },
];

const SOFFIT_COLORS_FULL = [
  { id: 'cedar',        name: '杉 節あり',         hex: '#b88848' },
  { id: 'walnut',       name: 'ウォルナット',       hex: '#6a4628' },
  { id: 'oak',          name: 'オーク',             hex: '#a67838' },
  { id: 'pine',         name: 'パイン',             hex: '#d0a060' },
  { id: 'yk021_natural', name: 'YK021',            hex: '#d8b06a', sub: 'ナチュラルメイプル' },
  { id: 'latte_gray',   name: 'ラテングレー',       hex: '#9a948a' },
  { id: 'blackwalnut',  name: 'ブラックウォルナット', hex: '#4a3020' },
];

const WALL_COLORS = WALL_COLORS_FULL;
const ROOF_COLORS = ROOF_COLORS_FULL;
const SOFFIT_COLORS = SOFFIT_COLORS_FULL;

const FRAME_COLORS = [
  { id: 'black',    name: 'ブラック',     hex: '#141414' },
  { id: 'charcoal', name: 'チャコール',   hex: '#2a2a26' },
  { id: 'brown',    name: 'ダークブラウン', hex: '#3a2818' },
  { id: 'white',    name: 'ホワイト',     hex: '#eae6dc' },
  { id: 'silver',   name: 'シルバー',     hex: '#a0a0a0' },
];

const DOOR_STYLES = [
  { id: 'venato_n09n', name: 'ヴェナート N09N', sub: 'ナチュラルオーク', hex: '#d8a458' },
  { id: 'plain',       name: 'プレーン黒',       sub: 'シンプル',         hex: '#252220' },
];

const CARPORT_OPTS = [
  { id: 'aluminum', name: 'アルミ半透明', sub: 'スタンダード' },
  { id: 'wood',     name: '木製+ポリカ',  sub: 'ナチュラル' },
  { id: 'none',     name: 'なし',         sub: '— 設置しない' },
];

// ── 仕様の状態（モック）─────────────────────
const initialSpec = {
  wall: 't128',
  wallSouthEnabled: true,
  wallSouth: 't104',
  wallPorchEnabled: true,
  wallPorch: 'olive_warm',
  wallStepEnabled: true,
  wallStep: 't104',
  roof: 'dkgray',
  soffit: 'blackwalnut',
  frame: 'silver',
  doorStyle: 'venato_n09n',
  carport: 'aluminum',
  deck: 'wood_natural',
  lawn: 'artificial',
  showLabels: true,
};

const projectMeta = {
  name: '仕様打合せ 2026.05',
  client: 'S邸 — 木造2階建',
  area: { land: 198.6, building: 105.2, floor: 168.4 },
  perf: { ua: 0.42, c: 0.5, eta: 1.6 },           // 断熱・気密・冷房期日射取得
  sun: { south: 92, east: 64, west: 38 },         // 日照スコア
  cost: { base: 28.6, options: 4.2, total: 32.8 }, // 万円ベース...
};

// ── アイコン群（SVGをインライン）─────────
const Icon = ({ name, size = 18, ...rest }) => {
  const sw = 1.7;
  const props = { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: sw, strokeLinecap: "round", strokeLinejoin: "round", ...rest };
  switch (name) {
    case 'cube':       return <svg {...props}><path d="M12 2 3 7v10l9 5 9-5V7l-9-5Z"/><path d="m3 7 9 5 9-5"/><path d="M12 22V12"/></svg>;
    case 'floor':      return <svg {...props}><rect x="3" y="3" width="18" height="18" rx="1"/><path d="M3 12h18M12 3v18M9 12v9M15 3v6"/></svg>;
    case 'spec':       return <svg {...props}><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><path d="M14 2v6h6M9 13h6M9 17h4"/></svg>;
    case 'sun':        return <svg {...props}><circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M4.93 19.07l1.41-1.41M17.66 6.34l1.41-1.41"/></svg>;
    case 'leaf':       return <svg {...props}><path d="M11 20A7 7 0 0 1 4 13c0-7 7-11 16-11 0 9-4 16-11 16 0 0-2 0-3.5-1.5"/><path d="M2 22c1.5-3 4.5-6 9-9"/></svg>;
    case 'coin':       return <svg {...props}><circle cx="12" cy="12" r="9"/><path d="M14.8 9a2.5 2.5 0 0 0-2.3-1.5h-1a2.5 2.5 0 0 0 0 5h1a2.5 2.5 0 0 1 0 5h-1A2.5 2.5 0 0 1 9.2 16M12 6v2m0 8v2"/></svg>;
    case 'compare':    return <svg {...props}><path d="M16 3h5v5M21 3l-7 7M8 21H3v-5M3 21l7-7"/></svg>;
    case 'edit':       return <svg {...props}><path d="M12 20h9"/><path d="M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4Z"/></svg>;
    case 'check':      return <svg {...props}><path d="m5 12 5 5L20 7"/></svg>;
    case 'chevDown':   return <svg {...props}><path d="m6 9 6 6 6-6"/></svg>;
    case 'chevRight':  return <svg {...props}><path d="m9 6 6 6-6 6"/></svg>;
    case 'chevLeft':   return <svg {...props}><path d="m15 6-6 6 6 6"/></svg>;
    case 'plus':       return <svg {...props}><path d="M12 5v14M5 12h14"/></svg>;
    case 'menu':       return <svg {...props}><path d="M4 6h16M4 12h16M4 18h16"/></svg>;
    case 'close':      return <svg {...props}><path d="M18 6 6 18M6 6l12 12"/></svg>;
    case 'theme':      return <svg {...props}><path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"/></svg>;
    case 'share':      return <svg {...props}><circle cx="18" cy="5" r="3"/><circle cx="6" cy="12" r="3"/><circle cx="18" cy="19" r="3"/><path d="m8.6 13.5 6.8 4M15.4 6.5l-6.8 4"/></svg>;
    case 'copy':       return <svg {...props}><rect x="8" y="8" width="13" height="13" rx="2"/><path d="M16 8V4a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h4"/></svg>;
    case 'download':   return <svg {...props}><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4M7 10l5 5 5-5M12 15V3"/></svg>;
    case 'compass':    return <svg {...props}><circle cx="12" cy="12" r="9"/><path d="m16 8-2 6-6 2 2-6 6-2Z"/></svg>;
    case 'rotate':     return <svg {...props}><path d="M3 12a9 9 0 1 0 3-6.7L3 8"/><path d="M3 3v5h5"/></svg>;
    case 'eye':        return <svg {...props}><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8S1 12 1 12Z"/><circle cx="12" cy="12" r="3"/></svg>;
    case 'panel':      return <svg {...props}><rect x="3" y="3" width="18" height="18" rx="2"/><path d="M9 3v18"/></svg>;
    case 'reset':      return <svg {...props}><path d="M3 12a9 9 0 1 0 3-6.7L3 8M3 3v5h5"/></svg>;
    case 'window':     return <svg {...props}><rect x="3" y="3" width="18" height="18" rx="1"/><path d="M3 12h18M12 3v18"/></svg>;
    case 'door':       return <svg {...props}><path d="M5 22V4a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v18"/><path d="M3 22h18M15 13v.01"/></svg>;
    case 'roof':       return <svg {...props}><path d="m3 12 9-7 9 7"/><path d="M5 11v9h14v-9"/></svg>;
    case 'paint':      return <svg {...props}><path d="M19 11h-4l-2-2H5a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-6a2 2 0 0 0-2-2Z"/><path d="M11 9V5a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v4"/></svg>;
    case 'tree':       return <svg {...props}><path d="M12 22v-7M5 15a4 4 0 0 1 1-7.7 5 5 0 0 1 9.6-1.5A4.5 4.5 0 0 1 19 15Z"/></svg>;
    case 'expand':     return <svg {...props}><path d="M15 3h6v6M9 21H3v-6M21 3l-7 7M3 21l7-7"/></svg>;
    case 'collapse':   return <svg {...props}><path d="M4 14h6v6M20 10h-6V4M14 10l7-7M3 21l7-7"/></svg>;
    default:           return null;
  }
};

// ── 平面図(2D) — 仕様の壁色を投影 ────────────
// 各壁面ゾーン (北/南/ポーチ/段差) を選択された素材色で塗り分け表示
const FloorPlanSVG = ({ floor = '1F', theme = 'light', spec, showLabels = true }) => {
  const isDark = theme === 'dark';
  const ink     = isDark ? '#d8cdb8' : '#1a1614';
  const inkSub  = isDark ? '#9a9080' : '#5a5246';
  const wall    = isDark ? '#5a544a' : '#2a2622';
  const fill    = isDark ? '#2a2418' : '#faf7f1';
  const labelBg = isDark ? '#332d23' : '#ece5d6';
  const bg      = isDark ? '#16130f' : '#f4f1eb';

  // 仕様から色を引く
  const colorOf = (id) => (WALL_COLORS_FULL.find(c => c.id === id) || WALL_COLORS_FULL[0]).hex;
  const nameOf  = (id) => (WALL_COLORS_FULL.find(c => c.id === id) || WALL_COLORS_FULL[0]).name;
  const c = {
    north: colorOf(spec?.wall),
    south: spec?.wallSouthEnabled ? colorOf(spec?.wallSouth) : colorOf(spec?.wall),
    porch: spec?.wallPorchEnabled ? colorOf(spec?.wallPorch) : colorOf(spec?.wall),
    step:  spec?.wallStepEnabled  ? colorOf(spec?.wallStep)  : colorOf(spec?.wall),
  };
  const n = {
    north: nameOf(spec?.wall),
    south: spec?.wallSouthEnabled ? nameOf(spec?.wallSouth) : nameOf(spec?.wall) + ' (北と同色)',
    porch: spec?.wallPorchEnabled ? nameOf(spec?.wallPorch) : nameOf(spec?.wall) + ' (北と同色)',
    step:  spec?.wallStepEnabled  ? nameOf(spec?.wallStep)  : nameOf(spec?.wall) + ' (北と同色)',
  };

  // 色付き壁の太さ
  const WSTROKE = 12;

  if (floor === '1F') {
    return (
      <svg viewBox="0 0 900 540" preserveAspectRatio="xMidYMid meet" style={{ width: '100%', height: '100%', display: 'block' }}>
        <rect width="900" height="540" fill={bg}/>

        {/* 室内塗りつぶし */}
        <g fill={fill} stroke="none">
          <polygon points="180,120 700,120 700,260 720,260 720,420 450,420 450,460 180,460"/>
          <rect x="100" y="160" width="80" height="180"/>
        </g>

        {/* 内壁 (細線) */}
        <g stroke={wall} strokeWidth="1.6" opacity="0.7">
          <line x1="340" y1="120" x2="340" y2="310"/>
          <line x1="180" y1="310" x2="700" y2="310"/>
          <line x1="480" y1="120" x2="480" y2="310"/>
          <line x1="450" y1="310" x2="450" y2="460"/>
          <line x1="260" y1="310" x2="260" y2="460"/>
        </g>

        {/* ── 外壁: 仕様色で塗り分け ── */}
        {/* 北側外壁 (上辺) — wall (北側・玄関周り) */}
        <line x1="180" y1="120" x2="700" y2="120" stroke={c.north} strokeWidth={WSTROKE} strokeLinecap="square"/>
        {/* 東側外壁 — 北色を継承 */}
        <line x1="700" y1="120" x2="700" y2="260" stroke={c.north} strokeWidth={WSTROKE}/>
        <line x1="720" y1="260" x2="720" y2="420" stroke={c.north} strokeWidth={WSTROKE}/>
        <line x1="700" y1="260" x2="720" y2="260" stroke={c.north} strokeWidth={WSTROKE}/>

        {/* 南側外壁 (下辺・パントリー〜浴室〜LDK南) — wallSouth */}
        <line x1="180" y1="460" x2="450" y2="460" stroke={c.south} strokeWidth={WSTROKE}/>
        <line x1="450" y1="420" x2="720" y2="420" stroke={c.south} strokeWidth={WSTROKE}/>
        <line x1="450" y1="420" x2="450" y2="460" stroke={c.south} strokeWidth={WSTROKE}/>

        {/* 西側外壁 (本体側・段差部) — wallStep */}
        <line x1="180" y1="120" x2="180" y2="160" stroke={c.north} strokeWidth={WSTROKE}/>
        <line x1="180" y1="340" x2="180" y2="460" stroke={c.step} strokeWidth={WSTROKE}/>

        {/* 玄関ポーチ突出部 — wallPorch */}
        <line x1="100" y1="160" x2="180" y2="160" stroke={c.porch} strokeWidth={WSTROKE}/>
        <line x1="100" y1="160" x2="100" y2="340" stroke={c.porch} strokeWidth={WSTROKE}/>
        <line x1="100" y1="340" x2="180" y2="340" stroke={c.porch} strokeWidth={WSTROKE}/>

        {/* 窓を表す印 (色付き壁を切る) */}
        <g stroke={bg} strokeWidth={WSTROKE + 2}>
          {/* LDK 南掃き出し */}
          <line x1="560" y1="420" x2="680" y2="420"/>
          {/* 主寝室東スリット (1F東) */}
          <line x1="700" y1="160" x2="700" y2="210"/>
          {/* 玄関ドア (ポーチ南) */}
          <line x1="110" y1="340" x2="160" y2="340"/>
        </g>
        {/* 窓は細線で再描画 */}
        <g stroke={wall} strokeWidth="1.4" strokeDasharray="2,2">
          <line x1="560" y1="420" x2="680" y2="420"/>
          <line x1="700" y1="160" x2="700" y2="210"/>
          <line x1="110" y1="340" x2="160" y2="340"/>
        </g>

        {/* 部屋ラベル */}
        {showLabels && [
          { x: 260, y: 200, name: '畳コーナー' },
          { x: 410, y: 200, name: '玄関' },
          { x: 590, y: 200, name: 'LDK' },
          { x: 220, y: 380, name: 'パントリー' },
          { x: 360, y: 380, name: '洗面・浴室' },
          { x: 590, y: 380, name: 'リビング' },
          { x: 140, y: 250, name: 'ポーチ' },
        ].map(r => (
          <g key={r.name}>
            <rect x={r.x - 42} y={r.y - 12} width="84" height="24" rx="4" fill={labelBg} stroke={wall} strokeWidth="1"/>
            <text x={r.x} y={r.y + 4} textAnchor="middle" fontSize="12" fontWeight="600" fill={ink}>{r.name}</text>
          </g>
        ))}

        {/* 寸法 */}
        <g fontSize="10" fill={inkSub} opacity="0.7" fontFamily="JetBrains Mono">
          <text x={440} y={108} textAnchor="middle">9,556 mm</text>
          <text x={734} y={290} textAnchor="start">7,736 mm</text>
        </g>

        {/* 凡例 (左下) — 色 = 壁面の対応 */}
        <PlanLegend zones={[
          { color: c.north, label: '北側外壁', name: n.north },
          { color: c.south, label: '南側外壁', name: n.south },
          { color: c.porch, label: 'ポーチ',   name: n.porch },
          { color: c.step,  label: '段差横壁', name: n.step  },
        ]} ink={ink} inkSub={inkSub} surface={labelBg} stroke={wall}/>
      </svg>
    );
  }

  // 2F
  return (
    <svg viewBox="0 0 900 540" preserveAspectRatio="xMidYMid meet" style={{ width: '100%', height: '100%', display: 'block' }}>
      <rect width="900" height="540" fill={bg}/>
      <g fill={fill} stroke="none">
        <polygon points="260,120 700,120 700,400 260,400"/>
      </g>
      <g stroke={wall} strokeWidth="1.6" opacity="0.7">
        <line x1="260" y1="260" x2="700" y2="260"/>
        <line x1="480" y1="120" x2="480" y2="260"/>
      </g>
      {/* 外壁 — 2Fは本体色のみ */}
      <g stroke={c.north} strokeWidth={WSTROKE}>
        <line x1="260" y1="120" x2="700" y2="120"/>
        <line x1="700" y1="120" x2="700" y2="400"/>
        <line x1="260" y1="400" x2="700" y2="400"/>
        <line x1="260" y1="120" x2="260" y2="400"/>
      </g>
      {/* 2F南窓 (寝室南窓・洋室B南窓) */}
      <g stroke={bg} strokeWidth={WSTROKE + 2}>
        <line x1="370" y1="400" x2="420" y2="400"/>
        <line x1="560" y1="400" x2="610" y2="400"/>
      </g>
      <g stroke={wall} strokeWidth="1.4" strokeDasharray="2,2">
        <line x1="370" y1="400" x2="420" y2="400"/>
        <line x1="560" y1="400" x2="610" y2="400"/>
      </g>

      {showLabels && [
        { x: 370, y: 195, name: '主寝室' },
        { x: 590, y: 195, name: '洋室 A' },
        { x: 480, y: 330, name: '洋室 B' },
      ].map(r => (
        <g key={r.name}>
          <rect x={r.x - 50} y={r.y - 12} width="100" height="24" rx="4" fill={labelBg} stroke={wall} strokeWidth="1"/>
          <text x={r.x} y={r.y + 4} textAnchor="middle" fontSize="12" fontWeight="600" fill={ink}>{r.name}</text>
        </g>
      ))}

      <PlanLegend zones={[
        { color: c.north, label: '外壁(本体)', name: n.north },
      ]} ink={ink} inkSub={inkSub} surface={labelBg} stroke={wall}/>
    </svg>
  );
};

// 凡例 (左下): 色 ⇔ どの壁面か
const PlanLegend = ({ zones, ink, inkSub, surface, stroke }) => {
  const rowH = 22;
  const padY = 12;
  const padX = 14;
  const w = 230;
  const h = padY * 2 + zones.length * rowH + 18;
  return (
    <g transform={`translate(16, ${540 - h - 16})`}>
      <rect width={w} height={h} rx="8" fill={surface} stroke={stroke} strokeWidth="1" opacity="0.95"/>
      <text x={padX} y={padY + 11} fontSize="10" fontWeight="700" fill={inkSub} letterSpacing="0.08em">EXTERIOR MATERIAL</text>
      {zones.map((z, i) => (
        <g key={z.label} transform={`translate(${padX}, ${padY + 22 + i * rowH})`}>
          <rect width="14" height="14" rx="2" fill={z.color} stroke={stroke} strokeWidth="0.6"/>
          <text x="22" y="11" fontSize="11" fontWeight="600" fill={ink}>{z.label}</text>
          <text x="90" y="11" fontSize="10" fill={inkSub}>{z.name}</text>
        </g>
      ))}
    </g>
  );
};

const HouseSVG = ({ theme = 'light' }) => {
  const isDark = theme === 'dark';
  const wall = isDark ? '#5a5544' : '#3a4636';        // ダークオリーブ
  const wallPorch = '#6b7a44';                         // ウォームオリーブ
  const wallSouth = isDark ? '#9c9384' : '#cbc4ba';   // ベージュ
  const roof = '#2a2825';
  const soffit = '#4a3020';
  const window = isDark ? '#b8d4dc' : '#a8c8d8';
  const ground = isDark ? '#3a3328' : '#d8cdb8';
  const lawn = isDark ? '#4a6a3a' : '#6b8a4a';
  const deck = isDark ? '#8a6438' : '#a67848';
  const concrete = isDark ? '#5a544a' : '#c8c4b8';

  return (
    <svg viewBox="0 0 900 540" preserveAspectRatio="xMidYMid meet" style={{ width: '100%', height: '100%', display: 'block' }}>
      <defs>
        <linearGradient id="sky" x1="0" y1="0" x2="0" y2="1">
          {isDark ? (<>
            <stop offset="0" stopColor="#1c2430"/>
            <stop offset="0.7" stopColor="#2a2418"/>
            <stop offset="1" stopColor="#3a2e1e"/>
          </>) : (<>
            <stop offset="0" stopColor="#c8d6e2"/>
            <stop offset="0.7" stopColor="#e2dccd"/>
            <stop offset="1" stopColor="#d0c8b8"/>
          </>)}
        </linearGradient>
        <pattern id="grass" width="6" height="6" patternUnits="userSpaceOnUse">
          <rect width="6" height="6" fill={lawn}/>
          <circle cx="2" cy="2" r="0.6" fill={isDark ? '#3a5a2a' : '#5a7a3a'}/>
          <circle cx="4.5" cy="4.5" r="0.5" fill={isDark ? '#5a7a3a' : '#7a9a4a'}/>
        </pattern>
        <filter id="softshad" x="-20%" y="-20%" width="140%" height="140%">
          <feGaussianBlur in="SourceAlpha" stdDeviation="3"/>
          <feOffset dx="2" dy="6" result="offsetblur"/>
          <feComponentTransfer><feFuncA type="linear" slope="0.4"/></feComponentTransfer>
          <feMerge><feMergeNode/><feMergeNode in="SourceGraphic"/></feMerge>
        </filter>
      </defs>
      {/* sky */}
      <rect width="900" height="540" fill="url(#sky)"/>
      {/* ground */}
      <polygon points="0,400 900,360 900,540 0,540" fill={ground}/>
      {/* lawn (SE garden) */}
      <polygon points="540,430 820,400 820,540 540,540" fill="url(#grass)"/>
      {/* wood deck (between house and lawn) */}
      <polygon points="500,420 540,430 540,500 500,495" fill={deck}/>
      <g stroke={isDark ? '#604528' : '#7a5a38'} strokeWidth="1" opacity="0.5">
        <line x1="500" y1="430" x2="540" y2="440"/>
        <line x1="500" y1="445" x2="540" y2="455"/>
        <line x1="500" y1="460" x2="540" y2="470"/>
        <line x1="500" y1="475" x2="540" y2="485"/>
      </g>
      {/* concrete (driveway) */}
      <polygon points="100,420 320,410 320,540 100,540" fill={concrete}/>
      {/* carport roof (semi-transparent) */}
      <g opacity="0.6" filter="url(#softshad)">
        <polygon points="100,300 320,290 320,330 100,330" fill="#d8e0e4" stroke={isDark ? '#5a5a5a' : '#a0a0a0'} strokeWidth="1"/>
        <line x1="120" y1="330" x2="120" y2="425" stroke="#8a8a8a" strokeWidth="3"/>
        <line x1="310" y1="330" x2="310" y2="415" stroke="#8a8a8a" strokeWidth="3"/>
      </g>

      {/* 2F volume (back, taller, dark olive) */}
      <g filter="url(#softshad)">
        {/* roof of 2F (slight slope) */}
        <polygon points="340,140 760,120 770,135 350,155" fill={roof}/>
        {/* 2F wall front */}
        <polygon points="340,155 760,135 760,260 340,275" fill={wall}/>
        {/* 2F wall side (east) */}
        <polygon points="760,135 800,150 800,265 760,260" fill={isDark ? '#4a4434' : '#2a3326'}/>
        {/* soffit line */}
        <polygon points="340,140 760,120 770,135 350,155" fill="none" stroke={soffit} strokeWidth="2"/>
        {/* windows 2F */}
        <rect x="380" y="180" width="60" height="50" fill={window} stroke="#0a0a0a" strokeWidth="1.5" opacity="0.85"/>
        <rect x="500" y="180" width="60" height="50" fill={window} stroke="#0a0a0a" strokeWidth="1.5" opacity="0.85"/>
        <rect x="620" y="180" width="120" height="35" fill={window} stroke="#0a0a0a" strokeWidth="1.5" opacity="0.85"/>
      </g>

      {/* 1F volume (front, beige south wall) */}
      <g filter="url(#softshad)">
        {/* 1F roof (south strip, low slope) */}
        <polygon points="340,275 760,260 770,275 350,290" fill={roof}/>
        {/* 1F south wall (beige) */}
        <polygon points="340,290 540,280 540,420 340,420" fill={wallSouth}/>
        {/* 1F east wall (dark olive continuation) */}
        <polygon points="540,280 760,275 800,290 800,440 540,420" fill={isDark ? '#5a5546' : '#3a4032'}/>
        {/* East wall edge */}
        <polygon points="760,275 800,290 800,440 760,425" fill={isDark ? '#4a4434' : '#2a2e22'}/>
        {/* 1F windows south */}
        <rect x="365" y="320" width="40" height="70" fill={window} stroke="#0a0a0a" strokeWidth="1.5" opacity="0.85"/>
        {/* Large garden opening (sliding) */}
        <rect x="430" y="310" width="100" height="105" fill={window} stroke="#0a0a0a" strokeWidth="1.5" opacity="0.85"/>
        <line x1="480" y1="310" x2="480" y2="415" stroke="#0a0a0a" strokeWidth="1"/>
        {/* 1F windows east */}
        <rect x="600" y="320" width="80" height="25" fill={window} stroke="#0a0a0a" strokeWidth="1.5" opacity="0.85"/>
      </g>

      {/* Porch (west protrusion, olive warm) */}
      <g filter="url(#softshad)">
        <polygon points="245,250 340,255 340,420 245,415" fill={wallPorch}/>
        {/* Porch overhang */}
        <polygon points="240,250 345,255 345,267 240,262" fill={roof}/>
        {/* Door */}
        <rect x="270" y="320" width="42" height="90" fill={DOOR_STYLES[0].hex} stroke="#0a0a0a" strokeWidth="1"/>
        <line x1="304" y1="358" x2="304" y2="385" stroke="#101010" strokeWidth="3"/>
        {/* slit window beside door */}
        <rect x="255" y="328" width="6" height="60" fill={window} stroke="#0a0a0a" strokeWidth="0.8" opacity="0.8"/>
        {/* steps */}
        <rect x="245" y="410" width="90" height="6"  fill="#d2cec6"/>
        <rect x="260" y="415" width="50" height="6"  fill="#c2bdb4"/>
      </g>

      {/* sun */}
      {!isDark && <circle cx="150" cy="80" r="28" fill="#fff5d8" opacity="0.85"/>}
      {isDark && <circle cx="730" cy="100" r="22" fill="#e8d8b8" opacity="0.6"/>}
    </svg>
  );
};

// ── スウォッチ (改善版) ─────────────────────
const Swatch = ({ option, selected, onClick, size = 'md' }) => {
  const dims = { sm: 36, md: 48, lg: 64 }[size];
  return (
    <button
      onClick={onClick}
      className={`swatch ${selected ? 'is-selected' : ''}`}
      title={option.name}
      style={{ ['--swatch-size']: dims + 'px' }}
    >
      <span className="swatch-chip" style={{ background: option.hex }}>
        {selected && (
          <span className="swatch-check">
            <Icon name="check" size={14}/>
          </span>
        )}
      </span>
      <span className="swatch-label">
        <span className="swatch-name">{option.name}</span>
        {option.sub && <span className="swatch-sub">{option.sub}</span>}
        {option.tag && <span className="swatch-tag">{option.tag}</span>}
      </span>
    </button>
  );
};

// ── Section (折りたたみ) ────────────────────
const Section = ({ icon, title, count, defaultOpen = true, children, dense }) => {
  const [open, setOpen] = useState(defaultOpen);
  return (
    <section className={`section ${open ? 'is-open' : ''} ${dense ? 'is-dense' : ''}`}>
      <button className="section-head" onClick={() => setOpen(!open)}>
        <span className="section-head-left">
          {icon && <Icon name={icon} size={15}/>}
          <span className="section-title">{title}</span>
          {count != null && <span className="section-count">{count}</span>}
        </span>
        <Icon name={open ? 'chevDown' : 'chevRight'} size={15}/>
      </button>
      {open && <div className="section-body">{children}</div>}
    </section>
  );
};

// ── メトリクス値表示 ────────────────────────
const Metric = ({ label, value, unit, hint, trend }) => (
  <div className="metric">
    <div className="metric-label">{label}</div>
    <div className="metric-value">
      <span className="metric-num">{value}</span>
      {unit && <span className="metric-unit">{unit}</span>}
    </div>
    {hint && <div className="metric-hint">{hint}</div>}
  </div>
);

// ── ビューポート（iframe 3D + 平面図 / 性能ダッシュボード）──
// 外観と内装の iframe を常時保持（遅延初期化）し、display: none/block で切替する。
// これにより外観 ⇔ 内装の切替時に iframe の再読み込みが不要になりパフォーマンスが向上する。
const Viewport = ({ theme, viewMode, onViewModeChange, mode = 'exterior', spec, chromeStyle = 'floating' }) => {
  const extRef = useRef(null);
  const intRef = useRef(null);
  // 内装は初回アクセス時だけ iframe を生成（遅延初期化）
  const [intInited, setIntInited] = useState(false);

  // 内装モードへ初めて遷移したとき iframe を生成
  useEffect(() => {
    if (mode === 'interior' && !intInited) setIntInited(true);
  }, [mode, intInited]);

  // 内装 iframe をアイドル時にバックグラウンド先読み（初回切替を即時化）
  // 外観の初期表示を妨げないよう requestIdleCallback で遅延ロードする
  useEffect(() => {
    if (intInited) return;
    const ric = window.requestIdleCallback || ((cb) => setTimeout(cb, 1200));
    const cic = window.cancelIdleCallback || clearTimeout;
    const id = ric(() => setIntInited(true), { timeout: 4000 });
    return () => cic(id);
  }, [intInited]);

  // 外観モード: viewMode が変わったら iframe 内 setMode() に転送
  useEffect(() => {
    if (mode !== 'exterior') return;
    const f = extRef.current;
    if (!f) return;
    let cancelled = false;
    const apply = () => {
      if (cancelled) return;
      try {
        const w = f.contentWindow;
        if (w && typeof w.setMode === 'function') {
          w.setMode(viewMode);
        } else {
          setTimeout(apply, 120);
        }
      } catch (e) { /* sandbox */ }
    };
    apply();
    const onLoad = () => apply();
    f.addEventListener('load', onLoad);
    return () => { cancelled = true; f.removeEventListener('load', onLoad); };
  }, [mode, viewMode]);

  // モード切替時: 表示中の iframe に resize イベントを通知（Three.js が再計算）
  useEffect(() => {
    const f = mode === 'interior' ? intRef.current : extRef.current;
    if (!f) return;
    const t = setTimeout(() => {
      try { f.contentWindow?.dispatchEvent(new Event('resize')); } catch (e) {}
    }, 60);
    return () => clearTimeout(t);
  }, [mode]);

  const openEditMode = () => {
    try {
      const w = extRef.current?.contentWindow;
      if (w && typeof w.toggleEdit === 'function') w.toggleEdit();
    } catch (e) { /* iframe not ready */ }
  };

  // 性能モードは独自ダッシュボード（3D は使わない）。
  // ※ hooks はすべてこのブランチより前に記述しておく必要がある（React Rules of Hooks）
  if (mode === 'perf') {
    return <PerformanceViewport theme={theme}/>;
  }

  const isPlanView = mode === 'exterior' && (viewMode === '1f' || viewMode === '2f');

  return (
    <div className="viewport" data-mode={mode}>
      {/* 外観 iframe — 常時ロード済み、内装時は非表示 */}
      <iframe
        ref={extRef}
        src="3d-app/index.html?embed=1"
        title={isPlanView ? `${viewMode === '2f' ? '2F' : '1F'}平面図` : '外観3Dビュー'}
        className="viewport-iframe"
        data-iframe-type="exterior"
        style={{ display: mode === 'interior' ? 'none' : 'block' }}
      />
      {/* 内装 iframe — 初回アクセス時に遅延生成し、外観時は非表示 */}
      {intInited && (
        <iframe
          ref={intRef}
          src="3d-app/rooms.html"
          title="内装3Dビュー"
          className="viewport-iframe"
          data-iframe-type="interior"
          style={{ display: mode === 'interior' ? 'block' : 'none' }}
        />
      )}

      {/* View mode pill: 外観時のみ (3D ⇔ 平面図 切替) */}
      {chromeStyle !== 'minimal' && mode === 'exterior' && (
        <div className="vp-mode-pill">
          {[
            { id: 'ext', label: '外観',   icon: 'cube' },
            { id: '1f',  label: '1F平面', icon: 'floor' },
            { id: '2f',  label: '2F平面', icon: 'floor' },
          ].map(m => (
            <button
              key={m.id}
              className={`vp-mode-btn ${viewMode === m.id ? 'is-active' : ''}`}
              onClick={() => onViewModeChange?.(m.id)}
            >
              <Icon name={m.icon} size={14}/>
              <span>{m.label}</span>
            </button>
          ))}
        </div>
      )}

      {/* Hint */}
      <div className="vp-hint">
        <Icon name={isPlanView ? 'floor' : 'rotate'} size={12}/>
        <span>
          {isPlanView
            ? '平面図 · 寸法/窓/間取りは元データを反映 · 右上の編集モードから修正可'
            : mode === 'interior'
              ? '部屋カードをクリックで切替  /  ドラッグで視点回転'
              : 'ドラッグで回転  /  スクロールでズーム  /  右ドラッグで平行移動 · 左上コンパスで方位を確認'}
        </span>
      </div>

      {/* Viewport tools */}
      <div className="vp-tools">
        {mode === 'exterior' && (
          <button title="編集モード — 寸法・窓・配置を手動修正" onClick={openEditMode}>
            <Icon name="edit" size={14}/>
          </button>
        )}
        <button title="ズーム拡大"><Icon name="plus" size={14}/></button>
        <button title="リセット視点"><Icon name="reset" size={14}/></button>
        <button title="フルスクリーン" onClick={() => window.open(mode === 'interior' ? '3d-app/rooms.html' : '3d-app/index.html', '_blank')}>
          <Icon name="expand" size={14}/>
        </button>
      </div>
    </div>
  );
};

// ── 性能ダッシュボード(性能モード専用ビュー) ──
// visualizer-perf.jsx で組み立てた PerformancePage を呼び出す
//  - 既存の React 製 6カードサマリーは PerformancePage の「性能サマリー」タブとして保持
//  - 元リポジトリ cost.html の 設備選択 / 動線 / コスト / 設計指針 もタブとして合流
const PerformanceViewport = ({ theme }) => {
  if (window.HV && window.HV.PerformancePage) {
    const Comp = window.HV.PerformancePage;
    return <Comp theme={theme}/>;
  }
  return <div className="perf-viewport"><div style={{ padding: 40, color: 'var(--ink-3)' }}>性能ページ読込中...</div></div>;
};

// ── 旧: React 製ダッシュボード (参考保持) ──
const PerformanceViewport_React = ({ theme }) => {
  return (
    <div className="viewport perf-viewport" data-mode="perf">
      <div className="perf-grid">
        {/* 大きいUA値カード + 等級バー */}
        <div className="perf-card perf-card-hero">
          <div className="perf-card-eyebrow">熱損失係数 UA</div>
          <div className="perf-hero-value">
            <span className="serif" style={{ fontSize: 80, lineHeight: 1, fontWeight: 700 }}>0.42</span>
            <span style={{ fontSize: 14, color: 'var(--ink-3)', marginLeft: 8 }}>W/m²K</span>
          </div>
          <div style={{ marginTop: 20 }}>
            <div className="perf-grade-bar">
              <div className="perf-grade-segment" data-active="true">  <span>HEAT20 G3</span><span className="mono">≤0.34</span></div>
              <div className="perf-grade-segment" data-active="current">  <span>HEAT20 G2 ★</span><span className="mono">≤0.46</span></div>
              <div className="perf-grade-segment">                       <span>HEAT20 G1</span><span className="mono">≤0.56</span></div>
              <div className="perf-grade-segment">                       <span>ZEH</span><span className="mono">≤0.60</span></div>
              <div className="perf-grade-segment">                       <span>4等級</span><span className="mono">≤0.87</span></div>
            </div>
          </div>
          <div className="perf-card-foot">本住宅は HEAT20 G2 グレード相当 — 6地域での推奨水準を満たしています</div>
        </div>

        {/* 気密 C値 */}
        <div className="perf-card">
          <div className="perf-card-eyebrow">気密性能 C値</div>
          <div className="perf-card-value-row">
            <span className="serif" style={{ fontSize: 44, fontWeight: 700, lineHeight: 1 }}>0.5</span>
            <span style={{ fontSize: 11, color: 'var(--ink-3)' }}>cm²/m²</span>
          </div>
          <div className="perf-mini-bar">
            <div style={{ width: '92%', background: 'var(--positive)' }}/>
          </div>
          <div style={{ fontSize: 11, color: 'var(--ink-3)', marginTop: 6 }}>業界平均 (2.0) より優秀 · 高気密住宅基準クリア</div>
        </div>

        {/* 冷房日射 ηAC */}
        <div className="perf-card">
          <div className="perf-card-eyebrow">冷房期 日射取得率 ηAC</div>
          <div className="perf-card-value-row">
            <span className="serif" style={{ fontSize: 44, fontWeight: 700, lineHeight: 1 }}>1.6</span>
            <span style={{ fontSize: 11, color: 'var(--ink-3)' }}>—</span>
          </div>
          <div className="perf-mini-bar">
            <div style={{ width: '78%', background: 'var(--positive)' }}/>
          </div>
          <div style={{ fontSize: 11, color: 'var(--ink-3)', marginTop: 6 }}>日射遮蔽 良好 · 6地域基準 (2.8以下) 余裕クリア</div>
        </div>

        {/* 日照ヒートマップ風 */}
        <div className="perf-card perf-card-sun">
          <div className="perf-card-eyebrow">日照シミュレーション · 冬至</div>
          <div className="perf-sun-grid">
            <div className="perf-sun-face">
              <div className="perf-sun-label">北面</div>
              <div className="perf-sun-cell" style={{ background: `linear-gradient(180deg, var(--bg-2) 88%, oklch(0.75 0.10 70) 100%)` }}>
                <span className="mono">12%</span>
              </div>
            </div>
            <div className="perf-sun-face">
              <div className="perf-sun-label">東面</div>
              <div className="perf-sun-cell" style={{ background: `linear-gradient(180deg, var(--bg-2) 36%, oklch(0.72 0.13 75) 100%)` }}>
                <span className="mono">64%</span>
              </div>
            </div>
            <div className="perf-sun-face">
              <div className="perf-sun-label">南面 ★</div>
              <div className="perf-sun-cell" style={{ background: `linear-gradient(180deg, var(--bg-2) 8%, oklch(0.78 0.16 75) 100%)` }}>
                <span className="mono">92%</span>
              </div>
            </div>
            <div className="perf-sun-face">
              <div className="perf-sun-label">西面</div>
              <div className="perf-sun-cell" style={{ background: `linear-gradient(180deg, var(--bg-2) 62%, oklch(0.68 0.13 70) 100%)` }}>
                <span className="mono">38%</span>
              </div>
            </div>
          </div>
          <div className="perf-sun-foot">南面の日射取得が良好 · LDK・主寝室は冬季暖房負荷を抑制できる配置</div>
        </div>

        {/* エネルギー消費 */}
        <div className="perf-card">
          <div className="perf-card-eyebrow">一次エネルギー消費</div>
          <div className="perf-card-value-row">
            <span className="serif" style={{ fontSize: 44, fontWeight: 700, lineHeight: 1 }}>71</span>
            <span style={{ fontSize: 11, color: 'var(--ink-3)' }}>GJ/年</span>
          </div>
          <div className="perf-bar-stack">
            <div title="冷房" style={{ width: '20%', background: 'oklch(0.72 0.12 230)' }}><span>冷 14.2</span></div>
            <div title="暖房" style={{ width: '26%', background: 'oklch(0.66 0.13 25)' }}><span>暖 18.6</span></div>
            <div title="給湯" style={{ width: '32%', background: 'oklch(0.62 0.10 80)' }}><span>給湯 22.4</span></div>
            <div title="家電・照明" style={{ width: '22%', background: 'oklch(0.55 0.07 105)' }}><span>家電 15.8</span></div>
          </div>
          <div style={{ fontSize: 11, color: 'var(--ink-3)', marginTop: 4 }}>ZEH基準比 -28%</div>
        </div>

        {/* 太陽軌跡 */}
        <div className="perf-card perf-card-sunpath">
          <div className="perf-card-eyebrow">太陽軌跡 · 冬至/夏至</div>
          <SunPathSVG/>
        </div>
      </div>
    </div>
  );
};

const SunPathSVG = () => (
  <svg viewBox="0 0 320 200" style={{ width: '100%', height: '100%' }}>
    <defs>
      <radialGradient id="skyG" cx="50%" cy="100%" r="80%">
        <stop offset="0" stopColor="var(--bg-2)" stopOpacity="0.8"/>
        <stop offset="1" stopColor="var(--bg-2)" stopOpacity="0.2"/>
      </radialGradient>
    </defs>
    <rect width="320" height="200" fill="url(#skyG)" rx="6"/>
    {/* horizon */}
    <line x1="20" y1="180" x2="300" y2="180" stroke="var(--ink-3)" strokeWidth="1" opacity="0.4"/>
    <text x="160" y="195" textAnchor="middle" fontSize="9" fill="var(--ink-3)">N ← 地平線 → S</text>
    {/* sun paths */}
    <path d="M 30 175 Q 160 60 290 175" fill="none" stroke="oklch(0.72 0.16 75)" strokeWidth="2" opacity="0.9"/>
    <path d="M 30 175 Q 160 120 290 175" fill="none" stroke="oklch(0.55 0.07 105)" strokeWidth="2" opacity="0.7" strokeDasharray="4,3"/>
    {/* hour marks */}
    {[6, 9, 12, 15, 18].map((h, i) => {
      const t = i / 4;
      const x = 30 + t * 260;
      const summerY = 175 - Math.sin(t * Math.PI) * 115;
      const winterY = 175 - Math.sin(t * Math.PI) * 55;
      return (
        <g key={h}>
          <circle cx={x} cy={summerY} r="3" fill="oklch(0.78 0.18 75)"/>
          <circle cx={x} cy={winterY} r="2" fill="oklch(0.55 0.07 105)"/>
          <text x={x} y={summerY - 7} textAnchor="middle" fontSize="9" fill="var(--ink-2)">{h}時</text>
        </g>
      );
    })}
    {/* legend */}
    <g transform="translate(20, 16)">
      <line x1="0" y1="6" x2="20" y2="6" stroke="oklch(0.72 0.16 75)" strokeWidth="2"/>
      <text x="24" y="10" fontSize="10" fill="var(--ink-2)">夏至</text>
      <line x1="60" y1="6" x2="80" y2="6" stroke="var(--ink-2)" strokeWidth="2" strokeDasharray="4,3"/>
      <text x="84" y="10" fontSize="10" fill="var(--ink-2)">冬至</text>
    </g>
  </svg>
);

// ── 表示モードバー（外観 / 内装 / 性能）──
const ModeSwitch = ({ mode, onChange, includeSub = true }) => {
  const items = [
    { id: 'exterior', label: '外観',    sub: '仕上げ・外構', icon: 'cube' },
    { id: 'interior', label: '内装',    sub: '部屋・配置',   icon: 'floor' },
    { id: 'perf',     label: '性能',    sub: '日照・断熱',   icon: 'sun' },
  ];
  return (
    <div className="mode-switch">
      {items.map(it => (
        <button
          key={it.id}
          className={`mode-tab ${mode === it.id ? 'is-active' : ''}`}
          onClick={() => onChange?.(it.id)}
        >
          <Icon name={it.icon} size={16}/>
          <div className="mode-tab-text">
            <span className="mode-tab-label">{it.label}</span>
            {includeSub && <span className="mode-tab-sub">{it.sub}</span>}
          </div>
        </button>
      ))}
    </div>
  );
};

// ── トップバー ─────────────────────────────
const TopBar = ({ theme, onThemeToggle, mode, onModeChange, density, onDensityToggle, layout, onLayoutChange, showModeSwitch = true }) => (
  <header className="topbar">
    <div className="topbar-l">
      <div className="brand">
        <div className="brand-mark">
          <svg viewBox="0 0 28 28" width="22" height="22">
            <path d="M4 14 L14 5 L24 14 L24 24 L4 24 Z" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinejoin="round"/>
            <path d="M11 24 L11 16 L17 16 L17 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinejoin="round"/>
          </svg>
        </div>
        <div className="brand-text">
          <div className="brand-name serif">住宅最適設計</div>
          <div className="brand-sub">{projectMeta.name}</div>
        </div>
      </div>
      {/* モード切替は下部ドックに一本化する場合は showModeSwitch=false（左上コンパスとの重なり回避） */}
      {showModeSwitch && <div className="topbar-divider"/>}
      {showModeSwitch && <ModeSwitch mode={mode} onChange={onModeChange}/>}
    </div>
    <div className="topbar-r">
      <div className="topbar-meta">
        <span className="t-eyebrow">PROJECT</span>
        <span className="t-value">{projectMeta.client}</span>
      </div>
      <button className="icon-btn" title="仕様をコピー"><Icon name="copy" size={16}/></button>
      <button className="icon-btn" title="PDFエクスポート"><Icon name="download" size={16}/></button>
      <button className="icon-btn" title={theme === 'dark' ? 'ライトモード' : 'ダークモード'} onClick={onThemeToggle}>
        <Icon name="theme" size={16}/>
      </button>
    </div>
  </header>
);

// ── Status bar (下部) ──────────────────────
const StatusBar = () => (
  <footer className="statusbar">
    <span className="status-chip"><Icon name="check" size={12}/> 自動保存済み · 14:32</span>
    <span className="status-chip">仕様打合せ2回目4.26.pdf 準拠</span>
    <span className="status-divider"/>
    <span className="status-chip mono">UA 0.42 W/m²K</span>
    <span className="status-chip mono">C値 0.5 cm²/m²</span>
    <span className="status-chip mono">延床 168.4 m²</span>
    <span className="status-spacer"/>
    <span className="status-chip">v12 — 屋根一体化・階段連動</span>
  </footer>
);

// Export to window for use across files
window.HV = Object.assign(window.HV || {}, {
  Icon, Swatch, Section, Metric, Viewport, ModeSwitch, TopBar, StatusBar, HouseSVG, FloorPlanSVG, SunPathSVG,
  WALL_COLORS, ROOF_COLORS, SOFFIT_COLORS, FRAME_COLORS, DOOR_STYLES, CARPORT_OPTS, DECK_COLORS, LAWN_COLORS,
  initialSpec, projectMeta,
});
