{"id":26254,"date":"2026-01-16T01:21:04","date_gmt":"2026-01-15T16:21:04","guid":{"rendered":"http:\/\/www.tyosuke20xx.com\/blog\/?p=26254"},"modified":"2026-01-16T01:21:07","modified_gmt":"2026-01-15T16:21:07","slug":"vooglebrowser-2","status":"publish","type":"post","link":"http:\/\/www.tyosuke20xx.com\/blog\/?p=26254","title":{"rendered":"Vooglebrowser"},"content":{"rendered":"\n<pre class=\"wp-block-code\"><code>\n&lt;!DOCTYPE html>\n&lt;html lang=\"ja\">\n&lt;head>\n&lt;meta charset=\"UTF-8\" \/>\n&lt;meta name=\"viewport\" content=\"width=device-width, initial-scale=1, maximum-scale=1\" \/>\n&lt;title>Voogle - Mini Browser&lt;\/title>\n&lt;style>\n  :root{\n    --bg:#0b0f14;\n    --panel: rgba(255,255,255,.06);\n    --stroke: rgba(255,255,255,.10);\n    --ink:#eaf0ff;\n    --muted: rgba(234,240,255,.70);\n    --accent:#7cf0ff;\n    --accent2:#7ca0ff;\n    --danger:#ff6b6b;\n    --ok:#79ffa7;\n    --shadow: 0 18px 50px rgba(0,0,0,.35);\n    --radius:16px;\n    --radius2:22px;\n    --glass: blur(14px) saturate(1.2);\n  }\n  &#91;data-theme=\"light\"]{\n    --bg:#f6f7fb;\n    --panel: rgba(0,0,0,.05);\n    --stroke: rgba(0,0,0,.10);\n    --ink:#101828;\n    --muted: rgba(16,24,40,.68);\n    --shadow: 0 18px 50px rgba(16,24,40,.12);\n  }\n  *{box-sizing:border-box}\n  html,body{height:100%}\n  body{\n    margin:0;\n    background: radial-gradient(1200px 800px at 20% 10%, rgba(124,240,255,.15), transparent 60%),\n                radial-gradient(1200px 800px at 80% 20%, rgba(124,160,255,.14), transparent 60%),\n                var(--bg);\n    color:var(--ink);\n    font-family: ui-sans-serif, system-ui, -apple-system, \"Segoe UI\", Roboto, \"Noto Sans JP\", Arial;\n    overflow:hidden;\n  }\n  .app{\n    height:100%;\n    display:grid;\n    grid-template-columns: 320px 1fr;\n    gap: 12px;\n    padding: 12px;\n  }\n  .card{\n    background: linear-gradient(180deg, rgba(255,255,255,.08), rgba(255,255,255,.03));\n    border: 1px solid var(--stroke);\n    border-radius: var(--radius2);\n    box-shadow: var(--shadow);\n    backdrop-filter: var(--glass);\n    overflow:hidden;\n    min-height:0;\n  }\n  .sidebar{display:flex; flex-direction:column; min-height:0;}\n  .main{display:flex; flex-direction:column; min-height:0;}\n\n  \/* Topbar *\/\n  .topbar{\n    display:flex;\n    align-items:center;\n    gap:10px;\n    padding:10px;\n    border-bottom:1px solid var(--stroke);\n    background: rgba(0,0,0,.08);\n  }\n  &#91;data-theme=\"light\"] .topbar{ background: rgba(255,255,255,.55); }\n  .brand{\n    display:flex; align-items:center; gap:10px;\n    padding:10px;\n    border-bottom:1px solid var(--stroke);\n  }\n  .logo{\n    width:34px; height:34px; border-radius:12px;\n    background: radial-gradient(circle at 30% 30%, var(--accent), rgba(124,240,255,.0) 55%),\n                radial-gradient(circle at 70% 70%, var(--accent2), rgba(124,160,255,.0) 55%),\n                rgba(255,255,255,.06);\n    border:1px solid var(--stroke);\n    box-shadow: 0 12px 30px rgba(124,240,255,.14);\n  }\n  .brand h1{\n    font-size:14px; margin:0; letter-spacing:.4px;\n  }\n  .brand p{margin:0; font-size:12px; color:var(--muted)}\n  .btn{\n    appearance:none;\n    border:1px solid var(--stroke);\n    background: rgba(255,255,255,.06);\n    color:var(--ink);\n    padding:8px 10px;\n    border-radius: 12px;\n    cursor:pointer;\n    transition: transform .08s ease, background .15s ease, border-color .15s ease;\n    user-select:none;\n    white-space:nowrap;\n  }\n  .btn:hover{ background: rgba(255,255,255,.10); border-color: rgba(124,240,255,.28); }\n  .btn:active{ transform: scale(.98); }\n  .btn.primary{\n    border-color: rgba(124,240,255,.35);\n    background: linear-gradient(180deg, rgba(124,240,255,.18), rgba(124,160,255,.10));\n  }\n  .btn.danger{\n    border-color: rgba(255,107,107,.35);\n    background: linear-gradient(180deg, rgba(255,107,107,.16), rgba(255,107,107,.08));\n  }\n  .btn.ok{\n    border-color: rgba(121,255,167,.35);\n    background: linear-gradient(180deg, rgba(121,255,167,.14), rgba(121,255,167,.07));\n  }\n  .icon{\n    width:18px;height:18px;display:inline-grid;place-items:center;\n    font-weight:700; opacity:.9;\n  }\n\n  \/* Address *\/\n  .addr{\n    flex:1;\n    display:flex;\n    gap:10px;\n    align-items:center;\n    min-width:0;\n  }\n  .addr input{\n    width:100%;\n    min-width:0;\n    padding:10px 12px;\n    border-radius: 14px;\n    border:1px solid var(--stroke);\n    background: rgba(0,0,0,.14);\n    color:var(--ink);\n    outline:none;\n  }\n  &#91;data-theme=\"light\"] .addr input{ background: rgba(255,255,255,.75); }\n  .hint{\n    font-size:12px;\n    color:var(--muted);\n    padding: 0 12px 10px;\n  }\n\n  \/* Tabs *\/\n  .tabs{\n    display:flex;\n    gap:8px;\n    padding:10px;\n    border-bottom:1px solid var(--stroke);\n    overflow:auto;\n  }\n  .tab{\n    display:flex; align-items:center; gap:8px;\n    padding:8px 10px;\n    border-radius: 14px;\n    border:1px solid var(--stroke);\n    background: rgba(255,255,255,.06);\n    cursor:pointer;\n    min-width: 160px;\n    max-width: 260px;\n    flex: 0 0 auto;\n  }\n  .tab.active{\n    border-color: rgba(124,240,255,.45);\n    background: linear-gradient(180deg, rgba(124,240,255,.16), rgba(124,160,255,.10));\n  }\n  .tab .title{\n    overflow:hidden;\n    text-overflow:ellipsis;\n    white-space:nowrap;\n    font-size:13px;\n    flex:1;\n  }\n  .pill{\n    font-size:11px;\n    color:var(--muted);\n    border:1px solid var(--stroke);\n    padding:2px 8px;\n    border-radius:999px;\n    background: rgba(0,0,0,.10);\n  }\n  &#91;data-theme=\"light\"] .pill{ background: rgba(255,255,255,.6); }\n  .x{\n    width:24px;height:24px; border-radius:10px;\n    display:grid; place-items:center;\n    border:1px solid var(--stroke);\n    background: rgba(0,0,0,.10);\n    opacity:.9;\n  }\n  .x:hover{ border-color: rgba(255,107,107,.5); }\n  &#91;data-theme=\"light\"] .x{ background: rgba(255,255,255,.6); }\n\n  \/* Viewport *\/\n  .viewport{\n    position:relative;\n    flex:1;\n    min-height:0;\n    background: rgba(0,0,0,.10);\n  }\n  &#91;data-theme=\"light\"] .viewport{ background: rgba(0,0,0,.03); }\n  .frame{\n    position:absolute; inset:0;\n    width:100%; height:100%;\n    border:0;\n    background: transparent;\n  }\n  .overlay{\n    position:absolute; inset: 14px;\n    border-radius: 18px;\n    border:1px dashed rgba(124,240,255,.35);\n    display:none;\n    place-items:center;\n    text-align:center;\n    padding:18px;\n    background: rgba(0,0,0,.35);\n    backdrop-filter: blur(10px);\n  }\n  &#91;data-theme=\"light\"] .overlay{ background: rgba(255,255,255,.78); }\n  .overlay.show{ display:grid; }\n  .overlay h2{margin:0 0 8px; font-size:16px;}\n  .overlay p{margin:0 0 12px; color:var(--muted); font-size:13px;}\n  .overlay .row{display:flex; gap:10px; flex-wrap:wrap; justify-content:center}\n\n  \/* Sidebar content *\/\n  .section{\n    padding:12px;\n    border-top:1px solid var(--stroke);\n    min-height:0;\n    overflow:auto;\n  }\n  .section h3{\n    margin:0 0 10px;\n    font-size:12px;\n    color:var(--muted);\n    letter-spacing:.18em;\n  }\n  .list{\n    display:flex;\n    flex-direction:column;\n    gap:8px;\n  }\n  .item{\n    display:flex;\n    gap:10px;\n    align-items:center;\n    padding:10px 10px;\n    border-radius: 14px;\n    border:1px solid var(--stroke);\n    background: rgba(255,255,255,.05);\n    cursor:pointer;\n  }\n  .item:hover{ border-color: rgba(124,240,255,.28); background: rgba(255,255,255,.08); }\n  .item .meta{flex:1; min-width:0}\n  .item .meta .t{\n    font-size:13px;\n    overflow:hidden; white-space:nowrap; text-overflow:ellipsis;\n  }\n  .item .meta .s{\n    font-size:12px; color:var(--muted);\n    overflow:hidden; white-space:nowrap; text-overflow:ellipsis;\n  }\n  .tag{\n    font-size:11px;\n    padding:2px 8px;\n    border-radius: 999px;\n    border:1px solid var(--stroke);\n    color: var(--muted);\n  }\n\n  .footerbar{\n    padding:10px 12px;\n    border-top:1px solid var(--stroke);\n    font-size:12px;\n    color:var(--muted);\n    display:flex;\n    gap:12px;\n    align-items:center;\n    justify-content:space-between;\n  }\n  .kbd{\n    border:1px solid var(--stroke);\n    border-bottom-width:2px;\n    padding:2px 6px;\n    border-radius:8px;\n    background: rgba(0,0,0,.10);\n    font-size:11px;\n    color:var(--muted);\n    white-space:nowrap;\n  }\n  &#91;data-theme=\"light\"] .kbd{ background: rgba(255,255,255,.6); }\n\n  .row{\n    display:flex; gap:8px; flex-wrap:wrap;\n  }\n  .mini{\n    font-size:12px;\n    padding:6px 8px;\n    border-radius: 12px;\n  }\n\n  .toast{\n    position:fixed;\n    right:14px; bottom:14px;\n    padding:10px 12px;\n    border-radius: 14px;\n    border:1px solid var(--stroke);\n    background: rgba(0,0,0,.50);\n    backdrop-filter: blur(10px);\n    color:var(--ink);\n    box-shadow: var(--shadow);\n    transform: translateY(10px);\n    opacity:0;\n    transition: .22s ease;\n    pointer-events:none;\n    max-width: min(420px, calc(100vw - 28px));\n  }\n  &#91;data-theme=\"light\"] .toast{ background: rgba(255,255,255,.86); }\n  .toast.show{ transform: translateY(0); opacity:1; }\n  .toast .small{ font-size:12px; color:var(--muted); margin-top:2px; }\n\n  @media (max-width: 980px){\n    .app{ grid-template-columns: 1fr; }\n    .sidebar{ display:none; }\n  }\n&lt;\/style>\n&lt;\/head>\n&lt;body data-theme=\"dark\">\n  &lt;div class=\"app\">\n    &lt;!-- Sidebar -->\n    &lt;aside class=\"card sidebar\">\n      &lt;div class=\"brand\">\n        &lt;div class=\"logo\" aria-hidden=\"true\">&lt;\/div>\n        &lt;div>\n          &lt;h1>Voogle&lt;\/h1>\n          &lt;p>Mini Browser (1-file)&lt;\/p>\n        &lt;\/div>\n      &lt;\/div>\n\n      &lt;div class=\"section\" style=\"border-top:none\">\n        &lt;div class=\"row\">\n          &lt;button class=\"btn mini primary\" id=\"btnNewTab\">&lt;span class=\"icon\">+&lt;\/span>\u65b0\u898f\u30bf\u30d6&lt;\/button>\n          &lt;button class=\"btn mini\" id=\"btnToggleTheme\">&lt;span class=\"icon\">\u263e&lt;\/span>\u30c6\u30fc\u30de&lt;\/button>\n          &lt;button class=\"btn mini\" id=\"btnExport\">&lt;span class=\"icon\">\u2913&lt;\/span>\u30c7\u30fc\u30bf\u51fa\u529b&lt;\/button>\n          &lt;label class=\"btn mini\" style=\"display:inline-flex; align-items:center; gap:8px; cursor:pointer;\">\n            &lt;span class=\"icon\">\u2912&lt;\/span>\u30c7\u30fc\u30bf\u53d6\u8fbc\n            &lt;input id=\"importFile\" type=\"file\" accept=\"application\/json\" style=\"display:none\" \/>\n          &lt;\/label>\n        &lt;\/div>\n        &lt;div class=\"hint\">\u203b\u591a\u304f\u306e\u5916\u90e8\u30b5\u30a4\u30c8\u306f\u57cb\u3081\u8fbc\u307f\u7981\u6b62\u3002\u958b\u3051\u306a\u3044\u6642\u306f\u300c\u65b0\u3057\u3044\u30bf\u30d6\u3067\u958b\u304f\u300d\u3002&lt;\/div>\n      &lt;\/div>\n\n      &lt;div class=\"section\">\n        &lt;h3>\u30af\u30a4\u30c3\u30af&lt;\/h3>\n        &lt;div class=\"list\" id=\"quickList\">&lt;\/div>\n      &lt;\/div>\n\n      &lt;div class=\"section\">\n        &lt;h3>\u30d6\u30c3\u30af\u30de\u30fc\u30af&lt;\/h3>\n        &lt;div class=\"list\" id=\"bmList\">&lt;\/div>\n      &lt;\/div>\n\n      &lt;div class=\"section\">\n        &lt;h3>\u5c65\u6b74\uff08\u6700\u65b020\u4ef6\uff09&lt;\/h3>\n        &lt;div class=\"list\" id=\"histList\">&lt;\/div>\n      &lt;\/div>\n\n      &lt;div class=\"footerbar\">\n        &lt;div class=\"row\" style=\"gap:6px\">\n          &lt;span class=\"kbd\">Ctrl&lt;\/span>+&lt;span class=\"kbd\">L&lt;\/span> \u30a2\u30c9\u30ec\u30b9\n          &lt;span class=\"kbd\">Ctrl&lt;\/span>+&lt;span class=\"kbd\">T&lt;\/span> \u65b0\u898f\n          &lt;span class=\"kbd\">Ctrl&lt;\/span>+&lt;span class=\"kbd\">W&lt;\/span> \u9589\u3058\u308b\n        &lt;\/div>\n        &lt;span id=\"statusText\">Ready&lt;\/span>\n      &lt;\/div>\n    &lt;\/aside>\n\n    &lt;!-- Main -->\n    &lt;main class=\"card main\">\n      &lt;div class=\"topbar\">\n        &lt;button class=\"btn\" id=\"btnBack\" title=\"\u623b\u308b\">&lt;span class=\"icon\">\u2190&lt;\/span>&lt;\/button>\n        &lt;button class=\"btn\" id=\"btnForward\" title=\"\u9032\u3080\">&lt;span class=\"icon\">\u2192&lt;\/span>&lt;\/button>\n        &lt;button class=\"btn\" id=\"btnReload\" title=\"\u66f4\u65b0\">&lt;span class=\"icon\">\u21bb&lt;\/span>&lt;\/button>\n\n        &lt;div class=\"addr\">\n          &lt;input id=\"addrInput\" placeholder=\"URL \u307e\u305f\u306f \u691c\u7d22\u30ef\u30fc\u30c9\uff08\u4f8b: https:\/\/example.com \/ openai\uff09\" autocomplete=\"off\" \/>\n        &lt;\/div>\n\n        &lt;button class=\"btn primary\" id=\"btnGo\" title=\"\u79fb\u52d5\">&lt;span class=\"icon\">\u23ce&lt;\/span>&lt;\/button>\n        &lt;button class=\"btn\" id=\"btnBookmark\" title=\"\u30d6\u30c3\u30af\u30de\u30fc\u30af\">&lt;span class=\"icon\">\u2606&lt;\/span>&lt;\/button>\n        &lt;button class=\"btn\" id=\"btnOpenExternal\" title=\"\u65b0\u3057\u3044\u30bf\u30d6\u3067\u958b\u304f\">&lt;span class=\"icon\">\u2197&lt;\/span>&lt;\/button>\n        &lt;button class=\"btn\" id=\"btnPip\" title=\"PiP\uff08\u5bfe\u5fdc\u30b5\u30a4\u30c8\u306e\u307f\uff09\">&lt;span class=\"icon\">\u25a3&lt;\/span>&lt;\/button>\n      &lt;\/div>\n\n      &lt;div class=\"tabs\" id=\"tabs\">&lt;\/div>\n\n      &lt;div class=\"viewport\">\n        &lt;iframe id=\"frame\" class=\"frame\" sandbox=\"allow-forms allow-modals allow-popups allow-same-origin allow-scripts allow-downloads\">&lt;\/iframe>\n\n        &lt;div class=\"overlay\" id=\"overlay\">\n          &lt;div>\n            &lt;h2>\u3053\u306e\u30da\u30fc\u30b8\u306f\u57cb\u3081\u8fbc\u307f\u3092\u62d2\u5426\u3057\u3066\u308b&lt;\/h2>\n            &lt;p>\n              \u305f\u3044\u3066\u3044\u306f\u30b5\u30a4\u30c8\u5074\u306e\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3\uff08X-Frame-Options \/ CSP\uff09\u3067\u3059\u3002&lt;br>\n              \u4e0b\u306e\u30dc\u30bf\u30f3\u3067\u5916\u90e8\u30bf\u30d6\u3068\u3057\u3066\u958b\u3051\u3002\n            &lt;\/p>\n            &lt;div class=\"row\">\n              &lt;button class=\"btn ok\" id=\"overlayOpenExternal\">&lt;span class=\"icon\">\u2197&lt;\/span>\u65b0\u3057\u3044\u30bf\u30d6\u3067\u958b\u304f&lt;\/button>\n              &lt;button class=\"btn\" id=\"overlayTrySearch\">&lt;span class=\"icon\">\u2315&lt;\/span>\u691c\u7d22\u3067\u958b\u304f&lt;\/button>\n              &lt;button class=\"btn danger\" id=\"overlayClose\">&lt;span class=\"icon\">\u00d7&lt;\/span>\u9589\u3058\u308b&lt;\/button>\n            &lt;\/div>\n          &lt;\/div>\n        &lt;\/div>\n      &lt;\/div>\n\n      &lt;div class=\"footerbar\">\n        &lt;div class=\"row\" style=\"gap:10px; align-items:center\">\n          &lt;span class=\"tag\" id=\"originTag\">\u2014&lt;\/span>\n          &lt;span class=\"tag\" id=\"secureTag\">\u2014&lt;\/span>\n          &lt;span class=\"tag\" id=\"embedTag\">\u2014&lt;\/span>\n        &lt;\/div>\n        &lt;div class=\"row\" style=\"gap:8px\">\n          &lt;button class=\"btn mini\" id=\"btnHome\">\u30db\u30fc\u30e0&lt;\/button>\n          &lt;button class=\"btn mini\" id=\"btnClearHistory\">\u5c65\u6b74\u30af\u30ea\u30a2&lt;\/button>\n          &lt;button class=\"btn mini danger\" id=\"btnResetAll\">\u5168\u30ea\u30bb\u30c3\u30c8&lt;\/button>\n        &lt;\/div>\n      &lt;\/div>\n    &lt;\/main>\n  &lt;\/div>\n\n  &lt;div class=\"toast\" id=\"toast\">&lt;\/div>\n\n&lt;script>\n(() => {\n  \/\/ =========================\n  \/\/ Utilities\n  \/\/ =========================\n  const $ = (sel) => document.querySelector(sel);\n  const escapeHTML = (s) => (s ?? \"\").toString()\n    .replaceAll(\"&amp;\",\"&amp;amp;\").replaceAll(\"&lt;\",\"&amp;lt;\")\n    .replaceAll(\">\",\"&amp;gt;\").replaceAll('\"',\"&amp;quot;\").replaceAll(\"'\",\"&amp;#039;\");\n  const nowISO = () => new Date().toISOString();\n  const isUrlLike = (text) => {\n    const t = (text || \"\").trim();\n    if (!t) return false;\n    if (\/^https?:\\\/\\\/\/i.test(t)) return true;\n    if (\/^&#91;a-z0-9.-]+\\.&#91;a-z]{2,}(&#91;\\\/?#].*)?$\/i.test(t)) return true;\n    if (\/^localhost(:\\d+)?(\\\/.*)?$\/i.test(t)) return true;\n    if (\/^\\d{1,3}(\\.\\d{1,3}){3}(:\\d+)?(\\\/.*)?$\/.test(t)) return true;\n    return false;\n  };\n  const normalizeToUrl = (text) => {\n    let t = (text || \"\").trim();\n    if (!t) return \"\";\n    if (\/^https?:\\\/\\\/\/i.test(t)) return t;\n    if (isUrlLike(t)) return \"https:\/\/\" + t;\n    return \"\";\n  };\n  const buildSearchUrl = (q) => \"https:\/\/www.google.com\/search?q=\" + encodeURIComponent(q);\n\n  const toast = (title, detail=\"\") => {\n    const el = $(\"#toast\");\n    el.innerHTML = `&lt;div>&lt;b>${escapeHTML(title)}&lt;\/b>&lt;\/div>${detail ? `&lt;div class=\"small\">${escapeHTML(detail)}&lt;\/div>` : \"\"}`;\n    el.classList.add(\"show\");\n    clearTimeout(toast._t);\n    toast._t = setTimeout(() => el.classList.remove(\"show\"), 2400);\n  };\n\n  const setStatus = (s) => { $(\"#statusText\").textContent = s; };\n\n  \/\/ =========================\n  \/\/ Storage\n  \/\/ =========================\n  const KEY = \"voogle.v1\";\n  const defaultState = () => ({\n    theme: \"dark\",\n    tabs: &#91;\n      { id: crypto.randomUUID(), title: \"Home\", url: \"about:home\", history: &#91;\"about:home\"], hIndex: 0, createdAt: nowISO() }\n    ],\n    activeTabId: null,\n    bookmarks: &#91;\n      { title:\"OpenAI\", url:\"https:\/\/openai.com\", addedAt: nowISO() },\n      { title:\"Wikipedia\", url:\"https:\/\/ja.wikipedia.org\", addedAt: nowISO() },\n      { title:\"GitHub\", url:\"https:\/\/github.com\", addedAt: nowISO() },\n      { title:\"MDN\", url:\"https:\/\/developer.mozilla.org\/ja\/\", addedAt: nowISO() },\n      { title:\"YouTube\", url:\"https:\/\/www.youtube.com\", addedAt: nowISO() },\n    ],\n    history: &#91;],\n    quick: &#91;\n      { title:\"\u30cb\u30e5\u30fc\u30b9\", url:\"https:\/\/news.google.com\/?hl=ja&amp;gl=JP&amp;ceid=JP:ja\" },\n      { title:\"X\", url:\"https:\/\/x.com\" },\n      { title:\"Reddit\", url:\"https:\/\/www.reddit.com\" },\n      { title:\"Qiita\", url:\"https:\/\/qiita.com\" },\n      { title:\"Zenn\", url:\"https:\/\/zenn.dev\" },\n      { title:\"Google\", url:\"https:\/\/www.google.com\" },\n    ],\n    settings: {\n      homeUrl: \"about:home\",\n      maxHistory: 200,\n      sidebarHistoryView: 20\n    }\n  });\n\n  const loadState = () => {\n    try{\n      const raw = localStorage.getItem(KEY);\n      if(!raw) return defaultState();\n      const s = JSON.parse(raw);\n      \/\/ minimal migrate\n      if(!s.tabs?.length) return defaultState();\n      return s;\n    }catch(e){\n      console.warn(e);\n      return defaultState();\n    }\n  };\n  const saveState = () => localStorage.setItem(KEY, JSON.stringify(state));\n\n  let state = loadState();\n\n  \/\/ =========================\n  \/\/ Tabs\n  \/\/ =========================\n  const getActiveTab = () => state.tabs.find(t => t.id === state.activeTabId) || state.tabs&#91;0];\n  const setActive = (id) => {\n    state.activeTabId = id;\n    saveState();\n    renderAll();\n    loadTabToViewport(getActiveTab());\n  };\n\n  const newTab = (url = \"about:home\", title = \"New Tab\") => {\n    const tab = {\n      id: crypto.randomUUID(),\n      title,\n      url,\n      history: &#91;url],\n      hIndex: 0,\n      createdAt: nowISO()\n    };\n    state.tabs.push(tab);\n    state.activeTabId = tab.id;\n    saveState();\n    renderAll();\n    loadTabToViewport(tab);\n    toast(\"\u65b0\u898f\u30bf\u30d6\", title);\n  };\n\n  const closeTab = (id) => {\n    if(state.tabs.length &lt;= 1){\n      toast(\"\u3053\u308c\u4ee5\u4e0a\u9589\u3058\u308c\u306a\u3044\", \"\u6700\u4f4e1\u30bf\u30d6\u306f\u6b8b\u308b\");\n      return;\n    }\n    const idx = state.tabs.findIndex(t => t.id === id);\n    if(idx &lt; 0) return;\n    const wasActive = state.activeTabId === id;\n    const closed = state.tabs&#91;idx];\n    state.tabs.splice(idx,1);\n    if(wasActive){\n      const fallback = state.tabs&#91;Math.max(0, idx-1)];\n      state.activeTabId = fallback.id;\n    }\n    saveState();\n    renderAll();\n    loadTabToViewport(getActiveTab());\n    toast(\"\u30bf\u30d6\u3092\u9589\u3058\u305f\", closed.title);\n  };\n\n  const setTabTitle = (tab, title) => {\n    tab.title = (title || \"Untitled\").slice(0, 60);\n    saveState();\n    renderTabs();\n  };\n\n  const pushHistory = (tab, url) => {\n    if(tab.history&#91;tab.hIndex] === url) return;\n    tab.history = tab.history.slice(0, tab.hIndex + 1);\n    tab.history.push(url);\n    tab.hIndex = tab.history.length - 1;\n  };\n\n  \/\/ =========================\n  \/\/ History + Bookmarks\n  \/\/ =========================\n  const addGlobalHistory = (url, title=\"\") => {\n    if(!url || url === \"about:home\") return;\n    state.history.unshift({ url, title, at: nowISO() });\n    \/\/ de-dupe\n    const seen = new Set();\n    state.history = state.history.filter(h => {\n      const k = h.url;\n      if(seen.has(k)) return false;\n      seen.add(k);\n      return true;\n    });\n    state.history = state.history.slice(0, state.settings.maxHistory || 200);\n    saveState();\n    renderSidebar();\n  };\n\n  const isBookmarked = (url) => state.bookmarks.some(b => b.url === url);\n  const toggleBookmark = () => {\n    const tab = getActiveTab();\n    const url = tab.url;\n    if(!url || url === \"about:home\") return toast(\"\u30db\u30fc\u30e0\u306f\u767b\u9332\u3057\u306a\u3044\");\n    if(isBookmarked(url)){\n      state.bookmarks = state.bookmarks.filter(b => b.url !== url);\n      saveState();\n      renderSidebar();\n      toast(\"\u30d6\u30c3\u30af\u30de\u30fc\u30af\u524a\u9664\", url);\n    }else{\n      state.bookmarks.unshift({ title: tab.title || url, url, addedAt: nowISO() });\n      saveState();\n      renderSidebar();\n      toast(\"\u30d6\u30c3\u30af\u30de\u30fc\u30af\u8ffd\u52a0\", tab.title || url);\n    }\n    renderIndicators();\n  };\n\n  \/\/ =========================\n  \/\/ Viewport Loader\n  \/\/ =========================\n  const frame = $(\"#frame\");\n  const overlay = $(\"#overlay\");\n\n  let embedBlockedTimer = null;\n\n  const setOverlay = (show) => {\n    overlay.classList.toggle(\"show\", !!show);\n  };\n\n  const updateAddressBar = (tab) => {\n    $(\"#addrInput\").value = tab.url === \"about:home\" ? \"\" : tab.url;\n  };\n\n  const renderIndicators = () => {\n    const tab = getActiveTab();\n    const url = tab.url || \"\";\n    const originTag = $(\"#originTag\");\n    const secureTag = $(\"#secureTag\");\n    const embedTag = $(\"#embedTag\");\n\n    let origin = \"\u2014\";\n    try{\n      if(url.startsWith(\"about:\")) origin = \"about\";\n      else origin = (new URL(url)).hostname;\n    }catch(e){ origin = \"\u2014\"; }\n\n    const secure = url.startsWith(\"https:\/\/\") ? \"HTTPS\" : (url.startsWith(\"http:\/\/\") ? \"HTTP\" : \"\u2014\");\n    originTag.textContent = origin;\n    secureTag.textContent = secure;\n\n    const bm = isBookmarked(url) ? \"Bookmarked\" : \"Not bookmarked\";\n    embedTag.textContent = bm;\n  };\n\n  const loadTabToViewport = (tab) => {\n    setOverlay(false);\n    clearTimeout(embedBlockedTimer);\n    renderIndicators();\n    updateAddressBar(tab);\n\n    const url = tab.url;\n\n    if(url === \"about:home\"){\n      frame.removeAttribute(\"src\");\n      frame.srcdoc = homeHTML();\n      setStatus(\"Home\");\n      return;\n    }\n\n    frame.removeAttribute(\"srcdoc\");\n    frame.src = url;\n\n    setStatus(\"Loading\u2026\");\n\n    \/\/ \"\u57cb\u3081\u8fbc\u307f\u30d6\u30ed\u30c3\u30af\" \u306f\u78ba\u5b9f\u306b\u691c\u77e5\u3067\u304d\u306a\u3044\u304c\u3001\n    \/\/ \u4e00\u5b9a\u6642\u9593\u3067\u8868\u793a\u3055\u308c\u306a\u3051\u308c\u3070 overlay \u3092\u51fa\u3057\u3066\u9003\u3052\u9053\u3092\u7528\u610f\u3059\u308b\u3002\n    embedBlockedTimer = setTimeout(() => {\n      \/\/ about:blank \u3060\u3063\u305f\u308a\u3001\u4f55\u3082\u8868\u793a\u3055\u308c\u306a\u3044\u30b1\u30fc\u30b9\u3092\u60f3\u5b9a\n      \/\/ \u3053\u3053\u306f\u300c\u4fdd\u967a\u300d\u306a\u306e\u3067\u5f37\u5236\u8868\u793a\u3067\u306f\u306a\u304f\u3001\u72b6\u6cc1\u3092\u898b\u3066\u51fa\u3059\n      \/\/ \u2192 \u30bf\u30d6\u306eURL\u304c\u5916\u90e8\u306a\u3089\u57fa\u672c\u51fa\u3059\n      if(getActiveTab().url === url){\n        setOverlay(true);\n        setStatus(\"Embed blocked (maybe)\");\n      }\n    }, 1400);\n  };\n\n  frame.addEventListener(\"load\", () => {\n    clearTimeout(embedBlockedTimer);\n    const tab = getActiveTab();\n    \/\/ \u30bf\u30a4\u30c8\u30eb\u306e\u63a8\u5b9a\u306f\u3001\u30af\u30ed\u30b9\u30aa\u30ea\u30b8\u30f3\u3060\u3068\u53d6\u308c\u306a\u3044\u306e\u3067URL\u304b\u3089\u4f5c\u308b\n    if(tab.url.startsWith(\"about:\")){\n      setStatus(\"Ready\");\n      return;\n    }\n    setOverlay(false);\n    setStatus(\"Ready\");\n    addGlobalHistory(tab.url, tab.title);\n\n    \/\/ \u30bf\u30a4\u30c8\u30eb\u63a8\u5b9a\n    let title = tab.title;\n    try{\n      const u = new URL(tab.url);\n      title = u.hostname;\n      if(u.pathname &amp;&amp; u.pathname !== \"\/\") title += u.pathname.slice(0, 14) + (u.pathname.length > 14 ? \"\u2026\" : \"\");\n    }catch(e){}\n    setTabTitle(tab, title);\n    renderIndicators();\n  });\n\n  frame.addEventListener(\"error\", () => {\n    clearTimeout(embedBlockedTimer);\n    setOverlay(true);\n    setStatus(\"Load error\");\n  });\n\n  const navigate = (input) => {\n    const tab = getActiveTab();\n    const raw = (input ?? $(\"#addrInput\").value).trim();\n    if(!raw){\n      tab.url = \"about:home\";\n      pushHistory(tab, tab.url);\n      saveState();\n      loadTabToViewport(tab);\n      renderTabs();\n      return;\n    }\n\n    const url = normalizeToUrl(raw) || buildSearchUrl(raw);\n    tab.url = url;\n    pushHistory(tab, url);\n    saveState();\n    renderTabs();\n    loadTabToViewport(tab);\n    toast(\"\u79fb\u52d5\", url);\n  };\n\n  const back = () => {\n    const tab = getActiveTab();\n    if(tab.hIndex &lt;= 0) return toast(\"\u623b\u308c\u306a\u3044\");\n    tab.hIndex -= 1;\n    tab.url = tab.history&#91;tab.hIndex];\n    saveState();\n    renderTabs();\n    loadTabToViewport(tab);\n  };\n\n  const forward = () => {\n    const tab = getActiveTab();\n    if(tab.hIndex >= tab.history.length - 1) return toast(\"\u9032\u3081\u306a\u3044\");\n    tab.hIndex += 1;\n    tab.url = tab.history&#91;tab.hIndex];\n    saveState();\n    renderTabs();\n    loadTabToViewport(tab);\n  };\n\n  const reload = () => {\n    const tab = getActiveTab();\n    if(tab.url === \"about:home\"){\n      loadTabToViewport(tab);\n      return;\n    }\n    try{\n      frame.contentWindow.location.reload();\n    }catch(e){\n      \/\/ \u30af\u30ed\u30b9\u30aa\u30ea\u30b8\u30f3\u306f reload \u5236\u9650\u304c\u3042\u308b\u306e\u3067 src \u518d\u8a2d\u5b9a\n      frame.src = tab.url;\n    }\n    setStatus(\"Reloading\u2026\");\n  };\n\n  const openExternal = () => {\n    const tab = getActiveTab();\n    const url = tab.url === \"about:home\" ? buildSearchUrl($(\"#addrInput\").value.trim() || \"home\") : tab.url;\n    window.open(url, \"_blank\", \"noopener,noreferrer\");\n    toast(\"\u5916\u90e8\u3067\u958b\u3044\u305f\", url);\n  };\n\n  const tryPip = async () => {\n    try{\n      const doc = frame.contentDocument;\n      if(!doc) throw new Error(\"Cross-origin\");\n      const video = doc.querySelector(\"video\");\n      if(!video) return toast(\"\u52d5\u753b\u304c\u898b\u3064\u304b\u3089\u306a\u3044\", \"\u3053\u306e\u30da\u30fc\u30b8\u306b &lt;video> \u304c\u306a\u3044\");\n      if(document.pictureInPictureElement) await document.exitPictureInPicture();\n      await video.requestPictureInPicture();\n      toast(\"PiP\", \"Picture-in-Picture\");\n    }catch(e){\n      toast(\"PiP\u4e0d\u53ef\", \"\u591a\u304f\u306e\u5916\u90e8\u30b5\u30a4\u30c8\u306f\u5236\u9650\u304c\u3042\u308b\");\n    }\n  };\n\n  \/\/ =========================\n  \/\/ UI Render\n  \/\/ =========================\n  const renderTabs = () => {\n    const el = $(\"#tabs\");\n    const activeId = state.activeTabId || state.tabs&#91;0]?.id;\n    if(!state.activeTabId) state.activeTabId = activeId;\n\n    el.innerHTML = state.tabs.map(t => {\n      const active = t.id === activeId ? \"active\" : \"\";\n      const pill = t.url === \"about:home\" ? \"HOME\" : (t.url.startsWith(\"https:\/\/\") ? \"HTTPS\" : (t.url.startsWith(\"http:\/\/\") ? \"HTTP\" : \"\u2014\"));\n      return `\n        &lt;div class=\"tab ${active}\" data-tab=\"${t.id}\">\n          &lt;div class=\"title\">${escapeHTML(t.title || \"Untitled\")}&lt;\/div>\n          &lt;span class=\"pill\">${escapeHTML(pill)}&lt;\/span>\n          &lt;div class=\"x\" title=\"\u9589\u3058\u308b\" data-close=\"${t.id}\">\u00d7&lt;\/div>\n        &lt;\/div>\n      `;\n    }).join(\"\");\n\n    el.querySelectorAll(\".tab\").forEach(tabEl => {\n      tabEl.addEventListener(\"click\", (ev) => {\n        const closeId = ev.target?.getAttribute?.(\"data-close\");\n        if(closeId){\n          ev.stopPropagation();\n          closeTab(closeId);\n          return;\n        }\n        const id = tabEl.getAttribute(\"data-tab\");\n        setActive(id);\n      });\n    });\n  };\n\n  const renderSidebar = () => {\n    \/\/ Quick\n    const q = $(\"#quickList\");\n    q.innerHTML = state.quick.map(x => `\n      &lt;div class=\"item\" data-url=\"${escapeHTML(x.url)}\">\n        &lt;div class=\"icon\">\u26a1&lt;\/div>\n        &lt;div class=\"meta\">\n          &lt;div class=\"t\">${escapeHTML(x.title)}&lt;\/div>\n          &lt;div class=\"s\">${escapeHTML(x.url)}&lt;\/div>\n        &lt;\/div>\n        &lt;span class=\"tag\">OPEN&lt;\/span>\n      &lt;\/div>\n    `).join(\"\");\n\n    \/\/ Bookmarks\n    const b = $(\"#bmList\");\n    b.innerHTML = (state.bookmarks.length ? state.bookmarks : &#91;{title:\"(\u306a\u3057)\", url:\"\"}]).map(x => `\n      &lt;div class=\"item\" data-url=\"${escapeHTML(x.url || \"\")}\" ${x.url ? \"\" : \"style='opacity:.6; cursor:default'\"}>\n        &lt;div class=\"icon\">\u2606&lt;\/div>\n        &lt;div class=\"meta\">\n          &lt;div class=\"t\">${escapeHTML(x.title)}&lt;\/div>\n          &lt;div class=\"s\">${escapeHTML(x.url)}&lt;\/div>\n        &lt;\/div>\n        ${x.url ? `&lt;span class=\"tag\">OPEN&lt;\/span>` : `&lt;span class=\"tag\">\u2014&lt;\/span>`}\n      &lt;\/div>\n    `).join(\"\");\n\n    \/\/ History\n    const h = $(\"#histList\");\n    const max = state.settings.sidebarHistoryView || 20;\n    const hist = state.history.slice(0, max);\n    h.innerHTML = (hist.length ? hist : &#91;{title:\"(\u306a\u3057)\", url:\"\"}]).map(x => `\n      &lt;div class=\"item\" data-url=\"${escapeHTML(x.url || \"\")}\" ${x.url ? \"\" : \"style='opacity:.6; cursor:default'\"}>\n        &lt;div class=\"icon\">\u27f2&lt;\/div>\n        &lt;div class=\"meta\">\n          &lt;div class=\"t\">${escapeHTML(x.title || x.url || \"(\u306a\u3057)\")}&lt;\/div>\n          &lt;div class=\"s\">${escapeHTML(x.url || \"\")}&lt;\/div>\n        &lt;\/div>\n        ${x.url ? `&lt;span class=\"tag\">OPEN&lt;\/span>` : `&lt;span class=\"tag\">\u2014&lt;\/span>`}\n      &lt;\/div>\n    `).join(\"\");\n\n    \/\/ Handlers\n    const bindOpen = (root) => {\n      root.querySelectorAll(\".item\").forEach(it => {\n        it.addEventListener(\"click\", () => {\n          const url = it.getAttribute(\"data-url\");\n          if(!url) return;\n          navigate(url);\n        });\n      });\n    };\n    bindOpen(q); bindOpen(b); bindOpen(h);\n  };\n\n  const renderTheme = () => {\n    document.body.setAttribute(\"data-theme\", state.theme || \"dark\");\n    $(\"#btnToggleTheme\").innerHTML = state.theme === \"dark\"\n      ? `&lt;span class=\"icon\">\u263e&lt;\/span>\u30c6\u30fc\u30de`\n      : `&lt;span class=\"icon\">\u2600&lt;\/span>\u30c6\u30fc\u30de`;\n  };\n\n  const renderAll = () => {\n    renderTheme();\n    renderTabs();\n    renderSidebar();\n    renderIndicators();\n  };\n\n  \/\/ =========================\n  \/\/ Home page (srcdoc)\n  \/\/ =========================\n  const homeHTML = () => {\n    const quick = state.quick.slice(0, 6).map(x => `\n      &lt;a class=\"card\" href=\"${x.url}\" target=\"_blank\" rel=\"noopener noreferrer\">\n        &lt;div class=\"t\">${escapeHTML(x.title)}&lt;\/div>\n        &lt;div class=\"s\">${escapeHTML(x.url)}&lt;\/div>\n      &lt;\/a>\n    `).join(\"\");\n\n    const bm = state.bookmarks.slice(0, 6).map(x => `\n      &lt;a class=\"card\" href=\"${x.url}\" target=\"_blank\" rel=\"noopener noreferrer\">\n        &lt;div class=\"t\">\u2606 ${escapeHTML(x.title)}&lt;\/div>\n        &lt;div class=\"s\">${escapeHTML(x.url)}&lt;\/div>\n      &lt;\/a>\n    `).join(\"\");\n\n    return `&lt;!doctype html>\n&lt;html lang=\"ja\">\n&lt;head>\n&lt;meta charset=\"utf-8\"\/>\n&lt;meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"\/>\n&lt;title>Home&lt;\/title>\n&lt;style>\n  :root{ color-scheme: dark; }\n  body{\n    margin:0;\n    font-family: ui-sans-serif, system-ui, -apple-system, \"Segoe UI\", Roboto, \"Noto Sans JP\", Arial;\n    background: radial-gradient(1000px 600px at 20% 20%, rgba(124,240,255,.18), transparent 60%),\n                radial-gradient(1000px 600px at 80% 20%, rgba(124,160,255,.16), transparent 60%),\n                #0b0f14;\n    color:#eaf0ff;\n  }\n  .wrap{ padding: 18px; }\n  h1{ font-size:18px; margin:0 0 8px; }\n  p{ margin:0 0 14px; opacity:.75; font-size:13px; }\n  .grid{\n    display:grid;\n    grid-template-columns: repeat(2, minmax(0, 1fr));\n    gap:10px;\n  }\n  .card{\n    display:block;\n    padding:12px 12px;\n    border-radius: 16px;\n    border:1px solid rgba(255,255,255,.10);\n    background: rgba(255,255,255,.06);\n    text-decoration:none;\n    color:inherit;\n  }\n  .card:hover{ border-color: rgba(124,240,255,.35); background: rgba(255,255,255,.09); }\n  .t{ font-size:14px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }\n  .s{ font-size:12px; opacity:.70; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; margin-top:4px; }\n  .row{ display:flex; gap:8px; flex-wrap:wrap; margin-top:12px; }\n  .pill{\n    border:1px solid rgba(255,255,255,.10);\n    padding:6px 10px;\n    border-radius: 999px;\n    background: rgba(255,255,255,.06);\n    font-size:12px;\n    opacity:.85;\n  }\n&lt;\/style>\n&lt;\/head>\n&lt;body>\n  &lt;div class=\"wrap\">\n    &lt;h1>Voogle Home&lt;\/h1>\n    &lt;p>\u30a2\u30c9\u30ec\u30b9\u30d0\u30fc\u306bURL\u304b\u691c\u7d22\u30ef\u30fc\u30c9\u3092\u5165\u308c\u3066 Enter\u3002\u57cb\u3081\u8fbc\u307f\u4e0d\u53ef\u30b5\u30a4\u30c8\u306f\u5916\u90e8\u30bf\u30d6\u3067\u958b\u304f\u3002&lt;\/p>\n\n    &lt;div class=\"row\">\n      &lt;span class=\"pill\">Ctrl+L: \u30a2\u30c9\u30ec\u30b9&lt;\/span>\n      &lt;span class=\"pill\">Ctrl+T: \u65b0\u898f\u30bf\u30d6&lt;\/span>\n      &lt;span class=\"pill\">Ctrl+W: \u30bf\u30d6\u9589\u3058\u308b&lt;\/span>\n      &lt;span class=\"pill\">Ctrl+R: \u66f4\u65b0&lt;\/span>\n    &lt;\/div>\n\n    &lt;h1 style=\"margin-top:18px\">Quick&lt;\/h1>\n    &lt;div class=\"grid\">${quick}&lt;\/div>\n\n    &lt;h1 style=\"margin-top:18px\">Bookmarks&lt;\/h1>\n    &lt;div class=\"grid\">${bm}&lt;\/div>\n  &lt;\/div>\n&lt;\/body>\n&lt;\/html>`;\n  };\n\n  \/\/ =========================\n  \/\/ Export \/ Import\n  \/\/ =========================\n  const exportData = () => {\n    const data = JSON.stringify(state, null, 2);\n    const blob = new Blob(&#91;data], {type:\"application\/json\"});\n    const url = URL.createObjectURL(blob);\n    const a = document.createElement(\"a\");\n    a.href = url;\n    a.download = \"voogle-data.json\";\n    document.body.appendChild(a);\n    a.click();\n    a.remove();\n    URL.revokeObjectURL(url);\n    toast(\"\u51fa\u529b\u3057\u305f\", \"voogle-data.json\");\n  };\n\n  const importData = async (file) => {\n    try{\n      const text = await file.text();\n      const obj = JSON.parse(text);\n      if(!obj || !obj.tabs || !Array.isArray(obj.tabs)) throw new Error(\"Invalid\");\n      state = obj;\n      saveState();\n      renderAll();\n      loadTabToViewport(getActiveTab());\n      toast(\"\u53d6\u8fbc\u5b8c\u4e86\", \"\u30c7\u30fc\u30bf\u3092\u5fa9\u5143\u3057\u305f\");\n    }catch(e){\n      toast(\"\u53d6\u8fbc\u5931\u6557\", \"JSON\u304c\u58ca\u308c\u3066\u308b\u304b\u5f62\u5f0f\u304c\u9055\u3046\");\n    }\n  };\n\n  const resetAll = () => {\n    if(!confirm(\"\u5168\u30c7\u30fc\u30bf\u3092\u521d\u671f\u5316\u3059\u308b\uff1f\")) return;\n    state = defaultState();\n    saveState();\n    renderAll();\n    loadTabToViewport(getActiveTab());\n    toast(\"\u521d\u671f\u5316\u3057\u305f\");\n  };\n\n  \/\/ =========================\n  \/\/ Bindings\n  \/\/ =========================\n  $(\"#btnGo\").addEventListener(\"click\", () => navigate());\n  $(\"#addrInput\").addEventListener(\"keydown\", (e) => {\n    if(e.key === \"Enter\") navigate();\n  });\n\n  $(\"#btnBack\").addEventListener(\"click\", back);\n  $(\"#btnForward\").addEventListener(\"click\", forward);\n  $(\"#btnReload\").addEventListener(\"click\", reload);\n  $(\"#btnBookmark\").addEventListener(\"click\", toggleBookmark);\n  $(\"#btnOpenExternal\").addEventListener(\"click\", openExternal);\n  $(\"#btnPip\").addEventListener(\"click\", tryPip);\n  $(\"#btnNewTab\").addEventListener(\"click\", () => newTab(\"about:home\", \"Home\"));\n\n  $(\"#btnToggleTheme\").addEventListener(\"click\", () => {\n    state.theme = (state.theme === \"dark\") ? \"light\" : \"dark\";\n    saveState();\n    renderTheme();\n    toast(\"\u30c6\u30fc\u30de\", state.theme);\n  });\n\n  $(\"#btnExport\").addEventListener(\"click\", exportData);\n  $(\"#importFile\").addEventListener(\"change\", (e) => {\n    const f = e.target.files?.&#91;0];\n    if(f) importData(f);\n    e.target.value = \"\";\n  });\n\n  $(\"#btnHome\").addEventListener(\"click\", () => navigate(\"about:home\"));\n  $(\"#btnClearHistory\").addEventListener(\"click\", () => {\n    state.history = &#91;];\n    saveState();\n    renderSidebar();\n    toast(\"\u5c65\u6b74\u30af\u30ea\u30a2\");\n  });\n  $(\"#btnResetAll\").addEventListener(\"click\", resetAll);\n\n  \/\/ Overlay buttons\n  $(\"#overlayOpenExternal\").addEventListener(\"click\", openExternal);\n  $(\"#overlayTrySearch\").addEventListener(\"click\", () => {\n    const tab = getActiveTab();\n    const q = tab.url &amp;&amp; tab.url !== \"about:home\" ? tab.url : ($(\"#addrInput\").value.trim() || \"home\");\n    newTab(buildSearchUrl(q), \"Search\");\n  });\n  $(\"#overlayClose\").addEventListener(\"click\", () => {\n    setOverlay(false);\n    toast(\"\u9589\u3058\u305f\");\n  });\n\n  \/\/ Keyboard shortcuts\n  window.addEventListener(\"keydown\", (e) => {\n    const ctrl = e.ctrlKey || e.metaKey;\n    if(ctrl &amp;&amp; e.key.toLowerCase() === \"l\"){ e.preventDefault(); $(\"#addrInput\").focus(); $(\"#addrInput\").select(); }\n    if(ctrl &amp;&amp; e.key.toLowerCase() === \"t\"){ e.preventDefault(); newTab(\"about:home\", \"Home\"); }\n    if(ctrl &amp;&amp; e.key.toLowerCase() === \"w\"){ e.preventDefault(); closeTab(getActiveTab().id); }\n    if(ctrl &amp;&amp; e.key.toLowerCase() === \"r\"){ e.preventDefault(); reload(); }\n    if(ctrl &amp;&amp; e.key === \"Enter\"){ e.preventDefault(); openExternal(); }\n  });\n\n  \/\/ Init\n  if(!state.activeTabId) state.activeTabId = state.tabs&#91;0].id;\n  renderAll();\n  loadTabToViewport(getActiveTab());\n})();\n&lt;\/script>\n&lt;\/body>\n&lt;\/html>\n<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_uf_show_specific_survey":0,"_uf_disable_surveys":false,"footnotes":""},"categories":[80],"tags":[],"class_list":["post-26254","post","type-post","status-publish","format-standard","hentry","category-html"],"aioseo_notices":[],"jetpack_featured_media_url":"","_links":{"self":[{"href":"http:\/\/www.tyosuke20xx.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/26254","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.tyosuke20xx.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.tyosuke20xx.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.tyosuke20xx.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.tyosuke20xx.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=26254"}],"version-history":[{"count":1,"href":"http:\/\/www.tyosuke20xx.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/26254\/revisions"}],"predecessor-version":[{"id":26255,"href":"http:\/\/www.tyosuke20xx.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/26254\/revisions\/26255"}],"wp:attachment":[{"href":"http:\/\/www.tyosuke20xx.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=26254"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.tyosuke20xx.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=26254"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.tyosuke20xx.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=26254"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}