<!DOCTYPE html>
<html lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@700;900&family=Space+Grotesk:wght@400;500;600;700&family=IBM+Plex+Mono:wght@400;500;600&display=swap" rel="stylesheet">
<link rel="icon" href="./cassie.ico">
<title>Eureka Blizzard Weather</title>
<style>
:root{
--bg: #DDEFD3;
--panel: #F4FBF1;
--panel-alt: #DCEFD3;
--line: #B5D7A6;
--text: #1f2e1c;
--text-dim: #4a6544;
--text-faint: #7d977a;
--ice: #0284c7;
--ice-deep: #0369a1;
--ember: #c2410c;
--violet: #7e22ce;
--fog: #4d6a5a;
--alert: #dc2626;
--alert-deep: #b91c1c;
--paper: #F7FCF4;
--paper-shadow: #CFE5C4;
--ink: #232320;
--ink-soft: #5B5A52;
--stamp: #B8402E;
--stamp-soft: #E7CFC8;
--r-sm: 4px;
--r-md: 6px;
--r-lg: 8px;
--f-display: "Orbitron", sans-serif;
--f-body: "Space Grotesk", "Hiragino Kaku Gothic ProN", sans-serif;
--f-mono: "Yu Gothic UI", "IBM Plex Mono", "Courier New", monospace;
}
body {
font-family: var(--f-body);
background: radial-gradient(circle at 18% -10%, #F3FAEE 0%, var(--bg) 45%) fixed;
color: var(--text);
margin: 0;
padding: 6px 8px 16px; /* 余白を最小化 */
font-size: 13px;
line-height: 1.25; /* 行間を小さく */
-webkit-font-smoothing: antialiased;
}
.meteor-logo {
font-family: var(--f-display);
font-weight: 900;
font-size: 17px; /* スペース最適化: 20pxから17pxにコンパクト化 */
letter-spacing: 0.5px;
background: linear-gradient(180deg, #aee6ff 0%, var(--ice) 45%, var(--ice-deep) 100%);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
text-shadow: 0 1px 6px rgba(47, 143, 192, 0.35);
flex-shrink: 0;
white-space: nowrap;
}
button { padding: 0 6px; border: 1px solid var(--line); border-radius: 999px; font-size: 10px; cursor: pointer; background: var(--panel-alt); color: var(--text-dim); height: 18px; line-height: 16px; flex-shrink: 0; font-weight: 600; font-family: var(--f-body); transition: background .15s ease, color .15s ease, border-color .15s ease, transform .1s ease; }
button:hover { color: var(--text); border-color: var(--ice-deep); background: #C9E5BA; }
button:active { transform: scale(.96); }
button:disabled { opacity: 0.4; cursor: default; transform: none; }
button:focus-visible { outline: 2px solid var(--ice); outline-offset: 1px; }
.container { width: 100%; max-width: 1100px; margin: 10px auto 0; box-sizing: border-box; }
.controls { background: var(--panel); padding: 5px 6px; margin-bottom: 6px; border-radius: var(--r-lg); border: 1px solid var(--line); display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 4px; }
.checkbox-group { display: flex; flex-wrap: wrap; gap: 4px 6px; }
.checkbox-group .zone-toggle-title { display: flex; align-items: center; font-size: 12px; white-space: nowrap; color: var(--text-dim); font-weight: 600; }
.checkbox-group label { display: flex; align-items: center; gap: 2px; font-size: 12px; cursor: pointer; white-space: nowrap; color: var(--text-dim); font-weight: 600; }
.checkbox-group input[type="checkbox"] { appearance: none; -webkit-appearance: none; width: 13px; height: 13px; border-radius: 3px; border: 1px solid var(--line); background: var(--panel-alt); position: relative; cursor: pointer; margin: 0; }
.checkbox-group input[type="checkbox"]:checked { background: #2f8f3e; border-color: #1f6f2d; }
.checkbox-group input[type="checkbox"]:checked::before { content: ""; position: absolute; inset: 2px; background: #fff; border-radius: 1px; }
.info { font-size: 11px; color: var(--text-dim); text-align: right; font-family: var(--f-mono); }
/* 天気テーブルの並びと余白調整 */
.weather-tables-wrapper { display: flex; flex-wrap: nowrap; gap: 8px; width: 100%; }
.weather-table-container { flex: 1; min-width: 0; background: var(--panel); border: 1px solid var(--line); border-radius: var(--r-md); overflow: hidden; }
/* 天気セルのマウスオーバー表示(新鋭など) */
#weather-tip {
position: fixed; z-index: 900; display: none; pointer-events: none; white-space: nowrap;
background: var(--panel); border: 2px solid var(--text); border-radius: var(--r-md);
padding: 1px 10px; font-size: 15.4px; font-weight: bold; line-height: 1.3; /* 天気の文字(11px)のマウスオーバー時サイズ(140%)に合わせる */ color: var(--text);
box-shadow: 0 8px 20px -8px rgba(0,0,0,0.55);
}
/* ヒュダトス・アネモスはピューロス・パゴスの半分の幅 */
#container-hydatos, #container-anemos { flex: 0.5 1 0%; }
/* 4ゾーンを常に横並び。狭い画面では文字を小さくして収める */
@media screen and (max-width: 1000px) {
.weather-tables-wrapper { gap: 3px; flex-wrap: nowrap; }
.weather-tables-wrapper th { font-size: 8px; letter-spacing: 0; padding: 3px 0; }
.weather-tables-wrapper .zone-header { font-size: 9px; letter-spacing: 0; padding: 3px 1px; }
.weather-tables-wrapper td { padding: 4px 0; }
.weather-tables-wrapper .time-text { font-size: 7.5px; white-space: normal; line-height: 1.15; }
.weather-tables-wrapper .weather-text { font-size: 9px; white-space: normal; }
#container-hydatos th, #container-anemos th { word-break: normal; }
#weather-tip { font-size: 12.6px; } /* 狭い画面の天気の文字(9px)×140% */
}
table {
border-collapse: collapse;
width: 100%;
background: var(--panel);
font-size: 12px;
table-layout: fixed;
}
th, td {
border: 1px solid var(--line);
padding: 4px 2px; /* 天気セルの行間(上下パディング)を拡大 */
text-align: center;
word-break: break-all;
}
th {
background: var(--panel-alt);
font-weight: 600;
color: var(--text-dim);
font-family: var(--f-mono);
font-size: 11px;
letter-spacing: .04em;
}
.zone-header { background: linear-gradient(135deg, #B9E0A0, #8FCB72); color: var(--text); font-size: 12px; padding: 4px 4px; font-family: var(--f-display); letter-spacing: 1px; font-weight: 700; }
.cell-blizzard { background-color: #e0f2fe !important; }
.cell-gales-night { background-color: #a9dd8c !important; } /* アネモス暴風 ET16:00 / ET00:00 */
.cell-fog { background-color: #d1d5db !important; }
.cell-heatwaves { background-color: rgba(255, 154, 90, 0.14) !important; }
.cell-thunder { background-color: rgba(185, 138, 240, 0.14) !important; }
.current-cell { background-color: rgba(255, 107, 94, 0.18) !important; border: 1px solid var(--alert) !important; box-shadow: inset 0 0 0 1px var(--alert); font-weight: bold; }
.weather-blizzard { color: var(--ice); font-weight: bold; }
.weather-heatwaves { color: var(--ember); font-weight: bold; }
.weather-thunder { color: var(--violet); font-weight: bold; }
.weather-fog { color: var(--fog); font-weight: bold; }
.weather-text.weather-hydatos-thunder { /* ヒュダトス暴雨・雷雨:水色+黒縁取り */
color: #0ea5e9; font-weight: bold;
text-shadow: -1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000, 1px 1px 0 #000,
0 -1px 0 #000, 0 1px 0 #000, -1px 0 0 #000, 1px 0 0 #000;
transition: transform .1s ease;
}
.weather-tables-wrapper .weather-text { transition: transform .1s ease; }
.weather-tables-wrapper td:hover .weather-text { transform: scale(1.4); font-weight: bold; } /* 全ゾーン:セルのマウスオーバーで天候の文字を140%・太字 */
.weather-text.weather-hydatos-gloom { /* ヒュダトス妖霧:紫+黒縁取り */
color: #a855f7; font-weight: bold;
text-shadow: -1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000, 1px 1px 0 #000,
0 -1px 0 #000, 0 1px 0 #000, -1px 0 0 #000, 1px 0 0 #000;
}
.weather-text.weather-hydatos-snow { /* ヒュダトス雪:白文字+黒縁取り */
color: #fff; font-weight: bold;
text-shadow: -1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000, 1px 1px 0 #000,
0 -1px 0 #000, 0 1px 0 #000, -1px 0 0 #000, 1px 0 0 #000;
}
.time-text { display: block; font-size: 9.5px; color: #000000; margin-bottom: 2px; white-space: nowrap; font-family: var(--f-mono); line-height: 1.3; font-weight: 600; } /* 日時を黒色に変更し行間と余白を調整 */
.weather-text { display: block; font-size: 11px; line-height: 1.25; white-space: nowrap; color: var(--text-dim); }
.weather-tables-wrapper tbody td {
cursor: pointer;
touch-action: manipulation;
-webkit-tap-highlight-color: rgba(125, 211, 252, 0.15);
user-select: none;
transition: filter .1s ease;
}
.weather-tables-wrapper tbody td:hover { filter: brightness(0.95); }
.weather-tables-wrapper tbody td:active { filter: brightness(0.88); }
.popup-overlay {
position: fixed;
top: 0; left: 0; right: 0; bottom: 0;
background: rgba(6,9,14,0.72);
display: flex;
align-items: center;
justify-content: center;
z-index: 1000;
}
.popup-overlay.hidden { display: none; }
.popup-box {
background: var(--panel);
border: 1px solid var(--line);
border-radius: var(--r-lg);
padding: 12px 14px;
width: 90%;
max-width: 500px;
max-height: 80vh;
overflow-y: auto;
overflow-x: auto;
box-shadow: 0 24px 60px -20px rgba(0,0,0,0.7);
color: var(--text);
}
.popup-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 6px;
font-weight: bold;
font-size: 14px;
font-family: var(--f-display);
letter-spacing: .03em;
}
.popup-header button {
height: 24px;
min-width: 28px;
font-size: 14px;
line-height: 22px;
padding: 0 6px;
touch-action: manipulation;
border-radius: var(--r-sm);
}
.popup-table { width: 100%; border-collapse: collapse; font-size: 11px; }
.popup-table th, .popup-table td { border: 1px solid var(--line); padding: 4px 6px; text-align: center; white-space: nowrap; color: var(--text-dim); }
.popup-table th { background: var(--panel-alt); color: var(--text); font-family: var(--f-mono); }
.hidden { display: none !important; }
.info-box { display: inline-block; box-sizing: border-box; text-align: center; font-variant-numeric: tabular-nums; flex-shrink: 0; padding: 2px 6px; background: var(--panel); border: 1px solid #2f8f3e; border-radius: var(--r-md); color: var(--text); font-weight: 600; white-space: nowrap; }
.site-title { margin: 0 0 6px; }
</style>
</head>
<body>
<div class="container">
<div class="site-title"><span class="meteor-logo">Eureka Blizzard Weather</span></div>
<div class="controls">
<div class="checkbox-group">
<span class="zone-toggle-title">天気表示</span>
<label><input type="checkbox" id="chk-hydatos" onchange="toggleZoneColumns()"> ヒュダトス</label>
<label><input type="checkbox" id="chk-pyros" checked="" onchange="toggleZoneColumns()"> ピューロス</label>
<label><input type="checkbox" id="chk-pagos" checked="" onchange="toggleZoneColumns()"> パゴス</label>
<label><input type="checkbox" id="chk-anemos" onchange="toggleZoneColumns()"> アネモス</label>
</div>
<div class="info" style="display: flex; align-items: center; gap: 4px;">
<span class="info-box" style="width: 10.5em;">天気更新 <span id="countdown">--:--</span></span>
<span class="info-box" id="et-clock" style="width: 7em;">ET --:--</span>
</div>
</div>
<div class="weather-tables-wrapper">
<div class="weather-table-container hidden" id="container-hydatos">
<table>
<thead>
<tr><th colspan="3" class="zone-header">ヒュダトス帯</th></tr>
<tr><th>ET 00:00</th><th>ET 08:00</th><th>ET 16:00</th></tr>
</thead>
<tbody id="weather-tbody-hydatos"></tbody>
</table>
</div>
<div class="weather-table-container" id="container-pyros">
<table>
<thead>
<tr><th colspan="3" class="zone-header">ピューロス帯</th></tr>
<tr><th>ET 00:00</th><th>ET 08:00</th><th>ET 16:00</th></tr>
</thead>
<tbody id="weather-tbody-pyros"></tbody>
</table>
</div>
<div class="weather-table-container" id="container-pagos">
<table>
<thead>
<tr><th colspan="3" class="zone-header">パゴス帯</th></tr>
<tr><th>ET 00:00</th><th>ET 08:00</th><th>ET 16:00</th></tr>
</thead>
<tbody id="weather-tbody-pagos"></tbody>
</table>
</div>
<div class="weather-table-container hidden" id="container-anemos">
<table>
<thead>
<tr><th colspan="3" class="zone-header">アネモス帯</th></tr>
<tr><th>ET 00:00</th><th>ET 08:00</th><th>ET 16:00</th></tr>
</thead>
<tbody id="weather-tbody-anemos"></tbody>
</table>
</div>
</div>
</div>
<!-- 天気セルクリック用ポップアップ -->
<div id="weather-popup-overlay" class="popup-overlay hidden">
<div class="popup-box">
<div class="popup-header">
<span id="popup-title"></span>
<button id="popup-close">×</button>
</div>
<table class="popup-table">
<thead><tr><th>天候</th><th>日付</th><th>時間</th><th>ET</th><th>今から</th></tr></thead>
<tbody id="popup-tbody"></tbody>
</table>
</div>
</div>
<script>
const PAGOS_RATES = [
{ max: 9, name: "晴れ" },
{ max: 27, name: "霧", class: "weather-fog", cellClass: "cell-fog", tooltip: "キングアースロ" },
{ max: 45, name: "灼熱波" },
{ max: 63, name: "雪" },
{ max: 81, name: "雷" },
{ max: 99, name: "吹雪", class: "weather-blizzard", cellClass: "cell-blizzard", tooltip: "キャシー" }
];
const PYROS_RATES = [
{ max: 9, name: "晴れ" },
{ max: 27, name: "灼熱波" },
{ max: 45, name: "雷" },
{ max: 63, name: "吹雪", class: "weather-blizzard", cellClass: "cell-blizzard", tooltip: "スコル" },
{ max: 81, name: "霊風" },
{ max: 99, name: "雪" }
];
// ヒュダトス:晴れ12% / 暴雨22% / 妖霧22% / 雷雨22% / 雪22%
const HYDATOS_RATES = [
{ max: 11, name: "晴れ" },
{ max: 33, name: "暴雨", class: "weather-hydatos-thunder", tooltip: "リフレク狩り:新鋭" },
{ max: 55, name: "妖霧", class: "weather-hydatos-gloom", tooltip: "リフレク狩り:熟練" },
{ max: 77, name: "雷雨", class: "weather-hydatos-thunder", tooltip: "リフレク狩り:新鋭" },
{ max: 99, name: "雪", class: "weather-hydatos-snow", tooltip: "攻勢" }
];
// アネモス:晴れ30% / 暴風30% / 暴雨30% / 雪10%
const ANEMOS_RATES = [
{ max: 29, name: "晴れ" },
{ max: 59, name: "暴風", nightCellClass: "cell-gales-night", nightTooltip: "パズズ" },
{ max: 89, name: "暴雨" },
{ max: 99, name: "雪" }
];
// 表示順(左→右)。key は chk-◯◯ / container-◯◯ / weather-tbody-◯◯ のID用
const WEATHER_ZONES = [
{ key: "hydatos", rates: HYDATOS_RATES, showDate: false },
{ key: "pyros", rates: PYROS_RATES, showDate: true },
{ key: "pagos", rates: PAGOS_RATES, showDate: true },
{ key: "anemos", rates: ANEMOS_RATES, showDate: false }
];
function getEorzeaInterval(ms) {
const eoMs = ms * (1440 / 70);
return Math.floor(eoMs / (8 * 60 * 60 * 1000));
}
function getJstTimeFromInterval(interval) {
const eoMs = interval * 8 * 60 * 60 * 1000;
return Math.round(eoMs / (1440 / 70));
}
function calculateWeather(interval, rates) {
const baseMs = getJstTimeFromInterval(interval);
const totalDays = Math.floor(baseMs / 4200000);
const dayInterval = (interval % 3 + 3) % 3;
const hour = dayInterval === 0 ? 0 : (dayInterval === 1 ? 8 : 16);
const x = (totalDays * 100) + ((hour + 8 - (hour % 8)) % 24);
let r0 = ((x << 11) ^ x) | 0;
let r1 = ((r0 >>> 8) ^ r0) | 0;
let seed = (r1 % 100 + 100) % 100;
return rates.find(w => seed <= w.max) || { name: "不明", class: "", cellClass: "" };
}
let cachedCurrentInterval = null;
function buildWeatherCell(targetInterval, currentInterval, rates, showDate) {
const jstMs = getJstTimeFromInterval(targetInterval);
const weather = calculateWeather(targetInterval, rates);
const date = new Date(jstMs);
const mm = String(date.getMonth() + 1).padStart(2, '0');
const dd = String(date.getDate()).padStart(2, '0');
const hh = String(date.getHours()).padStart(2, '0');
const min = String(date.getMinutes()).padStart(2, '0');
const td = document.createElement("td");
if (weather.cellClass) td.className = weather.cellClass;
// ET 00:00 / ET 16:00 の列のみ背景色を付ける天候(アネモス暴風)
if (weather.nightCellClass && (((targetInterval % 3) + 3) % 3) !== 1) td.classList.add(weather.nightCellClass);
if (targetInterval === currentInterval) td.classList.add("current-cell");
if (weather.tooltip) td.dataset.tip = weather.tooltip; // マウスオーバー表示(専用ツールチップ)
// ET 00:00 / ET 16:00 の列のみ表示するツールチップ(アネモス暴風)
if (weather.nightTooltip && (((targetInterval % 3) + 3) % 3) !== 1) td.dataset.tip = weather.nightTooltip;
td.innerHTML = `<span class="time-text">${showDate ? `${mm}/${dd} ` : ""}${hh}:${min}</span><span class="weather-text ${weather.class || ''}">${weather.name}</span>`;
td.addEventListener("click", () => showWeatherPopup(weather.name, rates));
return td;
}
function updateWeatherTable() {
const now = Date.now();
const currentInterval = getEorzeaInterval(now);
const currentMod = (currentInterval % 3 + 3) % 3;
const baseInterval = currentInterval - currentMod;
if (currentInterval !== cachedCurrentInterval) {
cachedCurrentInterval = currentInterval;
WEATHER_ZONES.forEach(zone => {
const frag = document.createDocumentFragment();
for (let r = -3; r <= 13; r++) {
const tr = document.createElement("tr");
for (let c = 0; c < 3; c++) {
tr.appendChild(buildWeatherCell(baseInterval + (r * 3) + c, currentInterval, zone.rates, zone.showDate));
}
frag.appendChild(tr);
}
const tbody = document.getElementById(`weather-tbody-${zone.key}`);
tbody.innerHTML = "";
tbody.appendChild(frag);
});
}
const nextJstMs = getJstTimeFromInterval(currentInterval + 1);
const diffSec = Math.max(0, Math.floor((nextJstMs - now) / 1000));
const cm = String(Math.floor(diffSec / 60)).padStart(2, '0');
const cs = String(diffSec % 60).padStart(2, '0');
document.getElementById("countdown").textContent = `${cm}:${cs}`;
const etMs = now * (1440 / 70);
const etH = String(Math.floor(etMs / 3600000) % 24).padStart(2, '0');
const etM = String(Math.floor(etMs / 60000) % 60).padStart(2, '0');
document.getElementById("et-clock").textContent = `ET ${etH}:${etM}`;
}
function etLabelFromInterval(interval) {
const mod = ((interval % 3) + 3) % 3;
const hour = mod === 0 ? 0 : (mod === 1 ? 8 : 16);
return `ET ${String(hour).padStart(2, '0')}:00`;
}
function showWeatherPopup(weatherName, rates) {
const now = Date.now();
const currentInterval = getEorzeaInterval(now);
const results = [];
let interval = currentInterval;
let safety = 0;
while (results.length < 20 && safety < 8000) {
const weather = calculateWeather(interval, rates);
if (weather.name === weatherName) {
const jstMs = getJstTimeFromInterval(interval);
const date = new Date(jstMs);
const mm = String(date.getMonth() + 1).padStart(2, '0');
const dd = String(date.getDate()).padStart(2, '0');
const hh = String(date.getHours()).padStart(2, '0');
const min = String(date.getMinutes()).padStart(2, '0');
const hoursFromNow = (jstMs - now) / 3600000;
results.push({ date: `${mm}/${dd}`, time: `${hh}:${min}`, et: etLabelFromInterval(interval), hoursFromNow });
}
interval++;
safety++;
}
renderWeatherPopup(weatherName, results);
}
// 天気セルのマウスオーバーで「新鋭」などを大きく表示(マウスのある端末のみ)
(function () {
if (!window.matchMedia('(hover: hover) and (pointer: fine)').matches) return;
const tip = document.createElement("div");
tip.id = "weather-tip";
document.body.appendChild(tip);
const cellOf = (t) => (t && t.closest) ? t.closest("td[data-tip]") : null;
const hide = () => { tip.style.display = "none"; };
function show(td) {
tip.textContent = td.dataset.tip;
tip.style.display = "block";
const r = td.getBoundingClientRect();
const w = tip.offsetWidth, h = tip.offsetHeight;
const left = Math.max(4, Math.min(r.left + r.width / 2 - w / 2, window.innerWidth - w - 4));
let top = r.bottom + 4;
if (top + h > window.innerHeight - 4) top = Math.max(4, r.top - h - 4); // 下に入らない場合のみ上に表示
tip.style.left = left + "px";
tip.style.top = top + "px";
}
document.addEventListener("mouseover", (e) => {
const td = cellOf(e.target);
if (td) show(td); else hide();
});
document.addEventListener("mouseout", (e) => { if (!e.relatedTarget) hide(); });
window.addEventListener("scroll", hide, true);
})();
function renderWeatherPopup(weatherName, results) {
document.getElementById("popup-title").textContent = `${weatherName} の発生予定`;
const tbody = document.getElementById("popup-tbody");
tbody.innerHTML = "";
if (results.length === 0) {
tbody.innerHTML = '<tr><td colspan="5" style="color:#999;">見つかりませんでした</td></tr>';
} else {
results.forEach(r => {
const tr = document.createElement("tr");
let hoursText;
if (r.hoursFromNow < 0) {
hoursText = "経過";
} else {
const totalMin = Math.floor(r.hoursFromNow * 60);
const hh2 = String(Math.floor(totalMin / 60)).padStart(2, '0');
const mm2 = String(totalMin % 60).padStart(2, '0');
hoursText = `${hh2}:${mm2}後`;
}
tr.innerHTML = `<td>${weatherName}</td><td>${r.date}</td><td>${r.time}</td><td>${r.et}</td><td>${hoursText}</td>`;
tbody.appendChild(tr);
});
}
document.getElementById("weather-popup-overlay").classList.remove("hidden");
}
document.getElementById("popup-close").addEventListener("click", () => {
document.getElementById("weather-popup-overlay").classList.add("hidden");
});
document.getElementById("weather-popup-overlay").classList.add("hidden"); // 初期状態補正
document.getElementById("weather-popup-overlay").addEventListener("click", (e) => {
if (e.target.id === "weather-popup-overlay") document.getElementById("weather-popup-overlay").classList.add("hidden");
});
function toggleZoneColumns() {
WEATHER_ZONES.forEach(zone => {
const show = document.getElementById(`chk-${zone.key}`).checked;
document.getElementById(`container-${zone.key}`).classList.toggle("hidden", !show);
});
}
setInterval(updateWeatherTable, 1000);
updateWeatherTable();
toggleZoneColumns();
</script>
</body></html>
コメント
こんにちは、これはコメントです。
コメントの承認、編集、削除を始めるにはダッシュボードの「コメント」画面にアクセスしてください。
コメントのアバターは「Gravatar」から取得されます。