<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:base="https://www.pandoraburo.ru/" xml:lang="ru">
  <id>https://www.pandoraburo.ru/plamya-glubin</id>
  <link href="https://www.pandoraburo.ru/plamya-glubin.xml" rel="self"/>
  <title>Пламя глубин</title>
  <subtitle type="html">
&lt;html lang="ru"&gt;
&lt;head&gt;
&lt;meta charset="UTF-8"&gt;
&lt;meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"&gt;
&lt;title&gt;ПЛАМЯ ГЛУБИН | Прототип&lt;/title&gt;
&lt;style&gt;
  /* === БАЗОВЫЕ НАСТРОЙКИ === */
  html, body {
    margin: 0; padding: 0; height: 100%; width: 100%;
    background: #000; overflow: hidden;
    font-family: "Courier New", Courier, monospace;
    cursor: crosshair;
    -webkit-tap-highlight-color: transparent;
    touch-action: none;
    user-select: none;
  }
  
  /* Контейнер игры */
  #depths-game-container {
    position: relative;
    width: 100%;
    height: 100%;
  }

  canvas#game {
    display: block;
    width: 100%;
    height: 100%;
  }

  /* Экран загрузки / меню */
  #overlay {
    position: absolute; inset: 0;
    display: flex; flex-direction: column;
    align-items: center; justify-content: center;
    background: radial-gradient(circle at center, #0a1a2a 0%, #000000 100%);
    color: #7ef0c8; text-align: center; z-index: 100;
    transition: opacity 0.8s ease;
  }
  #overlay h1 {
    font-size: clamp(24px, 5vw, 48px);
    letter-spacing: 6px; margin: 0 0 16px;
    text-shadow: 0 0 15px rgba(126, 240, 200, 0.4);
  }
  #overlay p {
    font-size: clamp(12px, 2vw, 16px);
    opacity: 0.7; max-width: 400px; line-height: 1.6;
    margin: 0 0 32px;
  }
  #start-btn {
    padding: 14px 36px;
    font-family: inherit; font-size: 16px; letter-spacing: 3px;
    background: transparent; color: #7ef0c8;
    border: 1px solid #7ef0c8; cursor: pointer;
    transition: all 0.3s ease;
  }
  #start-btn:hover {
    background: #7ef0c8; color: #000;
    box-shadow: 0 0 20px rgba(126, 240, 200, 0.6);
  }
  .hidden { opacity: 0; pointer-events: none; }

  /* === НАДЁЖНЫЙ ПОЛНОЭКРАННЫЙ РЕЖИМ (ТЕАТР) === */
  body.depths-theater-mode {
    overflow: hidden !important;
  }

  /* Контейнер игры вырывается из потока и ложится ПОВЕРХ всего сайта */
  #depths-game-container.depths-theater-mode {
    position: fixed !important;
    top: 0 !important;
    left: 0 !important;
    width: 100vw !important;
    height: 100vh !important;
    max-width: none !important;
    max-height: none !important;
    margin: 0 !important;
    padding: 0 !important;
    z-index: 2147483647 !important; /* Максимально возможный z-index */
    background: #000000 !important; /* Жёсткий чёрный фон, перекрывающий сайт */
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
  }

  /* Принудительное растягивание холста и оверлея внутри контейнера */
  #depths-game-container.depths-theater-mode #game,
  #depths-game-container.depths-theater-mode #overlay {
    width: 100% !important;
    height: 100% !important;
    max-width: none !important;
    max-height: none !important;
    display: block !important; /* Запрет на схлопывание в 0x0 */
  }

  /* Кнопка переключения режима */
  #depths-fs-btn {
    position: fixed;
    bottom: 20px;
    right: 20px;
    z-index: 2147483646; /* Чуть ниже игры, но выше сайта */
    padding: 12px 24px;
    background: rgba(5, 20, 30, 0.95);
    color: #7ef0c8;
    border: 1px solid #7ef0c8;
    border-radius: 4px;
    font-family: 'Courier New', monospace;
    font-size: 14px;
    letter-spacing: 2px;
    cursor: pointer;
    box-shadow: 0 0 15px rgba(126, 240, 200, 0.4);
    transition: all 0.3s ease;
  }
  #depths-fs-btn:hover {
    background: #7ef0c8;
    color: #000;
    box-shadow: 0 0 25px rgba(126, 240, 200, 0.7);
  }

  /* Вид кнопки, когда игра развёрнута */
  body.depths-theater-mode #depths-fs-btn {
    top: 20px !important;
    bottom: auto !important;
    right: 20px !important;
    background: rgba(0, 0, 0, 0.8) !important;
    border-color: #ff4466 !important;
    color: #ff4466 !important;
    box-shadow: 0 0 15px rgba(255, 68, 102, 0.5) !important;
  }
  body.depths-theater-mode #depths-fs-btn:hover {
    background: #ff4466 !important;
    color: #000 !important;
  }
&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;


&lt;div id="depths-game-container"&gt;
  &lt;canvas id="game"&gt;&lt;/canvas&gt;
  &lt;div id="overlay"&gt;
    &lt;h1&gt;ПЛАМЯ ГЛУБИН&lt;/h1&gt;
    &lt;p&gt;2145 год. Субмарина «Гефест».&lt;br /&gt;
       Ты — глаза лодки. Смотри в перископ.&lt;br /&gt;
       Стреляй. Но не смотри слишком долго.&lt;/p&gt;
    &lt;button id="start-btn"&gt;ПОГРУЗИТЬСЯ&lt;/button&gt;
    &lt;p style="font-size: 11px; opacity: 0.4; margin-top: 40px;"&gt;
      МЫШЬ: Наведение • ЛКМ: Огонь • ПКМ/Колесо: Зум • R: Перезарядка
    &lt;/p&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;button id="depths-fs-btn" type="button"&gt;⛶ РАЗВЕРНУТЬ&lt;/button&gt;


&lt;script&gt;
"use strict";

/* --- БЛОК 1: НАСТРОЙКА CANVAS И УТИЛИТЫ --- */
const canvas = document.getElementById('game');
const ctx = canvas.getContext('2d', { alpha: false });
let W = 0, H = 0, CX = 0, CY = 0, VIEW_R = 0, K = 1;

const G = {
  mode: 'menu', time: 0, paused: false,
  sanity: 1, score: 0, wave: 0, ammo: 0, maxAmmo: 0, reload: 0,
  camX: 0, camY: 0, zoom: 1, targetZoom: 1,
  shake: 0, flash: 0, distortion: 0,
  ships: [], torpedoes: [], particles: [], rings: [], ticker: [], debris: [],
  spawnQueue: [], waveTimer: 0, betweenWaves: false,
  discovered: false, civiliansLost: 0, civiliansSaved: 0
};

function resize() {
  const dpr = Math.min(window.devicePixelRatio || 1, 2);
  W = window.innerWidth; 
  H = window.innerHeight;
  canvas.width = Math.floor(W * dpr);
  canvas.height = Math.floor(H * dpr);
  canvas.style.width = W + 'px';
  canvas.style.height = H + 'px';
  ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
  CX = W / 2; 
  CY = H / 2;
  VIEW_R = Math.min(W, H) * 0.44;
  K = H / 1080;
}
window.addEventListener('resize', resize);
resize();

const rand = (a, b) =&gt; a + Math.random() * (b - a);
const randInt = (a, b) =&gt; Math.floor(rand(a, b + 1));
const clamp = (v, a, b) =&gt; v &lt; a ? a : v &gt; b ? b : v;
const lerp = (a, b, t) =&gt; a + (b - a) * t;
const pick = arr =&gt; arr[Math.floor(Math.random() * arr.length)];
const TAU = Math.PI * 2;

/* --- БЛОК 2: ПРОЦЕДУРНЫЙ ЗВУК --- */
const Sfx = {
  ctx: null,
  init() {
    if (this.ctx) return;
    try { this.ctx = new (window.AudioContext || window.webkitAudioContext)(); } 
    catch(e) { console.warn("Web Audio не поддерживается"); }
  },
  tone(freq, dur, type='sine', vol=0.18, slideTo=0) {
    if (!this.ctx) return;
    const t = this.ctx.currentTime;
    const o = this.ctx.createOscillator(), g = this.ctx.createGain();
    o.type = type;
    o.frequency.setValueAtTime(freq, t);
    if (slideTo) o.frequency.exponentialRampToValueAtTime(Math.max(20, slideTo), t + dur);
    g.gain.setValueAtTime(vol, t);
    g.gain.exponentialRampToValueAtTime(0.0001, t + dur);
    o.connect(g); g.connect(this.ctx.destination);
    o.start(t); o.stop(t + dur + 0.05);
  },
  noise(dur, vol=0.3, f0=900, f1=70) {
    if (!this.ctx) return;
    const t = this.ctx.currentTime;
    const n = Math.floor(this.ctx.sampleRate * dur);
    const buf = this.ctx.createBuffer(1, n, this.ctx.sampleRate);
    const d = buf.getChannelData(0);
    for (let i = 0; i &lt; n; i++) d[i] = (Math.random() * 2 - 1) * (1 - i / n);
    const src = this.ctx.createBufferSource(); src.buffer = buf;
    const flt = this.ctx.createBiquadFilter();
    flt.type = 'lowpass';
    flt.frequency.setValueAtTime(f0, t);
    flt.frequency.exponentialRampToValueAtTime(f1, t + dur);
    const g = this.ctx.createGain();
    g.gain.setValueAtTime(vol, t);
    g.gain.exponentialRampToValueAtTime(0.0001, t + dur);
    src.connect(flt); flt.connect(g); g.connect(this.ctx.destination);
    src.start(t);
  },
  launch() { this.tone(180, 0.35, 'sawtooth', 0.14, 60); this.noise(0.3, 0.10, 1400, 300); },
  boom()   { this.noise(0.9, 0.55, 700, 40); this.tone(60, 0.7, 'sine', 0.25, 25); },
  ping()   { this.tone(1180, 0.30, 'sine', 0.10, 900); },
  whisper(){ this.tone(rand(140,190), 1.6, 'sine', 0.045, rand(90,130)); },
  hit()    { this.noise(0.25, 0.35, 2200, 200); },
  reload() { this.tone(420, 0.12, 'square', 0.08); }
};

/* --- БЛОК 3: ДАННЫЕ И СОСТОЯНИЕ --- */
const SHIPS = {
  clipper: { cls: 'КЛИПЕР', name: 'ЛОРЕЛЕЯ', len: 400, depth: 110, bow: 0.03, hp: 2, spd: [55, 80], sanity: 0.070, score: 120, civ: false, wps: [{ x: 0.05, y: 55, r: 30 }] },
  yacht:   { cls: 'ЯХТА', name: 'МИРАЖ', len: 300, depth: 78, bow: 0.05, hp: 1, spd: [90, 125], sanity: 0.032, score: 80, civ: false, wps: [{ x: 0.0, y: 38, r: 24 }] },
  liner:   { cls: 'ЛАЙНЕР', name: 'КОЛОСС', len: 640, depth: 170, bow: 0.26, hp: 5, spd: [28, 42], sanity: 0.045, score: 200, civ: false, wps: [{ x: -0.14, y: 70, r: 38 }, { x: 0.20, y: 80, r: 38 }] },
  ark:     { cls: 'КОВЧЕГ', name: 'ТИШИНА', len: 700, depth: 200, bow: 0.34, hp: 4, spd: [24, 34], sanity: 0.018, score: 250, civ: true, wps: [{ x: 0.0, y: 90, r: 36, node: true }] },
  frigate: { cls: 'ФРЕГАТ', name: 'ЛЕВИАФАН', len: 840, depth: 230, bow: 0.18, hp: 12, spd: [24, 32], sanity: 0.100, score: 1200, civ: false, wps: [{ x: -0.22, y: 85, r: 42 }, { x: 0.02, y: 95, r: 46 }, { x: 0.26, y: 70, r: 38 }] }
};

const WAVES = [
  { ships: ['clipper', 'clipper', 'yacht'], ammo: 8, label: 'ПАТРУЛЬ' },
  { ships: ['yacht', 'clipper', 'liner'], ammo: 9, label: 'КОНВОЙ' },
  { ships: ['clipper', 'ark', 'yacht', 'clipper'], ammo: 11, label: 'ТУМАН' },
  { ships: ['liner', 'clipper', 'yacht', 'ark'], ammo: 12, label: 'НОЧЬ' },
  { ships: ['clipper', 'clipper', 'liner', 'yacht'], ammo: 12, label: 'ШТОРМ' },
  { ships: ['frigate'], ammo: 14, label: 'ЛЕВИАФАН' }
];

const PAN_MIN = 0, PAN_MAX = 1500, WORLD_TOP = -900;

function addTicker(text, life = 2.4, color = '#7ef0c8') {
  G.ticker.push({ text, life, maxLife: life, color });
  if (G.ticker.length &gt; 4) G.ticker.shift();
}

function nextWave() {
  G.wave++;
  if (G.wave &gt; WAVES.length) { endGame(true); return; }
  const w = WAVES[G.wave - 1];
  G.maxAmmo = w.ammo; G.ammo = w.ammo; G.reload = 0; G.betweenWaves = false; G.spawnQueue = [];
  let cursor = 0;
  const order = w.ships.slice();
  for (let i = 0; i &lt; order.length; i++) {
    cursor += rand(700, 1300);
    G.spawnQueue.push({ type: order[i], at: cursor });
  }
  G.waveTimer = 0;
  Sfx.ping();
  G.rings.push({ x: G.camX, y: G.camY, r: 0, max: 2600, life: 1, speed: 1500 });
  addTicker(`ВОЛНА ${G.wave} — ${w.label}`, 3.0);
  if (G.wave === 3) addTicker('ВНИМАНИЕ: в секторе гражданские ковчеги', 4.0);
}

function startGame() {
  G.mode = 'play'; G.wave = 0; G.score = 0; G.totalScore = 0; G.sanity = 1;
  G.ships.length = 0; G.torpedoes.length = 0; G.particles.length = 0; 
  G.rings.length = 0; G.ticker.length = 0; G.debris.length = 0;
  G.discovered = false; G.civiliansLost = 0; G.civiliansSaved = 0;
  G.camX = 700; G.zoom = 1; G.targetZoom = 1; G.shake = 0; G.flash = 0; G.distortion = 0; G.paused = false;
  nextWave();
}

function endGame(win) {
  G.mode = win ? 'win' : 'dead'; G.paused = false;
  if (win) {
    Sfx.tone(523, 0.6, 'sine', 0.15);
    setTimeout(() =&gt; Sfx.tone(784, 0.8, 'sine', 0.15), 180);
    setTimeout(() =&gt; Sfx.tone(1046, 1.2, 'sine', 0.13), 380);
  } else {
    Sfx.noise(1.6, 0.35, 500, 30);
    Sfx.tone(90, 1.8, 'sawtooth', 0.12, 40);
  }
}

document.getElementById('start-btn').addEventListener('click', () =&gt; {
  Sfx.init();
  setTimeout(() =&gt; Sfx.ping(), 500);
  const overlay = document.getElementById('overlay');
  overlay.classList.add('hidden');
  setTimeout(() =&gt; { overlay.style.display = 'none'; }, 800);
  startGame();
});

/* --- БЛОК 4: УПРАВЛЕНИЕ --- */
const mouse = { x: CX, y: CY, down: false, inside: false };
const keys = {};
let touchPanX = null, touchStartDist = 0, touchZoomStart = 1, touchMoved = false;

function fireTorpedo() {
  if (G.mode !== 'play' || G.ammo &lt;= 0 || G.reload &gt; 0) return;
  const spawn = { x: G.camX + rand(-60, 60), y: G.camY + (VIEW_R / (G.zoom * K)) + 120 };
  const target = screenToWorld(mouse.x, mouse.y);
  let dx = target.x - spawn.x, dy = target.y - spawn.y;
  const len = Math.hypot(dx, dy) || 1;
  const SPEED = 900;
  G.torpedoes.push({ x: spawn.x, y: spawn.y, vx: (dx / len) * SPEED, vy: (dy / len) * SPEED, life: 4.0, trail: 0 });
  G.ammo--; G.reload = 0.85; Sfx.launch();
  emitBubbles(spawn.x, spawn.y, 22, 1.4);
  if (G.ammo === 0 &amp;&amp; G.ships.length &gt; 0) addTicker('БОЕЗАПАС ПУСТ — ЖДИ ПЕРЕЗАРЯДКИ [R]', 2.5, '#ffb347');
}

function manualReload() {
  if (G.mode !== 'play' || G.ammo &gt;= G.maxAmmo || G.reload &gt; 0) return;
  G.reload = 2.6;
  addTicker('ПЕРЕЗАРЯДКА...', 2.6, '#ffb347');
}

canvas.addEventListener('mousemove', e =&gt; {
  const r = canvas.getBoundingClientRect();
  mouse.x = e.clientX - r.left; mouse.y = e.clientY - r.top; mouse.inside = true;
});
canvas.addEventListener('mousedown', e =&gt; {
  Sfx.init();
  if (e.button === 0) { mouse.down = true; fireTorpedo(); }
  if (e.button === 2) G.targetZoom = 2.2;
  if (G.mode === 'menu') { document.getElementById('overlay').classList.add('hidden'); setTimeout(()=&gt;document.getElementById('overlay').style.display='none', 800); startGame(); }
  else if (G.mode === 'dead' || G.mode === 'win') { G.mode = 'menu'; const ov = document.getElementById('overlay'); ov.style.display = 'flex'; ov.classList.remove('hidden'); }
});
window.addEventListener('mouseup', e =&gt; { if (e.button === 0) mouse.down = false; if (e.button === 2) G.targetZoom = 1; });
canvas.addEventListener('contextmenu', e =&gt; e.preventDefault());
canvas.addEventListener('wheel', e =&gt; { e.preventDefault(); G.targetZoom = clamp(G.targetZoom - Math.sign(e.deltaY) * 0.25, 1, 2.6); }, { passive: false });

window.addEventListener('keydown', e =&gt; {
  Sfx.init(); keys[e.code] = true;
  if (e.code === 'Space') { e.preventDefault(); fireTorpedo(); }
  if (e.code === 'KeyR') manualReload();
  if (e.code === 'KeyP') G.paused = !G.paused;
});
window.addEventListener('keyup', e =&gt; { keys[e.code] = false; });

canvas.addEventListener('touchstart', e =&gt; {
  e.preventDefault(); Sfx.init();
  if (e.touches.length === 1) {
    touchPanX = e.touches[0].clientX; touchMoved = false;
    mouse.x = e.touches[0].clientX; mouse.y = e.touches[0].clientY; mouse.inside = true;
  } else if (e.touches.length === 2) {
    touchStartDist = Math.hypot(e.touches[0].clientX - e.touches[1].clientX, e.touches[0].clientY - e.touches[1].clientY);
    touchZoomStart = G.targetZoom;
  }
  if (G.mode === 'menu') { document.getElementById('overlay').classList.add('hidden'); setTimeout(()=&gt;document.getElementById('overlay').style.display='none', 800); startGame(); }
  else if (G.mode === 'dead' || G.mode === 'win') { G.mode = 'menu'; const ov = document.getElementById('overlay'); ov.style.display = 'flex'; ov.classList.remove('hidden'); }
}, { passive: false });

canvas.addEventListener('touchmove', e =&gt; {
  e.preventDefault();
  if (e.touches.length === 1 &amp;&amp; touchPanX !== null) {
    const dx = e.touches[0].clientX - touchPanX;
    if (Math.abs(dx) &gt; 3) touchMoved = true;
    G.camX = clamp(G.camX - dx * 1.4 / G.zoom, PAN_MIN, PAN_MAX);
    mouse.x = e.touches[0].clientX; mouse.y = e.touches[0].clientY; touchPanX = e.touches[0].clientX;
  } else if (e.touches.length === 2) {
    const d = Math.hypot(e.touches[0].clientX - e.touches[1].clientX, e.touches[0].clientY - e.touches[1].clientY) || 1;
    G.targetZoom = clamp(touchZoomStart * (touchStartDist / d), 1, 2.6); touchMoved = true;
  }
}, { passive: false });

canvas.addEventListener('touchend', e =&gt; {
  e.preventDefault();
  if (e.touches.length === 0) {
    if (touchPanX !== null &amp;&amp; !touchMoved &amp;&amp; G.mode === 'play') fireTorpedo();
    touchPanX = null; mouse.inside = false; touchMoved = false;
  }
}, { passive: false });

/* --- БЛОК 5: ИГРОВАЯ ЛОГИКА --- */
function spawnShip(typeKey) {
  const t = SHIPS[typeKey];
  const spd = rand(t.spd[0], t.spd[1]);
  const depthT = Math.random();
  const y = lerp(300, 780, depthT);
  const sizeMul = lerp(0.62, 1.15, depthT);
  const ship = {
    type: typeKey, t, spd, y, x: -(t.len * sizeMul) - rand(200, 900), sizeMul,
    hp: t.hp, maxHp: t.hp, burning: false, burnT: 0, state: 'alive', tilt: 0, sink: 0, alpha: 1,
    wps: t.wps.map(w =&gt; ({ ...w, hit: false, pulse: rand(0, TAU) })),
    sanity: 0, hitFlash: 0, civ: t.civ, singing: rand(2.5, 6), focused: 0, disabled: false
  };
  G.ships.push(ship);
  return ship;
}

function worldToScreen(wx, wy) { const s = G.zoom * K; return { x: (wx - G.camX) * s + CX, y: (wy - G.camY) * s + CY }; }
function screenToWorld(sx, sy) { const s = G.zoom * K; return { x: (sx - CX) / s + G.camX, y: (sy - CY) / s + G.camY }; }
function shipScreenPos(sh) { return worldToScreen(sh.x, sh.y); }
function shipVisible(sh) { const p = shipScreenPos(sh); return Math.hypot(p.x - CX, p.y - CY) &lt; VIEW_R * 1.05; }

function update(dt) {
  G.time += dt;
  const edgeL = CX - VIEW_R * 0.55, edgeR = CX + VIEW_R * 0.55;
  let panDir = 0;
  if (mouse.inside) {
    if (mouse.x &lt; edgeL) panDir = -(1 - mouse.x / Math.max(1, edgeL)) - 0.35;
    if (mouse.x &gt; edgeR) panDir = ((mouse.x - edgeR) / Math.max(1, CX - edgeR)) + 0.35;
  }
  if (panDir !== 0) G.camX += panDir * 1500 * dt / G.zoom;
  if (keys['KeyA']) G.camX -= 900 * dt / G.zoom;
  if (keys['KeyD']) G.camX += 900 * dt / G.zoom;
  G.camX = clamp(G.camX, PAN_MIN, PAN_MAX);
  G.zoom = lerp(G.zoom, G.targetZoom, 1 - Math.pow(0.001, dt));
  G.shake = Math.max(0, G.shake - dt * 2.4);
  G.flash = Math.max(0, G.flash - dt * 3.0);

  if (G.reload &gt; 0) {
    G.reload -= dt;
    if (G.reload &lt;= 0) {
      G.reload = 0;
      if (G.ammo &lt; G.maxAmmo) { G.ammo = Math.min(G.maxAmmo, G.ammo + Math.ceil(G.maxAmmo / 3)); Sfx.reload(); addTicker('ТОРПЕДЫ ЗАГРУЖЕНЫ', 1.4); }
    }
  }

  if (G.mode !== 'play') { updateParticles(dt); return; }

  G.waveTimer += dt;
  for (let i = G.spawnQueue.length - 1; i &gt;= 0; i--) {
    if (G.waveTimer * 260 &gt;= G.spawnQueue[i].at) { spawnShip(G.spawnQueue[i].type); G.spawnQueue.splice(i, 1); }
  }

  let visibleCount = 0, focusDrain = 0;
  for (let i = G.ships.length - 1; i &gt;= 0; i--) {
    const sh = G.ships[i], t = sh.t;
    if (sh.state === 'alive') {
      sh.x += sh.spd * dt;
      sh.singing -= dt;
      if (sh.singing &lt;= 0 &amp;&amp; shipVisible(sh)) { sh.singing = rand(3, 7); Sfx.whisper(); }
      if (sh.burning) {
        sh.burnT += dt;
        emitFire(sh.x + rand(-t.len * sh.sizeMul * 0.3, t.len * sh.sizeMul * 0.3), sh.y + rand(-10, t.depth * sh.sizeMul * 0.5), Math.min(4, Math.floor(1 + sh.burnT)), 0.9);
        if (Math.random() &lt; dt * 6) emitSmoke(sh.x, sh.y, 1);
      }
      if (sh.x &gt; PAN_MAX + 1400) { if (sh.civ &amp;&amp; !sh.disabled) G.civiliansLost++; G.ships.splice(i, 1); continue; }
      
      if (shipVisible(sh)) {
        visibleCount++;
        const p = shipScreenPos(sh);
        const near = 1 - clamp(Math.hypot(p.x - CX, p.y - CY) / VIEW_R, 0, 1);
        let drain = t.sanity * (0.35 + near * 0.65);
        const halfLen = t.len * sh.sizeMul * 0.5 * G.zoom * K;
        const onTarget = Math.abs(mouse.x - p.x) &lt; halfLen &amp;&amp; Math.abs(mouse.y - p.y) &lt; halfLen * 0.7;
        if (onTarget) {
          sh.focused += dt;
          const grace = clamp((sh.focused - 1.2) / 0.8, 0, 1);
          drain *= lerp(0.15, 2.4, grace);
        } else { sh.focused = Math.max(0, sh.focused - dt * 1.5); }
        focusDrain += drain;
      } else { sh.focused = Math.max(0, sh.focused - dt * 1.5); }
    } else if (sh.state === 'dying') {
      sh.sink += dt * 60; sh.tilt += dt * 0.35; sh.alpha = Math.max(0, sh.alpha - dt * 0.35); sh.x += sh.spd * dt * 0.3;
      emitFire(sh.x + rand(-t.len * 0.3, t.len * 0.3), sh.y + rand(0, t.depth), 3, 1.1);
      if (Math.random() &lt; dt * 8) emitSmoke(sh.x, sh.y, 1);
      if (Math.random() &lt; dt * 4) emitBubbles(sh.x + rand(-80, 80), sh.y + rand(0, 120), 4, 1);
      if (sh.alpha &lt;= 0) { G.ships.splice(i, 1); continue; }
    }
    sh.hitFlash = Math.max(0, sh.hitFlash - dt * 4);
  }

  if (visibleCount === 0) G.sanity = Math.min(1, G.sanity + dt * 0.16);
  else G.sanity = Math.max(0, G.sanity - focusDrain * dt);
  if (G.sanity &lt;= 0) { endGame(false); return; }
  G.distortion = clamp(1 - G.sanity / 0.45, 0, 1);

  for (let i = G.torpedoes.length - 1; i &gt;= 0; i--) {
    const tp = G.torpedoes[i];
    tp.x += tp.vx * dt; tp.y += tp.vy * dt; tp.life -= dt;
    tp.trail -= dt;
    if (tp.trail &lt;= 0) {
      tp.trail = 0.02;
      emitBubbles(tp.x, tp.y, 2, 0.8);
      spawnParticle({ x: tp.x, y: tp.y, vx: rand(-20, 20), vy: rand(-20, 20), life: 0.5, maxLife: 0.5, size: rand(6, 14), type: 'glow', hue: 35 });
    }
    let hit = false;
    for (const sh of G.ships) {
      if (sh.state !== 'alive') continue;
      const t = sh.t, sm = sh.sizeMul, halfL = t.len * sm * 0.5, D = t.depth * sm;
      for (const wp of sh.wps) {
        if (wp.hit) continue;
        const wx = sh.x + wp.x * t.len * sm, wy = sh.y + wp.y * sm;
        if (Math.hypot(tp.x - wx, tp.y - wy) &lt; wp.r * sm + 10) {
          wp.hit = true; hit = true; onWeakPoint(sh, wp, tp); break;
        }
      }
      if (hit) break;
      if (Math.abs(tp.x - sh.x) &lt; halfL &amp;&amp; tp.y &gt; sh.y - 20 &amp;&amp; tp.y &lt; sh.y + D) { hit = true; onHullHit(sh, tp); break; }
    }
    if (tp.y &lt; WORLD_TOP || tp.y &gt; 2000 || tp.life &lt;= 0 || tp.x &lt; -2500 || tp.x &gt; 6000) hit = true;
    if (hit) { emitBubbles(tp.x, tp.y, 14, 1.2); G.torpedoes.splice(i, 1); }
  }

  if (!G.betweenWaves &amp;&amp; G.spawnQueue.length === 0 &amp;&amp; G.ships.filter(s =&gt; s.state === 'alive').length === 0 &amp;&amp; G.ships.length === 0) {
    G.betweenWaves = true;
    setTimeout(() =&gt; { if (G.mode === 'play') nextWave(); }, 1400);
    if (G.wave &lt; WAVES.length) addTicker('СЕКТОР ОЧИЩЕН', 2.0);
  }

  for (let i = G.rings.length - 1; i &gt;= 0; i--) {
    const r = G.rings[i]; r.r += r.speed * dt; r.life -= dt * 0.7;
    if (r.life &lt;= 0) G.rings.splice(i, 1);
  }
  for (let i = G.ticker.length - 1; i &gt;= 0; i--) {
    G.ticker[i].life -= dt;
    if (G.ticker[i].life &lt;= 0) G.ticker.splice(i, 1);
  }
  updateParticles(dt);
}

function updateParticles(dt) {
  for (let i = G.particles.length - 1; i &gt;= 0; i--) {
    const p = G.particles[i];
    p.x += p.vx * dt; p.y += p.vy * dt;
    p.vx *= Math.pow(p.drag, dt * 60); p.vy *= Math.pow(p.drag, dt * 60);
    if (p.type === 'fire') p.vy -= 55 * dt;
    if (p.type === 'smoke') p.vy -= 12 * dt;
    if (p.type === 'bubble') p.vy -= 40 * dt;
    if (p.type === 'spark') p.vy += 90 * dt;
    p.life -= dt;
    if (p.life &lt;= 0) G.particles.splice(i, 1);
  }
  for (let i = G.debris.length - 1; i &gt;= 0; i--) {
    const d = G.debris[i];
    d.x += d.vx * dt; d.y += d.vy * dt; d.vy *= 0.98; d.vx *= 0.98; d.rot += d.rotSpeed * dt; d.life -= dt;
    if (d.life &lt;= 0) G.debris.splice(i, 1);
  }
}

function onWeakPoint(sh, wp, tp) {
  Sfx.hit(); G.shake = Math.max(G.shake, 0.5); G.flash = 0.35;
  if (wp.node &amp;&amp; sh.civ) {
    sh.disabled = true; sh.state = 'dying'; sh.tilt = 0.05; G.civiliansSaved++; G.score += 400;
    addTicker('КОВЧЕГ ОБЕЗВРЕЖЕН. ЛЮДИ ЖИВЫ.', 3.2, '#7ef0c8');
    if (!G.discovered) { G.discovered = true; addTicker('...в иллюминаторах были люди...', 4.0, '#ff88cc'); }
    emitSparks(tp.x, tp.y, 40, 1.2); return;
  }
  sh.hp -= 3; emitSparks(tp.x, tp.y, 34, 1.3); emitFire(tp.x, tp.y, 22, 1.2); sh.burning = true;
  if (sh.hp &lt;= 0) destroyShip(sh, tp);
}

function onHullHit(sh, tp) {
  Sfx.hit(); G.shake = Math.max(G.shake, 0.3); sh.hp -= 1; sh.hitFlash = 1;
  emitFire(tp.x, tp.y, 14, 1.0); emitSparks(tp.x, tp.y, 16, 1.0); sh.burning = true;
  if (sh.hp &lt;= 0) destroyShip(sh, tp);
}

function destroyShip(sh, tp) {
  sh.state = 'dying'; sh.tilt = rand(-0.25, 0.25); Sfx.boom(); G.shake = Math.max(G.shake, 1.0); G.flash = 0.7;
  emitFire(sh.x, sh.y + sh.t.depth * 0.3, 60, 1.8); emitSmoke(sh.x, sh.y, 20); emitSparks(sh.x, sh.y + 40, 60, 1.6); emitBubbles(sh.x, sh.y + 60, 40, 1.6);
  if (sh.civ) {
    G.civiliansLost++; G.score = Math.max(0, G.score - 300);
    addTicker('ТЫ УБИЛ ИХ. ОНИ БЫЛИ ЖИВЫ.', 4.5, '#ff4466');
    if (!G.discovered) { G.discovered = true; addTicker('...детский рисунок в иллюминаторе...', 5.0, '#ff88cc'); }
    if (Math.random() &lt; 0.7) {
      G.debris.push({ x: sh.x + rand(-20, 20), y: sh.y, vx: rand(-15, 15), vy: rand(-60, -30), rot: rand(0, TAU), rotSpeed: rand(-0.8, 0.8), life: 8.0, maxLife: 8.0, size: rand(40, 60) });
    }
  } else { G.score += sh.t.score; }
}

function spawnParticle(p) {
  if (G.particles.length &gt; 700) G.particles.shift();
  G.particles.push(Object.assign({ x: 0, y: 0, vx: 0, vy: 0, life: 1, maxLife: 1, size: 4, type: 'fire', hue: 30, drag: 0.96, grav: 0 }, p));
}
function emitFire(x, y, amount, power = 1) {
  for (let i = 0; i &lt; amount; i++) spawnParticle({ x: x + rand(-30, 30) * power, y: y + rand(-16, 10) * power, vx: rand(-40, 40) * power, vy: rand(-130, -45) * power, life: rand(0.5, 1.5), maxLife: 1.5, size: rand(8, 26) * power, type: 'fire', hue: rand(18, 46) });
}
function emitSmoke(x, y, amount) {
  for (let i = 0; i &lt; amount; i++) spawnParticle({ x: x + rand(-40, 40), y: y + rand(-20, 10), vx: rand(-25, 25), vy: rand(-70, -20), life: rand(1.4, 3.0), maxLife: 3.0, size: rand(20, 55), type: 'smoke' });
}
function emitBubbles(x, y, amount, power = 1) {
  for (let i = 0; i &lt; amount; i++) spawnParticle({ x: x + rand(-14, 14), y: y + rand(-10, 10), vx: rand(-35, 35) * power, vy: rand(-95, -35) * power, life: rand(0.6, 1.6), maxLife: 1.6, size: rand(2, 7) * power, type: 'bubble' });
}
function emitSparks(x, y, amount, power = 1) {
  for (let i = 0; i &lt; amount; i++) { const a = rand(0, TAU), sp = rand(120, 520) * power; spawnParticle({ x, y, vx: Math.cos(a) * sp, vy: Math.sin(a) * sp, life: rand(0.25, 0.8), maxLife: 0.8, size: rand(1.5, 4), type: 'spark', drag: 0.90 }); }
}

/* --- БЛОК 6 и 7: ВИЗУАЛ И ЧАСТИЦЫ --- */
const snowFar = [], snowNear = [];
function initSnow() {
  snowFar.length = 0; snowNear.length = 0;
  for (let i = 0; i &lt; 160; i++) snowFar.push({ x: rand(-2000, 4000), y: rand(-400, 1400), s: rand(1, 2.6), v: rand(6, 20), a: rand(0.10, 0.35) });
  for (let i = 0; i &lt; 50; i++) snowNear.push({ x: rand(-2000, 4000), y: rand(-400, 1400), s: rand(3, 7), v: rand(20, 55), a: rand(0.05, 0.16) });
}
initSnow();

function drawSnow(layer, parallax) {
  for (const s of layer) {
    const sy = s.y + (G.time * s.v) % 1900;
    const p = worldToScreen(s.x + G.camX * parallax, sy);
    if (p.x &lt; -50 || p.x &gt; W + 50 || p.y &lt; -50 || p.y &gt; H + 50) continue;
    ctx.fillStyle = `rgba(200,235,255,${s.a})`;
    ctx.beginPath(); ctx.arc(p.x, p.y, s.s, 0, TAU); ctx.fill();
  }
}

function drawBackground() {
  const top = worldToScreen(G.camX, WORLD_TOP).y, bot = worldToScreen(G.camX, 2400).y, surfaceY = worldToScreen(G.camX, 0).y;
  const g = ctx.createLinearGradient(0, top, 0, bot);
  g.addColorStop(0.00, '#dff6ff'); g.addColorStop(0.10, '#9fe4f5'); g.addColorStop(0.22, '#2f8fb5');
  g.addColorStop(0.42, '#0d4568'); g.addColorStop(0.68, '#052132'); g.addColorStop(1.00, '#01080f');
  ctx.fillStyle = g; ctx.fillRect(-W, top - 200, W * 3, bot - top + 400);
  ctx.save(); ctx.globalCompositeOperation = 'lighter';
  const sg = ctx.createLinearGradient(0, surfaceY - 90, 0, surfaceY + 140);
  sg.addColorStop(0, 'rgba(220,250,255,0)'); sg.addColorStop(0.45, 'rgba(190,240,255,0.30)');
  sg.addColorStop(0.55, 'rgba(220,255,255,0.42)'); sg.addColorStop(1, 'rgba(160,220,255,0)');
  ctx.fillStyle = sg; ctx.fillRect(-W, surfaceY - 90, W * 3, 230); ctx.restore();
  ctx.save(); ctx.globalCompositeOperation = 'lighter';
  for (let i = 0; i &lt; 11; i++) {
    const bx = -600 + i * 420 + Math.sin(G.time * 0.12 + i) * 90;
    const p1 = worldToScreen(bx, WORLD_TOP), p2 = worldToScreen(bx + 260 + Math.sin(G.time * 0.09 + i * 2) * 160, 1300);
    const a = 0.030 + 0.022 * Math.sin(G.time * 0.35 + i * 1.7);
    const lg = ctx.createLinearGradient(p1.x, p1.y, p2.x, p2.y);
    lg.addColorStop(0, `rgba(190,245,255,${a * 2.2})`); lg.addColorStop(1, 'rgba(120,200,255,0)');
    ctx.fillStyle = lg; ctx.beginPath(); ctx.moveTo(p1.x - 70, p1.y); ctx.lineTo(p1.x + 70, p1.y);
    ctx.lineTo(p2.x + 180, p2.y); ctx.lineTo(p2.x - 180, p2.y); ctx.closePath(); ctx.fill();
  }
  ctx.restore();
}

function drawRings() {
  ctx.save(); ctx.globalCompositeOperation = 'lighter';
  for (const r of G.rings) {
    const p = worldToScreen(r.x, r.y);
    ctx.strokeStyle = `rgba(130,240,255,${r.life * 0.45})`; ctx.lineWidth = 2.5;
    ctx.beginPath(); ctx.arc(p.x, p.y, r.r * K * G.zoom, 0, TAU); ctx.stroke();
  }
  ctx.restore();
}

function traceHull(c, L, D, bow) {
  const s = -L * 0.5, b = L * 0.5;
  c.beginPath(); c.moveTo(s, 0);
  c.bezierCurveTo(s + L * 0.06, D * 1.05, s + L * 0.35, D * 1.20, 0, D * 1.12);
  c.bezierCurveTo(L * 0.32, D * 1.06, b - L * bow, D * 0.78, b, 0);
  c.closePath();
}

function drawTop(c, type, L, D) {
  c.fillStyle = '#04080f'; c.strokeStyle = '#04080f';
  if (type === 'clipper') {
    c.lineWidth = Math.max(2, L * 0.012);
    [-0.30, 0, 0.28].forEach(mx =&gt; { c.beginPath(); c.moveTo(L * mx, 0); c.lineTo(L * mx * 1.03, -D * 1.65); c.stroke(); });
    c.lineWidth = Math.max(1.5, L * 0.008);
    [-0.30, 0, 0.28].forEach(mx =&gt; {
      c.beginPath(); c.moveTo(L * mx - L * 0.10, -D * 1.15); c.lineTo(L * mx + L * 0.10, -D * 1.15); c.stroke();
      c.beginPath(); c.moveTo(L * mx - L * 0.07, -D * 0.78); c.lineTo(L * mx + L * 0.07, -D * 0.78); c.stroke();
      c.beginPath(); c.moveTo(L * mx - L * 0.05, -D * 0.42); c.lineTo(L * mx + L * 0.05, -D * 0.42); c.stroke();
    });
  } else if (type === 'liner') {
    c.beginPath(); c.moveTo(-L * 0.34, 0); c.lineTo(L * 0.30, 0); c.lineTo(L * 0.23, -D * 0.58); c.lineTo(-L * 0.27, -D * 0.58); c.closePath(); c.fill();
    c.beginPath(); c.moveTo(-L * 0.22, -D * 0.58); c.lineTo(L * 0.16, -D * 0.58); c.lineTo(L * 0.10, -D * 1.10); c.lineTo(-L * 0.14, -D * 1.10); c.closePath(); c.fill();
    c.fillRect(-L * 0.07, -D * 1.52, L * 0.10, D * 0.44); c.fillRect(-L * 0.03, -D * 1.70, L * 0.04, D * 0.20);
  } else if (type === 'yacht') {
    c.beginPath(); c.moveTo(-L * 0.30, 0); c.lineTo(L * 0.20, 0); c.lineTo(L * 0.02, -D * 0.52); c.lineTo(-L * 0.22, -D * 0.52); c.closePath(); c.fill();
    c.fillRect(-L * 0.06, -D * 0.78, L * 0.03, D * 0.30);
  } else if (type === 'ark') {
    c.beginPath(); c.moveTo(-L * 0.42, 0); c.lineTo(L * 0.40, 0); c.lineTo(L * 0.40, -D * 1.25); c.lineTo(-L * 0.40, -D * 1.25); c.closePath(); c.fill();
    c.fillRect(-L * 0.30, -D * 1.50, L * 0.52, D * 0.26); c.fillRect(-L * 0.10, -D * 1.70, L * 0.16, D * 0.22);
  } else if (type === 'frigate') {
    c.beginPath(); c.moveTo(-L * 0.40, 0); c.lineTo(L * 0.34, 0); c.lineTo(L * 0.30, -D * 0.42); c.lineTo(-L * 0.34, -D * 0.42); c.closePath(); c.fill();
    c.fillRect(-L * 0.12, -D * 0.86, L * 0.22, D * 0.46); c.fillRect(-L * 0.02, -D * 1.04, L * 0.05, D * 0.20);
    c.beginPath(); c.moveTo(L * 0.04, -D * 0.42); c.lineTo(L * 0.34, -D * 0.54); c.lineTo(L * 0.34, -D * 0.40); c.closePath(); c.fill();
  }
}

function drawShip(sh) {
  const t = sh.t, sm = sh.sizeMul, L = t.len * sm, D = t.depth * sm, p = shipScreenPos(sh);
  ctx.save(); ctx.globalAlpha = sh.alpha; ctx.translate(p.x, p.y);
  if (sh.state === 'dying') { ctx.rotate(sh.tilt); ctx.translate(0, sh.sink * K * G.zoom * 0.6); }
  const s = G.zoom * K; ctx.scale(s, s);
  const halo = ctx.createRadialGradient(0, D * 0.5, 0, 0, D * 0.5, L * 0.75);
  halo.addColorStop(0, 'rgba(80,180,255,0.10)'); halo.addColorStop(1, 'rgba(80,180,255,0)');
  ctx.fillStyle = halo; ctx.beginPath(); ctx.ellipse(0, D * 0.5, L * 0.72, D * 1.3, 0, 0, TAU); ctx.fill();
  drawTop(ctx, sh.type, L, D);
  traceHull(ctx, L, D, t.bow);
  ctx.fillStyle = sh.hitFlash &gt; 0 ? `rgba(${180 + 70 * sh.hitFlash | 0},${90 + 100 * sh.hitFlash | 0},${60},1)` : '#04080f';
  ctx.fill();
  ctx.strokeStyle = 'rgba(150,220,255,0.30)'; ctx.lineWidth = Math.max(1, 1.6 / s); ctx.stroke();
  const n = Math.max(4, Math.floor(L / 72));
  for (let i = 0; i &lt; n; i++) {
    const px = -L * 0.36 + (i / (n - 1)) * (L * 0.70), py = D * 0.40;
    const flick = 0.55 + 0.25 * Math.sin(G.time * 3 + i * 1.4);
    ctx.fillStyle = `rgba(255,196,110,${flick})`; ctx.beginPath(); ctx.arc(px, py, Math.max(1.6, L * 0.011), 0, TAU); ctx.fill();
  }
  if (sh.civ &amp;&amp; sh.state === 'alive') {
    const px = L * 0.30, py = D * 0.40, pulse = 0.6 + 0.4 * Math.sin(G.time * 4);
    ctx.fillStyle = `rgba(255,120,190,${pulse})`; ctx.beginPath(); ctx.arc(px, py, Math.max(2.4, L * 0.014), 0, TAU); ctx.fill();
    ctx.fillStyle = `rgba(255,220,240,${pulse})`; ctx.beginPath(); ctx.arc(px, py - 2.2 * sm, 1.5 * sm, 0, TAU); ctx.fill();
    ctx.fillRect(px - 1.2 * sm, py - 0.6 * sm, 2.4 * sm, 3.2 * sm);
  }
  if (sh.state === 'alive') {
    for (const wp of sh.wps) {
      if (wp.hit) continue;
      const wx = wp.x * L, wy = wp.y * sm; wp.pulse += 0.05;
      const pr = wp.r * sm * (1 + 0.12 * Math.sin(wp.pulse * 3)), isNode = wp.node;
      const gg = ctx.createRadialGradient(wx, wy, 0, wx, wy, pr * 2.2);
      if (isNode) { gg.addColorStop(0, 'rgba(120,255,220,0.95)'); gg.addColorStop(0.4, 'rgba(80,220,255,0.45)'); gg.addColorStop(1, 'rgba(80,220,255,0)'); }
      else { gg.addColorStop(0, 'rgba(255,220,120,0.95)'); gg.addColorStop(0.4, 'rgba(255,110,40,0.45)'); gg.addColorStop(1, 'rgba(255,80,0,0)'); }
      ctx.fillStyle = gg; ctx.beginPath(); ctx.arc(wx, wy, pr * 2.2, 0, TAU); ctx.fill();
      ctx.strokeStyle = isNode ? 'rgba(160,255,230,0.9)' : 'rgba(255,200,120,0.85)'; ctx.lineWidth = Math.max(1, 1.8 / s);
      ctx.beginPath(); ctx.arc(wx, wy, pr, 0, TAU); ctx.stroke();
      ctx.beginPath(); ctx.moveTo(wx - pr * 1.5, wy); ctx.lineTo(wx - pr * 0.6, wy); ctx.moveTo(wx + pr * 0.6, wy); ctx.lineTo(wx + pr * 1.5, wy);
      ctx.moveTo(wx, wy - pr * 1.5); ctx.lineTo(wx, wy - pr * 0.6); ctx.moveTo(wx, wy + pr * 0.6); ctx.lineTo(wx, wy + pr * 1.5); ctx.stroke();
    }
  }
  ctx.restore();
}

function createDrawingTexture() {
  const c = document.createElement('canvas'); c.width = 128; c.height = 128;
  const d = c.getContext('2d');
  d.fillStyle = '#e8dcc0'; d.fillRect(0, 0, 128, 128);
  const burn = d.createRadialGradient(64, 64, 30, 64, 64, 80);
  burn.addColorStop(0, 'rgba(0,0,0,0)'); burn.addColorStop(0.7, 'rgba(60,30,10,0.2)'); burn.addColorStop(1, 'rgba(30,10,0,0.7)');
  d.fillStyle = burn; d.fillRect(0, 0, 128, 128);
  d.strokeStyle = '#d63030'; d.fillStyle = '#ffcc33'; d.lineWidth = 2;
  d.beginPath(); d.arc(30, 30, 12, 0, TAU); d.fill(); d.stroke();
  for (let i = 0; i &lt; 8; i++) { const a = i * TAU / 8; d.beginPath(); d.moveTo(30 + Math.cos(a) * 15, 30 + Math.sin(a) * 15); d.lineTo(30 + Math.cos(a) * 22, 30 + Math.sin(a) * 22); d.stroke(); }
  d.strokeStyle = '#333'; d.lineWidth = 2.5; d.fillStyle = '#c9a876';
  d.beginPath(); d.moveTo(50, 70); d.lineTo(75, 45); d.lineTo(100, 70); d.closePath(); d.fill(); d.stroke();
  d.fillRect(55, 70, 40, 30); d.strokeRect(55, 70, 40, 30);
  d.fillStyle = '#6b4423'; d.fillRect(70, 82, 10, 18);
  d.strokeStyle = '#222'; d.lineWidth = 1.8;
  d.beginPath(); d.arc(25, 90, 4, 0, TAU); d.stroke(); d.beginPath(); d.moveTo(25, 94); d.lineTo(25, 108); d.stroke();
  d.beginPath(); d.moveTo(20, 100); d.lineTo(30, 100); d.stroke(); d.beginPath(); d.moveTo(25, 108); d.lineTo(20, 118); d.stroke(); d.beginPath(); d.moveTo(25, 108); d.lineTo(30, 118); d.stroke();
  d.beginPath(); d.arc(38, 98, 3, 0, TAU); d.stroke(); d.beginPath(); d.moveTo(38, 101); d.lineTo(38, 111); d.stroke();
  d.beginPath(); d.moveTo(33, 106); d.lineTo(43, 106); d.stroke(); d.beginPath(); d.moveTo(38, 111); d.lineTo(35, 118); d.stroke(); d.beginPath(); d.moveTo(38, 111); d.lineTo(41, 118); d.stroke();
  d.fillStyle = '#222'; d.font = 'bold 14px "Courier New", monospace'; d.textAlign = 'center'; d.fillText('МАМЕ', 64, 122);
  return c;
}
const drawingCanvas = createDrawingTexture();

function drawParticles() {
  ctx.save();
  for (const p of G.particles) {
    if (p.type !== 'smoke') continue;
    const a = (p.life / p.maxLife) * 0.16, sp = worldToScreen(p.x, p.y);
    ctx.fillStyle = `rgba(30,50,70,${a})`; ctx.beginPath(); ctx.arc(sp.x, sp.y, p.size * K * G.zoom, 0, TAU); ctx.fill();
  }
  ctx.restore();
  ctx.save(); ctx.globalCompositeOperation = 'lighter';
  for (const p of G.particles) {
    if (p.type === 'smoke') continue;
    const t = p.life / p.maxLife, sp = worldToScreen(p.x, p.y);
    const r = p.size * K * G.zoom * (p.type === 'fire' ? (0.5 + t * 0.9) : 1);
    if (p.type === 'fire') { const hue = p.hue * t + 8, light = 30 + 60 * t; ctx.fillStyle = `hsla(${hue},100%,${light}%,${t * 0.75})`; ctx.beginPath(); ctx.arc(sp.x, sp.y, r, 0, TAU); ctx.fill(); }
    else if (p.type === 'spark') { ctx.fillStyle = `rgba(255,${180 + 70 * t | 0},120,${t})`; ctx.beginPath(); ctx.arc(sp.x, sp.y, Math.max(0.8, p.size * K * G.zoom), 0, TAU); ctx.fill(); }
    else if (p.type === 'bubble') { ctx.strokeStyle = `rgba(190,235,255,${t * 0.55})`; ctx.lineWidth = Math.max(0.7, 1.1 * K * G.zoom); ctx.beginPath(); ctx.arc(sp.x, sp.y, Math.max(1, p.size * K * G.zoom), 0, TAU); ctx.stroke(); }
    else if (p.type === 'glow') { const gg = ctx.createRadialGradient(sp.x, sp.y, 0, sp.x, sp.y, r * 3); gg.addColorStop(0, `rgba(255,220,150,${t * 0.8})`); gg.addColorStop(0.5, `rgba(255,120,30,${t * 0.35})`); gg.addColorStop(1, 'rgba(255,60,0,0)'); ctx.fillStyle = gg; ctx.beginPath(); ctx.arc(sp.x, sp.y, r * 3, 0, TAU); ctx.fill(); }
  }
  ctx.restore();
}

function drawTorpedoes() {
  ctx.save(); ctx.globalCompositeOperation = 'lighter';
  for (const tp of G.torpedoes) {
    const p = worldToScreen(tp.x, tp.y), R = 26 * K * G.zoom;
    const ang = Math.atan2(-tp.vy, -tp.vx), tailX = p.x + Math.cos(ang) * R * 4.5, tailY = p.y + Math.sin(ang) * R * 4.5;
    const lg = ctx.createLinearGradient(p.x, p.y, tailX, tailY);
    lg.addColorStop(0, 'rgba(255,240,190,0.85)'); lg.addColorStop(0.35, 'rgba(255,150,40,0.45)'); lg.addColorStop(1, 'rgba(255,60,0,0)');
    ctx.strokeStyle = lg; ctx.lineWidth = R * 0.85; ctx.lineCap = 'round';
    ctx.beginPath(); ctx.moveTo(p.x, p.y); ctx.lineTo(tailX, tailY); ctx.stroke();
    const cg = ctx.createRadialGradient(p.x, p.y, 0, p.x, p.y, R * 2.2);
    cg.addColorStop(0, 'rgba(255,255,240,1)'); cg.addColorStop(0.28, 'rgba(255,210,120,0.85)'); cg.addColorStop(1, 'rgba(255,90,0,0)');
    ctx.fillStyle = cg; ctx.beginPath(); ctx.arc(p.x, p.y, R * 2.2, 0, TAU); ctx.fill();
  }
  ctx.restore();
}

function drawDebris() {
  for (const d of G.debris) {
    const p = worldToScreen(d.x, d.y), size = d.size * K * G.zoom, alpha = Math.min(1, d.life / 2.0);
    ctx.save(); ctx.globalAlpha = alpha; ctx.translate(p.x, p.y); ctx.rotate(d.rot);
    ctx.shadowColor = 'rgba(255, 200, 150, 0.6)'; ctx.shadowBlur = 15;
    ctx.drawImage(drawingCanvas, -size / 2, -size / 2, size, size);
    ctx.restore();
  }
}

/* --- БЛОК 8: ИНТЕРФЕЙС И ЦИКЛ --- */
function drawScopeOverlay() {
  ctx.save(); ctx.beginPath(); ctx.rect(0, 0, W, H); ctx.arc(CX, CY, VIEW_R, 0, TAU, true); ctx.fillStyle = '#000'; ctx.fill(); ctx.restore();
  ctx.save();
  const rim = ctx.createRadialGradient(CX, CY, VIEW_R * 0.82, CX, CY, VIEW_R * 1.05);
  rim.addColorStop(0, 'rgba(0,0,0,0)'); rim.addColorStop(0.6, 'rgba(0,0,0,0.55)'); rim.addColorStop(1, 'rgba(0,0,0,0.98)');
  ctx.fillStyle = rim; ctx.beginPath(); ctx.arc(CX, CY, VIEW_R * 1.06, 0, TAU); ctx.fill(); ctx.restore();
  ctx.save(); ctx.strokeStyle = 'rgba(70,90,105,0.55)'; ctx.lineWidth = 3; ctx.beginPath(); ctx.arc(CX, CY, VIEW_R * 1.005, 0, TAU); ctx.stroke();
  ctx.strokeStyle = 'rgba(140,180,200,0.20)'; ctx.lineWidth = 1; ctx.beginPath(); ctx.arc(CX, CY, VIEW_R * 1.02, 0, TAU); ctx.stroke(); ctx.restore();
  ctx.save(); ctx.globalCompositeOperation = 'lighter';
  const lens = ctx.createLinearGradient(CX - VIEW_R, CY - VIEW_R, CX + VIEW_R * 0.4, CY + VIEW_R * 0.4);
  lens.addColorStop(0, 'rgba(180,230,255,0.055)'); lens.addColorStop(0.5, 'rgba(180,230,255,0)'); lens.addColorStop(1, 'rgba(180,230,255,0.02)');
  ctx.fillStyle = lens; ctx.beginPath(); ctx.arc(CX, CY, VIEW_R, 0, TAU); ctx.fill(); ctx.restore();
}

function drawReticle() {
  const inView = Math.hypot(mouse.x - CX, mouse.y - CY) &lt; VIEW_R * 0.94;
  let mx = mouse.x, my = mouse.y;
  if (!inView) { const a = Math.atan2(mouse.y - CY, mouse.x - CX); mx = CX + Math.cos(a) * VIEW_R * 0.94; my = CY + Math.sin(a) * VIEW_R * 0.94; }
  ctx.save(); ctx.strokeStyle = 'rgba(120,255,200,0.75)'; ctx.lineWidth = 1.4; const gap = 22, len = 34;
  ctx.beginPath(); ctx.moveTo(mx - gap - len, my); ctx.lineTo(mx - gap, my); ctx.moveTo(mx + gap, my); ctx.lineTo(mx + gap + len, my);
  ctx.moveTo(mx, my - gap - len); ctx.lineTo(mx, my - gap); ctx.moveTo(mx, my + gap); ctx.lineTo(mx, my + gap + len); ctx.stroke();
  ctx.beginPath(); ctx.arc(mx, my, gap * 0.62, 0, TAU); ctx.stroke();
  ctx.fillStyle = 'rgba(120,255,200,0.9)'; ctx.beginPath(); ctx.arc(mx, my, 1.8, 0, TAU); ctx.fill();
  ctx.strokeStyle = 'rgba(120,255,200,0.30)'; ctx.lineWidth = 1;
  for (let i = 1; i &lt;= 4; i++) { const y = my + i * 24, w = 14 - i * 2; ctx.beginPath(); ctx.moveTo(mx - w, y); ctx.lineTo(mx + w, y); ctx.stroke(); }
  ctx.restore();
  for (const sh of G.ships) {
    if (sh.state !== 'alive') continue;
    const p = shipScreenPos(sh);
    for (const wp of sh.wps) {
      if (wp.hit) continue;
      const s = G.zoom * K, wx = p.x + wp.x * sh.t.len * sh.sizeMul * s, wy = p.y + wp.y * sh.sizeMul * s;
      if (Math.hypot(wx - mx, wy - my) &lt; wp.r * sh.sizeMul * s * 1.6 + 12) {
        ctx.save(); ctx.strokeStyle = wp.node ? 'rgba(140,255,230,0.95)' : 'rgba(255,210,120,0.95)'; ctx.lineWidth = 2; ctx.setLineDash([5, 4]);
        ctx.beginPath(); ctx.arc(wx, wy, wp.r * sh.sizeMul * s * 1.9, 0, TAU); ctx.stroke(); ctx.restore();
      }
    }
  }
}

function drawHUD() {
  ctx.save(); ctx.font = `${Math.max(12, H * 0.016)}px "Courier New",monospace`; ctx.textBaseline = 'middle';
  ctx.fillStyle = 'rgba(126,240,200,0.85)'; ctx.textAlign = 'left'; ctx.fillText(`ВОЛНА ${G.wave}/${WAVES.length}`, 34, 40);
  ctx.fillStyle = 'rgba(126,240,200,0.5)'; ctx.fillText(`СЧЁТ ${G.score}`, 34, 66);
  const bw = 190, bh = 12, bx = W - 34 - bw, by = 34; ctx.textAlign = 'right'; ctx.fillStyle = 'rgba(126,240,200,0.6)'; ctx.fillText('РАССУДОК', W - 34, by - 14);
  ctx.strokeStyle = 'rgba(126,240,200,0.35)'; ctx.lineWidth = 1; ctx.strokeRect(bx, by, bw, bh);
  const sanCol = G.sanity &gt; 0.55 ? '#7ef0c8' : G.sanity &gt; 0.28 ? '#ffb347' : '#ff4466';
  ctx.fillStyle = sanCol; ctx.fillRect(bx + 1, by + 1, (bw - 2) * G.sanity, bh - 2);
  if (G.sanity &lt; 0.30 &amp;&amp; Math.sin(G.time * 12) &gt; 0) { ctx.fillStyle = '#ff4466'; ctx.fillText('ОТВЕДИ ВЗГЛЯД', W - 34, by + bh + 18); }
  const tpY = H - 52, tpX0 = CX - (G.maxAmmo * 22) / 2;
  for (let i = 0; i &lt; G.maxAmmo; i++) {
    const x = tpX0 + i * 22, loaded = i &lt; G.ammo;
    ctx.beginPath(); ctx.moveTo(x, tpY - 9); ctx.lineTo(x + 9, tpY); ctx.lineTo(x, tpY + 9); ctx.lineTo(x - 9, tpY); ctx.closePath();
    if (loaded) { ctx.fillStyle = 'rgba(255,160,60,0.85)'; ctx.fill(); } else { ctx.strokeStyle = 'rgba(255,160,60,0.35)'; ctx.stroke(); }
  }
  ctx.textAlign = 'center'; ctx.fillStyle = 'rgba(126,240,200,0.5)'; ctx.fillText('ОГНЕННЫЕ ТОРПЕДЫ', CX, tpY + 26);
  if (G.reload &gt; 0) {
    const rw = 220, rh = 5, rx = CX - rw / 2, ry = H - 100;
    ctx.fillStyle = 'rgba(255,179,71,0.2)'; ctx.fillRect(rx, ry, rw, rh);
    ctx.fillStyle = 'rgba(255,179,71,0.9)'; ctx.fillRect(rx, ry, rw * (1 - clamp(G.reload / 2.6, 0, 1)), rh);
  }
  ctx.textAlign = 'center'; let ty = H - 140;
  for (let i = G.ticker.length - 1; i &gt;= 0; i--) {
    const m = G.ticker[i], a = Math.min(1, m.life / 0.6); ctx.globalAlpha = a; ctx.fillStyle = m.color;
    ctx.font = `${Math.max(13, H * 0.018)}px "Courier New",monospace`; ctx.fillText(m.text, CX, ty); ty -= Math.max(20, H * 0.026); ctx.globalAlpha = 1;
  }
  if (G.discovered) {
    ctx.font = `${Math.max(11, H * 0.014)}px "Courier New",monospace`; ctx.textAlign = 'left';
    ctx.fillStyle = 'rgba(255,136,204,0.75)'; ctx.fillText(`СПАСЕНО: ${G.civiliansSaved}`, 34, H - 84);
    ctx.fillStyle = 'rgba(255,68,102,0.75)'; ctx.fillText(`ПОГИБЛО: ${G.civiliansLost}`, 34, H - 62);
  }
  if (G.distortion &gt; 0.01) {
    const d = G.distortion; ctx.save(); ctx.globalCompositeOperation = 'lighter';
    const vg = ctx.createRadialGradient(CX, CY, VIEW_R * 0.35, CX, CY, VIEW_R);
    vg.addColorStop(0, 'rgba(120,0,90,0)'); vg.addColorStop(1, `rgba(140,0,90,${0.5 * d})`);
    ctx.fillStyle = vg; ctx.beginPath(); ctx.arc(CX, CY, VIEW_R, 0, TAU); ctx.fill(); ctx.restore();
    if (d &gt; 0.35) { ctx.save(); ctx.globalAlpha = (d - 0.35) * 0.5; for (let i = 0; i &lt; 8; i++) { ctx.fillStyle = 'rgba(180,60,160,0.20)'; ctx.fillRect(0, rand(0, H), W, rand(1, 4)); } ctx.restore(); }
  }
  if (G.wave === 1 &amp;&amp; G.time &lt; 14) {
    ctx.textAlign = 'center'; ctx.fillStyle = `rgba(126,240,200,${clamp((14 - G.time) / 3, 0, 1) * 0.55})`;
    ctx.font = `${Math.max(12, H * 0.016)}px "Courier New",monospace`;
    ctx.fillText('МЫШЬ — НАВЕДЕНИЕ И ПАНОРАМА • ЛКМ — ТОРПЕДА • ПКМ — ЗУМ • A/D — ТОЧНАЯ НАВОДКА', CX, H - 175);
  }
  ctx.restore();
}

function drawMenu() {
  ctx.fillStyle = '#000'; ctx.fillRect(0, 0, W, H);
  const g = ctx.createRadialGradient(CX, CY * 0.7, 0, CX, CY, Math.max(W, H) * 0.8);
  g.addColorStop(0, 'rgba(20,70,100,0.55)'); g.addColorStop(1, 'rgba(0,0,0,1)'); ctx.fillStyle = g; ctx.fillRect(0, 0, W, H);
  ctx.textAlign = 'center'; ctx.fillStyle = '#7ef0c8'; ctx.font = `bold ${Math.max(38, H * 0.075)}px "Courier New",monospace`; ctx.fillText('ПЛАМЯ ГЛУБИН', CX, CY - H * 0.14);
  ctx.fillStyle = 'rgba(126,240,200,0.55)'; ctx.font = `${Math.max(13, H * 0.020)}px "Courier New",monospace`;
  ctx.fillText('2145. Посейдон. Последняя субмарина «Гефест».', CX, CY - H * 0.06);
  ctx.fillText('Сирены идут по фронту. Ты — глаза лодки.', CX, CY - H * 0.02);
  ctx.fillStyle = 'rgba(255,136,204,0.75)'; ctx.font = `${Math.max(12, H * 0.018)}px "Courier New",monospace`; ctx.fillText('Но помни: они прекрасны не просто так.', CX, CY + H * 0.045);
  const pulse = 0.55 + 0.45 * Math.sin(G.time * 3); ctx.fillStyle = `rgba(255,179,71,${pulse})`;
  ctx.font = `bold ${Math.max(15, H * 0.024)}px "Courier New",monospace`; ctx.fillText('— КЛИК, ЧТОБЫ ПОГРУЗИТЬСЯ —', CX, CY + H * 0.16);
  ctx.fillStyle = 'rgba(126,240,200,0.35)'; ctx.font = `${Math.max(11, H * 0.015)}px "Courier New",monospace`; ctx.fillText('ЛКМ — торпеда • ПКМ — зум • A/D — наводка • R — перезарядка', CX, H - 60);
}

function drawEndScreen(win) {
  ctx.fillStyle = 'rgba(0,0,0,0.86)'; ctx.fillRect(0, 0, W, H); ctx.textAlign = 'center';
  if (win) {
    ctx.fillStyle = '#7ef0c8'; ctx.font = `bold ${Math.max(30, H * 0.058)}px "Courier New",monospace`; ctx.fillText('СЕКТОР ОЧИЩЕН', CX, CY - H * 0.10);
    ctx.fillStyle = 'rgba(126,240,200,0.7)'; ctx.font = `${Math.max(13, H * 0.019)}px "Courier New",monospace`;
    ctx.fillText(`Счёт: ${G.score}`, CX, CY - H * 0.01); ctx.fillText(`Ковчегов спасено: ${G.civiliansSaved}`, CX, CY + H * 0.03);
    ctx.fillStyle = G.civiliansLost &gt; 0 ? '#ff4466' : 'rgba(126,240,200,0.7)'; ctx.fillText(`Ковчегов потеряно: ${G.civiliansLost}`, CX, CY + H * 0.07);
    let verdict = G.civiliansLost === 0 &amp;&amp; G.civiliansSaved &gt; 0 ? '«Ты видел в них людей. Это редкость.»' : G.civiliansLost === 0 ? '«Ты не тронул ни одного ковчега. Посейдон пал, но совесть — нет.»' : G.civiliansSaved &gt; 0 ? '«Ты спас часть. Остальное — пепел на дне.»' : '«Ты стрелял красиво. И убивал красиво.»';
    ctx.fillStyle = 'rgba(255,136,204,0.85)'; ctx.font = `${Math.max(12, H * 0.018)}px "Courier New",monospace`; ctx.fillText(verdict, CX, CY + H * 0.15);
  } else {
    ctx.fillStyle = '#ff4466'; ctx.font = `bold ${Math.max(30, H * 0.058)}px "Courier New",monospace`; ctx.fillText('РАЗУМ ПОТЕРЯН', CX, CY - H * 0.08);
    ctx.fillStyle = 'rgba(255,136,204,0.8)'; ctx.font = `${Math.max(13, H * 0.019)}px "Courier New",monospace`;
    ctx.fillText('Ты смотрел на них слишком долго.', CX, CY + H * 0.02); ctx.fillText('Они позвали — и ты пошёл.', CX, CY + H * 0.06);
    ctx.fillStyle = 'rgba(126,240,200,0.6)'; ctx.fillText(`Счёт: ${G.score} • Волна: ${G.wave}`, CX, CY + H * 0.13);
  }
  const pulse = 0.5 + 0.5 * Math.sin(G.time * 3); ctx.fillStyle = `rgba(255,179,71,${pulse})`;
  ctx.font = `bold ${Math.max(14, H * 0.022)}px "Courier New",monospace`; ctx.fillText('— КЛИК, ЧТОБЫ ВЕРНУТЬСЯ —', CX, CY + H * 0.24);
}

function render() {
  ctx.fillStyle = '#000'; ctx.fillRect(0, 0, W, H);
  if (G.mode === 'menu') { drawMenu(); return; }
  const sh = G.shake, ox = sh ? rand(-1, 1) * sh * 14 : 0, oy = sh ? rand(-1, 1) * sh * 14 : 0;
  ctx.save(); ctx.translate(ox, oy);
  ctx.save(); ctx.beginPath(); ctx.arc(CX, CY, VIEW_R, 0, TAU); ctx.clip();
  drawBackground(); drawSnow(snowFar, 0.25); drawRings();
  const sorted = G.ships.slice().sort((a, b) =&gt; a.y - b.y);
  for (const s of sorted) drawShip(s);
  drawParticles(); drawTorpedoes(); drawDebris(); drawSnow(snowNear, 0.55);
  if (G.flash &gt; 0.01) { ctx.save(); ctx.globalCompositeOperation = 'lighter'; ctx.fillStyle = `rgba(255,200,140,${G.flash * 0.35})`; ctx.fillRect(0, 0, W, H); ctx.restore(); }
  ctx.restore();
  drawScopeOverlay();
  ctx.save(); ctx.beginPath(); ctx.arc(CX, CY, VIEW_R * 0.99, 0, TAU); ctx.clip(); drawReticle(); ctx.restore();
  ctx.restore();
  if (G.mode === 'play') drawHUD();
  if (G.mode === 'dead') drawEndScreen(false);
  if (G.mode === 'win') drawEndScreen(true);
  if (G.paused &amp;&amp; G.mode === 'play') { ctx.fillStyle = 'rgba(0,0,0,0.6)'; ctx.fillRect(0, 0, W, H); ctx.textAlign = 'center'; ctx.fillStyle = '#7ef0c8'; ctx.font = `bold ${Math.max(24, H * 0.04)}px "Courier New",monospace`; ctx.fillText('ПАУЗА [P]', CX, CY); }
}

let last = performance.now();
function loop(now) {
  const dt = Math.min(0.05, (now - last) / 1000); last = now;
  if (G.mode === 'menu') G.time += dt;
  else if (!G.paused) update(dt);
  render();
  requestAnimationFrame(loop);
}
requestAnimationFrame(loop);
&lt;/script&gt;


&lt;script&gt;
(function() {
  "use strict";
  
  const container = document.getElementById('depths-game-container');
  const canvas = document.getElementById('game');
  const btn = document.getElementById('depths-fs-btn');
  
  if (!container || !canvas) {
    console.warn('⚠️ ПЛАМЯ ГЛУБИН: Контейнер или Canvas не найдены.');
    return;
  }

  let inTheater = false;

  function fireResize() {
    window.dispatchEvent(new Event('resize'));
  }

  function enterTheater() {
    if (inTheater) return;
    inTheater = true;
    document.body.classList.add('depths-theater-mode');
    container.classList.add('depths-theater-mode');
    btn.textContent = '✕ СВЕРНУТЬ (ESC)';
    
    // Запрос нативного полноэкранного режима браузера
    if (container.requestFullscreen) {
      container.requestFullscreen().catch(() =&gt; {});
    } else if (container.webkitRequestFullscreen) {
      container.webkitRequestFullscreen();
    }
    
    // Принудительный пересчёт размеров Canvas
    setTimeout(fireResize, 50);
    setTimeout(fireResize, 200);
    setTimeout(fireResize, 500);
    setTimeout(fireResize, 1000);
  }

  function exitTheater() {
    if (!inTheater) return;
    inTheater = false;
    document.body.classList.remove('depths-theater-mode');
    container.classList.remove('depths-theater-mode');
    btn.textContent = '⛶ РАЗВЕРНУТЬ';
    
    // Выход из нативного полноэкранного режима
    if (document.fullscreenElement) {
      document.exitFullscreen().catch(() =&gt; {});
    }
    
    setTimeout(fireResize, 50);
    setTimeout(fireResize, 300);
  }

  function toggle() {
    inTheater ? exitTheater() : enterTheater();
  }

  // Обработчик кнопки
  btn.addEventListener('click', function(e) {
    e.preventDefault();
    e.stopPropagation();
    toggle();
  });

  // Горячие клавиши
  window.addEventListener('keydown', function(e) {
    if (e.key === 'Escape' &amp;&amp; inTheater) {
      e.preventDefault();
      e.stopPropagation();
      exitTheater();
    }
    if (e.key === 'F11') {
      e.preventDefault();
      e.stopPropagation();
      toggle();
    }
  }, true);

  // Отслеживание выхода из Fullscreen через системный Esc
  document.addEventListener('fullscreenchange', function() {
    if (!document.fullscreenElement &amp;&amp; !document.webkitFullscreenElement &amp;&amp; inTheater) {
      // Не сворачиваем игру полностью, просто синхронизируем кнопку
      btn.textContent = '✕ СВЕРНУТЬ';
    }
  });

  // Мобильная ориентация
  window.addEventListener('orientationchange', function() {
    if (inTheater) setTimeout(fireResize, 300);
  });

  console.log('✅ ПЛАМЯ ГЛУБИН: Надёжный патч полноэкранного режима активен.');
})();
&lt;/script&gt;

&lt;/body&gt;
&lt;/html&gt;</subtitle>
  <updated>2026-09-22T08:19:14Z</updated>
  <logo>https://pandoraburo.ru/ssl/u/pic/ef/f66878aa6d11f1abb9f7ceed6face4/-/image%20%284%29.jpg</logo>
  <author>
    <name>1592962</name>
    <uri>https://www.pandoraburo.ru/</uri>
  </author>
</feed>
