{"id":7057,"date":"2026-02-09T17:02:13","date_gmt":"2026-02-09T16:02:13","guid":{"rendered":"https:\/\/bulldogmusik.it\/?page_id=7057"},"modified":"2026-07-05T18:08:11","modified_gmt":"2026-07-05T16:08:11","slug":"bulldogle-rap-ita","status":"publish","type":"page","link":"https:\/\/bulldogmusik.it\/en\/bulldogle-rap-ita\/","title":{"rendered":"Bulldogle"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"7057\" class=\"elementor elementor-7057\">\n\t\t\t\t<div class=\"elementor-element elementor-element-2b2821e elementor-hidden-desktop elementor-hidden-tablet elementor-hidden-mobile e-flex e-con-boxed wcf-starter-animations-none e-con e-parent\" data-id=\"2b2821e\" 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-789bc05 wcf-starter-animations-none elementor-widget elementor-widget-text-editor\" data-id=\"789bc05\" data-element_type=\"widget\" data-e-type=\"widget\" data-settings=\"{&quot;wcf_starter_animations&quot;:&quot;none&quot;,&quot;wcf_anim_duration&quot;:1000,&quot;wcf_anim_delay&quot;:0,&quot;wcf_anim_ease&quot;:&quot;ease&quot;}\" data-widget_type=\"text-editor.default\">\n\t\t\t\t\t\t\t\t\t<p>Indovina il rapper in meno di 10 tentativi, <strong>ogni tentativo scopri nuove informazioni<\/strong><\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-54b7bf63 elementor-hidden-mobile e-flex e-con-boxed wcf-starter-animations-none e-con e-parent\" data-id=\"54b7bf63\" 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-5f8cf7d5 elementor-widget elementor-widget-wcf--floating-elements\" data-id=\"5f8cf7d5\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"wcf--floating-elements.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"wcf--floating-elements\">\r\n\t\t\t                <div class=\"floating-element wcf-live-anim-wiggle elementor-repeater-item-77e55b9   \">\r\n\t\t\t\t\t<img decoding=\"async\" src=\"https:\/\/bulldogmusik.it\/wp-content\/uploads\/2026\/05\/Coppa.png\" alt=\"Coppa\" \/>\t\t\t\t<\/div>\r\n\t\t\t\t\t\t<\/div>\r\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 class=\"elementor-element elementor-element-363af42b elementor-hidden-mobile e-flex e-con-boxed wcf-starter-animations-none e-con e-parent\" data-id=\"363af42b\" 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-d385d9c elementor-widget__width-initial e-n-tabs-mobile elementor-widget elementor-widget-n-tabs\" data-id=\"d385d9c\" data-element_type=\"widget\" data-e-type=\"widget\" data-settings=\"{&quot;tabs_justify_horizontal&quot;:&quot;center&quot;,&quot;horizontal_scroll&quot;:&quot;disable&quot;}\" data-widget_type=\"nested-tabs.default\">\n\t\t\t\t\t\t\t<div class=\"e-n-tabs\" data-widget-number=\"221797788\" aria-label=\"Schede. Apri gli elementi con Invio o Spazio, chiudili con Esc e naviga con i tasti freccia.\">\n\t\t\t<div class=\"e-n-tabs-heading\" role=\"tablist\">\n\t\t\t\t\t<button id=\"maiuscolo\" data-tab-title-id=\"e-n-tab-title-2217977881\" class=\"e-n-tab-title\" aria-selected=\"true\" data-tab-index=\"1\" role=\"tab\" tabindex=\"0\" aria-controls=\"e-n-tab-content-2217977881\" style=\"--n-tabs-title-order: 1;\">\n\t\t\t\t\t\t<span class=\"e-n-tab-title-text\">\n\t\t\t\tGiornaliera\t\t\t<\/span>\n\t\t<\/button>\n\t\t\t\t<button id=\"tab-speciale\" data-tab-title-id=\"e-n-tab-title-2217977882\" class=\"e-n-tab-title\" aria-selected=\"false\" data-tab-index=\"2\" role=\"tab\" tabindex=\"-1\" aria-controls=\"e-n-tab-content-2217977882\" style=\"--n-tabs-title-order: 2;\">\n\t\t\t\t\t\t<span class=\"e-n-tab-title-text\">\n\t\t\t\tClassificata\t\t\t<\/span>\n\t\t<\/button>\n\t\t\t\t\t<\/div>\n\t\t\t<div class=\"e-n-tabs-content\">\n\t\t\t\t<div id=\"e-n-tab-content-2217977881\" role=\"tabpanel\" aria-labelledby=\"maiuscolo\" data-tab-index=\"1\" style=\"--n-tabs-title-order: 1;\" class=\"e-active elementor-element elementor-element-1a461935 e-con-full e-flex wcf-starter-animations-none e-con e-child\" data-id=\"1a461935\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t<div class=\"elementor-element elementor-element-427f49e7 e-grid e-con-boxed wcf-starter-animations-none e-con e-child\" data-id=\"427f49e7\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-63bfd945 elementor-widget__width-initial e-transform elementor-widget elementor-widget-html\" data-id=\"63bfd945\" data-element_type=\"widget\" data-e-type=\"widget\" data-settings=\"{&quot;_transform_translateX_effect&quot;:{&quot;unit&quot;:&quot;px&quot;,&quot;size&quot;:-4,&quot;sizes&quot;:[]},&quot;_transform_translateX_effect_tablet&quot;:{&quot;unit&quot;:&quot;px&quot;,&quot;size&quot;:&quot;&quot;,&quot;sizes&quot;:[]},&quot;_transform_translateX_effect_mobile&quot;:{&quot;unit&quot;:&quot;px&quot;,&quot;size&quot;:&quot;&quot;,&quot;sizes&quot;:[]},&quot;_transform_translateY_effect&quot;:{&quot;unit&quot;:&quot;px&quot;,&quot;size&quot;:&quot;&quot;,&quot;sizes&quot;:[]},&quot;_transform_translateY_effect_tablet&quot;:{&quot;unit&quot;:&quot;px&quot;,&quot;size&quot;:&quot;&quot;,&quot;sizes&quot;:[]},&quot;_transform_translateY_effect_mobile&quot;:{&quot;unit&quot;:&quot;px&quot;,&quot;size&quot;:&quot;&quot;,&quot;sizes&quot;:[]}}\" data-widget_type=\"html.default\">\n\t\t\t\t\t<!DOCTYPE html>\r\n<html lang=\"it\">\r\n<head>\r\n  <meta charset=\"UTF-8\">\r\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\r\n  <title>Bulldogle Demo<\/title>\r\n  <link rel=\"preconnect\" href=\"https:\/\/fonts.googleapis.com\">\r\n  <link rel=\"preconnect\" href=\"https:\/\/fonts.gstatic.com\" crossorigin>\r\n  <link href=\"https:\/\/fonts.googleapis.com\/css2?family=Instrument+Sans:wght@400;500;600;700;800;900&family=Space+Grotesk:wght@500;700&display=swap\" rel=\"stylesheet\">\r\n  <style>\r\n    :root {\r\n      --bg: #000;\r\n      --panel: #070707;\r\n      --panel-2: #0b0b0b;\r\n      --line: rgba(255, 255, 255, 0.08);\r\n      --line-strong: rgba(241, 108, 29, 0.28);\r\n      --line-faint: rgba(255, 255, 255, 0.05);\r\n      --white: #f7f4ef;\r\n      --copy: rgba(247, 244, 239, 0.76);\r\n      --copy-soft: rgba(247, 244, 239, 0.54);\r\n      --copy-faint: rgba(247, 244, 239, 0.34);\r\n      --accent: #f16c1d;\r\n      --ranked-accent: #952800;\r\n      --ranked-line-strong: rgba(149, 40, 0, 0.28);\r\n      --success: #7dc56a;\r\n      --warning: #f0b955;\r\n      --radius-lg: 18px;\r\n      --radius-md: 14px;\r\n      --ease: 220ms cubic-bezier(.2,.9,.2,1);\r\n    }\r\n\r\n    * {\r\n      box-sizing: border-box;\r\n    }\r\n\r\n    html,\r\n    body {\r\n      margin: 0;\r\n      min-height: 100%;\r\n      background: var(--bg);\r\n      color: var(--white);\r\n      font-family: \"Instrument Sans\", system-ui, sans-serif;\r\n      overflow-x: hidden;\r\n    }\r\n\r\n    button,\r\n    input,\r\n    iframe {\r\n      font: inherit;\r\n    }\r\n\r\n    .demo-app {\r\n      width: min(760px, calc(100vw - 20px));\r\n      margin: 0 auto;\r\n      padding: 18px 0 24px;\r\n    }\r\n\r\n    .app-shell {\r\n      position: relative;\r\n      isolation: isolate;\r\n      padding: 14px;\r\n      border: 1px solid var(--line);\r\n      border-radius: 22px;\r\n      background: linear-gradient(180deg, rgba(14, 14, 14, 0.98), rgba(7, 7, 7, 0.98));\r\n      overflow: visible;\r\n      box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.03);\r\n    }\r\n\r\n    .app-shell::after {\r\n      content: \"\";\r\n      position: absolute;\r\n      inset: 0;\r\n      border-radius: inherit;\r\n      background-image: url(\"data:image\/svg+xml,%3Csvg%20xmlns='http:\/\/www.w3.org\/2000\/svg'%20viewBox='0%200%20180%20180'%3E%3Cfilter%20id='n'%3E%3CfeTurbulence%20type='fractalNoise'%20baseFrequency='.9'%20numOctaves='3'%20stitchTiles='stitch'\/%3E%3CfeColorMatrix%20type='saturate'%20values='0'\/%3E%3CfeComponentTransfer%3E%3CfeFuncA%20type='table'%20tableValues='0%20.58'\/%3E%3C\/feComponentTransfer%3E%3C\/filter%3E%3Crect%20width='180'%20height='180'%20filter='url(%23n)'%20opacity='1'\/%3E%3C\/svg%3E\");\r\n      background-size: 180px 180px;\r\n      mix-blend-mode: overlay;\r\n      opacity: 0.1;\r\n      pointer-events: none;\r\n    }\r\n\r\n    .app-shell > * {\r\n      position: relative;\r\n      z-index: 1;\r\n    }\r\n\r\n    .topbar {\r\n      display: flex;\r\n      flex-direction: column;\r\n      align-items: center;\r\n      gap: 0;\r\n      padding: 10px 8px 14px;\r\n    }\r\n\r\n    .top-logo {\r\n      display: block;\r\n      width: min(320px, 58vw);\r\n      height: auto;\r\n    }\r\n\r\n    .shell {\r\n      margin-top: 0;\r\n      padding-top: 14px;\r\n      border-top: 1px solid var(--line);\r\n    }\r\n\r\n    .controls-shell {\r\n      margin-top: 0;\r\n      padding: 14px 0;\r\n      border-top: 1px solid var(--line);\r\n    }\r\n\r\n    .controls-inner {\r\n      display: grid;\r\n      grid-template-columns: repeat(3, minmax(0, 1fr));\r\n      gap: 8px;\r\n    }\r\n\r\n    .game-shell {\r\n      position: relative;\r\n      padding: 2px 0 6px;\r\n      overflow: visible;\r\n    }\r\n\r\n    .mode-tabs,\r\n    .top-actions {\r\n      display: flex;\r\n      gap: 8px;\r\n      flex-wrap: wrap;\r\n      align-items: center;\r\n    }\r\n\r\n    .mode-tabs,\r\n    .top-actions {\r\n      width: 100%;\r\n      justify-content: stretch;\r\n    }\r\n\r\n    .controls-inner .tab,\r\n    .controls-inner .ghost-button {\r\n      width: 100%;\r\n      min-width: 0;\r\n      min-height: 56px;\r\n      height: 56px;\r\n      padding: 0 22px;\r\n      border-radius: 12px;\r\n      font-size: 15px;\r\n      line-height: 1.1;\r\n      text-transform: uppercase;\r\n    }\r\n\r\n    .tab-ranked-mobile {\r\n      display: none;\r\n    }\r\n\r\n    .controls-inner .tab-ranked-mobile {\r\n      display: none !important;\r\n    }\r\n\r\n    .demo-app.is-ranked-mode .hide-when-ranked,\r\n    body.bulldogle-ranked-mode-active .hide-when-ranked,\r\n    html.bulldogle-ranked-mode-active .hide-when-ranked,\r\n    .demo-app.is-ranked-mode .hide.when.ranked,\r\n    body.bulldogle-ranked-mode-active .hide.when.ranked,\r\n    html.bulldogle-ranked-mode-active .hide.when.ranked {\r\n      display: none !important;\r\n    }\r\n\r\n    .show-when-ranked,\r\n    .show.when.ranked,\r\n    .show-when-ranked-flex,\r\n    .show.flex.when.ranked,\r\n    .show-when-ranked-grid,\r\n    .show.grid.when.ranked,\r\n    .show-when-ranked-inline {\r\n      display: none !important;\r\n    }\r\n\r\n    .demo-app.is-ranked-mode .show-when-ranked,\r\n    body.bulldogle-ranked-mode-active .show-when-ranked,\r\n    html.bulldogle-ranked-mode-active .show-when-ranked,\r\n    .demo-app.is-ranked-mode .show.when.ranked,\r\n    body.bulldogle-ranked-mode-active .show.when.ranked,\r\n    html.bulldogle-ranked-mode-active .show.when.ranked {\r\n      display: block !important;\r\n    }\r\n\r\n    .demo-app.is-ranked-mode .show-when-ranked-flex,\r\n    body.bulldogle-ranked-mode-active .show-when-ranked-flex,\r\n    html.bulldogle-ranked-mode-active .show-when-ranked-flex,\r\n    .demo-app.is-ranked-mode .show.flex.when.ranked,\r\n    body.bulldogle-ranked-mode-active .show.flex.when.ranked,\r\n    html.bulldogle-ranked-mode-active .show.flex.when.ranked {\r\n      display: flex !important;\r\n    }\r\n\r\n    .demo-app.is-ranked-mode .show-when-ranked-grid,\r\n    body.bulldogle-ranked-mode-active .show-when-ranked-grid,\r\n    html.bulldogle-ranked-mode-active .show-when-ranked-grid,\r\n    .demo-app.is-ranked-mode .show.grid.when.ranked,\r\n    body.bulldogle-ranked-mode-active .show.grid.when.ranked,\r\n    html.bulldogle-ranked-mode-active .show.grid.when.ranked {\r\n      display: grid !important;\r\n    }\r\n\r\n    .demo-app.is-ranked-mode .show-when-ranked-inline,\r\n    body.bulldogle-ranked-mode-active .show-when-ranked-inline,\r\n    html.bulldogle-ranked-mode-active .show-when-ranked-inline {\r\n      display: inline-flex !important;\r\n    }\r\n\r\n    .tab,\r\n    .ghost-button,\r\n    .button,\r\n    .secondary-button {\r\n      display: inline-flex;\r\n      align-items: center;\r\n      justify-content: center;\r\n      min-height: 32px;\r\n      padding: 0 13px;\r\n      border-radius: 999px;\r\n      border: 1px solid var(--line);\r\n      background: rgba(255, 255, 255, 0.03);\r\n      color: var(--white);\r\n      font-size: 11px;\r\n      font-weight: 700;\r\n      cursor: pointer;\r\n      transition: transform var(--ease), border-color var(--ease), background var(--ease), color var(--ease);\r\n    }\r\n\r\n    .tab.is-active,\r\n    .ghost-button.is-active {\r\n      border-color: var(--line-strong);\r\n      background: rgba(241, 108, 29, 0.12);\r\n    }\r\n\r\n    .demo-app.is-ranked-mode .tab-ranked-mobile.is-active,\r\n    .demo-app.is-ranked-mode .ghost-button.is-active {\r\n      border-color: var(--ranked-line-strong);\r\n      background: rgba(149, 40, 0, 0.12);\r\n    }\r\n\r\n    .button {\r\n      min-width: 152px;\r\n      min-height: 56px;\r\n      padding: 0 22px;\r\n      border-radius: 12px;\r\n      background: var(--accent);\r\n      border-color: var(--accent);\r\n      color: #111;\r\n      font-size: 15px;\r\n      font-weight: 700;\r\n      letter-spacing: 0;\r\n      text-transform: uppercase;\r\n      box-shadow: none;\r\n    }\r\n\r\n    .button:hover {\r\n      background: #fff;\r\n      border-color: #fff;\r\n      color: #111;\r\n    }\r\n\r\n    .secondary-button {\r\n      min-width: 152px;\r\n      min-height: 56px;\r\n      padding: 0 22px;\r\n      border-radius: 12px;\r\n      background: var(--accent);\r\n      border-color: var(--accent);\r\n      color: #111;\r\n      font-size: 15px;\r\n      font-weight: 700;\r\n      letter-spacing: 0;\r\n      text-transform: uppercase;\r\n      box-shadow: none;\r\n    }\r\n\r\n    .secondary-button:hover {\r\n      background: #fff;\r\n      border-color: #fff;\r\n      color: #111;\r\n    }\r\n\r\n    .streak-card.is-guest:hover {\r\n      background: #fff;\r\n      border-color: #fff;\r\n      color: #111;\r\n    }\r\n\r\n    .streak-card.is-guest:hover .streak-sub {\r\n      color: rgba(17, 17, 17, 0.74);\r\n    }\r\n\r\n    .tab:hover,\r\n    .ghost-button:hover,\r\n    .button:hover,\r\n    .secondary-button:hover,\r\n    .streak-card.is-guest:hover,\r\n    .suggestion:hover {\r\n      transform: translateY(-1px);\r\n    }\r\n\r\n    .help-panel {\r\n      max-height: 0;\r\n      overflow: hidden;\r\n      padding-bottom: 0;\r\n      border-bottom: 1px solid transparent;\r\n      transition: max-height 240ms ease, margin 240ms ease, padding-bottom 240ms ease, border-color 240ms ease;\r\n      margin: 0;\r\n    }\r\n\r\n    .help-panel.is-open {\r\n      max-height: 1200px;\r\n      padding-bottom: 12px;\r\n      border-bottom-color: var(--line);\r\n      margin: 0 0 12px;\r\n    }\r\n\r\n    .help-panel-mobile-slot {\r\n      display: none;\r\n    }\r\n\r\n    .help-grid {\r\n      display: grid;\r\n      grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));\r\n      gap: 10px;\r\n    }\r\n\r\n    .help-card {\r\n      min-height: 100%;\r\n      padding: 12px 13px;\r\n      border: 1px solid var(--line);\r\n      border-radius: 12px;\r\n      background: rgba(255, 255, 255, 0.03);\r\n    }\r\n\r\n    .help-card.is-legacy-hidden {\r\n      display: none;\r\n    }\r\n\r\n    .help-card strong {\r\n      display: block;\r\n      margin-bottom: 8px;\r\n      font-size: 13px;\r\n    }\r\n\r\n    .help-card span {\r\n      display: block;\r\n      color: var(--copy-soft);\r\n      font-size: 12px;\r\n      line-height: 1.45;\r\n    }\r\n\r\n    .ranked-mode-panel {\r\n      display: grid;\r\n      gap: 12px;\r\n    }\r\n\r\n    .ranked-mode-panel > .results-list,\r\n    .ranked-mode-panel > .message,\r\n    .ranked-mode-panel > .ranked-summary-panel {\r\n      width: 100%;\r\n      min-width: 0;\r\n      margin-left: 0;\r\n      margin-right: 0;\r\n      justify-self: stretch;\r\n    }\r\n\r\n    .ranked-mode-panel > .results-list {\r\n      margin-top: 6px;\r\n    }\r\n\r\n    .ranked-mode-panel.hidden {\r\n      display: none !important;\r\n    }\r\n\r\n    .ranked-meta-grid {\r\n      display: grid;\r\n      grid-template-columns: repeat(2, minmax(0, 1fr));\r\n      gap: 10px;\r\n      margin-bottom: 2px;\r\n    }\r\n\r\n    .ranked-meta-card {\r\n      min-height: 74px;\r\n      padding: 12px 14px;\r\n      border: 1px solid var(--line);\r\n      border-radius: 16px;\r\n      background: rgba(255, 255, 255, 0.03);\r\n      display: flex;\r\n      flex-direction: column;\r\n      justify-content: space-between;\r\n      gap: 8px;\r\n      text-align: left;\r\n    }\r\n\r\n    .ranked-meta-card.is-accent {\r\n      border-color: rgba(149, 40, 0, 0.24);\r\n      background: rgba(149, 40, 0, 0.08);\r\n    }\r\n\r\n    .ranked-meta-label {\r\n      display: block;\r\n      color: var(--copy-soft);\r\n      font-size: 11px;\r\n      font-weight: 800;\r\n      letter-spacing: 0.12em;\r\n      text-transform: uppercase;\r\n    }\r\n\r\n    .ranked-meta-value {\r\n      display: block;\r\n      font-family: \"Space Grotesk\", sans-serif;\r\n      font-size: clamp(24px, 3.2vw, 30px);\r\n      line-height: 1;\r\n      letter-spacing: -0.05em;\r\n    }\r\n\r\n    .ranked-summary-panel {\r\n      margin-top: 4px;\r\n      padding: 16px;\r\n      border: 1px solid rgba(149, 40, 0, 0.28);\r\n      border-radius: 18px;\r\n      background: rgba(149, 40, 0, 0.08);\r\n    }\r\n\r\n    .ranked-summary-panel.hidden {\r\n      display: none !important;\r\n    }\r\n\r\n    .ranked-summary-panel.is-record {\r\n      border-color: rgba(125, 197, 106, 0.32);\r\n      background: rgba(125, 197, 106, 0.08);\r\n    }\r\n\r\n    .ranked-summary-title {\r\n      margin: 0 0 10px;\r\n      color: var(--white);\r\n      font-family: \"Space Grotesk\", sans-serif;\r\n      font-size: clamp(22px, 4vw, 28px);\r\n      line-height: 1;\r\n      letter-spacing: -0.04em;\r\n      font-weight: 900;\r\n    }\r\n\r\n    .ranked-summary-lines {\r\n      display: grid;\r\n      gap: 5px;\r\n    }\r\n\r\n    .ranked-summary-line {\r\n      color: var(--white);\r\n      font-size: 14px;\r\n      line-height: 1.5;\r\n      font-weight: 600;\r\n    }\r\n\r\n    .ranked-summary-line strong {\r\n      font-weight: 800;\r\n    }\r\n\r\n    .demo-app.is-ranked-mode #mobileRankedGuessForm .button,\r\n    .demo-app.is-ranked-mode #mobileRankedGuessForm .secondary-button {\r\n      background: var(--ranked-accent);\r\n      border-color: var(--ranked-accent);\r\n      color: #111;\r\n    }\r\n\r\n    .input-grid {\r\n      display: grid;\r\n      grid-template-columns: 152px minmax(0, 1fr) 152px 152px;\r\n      gap: 10px;\r\n      align-items: stretch;\r\n      max-width: none;\r\n      margin: 0 auto;\r\n    }\r\n\r\n    .attempts-card {\r\n      display: flex;\r\n      align-items: center;\r\n      justify-content: center;\r\n      min-width: 152px;\r\n      padding: 0 22px;\r\n      border: 1px solid #fff;\r\n      border-radius: 12px;\r\n      background: #fff;\r\n      color: #111;\r\n      font-size: 15px;\r\n      font-weight: 700;\r\n      letter-spacing: 0;\r\n      text-transform: uppercase;\r\n      text-align: center;\r\n      white-space: nowrap;\r\n      box-shadow: none;\r\n    }\r\n\r\n    .button,\r\n    .secondary-button,\r\n    .attempts-card {\r\n      font-family: \"Instrument Sans\", system-ui, sans-serif;\r\n      font-size: 15px;\r\n      line-height: 1;\r\n      font-weight: 700;\r\n      letter-spacing: 0;\r\n      text-transform: uppercase;\r\n      font-variation-settings: \"wght\" 700;\r\n    }\r\n\r\n    .action-slot {\r\n      width: 152px;\r\n      min-width: 152px;\r\n      align-self: stretch;\r\n    }\r\n\r\n    .input-grid > .attempts-card,\r\n    .input-grid > .button,\r\n    .action-slot > .secondary-button,\r\n    .action-slot > .streak-card {\r\n      width: 100%;\r\n      min-width: 0;\r\n      min-height: 56px;\r\n      height: 56px;\r\n    }\r\n\r\n    .input-shell {\r\n      position: relative;\r\n      z-index: 5;\r\n    }\r\n\r\n    .input-label {\r\n      display: none;\r\n      margin: 0;\r\n      color: var(--white);\r\n      font-size: 15px;\r\n      font-weight: 700;\r\n      letter-spacing: -0.01em;\r\n      text-align: center;\r\n    }\r\n\r\n    .search-field {\r\n      width: 100%;\r\n      min-height: 56px;\r\n      padding: 0 16px;\r\n      border-radius: 12px;\r\n      border: 1px solid rgba(255, 255, 255, 0.1);\r\n      background: #101010;\r\n      color: var(--white);\r\n      font-size: 15px;\r\n      outline: none;\r\n      transition: border-color var(--ease), background var(--ease);\r\n    }\r\n\r\n    .search-field:focus {\r\n      border-color: rgba(255, 255, 255, 0.18);\r\n      background: #111;\r\n    }\r\n\r\n    .search-field::placeholder {\r\n      color: var(--copy-faint);\r\n    }\r\n\r\n    .search-field:disabled {\r\n      opacity: 0.5;\r\n      cursor: not-allowed;\r\n    }\r\n\r\n    .suggestions {\r\n      position: fixed;\r\n      top: 0;\r\n      left: 0;\r\n      width: 280px;\r\n      max-height: min(280px, calc(100dvh - 24px));\r\n      overflow-y: auto;\r\n      z-index: 2147483001;\r\n      display: none;\r\n      padding: 6px;\r\n      border: 1px solid var(--line);\r\n      border-radius: 14px;\r\n      background: rgba(9, 9, 9, 0.98);\r\n      box-shadow: 0 22px 50px rgba(0, 0, 0, 0.55);\r\n      backdrop-filter: blur(12px);\r\n      overscroll-behavior: contain;\r\n      -webkit-overflow-scrolling: touch;\r\n    }\r\n\r\n    .suggestion {\r\n      width: 100%;\r\n      display: flex;\r\n      justify-content: space-between;\r\n      gap: 8px;\r\n      padding: 11px 12px;\r\n      border: 0;\r\n      border-radius: 10px;\r\n      background: transparent;\r\n      color: var(--white);\r\n      text-align: left;\r\n      cursor: pointer;\r\n    }\r\n\r\n    .suggestion small {\r\n      color: var(--copy-faint);\r\n      font-size: 11px;\r\n    }\r\n\r\n    .input-grid > .attempts-card,\r\n    .input-grid > .button,\r\n    .input-grid > .action-slot {\r\n      align-self: stretch;\r\n      height: 56px;\r\n    }\r\n\r\n    .streak-card {\r\n      display: flex;\r\n      flex-direction: column;\r\n      align-items: center;\r\n      justify-content: center;\r\n      padding: 8px 14px;\r\n      border: 1px solid var(--accent);\r\n      border-radius: 12px;\r\n      background: var(--accent);\r\n      color: #111;\r\n      text-decoration: none;\r\n      box-shadow: none;\r\n    }\r\n\r\n    .streak-card:not(.is-guest) {\r\n      cursor: default;\r\n      pointer-events: none;\r\n    }\r\n\r\n    .streak-card:not(.is-guest):hover {\r\n      background: var(--accent);\r\n      border-color: var(--accent);\r\n      color: #111;\r\n      transform: none;\r\n    }\r\n\r\n    .streak-card:not(.is-guest):hover .streak-sub {\r\n      color: rgba(17, 17, 17, 0.74);\r\n    }\r\n\r\n    .streak-card.is-guest {\r\n      cursor: pointer;\r\n    }\r\n\r\n    .streak-main {\r\n      display: block;\r\n      font-size: 15px;\r\n      line-height: 1;\r\n      font-weight: 700;\r\n      letter-spacing: 0;\r\n      text-transform: uppercase;\r\n    }\r\n\r\n    .streak-sub {\r\n      display: block;\r\n      margin-top: 4px;\r\n      color: rgba(17, 17, 17, 0.74);\r\n      font-size: 9px;\r\n      line-height: 1.2;\r\n      font-weight: 700;\r\n      text-transform: none;\r\n      letter-spacing: 0;\r\n      text-align: center;\r\n    }\r\n\r\n    .message {\r\n      display: none;\r\n      width: 100%;\r\n      max-width: none;\r\n      margin: 12px 0 0;\r\n      padding: 10px 12px;\r\n      border-radius: 999px;\r\n      border: 1px solid var(--line);\r\n      background: rgba(255, 255, 255, 0.03);\r\n      color: var(--copy);\r\n      font-size: 13px;\r\n      line-height: 1.45;\r\n      text-align: center;\r\n    }\r\n\r\n    .message.is-visible {\r\n      display: block;\r\n    }\r\n\r\n    .message.is-success {\r\n      border-color: rgba(125, 197, 106, 0.36);\r\n      background: rgba(125, 197, 106, 0.1);\r\n      color: #daf2d3;\r\n    }\r\n\r\n    .message.is-error {\r\n      border-color: rgba(241, 108, 29, 0.32);\r\n      background: rgba(241, 108, 29, 0.1);\r\n      color: #ffd7b5;\r\n    }\r\n\r\n    .message.is-error-final {\r\n      border-color: rgba(241, 108, 29, 0.32);\r\n      background: rgba(241, 108, 29, 0.1);\r\n      color: #ffd7b5;\r\n    }\r\n\r\n    .results-list {\r\n      display: grid;\r\n      gap: 12px;\r\n      margin-top: 18px;\r\n      max-width: none;\r\n      margin-left: auto;\r\n      margin-right: auto;\r\n    }\r\n\r\n    .empty-state {\r\n      padding: 16px;\r\n      border: 1px dashed rgba(255, 255, 255, 0.15);\r\n      border-radius: 12px;\r\n      color: var(--copy-soft);\r\n      font-size: 13px;\r\n      line-height: 1.5;\r\n      text-align: center;\r\n    }\r\n\r\n    .guess-card {\r\n      padding: 18px;\r\n      border: 1px solid var(--line-faint);\r\n      border-radius: 22px;\r\n      background: linear-gradient(180deg, rgba(14, 14, 14, 0.96), rgba(10, 10, 10, 0.96));\r\n      box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.03);\r\n      text-align: left;\r\n    }\r\n\r\n    .guess-card.is-solved {\r\n      border-color: rgba(125, 197, 106, 0.34);\r\n    }\r\n\r\n    .guess-card.is-answer {\r\n      border-color: rgba(125, 197, 106, 0.5);\r\n    }\r\n\r\n    .guess-card.is-hint {\r\n      border-color: rgba(240, 185, 85, 0.28);\r\n    }\r\n\r\n    .guess-top {\r\n      display: flex;\r\n      align-items: center;\r\n      gap: 18px;\r\n      margin-bottom: 18px;\r\n    }\r\n\r\n    .guess-cover {\r\n      position: relative;\r\n      flex: 0 0 96px;\r\n      width: 96px;\r\n      height: 96px;\r\n      border: 1px solid rgba(255, 255, 255, 0.12);\r\n      border-radius: 50%;\r\n      background:\r\n        radial-gradient(circle at 32% 28%, rgba(241, 108, 29, 0.34), transparent 44%),\r\n        linear-gradient(145deg, rgba(241, 108, 29, 0.16), rgba(255, 255, 255, 0.03));\r\n      overflow: hidden;\r\n      box-shadow: 0 18px 34px rgba(0, 0, 0, 0.34);\r\n    }\r\n\r\n    .guess-cover img {\r\n      width: 100%;\r\n      height: 100%;\r\n      object-fit: cover;\r\n      display: block;\r\n    }\r\n\r\n    .guess-cover-fallback {\r\n      width: 100%;\r\n      height: 100%;\r\n      display: flex;\r\n      align-items: center;\r\n      justify-content: center;\r\n      color: var(--white);\r\n      font-family: \"Space Grotesk\", sans-serif;\r\n      font-size: 28px;\r\n      font-weight: 700;\r\n      letter-spacing: -0.04em;\r\n      text-transform: uppercase;\r\n    }\r\n\r\n    .guess-copy {\r\n      min-width: 0;\r\n      display: flex;\r\n      flex-direction: column;\r\n      align-items: flex-start;\r\n      gap: 10px;\r\n    }\r\n\r\n    .guess-badge {\r\n      display: inline-flex;\r\n      align-items: center;\r\n      justify-content: center;\r\n      min-height: 28px;\r\n      padding: 0 12px;\r\n      border: 1px solid var(--line);\r\n      border-radius: 999px;\r\n      color: var(--copy-soft);\r\n      font-size: 11px;\r\n      font-weight: 700;\r\n      letter-spacing: -0.01em;\r\n    }\r\n\r\n    .guess-name {\r\n      margin: 0;\r\n      font-family: \"Space Grotesk\", sans-serif;\r\n      font-size: clamp(28px, 4vw, 34px);\r\n      line-height: 1;\r\n      letter-spacing: -0.04em;\r\n    }\r\n\r\n    .guess-sub {\r\n      margin: -2px 0 0;\r\n      color: var(--copy-soft);\r\n      font-size: 12px;\r\n      line-height: 1.45;\r\n    }\r\n\r\n    .traits {\r\n      display: grid;\r\n      grid-template-columns: repeat(5, minmax(0, 1fr));\r\n      gap: 8px;\r\n    }\r\n\r\n    .trait {\r\n      min-height: 98px;\r\n      padding: 12px 10px;\r\n      border: 1px solid rgba(255, 255, 255, 0.08);\r\n      border-radius: 14px;\r\n      background: rgba(255, 255, 255, 0.04);\r\n      display: flex;\r\n      flex-direction: column;\r\n      justify-content: space-between;\r\n      align-items: center;\r\n      text-align: center;\r\n    }\r\n\r\n    .trait.is-correct {\r\n      border-color: rgba(84, 184, 106, 0.68);\r\n      background: #46b065;\r\n      color: #fff;\r\n    }\r\n\r\n    .trait.is-close {\r\n      border-color: rgba(233, 181, 76, 0.72);\r\n      background: #d2a43a;\r\n      color: #fff;\r\n    }\r\n\r\n    .trait-label {\r\n      display: block;\r\n      margin: 0;\r\n      color: inherit;\r\n      opacity: 0.92;\r\n      font-size: 12px;\r\n      font-weight: 700;\r\n      letter-spacing: -0.02em;\r\n    }\r\n\r\n    .trait-value {\r\n      display: inline-flex;\r\n      flex-wrap: wrap;\r\n      align-items: center;\r\n      justify-content: center;\r\n      gap: 5px;\r\n      font-size: clamp(15px, 1.8vw, 18px);\r\n      line-height: 1.06;\r\n      font-weight: 800;\r\n      letter-spacing: -0.03em;\r\n      word-break: break-word;\r\n    }\r\n\r\n    .trait-value-text {\r\n      display: inline;\r\n    }\r\n\r\n    .trait-arrow {\r\n      display: inline-flex;\r\n      align-items: center;\r\n      justify-content: center;\r\n      font-family: \"Segoe UI Symbol\", \"Noto Sans Symbols 2\", \"Arial Unicode MS\", sans-serif;\r\n      font-size: 0.95em;\r\n      line-height: 1;\r\n      letter-spacing: 0;\r\n      font-weight: 700;\r\n      white-space: nowrap;\r\n    }\r\n\r\n    .trait-suffix {\r\n      display: inline;\r\n      font-size: 0.76em;\r\n      line-height: 1;\r\n      font-weight: 800;\r\n      letter-spacing: 0;\r\n      white-space: nowrap;\r\n    }\r\n\r\n    .guess-spotify {\r\n      margin-top: 12px;\r\n      padding-top: 12px;\r\n      border-top: 1px solid rgba(255, 255, 255, 0.06);\r\n    }\r\n\r\n    .guess-spotify iframe {\r\n      width: 100%;\r\n      min-height: 152px;\r\n      border: 0;\r\n      border-radius: 14px;\r\n      background: #0b0b0b;\r\n      display: block;\r\n    }\r\n\r\n    .guess-tip {\r\n      margin: 12px 0 0;\r\n      padding-top: 12px;\r\n      border-top: 1px solid rgba(255, 255, 255, 0.06);\r\n      color: var(--white);\r\n      font-size: 15px;\r\n      line-height: 1.6;\r\n      font-weight: 500;\r\n    }\r\n\r\n    .hidden {\r\n      display: none !important;\r\n    }\r\n\r\n    @media (max-width: 720px) {\r\n      .demo-app {\r\n        width: 100%;\r\n        max-width: 100%;\r\n        padding: max(6px, env(safe-area-inset-top, 0px)) 4px calc(10px + env(safe-area-inset-bottom, 0px));\r\n      }\r\n\r\n      .app-shell {\r\n        display: flex;\r\n        flex-direction: column;\r\n        padding: 8px 6px 10px;\r\n        border: 0;\r\n        border-radius: 0;\r\n        background: transparent;\r\n        box-shadow: none;\r\n      }\r\n\r\n      .app-shell::after {\r\n        display: none;\r\n      }\r\n\r\n      .controls-shell {\r\n        order: 1;\r\n        position: relative;\r\n        border-top: 0;\r\n        border-bottom: 1px solid var(--line);\r\n        padding-bottom: 20px;\r\n      }\r\n\r\n      .controls-shell::after {\r\n        content: \"Gioca\";\r\n        position: absolute;\r\n        left: 50%;\r\n        bottom: -11px;\r\n        transform: translateX(-50%) translateY(-2px);\r\n        padding: 0 14px;\r\n        background: var(--bg);\r\n        color: #9E9E9E;\r\n        font-size: 15px;\r\n        line-height: 1;\r\n      }\r\n\r\n      .topbar {\r\n        order: 2;\r\n      }\r\n\r\n      .shell {\r\n        order: 3;\r\n        border-top: 0;\r\n      }\r\n\r\n      .top-logo {\r\n        width: min(260px, 66vw);\r\n      }\r\n\r\n      .topbar {\r\n        padding: 12px 4px 4px;\r\n      }\r\n\r\n      .controls-shell,\r\n      .shell {\r\n        padding-top: 10px;\r\n      }\r\n\r\n      .controls-inner .tab,\r\n      .controls-inner .ghost-button {\r\n        min-height: 40px;\r\n        padding: 0 10px;\r\n        font-size: 12px;\r\n      }\r\n\r\n      .tab-ranked-mobile {\r\n        display: inline-flex;\r\n      }\r\n\r\n      .controls-inner .tab-ranked-mobile {\r\n        display: inline-flex !important;\r\n        width: 100%;\r\n      }\r\n\r\n      .help-panel-mobile-slot {\r\n        display: block;\r\n      }\r\n\r\n      .controls-shell .help-panel.is-open {\r\n        margin: 10px 0 0;\r\n        padding-bottom: 0;\r\n        border-bottom-color: transparent;\r\n      }\r\n\r\n      .input-grid {\r\n        grid-template-columns: repeat(2, minmax(0, 1fr));\r\n        gap: 8px;\r\n        width: 100%;\r\n      }\r\n\r\n      .attempts-card {\r\n        order: 1;\r\n        min-width: 0;\r\n        min-height: 48px;\r\n        height: 48px;\r\n        padding: 0 10px;\r\n        font-size: 13px;\r\n      }\r\n\r\n      .action-slot {\r\n        order: 2;\r\n        width: auto;\r\n        min-width: 0;\r\n      }\r\n\r\n      .input-shell {\r\n        order: 3;\r\n        grid-column: 1 \/ -1;\r\n        min-width: 0;\r\n        padding: 0;\r\n        border: 0;\r\n        border-radius: 0;\r\n        background: #0b0b0b;\r\n      }\r\n\r\n      .input-grid > .button {\r\n        order: 4;\r\n        grid-column: 1 \/ -1;\r\n      }\r\n\r\n      .input-grid > .attempts-card,\r\n      .input-grid > .button,\r\n      .action-slot > .secondary-button,\r\n      .action-slot > .streak-card,\r\n      .input-grid > .action-slot {\r\n        width: 100%;\r\n        min-width: 0;\r\n        min-height: 48px;\r\n        height: 48px;\r\n      }\r\n\r\n      .button,\r\n      .secondary-button,\r\n      .streak-card,\r\n      .attempts-card,\r\n      .action-slot {\r\n        min-width: 0;\r\n      }\r\n\r\n      .search-field {\r\n        min-height: 48px;\r\n        padding: 0 14px;\r\n        border: 1px solid rgba(255, 255, 255, 0.14);\r\n        border-radius: 12px;\r\n        background: #0b0b0b;\r\n        font-size: 16px;\r\n      }\r\n\r\n      .suggestion {\r\n        min-height: 48px;\r\n        padding: 13px 12px;\r\n      }\r\n\r\n      .help-grid {\r\n        grid-template-columns: 1fr;\r\n      }\r\n\r\n      .help-card span {\r\n        font-size: 13px;\r\n        line-height: 1.5;\r\n      }\r\n\r\n      .ranked-meta-grid {\r\n        gap: 8px;\r\n      }\r\n\r\n      .ranked-meta-card {\r\n        min-height: 62px;\r\n        padding: 10px 11px;\r\n      }\r\n\r\n      .ranked-meta-value {\r\n        font-size: clamp(18px, 5vw, 24px);\r\n      }\r\n\r\n      .traits {\r\n        grid-template-columns: repeat(2, minmax(0, 1fr));\r\n        gap: 6px;\r\n      }\r\n\r\n      .top-actions,\r\n      .guess-top {\r\n        flex-direction: column;\r\n        align-items: center;\r\n        justify-content: center;\r\n      }\r\n\r\n      .guess-copy {\r\n        align-items: center;\r\n        text-align: center;\r\n      }\r\n\r\n      .guess-card {\r\n        padding: 12px;\r\n        border-radius: 16px;\r\n      }\r\n\r\n      .guess-top {\r\n        gap: 10px;\r\n        margin-bottom: 10px;\r\n      }\r\n\r\n      .guess-cover {\r\n        flex-basis: 72px;\r\n        width: 72px;\r\n        height: 72px;\r\n      }\r\n\r\n      .guess-name {\r\n        font-size: clamp(20px, 7vw, 26px);\r\n      }\r\n\r\n      .trait {\r\n        min-height: 74px;\r\n        padding: 8px 7px;\r\n      }\r\n\r\n      .trait:nth-child(5) {\r\n        grid-column: 1 \/ -1;\r\n      }\r\n\r\n      .trait-label {\r\n        font-size: 10px;\r\n      }\r\n\r\n      .trait-value {\r\n        font-size: clamp(12px, 3.9vw, 15px);\r\n      }\r\n\r\n      .message {\r\n        margin-top: 10px;\r\n        padding: 9px 11px;\r\n        font-size: 13px;\r\n      }\r\n\r\n      .controls-inner {\r\n        grid-template-columns: repeat(2, minmax(0, 1fr));\r\n      }\r\n    }\r\n\r\n    @media (max-width: 520px) {\r\n      .demo-app {\r\n        padding-inline: 3px;\r\n      }\r\n\r\n      .top-logo {\r\n        width: min(232px, 64vw);\r\n      }\r\n\r\n      .controls-shell,\r\n      .shell {\r\n        padding-top: 8px;\r\n      }\r\n\r\n      .guess-card {\r\n        padding: 11px;\r\n      }\r\n\r\n      .trait {\r\n        min-height: 70px;\r\n      }\r\n\r\n      .guess-badge {\r\n        min-height: 24px;\r\n        padding: 0 10px;\r\n        font-size: 10px;\r\n      }\r\n\r\n      .guess-sub {\r\n        font-size: 11px;\r\n      }\r\n\r\n      .guess-spotify {\r\n        margin-top: 10px;\r\n        padding-top: 10px;\r\n      }\r\n\r\n      .guess-spotify iframe {\r\n        min-height: 152px;\r\n      }\r\n\r\n      .guess-tip {\r\n        margin-top: 10px;\r\n        padding-top: 10px;\r\n        font-size: 13px;\r\n      }\r\n\r\n      .controls-inner {\r\n        grid-template-columns: 1fr;\r\n      }\r\n\r\n      .controls-inner .tab-ranked-mobile {\r\n        display: inline-flex !important;\r\n        width: 100%;\r\n      }\r\n\r\n      .ranked-meta-grid {\r\n        grid-template-columns: repeat(2, minmax(0, 1fr));\r\n      }\r\n    }\r\n\r\n    @media (max-width: 400px) {\r\n      .demo-app {\r\n        padding-inline: 2px;\r\n      }\r\n\r\n      .top-logo {\r\n        width: min(214px, 62vw);\r\n      }\r\n\r\n      .attempts-card,\r\n      .button,\r\n      .secondary-button,\r\n      .streak-main {\r\n        font-size: 12px;\r\n      }\r\n\r\n      .streak-sub {\r\n        font-size: 8px;\r\n      }\r\n\r\n      .trait {\r\n        min-height: 66px;\r\n        padding: 8px 6px;\r\n      }\r\n\r\n      .trait-value {\r\n        font-size: 12px;\r\n      }\r\n    }\r\n\r\n    @media (hover: none), (pointer: coarse) {\r\n      .tab:hover,\r\n      .ghost-button:hover,\r\n      .button:hover,\r\n      .secondary-button:hover,\r\n      .streak-card.is-guest:hover,\r\n      .suggestion:hover {\r\n        transform: none;\r\n      }\r\n\r\n      .button:hover,\r\n      .secondary-button:hover {\r\n        background: var(--accent);\r\n        border-color: var(--accent);\r\n        color: #111;\r\n      }\r\n\r\n      .demo-app.is-ranked-mode #mobileRankedGuessForm .button:hover,\r\n      .demo-app.is-ranked-mode #mobileRankedGuessForm .secondary-button:hover {\r\n        background: var(--ranked-accent);\r\n        border-color: var(--ranked-accent);\r\n        color: #111;\r\n      }\r\n\r\n      .streak-card.is-guest:hover {\r\n        background: var(--accent);\r\n        border-color: var(--accent);\r\n        color: #111;\r\n      }\r\n\r\n      .streak-card.is-guest:hover .streak-sub {\r\n        color: rgba(17, 17, 17, 0.74);\r\n      }\r\n\r\n      .suggestion:hover {\r\n        background: transparent;\r\n      }\r\n\r\n      .button:active,\r\n      .secondary-button:active,\r\n      .streak-card.is-guest:active,\r\n      .tab:active,\r\n      .ghost-button:active,\r\n      .suggestion:active {\r\n        transform: scale(0.99);\r\n      }\r\n    }\r\n\r\n    .demo-app button,\r\n    .demo-app button *,\r\n    .demo-app .attempts-card,\r\n    .demo-app .attempts-card *,\r\n    .demo-app .classic-attempts-badge,\r\n    .demo-app .classic-attempts-badge *,\r\n    .demo-app .classic-streak-badge,\r\n    .demo-app .classic-streak-badge *,\r\n    .demo-app .streak-card,\r\n    .demo-app .streak-card *,\r\n    .demo-app .guess-name,\r\n    .demo-app .guess-name *,\r\n    .demo-app .artist-name,\r\n    .demo-app .artist-name *,\r\n    .demo-app .result-name,\r\n    .demo-app .result-name *,\r\n    .demo-app .board-row .name,\r\n    .demo-app .board-row .name * {\r\n      font-family: Verdana, Geneva, sans-serif !important;\r\n      font-weight: 900 !important;\r\n      -webkit-text-stroke: 0.18px currentColor;\r\n      text-shadow: 0.18px 0 currentColor;\r\n    }\r\n\r\n    .demo-app .controls-inner .tab,\r\n    .demo-app .controls-inner .ghost-button {\r\n      min-height: 56px !important;\r\n      height: 56px !important;\r\n      padding: 0 22px !important;\r\n      border-radius: 12px !important;\r\n      font-size: 15px !important;\r\n      line-height: 1.1 !important;\r\n      text-transform: uppercase !important;\r\n    }\r\n\r\n    @media (max-width: 720px) {\r\n      .demo-app .top-logo {\r\n        margin-top: 14px !important;\r\n      }\r\n\r\n      .demo-app .controls-inner {\r\n        margin-bottom: 18px !important;\r\n      }\r\n    }\r\n\r\n  <\/style>\r\n<\/head>\r\n<body>\r\n  <div class=\"demo-app\">\r\n    <div class=\"app-shell\">\r\n      <header class=\"topbar\">\r\n        <img decoding=\"async\" class=\"top-logo\" src=\"https:\/\/bulldogmusik.it\/wp-content\/uploads\/2026\/05\/Bulldogle-Classico-New.png\" alt=\"Bulldogle Classico\">\r\n      <\/header>\r\n\r\n      <section class=\"controls-shell\" aria-label=\"Controlli Bulldogle\">\r\n        <div class=\"controls-inner\">\r\n          <button class=\"tab is-active\" data-mode=\"classic\" type=\"button\">DAILY<\/button>\r\n          <button class=\"tab\" data-mode=\"practice\" type=\"button\">ALLENAMENTO<\/button>\r\n          <button id=\"rankedModeButton\" class=\"tab tab-ranked-mobile\" type=\"button\">CLASSIFICATA<\/button>\r\n          <button id=\"helpToggle\" class=\"ghost-button\" type=\"button\">COME SI GIOCA<\/button>\r\n        <\/div>\r\n        <div id=\"helpPanelMobileSlot\" class=\"help-panel-mobile-slot\"><\/div>\r\n      <\/section>\r\n\r\n       <main class=\"shell\">\r\n        <section class=\"game-shell\">\r\n          <section id=\"helpPanel\" class=\"help-panel\" aria-hidden=\"true\">\r\n            <div class=\"help-grid\">\r\n                <div class=\"help-card\">\r\n                  <strong>Colori<\/strong>\r\n                  <span>\ud83d\udfe2 = corretto. <br>\r\n \ud83d\udfe1 = vicino.<br>\r\n \u26aa = errato.<\/span>\r\n                <\/div>\r\n                <div class=\"help-card\">\r\n                  <strong>Citta<\/strong>\r\n                  <span>\ud83d\udfe1 se sei nella stessa regione. <br>\r\nSe sbagli, la freccia ti dice dove cercare.<\/span>\r\n                <\/div>\r\n                <div class=\"help-card is-legacy-hidden\">\r\n                  <strong>Estero<\/strong>\r\n                  <span>\ud83c\udf0d significa che l'artista corretto \u00e8 nato fuori dall'Italia.<br>\r\n \ud83c\uddee\ud83c\uddf9 significa che hai provato un artista estero ma quello corretto \u00e8 italiano.<\/span>\r\n                <\/div>\r\n                <div class=\"help-card\">\r\n                  <strong>Popolarita<\/strong>\r\n                  <span>Scala: underground, emergente, riconosciuto, mainstream, icona. <br>\r\n\ud83d\udfe1 = un solo livello di distanza.<\/span>\r\n                <\/div>\r\n                <div class=\"help-card is-legacy-hidden\">\r\n                  <strong>Frecce<\/strong>\r\n                  <span>\u2191 indica che l'artista corretto \u00e8 piu in alto nella scala o piu avanti nel debutto. <br>\r\n \u2193 indica che \u00e8 piu in basso.<\/span>\r\n                <\/div>\r\n                <div class=\"help-card\">\r\n                  <strong>Debutto<\/strong>\r\n                  <span>\ud83d\udfe1 se la differenza \u00e8 sotto i 5 anni.<\/span>\r\n                <\/div>\r\n                <div class=\"help-card\">\r\n                  <strong>Estero<\/strong>\r\n                  <span>&rarr; \ud83c\uddee\ud83c\uddf9: hai provato un artista estero ma il target \u00e8 italiano. <br>\r\n &rarr;\ud83c\udf0d: il target \u00e8 nato fuori dall'Italia. <br><\/span>\r\n                <\/div>\r\n                <div class=\"help-card\">\r\n                  <strong>Frecce<\/strong>\r\n                  <span>&uarr; vuol dire piu in alto o piu avanti. <br>\r\n &darr; vuol dire piu in basso o piu indietro.<\/span>\r\n                <\/div>\r\n            <\/div>\r\n          <\/section>\r\n\r\n          <section id=\"standardGamePanel\" class=\"game-panel\">\r\n            <form id=\"guessForm\" class=\"input-grid\" autocomplete=\"off\">\r\n              <div id=\"attemptsCard\" class=\"attempts-card\" aria-live=\"polite\">10 TENTATIVI<\/div>\r\n\r\n              <div class=\"input-shell\">\r\n                <label id=\"inputLabel\" class=\"input-label\" for=\"artistInput\">inserisci un artista<\/label>\r\n                <input id=\"artistInput\" class=\"search-field\" type=\"text\" placeholder=\"inserisci un artista\" aria-describedby=\"gameMsg\">\r\n                <div id=\"suggestions\" class=\"suggestions\" role=\"listbox\" aria-label=\"Suggerimenti artisti\"><\/div>\r\n              <\/div>\r\n\r\n              <button id=\"submitButton\" class=\"button\" type=\"submit\">PROVA<\/button>\r\n              <div class=\"action-slot\">\r\n                <button id=\"modeActionButton\" class=\"secondary-button hidden\" type=\"button\">NUOVO<\/button>\r\n                <a id=\"dailyStreakCard\" class=\"streak-card hidden is-guest\" href=\"https:\/\/bulldogmusik.it\/account-login\/\" aria-label=\"Accedi per salvare la streak\">\r\n                  <span id=\"dailyStreakMain\" class=\"streak-main\">STREAK<\/span>\r\n                  <span id=\"dailyStreakSub\" class=\"streak-sub\">Accedi per salvarla<\/span>\r\n                <\/a>\r\n              <\/div>\r\n            <\/form>\r\n\r\n            <div id=\"gameMsg\" class=\"message\" aria-live=\"polite\"><\/div>\r\n\r\n            <div id=\"resultsList\" class=\"results-list\">\r\n              <div class=\"empty-state\">Nessun tentativo ancora.<\/div>\r\n            <\/div>\r\n          <\/section>\r\n\r\n          <section id=\"mobileRankedGamePanel\" class=\"ranked-mode-panel hidden\">\r\n            <section id=\"mobileRankedHelpPanel\" class=\"help-panel\" aria-hidden=\"true\">\r\n              <div class=\"help-grid\">\r\n                <div class=\"help-card\">\r\n                  <strong>Timer<\/strong>\r\n                  <span>Hai 3 minuti per fare il punteggio piu alto possibile.<\/span>\r\n                <\/div>\r\n                <div class=\"help-card\">\r\n                  <strong>Punti<\/strong>\r\n                  <span>Ogni artista indovinato vale 1 punto e aggiunge 15 secondi.<\/span>\r\n                <\/div>\r\n                <div class=\"help-card\">\r\n                  <strong>Skip<\/strong>\r\n                  <span>Puoi skippare l'artista corrente, ma perdi 15 secondi.<\/span>\r\n                <\/div>\r\n                <div class=\"help-card\">\r\n                  <strong>Tentativi<\/strong>\r\n                  <span>Hai 10 tentativi per artista. Se li finisci, passi al successivo.<\/span>\r\n                <\/div>\r\n                <div class=\"help-card\">\r\n                  <strong>Indizi<\/strong>\r\n                  <span>Verde = corretto. Giallo = vicino. Le frecce indicano la direzione giusta.<\/span>\r\n                <\/div>\r\n                <div class=\"help-card\">\r\n                  <strong>Classificata<\/strong>\r\n                  <span>Il tuo miglior punteggio viene salvato nella classifica mensile della ranked.<\/span>\r\n                <\/div>\r\n              <\/div>\r\n            <\/section>\r\n\r\n            <section class=\"ranked-meta-grid\" aria-label=\"Statistiche Ranked\">\r\n              <article class=\"ranked-meta-card is-accent\">\r\n                <span class=\"ranked-meta-label\">Tempo<\/span>\r\n                <strong id=\"mobileRankedTimerValue\" class=\"ranked-meta-value\">3:00<\/strong>\r\n              <\/article>\r\n              <article class=\"ranked-meta-card\">\r\n                <span class=\"ranked-meta-label\">Punti<\/span>\r\n                <strong id=\"mobileRankedScoreValue\" class=\"ranked-meta-value\">0<\/strong>\r\n              <\/article>\r\n            <\/section>\r\n\r\n            <form id=\"mobileRankedGuessForm\" class=\"input-grid\" autocomplete=\"off\">\r\n              <div id=\"mobileRankedAttemptsCard\" class=\"attempts-card\" aria-live=\"polite\">10 TENTATIVI<\/div>\r\n\r\n              <div class=\"input-shell\">\r\n                <input id=\"mobileRankedArtistInput\" class=\"search-field\" type=\"text\" placeholder=\"inserisci un artista\" aria-describedby=\"mobileRankedGameMsg\">\r\n                <div id=\"mobileRankedSuggestions\" class=\"suggestions\" role=\"listbox\" aria-label=\"Suggerimenti artisti ranked\"><\/div>\r\n              <\/div>\r\n\r\n              <button id=\"mobileRankedSubmitButton\" class=\"button\" type=\"submit\">PROVA<\/button>\r\n\r\n              <div class=\"action-slot\">\r\n                <button id=\"mobileRankedSideActionButton\" class=\"secondary-button\" type=\"button\">INIZIA<\/button>\r\n              <\/div>\r\n            <\/form>\r\n\r\n            <section id=\"mobileRankedSummaryPanel\" class=\"ranked-summary-panel hidden\" aria-live=\"polite\">\r\n              <h3 id=\"mobileRankedSummaryTitle\" class=\"ranked-summary-title\">Partita conclusa<\/h3>\r\n              <div id=\"mobileRankedSummaryLines\" class=\"ranked-summary-lines\"><\/div>\r\n            <\/section>\r\n\r\n            <div id=\"mobileRankedGameMsg\" class=\"message\" aria-live=\"polite\"><\/div>\r\n\r\n            <div id=\"mobileRankedResultsList\" class=\"results-list\">\r\n              <div class=\"empty-state\">ACCEDI per giocare.<\/div>\r\n            <\/div>\r\n          <\/section>\r\n        <\/section>\r\n      <\/main>\r\n    <\/div>\r\n  <\/div>\r\n\r\n  <script>\r\n    (async function () {\r\n      const bootstrapScript = document.currentScript;\r\n\r\n      async function loadScriptSource(src) {\r\n        return new Promise((resolve) => {\r\n          const existing = Array.from(document.querySelectorAll(\"script[src]\")).find((node) => node.src === src);\r\n          if (existing) {\r\n            if (Array.isArray(window.bulldogleArtists) && window.bulldogleArtists.length) {\r\n              resolve(true);\r\n              return;\r\n            }\r\n          }\r\n\r\n          const script = document.createElement(\"script\");\r\n          script.src = src;\r\n          script.async = false;\r\n          script.onload = () => resolve(true);\r\n          script.onerror = () => resolve(false);\r\n          document.head.appendChild(script);\r\n        });\r\n      }\r\n\r\n      async function ensureArtistsLoaded() {\r\n        if (Array.isArray(window.bulldogleArtists) && window.bulldogleArtists.length) {\r\n          return window.bulldogleArtists;\r\n        }\r\n\r\n        const sources = [\r\n          \".\/artists.js\",\r\n          \"artists.js\",\r\n          \"\/bulldogle\/artists.js?v=65\"\r\n        ];\r\n\r\n        if (window.location && \/^https?:\/i.test(window.location.protocol) && window.location.origin) {\r\n          sources.push(window.location.origin + \"\/bulldogle\/artists.js?v=65\");\r\n        }\r\n\r\n        sources.push(\"https:\/\/bulldogmusik.it\/bulldogle\/artists.js?v=65\");\r\n\r\n        for (const source of sources) {\r\n          const loaded = await loadScriptSource(source);\r\n          if (loaded && Array.isArray(window.bulldogleArtists) && window.bulldogleArtists.length) {\r\n            return window.bulldogleArtists;\r\n          }\r\n        }\r\n\r\n        return [];\r\n      }\r\n\r\n      const artistsSource = await ensureArtistsLoaded();\r\n      const ARROWS = {\r\n        up: String.fromCharCode(8593),\r\n        down: String.fromCharCode(8595),\r\n        left: String.fromCharCode(8592),\r\n        right: String.fromCharCode(8594)\r\n      };\r\n\r\n      const regionCoords = {\r\n        \"Abruzzo\": { lat: 42.3, lon: 13.9 },\r\n        \"Basilicata\": { lat: 40.6, lon: 15.8 },\r\n        \"Calabria\": { lat: 38.9, lon: 16.6 },\r\n        \"Campania\": { lat: 40.8, lon: 14.3 },\r\n        \"Emilia-Romagna\": { lat: 44.5, lon: 11.3 },\r\n        \"Friuli-Venezia Giulia\": { lat: 46.1, lon: 13.1 },\r\n        \"Lazio\": { lat: 41.9, lon: 12.5 },\r\n        \"Liguria\": { lat: 44.4, lon: 8.9 },\r\n        \"Lombardia\": { lat: 45.5, lon: 9.2 },\r\n        \"Marche\": { lat: 43.6, lon: 13.5 },\r\n        \"Molise\": { lat: 41.6, lon: 14.6 },\r\n        \"Piemonte\": { lat: 45.1, lon: 7.7 },\r\n        \"Puglia\": { lat: 41.1, lon: 16.9 },\r\n        \"Sardegna\": { lat: 40.1, lon: 9.0 },\r\n        \"Sicilia\": { lat: 37.6, lon: 14.0 },\r\n        \"Toscana\": { lat: 43.8, lon: 11.2 },\r\n        \"Trentino-Alto Adige\": { lat: 46.5, lon: 11.3 },\r\n        \"Umbria\": { lat: 43.1, lon: 12.4 },\r\n        \"Valle d'Aosta\": { lat: 45.7, lon: 7.3 },\r\n        \"Veneto\": { lat: 45.4, lon: 12.3 },\r\n        \"Estero\": null\r\n      };\r\n\r\n      const classicConfig = window.bulldogleClassicConfig || {};\r\n      const rankedConfig = window.bulldogleRankedConfig || {};\r\n      const guestStreakLoginUrl = \"https:\/\/bulldogmusik.it\/account-login\/\";\r\n      const popularityLevels = [\"underground\", \"emergente\", \"riconosciuto\", \"mainstream\", \"icona\"];\r\n      const monthlyListenerBuckets = [\r\n        { level: \"underground\", min: 0 },\r\n        { level: \"emergente\", min: 250000 },\r\n        { level: \"riconosciuto\", min: 750000 },\r\n        { level: \"mainstream\", min: 1500000 },\r\n        { level: \"icona\", min: 3000000 }\r\n      ];\r\n      let classicStreakLoading = false;\r\n      let classicStreakLoaded = false;\r\n      let rankedMessageTimeoutId = 0;\r\n      const CLASSIC_LOGO_URL = \"https:\/\/bulldogmusik.it\/wp-content\/uploads\/2026\/05\/Bulldogle-Classico-New.png\";\r\n      const RANKED_LOGO_URL = \"https:\/\/bulldogmusik.it\/wp-content\/uploads\/2026\/05\/Bulldogle-Ranked-New-1.png\";\r\n      const RANKED_INITIAL_TIME = 180;\r\n      const RANKED_ATTEMPTS = 10;\r\n      const RANKED_CORRECT_BONUS = 15;\r\n      const RANKED_SKIP_PENALTY = 15;\r\n      const RANKED_ROUND_TRANSITION_MS = 1000;\r\n      const hasRankedBackend = Boolean(rankedConfig && rankedConfig.ajaxUrl && rankedConfig.nonce);\r\n\r\n      const modeConfig = {\r\n        classic: { submitLabel: \"PROVA\", actionLabel: \"\", inputPlaceholder: \"inserisci un artista\" },\r\n        practice: { submitLabel: \"PROVA\", actionLabel: \"NUOVO\", inputPlaceholder: \"inserisci un artista\" }\r\n      };\r\n\r\n      function parseMonthlyListenersValue(value) {\r\n        if (typeof value === \"number\") {\r\n          return Number.isFinite(value) && value > 0 ? Math.round(value) : 0;\r\n        }\r\n\r\n        const raw = String(value || \"\").trim();\r\n        if (!raw) return 0;\r\n\r\n        const compact = raw.replace(\/\\s+\/g, \"\");\r\n        const suffixMatch = compact.match(\/^([0-9]+(?:[.,][0-9]+)?)\\s*([kmb])$\/i);\r\n        if (suffixMatch) {\r\n          const amount = Number(suffixMatch[1].replace(\",\", \".\"));\r\n          if (!Number.isFinite(amount) || amount <= 0) return 0;\r\n          const unit = suffixMatch[2].toLowerCase();\r\n          if (unit === \"b\") return Math.round(amount * 1e9);\r\n          if (unit === \"m\") return Math.round(amount * 1e6);\r\n          return Math.round(amount * 1e3);\r\n        }\r\n\r\n        if (\/^\\d{1,3}([.,]\\d{3})+$\/.test(compact)) {\r\n          return Math.round(Number(compact.replace(\/[.,]\/g, \"\")) || 0);\r\n        }\r\n\r\n        const parsed = Number(compact.replace(\",\", \".\"));\r\n        return Number.isFinite(parsed) && parsed > 0 ? Math.round(parsed) : 0;\r\n      }\r\n\r\n      function getManualMonthlyListeners(artist) {\r\n        const manualKeys = [\r\n          \"listenersManual\",\r\n          \"monthlyListenersManual\",\r\n          \"manualMonthlyListeners\",\r\n          \"manualListeners\",\r\n          \"listeners_manual\",\r\n          \"monthly_listeners_manual\",\r\n          \"listeners-manual\",\r\n          \"monthly-listeners-manual\"\r\n        ];\r\n\r\n        for (const key of manualKeys) {\r\n          const value = parseMonthlyListenersValue(artist && artist[key]);\r\n          if (value > 0) return value;\r\n        }\r\n\r\n        return 0;\r\n      }\r\n\r\n      const artists = artistsSource.map((artist) => ({\r\n        id: Number(artist.id),\r\n        name: String(artist.name || \"\").trim(),\r\n        city: String(artist.city || \"\").trim(),\r\n        region: String(artist.region || \"\").trim(),\r\n        debutYear: Number(artist.debutYear || 0),\r\n        members: String(artist.members || \"N\/D\").trim(),\r\n        gender: String(artist.gender || \"\").trim(),\r\n        popularity: String(artist.popularity || \"\").trim().toLowerCase(),\r\n        monthlyListeners: Number(artist.monthlyListeners || 0),\r\n        listenersManual: getManualMonthlyListeners(artist),\r\n        spotifyId: String(artist.spotifyId || \"\").trim(),\r\n        tip: String(artist.tip || \"\").trim()\r\n      })).filter((artist) => artist.id && artist.name);\r\n\r\n      const spotifyThumbStorageKey = \"bulldogle-spotify-thumbs-v1\";\r\n      const spotifyThumbCache = new Map();\r\n      const spotifyThumbRequests = new Map();\r\n      let messageTimeoutId = 0;\r\n\r\n      try {\r\n        const storedThumbs = JSON.parse(window.localStorage.getItem(spotifyThumbStorageKey) || \"{}\");\r\n        Object.keys(storedThumbs).forEach((spotifyId) => {\r\n          if (storedThumbs[spotifyId]) {\r\n            spotifyThumbCache.set(spotifyId, String(storedThumbs[spotifyId]));\r\n          }\r\n        });\r\n      } catch (_) {}\r\n\r\n      const demoRoots = Array.from(document.querySelectorAll(\".demo-app\"));\r\n      const appRoot = bootstrapScript &&\r\n        bootstrapScript.previousElementSibling &&\r\n        bootstrapScript.previousElementSibling.classList &&\r\n        bootstrapScript.previousElementSibling.classList.contains(\"demo-app\")\r\n          ? bootstrapScript.previousElementSibling\r\n          : demoRoots[demoRoots.length - 1];\r\n\r\n      if (!appRoot) {\r\n        return;\r\n      }\r\n\r\n      const elements = {\r\n        topLogo: appRoot.querySelector(\".top-logo\"),\r\n        tabs: Array.from(appRoot.querySelectorAll(\".tab[data-mode]\")),\r\n        rankedModeButton: appRoot.querySelector(\"#rankedModeButton\"),\r\n        helpToggle: appRoot.querySelector(\"#helpToggle\"),\r\n        helpPanel: appRoot.querySelector(\"#helpPanel\"),\r\n        helpPanelMobileSlot: appRoot.querySelector(\"#helpPanelMobileSlot\"),\r\n        standardGamePanel: appRoot.querySelector(\"#standardGamePanel\"),\r\n        attemptsCard: appRoot.querySelector(\"#attemptsCard\"),\r\n        guessForm: appRoot.querySelector(\"#guessForm\"),\r\n        inputLabel: appRoot.querySelector(\"#inputLabel\"),\r\n        input: appRoot.querySelector(\"#artistInput\"),\r\n        suggestions: appRoot.querySelector(\"#suggestions\"),\r\n        submitButton: appRoot.querySelector(\"#submitButton\"),\r\n        modeActionButton: appRoot.querySelector(\"#modeActionButton\"),\r\n        dailyStreakCard: appRoot.querySelector(\"#dailyStreakCard\"),\r\n        dailyStreakMain: appRoot.querySelector(\"#dailyStreakMain\"),\r\n        dailyStreakSub: appRoot.querySelector(\"#dailyStreakSub\"),\r\n        message: appRoot.querySelector(\"#gameMsg\"),\r\n        resultsList: appRoot.querySelector(\"#resultsList\"),\r\n        mobileRankedGamePanel: appRoot.querySelector(\"#mobileRankedGamePanel\"),\r\n        mobileRankedHelpPanel: appRoot.querySelector(\"#mobileRankedHelpPanel\"),\r\n        mobileRankedTimerValue: appRoot.querySelector(\"#mobileRankedTimerValue\"),\r\n        mobileRankedScoreValue: appRoot.querySelector(\"#mobileRankedScoreValue\"),\r\n        mobileRankedRoundValue: appRoot.querySelector(\"#mobileRankedRoundValue\"),\r\n        mobileRankedAttemptsCard: appRoot.querySelector(\"#mobileRankedAttemptsCard\"),\r\n        mobileRankedGuessForm: appRoot.querySelector(\"#mobileRankedGuessForm\"),\r\n        mobileRankedInput: appRoot.querySelector(\"#mobileRankedArtistInput\"),\r\n        mobileRankedSuggestions: appRoot.querySelector(\"#mobileRankedSuggestions\"),\r\n        mobileRankedSubmitButton: appRoot.querySelector(\"#mobileRankedSubmitButton\"),\r\n        mobileRankedSideActionButton: appRoot.querySelector(\"#mobileRankedSideActionButton\"),\r\n        mobileRankedSummaryPanel: appRoot.querySelector(\"#mobileRankedSummaryPanel\"),\r\n        mobileRankedSummaryTitle: appRoot.querySelector(\"#mobileRankedSummaryTitle\"),\r\n        mobileRankedSummaryLines: appRoot.querySelector(\"#mobileRankedSummaryLines\"),\r\n        mobileRankedMessage: appRoot.querySelector(\"#mobileRankedGameMsg\"),\r\n        mobileRankedResultsList: appRoot.querySelector(\"#mobileRankedResultsList\")\r\n      };\r\n\r\n      if (!elements.guessForm || !elements.input || !elements.submitButton || !elements.suggestions) {\r\n        return;\r\n      }\r\n\r\n      const desktopHelpPanelParent = elements.helpPanel ? elements.helpPanel.parentElement : null;\r\n      const desktopHelpPanelNextSibling = elements.helpPanel ? elements.helpPanel.nextElementSibling : null;\r\n      const desktopRankedHelpPanelParent = elements.mobileRankedHelpPanel ? elements.mobileRankedHelpPanel.parentElement : null;\r\n      const desktopRankedHelpPanelNextSibling = elements.mobileRankedHelpPanel ? elements.mobileRankedHelpPanel.nextElementSibling : null;\r\n\r\n      if (elements.suggestions.parentElement !== document.body) {\r\n        document.body.appendChild(elements.suggestions);\r\n      }\r\n\r\n      if (elements.mobileRankedSuggestions && elements.mobileRankedSuggestions.parentElement !== document.body) {\r\n        document.body.appendChild(elements.mobileRankedSuggestions);\r\n      }\r\n\r\n      const italyDateInfo = getItalyDateInfo();\r\n      const classicStorageKey = \"bulldogle_classic_\" + italyDateInfo.dayKey;\r\n\r\n      const app = {\r\n        mode: \"classic\",\r\n        lastStandardMode: \"classic\",\r\n        modes: {\r\n          classic: createClassicState(),\r\n          practice: createPracticeState()\r\n        },\r\n        ranked: createRankedState()\r\n      };\r\n\r\n      if (!artists.length) {\r\n        elements.message.textContent = \"artists.js non e stato caricato correttamente.\";\r\n        elements.message.classList.add(\"is-visible\", \"is-error\");\r\n        disableGameInput(true);\r\n        return;\r\n      }\r\n\r\n      function createClassicState() {\r\n        return {\r\n          maxAttempts: 10,\r\n          attempts: 0,\r\n          guessedIds: new Set(),\r\n          results: [],\r\n          complete: false,\r\n          target: getDailyTarget()\r\n        };\r\n      }\r\n\r\n      function createPracticeState() {\r\n        return {\r\n          maxAttempts: 10,\r\n          attempts: 0,\r\n          round: 1,\r\n          guessedIds: new Set(),\r\n          results: [],\r\n          complete: false,\r\n          target: pickRandomArtist()\r\n        };\r\n      }\r\n\r\n      function createRankedState() {\r\n        return {\r\n          active: false,\r\n          preparing: false,\r\n          submitting: false,\r\n          complete: false,\r\n          betweenRounds: false,\r\n          sessionToken: \"\",\r\n          currentArtist: null,\r\n          score: 0,\r\n          timeLeft: RANKED_INITIAL_TIME,\r\n          roundAttempts: 0,\r\n          roundGuessedIds: new Set(),\r\n          usedTargetIds: new Set(),\r\n          freeHintArtist: null,\r\n          results: [],\r\n          timerId: 0,\r\n          roundTransitionId: 0,\r\n          summaryTitle: \"Partita conclusa\",\r\n          summaryLines: [],\r\n          isRecord: false\r\n        };\r\n      }\r\n\r\n      function getClassicSaveStatus() {\r\n        const state = app.modes.classic;\r\n        if (!state.complete) return \"playing\";\r\n        return state.results.some((result) => result.kind === \"guess\" && result.solved) ? \"won\" : \"lost\";\r\n      }\r\n\r\n      function saveClassicState(status) {\r\n        const state = app.modes.classic;\r\n        const guessedArtistIds = state.results\r\n          .filter((result) => result.kind === \"guess\" && result.guessArtist && result.guessArtist.id)\r\n          .map((result) => result.guessArtist.id);\r\n\r\n        const payload = {\r\n          attempts: state.attempts,\r\n          guessedIds: Array.from(state.guessedIds),\r\n          guessedArtistIds: guessedArtistIds,\r\n          status: status || getClassicSaveStatus(),\r\n          targetId: state.target && state.target.id ? Number(state.target.id) : 0\r\n        };\r\n\r\n        try {\r\n          window.localStorage.setItem(classicStorageKey, JSON.stringify(payload));\r\n        } catch (_) {}\r\n      }\r\n\r\n      function loadClassicState() {\r\n        let rawState = \"\";\r\n\r\n        try {\r\n          rawState = window.localStorage.getItem(classicStorageKey) || \"\";\r\n        } catch (_) {\r\n          return;\r\n        }\r\n\r\n        if (!rawState) return;\r\n\r\n        try {\r\n          const savedState = JSON.parse(rawState);\r\n          const state = app.modes.classic;\r\n          const savedTargetId = Number(savedState.targetId || 0);\r\n\r\n          if (!savedTargetId || savedTargetId !== Number(state.target.id)) {\r\n            try {\r\n              window.localStorage.removeItem(classicStorageKey);\r\n            } catch (_) {}\r\n            return;\r\n          }\r\n\r\n          const savedArtistIds = Array.isArray(savedState.guessedArtistIds)\r\n            ? savedState.guessedArtistIds.map((id) => Number(id)).filter((id) => Number.isFinite(id) && id > 0)\r\n            : [];\r\n          const chronologicalIds = savedArtistIds.slice().reverse();\r\n          const restoredGuessedIds = new Set(\r\n            Array.isArray(savedState.guessedIds)\r\n              ? savedState.guessedIds.map((id) => Number(id)).filter((id) => Number.isFinite(id) && id > 0)\r\n              : []\r\n          );\r\n          const savedAttempts = Number(savedState.attempts);\r\n\r\n          state.results = [];\r\n          state.guessedIds = restoredGuessedIds;\r\n          state.attempts = Math.max(\r\n            0,\r\n            Math.min(\r\n              state.maxAttempts,\r\n              Number.isFinite(savedAttempts) ? savedAttempts : chronologicalIds.length\r\n            )\r\n          );\r\n          state.complete = false;\r\n\r\n          chronologicalIds.forEach((id, index) => {\r\n            const guessArtist = artists.find((artist) => artist.id === id);\r\n            if (!guessArtist) return;\r\n\r\n            state.guessedIds.add(guessArtist.id);\r\n            state.results.unshift(buildResultEntry(guessArtist, state.target, {\r\n              label: \"Tentativo \" + (index + 1),\r\n              spotifyId: guessArtist.id === state.target.id ? state.target.spotifyId : \"\"\r\n            }));\r\n          });\r\n\r\n          if (!Number.isFinite(savedAttempts)) {\r\n            state.attempts = Math.min(state.maxAttempts, chronologicalIds.length);\r\n          }\r\n\r\n          if (savedState.status === \"won\") {\r\n            state.complete = true;\r\n            setMessage(\"Hai indovinato \" + state.target.name + \".\", \"success\");\r\n            syncClassicStreakResult(\"won\");\r\n            return;\r\n          }\r\n\r\n          if (savedState.status === \"lost\") {\r\n            state.complete = true;\r\n            state.results.unshift(buildResultEntry(state.target, state.target, {\r\n              kind: \"answer\",\r\n              label: \"Artista corretto\",\r\n              spotifyId: state.target.spotifyId || \"\"\r\n            }));\r\n            setMessage(\"Tentativi finiti. L'artista era \" + state.target.name + \".\", \"error-final\");\r\n            syncClassicStreakResult(\"lost\");\r\n            return;\r\n          }\r\n\r\n          setMessage(\"\", \"\");\r\n        } catch (error) {\r\n          console.error(\"Errore nel caricamento del Daily salvato:\", error);\r\n          try {\r\n            window.localStorage.removeItem(classicStorageKey);\r\n          } catch (_) {}\r\n        }\r\n      }\r\n\r\n      function normalize(value) {\r\n        return String(value || \"\").trim().toLowerCase();\r\n      }\r\n\r\n      function formatPopularityLevel(value) {\r\n        const listeners = Number(value || 0);\r\n        if (!Number.isFinite(listeners) || listeners <= 0) return \"N\/D\";\r\n        if (listeners >= 1e9) return (listeners \/ 1e9).toFixed(listeners >= 1e10 ? 0 : 1).replace(\/\\.0$\/, \"\") + \"B\";\r\n        if (listeners >= 1e6) return (listeners \/ 1e6).toFixed(listeners >= 1e7 ? 0 : 1).replace(\/\\.0$\/, \"\") + \"M\";\r\n        if (listeners >= 1e3) return (listeners \/ 1e3).toFixed(listeners >= 1e5 ? 0 : 1).replace(\/\\.0$\/, \"\") + \"K\";\r\n        return String(listeners);\r\n      }\r\n\r\n      function getMonthlyListeners(artist) {\r\n        const manualValue = getManualMonthlyListeners(artist);\r\n        if (manualValue > 0) {\r\n          return manualValue;\r\n        }\r\n\r\n        const value = Number(artist && artist.monthlyListeners || 0);\r\n        return Number.isFinite(value) && value > 0 ? Math.round(value) : 0;\r\n      }\r\n\r\n      function getLegacyPopularityLevel(artist) {\r\n        const value = normalize(artist && artist.popularity);\r\n        return popularityLevels.includes(value) ? value : \"\";\r\n      }\r\n\r\n      function getPopularityIndexFromMonthlyListeners(value) {\r\n        const listeners = Number(value || 0);\r\n        if (!Number.isFinite(listeners) || listeners <= 0) {\r\n          return -1;\r\n        }\r\n\r\n        let level = monthlyListenerBuckets[0].level;\r\n        for (const bucket of monthlyListenerBuckets) {\r\n          if (listeners >= bucket.min) {\r\n            level = bucket.level;\r\n          }\r\n        }\r\n\r\n        return popularityLevels.indexOf(level);\r\n      }\r\n\r\n      function getComparablePopularityIndex(artist) {\r\n        const monthlyIndex = getPopularityIndexFromMonthlyListeners(getMonthlyListeners(artist));\r\n        if (monthlyIndex >= 0) {\r\n          return monthlyIndex;\r\n        }\r\n\r\n        return popularityLevels.indexOf(getLegacyPopularityLevel(artist));\r\n      }\r\n\r\n      function formatPopularityDisplay(artist) {\r\n        const listeners = getMonthlyListeners(artist);\r\n        if (listeners > 0) {\r\n          return formatPopularityLevel(listeners);\r\n        }\r\n\r\n        const fallback = getLegacyPopularityLevel(artist);\r\n        return fallback ? fallback.charAt(0).toUpperCase() + fallback.slice(1) : \"N\/D\";\r\n      }\r\n\r\n      function formatGenderValue(value) {\r\n        if (value === \"M\") return \"Uomo\";\r\n        if (value === \"F\") return \"Donna\";\r\n        return value || \"N\/D\";\r\n      }\r\n\r\n      function getItalyDateInfo() {\r\n        const formatter = new Intl.DateTimeFormat(\"en-CA\", {\r\n          timeZone: \"Europe\/Rome\",\r\n          year: \"numeric\",\r\n          month: \"2-digit\",\r\n          day: \"2-digit\"\r\n        });\r\n        const parts = formatter.formatToParts(new Date());\r\n        const year = Number(parts.find((part) => part.type === \"year\").value);\r\n        const month = Number(parts.find((part) => part.type === \"month\").value);\r\n        const day = Number(parts.find((part) => part.type === \"day\").value);\r\n        return {\r\n          dayKey: year + \"-\" + String(month).padStart(2, \"0\") + \"-\" + String(day).padStart(2, \"0\"),\r\n          dayIndex: Math.floor(Date.UTC(year, month - 1, day) \/ 86400000)\r\n        };\r\n      }\r\n\r\n      function hashString(value) {\r\n        let hash = 2166136261;\r\n\r\n        for (let index = 0; index < value.length; index++) {\r\n          hash ^= value.charCodeAt(index);\r\n          hash = Math.imul(hash, 16777619);\r\n        }\r\n\r\n        return hash >>> 0;\r\n      }\r\n\r\n      function createSeededRandom(seed) {\r\n        let state = seed >>> 0;\r\n\r\n        return function () {\r\n          state += 0x6D2B79F5;\r\n          let value = Math.imul(state ^ (state >>> 15), 1 | state);\r\n          value ^= value + Math.imul(value ^ (value >>> 7), 61 | value);\r\n          return ((value ^ (value >>> 14)) >>> 0) \/ 4294967296;\r\n        };\r\n      }\r\n\r\n      function getDailyTarget() {\r\n        if (!artists.length) return null;\r\n\r\n        const random = createSeededRandom(hashString(String(italyDateInfo.dayKey || \"\")));\r\n        const dailyIndex = Math.floor(random() * artists.length);\r\n        return artists[dailyIndex] || artists[0];\r\n      }\r\n\r\n      function pickRandomArtist(excludedIds) {\r\n        const blocked = excludedIds || new Set();\r\n        let pool = artists.filter((artist) => !blocked.has(artist.id));\r\n        if (!pool.length) pool = artists.slice();\r\n        return pool[Math.floor(Math.random() * pool.length)];\r\n      }\r\n\r\n      function setMessage(text, tone) {\r\n        if (messageTimeoutId) {\r\n          window.clearTimeout(messageTimeoutId);\r\n          messageTimeoutId = 0;\r\n        }\r\n\r\n        elements.message.className = \"message\";\r\n        if (text && tone) {\r\n          elements.message.textContent = text;\r\n          elements.message.classList.add(\"is-visible\", \"is-\" + tone);\r\n\r\n          if (tone !== \"success\" && tone !== \"error-final\") {\r\n            messageTimeoutId = window.setTimeout(function () {\r\n              elements.message.className = \"message\";\r\n              elements.message.textContent = \"\";\r\n              messageTimeoutId = 0;\r\n            }, 3000);\r\n          }\r\n          return;\r\n        }\r\n        elements.message.textContent = \"\";\r\n      }\r\n\r\n      function renderClassicStreakGuestState() {\r\n        elements.dailyStreakCard.classList.add(\"is-guest\");\r\n        elements.dailyStreakCard.setAttribute(\"href\", guestStreakLoginUrl);\r\n        elements.dailyStreakCard.setAttribute(\"aria-label\", \"Accedi per salvare la streak\");\r\n        elements.dailyStreakMain.textContent = \"STREAK\";\r\n        elements.dailyStreakSub.textContent = \"Accedi per salvarla\";\r\n        classicStreakLoaded = true;\r\n      }\r\n\r\n      function renderClassicStreakLoadingState() {\r\n        elements.dailyStreakCard.classList.remove(\"is-guest\");\r\n        elements.dailyStreakCard.removeAttribute(\"href\");\r\n        elements.dailyStreakCard.removeAttribute(\"aria-label\");\r\n        elements.dailyStreakMain.textContent = \"...\";\r\n        elements.dailyStreakSub.textContent = \"Caricamento streak\";\r\n      }\r\n\r\n      function renderClassicStreakState(data) {\r\n        if (!data || !data.is_logged_in) {\r\n          renderClassicStreakGuestState();\r\n          return;\r\n        }\r\n\r\n        elements.dailyStreakCard.classList.remove(\"is-guest\");\r\n        elements.dailyStreakCard.removeAttribute(\"href\");\r\n        elements.dailyStreakCard.removeAttribute(\"aria-label\");\r\n\r\n        const streakValue = Number(data.current_streak || 0);\r\n        elements.dailyStreakMain.textContent = String(streakValue) + \" \" + (streakValue === 1 ? \"GIORNO\" : \"GIORNI\");\r\n\r\n        if (data.today_result === \"won\") {\r\n          elements.dailyStreakSub.textContent = \"Indovinata oggi - Record \" + String(data.best_streak || data.current_streak || 0);\r\n        } else if (data.today_result === \"lost\") {\r\n          elements.dailyStreakSub.textContent = \"Interrotta oggi - Record \" + String(data.best_streak || 0);\r\n        } else {\r\n          elements.dailyStreakSub.textContent = \"Record \" + String(data.best_streak || data.current_streak || 0);\r\n        }\r\n\r\n        classicStreakLoaded = true;\r\n      }\r\n\r\n      async function postClassicStreakAction(action, extraData) {\r\n        const ajaxUrl = classicConfig.ajaxUrl;\r\n        if (!ajaxUrl) {\r\n          throw new Error(\"Config streak WordPress non trovata\");\r\n        }\r\n\r\n        const body = new URLSearchParams({\r\n          action: action,\r\n          nonce: classicConfig.nonce || \"\",\r\n          ...(extraData || {})\r\n        });\r\n\r\n        const response = await fetch(ajaxUrl, {\r\n          method: \"POST\",\r\n          credentials: \"same-origin\",\r\n          headers: {\r\n            \"Content-Type\": \"application\/x-www-form-urlencoded; charset=UTF-8\"\r\n          },\r\n          body: body.toString()\r\n        });\r\n\r\n        if (!response.ok) {\r\n          throw new Error(\"Richiesta streak non riuscita\");\r\n        }\r\n\r\n        return response.json();\r\n      }\r\n\r\n      async function loadClassicStreakStatus(force) {\r\n        if (!classicConfig.isLoggedIn) {\r\n          renderClassicStreakGuestState();\r\n          return;\r\n        }\r\n\r\n        if (classicStreakLoading) return;\r\n        if (classicStreakLoaded && !force) return;\r\n\r\n        classicStreakLoading = true;\r\n        renderClassicStreakLoadingState();\r\n\r\n        try {\r\n          const response = await postClassicStreakAction(\"bulldogle_classic_streak_status\");\r\n          if (response && response.success) {\r\n            renderClassicStreakState(response.data);\r\n          } else {\r\n            renderClassicStreakGuestState();\r\n          }\r\n        } catch (_) {\r\n          renderClassicStreakGuestState();\r\n        } finally {\r\n          classicStreakLoading = false;\r\n        }\r\n      }\r\n\r\n      async function syncClassicStreakResult(result) {\r\n        if (!classicConfig.isLoggedIn) return;\r\n\r\n        try {\r\n          const response = await postClassicStreakAction(\"bulldogle_classic_streak_update\", {\r\n            result: result,\r\n            day_key: getItalyDateInfo().dayKey\r\n          });\r\n\r\n          if (response && response.success) {\r\n            renderClassicStreakState(response.data);\r\n          }\r\n        } catch (error) {\r\n          console.error(\"Errore aggiornamento streak Bulldogle:\", error);\r\n        }\r\n      }\r\n\r\n      function getRankedLoginUrl() {\r\n        return rankedConfig.loginUrl || guestStreakLoginUrl;\r\n      }\r\n\r\n      function isRankedMode() {\r\n        return app.mode === \"ranked\";\r\n      }\r\n\r\n      function getCurrentHelpPanel() {\r\n        return isRankedMode() ? elements.mobileRankedHelpPanel : elements.helpPanel;\r\n      }\r\n\r\n      function closeAllHelpPanels() {\r\n        [elements.helpPanel, elements.mobileRankedHelpPanel].forEach((panel) => {\r\n          if (!panel) return;\r\n          panel.classList.remove(\"is-open\");\r\n          panel.setAttribute(\"aria-hidden\", \"true\");\r\n        });\r\n        elements.helpToggle.classList.remove(\"is-active\");\r\n      }\r\n\r\n      function syncHelpToggleState() {\r\n        const panel = getCurrentHelpPanel();\r\n        elements.helpToggle.classList.toggle(\"is-active\", !!panel && panel.classList.contains(\"is-open\"));\r\n      }\r\n\r\n      function restorePanelPlacement(panel, parent, nextSibling) {\r\n        if (!panel || !parent) return;\r\n        if (panel.parentElement === parent) return;\r\n\r\n        if (nextSibling && nextSibling.parentElement === parent) {\r\n          parent.insertBefore(panel, nextSibling);\r\n          return;\r\n        }\r\n\r\n        parent.appendChild(panel);\r\n      }\r\n\r\n      function positionSuggestionsFor(inputElement, suggestionElement) {\r\n        const rect = inputElement.getBoundingClientRect();\r\n        const viewport = getViewportMetrics();\r\n        const viewportPadding = 10;\r\n        const width = Math.min(rect.width, viewport.width - viewportPadding * 2);\r\n        const left = Math.max(\r\n          viewport.offsetLeft + viewportPadding,\r\n          Math.min(rect.left, viewport.offsetLeft + viewport.width - width - viewportPadding)\r\n        );\r\n        const spaceBelow = viewport.offsetTop + viewport.height - rect.bottom - viewportPadding;\r\n        const maxHeight = Math.max(140, Math.min(280, spaceBelow - 8));\r\n\r\n        suggestionElement.style.width = width + \"px\";\r\n        suggestionElement.style.left = left + \"px\";\r\n        suggestionElement.style.top = Math.max(viewportPadding, rect.bottom + 8) + \"px\";\r\n        suggestionElement.style.maxHeight = maxHeight + \"px\";\r\n      }\r\n\r\n      function setRankedMessage(text, tone) {\r\n        if (rankedMessageTimeoutId) {\r\n          window.clearTimeout(rankedMessageTimeoutId);\r\n          rankedMessageTimeoutId = 0;\r\n        }\r\n\r\n        elements.mobileRankedMessage.className = \"message\";\r\n        if (text && tone) {\r\n          elements.mobileRankedMessage.textContent = text;\r\n          elements.mobileRankedMessage.classList.add(\"is-visible\", \"is-\" + tone);\r\n\r\n          if (tone !== \"success\") {\r\n            rankedMessageTimeoutId = window.setTimeout(function () {\r\n              elements.mobileRankedMessage.className = \"message\";\r\n              elements.mobileRankedMessage.textContent = \"\";\r\n              rankedMessageTimeoutId = 0;\r\n            }, 2200);\r\n          }\r\n          return;\r\n        }\r\n\r\n        elements.mobileRankedMessage.textContent = \"\";\r\n      }\r\n\r\n      function disableRankedInput(disabled) {\r\n        elements.mobileRankedInput.disabled = disabled;\r\n        elements.mobileRankedSubmitButton.disabled =\r\n          disabled ||\r\n          !app.ranked.active ||\r\n          app.ranked.betweenRounds ||\r\n          app.ranked.preparing ||\r\n          app.ranked.submitting;\r\n      }\r\n\r\n      function hideRankedSuggestions() {\r\n        if (elements.mobileRankedSuggestions) {\r\n          elements.mobileRankedSuggestions.style.display = \"none\";\r\n        }\r\n      }\r\n\r\n      function showRankedSuggestions() {\r\n        positionSuggestionsFor(elements.mobileRankedInput, elements.mobileRankedSuggestions);\r\n        elements.mobileRankedSuggestions.style.display = \"block\";\r\n      }\r\n\r\n      function formatRankedSummaryLines(lines) {\r\n        elements.mobileRankedSummaryLines.innerHTML = \"\";\r\n        lines.forEach((line) => {\r\n          const row = document.createElement(\"div\");\r\n          row.className = \"ranked-summary-line\";\r\n          row.innerHTML = line;\r\n          elements.mobileRankedSummaryLines.appendChild(row);\r\n        });\r\n      }\r\n\r\n      function renderRankedMeta() {\r\n        const state = app.ranked;\r\n        elements.mobileRankedTimerValue.textContent = formatTime(state.timeLeft);\r\n        elements.mobileRankedScoreValue.textContent = String(state.score);\r\n        if (elements.mobileRankedRoundValue) {\r\n          elements.mobileRankedRoundValue.textContent = state.active\r\n            ? \"Artista #\" + String(state.score + 1)\r\n            : (state.complete ? \"Fine\" : \"Pronto\");\r\n        }\r\n      }\r\n\r\n      function renderRankedAttemptsCard() {\r\n        const attemptsLeft = Math.max(0, RANKED_ATTEMPTS - app.ranked.roundAttempts);\r\n        elements.mobileRankedAttemptsCard.textContent = String(attemptsLeft) + \" \" + (attemptsLeft === 1 ? \"TENTATIVO\" : \"TENTATIVI\");\r\n      }\r\n\r\n      function renderRankedInputState() {\r\n        disableRankedInput(!app.ranked.active);\r\n        elements.mobileRankedInput.placeholder = app.ranked.active ? \"inserisci un artista\" : (app.ranked.complete ? \"Partita conclusa\" : \"inserisci un artista\");\r\n      }\r\n\r\n      function renderRankedActionButton() {\r\n        const button = elements.mobileRankedSideActionButton;\r\n        button.className = \"secondary-button\";\r\n        button.disabled = false;\r\n\r\n        if (app.ranked.preparing || app.ranked.submitting) {\r\n          button.textContent = \"...\";\r\n          button.disabled = true;\r\n          button.dataset.action = \"wait\";\r\n          return;\r\n        }\r\n\r\n        if (app.ranked.active) {\r\n          if (app.ranked.betweenRounds) {\r\n            button.textContent = \"ATTENDI\";\r\n            button.disabled = true;\r\n            button.dataset.action = \"wait\";\r\n            return;\r\n          }\r\n\r\n          button.textContent = \"SKIP\";\r\n          button.dataset.action = \"skip\";\r\n          return;\r\n        }\r\n\r\n        if (app.ranked.complete) {\r\n          button.textContent = \"RIGIOCA\";\r\n          button.dataset.action = \"restart\";\r\n          return;\r\n        }\r\n\r\n        if (hasRankedBackend && !rankedConfig.isLoggedIn) {\r\n          button.textContent = \"ACCEDI\";\r\n          button.dataset.action = \"login\";\r\n          return;\r\n        }\r\n\r\n        button.textContent = \"INIZIA\";\r\n        button.dataset.action = \"start\";\r\n      }\r\n\r\n      function renderRankedResults() {\r\n        const results = app.ranked.results || [];\r\n        elements.mobileRankedResultsList.innerHTML = \"\";\r\n\r\n        if (!results.length) {\r\n          const empty = document.createElement(\"div\");\r\n          empty.className = \"empty-state\";\r\n          empty.textContent = app.ranked.complete\r\n            ? \"La partita e finita. Puoi controllare il riepilogo finale.\"\r\n            : (app.ranked.active\r\n              ? \"I tentativi di questo round appariranno qui.\"\r\n              : (hasRankedBackend && !rankedConfig.isLoggedIn ? \"ACCEDI per giocare.\" : \"Premi INIZIA per giocare.\"));\r\n          elements.mobileRankedResultsList.appendChild(empty);\r\n          return;\r\n        }\r\n\r\n        results.forEach((result) => {\r\n          elements.mobileRankedResultsList.appendChild(buildResultCard(result));\r\n        });\r\n      }\r\n\r\n      function renderRankedSummary() {\r\n        elements.mobileRankedSummaryPanel.classList.toggle(\"hidden\", !app.ranked.complete || !app.ranked.summaryLines.length);\r\n        elements.mobileRankedSummaryPanel.classList.toggle(\"is-record\", app.ranked.isRecord);\r\n        elements.mobileRankedSummaryTitle.textContent = app.ranked.summaryTitle || \"Partita conclusa\";\r\n        formatRankedSummaryLines(app.ranked.summaryLines);\r\n      }\r\n\r\n      function resetRankedState() {\r\n        const state = app.ranked;\r\n        state.active = false;\r\n        state.preparing = false;\r\n        state.submitting = false;\r\n        state.complete = false;\r\n        state.betweenRounds = false;\r\n        state.sessionToken = \"\";\r\n        state.currentArtist = null;\r\n        state.score = 0;\r\n        state.timeLeft = RANKED_INITIAL_TIME;\r\n        state.roundAttempts = 0;\r\n        state.roundGuessedIds = new Set();\r\n        state.usedTargetIds = new Set();\r\n        state.freeHintArtist = null;\r\n        state.results = [];\r\n        state.summaryTitle = \"Partita conclusa\";\r\n        state.summaryLines = [];\r\n        state.isRecord = false;\r\n        window.clearInterval(state.timerId);\r\n        window.clearTimeout(state.roundTransitionId);\r\n        state.timerId = 0;\r\n        state.roundTransitionId = 0;\r\n        setRankedMessage(\"\", \"\");\r\n        elements.mobileRankedInput.value = \"\";\r\n        hideRankedSuggestions();\r\n      }\r\n\r\n      function buildRankedSummaryLines(data) {\r\n        const lines = [];\r\n        if (app.ranked.currentArtist && app.ranked.currentArtist.name) {\r\n          lines.push(\"L'ultimo artista era: <strong>\" + escapeHtml(app.ranked.currentArtist.name) + \"<\/strong>\");\r\n        }\r\n        lines.push(\"Punteggio finale: <strong>\" + String(app.ranked.score) + \"<\/strong>\");\r\n\r\n        if (data && typeof data.best_score !== \"undefined\") {\r\n          lines.push(\"Record mensile: <strong>\" + String(data.best_score) + \"<\/strong>\");\r\n          if (data.best_rank) {\r\n            lines.push(\"Migliore posizione: <strong>#\" + String(data.best_rank) + \"<\/strong>\");\r\n          } else {\r\n            lines.push(\"Migliore posizione: <strong>Fuori top 50<\/strong>\");\r\n          }\r\n        } else if (hasRankedBackend) {\r\n          lines.push(\"Record non salvato, riprova piu tardi.\");\r\n        }\r\n\r\n        return lines;\r\n      }\r\n\r\n      async function postRankedAction(action, extraData) {\r\n        const body = new URLSearchParams({\r\n          action: action,\r\n          nonce: rankedConfig.nonce || \"\",\r\n          game_key: \"classic\",\r\n          ...(extraData || {})\r\n        });\r\n\r\n        const response = await fetch(rankedConfig.ajaxUrl, {\r\n          method: \"POST\",\r\n          credentials: \"same-origin\",\r\n          headers: {\r\n            \"Content-Type\": \"application\/x-www-form-urlencoded; charset=UTF-8\"\r\n          },\r\n          body: body.toString()\r\n        });\r\n\r\n        if (!response.ok) {\r\n          throw new Error(\"Richiesta ranked non riuscita\");\r\n        }\r\n\r\n        return response.json();\r\n      }\r\n\r\n      function startNextRankedArtist() {\r\n        if (!app.ranked.active) return;\r\n\r\n        window.clearTimeout(app.ranked.roundTransitionId);\r\n        app.ranked.betweenRounds = false;\r\n\r\n        if (app.ranked.usedTargetIds.size >= artists.length) {\r\n          app.ranked.usedTargetIds.clear();\r\n        }\r\n\r\n        const nextArtist = pickRandomArtist(app.ranked.usedTargetIds);\r\n        app.ranked.currentArtist = nextArtist;\r\n        app.ranked.usedTargetIds.add(nextArtist.id);\r\n        app.ranked.roundAttempts = 0;\r\n        app.ranked.roundGuessedIds = new Set();\r\n        app.ranked.results = [];\r\n\r\n        if (app.ranked.freeHintArtist) {\r\n          app.ranked.results.unshift(buildResultEntry(app.ranked.freeHintArtist, app.ranked.currentArtist, {\r\n            kind: \"auto\",\r\n            label: \"Reveal del Artista passato\"\r\n          }));\r\n          app.ranked.freeHintArtist = null;\r\n        }\r\n\r\n        elements.mobileRankedInput.value = \"\";\r\n        hideRankedSuggestions();\r\n        setRankedMessage(\"\", \"\");\r\n        renderRankedMeta();\r\n        renderRankedAttemptsCard();\r\n        renderRankedInputState();\r\n        renderRankedActionButton();\r\n        renderRankedResults();\r\n        if (app.mode === \"ranked\") {\r\n          elements.mobileRankedInput.focus();\r\n        }\r\n      }\r\n\r\n      function completeRankedRound(message, tone, carryArtist) {\r\n        if (!app.ranked.active || !app.ranked.currentArtist) return;\r\n\r\n        if (carryArtist) {\r\n          app.ranked.freeHintArtist = app.ranked.currentArtist;\r\n        }\r\n\r\n        app.ranked.betweenRounds = true;\r\n        elements.mobileRankedInput.value = \"\";\r\n        hideRankedSuggestions();\r\n        renderRankedInputState();\r\n        renderRankedActionButton();\r\n        setRankedMessage(message, tone);\r\n\r\n        app.ranked.roundTransitionId = window.setTimeout(function () {\r\n          if (!app.ranked.active || app.ranked.timeLeft <= 0) return;\r\n          startNextRankedArtist();\r\n        }, RANKED_ROUND_TRANSITION_MS);\r\n      }\r\n\r\n      function tickRanked() {\r\n        if (!app.ranked.active) return;\r\n        app.ranked.timeLeft -= 1;\r\n        renderRankedMeta();\r\n        if (app.ranked.timeLeft <= 0) {\r\n          finishRankedGame();\r\n        }\r\n      }\r\n\r\n      async function startRankedGame() {\r\n        if (app.ranked.active || app.ranked.preparing) return;\r\n\r\n        if (hasRankedBackend && !rankedConfig.isLoggedIn) {\r\n          window.location.href = getRankedLoginUrl();\r\n          return;\r\n        }\r\n\r\n        app.ranked.preparing = true;\r\n        app.ranked.complete = false;\r\n        app.ranked.summaryLines = [];\r\n        renderRankedActionButton();\r\n\r\n        try {\r\n          if (hasRankedBackend) {\r\n            const response = await postRankedAction(\"bulldogle_ranked_start\");\r\n            if (!response || !response.success || !response.data || !response.data.is_logged_in) {\r\n              window.location.href = getRankedLoginUrl();\r\n              return;\r\n            }\r\n            app.ranked.sessionToken = String(response.data.token || \"\");\r\n          } else {\r\n            app.ranked.sessionToken = \"demo-\" + String(Date.now());\r\n          }\r\n\r\n          window.clearInterval(app.ranked.timerId);\r\n          window.clearTimeout(app.ranked.roundTransitionId);\r\n          app.ranked.active = true;\r\n          app.ranked.complete = false;\r\n          app.ranked.betweenRounds = false;\r\n          app.ranked.submitting = false;\r\n          app.ranked.score = 0;\r\n          app.ranked.timeLeft = RANKED_INITIAL_TIME;\r\n          app.ranked.roundAttempts = 0;\r\n          app.ranked.roundGuessedIds = new Set();\r\n          app.ranked.usedTargetIds = new Set();\r\n          app.ranked.freeHintArtist = null;\r\n          app.ranked.results = [];\r\n          app.ranked.summaryTitle = \"Partita conclusa\";\r\n          app.ranked.summaryLines = [];\r\n          app.ranked.isRecord = false;\r\n          setRankedMessage(\"\", \"\");\r\n          renderRankedPanel();\r\n          startNextRankedArtist();\r\n          app.ranked.timerId = window.setInterval(tickRanked, 1000);\r\n        } catch (_) {\r\n          setRankedMessage(\"Non sono riuscito ad avviare la partita. Riprova tra poco.\", \"error\");\r\n        } finally {\r\n          app.ranked.preparing = false;\r\n          renderRankedInputState();\r\n          renderRankedActionButton();\r\n        }\r\n      }\r\n\r\n      function submitRankedGuess() {\r\n        if (!app.ranked.active || app.ranked.betweenRounds || !app.ranked.currentArtist) return;\r\n\r\n        const guessName = elements.mobileRankedInput.value.trim();\r\n        const guessArtist = findArtistByName(guessName);\r\n\r\n        if (!guessArtist) {\r\n          setRankedMessage(\"Artista non trovato nella lista.\", \"error\");\r\n          return;\r\n        }\r\n\r\n        if (app.ranked.roundGuessedIds.has(guessArtist.id)) {\r\n          setRankedMessage(\"Hai gia provato questo artista.\", \"error\");\r\n          elements.mobileRankedInput.value = \"\";\r\n          return;\r\n        }\r\n\r\n        app.ranked.roundGuessedIds.add(guessArtist.id);\r\n        app.ranked.roundAttempts += 1;\r\n        app.ranked.results.unshift(buildResultEntry(guessArtist, app.ranked.currentArtist, {\r\n          label: \"Tentativo \" + app.ranked.roundAttempts\r\n        }));\r\n        renderRankedAttemptsCard();\r\n        renderRankedResults();\r\n        elements.mobileRankedInput.value = \"\";\r\n        hideRankedSuggestions();\r\n\r\n        if (guessArtist.id === app.ranked.currentArtist.id) {\r\n          app.ranked.score += 1;\r\n          app.ranked.timeLeft += RANKED_CORRECT_BONUS;\r\n          renderRankedMeta();\r\n          completeRankedRound(\"Hai indovinato!\", \"success\", true);\r\n          return;\r\n        }\r\n\r\n        if (app.ranked.roundAttempts >= RANKED_ATTEMPTS) {\r\n          completeRankedRound(\"Hai finito i tentativi! Era \" + app.ranked.currentArtist.name + \".\", \"error\", true);\r\n        }\r\n      }\r\n\r\n      function skipRankedArtist() {\r\n        if (!app.ranked.active || app.ranked.betweenRounds || !app.ranked.currentArtist) return;\r\n\r\n        app.ranked.timeLeft = Math.max(0, app.ranked.timeLeft - RANKED_SKIP_PENALTY);\r\n        renderRankedMeta();\r\n\r\n        if (app.ranked.timeLeft <= 0) {\r\n          finishRankedGame();\r\n          return;\r\n        }\r\n\r\n        completeRankedRound(\"Hai skippato! Era \" + app.ranked.currentArtist.name + \".\", \"error\", true);\r\n      }\r\n\r\n      async function finishRankedGame() {\r\n        if (!app.ranked.active || app.ranked.submitting) return;\r\n\r\n        app.ranked.active = false;\r\n        app.ranked.complete = true;\r\n        app.ranked.betweenRounds = false;\r\n        app.ranked.submitting = true;\r\n        app.ranked.timeLeft = 0;\r\n        window.clearInterval(app.ranked.timerId);\r\n        window.clearTimeout(app.ranked.roundTransitionId);\r\n        app.ranked.timerId = 0;\r\n        app.ranked.roundTransitionId = 0;\r\n        hideRankedSuggestions();\r\n        setRankedMessage(\"\", \"\");\r\n        renderRankedMeta();\r\n        renderRankedInputState();\r\n        renderRankedActionButton();\r\n\r\n        app.ranked.summaryTitle = \"Partita conclusa\";\r\n        app.ranked.summaryLines = [\"Salvataggio record...\"];\r\n        app.ranked.isRecord = false;\r\n        renderRankedSummary();\r\n\r\n        try {\r\n          let data = null;\r\n\r\n          if (hasRankedBackend) {\r\n            const response = await postRankedAction(\"bulldogle_ranked_submit\", {\r\n              token: app.ranked.sessionToken,\r\n              score: String(app.ranked.score)\r\n            });\r\n            data = response && response.success ? response.data : null;\r\n          }\r\n\r\n          if (data) {\r\n            app.ranked.summaryTitle = data.is_record ? \"Nuovo record!\" : \"Partita conclusa\";\r\n            app.ranked.summaryLines = buildRankedSummaryLines(data);\r\n            app.ranked.isRecord = Boolean(data.is_record);\r\n          } else {\r\n            app.ranked.summaryTitle = \"Partita conclusa\";\r\n            app.ranked.summaryLines = buildRankedSummaryLines(null);\r\n            app.ranked.isRecord = false;\r\n          }\r\n        } catch (_) {\r\n          app.ranked.summaryTitle = \"Partita conclusa\";\r\n          app.ranked.summaryLines = buildRankedSummaryLines(null);\r\n          app.ranked.isRecord = false;\r\n        } finally {\r\n          app.ranked.submitting = false;\r\n          renderRankedPanel();\r\n        }\r\n      }\r\n\r\n      function updateRankedSuggestions() {\r\n        const value = normalize(elements.mobileRankedInput.value);\r\n        if (!value || !app.ranked.active || app.ranked.betweenRounds || !app.ranked.currentArtist) {\r\n          hideRankedSuggestions();\r\n          return;\r\n        }\r\n\r\n        const matches = artists.filter((artist) => {\r\n          return normalize(artist.name).includes(value) && !app.ranked.roundGuessedIds.has(artist.id);\r\n        }).slice(0, 8);\r\n\r\n        elements.mobileRankedSuggestions.innerHTML = \"\";\r\n        matches.forEach((artist) => {\r\n          const button = document.createElement(\"button\");\r\n          button.type = \"button\";\r\n          button.className = \"suggestion\";\r\n\r\n          const left = document.createElement(\"span\");\r\n          left.textContent = artist.name;\r\n          const right = document.createElement(\"small\");\r\n          right.textContent = artist.city + \" \/ \" + formatPopularityDisplay(artist);\r\n\r\n          button.appendChild(left);\r\n          button.appendChild(right);\r\n          button.addEventListener(\"click\", function () {\r\n            elements.mobileRankedInput.value = artist.name;\r\n            hideRankedSuggestions();\r\n            elements.mobileRankedInput.focus();\r\n          });\r\n          elements.mobileRankedSuggestions.appendChild(button);\r\n        });\r\n\r\n        if (matches.length) {\r\n          showRankedSuggestions();\r\n          return;\r\n        }\r\n\r\n        hideRankedSuggestions();\r\n      }\r\n\r\n      function handleRankedSideAction() {\r\n        const action = elements.mobileRankedSideActionButton.dataset.action;\r\n\r\n        if (action === \"login\") {\r\n          window.location.href = getRankedLoginUrl();\r\n          return;\r\n        }\r\n\r\n        if (action === \"start\" || action === \"restart\") {\r\n          startRankedGame();\r\n          return;\r\n        }\r\n\r\n        if (action === \"skip\") {\r\n          skipRankedArtist();\r\n        }\r\n      }\r\n\r\n      function renderRankedPanel() {\r\n        renderRankedMeta();\r\n        renderRankedAttemptsCard();\r\n        renderRankedInputState();\r\n        renderRankedActionButton();\r\n        renderRankedResults();\r\n        renderRankedSummary();\r\n        hideRankedSuggestions();\r\n      }\r\n\r\n      function disableGameInput(disabled) {\r\n        elements.input.disabled = disabled;\r\n        elements.submitButton.disabled = disabled;\r\n      }\r\n\r\n      function hideSuggestions() {\r\n        elements.suggestions.style.display = \"none\";\r\n      }\r\n\r\n      function getViewportMetrics() {\r\n        if (window.visualViewport) {\r\n          return {\r\n            width: window.visualViewport.width,\r\n            height: window.visualViewport.height,\r\n            offsetLeft: window.visualViewport.offsetLeft,\r\n            offsetTop: window.visualViewport.offsetTop\r\n          };\r\n        }\r\n\r\n        return {\r\n          width: window.innerWidth,\r\n          height: window.innerHeight,\r\n          offsetLeft: 0,\r\n          offsetTop: 0\r\n        };\r\n      }\r\n\r\n      function positionSuggestions() {\r\n        positionSuggestionsFor(elements.input, elements.suggestions);\r\n      }\r\n\r\n      function showSuggestions() {\r\n        positionSuggestions();\r\n        elements.suggestions.style.display = \"block\";\r\n      }\r\n\r\n      function syncHelpPanelPlacement() {\r\n        if (!elements.helpPanelMobileSlot) {\r\n          return;\r\n        }\r\n\r\n        const isMobileLayout = window.matchMedia(\"(max-width: 720px)\").matches;\r\n        const activePanel = getCurrentHelpPanel();\r\n\r\n        if (isMobileLayout) {\r\n          [elements.helpPanel, elements.mobileRankedHelpPanel].forEach((panel) => {\r\n            if (!panel) return;\r\n\r\n            if (panel === activePanel) {\r\n              if (panel.parentElement !== elements.helpPanelMobileSlot) {\r\n                elements.helpPanelMobileSlot.appendChild(panel);\r\n              }\r\n              return;\r\n            }\r\n\r\n            if (panel === elements.helpPanel) {\r\n              restorePanelPlacement(panel, desktopHelpPanelParent, desktopHelpPanelNextSibling);\r\n              return;\r\n            }\r\n\r\n            restorePanelPlacement(panel, desktopRankedHelpPanelParent, desktopRankedHelpPanelNextSibling);\r\n          });\r\n          return;\r\n        }\r\n\r\n        restorePanelPlacement(elements.helpPanel, desktopHelpPanelParent, desktopHelpPanelNextSibling);\r\n        restorePanelPlacement(elements.mobileRankedHelpPanel, desktopRankedHelpPanelParent, desktopRankedHelpPanelNextSibling);\r\n      }\r\n\r\n      function getActiveState() {\r\n        return app.modes[app.mode];\r\n      }\r\n\r\n      function getModeGuessedIds() {\r\n        return getActiveState().guessedIds;\r\n      }\r\n\r\n      function buildPopularityTrait(guessArtist, targetArtist) {\r\n        const guessIndex = getMonthlyListeners(guessArtist);\r\n        const targetIndex = getMonthlyListeners(targetArtist);\r\n        let status = \"wrong\";\r\n        let text = formatPopularityDisplay(guessArtist);\r\n        let hint = \"Dato non disponibile.\";\r\n        let arrow = \"\";\r\n\r\n        if (guessIndex > 0 && targetIndex > 0) {\r\n          if (guessIndex === targetIndex) {\r\n            status = \"correct\";\r\n            hint = \"Stesso valore.\";\r\n          } else {\r\n            if (Math.abs(guessIndex - targetIndex) \/ Math.max(targetIndex, 1) <= 0.2) {\r\n              status = \"close\";\r\n              hint = \"Molto vicino.\";\r\n            }\r\n            arrow = targetIndex > guessIndex ? ARROWS.up : ARROWS.down;\r\n            if (status !== \"close\") {\r\n              hint = targetIndex > guessIndex ? \"Il target ha piu ascoltatori mensili.\" : \"Il target ha meno ascoltatori mensili.\";\r\n            }\r\n          }\r\n        } else {\r\n          const fallbackGuessIndex = getComparablePopularityIndex(guessArtist);\r\n          const fallbackTargetIndex = getComparablePopularityIndex(targetArtist);\r\n\r\n          if (fallbackGuessIndex >= 0 && fallbackTargetIndex >= 0) {\r\n            if (fallbackGuessIndex === fallbackTargetIndex) {\r\n              status = \"correct\";\r\n              hint = \"Stesso livello.\";\r\n            } else {\r\n              if (Math.abs(fallbackGuessIndex - fallbackTargetIndex) === 1) {\r\n                status = \"close\";\r\n                hint = \"A un gradino di distanza.\";\r\n              }\r\n              arrow = fallbackTargetIndex > fallbackGuessIndex ? ARROWS.up : ARROWS.down;\r\n              if (status !== \"close\") {\r\n                hint = fallbackTargetIndex > fallbackGuessIndex ? \"Il target e piu popolare.\" : \"Il target e meno popolare.\";\r\n              }\r\n            }\r\n          }\r\n        }\r\n\r\n        return { label: \"Popolarita\", value: text, status: status, hint: hint, arrow: arrow, suffix: \"\" };\r\n      }\r\n\r\n      function getRegionDirection(guessRegion, targetRegion) {\r\n        if (guessRegion === \"Estero\" && targetRegion !== \"Estero\") {\r\n          return { arrow: ARROWS.right, suffix: \"\ud83c\uddee\ud83c\uddf9\" };\r\n        }\r\n\r\n        if (targetRegion === \"Estero\" && guessRegion !== \"Estero\") {\r\n          return { arrow: ARROWS.right, suffix: \"\ud83c\udf0d\" };\r\n        }\r\n\r\n        const guessCoords = regionCoords[guessRegion];\r\n        const targetCoords = regionCoords[targetRegion];\r\n        if (!guessCoords || !targetCoords) return null;\r\n\r\n        const latDiff = targetCoords.lat - guessCoords.lat;\r\n        const lonDiff = targetCoords.lon - guessCoords.lon;\r\n        const threshold = 0.8;\r\n\r\n        if (Math.abs(latDiff) > threshold) {\r\n          return { arrow: latDiff > 0 ? ARROWS.up : ARROWS.down, suffix: \"\" };\r\n        }\r\n        return { arrow: lonDiff > 0 ? ARROWS.right : ARROWS.left, suffix: \"\" };\r\n      }\r\n\r\n      function buildCityTrait(guessArtist, targetArtist) {\r\n        let status = \"wrong\";\r\n        let value = guessArtist.city || \"N\/D\";\r\n        let hint = \"Regione diversa.\";\r\n        let arrow = \"\";\r\n        let suffix = \"\";\r\n\r\n        if (guessArtist.city === targetArtist.city) {\r\n          status = \"correct\";\r\n          hint = \"Stessa citta.\";\r\n        } else if (guessArtist.region === targetArtist.region) {\r\n          status = \"close\";\r\n          hint = \"Stessa regione.\";\r\n        } else if (guessArtist.region === \"Estero\") {\r\n          const direction = getRegionDirection(guessArtist.region, targetArtist.region);\r\n          if (direction) {\r\n            arrow = direction.arrow;\r\n            suffix = direction.suffix;\r\n          }\r\n          hint = targetArtist.region !== \"Estero\" ? \"Il target e in Italia.\" : \"Ancora estero.\";\r\n        } else if (targetArtist.region === \"Estero\") {\r\n          const direction = getRegionDirection(guessArtist.region, targetArtist.region);\r\n          if (direction) {\r\n            arrow = direction.arrow;\r\n            suffix = direction.suffix;\r\n          }\r\n          hint = \"Il target e nato all'estero.\";\r\n        } else {\r\n          const direction = getRegionDirection(guessArtist.region, targetArtist.region);\r\n          if (direction) {\r\n            arrow = direction.arrow;\r\n            suffix = direction.suffix;\r\n            hint = \"Direzione corretta indicata.\";\r\n          }\r\n        }\r\n\r\n        return { label: \"Citta\", value: value, status: status, hint: hint, arrow: arrow, suffix: suffix };\r\n      }\r\n\r\n      function buildDebutTrait(guessArtist, targetArtist) {\r\n        let status = \"wrong\";\r\n        let value = String(guessArtist.debutYear || \"N\/D\");\r\n        let hint = \"Fuori range.\";\r\n        let arrow = \"\";\r\n        const diff = guessArtist.debutYear - targetArtist.debutYear;\r\n\r\n        if (diff === 0) {\r\n          status = \"correct\";\r\n          hint = \"Anno esatto.\";\r\n        } else {\r\n          if (Math.abs(diff) <= 5) {\r\n            status = \"close\";\r\n            hint = \"Molto vicino.\";\r\n          }\r\n          arrow = targetArtist.debutYear > guessArtist.debutYear ? ARROWS.up : ARROWS.down;\r\n        }\r\n\r\n        return { label: \"Debutto\", value: value, status: status, hint: hint, arrow: arrow, suffix: \"\" };\r\n      }\r\n\r\n      function buildSimpleTrait(label, guessValue, targetValue, formatFn) {\r\n        const status = normalize(guessValue) === normalize(targetValue) ? \"correct\" : \"wrong\";\r\n        return {\r\n          label: label,\r\n          value: formatFn ? formatFn(guessValue) : (guessValue || \"N\/D\"),\r\n          status: status,\r\n          hint: status === \"correct\" ? \"Match.\" : \"Non coincide.\",\r\n          arrow: \"\",\r\n          suffix: \"\"\r\n        };\r\n      }\r\n\r\n      function buildTraits(guessArtist, targetArtist) {\r\n        return [\r\n          buildCityTrait(guessArtist, targetArtist),\r\n          buildDebutTrait(guessArtist, targetArtist),\r\n          buildSimpleTrait(\"Tipo\", guessArtist.members, targetArtist.members),\r\n          buildSimpleTrait(\"Voce\", guessArtist.gender, targetArtist.gender, formatGenderValue),\r\n          buildPopularityTrait(guessArtist, targetArtist)\r\n        ];\r\n      }\r\n\r\n      function getHeatScore(traits, solved) {\r\n        return Math.min(99, traits.reduce((total, trait) => {\r\n          if (trait.status === \"correct\") return total + 20;\r\n          if (trait.status === \"close\") return total + 12;\r\n          return total + 5;\r\n        }, solved ? 8 : 0));\r\n      }\r\n\r\n      function buildResultEntry(guessArtist, targetArtist, meta) {\r\n        const traits = buildTraits(guessArtist, targetArtist);\r\n        const solved = guessArtist.id === targetArtist.id;\r\n        const kind = meta.kind || \"guess\";\r\n        return {\r\n          guessArtist: guessArtist,\r\n          traits: traits,\r\n          solved: solved,\r\n          heat: getHeatScore(traits, solved),\r\n          kind: kind,\r\n          label: meta.label || \"Tentativo\",\r\n          subcopy: meta.subcopy || \"\",\r\n          spotifyId: meta.spotifyId || (solved ? guessArtist.spotifyId : \"\"),\r\n          tip: meta.tip || (solved ? guessArtist.tip : \"\")\r\n        };\r\n      }\r\n\r\n      function getArtistInitials(name) {\r\n        const parts = String(name || \"\").trim().split(\/\\s+\/).filter(Boolean);\r\n        if (!parts.length) return \"BM\";\r\n        return parts.slice(0, 2).map((part) => part.charAt(0)).join(\"\");\r\n      }\r\n\r\n      function persistSpotifyThumbnailUrl(spotifyId, thumbnailUrl) {\r\n        if (!spotifyId || !thumbnailUrl) return;\r\n        try {\r\n          const storedThumbs = JSON.parse(window.localStorage.getItem(spotifyThumbStorageKey) || \"{}\");\r\n          storedThumbs[spotifyId] = thumbnailUrl;\r\n          window.localStorage.setItem(spotifyThumbStorageKey, JSON.stringify(storedThumbs));\r\n        } catch (_) {}\r\n      }\r\n\r\n      function clearSpotifyThumbnailUrl(spotifyId) {\r\n        if (!spotifyId) return;\r\n        spotifyThumbCache.delete(spotifyId);\r\n        spotifyThumbRequests.delete(spotifyId);\r\n        try {\r\n          const storedThumbs = JSON.parse(window.localStorage.getItem(spotifyThumbStorageKey) || \"{}\");\r\n          delete storedThumbs[spotifyId];\r\n          window.localStorage.setItem(spotifyThumbStorageKey, JSON.stringify(storedThumbs));\r\n        } catch (_) {}\r\n      }\r\n\r\n      async function getSpotifyThumbnailUrl(spotifyId) {\r\n        if (!spotifyId) return \"\";\r\n        if (spotifyThumbCache.has(spotifyId)) {\r\n          return spotifyThumbCache.get(spotifyId);\r\n        }\r\n        if (spotifyThumbRequests.has(spotifyId)) {\r\n          return spotifyThumbRequests.get(spotifyId);\r\n        }\r\n\r\n        const request = (async function () {\r\n          const sources = [\r\n            \"https:\/\/open.spotify.com\/oembed?url=\" + encodeURIComponent(\"https:\/\/open.spotify.com\/artist\/\" + spotifyId),\r\n            \"https:\/\/open.spotify.com\/oembed?url=\" + encodeURIComponent(\"spotify:artist:\" + spotifyId)\r\n          ];\r\n\r\n          for (const source of sources) {\r\n            try {\r\n              const response = await fetch(source, { credentials: \"omit\" });\r\n              if (!response.ok) continue;\r\n              const payload = await response.json();\r\n              const thumbnailUrl = payload && payload.thumbnail_url ? String(payload.thumbnail_url) : \"\";\r\n              if (thumbnailUrl) {\r\n                spotifyThumbCache.set(spotifyId, thumbnailUrl);\r\n                persistSpotifyThumbnailUrl(spotifyId, thumbnailUrl);\r\n                return thumbnailUrl;\r\n              }\r\n            } catch (_) {}\r\n          }\r\n\r\n          return \"\";\r\n        })().finally(function () {\r\n          spotifyThumbRequests.delete(spotifyId);\r\n        });\r\n\r\n        spotifyThumbRequests.set(spotifyId, request);\r\n        return request;\r\n      }\r\n\r\n      function buildArtistCover(artist) {\r\n        const cover = document.createElement(\"div\");\r\n        cover.className = \"guess-cover\";\r\n\r\n        const fallback = document.createElement(\"span\");\r\n        fallback.className = \"guess-cover-fallback\";\r\n        fallback.textContent = getArtistInitials(artist.name);\r\n        cover.appendChild(fallback);\r\n\r\n        if (artist.spotifyId) {\r\n          getSpotifyThumbnailUrl(artist.spotifyId).then((thumbnailUrl) => {\r\n            if (!thumbnailUrl) return;\r\n            const image = document.createElement(\"img\");\r\n            image.alt = artist.name;\r\n            image.loading = \"eager\";\r\n            image.decoding = \"async\";\r\n            image.referrerPolicy = \"no-referrer\";\r\n\r\n            function applyThumbnail() {\r\n              cover.replaceChildren(image);\r\n            }\r\n\r\n            function handleThumbnailError() {\r\n              clearSpotifyThumbnailUrl(artist.spotifyId);\r\n            }\r\n\r\n            image.addEventListener(\"error\", handleThumbnailError, { once: true });\r\n            image.addEventListener(\"load\", applyThumbnail, { once: true });\r\n            image.src = thumbnailUrl;\r\n\r\n            if (image.complete) {\r\n              if (image.naturalWidth > 0) {\r\n                applyThumbnail();\r\n              } else {\r\n                handleThumbnailError();\r\n              }\r\n            }\r\n          });\r\n        }\r\n\r\n        return cover;\r\n      }\r\n\r\n      function renderModeCopy() {\r\n        const config = modeConfig[app.mode];\r\n        elements.input.placeholder = config.inputPlaceholder;\r\n        elements.submitButton.textContent = config.submitLabel;\r\n      }\r\n\r\n      function renderAttemptsCard() {\r\n        const state = getActiveState();\r\n        const attemptsLeft = Math.max(0, state.maxAttempts - state.attempts);\r\n        elements.attemptsCard.textContent = String(attemptsLeft) + \" \" + (attemptsLeft === 1 ? \"TENTATIVO\" : \"TENTATIVI\");\r\n      }\r\n\r\n      function renderActionButton() {\r\n        if (app.mode === \"classic\") {\r\n          elements.modeActionButton.classList.add(\"hidden\");\r\n          elements.dailyStreakCard.classList.remove(\"hidden\");\r\n          loadClassicStreakStatus();\r\n          return;\r\n        }\r\n\r\n        const config = modeConfig[app.mode];\r\n        elements.dailyStreakCard.classList.add(\"hidden\");\r\n        elements.modeActionButton.classList.remove(\"hidden\");\r\n        elements.modeActionButton.textContent = config.actionLabel;\r\n        elements.modeActionButton.disabled = false;\r\n      }\r\n\r\n      function renderTabs() {\r\n        elements.tabs.forEach((tab) => {\r\n          tab.classList.toggle(\"is-active\", tab.dataset.mode === app.mode);\r\n        });\r\n      }\r\n\r\n      function renderRankedToggle() {\r\n        if (!elements.rankedModeButton) return;\r\n        elements.rankedModeButton.textContent = \"Classificata\";\r\n        elements.rankedModeButton.classList.toggle(\"is-active\", isRankedMode());\r\n      }\r\n\r\n      function renderBranding() {\r\n        if (!elements.topLogo) return;\r\n\r\n        const rankedActive = isRankedMode();\r\n        const nextSrc = rankedActive ? RANKED_LOGO_URL : CLASSIC_LOGO_URL;\r\n        const nextAlt = rankedActive ? \"Bulldogle Ranked\" : \"Bulldogle Classico\";\r\n\r\n        if (elements.topLogo.getAttribute(\"src\") !== nextSrc) {\r\n          elements.topLogo.setAttribute(\"src\", nextSrc);\r\n        }\r\n\r\n        elements.topLogo.setAttribute(\"alt\", nextAlt);\r\n        appRoot.classList.toggle(\"is-ranked-mode\", rankedActive);\r\n        document.body.classList.toggle(\"bulldogle-ranked-mode-active\", rankedActive);\r\n        document.documentElement.classList.toggle(\"bulldogle-ranked-mode-active\", rankedActive);\r\n      }\r\n\r\n      function renderPanels() {\r\n        const rankedActive = isRankedMode();\r\n        elements.standardGamePanel.classList.toggle(\"hidden\", rankedActive);\r\n        elements.mobileRankedGamePanel.classList.toggle(\"hidden\", !rankedActive);\r\n        syncHelpPanelPlacement();\r\n      }\r\n\r\n      function buildSpotifyEmbed(spotifyId) {\r\n        if (!spotifyId) return null;\r\n        const wrap = document.createElement(\"div\");\r\n        wrap.className = \"guess-spotify\";\r\n        const iframe = document.createElement(\"iframe\");\r\n        iframe.src = \"https:\/\/open.spotify.com\/embed\/artist\/\" + spotifyId + \"?utm_source=generator&theme=0\";\r\n        iframe.allow = \"autoplay; clipboard-write; encrypted-media; fullscreen; picture-in-picture\";\r\n        iframe.loading = \"lazy\";\r\n        wrap.appendChild(iframe);\r\n        return wrap;\r\n      }\r\n\r\n      function buildArtistTip(tip) {\r\n        const cleanTip = String(tip || \"\").trim();\r\n        if (!cleanTip) return null;\r\n\r\n        const copy = document.createElement(\"p\");\r\n        copy.className = \"guess-tip\";\r\n        copy.textContent = cleanTip;\r\n        return copy;\r\n      }\r\n\r\n      function buildResultCard(result) {\r\n        const article = document.createElement(\"article\");\r\n        article.className = \"guess-card\";\r\n        if (result.solved) article.classList.add(\"is-solved\");\r\n        if (result.kind === \"answer\") article.classList.add(\"is-answer\");\r\n        if (result.kind === \"auto\") article.classList.add(\"is-hint\");\r\n\r\n        const top = document.createElement(\"div\");\r\n        top.className = \"guess-top\";\r\n\r\n        const cover = buildArtistCover(result.guessArtist);\r\n        const copy = document.createElement(\"div\");\r\n        copy.className = \"guess-copy\";\r\n\r\n        const badge = document.createElement(\"span\");\r\n        badge.className = \"guess-badge\";\r\n        badge.textContent = result.label;\r\n\r\n        const name = document.createElement(\"h4\");\r\n        name.className = \"guess-name\";\r\n        name.textContent = result.guessArtist.name;\r\n\r\n        copy.appendChild(badge);\r\n        copy.appendChild(name);\r\n\r\n        if (result.subcopy) {\r\n          const sub = document.createElement(\"p\");\r\n          sub.className = \"guess-sub\";\r\n          sub.textContent = result.subcopy;\r\n          copy.appendChild(sub);\r\n        }\r\n\r\n        top.appendChild(cover);\r\n        top.appendChild(copy);\r\n\r\n        const traits = document.createElement(\"div\");\r\n        traits.className = \"traits\";\r\n\r\n        result.traits.forEach((trait) => {\r\n          const traitNode = document.createElement(\"div\");\r\n          traitNode.className = \"trait is-\" + trait.status;\r\n\r\n          const label = document.createElement(\"span\");\r\n          label.className = \"trait-label\";\r\n          label.textContent = trait.label;\r\n\r\n        const value = document.createElement(\"span\");\r\n        value.className = \"trait-value\";\r\n        const valueText = document.createElement(\"span\");\r\n        valueText.className = \"trait-value-text\";\r\n        valueText.textContent = trait.value;\r\n        value.appendChild(valueText);\r\n\r\n        if (trait.arrow) {\r\n          const arrow = document.createElement(\"span\");\r\n          arrow.className = \"trait-arrow\";\r\n          arrow.textContent = trait.arrow;\r\n          value.appendChild(arrow);\r\n        }\r\n\r\n        if (trait.suffix) {\r\n          const suffix = document.createElement(\"span\");\r\n          suffix.className = \"trait-suffix\";\r\n          suffix.textContent = trait.suffix;\r\n          value.appendChild(suffix);\r\n        }\r\n\r\n        traitNode.appendChild(label);\r\n        traitNode.appendChild(value);\r\n        traits.appendChild(traitNode);\r\n      });\r\n\r\n        article.appendChild(top);\r\n        article.appendChild(traits);\r\n        const spotifyEmbed = buildSpotifyEmbed(result.spotifyId);\r\n        if (spotifyEmbed) {\r\n          article.appendChild(spotifyEmbed);\r\n        }\r\n        if (result.solved && result.tip) {\r\n          const tipNode = buildArtistTip(result.tip);\r\n          if (tipNode) {\r\n            article.appendChild(tipNode);\r\n          }\r\n        }\r\n        return article;\r\n      }\r\n\r\n      function renderResults() {\r\n        const state = getActiveState();\r\n        const results = state.results || [];\r\n        elements.resultsList.innerHTML = \"\";\r\n\r\n        if (!results.length) {\r\n          const empty = document.createElement(\"div\");\r\n          empty.className = \"empty-state\";\r\n          empty.textContent = \"Nessun tentativo ancora.\";\r\n          elements.resultsList.appendChild(empty);\r\n          return;\r\n        }\r\n\r\n        results.forEach((result) => {\r\n          elements.resultsList.appendChild(buildResultCard(result));\r\n        });\r\n      }\r\n\r\n      function renderInputState() {\r\n        const state = getActiveState();\r\n        disableGameInput(state.complete);\r\n        elements.inputLabel.textContent = \"inserisci un artista\";\r\n        elements.input.placeholder = app.mode === \"classic\" && state.complete ? \"Torna domani!\" : \"inserisci un artista\";\r\n      }\r\n\r\n      function renderApp() {\r\n        renderBranding();\r\n        renderTabs();\r\n        renderRankedToggle();\r\n        renderPanels();\r\n\r\n        if (isRankedMode()) {\r\n          renderRankedPanel();\r\n          hideSuggestions();\r\n          syncHelpToggleState();\r\n          return;\r\n        }\r\n\r\n        renderModeCopy();\r\n        renderAttemptsCard();\r\n        renderActionButton();\r\n        renderInputState();\r\n        renderResults();\r\n        hideSuggestions();\r\n        hideRankedSuggestions();\r\n        syncHelpToggleState();\r\n      }\r\n\r\n      function formatTime(totalSeconds) {\r\n        const safeTime = Math.max(0, totalSeconds);\r\n        const minutes = Math.floor(safeTime \/ 60);\r\n        const seconds = String(safeTime % 60).padStart(2, \"0\");\r\n        return minutes + \":\" + seconds;\r\n      }\r\n\r\n      function findArtistByName(name) {\r\n        const normalized = normalize(name);\r\n        return artists.find((artist) => normalize(artist.name) === normalized);\r\n      }\r\n\r\n      function buildSuggestionList(matches) {\r\n        elements.suggestions.innerHTML = \"\";\r\n        matches.forEach((artist) => {\r\n          const button = document.createElement(\"button\");\r\n          button.type = \"button\";\r\n          button.className = \"suggestion\";\r\n\r\n          const left = document.createElement(\"span\");\r\n          left.textContent = artist.name;\r\n          const right = document.createElement(\"small\");\r\n          right.textContent = artist.city + \" \/ \" + formatPopularityDisplay(artist);\r\n\r\n          button.appendChild(left);\r\n          button.appendChild(right);\r\n          button.addEventListener(\"click\", function () {\r\n            elements.input.value = artist.name;\r\n            hideSuggestions();\r\n            elements.input.focus();\r\n          });\r\n          elements.suggestions.appendChild(button);\r\n        });\r\n        if (matches.length) {\r\n          showSuggestions();\r\n          return;\r\n        }\r\n        hideSuggestions();\r\n      }\r\n\r\n      function updateSuggestions() {\r\n        const value = normalize(elements.input.value);\r\n        if (!value) {\r\n          hideSuggestions();\r\n          return;\r\n        }\r\n\r\n        if (getActiveState().complete) {\r\n          hideSuggestions();\r\n          return;\r\n        }\r\n\r\n        const guessedIds = getModeGuessedIds();\r\n        const matches = artists.filter((artist) => {\r\n          return normalize(artist.name).includes(value) && !guessedIds.has(artist.id);\r\n        }).slice(0, 8);\r\n\r\n        buildSuggestionList(matches);\r\n      }\r\n\r\n      function addClassicGuess(guessArtist, modeKey) {\r\n        const state = app.modes[modeKey];\r\n        const targetArtist = state.target;\r\n        const attemptNumber = state.attempts + 1;\r\n        const isSolved = guessArtist.id === targetArtist.id;\r\n\r\n        state.guessedIds.add(guessArtist.id);\r\n        state.attempts += 1;\r\n        state.results.unshift(buildResultEntry(guessArtist, targetArtist, {\r\n          label: \"Tentativo \" + attemptNumber,\r\n          spotifyId: isSolved ? targetArtist.spotifyId : \"\"\r\n        }));\r\n\r\n        if (isSolved) {\r\n          state.complete = true;\r\n          setMessage(\"Hai indovinato \" + targetArtist.name + \".\", \"success\");\r\n          if (modeKey === \"classic\") {\r\n            saveClassicState(\"won\");\r\n            syncClassicStreakResult(\"won\");\r\n          }\r\n        } else if (state.attempts >= state.maxAttempts) {\r\n          state.complete = true;\r\n          state.results.unshift(buildResultEntry(targetArtist, targetArtist, {\r\n            kind: \"answer\",\r\n            label: \"Artista corretto\",\r\n            spotifyId: targetArtist.spotifyId || \"\"\r\n          }));\r\n          setMessage(\"Tentativi finiti. L'artista era \" + targetArtist.name + \".\", \"error-final\");\r\n          if (modeKey === \"classic\") {\r\n            saveClassicState(\"lost\");\r\n            syncClassicStreakResult(\"lost\");\r\n          }\r\n        } else {\r\n          setMessage(\"\", \"\");\r\n          if (modeKey === \"classic\") {\r\n            saveClassicState(\"playing\");\r\n          }\r\n        }\r\n      }\r\n\r\n      function submitClassicGuess(modeKey) {\r\n        const state = app.modes[modeKey];\r\n        if (state.complete) return;\r\n\r\n        const guessArtist = findArtistByName(elements.input.value.trim());\r\n        if (!guessArtist) {\r\n          setMessage(\"Artista non trovato nella lista.\", \"error\");\r\n          return;\r\n        }\r\n\r\n        if (state.guessedIds.has(guessArtist.id)) {\r\n          setMessage(\"Hai gia provato questo artista.\", \"error\");\r\n          elements.input.value = \"\";\r\n          return;\r\n        }\r\n\r\n        addClassicGuess(guessArtist, modeKey);\r\n        elements.input.value = \"\";\r\n      }\r\n\r\n      function startPracticeRound() {\r\n        const currentRound = app.modes.practice.round + 1;\r\n        app.modes.practice = {\r\n          maxAttempts: 10,\r\n          attempts: 0,\r\n          round: currentRound,\r\n          guessedIds: new Set(),\r\n          results: [],\r\n          complete: false,\r\n          target: pickRandomArtist()\r\n        };\r\n        if (app.mode === \"practice\") {\r\n          setMessage(\"\", \"\");\r\n          renderApp();\r\n        }\r\n      }\r\n\r\n      function switchMode(nextMode) {\r\n        if (nextMode === app.mode) return;\r\n        const previousMode = app.mode;\r\n\r\n        if (previousMode !== \"ranked\") {\r\n          app.lastStandardMode = previousMode;\r\n        }\r\n\r\n        if (previousMode === \"ranked\" && nextMode !== \"ranked\") {\r\n          resetRankedState();\r\n        }\r\n\r\n        app.mode = nextMode;\r\n\r\n        if (nextMode !== \"ranked\") {\r\n          app.lastStandardMode = nextMode;\r\n        }\r\n\r\n        elements.input.value = \"\";\r\n        elements.mobileRankedInput.value = \"\";\r\n        hideSuggestions();\r\n        hideRankedSuggestions();\r\n        closeAllHelpPanels();\r\n        setMessage(\"\", \"\");\r\n        setRankedMessage(\"\", \"\");\r\n        renderApp();\r\n      }\r\n\r\n      elements.tabs.forEach((tab) => {\r\n        tab.addEventListener(\"click\", function () {\r\n          switchMode(tab.dataset.mode);\r\n        });\r\n      });\r\n\r\n      if (elements.rankedModeButton) {\r\n        elements.rankedModeButton.addEventListener(\"click\", function () {\r\n          switchMode(\"ranked\");\r\n        });\r\n      }\r\n\r\n      elements.helpToggle.addEventListener(\"click\", function () {\r\n        const panel = getCurrentHelpPanel();\r\n        if (!panel) return;\r\n\r\n        const shouldOpen = !panel.classList.contains(\"is-open\");\r\n        closeAllHelpPanels();\r\n\r\n        if (shouldOpen) {\r\n          panel.classList.add(\"is-open\");\r\n          panel.setAttribute(\"aria-hidden\", \"false\");\r\n        }\r\n\r\n        syncHelpToggleState();\r\n      });\r\n\r\n      elements.dailyStreakCard.addEventListener(\"click\", function (event) {\r\n        if (elements.dailyStreakCard.classList.contains(\"is-guest\")) {\r\n          event.preventDefault();\r\n          window.location.href = elements.dailyStreakCard.getAttribute(\"href\") || guestStreakLoginUrl;\r\n          return;\r\n        }\r\n\r\n        if (!elements.dailyStreakCard.classList.contains(\"is-guest\")) {\r\n          event.preventDefault();\r\n          event.stopPropagation();\r\n        }\r\n      });\r\n\r\n      elements.modeActionButton.addEventListener(\"click\", function () {\r\n        if (app.mode === \"practice\") {\r\n          startPracticeRound();\r\n        }\r\n      });\r\n\r\n      elements.guessForm.addEventListener(\"submit\", function (event) {\r\n        event.preventDefault();\r\n\r\n        if (app.mode === \"classic\") {\r\n          submitClassicGuess(\"classic\");\r\n        } else {\r\n          submitClassicGuess(\"practice\");\r\n        }\r\n\r\n        renderApp();\r\n      });\r\n\r\n      elements.mobileRankedSideActionButton.addEventListener(\"click\", function () {\r\n        handleRankedSideAction();\r\n      });\r\n\r\n      elements.mobileRankedGuessForm.addEventListener(\"submit\", function (event) {\r\n        event.preventDefault();\r\n        submitRankedGuess();\r\n        renderRankedPanel();\r\n      });\r\n\r\n      elements.input.addEventListener(\"input\", updateSuggestions);\r\n      elements.input.addEventListener(\"focus\", updateSuggestions);\r\n      elements.mobileRankedInput.addEventListener(\"input\", updateRankedSuggestions);\r\n      elements.mobileRankedInput.addEventListener(\"focus\", updateRankedSuggestions);\r\n\r\n      document.addEventListener(\"click\", function (event) {\r\n        if (!elements.suggestions.contains(event.target) && event.target !== elements.input) {\r\n          hideSuggestions();\r\n        }\r\n\r\n        if (!elements.mobileRankedSuggestions.contains(event.target) && event.target !== elements.mobileRankedInput) {\r\n          hideRankedSuggestions();\r\n        }\r\n      });\r\n\r\n      window.addEventListener(\"resize\", function () {\r\n        syncHelpPanelPlacement();\r\n        if (elements.suggestions.style.display === \"block\") {\r\n          positionSuggestions();\r\n        }\r\n        if (elements.mobileRankedSuggestions.style.display === \"block\") {\r\n          positionSuggestionsFor(elements.mobileRankedInput, elements.mobileRankedSuggestions);\r\n        }\r\n      });\r\n\r\n      window.addEventListener(\"scroll\", function () {\r\n        if (elements.suggestions.style.display === \"block\") {\r\n          positionSuggestions();\r\n        }\r\n        if (elements.mobileRankedSuggestions.style.display === \"block\") {\r\n          positionSuggestionsFor(elements.mobileRankedInput, elements.mobileRankedSuggestions);\r\n        }\r\n      }, true);\r\n\r\n      if (window.visualViewport) {\r\n        window.visualViewport.addEventListener(\"resize\", function () {\r\n          syncHelpPanelPlacement();\r\n          if (elements.suggestions.style.display === \"block\") {\r\n            positionSuggestions();\r\n          }\r\n          if (elements.mobileRankedSuggestions.style.display === \"block\") {\r\n            positionSuggestionsFor(elements.mobileRankedInput, elements.mobileRankedSuggestions);\r\n          }\r\n        });\r\n\r\n        window.visualViewport.addEventListener(\"scroll\", function () {\r\n          if (elements.suggestions.style.display === \"block\") {\r\n            positionSuggestions();\r\n          }\r\n          if (elements.mobileRankedSuggestions.style.display === \"block\") {\r\n            positionSuggestionsFor(elements.mobileRankedInput, elements.mobileRankedSuggestions);\r\n          }\r\n        });\r\n      }\r\n\r\n      syncHelpPanelPlacement();\r\n      loadClassicState();\r\n      renderApp();\r\n      if (!app.modes.classic.complete) {\r\n        setMessage(\"\", \"\");\r\n      }\r\n    })();\r\n  <\/script>\r\n<\/body>\r\n<\/html>\r\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-2690ce25 crew elementor-widget__width-initial e-transform elementor-widget elementor-widget-post-widget\" data-id=\"2690ce25\" data-element_type=\"widget\" data-e-type=\"widget\" data-settings=\"{&quot;posts_per_page&quot;:100,&quot;post_type&quot;:[&quot;page&quot;],&quot;nb_columns&quot;:&quot;1&quot;,&quot;_transform_translateX_effect&quot;:{&quot;unit&quot;:&quot;%&quot;,&quot;size&quot;:4,&quot;sizes&quot;:[]},&quot;_transform_translateX_effect_tablet&quot;:{&quot;unit&quot;:&quot;%&quot;,&quot;size&quot;:&quot;&quot;,&quot;sizes&quot;:[]},&quot;_transform_translateX_effect_mobile&quot;:{&quot;unit&quot;:&quot;%&quot;,&quot;size&quot;:&quot;&quot;,&quot;sizes&quot;:[]},&quot;_transform_translateY_effect&quot;:{&quot;unit&quot;:&quot;%&quot;,&quot;size&quot;:3,&quot;sizes&quot;:[]},&quot;_transform_translateY_effect_tablet&quot;:{&quot;unit&quot;:&quot;%&quot;,&quot;size&quot;:&quot;&quot;,&quot;sizes&quot;:[]},&quot;_transform_translateY_effect_mobile&quot;:{&quot;unit&quot;:&quot;%&quot;,&quot;size&quot;:&quot;&quot;,&quot;sizes&quot;:[]},&quot;classic_layout&quot;:&quot;grid&quot;,&quot;nb_columns_tablet&quot;:&quot;3&quot;,&quot;nb_columns_mobile&quot;:&quot;1&quot;,&quot;post_status&quot;:&quot;publish&quot;,&quot;pagination&quot;:&quot;none&quot;}\" data-widget_type=\"post-widget.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<div class=\"post-container none classic\" data-total-post=\"2\" ><div class=\"post-container-inner\"><div class=\"elementor-grid\" ><article class=\"post-wrapper\"  data-post-id=\"8846\" ><div class=\"post-image\"><a href=\"https:\/\/bulldogmusik.it\/en\/bulldogfeat-ita\/\" ><img loading=\"lazy\" decoding=\"async\" width=\"1366\" height=\"768\" src=\"https:\/\/bulldogmusik.it\/wp-content\/uploads\/2026\/05\/BulldogFeat-Logo-1.png\" class=\"bpfwe-post-thumbnail\" alt=\"\" data-bpfwe-src=\"https:\/\/bulldogmusik.it\/wp-content\/uploads\/2026\/05\/BulldogFeat-Logo-1.png\" loading=\"lazy\" \/><\/a><\/div><div class=\"inner-content\"><div class=\"post-content elementor-repeater-item-aff2fa8\"><p>Indovina in rapper in meno di 5 tentativi, ogni tentativo scopri altre collaborazioni....<\/p><\/div><\/div><\/article><article class=\"post-wrapper\"  data-post-id=\"8209\" ><div class=\"post-image\"><a href=\"https:\/\/bulldogmusik.it\/en\/bulldogmatch-ita\/\" ><img loading=\"lazy\" decoding=\"async\" width=\"1366\" height=\"768\" src=\"https:\/\/bulldogmusik.it\/wp-content\/uploads\/2026\/05\/BulldogMatch-New.png\" class=\"bpfwe-post-thumbnail\" alt=\"\" data-bpfwe-src=\"https:\/\/bulldogmusik.it\/wp-content\/uploads\/2026\/05\/BulldogMatch-New.png\" loading=\"lazy\" \/><\/a><\/div><div class=\"inner-content\"><div class=\"post-content elementor-repeater-item-aff2fa8\"><p>Indovina in rapper in meno di 20 tentativi, ogni tentativo scopri diverse affinit\u00e0....<\/p><\/div><\/div><\/article><\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\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\t\t<\/div>\n\t\t<div id=\"e-n-tab-content-2217977882\" role=\"tabpanel\" aria-labelledby=\"tab-speciale\" data-tab-index=\"2\" style=\"--n-tabs-title-order: 2;\" class=\" elementor-element elementor-element-6652153b e-con-full e-flex wcf-starter-animations-none e-con e-child\" data-id=\"6652153b\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t<div class=\"elementor-element elementor-element-43598ae1 e-grid e-con-boxed wcf-starter-animations-none e-con e-child\" data-id=\"43598ae1\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-8a05bb4 elementor-widget__width-initial e-transform elementor-widget elementor-widget-html\" data-id=\"8a05bb4\" data-element_type=\"widget\" data-e-type=\"widget\" data-settings=\"{&quot;_transform_translateX_effect&quot;:{&quot;unit&quot;:&quot;px&quot;,&quot;size&quot;:-4,&quot;sizes&quot;:[]},&quot;_transform_translateX_effect_tablet&quot;:{&quot;unit&quot;:&quot;px&quot;,&quot;size&quot;:&quot;&quot;,&quot;sizes&quot;:[]},&quot;_transform_translateX_effect_mobile&quot;:{&quot;unit&quot;:&quot;px&quot;,&quot;size&quot;:&quot;&quot;,&quot;sizes&quot;:[]},&quot;_transform_translateY_effect&quot;:{&quot;unit&quot;:&quot;px&quot;,&quot;size&quot;:&quot;&quot;,&quot;sizes&quot;:[]},&quot;_transform_translateY_effect_tablet&quot;:{&quot;unit&quot;:&quot;px&quot;,&quot;size&quot;:&quot;&quot;,&quot;sizes&quot;:[]},&quot;_transform_translateY_effect_mobile&quot;:{&quot;unit&quot;:&quot;px&quot;,&quot;size&quot;:&quot;&quot;,&quot;sizes&quot;:[]}}\" data-widget_type=\"html.default\">\n\t\t\t\t\t<!DOCTYPE html>\r\n<html lang=\"it\">\r\n<head>\r\n  <meta charset=\"UTF-8\">\r\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\r\n  <title>Bulldogle Ranked Demo<\/title>\r\n  <link rel=\"preconnect\" href=\"https:\/\/fonts.googleapis.com\">\r\n  <link rel=\"preconnect\" href=\"https:\/\/fonts.gstatic.com\" crossorigin>\r\n  <link href=\"https:\/\/fonts.googleapis.com\/css2?family=Instrument+Sans:wght@400;500;600;700;800;900&family=Space+Grotesk:wght@500;700&display=swap\" rel=\"stylesheet\">\r\n  <style>\r\n    .ranked-demo-app {\r\n      --bg: #000;\r\n      --panel: #070707;\r\n      --panel-2: #0b0b0b;\r\n      --line: rgba(255, 255, 255, 0.08);\r\n      --ranked-accent-rgb: 149, 40, 0;\r\n      --line-strong: rgba(var(--ranked-accent-rgb), 0.28);\r\n      --line-faint: rgba(255, 255, 255, 0.05);\r\n      --white: #f7f4ef;\r\n      --copy: rgba(247, 244, 239, 0.76);\r\n      --copy-soft: rgba(247, 244, 239, 0.56);\r\n      --copy-faint: rgba(247, 244, 239, 0.34);\r\n      --ranked-accent: #952800;\r\n      --success: #7dc56a;\r\n      --warning: var(--ranked-accent);\r\n      --danger: var(--ranked-accent);\r\n      --radius-lg: 18px;\r\n      --radius-md: 14px;\r\n      --ease: 220ms cubic-bezier(.2,.9,.2,1);\r\n    }\r\n\r\n    .ranked-demo-app, .ranked-demo-app * {\r\n      box-sizing: border-box;\r\n    }\r\n\r\n    .ranked-demo-app {\r\n      margin: 0;\r\n      min-height: 100%;\r\n      background: var(--bg);\r\n      color: var(--white);\r\n      font-family: \"Instrument Sans\", system-ui, sans-serif;\r\n      overflow-x: hidden;\r\n    }\r\n\r\n    .ranked-demo-app button, .ranked-demo-app input, .ranked-demo-app iframe {\r\n      font: inherit;\r\n    }\r\n\r\n    .ranked-demo-app {\r\n      width: min(760px, calc(100vw - 20px));\r\n      margin: 0 auto;\r\n      padding: 18px 0 24px;\r\n    }\r\n\r\n    .ranked-demo-app .app-shell {\r\n      position: relative;\r\n      isolation: isolate;\r\n      padding: 14px;\r\n      border: 1px solid var(--line);\r\n      border-radius: 22px;\r\n      background: linear-gradient(180deg, rgba(14, 14, 14, 0.98), rgba(7, 7, 7, 0.98));\r\n      overflow: visible;\r\n      box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.03);\r\n    }\r\n\r\n    .ranked-demo-app .app-shell::after {\r\n      content: \"\";\r\n      position: absolute;\r\n      inset: 0;\r\n      border-radius: inherit;\r\n      background-image: url(\"data:image\/svg+xml,%3Csvg%20xmlns='http:\/\/www.w3.org\/2000\/svg'%20viewBox='0%200%20180%20180'%3E%3Cfilter%20id='n'%3E%3CfeTurbulence%20type='fractalNoise'%20baseFrequency='.9'%20numOctaves='3'%20stitchTiles='stitch'\/%3E%3CfeColorMatrix%20type='saturate'%20values='0'\/%3E%3CfeComponentTransfer%3E%3CfeFuncA%20type='table'%20tableValues='0%20.58'\/%3E%3C\/feComponentTransfer%3E%3C\/filter%3E%3Crect%20width='180'%20height='180'%20filter='url(%23n)'%20opacity='1'\/%3E%3C\/svg%3E\");\r\n      background-size: 180px 180px;\r\n      mix-blend-mode: overlay;\r\n      opacity: 0.1;\r\n      pointer-events: none;\r\n    }\r\n\r\n    .ranked-demo-app .app-shell > * {\r\n      position: relative;\r\n      z-index: 1;\r\n    }\r\n\r\n    .ranked-demo-app .topbar {\r\n      display: flex;\r\n      flex-direction: column;\r\n      align-items: center;\r\n      gap: 0;\r\n      padding: 10px 8px 14px;\r\n    }\r\n\r\n    .ranked-demo-app .top-logo {\r\n      display: block;\r\n      width: min(320px, 58vw);\r\n      height: auto;\r\n    }\r\n\r\n    .ranked-demo-app .shell {\r\n      margin-top: 0;\r\n      padding-top: 14px;\r\n      border-top: 1px solid var(--line);\r\n    }\r\n\r\n    .ranked-demo-app .controls-shell {\r\n      margin-top: 0;\r\n      padding: 14px 0;\r\n      border-top: 1px solid var(--line);\r\n    }\r\n\r\n    .ranked-demo-app .controls-inner {\r\n      display: grid;\r\n      grid-template-columns: repeat(3, minmax(0, 1fr));\r\n      gap: 8px;\r\n    }\r\n\r\n    .ranked-demo-app .game-shell {\r\n      position: relative;\r\n      padding: 2px 0 6px;\r\n      overflow: visible;\r\n    }\r\n\r\n    .ranked-demo-app .tab, .ranked-demo-app .ghost-button, .ranked-demo-app .button, .ranked-demo-app .secondary-button {\r\n      display: inline-flex;\r\n      align-items: center;\r\n      justify-content: center;\r\n      min-height: 32px;\r\n      padding: 0 13px;\r\n      border-radius: 999px;\r\n      border: 1px solid var(--line);\r\n      background: rgba(255, 255, 255, 0.03);\r\n      color: var(--white);\r\n      font-size: 11px;\r\n      font-weight: 900 !important;\r\n      cursor: pointer;\r\n      transition: transform var(--ease), border-color var(--ease), background var(--ease), color var(--ease), opacity var(--ease);\r\n    }\r\n\r\n    .ranked-demo-app .controls-inner .tab, .ranked-demo-app .controls-inner .ghost-button {\r\n      width: 100%;\r\n      min-width: 0;\r\n      min-height: 36px;\r\n      padding: 0 8px;\r\n      font-size: 12px;\r\n    }\r\n\r\n    .ranked-demo-app .tab.is-active, .ranked-demo-app .ghost-button.is-active {\r\n      border-color: var(--line-strong);\r\n      background: rgba(var(--ranked-accent-rgb), 0.12);\r\n    }\r\n\r\n    .ranked-demo-app .button, .ranked-demo-app .secondary-button {\r\n      min-width: 152px;\r\n      min-height: 56px;\r\n      padding: 0 22px;\r\n      border-radius: 12px;\r\n      background: var(--ranked-accent);\r\n      border-color: var(--ranked-accent);\r\n      color: #111;\r\n      font-size: 15px;\r\n      font-weight: 900 !important;\r\n      letter-spacing: 0;\r\n      text-transform: uppercase;\r\n      box-shadow: none;\r\n    }\r\n\r\n    .ranked-demo-app .attempts-card {\r\n      min-width: 152px;\r\n      min-height: 56px;\r\n      padding: 0 22px;\r\n      border-radius: 12px;\r\n      font-family: \"Instrument Sans\", system-ui, sans-serif;\r\n      font-size: 15px;\r\n      line-height: 1;\r\n      font-weight: 900 !important;\r\n      letter-spacing: 0;\r\n      text-transform: uppercase;\r\n      font-variation-settings: \"wght\" 700;\r\n      box-shadow: none;\r\n    }\r\n\r\n    .ranked-demo-app #rankedSubmitButton.button, .ranked-demo-app #rankedSideActionButton.secondary-button.is-primary {\r\n      background: var(--ranked-accent) !important;\r\n      background-image: none !important;\r\n      border-color: var(--ranked-accent) !important;\r\n      color: #111 !important;\r\n      box-shadow: none !important;\r\n    }\r\n\r\n    .ranked-demo-app .button:hover, .ranked-demo-app .secondary-button:hover {\r\n      background: #fff;\r\n      border-color: #fff;\r\n      color: #111;\r\n    }\r\n\r\n    .ranked-demo-app #rankedSubmitButton.button:hover, .ranked-demo-app #rankedSideActionButton.secondary-button.is-primary:hover {\r\n      background: #fff !important;\r\n      background-image: none !important;\r\n      border-color: #fff !important;\r\n      color: #111 !important;\r\n    }\r\n\r\n    .ranked-demo-app .tab:hover, .ranked-demo-app .ghost-button:hover, .ranked-demo-app .button:hover, .ranked-demo-app .secondary-button:hover, .ranked-demo-app .suggestion:hover, .ranked-demo-app .board-row:hover {\r\n      transform: translateY(-1px);\r\n    }\r\n\r\n    .ranked-demo-app .button:disabled, .ranked-demo-app .secondary-button:disabled {\r\n      cursor: not-allowed;\r\n      opacity: 0.45;\r\n      transform: none;\r\n    }\r\n\r\n    .ranked-demo-app .help-panel {\r\n      max-height: 0;\r\n      overflow: hidden;\r\n      padding-bottom: 0;\r\n      border-bottom: 1px solid var(--line);\r\n      transition: max-height 240ms ease, margin 240ms ease, padding-bottom 240ms ease, border-color 240ms ease;\r\n      margin: 0 0 12px;\r\n    }\r\n\r\n    .ranked-demo-app .help-panel.is-open {\r\n      max-height: 1200px;\r\n      padding-bottom: 12px;\r\n      margin: 0 0 12px;\r\n    }\r\n\r\n    .ranked-demo-app .help-panel-mobile-slot {\r\n      display: none;\r\n    }\r\n\r\n    .ranked-demo-app .help-grid {\r\n      display: grid;\r\n      grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));\r\n      gap: 10px;\r\n    }\r\n\r\n    .ranked-demo-app .help-card {\r\n      min-height: 100%;\r\n      padding: 12px 13px;\r\n      border: 1px solid var(--line);\r\n      border-radius: 12px;\r\n      background: rgba(255, 255, 255, 0.03);\r\n    }\r\n\r\n    .ranked-demo-app .help-card strong {\r\n      display: block;\r\n      margin-bottom: 8px;\r\n      font-size: 13px;\r\n    }\r\n\r\n    .ranked-demo-app .help-card span {\r\n      display: block;\r\n      color: var(--copy-soft);\r\n      font-size: 12px;\r\n      line-height: 1.45;\r\n    }\r\n\r\n    .ranked-demo-app .meta-grid {\r\n      display: grid;\r\n      grid-template-columns: repeat(3, minmax(0, 1fr));\r\n      gap: 10px;\r\n      margin-bottom: 12px;\r\n    }\r\n\r\n    @media (min-width: 721px) {\r\n      .ranked-demo-app .meta-grid {\r\n        padding-bottom: 14px;\r\n        border-bottom: 1px solid var(--line);\r\n      }\r\n\r\n      .ranked-demo-app #rankedHelpPanel {\r\n        border-bottom-color: transparent;\r\n      }\r\n\r\n      .ranked-demo-app #rankedHelpPanel.is-open {\r\n        border-bottom-color: var(--line);\r\n      }\r\n    }\r\n\r\n    .ranked-demo-app .meta-card {\r\n      min-height: 74px;\r\n      padding: 12px 14px;\r\n      border: 1px solid var(--line);\r\n      border-radius: 16px;\r\n      background: rgba(255, 255, 255, 0.03);\r\n      display: flex;\r\n      flex-direction: column;\r\n      justify-content: space-between;\r\n      gap: 8px;\r\n      text-align: left;\r\n    }\r\n\r\n    .ranked-demo-app .meta-card.is-accent {\r\n      border-color: rgba(var(--ranked-accent-rgb), 0.24);\r\n      background: rgba(var(--ranked-accent-rgb), 0.08);\r\n    }\r\n\r\n    .ranked-demo-app .ranked-meta-button {\r\n      width: 100%;\r\n      min-height: 74px;\r\n      padding: 12px 14px;\r\n      border: 1px solid var(--line);\r\n      border-radius: 16px;\r\n      background: rgba(255, 255, 255, 0.03);\r\n      color: var(--white);\r\n      display: flex;\r\n      align-items: center;\r\n      justify-content: center;\r\n      text-align: center;\r\n      font-size: 14px;\r\n      font-weight: 900 !important;\r\n      cursor: pointer;\r\n      transition: transform var(--ease), border-color var(--ease), background var(--ease), color var(--ease);\r\n    }\r\n\r\n    .ranked-demo-app .ranked-meta-button.is-active {\r\n      border-color: var(--line-strong);\r\n      background: rgba(var(--ranked-accent-rgb), 0.12);\r\n    }\r\n\r\n    .ranked-demo-app .ranked-meta-button:hover {\r\n      transform: translateY(-1px);\r\n    }\r\n\r\n    .ranked-demo-app .meta-card,\r\n    .ranked-demo-app .ranked-meta-button {\r\n      min-height: 74px !important;\r\n      height: 74px !important;\r\n      padding: 12px 14px !important;\r\n      border-radius: 16px !important;\r\n      font-size: 15px !important;\r\n      line-height: 1.1 !important;\r\n      text-transform: uppercase !important;\r\n    }\r\n\r\n    .ranked-demo-app .meta-label,\r\n    .ranked-demo-app .meta-value {\r\n      line-height: 1.1 !important;\r\n    }\r\n\r\n    @media (max-width: 720px) {\r\n      .ranked-demo-app .top-logo {\r\n        margin-top: 14px !important;\r\n      }\r\n\r\n      .ranked-demo-app .controls-inner {\r\n        margin-bottom: 18px !important;\r\n      }\r\n    }\r\n\r\n    .ranked-demo-app .meta-label {\r\n      display: block;\r\n      color: var(--copy-soft);\r\n      font-size: 11px;\r\n      font-weight: 900 !important;\r\n      letter-spacing: 0.12em;\r\n      text-transform: uppercase;\r\n    }\r\n\r\n    .ranked-demo-app .meta-value {\r\n      display: block;\r\n      font-family: \"Space Grotesk\", sans-serif;\r\n      font-size: clamp(24px, 3.2vw, 30px);\r\n      line-height: 1;\r\n      letter-spacing: -0.05em;\r\n    }\r\n\r\n    .ranked-demo-app .input-grid {\r\n      display: grid;\r\n      grid-template-columns: 152px minmax(0, 1fr) 152px 152px;\r\n      gap: 10px;\r\n      align-items: stretch;\r\n      max-width: none;\r\n      margin: 0 auto;\r\n    }\r\n\r\n    .ranked-demo-app .attempts-card {\r\n      display: flex;\r\n      align-items: center;\r\n      justify-content: center;\r\n      padding: 0 22px;\r\n      border: 1px solid #fff;\r\n      border-radius: 12px;\r\n      background: #fff;\r\n      color: #111;\r\n      text-align: center;\r\n      white-space: nowrap;\r\n    }\r\n\r\n    .ranked-demo-app .action-slot {\r\n      width: 152px;\r\n      min-width: 152px;\r\n      align-self: stretch;\r\n    }\r\n\r\n    .ranked-demo-app .input-grid > .attempts-card, .ranked-demo-app .input-grid > .button, .ranked-demo-app .action-slot > .secondary-button {\r\n      width: 100%;\r\n      min-width: 0;\r\n      min-height: 56px;\r\n      height: 56px;\r\n    }\r\n\r\n    .ranked-demo-app .input-grid > .action-slot {\r\n      align-self: stretch;\r\n      height: 56px;\r\n    }\r\n\r\n    .ranked-demo-app .input-shell {\r\n      position: relative;\r\n      z-index: 5;\r\n      border: 2px solid #080808;\r\n      border-radius: 0;\r\n      background: #101010;\r\n      overflow: hidden;\r\n    }\r\n\r\n    .ranked-demo-app .search-field {\r\n      width: 100%;\r\n      min-height: 56px;\r\n      height: 56px;\r\n      padding: 0 18px;\r\n      border: 0;\r\n      border-radius: 0;\r\n      background: transparent;\r\n      color: var(--white);\r\n      font-size: 15px;\r\n      outline: none;\r\n      box-shadow: none;\r\n      transition: none;\r\n      appearance: none;\r\n      -webkit-appearance: none;\r\n    }\r\n\r\n    .ranked-demo-app .search-field:focus {\r\n      background: transparent;\r\n      box-shadow: none;\r\n    }\r\n\r\n    .ranked-demo-app .search-field::placeholder {\r\n      color: rgba(247, 244, 239, 0.18);\r\n      opacity: 1;\r\n    }\r\n\r\n    .ranked-demo-app .search-field:disabled {\r\n      opacity: 1;\r\n      cursor: not-allowed;\r\n      color: rgba(247, 244, 239, 0.26);\r\n      -webkit-text-fill-color: rgba(247, 244, 239, 0.26);\r\n    }\r\n\r\n    .ranked-demo-app .search-field:disabled::placeholder {\r\n      color: rgba(247, 244, 239, 0.18);\r\n      -webkit-text-fill-color: rgba(247, 244, 239, 0.18);\r\n    }\r\n\r\n    .ranked-demo-app .suggestions {\r\n      position: fixed;\r\n      top: 0;\r\n      left: 0;\r\n      width: 280px;\r\n      max-height: min(280px, calc(100dvh - 24px));\r\n      overflow-y: auto;\r\n      z-index: 2147483001;\r\n      display: none;\r\n      padding: 6px;\r\n      border: 1px solid var(--line);\r\n      border-radius: 14px;\r\n      background: rgba(9, 9, 9, 0.98);\r\n      box-shadow: 0 22px 50px rgba(0, 0, 0, 0.55);\r\n      backdrop-filter: blur(12px);\r\n      overscroll-behavior: contain;\r\n      -webkit-overflow-scrolling: touch;\r\n    }\r\n\r\n    .ranked-demo-app .suggestion {\r\n      width: 100%;\r\n      display: flex;\r\n      justify-content: space-between;\r\n      gap: 8px;\r\n      padding: 11px 12px;\r\n      border: 0;\r\n      border-radius: 10px;\r\n      background: transparent;\r\n      color: var(--white);\r\n      text-align: left;\r\n      cursor: pointer;\r\n    }\r\n\r\n    .ranked-demo-app .suggestion small {\r\n      color: var(--copy-faint);\r\n      font-size: 11px;\r\n    }\r\n\r\n    .ranked-demo-app .message {\r\n      display: none;\r\n      width: 100%;\r\n      max-width: none;\r\n      margin: 12px 0 0;\r\n      padding: 10px 12px;\r\n      border-radius: 999px;\r\n      border: 1px solid var(--line);\r\n      background: rgba(255, 255, 255, 0.03);\r\n      color: var(--copy);\r\n      font-size: 13px;\r\n      line-height: 1.45;\r\n      text-align: center;\r\n    }\r\n\r\n    .ranked-demo-app .message.is-visible {\r\n      display: block;\r\n    }\r\n\r\n    .ranked-demo-app .message.is-success {\r\n      border-color: rgba(125, 197, 106, 0.36);\r\n      background: rgba(125, 197, 106, 0.1);\r\n      color: #daf2d3;\r\n    }\r\n\r\n    .ranked-demo-app .message.is-error {\r\n      border-color: rgba(var(--ranked-accent-rgb), 0.32);\r\n      background: rgba(var(--ranked-accent-rgb), 0.1);\r\n      color: var(--white);\r\n    }\r\n\r\n    .ranked-demo-app .results-list {\r\n      display: grid;\r\n      gap: 12px;\r\n      margin-top: 18px;\r\n      max-width: none;\r\n      margin-left: auto;\r\n      margin-right: auto;\r\n    }\r\n\r\n    .ranked-demo-app .empty-state {\r\n      padding: 16px;\r\n      border: 1px dashed rgba(255, 255, 255, 0.15);\r\n      border-radius: 12px;\r\n      color: var(--copy-soft);\r\n      font-size: 13px;\r\n      line-height: 1.5;\r\n      text-align: center;\r\n    }\r\n\r\n    .ranked-demo-app .guess-card {\r\n      padding: 18px;\r\n      border: 1px solid var(--line-faint);\r\n      border-radius: 22px;\r\n      background: linear-gradient(180deg, rgba(14, 14, 14, 0.96), rgba(10, 10, 10, 0.96));\r\n      box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.03);\r\n      text-align: left;\r\n    }\r\n\r\n    .ranked-demo-app .guess-card.is-solved {\r\n      border-color: rgba(125, 197, 106, 0.34);\r\n    }\r\n\r\n    .ranked-demo-app .guess-card.is-auto {\r\n      border-color: rgba(var(--ranked-accent-rgb), 0.34);\r\n    }\r\n\r\n    .ranked-demo-app .guess-top {\r\n      display: flex;\r\n      align-items: center;\r\n      gap: 18px;\r\n      margin-bottom: 18px;\r\n    }\r\n\r\n    .ranked-demo-app .guess-cover {\r\n      position: relative;\r\n      flex: 0 0 96px;\r\n      width: 96px;\r\n      height: 96px;\r\n      border: 1px solid rgba(255, 255, 255, 0.12);\r\n      border-radius: 50%;\r\n      background:\r\n        radial-gradient(circle at 32% 28%, rgba(var(--ranked-accent-rgb), 0.34), transparent 44%),\r\n        linear-gradient(145deg, rgba(var(--ranked-accent-rgb), 0.16), rgba(255, 255, 255, 0.03));\r\n      overflow: hidden;\r\n      box-shadow: 0 18px 34px rgba(0, 0, 0, 0.34);\r\n    }\r\n\r\n    .ranked-demo-app .guess-cover img {\r\n      width: 100%;\r\n      height: 100%;\r\n      object-fit: cover;\r\n      display: block;\r\n    }\r\n\r\n    .ranked-demo-app .guess-cover-fallback {\r\n      width: 100%;\r\n      height: 100%;\r\n      display: flex;\r\n      align-items: center;\r\n      justify-content: center;\r\n      color: var(--white);\r\n      font-family: \"Space Grotesk\", sans-serif;\r\n      font-size: 28px;\r\n      font-weight: 900 !important;\r\n      letter-spacing: -0.04em;\r\n      text-transform: uppercase;\r\n    }\r\n\r\n    .ranked-demo-app .guess-copy {\r\n      min-width: 0;\r\n      display: flex;\r\n      flex-direction: column;\r\n      align-items: flex-start;\r\n      gap: 10px;\r\n    }\r\n\r\n    .ranked-demo-app .guess-badge {\r\n      display: inline-flex;\r\n      align-items: center;\r\n      justify-content: center;\r\n      min-height: 28px;\r\n      padding: 0 12px;\r\n      border: 1px solid var(--line);\r\n      border-radius: 999px;\r\n      color: var(--copy-soft);\r\n      font-size: 11px;\r\n      font-weight: 900 !important;\r\n      letter-spacing: -0.01em;\r\n    }\r\n\r\n    .ranked-demo-app .guess-name {\r\n      margin: 0;\r\n      font-family: \"Space Grotesk\", sans-serif;\r\n      font-size: clamp(28px, 4vw, 34px);\r\n      line-height: 1;\r\n      letter-spacing: -0.04em;\r\n    }\r\n\r\n    .ranked-demo-app .guess-sub {\r\n      margin: -2px 0 0;\r\n      color: var(--copy-soft);\r\n      font-size: 12px;\r\n      line-height: 1.45;\r\n    }\r\n\r\n    .ranked-demo-app .traits {\r\n      display: grid;\r\n      grid-template-columns: repeat(5, minmax(0, 1fr));\r\n      gap: 8px;\r\n    }\r\n\r\n    .ranked-demo-app .trait {\r\n      min-height: 98px;\r\n      padding: 12px 10px;\r\n      border: 1px solid rgba(255, 255, 255, 0.08);\r\n      border-radius: 14px;\r\n      background: rgba(255, 255, 255, 0.04);\r\n      display: flex;\r\n      flex-direction: column;\r\n      justify-content: space-between;\r\n      align-items: center;\r\n      text-align: center;\r\n    }\r\n\r\n    .ranked-demo-app .trait.is-correct {\r\n      border-color: rgba(84, 184, 106, 0.68);\r\n      background: #46b065;\r\n      color: #fff;\r\n    }\r\n\r\n    .ranked-demo-app .trait.is-close {\r\n      border-color: rgba(233, 181, 76, 0.72);\r\n      background: #d2a43a;\r\n      color: #fff;\r\n    }\r\n\r\n    .ranked-demo-app .trait-label {\r\n      display: block;\r\n      margin: 0;\r\n      color: inherit;\r\n      opacity: 0.92;\r\n      font-size: 12px;\r\n      font-weight: 900 !important;\r\n      letter-spacing: -0.02em;\r\n    }\r\n\r\n    .ranked-demo-app .trait-value {\r\n      display: inline-flex;\r\n      flex-wrap: wrap;\r\n      align-items: center;\r\n      justify-content: center;\r\n      gap: 5px;\r\n      font-size: clamp(15px, 1.8vw, 18px);\r\n      line-height: 1.06;\r\n      font-weight: 900 !important;\r\n      letter-spacing: -0.03em;\r\n      word-break: break-word;\r\n    }\r\n\r\n    .ranked-demo-app .trait-value-text, .ranked-demo-app .trait-suffix {\r\n      display: inline;\r\n    }\r\n\r\n    .ranked-demo-app .trait-arrow {\r\n      display: inline-flex;\r\n      align-items: center;\r\n      justify-content: center;\r\n      font-family: \"Segoe UI Symbol\", \"Noto Sans Symbols 2\", \"Arial Unicode MS\", sans-serif;\r\n      font-size: 0.95em;\r\n      line-height: 1;\r\n      letter-spacing: 0;\r\n      font-weight: 900 !important;\r\n      white-space: nowrap;\r\n    }\r\n\r\n    .ranked-demo-app .trait-suffix {\r\n      font-size: 0.76em;\r\n      line-height: 1;\r\n      font-weight: 900 !important;\r\n      letter-spacing: 0;\r\n      white-space: nowrap;\r\n    }\r\n\r\n    .ranked-demo-app .summary-panel {\r\n      margin-top: 16px;\r\n      padding: 16px;\r\n      border: 1px solid rgba(var(--ranked-accent-rgb), 0.28);\r\n      border-radius: 18px;\r\n      background: rgba(var(--ranked-accent-rgb), 0.08);\r\n    }\r\n\r\n    .ranked-demo-app .summary-panel.hidden {\r\n      display: none;\r\n    }\r\n\r\n    .ranked-demo-app .summary-panel.is-record {\r\n      border-color: rgba(125, 197, 106, 0.32);\r\n      background: rgba(125, 197, 106, 0.08);\r\n    }\r\n\r\n    .ranked-demo-app .summary-title {\r\n      margin: 0 0 10px;\r\n      font-family: \"Space Grotesk\", sans-serif;\r\n      font-size: clamp(22px, 4vw, 28px);\r\n      line-height: 1;\r\n      letter-spacing: -0.04em;\r\n      color: var(--white) !important;\r\n      font-weight: 900 !important;\r\n    }\r\n\r\n    .ranked-demo-app .summary-lines {\r\n      display: grid;\r\n      gap: 5px;\r\n    }\r\n\r\n    .ranked-demo-app .summary-line {\r\n      color: var(--white);\r\n      font-size: 14px;\r\n      line-height: 1.5;\r\n      font-weight: 900 !important;\r\n    }\r\n\r\n    .ranked-demo-app .summary-line strong {\r\n      font-weight: 900 !important;\r\n    }\r\n\r\n    .ranked-demo-app .board-shell {\r\n      margin-top: 16px;\r\n      padding-top: 16px;\r\n      border-top: 1px solid var(--line);\r\n    }\r\n\r\n    .ranked-demo-app .board-head {\r\n      display: flex;\r\n      justify-content: space-between;\r\n      align-items: flex-end;\r\n      gap: 12px;\r\n      margin-bottom: 10px;\r\n    }\r\n\r\n    .ranked-demo-app .board-kicker {\r\n      display: block;\r\n      color: var(--ranked-accent);\r\n      font-size: 11px;\r\n      font-weight: 900 !important;\r\n      letter-spacing: 0.18em;\r\n      text-transform: uppercase;\r\n    }\r\n\r\n    .ranked-demo-app .board-title {\r\n      display: block;\r\n      margin-top: 6px;\r\n      font-family: \"Space Grotesk\", sans-serif;\r\n      font-size: 24px;\r\n      line-height: 1;\r\n      letter-spacing: -0.04em;\r\n    }\r\n\r\n    .ranked-demo-app .board-period {\r\n      color: var(--copy-soft);\r\n      font-size: 12px;\r\n      text-align: right;\r\n      white-space: nowrap;\r\n    }\r\n\r\n    .ranked-demo-app .board-list {\r\n      display: grid;\r\n      gap: 8px;\r\n    }\r\n\r\n    .ranked-demo-app .board-row {\r\n      display: grid;\r\n      grid-template-columns: 54px minmax(0, 1fr) auto;\r\n      align-items: center;\r\n      gap: 12px;\r\n      padding: 12px 14px;\r\n      border: 1px solid var(--line);\r\n      border-radius: 14px;\r\n      background: rgba(255, 255, 255, 0.03);\r\n      transition: transform var(--ease), border-color var(--ease), background var(--ease);\r\n    }\r\n\r\n    .ranked-demo-app .board-row.is-current {\r\n      border-color: rgba(var(--ranked-accent-rgb), 0.28);\r\n      background: rgba(var(--ranked-accent-rgb), 0.08);\r\n    }\r\n\r\n    .ranked-demo-app .board-rank {\r\n      color: var(--ranked-accent);\r\n      font-family: \"Space Grotesk\", sans-serif;\r\n      font-size: 22px;\r\n      line-height: 1;\r\n      letter-spacing: -0.04em;\r\n    }\r\n\r\n    .ranked-demo-app .board-name {\r\n      min-width: 0;\r\n      font-size: 14px;\r\n      font-weight: 900 !important;\r\n      white-space: nowrap;\r\n      overflow: hidden;\r\n      text-overflow: ellipsis;\r\n    }\r\n\r\n    .ranked-demo-app .board-meta {\r\n      color: var(--copy-faint);\r\n      font-size: 11px;\r\n      font-weight: 900 !important;\r\n      text-transform: uppercase;\r\n      letter-spacing: 0.08em;\r\n    }\r\n\r\n    .ranked-demo-app .board-score {\r\n      font-family: \"Space Grotesk\", sans-serif;\r\n      font-size: 24px;\r\n      line-height: 1;\r\n      letter-spacing: -0.04em;\r\n    }\r\n\r\n    .ranked-demo-app .board-msg {\r\n      margin-top: 10px;\r\n      color: var(--copy-soft);\r\n      font-size: 12px;\r\n      line-height: 1.45;\r\n      text-align: center;\r\n    }\r\n\r\n    .ranked-demo-app .hidden {\r\n      display: none !important;\r\n    }\r\n\r\n    @media (max-width: 720px) {\r\n      .ranked-demo-app {\r\n        width: 100%;\r\n        max-width: 100%;\r\n        padding: max(6px, env(safe-area-inset-top, 0px)) 4px calc(10px + env(safe-area-inset-bottom, 0px));\r\n      }\r\n\r\n      .ranked-demo-app .app-shell {\r\n        display: flex;\r\n        flex-direction: column;\r\n        padding: 8px 6px 10px;\r\n        border: 0;\r\n        border-radius: 0;\r\n        background: transparent;\r\n        box-shadow: none;\r\n      }\r\n\r\n      .ranked-demo-app .app-shell::after {\r\n        display: none;\r\n      }\r\n\r\n      .ranked-demo-app .controls-shell {\r\n        order: 1;\r\n        position: relative;\r\n        border-top: 0;\r\n        border-bottom: 1px solid var(--line);\r\n        padding-top: 10px;\r\n        padding-bottom: 20px;\r\n      }\r\n\r\n      .ranked-demo-app .controls-shell::after {\r\n        content: \"Gioca\";\r\n        position: absolute;\r\n        left: 50%;\r\n        bottom: -11px;\r\n        transform: translateX(-50%) translateY(-2px);\r\n        padding: 0 14px;\r\n        background: var(--bg);\r\n        color: #9E9E9E;\r\n        font-size: 15px;\r\n        line-height: 1;\r\n      }\r\n\r\n      .ranked-demo-app .topbar {\r\n        order: 2;\r\n        padding: 12px 4px 4px;\r\n      }\r\n\r\n      .ranked-demo-app .top-logo {\r\n        width: min(260px, 66vw);\r\n      }\r\n\r\n      .ranked-demo-app .shell {\r\n        order: 3;\r\n        border-top: 0;\r\n        padding-top: 14px;\r\n      }\r\n\r\n      .ranked-demo-app .controls-inner .tab, .ranked-demo-app .controls-inner .ghost-button {\r\n        min-height: 40px;\r\n        padding: 0 10px;\r\n        font-size: 12px;\r\n      }\r\n\r\n      .ranked-demo-app .help-panel-mobile-slot {\r\n        display: block;\r\n      }\r\n\r\n      .ranked-demo-app .controls-shell .help-panel.is-open {\r\n        margin: 10px 0 0;\r\n        padding-bottom: 0;\r\n        border-bottom-color: transparent;\r\n      }\r\n\r\n      .ranked-demo-app .meta-grid {\r\n        gap: 8px;\r\n      }\r\n\r\n      .ranked-demo-app .meta-card {\r\n        min-height: 62px;\r\n        padding: 10px 11px;\r\n      }\r\n\r\n      .ranked-demo-app .meta-value {\r\n        font-size: clamp(18px, 5vw, 24px);\r\n      }\r\n\r\n      .ranked-demo-app .input-grid {\r\n        grid-template-columns: repeat(2, minmax(0, 1fr));\r\n        gap: 8px;\r\n        width: 100%;\r\n      }\r\n\r\n      .ranked-demo-app .attempts-card {\r\n        order: 1;\r\n        min-width: 0;\r\n        min-height: 48px;\r\n        height: 48px;\r\n        padding: 0 10px;\r\n        font-size: 13px;\r\n      }\r\n\r\n      .ranked-demo-app .action-slot {\r\n        order: 2;\r\n        width: auto;\r\n        min-width: 0;\r\n      }\r\n\r\n      .ranked-demo-app .input-shell {\r\n        order: 3;\r\n        grid-column: 1 \/ -1;\r\n        min-width: 0;\r\n        padding: 0;\r\n        border: 2px solid #080808;\r\n        border-radius: 0;\r\n        background: #0b0b0b;\r\n      }\r\n\r\n      .ranked-demo-app .input-grid > .button {\r\n        order: 4;\r\n        grid-column: 1 \/ -1;\r\n      }\r\n\r\n      .ranked-demo-app .input-grid > .attempts-card, .ranked-demo-app .input-grid > .button, .ranked-demo-app .action-slot > .secondary-button, .ranked-demo-app .input-grid > .action-slot {\r\n        width: 100%;\r\n        min-width: 0;\r\n        min-height: 48px;\r\n        height: 48px;\r\n      }\r\n\r\n      .ranked-demo-app .button, .ranked-demo-app .secondary-button, .ranked-demo-app .attempts-card, .ranked-demo-app .action-slot {\r\n        min-width: 0;\r\n      }\r\n\r\n      .ranked-demo-app .search-field {\r\n        min-height: 48px;\r\n        height: 48px;\r\n        padding: 0 14px;\r\n        border: 0;\r\n        border-radius: 0;\r\n        background: transparent;\r\n        font-size: 16px;\r\n      }\r\n\r\n      .ranked-demo-app .suggestion {\r\n        min-height: 48px;\r\n        padding: 13px 12px;\r\n      }\r\n\r\n      .ranked-demo-app .help-grid {\r\n        grid-template-columns: 1fr;\r\n      }\r\n\r\n      .ranked-demo-app .help-card span {\r\n        font-size: 13px;\r\n        line-height: 1.5;\r\n      }\r\n\r\n      .ranked-demo-app .traits {\r\n        grid-template-columns: repeat(2, minmax(0, 1fr));\r\n        gap: 6px;\r\n      }\r\n\r\n      .ranked-demo-app .trait:nth-child(5) {\r\n        grid-column: 1 \/ -1;\r\n      }\r\n\r\n      .ranked-demo-app .guess-top, .ranked-demo-app .board-head {\r\n        flex-direction: column;\r\n        align-items: center;\r\n        justify-content: center;\r\n        text-align: center;\r\n      }\r\n\r\n      .ranked-demo-app .guess-copy {\r\n        align-items: center;\r\n        text-align: center;\r\n      }\r\n\r\n      .ranked-demo-app .guess-card {\r\n        padding: 12px;\r\n        border-radius: 16px;\r\n      }\r\n\r\n      .ranked-demo-app .guess-top {\r\n        gap: 10px;\r\n        margin-bottom: 10px;\r\n      }\r\n\r\n      .ranked-demo-app .guess-cover {\r\n        flex-basis: 72px;\r\n        width: 72px;\r\n        height: 72px;\r\n      }\r\n\r\n      .ranked-demo-app .guess-name {\r\n        font-size: clamp(20px, 7vw, 26px);\r\n      }\r\n\r\n      .ranked-demo-app .trait {\r\n        min-height: 74px;\r\n        padding: 8px 7px;\r\n      }\r\n\r\n      .ranked-demo-app .trait-label {\r\n        font-size: 10px;\r\n      }\r\n\r\n      .ranked-demo-app .trait-value {\r\n        font-size: clamp(12px, 3.9vw, 15px);\r\n      }\r\n\r\n      .ranked-demo-app .message {\r\n        margin-top: 10px;\r\n        padding: 9px 11px;\r\n        font-size: 13px;\r\n      }\r\n\r\n      .ranked-demo-app .controls-inner {\r\n        grid-template-columns: repeat(2, minmax(0, 1fr));\r\n      }\r\n\r\n      .ranked-demo-app .board-row {\r\n        grid-template-columns: 40px minmax(0, 1fr) auto;\r\n        gap: 10px;\r\n        padding: 11px 12px;\r\n      }\r\n\r\n      .ranked-demo-app .board-rank, .ranked-demo-app .board-score {\r\n        font-size: 18px;\r\n      }\r\n    }\r\n\r\n    @media (max-width: 520px) {\r\n      .ranked-demo-app {\r\n        padding-inline: 3px;\r\n      }\r\n\r\n      .ranked-demo-app .controls-shell, .ranked-demo-app .shell {\r\n        padding-top: 8px;\r\n      }\r\n\r\n      .ranked-demo-app .top-logo {\r\n        width: min(232px, 64vw);\r\n      }\r\n\r\n      .ranked-demo-app .guess-card {\r\n        padding: 11px;\r\n      }\r\n\r\n      .ranked-demo-app .trait {\r\n        min-height: 70px;\r\n      }\r\n\r\n      .ranked-demo-app .guess-badge {\r\n        min-height: 24px;\r\n        padding: 0 10px;\r\n        font-size: 10px;\r\n      }\r\n\r\n      .ranked-demo-app .guess-sub {\r\n        font-size: 11px;\r\n      }\r\n\r\n      .ranked-demo-app .controls-inner {\r\n        grid-template-columns: 1fr;\r\n      }\r\n    }\r\n\r\n    @media (max-width: 400px) {\r\n      .ranked-demo-app {\r\n        padding-inline: 2px;\r\n      }\r\n\r\n      .ranked-demo-app .top-logo {\r\n        width: min(214px, 62vw);\r\n      }\r\n\r\n      .ranked-demo-app .attempts-card, .ranked-demo-app .button, .ranked-demo-app .secondary-button {\r\n        font-size: 12px;\r\n      }\r\n\r\n      .ranked-demo-app .trait {\r\n        min-height: 66px;\r\n        padding: 8px 6px;\r\n      }\r\n\r\n      .ranked-demo-app .trait-value {\r\n        font-size: 12px;\r\n      }\r\n    }\r\n\r\n    @media (hover: none), (pointer: coarse) {\r\n      .ranked-demo-app .tab:hover, .ranked-demo-app .ghost-button:hover, .ranked-demo-app .button:hover, .ranked-demo-app .secondary-button:hover, .ranked-demo-app .suggestion:hover, .ranked-demo-app .board-row:hover {\r\n        transform: none;\r\n      }\r\n\r\n      .ranked-demo-app .button:hover, .ranked-demo-app .secondary-button.is-primary:hover {\r\n        background: var(--ranked-accent);\r\n        border-color: var(--ranked-accent);\r\n        color: #111;\r\n      }\r\n\r\n      .ranked-demo-app .secondary-button.is-muted:hover {\r\n        background: rgba(255, 255, 255, 0.03);\r\n        border-color: var(--line);\r\n        color: var(--white);\r\n      }\r\n\r\n      .ranked-demo-app .suggestion:hover, .ranked-demo-app .board-row:hover {\r\n        background: transparent;\r\n      }\r\n\r\n      .ranked-demo-app .button:active, .ranked-demo-app .secondary-button:active, .ranked-demo-app .tab:active, .ranked-demo-app .ghost-button:active, .ranked-demo-app .suggestion:active, .ranked-demo-app .board-row:active {\r\n        transform: scale(0.99);\r\n      }\r\n    }\r\n\r\n    .ranked-demo-app button,\r\n    .ranked-demo-app button *,\r\n    .ranked-demo-app .attempts-card,\r\n    .ranked-demo-app .attempts-card *,\r\n    .ranked-demo-app .classic-attempts-badge,\r\n    .ranked-demo-app .classic-attempts-badge *,\r\n    .ranked-demo-app .classic-streak-badge,\r\n    .ranked-demo-app .classic-streak-badge *,\r\n    .ranked-demo-app .streak-card,\r\n    .ranked-demo-app .streak-card *,\r\n    .ranked-demo-app .guess-name,\r\n    .ranked-demo-app .guess-name *,\r\n    .ranked-demo-app .artist-name,\r\n    .ranked-demo-app .artist-name *,\r\n    .ranked-demo-app .result-name,\r\n    .ranked-demo-app .result-name *,\r\n    .ranked-demo-app .board-row .name,\r\n    .ranked-demo-app .board-row .name * {\r\n      font-family: Verdana, Geneva, sans-serif !important;\r\n      font-weight: 900 !important;\r\n      -webkit-text-stroke: 0.18px currentColor;\r\n      text-shadow: 0.18px 0 currentColor;\r\n    }\r\n  <\/style>\r\n<\/head>\r\n<body>\r\n  <div class=\"demo-app ranked-demo-app\">\r\n    <div class=\"app-shell\">\r\n      <header class=\"topbar\">\r\n        <img decoding=\"async\" class=\"top-logo\" src=\"https:\/\/bulldogmusik.it\/wp-content\/uploads\/2026\/05\/Bulldogle-Ranked-New-1.png\" alt=\"Bulldogle Ranked\">\r\n      <\/header>\r\n\r\n        <main class=\"shell\">\r\n        <section class=\"game-shell\">\r\n          <section class=\"meta-grid\" aria-label=\"Statistiche partita\">\r\n            <article class=\"meta-card is-accent\">\r\n              <span class=\"meta-label\">Tempo<\/span>\r\n              <strong id=\"rankedTimerValue\" class=\"meta-value\">3:00<\/strong>\r\n            <\/article>\r\n            <article class=\"meta-card\">\r\n              <span class=\"meta-label\">Punti<\/span>\r\n              <strong id=\"rankedScoreValue\" class=\"meta-value\">0<\/strong>\r\n            <\/article>\r\n            <button id=\"rankedHelpToggle\" class=\"ranked-meta-button\" type=\"button\">COME SI GIOCA<\/button>\r\n          <\/section>\r\n\r\n          <section id=\"rankedHelpPanel\" class=\"help-panel\" aria-hidden=\"true\">\r\n            <div class=\"help-grid\">\r\n              <div class=\"help-card\">\r\n                <strong>Timer<\/strong>\r\n                <span>Hai 3 minuti per fare il punteggio piu alto possibile.<\/span>\r\n              <\/div>\r\n              <div class=\"help-card\">\r\n                <strong>Punti<\/strong>\r\n                <span>Ogni artista indovinato vale 1 punto e aggiunge 15 secondi.<\/span>\r\n              <\/div>\r\n              <div class=\"help-card\">\r\n                <strong>Skip<\/strong>\r\n                <span>Puoi skippare l'artista corrente, ma perdi 15 secondi.<\/span>\r\n              <\/div>\r\n              <div class=\"help-card\">\r\n                <strong>Tentativi<\/strong>\r\n                <span>Hai 10 tentativi per artista. Se li finisci, passi al successivo.<\/span>\r\n              <\/div>\r\n              <div class=\"help-card\">\r\n                <strong>Indizi<\/strong>\r\n                <span>\ud83d\udfe2 = corretto. \ud83d\udfe1 = vicino. Le frecce indicano la direzione giusta.<\/span>\r\n              <\/div>\r\n              <div class=\"help-card\">\r\n                <strong>Classifica<\/strong>\r\n                <span>Il record migliore viene salvato nella classifica mensile della ranked.<\/span>\r\n              <\/div>\r\n            <\/div>\r\n          <\/section>\r\n\r\n          <form id=\"rankedGuessForm\" class=\"input-grid\" autocomplete=\"off\">\r\n            <div id=\"rankedAttemptsCard\" class=\"attempts-card\" aria-live=\"polite\">10 TENTATIVI<\/div>\r\n\r\n            <div class=\"input-shell\">\r\n              <input id=\"rankedArtistInput\" class=\"search-field\" type=\"text\" placeholder=\"inserisci un artista\" aria-describedby=\"rankedGameMsg\">\r\n              <div id=\"rankedSuggestions\" class=\"suggestions\" role=\"listbox\" aria-label=\"Suggerimenti artisti\"><\/div>\r\n            <\/div>\r\n\r\n            <button id=\"rankedSubmitButton\" class=\"button\" type=\"submit\">PROVA<\/button>\r\n\r\n            <div class=\"action-slot\">\r\n              <button id=\"rankedSideActionButton\" class=\"secondary-button is-primary\" type=\"button\">INIZIA<\/button>\r\n            <\/div>\r\n          <\/form>\r\n\r\n          <section id=\"rankedSummaryPanel\" class=\"summary-panel hidden\" aria-live=\"polite\">\r\n            <h3 id=\"rankedSummaryTitle\" class=\"summary-title\">Partita conclusa<\/h3>\r\n            <div id=\"rankedSummaryLines\" class=\"summary-lines\"><\/div>\r\n          <\/section>\r\n\r\n          <div id=\"rankedGameMsg\" class=\"message\" aria-live=\"polite\"><\/div>\r\n\r\n          <div id=\"rankedResultsList\" class=\"results-list\">\r\n            <div class=\"empty-state\">ACCEDI per giocare.<\/div>\r\n          <\/div>\r\n        <\/section>\r\n      <\/main>\r\n    <\/div>\r\n  <\/div>\r\n\r\n  <script>\r\n    (async function () {\r\n      const bootstrapScript = document.currentScript;\r\n\r\n      async function loadScriptSource(src) {\r\n        return new Promise((resolve) => {\r\n          const existing = Array.from(document.querySelectorAll(\"script[src]\")).find((node) => node.src === src);\r\n          if (existing && Array.isArray(window.bulldogleArtists) && window.bulldogleArtists.length) {\r\n            resolve(true);\r\n            return;\r\n          }\r\n\r\n          const script = document.createElement(\"script\");\r\n          script.src = src;\r\n          script.async = false;\r\n          script.onload = () => resolve(true);\r\n          script.onerror = () => resolve(false);\r\n          document.head.appendChild(script);\r\n        });\r\n      }\r\n\r\n      async function ensureArtistsLoaded() {\r\n        if (Array.isArray(window.bulldogleArtists) && window.bulldogleArtists.length) {\r\n          return window.bulldogleArtists;\r\n        }\r\n\r\n        const sources = [\r\n          \".\/artists.js\",\r\n          \"artists.js\",\r\n          \"\/bulldogle\/artists.js?v=65\"\r\n        ];\r\n\r\n        if (window.location && \/^https?:\/i.test(window.location.protocol) && window.location.origin) {\r\n          sources.push(window.location.origin + \"\/bulldogle\/artists.js?v=65\");\r\n        }\r\n\r\n        sources.push(\"https:\/\/bulldogmusik.it\/bulldogle\/artists.js?v=65\");\r\n\r\n        for (const source of sources) {\r\n          const loaded = await loadScriptSource(source);\r\n          if (loaded && Array.isArray(window.bulldogleArtists) && window.bulldogleArtists.length) {\r\n            return window.bulldogleArtists;\r\n          }\r\n        }\r\n\r\n        return [];\r\n      }\r\n\r\n      const artistsSource = await ensureArtistsLoaded();\r\n      const rankedConfig = window.bulldogleRankedConfig || {};\r\n      const rankedDemoConfig = window.bulldogleRankedModernDemoConfig || {};\r\n      const GAME_KEY = String(rankedDemoConfig.gameKey || \"classic\").trim() || \"classic\";\r\n      const hasBackend = Boolean(rankedConfig && rankedConfig.ajaxUrl && rankedConfig.nonce);\r\n      const ROUND_ATTEMPTS = 10;\r\n      const INITIAL_TIME = 180;\r\n      const CORRECT_BONUS = 15;\r\n      const SKIP_PENALTY = 15;\r\n      const ROUND_TRANSITION_MS = 1000;\r\n      const BOARD_LIMIT = 10;\r\n      const ARROWS = {\r\n        up: String.fromCharCode(8593),\r\n        down: String.fromCharCode(8595),\r\n        left: String.fromCharCode(8592),\r\n        right: String.fromCharCode(8594)\r\n      };\r\n      const popularityLevels = [\"underground\", \"emergente\", \"riconosciuto\", \"mainstream\", \"icona\"];\r\n      const monthlyListenerBuckets = [\r\n        { level: \"underground\", min: 0 },\r\n        { level: \"emergente\", min: 250000 },\r\n        { level: \"riconosciuto\", min: 750000 },\r\n        { level: \"mainstream\", min: 1500000 },\r\n        { level: \"icona\", min: 3000000 }\r\n      ];\r\n\r\n      const regionCoords = {\r\n        \"Abruzzo\": { lat: 42.3, lon: 13.9 },\r\n        \"Basilicata\": { lat: 40.6, lon: 15.8 },\r\n        \"Calabria\": { lat: 38.9, lon: 16.6 },\r\n        \"Campania\": { lat: 40.8, lon: 14.3 },\r\n        \"Emilia-Romagna\": { lat: 44.5, lon: 11.3 },\r\n        \"Friuli-Venezia Giulia\": { lat: 46.1, lon: 13.1 },\r\n        \"Lazio\": { lat: 41.9, lon: 12.5 },\r\n        \"Liguria\": { lat: 44.4, lon: 8.9 },\r\n        \"Lombardia\": { lat: 45.5, lon: 9.2 },\r\n        \"Marche\": { lat: 43.6, lon: 13.5 },\r\n        \"Molise\": { lat: 41.6, lon: 14.6 },\r\n        \"Piemonte\": { lat: 45.1, lon: 7.7 },\r\n        \"Puglia\": { lat: 41.1, lon: 16.9 },\r\n        \"Sardegna\": { lat: 40.1, lon: 9.0 },\r\n        \"Sicilia\": { lat: 37.6, lon: 14.0 },\r\n        \"Toscana\": { lat: 43.8, lon: 11.2 },\r\n        \"Trentino-Alto Adige\": { lat: 46.5, lon: 11.3 },\r\n        \"Umbria\": { lat: 43.1, lon: 12.4 },\r\n        \"Valle d'Aosta\": { lat: 45.7, lon: 7.3 },\r\n        \"Veneto\": { lat: 45.4, lon: 12.3 },\r\n        \"Estero\": null\r\n      };\r\n\r\n      const spotifyThumbStorageKey = \"bulldogle-spotify-thumbs-v1\";\r\n      const spotifyThumbCache = new Map();\r\n      const spotifyThumbRequests = new Map();\r\n      let messageTimeoutId = 0;\r\n\r\n      try {\r\n        const storedThumbs = JSON.parse(window.localStorage.getItem(spotifyThumbStorageKey) || \"{}\");\r\n        Object.keys(storedThumbs).forEach((spotifyId) => {\r\n          if (storedThumbs[spotifyId]) {\r\n            spotifyThumbCache.set(spotifyId, String(storedThumbs[spotifyId]));\r\n          }\r\n        });\r\n      } catch (_) {}\r\n\r\n      function parseMonthlyListenersValue(value) {\r\n        if (typeof value === \"number\") {\r\n          return Number.isFinite(value) && value > 0 ? Math.round(value) : 0;\r\n        }\r\n\r\n        const raw = String(value || \"\").trim();\r\n        if (!raw) return 0;\r\n\r\n        const compact = raw.replace(\/\\s+\/g, \"\");\r\n        const suffixMatch = compact.match(\/^([0-9]+(?:[.,][0-9]+)?)\\s*([kmb])$\/i);\r\n        if (suffixMatch) {\r\n          const amount = Number(suffixMatch[1].replace(\",\", \".\"));\r\n          if (!Number.isFinite(amount) || amount <= 0) return 0;\r\n          const unit = suffixMatch[2].toLowerCase();\r\n          if (unit === \"b\") return Math.round(amount * 1e9);\r\n          if (unit === \"m\") return Math.round(amount * 1e6);\r\n          return Math.round(amount * 1e3);\r\n        }\r\n\r\n        if (\/^\\d{1,3}([.,]\\d{3})+$\/.test(compact)) {\r\n          return Math.round(Number(compact.replace(\/[.,]\/g, \"\")) || 0);\r\n        }\r\n\r\n        const parsed = Number(compact.replace(\",\", \".\"));\r\n        return Number.isFinite(parsed) && parsed > 0 ? Math.round(parsed) : 0;\r\n      }\r\n\r\n      function getManualMonthlyListeners(artist) {\r\n        const manualKeys = [\r\n          \"listenersManual\",\r\n          \"monthlyListenersManual\",\r\n          \"manualMonthlyListeners\",\r\n          \"manualListeners\",\r\n          \"listeners_manual\",\r\n          \"monthly_listeners_manual\",\r\n          \"listeners-manual\",\r\n          \"monthly-listeners-manual\"\r\n        ];\r\n\r\n        for (const key of manualKeys) {\r\n          const value = parseMonthlyListenersValue(artist && artist[key]);\r\n          if (value > 0) return value;\r\n        }\r\n\r\n        return 0;\r\n      }\r\n\r\n      const artists = artistsSource.map((artist) => ({\r\n        id: Number(artist.id),\r\n        name: String(artist.name || \"\").trim(),\r\n        city: String(artist.city || \"\").trim(),\r\n        region: String(artist.region || \"\").trim(),\r\n        debutYear: Number(artist.debutYear || 0),\r\n        members: String(artist.members || \"N\/D\").trim(),\r\n        gender: String(artist.gender || \"\").trim(),\r\n        popularity: String(artist.popularity || \"\").trim().toLowerCase(),\r\n        monthlyListeners: Number(artist.monthlyListeners || 0),\r\n        listenersManual: getManualMonthlyListeners(artist),\r\n        spotifyId: String(artist.spotifyId || \"\").trim()\r\n      })).filter((artist) => artist.id && artist.name);\r\n\r\n      const demoRoots = Array.from(document.querySelectorAll(\".ranked-demo-app\"));\r\n      const appRoot = bootstrapScript &&\r\n        bootstrapScript.previousElementSibling &&\r\n        bootstrapScript.previousElementSibling.classList &&\r\n        bootstrapScript.previousElementSibling.classList.contains(\"ranked-demo-app\")\r\n          ? bootstrapScript.previousElementSibling\r\n          : demoRoots[demoRoots.length - 1];\r\n\r\n      if (!appRoot) return;\r\n\r\n      const elements = {\r\n        boardScrollButton: appRoot.querySelector(\"#rankedBoardScrollButton\"),\r\n        helpToggle: appRoot.querySelector(\"#rankedHelpToggle\"),\r\n        helpPanel: appRoot.querySelector(\"#rankedHelpPanel\"),\r\n        helpPanelMobileSlot: appRoot.querySelector(\"#rankedHelpPanelMobileSlot\"),\r\n        timerValue: appRoot.querySelector(\"#rankedTimerValue\"),\r\n        scoreValue: appRoot.querySelector(\"#rankedScoreValue\"),\r\n        roundValue: appRoot.querySelector(\"#rankedRoundValue\"),\r\n        attemptsCard: appRoot.querySelector(\"#rankedAttemptsCard\"),\r\n        guessForm: appRoot.querySelector(\"#rankedGuessForm\"),\r\n        input: appRoot.querySelector(\"#rankedArtistInput\"),\r\n        suggestions: appRoot.querySelector(\"#rankedSuggestions\"),\r\n        submitButton: appRoot.querySelector(\"#rankedSubmitButton\"),\r\n        sideActionButton: appRoot.querySelector(\"#rankedSideActionButton\"),\r\n        message: appRoot.querySelector(\"#rankedGameMsg\"),\r\n        resultsList: appRoot.querySelector(\"#rankedResultsList\"),\r\n        summaryPanel: appRoot.querySelector(\"#rankedSummaryPanel\"),\r\n        summaryTitle: appRoot.querySelector(\"#rankedSummaryTitle\"),\r\n        summaryLines: appRoot.querySelector(\"#rankedSummaryLines\"),\r\n        leaderboardPanel: appRoot.querySelector(\"#rankedLeaderboardPanel\"),\r\n        boardList: appRoot.querySelector(\"#rankedBoardList\"),\r\n        boardMsg: appRoot.querySelector(\"#rankedBoardMsg\"),\r\n        boardPeriod: appRoot.querySelector(\"#rankedBoardPeriod\")\r\n      };\r\n\r\n      if (!elements.input || !elements.submitButton || !elements.sideActionButton || !elements.resultsList) {\r\n        return;\r\n      }\r\n\r\n      const desktopHelpPanelParent = elements.helpPanel ? elements.helpPanel.parentElement : null;\r\n      const desktopHelpPanelNextSibling = elements.helpPanel ? elements.helpPanel.nextElementSibling : null;\r\n\r\n      if (elements.suggestions.parentElement !== document.body) {\r\n        document.body.appendChild(elements.suggestions);\r\n      }\r\n\r\n      const italyDateInfo = getItalyDateInfo();\r\n      const state = {\r\n        active: false,\r\n        preparing: false,\r\n        submitting: false,\r\n        complete: false,\r\n        betweenRounds: false,\r\n        sessionToken: \"\",\r\n        currentArtist: null,\r\n        score: 0,\r\n        timeLeft: INITIAL_TIME,\r\n        roundAttempts: 0,\r\n        roundGuessedIds: new Set(),\r\n        usedTargetIds: new Set(),\r\n        freeHintArtist: null,\r\n        results: [],\r\n        timerId: 0,\r\n        roundTransitionId: 0,\r\n        summaryTitle: \"Partita conclusa\",\r\n        summaryLines: [],\r\n        isRecord: false,\r\n        boardRows: [],\r\n        boardPeriodLabel: getPeriodLabel(rankedConfig.currentPeriodKey || italyDateInfo.periodKey),\r\n        boardMessage: \"\",\r\n        boardLoading: false,\r\n        boardCurrentName: rankedConfig.displayName || \"Demo\"\r\n      };\r\n\r\n      if (!artists.length) {\r\n        elements.message.textContent = \"artists.js non e stato caricato correttamente.\";\r\n        elements.message.classList.add(\"is-visible\", \"is-error\");\r\n        disableGameInput(true);\r\n        return;\r\n      }\r\n\r\n      function normalize(value) {\r\n        return String(value || \"\").trim().toLowerCase();\r\n      }\r\n\r\n      function hashString(value) {\r\n        let hash = 2166136261;\r\n        for (let index = 0; index < value.length; index++) {\r\n          hash ^= value.charCodeAt(index);\r\n          hash = Math.imul(hash, 16777619);\r\n        }\r\n        return hash >>> 0;\r\n      }\r\n\r\n      function createSeededRandom(seed) {\r\n        let randomState = seed >>> 0;\r\n        return function () {\r\n          randomState += 0x6D2B79F5;\r\n          let value = Math.imul(randomState ^ (randomState >>> 15), 1 | randomState);\r\n          value ^= value + Math.imul(value ^ (value >>> 7), 61 | value);\r\n          return ((value ^ (value >>> 14)) >>> 0) \/ 4294967296;\r\n        };\r\n      }\r\n\r\n      function getItalyDateInfo() {\r\n        const formatter = new Intl.DateTimeFormat(\"en-CA\", {\r\n          timeZone: \"Europe\/Rome\",\r\n          year: \"numeric\",\r\n          month: \"2-digit\",\r\n          day: \"2-digit\"\r\n        });\r\n        const parts = formatter.formatToParts(new Date());\r\n        const year = Number(parts.find((part) => part.type === \"year\").value);\r\n        const month = Number(parts.find((part) => part.type === \"month\").value);\r\n        const day = Number(parts.find((part) => part.type === \"day\").value);\r\n        return {\r\n          dayKey: year + \"-\" + String(month).padStart(2, \"0\") + \"-\" + String(day).padStart(2, \"0\"),\r\n          dayIndex: Math.floor(Date.UTC(year, month - 1, day) \/ 86400000),\r\n          periodKey: year + \"-\" + String(month).padStart(2, \"0\")\r\n        };\r\n      }\r\n\r\n      function getPeriodLabel(periodKey) {\r\n        const safeKey = \/^\\d{4}-\\d{2}$\/.test(String(periodKey || \"\")) ? String(periodKey) : italyDateInfo.periodKey;\r\n        const date = new Date(safeKey + \"-01T12:00:00\");\r\n        const label = new Intl.DateTimeFormat(\"it-IT\", {\r\n          timeZone: \"Europe\/Rome\",\r\n          month: \"long\",\r\n          year: \"numeric\"\r\n        }).format(date);\r\n        return label.charAt(0).toUpperCase() + label.slice(1);\r\n      }\r\n\r\n      function formatTime(totalSeconds) {\r\n        const safeTime = Math.max(0, totalSeconds);\r\n        const minutes = Math.floor(safeTime \/ 60);\r\n        const seconds = String(safeTime % 60).padStart(2, \"0\");\r\n        return minutes + \":\" + seconds;\r\n      }\r\n\r\n      function formatPopularityLevel(value) {\r\n        const listeners = Number(value || 0);\r\n        if (!Number.isFinite(listeners) || listeners <= 0) return \"N\/D\";\r\n        if (listeners >= 1e9) return (listeners \/ 1e9).toFixed(listeners >= 1e10 ? 0 : 1).replace(\/\\.0$\/, \"\") + \"B\";\r\n        if (listeners >= 1e6) return (listeners \/ 1e6).toFixed(listeners >= 1e7 ? 0 : 1).replace(\/\\.0$\/, \"\") + \"M\";\r\n        if (listeners >= 1e3) return (listeners \/ 1e3).toFixed(listeners >= 1e5 ? 0 : 1).replace(\/\\.0$\/, \"\") + \"K\";\r\n        return String(listeners);\r\n      }\r\n\r\n      function getMonthlyListeners(artist) {\r\n        const manualValue = getManualMonthlyListeners(artist);\r\n        if (manualValue > 0) {\r\n          return manualValue;\r\n        }\r\n\r\n        const value = Number(artist && artist.monthlyListeners || 0);\r\n        return Number.isFinite(value) && value > 0 ? Math.round(value) : 0;\r\n      }\r\n\r\n      function getLegacyPopularityLevel(artist) {\r\n        const value = normalize(artist && artist.popularity);\r\n        return popularityLevels.includes(value) ? value : \"\";\r\n      }\r\n\r\n      function getPopularityIndexFromMonthlyListeners(value) {\r\n        const listeners = Number(value || 0);\r\n        if (!Number.isFinite(listeners) || listeners <= 0) {\r\n          return -1;\r\n        }\r\n\r\n        let level = monthlyListenerBuckets[0].level;\r\n        for (const bucket of monthlyListenerBuckets) {\r\n          if (listeners >= bucket.min) {\r\n            level = bucket.level;\r\n          }\r\n        }\r\n\r\n        return popularityLevels.indexOf(level);\r\n      }\r\n\r\n      function getComparablePopularityIndex(artist) {\r\n        const monthlyIndex = getPopularityIndexFromMonthlyListeners(getMonthlyListeners(artist));\r\n        if (monthlyIndex >= 0) {\r\n          return monthlyIndex;\r\n        }\r\n\r\n        return popularityLevels.indexOf(getLegacyPopularityLevel(artist));\r\n      }\r\n\r\n      function formatPopularityDisplay(artist) {\r\n        const listeners = getMonthlyListeners(artist);\r\n        if (listeners > 0) {\r\n          return formatPopularityLevel(listeners);\r\n        }\r\n\r\n        const fallback = getLegacyPopularityLevel(artist);\r\n        return fallback ? fallback.charAt(0).toUpperCase() + fallback.slice(1) : \"N\/D\";\r\n      }\r\n\r\n      function formatGenderValue(value) {\r\n        if (value === \"M\") return \"Uomo\";\r\n        if (value === \"F\") return \"Donna\";\r\n        return value || \"N\/D\";\r\n      }\r\n\r\n      function getModeDisplayName() {\r\n        const games = rankedConfig.games || {};\r\n        return games[GAME_KEY] || \"Bulldogle\";\r\n      }\r\n\r\n      function getLoginUrl() {\r\n        return rankedConfig.loginUrl || \"https:\/\/bulldogmusik.it\/account-login\/\";\r\n      }\r\n\r\n      function getCurrentPeriodKey() {\r\n        return rankedConfig.currentPeriodKey || italyDateInfo.periodKey;\r\n      }\r\n\r\n      function getLocalLeaderboardStorageKey(periodKey) {\r\n        return \"bulldogle_ranked_demo_scores_\" + GAME_KEY + \"_\" + periodKey;\r\n      }\r\n\r\n      function getLocalPlayerId() {\r\n        const storageKey = \"bulldogle_ranked_demo_player_id\";\r\n        try {\r\n          let value = window.localStorage.getItem(storageKey);\r\n          if (!value) {\r\n            value = \"demo-\" + String(hashString(String(Date.now()) + \"|\" + Math.random()));\r\n            window.localStorage.setItem(storageKey, value);\r\n          }\r\n          return value;\r\n        } catch (_) {\r\n          return \"demo-player\";\r\n        }\r\n      }\r\n\r\n      function sortLeaderboardRows(rows) {\r\n        return rows.slice().sort((left, right) => {\r\n          const scoreDiff = Number(right.score || 0) - Number(left.score || 0);\r\n          if (scoreDiff !== 0) return scoreDiff;\r\n          return String(left.updated_at || \"\").localeCompare(String(right.updated_at || \"\"));\r\n        });\r\n      }\r\n\r\n      function seedLocalLeaderboardRows(periodKey) {\r\n        const names = [\r\n          \"Tony Demo\",\r\n          \"Classic Flow\",\r\n          \"Zero Otto\",\r\n          \"East Tape\",\r\n          \"B-side Kid\",\r\n          \"Metro Bars\",\r\n          \"Cloud Voice\",\r\n          \"Rima Nova\"\r\n        ];\r\n        const random = createSeededRandom(hashString(periodKey + \"|\" + GAME_KEY + \"|board\"));\r\n        return names.map((name, index) => ({\r\n          user_id: \"seed-\" + index,\r\n          display_name: name,\r\n          score: 7 + Math.floor(random() * 18) + (index === 0 ? 10 : 0),\r\n          updated_at: periodKey + \"-0\" + String((index % 8) + 1) + \" 12:00:00\"\r\n        }));\r\n      }\r\n\r\n      function readLocalLeaderboardRows(periodKey) {\r\n        const storageKey = getLocalLeaderboardStorageKey(periodKey);\r\n        try {\r\n          const raw = window.localStorage.getItem(storageKey);\r\n          if (raw) {\r\n            const parsed = JSON.parse(raw);\r\n            if (Array.isArray(parsed)) {\r\n              return sortLeaderboardRows(parsed.filter((row) => row && typeof row === \"object\"));\r\n            }\r\n          }\r\n        } catch (_) {}\r\n        const seeded = sortLeaderboardRows(seedLocalLeaderboardRows(periodKey));\r\n        try {\r\n          window.localStorage.setItem(storageKey, JSON.stringify(seeded));\r\n        } catch (_) {}\r\n        return seeded;\r\n      }\r\n\r\n      function writeLocalLeaderboardRows(periodKey, rows) {\r\n        const ordered = sortLeaderboardRows(rows);\r\n        try {\r\n          window.localStorage.setItem(getLocalLeaderboardStorageKey(periodKey), JSON.stringify(ordered));\r\n        } catch (_) {}\r\n        return ordered;\r\n      }\r\n\r\n      function buildPreparedLeaderboardRows(rows, currentName) {\r\n        return sortLeaderboardRows(rows).slice(0, 50).map((row, index) => ({\r\n          rank: index + 1,\r\n          display_name: String(row.display_name || \"Utente\"),\r\n          username: String(row.display_name || \"Utente\"),\r\n          score: Number(row.score || 0),\r\n          updated_at: String(row.updated_at || \"\"),\r\n          is_current: currentName && String(row.display_name || \"\") === String(currentName)\r\n        }));\r\n      }\r\n\r\n      function buildLocalLeaderboardPayload(limit) {\r\n        const periodKey = getCurrentPeriodKey();\r\n        const currentName = rankedConfig.displayName || \"Demo\";\r\n        const rows = buildPreparedLeaderboardRows(readLocalLeaderboardRows(periodKey), currentName);\r\n        return {\r\n          period_key: periodKey,\r\n          period_label: getPeriodLabel(periodKey),\r\n          leaderboard: rows.slice(0, limit)\r\n        };\r\n      }\r\n\r\n      function submitLocalRankedScore(score) {\r\n        const periodKey = getCurrentPeriodKey();\r\n        const playerId = getLocalPlayerId();\r\n        const currentName = rankedConfig.displayName || \"Demo\";\r\n        const now = new Date();\r\n        const timestamp = now.getFullYear() + \"-\" +\r\n          String(now.getMonth() + 1).padStart(2, \"0\") + \"-\" +\r\n          String(now.getDate()).padStart(2, \"0\") + \" \" +\r\n          String(now.getHours()).padStart(2, \"0\") + \":\" +\r\n          String(now.getMinutes()).padStart(2, \"0\") + \":\" +\r\n          String(now.getSeconds()).padStart(2, \"0\");\r\n\r\n        const rows = readLocalLeaderboardRows(periodKey);\r\n        const currentIndex = rows.findIndex((row) => String(row.user_id || \"\") === playerId);\r\n        const previousBest = currentIndex > -1 ? Number(rows[currentIndex].score || 0) : 0;\r\n        const isRecord = score > previousBest;\r\n\r\n        if (isRecord) {\r\n          const nextRow = {\r\n            user_id: playerId,\r\n            display_name: currentName,\r\n            score: Number(score || 0),\r\n            updated_at: timestamp\r\n          };\r\n\r\n          if (currentIndex > -1) {\r\n            rows[currentIndex] = nextRow;\r\n          } else {\r\n            rows.push(nextRow);\r\n          }\r\n        }\r\n\r\n        const savedRows = writeLocalLeaderboardRows(periodKey, rows);\r\n        const prepared = buildPreparedLeaderboardRows(savedRows, currentName);\r\n        const bestRankRow = prepared.find((row) => row.display_name === currentName && row.score === Math.max(score, previousBest));\r\n\r\n        return {\r\n          submitted_score: score,\r\n          best_score: Math.max(score, previousBest),\r\n          best_rank: bestRankRow ? bestRankRow.rank : null,\r\n          is_record: isRecord,\r\n          leaderboard: prepared,\r\n          game_key: GAME_KEY,\r\n          game_label: getModeDisplayName(),\r\n          period_key: periodKey,\r\n          period_label: getPeriodLabel(periodKey),\r\n          available_periods: [{ key: periodKey, label: getPeriodLabel(periodKey) }]\r\n        };\r\n      }\r\n\r\n      function findArtistByName(name) {\r\n        const normalized = normalize(name);\r\n        return artists.find((artist) => normalize(artist.name) === normalized);\r\n      }\r\n\r\n      function pickRandomArtist(excludedIds) {\r\n        const blocked = excludedIds || new Set();\r\n        let pool = artists.filter((artist) => !blocked.has(artist.id));\r\n        if (!pool.length) pool = artists.slice();\r\n        return pool[Math.floor(Math.random() * pool.length)];\r\n      }\r\n\r\n      function buildPopularityTrait(guessArtist, targetArtist) {\r\n        const guessIndex = getMonthlyListeners(guessArtist);\r\n        const targetIndex = getMonthlyListeners(targetArtist);\r\n        let status = \"wrong\";\r\n        let text = formatPopularityDisplay(guessArtist);\r\n        let arrow = \"\";\r\n\r\n        if (guessIndex && targetIndex) {\r\n          if (guessIndex === targetIndex) {\r\n            status = \"correct\";\r\n          } else {\r\n            if (Math.abs(guessIndex - targetIndex) \/ Math.max(targetIndex, 1) <= 0.2) {\r\n              status = \"close\";\r\n            }\r\n            arrow = targetIndex > guessIndex ? ARROWS.up : ARROWS.down;\r\n          }\r\n\r\n          return { label: \"Popolarita\", value: text, status: status, arrow: arrow, suffix: \"\" };\r\n        }\r\n\r\n        const guessFallbackIndex = getComparablePopularityIndex(guessArtist);\r\n        const targetFallbackIndex = getComparablePopularityIndex(targetArtist);\r\n\r\n        if (guessFallbackIndex >= 0 && targetFallbackIndex >= 0) {\r\n          if (guessFallbackIndex === targetFallbackIndex) {\r\n            status = \"correct\";\r\n          } else {\r\n            if (Math.abs(guessFallbackIndex - targetFallbackIndex) === 1) {\r\n              status = \"close\";\r\n            }\r\n            arrow = targetFallbackIndex > guessFallbackIndex ? ARROWS.up : ARROWS.down;\r\n          }\r\n        }\r\n\r\n        return { label: \"Popolarita\", value: text, status: status, arrow: arrow, suffix: \"\" };\r\n      }\r\n\r\n      function getRegionDirection(guessRegion, targetRegion) {\r\n        if (guessRegion === \"Estero\" && targetRegion !== \"Estero\") {\r\n          return { arrow: ARROWS.right, suffix: \"\ud83c\uddee\ud83c\uddf9\" };\r\n        }\r\n\r\n        if (targetRegion === \"Estero\" && guessRegion !== \"Estero\") {\r\n          return { arrow: ARROWS.right, suffix: \"\ud83c\udf0d\" };\r\n        }\r\n\r\n        const guessCoords = regionCoords[guessRegion];\r\n        const targetCoords = regionCoords[targetRegion];\r\n        if (!guessCoords || !targetCoords) return null;\r\n\r\n        const latDiff = targetCoords.lat - guessCoords.lat;\r\n        const lonDiff = targetCoords.lon - guessCoords.lon;\r\n        const threshold = 0.8;\r\n\r\n        if (Math.abs(latDiff) > threshold) {\r\n          return { arrow: latDiff > 0 ? ARROWS.up : ARROWS.down, suffix: \"\" };\r\n        }\r\n\r\n        return { arrow: lonDiff > 0 ? ARROWS.right : ARROWS.left, suffix: \"\" };\r\n      }\r\n\r\n      function buildCityTrait(guessArtist, targetArtist) {\r\n        let status = \"wrong\";\r\n        let value = guessArtist.city || \"N\/D\";\r\n        let arrow = \"\";\r\n        let suffix = \"\";\r\n\r\n        if (guessArtist.city === targetArtist.city) {\r\n          status = \"correct\";\r\n        } else if (guessArtist.region === targetArtist.region) {\r\n          status = \"close\";\r\n        } else {\r\n          const direction = getRegionDirection(guessArtist.region, targetArtist.region);\r\n          if (direction) {\r\n            arrow = direction.arrow;\r\n            suffix = direction.suffix;\r\n          }\r\n        }\r\n\r\n        return { label: \"Citta\", value: value, status: status, arrow: arrow, suffix: suffix };\r\n      }\r\n\r\n      function buildDebutTrait(guessArtist, targetArtist) {\r\n        let status = \"wrong\";\r\n        let value = String(guessArtist.debutYear || \"N\/D\");\r\n        let arrow = \"\";\r\n        const diff = guessArtist.debutYear - targetArtist.debutYear;\r\n\r\n        if (diff === 0) {\r\n          status = \"correct\";\r\n        } else {\r\n          if (Math.abs(diff) <= 5) {\r\n            status = \"close\";\r\n          }\r\n          arrow = targetArtist.debutYear > guessArtist.debutYear ? ARROWS.up : ARROWS.down;\r\n        }\r\n\r\n        return { label: \"Debutto\", value: value, status: status, arrow: arrow, suffix: \"\" };\r\n      }\r\n\r\n      function buildSimpleTrait(label, guessValue, targetValue, formatFn) {\r\n        const status = normalize(guessValue) === normalize(targetValue) ? \"correct\" : \"wrong\";\r\n        return {\r\n          label: label,\r\n          value: formatFn ? formatFn(guessValue) : (guessValue || \"N\/D\"),\r\n          status: status,\r\n          arrow: \"\",\r\n          suffix: \"\"\r\n        };\r\n      }\r\n\r\n      function buildTraits(guessArtist, targetArtist) {\r\n        return [\r\n          buildCityTrait(guessArtist, targetArtist),\r\n          buildDebutTrait(guessArtist, targetArtist),\r\n          buildSimpleTrait(\"Tipo\", guessArtist.members, targetArtist.members),\r\n          buildSimpleTrait(\"Voce\", guessArtist.gender, targetArtist.gender, formatGenderValue),\r\n          buildPopularityTrait(guessArtist, targetArtist)\r\n        ];\r\n      }\r\n\r\n      function buildResultEntry(guessArtist, targetArtist, meta) {\r\n        return {\r\n          guessArtist: guessArtist,\r\n          traits: buildTraits(guessArtist, targetArtist),\r\n          solved: guessArtist.id === targetArtist.id,\r\n          label: meta.label || \"Tentativo\",\r\n          subcopy: meta.subcopy || \"\",\r\n          kind: meta.kind || \"guess\"\r\n        };\r\n      }\r\n\r\n      function getArtistInitials(name) {\r\n        const parts = String(name || \"\").trim().split(\/\\s+\/).filter(Boolean);\r\n        if (!parts.length) return \"BM\";\r\n        return parts.slice(0, 2).map((part) => part.charAt(0)).join(\"\");\r\n      }\r\n\r\n      function persistSpotifyThumbnailUrl(spotifyId, thumbnailUrl) {\r\n        if (!spotifyId || !thumbnailUrl) return;\r\n        try {\r\n          const storedThumbs = JSON.parse(window.localStorage.getItem(spotifyThumbStorageKey) || \"{}\");\r\n          storedThumbs[spotifyId] = thumbnailUrl;\r\n          window.localStorage.setItem(spotifyThumbStorageKey, JSON.stringify(storedThumbs));\r\n        } catch (_) {}\r\n      }\r\n\r\n      function clearSpotifyThumbnailUrl(spotifyId) {\r\n        if (!spotifyId) return;\r\n        spotifyThumbCache.delete(spotifyId);\r\n        spotifyThumbRequests.delete(spotifyId);\r\n        try {\r\n          const storedThumbs = JSON.parse(window.localStorage.getItem(spotifyThumbStorageKey) || \"{}\");\r\n          delete storedThumbs[spotifyId];\r\n          window.localStorage.setItem(spotifyThumbStorageKey, JSON.stringify(storedThumbs));\r\n        } catch (_) {}\r\n      }\r\n\r\n      async function getSpotifyThumbnailUrl(spotifyId) {\r\n        if (!spotifyId) return \"\";\r\n        if (spotifyThumbCache.has(spotifyId)) {\r\n          return spotifyThumbCache.get(spotifyId);\r\n        }\r\n        if (spotifyThumbRequests.has(spotifyId)) {\r\n          return spotifyThumbRequests.get(spotifyId);\r\n        }\r\n\r\n        const request = (async function () {\r\n          const sources = [\r\n            \"https:\/\/open.spotify.com\/oembed?url=\" + encodeURIComponent(\"https:\/\/open.spotify.com\/artist\/\" + spotifyId),\r\n            \"https:\/\/open.spotify.com\/oembed?url=\" + encodeURIComponent(\"spotify:artist:\" + spotifyId)\r\n          ];\r\n\r\n          for (const source of sources) {\r\n            try {\r\n              const response = await fetch(source, { credentials: \"omit\" });\r\n              if (!response.ok) continue;\r\n              const payload = await response.json();\r\n              const thumbnailUrl = payload && payload.thumbnail_url ? String(payload.thumbnail_url) : \"\";\r\n              if (thumbnailUrl) {\r\n                spotifyThumbCache.set(spotifyId, thumbnailUrl);\r\n                persistSpotifyThumbnailUrl(spotifyId, thumbnailUrl);\r\n                return thumbnailUrl;\r\n              }\r\n            } catch (_) {}\r\n          }\r\n\r\n          return \"\";\r\n        })().finally(function () {\r\n          spotifyThumbRequests.delete(spotifyId);\r\n        });\r\n\r\n        spotifyThumbRequests.set(spotifyId, request);\r\n        return request;\r\n      }\r\n\r\n      function buildArtistCover(artist) {\r\n        const cover = document.createElement(\"div\");\r\n        cover.className = \"guess-cover\";\r\n\r\n        const fallback = document.createElement(\"span\");\r\n        fallback.className = \"guess-cover-fallback\";\r\n        fallback.textContent = getArtistInitials(artist.name);\r\n        cover.appendChild(fallback);\r\n\r\n        if (artist.spotifyId) {\r\n          getSpotifyThumbnailUrl(artist.spotifyId).then((thumbnailUrl) => {\r\n            if (!thumbnailUrl) return;\r\n            const image = document.createElement(\"img\");\r\n            image.alt = artist.name;\r\n            image.loading = \"eager\";\r\n            image.decoding = \"async\";\r\n            image.referrerPolicy = \"no-referrer\";\r\n\r\n            function applyThumbnail() {\r\n              cover.replaceChildren(image);\r\n            }\r\n\r\n            function handleThumbnailError() {\r\n              clearSpotifyThumbnailUrl(artist.spotifyId);\r\n            }\r\n\r\n            image.addEventListener(\"error\", handleThumbnailError, { once: true });\r\n            image.addEventListener(\"load\", applyThumbnail, { once: true });\r\n            image.src = thumbnailUrl;\r\n\r\n            if (image.complete) {\r\n              if (image.naturalWidth > 0) {\r\n                applyThumbnail();\r\n              } else {\r\n                handleThumbnailError();\r\n              }\r\n            }\r\n          });\r\n        }\r\n\r\n        return cover;\r\n      }\r\n\r\n      function buildResultCard(result) {\r\n        const article = document.createElement(\"article\");\r\n        article.className = \"guess-card\";\r\n        if (result.solved) article.classList.add(\"is-solved\");\r\n        if (result.kind === \"auto\") article.classList.add(\"is-auto\");\r\n\r\n        const top = document.createElement(\"div\");\r\n        top.className = \"guess-top\";\r\n\r\n        const cover = buildArtistCover(result.guessArtist);\r\n        const copy = document.createElement(\"div\");\r\n        copy.className = \"guess-copy\";\r\n\r\n        const badge = document.createElement(\"span\");\r\n        badge.className = \"guess-badge\";\r\n        badge.textContent = result.label;\r\n\r\n        const name = document.createElement(\"h4\");\r\n        name.className = \"guess-name\";\r\n        name.textContent = result.guessArtist.name;\r\n\r\n        copy.appendChild(badge);\r\n        copy.appendChild(name);\r\n\r\n        if (result.subcopy) {\r\n          const sub = document.createElement(\"p\");\r\n          sub.className = \"guess-sub\";\r\n          sub.textContent = result.subcopy;\r\n          copy.appendChild(sub);\r\n        }\r\n\r\n        top.appendChild(cover);\r\n        top.appendChild(copy);\r\n\r\n        const traits = document.createElement(\"div\");\r\n        traits.className = \"traits\";\r\n\r\n        result.traits.forEach((trait) => {\r\n          const traitNode = document.createElement(\"div\");\r\n          traitNode.className = \"trait is-\" + trait.status;\r\n\r\n          const label = document.createElement(\"span\");\r\n          label.className = \"trait-label\";\r\n          label.textContent = trait.label;\r\n\r\n          const value = document.createElement(\"span\");\r\n          value.className = \"trait-value\";\r\n\r\n          const valueText = document.createElement(\"span\");\r\n          valueText.className = \"trait-value-text\";\r\n          valueText.textContent = trait.value;\r\n          value.appendChild(valueText);\r\n\r\n          if (trait.arrow) {\r\n            const arrow = document.createElement(\"span\");\r\n            arrow.className = \"trait-arrow\";\r\n            arrow.textContent = trait.arrow;\r\n            value.appendChild(arrow);\r\n          }\r\n\r\n          if (trait.suffix) {\r\n            const suffix = document.createElement(\"span\");\r\n            suffix.className = \"trait-suffix\";\r\n            suffix.textContent = trait.suffix;\r\n            value.appendChild(suffix);\r\n          }\r\n\r\n          traitNode.appendChild(label);\r\n          traitNode.appendChild(value);\r\n          traits.appendChild(traitNode);\r\n        });\r\n\r\n        article.appendChild(top);\r\n        article.appendChild(traits);\r\n        return article;\r\n      }\r\n\r\n      function setMessage(text, tone) {\r\n        if (messageTimeoutId) {\r\n          window.clearTimeout(messageTimeoutId);\r\n          messageTimeoutId = 0;\r\n        }\r\n\r\n        elements.message.className = \"message\";\r\n        if (text && tone) {\r\n          elements.message.textContent = text;\r\n          elements.message.classList.add(\"is-visible\", \"is-\" + tone);\r\n\r\n          if (tone !== \"success\") {\r\n            messageTimeoutId = window.setTimeout(function () {\r\n              elements.message.className = \"message\";\r\n              elements.message.textContent = \"\";\r\n              messageTimeoutId = 0;\r\n            }, 2200);\r\n          }\r\n          return;\r\n        }\r\n\r\n        elements.message.textContent = \"\";\r\n      }\r\n\r\n      function disableGameInput(disabled) {\r\n        elements.input.disabled = disabled;\r\n        elements.submitButton.disabled = disabled || !state.active || state.betweenRounds || state.preparing || state.submitting;\r\n      }\r\n\r\n      function renderMeta() {\r\n        if (elements.timerValue) {\r\n          elements.timerValue.textContent = formatTime(state.timeLeft);\r\n        }\r\n        if (elements.scoreValue) {\r\n          elements.scoreValue.textContent = String(state.score);\r\n        }\r\n        if (elements.roundValue) {\r\n          elements.roundValue.textContent = state.active\r\n            ? \"Artista #\" + String(state.score + 1)\r\n            : (state.complete ? \"Fine\" : \"Pronto\");\r\n        }\r\n      }\r\n\r\n      function renderAttemptsCard() {\r\n        const attemptsLeft = Math.max(0, ROUND_ATTEMPTS - state.roundAttempts);\r\n        elements.attemptsCard.textContent = String(attemptsLeft) + \" \" + (attemptsLeft === 1 ? \"TENTATIVO\" : \"TENTATIVI\");\r\n      }\r\n\r\n      function renderInputState() {\r\n        disableGameInput(!state.active);\r\n        elements.input.placeholder = state.active ? \"inserisci un artista\" : (state.complete ? \"Partita conclusa\" : \"inserisci un artista\");\r\n      }\r\n\r\n      function renderActionButton() {\r\n        const button = elements.sideActionButton;\r\n        button.className = \"secondary-button is-primary\";\r\n        button.disabled = false;\r\n\r\n        if (state.preparing || state.submitting) {\r\n          button.textContent = \"...\";\r\n          button.disabled = true;\r\n          button.dataset.action = \"wait\";\r\n          return;\r\n        }\r\n\r\n        if (state.active) {\r\n          if (state.betweenRounds) {\r\n            button.textContent = \"ATTENDI\";\r\n            button.disabled = true;\r\n            button.dataset.action = \"wait\";\r\n            return;\r\n          }\r\n\r\n          button.textContent = \"SKIP\";\r\n          button.dataset.action = \"skip\";\r\n          return;\r\n        }\r\n\r\n        if (state.complete) {\r\n          button.textContent = \"RIGIOCA\";\r\n          button.dataset.action = \"restart\";\r\n          return;\r\n        }\r\n\r\n        if (hasBackend && !rankedConfig.isLoggedIn) {\r\n          button.textContent = \"ACCEDI\";\r\n          button.dataset.action = \"login\";\r\n          return;\r\n        }\r\n\r\n        button.textContent = \"INIZIA\";\r\n        button.dataset.action = \"start\";\r\n      }\r\n\r\n      function renderResults() {\r\n        elements.resultsList.innerHTML = \"\";\r\n\r\n        if (!state.results.length) {\r\n          const empty = document.createElement(\"div\");\r\n          empty.className = \"empty-state\";\r\n          empty.textContent = state.complete\r\n            ? \"La partita e finita. Puoi controllare il riepilogo finale.\"\r\n            : (state.active\r\n              ? \"I tentativi di questo round appariranno qui.\"\r\n              : (hasBackend && !rankedConfig.isLoggedIn ? \"ACCEDI per giocare.\" : \"Premi INIZIA per giocare.\"));\r\n          elements.resultsList.appendChild(empty);\r\n          return;\r\n        }\r\n\r\n        state.results.forEach((result) => {\r\n          elements.resultsList.appendChild(buildResultCard(result));\r\n        });\r\n      }\r\n\r\n      function renderSummary() {\r\n        elements.summaryPanel.classList.toggle(\"hidden\", !state.complete || !state.summaryLines.length);\r\n        elements.summaryPanel.classList.toggle(\"is-record\", state.isRecord);\r\n        elements.summaryTitle.textContent = state.summaryTitle || \"Partita conclusa\";\r\n        elements.summaryLines.innerHTML = \"\";\r\n\r\n        state.summaryLines.forEach((line) => {\r\n          const row = document.createElement(\"div\");\r\n          row.className = \"summary-line\";\r\n          row.innerHTML = line;\r\n          elements.summaryLines.appendChild(row);\r\n        });\r\n      }\r\n\r\n      function renderBoard() {\r\n        if (!elements.boardPeriod || !elements.boardList || !elements.boardMsg) {\r\n          return;\r\n        }\r\n\r\n        elements.boardPeriod.textContent = state.boardPeriodLabel || getPeriodLabel(getCurrentPeriodKey());\r\n        elements.boardList.innerHTML = \"\";\r\n\r\n        if (state.boardRows.length) {\r\n          state.boardRows.forEach((row) => {\r\n            const item = document.createElement(\"div\");\r\n            item.className = \"board-row\" + (row.is_current ? \" is-current\" : \"\");\r\n\r\n            const rank = document.createElement(\"strong\");\r\n            rank.className = \"board-rank\";\r\n            rank.textContent = \"#\" + row.rank;\r\n\r\n            const info = document.createElement(\"div\");\r\n            const name = document.createElement(\"div\");\r\n            name.className = \"board-name\";\r\n            name.textContent = row.display_name || \"Utente\";\r\n            const meta = document.createElement(\"div\");\r\n            meta.className = \"board-meta\";\r\n            meta.textContent = row.is_current ? \"Il tuo record\" : \"Record del mese\";\r\n            info.appendChild(name);\r\n            info.appendChild(meta);\r\n\r\n            const score = document.createElement(\"strong\");\r\n            score.className = \"board-score\";\r\n            score.textContent = String(row.score || 0);\r\n\r\n            item.appendChild(rank);\r\n            item.appendChild(info);\r\n            item.appendChild(score);\r\n            elements.boardList.appendChild(item);\r\n          });\r\n        }\r\n\r\n        if (state.boardLoading) {\r\n          elements.boardMsg.textContent = \"Caricamento classifica...\";\r\n          return;\r\n        }\r\n\r\n        if (state.boardMessage) {\r\n          elements.boardMsg.textContent = state.boardMessage;\r\n          return;\r\n        }\r\n\r\n        elements.boardMsg.textContent = state.boardRows.length\r\n          ? \"La classifica mostra il miglior record del mese.\"\r\n          : \"Nessun record disponibile per questo mese.\";\r\n      }\r\n\r\n      function renderApp() {\r\n        renderMeta();\r\n        renderAttemptsCard();\r\n        renderInputState();\r\n        renderActionButton();\r\n        renderResults();\r\n        renderSummary();\r\n        renderBoard();\r\n        hideSuggestions();\r\n      }\r\n\r\n      function positionSuggestions() {\r\n        const rect = elements.input.getBoundingClientRect();\r\n        const viewportPadding = 8;\r\n        const width = Math.max(240, rect.width);\r\n        const left = Math.min(\r\n          window.innerWidth - width - viewportPadding,\r\n          Math.max(viewportPadding, rect.left)\r\n        );\r\n        const viewportHeight = window.visualViewport ? window.visualViewport.height : window.innerHeight;\r\n        const spaceBelow = viewportHeight - rect.bottom - viewportPadding;\r\n        const maxHeight = Math.max(140, Math.min(280, spaceBelow - 8));\r\n\r\n        elements.suggestions.style.width = width + \"px\";\r\n        elements.suggestions.style.left = left + \"px\";\r\n        elements.suggestions.style.top = Math.max(viewportPadding, rect.bottom + 8) + \"px\";\r\n        elements.suggestions.style.maxHeight = maxHeight + \"px\";\r\n      }\r\n\r\n      function showSuggestions() {\r\n        positionSuggestions();\r\n        elements.suggestions.style.display = \"block\";\r\n      }\r\n\r\n      function hideSuggestions() {\r\n        elements.suggestions.style.display = \"none\";\r\n      }\r\n\r\n      function buildSuggestionList(matches) {\r\n        elements.suggestions.innerHTML = \"\";\r\n        matches.forEach((artist) => {\r\n          const button = document.createElement(\"button\");\r\n          button.type = \"button\";\r\n          button.className = \"suggestion\";\r\n\r\n          const left = document.createElement(\"span\");\r\n          left.textContent = artist.name;\r\n          const right = document.createElement(\"small\");\r\n          right.textContent = artist.city + \" \/ \" + formatPopularityDisplay(artist);\r\n\r\n          button.appendChild(left);\r\n          button.appendChild(right);\r\n          button.addEventListener(\"click\", function () {\r\n            elements.input.value = artist.name;\r\n            hideSuggestions();\r\n            elements.input.focus();\r\n          });\r\n          elements.suggestions.appendChild(button);\r\n        });\r\n\r\n        if (matches.length) {\r\n          showSuggestions();\r\n          return;\r\n        }\r\n\r\n        hideSuggestions();\r\n      }\r\n\r\n      function updateSuggestions() {\r\n        const value = normalize(elements.input.value);\r\n        if (!value || !state.active || state.betweenRounds || !state.currentArtist) {\r\n          hideSuggestions();\r\n          return;\r\n        }\r\n\r\n        const matches = artists.filter((artist) => {\r\n          return normalize(artist.name).includes(value) && !state.roundGuessedIds.has(artist.id);\r\n        }).slice(0, 8);\r\n\r\n        buildSuggestionList(matches);\r\n      }\r\n\r\n      function syncHelpPanelPlacement() {\r\n        if (!elements.helpPanel || !elements.helpPanelMobileSlot || !desktopHelpPanelParent) {\r\n          return;\r\n        }\r\n\r\n        const isMobileLayout = window.matchMedia(\"(max-width: 720px)\").matches;\r\n\r\n        if (isMobileLayout) {\r\n          if (elements.helpPanel.parentElement !== elements.helpPanelMobileSlot) {\r\n            elements.helpPanelMobileSlot.appendChild(elements.helpPanel);\r\n          }\r\n          return;\r\n        }\r\n\r\n        if (elements.helpPanel.parentElement === desktopHelpPanelParent) {\r\n          return;\r\n        }\r\n\r\n        if (desktopHelpPanelNextSibling && desktopHelpPanelNextSibling.parentElement === desktopHelpPanelParent) {\r\n          desktopHelpPanelParent.insertBefore(elements.helpPanel, desktopHelpPanelNextSibling);\r\n          return;\r\n        }\r\n\r\n        desktopHelpPanelParent.appendChild(elements.helpPanel);\r\n      }\r\n\r\n      async function postRankedAction(action, extraData) {\r\n        const body = new URLSearchParams({\r\n          action: action,\r\n          nonce: rankedConfig.nonce || \"\",\r\n          game_key: GAME_KEY,\r\n          ...(extraData || {})\r\n        });\r\n\r\n        const response = await fetch(rankedConfig.ajaxUrl, {\r\n          method: \"POST\",\r\n          credentials: \"same-origin\",\r\n          headers: {\r\n            \"Content-Type\": \"application\/x-www-form-urlencoded; charset=UTF-8\"\r\n          },\r\n          body: body.toString()\r\n        });\r\n\r\n        if (!response.ok) {\r\n          throw new Error(\"Richiesta ranked non riuscita\");\r\n        }\r\n\r\n        return response.json();\r\n      }\r\n\r\n      function resetGameState() {\r\n        state.active = false;\r\n        state.preparing = false;\r\n        state.submitting = false;\r\n        state.complete = false;\r\n        state.betweenRounds = false;\r\n        state.sessionToken = \"\";\r\n        state.currentArtist = null;\r\n        state.score = 0;\r\n        state.timeLeft = INITIAL_TIME;\r\n        state.roundAttempts = 0;\r\n        state.roundGuessedIds = new Set();\r\n        state.usedTargetIds = new Set();\r\n        state.freeHintArtist = null;\r\n        state.results = [];\r\n        state.summaryTitle = \"Partita conclusa\";\r\n        state.summaryLines = [];\r\n        state.isRecord = false;\r\n        window.clearInterval(state.timerId);\r\n        window.clearTimeout(state.roundTransitionId);\r\n        state.timerId = 0;\r\n        state.roundTransitionId = 0;\r\n      }\r\n\r\n      function applyLeaderboardData(data) {\r\n        const rows = Array.isArray(data && data.leaderboard) ? data.leaderboard : [];\r\n        const currentName = rankedConfig.displayName || state.boardCurrentName || \"Demo\";\r\n\r\n        state.boardRows = rows.slice(0, BOARD_LIMIT).map((row) => ({\r\n          rank: Number(row.rank || 0),\r\n          display_name: String(row.display_name || row.username || \"Utente\"),\r\n          score: Number(row.score || 0),\r\n          updated_at: String(row.updated_at || \"\"),\r\n          is_current: String(row.display_name || row.username || \"\") === String(currentName)\r\n        }));\r\n        state.boardPeriodLabel = data && data.period_label ? String(data.period_label) : getPeriodLabel(getCurrentPeriodKey());\r\n        state.boardMessage = \"\";\r\n      }\r\n\r\n      async function loadLeaderboard(force) {\r\n        if (!elements.boardPeriod || !elements.boardList || !elements.boardMsg) {\r\n          return;\r\n        }\r\n\r\n        if (state.boardLoading && !force) return;\r\n        state.boardLoading = true;\r\n        state.boardMessage = \"\";\r\n        renderBoard();\r\n\r\n        try {\r\n          if (hasBackend) {\r\n            const response = await postRankedAction(\"bulldogle_ranked_leaderboard\", {\r\n              period_key: getCurrentPeriodKey()\r\n            });\r\n\r\n            if (response && response.success && response.data) {\r\n              applyLeaderboardData(response.data);\r\n            } else {\r\n              state.boardRows = [];\r\n              state.boardMessage = \"Non riesco a caricare la classifica ora.\";\r\n            }\r\n          } else {\r\n            applyLeaderboardData(buildLocalLeaderboardPayload(BOARD_LIMIT));\r\n          }\r\n        } catch (_) {\r\n          state.boardRows = [];\r\n          state.boardMessage = \"Non riesco a caricare la classifica ora.\";\r\n        } finally {\r\n          state.boardLoading = false;\r\n          renderBoard();\r\n        }\r\n      }\r\n\r\n      function startNextArtist() {\r\n        if (!state.active) return;\r\n\r\n        window.clearTimeout(state.roundTransitionId);\r\n        state.betweenRounds = false;\r\n\r\n        if (state.usedTargetIds.size >= artists.length) {\r\n          state.usedTargetIds.clear();\r\n        }\r\n\r\n        const nextArtist = pickRandomArtist(state.usedTargetIds);\r\n        state.currentArtist = nextArtist;\r\n        state.usedTargetIds.add(nextArtist.id);\r\n        state.roundAttempts = 0;\r\n        state.roundGuessedIds = new Set();\r\n        state.results = [];\r\n\r\n        if (state.freeHintArtist) {\r\n          state.results.unshift(buildResultEntry(state.freeHintArtist, state.currentArtist, {\r\n            kind: \"auto\",\r\n            label: \"Reveal del Artista passato\"\r\n          }));\r\n          state.freeHintArtist = null;\r\n        }\r\n\r\n        elements.input.value = \"\";\r\n        hideSuggestions();\r\n        setMessage(\"\", \"\");\r\n        renderMeta();\r\n        renderAttemptsCard();\r\n        renderInputState();\r\n        renderActionButton();\r\n        renderResults();\r\n        elements.input.focus();\r\n      }\r\n\r\n      function completeRound(message, tone, carryArtist) {\r\n        if (!state.active || !state.currentArtist) return;\r\n\r\n        if (carryArtist) {\r\n          state.freeHintArtist = state.currentArtist;\r\n        }\r\n\r\n        state.betweenRounds = true;\r\n        elements.input.value = \"\";\r\n        hideSuggestions();\r\n        renderInputState();\r\n        renderActionButton();\r\n        setMessage(message, tone);\r\n\r\n        state.roundTransitionId = window.setTimeout(function () {\r\n          if (!state.active || state.timeLeft <= 0) return;\r\n          startNextArtist();\r\n        }, ROUND_TRANSITION_MS);\r\n      }\r\n\r\n      function tick() {\r\n        if (!state.active) return;\r\n        state.timeLeft -= 1;\r\n        renderMeta();\r\n        if (state.timeLeft <= 0) {\r\n          finishGame();\r\n        }\r\n      }\r\n\r\n      async function startRankedGame() {\r\n        if (state.active || state.preparing) return;\r\n\r\n        if (hasBackend && !rankedConfig.isLoggedIn) {\r\n          window.location.href = getLoginUrl();\r\n          return;\r\n        }\r\n\r\n        state.preparing = true;\r\n        state.complete = false;\r\n        state.summaryLines = [];\r\n        renderActionButton();\r\n\r\n        try {\r\n          if (hasBackend) {\r\n            const response = await postRankedAction(\"bulldogle_ranked_start\");\r\n            if (!response || !response.success || !response.data || !response.data.is_logged_in) {\r\n              window.location.href = getLoginUrl();\r\n              return;\r\n            }\r\n            state.sessionToken = String(response.data.token || \"\");\r\n            state.boardCurrentName = String(response.data.display_name || rankedConfig.displayName || \"Utente\");\r\n          } else {\r\n            state.sessionToken = \"demo-\" + String(Date.now());\r\n            state.boardCurrentName = String(rankedConfig.displayName || \"Demo\");\r\n          }\r\n\r\n          window.clearInterval(state.timerId);\r\n          window.clearTimeout(state.roundTransitionId);\r\n          state.active = true;\r\n          state.complete = false;\r\n          state.betweenRounds = false;\r\n          state.submitting = false;\r\n          state.score = 0;\r\n          state.timeLeft = INITIAL_TIME;\r\n          state.roundAttempts = 0;\r\n          state.roundGuessedIds = new Set();\r\n          state.usedTargetIds = new Set();\r\n          state.freeHintArtist = null;\r\n          state.results = [];\r\n          state.summaryTitle = \"Partita conclusa\";\r\n          state.summaryLines = [];\r\n          state.isRecord = false;\r\n          setMessage(\"\", \"\");\r\n          renderApp();\r\n          startNextArtist();\r\n          state.timerId = window.setInterval(tick, 1000);\r\n        } catch (_) {\r\n          setMessage(\"Non sono riuscito ad avviare la partita. Riprova tra poco.\", \"error\");\r\n        } finally {\r\n          state.preparing = false;\r\n          renderInputState();\r\n          renderActionButton();\r\n        }\r\n      }\r\n\r\n      function makeGuess() {\r\n        if (!state.active || state.betweenRounds || !state.currentArtist) return;\r\n\r\n        const guessName = elements.input.value.trim();\r\n        const guessArtist = findArtistByName(guessName);\r\n\r\n        if (!guessArtist) {\r\n          setMessage(\"Artista non trovato nella lista.\", \"error\");\r\n          return;\r\n        }\r\n\r\n        if (state.roundGuessedIds.has(guessArtist.id)) {\r\n          setMessage(\"Hai gia provato questo artista.\", \"error\");\r\n          elements.input.value = \"\";\r\n          return;\r\n        }\r\n\r\n        state.roundGuessedIds.add(guessArtist.id);\r\n        state.roundAttempts += 1;\r\n        state.results.unshift(buildResultEntry(guessArtist, state.currentArtist, {\r\n          label: \"Tentativo \" + state.roundAttempts\r\n        }));\r\n        renderAttemptsCard();\r\n        renderResults();\r\n        elements.input.value = \"\";\r\n        hideSuggestions();\r\n\r\n        if (guessArtist.id === state.currentArtist.id) {\r\n          state.score += 1;\r\n          state.timeLeft += CORRECT_BONUS;\r\n          renderMeta();\r\n          completeRound(\"Hai indovinato!\", \"success\", true);\r\n          return;\r\n        }\r\n\r\n        if (state.roundAttempts >= ROUND_ATTEMPTS) {\r\n          completeRound(\"Hai finito i tentativi! Era \" + state.currentArtist.name + \".\", \"error\", true);\r\n        }\r\n      }\r\n\r\n      function skipArtist() {\r\n        if (!state.active || state.betweenRounds || !state.currentArtist) return;\r\n\r\n        state.timeLeft = Math.max(0, state.timeLeft - SKIP_PENALTY);\r\n        renderMeta();\r\n\r\n        if (state.timeLeft <= 0) {\r\n          finishGame();\r\n          return;\r\n        }\r\n\r\n        completeRound(\"Hai skippato! Era \" + state.currentArtist.name + \".\", \"error\", true);\r\n      }\r\n\r\n      function buildSummaryLines(data) {\r\n        const lines = [];\r\n        if (state.currentArtist && state.currentArtist.name) {\r\n          lines.push(\"L'ultimo artista era: <strong>\" + escapeHtml(state.currentArtist.name) + \"<\/strong>\");\r\n        }\r\n        lines.push(\"Punteggio finale: <strong>\" + String(state.score) + \"<\/strong>\");\r\n\r\n        if (data) {\r\n          if (typeof data.best_score !== \"undefined\") {\r\n            lines.push(\"Record mensile: <strong>\" + String(data.best_score) + \"<\/strong>\");\r\n          }\r\n\r\n          if (data.best_rank) {\r\n            lines.push(\"Migliore posizione: <strong>#\" + String(data.best_rank) + \"<\/strong>\");\r\n          } else {\r\n            lines.push(\"Migliore posizione: <strong>Fuori top 50<\/strong>\");\r\n          }\r\n        } else {\r\n          lines.push(\"Record non salvato, riprova piu tardi.\");\r\n        }\r\n\r\n        return lines;\r\n      }\r\n\r\n      async function finishGame() {\r\n        if (!state.active || state.submitting) return;\r\n\r\n        state.active = false;\r\n        state.complete = true;\r\n        state.betweenRounds = false;\r\n        state.submitting = true;\r\n        state.timeLeft = 0;\r\n        window.clearInterval(state.timerId);\r\n        window.clearTimeout(state.roundTransitionId);\r\n        state.timerId = 0;\r\n        state.roundTransitionId = 0;\r\n        hideSuggestions();\r\n        setMessage(\"\", \"\");\r\n        renderMeta();\r\n        renderInputState();\r\n        renderActionButton();\r\n\r\n        state.summaryTitle = \"Partita conclusa\";\r\n        state.summaryLines = [\"Salvataggio record...\"];\r\n        state.isRecord = false;\r\n        renderSummary();\r\n\r\n        try {\r\n          let data = null;\r\n\r\n          if (hasBackend) {\r\n            const response = await postRankedAction(\"bulldogle_ranked_submit\", {\r\n              token: state.sessionToken,\r\n              score: String(state.score)\r\n            });\r\n            data = response && response.success ? response.data : null;\r\n          } else {\r\n            data = submitLocalRankedScore(state.score);\r\n          }\r\n\r\n          if (data) {\r\n            state.summaryTitle = data.is_record ? \"Nuovo record!\" : \"Partita conclusa\";\r\n            state.summaryLines = buildSummaryLines(data);\r\n            state.isRecord = Boolean(data.is_record);\r\n            applyLeaderboardData(data);\r\n            window.dispatchEvent(new CustomEvent(\"bulldogleRankedLeaderboardRefresh\", { detail: data }));\r\n          } else {\r\n            state.summaryTitle = \"Partita conclusa\";\r\n            state.summaryLines = buildSummaryLines(null);\r\n            state.isRecord = false;\r\n          }\r\n        } catch (_) {\r\n          state.summaryTitle = \"Partita conclusa\";\r\n          state.summaryLines = buildSummaryLines(null);\r\n          state.isRecord = false;\r\n        } finally {\r\n          state.submitting = false;\r\n          renderApp();\r\n        }\r\n      }\r\n\r\n      function escapeHtml(value) {\r\n        const div = document.createElement(\"div\");\r\n        div.textContent = value || \"\";\r\n        return div.innerHTML;\r\n      }\r\n\r\n      function handleSideAction() {\r\n        const action = elements.sideActionButton.dataset.action;\r\n\r\n        if (action === \"login\") {\r\n          window.location.href = getLoginUrl();\r\n          return;\r\n        }\r\n\r\n        if (action === \"start\" || action === \"restart\") {\r\n          startRankedGame();\r\n          return;\r\n        }\r\n\r\n        if (action === \"skip\") {\r\n          skipArtist();\r\n        }\r\n      }\r\n\r\n      if (elements.helpToggle && elements.helpPanel) {\r\n        elements.helpToggle.addEventListener(\"click\", function () {\r\n          const isOpen = elements.helpPanel.classList.toggle(\"is-open\");\r\n          elements.helpPanel.setAttribute(\"aria-hidden\", isOpen ? \"false\" : \"true\");\r\n          elements.helpToggle.classList.toggle(\"is-active\", isOpen);\r\n        });\r\n      }\r\n\r\n      if (elements.boardScrollButton && elements.leaderboardPanel) {\r\n        elements.boardScrollButton.addEventListener(\"click\", function () {\r\n          elements.leaderboardPanel.scrollIntoView({ behavior: \"smooth\", block: \"start\" });\r\n        });\r\n      }\r\n\r\n      if (elements.sideActionButton) {\r\n        elements.sideActionButton.addEventListener(\"click\", handleSideAction);\r\n      }\r\n\r\n      if (elements.guessForm) {\r\n        elements.guessForm.addEventListener(\"submit\", function (event) {\r\n          event.preventDefault();\r\n          makeGuess();\r\n        });\r\n      }\r\n\r\n      if (elements.input) {\r\n        elements.input.addEventListener(\"input\", updateSuggestions);\r\n        elements.input.addEventListener(\"focus\", updateSuggestions);\r\n      }\r\n\r\n      document.addEventListener(\"click\", function (event) {\r\n        if (!elements.suggestions.contains(event.target) && event.target !== elements.input) {\r\n          hideSuggestions();\r\n        }\r\n      });\r\n\r\n      window.addEventListener(\"resize\", function () {\r\n        syncHelpPanelPlacement();\r\n        if (elements.suggestions.style.display === \"block\") {\r\n          positionSuggestions();\r\n        }\r\n      });\r\n\r\n      window.addEventListener(\"scroll\", function () {\r\n        if (elements.suggestions.style.display === \"block\") {\r\n          positionSuggestions();\r\n        }\r\n      }, true);\r\n\r\n      if (window.visualViewport) {\r\n        window.visualViewport.addEventListener(\"resize\", function () {\r\n          syncHelpPanelPlacement();\r\n          if (elements.suggestions.style.display === \"block\") {\r\n            positionSuggestions();\r\n          }\r\n        });\r\n\r\n        window.visualViewport.addEventListener(\"scroll\", function () {\r\n          if (elements.suggestions.style.display === \"block\") {\r\n            positionSuggestions();\r\n          }\r\n        });\r\n      }\r\n\r\n      window.addEventListener(\"bulldogleRankedLeaderboardRefresh\", function (event) {\r\n        if (!event.detail) return;\r\n        applyLeaderboardData(event.detail);\r\n        renderBoard();\r\n      });\r\n\r\n      resetGameState();\r\n      syncHelpPanelPlacement();\r\n      renderApp();\r\n      loadLeaderboard();\r\n    })();\r\n  <\/script>\r\n<\/body>\r\n<\/html>\r\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-61aa0da2 elementor-widget elementor-widget-html\" data-id=\"61aa0da2\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t\t<div class=\"ranked-board-widget ranked-sidebar-board\" data-game-key=\"classic\">\n  <div class=\"ranked-sidebar-board-inner\">\n    <div class=\"ranked-board-controls\" aria-label=\"Seleziona mese classifica\">\n      <select class=\"ranked-board-period-select\">\n        <option value=\"\">Caricamento...<\/option>\n      <\/select>\n    <\/div>\n\n    <img decoding=\"async\" class=\"ranked-sidebar-board-heading-image\" src=\"https:\/\/bulldogmusik.it\/wp-content\/uploads\/2026\/05\/LeadBasico.png\" alt=\"Classifica\">\n\n    <div class=\"ranked-board-list\"><\/div>\n\n    <div class=\"ranked-board-pager\">\n      <button class=\"ranked-board-prev\" type=\"button\" aria-label=\"Pagina precedente\">&#8249;<\/button>\n      <span class=\"ranked-board-page\">1\/1<\/span>\n      <button class=\"ranked-board-next\" type=\"button\" aria-label=\"Pagina successiva\">&#8250;<\/button>\n    <\/div>\n\n    <div class=\"ranked-board-msg\">Caricamento classifica...<\/div>\n  <\/div>\n<\/div>\n\n<script src=\"\/bulldogle\/ranked-leaderboard.js?v=58\"><\/script>\n\n<style>\n.ranked-sidebar-board {\n  --ranked-accent: #952800;\n  --ranked-accent-2: #a83100;\n  --ranked-accent-3: #7d2100;\n  --ranked-ink: #17110d;\n  --ranked-ink-soft: rgba(23, 17, 13, 0.72);\n  --ranked-cream: #f8f0e8;\n  width: 100%;\n  max-width: 100%;\n  margin: 0;\n  font-family: Verdana, Geneva, sans-serif;\n}\n\n.ranked-sidebar-board-inner {\n  position: relative;\n  width: 100%;\n  padding: 22px 22px 20px;\n  border-radius: 34px;\n  overflow: hidden;\n  background: var(--ranked-accent);\n  box-shadow:\n    inset 0 1px 0 rgba(255, 255, 255, 0.16),\n    0 18px 34px rgba(0, 0, 0, 0.18);\n  color: var(--ranked-ink);\n  text-align: center;\n}\n\n.ranked-sidebar-board-heading-image {\n  display: block;\n  width: min(100%, 206px) !important;\n  height: auto;\n  margin: 2px auto 16px;\n}\n\n.ranked-sidebar-board .ranked-board-controls {\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  margin-bottom: 12px;\n}\n\n.ranked-sidebar-board .ranked-board-controls select {\n  width: 100% !important;\n  max-width: 182px;\n  min-width: 0;\n  height: 40px;\n  padding: 0 14px !important;\n  border: 1px solid rgba(23, 17, 13, 0.12) !important;\n  border-radius: 999px !important;\n  background: rgba(12, 8, 6, 0.9) !important;\n  color: var(--ranked-cream) !important;\n  font-family: Verdana, Geneva, sans-serif;\n  font-size: 12px !important;\n  font-weight: 700;\n  text-align: center;\n  box-shadow: none !important;\n  outline: none;\n  appearance: none;\n  -webkit-appearance: none;\n}\n\n.ranked-sidebar-board .ranked-board-list {\n  display: grid;\n  gap: 10px;\n  margin: 0;\n}\n\n.ranked-sidebar-board .ranked-board-row {\n  display: grid;\n  grid-template-columns: 66px minmax(0, 1fr) 64px;\n  align-items: center;\n  gap: 8px;\n  min-height: 52px;\n  padding: 10px 14px;\n  border: 0;\n  border-radius: 18px;\n  background: #000000;\n  color: var(--ranked-cream);\n  text-align: center;\n}\n\n.ranked-sidebar-board .ranked-board-row:first-child {\n  background: #000000;\n}\n\n.ranked-sidebar-board .ranked-board-rank {\n  color: #ffffff;\n  font-size: 13px;\n  font-weight: 700;\n}\n\n.ranked-sidebar-board .ranked-board-name {\n  min-width: 0;\n  overflow: hidden;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  color: #ffffff;\n  font-size: 13px;\n  font-weight: 700;\n}\n\n.ranked-sidebar-board .ranked-board-score {\n  color: #ffffff;\n  font-size: 13px;\n  font-weight: 700;\n}\n\n.ranked-sidebar-board .ranked-board-pager {\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  gap: 12px;\n  margin-top: 14px;\n}\n\n.ranked-sidebar-board .ranked-board-pager button {\n  appearance: none !important;\n  display: inline-flex !important;\n  align-items: center !important;\n  justify-content: center !important;\n  width: 36px !important;\n  min-width: 36px !important;\n  height: 36px !important;\n  min-height: 36px !important;\n  padding: 0 !important;\n  margin: 0 !important;\n  border: 1px solid rgba(23, 17, 13, 0.12) !important;\n  border-radius: 999px !important;\n  background: #000000 !important;\n  color: #ffffff !important;\n  font-family: Verdana, Geneva, sans-serif !important;\n  font-size: 23px !important;\n  font-weight: 700 !important;\n  line-height: 1 !important;\n  box-shadow: none !important;\n  cursor: pointer;\n  transform: none !important;\n}\n\n.ranked-sidebar-board .ranked-board-pager button:hover {\n  background: #ffffff !important;\n  color: var(--ranked-ink) !important;\n}\n\n.ranked-sidebar-board .ranked-board-pager button:disabled {\n  opacity: 0.34;\n  cursor: not-allowed;\n}\n\n.ranked-sidebar-board .ranked-board-page {\n  color: rgba(23, 17, 13, 0.72);\n  font-size: 12px;\n  font-weight: 700;\n}\n\n.ranked-sidebar-board .ranked-board-msg {\n  min-height: 18px;\n  margin-top: 12px;\n  color: rgba(23, 17, 13, 0.72);\n  font-size: 12px;\n  line-height: 1.35;\n  font-weight: 700;\n  text-align: center;\n}\n\n@media (max-width: 767px) {\n  .ranked-sidebar-board-inner {\n    padding: 20px 18px 18px;\n    border-radius: 28px;\n  }\n\n  .ranked-sidebar-board .ranked-board-row {\n    grid-template-columns: 58px minmax(0, 1fr) 58px;\n    min-height: 48px;\n    padding: 9px 12px;\n  }\n\n  .ranked-sidebar-board-heading-image {\n    width: min(100%, 238px);\n  }\n}\n<\/style>\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\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-7d057094 elementor-hidden-desktop elementor-hidden-tablet e-flex e-con-boxed wcf-starter-animations-none e-con e-parent\" data-id=\"7d057094\" 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-c2ebe16 hide-when-ranked wcf-starter-animations-none elementor-widget elementor-widget-image\" data-id=\"c2ebe16\" data-element_type=\"widget\" data-e-type=\"widget\" data-settings=\"{&quot;wcf_starter_animations&quot;:&quot;none&quot;,&quot;wcf_anim_duration&quot;:1000,&quot;wcf_anim_delay&quot;:0,&quot;wcf_anim_ease&quot;:&quot;ease&quot;}\" data-widget_type=\"image.default\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"576\" src=\"https:\/\/bulldogmusik.it\/wp-content\/uploads\/2026\/05\/Bulldogle-Classico-New-1024x576.png\" class=\"attachment-large size-large wp-image-15033\" alt=\"\" srcset=\"https:\/\/bulldogmusik.it\/wp-content\/uploads\/2026\/05\/Bulldogle-Classico-New-1024x576.png 1024w, https:\/\/bulldogmusik.it\/wp-content\/uploads\/2026\/05\/Bulldogle-Classico-New-300x169.png 300w, https:\/\/bulldogmusik.it\/wp-content\/uploads\/2026\/05\/Bulldogle-Classico-New-768x432.png 768w, https:\/\/bulldogmusik.it\/wp-content\/uploads\/2026\/05\/Bulldogle-Classico-New-1320x742.png 1320w, https:\/\/bulldogmusik.it\/wp-content\/uploads\/2026\/05\/Bulldogle-Classico-New.png 1366w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-2b8ec14 show-when-ranked wcf-starter-animations-none elementor-widget elementor-widget-image\" data-id=\"2b8ec14\" data-element_type=\"widget\" data-e-type=\"widget\" data-settings=\"{&quot;wcf_starter_animations&quot;:&quot;none&quot;,&quot;wcf_anim_duration&quot;:1000,&quot;wcf_anim_delay&quot;:0,&quot;wcf_anim_ease&quot;:&quot;ease&quot;}\" data-widget_type=\"image.default\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"576\" src=\"https:\/\/bulldogmusik.it\/wp-content\/uploads\/2026\/05\/Bulldogle-Ranked-New-1-1024x576.png\" class=\"attachment-large size-large wp-image-15034\" alt=\"\" srcset=\"https:\/\/bulldogmusik.it\/wp-content\/uploads\/2026\/05\/Bulldogle-Ranked-New-1-1024x576.png 1024w, https:\/\/bulldogmusik.it\/wp-content\/uploads\/2026\/05\/Bulldogle-Ranked-New-1-300x169.png 300w, https:\/\/bulldogmusik.it\/wp-content\/uploads\/2026\/05\/Bulldogle-Ranked-New-1-768x432.png 768w, https:\/\/bulldogmusik.it\/wp-content\/uploads\/2026\/05\/Bulldogle-Ranked-New-1-1320x742.png 1320w, https:\/\/bulldogmusik.it\/wp-content\/uploads\/2026\/05\/Bulldogle-Ranked-New-1.png 1366w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-61e787ab elementor-widget elementor-widget-wcf--floating-elements\" data-id=\"61e787ab\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"wcf--floating-elements.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"wcf--floating-elements\">\r\n\t\t\t                <div class=\"floating-element wcf-live-anim-wiggle elementor-repeater-item-d4c5f46   \">\r\n\t\t\t\t\t<img decoding=\"async\" src=\"https:\/\/bulldogmusik.it\/wp-content\/uploads\/2026\/05\/Coppa.png\" alt=\"Coppa\" \/>\t\t\t\t<\/div>\r\n\t\t\t\t\t\t<\/div>\r\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-38e1cefa elementor-widget-divider--view-line_text elementor-widget-mobile__width-initial elementor-widget-divider--element-align-center elementor-widget elementor-widget-divider\" data-id=\"38e1cefa\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"divider.default\">\n\t\t\t\t\t\t\t<div class=\"elementor-divider\">\n\t\t\t<span class=\"elementor-divider-separator\">\n\t\t\t\t\t\t\t<span class=\"elementor-divider__text elementor-divider__element\">\n\t\t\t\tModalit\u00e0\t\t\t\t<\/span>\n\t\t\t\t\t\t<\/span>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-664dbe51 elementor-widget-mobile__width-initial elementor-widget elementor-widget-html\" data-id=\"664dbe51\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t\t<!DOCTYPE html>\r\n<html lang=\"it\">\r\n<head>\r\n  <meta charset=\"UTF-8\">\r\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\r\n  <title>Bulldogle Demo<\/title>\r\n  <link rel=\"preconnect\" href=\"https:\/\/fonts.googleapis.com\">\r\n  <link rel=\"preconnect\" href=\"https:\/\/fonts.gstatic.com\" crossorigin>\r\n  <link href=\"https:\/\/fonts.googleapis.com\/css2?family=Instrument+Sans:wght@400;500;600;700;800;900&family=Space+Grotesk:wght@500;700&display=swap\" rel=\"stylesheet\">\r\n  <style>\r\n    :root {\r\n      --bg: #000;\r\n      --panel: #070707;\r\n      --panel-2: #0b0b0b;\r\n      --line: rgba(255, 255, 255, 0.08);\r\n      --line-strong: rgba(241, 108, 29, 0.28);\r\n      --line-faint: rgba(255, 255, 255, 0.05);\r\n      --white: #f7f4ef;\r\n      --copy: rgba(247, 244, 239, 0.76);\r\n      --copy-soft: rgba(247, 244, 239, 0.54);\r\n      --copy-faint: rgba(247, 244, 239, 0.34);\r\n      --accent: #f16c1d;\r\n      --ranked-accent: #952800;\r\n      --ranked-line-strong: rgba(149, 40, 0, 0.28);\r\n      --success: #7dc56a;\r\n      --warning: #f0b955;\r\n      --radius-lg: 18px;\r\n      --radius-md: 14px;\r\n      --ease: 220ms cubic-bezier(.2,.9,.2,1);\r\n    }\r\n\r\n    * {\r\n      box-sizing: border-box;\r\n    }\r\n\r\n    html,\r\n    body {\r\n      margin: 0;\r\n      min-height: 100%;\r\n      background: var(--bg);\r\n      color: var(--white);\r\n      font-family: \"Instrument Sans\", system-ui, sans-serif;\r\n      overflow-x: hidden;\r\n    }\r\n\r\n    button,\r\n    input,\r\n    iframe {\r\n      font: inherit;\r\n    }\r\n\r\n    .demo-app {\r\n      width: min(760px, calc(100vw - 20px));\r\n      margin: 0 auto;\r\n      padding: 18px 0 24px;\r\n    }\r\n\r\n    .app-shell {\r\n      position: relative;\r\n      isolation: isolate;\r\n      padding: 14px;\r\n      border: 1px solid var(--line);\r\n      border-radius: 22px;\r\n      background: linear-gradient(180deg, rgba(14, 14, 14, 0.98), rgba(7, 7, 7, 0.98));\r\n      overflow: visible;\r\n      box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.03);\r\n    }\r\n\r\n    .app-shell::after {\r\n      content: \"\";\r\n      position: absolute;\r\n      inset: 0;\r\n      border-radius: inherit;\r\n      background-image: url(\"data:image\/svg+xml,%3Csvg%20xmlns='http:\/\/www.w3.org\/2000\/svg'%20viewBox='0%200%20180%20180'%3E%3Cfilter%20id='n'%3E%3CfeTurbulence%20type='fractalNoise'%20baseFrequency='.9'%20numOctaves='3'%20stitchTiles='stitch'\/%3E%3CfeColorMatrix%20type='saturate'%20values='0'\/%3E%3CfeComponentTransfer%3E%3CfeFuncA%20type='table'%20tableValues='0%20.58'\/%3E%3C\/feComponentTransfer%3E%3C\/filter%3E%3Crect%20width='180'%20height='180'%20filter='url(%23n)'%20opacity='1'\/%3E%3C\/svg%3E\");\r\n      background-size: 180px 180px;\r\n      mix-blend-mode: overlay;\r\n      opacity: 0.1;\r\n      pointer-events: none;\r\n    }\r\n\r\n    .app-shell > * {\r\n      position: relative;\r\n      z-index: 1;\r\n    }\r\n\r\n    .topbar {\r\n      display: flex;\r\n      flex-direction: column;\r\n      align-items: center;\r\n      gap: 0;\r\n      padding: 10px 8px 14px;\r\n    }\r\n\r\n    .top-logo {\r\n      display: block;\r\n      width: min(320px, 58vw);\r\n      height: auto;\r\n    }\r\n\r\n    .shell {\r\n      margin-top: 0;\r\n      padding-top: 14px;\r\n      border-top: 1px solid var(--line);\r\n    }\r\n\r\n    .controls-shell {\r\n      margin-top: 0;\r\n      padding: 14px 0;\r\n      border-top: 1px solid var(--line);\r\n    }\r\n\r\n    .controls-inner {\r\n      display: grid;\r\n      grid-template-columns: repeat(3, minmax(0, 1fr));\r\n      gap: 8px;\r\n    }\r\n\r\n    .game-shell {\r\n      position: relative;\r\n      padding: 2px 0 6px;\r\n      overflow: visible;\r\n    }\r\n\r\n    .mode-tabs,\r\n    .top-actions {\r\n      display: flex;\r\n      gap: 8px;\r\n      flex-wrap: wrap;\r\n      align-items: center;\r\n    }\r\n\r\n    .mode-tabs,\r\n    .top-actions {\r\n      width: 100%;\r\n      justify-content: stretch;\r\n    }\r\n\r\n    .controls-inner .tab,\r\n    .controls-inner .ghost-button {\r\n      width: 100%;\r\n      min-width: 0;\r\n      min-height: 56px;\r\n      height: 56px;\r\n      padding: 0 22px;\r\n      border-radius: 12px;\r\n      font-size: 15px;\r\n      line-height: 1.1;\r\n      text-transform: uppercase;\r\n    }\r\n\r\n    .tab-ranked-mobile {\r\n      display: none;\r\n    }\r\n\r\n    .controls-inner .tab-ranked-mobile {\r\n      display: none !important;\r\n    }\r\n\r\n    .demo-app.is-ranked-mode .hide-when-ranked,\r\n    body.bulldogle-ranked-mode-active .hide-when-ranked,\r\n    html.bulldogle-ranked-mode-active .hide-when-ranked,\r\n    .demo-app.is-ranked-mode .hide.when.ranked,\r\n    body.bulldogle-ranked-mode-active .hide.when.ranked,\r\n    html.bulldogle-ranked-mode-active .hide.when.ranked {\r\n      display: none !important;\r\n    }\r\n\r\n    .show-when-ranked,\r\n    .show.when.ranked,\r\n    .show-when-ranked-flex,\r\n    .show.flex.when.ranked,\r\n    .show-when-ranked-grid,\r\n    .show.grid.when.ranked,\r\n    .show-when-ranked-inline {\r\n      display: none !important;\r\n    }\r\n\r\n    .demo-app.is-ranked-mode .show-when-ranked,\r\n    body.bulldogle-ranked-mode-active .show-when-ranked,\r\n    html.bulldogle-ranked-mode-active .show-when-ranked,\r\n    .demo-app.is-ranked-mode .show.when.ranked,\r\n    body.bulldogle-ranked-mode-active .show.when.ranked,\r\n    html.bulldogle-ranked-mode-active .show.when.ranked {\r\n      display: block !important;\r\n    }\r\n\r\n    .demo-app.is-ranked-mode .show-when-ranked-flex,\r\n    body.bulldogle-ranked-mode-active .show-when-ranked-flex,\r\n    html.bulldogle-ranked-mode-active .show-when-ranked-flex,\r\n    .demo-app.is-ranked-mode .show.flex.when.ranked,\r\n    body.bulldogle-ranked-mode-active .show.flex.when.ranked,\r\n    html.bulldogle-ranked-mode-active .show.flex.when.ranked {\r\n      display: flex !important;\r\n    }\r\n\r\n    .demo-app.is-ranked-mode .show-when-ranked-grid,\r\n    body.bulldogle-ranked-mode-active .show-when-ranked-grid,\r\n    html.bulldogle-ranked-mode-active .show-when-ranked-grid,\r\n    .demo-app.is-ranked-mode .show.grid.when.ranked,\r\n    body.bulldogle-ranked-mode-active .show.grid.when.ranked,\r\n    html.bulldogle-ranked-mode-active .show.grid.when.ranked {\r\n      display: grid !important;\r\n    }\r\n\r\n    .demo-app.is-ranked-mode .show-when-ranked-inline,\r\n    body.bulldogle-ranked-mode-active .show-when-ranked-inline,\r\n    html.bulldogle-ranked-mode-active .show-when-ranked-inline {\r\n      display: inline-flex !important;\r\n    }\r\n\r\n    .tab,\r\n    .ghost-button,\r\n    .button,\r\n    .secondary-button {\r\n      display: inline-flex;\r\n      align-items: center;\r\n      justify-content: center;\r\n      min-height: 32px;\r\n      padding: 0 13px;\r\n      border-radius: 999px;\r\n      border: 1px solid var(--line);\r\n      background: rgba(255, 255, 255, 0.03);\r\n      color: var(--white);\r\n      font-size: 11px;\r\n      font-weight: 700;\r\n      cursor: pointer;\r\n      transition: transform var(--ease), border-color var(--ease), background var(--ease), color var(--ease);\r\n    }\r\n\r\n    .tab.is-active,\r\n    .ghost-button.is-active {\r\n      border-color: var(--line-strong);\r\n      background: rgba(241, 108, 29, 0.12);\r\n    }\r\n\r\n    .demo-app.is-ranked-mode .tab-ranked-mobile.is-active,\r\n    .demo-app.is-ranked-mode .ghost-button.is-active {\r\n      border-color: var(--ranked-line-strong);\r\n      background: rgba(149, 40, 0, 0.12);\r\n    }\r\n\r\n    .button {\r\n      min-width: 152px;\r\n      min-height: 56px;\r\n      padding: 0 22px;\r\n      border-radius: 12px;\r\n      background: var(--accent);\r\n      border-color: var(--accent);\r\n      color: #111;\r\n      font-size: 15px;\r\n      font-weight: 700;\r\n      letter-spacing: 0;\r\n      text-transform: uppercase;\r\n      box-shadow: none;\r\n    }\r\n\r\n    .button:hover {\r\n      background: #fff;\r\n      border-color: #fff;\r\n      color: #111;\r\n    }\r\n\r\n    .secondary-button {\r\n      min-width: 152px;\r\n      min-height: 56px;\r\n      padding: 0 22px;\r\n      border-radius: 12px;\r\n      background: var(--accent);\r\n      border-color: var(--accent);\r\n      color: #111;\r\n      font-size: 15px;\r\n      font-weight: 700;\r\n      letter-spacing: 0;\r\n      text-transform: uppercase;\r\n      box-shadow: none;\r\n    }\r\n\r\n    .secondary-button:hover {\r\n      background: #fff;\r\n      border-color: #fff;\r\n      color: #111;\r\n    }\r\n\r\n    .streak-card.is-guest:hover {\r\n      background: #fff;\r\n      border-color: #fff;\r\n      color: #111;\r\n    }\r\n\r\n    .streak-card.is-guest:hover .streak-sub {\r\n      color: rgba(17, 17, 17, 0.74);\r\n    }\r\n\r\n    .tab:hover,\r\n    .ghost-button:hover,\r\n    .button:hover,\r\n    .secondary-button:hover,\r\n    .streak-card.is-guest:hover,\r\n    .suggestion:hover {\r\n      transform: translateY(-1px);\r\n    }\r\n\r\n    .help-panel {\r\n      max-height: 0;\r\n      overflow: hidden;\r\n      padding-bottom: 0;\r\n      border-bottom: 1px solid transparent;\r\n      transition: max-height 240ms ease, margin 240ms ease, padding-bottom 240ms ease, border-color 240ms ease;\r\n      margin: 0;\r\n    }\r\n\r\n    .help-panel.is-open {\r\n      max-height: 1200px;\r\n      padding-bottom: 12px;\r\n      border-bottom-color: var(--line);\r\n      margin: 0 0 12px;\r\n    }\r\n\r\n    .help-panel-mobile-slot {\r\n      display: none;\r\n    }\r\n\r\n    .help-grid {\r\n      display: grid;\r\n      grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));\r\n      gap: 10px;\r\n    }\r\n\r\n    .help-card {\r\n      min-height: 100%;\r\n      padding: 12px 13px;\r\n      border: 1px solid var(--line);\r\n      border-radius: 12px;\r\n      background: rgba(255, 255, 255, 0.03);\r\n    }\r\n\r\n    .help-card.is-legacy-hidden {\r\n      display: none;\r\n    }\r\n\r\n    .help-card strong {\r\n      display: block;\r\n      margin-bottom: 8px;\r\n      font-size: 13px;\r\n    }\r\n\r\n    .help-card span {\r\n      display: block;\r\n      color: var(--copy-soft);\r\n      font-size: 12px;\r\n      line-height: 1.45;\r\n    }\r\n\r\n    .ranked-mode-panel {\r\n      display: grid;\r\n      gap: 12px;\r\n    }\r\n\r\n    .ranked-mode-panel > .results-list,\r\n    .ranked-mode-panel > .message,\r\n    .ranked-mode-panel > .ranked-summary-panel {\r\n      width: 100%;\r\n      min-width: 0;\r\n      margin-left: 0;\r\n      margin-right: 0;\r\n      justify-self: stretch;\r\n    }\r\n\r\n    .ranked-mode-panel > .results-list {\r\n      margin-top: 6px;\r\n    }\r\n\r\n    .ranked-mode-panel.hidden {\r\n      display: none !important;\r\n    }\r\n\r\n    .ranked-meta-grid {\r\n      display: grid;\r\n      grid-template-columns: repeat(2, minmax(0, 1fr));\r\n      gap: 10px;\r\n      margin-bottom: 2px;\r\n    }\r\n\r\n    .ranked-meta-card {\r\n      min-height: 74px;\r\n      padding: 12px 14px;\r\n      border: 1px solid var(--line);\r\n      border-radius: 16px;\r\n      background: rgba(255, 255, 255, 0.03);\r\n      display: flex;\r\n      flex-direction: column;\r\n      justify-content: space-between;\r\n      gap: 8px;\r\n      text-align: left;\r\n    }\r\n\r\n    .ranked-meta-card.is-accent {\r\n      border-color: rgba(149, 40, 0, 0.24);\r\n      background: rgba(149, 40, 0, 0.08);\r\n    }\r\n\r\n    .ranked-meta-label {\r\n      display: block;\r\n      color: var(--copy-soft);\r\n      font-size: 11px;\r\n      font-weight: 800;\r\n      letter-spacing: 0.12em;\r\n      text-transform: uppercase;\r\n    }\r\n\r\n    .ranked-meta-value {\r\n      display: block;\r\n      font-family: \"Space Grotesk\", sans-serif;\r\n      font-size: clamp(24px, 3.2vw, 30px);\r\n      line-height: 1;\r\n      letter-spacing: -0.05em;\r\n    }\r\n\r\n    .ranked-summary-panel {\r\n      margin-top: 4px;\r\n      padding: 16px;\r\n      border: 1px solid rgba(149, 40, 0, 0.28);\r\n      border-radius: 18px;\r\n      background: rgba(149, 40, 0, 0.08);\r\n    }\r\n\r\n    .ranked-summary-panel.hidden {\r\n      display: none !important;\r\n    }\r\n\r\n    .ranked-summary-panel.is-record {\r\n      border-color: rgba(125, 197, 106, 0.32);\r\n      background: rgba(125, 197, 106, 0.08);\r\n    }\r\n\r\n    .ranked-summary-title {\r\n      margin: 0 0 10px;\r\n      color: var(--white);\r\n      font-family: \"Space Grotesk\", sans-serif;\r\n      font-size: clamp(22px, 4vw, 28px);\r\n      line-height: 1;\r\n      letter-spacing: -0.04em;\r\n      font-weight: 900;\r\n    }\r\n\r\n    .ranked-summary-lines {\r\n      display: grid;\r\n      gap: 5px;\r\n    }\r\n\r\n    .ranked-summary-line {\r\n      color: var(--white);\r\n      font-size: 14px;\r\n      line-height: 1.5;\r\n      font-weight: 600;\r\n    }\r\n\r\n    .ranked-summary-line strong {\r\n      font-weight: 800;\r\n    }\r\n\r\n    .demo-app.is-ranked-mode #mobileRankedGuessForm .button,\r\n    .demo-app.is-ranked-mode #mobileRankedGuessForm .secondary-button {\r\n      background: var(--ranked-accent);\r\n      border-color: var(--ranked-accent);\r\n      color: #111;\r\n    }\r\n\r\n    .input-grid {\r\n      display: grid;\r\n      grid-template-columns: 152px minmax(0, 1fr) 152px 152px;\r\n      gap: 10px;\r\n      align-items: stretch;\r\n      max-width: none;\r\n      margin: 0 auto;\r\n    }\r\n\r\n    .attempts-card {\r\n      display: flex;\r\n      align-items: center;\r\n      justify-content: center;\r\n      min-width: 152px;\r\n      padding: 0 22px;\r\n      border: 1px solid #fff;\r\n      border-radius: 12px;\r\n      background: #fff;\r\n      color: #111;\r\n      font-size: 15px;\r\n      font-weight: 700;\r\n      letter-spacing: 0;\r\n      text-transform: uppercase;\r\n      text-align: center;\r\n      white-space: nowrap;\r\n      box-shadow: none;\r\n    }\r\n\r\n    .button,\r\n    .secondary-button,\r\n    .attempts-card {\r\n      font-family: \"Instrument Sans\", system-ui, sans-serif;\r\n      font-size: 15px;\r\n      line-height: 1;\r\n      font-weight: 700;\r\n      letter-spacing: 0;\r\n      text-transform: uppercase;\r\n      font-variation-settings: \"wght\" 700;\r\n    }\r\n\r\n    .action-slot {\r\n      width: 152px;\r\n      min-width: 152px;\r\n      align-self: stretch;\r\n    }\r\n\r\n    .input-grid > .attempts-card,\r\n    .input-grid > .button,\r\n    .action-slot > .secondary-button,\r\n    .action-slot > .streak-card {\r\n      width: 100%;\r\n      min-width: 0;\r\n      min-height: 56px;\r\n      height: 56px;\r\n    }\r\n\r\n    .input-shell {\r\n      position: relative;\r\n      z-index: 5;\r\n    }\r\n\r\n    .input-label {\r\n      display: none;\r\n      margin: 0;\r\n      color: var(--white);\r\n      font-size: 15px;\r\n      font-weight: 700;\r\n      letter-spacing: -0.01em;\r\n      text-align: center;\r\n    }\r\n\r\n    .search-field {\r\n      width: 100%;\r\n      min-height: 56px;\r\n      padding: 0 16px;\r\n      border-radius: 12px;\r\n      border: 1px solid rgba(255, 255, 255, 0.1);\r\n      background: #101010;\r\n      color: var(--white);\r\n      font-size: 15px;\r\n      outline: none;\r\n      transition: border-color var(--ease), background var(--ease);\r\n    }\r\n\r\n    .search-field:focus {\r\n      border-color: rgba(255, 255, 255, 0.18);\r\n      background: #111;\r\n    }\r\n\r\n    .search-field::placeholder {\r\n      color: var(--copy-faint);\r\n    }\r\n\r\n    .search-field:disabled {\r\n      opacity: 0.5;\r\n      cursor: not-allowed;\r\n    }\r\n\r\n    .suggestions {\r\n      position: fixed;\r\n      top: 0;\r\n      left: 0;\r\n      width: 280px;\r\n      max-height: min(280px, calc(100dvh - 24px));\r\n      overflow-y: auto;\r\n      z-index: 2147483001;\r\n      display: none;\r\n      padding: 6px;\r\n      border: 1px solid var(--line);\r\n      border-radius: 14px;\r\n      background: rgba(9, 9, 9, 0.98);\r\n      box-shadow: 0 22px 50px rgba(0, 0, 0, 0.55);\r\n      backdrop-filter: blur(12px);\r\n      overscroll-behavior: contain;\r\n      -webkit-overflow-scrolling: touch;\r\n    }\r\n\r\n    .suggestion {\r\n      width: 100%;\r\n      display: flex;\r\n      justify-content: space-between;\r\n      gap: 8px;\r\n      padding: 11px 12px;\r\n      border: 0;\r\n      border-radius: 10px;\r\n      background: transparent;\r\n      color: var(--white);\r\n      text-align: left;\r\n      cursor: pointer;\r\n    }\r\n\r\n    .suggestion small {\r\n      color: var(--copy-faint);\r\n      font-size: 11px;\r\n    }\r\n\r\n    .input-grid > .attempts-card,\r\n    .input-grid > .button,\r\n    .input-grid > .action-slot {\r\n      align-self: stretch;\r\n      height: 56px;\r\n    }\r\n\r\n    .streak-card {\r\n      display: flex;\r\n      flex-direction: column;\r\n      align-items: center;\r\n      justify-content: center;\r\n      padding: 8px 14px;\r\n      border: 1px solid var(--accent);\r\n      border-radius: 12px;\r\n      background: var(--accent);\r\n      color: #111;\r\n      text-decoration: none;\r\n      box-shadow: none;\r\n    }\r\n\r\n    .streak-card:not(.is-guest) {\r\n      cursor: default;\r\n      pointer-events: none;\r\n    }\r\n\r\n    .streak-card:not(.is-guest):hover {\r\n      background: var(--accent);\r\n      border-color: var(--accent);\r\n      color: #111;\r\n      transform: none;\r\n    }\r\n\r\n    .streak-card:not(.is-guest):hover .streak-sub {\r\n      color: rgba(17, 17, 17, 0.74);\r\n    }\r\n\r\n    .streak-card.is-guest {\r\n      cursor: pointer;\r\n    }\r\n\r\n    .streak-main {\r\n      display: block;\r\n      font-size: 15px;\r\n      line-height: 1;\r\n      font-weight: 700;\r\n      letter-spacing: 0;\r\n      text-transform: uppercase;\r\n    }\r\n\r\n    .streak-sub {\r\n      display: block;\r\n      margin-top: 4px;\r\n      color: rgba(17, 17, 17, 0.74);\r\n      font-size: 9px;\r\n      line-height: 1.2;\r\n      font-weight: 700;\r\n      text-transform: none;\r\n      letter-spacing: 0;\r\n      text-align: center;\r\n    }\r\n\r\n    .message {\r\n      display: none;\r\n      width: 100%;\r\n      max-width: none;\r\n      margin: 12px 0 0;\r\n      padding: 10px 12px;\r\n      border-radius: 999px;\r\n      border: 1px solid var(--line);\r\n      background: rgba(255, 255, 255, 0.03);\r\n      color: var(--copy);\r\n      font-size: 13px;\r\n      line-height: 1.45;\r\n      text-align: center;\r\n    }\r\n\r\n    .message.is-visible {\r\n      display: block;\r\n    }\r\n\r\n    .message.is-success {\r\n      border-color: rgba(125, 197, 106, 0.36);\r\n      background: rgba(125, 197, 106, 0.1);\r\n      color: #daf2d3;\r\n    }\r\n\r\n    .message.is-error {\r\n      border-color: rgba(241, 108, 29, 0.32);\r\n      background: rgba(241, 108, 29, 0.1);\r\n      color: #ffd7b5;\r\n    }\r\n\r\n    .message.is-error-final {\r\n      border-color: rgba(241, 108, 29, 0.32);\r\n      background: rgba(241, 108, 29, 0.1);\r\n      color: #ffd7b5;\r\n    }\r\n\r\n    .results-list {\r\n      display: grid;\r\n      gap: 12px;\r\n      margin-top: 18px;\r\n      max-width: none;\r\n      margin-left: auto;\r\n      margin-right: auto;\r\n    }\r\n\r\n    .empty-state {\r\n      padding: 16px;\r\n      border: 1px dashed rgba(255, 255, 255, 0.15);\r\n      border-radius: 12px;\r\n      color: var(--copy-soft);\r\n      font-size: 13px;\r\n      line-height: 1.5;\r\n      text-align: center;\r\n    }\r\n\r\n    .guess-card {\r\n      padding: 18px;\r\n      border: 1px solid var(--line-faint);\r\n      border-radius: 22px;\r\n      background: linear-gradient(180deg, rgba(14, 14, 14, 0.96), rgba(10, 10, 10, 0.96));\r\n      box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.03);\r\n      text-align: left;\r\n    }\r\n\r\n    .guess-card.is-solved {\r\n      border-color: rgba(125, 197, 106, 0.34);\r\n    }\r\n\r\n    .guess-card.is-answer {\r\n      border-color: rgba(125, 197, 106, 0.5);\r\n    }\r\n\r\n    .guess-card.is-hint {\r\n      border-color: rgba(240, 185, 85, 0.28);\r\n    }\r\n\r\n    .guess-top {\r\n      display: flex;\r\n      align-items: center;\r\n      gap: 18px;\r\n      margin-bottom: 18px;\r\n    }\r\n\r\n    .guess-cover {\r\n      position: relative;\r\n      flex: 0 0 96px;\r\n      width: 96px;\r\n      height: 96px;\r\n      border: 1px solid rgba(255, 255, 255, 0.12);\r\n      border-radius: 50%;\r\n      background:\r\n        radial-gradient(circle at 32% 28%, rgba(241, 108, 29, 0.34), transparent 44%),\r\n        linear-gradient(145deg, rgba(241, 108, 29, 0.16), rgba(255, 255, 255, 0.03));\r\n      overflow: hidden;\r\n      box-shadow: 0 18px 34px rgba(0, 0, 0, 0.34);\r\n    }\r\n\r\n    .guess-cover img {\r\n      width: 100%;\r\n      height: 100%;\r\n      object-fit: cover;\r\n      display: block;\r\n    }\r\n\r\n    .guess-cover-fallback {\r\n      width: 100%;\r\n      height: 100%;\r\n      display: flex;\r\n      align-items: center;\r\n      justify-content: center;\r\n      color: var(--white);\r\n      font-family: \"Space Grotesk\", sans-serif;\r\n      font-size: 28px;\r\n      font-weight: 700;\r\n      letter-spacing: -0.04em;\r\n      text-transform: uppercase;\r\n    }\r\n\r\n    .guess-copy {\r\n      min-width: 0;\r\n      display: flex;\r\n      flex-direction: column;\r\n      align-items: flex-start;\r\n      gap: 10px;\r\n    }\r\n\r\n    .guess-badge {\r\n      display: inline-flex;\r\n      align-items: center;\r\n      justify-content: center;\r\n      min-height: 28px;\r\n      padding: 0 12px;\r\n      border: 1px solid var(--line);\r\n      border-radius: 999px;\r\n      color: var(--copy-soft);\r\n      font-size: 11px;\r\n      font-weight: 700;\r\n      letter-spacing: -0.01em;\r\n    }\r\n\r\n    .guess-name {\r\n      margin: 0;\r\n      font-family: \"Space Grotesk\", sans-serif;\r\n      font-size: clamp(28px, 4vw, 34px);\r\n      line-height: 1;\r\n      letter-spacing: -0.04em;\r\n    }\r\n\r\n    .guess-sub {\r\n      margin: -2px 0 0;\r\n      color: var(--copy-soft);\r\n      font-size: 12px;\r\n      line-height: 1.45;\r\n    }\r\n\r\n    .traits {\r\n      display: grid;\r\n      grid-template-columns: repeat(5, minmax(0, 1fr));\r\n      gap: 8px;\r\n    }\r\n\r\n    .trait {\r\n      min-height: 98px;\r\n      padding: 12px 10px;\r\n      border: 1px solid rgba(255, 255, 255, 0.08);\r\n      border-radius: 14px;\r\n      background: rgba(255, 255, 255, 0.04);\r\n      display: flex;\r\n      flex-direction: column;\r\n      justify-content: space-between;\r\n      align-items: center;\r\n      text-align: center;\r\n    }\r\n\r\n    .trait.is-correct {\r\n      border-color: rgba(84, 184, 106, 0.68);\r\n      background: #46b065;\r\n      color: #fff;\r\n    }\r\n\r\n    .trait.is-close {\r\n      border-color: rgba(233, 181, 76, 0.72);\r\n      background: #d2a43a;\r\n      color: #fff;\r\n    }\r\n\r\n    .trait-label {\r\n      display: block;\r\n      margin: 0;\r\n      color: inherit;\r\n      opacity: 0.92;\r\n      font-size: 12px;\r\n      font-weight: 700;\r\n      letter-spacing: -0.02em;\r\n    }\r\n\r\n    .trait-value {\r\n      display: inline-flex;\r\n      flex-wrap: wrap;\r\n      align-items: center;\r\n      justify-content: center;\r\n      gap: 5px;\r\n      font-size: clamp(15px, 1.8vw, 18px);\r\n      line-height: 1.06;\r\n      font-weight: 800;\r\n      letter-spacing: -0.03em;\r\n      word-break: break-word;\r\n    }\r\n\r\n    .trait-value-text {\r\n      display: inline;\r\n    }\r\n\r\n    .trait-arrow {\r\n      display: inline-flex;\r\n      align-items: center;\r\n      justify-content: center;\r\n      font-family: \"Segoe UI Symbol\", \"Noto Sans Symbols 2\", \"Arial Unicode MS\", sans-serif;\r\n      font-size: 0.95em;\r\n      line-height: 1;\r\n      letter-spacing: 0;\r\n      font-weight: 700;\r\n      white-space: nowrap;\r\n    }\r\n\r\n    .trait-suffix {\r\n      display: inline;\r\n      font-size: 0.76em;\r\n      line-height: 1;\r\n      font-weight: 800;\r\n      letter-spacing: 0;\r\n      white-space: nowrap;\r\n    }\r\n\r\n    .guess-spotify {\r\n      margin-top: 12px;\r\n      padding-top: 12px;\r\n      border-top: 1px solid rgba(255, 255, 255, 0.06);\r\n    }\r\n\r\n    .guess-spotify iframe {\r\n      width: 100%;\r\n      min-height: 152px;\r\n      border: 0;\r\n      border-radius: 14px;\r\n      background: #0b0b0b;\r\n      display: block;\r\n    }\r\n\r\n    .guess-tip {\r\n      margin: 12px 0 0;\r\n      padding-top: 12px;\r\n      border-top: 1px solid rgba(255, 255, 255, 0.06);\r\n      color: var(--white);\r\n      font-size: 15px;\r\n      line-height: 1.6;\r\n      font-weight: 500;\r\n    }\r\n\r\n    .hidden {\r\n      display: none !important;\r\n    }\r\n\r\n    @media (max-width: 720px) {\r\n      .demo-app {\r\n        width: 100%;\r\n        max-width: 100%;\r\n        padding: max(6px, env(safe-area-inset-top, 0px)) 4px calc(10px + env(safe-area-inset-bottom, 0px));\r\n      }\r\n\r\n      .app-shell {\r\n        display: flex;\r\n        flex-direction: column;\r\n        padding: 8px 6px 10px;\r\n        border: 0;\r\n        border-radius: 0;\r\n        background: transparent;\r\n        box-shadow: none;\r\n      }\r\n\r\n      .app-shell::after {\r\n        display: none;\r\n      }\r\n\r\n      .controls-shell {\r\n        order: 1;\r\n        position: relative;\r\n        border-top: 0;\r\n        border-bottom: 1px solid var(--line);\r\n        padding-bottom: 20px;\r\n      }\r\n\r\n      .controls-shell::after {\r\n        content: \"Gioca\";\r\n        position: absolute;\r\n        left: 50%;\r\n        bottom: -11px;\r\n        transform: translateX(-50%) translateY(-2px);\r\n        padding: 0 14px;\r\n        background: var(--bg);\r\n        color: #9E9E9E;\r\n        font-size: 15px;\r\n        line-height: 1;\r\n      }\r\n\r\n      .topbar {\r\n        order: 2;\r\n      }\r\n\r\n      .shell {\r\n        order: 3;\r\n        border-top: 0;\r\n      }\r\n\r\n      .top-logo {\r\n        width: min(260px, 66vw);\r\n      }\r\n\r\n      .topbar {\r\n        padding: 12px 4px 4px;\r\n      }\r\n\r\n      .controls-shell,\r\n      .shell {\r\n        padding-top: 10px;\r\n      }\r\n\r\n      .controls-inner .tab,\r\n      .controls-inner .ghost-button {\r\n        min-height: 40px;\r\n        padding: 0 10px;\r\n        font-size: 12px;\r\n      }\r\n\r\n      .tab-ranked-mobile {\r\n        display: inline-flex;\r\n      }\r\n\r\n      .controls-inner .tab-ranked-mobile {\r\n        display: inline-flex !important;\r\n        width: 100%;\r\n      }\r\n\r\n      .help-panel-mobile-slot {\r\n        display: block;\r\n      }\r\n\r\n      .controls-shell .help-panel.is-open {\r\n        margin: 10px 0 0;\r\n        padding-bottom: 0;\r\n        border-bottom-color: transparent;\r\n      }\r\n\r\n      .input-grid {\r\n        grid-template-columns: repeat(2, minmax(0, 1fr));\r\n        gap: 8px;\r\n        width: 100%;\r\n      }\r\n\r\n      .attempts-card {\r\n        order: 1;\r\n        min-width: 0;\r\n        min-height: 48px;\r\n        height: 48px;\r\n        padding: 0 10px;\r\n        font-size: 13px;\r\n      }\r\n\r\n      .action-slot {\r\n        order: 2;\r\n        width: auto;\r\n        min-width: 0;\r\n      }\r\n\r\n      .input-shell {\r\n        order: 3;\r\n        grid-column: 1 \/ -1;\r\n        min-width: 0;\r\n        padding: 0;\r\n        border: 0;\r\n        border-radius: 0;\r\n        background: #0b0b0b;\r\n      }\r\n\r\n      .input-grid > .button {\r\n        order: 4;\r\n        grid-column: 1 \/ -1;\r\n      }\r\n\r\n      .input-grid > .attempts-card,\r\n      .input-grid > .button,\r\n      .action-slot > .secondary-button,\r\n      .action-slot > .streak-card,\r\n      .input-grid > .action-slot {\r\n        width: 100%;\r\n        min-width: 0;\r\n        min-height: 48px;\r\n        height: 48px;\r\n      }\r\n\r\n      .button,\r\n      .secondary-button,\r\n      .streak-card,\r\n      .attempts-card,\r\n      .action-slot {\r\n        min-width: 0;\r\n      }\r\n\r\n      .search-field {\r\n        min-height: 48px;\r\n        padding: 0 14px;\r\n        border: 1px solid rgba(255, 255, 255, 0.14);\r\n        border-radius: 12px;\r\n        background: #0b0b0b;\r\n        font-size: 16px;\r\n      }\r\n\r\n      .suggestion {\r\n        min-height: 48px;\r\n        padding: 13px 12px;\r\n      }\r\n\r\n      .help-grid {\r\n        grid-template-columns: 1fr;\r\n      }\r\n\r\n      .help-card span {\r\n        font-size: 13px;\r\n        line-height: 1.5;\r\n      }\r\n\r\n      .ranked-meta-grid {\r\n        gap: 8px;\r\n      }\r\n\r\n      .ranked-meta-card {\r\n        min-height: 62px;\r\n        padding: 10px 11px;\r\n      }\r\n\r\n      .ranked-meta-value {\r\n        font-size: clamp(18px, 5vw, 24px);\r\n      }\r\n\r\n      .traits {\r\n        grid-template-columns: repeat(2, minmax(0, 1fr));\r\n        gap: 6px;\r\n      }\r\n\r\n      .top-actions,\r\n      .guess-top {\r\n        flex-direction: column;\r\n        align-items: center;\r\n        justify-content: center;\r\n      }\r\n\r\n      .guess-copy {\r\n        align-items: center;\r\n        text-align: center;\r\n      }\r\n\r\n      .guess-card {\r\n        padding: 12px;\r\n        border-radius: 16px;\r\n      }\r\n\r\n      .guess-top {\r\n        gap: 10px;\r\n        margin-bottom: 10px;\r\n      }\r\n\r\n      .guess-cover {\r\n        flex-basis: 72px;\r\n        width: 72px;\r\n        height: 72px;\r\n      }\r\n\r\n      .guess-name {\r\n        font-size: clamp(20px, 7vw, 26px);\r\n      }\r\n\r\n      .trait {\r\n        min-height: 74px;\r\n        padding: 8px 7px;\r\n      }\r\n\r\n      .trait:nth-child(5) {\r\n        grid-column: 1 \/ -1;\r\n      }\r\n\r\n      .trait-label {\r\n        font-size: 10px;\r\n      }\r\n\r\n      .trait-value {\r\n        font-size: clamp(12px, 3.9vw, 15px);\r\n      }\r\n\r\n      .message {\r\n        margin-top: 10px;\r\n        padding: 9px 11px;\r\n        font-size: 13px;\r\n      }\r\n\r\n      .controls-inner {\r\n        grid-template-columns: repeat(2, minmax(0, 1fr));\r\n      }\r\n    }\r\n\r\n    @media (max-width: 520px) {\r\n      .demo-app {\r\n        padding-inline: 3px;\r\n      }\r\n\r\n      .top-logo {\r\n        width: min(232px, 64vw);\r\n      }\r\n\r\n      .controls-shell,\r\n      .shell {\r\n        padding-top: 8px;\r\n      }\r\n\r\n      .guess-card {\r\n        padding: 11px;\r\n      }\r\n\r\n      .trait {\r\n        min-height: 70px;\r\n      }\r\n\r\n      .guess-badge {\r\n        min-height: 24px;\r\n        padding: 0 10px;\r\n        font-size: 10px;\r\n      }\r\n\r\n      .guess-sub {\r\n        font-size: 11px;\r\n      }\r\n\r\n      .guess-spotify {\r\n        margin-top: 10px;\r\n        padding-top: 10px;\r\n      }\r\n\r\n      .guess-spotify iframe {\r\n        min-height: 152px;\r\n      }\r\n\r\n      .guess-tip {\r\n        margin-top: 10px;\r\n        padding-top: 10px;\r\n        font-size: 13px;\r\n      }\r\n\r\n      .controls-inner {\r\n        grid-template-columns: 1fr;\r\n      }\r\n\r\n      .controls-inner .tab-ranked-mobile {\r\n        display: inline-flex !important;\r\n        width: 100%;\r\n      }\r\n\r\n      .ranked-meta-grid {\r\n        grid-template-columns: repeat(2, minmax(0, 1fr));\r\n      }\r\n    }\r\n\r\n    @media (max-width: 400px) {\r\n      .demo-app {\r\n        padding-inline: 2px;\r\n      }\r\n\r\n      .top-logo {\r\n        width: min(214px, 62vw);\r\n      }\r\n\r\n      .attempts-card,\r\n      .button,\r\n      .secondary-button,\r\n      .streak-main {\r\n        font-size: 12px;\r\n      }\r\n\r\n      .streak-sub {\r\n        font-size: 8px;\r\n      }\r\n\r\n      .trait {\r\n        min-height: 66px;\r\n        padding: 8px 6px;\r\n      }\r\n\r\n      .trait-value {\r\n        font-size: 12px;\r\n      }\r\n    }\r\n\r\n    @media (hover: none), (pointer: coarse) {\r\n      .tab:hover,\r\n      .ghost-button:hover,\r\n      .button:hover,\r\n      .secondary-button:hover,\r\n      .streak-card.is-guest:hover,\r\n      .suggestion:hover {\r\n        transform: none;\r\n      }\r\n\r\n      .button:hover,\r\n      .secondary-button:hover {\r\n        background: var(--accent);\r\n        border-color: var(--accent);\r\n        color: #111;\r\n      }\r\n\r\n      .demo-app.is-ranked-mode #mobileRankedGuessForm .button:hover,\r\n      .demo-app.is-ranked-mode #mobileRankedGuessForm .secondary-button:hover {\r\n        background: var(--ranked-accent);\r\n        border-color: var(--ranked-accent);\r\n        color: #111;\r\n      }\r\n\r\n      .streak-card.is-guest:hover {\r\n        background: var(--accent);\r\n        border-color: var(--accent);\r\n        color: #111;\r\n      }\r\n\r\n      .streak-card.is-guest:hover .streak-sub {\r\n        color: rgba(17, 17, 17, 0.74);\r\n      }\r\n\r\n      .suggestion:hover {\r\n        background: transparent;\r\n      }\r\n\r\n      .button:active,\r\n      .secondary-button:active,\r\n      .streak-card.is-guest:active,\r\n      .tab:active,\r\n      .ghost-button:active,\r\n      .suggestion:active {\r\n        transform: scale(0.99);\r\n      }\r\n    }\r\n\r\n    .demo-app button,\r\n    .demo-app button *,\r\n    .demo-app .attempts-card,\r\n    .demo-app .attempts-card *,\r\n    .demo-app .classic-attempts-badge,\r\n    .demo-app .classic-attempts-badge *,\r\n    .demo-app .classic-streak-badge,\r\n    .demo-app .classic-streak-badge *,\r\n    .demo-app .streak-card,\r\n    .demo-app .streak-card *,\r\n    .demo-app .guess-name,\r\n    .demo-app .guess-name *,\r\n    .demo-app .artist-name,\r\n    .demo-app .artist-name *,\r\n    .demo-app .result-name,\r\n    .demo-app .result-name *,\r\n    .demo-app .board-row .name,\r\n    .demo-app .board-row .name * {\r\n      font-family: Verdana, Geneva, sans-serif !important;\r\n      font-weight: 900 !important;\r\n      -webkit-text-stroke: 0.18px currentColor;\r\n      text-shadow: 0.18px 0 currentColor;\r\n    }\r\n\r\n    .demo-app .controls-inner .tab,\r\n    .demo-app .controls-inner .ghost-button {\r\n      min-height: 56px !important;\r\n      height: 56px !important;\r\n      padding: 0 22px !important;\r\n      border-radius: 12px !important;\r\n      font-size: 15px !important;\r\n      line-height: 1.1 !important;\r\n      text-transform: uppercase !important;\r\n    }\r\n\r\n    @media (max-width: 720px) {\r\n      .demo-app .top-logo {\r\n        margin-top: 14px !important;\r\n      }\r\n\r\n      .demo-app .controls-inner {\r\n        margin-bottom: 18px !important;\r\n      }\r\n    }\r\n\r\n  <\/style>\r\n<\/head>\r\n<body>\r\n  <div class=\"demo-app\">\r\n    <div class=\"app-shell\">\r\n      <header class=\"topbar\">\r\n        <img decoding=\"async\" class=\"top-logo\" src=\"https:\/\/bulldogmusik.it\/wp-content\/uploads\/2026\/05\/Bulldogle-Classico-New.png\" alt=\"Bulldogle Classico\">\r\n      <\/header>\r\n\r\n      <section class=\"controls-shell\" aria-label=\"Controlli Bulldogle\">\r\n        <div class=\"controls-inner\">\r\n          <button class=\"tab is-active\" data-mode=\"classic\" type=\"button\">DAILY<\/button>\r\n          <button class=\"tab\" data-mode=\"practice\" type=\"button\">ALLENAMENTO<\/button>\r\n          <button id=\"rankedModeButton\" class=\"tab tab-ranked-mobile\" type=\"button\">CLASSIFICATA<\/button>\r\n          <button id=\"helpToggle\" class=\"ghost-button\" type=\"button\">COME SI GIOCA<\/button>\r\n        <\/div>\r\n        <div id=\"helpPanelMobileSlot\" class=\"help-panel-mobile-slot\"><\/div>\r\n      <\/section>\r\n\r\n       <main class=\"shell\">\r\n        <section class=\"game-shell\">\r\n          <section id=\"helpPanel\" class=\"help-panel\" aria-hidden=\"true\">\r\n            <div class=\"help-grid\">\r\n                <div class=\"help-card\">\r\n                  <strong>Colori<\/strong>\r\n                  <span>\ud83d\udfe2 = corretto. <br>\r\n \ud83d\udfe1 = vicino.<br>\r\n \u26aa = errato.<\/span>\r\n                <\/div>\r\n                <div class=\"help-card\">\r\n                  <strong>Citta<\/strong>\r\n                  <span>\ud83d\udfe1 se sei nella stessa regione. <br>\r\nSe sbagli, la freccia ti dice dove cercare.<\/span>\r\n                <\/div>\r\n                <div class=\"help-card is-legacy-hidden\">\r\n                  <strong>Estero<\/strong>\r\n                  <span>\ud83c\udf0d significa che l'artista corretto \u00e8 nato fuori dall'Italia.<br>\r\n \ud83c\uddee\ud83c\uddf9 significa che hai provato un artista estero ma quello corretto \u00e8 italiano.<\/span>\r\n                <\/div>\r\n                <div class=\"help-card\">\r\n                  <strong>Popolarita<\/strong>\r\n                  <span>Scala: underground, emergente, riconosciuto, mainstream, icona. <br>\r\n\ud83d\udfe1 = un solo livello di distanza.<\/span>\r\n                <\/div>\r\n                <div class=\"help-card is-legacy-hidden\">\r\n                  <strong>Frecce<\/strong>\r\n                  <span>\u2191 indica che l'artista corretto \u00e8 piu in alto nella scala o piu avanti nel debutto. <br>\r\n \u2193 indica che \u00e8 piu in basso.<\/span>\r\n                <\/div>\r\n                <div class=\"help-card\">\r\n                  <strong>Debutto<\/strong>\r\n                  <span>\ud83d\udfe1 se la differenza \u00e8 sotto i 5 anni.<\/span>\r\n                <\/div>\r\n                <div class=\"help-card\">\r\n                  <strong>Estero<\/strong>\r\n                  <span>&rarr; \ud83c\uddee\ud83c\uddf9: hai provato un artista estero ma il target \u00e8 italiano. <br>\r\n &rarr;\ud83c\udf0d: il target \u00e8 nato fuori dall'Italia. <br><\/span>\r\n                <\/div>\r\n                <div class=\"help-card\">\r\n                  <strong>Frecce<\/strong>\r\n                  <span>&uarr; vuol dire piu in alto o piu avanti. <br>\r\n &darr; vuol dire piu in basso o piu indietro.<\/span>\r\n                <\/div>\r\n            <\/div>\r\n          <\/section>\r\n\r\n          <section id=\"standardGamePanel\" class=\"game-panel\">\r\n            <form id=\"guessForm\" class=\"input-grid\" autocomplete=\"off\">\r\n              <div id=\"attemptsCard\" class=\"attempts-card\" aria-live=\"polite\">10 TENTATIVI<\/div>\r\n\r\n              <div class=\"input-shell\">\r\n                <label id=\"inputLabel\" class=\"input-label\" for=\"artistInput\">inserisci un artista<\/label>\r\n                <input id=\"artistInput\" class=\"search-field\" type=\"text\" placeholder=\"inserisci un artista\" aria-describedby=\"gameMsg\">\r\n                <div id=\"suggestions\" class=\"suggestions\" role=\"listbox\" aria-label=\"Suggerimenti artisti\"><\/div>\r\n              <\/div>\r\n\r\n              <button id=\"submitButton\" class=\"button\" type=\"submit\">PROVA<\/button>\r\n              <div class=\"action-slot\">\r\n                <button id=\"modeActionButton\" class=\"secondary-button hidden\" type=\"button\">NUOVO<\/button>\r\n                <a id=\"dailyStreakCard\" class=\"streak-card hidden is-guest\" href=\"https:\/\/bulldogmusik.it\/account-login\/\" aria-label=\"Accedi per salvare la streak\">\r\n                  <span id=\"dailyStreakMain\" class=\"streak-main\">STREAK<\/span>\r\n                  <span id=\"dailyStreakSub\" class=\"streak-sub\">Accedi per salvarla<\/span>\r\n                <\/a>\r\n              <\/div>\r\n            <\/form>\r\n\r\n            <div id=\"gameMsg\" class=\"message\" aria-live=\"polite\"><\/div>\r\n\r\n            <div id=\"resultsList\" class=\"results-list\">\r\n              <div class=\"empty-state\">Nessun tentativo ancora.<\/div>\r\n            <\/div>\r\n          <\/section>\r\n\r\n          <section id=\"mobileRankedGamePanel\" class=\"ranked-mode-panel hidden\">\r\n            <section id=\"mobileRankedHelpPanel\" class=\"help-panel\" aria-hidden=\"true\">\r\n              <div class=\"help-grid\">\r\n                <div class=\"help-card\">\r\n                  <strong>Timer<\/strong>\r\n                  <span>Hai 3 minuti per fare il punteggio piu alto possibile.<\/span>\r\n                <\/div>\r\n                <div class=\"help-card\">\r\n                  <strong>Punti<\/strong>\r\n                  <span>Ogni artista indovinato vale 1 punto e aggiunge 15 secondi.<\/span>\r\n                <\/div>\r\n                <div class=\"help-card\">\r\n                  <strong>Skip<\/strong>\r\n                  <span>Puoi skippare l'artista corrente, ma perdi 15 secondi.<\/span>\r\n                <\/div>\r\n                <div class=\"help-card\">\r\n                  <strong>Tentativi<\/strong>\r\n                  <span>Hai 10 tentativi per artista. Se li finisci, passi al successivo.<\/span>\r\n                <\/div>\r\n                <div class=\"help-card\">\r\n                  <strong>Indizi<\/strong>\r\n                  <span>Verde = corretto. Giallo = vicino. Le frecce indicano la direzione giusta.<\/span>\r\n                <\/div>\r\n                <div class=\"help-card\">\r\n                  <strong>Classificata<\/strong>\r\n                  <span>Il tuo miglior punteggio viene salvato nella classifica mensile della ranked.<\/span>\r\n                <\/div>\r\n              <\/div>\r\n            <\/section>\r\n\r\n            <section class=\"ranked-meta-grid\" aria-label=\"Statistiche Ranked\">\r\n              <article class=\"ranked-meta-card is-accent\">\r\n                <span class=\"ranked-meta-label\">Tempo<\/span>\r\n                <strong id=\"mobileRankedTimerValue\" class=\"ranked-meta-value\">3:00<\/strong>\r\n              <\/article>\r\n              <article class=\"ranked-meta-card\">\r\n                <span class=\"ranked-meta-label\">Punti<\/span>\r\n                <strong id=\"mobileRankedScoreValue\" class=\"ranked-meta-value\">0<\/strong>\r\n              <\/article>\r\n            <\/section>\r\n\r\n            <form id=\"mobileRankedGuessForm\" class=\"input-grid\" autocomplete=\"off\">\r\n              <div id=\"mobileRankedAttemptsCard\" class=\"attempts-card\" aria-live=\"polite\">10 TENTATIVI<\/div>\r\n\r\n              <div class=\"input-shell\">\r\n                <input id=\"mobileRankedArtistInput\" class=\"search-field\" type=\"text\" placeholder=\"inserisci un artista\" aria-describedby=\"mobileRankedGameMsg\">\r\n                <div id=\"mobileRankedSuggestions\" class=\"suggestions\" role=\"listbox\" aria-label=\"Suggerimenti artisti ranked\"><\/div>\r\n              <\/div>\r\n\r\n              <button id=\"mobileRankedSubmitButton\" class=\"button\" type=\"submit\">PROVA<\/button>\r\n\r\n              <div class=\"action-slot\">\r\n                <button id=\"mobileRankedSideActionButton\" class=\"secondary-button\" type=\"button\">INIZIA<\/button>\r\n              <\/div>\r\n            <\/form>\r\n\r\n            <section id=\"mobileRankedSummaryPanel\" class=\"ranked-summary-panel hidden\" aria-live=\"polite\">\r\n              <h3 id=\"mobileRankedSummaryTitle\" class=\"ranked-summary-title\">Partita conclusa<\/h3>\r\n              <div id=\"mobileRankedSummaryLines\" class=\"ranked-summary-lines\"><\/div>\r\n            <\/section>\r\n\r\n            <div id=\"mobileRankedGameMsg\" class=\"message\" aria-live=\"polite\"><\/div>\r\n\r\n            <div id=\"mobileRankedResultsList\" class=\"results-list\">\r\n              <div class=\"empty-state\">ACCEDI per giocare.<\/div>\r\n            <\/div>\r\n          <\/section>\r\n        <\/section>\r\n      <\/main>\r\n    <\/div>\r\n  <\/div>\r\n\r\n  <script>\r\n    (async function () {\r\n      const bootstrapScript = document.currentScript;\r\n\r\n      async function loadScriptSource(src) {\r\n        return new Promise((resolve) => {\r\n          const existing = Array.from(document.querySelectorAll(\"script[src]\")).find((node) => node.src === src);\r\n          if (existing) {\r\n            if (Array.isArray(window.bulldogleArtists) && window.bulldogleArtists.length) {\r\n              resolve(true);\r\n              return;\r\n            }\r\n          }\r\n\r\n          const script = document.createElement(\"script\");\r\n          script.src = src;\r\n          script.async = false;\r\n          script.onload = () => resolve(true);\r\n          script.onerror = () => resolve(false);\r\n          document.head.appendChild(script);\r\n        });\r\n      }\r\n\r\n      async function ensureArtistsLoaded() {\r\n        if (Array.isArray(window.bulldogleArtists) && window.bulldogleArtists.length) {\r\n          return window.bulldogleArtists;\r\n        }\r\n\r\n        const sources = [\r\n          \".\/artists.js\",\r\n          \"artists.js\",\r\n          \"\/bulldogle\/artists.js?v=61\"\r\n        ];\r\n\r\n        if (window.location && \/^https?:\/i.test(window.location.protocol) && window.location.origin) {\r\n          sources.push(window.location.origin + \"\/bulldogle\/artists.js?v=61\");\r\n        }\r\n\r\n        sources.push(\"https:\/\/bulldogmusik.it\/bulldogle\/artists.js?v=61\");\r\n\r\n        for (const source of sources) {\r\n          const loaded = await loadScriptSource(source);\r\n          if (loaded && Array.isArray(window.bulldogleArtists) && window.bulldogleArtists.length) {\r\n            return window.bulldogleArtists;\r\n          }\r\n        }\r\n\r\n        return [];\r\n      }\r\n\r\n      const artistsSource = await ensureArtistsLoaded();\r\n      const ARROWS = {\r\n        up: String.fromCharCode(8593),\r\n        down: String.fromCharCode(8595),\r\n        left: String.fromCharCode(8592),\r\n        right: String.fromCharCode(8594)\r\n      };\r\n\r\n      const regionCoords = {\r\n        \"Abruzzo\": { lat: 42.3, lon: 13.9 },\r\n        \"Basilicata\": { lat: 40.6, lon: 15.8 },\r\n        \"Calabria\": { lat: 38.9, lon: 16.6 },\r\n        \"Campania\": { lat: 40.8, lon: 14.3 },\r\n        \"Emilia-Romagna\": { lat: 44.5, lon: 11.3 },\r\n        \"Friuli-Venezia Giulia\": { lat: 46.1, lon: 13.1 },\r\n        \"Lazio\": { lat: 41.9, lon: 12.5 },\r\n        \"Liguria\": { lat: 44.4, lon: 8.9 },\r\n        \"Lombardia\": { lat: 45.5, lon: 9.2 },\r\n        \"Marche\": { lat: 43.6, lon: 13.5 },\r\n        \"Molise\": { lat: 41.6, lon: 14.6 },\r\n        \"Piemonte\": { lat: 45.1, lon: 7.7 },\r\n        \"Puglia\": { lat: 41.1, lon: 16.9 },\r\n        \"Sardegna\": { lat: 40.1, lon: 9.0 },\r\n        \"Sicilia\": { lat: 37.6, lon: 14.0 },\r\n        \"Toscana\": { lat: 43.8, lon: 11.2 },\r\n        \"Trentino-Alto Adige\": { lat: 46.5, lon: 11.3 },\r\n        \"Umbria\": { lat: 43.1, lon: 12.4 },\r\n        \"Valle d'Aosta\": { lat: 45.7, lon: 7.3 },\r\n        \"Veneto\": { lat: 45.4, lon: 12.3 },\r\n        \"Estero\": null\r\n      };\r\n\r\n      const classicConfig = window.bulldogleClassicConfig || {};\r\n      const rankedConfig = window.bulldogleRankedConfig || {};\r\n      const guestStreakLoginUrl = \"https:\/\/bulldogmusik.it\/account-login\/\";\r\n      const popularityLevels = [\"underground\", \"emergente\", \"riconosciuto\", \"mainstream\", \"icona\"];\r\n      const monthlyListenerBuckets = [\r\n        { level: \"underground\", min: 0 },\r\n        { level: \"emergente\", min: 250000 },\r\n        { level: \"riconosciuto\", min: 750000 },\r\n        { level: \"mainstream\", min: 1500000 },\r\n        { level: \"icona\", min: 3000000 }\r\n      ];\r\n      let classicStreakLoading = false;\r\n      let classicStreakLoaded = false;\r\n      let rankedMessageTimeoutId = 0;\r\n      const CLASSIC_LOGO_URL = \"https:\/\/bulldogmusik.it\/wp-content\/uploads\/2026\/05\/Bulldogle-Classico-New.png\";\r\n      const RANKED_LOGO_URL = \"https:\/\/bulldogmusik.it\/wp-content\/uploads\/2026\/05\/Bulldogle-Ranked-New-1.png\";\r\n      const RANKED_INITIAL_TIME = 180;\r\n      const RANKED_ATTEMPTS = 10;\r\n      const RANKED_CORRECT_BONUS = 15;\r\n      const RANKED_SKIP_PENALTY = 15;\r\n      const RANKED_ROUND_TRANSITION_MS = 1000;\r\n      const hasRankedBackend = Boolean(rankedConfig && rankedConfig.ajaxUrl && rankedConfig.nonce);\r\n\r\n      const modeConfig = {\r\n        classic: { submitLabel: \"PROVA\", actionLabel: \"\", inputPlaceholder: \"inserisci un artista\" },\r\n        practice: { submitLabel: \"PROVA\", actionLabel: \"NUOVO\", inputPlaceholder: \"inserisci un artista\" }\r\n      };\r\n\r\n      function parseMonthlyListenersValue(value) {\r\n        if (typeof value === \"number\") {\r\n          return Number.isFinite(value) && value > 0 ? Math.round(value) : 0;\r\n        }\r\n\r\n        const raw = String(value || \"\").trim();\r\n        if (!raw) return 0;\r\n\r\n        const compact = raw.replace(\/\\s+\/g, \"\");\r\n        const suffixMatch = compact.match(\/^([0-9]+(?:[.,][0-9]+)?)\\s*([kmb])$\/i);\r\n        if (suffixMatch) {\r\n          const amount = Number(suffixMatch[1].replace(\",\", \".\"));\r\n          if (!Number.isFinite(amount) || amount <= 0) return 0;\r\n          const unit = suffixMatch[2].toLowerCase();\r\n          if (unit === \"b\") return Math.round(amount * 1e9);\r\n          if (unit === \"m\") return Math.round(amount * 1e6);\r\n          return Math.round(amount * 1e3);\r\n        }\r\n\r\n        if (\/^\\d{1,3}([.,]\\d{3})+$\/.test(compact)) {\r\n          return Math.round(Number(compact.replace(\/[.,]\/g, \"\")) || 0);\r\n        }\r\n\r\n        const parsed = Number(compact.replace(\",\", \".\"));\r\n        return Number.isFinite(parsed) && parsed > 0 ? Math.round(parsed) : 0;\r\n      }\r\n\r\n      function getManualMonthlyListeners(artist) {\r\n        const manualKeys = [\r\n          \"listenersManual\",\r\n          \"monthlyListenersManual\",\r\n          \"manualMonthlyListeners\",\r\n          \"manualListeners\",\r\n          \"listeners_manual\",\r\n          \"monthly_listeners_manual\",\r\n          \"listeners-manual\",\r\n          \"monthly-listeners-manual\"\r\n        ];\r\n\r\n        for (const key of manualKeys) {\r\n          const value = parseMonthlyListenersValue(artist && artist[key]);\r\n          if (value > 0) return value;\r\n        }\r\n\r\n        return 0;\r\n      }\r\n\r\n      const artists = artistsSource.map((artist) => ({\r\n        id: Number(artist.id),\r\n        name: String(artist.name || \"\").trim(),\r\n        city: String(artist.city || \"\").trim(),\r\n        region: String(artist.region || \"\").trim(),\r\n        debutYear: Number(artist.debutYear || 0),\r\n        members: String(artist.members || \"N\/D\").trim(),\r\n        gender: String(artist.gender || \"\").trim(),\r\n        popularity: String(artist.popularity || \"\").trim().toLowerCase(),\r\n        monthlyListeners: Number(artist.monthlyListeners || 0),\r\n        listenersManual: getManualMonthlyListeners(artist),\r\n        spotifyId: String(artist.spotifyId || \"\").trim(),\r\n        tip: String(artist.tip || \"\").trim()\r\n      })).filter((artist) => artist.id && artist.name);\r\n\r\n      const spotifyThumbStorageKey = \"bulldogle-spotify-thumbs-v1\";\r\n      const spotifyThumbCache = new Map();\r\n      const spotifyThumbRequests = new Map();\r\n      let messageTimeoutId = 0;\r\n\r\n      try {\r\n        const storedThumbs = JSON.parse(window.localStorage.getItem(spotifyThumbStorageKey) || \"{}\");\r\n        Object.keys(storedThumbs).forEach((spotifyId) => {\r\n          if (storedThumbs[spotifyId]) {\r\n            spotifyThumbCache.set(spotifyId, String(storedThumbs[spotifyId]));\r\n          }\r\n        });\r\n      } catch (_) {}\r\n\r\n      const demoRoots = Array.from(document.querySelectorAll(\".demo-app\"));\r\n      const appRoot = bootstrapScript &&\r\n        bootstrapScript.previousElementSibling &&\r\n        bootstrapScript.previousElementSibling.classList &&\r\n        bootstrapScript.previousElementSibling.classList.contains(\"demo-app\")\r\n          ? bootstrapScript.previousElementSibling\r\n          : demoRoots[demoRoots.length - 1];\r\n\r\n      if (!appRoot) {\r\n        return;\r\n      }\r\n\r\n      const elements = {\r\n        topLogo: appRoot.querySelector(\".top-logo\"),\r\n        tabs: Array.from(appRoot.querySelectorAll(\".tab[data-mode]\")),\r\n        rankedModeButton: appRoot.querySelector(\"#rankedModeButton\"),\r\n        helpToggle: appRoot.querySelector(\"#helpToggle\"),\r\n        helpPanel: appRoot.querySelector(\"#helpPanel\"),\r\n        helpPanelMobileSlot: appRoot.querySelector(\"#helpPanelMobileSlot\"),\r\n        standardGamePanel: appRoot.querySelector(\"#standardGamePanel\"),\r\n        attemptsCard: appRoot.querySelector(\"#attemptsCard\"),\r\n        guessForm: appRoot.querySelector(\"#guessForm\"),\r\n        inputLabel: appRoot.querySelector(\"#inputLabel\"),\r\n        input: appRoot.querySelector(\"#artistInput\"),\r\n        suggestions: appRoot.querySelector(\"#suggestions\"),\r\n        submitButton: appRoot.querySelector(\"#submitButton\"),\r\n        modeActionButton: appRoot.querySelector(\"#modeActionButton\"),\r\n        dailyStreakCard: appRoot.querySelector(\"#dailyStreakCard\"),\r\n        dailyStreakMain: appRoot.querySelector(\"#dailyStreakMain\"),\r\n        dailyStreakSub: appRoot.querySelector(\"#dailyStreakSub\"),\r\n        message: appRoot.querySelector(\"#gameMsg\"),\r\n        resultsList: appRoot.querySelector(\"#resultsList\"),\r\n        mobileRankedGamePanel: appRoot.querySelector(\"#mobileRankedGamePanel\"),\r\n        mobileRankedHelpPanel: appRoot.querySelector(\"#mobileRankedHelpPanel\"),\r\n        mobileRankedTimerValue: appRoot.querySelector(\"#mobileRankedTimerValue\"),\r\n        mobileRankedScoreValue: appRoot.querySelector(\"#mobileRankedScoreValue\"),\r\n        mobileRankedRoundValue: appRoot.querySelector(\"#mobileRankedRoundValue\"),\r\n        mobileRankedAttemptsCard: appRoot.querySelector(\"#mobileRankedAttemptsCard\"),\r\n        mobileRankedGuessForm: appRoot.querySelector(\"#mobileRankedGuessForm\"),\r\n        mobileRankedInput: appRoot.querySelector(\"#mobileRankedArtistInput\"),\r\n        mobileRankedSuggestions: appRoot.querySelector(\"#mobileRankedSuggestions\"),\r\n        mobileRankedSubmitButton: appRoot.querySelector(\"#mobileRankedSubmitButton\"),\r\n        mobileRankedSideActionButton: appRoot.querySelector(\"#mobileRankedSideActionButton\"),\r\n        mobileRankedSummaryPanel: appRoot.querySelector(\"#mobileRankedSummaryPanel\"),\r\n        mobileRankedSummaryTitle: appRoot.querySelector(\"#mobileRankedSummaryTitle\"),\r\n        mobileRankedSummaryLines: appRoot.querySelector(\"#mobileRankedSummaryLines\"),\r\n        mobileRankedMessage: appRoot.querySelector(\"#mobileRankedGameMsg\"),\r\n        mobileRankedResultsList: appRoot.querySelector(\"#mobileRankedResultsList\")\r\n      };\r\n\r\n      if (!elements.guessForm || !elements.input || !elements.submitButton || !elements.suggestions) {\r\n        return;\r\n      }\r\n\r\n      const desktopHelpPanelParent = elements.helpPanel ? elements.helpPanel.parentElement : null;\r\n      const desktopHelpPanelNextSibling = elements.helpPanel ? elements.helpPanel.nextElementSibling : null;\r\n      const desktopRankedHelpPanelParent = elements.mobileRankedHelpPanel ? elements.mobileRankedHelpPanel.parentElement : null;\r\n      const desktopRankedHelpPanelNextSibling = elements.mobileRankedHelpPanel ? elements.mobileRankedHelpPanel.nextElementSibling : null;\r\n\r\n      if (elements.suggestions.parentElement !== document.body) {\r\n        document.body.appendChild(elements.suggestions);\r\n      }\r\n\r\n      if (elements.mobileRankedSuggestions && elements.mobileRankedSuggestions.parentElement !== document.body) {\r\n        document.body.appendChild(elements.mobileRankedSuggestions);\r\n      }\r\n\r\n      const italyDateInfo = getItalyDateInfo();\r\n      const classicStorageKey = \"bulldogle_classic_\" + italyDateInfo.dayKey;\r\n\r\n      const app = {\r\n        mode: \"classic\",\r\n        lastStandardMode: \"classic\",\r\n        modes: {\r\n          classic: createClassicState(),\r\n          practice: createPracticeState()\r\n        },\r\n        ranked: createRankedState()\r\n      };\r\n\r\n      if (!artists.length) {\r\n        elements.message.textContent = \"artists.js non e stato caricato correttamente.\";\r\n        elements.message.classList.add(\"is-visible\", \"is-error\");\r\n        disableGameInput(true);\r\n        return;\r\n      }\r\n\r\n      function createClassicState() {\r\n        return {\r\n          maxAttempts: 10,\r\n          attempts: 0,\r\n          guessedIds: new Set(),\r\n          results: [],\r\n          complete: false,\r\n          target: getDailyTarget()\r\n        };\r\n      }\r\n\r\n      function createPracticeState() {\r\n        return {\r\n          maxAttempts: 10,\r\n          attempts: 0,\r\n          round: 1,\r\n          guessedIds: new Set(),\r\n          results: [],\r\n          complete: false,\r\n          target: pickRandomArtist()\r\n        };\r\n      }\r\n\r\n      function createRankedState() {\r\n        return {\r\n          active: false,\r\n          preparing: false,\r\n          submitting: false,\r\n          complete: false,\r\n          betweenRounds: false,\r\n          sessionToken: \"\",\r\n          currentArtist: null,\r\n          score: 0,\r\n          timeLeft: RANKED_INITIAL_TIME,\r\n          roundAttempts: 0,\r\n          roundGuessedIds: new Set(),\r\n          usedTargetIds: new Set(),\r\n          freeHintArtist: null,\r\n          results: [],\r\n          timerId: 0,\r\n          roundTransitionId: 0,\r\n          summaryTitle: \"Partita conclusa\",\r\n          summaryLines: [],\r\n          isRecord: false\r\n        };\r\n      }\r\n\r\n      function getClassicSaveStatus() {\r\n        const state = app.modes.classic;\r\n        if (!state.complete) return \"playing\";\r\n        return state.results.some((result) => result.kind === \"guess\" && result.solved) ? \"won\" : \"lost\";\r\n      }\r\n\r\n      function saveClassicState(status) {\r\n        const state = app.modes.classic;\r\n        const guessedArtistIds = state.results\r\n          .filter((result) => result.kind === \"guess\" && result.guessArtist && result.guessArtist.id)\r\n          .map((result) => result.guessArtist.id);\r\n\r\n        const payload = {\r\n          attempts: state.attempts,\r\n          guessedIds: Array.from(state.guessedIds),\r\n          guessedArtistIds: guessedArtistIds,\r\n          status: status || getClassicSaveStatus(),\r\n          targetId: state.target && state.target.id ? Number(state.target.id) : 0\r\n        };\r\n\r\n        try {\r\n          window.localStorage.setItem(classicStorageKey, JSON.stringify(payload));\r\n        } catch (_) {}\r\n      }\r\n\r\n      function loadClassicState() {\r\n        let rawState = \"\";\r\n\r\n        try {\r\n          rawState = window.localStorage.getItem(classicStorageKey) || \"\";\r\n        } catch (_) {\r\n          return;\r\n        }\r\n\r\n        if (!rawState) return;\r\n\r\n        try {\r\n          const savedState = JSON.parse(rawState);\r\n          const state = app.modes.classic;\r\n          const savedTargetId = Number(savedState.targetId || 0);\r\n\r\n          if (!savedTargetId || savedTargetId !== Number(state.target.id)) {\r\n            try {\r\n              window.localStorage.removeItem(classicStorageKey);\r\n            } catch (_) {}\r\n            return;\r\n          }\r\n\r\n          const savedArtistIds = Array.isArray(savedState.guessedArtistIds)\r\n            ? savedState.guessedArtistIds.map((id) => Number(id)).filter((id) => Number.isFinite(id) && id > 0)\r\n            : [];\r\n          const chronologicalIds = savedArtistIds.slice().reverse();\r\n          const restoredGuessedIds = new Set(\r\n            Array.isArray(savedState.guessedIds)\r\n              ? savedState.guessedIds.map((id) => Number(id)).filter((id) => Number.isFinite(id) && id > 0)\r\n              : []\r\n          );\r\n          const savedAttempts = Number(savedState.attempts);\r\n\r\n          state.results = [];\r\n          state.guessedIds = restoredGuessedIds;\r\n          state.attempts = Math.max(\r\n            0,\r\n            Math.min(\r\n              state.maxAttempts,\r\n              Number.isFinite(savedAttempts) ? savedAttempts : chronologicalIds.length\r\n            )\r\n          );\r\n          state.complete = false;\r\n\r\n          chronologicalIds.forEach((id, index) => {\r\n            const guessArtist = artists.find((artist) => artist.id === id);\r\n            if (!guessArtist) return;\r\n\r\n            state.guessedIds.add(guessArtist.id);\r\n            state.results.unshift(buildResultEntry(guessArtist, state.target, {\r\n              label: \"Tentativo \" + (index + 1),\r\n              spotifyId: guessArtist.id === state.target.id ? state.target.spotifyId : \"\"\r\n            }));\r\n          });\r\n\r\n          if (!Number.isFinite(savedAttempts)) {\r\n            state.attempts = Math.min(state.maxAttempts, chronologicalIds.length);\r\n          }\r\n\r\n          if (savedState.status === \"won\") {\r\n            state.complete = true;\r\n            setMessage(\"Hai indovinato \" + state.target.name + \".\", \"success\");\r\n            syncClassicStreakResult(\"won\");\r\n            return;\r\n          }\r\n\r\n          if (savedState.status === \"lost\") {\r\n            state.complete = true;\r\n            state.results.unshift(buildResultEntry(state.target, state.target, {\r\n              kind: \"answer\",\r\n              label: \"Artista corretto\",\r\n              spotifyId: state.target.spotifyId || \"\"\r\n            }));\r\n            setMessage(\"Tentativi finiti. L'artista era \" + state.target.name + \".\", \"error-final\");\r\n            syncClassicStreakResult(\"lost\");\r\n            return;\r\n          }\r\n\r\n          setMessage(\"\", \"\");\r\n        } catch (error) {\r\n          console.error(\"Errore nel caricamento del Daily salvato:\", error);\r\n          try {\r\n            window.localStorage.removeItem(classicStorageKey);\r\n          } catch (_) {}\r\n        }\r\n      }\r\n\r\n      function normalize(value) {\r\n        return String(value || \"\").trim().toLowerCase();\r\n      }\r\n\r\n      function formatPopularityLevel(value) {\r\n        const listeners = Number(value || 0);\r\n        if (!Number.isFinite(listeners) || listeners <= 0) return \"N\/D\";\r\n        if (listeners >= 1e9) return (listeners \/ 1e9).toFixed(listeners >= 1e10 ? 0 : 1).replace(\/\\.0$\/, \"\") + \"B\";\r\n        if (listeners >= 1e6) return (listeners \/ 1e6).toFixed(listeners >= 1e7 ? 0 : 1).replace(\/\\.0$\/, \"\") + \"M\";\r\n        if (listeners >= 1e3) return (listeners \/ 1e3).toFixed(listeners >= 1e5 ? 0 : 1).replace(\/\\.0$\/, \"\") + \"K\";\r\n        return String(listeners);\r\n      }\r\n\r\n      function getMonthlyListeners(artist) {\r\n        const manualValue = getManualMonthlyListeners(artist);\r\n        if (manualValue > 0) {\r\n          return manualValue;\r\n        }\r\n\r\n        const value = Number(artist && artist.monthlyListeners || 0);\r\n        return Number.isFinite(value) && value > 0 ? Math.round(value) : 0;\r\n      }\r\n\r\n      function getLegacyPopularityLevel(artist) {\r\n        const value = normalize(artist && artist.popularity);\r\n        return popularityLevels.includes(value) ? value : \"\";\r\n      }\r\n\r\n      function getPopularityIndexFromMonthlyListeners(value) {\r\n        const listeners = Number(value || 0);\r\n        if (!Number.isFinite(listeners) || listeners <= 0) {\r\n          return -1;\r\n        }\r\n\r\n        let level = monthlyListenerBuckets[0].level;\r\n        for (const bucket of monthlyListenerBuckets) {\r\n          if (listeners >= bucket.min) {\r\n            level = bucket.level;\r\n          }\r\n        }\r\n\r\n        return popularityLevels.indexOf(level);\r\n      }\r\n\r\n      function getComparablePopularityIndex(artist) {\r\n        const monthlyIndex = getPopularityIndexFromMonthlyListeners(getMonthlyListeners(artist));\r\n        if (monthlyIndex >= 0) {\r\n          return monthlyIndex;\r\n        }\r\n\r\n        return popularityLevels.indexOf(getLegacyPopularityLevel(artist));\r\n      }\r\n\r\n      function formatPopularityDisplay(artist) {\r\n        const listeners = getMonthlyListeners(artist);\r\n        if (listeners > 0) {\r\n          return formatPopularityLevel(listeners);\r\n        }\r\n\r\n        const fallback = getLegacyPopularityLevel(artist);\r\n        return fallback ? fallback.charAt(0).toUpperCase() + fallback.slice(1) : \"N\/D\";\r\n      }\r\n\r\n      function formatGenderValue(value) {\r\n        if (value === \"M\") return \"Uomo\";\r\n        if (value === \"F\") return \"Donna\";\r\n        return value || \"N\/D\";\r\n      }\r\n\r\n      function getItalyDateInfo() {\r\n        const formatter = new Intl.DateTimeFormat(\"en-CA\", {\r\n          timeZone: \"Europe\/Rome\",\r\n          year: \"numeric\",\r\n          month: \"2-digit\",\r\n          day: \"2-digit\"\r\n        });\r\n        const parts = formatter.formatToParts(new Date());\r\n        const year = Number(parts.find((part) => part.type === \"year\").value);\r\n        const month = Number(parts.find((part) => part.type === \"month\").value);\r\n        const day = Number(parts.find((part) => part.type === \"day\").value);\r\n        return {\r\n          dayKey: year + \"-\" + String(month).padStart(2, \"0\") + \"-\" + String(day).padStart(2, \"0\"),\r\n          dayIndex: Math.floor(Date.UTC(year, month - 1, day) \/ 86400000)\r\n        };\r\n      }\r\n\r\n      function hashString(value) {\r\n        let hash = 2166136261;\r\n\r\n        for (let index = 0; index < value.length; index++) {\r\n          hash ^= value.charCodeAt(index);\r\n          hash = Math.imul(hash, 16777619);\r\n        }\r\n\r\n        return hash >>> 0;\r\n      }\r\n\r\n      function createSeededRandom(seed) {\r\n        let state = seed >>> 0;\r\n\r\n        return function () {\r\n          state += 0x6D2B79F5;\r\n          let value = Math.imul(state ^ (state >>> 15), 1 | state);\r\n          value ^= value + Math.imul(value ^ (value >>> 7), 61 | value);\r\n          return ((value ^ (value >>> 14)) >>> 0) \/ 4294967296;\r\n        };\r\n      }\r\n\r\n      function getDailyTarget() {\r\n        if (!artists.length) return null;\r\n\r\n        const random = createSeededRandom(hashString(String(italyDateInfo.dayKey || \"\")));\r\n        const dailyIndex = Math.floor(random() * artists.length);\r\n        return artists[dailyIndex] || artists[0];\r\n      }\r\n\r\n      function pickRandomArtist(excludedIds) {\r\n        const blocked = excludedIds || new Set();\r\n        let pool = artists.filter((artist) => !blocked.has(artist.id));\r\n        if (!pool.length) pool = artists.slice();\r\n        return pool[Math.floor(Math.random() * pool.length)];\r\n      }\r\n\r\n      function setMessage(text, tone) {\r\n        if (messageTimeoutId) {\r\n          window.clearTimeout(messageTimeoutId);\r\n          messageTimeoutId = 0;\r\n        }\r\n\r\n        elements.message.className = \"message\";\r\n        if (text && tone) {\r\n          elements.message.textContent = text;\r\n          elements.message.classList.add(\"is-visible\", \"is-\" + tone);\r\n\r\n          if (tone !== \"success\" && tone !== \"error-final\") {\r\n            messageTimeoutId = window.setTimeout(function () {\r\n              elements.message.className = \"message\";\r\n              elements.message.textContent = \"\";\r\n              messageTimeoutId = 0;\r\n            }, 3000);\r\n          }\r\n          return;\r\n        }\r\n        elements.message.textContent = \"\";\r\n      }\r\n\r\n      function renderClassicStreakGuestState() {\r\n        elements.dailyStreakCard.classList.add(\"is-guest\");\r\n        elements.dailyStreakCard.setAttribute(\"href\", guestStreakLoginUrl);\r\n        elements.dailyStreakCard.setAttribute(\"aria-label\", \"Accedi per salvare la streak\");\r\n        elements.dailyStreakMain.textContent = \"STREAK\";\r\n        elements.dailyStreakSub.textContent = \"Accedi per salvarla\";\r\n        classicStreakLoaded = true;\r\n      }\r\n\r\n      function renderClassicStreakLoadingState() {\r\n        elements.dailyStreakCard.classList.remove(\"is-guest\");\r\n        elements.dailyStreakCard.removeAttribute(\"href\");\r\n        elements.dailyStreakCard.removeAttribute(\"aria-label\");\r\n        elements.dailyStreakMain.textContent = \"...\";\r\n        elements.dailyStreakSub.textContent = \"Caricamento streak\";\r\n      }\r\n\r\n      function renderClassicStreakState(data) {\r\n        if (!data || !data.is_logged_in) {\r\n          renderClassicStreakGuestState();\r\n          return;\r\n        }\r\n\r\n        elements.dailyStreakCard.classList.remove(\"is-guest\");\r\n        elements.dailyStreakCard.removeAttribute(\"href\");\r\n        elements.dailyStreakCard.removeAttribute(\"aria-label\");\r\n\r\n        const streakValue = Number(data.current_streak || 0);\r\n        elements.dailyStreakMain.textContent = String(streakValue) + \" \" + (streakValue === 1 ? \"GIORNO\" : \"GIORNI\");\r\n\r\n        if (data.today_result === \"won\") {\r\n          elements.dailyStreakSub.textContent = \"Indovinata oggi - Record \" + String(data.best_streak || data.current_streak || 0);\r\n        } else if (data.today_result === \"lost\") {\r\n          elements.dailyStreakSub.textContent = \"Interrotta oggi - Record \" + String(data.best_streak || 0);\r\n        } else {\r\n          elements.dailyStreakSub.textContent = \"Record \" + String(data.best_streak || data.current_streak || 0);\r\n        }\r\n\r\n        classicStreakLoaded = true;\r\n      }\r\n\r\n      async function postClassicStreakAction(action, extraData) {\r\n        const ajaxUrl = classicConfig.ajaxUrl;\r\n        if (!ajaxUrl) {\r\n          throw new Error(\"Config streak WordPress non trovata\");\r\n        }\r\n\r\n        const body = new URLSearchParams({\r\n          action: action,\r\n          nonce: classicConfig.nonce || \"\",\r\n          ...(extraData || {})\r\n        });\r\n\r\n        const response = await fetch(ajaxUrl, {\r\n          method: \"POST\",\r\n          credentials: \"same-origin\",\r\n          headers: {\r\n            \"Content-Type\": \"application\/x-www-form-urlencoded; charset=UTF-8\"\r\n          },\r\n          body: body.toString()\r\n        });\r\n\r\n        if (!response.ok) {\r\n          throw new Error(\"Richiesta streak non riuscita\");\r\n        }\r\n\r\n        return response.json();\r\n      }\r\n\r\n      async function loadClassicStreakStatus(force) {\r\n        if (!classicConfig.isLoggedIn) {\r\n          renderClassicStreakGuestState();\r\n          return;\r\n        }\r\n\r\n        if (classicStreakLoading) return;\r\n        if (classicStreakLoaded && !force) return;\r\n\r\n        classicStreakLoading = true;\r\n        renderClassicStreakLoadingState();\r\n\r\n        try {\r\n          const response = await postClassicStreakAction(\"bulldogle_classic_streak_status\");\r\n          if (response && response.success) {\r\n            renderClassicStreakState(response.data);\r\n          } else {\r\n            renderClassicStreakGuestState();\r\n          }\r\n        } catch (_) {\r\n          renderClassicStreakGuestState();\r\n        } finally {\r\n          classicStreakLoading = false;\r\n        }\r\n      }\r\n\r\n      async function syncClassicStreakResult(result) {\r\n        if (!classicConfig.isLoggedIn) return;\r\n\r\n        try {\r\n          const response = await postClassicStreakAction(\"bulldogle_classic_streak_update\", {\r\n            result: result,\r\n            day_key: getItalyDateInfo().dayKey\r\n          });\r\n\r\n          if (response && response.success) {\r\n            renderClassicStreakState(response.data);\r\n          }\r\n        } catch (error) {\r\n          console.error(\"Errore aggiornamento streak Bulldogle:\", error);\r\n        }\r\n      }\r\n\r\n      function getRankedLoginUrl() {\r\n        return rankedConfig.loginUrl || guestStreakLoginUrl;\r\n      }\r\n\r\n      function isRankedMode() {\r\n        return app.mode === \"ranked\";\r\n      }\r\n\r\n      function getCurrentHelpPanel() {\r\n        return isRankedMode() ? elements.mobileRankedHelpPanel : elements.helpPanel;\r\n      }\r\n\r\n      function closeAllHelpPanels() {\r\n        [elements.helpPanel, elements.mobileRankedHelpPanel].forEach((panel) => {\r\n          if (!panel) return;\r\n          panel.classList.remove(\"is-open\");\r\n          panel.setAttribute(\"aria-hidden\", \"true\");\r\n        });\r\n        elements.helpToggle.classList.remove(\"is-active\");\r\n      }\r\n\r\n      function syncHelpToggleState() {\r\n        const panel = getCurrentHelpPanel();\r\n        elements.helpToggle.classList.toggle(\"is-active\", !!panel && panel.classList.contains(\"is-open\"));\r\n      }\r\n\r\n      function restorePanelPlacement(panel, parent, nextSibling) {\r\n        if (!panel || !parent) return;\r\n        if (panel.parentElement === parent) return;\r\n\r\n        if (nextSibling && nextSibling.parentElement === parent) {\r\n          parent.insertBefore(panel, nextSibling);\r\n          return;\r\n        }\r\n\r\n        parent.appendChild(panel);\r\n      }\r\n\r\n      function positionSuggestionsFor(inputElement, suggestionElement) {\r\n        const rect = inputElement.getBoundingClientRect();\r\n        const viewport = getViewportMetrics();\r\n        const viewportPadding = 10;\r\n        const width = Math.min(rect.width, viewport.width - viewportPadding * 2);\r\n        const left = Math.max(\r\n          viewport.offsetLeft + viewportPadding,\r\n          Math.min(rect.left, viewport.offsetLeft + viewport.width - width - viewportPadding)\r\n        );\r\n        const spaceBelow = viewport.offsetTop + viewport.height - rect.bottom - viewportPadding;\r\n        const maxHeight = Math.max(140, Math.min(280, spaceBelow - 8));\r\n\r\n        suggestionElement.style.width = width + \"px\";\r\n        suggestionElement.style.left = left + \"px\";\r\n        suggestionElement.style.top = Math.max(viewportPadding, rect.bottom + 8) + \"px\";\r\n        suggestionElement.style.maxHeight = maxHeight + \"px\";\r\n      }\r\n\r\n      function setRankedMessage(text, tone) {\r\n        if (rankedMessageTimeoutId) {\r\n          window.clearTimeout(rankedMessageTimeoutId);\r\n          rankedMessageTimeoutId = 0;\r\n        }\r\n\r\n        elements.mobileRankedMessage.className = \"message\";\r\n        if (text && tone) {\r\n          elements.mobileRankedMessage.textContent = text;\r\n          elements.mobileRankedMessage.classList.add(\"is-visible\", \"is-\" + tone);\r\n\r\n          if (tone !== \"success\") {\r\n            rankedMessageTimeoutId = window.setTimeout(function () {\r\n              elements.mobileRankedMessage.className = \"message\";\r\n              elements.mobileRankedMessage.textContent = \"\";\r\n              rankedMessageTimeoutId = 0;\r\n            }, 2200);\r\n          }\r\n          return;\r\n        }\r\n\r\n        elements.mobileRankedMessage.textContent = \"\";\r\n      }\r\n\r\n      function disableRankedInput(disabled) {\r\n        elements.mobileRankedInput.disabled = disabled;\r\n        elements.mobileRankedSubmitButton.disabled =\r\n          disabled ||\r\n          !app.ranked.active ||\r\n          app.ranked.betweenRounds ||\r\n          app.ranked.preparing ||\r\n          app.ranked.submitting;\r\n      }\r\n\r\n      function hideRankedSuggestions() {\r\n        if (elements.mobileRankedSuggestions) {\r\n          elements.mobileRankedSuggestions.style.display = \"none\";\r\n        }\r\n      }\r\n\r\n      function showRankedSuggestions() {\r\n        positionSuggestionsFor(elements.mobileRankedInput, elements.mobileRankedSuggestions);\r\n        elements.mobileRankedSuggestions.style.display = \"block\";\r\n      }\r\n\r\n      function formatRankedSummaryLines(lines) {\r\n        elements.mobileRankedSummaryLines.innerHTML = \"\";\r\n        lines.forEach((line) => {\r\n          const row = document.createElement(\"div\");\r\n          row.className = \"ranked-summary-line\";\r\n          row.innerHTML = line;\r\n          elements.mobileRankedSummaryLines.appendChild(row);\r\n        });\r\n      }\r\n\r\n      function renderRankedMeta() {\r\n        const state = app.ranked;\r\n        elements.mobileRankedTimerValue.textContent = formatTime(state.timeLeft);\r\n        elements.mobileRankedScoreValue.textContent = String(state.score);\r\n        if (elements.mobileRankedRoundValue) {\r\n          elements.mobileRankedRoundValue.textContent = state.active\r\n            ? \"Artista #\" + String(state.score + 1)\r\n            : (state.complete ? \"Fine\" : \"Pronto\");\r\n        }\r\n      }\r\n\r\n      function renderRankedAttemptsCard() {\r\n        const attemptsLeft = Math.max(0, RANKED_ATTEMPTS - app.ranked.roundAttempts);\r\n        elements.mobileRankedAttemptsCard.textContent = String(attemptsLeft) + \" \" + (attemptsLeft === 1 ? \"TENTATIVO\" : \"TENTATIVI\");\r\n      }\r\n\r\n      function renderRankedInputState() {\r\n        disableRankedInput(!app.ranked.active);\r\n        elements.mobileRankedInput.placeholder = app.ranked.active ? \"inserisci un artista\" : (app.ranked.complete ? \"Partita conclusa\" : \"inserisci un artista\");\r\n      }\r\n\r\n      function renderRankedActionButton() {\r\n        const button = elements.mobileRankedSideActionButton;\r\n        button.className = \"secondary-button\";\r\n        button.disabled = false;\r\n\r\n        if (app.ranked.preparing || app.ranked.submitting) {\r\n          button.textContent = \"...\";\r\n          button.disabled = true;\r\n          button.dataset.action = \"wait\";\r\n          return;\r\n        }\r\n\r\n        if (app.ranked.active) {\r\n          if (app.ranked.betweenRounds) {\r\n            button.textContent = \"ATTENDI\";\r\n            button.disabled = true;\r\n            button.dataset.action = \"wait\";\r\n            return;\r\n          }\r\n\r\n          button.textContent = \"SKIP\";\r\n          button.dataset.action = \"skip\";\r\n          return;\r\n        }\r\n\r\n        if (app.ranked.complete) {\r\n          button.textContent = \"RIGIOCA\";\r\n          button.dataset.action = \"restart\";\r\n          return;\r\n        }\r\n\r\n        if (hasRankedBackend && !rankedConfig.isLoggedIn) {\r\n          button.textContent = \"ACCEDI\";\r\n          button.dataset.action = \"login\";\r\n          return;\r\n        }\r\n\r\n        button.textContent = \"INIZIA\";\r\n        button.dataset.action = \"start\";\r\n      }\r\n\r\n      function renderRankedResults() {\r\n        const results = app.ranked.results || [];\r\n        elements.mobileRankedResultsList.innerHTML = \"\";\r\n\r\n        if (!results.length) {\r\n          const empty = document.createElement(\"div\");\r\n          empty.className = \"empty-state\";\r\n          empty.textContent = app.ranked.complete\r\n            ? \"La partita e finita. Puoi controllare il riepilogo finale.\"\r\n            : (app.ranked.active\r\n              ? \"I tentativi di questo round appariranno qui.\"\r\n              : (hasRankedBackend && !rankedConfig.isLoggedIn ? \"ACCEDI per giocare.\" : \"Premi INIZIA per giocare.\"));\r\n          elements.mobileRankedResultsList.appendChild(empty);\r\n          return;\r\n        }\r\n\r\n        results.forEach((result) => {\r\n          elements.mobileRankedResultsList.appendChild(buildResultCard(result));\r\n        });\r\n      }\r\n\r\n      function renderRankedSummary() {\r\n        elements.mobileRankedSummaryPanel.classList.toggle(\"hidden\", !app.ranked.complete || !app.ranked.summaryLines.length);\r\n        elements.mobileRankedSummaryPanel.classList.toggle(\"is-record\", app.ranked.isRecord);\r\n        elements.mobileRankedSummaryTitle.textContent = app.ranked.summaryTitle || \"Partita conclusa\";\r\n        formatRankedSummaryLines(app.ranked.summaryLines);\r\n      }\r\n\r\n      function resetRankedState() {\r\n        const state = app.ranked;\r\n        state.active = false;\r\n        state.preparing = false;\r\n        state.submitting = false;\r\n        state.complete = false;\r\n        state.betweenRounds = false;\r\n        state.sessionToken = \"\";\r\n        state.currentArtist = null;\r\n        state.score = 0;\r\n        state.timeLeft = RANKED_INITIAL_TIME;\r\n        state.roundAttempts = 0;\r\n        state.roundGuessedIds = new Set();\r\n        state.usedTargetIds = new Set();\r\n        state.freeHintArtist = null;\r\n        state.results = [];\r\n        state.summaryTitle = \"Partita conclusa\";\r\n        state.summaryLines = [];\r\n        state.isRecord = false;\r\n        window.clearInterval(state.timerId);\r\n        window.clearTimeout(state.roundTransitionId);\r\n        state.timerId = 0;\r\n        state.roundTransitionId = 0;\r\n        setRankedMessage(\"\", \"\");\r\n        elements.mobileRankedInput.value = \"\";\r\n        hideRankedSuggestions();\r\n      }\r\n\r\n      function buildRankedSummaryLines(data) {\r\n        const lines = [];\r\n        if (app.ranked.currentArtist && app.ranked.currentArtist.name) {\r\n          lines.push(\"L'ultimo artista era: <strong>\" + escapeHtml(app.ranked.currentArtist.name) + \"<\/strong>\");\r\n        }\r\n        lines.push(\"Punteggio finale: <strong>\" + String(app.ranked.score) + \"<\/strong>\");\r\n\r\n        if (data && typeof data.best_score !== \"undefined\") {\r\n          lines.push(\"Record mensile: <strong>\" + String(data.best_score) + \"<\/strong>\");\r\n          if (data.best_rank) {\r\n            lines.push(\"Migliore posizione: <strong>#\" + String(data.best_rank) + \"<\/strong>\");\r\n          } else {\r\n            lines.push(\"Migliore posizione: <strong>Fuori top 50<\/strong>\");\r\n          }\r\n        } else if (hasRankedBackend) {\r\n          lines.push(\"Record non salvato, riprova piu tardi.\");\r\n        }\r\n\r\n        return lines;\r\n      }\r\n\r\n      async function postRankedAction(action, extraData) {\r\n        const body = new URLSearchParams({\r\n          action: action,\r\n          nonce: rankedConfig.nonce || \"\",\r\n          game_key: \"classic\",\r\n          ...(extraData || {})\r\n        });\r\n\r\n        const response = await fetch(rankedConfig.ajaxUrl, {\r\n          method: \"POST\",\r\n          credentials: \"same-origin\",\r\n          headers: {\r\n            \"Content-Type\": \"application\/x-www-form-urlencoded; charset=UTF-8\"\r\n          },\r\n          body: body.toString()\r\n        });\r\n\r\n        if (!response.ok) {\r\n          throw new Error(\"Richiesta ranked non riuscita\");\r\n        }\r\n\r\n        return response.json();\r\n      }\r\n\r\n      function startNextRankedArtist() {\r\n        if (!app.ranked.active) return;\r\n\r\n        window.clearTimeout(app.ranked.roundTransitionId);\r\n        app.ranked.betweenRounds = false;\r\n\r\n        if (app.ranked.usedTargetIds.size >= artists.length) {\r\n          app.ranked.usedTargetIds.clear();\r\n        }\r\n\r\n        const nextArtist = pickRandomArtist(app.ranked.usedTargetIds);\r\n        app.ranked.currentArtist = nextArtist;\r\n        app.ranked.usedTargetIds.add(nextArtist.id);\r\n        app.ranked.roundAttempts = 0;\r\n        app.ranked.roundGuessedIds = new Set();\r\n        app.ranked.results = [];\r\n\r\n        if (app.ranked.freeHintArtist) {\r\n          app.ranked.results.unshift(buildResultEntry(app.ranked.freeHintArtist, app.ranked.currentArtist, {\r\n            kind: \"auto\",\r\n            label: \"Reveal del Artista passato\"\r\n          }));\r\n          app.ranked.freeHintArtist = null;\r\n        }\r\n\r\n        elements.mobileRankedInput.value = \"\";\r\n        hideRankedSuggestions();\r\n        setRankedMessage(\"\", \"\");\r\n        renderRankedMeta();\r\n        renderRankedAttemptsCard();\r\n        renderRankedInputState();\r\n        renderRankedActionButton();\r\n        renderRankedResults();\r\n        if (app.mode === \"ranked\") {\r\n          elements.mobileRankedInput.focus();\r\n        }\r\n      }\r\n\r\n      function completeRankedRound(message, tone, carryArtist) {\r\n        if (!app.ranked.active || !app.ranked.currentArtist) return;\r\n\r\n        if (carryArtist) {\r\n          app.ranked.freeHintArtist = app.ranked.currentArtist;\r\n        }\r\n\r\n        app.ranked.betweenRounds = true;\r\n        elements.mobileRankedInput.value = \"\";\r\n        hideRankedSuggestions();\r\n        renderRankedInputState();\r\n        renderRankedActionButton();\r\n        setRankedMessage(message, tone);\r\n\r\n        app.ranked.roundTransitionId = window.setTimeout(function () {\r\n          if (!app.ranked.active || app.ranked.timeLeft <= 0) return;\r\n          startNextRankedArtist();\r\n        }, RANKED_ROUND_TRANSITION_MS);\r\n      }\r\n\r\n      function tickRanked() {\r\n        if (!app.ranked.active) return;\r\n        app.ranked.timeLeft -= 1;\r\n        renderRankedMeta();\r\n        if (app.ranked.timeLeft <= 0) {\r\n          finishRankedGame();\r\n        }\r\n      }\r\n\r\n      async function startRankedGame() {\r\n        if (app.ranked.active || app.ranked.preparing) return;\r\n\r\n        if (hasRankedBackend && !rankedConfig.isLoggedIn) {\r\n          window.location.href = getRankedLoginUrl();\r\n          return;\r\n        }\r\n\r\n        app.ranked.preparing = true;\r\n        app.ranked.complete = false;\r\n        app.ranked.summaryLines = [];\r\n        renderRankedActionButton();\r\n\r\n        try {\r\n          if (hasRankedBackend) {\r\n            const response = await postRankedAction(\"bulldogle_ranked_start\");\r\n            if (!response || !response.success || !response.data || !response.data.is_logged_in) {\r\n              window.location.href = getRankedLoginUrl();\r\n              return;\r\n            }\r\n            app.ranked.sessionToken = String(response.data.token || \"\");\r\n          } else {\r\n            app.ranked.sessionToken = \"demo-\" + String(Date.now());\r\n          }\r\n\r\n          window.clearInterval(app.ranked.timerId);\r\n          window.clearTimeout(app.ranked.roundTransitionId);\r\n          app.ranked.active = true;\r\n          app.ranked.complete = false;\r\n          app.ranked.betweenRounds = false;\r\n          app.ranked.submitting = false;\r\n          app.ranked.score = 0;\r\n          app.ranked.timeLeft = RANKED_INITIAL_TIME;\r\n          app.ranked.roundAttempts = 0;\r\n          app.ranked.roundGuessedIds = new Set();\r\n          app.ranked.usedTargetIds = new Set();\r\n          app.ranked.freeHintArtist = null;\r\n          app.ranked.results = [];\r\n          app.ranked.summaryTitle = \"Partita conclusa\";\r\n          app.ranked.summaryLines = [];\r\n          app.ranked.isRecord = false;\r\n          setRankedMessage(\"\", \"\");\r\n          renderRankedPanel();\r\n          startNextRankedArtist();\r\n          app.ranked.timerId = window.setInterval(tickRanked, 1000);\r\n        } catch (_) {\r\n          setRankedMessage(\"Non sono riuscito ad avviare la partita. Riprova tra poco.\", \"error\");\r\n        } finally {\r\n          app.ranked.preparing = false;\r\n          renderRankedInputState();\r\n          renderRankedActionButton();\r\n        }\r\n      }\r\n\r\n      function submitRankedGuess() {\r\n        if (!app.ranked.active || app.ranked.betweenRounds || !app.ranked.currentArtist) return;\r\n\r\n        const guessName = elements.mobileRankedInput.value.trim();\r\n        const guessArtist = findArtistByName(guessName);\r\n\r\n        if (!guessArtist) {\r\n          setRankedMessage(\"Artista non trovato nella lista.\", \"error\");\r\n          return;\r\n        }\r\n\r\n        if (app.ranked.roundGuessedIds.has(guessArtist.id)) {\r\n          setRankedMessage(\"Hai gia provato questo artista.\", \"error\");\r\n          elements.mobileRankedInput.value = \"\";\r\n          return;\r\n        }\r\n\r\n        app.ranked.roundGuessedIds.add(guessArtist.id);\r\n        app.ranked.roundAttempts += 1;\r\n        app.ranked.results.unshift(buildResultEntry(guessArtist, app.ranked.currentArtist, {\r\n          label: \"Tentativo \" + app.ranked.roundAttempts\r\n        }));\r\n        renderRankedAttemptsCard();\r\n        renderRankedResults();\r\n        elements.mobileRankedInput.value = \"\";\r\n        hideRankedSuggestions();\r\n\r\n        if (guessArtist.id === app.ranked.currentArtist.id) {\r\n          app.ranked.score += 1;\r\n          app.ranked.timeLeft += RANKED_CORRECT_BONUS;\r\n          renderRankedMeta();\r\n          completeRankedRound(\"Hai indovinato!\", \"success\", true);\r\n          return;\r\n        }\r\n\r\n        if (app.ranked.roundAttempts >= RANKED_ATTEMPTS) {\r\n          completeRankedRound(\"Hai finito i tentativi! Era \" + app.ranked.currentArtist.name + \".\", \"error\", true);\r\n        }\r\n      }\r\n\r\n      function skipRankedArtist() {\r\n        if (!app.ranked.active || app.ranked.betweenRounds || !app.ranked.currentArtist) return;\r\n\r\n        app.ranked.timeLeft = Math.max(0, app.ranked.timeLeft - RANKED_SKIP_PENALTY);\r\n        renderRankedMeta();\r\n\r\n        if (app.ranked.timeLeft <= 0) {\r\n          finishRankedGame();\r\n          return;\r\n        }\r\n\r\n        completeRankedRound(\"Hai skippato! Era \" + app.ranked.currentArtist.name + \".\", \"error\", true);\r\n      }\r\n\r\n      async function finishRankedGame() {\r\n        if (!app.ranked.active || app.ranked.submitting) return;\r\n\r\n        app.ranked.active = false;\r\n        app.ranked.complete = true;\r\n        app.ranked.betweenRounds = false;\r\n        app.ranked.submitting = true;\r\n        app.ranked.timeLeft = 0;\r\n        window.clearInterval(app.ranked.timerId);\r\n        window.clearTimeout(app.ranked.roundTransitionId);\r\n        app.ranked.timerId = 0;\r\n        app.ranked.roundTransitionId = 0;\r\n        hideRankedSuggestions();\r\n        setRankedMessage(\"\", \"\");\r\n        renderRankedMeta();\r\n        renderRankedInputState();\r\n        renderRankedActionButton();\r\n\r\n        app.ranked.summaryTitle = \"Partita conclusa\";\r\n        app.ranked.summaryLines = [\"Salvataggio record...\"];\r\n        app.ranked.isRecord = false;\r\n        renderRankedSummary();\r\n\r\n        try {\r\n          let data = null;\r\n\r\n          if (hasRankedBackend) {\r\n            const response = await postRankedAction(\"bulldogle_ranked_submit\", {\r\n              token: app.ranked.sessionToken,\r\n              score: String(app.ranked.score)\r\n            });\r\n            data = response && response.success ? response.data : null;\r\n          }\r\n\r\n          if (data) {\r\n            app.ranked.summaryTitle = data.is_record ? \"Nuovo record!\" : \"Partita conclusa\";\r\n            app.ranked.summaryLines = buildRankedSummaryLines(data);\r\n            app.ranked.isRecord = Boolean(data.is_record);\r\n          } else {\r\n            app.ranked.summaryTitle = \"Partita conclusa\";\r\n            app.ranked.summaryLines = buildRankedSummaryLines(null);\r\n            app.ranked.isRecord = false;\r\n          }\r\n        } catch (_) {\r\n          app.ranked.summaryTitle = \"Partita conclusa\";\r\n          app.ranked.summaryLines = buildRankedSummaryLines(null);\r\n          app.ranked.isRecord = false;\r\n        } finally {\r\n          app.ranked.submitting = false;\r\n          renderRankedPanel();\r\n        }\r\n      }\r\n\r\n      function updateRankedSuggestions() {\r\n        const value = normalize(elements.mobileRankedInput.value);\r\n        if (!value || !app.ranked.active || app.ranked.betweenRounds || !app.ranked.currentArtist) {\r\n          hideRankedSuggestions();\r\n          return;\r\n        }\r\n\r\n        const matches = artists.filter((artist) => {\r\n          return normalize(artist.name).includes(value) && !app.ranked.roundGuessedIds.has(artist.id);\r\n        }).slice(0, 8);\r\n\r\n        elements.mobileRankedSuggestions.innerHTML = \"\";\r\n        matches.forEach((artist) => {\r\n          const button = document.createElement(\"button\");\r\n          button.type = \"button\";\r\n          button.className = \"suggestion\";\r\n\r\n          const left = document.createElement(\"span\");\r\n          left.textContent = artist.name;\r\n          const right = document.createElement(\"small\");\r\n          right.textContent = artist.city + \" \/ \" + formatPopularityDisplay(artist);\r\n\r\n          button.appendChild(left);\r\n          button.appendChild(right);\r\n          button.addEventListener(\"click\", function () {\r\n            elements.mobileRankedInput.value = artist.name;\r\n            hideRankedSuggestions();\r\n            elements.mobileRankedInput.focus();\r\n          });\r\n          elements.mobileRankedSuggestions.appendChild(button);\r\n        });\r\n\r\n        if (matches.length) {\r\n          showRankedSuggestions();\r\n          return;\r\n        }\r\n\r\n        hideRankedSuggestions();\r\n      }\r\n\r\n      function handleRankedSideAction() {\r\n        const action = elements.mobileRankedSideActionButton.dataset.action;\r\n\r\n        if (action === \"login\") {\r\n          window.location.href = getRankedLoginUrl();\r\n          return;\r\n        }\r\n\r\n        if (action === \"start\" || action === \"restart\") {\r\n          startRankedGame();\r\n          return;\r\n        }\r\n\r\n        if (action === \"skip\") {\r\n          skipRankedArtist();\r\n        }\r\n      }\r\n\r\n      function renderRankedPanel() {\r\n        renderRankedMeta();\r\n        renderRankedAttemptsCard();\r\n        renderRankedInputState();\r\n        renderRankedActionButton();\r\n        renderRankedResults();\r\n        renderRankedSummary();\r\n        hideRankedSuggestions();\r\n      }\r\n\r\n      function disableGameInput(disabled) {\r\n        elements.input.disabled = disabled;\r\n        elements.submitButton.disabled = disabled;\r\n      }\r\n\r\n      function hideSuggestions() {\r\n        elements.suggestions.style.display = \"none\";\r\n      }\r\n\r\n      function getViewportMetrics() {\r\n        if (window.visualViewport) {\r\n          return {\r\n            width: window.visualViewport.width,\r\n            height: window.visualViewport.height,\r\n            offsetLeft: window.visualViewport.offsetLeft,\r\n            offsetTop: window.visualViewport.offsetTop\r\n          };\r\n        }\r\n\r\n        return {\r\n          width: window.innerWidth,\r\n          height: window.innerHeight,\r\n          offsetLeft: 0,\r\n          offsetTop: 0\r\n        };\r\n      }\r\n\r\n      function positionSuggestions() {\r\n        positionSuggestionsFor(elements.input, elements.suggestions);\r\n      }\r\n\r\n      function showSuggestions() {\r\n        positionSuggestions();\r\n        elements.suggestions.style.display = \"block\";\r\n      }\r\n\r\n      function syncHelpPanelPlacement() {\r\n        if (!elements.helpPanelMobileSlot) {\r\n          return;\r\n        }\r\n\r\n        const isMobileLayout = window.matchMedia(\"(max-width: 720px)\").matches;\r\n        const activePanel = getCurrentHelpPanel();\r\n\r\n        if (isMobileLayout) {\r\n          [elements.helpPanel, elements.mobileRankedHelpPanel].forEach((panel) => {\r\n            if (!panel) return;\r\n\r\n            if (panel === activePanel) {\r\n              if (panel.parentElement !== elements.helpPanelMobileSlot) {\r\n                elements.helpPanelMobileSlot.appendChild(panel);\r\n              }\r\n              return;\r\n            }\r\n\r\n            if (panel === elements.helpPanel) {\r\n              restorePanelPlacement(panel, desktopHelpPanelParent, desktopHelpPanelNextSibling);\r\n              return;\r\n            }\r\n\r\n            restorePanelPlacement(panel, desktopRankedHelpPanelParent, desktopRankedHelpPanelNextSibling);\r\n          });\r\n          return;\r\n        }\r\n\r\n        restorePanelPlacement(elements.helpPanel, desktopHelpPanelParent, desktopHelpPanelNextSibling);\r\n        restorePanelPlacement(elements.mobileRankedHelpPanel, desktopRankedHelpPanelParent, desktopRankedHelpPanelNextSibling);\r\n      }\r\n\r\n      function getActiveState() {\r\n        return app.modes[app.mode];\r\n      }\r\n\r\n      function getModeGuessedIds() {\r\n        return getActiveState().guessedIds;\r\n      }\r\n\r\n      function buildPopularityTrait(guessArtist, targetArtist) {\r\n        const guessIndex = getMonthlyListeners(guessArtist);\r\n        const targetIndex = getMonthlyListeners(targetArtist);\r\n        let status = \"wrong\";\r\n        let text = formatPopularityDisplay(guessArtist);\r\n        let hint = \"Dato non disponibile.\";\r\n        let arrow = \"\";\r\n\r\n        if (guessIndex > 0 && targetIndex > 0) {\r\n          if (guessIndex === targetIndex) {\r\n            status = \"correct\";\r\n            hint = \"Stesso valore.\";\r\n          } else {\r\n            if (Math.abs(guessIndex - targetIndex) \/ Math.max(targetIndex, 1) <= 0.2) {\r\n              status = \"close\";\r\n              hint = \"Molto vicino.\";\r\n            }\r\n            arrow = targetIndex > guessIndex ? ARROWS.up : ARROWS.down;\r\n            if (status !== \"close\") {\r\n              hint = targetIndex > guessIndex ? \"Il target ha piu ascoltatori mensili.\" : \"Il target ha meno ascoltatori mensili.\";\r\n            }\r\n          }\r\n        } else {\r\n          const fallbackGuessIndex = getComparablePopularityIndex(guessArtist);\r\n          const fallbackTargetIndex = getComparablePopularityIndex(targetArtist);\r\n\r\n          if (fallbackGuessIndex >= 0 && fallbackTargetIndex >= 0) {\r\n            if (fallbackGuessIndex === fallbackTargetIndex) {\r\n              status = \"correct\";\r\n              hint = \"Stesso livello.\";\r\n            } else {\r\n              if (Math.abs(fallbackGuessIndex - fallbackTargetIndex) === 1) {\r\n                status = \"close\";\r\n                hint = \"A un gradino di distanza.\";\r\n              }\r\n              arrow = fallbackTargetIndex > fallbackGuessIndex ? ARROWS.up : ARROWS.down;\r\n              if (status !== \"close\") {\r\n                hint = fallbackTargetIndex > fallbackGuessIndex ? \"Il target e piu popolare.\" : \"Il target e meno popolare.\";\r\n              }\r\n            }\r\n          }\r\n        }\r\n\r\n        return { label: \"Popolarita\", value: text, status: status, hint: hint, arrow: arrow, suffix: \"\" };\r\n      }\r\n\r\n      function getRegionDirection(guessRegion, targetRegion) {\r\n        if (guessRegion === \"Estero\" && targetRegion !== \"Estero\") {\r\n          return { arrow: ARROWS.right, suffix: \"\ud83c\uddee\ud83c\uddf9\" };\r\n        }\r\n\r\n        if (targetRegion === \"Estero\" && guessRegion !== \"Estero\") {\r\n          return { arrow: ARROWS.right, suffix: \"\ud83c\udf0d\" };\r\n        }\r\n\r\n        const guessCoords = regionCoords[guessRegion];\r\n        const targetCoords = regionCoords[targetRegion];\r\n        if (!guessCoords || !targetCoords) return null;\r\n\r\n        const latDiff = targetCoords.lat - guessCoords.lat;\r\n        const lonDiff = targetCoords.lon - guessCoords.lon;\r\n        const threshold = 0.8;\r\n\r\n        if (Math.abs(latDiff) > threshold) {\r\n          return { arrow: latDiff > 0 ? ARROWS.up : ARROWS.down, suffix: \"\" };\r\n        }\r\n        return { arrow: lonDiff > 0 ? ARROWS.right : ARROWS.left, suffix: \"\" };\r\n      }\r\n\r\n      function buildCityTrait(guessArtist, targetArtist) {\r\n        let status = \"wrong\";\r\n        let value = guessArtist.city || \"N\/D\";\r\n        let hint = \"Regione diversa.\";\r\n        let arrow = \"\";\r\n        let suffix = \"\";\r\n\r\n        if (guessArtist.city === targetArtist.city) {\r\n          status = \"correct\";\r\n          hint = \"Stessa citta.\";\r\n        } else if (guessArtist.region === targetArtist.region) {\r\n          status = \"close\";\r\n          hint = \"Stessa regione.\";\r\n        } else if (guessArtist.region === \"Estero\") {\r\n          const direction = getRegionDirection(guessArtist.region, targetArtist.region);\r\n          if (direction) {\r\n            arrow = direction.arrow;\r\n            suffix = direction.suffix;\r\n          }\r\n          hint = targetArtist.region !== \"Estero\" ? \"Il target e in Italia.\" : \"Ancora estero.\";\r\n        } else if (targetArtist.region === \"Estero\") {\r\n          const direction = getRegionDirection(guessArtist.region, targetArtist.region);\r\n          if (direction) {\r\n            arrow = direction.arrow;\r\n            suffix = direction.suffix;\r\n          }\r\n          hint = \"Il target e nato all'estero.\";\r\n        } else {\r\n          const direction = getRegionDirection(guessArtist.region, targetArtist.region);\r\n          if (direction) {\r\n            arrow = direction.arrow;\r\n            suffix = direction.suffix;\r\n            hint = \"Direzione corretta indicata.\";\r\n          }\r\n        }\r\n\r\n        return { label: \"Citta\", value: value, status: status, hint: hint, arrow: arrow, suffix: suffix };\r\n      }\r\n\r\n      function buildDebutTrait(guessArtist, targetArtist) {\r\n        let status = \"wrong\";\r\n        let value = String(guessArtist.debutYear || \"N\/D\");\r\n        let hint = \"Fuori range.\";\r\n        let arrow = \"\";\r\n        const diff = guessArtist.debutYear - targetArtist.debutYear;\r\n\r\n        if (diff === 0) {\r\n          status = \"correct\";\r\n          hint = \"Anno esatto.\";\r\n        } else {\r\n          if (Math.abs(diff) <= 5) {\r\n            status = \"close\";\r\n            hint = \"Molto vicino.\";\r\n          }\r\n          arrow = targetArtist.debutYear > guessArtist.debutYear ? ARROWS.up : ARROWS.down;\r\n        }\r\n\r\n        return { label: \"Debutto\", value: value, status: status, hint: hint, arrow: arrow, suffix: \"\" };\r\n      }\r\n\r\n      function buildSimpleTrait(label, guessValue, targetValue, formatFn) {\r\n        const status = normalize(guessValue) === normalize(targetValue) ? \"correct\" : \"wrong\";\r\n        return {\r\n          label: label,\r\n          value: formatFn ? formatFn(guessValue) : (guessValue || \"N\/D\"),\r\n          status: status,\r\n          hint: status === \"correct\" ? \"Match.\" : \"Non coincide.\",\r\n          arrow: \"\",\r\n          suffix: \"\"\r\n        };\r\n      }\r\n\r\n      function buildTraits(guessArtist, targetArtist) {\r\n        return [\r\n          buildCityTrait(guessArtist, targetArtist),\r\n          buildDebutTrait(guessArtist, targetArtist),\r\n          buildSimpleTrait(\"Tipo\", guessArtist.members, targetArtist.members),\r\n          buildSimpleTrait(\"Voce\", guessArtist.gender, targetArtist.gender, formatGenderValue),\r\n          buildPopularityTrait(guessArtist, targetArtist)\r\n        ];\r\n      }\r\n\r\n      function getHeatScore(traits, solved) {\r\n        return Math.min(99, traits.reduce((total, trait) => {\r\n          if (trait.status === \"correct\") return total + 20;\r\n          if (trait.status === \"close\") return total + 12;\r\n          return total + 5;\r\n        }, solved ? 8 : 0));\r\n      }\r\n\r\n      function buildResultEntry(guessArtist, targetArtist, meta) {\r\n        const traits = buildTraits(guessArtist, targetArtist);\r\n        const solved = guessArtist.id === targetArtist.id;\r\n        const kind = meta.kind || \"guess\";\r\n        return {\r\n          guessArtist: guessArtist,\r\n          traits: traits,\r\n          solved: solved,\r\n          heat: getHeatScore(traits, solved),\r\n          kind: kind,\r\n          label: meta.label || \"Tentativo\",\r\n          subcopy: meta.subcopy || \"\",\r\n          spotifyId: meta.spotifyId || (solved ? guessArtist.spotifyId : \"\"),\r\n          tip: meta.tip || (solved ? guessArtist.tip : \"\")\r\n        };\r\n      }\r\n\r\n      function getArtistInitials(name) {\r\n        const parts = String(name || \"\").trim().split(\/\\s+\/).filter(Boolean);\r\n        if (!parts.length) return \"BM\";\r\n        return parts.slice(0, 2).map((part) => part.charAt(0)).join(\"\");\r\n      }\r\n\r\n      function persistSpotifyThumbnailUrl(spotifyId, thumbnailUrl) {\r\n        if (!spotifyId || !thumbnailUrl) return;\r\n        try {\r\n          const storedThumbs = JSON.parse(window.localStorage.getItem(spotifyThumbStorageKey) || \"{}\");\r\n          storedThumbs[spotifyId] = thumbnailUrl;\r\n          window.localStorage.setItem(spotifyThumbStorageKey, JSON.stringify(storedThumbs));\r\n        } catch (_) {}\r\n      }\r\n\r\n      function clearSpotifyThumbnailUrl(spotifyId) {\r\n        if (!spotifyId) return;\r\n        spotifyThumbCache.delete(spotifyId);\r\n        spotifyThumbRequests.delete(spotifyId);\r\n        try {\r\n          const storedThumbs = JSON.parse(window.localStorage.getItem(spotifyThumbStorageKey) || \"{}\");\r\n          delete storedThumbs[spotifyId];\r\n          window.localStorage.setItem(spotifyThumbStorageKey, JSON.stringify(storedThumbs));\r\n        } catch (_) {}\r\n      }\r\n\r\n      async function getSpotifyThumbnailUrl(spotifyId) {\r\n        if (!spotifyId) return \"\";\r\n        if (spotifyThumbCache.has(spotifyId)) {\r\n          return spotifyThumbCache.get(spotifyId);\r\n        }\r\n        if (spotifyThumbRequests.has(spotifyId)) {\r\n          return spotifyThumbRequests.get(spotifyId);\r\n        }\r\n\r\n        const request = (async function () {\r\n          const sources = [\r\n            \"https:\/\/open.spotify.com\/oembed?url=\" + encodeURIComponent(\"https:\/\/open.spotify.com\/artist\/\" + spotifyId),\r\n            \"https:\/\/open.spotify.com\/oembed?url=\" + encodeURIComponent(\"spotify:artist:\" + spotifyId)\r\n          ];\r\n\r\n          for (const source of sources) {\r\n            try {\r\n              const response = await fetch(source, { credentials: \"omit\" });\r\n              if (!response.ok) continue;\r\n              const payload = await response.json();\r\n              const thumbnailUrl = payload && payload.thumbnail_url ? String(payload.thumbnail_url) : \"\";\r\n              if (thumbnailUrl) {\r\n                spotifyThumbCache.set(spotifyId, thumbnailUrl);\r\n                persistSpotifyThumbnailUrl(spotifyId, thumbnailUrl);\r\n                return thumbnailUrl;\r\n              }\r\n            } catch (_) {}\r\n          }\r\n\r\n          return \"\";\r\n        })().finally(function () {\r\n          spotifyThumbRequests.delete(spotifyId);\r\n        });\r\n\r\n        spotifyThumbRequests.set(spotifyId, request);\r\n        return request;\r\n      }\r\n\r\n      function buildArtistCover(artist) {\r\n        const cover = document.createElement(\"div\");\r\n        cover.className = \"guess-cover\";\r\n\r\n        const fallback = document.createElement(\"span\");\r\n        fallback.className = \"guess-cover-fallback\";\r\n        fallback.textContent = getArtistInitials(artist.name);\r\n        cover.appendChild(fallback);\r\n\r\n        if (artist.spotifyId) {\r\n          getSpotifyThumbnailUrl(artist.spotifyId).then((thumbnailUrl) => {\r\n            if (!thumbnailUrl) return;\r\n            const image = document.createElement(\"img\");\r\n            image.alt = artist.name;\r\n            image.loading = \"eager\";\r\n            image.decoding = \"async\";\r\n            image.referrerPolicy = \"no-referrer\";\r\n\r\n            function applyThumbnail() {\r\n              cover.replaceChildren(image);\r\n            }\r\n\r\n            function handleThumbnailError() {\r\n              clearSpotifyThumbnailUrl(artist.spotifyId);\r\n            }\r\n\r\n            image.addEventListener(\"error\", handleThumbnailError, { once: true });\r\n            image.addEventListener(\"load\", applyThumbnail, { once: true });\r\n            image.src = thumbnailUrl;\r\n\r\n            if (image.complete) {\r\n              if (image.naturalWidth > 0) {\r\n                applyThumbnail();\r\n              } else {\r\n                handleThumbnailError();\r\n              }\r\n            }\r\n          });\r\n        }\r\n\r\n        return cover;\r\n      }\r\n\r\n      function renderModeCopy() {\r\n        const config = modeConfig[app.mode];\r\n        elements.input.placeholder = config.inputPlaceholder;\r\n        elements.submitButton.textContent = config.submitLabel;\r\n      }\r\n\r\n      function renderAttemptsCard() {\r\n        const state = getActiveState();\r\n        const attemptsLeft = Math.max(0, state.maxAttempts - state.attempts);\r\n        elements.attemptsCard.textContent = String(attemptsLeft) + \" \" + (attemptsLeft === 1 ? \"TENTATIVO\" : \"TENTATIVI\");\r\n      }\r\n\r\n      function renderActionButton() {\r\n        if (app.mode === \"classic\") {\r\n          elements.modeActionButton.classList.add(\"hidden\");\r\n          elements.dailyStreakCard.classList.remove(\"hidden\");\r\n          loadClassicStreakStatus();\r\n          return;\r\n        }\r\n\r\n        const config = modeConfig[app.mode];\r\n        elements.dailyStreakCard.classList.add(\"hidden\");\r\n        elements.modeActionButton.classList.remove(\"hidden\");\r\n        elements.modeActionButton.textContent = config.actionLabel;\r\n        elements.modeActionButton.disabled = false;\r\n      }\r\n\r\n      function renderTabs() {\r\n        elements.tabs.forEach((tab) => {\r\n          tab.classList.toggle(\"is-active\", tab.dataset.mode === app.mode);\r\n        });\r\n      }\r\n\r\n      function renderRankedToggle() {\r\n        if (!elements.rankedModeButton) return;\r\n        elements.rankedModeButton.textContent = \"Classificata\";\r\n        elements.rankedModeButton.classList.toggle(\"is-active\", isRankedMode());\r\n      }\r\n\r\n      function renderBranding() {\r\n        if (!elements.topLogo) return;\r\n\r\n        const rankedActive = isRankedMode();\r\n        const nextSrc = rankedActive ? RANKED_LOGO_URL : CLASSIC_LOGO_URL;\r\n        const nextAlt = rankedActive ? \"Bulldogle Ranked\" : \"Bulldogle Classico\";\r\n\r\n        if (elements.topLogo.getAttribute(\"src\") !== nextSrc) {\r\n          elements.topLogo.setAttribute(\"src\", nextSrc);\r\n        }\r\n\r\n        elements.topLogo.setAttribute(\"alt\", nextAlt);\r\n        appRoot.classList.toggle(\"is-ranked-mode\", rankedActive);\r\n        document.body.classList.toggle(\"bulldogle-ranked-mode-active\", rankedActive);\r\n        document.documentElement.classList.toggle(\"bulldogle-ranked-mode-active\", rankedActive);\r\n      }\r\n\r\n      function renderPanels() {\r\n        const rankedActive = isRankedMode();\r\n        elements.standardGamePanel.classList.toggle(\"hidden\", rankedActive);\r\n        elements.mobileRankedGamePanel.classList.toggle(\"hidden\", !rankedActive);\r\n        syncHelpPanelPlacement();\r\n      }\r\n\r\n      function buildSpotifyEmbed(spotifyId) {\r\n        if (!spotifyId) return null;\r\n        const wrap = document.createElement(\"div\");\r\n        wrap.className = \"guess-spotify\";\r\n        const iframe = document.createElement(\"iframe\");\r\n        iframe.src = \"https:\/\/open.spotify.com\/embed\/artist\/\" + spotifyId + \"?utm_source=generator&theme=0\";\r\n        iframe.allow = \"autoplay; clipboard-write; encrypted-media; fullscreen; picture-in-picture\";\r\n        iframe.loading = \"lazy\";\r\n        wrap.appendChild(iframe);\r\n        return wrap;\r\n      }\r\n\r\n      function buildArtistTip(tip) {\r\n        const cleanTip = String(tip || \"\").trim();\r\n        if (!cleanTip) return null;\r\n\r\n        const copy = document.createElement(\"p\");\r\n        copy.className = \"guess-tip\";\r\n        copy.textContent = cleanTip;\r\n        return copy;\r\n      }\r\n\r\n      function buildResultCard(result) {\r\n        const article = document.createElement(\"article\");\r\n        article.className = \"guess-card\";\r\n        if (result.solved) article.classList.add(\"is-solved\");\r\n        if (result.kind === \"answer\") article.classList.add(\"is-answer\");\r\n        if (result.kind === \"auto\") article.classList.add(\"is-hint\");\r\n\r\n        const top = document.createElement(\"div\");\r\n        top.className = \"guess-top\";\r\n\r\n        const cover = buildArtistCover(result.guessArtist);\r\n        const copy = document.createElement(\"div\");\r\n        copy.className = \"guess-copy\";\r\n\r\n        const badge = document.createElement(\"span\");\r\n        badge.className = \"guess-badge\";\r\n        badge.textContent = result.label;\r\n\r\n        const name = document.createElement(\"h4\");\r\n        name.className = \"guess-name\";\r\n        name.textContent = result.guessArtist.name;\r\n\r\n        copy.appendChild(badge);\r\n        copy.appendChild(name);\r\n\r\n        if (result.subcopy) {\r\n          const sub = document.createElement(\"p\");\r\n          sub.className = \"guess-sub\";\r\n          sub.textContent = result.subcopy;\r\n          copy.appendChild(sub);\r\n        }\r\n\r\n        top.appendChild(cover);\r\n        top.appendChild(copy);\r\n\r\n        const traits = document.createElement(\"div\");\r\n        traits.className = \"traits\";\r\n\r\n        result.traits.forEach((trait) => {\r\n          const traitNode = document.createElement(\"div\");\r\n          traitNode.className = \"trait is-\" + trait.status;\r\n\r\n          const label = document.createElement(\"span\");\r\n          label.className = \"trait-label\";\r\n          label.textContent = trait.label;\r\n\r\n        const value = document.createElement(\"span\");\r\n        value.className = \"trait-value\";\r\n        const valueText = document.createElement(\"span\");\r\n        valueText.className = \"trait-value-text\";\r\n        valueText.textContent = trait.value;\r\n        value.appendChild(valueText);\r\n\r\n        if (trait.arrow) {\r\n          const arrow = document.createElement(\"span\");\r\n          arrow.className = \"trait-arrow\";\r\n          arrow.textContent = trait.arrow;\r\n          value.appendChild(arrow);\r\n        }\r\n\r\n        if (trait.suffix) {\r\n          const suffix = document.createElement(\"span\");\r\n          suffix.className = \"trait-suffix\";\r\n          suffix.textContent = trait.suffix;\r\n          value.appendChild(suffix);\r\n        }\r\n\r\n        traitNode.appendChild(label);\r\n        traitNode.appendChild(value);\r\n        traits.appendChild(traitNode);\r\n      });\r\n\r\n        article.appendChild(top);\r\n        article.appendChild(traits);\r\n        const spotifyEmbed = buildSpotifyEmbed(result.spotifyId);\r\n        if (spotifyEmbed) {\r\n          article.appendChild(spotifyEmbed);\r\n        }\r\n        if (result.solved && result.tip) {\r\n          const tipNode = buildArtistTip(result.tip);\r\n          if (tipNode) {\r\n            article.appendChild(tipNode);\r\n          }\r\n        }\r\n        return article;\r\n      }\r\n\r\n      function renderResults() {\r\n        const state = getActiveState();\r\n        const results = state.results || [];\r\n        elements.resultsList.innerHTML = \"\";\r\n\r\n        if (!results.length) {\r\n          const empty = document.createElement(\"div\");\r\n          empty.className = \"empty-state\";\r\n          empty.textContent = \"Nessun tentativo ancora.\";\r\n          elements.resultsList.appendChild(empty);\r\n          return;\r\n        }\r\n\r\n        results.forEach((result) => {\r\n          elements.resultsList.appendChild(buildResultCard(result));\r\n        });\r\n      }\r\n\r\n      function renderInputState() {\r\n        const state = getActiveState();\r\n        disableGameInput(state.complete);\r\n        elements.inputLabel.textContent = \"inserisci un artista\";\r\n        elements.input.placeholder = app.mode === \"classic\" && state.complete ? \"Torna domani!\" : \"inserisci un artista\";\r\n      }\r\n\r\n      function renderApp() {\r\n        renderBranding();\r\n        renderTabs();\r\n        renderRankedToggle();\r\n        renderPanels();\r\n\r\n        if (isRankedMode()) {\r\n          renderRankedPanel();\r\n          hideSuggestions();\r\n          syncHelpToggleState();\r\n          return;\r\n        }\r\n\r\n        renderModeCopy();\r\n        renderAttemptsCard();\r\n        renderActionButton();\r\n        renderInputState();\r\n        renderResults();\r\n        hideSuggestions();\r\n        hideRankedSuggestions();\r\n        syncHelpToggleState();\r\n      }\r\n\r\n      function formatTime(totalSeconds) {\r\n        const safeTime = Math.max(0, totalSeconds);\r\n        const minutes = Math.floor(safeTime \/ 60);\r\n        const seconds = String(safeTime % 60).padStart(2, \"0\");\r\n        return minutes + \":\" + seconds;\r\n      }\r\n\r\n      function findArtistByName(name) {\r\n        const normalized = normalize(name);\r\n        return artists.find((artist) => normalize(artist.name) === normalized);\r\n      }\r\n\r\n      function buildSuggestionList(matches) {\r\n        elements.suggestions.innerHTML = \"\";\r\n        matches.forEach((artist) => {\r\n          const button = document.createElement(\"button\");\r\n          button.type = \"button\";\r\n          button.className = \"suggestion\";\r\n\r\n          const left = document.createElement(\"span\");\r\n          left.textContent = artist.name;\r\n          const right = document.createElement(\"small\");\r\n          right.textContent = artist.city + \" \/ \" + formatPopularityDisplay(artist);\r\n\r\n          button.appendChild(left);\r\n          button.appendChild(right);\r\n          button.addEventListener(\"click\", function () {\r\n            elements.input.value = artist.name;\r\n            hideSuggestions();\r\n            elements.input.focus();\r\n          });\r\n          elements.suggestions.appendChild(button);\r\n        });\r\n        if (matches.length) {\r\n          showSuggestions();\r\n          return;\r\n        }\r\n        hideSuggestions();\r\n      }\r\n\r\n      function updateSuggestions() {\r\n        const value = normalize(elements.input.value);\r\n        if (!value) {\r\n          hideSuggestions();\r\n          return;\r\n        }\r\n\r\n        if (getActiveState().complete) {\r\n          hideSuggestions();\r\n          return;\r\n        }\r\n\r\n        const guessedIds = getModeGuessedIds();\r\n        const matches = artists.filter((artist) => {\r\n          return normalize(artist.name).includes(value) && !guessedIds.has(artist.id);\r\n        }).slice(0, 8);\r\n\r\n        buildSuggestionList(matches);\r\n      }\r\n\r\n      function addClassicGuess(guessArtist, modeKey) {\r\n        const state = app.modes[modeKey];\r\n        const targetArtist = state.target;\r\n        const attemptNumber = state.attempts + 1;\r\n        const isSolved = guessArtist.id === targetArtist.id;\r\n\r\n        state.guessedIds.add(guessArtist.id);\r\n        state.attempts += 1;\r\n        state.results.unshift(buildResultEntry(guessArtist, targetArtist, {\r\n          label: \"Tentativo \" + attemptNumber,\r\n          spotifyId: isSolved ? targetArtist.spotifyId : \"\"\r\n        }));\r\n\r\n        if (isSolved) {\r\n          state.complete = true;\r\n          setMessage(\"Hai indovinato \" + targetArtist.name + \".\", \"success\");\r\n          if (modeKey === \"classic\") {\r\n            saveClassicState(\"won\");\r\n            syncClassicStreakResult(\"won\");\r\n          }\r\n        } else if (state.attempts >= state.maxAttempts) {\r\n          state.complete = true;\r\n          state.results.unshift(buildResultEntry(targetArtist, targetArtist, {\r\n            kind: \"answer\",\r\n            label: \"Artista corretto\",\r\n            spotifyId: targetArtist.spotifyId || \"\"\r\n          }));\r\n          setMessage(\"Tentativi finiti. L'artista era \" + targetArtist.name + \".\", \"error-final\");\r\n          if (modeKey === \"classic\") {\r\n            saveClassicState(\"lost\");\r\n            syncClassicStreakResult(\"lost\");\r\n          }\r\n        } else {\r\n          setMessage(\"\", \"\");\r\n          if (modeKey === \"classic\") {\r\n            saveClassicState(\"playing\");\r\n          }\r\n        }\r\n      }\r\n\r\n      function submitClassicGuess(modeKey) {\r\n        const state = app.modes[modeKey];\r\n        if (state.complete) return;\r\n\r\n        const guessArtist = findArtistByName(elements.input.value.trim());\r\n        if (!guessArtist) {\r\n          setMessage(\"Artista non trovato nella lista.\", \"error\");\r\n          return;\r\n        }\r\n\r\n        if (state.guessedIds.has(guessArtist.id)) {\r\n          setMessage(\"Hai gia provato questo artista.\", \"error\");\r\n          elements.input.value = \"\";\r\n          return;\r\n        }\r\n\r\n        addClassicGuess(guessArtist, modeKey);\r\n        elements.input.value = \"\";\r\n      }\r\n\r\n      function startPracticeRound() {\r\n        const currentRound = app.modes.practice.round + 1;\r\n        app.modes.practice = {\r\n          maxAttempts: 10,\r\n          attempts: 0,\r\n          round: currentRound,\r\n          guessedIds: new Set(),\r\n          results: [],\r\n          complete: false,\r\n          target: pickRandomArtist()\r\n        };\r\n        if (app.mode === \"practice\") {\r\n          setMessage(\"\", \"\");\r\n          renderApp();\r\n        }\r\n      }\r\n\r\n      function switchMode(nextMode) {\r\n        if (nextMode === app.mode) return;\r\n        const previousMode = app.mode;\r\n\r\n        if (previousMode !== \"ranked\") {\r\n          app.lastStandardMode = previousMode;\r\n        }\r\n\r\n        if (previousMode === \"ranked\" && nextMode !== \"ranked\") {\r\n          resetRankedState();\r\n        }\r\n\r\n        app.mode = nextMode;\r\n\r\n        if (nextMode !== \"ranked\") {\r\n          app.lastStandardMode = nextMode;\r\n        }\r\n\r\n        elements.input.value = \"\";\r\n        elements.mobileRankedInput.value = \"\";\r\n        hideSuggestions();\r\n        hideRankedSuggestions();\r\n        closeAllHelpPanels();\r\n        setMessage(\"\", \"\");\r\n        setRankedMessage(\"\", \"\");\r\n        renderApp();\r\n      }\r\n\r\n      elements.tabs.forEach((tab) => {\r\n        tab.addEventListener(\"click\", function () {\r\n          switchMode(tab.dataset.mode);\r\n        });\r\n      });\r\n\r\n      if (elements.rankedModeButton) {\r\n        elements.rankedModeButton.addEventListener(\"click\", function () {\r\n          switchMode(\"ranked\");\r\n        });\r\n      }\r\n\r\n      elements.helpToggle.addEventListener(\"click\", function () {\r\n        const panel = getCurrentHelpPanel();\r\n        if (!panel) return;\r\n\r\n        const shouldOpen = !panel.classList.contains(\"is-open\");\r\n        closeAllHelpPanels();\r\n\r\n        if (shouldOpen) {\r\n          panel.classList.add(\"is-open\");\r\n          panel.setAttribute(\"aria-hidden\", \"false\");\r\n        }\r\n\r\n        syncHelpToggleState();\r\n      });\r\n\r\n      elements.dailyStreakCard.addEventListener(\"click\", function (event) {\r\n        if (elements.dailyStreakCard.classList.contains(\"is-guest\")) {\r\n          event.preventDefault();\r\n          window.location.href = elements.dailyStreakCard.getAttribute(\"href\") || guestStreakLoginUrl;\r\n          return;\r\n        }\r\n\r\n        if (!elements.dailyStreakCard.classList.contains(\"is-guest\")) {\r\n          event.preventDefault();\r\n          event.stopPropagation();\r\n        }\r\n      });\r\n\r\n      elements.modeActionButton.addEventListener(\"click\", function () {\r\n        if (app.mode === \"practice\") {\r\n          startPracticeRound();\r\n        }\r\n      });\r\n\r\n      elements.guessForm.addEventListener(\"submit\", function (event) {\r\n        event.preventDefault();\r\n\r\n        if (app.mode === \"classic\") {\r\n          submitClassicGuess(\"classic\");\r\n        } else {\r\n          submitClassicGuess(\"practice\");\r\n        }\r\n\r\n        renderApp();\r\n      });\r\n\r\n      elements.mobileRankedSideActionButton.addEventListener(\"click\", function () {\r\n        handleRankedSideAction();\r\n      });\r\n\r\n      elements.mobileRankedGuessForm.addEventListener(\"submit\", function (event) {\r\n        event.preventDefault();\r\n        submitRankedGuess();\r\n        renderRankedPanel();\r\n      });\r\n\r\n      elements.input.addEventListener(\"input\", updateSuggestions);\r\n      elements.input.addEventListener(\"focus\", updateSuggestions);\r\n      elements.mobileRankedInput.addEventListener(\"input\", updateRankedSuggestions);\r\n      elements.mobileRankedInput.addEventListener(\"focus\", updateRankedSuggestions);\r\n\r\n      document.addEventListener(\"click\", function (event) {\r\n        if (!elements.suggestions.contains(event.target) && event.target !== elements.input) {\r\n          hideSuggestions();\r\n        }\r\n\r\n        if (!elements.mobileRankedSuggestions.contains(event.target) && event.target !== elements.mobileRankedInput) {\r\n          hideRankedSuggestions();\r\n        }\r\n      });\r\n\r\n      window.addEventListener(\"resize\", function () {\r\n        syncHelpPanelPlacement();\r\n        if (elements.suggestions.style.display === \"block\") {\r\n          positionSuggestions();\r\n        }\r\n        if (elements.mobileRankedSuggestions.style.display === \"block\") {\r\n          positionSuggestionsFor(elements.mobileRankedInput, elements.mobileRankedSuggestions);\r\n        }\r\n      });\r\n\r\n      window.addEventListener(\"scroll\", function () {\r\n        if (elements.suggestions.style.display === \"block\") {\r\n          positionSuggestions();\r\n        }\r\n        if (elements.mobileRankedSuggestions.style.display === \"block\") {\r\n          positionSuggestionsFor(elements.mobileRankedInput, elements.mobileRankedSuggestions);\r\n        }\r\n      }, true);\r\n\r\n      if (window.visualViewport) {\r\n        window.visualViewport.addEventListener(\"resize\", function () {\r\n          syncHelpPanelPlacement();\r\n          if (elements.suggestions.style.display === \"block\") {\r\n            positionSuggestions();\r\n          }\r\n          if (elements.mobileRankedSuggestions.style.display === \"block\") {\r\n            positionSuggestionsFor(elements.mobileRankedInput, elements.mobileRankedSuggestions);\r\n          }\r\n        });\r\n\r\n        window.visualViewport.addEventListener(\"scroll\", function () {\r\n          if (elements.suggestions.style.display === \"block\") {\r\n            positionSuggestions();\r\n          }\r\n          if (elements.mobileRankedSuggestions.style.display === \"block\") {\r\n            positionSuggestionsFor(elements.mobileRankedInput, elements.mobileRankedSuggestions);\r\n          }\r\n        });\r\n      }\r\n\r\n      syncHelpPanelPlacement();\r\n      loadClassicState();\r\n      renderApp();\r\n      if (!app.modes.classic.complete) {\r\n        setMessage(\"\", \"\");\r\n      }\r\n    })();\r\n  <\/script>\r\n<\/body>\r\n<\/html>\r\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-6661b873 elementor-widget-divider--view-line_text elementor-widget-mobile__width-initial hide-when-ranked elementor-widget-divider--element-align-center elementor-widget elementor-widget-divider\" data-id=\"6661b873\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"divider.default\">\n\t\t\t\t\t\t\t<div class=\"elementor-divider\">\n\t\t\t<span class=\"elementor-divider-separator\">\n\t\t\t\t\t\t\t<span class=\"elementor-divider__text elementor-divider__element\">\n\t\t\t\tAltri Giochi\t\t\t\t<\/span>\n\t\t\t\t\t\t<\/span>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-1dc9aa5 hide-when-ranked elementor-widget__width-initial elementor-widget elementor-widget-post-widget\" data-id=\"1dc9aa5\" data-element_type=\"widget\" data-e-type=\"widget\" data-settings=\"{&quot;posts_per_page&quot;:100,&quot;post_type&quot;:[&quot;page&quot;],&quot;nb_columns&quot;:&quot;1&quot;,&quot;classic_layout&quot;:&quot;grid&quot;,&quot;nb_columns_tablet&quot;:&quot;3&quot;,&quot;nb_columns_mobile&quot;:&quot;1&quot;,&quot;post_status&quot;:&quot;publish&quot;,&quot;pagination&quot;:&quot;none&quot;}\" data-widget_type=\"post-widget.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<div class=\"post-container none classic\" data-total-post=\"2\" ><div class=\"post-container-inner\"><div class=\"elementor-grid\" ><article class=\"post-wrapper\"  data-post-id=\"8209\" ><div class=\"post-image\"><a href=\"https:\/\/bulldogmusik.it\/en\/bulldogmatch-ita\/\" ><img loading=\"lazy\" decoding=\"async\" width=\"1366\" height=\"768\" src=\"https:\/\/bulldogmusik.it\/wp-content\/uploads\/2026\/05\/BulldogMatch-New.png\" class=\"bpfwe-post-thumbnail\" alt=\"\" data-bpfwe-src=\"https:\/\/bulldogmusik.it\/wp-content\/uploads\/2026\/05\/BulldogMatch-New.png\" loading=\"lazy\" \/><\/a><\/div><div class=\"inner-content\"><div class=\"post-content elementor-repeater-item-0b20400\"><p>Indovina in rapper in meno di 20 tentativi, ogni tentativo scopri diverse affinit\u00e0....<\/p><\/div><\/div><\/article><article class=\"post-wrapper\"  data-post-id=\"8846\" ><div class=\"post-image\"><a href=\"https:\/\/bulldogmusik.it\/en\/bulldogfeat-ita\/\" ><img loading=\"lazy\" decoding=\"async\" width=\"1366\" height=\"768\" src=\"https:\/\/bulldogmusik.it\/wp-content\/uploads\/2026\/05\/BulldogFeat-Logo-1.png\" class=\"bpfwe-post-thumbnail\" alt=\"\" data-bpfwe-src=\"https:\/\/bulldogmusik.it\/wp-content\/uploads\/2026\/05\/BulldogFeat-Logo-1.png\" loading=\"lazy\" \/><\/a><\/div><div class=\"inner-content\"><div class=\"post-content elementor-repeater-item-0b20400\"><p>Indovina in rapper in meno di 5 tentativi, ogni tentativo scopri altre collaborazioni....<\/p><\/div><\/div><\/article><\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-6e7cde84 elementor-widget-divider--view-line_text elementor-widget-mobile__width-initial show-when-ranked elementor-widget-divider--element-align-center elementor-widget elementor-widget-divider\" data-id=\"6e7cde84\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"divider.default\">\n\t\t\t\t\t\t\t<div class=\"elementor-divider\">\n\t\t\t<span class=\"elementor-divider-separator\">\n\t\t\t\t\t\t\t<span class=\"elementor-divider__text elementor-divider__element\">\n\t\t\t\tRanked\t\t\t\t<\/span>\n\t\t\t\t\t\t<\/span>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-661a2e17 elementor-widget-mobile__width-initial show-when-ranked elementor-widget elementor-widget-html\" data-id=\"661a2e17\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t\t<div class=\"ranked-board-widget ranked-sidebar-board\" data-game-key=\"classic\">\n  <div class=\"ranked-sidebar-board-inner\">\n    <div class=\"ranked-board-controls\" aria-label=\"Seleziona mese classifica\">\n      <select class=\"ranked-board-period-select\">\n        <option value=\"\">Caricamento...<\/option>\n      <\/select>\n    <\/div>\n\n    <img decoding=\"async\" class=\"ranked-sidebar-board-heading-image\" src=\"https:\/\/bulldogmusik.it\/wp-content\/uploads\/2026\/05\/LeadBasico.png\" alt=\"Classifica\">\n\n    <div class=\"ranked-board-list\"><\/div>\n\n    <div class=\"ranked-board-pager\">\n      <button class=\"ranked-board-prev\" type=\"button\" aria-label=\"Pagina precedente\">&#8249;<\/button>\n      <span class=\"ranked-board-page\">1\/1<\/span>\n      <button class=\"ranked-board-next\" type=\"button\" aria-label=\"Pagina successiva\">&#8250;<\/button>\n    <\/div>\n\n    <div class=\"ranked-board-msg\">Caricamento classifica...<\/div>\n  <\/div>\n<\/div>\n\n<script src=\"\/bulldogle\/ranked-leaderboard.js?v=58\"><\/script>\n\n<style>\n.ranked-sidebar-board {\n  --ranked-accent: #952800;\n  --ranked-accent-2: #a83100;\n  --ranked-accent-3: #7d2100;\n  --ranked-ink: #17110d;\n  --ranked-ink-soft: rgba(23, 17, 13, 0.72);\n  --ranked-cream: #f8f0e8;\n  width: 100%;\n  max-width: 100%;\n  margin: 0;\n  font-family: Verdana, Geneva, sans-serif;\n}\n\n.ranked-sidebar-board-inner {\n  position: relative;\n  width: 100%;\n  padding: 22px 22px 20px;\n  border-radius: 34px;\n  overflow: hidden;\n  background: var(--ranked-accent);\n  box-shadow:\n    inset 0 1px 0 rgba(255, 255, 255, 0.16),\n    0 18px 34px rgba(0, 0, 0, 0.18);\n  color: var(--ranked-ink);\n  text-align: center;\n}\n\n.ranked-sidebar-board-heading-image {\n  display: block;\n  width: min(100%, 206px) !important;\n  height: auto;\n  margin: 2px auto 16px;\n}\n\n.ranked-sidebar-board .ranked-board-controls {\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  margin-bottom: 12px;\n}\n\n.ranked-sidebar-board .ranked-board-controls select {\n  width: 100% !important;\n  max-width: 182px;\n  min-width: 0;\n  height: 40px;\n  padding: 0 14px !important;\n  border: 1px solid rgba(23, 17, 13, 0.12) !important;\n  border-radius: 999px !important;\n  background: rgba(12, 8, 6, 0.9) !important;\n  color: var(--ranked-cream) !important;\n  font-family: Verdana, Geneva, sans-serif;\n  font-size: 12px !important;\n  font-weight: 700;\n  text-align: center;\n  box-shadow: none !important;\n  outline: none;\n  appearance: none;\n  -webkit-appearance: none;\n}\n\n.ranked-sidebar-board .ranked-board-list {\n  display: grid;\n  gap: 10px;\n  margin: 0;\n}\n\n.ranked-sidebar-board .ranked-board-row {\n  display: grid;\n  grid-template-columns: 66px minmax(0, 1fr) 64px;\n  align-items: center;\n  gap: 8px;\n  min-height: 52px;\n  padding: 10px 14px;\n  border: 0;\n  border-radius: 18px;\n  background: #000000;\n  color: var(--ranked-cream);\n  text-align: center;\n}\n\n.ranked-sidebar-board .ranked-board-row:first-child {\n  background: #000000;\n}\n\n.ranked-sidebar-board .ranked-board-rank {\n  color: #ffffff;\n  font-size: 13px;\n  font-weight: 700;\n}\n\n.ranked-sidebar-board .ranked-board-name {\n  min-width: 0;\n  overflow: hidden;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  color: #ffffff;\n  font-size: 13px;\n  font-weight: 700;\n}\n\n.ranked-sidebar-board .ranked-board-score {\n  color: #ffffff;\n  font-size: 13px;\n  font-weight: 700;\n}\n\n.ranked-sidebar-board .ranked-board-pager {\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  gap: 12px;\n  margin-top: 14px;\n}\n\n.ranked-sidebar-board .ranked-board-pager button {\n  appearance: none !important;\n  display: inline-flex !important;\n  align-items: center !important;\n  justify-content: center !important;\n  width: 36px !important;\n  min-width: 36px !important;\n  height: 36px !important;\n  min-height: 36px !important;\n  padding: 0 !important;\n  margin: 0 !important;\n  border: 1px solid rgba(23, 17, 13, 0.12) !important;\n  border-radius: 999px !important;\n  background: #000000 !important;\n  color: #ffffff !important;\n  font-family: Verdana, Geneva, sans-serif !important;\n  font-size: 23px !important;\n  font-weight: 700 !important;\n  line-height: 1 !important;\n  box-shadow: none !important;\n  cursor: pointer;\n  transform: none !important;\n}\n\n.ranked-sidebar-board .ranked-board-pager button:hover {\n  background: #ffffff !important;\n  color: var(--ranked-ink) !important;\n}\n\n.ranked-sidebar-board .ranked-board-pager button:disabled {\n  opacity: 0.34;\n  cursor: not-allowed;\n}\n\n.ranked-sidebar-board .ranked-board-page {\n  color: rgba(23, 17, 13, 0.72);\n  font-size: 12px;\n  font-weight: 700;\n}\n\n.ranked-sidebar-board .ranked-board-msg {\n  min-height: 18px;\n  margin-top: 12px;\n  color: rgba(23, 17, 13, 0.72);\n  font-size: 12px;\n  line-height: 1.35;\n  font-weight: 700;\n  text-align: center;\n}\n\n@media (max-width: 767px) {\n  .ranked-sidebar-board-inner {\n    padding: 20px 18px 18px;\n    border-radius: 28px;\n  }\n\n  .ranked-sidebar-board .ranked-board-row {\n    grid-template-columns: 58px minmax(0, 1fr) 58px;\n    min-height: 48px;\n    padding: 9px 12px;\n  }\n\n  .ranked-sidebar-board-heading-image {\n    width: min(100%, 238px);\n  }\n}\n<\/style>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-7475099 e-flex e-con-boxed wcf-starter-animations-none e-con e-parent\" data-id=\"7475099\" 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-28e2fc3 elementor-widget elementor-widget-html\" data-id=\"28e2fc3\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t\t<style id=\"bulldogle-modern-font-900-override\">\n.demo-app button,\n.demo-app button *,\n.demo-app .attempts-card,\n.demo-app .attempts-card *,\n.demo-app .classic-attempts-badge,\n.demo-app .classic-attempts-badge *,\n.demo-app .classic-streak-badge,\n.demo-app .classic-streak-badge *,\n.demo-app .streak-card,\n.demo-app .streak-card *,\n.ranked-demo-app button,\n.ranked-demo-app button *,\n.ranked-demo-app .attempts-card,\n.ranked-demo-app .attempts-card *,\n.ranked-demo-app .classic-attempts-badge,\n.ranked-demo-app .classic-attempts-badge *,\n.ranked-demo-app .classic-streak-badge,\n.ranked-demo-app .classic-streak-badge *,\n.ranked-demo-app .streak-card,\n.ranked-demo-app .streak-card *,\n.demo-app .guess-name,\n.demo-app .guess-name *,\n.demo-app .artist-name,\n.demo-app .artist-name *,\n.demo-app .result-name,\n.demo-app .result-name *,\n.demo-app .board-row .name,\n.demo-app .board-row .name *,\n.ranked-demo-app .guess-name,\n.ranked-demo-app .guess-name *,\n.ranked-demo-app .artist-name,\n.ranked-demo-app .artist-name *,\n.ranked-demo-app .result-name,\n.ranked-demo-app .result-name *,\n.ranked-demo-app .board-row .name,\n.ranked-demo-app .board-row .name * {\n  font-family: Verdana, Geneva, sans-serif !important;\n  font-weight: 900 !important;\n  -webkit-text-stroke: 0.18px currentColor;\n  text-shadow: 0.18px 0 currentColor;\n}\n\n.demo-app .controls-inner .tab,\n.demo-app .controls-inner .ghost-button {\n  min-height: 56px !important;\n  height: 56px !important;\n  padding: 0 22px !important;\n  border-radius: 12px !important;\n  font-size: 15px !important;\n  line-height: 1.1 !important;\n  text-transform: uppercase !important;\n}\n\n.ranked-demo-app .meta-card,\n.ranked-demo-app .ranked-meta-button {\n  min-height: 74px !important;\n  height: 74px !important;\n  padding: 12px 14px !important;\n  border-radius: 16px !important;\n  font-size: 15px !important;\n  line-height: 1.1 !important;\n  text-transform: uppercase !important;\n}\n\n.ranked-demo-app .meta-label,\n.ranked-demo-app .meta-value {\n  line-height: 1.1 !important;\n}\n\n@media (max-width: 720px) {\n  .demo-app .top-logo,\n  .ranked-demo-app .top-logo {\n    margin-top: 14px !important;\n  }\n\n  .demo-app .controls-inner,\n  .ranked-demo-app .controls-inner {\n    margin-bottom: 18px !important;\n  }\n}\n\n<\/style>\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>Indovina il rapper in meno di 10 tentativi, ogni tentativo scopri nuove informazioni Giornaliera Classificata Bulldogle Demo DAILY ALLENAMENTO CLASSIFICATA COME SI GIOCA Colori \ud83d\udfe2 = corretto. \ud83d\udfe1 = vicino. \u26aa = errato. Citta \ud83d\udfe1 se sei nella stessa regione. Se sbagli, la freccia ti dice dove cercare. Estero \ud83c\udf0d significa che l&#8217;artista corretto \u00e8 [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":15033,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"elementor_header_footer","meta":{"_eb_attr":"","footnotes":""},"categories":[35,1],"tags":[],"class_list":["post-7057","page","type-page","status-publish","has-post-thumbnail","hentry","category-min","category-senza-categoria"],"blocksy_meta":{"styles_descriptor":{"styles":{"desktop":"","tablet":"","mobile":""},"google_fonts":[],"version":8}},"_links":{"self":[{"href":"https:\/\/bulldogmusik.it\/en\/wp-json\/wp\/v2\/pages\/7057","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/bulldogmusik.it\/en\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/bulldogmusik.it\/en\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/bulldogmusik.it\/en\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/bulldogmusik.it\/en\/wp-json\/wp\/v2\/comments?post=7057"}],"version-history":[{"count":20,"href":"https:\/\/bulldogmusik.it\/en\/wp-json\/wp\/v2\/pages\/7057\/revisions"}],"predecessor-version":[{"id":15621,"href":"https:\/\/bulldogmusik.it\/en\/wp-json\/wp\/v2\/pages\/7057\/revisions\/15621"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/bulldogmusik.it\/en\/wp-json\/wp\/v2\/media\/15033"}],"wp:attachment":[{"href":"https:\/\/bulldogmusik.it\/en\/wp-json\/wp\/v2\/media?parent=7057"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/bulldogmusik.it\/en\/wp-json\/wp\/v2\/categories?post=7057"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/bulldogmusik.it\/en\/wp-json\/wp\/v2\/tags?post=7057"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}