Files
fishing-game/index.html
T
andrey 0a0595c3c1 Этап 47: ревизия SVG-портретов рыб — детализация до уровня болотных + биологическое правдоподобие. (1) Полная перерисовка 32 портретов, кроме 5 болотных (эталон стиля, Этап 45): 8 речных (carass, perch, bream, carp, pike, catfish, sturge, gold), 10 озёрных (zander, chuch, crayfish, bleak, roundel, eelpout, tench, navaga, rudd, cisco), 5 морских (herring, mackerel, flounder, tuna, swordfish), 9 океанских (moray, grouper, turtle, angler, octopus, manta, shark, squid, whale). (2) Единый стиль: послойные заливки без градиентов/defs (--f1 тело, --f3 плавники — перекрашиваются вариантами; --f2 брюхо/светлое, --f4 тёмный узор/кромка — НЕ перекрашиваются), спинная кромка f4-серпом, жаберная пластина+дуга, глаз 5 кругов (ободок→склера→радужка фикс-hex→зрачок→блик), составные узоры (полосы/пятна/чешуя/жучки/финлеты) — одним compound-path, ≤38 элементов, фикс-hex-акценты разрешены. (3) Видовые отличия и разведение «двойников»: карась↔карп (усы), окунь↔судак (горб/полосы/красное vs косая полоса/клыки), лещ↔густера (длинная анальная «юбка» vs короткий анальный+крупный глаз+киль), плотва↔краснопёрка (красный vs жёлтый глаз, рот конечный vs вверх), сом↔вьюн (голова-¼/длинные усы vs лента/10 усиков), мурена↔вьюн, осьминог↔кальмар (мешок+8 равных рук vs мантия-ракета+2 ловчих+крылышки), кит↔акула (флоскулы/фонтан/ус vs треуг. D/гетероцерк/5 щелей), сельдь↔скумбрия↔тунец↔меч, манта↔камбала↔рак, черепаха (вид сверху). (4) «Не рыбы»: crayfish (рак, вид сверху, клешни/ноги/веер), turtle (черепаха, вид сверху, щитки/4 ласты/клюв), octopus/squid/whale — иная анатомия (присоски/ловчие щупальца/флоскулы/фонтан), допустимые отклонения от рыбьего протокола. (5) Двойные боссы sturge (Река) и whale (Океан) проверены под золотой аурой #card.boss-card — контраст держат f4-детали. (6) Дефекты, найденные на приёмке и исправленные точечно (композиция не менялась): octopus — 2 щели с фоном; swordfish — светлый стык голова↔меч; tuna — прозрачная «дыра» в выемке хвоста-полумесяца; grouper — щель пасть↔нижняя челюсть; angler — просвет между римом и эской. (7) viewBox (0 0 160 100) и id/имена файлов не менялись; данные/логика/баланс не тронуты. (8) Интеграция: node tools/embed-fish.mjs — блок FISH-SVG обновлён (202478 байт / 1512 строк, 37 symbol); проверено совпадение всех 37 symbol с текущими assets/fish/*.svg; tools/fish-preview.html — блок «Варианты» (8 инлайн-копий carass синхронизированы с источником) + секция «Читаемость в UI» (44×28 / 40×26 / 240×150). Тесты не правились: 222/222 PASS, exit 0; check.mjs OK; balance.mjs — пины без изменений (Река 65.1/125.9 · Озёра 194.1/249.0 · Болото 240.3/328.9 · Море 297.3/476.7 · Океан 329.1/552.7). Скриншоты перегенерированы (45 RU + 45 EN). Доки: DEVLOG Этап 47.
2026-09-23 16:55:52 +03:00

5412 lines
527 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, viewport-fit=cover">
<meta name="theme-color" content="#0d3b66">
<meta name="apple-mobile-web-app-capable" content="yes">
<title>Рыбалка</title>
<!-- EMOJI-FONT:BEGIN — генерируется tools/emoji-font.py, не редактировать руками -->
<style>
@font-face{
font-family:'EmojiEmbedded';
font-style:normal;
font-weight:400;
font-display:block;
src:url(data:font/woff2;base64,AAEAAAAPAIAAAwBwQ09MUoW5ghYAANTEAAAw2UNQQUxvjD5lAAEFoAAAA8JHU1VCuPq49AABCWQAAAAqT1MvMkFfYDoAAAF4AAAAYGNtYXBQYvNYAAAG8AAAA5FnbHlmJIFejQAAD5wAAMOQaGVhZDGn9acAAAD8AAAANmhoZWEIwAgoAAABNAAAACRobXR4Fycd9gAAAdgAAAUYbG9jYYbmt2gAAAqEAAAFGG1heHACpgDQAAABWAAAACBuYW1lGcQzwwAA0ywAAAF2cG9zdP+2ADMAANSkAAAAIHZoZWEHMAKXAAEJkAAAACR2bXR4BOIAAAABCbQAAAUYAAEAAAADDhQgaq9sXw889QADBAAAAAAA5q5QlQAAAADm2FNFADP/BgTVA7gAAAAGAAIAAAAAAAAAAQAAA7b/BgAABPsAMwAmBNUEAAAAAAAAAAAAAAAAAAAAAAEAAQAAAosAzwAaAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAEBPsBkAAFAAACmgJmAAAATQKaAmYAAAFmADMBMwAAAAAAAAAAAAAAAAAAAAACAMCgAAAAAAAAAABOT05FAMAhlP//A7b/BgAAA7YA+gAAAAEAAAAAAgACzQAAACAACQT7ADMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJcASwE3AEoAVAQ8AIAA9QFvAeECUgK7AdIAfwBCAGIARQBZAEsChANLAScAUABPAj8BEwGEAr0DegOTAk4BmQElAtQASQKvAEkA9wBJATIBSADSAOsATQLNAsUDPANNA5sDPQORAMgA0QGkAN8A9gE5Ae4CyQNxAEYAUgHYAPcCOQNKAdkA9QItA0EBAgD9Ak4BHwEaA1oAeABkA/YAZAJyAn0BSwBJAW0AtAG6APADDQK1A0MDvQKwA9EAcQDmAUMBrgILAngCbgK0AukDIQNQAxkDpAIaAb4CQAE4AWIBEwFuAbAAQwBiAkQB+wG3AZwCGgIzAWUC2gFUAWgCFwCVAEYD5AMbAWID4wB3AUABKAGAAJ0DnwG1AbUCzgLOAKcAXgHfAogB/AH7AGcATgFrAPoBDwF2AkAC7wCaAlcBtwCaAKICCQK3A0UDoQKDA2wAPwImAjsCVAQVBC4AhgNsAUsDfQDDAP8AvgEVAU8C9gCrAGsETwI9AEsARgGsA5EAbwA+AXYBQgCsAKwCRwGSAq4CYwFlAeECggMqAtEAgQGcAh4CfAOiA9AA6AFtANMBAwC5AMAB4wHjAeMChQKVAEYB6wBvBFUCfACkAG8AjgHqANkB9wE7ANkBkwDZAUYBxwDZANkBVwHbANkBRgDZAa8A2QGhA2ICvAPlArwDtQK8A4sCvAO8A/4CvAOTArwD3QK8A1gCvAM6AjcEAAD1AVQBwgL8AcIDRQKaAbkCmgG5AcIBwgI7AYwBVAEgAOUBNQC6AJsBZwJ0AdsASgB0AIcAlwByA9wA5AQKA+sA7QD/AQQATgBwAXICUgEpAF8BqQC7AkkCSwDXAHkAhAD0AE8AbgFZAiUBFgBfAYsAsgIcAh4AywB2AbAB6gKdAp0CowDPAMYBBgEJApEBFQBLAPQAxAGiAQ8CQAJlAQ8COQJXAbQBNQE/ALMA6ACDA6sAowBLAGMAhwH4AiUCAgNsBAgDhQPNA/EEOwOxARkApACdAQ8BeAICAlsCyQMTAuICTwIkAyUDJQIqAioASwDfAiUBAAMxAzQCCQINA0wCKQDaASABDADhAhICVAJCAhICUQJXAjsCDABIAEkA2wBQAjUC8wJBAGoC6gMFAvgC3gO0AL4B1wJDAs4BvgE1AWgBawITAJICFgISAFoCKAIoAUQCJABOAVsBlgCIAMYBFwF7AewCcQL1A2YDygQgBGEAkABkAVcAwQFdAzkBVwFUATUBjgF/AX8BVAGeATQDQgMyAzIBjgD3APcBuQHPA4MB8QIvAFwD3QKSA4kCbgMDA20ESwO4A1gAUgGJAMAAhAHFAE8AxABLALwASwF8AaUCZgN1A9QDBAHhAJIAPgEoAPEBNQBLAL8ASwBlAvwDqAJtAoADzAE+AGQCeQJ5AG8CGgC4Ao4BrgKNAn4BkQJdAjAA5AJFAbwCWgJBAEYARABEAEQAdgD4AN0DNwM1AzUDZQPpA88ASABFAjQCSQI0AU0AxwDaAaUBOAKSAJQC8QDIAS0BvALxAvMC9AFwAdcAhwJlAsUDJACPArIBuwM7AzIATwEjASYBPwE6AhwBjAJaATgBbABLAAAABQAAAAMAAAAsAAAABAAAAKgAAAAF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AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA) format('woff2');
unicode-range:U+2194,U+21A9,U+23F8,U+2600,U+2692-U+2693,U+2696,U+26A0-U+26A1,U+26F5,U+2728,U+2753,U+2B06,U+2B50,U+1F300,U+1F308,U+1F30A,U+1F319,U+1F327,U+1F32B,U+1F3A3,U+1F3A8,U+1F3AD,U+1F3AF,U+1F3C5-U+1F3C6,U+1F3F9,U+1F420,U+1F446,U+1F451,U+1F4A4-U+1F4A5,U+1F4AA,U+1F4B0,U+1F4D4,U+1F4D6,U+1F4DC,U+1F4FA,U+1F504,U+1F507,U+1F50A,U+1F512,U+1F525,U+1F5B1,U+1F5D1,U+1F5FA,U+1F6A2,U+1F6D2,U+1F948,U+1F9F9,U+1FA99,U+1FA9D,U+1FAB1;
}
</style>
<!-- EMOJI-FONT:END -->
<style>
*{margin:0;padding:0;box-sizing:border-box;-webkit-tap-highlight-color:transparent;user-select:none;-webkit-user-select:none;-webkit-touch-callout:none}
html,body{width:100%;height:100%;overflow:hidden;background:#0d3b66;font-family:'EmojiEmbedded',system-ui,-apple-system,'Segoe UI',Roboto,sans-serif} /* Э28: встроенный emoji-шрифт первым — единый вид на всех платформах (генерация: tools/emoji-font.py) */
#game{position:fixed;inset:0;touch-action:none;display:block}
button{font-family:inherit;cursor:pointer}
.hidden{display:none!important}
/* ---------- HUD ---------- */
#hud{position:fixed;top:0;left:0;right:0;display:flex;justify-content:space-between;align-items:center;
padding:calc(8px + env(safe-area-inset-top)) 10px 8px;z-index:10;pointer-events:none}
/* Этап 46: под сценой аквариума HUD скрыт — кошелёк/лавка не перехватывают клики сцены */
body.aq-open #hud{display:none}
.hudleft{display:flex;gap:8px;align-items:center}
#coins,#weather{background:linear-gradient(rgba(9,32,58,.72),rgba(6,25,45,.62));padding:8px 15px;border-radius:999px;color:#ffe9a8;font-weight:700;
font-size:17px;border:1px solid rgba(255,233,168,.22);
box-shadow:0 3px 12px rgba(0,0,0,.35),inset 0 1px 0 rgba(255,255,255,.12);text-shadow:0 1px 2px rgba(0,0,0,.4)}
/* Клик по монетам открывает лавку (вкладка «Лавка») — HUD сам pointer-events:none */
#coins{pointer-events:auto;cursor:pointer;transition:filter .15s,transform .12s}
#coins:hover{filter:brightness(1.18);transform:translateY(-1px)}
#coins:active{transform:translateY(1px)}
.hudbtns{display:flex;gap:8px;pointer-events:auto}
.hudbtns button{width:46px;height:46px;font-size:21px;border-radius:14px;
border:1px solid rgba(255,255,255,.16);background:linear-gradient(rgba(9,32,58,.72),rgba(6,25,45,.62));color:#fff;
box-shadow:0 3px 10px rgba(0,0,0,.3),inset 0 1px 0 rgba(255,255,255,.1);
transition:background .15s,transform .12s,box-shadow .12s}
.hudbtns button:hover{background:rgba(30,60,95,.8);transform:translateY(-1px)}
.hudbtns button:active{background:rgba(30,60,95,.85);transform:translateY(1px);box-shadow:0 1px 4px rgba(0,0,0,.3)}
#btnRecall{position:fixed;right:12px;bottom:calc(16px + env(safe-area-inset-bottom));width:54px;height:54px;
border-radius:50%;font-size:24px;background:linear-gradient(rgba(9,32,58,.8),rgba(6,25,45,.7));color:#fff;
border:1px solid rgba(255,255,255,.22);z-index:10;
box-shadow:0 4px 14px rgba(0,0,0,.35),inset 0 1px 0 rgba(255,255,255,.12);
transition:background .15s,transform .12s}
#btnRecall:hover{background:rgba(30,60,95,.85);transform:scale(1.05)}
#btnRecall:active{background:rgba(30,60,95,.9);transform:scale(.96)}
#toast{position:fixed;left:50%;bottom:calc(92px + env(safe-area-inset-bottom));transform:translateX(-50%);
background:linear-gradient(rgba(9,32,58,.94),rgba(5,20,38,.92));color:#fff;padding:11px 20px;border-radius:14px;font-size:15px;font-weight:600;
z-index:30;opacity:0;transition:opacity .25s;pointer-events:none;white-space:normal;text-align:center;max-width:min(88vw,560px);
border:1px solid rgba(255,255,255,.18);
box-shadow:0 6px 20px rgba(0,0,0,.45),inset 0 1px 0 rgba(255,255,255,.1)}
/* ---------- Overlays ---------- */
.overlay{position:fixed;inset:0;display:flex;align-items:center;justify-content:center;
background:rgba(4,16,32,.62);backdrop-filter:blur(4px);-webkit-backdrop-filter:blur(4px);z-index:20;padding:16px}
.panel{position:relative;background:linear-gradient(165deg,#1a4d7d 0%,#123a61 55%,#0d2f4e 100%);
border:1px solid rgba(120,180,235,.35);border-radius:22px;
padding:22px;width:min(92vw,370px);max-height:86vh;overflow-y:auto;color:#eaf4ff;text-align:center;
box-shadow:0 24px 60px rgba(0,0,0,.55),0 4px 14px rgba(0,0,0,.35),inset 0 1px 0 rgba(255,255,255,.14)}
.panel::-webkit-scrollbar{width:8px}
.panel::-webkit-scrollbar-thumb{background:rgba(255,255,255,.18);border-radius:99px}
.panel::-webkit-scrollbar-track{background:transparent}
.title{font-size:34px;font-weight:800;letter-spacing:1px;margin-bottom:10px;
text-shadow:0 2px 10px rgba(0,0,0,.4),0 1px 0 rgba(255,255,255,.15)}
.panel p{font-size:14.5px;line-height:1.5;color:#bcd6ee;margin-bottom:4px}
.big{width:100%;margin-top:16px;padding:15px;font-size:19px;font-weight:800;color:#04263d;
background:linear-gradient(#ffe08a,#f5a623);border:none;border-radius:14px;
box-shadow:0 4px 0 #b97708,0 8px 18px rgba(245,166,35,.35);
transition:transform .12s,box-shadow .12s,filter .12s}
.big:hover{filter:brightness(1.07)}
.big:active{transform:translateY(2px);box-shadow:0 2px 0 #b97708,0 4px 10px rgba(245,166,35,.3)}
.panelhead{font-size:22px;font-weight:800;margin-bottom:4px;text-shadow:0 1px 6px rgba(0,0,0,.35)}
#btnCloseShop{position:absolute;top:12px;right:12px;width:36px;height:36px;border-radius:50%;border:none;
background:rgba(255,255,255,.12);color:#fff;font-size:17px;transition:background .15s,transform .12s}
#btnCloseShop:hover{background:rgba(255,255,255,.22);transform:rotate(90deg)}
#btnCloseShop:active{transform:rotate(90deg) scale(.92)}
.tabs{display:flex;gap:8px;margin:10px 0 6px}
.tabs button{flex:1;padding:11px;border-radius:12px;border:none;background:rgba(255,255,255,.1);
color:#cfe4f7;font-weight:700;font-size:15px;box-shadow:inset 0 1px 0 rgba(255,255,255,.08);
transition:background .15s,color .15s,transform .12s,box-shadow .15s}
.tabs button:hover{background:rgba(255,255,255,.17)}
.tabs button:active{transform:scale(.96)}
.tabs button.active{background:linear-gradient(#ffd76e,#f5a623);color:#04263d;
box-shadow:0 3px 12px rgba(245,166,35,.4),inset 0 1px 0 rgba(255,255,255,.35)}
.section-title{font-size:12px;letter-spacing:1.5px;color:#8fb8dd;text-transform:uppercase;margin:14px 0 8px;text-align:left}
.item{display:flex;align-items:center;justify-content:space-between;gap:10px;background:rgba(255,255,255,.06);
border:1px solid rgba(255,255,255,.09);border-radius:12px;padding:10px 12px;margin-bottom:8px;text-align:left;
transition:background .15s,border-color .15s,transform .12s}
.item:hover{background:rgba(255,255,255,.1);border-color:rgba(255,255,255,.2);transform:translateY(-1px)}
.itemname{font-weight:700;font-size:15px}
.itemdesc{font-size:12px;color:#9fc3e2;margin-top:2px;line-height:1.35}
.buybtn{min-width:96px;padding:10px 10px;border-radius:10px;border:none;font-weight:700;font-size:13px;
background:#2e6da3;color:#fff;white-space:nowrap;flex-shrink:0;
box-shadow:0 2px 6px rgba(0,0,0,.25),inset 0 1px 0 rgba(255,255,255,.15);transition:filter .12s,transform .12s,background .15s}
.buybtn:hover{filter:brightness(1.15)}
.buybtn:active{transform:scale(.96)}
.buybtn.owned{background:rgba(255,255,255,.14)}
.buybtn.owned:hover{filter:none;background:rgba(255,255,255,.22)}
.buybtn.current{background:#2ecc71;color:#04263d;box-shadow:0 2px 8px rgba(46,204,113,.4)}
.buybtn:disabled{opacity:.45;cursor:default}
.buybtn.upgbt{background:#5c55a8}
.rowbtns{display:flex;flex-direction:column;gap:6px;flex-shrink:0;max-width:48%;align-items:stretch}
.rowbtns .buybtn{min-width:0;white-space:normal}
.lvtag{color:#ffd75e;font-weight:800;font-size:12px;margin-left:5px;white-space:nowrap}
.item.locked{opacity:.5}
.item.locked:hover{background:rgba(255,255,255,.06);border-color:rgba(255,255,255,.09);transform:none}
.statsline{font-size:13px;color:#9fc3e2;margin-bottom:6px}
.jrow{display:flex;align-items:center;gap:10px;padding:9px 10px;background:rgba(255,255,255,.05);
border:1px solid rgba(255,255,255,.06);border-radius:10px;margin-bottom:6px;font-size:14px;text-align:left;
transition:background .15s,border-color .15s}
.jrow:hover{background:rgba(255,255,255,.09);border-color:rgba(255,255,255,.14)}
.jrow .je{font-size:22px;width:30px;text-align:center}
/* SVG-портрет вида в дневнике (спрайт <use href="#fish-<id>">); ❓ для не пойманных — по-прежнему эмодзи */
.jrow .je svg{width:44px;height:28px;display:block}
.jrow .je .qfish{width:24px;height:15px;display:inline-block;vertical-align:-2px} /* Э42: иконка вида в строке квеста (выше по специфичности, чем правило портрета .je svg) */
.jrow .jn{flex:1}
.jrow .jc{color:#9fc3e2;font-weight:600;font-size:13px}
/* M6: мини-счётчики вариантов в дневнике (обычная/серебряная/золотая/радужная) */
.jrow .jv{font-weight:800;font-size:11px;margin-left:5px;white-space:nowrap}
.jrow .jv-n{color:#8fb8dd}
.jrow .jv-cp{color:#d99a62}
.jrow .jv-sv{color:#dbe7f3}
.jrow .jv-qz{color:#cdbfe0}
.jrow .jv-sn{color:#ffd75e}
.jrow .jv-em{color:#2ebd6b}
.jrow .jv-dm{color:#6db8f2}
.jrow .jv-rb{color:#c56cf0}
.jrow.unknown .je,.jrow.unknown .jn{color:#5d7f9e}
.jrow .adesc{font-size:11px;color:#9fc3e2}
.jrow.locked{opacity:.5}
.jrow.got .jc{color:#2ecc71;font-weight:800;font-size:16px}
.jrow.qdone{background:rgba(46,204,113,.14)}
.jrow.qdone .jc{color:#2ecc71;font-weight:700}
.streak{display:flex;gap:6px;justify-content:center;margin:8px 0 4px}
.st-dot{width:34px;height:34px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:800;
background:rgba(255,255,255,.08);color:#5d7f9e;border:2px solid rgba(255,255,255,.12);
transition:transform .15s,box-shadow .15s}
.st-dot.on{background:linear-gradient(#ffd76e,#f5a623);color:#04263d;border-color:#ffd75e}
.st-dot.cur{box-shadow:0 0 12px rgba(255,215,94,.85);transform:scale(1.12)}
#card .bigemoji{font-size:74px;margin:4px 0 2px;display:block;animation:bob 1.2s ease-in-out infinite;
filter:drop-shadow(0 6px 10px rgba(0,0,0,.4))}
/* SVG-портрет улова в карточке (спрайт <use href="#fish-<id>">, showCard ставит href у #cardFishUse) */
#card .bigemoji svg{width:240px;height:150px;display:block;margin:0 auto}
@keyframes bob{0%,100%{transform:translateY(0)}50%{transform:translateY(-9px)}}
#card .rarity{display:inline-block;font-weight:800;font-size:12px;letter-spacing:1.5px;text-transform:uppercase;
padding:5px 14px;border-radius:999px;background:rgba(255,255,255,.08);border:1px solid rgba(255,255,255,.15)}
#card .cname{font-size:24px;font-weight:800;margin:6px 0 6px;text-shadow:0 1px 6px rgba(0,0,0,.4)}
#card .cval{font-size:20px;font-weight:800;color:#ffe9a8;margin-bottom:6px;text-shadow:0 1px 4px rgba(0,0,0,.3)}
#card .csub{font-size:13px;color:#9fc3e2;margin-bottom:4px}
.record{display:inline-block;background:linear-gradient(#ffd76e,#f5a623);color:#04263d;font-weight:800;font-size:14px;letter-spacing:1px;padding:4px 14px;border-radius:999px;animation:recpulse .8s ease-in-out infinite;box-shadow:0 0 14px rgba(255,215,94,.5)}
@keyframes recpulse{0%,100%{transform:scale(1)}50%{transform:scale(1.09)}}
/* M6: бейдж варианта и оформление карточки (silver/gold/rainbow; normal — без оформления) */
.variant-badge{display:inline-block;font-weight:800;font-size:14px;letter-spacing:1px;padding:4px 14px;border-radius:999px;margin-left:8px;
border:1px solid #fff;animation:recpulse .8s ease-in-out infinite}
#card.silver-card .variant-badge{background:linear-gradient(#f7fafd,#c3d4e6);color:#2f4d6d;border-color:#dbe7f3;box-shadow:0 0 14px rgba(200,220,240,.8)}
#card.gold-card .variant-badge{background:linear-gradient(#fff6c9,#ffd75e);color:#6b4a00;border-color:#ffd75e;box-shadow:0 0 14px rgba(255,215,94,.75)}
#card.rainbow-card .variant-badge{background:linear-gradient(#f3ddff,#c56cf0);color:#4b1a70;border-color:#e0b3ff;box-shadow:0 0 14px rgba(197,108,240,.8)}
#card.copper-card .variant-badge{background:linear-gradient(#fbe9d7,#d99a62);color:#5b3a1e;border-color:#e8b98a;box-shadow:0 0 14px rgba(217,154,98,.7)}
#card.quartz-card .variant-badge{background:linear-gradient(#f6f1fa,#cdbfe0);color:#463355;border-color:#e3d7f0;box-shadow:0 0 14px rgba(205,191,224,.8)}
#card.emerald-card .variant-badge{background:linear-gradient(#d8f7e3,#2ebd6b);color:#063d1f;border-color:#7ee2a8;box-shadow:0 0 14px rgba(46,189,107,.8)}
#card.diamond-card .variant-badge{background:linear-gradient(#e8f6ff,#6db8f2);color:#0a3a66;border-color:#a8d8ff;box-shadow:0 0 14px rgba(109,184,242,.85)}
#card.silver-card .panel{border-color:#c3d4e6;box-shadow:0 0 34px rgba(200,220,240,.45),0 10px 40px rgba(0,0,0,.5)}
#card.silver-card .bigemoji{filter:grayscale(.85) brightness(1.25) drop-shadow(0 0 12px rgba(210,228,245,.9))}
#card.gold-card .panel{border-color:#ffd75e;box-shadow:0 0 34px rgba(255,215,94,.5),0 10px 40px rgba(0,0,0,.5)}
#card.gold-card .bigemoji{filter:drop-shadow(0 0 12px rgba(255,215,94,.9))}
#card.rainbow-card .panel{border-color:#c56cf0;box-shadow:0 0 34px rgba(197,108,240,.5),0 10px 40px rgba(0,0,0,.5)}
#card.rainbow-card .bigemoji{animation:bob 1.2s ease-in-out infinite,rainbowhue 2.4s linear infinite}
@keyframes rainbowhue{from{filter:hue-rotate(0deg) drop-shadow(0 0 12px rgba(255,120,220,.8))}to{filter:hue-rotate(360deg) drop-shadow(0 0 12px rgba(120,220,255,.8))}}
#card.copper-card .panel{border-color:#d99a62;box-shadow:0 0 34px rgba(217,154,98,.45),0 10px 40px rgba(0,0,0,.5)}
#card.copper-card .bigemoji{filter:drop-shadow(0 0 12px rgba(217,154,98,.9))}
#card.quartz-card .panel{border-color:#cdbfe0;box-shadow:0 0 34px rgba(205,191,224,.5),0 10px 40px rgba(0,0,0,.5)}
#card.quartz-card .bigemoji{filter:drop-shadow(0 0 12px rgba(205,191,224,.9))}
#card.emerald-card .panel{border-color:#2ebd6b;box-shadow:0 0 34px rgba(46,189,107,.5),0 10px 40px rgba(0,0,0,.5)}
#card.emerald-card .bigemoji{filter:drop-shadow(0 0 12px rgba(46,189,107,.9))}
#card.diamond-card .panel{border-color:#6db8f2;box-shadow:0 0 34px rgba(109,184,242,.5),0 10px 40px rgba(0,0,0,.5)}
#card.diamond-card .bigemoji{filter:drop-shadow(0 0 12px rgba(109,184,242,.95))}
.boss-badge{display:inline-block;background:linear-gradient(#fff6c9,#ffd75e);color:#6b4a00;font-weight:800;font-size:14px;letter-spacing:1px;padding:4px 14px;border-radius:999px;margin-left:8px;
border:1px solid #ffd75e;box-shadow:0 0 14px rgba(255,215,94,.75);animation:recpulse .8s ease-in-out infinite}
#card.boss-card .panel{border-color:#ffd75e;box-shadow:0 0 34px rgba(255,215,94,.55),0 10px 40px rgba(0,0,0,.5)}
#card.boss-card .bigemoji{filter:drop-shadow(0 0 12px rgba(255,215,94,.95))}
/* Фаза свечения «Болота»: светящийся вид в normal-варианте — цветной drop-shadow по --glow
(цвет ставит showCard; класс только для normal, чтобы не спорить с фильтрами вариантов) */
#card.glow-card .bigemoji{filter:drop-shadow(0 0 16px var(--glow,#5ff2ff)) drop-shadow(0 6px 10px rgba(0,0,0,.4))}
/* Перекраска SVG-портрета под вариант: --f1 (тело) / --f3 (плавники) — переменные наследуются
сквозь <use> в спрайт; silver/rainbow закрываются filter-правилами выше, boss — тоже */
#card.copper-card .bigemoji{--f1:hsl(25,55%,55%);--f3:hsl(25,50%,35%)}
#card.gold-card .bigemoji{--f1:#ffd75e;--f3:hsl(45,70%,40%)}
#card.quartz-card .bigemoji{--f1:hsl(270,25%,72%);--f3:hsl(270,25%,45%)}
#card.emerald-card .bigemoji{--f1:hsl(150,55%,42%);--f3:hsl(150,50%,28%)}
#card.diamond-card .bigemoji{--f1:hsl(200,60%,78%);--f3:hsl(200,50%,45%)}
#card{animation:pop .3s ease}
@keyframes pop{from{transform:scale(.75);opacity:0}to{transform:scale(1);opacity:1}}
/* Y2: rewarded «монеты ×2» (карточка улова) — тёмно-синяя в духе карточки,
янтарная обводка «читается» как бонус; простой текстовый button (треб. 1.16 —
НЕ имитация рекламного блока платформы) */
.rvbtn{width:100%;min-height:44px;margin-top:10px;padding:11px 12px;font-size:15px;font-weight:800;color:#ffe9a8;
background:linear-gradient(#14406b,#0b2a49);border:1.5px solid #ffd75e;border-radius:12px;
box-shadow:0 0 12px rgba(255,215,94,.22),inset 0 1px 0 rgba(255,255,255,.08);
transition:transform .12s,box-shadow .12s,filter .12s}
.rvbtn:hover{filter:brightness(1.18);box-shadow:0 0 16px rgba(255,215,94,.4),inset 0 1px 0 rgba(255,255,255,.1)}
.rvbtn:active{transform:scale(.97)}
.rvbtn:disabled{opacity:.55;cursor:default;filter:none;transform:none}
/* Этап 46: «В аквариум» на карточке улова — по образцу .rvbtn, бирюзовая «морская» гамма */
.aqbtn{width:100%;min-height:44px;margin-top:10px;padding:11px 12px;font-size:15px;font-weight:800;color:#c8fff4;
background:linear-gradient(#0f5f6b,#083f49);border:1.5px solid #57e0c8;border-radius:12px;
box-shadow:0 0 12px rgba(87,224,200,.22),inset 0 1px 0 rgba(255,255,255,.08);
transition:transform .12s,box-shadow .12s,filter .12s}
.aqbtn:hover{filter:brightness(1.18);box-shadow:0 0 16px rgba(87,224,200,.4),inset 0 1px 0 rgba(255,255,255,.1)}
.aqbtn:active{transform:scale(.97)}
.aqbtn:disabled{opacity:.55;cursor:default;filter:none;transform:none}
/* Этап 46: бар аквариума (#aqBar) и поповер выбранной рыбы (#aqPop) — DOM поверх canvas-сцены */
#aqBar{position:fixed;top:calc(8px + env(safe-area-inset-top));left:10px;right:10px;z-index:26;
display:flex;align-items:center;gap:8px;pointer-events:none}
/* Бар сам клики не ловит (бокс на всю ширину) — кликабельны только кнопки-пилюли внутри */
#aqBar .aqpill{pointer-events:auto}
.aqpill{background:linear-gradient(rgba(9,32,58,.8),rgba(6,25,45,.7));color:#eaf4ff;font-weight:700;font-size:15px;
padding:9px 14px;border-radius:999px;border:1px solid rgba(87,224,200,.35);white-space:nowrap;
box-shadow:0 3px 12px rgba(0,0,0,.35),inset 0 1px 0 rgba(255,255,255,.1);transition:filter .15s,transform .12s}
.aqpill:hover{filter:brightness(1.18);transform:translateY(-1px)}
.aqpill:active{transform:translateY(1px)}
.aqpill:disabled{opacity:.5;cursor:default;filter:none;transform:none}
#aqCount{margin-left:auto;color:#c8fff4;font-weight:800;font-size:15px;padding:9px 14px;border-radius:999px;
background:linear-gradient(rgba(9,32,58,.8),rgba(6,25,45,.7));border:1px solid rgba(255,255,255,.18);
box-shadow:0 3px 12px rgba(0,0,0,.35),inset 0 1px 0 rgba(255,255,255,.1)}
#aqPop{position:fixed;left:50%;transform:translateX(-50%);bottom:calc(18px + env(safe-area-inset-bottom));z-index:26;
background:linear-gradient(rgba(9,32,58,.95),rgba(5,20,38,.93));border:1px solid rgba(87,224,200,.45);border-radius:16px;
padding:12px 16px 14px;color:#eaf4ff;text-align:center;min-width:210px;max-width:86vw;
box-shadow:0 12px 34px rgba(0,0,0,.55),inset 0 1px 0 rgba(255,255,255,.1)}
#aqPopName{font-size:17px;font-weight:800}
#aqPopSub{font-size:12px;color:#9fc3e2;margin:4px 0 10px}
/* Ревизия: жильцы банки — те же SVG-портреты, что в карточке улова. Слой поверх canvas (вода/
стекло/ауры рисуются в drawAquarium), но под баром/поповером (#aqBar/#aqPop, z-index 26).
Вне сцены выключен (body.aq-open); клики не перехватывает (pointer-events:none). */
#aqFishLayer{position:fixed;inset:0;z-index:5;pointer-events:none;display:none;overflow:hidden}
body.aq-open #aqFishLayer{display:block}
#aqFishLayer .aqfish{position:absolute;left:0;top:0;will-change:transform}
#aqFishLayer .aqfish svg{width:100%;height:100%;display:block;overflow:visible}
/* Вариант — те же правила, что у карточки улова (#card.<variant>-card .bigemoji):
перекраска --f1/--f3 идёт inline (наследуется сквозь <use>), фильтры — классами */
#aqFishLayer .aqfish.varcopper{filter:drop-shadow(0 0 12px rgba(217,154,98,.9))}
#aqFishLayer .aqfish.varsilver{filter:grayscale(.85) brightness(1.25) drop-shadow(0 0 12px rgba(210,228,245,.9))}
#aqFishLayer .aqfish.vargold{filter:drop-shadow(0 0 12px rgba(255,215,94,.9))}
#aqFishLayer .aqfish.varquartz{filter:drop-shadow(0 0 12px rgba(205,191,224,.9))}
#aqFishLayer .aqfish.varemerald{filter:drop-shadow(0 0 12px rgba(46,189,107,.9))}
#aqFishLayer .aqfish.vardiamond{filter:drop-shadow(0 0 12px rgba(109,184,242,.95))}
#aqFishLayer .aqfish.varrainbow{animation:aqrainbowhue 2.4s linear infinite}
@keyframes aqrainbowhue{
from{filter:hue-rotate(0deg) drop-shadow(0 0 12px rgba(255,120,220,.8))}
to{filter:hue-rotate(360deg) drop-shadow(0 0 12px rgba(120,220,255,.8))}
}
.twobtns{display:flex;gap:10px;margin-top:16px}
.twobtns .big{margin-top:0;width:auto;flex:1}
/* Кнопки диалога «Меню» (#gamemenu): тёмные пилюли в духе HUD-кнопок */
.mbtns{display:flex;flex-direction:column;gap:10px;margin-top:16px}
.mbtn{width:100%;padding:13px 16px;font-size:16px;font-weight:700;color:#eaf4ff;text-align:left;
background:linear-gradient(rgba(9,32,58,.85),rgba(6,25,45,.72));border:1px solid rgba(255,255,255,.18);border-radius:12px;
box-shadow:inset 0 1px 0 rgba(255,255,255,.1);transition:background .15s,transform .12s}
.mbtn:hover{background:rgba(30,60,95,.9);transform:translateY(-1px)}
.mbtn:active{background:rgba(30,60,95,.95);transform:translateY(1px)}
.big.danger{background:linear-gradient(#ff8a7a,#e74c3c);box-shadow:0 4px 0 #96281b,0 8px 18px rgba(231,76,60,.35);color:#fff}
.big.danger:hover{filter:brightness(1.08)}
.big.danger:active{box-shadow:0 2px 0 #96281b,0 4px 10px rgba(231,76,60,.3)}
/* ---------- Адаптив: узкие и низкие экраны ---------- */
@media (max-width:420px){
.title{font-size:27px}
.panel{padding:16px;border-radius:18px}
.panelhead{font-size:19px}
.panel p{font-size:13.5px}
.big{padding:13px;font-size:17px;border-radius:12px}
#card .bigemoji{font-size:58px}
#card .bigemoji svg{width:188px;height:118px}
#card .cname{font-size:21px}
.hudbtns button{width:42px;height:42px;font-size:19px;border-radius:12px}
#coins,#weather{font-size:15px;padding:7px 12px}
.tabs button{padding:10px 6px;font-size:13.5px}
.jrow .je{font-size:20px;width:26px}
.jrow .je svg{width:40px;height:26px}
}
@media (max-height:620px){
.panel{max-height:92vh;padding:14px 16px}
.title{font-size:24px;margin-bottom:6px}
.panel p{font-size:13px;line-height:1.4}
#card .bigemoji{font-size:50px;margin:2px 0 0}
#card .bigemoji svg{width:162px;height:101.2px}
.big{margin-top:10px;padding:11px;font-size:16px}
.tabs button{padding:8px}
}
</style>
</head>
<body>
<!-- FISH-SVG:BEGIN (генерируется tools/embed-fish.mjs — не править руками) -->
<svg id="fishSprites" width="0" height="0" style="position:absolute" aria-hidden="true">
<symbol id="fish-carass" viewBox="0 0 160 100">
<!-- хвост: слабая вилка, закруглённые лопасти (стебель толстый, 14 ед.) -->
<path fill="var(--f3,hsl(46,42%,33%))" d="M42 44 L13 33 C21 41 25 46 30 51 C25 56 21 61 13 69 L42 58 Z"/>
<!-- спинной плавник: ДЛИННЫЙ, кромка полого-выпуклая (пик чуть ближе к хвосту), основание глубоко утоплено в тело (нахлёст ≥4 ед., щели нет) -->
<path fill="var(--f3,hsl(46,42%,33%))" d="M62 37 C64 23 72 13 84 12 C98 11 114 20 126 34 Z"/>
<!-- лучи спинного плавника: 5 тонких штрихов веером от основания к кромке (передние короче, задние длиннее) -->
<path fill="none" stroke="var(--f4,hsl(50,35%,22%))" stroke-width="0.9" opacity="0.3" d="M68 36.7 C67.6 31.8 67.8 26.5 68 21.5"/>
<path fill="none" stroke="var(--f4,hsl(50,35%,22%))" stroke-width="0.9" opacity="0.3" d="M79 36.2 C78.7 29.5 78.9 20.5 79 13.6"/>
<path fill="none" stroke="var(--f4,hsl(50,35%,22%))" stroke-width="0.9" opacity="0.3" d="M90 35.7 C89.8 28 89.8 19.5 89.8 12.8"/>
<path fill="none" stroke="var(--f4,hsl(50,35%,22%))" stroke-width="0.9" opacity="0.3" d="M101 35.2 C101.2 28.5 101.1 21.5 101 15.9"/>
<path fill="none" stroke="var(--f4,hsl(50,35%,22%))" stroke-width="0.9" opacity="0.3" d="M112 34.7 C112.3 30 112.1 25.5 112 21.9"/>
<!-- анальный плавник: округлый, ШИРОКИМ основанием растёт из брюха, а не висит каплей -->
<path fill="var(--f3,hsl(46,42%,33%))" d="M54 62 C59 81 65 89 72 89 C79 88 84 81 88 69 L54 62 Z"/>
<!-- лучи анального плавника: 3 коротких тёмных штриха на лопасти -->
<path fill="none" stroke="var(--f4,hsl(50,35%,22%))" stroke-width="1" opacity="0.3" d="M63 72 C63.6 77 64.4 80.5 65 83"/>
<path fill="none" stroke="var(--f4,hsl(50,35%,22%))" stroke-width="1" opacity="0.3" d="M70 75 C70.6 80 71.4 84 72.5 87"/>
<path fill="none" stroke="var(--f4,hsl(50,35%,22%))" stroke-width="1" opacity="0.3" d="M78 76 C78.5 79 79 81.5 79.3 83.5"/>
<!-- брюшные плавники: пара мягких округлых лопастей, направлены назад-вниз (без острых углов) -->
<path fill="var(--f3,hsl(46,42%,33%))" d="M109 73 C103 85 92 82 100 71 Z"/>
<path fill="var(--f3,hsl(46,42%,33%))" d="M118 73 C113 85 104 82 109 72 Z"/>
<!-- тело: высокое и округлое, спина горбатая, голова тупая (длина/глубина ≈0.51) -->
<path fill="var(--f1,hsl(48,45%,48%))" d="M148 50 C144 41 138 34 126 30 C116 26 106 24 96 24 C74 25 53 33 42 44 L42 58 C53 71 76 79 100 79 C120 79 137 70 142 57 C145 53 147 51 148 50 Z"/>
<!-- брюхо: светлая нижняя треть -->
<path fill="var(--f2,hsl(48,32%,72%))" d="M42 58 C53 71 76 79 100 79 C120 79 137 70 142 57 C136 66 118 72 100 72 C78 72 56 66 42 58 Z"/>
<!-- спинная кромка: тонкая тёмная полоса по верхнему контуру (не зубцы) -->
<path fill="var(--f4,hsl(50,35%,22%))" d="M148 50 C144 41 138 34 126 30 C116 26 106 24 96 24 C74 25 53 33 42 44 C54 37 76 30 96 27.5 C108 28 118 33 127 37.5 C136 42 143 47 148 50 Z"/>
<!-- жаберная пластина: мягкая светлая заливка (объём маленькой головы) -->
<path fill="var(--f2,hsl(48,32%,72%))" opacity="0.35" d="M132 39 C138 46 139 54 134 62 C129 54 127 46 127 40 Z"/>
<!-- жаберная дуга: тёмный серп у головы -->
<path fill="none" stroke="var(--f4,hsl(50,35%,22%))" stroke-width="1.5" d="M132 39 C138 46 139 54 134 62"/>
<!-- ГЛАВНЫЙ знак вида: тёмное пятно у самого основания хвостового плавника (не «второй глаз») -->
<ellipse fill="#2b2416" cx="44.5" cy="50" rx="3.2" ry="4"/>
<!-- чешуя: 3 широких серпа на плече (крупная чешуя, а не решётка) -->
<path fill="var(--f2,hsl(48,32%,72%))" opacity="0.3" d="M104 41 Q97 50 104 59 Q101 50 104 41 Z"/>
<path fill="var(--f2,hsl(48,32%,72%))" opacity="0.3" d="M114 40 Q106 50 114 60 Q111 50 114 40 Z"/>
<path fill="var(--f2,hsl(48,32%,72%))" opacity="0.3" d="M124 43 Q117 50 124 57 Q121 50 124 43 Z"/>
<!-- рот: крошечная щель на тупом рыле (усов нет — это карп!) -->
<path fill="var(--f4,hsl(50,35%,22%))" d="M143 49 C146 49.4 148 50.2 148.8 51.4 C147 52.6 145 52 143.4 50.6 Z"/>
<!-- грудной плавник: мягкая округлая лопасть на боку под жаберной дугой, направлена назад-вниз (в стиле брюшных) -->
<path fill="var(--f3,hsl(46,42%,33%))" d="M133 54 C126 57 116 61 118 66 C120 71 128 64 132 58 Z"/>
<!-- глаз: ободок → склера → радужка → зрачок → блик -->
<circle fill="var(--f4,hsl(50,35%,22%))" cx="137.5" cy="41.5" r="5.7"/>
<circle fill="#f7f3e6" cx="137.5" cy="41.5" r="4.6"/>
<circle fill="#c98a2a" cx="137.5" cy="41.5" r="3.2"/>
<circle fill="#142638" cx="137.5" cy="41.5" r="2.3"/>
<circle fill="#fff" cx="136" cy="40" r="0.9"/>
</symbol>
<symbol id="fish-perch" viewBox="0 0 160 100">
<!-- хвост: слабо выемчатый (неглубокая вырезка), корень утоплен в стебель толщ.14 (нахлёст 4 ед.) -->
<path fill="var(--f3,hsl(105,40%,30%))" d="M44 43 C36 39.5 26 34 14 29 C18 36 21.5 41.5 24 46 L24 54 C21.5 58.5 18 64 14 71 C26 66 36 60.5 44 57 Z"/>
<!-- рыжий низ хвоста (фикс-акцент): красная только НИЖНЯЯ лопасть, верх остаётся f3 -->
<path fill="#c0392b" d="M44 56.5 L24.5 52.5 C21.5 58.5 18 64 14 71 C26 66 36 60.5 44 57 Z"/>
<!-- лучи хвоста: по одному штриху в каждой лопасти -->
<path fill="none" stroke="var(--f4,hsl(110,45%,20%))" stroke-width="0.9" opacity="0.3" d="M40 44 C33 41 25 37 18 33 M40 56 C33 59 25 63 18 67"/>
<!-- D1 передний спинной (КОЛЮЧИЙ): 6 острых шипов, зубцы до y≈20, основание глубоко в теле (нахлёст ≥4 ед.) -->
<path fill="var(--f3,hsl(105,40%,30%))" d="M59.5 36 L61 33 L62 21 L64.5 33 L66 20 L68.5 33 L70 19 L72.5 33 L74 20 L76.5 33 L78 20.5 L80.5 33 L82 22 L84.5 33.5 L85.5 36 Z"/>
<!-- D2 задний спинной (МЯГКИЙ): отдельный округлый плавник на горбе (x90..112), НЕ слит с колючим -->
<path fill="var(--f3,hsl(105,40%,30%))" d="M88 32 C89 26.5 93 23 99 22.8 C105 22.8 110 25.5 112.5 29 L114.5 32 Z"/>
<!-- лучи D2: три коротких веерных штриха ВНУТРИ мягкого плавника (не выходят за кромку) -->
<path fill="none" stroke="var(--f4,hsl(110,45%,20%))" stroke-width="0.9" opacity="0.3" d="M92 31 C92.5 28 93.3 25.8 94.2 24.2 M99 31 C99.2 28 99.6 25.8 100 24 M106 31 C106.3 28.2 106.8 26.2 107.6 24.8"/>
<!-- анальный плавник: КРАСНЫЙ (фикс-акцент), основание глубоко в брюхе (нахлёст ≥4), кончик до y≈84 -->
<path fill="#c0392b" d="M50 59 C52 73 55.5 81 60.5 84 C65.5 81 68.5 74 69 60 Z"/>
<!-- лучи анального плавника: короткие штрихи ВНУТРИ лопасти (за кромку не выходят) -->
<path fill="none" stroke="var(--f4,hsl(110,45%,20%))" stroke-width="0.9" opacity="0.3" d="M54.5 71 C55 74.5 55.7 76.8 56.5 78.2 M60 72 C60.4 74.8 60.9 76.8 61.6 78"/>
<!-- брюшные плавники: ПАРА красных (фикс-акцент) лопастей, направлены вниз-назад, кончики до y≈88 -->
<path fill="#c0392b" d="M99 67 C97.5 77 99 84 103.5 88 C107 82.5 107.5 73 106 67 Z"/>
<path fill="#c0392b" d="M107.5 67 C106.5 77.5 108.5 84.5 113 88 C116 82 116.5 73 115 68 Z"/>
<!-- тело: высокое и сжатое, спина встаёт от мелкой головы к ГОРБУ (пик ≈x94) и падает к стеблю -->
<path fill="var(--f1,hsl(110,35%,42%))" d="M150 50 C146 42 142 37.5 137 36 C132 33.5 125 30 117 27 C108 24.3 100 23.2 94 23.2 C87 23.4 78 25 70 27.5 C62 30 50 36 40 43 L40 57 C50 64 62 70 74 72.6 C84 74.6 92 75 100 74.6 C118 73.6 134 67 142.5 58.5 C145.5 54.5 149 52 150 50 Z"/>
<!-- брюхо: светлая нижняя треть -->
<path fill="var(--f2,hsl(95,25%,68%))" d="M40 57 C50 64 62 70 74 72.6 C84 74.6 92 75 100 74.6 C118 73.6 134 67 142.5 58.5 C132 66 114 70.5 98 70.5 C75 70.5 54 64.5 40 57 Z"/>
<!-- жаберная пластина: мягкая светлая заливка за глазом (объём мелкой головы) -->
<path fill="var(--f2,hsl(95,25%,68%))" opacity="0.3" d="M120 38 C124 44 124 52 120 60 C116 52 115 44 116 39 Z"/>
<!-- 6 тёмных вертикальных полос одним compound-path: шире сверху (4.5), уже снизу (2.5), верх утоплен под спинную кромку, низ до y≈70 -->
<path fill="var(--f4,hsl(110,45%,20%))" opacity="0.5" d="M53.75 35.2 L58.25 35.2 L57.25 68 L54.75 68 Z M67.75 28.9 L72.25 28.9 L71.25 70 L68.75 70 Z M81.75 25.2 L86.25 25.2 L85.25 70 L82.75 70 Z M95.75 24.1 L100.25 24.1 L99.25 70 L96.75 70 Z M109.75 26.8 L114.25 26.8 L113.25 70 L110.75 70 Z M121.75 31.4 L126.25 31.4 L125.25 70 L122.75 70 Z"/>
<!-- спинная кромка: тонкая тёмная полоса по верхнему контуру (ложится ПОВЕРХ полос — их верх срезан, не шипы) -->
<path fill="var(--f4,hsl(110,45%,20%))" d="M150 50 C146 42 142 37.5 137 36 C132 33.5 125 30 117 27 C108 24.3 100 23.2 94 23.2 C87 23.4 78 25 70 27.5 C62 30 50 36 40 43 C50 38 62 33.5 70 31 C78 28.6 87 27 94 27 C100 27 108 28.4 117 30.6 C125 32.6 132 35.6 137 38.4 C142 41.2 147 46.5 150 50 Z"/>
<!-- жаберная дуга: тёмный серп у крышки (ниже и левее глаза, ободок не задет) -->
<path fill="none" stroke="var(--f4,hsl(110,45%,20%))" stroke-width="1.5" d="M120 41 C124 46 123.5 54 119.5 60"/>
<!-- тёмное пятно на жаберной крышке (видовой знак окуня) -->
<ellipse fill="var(--f4,hsl(110,45%,20%))" opacity="0.5" cx="123" cy="50" rx="2.6" ry="3.4"/>
<!-- рот: короткая конечная щель на тупом рыле -->
<path fill="var(--f4,hsl(110,45%,20%))" d="M143.5 48.6 C146.5 49 149 49.8 150.3 51.2 C148.6 52.6 146 51.8 143.8 50.2 Z"/>
<!-- грудной плавник: на боку под жаберной дугой (ПОСЛЕ тела), кончиком вниз-назад -->
<path fill="var(--f3,hsl(105,40%,30%))" d="M136 54 C132 57 126.5 62 123.5 67 C126.5 67.5 130.5 64 133.5 60 C135.5 57 136.3 55.5 136 54 Z"/>
<!-- глаз: КРУПНЫЙ (ободок → склера → радужка → зрачок → блик) -->
<circle fill="var(--f4,hsl(110,45%,20%))" cx="132" cy="43" r="5.6"/>
<circle fill="#f7f3e6" cx="132" cy="43" r="4.7"/>
<circle fill="#c98a2a" cx="132" cy="43" r="3.3"/>
<circle fill="#142638" cx="132" cy="43" r="2.3"/>
<circle fill="#fff" cx="130.8" cy="41.8" r="0.9"/>
</symbol>
<symbol id="fish-bream" viewBox="0 0 160 100">
<!-- хвост: глубокая вилка; светлая кромка, чтобы лопасти не сливались с тенью -->
<path fill="var(--f3,hsl(210,28%,36%))" stroke="var(--f2,hsl(205,24%,78%))" stroke-width="1" stroke-opacity="0.5" d="M50 46 L12 28 C22 40 26 46 30 50 C26 54 22 60 12 72 L50 54 Z"/>
<!-- спинной плавник: короткий и высокий (антипод длинного анального) -->
<path fill="var(--f3,hsl(210,28%,36%))" d="M74 24 C78 10 84 3 90 3 C97 3 103 9 107 23 L74 25 Z"/>
<!-- анальный плавник: главный признак — длинная «юбка» вдоль задней половины брюха, тёмная обводка вогнутой наружной кромки -->
<path fill="var(--f3,hsl(210,28%,36%))" stroke="var(--f4,hsl(28,30%,23%))" stroke-width="1" stroke-opacity="0.55" d="M58 61 C47 69 41 81 46 94 C63 86 82 84 99 91 C103 89 103 85 100 80 C84 74 68 67 58 61 Z"/>
<!-- лучи анального плавника: веер от основания к кромке (передние длиннее) -->
<path fill="none" stroke="var(--f4,hsl(28,30%,23%))" stroke-width="0.8" opacity="0.33" d="M60 62 L47 92 M69 66 L57 90 M79 70 L70 87 M89 74 L84 86 M97 78 L97 89"/>
<!-- брюшные плавники: пара мягких уплощённых лопастей без острых концов -->
<path fill="var(--f3,hsl(210,28%,36%))" d="M106 79 C100 83 101 90 107 90 C112 90 115 84 114 80 Z"/>
<path fill="var(--f3,hsl(210,28%,36%))" d="M119 81 C113 85 114 92 120 92 C125 92 128 86 127 82 Z"/>
<!-- тело: высокий ромб с остриём на спине и очень тонким стеблем (длина/глубина ≈0.65) -->
<path fill="var(--f1,hsl(208,30%,52%))" d="M150 53 C146 45 141 38 127 31 C118 24 106 17 94 17 C74 17 56 27 46 47 L46 53 C56 73 78 85 104 85 C126 85 142 74 146 62 C148 58 149 55 150 53 Z"/>
<!-- брюхо: серебристая нижняя треть -->
<path fill="var(--f2,hsl(205,24%,78%))" d="M46 53 C56 73 78 85 104 85 C126 85 142 74 146 62 C138 72 120 78 102 78 C76 78 58 68 46 53 Z"/>
<!-- спинная кромка: толстая тёмно-бронзовая полоса от затылка до стебля -->
<path fill="var(--f4,hsl(28,30%,23%))" d="M134 34 C126 26 112 19 94 17 C76 18 58 27 46 47 C59 31 77 23 94 23 C111 23 125 29 135 38 Z"/>
<!-- жаберная пластина: мягкая светлая заливка -->
<path fill="var(--f2,hsl(205,24%,78%))" opacity="0.3" d="M131 37 C137 44 138 54 133 64 C127 54 124 44 125 38 Z"/>
<!-- жаберная дуга (сдвинута влево, чтобы не сливаться с ободком глаза) -->
<path fill="none" stroke="var(--f4,hsl(28,30%,23%))" stroke-width="1.5" d="M131 37 C137 44 138 54 133 64"/>
<!-- чешуя: мелкие бледные полумесяцы в два ряда по средней части бока -->
<path fill="var(--f4,hsl(28,30%,23%))" opacity="0.15" d="M75 34 Q81 39 75 44 Q77 39 75 34 Z"/>
<path fill="var(--f4,hsl(28,30%,23%))" opacity="0.15" d="M91 32 Q97 37 91 42 Q93 37 91 32 Z"/>
<path fill="var(--f4,hsl(28,30%,23%))" opacity="0.15" d="M107 35 Q113 40 107 45 Q109 40 107 35 Z"/>
<path fill="var(--f4,hsl(28,30%,23%))" opacity="0.15" d="M69 48 Q75 53 69 58 Q71 53 69 48 Z"/>
<path fill="var(--f4,hsl(28,30%,23%))" opacity="0.15" d="M87 46 Q93 51 87 56 Q89 51 87 46 Z"/>
<path fill="var(--f4,hsl(28,30%,23%))" opacity="0.15" d="M105 50 Q111 55 105 60 Q107 55 105 50 Z"/>
<!-- рот: крошечная приподнятая щель (рот слегка вверх) -->
<path fill="var(--f4,hsl(28,30%,23%))" d="M144 49.5 C147 49.8 149 50.6 150 52 C148.4 53 146.2 52.4 144.8 51 Z"/>
<!-- грудной плавник: мелкий, низко на теле -->
<path fill="var(--f3,hsl(210,28%,36%))" d="M130 58 L113 73 L133 62 Z"/>
<!-- глаз: МАЛЕНЬКИЙ и низко у рыла; узкая склера, радужка/зрачок доминируют -->
<circle fill="var(--f4,hsl(28,30%,23%))" cx="138" cy="45" r="4.5"/>
<circle fill="#f4f1e6" cx="138" cy="45" r="2.9"/>
<circle fill="#c8b06a" cx="138" cy="45" r="2.3"/>
<circle fill="#142638" cx="138" cy="45" r="1.5"/>
<circle fill="#fff" cx="137" cy="44" r="0.6"/>
</symbol>
<symbol id="fish-carp" viewBox="0 0 160 100">
<!-- хвост: умеренная вилка, лопасти симметричны относительно y=50 (верх 32 / низ 68); база утоплена в стебель (нахлёст ≥4 ед.) -->
<path fill="var(--f3,hsl(30,50%,32%))" d="M40 44 L12 32 C20 40 25 45 30 50 C25 55 20 60 12 68 L40 56 Z"/>
<!-- спинной плавник: ДЛИННАЯ база (x70..119), высокий передний луч (86,15), задняя кромка ВОГНУТА (садится ниже хорды, не выпуклая, как у карася) -->
<path fill="var(--f3,hsl(30,50%,32%))" d="M70 30 C74 20 79 15 86 15 C95 22 107 25 119 28 L119 30 Z"/>
<!-- лучи спинного: 5 тонких штрихов веером от основания к кромке (передние короче) -->
<path fill="none" stroke="var(--f4,hsl(28,45%,20%))" stroke-width="0.9" opacity="0.3" d="M74 29 L76 21 M81 29 L83 17.5 M89 29 L91 19 M97 29 L99 22.3 M106 29 L108 25"/>
<!-- анальный плавник: широкая мягкая лопасть у самого хвоста (x46..62), база утоплена в брюхо -->
<path fill="var(--f3,hsl(30,50%,32%))" d="M46 60 C47 74 51 82 57 82.5 C63 82 66 76 62 68 Z"/>
<!-- лучи анального: 3 тёмных штриха на лопасти -->
<path fill="none" stroke="var(--f4,hsl(28,45%,20%))" stroke-width="1" opacity="0.3" d="M50 66 L52 78 M55 68 L57 80 M60 70 L60.5 80"/>
<!-- брюшные плавники: ДВЕ отдельные мягкие округлые лопасти (x94..113 на брюхе, кончики ~y87), назад-вниз, без острых углов -->
<path fill="var(--f3,hsl(30,50%,32%))" d="M94 71 C91 78 91 84 96 87 C99 84 101 78 102 71 Z"/>
<path fill="var(--f3,hsl(30,50%,32%))" d="M104 71 C102 78 102 84 107 87 C110 84 112 78 113 71 Z"/>
<!-- тело: вытянуто-мощное (глубина/длина ≈0.44), горб (88,24), низ брюха (96,78), тупое рыло (150,51), стебель 12 ед. -->
<path fill="var(--f1,hsl(36,52%,46%))" d="M150 49 C147 43 142 39 136 37 C124 29 104 25 88 24 C68 24 48 30 34 44 L34 56 C48 70 68 78 96 78 C124 78 142 66 150 53 C150.6 51.5 150.6 50.5 150 49 Z"/>
<!-- брюхо: светлая (f2) нижняя треть -->
<path fill="var(--f2,hsl(42,45%,74%))" d="M34 56 C48 70 68 78 96 78 C124 78 142 66 150 53 C142 64 126 71 104 72 C78 73 54 67 34 56 Z"/>
<!-- спинная кромка: тонкая тёмная полоса по верхнему контуру (не зубцы) -->
<path fill="var(--f4,hsl(28,45%,20%))" d="M150 49 C147 43 142 39 136 37 C124 29 104 25 88 24 C68 24 48 30 34 44 C46 34 66 29 88 28 C104 28 120 32 130 38 C140 44 146 47 150 49 Z"/>
<!-- жаберная пластина: мягкая светлая заливка (объём крупной головы) -->
<path fill="var(--f2,hsl(42,45%,74%))" opacity="0.35" d="M124 38 C130 45 131 55 126 63 C121 55 119.5 46 120 39 Z"/>
<!-- жаберная дуга: тёмный серп у головы (сдвинут влево, чтобы не липнуть к глазу) -->
<path fill="none" stroke="var(--f4,hsl(28,45%,20%))" stroke-width="1.5" d="M124 38 C130 45 131 55 126 63"/>
<!-- чешуя (признак породы): 6 широких f2-серпов в два ряда — верхний x76/92/108, нижний x72/88/106 -->
<path fill="var(--f2,hsl(42,45%,74%))" opacity="0.33" d="M76 34 Q68 40 76 46 Q73 40 76 34 Z"/>
<path fill="var(--f2,hsl(42,45%,74%))" opacity="0.33" d="M92 32 Q84 38 92 44 Q89 38 92 32 Z"/>
<path fill="var(--f2,hsl(42,45%,74%))" opacity="0.33" d="M108 36 Q100 42 108 48 Q105 42 108 36 Z"/>
<path fill="var(--f2,hsl(42,45%,74%))" opacity="0.33" d="M72 46 Q64 52 72 58 Q69 52 72 46 Z"/>
<path fill="var(--f2,hsl(42,45%,74%))" opacity="0.33" d="M88 44 Q80 50 88 56 Q85 50 88 44 Z"/>
<path fill="var(--f2,hsl(42,45%,74%))" opacity="0.33" d="M106 48 Q98 54 106 60 Q103 54 106 48 Z"/>
<!-- грудной плавник: мягкая лопасть на боку под жаберной дугой, ПОСЛЕ тела, направлена назад-вниз -->
<path fill="var(--f3,hsl(30,50%,32%))" d="M136 54 C130 58 123 63 124 67 C125 70 131 64 136 57 Z"/>
<!-- рот ПОЛУНИЖНИЙ: узкие тёмные губы на нижней стороне рыла (не конечный-верхний, как у карася) -->
<path fill="var(--f4,hsl(28,45%,20%))" d="M149.6 51.6 C148.2 54.2 146 55.6 144 55.4 C145.2 53.6 146.8 52.2 148.4 51.2 Z"/>
<!-- УСЫ (главный различитель с карасём, только f4, stroke-width 1.8): верхние длинные ~14 ед. — поверх грудного плавника -->
<path fill="none" stroke="var(--f4,hsl(28,45%,20%))" stroke-width="1.8" stroke-linecap="round" d="M146 52 L132 60 M144 52 L134 63"/>
<!-- нижние усы короткие ~7 ед., ниже и круче верхних -->
<path fill="none" stroke="var(--f4,hsl(28,45%,20%))" stroke-width="1.8" stroke-linecap="round" d="M145 55 L137 58 M145 56 L138 60"/>
<!-- глаз последним: ободок f4 → склера → радужка #c98a2a → зрачок → блик -->
<circle fill="var(--f4,hsl(28,45%,20%))" cx="133" cy="42" r="5"/>
<circle fill="#f4f1e6" cx="133" cy="42" r="4.1"/>
<circle fill="#c98a2a" cx="133" cy="42" r="3"/>
<circle fill="#142638" cx="133" cy="42" r="2.1"/>
<circle fill="#fff" cx="131.5" cy="40.5" r="0.8"/>
</symbol>
<symbol id="fish-pike" viewBox="0 0 160 100">
<!-- хвост: слабо выемчатый — лопасти чуть дальше центра; корень утоплен в стебель (нахлёст 4 ед.) -->
<path fill="var(--f3,hsl(100,35%,28%))" d="M32 45 C26 41 20 37 12 34 C15 41 17 46 17 50 C17 54 15 59 12 66 C20 63 26 59 32 55 Z"/>
<!-- спинной плавник: СДВИНУТ К ХВОСТУ, основание глубоко в теле (≥4 ед.), вершина округлая -->
<path fill="var(--f3,hsl(100,35%,28%))" d="M40 47 C41.5 35 46.5 29.5 52 29.5 C57.5 29.5 61 35 62 47 L40 47 Z"/>
<!-- анальный плавник: стоит НАПРОТИВ спинного, тем же сдвигом к хвосту -->
<path fill="var(--f3,hsl(100,35%,28%))" d="M42 55 C44.5 63 48.5 68.5 53 68.5 C57.5 68.5 60.5 63 62 55 L42 55 Z"/>
<!-- брюшные плавники: пара мелких лопастей, основания утоплены в брюхо -->
<path fill="var(--f3,hsl(100,35%,28%))" d="M64 56 C62 62 63 67 67 67.5 C70 66 71 61 70 56 Z"/>
<path fill="var(--f3,hsl(100,35%,28%))" d="M74 56 C73 63 75 68 79 68 C82 66 82 61 81 56 Z"/>
<!-- тело: торпеда ~4:1, спина почти прямая; верх головы плоский (150,42)→(130,38)→(116,40), верхняя челюсть (152,44), выдвинутая НИЖНЯЯ (153,46.5) -->
<path fill="var(--f1,hsl(95,30%,38%))" d="M152 44 L150 42 C142 39.5 136 38.2 130 38 L116 40 C100 35.5 86 35 72 36 C52 38 36 41.5 28 45 L28 55 C38 60 52 65 70 68 C98 67.5 128 60 146 50.5 L153 46.5 Z"/>
<!-- брюхо: светлая полоса вдоль брюшной кромки -->
<path fill="var(--f2,hsl(85,35%,72%))" d="M28 55 C38 60 52 65 70 68 C98 67.5 128 60 146 50.5 L153 46.5 C140 52 120 57.5 100 59.5 C76 61.5 48 59 28 55 Z"/>
<!-- спинная кромка: тонкая тёмная полоса по верхнему контуру (не зубцы) -->
<path fill="var(--f4,hsl(95,40%,18%))" d="M152 44 L150 42 C142 39.5 136 38.2 130 38 L116 40 C100 35.5 86 35 72 36 C52 38 36 41.5 28 45 L28 46.8 C37 43.2 53 39.8 72 38 C88 36.4 102 37.6 116 42.2 L130 40.3 L150 44.3 Z"/>
<!-- жаберная пластина: мягкая светлая заливка (объём головы), отодвинута от ободка глаза -->
<path fill="var(--f2,hsl(85,35%,72%))" opacity="0.3" d="M116 41 C120 46 120 51 116.5 56 C112.5 51 112.5 46 113.5 41.5 Z"/>
<!-- жаберная дуга: тёмный серп у затылка -->
<path fill="none" stroke="var(--f4,hsl(95,40%,18%))" stroke-width="1.5" d="M116 41 C120 46 120 51 116.5 56"/>
<!-- слабые тёмные вертикали по боку: 4 размытые полосы камуфляжа -->
<path fill="none" stroke="var(--f4,hsl(95,40%,18%))" stroke-width="3.4" stroke-linecap="round" opacity="0.3" d="M50 42 L50 58 M66 40 L66 61 M82 39.5 L82 61 M98 40.5 L98 60"/>
<!-- ГЛАВНЫЙ узор вида: 7-8 светлых овалов-пятен в тёмном поле одним compound-path (f2 светлые — читаются в любом варианте) -->
<path fill="var(--f2,hsl(85,35%,72%))" opacity="0.55" d="M115.03 50.52 A5 2.6 -6 1 0 124.97 49.48 A5 2.6 -6 1 0 115.03 50.52 Z M96.53 47.58 A5.5 2.6 -6 1 0 107.47 46.42 A5.5 2.6 -6 1 0 96.53 47.58 Z M81.03 49.52 A5 2.8 -6 1 0 90.97 48.48 A5 2.8 -6 1 0 81.03 49.52 Z M64.53 46.58 A5.5 2.5 -6 1 0 75.47 45.42 A5.5 2.5 -6 1 0 64.53 46.58 Z M49.03 50.52 A5 2.7 -6 1 0 58.97 49.48 A5 2.7 -6 1 0 49.03 50.52 Z M37.82 54.44 A4.2 2.2 -6 1 0 46.18 53.56 A4.2 2.2 -6 1 0 37.82 54.44 Z M57.53 56.47 A4.5 2.3 -6 1 0 66.47 55.53 A4.5 2.3 -6 1 0 57.53 56.47 Z M75.53 57.47 A4.5 2.2 -6 1 0 84.47 56.53 A4.5 2.2 -6 1 0 75.53 57.47 Z"/>
<!-- ротовая щель: длинная, от конца рыла НАЗАД ПОД глаз (не на конце рыла) -->
<path fill="var(--f4,hsl(95,40%,18%))" d="M151.5 44.4 C139 44.2 126 44.1 114 44.2 C126 46 139 46.8 151.5 46.5 Z"/>
<!-- грудной плавник: на боку у брюха, позади жаберной дуги, кончиком вниз-назад (ПОСЛЕ тела) -->
<path fill="var(--f3,hsl(100,35%,28%))" d="M124 50 C122.5 55 119 59.5 114 60.5 C115 55 118 50.5 122 47.5 Z"/>
<!-- глаз: крупный, жёлтая радужка (ободок → склера → радужка → зрачок → блик) -->
<circle fill="var(--f4,hsl(95,40%,18%))" cx="130" cy="42" r="4.6"/>
<circle fill="#f7f3e6" cx="130" cy="42" r="3.7"/>
<circle fill="#d9b23a" cx="130" cy="42" r="2.8"/>
<circle fill="#142638" cx="130" cy="42" r="2"/>
<circle fill="#fff" cx="128.9" cy="40.8" r="0.8"/>
</symbol>
<symbol id="fish-catfish" viewBox="0 0 160 100">
<!-- хвост: округлый «веер» (НЕ вилка), уменьшен ~на 23%, симметричен относительно y=50, основанием заходит в стебель -->
<path fill="var(--f3,hsl(35,35%,28%))" d="M30 43.1 C22.3 39.2 16.1 41.5 14.2 50 C16.1 58.5 22.3 60.8 30 56.9 Z"/>
<!-- спинной плавник: КРОШЕЧНЫЙ, основание утоплено в спину (нахлёст ≥4 ед.) -->
<path fill="var(--f3,hsl(35,35%,28%))" d="M89 44 C90 29.5 94 24.5 97.5 24.5 C101.5 24.5 104 30 105 44 Z"/>
<!-- анальный плавник: ДЛИННЫЙ, тянется вдоль задней половины брюха (антипод крошечного спинного) -->
<path fill="var(--f3,hsl(35,35%,28%))" d="M36 55 C34 64 41 71 53 71 C64 71 69 65 71 58 Z"/>
<!-- анальный плавник: тонкая тёмная обводка по передней кромке — отделяет от тела -->
<path fill="none" stroke="var(--f4,hsl(30,35%,16%))" stroke-width="1" opacity="0.55" d="M36 55 C34 64 41 71 53 71"/>
<!-- анальный плавник: 3 бледных луча f4 внутри лопасти -->
<path fill="none" stroke="var(--f4,hsl(30,35%,16%))" stroke-width="1" opacity="0.3" d="M41 59 L43.5 70.2"/>
<path fill="none" stroke="var(--f4,hsl(30,35%,16%))" stroke-width="1" opacity="0.3" d="M48 63.5 L50.5 70.7"/>
<path fill="none" stroke="var(--f4,hsl(30,35%,16%))" stroke-width="1" opacity="0.3" d="M56 66.5 L58 70.5"/>
<!-- брюшной плавник 1: мягкая маленькая лопасть -->
<path fill="var(--f3,hsl(35,35%,28%))" d="M75 62 C73.5 68 76 72.5 80.5 70.5 C83 68.5 82 64 81 61 Z"/>
<!-- брюшной плавник 2: пара к первой, чуть сзади -->
<path fill="var(--f3,hsl(35,35%,28%))" d="M84 62.5 C82.5 68.5 85 73 89.5 70.5 C92 68 90.5 64 89.5 61.5 Z"/>
<!-- верхний ус 1: ОЧЕНЬ длинный (≈45 ед.), ложится вдоль брюха почти до брюшных плавников -->
<path fill="none" stroke="var(--f4,hsl(30,35%,16%))" stroke-width="2" stroke-linecap="round" d="M147 53 C130 58 116 64 104 70"/>
<!-- верхний ус 2: пара к первому, чуть ниже -->
<path fill="none" stroke="var(--f4,hsl(30,35%,16%))" stroke-width="2" stroke-linecap="round" d="M145 54 C132 60 120 66 110 73"/>
<!-- нижний ус 1: короткий, уходит назад-вниз -->
<path fill="none" stroke="var(--f4,hsl(30,35%,16%))" stroke-width="2" stroke-linecap="round" d="M144 57 C138 60 130 63 124 67"/>
<!-- нижний ус 2: пара к короткому -->
<path fill="none" stroke="var(--f4,hsl(30,35%,16%))" stroke-width="2" stroke-linecap="round" d="M144 58 C140 61 133 65 128 70"/>
<!-- тело: массивная тупая голова ≈¼ длины с КРУТЫМ лбом-ГОРБОМ (пик 132,27, выше прежнего 31), седло за головой 114,36.5, суженный стебель 11 ед. -->
<path fill="var(--f1,hsl(40,30%,38%))" d="M150 52 C149 43 143.5 30 132 27 C126 26.8 119 29.5 114 36.5 C104 38.8 84 40.2 64 41.8 C50 43 34 44.5 24 45 L24 56 C40 61 62 70 86 70 C102 70 118 61.5 132 57 C139 54.5 147 53 150 52 Z"/>
<!-- брюхо: светлая нижняя полоса вдоль всего корпуса -->
<path fill="var(--f2,hsl(38,30%,68%))" d="M24 56 C40 61 62 70 86 70 C102 70 118 61.5 132 57 C139 54.5 147 53 150 52 C145 51.5 141 52.5 136 54 C129 56 122 58 114 59.5 C104 61.5 96 63.5 86 65 C64 64 42 58.5 24 56 Z"/>
<!-- спинная кромка: тонкая тёмная полоса по верхнему контуру, повторяет новый лоб-горб (не зубцы) -->
<path fill="var(--f4,hsl(30,35%,16%))" d="M150 52 C149 43 143.5 30 132 27 C126 26.8 119 29.5 114 36.5 C104 38.8 84 40.2 64 41.8 C50 43 34 44.5 24 45 C34 46.6 52 48.4 64 46.4 C84 44.4 104 41.8 114 39.5 C123 30 130 29 137 35 C143.5 41.5 148 48 150 52 Z"/>
<!-- жаберная пластина: мягкая светлая заливка (за головой, не липнет к глазу) -->
<path fill="var(--f2,hsl(38,30%,68%))" opacity="0.3" d="M119 36 C124 44 123 53 119 60 C115 53 114 44 114 37 Z"/>
<!-- жаберная дуга: тёмный серп у основания головы -->
<path fill="none" stroke="var(--f4,hsl(30,35%,16%))" stroke-width="1.5" d="M119 36 C124 44 123 53 119 60"/>
<!-- голое тело: блёклая f4-клякса 1 (чешуи у сома нет) -->
<path fill="var(--f4,hsl(30,35%,16%))" opacity="0.14" d="M60 43 C66 41 72 44 70.5 48 C69 52 61 51.5 58.5 48.5 C56.5 45.5 57.5 44 60 43 Z"/>
<!-- блёклая клякса 2 -->
<path fill="var(--f4,hsl(30,35%,16%))" opacity="0.12" d="M86 44 C91 42 96 45 94.5 49 C93 53 86 52 84 49 C82.5 46.5 83.5 45 86 44 Z"/>
<!-- блёклая клякса 3 -->
<path fill="var(--f4,hsl(30,35%,16%))" opacity="0.15" d="M46 50 C50 48.5 54 51 52.5 54.5 C51 57.5 45 57 43.5 54 C42.5 51.5 43.5 50.5 46 50 Z"/>
<!-- блёклая клякса 4 -->
<path fill="var(--f4,hsl(30,35%,16%))" opacity="0.13" d="M104 46 C107.5 44.5 110.5 47 109.5 50 C108.5 52.5 103 52 102 49.5 C101.5 47.5 102 46.5 104 46 Z"/>
<!-- губа: УЗКАЯ светлая кромка снизу пасти (нижняя челюсть) -->
<path fill="var(--f2,hsl(38,30%,68%))" d="M151 57.6 C144 60.6 133 61 124 58 C133 62 145 61.8 151.6 59 Z"/>
<!-- пасть: ЗАМЕТНАЯ тёмная полоса нутра высотой ~3.6 ед., раскрыта назад-вниз от (151,54) до (124,58) — не «улыбка» -->
<path fill="var(--f4,hsl(30,35%,16%))" d="M151 54 C144 55.6 133 57.2 124 58 C133 61 144 60.6 151 57.6 Z"/>
<!-- грудной плавник: мягкая лопасть на боку под жаберной дугой (рисуется ПОСЛЕ тела) -->
<path fill="var(--f3,hsl(35,35%,28%))" d="M133 53 C128 55 121 59.5 121.5 64.5 C122 69 128 62.5 132.5 57.5 Z"/>
<!-- глаз: НАМЕРЕННО крошечный (антипод окуня), высоко и вперёд; ободок → склера → тусклая радужка → зрачок → блик -->
<circle fill="var(--f4,hsl(30,35%,16%))" cx="135" cy="41" r="3.6"/>
<circle fill="#f4f1e6" cx="135" cy="41" r="2.7"/>
<circle fill="#b3a468" cx="135" cy="41" r="1.9"/>
<circle fill="#142638" cx="135" cy="41" r="1.3"/>
<circle fill="#fff" cx="134.2" cy="40.2" r="0.5"/>
</symbol>
<symbol id="fish-sturge" viewBox="0 0 160 100">
<!-- хвост: гетероцеркальный — верхняя лопасть длинная заострённая к (8,20), нижняя короткая округлая к (14,63) -->
<path fill="var(--f3,hsl(200,20%,30%))" d="M36 43 L8 20 C13 33 15 45 13 54 C19 57 27 57 36 56 Z M36 55.5 C27 56.5 18 58.5 14 62.5 C19 64.5 28 62.5 36 59.5 Z"/>
<!-- спинной плавник (D): маленький, сдвинут к хвосту, основание утоплено в тело (нахлёст ≥4 ед.) -->
<path fill="var(--f3,hsl(200,20%,30%))" d="M46 46 C49 36 55 30.5 61 30 C62.5 35 63 40 63 46 Z"/>
<!-- анальный плавник (A): маленький, сдвинут к хвосту, растёт широким основанием из брюха -->
<path fill="var(--f3,hsl(200,20%,30%))" d="M46 57.5 C48 65 53 70 58 70 C59.5 66 59.5 61 58.5 57.5 Z"/>
<!-- брюшные плавники: пара мягких округлых лопастей назад-вниз -->
<path fill="var(--f3,hsl(200,20%,30%))" d="M88 60 C84 67 80 70 81 72 C85 70 88 66 90 61 Z"/>
<path fill="var(--f3,hsl(200,20%,30%))" d="M80 60 C76 67 72 70 73 72 C77 70 80 66 82 61 Z"/>
<!-- усики: 4 тонких СУЖАЮЩИХСЯ к концу волокна-бахрома, начало спрятано под ртом, свисают вниз ПОЧТИ ВЕРТИКАЛЬНО (лёгкий наклон назад), разной длины — бахрома, не «пальцы» -->
<path fill="var(--f4,hsl(200,20%,18%))" d="M144.71 53 C144.81 55.78 144.66 55.78 144.37 58.56 C144.76 55.78 145.29 55.78 145.39 53 Z M145.51 53.15 C145.61 56.15 145.67 56.15 145.59 59.14 C145.77 56.15 146.09 56.15 146.19 53.15 Z M146.26 53.15 C146.36 56.1 146.68 56.1 146.86 59.04 C146.78 56.1 146.84 56.1 146.94 53.15 Z M147.01 53 C147.11 55.68 147.63 55.68 148.01 58.36 C147.73 55.68 147.59 55.68 147.69 53 Z"/>
<!-- рот: рисуется ДО тела — верх уходит под контур рыла (нахлёст ≥2, шва нет); видна лишь компактная СКРУГЛЁННАЯ снизу нижняя присоска (ширина ≈6.2, видимая высота ≈4.5), нижний край y≈53.4 — трубка вдвое меньше прежней, не «башмак» -->
<path fill="var(--f4,hsl(200,20%,18%))" d="M143.4 45 C143 47.8 143.2 50.8 144 52.2 C144.6 53.1 145.4 53.4 146.5 53.4 C147.6 53.4 148.4 53.1 149 52.2 C149.8 50.8 150 47.8 149.6 45 Z"/>
<!-- ротовое отверстие: маленькая тёмная щель по центру нижнего торца трубки -->
<path fill="#0d1417" d="M145.8 52.6 C146.3 53.05 146.9 53.05 147.4 52.65 C146.9 52.25 146.3 52.25 145.8 52.6 Z"/>
<!-- тело: веретеновидное (глубина/длина ≈0.26), спина горбатая (110,35), брюхо низкое (90,65), коническое рыло с чуть притуплённым кончиком (154,46.5..48.5), плавное сужение к тонкому стеблю (~11 ед.) в зоне x32..44 (без обрубка) -->
<path fill="var(--f1,hsl(200,18%,40%))" d="M154 47 C149 40.5 140 36.5 128 36 C118 35 108 34.8 100 35 C80 35.5 55 38.5 36 44 Q31.5 45.8 31.5 49.75 Q31.5 53.7 36 55.5 C55 61.5 80 64.5 100 65 C112 64 122 59 130 52 C139 50 149 48.8 154 47 Z"/>
<!-- брюхо: светлая полоса вдоль подводной кромки -->
<path fill="var(--f2,hsl(200,15%,72%))" d="M36 55.5 C55 61.5 80 64.5 100 65 C112 64 122 59 130 52 C124 53.5 110 57.5 100 58.5 C78 57 52 54 34.5 52 Z"/>
<!-- жаберная пластина: мягкая светлая заливка за глазом -->
<path fill="var(--f2,hsl(200,15%,72%))" opacity="0.35" d="M122 39 C127 45 128 53 122 59 C118 53 117 45 117 40 Z"/>
<!-- жаберная дуга: тёмный серп у основания головы -->
<path fill="none" stroke="var(--f4,hsl(200,20%,18%))" stroke-width="1.5" d="M122 39 C127 45 128 53 122 59"/>
<!-- ЖУЧКИ, спинной ряд: 8 мягких бугорков вдоль спины от x53.8 до x126.2 (основание утоплено в тело, высота 2.55–2.95), куполообразные и наклонены назад (вершина сдвинута к хвосту на ≈0.45) — бугорки на коже, а не пила -->
<path fill="var(--f4,hsl(200,20%,18%))" d="M53.8 40.86 C56.19 37.46 59.01 37.46 60.2 40.86 Z M63.3 39.38 C65.69 35.65 68.51 35.65 69.7 39.38 Z M72.8 38.22 C75.19 34.35 78.01 34.35 79.2 38.22 Z M82.3 37.34 C84.69 33.67 87.51 33.67 88.7 37.34 Z M91.8 36.77 C94.19 32.84 97.01 32.84 98.2 36.77 Z M101.3 36.53 C103.69 32.73 106.51 32.73 107.7 36.53 Z M110.8 36.67 C113.19 33.07 116.01 33.07 117.2 36.67 Z M119.8 37.16 C122.19 33.69 125.01 33.69 126.2 37.16 Z"/>
<!-- ЖУЧКИ, боковой ряд: 5 ромбиков 5×7 по боковой линии -->
<path fill="var(--f4,hsl(200,20%,18%))" d="M52 45.5 L54.5 49 L52 52.5 L49.5 49 Z M68 45 L70.5 48.5 L68 52 L65.5 48.5 Z M84 45 L86.5 48.5 L84 52 L81.5 48.5 Z M100 45 L102.5 48.5 L100 52 L97.5 48.5 Z M116 45 L118.5 48.5 L116 52 L113.5 48.5 Z"/>
<!-- ЖУЧКИ, брюшной ряд: 4 косых штриха под брюхом -->
<path fill="none" stroke="var(--f4,hsl(200,20%,18%))" stroke-width="1.2" d="M62 60 L58 64 M78 62 L74 66 M94 63.5 L90 67 M110 63.5 L106 67"/>
<!-- блики: 5 коротких светлых серпов по верху тела -->
<path fill="var(--f2,hsl(200,15%,72%))" opacity="0.35" d="M64 41 Q59 45 64 49 Q62 45 64 41 Z M80 39 Q75 43 80 47 Q78 43 80 39 Z M96 38 Q91 42 96 46 Q94 42 96 38 Z M112 39 Q107 43 112 47 Q110 43 112 39 Z M120 42 Q115 46 120 50 Q118 46 120 42 Z"/>
<!-- грудной плавник: уменьшен (≈⅔ прежнего), сидит на боку под жаберной дугой, направлен назад-вниз -->
<path fill="var(--f3,hsl(200,20%,30%))" d="M127 50.5 C122 52.5 117.5 56.5 117 60.5 C116.8 64.5 120 63 123 59.5 C126 56 128.8 52.5 129.5 51.5 Z"/>
<!-- глаз: ободок → склера → радужка → зрачок → блик (последним) -->
<circle fill="var(--f4,hsl(200,20%,18%))" cx="130" cy="41" r="3.5"/>
<circle fill="#f4f1e6" cx="130" cy="41" r="2.7"/>
<circle fill="#6f7566" cx="130" cy="41" r="1.9"/>
<circle fill="#142638" cx="130" cy="41" r="1.3"/>
<circle fill="#fff" cx="129" cy="40" r="0.5"/>
</symbol>
<symbol id="fish-gold" viewBox="0 0 160 100">
<!-- хвост: верхняя вуалевая лопасть (уходит вверх-влево, кромка текучая) -->
<path fill="var(--f3,hsl(32,80%,45%))" d="M80 45 C68 34 48 22 30 15 C20 11 15 11 13 12 C14 19 20 27 30 36 C42 46 60 50 80 45 Z"/>
<!-- хвост: нижняя вуалевая лопасть (расходится с верхней, выемка между ними) -->
<path fill="var(--f3,hsl(32,80%,45%))" d="M80 55 C68 66 48 78 30 85 C20 89 15 89 13 88 C14 81 20 73 30 64 C42 54 60 50 80 55 Z"/>
<!-- складка верхней лопасти: мягкий луч по центру (не параллелен кромке) -->
<path fill="none" stroke="#ffd98a" stroke-width="1" opacity="0.22" d="M74 43 C60 36 46 28 34 21"/>
<!-- складка нижней лопасти -->
<path fill="none" stroke="#ffd98a" stroke-width="1" opacity="0.22" d="M74 57 C60 64 46 72 34 79"/>
<!-- спинной плавник: высокий, длинная волнистая задняя кромка -->
<path fill="var(--f3,hsl(32,80%,45%))" d="M76 34 C81 16 92 4 104 3 C114 2 122 8 126 17 C129 24 132 29 134 34 C118 32 96 31 76 34 Z"/>
<!-- лучи спинного плавника -->
<path fill="none" stroke="var(--f4,hsl(14,55%,30%))" stroke-width="0.8" opacity="0.35" d="M88 24 L92 8"/>
<path fill="none" stroke="var(--f4,hsl(14,55%,30%))" stroke-width="0.8" opacity="0.35" d="M101 23 L103 4"/>
<path fill="none" stroke="var(--f4,hsl(14,55%,30%))" stroke-width="0.8" opacity="0.35" d="M114 24 L119 12"/>
<!-- анальный плавник: цельная ниспадающая вуаль с плавной кромкой -->
<path fill="var(--f3,hsl(32,80%,45%))" d="M110 74 C106 84 98 92 88 96 C82 98 76 98.5 72 98 C77 91 80 83 81 67 C90 70 100 71.5 110 74 Z"/>
<!-- лучи анальной вуали -->
<path fill="none" stroke="var(--f4,hsl(14,55%,30%))" stroke-width="0.8" opacity="0.35" d="M100 79 C94 85 87 90 80 94"/>
<path fill="none" stroke="var(--f4,hsl(14,55%,30%))" stroke-width="0.8" opacity="0.35" d="M92 78 C87 83 82 87 77 91"/>
<!-- брюшные плавники: пара мягких вуалей с округлыми концами (без острых щупалец) -->
<path fill="var(--f3,hsl(32,80%,45%))" d="M131 70 C134 79 132 89 125 95 C120 98 115 96 114 92 C117 86 119 78 119 70 C123 70.5 127 70.5 131 70 Z"/>
<path fill="var(--f3,hsl(32,80%,45%))" d="M123 71 C126 79 125 87 120 92 C117 95 113 94 112 90 C114 84 115 78 115 71 C118 71 120 71 123 71 Z"/>
<!-- тело: короткое яйцевидное, гладкие дуги спины и брюха (голова мелкая заострённая) -->
<path fill="var(--f1,hsl(36,84%,53%))" d="M149 50 C147 42 142 34 134 29 C125 23.5 113 21 101 22 C86 23 73 31 67 43 C65.5 46.5 65.5 53.5 67 57 C73 69 86 77 101 78 C113 79 125 76.5 134 71 C142 66 147 58 149 50 Z"/>
<!-- брюхо: кремовая нижняя дуга -->
<path fill="var(--f2,hsl(45,72%,80%))" d="M67 57 C73 69 86 77 101 78 C113 79 125 76.5 134 71 C126 72 114 71 102 70 C87 68 74 64 67 57 Z"/>
<!-- спинная кромка: тонкая тёмная полоса по верхнему контуру -->
<path fill="var(--f4,hsl(14,55%,30%))" d="M149 50 C147 42 142 34 134 29 C125 23.5 113 21 101 22 C86 23 73 31 67 43 C75 33 90 26 103 25 C115 24.5 127 28 135 33 C142 38 147 44 149 50 Z"/>
<!-- жаберная пластина: мягкая светлая заливка (сдвинута влево, чтобы не липла к глазу) -->
<path fill="var(--f2,hsl(45,72%,80%))" opacity="0.3" d="M119 34 C123.5 42 124 54 119.5 65 C115.5 54 114.5 44 115.5 35 Z"/>
<!-- жаберная дуга: чистый зазор ≥4.5 ед. от ободка глаза -->
<path fill="none" stroke="var(--f4,hsl(14,55%,30%))" stroke-width="1.5" d="M119 34 C123.5 42 124 54 119.5 65"/>
<!-- чешуя: 3 широких металлических серпа на боку -->
<path fill="var(--f2,hsl(45,72%,80%))" opacity="0.3" d="M108 33 Q98 50 108 67 Q103 50 108 33 Z"/>
<path fill="var(--f2,hsl(45,72%,80%))" opacity="0.3" d="M118 32 Q108 50 118 68 Q113 50 118 32 Z"/>
<path fill="var(--f2,hsl(45,72%,80%))" opacity="0.3" d="M128 34 Q118 50 128 66 Q123 50 128 34 Z"/>
<!-- металлические искры (фикс-акцент) -->
<circle fill="#fff3c4" cx="96" cy="31" r="1.8"/>
<circle fill="#fff3c4" cx="116" cy="52" r="1.5"/>
<!-- рот: крошечная щель на заострённом рыле (усов нет) -->
<path fill="var(--f4,hsl(14,55%,30%))" d="M145 49 C147.5 49.3 149 50 149.7 51 C148 52.2 146 51.4 145 50.2 Z"/>
<!-- грудной плавник: небольшой мягкий овал на боку у брюха, под жаберной дугой, кончиком заходит за брюшную кромку -->
<path fill="var(--f3,hsl(32,80%,45%))" opacity="0.55" d="M130.5 57.5 C127.5 62 121.5 69.5 115 81 C119.5 82 124 76 127.2 68.5 C129.3 63.5 130.7 60 130.5 57.5 Z"/>
<!-- лучи грудного плавника -->
<path fill="none" stroke="var(--f4,hsl(14,55%,30%))" stroke-width="0.8" opacity="0.35" d="M127 61 C123.5 66.5 119.5 73 116.5 78"/>
<path fill="none" stroke="var(--f4,hsl(14,55%,30%))" stroke-width="0.8" opacity="0.35" d="M129 64 C126 68 122 73.5 118.5 78.5"/>
<!-- глаз: САМЫЙ КРУПНЫЙ из трёх (тёмный ободок → узкий серп склеры → крупная радужка → зрачок → блик) -->
<circle fill="var(--f4,hsl(14,55%,30%))" cx="135" cy="41.5" r="7.5"/>
<circle fill="#fff8e8" cx="135" cy="41.5" r="5.4"/>
<circle fill="#e08a1e" cx="135" cy="41.5" r="4.9"/>
<circle fill="#142638" cx="135" cy="41.5" r="3"/>
<circle fill="#fff" cx="132.8" cy="39.2" r="1.3"/>
</symbol>
<symbol id="fish-zander" viewBox="0 0 160 100">
<!-- хвост: слабо вильчатый, корень утоплен в стебель толщ.12 (нахлёст 4 ед.) -->
<path fill="var(--f3,hsl(168,22%,36%))" d="M48 43.5 C40 40.5 29 35.5 12 31 C16 38.5 18.5 44 19.5 50 C18.5 56 16 61.5 12 69 C29 64.5 40 59.5 48 56.5 Z"/>
<!-- D1 передний спинной: ГЛАДКАЯ низкая лопасть, кромка спокойная с 4 МЕЛКИМИ вогнутыми выемками (без шипов и гребёнки — не путать с окунем), основание глубоко в спине (нахлёст ≥4) -->
<path fill="var(--f3,hsl(168,22%,36%))" d="M58 45 C59 36.5 61 29.8 65.5 27.4 Q67.35 31 69.2 29.6 Q71 33.4 72.8 32.2 Q74.65 36.5 76.5 35.8 Q78.75 41.6 81 42.5 Z"/>
<!-- D2 задний спинной: отдельный МЯГКИЙ плавник, чуть выше переднего, между ними зазор (81..86) -->
<path fill="var(--f3,hsl(168,22%,36%))" d="M86 40.5 C87 31 91 24.8 97 24.2 C103 24.2 106.5 30 108 38.5 Z"/>
<!-- анальный плавник: мягкий, основание вдоль брюха (нахлёст ≥4), низ до y≈79 -->
<path fill="var(--f3,hsl(168,22%,36%))" d="M67 58.5 C69 68 73 76.5 78 79 C82.5 77 85 69 85 62.5 Z"/>
<!-- брюшные плавники: пара мягких лопастей, основания утоплены в брюхо (нахлёст ≥4) -->
<path fill="var(--f3,hsl(168,22%,36%))" d="M91 63.5 C90 73 91.5 81.5 95 85.5 C98 81.5 99 73 98.5 63.5 Z M103 64 C102.5 73.5 104 82 107.5 86 C110.5 82 111.5 73.5 111 64 Z"/>
<!-- тело: низкое веретено ~3:1, спина почти ровная (100,33)→затылок (131,38), стебель толщ.11; рыло (151,49), нижняя челюсть чуть вперёд (152.5,51.3) -->
<path fill="var(--f1,hsl(165,18%,47%))" d="M150.5 48.8 C146 43 139.5 39.2 131 38 C120.5 35.8 110.5 33.5 100 33 C79 33.6 58 37.6 44 44.5 L44 55.5 C58 62.4 79 66.4 100 69 C123 70.6 143.5 60.5 149 53.5 L152.5 51.3 Z"/>
<!-- брюхо: светлая нижняя часть -->
<path fill="var(--f2,hsl(160,18%,72%))" d="M44 55.5 C58 62.4 79 66.4 100 69 C123 70.6 143.5 60.5 149 53.5 C138 59 120 64.5 100 65.5 C76 66.8 57 62 44 55.5 Z"/>
<!-- спинная кромка: тонкая тёмная полоса по ровному верхнему контуру (не зубцы) -->
<path fill="var(--f4,hsl(170,25%,20%))" d="M150.5 48.8 C146 43 139.5 39.2 131 38 C120.5 35.8 110.5 33.5 100 33 C79 33.6 58 37.6 44 44.5 C58 38.6 79 34.9 100 34.9 C110.5 35.2 120.5 37.2 130 40.5 C139 44 146 48 150.5 48.8 Z"/>
<!-- жаберная пластина: мягкая светлая заливка (объём головы) -->
<path fill="var(--f2,hsl(160,18%,72%))" opacity="0.3" d="M122 40.5 C126 45.5 126.5 51.5 123.5 57.5 C119.5 51.5 118.5 45.5 119.5 41 Z"/>
<!-- жаберная дуга: тёмный серп у затылка (не задевает ободок глаза) -->
<path fill="none" stroke="var(--f4,hsl(170,25%,20%))" stroke-width="1.5" d="M121 40.5 C125 45.5 125.5 51.5 122.5 57.5"/>
<!-- 5 КОСЫХ тёмных полос одним compound-path: наклон ~13° (верх сдвинут вперёд), шире сверху (4), уже снизу (2.5), брюхо не пересекают -->
<path fill="var(--f4,hsl(170,25%,20%))" opacity="0.55" d="M58 42 L62 42 L57.7 54 L55.2 54 Z M72 39 L76 39 L69.9 60 L67.4 60 Z M86 37 L90 37 L83.1 63 L80.6 63 Z M100 36 L104 36 L96.9 64.5 L94.4 64.5 Z M114 36.5 L118 36.5 L110.9 63.5 L108.4 63.5 Z"/>
<!-- ротовая щель: от конца рыла назад под глаз -->
<path fill="var(--f4,hsl(170,25%,20%))" d="M151 49.4 C143 49.9 136.5 50.9 128.5 52.4 C136.5 53.6 143.5 53 152 51.2 Z"/>
<!-- клыки (фикс-акцент): два мелких треугольника с верхней челюсти -->
<path fill="#f7f3e6" d="M146.5 49.9 L148.3 50 L147.2 52.7 Z M141.8 50.3 L143.5 50.4 L142.5 52.9 Z"/>
<!-- грудной плавник: на боку под жаберной дугой (ПОСЛЕ тела), корень (119,55)→ кончик (113,66) -->
<path fill="var(--f3,hsl(168,22%,36%))" d="M120.5 54.5 C118 58.5 115.5 62.5 113.5 66.5 C117.5 65 121 61 122.5 56.5 Z"/>
<!-- глаз: КРУПНЫЙ (ободок → склера → радужка → зрачок → блик) -->
<circle fill="var(--f4,hsl(170,25%,20%))" cx="133" cy="42" r="5.6"/>
<circle fill="#f7f3e6" cx="133" cy="42" r="4.6"/>
<circle fill="#c9c29a" cx="133" cy="42" r="3.3"/>
<circle fill="#142638" cx="133" cy="42" r="2.3"/>
<circle fill="#fff" cx="131.8" cy="40.8" r="0.9"/>
</symbol>
<symbol id="fish-chuch" viewBox="0 0 160 100">
<!-- хвост: вилочный, лопасти сведены в острия, база садится на тонкий стебель (8 ед.) -->
<path fill="var(--f3,hsl(255,18%,40%))" d="M46 46 L14 33 C23 39 31 44.5 36 49 L36 51 C31 55.5 23 61 14 66 L46 54 Z"/>
<!-- ГЛАВНЫЙ знак вида: спинной плавник-«парус» — высокий, волнистая верхняя кромка (гребни/ложбины), задняя лопасть свисает вниз-назад; основание утоплено в спину (нахлёст ≥4) -->
<path fill="var(--f3,hsl(255,18%,40%))" d="M58 39 C59 25 62 13 66 8 C70 12.5 73.5 13.5 76.5 11.5 C80 8.5 83.5 8.5 87 11.5 C90.5 14.5 94 14.5 97.5 11.5 C100.5 8.8 104 8.8 107 11 C110.5 13.8 114.5 19.5 118.5 26 C120 28.5 121.5 31 122 33 C116.5 33.5 112 35 107.5 37.5 Z"/>
<!-- красноватая кромка паруса (фикс-акцент): по переднему краю, волнистой верхней кромке и задней лопасти -->
<path fill="none" stroke="#c05a72" stroke-width="1.2" d="M58 39 C59 25 62 13 66 8 C70 12.5 73.5 13.5 76.5 11.5 C80 8.5 83.5 8.5 87 11.5 C90.5 14.5 94 14.5 97.5 11.5 C100.5 8.8 104 8.8 107 11 C110.5 13.8 114.5 19.5 118.5 26 C120 28.5 121.5 31 122 33"/>
<!-- лучи паруса: 5 штрихов веером от основания к кромке -->
<path fill="none" stroke="var(--f4,hsl(255,25%,24%))" stroke-width="0.8" opacity="0.35" d="M65 38 C65.5 30 66 20 67 12.5 M74 37.5 C74.5 29 75.5 19 76.5 12 M84 37 C84.5 28 85.5 18.5 86.5 12 M94 36.5 C94.5 27 95.5 18 96.5 12.5 M104 36 C104.5 27 106 18 108.5 13.5"/>
<!-- жировой плавничок: маленький, на спине позади паруса, у самого стебля -->
<path fill="var(--f3,hsl(255,18%,40%))" d="M46 45.5 C47 41.5 48.5 38 51 35.5 C52.5 37.5 53.5 39.5 54 41.5 C51 42.5 48.5 44 46 45.5 Z"/>
<!-- анальный плавник: широко растёт из брюха, мягкая кромка вниз -->
<path fill="var(--f3,hsl(255,18%,40%))" d="M61 65 C64 77.5 70 85 77 85 C84 84 88 77.5 89 65.5 L61 65 Z"/>
<!-- брюшные плавники: пара мягких лопастей назад-вниз -->
<path fill="var(--f3,hsl(255,18%,40%))" d="M90 66.5 C88.5 74 86.5 80.5 88.5 83.5 C92 80.5 94 74.5 95 67.5 Z M99 66.5 C97.5 74 95.5 80.5 97.5 83.5 C101 80.5 103 74.5 104 67.5 Z"/>
<!-- тело: умеренно высокое, спина ровно поднимается к плечу, мелкая голова, маленькое рыло -->
<path fill="var(--f1,hsl(252,16%,60%))" d="M42 46 C50 39.5 60 34 74 32.5 C86 31.2 96 30.6 104 31.4 C118 32.6 128 35.6 136 40.5 C143 44.6 147.5 46.4 150 48 C145 55.5 136.5 61 124.5 65 C110 69.5 94 70.4 79 69.9 C63 69.3 50 61.5 42 54 Z"/>
<!-- брюхо: светлая нижняя полоса -->
<path fill="var(--f2,hsl(250,20%,82%))" d="M42 54 C50 61.5 63 69.3 79 69.9 C94 70.4 110 69.5 124.5 65 C136.5 61 145 55.5 150 48 C144.5 55 134.5 60 120.5 63 C105 66.5 87 66.8 71 63.8 C58 61.3 48.5 58.5 42 54 Z"/>
<!-- тёмная спинная кромка: тонкая полоса по верхнему контуру (не чёрная шапка) -->
<path fill="var(--f4,hsl(255,25%,24%))" d="M42 46 C50 39.5 60 34 74 32.5 C86 31.2 96 30.6 104 31.4 C118 32.6 128 35.6 136 40.5 C143 44.6 147.5 46.4 150 48 C146.5 46.7 142 44.9 135 41.7 C127 37.7 117 35 104 33.7 C96 32.9 86 33.4 75 35 C61.5 36.8 51 41.5 42 46 Z"/>
<!-- жаберная пластина: мягкий светлый объём мелкой головы -->
<path fill="var(--f2,hsl(250,20%,82%))" opacity="0.35" d="M115 35 C120 42.5 121 52 117 61 C113 52 112 43 112.5 36 Z"/>
<!-- жаберная дуга: тёмный серп, чистый зазор от ободка глаза -->
<path fill="none" stroke="var(--f4,hsl(255,25%,24%))" stroke-width="1.4" d="M115 35 C120 42.5 121 52 117 61"/>
<!-- ГЛАВНЫЙ узор: мелкая чёрная крапь — 2 ряда по верхнему боку (7 точек) и 3 точки на самом парусе, один compound-path -->
<path fill="var(--f4,hsl(255,25%,24%))" d="M72.8 40 a1.2 1.2 0 1 0 2.4 0 a1.2 1.2 0 1 0 -2.4 0 Z M86.9 39 a1.1 1.1 0 1 0 2.2 0 a1.1 1.1 0 1 0 -2.2 0 Z M99.8 39.5 a1.2 1.2 0 1 0 2.4 0 a1.2 1.2 0 1 0 -2.4 0 Z M112 41 a1 1 0 1 0 2 0 a1 1 0 1 0 -2 0 Z M80.9 47 a1.1 1.1 0 1 0 2.2 0 a1.1 1.1 0 1 0 -2.2 0 Z M94 46 a1 1 0 1 0 2 0 a1 1 0 1 0 -2 0 Z M107.1 47.5 a0.9 0.9 0 1 0 1.8 0 a0.9 0.9 0 1 0 -1.8 0 Z M70.9 17 a1.1 1.1 0 1 0 2.2 0 a1.1 1.1 0 1 0 -2.2 0 Z M84 16 a1 1 0 1 0 2 0 a1 1 0 1 0 -2 0 Z M95.9 20 a1.1 1.1 0 1 0 2.2 0 a1.1 1.1 0 1 0 -2.2 0 Z"/>
<!-- чешуя: 3 широких серпа на боку -->
<path fill="var(--f2,hsl(250,20%,82%))" opacity="0.3" d="M104 41 Q97 50 104 59 Q100.5 50 104 41 Z M111 42.5 Q104 50 111 57.5 Q107.5 50 111 42.5 Z M97 40.5 Q90 50 97 59.5 Q93.5 50 97 40.5 Z"/>
<!-- рот: крошечная щель на мелком рыле -->
<path fill="var(--f4,hsl(255,25%,24%))" d="M145 47.4 C147.5 47.6 149.3 48.1 150 48.7 C148.6 49.3 146.5 49.2 144.8 48.4 Z"/>
<!-- грудной плавник: мягкая лопасть на боку под жаберной дугой (после тела) -->
<path fill="var(--f3,hsl(255,18%,40%))" opacity="0.8" d="M119.5 53.5 C114 55.5 109.5 60 110.5 65.5 C113.5 69 118.5 63 121.5 57.5 C121 55.5 120.5 54.2 119.5 53.5 Z"/>
<!-- лучи грудного плавника -->
<path fill="none" stroke="var(--f4,hsl(255,25%,24%))" stroke-width="0.7" opacity="0.3" d="M117.5 56 C113.5 59.5 111.2 63 110.8 64.5 M119.5 58.5 C116.2 61.3 113.8 64.5 113.2 65.8"/>
<!-- глаз: ободок → склера → радужка → зрачок → блик (последним) -->
<circle fill="var(--f4,hsl(255,25%,24%))" cx="132" cy="42" r="4.6"/>
<circle fill="#f7f3e6" cx="132" cy="42" r="3.7"/>
<circle fill="#8e8ba0" cx="132" cy="42" r="2.8"/>
<circle fill="#142638" cx="132" cy="42" r="2"/>
<circle fill="#fff" cx="130.8" cy="40.6" r="0.8"/>
</symbol>
<symbol id="fish-crayfish" viewBox="0 0 160 100">
<!-- хвостовой веер: две широкие уропода-лопасти f3 (верхняя и нижняя), compound-path -->
<path fill="var(--f3,hsl(15,46%,34%))" d="M35 39.5 C30 34 24 30.5 18 30 C20 38 26 44.5 33.5 45.5 Z M35 60.5 C30 66 24 69.5 18 70 C20 62 26 55.5 33.5 54.5 Z"/>
<!-- тельсон: клин f1 со светлым f2-ядром -->
<path fill="var(--f1,hsl(18,48%,44%))" d="M37 44.5 L16 50 L37 55.5 Z"/>
<path fill="var(--f2,hsl(28,34%,72%))" d="M35 47.2 L21 50 L35 52.8 Z"/>
<!-- брюшко: 4 сегмента-пластины (от заднего к переднему), compound-path -->
<path fill="var(--f1,hsl(18,48%,44%))" d="M34 50 a9 9 0 1 0 18 0 a9 9 0 1 0 -18 0 M41.5 50 a9.5 11 0 1 0 19 0 a9.5 11 0 1 0 -19 0 M50 50 a10 13 0 1 0 20 0 a10 13 0 1 0 -20 0 M60 50 a10 15 0 1 0 20 0 a10 15 0 1 0 -20 0"/>
<!-- светлая срединная полоса брюшка -->
<path fill="var(--f2,hsl(28,34%,72%))" opacity="0.32" d="M38 48 C52 45.2 66 44.2 78 45 L78 55 C66 56 52 55 38 52 Z"/>
<!-- границы сегментов брюшка: тёмные f4-дуги, compound-path -->
<path fill="none" stroke="var(--f4,hsl(12,48%,20%))" stroke-width="1.4" d="M68 36.4 C65.4 42.5 65.4 57.5 68 63.6 M58 38.4 C55.6 44 55.6 56 58 61.6 M48 40.4 C46 45 46 55 48 59.6"/>
<!-- ходильные ноги: 4 пары «расчёской» вверх и вниз, 2 compound-группы f4 -->
<path fill="none" stroke="var(--f4,hsl(12,48%,20%))" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" d="M116 37 L112 28 L100 24 M104 33 L98 25 L86 20 M92 34 L84 25 L72 17 M80 39 L70 27 L60 17"/>
<path fill="none" stroke="var(--f4,hsl(12,48%,20%))" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" d="M116 63 L112 72 L100 76 M104 67 L98 75 L86 80 M92 66 L84 75 L72 83 M80 61 L70 73 L60 83"/>
<!-- карапакс: широкий овал f1 -->
<ellipse cx="100" cy="50" rx="26" ry="17" fill="var(--f1,hsl(18,48%,44%))"/>
<!-- светлые боковые пластины карапакса, compound-path -->
<path fill="var(--f2,hsl(28,34%,72%))" opacity="0.28" d="M84 39 C79 45 79 55 84 61 C88 55 88 45 84 39 Z M116 39 C121 45 121 55 116 61 C112 55 112 45 116 39 Z"/>
<!-- тёмный панцирный узор: две поперечные борозды f4 -->
<path fill="none" stroke="var(--f4,hsl(12,48%,20%))" stroke-width="1.3" opacity="0.5" d="M110 34.6 C105 41.5 105 58.5 110 65.4 M94 34 C89 41.5 89 58.5 94 66"/>
<!-- рострум: клин f1 между глазами с тёмной срединной линией -->
<path fill="var(--f1,hsl(18,48%,44%))" d="M126 46.5 L150 50 L126 53.5 Z"/>
<path fill="none" stroke="var(--f4,hsl(12,48%,20%))" stroke-width="1.1" d="M127 50 L149 50"/>
<!-- клешни: кисть и плечо f1 (верх и низ зеркально) -->
<path fill="var(--f1,hsl(18,48%,44%))" d="M120 40 C123 33.5 124.5 27 129.5 21.5 C134 16.8 142 15.8 146.5 19 C152 23 152.5 30.5 147.5 33.5 C143.5 36 137 36.5 132 34.5 C127.5 32.8 125.5 35.5 124 40 Z"/>
<path fill="var(--f1,hsl(18,48%,44%))" d="M120 60 C123 66.5 124.5 73 129.5 78.5 C134 83.2 142 84.2 146.5 81 C152 77 152.5 69.5 147.5 66.5 C143.5 64 137 63.5 132 65.5 C127.5 67.2 125.5 64.5 124 60 Z"/>
<!-- пальцы клешней: тёмные f4, клешня раскрыта -->
<path fill="var(--f4,hsl(12,48%,20%))" d="M144 18.5 C148.5 15.5 153.5 16 157 20.5 C153 19.5 149 20.2 145 22.5 Z M146 34.5 C149.5 36.5 152.5 35.5 154.5 31 C151 31.2 148.5 32 146.5 33 Z"/>
<path fill="var(--f4,hsl(12,48%,20%))" d="M144 81.5 C148.5 84.5 153.5 84 157 79.5 C153 80.5 149 79.8 145 77.5 Z M146 65.5 C149.5 63.5 152.5 64.5 154.5 69 C151 68.8 148.5 68 146.5 67 Z"/>
<!-- глаза на стебельках: 3 слоя — f4-стебелёк с «бусиной», зрачок #142638, блик #fff -->
<path fill="var(--f4,hsl(12,48%,20%))" d="M117 43.5 L121.5 37 L129 36 Z M125 36 a4 4 0 1 0 8 0 a4 4 0 1 0 -8 0 M117 56.5 L121.5 63 L129 64 Z M125 64 a4 4 0 1 0 8 0 a4 4 0 1 0 -8 0"/>
<path fill="#142638" d="M126.8 35.4 a2.8 2.8 0 1 0 5.6 0 a2.8 2.8 0 1 0 -5.6 0 M126.8 64.6 a2.8 2.8 0 1 0 5.6 0 a2.8 2.8 0 1 0 -5.6 0"/>
<path fill="#fff" d="M126.9 34.3 a1 1 0 1 0 2 0 a1 1 0 1 0 -2 0 M126.9 65.7 a1 1 0 1 0 2 0 a1 1 0 1 0 -2 0"/>
<!-- длинные антенны (верхняя и нижняя), compound-path f4 -->
<path fill="none" stroke="var(--f4,hsl(12,48%,20%))" stroke-width="1.7" stroke-linecap="round" d="M131 45 C141 42 150 36 158 30 M131 55 C141 58 150 64 158 70"/>
<!-- короткие антеннулы (внутренняя пара), compound-path f4 -->
<path fill="none" stroke="var(--f4,hsl(12,48%,20%))" stroke-width="1.3" stroke-linecap="round" d="M134 47 C140 45 146 44 152 44 M134 53 C140 55 146 56 152 56"/>
</symbol>
<symbol id="fish-bleak" viewBox="0 0 160 100">
<!-- хвост: умеренная вилка, корень утоплен в стебель на 4 ед. (нахлёст) -->
<path fill="var(--f3,hsl(12,45%,50%))" d="M42 45 L14 33 C20.5 41 24 46 27 50 C24 54 20.5 59 14 67 L42 55 L46 55 L46 45 Z"/>
<!-- спинной плавник: основание x68..95 утоплено в спину, вершина (82,15), задняя кромка чуть вогнута -->
<path fill="var(--f3,hsl(12,45%,50%))" d="M67.5 38 C71 29 75.5 18.5 82 15 C84.5 21 88.5 27 95 33.2 Z"/>
<!-- лучи спинного плавника: 3 тонких штриха веером от основания к кромке -->
<path fill="none" stroke="var(--f4,hsl(205,30%,24%))" stroke-width="0.9" opacity="0.28" d="M72.5 35 C72.2 29.5 73 25 74.5 20.5"/>
<path fill="none" stroke="var(--f4,hsl(205,30%,24%))" stroke-width="0.9" opacity="0.28" d="M81.5 32.8 C81.7 26 81.8 20 82 15.6"/>
<path fill="none" stroke="var(--f4,hsl(205,30%,24%))" stroke-width="0.9" opacity="0.28" d="M90 33.9 C89 28.5 86.8 23.5 84.5 18.5"/>
<!-- анальный плавник: основание x57..75 утоплено в брюхо (нахлёст ≥4), низ до y84, лопасть отведена назад -->
<path fill="var(--f3,hsl(12,45%,50%))" d="M58 61.5 C60 72.5 63 80 68.5 83.5 C73 84.5 75 79 75 66.5 Z"/>
<!-- брюшные плавники: пара мягких округлых лопастей, x84..102, отведены назад-вниз -->
<path fill="var(--f3,hsl(12,45%,50%))" d="M84 68.5 C82.5 77 84 83.5 87.5 85.5 C91 84 92.5 77.5 92 68.5 Z"/>
<path fill="var(--f3,hsl(12,45%,50%))" d="M94 68.5 C92.5 78 94 84.5 97.5 86 C101 84.5 102.5 78 102 68.5 Z"/>
<!-- тело: умеренно высокое серебристое, рыло (152,50), затылок (132,39), спина (96,29), брюхо (96,73), стебель 42,45/42,55 -->
<path fill="var(--f1,hsl(205,22%,55%))" d="M152 50 C149.5 43 143 37 134 35.5 C120 31 108 29 96 29 C72 29 50 36.5 42 45 L42 55 C50 63.5 72 73 96 73 C114 73 129 68 138 60 C144 55 149.5 52 152 50 Z"/>
<!-- брюхо: светлая нижняя треть (серебро) -->
<path fill="var(--f2,hsl(200,20%,80%))" d="M42 55 C50 63.5 72 73 96 73 C114 73 129 68 138 60 C130 64 114 68 96 68 C74 68 54 62.5 42 55 Z"/>
<!-- тёмная спинная кромка: тонкая полоса по верхнему контуру (не зубцы) -->
<path fill="var(--f4,hsl(205,30%,24%))" d="M152 50 C149.5 43 143 37 134 35.5 C120 31 108 29 96 29 C72 29 50 36.5 42 45 C50 39.5 72 31.5 96 31.5 C108 31.5 120 34 134 38.5 C143 42 149 47 152 50 Z"/>
<!-- жаберная пластина: мягкая светлая заливка головы -->
<path fill="var(--f2,hsl(200,20%,80%))" opacity="0.35" d="M130 39.5 C135 46 136 54 131 61.5 C127 54.5 126 46.5 126 40.5 Z"/>
<!-- жаберная дуга: тонкий тёмный серп у головы -->
<path fill="none" stroke="var(--f4,hsl(205,30%,24%))" stroke-width="1.2" opacity="0.45" d="M130 39.5 C135 46 136 54 131 61.5"/>
<!-- чешуя: крупные широкие f2-серпы, верхний ряд из трёх -->
<path fill="var(--f2,hsl(200,20%,80%))" d="M74 38.5 Q66.5 45 74 51.5 Q69.9 45 74 38.5 Z M90 37.5 Q82.5 44 90 50.5 Q85.9 44 90 37.5 Z M106 37.5 Q98.5 44 106 50.5 Q101.9 44 106 37.5 Z"/>
<!-- чешуя: нижний ряд из двух серпов (compound-path) -->
<path fill="var(--f2,hsl(200,20%,80%))" d="M82 50.5 Q74.5 57 82 63.5 Q77.9 57 82 50.5 Z M98 50.5 Q90.5 57 98 63.5 Q93.9 57 98 50.5 Z"/>
<!-- рот: конечный, чуть вниз (152,51.5) -->
<path fill="var(--f4,hsl(205,30%,24%))" d="M148.6 50 C150.4 50.7 152 51.3 152 51.7 C150.9 52.4 149.6 52 148.4 51 Z"/>
<!-- грудной плавник: мягкая лопасть на боку, направлена назад-вниз (после тела) -->
<path fill="var(--f3,hsl(12,45%,50%))" d="M117 55 C112 58 109 62.5 111 66.5 C114.5 65 116.5 60.5 118.5 56.5 Z"/>
<!-- глаз: ГЛАВНЫЙ знак вида — красная радужка (ободок → склера → радужка → зрачок → блик) -->
<circle fill="var(--f4,hsl(205,30%,24%))" cx="134" cy="42" r="5.6"/>
<circle fill="#f7f3e6" cx="134" cy="42" r="4.6"/>
<circle fill="#c0392b" cx="134" cy="42" r="3.4"/>
<circle fill="#142638" cx="134" cy="42" r="2.2"/>
<circle fill="#fff" cx="132.6" cy="40.6" r="0.9"/>
</symbol>
<symbol id="fish-roundel" viewBox="0 0 160 100">
<!-- хвост: глубокая вилка, лопасти (16,31)/(16,69); корень утоплен в стебель (нахлёст), светлая кромка отделяет от тела -->
<path fill="var(--f3,hsl(215,26%,40%))" stroke="var(--f2,hsl(210,20%,82%))" stroke-width="1" stroke-opacity="0.5" d="M50 44 L16 31 C23 39 27 45 30.5 50 C27 55 23 61 16 69 L50 56 Z"/>
<!-- спинной плавник: короткий, основание x68..92 утоплено в спину (нахлёст ≥4), вершина (79,14), задняя кромка вогнута -->
<path fill="var(--f3,hsl(215,26%,40%))" d="M68 34.5 C69.5 24 73.5 16 79 14 C81 20 85 28 92 34.5 Z"/>
<!-- лучи спинного плавника: 4 тонких штриха веером от основания к кромке (не выходят за мембрану) -->
<path fill="none" stroke="var(--f4,hsl(215,30%,24%))" stroke-width="0.9" opacity="0.3" d="M70 33 C70.8 30 71.6 27.4 72.8 25.2 M76 32.6 C76.6 27.5 77 22.5 77.5 17.5 M81.5 32.4 C81.3 28.2 80.9 24.3 80.4 20.6 M87 32.6 C86.2 29.8 84.7 27.2 82.7 25"/>
<!-- анальный плавник: КОРОТКИЙ (главное отличие от леща), основание x58..70 утоплено в брюхо (нахлёст ≥4), низ y85, задняя кромка вогнута -->
<path fill="var(--f3,hsl(215,26%,40%))" d="M58 62 C59.5 70 61.5 78 64 85 C67 82.5 69.5 75 70 62 Z"/>
<!-- лучи анального плавника: 3 штриха (плотные 12-14 лучей), не выходят за мембрану -->
<path fill="none" stroke="var(--f4,hsl(215,30%,24%))" stroke-width="0.9" opacity="0.3" d="M60 66 C60.6 71 61.6 76.5 62.8 81.5 M63.5 66 C63.9 71 64.2 76.5 64.3 82 M67 65.5 C66.8 69.5 66.3 73.5 65.6 77.5"/>
<!-- брюшные плавники: пара мягких округлых лопастей x82..100, основание внутри брюха, отведены назад-вниз -->
<path fill="var(--f3,hsl(215,26%,40%))" d="M83 70 C80.5 79 81.5 84 85.5 86 C89.5 85 91.5 79 92.5 70 Z"/>
<path fill="var(--f3,hsl(215,26%,40%))" d="M93 70 C90.5 79 91.5 84.5 95.5 86.5 C99.5 85.5 101 79 101.5 70 Z"/>
<!-- тело: высокое и сжатое (D/L≈0.46), спина округлая БЕЗ ромбовидного острия; рыло (150,50), затылок (130,36), спина (98,27), брюхо (98,75), стебель 46,45/46,55 (толщина 10) -->
<path fill="var(--f1,hsl(213,24%,57%))" d="M150 50 C147 44 141 38 132 36 C121 29.5 110 27 98 27 C72 28 54 34 46 45 L46 55 C51 67 70 75.5 98 75 C116 74 132 69 141 61 C145 57 148 53 150 50 Z"/>
<!-- брюхо: светлая серебристая нижняя треть -->
<path fill="var(--f2,hsl(210,20%,82%))" d="M46 55 C51 67 70 75.5 98 75 C116 74 132 69 141 61 C134 64 118 68 98 68.5 C74 68 53 61 46 55 Z"/>
<!-- спинная кромка: тонкая тёмная полоса по верхнему контуру (не зубцы) -->
<path fill="var(--f4,hsl(215,30%,24%))" d="M150 50 C147 44 141 38 132 36 C121 29.5 110 27 98 27 C72 28 54 34 46 45 C60 37.5 78 31.5 98 31.5 C110 31.5 121 34 132 39 C141 43 147 47 150 50 Z"/>
<!-- КИЛЬ: тонкая f4-кромка-гребень по линии брюха между анальным и брюшными плавниками (отличие от плотвы) -->
<path fill="var(--f4,hsl(215,30%,24%))" d="M62 69.4 C68 71.3 74 73.3 79 74.4 L79 75.7 C74 74.6 68 72.6 62 70.7 Z"/>
<!-- жаберная пластина: мягкая светлая заливка головы (сдвинута от крупного глаза) -->
<path fill="var(--f2,hsl(210,20%,82%))" opacity="0.35" d="M120 38 C126 45 127 55 122 63 C118 55 116 45 116 39 Z"/>
<!-- жаберная дуга: тонкий тёмный серп у головы -->
<path fill="none" stroke="var(--f4,hsl(215,30%,24%))" stroke-width="1.3" opacity="0.5" d="M120 38 C126 45 127 55 122 63"/>
<!-- чешуя: очень бледная f4-сетка (compound-path), верхний ряд из трёх дуг -->
<path fill="var(--f4,hsl(215,30%,24%))" opacity="0.15" d="M75 36 Q81 41 75 46 Q77 41 75 36 Z M91 34 Q97 39 91 44 Q93 39 91 34 Z M107 37 Q113 42 107 47 Q109 42 107 37 Z"/>
<!-- чешуя: нижний ряд из трёх дуг (реже и бледнее, чем у леща) -->
<path fill="var(--f4,hsl(215,30%,24%))" opacity="0.15" d="M83 47 Q89 52 83 57 Q85 52 83 47 Z M99 49 Q105 54 99 59 Q101 54 99 49 Z M115 52 Q121 57 115 62 Q117 57 115 52 Z"/>
<!-- рот: конечный, на конце рыла (150,50) -->
<path fill="var(--f4,hsl(215,30%,24%))" d="M147 50.3 C149 50.5 150 51 150.6 51.8 C149.5 52.8 147.8 52.5 146.6 51.3 Z"/>
<!-- грудной плавник: посажен низко, мягкая лопасть на боку (после тела) -->
<path fill="var(--f3,hsl(215,26%,40%))" d="M117 56 C113 58 110 63 111.5 68 C115 66 117 61 118.5 57 Z"/>
<!-- глаз: КРУПНЫЙ (главный знак густеры, антипод крошечного глаза леща): ободок → склера → радужка → зрачок → блик -->
<circle fill="var(--f4,hsl(215,30%,24%))" cx="134" cy="43" r="5.6"/>
<circle fill="#f7f3e6" cx="134" cy="43" r="4.7"/>
<circle fill="#d7c07a" cx="134" cy="43" r="3.6"/>
<circle fill="#142638" cx="134" cy="43" r="2.6"/>
<circle fill="#fff" cx="132.8" cy="41.6" r="1"/>
</symbol>
<symbol id="fish-eelpout" viewBox="0 0 160 100">
<!-- хвост: ОКРУГЛАЯ пластина-лопасть (ВИЛКИ НЕТ), 10x8 на конце ленты -->
<path fill="var(--f3,hsl(38,42%,32%))" d="M21 46 C15.5 45.4 11.6 47.2 11 50 C11.6 52.8 15.5 54.6 21 54 Z"/>
<!-- спинной плавник: КРОШЕЧНЫЙ, далеко к хвосту, основание утоплено в спину -->
<path fill="var(--f3,hsl(38,42%,32%))" d="M25 46 C25.8 38.5 28 34.5 30 34.8 C32 36 34 39.4 35 42.5 Z"/>
<!-- анальный плавник: КРОШЕЧНЫЙ, напротив спинного, утоплен в брюхо -->
<path fill="var(--f3,hsl(38,42%,32%))" d="M29.5 51 C30.5 56.5 32 60.5 34.5 61 C37 60 39 55.5 40 51.5 Z"/>
<!-- тело: длинная тонкая лента, плавная S-волна по оси (150,50)→(88,58)→(28,48), сужается к хвосту, нос скруглён -->
<path fill="var(--f1,hsl(38,40%,44%))" d="M150 43.5 C146 43.4 133.3 42.3 126 42.9 C118.7 43.6 112.3 46.2 106 47.4 C99.7 48.6 93.7 49.9 88 50 C82.3 50.1 77 49.4 72 47.8 C67 46.2 62.7 42.1 58 40.5 C53.3 38.9 49 37.8 44 38.2 C39 38.6 31.6 41.7 28 43 C24.4 44.3 23.4 45.5 22.5 46 C19.5 46.5 19.5 53.5 22.5 54 C23.4 53.8 24.4 53.7 28 53 C31.6 52.3 39 49.7 44 49.8 C49 49.9 53.3 51.4 58 53.5 C62.7 55.6 67 60.1 72 62.2 C77 64.3 82.3 65.9 88 66 C93.7 66.1 99.7 64.1 106 62.6 C112.3 61.1 118.7 58.1 126 57.1 C133.3 56.1 146 56.6 150 56.5 C153.6 56.5 156.5 53.6 156.5 50 C156.5 46.4 153.6 43.5 150 43.5 Z"/>
<!-- брюхо: светлая нижняя полоса, сходит на нет у хвоста и на конце рыла -->
<path fill="var(--f2,hsl(35,30%,72%))" d="M156.5 50 C156.4 52.2 154 55.8 150 56.5 C146 56.6 133.3 56.1 126 57.1 C118.7 58.1 112.3 61.1 106 62.6 C99.7 64.1 93.7 66.1 88 66 C82.3 65.9 77 64.3 72 62.2 C67 60.1 62.7 55.6 58 53.5 C53.3 51.4 49 49.9 44 49.8 C39 49.7 31.6 52.3 28 53 C24.4 53.7 23.4 53.8 22.5 54 C23.4 53.3 24.4 52.4 28 48 C31.6 47.3 39 44.7 44 44.8 C49 44.9 53.3 46.4 58 48.5 C62.7 50.6 67 55.1 72 57.2 C77 59.3 82.3 60.9 88 61 C93.7 61.1 99.7 59.1 106 57.6 C112.3 56.1 118.7 53.1 126 52.1 C133.3 51.1 146 51.6 150 51.5 C154 51 156.4 50.6 156.5 50 Z"/>
<!-- тёмная спинная линия по хребту с уходом на рыло + 10 пятнышек мелкой крапчатости — одним compound-путём -->
<path fill="var(--f4,hsl(30,45%,18%))" d="M150 43.5 C146 43.4 133.3 42.3 126 42.9 C118.7 43.6 112.3 46.2 106 47.4 C99.7 48.6 93.7 49.9 88 50 C82.3 50.1 77 49.4 72 47.8 C67 46.2 62.7 42.1 58 40.5 C53.3 38.9 49 37.8 44 38.2 C39 38.6 31.6 41.7 28 43 C24.4 44.3 23.4 45.5 22.5 46 L22.5 48.2 C23.4 47.7 24.4 46.5 28 45.2 C31.6 43.9 39 40.8 44 40.4 C49 40 53.3 41.1 58 42.7 C62.7 44.3 67 48.4 72 50 C77 51.6 82.3 52.3 88 52.2 C93.7 52.1 99.7 50.8 106 49.6 C112.3 48.4 118.7 45.8 126 45.1 C133.3 44.5 146 45.6 150 45.7 C150.4 45.1 150.4 44.2 150 43.5 Z M116.7 50.6 C117.1 49.3 119 49.5 119.4 50.6 C119.2 51.5 117.3 51.9 116.7 50.6 Z M106.8 52.2 C107.1 51 108.9 51.2 109.3 52.2 C109.1 53 107.4 53.4 106.8 52.2 Z M96.9 54 C97.2 52.9 98.9 53.1 99.2 54 C99 54.7 97.4 55.1 96.9 54 Z M86.7 55 C87.1 53.8 89 54 89.3 55 C89.2 55.8 87.4 56.2 86.7 55 Z M76.9 54 C77.2 53 78.8 53.1 79.1 54 C79 54.7 77.5 55 76.9 54 Z M66.8 50.2 C67.1 49 68.9 49.2 69.3 50.2 C69.1 51 67.4 51.4 66.8 50.2 Z M56.9 44.6 C57.2 43.5 58.9 43.7 59.2 44.6 C59 45.3 57.4 45.7 56.9 44.6 Z M46.7 42.2 C47.1 41 49 41.2 49.3 42.2 C49.2 43 47.4 43.4 46.7 42.2 Z M36.9 44 C37.2 43 38.8 43.1 39.1 44 C39 44.7 37.5 45 36.9 44 Z M27.9 47 C28.2 45.9 29.9 46.1 30.2 47 C30 47.7 28.4 48.1 27.9 47 Z"/>
<!-- 5 пар тонких усиков (10 штук) вокруг рта — главный видовой знак; 2 пары верхних длинных к (124,44)/(126,58), средняя к (134,60), 2 пары нижних коротких к (140,60)/(142,62); одним compound-путём -->
<path fill="none" stroke="var(--f4,hsl(30,45%,18%))" stroke-width="0.8" stroke-linecap="round" d="M148.5 48.2 Q138 42 124 44 M148.2 49 Q137.5 43.2 125 45.6 M149.2 50 Q139 52.5 126 57.8 M148.9 50.6 Q138.6 53.4 127 58.5 M148.6 51.2 Q142.5 56 134 60 M148.3 51.6 Q142 56.6 135 60.5 M147.8 52 Q144.5 56.8 140 60 M147.4 52.3 Q144 57.4 140.6 60.6 M147 52.6 Q144.6 58 142 62 M146.6 52.9 Q144.4 58.8 142.6 62.4"/>
<!-- рот: крошечная тёмная щель на нижней губе рыла -->
<path fill="var(--f4,hsl(30,45%,18%))" d="M150.8 52.7 C153.6 53 155.8 52.4 156.7 50.8 C155.2 53.5 152.8 54.2 150.4 54 Z"/>
<!-- предглазничная складка-шип: тонкий тёмный серп перед глазом -->
<path fill="var(--f4,hsl(30,45%,18%))" d="M142.2 44.2 C140.8 46.6 140.4 49.4 141.2 51.8 C142.4 49.4 142.8 46.6 142.2 44.2 Z"/>
<!-- грудной плавник: маленькая мягкая лопасть у головы (рисуется ПОСЛЕ тела) -->
<path fill="var(--f3,hsl(38,42%,32%))" d="M134.5 51.8 C131.3 52.4 127.4 55 126.6 58.4 C129.9 57.9 133.4 54.8 134.7 52.4 Z"/>
<!-- глаз: НАМЕРЕННО крошечный (3 слоя), высоко и вперёд -->
<circle fill="var(--f4,hsl(30,45%,18%))" cx="139" cy="46" r="2"/>
<circle fill="#142638" cx="139" cy="46" r="1.2"/>
<circle fill="#fff" cx="138.4" cy="45.4" r="0.5"/>
</symbol>
<symbol id="fish-tench" viewBox="0 0 160 100">
<!-- хвост: почти ровный, слабая выемка, закруглённые лопасти (база утоплена в толстый стебель, нахлёст ≥4) -->
<path fill="var(--f3,hsl(92,30%,26%))" d="M48 44 L14 36 C20 42 23 46 25 50 C23 54 20 58 14 64 L48 56 Z"/>
<!-- спинной плавник: ЗАКРУГЛЁННЫЙ и выпуклый (вершина 79,19, задний конец скруглён), основание глубоко утоплено в спину (нахлёст ≥4) -->
<path fill="var(--f3,hsl(92,30%,26%))" d="M58 42 C61 28 69 19 79 19 C89 19 97 26 101 40 Z"/>
<!-- лучи спинного плавника: 3 тонких бледных штриха веером от основания к кромке -->
<path fill="none" stroke="var(--f4,hsl(95,30%,16%))" stroke-width="0.9" opacity="0.3" d="M67 39 L71 29"/>
<path fill="none" stroke="var(--f4,hsl(95,30%,16%))" stroke-width="0.9" opacity="0.3" d="M77 38 L79 21"/>
<path fill="none" stroke="var(--f4,hsl(95,30%,16%))" stroke-width="0.9" opacity="0.3" d="M87 39 L89 29"/>
<!-- анальный плавник: ЗАКРУГЛЁННЫЙ и выпуклый (низ 86), широким основанием растёт из брюха, не висит каплей -->
<path fill="var(--f3,hsl(92,30%,26%))" d="M56 57 C62 58 72 60 80 64 C86 71 84 86 73 86 C62 86 56 76 56 57 Z"/>
<!-- лучи анального плавника: 3 тонких бледных штриха на лопасти -->
<path fill="none" stroke="var(--f4,hsl(95,30%,16%))" stroke-width="1" opacity="0.3" d="M64 62 C65 70 66 76 67 81"/>
<path fill="none" stroke="var(--f4,hsl(95,30%,16%))" stroke-width="1" opacity="0.3" d="M71 64 C72 72 73 78 74 83"/>
<path fill="none" stroke="var(--f4,hsl(95,30%,16%))" stroke-width="1" opacity="0.3" d="M78 66 C79 73 79 79 79 83"/>
<!-- брюшные плавники: пара мягких округлых лопастей, направлены назад-вниз (нахлёст в брюхо ≥4) -->
<path fill="var(--f3,hsl(92,30%,26%))" d="M88 66 C85 76 88 85 93 85 C97 84 99 76 99 68 Z"/>
<path fill="var(--f3,hsl(92,30%,26%))" d="M99 68 C97 77 99 85 104 85 C108 84 110 77 110 69 Z"/>
<!-- тело: плотное «налитое», округлое (глубина/длина ≈0.43), спина (96,30), брюхо (96,74), тупое рыло (151,50), стебель 12 ед. -->
<path fill="var(--f1,hsl(90,26%,36%))" d="M151 50 C150 42 144 36 134 33 C124 30 110 28.5 96 30 C74 33 54 40 44 44 L44 56 C54 61 74 68 96 74 C114 74 136 67 144 60 C148 56 151 53 151 50 Z"/>
<!-- брюхо: светлая нижняя треть -->
<path fill="var(--f2,hsl(88,22%,64%))" d="M44 56 C54 61 74 68 96 74 C114 74 136 67 144 60 C138 66 122 71 104 72 C80 72 56 65 44 56 Z"/>
<!-- слизь: широкий f2-блик по спине (мелкая чешуя даёт сплошной глянец, а не сетку) -->
<path fill="var(--f2,hsl(88,22%,64%))" opacity="0.3" d="M52 49 C68 42 92 37 120 39 C102 41 78 45 52 54 Z"/>
<!-- слизь: широкий f2-блик по средней части бока -->
<path fill="var(--f2,hsl(88,22%,64%))" opacity="0.28" d="M58 57 C76 51 100 48 124 50 C106 52 82 56 58 63 Z"/>
<!-- слизь: узкий блик на плече у стебля -->
<path fill="var(--f2,hsl(88,22%,64%))" opacity="0.26" d="M48 44 C56 42 66 41 76 41 C66 43 56 45 48 48 Z"/>
<!-- мраморность: единый compound-path из 4 бледных f4-клякс (замена чешуйной сетке) -->
<path fill="var(--f4,hsl(95,30%,16%))" opacity="0.13" d="M62 42 C68 39 74 42 72 46 C70 50 62 49 59 46 C57 43 58 42 62 42 Z M86 38 C92 36 97 39 95 43 C93 47 85 46 83 43 C81.5 40.5 82.5 38.5 86 38 Z M106 43 C111 41 116 44 114 48 C112 51 106 50 104 47 C103 44.5 103.5 43.5 106 43 Z M72 55 C77 53 82 56 80 59 C78 62 71 61 69 58 C68 56 68.5 55 72 55 Z"/>
<!-- спинная кромка: тонкая тёмная полоса по верхнему контуру (не зубцы) -->
<path fill="var(--f4,hsl(95,30%,16%))" d="M151 50 C150 42 144 36 134 33 C124 30 110 28.5 96 30 C74 33 54 40 44 44 C54 38 74 32.5 96 33.5 C110 31.5 124 35 134 38 C143 41 148 46 151 50 Z"/>
<!-- жаберная пластина: мягкая светлая заливка (объём тупой головы) -->
<path fill="var(--f2,hsl(88,22%,64%))" opacity="0.3" d="M118 39 C124 46 125 55 120 62 C115 55 114 46 114.5 40 Z"/>
<!-- жаберная дуга: тёмный серп у головы (отодвинут от маленького глаза) -->
<path fill="none" stroke="var(--f4,hsl(95,30%,16%))" stroke-width="1.5" d="M118 39 C124 46 125 55 120 62"/>
<!-- рот: КОНЕЧНЫЙ и маленький, крошечная тёмная щель на самом рыле (усов-щупалец нет) -->
<path fill="var(--f4,hsl(95,30%,16%))" d="M151 49.4 C149.8 49.7 148.6 50.2 147.8 50.9 C148.9 51.7 150.2 51.5 151 50.6 Z"/>
<!-- микро-усики: 2 f4-штриха у углов рта, очень короткие (~3 ед.) — иначе прочтутся усами карпа/сома -->
<path fill="none" stroke="var(--f4,hsl(95,30%,16%))" stroke-width="1.5" stroke-linecap="round" d="M149 53 L146.6 54.8"/>
<path fill="none" stroke="var(--f4,hsl(95,30%,16%))" stroke-width="1.5" stroke-linecap="round" d="M149 55 L146.9 57.1"/>
<!-- грудной плавник: мягкая округлая лопасть на боку, ПОСЛЕ тела, направлена назад-вниз -->
<path fill="var(--f3,hsl(92,30%,26%))" d="M120 54 C114 55 109 61 111 68 C114 72 119 65 121 58 Z"/>
<!-- глаз ПОСЛЕДНИМ и НАМЕРЕННО МАЛЕНЬКИЙ, низко у рыла (антипод карася): ободок f4 → склера → красная радужка #c0392b → зрачок → блик -->
<circle fill="var(--f4,hsl(95,30%,16%))" cx="133" cy="45" r="3.8"/>
<circle fill="#f7f3e6" cx="133" cy="45" r="2.9"/>
<circle fill="#c0392b" cx="133" cy="45" r="2.2"/>
<circle fill="#142638" cx="133" cy="45" r="1.5"/>
<circle fill="#fff" cx="132.2" cy="44.2" r="0.6"/>
</symbol>
<symbol id="fish-navaga" viewBox="0 0 160 100">
<!-- хвост: слабо вильчатый, лопасти чуть расставлены, корень утоплен в стебель (нахлёст 4 ед.) -->
<path fill="var(--f3,hsl(212,16%,38%))" d="M46 47 L16 36 C23 43.5 26 47 27 50 C26 53 23 56.5 16 62 L46 53 Z"/>
<!-- D1 — первый спинной: самый высокий, основание глубоко в теле (нахлёст ≥4) -->
<path fill="var(--f3,hsl(212,16%,38%))" d="M102 43 C103 31 105 25 108 25 C111 25 113 31 114 43 Z"/>
<!-- D2 — второй спинной: ниже первого, ближе к хвосту -->
<path fill="var(--f3,hsl(212,16%,38%))" d="M84 43 C85 32 87 27 90 27 C93 27 95 32 96 43 Z"/>
<!-- D3 — третий спинной: самый низкий, у хвостового стебля (снова убывает) -->
<path fill="var(--f3,hsl(212,16%,38%))" d="M66 45.5 C67 35 69 30 72 30 C75 30 77 35 78 45.5 Z"/>
<!-- A1 — первый анальный: стоит под телом, растёт из брюха (нахлёст ≥4) -->
<path fill="var(--f3,hsl(212,16%,38%))" d="M76 57 C78 67 82 73 85 73 C88 73 89 67 90 57 Z"/>
<!-- A2 — второй анальный: дальше к хвосту, чуть ниже первого -->
<path fill="var(--f3,hsl(212,16%,38%))" d="M58 54 C60 65 63 72 66 72 C69 72 70 65 70 54 Z"/>
<!-- брюшные плавники: пара мелких лопастей под брюхом, основания утоплены в теле -->
<path fill="var(--f3,hsl(212,16%,38%))" d="M86 58 C85 65 86 70 89 72 C92 70 92 64 92 58 Z"/>
<path fill="var(--f3,hsl(212,16%,38%))" d="M94 58 C94 65 95 71 98 73 C100.5 70 100.5 64 100 58 Z"/>
<!-- лучи плавников: тонкие тёмные штрихи ВНУТРИ лопастей (один составной путь, наружу не выходят) -->
<path fill="none" stroke="var(--f4,hsl(210,18%,24%))" stroke-width="0.9" opacity="0.3" d="M104.5 41 C104.5 37 105.5 33 107 31 M108.5 41 C108.5 36 108.5 32 108.5 29 M112 41 C112 37 112 33 112.5 31 M87 41.5 C87.5 38 88.5 34 89.5 32 M91 41.5 C91.5 37 91.5 33 91.5 31 M94.5 41.5 C94.5 38 94.5 34 95 32 M69.5 43 C70 40 71 37 71.5 35 M73 43 C73.5 40 73.5 37 73.5 34 M76 43 C76 40.5 76.5 37.5 76.5 36 M81.5 59 C82 63 83 67 84 69 M84.5 59 C85 63 85.5 67 86 69 M87 59 C87 62.5 87.5 65.5 88 68 M62 58 C62.5 61.5 63.5 65 65 67 M65.5 58 C66 61.5 66.5 65 67 67 M68 58 C68 61 68.5 64 69 66"/>
<!-- тело: вытянутое, рыло (152,49), затылок (134,40), спина (100,36), брюхо (100,64), стебель 9 ед. -->
<path fill="var(--f1,hsl(210,14%,52%))" d="M152 49 C147 43 141 39.5 134 40 C120 36.5 110 36 100 36 C80 36 60 40 42 46 L42 54 C60 60 80 64 100 64 C112 64 124 62 134 58 C143 54.5 148.5 51.5 152 49 Z"/>
<!-- брюхо: светлая полоса вдоль нижней кромки -->
<path fill="var(--f2,hsl(205,12%,78%))" d="M42 54 C60 60 80 64 100 64 C112 64 124 62 134 58 C143 54.5 148.5 51.5 152 49 C148.5 52 139 55.5 131 57.5 C119 60.5 107 61 100 61 C78 61 57 57.5 42 54 Z"/>
<!-- тёмная спинная кромка: тонкая полоса по верхнему контуру -->
<path fill="var(--f4,hsl(210,18%,24%))" d="M152 49 C147 43 141 39.5 134 40 C120 36.5 110 36 100 36 C80 36 60 40 42 46 L42 47.8 C60 42 80 38 100 38 C110 38 120 38.6 134 42 C141 41.6 147 45 152 49 Z"/>
<!-- жаберная пластина: мягкая светлая заливка (объём головы), отодвинута от ободка глаза -->
<path fill="var(--f2,hsl(205,12%,78%))" opacity="0.35" d="M121 41 C124.8 46 124.8 53 121 58 C116.5 53 116.5 45 117.5 41 Z"/>
<!-- жаберная дуга: тёмный серп у затылка -->
<path fill="none" stroke="var(--f4,hsl(210,18%,24%))" stroke-width="1.5" d="M121 41 C124.8 46 124.8 53 121 58"/>
<!-- боковая линия: тонкая светлая тресковая черта вдоль середины тела -->
<path fill="none" stroke="var(--f2,hsl(205,12%,78%))" stroke-width="1.1" d="M120 49.5 C104 49 84 49.5 48 51.5"/>
<!-- крап: 6-8 мелких тёмных пятен вдоль бока одним compound-path -->
<path fill="var(--f4,hsl(210,18%,24%))" d="M48.4 54 A1.6 1.1 0 1 0 51.6 54 A1.6 1.1 0 1 0 48.4 54 Z M58.3 50 A1.7 1.1 0 1 0 61.7 50 A1.7 1.1 0 1 0 58.3 50 Z M70.4 52 A1.6 1.2 0 1 0 73.6 52 A1.6 1.2 0 1 0 70.4 52 Z M82.4 48.5 A1.6 1.1 0 1 0 85.6 48.5 A1.6 1.1 0 1 0 82.4 48.5 Z M93.3 53 A1.7 1.2 0 1 0 96.7 53 A1.7 1.2 0 1 0 93.3 53 Z M104.4 49 A1.6 1.1 0 1 0 107.6 49 A1.6 1.1 0 1 0 104.4 49 Z M113.5 52.5 A1.5 1 0 1 0 116.5 52.5 A1.5 1 0 1 0 113.5 52.5 Z"/>
<!-- рот: маленькая тёмная щель на конце рыла -->
<path fill="var(--f4,hsl(210,18%,24%))" d="M147 48 C149.2 48.3 151 49 151.8 50.4 C150 51.8 148 51.3 146.6 50 Z"/>
<!-- усик: ОДИН короткий f4-усик на подбородке (главное отличие наваги от прочих) -->
<path fill="none" stroke="var(--f4,hsl(210,18%,24%))" stroke-width="1.6" stroke-linecap="round" d="M147 51.5 C144 55 141 59 139 63"/>
<!-- грудной плавник: на боку за жаберной дугой, кончиком вниз-назад (ПОСЛЕ тела) -->
<path fill="var(--f3,hsl(212,16%,38%))" d="M123 55 C122 60 120 64 116.5 67 C114.5 63.5 116.5 58.5 120 54.5 C121 54.5 122 54.7 123 55 Z"/>
<!-- глаз: ободок f4 → склера → радужка → зрачок → блик (последним слоем) -->
<circle fill="var(--f4,hsl(210,18%,24%))" cx="131" cy="43" r="5"/>
<circle fill="#f7f3e6" cx="131" cy="43" r="4.1"/>
<circle fill="#9aa7b0" cx="131" cy="43" r="3"/>
<circle fill="#142638" cx="131" cy="43" r="2.1"/>
<circle fill="#fff" cx="130" cy="41.9" r="0.8"/>
</symbol>
<symbol id="fish-rudd" viewBox="0 0 160 100">
<!-- хвост: лопасти (14,32)/(14,68), корень утоплен в стебель на 4 ед. -->
<path fill="var(--f3,hsl(12,72%,52%))" d="M50 44 L14 32 C21.5 40 25.5 45 29 50 C25.5 55 21.5 60 14 68 L50 56 Z"/>
<!-- спинной плавник: СДВИНУТ К ХВОСТУ, основание x56..82 утоплено в спину, вершина (68,14) -->
<path fill="var(--f3,hsl(12,72%,52%))" d="M56 39 C58.5 28 62.5 19 68 14.5 C71.5 20.5 77 25.5 82 32 Z"/>
<!-- лучи спинного плавника: 4 тонких штриха веером, концы не выходят за мембрану -->
<path fill="none" stroke="var(--f4,hsl(85,30%,24%))" stroke-width="0.9" opacity="0.3" d="M62 37.4 C62.8 31.5 64 26 65.5 22 M68 35.8 C68.2 29 68.3 23.5 68.5 18.5 M74 34.2 C73.4 30 72.6 26 71.8 23 M79 33 C78.3 30.5 77 27.8 75.5 25.5"/>
<!-- анальный плавник: основание x52..70 утоплено в брюхо, низ до y86 -->
<path fill="var(--f3,hsl(12,72%,52%))" d="M52 60 C50 73 53 83 58.5 86 C64 85.5 68.5 78 70 68 Z"/>
<!-- лучи анального плавника: 3 коротких тёмных штриха, целиком внутри мембраны -->
<path fill="none" stroke="var(--f4,hsl(85,30%,24%))" stroke-width="0.9" opacity="0.3" d="M55 63 C55.5 69 56.2 76 56.8 81 M59.5 63 C60 69.5 60.7 76 61.3 80.5 M63.5 64 C64 69.5 64.5 74.5 64.8 78"/>
<!-- брюшные плавники: пара округлых лопастей x84..102, отведены назад-вниз -->
<path fill="var(--f3,hsl(12,72%,52%))" d="M84 68 C81.5 77 82.5 83.5 86.5 86 C90.5 84 92.5 77.5 93 68 Z"/>
<path fill="var(--f3,hsl(12,72%,52%))" d="M94 68 C91.5 77 92.5 84 96.5 86.5 C100.5 84.5 102.5 78 103 68 Z"/>
<!-- тело: высокий ромб, рыло (150,47), затылок (130,35.5), спина (94,27), брюхо (94,75), стебель 46,45/46,55 -->
<path fill="var(--f1,hsl(80,35%,50%))" d="M150 47 C148 41.5 143 36.5 136 35 C124 31.5 110 28 94 27 C72 28 53 35 46 45 L46 55 C49 62 55 69 64 72.5 C73 75 84 75.5 94 75 C112 75 128 69 138 59 C143.5 53.5 148 49.5 150 47 Z"/>
<!-- брюхо: светлая нижняя треть -->
<path fill="var(--f2,hsl(78,35%,74%))" d="M46 55 C49 62 55 69 64 72.5 C73 75 84 75.5 94 75 C112 75 128 69 138 59 C130 63.5 116 68 97 68.5 C76 69 55 63 46 55 Z"/>
<!-- спинная кромка: тёмная полоса по хребту, к затылку сходит на нет (голова остаётся золотистой) -->
<path fill="var(--f4,hsl(85,30%,24%))" d="M137 35.3 C124 31.5 110 28 94 27 C72 28 53 35 46 45 C59 38.4 77 32.4 94 31.8 C111 32 124 34.8 134 38.5 C135.7 37.4 136.6 36.2 137 35.3 Z"/>
<!-- КИЛЬ: тонкая f4-кромка по брюху между анальным и брюшными плавниками -->
<path fill="var(--f4,hsl(85,30%,24%))" d="M62 71.8 C68 73.5 74 74.7 80 75.3 L80 76.6 C74 76 68 74.8 62 73.1 Z"/>
<!-- жаберная пластина: мягкая светлая заливка (сдвинута от крупного глаза) -->
<path fill="var(--f2,hsl(78,35%,74%))" opacity="0.3" d="M118 37 C123 44 124 54 119.5 63 C115 54 114 44 114.5 37.5 Z"/>
<!-- жаберная дуга: тонкий тёмный серп у головы -->
<path fill="none" stroke="var(--f4,hsl(85,30%,24%))" stroke-width="1.3" opacity="0.5" d="M118 37 C123 44 124 54 119.5 63"/>
<!-- золотистый f2-блик по верхнему боку -->
<path fill="var(--f2,hsl(78,35%,74%))" opacity="0.28" d="M64 42 C84 34 110 32 130 37 C118 39 106 38.6 94 39.6 C80 40.8 70 43.8 62 48 Z"/>
<!-- чешуя: 5 f2-серпов (compound-path) -->
<path fill="var(--f2,hsl(78,35%,74%))" opacity="0.35" d="M74 41 Q68 47 74 53 Q70.5 47 74 41 Z M90 39.5 Q84 45.5 90 51.5 Q86.5 45.5 90 39.5 Z M106 40 Q100 46 106 52 Q102.5 46 106 40 Z M82 52 Q76 58 82 64 Q78.5 58 82 52 Z M98 51 Q92 57 98 63 Q94.5 57 98 51 Z"/>
<!-- чешуя: очень бледная f4-сетка (compound-path) -->
<path fill="var(--f4,hsl(85,30%,24%))" opacity="0.12" d="M82 40 Q88 45 82 50 Q84 45 82 40 Z M98 38.5 Q104 43.5 98 48.5 Q100 43.5 98 38.5 Z M114 41 Q120 46 114 51 Q116 46 114 41 Z M90 50 Q96 55 90 60 Q92 55 90 50 Z M106 49 Q112 54 106 59 Q108 54 106 49 Z"/>
<!-- рот: ГЛАВНЫЙ знак вида — полуверхний клин (150,45)→(146,44): верхняя губа выдаётся над кончиком рыла, устье смотрит вверх -->
<path fill="var(--f4,hsl(85,30%,24%))" d="M146.3 45.6 C147.8 45.1 149.3 44.1 150.4 43.1 C150.7 44.1 150.6 45.3 150 46.5 C148.8 46.4 147.5 46 146.3 45.6 Z"/>
<!-- грудной плавник: мягкая лопасть на боку (116,55)→(110,67), после тела -->
<path fill="var(--f3,hsl(12,72%,52%))" d="M118 54 C113 57 109 62 110.5 67 C114.5 65 117 60 119 56 Z"/>
<!-- глаз: ГЛАВНЫЙ знак вида — ЯРКО-ЖЁЛТАЯ радужка (ободок → склера → радужка → зрачок → блик) -->
<circle fill="var(--f4,hsl(85,30%,24%))" cx="134" cy="41" r="5.6"/>
<circle fill="#f7f3e6" cx="134" cy="41" r="4.7"/>
<circle fill="#e0b021" cx="134" cy="41" r="3.6"/>
<circle fill="#142638" cx="134" cy="41" r="2.4"/>
<circle fill="#fff" cx="132.7" cy="39.7" r="1.0"/>
</symbol>
<symbol id="fish-cisco" viewBox="0 0 160 100">
<!-- хвост: ГЛУБОКАЯ вилка, корень утоплен в стебель на 4 ед. (нахлёст) -->
<path fill="var(--f3,hsl(192,16%,42%))" d="M46 46 L14 30 C19 38 24 44.5 29 50 C24 55.5 19 62 14 70 L46 54 Z"/>
<!-- спинной плавник: ОДИН высокий узкий треугольник (основание x56..76 утоплено в спину, нахлёст ≥4), без задней лопасти — это не хариус -->
<path fill="var(--f3,hsl(192,16%,42%))" d="M56 44 C60 32.5 63 20 66 12 C69 20 72 31 76 43.5 Z"/>
<!-- лучи спинного плавника: 3 тонких штриха веером от основания к кромке (внутри контура плавника) -->
<path fill="none" stroke="var(--f4,hsl(195,22%,26%))" stroke-width="0.9" opacity="0.28" d="M61.5 39 C61.5 34.5 62 31.5 62 28 M66 40 C66 32 66 22 66 15 M70.5 39.5 C71 34.5 71 31.5 71 29.5"/>
<!-- жировой плавничок: маленький округлый, сразу за спинным на стебле (второй главный знак сиговых; плавничок ОДИН, не ряд) -->
<path fill="var(--f3,hsl(192,16%,42%))" d="M44 48.8 C45 42 46.5 37 48.5 36 C50.5 37.5 51.5 42 52 46 Z"/>
<!-- анальный плавник: удлинённый, основание x58..76 утоплено в брюхо (нахлёст ≥4), низ до y79 -->
<path fill="var(--f3,hsl(192,16%,42%))" d="M58 60.5 C58 70 62.5 77 68 79 C73.5 79.5 76 73 76 60.5 Z"/>
<!-- лучи анального плавника: 2 тонких штриха на лопасти (внутри контура) -->
<path fill="none" stroke="var(--f4,hsl(195,22%,26%))" stroke-width="0.9" opacity="0.28" d="M62 67.5 C62.6 71 63.6 73.5 64.5 75.5 M68 68.5 C68.3 71.5 68.8 74 69.3 76"/>
<!-- брюшные плавники: пара мягких округлых лопастей, x78..92 -->
<path fill="var(--f3,hsl(192,16%,42%))" d="M79 61 C77.5 70 79 76.5 82.5 79 C85.5 76.5 86 70 85.5 61 Z"/>
<path fill="var(--f3,hsl(192,16%,42%))" d="M87 61 C85.5 70 87 76.5 90.5 79 C93.5 76.5 94 70 93.5 61 Z"/>
<!-- тело: стройное серебристое, рыло (150,49), короткий затылок (134,40.5), спина (98,38), брюхо (100,66), стебель 42,46/42,54 (толщина 8) -->
<path fill="var(--f1,hsl(190,14%,62%))" d="M150 49 C147 43.5 141 40.5 134 40.5 C122 38.5 110 38 98 38 C80 38 64 38.8 54 40 C49 41.2 45 43 42 46 L42 54 C48 61 54 64.5 62 65.8 C72 66.5 88 66.6 100 66 C120 66 139 59.5 150 49 Z"/>
<!-- брюхо: светлая нижняя треть -->
<path fill="var(--f2,hsl(188,14%,84%))" d="M42 54 C48 61 54 64.5 62 65.8 C72 66.5 88 66.6 100 66 C120 66 139 59.5 150 49 C137 58.5 120 62.5 100 62.5 C80 62.5 55 58.5 42 54 Z"/>
<!-- спинная кромка: тонкая тёмная полоса по верхнему контуру (не зубцы) -->
<path fill="var(--f4,hsl(195,22%,26%))" d="M150 49 C147 43.5 141 40.5 134 40.5 C122 38.5 110 38 98 38 C80 38 64 38.8 54 40 C49 41.2 45 43 42 46 C54 42.6 76 40.8 98 40.8 C112 40.8 126 42.8 136 45.8 C142.5 47.6 147.5 48.4 150 49 Z"/>
<!-- жаберная пластина: мягкая светлая заливка маленькой головы -->
<path fill="var(--f2,hsl(188,14%,84%))" opacity="0.32" d="M133 41.5 C138 48 138.5 56 134 62 C129.5 54.5 128 47 128 42.5 Z"/>
<!-- жаберная дуга: тонкий тёмный серп у головы -->
<path fill="none" stroke="var(--f4,hsl(195,22%,26%))" stroke-width="1.3" opacity="0.4" d="M133 41.5 C138 48 138.5 56 134 62"/>
<!-- чешуя: 4 широких f2-серпа КРУПНОЙ чешуи (compound-path) -->
<path fill="var(--f2,hsl(188,14%,84%))" opacity="0.4" d="M82 41.5 Q74 49 82 56.5 Q77.5 49 82 41.5 Z M95 42 Q87 49.5 95 57 Q90.5 49.5 95 42 Z M108 42.5 Q100 50 108 57.5 Q103.5 50 108 42.5 Z M121 43.5 Q113.5 50.5 121 57.5 Q117 50.5 121 43.5 Z"/>
<!-- боковая линия: тонкая f2-полоска вдоль середины тела от жабер к хвосту -->
<path fill="var(--f2,hsl(188,14%,84%))" d="M124 51.3 C108 50.8 70 50.4 44 50 L44 51.4 C70 51.8 108 52.2 124 52.7 Z"/>
<!-- рот: маленький полунижний, чуть ниже короткого рыла (усиков нет) -->
<path fill="var(--f4,hsl(195,22%,26%))" d="M145 51 C147.5 51.8 149.5 52.4 150 53 C148.3 53.8 146.4 53.4 145 52.2 Z"/>
<!-- грудной плавник: мягкая лопасть на боку, направлена назад-вниз (ПОСЛЕ тела) -->
<path fill="var(--f3,hsl(192,16%,42%))" d="M118.5 55.5 C114.5 58 111.5 61.5 113 65 C116.5 63.5 118 59.5 119.5 56 Z"/>
<!-- глаз: НЕБОЛЬШОЙ (ободок → склера → радужка → зрачок → блик) -->
<circle fill="var(--f4,hsl(195,22%,26%))" cx="131" cy="44" r="4.4"/>
<circle fill="#f7f3e6" cx="131" cy="44" r="3.5"/>
<circle fill="#b9c2c6" cx="131" cy="44" r="2.7"/>
<circle fill="#142638" cx="131" cy="44" r="1.9"/>
<circle fill="#fff" cx="130" cy="43" r="0.7"/>
</symbol>
<symbol id="fish-herring" viewBox="0 0 160 100">
<!-- хвост: вилочный, лопасти (13,31)/(13,69), выемка (29,50); корень утоплен в стебель на 4.5 ед. (нахлёст) -->
<path fill="var(--f3,hsl(205,38%,44%))" d="M48.5 45.8 L13 31 C18 38 24 45 29 50 C24 55 18 62 13 69 L48.5 54.2 Z"/>
<!-- спинной плавник: ОДИН короткий НИЗКИЙ в середине спины, вершина (82,26), основание x70..94 утоплено в тело (нахлёст ≥4), без финлетов -->
<path fill="var(--f3,hsl(205,38%,44%))" d="M70 43 C73 33 76.5 27.5 82 26 C87.5 28.5 91.5 34 94 43 Z"/>
<!-- анальный плавник: низкий, основание x48..62 утоплено в брюхо (нахлёст ≥4), низ (55,72) -->
<path fill="var(--f3,hsl(205,38%,44%))" d="M48 53 C49.5 62 51.5 69 55 72 C58.5 69 60.5 61 62 56 Z"/>
<!-- брюшные плавники: пара мелких лопастей, основания утоплены в брюхо (compound-path), кончики y72..73 -->
<path fill="var(--f3,hsl(205,38%,44%))" d="M84 58.8 C83 66 85 70.5 87 72.5 C89 70.5 89.5 65 89 58.8 Z M91 58.8 C90 66 92 70.5 94 72.5 C96 70.5 96.5 65 96 58.8 Z"/>
<!-- тело: стройное серебристое ~4.1:1, рыло (151.5,49.5), затылок (135,42), спина (96,37), низ брюха (98,63), стебель x44 (46/54), нижняя челюсть чуть вперёд -->
<path fill="var(--f1,hsl(205,30%,62%))" d="M151.5 49.5 C149 44.8 142 42 135 42 C120 38.6 108 37 96 37 C76 37 58 39.5 44 46 L44 54 C58 60.5 78 64 96 64 C112 64 128 59 139 53.5 C145 50.8 151 50.4 152.5 51.5 Z"/>
<!-- брюхо: светлое серебро нижней трети -->
<path fill="var(--f2,hsl(200,22%,84%))" d="M44 54 C58 60.5 78 64 96 64 C112 64 128 59 139 53.5 C130 58 112 61.5 96 61.5 C76 61.5 57 58 44 54 Z"/>
<!-- спинная кромка: тонкий f4-серп по верхнему контуру (не зубцы) -->
<path fill="var(--f4,hsl(210,35%,24%))" d="M151.5 49.5 C149 44.8 142 42 135 42 C120 38.6 108 37 96 37 C76 37 58 39.5 44 46 C58 42.3 76 40.2 96 40.2 C108 40.4 120 42 135 45.2 C142 47 148 48 151.5 49.5 Z"/>
<!-- жаберная пластина: мягкая светлая заливка маленькой головы (не выходит за брюхо) -->
<path fill="var(--f2,hsl(200,22%,84%))" opacity="0.3" d="M127.5 43 C131.5 47.5 131.5 52 128 56 C124.5 51.5 124 46.5 124.5 43.2 Z"/>
<!-- жаберная дуга: тонкий тёмный серп у головы -->
<path fill="none" stroke="var(--f4,hsl(210,35%,24%))" stroke-width="1.1" opacity="0.4" d="M127.5 43 C131.5 47.5 131.5 52 128 56"/>
<!-- КИЛЬ: тонкая прямая f4-черта по брюху чуть ниже светлой кромки (главный знак сельди) -->
<path fill="none" stroke="var(--f4,hsl(210,35%,24%))" stroke-width="1.2" opacity="0.55" stroke-linecap="round" d="M60 60.4 L89 63.8"/>
<!-- рот: маленькая тёмная щель, нижняя челюсть чуть вперёд -->
<path fill="var(--f4,hsl(210,35%,24%))" d="M149 51.3 C150.8 51.7 152.2 52.3 152.7 53 C151.2 53.5 149.7 53 148.6 52.1 Z"/>
<!-- грудной плавник: мягкая лопасть на боку, назад-вниз, корень (120,54) → кончик (114,66) (ПОСЛЕ тела) -->
<path fill="var(--f3,hsl(205,38%,44%))" d="M120 54 C122 54.4 122.8 56 122 58.4 C120.6 62.6 117.6 65.4 114 66.2 C114.6 63.2 116 59.4 118 56.2 C118.7 55.2 119.4 54.4 120 54 Z"/>
<!-- глаз: КРУПНЫЙ на маленькой голове (ободок f4 → склера → радужка → зрачок → блик) -->
<circle fill="var(--f4,hsl(210,35%,24%))" cx="132" cy="44" r="5.2"/>
<circle fill="#f7f3e6" cx="132" cy="44" r="4.2"/>
<circle fill="#9fb6c4" cx="132" cy="44" r="3.2"/>
<circle fill="#142638" cx="132" cy="44" r="2.2"/>
<circle fill="#fff" cx="130.7" cy="42.7" r="0.9"/>
</symbol>
<symbol id="fish-mackerel" viewBox="0 0 160 100">
<!-- хвост: вилочный, выемка (31,50); корень утоплен в стебель толщ.9 (нахлёст ≥4) -->
<path fill="var(--f3,hsl(192,34%,46%))" d="M48 44 C40 40.5 28 35 12 30 C21 39 27.5 45 31 50 C27.5 55 21 61 12 70 C28 65 40 59.5 48 56 Z"/>
<!-- D2 задний спинной: мягкий, ниже переднего, основание глубоко в спине (нахлёст ≥4) -->
<path fill="var(--f3,hsl(192,34%,46%))" d="M83 40 C85 33.5 88 27.8 91 26 C94.5 28.5 97.5 33.5 99 39.5 Z"/>
<!-- D1 передний спинной: выше, вершина (113,24), задняя кромка с 4 ЛЁГКИМИ вогнутыми выемками -->
<path fill="var(--f3,hsl(192,34%,46%))" d="M103 41 C105 34 108.5 27.5 113 24 Q114.6 28.4 116.3 27.2 Q117.9 31 119.4 30.2 Q121 34.6 122.6 34.4 Q122.8 38 123.5 43.5 Z"/>
<!-- A2 задний анальный: мягкая лопасть, основание в брюхе (нахлёст ≥4) -->
<path fill="var(--f3,hsl(192,34%,46%))" d="M80 60.5 C81.5 64.8 83.2 68.6 85 72 C87.5 68.6 89 64.8 90 60.5 Z"/>
<!-- A1 передний анальный: низ (98,74) -->
<path fill="var(--f3,hsl(192,34%,46%))" d="M92 62 C94 67.5 95.8 71.5 98 74 C101 71.5 103.5 67 105 62 Z"/>
<!-- брюшные: пара мягких лопастей, кончики y71-73, основания в брюхе -->
<path fill="var(--f3,hsl(192,34%,46%))" d="M106.5 60.5 C105.5 66.5 106.3 70.5 108 72.5 C110 70.5 110.5 66.5 110.5 60.5 Z M113.5 60 C112.5 65.5 113.5 69.5 115.5 71.5 C117.5 69.5 118.3 65 118 60 Z"/>
<!-- ФИНЛЕТЫ спины: 5 клиньев x54..80 одним compound-path, видимые зазоры (~1 ед.), основания в теле -->
<path fill="var(--f3,hsl(192,34%,46%))" d="M54 44.5 L58 44.5 L54.8 33 Z M59 43.8 L63 43.8 L59.8 32.4 Z M64 42.8 L68 42.8 L64.8 31.9 Z M69 41.4 L73 41.4 L69.8 31.3 Z M74 40.6 L78 40.6 L74.8 30.8 Z"/>
<!-- ФИНЛЕТЫ брюха: 4 клина x54..76 одним compound-path, видимые зазоры -->
<path fill="var(--f3,hsl(192,34%,46%))" d="M54 55 L58 55 L54.8 72 Z M60 56.5 L64 56.5 L60.8 71.3 Z M66 58 L70 58 L66.8 70.6 Z M72 59.5 L76 59.5 L72.8 70 Z"/>
<!-- тело: веретено ~3.5:1, рыло (152,49)/низ (152.5,50.5), затылок (135,40.5), спина (98,34.5), низ брюха (100,65.5), стебель x44 (45.5/54.5) -->
<path fill="var(--f1,hsl(190,28%,66%))" d="M152 49 C148 43.5 143 41 135 40.5 C122 36.2 110 34.8 98 34.5 C76 35.5 56 39.5 44 45.5 L44 54.5 C56 60.5 76 64.5 100 65.5 C124 65.8 143 57.5 152.5 50.5 Z"/>
<!-- брюхо: светлое серебро (резкая двухцветность), не доходит до спины -->
<path fill="var(--f2,hsl(190,20%,86%))" d="M44 54.5 C56 60.5 76 64.5 100 65.5 C124 65.8 143 57.5 152.5 50.5 C144 57 124 62.5 100 62 C76 61.5 57 58.5 44 54.5 Z"/>
<!-- спинная кромка: тонкая тёмная полоса по верхнему контуру (не зубцы) -->
<path fill="var(--f4,hsl(195,32%,25%))" d="M152 49 C148 43.5 143 41 135 40.5 C122 36.2 110 34.8 98 34.5 C76 35.5 56 39.5 44 45.5 C57 40 76 36.8 98 37 C110 37.1 122 38.6 134 42.5 C142 45.5 148 48 152 49 Z"/>
<!-- 2 киля f4 на стебле (compound): тонкие тёмные гребни сверху и снизу -->
<path fill="var(--f4,hsl(195,32%,25%))" d="M50 46.4 C47.5 45.4 45.3 45.1 44 45.5 L44 47.4 C45.6 47.1 47.7 47.2 50 47.2 Z M50 53.6 C47.5 54.6 45.3 54.9 44 54.5 L44 52.6 C45.6 52.9 47.7 52.8 50 52.8 Z"/>
<!-- жаберная пластина: мягкая светлая заливка головы (объём), не задевает ободок глаза -->
<path fill="var(--f2,hsl(190,20%,86%))" opacity="0.3" d="M126 41 C130 46 130.5 52 127.5 58 C123.5 52 122.5 46 123.5 41.5 Z"/>
<!-- жаберная дуга: тонкий тёмный серп у головы -->
<path fill="none" stroke="var(--f4,hsl(195,32%,25%))" stroke-width="1.5" d="M125 41 C129 46 129.5 52 126.5 58"/>
<!-- 7 ВОЛНИСТЫХ тёмных «S»-полос по спине одним compound-path: верх вплотную под спинной кромкой, низ до середины бока (y≈50.5), брюхо НЕ задевают -->
<path fill="var(--f4,hsl(195,32%,25%))" d="M56 42.2 C58.9 45.3 53.6 47.3 58.2 50.5 L61 49.7 C56.9 45.1 62.2 46.4 59.2 42.2 Z M67 40.1 C69.9 44 64.6 46.4 69.2 50.5 L72 49.7 C67.9 45.1 73.2 44.3 70.2 40.1 Z M78 38.8 C80.9 43.2 75.6 45.9 80.2 50.5 L83 49.7 C78.9 45.1 84.2 43 81.2 38.8 Z M89 38.2 C91.9 42.8 86.6 45.7 91.2 50.5 L94 49.7 C89.9 45.1 95.2 42.4 92.2 38.2 Z M100 38.2 C102.9 42.8 97.6 45.7 102.2 50.5 L105 49.7 C100.9 45.1 106.2 42.4 103.2 38.2 Z M111 39 C113.9 43.3 108.6 46 113.2 50.5 L116 49.7 C111.9 45.1 117.2 43.2 114.2 39 Z M122 40.8 C124.9 44.4 119.6 46.7 124.2 50.5 L127 49.7 C122.9 45.1 128.2 45 125.2 40.8 Z"/>
<!-- рот: щель от заострённого конца рыла назад под глаз -->
<path fill="var(--f4,hsl(195,32%,25%))" d="M151.5 49.3 C145 49.8 139 50.6 132 52 C139 53.2 145 52.8 152 51.4 Z"/>
<!-- грудной плавник: на боку, корень (120,54) → кончик (113,67), ПОСЛЕ тела -->
<path fill="var(--f3,hsl(192,34%,46%))" d="M120.5 54 C117.5 58 114.5 62.5 113 67 C116.5 65 120 61 121.5 56 Z"/>
<!-- глаз: крупный у конца морды (ободок → склера → серая радужка → зрачок → блик) -->
<circle fill="var(--f4,hsl(195,32%,25%))" cx="133" cy="42.5" r="4.6"/>
<circle fill="#f7f3e6" cx="133" cy="42.5" r="3.7"/>
<circle fill="#9aa7b0" cx="133" cy="42.5" r="3"/>
<circle fill="#142638" cx="133" cy="42.5" r="2.1"/>
<circle fill="#fff" cx="131.8" cy="41.3" r="0.8"/>
</symbol>
<symbol id="fish-flounder" viewBox="0 0 160 100">
<!-- хвост-веер: КРОШЕЧНЫЙ и ОКРУГЛЫЙ (НЕ вилка), основанием заходит в стебель (нахлёст ≥4) -->
<path fill="var(--f3,hsl(38,38%,40%))" d="M44 43 C34 40.5 18 42 14 50 C18 58 34 59.5 44 57 Z"/>
<!-- бахрома СПИННОГО плавника: непрерывная по верхнему краю пластины, 6 мелких лопастей до y≈18 -->
<path fill="var(--f3,hsl(38,38%,40%))" d="M145 42 Q140 29 136 30 Q132 33 128 33 Q123 23 118 23 Q114 27 110 27 Q104 18 100 18.5 Q95 22 92 22 Q87 18 82 18.5 Q78 21 74 21 Q69 19 64 19.5 Q60 23 56 26 Q52 29 48 31 Q44 35 42 38 L40 43 L40 48 C58 42 86 29 116 33 C130 37 140 41 145 44 Z"/>
<!-- бахрома АНАЛЬНОГО плавника: зеркало спинной относительно y=50, лопасти до y≈82 -->
<path fill="var(--f3,hsl(38,38%,40%))" d="M145 58 Q140 71 136 70 Q132 67 128 67 Q123 77 118 77 Q114 73 110 73 Q104 82 100 81.5 Q95 78 92 78 Q87 82 82 81.5 Q78 79 74 79 Q69 81 64 80.5 Q60 77 56 74 Q52 71 48 69 Q44 65 42 62 L40 57 L40 52 C58 58 86 71 116 67 C130 63 140 59 145 56 Z"/>
<!-- тело: ШИРОКООВАЛЬНАЯ пластина (макс. ширина 52 у x≈88, стебель 10), тупое рыло (150,50); контур симметричен y=50 с точностью до контрольных точек -->
<path fill="var(--f1,hsl(40,42%,52%))" d="M40 45 C58 33.5 74 25 88 24 C106 22.8 132 33 148 45.5 C149.6 47 150 48.6 150 50 C150 51.4 149.6 53 148 54.5 C132 67 106 77.2 88 76 C74 75 58 66.5 40 55 C38.6 52 38.6 48 40 45 Z"/>
<!-- лучи бахромы: тёмные f4-штрихи по обеим кромкам (compound-path), приглушены -->
<path fill="none" stroke="var(--f4,hsl(35,40%,24%))" stroke-width="1" opacity="0.3" d="M50 44 L46 32 M64 39 L62 22 M80 33 L80 20 M96 32 L98 20 M110 35 L113 23 M124 39 L127 27 M138 43 L140 32 M50 56 L46 68 M64 61 L62 78 M80 67 L80 80 M96 68 L98 80 M110 65 L113 77 M124 61 L127 73 M138 57 L140 68"/>
<!-- светлые f2-пятна: 3 симметричные пары (compound-path) -->
<path fill="var(--f2,hsl(42,38%,80%))" opacity="0.55" d="M56 40 C62 37 68 40 66 44 C64 47 58 46.5 55 44 C53.5 42 54 40.8 56 40 Z M56 60 C62 63 68 60 66 56 C64 53 58 53.5 55 56 C53.5 58 54 59.2 56 60 Z M94 31 C100 29 105 32 103.5 35.5 C102 39 96 38.5 93.5 36 C92 34 92.5 32 94 31 Z M94 69 C100 71 105 68 103.5 64.5 C102 61 96 61.5 93.5 64 C92 66 92.5 68 94 69 Z M118 41 C122 39.5 126 42 125 44.5 C124 47 119 46.5 117.5 44.5 C116.5 43 117 41.5 118 41 Z M118 59 C122 60.5 126 58 125 55.5 C124 53 119 53.5 117.5 55.5 C116.5 57 117 58.5 118 59 Z"/>
<!-- мрамор: 7 f4-клякс-камуфляж ТОЛЬКО в верхней половине (асимметричный узор), compound-path -->
<path fill="var(--f4,hsl(35,40%,24%))" opacity="0.42" d="M46 42 C50 39.5 55 41 53.5 45 C52 48 46.5 47.5 44.5 45 C43.5 43.5 44 42.5 46 42 Z M64 34 C69 31.5 74 33.5 72.5 37.5 C71 41 65 40 63 37.5 C62 36 62.5 34.8 64 34 Z M82 29 C87 27 92 29.5 90.5 33 C89 36.5 82.5 35.5 80.5 33 C79.5 31.4 80 29.8 82 29 Z M100 32 C105 30 110 32.5 108.5 36 C107 39.5 100.5 38.5 98.5 36 C97.5 34.4 98 33 100 32 Z M116 40 C120 38 124 40.5 123 43.5 C122 46.5 117 46 115.5 43.5 C114.5 42 115 40.5 116 40 Z M74 43 C77.5 41.5 81 43.5 80 46 C79 48.5 74.5 48 73 46 C72.2 44.8 72.8 43.6 74 43 Z M86 40 C90 38.5 93 40.5 92 43 C91 45.5 86.5 45 85 43 C84.2 41.8 84.8 40.6 86 40 Z"/>
<!-- тёмная кромка контура: тонкие f4-линии по спинному и брюшному краю (compound-path, симметричны) -->
<path fill="none" stroke="var(--f4,hsl(35,40%,24%))" stroke-width="1.1" opacity="0.5" d="M40 45 C58 33.5 74 25 88 24 C106 22.8 132 33 148 45.5 M40 55 C58 66.5 74 75 88 76 C106 77.2 132 67 148 54.5"/>
<!-- жаберная пластина: мягкая светлая f2-заливка за головой -->
<path fill="var(--f2,hsl(42,38%,80%))" opacity="0.28" d="M114 38 C120 42.5 120 53.5 114 61 C109.5 53.5 109.5 45 114 38 Z"/>
<!-- жаберная дуга: тёмный серп (зазор от обоих глаз ≥4) -->
<path fill="none" stroke="var(--f4,hsl(35,40%,24%))" stroke-width="1.5" d="M114 38 C120 42.5 120 53.5 114 61"/>
<!-- боковая линия: наджаберная дуга (134,40)→(120,44) + прямая (120,44)→(48,49), compound-path f4 -->
<path fill="none" stroke="var(--f4,hsl(35,40%,24%))" stroke-width="1" opacity="0.5" d="M134 40 C128.5 41 123.5 42.5 120 44 L48 49"/>
<!-- грудной плавник: мягкий f3-эллипс на боку, рисуется ПОСЛЕ тела -->
<ellipse fill="var(--f3,hsl(38,38%,40%))" cx="110" cy="60" rx="11" ry="5.5" transform="rotate(-15 110 60)"/>
<!-- рот: асимметричная тёмная щель у притуплённого рыла (148,52.5) -->
<path fill="var(--f4,hsl(35,40%,24%))" d="M150 51.2 C145.5 51.6 141 52.2 137 53.2 C141.5 54.6 145.5 54.2 149.5 53.4 Z"/>
<!-- глаз передний (140,43): ободок → склера → янтарная радужка → зрачок → блик -->
<circle fill="var(--f4,hsl(35,40%,24%))" cx="140" cy="43" r="5.2"/>
<circle fill="#f7f3e6" cx="140" cy="43" r="4.2"/>
<circle fill="#c08a3e" cx="140" cy="43" r="3.2"/>
<circle fill="#142638" cx="140" cy="43" r="2.2"/>
<circle fill="#fff" cx="138.6" cy="41.6" r="0.9"/>
<!-- глаз задний (128,45.5): рядом с передним, чуть меньше — «двойная клякса» на верхнем краю -->
<circle fill="var(--f4,hsl(35,40%,24%))" cx="128" cy="45.5" r="4.4"/>
<circle fill="#f7f3e6" cx="128" cy="45.5" r="3.5"/>
<circle fill="#c08a3e" cx="128" cy="45.5" r="2.7"/>
<circle fill="#142638" cx="128" cy="45.5" r="1.9"/>
<circle fill="#fff" cx="126.8" cy="44.2" r="0.7"/>
</symbol>
<symbol id="fish-tuna" viewBox="0 0 160 100">
<!-- хвост-полумесяц: верхняя ТОНКАЯ серповидная лопасть, корень (52,46) → кончик (9,21), выемка (34,50) -->
<path fill="var(--f3,hsl(212,34%,38%))" d="M52 46 C36 35 21 26 9 21 C15 33 26 43.5 34 50 Z"/>
<!-- хвост-полумесяц: нижняя ТОНКАЯ серповидная лопасть, зеркало верхней (кончик 9,79) -->
<path fill="var(--f3,hsl(212,34%,38%))" d="M52 54 C36 65 21 74 9 79 C15 67 26 56.5 34 50 Z"/>
<!-- ЗАЛИВКА основания хвоста: закрывает карман между лопастями и стеблем (иначе внутренняя прозрачная «дыра»; силуэт не меняется) -->
<path fill="var(--f3,hsl(212,34%,38%))" d="M52 46 L34 50 L52 54 Z"/>
<!-- D1: маленький передний спинной, осн. x108..122, вершина (115,23.5) -->
<path fill="var(--f3,hsl(212,34%,38%))" d="M108 38 L115 23.5 L122 40 Z"/>
<!-- D2: второй маленький спинной позади D1, осн. x90..104, вершина (97,29) -->
<path fill="var(--f3,hsl(212,34%,38%))" d="M90 37.5 L97 29 L104 38 Z"/>
<!-- 7 финлетов сверху: мелкие треугольники позади D2, к хвосту мельчают, основания утоплены в тело (compound-path) -->
<path fill="var(--f3,hsl(212,34%,38%))" d="M87 37.6 L83 27 L79 37.8 Z M81 37.7 L77 28.5 L73 38.3 Z M75 38.2 L71 30.5 L67 39 Z M69 39 L65 32.5 L61 40.5 Z M63 40.4 L59 35 L55 42.5 Z M57 42.3 L53.5 38 L50 44.5 Z M51 44.5 L48.5 40.5 L46 46.5 Z"/>
<!-- 6 финлетов снизу: под анальным, вдоль брюха, к хвосту мельчают, основания утоплены (compound-path) -->
<path fill="var(--f3,hsl(212,34%,38%))" d="M88 62.8 L84 73 L80 62.8 Z M82 62.6 L78 72 L74 62 Z M76 61.5 L72 70.5 L68 60.3 Z M70 59.5 L66 68 L62 58.2 Z M64 57 L60 65 L56 55.5 Z M58 54 L54 61.5 L50 52.5 Z"/>
<!-- A1: анальный плавник, осн. x90..104, низ (97,74) -->
<path fill="var(--f3,hsl(212,34%,38%))" d="M90 62 L97 74 L104 62.5 Z"/>
<!-- брюшные плавники: пара, осн. x108..118, кончики y72..74 (compound-path) -->
<path fill="var(--f3,hsl(212,34%,38%))" d="M108 61.5 C107 67 108 71 110 72.8 C111.5 69.5 111 65 110.5 61.5 Z M116 61 C115.2 66 116 70 118.2 72.5 C119 69 118.8 65 118.3 60.8 Z"/>
<!-- тело: плотное обтекаемое торпедо (глубина 34.5, D/L≈3.1), рыло (151.5,49), затылок (135,40), спина (98,33), низ брюха (98,67), стебель x46 (45.5/54.5) -->
<path fill="var(--f1,hsl(210,32%,52%))" d="M151.5 49 C147 43 141 39.5 135 40 C121 35.5 109 33.2 98 33 C79 33 60 38 46 45.5 L46 54.5 C60 62 79 67 98 67 C109 67 121 64.5 135 60 C141 60 147 56.5 151.5 51 C152.7 50.6 152.7 49.4 151.5 49 Z"/>
<!-- брюхо: светлое серебро нижней трети (резкая двухцветность тёмная спина / серебро) -->
<path fill="var(--f2,hsl(206,22%,80%))" d="M46 54.5 C60 62 79 67 98 67 C109 67 121 64.5 135 60 C141 60 147 56.5 151.5 51 C146 55.5 139 59 131 61.5 C116 65 100 65.6 84 63.5 C69 61.3 57 58 46 54.5 Z"/>
<!-- спинная кромка: тонкая f4-полоса по верхнему контуру (тёмная спина) -->
<path fill="var(--f4,hsl(212,36%,22%))" d="M151.5 49 C147 43 141 39.5 135 40 C121 35.5 109 33.2 98 33 C79 33 60 38 46 45.5 C59 39.6 78 36 98 36 C110 36 122 38.5 135 43 C141 43.5 147 46.5 151.5 49 Z"/>
<!-- жаберная пластина: мягкая светлая заливка объёма головы -->
<path fill="var(--f2,hsl(206,22%,80%))" opacity="0.3" d="M124 41 C128 45.5 128 55.5 123.5 61 C119.5 55 119.5 45.5 120.5 41.5 Z"/>
<!-- жаберная дуга: тёмный серп у затылка -->
<path fill="none" stroke="var(--f4,hsl(212,36%,22%))" stroke-width="1.5" d="M124 41 C128 45.5 128 55.5 123.5 61"/>
<!-- штрихи-чёрточки: 5 тонких горизонтальных тёмных чёрточек в нижней половине бока (узнаваемый признак тунца, НЕ полосы) -->
<path fill="var(--f4,hsl(212,36%,22%))" d="M120 56.2 L134 56.2 L134 57.5 L120 57.5 Z M100 57.2 L114 57.2 L114 58.5 L100 58.5 Z M80 56.3 L94 56.3 L94 57.6 L80 57.6 Z M62 57.6 L76 57.6 L76 58.9 L62 58.9 Z M86 58.6 L101 58.6 L101 59.9 L86 59.9 Z"/>
<!-- 2 киля на хвостовом стебле: тонкие f4-черты (compound) -->
<path fill="none" stroke="var(--f4,hsl(212,36%,22%))" stroke-width="1.3" d="M46 48.5 L52 48.5 M46 51.5 L52 51.5"/>
<!-- рот: маленькая тёмная щель на конце морды -->
<path fill="var(--f4,hsl(212,36%,22%))" d="M143.5 50.2 C146.5 50.5 148.8 51.4 150.4 52.6 C148.2 53.6 145.6 53.1 144 51.8 Z"/>
<!-- грудной плавник: длинный заострённый, корень (118,54) → кончик (99,63) (ПОСЛЕ тела) -->
<path fill="var(--f3,hsl(212,34%,38%))" d="M118 54 C110 55.5 103 59 99 63 C106 62.5 113 59.5 119 56 Z"/>
<!-- глаз: ободок f4 → склера → янтарная радужка → зрачок → блик -->
<circle fill="var(--f4,hsl(212,36%,22%))" cx="133" cy="42" r="4.6"/>
<circle fill="#f7f3e6" cx="133" cy="42" r="3.7"/>
<circle fill="#c9a24a" cx="133" cy="42" r="3.0"/>
<circle fill="#142638" cx="133" cy="42" r="2.1"/>
<circle fill="#fff" cx="131.9" cy="40.9" r="0.8"/>
</symbol>
<symbol id="fish-swordfish" viewBox="0 0 160 100">
<!-- хвост: полумесяц — верхняя тонкая лопасть, корень утоплен в стебель (нахлёст ≥4), кончик (8,19) -->
<path fill="var(--f3,hsl(250,32%,36%))" d="M43 45.8 C34 38.5 21 28 8 19 C12 30 19 41 26 49.5 C31 48.6 37 47.9 43 47.3 Z"/>
<!-- хвост: полумесяц — нижняя тонкая лопасть, кончик (8,81), выемка у (26,50) -->
<path fill="var(--f3,hsl(250,32%,36%))" d="M43 54.2 C34 61.5 21 72 8 81 C12 70 19 59 26 50.5 C31 51.4 37 52.1 43 52.7 Z"/>
<!-- D1 «парус»: ВЫСОКИЙ серповидный, основание x62..90 утоплено в спину (нахлёст ≥4), ведущая кромка к вершине (80,12), задняя ВОГНУТАЯ к (58,33) — главный силуэтный знак -->
<path fill="var(--f3,hsl(250,32%,36%))" d="M90 43 C88 32.5 85 20 80 12 C73 21 64 29 58 33 C59.5 36.5 60.5 40 62 43 C71 44 81 44 90 43 Z"/>
<!-- D2: маленький задний спинной, сдвинут к хвосту, вершина (51,36.5), основание в теле (нахлёст ≥4) -->
<path fill="var(--f3,hsl(250,32%,36%))" d="M46 47 C47.5 42 49.5 38.2 51 36.5 C53 38.8 55 42 56.5 45.5 Z"/>
<!-- анальный: маленький, сдвинут к хвосту, низ (53,66.5), основание утоплено в брюхо (нахлёст ≥4, верхняя кромка идёт ВЫШЕ линии брюха) -->
<path fill="var(--f3,hsl(250,32%,36%))" d="M46 55.2 C48.6 60.2 51.2 63.9 53.3 66.5 C55.7 63.6 57.8 60.1 59 57.4 Z"/>
<!-- МЕЧ: длинный тонкий клинок f1, основание (122,47.2..52.8) → остриё (159,50), длина ~35 ед.; нарисован ДО тела, чтобы корень скрылся под головой -->
<path fill="var(--f1,hsl(250,28%,52%))" d="M122 47.2 C141 47.5 153 48.9 159 50 C153 51.1 141 52.5 122 52.8 Z"/>
<!-- меч, f4-кромка сверху: тонкая тёмная полоса по верхней грани клинка -->
<path fill="var(--f4,hsl(248,34%,22%))" d="M122 47.2 C141 47.5 153 48.9 159 50 C153 48.9 141 48.1 122 48.4 Z"/>
<!-- тело: удлинённое ~3:1, рыло/перед головы (124,47..52), затылок (106,40.5), спина (80,37), низ брюха (82,63), стебель x38 (45.5/54.5) -->
<path fill="var(--f1,hsl(250,28%,52%))" d="M38 45.5 C52 40 66 37.5 80 37 C92 37 100 38.2 106 40.5 C110.5 40.9 114 40.7 117 42.2 C120 43.8 122.4 45.8 124 48 L124 52 C121 54.5 114 57 106 59 C96 61.5 88 63 82 63 C66 62.5 50 58 38 54.5 Z"/>
<!-- брюхо: светлое серебро вдоль подводной кромки (гладкое, без узора) -->
<path fill="var(--f2,hsl(240,18%,82%))" d="M38 54.5 C50 58 66 62.5 82 63 C88 63 96 61.5 106 59 C114 57 121 54.5 124 52 L124 50.5 C120 52.8 112 55.5 104 57 C94 58.8 84 59.6 74 59.3 C60 58.8 48 55.8 38 52 Z"/>
<!-- спинная кромка: тонкая тёмная f4-полоса по верхнему контуру (не зубцы) -->
<path fill="var(--f4,hsl(248,34%,22%))" d="M38 45.5 C52 40 66 37.5 80 37 C92 37 100 38.2 106 40.5 C110.5 40.9 114 40.7 117 42.2 C120 43.8 122.4 45.8 124 48 L124 49.2 C122.4 47.2 120 45.2 117 43.6 C114 42.1 110.5 42.2 106 42 C100 39.6 92 38.4 80 38.4 C66 39.3 52 42 38 47.2 Z"/>
<!-- кили f4 на стебле (x38..44): тонкие тёмные гребни по верху и низу хвостового стебля, compound-path -->
<path fill="var(--f4,hsl(248,34%,22%))" d="M38 45.5 C40 44.7 42 43.7 44 43.4 L44 45.2 C42 45.3 40 46.2 38 47.2 Z M38 54.5 C40 55.4 42 56.2 44 56.3 L44 54.6 C42 54.5 40 53.6 38 52.7 Z"/>
<!-- жаберная пластина: мягкая светлая заливка головы (объём), отодвинута от ободка глаза на ≥4 -->
<path fill="var(--f2,hsl(240,18%,82%))" opacity="0.3" d="M103 41 C99 44.8 99.8 49 105.5 52.5 C107.8 48.6 106.7 44 106.1 41.2 Z"/>
<!-- жаберная дуга: тонкий тёмный серп у затылка (зазор от ободка глаза ≥4) -->
<path fill="none" stroke="var(--f4,hsl(248,34%,22%))" stroke-width="1.5" d="M103 41 C99 44.8 99.8 49 105.5 52.5"/>
<!-- рот: ШИРОКАЯ ЩЕЛЬ БЕЗ ЗУБОВ (124,50.5)→(112,53.5) вдоль нижней челюсти; верхний правый угол доведён до основания меча (x=124), чтобы не просвечивало брюхо f2 -->
<path fill="var(--f4,hsl(248,34%,22%))" d="M124 50.5 C119.6 51.2 115 52.5 112.2 53.5 C115 54.3 119 54.4 124 54.2 Z"/>
<!-- грудной плавник: узкая серповидная лопасть на боку, корень (101,53) → кончик (89,63) (ПОСЛЕ тела) -->
<path fill="var(--f3,hsl(250,32%,36%))" d="M101.5 53.2 C99.5 57.6 95 61.6 89 63.2 C92.6 58.6 97.2 54.4 100.6 51.6 Z"/>
<!-- глаз: ободок → склера → серая радужка → зрачок → блик (последним) -->
<circle fill="var(--f4,hsl(248,34%,22%))" cx="116" cy="43.5" r="5.2"/>
<circle fill="#f7f3e6" cx="116" cy="43.5" r="4.2"/>
<circle fill="#7d8f9c" cx="116" cy="43.5" r="3.2"/>
<circle fill="#142638" cx="116" cy="43.5" r="2.2"/>
<circle fill="#fff" cx="114.9" cy="42.4" r="0.9"/>
</symbol>
<symbol id="fish-moray" viewBox="0 0 160 100">
<!-- плавниковая складка: ЕДИНАЯ лента шириной ~5, от затылка по спине, вокруг острого хвоста и назад анальной частью — без швов и без отдельного хвостового плавника; тело поверх перекрывает её внутреннюю часть -->
<path fill="var(--f3,hsl(50,40%,30%))" d="M128 35 C122.7 33.5 106.7 31.0 96 31 C85.3 31.0 74.3 33.3 64 35 C53.7 36.7 42.0 39.3 34 41 C26.0 42.7 20.1 43.5 16 45 C11.9 46.5 9.5 48.3 9.5 50 C9.5 51.7 11.3 52.8 16 55 C20.8 57.2 29.7 61.0 38 63 C46.3 65.0 55.7 66.7 66 67 C76.3 67.3 89.7 65.7 100 65 C110.3 64.3 123.3 64.2 128 63 C132.7 61.8 132.7 58.5 128 58 C123.3 57.5 110.3 59.3 100 60 C89.7 60.7 76.3 62.3 66 62 C55.7 61.7 46.3 60.0 38 58 C29.7 56.0 16.7 52.0 16 50 C15.3 48.0 26.0 47.7 34 46 C42.0 44.3 53.7 41.7 64 40 C74.3 38.3 85.3 36.0 96 36 C106.7 36.0 122.7 40.2 128 40 Z"/>
<!-- тело: змеевидная лента, спина (128,40)→(96,36)→(64,40)→(34,46)→(16,50), брюхо (128,58)→(100,60)→(66,62)→(38,58)→(16,50); голова вправо, верхняя челюсть выходит на (152,44) -->
<path fill="var(--f1,hsl(50,38%,44%))" d="M152 44 C149.2 42.8 137.3 41.3 128 40 C118.7 38.7 106.7 36.0 96 36 C85.3 36.0 74.3 38.3 64 40 C53.7 41.7 42.0 44.3 34 46 C26.0 47.7 15.3 48.0 16 50 C16.7 52.0 29.7 56.0 38 58 C46.3 60.0 55.7 61.7 66 62 C76.3 62.3 89.7 60.7 100 60 C110.3 59.3 120.5 60.2 128 58 C135.5 55.8 141.0 49.3 145 47 Z"/>
<!-- брюхо: светлая полоса вдоль нижней кромки, сходит на нет к хвосту и у горла -->
<path fill="var(--f2,hsl(48,28%,70%))" d="M124 54.5 C110 56 90 58 66 58.5 C52 58.7 40 56.5 26 52.5 L24 52.9 C40 57 52 59 66 60.2 C90 60.5 110 58.4 124 56.8 Z"/>
<!-- пасть: зияющая тёмная каверна-капкан от верхней челюсти (151,45) до отведённого кончика нижней (149,62) -->
<path fill="var(--f4,hsl(48,42%,20%))" d="M151.2 45.4 C144 45.5 136 45.9 128 47.4 C131 49.5 136 52.4 141 55.6 C144.5 57.9 147 60.1 148.8 62.2 C151.6 56.4 151.6 50.2 151.2 45.4 Z"/>
<!-- нижняя челюсть: отведена вниз, шарнир (128,46) → кончик (148,62) -->
<path fill="var(--f1,hsl(50,38%,44%))" d="M126 47 C130.5 47.3 135 49 139 51.7 C143.2 54.6 146.4 57.8 148 60.8 C148.7 62.2 147.6 62.9 146.2 62.1 C141.8 58.9 137.2 55.3 132 52.7 C129 51.3 126.2 49.4 125 47.4 C124.7 46.9 125.3 46.8 126 47 Z"/>
<!-- зубы: крупные клыки-капканы — 5 сверху вниз и 5 снизу вверх, одним compound-путём -->
<path fill="#f7f3e6" d="M146.6 45.3 L149.4 45.2 L148 48.8 Z M142.1 45.5 L144.9 45.5 L143.5 49.1 Z M137.6 45.9 L140.4 46 L139 49.6 Z M133.1 46.4 L135.9 46.6 L134.5 50.2 Z M128.9 47.1 L131.7 47.4 L130.3 50.9 Z M130.1 48 L132.9 48.2 L131.5 44.9 Z M134.6 49.2 L137.4 50.2 L136 46.6 Z M139.1 51.7 L141.9 53 L140.5 49.4 Z M143.1 54.6 L145.9 56.3 L144.5 52.7 Z M145.6 57.4 L148.2 59 L147 55.4 Z"/>
<!-- жабра: маленькое f4-отверстие (нора), НЕ дуга -->
<path fill="var(--f4,hsl(48,42%,20%))" d="M124 44 C125.6 44.6 125.6 49.4 124 50 C122.4 49.4 122.4 44.6 124 44 Z"/>
<!-- леопардовые f4-розетки: 6 пятен разного размера вдоль ленты, одним compound-путём -->
<path fill="var(--f4,hsl(48,42%,20%))" d="M111 42 a5 5 0 1 0 10 0 a5 5 0 1 0 -10 0 Z M95.5 52 a4.5 4.5 0 1 0 9 0 a4.5 4.5 0 1 0 -9 0 Z M79 40 a5 5 0 1 0 10 0 a5 5 0 1 0 -10 0 Z M64 52 a4 4 0 1 0 8 0 a4 4 0 1 0 -8 0 Z M48 44 a4 4 0 1 0 8 0 a4 4 0 1 0 -8 0 Z M32.5 54 a3.5 3.5 0 1 0 7 0 a3.5 3.5 0 1 0 -7 0 Z"/>
<!-- f1-ядро розеток: чтобы пятна остались кольцами и не залили ленту одним цветом -->
<path fill="var(--f1,hsl(50,38%,44%))" d="M113.4 42 a2.6 2.6 0 1 0 5.2 0 a2.6 2.6 0 1 0 -5.2 0 Z M97.7 52 a2.3 2.3 0 1 0 4.6 0 a2.3 2.3 0 1 0 -4.6 0 Z M81.4 40 a2.6 2.6 0 1 0 5.2 0 a2.6 2.6 0 1 0 -5.2 0 Z M65.9 52 a2.1 2.1 0 1 0 4.2 0 a2.1 2.1 0 1 0 -4.2 0 Z M49.9 44 a2.1 2.1 0 1 0 4.2 0 a2.1 2.1 0 1 0 -4.2 0 Z M34.2 54 a1.8 1.8 0 1 0 3.6 0 a1.8 1.8 0 1 0 -3.6 0 Z"/>
<!-- глаз: НАМЕРЕННО крошечный (ободок → склера → радужка → зрачок → блик), рисуется последним -->
<circle fill="var(--f4,hsl(48,42%,20%))" cx="136" cy="41" r="3.2"/>
<circle fill="#f4f1e6" cx="136" cy="41" r="2.4"/>
<circle fill="#c9a23a" cx="136" cy="41" r="1.6"/>
<circle fill="#142638" cx="136" cy="41" r="1.1"/>
<circle fill="#fff" cx="135.6" cy="40.5" r="0.45"/>
</symbol>
<symbol id="fish-grouper" viewBox="0 0 160 100">
<!-- хвост: ВЕЕРНЫЙ (не вилка!) — выпуклая внешняя дуга (12,30)→(6,50)→(12,70) без центральной выемки; основание утоплено в стебель (нахлёст ≥4) -->
<path fill="var(--f3,hsl(15,42%,32%))" d="M52 40 C40 35 26 30.5 12 30 C7 36.5 6 42 6 50 C6 58 7 63.5 12 70 C26 69.5 40 65 52 60 Z"/>
<!-- лучи веера: три штриха от основания к наружной дуге -->
<path fill="none" stroke="var(--f4,hsl(12,42%,20%))" stroke-width="0.9" opacity="0.35" d="M46 43 C34 40 23 36 15.5 33 M46 50 C33 49.6 21 49.6 11 50 M46 57 C34 60 23 64 15.5 67"/>
<!-- спинной КОЛЮЧИЙ: длинный зубчатый гребень x54..126, 9 шипов и 8 выемок (высота 12–16 над спиной), основание глубоко в теле (нахлёст ≥4) -->
<path fill="var(--f3,hsl(15,42%,32%))" d="M52 50 L54.5 40 L57 23 L61.5 34 L65 17 L69.5 31.5 L73 15.5 L77.5 30 L81 13.8 L85.5 28.5 L89 13 L93.5 28 L97 12.6 L101.5 28 L105 12 L109.5 28.5 L113.5 14.5 L117.5 30.5 L121.5 17 L126 32.5 L128 50 Z"/>
<!-- анальный плавник: лопасть x62..84, основание утоплено в брюхо (нахлёст ≥4) -->
<path fill="var(--f3,hsl(15,42%,32%))" d="M62 65 C63 76 66.5 83 72.5 84 C78.5 82.5 83 75.5 84 65 Z"/>
<!-- брюшной плавник 1: пара у (92,72) -->
<path fill="var(--f3,hsl(15,42%,32%))" d="M90 67 C88.5 75 89.5 82 93 84.5 C96.5 80.5 97 73 96 67 Z"/>
<!-- брюшной плавник 2: пара к первому -->
<path fill="var(--f3,hsl(15,42%,32%))" d="M99 67 C98 75.5 99 82.5 102.5 84.5 C105.5 80 106 73 105 67 Z"/>
<!-- тело: массивное, высокое (D/L≈0.5), длинный высокий горбатый профиль; рыло (150,50), лоб (140,34), горб (106,25), спина (84,26)→(64,30), стебель (46,45)/(46,57), низ (150,52)→(132,60)→(110,70)→(80,74)→(56,70) -->
<path fill="var(--f1,hsl(15,40%,46%))" d="M150 50 C148.5 42 145 36.5 140 34 C133.5 31 120 26 106 25 C98.5 24.4 90.5 25.2 84 26 C76 27 69.5 28.6 64 30 C56.5 32.5 50 38 46 45 L46 57 C50 64.5 53 67.8 56 70 C64.5 73.2 72.5 74 80 74 C97 74.6 104.5 72.4 110 70 C118.5 66.8 126.5 62.8 132 60 C141 55.8 146.5 53.2 150 52 Z"/>
<!-- брюхо: светлая нижняя полоса -->
<path fill="var(--f2,hsl(18,28%,72%))" d="M46 57 C56 64.5 70 70.5 84 71.5 C100 72.5 118 68.5 132 60 C141 55.8 146.5 53.2 150 52 C143 54.6 136 57.6 129 60.5 C119 64.5 108 66.6 96 67 C76 67.6 59 62.5 46 57 Z"/>
<!-- спинная кромка f4: тёмная зубчатая полоса по вершинам шипов, у ГОРБА толще прочих (≈4.5 против ≈2.5) -->
<path fill="var(--f4,hsl(12,42%,20%))" d="M54.5 40 L57 23 L61.5 34 L65 17 L69.5 31.5 L73 15.5 L77.5 30 L81 13.8 L85.5 28.5 L89 13 L93.5 28 L97 12.6 L101.5 28 L105 12 L109.5 28.5 L113.5 14.5 L117.5 30.5 L121.5 17 L126 32.5 L126 35 L121.5 20 L117.5 33.5 L113.5 18.5 L109.5 33 L105 16.5 L101.5 33 L97 16.6 L93.5 32 L89 17 L85.5 32 L81 17.8 L77.5 33.5 L73 19.5 L69.5 35 L65 21 L61.5 37.5 L57 25.5 L54.5 43 Z"/>
<!-- жаберная пластина: мягкая светлая заливка (126,40)…(124,64) -->
<path fill="var(--f2,hsl(18,28%,72%))" opacity="0.3" d="M126 40 C130 48 129 57 124 64 C120.5 56 120 47.5 121.5 41 Z"/>
<!-- жаберная дуга: тёмный серп у основания головы (не задевает ободок глаза) -->
<path fill="none" stroke="var(--f4,hsl(12,42%,20%))" stroke-width="1.5" d="M126 40 C130 48 129 57 124 64"/>
<!-- спинная кромка головы: тонкая тёмная полоса от рыла по лбу (переходит в зубчатый гребень) -->
<path fill="var(--f4,hsl(12,42%,20%))" d="M150 49.5 C148 41.5 144 35.5 139.5 33.8 C135 32 130.5 33.5 126.5 36 C131 33.8 135.5 33.2 139.8 35 C144 36.9 148.2 42.5 150 50 Z"/>
<!-- тёмные неправильные РАЗВОДЫ (7 клякс одним compound-path — НЕ вертикальные полосы) -->
<path fill="var(--f4,hsl(12,42%,20%))" opacity="0.85" d="M115 40 C115 37.5 117 36.2 119.5 37 C122 37.8 124 38 124 40 C124 42.4 121.5 44 119.5 43.2 C117.5 42.4 115 42.5 115 40 Z M96.5 50 C96.5 46.4 99.5 44.6 103 45.6 C106.5 46.6 107 47.4 107 50 C107 53.4 103.5 55.4 100.5 54.4 C97.5 53.4 96.5 53.6 96.5 50 Z M79.5 34 C79.5 31.6 81.6 30.4 84 31.2 C86.4 32 87 32.2 87 34 C87 35.8 84.8 37.2 82.4 36.4 C80 35.6 79.5 36.4 79.5 34 Z M65 58 C65 55 67.4 53.8 70.4 54.8 C73.4 55.8 74 56 74 58 C74 60.4 71.4 61.8 68.6 60.8 C65.8 59.8 65 61 65 58 Z M54 44 C54 42.2 55.4 41.2 57 41.8 C58.6 42.4 59 42.6 59 44 C59 45.4 57.2 46.4 55.4 45.8 C53.6 45.2 54 46 54 44 Z M89.5 64 C89.5 62 91.4 61 94 61.6 C96.6 62.2 97 62.4 97 64 C97 65.6 94.8 66.8 92.4 66 C90 65.2 89.5 66 89.5 64 Z M72.5 44 C72.5 42.8 73.4 42.2 74.6 42.6 C75.8 43 76 43.2 76 44 C76 44.8 74.8 45.6 73.6 45.2 C72.4 44.8 72.5 45.2 72.5 44 Z"/>
<!-- пасть: крупная тёмная полоса нутра от рыла (150,48.5) назад-вниз; нижняя кромка чуть перекрывает верх нижней челюсти (нахлёст), чтобы не просвечивал фон -->
<path fill="var(--f4,hsl(12,42%,20%))" d="M150 48.5 C141.5 50.2 130.5 53.5 121 57.5 C131 60.5 143.5 58.8 151.5 53.8 Z"/>
<!-- нижняя челюсть: светлая f2-кромка, ВЫДАЁТСЯ вперёд до (152,57) за верхнюю челюсть -->
<path fill="var(--f2,hsl(18,28%,72%))" d="M151.5 53.8 C143.5 57.6 132 60.4 121 58.8 C131 62.6 145 60.6 152 57 Z"/>
<!-- зубы (фикс-акцент): compound-path из четырёх треугольников с верхней челюсти -->
<path fill="#f7f3e6" d="M143.5 50 L146 49.7 L144.7 52.8 Z M137.5 51.4 L140 51.1 L138.7 54.2 Z M131.5 52.9 L134 52.6 L132.7 55.7 Z M125.5 54.5 L128 54.2 L126.7 57.3 Z"/>
<!-- грудной плавник: округлая лопасть на боку под жаберной дугой (122,61), вниз-назад, рисуется ПОСЛЕ тела -->
<path fill="var(--f3,hsl(15,42%,32%))" d="M122.5 59 C118.5 61.5 114 66.5 113 72 C116 72.5 121 69.5 123 65 C124 62.5 123.5 60 122.5 59 Z"/>
<!-- глаз: ободок → склера → радужка → зрачок → блик (последним) -->
<circle fill="var(--f4,hsl(12,42%,20%))" cx="132" cy="44" r="6"/>
<circle fill="#f7f3e6" cx="132" cy="44" r="5"/>
<circle fill="#d9b23a" cx="132" cy="44" r="3.6"/>
<circle fill="#142638" cx="132" cy="44" r="2.5"/>
<circle fill="#fff" cx="130.9" cy="42.8" r="1"/>
</symbol>
<symbol id="fish-turtle" viewBox="0 0 160 100">
<!-- передние ласты-вёсла f3: корень у панциря → заметный «локоть» (~132,30) → широкий кончик с округлым краем; верхняя и нижняя зеркальны -->
<path fill="var(--f3,hsl(145,34%,30%))" d="M109 36 C117 33 124 30.5 129.5 27.5 C136 23.5 143 19.5 149.5 16.5 C151.5 18.5 151 22 148 24.5 C142 28.5 134 32.5 127 36 C121 39 115 41.5 109 43 Z M109 64 C117 67 124 69.5 129.5 72.5 C136 76.5 143 80.5 149.5 83.5 C151.5 81.5 151 78 148 75.5 C142 71.5 134 67.5 127 64 C121 61 115 58.5 109 57 Z"/>
<!-- задние ласты-вёсла f3: короткие, широкие у округлого кончика (лопатка, не шип) -->
<path fill="var(--f3,hsl(145,34%,30%))" d="M46 40.5 C38 37.5 29 33.8 22 31.3 C18.5 30 15.5 31.3 15.2 33.8 C15 36.3 17.5 38 21.5 38.6 C29.5 39.7 38.5 42.9 46 45.2 Z M46 59.5 C38 62.5 29 66.2 22 68.7 C18.5 70 15.5 68.7 15.2 66.2 C15 63.7 17.5 62 21.5 61.4 C29.5 60.3 38.5 57.1 46 54.8 Z"/>
<!-- хвостик f3: короткий, сужается назад -->
<path fill="var(--f3,hsl(145,34%,30%))" d="M35 46.6 C28 46.6 22 47.4 16 50 C22 52.6 28 53.4 35 53.4 Z"/>
<!-- карапакс: овальный панцирь f2 с чуть сужённым передом (перед — вправо, к голове) -->
<path fill="var(--f2,hsl(90,20%,70%))" d="M30 50 C30 35 52 23 74 23 C99 23 117.5 36 119 50 C117.5 64 99 77 74 77 C52 77 30 65 30 50 Z"/>
<!-- кромочный f4-контур карапакса -->
<path fill="none" stroke="var(--f4,hsl(140,42%,20%))" stroke-width="1" opacity="0.75" d="M30 50 C30 35 52 23 74 23 C99 23 117.5 36 119 50 C117.5 64 99 77 74 77 C52 77 30 65 30 50 Z"/>
<!-- тело карапакса f1 (вложено в f2-рим) -->
<path fill="var(--f1,hsl(140,36%,42%))" d="M32 50 C32 36 53 25 74 25 C98 25 115.5 37 117 50 C115.5 63 98 75 74 75 C53 75 32 64 32 50 Z"/>
<!-- 5 вертебральных щитков по оси: compound-path f4-контуров (шестиугольники 13×15, x=54,68,82,96,110) -->
<path fill="none" stroke="var(--f4,hsl(140,42%,20%))" stroke-width="1.2" opacity="0.85" d="M47.5 50 L50.75 42.5 L57.25 42.5 L60.5 50 L57.25 57.5 L50.75 57.5 Z M61.5 50 L64.75 42.5 L71.25 42.5 L74.5 50 L71.25 57.5 L64.75 57.5 Z M75.5 50 L78.75 42.5 L85.25 42.5 L88.5 50 L85.25 57.5 L78.75 57.5 Z M89.5 50 L92.75 42.5 L99.25 42.5 L102.5 50 L99.25 57.5 L92.75 57.5 Z M103.5 50 L106.75 42.5 L113.25 42.5 L116.5 50 L113.25 57.5 L106.75 57.5 Z"/>
<!-- 6 костальных щитков (по 3 на сторону): compound-path f4-контуров -->
<path fill="none" stroke="var(--f4,hsl(140,42%,20%))" stroke-width="1.2" opacity="0.85" d="M47 36.5 L52 30.5 L62 30.5 L67 36.5 L62 42.5 L52 42.5 Z M70 36.5 L75 30.5 L85 30.5 L90 36.5 L85 42.5 L75 42.5 Z M93 38 L96.5 33.5 L103.5 33.5 L107 38 L103.5 42.5 L96.5 42.5 Z M47 63.5 L52 69.5 L62 69.5 L67 63.5 L62 57.5 L52 57.5 Z M70 63.5 L75 69.5 L85 69.5 L90 63.5 L85 57.5 L75 57.5 Z M93 62 L96.5 66.5 L103.5 66.5 L107 62 L103.5 57.5 L96.5 57.5 Z"/>
<!-- бледные f2-блики в центре щитков: compound-path ромбиков -->
<path fill="var(--f2,hsl(90,20%,70%))" opacity="0.6" d="M54 46 L57.5 50 L54 54 L50.5 50 Z M68 46 L71.5 50 L68 54 L64.5 50 Z M82 46 L85.5 50 L82 54 L78.5 50 Z M96 46 L99.5 50 L96 54 L92.5 50 Z M110 46 L113.5 50 L110 54 L106.5 50 Z M57 32.5 L61.5 36.5 L57 40.5 L52.5 36.5 Z M80 32.5 L84.5 36.5 L80 40.5 L75.5 36.5 Z M100 34 L104.5 38 L100 42 L95.5 38 Z M57 59.5 L61.5 63.5 L57 67.5 L52.5 63.5 Z M80 59.5 L84.5 63.5 L80 67.5 L75.5 63.5 Z M100 58 L104.5 62 L100 66 L95.5 62 Z"/>
<!-- маргинальные щитки: короткие f4-засечки по задней кромке, compound-path -->
<path fill="none" stroke="var(--f4,hsl(140,42%,20%))" stroke-width="1.1" opacity="0.7" d="M35.5 36.5 L38.8 38.1 M31 43.2 L34.6 43.9 M30 50 L33.6 50 M31 56.8 L34.6 56.1 M35.5 63.5 L38.8 61.9"/>
<!-- шея: светлое f2-пятно между панцирем и головой -->
<path fill="var(--f2,hsl(90,20%,70%))" d="M106 45 C112 44 118 46 121 50 C118 54 112 56 106 55 Z"/>
<!-- голова f1, вытянута вправо -->
<path fill="var(--f1,hsl(140,36%,42%))" d="M116 50 C116 43.5 121 40 130 40 C139.5 40 145.5 44 148 50 C145.5 56 139.5 60 130 60 C121 60 116 56.5 116 50 Z"/>
<!-- клюв f4: тёмный клин -->
<path fill="var(--f4,hsl(140,42%,20%))" d="M146 46 L150 50 L146 54 Z"/>
<!-- глаза (2, вид сверху — по бокам головы): f4-кольцо → склера → зрачок → блик -->
<path fill="var(--f4,hsl(140,42%,20%))" d="M125.2 43 a2.8 2.8 0 1 0 5.6 0 a2.8 2.8 0 1 0 -5.6 0 M125.2 57 a2.8 2.8 0 1 0 5.6 0 a2.8 2.8 0 1 0 -5.6 0"/>
<path fill="#f4f1e6" d="M126 43 a2 2 0 1 0 4 0 a2 2 0 1 0 -4 0 M126 57 a2 2 0 1 0 4 0 a2 2 0 1 0 -4 0"/>
<path fill="#142638" d="M126.7 43 a1.3 1.3 0 1 0 2.6 0 a1.3 1.3 0 1 0 -2.6 0 M126.7 57 a1.3 1.3 0 1 0 2.6 0 a1.3 1.3 0 1 0 -2.6 0"/>
<path fill="#fff" d="M127.6 42.6 a0.4 0.4 0 1 0 0.8 0 a0.4 0.4 0 1 0 -0.8 0 M127.6 57.4 a0.4 0.4 0 1 0 0.8 0 a0.4 0.4 0 1 0 -0.8 0"/>
</symbol>
<symbol id="fish-angler" viewBox="0 0 160 100">
<!-- хвост: КРОШЕЧНЫЙ «веер» (антипод большому хвосту групера), корень (40,50) утоплен в тело (нахлёст ≥4) -->
<path fill="var(--f3,hsl(282,38%,28%))" d="M40 40 C34 36 30 40 30 50 C30 60 34 64 40 60 C43 55 43 45 40 40 Z"/>
<!-- хвост: 3 тёмных луча внутри крошечной лопасти -->
<path fill="none" stroke="var(--f4,hsl(280,40%,18%))" stroke-width="1" opacity="0.4" d="M40 43 L33 40 M40 50 L32 50 M40 57 L33 60"/>
<!-- спинной плавник: колючий бугор (пик ~66,17), основание глубоко в спине (нахлёст ≥4) -->
<path fill="var(--f3,hsl(282,38%,28%))" d="M48 38 C52 24 60 17 68 17 C78 17 86 24 90 36 C78 28 60 29 48 38 Z"/>
<!-- брюшные плавники: пара мягких лопастей под брюхом, основания утоплены в тело -->
<path fill="var(--f3,hsl(282,38%,28%))" d="M84 80 C82 87 84 92 89 90 C92 88 92 83 91 80 Z"/>
<path fill="var(--f3,hsl(282,38%,28%))" d="M94 80 C92 87 94 92 99 90 C102 88 101 83 100 80 Z"/>
<!-- тело: ШАРОВИДНЫЙ «пузырь» (центр ~85,54; ry≈31), голова справа без шеи, рыло (133,54) -->
<path fill="var(--f1,hsl(282,32%,40%))" d="M36 54 C36 34 56 23 84 23 C113 23 134 36 134 54 C134 62 132 70 128 75 C122 81 110 85 88 85 C58 85 36 73 36 54 Z"/>
<!-- брюхо: светлая нижняя полоса вдоль всего «пузыря» -->
<path fill="var(--f2,hsl(285,22%,68%))" d="M36 54 C36 73 58 85 88 85 C110 85 122 81 128 75 C126 77 118 80 106 81 C84 83 56 74 36 54 Z"/>
<!-- узор: 3 тёмные кляксы на боку (сбивают «гладкий шар») -->
<path fill="var(--f4,hsl(280,40%,18%))" opacity="0.22" d="M58 57 C64 54 70 57 68 62 C66 67 57 66 55 61 C54 58 55 57 58 57 Z"/>
<path fill="var(--f4,hsl(280,40%,18%))" opacity="0.2" d="M76 46 C82 43 88 47 86 52 C84 57 74 55 73 50 C72 47 73 46 76 46 Z"/>
<path fill="var(--f4,hsl(280,40%,18%))" opacity="0.24" d="M74 60 C80 57 86 61 84 66 C82 71 73 69 72 64 C71 61 71 60 74 60 Z"/>
<!-- колючая кожа: 7 мелких f4-треугольников по спине и брюху (один compound-path) -->
<path fill="var(--f4,hsl(280,40%,18%))" d="M44 37 L45 29 L48.5 36 Z M98 25 L99.5 17 L102.5 24 Z M105 27 L107 19 L110 26 Z M48 74 L48.5 81 L52.5 75 Z M60 80 L61.5 87 L65.5 81 Z M108 80 L109.5 87 L113.5 81 Z M123 70 L125.5 76.5 L128.5 71 Z"/>
<!-- колючий спинной бугор: 4 f4-шипа над лопастью (compound-path) -->
<path fill="var(--f4,hsl(280,40%,18%))" d="M54 25 L56 15 L60 23 Z M63 20 L66 11 L70 19 Z M73 19 L77 11 L80 20 Z M83 22 L87 15 L88.5 24 Z"/>
<!-- пасть: ОГРОМНОЕ тёмное нутро — шарнир (110,50), верхняя губа (134,58), нижняя челюсть (128,74) -->
<path fill="var(--f4,hsl(280,40%,18%))" d="M110 51 C121 52 129 54 134 58 C133 64 131 70 128 74 C119 71 110 63 105 56 C103 52 106 50 110 51 Z"/>
<!-- верхняя губа: светлая f2-кромка по верхнему контуру пасти -->
<path fill="var(--f2,hsl(285,22%,68%))" d="M109 50 C120 50.5 129 53 134.5 57.5 C131.5 54.5 121 51.5 110.5 51.5 Z"/>
<!-- зубы верхней челюсти: compound-path, 4 треугольника вниз (фикс-акцент) -->
<path fill="#f7f3e6" d="M113 51 L117 52 L114.5 56 Z M119 52.5 L123 53.5 L120.5 57.5 Z M125 54.5 L129 55.5 L126.5 59.5 Z M131 56.5 L134 57.5 L131.5 61 Z"/>
<!-- зубы нижней челюсти: compound-path, 4 треугольника вверх (фикс-акцент) -->
<path fill="#f7f3e6" d="M130 70 L125 69 L127.5 65.5 Z M124 69 L119 67.5 L121.5 63.5 Z M118 67.5 L113 65.5 L115.5 61.5 Z M113.5 65.5 L110 63.5 L112 59.5 Z"/>
<!-- грудной плавник: свисает с бока у основания головы (ПОСЛЕ тела), корень (104,65) утоплен в тело → кончик (115,86) -->
<path fill="var(--f3,hsl(282,38%,28%))" d="M104 64 C111 65 117 74 116 86 C109 85 103 76 102.5 68 C102 65 102 63.5 104 64 Z"/>
<!-- «удочка» (иллиций): f4-штрих от лба (112,28) дугой вперёд-вверх к (128,6) -->
<path fill="none" stroke="var(--f4,hsl(280,40%,18%))" stroke-width="2.6" stroke-linecap="round" d="M112 28 C110 16 116 7 128 6"/>
<!-- эска: подложка свечения — закрывает просвет между римом (внутренний край r=6) и шаром r=5 (иначе фон карточки просвечивал тёмным кольцом) -->
<circle fill="#dff8ff" cx="130" cy="7" r="6"/>
<!-- эска: тонкий светящийся рим -->
<circle fill="none" stroke="#8fe8ff" stroke-width="1" cx="130" cy="7" r="6.5"/>
<!-- эска: светящаяся приманка -->
<circle fill="#dff8ff" cx="130" cy="7" r="5"/>
<!-- эска: белое ядро -->
<circle fill="#ffffff" cx="130" cy="7" r="2.6"/>
<!-- глаз: НАМЕРЕННО КРОШЕЧНЫЙ (антипод крупному глазу групера) — 5 кругов последними -->
<circle fill="var(--f4,hsl(280,40%,18%))" cx="120" cy="44" r="2.8"/>
<circle fill="#f4f1e6" cx="120" cy="44" r="2"/>
<circle fill="#c9a23a" cx="120" cy="44" r="1.4"/>
<circle fill="#142638" cx="120" cy="44" r="0.9"/>
<circle fill="#fff" cx="119.3" cy="43.3" r="0.4"/>
</symbol>
<symbol id="fish-octopus" viewBox="0 0 160 100">
<!-- мантия-мешок f1: широкое основание у головы, сужение к правому кончику (150,50); симметрично y=50 -->
<path fill="var(--f1,hsl(350,40%,48%))" d="M96 26C112 25 130 30 143 39C149 43 151 47 150 50C151 53 149 57 143 61C130 70 112 75 96 74C90 70 90 30 96 26Z"/>
<!-- тёмная кромка f3 по верхнему и нижнему краю мантии (парный compound, тонкая, симметрична) -->
<path fill="var(--f3,hsl(350,42%,30%))" d="M96 28C112 27 130 31.5 143 40C148 43 151 47 150 50C143 44.5 132 39 120 36C113 34.5 105 33 96 32ZM96 72C112 73 130 68.5 143 60C148 57 151 53 150 50C143 55.5 132 61 120 64C113 65.5 105 67 96 68Z"/>
<!-- светлый срединный гребень f2 по мантии (симметричен y=50, сужен с обоих концов) -->
<path fill="var(--f2,hsl(348,24%,72%))" d="M104 47.6C118 46.6 133 48 146.5 50C133 52 118 53.4 104 52.4C101.4 51.2 101.4 48.8 104 47.6Z"/>
<!-- сифон f4: короткая трубка из-под головы вниз-влево -->
<path fill="var(--f4,hsl(350,44%,20%))" d="M94 57C90 61 86.5 64.5 84 68C82.6 70 84 71.6 85.8 70.4C88.5 68 91 63.5 95 58Z"/>
<!-- веб f3: лопасти мембраны в просветах между основаниями рук (симметричен y=50) -->
<path fill="var(--f3,hsl(350,42%,30%))" d="M91 41.4C72.8 39.4 53.56 36.9 39 42.4C53.56 47.9 72.8 45.4 91 43.4ZM91 56.6C72.8 54.6 53.56 52.1 39 57.6C53.56 63.1 72.8 60.6 91 58.6ZM91 44.3C74.9 42.3 57.88 39.8 45 45.3C57.88 50.8 74.9 48.3 91 46.3ZM91 53.7C74.9 51.7 57.88 49.2 45 54.7C57.88 60.2 74.9 57.7 91 55.7ZM91 46.8C78.4 44.8 65.08 42.3 55 47.8C65.08 53.3 78.4 50.8 91 48.8ZM91 51.2C78.4 49.2 65.08 46.7 55 52.2C65.08 57.7 78.4 55.2 91 53.2Z"/>
<!-- заплатки стыков (закрывают микро-щели с фоном: веб→голова по центру y=50 и голова→сифон/щупальца); рисуются ДО щупалец/головы, чтобы те перекрыли излишки -->
<rect fill="var(--f3,hsl(350,42%,30%))" x="82" y="49.4" width="3.4" height="1.2"/>
<ellipse fill="var(--f1,hsl(350,40%,48%))" cx="89.5" cy="60.9" rx="0.8" ry="0.8"/>
<!-- 8 щупалец f1 веером: compound из 8 зеркальных рук с подкрученными кончиками -->
<path fill="var(--f1,hsl(350,40%,48%))" d="M90.42 37.21L86.13 34.61L81.91 32.18L77.77 29.89L73.71 27.77L69.74 25.79L65.88 23.98L62.12 22.32L58.48 20.81L54.96 19.46L51.57 18.27L48.32 17.24L45.22 16.36L42.27 15.65L39.49 15.1L36.87 14.72L34.43 14.51L32.17 14.49L30.1 14.66L28.26 15.08L27 17L27 17L28.66 18.47L30.17 18.74L31.88 19.06L33.8 19.49L35.91 20.03L38.22 20.7L40.71 21.5L43.37 22.44L46.2 23.51L49.18 24.73L52.31 26.09L55.57 27.59L58.96 29.23L62.48 31.02L66.1 32.96L69.83 35.03L73.65 37.26L77.55 39.62L81.53 42.14L85.58 44.79ZM 90.42 62.79 L 86.13 65.39 L 81.91 67.82 L 77.77 70.11 L 73.71 72.23 L 69.74 74.21 L 65.88 76.02 L 62.12 77.68 L 58.48 79.19 L 54.96 80.54 L 51.57 81.73 L 48.32 82.76 L 45.22 83.64 L 42.27 84.35 L 39.49 84.9 L 36.87 85.28 L 34.43 85.49 L 32.17 85.51 L 30.1 85.34 L 28.26 84.92 L 27 83 L 27 83 L 28.66 81.53 L 30.17 81.26 L 31.88 80.94 L 33.8 80.51 L 35.91 79.97 L 38.22 79.3 L 40.71 78.5 L 43.37 77.56 L 46.2 76.49 L 49.18 75.27 L 52.31 73.91 L 55.57 72.41 L 58.96 70.77 L 62.48 68.98 L 66.1 67.04 L 69.83 64.97 L 73.65 62.74 L 77.55 60.38 L 81.53 57.86 L 85.58 55.21 ZM89.87 39.9L85.82 38.2L81.75 36.6L77.69 35.12L73.64 33.74L69.61 32.48L65.61 31.32L61.65 30.27L57.75 29.32L53.91 28.49L50.16 27.76L46.49 27.13L42.92 26.61L39.46 26.2L36.12 25.9L32.92 25.7L29.87 25.62L26.97 25.67L24.25 25.84L21.72 26.19L19.5 28L19.5 28L21.83 29.6L24.23 29.92L26.79 30.25L29.52 30.63L32.4 31.08L35.43 31.6L38.58 32.2L41.86 32.88L45.24 33.64L48.72 34.49L52.28 35.44L55.91 36.47L59.61 37.59L63.35 38.81L67.13 40.12L70.93 41.52L74.74 43.02L78.56 44.62L82.36 46.31L86.13 48.1ZM 89.87 60.1 L 85.82 61.8 L 81.75 63.4 L 77.69 64.88 L 73.64 66.26 L 69.61 67.52 L 65.61 68.68 L 61.65 69.73 L 57.75 70.68 L 53.91 71.51 L 50.16 72.24 L 46.49 72.87 L 42.92 73.39 L 39.46 73.8 L 36.12 74.1 L 32.92 74.3 L 29.87 74.38 L 26.97 74.33 L 24.25 74.16 L 21.72 73.81 L 19.5 72 L 19.5 72 L 21.83 70.4 L 24.23 70.08 L 26.79 69.75 L 29.52 69.37 L 32.4 68.92 L 35.43 68.4 L 38.58 67.8 L 41.86 67.12 L 45.24 66.36 L 48.72 65.51 L 52.28 64.56 L 55.91 63.53 L 59.61 62.41 L 63.35 61.19 L 67.13 59.88 L 70.93 58.48 L 74.74 56.98 L 78.56 55.38 L 82.36 53.69 L 86.13 51.9 ZM89.27 42.48L85.22 41.42L81.12 40.44L76.99 39.56L72.85 38.77L68.7 38.08L64.54 37.47L60.41 36.96L56.3 36.54L52.22 36.21L48.2 35.98L44.23 35.83L40.33 35.78L36.52 35.83L32.8 35.97L29.19 36.21L25.7 36.56L22.34 37.01L19.13 37.59L16.09 38.33L13.5 40.5L13.5 40.5L16.62 41.7L19.63 41.64L22.76 41.58L26.01 41.57L29.39 41.61L32.87 41.71L36.45 41.89L40.12 42.13L43.87 42.45L47.68 42.85L51.54 43.32L55.45 43.87L59.38 44.5L63.33 45.2L67.29 45.99L71.24 46.85L75.17 47.8L79.07 48.83L82.93 49.93L86.73 51.12ZM 89.27 57.52 L 85.22 58.58 L 81.12 59.56 L 76.99 60.44 L 72.85 61.23 L 68.7 61.92 L 64.54 62.53 L 60.41 63.04 L 56.3 63.46 L 52.22 63.79 L 48.2 64.02 L 44.23 64.17 L 40.33 64.22 L 36.52 64.17 L 32.8 64.03 L 29.19 63.79 L 25.7 63.44 L 22.34 62.99 L 19.13 62.41 L 16.09 61.67 L 13.5 59.5 L 13.5 59.5 L 16.62 58.3 L 19.63 58.36 L 22.76 58.42 L 26.01 58.43 L 29.39 58.39 L 32.87 58.29 L 36.45 58.11 L 40.12 57.87 L 43.87 57.55 L 47.68 57.15 L 51.54 56.68 L 55.45 56.13 L 59.38 55.5 L 63.33 54.8 L 67.29 54.01 L 71.24 53.15 L 75.17 52.2 L 79.07 51.17 L 82.93 50.07 L 86.73 48.88 ZM88.36 45.62L84.73 45.27L81.1 44.96L77.49 44.69L73.89 44.45L70.33 44.25L66.79 44.08L63.29 43.94L59.83 43.84L56.43 43.76L53.08 43.72L49.79 43.72L46.56 43.74L43.41 43.79L40.34 43.88L37.36 43.99L34.47 44.15L31.67 44.33L28.98 44.57L26.4 44.88L24 46.4L24 46.4L26.52 47.7L29.09 47.82L31.76 47.92L34.53 48L37.39 48.09L40.34 48.2L43.38 48.31L46.49 48.45L49.68 48.6L52.92 48.78L56.23 48.97L59.59 49.19L63 49.44L66.44 49.71L69.92 50.02L73.43 50.35L76.97 50.71L80.51 51.1L84.07 51.52L87.64 51.98ZM 88.36 54.38 L 84.73 54.73 L 81.1 55.04 L 77.49 55.31 L 73.89 55.55 L 70.33 55.75 L 66.79 55.92 L 63.29 56.06 L 59.83 56.16 L 56.43 56.24 L 53.08 56.28 L 49.79 56.28 L 46.56 56.26 L 43.41 56.21 L 40.34 56.12 L 37.36 56.01 L 34.47 55.85 L 31.67 55.67 L 28.98 55.43 L 26.4 55.12 L 24 53.6 L 24 53.6 L 26.52 52.3 L 29.09 52.18 L 31.76 52.08 L 34.53 52 L 37.39 51.91 L 40.34 51.8 L 43.38 51.69 L 46.49 51.55 L 49.68 51.4 L 52.92 51.22 L 56.23 51.03 L 59.59 50.81 L 63 50.56 L 66.44 50.29 L 69.92 49.98 L 73.43 49.65 L 76.97 49.29 L 80.51 48.9 L 84.07 48.48 L 87.64 48.02 Z"/>
<!-- присоски: контуры f4 (compound, 2 ряда на 4 ближних руках, 16 кружков) -->
<path fill="none" stroke="var(--f4,hsl(350,44%,20%))" stroke-width="0.55" d="M66.99 42.97a1.35 1.35 0 1 0 2.7 0a1.35 1.35 0 1 0 -2.7 0M67.37 40.8a1.35 1.35 0 1 0 2.7 0a1.35 1.35 0 1 0 -2.7 0M46.3 40.39a1.35 1.35 0 1 0 2.7 0a1.35 1.35 0 1 0 -2.7 0M46.45 38.2a1.35 1.35 0 1 0 2.7 0a1.35 1.35 0 1 0 -2.7 0M69.34 48.18a1.35 1.35 0 1 0 2.7 0a1.35 1.35 0 1 0 -2.7 0M69.5 45.98a1.35 1.35 0 1 0 2.7 0a1.35 1.35 0 1 0 -2.7 0M51.65 47.31a1.35 1.35 0 1 0 2.7 0a1.35 1.35 0 1 0 -2.7 0M51.72 45.11a1.35 1.35 0 1 0 2.7 0a1.35 1.35 0 1 0 -2.7 0M66.99 57.03a1.35 1.35 0 1 0 2.7 0a1.35 1.35 0 1 0 -2.7 0M67.37 59.2a1.35 1.35 0 1 0 2.7 0a1.35 1.35 0 1 0 -2.7 0M46.3 59.61a1.35 1.35 0 1 0 2.7 0a1.35 1.35 0 1 0 -2.7 0M46.45 61.8a1.35 1.35 0 1 0 2.7 0a1.35 1.35 0 1 0 -2.7 0M69.34 51.82a1.35 1.35 0 1 0 2.7 0a1.35 1.35 0 1 0 -2.7 0M69.5 54.02a1.35 1.35 0 1 0 2.7 0a1.35 1.35 0 1 0 -2.7 0M51.65 52.69a1.35 1.35 0 1 0 2.7 0a1.35 1.35 0 1 0 -2.7 0M51.72 54.89a1.35 1.35 0 1 0 2.7 0a1.35 1.35 0 1 0 -2.7 0"/>
<!-- присоски: светлые тела f2 (compound-кружки) -->
<path fill="var(--f2,hsl(348,24%,72%))" d="M66.99 42.97a1.35 1.35 0 1 0 2.7 0a1.35 1.35 0 1 0 -2.7 0M67.37 40.8a1.35 1.35 0 1 0 2.7 0a1.35 1.35 0 1 0 -2.7 0M46.3 40.39a1.35 1.35 0 1 0 2.7 0a1.35 1.35 0 1 0 -2.7 0M46.45 38.2a1.35 1.35 0 1 0 2.7 0a1.35 1.35 0 1 0 -2.7 0M69.34 48.18a1.35 1.35 0 1 0 2.7 0a1.35 1.35 0 1 0 -2.7 0M69.5 45.98a1.35 1.35 0 1 0 2.7 0a1.35 1.35 0 1 0 -2.7 0M51.65 47.31a1.35 1.35 0 1 0 2.7 0a1.35 1.35 0 1 0 -2.7 0M51.72 45.11a1.35 1.35 0 1 0 2.7 0a1.35 1.35 0 1 0 -2.7 0M66.99 57.03a1.35 1.35 0 1 0 2.7 0a1.35 1.35 0 1 0 -2.7 0M67.37 59.2a1.35 1.35 0 1 0 2.7 0a1.35 1.35 0 1 0 -2.7 0M46.3 59.61a1.35 1.35 0 1 0 2.7 0a1.35 1.35 0 1 0 -2.7 0M46.45 61.8a1.35 1.35 0 1 0 2.7 0a1.35 1.35 0 1 0 -2.7 0M69.34 51.82a1.35 1.35 0 1 0 2.7 0a1.35 1.35 0 1 0 -2.7 0M69.5 54.02a1.35 1.35 0 1 0 2.7 0a1.35 1.35 0 1 0 -2.7 0M51.65 52.69a1.35 1.35 0 1 0 2.7 0a1.35 1.35 0 1 0 -2.7 0M51.72 54.89a1.35 1.35 0 1 0 2.7 0a1.35 1.35 0 1 0 -2.7 0"/>
<!-- голова f1: короткий «капюшон» между мантией и руками (ширина ≈22) -->
<ellipse fill="var(--f1,hsl(350,40%,48%))" cx="96" cy="50" rx="11" ry="13"/>
<!-- глаза: 5 слоёв, симметричны y=50: тёмный ободок f4 -->
<path fill="var(--f4,hsl(350,44%,20%))" d="M93 38a7 7 0 1 0 14 0a7 7 0 1 0 -14 0M93 62a7 7 0 1 0 14 0a7 7 0 1 0 -14 0"/>
<!-- склера #f4f1e6 -->
<path fill="#f4f1e6" d="M94.2 38a5.8 5.8 0 1 0 11.6 0a5.8 5.8 0 1 0 -11.6 0M94.2 62a5.8 5.8 0 1 0 11.6 0a5.8 5.8 0 1 0 -11.6 0"/>
<!-- радужка #d9b23a -->
<path fill="#d9b23a" d="M96 38a4 4 0 1 0 8 0a4 4 0 1 0 -8 0M96 62a4 4 0 1 0 8 0a4 4 0 1 0 -8 0"/>
<!-- горизонтальный зрачок #142638 -->
<path fill="#142638" d="M96.4 38a3.6 1.6 0 1 0 7.2 0a3.6 1.6 0 1 0 -7.2 0M96.4 62a3.6 1.6 0 1 0 7.2 0a3.6 1.6 0 1 0 -7.2 0"/>
<!-- блик #fff -->
<path fill="#fff" d="M96.7 36a1.3 1.3 0 1 0 2.6 0a1.3 1.3 0 1 0 -2.6 0M96.7 64a1.3 1.3 0 1 0 2.6 0a1.3 1.3 0 1 0 -2.6 0"/>
</symbol>
<symbol id="fish-manta" viewBox="0 0 160 100">
<!-- хвост-хлыст f3: тонкий, сужается от корня (40,50) к кончику (8,50); НЕ хвостовой плавник -->
<path fill="var(--f3,hsl(220,34%,28%))" d="M40 47.2 C30 48.2 18 49.3 8 50 C18 50.7 30 51.8 40 52.8 Z"/>
<!-- диск: плоский ромб-«змей» — рыло (132,50) → кончики крыльев (20,18)/(20,82), задняя кромка вогнута к (48,44)/(48,56) и сходится у корня хвоста (40,50) -->
<path fill="var(--f1,hsl(220,28%,38%))" d="M132 50 C112 34 58 22 20 18 Q45 33 48 44 L40 50 L48 56 Q45 67 20 82 C58 78 112 66 132 50 Z"/>
<!-- кромка f4 по переднему краю крыльев (тонкая тёмная линия вдоль обеих кромок) -->
<path fill="none" stroke="var(--f4,hsl(220,38%,16%))" stroke-width="1.3" opacity="0.8" d="M20 18 C58 22 112 34 132 50 C112 66 58 78 20 82"/>
<!-- f4-кляксы камуфляжа: у плеч и по оси, попарно симметрично (compound-path) -->
<path fill="var(--f4,hsl(220,38%,16%))" opacity="0.45" d="M96 39 a3 2.2 0 1 0 6 0 a3 2.2 0 1 0 -6 0 M96 61 a3 2.2 0 1 0 6 0 a3 2.2 0 1 0 -6 0 M77.5 45.5 a2.8 2.1 0 1 0 5.6 0 a2.8 2.1 0 1 0 -5.6 0 M77.5 54.5 a2.8 2.1 0 1 0 5.6 0 a2.8 2.1 0 1 0 -5.6 0 M62 47.8 a2.4 1.8 0 1 0 4.8 0 a2.4 1.8 0 1 0 -4.8 0 M62 52.2 a2.4 1.8 0 1 0 4.8 0 a2.4 1.8 0 1 0 -4.8 0"/>
<!-- 2 светлых f2-шеврона, сходящихся на оси: (110,40)→(96,50)→(110,60) -->
<path fill="none" stroke="var(--f2,hsl(215,22%,72%))" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" opacity="0.55" d="M110 40 L96 50 L110 60"/>
<!-- жабры: 3 короткие f4-щели у каждого бока головы (в дорсальном ракурсе условны) -->
<path fill="none" stroke="var(--f4,hsl(220,38%,16%))" stroke-width="1.1" stroke-linecap="round" opacity="0.75" d="M109 42.5 L104 40.5 M107.5 44.5 L102 42 M106 46.5 L100.5 44 M109 57.5 L104 59.5 M107.5 55.5 L102 58 M106 53.5 L100.5 56"/>
<!-- цефалический рожок верхний f3: от головы (124,45.5) к кончику (150,42) -->
<path fill="var(--f3,hsl(220,34%,28%))" d="M124 45.5 C132 44.5 141 43.3 150 42 C143.5 45.5 136 47.5 127 49 Z"/>
<!-- цефалический рожок нижний f3: зеркало верхнего относительно y=50 -->
<path fill="var(--f3,hsl(220,34%,28%))" d="M124 54.5 C132 55.5 141 56.7 150 58 C143.5 54.5 136 52.5 127 51 Z"/>
<!-- рот f4: широкая терминальная щель (136,50) шириной 10 — тёмные губы -->
<path fill="var(--f4,hsl(220,38%,16%))" d="M136.5 45 Q131 47.5 131 50 Q131 52.5 136.5 55 Q139.5 52.5 139.5 50 Q139.5 47.5 136.5 45 Z"/>
<!-- рот f2: светлая открытая полость внутри щели -->
<path fill="var(--f2,hsl(215,22%,72%))" d="M135.4 47.2 Q132.2 48.7 132.2 50 Q132.2 51.3 135.4 52.8 Q137.4 51.3 137.4 50 Q137.4 48.7 135.4 47.2 Z"/>
<!-- глаз верхний (116,43): f4-ободок → склера → янтарная радужка → зрачок → блик; оба глаза разнесены по бокам головы -->
<path fill="var(--f4,hsl(220,38%,16%))" d="M113.2 43 a2.8 2.8 0 1 0 5.6 0 a2.8 2.8 0 1 0 -5.6 0 M113.2 57 a2.8 2.8 0 1 0 5.6 0 a2.8 2.8 0 1 0 -5.6 0"/>
<path fill="#f4f1e6" d="M114 43 a2 2 0 1 0 4 0 a2 2 0 1 0 -4 0 M114 57 a2 2 0 1 0 4 0 a2 2 0 1 0 -4 0"/>
<path fill="#c9a23a" d="M114.7 43 a1.3 1.3 0 1 0 2.6 0 a1.3 1.3 0 1 0 -2.6 0 M114.7 57 a1.3 1.3 0 1 0 2.6 0 a1.3 1.3 0 1 0 -2.6 0"/>
<path fill="#142638" d="M115.1 43 a0.9 0.9 0 1 0 1.8 0 a0.9 0.9 0 1 0 -1.8 0 M115.1 57 a0.9 0.9 0 1 0 1.8 0 a0.9 0.9 0 1 0 -1.8 0"/>
<path fill="#fff" d="M114.9 42.1 a0.5 0.5 0 1 0 1 0 a0.5 0.5 0 1 0 -1 0 M114.9 57.9 a0.5 0.5 0 1 0 1 0 a0.5 0.5 0 1 0 -1 0"/>
</symbol>
<symbol id="fish-shark" viewBox="0 0 160 100">
<!-- хвост: гетероцеркальный — ВЕРХНЯЯ лопасть длинная, от корня (47,42) к кончику (10,14), корень утоплен в стебель (нахлёст ≥5) -->
<path fill="var(--f3,hsl(210,34%,30%))" d="M47 42 C36 33 22 22 10 14 C12 26 15 38 20 49 C30 48.5 39 49.5 47 51 Z"/>
<!-- хвост: НИЖНЯЯ лопасть КОРОЧЕ верхней — корень (47,49..56.5) утоплен в стебель, кончик (20,74), не зеркало верхней -->
<path fill="var(--f3,hsl(210,34%,30%))" d="M47 49 L47 56.5 C38 59.5 28 66 20 74 C25 66 32 58 38 51 Z"/>
<!-- спинной плавник: ВЫСОКИЙ ТРЕУГОЛЬНИК в средней трети спины, основание x77..102 (y≈37) утоплено в тело, вершина (89,10) скошена назад -->
<path fill="var(--f3,hsl(210,34%,30%))" d="M102 37 C100 24 96 13.5 89 10 C83 17.5 79 27 77 37 Z"/>
<!-- второй спинной (D2): маленький, сдвинут к хвосту, вершина (53,31.5), основание утоплено в спину (нахлёст ≥4) -->
<path fill="var(--f3,hsl(210,34%,30%))" d="M47 44 C48 37 50.5 32.5 53 31.5 C56 34 58.5 39 61 43 Z"/>
<!-- анальный плавник: маленький, снизу позади середины, низ (52,70.5), основание утоплено в брюхо -->
<path fill="var(--f3,hsl(210,34%,30%))" d="M44 56 C46 64 49 70 52 70.5 C56 69 58 64 58.5 56 Z"/>
<!-- брюшные плавники: пара мелких лопастей назад-вниз, основания утоплены в брюхо (compound-path) -->
<path fill="var(--f3,hsl(210,34%,30%))" d="M72 57 C70 64 69 71 71 73 C74 70 75 65 75 57 Z M84 58 C82 66 81 73 83 75 C86 72 87 67 87 58 Z"/>
<!-- дальний грудной плавник: серповидный, корень (114,51) скрыт телом, из-под брюха виден кончик (88,68) -->
<path fill="var(--f3,hsl(210,34%,30%))" d="M114 51 C105 54 96 60 88 68 C96 62.5 106 57 116 53 Z"/>
<!-- тело: торпеда, коническое рыло (152,50), спина (104,32)→(72,34), брюхо (140,58)→(104,64)→(72,60), стебель x42 толщиной 8 -->
<path fill="var(--f1,hsl(210,28%,44%))" d="M152 50 C148 45 144 42.5 140 42 C128 36 116 32.5 104 32 C92 31.5 80 32.5 72 34 C59 37 48 41.5 42 46 L42 54 C50 57.5 60 60.5 72 60 C82 61.5 93 63.5 104 64 C115 63.8 128 62 140 58 C144 56.5 148 54 152 50 Z"/>
<!-- брюхо: БЕЛОЕ, резкая граница контр-шейдинга чуть ниже оси идёт от (152,50) назад и вниз, до стебля -->
<path fill="var(--f2,hsl(205,18%,86%))" d="M152 50.3 C147 51.5 141 52.8 135 53 C125 55.5 110 57 98 57 C88 57 74 56.8 62 54.5 C55 53.3 48 52.3 42 51.4 L42 54 C50 57.5 60 60.5 72 60 C82 61.5 93 63.5 104 64 C115 63.8 128 62 140 58 C146 56.2 150 53.8 152 50.5 Z"/>
<!-- тёмная кромка f4 по спине: тонкая полоса вдоль верхнего контура (не зубцы) -->
<path fill="var(--f4,hsl(210,34%,16%))" d="M152 50 C148 45 144 42.5 140 42 C128 36 116 32.5 104 32 C92 31.5 80 32.5 72 34 C59 37 48 41.5 42 46 C48 43 59 39 72 36.3 C80 34.8 92 33.8 104 34.3 C116 34.8 128 38.3 140 44.3 C144 45.3 148 47.6 152 50 Z"/>
<!-- тёмная кромка f4 по спинному плавнику: тонкий контур ведущей и задней кромок -->
<path fill="none" stroke="var(--f4,hsl(210,34%,16%))" stroke-width="1.4" d="M102 37 C100 24 96 13.5 89 10 C83 17.5 79 27 77 37"/>
<!-- РОТ СНИЗУ: тёмная щель-полумесяц СТАРТУЕТ ПОД РЫЛОМ (149,52.5) и уходит назад к углу (127,60) — НЕ на конце рыла -->
<path fill="var(--f4,hsl(210,34%,16%))" d="M149 52.5 C142 54.8 135 57.2 127 60 C134.5 60.6 142 58.7 149 56.5 Z"/>
<!-- ЗУБЫ: ряд из 6 белых треугольников, compound-path, bases на верхней губе, кончики в тёмной пасти -->
<path fill="#fff" d="M145.7 53 L148.3 53 L146.8 55.7 Z M142.2 54.3 L144.8 54.3 L143.3 57 Z M138.7 55.4 L141.3 55.4 L139.8 58.1 Z M135.2 56.7 L137.8 56.7 L136.3 59.3 Z M131.7 57.8 L134.3 57.8 L132.8 60.4 Z M128.2 58.9 L130.8 58.9 L129.3 61.2 Z"/>
<!-- ПЯТЬ жаберных щелей f4 позади головы (x=128,124,120,116,112, вертикали ~10 при y44..54), compound-path -->
<path fill="var(--f4,hsl(210,34%,16%))" d="M128 44 C129.1 47 129.1 51 128 54 C126.9 51 126.9 47 128 44 Z M124 43.8 C125.1 46.9 125.1 50.9 124 54 C122.9 50.9 122.9 46.9 124 43.8 Z M120 43.6 C121.1 46.8 121.1 50.8 120 54 C118.9 50.8 118.9 46.8 120 43.6 Z M116 43.4 C117.1 46.6 117.1 50.7 116 54 C114.9 50.7 114.9 46.6 116 43.4 Z M112 43.2 C113.1 46.5 113.1 50.6 112 54 C110.9 50.6 110.9 46.5 112 43.2 Z"/>
<!-- грудной плавник: широкий серповидный, корень (123,54.5) скрыт телом, кончик (86,80) — ПОСЛЕ тела -->
<path fill="var(--f3,hsl(210,34%,30%))" d="M123 54.5 C112 58 96 68 86 80 C101 76 117 66 125 58 Z"/>
<!-- глаз мелкий «чёрный»: ободок → склера → радужка → зрачок → блик (последним) -->
<circle fill="var(--f4,hsl(210,34%,16%))" cx="140" cy="45" r="3.4"/>
<circle fill="#e6e1d2" cx="140" cy="45" r="2.5"/>
<circle fill="#142638" cx="140" cy="45" r="1.8"/>
<circle fill="#0d0d0d" cx="140" cy="45" r="1.1"/>
<circle fill="#fff" cx="139.3" cy="44.3" r="0.5"/>
</symbol>
<symbol id="fish-squid" viewBox="0 0 160 100">
<!-- мантия-торпеда: кончик (18,50), спинной подъём (56,36)→(94,40), голова (106,42)…(120,58); низ зеркален -->
<path fill="var(--f1,hsl(300,36%,46%))" d="M 18 50 C 28 44 40 38 56 36 C 72 34.5 86 36.5 96 40 C 101 41.5 105 42 108 42 C 115 42 120 45 120 50 C 120 55 115 58 108 58 C 105 58 101 58.5 96 60 C 86 63.5 72 65.5 56 64 C 40 62 28 56 18 50 Z"/>
<!-- светлое брюхо мантии f2 вдоль нижнего контура -->
<path fill="var(--f2,hsl(300,22%,72%))" d="M 108 58 C 105 58 101 58.5 96 60 C 86 63.5 72 65.5 56 64 C 40 62 28 56 18 50 C 26 55.5 38 60.5 54 61.8 C 70 63 86 61.5 96 58.5 C 102 57 105 56.5 108 56.5 Z"/>
<!-- плавники-«крылышки» f3 у заднего конца мантии (верхний и нижний зеркально): (18,50)-(40,34)-(52,44) -->
<path fill="var(--f3,hsl(300,40%,30%))" d="M 18 50 C 26 39.5 34 34.5 40 34 C 46 36.5 50 40.5 52 44 C 43 41.5 29 45.5 18 50 Z M 18 50 C 26 60.5 34 65.5 40 66 C 46 63.5 50 59.5 52 56 C 43 58.5 29 54.5 18 50 Z"/>
<!-- тёмная кромка f4 по верху мантии -->
<path fill="none" stroke="var(--f4,hsl(300,42%,18%))" stroke-width="1.6" stroke-linecap="round" d="M 108 42 C 105 42 101 41.5 96 40 C 86 36.5 72 34.5 56 36 C 40 38 28 44 18 50"/>
<!-- тёмная граница f4 между мантией и головой -->
<path fill="none" stroke="var(--f4,hsl(300,42%,18%))" stroke-width="1.2" d="M 105 43.5 C 108.5 46 108.5 54 105 56.5"/>
<!-- сифон f4: короткая трубка от (104,56) влево-вниз -->
<path fill="var(--f4,hsl(300,42%,18%))" d="M 107 54.5 C 101 56 96.5 59.5 94 63.5 L 98.5 65.5 C 100.5 61.5 103.5 58.5 108 56.5 Z"/>
<!-- 8 коротких рук f1: веер от (119.5,42..58) вправо, кончики подкручены (4 вверх + 4 зеркальные вниз), compound-path -->
<path fill="var(--f1,hsl(300,36%,46%))" d="M 119.5 42.5 C 127 38.5 136 34 144 29 C 148 26.6 151.5 25.2 152.5 23.6 C 153.5 21.9 151.2 21.7 148.4 23.5 C 140.5 28.5 129.5 34 122 38.8 C 120.5 40.6 119 43.5 119.5 45.5 Z M 119.5 44 C 128 41.5 139 39.2 147.5 37.4 C 151.5 36.5 154 35.8 154.4 34.4 C 154.8 33 152.2 33.2 149.4 34 C 140 37 129.5 39.8 122.5 41.8 C 120.5 42.8 119.2 45.5 119.5 47 Z M 119.5 45.5 C 128 45 138 44.4 146.5 43.6 C 150 43.2 152 42.8 152.3 41.8 C 152.6 40.8 150.2 40.9 147.6 41.3 C 139.5 42.7 130 44 122.5 44.7 C 120.8 45 119.2 46.5 119.5 48.5 Z M 119.5 46.5 C 126 47 134 47.2 140.5 47.1 C 143.8 47 146 46.7 146.4 45.9 C 146.8 45.1 144.6 45.1 142.4 45.5 C 136 46.6 128.5 47.4 122.5 47.9 C 120.8 48.1 119.2 48.2 119.5 49.5 Z M 119.5 57.5 C 127 61.5 136 66 144 71 C 148 73.4 151.5 74.8 152.5 76.4 C 153.5 78.1 151.2 78.3 148.4 76.5 C 140.5 71.5 129.5 66 122 61.2 C 120.5 59.4 119 56.5 119.5 54.5 Z M 119.5 56 C 128 58.5 139 60.8 147.5 62.6 C 151.5 63.5 154 64.2 154.4 65.6 C 154.8 67 152.2 66.8 149.4 66 C 140 63 129.5 60.2 122.5 58.2 C 120.5 57.2 119.2 54.5 119.5 53 Z M 119.5 54.5 C 128 55 138 55.6 146.5 56.4 C 150 56.8 152 57.2 152.3 58.2 C 152.6 59.2 150.2 59.1 147.6 58.7 C 139.5 57.3 130 56 122.5 55.3 C 120.8 55 119.2 53.5 119.5 51.5 Z M 119.5 53.5 C 126 53 134 52.8 140.5 52.9 C 143.8 53 146 53.3 146.4 54.1 C 146.8 54.9 144.6 54.9 142.4 54.5 C 136 53.4 128.5 52.6 122.5 52.1 C 120.8 51.9 119.2 51.8 119.5 50.5 Z"/>
<!-- 2 ДЛИННЫХ ловчих щупальца f1: от (120,48)/(120,52) с изгибом к (156,20)/(156,80), на концах «булавы» с присосками -->
<path fill="var(--f1,hsl(300,36%,46%))" d="M 120 47 C 130 45 140 39 147 32 C 150 29 152 25.5 153.5 22.5 C 154.5 24.5 153.5 27 151 30 C 144 38 133 45 121 50 Z M 120 53 C 130 55 140 61 147 68 C 150 71 152 74.5 153.5 77.5 C 154.5 75.5 153.5 73 151 70 C 144 62 133 55 121 50 Z M 150 25 C 151.5 20.5 155 17.5 157 19 C 158.5 20.2 157.5 24 154.5 26.5 C 152.5 28 150.5 27.5 150 25 Z M 150 75 C 151.5 79.5 155 82.5 157 81 C 158.5 79.8 157.5 76 154.5 73.5 C 152.5 72 150.5 72.5 150 75 Z"/>
<!-- низ ловчих щупалец f3 (перекрашиваемый) — тонкая полоса по внутренней кромке -->
<path fill="var(--f3,hsl(300,40%,30%))" d="M 121 50 C 133 45 144 38 151 30 C 150 32 148 34 145 36 C 138 41 129 46 122 49 Z M 121 50 C 133 55 144 62 151 70 C 150 68 148 66 145 64 C 138 59 129 54 122 51 Z"/>
<!-- присоски f2 с тёмным римом f4: по 2 ряда на руках и на булавах (compound-path) -->
<path fill="var(--f2,hsl(300,22%,72%))" stroke="var(--f4,hsl(300,42%,18%))" stroke-width="0.5" d="M 128.98 38.78 a 1 1 0 1 0 2 0 a 1 1 0 1 0 -2 0 M 127.82 36.92 a 1 1 0 1 0 2 0 a 1 1 0 1 0 -2 0 M 137.23 33.63 a 1 1 0 1 0 2 0 a 1 1 0 1 0 -2 0 M 136.07 31.77 a 1 1 0 1 0 2 0 a 1 1 0 1 0 -2 0 M 129.3 43.22 a 1 1 0 1 0 2 0 a 1 1 0 1 0 -2 0 M 128.64 41.12 a 1 1 0 1 0 2 0 a 1 1 0 1 0 -2 0 M 138.01 40.44 a 1 1 0 1 0 2 0 a 1 1 0 1 0 -2 0 M 137.35 38.34 a 1 1 0 1 0 2 0 a 1 1 0 1 0 -2 0 M 128.51 46.53 a 1 1 0 1 0 2 0 a 1 1 0 1 0 -2 0 M 128.17 44.35 a 1 1 0 1 0 2 0 a 1 1 0 1 0 -2 0 M 136.71 45.23 a 1 1 0 1 0 2 0 a 1 1 0 1 0 -2 0 M 136.37 43.05 a 1 1 0 1 0 2 0 a 1 1 0 1 0 -2 0 M 126.66 48.47 a 1 1 0 1 0 2 0 a 1 1 0 1 0 -2 0 M 126.48 46.27 a 1 1 0 1 0 2 0 a 1 1 0 1 0 -2 0 M 133.39 47.95 a 1 1 0 1 0 2 0 a 1 1 0 1 0 -2 0 M 133.21 45.75 a 1 1 0 1 0 2 0 a 1 1 0 1 0 -2 0 M 128.98 61.22 a 1 1 0 1 0 2 0 a 1 1 0 1 0 -2 0 M 127.82 63.08 a 1 1 0 1 0 2 0 a 1 1 0 1 0 -2 0 M 137.23 66.37 a 1 1 0 1 0 2 0 a 1 1 0 1 0 -2 0 M 136.07 68.23 a 1 1 0 1 0 2 0 a 1 1 0 1 0 -2 0 M 129.3 56.78 a 1 1 0 1 0 2 0 a 1 1 0 1 0 -2 0 M 128.64 58.88 a 1 1 0 1 0 2 0 a 1 1 0 1 0 -2 0 M 138.01 59.56 a 1 1 0 1 0 2 0 a 1 1 0 1 0 -2 0 M 137.35 61.66 a 1 1 0 1 0 2 0 a 1 1 0 1 0 -2 0 M 128.51 53.47 a 1 1 0 1 0 2 0 a 1 1 0 1 0 -2 0 M 128.17 55.65 a 1 1 0 1 0 2 0 a 1 1 0 1 0 -2 0 M 136.71 54.77 a 1 1 0 1 0 2 0 a 1 1 0 1 0 -2 0 M 136.37 56.95 a 1 1 0 1 0 2 0 a 1 1 0 1 0 -2 0 M 126.66 51.53 a 1 1 0 1 0 2 0 a 1 1 0 1 0 -2 0 M 126.48 53.73 a 1 1 0 1 0 2 0 a 1 1 0 1 0 -2 0 M 133.39 52.05 a 1 1 0 1 0 2 0 a 1 1 0 1 0 -2 0 M 133.21 54.25 a 1 1 0 1 0 2 0 a 1 1 0 1 0 -2 0 M 151.57 24.75 a 1 1 0 1 0 2 0 a 1 1 0 1 0 -2 0 M 153.42 23.1 a 1 1 0 1 0 2 0 a 1 1 0 1 0 -2 0 M 155.27 21.45 a 1 1 0 1 0 2 0 a 1 1 0 1 0 -2 0 M 150.23 23.25 a 1 1 0 1 0 2 0 a 1 1 0 1 0 -2 0 M 152.08 21.6 a 1 1 0 1 0 2 0 a 1 1 0 1 0 -2 0 M 153.93 19.95 a 1 1 0 1 0 2 0 a 1 1 0 1 0 -2 0 M 151.57 75.25 a 1 1 0 1 0 2 0 a 1 1 0 1 0 -2 0 M 153.42 76.9 a 1 1 0 1 0 2 0 a 1 1 0 1 0 -2 0 M 155.27 78.55 a 1 1 0 1 0 2 0 a 1 1 0 1 0 -2 0 M 150.23 76.75 a 1 1 0 1 0 2 0 a 1 1 0 1 0 -2 0 M 152.08 78.4 a 1 1 0 1 0 2 0 a 1 1 0 1 0 -2 0 M 153.93 80.05 a 1 1 0 1 0 2 0 a 1 1 0 1 0 -2 0"/>
<!-- глаза (110,40)/(110,60): 5 слоёв — тёмный ободок f4 → склера → золотая радужка → зрачок → блик -->
<circle cx="110" cy="40" r="6.2" fill="var(--f4,hsl(300,42%,18%))"/>
<circle cx="110" cy="40" r="5.2" fill="#f4f1e6"/>
<circle cx="110" cy="40" r="3.6" fill="#d9b23a"/>
<circle cx="110" cy="40" r="2.4" fill="#142638"/>
<circle cx="110.8" cy="38.9" r="0.9" fill="#fff"/>
<circle cx="110" cy="60" r="6.2" fill="var(--f4,hsl(300,42%,18%))"/>
<circle cx="110" cy="60" r="5.2" fill="#f4f1e6"/>
<circle cx="110" cy="60" r="3.6" fill="#d9b23a"/>
<circle cx="110" cy="60" r="2.4" fill="#142638"/>
<circle cx="110.8" cy="61.1" r="0.9" fill="#fff"/>
</symbol>
<symbol id="fish-whale" viewBox="0 0 160 100">
<!-- хвост: Горизонтальные флоскулы — ДВЕ симметричные широкие лопасти (compound), корни утоплены в стебель (нахлёст ≥4), кончики (6,34) и (6,66) -->
<path fill="var(--f3,hsl(230,30%,30%))" d="M34 44.5 C24 40 13 35.5 6 34 C8 40.5 15.5 46.5 26 50.2 C29 51.2 31.5 51.4 34 51 Z M34 55.5 C24 60 13 64.5 6 66 C8 59.5 15.5 53.5 26 49.8 C29 48.8 31.5 48.6 34 49 Z"/>
<!-- спинной плавник: КРОШЕЧНЫЙ серповидный (НЕ высокий треугольник акулы), далеко назад, основание x49..59 утоплено в спину (нахлёст ≥4) -->
<path fill="var(--f3,hsl(230,30%,30%))" d="M49 38 C51 35 52.5 32.8 54.5 31.2 C56.5 32.8 58 35.2 59 37.2 C55.5 36.6 52 37 49 38 Z"/>
<!-- тело: массивное веретено (длина/глубина ≈4:1) с КОРОТКОЙ ШИРОКОЙ U-образной головой справа (рострум 154,56), спина (78,31), брюхо (116,70), стебель x30 толщиной 14 (43..57) -->
<path fill="var(--f1,hsl(228,28%,46%))" d="M30 43 C36 41 41 39.5 46 38 C56 34.5 67 31.5 78 31 C100 30 118 32.5 134 37.5 C143 40.5 149 44 152.5 49 C154.2 51.5 155 54 154.3 56 C153.6 58 152 60.5 149.5 62.5 C142 67 130 69.2 116 70 C100 70.9 82 71 66 70 C54 69.2 45 64.5 40.5 58.5 C37 55 33 57 30 57 Z"/>
<!-- спинная кромка f4: тонкая тёмная полоса по верхнему контуру (не зубцы) — объём спины -->
<path fill="var(--f4,hsl(228,32%,18%))" d="M30 43 C36 41 41 39.5 46 38 C56 34.5 67 31.5 78 31 C100 30 118 32.5 134 37.5 C143 40.5 149 44 152.5 49 C150 45.5 144.5 42.5 137 40 C121 35 100 33 78 33.5 C66 34 55 36.5 46 40 C39.5 42.6 34 45 30 46 Z"/>
<!-- брюхо: светлая f2-полоса вдоль подводной кромки (контраст к f1 L≈46%) -->
<path fill="var(--f2,hsl(215,18%,80%))" d="M154 56 C153.6 58 152 60.5 149.5 62.5 C142 67 130 69.2 116 70 C100 70.9 82 71 66 70 C54 69.2 45 64.5 40.5 58.5 C37 55 33 57 30 57 C34 53.5 40 55 48 58 C58 61.5 72 63 86 63 C104 63 126 61.5 142 57.5 C147 56 151 55.5 154 56 Z"/>
<!-- марблинг: 3 бледных f2-пятна на верхнем боку (compound) — не рыбьи полосы -->
<path fill="var(--f2,hsl(215,18%,80%))" opacity="0.5" d="M96 39.5 C100.5 38 104.5 40.5 102.5 43.5 C100.5 46.5 94.5 45.5 93.5 43 C92.8 41.2 93.8 40.3 96 39.5 Z M70 36.5 C74.5 35 78.5 37.5 76.5 40.5 C74.5 43.5 68.5 42.5 67.5 40 C66.8 38.2 67.8 37.3 70 36.5 Z M118 41.5 C121.5 40.5 124 42.5 122.5 44.5 C121 46.5 117 45.8 116.2 44 C115.7 42.7 116.4 42 118 41.5 Z"/>
<!-- рот-барьер f4: длинная тёмная полоса-щель вдоль нижней челюсти от (152,58) назад до (104,64) -->
<path fill="var(--f4,hsl(228,32%,18%))" d="M152.5 57.5 C139 59.4 121 61.7 104 63.8 C120 65.2 139 63.2 152.5 60.4 Z"/>
<!-- китовый ус: 7 коротких вертикалей #e9e2cc под барьером (compound, фикс-акцент — млекопитающее, не рыбьи зубы) -->
<path fill="none" stroke="#e9e2cc" stroke-width="1.2" stroke-linecap="round" d="M148 60.7 L148 63.5 M142 61.1 L142 63.9 M136 61.6 L136 64.4 M130 62 L130 64.8 M124 62.4 L124 65.2 M118 62.8 L118 65.6 M112 63.2 L112 66"/>
<!-- горловые борозды f4: 4 короткие дуги от (148,62) назад-вниз до (108,70) (compound) — знак кита, НЕ жаберные щели -->
<path fill="none" stroke="var(--f4,hsl(228,32%,18%))" stroke-width="1.4" stroke-linecap="round" d="M146 61.5 Q143.5 63.5 145.4 65.4 M134 63 Q131.5 65 133.4 67.2 M122 64.5 Q119.5 66.8 121.4 69 M110 66 Q107.5 68.2 109.4 70"/>
<!-- грудной плавник f3: узкая серповидная лопасть (112,66)→(86,76), заметно выступает из-под брюха, рисуется ПОСЛЕ тела -->
<path fill="var(--f3,hsl(230,30%,30%))" d="M112 69.5 C104 74.5 96 77 86 79 C100 74 111 66.5 119 59.5 Z"/>
<!-- ФОНТАН, светлый веер #eaf6ff: широкая мягкая струя-раструб наверху, притуплённые края (фикс-акцент) -->
<path fill="#eaf6ff" d="M129 10 C123 13 118 19 115 26 C119 20 124 15 129 13 C134 16 138 21 141 28 C139 20 135 13 129 10 Z"/>
<!-- ФОНТАН, конус #cfe9ff: узкая струя от дыхал (126,34) вверх к (130,10) (фикс-акцент) -->
<path fill="#cfe9ff" d="M125 35 C124 27 126 17 130 10 C132 18 130 28 128.5 35 Z"/>
<!-- дыхала f4: два маленьких тёмных отверстия на голове вокруг (126,37) (compound) -->
<path fill="var(--f4,hsl(228,32%,18%))" d="M123.3 36.7 a1.4 0.9 0 1 0 2.8 0 a1.4 0.9 0 1 0 -2.8 0 M126.5 36.7 a1.4 0.9 0 1 0 2.8 0 a1.4 0.9 0 1 0 -2.8 0"/>
<!-- глаз: НАМЕРЕННО крошечный (млекопитающее), ободок f4 → склера #e6e1d2 → радужка → зрачок → блик (последним) -->
<circle fill="var(--f4,hsl(228,32%,18%))" cx="136" cy="50" r="3"/>
<circle fill="#e6e1d2" cx="136" cy="50" r="2.2"/>
<circle fill="#1a2a3a" cx="136" cy="50" r="1.5"/>
<circle fill="#0d1418" cx="136" cy="50" r="1"/>
<circle fill="#fff" cx="135.4" cy="49.4" r="0.4"/>
</symbol>
<symbol id="fish-glowfin" viewBox="0 0 160 100">
<!-- свечение хвостового плавника -->
<circle fill="#5ff2ff" cx="19" cy="38" r="1.7"/>
<circle fill="#5ff2ff" cx="19" cy="62" r="1.7"/>
<circle fill="#d6fdff" cx="24.5" cy="50" r="1.4"/>
<!-- хвост: мелкий вилочный -->
<path fill="var(--f3,hsl(150,30%,26%))" d="M35 43 L14 31 L24 48.5 L14 69 L35 57 Z"/>
<!-- тело: мелкое, стройное, заострённая морда -->
<path fill="var(--f1,hsl(150,22%,30%))" d="M146 50 C136 42 114 38 88 38 C62 38 44 42 34 47 L34 53 C44 58 62 62 88 62 C114 62 136 58 146 50 Z"/>
<!-- брюшко: чуть светлее (налёт полупрозрачности) -->
<path fill="var(--f2,hsl(150,18%,46%))" d="M146 50 C136 58 114 62 88 62 C62 62 44 58 34 53 C44 56 62 59 88 59 C114 59 136 56 146 50 Z"/>
<!-- просвет тела: тонкая светлая жилка-полупрозрачность -->
<path fill="var(--f2,hsl(150,18%,46%))" d="M134 47.5 C122 43.5 106 41.8 88 41.8 C70 41.8 56 43.5 46 47 C56 45 70 44 88 44 C106 44 122 45.5 134 47.5 Z"/>
<!-- спинная кромка: тонкая тёмная полоса -->
<path fill="var(--f4,hsl(150,25%,17%))" d="M146 50 C136 42 114 38 88 38 C62 38 44 42 34 47 C44 44 62 41.8 88 41.8 C114 41.8 136 44 146 50 Z"/>
<!-- спинной плавник: низкий, со свечением -->
<path fill="var(--f3,hsl(150,30%,26%))" d="M70 39.5 Q82 24 96 39 Z"/>
<circle fill="#5ff2ff" cx="79" cy="33" r="1.4"/>
<circle fill="#5ff2ff" cx="89" cy="35" r="1.4"/>
<!-- грудной плавник -->
<path fill="var(--f3,hsl(150,30%,26%))" d="M116 53 C112 56.5 111.5 60.5 115 63.5 C118 60 118.5 56.5 117.5 53.5 Z"/>
<circle fill="#5ff2ff" cx="115.5" cy="58" r="1.2"/>
<!-- брюшной плавник -->
<path fill="var(--f3,hsl(150,30%,26%))" d="M86 62 L82 68.5 L94 62.5 Z"/>
<!-- анальный плавник -->
<path fill="var(--f3,hsl(150,30%,26%))" d="M62 61.5 L57 68 L68 62.2 Z"/>
<circle fill="#5ff2ff" cx="63" cy="64" r="1.2"/>
<!-- рот: маленькая тёмная щель на конце морды (внутри силуэта) -->
<path fill="var(--f4,hsl(150,25%,17%))" d="M143 49.6 C145.5 49.9 147 50.6 147.8 51.6 C146.2 52.8 144.6 52.4 143.2 51.2 Z"/>
<!-- свечение вдоль бока: ряд циановых чёрточек -->
<ellipse fill="#5ff2ff" cx="50" cy="50.2" rx="2.3" ry="1.4"/>
<ellipse fill="#5ff2ff" cx="60" cy="50" rx="2.3" ry="1.4"/>
<ellipse fill="#5ff2ff" cx="70" cy="49.6" rx="2.3" ry="1.4"/>
<ellipse fill="#5ff2ff" cx="80" cy="49.2" rx="2.3" ry="1.4"/>
<ellipse fill="#5ff2ff" cx="90" cy="48.8" rx="2.3" ry="1.4"/>
<ellipse fill="#5ff2ff" cx="100" cy="48.4" rx="2.3" ry="1.4"/>
<ellipse fill="#5ff2ff" cx="110" cy="48" rx="2.3" ry="1.4"/>
<!-- яркие ядрышки свечения -->
<ellipse fill="#e8feff" cx="50" cy="49.6" rx="0.9" ry="0.6"/>
<ellipse fill="#e8feff" cx="70" cy="49" rx="0.9" ry="0.6"/>
<ellipse fill="#e8feff" cx="90" cy="48.2" rx="0.9" ry="0.6"/>
<ellipse fill="#e8feff" cx="110" cy="47.4" rx="0.9" ry="0.6"/>
<!-- фотофоры: точки свечения вдоль брюха -->
<circle fill="#5ff2ff" cx="49" cy="55.6" r="1.05"/>
<circle fill="#5ff2ff" cx="60" cy="57.6" r="1.05"/>
<circle fill="#5ff2ff" cx="71" cy="58.9" r="1.05"/>
<circle fill="#5ff2ff" cx="83" cy="59.4" r="1.05"/>
<circle fill="#5ff2ff" cx="95" cy="58.8" r="1.05"/>
<circle fill="#5ff2ff" cx="107" cy="57.6" r="1.05"/>
<circle fill="#5ff2ff" cx="117" cy="55.8" r="1.05"/>
<circle fill="#5ff2ff" cx="126" cy="53.2" r="1.05"/>
<!-- глаз: светится цианом -->
<circle fill="var(--f4,hsl(150,25%,17%))" cx="126.5" cy="47.5" r="4.1"/>
<circle fill="#5ff2ff" cx="126.5" cy="47.5" r="3.2"/>
<circle fill="#bdfbff" cx="126.5" cy="47.5" r="1.7"/>
<circle fill="#f2ffff" cx="126.5" cy="47" r="0.85"/>
</symbol>
<symbol id="fish-moonfish" viewBox="0 0 160 100">
<!-- хвост: короткий полумесячный -->
<path fill="var(--f3,hsl(220,40%,34%))" d="M36 50 L9 31 L21 50 L9 69 Z"/>
<!-- спинной плавник: мягкий округлый -->
<path fill="var(--f3,hsl(220,40%,34%))" d="M60 22 C72 2 104 1 120 18 C99 12 76 14 60 22 Z"/>
<!-- анальный плавник -->
<path fill="var(--f3,hsl(220,40%,34%))" d="M64 84 C76 98 102 99 116 88 C98 90 78 88 64 84 Z"/>
<!-- тело: округлое лунное, серо-голубое -->
<path fill="var(--f1,hsl(220,25%,58%))" d="M30 50 C30 24 54 10 88 10 C124 10 148 28 148 50 C148 72 124 90 88 90 C54 90 30 76 30 50 Z"/>
<!-- брюхо: светлее, холодный отблеск -->
<path fill="var(--f2,hsl(220,25%,80%))" d="M30 50 C30 76 54 90 88 90 C124 90 148 72 148 50 C147 66 122 76 88 76 C58 76 32 66 30 50 Z"/>
<!-- узор: бледно-голубые (#b9c8ff = hsl(227,100%,86%)) полумесячные лунки на боку -->
<path fill="var(--f4,hsl(227,100%,86%))" d="M74 34 A17 17 0 1 0 74 62 A30 30 0 0 1 74 34 Z"/>
<path fill="var(--f4,hsl(227,100%,86%))" d="M98 52 A11 11 0 1 0 98 70 A20 20 0 0 1 98 52 Z"/>
<path fill="var(--f4,hsl(227,100%,86%))" d="M112 25 A7 7 0 1 0 112 39 A13 13 0 0 1 112 25 Z"/>
<!-- грудной плавник -->
<path fill="var(--f3,hsl(220,40%,34%))" d="M106 56 C116 58 122 68 118 77 C110 71 104 64 102 58 Z"/>
<!-- рот: маленький, на конце морды -->
<path fill="var(--f3,hsl(220,40%,34%))" d="M143 52 C147 53 149 55 150 57 C147 57 144 55 142 54 Z"/>
<!-- глаз: крупный, светлый, с бледно-голубой радужкой и блеском -->
<circle cx="123" cy="40" r="9.5" fill="#fff"/>
<circle cx="123" cy="40" r="6.5" fill="var(--f4,hsl(227,100%,86%))"/>
<circle cx="124" cy="40.5" r="3.2" fill="#142638"/>
<circle cx="121.5" cy="37.5" r="1.8" fill="#fff"/>
</symbol>
<symbol id="fish-emberfin" viewBox="0 0 160 100">
<!-- хвостовой плавник: три рваных языка пламени с вырезами посередине -->
<path d="M47,38 C41,29 34,20 27,12 C23,7 17,3 9,1 C16,8 18,14 16,19 L23,21 L14,26 C17,31 23,35 31,39 C37,42 42,41 47,42 Z" fill="var(--f3,hsl(150,55%,27%))"/>
<path d="M47,43 C38,39 28,35 18,32 C13,30 8,29 1,31 C8,34 10,38 9,42 L16,44 L8,48 C12,52 18,53 27,52 C35,51 42,48 47,48 Z" fill="var(--f3,hsl(150,55%,27%))"/>
<path d="M47,54 C42,61 36,68 29,75 C25,79 20,83 12,89 C18,80 19,75 18,70 L25,68 L17,63 C20,58 25,55 33,53 C39,52 43,54 47,54 Z" fill="var(--f3,hsl(150,55%,27%))"/>
<!-- горящая сердцевина пламени: акцентная изумрудная вспышка -->
<path d="M45,41 C39,34 33,27 27,22 C23,19 18,17 13,16 C18,21 19,25 17,29 L22,30 L16,34 C20,38 26,41 33,42 C39,42 42,41 45,41 Z" fill="#57ffa8" fill-opacity="0.8"/>
<path d="M45,46 C37,44 29,41 21,39 C17,38 13,38 8,39 C13,41 14,44 13,47 L18,48 L13,51 C17,53 22,53 29,51 C35,49 41,47 45,47 Z" fill="#57ffa8" fill-opacity="0.6"/>
<!-- тело: плотное, смотрит вправо -->
<path d="M40,50 C56,24 78,20 104,22 C130,25 143,36 148,50 C143,64 130,75 104,78 C78,80 56,76 40,50 Z" fill="var(--f1,hsl(150,52%,40%))"/>
<!-- брюхо: светлее, блик вдоль нижней кромки -->
<path d="M148,50 C143,64 130,75 104,78 C78,80 56,76 40,50 C56,66 82,70 108,68 C130,66 141,60 148,50 Z" fill="var(--f2,hsl(150,45%,64%))"/>
<!-- спинной плавник -->
<path d="M78,26 C88,12 100,8 116,22 C100,23 88,25 82,30 Z" fill="var(--f3,hsl(150,55%,27%))"/>
<!-- грудной плавник -->
<path d="M104,56 C118,60 124,66 120,78 C112,72 104,66 100,60 Z" fill="var(--f3,hsl(150,55%,27%))"/>
<!-- брюшной плавник -->
<path d="M84,76 C92,86 100,89 108,84 C100,81 94,78 90,73 Z" fill="var(--f3,hsl(150,55%,27%))"/>
<!-- жаберная дуга -->
<path d="M120,32 C114,42 114,50 120,58" fill="none" stroke="var(--f4,hsl(150,60%,19%))" stroke-width="1.8" stroke-linecap="round"/>
<!-- искры по телу: свечение + ядро -->
<circle cx="70" cy="33" r="4" fill="#57ffa8" fill-opacity="0.22"/>
<circle cx="70" cy="33" r="2.2" fill="#57ffa8"/>
<circle cx="92" cy="29" r="3.4" fill="#57ffa8" fill-opacity="0.22"/>
<circle cx="92" cy="29" r="1.8" fill="#57ffa8"/>
<circle cx="110" cy="40" r="4.6" fill="#57ffa8" fill-opacity="0.25"/>
<circle cx="110" cy="40" r="2.6" fill="#57ffa8"/>
<circle cx="82" cy="50" r="3.6" fill="#57ffa8" fill-opacity="0.22"/>
<circle cx="82" cy="50" r="2" fill="#57ffa8"/>
<circle cx="122" cy="57" r="4" fill="#57ffa8" fill-opacity="0.22"/>
<circle cx="122" cy="57" r="2.2" fill="#57ffa8"/>
<circle cx="98" cy="64" r="3.4" fill="#57ffa8" fill-opacity="0.22"/>
<circle cx="98" cy="64" r="1.8" fill="#57ffa8"/>
<circle cx="62" cy="57" r="4.2" fill="#57ffa8" fill-opacity="0.25"/>
<circle cx="62" cy="57" r="2.4" fill="#57ffa8"/>
<circle cx="134" cy="47" r="3" fill="#57ffa8" fill-opacity="0.22"/>
<circle cx="134" cy="47" r="1.6" fill="#57ffa8"/>
<circle cx="76" cy="68" r="2.8" fill="#57ffa8" fill-opacity="0.22"/>
<circle cx="76" cy="68" r="1.5" fill="#57ffa8"/>
<!-- угольки, слетающие с пламени -->
<circle cx="18" cy="20" r="2.6" fill="#57ffa8" fill-opacity="0.2"/>
<circle cx="18" cy="20" r="1.4" fill="#57ffa8"/>
<circle cx="14" cy="64" r="2.2" fill="#57ffa8" fill-opacity="0.2"/>
<circle cx="14" cy="64" r="1.2" fill="#57ffa8"/>
<circle cx="10" cy="86" r="2.4" fill="#57ffa8" fill-opacity="0.2"/>
<circle cx="10" cy="86" r="1.3" fill="#57ffa8"/>
<!-- светящийся глаз -->
<circle cx="130" cy="40" r="9" fill="#57ffa8" fill-opacity="0.3"/>
<circle cx="130" cy="40" r="6.5" fill="#fff"/>
<circle cx="131.5" cy="40" r="3" fill="#142638"/>
</symbol>
<symbol id="fish-violetlure" viewBox="0 0 160 100">
<!-- хвостовой плавник: узкая вилочка с вырезом -->
<path fill="var(--f3,hsl(280,52%,34%))" d="M46 50 C38 42 28 34 14 30 C24 38 28 44 26 50 C28 56 24 62 14 70 C28 66 38 58 46 50 Z"/>
<!-- спинной плавник: длинный низкий «парус» -->
<path fill="var(--f3,hsl(280,52%,34%))" d="M74 28 C82 12 100 6 118 20 C100 22 86 26 78 32 Z"/>
<!-- анальный плавник -->
<path fill="var(--f3,hsl(280,52%,34%))" d="M80 74 C88 88 102 92 114 84 C100 84 88 80 82 72 Z"/>
<!-- тело: стройное, вытянутое, смотрит вправо -->
<path fill="var(--f1,hsl(280,48%,52%))" d="M44 50 C52 33 74 24 100 24 C126 24 143 35 150 50 C143 65 126 76 100 76 C74 76 52 67 44 50 Z"/>
<!-- брюхо: светлее, сиреневый отблеск снизу -->
<path fill="var(--f2,hsl(280,38%,74%))" d="M150 50 C143 65 126 76 100 76 C74 76 52 67 44 50 C58 64 80 70 104 69 C127 68 142 60 150 50 Z"/>
<!-- светящиеся полоски вдоль бока: мягкое свечение + яркая сердцевина -->
<path fill="none" stroke="#d17bff" stroke-width="4.5" stroke-linecap="round" opacity="0.25" d="M58 44 C82 38 110 37 140 44"/>
<path fill="none" stroke="#d17bff" stroke-width="2" stroke-linecap="round" opacity="0.9" d="M58 44 C82 38 110 37 140 44"/>
<path fill="none" stroke="#d17bff" stroke-width="4.5" stroke-linecap="round" opacity="0.25" d="M62 54 C86 60 112 60 138 53"/>
<path fill="none" stroke="#d17bff" stroke-width="2" stroke-linecap="round" opacity="0.9" d="M62 54 C86 60 112 60 138 53"/>
<path fill="none" stroke="#d17bff" stroke-width="4" stroke-linecap="round" opacity="0.22" d="M70 63 C90 68 110 67 128 60"/>
<path fill="none" stroke="#d17bff" stroke-width="1.8" stroke-linecap="round" opacity="0.8" d="M70 63 C90 68 110 67 128 60"/>
<!-- искорки-огоньки на полосках -->
<circle fill="#d17bff" cx="70" cy="41" r="3.2" opacity="0.25"/>
<circle fill="#d17bff" cx="70" cy="41" r="1.5"/>
<circle fill="#d17bff" cx="96" cy="48" r="3.6" opacity="0.25"/>
<circle fill="#d17bff" cx="96" cy="48" r="1.7"/>
<circle fill="#d17bff" cx="124" cy="47" r="3" opacity="0.25"/>
<circle fill="#d17bff" cx="124" cy="47" r="1.4"/>
<!-- грудной плавник -->
<path fill="var(--f3,hsl(280,52%,34%))" d="M110 58 C122 60 128 68 124 78 C116 72 108 66 105 60 Z"/>
<!-- жаберная дуга у головы -->
<path fill="none" stroke="var(--f4,hsl(282,48%,24%))" stroke-width="2" stroke-linecap="round" opacity="0.5" d="M118 30 C112 40 112 60 119 72"/>
<!-- рот: маленький, на конце морды -->
<path fill="var(--f4,hsl(282,48%,24%))" d="M149 52 C143 56 137 56 132 54 C139 59 147 57 149 52 Z"/>
<!-- «удочка»-иллюций: тонкая дуга от лба вверх-вперёд -->
<path fill="none" stroke="var(--f4,hsl(282,48%,24%))" stroke-width="3" stroke-linecap="round" d="M124 28 C124 15 134 8 150 9"/>
<!-- приманка: яркий фиолетовый огонёк с ореолом свечения -->
<circle fill="#d17bff" cx="150" cy="9" r="9" opacity="0.22"/>
<circle fill="#d17bff" cx="150" cy="9" r="5" opacity="0.4"/>
<circle fill="#e9c4ff" cx="150" cy="9" r="3.4"/>
<!-- глаз: белый круг + зрачок, вокруг — фиалковое свечение -->
<circle fill="#d17bff" cx="126" cy="40" r="9.5" opacity="0.22"/>
<circle fill="#fff" cx="126" cy="40" r="7"/>
<circle fill="#142638" cx="127.5" cy="40" r="3.3"/>
<circle fill="#fff" cx="125" cy="37.8" r="1.5"/>
</symbol>
<symbol id="fish-spiritfin" viewBox="0 0 160 100">
<!-- ореол: светящиеся дуги вокруг головы (сзади тела) -->
<path fill="none" stroke="#ffe07a" stroke-width="7" stroke-linecap="round" opacity="0.08" d="M76 18 Q118 -6 158 26"/>
<path fill="none" stroke="#ffe07a" stroke-width="3" stroke-linecap="round" opacity="0.55" d="M78 18 Q118 -5 158 26"/>
<path fill="none" stroke="#ffe07a" stroke-width="2.6" stroke-linecap="round" opacity="0.7" d="M88 18 Q122 1 158 32"/>
<path fill="none" stroke="#ffe07a" stroke-width="2.4" stroke-linecap="round" opacity="0.6" d="M102 18 Q132 5 158 38"/>
<path fill="none" stroke="#ffe07a" stroke-width="5" stroke-linecap="round" opacity="0.1" d="M138 82 Q162 66 158 42"/>
<path fill="none" stroke="#ffe07a" stroke-width="2.4" stroke-linecap="round" opacity="0.6" d="M138 82 Q162 66 158 42"/>
<!-- души-точки (задний план) -->
<circle fill="#ffe07a" cx="88" cy="10" r="5" opacity="0.18"/>
<circle fill="#ffe07a" cx="88" cy="10" r="2.2"/>
<circle fill="#ffe07a" cx="34" cy="18" r="6" opacity="0.18"/>
<circle fill="#ffe07a" cx="34" cy="18" r="2.6"/>
<circle fill="#ffe07a" cx="16" cy="70" r="5" opacity="0.18"/>
<circle fill="#ffe07a" cx="16" cy="70" r="2.2"/>
<!-- духовные отростки вместо хвоста: растекающиеся вниз струи -->
<path fill="var(--f3,hsl(184,34%,28%))" opacity="0.45" d="M40 30 C33 22 26 18 17 18 C26 23 32 28 36 35 Z"/>
<path fill="var(--f3,hsl(184,34%,28%))" opacity="0.8" d="M28 60 C24 72 22 84 25 97 C31 89 33 78 36 66 Z"/>
<path fill="var(--f3,hsl(184,34%,28%))" opacity="0.7" d="M44 73 C41 83 42 92 47 99 C52 91 51 82 53 73 Z"/>
<path fill="var(--f3,hsl(184,34%,28%))" opacity="0.6" d="M60 80 C59 88 62 95 68 100 C71 92 68 86 67 80 Z"/>
<path fill="var(--f3,hsl(184,34%,28%))" opacity="0.5" d="M76 84 C76 90 79 95 84 98 C86 92 84 87 82 83 Z"/>
<!-- спинной и грудной плавники: призрачные, полупрозрачные -->
<path fill="var(--f3,hsl(184,34%,28%))" opacity="0.85" d="M56 27 C64 12 82 7 96 15 C82 15 68 20 60 29 Z"/>
<path fill="var(--f3,hsl(184,34%,28%))" opacity="0.8" d="M116 60 C108 68 100 78 102 88 C112 80 120 70 124 62 Z"/>
<!-- тело: крупная призрачная «капля», полупрозрачная, тянется влево -->
<path fill="var(--f1,hsl(182,30%,40%))" opacity="0.85" d="M150 52 C150 38 138 27 118 23 C96 18.5 68 20 48 29 C38 33.5 30 40 25 47 C22 51 22 55 25 59 C30 66 38 72 48 76 C68 85 96 86.5 118 82 C138 78 150 66 150 52 Z"/>
<!-- брюхо: светлая пологая полоса снизу -->
<path fill="var(--f2,hsl(178,22%,64%))" opacity="0.85" d="M150 52 C150 66 138 78 118 82 C96 86.5 68 85 48 76 C38 72 30 66 25 59 C35 64.5 48 69 62 72 C90 78 122 74 150 52 Z"/>
<!-- духовные вихри на теле -->
<path fill="none" stroke="var(--f2,hsl(178,22%,64%))" stroke-width="2" stroke-linecap="round" opacity="0.5" d="M70 40 Q90 30 112 33"/>
<path fill="none" stroke="var(--f4,hsl(186,38%,20%))" stroke-width="2" stroke-linecap="round" opacity="0.3" d="M64 58 Q88 64 116 60"/>
<path fill="none" stroke="var(--f2,hsl(178,22%,64%))" stroke-width="1.8" stroke-linecap="round" opacity="0.4" d="M78 72 Q98 78 120 72"/>
<!-- жаберная линия у головы -->
<path fill="none" stroke="var(--f4,hsl(186,38%,20%))" stroke-width="2.5" stroke-linecap="round" opacity="0.32" d="M110 30 Q103 52 112 76"/>
<!-- пасть: тёмная щель на нижней части головы -->
<path fill="var(--f4,hsl(186,38%,20%))" d="M150 54 C140 61 128 65 118 65 C130 70 146 65 150 54 Z"/>
<!-- глаз: большой светящийся золотой -->
<circle fill="#ffe07a" cx="122" cy="44" r="13" opacity="0.18"/>
<circle fill="#ffe07a" cx="122" cy="44" r="9" opacity="0.35"/>
<circle fill="#fff3c4" cx="122" cy="44" r="6.5"/>
<circle fill="#142638" cx="122" cy="44" r="3.2"/>
<circle fill="#fff" cx="123.6" cy="42.2" r="1.4"/>
<!-- души-точки (передний план) -->
<circle fill="#ffe07a" cx="150" cy="24" r="6.5" opacity="0.2"/>
<circle fill="#ffe07a" cx="150" cy="24" r="3"/>
<circle fill="#ffe07a" cx="138" cy="88" r="5" opacity="0.2"/>
<circle fill="#ffe07a" cx="138" cy="88" r="2.2"/>
<circle fill="#ffe07a" cx="104" cy="92" r="7" opacity="0.2"/>
<circle fill="#ffe07a" cx="104" cy="92" r="3.2"/>
<circle fill="#ffe07a" cx="58" cy="94" r="5.5" opacity="0.2"/>
<circle fill="#ffe07a" cx="58" cy="94" r="2.4"/>
<circle fill="#ffe07a" cx="72" cy="70" r="4" opacity="0.35"/>
<circle fill="#ffe07a" cx="72" cy="70" r="1.8"/>
</symbol>
</svg>
<!-- FISH-SVG:END -->
<canvas id="game"></canvas>
<!-- Этап 46 (ревизия): рыбы-жильцы банки — DOM-слой тех же SVG-портретов, что на карточке улова
(спрайт FISH-SVG + вариантное оформление). Слой выключен вне сцены (body.aq-open) -->
<div id="aqFishLayer" aria-hidden="true"></div>
<div id="hud">
<div class="hudleft">
<div id="coins">🪙 0</div>
<span id="weather" class="hidden"></span>
</div>
<div class="hudbtns">
<button id="btnShop">🛒</button>
<button id="btnPause" class="hidden" title="Пауза">⏸</button>
</div>
</div>
<button id="btnRecall" class="hidden">↩</button>
<div id="toast"></div>
<!-- Меню -->
<div id="menu" class="overlay">
<div class="panel">
<div class="title" id="menuTitle">🎣 РЫБАЛКА</div>
<!-- Y5: i18n — содержимое <p> и кнопки заполняет renderMenu() из T (RU-значения те же) -->
<p id="menuP1">👆 <b>Держи палец</b> — заряжай бросок,<br>
<b>отпусти</b> — кидай удочку.<br>
Дальше бросок = реже и жирнее рыба!</p>
<p id="menuP2" style="margin-top:8px">Видишь <b style="color:#ff6b5e">!</b> — быстро жми, чтобы зацепить.<br>
При вываживании: тяни, когда рыба отдыхает,<br>
отпусти, когда она <b>тянет</b> — иначе лопнет!<br>
Не тяни слишком долго — рыба <b>сбегает</b> (красная полоса)!</p>
<p id="menuP3" style="margin-top:8px">У каждой рыбы свой <b>вес</b>, продажа — по цене за кг.<br>
У удочек есть <b>предел веса</b>: перевесишь — шнур лопнет! <br>
Лучшие снасти = больше шансов на трофей 🏆</p>
<p id="menuP4" style="margin-top:8px">Не каждый заброс — с клёвом: если молчит — подожди.<br>
У удилищ есть <b>тормоз (drag)</b>: рывок сильнее — леска скользит!</p>
<button id="btnPlay" class="big">Играть</button>
</div>
</div>
<!-- Магазин -->
<div id="shop" class="overlay hidden">
<div class="panel">
<button id="btnCloseShop">×</button>
<div class="panelhead" id="shopTitle">🛒 Лавка рыбака</div>
<div class="tabs">
<button id="tabTackle" class="active" title="Лавка">🛒</button>
<button id="tabJournal" title="Дневник">📔</button>
<button id="tabRewards" title="Награды">🎯</button>
<button id="tabAch" title="Достижения">🏅</button>
<button id="tabSkins" title="Скины">🎨</button>
<button id="tabLocations" title="Локации">🗺️</button>
</div>
<div id="shopBody"></div>
</div>
</div>
<!-- Подтверждение сброса -->
<div id="resetDlg" class="overlay hidden">
<div class="panel">
<div class="panelhead" id="resetTitle">🗑️ Сбросить прогресс?</div>
<p id="resetText" style="margin-top:8px">Монеты, снасти и коллекция будут стёрты.<br>Это действие <b>нельзя отменить</b>.</p>
<div class="twobtns">
<button id="btnResetNo" class="big">Отмена</button>
<button id="btnResetYes" class="big danger">Сбросить</button>
</div>
</div>
</div>
<!-- Пауза (треб. Яндекс Игр 6.3) -->
<div id="pause" class="overlay hidden">
<div class="panel">
<div class="panelhead" id="pauseTitle">⏸ Пауза</div>
<div class="twobtns">
<button id="btnPauseResume" class="big">Продолжить</button>
<button id="btnPauseMenu" class="big">В меню</button>
</div>
</div>
</div>
<!-- Меню (открывается из паузы «В меню»): хаб — игра остаётся на паузе-оверлее,
текущая сессия (заброс/вываживание) сохраняется до «Продолжить» -->
<div id="gamemenu" class="overlay hidden">
<div class="panel">
<div class="panelhead" id="gmTitle">🎣 Меню</div>
<div class="mbtns">
<button id="btnGmResume" class="mbtn">Продолжить</button>
<button id="btnGmShop" class="mbtn">🛒 Магазин</button>
<button id="btnGmAch" class="mbtn">🏅 Достижения</button>
<button id="btnGmJournal" class="mbtn">📔 Дневник</button>
<button id="btnGmAquarium" class="mbtn">🐠 Аквариум</button>
<button id="btnGmHowto" class="mbtn">📖 Инструкции</button>
<button id="btnMute" class="mbtn">🔊 Звук</button>
<button id="btnReset" class="mbtn" title="Сбросить прогресс">🗑️ Очистить</button>
</div>
</div>
</div>
<!-- Карточка улова -->
<div id="card" class="overlay hidden">
<div class="panel">
<div class="rarity" id="cardRarity">Обычная</div>
<div><span class="record hidden" id="cardRecord">🏆 РЕКОРД!</span><span class="variant-badge hidden" id="cardVariant">ЗОЛОТАЯ</span><span class="boss-badge hidden" id="cardBoss">🏆 БОСС!</span></div>
<span class="bigemoji" id="cardEmoji"><svg viewBox="0 0 160 100"><use id="cardFishUse" href="#fish-carass"/></svg></span>
<div class="cname" id="cardName">Карась</div>
<div class="csub" id="cardSub">0.0 кг · 0 🪙/кг</div>
<div class="cval" id="cardVal">+0 🪙</div>
<!-- Y2: rewarded-видео «монеты ×2» (чистый бонус; 4.5.1 — что получим, написано прямо на кнопке) -->
<button id="btnRv" class="rvbtn hidden" title="Посмотрите рекламу — двойная цена за этот улов">📺 Реклама: ×2 за этот улов</button>
<!-- Этап 46: «В аквариум» (модель C — бесплатная копия экземпляра; catchFish не трогаем) -->
<button id="btnKeep" class="aqbtn">🐠 В аквариум</button>
<div class="twobtns">
<button id="btnCardOk" class="big">Отлично!</button>
</div>
</div>
</div>
<!-- Этап 46: сцена аквариума — DOM-бар и поповер поверх canvas (сама сцена рисуется в drawAquarium) -->
<div id="aqBar" class="hidden">
<button id="btnAqBack" class="aqpill">← Назад</button>
<span id="aqCount">0/6</span>
<button id="btnAqSlot" class="aqpill">+ Слот</button>
</div>
<div id="aqPop" class="hidden">
<div id="aqPopName"></div>
<div id="aqPopSub"></div>
<button id="btnAqRelease" class="aqpill">Выпустить</button>
</div>
<script>
'use strict';
/* =========================================================
ДАННЫЕ
========================================================= */
const SPECIES=[
{id:'carass', name:'Карась', nameEn:'Crucian carp', rarity:0, weight:100, minDist:0.00, strength:0.25, wMin:0.1, wMax:0.8, price:20, hue:45},
{id:'perch', name:'Окунь', nameEn:'Perch', rarity:0, weight:55, minDist:0.05, strength:0.30, wMin:0.1, wMax:1.5, price:22, hue:120},
{id:'bream', name:'Лещ', nameEn:'Bream', rarity:1, weight:26, minDist:0.30, strength:0.40, wMin:0.3, wMax:3.0, price:25, hue:210},
{id:'carp', name:'Карп', nameEn:'Carp', rarity:1, weight:22, minDist:0.35, strength:0.45, wMin:0.5, wMax:8.0, price:28, hue:30},
{id:'pike', name:'Щука', nameEn:'Pike', rarity:2, weight:9, minDist:0.50, strength:0.60, wMin:1.0, wMax:10.0, price:35, hue:100},
{id:'catfish',name:'Сом', nameEn:'Catfish', rarity:2, weight:5, minDist:0.65, strength:0.75, wMin:2.0, wMax:20.0, price:45, hue:260},
{id:'sturge', name:'Осётр', nameEn:'Sturgeon', rarity:3, weight:2.5, minDist:0.80, strength:0.85, wMin:5.0, wMax:40.0, price:65, hue:200},
{id:'gold', name:'Золотая рыбка', nameEn:'Golden Fish', rarity:4, weight:1.2, minDist:0.90, strength:0.90, wMin:0.05, wMax:1.0, price:1500, hue:45},
/* Этап 38: лестница веса по локациям (дороже вода = тяжелее рыба = сложнее бой):
Озёра ×8, Море ×6 (Рыба-меч ×4), Океан ×4 (Синий кит ×2 — чтобы остался вываживаемым);
Река не меняется (пины §9j/M4/M6). Правятся только wMin/wMax — ролл-веса
(RIVER_*, LAKE_*, SEA_*, OCEAN_*) не тронуты */
/* Этап 5: жильцы Озёр (в реку не заходят — ролл реки по RIVER_*; порядок 0..7 не трогаем);
weight у новых видов не используется для ролла: река — RIVER_*, Озёра — LAKE_DAY_WEIGHTS/LAKE_NIGHT_WEIGHTS */
{id:'zander', name:'Судак', nameEn:'Zander', rarity:2, weight:8, minDist:0.45, strength:0.60, wMin:8.0, wMax:48.0, price:8, hue:180},
{id:'chuch', name:'Хариус', nameEn:'Grayling', rarity:1, weight:18, minDist:0.35, strength:0.35, wMin:1.6, wMax:16.0, price:6, hue:25},
{id:'crayfish',name:'Гигантский рак', nameEn:'Giant Crayfish', rarity:3, weight:1.5, minDist:0.70, strength:0.50, wMin:1.6, wMax:8.0, price:40, hue:0},
/* Этап 33: ещё пять жильцов Озёр (в реку не заходят — ролл реки по RIVER_*; порядок 0..7 и записи
этапа 5 не тронуты); weight не используется для ролла Озёр — там LAKE_*_WEIGHTS */
{id:'bleak', name:'Плотва', nameEn:'Roach', rarity:0, weight:70, minDist:0.05, strength:0.28, wMin:0.4, wMax:4.8, price:4, hue:200},
{id:'roundel',name:'Густера', nameEn:'White bream', rarity:0, weight:34, minDist:0.15, strength:0.32, wMin:0.8, wMax:7.2, price:5, hue:215},
{id:'eelpout',name:'Вьюн', nameEn:'Weather loach', rarity:1, weight:12, minDist:0.40, strength:0.30, wMin:0.4, wMax:3.2, price:11, hue:35},
{id:'tench', name:'Линь', nameEn:'Tench', rarity:2, weight:10, minDist:0.55, strength:0.55, wMin:2.4, wMax:32.0, price:16, hue:95},
{id:'navaga', name:'Навага', nameEn:'Navaga', rarity:3, weight:2, minDist:0.75, strength:0.70, wMin:2.4, wMax:20.0, price:50, hue:195},
/* Этап 35: у каждой локации — своя ихтиофауна (без пересечения с Рекой).
Две новые озёрные рыбы (в Озёра, в реку не заходят); weight не для ролла — там LAKE_*_WEIGHTS */
{id:'rudd', name:'Краснопёрка', nameEn:'Rudd', rarity:1, weight:20, minDist:0.25, strength:0.34, wMin:0.8, wMax:9.6, price:5, hue:25},
{id:'cisco', name:'Сиг', nameEn:'Cisco', rarity:2, weight:11, minDist:0.58, strength:0.58, wMin:4.0, wMax:28.0, price:18, hue:200},
/* Этап 35: Море — 5 морских видов (только в Море, id с конца; ролл — SEA_*_WEIGHTS) */
{id:'herring', name:'Сельдь', nameEn:'Herring', rarity:0, weight:60, minDist:0.05, strength:0.28, wMin:0.6, wMax:4.8, price:8, hue:205},
{id:'mackerel',name:'Скумбрия', nameEn:'Mackerel', rarity:1, weight:30, minDist:0.30, strength:0.42, wMin:1.8, wMax:15.0, price:18, hue:190},
{id:'flounder',name:'Камбала', nameEn:'Flounder', rarity:2, weight:12, minDist:0.50, strength:0.60, wMin:3.0, wMax:30.0, price:33, hue:40},
{id:'tuna', name:'Тунец', nameEn:'Tuna', rarity:3, weight:4, minDist:0.72, strength:0.80, wMin:12.0, wMax:72.0, price:46, hue:210},
{id:'swordfish',name:'Рыба-меч', nameEn:'Swordfish', rarity:4, weight:1.5, minDist:0.88, strength:0.92, wMin:20.0, wMax:80.0, price:81, hue:250},
/* Этап 36: Океан — 9 глубоководных видов (только Океан; ролл — OCEAN_*_WEIGHTS).
minDist/strength — кривые по редкости; портреты — спрайт FISH-SVG (эмодзи рыб убраны в этапе 42) */
{id:'moray', name:'Гигантская мурена', nameEn:'Giant Moray Eel', rarity:0, weight:30, minDist:0.10, strength:0.35, wMin:6.0, wMax:24.0, price:5, hue:50},
{id:'grouper', name:'Горбуна', nameEn:'Grouper', rarity:0, weight:25, minDist:0.20, strength:0.35, wMin:8.0, wMax:40.0, price:5, hue:15},
{id:'turtle', name:'Морская черепаха', nameEn:'Green Sea Turtle', rarity:1, weight:10, minDist:0.35, strength:0.45, wMin:20.0, wMax:56.0, price:9, hue:140},
{id:'angler', name:'Удильщик', nameEn:'Anglerfish', rarity:2, weight:6, minDist:0.50, strength:0.55, wMin:4.0, wMax:16.0, price:21, hue:280},
{id:'octopus', name:'Гигантский осьминог', nameEn:'Giant Octopus', rarity:2, weight:4, minDist:0.55, strength:0.60, wMin:16.0, wMax:48.0, price:23, hue:350},
{id:'manta', name:'Скат-манта', nameEn:'Manta Ray', rarity:3, weight:3, minDist:0.75, strength:0.75, wMin:24.0, wMax:60.0, price:29, hue:220},
{id:'shark', name:'Большая белая акула', nameEn:'Great White Shark', rarity:3, weight:2.5, minDist:0.78, strength:0.78, wMin:20.0, wMax:56.0, price:31, hue:210},
{id:'squid', name:'Гигантский кальмар', nameEn:'Giant Squid', rarity:4, weight:2.5, minDist:0.85, strength:0.85, wMin:16.0, wMax:48.0, price:37, hue:300},
{id:'whale', name:'Синий кит', nameEn:'Blue Whale', rarity:4, weight:2, minDist:0.92, strength:0.95, wMin:40.0, wMax:100.0, price:67, hue:230},
/* Этап 45: Волшебное болото — 5 светящихся видов (только в конец массива: SPECIES[0..7]
запинены тестами/квестами). Новое поле glow — цвет ночного свечения (у старых видов нет) */
{id:'glowfin', name:'Светлячок', nameEn:'Glowfin', rarity:0, weight:38, minDist:0.05, strength:0.28, wMin:0.3, wMax:3.0, price:8, hue:185, glow:'#5ff2ff'},
{id:'moonfish', name:'Лунная рыбка', nameEn:'Moonfish', rarity:1, weight:24, minDist:0.30, strength:0.40, wMin:0.8, wMax:8.0, price:13, hue:225, glow:'#b9c8ff'},
{id:'emberfin', name:'Изумрудный светляк', nameEn:'Emerald Glowfish', rarity:2, weight:14, minDist:0.55, strength:0.58, wMin:1.5, wMax:16.0, price:20, hue:150, glow:'#57ffa8'},
{id:'violetlure',name:'Фиалковый огонёк', nameEn:'Violet Lure', rarity:3, weight:5, minDist:0.75, strength:0.80, wMin:2.0, wMax:24.0, price:38, hue:280, glow:'#d17bff'},
{id:'spiritfin', name:'Дух болота', nameEn:'Swamp Spirit', rarity:4, weight:2.5, minDist:0.88, strength:0.88, wMin:0.5, wMax:6.0, price:70, hue:45, glow:'#ffe07a'},
];
const RARITY_NAMES=['Обычная','Необычная','Редкая','Эпическая','Легендарная'];
const RARITY_NAMES_EN=['Common','Uncommon','Rare','Epic','Legendary']; // Y5: i18n — EN-названия редкостей
const RARITY_COLORS=['#9fc3e2','#2ecc71','#4da3ff','#c56cf0','#ffd75e'];
/* M3: ночная таблица — те же виды, но веса спавна смещены к ночной рыбе (клон SPECIES);
Этап 5: +ночные веса новых видов (zander 6 / chuch 10 / crayfish 2.5);
Этап 33: +озёрные ночные веса пяти новых видов (значения нужны ВСЕМ видам — SPECIES_NIGHT
строится как NIGHT_WEIGHTS[s.id], у пропущенного id вес стал бы undefined) */
const NIGHT_WEIGHTS={carass:40,perch:80,bream:10,carp:8,pike:22,catfish:18,sturge:4,gold:1.2,zander:6,chuch:10,crayfish:2.5,bleak:20,roundel:14,eelpout:18,tench:12,navaga:3,rudd:14,cisco:9,herring:30,mackerel:16,flounder:8,tuna:3,swordfish:1.5,moray:20,grouper:18,turtle:8,angler:6,octopus:4,manta:2.5,shark:2.5,squid:2,whale:2,glowfin:38,moonfish:24,emberfin:14,violetlure:5,spiritfin:2.5}; // Этап 36: +океанские id; Этап 45: +болотные (у Болота свои таблицы — значения декоративные, главное — ключи есть, иначе weight=undefined)
const SPECIES_NIGHT=SPECIES.map(s=>Object.assign({},s,{weight:NIGHT_WEIGHTS[s.id]}));
/* Этап 5: Локации — Река (родная вода, бесплатно) и Озёра (65536 🪙, новые рыбы).
Этап 35: +Море (131072 🪙). Этап 36: +Океан (196608 🪙). Этап 45: +Волшебное болото (90000 🪙).
У каждой локации СВОЯ ихтиофауна, без пересечений:
Река=8, Озёра=10, Море=5, Океан=9, Болото=5 (см. *_IDS ниже).
water: [dayTop, dayMid, dayBot, nightTop, nightMid, nightBot] — базовые пары цветов
градиента drawWater(): день ↔ ночь плавно через nightMix (логика не меняется).
Этап 43: визуальное различение локаций — (1) вода различима по цвету (Река/Озёра не
тронуты; Море — светлая бирюза, Океан — глубокий тёмно-синий; тест пинит только ФОРМАТ
6 hex на локацию — значения можно двигать); (2) waves — характер волн поверхности в
drawWater(): amp/amp2 — амплитуда, freq/freq2 — частота, speed/speed2 — скорость;
amp/amp2=0 — линии НЕ рисуются (Река — без волн, спокойная вода — ревизия Этапа 44);
Озёра — длинная медленная гладь; Море — умеренная волна; Океан — крупные зыби;
Этап 45: Волшебное болото — слабая рябь поверх мрачной тёмно-моховой воды.
Чисто визуал, на механику/баланс не влияет. */
const LOCATIONS=[
{id:0, name:'Река', nameEn:'River', cost:0, desc:'родная вода', descEn:'home waters',
water:['#2f9bd8','#1f6fb0','#0a2f52','#0d2246','#091c3a','#041226'],
waves:{amp:0,amp2:0,freq:0,freq2:0,speed:0,speed2:0}}, // Река — без волновых линий (спокойная вода)
{id:1, name:'Озёра', nameEn:'Lakes', cost:65536, desc:'озёрные рыбы: судак, хариус, линь, навага, сиг, гигантский рак и другие', descEn:'lake fish: zander, grayling, tench, navaga, cisco, giant crayfish and more',
water:['#3d9c8a','#20726a','#0c423c','#0f2b33','#0a2129','#04141a'],
waves:{amp:1.2,amp2:1.6,freq:0.03,freq2:0.025,speed:0.8,speed2:0.5}},
{id:2, name:'Море', nameEn:'Sea', cost:131072, desc:'морская рыба: скумбрия, камбала, тунец, рыба-меч и другие', descEn:'sea fish: mackerel, flounder, tuna, swordfish and more',
water:['#41b1e8','#2287c9','#0b3d6e','#112e5c','#0a2348','#04102a'],
waves:{amp:3.5,amp2:4.5,freq:0.045,freq2:0.035,speed:1.8,speed2:1.2}},
{id:3, name:'Океан', nameEn:'Ocean', cost:196608, desc:'глубоководные гиганты: синий кит, гигантский кальмар, скат-манта, гигантский осьминог и другие', descEn:'deep-sea giants: blue whale, giant squid, manta ray, giant octopus and more',
water:['#1a5fa8','#0c3d74','#031a3c','#081430','#050d22','#020611'],
waves:{amp:6,amp2:8,freq:0.035,freq2:0.028,speed:1.5,speed2:1.0}},
{id:4, name:'Волшебное болото', nameEn:'Magic Swamp', cost:90000, desc:'светящиеся обитатели: светлячок, лунная рыбка, изумрудный светляк, фиалковый огонёк и дух болота', descEn:'glowing dwellers: glowfin, moonfish, emerald glowfish, violet lure and swamp spirit',
water:['#4d6b38','#2e4a28','#122818','#0d1f12','#08160c','#030a06'], // Этап 45: мрачно-болотная тёмно-зелёная вода (ночь — почти чёрная с зеленью)
waves:{amp:0.8,amp2:0.5,freq:0.025,freq2:0.02,speed:0.5,speed2:0.35}} // слабая рябь (тише Озёр)
];
/* Река — только 8 базовых видов: роллы реки остаются прежними (новые виды заходят только в Озёра).
Фильтр по id: порядок и веса записей — ровно как в SPECIES/SPECIES_NIGHT */
const RIVER_IDS=['carass','perch','bream','carp','pike','catfish','sturge','gold'];
const RIVER_SPECIES=SPECIES.filter(s=>RIVER_IDS.indexOf(s.id)>=0);
const RIVER_SPECIES_NIGHT=SPECIES_NIGHT.filter(s=>RIVER_IDS.indexOf(s.id)>=0);
/* Этап 35: у каждой локации — ТОЛЬКО свои виды (без пересечений):
Река=8 (RIVER_IDS), Озёра=10 (LAKE_IDS), Море=5 (SEA_IDS); Этап 36: +Океан=9 (OCEAN_IDS).
SPECIES_NIGHT — источник ночных весов только для реки; у Озёр, Моря и Океана свои таблицы.
Этап 34 (до разделения): доход озёр держался на речной рыбе (carass/perch) — после
эксклюзивности доли перераспределены на своих жильцов, доход СОХРАНЁН и поднят:
день ≈121 🪙 (было 110.4 с речными), ночь ≈134 (было 145.5; ночь реки 125.9 — озёра
снова впереди). Море (этап 35): день ≈190, ночь ≈222 — топ-локация за 300000 🪙.
Пол редких: мин. вес ≥ ~1.2 (swordfish) — за 3000 роллов ожидается ≥40 попаданий,
тест «каждый вид ≥1» проходит с запасом.
Этап 40: ночные *_WEIGHTS подтянуты к «ночь доходнее» (Озёра: +навaga/сиг/судак,
−вьюн/хариус/плотва; Море: ночь смещена к камбале/тунцу/мечу сильнее; Океан:
+кит/манта/акула/кальмар/осьминог, −мурена/горбуна) + доля сельди/скумбрии в Море
снижена (день 82→79%, ночь 78→64%); инвариант «каждая новая вода доходнее в ОБЕ
фазы» сохраняется (Океан/Море день ×1.11 — тонкий запас, см. AGENTS.md) */
const LAKE_IDS=['zander','chuch','crayfish','bleak','roundel','eelpout','tench','navaga','rudd','cisco'];
const LAKE_DAY_WEIGHTS={zander:20,chuch:8,crayfish:4,bleak:8,roundel:6,eelpout:3,tench:20,navaga:4.5,rudd:6,cisco:14};
const LAKE_NIGHT_WEIGHTS={zander:32,chuch:3,crayfish:5,bleak:3,roundel:2.5,eelpout:4,tench:24,navaga:10,rudd:2.5,cisco:18}; // Этап 40: ночь доходнее (крупная/дорогая: судак/линь/навага/сиг)
const LAKE_SPECIES=LAKE_IDS.map(id=>Object.assign({},SPECIES.find(s=>s.id===id),{weight:LAKE_DAY_WEIGHTS[id]}));
const LAKE_SPECIES_NIGHT=LAKE_IDS.map(id=>Object.assign({},SPECIES.find(s=>s.id===id),{weight:LAKE_NIGHT_WEIGHTS[id]}));
/* Этап 35: Море — только морские виды; ночь смещена к хищникам (камбала/тунец/рыба-меч).
Этап 40: доля сельди/скумбрии снижена (день 82→79%, ночь 78→64%) — средневесовое
Море тяжелее; день ограничен инвариантом «Море < Океан» (Океан/Море ×1.11) */
const SEA_IDS=['herring','mackerel','flounder','tuna','swordfish'];
const SEA_DAY_WEIGHTS={herring:32,mackerel:32,flounder:12,tuna:3,swordfish:1.5};
const SEA_NIGHT_WEIGHTS={herring:18,mackerel:20,flounder:15,tuna:4,swordfish:2.2};
const SEA_SPECIES=SEA_IDS.map(id=>Object.assign({},SPECIES.find(s=>s.id===id),{weight:SEA_DAY_WEIGHTS[id]}));
const SEA_SPECIES_NIGHT=SEA_IDS.map(id=>Object.assign({},SPECIES.find(s=>s.id===id),{weight:SEA_NIGHT_WEIGHTS[id]}));
/* Этап 36: Океан — только свои 9 видов; ночь — смещение к крупным (паттерн LAKE/SEA).
Этап 40: ночь сильнее к гигантам (кит 2.5→4, манта 3.5→5, акула/кальмар 3→4.5, осьминог 6→8;
мурена/горбуна 32/28→26/22) — ночь доходнее */
const OCEAN_IDS=['moray','grouper','turtle','angler','octopus','manta','shark','squid','whale'];
const OCEAN_DAY_WEIGHTS={moray:40,grouper:32,turtle:10,angler:8,octopus:5,manta:3,shark:2.5,squid:2.5,whale:2};
const OCEAN_NIGHT_WEIGHTS={moray:26,grouper:22,turtle:11,angler:8,octopus:8,manta:5,shark:4.5,squid:4.5,whale:4};
const OCEAN_SPECIES=OCEAN_IDS.map(id=>Object.assign({},SPECIES.find(s=>s.id===id),{weight:OCEAN_DAY_WEIGHTS[id]}));
const OCEAN_SPECIES_NIGHT=OCEAN_IDS.map(id=>Object.assign({},SPECIES.find(s=>s.id===id),{weight:OCEAN_NIGHT_WEIGHTS[id]}));
/* Этап 45: Волшебное болото — только свои 5 светящихся видов (паттерн LAKE/SEA/OCEAN).
Баланс (tools/balance.mjs, нейтральная снасть): день ≈240.3 🪙, ночь ≈328.9 🪙 —
между Озёрами (194.1/249.0) и Морем (297.3/476.7) в ОБЕ фазы; ночь/день ×1.37.
Ночью доля редких/дорогих (violetlure/emberfin) выше, дешёвый glowfin и spiritfin падают.
Минимальный вес ≥2.5 (тест «каждый вид ≥1» за 3000 роллов проходит с запасом).
Значения NIGHT_WEIGHTS новых id — декоративные (у Болота своя таблица). */
const SWAMP_IDS=['glowfin','moonfish','emberfin','violetlure','spiritfin'];
const SWAMP_DAY_WEIGHTS={glowfin:3,moonfish:4,emberfin:28,violetlure:13,spiritfin:4.5};
const SWAMP_NIGHT_WEIGHTS={glowfin:2.5,moonfish:2.5,emberfin:20,violetlure:30,spiritfin:4};
const SWAMP_SPECIES=SWAMP_IDS.map(id=>Object.assign({},SPECIES.find(s=>s.id===id),{weight:SWAMP_DAY_WEIGHTS[id]}));
const SWAMP_SPECIES_NIGHT=SWAMP_IDS.map(id=>Object.assign({},SPECIES.find(s=>s.id===id),{weight:SWAMP_NIGHT_WEIGHTS[id]}));
/* Этап 45: табличный выбор таблицы ролла по save.location (0..4) — используется в pickSpecies();
guard «вне 0..4 → Река» там же. Порядок обязан совпадать с LOCATIONS */
const SPECIES_BY_LOCATION=[RIVER_SPECIES,LAKE_SPECIES,SEA_SPECIES,OCEAN_SPECIES,SWAMP_SPECIES];
const SPECIES_BY_LOCATION_NIGHT=[RIVER_SPECIES_NIGHT,LAKE_SPECIES_NIGHT,SEA_SPECIES_NIGHT,OCEAN_SPECIES_NIGHT,SWAMP_SPECIES_NIGHT];
/* Этап 37: босс в каждой локации — id босса по локации (Река=осётр как в M4,
Озёра=гигантский рак, Море=рыба-меч, Океан=синий кит). Босс — существующий вид
с runtime-флагом boss:true (паттерн M4), новых видов нет. Чтение — в startBite()
Этап 45: Болото=дух болота (spiritfin) */
const BOSS_BY_LOCATION={0:'sturge',1:'crayfish',2:'swordfish',3:'whale',4:'spiritfin'};
/* M6: шанс gold-варианта (let — автотест форсирует значения, как раньше) */
let SHINY_CHANCE=0.06;
/* M6: варианты рыб — таблица (порядок = лестница ценности и порядок ролла).
Ролл по порядку: copper → silver → quartz → gold (SHINY_CHANCE) → emerald → diamond → rainbow, иначе normal.
P(особой)≈31% без буста снасти, E[mult]≈1.36; топ лестницы — радужная (×5, самая редкая).
Снасть (тип наживки + её уровень) усиливает шансы — см. variantBoost()/variantChance() */
const VARIANTS=[
{id:'normal', name:'Обычная', nameEn:'Normal', mult:1, chance:0, css:''},
{id:'copper', name:'Медная', nameEn:'Copper', mult:1.5, chance:0.12, css:'copper'},
{id:'silver', name:'Серебряная', nameEn:'Silver', mult:2, chance:0.08, css:'silver'},
{id:'quartz', name:'Кварцевая', nameEn:'Quartz', mult:2.5, chance:0.07, css:'quartz'},
{id:'gold', name:'Золотая', nameEn:'Gold', mult:3, chance:0.06, css:'gold'}, // chance — только для читабельности: у gold живая SHINY_CHANCE
{id:'emerald', name:'Изумрудная', nameEn:'Emerald', mult:4, chance:0.01, css:'emerald'},
{id:'diamond', name:'Алмазная', nameEn:'Diamond', mult:4.5, chance:0.007, css:'diamond'},
{id:'rainbow', name:'Радужная', nameEn:'Rainbow', mult:5, chance:0.005, css:'rainbow'},
];
let forceVariant=null; // M6: тест-форс варианта (id из VARIANTS/null — всегда даёт его, паттерн forceBoss)
/* M6: счётчики вариантов в caught[id] (normal — без счётчика; sn — «shiny» = gold) */
const VARIANT_KEY={copper:'cp',silver:'sv',quartz:'qz',gold:'sn',emerald:'em',diamond:'dm',rainbow:'rb'};
/* M6+: буст вариантов от снасти — тип наживки (её эффективный rare-стат: 0/0.2/0.8/2.0,
у 3–4 ур. +1.0) и уровень апгрейда наживки (1..4). Простая наживка 1 ур. — B=0 (шансы базовые) */
function variantBoost(){
return lure().rare*0.15+(lureLvOf(save.lure)-1)*0.05;
}
function variantChance(v){
let c=v.id==='gold'?SHINY_CHANCE:v.chance; // chance gold — живая SHINY_CHANCE
if(v.id!=='normal'){
// M8: дождь — особые варианты ярче (×3; босс всегда normal — не доходит сюда)
if(weatherActive()==='rain') c*=WEATHER.rain.variantMult;
// M6+: снасть усиливает варианты — множитель ×(1+B·r), r — номер в лестнице VARIANTS (1..7):
// чем реже вариант, тем сильнее прибавка (медь ×(1+B) … радуга ×(1+7B))
c*=1+variantBoost()*VARIANTS.indexOf(v);
}
return c;
}
/* M6: ролл варианта улова */
function rollVariant(){
if(forceVariant){
const v=VARIANTS.find(x=>x.id===forceVariant);
if(v) return v;
}
for(const v of VARIANTS){ if(v.id==='normal') continue;
if(Math.random()<variantChance(v)) return v;
}
return VARIANTS.find(x=>x.id==='normal');
}
/* M4: босс-рыба (Этап 37: в каждой локации) — тест-форс появления (let — автотест, как SHINY_CHANCE) */
let forceBoss=false;
/* Спринт 4: пустые клёвы — тест-форс клёва (let — автотест, паттерн forceBoss) */
let forceBite=false;
/* M8: погода — дождь (варианты ×3) и туман (клёв ×1,5); события раз в 120–240 с, длятся 120 с */
const WEATHER={
rain:{icon:'🌧️', variantMult:3, toast:'Дождь: шанс особых рыб ×3'},
fog:{icon:'🌫️', biteMult:1.5, toast:'Туман: клёв чаще ×1,5'}
};
const WEATHER_GAP_MIN=120, WEATHER_GAP_MAX=240; // сек до следующего события (случайный разброс)
const WEATHER_DURATION=120; // сек активного события
let forceWeather=null; // M8: тест-форс погоды ('rain'/'fog'/null — активна всегда, паттерн forceBoss)
const RODS=[
{id:0, name:'Дедова удочка', nameEn:"Grandpa's Rod", icon:'🧹', cost:0, maxW:3, line:100, drag:34, reel:1.0, size:0.00, desc:'До 3 кг · Нагрузка 100 · Drag 34 · Подсечка ×1.0', descEn:'Up to 3 kg · Load 100 · Drag 34 · Hookset ×1.0'},
{id:1, name:'Стеклопластик', nameEn:'Fiberglass', icon:'🎣', cost:875, maxW:8, line:140, drag:47, reel:1.3, size:0.08, desc:'До 8 кг · Нагрузка 140 · Drag 47 · Подсечка ×1.3', descEn:'Up to 8 kg · Load 140 · Drag 47 · Hookset ×1.3'},
{id:2, name:'Карбоновая', nameEn:'Carbon', icon:'🏹', cost:4500, maxW:18, line:190, drag:63, reel:1.7, size:0.16, desc:'До 18 кг · Нагрузка 190 · Drag 63 · Подсечка ×1.7', descEn:'Up to 18 kg · Load 190 · Drag 63 · Hookset ×1.7'},
{id:3, name:'Титан', nameEn:'Titanium', icon:'💪', cost:15000, maxW:40, line:260, drag:87, reel:2.3, size:0.28, desc:'До 40 кг · Нагрузка 260 · Drag 87 · Подсечка ×2.3', descEn:'Up to 40 kg · Load 260 · Drag 87 · Hookset ×2.3'},
];
const LURES=[
{id:0, name:'Простой крючок', nameEn:'Simple Hook', icon:'🪝', cost:0, cast:1.00, bite:1.0, rare:0.0, size:0.00, desc:'Надёжно, но рыба не в восторге', descEn:'Reliable, but the fish are not thrilled'},
{id:1, name:'Червь', nameEn:'Worm', icon:'🪱', cost:625, cast:1.00, bite:1.3, rare:0.2, size:0.12, desc:'Клёв на 30% чаще, шанс крупной выше', descEn:'30% more bites, better chance of big fish'},
{id:2, name:'Воблер', nameEn:'Wobbler', icon:'🎣', cost:3000, cast:1.15, bite:1.2, rare:0.8, size:0.28, desc:'Дальше бросок, приманивает крупных', descEn:'Farther casts, attracts big fish'}, // Э42: иконка 🎣 (эмодзи рыб убраны)
{id:3, name:'Золотая блёстка', nameEn:'Gold Spinner', icon:'✨', cost:11250, cast:1.20, bite:1.4, rare:2.0, size:0.50, desc:'Лучшее, что есть. К ней плывут легенды', descEn:'The best there is — legends come to it'},
];
/* M5: апгрейды снастей — уровни 1..4 (макс). id 0 (база 0) — фиксированные цены
переходов 1→2, 2→3, 3→4; снасти id>0 — доля UPG_MULT от их базовой стоимости */
const ROD_UPG_COST=[70,210,500];
const LURE_UPG_COST=[60,160,400];
const UPG_MULT=[0.2,0.6,1.2]; // доля базы: →2 ур ×0.2, →3 ур ×0.6, →4 ур ×1.2
/* Что даёт следующий уровень (индекс = текущий уровень − 1) — подпись в лавке */
const ROD_UPG_NEXT=['фонарик (ночь), леска ×1.15','тормоз ×1.15, катушка ×1.10','леска ещё ×1.15, крупные +0.10'];
const LURE_UPG_NEXT=['клёв ×1.15','редкие +1.0','крупные +0.15'];
/* Y5: i18n — EN-версии подписей уровней (индексы те же) */
const ROD_UPG_NEXT_EN=['flashlight (night), line ×1.15','drag ×1.15, reel ×1.10','line ×1.15 more, big fish +0.10'];
const LURE_UPG_NEXT_EN=['bites ×1.15','rare +1.0','big fish +0.15'];
/* Цена перехода снасти i на следующий уровень (lv — текущий 1..3): id 0 — фикс, id>0 — база×множитель */
function upgCost(type,i,lv){
if(i===0) return (type==='rod'?ROD_UPG_COST:LURE_UPG_COST)[lv-1];
const base=(type==='rod'?RODS:LURES)[i].cost;
return Math.round(base*UPG_MULT[lv-1]/10)*10;
}
/* Этап 4: скины лодки и поплавка — чистая косметика (coin-sink), в лавке вкладка «Скины» */
const BOAT_SKINS=[
{id:0, name:'Обычная', nameEn:'Classic', cost:0},
{id:1, name:'Красная лодка', nameEn:'Red Boat', cost:800},
{id:2, name:'Лодка-домик', nameEn:'Boat House', cost:2000}
];
const BOBBER_SKINS=[
{id:0, name:'Обычный', nameEn:'Classic', cost:0},
{id:1, name:'Красный', nameEn:'Red', cost:500},
{id:2, name:'Неоновый', nameEn:'Neon', cost:1500}
];
/* Этап 46: Аквариум — декоративная сцена коллекции ЭКЗЕМПЛЯРОВ (вид+вариант+вес), не вода:
в LOCATIONS не добавляем (иначе сломаются роллы/боссы/баланс). Слоты: старт AQ_BASE_SLOTS,
максимум AQ_MAX_SLOTS; цена следующего слота — AQ_SLOT_COSTS[aqSlots-AQ_BASE_SLOTS]
(в масштабе цен локаций 65k–196k это доступный coin-sink). Экономику улова (catchFish
платит как раньше) не трогаем — «В аквариум» лишь копирует экземпляр (модель C). */
const AQ_BASE_SLOTS=6;
const AQ_MAX_SLOTS=12;
const AQ_SLOT_COSTS=[1500,4000,9000,20000,45000,100000];
/* =========================================================
СОХРАНЕНИЕ
========================================================= */
const SAVE_KEY='fishing-save-v1';
let save={coins:0,rod:0,lure:0,rods:[0],lures:[0],rodLv:{0:1},lureLv:{0:1},caught:{},muted:false,casts:0,earned:0,
snaps:0,ach:{},quests:null,streak:{last:null,days:0,shieldWeek:null},questsDoneTotal:0,
bossBeaten:false,bossCount:0,bosses:{},
boatSkins:[0],boatSkin:0,bobberSkins:[0],bobberSkin:0,
locations:[0],location:0,
aqFish:[],aqSlots:AQ_BASE_SLOTS, /* Этап 46: аквариум — экземпляры {id,v,w} и число слотов */
kgTotal:0,nightCatch:false,wxRainV:0,wxFog:0}; // Этап 4: скины; Этап 5: локации; Этап 22: счётчики ачивок (кг/ночь/погода); Этап 37: bosses — пер-босс; Этап 46: аквариум
function freshSave(muted){
return {coins:0,rod:0,lure:0,rods:[0],lures:[0],rodLv:{0:1},lureLv:{0:1},caught:{},muted:muted,casts:0,earned:0,
snaps:0,ach:{},quests:null,streak:{last:null,days:0,shieldWeek:null},questsDoneTotal:0,
bossBeaten:false,bossCount:0,bosses:{},
boatSkins:[0],boatSkin:0,bobberSkins:[0],bobberSkin:0,
locations:[0],location:0,
aqFish:[],aqSlots:AQ_BASE_SLOTS, // Этап 46: аквариум
kgTotal:0,nightCatch:false,wxRainV:0,wxFog:0}; // Этап 4: скины; Этап 5: локации; Этап 22: счётчики ачивок; Этап 37: bosses
}
function loadSave(){
try{ const s=localStorage.getItem(SAVE_KEY); if(s) Object.assign(save,JSON.parse(s)); }catch(e){}
// миграция старых сейвов: caught[id] был числом → теперь {n, best}
for(const k in save.caught){
if(typeof save.caught[k]==='number') save.caught[k]={n:save.caught[k],best:0};
}
// миграция M1: у записи появился счётчик shiny (sn)
for(const k in save.caught){
const c=save.caught[k];
if(c&&typeof c==='object'&&typeof c.sn!=='number') c.sn=0;
}
// миграция M6: счётчики всех вариантов (cp/sv/qz/sn/em/dm/rb)
for(const k in save.caught){
const c=save.caught[k];
if(c&&typeof c==='object'){
for(const key of Object.values(VARIANT_KEY)) if(typeof c[key]!=='number') c[key]=0;
}
}
// миграция M2: новые поля (старые сейвы обязаны читаться)
if(typeof save.snaps!=='number') save.snaps=0;
if(!save.ach||typeof save.ach!=='object') save.ach={};
if(typeof save.questsDoneTotal!=='number') save.questsDoneTotal=0;
if(!save.quests||typeof save.quests!=='object') save.quests=null;
if(!save.streak||typeof save.streak!=='object') save.streak={last:null,days:0,shieldWeek:null};
// M3: приманки — дефолт для старых сейвов
if(!save.lures||!Array.isArray(save.lures)) save.lures=[0];
if(!save.rods||!Array.isArray(save.rods)) save.rods=[0];
// M5: фонарик больше не приманка (id=4) — убираем из старых сейвов
if(save.lures.includes(4)) save.lures=save.lures.filter(x=>x!==4);
if(!save.lures.length) save.lures=[0];
if(save.lure===4) save.lure=0;
// M5: уровни снастей 1..4 — в старых сейвах их нет: купленным — уровень 1
if(!save.rodLv||typeof save.rodLv!=='object') save.rodLv={};
if(!save.lureLv||typeof save.lureLv!=='object') save.lureLv={};
for(const i of save.rods) if(!(save.rodLv[i]>=1)) save.rodLv[i]=1;
for(const i of save.lures) if(!(save.lureLv[i]>=1)) save.lureLv[i]=1;
delete save.lureLv[4];
// M3: цикл дня/ночи — без dayTime старт с утра; день идёт в реальном времени,
// пока игрока не было, сдвиг догоняет (mod 1)
if(typeof save.dayTime!=='number'||save.dayTime<0) save.dayTime=0;
setDayTime(save.dayTime+(Date.now()-(save.lastSaveMs||Date.now()))/1000/DAY_LENGTH);
save.lastSaveMs=Date.now();
// M4: босс (Этап 37: в каждой локации) — новые поля, дефолты для старых сейвов
if(typeof save.bossBeaten!=='boolean') save.bossBeaten=false;
if(typeof save.bossCount!=='number') save.bossCount=0;
// Этап 37: босс в каждой локации — save.bosses {id: true}, дефолт для старых сейвов
if(!save.bosses||typeof save.bosses!=='object') save.bosses={};
// Этап 4: скины лодки/поплавка — дефолты для старых сейвов и чинка битых значений
if(!save.boatSkins||!Array.isArray(save.boatSkins)) save.boatSkins=[0];
if(save.boatSkins.indexOf(0)<0) save.boatSkins.push(0); // бесплатный скин 0 гарантирован (битый сейв)
if(!save.bobberSkins||!Array.isArray(save.bobberSkins)) save.bobberSkins=[0];
if(save.bobberSkins.indexOf(0)<0) save.bobberSkins.push(0);
if(typeof save.boatSkin!=='number'||save.boatSkin<0||save.boatSkin>2) save.boatSkin=0;
if(typeof save.bobberSkin!=='number'||save.bobberSkin<0||save.bobberSkin>2) save.bobberSkin=0;
if(save.boatSkins.indexOf(save.boatSkin)<0) save.boatSkin=0; // экипированного нет в купленных (битый сейв)
if(save.bobberSkins.indexOf(save.bobberSkin)<0) save.bobberSkin=0;
// Этап 5: локации (Река/Озёра) — дефолты для старых сейвов и чинка битых значений (паттерн скинов)
// Этап 36: граница — из LOCATIONS.length (баг этапа 5: жёсткое >1 сбрасывало Море при reload)
if(!save.locations||!Array.isArray(save.locations)) save.locations=[0];
if(save.locations.indexOf(0)<0) save.locations.push(0); // родная Река гарантирована (битый сейв)
if(typeof save.location!=='number'||save.location<0||save.location>=LOCATIONS.length) save.location=0;
if(save.locations.indexOf(save.location)<0) save.location=0; // выбранной локации нет в купленных (битый сейв)
// Этап 46: аквариум — дефолты/чинка битых значений (паттерн скинов/локаций):
// экземпляр валиден, если id есть в SPECIES и w — число >0; вариант нормализуем по VARIANTS → 'normal'
if(!Array.isArray(save.aqFish)) save.aqFish=[];
save.aqFish=save.aqFish
.filter(f=>f&&SPECIES.some(s=>s.id===f.id)&&Number.isFinite(f.w)&&f.w>0) // Этап 46: Infinity/NaN отбрасываем
.map(f=>({id:f.id,v:VARIANTS.some(x=>x.id===f.v)?f.v:'normal',w:f.w}));
if(typeof save.aqSlots!=='number'||!Number.isFinite(save.aqSlots)) save.aqSlots=AQ_BASE_SLOTS;
save.aqSlots=Math.trunc(save.aqSlots); // Этап 46: нецелое (6.5) давало AQ_SLOT_COSTS[0.5]=undefined → NaN
if(save.aqSlots<AQ_BASE_SLOTS) save.aqSlots=AQ_BASE_SLOTS;
if(save.aqSlots>AQ_MAX_SLOTS) save.aqSlots=AQ_MAX_SLOTS;
if(save.aqFish.length>save.aqSlots) save.aqFish.length=save.aqSlots; // больше слотов, чем есть, — обрезаем
// M2: стрик входа и квесты дня (новый день — перегенерация)
applyStreak();
refreshQuests();
}
function persist(){
save.dayTime=dayTime; // M3: время суток храним в сейве
save.lastSaveMs=Date.now(); // M3: время последнего сейва (для догона дня)
try{ localStorage.setItem(SAVE_KEY,JSON.stringify(save)); }catch(e){}
}
/* =========================================================
M3: ЦИКЛ ДНЯ/НОЧИ
========================================================= */
const DAY_LENGTH=300; // секунд на полный день
let dayTime=0; // 0..1 — позиция в сутках
let dayPhase='morning'; // morning (0-0.25) day (0.25-0.5) evening (0.5-0.75) night (0.75-1.0)
let nightNoLightToast=false; // тост «Ночью нужен фонарик» — разово, не каждый кадр
function phaseOf(t){ return t<0.25?'morning':(t<0.5?'day':(t<0.75?'evening':'night')); }
function setDayTime(t){ t%=1; if(t<0)t+=1; dayTime=t; dayPhase=phaseOf(dayTime); }
/* =========================================================
M8: ПОГОДА — ДОЖДЬ И ТУМАН
========================================================= */
/* Случайный разброс до следующего события (сек) */
function weatherGapNext(){ return WEATHER_GAP_MIN+Math.random()*(WEATHER_GAP_MAX-WEATHER_GAP_MIN); }
/* Эффективная погода: тест-форс имеет приоритет (срабатывает синхронно, без ожидания кадра),
иначе естественное состояние. Единственная точка чтения для эффектов/визуала/HUD */
function weatherActive(){ return forceWeather||weather; }
/* Таймер — в реальном времени (как DAY_LENGTH в frame): между событиями разброс WEATHER_GAP_*,
само событие длится WEATHER_DURATION. При forceWeather погода активна всегда — таймеры не гоняем */
function updateWeather(dt){
if(forceWeather) return; // форс: таймеры не гоняем, weatherT не тикает
if(weather){
weatherT-=dt;
if(weatherT<=0){
weather=null; weatherGap=weatherGapNext();
toast(t('wx_clear'));
}
}else{
weatherGap-=dt;
if(weatherGap<=0){
weather=Math.random()<0.5?'rain':'fog'; // rain/fog 50/50
weatherT=WEATHER_DURATION;
// gap следующего события не роллим здесь: его задаст ветка конца события
toast(t('wx_'+weather)); // Y5: i18n — тост погоды из T (RU/EN)
}
}
}
/* Пилюля #weather в HUD рядом с #coins: иконка + остаток секунд («🌧️ 97с»);
при форсе показываем полную длительность (событие «всегда активно»). Обновляется по таймеру;
сравниваем ЦЕЛИК text (смена иконки rain↔fog не меняет секунд) */
let weatherHudTxt='';
function updateWeatherHud(){
const el=$('weather');
const id=weatherActive();
if(!id){
if(!el.classList.contains('hidden')) el.classList.add('hidden');
weatherHudTxt='';
return;
}
if(el.classList.contains('hidden')) el.classList.remove('hidden');
const sec=forceWeather?WEATHER_DURATION:Math.max(0,Math.ceil(weatherT));
const txt=WEATHER[id].icon+' '+sec+t('sec_short'); // Y5: i18n — «с»/«s»
if(txt!==weatherHudTxt){
weatherHudTxt=txt;
el.textContent=txt;
}
}
/* =========================================================
M2: НАГРАДЫ — КВЕСТЫ ДНЯ, СТРИК ВХОДА, ДОСТИЖЕНИЯ
========================================================= */
const STREAK_REWARDS=[25,50,75,100,125,150,200]; // награды дней 1-7 стрика
function todayStr(){
const d=new Date();
return d.getFullYear()+'-'+String(d.getMonth()+1).padStart(2,'0')+'-'+String(d.getDate()).padStart(2,'0');
}
function dateShift(dateStr,days){
const d=new Date(dateStr+'T00:00:00');
d.setDate(d.getDate()+days);
return d.getFullYear()+'-'+String(d.getMonth()+1).padStart(2,'0')+'-'+String(d.getDate()).padStart(2,'0');
}
/* ISO-неделя «YYYY-Www» (детерминированно — тесты повторяют расчёт) */
function isoWeek(dateStr){
const d=new Date(dateStr+'T12:00:00');
const day=(d.getDay()+6)%7;
d.setDate(d.getDate()-day+3); // четверг этой ISO-недели
const year=d.getFullYear();
const jan4=new Date(year,0,4);
const jan4day=(jan4.getDay()+6)%7;
const week1Thu=new Date(year,0,4-jan4day+3);
const week=1+Math.round((d-week1Thu)/(7*24*3600*1000));
return year+'-W'+String(week).padStart(2,'0');
}
/* Детерминированный hash строки даты (FNV-1a) — тесты смогут повторить генерацию */
function daySeed(dateStr){
let h=2166136261>>>0;
for(let i=0;i<dateStr.length;i++){
h^=dateStr.charCodeAt(i);
h=Math.imul(h,16777619);
}
return h>>>0;
}
function seededRand(seed){
let a=seed>>>0;
return function(){
a=(a+0x6D2B79F5)>>>0;
let t=a;
t=Math.imul(t^(t>>>15),t|1);
t^=t+Math.imul(t^(t>>>7),t|61);
return ((t^(t>>>14))>>>0)/4294967296;
};
}
/* --- Квесты дня --- */
const QUEST_NAMES={carass:['карась','карася','карасей'],perch:['окунь','окуня','окуней'],bream:['лещ','леща','лещей']};
const QUEST_NAMES_EN={carass:'Crucian carp',perch:'Perch',bream:'Bream'}; // Y5: i18n — EN-имена для квестов
const QUEST_TPLS=[
{tpl:'catch_species', make(r){ const sp=SPECIES[[0,1,2][Math.floor(r()*3)]];
return {tpl:'catch_species', param:sp.id, goal:3+Math.floor(r()*3), reward:100+Math.floor(r()*51)}; }},
{tpl:'earn_coins', make(r){
return {tpl:'earn_coins', param:0, goal:[150,250,400][Math.floor(r()*3)], reward:80+Math.floor(r()*41)}; }},
{tpl:'catch_weight', make(r){ const n=[2,3,5][Math.floor(r()*3)];
return {tpl:'catch_weight', param:n, goal:1, reward:120+Math.floor(r()*41)}; }},
{tpl:'casts', make(r){
return {tpl:'casts', param:0, goal:[8,10,15][Math.floor(r()*3)], reward:60+Math.floor(r()*41)}; }},
{tpl:'catch_rarity', make(r){
return {tpl:'catch_rarity', param:[1,2][Math.floor(r()*2)], goal:1, reward:150}; }},
{tpl:'catch_shiny', make(r){
return {tpl:'catch_shiny', param:0, goal:1, reward:200}; }},
];
function pluralN(n,forms){
const m10=n%10,m100=n%100;
if(m10===1&&m100!==11) return forms[0];
if(m10>=2&&m10<=4&&(m100<12||m100>14)) return forms[1];
return forms[2];
}
function questText(q){
if(LANG==='en'){ // Y5: i18n — EN-ветка (RU-ветка ниже — побуквенно без изменений)
switch(q.tpl){
case 'catch_species': return 'Catch '+q.goal+' '+QUEST_NAMES_EN[q.param];
case 'earn_coins': return 'Earn '+q.goal+' coins today';
case 'catch_weight': return 'Catch a fish from '+q.param+' kg';
case 'casts': return 'Make '+q.goal+' casts today';
case 'catch_rarity': return 'Catch a '+trRarity(q.param)+'+ fish';
case 'catch_shiny': return 'Catch a golden fish';
}
return '?';
}
switch(q.tpl){
case 'catch_species': return 'Поймай '+q.goal+' '+pluralN(q.goal,QUEST_NAMES[q.param]);
case 'earn_coins': return 'Заработай '+q.goal+' монет за день';
case 'catch_weight': return 'Поймай рыбу от '+q.param+' кг';
case 'casts': return 'Сделай '+q.goal+' забросов за день';
case 'catch_rarity': return 'Поймай рыбу редкости '+RARITY_NAMES[q.param]+'+';
case 'catch_shiny': return 'Поймай золотую рыбу'; // M6: «shiny» = gold-вариант
}
return '?';
}
function questIcon(q){
// Э42: catch_species — мини-SVG портрет вида (спрайт FISH-SVG) вместо эмодзи
if(q.tpl==='catch_species'){ const sp=SPECIES.find(s=>s.id===q.param); return sp?'<svg class="qfish" viewBox="0 0 160 100"><use href="#fish-'+sp.id+'"/></svg>':'❓'; }
return {earn_coins:'🪙', catch_weight:'⚖', casts:'🎣', catch_rarity:'⭐', catch_shiny:'✨'}[q.tpl]||'🎯';
}
/* 3 квеста дня из 6 шаблонов, без повторов, детерминированно от даты */
function genQuests(dateStr){
const r=seededRand(daySeed(dateStr));
const ids=QUEST_TPLS.map((t,i)=>i);
for(let i=ids.length-1;i>0;i--){ const j=Math.floor(r()*(i+1)); const tmp=ids[i]; ids[i]=ids[j]; ids[j]=tmp; }
return ids.slice(0,3).map(i=>{ const q=QUEST_TPLS[i].make(r); q.prog=0; q.done=false; return q; });
}
function refreshQuests(){
const today=todayStr();
if(!(save.quests&&save.quests.date===today)){
save.quests={date:today, list:genQuests(today)};
persist();
}
}
/* --- Стрик входа (с еженедельным щитом на один пропуск) --- */
function streakIdx(days){ return ((days-1)%7)+1; }
function nextStreakReward(days){ return STREAK_REWARDS[streakIdx((days||0)+1)-1]; }
function applyStreak(){
const today=todayStr();
if(save.streak.last===today) return;
const fresh=!save.streak.last; // первый визит — стрик запускается (награда дня с неё не выдаётся)
if(save.streak.last===dateShift(today,-1)){
save.streak.days=(save.streak.days||0)+1; // вчерашний визит — стрик растёт
}else if(save.streak.last===dateShift(today,-2)&&save.streak.shieldWeek!==isoWeek(today)){
save.streak.days=(save.streak.days||0)+1; // один пропуск в неделю прощает щит
save.streak.shieldWeek=isoWeek(today);
toast(t('shield'));
}else{
save.streak.days=1;
}
save.streak.last=today;
if(!fresh){
const coins=STREAK_REWARDS[streakIdx(save.streak.days)-1];
save.coins+=coins;
toast(tt('streak_day',{d:save.streak.days,c:coins}));
}
persist();
checkAchievements(); // streak_7
}
/* --- Прогресс квестов (delta — на сколько шагнуть: 1 улов / N монет и т.п.) --- */
function questHit(tpl,condFn,delta){
if(!save.quests) return;
for(const q of save.quests.list){
if(q.done||q.tpl!==tpl) continue;
if(!condFn(q)) continue;
q.prog+=delta||1;
if(q.prog>=q.goal){
q.prog=q.goal; q.done=true;
save.coins+=q.reward; save.questsDoneTotal++;
updateHUD(); // награда может прийти на забросе (вне catchFish) — счётчик монет обновить сразу
sfx('coin');
toast(tt('quest_done',{text:questText(q),r:q.reward}));
checkAchievements(); // quests_5
}
}
}
/* Новый день: стрик + перегенерация квестов (loadSave, cast, catch) */
function newDayCheck(){ applyStreak(); refreshQuests(); }
/* --- Достижения с постоянными бонусами --- */
function caughtN(s,id){ const c=s.caught&&s.caught[id]; return c?c.n:0; }
function caughtBest(s,id){ const c=s.caught&&s.caught[id]; return c?c.best:0; }
/* Y5: i18n — у достижений nameEn/descEn (RU name/desc — побуквенно те же) */
const ACHIEVEMENTS=[
{id:'first_catch', name:'Первый улов', nameEn:'First Catch', desc:'Поймай первую рыбу', descEn:'Catch your first fish', icon:'🏅', bonus:{coinPct:0.01}, check:s=>SPECIES.some(sp=>caughtN(s,sp.id)>0)}, // Э42: иконка 🏅 (эмодзи рыб убраны)
{id:'casts_10', name:'Разминка', nameEn:'Warm-up', desc:'Сделай 10 забросов', descEn:'Make 10 casts', icon:'🎣', bonus:{coinPct:0.01}, check:s=>s.casts>=10},
{id:'casts_100', name:'Моряк', nameEn:'Sailor', desc:'Сделай 100 забросов', descEn:'Make 100 casts', icon:'⛵', bonus:{coinPct:0.01}, check:s=>s.casts>=100},
{id:'earned_1000', name:'Первая тысяча', nameEn:'First Thousand', desc:'Заработай 1000 монет', descEn:'Earn 1,000 coins', icon:'🪙', bonus:{coinPct:0.01}, check:s=>s.earned>=1000},
{id:'earned_10000', name:'Рыбацкий капитал', nameEn:'Fishing Capital', desc:'Заработай 10 000 монет', descEn:'Earn 10,000 coins', icon:'💰', bonus:{coinPct:0.02}, check:s=>s.earned>=10000},
{id:'gear_max', name:'Максимальная снасть', nameEn:'Max Gear', desc:'Улучши снасть до 4 уровня', descEn:'Upgrade a gear to level 4', icon:'⚒️', bonus:{coinPct:0.01}, check:s=>Object.values(s.rodLv||{}).some(v=>v>=4)||Object.values(s.lureLv||{}).some(v=>v>=4)}, // Этап 22: M5 апгрейды
{id:'titan', name:'Титан', nameEn:'Titan', desc:'Купи удочку «Титан»', descEn:'Buy the Titanium rod', icon:'💪', bonus:{coinPct:0.02}, check:s=>(s.rods||[]).indexOf(3)>=0},
{id:'species_3', name:'Ботаник', nameEn:'Botanist', desc:'Поймай 3 вида рыб', descEn:'Catch 3 fish species', icon:'📖', bonus:{coinPct:0.01}, check:s=>SPECIES.filter(sp=>caughtN(s,sp.id)>0).length>=3},
{id:'species_8', name:'Энциклопедия', nameEn:'Encyclopedia', desc:'Поймай все виды', descEn:'Catch all species', icon:'🏆', bonus:{coinPct:0.02}, check:s=>SPECIES.every(sp=>caughtN(s,sp.id)>0)}, // Этап 5: все 11 видов, этап 33: все 16, этап 35: все 23, этап 36: все 32, этап 45: все 37 (id старый сейв; desc и чек — «все», масштабируются автоматически)
{id:'rare_fish', name:'Редкий гость', nameEn:'Rare Guest', desc:'Поймай рыбу редкости «Редкая»+ ', descEn:'Catch a Rare+ fish', icon:'⭐', bonus:{coinPct:0.01}, check:s=>SPECIES.some(sp=>sp.rarity>=2&&caughtN(s,sp.id)>0)},
{id:'legendary_fish',name:'Легенда', nameEn:'Legend', desc:'Поймай рыбу редкости «Легендарная»', descEn:'Catch a Legendary fish', icon:'👑',bonus:{coinPct:0.02}, check:s=>SPECIES.some(sp=>sp.rarity>=4&&caughtN(s,sp.id)>0)},
{id:'first_shiny', name:'Золотая жила', nameEn:'Gold Rush', desc:'Поймай золотую рыбу', descEn:'Catch a golden fish', icon:'✨', bonus:{coinPct:0.01}, check:s=>SPECIES.some(sp=>{const c=s.caught&&s.caught[sp.id]; return c&&c.sn>0;})},
{id:'first_silver', name:'Серебро', nameEn:'Silver', desc:'Поймай серебряную рыбу', descEn:'Catch a silver fish', icon:'🥈', bonus:{coinPct:0.01}, check:s=>SPECIES.some(sp=>{const c=s.caught&&s.caught[sp.id]; return c&&(c.sv||0)>0;})}, // Этап 22: M6 варианты
{id:'first_rainbow',name:'Радужный улов', nameEn:'Rainbow Catch', desc:'Поймай радужную рыбу', descEn:'Catch a rainbow fish', icon:'🌈', bonus:{coinPct:0.02}, check:s=>SPECIES.some(sp=>{const c=s.caught&&s.caught[sp.id]; return c&&(c.rb||0)>0;})},
{id:'full_variants',name:'Полная коллекция', nameEn:'Full Collection', desc:'Поймай все виды во всех вариантах', descEn:'Catch every species in every variant', icon:'🌈',bonus:{coinPct:0.05}, check:s=>SPECIES.every(sp=>{const c=s.caught&&s.caught[sp.id]; return c&&c.n>0&&VARIANTS.every(v=>{const k=VARIANT_KEY[v.id]; return !k||(c[k]||0)>0;});})},
{id:'weight_10', name:'Трофей', nameEn:'Trophy', desc:'Поймай рыбу 10+ кг', descEn:'Catch a fish of 10+ kg', icon:'⚖', bonus:{windowS:0.05}, check:s=>SPECIES.some(sp=>caughtBest(s,sp.id)>=10)},
{id:'weight_20', name:'Монстр глубин', nameEn:'Deep Monster', desc:'Поймай рыбу 20+ кг', descEn:'Catch a fish of 20+ kg', icon:'💪', bonus:{line:5}, check:s=>SPECIES.some(sp=>caughtBest(s,sp.id)>=20)}, // Э42: иконка 💪, лестница ⚖/💪/🚢 (эмодзи рыб убраны)
{id:'weight_1000', name:'Тонна рыбы', nameEn:'A Ton of Fish', desc:'Поймай рыбы на 1000+ кг', descEn:'Catch 1,000+ kg of fish', icon:'🚢', bonus:{coinPct:0.02}, check:s=>(s.kgTotal||0)>=1000}, // Этап 22
{id:'night_first', name:'Ночной клёв', nameEn:'Night Bite', desc:'Поймай рыбу ночью', descEn:'Catch a fish at night', icon:'🌙', bonus:{coinPct:0.01}, check:s=>s.nightCatch===true},
{id:'rain_variant', name:'Дождливый везунчик', nameEn:'Rainy Lucky Guy', desc:'Поймай особую рыбу в дождь', descEn:'Catch a special fish in the rain', icon:'🌧️', bonus:{coinPct:0.01}, check:s=>(s.wxRainV||0)>0}, // Этап 22: M8 погода
{id:'fog_catch', name:'Туманный улов', nameEn:'Foggy Catch', desc:'Поймай рыбу в тумане', descEn:'Catch a fish in the fog', icon:'🌫️', bonus:{coinPct:0.01}, check:s=>(s.wxFog||0)>0},
{id:'snaps_10', name:'Упёртый', nameEn:'Stubborn', desc:'10 обрывов шнура', descEn:'Snap the line 10 times', icon:'💥', bonus:{coinPct:0.01}, check:s=>s.snaps>=10},
{id:'snaps_50', name:'Хроники обрывов', nameEn:'Snap Chronicles', desc:'50 обрывов шнура', descEn:'Snap the line 50 times', icon:'📜', bonus:{coinPct:0.01}, check:s=>s.snaps>=50},
{id:'streak_7', name:'Семёрка', nameEn:'Seven', desc:'Стрик 7 дней', descEn:'7-day streak', icon:'🔥', bonus:{coinPct:0.01}, check:s=>s.streak&&s.streak.days>=7},
{id:'quests_5', name:'Дневник искателя', nameEn:"Seeker's Diary", desc:'Выполни 5 квестов', descEn:'Complete 5 quests', icon:'🎯', bonus:{coinPct:0.01}, check:s=>s.questsDoneTotal>=5},
{id:'skin_first', name:'Красуйся', nameEn:'Dress Up', desc:'Купи скин лодки или поплавка', descEn:'Buy a boat or bobber skin', icon:'🎨', bonus:{coinPct:0.01}, check:s=>(s.boatSkins||[]).length>1||(s.bobberSkins||[]).length>1}, // Этап 22: M-skins
{id:'skins_all', name:'Стилист', nameEn:'Stylist', desc:'Собери все скины лодки и поплавка', descEn:'Collect all boat and bobber skins', icon:'🎭',bonus:{coinPct:0.02}, check:s=>BOAT_SKINS.every(b=>(s.boatSkins||[]).indexOf(b.id)>=0)&&BOBBER_SKINS.every(b=>(s.bobberSkins||[]).indexOf(b.id)>=0)},
{id:'lake_first', name:'Новые берега', nameEn:'New Shores', desc:'Открой локацию «Озёра»', descEn:'Unlock the Lakes location', icon:'🗺️', bonus:{coinPct:0.02}, check:s=>(s.locations||[]).indexOf(1)>=0}, // Этап 22: локации
{id:'sea_first', name:'Широкая вода', nameEn:'Open Water', desc:'Открой локацию «Море»', descEn:'Unlock the Sea location', icon:'⚓', bonus:{coinPct:0.02}, check:s=>(s.locations||[]).indexOf(2)>=0}, // Этап 36: локации (locations-based — пин §10c(8) achBonus не трогает)
{id:'ocean_first', name:'Глубина', nameEn:'The Deep', desc:'Открой локацию «Океан»', descEn:'Unlock the Ocean location', icon:'🌊', bonus:{coinPct:0.02}, check:s=>(s.locations||[]).indexOf(3)>=0}, // Этап 36: локации
{id:'swamp_first', name:'Тайна болота', nameEn:'Swamp Secret', desc:'Открой локацию «Волшебное болото»', descEn:'Unlock the Magic Swamp location', icon:'🗺️', bonus:{coinPct:0.02}, check:s=>(s.locations||[]).indexOf(4)>=0}, // Этап 45: локация Болото (locations-based — пин §10c(8) achBonus не трогает)
{id:'boss_first', name:'Босс-рыбак', nameEn:'Boss Angler', desc:'Победи рыбу-босса', descEn:'Defeat a boss fish', icon:'🏆', bonus:{coinPct:0.03}, check:s=>(s.bossBeaten===true)||(s.bossCount>0)}, // Этап 37: текст нейтральный — босс в каждой локации
// Этап 37: пер-босс ачивки (без coinPct — пин §10c(8) сумма achBonus().coinPct=0.16 не сдвигается;
// bonus:{} пустой — bonusText() в вкладке «Достижения» требует объект, coinPct там нет)
{id:'lake_boss', name:'Победа над Раком', nameEn:'Crayfish Slayer', desc:'Победи босса Озёр', descEn:'Defeat the Lakes boss', icon:'🗺️', bonus:{}, check:s=>!!(s.bosses&&s.bosses.crayfish)}, // Э42: иконка локации (эмодзи рыб убраны)
{id:'sea_boss', name:'Победа над Рыбой-мечом', nameEn:'Swordfish Slayer', desc:'Победи босса Моря', descEn:'Defeat the Sea boss', icon:'⚓', bonus:{}, check:s=>!!(s.bosses&&s.bosses.swordfish)}, // Э42: иконка локации (эмодзи рыб убраны)
{id:'ocean_boss', name:'Победа над Китом', nameEn:'Whale Slayer', desc:'Победи босса Океана', descEn:'Defeat the Ocean boss', icon:'🌊', bonus:{}, check:s=>!!(s.bosses&&s.bosses.whale)}, // Э42: иконка локации (эмодзи рыб убраны)
{id:'swamp_boss', name:'Победа над Духом болота', nameEn:'Spirit Slayer', desc:'Победи Духа болота', descEn:'Defeat the Swamp Spirit', icon:'🗺️', bonus:{}, check:s=>!!(s.bosses&&s.bosses.spiritfin)}, // Этап 45: босс Болота (без coinPct — пин §10c(8); bonus:{} пустой — bonusText() требует объект)
// Этап 46: аквариум — locations-based проверки (см. checkAchievements: массив ACHIEVEMENTS,
// поле check). БЕЗ coinPct — пин §10c(8) сумма achBonus().coinPct=0.18 не сдвигается;
// bonus:{} пустой (как у пер-босс-ачивок) — bonusText() в «Достижениях» требует объект.
// Проверки терпимы к старому сейву: нет aqFish/aqSlots — ложных выдач нет
{id:'aq_first', name:'Первый жилец', nameEn:'First Tenant', desc:'Посели рыбу в аквариум', descEn:'Move a fish into the aquarium', icon:'🐠', bonus:{}, check:s=>(s.aqFish||[]).length>0},
{id:'aq_full', name:'Аквариум полон', nameEn:'Full Tank', desc:'Заполни все слоты аквариума', descEn:'Fill every aquarium slot', icon:'🐠', bonus:{}, check:s=>(s.aqFish||[]).length>=(s.aqSlots||AQ_BASE_SLOTS)},
];
/* Сумма бонусов по выданным достижениям */
function achBonus(){
const b={coinPct:0,windowS:0,line:0};
for(const a of ACHIEVEMENTS){
if(!save.ach||!save.ach[a.id]) continue;
if(a.bonus.coinPct) b.coinPct+=a.bonus.coinPct;
if(a.bonus.windowS) b.windowS+=a.bonus.windowS;
if(a.bonus.line) b.line+=a.bonus.line;
}
return b;
}
function checkAchievements(){
let changed=false;
for(const a of ACHIEVEMENTS){
if(save.ach[a.id]) continue;
if(a.check(save)){
save.ach[a.id]=true; changed=true;
sfx('coin');
if(a.id==='full_variants'){ save.coins+=5000; updateHUD(); } // M6: разовые 5000 за полную коллекцию вариантов
toast(tt('ach_toast',{name:trName(a)})+(a.id==='full_variants'?' +5000 🪙':''));
}
}
if(changed) persist();
}
function bonusText(b){
if(b.coinPct) return tt('bonus_coin',{v:(b.coinPct*100)});
if(b.windowS) return tt('bonus_window',{v:b.windowS});
if(b.line) return tt('bonus_line',{v:b.line});
return '';
}
/* =========================================================
ХОЛСТ И РАЗМЕРЫ
========================================================= */
const canvas=document.getElementById('game');
const ctx=canvas.getContext('2d');
let W=0,H=0,DPR=1,waterY=0,boatX=0;
let tip={x:0,y:0};
function resize(){
DPR=Math.min(window.devicePixelRatio||1,2);
W=window.innerWidth; H=window.innerHeight;
canvas.width=W*DPR; canvas.height=H*DPR;
canvas.style.width=W+'px'; canvas.style.height=H+'px';
ctx.setTransform(DPR,0,0,DPR,0,0);
waterY=Math.round(H*0.26);
boatX=Math.round(W*0.20);
initClouds(); initSparkles(); initRain(); initScenery(); // Этап 44: силуэты по новой ширине
if(aqOpen) initAquarium(); // Этап 46: банка перераскладывается по новым W/H
}
window.addEventListener('resize',resize);
/* =========================================================
ЗВУК
========================================================= */
let AC=null;
function ac(){
if(!AC){ try{ AC=new (window.AudioContext||window.webkitAudioContext)(); }catch(e){ return null; } }
if(AC&&AC.state==='suspended'){ AC.resume(); }
return AC;
}
function beep(t0,f,dur,type,vol){
const c=ac(); if(!c)return;
const o=c.createOscillator(),g=c.createGain();
o.type=type||'sine'; o.frequency.setValueAtTime(f,t0);
g.gain.setValueAtTime(vol,t0); g.gain.exponentialRampToValueAtTime(0.001,t0+dur);
o.connect(g); g.connect(c.destination); o.start(t0); o.stop(t0+dur+0.02);
}
function noiseBurst(t0,dur,vol,freq){
const c=ac(); if(!c)return;
const n=Math.floor(c.sampleRate*dur);
const buf=c.createBuffer(1,n,c.sampleRate),d=buf.getChannelData(0);
for(let i=0;i<n;i++) d[i]=(Math.random()*2-1)*(1-i/n);
const src=c.createBufferSource(); src.buffer=buf;
const f=c.createBiquadFilter(); f.type='lowpass'; f.frequency.value=freq;
const g=c.createGain(); g.gain.value=vol;
src.connect(f); f.connect(g); g.connect(c.destination); src.start(t0);
}
function sfx(name){
if(save.muted) return;
const c=ac(); if(!c) return;
const t=c.currentTime;
switch(name){
case 'click': beep(t,500,0.06,'triangle',0.15); break;
case 'cast': noiseBurst(t,0.22,0.15,2500); break;
case 'splash': noiseBurst(t,0.3,0.4,700); break;
case 'bite': beep(t,900,0.07,'square',0.2); beep(t+0.1,1200,0.09,'square',0.2); break;
case 'hook': beep(t,600,0.05,'triangle',0.25); beep(t+0.06,900,0.08,'triangle',0.25); break;
case 'tick': beep(t,260,0.03,'triangle',0.07); break;
case 'pull': beep(t,140,0.18,'sawtooth',0.12); break;
case 'snap': noiseBurst(t,0.25,0.5,3000); beep(t,180,0.2,'sawtooth',0.2); break;
case 'escape': beep(t,500,0.12,'sine',0.2); beep(t+0.12,350,0.16,'sine',0.18); break;
case 'coin': beep(t,1200,0.08,'sine',0.2); beep(t+0.09,1600,0.12,'sine',0.2); break;
case 'catch': [523,659,784,1047].forEach((f,i)=>beep(t+i*0.11,f,0.14,'triangle',0.22)); break;
case 'no': beep(t,220,0.12,'square',0.15); break;
}
}
function vib(p){ try{ if(navigator.vibrate) navigator.vibrate(p); }catch(e){} }
/* =========================================================
СОСТОЯНИЕ ИГРЫ
========================================================= */
let state='MENU'; // MENU IDLE CHARGE CAST WAIT APPROACH BITE REEL SNAP CARD
let uiOpen=true;
let pauseOpen=false; // Y6: оверлей паузы (треб. 6.3) открыт — гард в YG.onResume
let time=0;
let charge=0, power=0;
let castT=0, castFrom={x:0,y:0}, castTo={x:0,y:0};
let bobber={x:0,y:0};
let castDist=0; // дальность заброса 0..0.97 (визуал: глубина крючка оснастки)
let hookPos={x:0,y:0}; // позиция крючка (визуал; пригодится lane поклёвки/вываживания)
let biteTimer=0, biteT=0, biteFish=null, rippleTimer=0;
let reel=null;
let snapT=0, shake=0;
let stateBoss=false, bossPhase=0; // M4: босс-бой (Этап 37: в каждой локации, 3 фазы)
/* M8: погода — активное событие и таймеры (в реальном времени, как день/ночь) */
let weather=null; // 'rain'/'fog'/null — активное погодное событие (естественное состояние)
let weatherT=0; // M8: остаток секунд активного события
let weatherGap=WEATHER_GAP_MIN+Math.random()*(WEATHER_GAP_MAX-WEATHER_GAP_MIN); // M8: сек до следующего события
let ambient=[]; // фоновые рыбы
let scenery=[]; // Этап 44: береговые силуэты на горизонте (по локации)
/* Этап 45: декор «Волшебного болота» — ОТДЕЛЬНЫЕ от scenery слои поверх воды.
Кувшинки/лилии и лягушки рисуются после воды (drawSwampDecor), поэтому dusk()
береговых силуэтов их не гасит; пересобираются в initScenery() вместе со scenery. */
let pads=[]; // кувшинки: {x,y,r,ph,bob,notch,lily,lilyColor}
let frogs=[]; // лягушки: {x,y,s,state,t,dur,jh,dir,x0,y0,x1,y1}
let clouds=[], sparkles=[];
let rain=[]; // M8: частицы дождя (визуал)
let particles=[], ripples=[];
let bobberTrail=[]; // визуал: след поплавка при забросе
/* M5: уровни снастей (1..4) и эффективные статы: базовые + эффекты апгрейдов */
function rodLvOf(i){ const v=save.rodLv&&save.rodLv[i]>=1?save.rodLv[i]:1; return Math.max(1,Math.min(4,v)); }
function lureLvOf(i){ const v=save.lureLv&&save.lureLv[i]>=1?save.lureLv[i]:1; return Math.max(1,Math.min(4,v)); }
function effRod(i){
const b=RODS[i], lv=rodLvOf(i);
const e=Object.assign({},b,{light:lv>=2}); // M5: Lv2 — фонарик (ночная рыбалка)
if(lv>=2) e.line*=1.15; // Lv2: леска крепче
if(lv>=3){ e.drag*=1.15; e.reel*=1.10; } // Lv3: тормоз и катушка
if(lv>=4){ e.line*=1.15; e.size+=0.10; } // Lv4: леска ещё + крупные
return e;
}
function effLure(i){
const b=LURES[i], lv=lureLvOf(i);
const e=Object.assign({},b);
if(lv>=2) e.bite*=1.15; // Lv2: клёв чаще
if(lv>=3) e.rare+=1.0; // Lv3: редкие
if(lv>=4) e.size+=0.15; // Lv4: крупные
return e;
}
const rod=()=>effRod(save.rod);
const lure=()=>effLure(save.lure);
/* M5: фонарик — не приманка, а апгрейд 1 любого удилища (2+ ур.) */
const hasLight=()=>rodLvOf(save.rod)>=2;
const rand=(a,b)=>a+Math.random()*(b-a);
/* Этап 43: фоновые рыбы — масштаб и оттенок по локации (индекс = save.location, clamp по
той же границе, что LOCATIONS в drawWater): Река — как было (8–22), Озёра — зеленоватые,
Море — синеватые и покрупнее, Океан — редкие крупные тёмно-синие. Чисто визуал.
Этап 45: Болото — мелкая тёмно-зелёная стайка + palette цветов свечения (initFish раскладывает
цвета по рыбам, ночную ауру рисует drawAmbientFish).
Вызовы: старт (СТАРТ), смена локации в shopClick (buylocation/selectlocation) */
const AMBIENT_FISH=[
{n:9,sMin:8, sMax:22,hMin:130,hMax:220},
{n:9,sMin:10,sMax:26,hMin:120,hMax:200},
{n:8,sMin:12,sMax:32,hMin:160,hMax:230},
{n:6,sMin:18,sMax:44,hMin:180,hMax:250},
{n:7,sMin:12,sMax:30,hMin:120,hMax:170,palette:['#5ff2ff','#57ffa8','#d17bff','#ffe07a']}
];
function initFish(){
const f=AMBIENT_FISH[Math.max(0,Math.min(AMBIENT_FISH.length-1,save.location|0))];
ambient=[];
for(let i=0;i<f.n;i++){
ambient.push({
x:Math.random()*W, depth:rand(0.12,0.92), size:rand(f.sMin,f.sMax),
speed:rand(10,32), dir:Math.random()<0.5?1:-1, hue:rand(f.hMin,f.hMax), ph:rand(0,6.28),
// Фаза свечения: только у Болота (есть palette) — стабильный цвет из палитры по индексу рыбы;
// у локаций 0..3 поле = null и нигде не читается
glow:f.palette?f.palette[i%f.palette.length]:null
});
}
}
/* Этап 44: береговые силуэты на горизонте — визуальное различение локаций:
Река — береговая полоса НА ВСЮ ШИРИНУ (трава, 12–17 px, тёмная кромка у воды) + хвойный
лес, посаженный НА ЕЁ КРАЮ (дальний ряд светлее, ближний темнее), Озёра — холмы +
лиственные деревья, Море — парусник (медленно дрейфует) + чайки (летят, машут крыльями),
Океан — открытый горизонт БЕЗ берега (вода и небо). Элементы: {k:'bank',h,c?,c2?} /
{k:'pine',layer,by?,c?} (by — база ствола: у реки — верх кромки берега; c — цвет) /
{k:'hill'} / {k:'tree',c?} / {k:'ship',dir,v} / {k:'gull',y,v,ph} /
{k:'reed',h,lean,ph} (камыш) / {k:'snag',h,lean} (кривое дерево) — болотная гамма.
Этап 45: Болото дополнительно собирает отдельные слои pads[]/frogs[] (кувшинки/лилии,
лягушки) — рисуются поверх воды в drawSwampDecor(), прыжки/покачивание — updateDecor(dt).
Вызовы initScenery(): resize(), старт (в resize), смена локации в shopClick —
новую точку смены локации без initScenery() не добавлять. Дрейф парусника/чаек —
updateDecor(dt). Отрисовка drawScenery() — между drawSky() и drawWater() (базу
силуэтов закрывает вода). Чисто визуал */
function initScenery(){
const i=Math.max(0,Math.min(LOCATIONS.length-1,save.location|0));
scenery=[];
pads=[]; // Этап 45: болотный декор пересобирается вместе с силуэтами (смена локации/ресайз)
frogs=[];
if(i===0){ // Река — береговая полоса на всю ширину + лес в два ряда, посаженный на её кромку
const bankH=12+((Math.random()*6)|0); // 12–17 px
scenery.push({k:'bank',h:bankH});
for(let k=0;k<16;k++) scenery.push({k:'pine',layer:0,x:rand(-12,W+12),h:rand(16,34),by:waterY-bankH});
for(let k=0;k<12;k++) scenery.push({k:'pine',layer:1,x:rand(-12,W+12),h:rand(12,26),by:waterY-bankH});
}else if(i===1){ // Озёра — холмы (за деревьями) + лиственные деревья
const nh=2+((Math.random()*2)|0);
for(let k=0;k<nh;k++) scenery.push({k:'hill',x:rand(W*0.1,W*0.9),rx:rand(W*0.22,W*0.42),ry:rand(16,34)});
for(let k=0;k<10;k++) scenery.push({k:'tree',x:rand(-8,W+8),h:rand(8,18)});
}else if(i===2){ // Море — парусник + чайки (берега нет — открытый горизонт)
scenery.push({k:'ship',x:rand(W*0.25,W*0.8),v:rand(2.5,5),s:rand(0.8,1.15),dir:Math.random()<0.5?1:-1});
for(let k=0;k<3;k++) scenery.push({k:'gull',x:rand(0,W),y:rand(26,72),v:rand(14,26),ph:rand(0,6.28)});
}else if(i===4){ // Этап 45: Болото — мшистый задний берег: камыш + кривые деревья + туи
const bankH=10+((Math.random()*5)|0); // 10–14 px
scenery.push({k:'bank',h:bankH,c:'#3d5130',c2:'#28381f'});
for(let k=0;k<14;k++) scenery.push({k:'reed',x:rand(-12,W+12),h:rand(18,42),lean:rand(2,6),ph:rand(0,6.28)});
for(let k=0;k<6;k++) scenery.push({k:'snag',x:rand(-8,W+8),h:rand(14,30),lean:rand(-0.5,0.5)});
for(let k=0;k<8;k++) scenery.push({k:'pine',layer:0,x:rand(-12,W+12),h:rand(14,26),by:waterY-bankH,c:'#33503a'});
for(let k=0;k<6;k++) scenery.push({k:'pine',layer:1,x:rand(-12,W+12),h:rand(10,20),by:waterY-bankH,c:'#22392a'});
// Кувшинки (8–14): кувшинка = эллипс с вырезом-прорезью; на части — лилия (3 цвета)
const np=8+((Math.random()*7)|0);
for(let k=0;k<np;k++){
pads.push({
x:rand(10,W-10),
y:waterY+rand(18,Math.max(30,H-waterY-30)), // на воде, ниже линии воды
r:rand(9,17),
ph:rand(0,6.28), bob:0,
notch:rand(0,6.28), // угол выреза-прорези
lily:Math.random()<0.45,
lilyColor:['#ffe07a','#f2efe2','#ff9ec4'][(Math.random()*3)|0] // жёлтый/белый/розовый
});
}
// Лягушки (3–5): стартуют на кувшинках, прыгают по параболе на соседние (см. updateDecor).
// Размер s — заметно крупнее (9–14: читаемы на телефоне), вся отрисовка в drawSwampDecor масштабируется от s
const nf=3+((Math.random()*3)|0);
for(let k=0;k<nf;k++){
const p=pads.length?pads[(Math.random()*pads.length)|0]:null;
frogs.push({
x:p?p.x:rand(20,W-20), y:p?p.y-2:waterY+rand(30,120),
s:rand(9,14),
state:'sit', t:rand(0,3), dur:0.5, jh:20, dir:1,
x0:0,y0:0,x1:0,y1:0
});
}
}
// i===3 — Океан: берега нет вообще (открытая вода)
}
function initClouds(){
clouds=[];
for(let i=0;i<4;i++){
clouds.push({x:Math.random()*W,y:rand(14,Math.max(20,waterY-50)),s:rand(0.6,1.2),v:rand(4,9)});
}
}
function initSparkles(){
sparkles=[];
for(let i=0;i<24;i++){
sparkles.push({x:Math.random()*W,y:waterY+rand(10,H-waterY-10),ph:rand(0,6.28)});
}
initStars();
}
/* Визуал: звёзды для ночного неба (только отрисовка, на механику не влияют) */
let stars=[];
function initStars(){
stars=[];
for(let i=0;i<46;i++){
stars.push({x:Math.random()*W,y:Math.random()*Math.max(10,waterY-14),r:rand(0.6,1.7),ph:rand(0,6.28),sp:rand(0.8,2.2)});
}
}
/* M8: частицы дождя (визуал) — ~40 косых полосок; обновление по dt в updateDecor, пересчёт по высоте */
function initRain(){
rain=[];
for(let i=0;i<40;i++){
rain.push({x:rand(-40,W+40), y:rand(-H,H), v:rand(520,760)});
}
}
/* =========================================================
УТИЛИТЫ
========================================================= */
const $=id=>document.getElementById(id);
let toastTO=null;
function toast(msg){
const t=$('toast'); t.textContent=msg; t.style.opacity=1;
clearTimeout(toastTO); toastTO=setTimeout(()=>t.style.opacity=0,1600);
}
function updateHUD(){ $('coins').textContent='🪙 '+save.coins; $('btnMute').textContent=(save.muted?'🔇':'🔊')+' '+t('gm_sound'); }
function splash(x,y,n,spread){
for(let i=0;i<n;i++){
particles.push({
x:x,y:y, vx:rand(-1,1)*(spread||90), vy:rand(-160,-40),
g:320, life:rand(0.35,0.7), max:0.7, size:rand(1.5,3.5),
color:Math.random()<0.5?'255,255,255':'160,215,255'
});
}
}
function addRipple(x,y,max){ ripples.push({x:x,y:y,r:4,max:max||36,a:0.6}); }
/* =========================================================
ЛОГИКА
========================================================= */
function pickSpecies(dist){
const l=lure();
// M3: ночь/вечер — ночная таблица, иначе дневная (жёсткий переключатель)
// Этап 5: локация — Река (8 видов) или Озёра (все 16, этап 33); логика ролла по весам без изменений
// Этап 35: локации — у каждой СВОИ виды (без пересечений); Этап 36: +Океан; Этап 45: +Болото →
// пять локаций: Река 8 / Озёра 10 / Море 5 / Океан 9 / Болото 5.
// Этап 45: табличный доступ по save.location вместо вложенного тернарника (роллы 0..3 идентичны);
// guard: вне диапазона 0..4 (битый сейв/тест) — Река, как было раньше по умолчанию
const night=(dayPhase==='night'||dayPhase==='evening');
const li=save.location|0;
const idx=(li>=0&&li<SPECIES_BY_LOCATION.length)?li:0;
const tbl=night?SPECIES_BY_LOCATION_NIGHT[idx]:SPECIES_BY_LOCATION[idx];
let total=0;
const ws=tbl.map(s=>{
let w=s.weight;
if(dist<s.minDist) w*=0.06;
w*=1+l.rare*s.rarity;
total+=w; return w;
});
let r=Math.random()*total;
for(let i=0;i<tbl.length;i++){ r-=ws[i]; if(r<=0) return tbl[i]; }
return tbl[0];
}
function biteWindow(sp){
if(sp.boss) return rand(0.25,0.5); // M4: босс клюёт реже — окно подсечки короче
return Math.max(0.35, 0.8 - sp.rarity*0.08 + save.rod*0.04 + achBonus().windowS);
}
/* Спринт 4: шанс клёва на таймер — не каждый заброс даёт рыбу (дальше = чаще, ночь тише) */
function biteChance(){
const dist=Math.min(1,(castTo.x-(boatX+30))/Math.max(1,W-boatX-70));
let p=0.65+0.25*dist;
if(dayPhase==='night') p*=0.85;
if(weatherActive()==='fog') p*=WEATHER.fog.biteMult; // M8: туман — клёв чаще ×1,5
return p;
}
/* Ролл веса рыбы: сдвиг в крупную сторону зависит от удочки и приманки */
function rollWeight(sp){
const B=Math.min(0.95, rod().size + lure().size);
const s=Math.pow(Math.random(), 2/(1+2*B)); // B=0 → смещено к мелкой, B↑ → ближе к равномерной
return sp.wMin + s*(sp.wMax-sp.wMin);
}
function startBite(){
const dist=Math.min(1,(castTo.x-(boatX+30))/Math.max(1,W-boatX-70));
let sp=pickSpecies(dist);
// M4: осётр → босс (30% шанс или тест-форс) — клонируем, чтобы не трогать таблицу SPECIES
// Этап 37: босс в каждой локации — босс = вид BOSS_BY_LOCATION[save.location]
const bossId=BOSS_BY_LOCATION[save.location|0];
if(bossId===sp.id && (forceBoss || Math.random()<0.3)) sp=Object.assign({},sp,{boss:true});
const fromLeft=Math.random()<0.5;
const d=Math.max(0.25,sp.minDist)*0.8+0.1;
biteFish={
x:fromLeft?-30:W+30, y:waterY+d*(H-waterY-40),
sx:fromLeft?-30:W+30, sy:waterY+d*(H-waterY-40),
dir:fromLeft?1:-1, sp:sp, t:0, mode:'in'
};
state='APPROACH';
}
function hook(){
const sp=biteFish.sp;
biteFish=null;
sfx('hook'); vib(30);
state='REEL';
stateBoss=!!sp.boss; bossPhase=sp.boss?1:0; // M4: старт босс-боя — фаза 1
let w=sp.boss?20+Math.random()*30:rollWeight(sp); // Этап 37: любой босс весит 20–50 кг (без ролла wMin..wMax вида)
const ov=w/rod().maxW; // 1.0 = рыба ровно на пределе удочки
const str=sp.boss?0.95:sp.strength; // M4: босс сильнее (осётр 0.85 → 0.95)
const aggr=Math.min(1, 0.35*str + 0.75*Math.min(1.25,ov)/1.25); // «злость» рыбы
const d0=45+7*w; // чем крупнее, тем дальше от лодки (T2b: буфер для «сдавать в рывок»)
const line=rod().line+achBonus().line; // прочность с бонусом достижений
// Спринт 4: выносливость — крупная рыба выносливее, босс свежий
const st0=sp.boss?1:0.65+0.35*Math.min(1,w/sp.wMax);
reel={d:d0, d0:d0, tension:0, escape:0, holding:false, phase:'calm', phaseT:rand(0.8,1.5), sp:sp, w:w, ov:ov, aggr:aggr, tick:0, line:line, boss:!!sp.boss, st:st0, tired:false};
}
/* Спринт 4: сила рыбы (перетягивание с drag) — глобальная, автотесты вызывают */
function fishForce(r,ag,pull){
const base=pull?(16+34*r.st)*(0.5+0.9*ag)*(0.7+0.5*Math.min(1.5,r.ov)):5+7*ag;
return r.tired?0.45*base:base;
}
function doCast(){
const p=Math.max(0.12,power);
const dist=Math.min(0.97,(0.10+0.80*p)*lure().cast);
castDist=dist; // запоминаем дальность (визуал: глубина крючка оснастки)
castFrom={x:tip.x,y:tip.y};
castTo={x:boatX+30+dist*Math.max(1,W-boatX-70), y:waterY-2};
castT=0; state='CAST'; sfx('cast');
save.casts++;
newDayCheck();
questHit('casts',()=>true); // condFn обязателен: без него questHit падает с TypeError
checkAchievements();
persist();
}
function recall(){
if(state==='WAIT'||state==='APPROACH'||state==='BITE'){
state='IDLE'; biteFish=null; sfx('click');
}
}
function updateReel(dt){
const r=rod(), sp=reel.sp, ag=reel.aggr, ov=reel.ov;
reel.phaseT-=dt;
if(reel.phaseT<=0){
if(reel.phase==='calm'){
// Спринт 4: рывок длиннее у свежей рыбы, короче у уставшей
reel.phase='pull'; reel.phaseT=(0.8+2.2*reel.st)*(0.6+0.7*ag)*rand(0.8,1.25);
sfx('pull'); vib(40);
}else{
// Спринт 4: пауза растёт по мере усталости
reel.phase='calm'; reel.phaseT=Math.max(0.35,(1.3-0.8*reel.st)*rand(0.8,1.3)); vib(15);
}
}
const pulling=reel.phase==='pull';
// Спринт 4 T2b: выносливость — медленная дуга: свежая тянет сильно, уставшая слабо (Monte-Carlo)
const drain=(pulling?0.016+0.02*ag:0.002)+(reel.holding?0.006:0.001)+(pulling&&!reel.holding?0.01:0);
reel.st=Math.max(0,reel.st-drain*dt);
if(reel.st<=0.12) reel.tired=true; // устала: рывки слабее, втягивается быстрее
const F=fishForce(reel,ag,pulling);
if(reel.holding){
// Спринт 4: перетягивание через drag — рывок сильнее тормоза: леска скользит
const over=F-r.drag;
reel.tension+=(10+Math.max(0,over)*1.1+22*ag*(pulling?1:0.35))*dt;
if(over>0) reel.d+=over*0.22*dt;
else reel.d-=(11+3*r.reel)*(1+0.6*(1-reel.st))*dt; // втягивание, усталую быстрее (до ×1.6)
reel.tick-=dt;
if(reel.tick<=0){ sfx('tick'); reel.tick=0.12; }
if(Math.random()<0.3) splash(bobber.x,waterY,1,40); // брызги у поплавка (он едет за рыбой)
}else{
reel.tension-=38*dt;
if(pulling) reel.d+=F*0.32*dt; // свободный бег: рыба реально отходит (стоимость отпускания — дистанция)
}
reel.tension=Math.max(0,reel.tension);
// escape T2b: отпускать в РЫВОК безопасно (бар не растёт) — «сдался рыбе»;
// а вот зависнуть без удержания в затишье = рыба уходит (пассив = сход)
if(reel.holding){
reel.escape=Math.max(0,reel.escape-0.5*dt);
}else if(!pulling){
reel.escape=Math.min(1,reel.escape+(0.2+ag*0.4)*dt);
}
if(reel.escape>=1){
fishEscaped(sp);
return;
}
if(reel.tension>=reel.line){
state='SNAP'; snapT=1.0; shake=0.5;
save.snaps++; persist(); // счётчик обрывов (достижения)
sfx('snap'); vib(200);
stateBoss=false; bossPhase=0; // M4: настоящий обрыв — босс-бой окончен
toast((ov>1.15?t('snap_big'):t('snap'))+' '+trName(sp)+' '+reel.w.toFixed(1)+' '+t('kg')); // Э42: без эмодзи вида (убраны из SPECIES)
checkAchievements();
}else if(reel.d<=0){
if(reel.boss && bossPhase<3){
// M4: босс-обрыв фаз 1-2 — без штрафа (без save.snaps++), дальше фаза глубже
state='SNAP'; snapT=0.6; shake=0.5;
sfx('snap'); vib(120);
toast(tt('boss_phase',{p:bossPhase}));
}else{
catchFish(sp);
}
}else if(reel.d>=reel.d0*1.45){
// M4: босс тоже может уйти — босс-бой окончен
fishEscaped(sp);
}
}
function fishEscaped(sp){
stateBoss=false; bossPhase=0;
toast(t('escaped')+' '+trName(sp)+' '+reel.w.toFixed(1)+' '+t('kg')); // Э42: без эмодзи вида (убраны из SPECIES)
state='WAIT'; biteTimer=rand(5,10)/lure().bite;
sfx('escape');
}
function catchFish(sp){
const w=reel.w;
const boss=!!reel.boss; // M4: пойман босс (Этап 37: в каждой локации)
const variant=boss?VARIANTS[0]:rollVariant(); // M6: вариант улова (босс — всегда normal, без сложения с ×5)
const shiny=variant.id==='gold'; // M6: семантика «shiny» = gold-вариант (квест, счётчик sn)
const b=achBonus();
const mult=variant.mult*(boss?5:1); // M4: босс = ×5 к цене
const val=Math.max(1,Math.round(w*sp.price*mult*(0.95+Math.random()*0.1)*(1+b.coinPct)));
save.coins+=val; save.earned+=val;
const rec=Object.assign({n:0,best:0,cp:0,sv:0,qz:0,sn:0,em:0,dm:0,rb:0},save.caught[sp.id]||{});
const isRecord=w>rec.best;
rec.n++; rec.best=Math.max(rec.best,w);
const vk=VARIANT_KEY[variant.id]; if(vk) rec[vk]=(rec[vk]||0)+1;
save.caught[sp.id]=rec;
if(boss){ // M4: босс побеждён
save.bossBeaten=true; save.bossCount++;
if(!save.bosses||typeof save.bosses!=='object') save.bosses={}; // Этап 37: защита in-memory старого сейва
save.bosses[sp.id]=true; // Этап 37: пер-босс трекинг (ачивки lake_boss/sea_boss/ocean_boss)
toast(tt('boss_defeated',{v:val}));
}
newDayCheck();
questHit('catch_species',q=>sp.id===q.param);
questHit('catch_weight',q=>w>=q.param);
questHit('catch_rarity',q=>sp.rarity>=q.param);
questHit('catch_shiny',q=>shiny); // M6: «shiny-рыба» = gold-вариант
questHit('earn_coins',()=>true,val); // прогресс — монеты улова (с бонусами)
// Этап 22: счётчики достижений — общий вес, ночной улов, уловы в дождь/туман
save.kgTotal=(save.kgTotal||0)+w;
if(dayPhase==='night') save.nightCatch=true;
const wx=weatherActive();
if(wx==='rain'&&variant.id!=='normal') save.wxRainV=(save.wxRainV||0)+1; // босс всегда normal — не заходит
if(wx==='fog') save.wxFog=(save.wxFog||0)+1;
checkAchievements();
persist(); updateHUD();
sfx('catch'); vib([40,60,40]);
splash(castTo.x,waterY,boss?40:26,boss?180:140);
// вариант — ярче: больше и разноцветнее золотых частиц; босс — частицы крупнее
for(let i=0;i<(boss?44:(variant.id!=='normal'?28:10));i++){
particles.push({x:castTo.x,y:waterY,vx:rand(-80,80),vy:rand(-240,-80),g:300,
life:rand(0.5,0.9),max:0.9,size:boss?rand(3,7):rand(2,4),
color:(variant.id!=='normal'&&i%3===0)?'255,246,190':'255,215,94'});
}
reel=null; stateBoss=false; bossPhase=0; state='CARD';
showCard(sp,w,val,isRecord,variant,boss);
}
function updateGame(dt){
// фоновые рыбы
for(const f of ambient){
f.x+=f.dir*f.speed*dt;
if(f.dir>0&&f.x>W+40){ f.x=-40; f.depth=rand(0.12,0.92); }
if(f.dir<0&&f.x<-40){ f.x=W+40; f.depth=rand(0.12,0.92); }
}
switch(state){
case 'CHARGE':
charge+=dt;
power=1-Math.abs(1-((charge/0.9)%2));
break;
case 'CAST':{
castT+=dt/0.65;
if(castT>=1){
castT=1;
bobber={x:castTo.x,y:waterY-2};
state='WAIT';
biteTimer=rand(4,10)/lure().bite;
nightNoLightToast=false; // новый заброс — тост о фонарике может показаться снова
splash(castTo.x,waterY,14,100);
addRipple(castTo.x,waterY,40);
sfx('splash'); vib(10);
}else{
const t=castT;
bobber.x=castFrom.x+(castTo.x-castFrom.x)*t;
bobber.y=castFrom.y+(castTo.y-castFrom.y)*t-150*Math.sin(Math.PI*t);
}
break;
}
case 'WAIT':{
bobber.y=waterY-3+Math.sin(time*2)*1.5;
rippleTimer-=dt;
if(rippleTimer<=0){ addRipple(bobber.x,waterY+3,22); rippleTimer=1.6; }
if(biteFish&&biteFish.mode==='out') updateBiteFishOut(dt);
biteTimer-=dt;
if(biteTimer<=0&&!biteFish){
if(dayPhase==='night'&&!hasLight()){
// M5: ночью без фонарика клёва нет — таймер тикает вхолостую
// (фонарик — апгрейд 1 удилища: save.rodLv[save.rod]>=2)
if(!nightNoLightToast){ toast(t('night_light')); nightNoLightToast=true; }
}else if(forceBite||Math.random()<biteChance()){
startBite();
}else{
// Спринт 4: пустой клёв — поплавок молчит, попробуем ещё раз
biteTimer=rand(2.5,5)/lure().bite;
}
}
break;
}
case 'APPROACH':
updateBiteFishIn(dt);
bobber.y=waterY-3+Math.sin(time*2)*1.5+Math.sin(time*14)*1.5*Math.min(1,biteFish?biteFish.t:0); // предвестники: дрожание, сильнее по мере приближения рыбы
if(biteFish){
if(biteFish.t>=1){
state='BITE';
biteT=biteWindow(biteFish.sp);
sfx('bite'); vib(60);
addRipple(castTo.x,waterY+3,30);
}
}
break;
case 'BITE':
biteT-=dt;
bobber.y=waterY+9+Math.sin(time*22)*3; // топление: глубже и резче (синхронно с дёрганием рыбы у крючка)
if(Math.random()<0.2) addRipple(bobber.x,waterY+3,26);
if(biteT<=0){
if(biteFish) biteFish.mode='out';
state='WAIT'; biteTimer=rand(5,11)/lure().bite;
sfx('escape'); toast(t('escaped_bite'));
}
break;
case 'REEL':
updateReel(dt);
if(state==='REEL'&&reel){
const fp=fishReelPos();
let tx,ty;
if(reel.holding){
// натянуто: поплавок на пересечении прямой tip→fish с поверхностью (tip–поплавок–рыба коллинеарны, fp.y>waterY>tip.y)
const k=(waterY-tip.y)/(fp.y-tip.y);
tx=tip.x+(fp.x-tip.x)*k; ty=waterY-2;
}else{
// отпускание: провис, поплавок едет за рыбой с отставанием (покачивание на поверхности)
tx=castTo.x+(fp.x-castTo.x)*0.55; ty=waterY-2+Math.sin(time*9)*2;
}
const sm=Math.min(1,dt*8); // сглаживание, чтобы не телепортировалось
bobber.x+=(tx-bobber.x)*sm;
bobber.y+=(ty-bobber.y)*sm;
if(Math.random()<0.25) addRipple(bobber.x,waterY+3,24);
}
break;
case 'SNAP':
snapT-=dt;
if(snapT<=0){
if(stateBoss && bossPhase<3){
// M4: босс-обрыв — не штраф: автоматом следующая (глубже) фаза, без ввода
reel.d=(bossPhase===1?0.6:1.0)*reel.d0; // фаза2: d=0.6·d0, фаза3: d=1.0·d0
reel.tension=0; // фазовый обрыв сбрасывает нагрузку, иначе «беспошлинный» обрыв ведёт к настоящему
bossPhase++;
state='REEL';
}else{
state='IDLE';
}
}
break;
}
}
function updateBiteFishIn(dt){
biteFish.t+=dt/0.45;
const t=Math.min(1,biteFish.t);
const e=t*t*(3-2*t);
// рыба плывёт диагональю от поверхности вниз к крючку/наживке (hookPos — кадр прошлого, паттерн как раньше)
biteFish.x=biteFish.sx+(hookPos.x-biteFish.sx)*e;
biteFish.y=biteFish.sy+(hookPos.y-biteFish.sy)*e;
biteFish.dir=hookPos.x>biteFish.sx?1:-1;
}
function updateBiteFishOut(dt){
biteFish.t+=dt/0.6;
const dir=biteFish.x<W/2?-1:1;
biteFish.x+=dir*380*dt;
biteFish.y+=40*dt;
if(biteFish.t>=1||biteFish.x<-50||biteFish.x>W+50) biteFish=null;
}
function updateDecor(dt){
for(const c of clouds){ c.x+=c.v*dt; if(c.x>W+80) c.x=-80; }
// Этап 44: дрейф силуэтов — парусник медленно (по курсу), чайки быстрее (вправо)
for(const o of scenery){
if(o.k==='ship'){ o.x+=o.dir*o.v*dt; if(o.dir>0&&o.x>W+40) o.x=-40; if(o.dir<0&&o.x<-40) o.x=W+40; }
else if(o.k==='gull'){ o.x+=o.v*dt; if(o.x>W+30) o.x=-30; }
}
// Этап 45: Болото — покачивание кувшинок (sin, амплитуда 1–2 px) и прыжки лягушек.
// Лягушка сидит (таймер 3–7 с) → параболический прыжок (t 0..1) на соседнюю кувшинку → садится.
for(const p of pads) p.bob=Math.sin(time*1.1+p.ph)*1.6;
for(const fr of frogs){
if(fr.state==='jump'){
fr.t+=dt/fr.dur;
if(fr.t>=1){ // приземлилась
fr.x=fr.x1; fr.y=fr.y1; fr.state='sit'; fr.t=rand(3,7);
}else{
const k=fr.t;
fr.x=fr.x0+(fr.x1-fr.x0)*k;
fr.y=fr.y0+(fr.y1-fr.y0)*k-Math.sin(Math.PI*k)*fr.jh; // парабола dx/dy
}
}else{
fr.t-=dt;
if(fr.t<=0){ // выбор цели: ближайшая ДРУГАЯ кувшинка, иначе случайная точка воды
let tgt=null,best=1e9;
for(const p of pads){
const d=(p.x-fr.x)*(p.x-fr.x)+(p.y-fr.y)*(p.y-fr.y);
if(d>16&&d<best){ best=d; tgt=p; }
}
fr.x0=fr.x; fr.y0=fr.y;
if(tgt&&Math.random()<0.85){ fr.x1=tgt.x; fr.y1=tgt.y-2; }
else{
fr.x1=Math.max(20,Math.min(W-20,fr.x+rand(-90,90)));
fr.y1=Math.min(H-24,Math.max(waterY+24,fr.y+rand(-24,36)));
}
fr.dur=rand(0.4,0.7); fr.jh=rand(16,30); fr.t=0; fr.state='jump';
fr.dir=fr.x1>=fr.x0?1:-1;
}
}
}
// M8: дождь — полоски летят вниз-влево, ушедшие за нижний край возвращаются сверху
if(weatherActive()==='rain'){
for(const dr of rain){
dr.y+=dr.v*dt; dr.x-=dr.v*0.3*dt;
if(dr.y>H+20){ dr.y=rand(-120,-20); dr.x=rand(-40,W+40); }
if(dr.x<-60) dr.x=W+40;
}
}
for(let i=particles.length-1;i>=0;i--){
const p=particles[i];
p.life-=dt; p.vy+=p.g*dt; p.x+=p.vx*dt; p.y+=p.vy*dt;
if(p.life<=0||p.y>H) particles.splice(i,1);
}
for(let i=ripples.length-1;i>=0;i--){
const r=ripples[i];
r.r+=45*dt; r.a-=0.9*dt;
if(r.a<=0||r.r>r.max) ripples.splice(i,1);
}
if(shake>0) shake-=dt;
}
function syncDom(){
document.body.classList.toggle('aq-open',aqOpen); // Этап 46: под сценой банки HUD скрыт (CSS body.aq-open #hud)
if(aqOpen){ // Этап 46: под сценой банки игровые HUD-кнопки не показываем
$('btnRecall').classList.add('hidden');
$('btnPause').classList.add('hidden');
return;
}
const showRecall=(state==='WAIT'||state==='APPROACH'||state==='BITE');
$('btnRecall').classList.toggle('hidden',!showRecall);
$('btnPause').classList.toggle('hidden',!(state!=='MENU'&&!uiOpen&&!pauseOpen)); // Y6: пауза — вне меню и без оверлеев
}
/* =========================================================
ОТРИСОВКА
========================================================= */
const UI_FONT="'EmojiEmbedded',system-ui"; // Э28: для canvas-текста (emoji 💥🌀⚡💪💤) — встроенный шрифт первым, как в CSS
function rr(x,y,w,h,r){
ctx.beginPath();
ctx.moveTo(x+r,y);
ctx.arcTo(x+w,y,x+w,y+h,r);
ctx.arcTo(x+w,y+h,x,y+h,r);
ctx.arcTo(x,y+h,x,y,r);
ctx.arcTo(x,y,x+w,y,r);
ctx.closePath();
}
const SKY_PHASES={ // M3: градиенты неба по фазе суток
morning:['#f5a623','#fce38a'],
day:['#7ec8e3','#cfeef7'],
evening:['#e44d26','#f16529'],
night:['#0c1445','#1a237e']
};
/* Визуал: плавные переходы неба/освещения — зона перехода в КОНЦЕ фазы
(ночь темнеет к концу вечера, рассвет — в конце ночи; на стыке t=0 чистое утро) */
const SKY_SEQ=['morning','day','evening','night'];
const SKY_BOUNDS=[0.25,0.5,0.75,1.0]; // переход к следующей фазе завершается на границе
const SKY_ZONE=0.08; // ширина переходной зоны
function hexLerp(a,b,k){
const pa=parseInt(a.slice(1),16),pb=parseInt(b.slice(1),16);
const r=Math.round(((pa>>16)&255)+(((pb>>16)&255)-((pa>>16)&255))*k);
const g=Math.round(((pa>>8)&255)+(((pb>>8)&255)-((pa>>8)&255))*k);
const bl=Math.round((pa&255)+((pb&255)-(pa&255))*k);
return 'rgb('+r+','+g+','+bl+')';
}
function skyColors(){
const t=dayTime;
for(let i=0;i<4;i++){
const b=SKY_BOUNDS[i];
if(t<b||i===3){
const a=SKY_PHASES[SKY_SEQ[i]], c=SKY_PHASES[SKY_SEQ[(i+1)%4]];
const z0=b-SKY_ZONE;
if(t>=z0){ const k=Math.max(0,Math.min(1,(t-z0)/SKY_ZONE)); return [hexLerp(a[0],c[0],k),hexLerp(a[1],c[1],k)]; }
return [a[0],a[1]];
}
}
return [SKY_PHASES.morning[0],SKY_PHASES.morning[1]];
}
/* Числовые величины (ночная доля и т.п.) с теми же переходами */
function phaseLerp(vals){
const t=dayTime;
for(let i=0;i<4;i++){
const b=SKY_BOUNDS[i];
if(t<b||i===3){
const z0=b-SKY_ZONE;
if(t>=z0){ const k=Math.max(0,Math.min(1,(t-z0)/SKY_ZONE)); return vals[i]+(vals[(i+1)%4]-vals[i])*k; }
return vals[i];
}
}
return vals[0];
}
/* Ночная доля освещения 0..1 (1 = глубокая ночь) — вода, звёзды, фонарь */
function nightMix(){ return phaseLerp([0,0,0.4,1]); }
let luminary={x:0,y:0,a:0,night:false}; // визуал: где солнце/луна и её яркость (для дорожки на воде)
function drawSky(){
const cols=skyColors();
const nm=nightMix();
const g=ctx.createLinearGradient(0,0,0,waterY);
g.addColorStop(0,cols[0]); g.addColorStop(1,cols[1]);
ctx.fillStyle=g; ctx.fillRect(0,0,W,waterY);
// звёзды — проступают с ночью, мерцают
if(nm>0.15){
for(const st of stars){
const a=nm*Math.max(0,Math.sin(time*st.sp+st.ph))*0.9;
if(a>0.03){
ctx.fillStyle='rgba(255,255,255,'+a.toFixed(3)+')';
ctx.beginPath(); ctx.arc(st.x,st.y,st.r,0,7); ctx.fill();
}
}
}
// M3: солнце/луна по дуге (визуал: мягкое свечение, гаснут/всходят в сумерках без наложения)
const ang=dayTime*2*Math.PI;
const bx=W/2+Math.cos(ang)*W*0.4, by=H*0.15-Math.sin(ang)*H*0.1;
luminary.x=bx; luminary.y=by; luminary.a=0; luminary.night=false;
if(nm<0.45){
const a=1-nm/0.45; // солнце садится к ночи
luminary.a=a;
ctx.globalAlpha=Math.max(0,a);
const glow=ctx.createRadialGradient(bx,by,6,bx,by,64);
glow.addColorStop(0,'rgba(255,225,130,0.5)'); glow.addColorStop(1,'rgba(255,225,130,0)');
ctx.fillStyle=glow; ctx.fillRect(bx-64,by-64,128,128);
ctx.fillStyle='#ffd700';
ctx.beginPath(); ctx.arc(bx,by,20,0,7); ctx.fill();
ctx.fillStyle='rgba(255,255,255,0.5)';
ctx.beginPath(); ctx.arc(bx-6,by-6,7,0,7); ctx.fill();
ctx.globalAlpha=1;
}else if(nm>0.55){
const a=(nm-0.55)/0.45; // луна всходит в глубине сумерек
luminary.a=a; luminary.night=true;
ctx.globalAlpha=Math.max(0,Math.min(1,a));
const glow=ctx.createRadialGradient(bx,by,8,bx,by,56);
glow.addColorStop(0,'rgba(220,230,255,0.32)'); glow.addColorStop(1,'rgba(220,230,255,0)');
ctx.fillStyle=glow; ctx.fillRect(bx-56,by-56,112,112);
ctx.fillStyle='#f5f5dc';
ctx.beginPath(); ctx.arc(bx,by,18,0,7); ctx.fill();
// кратеры
ctx.fillStyle='rgba(120,130,150,0.35)';
ctx.beginPath(); ctx.arc(bx+6,by+3,3.2,0,7); ctx.fill();
ctx.beginPath(); ctx.arc(bx-4,by+7,2.2,0,7); ctx.fill();
ctx.beginPath(); ctx.arc(bx-2,by-6,2.6,0,7); ctx.fill();
// серп — вырез цветом неба в точке луны
ctx.fillStyle=cols[0];
ctx.beginPath(); ctx.arc(bx+9,by-6,13.5,0,7); ctx.fill();
ctx.globalAlpha=1;
}
// облака (ночью приглушены)
ctx.fillStyle='rgba(255,255,255,'+(0.9-0.68*nm).toFixed(3)+')';
for(const c of clouds){
ctx.save(); ctx.translate(c.x,c.y); ctx.scale(c.s,c.s);
ctx.beginPath();
ctx.arc(0,0,14,0,7); ctx.arc(16,-6,12,0,7); ctx.arc(32,0,15,0,7); ctx.arc(16,6,13,0,7);
ctx.fill(); ctx.restore();
}
}
/* Этап 44: береговые силуэты по локации (см. initScenery). Ночь — силуэты гаснут
к тёмно-синему (hexLerp к #0b1220), парусник/чайки темнеют. Рисуется ПЕРЕД водой:
то, что проваливается под линию воды (низ холмов/киль), перекрывается градиентом */
function drawScenery(){
if(!scenery.length) return;
const nm=nightMix();
const dusk=c=>hexLerp(c,'#0b1220',nm*0.8);
const y0=waterY+1; // базовая линия — чуть под кромкой, чтобы «сесть» на воду
for(const o of scenery){
if(o.k==='bank'){
// Река: береговая полоса на всю ширину (трава + тёмная влажная кромка у воды);
// рисуется ПЕРВОЙ (в scenery стоит первой) — лес сажается на её верхнюю кромку.
// Этап 45: у Болота — своя мшистая гамма (c/c2), у остальных локаций цвета те же
ctx.fillStyle=dusk(o.c||'#4e7a4e');
ctx.fillRect(0,waterY-o.h,W,o.h+3);
ctx.fillStyle=dusk(o.c2||'#39583c');
ctx.fillRect(0,waterY-3,W,6);
}else if(o.k==='pine'){
// сосна: ствол + 3 яруса (дальний ряд — светлее и выше, ближний — темнее);
// база ствола — o.by (у реки — верх кромки берега), по умолчанию линия воды;
// Этап 45: цвет o.c — болотные туи темнее речных сосен
const pb=o.by==null?y0:o.by;
ctx.fillStyle=dusk(o.c||(o.layer?'#24452f':'#3a6a4a'));
ctx.fillRect(o.x-1.2,pb-3,2.4,4);
for(let t=0;t<3;t++){
const by=pb-3-t*o.h*0.26, hw=o.h*0.3*(1-0.3*t), th=o.h*0.42;
ctx.beginPath(); ctx.moveTo(o.x-hw,by); ctx.lineTo(o.x+hw,by); ctx.lineTo(o.x,by-th);
ctx.closePath(); ctx.fill();
}
}else if(o.k==='hill'){
// холм: дуга эллипса над линией воды (низ закроет вода)
ctx.fillStyle=dusk('#4a7a5e');
ctx.beginPath(); ctx.ellipse(o.x,y0+4,o.rx,o.ry,0,Math.PI,0); ctx.fill();
}else if(o.k==='tree'){
// лиственное дерево: ствол + крона из трёх кругов (o.c — опциональный цвет)
ctx.fillStyle=dusk(o.c||'#3c6b4f');
ctx.fillRect(o.x-1,y0-o.h*0.5,2,o.h*0.5+1);
ctx.beginPath();
ctx.arc(o.x,y0-o.h,o.h*0.42,0,7);
ctx.arc(o.x-o.h*0.3,y0-o.h*0.78,o.h*0.34,0,7);
ctx.arc(o.x+o.h*0.3,y0-o.h*0.78,o.h*0.34,0,7);
ctx.fill();
}else if(o.k==='reed'){
// Этап 45: камыш — пучок тонких стеблей с метёлками, качается на ветру (болотная гамма)
const sway=Math.sin(time*0.9+o.ph)*o.lean;
for(let t=0;t<4;t++){
const off=(t-1.5)*2.2;
const h=o.h*(0.72+0.07*t);
const tx=o.x+off+sway*(0.6+t*0.14), ty=y0-h;
ctx.strokeStyle=dusk('#3f5a2e'); ctx.lineWidth=1.2;
ctx.beginPath(); ctx.moveTo(o.x+off,y0);
ctx.quadraticCurveTo(o.x+off+sway*0.4,y0-h*0.6,tx,ty); ctx.stroke();
ctx.fillStyle=dusk('#7a6a35'); // метёлка
ctx.beginPath(); ctx.ellipse(tx,ty,1.7,4.5,sway*0.06,0,7); ctx.fill();
}
}else if(o.k==='snag'){
// Этап 45: кривое болотное дерево — наклонный ствол + пара голых веток
const ln=o.lean||0;
ctx.save(); // не оставляем lineCap/lineWidth остальным слоям кадра
ctx.strokeStyle=dusk('#5a5340'); ctx.lineWidth=2.4; ctx.lineCap='round';
ctx.beginPath(); ctx.moveTo(o.x,y0);
ctx.quadraticCurveTo(o.x+ln*o.h*0.5,y0-o.h*0.55,o.x+ln*o.h,y0-o.h); ctx.stroke();
ctx.lineWidth=1.6;
ctx.beginPath(); ctx.moveTo(o.x+ln*o.h*0.25,y0-o.h*0.5);
ctx.lineTo(o.x+ln*o.h*0.25-o.h*0.3,y0-o.h*0.62); ctx.stroke();
ctx.beginPath(); ctx.moveTo(o.x+ln*o.h*0.4,y0-o.h*0.72);
ctx.lineTo(o.x+ln*o.h*0.4+o.h*0.26,y0-o.h*0.8); ctx.stroke();
ctx.restore();
}else if(o.k==='ship'){
// парусник: киль/мачта/два паруса (парус светлее силуэта — читается на небе)
ctx.save(); ctx.translate(o.x,0); ctx.scale(o.dir,1);
const s=o.s;
ctx.fillStyle=dusk('#3a4f63');
ctx.beginPath(); ctx.moveTo(-14*s,y0-4*s); ctx.lineTo(14*s,y0-4*s); ctx.lineTo(9*s,y0+1); ctx.lineTo(-9*s,y0+1);
ctx.closePath(); ctx.fill();
ctx.strokeStyle=dusk('#3a4f63'); ctx.lineWidth=1.6;
ctx.beginPath(); ctx.moveTo(0,y0-4*s); ctx.lineTo(0,y0-22*s); ctx.stroke();
ctx.fillStyle='rgba(235,242,250,'+(0.9-0.45*nm).toFixed(3)+')';
ctx.beginPath(); ctx.moveTo(1.5,y0-4.5*s); ctx.lineTo(1.5,y0-20*s); ctx.lineTo(12*s,y0-5.5*s);
ctx.closePath(); ctx.fill();
ctx.beginPath(); ctx.moveTo(-1.5,y0-4.5*s); ctx.lineTo(-1.5,y0-16*s); ctx.lineTo(-10*s,y0-5.5*s);
ctx.closePath(); ctx.fill();
ctx.restore();
}else if(o.k==='gull'){
// чайка: две дуги крыла, взмах синусом; ночью почти гаснет
const a=0.65-0.4*nm;
if(a<0.12) continue;
const y=y0-o.y+Math.sin(time*1.3+o.ph)*3;
const f=Math.sin(time*7+o.ph)*0.5+0.5;
ctx.strokeStyle='rgba(35,45,60,'+a.toFixed(3)+')';
ctx.lineWidth=1.4;
ctx.beginPath();
ctx.moveTo(o.x-6,y);
ctx.quadraticCurveTo(o.x-3,y-3-3*f,o.x,y);
ctx.quadraticCurveTo(o.x+3,y-3-3*f,o.x+6,y);
ctx.stroke();
}
}
}
function drawWater(){
const nm=nightMix();
// градиент воды: день ↔ ночь, плавно (визуал); Этап 5: базовые цвета по локации (LOCATIONS)
const loc=LOCATIONS[Math.max(0,Math.min(LOCATIONS.length-1,save.location|0))]; // clamp — миграция гарантирует диапазон
const w=loc.water;
const top=hexLerp(w[0],w[3],nm), bot=hexLerp(w[2],w[5],nm);
const g=ctx.createLinearGradient(0,waterY,0,H);
g.addColorStop(0,top); g.addColorStop(0.55,hexLerp(w[1],w[4],nm)); g.addColorStop(1,bot);
ctx.fillStyle=g; ctx.fillRect(0,waterY,W,H-waterY);
// дорожка света от солнца/луны — мерцающие блики под светилом
if(luminary.a>0.05){
const depth=Math.min(1,Math.max(0,(luminary.y)/(waterY||1))); // светило низко — дорожка длиннее
const len=(H-waterY)*(0.18+0.3*depth);
const base=(luminary.night?0.12:0.2)*luminary.a;
ctx.fillStyle=luminary.night?'rgba(200,220,255,1)':'rgba(255,235,170,1)';
for(let y=waterY+6;y<waterY+len;y+=7){
const k=(y-waterY)/len;
const wob=Math.sin(time*2.2+y*0.55);
const a=Math.max(0,base*(1-k)*(0.45+0.55*wob));
if(a<0.02) continue;
ctx.globalAlpha=a;
const wdt=14+k*30+Math.sin(time*1.7+y)*4;
ctx.fillRect(luminary.x-wdt/2,y,wdt,2);
}
ctx.globalAlpha=1;
}
// блики
for(const s of sparkles){
const a=Math.max(0,Math.sin(time*1.5+s.ph))*0.25*(1-nm*0.5);
if(a>0.02){ ctx.fillStyle='rgba(255,255,255,'+a.toFixed(3)+')'; ctx.fillRect(s.x,s.y,3,1.5); }
}
// волна на поверхности + вторая, глубинная (визуал); Этап 43: характер по локации (LOCATIONS.waves);
// ревизия Этапа 44: amp/amp2=0 — линия не рисуется (Река — спокойная вода без волн)
const wv=loc.waves;
if(wv.amp>0){
ctx.strokeStyle='rgba(255,255,255,'+(0.55-nm*0.25).toFixed(3)+')'; ctx.lineWidth=2;
ctx.beginPath();
for(let x=0;x<=W;x+=8){
const y=waterY+Math.sin(x*wv.freq+time*wv.speed)*wv.amp;
if(x===0) ctx.moveTo(x,y); else ctx.lineTo(x,y);
}
ctx.stroke();
}
if(wv.amp2>0){
ctx.strokeStyle='rgba(255,255,255,'+(0.2-nm*0.1).toFixed(3)+')'; ctx.lineWidth=1.5;
ctx.beginPath();
for(let x=0;x<=W;x+=10){
const y=waterY+7+Math.sin(x*wv.freq2-time*wv.speed2+1.7)*wv.amp2;
if(x===0) ctx.moveTo(x,y); else ctx.lineTo(x,y);
}
ctx.stroke();
}
}
/* Фаза свечения «Волшебного болота»: аура-свечение (радиальный градиент + 'lighter').
rgba-строки цветов кэшируются по hex — строки не собираются каждый кадр (мобильные аллокации).
Профиль градиента крутой (свет собран у тела рыбы), интенсивность масштабирует альфу через
globalAlpha. Аура рисуется ПОЗАДИ силуэта, поэтому контур рыбы остаётся чётким. */
const GLOW_RGBA={}; // hex -> {in:'rgba(...,0.55)',mid:'rgba(...,0.30)',out:'rgba(...,0)'}
function glowColors(hex){
let c=GLOW_RGBA[hex];
if(!c){
const h=hex.replace('#','');
const r=parseInt(h.substr(0,2),16),g=parseInt(h.substr(2,2),16),b=parseInt(h.substr(4,2),16);
c=GLOW_RGBA[hex]={
in:'rgba('+r+','+g+','+b+',0.55)',
mid:'rgba('+r+','+g+','+b+',0.30)',
out:'rgba('+r+','+g+','+b+',0)'
};
}
return c;
}
/* Плавный ramp ночного свечения: 0 при nightMix()<=0.35 (тот же старт, что у фонаря лодки),
затем smoothstep до 1 при nightMix()>=0.9 — вечером разгорается, к утру гаснет. */
function glowIntensity(){
const nm=nightMix();
if(nm<=0.35) return 0;
const k=Math.min(1,(nm-0.35)/0.55);
return k*k*(3-2*k); // smoothstep 0..1
}
// I — интенсивность 0..1 (glowIntensity): множитель на альфу ВСЕХ стопов профиля (globalAlpha)
function drawGlowAura(x,y,r,hex,I){
if(I<=0.02) return; // почти не видно — не создаём градиент/заливку
const c=glowColors(hex);
ctx.save(); // изолируем 'lighter', globalAlpha и fillStyle — не ломаем остальную отрисовку
ctx.globalCompositeOperation='lighter';
ctx.globalAlpha=I;
const g=ctx.createRadialGradient(x,y,r*0.12,x,y,r);
g.addColorStop(0,c.in); g.addColorStop(0.45,c.mid); g.addColorStop(1,c.out);
ctx.fillStyle=g; ctx.fillRect(x-r,y-r,r*2,r*2);
ctx.restore();
}
// Аура светящегося вида: интенсивность плавно растёт с ночью (glowIntensity), утром гаснет
function fishGlow(sp,x,y,r){
if(sp&&sp.glow) drawGlowAura(x,y,r,sp.glow,glowIntensity());
}
function drawFishShape(x,y,size,dir,hue,alpha,wob){
ctx.save(); ctx.translate(x,y); ctx.scale(dir,1);
const w=wob||0;
ctx.fillStyle='hsla('+hue+',55%,38%,'+alpha+')';
ctx.beginPath(); ctx.ellipse(0,0,size,size*0.45,0,0,7); ctx.fill();
// хвост качается (визуал)
ctx.save(); ctx.translate(-size*0.8,0); ctx.rotate(w);
ctx.beginPath();
ctx.moveTo(0,0); ctx.lineTo(-size*0.65,-size*0.42); ctx.lineTo(-size*0.65,size*0.42);
ctx.closePath(); ctx.fill();
ctx.restore();
// блик на спинке + глаз (визуал: живость, у силуэтов едва видны)
ctx.fillStyle='rgba(255,255,255,'+(alpha*0.22).toFixed(3)+')';
ctx.beginPath(); ctx.ellipse(-size*0.1,-size*0.16,size*0.55,size*0.18,-0.25,0,7); ctx.fill();
ctx.fillStyle='rgba(10,25,40,'+(alpha*0.8).toFixed(3)+')';
ctx.beginPath(); ctx.arc(size*0.6,-size*0.07,size*0.09,0,7); ctx.fill();
ctx.restore();
}
function drawAmbientFish(){
const glowI=save.location===4?glowIntensity():0; // свечение фоновых рыб — только Болото, плавный ramp
for(const f of ambient){
const y=waterY+20+f.depth*(H-waterY-50)+Math.sin(time*2+f.ph)*2;
let a=0.22+0.2*(1-f.depth);
if(f.glow){ // болотная рыба: компактный ореол + непрозрачное тело к ночи — контур чёткий
if(glowI>0.02) drawGlowAura(f.x,y,f.size*1.5,f.glow,glowI); // цвет каждой рыбы из palette
a=a+(1-a)*glowI; // к глубокой ночи силуэт становится полностью непрозрачным
}
drawFishShape(f.x,y,f.size,f.dir,f.hue,a,Math.sin(time*5+f.ph)*0.28);
}
}
/* Этап 45: декор «Волшебного болота» — кувшинки с лилиями и прыгающие лягушки.
Отдельный слой ПОВЕРХ воды (вызов в draw() после drawWater/drawAmbientFish, до drawBoat):
рисуется после воды, поэтому dusk() берега его не гасит. К ночи декор лишь притухает
(hexLerp к тёмно-зелёному), днём — живой, а ночное свечение рыб (B2) остаётся видимым.
Фигуры простые (arc/ellipse/lineTo) без shadowBlur и градиентов на кадр. */
function drawSwampDecor(){
if(!pads.length&&!frogs.length) return;
const nm=nightMix();
const dusk=c=>hexLerp(c,'#0b1a12',nm*0.55);
// --- кувшинки (+ лилии на части из них) ---
for(const p of pads){
const x=p.x, y=p.y+p.bob;
// кувшинка: эллипс с радиальным вырезом-прорезью (Pac-Man-образный клин к центру)
ctx.fillStyle=dusk('#2f6b3a');
ctx.strokeStyle=dusk('#1d4527'); ctx.lineWidth=1;
ctx.beginPath();
ctx.moveTo(x,y);
ctx.arc(x,y,p.r,p.notch+0.24,p.notch-0.24+Math.PI*2);
ctx.closePath(); ctx.fill(); ctx.stroke();
// блик на листе (визуал)
ctx.fillStyle=dusk('#3f7f4a');
ctx.beginPath(); ctx.ellipse(x-p.r*0.28,y-p.r*0.22,p.r*0.42,p.r*0.2,-0.3,0,7); ctx.fill();
// лилия: 6 лепестков-эллипсов одного из трёх цветов (жёлтый/белый/розовый)
if(p.lily){
const lx=x+p.r*0.28, ly=y-p.r*0.26;
ctx.fillStyle=dusk(p.lilyColor);
for(let k=0;k<6;k++){
const a=k/6*Math.PI*2+p.ph*0.2;
ctx.beginPath();
ctx.ellipse(lx+Math.cos(a)*3.2,ly+Math.sin(a)*2.4,3.4,1.9,a,0,7);
ctx.fill();
}
}
}
// --- лягушки (тело + задние лапы, тёмно-зелёные; прыгают по параболе из updateDecor) ---
for(const fr of frogs){
const s=fr.s, dir=fr.dir||1;
ctx.save(); ctx.translate(fr.x,fr.y); ctx.scale(dir,1);
ctx.fillStyle=dusk('#2f5a2a');
// задние лапы
ctx.beginPath(); ctx.ellipse(-s*0.55,s*0.55,s*0.72,s*0.34,-0.4,0,7); ctx.fill();
ctx.beginPath(); ctx.ellipse(s*0.1,s*0.72,s*0.78,s*0.3,0.35,0,7); ctx.fill();
// тело
ctx.beginPath(); ctx.ellipse(0,0,s,s*0.72,0,0,7); ctx.fill();
// голова + глаз
ctx.fillStyle=dusk('#3f7a38');
ctx.beginPath(); ctx.ellipse(s*0.68,-s*0.28,s*0.46,s*0.4,0,0,7); ctx.fill();
ctx.fillStyle='rgba(10,25,10,0.9)';
ctx.beginPath(); ctx.arc(s*0.84,-s*0.4,s*0.13,0,7); ctx.fill();
// передние лапы
ctx.fillStyle=dusk('#2f5a2a');
ctx.beginPath(); ctx.ellipse(s*0.5,s*0.5,s*0.5,s*0.2,0.5,0,7); ctx.fill();
ctx.restore();
}
}
function drawBoat(){
const bx=boatX, by=waterY+Math.sin(time*1.5)*1.5;
// блик-отражение под лодкой (визуал)
ctx.fillStyle='rgba(0,20,40,0.28)';
ctx.beginPath(); ctx.ellipse(bx,by+17,34,4.5,0,0,7); ctx.fill();
// лодка (Этап 4: скины — градиент корпуса и кромка по save.boatSkin)
const skin=Math.max(0,Math.min(2,save.boatSkin|0));
const bcols=[['#c9773c','#96521f','#8a4519'],['#c0392b','#7b241c','#6e221a'],['#5d6d7e','#34495e','#2c3a47']][skin];
const bg=ctx.createLinearGradient(bx-32,by,bx+32,by+15);
bg.addColorStop(0,bcols[0]); bg.addColorStop(1,bcols[1]);
ctx.fillStyle=bg;
ctx.beginPath();
ctx.moveTo(bx-32,by); ctx.lineTo(bx+32,by); ctx.lineTo(bx+21,by+15); ctx.lineTo(bx-21,by+15);
ctx.closePath(); ctx.fill();
ctx.fillStyle=bcols[2]; ctx.fillRect(bx-32,by,64,4);
// «Лодка-домик»: каюта на корме корпуса (над линией борта) с ярко-жёлтым окном (визуал)
if(skin===2){
ctx.fillStyle='#2c3a47';
ctx.fillRect(bx-31,by-11,16,11);
ctx.fillStyle='rgba(255,220,100,0.9)';
ctx.fillRect(bx-28,by-9,9,5);
}
// рыбак
ctx.fillStyle='#34495e';
ctx.fillRect(bx-9,by-18,12,12);
ctx.fillStyle='#e8b88a';
ctx.beginPath(); ctx.arc(bx-3,by-24,6.5,0,7); ctx.fill();
ctx.fillStyle='#c0392b';
ctx.beginPath(); ctx.arc(bx-3,by-27,6.5,Math.PI,0); ctx.fill();
// удочка
const swing=state==='CHARGE'?-power*0.35:0;
ctx.strokeStyle='#5d4023'; ctx.lineWidth=3; ctx.lineCap='round';
ctx.beginPath(); ctx.moveTo(bx+2,by-14);
const tx=bx+34+swing*20, ty=by-38-swing*14;
ctx.lineTo(tx,ty); ctx.stroke();
tip={x:tx,y:ty};
// флажок
ctx.strokeStyle='#5d4023'; ctx.lineWidth=2;
ctx.beginPath(); ctx.moveTo(bx-24,by); ctx.lineTo(bx-24,by-22); ctx.stroke();
ctx.fillStyle='#f5a623';
const fl=Math.sin(time*4)*1.5; // флажок колышется (визуал)
ctx.beginPath(); ctx.moveTo(bx-24,by-22); ctx.lineTo(bx-12,by-18+fl); ctx.lineTo(bx-24,by-14); ctx.closePath(); ctx.fill();
// фонарь на носу ночью (визуал: тёплое пятно света)
if(nightMix()>0.35){
const a=(nightMix()-0.35)/0.65;
const lx=bx-24,ly=by-20;
const lg=ctx.createRadialGradient(lx,ly,2,lx,ly,46);
lg.addColorStop(0,'rgba(255,214,120,'+(0.4*a).toFixed(3)+')');
lg.addColorStop(1,'rgba(255,214,120,0)');
ctx.fillStyle=lg; ctx.fillRect(lx-46,ly-46,92,92);
ctx.fillStyle='rgba(255,224,150,'+(0.9*a).toFixed(3)+')';
ctx.beginPath(); ctx.arc(lx,ly,2.5,0,7); ctx.fill();
}
}
function drawLineTo(x,y,sag){
ctx.strokeStyle='rgba(230,240,255,0.8)'; ctx.lineWidth=1.2;
ctx.beginPath(); ctx.moveTo(tip.x,tip.y);
ctx.quadraticCurveTo((tip.x+x)/2,(tip.y+y)/2+sag,x,y);
ctx.stroke();
}
function drawBobber(sink){
const x=bobber.x,y=bobber.y;
// тёмная кромка воды под поплавком (визуал)
ctx.fillStyle='rgba(0,20,40,0.25)';
ctx.beginPath(); ctx.ellipse(x,y+6,7,1.8,0,0,7); ctx.fill();
// Этап 4: скины — поплавок по save.bobberSkin (0 обычный, 1 красный, 2 неоновый)
const skin=Math.max(0,Math.min(2,save.bobberSkin|0));
const bot=['#fff','#e74c3c','#aaff00'][skin];
const top=['#e74c3c','#e74c3c','#aaff00'][skin];
if(skin===2){ ctx.save(); ctx.shadowColor='rgba(170,255,0,0.8)'; ctx.shadowBlur=10; } // неоновое свечение — обязательно save/restore, чтобы не перетечь на другие элементы
ctx.fillStyle=bot;
ctx.beginPath(); ctx.arc(x,y,5.5,0,7); ctx.fill();
ctx.fillStyle=top;
ctx.beginPath(); ctx.arc(x,y,5.5,Math.PI,0); ctx.fill();
// блик (визуал)
ctx.fillStyle='rgba(255,255,255,0.85)';
ctx.beginPath(); ctx.arc(x-1.8,y-1.8,1.4,0,7); ctx.fill();
ctx.strokeStyle=skin===2?'#77cc00':'rgba(255,255,255,0.9)'; ctx.lineWidth=1.5;
ctx.beginPath(); ctx.arc(x,y,5.5,0,7); ctx.stroke();
if(skin===2) ctx.restore();
// топление (визуал, lane 2): в BITE нижняя половина уходит под воду — полупрозрачная кромка воды поверх низа поплавка
// рисуем ВНЕ save/restore неона, чтобы свечение не перетекло на слой воды
if(sink){
ctx.fillStyle='rgba(10,30,60,0.35)';
ctx.beginPath(); ctx.arc(x,y,5.6,0,Math.PI); ctx.closePath(); ctx.fill(); // нижняя половина под водой
ctx.strokeStyle='rgba(150,200,235,0.55)'; ctx.lineWidth=1; // тонкая светлая линия уровня воды
ctx.beginPath(); ctx.moveTo(x-5.6,y); ctx.lineTo(x+5.6,y); ctx.stroke();
}
}
function hookY(){
// глубина крючка на середине воды: доля глубины 0.42..0.54 по дальности заброса (визуал)
return waterY+(H-waterY)*(0.42+castDist*0.12);
}
function drawRig(){
// Живой оснастки (lane 1): поводок от поплавка вниз, крючок и наживка.
// Только визуал — механика/баланс не трогается. hookPos экспортируем для следующих шагов.
const hy=hookY(); // глубина крючка (середина воды, доля 0.42..0.54 по дальности)
const hx=bobber.x+Math.sin(time*2.2)*3; // лёгкое покачивание в противофазе к поплавку
hookPos={x:hx,y:hy};
// вертикальный бледный поводок (бледнее надводной лески 0.8 → 0.35)
ctx.strokeStyle='rgba(230,240,255,0.35)'; ctx.lineWidth=1;
ctx.beginPath(); ctx.moveTo(bobber.x,bobber.y); ctx.lineTo(hx,hy); ctx.stroke();
// крючок: дуга + жало (серый ~5px)
ctx.strokeStyle='#cfd6dd'; ctx.lineWidth=1.4; ctx.lineCap='round';
ctx.beginPath(); ctx.arc(hx,hy+4,4.5,Math.PI*0.1,Math.PI*1.6); ctx.stroke();
const eb=Math.PI*1.6, ex=hx+4.5*Math.cos(eb), ey=(hy+4)+4.5*Math.sin(eb);
ctx.beginPath(); ctx.moveTo(ex,ey); ctx.lineTo(ex+2.5,ey-2); ctx.stroke(); // жало
}
function drawLineAndBobber(){
// след поплавка: копим в забросе, чистим в остальных состояниях (визуал)
if(state==='CAST'){ bobberTrail.push({x:bobber.x,y:bobber.y}); if(bobberTrail.length>14) bobberTrail.shift(); }
else if(bobberTrail.length) bobberTrail.length=0;
if(state==='IDLE'||state==='CHARGE'||state==='MENU'||state==='CARD'){
// болтается грузило
const a=state==='CHARGE'?Math.sin(time*10)*power*4:Math.sin(time*1.2)*1.5;
ctx.strokeStyle='rgba(230,240,255,0.8)'; ctx.lineWidth=1.2;
ctx.beginPath(); ctx.moveTo(tip.x,tip.y); ctx.lineTo(tip.x+a,tip.y+22); ctx.stroke();
ctx.fillStyle='#e74c3c';
ctx.beginPath(); ctx.arc(tip.x+a,tip.y+25,3.5,0,7); ctx.fill();
return;
}
if(state==='SNAP'){
ctx.strokeStyle='rgba(230,240,255,0.8)'; ctx.lineWidth=1.2;
ctx.beginPath(); ctx.moveTo(tip.x,tip.y);
ctx.lineTo(tip.x+10+Math.sin(time*20)*6,tip.y+26); ctx.stroke();
ctx.globalAlpha=Math.min(1,snapT*2);
ctx.shadowColor='rgba(255,120,60,0.9)'; ctx.shadowBlur=14; // вспышка (визуал)
ctx.font='34px '+UI_FONT; ctx.textAlign='center';
ctx.fillText('💥',castTo.x,waterY-20);
ctx.shadowBlur=0;
ctx.globalAlpha=1;
return;
}
if(state==='CAST'){
// след: затухающие точки по траектории (визуал)
for(let i=0;i<bobberTrail.length;i++){
const tp=bobberTrail[i];
ctx.fillStyle='rgba(255,255,255,'+(i/bobberTrail.length*0.35).toFixed(3)+')';
ctx.beginPath(); ctx.arc(tp.x,tp.y,1.6,0,7); ctx.fill();
}
drawLineTo(bobber.x,bobber.y,14); drawBobber(); return;
}
let sag;
if(state==='REEL'){
sag=reel.holding?0:(reel.phase==='pull'?16:12); // holding — натянуто (прямая tip→поплавок); отпускание — провис (рывок больше)
}else{
sag=18+Math.sin(time*2)*3;
}
drawLineTo(bobber.x,bobber.y,sag);
drawBobber(state==='BITE'?1:0); // топление: в BITE нижняя половина под водой, в WAIT/APPROACH/REEL — нет
if(state==='REEL'&&reel){ // подводный сегмент лески bobber→рыба (бледнее надводной), чтобы леска шла к рыбе
const fp=fishReelPos();
ctx.strokeStyle='rgba(230,240,255,0.35)'; ctx.lineWidth=1;
ctx.beginPath(); ctx.moveTo(bobber.x,bobber.y); ctx.lineTo(fp.x,fp.y); ctx.stroke();
}
if(state==='WAIT'||state==='APPROACH'||state==='BITE') drawRig(); // живая оснастка (в REEL крючок «в рыбе» — не рисуем)
if(state==='BITE'){
const yy=bobber.y-24+Math.sin(time*12)*2;
ctx.font='800 28px '+UI_FONT; ctx.textAlign='center';
ctx.lineWidth=4; ctx.strokeStyle='#fff';
ctx.strokeText('!',bobber.x,yy);
ctx.fillStyle='#ff3b30';
ctx.fillText('!',bobber.x,yy);
}
}
function fishReelPos(){
// lane 3: позиция пойманной рыбы в REEL по прогрессу вываживания — по диагонали от глубины крючка (середина воды) к лодке у поверхности (d0>0 гарантировано)
const p=Math.max(0,Math.min(1,1-reel.d/reel.d0));
const pe=p*p*(3-2*p); // лёгкое ease — плавный подход к лодке
const k=reel.tired?0.35:1; // уставшая рыба вялая — амплитуда покачивания ниже
const hy=hookY(); // старт пути — точка крючка (середина воды)
const x=castTo.x+(boatX+24-castTo.x)*pe + Math.sin(time*7*k)*4*k; // сохраняем покачивание
const y=hy+(waterY+10-hy)*pe + Math.sin(time*5*k)*3*k; // диагональ: из глубины к лодке у поверхности
return {x:x,y:y};
}
/* Размер силуэта пойманной рыбы — от АБСОЛЮТНОГО веса (кг), не от wMin/wMax вида.
УЗЛОВАЯ ТАБЛИЦА (длина силуэта = 2.45·fs: тело 2·fs + хвост), узлы по степеням двойки:
0.1 кг → 12 px · 0.2 → 16 · 0.4 → 20 · 0.8 → 24 · 1.6 → 36 · 3.2 → 48 ·
6.4 → 64 (= лодка) · 12.8 → 80 · 25.6 → 96 · 51.2 → 160 · 100 → 256 px = 4× лодки 64 px.
Интерполяция линейна по log2(веса) — узлы степени двойки, кривая монотонна, узлы бьёт точно.
Веса <0.1 кг клампятся в 12 px, >100 кг — в 256 px. */
const FISH_SIZE_KNOTS=[[0,12],[1,16],[2,20],[3,24],[4,36],[5,48],[6,64],[7,80],[8,96],[9,160],[Math.log2(1000),256]]; // [log2(w/0.1), длина px]
function fishSizeFromW(w){
const t=Math.log2(Math.max(0.1,Math.min(100,w))/0.1);
for(let i=1;i<FISH_SIZE_KNOTS.length;i++){
const t0=FISH_SIZE_KNOTS[i-1][0],l0=FISH_SIZE_KNOTS[i-1][1],t1=FISH_SIZE_KNOTS[i][0],l1=FISH_SIZE_KNOTS[i][1];
if(t<=t1) return (l0+(l1-l0)*(t-t0)/(t1-t0))/2.45;
}
return 256/2.45;
}
function drawHookedFish(){
if(state!=='REEL'||!reel) return;
const sp=reel.sp;
const k=reel.tired?0.35:1; // Спринт 4: уставшая рыба вялая — медленнее и амплитуда ниже
const fp=fishReelPos();
const x=fp.x, y=fp.y;
const dir=Math.sin(time*2.5*k)>0?1:-1;
const fs=fishSizeFromW(reel.w); // размер = абсолютный вес (редкость и босс-×1.5 убраны: крупнее вес → крупнее рыба)
if(reel.boss){ // босс: золотая аура (визуал)
const gg=ctx.createRadialGradient(x,y,4,x,y,fs*2.6);
gg.addColorStop(0,'rgba(255,215,94,0.35)'); gg.addColorStop(1,'rgba(255,215,94,0)');
ctx.fillStyle=gg; ctx.fillRect(x-fs*2.6,y-fs*2.6,fs*5.2,fs*5.2);
}
fishGlow(sp,x,y,fs*1.5); // Фаза свечения: компактный ореол вида ночью (в save/restore — не ломает боссовую)
drawFishShape(x,y,fs,dir,sp.hue,sp.glow?1:0.75,Math.sin(time*9*k)*0.3*k); // светящийся вид — непрозрачный силуэт (крупнее у тяжёлых)
}
function drawParticles(){
for(const p of particles){
ctx.fillStyle='rgba('+p.color+','+(Math.max(0,p.life/p.max)).toFixed(3)+')';
ctx.beginPath(); ctx.arc(p.x,p.y,p.size,0,7); ctx.fill();
}
}
function drawRipples(){
for(const r of ripples){
ctx.strokeStyle='rgba(255,255,255,'+Math.max(0,r.a).toFixed(3)+')';
ctx.lineWidth=1.5;
ctx.beginPath(); ctx.ellipse(r.x,r.y,r.r,r.r*0.3,0,0,7); ctx.stroke();
}
}
// Э42: рыбка-маркер на канвасе (вместо эмодзи-рыбки — рыбные глифы убраны из субсета):
// тело-эллипс + треугольный хвост + глазок; s — «радиус» тела
function drawFishMark(x,y,s){
ctx.save();
ctx.fillStyle='rgba(230,244,252,0.95)';
ctx.beginPath(); ctx.ellipse(x-s*0.15,y,s,s*0.55,0,0,Math.PI*2); ctx.fill();
ctx.beginPath(); ctx.moveTo(x+s*0.55,y); ctx.lineTo(x+s*1.25,y-s*0.55); ctx.lineTo(x+s*1.25,y+s*0.55); ctx.closePath(); ctx.fill();
ctx.fillStyle='#17436b';
ctx.beginPath(); ctx.arc(x-s*0.55,y-s*0.12,Math.max(1,s*0.14),0,Math.PI*2); ctx.fill();
ctx.restore();
}
function drawMeters(){
if(state!=='REEL'||!reel) return;
const r=rod(), sp=reel.sp;
const pulling=reel.phase==='pull';
// M4: босс-бой — золотая полоса фазы над метрами (визуал: пульс + точки фаз)
if(reel.boss){
const pulse=1+Math.sin(time*5)*0.08;
ctx.textAlign='center';
ctx.font='800 '+(16*pulse).toFixed(1)+'px '+UI_FONT;
ctx.fillStyle='#ffd75e';
ctx.shadowColor='rgba(255,180,40,0.8)'; ctx.shadowBlur=10;
ctx.fillText(tt('boss_phase_draw',{p:bossPhase}),W/2,84);
ctx.shadowBlur=0;
for(let i=1;i<=3;i++){
ctx.beginPath();
ctx.arc(W/2-20+i*20,94,4,0,7);
ctx.fillStyle=i<=bossPhase?'#ffd75e':'rgba(255,255,255,0.25)';
ctx.fill();
}
}
// --- нагрузка (вертикально справа) ---
const bw=14, bh=H*0.36, bx=W-30, by=H*0.46-bh/2;
ctx.fillStyle='rgba(0,0,0,0.35)'; rr(bx,by,bw,bh,7); ctx.fill();
const ratio=Math.min(1,reel.tension/reel.line);
const col=ratio<0.5?'#2ecc71':ratio<0.8?'#f1c40f':'#e74c3c';
if(ratio>0.01){
ctx.fillStyle=col;
if(ratio>0.8){ ctx.shadowColor='rgba(231,76,60,0.85)'; ctx.shadowBlur=12; } // перегруз: тревожное свечение
const fh=bh*ratio;
rr(bx+2,by+bh-2-fh,bw-4,Math.max(2,fh-2),5); ctx.fill();
ctx.shadowBlur=0;
}
ctx.strokeStyle='rgba(255,255,255,0.6)'; ctx.lineWidth=1.5;
ctx.beginPath(); ctx.moveTo(bx-3,by); ctx.lineTo(bx+bw+3,by); ctx.stroke();
// Спринт 4: черта drag — выше неё при удержании леска скользит
const dgy=by+bh*(1-Math.min(1,r.drag/reel.line));
ctx.strokeStyle='rgba(255,255,255,0.9)'; ctx.lineWidth=2;
ctx.beginPath(); ctx.moveTo(bx-2,dgy); ctx.lineTo(bx+bw+2,dgy); ctx.stroke();
const Fm=fishForce(reel,reel.aggr,pulling);
const slipping=reel.holding&&Fm-r.drag>0;
ctx.font='16px '+UI_FONT; ctx.textAlign='center';
ctx.fillText(slipping?'🌀':pulling?'⚡':(reel.holding?'💪':'·'),bx+bw/2,by-8);
// --- дистанция (снизу) ---
const dw=W-96, dx=22, dy=H-52, dh=13;
ctx.fillStyle='rgba(0,0,0,0.35)'; rr(dx,dy,dw,dh,7); ctx.fill();
// rem = доля оставшейся дистанции: полоска «сгорает» к лодке, рыбка на её конце
const rem=Math.max(0,Math.min(1,reel.d/reel.d0));
if(rem>0.01){
const dg=ctx.createLinearGradient(dx,0,dx+dw,0);
dg.addColorStop(0,'#2e86c8'); dg.addColorStop(1,'#3fa7e8');
ctx.fillStyle=dg;
rr(dx+2,dy+2,Math.max(2,(dw-4)*rem),dh-4,5); ctx.fill();
}
// escape: красная заливка поверх синей, слева направо (рыба ускользает)
if(reel.escape>0.01){
const ew=(dw-4)*reel.escape;
ctx.fillStyle='rgba(231,76,60,0.7)';
rr(dx+2,dy+2,ew,dh-4,5); ctx.fill();
}
// рыбка-маркер на конце полоски (Э42: рисуется path-рыбкой, эмодзи убраны)
const fx=dx+2+(dw-4)*rem;
drawFishMark(fx,dy-6+Math.sin(time*10)*1.5,8);
ctx.font='18px '+UI_FONT; ctx.textAlign='center';
drawFishMark(dx+12,dy+dh+18,6.5);
ctx.fillText('⚡',dx+32,dy+dh+18);
// Спринт 4: выносливость — тонкая полоска под дистанцией (затухает к нулю)
// T2b: начинается после иконок дистанции/выносливости (dx+44), чтобы не перекрывать их
const sdh=5, sdy=dy+dh+3;
ctx.fillStyle='rgba(0,0,0,0.3)'; rr(dx+44,sdy,dw-44,sdh,2.5); ctx.fill();
if(reel.st>0.01){
ctx.fillStyle=reel.tired?'#7d5ba6':'#b07cc6';
rr(dx+45.5,sdy+1.5,Math.max(1.5,(dw-47)*reel.st),sdh-3,2); ctx.fill();
}
if(reel.tired){
ctx.font='13px '+UI_FONT; ctx.textAlign='left';
ctx.fillText('💤',dx+dw+6,sdy+sdh-1);
}
// статус
ctx.font='700 15px '+UI_FONT; ctx.textAlign='center';
if(pulling){
ctx.fillStyle='#ff6b5e';
ctx.shadowColor='rgba(255,60,40,'+(0.5+0.4*Math.sin(time*10)).toFixed(3)+')'; ctx.shadowBlur=8;
ctx.fillText(t('reel_pull'),W/2,dy-30);
ctx.shadowBlur=0;
}else if(reel.tired){
ctx.fillStyle='#c9a0f5';
ctx.shadowColor='rgba(120,60,180,0.6)'; ctx.shadowBlur=6;
ctx.fillText(t('reel_tired'),W/2,dy-30);
ctx.shadowBlur=0;
}else{
ctx.fillStyle='#7ef0a8';
ctx.shadowColor='rgba(0,0,0,0.6)'; ctx.shadowBlur=4;
ctx.fillText(t('reel_hold'),W/2,dy-30);
ctx.shadowBlur=0;
}
}
function drawPowerBar(){
if(state!=='CHARGE') return;
const w=W*0.7,h=16,x=(W-w)/2,y=H-64;
ctx.fillStyle='rgba(0,0,0,0.4)'; rr(x,y,w,h,8); ctx.fill();
const g=ctx.createLinearGradient(x,0,x+w,0);
g.addColorStop(0,'#2ecc71'); g.addColorStop(0.6,'#f1c40f'); g.addColorStop(1,'#e74c3c');
ctx.fillStyle=g;
if(power>0.01){
const fw=Math.max(2,(w-4)*power);
rr(x+2,y+2,fw,h-4,6); ctx.fill();
// бегунок на конце заливки (визуал)
ctx.fillStyle='rgba(255,255,255,0.9)';
ctx.beginPath(); ctx.arc(x+2+fw-3,y+h/2,4,0,7); ctx.fill();
}
ctx.font='700 14px '+UI_FONT; ctx.textAlign='center';
ctx.fillStyle='#fff';
ctx.shadowColor='rgba(0,0,0,0.65)'; ctx.shadowBlur=4;
ctx.fillText(t('cast_release'),W/2,y-10);
ctx.shadowBlur=0;
}
function drawHint(){
if(state!=='IDLE'||save.casts>=5) return;
const a=0.55+Math.sin(time*3)*0.25;
ctx.globalAlpha=a;
ctx.font='700 17px '+UI_FONT; ctx.textAlign='center';
ctx.fillStyle='#fff';
ctx.shadowColor='rgba(0,0,0,0.65)'; ctx.shadowBlur=5;
ctx.fillText(t('menu_charge_touch'),W/2,H-70); // Y5: i18n (текст тот же, что в меню — тач-ветка)
ctx.shadowBlur=0;
ctx.globalAlpha=1;
}
/* M8: погода — слой в КОНЦЕ draw-цикла: дождь — косые полоски поверх воды и неба,
туман — полупрозрачный слой поверх сцены (+2 полосы глубже для объёма).
HUD — DOM, canvas-слой его не скрывает; поплавок/кнопки под 0.28 тумана остаются читаемыми */
function drawWeather(){
const id=weatherActive();
if(!id) return;
if(id==='rain'){
ctx.strokeStyle='rgba(180,200,220,0.5)';
ctx.lineWidth=1.5;
ctx.beginPath();
for(const dr of rain){
ctx.moveTo(dr.x,dr.y);
ctx.lineTo(dr.x-6,dr.y+20);
}
ctx.stroke();
}else{
ctx.fillStyle='rgba(200,215,225,0.28)';
ctx.fillRect(-8,-8,W+16,H+16); // +8px по периметру: слой рисуется внутри shake-транса — без просвета фона при обрыве
// две полосы с разной прозрачностью и медленным дрейфом — глубина
const b1=((time*10)%(H+120))-120;
const b2=H-((time*6)%(H+160));
ctx.fillStyle='rgba(226,236,244,0.10)';
ctx.fillRect(0,b1,W,48);
ctx.fillStyle='rgba(226,236,244,0.07)';
ctx.fillRect(0,b2,W,70);
}
}
function draw(){
ctx.clearRect(0,0,W,H);
ctx.save();
if(shake>0){
ctx.translate(rand(-1,1)*shake*8,rand(-1,1)*shake*8);
}
if(aqOpen){ drawAquarium(); ctx.restore(); return; } // Этап 46: сцена аквариума вместо озера
drawSky();
drawScenery(); // Этап 44: береговые силуэты (перед водой — базу закрывает градиент)
drawWater();
drawAmbientFish();
drawSwampDecor(); // Этап 45: кувшинки/лилии/лягушки Болота — поверх воды, до лодки
if(biteFish&&biteFish.mode!=='out'){
const bs=12+biteFish.sp.rarity*2.5; // размер силуэта зацепившейся рыбы
if(state==='BITE'){
// топление (lane 2): рыба дёргается у крючка, синхронно с фазами топления поплавка (time*22)
const bx=hookPos.x+Math.sin(time*25)*7, by=hookPos.y+Math.cos(time*22)*5;
fishGlow(biteFish.sp,bx,by,bs*1.5); // Фаза свечения: компактный ореол вида ночью
drawFishShape(bx,by,bs, Math.sin(time*25)>0?1:-1, biteFish.sp.hue, biteFish.sp.glow?1:0.8, Math.sin(time*8)*0.25);
}else{
// APPROACH: подплывает к поплавку как раньше
fishGlow(biteFish.sp,biteFish.x,biteFish.y,bs*1.5);
drawFishShape(biteFish.x,biteFish.y,bs,biteFish.dir,biteFish.sp.hue,biteFish.sp.glow?1:0.8,Math.sin(time*8)*0.25);
}
}
else if(biteFish&&biteFish.mode==='out'){ // рыба ушла — светящийся силуэт гаснет, но аура ещё видна
const bs=12+biteFish.sp.rarity*2.5;
fishGlow(biteFish.sp,biteFish.x,biteFish.y,bs*1.5);
drawFishShape(biteFish.x,biteFish.y,bs,biteFish.dir,biteFish.sp.hue,biteFish.sp.glow?0.85:0.5,Math.sin(time*8)*0.25);
}
drawBoat();
drawLineAndBobber();
drawHookedFish();
drawRipples();
drawParticles();
drawMeters();
drawPowerBar();
drawHint();
drawWeather(); // M8: погодный слой — в конце draw-цикла
ctx.restore();
}
/* =========================================================
АКВАРИУМ (Этап 46)
Декоративная сцена коллекции ЭКЗЕМПЛЯРОВ (вид+вариант+вес), не вода:
в LOCATIONS не добавляется, роллы/боссы/баланс не трогаются. Сцена рисуется
в draw() ВМЕСТО озера при aqOpen; DOM-бар #aqBar и поповер #aqPop — поверх
canvas. Вход — из хаба «Меню» (#btnGmAquarium). Экземпляры копятся кнопкой
«В аквариум» на карточке улова (модель C — бесплатная копия, catchFish не
меняется). Рантайм-раскладка aqFishRt НЕ персистится (индекс = save.aqFish).
========================================================= */
let aqOpen=false; // сцена активна (draw() рисует банку вместо озера)
let aqFishRt=[]; // рантайм: {x,y,dir,ph,spd,vy,tail} по индексу save.aqFish — НЕ в сейве
let aqSel=-1; // выбранный экземпляр (-1 — ничего)
let aqFromMenu=false; // вход был из хаба «Меню» (аналог shopFromMenu): «Назад» вернёт в #gamemenu
let aqTank={x:0,y:0,w:0,h:0,sandY:0}; // геометрия банки (пересобирается в initAquarium)
let aqPlants=[], aqBubbles=[]; // декор сцены (растения/пузыри) — тоже не в сейве
let aqFishEls=[]; // DOM-элементы жильцов (#aqFishLayer) — те же SVG-портреты, что на карточке; индекс = save.aqFish
/* Вариантное оформление жильца — ровно как на карточке улова: перекраска тела/плавников
(--f1/--f3, наследуется сквозь <use> в спрайт) для copper/gold/quartz/emerald/diamond,
плюс класс .var<id> по варианту — CSS в #aqFishLayer добавляет цветной drop-shadow
(silver — grayscale+brightness, rainbow — вращение оттенка). normal — без эффекта,
как и на карточке. */
const AQ_VARIANT_RECOLOR={
copper:{f1:'hsl(25,55%,55%)',f3:'hsl(25,50%,35%)'},
gold:{f1:'#ffd75e',f3:'hsl(45,70%,40%)'},
quartz:{f1:'hsl(270,25%,72%)',f3:'hsl(270,25%,45%)'},
emerald:{f1:'hsl(150,55%,42%)',f3:'hsl(150,50%,28%)'},
diamond:{f1:'hsl(200,60%,78%)',f3:'hsl(200,50%,45%)'}
};
/* CSS-классы оформления варианта в банке — те же имена, что у карточки (var<id>),
кроме normal (на карточке normal тоже без оформления) */
const AQ_VARIANT_CLASS=['copper','silver','quartz','gold','emerald','diamond','rainbow'];
function aqApplyVariant(el,variant){
const r=AQ_VARIANT_RECOLOR[variant.id];
if(r){ el.style.setProperty('--f1',r.f1); el.style.setProperty('--f3',r.f3); }
else{ el.style.removeProperty('--f1'); el.style.removeProperty('--f3'); }
for(const id of AQ_VARIANT_CLASS) el.classList.toggle('var'+id,variant.id===id);
}
/* Размер силуэта в банке: от веса к пределу вида (w/wMax) и редкости; кламп — чтобы влезал */
function aqFishSize(sp,w){
const rel=sp.wMax>0?Math.min(1,Math.max(0,w/sp.wMax)):0.4;
const s=8+rel*22+sp.rarity*1.6;
return Math.max(7,Math.min(Math.min(W,H)*0.11,s));
}
/* Позиция жильца в DOM: та же система координат, что у canvas (W/H — CSS-px), элемент
центрируется на (x,y) и зеркалится по направлению. Вызывается каждый кадр из updateAquarium. */
function aqPlaceFish(el,rt){
if(!el||!rt) return;
el.style.transform='translate('+rt.x.toFixed(1)+'px,'+rt.y.toFixed(1)+'px) translate(-50%,-50%)'
+' rotate('+(Math.sin(rt.tail||0)*4).toFixed(2)+'deg) scale('+rt.dir+',1)';
}
/* DOM-элемент жильца: <div class=aqfish><svg viewBox=0 0 160 100><use href="#fish-<id>"/></svg></div>.
Те же SVG-портреты и вариантное оформление, что на карточке улова (Э42 + ревизия). Размер —
aqFishSize (прежняя шкала): длина 2·size, высота по соотношению 160:100. */
function aqBuildFishEl(i){
const f=save.aqFish[i];
const sp=SPECIES.find(s=>s.id===f.id); if(!sp) return null;
const variant=VARIANTS.find(v=>v.id===f.v)||VARIANTS[0];
const size=aqFishSize(sp,f.w);
const el=document.createElement('div');
el.className='aqfish'; el.dataset.i=i;
el.style.width=(size*2).toFixed(1)+'px';
el.style.height=(size*1.25).toFixed(1)+'px';
const svg=document.createElementNS('http://www.w3.org/2000/svg','svg');
svg.setAttribute('viewBox','0 0 160 100');
const use=document.createElementNS('http://www.w3.org/2000/svg','use');
use.setAttribute('href','#fish-'+sp.id);
svg.appendChild(use); el.appendChild(svg);
aqApplyVariant(el,variant);
aqPlaceFish(el,aqFishRt[i]);
return el;
}
/* Раскладка банки и экземпляров по текущим W/H; вызывается при входе и на resize */
function initAquarium(){
aqTank.x=14; aqTank.y=14;
aqTank.w=Math.max(160,W-28); aqTank.h=Math.max(160,H-28);
aqTank.sandY=aqTank.y+aqTank.h*0.80;
const topPad=aqTank.y+54; // запас под DOM-бар #aqBar (пилюли лежат поверх верхней кромки банки)
const n=save.aqFish.length;
aqFishRt=[];
// Сетка по ширине/высоте — рыбы стартуют вразброс, не друг на друге
const cols=Math.max(1,Math.ceil(Math.sqrt(n)));
const rows=Math.max(1,Math.ceil(n/cols));
for(let i=0;i<n;i++){
const cr=Math.floor(i/cols), cc=i%cols;
const cw=(aqTank.w-70)/cols, ch=Math.max(24,(aqTank.sandY-topPad-16)/rows);
aqFishRt.push({
x:aqTank.x+40+cc*cw+rand(0,Math.max(1,cw*0.5)),
y:topPad+cr*ch+rand(0,Math.max(1,ch*0.6)),
dir:Math.random()<0.5?1:-1, ph:rand(0,6.28), tail:rand(0,6.28),
spd:rand(12,26), vy:rand(5,12)
});
}
// Рыбы-жильцы — DOM-слой тех же SVG-портретов (по индексу save.aqFish); слой обрезан по банке
const layer=$('aqFishLayer');
layer.innerHTML='';
layer.style.clipPath='inset('+aqTank.y+'px '+(W-aqTank.x-aqTank.w).toFixed(1)+'px '
+(H-aqTank.y-aqTank.h).toFixed(1)+'px '+aqTank.x+'px round 18px)';
aqFishEls=[];
for(let i=0;i<n;i++){
const el=aqBuildFishEl(i); // индекс массива = индекс save.aqFish (даже если вид битый → null)
aqFishEls[i]=el;
if(el) layer.appendChild(el);
}
aqPlants=[];
const np=5+((Math.random()*4)|0);
for(let k=0;k<np;k++) aqPlants.push({
x:rand(aqTank.x+18,aqTank.x+aqTank.w-18),
h:rand(28,Math.min(110,aqTank.h*0.5)), w:rand(3,7), ph:rand(0,6.28),
c:['#2f7a4a','#3f8f57','#256b41'][(Math.random()*3)|0]
});
aqBubbles=[];
for(let k=0;k<16;k++) aqBubbles.push({
x:rand(aqTank.x+14,aqTank.x+aqTank.w-14), y:rand(aqTank.y+20,aqTank.sandY),
r:rand(1.5,3.5), v:rand(16,34), ph:rand(0,6.28)
});
aqSel=-1;
renderAqBar();
}
/* Плавание: движение по горизонтали, разворот у стенок, вертикальный дрейф, анимация хвоста */
function updateAquarium(dt){
const left=aqTank.x+14, right=aqTank.x+aqTank.w-14;
const top=aqTank.y+52, bot=aqTank.sandY-8; // top — ниже DOM-бара #aqBar
for(const f of aqFishRt){
f.x+=f.dir*f.spd*dt;
f.y+=Math.sin(time*0.8+f.ph)*f.vy*dt;
f.tail+=dt*7;
if(f.dir>0&&f.x>right) f.dir=-1;
if(f.dir<0&&f.x<left) f.dir=1;
if(f.y<top) f.y=top;
if(f.y>bot) f.y=bot;
}
for(let i=0;i<aqFishRt.length;i++) aqPlaceFish(aqFishEls[i],aqFishRt[i]); // синхронизируем DOM-портреты
for(const b of aqBubbles){
b.y-=b.v*dt; b.ph+=dt*2;
if(b.y<aqTank.y+10){ b.y=aqTank.sandY-4; b.x=rand(left,right); }
}
}
/* Отрисовка банки: вода/стекло (hexLerp к nightMix — общий цикл суток), грунт, растения,
пузыри, аура болотных и рамка выбора. Сами рыбы-жильцы — DOM-слой #aqFishLayer
(SVG-портреты, как на карточке улова) поверх canvas. */
function drawAquarium(){
const nm=nightMix();
const x=aqTank.x, y=aqTank.y, w=aqTank.w, h=aqTank.h;
// фон комнаты за стеклом
ctx.fillStyle='#050b14'; ctx.fillRect(0,0,W,H);
ctx.save();
rr(x,y,w,h,18); ctx.clip();
// вода: день ↔ ночь
const g=ctx.createLinearGradient(0,y,0,y+h);
g.addColorStop(0,hexLerp('#a9e4ff','#123a5c',nm));
g.addColorStop(1,hexLerp('#2f8fc4','#06172b',nm));
ctx.fillStyle=g; ctx.fillRect(x,y,w,h);
// косые лучи света (визуал)
ctx.globalAlpha=0.05+0.06*(1-nm); ctx.fillStyle='#ffffff';
for(let k=0;k<4;k++){
const bx0=x+w*(0.08+k*0.24);
ctx.beginPath();
ctx.moveTo(bx0,y); ctx.lineTo(bx0+w*0.05,y);
ctx.lineTo(bx0-w*0.03,y+h); ctx.lineTo(bx0-w*0.08,y+h);
ctx.closePath(); ctx.fill();
}
ctx.globalAlpha=1;
// грунт (волнистая кромка песка)
ctx.fillStyle=hexLerp('#e8d6a6','#4b4233',nm*0.75);
ctx.beginPath();
ctx.moveTo(x,aqTank.sandY);
for(let px=x;px<=x+w;px+=24) ctx.lineTo(px,aqTank.sandY+Math.sin(px*0.05)*4);
ctx.lineTo(x+w,y+h); ctx.lineTo(x,y+h); ctx.closePath(); ctx.fill();
ctx.strokeStyle=hexLerp('#b9a06b','#33291d',nm*0.75); ctx.lineWidth=2;
ctx.beginPath();
for(let px=x;px<=x+w;px+=24){ const py=aqTank.sandY+Math.sin(px*0.05)*4; if(px===x)ctx.moveTo(px,py); else ctx.lineTo(px,py); }
ctx.stroke();
// растения (пучок из 3 тростинок, качается; лист у средней — читаемость на телефоне)
for(const pl of aqPlants){
const col=hexLerp(pl.c,'#0a1a12',nm*0.45);
ctx.strokeStyle=col; ctx.fillStyle=col; ctx.lineCap='round';
for(let b=-1;b<=1;b++){
const sway=Math.sin(time*1.1+pl.ph+b*0.6)*pl.h*0.08;
const bx=pl.x+b*pl.w*1.4;
ctx.lineWidth=pl.w*(b===0?1:0.7);
ctx.beginPath();
ctx.moveTo(bx,aqTank.sandY+4);
ctx.quadraticCurveTo(bx+pl.w*1.5,aqTank.sandY-pl.h*0.55,bx+sway,aqTank.sandY-pl.h*(b===0?1:0.78));
ctx.stroke();
}
ctx.beginPath();
ctx.ellipse(pl.x+pl.w*2.4,aqTank.sandY-pl.h*0.52,pl.w*1.7,pl.w*0.8,-0.5,0,7);
ctx.fill();
}
// пузыри
ctx.strokeStyle='rgba(255,255,255,'+(0.25+0.25*(1-nm)).toFixed(3)+')'; ctx.lineWidth=1.2;
for(const b of aqBubbles){
ctx.beginPath(); ctx.arc(b.x+Math.sin(b.ph)*3,b.y,b.r,0,7); ctx.stroke();
}
// рыбы-жильцы: сами портреты — DOM-слой #aqFishLayer (те же SVG-спрайты и вариантное
// оформление, что на карточке улова); на canvas — только ореол свечения болотных
// (уходит ЗА портрет) и рамка выбора
for(let i=0;i<aqFishRt.length;i++){
const f=save.aqFish[i], rt=aqFishRt[i];
if(!f||!rt) continue;
const sp=SPECIES.find(s=>s.id===f.id); if(!sp) continue;
const size=aqFishSize(sp,f.w);
if(sp.glow) drawGlowAura(rt.x,rt.y,size*1.5,sp.glow,glowIntensity()); // болотные — свечение вида
if(aqSel===i){ // рамка выбранной рыбы
ctx.strokeStyle='#c8fff4'; ctx.lineWidth=2;
ctx.beginPath(); ctx.ellipse(rt.x,rt.y,size*1.25,size*0.85,0,0,7); ctx.stroke();
}
}
ctx.restore();
// стекло: рамка + вертикальный блик
ctx.save();
rr(x,y,w,h,18); ctx.clip();
ctx.globalAlpha=0.10; ctx.fillStyle='#fff';
ctx.beginPath();
ctx.moveTo(x+w*0.06,y); ctx.lineTo(x+w*0.16,y);
ctx.lineTo(x+w*0.04,y+h); ctx.lineTo(x-w*0.02,y+h);
ctx.closePath(); ctx.fill();
ctx.restore();
ctx.strokeStyle='rgba(200,255,244,.55)'; ctx.lineWidth=3; rr(x,y,w,h,18); ctx.stroke();
ctx.strokeStyle='rgba(255,255,255,.10)'; ctx.lineWidth=1; rr(x+4,y+4,w-8,h-8,15); ctx.stroke();
}
/* Тап по сцене: ближайшая рыба в радиусе → выделение + поповер; тап в пустоту — снять выбор */
function aqTap(x,y){
let best=-1, bd=Infinity;
for(let i=0;i<aqFishRt.length;i++){
const rt=aqFishRt[i], f=save.aqFish[i];
if(!f) continue;
const sp=SPECIES.find(s=>s.id===f.id); if(!sp) continue;
const r=aqFishSize(sp,f.w)*1.2+10;
const d=(rt.x-x)*(rt.x-x)+(rt.y-y)*(rt.y-y);
if(d<r*r&&d<bd){ bd=d; best=i; }
}
if(best>=0){ aqSel=best; showAqPop(); }
else{ aqSel=-1; hideAqPop(); }
renderAqBar();
}
function showAqPop(){
const f=save.aqFish[aqSel]; if(!f){ hideAqPop(); return; }
const sp=SPECIES.find(s=>s.id===f.id); if(!sp){ hideAqPop(); return; }
const variant=VARIANTS.find(v=>v.id===f.v)||VARIANTS[0];
$('aqPopName').textContent=trName(sp)+(variant.id!=='normal'?' · '+trName(variant):'');
$('aqPopSub').textContent=f.w.toFixed(1)+' '+t('kg')+' · '+trRarity(sp.rarity); // Этап 46: без цены — выпуск бесплатный
$('btnAqRelease').textContent=t('aq_release');
$('aqPop').classList.remove('hidden');
}
function hideAqPop(){ $('aqPop').classList.add('hidden'); }
/* Бар аквариума: счётчик слотов + кнопка покупки (цена = AQ_SLOT_COSTS[aqSlots-AQ_BASE_SLOTS]) */
function renderAqBar(){
$('aqBar').title=t('aq_title');
$('btnAqBack').textContent=t('aq_back');
$('aqCount').textContent=tt('aq_slots',{n:save.aqFish.length,m:save.aqSlots});
const btn=$('btnAqSlot'), maxed=save.aqSlots>=AQ_MAX_SLOTS;
btn.disabled=maxed;
btn.textContent=maxed?t('aq_max'):tt('aq_buy_slot',{n:AQ_SLOT_COSTS[save.aqSlots-AQ_BASE_SLOTS]});
if(aqSel>=0&&aqSel<save.aqFish.length) showAqPop(); else hideAqPop();
}
/* Выпуск выбранного экземпляра из банки (Этап 46, ревизия: чистая косметика — без монет).
Точечно удаляем запись и её рантайм-раскладку ИНДЕКСАМИ, позиции остальных рыб сохраняем
(никакого initAquarium — иначе остальные «телепортируются»). Слот просто освобождается. */
function aqReleaseSel(){
if(aqSel<0||aqSel>=save.aqFish.length) return;
save.aqFish.splice(aqSel,1);
aqFishRt.splice(aqSel,1);
const el=aqFishEls[aqSel]; if(el) el.remove(); // портрет (DOM) уносим точечно — остальных не трогаем
aqFishEls.splice(aqSel,1);
aqSel=-1;
hideAqPop();
persist();
toast(t('aq_released'));
renderAqBar();
}
/* Вход/выход: из хаба «Меню» (аналог fromMenuShop) — гменю прячем, «Назад» возвращает в него */
function openAquarium(){
sfx('click');
aqFromMenu=true;
$('gamemenu').classList.add('hidden');
aqOpen=true; uiOpen=true;
YG.gameplayStop(); // сцена — не геймплей (паттерн лавки/паузы)
initAquarium();
$('aqBar').classList.remove('hidden');
document.body.classList.add('aq-open'); // HUD (#coins/#btnShop/#weather) скрыт под сценой
syncDom(); // под оверлеем-сценой #btnPause/#btnRecall не показываем
}
function closeAquarium(){
sfx('click');
aqOpen=false; aqSel=-1;
$('aqBar').classList.add('hidden');
document.body.classList.remove('aq-open'); // HUD возвращаем
hideAqPop();
if(aqFromMenu){ $('gamemenu').classList.remove('hidden'); uiOpen=true; }
aqFromMenu=false;
}
/* =========================================================
Y1: SDK Яндекс Игр
Обёртка YG — единственная точка SDK. Стаб (file:// без ?sdk=1) —
no-op + счётчики для тестов. SDK подгружается динамически ТОЛЬКО
по http(s) (или file://?sdk=1): при чистом file:// скрипт не
создаётся вообще (иначе 404/ERR_FILE_NOT_FOUND в консоли).
file://?sdk=1 — относительный sdk.js: работает, если лежит рядом
с index.html.
========================================================= */
const YG={
sdk:null, active:false, // ysdk или null (стаб)
paused:false, // глобальная пауза: реклама / скрытая вкладка / платформа
readySent:false,
counts:{ready:0,start:0,stop:0,fsAdv:0,rv:0}, // счётчики вызовов (для тестов)
adWatchdog:null, // Y2: watchdog — SDK не закрыл рекламу (нет onClose/onError) → снять паузу
_sdkReady(){ if(this.sdk){ try{ this.sdk.features.LoadingAPI&&this.sdk.features.LoadingAPI.ready&&this.sdk.features.LoadingAPI.ready(); }catch(e){} } },
init(ysdk){
if(this.active) return; // однократно (апгрейд стаб(null) → реальный SDK позже — разрешён)
this.sdk=ysdk||null; this.active=!!ysdk;
if(ysdk){
try{
const p=()=>this.onPause(), r=()=>this.onResume();
ysdk.on('game_api_pause',p);
ysdk.on('game_api_resume',r);
}catch(e){}
}
if(this.readySent) this._sdkReady(); // SDK доинициализировался после ready()
},
ready(){ this.readySent=true; this.counts.ready++; this._sdkReady(); },
gameplayStart(){ this.counts.start++; if(this.sdk){ try{ this.sdk.features.GameplayAPI&&this.sdk.features.GameplayAPI.start&&this.sdk.features.GameplayAPI.start(); }catch(e){} } },
gameplayStop(){ this.counts.stop++; if(this.sdk){ try{ this.sdk.features.GameplayAPI&&this.sdk.features.GameplayAPI.stop&&this.sdk.features.GameplayAPI.stop(); }catch(e){} } },
onPause(){
if(this.paused) return;
this.paused=true;
this.gameplayStop();
if(AC){ try{ AC.suspend(); }catch(e){} }
},
onResume(){
if(!this.paused) return;
// резюме не снимается, пока открыта реклама — снимет endAd()
// (пути сюда: visibilitychange / game_api_resume, а оверлей рекламы ещё открыт)
if(adShowing) return;
// Y6: резюме не снимается, пока открыт оверлей паузы — снимут только
// closePause()/кнопка «В меню» (пути сюда: blur/focus/visibilitychange
// во время открытой паузы)
if(pauseOpen) return;
this.paused=false;
last=performance.now();
if(state!=='MENU'&&!uiOpen) this.gameplayStart();
},
// Y2: реклама — ТОЛЬКО через SDK Яндекса (треб. 4.1). Стаб: fullscreen —
// no-op (вернёт false — реклама не показана), rewarded — симуляция успешного
// просмотра (локальная разработка, all-в-одном-клике флоу).
// Y2: watchdog — если SDK не доставит onClose/onError (баг SDK, убитый iframe),
// паузу снимаем сами, иначе игра замрзнет навсегда (треб. 1.14)
_startAdWatchdog(){
clearTimeout(this.adWatchdog);
this.adWatchdog=setTimeout(()=>{ if(adShowing){ console.warn('Yandex SDK: реклама не закрылась (90 с) — снимаю паузу'); endAd(); } },90000);
},
showFullscreen(cb){
this.counts.fsAdv++;
if(this.sdk){
try{ this.sdk.adv.showFullscreenAdv({callbacks:cb}); }catch(e){ return false; } // сбой SDK — как стаб: endAd() на месте вызова
this._startAdWatchdog();
return true;
}
return false; // стаб: реклама не показана
},
showRewarded(cb){
this.counts.rv++;
if(this.sdk){
try{ this.sdk.adv.showRewardedVideo({callbacks:cb}); }catch(e){ return false; }
this._startAdWatchdog(); // стаб-ветка ниже — флоу синхронный, watchdog не ставится
return true;
}
// стаб: симуляция успешного просмотра (локальная разработка)
try{ cb.onOpen&&cb.onOpen(); cb.onRewarded&&cb.onRewarded(); cb.onClose&&cb.onClose(true); }catch(e){}
return true;
},
};
// Y2: константы и состояние рекламы. Interstitial — на закрытии карточки улова
// (логическая пауза, треб. 4.4): первый показ не раньше AD_FIRST_MS сессии,
// дальше не чаще AD_COOLDOWN_MS. Rewarded «монеты ×2» — на самой карточке
// (треб. 4.5.1/4.5.2). Реклама не персистится (как погода).
const AD_FIRST_MS=120000; // первый interstitial не раньше 2 мин сессии
const AD_COOLDOWN_MS=180000; // между interstitial'ами — 3 мин
let sessionStartTs=Date.now(); // старт сессии (момент загрузки страницы)
let lastAdTs=0; // время запуска последнего interstitial
let adShowing=false; // реклама прямо сейчас (interstitial или rewarded)
let rvVal=0, rvDone=false; // rewarded: цена улова для бонуса ×2 и флаг «уже получен»
/* =========================================================
Y5: i18n RU/EN — автоопределение языка (треб. 2.14)
T — таблицы строк: ru — ТЕКУЩИЕ точные тексты, en — перевод.
Резолюция языка: forceLang (тест-форс) → SDK environment.i18n.lang
→ ru. Стаб (file:// без SDK) — ВСЕГДА ru. navigator.language
не используем осознанно (headless en-US сломал бы RU-тесты).
Блок стоит ДО IIFE-загрузки SDK: стаб-ветка сразу вызывает
resolveLang(null) → setLang → t(...), так что T должен быть
инициализирован до этой точки скрипта.
========================================================= */
const T={
ru:{
title:'Рыбалка',
menu_title:'🎣 РЫБАЛКА',
menu_charge_touch:'👆 Держи палец — заряжай бросок',
menu_charge_mouse:'🖱 Зажми кнопку мыши — заряжай бросок',
menu_throw:'<b>отпусти</b> — кидай удочку.<br>Дальше бросок = реже и жирнее рыба!',
menu_bite:'Видишь <b style="color:#ff6b5e">!</b> — быстро жми, чтобы зацепить.<br>При вываживании: тяни, когда рыба отдыхает,<br>отпусти, когда она <b>тянет</b> — иначе лопнет!<br>Не тяни слишком долго — рыба <b>сбегает</b> (красная полоса)!',
menu_weight:'У каждой рыбы свой <b>вес</b>, продажа — по цене за кг.<br>У удочек есть <b>предел веса</b>: перевесишь — шнур лопнет! <br>Лучшие снасти = больше шансов на трофей 🏆',
menu_drag:'Не каждый заброс — с клёвом: если молчит — подожди.<br>У удилищ есть <b>тормоз (drag)</b>: рывок сильнее — леска скользит!',
btn_play:'Играть',
shop_title:'🛒 Лавка рыбака',
sec_rods:'🎣 Удилища',
sec_lures:'🪱 Приманки',
sec_boat:'Лодка',
sec_bobber:'Поплавок',
sec_locations:'Локации',
sec_streak:'Стрик входа',
sec_quests:'Квесты дня',
sec_ach:'🏅 Достижения',
btn_select:'Выбрать',
btn_selected:'✓ Выбрано',
btn_selected_chk:'Выбрано ✓',
btn_selected_f:'Выбрана ✓',
btn_buy:'Купить',
btn_cancel:'Отмена',
btn_reset:'Сбросить',
btn_ok:'Отлично!',
free:'бесплатно',
lvl:'ур.',
kg:'кг',
per_kg:'🪙/кг',
price_label:'Цена: ',
locked_desc:'Откроется: улучши «{name}» до 4 ур.',
gate_toast:'Сначала улучши «{name}» до 4 ур.',
stats:'Бросков: {casts} · Заработано: {earned} 🪙',
not_caught:'не пойман',
max_w:'макс {w} кг',
card_sub:'{w} кг · {price} 🪙/кг',
card_record:'🏆 РЕКОРД!',
card_boss:'🏆 БОСС!',
card_boss_suffix:'-БОСС',
rv_btn:'📺 Реклама: ×2 за этот улов',
rv_done:'✓ Бонус получен',
boss_defeated:'🏆 БОСС ПОБЕЖДЁН! +{v} 🪙',
streak_day:'Стрик: день {d} — +{c} 🪙',
streak_line:'День {d} · далее +{n} 🪙',
quest_done:'Квест выполнен: {text} +{r} 🪙',
quests_done_today:'Квесты на сегодня закончились — заходи завтра!',
shield:'Щит спас стрик!',
bonus_coin:'+{v}% к монетам',
bonus_window:'+{v} с к подсечке',
bonus_line:'+{v} к прочности',
ach_toast:'🏅 Достижение: {name}',
bought:'Куплено: {name}!',
upgraded:'Улучшено: {name} → {lv} ур.!',
not_enough:'Не хватает монет 🪙',
welcome_lakes:'Добро пожаловать на Озёра!',
welcome_sea:'Добро пожаловать в Море!',
welcome_ocean:'Добро пожаловать в Океан!',
welcome_swamp:'Добро пожаловать в Волшебное болото! Здесь всё светится...',
location_set:'Локация: {name}',
progress_reset:'Прогресс сброшен 🔄',
night_light:'Ночью нужен фонарик — улучши удилище (первый апгрейд)',
escaped_bite:'Ушла… жми быстрее!',
snap_big:'💥 Рыба крупнее предела удочки!',
snap:'💥 Линия лопнула!',
escaped:'Сбежала!',
boss_phase:'⚠️ Босс рвёт леску! Фаза {p}/3',
boss_phase_draw:'⚠️ БОСС-РЫБА · ФАЗА {p}/3',
reel_pull:'⚡ РЫБА ТЯНЕТ — ОТПУСТИ! ⚡',
reel_tired:'💤 Рыба устала — втягивай!',
reel_hold:'Держи палец — втягивай!',
cast_release:'Отпусти — бросок!',
wx_clear:'☀️ Погода прояснила',
wx_rain:'Дождь: шанс особых рыб ×3',
wx_fog:'Туман: клёв чаще ×1,5',
sec_short:'с',
reset_title:'🗑️ Сбросить прогресс?',
reset_text:'Монеты, снасти и коллекция будут стёрты.<br>Это действие <b>нельзя отменить</b>.',
reset_title_attr:'Сбросить прогресс',
tab_tackle:'Лавка',
tab_journal:'Дневник',
tab_rewards:'Награды',
tab_ach:'Достижения',
tab_skins:'Скины',
tab_locations:'Локации',
pause_title:'⏸ Пауза',
pause_resume:'Продолжить',
pause_menu:'В меню',
btn_pause_title:'Пауза',
gm_title:'🎣 Меню',
gm_shop:'🛒 Магазин',
gm_ach:'🏅 Достижения',
gm_journal:'📔 Дневник',
gm_howto:'📖 Инструкции',
gm_sound:'Звук',
gm_reset:'🗑️ Очистить',
gm_aquarium:'🐠 Аквариум',
aq_title:'🐠 Аквариум',
aq_keep:'🐠 В аквариум',
aq_back:'← Назад',
aq_slots:'{n}/{m}',
aq_buy_slot:'+ Слот ({n} 🪙)',
aq_max:'+ Слот: максимум',
aq_release:'Выпустить',
aq_no_room:'Нет места',
aq_kept:'🐠 Рыба поселилась в аквариуме!',
aq_released:'Рыба выпущена'
},
en:{
title:'Fishing',
menu_title:'🎣 FISHING',
menu_charge_touch:'👆 Hold your finger — charge the cast',
menu_charge_mouse:'🖱 Hold the mouse button — charge the cast',
menu_throw:'<b>let go</b> — cast your rod.<br>Farther cast = rarer and bigger fish!',
menu_bite:'See the <b style="color:#ff6b5e">!</b> — hit it fast to hook the fish.<br>While reeling in: pull when the fish rests,<br>let go when it <b>pulls</b> — or the line snaps!<br>Do not hold too long — the fish <b>escapes</b> (red bar)!',
menu_weight:'Every fish has its own <b>weight</b>, sold by price per kg.<br>Rods have a <b>weight limit</b>: overload — the line snaps! <br>Better gear = better trophy chances 🏆',
menu_drag:'Not every cast gets a bite: if it is silent — wait.<br>Rods have a <b>drag</b>: a stronger jerk — the line slips!',
btn_play:'Play',
shop_title:"🛒 Angler's Shop",
sec_rods:'🎣 Rods',
sec_lures:'🪱 Lures',
sec_boat:'Boat',
sec_bobber:'Bobber',
sec_locations:'Locations',
sec_streak:'Daily Streak',
sec_quests:'Daily Quests',
sec_ach:'🏅 Achievements',
btn_select:'Select',
btn_selected:'✓ Selected',
btn_selected_chk:'Selected ✓',
btn_selected_f:'Selected ✓',
btn_buy:'Buy',
btn_cancel:'Cancel',
btn_reset:'Reset',
btn_ok:'Nice!',
free:'Free',
lvl:'lvl',
kg:'kg',
per_kg:'🪙/kg',
price_label:'Price: ',
locked_desc:'Unlocks: upgrade "{name}" to level 4',
gate_toast:'Upgrade "{name}" to level 4 first',
stats:'Casts: {casts} · Earned: {earned} 🪙',
not_caught:'not caught',
max_w:'max {w} kg',
card_sub:'{w} kg · {price} 🪙/kg',
card_record:'🏆 RECORD!',
card_boss:'🏆 BOSS!',
card_boss_suffix:'-BOSS',
rv_btn:'📺 Ad: ×2 for this catch',
rv_done:'✓ Bonus received',
boss_defeated:'🏆 BOSS DEFEATED! +{v} 🪙',
streak_day:'Streak: day {d} — +{c} 🪙',
streak_line:'Day {d} · next +{n} 🪙',
quest_done:'Quest done: {text} +{r} 🪙',
quests_done_today:"Today's quests are done — come back tomorrow!",
shield:'The shield saved your streak!',
bonus_coin:'+{v}% to coins',
bonus_window:'+{v}s hookset window',
bonus_line:'+{v} line strength',
ach_toast:'🏅 Achievement: {name}',
bought:'Bought: {name}!',
upgraded:'Upgraded: {name} → lvl {lv}!',
not_enough:'Not enough coins 🪙',
welcome_lakes:'Welcome to the Lakes!',
welcome_sea:'Welcome to the Sea!',
welcome_ocean:'Welcome to the Ocean!',
welcome_swamp:'Welcome to the Magic Swamp! Everything glows here...',
location_set:'Location: {name}',
progress_reset:'Progress reset 🔄',
night_light:'Night needs a flashlight — upgrade your rod (first upgrade)',
escaped_bite:'It got away… hit it faster!',
snap_big:'💥 Fish bigger than the rod limit!',
snap:'💥 Line snapped!',
escaped:'Escaped!',
boss_phase:'⚠️ The boss is tearing the line! Phase {p}/3',
boss_phase_draw:'⚠️ BOSS FISH · PHASE {p}/3',
reel_pull:'⚡ FISH PULLS — LET GO! ⚡',
reel_tired:'💤 Fish is tired — reel in!',
reel_hold:'Hold — reel in!',
cast_release:'Release — cast!',
wx_clear:'☀️ Weather cleared',
wx_rain:'Rain: special fish chance ×3',
wx_fog:'Fog: bites more often ×1.5',
sec_short:'s',
reset_title:'🗑️ Reset progress?',
reset_text:'Coins, gear and the collection will be erased.<br>This action <b>cannot be undone</b>.',
reset_title_attr:'Reset progress',
tab_tackle:'Shop',
tab_journal:'Journal',
tab_rewards:'Rewards',
tab_ach:'Achievements',
tab_skins:'Skins',
tab_locations:'Locations',
pause_title:'⏸ Pause',
pause_resume:'Resume',
pause_menu:'To menu',
btn_pause_title:'Pause',
gm_title:'🎣 Menu',
gm_shop:'🛒 Shop',
gm_ach:'🏅 Achievements',
gm_journal:'📔 Journal',
gm_howto:'📖 How to play',
gm_sound:'Sound',
gm_reset:'🗑️ Reset',
gm_aquarium:'🐠 Aquarium',
aq_title:'🐠 Aquarium',
aq_keep:'🐠 To aquarium',
aq_back:'← Back',
aq_slots:'{n}/{m}',
aq_buy_slot:'+ Slot ({n} 🪙)',
aq_max:'+ Slot: max',
aq_release:'Release',
aq_no_room:'No room',
aq_kept:'🐠 The fish moved into the aquarium!',
aq_released:'Fish released'
}
};
let LANG='ru';
let forceLang=null; // Y5: тест-глобал: 'ru'|'en'|null (приоритет в resolveLang)
function t(key){ const m=T[LANG]||{}; return (key in m)?m[key]:((T.ru&&T.ru[key]!==undefined)?T.ru[key]:key); }
function tt(key,o){ let s=t(key); if(o){for(const k in o)s=s.split('{'+k+'}').join(o[k]);} return s; }
function trName(x){ return (LANG==='en'&&x.nameEn)?x.nameEn:x.name; }
function trDesc(x){ return (LANG==='en'&&x.descEn)?x.descEn:x.desc; }
function trRarity(i){ return (LANG==='en')?RARITY_NAMES_EN[i]:RARITY_NAMES[i]; }
/* Y5: подпись следующего уровня снасти в лавке (RU/EN по языку) */
function upgNextText(type,lv){ return (LANG==='en')?((type==='rod'?ROD_UPG_NEXT_EN:LURE_UPG_NEXT_EN)[lv]):((type==='rod'?ROD_UPG_NEXT:LURE_UPG_NEXT)[lv]); }
/* Y5: безопасные проверки видимости оверлеев (для setLang) */
function shopOpenNow(){ const s=$('shop'); return !!(s&&!s.classList.contains('hidden')); }
function cardOpenNow(){ const c=$('card'); return !!(c&&!c.classList.contains('hidden')); }
const IS_TOUCH=('ontouchstart' in window)||(navigator.maxTouchPoints>0); // Y5: device-aware текст меню
/* Y5: меню — заполняется из T (ид btnPlay и класс big сохраняются; узлы НЕ пересоздаются —
обработчики слушателей живут) */
function renderMenu(){
$('menuTitle').textContent=t('menu_title');
$('menuP1').innerHTML=(IS_TOUCH?t('menu_charge_touch'):t('menu_charge_mouse'))+'<br>'+t('menu_throw');
$('menuP2').innerHTML=t('menu_bite');
$('menuP3').innerHTML=t('menu_weight');
$('menuP4').innerHTML=t('menu_drag');
$('btnPlay').textContent=t('btn_play');
}
/* Y5: статичные подписи вне shopBody (лавка/вкладки/сброс/карточка) — из T */
function renderStaticUI(){
$('shopTitle').textContent=t('shop_title');
$('coins').title=t('shop_title'); // клик по монетам → лавка
$('btnReset').title=t('reset_title_attr');
$('tabTackle').title=t('tab_tackle');
$('tabJournal').title=t('tab_journal');
$('tabRewards').title=t('tab_rewards');
$('tabAch').title=t('tab_ach');
$('tabSkins').title=t('tab_skins');
$('tabLocations').title=t('tab_locations');
$('resetTitle').textContent=t('reset_title');
$('resetText').innerHTML=t('reset_text');
$('btnResetNo').textContent=t('btn_cancel');
$('btnResetYes').textContent=t('btn_reset');
$('pauseTitle').textContent=t('pause_title');
$('btnPauseResume').textContent=t('pause_resume');
$('btnPauseMenu').textContent=t('pause_menu');
$('btnPause').title=t('btn_pause_title');
$('gmTitle').textContent=t('gm_title');
$('btnGmResume').textContent=t('pause_resume');
$('btnGmShop').textContent=t('gm_shop');
$('btnGmAch').textContent=t('gm_ach');
$('btnGmJournal').textContent=t('gm_journal');
$('btnGmHowto').textContent=t('gm_howto');
$('btnGmAquarium').textContent=t('gm_aquarium'); // Этап 46: вход в аквариум
$('btnReset').textContent=t('gm_reset');
$('btnMute').textContent=(save.muted?'🔇':'🔊')+' '+t('gm_sound');
$('cardRecord').textContent=t('card_record');
$('cardBoss').textContent=t('card_boss');
$('btnCardOk').textContent=t('btn_ok');
$('btnRv').textContent=t('rv_btn');
syncKeepBtn(); // Этап 46: подпись/доступность «В аквариум»
}
/* Y5: пере-подпись открытых элементов карточки улова при смене языка */
function refreshCardNow(){
$('cardRecord').textContent=t('card_record');
$('cardBoss').textContent=t('card_boss');
$('btnCardOk').textContent=t('btn_ok');
$('btnRv').textContent=rvDone?t('rv_done'):t('rv_btn');
syncKeepBtn(); // Этап 46
}
function setLang(lang){
LANG=(lang==='en')?'en':'ru';
document.documentElement.lang=LANG;
document.title=t('title');
renderMenu();
renderStaticUI();
updateHUD(); // 🔊/🔇 «Звук» — подпись от языка
if(shopOpenNow())renderShop();
if(cardOpenNow())refreshCardNow();
if(aqOpen)renderAqBar(); // Этап 46: язык открытой сцены аквариума
}
/* Y5: резолюция языка — ДВЕ ветки вызова (стаб IIFE / finish(ysdk)):
forceLang → SDK i18n.lang → ru (дефолт, в т.ч. стаб) */
function resolveLang(ysdk){
let lg=forceLang;
if(!lg&&ysdk&&ysdk.environment&&ysdk.environment.i18n&&ysdk.environment.i18n.lang)lg=ysdk.environment.i18n.lang;
setLang(lg||'ru');
}
// Y1: динамическая загрузка SDK (документированный Яндексом вариант):
// http(s) — /sdk.js, file://?sdk=1 — sdk.js рядом с index.html. Первый сбой
// — один ретраи, второй — стаб + warn. 3-секундный таймер не финализирует.
(function(){
const sdkEnabled=location.protocol!=='file:'||/[?&]sdk=1/.test(location.search);
if(!sdkEnabled){ YG.init(null); resolveLang(null); return; } // file:// без ?sdk=1 — сразу стаб (язык всегда ru, кроме forceLang), скрипт не создаётся
const finish=(ysdk)=>{ YG.init(ysdk||null); resolveLang(ysdk); }; // единая точка (защита в init: идемпотентно); Y5: язык из SDK i18n.lang
let attempt=0, settled=false, slowWarned=false;
const load=()=>{
attempt++;
const s=document.createElement('script');
s.src=location.protocol==='file:'?'sdk.js':'/sdk.js'; // file:// — относительный путь
s.async=true;
s.onload=()=>{
settled=true;
if(window.YaGames){ try{ YaGames.init().then(y=>finish(y)).catch(()=>finish(null)); }catch(e){ finish(null); } }
else finish(null);
};
s.onerror=()=>{
if(attempt<2){ load(); return; } // первый сбой — один ретраи (новый скрипт с тем же src)
settled=true;
finish(null);
console.warn('Yandex SDK: загрузка не удалась, игра в стаб-режиме');
};
document.head.appendChild(s);
};
load();
setTimeout(()=>{ // страховка: не финализирует, только одноразовый warn
if(!settled&&!slowWarned){ slowWarned=true; console.warn('Yandex SDK: загрузка дольше 3 с'); }
},3000);
})();
// Y1/Y6: потеря фокуса (треб. 1.3) — пауза звука/гейма при скрытой вкладке
// (visibilitychange) И при потере фокуса окна (blur, десктоп/мобил);
// возврат — visible/focus → YG.onResume (гарды adShowing/pauseOpen внутри)
document.addEventListener('visibilitychange',()=>{ if(document.hidden) YG.onPause(); else YG.onResume(); });
window.addEventListener('blur',()=>YG.onPause());
window.addEventListener('focus',()=>YG.onResume());
/* =========================================================
ЦИКЛ
========================================================= */
let last=performance.now();
function frame(now){
if(!YG.readySent) YG.ready(); // Y1: LoadingAPI.ready() (треб. 1.19.2) — первый кадр = меню видно
const dt=Math.min(0.05,(now-last)/1000); last=now;
if(!YG.paused){ // Y1: под паузой (реклама/скрытая вкладка/платформа) замораживается всё игровое время
time+=dt;
setDayTime(dayTime+dt/DAY_LENGTH); // M3: день/ночь идут в реальном времени
updateWeather(dt); // M8: погода — в реальном времени (как день/ночь)
updateWeatherHud(); // M8: пилюля погоды в HUD (иконка + остаток секунд)
updateDecor(dt);
if(aqOpen) updateAquarium(dt); // Этап 46: жизнь банки (плавание/пузыри) поверх uiOpen-паузы
if(!uiOpen) updateGame(dt);
// Y6: синхронизация HUD-кнопок — каждый кадр вне паузы (а не только в updateGame):
// переходы в MENU/под оверлеи (btnResetYes/openShop/btnReset) не гонят updateGame,
// и без этого #btnPause оставался бы «залипшим» видимым за оверлеем
syncDom();
}
draw();
requestAnimationFrame(frame);
}
/* =========================================================
ВВОД
========================================================= */
function onDown(px,py){
ac();
if(aqOpen){ aqTap(px,py); return; } // Этап 46: в аквариуме тап выбирает рыбу (сцена вместо озера)
if(uiOpen) return;
if(state==='IDLE'){ state='CHARGE'; charge=0; power=0; }
else if(state==='APPROACH'||state==='BITE'){ hook(); }
else if(state==='REEL'&&reel){ reel.holding=true; }
}
function onUp(){
if(state==='CHARGE') doCast();
else if(state==='REEL'&&reel) reel.holding=false;
}
canvas.addEventListener('pointerdown',e=>{ e.preventDefault(); onDown(e.clientX,e.clientY); });
window.addEventListener('pointerup',onUp);
window.addEventListener('pointercancel',onUp);
document.addEventListener('contextmenu',e=>e.preventDefault());
/* =========================================================
UI: МАГАЗИН / ДНЕВНИК / КАРТОЧКА
========================================================= */
let shopTab='tackle';
let shopFromMenu=false; // лавка открыта из «Меню» — × вернёт в меню, а не в игру
function syncTabs(){
$('tabTackle').classList.toggle('active',shopTab==='tackle');
$('tabJournal').classList.toggle('active',shopTab==='journal');
$('tabRewards').classList.toggle('active',shopTab==='rewards');
$('tabAch').classList.toggle('active',shopTab==='ach');
$('tabSkins').classList.toggle('active',shopTab==='skins');
$('tabLocations').classList.toggle('active',shopTab==='locations');
}
function openShop(tab){ // tab не задан — открыть на последней вкладке (HUD 🛒); задан — принудительно (монеты/«Меню»)
if(tab!==undefined) shopTab=tab;
syncTabs();
uiOpen=true; $('shop').classList.remove('hidden'); renderShop(); sfx('click'); YG.gameplayStop();
} // Y1: геймплейная разметка
function closeShop(){
$('shop').classList.add('hidden'); sfx('click');
if(shopFromMenu){ shopFromMenu=false; $('gamemenu').classList.remove('hidden'); uiOpen=true; } // шаг назад — в «Меню» (без gameplayStart)
else{ uiOpen=false; YG.gameplayStart(); }
} // Y1: геймплейная разметка
function setTab(t){ shopTab=t; syncTabs(); renderShop(); }
function lvPips(lv){ let s=''; for(let k=1;k<=4;k++) s+=k<=lv?'●':'○'; return s; }
function itemRow(item,i,type,owned,cur){
const list=type==='rod'?RODS:LURES;
const lvMap=type==='rod'?(save.rodLv||{}):(save.lureLv||{});
const lv=owned?Math.max(1,Math.min(4,lvMap[i]>=1?lvMap[i]:1)):1;
// M5: гейтинг — снасть №i открывается, когда снасть №(i−1) того же типа на 4 ур.
const prevLv=i>0?((lvMap[list[i-1].id]>=1)?lvMap[list[i-1].id]:1):0;
const locked=!owned&&i>0&&prevLv<4;
let btns='';
if(owned){
btns+=cur?'<button class="buybtn current" disabled>'+t('btn_selected')+'</button>'
:'<button class="buybtn owned" data-act="use" data-type="'+type+'" data-i="'+i+'">'+t('btn_select')+'</button>';
if(lv<4) btns+='<button class="buybtn upgbt" data-act="upgrade" data-type="'+type+'" data-i="'+i+'">⬆ '+upgNextText(type,lv-1)+' · '+upgCost(type,i,lv)+' 🪙</button>';
}else if(!locked){
btns='<button class="buybtn" data-act="buy" data-type="'+type+'" data-i="'+i+'">'+item.cost+' 🪙</button>';
}
let desc=trDesc(item); // Y5: i18n
if(locked) desc=tt('locked_desc',{name:trName(list[i-1])});
const lvTag=owned?' <span class="lvtag">'+lvPips(lv)+' '+lv+' '+t('lvl')+'</span>':'';
return '<div class="item'+(locked?' locked':'')+'"><div><div class="itemname">'+(item.icon||'')+' '+trName(item)+lvTag+'</div>'+
'<div class="itemdesc">'+desc+'</div></div>'+
(btns?'<div class="rowbtns">'+btns+'</div>':'<div class="rowbtns"><button class="buybtn" disabled>🔒</button></div>')+'</div>';
}
/* Этап 4: строка скина (стиль как у снастей, но проще): название, цена, одна кнопка
(«Купить N 🪙» / «Выбрать» / «Выбрано ✓») */
function skinRow(list,i,owned,equipped,group){
const s=list[i];
const price=s.cost>0?s.cost+' 🪙':t('free');
let btn;
if(equipped){
btn='<button class="buybtn current" disabled>'+t('btn_selected_chk')+'</button>';
}else if(owned){
btn='<button class="buybtn owned" data-act="select" data-type="'+group+'" data-i="'+i+'">'+t('btn_select')+'</button>';
}else{
btn='<button class="buybtn" data-act="buyskin" data-type="'+group+'" data-i="'+i+'">'+t('btn_buy')+' '+price+'</button>';
}
return '<div class="item"><div><div class="itemname">'+trName(s)+'</div>'+
'<div class="itemdesc">'+t('price_label')+price+'</div></div>'+
'<div class="rowbtns">'+btn+'</div></div>';
}
/* Этап 5: строка локации (по образцу skinRow): название, подпись, цена, одна кнопка
(«Купить N 🪙» / «Выбрать» / «Выбрана ✓») */
function locationRow(loc,i,owned,selected){
const price=loc.cost>0?loc.cost+' 🪙':t('free');
let btn;
if(selected){
btn='<button class="buybtn current" disabled>'+t('btn_selected_f')+'</button>';
}else if(owned){
btn='<button class="buybtn owned" data-act="selectlocation" data-i="'+i+'">'+t('btn_select')+'</button>';
}else{
btn='<button class="buybtn" data-act="buylocation" data-i="'+i+'">'+t('btn_buy')+' '+price+'</button>';
}
return '<div class="item"><div><div class="itemname">'+trName(loc)+'</div>'+
'<div class="itemdesc">'+trDesc(loc)+' · '+price+'</div></div>'+
'<div class="rowbtns">'+btn+'</div></div>';
}
function renderShop(){
const body=$('shopBody');
if(shopTab==='tackle'){
let h='<div class="section-title">'+t('sec_rods')+'</div>';
RODS.forEach((r,i)=>{ h+=itemRow(r,i,'rod',save.rods.indexOf(i)>=0,save.rod===i); });
h+='<div class="section-title">'+t('sec_lures')+'</div>';
LURES.forEach((l,i)=>{ h+=itemRow(l,i,'lure',save.lures.indexOf(i)>=0,save.lure===i); });
body.innerHTML=h;
}else if(shopTab==='journal'){
let h='<div class="statsline">'+tt('stats',{casts:save.casts,earned:save.earned})+'</div>';
const vc=v=>v>0?String(v):'—'; // M6: не пойманный вариант — «—»
const spKeys=VARIANTS.filter(v=>v.id!=='normal').map(v=>VARIANT_KEY[v.id]);
for(const s of SPECIES){
const c=Object.assign({n:0,best:0,cp:0,sv:0,qz:0,sn:0,em:0,dm:0,rb:0},save.caught[s.id]||{});
if(c.n>0){
const nm=c.n-spKeys.reduce((a,k)=>a+(c[k]||0),0);
// M6: мини-счётчики вариантов (обычная + все особые по лестнице VARIANTS);
// Y5: i18n — подписи вариантов из VARIANTS через trName
// Фаза свечения: светящийся вид — маркер-класс + drop-shadow цвета glow на портрете
const glowAttr=s.glow?' class="glow-fish" style="filter:drop-shadow(0 0 6px '+s.glow+')"':'';
h+='<div class="jrow"><span class="je"><svg'+glowAttr+' viewBox="0 0 160 100"><use href="#fish-'+s.id+'"/></svg></span><span class="jn"><b>'+trName(s)+'</b>'+
'<span class="jv jv-n" title="'+trName(VARIANTS[0])+'">'+vc(nm)+'</span>'+
spKeys.map(k=>{const v=VARIANTS.find(x=>VARIANT_KEY[x.id]===k);
return '<span class="jv jv-'+k+'" title="'+trName(v)+'">'+vc(c[k])+'</span>';}).join('')+'<br>'+
'<span style="font-size:11px;color:'+RARITY_COLORS[s.rarity]+'">'+trRarity(s.rarity)+' · '+s.price+' '+t('per_kg')+'</span></span>'+
'<span class="jc">×'+c.n+'<br>'+tt('max_w',{w:c.best.toFixed(1)})+'</span></div>';
}else{
h+='<div class="jrow unknown"><span class="je">❓</span><span class="jn">???</span>'+
'<span class="jc">'+t('not_caught')+'</span></div>';
}
}
body.innerHTML=h;
}else if(shopTab==='rewards'){
// 🎯 Награды: стрик входа + квесты дня
const st=save.streak;
const idx=st.days>0?streakIdx(st.days):0;
let h='<div class="section-title">'+t('sec_streak')+'</div><div class="streak">';
for(let i=1;i<=7;i++){
h+='<span class="st-dot'+(st.days>0&&i<=idx?' on':'')+(st.days>0&&i===idx?' cur':'')+'">'+STREAK_REWARDS[i-1]+'</span>';
}
h+='</div>';
h+='<div class="statsline">'+tt('streak_line',{d:(st.days||0),n:nextStreakReward(st.days||1)})+'</div>';
h+='<div class="section-title">'+t('sec_quests')+'</div>';
const ql=(save.quests&&save.quests.list)||[];
if(ql.length){
for(const q of ql){
h+='<div class="jrow'+(q.done?' qdone':'')+'"><span class="je">'+questIcon(q)+'</span>'+
'<span class="jn"><b>'+questText(q)+'</b></span>'+
'<span class="jc">'+(q.done?'✓ +'+q.reward+' 🪙':q.prog+'/'+q.goal)+'</span></div>';
}
}else{
h+='<div class="statsline">'+t('quests_done_today')+'</div>';
}
body.innerHTML=h;
}else if(shopTab==='ach'){
// 🏅 Достижения: выданные — яркие, остальные приглушённые
let h='<div class="section-title">'+t('sec_ach')+'</div>';
for(const a of ACHIEVEMENTS){
const got=!(!(save.ach&&save.ach[a.id]));
h+='<div class="jrow'+(got?' got':' locked')+'"><span class="je">'+a.icon+'</span>'+
'<span class="jn"><b>'+trName(a)+'</b><br><span class="adesc">'+trDesc(a)+' · '+bonusText(a.bonus)+'</span></span>'+
(got?'<span class="jc">✓</span>':'')+'</div>';
}
body.innerHTML=h;
}else if(shopTab==='skins'){
// Этап 4: скины — лодка и поплавок (чистая косметика, coin-sink)
let h='<div class="section-title">'+t('sec_boat')+'</div>';
BOAT_SKINS.forEach((s,i)=>{ h+=skinRow(BOAT_SKINS,i,save.boatSkins.indexOf(i)>=0,save.boatSkin===i,'boat'); });
h+='<div class="section-title">'+t('sec_bobber')+'</div>';
BOBBER_SKINS.forEach((s,i)=>{ h+=skinRow(BOBBER_SKINS,i,save.bobberSkins.indexOf(i)>=0,save.bobberSkin===i,'bobber'); });
body.innerHTML=h;
}else if(shopTab==='locations'){
// Этап 5: локации — Река (родная вода) и Озёра (65536 🪙, новые рыбы)
let h='<div class="section-title">'+t('sec_locations')+'</div>';
LOCATIONS.forEach((loc,i)=>{ h+=locationRow(loc,i,save.locations.indexOf(i)>=0,save.location===i); });
body.innerHTML=h;
}
}
function shopClick(e){
const b=e.target.closest('[data-act]');
if(!b) return;
const type=b.dataset.type, i=+b.dataset.i;
if(b.dataset.act==='buylocation'||b.dataset.act==='selectlocation'){
// Этап 5: локации — покупка (монеты списать, push, АВТО-ПЕРЕХОД) и выбор
const loc=LOCATIONS[i];
if(!loc) return;
if(loc.id!==i) return; // защита: индекс массива не обязан совпадать с id при будущей вставке записей
if(b.dataset.act==='buylocation'){
if(save.locations.indexOf(i)>=0){ sfx('no'); return; } // уже куплено — защита
if(save.coins<loc.cost){ sfx('no'); toast(t('not_enough')); return; }
save.coins-=loc.cost; save.locations.push(i);
save.location=i; // авто-переход на купленную локацию
initFish(); // Этап 43: фоновые рыбы по новой воде
initScenery(); // Этап 44: силуэты новой воды
persist(); updateHUD(); sfx('coin'); renderShop();
// Этап 35/36/45: у каждой локации свой тост (id 0 «Река» не покупается — общий «Куплено»)
let buyToast;
if(loc.id===1) buyToast=t('welcome_lakes');
else if(loc.id===2) buyToast=t('welcome_sea');
else if(loc.id===3) buyToast=t('welcome_ocean');
else if(loc.id===4) buyToast=t('welcome_swamp');
else buyToast=tt('bought',{name:trName(loc)});
toast(buyToast);
}else{
if(save.locations.indexOf(i)<0){ sfx('no'); return; } // не куплено — выбрать нельзя (паттерн защиты buy)
save.location=i;
initFish(); // Этап 43: фоновые рыбы по новой воде
initScenery(); // Этап 44: силуэты новой воды
persist(); updateHUD(); sfx('click'); renderShop();
toast(tt('location_set',{name:trName(loc)}));
}
return;
}
if(type==='boat'||type==='bobber'){
// Этап 4: скины — покупка (монеты списать, авто-экипировка) и выбор
const slist=type==='boat'?BOAT_SKINS:BOBBER_SKINS;
const owned=type==='boat'?save.boatSkins:save.bobberSkins;
const item=slist[i];
if(b.dataset.act==='buyskin'){
if(!item||owned.indexOf(i)>=0){ sfx('no'); return; } // уже куплено — защита
if(save.coins<item.cost){ sfx('no'); toast(t('not_enough')); return; }
save.coins-=item.cost; owned.push(i);
if(type==='boat') save.boatSkin=i; else save.bobberSkin=i; // авто-экипировка
persist(); updateHUD(); sfx('coin'); renderShop();
toast(tt('bought',{name:trName(item)}));
}else{
if(!item||owned.indexOf(i)<0){ sfx('no'); return; } // не куплено — выбрать нельзя (паттерн защиты buy)
if(type==='boat') save.boatSkin=i; else save.bobberSkin=i;
persist(); updateHUD(); sfx('click'); renderShop();
}
return;
}
const list=type==='rod'?RODS:LURES;
const owned=type==='rod'?save.rods:save.lures;
if(!save.rodLv||typeof save.rodLv!=='object') save.rodLv={};
if(!save.lureLv||typeof save.lureLv!=='object') save.lureLv={};
const lvMap=type==='rod'?save.rodLv:save.lureLv;
const item=list[i];
if(b.dataset.act==='buy'){
if(i>0&&lvMap[list[i-1].id]<4){ sfx('no'); toast(tt('gate_toast',{name:trName(list[i-1])})); return; } // M5: гейтинг
if(save.coins<item.cost){ sfx('no'); toast(t('not_enough')); return; }
save.coins-=item.cost; owned.push(i); lvMap[i]=1; // куплено — уровень 1
if(type==='rod') save.rod=i; else save.lure=i;
persist(); updateHUD(); sfx('coin'); renderShop();
toast(tt('bought',{name:trName(item)}));
checkAchievements();
}else if(b.dataset.act==='upgrade'){
if(owned.indexOf(i)<0){ sfx('no'); return; } // M5: не куплено — апгрейд недоступен (паттерн защиты buy)
const lv=(lvMap[i]>=1)?lvMap[i]:1;
if(lv>=4) return;
const cost=upgCost(type,i,lv);
if(save.coins<cost){ sfx('no'); toast(t('not_enough')); return; }
save.coins-=cost; lvMap[i]=lv+1; // M5: апгрейд — уровень++
persist(); updateHUD(); sfx('coin'); renderShop();
toast(tt('upgraded',{name:trName(item),lv:lv+1}));
checkAchievements();
}else{
if(type==='rod') save.rod=i; else save.lure=i;
persist(); updateHUD(); sfx('click'); renderShop();
}
}
let cardSpec=null; // Этап 46: экземпляр открытой карточки {sp,w,variant} — для кнопки «В аквариум»
function syncKeepBtn(){ // Этап 46: доступность «В аквариум» — нет свободного слота → disabled + «Нет места»
const full=save.aqFish.length>=save.aqSlots;
$('btnKeep').disabled=full;
$('btnKeep').textContent=full?t('aq_no_room'):t('aq_keep');
$('btnKeep').title=full?t('aq_no_room'):t('aq_keep');
}
function showCard(sp,w,val,rec,variant,boss){
cardSpec={sp:sp,w:w,variant:variant}; // Этап 46: копия экземпляра для аквариума (модель C; catchFish не трогаем)
syncKeepBtn();
$('cardRarity').textContent=trRarity(sp.rarity);
$('cardRarity').style.color=RARITY_COLORS[sp.rarity];
document.getElementById('cardFishUse').setAttribute('href','#fish-'+sp.id); // SVG-портрет вида (спрайт; эмодзи рыб убраны — этап 42)
$('cardName').textContent=trName(sp)+(boss?t('card_boss_suffix'):''); // M4: имя босса; Y5: i18n
$('cardSub').textContent=tt('card_sub',{w:w.toFixed(1),price:sp.price});
$('cardVal').textContent='+'+val+' 🪙';
$('cardRecord').classList.toggle('hidden',!rec);
// M6: бейдж варианта + оформление карточки (по лестнице VARIANTS; normal — без оформления)
for(const v of VARIANTS){ if(v.id==='normal') continue;
$('card').classList.toggle(v.css+'-card',variant.id===v.id);
}
$('cardVariant').classList.toggle('hidden',variant.id==='normal');
$('cardVariant').textContent=trName(variant).toUpperCase();
// M4: босс: бейдж 🏆 + золотое оформление карточки
$('cardBoss').classList.toggle('hidden',!boss);
$('card').classList.toggle('boss-card',!!boss);
// Фаза свечения: светящийся вид (glow) в normal-варианте — цветной drop-shadow портрета;
// CSS-переменная --glow читается правилом #card.glow-card .bigemoji. Свечение — оформление
// вида (не зависит от времени суток), вариант normal — чтобы не спорить с фильтрами вариантов
const glowOn=!!sp.glow&&variant.id==='normal';
$('card').classList.toggle('glow-card',glowOn);
if(sp.glow) $('card').style.setProperty('--glow',sp.glow);
// Y2: rewarded «монеты ×2» — бонус = полная цена улова (rvVal), сброс флага
rvVal=val; rvDone=false;
$('btnRv').classList.remove('hidden');
$('btnRv').disabled=false;
$('btnRv').textContent=t('rv_btn');
$('card').classList.remove('hidden');
}
/* =========================================================
КНОПКИ
========================================================= */
$('btnPlay').addEventListener('click',()=>{
ac(); sfx('click');
$('menu').classList.add('hidden');
$('gamemenu').classList.add('hidden'); // инструкции могли быть открыты из «Меню»
shopFromMenu=false;
uiOpen=false; state='IDLE';
if(!YG.paused) YG.gameplayStart(); // Y1: геймплейная разметка (треб. 1.19.3; под паузой резюме поднимет сам)
});
$('btnShop').addEventListener('click',()=>openShop()); // без аргумента — последняя вкладка
$('coins').addEventListener('click',()=>openShop('tackle')); // монеты → лавка, вкладка «Лавка»
$('btnCloseShop').addEventListener('click',closeShop);
$('tabTackle').addEventListener('click',()=>{ setTab('tackle'); sfx('click'); });
$('tabJournal').addEventListener('click',()=>{ setTab('journal'); sfx('click'); });
$('tabRewards').addEventListener('click',()=>{ setTab('rewards'); sfx('click'); });
$('tabAch').addEventListener('click',()=>{ setTab('ach'); sfx('click'); });
$('tabSkins').addEventListener('click',()=>{ setTab('skins'); sfx('click'); }); // Этап 4: вкладка скинов
$('tabLocations').addEventListener('click',()=>{ setTab('locations'); sfx('click'); }); // Этап 5: вкладка локаций
$('shopBody').addEventListener('click',shopClick);
$('btnMute').addEventListener('click',()=>{
save.muted=!save.muted; persist(); updateHUD(); sfx('click');
});
$('btnRecall').addEventListener('click',()=>{ recall(); });
// Y6: кнопка паузы (треб. Яндекс Игр 6.3) — оверлей «Продолжить/В меню».
// Общие гарды: паузу можно открыть только в игре (не MENU, без оверлеев и рекламы);
// снять её может только closePause()/«В меню» (YG.onResume под гардом pauseOpen).
function openPause(){
if(state==='MENU'||uiOpen||adShowing||pauseOpen) return;
sfx('click');
pauseOpen=true; uiOpen=true;
YG.onPause();
$('pause').classList.remove('hidden');
$('btnPause').classList.add('hidden'); // под паузой updateGame/syncDom не гонятся — прячем руками
}
function closePause(){
if(!pauseOpen) return;
sfx('click');
pauseOpen=false; uiOpen=(state==='MENU');
$('pause').classList.add('hidden');
YG.onResume();
}
$('btnPause').addEventListener('click',openPause);
$('btnPauseResume').addEventListener('click',closePause);
/* Y6/этап «Меню»: «В меню» из паузы открывает хаб #gamemenu — state НЕ меняем,
сессия (заброс/вываживание) заморожена под оверлеем до «Продолжить».
YG.onResume: state!=='MENU', но uiOpen=true — gameplayStart не вызовет
(onPause при открытии паузы уже сделал gameplayStop — счётчики сбалансированы). */
$('btnPauseMenu').addEventListener('click',()=>{
sfx('click');
pauseOpen=false;
$('pause').classList.add('hidden');
$('gamemenu').classList.remove('hidden');
uiOpen=true;
YG.onResume();
});
/* Кнопки хаба «Меню» */
$('btnGmResume').addEventListener('click',()=>{
sfx('click');
$('gamemenu').classList.add('hidden');
uiOpen=false;
YG.gameplayStart(); // Y1: возврат к геймплею (сессия сохранена — продолжается с того же места)
});
function fromMenuShop(tab){ // лавка из «Меню»: гменю прячем (#gamemenu в DOM позже #shop — иначе перекрыл бы лавку), × вернёт назад
shopFromMenu=true;
$('gamemenu').classList.add('hidden');
openShop(tab);
}
$('btnGmShop').addEventListener('click',()=>fromMenuShop('tackle'));
$('btnGmAch').addEventListener('click',()=>fromMenuShop('ach'));
$('btnGmJournal').addEventListener('click',()=>fromMenuShop('journal'));
/* Этап 46: вход в аквариум из «Меню» + бар сцены (назад/слот/продажа из банки) */
$('btnGmAquarium').addEventListener('click',()=>openAquarium());
$('btnAqBack').addEventListener('click',()=>closeAquarium());
$('btnAqSlot').addEventListener('click',()=>{
if(save.aqSlots>=AQ_MAX_SLOTS){ sfx('no'); return; } // максимум — кнопка disabled, защита
const cost=AQ_SLOT_COSTS[save.aqSlots-AQ_BASE_SLOTS];
if(!Number.isFinite(cost)){ sfx('no'); return; } // Этап 46: битый aqSlots (индекс вне лестницы) — не даём NaN
if(save.coins<cost){ sfx('no'); toast(t('not_enough')); return; } // паттерн shopClick
save.coins-=cost; save.aqSlots++;
persist(); updateHUD(); sfx('coin');
renderAqBar(); checkAchievements();
});
$('btnAqRelease').addEventListener('click',()=>aqReleaseSel());
$('btnGmHowto').addEventListener('click',()=>{
sfx('click');
$('gamemenu').classList.add('hidden');
$('menu').classList.remove('hidden'); // начальные инструкции; «Играть» вернёт в игру
});
$('btnReset').addEventListener('click',()=>{
sfx('click');
$('gamemenu').classList.add('hidden'); // #resetDlg в DOM раньше #gamemenu — иначе оказался бы под ним
uiOpen=true; // подтверждение поверх (единственный путь к сбросу — из «Меню»)
$('resetDlg').classList.remove('hidden');
// gameplayStop не нужен: в «Меню» попадаем только из паузы — onPause уже остановил геймплей
});
$('btnResetNo').addEventListener('click',()=>{
sfx('click');
$('resetDlg').classList.add('hidden');
$('gamemenu').classList.remove('hidden'); // отмена → возврат в «Меню»
uiOpen=true;
});
$('btnResetYes').addEventListener('click',()=>{
const muted=save.muted; // настройка звука — не игровые данные, оставляем
save=freshSave(muted);
persist();
refreshQuests(); // квесты дня; стрик начнётся с первой загрузки (чистый старт, coins=0)
reel=null; biteFish=null;
stateBoss=false; bossPhase=0; // M4: босс-бой сброшен
forceBite=false; forceBoss=false; forceVariant=null; forceWeather=null; // T2b: тест-форсы тоже сбрасываем (симметрия); M8: погода
weather=null; weatherT=0; weatherGap=weatherGapNext(); // M8: чистый старт — новый погодный таймер
$('resetDlg').classList.add('hidden');
$('shop').classList.add('hidden');
$('card').classList.add('hidden');
$('gamemenu').classList.add('hidden');
shopFromMenu=false;
state='MENU'; uiOpen=true;
$('menu').classList.remove('hidden');
updateHUD(); renderShop();
sfx('no'); vib(50);
toast(t('progress_reset'));
});
// Y2: interstitial на закрытии карточки улова (треб. 4.4 — логическая пауза).
// Гейт: первый показ не раньше AD_FIRST_MS сессии, затем — через AD_COOLDOWN_MS.
// persist() — ПЕРЕД паузой (треб. 4.2: процесс сохранён до перехода на рекламу);
// YG.onPause() — звук и весь игровой процесс (треб. 4.7). В стабе showFullscreen
// вернёт false — endAd() сразу, игра не зависает в adShowing=true.
function tryInterstitial(){
if(adShowing) return;
const now=Date.now();
if(now-sessionStartTs < AD_FIRST_MS) return;
if(now-lastAdTs < AD_COOLDOWN_MS) return;
lastAdTs=now; // отмечаем ПОПЫТКУ, а не показ: при троттлинге платформы (wasShown=false) кулдаун сгорает — это осознанно, ограничивает частоту вызовов (retry-storm)
adShowing=true;
persist(); // 4.2: процесс сохранён до перехода на рекламу
YG.onPause(); // 4.7: звук + весь игровой процесс на паузе
const ok=YG.showFullscreen({
onOpen(){},
onClose(){ endAd(); }, // onClose(wasShown) приходит и при троттлинге
onError(){ endAd(); }
});
if(!ok) endAd(); // стаб: не показана — сразу резюм
}
function endAd(){ clearTimeout(YG.adWatchdog); YG.adWatchdog=null; adShowing=false; YG.onResume(); } // Y2: реклама закрыта/ошибка — снимаем паузу и останавливаем watchdog
$('btnCardOk').addEventListener('click',()=>{
sfx('click');
$('card').classList.add('hidden');
state='IDLE';
tryInterstitial(); // Y2: после возврата в IDLE; гейт может пропустить (внутри return)
});
/* Этап 46: «В аквариум» (модель C — бесплатная КОПИЯ экземпляра). Монеты/квесты/ачивки улова
уже начислены catchFish; здесь только push в save.aqFish + persist. Карточка закрывается
как при «Отлично!» — интерстишел тем же гейтом. */
$('btnKeep').addEventListener('click',()=>{
if(!cardSpec) return;
if(save.aqFish.length>=save.aqSlots){ sfx('no'); toast(t('aq_no_room')); return; }
sfx('click');
save.aqFish.push({id:cardSpec.sp.id,v:cardSpec.variant.id,w:cardSpec.w});
persist();
checkAchievements();
toast(t('aq_kept'));
cardSpec=null;
$('card').classList.add('hidden');
state='IDLE';
tryInterstitial();
});
// Y2: rewarded «монеты ×2» (треб. 4.5.1 — что показываем и что даём, написано на
// кнопке и в title; 4.5.2 — чистый бонус, игру не блокирует: карточка остаётся,
// закрыть можно в любой момент). В стабе onRewarded срабатывает синхронно — весь
// флоу в одном клике; в реальном SDK onRewarded придёт после просмотра, onClose —
// позже (endAd именно через onClose, не раньше).
$('btnRv').addEventListener('click',()=>{
if(rvDone||adShowing) return;
sfx('click');
adShowing=true;
YG.onPause(); // 4.7
const ok=YG.showRewarded({
onOpen(){},
onRewarded(){
rvDone=true;
save.coins+=rvVal; // бонус = полная цена улова ещё раз
persist(); updateHUD();
$('cardVal').textContent='+'+(rvVal*2)+' 🪙';
$('btnRv').disabled=true;
$('btnRv').textContent=t('rv_done');
sfx('coin'); vib(30);
},
onClose(){ endAd(); },
onError(){ endAd(); }
});
if(!ok) endAd();
});
/* Закрытие по тапу мимо диалога: тап «в молоко» — на подложку оверлея (e.target === сам
оверлей, а не .panel) — закрывает его тем же действием, что и кнопка закрытия.
pointerdown — отзывчиво, как и весь ввод игры. #menu не диалог (экран старта) — вне списка. */
function backdropClose(el,fn){ el.addEventListener('pointerdown',e=>{ if(e.target===el) fn(); }); }
backdropClose($('shop'),closeShop); // лавка — как ×
backdropClose($('resetDlg'),()=>$('btnResetNo').click()); // сброс — как «Отмена» (в «Меню»)
backdropClose($('pause'),closePause); // пауза — как «Продолжить»
backdropClose($('gamemenu'),()=>$('btnGmResume').click()); // хаб — как «Продолжить» (сессия с места)
backdropClose($('card'),()=>$('btnCardOk').click()); // карточка — как «Отлично!» (вкл. интерстишел)
/* =========================================================
СТАРТ
========================================================= */
loadSave();
resize();
initFish();
updateHUD();
renderMenu(); // Y5: i18n — меню из T (device-aware; стаб-ветка уже вызывала через resolveLang, это страховка)
renderStaticUI(); // Y5: i18n — статичные подписи (лавка/вкладки/сброс/карточка)
// Э28: встроенный emoji-шрифт — дождаться @font-face перед первым кадром (канвас-emoji 💥🌀⚡💪💤
// рисуются им); data: URI грузится быстро, timeout-фолбэк 1.5 с — игра не «висит» даже на file://
const fontsGate=(document.fonts&&document.fonts.load)
?Promise.race([document.fonts.load('16px "EmojiEmbedded"').catch(()=>{}),new Promise(r=>setTimeout(r,1500))])
:Promise.resolve();
fontsGate.then(()=>requestAnimationFrame(frame));
</script>
</body>
</html>