{"id":4915,"date":"2026-09-28T21:59:20","date_gmt":"2026-09-28T18:59:20","guid":{"rendered":"https:\/\/www.seoliva.com\/?page_id=4915"},"modified":"2026-10-15T13:14:16","modified_gmt":"2026-10-15T10:14:16","slug":"ilk-sira","status":"publish","type":"page","link":"https:\/\/www.seoliva.com\/en\/seo-oyunlari\/ilk-sira","title":{"rendered":"Google\u2019da Birinci Ol"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"4915\" class=\"elementor elementor-4915\" data-elementor-post-type=\"page\">\n\t\t\t\t<div data-particle_enable=\"false\" data-particle-mobile-disabled=\"false\" class=\"elementor-element elementor-element-841993d e-flex e-con-boxed e-con e-parent\" data-id=\"841993d\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-14e6aaa elementor-widget elementor-widget-shortcode\" data-id=\"14e6aaa\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"shortcode.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-shortcode\"><style>\n#sl-ilk-sira-oyun{\n    --black:#111111;\n    --muted:#656565;\n    --green:#039358;\n    --green-dark:#08764c;\n    color:#171717;\n    font-family:inherit;\n}\n#sl-ilk-sira-oyun *{box-sizing:border-box}\n#sl-ilk-sira-oyun .wrap{\n    width:min(1180px,calc(100% - 44px));\n    margin:0 auto;\n}\n#sl-ilk-sira-oyun .head{padding:40px 0 20px}\n#sl-ilk-sira-oyun .breadcrumb{\n    display:flex;\n    flex-wrap:wrap;\n    align-items:center;\n    gap:8px;\n    margin-bottom:16px;\n    color:#8a8a86;\n    font-size:12.5px;\n    line-height:1.4;\n}\n#sl-ilk-sira-oyun .breadcrumb a{color:#6f6f6b;text-decoration:none}\n#sl-ilk-sira-oyun .breadcrumb-sep{color:#b8b8b3}\n#sl-ilk-sira-oyun .breadcrumb-current{color:#2a2a2a;font-weight:650}\n#sl-ilk-sira-oyun h1{\n    margin:0;\n    color:var(--black);\n    font-size:46px;\n    line-height:1.05;\n    letter-spacing:-.045em;\n    font-weight:790;\n    white-space:nowrap;\n}\n#sl-ilk-sira-oyun .head p{\n    max-width:940px;\n    margin:12px 0 0;\n    color:var(--muted);\n    font-size:16px;\n    line-height:1.65;\n}\n#sl-ilk-sira-oyun .frame{\n    position:relative;\n    touch-action:manipulation;\n    height:min(940px,max(480px,calc(100vh - 97px)));\n    height:min(940px,max(480px,calc(100svh - 97px)));\n    border-radius:24px;\n    overflow:hidden;\n    background:#E9F1EC;\n    border:1px solid #dce8e0;\n}\n#sl-ilk-sira-oyun iframe{\n    display:block;\n    touch-action:manipulation;\n    width:100%;\n    height:100%;\n    border:0;\n    background:#E9F1EC;\n}\n\/* big screens: the game breaks out of the text column and uses the width of the screen *\/\n@media(min-width:1200px){\n    #sl-ilk-sira-oyun .frame{\n        width:min(1640px,calc(100vw - 72px));\n        margin-left:calc(50% - min(820px,50vw - 36px));\n        border-radius:28px;\n    }\n}\n@media(max-width:760px){\n    #sl-ilk-sira-oyun .wrap{width:min(100% - 20px,1180px)}\n    #sl-ilk-sira-oyun .head{padding:12px 4px 10px}\n    #sl-ilk-sira-oyun .breadcrumb{margin-bottom:6px;font-size:11.5px;gap:6px}\n    #sl-ilk-sira-oyun h1{font-size:clamp(24px,7.4vw,30px)}\n    #sl-ilk-sira-oyun .head p{margin-top:5px;font-size:14px;line-height:1.5}\n    #sl-ilk-sira-oyun .frame{\n        height:max(540px,calc(100vh - 84px));\n        height:max(540px,calc(100svh - 84px));\n        border-radius:20px;\n    }\n    }\n\/* phones: nothing on this page may push it sideways (clip keeps the sticky header working) *\/\n@media(max-width:760px){ html,body{overflow-x:clip} }\n\/* phone held sideways: the whole game fits the screen *\/\n@media(orientation:landscape) and (max-height:520px){\n    #sl-ilk-sira-oyun .frame{height:calc(100vh - 12px);height:calc(100svh - 12px)}\n}\n<\/style>\n\n<section id=\"sl-ilk-sira-oyun\">\n    <div class=\"wrap\">\n        <div class=\"head\">\n            <nav class=\"breadcrumb\" aria-label=\"Breadcrumb\">\n                <a href=\"https:\/\/www.seoliva.com\/\">Ana Sayfa<\/a>\n                <span class=\"breadcrumb-sep\" aria-hidden=\"true\">\/<\/span>\n                <a href=\"https:\/\/www.seoliva.com\/seo-oyunlari\">SEO Oyunlar\u0131<\/a>\n                <span class=\"breadcrumb-sep\" aria-hidden=\"true\">\/<\/span>\n                <span class=\"breadcrumb-current\" aria-current=\"page\">Google'da Birinci Ol<\/span>\n            <\/nav>\n            <h1>Google'da Birinci Ol<\/h1>\n            <p>Siteniz 100. s\u0131rada. Algoritman\u0131n de\u011fi\u015fen kurallar\u0131na uyun, zirvede 1. s\u0131radaki rakibinizi ge\u00e7in.<\/p>\n        <\/div>\n        <div class=\"frame\">\n            <iframe title=\"Google'da Birinci Ol oyunu\" srcdoc=\"&lt;!doctype html&gt;\n&lt;html lang=&quot;tr&quot;&gt;\n&lt;head&gt;\n&lt;meta charset=&quot;utf-8&quot;&gt;\n&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width,initial-scale=1,viewport-fit=cover&quot;&gt;\n&lt;meta name=&quot;description&quot; content=&quot;SEOliva&#039;n\u0131n SEO oyunu Google&#039;da Birinci Ol: siteni 100. s\u0131radan 1. s\u0131raya ta\u015f\u0131, algoritma g\u00fcncellemelerini atlat, zirvede rakibini yen.&quot;&gt;\n&lt;title&gt;Google&#039;da Birinci Ol&lt;\/title&gt;\n&lt;link rel=&quot;preconnect&quot; href=&quot;https:\/\/fonts.googleapis.com&quot;&gt;\n&lt;link rel=&quot;preconnect&quot; href=&quot;https:\/\/fonts.gstatic.com&quot; crossorigin&gt;\n&lt;link rel=&quot;stylesheet&quot; href=&quot;https:\/\/fonts.googleapis.com\/css2?family=Poppins:wght@600;700;800&amp;family=Inter:wght@400;500;600&amp;display=swap&quot;&gt;\n&lt;style&gt;\n  :root{\n    color-scheme: light;\n    --bg:#E9F1EC;\n    --ink:#04281c;\n    --green:#039358;\n    --deep:#046A40;\n    --lime:#c9f24e;\n    --muted:#5A7266;\n    --card:#ffffff;\n    --line:#D3E1D8;\n  }\n  [hidden]{display:none!important}\n  html,body{height:100%;touch-action:manipulation}\n  body{background:var(--bg);color:var(--ink);font-family:Inter,system-ui,-apple-system,&quot;Segoe UI&quot;,sans-serif;margin:0;-webkit-tap-highlight-color:transparent}\n  .app{height:100%;height:100dvh;box-sizing:border-box;max-width:1180px;margin:0 auto;padding-inline:16px;padding-block:10px;display:flex;flex-direction:column;gap:8px}\n  .top{display:flex;align-items:center;justify-content:space-between;gap:12px}\n  .brand{display:flex;align-items:center;gap:9px;font-family:Poppins,system-ui,sans-serif;font-weight:700;font-size:15px;white-space:nowrap}\n  .brand svg{flex:none}\n  .tbtns{display:flex;gap:6px}\n  .tbtn.pbtn{display:grid;place-items:center;min-width:38px;padding:7px 10px}\n  .psub{margin:0;color:var(--muted);font-size:14px}\n  @media (pointer:coarse){ .tbtn{min-height:40px} }\n  .tbtn{white-space:nowrap}\n  @media (max-width:360px){.tbtns .tbtn{padding:6px 8px;font-size:12px}}\n  .tbtn.off{color:var(--muted);opacity:.75}\n  .tbtn{font:inherit;font-size:12.5px;padding:7px 11px;border-radius:10px;background:var(--card);border:1px solid var(--line);color:var(--ink);font-weight:600;cursor:pointer}\n  .stage{flex:1;min-height:0;position:relative;display:grid;place-items:center;touch-action:manipulation;user-select:none;-webkit-user-select:none}\n  canvas{-webkit-touch-callout:none;-webkit-user-select:none;display:block;border-radius:22px;box-shadow:0 1px 0 var(--line),0 24px 50px -30px rgba(4,40,28,.5);cursor:pointer}\n  .pad{display:none}\n  @media (pointer:coarse) and (orientation:portrait) and (min-height:460px){\n    .pad{display:flex;flex:none;height:clamp(76px,12vh,110px);border-radius:22px;background:var(--ink);color:var(--lime);align-items:center;justify-content:center;gap:12px;touch-action:manipulation;user-select:none;-webkit-user-select:none;-webkit-touch-callout:none;box-shadow:0 5px 0 -1px #021a12}\n    .pad span{display:flex;flex-direction:column;line-height:1.25}\n    .pad b{font-family:Poppins,system-ui,sans-serif;font-size:16px;white-space:nowrap}\n    .pad small{color:#CFE3D7;font-size:12px;white-space:nowrap}\n    .pad.on{transform:translateY(3px);box-shadow:0 2px 0 -1px #021a12;background:#0A3A2A}\n    .app .foot{display:none}\n    .stage{place-items:end center}\n  }\n  .foot{display:flex;justify-content:space-between;gap:12px;flex-wrap:wrap;font-size:12.5px;color:var(--muted)}\n  .foot a{color:var(--deep);font-weight:600;text-decoration:none}\n\n  button{font:inherit;cursor:pointer;border:0}\n  button:focus-visible,a:focus-visible{outline:3px solid var(--lime);outline-offset:3px}\n  .primary{background:var(--ink);color:var(--lime);font-family:Poppins,system-ui,sans-serif;font-weight:700;font-size:17px;padding:15px 34px;border-radius:16px;box-shadow:0 6px 0 -1px #021a12}\n  .primary:hover{background:var(--deep)}\n  .primary:active{transform:translateY(2px);box-shadow:0 3px 0 -1px #021a12}\n  .link{background:none;color:var(--muted);font-weight:600;font-size:14px;padding:10px;text-decoration:underline;text-underline-offset:3px}\n\n  .overlay{position:absolute;inset:0;display:grid;place-items:center;padding:14px;box-sizing:border-box;overflow:auto}\n  .overlay.dim{background:rgba(233,241,236,.55);backdrop-filter:blur(4px);-webkit-backdrop-filter:blur(4px)}\n  .card{width:100%;max-width:380px;background:var(--card);border-radius:26px;padding:22px 22px;box-sizing:border-box;display:flex;flex-direction:column;align-items:center;text-align:center;gap:13px;box-shadow:0 30px 70px -30px rgba(4,40,28,.55),0 0 0 1px rgba(4,40,28,.05);margin:auto;animation:rise .35s cubic-bezier(.2,.9,.3,1.25)}\n  @keyframes rise{from{transform:translateY(16px) scale(.96);opacity:0}to{transform:none;opacity:1}}\n  h1,h2{font-family:Poppins,system-ui,sans-serif;font-weight:800;margin:0;line-height:1.05;letter-spacing:-.02em;white-space:nowrap}\n  h1{font-size:clamp(24px,6.8vw,32px)}\n  h1 em,h2 em{font-style:normal;color:var(--green)}\n  .lede{margin:0;font-size:16px;line-height:1.45;color:var(--muted)}\n  .legend{display:flex;gap:10px;justify-content:center;width:100%}\n  .legend &gt; div{flex:1;background:var(--bg);border-radius:16px;padding:10px 8px 8px;display:flex;flex-direction:column;align-items:center;gap:4px}\n  .legend .icons{display:flex;gap:6px;align-items:center;height:36px}\n  .legend b{font-family:Poppins,system-ui,sans-serif;font-size:13px}\n  .legend .sub{font-size:11px;color:var(--muted);white-space:nowrap}\n  .tip{margin:0;font-size:13.5px;line-height:1.45;color:var(--ink);background:#F3F8F5;border-radius:12px;padding:10px 12px}\n  .notes{margin:0;padding:0;list-style:none;display:grid;gap:6px;text-align:left;width:100%}\n  .notes li{font-size:14px;line-height:1.4;padding-left:14px;position:relative}\n  .notes li::before{content:&quot;&quot;;position:absolute;left:0;top:.5em;width:6px;height:6px;border-radius:2px;background:var(--green)}\n  .pbars{display:grid;gap:6px;width:100%}\n  .pbar{display:grid;grid-template-columns:60px 1fr;align-items:center;gap:10px;font-size:12.5px;text-align:left}\n  .pbar i{display:block;height:8px;border-radius:4px;background:#E6EEE9;overflow:hidden}\n  .pbar i u{display:block;height:100%;border-radius:4px}\n  .legend.good b{color:var(--green)}\n  .tap{font-size:13px;color:var(--muted)}\n  .ctl{white-space:nowrap;font-size:12.5px}\n  @media (max-width:360px){ .ctl{font-size:11.5px} }\n\n  .rank-label{font-size:12px;letter-spacing:.1em;text-transform:uppercase;font-weight:600;color:var(--muted);margin-bottom:-10px}\n  .badges{display:flex;gap:6px;flex-wrap:wrap;justify-content:center}\n  .bset{display:flex;gap:6px;justify-content:center}\n  .bi{width:28px;height:28px;border-radius:50%;display:grid;place-items:center;font-size:12px;font-weight:800;background:#E8EFEA;color:#A9B8AE;border:1.5px dashed #C9D6CD}\n  .bi.on{background:var(--ink);color:var(--lime);border:1.5px solid var(--ink)}\n  .bi.new{animation:bpop .5s 1.3s both}\n  @keyframes bpop{0%{transform:scale(.3);opacity:0}70%{transform:scale(1.25);opacity:1}100%{transform:scale(1)}}\n  .bcap{margin:6px 0 0;font-size:12.5px;color:var(--muted);text-align:center;line-height:1.35}\n  .bcap b{color:var(--ink)}\n  .badge{display:inline-flex;align-items:center;gap:6px;background:var(--ink);color:#fff;border-radius:999px;padding:5px 11px 5px 5px;font-size:12.5px;font-weight:600;white-space:nowrap;animation:rise .4s .9s both}\n  .badge i{font-style:normal;width:20px;height:20px;border-radius:50%;background:var(--lime);color:var(--ink);display:grid;place-items:center;font-size:11px;font-weight:800}\n  .big-rank.pop{animation:rankpop .45s cubic-bezier(.2,.9,.3,1.5)}\n  @keyframes rankpop{0%{transform:scale(1)}40%{transform:scale(1.18)}100%{transform:scale(1)}}\n  .big-rank{font-family:Poppins,system-ui,sans-serif;font-weight:800;font-size:56px;line-height:1;letter-spacing:-.03em;color:var(--green)}\n  .climb{display:flex;align-items:center;gap:10px;font-family:Poppins,system-ui,sans-serif;font-weight:700;font-size:15px;color:var(--muted)}\n  .climb s{text-decoration:none}\n  .climb .up{background:var(--lime);color:var(--ink);border-radius:999px;padding:4px 10px;font-size:13px}\n  .praise{margin:0;font-size:16px;line-height:1.45}\n  .cta{width:100%;background:var(--ink);color:#fff;border-radius:20px;padding:18px;box-sizing:border-box;display:flex;flex-direction:column;gap:12px;align-items:center}\n  .cta p{margin:0;font-size:15px;line-height:1.45;color:#CFE3D7}\n  .cta p b{color:#fff;font-family:Poppins,system-ui,sans-serif;font-size:17px;display:block;margin-bottom:2px;white-space:nowrap}\n  .cta a{display:block;width:100%;box-sizing:border-box;background:var(--lime);color:var(--ink);font-family:Poppins,system-ui,sans-serif;font-weight:700;font-size:16px;padding:14px;border-radius:14px;text-decoration:none}\n  .cta a:hover{background:#fff}\n  .cta a{white-space:nowrap}\n  @media (max-width:400px) and (max-height:820px){ #over .notes{display:none} }\n  @media (max-width:380px){ .cta a{font-size:15px} }\n  @media (max-height:800px){ #over .notes li:nth-child(n+2){display:none} #over .card{gap:8px} #over .cta a:not(.alt){padding:12px} }\n  @media (max-height:600px){ #over .cta p span{display:none} #over .cta{gap:8px} }\n  .cta a.alt{background:none;color:#CFE3D7;font-family:Inter,system-ui,sans-serif;font-weight:600;font-size:14px;padding:2px;margin-top:-4px;text-decoration:underline;text-underline-offset:3px}\n  .cta a.alt:hover{background:none;color:#fff}\n  .row{display:flex;gap:6px;align-items:center;justify-content:center;flex-wrap:wrap}\n  .copied{font-size:13px;color:var(--green);font-weight:600}\n  .sharebox{width:100%;box-sizing:border-box;font:inherit;font-size:13px;border:1px solid var(--line);border-radius:10px;padding:8px;resize:none}\n  @media (max-width:560px){ .foot .keys{display:none} .app{padding-inline:10px} }\n  @media (prefers-reduced-motion: reduce){ .card{animation:none} }\n  \/* inside the WordPress page (iframe): the site header already carries the brand *\/\n  html.embed .brand, html.embed .foot{display:none}\n  html.embed .top{justify-content:flex-end}\n  html.embed .app{max-width:none;padding-block:8px 10px}\n  html.embed.playing .stage, html.embed.playing .pad{touch-action:none}\n  html.over .pad{display:none !important}\n  \/* phones in the page: the start card sits right under the sound buttons, so Ba\u015fla is visible without scrolling *\/\n  @media (pointer:coarse) and (orientation:portrait){ html.embed #start{align-items:start;padding-top:2px} html.embed #start .card{margin:0 auto auto} }\n  html.embed body{background:transparent}\n  \/* desktop inside the site: buttons sit on the dark ground band, no extra row above the game *\/\n  html.desk .app{position:relative;padding:6px}\n  html.desk .top{position:absolute;z-index:3;right:20px;bottom:20px}\n  html.desk .tbtn{background:rgba(255,255,255,.1);border-color:rgba(255,255,255,.2);color:#fff}\n  html.desk .tbtn.off{color:rgba(255,255,255,.6);opacity:1}\n  html.desk .tbtn:hover{background:rgba(255,255,255,.18)}\n  html.desk.over .top{display:none}\n  .rank-label{display:none}\n  @media (min-width:900px){ #over .card{max-width:460px} #over h2,#over .praise{text-wrap:balance} }\n  .col-a,.col-b{display:flex;flex-direction:column;align-items:center;gap:inherit;width:100%}\n  #over .row{gap:14px}\n  #over .primary{padding:13px 26px}\n  @media (max-height:780px){ #over .pbars{display:none} #over .big-rank{font-size:48px} #over .card{gap:10px;padding-block:18px} #over .cta{padding:14px;gap:10px} #over .notes li{font-size:13px} }\n  @media (max-height:700px){ #over .notes li:nth-child(n+2){display:none} #over .notes li{font-size:12.5px} #over .card{gap:8px;padding-block:14px 20px} #over .big-rank{font-size:44px} #over .cta{padding:12px;gap:8px} }\n  @media (max-width:340px){ .card{padding:18px 14px} h1{font-size:25px} .legend{gap:6px} .legend &gt; div{padding:9px 5px 7px} .legend .sub{font-size:10px} }\n  @media (max-height:600px){ #oBadges{display:none !important} }\n  @media (max-height:640px){ #over .notes{display:none} #over .praise{font-size:14px} #over .big-rank{font-size:42px} #start .card{gap:10px;padding-block:16px} .legend .sub{display:none} #over .cta p{font-size:14px} }\n  @media (max-height:480px) and (orientation:landscape){\n    .card{max-width:700px;flex-direction:row;align-items:center;gap:22px;padding:18px 22px}\n    .col-a,.col-b{flex:1;gap:10px}\n    #over .pbars,#over .notes{display:none} #over .praise{display:block}\n    #over .big-rank{font-size:40px}\n    h1{font-size:28px}\n    .foot{display:none}\n  }\n&lt;\/style&gt;\n&lt;\/head&gt;\n&lt;body&gt;\n\n&lt;div class=&quot;app&quot; lang=&quot;tr&quot;&gt;\n  &lt;div class=&quot;top&quot;&gt;\n    &lt;div class=&quot;brand&quot;&gt;\n      &lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; aria-hidden=&quot;true&quot;&gt;&lt;defs&gt;&lt;linearGradient id=&quot;bg1&quot; x1=&quot;0&quot; y1=&quot;0&quot; x2=&quot;1&quot; y2=&quot;1&quot;&gt;&lt;stop offset=&quot;0&quot; stop-color=&quot;#1FB06C&quot;\/&gt;&lt;stop offset=&quot;1&quot; stop-color=&quot;#027A48&quot;\/&gt;&lt;\/linearGradient&gt;&lt;\/defs&gt;&lt;circle cx=&quot;12&quot; cy=&quot;12&quot; r=&quot;8&quot; fill=&quot;none&quot; stroke=&quot;url(#bg1)&quot; stroke-width=&quot;5&quot; stroke-dasharray=&quot;44 6.3&quot; transform=&quot;rotate(180 12 12)&quot;\/&gt;&lt;\/svg&gt;\n      SEOliva\n    &lt;\/div&gt;\n    &lt;div class=&quot;tbtns&quot;&gt;&lt;button class=&quot;tbtn pbtn&quot; id=&quot;pauseBtn&quot; type=&quot;button&quot; aria-label=&quot;Duraklat&quot; hidden&gt;&lt;svg width=&quot;12&quot; height=&quot;14&quot; viewBox=&quot;0 0 14 16&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;1&quot; y=&quot;1&quot; width=&quot;4&quot; height=&quot;14&quot; rx=&quot;1.5&quot; fill=&quot;currentColor&quot;\/&gt;&lt;rect x=&quot;9&quot; y=&quot;1&quot; width=&quot;4&quot; height=&quot;14&quot; rx=&quot;1.5&quot; fill=&quot;currentColor&quot;\/&gt;&lt;\/svg&gt;&lt;\/button&gt;&lt;button class=&quot;tbtn&quot; id=&quot;musBtn&quot; type=&quot;button&quot;&gt;M\u00fczik a\u00e7\u0131k&lt;\/button&gt;&lt;button class=&quot;tbtn&quot; id=&quot;sndBtn&quot; type=&quot;button&quot;&gt;Ses a\u00e7\u0131k&lt;\/button&gt;&lt;\/div&gt;\n  &lt;\/div&gt;\n\n  &lt;div class=&quot;stage&quot; id=&quot;stage&quot;&gt;\n    &lt;canvas id=&quot;game&quot; aria-label=&quot;Google&#039;da Birinci Ol oyun alan\u0131&quot;&gt;&lt;\/canvas&gt;\n\n    &lt;div class=&quot;overlay dim&quot; id=&quot;start&quot; role=&quot;dialog&quot; aria-modal=&quot;true&quot; aria-label=&quot;Oyuna ba\u015fla&quot;&gt;\n      &lt;div class=&quot;card&quot;&gt;\n        &lt;div class=&quot;col-a&quot;&gt;\n        &lt;h1&gt;Google&#039;da &lt;em&gt;Birinci Ol&lt;\/em&gt;&lt;\/h1&gt;\n        &lt;p class=&quot;lede&quot;&gt;Siteni 100. s\u0131radan 1. s\u0131raya ta\u015f\u0131.&lt;\/p&gt;\n        &lt;div class=&quot;legend&quot;&gt;\n          &lt;div class=&quot;good&quot;&gt;\n            &lt;div class=&quot;icons&quot;&gt;\n              &lt;svg width=&quot;26&quot; height=&quot;32&quot; viewBox=&quot;0 0 28 34&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3 3h15l7 7v21H3z&quot; fill=&quot;#fff&quot; stroke=&quot;#039358&quot; stroke-width=&quot;2.4&quot;\/&gt;&lt;path d=&quot;M18 3v7h7&quot; fill=&quot;#BFE5CF&quot;\/&gt;&lt;path d=&quot;M8 17h12M8 22h12M8 27h7&quot; stroke=&quot;#039358&quot; stroke-width=&quot;2.2&quot; stroke-linecap=&quot;round&quot;\/&gt;&lt;\/svg&gt;\n              &lt;svg width=&quot;30&quot; height=&quot;30&quot; viewBox=&quot;0 0 32 32&quot; aria-hidden=&quot;true&quot;&gt;&lt;circle cx=&quot;16&quot; cy=&quot;16&quot; r=&quot;14&quot; fill=&quot;#6A5AE0&quot;\/&gt;&lt;g transform=&quot;rotate(-45 16 16)&quot; fill=&quot;none&quot; stroke=&quot;#fff&quot; stroke-width=&quot;2.6&quot;&gt;&lt;rect x=&quot;6.5&quot; y=&quot;12.8&quot; width=&quot;11&quot; height=&quot;6.4&quot; rx=&quot;3.2&quot;\/&gt;&lt;rect x=&quot;14.5&quot; y=&quot;12.8&quot; width=&quot;11&quot; height=&quot;6.4&quot; rx=&quot;3.2&quot;\/&gt;&lt;\/g&gt;&lt;\/svg&gt;\n            &lt;\/div&gt;\n            &lt;b&gt;Topla&lt;\/b&gt;\n            &lt;small class=&quot;sub&quot;&gt;\u00d6zg\u00fcn i\u00e7erik \u00b7 Link&lt;\/small&gt;\n          &lt;\/div&gt;\n          &lt;div&gt;\n            &lt;div class=&quot;icons&quot;&gt;\n              &lt;svg width=&quot;28&quot; height=&quot;32&quot; viewBox=&quot;0 0 30 34&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3 3h15l7 7v21H3z&quot; fill=&quot;#FBB9A4&quot; stroke=&quot;#E4572E&quot; stroke-width=&quot;2.2&quot;\/&gt;&lt;path d=&quot;M7 14l4 2M20 14l-4 2&quot; stroke=&quot;#8A2410&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot;\/&gt;&lt;circle cx=&quot;10&quot; cy=&quot;19&quot; r=&quot;1.8&quot; fill=&quot;#8A2410&quot;\/&gt;&lt;circle cx=&quot;17&quot; cy=&quot;19&quot; r=&quot;1.8&quot; fill=&quot;#8A2410&quot;\/&gt;&lt;path d=&quot;M11 27a3.5 3.5 0 0 1 6 0&quot; stroke=&quot;#8A2410&quot; stroke-width=&quot;2&quot; fill=&quot;none&quot; stroke-linecap=&quot;round&quot;\/&gt;&lt;\/svg&gt;\n              &lt;svg width=&quot;34&quot; height=&quot;28&quot; viewBox=&quot;0 0 34 28&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;1&quot; y=&quot;4&quot; width=&quot;30&quot; height=&quot;22&quot; rx=&quot;4&quot; fill=&quot;#F27A3A&quot;\/&gt;&lt;path d=&quot;M4 7l13 10L30 7&quot; fill=&quot;none&quot; stroke=&quot;#fff&quot; stroke-width=&quot;2&quot; stroke-linejoin=&quot;round&quot;\/&gt;&lt;path d=&quot;M9 18l4 1.6M23 18l-4 1.6&quot; stroke=&quot;#5E1A00&quot; stroke-width=&quot;1.8&quot; stroke-linecap=&quot;round&quot;\/&gt;&lt;circle cx=&quot;12&quot; cy=&quot;21.5&quot; r=&quot;1.6&quot; fill=&quot;#5E1A00&quot;\/&gt;&lt;circle cx=&quot;20&quot; cy=&quot;21.5&quot; r=&quot;1.6&quot; fill=&quot;#5E1A00&quot;\/&gt;&lt;circle cx=&quot;29&quot; cy=&quot;5&quot; r=&quot;5&quot; fill=&quot;#E4572E&quot;\/&gt;&lt;path d=&quot;M29 2.5v3&quot; stroke=&quot;#fff&quot; stroke-width=&quot;1.8&quot; stroke-linecap=&quot;round&quot;\/&gt;&lt;circle cx=&quot;29&quot; cy=&quot;7.4&quot; r=&quot;.9&quot; fill=&quot;#fff&quot;\/&gt;&lt;\/svg&gt;\n            &lt;\/div&gt;\n            &lt;b&gt;Ka\u00e7&lt;\/b&gt;\n            &lt;small class=&quot;sub&quot;&gt;Kopya \u00b7 Spam&lt;\/small&gt;\n          &lt;\/div&gt;\n        &lt;\/div&gt;\n        &lt;\/div&gt;\n        &lt;div class=&quot;col-b&quot;&gt;\n        &lt;p class=&quot;tip&quot;&gt;Algoritma s\u0131k s\u0131k kural de\u011fi\u015ftirir. Kurala en h\u0131zl\u0131 uyan y\u00fckselir.&lt;\/p&gt;\n        &lt;button class=&quot;primary&quot; id=&quot;startBtn&quot; type=&quot;button&quot;&gt;Ba\u015fla&lt;\/button&gt;\n        &lt;div class=&quot;tap&quot; id=&quot;lvlTag&quot; hidden&gt;&lt;\/div&gt;\n        &lt;div class=&quot;tap ctl&quot; id=&quot;ctlTip&quot;&gt;Ekrana dokun = z\u0131pla&lt;\/div&gt;\n        &lt;\/div&gt;\n      &lt;\/div&gt;\n    &lt;\/div&gt;\n\n    &lt;div class=&quot;overlay dim&quot; id=&quot;pause&quot; role=&quot;dialog&quot; aria-modal=&quot;true&quot; aria-label=&quot;Oyun duraklat\u0131ld\u0131&quot; hidden&gt;\n      &lt;div class=&quot;card&quot;&gt;\n        &lt;h2&gt;Duraklat\u0131ld\u0131&lt;\/h2&gt;\n        &lt;p class=&quot;psub&quot;&gt;S\u0131ran ve canlar\u0131n bekliyor.&lt;\/p&gt;\n        &lt;button class=&quot;primary&quot; id=&quot;resumeBtn&quot; type=&quot;button&quot;&gt;Devam et&lt;\/button&gt;\n      &lt;\/div&gt;\n    &lt;\/div&gt;\n    &lt;div class=&quot;overlay dim&quot; id=&quot;over&quot; role=&quot;dialog&quot; aria-modal=&quot;true&quot; aria-label=&quot;Oyun sonucu&quot; hidden&gt;\n      &lt;div class=&quot;card&quot;&gt;\n        &lt;div class=&quot;col-a&quot;&gt;\n          &lt;div class=&quot;climb&quot;&gt;&lt;s&gt;#100&lt;\/s&gt;&lt;span&gt;\u2192&lt;\/span&gt;&lt;span id=&quot;oTo&quot;&gt;#1&lt;\/span&gt;&lt;span class=&quot;up&quot; id=&quot;oUp&quot;&gt;0 s\u0131ra y\u00fckseldin&lt;\/span&gt;&lt;\/div&gt;\n          &lt;div class=&quot;rank-label&quot; id=&quot;oLabel&quot;&gt;En iyi s\u0131ran&lt;\/div&gt;\n          &lt;div class=&quot;big-rank&quot; id=&quot;oRank&quot;&gt;#1&lt;\/div&gt;\n          &lt;p class=&quot;praise&quot; id=&quot;oPraise&quot;&gt;&lt;\/p&gt;\n          &lt;div id=&quot;oBadges&quot; hidden&gt;&lt;\/div&gt;\n          &lt;div class=&quot;pbars&quot; id=&quot;oBars&quot;&gt;&lt;\/div&gt;\n          &lt;ul class=&quot;notes&quot; id=&quot;oNotes&quot;&gt;&lt;\/ul&gt;\n        &lt;\/div&gt;\n        &lt;div class=&quot;col-b&quot;&gt;\n          &lt;div class=&quot;cta&quot;&gt;\n            &lt;p&gt;&lt;b id=&quot;ctaTitle&quot;&gt;Ya ger\u00e7ek siten ka\u00e7\u0131nc\u0131?&lt;\/b&gt;&lt;span id=&quot;ctaSub&quot;&gt;Sitenin Google&#039;da bug\u00fcn ka\u00e7\u0131nc\u0131 oldu\u011funu S\u0131ra Bulucu ile \u00fccretsiz g\u00f6r.&lt;\/span&gt;&lt;\/p&gt;\n            &lt;a id=&quot;ctaLink&quot; href=&quot;https:\/\/www.seoliva.com\/sira-bulucu?kaynak=ilk-sira-oyunu&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Ger\u00e7ek s\u0131ran\u0131 \u00fccretsiz bul&lt;\/a&gt;\n            &lt;a id=&quot;ctaAlt&quot; class=&quot;alt&quot; href=&quot;https:\/\/www.seoliva.com\/iletisim?kaynak=ilk-sira-oyunu&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;ya da SEOliva ile konu\u015f&lt;\/a&gt;\n          &lt;\/div&gt;\n          &lt;div class=&quot;row&quot;&gt;&lt;button class=&quot;primary&quot; id=&quot;againBtn&quot; type=&quot;button&quot;&gt;Tekrar oyna&lt;\/button&gt;&lt;button class=&quot;link&quot; id=&quot;copyBtn&quot; type=&quot;button&quot;&gt;Skorunu payla\u015f&lt;\/button&gt;&lt;span class=&quot;copied&quot; id=&quot;copied&quot; hidden&gt;Kopyaland\u0131&lt;\/span&gt;&lt;\/div&gt;\n          &lt;textarea class=&quot;sharebox&quot; id=&quot;shareBox&quot; aria-label=&quot;Payla\u015f\u0131m metni&quot; rows=&quot;2&quot; readonly hidden&gt;&lt;\/textarea&gt;\n        &lt;\/div&gt;\n      &lt;\/div&gt;\n    &lt;\/div&gt;\n  &lt;\/div&gt;\n\n  &lt;div class=&quot;pad&quot; id=&quot;pad&quot; aria-hidden=&quot;true&quot;&gt;&lt;svg width=&quot;22&quot; height=&quot;22&quot; viewBox=&quot;0 0 24 24&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M12 19V6M6 11l6-6 6 6&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2.6&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;\/&gt;&lt;\/svg&gt;&lt;span&gt;&lt;b&gt;Z\u0131plamak i\u00e7in buraya dokun&lt;\/b&gt;&lt;small&gt;Bas\u0131l\u0131 tut, daha y\u00fckse\u011fe z\u0131pla&lt;\/small&gt;&lt;\/span&gt;&lt;\/div&gt;\n  &lt;div class=&quot;foot&quot;&gt;\n    &lt;span class=&quot;keys&quot;&gt;Dokun ya da Bo\u015fluk: z\u0131pla \u00b7 Uzun bas: daha y\u00fckse\u011fe \u00b7 Havada tekrar: \u00e7ift z\u0131plama&lt;\/span&gt;\n    &lt;a href=&quot;https:\/\/www.seoliva.com\/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;seoliva.com&lt;\/a&gt;\n  &lt;\/div&gt;\n&lt;\/div&gt;\n\n&lt;script&gt;\n(() =&gt; {\n  \/\/ ================= constants =================\n  const C = { ink:&#039;#04281c&#039;, green:&#039;#039358&#039;, green2:&#039;#1FB06C&#039;, deep:&#039;#046A40&#039;, lime:&#039;#c9f24e&#039;, muted:&#039;#5A7266&#039;, danger:&#039;#E4572E&#039;, spam:&#039;#F07A1A&#039;, white:&#039;#ffffff&#039;, teal:&#039;#138DA8&#039;, violet:&#039;#6A5AE0&#039;, navy:&#039;#23407A&#039; };\n  const WEAK = 25;   \/\/ one threshold for red gauge, neglect bleed and the update check\n  const UNIT_CAP = { c:&#039;Sayfa&#039;, t:&#039;\u015eim\u015fek&#039;, a:&#039;Link&#039; };\n  const PIL = { c:{ name:&#039;\u0130\u00e7erik&#039;, low:&#039;i\u00e7eri\u011fin&#039;, col:C.green }, t:{ name:&#039;Teknik&#039;, low:&#039;tekni\u011fin&#039;, col:C.teal }, a:{ name:&#039;Otorite&#039;, low:&#039;otoriten&#039;, col:C.violet } };\n  const KIND_PIL = { doc:&#039;c&#039;, bolt:&#039;t&#039;, link:&#039;a&#039; };\n  const GRAV = 2300, JUMP = -760, JUMP2 = -680;\n  const AIR = 2 * (-JUMP) \/ GRAV;\n  const K = 520;                        \/\/ #1 needs ~2400 points: about 2-2.5 minutes of good play\n  const BOSS_LEN = 32;\n  const RING_START = Math.PI, RING_SPAN = Math.PI * 2 * 0.88;\n  const WORDS = [[5, &#039;S\u00fcper!&#039;], [10, &#039;Harika!&#039;], [15, &#039;Muhte\u015fem!&#039;], [20, &#039;Efsane!&#039;], [30, &#039;Durdurulamaz!&#039;]];\n  const reduceMotion = window.matchMedia &amp;&amp; matchMedia(&#039;(prefers-reduced-motion: reduce)&#039;).matches;\n\n  const BANDS = [\n    { top:[241,246,243], bot:[213,224,218], glow:0,    ringA:0.05, cardA:0.45 },\n    { top:[236,250,242], bot:[188,229,205], glow:0.15, ringA:0.09, cardA:0.62 },\n    { top:[251,255,236], bot:[214,243,196], glow:0.4,  ringA:0.11, cardA:0.78 },\n    { top:[8,50,36],     bot:[4,32,23],     glow:0.25, ringA:0.12, cardA:0.1 }\n  ];\n  const PAGE_KEYS = [\n    [10, { top:[226,232,236], bot:[196,206,212], glow:0,    ringA:0.05, cardA:0.36 }],\n    [7,  { top:[226,241,238], bot:[182,215,208], glow:0.04, ringA:0.07, cardA:0.48 }],\n    [4,  { top:[232,247,238], bot:[176,226,197], glow:0.15, ringA:0.09, cardA:0.6 }],\n    [2,  { top:[244,252,232], bot:[198,238,180], glow:0.3,  ringA:0.1,  cardA:0.72 }],\n    [1,  { top:[255,247,214], bot:[236,238,172], glow:0.55, ringA:0.1,  cardA:0.85 }]\n  ];\n  function pageVis(pg){\n    for (let i = 0; i &lt; PAGE_KEYS.length - 1; i++){\n      const [a, A] = PAGE_KEYS[i], [b, B] = PAGE_KEYS[i + 1];\n      if (pg &lt;= a &amp;&amp; pg &gt;= b){ const k = a === b ? 0 : (a - pg) \/ (a - b), f = (x, y) =&gt; x + (y - x) * k;\n        return { top:A.top.map((x, j) =&gt; f(x, B.top[j])), bot:A.bot.map((x, j) =&gt; f(x, B.bot[j])), glow:f(A.glow, B.glow), ringA:f(A.ringA, B.ringA), cardA:f(A.cardA, B.cardA) }; }\n    }\n    return PAGE_KEYS[PAGE_KEYS.length - 1][1];\n  }\n  const rankToP = r =&gt; K * Math.log(100 \/ (Math.max(1, r) - 0.5));\n  const rankOf = P =&gt; Math.max(1, Math.ceil(100 * Math.exp(-Math.max(0, P) \/ K)));\n  const clamp = (v, a, b) =&gt; Math.max(a, Math.min(b, v));\n  const rand = (a, b) =&gt; a + Math.random() * (b - a);\n  const ease = t =&gt; 1 - Math.pow(1 - t, 3);\n  const shuffle = a =&gt; { for (let i = a.length - 1; i &gt; 0; i--){ const j = Math.floor(Math.random() * (i + 1)); [a[i], a[j]] = [a[j], a[i]]; } return a; };\n\n  \/\/ ================= dom =================\n  const $ = id =&gt; document.getElementById(id);\n  const stage = $(&#039;stage&#039;), cv = $(&#039;game&#039;), ctx = cv.getContext(&#039;2d&#039;);\n  const TOUCH = window.matchMedia &amp;&amp; matchMedia(&#039;(pointer:coarse)&#039;).matches, TAP = TOUCH ? &#039;dokun&#039; : &#039;bas&#039;;\n  const startEl = $(&#039;start&#039;), overEl = $(&#039;over&#039;);\n  const store = {\n    get(k){ try { return localStorage.getItem(k); } catch(e){ return null; } },\n    set(k, v){ try { localStorage.setItem(k, v); } catch(e){} }\n  };\n  let best = parseInt(store.get(&#039;ak5_best&#039;) || &#039;0&#039;, 10) || null;\n\n  \/\/ ================= measurement (GA4 \/ GTM \/ Meta Pixel, if present on the page) =================\n  \/\/ inside the WordPress page the game runs in an iframe: report to the page&#039;s own analytics\n  const EMBED = (() =&gt; { try { return window.self !== window.top; } catch(e){ return true; } })();\n  const HOST = (() =&gt; { try { return EMBED &amp;&amp; window.parent.document ? window.parent : window; } catch(e){ return window; } })();\n  if (EMBED) document.documentElement.classList.add(&#039;embed&#039;);\n  function track(name, params = {}){\n    const ev = &#039;ak_&#039; + name;\n    try { if (typeof HOST.gtag === &#039;function&#039;) HOST.gtag(&#039;event&#039;, ev, params); else (HOST.dataLayer = HOST.dataLayer || []).push(Object.assign({ event:ev }, params)); } catch(e){}\n    try { if (typeof HOST.fbq === &#039;function&#039;) HOST.fbq(&#039;trackCustom&#039;, ev, params); } catch(e){}\n  }\n  let runs = 0;\n  let tipsSeen = store.get(&#039;ak_tips&#039;) === &#039;1&#039;;\n\n  \/\/ ================= sound =================\n  \/\/ everything goes through one bus with a compressor, so hits, music and stingers sit together and punch\n  const SCALE = [523, 587, 659, 784, 880, 1047, 1175, 1319, 1568, 1760, 2093];\n  const snd = {\n    ac:null, bus:null, nb:null, on: store.get(&#039;ak_snd&#039;) !== &#039;0&#039;,\n    init(){\n      if (!this.ac){ try { this.ac = new (window.AudioContext || window.webkitAudioContext)(); } catch(e){} }\n      if (this.ac &amp;&amp; !this.bus){\n        try {\n          const c = this.ac, comp = c.createDynamicsCompressor();\n          comp.threshold.value = -16; comp.knee.value = 10; comp.ratio.value = 4; comp.attack.value = 0.004; comp.release.value = 0.18;\n          this.bus = c.createGain(); this.bus.gain.value = 1.35; this.bus.connect(comp); comp.connect(c.destination); this.comp = comp;\n          const len = Math.floor(c.sampleRate * 0.6); this.nb = c.createBuffer(1, len, c.sampleRate); const ch = this.nb.getChannelData(0); for (let k = 0; k &lt; len; k++) ch[k] = Math.random() * 2 - 1;\n        } catch(e){}\n      }\n      if (this.ac &amp;&amp; this.ac.state === &#039;suspended&#039;){ const pr = this.ac.resume(); if (pr &amp;&amp; pr.catch) pr.catch(() =&gt; {}); }\n    },\n    out(){ return this.bus || this.ac.destination; },\n    note(f, dur = 0.3, vol = 0.07, delay = 0, type = &#039;sine&#039;){\n      if (!this.on || !this.ac) return;\n      try {\n        const c = this.ac, t = c.currentTime + delay;\n        const o = c.createOscillator(), o2 = c.createOscillator(), gn = c.createGain(), g2 = c.createGain();\n        o.type = type; o.frequency.setValueAtTime(f, t);\n        o2.type = &#039;sine&#039;; o2.frequency.setValueAtTime(f * 4, t);\n        gn.gain.setValueAtTime(0.0001, t); gn.gain.exponentialRampToValueAtTime(vol, t + 0.006); gn.gain.exponentialRampToValueAtTime(0.0001, t + dur);\n        g2.gain.setValueAtTime(vol * 0.3, t); g2.gain.exponentialRampToValueAtTime(0.0001, t + 0.07);\n        o.connect(gn); o2.connect(g2); gn.connect(this.out()); g2.connect(this.out());\n        o.start(t); o2.start(t); o.stop(t + dur + 0.05); o2.stop(t + 0.1);\n      } catch(e){}\n    },\n    slide(f1, f2, dur, type = &#039;triangle&#039;, vol = 0.05, delay = 0){\n      if (!this.on || !this.ac) return;\n      try {\n        const c = this.ac, t = c.currentTime + delay, o = c.createOscillator(), gn = c.createGain();\n        o.type = type; o.frequency.setValueAtTime(f1, t); o.frequency.exponentialRampToValueAtTime(f2, t + dur);\n        gn.gain.setValueAtTime(vol, t); gn.gain.exponentialRampToValueAtTime(0.0001, t + dur);\n        o.connect(gn); gn.connect(this.out()); o.start(t); o.stop(t + dur + 0.05);\n      } catch(e){}\n    },\n    \/\/ filtered noise: f1\u2192f2 sweep, used for whooshes, risers, crashes and crunches\n    noise(dur, vol, f1, f2, type = &#039;bandpass&#039;, delay = 0, q = 1.2){\n      if (!this.on || !this.ac || !this.nb) return;\n      try {\n        const c = this.ac, t = c.currentTime + delay, s0 = c.createBufferSource(), fl = c.createBiquadFilter(), gn = c.createGain();\n        s0.buffer = this.nb; s0.loop = true; fl.type = type; fl.Q.value = q;\n        fl.frequency.setValueAtTime(f1, t); fl.frequency.exponentialRampToValueAtTime(f2, t + dur);\n        gn.gain.setValueAtTime(0.0001, t); gn.gain.exponentialRampToValueAtTime(vol, t + Math.min(0.02, dur * 0.3)); gn.gain.exponentialRampToValueAtTime(0.0001, t + dur);\n        s0.connect(fl); fl.connect(gn); gn.connect(this.out()); s0.start(t); s0.stop(t + dur + 0.05);\n      } catch(e){}\n    },\n    \/\/ chord stab: detuned saws through a closing low-pass, the &quot;brass hit&quot; of arcade games\n    stab(fs, dur = 0.5, vol = 0.05, delay = 0){\n      if (!this.on || !this.ac) return;\n      try {\n        const c = this.ac, t = c.currentTime + delay, fl = c.createBiquadFilter(), gn = c.createGain();\n        fl.type = &#039;lowpass&#039;; fl.frequency.setValueAtTime(4200, t); fl.frequency.exponentialRampToValueAtTime(500, t + dur);\n        gn.gain.setValueAtTime(0.0001, t); gn.gain.exponentialRampToValueAtTime(vol, t + 0.01); gn.gain.exponentialRampToValueAtTime(0.0001, t + dur);\n        fl.connect(gn); gn.connect(this.out());\n        for (const f of fs) for (const d of [-7, 7]){ const o = c.createOscillator(); o.type = &#039;sawtooth&#039;; o.frequency.value = f; o.detune.value = d; o.connect(fl); o.start(t); o.stop(t + dur + 0.05); }\n      } catch(e){}\n    },\n    boom(vol = 0.5, delay = 0){ this.slide(150, 38, 0.45, &#039;sine&#039;, vol, delay); this.noise(0.5, vol * 0.35, 3000, 400, &#039;lowpass&#039;, delay, 0.7); },\n    pop(combo){\n      const f = SCALE[Math.min(combo, SCALE.length - 1)];\n      this.note(f, 0.26, 0.085, 0, &#039;triangle&#039;); this.note(f * 2, 0.16, 0.03);\n      if (combo &gt;= 3) this.note(f * 1.5, 0.18, 0.035, 0.05);\n      this.noise(0.05, 0.05, 6000, 9000, &#039;highpass&#039;);\n    },\n    rankUp(n){ const f = 784 * Math.pow(2, Math.min(n, 14) \/ 12); this.note(f, 0.14, 0.05, 0.04, &#039;square&#039;); this.note(f * 1.5, 0.22, 0.045, 0.1, &#039;square&#039;); },\n    jump(){ this.slide(260, 560, 0.1, &#039;triangle&#039;, 0.04); this.noise(0.08, 0.02, 1500, 4000, &#039;bandpass&#039;); },\n    word(){ [0, 4, 7, 12].forEach((k, i) =&gt; this.note(523 * Math.pow(2, k \/ 12), 0.45, 0.07, i * 0.06, &#039;triangle&#039;)); this.noise(0.35, 0.04, 2000, 9000, &#039;highpass&#039;); },\n    hit(){ this.slide(180, 45, 0.3, &#039;sine&#039;, 0.4); this.slide(240, 70, 0.25, &#039;sawtooth&#039;, 0.06); this.noise(0.22, 0.2, 2500, 300, &#039;lowpass&#039;, 0, 0.8); },\n    warn(){ for (let i = 0; i &lt; 3; i++){ this.note(988, 0.13, 0.06, i * 0.26, &#039;square&#039;); this.note(740, 0.13, 0.05, i * 0.26 + 0.13, &#039;square&#039;); } this.noise(1.2, 0.08, 400, 6000, &#039;bandpass&#039;, 0.2, 3); },\n    impact(){ this.boom(0.55); this.noise(0.9, 0.12, 9000, 3000, &#039;highpass&#039;, 0, 0.5); this.stab([220, 262, 330], 0.6, 0.05); },\n    good(){ this.stab([523, 659, 784], 0.35, 0.05); this.stab([587, 740, 880], 0.5, 0.05, 0.16); [0, 4, 7, 12, 16].forEach((k, i) =&gt; this.note(1047 * Math.pow(2, k \/ 12), 0.3, 0.04, 0.3 + i * 0.06)); },\n    big(){ this.noise(0.5, 0.1, 500, 8000, &#039;bandpass&#039;, 0, 2); this.boom(0.45, 0.02); },\n    meh(){ this.stab([392, 466], 0.35, 0.04); this.stab([330, 392], 0.6, 0.04, 0.2); this.slide(200, 90, 0.5, &#039;sine&#039;, 0.2, 0.2); },\n    fanfare(){ [523, 659, 784, 1047, 1319].forEach((f, i) =&gt; this.note(f, 0.5, 0.075, i * 0.09, &#039;triangle&#039;)); this.stab([523, 659, 784, 1047], 0.9, 0.05, 0.45); this.noise(1.1, 0.07, 9000, 4000, &#039;highpass&#039;, 0.45, 0.5); },\n    end(){ [659, 523, 392].forEach((f, i) =&gt; this.note(f, 0.5, 0.07, i * 0.14, &#039;triangle&#039;)); }\n  };\n  \/\/ procedural soundtrack: calm groove, a driving beat in updates, a duel beat in the final.\n  \/\/ drums duck the rest (side-chain pump), a pad gives body, mode changes land on an impact\n  const music = {\n    ac:null, gain:null, pump:null, timer:null, step:0, next:0, mode:&#039;calm&#039;, played:&#039;calm&#039;, on: store.get(&#039;ak_mus&#039;) !== &#039;0&#039;,\n    start(){\n      if (!snd.on || !this.on || !snd.ac) return;\n      this.ac = snd.ac;\n      if (!this.gain){ this.gain = this.ac.createGain(); this.gain.gain.value = 0.0001; this.gain.connect(snd.out()); this.pump = this.ac.createGain(); this.pump.connect(this.gain); }\n      const t = this.ac.currentTime; this.gain.gain.cancelScheduledValues(t); this.gain.gain.setValueAtTime(Math.max(0.0001, this.gain.gain.value), t); this.gain.gain.linearRampToValueAtTime(this.level(), t + 0.8);\n      if (this.timer) return;\n      this.next = t + 0.1; this.step = 0; this.played = this.mode; this.timer = setInterval(() =&gt; this.tick(), 25);\n    },\n    level(){ return this.mode === &#039;calm&#039; ? 0.3 : this.mode === &#039;final&#039; ? 0.55 : 0.48; },\n    stop(){ if (!this.ac || !this.gain) return; const t = this.ac.currentTime; this.gain.gain.cancelScheduledValues(t); this.gain.gain.setValueAtTime(this.gain.gain.value, t); this.gain.gain.linearRampToValueAtTime(0.0001, t + 0.5); clearInterval(this.timer); this.timer = null; },\n    tick(){\n      if (this.mode !== this.played){ const up = this.mode !== &#039;calm&#039;; this.played = this.mode; this.step = 0; if (up) snd.impact(); const t0 = this.ac.currentTime; this.gain.gain.cancelScheduledValues(t0); this.gain.gain.setValueAtTime(Math.max(0.0001, this.gain.gain.value), t0); this.gain.gain.linearRampToValueAtTime(this.level(), t0 + (up ? 0.3 : 1.5)); }\n      const bpm = this.mode === &#039;final&#039; ? 136 : this.mode === &#039;update&#039; ? 128 : 112, eighth = 60 \/ bpm \/ 2;\n      while (this.next &lt; this.ac.currentTime + 0.12){ this.play(this.step, this.next, eighth); this.next += eighth; this.step++; }\n    },\n    play(i, t, eighth){\n      const m = this.mode, calm = m === &#039;calm&#039;;\n      const prog = m === &#039;final&#039; ? [[57,60,64],[53,57,60],[55,59,62],[52,56,59]] : [[57,60,64],[53,57,60],[48,52,55],[55,59,62]];\n      const chord = prog[Math.floor(i \/ 8) % 4], pos = i % 8, f = n =&gt; 440 * Math.pow(2, (n - 69) \/ 12);\n      \/\/ drums\n      const kick = calm ? (pos === 0 || pos === 4) : pos % 2 === 0;\n      if (kick){ this.kick(t, calm ? 0.14 : 0.24); this.duck(t); }\n      if (!calm &amp;&amp; (pos === 2 || pos === 6)) this.clap(t, m === &#039;final&#039; ? 0.12 : 0.09);\n      \n      if (pos % 2 === 1 &amp;&amp; (!calm || pos === 3 || pos === 7)) this.hat(t, calm ? 0.02 : 0.06);\n      if (m === &#039;final&#039; &amp;&amp; pos % 2 === 0) this.hat(t, 0.025);\n      \/\/ bass: quarter notes when calm, driving eighths otherwise\n      if (!calm || pos % 2 === 0) this.bass(f(chord[0] - 12 + (pos === 7 &amp;&amp; !calm ? 12 : 0)), t, calm ? 0.28 : 0.18, calm ? 0.06 : 0.07);\n      \/\/ pad on each chord change\n      if (pos === 0) this.pad(chord.map(n =&gt; f(n)), t, eighth * 8, calm ? 0.012 : 0.02);\n      \/\/ lead arpeggio\n      if (!calm) this.tone(f(chord[[0, 1, 2, 1, 0, 2, 1, 2][pos]] + 12), t, 0.18, &#039;sine&#039;, 0.05);\n      else if (pos === 0 || pos === 3) this.tone(f(chord[pos === 0 ? 2 : 1] + 12), t, 0.5, &#039;sine&#039;, 0.025);\n      if (m === &#039;final&#039; &amp;&amp; pos === 7 &amp;&amp; Math.floor(i \/ 8) % 4 === 3) snd.noise(0.5, 0.05, 500, 7000, &#039;bandpass&#039;, Math.max(0, t - this.ac.currentTime), 2);\n    },\n    duck(t){ const gp = this.pump.gain; gp.cancelScheduledValues(t); gp.setValueAtTime(0.5, t); gp.linearRampToValueAtTime(1, t + 0.2); },\n    tone(fq, t, d, type, v){ const o = this.ac.createOscillator(), gn = this.ac.createGain(); o.type = type; o.frequency.value = fq; gn.gain.setValueAtTime(0.0001, t); gn.gain.exponentialRampToValueAtTime(v, t + 0.01); gn.gain.exponentialRampToValueAtTime(0.0001, t + d); o.connect(gn); gn.connect(this.pump); o.start(t); o.stop(t + d + 0.02); },\n    bass(fq, t, d, v){ const c = this.ac, o = c.createOscillator(), o2 = c.createOscillator(), fl = c.createBiquadFilter(), gn = c.createGain(); o.type = &#039;sawtooth&#039;; o.frequency.value = fq; o2.type = &#039;sine&#039;; o2.frequency.value = fq; fl.type = &#039;lowpass&#039;; fl.frequency.setValueAtTime(900, t); fl.frequency.exponentialRampToValueAtTime(220, t + d); gn.gain.setValueAtTime(0.0001, t); gn.gain.exponentialRampToValueAtTime(v, t + 0.01); gn.gain.exponentialRampToValueAtTime(0.0001, t + d); o.connect(fl); o2.connect(fl); fl.connect(gn); gn.connect(this.pump); o.start(t); o2.start(t); o.stop(t + d + 0.02); o2.stop(t + d + 0.02); },\n    pad(fs, t, d, v){ const c = this.ac, fl = c.createBiquadFilter(), gn = c.createGain(); fl.type = &#039;lowpass&#039;; fl.frequency.value = 1000; gn.gain.setValueAtTime(0.0001, t); gn.gain.linearRampToValueAtTime(v, t + 0.25); gn.gain.setValueAtTime(v, t + d - 0.3); gn.gain.linearRampToValueAtTime(0.0001, t + d); fl.connect(gn); gn.connect(this.pump); for (const fq of fs) for (const dt of [-9, 9]){ const o = c.createOscillator(); o.type = &#039;sawtooth&#039;; o.frequency.value = fq; o.detune.value = dt; o.connect(fl); o.start(t); o.stop(t + d + 0.02); } },\n    src(t, d, v, type, fq, q){ const c = this.ac, s0 = c.createBufferSource(), fl = c.createBiquadFilter(), gn = c.createGain(); s0.buffer = snd.nb; fl.type = type; fl.frequency.value = fq; fl.Q.value = q; gn.gain.setValueAtTime(v, t); gn.gain.exponentialRampToValueAtTime(0.0001, t + d); s0.connect(fl); fl.connect(gn); gn.connect(this.gain); s0.start(t, Math.random() * 0.4); s0.stop(t + d + 0.02); },\n    hat(t, v){ if (snd.nb) this.src(t, 0.04, v, &#039;highpass&#039;, 7000, 0.7); },\n    clap(t, v){ if (snd.nb){ this.src(t, 0.14, v, &#039;bandpass&#039;, 1700, 1.4); this.src(t + 0.012, 0.1, v * 0.7, &#039;bandpass&#039;, 2400, 1.2); } },\n    kick(t, v){ const o = this.ac.createOscillator(), gn = this.ac.createGain(); o.frequency.setValueAtTime(150, t); o.frequency.exponentialRampToValueAtTime(45, t + 0.12); gn.gain.setValueAtTime(v, t); gn.gain.exponentialRampToValueAtTime(0.0001, t + 0.22); o.connect(gn); gn.connect(this.gain); o.start(t); o.stop(t + 0.24); }\n  };\n  const buzz = ms =&gt; { try { navigator.vibrate &amp;&amp; navigator.vibrate(ms); } catch(e){} };\n  function paintSnd(){ $(&#039;sndBtn&#039;).textContent = snd.on ? &#039;Ses a\u00e7\u0131k&#039; : &#039;Ses kapal\u0131&#039;; $(&#039;sndBtn&#039;).classList.toggle(&#039;off&#039;, !snd.on); $(&#039;musBtn&#039;).textContent = music.on ? &#039;M\u00fczik a\u00e7\u0131k&#039; : &#039;M\u00fczik kapal\u0131&#039;; $(&#039;musBtn&#039;).classList.toggle(&#039;off&#039;, !music.on); $(&#039;musBtn&#039;).disabled = !snd.on; if (!snd.on){ $(&#039;musBtn&#039;).textContent = &#039;M\u00fczik kapal\u0131&#039;; $(&#039;musBtn&#039;).classList.add(&#039;off&#039;); } }\n  paintSnd();\n\n  \/\/ ================= layout =================\n  let BTN_X = 1e4, W = 720, H = 400, GROUND = 336, PX = 110, SPEEDK = 1, HS = 1, PF = 1, JS = 1, scale = 1, dpr = 1;\n  const DESK_MQ = window.matchMedia ? window.matchMedia(&#039;(pointer:fine)&#039;) : null;\n  function resize(){\n    \/\/ desktop inside the site: the sound\/pause buttons live in the dark ground band, so the stage gets that row back\n    document.documentElement.classList.toggle(&#039;desk&#039;, EMBED &amp;&amp; window.innerWidth &gt;= 700 &amp;&amp; (!DESK_MQ || DESK_MQ.matches));\n    const r = stage.getBoundingClientRect();\n    if (!r.width || !r.height) return;\n    const rh = r.width &gt;= 700 ? Math.min(r.height, r.width \/ 1.5) : r.height, aspect = r.width \/ rh;\n    if (aspect &lt; 1){ W = 400; H = Math.round(clamp(W \/ aspect, 420, 600)); }\n    \/\/ big desktop frames: draw on a larger logical stage instead of blowing everything up (at most ~1.55x), so the HUD and messages keep their room\n    else { H = r.width &gt;= 900 ? Math.round(clamp(rh \/ 1.65, 400, 520)) : 400; W = Math.round(clamp(H * aspect, 460, 1150)); }\n    GROUND = H - 64;\n    PX = Math.round(r.width &gt;= 900 ? clamp(W * 0.35 - 19, 110, 420) : clamp(W * 0.2, 70, 130));   \/\/ desktop: the runner sits in the central third, where the eye is, with the road ahead in view\n    \/\/ same feel on every screen: the player always sees ~1.9 s ahead, and the same number of things per second\n    SPEEDK = clamp((W - PX) \/ (1.9 * 320), 0.5, 1);\n    HS = clamp(SPEEDK, 0.72, 1);          \/\/ horizontal spacing scale (never so tight that items overlap)\n    JS = clamp(Math.sqrt(0.86 \/ SPEEDK), 1, 1.3);  \/\/ slower screens: same jump height, a bit more hang time, same distance covered\n    PF = Math.pow(HS \/ SPEEDK, 1.35);                   \/\/ pickups arrive a little less often on narrow screens: each one counts a little more\n    scale = Math.min(r.width \/ W, rh \/ H);\n    dpr = Math.min(window.devicePixelRatio || 1, 2, Math.max(1, 2400 \/ (W * scale)));   \/\/ very large retina canvases: cap the pixel count, it is the main cost per frame\n    cv.style.width = (W * scale) + &#039;px&#039;;\n    cv.style.height = (H * scale) + &#039;px&#039;;\n    cv.width = Math.round(W * scale * dpr);\n    cv.height = Math.round(H * scale * dpr);\n    ctx.setTransform(scale * dpr, 0, 0, scale * dpr, 0, 0);\n    try { ctx.textRendering = &#039;geometricPrecision&#039;; } catch(e){}\n    SPEEDK = 1; HS = 1; PF = 1; JS = 1;\n    \/\/ centred runner on desktop: things come in slower, so the jump hangs a little longer (same height) to clear them just as easily\n    if (r.width &gt;= 900 &amp;&amp; aspect &gt;= 1) JS = clamp(Math.sqrt(W * 0.8 \/ (W - PX)), 1, 1.25);\n    if (g){ g.p.x = PX; if (g.p.onGround) g.p.y = GROUND - g.p.h; }\n    if (g) draw();\n    if (typeof placePause === &#039;function&#039;) placePause();\n  }\n\n  \/\/ ================= state =================\n  let state = &#039;start&#039;, g = null, seq = 0;\n  function newRun(){\n    g = {\n      t:0, speed:260, P:0, lives:3, inv:0, hitstop:0, slowmo:0, flash:0, shake:0,\n      p:{ x:PX, y:GROUND - 40, vy:0, w:38, h:40, onGround:true, jumps:0, squash:0, holding:false, blink:0 },\n      objs:[], parts:[], waves:[], pops:[], words:[], cards:[], rings:[], flyers:[],\n      pil:{ c:45, t:45, a:45 }, gotCalm:{ c:0, t:0, a:0 }, red:{ c:0, t:0, a:0 }, redTot:{ c:0, t:0, a:0 }, bleedN:{ c:0, t:0, a:0 }, bleedT:0, got:{ c:0, t:0, a:0 },\n      combo:0, maxCombo:0, lastPick:-9, wordIdx:0,\n      best:100, rankFlash:0, crown:false, pageMsg:{},\n      upd:{ cnt:{ c:0, t:0, a:0 }, wrongHint:false, phase:&#039;idle&#039;, timer:20, n:0, hits:0, ups:0, downs:0, gained:0, focus:&#039;&#039;, jitter:0, jT:0, rainT:0, spamN:0 },\n      vis:{ top:[226,232,236], bot:[196,206,212], glow:0, ringA:0.05, cardA:0.36 }, page:10, pgA:null, pageFx:0,\n      boss:{ active:false, done:false, t:0, L:20, waves:[], wi:-1, wave:null, str:{}, lastFlip:-9, wasLead:true },\n      msg:null, banner:null, outcome:null,\n      shields:0, coreHits:0, ri:-1, rp:&#039;intro&#039;, rT:0, cardT:2.6, resT:0, rr0:100, frac:0, rs:{ good:0, bad:0 }, coreGood:0, coreBad:0, coreUps:0, coreDowns:0, cleanSpam:0, spamHitsRule:0, heartGiven:false,\n      stats:{ orijinal:{ good:0, bad:0 }, hiz:{ good:0, bad:0 }, kirik:{ good:0, bad:0 }, core:{ good:0, bad:0 }, spam:{ good:0, bad:0 } },\n      nextSpawn:280, lastHeart:-99, lifeFx:0, bgOff:0, ending:0, glow:0, dark:0, reachT:0\n    };\n    for (let i = 0; i &lt; 3; i++) g.rings.push({ x:rand(0, W), r:rand(80, 150), y:rand(GROUND * 0.25, GROUND * 0.7), k:rand(0.05, 0.12) });\n  }\n  const curRank = () =&gt; (g.boss.active || g.boss.done) ? (g.boss.lead ? 1 : 2) : rankOf(g.P);\n  function balance(){ const v = [g.pil.c, g.pil.t, g.pil.a], mx = Math.max(...v); return mx &gt; 0 ? Math.min(...v) \/ mx : 0; }\n  const avgPil = () =&gt; (g.pil.c + g.pil.t + g.pil.a) \/ 300;\n\n  \/\/ ================= messages =================\n  function say(text, life = 1.6, tone = &#039;dark&#039;){ if (tone === &#039;red&#039; &amp;&amp; g.words.length) g.words = []; if (g.banner){ if (tone === &#039;red&#039;) g.pending = { text, life, tone, t:g.t }; return; } g.msg = { text, life, max:life, tone }; }\n  \/\/ a stacked column in the air looks like a wall to jump; the first few of each kind say what to do\n  function spamTip(k){ const t = g.tips || (g.tips = { lo:0, hi:0 }); return t[k]++ &lt; (k === &#039;hi&#039; ? 3 : 2) ? (k === &#039;hi&#039; ? &#039;ALTINDAN GE\u00c7&#039; : &#039;\u00dcST\u00dcNDEN ZIPLA&#039;) : undefined; }\n  function word(text, big = false){ if (g.boss.atak) return; if (!big &amp;&amp; (g.msg || g.bigWord || g.rp === &#039;result&#039; || g.rp === &#039;card&#039;)) return; if (big &amp;&amp; g.bigWord) return; if ((g.banner || g.boss.active || g.upd.phase === &#039;spam&#039; || g.upd.phase === &#039;warn&#039; || g.upd.phase === &#039;active&#039;) &amp;&amp; !big) return; const cur = g.words[0]; if (cur &amp;&amp; cur.big &amp;&amp; !big &amp;&amp; cur.t &lt; 0.9) return; g.words = [{ text, t:0, life:big ? 1.3 : 1.1, big }]; }\n  function banner(title, sub, tone = &#039;dark&#039;, life = 2.8){ g.banner = { title, sub, tone, life, max:life }; g.msg = null; g.words = []; }\n\n  \/\/ ================= spawning =================\n  function add(o){ o.id = ++seq; g.objs.push(o); return o; }\n  const SIZE = { doc:[24, 30], bolt:[28, 28], link:[28, 28] };\n  const item = (kind, x, y) =&gt; add({ kind, x, y, w:SIZE[kind][0], h:SIZE[kind][1], bob:true });\n  const dup = x =&gt; add({ kind:&#039;dup&#039;, x, y:GROUND - 38, w:32, h:38 });\n  const spam = (x, y) =&gt; add({ kind:&#039;spam&#039;, x, y, w:34, h:26, spin:0 });\n  function pickKind(){\n    const b = g.boss;\n    if (b.active &amp;&amp; b.wave) return b.wave === &#039;c&#039; ? &#039;doc&#039; : b.wave === &#039;t&#039; ? &#039;bolt&#039; : &#039;link&#039;;\n    return Math.random() &lt; 0.5 ? &#039;doc&#039; : &#039;link&#039;;   \/\/ no hidden balancing: keeping all three fed is the player&#039;s job\n  }\n  function chainOf(kind, x, shape, n){\n    const base = GROUND - 44 - Math.random() * 30;\n    for (let k = 0; k &lt; n; k++){\n      let y;\n      if (shape === 0) y = GROUND - 44;\n      else if (shape === 1) y = base - Math.sin(k \/ (n - 1) * Math.PI) * 90;\n      else if (shape === 2) y = GROUND - 44 - k * 22;\n      else if (shape === 4) y = GROUND - 92;                     \/\/ a short hop\n      else y = GROUND - 128 - Math.sin(k \/ (n - 1) * Math.PI) * 26;\n      item(kind, x + k * 40 * HS, y);\n    }\n    return (n - 1) * 40 * HS + 28;\n  }\n  const FOCUS_KIND = { c:&#039;doc&#039;, t:&#039;bolt&#039;, a:&#039;link&#039; };\n  function twin(x, y){\n    const f = g.upd.focus;\n    if (f === &#039;c&#039;) return add({ kind:&#039;dup&#039;, x, y, w:28, h:34, trap:true, bob:true });\n    if (f === &#039;t&#039;) return add({ kind:&#039;err&#039;, x, y, w:34, h:30, trap:true, bob:true, code:Math.random() &lt; 0.5 ? &#039;404&#039; : &#039;500&#039; });\n    return add({ kind:&#039;spam&#039;, x, y, w:34, h:26, trap:true, bob:true, spin:0 });\n  }\n  \/\/ during an algorithm update: only the focus item and its bad twin, Fruit Ninja style.\n  \/\/ twins never sit inside a chain; they come on their own, so there is always a clean way past\n  function frenzySpawn(x){\n    const kind = FOCUS_KIND[g.upd.focus];\n    g.frz = (g.frz || 0) + 1;\n    if (g.frz % 2 === 0){\n      const r = Math.random();\n      const y = r &lt; 0.45 ? GROUND - 40 : r &lt; 0.8 ? GROUND - 92 : GROUND - 150;\n      twin(x, y);\n      if (y === GROUND - 40) item(kind, x - 6, GROUND - 140);       \/\/ jump over it and grab the reward\n      else if (y === GROUND - 92) item(kind, x + 4, GROUND - 40);   \/\/ stay low under it\n      else item(kind, x, GROUND - 40);\n      g.nextSpawn = 40 * HS + g.speed * AIR * JS * 1.05 + rand(40, 120) * HS;\n      return;\n    }\n    const n = 4 + Math.floor(Math.random() * 3), shape = Math.floor(Math.random() * 4);\n    const base = GROUND - 50 - Math.random() * 24;\n    for (let k = 0; k &lt; n; k++){\n      let y;\n      if (shape === 0) y = GROUND - 92;\n      else if (shape === 1) y = base - Math.sin(k \/ (n - 1) * Math.PI) * 90;\n      else if (shape === 2) y = GROUND - 44 - k * 20;\n      else y = GROUND - 128 - Math.sin(k \/ (n - 1) * Math.PI) * 26;\n      item(kind, x + k * 44 * HS, y);\n    }\n    g.nextSpawn = (n - 1) * 44 * HS + 30 + rand(90, 180) * HS;\n  }\n  function spawn(){\n    const x = W + 30;\n    if (!g.boss.active){ ruleSpawn(); return; }\n    if (g.tut){ g.nextSpawn = 80; return; }\n    if (!g.boss.active &amp;&amp; (g.upd.phase === &#039;warn&#039; || g.upd.phase === &#039;active&#039;)){ frenzySpawn(x); return; }\n    if (!g.boss.active &amp;&amp; g.upd.phase === &#039;spam&#039;){ g.nextSpawn = 60; return; }\n    if (!g.boss.active &amp;&amp; g.lives &lt; 3 &amp;&amp; g.t &gt; 60 &amp;&amp; g.t - g.lastHeart &gt; 45 &amp;&amp; (g.heartsGiven || 0) &lt; 1 &amp;&amp; Math.random() &lt; 0.5){\n      g.lastHeart = g.t; g.heartsGiven = (g.heartsGiven || 0) + 1;\n      add({ kind:&#039;heart&#039;, x, y:GROUND - 118, w:28, h:26, bob:true });\n      g.nextSpawn = (60 + rand(160, 260)) * HS;\n      return;\n    }\n    const diff = clamp(g.t \/ LV[LVL].dt, 0, 1);\n    const act = g.upd.phase === &#039;active&#039; || g.boss.active;\n    const calm = g.t &lt; 7 || g.boss.active;\n    const r = Math.random();\n    let span = 30, obstacle = false;\n    if (calm || r &lt; (act ? 0.3 : g.t &lt; 30 ? 0.46 : 0.38) - diff * 0.13){\n      if (!calm &amp;&amp; Math.random() &lt; 0.55){\n        \/\/ a choice: your weakest pillar on one path, your strongest on the other, so &quot;feed all three&quot; is a real decision\n        const byPil = [&#039;doc&#039;, &#039;bolt&#039;, &#039;link&#039;].sort((x, y) =&gt; g.pil[KIND_PIL[x]] - g.pil[KIND_PIL[y]]);\n        const ks = Math.random() &lt; 0.5 ? [byPil[0], byPil[2]] : [byPil[2], byPil[0]];\n        chainOf(ks[0], x, 4, 4);                 \/\/ short hop for one pillar\u2026\n        span = chainOf(ks[1], x + 10, 3, 4);     \/\/ \u2026long jump for the other\n      } else span = chainOf(pickKind(), x, [1, 1, 2, 3, 4, 0][Math.floor(Math.random() * 6)], 4 + Math.floor(Math.random() * 2));\n    } else if (!act &amp;&amp; g.t &gt; 25 &amp;&amp; Math.random() &lt; (0.15 + diff * 0.45) * LV[LVL].pat){\n      \/\/ rhythm patterns: the climb gets tighter and asks for timing, not just reaction\n      obstacle = true;\n      const land = g.speed * AIR * JS;               \/\/ ground covered during one full jump\n      const pat = Math.floor(Math.random() * (diff &gt; 0.5 ? 4 : 3));\n      const kind = pickKind();\n      if (pat === 0){            \/\/ hop, land, hop again\n        const gap = land + rand(50, 90) * HS;\n        dup(x); dup(x + gap);\n        item(kind, x - 4, GROUND - 120); item(kind, x + gap - 4, GROUND - 120);\n        span = gap + 40;\n      } else if (pat === 1){     \/\/ jump the copy, then stay down under the spam\n        const gap = land + rand(70, 110) * HS;\n        dup(x); spam(x + gap, GROUND - 100);\n        item(kind, x - 4, GROUND - 120); item(kind, x + gap + 6, GROUND - 44);\n        span = gap + 50;\n      } else if (pat === 2){     \/\/ two spams in a row: patience\n        spam(x, GROUND - 100); spam(x + 110 * HS, GROUND - 150);\n        for (let k = 0; k &lt; 3; k++) item(kind, x - 10 + k * 55 * HS, GROUND - 44);\n        span = 160 * HS;\n      } else {                   \/\/ a runaway 404 on the ground, announced at the edge\n        add({ kind:&#039;err&#039;, code:Math.random() &lt; 0.5 ? &#039;404&#039; : &#039;500&#039;, x:W + 30, y:GROUND - 30, w:34, h:30, vx:g.speed * 0.45, hold:0.7 });\n        span = 140 * HS;\n      }\n    } else if (r &lt; 0.74){\n      obstacle = true;\n      dup(x);\n      if (Math.random() &lt; 0.35 + diff * 0.5 &amp;&amp; g.t &gt; 15) dup(x + 36);\n      const kind = pickKind();\n      for (let k = 0; k &lt; 3; k++) item(kind, x - 30 + k * 46 * HS, GROUND - 100 - Math.sin(k \/ 2 * Math.PI) * 40);\n      span = 100;\n    } else {\n      obstacle = true;\n      const high = Math.random() &lt; 0.5, kind = pickKind();\n      \/\/ one rule for everything floating: stay under it. The reward sits under it, never above it\n      spam(x, high ? GROUND - 150 : GROUND - 100);\n      for (let k = 0; k &lt; 2; k++) item(kind, x - 20 + k * 40 * HS, GROUND - 44);\n      span = 60;\n    }\n    const minGap = obstacle ? g.speed * AIR * JS * 1.05 + 60 * HS : 90 * HS;\n    const extra = (act ? rand(40, 150) : rand(90, 240 - diff * 120)) * HS;\n    g.nextSpawn = span + minGap + extra;\n  }\n\n  \/\/ ================= interactions =================\n  function gaugePos(k){ return { x:38, y:40 }; }\n  \/\/ move the rank by whole steps (+ = up), used where the player must SEE cause and effect\n  function stepRank(n, pop = true){\n    if (!n || g.boss.active || g.boss.done) return;\n    const r = rankOf(g.P), t = clamp(r - n, Math.min(r, 2), 100);   \/\/ step bonuses never hand you #1: the final is earned by play\n    const P2 = rankToP(t);\n    g.P = n &gt; 0 ? Math.max(g.P, P2) : Math.min(g.P, P2);\n    if (!g.boss.active &amp;&amp; rankOf(g.P) &lt;= 2) g.finalistLock = true;\n    const dd = r - rankOf(g.P);\n    if (pop &amp;&amp; dd) g.rankPop = { text:(dd &gt; 0 ? &#039;+&#039; : &#039;\u2212&#039;) + Math.abs(dd), good:dd &gt; 0, life:0.9 };\n    g.lift = clamp((g.lift || 0) + n * 16, -90, 180);\n    if (n &gt; 0) g.rankFlash = 0.5;\n  }\n  function collect(o){\n    o.dead = true;\n    const k = KIND_PIL[o.kind];\n    const cx = o.x + o.w \/ 2, cy = o.y + (o.by || 0) + o.h \/ 2;\n    g.combo = (g.t - g.lastPick &lt; 1.3) ? g.combo + 1 : 1;\n    g.lastPick = g.t;\n    g.maxCombo = Math.max(g.maxCombo, g.combo);\n    g.got[k]++; if (g.upd.phase !== &#039;warn&#039; &amp;&amp; g.upd.phase !== &#039;active&#039; &amp;&amp; !g.boss.active) g.gotCalm[k]++;\n    g.pil[k] = Math.min(100, g.pil[k] + 10 * (1 - g.pil[k] \/ 140)); g.red[k] = 0; g.bleedN[k] = 0;   \/\/ one pickup stops the neglect bleed\n    const uu = g.upd;\n    if (uu.phase === &#039;warn&#039; || uu.phase === &#039;active&#039;){\n      uu.cnt[k]++;\n      if (k === uu.focus){\n        const r0 = rankOf(g.P), per = r0 &gt; 20 ? 0.9 : r0 &gt; 10 ? 0.5 : 0.22;\n        uu.acc = (uu.acc || 0) + Math.min(1.5, PF) * per;\n        if (uu.acc &gt;= 1){ const n = Math.floor(uu.acc); uu.acc -= n; stepRank(n); snd.rankUp(uu.cnt[k]); }\n        if (uu.cnt[k] === UPD_GOAL){ stepRank(3); say(&#039;Hedef tamam! +3 s\u0131ra&#039;, 1.4, &#039;lime&#039;); snd.good(); confetti(20); }\n      }\n    }\n    if (!g.boss.active){\n      const key = curRule();\n      if (key === &#039;core&#039;){ g.coreGood++; gain(V.coreItem); } else gain(V.doc);\n      g.rs.good++; g.stats[key === &#039;core&#039; ? &#039;core&#039; : &#039;orijinal&#039;].good++;\n    } else { const b = g.boss; const gain = (b.wave ? (b.wave === k ? 9 : 2) : 5) * PF * (b.t &lt; 1.6 ? 0.35 : 1); b.gs = (b.gs || 0) + gain; b.L = clamp(b.L + gain * (b.L &gt; 0 ? 1 - b.L \/ 130 : 1), -100, 100); }\n    snd.pop(Math.min(g.combo - 1, 10));\n    g.pops.push({ kind:o.kind, x:o.x, y:o.y + (o.by || 0), w:o.w, h:o.h, t:0 });\n    const col = PIL[k].col;\n    g.waves.push({ x:cx, y:cy, r:8, life:0.4, col });\n    const gp = gaugePos(k);\n    g.flyers.push({ sx:cx, sy:cy, x:cx, y:cy, tx:gp.x, ty:gp.y, t:0, col });\n    const n = 7 + Math.min(10, g.combo);\n    for (let i = 0; i &lt; n; i++){ const a = Math.random() * Math.PI * 2, s = rand(70, 170 + g.combo * 6); g.parts.push({ x:cx, y:cy, vx:Math.cos(a) * s, vy:Math.sin(a) * s - 40, r:rand(1.8, 3.4), c:[C.lime, col, C.white][i % 3], life:rand(0.4, 0.7), gr:320, star:i % 4 === 0 }); }\n    const next = WORDS[g.wordIdx];\n    if (next &amp;&amp; g.combo &gt;= next[0]){ g.wordIdx++; word(next[1]); snd.word(); buzz(15); g.shake = Math.max(g.shake, 0.18); }\n  }\n  function damage(o){\n    o.hit = true;\n    if (g.inv &gt; 0 || g.ending) return;\n    if (o.trap || o.rain){\n      const u = g.upd;\n      if (o.trap) u.traps++; else u.hits++;\n      g.combo = 0; g.wordIdx = 0; g.inv = 0.5; g.shake = 0.25; g.flash = 0.2; g.hitstop = 0.05;\n      snd.hit(); buzz(25);\n      for (let k = 0; k &lt; 8; k++){ const a = Math.random() * Math.PI * 2, s3 = rand(60, 150); g.parts.push({ x:o.x + o.w \/ 2, y:o.y + o.h \/ 2, vx:Math.cos(a) * s3, vy:Math.sin(a) * s3, r:rand(2, 3), c:C.danger, life:0.45, gr:260 }); }\n      o.dead = true;\n      if (o.trap){ const r0 = rankOf(g.P), pen = r0 &gt; 20 ? 5 : r0 &gt; 10 ? 4 : 3; stepRank(-pen); if (!g.saidTrap){ g.saidTrap = true; say(TRAP_MSG[u.focus] + ` \u2212${pen} s\u0131ra`, 1.2, &#039;red&#039;); } }\n      else { const r0 = rankOf(g.P), pen = u.hits &gt; 3 ? 0 : r0 &gt; 20 ? 4 : r0 &gt; 10 ? 3 : 2; if (pen) stepRank(-pen); if (!g.saidRain) g.saidRain = true, say((o.kind === &#039;err&#039; ? &#039;Hataya&#039; : &#039;Spama&#039;) + &#039; tak\u0131ld\u0131n&#039; + (pen ? `: \u2212${pen} s\u0131ra` : &#039;&#039;), 1.2, &#039;red&#039;); }\n      return;\n    }\n    const before = curRank(), u = g.upd;\n    let saved = &#039;&#039;;\n    if (!g.boss.active){\n      \/\/ no death in the first 45 s (nobody leaves after a bad start); on page 1, one second chance so a long climb doesn&#039;t end 1 step before the final\n      if (o.tut) saved = &#039;tut&#039;;\n      else if (o.kind === &#039;img&#039; &amp;&amp; cycleN() === 0 &amp;&amp; !g.warnedImg){ g.warnedImg = true; saved = &#039;img1&#039;; }\n      else if (g.lives &gt; 1) g.lives--;\n      else g.lives--;\n      if (!saved){ g.lifeFx = 1; g.lifePop = 1; }\n    }\n    g.combo = 0; g.wordIdx = 0;\n    g.inv = 1.5; g.shake = 0.4; g.flash = 0.3; g.hitstop = 0.08;\n    if (u.phase === &#039;active&#039; || u.phase === &#039;spam&#039;) u.hits++;\n    if (g.boss.active) g.boss.L = clamp(g.boss.L - 16, -100, 100);\n    else { const r1 = rankOf(g.P); stepRank(-(r1 &gt; 20 ? 4 : r1 &gt; 10 ? 3 : 2)); g.acc = 0; }\n    snd.hit(); buzz(40);\n    const p = g.p;\n    for (let k = 0; k &lt; 10; k++){ const a = Math.random() * Math.PI * 2, s2 = rand(60, 160); g.parts.push({ x:p.x + 19, y:p.y + 20, vx:Math.cos(a) * s2, vy:Math.sin(a) * s2, r:rand(2, 3), c:C.danger, life:0.5, gr:260 }); }\n    if (g.lives &lt;= 0){ endRun(&#039;dead&#039;); return; }\n    const lost = curRank() - before;\n    const what = o.kind === &#039;dup&#039; ? &#039;Kopya i\u00e7erik&#039; : o.kind === &#039;err&#039; ? &#039;404 \u00e7ukuruna d\u00fc\u015ft\u00fcn&#039; : o.kind === &#039;img&#039; ? &#039;A\u011f\u0131r g\u00f6rsel siteni yava\u015flatt\u0131&#039; : &#039;Spam&#039;;\n    if (!g.boss.active &amp;&amp; (g.rp === &#039;rule&#039; || g.rp === &#039;card&#039;)){ const key = curRule(); g.rs.bad++; if (key === &#039;spam&#039;){ g.stats.spam.bad++; g.spamHitsRule++; } }\n    if (g.boss.active) say(`${what}: rakibin \u00f6ne ge\u00e7iyor`, 1.4, &#039;red&#039;);\n    else if (saved === &#039;second&#039;) say(&#039;\u0130kinci \u015fans! Can\u0131n gitmedi, bir daha olmaz&#039;, 1.9, &#039;red&#039;);\n    else if (saved === &#039;img1&#039;) say(&#039;\u0130lk uyar\u0131: a\u011f\u0131r g\u00f6rselin \u00fcst\u00fcne z\u0131pla!&#039;, 1.9, &#039;red&#039;);\n    else if (saved === &#039;tut&#039;) say(&#039;Z\u0131plaman gerekiyordu. Sorun yok, bu deneme!&#039;, 1.8, &#039;red&#039;);\n    else if (saved === &#039;warm&#039;) say(`${what}: ${lost &gt; 0 ? lost + &#039; s\u0131ra kaybettin \u00b7 &#039; : &#039;&#039;}\u0131s\u0131nma turu, can\u0131n gitmedi`, 1.8, &#039;red&#039;);\n    else if (g.lives &gt; 1 &amp;&amp; (g.hitSaid = (g.hitSaid || 0) + 1) &gt; 2){ \/* the rank badge already shows the loss *\/ }\n    else if (g.lives === 1) say(lost &gt; 0 ? `${what}: ${lost} s\u0131ra kaybettin \u00b7 son hakk\u0131n` : &#039;Son hakk\u0131n, dikkatli ol&#039;, 1.7, &#039;red&#039;);\n    else say(lost &gt; 0 ? `${what}: ${lost} s\u0131ra kaybettin` : `${what} s\u0131ralaman\u0131 sarst\u0131`, 1.4, &#039;red&#039;);\n  }\n  function endRun(kind){\n    if (g.ending) return;\n    g.finishT = g.t;\n    g.outcome = kind; g.ending = kind === &#039;dead&#039; ? 1.0 : 2.2; g.slowmo = kind === &#039;dead&#039; ? 0.6 : 0;\n    if (kind === &#039;win&#039;) track(&#039;reach_top&#039;, { seconds:Math.round(g.t), snippet:!!g.snippet });\n    if (kind === &#039;win&#039;){ confetti(160); snd.fanfare(); word(g.snippet ? &#039;\u00d6ne \u00c7\u0131kan Sonu\u00e7!&#039; : &#039;Zirvedesin!&#039;, true); buzz(80); g.banner = null; }\n    else if (kind === &#039;lose&#039;){ snd.meh(); }\n    else snd.end();\n  }\n\n  \/\/ ================= algorithm update: the exam of balance =================\n  const UNIT = { c:&#039;sayfa&#039;, t:&#039;\u015fim\u015fek&#039;, a:&#039;link&#039; };\n  const TWIN = { c:&#039;kopyaya&#039;, t:&#039;hataya&#039;, a:&#039;spama&#039; };\n  const TRAP_MSG = { c:&#039;Kopyaya tak\u0131ld\u0131n!&#039;, t:&#039;Hataya tak\u0131ld\u0131n!&#039;, a:&#039;Spama tak\u0131ld\u0131n!&#039; };\n  const UPD_GOAL = 12;\n  const FOCUS2 = { c:&#039;Sayfa topla, kopyadan ka\u00e7.&#039;, t:&#039;\u015eim\u015fek topla, hatadan ka\u00e7.&#039;, a:&#039;Link topla, spamdan ka\u00e7.&#039; };\n  const FOCUS = { c:[&#039;i\u00e7eri\u011fe&#039;, &#039;Sayfalar\u0131 topla!&#039;], t:[&#039;tekni\u011fe&#039;, &#039;Mavi \u015fim\u015fekleri topla!&#039;], a:[&#039;otoriteye&#039;, &#039;Mor linkleri topla!&#039;] };\n  \/\/ focus rotates: every pillar gets its turn, never the same twice in a row; picked early so it can be announced\n  function nextFocus(){ const u = g.upd; if (!u.bag || !u.bag.length){ u.bag = shuffle([&#039;c&#039;, &#039;t&#039;, &#039;a&#039;]); if (u.bag[0] === u.focus) u.bag.push(u.bag.shift()); } return u.bag.shift(); }\n  function tickUpdate(dt){\n    const u = g.upd; u.timer -= dt;\n    if (u.phase === &#039;idle&#039; &amp;&amp; !u.next) u.next = nextFocus();\n    if (u.phase === &#039;idle&#039; &amp;&amp; u.timer &lt;= 10 &amp;&amp; u.timer &gt; 3.5 &amp;&amp; u.announced !== u.n &amp;&amp; !g.banner){\n      u.announced = u.n; u.annAt = g.t; u.annText = `S\u0131radaki g\u00fcncelleme: ${PIL[u.next].name}`;\n      say(u.annText, 2.6, &#039;dark&#039;);\n    } else if (u.phase === &#039;idle&#039; &amp;&amp; u.announced === u.n &amp;&amp; g.t - u.annAt &lt; 1.2 &amp;&amp; (!g.msg || g.msg.text !== u.annText) &amp;&amp; u.timer &gt; 4) u.announced = -1;   \/\/ overwritten: show it again when free\n    if (u.phase === &#039;idle&#039; &amp;&amp; u.timer &lt;= 0){\n      u.phase = &#039;warn&#039;; u.timer = 3; u.focus = u.next || nextFocus(); u.next = null; g.red = { c:0, t:0, a:0 }; u.cnt = { c:0, t:0, a:0 }; u.traps = 0; u.acc = 0; u.weak = false; u.r0 = rankOf(g.P);   \/\/ focus rotates: every pillar gets its turn, never the same twice in a row\n      for (const o of g.objs){ if (!o.dead &amp;&amp; o.x &gt; g.p.x + 60 &amp;&amp; !KIND_PIL[o.kind] &amp;&amp; o.kind !== &#039;snippet&#039;){ o.dead = true; for (let k = 0; k &lt; 5; k++) g.parts.push({ x:o.x + o.w \/ 2, y:o.y + o.h \/ 2, vx:rand(-80, 80), vy:rand(-120, 0), r:2, c:&#039;rgba(255,255,255,.8)&#039;, life:0.4, gr:200 }); } }\n      g.nextSpawn = Math.max(g.nextSpawn, g.speed * 1.2);\n      banner(`Algoritma g\u00fcncellemesi: ${PIL[u.focus].name}`, FOCUS2[u.focus], &#039;dark&#039;, 3);\n      snd.warn();\n    } else if (u.phase === &#039;warn&#039; &amp;&amp; u.timer &lt;= 0){\n      u.phase = &#039;active&#039;; u.timer = 8; u.hits = 0; g.glitch = 0.4; g.shake = Math.max(g.shake, 0.2); snd.slide(900, 120, 0.3, &#039;sawtooth&#039;, 0.03);\n      if (g.pil[u.focus] &gt;= 60){ stepRank(2); snd.rankUp(4); say(`G\u00fc\u00e7l\u00fc ${PIL[u.focus].name.toLocaleLowerCase(&#039;tr&#039;)}: +2 s\u0131ra`, 1.6, &#039;lime&#039;); }\n      else if (g.pil[u.focus] &lt; WEAK){ stepRank(-4); u.weak = true; say(`Zay\u0131f ${PIL[u.focus].name.toLocaleLowerCase(&#039;tr&#039;)}: \u22124 s\u0131ra`, 1.8, &#039;red&#039;); snd.meh(); }\n      \/\/ anything left over from before the update turns into the focus item, obstacles ahead fade away\n      for (const o of g.objs){\n        if (o.dead || o.x &lt; g.p.x + 20 || o.trap) continue;\n        if (KIND_PIL[o.kind] &amp;&amp; o.kind !== FOCUS_KIND[u.focus]){ const sz = SIZE[FOCUS_KIND[u.focus]]; o.kind = FOCUS_KIND[u.focus]; o.w = sz[0]; o.h = sz[1]; g.waves.push({ x:o.x + o.w \/ 2, y:o.y + o.h \/ 2, r:6, life:0.35, col:PIL[u.focus].col }); }\n        else if (!KIND_PIL[o.kind] &amp;&amp; o.kind !== &#039;snippet&#039;){ o.dead = true; for (let k = 0; k &lt; 5; k++) g.parts.push({ x:o.x + o.w \/ 2, y:o.y + o.h \/ 2, vx:rand(-80, 80), vy:rand(-120, 0), r:2, c:&#039;rgba(255,255,255,.8)&#039;, life:0.4, gr:200 }); }\n      }\n    } else if (u.phase === &#039;active&#039;){\n      if (u.timer &lt;= 0){\n        u.n++; resolveUpdate();\n        u.phase = &#039;idle&#039;; u.timer = 23; u.sAt = (u.n === 1 || Math.random() &lt; 0.6) ? rand(9, 15) : -1;\n      }\n    } else if (u.phase === &#039;idle&#039; &amp;&amp; u.sAt &gt; 0 &amp;&amp; (u.sAt -= dt) &lt;= 0){\n      u.sAt = -1; g.red = { c:0, t:0, a:0 }; u.phase = &#039;spam&#039;; u.sT = 16; u.hits = 0; u.rainT = 1.0; u.rainN = 0; u.spamN++; u.r0 = rankOf(g.P);\n      u.stype = u.lastS === &#039;spam&#039; ? &#039;tech&#039; : u.lastS === &#039;tech&#039; ? &#039;spam&#039; : (Math.random() &lt; 0.5 ? &#039;spam&#039; : &#039;tech&#039;);\n      u.lastS = u.stype;\n      \/\/ each surprise is a new pattern, so it never turns into a known routine: rain, then a head-on attack, then both\n      u.pat = u.spamN === 1 ? &#039;rain&#039; : u.spamN === 2 ? &#039;wave&#039; : &#039;mix&#039;;\n      u.rainMax = u.pat === &#039;rain&#039; ? 6 : u.pat === &#039;wave&#039; ? 7 : 9;\n      const sp = u.stype === &#039;spam&#039;;\n      if (u.pat === &#039;rain&#039;) banner(sp ? &#039;Beklenmedik spam g\u00fcncellemesi!&#039; : &#039;Sitende teknik hata \u00e7\u0131kt\u0131!&#039;, sp ? &#039;G\u00f6lgeye dikkat, d\u00fc\u015fen spamlar\u0131n \u00fcst\u00fcnden z\u0131pla.&#039; : &#039;G\u00f6lgeye dikkat, d\u00fc\u015fen hatalar\u0131n \u00fcst\u00fcnden z\u0131pla.&#039;, &#039;red&#039;, 2.4);\n      else if (u.pat === &#039;wave&#039;) banner(sp ? &#039;Spam sald\u0131r\u0131s\u0131!&#039; : &#039;Sunucun hata f\u0131rlat\u0131yor!&#039;, &#039;Yerdekinin \u00fcst\u00fcnden z\u0131pla, havadakinin alt\u0131ndan ge\u00e7.&#039;, &#039;red&#039;, 2.6);\n      else banner(sp ? &#039;B\u00fcy\u00fck spam sald\u0131r\u0131s\u0131!&#039; : &#039;Siten \u00e7\u00f6k\u00fcyor!&#039;, &#039;G\u00f6lgeye ve \u00fcnlemlere bak.&#039;, &#039;red&#039;, 2.6);\n      snd.warn(); g.shake = 0.3; buzz(30);\n    } else if (u.phase === &#039;spam&#039;){\n      u.rainT -= dt; u.sT -= dt;\n      if (u.rainT &lt;= 0 &amp;&amp; u.rainN &lt; u.rainMax){\n        u.rainN++;\n        const tech = u.stype === &#039;tech&#039;, h = tech ? 30 : 26;\n        const kind = tech ? { kind:&#039;err&#039;, code:Math.random() &lt; 0.5 ? &#039;404&#039; : &#039;500&#039; } : { kind:&#039;spam&#039;, spin:0 };\n        const wave = u.pat === &#039;wave&#039; || (u.pat === &#039;mix&#039; &amp;&amp; u.rainN % 2 === 0);\n        if (wave){\n          \/\/ head-on: announced by a &quot;!&quot; at the screen edge, then flies in faster than the ground.\n          \/\/ low ones must be jumped, high ones pass over your head if you stay down\n          const low = u.lastLow === false ? Math.random() &lt; 0.7 : Math.random() &lt; 0.5;\n          u.lastLow = low;\n          \/\/ a high attack is a column of three: you can&#039;t jump over it, you stay under it\n          const nk = low ? 1 : 3;\n          for (let k = 0; k &lt; nk; k++){\n            const kk = Object.assign({}, kind, kind.code ? { code:Math.random() &lt; 0.5 ? &#039;404&#039; : &#039;500&#039; } : {});\n            add(Object.assign({ x:W + 30, y:low ? GROUND - h : GROUND - 54 - h - k * (h + 3), w:34, h, vx:g.speed * 0.5, rain:true, wave:true, hold:0.75 }, kk));\n          }\n          u.rainT = low ? AIR * JS + rand(0.3, 0.45) : rand(0.6, 0.8);\n        } else {\n          const landX = PX + g.speed * rand(0.85, 1.2);           \/\/ lands ahead of you; reaches you 1.0\u20131.35 s later\n          const T = Math.max(0.7, (W + 40 - landX) \/ g.speed);     \/\/ enters from off-screen right\n          const y0 = Math.max(-40, GROUND - 420);\n          add(Object.assign({ x:landX + g.speed * T, y:y0, w:34, h, fall:(GROUND - h - y0) \/ T, rain:true }, kind));\n          u.lastLow = true;\n          u.rainT = u.pat === &#039;mix&#039; ? AIR * JS + rand(0.25, 0.4) : rand(0.72, 0.92);\n        }\n      }\n      const pending = g.objs.some(o =&gt; o.rain &amp;&amp; !o.dead &amp;&amp; o.x + o.w &gt; PX - 20);\n      if ((u.rainN &gt;= u.rainMax &amp;&amp; !pending) || u.sT &lt;= 0){ u.phase = &#039;idle&#039;; u.timer = Math.max(u.timer, 10); resolveSpam(); }\n    }\n  }\n  function resolveUpdate(){\n    const u = g.upd, f = u.focus, right = u.cnt[f], traps = u.traps || 0;\n    let missed = false;\n    if (right &lt; UPD_GOAL \/ 2){ stepRank(-5, false); missed = true; }\n    const d = u.r0 - rankOf(g.P);\n    track(&#039;update_result&#039;, { type:&#039;core&#039;, focus:f, change:d, right, traps });\n    const sub = `${right} ${UNIT[f]} toplad\u0131n` + (traps ? `, ${traps} kez ${TWIN[f]} tak\u0131ld\u0131n.` : &#039;, hi\u00e7 tuza\u011fa d\u00fc\u015fmedin.&#039;);\n    if (d &gt; 0){ u.coreUps = (u.coreUps || 0) + 1; u.gained += d; banner(`G\u00fcncelleme: ${d} s\u0131ra y\u00fckseldin`, sub, &#039;lime&#039;, 3); snd.good(); confetti(40); bigWin(`+${d} SIRA!`); }\n    else if (d &lt; 0){ u.downs++; banner(`G\u00fcncelleme: ${-d} s\u0131ra d\u00fc\u015ft\u00fcn`, missed ? `Algoritma yeterince ${UNIT[f]} g\u00f6remedi.` : sub, &#039;light&#039;, 3); snd.meh(); g.shake = 0.45; g.flash = 0.25; }\n    else banner(&#039;G\u00fcncelleme: s\u0131ran de\u011fi\u015fmedi&#039;, sub, &#039;light&#039;, 2.6);\n  }\n  function bigWin(t){ g.bigWord = { text:t, t:0, life:1.4 }; snd.big(); }\n  function resolveSpam(){\n    const u = g.upd, tech = u.stype === &#039;tech&#039;;\n    for (const o of g.objs) if (o.rain &amp;&amp; !o.dead){ o.dead = true; for (let k = 0; k &lt; 6; k++) g.parts.push({ x:o.x + o.w \/ 2, y:o.y + o.h \/ 2, vx:rand(-90, 90), vy:rand(-140, -20), r:2.2, c:&#039;rgba(255,255,255,.85)&#039;, life:0.45, gr:260 }); }\n    track(&#039;update_result&#039;, { type:tech ? &#039;tech&#039; : &#039;spam&#039;, hits:u.hits });\n    if (u.hits === 0){\n      stepRank(5, false);\n      const d = u.r0 - rankOf(g.P);\n      if (d &gt; 0) bigWin(`+${d} SIRA!`);\n      if (d &gt; 0) u.gained += d;\n      u.cleanS = (u.cleanS || 0) + 1;\n      if (tech) banner(`Siteni ayakta tuttun: ${d} s\u0131ra y\u00fckseldin`, &#039;Hatal\u0131 rakiplerin geride kald\u0131.&#039;, &#039;lime&#039;, 2.8);\n      else banner(`Spamdan temiz \u00e7\u0131kt\u0131n: ${d} s\u0131ra y\u00fckseldin`, &#039;Spam yapan rakiplerin d\u00fc\u015ft\u00fc.&#039;, &#039;lime&#039;, 2.8);\n      snd.good();\n    } else {\n      const d = rankOf(g.P) - u.r0;\n      if (tech) banner(&#039;Teknik hatalar giderildi&#039;, `Hatalara tak\u0131ld\u0131n, ${d} s\u0131ra kaybettin.`, &#039;light&#039;, 2.8);\n      else banner(&#039;Spam g\u00fcncellemesi bitti&#039;, `Spama tak\u0131ld\u0131n, ${d} s\u0131ra kaybettin.`, &#039;light&#039;, 2.8);\n      snd.meh();\n    }\n  }\n\n  \/\/ ================= final: keep the top spot =================\n  const WAVE_MSG = { c:[&#039;Rakibin i\u00e7eri\u011fini yeniledi&#039;, &#039;En zay\u0131f yerinden vuruyor: sayfa topla!&#039;], t:[&#039;Rakibin sitesini h\u0131zland\u0131rd\u0131&#039;, &#039;En zay\u0131f yerinden vuruyor: \u015fim\u015fek topla!&#039;], a:[&#039;Rakibin yeni linkler ald\u0131&#039;, &#039;En zay\u0131f yerinden vuruyor: link topla!&#039;] };\n  let FINAL_P = 12.5;\n  let LVL = 1;   \/\/ 0 rahat, 1 normal, 2 sert\n  const LV = [{ sp:1.2, dt:150, pat:0.6 }, { sp:1.55, dt:125, pat:0.85 }, { sp:2.1, dt:85, pat:1.35 }];\n  let ITEM_RANK = [0.45, 0.28, 0.18, 0.1];\n  \/\/ ===== the algorithm changes the rule every few seconds; the run never stops =====\n  const RULES = {\n    orijinal:{ icon:&#039;doc&#039;,  title:&#039;\u00d6zg\u00fcn i\u00e7erik&#039;, line:&#039;Ye\u015fil sayfay\u0131 topla, kopyaya dokunma&#039;, col:C.green },\n    hiz:     { icon:&#039;img&#039;,  title:&#039;H\u0131z testi&#039;,       line:&#039;A\u011f\u0131r g\u00f6rselin \u00fcst\u00fcne z\u0131pla, s\u0131k\u0131\u015ft\u0131r&#039;,     col:C.teal },\n    core:    { icon:&#039;core&#039;, title:&#039;Core update!&#039;,    line:&#039;Kalkan topla, k\u0131rm\u0131z\u0131 sars\u0131nt\u0131dan ka\u00e7&#039;, col:C.violet },\n    kirik:   { icon:&#039;hole&#039;, title:&#039;K\u0131r\u0131k linkler&#039;,   line:&#039;404 \u00e7ukurunun \u00fcst\u00fcnden atla&#039;, col:C.danger },\n    spam:    { icon:&#039;spam&#039;, title:&#039;Spam sald\u0131r\u0131s\u0131&#039;,  line:&#039;Yerdekinin \u00fcst\u00fcnden z\u0131pla, havadakinin alt\u0131ndan ge\u00e7&#039;, col:C.danger }\n  };\n  const CYCLE = [&#039;orijinal&#039;, &#039;hiz&#039;, &#039;core&#039;, &#039;spam&#039;];\n  const RULE_LEN = 11, CARD_LEN = 1.8, RES_LEN = 1.6;\n  const V = { doc:0.6, stomp:1.5, dodge:1.2, coreItem:0.6, copy:-1.5 };\n  const LOOK = [[1.4, 1.25, 1.15], [1.25, 1.05, 0.95], [1.1, 0.95, 0.85]];   \/\/ seconds of look-ahead per level and cycle: the run speeds up every cycle   \/\/ ranks per pickup by band (&gt;50, 21-50, 11-20, top 10), tuned by sim   \/\/ tuned by sim: strong players win ~9\/10, average ~half, weak rarely\n  const curRule = () =&gt; { const i = Math.max(0, g.ri), pos = i % 4; return pos === 1 ? (Math.floor(i \/ 4) % 2 === 0 ? &#039;hiz&#039; : &#039;kirik&#039;) : CYCLE[pos]; };\n  const cycleN = () =&gt; Math.floor(Math.max(0, g.ri) \/ 4);\n  \/\/ rank steps feel big far down the list and small near the top, like real rankings\n  function gain(n){\n    const r = curRank(), m = n &gt; 0 ? (r &gt; 50 ? 1.6 : r &gt; 20 ? 1.0 : r &gt; 8 ? 0.55 : r &gt; 3 ? 0.3 : 0.15) : 1;\n    g.frac += n * m;\n    const whole = g.frac &gt; 0 ? Math.floor(g.frac) : Math.ceil(g.frac);\n    if (whole){ g.frac -= whole; stepRank(whole); if (whole &gt; 0) snd.rankUp(Math.min(12, g.combo)); }\n  }\n  function tickRules(dt){\n    if (g.rp === &#039;intro&#039;){ g.cardT -= dt; if (g.cardT &lt;= 0) nextRule(); }\n    else if (g.rp === &#039;card&#039;){ g.cardT -= dt; if (g.cardT &lt;= 0){ g.rp = &#039;rule&#039;; g.rT = RULE_LEN; } }\n    else if (g.rp === &#039;rule&#039;){ g.rT -= dt; if (g.rT &lt;= 0) endRule(); }\n    else if (g.rp === &#039;result&#039;){ g.resT -= dt; if (g.resT &lt;= 0){ if (curRank() &lt;= 2 || g.finalistLock) startBoss(); else nextRule(); } }\n  }\n  function nextRule(){\n    g.ri++; g.rp = &#039;card&#039;; g.cardT = CARD_LEN; g.rr0 = curRank(); g.rs = { good:0, bad:0 };\n    const key = curRule();\n    g.nextSpawn = Math.max(g.nextSpawn, g.speed * (CARD_LEN - 0.5));\n    snd.warn();\n    if (key === &#039;spam&#039;) g.spamHitsRule = 0;\n    if (key === &#039;core&#039;){\n      \/\/ the shake-up: rankings move before you can do anything, then quality decides the rebound\n      g.coreGood = 0; g.coreBad = 0; g.coreHits = 0; g.shields = 0;\n      g.glitch = 0.7; g.shake = 0.4; buzz(40);\n    }\n    track(&#039;rule_start&#039;, { rule:key, cycle:cycleN() });\n  }\n  function endRule(){\n    const key = curRule(), st = g.rs;\n    if (key === &#039;core&#039;){ const n = Math.max(0, 6 - g.coreHits * 3); if (n) stepRank(n); if (!g.coreHits) g.coreUps++; else g.coreDowns++; g.shields = 0; }\n    if (key === &#039;spam&#039; &amp;&amp; !g.spamHitsRule){ g.cleanSpam++; stepRank(3); }\n    const d = g.rr0 - curRank();\n    const sub = key === &#039;orijinal&#039; ? `${st.good} \u00f6zg\u00fcn sayfa, ${st.bad} kopya` : key === &#039;hiz&#039; ? `${st.good} g\u00f6rseli s\u0131k\u0131\u015ft\u0131rd\u0131n` + (st.bad ? `, ${st.bad} kez \u00e7arpt\u0131n` : &#039;&#039;) : key === &#039;core&#039; ? (g.coreHits ? `${g.coreHits} sars\u0131nt\u0131 yedin, ${g.coreGood} kalkan toplad\u0131n` : &#039;Hi\u00e7 sars\u0131lmad\u0131n: rakipler d\u00fc\u015ft\u00fc, sen y\u00fckseldin!&#039;) : key === &#039;kirik&#039; ? `${st.good} \u00e7ukuru atlad\u0131n` + (st.bad ? `, ${st.bad} kez d\u00fc\u015ft\u00fcn` : &#039;&#039;) : (g.spamHitsRule ? `${st.good} spam atlatt\u0131n, ${g.spamHitsRule} kez tak\u0131ld\u0131n` : &#039;Hi\u00e7 tak\u0131lmad\u0131n, temiz site bonusu!&#039;);\n    const T = RULES[key].title.replace(&#039;!&#039;, &#039;&#039;);\n    if (d &gt; 0){ banner(`${T}: ${d} s\u0131ra y\u00fckseldin`, sub, &#039;lime&#039;, RES_LEN + 0.2); bigWin(`+${d} SIRA!`); confetti(30); snd.good(); }\n    else if (d &lt; 0){ banner(`${T}: ${-d} s\u0131ra d\u00fc\u015ft\u00fcn`, sub, &#039;light&#039;, RES_LEN + 0.2); snd.meh(); g.shake = 0.35; }\n    else banner(`${T}: s\u0131ran de\u011fi\u015fmedi`, sub, &#039;light&#039;, RES_LEN);\n    g.rp = &#039;result&#039;; g.resT = RES_LEN;\n    track(&#039;rule_result&#039;, { rule:key, change:d });\n  }\n  \/\/ what spawns depends on the rule; gaps are in seconds so every screen gets the same rhythm\n  function ruleSpawn(){\n    const x = W + 30, key = curRule(), lvl = Math.min(2, cycleN()), sp = g.speed;\n    if (!(g.rp === &#039;rule&#039; || (g.rp === &#039;card&#039; &amp;&amp; g.cardT &lt; 0.6)) || (g.rp === &#039;rule&#039; &amp;&amp; g.rT &lt; 1.3)){ g.nextSpawn = 40; return; }\n    const air = GROUND - 128, low = GROUND - 44;\n    \/\/ a new round brings one chance to repair the site (max twice per run)\n    if (key === &#039;orijinal&#039; &amp;&amp; cycleN() &gt; 0 &amp;&amp; g.heartRound !== g.ri &amp;&amp; (g.heartsGot || 0) &lt; 2 &amp;&amp; g.lives &lt; 3 &amp;&amp; g.rp === &#039;rule&#039;){ g.heartRound = g.ri; g.heartsGot = (g.heartsGot || 0) + 1; add({ kind:&#039;heart&#039;, x, y:GROUND - 118, w:28, h:26, bob:true }); g.nextSpawn = sp * 0.8; return; }\n    if (key === &#039;orijinal&#039;){\n      \/\/ two lanes: originals in one, copies in the other. Look, then decide: jump or stay\n      const upGood = Math.random() &lt; 0.55, n = 3, st = sp * 0.125;\n      for (let k = 0; k &lt; n; k++){\n        add({ kind:&#039;doc&#039;, x:x + k * st, y:(upGood ? air - Math.sin(k \/ (n - 1) * Math.PI) * 18 : low), w:24, h:30 });\n        add({ kind:&#039;copy&#039;, x:x + k * st, y:upGood ? GROUND - 38 : air, w:28, h:34, trap:true });\n      }\n      g.nextSpawn = sp * (rand(0.85, 1.1) - lvl * 0.12);\n    } else if (key === &#039;hiz&#039;){\n      \/\/ heavy images: land on top to compress them; run into their side and the site slows down\n      const tall = lvl &gt; 0 &amp;&amp; Math.random() &lt; 0.35, h = tall ? 58 : 34;\n      add({ kind:&#039;img&#039;, x, y:GROUND - h, w:58, h, mb:(tall ? rand(3.2, 4.8) : rand(1.2, 2.9)).toFixed(1) });\n      if (Math.random() &lt; 0.3 + lvl * 0.25){ add({ kind:&#039;img&#039;, x:x + sp * 0.55, y:GROUND - 34, w:58, h:34, mb:rand(1.2, 2.9).toFixed(1) }); g.nextSpawn = sp * (0.55 + rand(0.7, 0.95)); }\n      else g.nextSpawn = sp * (rand(0.72, 1.0) - lvl * 0.1);\n    } else if (key === &#039;kirik&#039;){\n      \/\/ broken links: 404 holes in the road. Jump them; a repaired link (301) floats over each one\n      const hw = sp * rand(0.22, 0.3 + lvl * 0.04);\n      add({ kind:&#039;hole&#039;, x, y:GROUND, w:hw, h:0 });\n      add({ kind:&#039;link&#039;, x:x + hw \/ 2 - 14, y:GROUND - 150, w:28, h:28 });\n      if (lvl &gt; 0 &amp;&amp; Math.random() &lt; 0.35){ add({ kind:&#039;hole&#039;, x:x + hw + sp * 0.42, y:GROUND, w:sp * 0.24, h:0 }); g.nextSpawn = hw + sp * (0.42 + 0.24 + rand(0.55, 0.8)); }\n      else g.nextSpawn = hw + sp * (rand(0.62, 0.9) - lvl * 0.08);\n    } else if (key === &#039;core&#039;){\n      \/\/ an update shakes the rankings: shields protect what you have; quakes fall and crack the road\n      if ((g.coreSpawnN = ((g.coreSpawnN || 0) + 1) % 3) === 1){\n        add({ kind:&#039;shield&#039;, x, y:GROUND - rand(110, 150), w:30, h:32, bob:true });\n        g.nextSpawn = sp * rand(0.45, 0.6);\n      } else {\n        const landX = PX + sp * rand(0.85, 1.15), T = Math.max(0.7, (W + 40 - landX) \/ sp), y0 = Math.max(-40, GROUND - 420);\n        add({ kind:&#039;quake&#039;, x:landX + sp * T, y:y0, w:34, h:28, fall:(GROUND - 28 - y0) \/ T, rain:true });\n        g.nextSpawn = sp * (rand(0.62, 0.8) - lvl * 0.06);\n      }\n    } else if (key === &#039;core_old&#039;){\n      const upGood = Math.random() &lt; 0.5, gk = Math.random() &lt; 0.5 ? &#039;doc&#039; : &#039;link&#039;, bk = Math.random() &lt; 0.5 ? &#039;copy&#039; : &#039;spamlink&#039;, st = sp * 0.13;\n      const gs = gk === &#039;doc&#039; ? [24, 30] : [28, 28], bs = bk === &#039;copy&#039; ? [28, 34] : [36, 28];\n      for (let k = 0; k &lt; 2; k++){\n        add({ kind:gk, x:x + k * st, y:upGood ? air : GROUND - gs[1] - 8, w:gs[0], h:gs[1] });\n        add({ kind:bk, x:x + k * st, y:upGood ? GROUND - bs[1] - 4 : air, w:bs[0], h:bs[1], trap:true, spin:0 });\n      }\n      g.nextSpawn = sp * (rand(0.68, 0.86) - lvl * 0.08);\n    } else {\n      \/\/ head-on attack announced at the edge: low one = jump, high column = stay down\n      const first = cycleN() === 0, lowOne = Math.random() &lt; (first ? 0.65 : 0.55), vx = sp * (first ? 0.32 : 0.45 + lvl * 0.12);   \/\/ first round: slower, mostly the easy low one\n      if (lowOne) add({ kind:&#039;spam&#039;, x, y:GROUND - 28, w:36, h:28, vx, hold:0.7, dodge:true, spin:0, label:spamTip(&#039;lo&#039;) });\n      else for (let k = 0; k &lt; 3; k++) add({ kind:&#039;spam&#039;, x, y:GROUND - 56 - 28 - k * 31, w:36, h:28, vx, hold:0.7, dodge:k === 0, spin:0, hi:k === 0, label:k === 2 ? spamTip(&#039;hi&#039;) : undefined });\n      g.nextSpawn = sp * ((lowOne ? 0.95 : 0.7) + rand(0.13, 0.4) - lvl * 0.08 + (lvl === 0 ? 0.3 : 0.12) + (first ? 0.25 : 0));\n    }\n  }\n  function startBoss(){\n    const b = g.boss;\n    g.tut = null;\n    g.rp = &#039;boss&#039;; b.active = true; b.t = 0; b.L = -20; b.rx = null; b.nextMove = rand(4, 6); b.rivalSnip = false; b.surge2 = false; b.wi = -1; b.wave = null; b.wasLead = false; b.lead = false; b.lastFlip = -9;\n    b.waves = shuffle([&#039;c&#039;, &#039;t&#039;, &#039;a&#039;]).slice(0, 2);\n    b.str = { c:rand(0.9, 1.2), t:rand(0.9, 1.2), a:rand(0.9, 1.2) };\n    b.surged = false; b.nextThrow = 9; b.windup = 0; b.snipN = 0; b.nextSnip = 25; b.beat = 0; b.fall = 0; b.atak = null; b.atkN = 0; b.nextAtak = 6; b.atkRes = []; b.surpN = 0;\n    g.upd.phase = &#039;idle&#039;; g.upd.timer = 9999;\n    g.objs = g.objs.filter(o =&gt; KIND_PIL[o.kind]);\n    g.crown = false; g.slowmo = 1.0; g.reachT = g.t; track(&#039;final_start&#039;, { seconds:Math.round(g.t) });\n    snd.fanfare(); buzz(60);\n    banner(&#039;Final: 1. s\u0131radaki rakibinle d\u00fcello&#039;, &#039;Tac\u0131 ondan al ve s\u00fcre bitene kadar tut.&#039;, &#039;lime&#039;, 3.2);\n  }\n  \/\/ the rival stands where the race is: ahead of you when it leads, chasing you from behind when you lead\n  function rivalTarget(){ const b = g.boss; return clamp(b.lead ? PX - 54 - Math.max(0, b.L) * 1.4 : PX + 60 + Math.max(0, -b.L) * 2.6, 4, W - 64); }\n  function rivalX(){ const b = g.boss; return b.rx == null ? rivalTarget() : b.rx; }\n  const rivalAhead = () =&gt; rivalX() &gt; PX + 80;\n  function throwAttack(){\n    const b = g.boss, rx = rivalX();\n    if (Math.random() &lt; 0.5){\n      add({ kind:&#039;dup&#039;, x:rx, y:GROUND - 38, w:32, h:38, vx:0, thrown:true });\n    } else {\n      \/\/ an envelope lobbed in an arc toward the player\n      const t = 0.85;\n      add({ kind:&#039;spam&#039;, x:rx, y:GROUND - 70, w:34, h:26, vx:(rx - g.p.x) \/ t - g.speed, vy:-380, arc:true, spin:0, thrown:true });\n    }\n    snd.slide(500, 250, 0.2, &#039;square&#039;, 0.03);\n  }\n  function tickBoss(dt){\n    const b = g.boss;\n    b.t += dt;\n    \/\/ act 1: the rival strikes and takes the crown\n    if (!b.surged &amp;&amp; b.t &gt;= 9 &amp;&amp; b.lead){\n      b.surged = true; b.L -= 18;\n      g.rivalFx = 0.5;\n      snd.meh(); g.shake = 0.4; buzz(40);\n    }\n    if (b.surged &amp;&amp; !b.surge2 &amp;&amp; b.t &gt;= 18 &amp;&amp; b.L &gt; 30){ b.surge2 = true; b.L -= 16; g.rivalFx = 0.5; snd.meh(); g.shake = 0.35; }\n    if (b.t &gt;= b.nextMove &amp;&amp; b.t &lt; BOSS_LEN - 3){\n      b.nextMove = b.t + rand(4.5, 7); b.L -= rand(5, 9);\n      g.rivalFx = 0.5;\n      snd.slide(420, 260, 0.18, &#039;square&#039;, 0.03);\n    }\n    \/\/ act 2: two counter waves\n    const starts = [999, 999];   \/\/ waves replaced by ATAK moments\n    if (b.wi &lt; 1 &amp;&amp; b.t &gt;= starts[b.wi + 1]){\n      b.wi++; { const prev = b.wi ? b.waves[b.wi - 1] : null; b.waves[b.wi] = [&#039;c&#039;, &#039;a&#039;].filter(k =&gt; k !== prev)[0] || &#039;c&#039;; } b.wave = b.waves[b.wi];\n      const m = WAVE_MSG[b.wave];\n      banner(m[0], m[1], &#039;navy&#039;, 2.4); snd.warn();\n    }\n    if (b.t &gt;= 24) b.wave = null;\n    \/\/ ATAK: three timing moments decide the duel. Stop the needle in the green zone\n    if (!b.atak &amp;&amp; b.atkN &lt; 3 &amp;&amp; b.t &gt;= b.nextAtak){\n      b.atkN++; b.nextAtak = b.t + 7;\n      b.atak = { t:0, pre:1.1, dur:3.4, sp:0.72 + b.atkN * 0.14, zc:rand(0.3, 0.7), zw:0.11 - b.atkN * 0.012, ph:Math.random() * 6 };\n      snd.warn(); buzz(20);\n    }\n    \/\/ two surprise attacks: the rival fires spam at you even when you lead (between the ATAK moments)\n    if (!b.atak &amp;&amp; b.surpN &lt; 2 &amp;&amp; b.t &gt;= (b.surpN ? 18.6 : 11.4)){\n      b.surpN++;\n      for (const o of g.objs) if (!o.dead &amp;&amp; o.x &gt; W - 160 &amp;&amp; [&#039;doc&#039;,&#039;link&#039;,&#039;bolt&#039;,&#039;snippet&#039;,&#039;shield&#039;,&#039;heart&#039;].includes(o.kind)) o.dead = true;   \/\/ nothing hides the attack\n      const hi = b.surpN === 2 &amp;&amp; Math.random() &lt; 0.5, vx = g.speed * 0.5;\n      if (hi) for (let k = 0; k &lt; 3; k++) add({ kind:&#039;spam&#039;, x:W + 30, y:GROUND - 84 - k * 31, w:36, h:28, vx, hold:0.8, dodge:k === 0, spin:0, surprise:true, hi:k === 0, label:k === 2 ? &#039;ALTINDAN GE\u00c7&#039; : undefined });\n      else add({ kind:&#039;spam&#039;, x:W + 30, y:GROUND - 28, w:36, h:28, vx, hold:0.8, dodge:true, spin:0, surprise:true, label:&#039;\u00dcST\u00dcNDEN ZIPLA&#039; });\n      banner(&#039;Rakip spam sald\u0131r\u0131s\u0131!&#039;, hi ? &#039;Havadan geliyor: yerde kal.&#039; : &#039;Yerden geliyor: \u00fcst\u00fcnden z\u0131pla.&#039;, &#039;navy&#039;, 1.8); snd.warn(); buzz(30);\n    }\n    \/\/ the rival throws spam and copies back at you (negative SEO)\n    if (b.t &gt;= b.nextThrow - 0.6 &amp;&amp; !b.windup &amp;&amp; b.t &lt; BOSS_LEN - 2){ if (rivalAhead()) b.windup = 0.6; else b.nextThrow = b.t + 0.8; }\n    if (b.windup){ b.windup -= dt * 0.75; if (b.windup &lt;= 0){ b.windup = 0; throwAttack(); b.nextThrow = b.t + (W &lt; 520 ? rand(2.8, 3.8) : rand(2.2, 3.2)); } }\n    \/\/ act 3: the Featured Result appears, the axe at the end of the bridge\n    \/\/ act 3: the Featured Result goes to whoever is ahead when it appears, like the real one\n    if (b.t &gt;= b.nextSnip &amp;&amp; b.snipN &lt; 2 &amp;&amp; (b.lead || !b.rivalSnip) &amp;&amp; !g.objs.some(o =&gt; o.kind === &#039;snippet&#039;)){\n      b.snipN++; b.nextSnip = b.t + 3.5;\n      if (b.lead){\n        add({ kind:&#039;snippet&#039;, x:W + 30, y:GROUND - 196, w:52, h:38, bob:true });\n        if (b.snipN === 1) banner(&#039;\u00d6ne \u00c7\u0131kan Sonu\u00e7 geldi!&#039;, &#039;\u00d6ndesin, kart senin. Z\u0131pla, yakala!&#039;, &#039;lime&#039;, 2.2); else say(&#039;Son \u015fans! Alt\u0131n kart\u0131 yakala!&#039;, 2.2, &#039;lime&#039;);\n        snd.word();\n      } else {\n        b.rivalSnip = true;\n        add({ kind:&#039;snippet&#039;, x:W + 30, y:GROUND - 196, w:52, h:38, bob:true, rivalTake:true, tt:2.4 });\n        banner(&#039;\u00d6ne \u00c7\u0131kan Sonu\u00e7 rakibine gidiyor!&#039;, &#039;\u00d6nde olan al\u0131r. Hemen \u00f6ne ge\u00e7, kart\u0131 kap!&#039;, &#039;navy&#039;, 2.2);\n        snd.warn();\n      }\n    }\n    for (const o of g.objs){\n      if (!o.rivalTake || o.dead) continue;\n      if (b.lead){ o.rivalTake = false; say(&#039;\u00d6ne ge\u00e7tin, kart art\u0131k senin!&#039;, 1.4, &#039;lime&#039;); continue; }\n      \/\/ it drifts to the rival over ~2.4 s: a visible moment, and time to steal it back by taking the lead\n      const rx = rivalX() - 4;\n      o.tt -= dt;\n      o.x += (rx - o.x) * Math.min(1, dt \/ Math.max(0.05, o.tt));\n      if (o.tt &lt; 1) o.y += (GROUND - 118 - o.y) * Math.min(1, dt * 5);\n      if (o.tt &lt;= 0){\n        o.dead = true; b.L -= 22;\n        for (let k = 0; k &lt; 20; k++){ const a = Math.random() * Math.PI * 2, s2 = rand(60, 200); g.parts.push({ x:o.x + o.w \/ 2, y:o.y + o.h \/ 2, vx:Math.cos(a) * s2, vy:Math.sin(a) * s2, r:rand(2, 3.5), c:[&#039;#FFD84D&#039;, &#039;#6F8FD6&#039;, C.white][k % 3], life:0.7, gr:200 }); }\n        say(&#039;\u00d6ne \u00c7\u0131kan Sonu\u00e7 rakibine gitti!&#039;, 1.6, &#039;red&#039;); snd.meh(); g.shake = 0.3;\n      }\n    }\n    \/\/ pressure, rubber-banded so the crown keeps changing hands\n    let pr = FINAL_P * (W &gt;= 600 ? 0.85 : 1) + (b.L &lt; -45 ? -3 : b.L &gt; 45 ? 2 : 0);   \/\/ steady pressure: the lead is earned, only a mild catch-up at the extremes\n    if (b.wave) pr += 4 * b.str[b.wave] * (1.2 - g.pil[b.wave] \/ 100 * 0.7);\n    b.L = clamp(b.L - pr * dt, -100, 100);\n    const lead = b.lead ? b.L &gt; -6 : b.L &gt; 6;\n    b.lead = lead; g.crown = lead;\n    { const tg = rivalTarget(); b.rx = b.rx == null ? tg : b.rx + (tg - b.rx) * Math.min(1, dt * 3.2); }\n    if (lead !== b.wasLead &amp;&amp; b.t - b.lastFlip &gt; 1.2){\n      b.lastFlip = b.t; b.wasLead = lead;\n      if (lead){ if (g.banner) g.banner.life = Math.min(g.banner.life, 0.18); word(&#039;Ta\u00e7 senin!&#039;, true); snd.fanfare(); buzz(30); confetti(25); }\n      else { say(&#039;Rakibin \u00f6ne ge\u00e7ti!&#039;, 1.4, &#039;red&#039;); snd.meh(); }\n    }\n    \/\/ heartbeat, faster at the end\n    b.beat -= dt;\n    if (b.beat &lt;= 0){ b.beat = b.t &gt; BOSS_LEN - 8 ? 0.42 : 0.7; snd.slide(90, 50, 0.16, &#039;sine&#039;, 0.09); }\n    if (b.t &gt;= BOSS_LEN){ b.active = false; b.done = true; endRun(b.lead ? &#039;win&#039; : &#039;lose&#039;); }\n  }\n  function atakPos(a){ return 0.5 + 0.5 * Math.sin(a.ph + a.t * a.sp * Math.PI); }\n  function tickAtak(real){ const a = g.boss.atak; if (!a) return; if (a.pre &gt; 0){ a.pre -= real; return; } a.t += real; if (a.t &gt;= a.dur) resolveAtak(true); }\n  function resolveAtak(timeout){\n    const b = g.boss, a = b.atak; if (!a) return; b.atak = null;\n    const d = Math.abs(atakPos(a) - a.zc);\n    if (!timeout &amp;&amp; d &lt;= a.zw){ b.L = clamp(b.L + 40, -100, 100); b.rx = null; b.atkRes.push(2); word(&#039;M\u00fckemmel atak!&#039;, true); snd.fanfare(); confetti(40); buzz(40); g.shake = 0.3; }\n    else if (!timeout &amp;&amp; d &lt;= a.zw * 2.4){ b.L = clamp(b.L + 20, -100, 100); b.atkRes.push(1); say(&#039;\u0130yi atak! Rakibe yakla\u015ft\u0131n&#039;, 1.2, &#039;lime&#039;); snd.good(); }\n    else { b.L = clamp(b.L - 12, -100, 100); b.atkRes.push(0); say(timeout ? &#039;Atak ka\u00e7t\u0131! Rakip a\u00e7\u0131ld\u0131&#039; : &#039;Iskalad\u0131n! Rakip a\u00e7\u0131ld\u0131&#039;, 1.3, &#039;red&#039;); snd.meh(); g.shake = 0.3; }\n  }\n  function drawAtak(){\n    const a = g.boss.atak; if (!a) return;\n    const bw = Math.min(320, W - 60), bx = (W - bw) \/ 2, cy = Math.max(192, Math.min(GROUND * 0.42, GROUND - 170));   \/\/ always below the race bar\n    ctx.fillStyle = &#039;rgba(2,15,10,0.35)&#039;; ctx.fillRect(0, 0, W, H);\n    ctx.fillStyle = &#039;rgba(4,40,28,0.95)&#039;; rr(bx - 16, cy - 58, bw + 32, 118, 22); ctx.fill();\n    const pre = a.pre &gt; 0;\n    text(pre ? &#039;ATAK GEL\u0130YOR&#039; : &#039;ATAK!&#039;, W \/ 2, cy - 26, `800 ${pre ? 20 : 24}px Poppins, sans-serif`, C.lime);\n    text(pre ? &#039;Haz\u0131r ol, ibre birazdan kayacak&#039; : `\u0130bre ye\u015fildeyken ${TAP}`, W \/ 2, cy - 6, &#039;600 12.5px Inter, sans-serif&#039;, &#039;rgba(255,255,255,0.85)&#039;);\n    if (pre) ctx.globalAlpha = 0.55;\n    const y = cy + 16, hgt = 18;\n    ctx.fillStyle = &#039;#7A2A1A&#039;; rr(bx, y, bw, hgt, 9); ctx.fill();\n    ctx.fillStyle = &#039;#C9A227&#039;; rr(bx + bw * (a.zc - a.zw * 2.6), y, bw * a.zw * 5.2, hgt, 6); ctx.fill();\n    ctx.fillStyle = C.lime; rr(bx + bw * (a.zc - a.zw), y, bw * a.zw * 2, hgt, 5); ctx.fill();\n    const nx = bx + bw * atakPos(a);\n    ctx.fillStyle = C.white; rr(nx - 3, y - 7, 6, hgt + 14, 3); ctx.fill();\n    ctx.globalAlpha = 1;\n    if (pre){ ctx.fillStyle = C.lime; rr(bx, y + hgt + 8, bw * (1 - a.pre \/ 1.1), 3, 1.5); ctx.fill(); }\n    else { ctx.fillStyle = &#039;rgba(255,255,255,0.25)&#039;; rr(bx, y + hgt + 8, bw * (1 - a.t \/ a.dur), 3, 1.5); ctx.fill(); }\n  }\n  function grabSnippet(o){\n    const b = g.boss;\n    o.dead = true;\n    b.L = 100; b.lead = true; b.active = false; b.done = true; b.fall = 0.001;\n    g.crown = true; g.snippet = true;\n    for (let k = 0; k &lt; 30; k++){ const a = Math.random() * Math.PI * 2, s2 = rand(80, 260); g.parts.push({ x:o.x + o.w \/ 2, y:o.y + o.h \/ 2, vx:Math.cos(a) * s2, vy:Math.sin(a) * s2, r:rand(2, 4), c:[&#039;#FFD84D&#039;, C.lime, C.white][k % 3], life:0.9, gr:200, star:k % 3 === 0 }); }\n    track(&#039;snippet&#039;, { seconds:Math.round(b.t) });\n    endRun(&#039;win&#039;);\n  }\n\n  \/\/ ================= update =================\n  function update(dt){\n    const p = g.p, b = g.boss;\n    g.t += dt;\n    if (!g.ending){ if (b.active) tickBoss(dt); else if (!b.done) tickRules(dt); }\n    \/\/ wider screens: the same crossing time feels far faster to the eye, so give them more time (phone = 1, big desktop = 1.75)\n    g.speed = (W - PX) \/ (LOOK[LVL][Math.min(2, b.active ? 2 : cycleN())] * (1 + clamp((W - 440) \/ 360, 0, 1) * 0.4));\n    const dx = g.speed * dt;\n    g.bgOff += dx;\n    p.prevBottom = p.y + p.h;\n    const hm = 8 + g.speed * 0.045, hole = g.objs.find(o =&gt; o.kind === &#039;hole&#039; &amp;&amp; !o.dead &amp;&amp; p.x + p.w \/ 2 &gt; o.x + hm &amp;&amp; p.x + p.w \/ 2 &lt; o.x + o.w - hm);\n    if (hole &amp;&amp; p.y + p.h &gt;= GROUND - 1 &amp;&amp; p.vy &gt;= 0 &amp;&amp; !p.inHole){ p.inHole = hole; p.onGround = false; }\n    const grav = ((p.vy &lt; 0 &amp;&amp; !p.holding) ? GRAV * 1.9 : GRAV) \/ (JS * JS);\n    p.vy += grav * dt; p.y += p.vy * dt;\n    if (p.inHole){\n      if (p.y &gt; GROUND + 50){\n        \/\/ fell into a broken link: lose a life, drop back onto the road\n        const hl = p.inHole; p.inHole = null; hl.fell = true; g.stats.kirik.bad++;\n        for (const o of g.objs) if (o.kind === &#039;hole&#039; &amp;&amp; o.x &lt; p.x + p.w + 40 &amp;&amp; o.x + o.w &gt; p.x - 20) o.dead = true;\n        damage({ kind:&#039;err&#039;, x:p.x, y:GROUND, w:10, h:10 }); p.y = GROUND - p.h - 90; p.vy = 0;\n      }\n    } else if (p.y &gt;= GROUND - p.h){\n      if (!p.onGround &amp;&amp; p.vy &gt; 350) p.squash = 1;\n      p.y = GROUND - p.h; p.vy = 0; p.onGround = true; p.jumps = 0;\n    } else p.onGround = false;\n    p.squash = Math.max(0, p.squash - dt * 6);\n    p.blink -= dt; if (p.blink &lt; -3) p.blink = 0.12;\n\n    g.inv = Math.max(0, g.inv - dt);\n    g.lift = (g.lift || 0) * Math.max(0, 1 - dt * 2.2);\n    music.mode = g.boss.active ? &#039;final&#039; : ((curRule() === &#039;core&#039; || curRule() === &#039;spam&#039;) &amp;&amp; g.rp !== &#039;intro&#039;) ? &#039;update&#039; : &#039;calm&#039;;\n    if (g.bigWord){ g.bigWord.t += dt; if (g.bigWord.t &gt; g.bigWord.life) g.bigWord = null; }\n    g.glitch = Math.max(0, (g.glitch || 0) - dt);\n    g.lb = (g.lb || 0) + (((g.boss.active || (g.boss.done &amp;&amp; g.ending)) ? 1 : 0) - (g.lb || 0)) * Math.min(1, dt * 2.5);\n    g.lifeFx = Math.max(0, g.lifeFx - dt * 2); if (g.lifePop &gt; 0) g.lifePop -= dt;\n    g.shake = Math.max(0, g.shake - dt);\n    g.flash = Math.max(0, g.flash - dt);\n    g.rankFlash = Math.max(0, g.rankFlash - dt);\n    if (g.msg){ g.msg.life -= dt; if (g.msg.life &lt;= 0) g.msg = null; }\n    if (g.banner){ g.banner.life -= dt; if (g.banner.life &lt;= 0){ g.banner = null; if (g.pending &amp;&amp; g.t - g.pending.t &lt; 3){ const pm = g.pending; g.msg = { text:pm.text, life:pm.life, max:pm.life, tone:pm.tone }; } g.pending = null; } }\n    if (g.rankPop){ g.rankPop.life -= dt; if (g.rankPop.life &lt;= 0) g.rankPop = null; }\n    if (g.combo &gt; 0 &amp;&amp; g.t - g.lastPick &gt; 1.3){ g.combo = 0; g.wordIdx = 0; }\n    if (!g.ending){ g.nextSpawn -= dx; if (g.nextSpawn &lt;= 0) spawn(); }\n\n    const pr = { x:p.x + 6, y:p.y + 4, w:p.w - 12, h:p.h - 6 };\n    for (const o of g.objs){\n      if (o.hold &gt; 0){ o.hold -= dt; if (o.hold &lt;= 0) snd.noise(0.3, 0.07, 700, 3200, &#039;bandpass&#039;); continue; }\n      o.x -= dx * (o.kind === &#039;snippet&#039; ? (o.rivalTake ? 0 : 0.55) : 1) + (o.vx || 0) * dt;\n      if (o.arc){ o.vy += 900 * dt; o.y += o.vy * dt; if (o.y + o.h &gt;= GROUND){ o.dead = true; for (let k = 0; k &lt; 6; k++) g.parts.push({ x:o.x + o.w \/ 2, y:GROUND - 4, vx:rand(-90, 90), vy:rand(-160, -60), r:rand(1.5, 2.8), c:C.spam, life:0.45, gr:500 }); continue; } }\n      if (o.fall){ o.y += o.fall * dt; if (o.y + o.h &gt;= GROUND){ o.y = GROUND - o.h; o.fall = 0; o.landed = true; g.shake = Math.max(g.shake, 0.12); for (let k = 0; k &lt; 6; k++) g.parts.push({ x:o.x + o.w \/ 2, y:GROUND - 4, vx:rand(-90, 90), vy:rand(-160, -60), r:rand(1.5, 2.8), c:C.spam, life:0.45, gr:500 }); } }\n      o.by = o.bob ? Math.sin(g.t * 4 + o.id) * 4 : 0;\n      if (o.dead || o.hit || g.ending) continue;\n      if (o.kind === &#039;snippet&#039;){ if (o.rivalTake) continue; const by2 = o.by || 0; if (pr.x &lt; o.x + o.w + 10 &amp;&amp; pr.x + pr.w &gt; o.x - 10 &amp;&amp; pr.y &lt; o.y + by2 + o.h + 10 &amp;&amp; pr.y + pr.h &gt; o.y + by2 - 10) grabSnippet(o); continue; }\n      if (o.kind === &#039;heart&#039;){\n        if (pr.x &lt; o.x + o.w + 6 &amp;&amp; pr.x + pr.w &gt; o.x - 6 &amp;&amp; pr.y &lt; o.y + o.by + o.h + 6 &amp;&amp; pr.y + pr.h &gt; o.y + o.by - 6){\n          o.dead = true; g.lives = Math.min(3, g.lives + 1); g.lifeFx = 0.6;\n          say(&#039;Ekstra can!&#039;, 1.3, &#039;lime&#039;); snd.word(); buzz(20);\n          for (let k = 0; k &lt; 14; k++){ const a = Math.random() * Math.PI * 2, s3 = rand(60, 170); g.parts.push({ x:o.x + 14, y:o.y + 13, vx:Math.cos(a) * s3, vy:Math.sin(a) * s3, r:rand(2, 3.2), c:[C.danger, C.white, &#039;#FF9FB0&#039;][k % 3], life:0.6, gr:200 }); }\n        }\n        continue;\n      }\n      if (o.kind === &#039;hole&#039;){\n        if (!o.passed &amp;&amp; o.x + o.w &lt; p.x &amp;&amp; !o.fell){ o.passed = true; gain(V.dodge); g.rs.good++; g.stats.kirik.good++; }\n        continue;\n      }\n      if (o.kind === &#039;shield&#039;){\n        if (pr.x &lt; o.x + o.w + 6 &amp;&amp; pr.x + pr.w &gt; o.x - 6 &amp;&amp; pr.y &lt; o.y + o.by + o.h + 6 &amp;&amp; pr.y + pr.h &gt; o.y + o.by - 6){\n          o.dead = true; g.shields = Math.min(2, g.shields + 1); if (!g.saidShield){ g.saidShield = true; say(&#039;Kalkan ald\u0131n: 1 sars\u0131nt\u0131y\u0131 durdurur&#039;, 1.6, &#039;lime&#039;); } g.coreGood++; g.rs.good++; g.stats.core.good++;\n          snd.note(880, 0.2, 0.06, 0, &#039;triangle&#039;); snd.note(1320, 0.25, 0.05, 0.08, &#039;triangle&#039;);\n          for (let k = 0; k &lt; 10; k++){ const a2 = Math.random() * 6.28, s3 = rand(60, 160); g.parts.push({ x:o.x + 15, y:o.y + 16, vx:Math.cos(a2) * s3, vy:Math.sin(a2) * s3, r:rand(2, 3), c:[C.lime, C.violet, C.white][k % 3], life:0.5, gr:200 }); }\n        }\n        continue;\n      }\n      if (o.kind === &#039;quake&#039;){\n        if (pr.x &lt; o.x + o.w - 4 &amp;&amp; pr.x + pr.w &gt; o.x + 4 &amp;&amp; pr.y &lt; o.y + o.h - 4 &amp;&amp; pr.y + pr.h &gt; o.y + 4){\n          o.dead = true;\n          if (g.shields &gt; 0){ g.shields--; g.shieldPop = 0.5; say(g.shields ? &#039;Kalkan korudu! 1 kalkan kald\u0131&#039; : &#039;Kalkan korudu!&#039;, 1, &#039;lime&#039;); snd.note(660, 0.15, 0.06, 0, &#039;square&#039;); for (let k = 0; k &lt; 12; k++){ const a2 = Math.random() * 6.28, s3 = rand(80, 200); g.parts.push({ x:p.x + 19, y:p.y + 10, vx:Math.cos(a2) * s3, vy:Math.sin(a2) * s3, r:rand(2, 3), c:C.violet, life:0.5, gr:100 }); } }\n          else { g.coreHits++; g.coreBad++; g.stats.core.bad++; g.rs.bad++; stepRank(-3); g.shake = 0.45; g.flash = 0.2; snd.hit(); buzz(30); say(g.saidQuake ? &#039;Sars\u0131nt\u0131: \u22123 s\u0131ra&#039; : &#039;Kalkans\u0131z yakaland\u0131n: \u22123 s\u0131ra&#039;, 1.2, &#039;red&#039;); g.saidQuake = true; }\n        }\n        continue;\n      }\n      if (o.kind === &#039;img&#039;){\n        \/\/ stomp it from above (or clip it in the air): compressed. Run into it on the ground: crash\n        const ov = pr.x &lt; o.x + o.w - 2 &amp;&amp; pr.x + pr.w &gt; o.x + 2 &amp;&amp; pr.y &lt; o.y + o.h - 2 &amp;&amp; pr.y + pr.h &gt; o.y + 2;\n        const onTop = (!p.onGround &amp;&amp; ov) || (p.vy &gt; 0 &amp;&amp; p.prevBottom &lt;= o.y + 22 &amp;&amp; p.y + p.h &gt;= o.y - 2 &amp;&amp; p.x + p.w &gt; o.x - 6 &amp;&amp; p.x &lt; o.x + o.w + 4);\n        if (onTop){\n          o.dead = true; p.vy = -560; p.jumps = 1; gain(V.stomp); g.rs.good++; g.stats.hiz.good++;\n          g.combo = (g.t - g.lastPick &lt; 1.6) ? g.combo + 1 : 1; g.lastPick = g.t;\n          snd.slide(160, 60, 0.14, &#039;square&#039;, 0.12); snd.note(620, 0.15, 0.05, 0.04);\n          for (let k = 0; k &lt; 16; k++){ const a2 = Math.random() * 6.28, s3 = rand(60, 220); g.parts.push({ x:o.x + o.w \/ 2, y:o.y, vx:Math.cos(a2) * s3, vy:Math.sin(a2) * s3 - 60, r:rand(2, 3.5), c:[C.teal, C.lime, C.white][k % 3], life:0.6, gr:420 }); }\n          word(`\u2212${o.mb} MB!`); g.shake = Math.max(g.shake, 0.15);\n        } else if (ov &amp;&amp; p.onGround){\n          \/\/ a heavy page doesn&#039;t kill the site, it slows it down: rank loss and a stumble\n          o.dead = true; g.stats.hiz.bad++; damage(o);\n        }\n        continue;\n      }\n      if (o.kind === &#039;copy&#039; || o.kind === &#039;spamlink&#039;){\n        if (pr.x &lt; o.x + o.w - 4 &amp;&amp; pr.x + pr.w &gt; o.x + 4 &amp;&amp; pr.y &lt; o.y + o.h - 4 &amp;&amp; pr.y + pr.h &gt; o.y + 4){\n          o.dead = true; const key = curRule(); g.rs.bad++; g.stats[key].bad++; if (key === &#039;core&#039;) g.coreBad++;\n          gain(V.copy); g.combo = 0; g.wordIdx = 0; g.shake = 0.25; snd.hit(); buzz(20);\n          for (let k = 0; k &lt; 8; k++){ const a2 = Math.random() * 6.28, s3 = rand(60, 150); g.parts.push({ x:o.x + o.w \/ 2, y:o.y + o.h \/ 2, vx:Math.cos(a2) * s3, vy:Math.sin(a2) * s3, r:rand(2, 3), c:C.danger, life:0.45, gr:260 }); }\n          if ((g.badSaid = (g.badSaid || 0) + 1) &lt;= 3) say(o.kind === &#039;copy&#039; ? &#039;Kopya i\u00e7erik!&#039; : &#039;\u00c7\u00f6p link!&#039;, 0.9, &#039;red&#039;);\n        }\n        continue;\n      }\n      if (o.dodge &amp;&amp; !o.passed &amp;&amp; o.x + o.w &lt; p.x){ o.passed = true; gain(V.dodge); g.rs.good++; g.stats.spam.good++; g.combo++; snd.pop(Math.min(g.combo, 10)); }\n      const isGood = !!KIND_PIL[o.kind];\n      if (isGood){\n        if (pr.x &lt; o.x + o.w + 8 &amp;&amp; pr.x + pr.w &gt; o.x - 8 &amp;&amp; pr.y &lt; o.y + o.by + o.h + 8 &amp;&amp; pr.y + pr.h &gt; o.y + o.by - 8) collect(o);\n      } else {\n        \/\/ hazards: horizontal overlap scales with scroll speed, so clearing an obstacle takes the same time on every screen\n        const hk = Math.min(1, SPEEDK \/ 0.86);\n        const hw = (o.w \/ 2 - 8) * hk, pw = (p.w \/ 2 - 6) * hk;\n        if (Math.abs((o.x + o.w \/ 2) - (p.x + p.w \/ 2)) &lt; hw + pw &amp;&amp; pr.y &lt; o.y + o.by + o.h - 8 &amp;&amp; pr.y + pr.h &gt; o.y + o.by + 8) damage(o);\n        \/\/ near miss: clearing a ground hazard by a hair is a small thrill and a small reward\n        else if (!o.nm &amp;&amp; !o.rain &amp;&amp; !o.trap &amp;&amp; o.y + o.h &gt;= GROUND - 2 &amp;&amp; !p.onGround &amp;&amp; Math.abs((o.x + o.w \/ 2) - (p.x + p.w \/ 2)) &lt; hw + pw &amp;&amp; p.y + p.h &gt; o.y - 16 &amp;&amp; p.y + p.h &lt;= o.y + 8){\n          o.nm = true; g.nmN = (g.nmN || 0) + 1; g.acc = (g.acc || 0) + 0.4;\n          if (g.nmN &lt;= 3 || Math.random() &lt; 0.35) word(&#039;K\u0131l pay\u0131!&#039;); snd.slide(900, 1500, 0.12, &#039;triangle&#039;, 0.04);\n        }\n      }\n    }\n    g.objs = g.objs.filter(o =&gt; !o.dead &amp;&amp; o.x + o.w &gt; -80);\n\n    for (const f of g.flyers){ f.t += dt \/ 0.45; const e = ease(Math.min(1, f.t)); f.x = f.sx + (f.tx - f.sx) * e; f.y = f.sy + (f.ty - f.sy) * e - Math.sin(e * Math.PI) * 50; }\n    g.flyers = g.flyers.filter(f =&gt; f.t &lt; 1);\n    for (const q of g.pops) q.t += dt \/ 0.18;\n    g.pops = g.pops.filter(q =&gt; q.t &lt; 1);\n    for (const w of g.waves){ w.life -= dt; w.r += dt * 90; }\n    g.waves = g.waves.filter(w =&gt; w.life &gt; 0);\n    for (const q of g.parts){ q.life -= dt; q.x += q.vx * dt; q.y += q.vy * dt; q.vy += q.gr * dt; if (q.sq) q.rot += dt * 5; }\n    g.parts = g.parts.filter(q =&gt; q.life &gt; 0 &amp;&amp; q.y &lt; H + 20);\n    for (const w of g.words) w.t += dt;\n    g.words = g.words.filter(w =&gt; w.t &lt; w.life);\n\n    const r = curRank();\n    if (r &lt; g.best){ g.best = r; g.rankFlash = 0.5; }\n    if (!b.active &amp;&amp; !b.done &amp;&amp; !g.ending){\n      if (r &lt;= 20 &amp;&amp; !g.pageMsg.p2){ g.pageMsg.p2 = true; track(&#039;reach_page2&#039;, { seconds:Math.round(g.t) }); word(&#039;2. sayfa!&#039;, true); snd.word(); confetti(25); }\n      if (r &lt;= 10 &amp;&amp; !g.pageMsg.p1){ g.pageMsg.p1 = true; track(&#039;reach_page1&#039;, { seconds:Math.round(g.t) }); word(&#039;\u0130lk sayfa!&#039;, true); snd.fanfare(); confetti(70); buzz(40); }\n      if (r &lt;= 3 &amp;&amp; !g.pageMsg.p3){ g.pageMsg.p3 = true; word(&#039;\u0130lk 3!&#039;, true); snd.word(); confetti(40); say(&#039;1. s\u0131radaki rakibin seni fark etti&#039;, 2, &#039;dark&#039;); }\n    }\n    const dk = (b.active || (b.done &amp;&amp; g.ending)) ? 1 : 0;\n    g.dark += (dk - g.dark) * Math.min(1, dt * 1.5);\n    \/\/ the world changes page by page: you can see yourself climbing out of the deep pages\n    const pg = Math.min(10, Math.ceil(r \/ 10));\n    if (pg !== g.page &amp;&amp; !b.active &amp;&amp; !b.done){\n      const up = pg &lt; g.page;\n      g.pgA = { from:g.page, to:pg, t:0, up };\n      g.page = pg;\n      if (up){ g.pageFx = 1; snd.noise(0.6, 0.06, 500, 5000, &#039;bandpass&#039;, 0, 1.5); snd.note(523 * Math.pow(2, (10 - pg) * 2 \/ 12), 0.5, 0.05, 0.08, &#039;triangle&#039;); }\n    }\n    if (g.pgA){ g.pgA.t += dt \/ 0.8; if (g.pgA.t &gt;= 1) g.pgA = null; }\n    if (g.pageFx &gt; 0) g.pageFx = Math.max(0, g.pageFx - dt \/ 0.9);\n    const T = (b.active || (b.done &amp;&amp; g.ending)) ? BANDS[3] : pageVis(pg), v = g.vis, kk = Math.min(1, dt * 1.4);\n    for (let i = 0; i &lt; 3; i++){ v.top[i] += (T.top[i] - v.top[i]) * kk; v.bot[i] += (T.bot[i] - v.bot[i]) * kk; }\n    for (const key of [&#039;glow&#039;, &#039;ringA&#039;, &#039;cardA&#039;]) v[key] += (T[key] - v[key]) * kk;\n    scenery(dx);\n  }\n  function scenery(dx){\n    for (const c of g.cards) c.x -= dx * 0.28;\n    g.cards = g.cards.filter(c =&gt; c.x &gt; -240);\n    let lx = g.cards.length ? g.cards[g.cards.length - 1].x : -260;\n    while (lx &lt; W + 260){ lx += 260; g.cards.push({ x:lx, row:g.cards.length % 2, j:Math.random() * 16, tw:100 + Math.random() * 70 }); }\n    for (const r of g.rings){ r.x -= dx * r.k; if (r.x &lt; -r.r - 20){ r.x = W + r.r + rand(0, 200); r.y = rand(GROUND * 0.25, GROUND * 0.7); r.r = rand(80, 150); } }\n  }\n  function confetti(n){ for (let k = 0; k &lt; n; k++) g.parts.push({ x:rand(0, W), y:rand(-80, -5), vx:rand(-40, 40), vy:rand(70, 190), r:rand(2.5, 4.5), c:[C.lime, C.green, C.white, C.violet, C.teal][k % 5], life:rand(1.6, 2.6), gr:50, sq:true, rot:rand(0, 6) }); }\n\n  \/\/ ================= drawing helpers =================\n  function rr(x, y, w, h, r){\n    r = Math.max(0, Math.min(r, w \/ 2, h \/ 2));\n    ctx.beginPath();\n    ctx.moveTo(x + r, y); ctx.lineTo(x + w - r, y); ctx.quadraticCurveTo(x + w, y, x + w, y + r);\n    ctx.lineTo(x + w, y + h - r); ctx.quadraticCurveTo(x + w, y + h, x + w - r, y + h);\n    ctx.lineTo(x + r, y + h); ctx.quadraticCurveTo(x, y + h, x, y + h - r);\n    ctx.lineTo(x, y + r); ctx.quadraticCurveTo(x, y, x + r, y); ctx.closePath();\n  }\n  function text(str, x, y, font, color, align = &#039;center&#039;, base = &#039;alphabetic&#039;){\n    ctx.font = font; ctx.fillStyle = color; ctx.textAlign = align; ctx.textBaseline = base; ctx.fillText(str, x, y);\n  }\n  function cutRing(cx, cy, r, w, col, frac = 1){\n    ctx.lineWidth = w; ctx.strokeStyle = col; ctx.lineCap = &#039;butt&#039;;\n    ctx.beginPath(); ctx.arc(cx, cy, r, RING_START, RING_START + RING_SPAN * clamp(frac, 0, 1)); ctx.stroke();\n  }\n  function ringGrad(cx, cy, r){ const gr = ctx.createLinearGradient(cx - r, cy - r, cx + r, cy + r); gr.addColorStop(0, C.green2); gr.addColorStop(1, &#039;#027A48&#039;); return gr; }\n  function chain(cx, cy, size, col){\n    ctx.save(); ctx.translate(cx, cy); ctx.rotate(-Math.PI \/ 4);\n    ctx.lineWidth = size * 0.16; ctx.strokeStyle = col;\n    const w = size * 0.62, h = size * 0.36;\n    rr(-w * 0.78, -h \/ 2, w, h, h \/ 2); ctx.stroke();\n    rr(-w * 0.22, -h \/ 2, w, h, h \/ 2); ctx.stroke();\n    ctx.restore();\n  }\n  function starPath(cx, cy, r){ ctx.beginPath(); for (let k = 0; k &lt; 10; k++){ const a = -Math.PI \/ 2 + k * Math.PI \/ 5, q = k % 2 ? r * 0.45 : r; ctx.lineTo(cx + Math.cos(a) * q, cy + Math.sin(a) * q); } ctx.closePath(); }\n  const mix = (a, b, t) =&gt; `rgb(${Math.round(a[0] + (b[0] - a[0]) * t)},${Math.round(a[1] + (b[1] - a[1]) * t)},${Math.round(a[2] + (b[2] - a[2]) * t)})`;\n\n  \/\/ ================= drawing =================\n  function drawBackground(){\n    const d = g.dark;\n    const v = g.vis;\n    const sky = ctx.createLinearGradient(0, 0, 0, GROUND);\n    sky.addColorStop(0, mix(v.top, v.top, 0)); sky.addColorStop(1, mix(v.bot, v.bot, 0));\n    ctx.fillStyle = sky; ctx.fillRect(0, 0, W, GROUND);\n    const glow = v.glow;\n    if (glow &gt; 0.02){\n      const gr = ctx.createRadialGradient(W * 0.72, -30, 10, W * 0.72, -30, Math.max(W, H) * 0.8);\n      gr.addColorStop(0, `rgba(201,242,78,${(d &gt; 0.5 ? 0.25 : 0.45) * glow})`); gr.addColorStop(1, &#039;rgba(201,242,78,0)&#039;);\n      ctx.fillStyle = gr; ctx.fillRect(0, 0, W, GROUND);\n    }\n    for (const r of g.rings){ ctx.globalAlpha = v.ringA; cutRing(r.x, r.y, r.r, 26, d &gt; 0.5 ? C.lime : C.green); }\n    ctx.globalAlpha = 1;\n    const top = GROUND - 250 + (g.lift || 0);\n    for (const c of g.cards){\n      const x = c.x, y = top + c.row * 96 + c.j;\n      ctx.fillStyle = d &gt; 0.5 ? &#039;rgba(255,255,255,0.06)&#039; : `rgba(255,255,255,${v.cardA})`; rr(x, y, 200, 70, 14); ctx.fill();\n      ctx.fillStyle = &#039;rgba(3,147,88,0.3)&#039;; ctx.beginPath(); ctx.arc(x + 18, y + 18, 5, 0, Math.PI * 2); ctx.fill();\n      ctx.fillStyle = d &gt; 0.5 ? &#039;rgba(255,255,255,0.08)&#039; : &#039;rgba(4,40,28,0.1)&#039;; rr(x + 30, y + 15, 60, 6, 3); ctx.fill();\n      ctx.fillStyle = d &gt; 0.5 ? &#039;rgba(201,242,78,0.18)&#039; : &#039;rgba(4,106,64,0.22)&#039;; rr(x + 14, y + 31, c.tw, 8, 4); ctx.fill();\n      if (g.page === 1 &amp;&amp; d &lt; 0.5){ ctx.strokeStyle = &#039;rgba(232,180,20,0.7)&#039;; ctx.lineWidth = 2; rr(x, y, 200, 70, 14); ctx.stroke(); ctx.fillStyle = &#039;#E8B414&#039;; starPath(x + 182, y + 18, 7); ctx.fill(); }\n    }\n    if (d &lt; 0.5 &amp;&amp; state !== &#039;start&#039;){\n      if (g.page === 1){\n        \/\/ the first page shines: warm light and sparkles\n        const gl = ctx.createRadialGradient(W * 0.5, -40, 20, W * 0.5, -40, Math.max(W, GROUND) * 0.9); gl.addColorStop(0, &#039;rgba(255,216,77,0.35)&#039;); gl.addColorStop(1, &#039;rgba(255,216,77,0)&#039;);\n        ctx.fillStyle = gl; ctx.fillRect(0, 0, W, GROUND);\n        for (let k = 0; k &lt; 14; k++){ const sx = ((k * 137.5 + g.bgOff * 0.12) % (W + 40)) - 20, sy = 60 + (k * 71) % (GROUND - 120), tw = 0.5 + 0.5 * Math.sin(g.t * 3 + k * 1.7);\n          ctx.globalAlpha = 0.18 + 0.3 * tw; ctx.fillStyle = k % 3 ? &#039;#FFE88A&#039; : C.white; starPath(sx, sy, 2 + tw * 2); ctx.fill(); }\n        ctx.globalAlpha = 1;\n      }\n      if (g.pageFx &gt; 0){\n        const x = (1 - g.pageFx) * (W + 400) - 200, sw = ctx.createLinearGradient(x - 90, 0, x + 90, 0);\n        sw.addColorStop(0, &#039;rgba(255,255,255,0)&#039;); sw.addColorStop(0.5, `rgba(255,255,255,${0.45 * Math.sin(g.pageFx * Math.PI)})`); sw.addColorStop(1, &#039;rgba(255,255,255,0)&#039;);\n        ctx.fillStyle = sw; ctx.fillRect(0, 0, W, GROUND);\n      }\n    }\n    if (g.upd.phase === &#039;active&#039;){\n      const a = 0.07 + 0.04 * Math.sin(g.t * 10);\n      ctx.fillStyle = `rgba(4,40,28,${a})`; ctx.fillRect(0, 0, W, GROUND);\n      ctx.strokeStyle = &#039;rgba(201,242,78,0.35)&#039;; ctx.lineWidth = 2;\n      for (let k = 0; k &lt; 5; k++){ const yy = ((g.bgOff * 0.6 + k * 113) % GROUND); ctx.beginPath(); ctx.moveTo(0, yy); ctx.lineTo(W, yy); ctx.stroke(); }\n    }\n  }\n  function drawGround(){\n    const gg = ctx.createLinearGradient(0, GROUND, 0, H);\n    gg.addColorStop(0, &#039;#0A3A2A&#039;); gg.addColorStop(1, &#039;#04281c&#039;);\n    ctx.fillStyle = gg; ctx.fillRect(0, GROUND, W, H - GROUND);\n    ctx.fillStyle = g.dark &gt; 0.5 ? C.lime : C.green; ctx.fillRect(0, GROUND, W, 4);\n    ctx.fillStyle = &#039;rgba(201,242,78,0.2)&#039;;\n    const off = g.bgOff % 60;\n    for (let x = -off; x &lt; W; x += 60){ rr(x, GROUND + 9, 26, 3, 1.5); ctx.fill(); }\n    \/\/ broken links: holes cut into the road, with a 404 sign\n    for (const o of g.objs){\n      if (o.kind !== &#039;hole&#039; || o.dead) continue;\n      const gr2 = ctx.createLinearGradient(0, GROUND, 0, H); gr2.addColorStop(0, &#039;#010805&#039;); gr2.addColorStop(1, &#039;#000&#039;);\n      ctx.fillStyle = gr2; ctx.fillRect(o.x, GROUND - 1, o.w, 25); ctx.beginPath(); ctx.moveTo(o.x, GROUND + 24); for (let k = 0; k &lt;= 6; k++) ctx.lineTo(o.x + o.w * k \/ 6, GROUND + 24 + (k % 2 ? 6 : 0)); ctx.closePath(); ctx.fill();\n      ctx.fillStyle = C.danger; ctx.fillRect(o.x - 3, GROUND - 1, 3, 5); ctx.fillRect(o.x + o.w, GROUND - 1, 3, 5);\n      ctx.fillStyle = &#039;#3A4A44&#039;; ctx.fillRect(o.x - 12, GROUND - 26, 3, 26);\n      ctx.fillStyle = C.danger; rr(o.x - 30, GROUND - 42, 38, 18, 5); ctx.fill(); text(&#039;404&#039;, o.x - 11, GROUND - 28.5, &#039;800 11px Poppins, sans-serif&#039;, C.white);\n    }\n    \/\/ where you are in the results, like the page numbers under a search result list\n    if (state === &#039;play&#039; &amp;&amp; !(g.boss.active || g.boss.done)){\n      \/\/ the results-page footer everyone knows, in our own letters: SE O O O ... O liva, one O per page, page numbers under them\n      const big = W &gt;= 600, fs = big ? 26 : 19, step = big ? 25 : 19, yL = GROUND + (big ? 38 : 34), yN = yL + (big ? 17 : 16);\n      const fL = `800 ${fs}px Poppins, sans-serif`;\n      ctx.font = fL; const wSE = ctx.measureText(&#039;SE&#039;).width, wLi = ctx.measureText(&#039;liva&#039;).width, gap = fs * 0.12;\n      ctx.font = &#039;700 12px Poppins, sans-serif&#039;; let wPrev = big &amp;&amp; g.page &gt; 1 ? ctx.measureText(&#039;\u2039 \u00d6nceki&#039;).width + 22 : 0, wNext = big &amp;&amp; g.page &lt; 10 ? ctx.measureText(&#039;Sonraki \u203a&#039;).width + 22 : 0;\n      const core = wSE + gap + step * 10 + gap + wLi, lim = BTN_X - 14; let sx = W \/ 2 - core \/ 2;\n      if (sx + core + wNext &gt; lim){ wPrev = wNext = 0; }   \/\/ small desktop windows: never run under the sound buttons\n      if (sx + core &gt; lim) sx = Math.max(12, lim - core);\n      const oc = k =&gt; sx + wSE + gap + step * (k - 0.5);\n      text(&#039;SE&#039;, sx, yL, fL, C.white, &#039;left&#039;);\n      text(&#039;liva&#039;, sx + wSE + gap * 2 + step * 10, yL, fL, C.white, &#039;left&#039;);\n      if (wPrev) text(&#039;\u2039 \u00d6nceki&#039;, sx - 22, yL - 2, &#039;700 12px Poppins, sans-serif&#039;, C.lime, &#039;right&#039;);\n      if (wNext) text(&#039;Sonraki \u203a&#039;, sx + core + 22, yL - 2, &#039;700 12px Poppins, sans-serif&#039;, &#039;rgba(255,255,255,0.4)&#039;, &#039;left&#039;);\n      for (let k = 1; k &lt;= 10; k++){\n        const x = oc(k), cur = k === g.page, pop = cur &amp;&amp; g.pageFx &gt; 0 ? 1 + 0.25 * Math.sin(g.pageFx * Math.PI) : 1;\n        const col = cur ? (k === 1 ? &#039;#FFD84D&#039; : C.lime) : k &lt; g.page ? &#039;rgba(255,255,255,0.92)&#039; : &#039;rgba(255,255,255,0.32)&#039;;\n        ctx.save(); ctx.translate(x, yL); ctx.scale(pop, pop); text(&#039;O&#039;, 0, 0, fL, col); ctx.restore();\n        text(String(k), x, yN, `${cur ? 800 : 600} ${big ? 11.5 : 12}px Poppins, sans-serif`, cur ? col : k &lt; g.page ? &#039;rgba(255,255,255,0.7)&#039; : &#039;rgba(255,255,255,0.3)&#039;);\n      }\n    }\n  }\n  function drawShield(o, x, y){\n    const w = o.w, h = o.h;\n    ctx.fillStyle = `rgba(201,242,78,${0.25 + 0.1 * Math.sin(g.t * 6 + o.id)})`; ctx.beginPath(); ctx.arc(x + w \/ 2, y + h \/ 2, 22, 0, 6.28); ctx.fill();\n    const gr = ctx.createLinearGradient(x, y, x, y + h); gr.addColorStop(0, &#039;#8C7DF2&#039;); gr.addColorStop(1, &#039;#4B3BC4&#039;);\n    ctx.fillStyle = gr; ctx.beginPath(); ctx.moveTo(x + w \/ 2, y); ctx.lineTo(x + w, y + h * 0.2); ctx.lineTo(x + w * 0.9, y + h * 0.65); ctx.lineTo(x + w \/ 2, y + h); ctx.lineTo(x + w * 0.1, y + h * 0.65); ctx.lineTo(x, y + h * 0.2); ctx.closePath(); ctx.fill();\n    ctx.strokeStyle = C.white; ctx.lineWidth = 2.4; ctx.lineCap = &#039;round&#039;; ctx.beginPath(); ctx.moveTo(x + w * 0.3, y + h * 0.5); ctx.lineTo(x + w * 0.46, y + h * 0.66); ctx.lineTo(x + w * 0.72, y + h * 0.36); ctx.stroke(); ctx.lineCap = &#039;butt&#039;;\n  }\n  function drawQuake(o, x, y){\n    const w = o.w, h = o.h;\n    ctx.fillStyle = &#039;rgba(4,40,28,0.15)&#039;; rr(x + 2, y + 3, w, h, 6); ctx.fill();\n    ctx.fillStyle = C.danger; rr(x, y, w, h, 6); ctx.fill();\n    ctx.strokeStyle = &#039;#7A1E08&#039;; ctx.lineWidth = 2; rr(x + 1, y + 1, w - 2, h - 2, 5); ctx.stroke();\n    ctx.strokeStyle = C.white; ctx.lineWidth = 2.6; ctx.lineJoin = &#039;round&#039;; ctx.beginPath(); ctx.moveTo(x + w * 0.2, y + h * 0.3); ctx.lineTo(x + w * 0.42, y + h * 0.62); ctx.lineTo(x + w * 0.56, y + h * 0.36); ctx.lineTo(x + w * 0.8, y + h * 0.72); ctx.stroke(); ctx.lineJoin = &#039;miter&#039;;\n  }\n\n  function drawDoc(x, y, w, h){\n    const f = Math.min(9, w * 0.32);\n    ctx.fillStyle = &#039;rgba(4,40,28,0.13)&#039;;\n    ctx.beginPath(); ctx.moveTo(x + 2, y + 3); ctx.lineTo(x + w - f + 2, y + 3); ctx.lineTo(x + w + 2, y + f + 3); ctx.lineTo(x + w + 2, y + h + 3); ctx.lineTo(x + 2, y + h + 3); ctx.closePath(); ctx.fill();\n    const bg = ctx.createLinearGradient(x, y, x + w, y + h); bg.addColorStop(0, &#039;#FFFFFF&#039;); bg.addColorStop(1, &#039;#E6F3EB&#039;);\n    ctx.fillStyle = bg; ctx.strokeStyle = C.green; ctx.lineWidth = 2;\n    ctx.beginPath(); ctx.moveTo(x, y); ctx.lineTo(x + w - f, y); ctx.lineTo(x + w, y + f); ctx.lineTo(x + w, y + h); ctx.lineTo(x, y + h); ctx.closePath(); ctx.fill(); ctx.stroke();\n    ctx.fillStyle = &#039;#BFE5CF&#039;; ctx.beginPath(); ctx.moveTo(x + w - f, y); ctx.lineTo(x + w - f, y + f); ctx.lineTo(x + w, y + f); ctx.closePath(); ctx.fill();\n    ctx.strokeStyle = &#039;rgba(3,147,88,0.75)&#039;; ctx.lineWidth = 2; ctx.lineCap = &#039;round&#039;; ctx.beginPath();\n    for (let k = 0; k &lt; 3; k++){ const ly = y + h * (0.42 + k * 0.17); ctx.moveTo(x + 5, ly); ctx.lineTo(x + w - (k === 2 ? w * 0.42 : 6), ly); }\n    ctx.stroke(); ctx.lineCap = &#039;butt&#039;;\n  }\n  function drawOrb(x, y, w, c1, c2){\n    const cx = x + w \/ 2, cy = y + w \/ 2, r = w \/ 2;\n    ctx.fillStyle = &#039;rgba(4,40,28,0.13)&#039;; ctx.beginPath(); ctx.arc(cx + 2, cy + 3, r, 0, Math.PI * 2); ctx.fill();\n    const gr = ctx.createLinearGradient(x, y, x + w, y + w); gr.addColorStop(0, c1); gr.addColorStop(1, c2);\n    ctx.fillStyle = gr; ctx.beginPath(); ctx.arc(cx, cy, r, 0, Math.PI * 2); ctx.fill();\n    ctx.fillStyle = &#039;rgba(255,255,255,0.35)&#039;; ctx.beginPath(); ctx.ellipse(cx - r * 0.3, cy - r * 0.45, r * 0.45, r * 0.22, -0.5, 0, Math.PI * 2); ctx.fill();\n    return [cx, cy, r];\n  }\n  function drawLink(x, y, w){ const [cx, cy] = drawOrb(x, y, w, &#039;#8C7DF2&#039;, &#039;#5140C9&#039;); chain(cx, cy, w * 0.78, C.white); }\n  function drawBolt(x, y, w){\n    const [cx, cy, r] = drawOrb(x, y, w, &#039;#2FB3CF&#039;, &#039;#0E7690&#039;);\n    ctx.fillStyle = C.white; ctx.beginPath();\n    ctx.moveTo(cx + r * 0.15, cy - r * 0.7); ctx.lineTo(cx - r * 0.45, cy + r * 0.1); ctx.lineTo(cx - r * 0.02, cy + r * 0.1); ctx.lineTo(cx - r * 0.18, cy + r * 0.72); ctx.lineTo(cx + r * 0.45, cy - r * 0.15); ctx.lineTo(cx + r * 0.02, cy - r * 0.15); ctx.closePath(); ctx.fill();\n  }\n  function drawItem(kind, x, y, w, h){ if (kind === &#039;doc&#039;) drawDoc(x, y, w, h); else if (kind === &#039;bolt&#039;) drawBolt(x, y, w); else drawLink(x, y, w); }\n  function drawGood(o, x, y){\n    const pulse = 0.2 + 0.1 * Math.sin(g.t * 5 + o.id);\n    ctx.fillStyle = `rgba(201,242,78,${pulse})`;\n    ctx.beginPath(); ctx.arc(x + o.w \/ 2, y + o.h \/ 2, 21, 0, Math.PI * 2); ctx.fill();\n    drawItem(o.kind, x, y, o.w, o.h);\n  }\n  function drawDup(o, x, y){\n    const w = o.w, h = o.h, f = 9;\n    const wob = Math.sin(g.t * 6 + o.id) * 1.5;\n    if (!o.trap){ ctx.fillStyle = &#039;rgba(4,40,28,0.12)&#039;; ctx.beginPath(); ctx.ellipse(x + w \/ 2, GROUND + 1, w * 0.55, 4, 0, 0, Math.PI * 2); ctx.fill(); }\n    const body = (ox, oy, a) =&gt; {\n      ctx.globalAlpha = a;\n      const bg = ctx.createLinearGradient(ox, oy, ox, oy + h); bg.addColorStop(0, &#039;#FFD9CC&#039;); bg.addColorStop(1, &#039;#F6A58C&#039;);\n      ctx.fillStyle = bg; ctx.strokeStyle = C.danger; ctx.lineWidth = 2;\n      ctx.beginPath(); ctx.moveTo(ox, oy); ctx.lineTo(ox + w - f, oy); ctx.lineTo(ox + w, oy + f); ctx.lineTo(ox + w, oy + h); ctx.lineTo(ox, oy + h); ctx.closePath(); ctx.fill(); ctx.stroke();\n      ctx.globalAlpha = 1;\n    };\n    body(x + 7, y - 6 + wob, 0.5); body(x, y, 1);\n    ctx.strokeStyle = &#039;#8A2410&#039;; ctx.lineWidth = 2; ctx.lineCap = &#039;round&#039;;\n    ctx.beginPath(); ctx.moveTo(x + 7, y + 13); ctx.lineTo(x + 12, y + 15); ctx.moveTo(x + w - 8, y + 13); ctx.lineTo(x + w - 13, y + 15); ctx.stroke();\n    ctx.fillStyle = &#039;#8A2410&#039;; ctx.beginPath(); ctx.arc(x + 10.5, y + 18, 2, 0, Math.PI * 2); ctx.arc(x + w - 11.5, y + 18, 2, 0, Math.PI * 2); ctx.fill();\n    ctx.beginPath(); ctx.arc(x + w \/ 2 - 0.5, y + 29, 4, 1.15 * Math.PI, 1.85 * Math.PI); ctx.stroke();\n    ctx.lineCap = &#039;butt&#039;;\n  }\n  function drawSpam(o, x, y){\n    const w = o.w, h = o.h, cx = x + w \/ 2, cy = y + h \/ 2;\n    ctx.save(); ctx.translate(cx, cy); ctx.rotate(Math.sin(g.t * 6 + o.id) * 0.12);\n    if (o.fall){ ctx.strokeStyle = &#039;rgba(240,122,26,0.45)&#039;; ctx.lineWidth = 2; ctx.lineCap = &#039;round&#039;; for (let k = 0; k &lt; 3; k++){ ctx.beginPath(); ctx.moveTo(-9 + k * 9, -h \/ 2 - 6); ctx.lineTo(-9 + k * 9, -h \/ 2 - 20); ctx.stroke(); } ctx.lineCap = &#039;butt&#039;; }\n    ctx.fillStyle = &#039;rgba(4,40,28,0.13)&#039;; rr(-w \/ 2 + 2, -h \/ 2 + 3, w, h, 5); ctx.fill();\n    const gr = ctx.createLinearGradient(0, -h \/ 2, 0, h \/ 2); gr.addColorStop(0, &#039;#FF9D4D&#039;); gr.addColorStop(1, &#039;#E4572E&#039;);\n    ctx.fillStyle = gr; rr(-w \/ 2, -h \/ 2, w, h, 5); ctx.fill();\n    ctx.strokeStyle = &#039;rgba(255,255,255,0.9)&#039;; ctx.lineWidth = 2; ctx.lineJoin = &#039;round&#039;;\n    ctx.beginPath(); ctx.moveTo(-w \/ 2 + 3, -h \/ 2 + 3); ctx.lineTo(0, 2); ctx.lineTo(w \/ 2 - 3, -h \/ 2 + 3); ctx.stroke();\n    ctx.strokeStyle = &#039;#5E1A00&#039;; ctx.lineWidth = 1.8; ctx.lineCap = &#039;round&#039;;\n    ctx.beginPath(); ctx.moveTo(-9, 3); ctx.lineTo(-4, 5); ctx.moveTo(9, 3); ctx.lineTo(4, 5); ctx.stroke();\n    ctx.fillStyle = &#039;#5E1A00&#039;; ctx.beginPath(); ctx.arc(-6, 7.5, 1.8, 0, Math.PI * 2); ctx.arc(6, 7.5, 1.8, 0, Math.PI * 2); ctx.fill();\n    ctx.lineCap = &#039;butt&#039;;\n    ctx.fillStyle = C.danger; ctx.beginPath(); ctx.arc(w \/ 2 - 1, -h \/ 2 + 1, 6, 0, Math.PI * 2); ctx.fill();\n    ctx.fillStyle = C.white; ctx.font = &#039;800 9px Poppins, sans-serif&#039;; ctx.textAlign = &#039;center&#039;; ctx.textBaseline = &#039;middle&#039;; ctx.fillText(&#039;!&#039;, w \/ 2 - 1, -h \/ 2 + 1.5);\n    ctx.restore();\n  }\n  function drawErr(o, x, y){\n    const w = o.w, h = o.h, cx = x + w \/ 2, cy = y + h \/ 2;\n    ctx.save(); ctx.translate(cx, cy); ctx.rotate(Math.sin(g.t * 7 + o.id) * 0.1);\n    ctx.strokeStyle = &#039;rgba(228,87,46,0.45)&#039;; ctx.lineWidth = 2; ctx.lineCap = &#039;round&#039;;\n    if (o.fall) for (let k = 0; k &lt; 3; k++){ ctx.beginPath(); ctx.moveTo(-9 + k * 9, -h \/ 2 - 6); ctx.lineTo(-9 + k * 9, -h \/ 2 - 20); ctx.stroke(); }\n    ctx.lineCap = &#039;butt&#039;;\n    ctx.fillStyle = &#039;rgba(4,40,28,0.15)&#039;; rr(-w \/ 2 + 2, -h \/ 2 + 3, w, h, 6); ctx.fill();\n    ctx.fillStyle = &#039;#3A4A44&#039;; rr(-w \/ 2, -h \/ 2, w, h, 6); ctx.fill();\n    ctx.fillStyle = C.danger; rr(-w \/ 2, -h \/ 2, w, 8, 4); ctx.fill(); ctx.fillRect(-w \/ 2, -h \/ 2 + 4, w, 4);\n    ctx.fillStyle = C.white; ctx.beginPath(); ctx.arc(-w \/ 2 + 5, -h \/ 2 + 4, 1.4, 0, Math.PI * 2); ctx.arc(-w \/ 2 + 9, -h \/ 2 + 4, 1.4, 0, Math.PI * 2); ctx.fill();\n    text(o.code, 0, 10, &#039;800 12px Poppins, sans-serif&#039;, &#039;#FFB199&#039;);\n    ctx.restore();\n  }\n  function drawImg(o, x = o.x, y = o.y){\n    const w = o.w, h = o.h;\n    ctx.fillStyle = &#039;rgba(4,40,28,0.15)&#039;; rr(x + 2, y + 3, w, h, 6); ctx.fill();\n    ctx.fillStyle = &#039;#E9EEF0&#039;; rr(x, y, w, h, 6); ctx.fill(); ctx.strokeStyle = &#039;#7C8B92&#039;; ctx.lineWidth = 2; ctx.stroke();\n    ctx.fillStyle = &#039;#9FB7C2&#039;; ctx.beginPath(); ctx.moveTo(x + 6, y + h - 6); ctx.lineTo(x + w * 0.42, y + h * 0.35); ctx.lineTo(x + w * 0.62, y + h - 14); ctx.lineTo(x + w * 0.74, y + h * 0.55); ctx.lineTo(x + w - 6, y + h - 6); ctx.closePath(); ctx.fill();\n    ctx.fillStyle = &#039;#F5C542&#039;; ctx.beginPath(); ctx.arc(x + w - 12, y + 10, 4, 0, 6.28); ctx.fill();\n    if (o.mb){ ctx.fillStyle = C.ink; rr(x + 6, y - 15, w - 12, 13, 6); ctx.fill(); text(o.mb + &#039; MB&#039;, x + w \/ 2, y - 5.5, &#039;800 9px Poppins, sans-serif&#039;, C.lime); }\n  }\n  function drawCopy(o, x, y){\n    drawDup(o, x, y);\n    ctx.save(); ctx.translate(x + o.w \/ 2, y + o.h \/ 2 + 2); ctx.rotate(-0.25);\n    ctx.fillStyle = &#039;rgba(228,87,46,0.95)&#039;; rr(-19, -6, 38, 12, 3); ctx.fill();\n    text(&#039;KOPYA&#039;, 0, 3.5, &#039;800 8px Poppins, sans-serif&#039;, C.white); ctx.restore();\n  }\n  function ruleIcon(kind, x, y, s){\n    if (kind === &#039;doc&#039;) drawDoc(x - 9 * s, y - 11 * s, 18 * s, 22 * s);\n    else if (kind === &#039;img&#039;) drawImg({ w:26 * s, h:20 * s }, x - 13 * s, y - 10 * s);\n    else if (kind === &#039;spam&#039;) drawSpam({ w:26 * s, h:20 * s, id:1 }, x - 13 * s, y - 10 * s);\n    else if (kind === &#039;hole&#039;){ ctx.fillStyle = C.danger; rr(x - 13 * s, y - 8 * s, 26 * s, 16 * s, 4 * s); ctx.fill(); text(&#039;404&#039;, x, y + 4 * s, `800 ${Math.round(10 * s)}px Poppins, sans-serif`, C.white); }\n    else { ctx.fillStyle = C.violet; ctx.beginPath(); ctx.arc(x, y, 11 * s, 0, 6.28); ctx.fill(); ctx.strokeStyle = C.white; ctx.lineWidth = 2.2 * s; ctx.beginPath(); ctx.arc(x, y, 5.5 * s, 0.3, 5.3); ctx.stroke(); ctx.fillStyle = C.white; ctx.beginPath(); ctx.moveTo(x + 6.5 * s, y - 4 * s); ctx.lineTo(x + 3 * s, y - 7.5 * s); ctx.lineTo(x + 8.5 * s, y - 8 * s); ctx.closePath(); ctx.fill(); }\n  }\n  function drawRuleCard(){\n    if (!(g.rp === &#039;intro&#039; || g.rp === &#039;card&#039;) || g.boss.active) return;\n    const key = curRule(), R = RULES[key], cw = Math.min(W - 48, 380), ch = 150, cx = W \/ 2, cy = clamp(GROUND * 0.45, 167, GROUND - 130);   \/\/ never touches the HUD\n    const a = g.rp === &#039;intro&#039; ? Math.min(1, (2.6 - g.cardT) * 5, g.cardT * 4) : Math.min(1, g.cardT * 4, (CARD_LEN - g.cardT) * 6);\n    const pop = g.rp === &#039;card&#039; ? 0.92 + 0.08 * Math.min(1, (CARD_LEN - g.cardT) * 6) : 1;\n    ctx.save(); ctx.globalAlpha = a; ctx.translate(cx, cy); ctx.scale(pop, pop);\n    ctx.fillStyle = &#039;rgba(4,40,28,0.2)&#039;; rr(-cw \/ 2, -ch \/ 2 + 5, cw, ch, 22); ctx.fill();\n    ctx.fillStyle = &#039;rgba(4,40,28,0.94)&#039;; rr(-cw \/ 2, -ch \/ 2, cw, ch, 22); ctx.fill();\n    if (g.rp === &#039;intro&#039;){\n      text(&#039;HEDEF&#039;, 0, -44, &#039;800 11px Poppins, sans-serif&#039;, &#039;rgba(255,255,255,0.6)&#039;);\n      text(&#039;Siteni 1. s\u0131raya ta\u015f\u0131&#039;, 0, -16, &#039;800 22px Poppins, sans-serif&#039;, C.white);\n      text(&#039;100. s\u0131radan ba\u015fl\u0131yorsun.&#039;, 0, 14, &#039;600 13px Inter, sans-serif&#039;, &#039;rgba(255,255,255,0.85)&#039;);\n      text(&#039;Zirvede 1. s\u0131radaki rakip bekliyor.&#039;, 0, 36, &#039;700 13px Inter, sans-serif&#039;, C.lime);\n    } else {\n      text(g.ri === 0 ? &#039;\u0130LK KURAL&#039; : cycleN() &gt; 0 &amp;&amp; key === &#039;orijinal&#039; ? &#039;YEN\u0130 TUR \u00b7 DAHA HIZLI&#039; : &#039;ALGOR\u0130TMA KURALI DE\u011e\u0130\u015eT\u0130RD\u0130&#039;, 0, -46, &#039;800 11px Poppins, sans-serif&#039;, &#039;rgba(255,255,255,0.6)&#039;);\n      ruleIcon(R.icon, 0, -16, 1.35);\n      text(R.title, 0, 26, &#039;800 21px Poppins, sans-serif&#039;, C.lime);\n      ctx.font = &#039;600 12.5px Inter, sans-serif&#039;; const tw = ctx.measureText(R.line).width, f = Math.min(1, (cw - 30) \/ tw);\n      ctx.save(); ctx.translate(0, 52); ctx.scale(f, f); text(R.line, 0, 0, &#039;600 12.5px Inter, sans-serif&#039;, C.white); ctx.restore();\n    }\n    ctx.restore();\n  }\n  function drawBuddy(x, y, w, h, opts = {}){\n    const top = opts.rival ? [&#039;#3D5FA8&#039;, C.navy] : [&#039;#FFFFFF&#039;, &#039;#E6F1EA&#039;];\n    const bg = ctx.createLinearGradient(x, y, x, y + h); bg.addColorStop(0, top[0]); bg.addColorStop(1, top[1]);\n    ctx.fillStyle = &#039;rgba(4,40,28,0.16)&#039;; rr(x + 1.5, y + 3, w, h, 10); ctx.fill();\n    ctx.fillStyle = bg; rr(x, y, w, h, 10); ctx.fill();\n    ctx.strokeStyle = &#039;rgba(4,40,28,0.14)&#039;; ctx.lineWidth = 1.2; ctx.stroke();\n    ctx.fillStyle = opts.rival ? &#039;#9DB4E6&#039; : C.green; rr(x + 5, y + 7, 4, h - 14, 2); ctx.fill();\n    const ey = y + h * 0.44, blink = opts.blink ? 0.2 : 1, eye = opts.rival ? C.white : C.ink;\n    for (const ex of [x + w * 0.46, x + w * 0.74]){\n      ctx.fillStyle = eye; ctx.beginPath(); ctx.ellipse(ex, ey, 3.3 * w \/ 38, 4.2 * blink * w \/ 38, 0, 0, Math.PI * 2); ctx.fill();\n      if (blink === 1 &amp;&amp; !opts.rival){ ctx.fillStyle = C.white; ctx.beginPath(); ctx.arc(ex + 1, ey - 1.5, 1.2, 0, Math.PI * 2); ctx.fill(); }\n    }\n    if (opts.rival){ ctx.strokeStyle = C.white; ctx.lineWidth = 2; ctx.beginPath(); ctx.moveTo(x + w * 0.38, ey - 7); ctx.lineTo(x + w * 0.52, ey - 5); ctx.moveTo(x + w * 0.82, ey - 7); ctx.lineTo(x + w * 0.68, ey - 5); ctx.stroke(); }\n    else { ctx.fillStyle = &#039;rgba(201,242,78,0.9)&#039;; ctx.beginPath(); ctx.ellipse(x + w * 0.36, ey + 6, 3, 1.8, 0, 0, Math.PI * 2); ctx.ellipse(x + w * 0.86, ey + 6, 3, 1.8, 0, 0, Math.PI * 2); ctx.fill(); }\n    ctx.strokeStyle = eye; ctx.lineWidth = 1.8; ctx.lineCap = &#039;round&#039;; ctx.beginPath();\n    if (opts.sad) ctx.arc(x + w * 0.6, ey + 9, 3, 1.15 * Math.PI, 1.85 * Math.PI);\n    else if (opts.happy) ctx.arc(x + w * 0.6, ey + 4, 4.4, 0.05 * Math.PI, 0.95 * Math.PI);\n    else if (opts.rival) { ctx.moveTo(x + w * 0.5, ey + 8); ctx.lineTo(x + w * 0.7, ey + 7); }\n    else ctx.arc(x + w * 0.6, ey + 4.5, 3.6, 0.15 * Math.PI, 0.85 * Math.PI);\n    ctx.stroke(); ctx.lineCap = &#039;butt&#039;;\n  }\n  function drawCrown(cx, by, s = 1){\n    ctx.fillStyle = C.lime; ctx.strokeStyle = C.ink; ctx.lineWidth = 1.6;\n    ctx.beginPath(); ctx.moveTo(cx - 11 * s, by); ctx.lineTo(cx - 12 * s, by - 11 * s); ctx.lineTo(cx - 5 * s, by - 5 * s); ctx.lineTo(cx, by - 13 * s); ctx.lineTo(cx + 5 * s, by - 5 * s); ctx.lineTo(cx + 12 * s, by - 11 * s); ctx.lineTo(cx + 11 * s, by); ctx.closePath(); ctx.fill(); ctx.stroke();\n  }\n  function legs(x, w, feetY, run, t){\n    ctx.strokeStyle = C.ink; ctx.lineWidth = 3.5; ctx.lineCap = &#039;round&#039;;\n    const ph = run ? Math.sin(t * 22) : 0.5;\n    ctx.beginPath();\n    ctx.moveTo(x + w * 0.36, feetY - 8); ctx.lineTo(x + w * 0.36 + ph * 4, feetY - 1);\n    ctx.moveTo(x + w * 0.7, feetY - 8); ctx.lineTo(x + w * 0.7 - ph * 4, feetY - 1);\n    ctx.stroke(); ctx.lineCap = &#039;butt&#039;;\n  }\n  function drawRival(){\n    const b = g.boss;\n    if (!(b.active || (b.done &amp;&amp; g.ending))) return;\n    const w = 54, h = 44;\n    const x = rivalX();\n    let hop = Math.abs(Math.sin(g.t * 9)) * 5, feetY = GROUND - hop, rot = 0, alpha = 1;\n    if (b.fall){ b.fall += 1 \/ 60; feetY = GROUND + b.fall * b.fall * 900; rot = b.fall * 2; alpha = Math.max(0, 1 - b.fall * 1.2); }\n    const y = feetY - 8 - h;\n    ctx.save(); ctx.globalAlpha = alpha;\n    if (!b.fall){ ctx.fillStyle = &#039;rgba(0,0,0,0.25)&#039;; ctx.beginPath(); ctx.ellipse(x + w \/ 2, GROUND + 1, 24, 4, 0, 0, Math.PI * 2); ctx.fill(); }\n    ctx.translate(x + w \/ 2, y + h \/ 2); ctx.rotate(rot); ctx.translate(-(x + w \/ 2), -(y + h \/ 2));\n    if (g.rivalFx &gt; 0){ g.rivalFx -= 1 \/ 60; ctx.strokeStyle = `rgba(111,143,214,${g.rivalFx * 1.6})`; ctx.lineWidth = 3; ctx.beginPath(); ctx.arc(x + w \/ 2, y + h \/ 2, 30 + (0.5 - g.rivalFx) * 50, 0, Math.PI * 2); ctx.stroke(); }\n    legs(x, w, feetY, !b.fall, g.t + 0.3);\n    drawBuddy(x, y, w, h, { rival:true });\n    ctx.fillStyle = &#039;#F07A1A&#039;; rr(x + w - 12, y + 6, 6, h - 12, 3); ctx.fill();\n    if (b.windup &gt; 0){\n      const s = 1 + Math.sin(g.t * 30) * 0.1;\n      ctx.fillStyle = C.danger; ctx.beginPath(); ctx.arc(x + w \/ 2, y - 16, 10 * s, 0, Math.PI * 2); ctx.fill();\n      text(&#039;!&#039;, x + w \/ 2, y - 11, &#039;800 14px Poppins, sans-serif&#039;, C.white);\n    } else {\n      ctx.font = &#039;800 11px Poppins, sans-serif&#039;;\n      const label = &#039;RAK\u0130P&#039;, tw = ctx.measureText(label).width + 16;\n      const ly = y - (!b.lead ? 38 : 24);\n      ctx.fillStyle = C.navy; rr(x + w \/ 2 - tw \/ 2, ly, tw, 18, 9); ctx.fill();\n      text(label, x + w \/ 2, ly + 13, &#039;800 11px Poppins, sans-serif&#039;, C.white);\n    }\n    if (!b.lead &amp;&amp; !b.fall) drawCrown(x + w \/ 2, y - 2, 1.15);\n    ctx.restore();\n    if (b.fall){ text(&#039;#2&#039;, x + w \/ 2, Math.min(GROUND - 20, y + 10), &#039;800 22px Poppins, sans-serif&#039;, `rgba(255,255,255,${alpha})`); }\n  }\n  function drawSnippet(o, x, y){\n    const pulse = 0.5 + 0.5 * Math.sin(g.t * 8);\n    const gl = ctx.createRadialGradient(x + o.w \/ 2, y + o.h \/ 2, 4, x + o.w \/ 2, y + o.h \/ 2, 60);\n    gl.addColorStop(0, `rgba(255,216,77,${0.55 + 0.25 * pulse})`); gl.addColorStop(1, &#039;rgba(255,216,77,0)&#039;);\n    ctx.fillStyle = gl; ctx.beginPath(); ctx.arc(x + o.w \/ 2, y + o.h \/ 2, 60, 0, Math.PI * 2); ctx.fill();\n    ctx.fillStyle = &#039;rgba(0,0,0,0.2)&#039;; rr(x + 2, y + 4, o.w, o.h, 8); ctx.fill();\n    const gr = ctx.createLinearGradient(x, y, x, y + o.h); gr.addColorStop(0, &#039;#FFE680&#039;); gr.addColorStop(1, &#039;#F2B400&#039;);\n    ctx.fillStyle = gr; rr(x, y, o.w, o.h, 8); ctx.fill();\n    ctx.strokeStyle = &#039;#8A5A00&#039;; ctx.lineWidth = 1.5; ctx.stroke();\n    ctx.fillStyle = &#039;rgba(138,90,0,0.55)&#039;; rr(x + 8, y + 10, o.w - 22, 5, 2.5); ctx.fill(); rr(x + 8, y + 19, o.w - 16, 4, 2); ctx.fill(); rr(x + 8, y + 26, o.w - 26, 4, 2); ctx.fill();\n    starPath(x + o.w - 9, y + 11, 6); ctx.fillStyle = C.white; ctx.fill();\n    \/\/ arrow hint\n    const ay = y - 18 + Math.sin(g.t * 10) * 3;\n    ctx.strokeStyle = &#039;#FFD84D&#039;; ctx.lineWidth = 3; ctx.lineCap = &#039;round&#039;;\n    ctx.beginPath(); ctx.moveTo(x + o.w \/ 2, ay - 10); ctx.lineTo(x + o.w \/ 2, ay); ctx.moveTo(x + o.w \/ 2 - 5, ay - 5); ctx.lineTo(x + o.w \/ 2, ay); ctx.lineTo(x + o.w \/ 2 + 5, ay - 5); ctx.stroke(); ctx.lineCap = &#039;butt&#039;;\n  }\n  function drawSpots(){\n    const b = g.boss;\n    if (!(b.active || (b.done &amp;&amp; g.ending))) return;\n    const cones = [[g.p.x + 19, &#039;rgba(201,242,78,0.10)&#039;], [rivalX() + 27, &#039;rgba(111,143,214,0.10)&#039;]];\n    for (const [cx, col] of cones){\n      const gr = ctx.createLinearGradient(0, 0, 0, GROUND);\n      gr.addColorStop(0, &#039;rgba(255,255,255,0)&#039;); gr.addColorStop(1, col);\n      ctx.fillStyle = gr; ctx.beginPath(); ctx.moveTo(cx - 18, 0); ctx.lineTo(cx + 18, 0); ctx.lineTo(cx + 70, GROUND); ctx.lineTo(cx - 70, GROUND); ctx.closePath(); ctx.fill();\n    }\n  }\n  function drawPlayer(){\n    const p = g.p;\n    const hgt = GROUND - (p.y + p.h);\n    ctx.fillStyle = `rgba(4,40,28,${0.18 * Math.max(0.3, 1 - hgt \/ 200)})`;\n    ctx.beginPath(); ctx.ellipse(p.x + p.w \/ 2, GROUND + 1, 18 * Math.max(0.5, 1 - hgt \/ 250), 4, 0, 0, Math.PI * 2); ctx.fill();\n    if (g.inv &gt; 0 &amp;&amp; Math.floor(g.inv * 14) % 2 === 0) return;\n    const sq = p.squash, bodyH = 32;\n    const w = p.w * (1 + sq * 0.18), h = bodyH * (1 - sq * 0.18);\n    const x = p.x - (w - p.w) \/ 2, feetY = p.y + p.h, y = feetY - 7 - h;\n    legs(x, w, feetY, p.onGround &amp;&amp; state === &#039;play&#039; &amp;&amp; !g.ending, g.t);\n    drawBuddy(x, y, w, h, { blink:p.blink &gt; 0, sad:g.inv &gt; 0.7, happy:g.combo &gt;= 5 || g.crown });\n    if (g.crown) drawCrown(x + w \/ 2 + 2, y - 1);\n  }\n\n  function drawFX(){\n    for (const q of g.pops){\n      const s = 1 + ease(q.t) * 0.7, a = 1 - q.t;\n      ctx.save(); ctx.globalAlpha = a;\n      ctx.translate(q.x + q.w \/ 2, q.y + q.h \/ 2); ctx.scale(s, s); ctx.translate(-(q.x + q.w \/ 2), -(q.y + q.h \/ 2));\n      drawItem(q.kind, q.x, q.y, q.w, q.h);\n      ctx.restore();\n    }\n    for (const w of g.waves){ ctx.globalAlpha = Math.max(0, w.life \/ 0.4) * 0.9; cutRing(w.x, w.y, w.r, 3.5, w.col); }\n    ctx.globalAlpha = 1;\n    for (const q of g.parts){\n      ctx.globalAlpha = Math.max(0, Math.min(1, q.life * 2.2));\n      ctx.fillStyle = q.c;\n      if (q.sq){ ctx.save(); ctx.translate(q.x, q.y); ctx.rotate(q.rot); ctx.fillRect(-q.r, -q.r \/ 2, q.r * 2, q.r); ctx.restore(); }\n      else if (q.star){ starPath(q.x, q.y, q.r * 1.6); ctx.fill(); }\n      else { ctx.beginPath(); ctx.arc(q.x, q.y, q.r, 0, Math.PI * 2); ctx.fill(); }\n    }\n    ctx.globalAlpha = 1;\n  }\n  function drawFlyers(){\n    for (const f of g.flyers){\n      ctx.fillStyle = &#039;rgba(201,242,78,0.5)&#039;; ctx.beginPath(); ctx.arc(f.x, f.y, 8, 0, Math.PI * 2); ctx.fill();\n      ctx.fillStyle = f.col; ctx.beginPath(); ctx.arc(f.x, f.y, 4.5, 0, Math.PI * 2); ctx.fill();\n    }\n  }\n\n  function candy(textStr, cy, size, s, a, rot = -0.06){\n    ctx.save(); ctx.globalAlpha = a; ctx.translate(W \/ 2, cy); ctx.rotate(rot); ctx.scale(s, s);\n    ctx.font = `800 ${size}px Poppins, sans-serif`; ctx.textAlign = &#039;center&#039;; ctx.textBaseline = &#039;middle&#039;;\n    const tw = ctx.measureText(textStr).width;\n    if (tw &gt; W - 40){ const k = (W - 40) \/ tw; ctx.scale(k, k); }\n    ctx.lineJoin = &#039;round&#039;; ctx.lineWidth = 10; ctx.strokeStyle = C.ink; ctx.strokeText(textStr, 0, 0);\n    const gr = ctx.createLinearGradient(0, -size \/ 2, 0, size \/ 2); gr.addColorStop(0, &#039;#E4FF8A&#039;); gr.addColorStop(1, &#039;#9ED62B&#039;);\n    ctx.fillStyle = gr; ctx.fillText(textStr, 0, 0);\n    ctx.restore();\n  }\n  const skyY = () =&gt; H &gt; 520 ? GROUND - 262 : Math.min(GROUND - 200, Math.max(150, GROUND * 0.4));\n  function drawWords(){\n    if (!g.boss.atak) for (const w of g.words){\n      const t = w.t;\n      const s = t &lt; 0.16 ? (t \/ 0.16) * 1.25 : t &lt; 0.3 ? 1.25 - (t - 0.16) \/ 0.14 * 0.25 : 1;\n      candy(w.text, skyY() - t * 16, w.big ? 44 : 36, s, Math.min(1, (w.life - t) \/ 0.3));\n    }\n  }\n  function drawBigWord(){\n    const w = g.bigWord; if (!w) return;\n    const t = w.t, s2 = t &lt; 0.18 ? (t \/ 0.18) * 1.35 : t &lt; 0.34 ? 1.35 - (t - 0.18) \/ 0.16 * 0.35 : 1;\n    candy(w.text, skyY() - 70 - t * 10, 54, s2, Math.min(1, (w.life - t) \/ 0.35), -0.04);\n  }\n  function drawBanner(){\n    const bn = g.banner; if (!bn) return;\n    const age = bn.max - bn.life, a = Math.min(1, age * 6, bn.life * 4);\n    const pal = { dark:[C.ink, C.lime, &#039;rgba(255,255,255,.85)&#039;], red:[C.danger, C.white, &#039;rgba(255,255,255,.9)&#039;], lime:[C.lime, C.ink, C.deep], light:[C.white, C.ink, C.muted], navy:[C.navy, C.white, &#039;rgba(255,255,255,.85)&#039;] }[bn.tone];\n    ctx.font = &#039;800 17px Poppins, sans-serif&#039;; const t1 = ctx.measureText(bn.title).width;\n    ctx.font = &#039;500 12.5px Inter, sans-serif&#039;; const t2 = ctx.measureText(bn.sub).width;\n    const w = Math.min(W - 24, Math.max(t1, t2) + 40), h = 58;\n    const fit = Math.min(1, (w - 32) \/ Math.max(t1, t2));\n    const pop = age &lt; 0.18 ? 0.9 + (age \/ 0.18) * 0.1 : 1;\n    const cy = g.boss.active ? Math.max(skyY() - 10, 150) : skyY() - 10;\n    ctx.save(); ctx.globalAlpha = a; ctx.translate(W \/ 2, cy); ctx.scale(pop, pop);\n    ctx.fillStyle = &#039;rgba(4,40,28,0.16)&#039;; rr(-w \/ 2, -h \/ 2 + 4, w, h, 18); ctx.fill();\n    ctx.fillStyle = pal[0]; rr(-w \/ 2, -h \/ 2, w, h, 18); ctx.fill();\n    ctx.save(); ctx.scale(fit, fit);\n    text(bn.title, 0, -3 \/ fit, &#039;800 17px Poppins, sans-serif&#039;, pal[1]);\n    text(bn.sub, 0, 17 \/ fit, &#039;500 12.5px Inter, sans-serif&#039;, pal[2]);\n    ctx.restore();\n    ctx.restore();\n  }\n\n  function hudLayout(){\n    const gx0 = 12 + 132 + 8, room = W - gx0 - 12 - 96 - 8, gw = Math.min(room, 420), gx = gx0 + (room - gw) \/ 2;   \/\/ wide screens: the rule chip stays chip-sized, centred\n    return { gx, gw, rows:{ c:26, t:41, a:56 } };\n  }\n  function drawMini(k, cx, cy){\n    if (k === &#039;c&#039;){\n      ctx.fillStyle = C.white; ctx.strokeStyle = C.green; ctx.lineWidth = 1.5;\n      ctx.beginPath(); ctx.moveTo(cx - 4, cy - 5.5); ctx.lineTo(cx + 2, cy - 5.5); ctx.lineTo(cx + 4.5, cy - 3); ctx.lineTo(cx + 4.5, cy + 5.5); ctx.lineTo(cx - 4, cy + 5.5); ctx.closePath(); ctx.fill(); ctx.stroke();\n      ctx.beginPath(); ctx.moveTo(cx - 2, cy); ctx.lineTo(cx + 2.5, cy); ctx.moveTo(cx - 2, cy + 2.5); ctx.lineTo(cx + 2.5, cy + 2.5); ctx.stroke();\n    } else {\n      ctx.fillStyle = k === &#039;t&#039; ? C.teal : C.violet; ctx.beginPath(); ctx.arc(cx, cy, 6, 0, Math.PI * 2); ctx.fill();\n      if (k === &#039;t&#039;){ ctx.fillStyle = C.white; ctx.beginPath(); ctx.moveTo(cx + 1, cy - 4.2); ctx.lineTo(cx - 2.8, cy + 0.6); ctx.lineTo(cx - 0.2, cy + 0.6); ctx.lineTo(cx - 1.2, cy + 4.2); ctx.lineTo(cx + 2.8, cy - 0.8); ctx.lineTo(cx + 0.2, cy - 0.8); ctx.closePath(); ctx.fill(); }\n      else chain(cx, cy, 9, C.white);\n    }\n  }\n  function heart(cx, cy, r, fill, stroke){\n    ctx.beginPath();\n    ctx.moveTo(cx, cy + r * 0.9);\n    ctx.bezierCurveTo(cx - r * 1.4, cy - r * 0.1, cx - r * 0.7, cy - r * 1.1, cx, cy - r * 0.35);\n    ctx.bezierCurveTo(cx + r * 0.7, cy - r * 1.1, cx + r * 1.4, cy - r * 0.1, cx, cy + r * 0.9);\n    ctx.closePath();\n    if (fill){ ctx.fillStyle = fill; ctx.fill(); ctx.fillStyle = &#039;rgba(255,255,255,0.45)&#039;; ctx.beginPath(); ctx.ellipse(cx - r * 0.42, cy - r * 0.35, r * 0.22, r * 0.14, -0.6, 0, Math.PI * 2); ctx.fill(); }\n    if (stroke){ ctx.strokeStyle = stroke; ctx.lineWidth = 2; ctx.stroke(); }\n  }\n  function drawHUD(){\n    const jit = 0;\n    const r = curRank();\n    \/\/ rank pill\n    const into = r === 1 ? 1 : 1 - ((r - 1) % 10) \/ 10;\n    ctx.fillStyle = &#039;rgba(255,255,255,0.95)&#039;; rr(12, 12, 132, 56, 18); ctx.fill();\n    const gx0 = 38, gy0 = 40;\n    cutRing(gx0, gy0, 14, 6, &#039;#E1EAE4&#039;);\n    cutRing(gx0, gy0, 14, 6, ringGrad(gx0, gy0, 14), into);\n    text(&#039;SIRAN&#039;, 62, 32, &#039;600 9.5px Inter, sans-serif&#039;, C.muted, &#039;left&#039;);\n    if (g.rankPop){ const rp = g.rankPop; ctx.globalAlpha = Math.min(1, rp.life * 2); text(rp.text, 134, 40 - (0.9 - rp.life) * 18, &#039;800 15px Poppins, sans-serif&#039;, rp.good ? C.green : C.danger, &#039;right&#039;); ctx.globalAlpha = 1; }\n    const s = 1 + g.rankFlash * 0.25;\n    ctx.save(); ctx.translate(62, 58); ctx.scale(s, s);\n    text(&#039;#&#039; + r, 0, 0, &#039;800 25px Poppins, sans-serif&#039;, jit &gt; 0 ? C.danger : r === 1 ? C.green : C.ink, &#039;left&#039;);\n    ctx.restore();\n    \/\/ current rule (or the final): what the algorithm wants right now\n    const L = hudLayout();\n    ctx.fillStyle = &#039;rgba(255,255,255,0.95)&#039;; rr(L.gx, 12, L.gw, 56, 18); ctx.fill();\n    if (g.boss.active || g.boss.done){ text(&#039;F\u0130NAL \u00b7 KALAN&#039;, L.gx + L.gw \/ 2, 36, &#039;800 10px Poppins, sans-serif&#039;, C.muted); text(Math.max(0, Math.ceil(BOSS_LEN - g.boss.t)) + &#039; sn&#039;, L.gx + L.gw \/ 2, 56, &#039;800 17px Poppins, sans-serif&#039;, g.boss.t &gt; BOSS_LEN - 8 ? C.danger : C.ink); }\n    else if (g.rp === &#039;intro&#039;){ text(&#039;HEDEF&#039;, L.gx + L.gw \/ 2, 36, &#039;800 10px Poppins, sans-serif&#039;, C.muted); text(&#039;1. s\u0131ra&#039;, L.gx + L.gw \/ 2, 56, &#039;800 16px Poppins, sans-serif&#039;, C.green); }\n    else {\n      const R = RULES[curRule()], tl = g.rp === &#039;rule&#039; ? clamp(g.rT \/ RULE_LEN, 0, 1) : g.rp === &#039;card&#039; ? 1 : 0;\n      ruleIcon(R.icon, L.gx + 20, 34, 0.75);\n      text(&#039;KURAL&#039;, L.gx + 36, 29, &#039;800 9px Poppins, sans-serif&#039;, C.muted, &#039;left&#039;);\n      ctx.font = &#039;800 12px Poppins, sans-serif&#039;; const shN = 0, tw = ctx.measureText(R.title).width, f = Math.min(1, (L.gw - 46 - shN * 15) \/ tw);\n      ctx.save(); ctx.translate(L.gx + 36, 44); ctx.scale(f, f); text(R.title, 0, 0, &#039;800 12px Poppins, sans-serif&#039;, C.ink, &#039;left&#039;); ctx.restore();\n      if (curRule() === &#039;core&#039; &amp;&amp; g.rp === &#039;rule&#039;) for (let k = 0; k &lt; shN; k++) drawShield({ w:12, h:13, id:k }, L.gx + L.gw - 18 - k * 15, 22);\n      ctx.fillStyle = &#039;#E4EDE7&#039;; rr(L.gx + 12, 54, L.gw - 24, 5, 2.5); ctx.fill();\n      ctx.fillStyle = tl &lt; 0.25 ? C.danger : R.col; rr(L.gx + 12, 54, Math.max(5, (L.gw - 24) * tl), 5, 2.5); ctx.fill();\n    }\n    \/\/ lives\n    {\n      const lx = W - 12 - 96;\n      const sh = g.lifeFx &gt; 0 &amp;&amp; !reduceMotion ? Math.sin(g.lifeFx * 40) * 3 * g.lifeFx : 0;\n      ctx.fillStyle = &#039;rgba(255,255,255,0.95)&#039;; rr(lx, 12, 96, 56, 18); ctx.fill();\n      text(&#039;CAN&#039;, lx + 48, 30, &#039;600 9.5px Inter, sans-serif&#039;, g.lives === 1 &amp;&amp; !g.boss.active ? C.danger : C.muted);\n      for (let k = 0; k &lt; 3; k++){\n        const cx = lx + 22 + k * 26 + sh, cy = 48;\n        const last = g.lives === 1 &amp;&amp; k === 0 &amp;&amp; !g.boss.active;\n        const s2 = last ? 1 + Math.abs(Math.sin(g.t * 6)) * 0.18 : 1;\n        if (k &lt; g.lives) heart(cx, cy, 9 * s2, C.danger, null);\n        else heart(cx, cy, 9, null, &#039;#D5E0D9&#039;);\n      }\n    }\n    let y2 = 82;\n    \/\/ boss tug bar or combo\n    const b = g.boss;\n    if (b.active){\n      \/\/ tug of war for the #1 spot: rival on the left, you on the right, the crown shows who holds it\n      const bw = Math.min(380, W - 24), bx = (W - bw) \/ 2;\n      ctx.fillStyle = C.ink; rr(bx, y2, bw, 36, 18); ctx.fill();\n      text(&#039;RAK\u0130P&#039;, bx + 14, y2 + 22, &#039;800 10px Poppins, sans-serif&#039;, &#039;#9DB4E6&#039;, &#039;left&#039;);\n      text(&#039;SEN&#039;, bx + bw - 14, y2 + 22, &#039;800 10px Poppins, sans-serif&#039;, C.lime, &#039;right&#039;);\n      const x0 = bx + 58, x1 = bx + bw - 46, cx = (x0 + x1) \/ 2, yy = y2 + 18, half = (x1 - x0) \/ 2;\n      ctx.fillStyle = &#039;rgba(255,255,255,0.12)&#039;; rr(x0, yy - 4, x1 - x0, 8, 4); ctx.fill();\n      const mx = cx + clamp(b.L \/ 100, -1, 1) * half, lead = b.lead;\n      ctx.fillStyle = b.L &gt;= 0 ? C.lime : &#039;#6F8FD6&#039;;\n      if (b.L &gt;= 0) rr(cx, yy - 4, mx - cx, 8, 4); else rr(mx, yy - 4, cx - mx, 8, 4);\n      ctx.fill();\n      ctx.fillStyle = &#039;rgba(255,255,255,0.6)&#039;; ctx.fillRect(cx - 1, yy - 8, 2, 16);\n      ctx.fillStyle = C.white; ctx.beginPath(); ctx.arc(mx, yy, 7, 0, 6.28); ctx.fill();\n      drawCrown(mx, yy - 9, 0.55);\n      void lead;\n      y2 += 42;\n    } else if (g.rp === &#039;rule&#039;){\n      const R = RULES[curRule()]; ctx.font = &#039;700 12px Inter, sans-serif&#039;;\n      const tw = Math.min(W - 24, ctx.measureText(R.line).width + 30), bx = (W - tw) \/ 2;\n      ctx.fillStyle = C.ink; rr(bx, y2, tw, 26, 13); ctx.fill();\n      ctx.save(); ctx.translate(W \/ 2, y2 + 17); const f = Math.min(1, (tw - 20) \/ ctx.measureText(R.line).width); ctx.scale(f, f); text(R.line, 0, 0, &#039;700 12px Inter, sans-serif&#039;, C.lime); ctx.restore();\n      y2 += 38;\n    }\n    \/\/ single message slot\n    const m = g.msg;\n    if (m){\n      const a = Math.min(1, (m.max - m.life) * 6, m.life * 4);\n      const pal = m.tone === &#039;lime&#039; ? [C.lime, C.ink] : m.tone === &#039;red&#039; ? [C.danger, C.white] : [C.ink, C.white];\n      ctx.font = &#039;800 14px Poppins, sans-serif&#039;;\n      const raw = ctx.measureText(m.text).width, tw = Math.min(W - 24, raw + 28), mf = Math.min(1, (tw - 24) \/ raw);\n      const yTop = H &gt; 520 ? Math.max(y2 + 4, skyY() - 72) : y2 + 4;\n      const y = yTop - (1 - Math.min(1, (m.max - m.life) * 6)) * 8;\n      ctx.globalAlpha = a;\n      ctx.fillStyle = pal[0]; rr(W \/ 2 - tw \/ 2, y, tw, 28, 14); ctx.fill();\n      ctx.save(); ctx.translate(W \/ 2, y + 19); ctx.scale(mf, mf); text(m.text, 0, 0, &#039;800 14px Poppins, sans-serif&#039;, pal[1]); ctx.restore();\n      ctx.globalAlpha = 1;\n    }\n  }\n\n  function draw(){\n    ctx.save();\n    if (g.shake &gt; 0 &amp;&amp; !reduceMotion) ctx.translate((Math.random() - 0.5) * 9 * g.shake, (Math.random() - 0.5) * 9 * g.shake);\n    if (state === &#039;play&#039; &amp;&amp; g.t &lt; 1 &amp;&amp; !reduceMotion){ const z = 1 + 0.07 * (1 - ease(g.t)); ctx.translate(W \/ 2, GROUND); ctx.scale(z, z); ctx.translate(-W \/ 2, -GROUND); }\n    drawBackground();\n    drawGround();\n    drawSpots();\n    drawRival();\n    for (const o of g.objs){\n      if (o.dead) continue;\n      if (o.hold &gt; 0){\n        const my = o.y + o.h \/ 2, pulse = 1 + 0.15 * Math.sin(g.t * 18), mx = W - 22;\n        ctx.fillStyle = &#039;rgba(255,106,61,0.18)&#039;; ctx.fillRect(mx - 40, my - 2, 40, 4);\n        ctx.fillStyle = C.danger; ctx.beginPath(); ctx.arc(mx, my, 12 * pulse, 0, Math.PI * 2); ctx.fill();\n        text(&#039;!&#039;, mx, my + 5.5, &#039;800 16px Poppins, sans-serif&#039;, C.white, &#039;center&#039;);\n        continue;\n      }\n      const y = o.y + (o.by || 0);\n      if (o.kind === &#039;hole&#039;) continue;\n      else if (o.kind === &#039;shield&#039;) drawShield(o, o.x, y);\n      else if (o.kind === &#039;quake&#039;) drawQuake(o, o.x, o.y);\n      else if (o.kind === &#039;img&#039;){ drawImg(o); if (cycleN() === 0 &amp;&amp; curRule() === &#039;hiz&#039; &amp;&amp; !o.hit &amp;&amp; o.x &gt; g.p.x){ const ax = o.x + o.w \/ 2, ay = o.y - 30 + Math.sin(g.t * 8) * 4; ctx.fillStyle = C.ink; ctx.beginPath(); ctx.moveTo(ax - 9, ay); ctx.lineTo(ax + 9, ay); ctx.lineTo(ax, ay + 11); ctx.closePath(); ctx.fill(); ctx.fillRect(ax - 3.5, ay - 10, 7, 11); if (o.x &lt; W * 0.8) text(&#039;\u00dcST\u00dcNE ZIPLA&#039;, ax, ay - 16, &#039;800 10px Poppins, sans-serif&#039;, C.ink); } }\n      else if (o.kind === &#039;copy&#039;) drawCopy(o, o.x, o.y);\n      else if (o.kind === &#039;spamlink&#039;) drawSpam(o, o.x, o.y);\n      else if (KIND_PIL[o.kind]) drawGood(o, o.x, y);\n      else if (o.kind === &#039;heart&#039;){\n        const p2 = 0.25 + 0.15 * Math.sin(g.t * 6);\n        ctx.fillStyle = `rgba(228,87,46,${p2})`; ctx.beginPath(); ctx.arc(o.x + 14, y + 13, 24, 0, Math.PI * 2); ctx.fill();\n        heart(o.x + 14, y + 14, 13 * (1 + Math.abs(Math.sin(g.t * 5)) * 0.08), C.danger, C.white);\n      }\n      else if (o.kind === &#039;dup&#039;) drawDup(o, o.x, o.trap ? y : o.y);\n      else if (o.kind === &#039;spam&#039;){ if (o.hi){ ctx.fillStyle = &#039;rgba(4,40,28,0.22)&#039;; ctx.beginPath(); ctx.ellipse(o.x + o.w \/ 2, GROUND + 1, 20, 4, 0, 0, Math.PI * 2); ctx.fill(); } drawSpam(o, o.x, o.trap ? y : o.y); }\n      else if (o.kind === &#039;err&#039;) drawErr(o, o.x, o.trap ? y : o.y);\n      else if (o.kind === &#039;snippet&#039;) drawSnippet(o, o.x, y);\n      if (o.label &amp;&amp; o.x &gt; PX - 30){\n        ctx.font = &#039;700 12px Poppins, sans-serif&#039;; const tw2 = ctx.measureText(o.label).width + 18, lx = clamp(o.x + o.w \/ 2, tw2 \/ 2 + 6, W - tw2 \/ 2 - 6), ly = o.y + (o.by || 0) - 22;\n        ctx.fillStyle = &#039;rgba(4,40,28,0.9)&#039;; rr(lx - tw2 \/ 2, ly - 15, tw2, 22, 11); ctx.fill();\n        ctx.beginPath(); ctx.moveTo(o.x + o.w \/ 2 - 5, ly + 7); ctx.lineTo(o.x + o.w \/ 2 + 5, ly + 7); ctx.lineTo(o.x + o.w \/ 2, ly + 12); ctx.fill();\n        text(o.label, lx, ly + 0.5, &#039;700 12px Poppins, sans-serif&#039;, C.lime);\n      }\n      if (o.rain &amp;&amp; o.fall){\n        const k2 = clamp(1 - (GROUND - (o.y + o.h)) \/ 420, 0, 1), cx2 = o.x + o.w \/ 2;\n        ctx.strokeStyle = &#039;rgba(255,106,61,0.35)&#039;; ctx.lineWidth = 1.5; ctx.setLineDash([4, 6]);\n        ctx.beginPath(); ctx.moveTo(cx2, o.y + o.h + 4); ctx.lineTo(cx2, GROUND); ctx.stroke(); ctx.setLineDash([]);\n        ctx.fillStyle = `rgba(255,106,61,${0.6 + 0.35 * k2})`; ctx.beginPath(); ctx.ellipse(cx2, GROUND + 2, 12 + 8 * k2, 4 + 2 * k2, 0, 0, Math.PI * 2); ctx.fill();\n      }\n    }\n    drawPlayer();\n    if (g.shields &gt; 0 &amp;&amp; curRule() === &#039;core&#039; &amp;&amp; g.rp === &#039;rule&#039;){\n      const p = g.p, cx = p.x + p.w \/ 2, cy = p.y + p.h \/ 2 - 2, r0 = 30 + Math.sin(g.t * 5) * 1.5;\n      ctx.fillStyle = &#039;rgba(106,90,224,0.16)&#039;; ctx.beginPath(); ctx.arc(cx, cy, r0, 0, 6.28); ctx.fill();\n      ctx.strokeStyle = &#039;rgba(106,90,224,0.85)&#039;; ctx.lineWidth = 3; ctx.beginPath(); ctx.arc(cx, cy, r0, 0, 6.28); ctx.stroke();\n      if (g.shields &gt; 1){ ctx.strokeStyle = &#039;rgba(201,242,78,0.9)&#039;; ctx.lineWidth = 2; ctx.beginPath(); ctx.arc(cx, cy, r0 + 5, 0, 6.28); ctx.stroke(); }\n      drawShield({ w:16, h:18, id:0 }, cx + r0 - 12, cy - r0 - 6); text(&#039;x&#039; + g.shields, cx + r0 + 12, cy - r0 + 8, &#039;800 11px Poppins, sans-serif&#039;, &#039;#4B3BC4&#039;, &#039;left&#039;);\n    }\n    if (g.lifePop &gt; 0){ const p = g.p, k = 1 - g.lifePop; ctx.globalAlpha = Math.min(1, g.lifePop * 2); text(&#039;\u22121 can&#039;, p.x + p.w \/ 2, p.y - 16 - k * 22, &#039;800 14px Poppins, sans-serif&#039;, C.danger); ctx.globalAlpha = 1; }\n    drawFX();\n    ctx.restore();\n    if (g.upd.phase === &#039;active&#039;){ ctx.fillStyle = PIL[g.upd.focus].col; ctx.globalAlpha = 0.07; ctx.fillRect(0, 0, W, GROUND); ctx.globalAlpha = 1; }\n    if (g.glitch &gt; 0 &amp;&amp; !reduceMotion){\n      for (let k = 0; k &lt; 7; k++){ const yy = Math.random() * H, hh = 3 + Math.random() * 10; ctx.fillStyle = k % 2 ? `rgba(201,242,78,${g.glitch})` : `rgba(106,90,224,${g.glitch * 0.8})`; ctx.fillRect(Math.random() * -40, yy, W + 80, hh); }\n    }\n    if (g.lb &gt; 0.01){ const bh = 16 * g.lb; ctx.fillStyle = &#039;#020f0a&#039;; ctx.fillRect(0, 0, W, bh); ctx.fillRect(0, H - bh, W, bh); }\n    if (state === &#039;play&#039; &amp;&amp; g.t &lt; 0.9){ ctx.fillStyle = `rgba(4,40,28,${0.6 * (1 - g.t \/ 0.9)})`; ctx.fillRect(0, 0, W, H); }\n    if (state === &#039;play&#039;){ drawHUD(); drawFlyers(); drawBanner(); drawWords(); drawBigWord(); drawRuleCard(); drawAtak(); }\n    if (g.flash &gt; 0){\n      const vg = ctx.createRadialGradient(W \/ 2, H \/ 2, Math.min(W, H) * 0.3, W \/ 2, H \/ 2, Math.max(W, H) * 0.7);\n      vg.addColorStop(0, &#039;rgba(228,87,46,0)&#039;); vg.addColorStop(1, `rgba(228,87,46,${g.flash * 1.1})`);\n      ctx.fillStyle = vg; ctx.fillRect(0, 0, W, H);\n    }\n  }\n\n  \/\/ ================= end screen =================\n  function finalist(){ return g.reachT &gt; 0; }\n  function praise(){\n    const r = g.best, climbed = 100 - r;\n    if (g.outcome === &#039;win&#039; &amp;&amp; g.snippet) return &#039;\u00d6ne \u00c7\u0131kan Sonu\u00e7\\&#039;u yakalad\u0131n. Art\u0131k 1.\\u00a0s\u0131ran\u0131n da \u00fcst\u00fcndesin!&#039;;\n    if (g.outcome === &#039;win&#039;) return &#039;Rakibini ge\u00e7tin, zirve art\u0131k senin!&#039;;\n    if (g.outcome === &#039;lose&#039;) return &#039;Zirveye bir ad\u0131m kald\u0131! Rakibin tac\u0131 korudu, bir tur daha?&#039;;\n    if (finalist()) return &#039;Final d\u00fcellosuna kadar geldin. Bir tur daha?&#039;;\n    if (r &lt;= 3) return &#039;\u0130lk \u00fc\u00e7e girdin. T\u0131klamalar\u0131n \u00e7o\u011fu tam burada.&#039;;\n    if (r &lt;= 10) return &#039;\u0130lk sayfaya \u00e7\u0131kt\u0131n. Art\u0131k arayanlar seni g\u00f6r\u00fcyor.&#039;;\n    if (r &lt;= 30) return &#039;\u0130lk sayfa \u00e7ok yak\u0131n. Bir tur daha?&#039;;\n    const st = g.stats, idle = (st.orijinal.good + st.hiz.good + st.core.good + st.spam.good) &lt; 8;\n    return (climbed &lt; 10 || idle) ? &#039;Is\u0131nma turuydu, bir daha dene!&#039; : &#039;G\u00fczel ba\u015flang\u0131\u00e7! Bir tur daha?&#039;;\n  }\n  const TOPIC = { orijinal:&#039;kopya i\u00e7erik&#039;, hiz:&#039;a\u011f\u0131r g\u00f6rseller&#039;, core:&#039;core update&#039;, kirik:&#039;k\u0131r\u0131k linkler&#039;, spam:&#039;spam&#039; };\n  function notes(){\n    const n = [], s0 = g.stats;\n    \/\/ one personal, true SEO line from the rule you struggled with most\n    const errs = { orijinal:s0.orijinal.bad, hiz:s0.hiz.bad * 2, core:s0.core.bad, kirik:s0.kirik.bad * 2, spam:s0.spam.bad * 2 };\n    const worst = Object.keys(errs).sort((x, y) =&gt; errs[y] - errs[x])[0];\n    g.weakest = errs[worst] &gt;= 3 ? worst : null;\n    const tot = s0.orijinal.good + s0.hiz.good + s0.core.good + s0.spam.good + s0.kirik.good;\n    g.idle = tot &lt; 8;\n    const L2 = { orijinal:`Kopya i\u00e7eri\u011fe ${s0.orijinal.bad} kez dokundun. Ger\u00e7ek sitelerde de kopya i\u00e7erik s\u0131ralamay\u0131 d\u00fc\u015f\u00fcr\u00fcr.`, hiz:`A\u011f\u0131r g\u00f6rseller seni ${s0.hiz.bad} kez durdurdu. Ger\u00e7ek sitelerde de yava\u015f sayfa s\u0131ra kaybettirir.`, core:`Core update sars\u0131nt\u0131s\u0131na ${s0.core.bad} kez kalkans\u0131z yakaland\u0131n. Ger\u00e7ekte de g\u00fcncellemeler kaliteli siteleri korur.`, kirik:`404 \u00e7ukuruna ${s0.kirik.bad} kez d\u00fc\u015ft\u00fcn. Ger\u00e7ek sitelerde de k\u0131r\u0131k linkler ziyaret\u00e7iyi ve s\u0131ray\u0131 ka\u00e7\u0131r\u0131r.`, spam:`Spama ${s0.spam.bad} kez tak\u0131ld\u0131n. Ger\u00e7ek sitelerde de spam s\u0131ralamay\u0131 bir gecede d\u00fc\u015f\u00fcrebilir.` };\n    if (g.idle) n.push(&#039;Siten yerinde sayd\u0131. Ger\u00e7ek SEO\\&#039;da da emek vermeden s\u0131ra gelmez.&#039;);\n    else if (g.weakest) n.push(L2[g.weakest]);\n    else n.push(&#039;Her kurala h\u0131zl\u0131 uydun. Ger\u00e7ek SEO\\&#039;da da kazanan, de\u011fi\u015fime en h\u0131zl\u0131 uyan olur.&#039;);\n    if (g.outcome === &#039;win&#039;){\n      const T = Math.round(g.finishT || g.t), bt = +store.get(&#039;ak_bestT&#039;) || 0, rec = !bt || T &lt; bt, fmt = x =&gt; Math.floor(x \/ 60) + &#039;:&#039; + String(x % 60).padStart(2, &#039;0&#039;);\n      if (rec) store.set(&#039;ak_bestT&#039;, String(T));\n      n.push(`Zirve s\u00fcren: ${fmt(T)}` + (bt &amp;&amp; rec ? &#039; \u00b7 yeni rekor!&#039; : bt ? ` \u00b7 rekorun ${fmt(bt)}` : &#039;. Daha h\u0131zl\u0131s\u0131n\u0131 dene!&#039;));\n    } else if (g.outcome === &#039;lose&#039;) n.push(&#039;Rakip finalde tac\u0131 korudu. Kaliteli i\u00e7erik ve link toplayarak onu ge\u00e7ebilirsin.&#039;);\n    else n.push(`Algoritma ${Math.max(1, g.ri + 1)} kez kural de\u011fi\u015ftirdi. Her yeni turda oyun h\u0131zlan\u0131r.`);\n    return n.slice(0, 2);\n  }\n  function showOver(){\n    state = &#039;over&#039;; pauseBtn.hidden = true; document.documentElement.classList.remove(&#039;playing&#039;); document.documentElement.classList.add(&#039;over&#039;);\n    const r = g.outcome === &#039;win&#039; ? 1 : g.outcome === &#039;lose&#039; ? 2 : g.best, climbed = 100 - r;\n    const hadBest = !!best, record = !best || r &lt; best;\n    if (record){ best = r; store.set(&#039;ak5_best&#039;, String(r)); }\n    $(&#039;oLabel&#039;).textContent = g.outcome === &#039;win&#039; || g.outcome === &#039;lose&#039; ? &#039;Final sonucun&#039; : &#039;En iyi s\u0131ran&#039;;\n    music.stop();\n    const el = $(&#039;oRank&#039;); el.textContent = &#039;#100&#039;;\n    const t0 = performance.now(), dur = 1100;\n    const tickR = () =&gt; { const k = Math.min(1, (performance.now() - t0) \/ dur), v = Math.round(100 - (100 - r) * ease(k)); if (el.textContent !== &#039;#&#039; + v){ el.textContent = &#039;#&#039; + v; if (v % 4 === 0) snd.note(900 + (100 - v) * 6, 0.05, 0.025); } if (k &lt; 1) requestAnimationFrame(tickR); else { el.classList.remove(&#039;pop&#039;); void el.offsetWidth; el.classList.add(&#039;pop&#039;); snd.fanfare(); } };\n    setTimeout(tickR, 250);\n    const u = g.upd;\n    \/\/ badge collection across runs: lit = owned, pulse = earned this run, grey = still to get (the reason to play again)\n    const BADGES = [\n      [&#039;10&#039;, &#039;\u0130lk Sayfa&#039;, &#039;ilk 10\\&#039;a gir&#039;, g.best &lt;= 10 || g.outcome === &#039;win&#039; || g.outcome === &#039;lose&#039;],\n      [&#039;\u2713&#039;, &#039;Temiz Site&#039;, &#039;bir spam sald\u0131r\u0131s\u0131n\u0131 hi\u00e7 tak\u0131lmadan ge\u00e7&#039;, g.cleanSpam &gt; 0],\n      [&#039;\u2191&#039;, &#039;G\u00fcncelleme Ustas\u0131&#039;, &#039;iki core update\\&#039;ten de y\u00fckselerek \u00e7\u0131k&#039;, g.coreUps &gt;= 2 &amp;&amp; !g.coreDowns],\n      [&#039;1&#039;, &#039;Zirve Sahibi&#039;, &#039;finalde rakibini ge\u00e7 ve zirveyi al&#039;, g.outcome === &#039;win&#039;],\n      [&#039;\u2605&#039;, &#039;\u00d6ne \u00c7\u0131kan Sonu\u00e7&#039;, &#039;finalde alt\u0131n kart\u0131 yakala&#039;, !!g.snippet]\n    ];\n    let owned = {}; try { owned = JSON.parse(store.get(&#039;ak_badges&#039;) || &#039;{}&#039;) || {}; } catch(e){}\n    const fresh = BADGES.filter(x =&gt; x[3] &amp;&amp; !owned[x[1]]);\n    BADGES.forEach(x =&gt; { if (x[3]) owned[x[1]] = 1; });\n    store.set(&#039;ak_badges&#039;, JSON.stringify(owned));\n    const have = BADGES.filter(x =&gt; owned[x[1]]).length, nextB = BADGES.find(x =&gt; !owned[x[1]]);\n    $(&#039;oBadges&#039;).innerHTML = &#039;&lt;div class=&quot;bset&quot;&gt;&#039; + BADGES.map(x =&gt; `&lt;span class=&quot;bi${owned[x[1]] ? &#039; on&#039; : &#039;&#039;}${fresh.includes(x) ? &#039; new&#039; : &#039;&#039;}&quot; title=&quot;${x[1]}&quot;&gt;${owned[x[1]] ? x[0] : &#039;?&#039;}&lt;\/span&gt;`).join(&#039;&#039;) + &#039;&lt;\/div&gt;&#039;\n      + `&lt;p class=&quot;bcap&quot;&gt;&lt;b&gt;${have}\/5 rozet&lt;\/b&gt;` + (fresh.length ? ` \u00b7 Yeni: ${fresh.map(x =&gt; x[1]).join(&#039;, &#039;)}` : nextB ? ` \u00b7 S\u0131radaki: ${nextB[2]}` : &#039; \u00b7 Hepsini toplad\u0131n!&#039;) + &#039;&lt;\/p&gt;&#039;;\n    $(&#039;oBadges&#039;).hidden = false;\n    $(&#039;oTo&#039;).textContent = &#039;#&#039; + r;\n    $(&#039;oUp&#039;).textContent = `${climbed} s\u0131ra y\u00fckseldin`;\n    document.querySelector(&#039;#over .climb&#039;).hidden = climbed &lt;= 0;\n    for (const id of [&#039;ctaLink&#039;, &#039;ctaAlt&#039;]){ const link = $(id); if (!link) continue; const u0 = new URL(link.href); u0.searchParams.set(&#039;sira&#039;, r); link.href = u0.toString(); }\n    g.shownRank = r;\n    track(&#039;game_end&#039;, { outcome:g.outcome, best_rank:r, seconds:Math.round(g.finishT || g.t), run:runs });\n    $(&#039;oPraise&#039;).textContent = (g.outcome === &#039;dead&#039; ? &#039;Canlar\u0131n bitti. &#039; : &#039;&#039;) + praise() + (hadBest &amp;&amp; record &amp;&amp; r &gt; 1 ? &#039; Yeni rekorun!&#039; : &#039;&#039;);\n    $(&#039;oBars&#039;).innerHTML = &#039;&#039;;\n    $(&#039;oNotes&#039;).innerHTML = notes().map(s =&gt; `&lt;li&gt;${s}&lt;\/li&gt;`).join(&#039;&#039;);\n    $(&#039;ctaSub&#039;).textContent = g.weakest ? `Oyunda seni en \u00e7ok ${TOPIC[g.weakest]} zorlad\u0131. Ger\u00e7ek sitenin s\u0131ras\u0131n\u0131 S\u0131ra Bulucu ile \u00fccretsiz g\u00f6r.` : &#039;Sitenin Google\\&#039;da bug\u00fcn ka\u00e7\u0131nc\u0131 oldu\u011funu S\u0131ra Bulucu ile \u00fccretsiz g\u00f6r.&#039;;\n    $(&#039;copied&#039;).hidden = true; $(&#039;shareBox&#039;).hidden = true;\n    overEl.hidden = false;\n    { const det = { rank:r, outcome:g.outcome || &#039;dead&#039;, weakest:g.weakest || &#039;&#039; };\n      try { HOST.sessionStorage.setItem(&#039;sl_oyun_sonuc&#039;, JSON.stringify(det)); } catch(e){}\n      if (EMBED) try { HOST.dispatchEvent(new HOST.CustomEvent(&#039;seoliva:oyun-bitti&#039;, { detail:det })); } catch(e){} }\n    $(&#039;againBtn&#039;).disabled = true; setTimeout(() =&gt; { $(&#039;againBtn&#039;).disabled = false; }, 1000);\n  }\n\n  \/\/ ================= flow &amp; input =================\n  function start(){\n    snd.init();\n    newRun();\n    runs++; track(&#039;game_start&#039;, { run:runs });\n    state = &#039;play&#039;; paused = false; pauseEl.hidden = true; pauseBtn.hidden = false; placePause(); document.documentElement.classList.add(&#039;playing&#039;); document.documentElement.classList.remove(&#039;over&#039;);\n    if (EMBED){ try { const fe = window.frameElement; if (fe){ const r = fe.getBoundingClientRect(), vh = HOST.innerHeight; if (HOST.innerWidth &gt; 760 &amp;&amp; vh &gt; 560){ const d = r.top - 93; if (Math.abs(d) &gt; 6) HOST.scrollBy({ top:d, behavior:&#039;smooth&#039; }); }   \/\/ desktop: frame top just under the site header, the whole game in view\n          else if (HOST.innerWidth &gt; 760) fe.scrollIntoView({ behavior:&#039;smooth&#039;, block:&#039;center&#039; });\n          else if (r.bottom &gt; vh + 2 || r.top &lt; 0) fe.scrollIntoView({ behavior:&#039;smooth&#039;, block:r.height &lt;= vh ? &#039;end&#039; : &#039;start&#039; }); } } catch(e){} }\n    startEl.hidden = true; overEl.hidden = true;\n    g.tut = null;\n    music.mode = &#039;calm&#039;; music.start();\n    last = performance.now();\n  }\n  function jump(){\n    const p = g.p;\n    if (g.ending) return;\n    if (g.boss.atak){ if (g.boss.atak.pre &lt;= 0) resolveAtak(false); return; }\n    p.holding = true;\n    if (p.onGround){ p.vy = JUMP \/ JS; p.onGround = false; p.jumps = 1; snd.jump(); }\n    else if (p.jumps &lt; 2){ p.vy = JUMP2 \/ JS; p.jumps = 2; snd.jump(); for (let k = 0; k &lt; 5; k++) g.parts.push({ x:p.x + 19, y:p.y + p.h, vx:rand(-60, 60), vy:rand(20, 90), r:2, c:C.lime, life:0.35, gr:0 }); }\n  }\n  const release = () =&gt; { if (g) g.p.holding = false; };\n\n  \/\/ inside the page: while playing, a swipe on the game must never scroll the page (iOS ignores touch-action here)\n  document.addEventListener(&#039;touchmove&#039;, e =&gt; { if (EMBED &amp;&amp; state === &#039;play&#039; &amp;&amp; !paused) e.preventDefault(); }, { passive:false });\n  \/\/ iPhone: two quick taps (a double jump) must never zoom the page. Swallow the second tap&#039;s default, never the first one&#039;s.\n  { let lastEnd = 0;\n    document.addEventListener(&#039;touchend&#039;, e =&gt; { const now = performance.now(), quick = now - lastEnd &lt; 380; lastEnd = now;\n      if (quick &amp;&amp; e.cancelable &amp;&amp; !(e.target.closest &amp;&amp; e.target.closest(&#039;textarea&#039;))) e.preventDefault(); }, { passive:false });\n    document.addEventListener(&#039;dblclick&#039;, e =&gt; e.preventDefault(), { passive:false });\n    document.addEventListener(&#039;gesturestart&#039;, e =&gt; { if (state === &#039;play&#039;) e.preventDefault(); }, { passive:false }); }\n  \/\/ touch on the start screen: a swipe past the game is a scroll, only a real tap starts it\n  let tap0 = null;\n  const tapDown = e =&gt; { tap0 = { x:e.clientX, y:e.clientY, t:performance.now() }; };\n  const isTap = e =&gt; { const t = tap0; tap0 = null; return !!t &amp;&amp; Math.hypot(e.clientX - t.x, e.clientY - t.y) &lt; 10 &amp;&amp; performance.now() - t.t &lt; 400; };\n  \/\/ phones: a jump pad under the game so the thumb never covers what is coming from the right\n  { const pad = $(&#039;pad&#039;);\n    pad.addEventListener(&#039;pointerdown&#039;, e =&gt; { if (state !== &#039;play&#039; || paused){ tapDown(e); return; } e.preventDefault(); pad.classList.add(&#039;on&#039;); try { pad.setPointerCapture(e.pointerId); } catch(_){} jump(); });\n    pad.addEventListener(&#039;pointerup&#039;, e =&gt; { if (isTap(e)){ if (state === &#039;start&#039;) start(); else if (paused) resume(); } });\n    const up = () =&gt; { pad.classList.remove(&#039;on&#039;); release(); };\n    pad.addEventListener(&#039;pointerup&#039;, up); pad.addEventListener(&#039;pointercancel&#039;, up); pad.addEventListener(&#039;lostpointercapture&#039;, up);\n    pad.addEventListener(&#039;contextmenu&#039;, e =&gt; e.preventDefault()); }\n  stage.addEventListener(&#039;pointerdown&#039;, e =&gt; {\n    if (e.target.closest(&#039;button, a, textarea, .card&#039;)) return;\n    if (state === &#039;play&#039; &amp;&amp; !paused){ e.preventDefault(); jump(); }\n    else if (state === &#039;start&#039;){ if (e.pointerType === &#039;mouse&#039;) start(); else tapDown(e); }\n  });\n  stage.addEventListener(&#039;pointerup&#039;, e =&gt; { if (state === &#039;start&#039; &amp;&amp; e.pointerType !== &#039;mouse&#039; &amp;&amp; !e.target.closest(&#039;button, a, textarea, .card&#039;) &amp;&amp; isTap(e)) start(); });\n  window.addEventListener(&#039;pointerup&#039;, release);\n  window.addEventListener(&#039;pointercancel&#039;, release);\n  let TESTKEYS = \/[?&amp;]oyuntest=1\/.test(location.search); try { if (EMBED) TESTKEYS = \/[?&amp;]oyuntest=1\/.test(HOST.location.search); } catch(e){}\n  window.addEventListener(&#039;keydown&#039;, e =&gt; {\n    if ((e.code === &#039;Escape&#039; || e.code === &#039;KeyP&#039;) &amp;&amp; state === &#039;play&#039;){ e.preventDefault(); paused ? resume() : pause(); return; }\n    if (paused){ if (e.code === &#039;Space&#039; || e.code === &#039;Enter&#039;){ e.preventDefault(); resume(); } return; }\n    if (e.code === &#039;Space&#039; || e.code === &#039;ArrowUp&#039; || e.code === &#039;KeyW&#039;){\n      const onCtl = e.target &amp;&amp; e.target.closest &amp;&amp; e.target.closest(&#039;button, a, textarea&#039;);\n      if (state === &#039;play&#039;){ e.preventDefault(); if (!e.repeat) jump(); }\n      else if (!onCtl &amp;&amp; state === &#039;start&#039;){ e.preventDefault(); start(); }\n      else if (state === &#039;over&#039;) e.preventDefault();\n    }\n    if (TESTKEYS &amp;&amp; (state === &#039;start&#039; || state === &#039;over&#039;) &amp;&amp; [&#039;Digit1&#039;, &#039;Digit2&#039;, &#039;Digit3&#039;].includes(e.code)){\n      LVL = +e.code.slice(-1) - 1; const t = $(&#039;lvlTag&#039;); if (t){ t.textContent = &#039;Test zorlu\u011fu: &#039; + [&#039;Rahat&#039;, &#039;Normal&#039;, &#039;Sert&#039;][LVL]; t.hidden = false; }\n    }\n  });\n  window.addEventListener(&#039;keyup&#039;, e =&gt; { if (e.code === &#039;Space&#039; || e.code === &#039;ArrowUp&#039; || e.code === &#039;KeyW&#039;) release(); });\n\n  $(&#039;startBtn&#039;).addEventListener(&#039;click&#039;, start);\n  if (EMBED) for (const id of [&#039;ctaLink&#039;, &#039;ctaAlt&#039;]){ const l = $(id); if (l){ l.target = &#039;_top&#039;; l.removeAttribute(&#039;rel&#039;); } }\n  { const c = $(&#039;ctlTip&#039;); const padOn = getComputedStyle($(&#039;pad&#039;)).display !== &#039;none&#039;; if (c) c.textContent = padOn ? &#039;Alttaki koyu alana dokun: z\u0131pla&#039; : TOUCH ? &#039;Dokun: z\u0131pla \u00b7 havada tekrar: \u00e7ift z\u0131pla&#039; : &#039;Bo\u015fluk ya da t\u0131k: z\u0131pla&#039;; }\n  $(&#039;againBtn&#039;).addEventListener(&#039;click&#039;, start);\n  $(&#039;musBtn&#039;).addEventListener(&#039;click&#039;, () =&gt; { music.on = !music.on; store.set(&#039;ak_mus&#039;, music.on ? &#039;1&#039; : &#039;0&#039;); if (music.on){ snd.init(); if (state === &#039;play&#039;) music.start(); } else music.stop(); paintSnd(); });\n  $(&#039;sndBtn&#039;).addEventListener(&#039;click&#039;, () =&gt; { snd.on = !snd.on; store.set(&#039;ak_snd&#039;, snd.on ? &#039;1&#039; : &#039;0&#039;); if (snd.on){ snd.init(); if (state === &#039;play&#039;) music.start(); } else music.stop(); paintSnd(); });\n  document.addEventListener(&#039;visibilitychange&#039;, () =&gt; { if (document.hidden){ music.stop(); pause(); } else if (state === &#039;play&#039; &amp;&amp; !paused) music.start(); });\n  $(&#039;ctaLink&#039;).addEventListener(&#039;click&#039;, () =&gt; track(&#039;cta_click&#039;, { best_rank:g.shownRank || g.best, outcome:g.outcome || &#039;&#039;, target:&#039;sira_bulucu&#039; }));\n  $(&#039;ctaAlt&#039;).addEventListener(&#039;click&#039;, () =&gt; track(&#039;cta_click&#039;, { best_rank:g.shownRank || g.best, outcome:g.outcome || &#039;&#039;, target:&#039;iletisim&#039; }));\n  $(&#039;copyBtn&#039;).addEventListener(&#039;click&#039;, () =&gt; {\n    const r = g.outcome === &#039;win&#039; ? 1 : g.best;\n    const msg = g.outcome === &#039;win&#039; ? &#039;Google\\&#039;da Birinci Ol oyununda sitemi 1. s\u0131raya ta\u015f\u0131d\u0131m ve rakibime tac\u0131 b\u0131rakmad\u0131m! Sen ka\u00e7\u0131nc\u0131 olursun?&#039; : `Google&#039;da Birinci Ol oyununda sitemi 100. s\u0131radan ${r}. s\u0131raya ta\u015f\u0131d\u0131m. Sen ka\u00e7\u0131nc\u0131 olursun?`;\n    track(&#039;share_click&#039;, { best_rank:r });\n    const done = () =&gt; { $(&#039;copied&#039;).hidden = false; track(&#039;share&#039;, { best_rank:r, method:&#039;copy&#039; }); };\n    const fallback = () =&gt; { const b = $(&#039;shareBox&#039;); b.value = msg + &#039; &#039; + url; b.hidden = false; b.focus(); b.select(); };\n    const url = &#039;https:\/\/www.seoliva.com\/seo-oyunlari\/ilk-sira&#039;;   \/\/ clean address: shares never carry ad parameters\n    const copy = () =&gt; { try { navigator.clipboard.writeText(msg + &#039; &#039; + url).then(done, fallback); } catch(e){ fallback(); } };\n    if (navigator.share){ navigator.share({ title:&#039;Google\\&#039;da Birinci Ol&#039;, text:msg, url }).then(() =&gt; track(&#039;share&#039;, { best_rank:r, method:&#039;native&#039; })).catch(err =&gt; { if (!err || err.name !== &#039;AbortError&#039;) copy(); }); }\n    else copy();\n  });\n\n  \/\/ ================= pause =================\n  \/\/ auto-pauses when the app is left (Instagram notification, call, tab switch); resuming gives a short slow-motion grace\n  const pauseEl = $(&#039;pause&#039;), pauseBtn = $(&#039;pauseBtn&#039;);\n  let paused = false;\n  function pause(){ if (state !== &#039;play&#039; || paused || g.ending) return; paused = true; pauseEl.hidden = false; pauseBtn.hidden = true; music.stop(); setTimeout(() =&gt; $(&#039;resumeBtn&#039;).focus(), 30); }\n  function resume(){ if (!paused) return; paused = false; pauseEl.hidden = true; pauseBtn.hidden = false; g.slowmo = Math.max(g.slowmo, 0.7); g.p.holding = false; last = performance.now(); if (snd.on) music.start(); }\n  function placePause(){\n    const top = document.querySelector(&#039;.top&#039;); if (!top) return;\n    if (!document.documentElement.classList.contains(&#039;desk&#039;)){ top.style.right = top.style.bottom = &#039;&#039;; BTN_X = W + 14; return; }\n    const a = document.querySelector(&#039;.app&#039;).getBoundingClientRect(), c = cv.getBoundingClientRect(), band = (H - GROUND) * scale;\n    top.style.right = Math.round(a.right - c.right + 14) + &#039;px&#039;;\n    top.style.bottom = Math.round(a.bottom - c.bottom + Math.max(6, (band - top.offsetHeight) \/ 2)) + &#039;px&#039;;\n    BTN_X = (top.getBoundingClientRect().left - c.left) \/ scale;   \/\/ where the buttons start, in game units\n  }\n  pauseBtn.addEventListener(&#039;click&#039;, e =&gt; { e.stopPropagation(); pause(); });\n  $(&#039;resumeBtn&#039;).addEventListener(&#039;click&#039;, resume);\n  window.addEventListener(&#039;blur&#039;, pause);\n\n  \/\/ ================= loop =================\n  let last = performance.now();\n  function frame(now){\n    let real = (now - last) \/ 1000;\n    if (real &lt; 0 || real &gt; 0.25) real = 0;\n    real = Math.min(0.1, real);   \/\/ a late frame is caught up below in small steps, so the world never visibly slows down\n    last = now;\n    if (state === &#039;play&#039; &amp;&amp; paused){ \/* frozen *\/ }\n    else if (state === &#039;play&#039;){\n      if (g.hitstop &gt; 0) g.hitstop -= real;\n      else {\n        \/\/ desktop: the whole game runs a little slower (world, jumps and rule timers alike), so it stays readable on a big screen\n        let dt = real * (W &gt;= 560 ? 0.72 : 1);\n        if (g.boss.atak){ tickAtak(real); dt *= 0.25; }\n        if (g.slowmo &gt; 0){ g.slowmo -= real; dt *= 0.35; }\n        if (g.ending){ dt *= 0.5; g.ending -= real; }\n        \/\/ fixed small steps: a slow frame (busy laptop, big retina canvas) no longer feels like a hiccup\n        const n = Math.max(1, Math.ceil(real \/ 0.0175)), sdt = dt \/ n;\n        for (let k = 0; k &lt; n &amp;&amp; state === &#039;play&#039;; k++) update(sdt);\n        if (g.ending &amp;&amp; g.ending &lt;= 0) showOver();\n      }\n    } else {\n      g.t += real; g.bgOff += 60 * real; scenery(60 * real);\n      g.p.blink -= real; if (g.p.blink &lt; -3) g.p.blink = 0.12;\n      for (const q of g.parts){ q.life -= real; q.x += q.vx * real; q.y += q.vy * real; q.vy += q.gr * real; if (q.sq) q.rot += real * 5; }\n      g.parts = g.parts.filter(q =&gt; q.life &gt; 0 &amp;&amp; q.y &lt; H + 20);\n    }\n    draw();\n    requestAnimationFrame(frame);\n  }\n\n  resize();\n  newRun();\n  window.addEventListener(&#039;resize&#039;, resize);\n  if (window.ResizeObserver) new ResizeObserver(resize).observe(stage);\n  (document.fonts &amp;&amp; document.fonts.ready ? document.fonts.ready : Promise.resolve()).then(() =&gt; draw());\n  requestAnimationFrame(frame);\n\n})();\n\n&lt;\/script&gt;\n\n&lt;\/body&gt;\n&lt;\/html&gt;\n\" allow=\"web-share\" loading=\"eager\"><\/iframe>\n        <\/div>\n    <\/div>\n<\/section>\n<script>\n\/* Space \/ Arrow up while the game is on screen: start or jump in the game instead of scrolling the page *\/\n(function(){\n    var fr = document.querySelector('#sl-ilk-sira-oyun iframe');\n    if (!fr) return;\n    function live(){ var r = fr.getBoundingClientRect(); return r.top < window.innerHeight * 0.6 && r.bottom > 160; }\n    function pass(type, e){\n        try {\n            var w = fr.contentWindow, d = w.document.documentElement;\n            if (d.classList.contains('over')) return false;\n            w.focus();\n            w.dispatchEvent(new w.KeyboardEvent(type, { code:e.code, key:e.key, bubbles:true }));\n            return true;\n        } catch(err){ return false; }\n    }\n    document.addEventListener('keydown', function(e){\n        if (e.code !== 'Space' && e.code !== 'ArrowUp') return;\n        var t = e.target;\n        if (t && (t.isContentEditable || \/^(INPUT|TEXTAREA|SELECT|BUTTON|A)$\/.test(t.tagName))) return;\n        if (!live()) return;\n        if (pass('keydown', e)) e.preventDefault();\n    });\n    document.addEventListener('keyup', function(e){\n        if ((e.code === 'Space' || e.code === 'ArrowUp') && live()) pass('keyup', e);\n    });\n})();\n<\/script>\n\n<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div data-particle_enable=\"false\" data-particle-mobile-disabled=\"false\" class=\"elementor-element elementor-element-d37a998 e-flex e-con-boxed e-con e-parent\" data-id=\"d37a998\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-00f6e4e elementor-widget elementor-widget-html\" data-id=\"00f6e4e\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<style>\n#sl-ilk-sira{\n    --black:#111111;\n    --green:#039358;\n    --green-dark:#08764c;\n    --ink:#04281c;\n    --lime:#c9f24e;\n    color:#171717;\n    font-family:inherit;\n    background:#fff;\n}\n#sl-ilk-sira *{box-sizing:border-box}\n#sl-ilk-sira a{color:inherit}\n#sl-ilk-sira .wrap{width:min(1180px,calc(100% - 44px));margin:0 auto}\n#sl-ilk-sira h2,#sl-ilk-sira h3{margin:0}\n#sl-ilk-sira .sec-head h2{\n    color:var(--black);\n    font-size:40px;\n    line-height:1.08;\n    letter-spacing:-.04em;\n    font-weight:790;\n    white-space:nowrap;\n}\n#sl-ilk-sira .sec-head p{\n    max-width:900px;\n    margin:12px 0 0;\n    color:#656565;\n    font-size:16.5px;\n    line-height:1.65;\n}\n\n\/* HOW TO PLAY *\/\n#sl-ilk-sira .how{padding:60px 0 30px}\n#sl-ilk-sira .keys{\n    display:flex;\n    flex-wrap:wrap;\n    gap:10px;\n    margin-top:22px;\n}\n#sl-ilk-sira .keys span{\n    display:inline-flex;\n    align-items:center;\n    gap:10px;\n    padding:8px 14px 8px 8px;\n    border-radius:12px;\n    background:#f3f8f5;\n    border:1px solid #dcebe2;\n    color:#2f3632;\n    font-size:14.5px;\n    font-weight:600;\n    white-space:nowrap;\n}\n#sl-ilk-sira .keys kbd{\n    display:inline-flex;\n    align-items:center;\n    justify-content:center;\n    height:30px;\n    padding:0 11px;\n    border-radius:8px;\n    background:#fff;\n    border:1px solid #cfe0d6;\n    box-shadow:0 2px 0 #cfe0d6;\n    color:#111;\n    font:inherit;\n    font-size:13px;\n    font-weight:800;\n}\n#sl-ilk-sira .rules{\n    display:grid;\n    grid-template-columns:repeat(3,minmax(0,1fr));\n    gap:16px;\n    margin-top:28px;\n}\n#sl-ilk-sira .rule{\n    border-radius:20px;\n    background:#fff;\n    border:1px solid #e1ebe5;\n    overflow:hidden;\n    transition:transform .18s ease,box-shadow .18s ease;\n}\n#sl-ilk-sira .rule:hover{transform:translateY(-3px);box-shadow:0 18px 36px -18px rgba(4,40,28,.35)}\n#sl-ilk-sira .scene{display:block;aspect-ratio:320\/170;background:#EAF3EE}\n#sl-ilk-sira .scene svg{display:block;width:100%;height:100%}\n#sl-ilk-sira .rule-text{padding:18px 20px 20px}\n#sl-ilk-sira .rule-text h3{\n    color:#111;\n    font-size:19px;\n    line-height:1.25;\n    letter-spacing:-.02em;\n    font-weight:780;\n    white-space:nowrap;\n}\n#sl-ilk-sira .rule-text p{\n    margin:6px 0 0;\n    color:#5f6662;\n    font-size:15px;\n    line-height:1.55;\n}\n#sl-ilk-sira .rule.is-final{background:var(--ink);border-color:var(--ink)}\n#sl-ilk-sira .rule.is-final .rule-text h3{color:var(--lime)}\n#sl-ilk-sira .rule.is-final .rule-text p{color:#bcd3c6}\n\n\/* OTHER GAMES *\/\n#sl-ilk-sira .others{padding:34px 0 20px}\n#sl-ilk-sira .game-list{margin-top:20px}\n#sl-ilk-sira .game-row{\n    display:grid;\n    grid-template-columns:150px minmax(0,1fr) auto;\n    gap:22px;\n    align-items:center;\n    padding:14px 22px 14px 14px;\n    border-radius:20px;\n    background:#fff;\n    border:1px solid #e1ebe5;\n    text-decoration:none;\n    transition:transform .16s ease,box-shadow .16s ease;\n}\n#sl-ilk-sira .game-row:hover{transform:translateY(-2px);box-shadow:0 18px 36px -18px rgba(4,40,28,.3)}\n#sl-ilk-sira .game-thumb{display:block;width:150px;height:100px;border-radius:14px;overflow:hidden;background:#EEF2EF}\n#sl-ilk-sira .game-thumb svg{display:block;width:100%;height:100%}\n#sl-ilk-sira .game-row strong{display:block;color:#111;font-size:21px;line-height:1.25;font-weight:780;letter-spacing:-.02em;white-space:nowrap}\n#sl-ilk-sira .game-row em{display:block;margin-top:4px;color:#5f6662;font-size:15px;line-height:1.55;font-style:normal}\n#sl-ilk-sira .play{\n    display:inline-flex;\n    align-items:center;\n    gap:9px;\n    min-height:46px;\n    padding:0 20px;\n    border-radius:10px;\n    background:var(--green);\n    color:#fff;\n    font-size:15px;\n    font-weight:700;\n    white-space:nowrap;\n}\n#sl-ilk-sira .game-row:hover .play{background:var(--green-dark)}\n#sl-ilk-sira .play svg{width:14px;height:14px;fill:currentColor}\n#sl-ilk-sira .all-games{\n    display:inline-flex;\n    align-items:center;\n    gap:8px;\n    margin-top:14px;\n    color:#111;\n    font-size:14.5px;\n    font-weight:700;\n    text-decoration:none;\n}\n#sl-ilk-sira .all-games:hover{color:var(--green-dark)}\n\n\/* REAL RESULTS *\/\n#sl-ilk-sira .real{padding:40px 0 80px}\n#sl-ilk-sira .real-box{\n    position:relative;\n    overflow:hidden;\n    padding:46px 44px 40px;\n    border-radius:26px;\n    background:var(--ink);\n    color:#fff;\n}\n#sl-ilk-sira .real-box::after{\n    content:\"\";\n    position:absolute;\n    right:-120px;\n    top:-140px;\n    width:420px;\n    height:420px;\n    border-radius:50%;\n    border:56px solid rgba(201,242,78,.07);\n    pointer-events:none;\n}\n#sl-ilk-sira .real-box h2{\n    position:relative;\n    color:#fff;\n    font-size:44px;\n    line-height:1.06;\n    letter-spacing:-.04em;\n    font-weight:790;\n    white-space:nowrap;\n}\n#sl-ilk-sira .real-box > p{\n    position:relative;\n    max-width:760px;\n    margin:14px 0 0;\n    color:#bcd3c6;\n    font-size:16.5px;\n    line-height:1.65;\n}\n#sl-ilk-sira .wins{\n    position:relative;\n    display:grid;\n    grid-template-columns:repeat(3,minmax(0,1fr));\n    gap:12px;\n    margin-top:16px;\n}\n#sl-ilk-sira .win{\n    display:flex;\n    flex-direction:column;\n    padding:20px 20px 16px;\n    border-radius:18px;\n    background:#fff;\n    color:#111;\n    text-decoration:none;\n    transition:transform .16s ease;\n}\n#sl-ilk-sira .win:hover{transform:translateY(-3px)}\n#sl-ilk-sira .win-top{\n    display:flex;\n    align-items:center;\n    justify-content:space-between;\n    gap:10px;\n    color:#171717;\n    font-size:15px;\n    font-weight:750;\n}\n#sl-ilk-sira .win-top span{\n    padding:4px 10px;\n    border-radius:999px;\n    background:#eef8f3;\n    color:var(--green-dark);\n    font-size:12.5px;\n    font-weight:700;\n    white-space:nowrap;\n}\n#sl-ilk-sira .win strong{\n    display:block;\n    margin-top:14px;\n    color:var(--green);\n    font-size:46px;\n    line-height:1;\n    letter-spacing:-.04em;\n    font-weight:800;\n}\n#sl-ilk-sira .win em{\n    display:block;\n    margin-top:6px;\n    color:#555;\n    font-size:14.5px;\n    font-style:normal;\n    font-weight:600;\n}\n#sl-ilk-sira .win-foot{\n    display:flex;\n    align-items:center;\n    justify-content:space-between;\n    gap:12px;\n    margin-top:16px;\n    padding-top:14px;\n    border-top:1px solid #edf1ee;\n    font-size:14px;\n    font-weight:700;\n}\n#sl-ilk-sira .go{\n    display:flex;\n    align-items:center;\n    justify-content:center;\n    flex:none;\n    width:30px;\n    height:30px;\n    border-radius:50%;\n    background:var(--green);\n    color:#fff;\n}\n#sl-ilk-sira .go svg{display:block;width:14px;height:14px;fill:none;stroke:currentColor;stroke-width:2.2;stroke-linecap:round;stroke-linejoin:round}\n#sl-ilk-sira .actions{\n    position:relative;\n    display:flex;\n    flex-wrap:wrap;\n    align-items:center;\n    gap:10px;\n    margin-top:24px;\n}\n#sl-ilk-sira .bridge{\n    position:relative;\n    margin:36px 0 0;\n    padding-top:26px;\n    border-top:1px solid rgba(255,255,255,.12);\n    color:#fff;\n    font-size:17px;\n    font-weight:700;\n    letter-spacing:-.01em;\n}\n#sl-ilk-sira .real-box h2.is-result{color:var(--lime)}\n#sl-ilk-sira .btn{\n    display:inline-flex;\n    align-items:center;\n    justify-content:center;\n    gap:8px;\n    min-height:52px;\n    padding:0 24px;\n    border-radius:10px;\n    font-size:15.5px;\n    font-weight:700;\n    text-decoration:none;\n    white-space:nowrap;\n    transition:background .16s ease,border-color .16s ease;\n}\n#sl-ilk-sira .btn.primary{background:var(--lime);color:var(--ink)}\n#sl-ilk-sira .btn.primary:hover{background:#fff}\n#sl-ilk-sira .btn.ghost{border:1px solid rgba(255,255,255,.25);color:#fff}\n#sl-ilk-sira .btn.ghost:hover{border-color:rgba(255,255,255,.6)}\n\n\n@media(max-width:1100px){\n    #sl-ilk-sira .rules{grid-template-columns:repeat(2,minmax(0,1fr))}\n}\n@media(max-width:1000px){\n    #sl-ilk-sira .wins{grid-template-columns:1fr 1fr 1fr;gap:10px}\n    #sl-ilk-sira .win strong{font-size:36px}\n}\n@media(max-width:760px){\n    #sl-ilk-sira .wrap{width:min(100% - 20px,1180px)}\n    #sl-ilk-sira .sec-head h2{font-size:clamp(24px,7.4vw,30px)}\n    #sl-ilk-sira .sec-head p{font-size:15px}\n    #sl-ilk-sira .how{padding:38px 0 18px}\n    #sl-ilk-sira .keys{gap:8px;margin-top:16px}\n    #sl-ilk-sira .keys span{font-size:13.5px}\n    #sl-ilk-sira .rules{grid-template-columns:1fr;gap:12px;margin-top:20px}\n    #sl-ilk-sira .rule{display:grid;grid-template-columns:140px minmax(0,1fr);align-items:stretch}\n    #sl-ilk-sira .scene{aspect-ratio:auto;height:100%;min-height:96px}\n    #sl-ilk-sira .rule-text{padding:12px 14px}\n    #sl-ilk-sira .rule-text h3{font-size:16.5px}\n    #sl-ilk-sira .rule-text p{margin-top:3px;font-size:13.5px;line-height:1.5}\n    #sl-ilk-sira .others{padding:26px 0 12px}\n    #sl-ilk-sira .game-list{margin-top:14px}\n    #sl-ilk-sira .game-row{grid-template-columns:84px minmax(0,1fr);gap:12px;padding:10px 12px 12px 10px}\n    #sl-ilk-sira .game-thumb{width:84px;height:64px}\n    #sl-ilk-sira .game-row strong{font-size:clamp(14px,4.2vw,19px)}\n    #sl-ilk-sira .game-row em{font-size:13.5px}\n    #sl-ilk-sira .game-row .play{grid-column:1 \/ -1;justify-content:center;min-height:48px}\n    #sl-ilk-sira .real{padding:26px 0 56px}\n    #sl-ilk-sira .real-box{padding:28px 20px 22px;border-radius:22px}\n    #sl-ilk-sira .real-box h2{font-size:clamp(22px,6.9vw,30px)}\n    #sl-ilk-sira .real-box > p{font-size:15px}\n    #sl-ilk-sira .wins{grid-template-columns:1fr;margin-top:14px}\n    #sl-ilk-sira .wins{gap:8px}\n    #sl-ilk-sira .win{display:grid;grid-template-columns:minmax(0,1fr) 30px;align-items:center;column-gap:12px;padding:14px 16px}\n    #sl-ilk-sira .win-top{grid-column:1 \/ -1}\n    #sl-ilk-sira .win strong{margin-top:10px;font-size:34px}\n    #sl-ilk-sira .win em{grid-column:1;margin-top:4px;font-size:14px}\n    #sl-ilk-sira .win-foot{grid-column:2;grid-row:2 \/ span 2;margin:0;padding:0;border:0;font-size:0}\n    #sl-ilk-sira .actions{flex-direction:column;align-items:stretch;margin-top:20px}\n    #sl-ilk-sira .bridge{margin-top:26px;padding-top:20px;font-size:15.5px}\n    #sl-ilk-sira .btn{width:100%}\n    #sl-ilk-sira .win,#sl-ilk-sira .more-box{transition:none}\n}\n@media (prefers-reduced-motion:reduce){\n    #sl-ilk-sira .rule,#sl-ilk-sira .game-row,#sl-ilk-sira .win{transition:none}\n}\n<\/style>\n\n<div id=\"sl-ilk-sira\">\n\n    <section class=\"how\" aria-labelledby=\"nasil-oynanir\">\n        <div class=\"wrap\">\n            <div class=\"sec-head\">\n                <h2 id=\"nasil-oynanir\">Nas\u0131l oynan\u0131r?<\/h2>\n                <p>Siteniz 100.&nbsp;s\u0131radan ba\u015flar. Algoritma birka\u00e7 saniyede bir kural de\u011fi\u015ftirir; kurala uyan y\u00fckselir, \u00e7arpan can kaybeder. 2.&nbsp;s\u0131raya \u00e7\u0131k\u0131nca final ba\u015flar.<\/p>\n            <\/div>\n            <div class=\"keys\">\n                <span><kbd>Dokun<\/kbd>ya da<kbd>Bo\u015fluk<\/kbd>z\u0131pla<\/span>\n                <span><kbd>Bas\u0131l\u0131 tut<\/kbd>daha y\u00fckse\u011fe<\/span>\n                <span><kbd>Havada tekrar<\/kbd>\u00e7ift z\u0131pla<\/span>\n            <\/div>\n            <div class=\"rules\">\n                <article class=\"rule\">\n                    <div class=\"scene\" aria-hidden=\"true\"><svg viewBox=\"0 0 320 170\" preserveAspectRatio=\"xMidYMid slice\"><rect width=\"320\" height=\"170\" fill=\"#EAF3EE\"\/><circle cx=\"270\" cy=\"40\" r=\"46\" fill=\"none\" stroke=\"#039358\" stroke-opacity=\".06\" stroke-width=\"16\"\/><rect x=\"0\" y=\"132\" width=\"320\" height=\"38\" fill=\"#04281c\"\/><rect x=\"0\" y=\"132\" width=\"320\" height=\"3\" fill=\"#039358\"\/><g fill=\"#c9f24e\" fill-opacity=\".18\"><rect x=\"14\" y=\"148\" width=\"26\" height=\"3\" rx=\"1.5\"\/><rect x=\"74\" y=\"148\" width=\"26\" height=\"3\" rx=\"1.5\"\/><rect x=\"134\" y=\"148\" width=\"26\" height=\"3\" rx=\"1.5\"\/><rect x=\"194\" y=\"148\" width=\"26\" height=\"3\" rx=\"1.5\"\/><rect x=\"254\" y=\"148\" width=\"26\" height=\"3\" rx=\"1.5\"\/><\/g><g transform=\"translate(40 98) scale(1)\"><rect x=\"0\" y=\"0\" width=\"30\" height=\"27\" rx=\"8\" fill=\"#fff\" stroke=\"#cfe0d6\" stroke-width=\"1.3\"\/><rect x=\"5\" y=\"6\" width=\"3.6\" height=\"15\" rx=\"1.8\" fill=\"#039358\"\/><circle cx=\"15\" cy=\"12\" r=\"2.5\" fill=\"#04281c\"\/><circle cx=\"23\" cy=\"12\" r=\"2.5\" fill=\"#04281c\"\/><path d=\"M15.5 18q3.5 3 7 0\" fill=\"none\" stroke=\"#04281c\" stroke-width=\"1.8\" stroke-linecap=\"round\"\/><path d=\"M10 27l-2 6M20 27l2 6\" stroke=\"#04281c\" stroke-width=\"2.4\" stroke-linecap=\"round\"\/><\/g><path d=\"M58 96 Q110 20 158 52\" fill=\"none\" stroke=\"#039358\" stroke-opacity=\".45\" stroke-width=\"2.4\" stroke-dasharray=\"3 6\" stroke-linecap=\"round\"\/><circle cx=\"161\" cy=\"53\" r=\"19\" fill=\"#c9f24e\" fill-opacity=\".35\"\/><g transform=\"translate(150 40)\"><path d=\"M1 1h14l6 6v19H1z\" fill=\"#fff\" stroke=\"#039358\" stroke-width=\"2\"\/><path d=\"M5 12h10M5 16h10M5 20h6\" stroke=\"#039358\" stroke-width=\"1.8\" stroke-linecap=\"round\"\/><\/g><circle cx=\"197\" cy=\"47\" r=\"19\" fill=\"#c9f24e\" fill-opacity=\".35\"\/><g transform=\"translate(186 34)\"><path d=\"M1 1h14l6 6v19H1z\" fill=\"#fff\" stroke=\"#039358\" stroke-width=\"2\"\/><path d=\"M5 12h10M5 16h10M5 20h6\" stroke=\"#039358\" stroke-width=\"1.8\" stroke-linecap=\"round\"\/><\/g><circle cx=\"233\" cy=\"53\" r=\"19\" fill=\"#c9f24e\" fill-opacity=\".35\"\/><g transform=\"translate(222 40)\"><path d=\"M1 1h14l6 6v19H1z\" fill=\"#fff\" stroke=\"#039358\" stroke-width=\"2\"\/><path d=\"M5 12h10M5 16h10M5 20h6\" stroke=\"#039358\" stroke-width=\"1.8\" stroke-linecap=\"round\"\/><\/g><g transform=\"translate(160 104)\"><path d=\"M1 1h14l6 6v19H1z\" fill=\"#FBB9A4\" stroke=\"#E4572E\" stroke-width=\"2\"\/><circle cx=\"7.5\" cy=\"14\" r=\"1.6\" fill=\"#8A2410\"\/><circle cx=\"14\" cy=\"14\" r=\"1.6\" fill=\"#8A2410\"\/><path d=\"M7.5 21a3.4 3.4 0 0 1 6.5 0\" stroke=\"#8A2410\" stroke-width=\"1.7\" fill=\"none\" stroke-linecap=\"round\"\/><\/g><g transform=\"translate(196 104)\"><path d=\"M1 1h14l6 6v19H1z\" fill=\"#FBB9A4\" stroke=\"#E4572E\" stroke-width=\"2\"\/><circle cx=\"7.5\" cy=\"14\" r=\"1.6\" fill=\"#8A2410\"\/><circle cx=\"14\" cy=\"14\" r=\"1.6\" fill=\"#8A2410\"\/><path d=\"M7.5 21a3.4 3.4 0 0 1 6.5 0\" stroke=\"#8A2410\" stroke-width=\"1.7\" fill=\"none\" stroke-linecap=\"round\"\/><\/g><g transform=\"translate(232 104)\"><path d=\"M1 1h14l6 6v19H1z\" fill=\"#FBB9A4\" stroke=\"#E4572E\" stroke-width=\"2\"\/><circle cx=\"7.5\" cy=\"14\" r=\"1.6\" fill=\"#8A2410\"\/><circle cx=\"14\" cy=\"14\" r=\"1.6\" fill=\"#8A2410\"\/><path d=\"M7.5 21a3.4 3.4 0 0 1 6.5 0\" stroke=\"#8A2410\" stroke-width=\"1.7\" fill=\"none\" stroke-linecap=\"round\"\/><\/g><rect x=\"172\" y=\"78\" width=\"64\" height=\"20\" rx=\"10\" fill=\"#E4572E\"\/><text x=\"204.0\" y=\"92\" text-anchor=\"middle\" font-family=\"Poppins,Inter,Arial,sans-serif\" font-size=\"11\" font-weight=\"800\" fill=\"#fff\">KOPYA<\/text><\/svg><\/div>\n                    <div class=\"rule-text\"><h3>\u00d6zg\u00fcn i\u00e7erik<\/h3><p>Havadaki ye\u015fil sayfalar\u0131 topla, yerdeki kopyalara \u00e7arpma.<\/p><\/div>\n                <\/article>\n                <article class=\"rule\">\n                    <div class=\"scene\" aria-hidden=\"true\"><svg viewBox=\"0 0 320 170\" preserveAspectRatio=\"xMidYMid slice\"><rect width=\"320\" height=\"170\" fill=\"#EAF3EE\"\/><circle cx=\"270\" cy=\"40\" r=\"46\" fill=\"none\" stroke=\"#039358\" stroke-opacity=\".06\" stroke-width=\"16\"\/><rect x=\"0\" y=\"132\" width=\"320\" height=\"38\" fill=\"#04281c\"\/><rect x=\"0\" y=\"132\" width=\"320\" height=\"3\" fill=\"#039358\"\/><g fill=\"#c9f24e\" fill-opacity=\".18\"><rect x=\"14\" y=\"148\" width=\"26\" height=\"3\" rx=\"1.5\"\/><rect x=\"74\" y=\"148\" width=\"26\" height=\"3\" rx=\"1.5\"\/><rect x=\"134\" y=\"148\" width=\"26\" height=\"3\" rx=\"1.5\"\/><rect x=\"194\" y=\"148\" width=\"26\" height=\"3\" rx=\"1.5\"\/><rect x=\"254\" y=\"148\" width=\"26\" height=\"3\" rx=\"1.5\"\/><\/g><g transform=\"translate(176 96)\"><rect x=\"0\" y=\"0\" width=\"56\" height=\"36\" rx=\"6\" fill=\"#fff\" stroke=\"#6b7a73\" stroke-width=\"2\"\/><circle cx=\"14\" cy=\"12\" r=\"4\" fill=\"#F2B84B\"\/><path d=\"M6 31l12-12 9 9 7-7 14 14\" fill=\"none\" stroke=\"#6b7a73\" stroke-width=\"2\" stroke-linejoin=\"round\"\/><\/g><rect x=\"178\" y=\"74\" width=\"52\" height=\"20\" rx=\"10\" fill=\"#04281c\"\/><text x=\"204.0\" y=\"88\" text-anchor=\"middle\" font-family=\"Poppins,Inter,Arial,sans-serif\" font-size=\"11\" font-weight=\"800\" fill=\"#c9f24e\">2.4 MB<\/text><g transform=\"translate(190 28) scale(1)\"><rect x=\"0\" y=\"0\" width=\"30\" height=\"27\" rx=\"8\" fill=\"#fff\" stroke=\"#cfe0d6\" stroke-width=\"1.3\"\/><rect x=\"5\" y=\"6\" width=\"3.6\" height=\"15\" rx=\"1.8\" fill=\"#039358\"\/><circle cx=\"15\" cy=\"12\" r=\"2.5\" fill=\"#04281c\"\/><circle cx=\"23\" cy=\"12\" r=\"2.5\" fill=\"#04281c\"\/><path d=\"M15.5 18q3.5 3 7 0\" fill=\"none\" stroke=\"#04281c\" stroke-width=\"1.8\" stroke-linecap=\"round\"\/><path d=\"M10 27l-2 6M20 27l2 6\" stroke=\"#04281c\" stroke-width=\"2.4\" stroke-linecap=\"round\"\/><\/g><path d=\"M205 62v8M200 66l5 5 5-5\" fill=\"none\" stroke=\"#039358\" stroke-width=\"2.4\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\/><path d=\"M90 128 Q130 6 188 40\" fill=\"none\" stroke=\"#039358\" stroke-opacity=\".45\" stroke-width=\"2.4\" stroke-dasharray=\"3 6\" stroke-linecap=\"round\"\/><rect x=\"212\" y=\"36\" width=\"62\" height=\"20\" rx=\"10\" fill=\"#c9f24e\"\/><text x=\"243.0\" y=\"50\" text-anchor=\"middle\" font-family=\"Poppins,Inter,Arial,sans-serif\" font-size=\"11\" font-weight=\"800\" fill=\"#04281c\">\u22122.4 MB<\/text><\/svg><\/div>\n                    <div class=\"rule-text\"><h3>H\u0131z testi<\/h3><p>A\u011f\u0131r g\u00f6rselin tam \u00fcst\u00fcne z\u0131pla, g\u00f6rseli s\u0131k\u0131\u015ft\u0131r.<\/p><\/div>\n                <\/article>\n                <article class=\"rule\">\n                    <div class=\"scene\" aria-hidden=\"true\"><svg viewBox=\"0 0 320 170\" preserveAspectRatio=\"xMidYMid slice\"><rect width=\"320\" height=\"170\" fill=\"#EAF3EE\"\/><circle cx=\"270\" cy=\"40\" r=\"46\" fill=\"none\" stroke=\"#039358\" stroke-opacity=\".06\" stroke-width=\"16\"\/><rect x=\"0\" y=\"132\" width=\"320\" height=\"38\" fill=\"#04281c\"\/><rect x=\"0\" y=\"132\" width=\"320\" height=\"3\" fill=\"#039358\"\/><g fill=\"#c9f24e\" fill-opacity=\".18\"><rect x=\"14\" y=\"148\" width=\"26\" height=\"3\" rx=\"1.5\"\/><rect x=\"74\" y=\"148\" width=\"26\" height=\"3\" rx=\"1.5\"\/><rect x=\"134\" y=\"148\" width=\"26\" height=\"3\" rx=\"1.5\"\/><rect x=\"194\" y=\"148\" width=\"26\" height=\"3\" rx=\"1.5\"\/><rect x=\"254\" y=\"148\" width=\"26\" height=\"3\" rx=\"1.5\"\/><\/g><rect x=\"150\" y=\"131\" width=\"62\" height=\"24\" fill=\"#000\"\/><path d=\"M150 155 l10 6 10-6 10 6 10-6 10 6 12-6\" fill=\"#000\"\/><rect x=\"146\" y=\"131\" width=\"4\" height=\"5\" fill=\"#E4572E\"\/><rect x=\"212\" y=\"131\" width=\"4\" height=\"5\" fill=\"#E4572E\"\/><rect x=\"128\" y=\"104\" width=\"3\" height=\"28\" fill=\"#3A4A44\"\/><rect x=\"112\" y=\"86\" width=\"36\" height=\"20\" rx=\"10\" fill=\"#E4572E\"\/><text x=\"130.0\" y=\"100\" text-anchor=\"middle\" font-family=\"Poppins,Inter,Arial,sans-serif\" font-size=\"11\" font-weight=\"800\" fill=\"#fff\">404<\/text><g transform=\"translate(70 98) scale(1)\"><rect x=\"0\" y=\"0\" width=\"30\" height=\"27\" rx=\"8\" fill=\"#fff\" stroke=\"#cfe0d6\" stroke-width=\"1.3\"\/><rect x=\"5\" y=\"6\" width=\"3.6\" height=\"15\" rx=\"1.8\" fill=\"#039358\"\/><circle cx=\"15\" cy=\"12\" r=\"2.5\" fill=\"#04281c\"\/><circle cx=\"23\" cy=\"12\" r=\"2.5\" fill=\"#04281c\"\/><path d=\"M15.5 18q3.5 3 7 0\" fill=\"none\" stroke=\"#04281c\" stroke-width=\"1.8\" stroke-linecap=\"round\"\/><path d=\"M10 27l-2 6M20 27l2 6\" stroke=\"#04281c\" stroke-width=\"2.4\" stroke-linecap=\"round\"\/><\/g><path d=\"M88 96 Q181 -6 246 124\" fill=\"none\" stroke=\"#039358\" stroke-opacity=\".45\" stroke-width=\"2.4\" stroke-dasharray=\"3 6\" stroke-linecap=\"round\"\/><g transform=\"translate(170 30)\"><circle cx=\"11\" cy=\"11\" r=\"17\" fill=\"#c9f24e\" fill-opacity=\".35\"\/><circle cx=\"11\" cy=\"11\" r=\"11\" fill=\"#6A5AE0\"\/><g transform=\"rotate(-45 11 11)\" fill=\"none\" stroke=\"#fff\" stroke-width=\"2\"><rect x=\"3.5\" y=\"8.6\" width=\"8\" height=\"4.8\" rx=\"2.4\"\/><rect x=\"10.5\" y=\"8.6\" width=\"8\" height=\"4.8\" rx=\"2.4\"\/><\/g><\/g><\/svg><\/div>\n                    <div class=\"rule-text\"><h3>K\u0131r\u0131k linkler<\/h3><p>404 \u00e7ukurunun \u00fcst\u00fcnden atla, linki havada kap.<\/p><\/div>\n                <\/article>\n                <article class=\"rule\">\n                    <div class=\"scene\" aria-hidden=\"true\"><svg viewBox=\"0 0 320 170\" preserveAspectRatio=\"xMidYMid slice\"><rect width=\"320\" height=\"170\" fill=\"#EAF3EE\"\/><circle cx=\"270\" cy=\"40\" r=\"46\" fill=\"none\" stroke=\"#039358\" stroke-opacity=\".06\" stroke-width=\"16\"\/><rect x=\"0\" y=\"132\" width=\"320\" height=\"38\" fill=\"#04281c\"\/><rect x=\"0\" y=\"132\" width=\"320\" height=\"3\" fill=\"#039358\"\/><g fill=\"#c9f24e\" fill-opacity=\".18\"><rect x=\"14\" y=\"148\" width=\"26\" height=\"3\" rx=\"1.5\"\/><rect x=\"74\" y=\"148\" width=\"26\" height=\"3\" rx=\"1.5\"\/><rect x=\"134\" y=\"148\" width=\"26\" height=\"3\" rx=\"1.5\"\/><rect x=\"194\" y=\"148\" width=\"26\" height=\"3\" rx=\"1.5\"\/><rect x=\"254\" y=\"148\" width=\"26\" height=\"3\" rx=\"1.5\"\/><\/g><path d=\"M213 8v44\" stroke=\"#E4572E\" stroke-opacity=\".35\" stroke-width=\"2\" stroke-dasharray=\"3 5\"\/><g transform=\"translate(200 52)\"><rect width=\"26\" height=\"22\" rx=\"5\" fill=\"#E4572E\"\/><path d=\"M5 7l6 8 4-6 6 8\" fill=\"none\" stroke=\"#fff\" stroke-width=\"2.2\" stroke-linejoin=\"round\"\/><\/g><ellipse cx=\"213\" cy=\"134\" rx=\"14\" ry=\"3\" fill=\"#E4572E\" fill-opacity=\".55\"\/><g transform=\"translate(252 110)\"><rect width=\"26\" height=\"22\" rx=\"5\" fill=\"#E4572E\"\/><path d=\"M5 7l6 8 4-6 6 8\" fill=\"none\" stroke=\"#fff\" stroke-width=\"2.2\" stroke-linejoin=\"round\"\/><\/g><circle cx=\"120\" cy=\"112\" r=\"30\" fill=\"#6A5AE0\" fill-opacity=\".14\" stroke=\"#6A5AE0\" stroke-width=\"2.4\"\/><g transform=\"translate(105 98) scale(1)\"><rect x=\"0\" y=\"0\" width=\"30\" height=\"27\" rx=\"8\" fill=\"#fff\" stroke=\"#cfe0d6\" stroke-width=\"1.3\"\/><rect x=\"5\" y=\"6\" width=\"3.6\" height=\"15\" rx=\"1.8\" fill=\"#039358\"\/><circle cx=\"15\" cy=\"12\" r=\"2.5\" fill=\"#04281c\"\/><circle cx=\"23\" cy=\"12\" r=\"2.5\" fill=\"#04281c\"\/><path d=\"M15.5 18q3.5 3 7 0\" fill=\"none\" stroke=\"#04281c\" stroke-width=\"1.8\" stroke-linecap=\"round\"\/><path d=\"M10 27l-2 6M20 27l2 6\" stroke=\"#04281c\" stroke-width=\"2.4\" stroke-linecap=\"round\"\/><\/g><g transform=\"translate(46 40)\"><circle cx=\"12\" cy=\"13\" r=\"20\" fill=\"#c9f24e\" fill-opacity=\".35\"\/><path d=\"M12 0l11 4v8c0 7-4.8 11.9-11 14C5.8 23.9 1 19 1 12V4z\" fill=\"#6A5AE0\"\/><path d=\"M7 12.5l3.6 3.6 6.8-7.2\" fill=\"none\" stroke=\"#fff\" stroke-width=\"2.2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\/><\/g><rect x=\"140\" y=\"64\" width=\"30\" height=\"20\" rx=\"10\" fill=\"#6A5AE0\"\/><text x=\"155.0\" y=\"78\" text-anchor=\"middle\" font-family=\"Poppins,Inter,Arial,sans-serif\" font-size=\"11\" font-weight=\"800\" fill=\"#fff\">x1<\/text><\/svg><\/div>\n                    <div class=\"rule-text\"><h3>Core update<\/h3><p>Kalkan topla; k\u0131rm\u0131z\u0131 sars\u0131nt\u0131ya kalkans\u0131z yakalanma.<\/p><\/div>\n                <\/article>\n                <article class=\"rule\">\n                    <div class=\"scene\" aria-hidden=\"true\"><svg viewBox=\"0 0 320 170\" preserveAspectRatio=\"xMidYMid slice\"><rect width=\"320\" height=\"170\" fill=\"#EAF3EE\"\/><circle cx=\"270\" cy=\"40\" r=\"46\" fill=\"none\" stroke=\"#039358\" stroke-opacity=\".06\" stroke-width=\"16\"\/><rect x=\"0\" y=\"132\" width=\"320\" height=\"38\" fill=\"#04281c\"\/><rect x=\"0\" y=\"132\" width=\"320\" height=\"3\" fill=\"#039358\"\/><g fill=\"#c9f24e\" fill-opacity=\".18\"><rect x=\"14\" y=\"148\" width=\"26\" height=\"3\" rx=\"1.5\"\/><rect x=\"74\" y=\"148\" width=\"26\" height=\"3\" rx=\"1.5\"\/><rect x=\"134\" y=\"148\" width=\"26\" height=\"3\" rx=\"1.5\"\/><rect x=\"194\" y=\"148\" width=\"26\" height=\"3\" rx=\"1.5\"\/><rect x=\"254\" y=\"148\" width=\"26\" height=\"3\" rx=\"1.5\"\/><\/g><g transform=\"translate(196 106)\"><rect width=\"34\" height=\"26\" rx=\"5\" fill=\"#F27A3A\"\/><path d=\"M3 4l14 11 14-11\" fill=\"none\" stroke=\"#fff\" stroke-width=\"2\" stroke-linejoin=\"round\"\/><circle cx=\"33\" cy=\"2\" r=\"6\" fill=\"#E4572E\"\/><path d=\"M33 -1v3.4\" stroke=\"#fff\" stroke-width=\"1.8\" stroke-linecap=\"round\"\/><\/g><g stroke=\"#F27A3A\" stroke-opacity=\".5\" stroke-width=\"2.4\" stroke-linecap=\"round\"><path d=\"M240 112h22M244 120h28M240 128h18\"\/><\/g><g transform=\"translate(150 40) scale(1)\"><rect x=\"0\" y=\"0\" width=\"30\" height=\"27\" rx=\"8\" fill=\"#fff\" stroke=\"#cfe0d6\" stroke-width=\"1.3\"\/><rect x=\"5\" y=\"6\" width=\"3.6\" height=\"15\" rx=\"1.8\" fill=\"#039358\"\/><circle cx=\"15\" cy=\"12\" r=\"2.5\" fill=\"#04281c\"\/><circle cx=\"23\" cy=\"12\" r=\"2.5\" fill=\"#04281c\"\/><path d=\"M15.5 18q3.5 3 7 0\" fill=\"none\" stroke=\"#04281c\" stroke-width=\"1.8\" stroke-linecap=\"round\"\/><path d=\"M10 27l-2 6M20 27l2 6\" stroke=\"#04281c\" stroke-width=\"2.4\" stroke-linecap=\"round\"\/><\/g><path d=\"M110 128 Q150 0 200 96\" fill=\"none\" stroke=\"#039358\" stroke-opacity=\".45\" stroke-width=\"2.4\" stroke-dasharray=\"3 6\" stroke-linecap=\"round\"\/><path d=\"M172 82v10M167 88l5 5 5-5\" fill=\"none\" stroke=\"#039358\" stroke-width=\"2.4\" stroke-linecap=\"round\" stroke-linejoin=\"round\" opacity=\"0\"\/><\/svg><\/div>\n                    <div class=\"rule-text\"><h3>Spam sald\u0131r\u0131s\u0131<\/h3><p>Yerden gelenin \u00fcst\u00fcnden z\u0131pla, havadan gelenin alt\u0131nda kal.<\/p><\/div>\n                <\/article>\n                <article class=\"rule is-final\">\n                    <div class=\"scene\" aria-hidden=\"true\"><svg viewBox=\"0 0 320 170\" preserveAspectRatio=\"xMidYMid slice\"><rect width=\"320\" height=\"170\" fill=\"#0b3325\"\/><circle cx=\"160\" cy=\"-10\" r=\"120\" fill=\"#c9f24e\" fill-opacity=\".06\"\/><rect x=\"0\" y=\"132\" width=\"320\" height=\"38\" fill=\"#04281c\"\/><rect x=\"0\" y=\"132\" width=\"320\" height=\"3\" fill=\"#c9f24e\"\/><g transform=\"translate(92 98) scale(1)\"><rect x=\"0\" y=\"0\" width=\"30\" height=\"27\" rx=\"8\" fill=\"#fff\" stroke=\"#cfe0d6\" stroke-width=\"1.3\"\/><rect x=\"5\" y=\"6\" width=\"3.6\" height=\"15\" rx=\"1.8\" fill=\"#039358\"\/><circle cx=\"15\" cy=\"12\" r=\"2.5\" fill=\"#04281c\"\/><circle cx=\"23\" cy=\"12\" r=\"2.5\" fill=\"#04281c\"\/><path d=\"M15.5 18q3.5 3 7 0\" fill=\"none\" stroke=\"#04281c\" stroke-width=\"1.8\" stroke-linecap=\"round\"\/><path d=\"M10 27l-2 6M20 27l2 6\" stroke=\"#04281c\" stroke-width=\"2.4\" stroke-linecap=\"round\"\/><\/g><path d=\"M96 92l2-12 6 6 3-9 3 9 6-6 2 12z\" fill=\"#FFD84D\" stroke=\"#E0B21C\" stroke-width=\"1.2\" stroke-linejoin=\"round\"\/><g transform=\"translate(196 90)\"><rect width=\"38\" height=\"42\" rx=\"9\" fill=\"#2F4F8F\"\/><rect x=\"5\" y=\"8\" width=\"4\" height=\"26\" rx=\"2\" fill=\"#6F8FD6\"\/><rect x=\"29\" y=\"8\" width=\"4\" height=\"26\" rx=\"2\" fill=\"#F27A3A\"\/><circle cx=\"15\" cy=\"17\" r=\"2.6\" fill=\"#fff\"\/><circle cx=\"23\" cy=\"17\" r=\"2.6\" fill=\"#fff\"\/><path d=\"M14 26h10\" stroke=\"#fff\" stroke-width=\"2\" stroke-linecap=\"round\"\/><\/g><rect x=\"60\" y=\"22\" width=\"200\" height=\"14\" rx=\"7\" fill=\"#7A2A1A\"\/><rect x=\"138\" y=\"22\" width=\"50\" height=\"14\" rx=\"4\" fill=\"#C9A227\"\/><rect x=\"150\" y=\"22\" width=\"26\" height=\"14\" rx=\"4\" fill=\"#c9f24e\"\/><rect x=\"161\" y=\"16\" width=\"5\" height=\"26\" rx=\"2.5\" fill=\"#fff\"\/><text x=\"160\" y=\"60\" text-anchor=\"middle\" font-family=\"Poppins,Inter,Arial,sans-serif\" font-size=\"13\" font-weight=\"800\" fill=\"#c9f24e\">ATAK!<\/text><\/svg><\/div>\n                    <div class=\"rule-text\"><h3>Final<\/h3><p>\u0130bre ye\u015fildeyken bas, 1. s\u0131radaki rakibi ge\u00e7.<\/p><\/div>\n                <\/article>\n            <\/div>\n        <\/div>\n    <\/section>\n\n    <section class=\"others\" aria-labelledby=\"diger-oyunlar\">\n        <div class=\"wrap\">\n            <div class=\"sec-head\">\n                <h2 id=\"diger-oyunlar\">Di\u011fer oyunlar<\/h2>\n            <\/div>\n            <div class=\"game-list\">\n                <a class=\"game-row\" href=\"https:\/\/www.seoliva.com\/seo-oyunlari\/arama-tahmini\">\n                    <span class=\"game-thumb\" aria-hidden=\"true\">\n                        <svg viewBox=\"0 0 132 92\" preserveAspectRatio=\"xMidYMid meet\">\n                            <rect width=\"132\" height=\"92\" fill=\"#EEF2EF\"\/>\n                            <g transform=\"rotate(-5 40 46)\"><rect x=\"14\" y=\"14\" width=\"46\" height=\"62\" rx=\"9\" fill=\"#fff\" stroke=\"#039358\" stroke-width=\"2\"\/><circle cx=\"37\" cy=\"36\" r=\"10\" fill=\"none\" stroke=\"#039358\" stroke-width=\"2\"\/><circle cx=\"37\" cy=\"36\" r=\"2.6\" fill=\"#039358\"\/><rect x=\"21\" y=\"56\" width=\"32\" height=\"10\" rx=\"5\" fill=\"#04281c\"\/><\/g>\n                            <g transform=\"rotate(5 92 46)\"><rect x=\"72\" y=\"14\" width=\"46\" height=\"62\" rx=\"9\" fill=\"#fff\" stroke=\"#D5E0D9\" stroke-width=\"1.5\"\/><rect x=\"85\" y=\"26\" width=\"20\" height=\"20\" rx=\"5\" fill=\"none\" stroke=\"#9aa39d\" stroke-width=\"2\"\/><rect x=\"80\" y=\"56\" width=\"30\" height=\"10\" rx=\"5\" fill=\"#EEF2EF\"\/><\/g>\n                            <rect x=\"52\" y=\"37\" width=\"28\" height=\"18\" rx=\"9\" fill=\"#111\"\/>\n                            <text x=\"66\" y=\"49.5\" text-anchor=\"middle\" font-family=\"Poppins,Inter,Arial,sans-serif\" font-size=\"8\" font-weight=\"800\" fill=\"#fff\">ya da<\/text>\n                        <\/svg>\n                    <\/span>\n                    <span><strong>Hangisi Daha \u00c7ok Aran\u0131yor?<\/strong><em>\u0130ki aramadan hangisi Google'da daha \u00e7ok aran\u0131yor, tahmin et.<\/em><\/span>\n                    <span class=\"play\"><svg viewBox=\"0 0 16 16\" aria-hidden=\"true\"><path d=\"M4 2.5v11l9-5.5z\"\/><\/svg>Oyna<\/span>\n                <\/a>\n            <\/div>\n            <a class=\"all-games\" href=\"https:\/\/www.seoliva.com\/seo-oyunlari\">T\u00fcm SEO oyunlar\u0131 <span aria-hidden=\"true\">\u2192<\/span><\/a>\n        <\/div>\n    <\/section>\n\n    <section class=\"real\">\n        <div class=\"wrap\">\n            <div class=\"real-box\">\n                <h2 id=\"sl-real-title\">Siteniz ka\u00e7\u0131nc\u0131 s\u0131rada?<\/h2>\n                <p id=\"sl-real-text\">Oyundaki s\u0131ra birka\u00e7 dakikada de\u011fi\u015fiyor, ger\u00e7e\u011fi ise Google'da. Sitenizin bug\u00fcn hangi s\u0131rada oldu\u011funu S\u0131ra Bulucu ile \u00fccretsiz g\u00f6r\u00fcn; y\u00fckselmek i\u00e7in gerisini birlikte planlayal\u0131m.<\/p>\n\n                <div class=\"actions\">\n                    <a class=\"btn primary\" href=\"https:\/\/www.seoliva.com\/sira-bulucu\">Ger\u00e7ek S\u0131ram\u0131 Bul <span aria-hidden=\"true\">\u2192<\/span><\/a>\n                    <a class=\"btn ghost\" href=\"https:\/\/www.seoliva.com\/iletisim\">Sitenize Birlikte Bakal\u0131m<\/a>\n                <\/div>\n\n                <p class=\"bridge\">S\u0131ra y\u00fckselince trafik de geliyor. M\u00fc\u015fterilerimizin sonu\u00e7lar\u0131:<\/p>\n                <div class=\"wins\">\n                    <a class=\"win\" href=\"https:\/\/www.seoliva.com\/shipentegra-seo-basari-hikayesi\">\n                        <span class=\"win-top\">ShipEntegra<span>\u0130lk 90 g\u00fcn<\/span><\/span>\n                        <strong>+%148<\/strong>\n                        <em>Organik trafik art\u0131\u015f\u0131<\/em>\n                        <span class=\"win-foot\">Hikayeyi oku<span class=\"go\" aria-hidden=\"true\"><svg viewBox=\"0 0 16 16\"><path d=\"M3 8h9M8.5 4.5 12 8l-3.5 3.5\"\/><\/svg><\/span><\/span>\n                    <\/a>\n                    <a class=\"win\" href=\"https:\/\/www.seoliva.com\/ortoplus-seo-basari-hikayesi\">\n                        <span class=\"win-top\">OrtoPlus<span>Son 3 ay<\/span><\/span>\n                        <strong>+%177<\/strong>\n                        <em>Organik t\u0131klama art\u0131\u015f\u0131<\/em>\n                        <span class=\"win-foot\">Hikayeyi oku<span class=\"go\" aria-hidden=\"true\"><svg viewBox=\"0 0 16 16\"><path d=\"M3 8h9M8.5 4.5 12 8l-3.5 3.5\"\/><\/svg><\/span><\/span>\n                    <\/a>\n                    <a class=\"win\" href=\"https:\/\/www.seoliva.com\/profpetmama-seo-basari-hikayesi\">\n                        <span class=\"win-top\">ProfpetMama<span>\u0130lk 6 ay<\/span><\/span>\n                        <strong>+%814<\/strong>\n                        <em>Organik trafik art\u0131\u015f\u0131<\/em>\n                        <span class=\"win-foot\">Hikayeyi oku<span class=\"go\" aria-hidden=\"true\"><svg viewBox=\"0 0 16 16\"><path d=\"M3 8h9M8.5 4.5 12 8l-3.5 3.5\"\/><\/svg><\/span><\/span>\n                    <\/a>\n                <\/div>\n\n            <\/div>\n        <\/div>\n    <\/section>\n\n<\/div>\n\n<script>\n(function(){\n    var title = document.getElementById('sl-real-title');\n    var text = document.getElementById('sl-real-text');\n    if (!title || !text) return;\n    var TOPIC = { orijinal:'kopya i\u00e7erik', hiz:'a\u011f\u0131r g\u00f6rseller', core:'core update', kirik:'k\u0131r\u0131k linkler', spam:'spam' };\n    function show(d){\n        if (!d || !d.rank) return;\n        var r = parseInt(d.rank, 10);\n        if (!r) return;\n        title.textContent = 'Oyunda #' + r + '. Ger\u00e7ekte?';\n        title.classList.add('is-result');\n        var first = r === 1 ? 'Oyunda zirveye \u00e7\u0131kt\u0131n\u0131z. ' : r >= 100 ? 'Bu tur 100. s\u0131radan \u00e7\u0131kamad\u0131n\u0131z, bir tur daha deneyin. ' : 'Oyunda ' + r + '. s\u0131raya kadar y\u00fckseldiniz. ';\n        var weak = d.weakest && TOPIC[d.weakest] ? 'Sizi en \u00e7ok ' + TOPIC[d.weakest] + ' zorlad\u0131; ger\u00e7ek sitenizde de ayn\u0131 sorun olabilir. ' : '';\n        text.textContent = first + weak + 'Sitenizin Google\\'daki ger\u00e7ek s\u0131ras\u0131n\u0131 S\u0131ra Bulucu ile \u00fccretsiz g\u00f6r\u00fcn, gerisini birlikte planlayal\u0131m.';\n    }\n    try { show(JSON.parse(sessionStorage.getItem('sl_oyun_sonuc') || 'null')); } catch(e){}\n    window.addEventListener('seoliva:oyun-bitti', function(e){ show(e.detail); });\n})();\n<\/script>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>Nas\u0131l oynan\u0131r? Siteniz 100.&nbsp;s\u0131radan ba\u015flar. Algoritma birka\u00e7 saniyede bir kural de\u011fi\u015ftirir; kurala uyan y\u00fckselir, \u00e7arpan can kaybeder. 2.&nbsp;s\u0131raya \u00e7\u0131k\u0131nca final ba\u015flar. Dokunya daBo\u015flukz\u0131pla Bas\u0131l\u0131 tutdaha y\u00fckse\u011fe Havada tekrar\u00e7ift z\u0131pla KOPYA \u00d6zg\u00fcn i\u00e7erik Havadaki ye\u015fil sayfalar\u0131 topla, yerdeki kopyalara \u00e7arpma. 2.4 MB\u22122.4 MB H\u0131z testi A\u011f\u0131r g\u00f6rselin tam \u00fcst\u00fcne z\u0131pla, g\u00f6rseli s\u0131k\u0131\u015ft\u0131r. 404 K\u0131r\u0131k linkler 404 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":5189,"parent":4910,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"elementor_header_footer","meta":{"_acf_changed":false,"footnotes":""},"class_list":["post-4915","page","type-page","status-publish","has-post-thumbnail","hentry"],"acf":[],"permalink_manager":null,"_links":{"self":[{"href":"https:\/\/www.seoliva.com\/en\/wp-json\/wp\/v2\/pages\/4915","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.seoliva.com\/en\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.seoliva.com\/en\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.seoliva.com\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.seoliva.com\/en\/wp-json\/wp\/v2\/comments?post=4915"}],"version-history":[{"count":28,"href":"https:\/\/www.seoliva.com\/en\/wp-json\/wp\/v2\/pages\/4915\/revisions"}],"predecessor-version":[{"id":5295,"href":"https:\/\/www.seoliva.com\/en\/wp-json\/wp\/v2\/pages\/4915\/revisions\/5295"}],"up":[{"embeddable":true,"href":"https:\/\/www.seoliva.com\/en\/wp-json\/wp\/v2\/pages\/4910"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.seoliva.com\/en\/wp-json\/wp\/v2\/media\/5189"}],"wp:attachment":[{"href":"https:\/\/www.seoliva.com\/en\/wp-json\/wp\/v2\/media?parent=4915"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}