<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Crawlio Search</title>
<style>
:root {
color-scheme: light;
--text: #202124;
--muted: #5f6368;
--line: #dadce0;
--blue: #4285f4;
--red: #ea4335;
--yellow: #fbbc04;
--green: #34a853;
--shadow: 0 18px 40px rgba(60, 64, 67, 0.15);
}
* {
box-sizing: border-box;
}
body {
margin: 0;
min-height: 100vh;
color: var(--text);
font-family: Arial, "Hiragino Kaku Gothic ProN", "Yu Gothic", Meiryo, sans-serif;
background:
radial-gradient(circle at top left, rgba(66, 133, 244, 0.12), transparent 32rem),
linear-gradient(180deg, #fff 0%, #f7f9fc 68%, #eef3fa 100%);
}
a {
color: inherit;
text-decoration: none;
}
.topbar {
display: flex;
align-items: center;
justify-content: space-between;
min-height: 64px;
padding: 0 28px;
}
.brand {
display: inline-flex;
align-items: center;
gap: 7px;
color: #3c4043;
font-size: 15px;
font-weight: 700;
}
.brand-dot {
width: 8px;
height: 8px;
border-radius: 50%;
}
.nav {
display: flex;
gap: 22px;
color: #3c4043;
font-size: 14px;
}
.nav a:hover {
text-decoration: underline;
}
main {
width: min(1120px, calc(100% - 32px));
margin: 0 auto;
}
.search-shell {
position: relative;
display: grid;
place-items: center;
min-height: 430px;
padding: 38px 0 46px;
overflow: hidden;
}
.crawler-visual {
position: absolute;
inset: 12px 0 auto;
height: 320px;
pointer-events: none;
opacity: 0.92;
}
.orbit {
position: absolute;
left: 50%;
top: 50%;
border: 1px solid rgba(95, 99, 104, 0.18);
border-radius: 50%;
transform: translate(-50%, -50%);
}
.orbit-a {
width: min(640px, 86vw);
height: 210px;
}
.orbit-b {
width: min(440px, 68vw);
height: 145px;
transform: translate(-50%, -50%) rotate(-12deg);
}
.node {
position: absolute;
width: 12px;
height: 12px;
border-radius: 50%;
box-shadow: 0 0 0 8px rgba(66, 133, 244, 0.08);
}
.node-a {
left: calc(50% - 302px);
top: 120px;
background: var(--blue);
}
.node-b {
left: calc(50% + 250px);
top: 88px;
background: var(--green);
}
.node-c {
left: calc(50% + 72px);
top: 216px;
background: var(--red);
}
.scan-line {
position: absolute;
left: 50%;
top: 64px;
width: 3px;
height: 220px;
background: linear-gradient(180deg, transparent, rgba(66, 133, 244, 0.72), transparent);
animation: scan 3.4s ease-in-out infinite;
}
.wordmark {
position: relative;
z-index: 1;
margin: 52px 0 25px;
font-size: clamp(68px, 12vw, 112px);
font-weight: 700;
line-height: 0.95;
}
.blue { color: var(--blue); }
.red { color: var(--red); }
.yellow { color: var(--yellow); }
.green { color: var(--green); }
.search-form {
position: relative;
z-index: 1;
width: min(640px, 100%);
}
.search-box {
display: grid;
grid-template-columns: 24px 1fr 42px;
align-items: center;
min-height: 58px;
padding: 0 8px 0 21px;
background: #fff;
border: 1px solid var(--line);
border-radius: 32px;
box-shadow: 0 2px 8px rgba(60, 64, 67, 0.08);
transition: box-shadow 160ms ease, border-color 160ms ease;
}
.search-box:focus-within,
.search-box:hover {
border-color: transparent;
box-shadow: var(--shadow);
}
.search-box svg,
.icon-button svg {
width: 22px;
height: 22px;
fill: #5f6368;
}
input {
width: 100%;
border: 0;
outline: 0;
padding: 0 14px;
color: var(--text);
font-size: 17px;
background: transparent;
}
.icon-button {
display: grid;
place-items: center;
width: 42px;
height: 42px;
border: 0;
border-radius: 50%;
background: transparent;
cursor: pointer;
}
.icon-button:hover {
background: #f1f3f4;
}
.actions {
display: flex;
justify-content: center;
gap: 12px;
margin-top: 24px;
}
.actions button {
min-width: 112px;
min-height: 38px;
border: 1px solid #f8f9fa;
border-radius: 4px;
padding: 0 18px;
color: #3c4043;
background: #f8f9fa;
font-size: 14px;
cursor: pointer;
}
.actions button:hover {
border-color: #dadce0;
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.08);
}
.results-area {
display: none;
max-width: 760px;
margin: 0 auto 46px;
}
.results-area.visible {
display: block;
}
.result-meta {
margin-bottom: 18px;
color: var(--muted);
font-size: 14px;
}
.result {
padding: 18px 0;
border-top: 1px solid #edf0f2;
}
.result-url {
color: #3c4043;
font-size: 13px;
}
.result h3 {
margin: 4px 0 6px;
color: #1a0dab;
font-size: 21px;
font-weight: 400;
}
.result p {
margin: 0;
color: #4d5156;
font-size: 14px;
line-height: 1.55;
}
.crawler-panel {
margin: 12px 0 28px;
padding: 24px;
background: rgba(255, 255, 255, 0.82);
border: 1px solid rgba(218, 220, 224, 0.9);
border-radius: 8px;
box-shadow: 0 12px 32px rgba(60, 64, 67, 0.08);
backdrop-filter: blur(10px);
}
.panel-heading {
display: flex;
align-items: end;
justify-content: space-between;
gap: 18px;
margin-bottom: 18px;
}
.eyebrow {
margin: 0 0 4px;
color: var(--blue);
font-size: 12px;
font-weight: 700;
letter-spacing: 0.08em;
text-transform: uppercase;
}
h2 {
margin: 0;
font-size: 24px;
}
.pulse {
display: inline-flex;
align-items: center;
gap: 8px;
color: #137333;
font-size: 12px;
font-weight: 700;
}
.pulse::before {
content: "";
width: 8px;
height: 8px;
border-radius: 50%;
background: var(--green);
box-shadow: 0 0 0 8px rgba(52, 168, 83, 0.12);
}
.crawl-grid {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 12px;
}
.crawl-card {
min-height: 122px;
padding: 16px;
border: 1px solid #e6eaee;
border-radius: 8px;
background: #fff;
}
.crawl-card strong {
display: block;
margin-bottom: 8px;
font-size: 15px;
}
.crawl-card span {
display: block;
color: var(--muted);
font-size: 13px;
line-height: 1.45;
}
.crawl-progress {
height: 5px;
margin-top: 14px;
overflow: hidden;
border-radius: 999px;
background: #edf0f2;
}
.crawl-progress i {
display: block;
height: 100%;
width: var(--progress);
border-radius: inherit;
background: linear-gradient(90deg, var(--blue), var(--green));
}
.stats-band {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 1px;
overflow: hidden;
margin-bottom: 44px;
border: 1px solid #dfe4ea;
border-radius: 8px;
background: #dfe4ea;
}
.stats-band div {
padding: 22px;
background: #fff;
}
.stats-band strong,
.stats-band span {
display: block;
}
.stats-band strong {
margin-bottom: 5px;
font-size: 27px;
}
.stats-band span {
color: var(--muted);
font-size: 13px;
}
footer {
display: flex;
flex-wrap: wrap;
gap: 22px;
padding: 18px 28px;
color: #70757a;
background: #f2f2f2;
font-size: 14px;
}
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
@keyframes scan {
0%, 100% {
transform: translateX(-260px);
opacity: 0.35;
}
50% {
transform: translateX(260px);
opacity: 1;
}
}
@media (max-width: 760px) {
.topbar {
padding: 0 16px;
}
.nav {
gap: 12px;
font-size: 13px;
}
.search-shell {
min-height: 390px;
}
.crawler-visual {
height: 270px;
}
.node-a {
left: 6%;
}
.node-b {
left: 86%;
}
.node-c {
left: 58%;
}
.actions {
flex-wrap: wrap;
}
.crawl-grid,
.stats-band {
grid-template-columns: 1fr;
}
.panel-heading {
align-items: start;
flex-direction: column;
}
}
</style>
</head>
<body>
<header class="topbar">
<a class="brand" href="#" aria-label="Crawlio Search">
<span class="brand-dot blue"></span>
<span class="brand-dot red"></span>
<span class="brand-dot yellow"></span>
<span class="brand-dot green"></span>
<span>Crawlio</span>
</a>
<nav class="nav" aria-label="メイン">
<a href="#crawler">Crawler</a>
<a href="#index">Index</a>
<a href="#status">Status</a>
</nav>
</header>
<main>
<section class="search-shell" aria-labelledby="hero-title">
<div class="crawler-visual" aria-hidden="true">
<div class="orbit orbit-a"></div>
<div class="orbit orbit-b"></div>
<div class="node node-a"></div>
<div class="node node-b"></div>
<div class="node node-c"></div>
<div class="scan-line"></div>
</div>
<h1 id="hero-title" class="wordmark">
<span class="blue">C</span><span class="red">r</span><span class="yellow">a</span><span class="blue">w</span><span class="green">l</span><span class="red">i</span><span class="blue">o</span>
</h1>
<form class="search-form" id="searchForm">
<label class="sr-only" for="query">検索キーワード</label>
<div class="search-box">
<svg aria-hidden="true" viewBox="0 0 24 24">
<path d="M10.8 18a7.2 7.2 0 1 1 5.1-12.3 7.2 7.2 0 0 1-5.1 12.3Zm0-2a5.2 5.2 0 1 0 0-10.4 5.2 5.2 0 0 0 0 10.4Zm6.3.1 4 4-1.4 1.4-4-4 1.4-1.4Z" />
</svg>
<input id="query" name="query" autocomplete="off" placeholder="URL、キーワード、サイト名を検索" />
<button class="icon-button" type="button" id="voiceButton" aria-label="音声検索">
<svg aria-hidden="true" viewBox="0 0 24 24">
<path d="M12 14a3 3 0 0 0 3-3V6a3 3 0 1 0-6 0v5a3 3 0 0 0 3 3Zm5-3a5 5 0 0 1-10 0H5a7 7 0 0 0 6 6.9V21h2v-3.1a7 7 0 0 0 6-6.9h-2Z" />
</svg>
</button>
</div>
<div class="actions">
<button type="submit">検索</button>
<button type="button" id="crawlButton">クローラーを走らせる</button>
</div>
</form>
</section>
<section class="results-area" aria-live="polite">
<div class="result-meta" id="resultMeta">約 8,420,000 件中 0.38 秒</div>
<div class="results" id="results"></div>
</section>
<section class="crawler-panel" id="crawler" aria-labelledby="crawler-title">
<div class="panel-heading">
<div>
<p class="eyebrow">Live Crawl</p>
<h2 id="crawler-title">巡回中のページ</h2>
</div>
<span class="pulse">ONLINE</span>
</div>
<div class="crawl-grid" id="crawlGrid"></div>
</section>
<section class="stats-band" id="index" aria-label="インデックス統計">
<div>
<strong>12.8B</strong>
<span>Indexed pages</span>
</div>
<div>
<strong>94ms</strong>
<span>Median lookup</span>
</div>
<div>
<strong>37K/s</strong>
<span>Crawl rate</span>
</div>
<div>
<strong>99.98%</strong>
<span>Freshness</span>
</div>
</section>
</main>
<footer id="status">
<span>Japan</span>
<span>Privacy</span>
<span>Terms</span>
<span>Search Console</span>
</footer>
<script>
const results = [
{
title: "Crawlio Search Console - サイトのクロール状況",
url: "https://crawlio.example/search-console",
text: "サイトマップ、robots.txt、インデックス登録、検索パフォーマンスをまとめて確認できます。"
},
{
title: "高速インデックスの仕組み",
url: "https://crawlio.example/docs/indexing",
text: "分散クローラーがページを発見し、内容を解析して、新しい検索結果へ反映します。"
},
{
title: "ニュース、画像、動画を横断検索",
url: "https://crawlio.example/discover",
text: "キーワードに関連するページ、メディア、トレンドをひとつの検索画面で素早く探せます。"
},
{
title: "Web Crawler Health Report",
url: "https://status.crawlio.example/crawler",
text: "現在のクロール速度、エラー率、再訪問キュー、インデックス鮮度のライブ統計です。"
}
];
const crawlItems = [
["news.metro.jp/today", "HTML parsed / 32 links discovered", 78],
["shop.example.com/products", "Sitemap queued / canonical found", 64],
["docs.dev.local/api", "Robots allowed / snippets updated", 91],
["media.example.net/video", "Metadata extracted / thumbnail indexed", 56],
["blog.studio.jp/launch", "Fresh content detected / rank signals ready", 84],
["archive.city.jp/events", "Recrawl scheduled / duplicate checked", 43]
];
const form = document.querySelector("#searchForm");
const queryInput = document.querySelector("#query");
const resultsArea = document.querySelector(".results-area");
const resultMeta = document.querySelector("#resultMeta");
const resultList = document.querySelector("#results");
const crawlGrid = document.querySelector("#crawlGrid");
const crawlButton = document.querySelector("#crawlButton");
const voiceButton = document.querySelector("#voiceButton");
function renderResults(query = "クローラー") {
const filtered = results.map((item) => ({
...item,
title: query ? `${item.title} | ${query}` : item.title
}));
resultMeta.textContent = `約 ${(8420000 + query.length * 17321).toLocaleString("ja-JP")} 件中 ${(0.21 + Math.random() * 0.28).toFixed(2)} 秒`;
resultList.innerHTML = filtered
.map(
(item) => `
<article class="result">
<div class="result-url">${item.url}</div>
<h3>${item.title}</h3>
<p>${item.text}</p>
</article>
`
)
.join("");
resultsArea.classList.add("visible");
}
function renderCrawlGrid(offset = 0) {
crawlGrid.innerHTML = crawlItems
.map(([url, status, progress], index) => {
const shifted = Math.min(99, Math.max(24, progress + ((offset + index * 7) % 18) - 7));
return `
<article class="crawl-card">
<strong>${url}</strong>
<span>${status}</span>
<div class="crawl-progress" aria-label="クロール進捗 ${shifted}%">
<i style="--progress: ${shifted}%"></i>
</div>
</article>
`;
})
.join("");
}
form.addEventListener("submit", (event) => {
event.preventDefault();
renderResults(queryInput.value.trim() || "クローラー");
});
crawlButton.addEventListener("click", () => {
renderCrawlGrid(Math.floor(Math.random() * 20));
renderResults(queryInput.value.trim() || "live crawl");
document.querySelector("#crawler").scrollIntoView({ behavior: "smooth", block: "start" });
});
voiceButton.addEventListener("click", () => {
queryInput.value = "最新のインデックス状況";
queryInput.focus();
});
renderCrawlGrid();
</script>
</body>
</html>