Newer
Older
client_dwatch / d-watch-mock.jsx
import { useState } from "react";

const DARK = {
  bg: "#0f1419", sf: "#1a2332", sfH: "#1e2a3a", bd: "#2a3a4e",
  pr: "#3b82f6", prD: "#1e3a5f", ok: "#22c55e", okD: "#0a3d1f",
  wn: "#f59e0b", wnD: "#3d2a06", ng: "#ef4444", ngD: "#3d1111",
  ngB: "#ff6b6b", tx: "#e2e8f0", txD: "#94a3b8", txM: "#64748b", ac: "#06b6d4"
};
const LIGHT = {
  bg: "#f1f5f9", sf: "#ffffff", sfH: "#f8fafc", bd: "#e2e8f0",
  pr: "#2563eb", prD: "#dbeafe", ok: "#16a34a", okD: "#dcfce7",
  wn: "#d97706", wnD: "#fef3c7", ng: "#dc2626", ngD: "#fee2e2",
  ngB: "#dc2626", tx: "#1e293b", txD: "#475569", txM: "#94a3b8", ac: "#0891b2"
};

const LOG = [
  { f: "MEGAドンキ渋谷本店", m: "PUDU CC1", s: "8111R5628060011", d: "3/27", t: "02:00", h1: "充電中", h30: "待機中", dp: true, cp: 92, g: "◎" },
  { f: "ドンキ新宿歌舞伎町店", m: "PUDU CC1", s: "8111R5628060022", d: "3/27", t: "02:00", h1: "ハンドルアップ", h30: "ハンドルアップ", dp: false, cp: 0, g: "×" },
  { f: "MEGAドンキ池袋駅北口店", m: "PUDU CC1", s: "8111R5628060033", d: "3/27", t: "01:30", h1: "待機中", h30: "待機中", dp: true, cp: 45, g: "△" },
  { f: "ドンキ中目黒本店", m: "PUDU CC1", s: "8111R5628060044", d: "3/27", t: "03:00", h1: "待機中", h30: "待機中", dp: false, cp: 0, g: "×" },
  { f: "MEGAドンキ港山下総本店", m: "PUDU CC1", s: "8111R5628060055", d: "3/27", t: "02:00", h1: "待機中", h30: "待機中", dp: true, cp: 35, g: "△" },
  { f: "ドンキ八王子駅前店", m: "PUDU CC1", s: "8111R5628060077", d: "3/27", t: "02:30", h1: "オフライン", h30: "オフライン", dp: false, cp: 0, g: "×" },
  { f: "ドンキ町田店", m: "PUDU CC1", s: "8111R5628060088", d: "3/27", t: "03:00", h1: "待機中", h30: "待機中", dp: false, cp: 0, g: "×" },
  { f: "MEGAドンキ立川店", m: "PUDU CC1", s: "8111R5628060099", d: "3/27", t: "01:30", h1: "緊急停止", h30: "待機中", dp: true, cp: 62, g: "△" },
  { f: "MEGAドンキ吉祥寺店", m: "PUDU CC1", s: "8111R5628060122", t: "02:00", h1: "待機中", h30: "待機中", dp: true, cp: 96, g: "◎" },
  { f: "ドンキ三軒茶屋店", m: "PUDU CC1", s: "8111R5628060133", t: "02:30", h1: "待機中", h30: "待機中", dp: true, cp: 94, g: "◎" },
];

const PRECHK = [
  { id: 1, sev: "1h前異常", serial: "8111R5628060011", fac: "MEGAドンキ渋谷本店", sch: "02:00", st: "充電中", ok: true, at: "01:45", dt: "3/27 01:00", note: "30分前までに充電完了、出発成功" },
  { id: 2, sev: "1h前異常", serial: "8111R5628060022", fac: "ドンキ新宿歌舞伎町店", sch: "02:00", st: "ハンドルアップ", ok: false, at: "-", dt: "3/27 01:00", note: "30分前も未解消 → 出発失敗" },
  { id: 3, sev: "1h前異常", serial: "8111R5628060099", fac: "MEGAドンキ立川店", sch: "01:30", st: "緊急停止", ok: true, at: "01:10", dt: "3/27 00:30", note: "30分前に復旧、出発成功(完了率62%)" },
  { id: 4, sev: "1h前異常", serial: "8111R5628060077", fac: "ドンキ八王子駅前店", sch: "02:30", st: "オフライン", ok: false, at: "-", dt: "3/27 01:30", note: "30分前もオフライン → 出発失敗" },
  { id: 5, sev: "出発失敗", serial: "8111R5628060044", fac: "ドンキ中目黒本店", sch: "03:00", st: "セキュリティ有効", ok: false, at: "-", dt: "3/27 03:00", note: "セキュリティ解除されず出発不可" },
  { id: 6, sev: "出発失敗", serial: "8111R5628060088", fac: "ドンキ町田店", sch: "03:00", st: "セキュリティ有効", ok: false, at: "-", dt: "3/27 03:00", note: "セキュリティ解除されず出発不可" },
];

const DSA_INIT = [
  { id: 1, type: "セキュリティ無効", dev: "DS-001", fac: "MEGAドンキ渋谷本店", tm: "3/27 03:42", det: "清掃終了後もセキュリティが復帰していない", st: "未対応", mm: "" },
  { id: 2, type: "通信断", dev: "DS-005", fac: "MEGAドンキ大森山王店", tm: "3/27 02:55", det: "DS-005 が6時間以上通信なし", st: "未対応", mm: "" },
  { id: 3, type: "トークン期限", dev: "DS-004", fac: "MEGAドンキ港山下総本店", tm: "3/20", det: "DS-004 残り9日", st: "対応中", mm: "更新手続き中" },
  { id: 4, type: "セキュリティ無効", dev: "DS-003", fac: "ドンキ中目黒本店", tm: "3/26 03:55", det: "復帰遅延(10分後に復帰)", st: "対応済み", mm: "正常復帰を確認" },
];

const RANK = [
  { f: "ドンキ蒲田駅前店", ar: 68, arP: 75, dp: 72, dpP: 80, cv: 55, cvP: 62, er: 12.5, erP: 9.0, s: "要改善", cont: 5 },
  { f: "ドンキ八王子駅前店", ar: 72, arP: 70, dp: 65, dpP: 68, cv: 63, cvP: 60, er: 9.8, erP: 10.2, s: "要改善", cont: 3 },
  { f: "ドンキ新宿歌舞伎町店", ar: 78, arP: 82, dp: 82, dpP: 85, cv: 71, cvP: 78, er: 7.2, erP: 5.5, s: "注意", cont: 0 },
  { f: "MEGAドンキ立川店", ar: 85, arP: 83, dp: 90, dpP: 88, cv: 80, cvP: 78, er: 5.1, erP: 5.8, s: "注意", cont: 0 },
  { f: "MEGAドンキ池袋駅北口店", ar: 92, arP: 90, dp: 95, dpP: 93, cv: 88, cvP: 85, er: 3.2, erP: 4.0, s: "良好", cont: 0 },
  { f: "MEGAドンキ渋谷本店", ar: 96, arP: 95, dp: 98, dpP: 97, cv: 94, cvP: 92, er: 1.8, erP: 2.1, s: "良好", cont: 0 },
];

const ROBOTS = [
  { f: "MEGAドンキ渋谷本店", pref: "東京都", addr: "渋谷区宇田川町28-6", tel: "03-5428-4086", mgr: "山田 健一", staff: "小林 美咲", email: "shibuya@donki.co.jp", mon: true, dsec: true, bots: [{ mk: "PUDU", md: "CC1", sn: "8111R5628060011" }] },
  { f: "ドンキ新宿歌舞伎町店", pref: "東京都", addr: "新宿区歌舞伎町1-16-5", tel: "03-5291-9211", mgr: "高橋 誠", staff: "渡辺 翔", email: "shinjuku@donki.co.jp", mon: true, dsec: false, bots: [{ mk: "PUDU", md: "CC1", sn: "8111R5628060022" }] },
  { f: "MEGAドンキ池袋駅北口店", pref: "東京都", addr: "豊島区東池袋1-19-3", tel: "03-5957-3311", mgr: "伊藤 大輔", staff: "中村 拓也", email: "ikebukuro@donki.co.jp", mon: true, dsec: true, bots: [{ mk: "PUDU", md: "CC1", sn: "8111R5628060033" }] },
  { f: "ドンキ中目黒本店", pref: "東京都", addr: "目黒区上目黒2-6-1", tel: "03-5725-7532", mgr: "加藤 隆", staff: "佐々木 優", email: "nakameguro@donki.co.jp", mon: true, dsec: true, bots: [{ mk: "PUDU", md: "CC1", sn: "8111R5628060044" }] },
  { f: "MEGAドンキ港山下総本店", pref: "神奈川県", addr: "横浜市中区山下町194", tel: "045-650-6611", mgr: "松本 洋介", staff: "井上 真央", email: "yamashita@donki.co.jp", mon: true, dsec: true, bots: [{ mk: "PUDU", md: "CC1", sn: "8111R5628060055" }, { mk: "PUDU", md: "Phantas", sn: "8222P4527080066" }] },
  { f: "ドンキ八王子駅前店", pref: "東京都", addr: "八王子市旭町1-13", tel: "042-649-3611", mgr: "木村 達也", staff: "斎藤 愛", email: "hachioji@donki.co.jp", mon: true, dsec: false, bots: [{ mk: "PUDU", md: "CC1", sn: "8111R5628060077" }] },
  { f: "MEGAドンキ立川店", pref: "東京都", addr: "立川市曙町2-14-1", tel: "042-527-1811", mgr: "清水 健", staff: "森田 翼", email: "tachikawa@donki.co.jp", mon: true, dsec: true, bots: [{ mk: "PUDU", md: "CC1", sn: "8111R5628060099" }, { mk: "PUDU", md: "CC1", sn: "8111R5628060100" }, { mk: "Keenon", md: "T5", sn: "9333K7412050111" }] },
  { f: "MEGAドンキ吉祥寺店", pref: "東京都", addr: "武蔵野市吉祥寺本町1-1", tel: "0422-23-6211", mgr: "岡田 修", staff: "藤井 彩", email: "kichijoji@donki.co.jp", mon: true, dsec: false, bots: [{ mk: "PUDU", md: "CC1", sn: "8111R5628060122" }] },
  { f: "ドンキ三軒茶屋店", pref: "東京都", addr: "世田谷区太子堂4-1", tel: "03-5430-5811", mgr: "池田 正", staff: "西村 舞", email: "sangenjaya@donki.co.jp", mon: true, dsec: false, bots: [{ mk: "PUDU", md: "CC1", sn: "8111R5628060133" }] },
];

const SCHED = [
  { s: "8111R5628060011", f: "MEGAドンキ渋谷本店", d: "毎日", st: "02:00", en: "03:00", on: true },
  { s: "8111R5628060022", f: "ドンキ新宿歌舞伎町店", d: "毎日", st: "02:00", en: "02:45", on: true },
  { s: "8111R5628060044", f: "ドンキ中目黒本店", d: "月水金", st: "03:00", en: "03:45", on: true },
  { s: "8111R5628060077", f: "ドンキ八王子駅前店", d: "毎日", st: "02:30", en: "03:15", on: false },
];

const DSDEV = [
  { id: "DS-001", f: "MEGAドンキ渋谷本店", st: "異常", lc: "3/27 03:42", te: "2026-06-15", n: "セキュリティ復帰失敗" },
  { id: "DS-002", f: "MEGAドンキ池袋駅北口店", st: "正常", lc: "3/27 09:01", te: "2026-08-20", n: "" },
  { id: "DS-003", f: "ドンキ中目黒本店", st: "正常", lc: "3/27 09:00", te: "2026-07-10", n: "" },
  { id: "DS-004", f: "MEGAドンキ港山下総本店", st: "正常", lc: "3/27 08:55", te: "2026-04-05", n: "" },
  { id: "DS-005", f: "MEGAドンキ大森山王店", st: "通信断", lc: "3/27 02:55", te: "2026-07-20", n: "6時間以上通信なし" },
];
var INSP_ITEMS = ["ブラシ", "ダストボックス", "フィルター", "スクイジー", "吸引ホース", "汚水タンク", "ブラシ裏面"];
const INSPECTIONS = [
  { id: 1, date: "2026/03/11", inspector: "香原秀俊", company: "DFA Robotics", brand: "ドン・キホーテ", facility: "MEGAUNY西大和店", robot: "8111R5628060011", notes: "" },
  { id: 2, date: "2026/03/11", inspector: "香原秀俊", company: "DFA Robotics", brand: "ドン・キホーテ", facility: "アピタ大和郡山店", robot: "8111R5628060022", notes: "" },
  { id: 3, date: "2026/03/11", inspector: "香原秀俊", company: "DFA Robotics", brand: "ドン・キホーテ", facility: "アピタ伊賀上野店", robot: "8111R5628060033", notes: "副店長様より、以前水漏れがしていて何度かメンテナンスをしてもらったとのこと。現状は改善されているとのことで、今回メンテナンス時も異常なし" },
  { id: 4, date: "2026/03/11", inspector: "香原秀俊", company: "DFA Robotics", brand: "ドン・キホーテ", facility: "MEGAUNY名張店", robot: "8111R5628060044", notes: "" },
  { id: 5, date: "2026/03/16", inspector: "香原秀俊", company: "DFA Robotics", brand: "ドン・キホーテ", facility: "アピタ松阪三雲店", robot: "8111R5628060055", notes: "" },
  { id: 6, date: "2026/03/16", inspector: "香原秀俊", company: "DFA Robotics", brand: "ユニー", facility: "MEGAUNY星川店", robot: "8111R5628060066", notes: "" },
  { id: 7, date: "2026/03/16", inspector: "香原秀俊", company: "DFA Robotics", brand: "ドン・キホーテ", facility: "アピタ桑名店", robot: "8111R5628060077", notes: "" },
];

function Pill({ text, color }) {
  return (
    <span style={{ fontSize: 12, padding: "2px 8px", borderRadius: 4, background: color + "22", color: color }}>
      {text}
    </span>
  );
}

function Num({ value, label, sub, color, onClick, c }) {
  return (
    <div onClick={onClick} style={{ background: c.sf, border: "1px solid " + c.bd, borderRadius: 12, padding: "20px 24px", cursor: onClick ? "pointer" : "default", borderLeft: "3px solid " + color }}>
      <div style={{ fontSize: 11, color: c.txM, textTransform: "uppercase", letterSpacing: 1.2, marginBottom: 8 }}>{label}</div>
      <div style={{ fontSize: 36, fontWeight: 700, color: color, lineHeight: 1 }}>{value}</div>
      {sub && <div style={{ fontSize: 12, color: c.txD, marginTop: 6 }}>{sub}</div>}
    </div>
  );
}

function stColor(c, v) {
  if (v === "待機中") return c.ok;
  if (v === "充電中") return c.pr;
  if (v === "ハンドルアップ" || v === "緊急停止" || v === "オフライン") return c.ng;
  if (v === "セキュリティ有効") return c.ac;
  return c.txD;
}

function gradeStyle(c, g) {
  if (g === "◎" || g === "○") return { bg: c.okD, tx: c.ok };
  if (g === "△") return { bg: c.wnD, tx: c.wn };
  return { bg: c.ngD, tx: c.ng };
}

export default function App() {
  const [page, setPage] = useState("dashboard");
  const [dark, setDark] = useState(true);
  const [lang, setLang] = useState("ja");
  var T = {
    "DFAロボット監視システム": "DFA Robot Monitoring System", "DFA運用担当": "DFA Operator",
    "📊 ダッシュボード": "📊 Dashboard", "📋 清掃詳細ログ": "📋 Cleaning Logs", "🔔 アラート": "🔔 Alerts", "📈 レポート": "📈 Reports", "🔧 点検記録": "🔧 Inspections",
    "🔒 D-Secログ": "🔒 D-Sec Logs", "⚠ D-Secアラート": "⚠ D-Sec Alerts",
    "🏢 施設ロボットマスタ": "🏢 Facility Master", "📅 スケジュール": "📅 Schedules", "⚙ システム管理": "⚙ System Admin",
    "モニタリング": "MONITORING", "設定": "SETTINGS",
    "施設名": "Facility", "機種": "Model", "シリアル": "Serial", "日付": "Date", "予定": "Scheduled", "出発": "Dep.", "完了率": "Completion", "判定": "Grade",
    "接続状態": "Status", "最終通信": "Last Comm.", "トークン期限": "Token Expiry", "残日数": "Days Left", "備考": "Notes", "操作": "Actions",
    "会社名": "Company", "グループ名": "Group", "連絡先": "Contact", "契約プラン": "Plan", "契約モジュール": "Modules", "状態": "Status", "ステータス": "Status",
    "名前": "Name", "メール": "Email", "ロール": "Role", "会社": "Company", "施設": "Facility", "訪問日": "Visit Date", "記入者": "Inspector", "所属会社": "Org.", "店舗名": "Store", "ブランド": "Brand", "申し送り": "Notes",
    "ダッシュボード": "Dashboard", "清掃詳細ログ": "Cleaning Detail Log", "アラート(事前チェック)": "Alerts (Pre-check)", "レポート": "Reports", "D-Sec ログ": "D-Sec Logs", "D-Security アラート": "D-Security Alerts", "施設ロボットマスタ": "Facility Robot Master", "スケジュール管理": "Schedule Mgmt", "システム管理": "System Admin", "点検記録": "Inspection Records",
    "CSVエクスポート": "CSV Export", "CSV": "CSV", "検索": "Search", "閉じる": "Close", "キャンセル": "Cancel", "保存": "Save", "登録": "Register", "編集": "Edit", "削除": "Delete", "詳細": "Detail",
    "全グループ": "All Groups", "全会社": "All Companies", "全件": "All", "全ステータス": "All Status", "全種別": "All Types", "全て": "All",
    "未解消のみ": "Unresolved", "解消済み": "Resolved", "未対応・対応中": "Open / In Progress", "対応済み": "Done", "△×のみ": "△× Only", "×のみ": "× Only",
    "問題エリアのみ": "Problems Only",
    "未解消": "Unresolved", "要対応": "Action Needed", "合計": "Total", "全アラート": "All Alerts", "対応完了": "Completed", "未対応": "Open", "即時対応": "Urgent", "対応中": "In Progress", "進行中": "Ongoing", "完了": "Done",
    "正常稼働": "Normal", "異常・通信断": "Error / Offline", "D-Sデバイス総数": "Total Devices",
    "週次": "Weekly", "月次": "Monthly", "稼働率": "Uptime", "出発成功率": "Dep. Rate", "清掃完了率": "Completion", "エラー発生率": "Error Rate",
    "連続問題施設": "Recurring Issues", "エラー種別の内訳": "Error Breakdown", "施設別パフォーマンス(稼働率ワースト順)": "Facility Performance (Worst Uptime)",
    "表示設定": "Display", "通知設定": "Notifications", "ユーザー管理": "Users", "権限管理": "Permissions", "顧客管理": "Customers", "グループ管理": "Groups", "運用設定": "Operations", "監査ログ": "Audit Log",
    "要改善": "Needs Fix", "注意": "Caution", "良好": "Good", "有効": "Active", "停止": "Inactive",
    "事前チェック設定": "Pre-check Timing", "完了率の判定閾値": "Completion Thresholds", "アドバイス エスカレーション閾値": "Escalation Thresholds", "分前": "min before", "日以上連続": "consecutive days+",
    "+ 新規登録": "+ New Record", "+ 顧客追加": "+ Add Customer", "+ グループ追加": "+ Add Group", "📥 CSVインポート": "📥 CSV Import",
    "エリア別詳細を見る →": "View Area Details →", "エリア別清掃完了率": "Area Completion Rates",
    "点検記録 詳細": "Inspection Detail", "点検記録 新規登録": "New Inspection", "総点検数": "Total", "期間内": "In Period", "点検施設数": "Facilities", "ユニーク": "Unique", "申し送りあり": "Has Notes", "要確認": "Review", "あり": "Yes",
    "スケジュール開始前のエラー検知と出発失敗": "Pre-schedule error detection and departure failures",
    "セキュリティ無効・通信断・トークン期限のアラート管理": "Security / connection / token alerts",
    "定期点検の実施記録・写真・申し送り事項を管理": "Manage inspection records, photos and notes",
    "申し送り事項": "Notes", "Before(点検前)": "Before", "After(点検後)": "After",
  };
  function t(s) { return lang === "en" && T[s] ? T[s] : s; }
  const [dFilt, setDFilt] = useState("problem");
  const [lFilt, setLFilt] = useState("problem");
  const [lSF, setLSF] = useState("");
  const [lSM, setLSM] = useState("");
  const [lSS, setLSS] = useState("");
  const [aFilt, setAFilt] = useState("unresolved");
  const [daFilt, setDaFilt] = useState("unresolved");
  const [dsaState, setDsaState] = useState(DSA_INIT);
  const [rSrch, setRSrch] = useState("");
  const [sSrch, setSSrch] = useState("");
  const [showDS, setShowDS] = useState(true);
  const [sysTab, setSysTab] = useState("display");
  const [dashItems, setDashItems] = useState({ secBanner: true, detailLog: true, scheduleBar: true, failBreakdown: true });
  const [showGradeInfo, setShowGradeInfo] = useState(false);
  const [custEdit, setCustEdit] = useState(null);
  const [userEdit, setUserEdit] = useState(null);
  const [grpEdit, setGrpEdit] = useState(null);
  const [expandedRow, setExpandedRow] = useState(null);
  const [areaModal, setAreaModal] = useState(null);
  const [areaFilt, setAreaFilt] = useState("problem");
  const [rptPeriod, setRptPeriod] = useState("weekly");
  const [showAllRank, setShowAllRank] = useState(false);
  const [showAllCont, setShowAllCont] = useState(false);
  const [dsLogFilt, setDsLogFilt] = useState("all");
  const [dsaTypeFilt, setDsaTypeFilt] = useState("all");
  const [inspDetail, setInspDetail] = useState(null);
  const [inspNew, setInspNew] = useState(false);

  const c = dark ? DARK : LIGHT;

  const unresPre = PRECHK.filter(function (a) { return !a.ok; }).length;
  const unresDsa = dsaState.filter(function (a) { return a.st === "未対応" || a.st === "対応中"; }).length;

  function cycleDsa(id) {
    setDsaState(function (prev) {
      return prev.map(function (a) {
        if (a.id !== id) return a;
        var nx = "未対応";
        if (a.st === "未対応") nx = "対応中";
        if (a.st === "対応中") nx = "対応済み";
        if (a.st === "対応済み") nx = "未対応";
        return Object.assign({}, a, { st: nx });
      });
    });
  }

  function filt(data, grade, sf, sm, ss) {
    var d = data;
    if (grade === "problem") d = d.filter(function (r) { return r.g === "△" || r.g === "×"; });
    else if (grade !== "all") d = d.filter(function (r) { return r.g === grade; });
    if (sf) d = d.filter(function (r) { return r.f.toLowerCase().indexOf(sf.toLowerCase()) >= 0; });
    if (sm) d = d.filter(function (r) { return r.m.toLowerCase().indexOf(sm.toLowerCase()) >= 0; });
    if (ss) d = d.filter(function (r) { return r.s.toLowerCase().indexOf(ss.toLowerCase()) >= 0; });
    return d;
  }

  var th = { padding: "10px 12px", fontSize: 11, color: c.txM, textTransform: "uppercase", letterSpacing: 0.6, borderBottom: "1px solid " + c.bd, whiteSpace: "nowrap" };
  var td = { padding: "12px", fontSize: 13, color: c.tx };
  var tdm = { padding: "12px", fontSize: 13, color: c.txD };

  function BtnF(props) {
    var active = props.active;
    var color = props.color;
    return (
      <button onClick={props.onClick} style={{ fontSize: 12, padding: "4px 12px", borderRadius: 6, cursor: "pointer", border: "1px solid " + (active ? color : c.bd), background: active ? color + "22" : "transparent", color: active ? color : c.txM }}>
        {props.children}
      </button>
    );
  }

  function getAdvice(row) {
    var advices = [];
    if (!row.dp && row.cp === 0) {
      advices.push({ level: 1, icon: "⚠", title: "出発失敗(R1)", text: "事前チェックのアラート内容を確認してください。セキュリティ未解除/ロボット異常/充電不足のいずれかが原因です。" });
    }
    if (row.cp > 0 && row.cp < 10) {
      advices.push({ level: 1, icon: "⚠", title: "完了率が極端に低い(R2)", text: "現場の通路状況+ロボット状態を確認してください。出発直後に停止した可能性があります。" });
    }
    if (row.cp >= 10 && row.cp < 70) {
      advices.push({ level: 1, icon: "⚠", title: "マップ更新の確認", text: "マップがレイアウト変更に追従していない可能性があります。直近の棚替え・売場変更がなかったか現場に確認してください。" });
    }
    if (row.g === "△") {
      advices.push({ level: 2, icon: "🔶", title: "2日連続で完了率低下(R3)", text: "恒常的な環境変化の可能性があります。現場責任者に状況をヒアリングしてください。" });
    }
    if (row.g === "×" && !row.dp) {
      advices.push({ level: 3, icon: "🔴", title: "複数日連続で清掃未実施(R4)", text: "現場対応では解決しない構造的問題の可能性があります。DFAオンサイト訪問(マップ再作成・環境調査)の手配を検討してください。" });
    }
    if (row.h1 === "ハンドルアップ" || row.h30 === "ハンドルアップ") {
      advices.push({ level: 1, icon: "🔧", title: "ハンドルアップ検知", text: "ハンドルが上がった状態です。現場にハンドルを下ろすよう連絡してください。" });
    }
    if (row.h1 === "オフライン" || row.h30 === "オフライン") {
      advices.push({ level: 1, icon: "📡", title: "オフライン検知", text: "ネットワーク接続が切れています。Wi-Fiルーターの再起動を現場に依頼してください。" });
    }
    return advices;
  }

  var AREA_DATA = {
    "MEGAドンキ渋谷本店": [
      { name: "1F入口", cp: 100 }, { name: "1F売場", cp: 98 }, { name: "1Fレジ前", cp: 95 }, { name: "1F通路A", cp: 100 },
      { name: "2F家電", cp: 92 }, { name: "2F文具", cp: 88 }, { name: "2F玩具", cp: 96 }, { name: "2F通路B", cp: 100 },
      { name: "3Fアパレル", cp: 94 }, { name: "3F靴売場", cp: 90 }, { name: "B1食品", cp: 97 }, { name: "B1飲料", cp: 100 },
    ],
    "MEGAドンキ立川店": [
      { name: "1F入口", cp: 100 }, { name: "1F売場", cp: 98 }, { name: "1Fレジ前", cp: 95 }, { name: "1F通路A", cp: 100 },
      { name: "1Fコスメ", cp: 92 }, { name: "1Fお菓子", cp: 88 },
      { name: "2F家電入口", cp: 45 }, { name: "2F家電奥", cp: 78 }, { name: "2F文具", cp: 82 }, { name: "2F玩具", cp: 96 },
      { name: "3F倉庫前通路", cp: 38 }, { name: "3Fアパレル", cp: 72 }, { name: "3F靴売場", cp: 90 },
      { name: "B1食品", cp: 12 }, { name: "B1飲料", cp: 55 }, { name: "B1日配", cp: 68 },
    ],
    "MEGAドンキ池袋駅北口店": [
      { name: "1", cp: 98 }, { name: "2", cp: 95 }, { name: "3", cp: 42 }, { name: "4", cp: 88 },
      { name: "5", cp: 35 }, { name: "6", cp: 100 }, { name: "7", cp: 52 }, { name: "8", cp: 90 },
    ],
    "MEGAドンキ港山下総本店": [
      { name: "A棟1F", cp: 100 }, { name: "A棟2F", cp: 85 }, { name: "A棟3F", cp: 22 },
      { name: "B棟1F", cp: 95 }, { name: "B棟2F", cp: 18 }, { name: "B棟3F", cp: 42 },
    ],
  };
  function getAreaData(facility) {
    return AREA_DATA[facility] || [
      { name: "1", cp: 88 }, { name: "2", cp: 45 }, { name: "3", cp: 12 },
      { name: "4", cp: 92 }, { name: "5", cp: 78 }, { name: "6", cp: 100 },
    ];
  }
  function areaGrade(cp) { return cp >= 90 ? "◎" : cp >= 70 ? "○" : cp >= 10 ? "△" : "×"; }
  function tokenDays(dateStr) { var d = new Date(dateStr); var now = new Date("2026-03-27"); return Math.ceil((d - now) / 86400000); }

  function LogTable(props) {
    var data = props.data;
    var compact = props.compact;
    return (
      <table style={{ width: "100%", borderCollapse: "collapse", minWidth: compact ? 700 : 1000 }}>
        <thead>
          <tr>
            <th style={Object.assign({}, th, { textAlign: "left" })}>施設名</th>
            {!compact && <th style={Object.assign({}, th, { textAlign: "left" })}>機種</th>}
            {!compact && <th style={Object.assign({}, th, { textAlign: "left" })}>シリアル</th>}
            <th style={Object.assign({}, th, { textAlign: "left" })}>日付</th>
            <th style={Object.assign({}, th, { textAlign: "left" })}>予定</th>
            <th style={Object.assign({}, th, { textAlign: "left" })}>1h前ST</th>
            <th style={Object.assign({}, th, { textAlign: "left" })}>30分前ST</th>
            <th style={Object.assign({}, th, { textAlign: "center" })}>出発</th>
            <th style={Object.assign({}, th, { textAlign: "right" })}>完了率</th>
            <th style={Object.assign({}, th, { textAlign: "center" })}>判定 <span onClick={function () { setShowGradeInfo(!showGradeInfo); }} style={{ cursor: "pointer", fontSize: 10, color: c.pr, border: "1px solid " + c.pr + "44", borderRadius: "50%", width: 16, height: 16, display: "inline-flex", alignItems: "center", justifyContent: "center", verticalAlign: "middle", marginLeft: 4 }}>?</span></th>
          </tr>
        </thead>
        {showGradeInfo && (
          <caption style={{ captionSide: "bottom", padding: 0 }}>
            <div style={{ margin: "8px 0", padding: "12px 16px", background: c.sf, border: "1px solid " + c.bd, borderRadius: 8, display: "inline-flex", gap: 16, alignItems: "center" }}>
              <span style={{ fontSize: 12, fontWeight: 600, color: c.tx }}>判定基準(タスク完了率):</span>
              <span style={{ fontSize: 12, color: c.ok }}>◎ 90%超</span>
              <span style={{ fontSize: 12, color: c.ok }}>○ 70%超</span>
              <span style={{ fontSize: 12, color: c.wn }}>△ 10-69%</span>
              <span style={{ fontSize: 12, color: c.ng }}>× 10%未満</span>
              <span style={{ fontSize: 11, color: c.txM }}>(閾値はシステム設定で変更可能)</span>
              <span onClick={function () { setShowGradeInfo(false); }} style={{ cursor: "pointer", fontSize: 14, color: c.txM, marginLeft: 8 }}>✕</span>
            </div>
          </caption>
        )}
        <tbody>
          {data.map(function (r, i) {
            var gs = gradeStyle(c, r.g);
            var hasAdvice = r.g === "△" || r.g === "×";
            var isExpanded = expandedRow === (compact ? "d" + i : "l" + i);
            var rowKey = compact ? "d" + i : "l" + i;
            var advices = hasAdvice ? getAdvice(r) : [];
            var maxLevel = advices.reduce(function (m, a) { return Math.max(m, a.level); }, 0);
            return (
              <React.Fragment key={i}>
              <tr style={{ borderBottom: isExpanded ? "none" : "1px solid " + c.bd + "22", cursor: hasAdvice ? "pointer" : "default", background: isExpanded ? c.pr + "08" : "transparent" }} onClick={hasAdvice ? function () { setExpandedRow(isExpanded ? null : rowKey); } : undefined}>
                <td style={td}>{r.f}</td>
                {!compact && <td style={tdm}>{r.m}</td>}
                {!compact && <td style={{ padding: "12px", fontSize: 11, fontFamily: "monospace", color: c.txM }}>{r.s}</td>}
                <td style={{ padding: "12px", fontSize: 12, color: c.txD }}>{r.d}</td>
                <td style={td}>{r.t}</td>
                <td style={td}><Pill text={r.h1} color={stColor(c, r.h1)} /></td>
                <td style={td}><Pill text={r.h30} color={stColor(c, r.h30)} /></td>
                <td style={{ padding: "12px", textAlign: "center", fontSize: 18, color: r.dp ? c.ok : c.ng }}>{r.dp ? "✓" : "✗"}</td>
                <td style={{ padding: "12px", textAlign: "right", fontSize: 13, color: c.tx }}>{r.cp}%</td>
                <td style={{ padding: "12px", textAlign: "center" }}>
                  <div style={{ display: "flex", alignItems: "center", justifyContent: "center", gap: 4 }}>
                    <span style={{ display: "inline-block", width: 28, height: 28, lineHeight: "28px", textAlign: "center", borderRadius: 6, fontSize: 14, fontWeight: 700, background: gs.bg, color: gs.tx, border: "1px solid " + gs.tx + "33" }}>{r.g}</span>
                    {hasAdvice && <span style={{ fontSize: 10, color: c.txM }}>{isExpanded ? "▲" : "▼"}</span>}
                  </div>
                </td>
              </tr>
              {isExpanded && advices.length > 0 && (
                <tr><td colSpan={compact ? 8 : 10} style={{ padding: 0, borderBottom: "1px solid " + c.bd + "22" }}>
                  <div style={{ padding: "12px 20px 16px", background: maxLevel >= 3 ? c.ng + "08" : maxLevel >= 2 ? c.wn + "08" : c.pr + "06" }}>
                    <div style={{ fontSize: 12, fontWeight: 700, color: maxLevel >= 3 ? c.ng : maxLevel >= 2 ? c.wn : c.pr, marginBottom: 10 }}>
                      {maxLevel >= 3 ? "🔴 レベル3 — DFA介入を検討" : maxLevel >= 2 ? "🔶 レベル2 — DFA運用担当がアクション" : "⚠ レベル1 — 現場確認が必要"}
                    </div>
                    {advices.map(function (a, j) {
                      return (
                        <div key={j} style={{ padding: "8px 12px", marginBottom: 6, borderRadius: 6, background: c.sf, border: "1px solid " + c.bd }}>
                          <div style={{ fontSize: 12, fontWeight: 600, color: c.tx }}>{a.icon} {a.title}</div>
                          <div style={{ fontSize: 12, color: c.txD, marginTop: 4 }}>{a.text}</div>
                        </div>
                      );
                    })}
                    <button onClick={function (e) { e.stopPropagation(); setAreaModal({ facility: r.f, date: r.d, cp: r.cp, g: r.g }); setAreaFilt("problem"); }} style={{ marginTop: 4, fontSize: 12, color: c.pr, background: c.prD, border: "none", borderRadius: 6, padding: "6px 14px", cursor: "pointer" }}>{t("エリア別詳細を見る →")}</button>
                  </div>
                </td></tr>
              )}
              </React.Fragment>
            );
          })}
        </tbody>
      </table>
    );
  }

  var menuMon = [
    { id: "detailLog", label: t("📋 清掃詳細ログ") },
    { id: "alert", label: t("🔔 アラート"), badge: unresPre },
    { id: "report", label: t("📈 レポート") },
    { id: "inspection", label: t("🔧 点検記録") },
  ];
  var menuDS = [
    { id: "dsecurity", label: t("🔒 D-Secログ") },
    { id: "dsalert", label: t("⚠ D-Secアラート"), badge: unresDsa },
  ];
  var menuSet = [
    { id: "robot", label: t("🏢 施設ロボットマスタ") },
    { id: "schedule", label: t("📅 スケジュール") },
    { id: "system", label: t("⚙ システム管理") },
  ];

  function NavItem(props) {
    var active = page === props.id;
    return (
      <div onClick={function () { setPage(props.id); }} style={{ padding: "10px 12px", borderRadius: 8, cursor: "pointer", fontSize: 13, display: "flex", alignItems: "center", gap: 10, marginBottom: 2, background: active ? c.prD : "transparent", color: active ? c.pr : c.txD }}>
        {props.label}
        {props.badge > 0 && <span style={{ marginLeft: "auto", fontSize: 11, background: c.ng, color: "#fff", borderRadius: 10, padding: "1px 7px", fontWeight: 600 }}>{props.badge}</span>}
      </div>
    );
  }

  function Section(props) {
    return <div style={{ fontSize: 10, color: c.txM, padding: "16px 12px 8px 12px", textTransform: "uppercase", letterSpacing: 1.2 }}>{props.title}</div>;
  }

  var inputSt = { fontSize: 13, padding: "8px 12px", borderRadius: 6, border: "1px solid " + c.bd, background: c.sfH, color: c.tx, width: "100%" };
  var selectSt = { fontSize: 13, padding: "8px 12px", borderRadius: 6, border: "1px solid " + c.bd, background: c.sfH, color: c.tx, width: "100%" };
  var labelSt = { fontSize: 12, color: c.txM, marginBottom: 4, display: "block" };
  var fieldSt = { marginBottom: 14 };

  function Modal(props) {
    return (
      <div style={{ position: "fixed", top: 0, left: 0, right: 0, bottom: 0, background: "rgba(0,0,0,0.5)", display: "flex", alignItems: "center", justifyContent: "center", zIndex: 1000 }}>
        <div style={{ background: c.sf, border: "1px solid " + c.bd, borderRadius: 16, padding: 0, width: 520, maxHeight: "80vh", overflow: "auto" }}>
          <div style={{ padding: "20px 24px", borderBottom: "1px solid " + c.bd, display: "flex", justifyContent: "space-between", alignItems: "center" }}>
            <div style={{ fontSize: 16, fontWeight: 700 }}>{props.title}</div>
            <button onClick={props.onClose} style={{ fontSize: 18, color: c.txM, background: "none", border: "none", cursor: "pointer", padding: "4px 8px" }}>✕</button>
          </div>
          <div style={{ padding: "20px 24px" }}>
            {props.children}
          </div>
          <div style={{ padding: "16px 24px", borderTop: "1px solid " + c.bd, display: "flex", justifyContent: "flex-end", gap: 8 }}>
            <button onClick={props.onClose} style={{ fontSize: 13, padding: "8px 20px", borderRadius: 6, border: "1px solid " + c.bd, background: "transparent", color: c.txD, cursor: "pointer" }}>{t("キャンセル")}</button>
            <button onClick={props.onClose} style={{ fontSize: 13, padding: "8px 20px", borderRadius: 6, border: "none", background: c.pr, color: "#fff", cursor: "pointer", fontWeight: 600 }}>{props.action || "保存"}</button>
          </div>
        </div>
      </div>
    );
  }

  return (
    <div style={{ display: "flex", minHeight: "100vh", background: c.bg, color: c.tx, fontFamily: "sans-serif" }}>

      {/* Sidebar */}
      <div style={{ width: 220, background: c.sf, borderRight: "1px solid " + c.bd, display: "flex", flexDirection: "column", flexShrink: 0 }}>
        <div style={{ padding: "20px 16px", borderBottom: "1px solid " + c.bd, display: "flex", justifyContent: "space-between", alignItems: "center" }}>
          <div>
            <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
              <svg width="32" height="32" viewBox="0 0 32 32" fill="none">
                <rect width="32" height="32" rx="8" fill={c.pr} fillOpacity="0.15"/>
                <rect x="8" y="10" width="16" height="14" rx="3" stroke={c.pr} strokeWidth="1.5" fill="none"/>
                <circle cx="13" cy="17" r="1.5" fill={c.pr}/>
                <circle cx="19" cy="17" r="1.5" fill={c.pr}/>
                <line x1="12" y1="22" x2="20" y2="22" stroke={c.pr} strokeWidth="1.5" strokeLinecap="round"/>
                <line x1="16" y1="6" x2="16" y2="10" stroke={c.pr} strokeWidth="1.5" strokeLinecap="round"/>
                <circle cx="16" cy="5" r="1.5" fill={c.pr}/>
              </svg>
              <div>
                <div style={{ fontSize: 16, fontWeight: 700, color: c.pr }}>D-Watch</div>
                <div style={{ fontSize: 9, color: c.txM, marginTop: 1 }}>"DFAロボット監視システム"</div>
              </div>
            </div>
          </div>
          <button onClick={function () { setDark(!dark); }} style={{ width: 32, height: 32, borderRadius: 8, border: "1px solid " + c.bd, background: c.sfH, cursor: "pointer", fontSize: 14 }}>
            {dark ? "☀" : "🌙"}
          </button>
          <button onClick={function () { setLang(lang === "ja" ? "en" : "ja"); }} style={{ fontSize: 11, fontWeight: 600, padding: "6px 10px", borderRadius: 8, border: "1px solid " + c.bd, background: lang === "en" ? c.pr + "18" : c.sfH, color: lang === "en" ? c.pr : c.txD, cursor: "pointer", letterSpacing: 0.5 }}>
            {lang === "ja" ? "EN" : "JP"}
          </button>
        </div>
        <div style={{ padding: "12px 8px", flex: 1 }}>
          <NavItem id="dashboard" label="📊 ダッシュボード" />
          <Section title={t("モニタリング")} />
          {menuMon.map(function (m) { return <NavItem key={m.id} id={m.id} label={m.label} badge={m.badge} />; })}
          <Section title="D-Security" />
          {menuDS.map(function (m) { return <NavItem key={m.id} id={m.id} label={m.label} badge={m.badge} />; })}
          <Section title={t("設定")} />
          {menuSet.map(function (m) { return <NavItem key={m.id} id={m.id} label={m.label} />; })}
        </div>
        <div style={{ padding: "12px 16px", borderTop: "1px solid " + c.bd, fontSize: 11, color: c.txM }}>"DFA運用担当"</div>
      </div>

      {/* Main */}
      <div style={{ flex: 1, overflow: "auto", padding: "24px 32px" }}>

        {/* DASHBOARD */}
        {page === "dashboard" && (
          <div>
            <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 24 }}>
              <div>
                <h1 style={{ fontSize: 22, fontWeight: 700, margin: 0 }}>{t("ダッシュボード")}</h1>
                <div style={{ fontSize: 13, color: c.txD, marginTop: 4 }}>昨夜の清掃結果サマリー — 2026-03-27</div>
              </div>
              <div style={{ display: "flex", gap: 8 }}>
                {unresPre > 0 && <Pill text={unresPre + " 件未解消"} color={c.ng} />}
                {dashItems.secBanner && unresDsa > 0 && <Pill text={"D-Sec " + unresDsa + "件"} color={c.wn} />}
              </div>
            </div>

            {dashItems.secBanner && (
              <div style={{ background: c.ngD, border: "1px solid " + c.ng + "44", borderRadius: 12, padding: "16px 20px", marginBottom: 16 }}>
                <div style={{ fontSize: 13, fontWeight: 700, color: c.ngB }}>⚠ セキュリティ無効: MEGAドンキ渋谷本店 1F売場(03:42以降)</div>
              </div>
            )}

            <div style={{ display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: 16, marginBottom: 24 }}>
              <Num value={285} label="成功" sub="/ 300施設" color={c.ok} c={c} />
              <Num value={10} label="失敗" sub="ロボット7 / セキュリティ2 / 制御盤1" color={c.ng} c={c} onClick={function () { setPage("detailLog"); }} />
              <Num value={5} label="未実施" sub="予定時刻経過・実績なし" color={c.wn} c={c} onClick={function () { setPage("detailLog"); }} />
              <Num value="95%" label="成功率" sub="目標: 95%" color={c.ac} c={c} />
            </div>

            {dashItems.detailLog && (
              <div style={{ background: c.sf, border: "1px solid " + c.bd, borderRadius: 12, overflow: "hidden", marginBottom: 16 }}>
                <div style={{ padding: "16px 20px", borderBottom: "1px solid " + c.bd, display: "flex", justifyContent: "space-between", alignItems: "center" }}>
                  <span style={{ fontSize: 14, fontWeight: 600, color: c.tx }}>清掃詳細ログ</span>
                  <div style={{ display: "flex", gap: 6 }}>
                    <BtnF active={dFilt === "problem"} color={c.wn} onClick={function () { setDFilt("problem"); }}>{t("△×のみ")}</BtnF>
                    <BtnF active={dFilt === "all"} color={c.txD} onClick={function () { setDFilt("all"); }}>{t("全件")}</BtnF>
                    <button onClick={function () { setPage("detailLog"); }} style={{ fontSize: 12, color: c.pr, background: "none", border: "1px solid " + c.pr + "44", borderRadius: 6, padding: "4px 12px", cursor: "pointer" }}>全項目 →</button>
                  </div>
                </div>
                <div style={{ overflowX: "auto" }}>
                  <LogTable data={filt(LOG, dFilt, "", "", "")} compact={true} />
                </div>
              </div>
            )}

            <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 16 }}>
              {dashItems.scheduleBar && (
                <div style={{ background: c.sf, border: "1px solid " + c.bd, borderRadius: 12, padding: 20 }}>
                  <div style={{ fontSize: 11, color: c.txM, textTransform: "uppercase", letterSpacing: 1, marginBottom: 12 }}>スケジュール進捗</div>
                  <span style={{ fontSize: 28, fontWeight: 700, color: c.tx }}>300</span>
                  <span style={{ fontSize: 14, color: c.txM }}> / 312 完了</span>
                  <div style={{ marginTop: 12, height: 6, background: c.bd, borderRadius: 3, overflow: "hidden" }}>
                    <div style={{ height: "100%", width: "96%", background: c.ok, borderRadius: 3 }} />
                  </div>
                </div>
              )}
              {dashItems.failBreakdown && (
                <div style={{ background: c.sf, border: "1px solid " + c.bd, borderRadius: 12, padding: 20 }}>
                  <div style={{ fontSize: 11, color: c.txM, textTransform: "uppercase", letterSpacing: 1, marginBottom: 12 }}>失敗の内訳</div>
                  <div style={{ display: "flex", justifyContent: "space-between", padding: "4px 0" }}><span style={{ color: c.txD }}>ロボット異常</span><span style={{ fontWeight: 600, color: c.ng }}>7</span></div>
                  <div style={{ display: "flex", justifyContent: "space-between", padding: "4px 0" }}><span style={{ color: c.txD }}>未実施</span><span style={{ fontWeight: 600, color: c.wn }}>5</span></div>
                  <div style={{ display: "flex", justifyContent: "space-between", padding: "4px 0" }}><span style={{ color: c.txD }}>セキュリティ有効</span><span style={{ fontWeight: 600, color: c.ac }}>2</span></div>
                  <div style={{ display: "flex", justifyContent: "space-between", padding: "4px 0" }}><span style={{ color: c.txD }}>制御盤異常</span><span style={{ fontWeight: 600, color: c.ng }}>1</span></div>
                </div>
              )}
            </div>
          </div>
        )}

        {/* DETAIL LOG */}
        {page === "detailLog" && (
          <div>
            <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 16 }}>
              <div>
                <h1 style={{ fontSize: 22, fontWeight: 700, margin: 0 }}>{t("清掃詳細ログ")}</h1>
                <div style={{ fontSize: 13, color: c.txD, marginTop: 4 }}>1行=1ロボット×1スケジュール実行</div>
              </div>
              <div style={{ display: "flex", gap: 8, alignItems: "center" }}>
                <input type="date" defaultValue="2026-03-27" style={{ fontSize: 12, padding: "6px 10px", borderRadius: 6, border: "1px solid " + c.bd, background: c.sfH, color: c.tx }} />
                <span style={{ color: c.txM }}>~</span>
                <input type="date" defaultValue="2026-03-27" style={{ fontSize: 12, padding: "6px 10px", borderRadius: 6, border: "1px solid " + c.bd, background: c.sfH, color: c.tx }} />
                <button onClick={function () { setPage("dashboard"); }} style={{ fontSize: 12, color: c.txD, background: "none", border: "1px solid " + c.bd, borderRadius: 6, padding: "6px 12px", cursor: "pointer" }}>← 戻る</button>
              </div>
            </div>
            <div style={{ background: c.sf, border: "1px solid " + c.bd, borderRadius: 12, overflow: "hidden" }}>
              <div style={{ padding: "16px 20px", borderBottom: "1px solid " + c.bd, display: "flex", justifyContent: "space-between", alignItems: "center", flexWrap: "wrap", gap: 8 }}>
                <div style={{ display: "flex", gap: 6, alignItems: "center" }}>
                  <select style={{ fontSize: 12, padding: "4px 8px", borderRadius: 6, border: "1px solid " + c.bd, background: c.sfH, color: c.tx }}>
                    <option>{t("全グループ")}</option><option>PPIH</option>
                  </select>
                  <select style={{ fontSize: 12, padding: "4px 8px", borderRadius: 6, border: "1px solid " + c.bd, background: c.sfH, color: c.tx }}>
                    <option>{t("全会社")}</option><option>ドン・キホーテ</option><option>ユニー</option><option>セブン-イレブン</option><option>ローソン</option>
                  </select>
                  <BtnF active={lFilt === "problem"} color={c.wn} onClick={function () { setLFilt("problem"); }}>{t("△×のみ")}</BtnF>
                  <BtnF active={lFilt === "all"} color={c.txD} onClick={function () { setLFilt("all"); }}>{t("全件")}</BtnF>
                  <BtnF active={lFilt === "×"} color={c.ng} onClick={function () { setLFilt("×"); }}>{t("×のみ")}</BtnF>
                </div>
                <div style={{ display: "flex", gap: 6 }}>
                  <input value={lSF} onChange={function (e) { setLSF(e.target.value); }} placeholder="施設名" style={{ fontSize: 12, padding: "6px 10px", borderRadius: 6, border: "1px solid " + c.bd, background: c.sfH, color: c.tx, width: 130 }} />
                  <input value={lSM} onChange={function (e) { setLSM(e.target.value); }} placeholder="機種" style={{ fontSize: 12, padding: "6px 10px", borderRadius: 6, border: "1px solid " + c.bd, background: c.sfH, color: c.tx, width: 80 }} />
                  <input value={lSS} onChange={function (e) { setLSS(e.target.value); }} placeholder="シリアル" style={{ fontSize: 12, padding: "6px 10px", borderRadius: 6, border: "1px solid " + c.bd, background: c.sfH, color: c.tx, width: 100 }} />
                  <button style={{ fontSize: 12, color: c.pr, background: c.prD, border: "none", borderRadius: 6, padding: "6px 12px", cursor: "pointer" }}>{t("CSV")}</button>
                </div>
              </div>
              <div style={{ overflowX: "auto" }}>
                <LogTable data={filt(LOG, lFilt, lSF, lSM, lSS)} compact={false} />
              </div>
              <div style={{ padding: "12px 20px", borderTop: "1px solid " + c.bd, fontSize: 12, color: c.txM }}>{filt(LOG, lFilt, lSF, lSM, lSS).length}件 / 全{LOG.length}件</div>
            </div>
          </div>
        )}

        {/* ALERT - Pre-check */}
        {page === "alert" && (
          <div>
            <h1 style={{ fontSize: 22, fontWeight: 700, margin: "0 0 4px" }}>{t("アラート(事前チェック)")}</h1>
            <div style={{ fontSize: 13, color: c.txD, marginBottom: 16 }}>{t("スケジュール開始前のエラー検知と出発失敗")}</div>

            {/* #2 サマリーカウント */}
            <div style={{ display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: 12, marginBottom: 16 }}>
              <div style={{ background: c.sf, border: "1px solid " + c.bd, borderRadius: 10, padding: "12px 16px", display: "flex", alignItems: "center", gap: 12 }}>
                <div style={{ fontSize: 28, fontWeight: 700, color: c.ng }}>{PRECHK.filter(function (a) { return !a.ok; }).length}</div>
                <div><div style={{ fontSize: 12, fontWeight: 600, color: c.ng }}>{t("未解消")}</div><div style={{ fontSize: 11, color: c.txM }}>{t("要対応")}</div></div>
              </div>
              <div style={{ background: c.sf, border: "1px solid " + c.bd, borderRadius: 10, padding: "12px 16px", display: "flex", alignItems: "center", gap: 12 }}>
                <div style={{ fontSize: 28, fontWeight: 700, color: c.ok }}>{PRECHK.filter(function (a) { return a.ok; }).length}</div>
                <div><div style={{ fontSize: 12, fontWeight: 600, color: c.ok }}>{t("解消済み")}</div><div style={{ fontSize: 11, color: c.txM }}>{t("対応完了")}</div></div>
              </div>
              <div style={{ background: c.sf, border: "1px solid " + c.bd, borderRadius: 10, padding: "12px 16px", display: "flex", alignItems: "center", gap: 12 }}>
                <div style={{ fontSize: 28, fontWeight: 700, color: c.txD }}>{PRECHK.length}</div>
                <div><div style={{ fontSize: 12, fontWeight: 600, color: c.txD }}>{t("合計")}</div><div style={{ fontSize: 11, color: c.txM }}>{t("全アラート")}</div></div>
              </div>
            </div>

            {/* #1 日付フィルタ + #3 グループ/会社フィルタ + ステータスフィルタ */}
            <div style={{ display: "flex", gap: 10, marginBottom: 16, flexWrap: "wrap", alignItems: "center" }}>
              <div style={{ display: "flex", alignItems: "center", gap: 6 }}>
                <input type="date" defaultValue="2026-03-27" style={{ fontSize: 12, padding: "6px 10px", borderRadius: 6, border: "1px solid " + c.bd, background: c.sfH, color: c.tx }} />
                <span style={{ fontSize: 12, color: c.txM }}>〜</span>
                <input type="date" defaultValue="2026-03-27" style={{ fontSize: 12, padding: "6px 10px", borderRadius: 6, border: "1px solid " + c.bd, background: c.sfH, color: c.tx }} />
              </div>
              <select style={{ fontSize: 12, padding: "6px 10px", borderRadius: 6, border: "1px solid " + c.bd, background: c.sfH, color: c.tx }}>
                <option>{t("全グループ")}</option><option>PPIH</option>
              </select>
              <select style={{ fontSize: 12, padding: "6px 10px", borderRadius: 6, border: "1px solid " + c.bd, background: c.sfH, color: c.tx }}>
                <option>{t("全会社")}</option><option>ドン・キホーテ</option><option>ユニー</option><option>セブン-イレブン</option><option>ローソン</option>
              </select>
              <div style={{ display: "flex", gap: 6 }}>
                <BtnF active={aFilt === "unresolved"} color={c.ng} onClick={function () { setAFilt("unresolved"); }}>{t("未解消のみ")}</BtnF>
                <BtnF active={aFilt === "all"} color={c.txD} onClick={function () { setAFilt("all"); }}>{t("全件")}</BtnF>
                <BtnF active={aFilt === "resolved"} color={c.ok} onClick={function () { setAFilt("resolved"); }}>{t("解消済み")}</BtnF>
              </div>
            </div>

            {PRECHK.filter(function (a) {
              if (aFilt === "unresolved") return !a.ok;
              if (aFilt === "resolved") return a.ok;
              return true;
            }).map(function (a) {
              var sevCol = a.sev === "出発失敗" ? c.ng : c.wn;
              return (
                <div key={a.id} style={{ background: c.sf, border: "1px solid " + c.bd, borderRadius: 12, borderLeft: "3px solid " + sevCol, padding: "16px 20px", marginBottom: 12 }}>
                  <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start", flexWrap: "wrap", gap: 12 }}>
                    <div style={{ flex: 1, minWidth: 250 }}>
                      <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 6 }}>
                        <Pill text={a.sev} color={sevCol} />
                        <Pill text={a.st} color={stColor(c, a.st)} />
                        <span style={{ fontSize: 12, fontFamily: "monospace", color: c.txM }}>{a.serial}</span>
                      </div>
                      <div style={{ fontSize: 14, fontWeight: 600, color: c.tx }}>{a.fac}</div>
                      <div style={{ fontSize: 13, color: c.txD, marginTop: 4 }}>予定: {a.sch} — {a.note}</div>
                      <div style={{ fontSize: 11, color: c.txM, marginTop: 4 }}>検知: {a.dt}</div>
                    </div>
                    <div>
                      {a.ok
                        ? <span style={{ fontSize: 12, padding: "4px 14px", borderRadius: 6, background: c.okD, color: c.ok, fontWeight: 600 }}>解消 ({a.at})</span>
                        : <span style={{ fontSize: 12, padding: "4px 14px", borderRadius: 6, background: c.ngD, color: c.ng, fontWeight: 600 }}>{t("未解消")}</span>
                      }
                    </div>
                  </div>
                </div>
              );
            })}
          </div>
        )}

        {/* REPORT */}
        {page === "report" && (
          <div>
            <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 16 }}>
              <h1 style={{ fontSize: 22, fontWeight: 700, margin: 0 }}>{t("レポート")}</h1>
              <button style={{ fontSize: 12, color: c.pr, background: c.prD, border: "none", borderRadius: 6, padding: "6px 14px", cursor: "pointer" }}>{t("CSVエクスポート")}</button>
            </div>
            <div style={{ display: "flex", gap: 10, marginBottom: 20, flexWrap: "wrap", alignItems: "center" }}>
              <div style={{ display: "flex", alignItems: "center", gap: 6 }}>
                <span style={{ fontSize: 12, color: c.txM }}>期間</span>
                <input type="date" defaultValue="2026-03-01" style={{ fontSize: 12, padding: "6px 10px", borderRadius: 6, border: "1px solid " + c.bd, background: c.sfH, color: c.tx }} />
                <span style={{ fontSize: 12, color: c.txM }}>〜</span>
                <input type="date" defaultValue="2026-03-27" style={{ fontSize: 12, padding: "6px 10px", borderRadius: 6, border: "1px solid " + c.bd, background: c.sfH, color: c.tx }} />
              </div>
              <select style={{ fontSize: 12, padding: "6px 10px", borderRadius: 6, border: "1px solid " + c.bd, background: c.sfH, color: c.tx }}>
                <option>{t("全グループ")}</option><option>PPIH</option>
              </select>
              <select style={{ fontSize: 12, padding: "6px 10px", borderRadius: 6, border: "1px solid " + c.bd, background: c.sfH, color: c.tx }}>
                <option>{t("全会社")}</option><option>ドン・キホーテ</option><option>ユニー</option><option>セブン-イレブン</option><option>ローソン</option>
              </select>
              <input placeholder="施設名" style={{ fontSize: 12, padding: "6px 12px", borderRadius: 6, border: "1px solid " + c.bd, background: c.sfH, color: c.tx, width: 140 }} />
              <input placeholder="シリアルNo." style={{ fontSize: 12, padding: "6px 12px", borderRadius: 6, border: "1px solid " + c.bd, background: c.sfH, color: c.tx, width: 140 }} />
              <select style={{ fontSize: 12, padding: "6px 10px", borderRadius: 6, border: "1px solid " + c.bd, background: c.sfH, color: c.tx }}>
                <option>{t("全ステータス")}</option><option>要改善</option><option>注意</option><option>良好</option>
              </select>
              <button style={{ fontSize: 12, color: "#fff", background: c.pr, border: "none", borderRadius: 6, padding: "6px 16px", cursor: "pointer" }}>{t("検索")}</button>
            </div>
            <div style={{ display: "flex", justifyContent: "flex-end", marginBottom: 16 }}>
              <div style={{ display: "flex", background: c.sfH, borderRadius: 6, border: "1px solid " + c.bd, overflow: "hidden" }}>
                <button onClick={function () { setRptPeriod("weekly"); setShowAllRank(false); setShowAllCont(false); }} style={{ fontSize: 12, padding: "6px 16px", border: "none", cursor: "pointer", background: rptPeriod === "weekly" ? c.pr : "transparent", color: rptPeriod === "weekly" ? "#fff" : c.txD, fontWeight: rptPeriod === "weekly" ? 600 : 400 }}>{t("週次")}</button>
                <button onClick={function () { setRptPeriod("monthly"); setShowAllRank(false); setShowAllCont(false); }} style={{ fontSize: 12, padding: "6px 16px", border: "none", cursor: "pointer", background: rptPeriod === "monthly" ? c.pr : "transparent", color: rptPeriod === "monthly" ? "#fff" : c.txD, fontWeight: rptPeriod === "monthly" ? 600 : 400 }}>{t("月次")}</button>
              </div>
            </div>
            <div style={{ display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: 12, marginBottom: 24 }}>
              {[["稼働率", 92, 89, c.ok], ["出発成功率", 88, 90, c.pr], ["清掃完了率", 87, 85, c.ac], ["エラー発生率", 4.2, 4.7, c.ng]].map(function (item, i) {
                var diff = Math.round((item[1] - item[2]) * 10) / 10;
                var better = i < 3 ? diff > 0 : diff < 0;
                var worse = i < 3 ? diff < 0 : diff > 0;
                var prevLabel = rptPeriod === "weekly" ? "前週" : "前月";
                return (
                  <div key={i} style={{ background: c.sf, border: "1px solid " + c.bd, borderRadius: 12, padding: 16 }}>
                    <div style={{ fontSize: 11, color: c.txM, textTransform: "uppercase", letterSpacing: 1, marginBottom: 8 }}>{item[0]}</div>
                    <div style={{ fontSize: 32, fontWeight: 700, color: item[3], lineHeight: 1 }}>{item[1]}%</div>
                    <div style={{ display: "flex", alignItems: "center", gap: 6, marginTop: 8 }}>
                      <span style={{ fontSize: 12, color: better ? c.ok : worse ? c.ng : c.txM, fontWeight: 600 }}>{diff > 0 ? "▲" : diff < 0 ? "▼" : "→"}{Math.abs(diff)}%</span>
                      <span style={{ fontSize: 11, color: c.txM }}>{prevLabel}比</span>
                    </div>
                    <div style={{ fontSize: 11, color: c.txM, marginTop: 2 }}>{prevLabel}: {item[2]}%</div>
                  </div>
                );
              })}
            </div>

            {/* 連続問題施設 + エラー種別 */}
            <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 16, marginBottom: 24 }}>
              {/* #4 連続問題施設 */}
              <div style={{ background: c.sf, border: "1px solid " + c.bd, borderRadius: 12, overflow: "hidden" }}>
                <div style={{ padding: "14px 20px", borderBottom: "1px solid " + c.bd }}>
                  <div style={{ fontSize: 13, fontWeight: 600, color: c.tx }}>{t("連続問題施設")}</div>
                  <div style={{ fontSize: 11, color: c.txM, marginTop: 2 }}>2日以上連続で△以下または出発失敗の施設</div>
                </div>
                {RANK.filter(function (f) { return f.cont >= 2; }).length === 0
                  ? <div style={{ padding: "20px", textAlign: "center", fontSize: 12, color: c.txM }}>該当施設なし</div>
                  : (function () {
                    var contFacs = RANK.filter(function (f) { return f.cont >= 2; }).sort(function (a, b) { return b.cont - a.cont; });
                    var displayFacs = showAllCont ? contFacs : contFacs.slice(0, 10);
                    return (
                      <div>
                        {displayFacs.map(function (f, i) {
                          var lv = f.cont >= 3 ? 3 : 2;
                          var lvCol = lv >= 3 ? c.ng : c.wn;
                          return (
                            <div key={i} style={{ display: "flex", alignItems: "center", gap: 12, padding: "10px 20px", borderBottom: "1px solid " + c.bd + "11" }}>
                              <span style={{ fontSize: 11, padding: "2px 8px", borderRadius: 4, background: lvCol + "18", color: lvCol, fontWeight: 600, whiteSpace: "nowrap" }}>Lv{lv} / {f.cont}日</span>
                              <span style={{ fontSize: 13, fontWeight: 600, color: c.tx, flex: 1 }}>{f.f}</span>
                              <span style={{ fontSize: 12, color: c.txM }}>完了率 {f.cv}%</span>
                            </div>
                          );
                        })}
                        {!showAllCont && contFacs.length > 10 && (
                          <div style={{ padding: "10px 20px", textAlign: "center" }}>
                            <button onClick={function () { setShowAllCont(true); }} style={{ fontSize: 12, color: c.pr, background: "none", border: "none", cursor: "pointer" }}>他{contFacs.length - 10}件を表示 →</button>
                          </div>
                        )}
                      </div>
                    );
                  })()
                }
              </div>

              {/* #5 エラー種別の内訳 */}
              <div style={{ background: c.sf, border: "1px solid " + c.bd, borderRadius: 12, overflow: "hidden" }}>
                <div style={{ padding: "14px 20px", borderBottom: "1px solid " + c.bd }}>
                  <div style={{ fontSize: 13, fontWeight: 600, color: c.tx }}>{t("エラー種別の内訳")}</div>
                  <div style={{ fontSize: 11, color: c.txM, marginTop: 2 }}>今週のエラー発生件数(種別ごと)</div>
                </div>
                {[
                  { name: "ハンドルアップ", count: 8, pct: 32, color: c.wn },
                  { name: "LostLocation", count: 5, pct: 20, color: c.ng },
                  { name: "オフライン", count: 4, pct: 16, color: c.ng },
                  { name: "ブラシエラー", count: 3, pct: 12, color: c.wn },
                  { name: "緊急停止", count: 2, pct: 8, color: c.ng },
                  { name: "充電不足", count: 2, pct: 8, color: c.txD },
                  { name: "その他", count: 1, pct: 4, color: c.txM },
                ].map(function (e, i) {
                  return (
                    <div key={i} style={{ display: "flex", alignItems: "center", gap: 10, padding: "8px 20px", borderBottom: "1px solid " + c.bd + "11" }}>
                      <div style={{ width: 110, fontSize: 12, color: c.tx }}>{e.name}</div>
                      <div style={{ flex: 1, height: 6, background: c.bd + "44", borderRadius: 3, overflow: "hidden" }}>
                        <div style={{ width: e.pct + "%", height: "100%", background: e.color, borderRadius: 3 }} />
                      </div>
                      <div style={{ width: 30, textAlign: "right", fontSize: 13, fontWeight: 600, color: e.color }}>{e.count}</div>
                      <div style={{ width: 35, textAlign: "right", fontSize: 11, color: c.txM }}>{e.pct}%</div>
                    </div>
                  );
                })}
              </div>
            </div>

            {/* 施設別パフォーマンス */}
            <div style={{ background: c.sf, border: "1px solid " + c.bd, borderRadius: 12, overflow: "hidden" }}>
              <div style={{ padding: "16px 20px", borderBottom: "1px solid " + c.bd, display: "flex", justifyContent: "space-between", alignItems: "center" }}>
                <div style={{ fontSize: 14, fontWeight: 600, color: c.tx }}>{t("施設別パフォーマンス(稼働率ワースト順)")}</div>
                <span style={{ fontSize: 12, color: c.txM }}>{RANK.length}施設</span>
              </div>
              <div style={{ overflowX: "auto" }}>
              <table style={{ width: "100%", borderCollapse: "collapse", minWidth: 900 }}>
                <thead><tr>
                  <th style={Object.assign({}, th, { textAlign: "left" })}>施設名</th>
                  <th style={Object.assign({}, th, { textAlign: "right" })}>{t("稼働率")}</th>
                  <th style={Object.assign({}, th, { textAlign: "right" })}>{rptPeriod === "weekly" ? "前週" : "前月"}</th>
                  <th style={Object.assign({}, th, { textAlign: "right" })}>{t("出発成功率")}</th>
                  <th style={Object.assign({}, th, { textAlign: "right" })}>完了率</th>
                  <th style={Object.assign({}, th, { textAlign: "right" })}>{rptPeriod === "weekly" ? "前週" : "前月"}</th>
                  <th style={Object.assign({}, th, { textAlign: "right" })}>エラー率</th>
                  <th style={Object.assign({}, th, { textAlign: "center" })}>変化</th>
                  <th style={Object.assign({}, th, { textAlign: "left" })}>ステータス</th>
                </tr></thead>
                <tbody>
                  {(showAllRank ? RANK : RANK.slice(0, 10)).map(function (f, i) {
                    var sc = f.s === "要改善" ? c.ng : f.s === "注意" ? c.wn : c.ok;
                    var arDiff = f.ar - f.arP;
                    var cvDiff = f.cv - f.cvP;
                    var overallDiff = Math.round((arDiff + cvDiff) / 2);
                    var diffCol = overallDiff > 0 ? c.ok : overallDiff < 0 ? c.ng : c.txM;
                    return (
                      <tr key={i} style={{ borderBottom: "1px solid " + c.bd + "22" }}>
                        <td style={Object.assign({}, td, { fontWeight: 600 })}>{f.f}</td>
                        <td style={{ padding: "12px", textAlign: "right" }}><span style={{ fontWeight: 600, color: f.ar < 80 ? c.ng : f.ar < 90 ? c.wn : c.ok }}>{f.ar}%</span></td>
                        <td style={{ padding: "12px", textAlign: "right", fontSize: 11, color: c.txM }}>{f.arP}%</td>
                        <td style={{ padding: "12px", textAlign: "right" }}><span style={{ fontWeight: 600, color: f.dp < 80 ? c.ng : f.dp < 90 ? c.wn : c.pr }}>{f.dp}%</span></td>
                        <td style={{ padding: "12px", textAlign: "right", color: c.tx }}>{f.cv}%</td>
                        <td style={{ padding: "12px", textAlign: "right", fontSize: 11, color: c.txM }}>{f.cvP}%</td>
                        <td style={{ padding: "12px", textAlign: "right" }}><span style={{ color: f.er > 8 ? c.ng : c.txD }}>{f.er}%</span></td>
                        <td style={{ padding: "12px", textAlign: "center" }}><span style={{ fontSize: 12, fontWeight: 600, color: diffCol }}>{overallDiff > 0 ? "▲" + overallDiff : overallDiff < 0 ? "▼" + Math.abs(overallDiff) : "→"}</span></td>
                        <td style={td}><Pill text={t(f.s)} color={sc} /></td>
                      </tr>
                    );
                  })}
                </tbody>
              </table>
              </div>
              {!showAllRank && RANK.length > 10 && (
                <div style={{ padding: "12px 20px", borderTop: "1px solid " + c.bd, textAlign: "center" }}>
                  <button onClick={function () { setShowAllRank(true); }} style={{ fontSize: 12, color: c.pr, background: "none", border: "none", cursor: "pointer" }}>全{RANK.length}施設を表示 →</button>
                </div>
              )}
              {showAllRank && RANK.length > 10 && (
                <div style={{ padding: "12px 20px", borderTop: "1px solid " + c.bd, textAlign: "center" }}>
                  <button onClick={function () { setShowAllRank(false); }} style={{ fontSize: 12, color: c.txM, background: "none", border: "none", cursor: "pointer" }}>上位10件に戻す</button>
                </div>
              )}
            </div>
          </div>
        )}

        {/* D-SECURITY DEVICE */}
        {page === "dsecurity" && (
          <div>
            <h1 style={{ fontSize: 22, fontWeight: 700, margin: "0 0 16px" }}>{t("D-Sec ログ")}</h1>
            <div style={{ display: "flex", gap: 10, marginBottom: 16, flexWrap: "wrap", alignItems: "center" }}>
              <select style={{ fontSize: 12, padding: "6px 10px", borderRadius: 6, border: "1px solid " + c.bd, background: c.sfH, color: c.tx }}>
                <option>{t("全グループ")}</option><option>PPIH</option>
              </select>
              <select style={{ fontSize: 12, padding: "6px 10px", borderRadius: 6, border: "1px solid " + c.bd, background: c.sfH, color: c.tx }}>
                <option>{t("全会社")}</option><option>ドン・キホーテ</option><option>ユニー</option><option>ローソン</option>
              </select>
              <input placeholder="施設名 / デバイスID" style={{ fontSize: 12, padding: "6px 12px", borderRadius: 6, border: "1px solid " + c.bd, background: c.sfH, color: c.tx, width: 180 }} />
              <div style={{ display: "flex", gap: 6 }}>
                <BtnF active={dsLogFilt === "all"} color={c.txD} onClick={function () { setDsLogFilt("all"); }}>{t("全て")}</BtnF>
                <BtnF active={dsLogFilt === "abnormal"} color={c.ng} onClick={function () { setDsLogFilt("abnormal"); }}>{t("異常・通信断")}</BtnF>
                <BtnF active={dsLogFilt === "normal"} color={c.ok} onClick={function () { setDsLogFilt("normal"); }}>正常</BtnF>
              </div>
            </div>
            <div style={{ display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: 16, marginBottom: 24 }}>
              <Num value={DSDEV.length} label="D-Sデバイス総数" color={c.pr} c={c} />
              <Num value={DSDEV.filter(function (d) { return d.st === "正常"; }).length} label="正常稼働" color={c.ok} c={c} />
              <Num value={DSDEV.filter(function (d) { return d.st !== "正常"; }).length} label="異常・通信断" sub="要対応" color={c.ng} c={c} />
            </div>
            <div style={{ background: c.sf, border: "1px solid " + c.bd, borderRadius: 12, overflow: "hidden" }}>
              <table style={{ width: "100%", borderCollapse: "collapse" }}>
                <thead><tr>
                  <th style={Object.assign({}, th, { textAlign: "left" })}>ID</th>
                  <th style={Object.assign({}, th, { textAlign: "left" })}>施設名</th>
                  <th style={Object.assign({}, th, { textAlign: "center" })}>接続状態</th>
                  <th style={Object.assign({}, th, { textAlign: "left" })}>最終通信</th>
                  <th style={Object.assign({}, th, { textAlign: "left" })}>トークン期限</th>
                  <th style={Object.assign({}, th, { textAlign: "center" })}>残日数</th>
                  <th style={Object.assign({}, th, { textAlign: "left" })}>備考</th>
                </tr></thead>
                <tbody>
                  {DSDEV.filter(function (d) {
                    if (dsLogFilt === "abnormal") return d.st !== "正常";
                    if (dsLogFilt === "normal") return d.st === "正常";
                    return true;
                  }).sort(function (a, b) {
                    var order = { "異常": 0, "通信断": 1, "正常": 2 };
                    return (order[a.st] || 9) - (order[b.st] || 9);
                  }).map(function (d, i) {
                    var days = tokenDays(d.te);
                    var dayCol = days <= 7 ? c.ng : days <= 30 ? c.wn : c.ok;
                    return (
                      <tr key={i} style={{ borderBottom: "1px solid " + c.bd + "22" }}>
                        <td style={{ padding: "12px", fontFamily: "monospace", fontSize: 12, color: c.tx }}>{d.id}</td>
                        <td style={td}>{d.f}</td>
                        <td style={{ padding: "12px", textAlign: "center" }}><Pill text={d.st} color={d.st === "正常" ? c.ok : c.ng} /></td>
                        <td style={{ padding: "12px", fontSize: 12, color: c.txD }}>{d.lc}</td>
                        <td style={tdm}>{d.te}</td>
                        <td style={{ padding: "12px", textAlign: "center" }}><span style={{ fontSize: 12, fontWeight: 600, color: dayCol }}>{days}日</span></td>
                        <td style={{ padding: "12px", fontSize: 12, color: d.n ? c.wn : c.txM }}>{d.n || "-"}</td>
                      </tr>
                    );
                  })}
                </tbody>
              </table>
            </div>
          </div>
        )}

        {/* D-SECURITY ALERT */}
        {page === "dsalert" && (
          <div>
            <h1 style={{ fontSize: 22, fontWeight: 700, margin: "0 0 4px" }}>{t("D-Security アラート")}</h1>
            <div style={{ fontSize: 13, color: c.txD, marginBottom: 16 }}>{t("セキュリティ無効・通信断・トークン期限のアラート管理")}</div>

            {/* サマリーカウント */}
            <div style={{ display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: 12, marginBottom: 16 }}>
              <div style={{ background: c.sf, border: "1px solid " + c.bd, borderRadius: 10, padding: "12px 16px", display: "flex", alignItems: "center", gap: 12 }}>
                <div style={{ fontSize: 28, fontWeight: 700, color: c.ng }}>{dsaState.filter(function (a) { return a.st === "未対応"; }).length}</div>
                <div><div style={{ fontSize: 12, fontWeight: 600, color: c.ng }}>{t("未対応")}</div><div style={{ fontSize: 11, color: c.txM }}>{t("即時対応")}</div></div>
              </div>
              <div style={{ background: c.sf, border: "1px solid " + c.bd, borderRadius: 10, padding: "12px 16px", display: "flex", alignItems: "center", gap: 12 }}>
                <div style={{ fontSize: 28, fontWeight: 700, color: c.wn }}>{dsaState.filter(function (a) { return a.st === "対応中"; }).length}</div>
                <div><div style={{ fontSize: 12, fontWeight: 600, color: c.wn }}>{t("対応中")}</div><div style={{ fontSize: 11, color: c.txM }}>{t("進行中")}</div></div>
              </div>
              <div style={{ background: c.sf, border: "1px solid " + c.bd, borderRadius: 10, padding: "12px 16px", display: "flex", alignItems: "center", gap: 12 }}>
                <div style={{ fontSize: 28, fontWeight: 700, color: c.ok }}>{dsaState.filter(function (a) { return a.st === "対応済み"; }).length}</div>
                <div><div style={{ fontSize: 12, fontWeight: 600, color: c.ok }}>{t("対応済み")}</div><div style={{ fontSize: 11, color: c.txM }}>{t("完了")}</div></div>
              </div>
            </div>

            {/* フィルタ */}
            <div style={{ display: "flex", gap: 10, marginBottom: 16, flexWrap: "wrap", alignItems: "center" }}>
              <div style={{ display: "flex", alignItems: "center", gap: 6 }}>
                <input type="date" defaultValue="2026-03-20" style={{ fontSize: 12, padding: "6px 10px", borderRadius: 6, border: "1px solid " + c.bd, background: c.sfH, color: c.tx }} />
                <span style={{ fontSize: 12, color: c.txM }}>〜</span>
                <input type="date" defaultValue="2026-03-27" style={{ fontSize: 12, padding: "6px 10px", borderRadius: 6, border: "1px solid " + c.bd, background: c.sfH, color: c.tx }} />
              </div>
              <select style={{ fontSize: 12, padding: "6px 10px", borderRadius: 6, border: "1px solid " + c.bd, background: c.sfH, color: c.tx }}>
                <option>{t("全グループ")}</option><option>PPIH</option>
              </select>
              <select style={{ fontSize: 12, padding: "6px 10px", borderRadius: 6, border: "1px solid " + c.bd, background: c.sfH, color: c.tx }}>
                <option>{t("全会社")}</option><option>ドン・キホーテ</option><option>ユニー</option><option>ローソン</option>
              </select>
              <select value={dsaTypeFilt} onChange={function (e) { setDsaTypeFilt(e.target.value); }} style={{ fontSize: 12, padding: "6px 10px", borderRadius: 6, border: "1px solid " + c.bd, background: c.sfH, color: c.tx }}>
                <option value="all">全種別</option><option value="セキュリティ無効">セキュリティ無効</option><option value="通信断">通信断</option><option value="トークン期限">トークン期限</option>
              </select>
              <div style={{ display: "flex", gap: 6 }}>
                <BtnF active={daFilt === "unresolved"} color={c.wn} onClick={function () { setDaFilt("unresolved"); }}>{t("未対応・対応中")}</BtnF>
                <BtnF active={daFilt === "all"} color={c.txD} onClick={function () { setDaFilt("all"); }}>{t("全件")}</BtnF>
                <BtnF active={daFilt === "done"} color={c.ok} onClick={function () { setDaFilt("done"); }}>{t("対応済み")}</BtnF>
              </div>
            </div>

            {dsaState.filter(function (a) {
              if (daFilt === "unresolved") return a.st === "未対応" || a.st === "対応中";
              if (daFilt === "done") return a.st === "対応済み";
              return true;
            }).filter(function (a) {
              if (dsaTypeFilt === "all") return true;
              return a.type === dsaTypeFilt;
            }).map(function (a) {
              var tpCol = a.type === "トークン期限" ? c.wn : c.ng;
              var ss = a.st === "未対応" ? { b: c.ngD, t: c.ng } : a.st === "対応中" ? { b: c.wnD, t: c.wn } : { b: c.okD, t: c.ok };
              return (
                <div key={a.id} style={{ background: c.sf, border: "1px solid " + c.bd, borderRadius: 12, borderLeft: "3px solid " + tpCol, padding: "16px 20px", marginBottom: 12 }}>
                  <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start", flexWrap: "wrap", gap: 12 }}>
                    <div style={{ flex: 1, minWidth: 250 }}>
                      <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 6 }}>
                        <Pill text={t(a.type)} color={tpCol} />
                        <span style={{ fontSize: 11, fontFamily: "monospace", padding: "2px 6px", borderRadius: 4, background: c.sfH, color: c.txM }}>{a.dev}</span>
                      </div>
                      <div style={{ fontSize: 14, fontWeight: 600, color: c.tx }}>{a.fac}</div>
                      <div style={{ fontSize: 13, color: c.txD, marginTop: 4 }}>{a.det}</div>
                      <div style={{ fontSize: 11, color: c.txM, marginTop: 4 }}>検知: {a.tm}</div>
                      {a.mm && <div style={{ fontSize: 12, color: c.txM, marginTop: 6, padding: "6px 10px", background: c.sfH, borderRadius: 6, borderLeft: "2px solid " + c.bd }}>{a.mm}</div>}
                    </div>
                    <button onClick={function () { cycleDsa(a.id); }} style={{ fontSize: 12, padding: "4px 14px", borderRadius: 6, cursor: "pointer", border: "1px solid " + ss.t + "44", background: ss.b, color: ss.t, fontWeight: 600 }}>
                      {a.st}
                    </button>
                  </div>
                </div>
              );
            })}
          </div>
        )}

        {/* FACILITY ROBOT MASTER */}
        {page === "robot" && (
          <div>
            <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 24 }}>
              <h1 style={{ fontSize: 22, fontWeight: 700, margin: 0 }}>{t("施設ロボットマスタ")}</h1>
              <div style={{ display: "flex", gap: 8 }}>
                <input value={rSrch} onChange={function (e) { setRSrch(e.target.value); }} placeholder="施設名 / シリアル / 住所" style={{ fontSize: 12, padding: "6px 12px", borderRadius: 6, border: "1px solid " + c.bd, background: c.sfH, color: c.tx, width: 200 }} />
                <button style={{ fontSize: 12, color: c.ac, background: "none", border: "1px solid " + c.ac + "44", borderRadius: 6, padding: "6px 14px", cursor: "pointer" }}>📥 インポート</button>
                <button style={{ fontSize: 12, color: c.pr, background: c.prD, border: "none", borderRadius: 6, padding: "6px 14px", cursor: "pointer" }}>+ 新規追加</button>
              </div>
            </div>
            <div style={{ background: c.sf, border: "1px solid " + c.bd, borderRadius: 12, overflow: "hidden" }}>
              <div style={{ overflowX: "auto" }}>
                <table style={{ width: "100%", borderCollapse: "collapse", minWidth: 1300 }}>
                  <thead><tr>
                    <th style={Object.assign({}, th, { textAlign: "left" })}>施設名</th>
                    <th style={Object.assign({}, th, { textAlign: "left" })}>都道府県</th>
                    <th style={Object.assign({}, th, { textAlign: "left" })}>住所</th>
                    <th style={Object.assign({}, th, { textAlign: "left" })}>電話番号</th>
                    <th style={Object.assign({}, th, { textAlign: "left" })}>責任者名</th>
                    <th style={Object.assign({}, th, { textAlign: "left" })}>担当者名</th>
                    <th style={Object.assign({}, th, { textAlign: "left" })}>メール</th>
                    <th style={Object.assign({}, th, { textAlign: "center" })}>監視</th>
                    <th style={Object.assign({}, th, { textAlign: "center" })}>D-Sec</th>
                    <th style={Object.assign({}, th, { textAlign: "left" })}>ロボット(メーカー / 機種 / シリアル)</th>
                  </tr></thead>
                  <tbody>
                    {ROBOTS.filter(function (r) {
                      if (!rSrch) return true;
                      var q = rSrch.toLowerCase();
                      var botMatch = r.bots.some(function (b) { return b.sn.toLowerCase().indexOf(q) >= 0 || b.mk.toLowerCase().indexOf(q) >= 0 || b.md.toLowerCase().indexOf(q) >= 0; });
                      return r.f.toLowerCase().indexOf(q) >= 0 || r.pref.toLowerCase().indexOf(q) >= 0 || r.addr.toLowerCase().indexOf(q) >= 0 || botMatch;
                    }).map(function (r, i) {
                      return (
                        <tr key={i} style={{ borderBottom: "1px solid " + c.bd + "22", verticalAlign: "top" }}>
                          <td style={Object.assign({}, td, { fontWeight: 600 })}>{r.f}</td>
                          <td style={{ padding: "12px", fontSize: 12, color: c.txD }}>{r.pref}</td>
                          <td style={{ padding: "12px", fontSize: 12, color: c.txD }}>{r.addr}</td>
                          <td style={{ padding: "12px", fontSize: 12, color: c.txD, whiteSpace: "nowrap" }}>{r.tel}</td>
                          <td style={td}>{r.mgr}</td>
                          <td style={td}>{r.staff}</td>
                          <td style={{ padding: "12px", fontSize: 11, fontFamily: "monospace", color: c.txD }}>{r.email}</td>
                          <td style={{ padding: "12px", textAlign: "center", fontSize: 16 }}>{r.mon ? <span style={{ color: c.ok }}>○</span> : <span style={{ color: c.txM }}>ー</span>}</td>
                          <td style={{ padding: "12px", textAlign: "center", fontSize: 16 }}>{r.dsec ? <span style={{ color: c.ac }}>○</span> : <span style={{ color: c.txM }}>ー</span>}</td>
                          <td style={{ padding: "12px" }}>
                            {r.bots.map(function (b, j) {
                              return (
                                <div key={j} style={{ display: "flex", alignItems: "center", gap: 6, marginBottom: j < r.bots.length - 1 ? 6 : 0 }}>
                                  <span style={{ fontSize: 11, padding: "2px 6px", borderRadius: 4, background: c.prD, color: c.pr, fontWeight: 600 }}>{b.mk}</span>
                                  <span style={{ fontSize: 12, color: c.tx }}>{b.md}</span>
                                  <span style={{ fontSize: 11, fontFamily: "monospace", color: c.txM }}>{b.sn}</span>
                                </div>
                              );
                            })}
                          </td>
                        </tr>
                      );
                    })}
                  </tbody>
                </table>
              </div>
              <div style={{ padding: "12px 20px", borderTop: "1px solid " + c.bd, fontSize: 12, color: c.txM }}>全{ROBOTS.length}施設</div>
            </div>
          </div>
        )}

        {/* SCHEDULE */}
        {page === "schedule" && (
          <div>
            <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 24 }}>
              <h1 style={{ fontSize: 22, fontWeight: 700, margin: 0 }}>{t("スケジュール管理")}</h1>
              <input value={sSrch} onChange={function (e) { setSSrch(e.target.value); }} placeholder="施設名 / シリアル" style={{ fontSize: 12, padding: "6px 12px", borderRadius: 6, border: "1px solid " + c.bd, background: c.sfH, color: c.tx, width: 180 }} />
            </div>
            <div style={{ background: c.sf, border: "1px solid " + c.bd, borderRadius: 12, overflow: "hidden" }}>
              <table style={{ width: "100%", borderCollapse: "collapse" }}>
                <thead><tr>
                  <th style={Object.assign({}, th, { textAlign: "left" })}>シリアル</th>
                  <th style={Object.assign({}, th, { textAlign: "left" })}>施設名</th>
                  <th style={Object.assign({}, th, { textAlign: "left" })}>曜日</th>
                  <th style={Object.assign({}, th, { textAlign: "left" })}>時間</th>
                  <th style={Object.assign({}, th, { textAlign: "center" })}>有効</th>
                </tr></thead>
                <tbody>
                  {SCHED.filter(function (s) { return !sSrch || s.s.toLowerCase().indexOf(sSrch.toLowerCase()) >= 0 || s.f.toLowerCase().indexOf(sSrch.toLowerCase()) >= 0; }).map(function (s, i) {
                    return (
                      <tr key={i} style={{ borderBottom: "1px solid " + c.bd + "22", opacity: s.on ? 1 : 0.5 }}>
                        <td style={{ padding: "12px", fontFamily: "monospace", fontSize: 12, color: c.tx }}>{s.s}</td>
                        <td style={td}>{s.f}</td>
                        <td style={td}>{s.d}</td>
                        <td style={td}>{s.st} - {s.en}</td>
                        <td style={{ padding: "12px", textAlign: "center", fontSize: 18, color: s.on ? c.ok : c.ng }}>{s.on ? "●" : "○"}</td>
                      </tr>
                    );
                  })}
                </tbody>
              </table>
            </div>
          </div>
        )}

        {/* INSPECTION RECORDS */}
        {page === "inspection" && (
          <div>
            <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 16 }}>
              <div>
                <h1 style={{ fontSize: 22, fontWeight: 700, margin: "0 0 4px" }}>{t("点検記録")}</h1>
                <div style={{ fontSize: 13, color: c.txD }}>{t("定期点検の実施記録・写真・申し送り事項を管理")}</div>
              </div>
              <div style={{ display: "flex", gap: 8 }}>
                <button style={{ fontSize: 12, color: c.pr, background: c.prD, border: "none", borderRadius: 6, padding: "8px 14px", cursor: "pointer" }}>{t("📥 CSVインポート")}</button>
                <button onClick={function () { setInspNew(true); }} style={{ fontSize: 12, color: "#fff", background: c.pr, border: "none", borderRadius: 6, padding: "8px 16px", cursor: "pointer", fontWeight: 600 }}>{t("+ 新規登録")}</button>
              </div>
            </div>
            <div style={{ display: "flex", gap: 10, marginBottom: 16, flexWrap: "wrap", alignItems: "center" }}>
              <div style={{ display: "flex", alignItems: "center", gap: 6 }}>
                <input type="date" defaultValue="2026-03-01" style={{ fontSize: 12, padding: "6px 10px", borderRadius: 6, border: "1px solid " + c.bd, background: c.sfH, color: c.tx }} />
                <span style={{ fontSize: 12, color: c.txM }}>〜</span>
                <input type="date" defaultValue="2026-03-31" style={{ fontSize: 12, padding: "6px 10px", borderRadius: 6, border: "1px solid " + c.bd, background: c.sfH, color: c.tx }} />
              </div>
              <select style={{ fontSize: 12, padding: "6px 10px", borderRadius: 6, border: "1px solid " + c.bd, background: c.sfH, color: c.tx }}>
                <option>{t("全グループ")}</option><option>PPIH</option>
              </select>
              <select style={{ fontSize: 12, padding: "6px 10px", borderRadius: 6, border: "1px solid " + c.bd, background: c.sfH, color: c.tx }}>
                <option>{t("全会社")}</option><option>ドン・キホーテ</option><option>ユニー</option>
              </select>
              <input placeholder="施設名 / 記入者" style={{ fontSize: 12, padding: "6px 12px", borderRadius: 6, border: "1px solid " + c.bd, background: c.sfH, color: c.tx, width: 180 }} />
            </div>
            <div style={{ display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: 12, marginBottom: 20 }}>
              <div style={{ background: c.sf, border: "1px solid " + c.bd, borderRadius: 10, padding: "12px 16px", display: "flex", alignItems: "center", gap: 12 }}>
                <div style={{ fontSize: 28, fontWeight: 700, color: c.pr }}>{INSPECTIONS.length}</div>
                <div><div style={{ fontSize: 12, fontWeight: 600, color: c.tx }}>{t("総点検数")}</div><div style={{ fontSize: 11, color: c.txM }}>{t("期間内")}</div></div>
              </div>
              <div style={{ background: c.sf, border: "1px solid " + c.bd, borderRadius: 10, padding: "12px 16px", display: "flex", alignItems: "center", gap: 12 }}>
                <div style={{ fontSize: 28, fontWeight: 700, color: c.ok }}>{new Set(INSPECTIONS.map(function (x) { return x.facility; })).size}</div>
                <div><div style={{ fontSize: 12, fontWeight: 600, color: c.tx }}>{t("点検施設数")}</div><div style={{ fontSize: 11, color: c.txM }}>{t("ユニーク")}</div></div>
              </div>
              <div style={{ background: c.sf, border: "1px solid " + c.bd, borderRadius: 10, padding: "12px 16px", display: "flex", alignItems: "center", gap: 12 }}>
                <div style={{ fontSize: 28, fontWeight: 700, color: c.wn }}>{INSPECTIONS.filter(function (x) { return x.notes; }).length}</div>
                <div><div style={{ fontSize: 12, fontWeight: 600, color: c.tx }}>{t("申し送りあり")}</div><div style={{ fontSize: 11, color: c.txM }}>{t("要確認")}</div></div>
              </div>
            </div>
            <div style={{ background: c.sf, border: "1px solid " + c.bd, borderRadius: 12, overflow: "hidden" }}>
              <div style={{ overflowX: "auto" }}>
              <table style={{ width: "100%", borderCollapse: "collapse", minWidth: 800 }}>
                <thead><tr>
                  <th style={Object.assign({}, th, { textAlign: "left" })}>訪問日</th>
                  <th style={Object.assign({}, th, { textAlign: "left" })}>記入者</th>
                  <th style={Object.assign({}, th, { textAlign: "left" })}>所属会社</th>
                  <th style={Object.assign({}, th, { textAlign: "left" })}>店舗名</th>
                  <th style={Object.assign({}, th, { textAlign: "left" })}>ブランド</th>
                  <th style={Object.assign({}, th, { textAlign: "left" })}>シリアル</th>
                  <th style={Object.assign({}, th, { textAlign: "center" })}>申し送り</th>
                  <th style={Object.assign({}, th, { textAlign: "center" })}>操作</th>
                </tr></thead>
                <tbody>
                  {INSPECTIONS.map(function (ins, i) {
                    return (
                      <tr key={i} style={{ borderBottom: "1px solid " + c.bd + "22" }}>
                        <td style={{ padding: "12px", fontSize: 13, color: c.tx }}>{ins.date}</td>
                        <td style={Object.assign({}, td, { fontWeight: 600 })}>{ins.inspector}</td>
                        <td style={{ padding: "12px", fontSize: 12, color: c.txD }}>{ins.company}</td>
                        <td style={td}>{ins.facility}</td>
                        <td style={td}><Pill text={ins.brand} color={ins.brand === "ユニー" ? c.ac : c.pr} /></td>
                        <td style={{ padding: "12px", fontSize: 11, fontFamily: "monospace", color: c.txM }}>{ins.robot}</td>
                        <td style={{ padding: "12px", textAlign: "center" }}>{ins.notes ? <span style={{ fontSize: 12, color: c.wn, fontWeight: 600 }}>{t("あり")}</span> : <span style={{ fontSize: 12, color: c.txM }}>ー</span>}</td>
                        <td style={{ padding: "12px", textAlign: "center" }}>
                          <button onClick={function () { setInspDetail(ins); }} style={{ fontSize: 11, color: c.pr, background: c.prD, border: "none", borderRadius: 4, padding: "4px 10px", cursor: "pointer" }}>{t("詳細")}</button>
                        </td>
                      </tr>
                    );
                  })}
                </tbody>
              </table>
              </div>
            </div>
          </div>
        )}

        {/* SYSTEM */}
        {page === "system" && (
          <div>
            <h1 style={{ fontSize: 22, fontWeight: 700, margin: "0 0 16px" }}>{t("システム管理")}</h1>

            {/* Sub-menu tabs */}
            <div style={{ display: "flex", gap: 4, marginBottom: 24, borderBottom: "1px solid " + c.bd, paddingBottom: 0 }}>
              {[
                { id: "display", label: t("表示設定") },
                { id: "ops", label: t("運用設定") },
                { id: "notify", label: t("通知設定") },
                { id: "users", label: t("ユーザー管理") },
                { id: "roles", label: t("権限管理") },
                { id: "customer", label: t("顧客管理") },
                { id: "group", label: t("グループ管理") },
                { id: "ops", label: t("運用設定") },
                { id: "auditlog", label: t("監査ログ") },
              ].map(function (tab) {
                var active = sysTab === tab.id;
                return (
                  <button key={tab.id} onClick={function () { setSysTab(tab.id); }} style={{
                    fontSize: 13, fontWeight: active ? 600 : 400, padding: "10px 20px",
                    cursor: "pointer", border: "none", borderBottom: active ? "2px solid " + c.pr : "2px solid transparent",
                    background: "transparent", color: active ? c.pr : c.txD,
                    marginBottom: -1,
                  }}>
                    {tab.label}
                  </button>
                );
              })}
            </div>

            {/* 表示設定 */}
            {sysTab === "display" && (
              <div>
                <div style={{ background: c.sf, border: "1px solid " + c.bd, borderRadius: 12, overflow: "hidden" }}>
                  <div style={{ padding: "16px 20px", borderBottom: "1px solid " + c.bd }}>
                    <div style={{ fontSize: 14, fontWeight: 600, color: c.tx }}>ダッシュボード表示項目</div>
                    <div style={{ fontSize: 12, color: c.txM, marginTop: 2 }}>各項目のON/OFFでダッシュボードの表示内容をカスタマイズ</div>
                  </div>
                  {[
                    { key: "secBanner", label: "D-Securityアラートバナー", desc: "セキュリティ無効施設の赤色警告バナー" },
                    { key: "detailLog", label: "清掃詳細ログ(コンパクト版)", desc: "△×の清掃詳細ログテーブル" },
                    { key: "scheduleBar", label: "スケジュール進捗", desc: "完了数/予定数のプログレスバー" },
                    { key: "failBreakdown", label: "失敗の内訳", desc: "ロボット異常/未実施/セキュリティ有効/制御盤異常の件数" },
                  ].map(function (item, i) {
                    var isOn = dashItems[item.key];
                    return (
                      <div key={i} style={{ padding: "14px 20px", borderBottom: "1px solid " + c.bd + "44", display: "flex", justifyContent: "space-between", alignItems: "center" }}>
                        <div>
                          <div style={{ fontSize: 13, fontWeight: 600, color: c.tx }}>{item.label}</div>
                          <div style={{ fontSize: 12, color: c.txM, marginTop: 2 }}>{item.desc}</div>
                        </div>
                        <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
                          <button onClick={function () {
                            var next = {};
                            Object.keys(dashItems).forEach(function (k) { next[k] = dashItems[k]; });
                            next[item.key] = !isOn;
                            setDashItems(next);
                          }} style={{ width: 48, height: 26, borderRadius: 13, border: "none", cursor: "pointer", background: isOn ? c.ok : c.bd, position: "relative" }}>
                            <div style={{ width: 20, height: 20, borderRadius: 10, background: "#fff", position: "absolute", top: 3, left: isOn ? 25 : 3, transition: "left .2s" }} />
                          </button>
                          <span style={{ fontSize: 12, fontWeight: 600, color: isOn ? c.ok : c.txM, width: 28 }}>{isOn ? "ON" : "OFF"}</span>
                        </div>
                      </div>
                    );
                  })}
                </div>
              </div>
            )}

            {/* 運用設定 */}
            {sysTab === "ops" && (
              <div>
                <div style={{ background: c.sf, border: "1px solid " + c.bd, borderRadius: 12, overflow: "hidden", marginBottom: 16 }}>
                  <div style={{ padding: "16px 20px", borderBottom: "1px solid " + c.bd }}>
                    <div style={{ fontSize: 14, fontWeight: 600, color: c.tx }}>{t("事前チェック設定")}</div>
                    <div style={{ fontSize: 12, color: c.txM, marginTop: 2 }}>清掃開始予定時刻の何分前にロボット状態を自動チェックするかを設定</div>
                  </div>
                  <div style={{ padding: "20px" }}>
                    <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 20 }}>
                      <div>
                        <label style={{ fontSize: 12, color: c.txM, display: "block", marginBottom: 6 }}>第1回チェック(分前)</label>
                        <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
                          <input type="number" defaultValue="60" min="10" max="120" style={{ fontSize: 14, padding: "8px 12px", borderRadius: 6, border: "1px solid " + c.bd, background: c.sfH, color: c.tx, width: 80, textAlign: "right" }} />
                          <span style={{ fontSize: 13, color: c.txD }}>{t("分前")}</span>
                          <span style={{ fontSize: 11, color: c.txM, marginLeft: 8 }}>デフォルト: 60分</span>
                        </div>
                      </div>
                      <div>
                        <label style={{ fontSize: 12, color: c.txM, display: "block", marginBottom: 6 }}>第2回チェック(分前)</label>
                        <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
                          <input type="number" defaultValue="30" min="5" max="60" style={{ fontSize: 14, padding: "8px 12px", borderRadius: 6, border: "1px solid " + c.bd, background: c.sfH, color: c.tx, width: 80, textAlign: "right" }} />
                          <span style={{ fontSize: 13, color: c.txD }}>{t("分前")}</span>
                          <span style={{ fontSize: 11, color: c.txM, marginLeft: 8 }}>デフォルト: 30分</span>
                        </div>
                      </div>
                    </div>
                  </div>
                </div>

                <div style={{ background: c.sf, border: "1px solid " + c.bd, borderRadius: 12, overflow: "hidden", marginBottom: 16 }}>
                  <div style={{ padding: "16px 20px", borderBottom: "1px solid " + c.bd }}>
                    <div style={{ fontSize: 14, fontWeight: 600, color: c.tx }}>{t("完了率の判定閾値")}</div>
                    <div style={{ fontSize: 12, color: c.txM, marginTop: 2 }}>清掃詳細ログの◎○△×判定に使用する閾値を設定</div>
                  </div>
                  <div style={{ padding: "20px" }}>
                    <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr 1fr", gap: 20 }}>
                      {[["◎ 基準", 90, c.ok, "以上で◎"], ["○ 基準", 70, c.ok, "以上で○(◎未満)"], ["△ 基準", 10, c.wn, "以上で△(○未満)"]].map(function (item, i) {
                        return (
                          <div key={i}>
                            <label style={{ fontSize: 12, color: c.txM, display: "block", marginBottom: 6 }}>{item[0]}</label>
                            <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
                              <input type="number" defaultValue={item[1]} min="0" max="100" style={{ fontSize: 14, padding: "8px 12px", borderRadius: 6, border: "1px solid " + c.bd, background: c.sfH, color: c.tx, width: 70, textAlign: "right" }} />
                              <span style={{ fontSize: 13, color: c.txD }}>%</span>
                            </div>
                            <div style={{ fontSize: 11, color: c.txM, marginTop: 4 }}>{item[3]}</div>
                          </div>
                        );
                      })}
                    </div>
                    <div style={{ fontSize: 11, color: c.txM, marginTop: 12 }}>※ △基準未満は自動的に×判定。現在はシステム全体の設定。P2以降で顧客別設定に拡張予定</div>
                  </div>
                </div>

                <div style={{ background: c.sf, border: "1px solid " + c.bd, borderRadius: 12, overflow: "hidden" }}>
                  <div style={{ padding: "16px 20px", borderBottom: "1px solid " + c.bd }}>
                    <div style={{ fontSize: 14, fontWeight: 600, color: c.tx }}>{t("アドバイス エスカレーション閾値")}</div>
                    <div style={{ fontSize: 12, color: c.txM, marginTop: 2 }}>対応アドバイスのレベルが上がる連続日数の閾値を設定</div>
                  </div>
                  <div style={{ padding: "20px" }}>
                    <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 20 }}>
                      <div>
                        <label style={{ fontSize: 12, color: c.txM, display: "block", marginBottom: 6 }}>レベル2(DFA運用がアクション)</label>
                        <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
                          <input type="number" defaultValue="2" min="2" max="7" style={{ fontSize: 14, padding: "8px 12px", borderRadius: 6, border: "1px solid " + c.bd, background: c.sfH, color: c.tx, width: 70, textAlign: "right" }} />
                          <span style={{ fontSize: 13, color: c.txD }}>{t("日以上連続")}</span>
                        </div>
                      </div>
                      <div>
                        <label style={{ fontSize: 12, color: c.txM, display: "block", marginBottom: 6 }}>レベル3(DFA介入・オンサイト訪問検討)</label>
                        <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
                          <input type="number" defaultValue="3" min="2" max="14" style={{ fontSize: 14, padding: "8px 12px", borderRadius: 6, border: "1px solid " + c.bd, background: c.sfH, color: c.tx, width: 70, textAlign: "right" }} />
                          <span style={{ fontSize: 13, color: c.txD }}>{t("日以上連続")}</span>
                        </div>
                      </div>
                    </div>
                    <div style={{ fontSize: 11, color: c.txM, marginTop: 12 }}>※「連続」はスケジュール存在日の連続。実績データに基づき調整を推奨</div>
                  </div>
                </div>
              </div>
            )}

            {/* 通知設定 */}
            {sysTab === "notify" && (
              <div>
                <div style={{ background: c.sf, border: "1px solid " + c.bd, borderRadius: 12, overflow: "hidden" }}>
                  <div style={{ padding: "16px 20px", borderBottom: "1px solid " + c.bd, display: "flex", justifyContent: "space-between", alignItems: "center" }}>
                    <div>
                      <div style={{ fontSize: 14, fontWeight: 600, color: c.tx }}>通知設定</div>
                      <div style={{ fontSize: 12, color: c.txM, marginTop: 2 }}>顧客デフォルト+施設上書きの継承モデル</div>
                    </div>
                    <button style={{ fontSize: 12, color: c.pr, background: c.prD, border: "none", borderRadius: 6, padding: "6px 14px", cursor: "pointer" }}>+ 通知追加</button>
                  </div>
                  <table style={{ width: "100%", borderCollapse: "collapse" }}>
                    <thead><tr>
                      <th style={Object.assign({}, th, { textAlign: "left" })}>チャネル</th>
                      <th style={Object.assign({}, th, { textAlign: "left" })}>送信先</th>
                      <th style={Object.assign({}, th, { textAlign: "left" })}>イベント</th>
                      <th style={Object.assign({}, th, { textAlign: "left" })}>スコープ</th>
                    </tr></thead>
                    <tbody>
                      {[
                        { ch: "Slack", dest: "#donki-robot-alert", ev: "Critical, Warning", sc: "全施設(デフォルト)" },
                        { ch: "メール", dest: "ops@donki.co.jp", ev: "Critical", sc: "全施設(デフォルト)" },
                        { ch: "Slack", dest: "#shibuya-ops", ev: "全イベント", sc: "渋谷本店(上書き)" },
                      ].map(function (n, i) {
                        return (
                          <tr key={i} style={{ borderBottom: "1px solid " + c.bd + "22" }}>
                            <td style={td}><Pill text={n.ch} color={n.ch === "Slack" ? c.ac : c.pr} /></td>
                            <td style={{ padding: "12px", fontSize: 12, fontFamily: "monospace", color: c.txD }}>{n.dest}</td>
                            <td style={td}>{n.ev}</td>
                            <td style={{ padding: "12px", fontSize: 12, color: n.sc.indexOf("上書き") >= 0 ? c.ac : c.txD }}>{n.sc}</td>
                          </tr>
                        );
                      })}
                    </tbody>
                  </table>
                </div>
              </div>
            )}

            {/* ユーザー管理 */}
            {sysTab === "users" && (
              <div>
                <div style={{ background: c.sf, border: "1px solid " + c.bd, borderRadius: 12, overflow: "hidden" }}>
                  <div style={{ padding: "16px 20px", borderBottom: "1px solid " + c.bd, display: "flex", justifyContent: "space-between", alignItems: "center" }}>
                    <div>
                      <div style={{ fontSize: 14, fontWeight: 600, color: c.tx }}>ユーザーマスタ</div>
                      <div style={{ fontSize: 12, color: c.txM, marginTop: 2 }}>顧客管理者は会社/グループに紐づく。施設運用者は施設に紐づく</div>
                    </div>
                    <button onClick={function () { setUserEdit({ nm: "", em: "", rl: "DFA運用担当", co: "DFA Robotics", fac: "ー" }); }} style={{ fontSize: 12, color: "#fff", background: c.pr, border: "none", borderRadius: 6, padding: "8px 16px", cursor: "pointer", fontWeight: 600 }}>{t("+ 新規登録")}</button>
                  </div>
                  <div style={{ overflowX: "auto" }}>
                    <table style={{ width: "100%", borderCollapse: "collapse", minWidth: 1000 }}>
                      <thead><tr>
                        <th style={Object.assign({}, th, { textAlign: "left" })}>名前</th>
                        <th style={Object.assign({}, th, { textAlign: "left" })}>メール</th>
                        <th style={Object.assign({}, th, { textAlign: "left" })}>ロール</th>
                        <th style={Object.assign({}, th, { textAlign: "left" })}>会社/グループ</th>
                        <th style={Object.assign({}, th, { textAlign: "left" })}>施設</th>
                        <th style={Object.assign({}, th, { textAlign: "left" })}>最終ログイン</th>
                        <th style={Object.assign({}, th, { textAlign: "center" })}>操作</th>
                      </tr></thead>
                      <tbody>
                        {[
                          { nm: "田中 太郎", em: "tanaka@dfa.co.jp", rl: "DFAシステム管理者", co: "DFA Robotics", fac: "ー", ll: "2026-03-27 09:02" },
                          { nm: "佐藤 花子", em: "sato@dfa.co.jp", rl: "DFA運用担当", co: "DFA Robotics", fac: "ー", ll: "2026-03-27 09:05" },
                          { nm: "鈴木 一郎", em: "suzuki@dfa.co.jp", rl: "DFA運用担当", co: "DFA Robotics", fac: "ー", ll: "2026-03-26 09:10" },
                          { nm: "中野 浩二", em: "nakano@donki.co.jp", rl: "顧客管理者", co: "ドン・キホーテ", fac: "ー(会社全体)", ll: "2026-03-25 14:00" },
                          { nm: "小林 美咲", em: "kobayashi@donki.co.jp", rl: "施設運用者", co: "ドン・キホーテ", fac: "MEGAドンキ渋谷本店", ll: "2026-03-27 06:30" },
                          { nm: "渡辺 翔", em: "watanabe@donki.co.jp", rl: "施設運用者", co: "ドン・キホーテ", fac: "ドンキ新宿歌舞伎町店", ll: "2026-03-27 06:45" },
                        ].map(function (u, i) {
                          var rlCol = u.rl.indexOf("システム管理") >= 0 ? c.pr : u.rl.indexOf("運用担当") >= 0 ? c.ac : u.rl.indexOf("顧客") >= 0 ? c.wn : c.txD;
                          return (
                            <tr key={i} style={{ borderBottom: "1px solid " + c.bd + "22", cursor: "pointer" }} onClick={function () { setUserEdit(u); }}>
                              <td style={Object.assign({}, td, { fontWeight: 600 })}>{u.nm}</td>
                              <td style={{ padding: "12px", fontSize: 12, fontFamily: "monospace", color: c.txD }}>{u.em}</td>
                              <td style={td}><Pill text={u.rl} color={rlCol} /></td>
                              <td style={td}>{u.co}</td>
                              <td style={{ padding: "12px", fontSize: 12, color: u.fac === "ー" || u.fac.indexOf("全体") >= 0 ? c.txM : c.tx }}>{u.fac}</td>
                              <td style={{ padding: "12px", fontSize: 12, color: c.txM }}>{u.ll}</td>
                              <td style={{ padding: "12px", textAlign: "center" }}>
                                <div style={{ display: "flex", gap: 6, justifyContent: "center" }}>
                                  <button style={{ fontSize: 11, color: c.pr, background: c.prD, border: "none", borderRadius: 4, padding: "4px 10px", cursor: "pointer" }}>{t("編集")}</button>
                                  <button style={{ fontSize: 11, color: c.ng, background: "none", border: "1px solid " + c.ng + "44", borderRadius: 4, padding: "4px 10px", cursor: "pointer" }}>{t("削除")}</button>
                                </div>
                              </td>
                            </tr>
                          );
                        })}
                      </tbody>
                    </table>
                  </div>
                </div>
              </div>
            )}

            {/* 権限管理 */}
            {sysTab === "roles" && (
              <div>
                <div style={{ background: c.sf, border: "1px solid " + c.bd, borderRadius: 12, overflow: "hidden", marginBottom: 16 }}>
                  <div style={{ padding: "16px 20px", borderBottom: "1px solid " + c.bd }}>
                    <div style={{ fontSize: 14, fontWeight: 600, color: c.tx }}>ロール定義(4層)</div>
                    <div style={{ fontSize: 12, color: c.txM, marginTop: 2 }}>各ロールのスコープと紐づき</div>
                  </div>
                  <table style={{ width: "100%", borderCollapse: "collapse" }}>
                    <thead><tr>
                      <th style={Object.assign({}, th, { textAlign: "left" })}>ロール</th>
                      <th style={Object.assign({}, th, { textAlign: "left" })}>実装</th>
                      <th style={Object.assign({}, th, { textAlign: "left" })}>紐づき</th>
                      <th style={Object.assign({}, th, { textAlign: "left" })}>データスコープ</th>
                      <th style={Object.assign({}, th, { textAlign: "left" })}>説明</th>
                    </tr></thead>
                    <tbody>
                      {[
                        { rl: "DFAシステム管理者", ph: "P1", bind: "ー", sc: "全顧客・全施設", desc: "全権限。権限管理の編集はこのロールのみ" },
                        { rl: "DFA運用担当", ph: "P1", bind: "ー", sc: "全顧客・全施設", desc: "全メニュー閲覧+施設ロボットマスタ編集。権限管理は閲覧のみ" },
                        { rl: "顧客管理者", ph: "P2", bind: "会社", sc: "自社施設のみ", desc: "自社の閲覧全般。施設ロボットマスタの編集不可" },
                        { rl: "施設運用者・清掃業者", ph: "P2", bind: "施設", sc: "自施設のみ", desc: "設定メニュー以外の自施設データを閲覧" },
                      ].map(function (r, i) {
                        var bindCol = r.bind === "会社" ? c.wn : r.bind === "施設" ? c.ac : c.txM;
                        return (
                          <tr key={i} style={{ borderBottom: "1px solid " + c.bd + "22" }}>
                            <td style={Object.assign({}, td, { fontWeight: 600 })}>{r.rl}</td>
                            <td style={td}><Pill text={r.ph} color={r.ph === "P1" ? c.ok : c.txM} /></td>
                            <td style={{ padding: "12px", textAlign: "center" }}>{r.bind !== "ー" ? <Pill text={r.bind} color={bindCol} /> : <span style={{ color: c.txM }}>ー</span>}</td>
                            <td style={td}>{r.sc}</td>
                            <td style={tdm}>{r.desc}</td>
                          </tr>
                        );
                      })}
                    </tbody>
                  </table>
                </div>
                <div style={{ background: c.sf, border: "1px solid " + c.bd, borderRadius: 12, overflow: "hidden" }}>
                  <div style={{ padding: "16px 20px", borderBottom: "1px solid " + c.bd }}>
                    <div style={{ fontSize: 14, fontWeight: 600, color: c.tx }}>メニュー×ロール アクセスマトリクス</div>
                    <div style={{ fontSize: 12, color: c.txM, marginTop: 2 }}>施設運用者のスコープは自施設のみに限定</div>
                  </div>
                  <div style={{ overflowX: "auto" }}>
                    <table style={{ width: "100%", borderCollapse: "collapse", minWidth: 800 }}>
                      <thead><tr>
                        <th style={Object.assign({}, th, { textAlign: "left" })}>メニュー</th>
                        <th style={Object.assign({}, th, { textAlign: "center" })}>DFA管理者</th>
                        <th style={Object.assign({}, th, { textAlign: "center" })}>DFA運用</th>
                        <th style={Object.assign({}, th, { textAlign: "center" })}>顧客管理者</th>
                        <th style={Object.assign({}, th, { textAlign: "center" })}>施設運用者</th>
                      </tr></thead>
                      <tbody>
                        {[
                          { menu: "ダッシュボード", v: ["閲覧", "閲覧", "閲覧", "閲覧"] },
                          { menu: "清掃詳細ログ", v: ["閲覧", "閲覧", "閲覧", "閲覧"] },
                          { menu: "アラート", v: ["閲覧", "閲覧", "閲覧", "閲覧"] },
                          { menu: "レポート", v: ["閲覧", "閲覧", "閲覧", "閲覧"] },
                          { menu: "D-Secログ", v: ["閲覧", "閲覧", "閲覧", "閲覧"] },
                          { menu: "D-Secアラート", v: ["閲覧", "閲覧", "閲覧", "閲覧"] },
                          { menu: "施設ロボットマスタ", v: ["閲覧/編集/登録", "閲覧/編集/登録", "閲覧", "×"] },
                          { menu: "スケジュール", v: ["閲覧", "閲覧", "閲覧", "閲覧"] },
                          { menu: "システム設定", v: ["", "", "", ""], sec: true },
                          { menu: "表示設定", v: ["閲覧/編集", "閲覧/編集", "閲覧/編集", "閲覧/編集"], sub: true },
                          { menu: "運用設定", v: ["閲覧/編集", "閲覧", "×", "×"], sub: true },
                          { menu: "通知設定", v: ["閲覧/編集/登録", "閲覧", "閲覧", "×"], sub: true },
                          { menu: "ユーザー管理", v: ["閲覧/編集/登録", "閲覧", "×", "×"], sub: true },
                          { menu: "権限管理", v: ["閲覧/編集/登録", "閲覧", "×", "×"], sub: true },
                          { menu: "顧客管理", v: ["閲覧/編集/登録", "閲覧", "×", "×"], sub: true },
                          { menu: "グループ管理", v: ["閲覧/編集/登録", "閲覧", "×", "×"], sub: true },
                          { menu: "運用設定", v: ["閲覧/編集", "閲覧", "×", "×"], sub: true },
                          { menu: "監査ログ", v: ["閲覧", "閲覧", "×", "×"], sub: true },
                        ].map(function (r, i) {
                          function acStyle(v) {
                            if (!v) return { padding: "8px 12px", textAlign: "center" };
                            var col = c.txM;
                            if (v.indexOf("登録") >= 0) col = c.pr;
                            else if (v.indexOf("編集") >= 0) col = c.ok;
                            else if (v === "閲覧") col = c.txD;
                            else if (v === "×") col = c.ng;
                            return { padding: "8px 12px", textAlign: "center", fontSize: 11, color: col, fontWeight: v.indexOf("登録") >= 0 ? 600 : 400 };
                          }
                          if (r.sec) {
                            return (
                              <tr key={i} style={{ borderBottom: "1px solid " + c.bd }}>
                                <td colSpan={5} style={{ padding: "10px 12px", fontSize: 11, fontWeight: 700, color: c.txM, textTransform: "uppercase", letterSpacing: 1, background: c.sfH }}>{r.menu}</td>
                              </tr>
                            );
                          }
                          return (
                            <tr key={i} style={{ borderBottom: "1px solid " + c.bd + "22", background: r.sub ? c.sfH : "transparent" }}>
                              <td style={{ padding: "8px 12px", fontSize: 13, color: c.tx, paddingLeft: r.sub ? 32 : 12 }}>{r.sub ? "└ " : ""}{r.menu}</td>
                              <td style={acStyle(r.v[0])}>{r.v[0]}</td>
                              <td style={acStyle(r.v[1])}>{r.v[1]}</td>
                              <td style={acStyle(r.v[2])}>{r.v[2]}</td>
                              <td style={acStyle(r.v[3])}>{r.v[3]}</td>
                            </tr>
                          );
                        })}
                      </tbody>
                    </table>
                  </div>
                  <div style={{ padding: "12px 20px", borderTop: "1px solid " + c.bd, fontSize: 12, color: c.txM }}>
                    <span style={{ color: c.pr, fontWeight: 600 }}>閲覧/編集/登録</span> = フル権限 / <span style={{ color: c.ok }}>閲覧/編集</span> = 新規登録不可 / <span style={{ color: c.txD }}>閲覧</span> = 表示のみ / <span style={{ color: c.ng }}>×</span> = アクセス不可
                  </div>
                </div>
              </div>
            )}

            {/* 顧客管理 */}
            {sysTab === "customer" && (
              <div>
                <div style={{ background: c.sf, border: "1px solid " + c.bd, borderRadius: 12, overflow: "hidden" }}>
                  <div style={{ padding: "16px 20px", borderBottom: "1px solid " + c.bd, display: "flex", justifyContent: "space-between", alignItems: "center" }}>
                    <div>
                      <div style={{ fontSize: 14, fontWeight: 600, color: c.tx }}>顧客管理</div>
                      <div style={{ fontSize: 12, color: c.txM, marginTop: 2 }}>会社単位の契約・モジュール管理</div>
                    </div>
                    <button onClick={function () { setCustEdit({ grp: "", nm: "", ct: "", plan: "Monitor Assist", mon: true, dsec: false, st: "有効" }); }} style={{ fontSize: 12, color: c.pr, background: c.prD, border: "none", borderRadius: 6, padding: "6px 14px", cursor: "pointer" }}>{t("+ 顧客追加")}</button>
                  </div>
                  <div style={{ overflowX: "auto" }}>
                    <table style={{ width: "100%", borderCollapse: "collapse", minWidth: 900 }}>
                      <thead><tr>
                        <th style={Object.assign({}, th, { textAlign: "left" })}>グループ</th>
                        <th style={Object.assign({}, th, { textAlign: "left" })}>会社名</th>
                        <th style={Object.assign({}, th, { textAlign: "left" })}>連絡先</th>
                        <th style={Object.assign({}, th, { textAlign: "left" })}>契約プラン</th>
                        <th style={Object.assign({}, th, { textAlign: "center" })}>契約モジュール</th>
                        <th style={Object.assign({}, th, { textAlign: "center" })}>監視施設</th>
                        <th style={Object.assign({}, th, { textAlign: "center" })}>D-Sec施設</th>
                        <th style={Object.assign({}, th, { textAlign: "right" })}>全施設</th>
                        <th style={Object.assign({}, th, { textAlign: "right" })}>ロボット</th>
                        <th style={Object.assign({}, th, { textAlign: "center" })}>状態</th>
                        <th style={Object.assign({}, th, { textAlign: "center" })}>操作</th>
                      </tr></thead>
                      <tbody>
                        {[
                          { grp: "PPIH", nm: "株式会社ドン・キホーテ", ct: "nakano@donki.co.jp", plan: "Insight Assist", mon: true, dsec: true, monF: 9, dsecF: 5, fac: 9, rob: 11, st: "有効" },
                          { grp: "PPIH", nm: "株式会社ユニー", ct: "ito@uny.co.jp", plan: "Monitor Assist", mon: true, dsec: false, monF: 2, dsecF: 0, fac: 2, rob: 2, st: "有効" },
                          { grp: "ー", nm: "株式会社セブン-イレブン", ct: "tanaka@sej.co.jp", plan: "Monitor Assist", mon: true, dsec: false, monF: 3, dsecF: 0, fac: 3, rob: 3, st: "有効" },
                          { grp: "ー", nm: "株式会社ローソン", ct: "suzuki@lawson.co.jp", plan: "D-Security", mon: false, dsec: true, monF: 0, dsecF: 2, fac: 2, rob: 0, st: "有効" },
                        ].map(function (cu, i) {
                          return (
                            <tr key={i} style={{ borderBottom: "1px solid " + c.bd + "22" }}>
                              <td style={{ padding: "12px", fontSize: 12, color: cu.grp === "ー" ? c.txM : c.tx, fontWeight: cu.grp !== "ー" ? 600 : 400 }}>{cu.grp}</td>
                              <td style={Object.assign({}, td, { fontWeight: 600 })}>{cu.nm}</td>
                              <td style={{ padding: "12px", fontSize: 11, fontFamily: "monospace", color: c.txD }}>{cu.ct}</td>
                              <td style={td}><Pill text={cu.plan} color={c.pr} /></td>
                              <td style={{ padding: "12px", textAlign: "center" }}>
                                <div style={{ display: "inline-flex", gap: 6, alignItems: "center" }}>
                                  <span style={{ fontSize: 12, padding: "2px 8px", borderRadius: 4, background: cu.mon ? c.ok + "22" : "transparent", color: cu.mon ? c.ok : c.txM, border: "1px solid " + (cu.mon ? c.ok + "44" : c.bd) }}>{cu.mon ? "○ 監視" : "ー 監視"}</span>
                                  <span style={{ fontSize: 12, padding: "2px 8px", borderRadius: 4, background: cu.dsec ? c.ac + "22" : "transparent", color: cu.dsec ? c.ac : c.txM, border: "1px solid " + (cu.dsec ? c.ac + "44" : c.bd) }}>{cu.dsec ? "○ D-Sec" : "ー D-Sec"}</span>
                                </div>
                              </td>
                              <td style={{ padding: "12px", textAlign: "center", color: cu.monF > 0 ? c.ok : c.txM }}>{cu.monF > 0 ? cu.monF + " / " + cu.fac : "ー"}</td>
                              <td style={{ padding: "12px", textAlign: "center", color: cu.dsecF > 0 ? c.ac : c.txM }}>{cu.dsecF > 0 ? cu.dsecF + " / " + cu.fac : "ー"}</td>
                              <td style={{ padding: "12px", textAlign: "right" }}>{cu.fac}</td>
                              <td style={{ padding: "12px", textAlign: "right" }}>{cu.rob}</td>
                              <td style={{ padding: "12px", textAlign: "center" }}><Pill text={cu.st} color={c.ok} /></td>
                              <td style={{ padding: "12px", textAlign: "center" }}>
                                <div style={{ display: "flex", gap: 6, justifyContent: "center" }}>
                                  <button onClick={function () { setCustEdit(cu); }} style={{ fontSize: 11, color: c.pr, background: c.prD, border: "none", borderRadius: 4, padding: "4px 10px", cursor: "pointer" }}>{t("編集")}</button>
                                  <button style={{ fontSize: 11, color: c.ng, background: "none", border: "1px solid " + c.ng + "44", borderRadius: 4, padding: "4px 10px", cursor: "pointer" }}>{t("削除")}</button>
                                </div>
                              </td>
                            </tr>
                          );
                        })}
                      </tbody>
                    </table>
                  </div>
                </div>
              </div>
            )}

            {/* グループ管理 */}
            {sysTab === "group" && (
              <div>
                <div style={{ background: c.sf, border: "1px solid " + c.bd, borderRadius: 12, overflow: "hidden" }}>
                  <div style={{ padding: "16px 20px", borderBottom: "1px solid " + c.bd, display: "flex", justifyContent: "space-between", alignItems: "center" }}>
                    <div>
                      <div style={{ fontSize: 14, fontWeight: 600, color: c.tx }}>グループ管理</div>
                      <div style={{ fontSize: 12, color: c.txM, marginTop: 2 }}>グループ会社の親子関係を管理。顧客管理者をグループに紐づけると傘下の全会社を横断閲覧可能</div>
                    </div>
                    <button onClick={function () { setGrpEdit({ nm: "", companies: [] }); }} style={{ fontSize: 12, color: c.pr, background: c.prD, border: "none", borderRadius: 6, padding: "6px 14px", cursor: "pointer" }}>{t("+ グループ追加")}</button>
                  </div>
                  <div style={{ overflowX: "auto" }}>
                    <table style={{ width: "100%", borderCollapse: "collapse" }}>
                      <thead><tr>
                        <th style={Object.assign({}, th, { textAlign: "left" })}>グループ名</th>
                        <th style={Object.assign({}, th, { textAlign: "left" })}>連絡先</th>
                        <th style={Object.assign({}, th, { textAlign: "left" })}>傘下会社</th>
                        <th style={Object.assign({}, th, { textAlign: "right" })}>会社数</th>
                        <th style={Object.assign({}, th, { textAlign: "right" })}>総施設数</th>
                        <th style={Object.assign({}, th, { textAlign: "right" })}>総ロボット数</th>
                        <th style={Object.assign({}, th, { textAlign: "center" })}>状態</th>
                        <th style={Object.assign({}, th, { textAlign: "center" })}>操作</th>
                      </tr></thead>
                      <tbody>
                        {[
                          { nm: "PPIH", ct: "admin@ppih.co.jp", tel: "03-5791-1111", companies: ["株式会社ドン・キホーテ", "株式会社ユニー"], cnt: 2, fac: 11, rob: 13, st: "有効" },
                        ].map(function (g, i) {
                          return (
                            <tr key={i} style={{ borderBottom: "1px solid " + c.bd + "22" }}>
                              <td style={Object.assign({}, td, { fontWeight: 600 })}>{g.nm}</td>
                              <td style={{ padding: "12px", fontSize: 11, fontFamily: "monospace", color: c.txD }}>{g.ct}</td>
                              <td style={{ padding: "12px" }}>
                                {g.companies.map(function (co, j) {
                                  return <span key={j} style={{ display: "inline-block", fontSize: 11, padding: "2px 8px", borderRadius: 4, background: c.prD, color: c.pr, marginRight: 4, marginBottom: 2 }}>{co}</span>;
                                })}
                              </td>
                              <td style={{ padding: "12px", textAlign: "right" }}>{g.cnt}</td>
                              <td style={{ padding: "12px", textAlign: "right" }}>{g.fac}</td>
                              <td style={{ padding: "12px", textAlign: "right" }}>{g.rob}</td>
                              <td style={{ padding: "12px", textAlign: "center" }}><Pill text={g.st} color={c.ok} /></td>
                              <td style={{ padding: "12px", textAlign: "center" }}>
                                <div style={{ display: "flex", gap: 6, justifyContent: "center" }}>
                                  <button onClick={function () { setGrpEdit(g); }} style={{ fontSize: 11, color: c.pr, background: c.prD, border: "none", borderRadius: 4, padding: "4px 10px", cursor: "pointer" }}>{t("編集")}</button>
                                  <button style={{ fontSize: 11, color: c.ng, background: "none", border: "1px solid " + c.ng + "44", borderRadius: 4, padding: "4px 10px", cursor: "pointer" }}>{t("削除")}</button>
                                </div>
                              </td>
                            </tr>
                          );
                        })}
                      </tbody>
                    </table>
                  </div>
                </div>
              </div>
            )}

            {/* 運用設定 */}
            {sysTab === "ops" && (
              <div>
                <div style={{ background: c.sf, border: "1px solid " + c.bd, borderRadius: 12, overflow: "hidden" }}>
                  <div style={{ padding: "16px 20px", borderBottom: "1px solid " + c.bd }}>
                    <div style={{ fontSize: 14, fontWeight: 600, color: c.tx }}>運用設定</div>
                    <div style={{ fontSize: 12, color: c.txM, marginTop: 2 }}>清掃監視の運用パラメータ。変更はDFAシステム管理者のみ</div>
                  </div>

                  {/* 事前チェック設定 */}
                  <div style={{ padding: "16px 20px", borderBottom: "1px solid " + c.bd }}>
                    <div style={{ fontSize: 13, fontWeight: 600, color: c.tx, marginBottom: 12 }}>{t("事前チェック設定")}</div>
                    <div style={{ fontSize: 12, color: c.txM, marginBottom: 12 }}>清掃開始予定時刻の何分前にロボット状態をチェックするか</div>
                    <div style={{ display: "flex", gap: 24 }}>
                      <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
                        <span style={{ fontSize: 13, color: c.tx }}>第1回チェック</span>
                        <input type="number" defaultValue={60} min={10} max={120} style={{ width: 70, fontSize: 13, padding: "6px 10px", borderRadius: 6, border: "1px solid " + c.bd, background: c.sfH, color: c.tx, textAlign: "right" }} />
                        <span style={{ fontSize: 12, color: c.txM }}>{t("分前")}</span>
                      </div>
                      <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
                        <span style={{ fontSize: 13, color: c.tx }}>第2回チェック</span>
                        <input type="number" defaultValue={30} min={5} max={60} style={{ width: 70, fontSize: 13, padding: "6px 10px", borderRadius: 6, border: "1px solid " + c.bd, background: c.sfH, color: c.tx, textAlign: "right" }} />
                        <span style={{ fontSize: 12, color: c.txM }}>{t("分前")}</span>
                      </div>
                    </div>
                  </div>

                  {/* 判定閾値設定 */}
                  <div style={{ padding: "16px 20px", borderBottom: "1px solid " + c.bd }}>
                    <div style={{ fontSize: 13, fontWeight: 600, color: c.tx, marginBottom: 12 }}>{t("完了率の判定閾値")}</div>
                    <div style={{ fontSize: 12, color: c.txM, marginBottom: 12 }}>清掃詳細ログの◎○△×判定に使用する閾値</div>
                    <div style={{ display: "flex", gap: 16 }}>
                      {[
                        { label: "◎", desc: "以上", def: 90, color: c.ok },
                        { label: "○", desc: "以上", def: 70, color: c.ok },
                        { label: "△", desc: "以上", def: 10, color: c.wn },
                        { label: "×", desc: "未満", def: 10, color: c.ng },
                      ].map(function (g, i) {
                        return (
                          <div key={i} style={{ display: "flex", alignItems: "center", gap: 6 }}>
                            <span style={{ display: "inline-block", width: 28, height: 28, lineHeight: "28px", textAlign: "center", borderRadius: 6, fontSize: 14, fontWeight: 700, background: g.color + "18", color: g.color, border: "1px solid " + g.color + "33" }}>{g.label}</span>
                            {i < 3 && <input type="number" defaultValue={g.def} min={0} max={100} style={{ width: 60, fontSize: 13, padding: "6px 8px", borderRadius: 6, border: "1px solid " + c.bd, background: c.sfH, color: c.tx, textAlign: "right" }} />}
                            {i < 3 && <span style={{ fontSize: 12, color: c.txM }}>%{g.desc}</span>}
                            {i === 3 && <span style={{ fontSize: 12, color: c.txM }}>上記未満</span>}
                          </div>
                        );
                      })}
                    </div>
                  </div>

                  {/* エスカレーション閾値 */}
                  <div style={{ padding: "16px 20px" }}>
                    <div style={{ fontSize: 13, fontWeight: 600, color: c.tx, marginBottom: 12 }}>{t("アドバイス エスカレーション閾値")}</div>
                    <div style={{ fontSize: 12, color: c.txM, marginBottom: 12 }}>同一施設で問題が連続した場合のレベル引き上げ基準(スケジュール存在日の連続日数)</div>
                    <div style={{ display: "flex", gap: 24 }}>
                      <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
                        <span style={{ fontSize: 12, padding: "2px 10px", borderRadius: 4, background: c.wn + "18", color: c.wn, fontWeight: 600 }}>Lv2</span>
                        <input type="number" defaultValue={2} min={2} max={7} style={{ width: 60, fontSize: 13, padding: "6px 8px", borderRadius: 6, border: "1px solid " + c.bd, background: c.sfH, color: c.tx, textAlign: "right" }} />
                        <span style={{ fontSize: 12, color: c.txM }}>{t("日以上連続")}</span>
                      </div>
                      <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
                        <span style={{ fontSize: 12, padding: "2px 10px", borderRadius: 4, background: c.ng + "18", color: c.ng, fontWeight: 600 }}>Lv3</span>
                        <input type="number" defaultValue={3} min={2} max={14} style={{ width: 60, fontSize: 13, padding: "6px 8px", borderRadius: 6, border: "1px solid " + c.bd, background: c.sfH, color: c.tx, textAlign: "right" }} />
                        <span style={{ fontSize: 12, color: c.txM }}>{t("日以上連続")}</span>
                      </div>
                    </div>
                  </div>
                </div>
              </div>
            )}

            {/* 監査ログ */}
            {sysTab === "auditlog" && (
              <div>
                <div style={{ background: c.sf, border: "1px solid " + c.bd, borderRadius: 12, overflow: "hidden" }}>
                  <div style={{ padding: "16px 20px", borderBottom: "1px solid " + c.bd }}>
                    <div style={{ fontSize: 14, fontWeight: 600, color: c.tx }}>操作ログ(監査ログ)</div>
                    <div style={{ fontSize: 12, color: c.txM, marginTop: 2 }}>全ての手動操作を記録。誰が・いつ・何をしたかを追跡</div>
                  </div>
                  <table style={{ width: "100%", borderCollapse: "collapse" }}>
                    <thead><tr>
                      <th style={Object.assign({}, th, { textAlign: "left" })}>日時</th>
                      <th style={Object.assign({}, th, { textAlign: "left" })}>操作者</th>
                      <th style={Object.assign({}, th, { textAlign: "left" })}>アクション</th>
                      <th style={Object.assign({}, th, { textAlign: "left" })}>対象</th>
                    </tr></thead>
                    <tbody>
                      {[
                        { t: "2026-03-27 09:15", u: "田中 太郎", a: "清掃開始(手動)", tg: "MEGAドンキ渋谷本店 / 1F売場" },
                        { t: "2026-03-26 22:30", u: "田中 太郎", a: "スケジュール変更", tg: "ドンキ八王子駅前店 — 無効化" },
                        { t: "2026-03-26 15:00", u: "佐藤 花子", a: "ロボット同期", tg: "8111R5628060011 v3.2に更新" },
                        { t: "2026-03-25 11:00", u: "田中 太郎", a: "顧客モジュール変更", tg: "ドン・キホーテ — D-Security有効化" },
                        { t: "2026-03-25 10:30", u: "田中 太郎", a: "施設追加", tg: "MEGAドンキ大森山王店" },
                      ].map(function (l, i) {
                        return (
                          <tr key={i} style={{ borderBottom: "1px solid " + c.bd + "22" }}>
                            <td style={{ padding: "12px", fontSize: 12, fontFamily: "monospace", color: c.txM }}>{l.t}</td>
                            <td style={td}>{l.u}</td>
                            <td style={td}><Pill text={l.a} color={l.a.indexOf("手動") >= 0 ? c.wn : c.pr} /></td>
                            <td style={{ padding: "12px", fontSize: 12, color: c.txD }}>{l.tg}</td>
                          </tr>
                        );
                      })}
                    </tbody>
                  </table>
                </div>
              </div>
            )}

          </div>
        )}

      </div>

      {/* Customer Edit Modal */}
      {custEdit && (
        <Modal title={custEdit.nm ? "顧客編集 — " + custEdit.nm : "顧客追加"} onClose={function () { setCustEdit(null); }} action={custEdit.nm ? "保存" : "登録"}>
          <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 16 }}>
            <div style={fieldSt}>
              <label style={labelSt}>グループ</label>
              <select defaultValue={custEdit.grp || ""} style={selectSt}>
                <option value="">ー(グループなし)</option>
                <option value="PPIH">PPIH</option>
              </select>
            </div>
            <div style={fieldSt}>
              <label style={labelSt}>会社名 *</label>
              <input defaultValue={custEdit.nm || ""} placeholder="例: 株式会社○○" style={inputSt} />
            </div>
            <div style={fieldSt}>
              <label style={labelSt}>連絡先メール *</label>
              <input defaultValue={custEdit.ct || ""} placeholder="admin@example.co.jp" style={inputSt} />
            </div>
            <div style={fieldSt}>
              <label style={labelSt}>契約プラン</label>
              <select defaultValue={custEdit.plan || "Monitor Assist"} style={selectSt}>
                <option value="Monitor Assist">Monitor Assist</option>
                <option value="Insight Assist">Insight Assist</option>
                <option value="D-Security">D-Security</option>
              </select>
            </div>
          </div>
          <div style={fieldSt}>
            <label style={labelSt}>契約モジュール</label>
            <div style={{ display: "flex", gap: 24, padding: "10px 0" }}>
              <label style={{ display: "flex", alignItems: "center", gap: 8, cursor: "pointer" }}>
                <input type="checkbox" defaultChecked={custEdit.mon !== false} />
                <span style={{ fontSize: 13, padding: "4px 12px", borderRadius: 6, background: c.ok + "18", color: c.ok, border: "1px solid " + c.ok + "44" }}>○ 監視(モニタリング)</span>
              </label>
              <label style={{ display: "flex", alignItems: "center", gap: 8, cursor: "pointer" }}>
                <input type="checkbox" defaultChecked={custEdit.dsec === true} />
                <span style={{ fontSize: 13, padding: "4px 12px", borderRadius: 6, background: c.ac + "18", color: c.ac, border: "1px solid " + c.ac + "44" }}>○ D-Security</span>
              </label>
            </div>
          </div>
          <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 16 }}>
            <div style={fieldSt}>
              <label style={labelSt}>電話番号</label>
              <input defaultValue="" placeholder="03-1234-5678" style={inputSt} />
            </div>
            <div style={fieldSt}>
              <label style={labelSt}>状態</label>
              <select defaultValue={custEdit.st || "有効"} style={selectSt}>
                <option value="有効">有効</option>
                <option value="停止">停止</option>
              </select>
            </div>
          </div>
        </Modal>
      )}

      {/* User Edit Modal */}
      {userEdit && (
        <Modal title={userEdit.ll ? "ユーザー編集 — " + userEdit.nm : "ユーザー新規登録"} onClose={function () { setUserEdit(null); }} action={userEdit.ll ? "保存" : "登録"}>
          <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 16 }}>
            <div style={fieldSt}>
              <label style={labelSt}>名前 *</label>
              <input defaultValue={userEdit.nm || ""} placeholder="姓 名" style={inputSt} />
            </div>
            <div style={fieldSt}>
              <label style={labelSt}>メールアドレス *</label>
              <input defaultValue={userEdit.em || ""} placeholder="user@example.co.jp" style={inputSt} />
            </div>
          </div>
          <div style={fieldSt}>
            <label style={labelSt}>ロール *</label>
            <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 8, padding: "6px 0" }}>
              {["DFAシステム管理者", "DFA運用担当", "顧客管理者", "施設運用者"].map(function (rl) {
                var active = (userEdit.rl || "") === rl;
                var col = rl.indexOf("システム管理") >= 0 ? c.pr : rl.indexOf("運用担当") >= 0 ? c.ac : rl.indexOf("顧客") >= 0 ? c.wn : c.txD;
                return (
                  <div key={rl} style={{ padding: "8px 12px", borderRadius: 6, border: "1px solid " + (active ? col : c.bd), background: active ? col + "18" : "transparent", cursor: "pointer", fontSize: 13, color: active ? col : c.txD }}>
                    {active ? "● " : "○ "}{rl}
                  </div>
                );
              })}
            </div>
          </div>
          <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 16 }}>
            <div style={fieldSt}>
              <label style={labelSt}>会社 / グループ *</label>
              <select defaultValue={userEdit.co || ""} style={selectSt}>
                <option value="DFA Robotics">DFA Robotics</option>
                <option value="PPIH">PPIH(グループ)</option>
                <option value="ドン・キホーテ">株式会社ドン・キホーテ</option>
                <option value="ユニー">株式会社ユニー</option>
                <option value="セブン-イレブン">株式会社セブン-イレブン</option>
                <option value="ローソン">株式会社ローソン</option>
              </select>
            </div>
            <div style={fieldSt}>
              <label style={labelSt}>施設(施設運用者のみ)</label>
              <select defaultValue={userEdit.fac || "ー"} style={selectSt}>
                <option value="ー">ー(会社/グループ全体)</option>
                <option value="MEGAドンキ渋谷本店">MEGAドンキ渋谷本店</option>
                <option value="ドンキ新宿歌舞伎町店">ドンキ新宿歌舞伎町店</option>
                <option value="MEGAドンキ池袋駅北口店">MEGAドンキ池袋駅北口店</option>
              </select>
            </div>
          </div>
          {userEdit.ll && (
            <div style={{ marginTop: 8, padding: "12px 16px", borderRadius: 8, background: c.sfH, border: "1px solid " + c.bd }}>
              <div style={{ fontSize: 12, color: c.txM }}>最終ログイン: {userEdit.ll}</div>
            </div>
          )}
        </Modal>
      )}

      {/* Group Edit Modal */}
      {grpEdit && (
        <Modal title={grpEdit.ct ? "グループ編集 — " + grpEdit.nm : "グループ追加"} onClose={function () { setGrpEdit(null); }} action={grpEdit.ct ? "保存" : "登録"}>
          <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 16 }}>
            <div style={fieldSt}>
              <label style={labelSt}>グループ名 *</label>
              <input defaultValue={grpEdit.nm || ""} placeholder="例: PPIH" style={inputSt} />
            </div>
            <div style={fieldSt}>
              <label style={labelSt}>連絡先メール</label>
              <input defaultValue={grpEdit.ct || ""} placeholder="admin@example.co.jp" style={inputSt} />
            </div>
            <div style={fieldSt}>
              <label style={labelSt}>電話番号</label>
              <input defaultValue={grpEdit.tel || ""} placeholder="03-1234-5678" style={inputSt} />
            </div>
            <div style={fieldSt}>
              <label style={labelSt}>状態</label>
              <select defaultValue={grpEdit.st || "有効"} style={selectSt}>
                <option value="有効">有効</option>
                <option value="停止">停止</option>
              </select>
            </div>
          </div>
          <div style={fieldSt}>
            <label style={labelSt}>傘下会社の選択</label>
            <div style={{ border: "1px solid " + c.bd, borderRadius: 8, overflow: "hidden" }}>
              {["株式会社ドン・キホーテ", "株式会社ユニー", "株式会社セブン-イレブン", "株式会社ローソン"].map(function (co, j) {
                var checked = grpEdit.companies && grpEdit.companies.indexOf(co) >= 0;
                return (
                  <label key={co} style={{ display: "flex", alignItems: "center", gap: 10, padding: "10px 14px", cursor: "pointer", borderBottom: j < 3 ? "1px solid " + c.bd + "44" : "none", background: checked ? c.pr + "08" : "transparent" }}>
                    <input type="checkbox" defaultChecked={checked} />
                    <span style={{ fontSize: 13, color: c.tx, fontWeight: checked ? 600 : 400, flex: 1 }}>{co}</span>
                    {checked && <Pill text="所属中" color={c.pr} />}
                  </label>
                );
              })}
            </div>
            <div style={{ fontSize: 11, color: c.txM, marginTop: 6 }}>チェックした会社がこのグループの傘下として紐づきます。グループ管理者は傘下全社のデータを横断閲覧可能になります。</div>
          </div>
          {grpEdit.cnt && (
            <div style={{ marginTop: 4, padding: "14px 16px", borderRadius: 8, background: c.sfH, border: "1px solid " + c.bd }}>
              <div style={{ fontSize: 12, fontWeight: 600, color: c.tx, marginBottom: 8 }}>グループサマリー</div>
              <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr 1fr", gap: 12 }}>
                <div style={{ textAlign: "center" }}>
                  <div style={{ fontSize: 20, fontWeight: 700, color: c.pr }}>{grpEdit.cnt}</div>
                  <div style={{ fontSize: 11, color: c.txM }}>傘下会社</div>
                </div>
                <div style={{ textAlign: "center" }}>
                  <div style={{ fontSize: 20, fontWeight: 700, color: c.ok }}>{grpEdit.fac}</div>
                  <div style={{ fontSize: 11, color: c.txM }}>総施設数</div>
                </div>
                <div style={{ textAlign: "center" }}>
                  <div style={{ fontSize: 20, fontWeight: 700, color: c.ac }}>{grpEdit.rob}</div>
                  <div style={{ fontSize: 11, color: c.txM }}>総ロボット数</div>
                </div>
              </div>
            </div>
          )}
        </Modal>
      )}

      {/* Area Detail Modal */}
      {areaModal && (
        <div style={{ position: "fixed", top: 0, left: 0, right: 0, bottom: 0, background: "rgba(0,0,0,0.5)", display: "flex", alignItems: "center", justifyContent: "center", zIndex: 1000 }}>
          <div style={{ background: c.sf, border: "1px solid " + c.bd, borderRadius: 16, width: 600, maxHeight: "80vh", display: "flex", flexDirection: "column" }}>
            <div style={{ padding: "20px 24px", borderBottom: "1px solid " + c.bd }}>
              <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start" }}>
                <div>
                  <div style={{ fontSize: 16, fontWeight: 700, color: c.tx }}>{t("エリア別清掃完了率")}</div>
                  <div style={{ fontSize: 13, color: c.txD, marginTop: 4 }}>{areaModal.facility} | {areaModal.date} | 全体 {areaModal.cp}% {areaModal.g}</div>
                </div>
                <button onClick={function () { setAreaModal(null); }} style={{ fontSize: 18, color: c.txM, background: "none", border: "none", cursor: "pointer", padding: "4px 8px" }}>✕</button>
              </div>
              <div style={{ display: "flex", gap: 6, marginTop: 12 }}>
                {["problem", "all"].map(function (f) {
                  var active = areaFilt === f;
                  var label = f === "problem" ? "問題エリアのみ" : "全件";
                  return <button key={f} onClick={function () { setAreaFilt(f); }} style={{ fontSize: 12, padding: "4px 12px", borderRadius: 6, border: "1px solid " + (active ? c.pr : c.bd), background: active ? c.prD : "transparent", color: active ? c.pr : c.txD, cursor: "pointer", fontWeight: active ? 600 : 400 }}>{label}</button>;
                })}
              </div>
            </div>
            <div style={{ overflowY: "auto", flex: 1, padding: "8px 0" }}>
              {(function () {
                var areas = getAreaData(areaModal.facility).map(function (a) { return Object.assign({}, a, { g: areaGrade(a.cp) }); });
                areas.sort(function (a, b) { return a.cp - b.cp; });
                var filtered = areaFilt === "problem" ? areas.filter(function (a) { return a.g === "△" || a.g === "×"; }) : areas;
                var problemCount = areas.filter(function (a) { return a.g === "△" || a.g === "×"; }).length;
                return (
                  <div>
                    <div style={{ padding: "4px 24px 8px", fontSize: 12, color: c.txM }}>
                      {areaFilt === "problem" ? "問題エリア(" + problemCount + " / " + areas.length + "エリア)" : "全" + areas.length + "エリア(完了率昇順)"}
                    </div>
                    {filtered.length === 0 && (
                      <div style={{ padding: "24px", textAlign: "center", color: c.txM, fontSize: 13 }}>問題エリアはありません(全エリア◎○)</div>
                    )}
                    {filtered.map(function (a, i) {
                      var gs = gradeStyle(c, a.g);
                      var barColor = a.g === "◎" || a.g === "○" ? c.ok : a.g === "△" ? c.wn : c.ng;
                      return (
                        <div key={i} style={{ display: "flex", alignItems: "center", gap: 12, padding: "8px 24px", borderBottom: "1px solid " + c.bd + "11" }}>
                          <div style={{ width: 120, fontSize: 13, fontWeight: a.g === "△" || a.g === "×" ? 600 : 400, color: a.g === "△" || a.g === "×" ? c.tx : c.txD, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{a.name}</div>
                          <div style={{ flex: 1, height: 8, background: c.bd + "44", borderRadius: 4, overflow: "hidden" }}>
                            <div style={{ width: a.cp + "%", height: "100%", background: barColor, borderRadius: 4 }} />
                          </div>
                          <div style={{ width: 40, textAlign: "right", fontSize: 13, fontWeight: 600, color: barColor }}>{a.cp}%</div>
                          <span style={{ display: "inline-block", width: 24, height: 24, lineHeight: "24px", textAlign: "center", borderRadius: 4, fontSize: 12, fontWeight: 700, background: gs.bg, color: gs.tx, border: "1px solid " + gs.tx + "33" }}>{a.g}</span>
                        </div>
                      );
                    })}
                  </div>
                );
              })()}
            </div>
            <div style={{ padding: "12px 24px", borderTop: "1px solid " + c.bd, display: "flex", justifyContent: "flex-end" }}>
              <button onClick={function () { setAreaModal(null); }} style={{ fontSize: 13, padding: "8px 20px", borderRadius: 6, border: "1px solid " + c.bd, background: "transparent", color: c.txD, cursor: "pointer" }}>{t("閉じる")}</button>
            </div>
          </div>
        </div>
      )}

      {/* Inspection Detail Modal */}
      {inspDetail && (
        <div style={{ position: "fixed", top: 0, left: 0, right: 0, bottom: 0, background: "rgba(0,0,0,0.5)", display: "flex", alignItems: "center", justifyContent: "center", zIndex: 1000 }}>
          <div style={{ background: c.sf, border: "1px solid " + c.bd, borderRadius: 16, width: 640, maxHeight: "85vh", display: "flex", flexDirection: "column" }}>
            <div style={{ padding: "20px 24px", borderBottom: "1px solid " + c.bd, display: "flex", justifyContent: "space-between", alignItems: "flex-start" }}>
              <div>
                <div style={{ fontSize: 16, fontWeight: 700, color: c.tx }}>{t("点検記録 詳細")}</div>
                <div style={{ fontSize: 13, color: c.txD, marginTop: 4 }}>{inspDetail.facility} | {inspDetail.date}</div>
              </div>
              <button onClick={function () { setInspDetail(null); }} style={{ fontSize: 18, color: c.txM, background: "none", border: "none", cursor: "pointer", padding: "4px 8px" }}>✕</button>
            </div>
            <div style={{ overflowY: "auto", flex: 1, padding: "20px 24px" }}>
              <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12, marginBottom: 20 }}>
                <div style={{ fontSize: 12 }}><span style={{ color: c.txM }}>記入者:</span> <span style={{ color: c.tx, fontWeight: 600 }}>{inspDetail.inspector}</span></div>
                <div style={{ fontSize: 12 }}><span style={{ color: c.txM }}>所属会社:</span> <span style={{ color: c.tx }}>{inspDetail.company}</span></div>
                <div style={{ fontSize: 12 }}><span style={{ color: c.txM }}>ブランド:</span> <span style={{ color: c.tx }}>{inspDetail.brand}</span></div>
                <div style={{ fontSize: 12 }}><span style={{ color: c.txM }}>シリアル:</span> <span style={{ fontFamily: "monospace", color: c.tx }}>{inspDetail.robot}</span></div>
              </div>

              <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 16 }}>
                {["Before(点検前)", "After(点検後)"].map(function (phase, pi) {
                  return (
                    <div key={pi}>
                      <div style={{ fontSize: 13, fontWeight: 600, color: pi === 0 ? c.wn : c.ok, marginBottom: 10, padding: "4px 10px", background: (pi === 0 ? c.wn : c.ok) + "12", borderRadius: 6, display: "inline-block" }}>{phase}</div>
                      {INSP_ITEMS.map(function (item, j) {
                        return (
                          <div key={j} style={{ display: "flex", alignItems: "center", justifyContent: "space-between", padding: "8px 12px", borderBottom: "1px solid " + c.bd + "22" }}>
                            <span style={{ fontSize: 12, color: c.tx }}>{item}</span>
                            <span style={{ fontSize: 11, color: c.pr, background: c.prD, padding: "2px 8px", borderRadius: 4, cursor: "pointer" }}>📷 写真</span>
                          </div>
                        );
                      })}
                    </div>
                  );
                })}
              </div>

              {inspDetail.notes && (
                <div style={{ marginTop: 16 }}>
                  <div style={{ fontSize: 13, fontWeight: 600, color: c.tx, marginBottom: 6 }}>{t("申し送り事項")}</div>
                  <div style={{ fontSize: 13, color: c.txD, padding: "12px 16px", background: c.sfH, borderRadius: 8, border: "1px solid " + c.bd, lineHeight: 1.6 }}>{inspDetail.notes}</div>
                </div>
              )}
            </div>
            <div style={{ padding: "12px 24px", borderTop: "1px solid " + c.bd, display: "flex", justifyContent: "flex-end" }}>
              <button onClick={function () { setInspDetail(null); }} style={{ fontSize: 13, padding: "8px 20px", borderRadius: 6, border: "1px solid " + c.bd, background: "transparent", color: c.txD, cursor: "pointer" }}>{t("閉じる")}</button>
            </div>
          </div>
        </div>
      )}

      {/* Inspection New Modal */}
      {inspNew && (
        <Modal title="点検記録 新規登録" onClose={function () { setInspNew(false); }} action="登録">
          <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 16 }}>
            <div style={fieldSt}>
              <label style={labelSt}>訪問日 *</label>
              <input type="date" defaultValue="2026-03-27" style={inputSt} />
            </div>
            <div style={fieldSt}>
              <label style={labelSt}>店舗 *</label>
              <select style={selectSt}>
                <option value="">選択してください</option>
                <option>MEGAUNY西大和店</option><option>アピタ大和郡山店</option><option>アピタ伊賀上野店</option><option>MEGAUNY名張店</option>
              </select>
            </div>
            <div style={fieldSt}>
              <label style={labelSt}>記入者氏名 *</label>
              <input defaultValue="" placeholder="姓 名" style={inputSt} />
            </div>
            <div style={fieldSt}>
              <label style={labelSt}>所属会社 *</label>
              <input defaultValue="DFA Robotics" style={inputSt} />
            </div>
            <div style={fieldSt}>
              <label style={labelSt}>ロボット *</label>
              <select style={selectSt}>
                <option value="">店舗を選択すると表示</option>
              </select>
            </div>
          </div>

          <div style={{ marginTop: 8 }}>
            <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 16 }}>
              {["Before(点検前)", "After(点検後)"].map(function (phase, pi) {
                return (
                  <div key={pi}>
                    <div style={{ fontSize: 13, fontWeight: 600, color: pi === 0 ? c.wn : c.ok, marginBottom: 10 }}>{phase}</div>
                    {INSP_ITEMS.map(function (item, j) {
                      return (
                        <div key={j} style={{ display: "flex", alignItems: "center", justifyContent: "space-between", padding: "6px 0", borderBottom: "1px solid " + c.bd + "22" }}>
                          <span style={{ fontSize: 12, color: c.tx }}>{item}</span>
                          <label style={{ fontSize: 11, color: c.pr, background: c.prD, padding: "4px 10px", borderRadius: 4, cursor: "pointer" }}>📷 アップロード</label>
                        </div>
                      );
                    })}
                  </div>
                );
              })}
            </div>
          </div>

          <div style={Object.assign({}, fieldSt, { marginTop: 12 })}>
            <label style={labelSt}>{t("申し送り事項")}</label>
            <textarea placeholder="申し送り事項があればこちらに記載ください" style={Object.assign({}, inputSt, { height: 80, resize: "vertical" })} />
          </div>
        </Modal>
      )}

    </div>
  );
}