Найден корректный robots.txt
Файл управления сканированием сайта роботами
?
Robots.txt указывает поисковым роботам, какие страницы сканировать, а какие — нет. Ошибки в файле могут случайно закрыть важные разделы от индексации.
Robots.txt настроен корректно. Размер файла: 20336 байт. Загружен за: 0сек.
Проверяемая страница не запрещена в robots.txt.
Показать содержимое robots.txt
# As a condition of accessing this website, you agree to abide by the following
# content signals:
# (a) If a Content-Signal = yes, you may collect content for the corresponding
# use.
# (b) If a Content-Signal = no, you may not collect content for the
# corresponding use.
# (c) If the website operator does not include a Content-Signal for a
# corresponding use, the website operator neither grants nor restricts
# permission via Content-Signal with respect to the corresponding use.
# The content signals and their meanings are:
# search: building a search index and providing search results (e.g., returning
# hyperlinks and short excerpts from your website's contents). Search does not
# include providing AI-generated search summaries.
# ai-input: inputting content into one or more AI models (e.g., retrieval
# augmented generation, grounding, or other real-time taking of content for
# generative AI search answers).
# ai-train: training or fine-tuning AI models.
# use: how AI systems may consume the content (immediate, reference, or full).
# ANY RESTRICTIONS EXPRESSED VIA CONTENT SIGNALS ARE EXPRESS RESERVATIONS OF
# RIGHTS UNDER ARTICLE 4 OF THE EUROPEAN UNION DIRECTIVE 2019/790 ON COPYRIGHT
# AND RELATED RIGHTS IN THE DIGITAL SINGLE MARKET.
# BEGIN Cloudflare Managed content
User-agent: *
Content-Signal: search=yes,ai-train=no,use=reference
Allow: /
User-agent: Amazonbot
Disallow: /
User-agent: Applebot-Extended
Disallow: /
User-agent: Bytespider
Disallow: /
User-agent: CCBot
Disallow: /
User-agent: ClaudeBot
Disallow: /
User-agent: CloudflareBrowserRenderingCrawler
Disallow: /
User-agent: Google-Extended
Disallow: /
User-agent: GPTBot
Disallow: /
User-agent: meta-externalagent
Disallow: /
# END Cloudflare Managed Content
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Game Rules | Brain Games</title>
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Google+Sans:wght@400;500;600;700&family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--bg: #f8f9fa;
--surface: #ffffff;
--surface-hover: #f1f3f4;
--border: #e0e0e0;
--border-light: #eeeeee;
--text: #202124;
--text-secondary: #5f6368;
--text-dim: #80868b;
--accent: #1a73e8;
--accent-hover: #1765cc;
--shadow-sm: 0 1px 2px rgba(60,64,67,0.1), 0 1px 3px rgba(60,64,67,0.08);
--shadow-md: 0 1px 3px rgba(60,64,67,0.15), 0 4px 8px rgba(60,64,67,0.1);
--shadow-lg: 0 1px 4px rgba(60,64,67,0.2), 0 6px 12px rgba(60,64,67,0.12);
--radius: 8px;
--radius-lg: 24px;
}
body {
font-family: 'Inter', 'Google Sans', -apple-system, BlinkMacSystemFont, sans-serif;
background: var(--bg);
color: var(--text);
min-height: 100vh;
line-height: 1.5;
-webkit-font-smoothing: antialiased;
}
/* ── Header ── */
.header {
padding: 0.5rem 1rem;
display: flex;
align-items: center;
justify-content: space-between;
gap: 1rem;
max-width: 720px;
margin: 0 auto;
}
.header-bar {
background: var(--surface);
box-shadow: var(--shadow-sm);
position: sticky;
top: 0;
z-index: 10;
}
.header-logo {
height: clamp(32px, 5vw, 40px);
width: auto;
display: block;
}
.header-shops {
display: flex;
align-items: center;
gap: 6px;
}
.header-shops-label {
color: var(--text-dim);
font-size: 0.75rem;
margin-right: 4px;
}
.shop-link {
display: inline-flex;
align-items: center;
gap: 4px;
padding: 6px 10px;
border-radius: 16px;
font-size: 0.75rem;
font-weight: 600;
text-decoration: none;
color: var(--text-secondary);
background: var(--bg);
transition: all 0.15s;
}
.flag {
display: inline-block;
width: 18px;
height: 13px;
border-radius: 2px;
background-size: cover;
background-position: center;
flex-shrink: 0;
box-shadow: 0 0 0 0.5px rgba(0,0,0,0.1);
}
.flag-ee { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 6 4'%3E%3Crect width='6' height='1.33' fill='%230072CE'/%3E%3Crect y='1.33' width='6' height='1.33' fill='%23000'/%3E%3Crect y='2.67' width='6' height='1.33' fill='%23fff'/%3E%3C/svg%3E"); }
.flag-lv { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 6 4'%3E%3Crect width='6' height='4' fill='%239E3039'/%3E%3Crect y='1.5' width='6' height='1' fill='%23fff'/%3E%3C/svg%3E"); }
.flag-lt { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 6 4'%3E%3Crect width='6' height='1.33' fill='%23FDB913'/%3E%3Crect y='1.33' width='6' height='1.33' fill='%23006A44'/%3E%3Crect y='2.67' width='6' height='1.33' fill='%23C1272D'/%3E%3C/svg%3E"); }
.flag-ru { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 6 4'%3E%3Crect width='6' height='1.33' fill='%23fff'/%3E%3Crect y='1.33' width='6' height='1.33' fill='%230039A6'/%3E%3Crect y='2.67' width='6' height='1.33' fill='%23D52B1E'/%3E%3C/svg%3E"); }
.flag-en { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 60 40'%3E%3Crect width='60' height='40' fill='%23012169'/%3E%3Cpath d='M0 0L60 40M60 0L0 40' stroke='%23fff' stroke-width='6'/%3E%3Cpath d='M0 0L60 40M60 0L0 40' stroke='%23C8102E' stroke-width='4' clip-path='polygon(30 20,60 0,60 40,30 20,0 40,0 0)'/%3E%3Cpath d='M30 0V40M0 20H60' stroke='%23fff' stroke-width='8'/%3E%3Cpath d='M30 0V40M0 20H60' stroke='%23C8102E' stroke-width='5'/%3E%3C/svg%3E"); }
.shop-link:hover {
background: var(--surface-hover);
color: var(--text);
}
@media (max-width: 600px) {
.header { padding: 0.6rem 1rem; }
.header-shops-label { display: none; }
.shop-link { padding: 5px 8px; font-size: 0.7rem; }
}
/* ── Controls ── */
.controls {
max-width: 720px;
margin: 0 auto;
padding: 0.4rem 1rem 0.5rem;
}
.search-wrap {
position: relative;
margin-bottom: 0.4rem;
}
.search-wrap svg {
position: absolute;
left: 14px;
top: 50%;
transform: translateY(-50%);
width: 18px;
height: 18px;
color: var(--text-dim);
pointer-events: none;
}
.search-input {
width: 100%;
padding: 10px 16px 10px 44px;
background: var(--surface);
border: none;
border-radius: var(--radius-lg);
color: var(--text);
font-size: 0.9rem;
font-family: inherit;
outline: none;
box-shadow: var(--shadow-md);
transition: box-shadow 0.2s;
}
.search-input:focus { box-shadow: var(--shadow-lg); }
.search-input::placeholder { color: var(--text-dim); }
.filter-row {
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
}
.stats {
color: var(--text-dim);
font-size: 0.8rem;
padding: 0;
white-space: nowrap;
}
.lang-filters {
display: flex;
align-items: center;
gap: 6px;
justify-content: center;
margin-bottom: 0.25rem;
}
.lang-filters-label {
font-size: 0.72rem;
color: var(--text-dim);
margin-right: 2px;
}
.lang-filter-btn {
padding: 4px 12px;
border-radius: 14px;
font-size: 0.72rem;
font-weight: 600;
font-family: inherit;
letter-spacing: 0.02em;
border: 1px solid var(--border);
background: var(--surface);
color: var(--text-secondary);
cursor: pointer;
transition: all 0.15s;
}
.lang-filter-btn:hover {
border-color: var(--accent);
color: var(--accent);
}
.lang-filter-btn.active {
background: var(--accent);
color: #fff;
border-color: var(--accent);
}
/* ── Group & letter separators ── */
.letter-separator {
font-size: 0.7rem;
font-weight: 600;
color: var(--text-dim);
padding: 1rem 16px 0.25rem;
letter-spacing: 0.05em;
text-transform: uppercase;
}
/* ── Games List ── */
.games {
max-width: 720px;
margin: 0.5rem auto 0;
padding: 0 1rem 3rem;
display: flex;
flex-direction: column;
}
.game-card {
display: flex;
align-items: center;
justify-content: space-between;
padding: 12px 16px;
background: transparent;
border-radius: var(--radius);
border: none;
transition: background 0.15s;
gap: 8px;
border-bottom: 1px solid var(--border-light);
}
.game-card:last-child { border-bottom: none; }
.game-card:hover {
background: var(--surface-hover);
}
.game-info {
flex: 1;
min-width: 0;
}
.game-title {
font-weight: 500;
font-size: 0.9rem;
color: var(--text);
overflow-wrap: anywhere;
word-break: break-word;
}
.game-meta {
font-size: 0.7rem;
color: var(--text-dim);
margin-top: 1px;
}
.game-langs {
display: flex;
gap: 4px;
flex-shrink: 0;
}
@media (max-width: 480px) {
.game-card {
flex-direction: column;
align-items: flex-start;
gap: 6px;
}
.game-title {
white-space: normal;
overflow: visible;
}
}
.lang-badge {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 4px;
padding: 0 10px;
height: 32px;
border-radius: 16px;
font-size: 0.8rem;
font-weight: 600;
text-decoration: none;
letter-spacing: 0.02em;
transition: all 0.15s;
border: 1px solid var(--border);
color: var(--text-secondary);
background: var(--surface);
box-shadow: var(--shadow-sm);
cursor: pointer;
}
.lang-badge:hover {
background: var(--accent);
color: #fff;
border-color: var(--accent);
box-shadow: var(--shadow-md);
transform: translateY(-1px);
}
.empty {
text-align: center;
padding: 3rem 1rem;
color: var(--text-dim);
}
.empty-icon { font-size: 2.5rem; margin-bottom: 0.5rem; }
.loader {
text-align: center;
padding: 3rem;
color: var(--text-dim);
}
@keyframes pulse { 0%, 100% { opacity: 0.4; } 50% { opacity: 1; } }
.loader span { animation: pulse 1.2s infinite; }
.footer {
text-align: center;
padding: 1.5rem 1rem;
color: var(--text-dim);
font-size: 0.75rem;
}
/* ── Embed mode ── */
body.embed .header { padding: 0.5rem 1rem; box-shadow: none; border-bottom: 1px solid var(--border); }
body.embed .header-logo { height: clamp(24px, 4vw, 32px); }
@media (max-width: 600px) {
.game-card { padding: 10px 12px; }
.game-title { font-size: 0.85rem; }
.lang-badge { padding: 0 8px; height: 28px; font-size: 0.7rem; }
.controls { padding: 0.4rem 0.75rem 0.4rem; }
.search-wrap { margin-bottom: 0.3rem; }
.search-input { font-size: 16px; }
.lang-filters { margin-bottom: 0; }
.lang-filters-label { display: none; }
.lang-filter-btn { padding: 3px 10px; font-size: 0.68rem; }
.stats { font-size: 0.72rem; }
.games { padding: 0 0.75rem 3rem; }
}
</style>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-47KR6Q9411"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-47KR6Q9411');
</script>
</head>
<body>
<div class="header-bar">
<div class="header">
<a href="/"><img src="/logo.png" alt="Brain Games" class="header-logo"></a>
<div class="header-shops">
<span class="header-shops-label">Shop:</span>
<a href="https://brain-games.ee?utm_source=rules&utm_medium=web&utm_campaign=rules_page" target="_blank" rel="noopener" class="shop-link" title="brain-games.ee"><span class="flag flag-ee"></span></a>
<a href="https://brain-games.lv?utm_source=rules&utm_medium=web&utm_campaign=rules_page" target="_blank" rel="noopener" class="shop-link" title="brain-games.lv"><span class="flag flag-lv"></span></a>
<a href="https://brain-games.lt?utm_source=rules&utm_medium=web&utm_campaign=rules_page" target="_blank" rel="noopener" class="shop-link" title="brain-games.lt"><span class="flag flag-lt"></span></a>
</div>
</div>
<div class="controls">
<div class="search-wrap">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M21 21l-5.197-5.197m0 0A7.5 7.5 0 105.196 5.196a7.5 7.5 0 0010.607 10.607z"/>
</svg>
<input type="text" class="search-input" id="search" placeholder="Search for a game..." autocomplete="off">
</div>
<div class="filter-row">
<div class="lang-filters" id="langFilters">
<span class="lang-filters-label">Rules language:</span>
<button class="lang-filter-btn" data-lang="estonian">EE</button>
<button class="lang-filter-btn" data-lang="latvian">LV</button>
<button class="lang-filter-btn" data-lang="lithuanian">LT</button>
<button class="lang-filter-btn" data-lang="russian">RU</button>
<button class="lang-filter-btn" data-lang="english">EN</button>
</div>
<div class="stats" id="stats"></div>
</div>
</div>
</div>
<div class="games" id="games">
<div class="loader"><span>Loading rules...</span></div>
</div>
<footer class="footer">© 2026 Brain Games</footer>
<script>
const LANGS = ['estonian','latvian','lithuanian','russian','english'];
const LANG_LABEL = { estonian:'EE', latvian:'LV', lithuanian:'LT', russian:'RU', english:'EN' };
const UI_STRINGS = {
estonian: {
title: 'Mängureeglid | Brain Games',
search: 'Otsi mängu...',
langLabel: 'Reeglite keel:',
found: function(n) { return n + ' mäng' + (n !== 1 ? 'u' : '') + ' leitud'; },
noResults: 'Otsingule vastavaid mänge ei leitud',
loading: 'Reeglite laadimine...',
loadError: 'Reeglite laadimine ebaõnnestus',
},
latvian: {
title: 'Spēļu noteikumi | Brain Games',
search: 'Meklēt spēli...',
langLabel: 'Noteikumu valoda:',
found: function(n) { return 'Atrast' + (n !== 1 ? 'as' : 'a') + ' ' + n + ' spēle' + (n !== 1 ? 's' : ''); },
noResults: 'Nav atrasta neviena spēle',
loading: 'Noteikumi tiek ielādēti...',
loadError: 'Neizdevās ielādēt noteikumus',
},
lithuanian: {
title: 'Žaidimų taisyklės | Brain Games',
search: 'Ieškoti žaidimo...',
langLabel: 'Taisyklių kalba:',
found: function(n) { return 'Rast' + (n !== 1 ? 'a' : 'as') + ' ' + n + ' žaidim' + (n === 1 ? 'as' : (n < 10 || n > 20) && n % 10 >= 2 && n % 10 <= 9 ? 'ai' : 'ų'); },
noResults: 'Nerasta žaidimų pagal paiešką',
loading: 'Taisyklės kraunamos...',
loadError: 'Nepavyko įkelti taisyklių',
},
russian: {
title: 'Правила игр | Brain Games',
search: 'Найти игру...',
langLabel: 'Язык правил:',
found: function(n) { return 'Найдено ' + n + ' игр' + (n === 1 ? 'а' : (n >= 2 && n <= 4) ? 'ы' : ''); },
noResults: 'Игры не найдены',
loading: 'Загрузка правил...',
loadError: 'Не удалось загрузить правила',
},
english: {
title: 'Game Rules | Brain Games',
search: 'Search for a game...',
langLabel: 'Rules language:',
found: function(n) { return n + ' game' + (n !== 1 ? 's' : '') + ' found'; },
noResults: 'No games found matching your search',
loading: 'Loading rules...',
loadError: 'Failed to load rules',
},
};
function t(key) {
const strings = currentLang && UI_STRINGS[currentLang] ? UI_STRINGS[currentLang] : UI_STRINGS.english;
return strings[key];
}
let allRules = [];
let currentQuery = '';
let currentLang = '';
// Auto-detect language from browser
function detectLang() {
const browserLangs = navigator.languages || [navigator.language || ''];
for (const bl of browserLangs) {
const code = bl.toLowerCase().split('-')[0];
if (code === 'et') return 'estonian';
if (code === 'lv') return 'latvian';
if (code === 'lt') return 'lithuanian';
}
return '';
}
// Read URL params
const params = new URLSearchParams(window.location.search);
if (params.get('q')) currentQuery = params.get('q');
if (params.has('lang')) { currentLang = params.get('lang'); }
else { currentLang = detectLang(); if (currentLang) updateURL(); }
if (params.has('embed')) document.body.classList.add('embed');
// Init
document.getElementById('search').value = currentQuery;
updateFilterButtons();
updateUIStrings();
// Lang filter clicks
document.getElementById('langFilters').addEventListener('click', e => {
const btn = e.target.closest('.lang-filter-btn');
if (!btn) return;
const lang = btn.dataset.lang;
currentLang = currentLang === lang ? '' : lang;
updateFilterButtons();
updateUIStrings();
updateURL();
render();
});
function updateFilterButtons() {
document.querySelectorAll('.lang-filter-btn').forEach(btn => {
btn.classList.toggle('active', btn.dataset.lang === currentLang);
});
}
function updateUIStrings() {
document.title = t('title');
document.getElementById('search').placeholder = t('search');
const label = document.querySelector('.lang-filters-label');
if (label) label.textContent = t('langLabel');
}
// Fetch rules
fetch('/api/rules')
.then(r => r.json())
.then(data => { allRules = data; render(); })
.catch(() => {
document.getElementById('games').innerHTML = '<div class="empty"><div class="empty-icon">⚠️</div>' + escapeHTML(t('loadError')) + '</div>';
});
// Search
document.getElementById('search').addEventListener('input', e => {
currentQuery = e.target.value;
updateURL();
render();
});
function updateURL() {
const p = new URLSearchParams();
if (currentQuery) p.set('q', currentQuery);
if (currentLang) p.set('lang', currentLang);
const qs = p.toString();
history.replaceState(null, '', qs ? '?' + qs : window.location.pathname);
}
function render() {
const q = currentQuery.toLowerCase().trim();
const container = document.getElementById('games');
let filtered = allRules;
if (q) {
filtered = filtered.filter(game => {
if (game.title.toLowerCase().includes(q)) return true;
if (Array.isArray(game.aliases)) {
return game.aliases.some(a => String(a).toLowerCase().includes(q));
}
return false;
});
}
if (currentLang) {
filtered = filtered.filter(game => game[currentLang]);
}
document.getElementById('stats').textContent = t('found')(filtered.length);
if (!filtered.length) {
container.innerHTML = '<div class="empty"><div class="empty-icon">🔍</div>' + escapeHTML(t('noResults')) + '</div>';
return;
}
let html = '';
let currentLetter = '';
filtered.forEach(game => {
const firstChar = game.title.charAt(0).toUpperCase();
const letter = /[A-Z]/.test(firstChar) ? firstChar : '#';
if (letter !== currentLetter) {
currentLetter = letter;
html += '<div class="letter-separator">' + letter + '</div>';
}
const langList = currentLang ? [currentLang] : LANGS.filter(l => game[l]);
const langs = langList
.filter(l => game[l])
.map(l => '<a href="' + escapeAttr(game[l]) + '" target="_blank" rel="noopener" class="lang-badge" title="' + l.charAt(0).toUpperCase() + l.slice(1) + ' rules">' + LANG_LABEL[l] + '</a>')
.join('');
html += '<div class="game-card"><div class="game-info"><div class="game-title">' + escapeHTML(game.title) + '</div></div><div class="game-langs">' + langs + '</div></div>';
});
container.innerHTML = html;
}
function escapeHTML(str) {
const d = document.createElement('div');
d.textContent = str;
return d.innerHTML;
}
function escapeAttr(str) {
return str.replace(/&/g,'&').replace(/"/g,'"').replace(/</g,'<').replace(/>/g,'>');
}
function formatDate(iso) {
const d = new Date(iso);
const pad = n => String(n).padStart(2, '0');
return d.getFullYear() + '-' + pad(d.getMonth() + 1) + '-' + pad(d.getDate()) + ' ' + pad(d.getHours()) + ':' + pad(d.getMinutes());
}
</script>
<script defer src='https://static.cloudflareinsights.com/beacon.min.js' data-cf-beacon='{"token": "CLOUDFLARE_WEB_ANALYTICS_TOKEN"}'></script>
</body>
</html>