GitHub GitFut

GitHubプロフィールとアバターホバーカードにGitFut情報を表示

2026/07/16のページです。最新版はこちら

スクリプトをインストールするには、Tampermonkey, GreasemonkeyViolentmonkey のような拡張機能のインストールが必要です。

You will need to install an extension such as Tampermonkey to install this script.

スクリプトをインストールするには、TampermonkeyViolentmonkey のような拡張機能のインストールが必要です。

スクリプトをインストールするには、TampermonkeyUserscripts のような拡張機能のインストールが必要です。

このスクリプトをインストールするには、Tampermonkeyなどの拡張機能をインストールする必要があります。

このスクリプトをインストールするには、ユーザースクリプト管理ツールの拡張機能をインストールする必要があります。

(ユーザースクリプト管理ツールは設定済みなのでインストール!)

このスタイルをインストールするには、Stylusなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus などの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus tなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

(ユーザースタイル管理ツールは設定済みなのでインストール!)

作者のサイトでサポートを受ける。または、このスクリプトの質問や評価の投稿はこちら通報はこちらへお寄せください
// ==UserScript==
// @name              GitHub GitFut
// @name:ru           GitHub GitFut
// @name:zh-CN        GitHub GitFut
// @name:es           GitHub GitFut
// @name:pt-BR        GitHub GitFut
// @name:de           GitHub GitFut
// @name:fr           GitHub GitFut
// @name:ja           GitHub GitFut
// @name:ko           GitHub GitFut
// @name:pl           GitHub GitFut
// @namespace         https://github.com/NemoKing1210/github-gitfut
// @version           1.9.0
// @description       Adds GitFut scouting cards on GitHub profiles and avatar hovercards
// @description:ru    Добавляет карточки GitFut на профили GitHub и в поповеры аватаров
// @description:zh-CN 在 GitHub 个人资料页与头像悬停卡片中显示 GitFut 球探信息
// @description:es    Añade cartas GitFut en perfiles y hovercards de avatar de GitHub
// @description:pt-BR  Adiciona cartas GitFut nos perfis e hovercards de avatar do GitHub
// @description:de     Zeigt GitFut-Karten auf GitHub-Profilen und Avatar-Hovercards
// @description:fr     Ajoute les cartes GitFut sur les profils et hovercards d’avatar GitHub
// @description:ja     GitHubプロフィールとアバターホバーカードにGitFut情報を表示
// @description:ko     GitHub 프로필과 아바타 호버카드에 GitFut 스카우트 정보를 표시
// @description:pl     Dodaje karty GitFut na profilach i hovercardach awatarów GitHub
// @author             NemoKing1210
// @tag                github
// @tag                gitfut
// @homepageURL        https://github.com/NemoKing1210/github-gitfut
// @supportURL         https://github.com/NemoKing1210/github-gitfut/issues
// @license            MIT
// @icon               https://gitfut.com/favicon.ico
// @match              https://github.com/*
// @match              https://gist.github.com/*
// @grant              GM_xmlhttpRequest
// @grant              GM_getValue
// @grant              GM_setValue
// @grant              GM_addStyle
// @grant              GM_registerMenuCommand
// @connect            gitfut.com
// @run-at             document-idle
// @noframes
// ==/UserScript==

(function () {
  'use strict';

  const API_BASE = 'https://gitfut.com/api/card';
  const SITE_BASE = 'https://gitfut.com';
  const REPO_URL = 'https://github.com/NemoKing1210/github-gitfut';
  const CACHE_KEY = 'gf_github_cache_v1';
  const SETTINGS_KEY = 'gf_github_settings';
  /** Soft budget for cache progress UI (GM storage itself may allow more). */
  const CACHE_BUDGET_BYTES = 5 * 1024 * 1024;
  /** Fallback if GM_info is unavailable — keep in sync with @version. */
  const SCRIPT_VERSION =
    (typeof GM_info !== 'undefined' && GM_info?.script?.version) || '1.9.0';
  const CACHE_HOURS_MAX = 168;
  const DEFAULT_SETTINGS = {
    cacheHours: 12,
    showHovercard: true,
    cardTheme: 'standard',
    locale: 'auto',
  };
  const CARD_THEMES = ['standard', 'github', 'fifa', 'neon'];
  const MAX_CONCURRENT = 2;
  const REQUEST_DELAY_MS = 100;
  const CACHE_PERSIST_MS = 1000;
  const SCAN_DEBOUNCE_MS = 400;
  const PANEL_ID = 'gf-profile-panel';
  const HOVERCARD_BLOCK_ID = 'gf-hovercard-block';

  const RESERVED_PATHS = new Set([
    'about', 'account', 'actions', 'apps', 'blog', 'cache', 'codespaces', 'collections',
    'contact', 'copilot', 'customer', 'dashboard', 'developer', 'discussions', 'docs',
    'education', 'enterprise', 'events', 'explore', 'features', 'files', 'funding',
    'gist', 'home', 'issues', 'join', 'login', 'logout', 'marketplace', 'mcp',
    'new', 'notifications', 'organizations', 'orgs', 'packages', 'pages', 'pricing',
    'pulls', 'readme', 'search', 'security', 'sessions', 'settings', 'site', 'sponsors',
    'stars', 'topics', 'trending', 'users', 'watching', 'workflows',
  ]);

  const FINISH_COLORS = {
    bronze: {
      accent: '#CD7F32',
      ink: '#2A1A0C',
      soft: 'rgba(205,127,50,0.16)',
      glow: 'rgba(205,127,50,0.28)',
      deep: '#5a3412',
      shine: 'rgba(255,198,120,0.45)',
      tier: 1,
    },
    silver: {
      accent: '#AAB2BD',
      ink: '#1F242B',
      soft: 'rgba(170,178,189,0.2)',
      glow: 'rgba(180,190,205,0.4)',
      deep: '#3a4250',
      shine: 'rgba(255,255,255,0.55)',
      tier: 2,
    },
    gold: {
      accent: '#E6B422',
      ink: '#3A2806',
      soft: 'rgba(230,180,34,0.22)',
      glow: 'rgba(230,180,34,0.55)',
      deep: '#7a5608',
      shine: 'rgba(255,236,160,0.7)',
      tier: 3,
    },
    totw: {
      accent: '#E03E52',
      ink: '#4A0A14',
      soft: 'rgba(224,62,82,0.2)',
      glow: 'rgba(224,62,82,0.55)',
      deep: '#6a1020',
      shine: 'rgba(255,140,160,0.65)',
      tier: 4,
    },
    toty: {
      accent: '#3B7AFF',
      ink: '#10254F',
      soft: 'rgba(59,122,255,0.22)',
      glow: 'rgba(59,122,255,0.6)',
      deep: '#0a1f5c',
      shine: 'rgba(160,200,255,0.75)',
      tier: 5,
    },
    icon: {
      accent: '#F3D688',
      ink: '#2A1A45',
      soft: 'rgba(243,214,136,0.24)',
      glow: 'rgba(180,120,255,0.55)',
      deep: '#3a1a70',
      shine: 'rgba(255,240,200,0.85)',
      tier: 6,
    },
    founder: {
      accent: '#FF5A7A',
      ink: '#3A0A18',
      soft: 'rgba(255,90,122,0.22)',
      glow: 'rgba(255,90,122,0.6)',
      deep: '#5a1028',
      shine: 'rgba(255,180,200,0.8)',
      tier: 7,
    },
  };
  const FINISH_KEYS = Object.keys(FINISH_COLORS);
  const FINISH_CLASS_RE = /^gf-(?:hc|panel)-finish--/;

  const STAT_ORDER = [
    ['pac', 'PAC'],
    ['sho', 'SHO'],
    ['pas', 'PAS'],
    ['dri', 'DRI'],
    ['def', 'DEF'],
    ['phy', 'PHY'],
  ];

  const SUPPORTED_LOCALES = ['en', 'ru', 'zh', 'es', 'pt', 'de', 'fr', 'ja', 'ko', 'pl'];

  /** Native labels for the language picker (not translated per UI locale). */
  const LOCALE_NATIVE_NAMES = {
    en: 'English',
    ru: 'Русский',
    zh: '中文',
    es: 'Español',
    pt: 'Português',
    de: 'Deutsch',
    fr: 'Français',
    ja: '日本語',
    ko: '한국어',
    pl: 'Polski',
  };

  const TRANSLATIONS = {
    en: {
      loading: 'Scouting…',
      loadError: 'Scout failed',
      notFound: 'Not scouted',
      overall: 'OVR',
      position: 'POS',
      finish: 'Finish',
      archetype: 'Archetype',
      language: 'Language',
      playstyles: 'Playstyles',
      metrics: 'Scouting metrics',
      openReport: 'Open full scout report',
      duel: 'Duel a rival',
      menuSettings: 'GitHub GitFut — Settings',
      navMenuItem: 'GitFut settings',
      panelTitle: 'GitFut',
      panelSubtitle: 'Scouting · cache · display',
      close: 'Close',
      cancel: 'Cancel',
      save: 'Save',
      saveReload: 'Save & Reload page',
      sectionDisplay: 'Display',
      uiLanguage: 'Language',
      uiLanguageHint: 'Language for GitFut panels, hovercards, and settings. Auto follows the browser.',
      uiLanguageAuto: 'Auto (browser)',
      sectionCache: 'Cache',
      showHovercard: 'Show GitFut in avatar hovercards',
      showHovercardHint: 'Injects OVR, position, and stats into GitHub’s user popover on avatar hover.',
      cardTheme: 'Card style',
      cardThemeHint: 'Standard, GitHub (subtle Primer look), FIFA (metallic), or Neon (glow).',
      cardThemeStandard: 'Standard',
      cardThemeGithub: 'GitHub',
      cardThemeFifa: 'FIFA',
      cardThemeNeon: 'Neon',
      on: 'ON',
      off: 'OFF',
      cacheHours: 'Cache duration (hours)',
      cacheHoursHint: 'How long to reuse GitFut API results. 0 disables cache.',
      clearCache: 'Clear cache',
      cacheCleared: 'Cache cleared ({count})',
      cacheEmpty: 'Cache is empty',
      cacheClearHint: 'Removes all stored GitFut lookups from this browser profile.',
      version: 'Version {version}',
      cacheCards: '{count} cards cached',
      cacheStorage: '{used} used · {free} free',
      cacheStorageHint: 'Local card-cache size vs a soft {budget} budget.',
      repoLink: 'GitHub',
      repoAbout: 'Source code, updates, and issue reports',
      skillMoves: 'Skill moves',
      weakFoot: 'Weak foot',
      workRate: 'Work rate',
      style: 'Style',
    },
    ru: {
      loading: 'Скаутинг…',
      loadError: 'Ошибка скаутинга',
      notFound: 'Нет карточки',
      overall: 'OVR',
      position: 'ПОЗ',
      finish: 'Тир',
      archetype: 'Архетип',
      language: 'Язык',
      playstyles: 'Стили',
      metrics: 'Метрики скаутинга',
      openReport: 'Открыть полный отчёт',
      duel: 'Дуэль с соперником',
      menuSettings: 'GitHub GitFut — Настройки',
      navMenuItem: 'Настройки GitFut',
      panelTitle: 'GitFut',
      panelSubtitle: 'Скаутинг · кэш · отображение',
      close: 'Закрыть',
      cancel: 'Отмена',
      save: 'Сохранить',
      saveReload: 'Сохранить и перезагрузить',
      sectionDisplay: 'Отображение',
      uiLanguage: 'Язык',
      uiLanguageHint: 'Язык панелей GitFut, hovercard и настроек. Авто — как в браузере.',
      uiLanguageAuto: 'Авто (браузер)',
      sectionCache: 'Кэш',
      showHovercard: 'GitFut в поповере аватара',
      showHovercardHint: 'Добавляет OVR, позицию и статы в нативный hovercard GitHub при наведении на аватар.',
      cardTheme: 'Оформление карточек',
      cardThemeHint: 'Стандартный, GitHub (спокойный Primer), FIFA (металл) или Неон (свечение).',
      cardThemeStandard: 'Стандартный вид',
      cardThemeGithub: 'GitHub',
      cardThemeFifa: 'FIFA',
      cardThemeNeon: 'Неон',
      on: 'ВКЛ',
      off: 'ВЫКЛ',
      cacheHours: 'Время кэша (часы)',
      cacheHoursHint: 'Как долго переиспользовать ответы API. 0 отключает кэш.',
      clearCache: 'Очистить кэш',
      cacheCleared: 'Кэш очищен ({count})',
      cacheEmpty: 'Кэш пуст',
      cacheClearHint: 'Удаляет все сохранённые запросы GitFut в этом профиле браузера.',
      version: 'Версия {version}',
      cacheCards: 'Карточек в кэше: {count}',
      cacheStorage: '{used} занято · {free} свободно',
      cacheStorageHint: 'Размер локального кэша карточек относительно лимита {budget}.',
      repoLink: 'GitHub',
      repoAbout: 'Исходники, обновления и баг-репорты',
      skillMoves: 'Финты',
      weakFoot: 'Слабая нога',
      workRate: 'Работоспособность',
      style: 'Стиль',
    },
    zh: {
      loading: '球探中…',
      loadError: '球探失败',
      notFound: '无卡片',
      overall: 'OVR',
      position: '位置',
      finish: '品质',
      archetype: '原型',
      language: '语言',
      playstyles: '风格',
      metrics: '球探指标',
      openReport: '打开完整报告',
      duel: '对决对手',
      menuSettings: 'GitHub GitFut — 设置',
      navMenuItem: 'GitFut 设置',
      panelTitle: 'GitFut',
      panelSubtitle: '球探 · 缓存 · 显示',
      close: '关闭',
      cancel: '取消',
      save: '保存',
      saveReload: '保存并刷新',
      sectionDisplay: '显示',
      uiLanguage: '语言',
      uiLanguageHint: 'GitFut 面板、悬停卡片与设置的界面语言。自动跟随浏览器。',
      uiLanguageAuto: '自动(浏览器)',
      sectionCache: '缓存',
      showHovercard: '在头像悬停卡片中显示 GitFut',
      showHovercardHint: '悬停头像时在 GitHub 用户弹层中注入 OVR、位置与属性。',
      cardTheme: '卡片样式',
      cardThemeHint: '资料页与悬停卡片球探面板的视觉风格。',
      cardThemeStandard: '标准',
      cardThemeGithub: 'GitHub',
      cardThemeFifa: 'FIFA',
      cardThemeNeon: '霓虹',
      on: '开',
      off: '关',
      cacheHours: '缓存时长(小时)',
      cacheHoursHint: '复用 API 结果的时长。0 禁用缓存。',
      clearCache: '清空缓存',
      cacheCleared: '已清空 ({count})',
      cacheEmpty: '缓存为空',
      cacheClearHint: '删除本浏览器配置中保存的 GitFut 查询。',
      version: '版本 {version}',
      cacheCards: '已缓存 {count} 张',
      cacheStorage: '已用 {used} · 剩余 {free}',
      cacheStorageHint: '本地卡片缓存相对软上限 {budget}。',
      repoLink: 'GitHub',
      repoAbout: '源码、更新与问题反馈',
      skillMoves: '花式',
      weakFoot: '逆足',
      workRate: '积极性',
      style: '风格',
    },
    es: {
      loading: 'Scouting…',
      loadError: 'Scout fallido',
      notFound: 'Sin carta',
      overall: 'OVR',
      position: 'POS',
      finish: 'Acabado',
      archetype: 'Arquetipo',
      language: 'Lenguaje',
      playstyles: 'Estilos',
      metrics: 'Métricas',
      openReport: 'Abrir informe completo',
      duel: 'Duelo',
      menuSettings: 'GitHub GitFut — Ajustes',
      navMenuItem: 'Ajustes de GitFut',
      panelTitle: 'GitFut',
      panelSubtitle: 'Scouting · caché · pantalla',
      close: 'Cerrar',
      cancel: 'Cancelar',
      save: 'Guardar',
      saveReload: 'Guardar y recargar',
      sectionDisplay: 'Pantalla',
      uiLanguage: 'Idioma',
      uiLanguageHint: 'Idioma de paneles GitFut, hovercards y ajustes. Auto sigue el navegador.',
      uiLanguageAuto: 'Auto (navegador)',
      sectionCache: 'Caché',
      showHovercard: 'Mostrar GitFut en hovercards de avatar',
      showHovercardHint: 'Inyecta OVR, posición y stats en el popover nativo de GitHub.',
      cardTheme: 'Estilo de carta',
      cardThemeHint: 'Acabado visual del panel en perfil y hovercard.',
      cardThemeStandard: 'Estándar',
      cardThemeGithub: 'GitHub',
      cardThemeFifa: 'FIFA',
      cardThemeNeon: 'Neón',
      on: 'ON',
      off: 'OFF',
      cacheHours: 'Duración de caché (horas)',
      cacheHoursHint: 'Cuánto reutilizar resultados de la API. 0 desactiva.',
      clearCache: 'Vaciar caché',
      cacheCleared: 'Caché vaciada ({count})',
      cacheEmpty: 'Caché vacía',
      cacheClearHint: 'Elimina búsquedas GitFut de este perfil.',
      version: 'Versión {version}',
      cacheCards: '{count} cartas en caché',
      cacheStorage: '{used} usados · {free} libres',
      cacheStorageHint: 'Tamaño de la caché local frente a un tope blando de {budget}.',
      repoLink: 'GitHub',
      repoAbout: 'Código, actualizaciones e issues',
      skillMoves: 'Regates',
      weakFoot: 'Pie malo',
      workRate: 'Trabajo',
      style: 'Estilo',
    },
    pt: {
      loading: 'Scouting…',
      loadError: 'Scout falhou',
      notFound: 'Sem carta',
      overall: 'OVR',
      position: 'POS',
      finish: 'Acabamento',
      archetype: 'Arquétipo',
      language: 'Linguagem',
      playstyles: 'Estilos',
      metrics: 'Métricas',
      openReport: 'Abrir relatório completo',
      duel: 'Duelo',
      menuSettings: 'GitHub GitFut — Configurações',
      navMenuItem: 'Configurações do GitFut',
      panelTitle: 'GitFut',
      panelSubtitle: 'Scouting · cache · exibição',
      close: 'Fechar',
      cancel: 'Cancelar',
      save: 'Salvar',
      saveReload: 'Salvar e recarregar',
      sectionDisplay: 'Exibição',
      uiLanguage: 'Idioma',
      uiLanguageHint: 'Idioma dos painéis GitFut, hovercards e configurações. Auto segue o navegador.',
      uiLanguageAuto: 'Auto (navegador)',
      sectionCache: 'Cache',
      showHovercard: 'Mostrar GitFut nos hovercards de avatar',
      showHovercardHint: 'Injeta OVR, posição e stats no popover nativo do GitHub.',
      cardTheme: 'Estilo da carta',
      cardThemeHint: 'Visual do painel no perfil e no hovercard.',
      cardThemeStandard: 'Padrão',
      cardThemeGithub: 'GitHub',
      cardThemeFifa: 'FIFA',
      cardThemeNeon: 'Neon',
      on: 'ON',
      off: 'OFF',
      cacheHours: 'Duração do cache (horas)',
      cacheHoursHint: 'Por quanto tempo reutilizar a API. 0 desativa.',
      clearCache: 'Limpar cache',
      cacheCleared: 'Cache limpo ({count})',
      cacheEmpty: 'Cache vazio',
      cacheClearHint: 'Remove buscas GitFut deste perfil.',
      version: 'Versão {version}',
      cacheCards: '{count} cartas em cache',
      cacheStorage: '{used} usados · {free} livres',
      cacheStorageHint: 'Tamanho do cache local vs orçamento suave de {budget}.',
      repoLink: 'GitHub',
      repoAbout: 'Código, atualizações e issues',
      skillMoves: 'Habilidades',
      weakFoot: 'Pé fraco',
      workRate: 'Dedicação',
      style: 'Estilo',
    },
    de: {
      loading: 'Scouting…',
      loadError: 'Scout fehlgeschlagen',
      notFound: 'Keine Karte',
      overall: 'OVR',
      position: 'POS',
      finish: 'Finish',
      archetype: 'Archetyp',
      language: 'Sprache',
      playstyles: 'Spielstile',
      metrics: 'Scout-Metriken',
      openReport: 'Vollen Bericht öffnen',
      duel: 'Duell',
      menuSettings: 'GitHub GitFut — Einstellungen',
      navMenuItem: 'GitFut-Einstellungen',
      panelTitle: 'GitFut',
      panelSubtitle: 'Scouting · Cache · Anzeige',
      close: 'Schließen',
      cancel: 'Abbrechen',
      save: 'Speichern',
      saveReload: 'Speichern & neu laden',
      sectionDisplay: 'Anzeige',
      uiLanguage: 'Sprache',
      uiLanguageHint: 'Sprache für GitFut-Panels, Hovercards und Einstellungen. Auto folgt dem Browser.',
      uiLanguageAuto: 'Auto (Browser)',
      sectionCache: 'Cache',
      showHovercard: 'GitFut in Avatar-Hovercards zeigen',
      showHovercardHint: 'Fügt OVR, Position und Stats in GitHubs User-Popover ein.',
      cardTheme: 'Kartenstil',
      cardThemeHint: 'Optik der Scout-Panels auf Profil und Hovercard.',
      cardThemeStandard: 'Standard',
      cardThemeGithub: 'GitHub',
      cardThemeFifa: 'FIFA',
      cardThemeNeon: 'Neon',
      on: 'AN',
      off: 'AUS',
      cacheHours: 'Cache-Dauer (Stunden)',
      cacheHoursHint: 'Wie lange API-Ergebnisse wiederverwendet werden. 0 = aus.',
      clearCache: 'Cache leeren',
      cacheCleared: 'Cache geleert ({count})',
      cacheEmpty: 'Cache ist leer',
      cacheClearHint: 'Löscht gespeicherte GitFut-Lookups.',
      version: 'Version {version}',
      cacheCards: '{count} Karten im Cache',
      cacheStorage: '{used} belegt · {free} frei',
      cacheStorageHint: 'Lokaler Karten-Cache gegenüber Soft-Limit {budget}.',
      repoLink: 'GitHub',
      repoAbout: 'Quellcode, Updates und Issues',
      skillMoves: 'Tricks',
      weakFoot: 'Schwachfuß',
      workRate: 'Einsatz',
      style: 'Stil',
    },
    fr: {
      loading: 'Scouting…',
      loadError: 'Échec du scout',
      notFound: 'Pas de carte',
      overall: 'OVR',
      position: 'POS',
      finish: 'Finition',
      archetype: 'Archétype',
      language: 'Langage',
      playstyles: 'Styles',
      metrics: 'Métriques',
      openReport: 'Ouvrir le rapport complet',
      duel: 'Duel',
      menuSettings: 'GitHub GitFut — Réglages',
      navMenuItem: 'Réglages GitFut',
      panelTitle: 'GitFut',
      panelSubtitle: 'Scouting · cache · affichage',
      close: 'Fermer',
      cancel: 'Annuler',
      save: 'Enregistrer',
      saveReload: 'Enregistrer et recharger',
      sectionDisplay: 'Affichage',
      uiLanguage: 'Langue',
      uiLanguageHint: 'Langue des panneaux GitFut, hovercards et réglages. Auto suit le navigateur.',
      uiLanguageAuto: 'Auto (navigateur)',
      sectionCache: 'Cache',
      showHovercard: 'Afficher GitFut dans les hovercards d’avatar',
      showHovercardHint: 'Injecte OVR, poste et stats dans le popover natif de GitHub.',
      cardTheme: 'Style de carte',
      cardThemeHint: 'Apparence des panneaux scout sur profil et hovercard.',
      cardThemeStandard: 'Standard',
      cardThemeGithub: 'GitHub',
      cardThemeFifa: 'FIFA',
      cardThemeNeon: 'Néon',
      on: 'ON',
      off: 'OFF',
      cacheHours: 'Durée du cache (heures)',
      cacheHoursHint: 'Durée de réutilisation de l’API. 0 désactive.',
      clearCache: 'Vider le cache',
      cacheCleared: 'Cache vidé ({count})',
      cacheEmpty: 'Cache vide',
      cacheClearHint: 'Supprime les recherches GitFut de ce profil.',
      version: 'Version {version}',
      cacheCards: '{count} cartes en cache',
      cacheStorage: '{used} utilisés · {free} libres',
      cacheStorageHint: 'Taille du cache local vs budget souple de {budget}.',
      repoLink: 'GitHub',
      repoAbout: 'Code, mises à jour et issues',
      skillMoves: 'Gestes',
      weakFoot: 'Pied faible',
      workRate: 'Intensité',
      style: 'Style',
    },
    ja: {
      loading: 'スカウティング…',
      loadError: 'スカウト失敗',
      notFound: 'カードなし',
      overall: 'OVR',
      position: 'ポジ',
      finish: 'フィニッシュ',
      archetype: 'アーキタイプ',
      language: '言語',
      playstyles: 'プレースタイル',
      metrics: 'スカウト指標',
      openReport: 'フルレポートを開く',
      duel: 'デュエル',
      menuSettings: 'GitHub GitFut — 設定',
      navMenuItem: 'GitFutの設定',
      panelTitle: 'GitFut',
      panelSubtitle: 'スカウト · キャッシュ · 表示',
      close: '閉じる',
      cancel: 'キャンセル',
      save: '保存',
      saveReload: '保存して再読込',
      sectionDisplay: '表示',
      uiLanguage: '言語',
      uiLanguageHint: 'GitFutパネル・ホバーカード・設定の表示言語。自動はブラウザに合わせます。',
      uiLanguageAuto: '自動(ブラウザ)',
      sectionCache: 'キャッシュ',
      showHovercard: 'アバターホバーカードにGitFutを表示',
      showHovercardHint: 'アバターホバー時にGitHubのユーザーポップオーバーへOVR等を挿入。',
      cardTheme: 'カードスタイル',
      cardThemeHint: 'プロフィールとホバーカードの見た目。',
      cardThemeStandard: 'スタンダード',
      cardThemeGithub: 'GitHub',
      cardThemeFifa: 'FIFA',
      cardThemeNeon: 'ネオン',
      on: 'ON',
      off: 'OFF',
      cacheHours: 'キャッシュ時間(時間)',
      cacheHoursHint: 'API結果の再利用時間。0で無効。',
      clearCache: 'キャッシュ削除',
      cacheCleared: '削除しました ({count})',
      cacheEmpty: 'キャッシュは空です',
      cacheClearHint: 'このブラウザのGitFut照会を削除します。',
      version: 'バージョン {version}',
      cacheCards: 'キャッシュ済み: {count} 件',
      cacheStorage: '使用 {used} · 空き {free}',
      cacheStorageHint: 'ローカルカードキャッシュとソフト上限 {budget}。',
      repoLink: 'GitHub',
      repoAbout: 'ソース・更新・Issue',
      skillMoves: 'スキル',
      weakFoot: 'ウィークフット',
      workRate: 'ワークレート',
      style: 'スタイル',
    },
    ko: {
      loading: '스카우팅…',
      loadError: '스카우트 실패',
      notFound: '카드 없음',
      overall: 'OVR',
      position: '포지션',
      finish: '피니시',
      archetype: '아키타입',
      language: '언어',
      playstyles: '플레이스타일',
      metrics: '스카우트 지표',
      openReport: '전체 리포트 열기',
      duel: '듀얼',
      menuSettings: 'GitHub GitFut — 설정',
      navMenuItem: 'GitFut 설정',
      panelTitle: 'GitFut',
      panelSubtitle: '스카우팅 · 캐시 · 표시',
      close: '닫기',
      cancel: '취소',
      save: '저장',
      saveReload: '저장 후 새로고침',
      sectionDisplay: '표시',
      uiLanguage: '언어',
      uiLanguageHint: 'GitFut 패널·호버카드·설정의 표시 언어. 자동은 브라우저를 따릅니다.',
      uiLanguageAuto: '자동 (브라우저)',
      sectionCache: '캐시',
      showHovercard: '아바타 호버카드에 GitFut 표시',
      showHovercardHint: '아바타 호버 시 GitHub 사용자 팝오버에 OVR·포지션·스탯을 넣습니다.',
      cardTheme: '카드 스타일',
      cardThemeHint: '프로필·호버카드 스카우트 패널의 시각 스타일.',
      cardThemeStandard: '기본',
      cardThemeGithub: 'GitHub',
      cardThemeFifa: 'FIFA',
      cardThemeNeon: '네온',
      on: 'ON',
      off: 'OFF',
      cacheHours: '캐시 시간(시간)',
      cacheHoursHint: 'API 결과 재사용 시간. 0이면 비활성.',
      clearCache: '캐시 비우기',
      cacheCleared: '비움 ({count})',
      cacheEmpty: '캐시가 비어 있음',
      cacheClearHint: '이 브라우저의 GitFut 조회를 삭제합니다.',
      version: '버전 {version}',
      cacheCards: '캐시된 카드 {count}개',
      cacheStorage: '사용 {used} · 남음 {free}',
      cacheStorageHint: '로컬 카드 캐시와 소프트 한도 {budget}.',
      repoLink: 'GitHub',
      repoAbout: '소스, 업데이트, 이슈',
      skillMoves: '스킬',
      weakFoot: '약발',
      workRate: '활동량',
      style: '스타일',
    },
    pl: {
      loading: 'Scouting…',
      loadError: 'Scout nieudany',
      notFound: 'Brak karty',
      overall: 'OVR',
      position: 'POZ',
      finish: 'Wykończenie',
      archetype: 'Archetyp',
      language: 'Język',
      playstyles: 'Style gry',
      metrics: 'Metryki',
      openReport: 'Otwórz pełny raport',
      duel: 'Pojedynek',
      menuSettings: 'GitHub GitFut — Ustawienia',
      navMenuItem: 'Ustawienia GitFut',
      panelTitle: 'GitFut',
      panelSubtitle: 'Scouting · cache · wyświetlanie',
      close: 'Zamknij',
      cancel: 'Anuluj',
      save: 'Zapisz',
      saveReload: 'Zapisz i odśwież',
      sectionDisplay: 'Wyświetlanie',
      uiLanguage: 'Język',
      uiLanguageHint: 'Język paneli GitFut, hovercard i ustawień. Auto — według przeglądarki.',
      uiLanguageAuto: 'Auto (przeglądarka)',
      sectionCache: 'Cache',
      showHovercard: 'Pokaż GitFut w hovercardach awatara',
      showHovercardHint: 'Wstawia OVR, pozycję i staty do natywnego popovera GitHub.',
      cardTheme: 'Styl karty',
      cardThemeHint: 'Wygląd paneli scout na profilu i w hovercard.',
      cardThemeStandard: 'Standardowy',
      cardThemeGithub: 'GitHub',
      cardThemeFifa: 'FIFA',
      cardThemeNeon: 'Neon',
      on: 'WŁ',
      off: 'WYŁ',
      cacheHours: 'Czas cache (godziny)',
      cacheHoursHint: 'Jak długo ponownie używać API. 0 wyłącza.',
      clearCache: 'Wyczyść cache',
      cacheCleared: 'Wyczyszczono ({count})',
      cacheEmpty: 'Cache pusty',
      cacheClearHint: 'Usuwa zapisane zapytania GitFut.',
      version: 'Wersja {version}',
      cacheCards: 'Karty w cache: {count}',
      cacheStorage: '{used} zajęte · {free} wolne',
      cacheStorageHint: 'Rozmiar lokalnego cache względem limitu {budget}.',
      repoLink: 'GitHub',
      repoAbout: 'Kod, aktualizacje i zgłoszenia',
      skillMoves: 'Sztuczki',
      weakFoot: 'Słaba noga',
      workRate: 'Zaangażowanie',
      style: 'Styl',
    },
  };

  function detectBrowserLocale() {
    const candidates = [navigator.language, ...(navigator.languages || [])];
    for (const candidate of candidates) {
      const raw = String(candidate).toLowerCase();
      const primary = raw.split('-')[0];
      if (SUPPORTED_LOCALES.includes(primary)) return primary;
      if (raw.startsWith('zh')) return 'zh';
      if (raw.startsWith('pt')) return 'pt';
    }
    return 'en';
  }

  function normalizeUiLocale(value) {
    const raw = String(value ?? 'auto').toLowerCase().trim();
    if (!raw || raw === 'auto') return 'auto';
    const primary = raw.split('-')[0];
    if (SUPPORTED_LOCALES.includes(primary)) return primary;
    if (raw.startsWith('zh')) return 'zh';
    if (raw.startsWith('pt')) return 'pt';
    return 'auto';
  }

  function resolveActiveLocale(pref) {
    const normalized = normalizeUiLocale(pref);
    return normalized === 'auto' ? detectBrowserLocale() : normalized;
  }

  /** @type {typeof DEFAULT_SETTINGS} */
  let settings = loadSettings();
  let locale = resolveActiveLocale(settings.locale);
  let panelOpen = false;

  function t(key, vars) {
    let text = TRANSLATIONS[locale]?.[key] ?? TRANSLATIONS.en[key] ?? key;
    if (vars && typeof vars === 'object') {
      for (const [name, value] of Object.entries(vars)) {
        text = text.replace(new RegExp(`\\{${name}\\}`, 'g'), String(value));
      }
    }
    return text;
  }

  function normalizeCacheHours(value) {
    const n = Math.round(Number(value));
    if (!Number.isFinite(n) || n < 0) return DEFAULT_SETTINGS.cacheHours;
    return Math.min(n, CACHE_HOURS_MAX);
  }

  function normalizeCardTheme(value) {
    const key = String(value || '').toLowerCase();
    return CARD_THEMES.includes(key) ? key : DEFAULT_SETTINGS.cardTheme;
  }

  function applyCardTheme() {
    const theme = normalizeCardTheme(settings.cardTheme);
    document.documentElement.dataset.gfCardTheme = theme;
    document.documentElement.classList.toggle('gf-card-theme-github', theme === 'github');
    document.documentElement.classList.toggle('gf-card-theme-fifa', theme === 'fifa');
    document.documentElement.classList.toggle('gf-card-theme-neon', theme === 'neon');
  }

  function loadSettings() {
    const raw = GM_getValue(SETTINGS_KEY, null);
    if (!raw || typeof raw !== 'object') return { ...DEFAULT_SETTINGS };
    return {
      ...DEFAULT_SETTINGS,
      ...raw,
      cacheHours: normalizeCacheHours(raw.cacheHours),
      showHovercard:
        typeof raw.showHovercard === 'boolean'
          ? raw.showHovercard
          : raw.showInlineBadges !== false,
      cardTheme: normalizeCardTheme(raw.cardTheme),
      locale: normalizeUiLocale(raw.locale),
    };
  }

  function saveSettings(next) {
    settings = {
      ...settings,
      ...next,
      cacheHours: normalizeCacheHours(next.cacheHours ?? settings.cacheHours),
      showHovercard:
        typeof next.showHovercard === 'boolean'
          ? next.showHovercard
          : settings.showHovercard !== false,
      cardTheme: normalizeCardTheme(
        next.cardTheme !== undefined ? next.cardTheme : settings.cardTheme
      ),
      locale: normalizeUiLocale(
        next.locale !== undefined ? next.locale : settings.locale
      ),
    };
    GM_setValue(SETTINGS_KEY, settings);
    locale = resolveActiveLocale(settings.locale);
    applyCardTheme();
    updateSettingsMenuState();
  }

  function getCacheTtlMs() {
    const hours = normalizeCacheHours(settings.cacheHours);
    return hours > 0 ? hours * 60 * 60 * 1000 : 0;
  }

  /** @type {Map<string, Promise<object|null>>} */
  const inflight = new Map();
  /** @type {Array<{ task: () => Promise<unknown>, resolve: Function, reject: Function }>} */
  const queue = [];
  let activeRequests = 0;
  /** @type {Record<string, unknown>|null} */
  let memoryCache = null;
  let cacheDirty = false;
  let cachePersistTimer = null;
  let scanTimer = null;
  let mutationObserver = null;
  let hovercardObserver = null;
  /** @type {number} */
  let hovercardSeq = 0;

  function escapeHtml(value) {
    return String(value ?? '')
      .replace(/&/g, '&amp;')
      .replace(/</g, '&lt;')
      .replace(/>/g, '&gt;')
      .replace(/"/g, '&quot;')
      .replace(/'/g, '&#39;');
  }

  function finishMeta(finish) {
    return FINISH_COLORS[finish] || FINISH_COLORS.bronze;
  }

  function isValidUsername(login) {
    if (!login || typeof login !== 'string') return false;
    const name = login.trim();
    if (name.length < 1 || name.length > 39) return false;
    if (RESERVED_PATHS.has(name.toLowerCase())) return false;
    return /^[A-Za-z0-9](?:[A-Za-z0-9]|-(?=[A-Za-z0-9])){0,38}$/.test(name);
  }

  function getLoggedInUsername() {
    const meta = document.querySelector('meta[name="user-login"]');
    const login = meta?.getAttribute('content')?.trim();
    return login && isValidUsername(login) ? login : null;
  }

  /** @param {string} opponentLogin */
  function buildDuelUrl(opponentLogin) {
    const opponent = String(opponentLogin || '').trim();
    if (!opponent || !isValidUsername(opponent)) {
      return `${SITE_BASE}`;
    }
    const me = getLoggedInUsername();
    if (me && me.toLowerCase() !== opponent.toLowerCase()) {
      return `${SITE_BASE}/${encodeURIComponent(me)}/vs/${encodeURIComponent(opponent)}`;
    }
    return `${SITE_BASE}/${encodeURIComponent(opponent)}/vs`;
  }

  function getProfileUsername() {
    if (location.hostname === 'gist.github.com') {
      const parts = location.pathname.split('/').filter(Boolean);
      return parts[0] && isValidUsername(parts[0]) ? parts[0] : null;
    }
    const parts = location.pathname.split('/').filter(Boolean);
    if (parts.length !== 1) return null;
    return isValidUsername(parts[0]) ? parts[0] : null;
  }

  function extractUsernameFromHref(href) {
    try {
      const url = new URL(href, location.origin);
      if (!/^(?:www\.)?github\.com$/.test(url.hostname) && url.hostname !== 'gist.github.com') {
        return null;
      }
      const parts = url.pathname.split('/').filter(Boolean);
      if (!parts.length) return null;
      if (parts.length === 1 || (url.hostname === 'gist.github.com' && parts.length >= 1)) {
        return isValidUsername(parts[0]) ? parts[0] : null;
      }
      return null;
    } catch {
      return null;
    }
  }

  function loadMemoryCache() {
    if (memoryCache) return memoryCache;
    const raw = GM_getValue(CACHE_KEY, null);
    memoryCache = raw && typeof raw === 'object' ? raw : {};
    return memoryCache;
  }

  function persistCacheNow() {
    if (!cacheDirty || !memoryCache) return;
    GM_setValue(CACHE_KEY, memoryCache);
    cacheDirty = false;
  }

  function schedulePersistCache() {
    cacheDirty = true;
    if (cachePersistTimer) clearTimeout(cachePersistTimer);
    cachePersistTimer = setTimeout(() => {
      cachePersistTimer = null;
      persistCacheNow();
    }, CACHE_PERSIST_MS);
  }

  function getCached(login) {
    const cache = loadMemoryCache();
    const key = login.toLowerCase();
    const entry = cache[key];
    if (!entry || typeof entry !== 'object') return null;
    const ttl = getCacheTtlMs();
    if (ttl <= 0) return null;
    if (Date.now() - (entry.ts || 0) > ttl) {
      delete cache[key];
      schedulePersistCache();
      return null;
    }
    return entry.data ?? null;
  }

  function setCached(login, data) {
    const cache = loadMemoryCache();
    cache[login.toLowerCase()] = { ts: Date.now(), data };
    schedulePersistCache();
  }

  function clearCardCache() {
    const cache = loadMemoryCache();
    const count = Object.keys(cache).length;
    memoryCache = {};
    cacheDirty = true;
    persistCacheNow();
    return count;
  }

  function formatBytes(bytes) {
    const n = Math.max(0, Number(bytes) || 0);
    if (n < 1024) return `${Math.round(n)} B`;
    if (n < 1024 * 1024) return `${(n / 1024).toFixed(n < 10 * 1024 ? 1 : 0)} KB`;
    return `${(n / (1024 * 1024)).toFixed(2)} MB`;
  }

  function getCacheStats() {
    const cache = loadMemoryCache();
    const count = Object.keys(cache).length;
    let used = 0;
    try {
      used = new TextEncoder().encode(JSON.stringify(cache)).length;
    } catch {
      used = JSON.stringify(cache).length;
    }
    const budget = CACHE_BUDGET_BYTES;
    const free = Math.max(0, budget - used);
    const usedRatio = budget > 0 ? Math.min(1, used / budget) : 0;
    const freeRatio = budget > 0 ? Math.max(0, 1 - usedRatio) : 0;
    return { count, used, free, budget, usedRatio, freeRatio };
  }

  function updateCacheStatsUI() {
    const panel = document.getElementById('gf-panel');
    if (!panel) return;
    const stats = getCacheStats();
    const countEl = panel.querySelector('#gf-cache-count');
    const storageEl = panel.querySelector('#gf-cache-storage');
    const bar = panel.querySelector('#gf-cache-bar');
    const fill = panel.querySelector('#gf-cache-bar-fill');
    if (countEl) countEl.textContent = t('cacheCards', { count: stats.count });
    if (storageEl) {
      storageEl.textContent = t('cacheStorage', {
        used: formatBytes(stats.used),
        free: formatBytes(stats.free),
      });
    }
    if (bar && fill) {
      const pct = Math.round(stats.freeRatio * 100);
      fill.style.width = `${pct}%`;
      bar.setAttribute('aria-valuenow', String(pct));
      bar.setAttribute('aria-valuetext', t('cacheStorage', {
        used: formatBytes(stats.used),
        free: formatBytes(stats.free),
      }));
      bar.classList.toggle('is-warn', stats.usedRatio >= 0.7 && stats.usedRatio < 0.9);
      bar.classList.toggle('is-full', stats.usedRatio >= 0.9);
    }
  }

  function enqueue(task) {
    return new Promise((resolve, reject) => {
      queue.push({ task, resolve, reject });
      pumpQueue();
    });
  }

  function pumpQueue() {
    while (activeRequests < MAX_CONCURRENT && queue.length) {
      const item = queue.shift();
      activeRequests += 1;
      Promise.resolve()
        .then(() => new Promise((r) => setTimeout(r, REQUEST_DELAY_MS)))
        .then(() => item.task())
        .then(item.resolve, item.reject)
        .finally(() => {
          activeRequests -= 1;
          pumpQueue();
        });
    }
  }

  function gmGetJson(url) {
    return new Promise((resolve, reject) => {
      GM_xmlhttpRequest({
        method: 'GET',
        url,
        headers: { Accept: 'application/json' },
        onload(res) {
          if (res.status === 404) {
            resolve(null);
            return;
          }
          if (res.status < 200 || res.status >= 300) {
            reject(new Error(`HTTP ${res.status}`));
            return;
          }
          try {
            resolve(JSON.parse(res.responseText));
          } catch (err) {
            reject(err);
          }
        },
        onerror: () => reject(new Error('Network error')),
        ontimeout: () => reject(new Error('Timeout')),
      });
    });
  }

  function fetchCard(login) {
    const key = login.toLowerCase();
    const cached = getCached(login);
    if (cached !== null && cached !== undefined) {
      return Promise.resolve(cached);
    }
    if (inflight.has(key)) return inflight.get(key);

    const promise = enqueue(() => gmGetJson(`${API_BASE}/${encodeURIComponent(login)}`))
      .then((data) => {
        setCached(login, data);
        return data;
      })
      .finally(() => inflight.delete(key));

    inflight.set(key, promise);
    return promise;
  }

  GM_addStyle(`
    :root {
      --gf-radius: 16px;
      --gf-font: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Helvetica, Arial, sans-serif;
      --gf-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
    }

    #${PANEL_ID} {
      position: relative;
      isolation: isolate;
      font-family: var(--gf-font);
      margin: 0 0 16px;
      border: 1px solid color-mix(
        in srgb,
        var(--gf-finish-accent, #CD7F32) 48%,
        var(--borderColor-default, var(--color-border-default, #d0d7de))
      );
      border-radius: var(--gf-radius);
      background:
        radial-gradient(
          120% 80% at 0% 0%,
          var(--gf-finish-soft, rgba(205,127,50,0.16)),
          transparent 55%
        ),
        radial-gradient(
          90% 70% at 100% 100%,
          color-mix(in srgb, var(--gf-finish-glow, rgba(205,127,50,0.28)) 32%, transparent),
          transparent 60%
        ),
        var(--bgColor-default, var(--color-canvas-default, #fff));
      overflow: hidden;
      box-shadow:
        var(--gf-panel-outer-glow, 0 0 0 transparent),
        var(--gf-panel-ring, 0 0 0 1px transparent),
        0 8px 24px rgba(1, 4, 9, 0.1);
      transition: box-shadow 0.25s ease, border-color 0.25s ease, background 0.25s ease;
    }

    #${PANEL_ID}.is-expanding {
      transition:
        height 0.42s cubic-bezier(0.22, 1, 0.36, 1),
        margin-bottom 0.42s cubic-bezier(0.22, 1, 0.36, 1),
        opacity 0.3s ease,
        box-shadow 0.25s ease,
        border-color 0.25s ease,
        background 0.25s ease;
      will-change: height, opacity, margin-bottom;
    }

    #${PANEL_ID} > .gf-panel-theme-fx {
      position: absolute;
      inset: 0;
      border-radius: inherit;
      overflow: hidden;
      pointer-events: none;
      z-index: 0;
    }

    #${PANEL_ID} > .gf-panel-theme-fx + * {
      position: relative;
      z-index: 1;
    }

    .gf-panel-theme-fx__shine {
      position: absolute;
      inset: 0;
      background: linear-gradient(
        115deg,
        transparent 35%,
        var(--gf-finish-shine, rgba(255,255,255,0.35)) 48%,
        transparent 62%
      );
      background-size: 220% 100%;
      background-position: 120% 0;
      opacity: 0;
    }

    #${PANEL_ID}.gf-panel-finish--bronze {
      --gf-hc-shine-opacity: 0;
      --gf-panel-ring: inset 0 0 0 1px color-mix(in srgb, var(--gf-finish-accent) 24%, transparent);
      --gf-panel-outer-glow: 0 0 0 transparent;
    }

    #${PANEL_ID}.gf-panel-finish--silver {
      --gf-hc-shine-opacity: 0.16;
      --gf-panel-ring: inset 0 0 0 1px color-mix(in srgb, var(--gf-finish-accent) 36%, transparent);
      --gf-panel-outer-glow: 0 0 18px color-mix(in srgb, var(--gf-finish-glow) 40%, transparent);
    }

    #${PANEL_ID}.gf-panel-finish--gold {
      --gf-hc-shine-opacity: 0.3;
      --gf-panel-ring: inset 0 0 0 1px color-mix(in srgb, var(--gf-finish-accent) 50%, transparent);
      --gf-panel-outer-glow:
        0 0 22px color-mix(in srgb, var(--gf-finish-glow) 65%, transparent),
        0 0 40px color-mix(in srgb, var(--gf-finish-glow) 24%, transparent);
    }

    #${PANEL_ID}.gf-panel-finish--totw {
      --gf-hc-shine-opacity: 0.26;
      --gf-panel-ring: inset 0 0 0 1px color-mix(in srgb, var(--gf-finish-accent) 55%, transparent);
      --gf-panel-outer-glow:
        0 0 24px color-mix(in srgb, var(--gf-finish-glow) 70%, transparent),
        0 0 48px color-mix(in srgb, var(--gf-finish-glow) 28%, transparent);
    }

    #${PANEL_ID}.gf-panel-finish--toty {
      --gf-hc-shine-opacity: 0.36;
      --gf-panel-ring: inset 0 0 0 1px color-mix(in srgb, var(--gf-finish-accent) 60%, transparent);
      --gf-panel-outer-glow:
        0 0 28px color-mix(in srgb, var(--gf-finish-glow) 75%, transparent),
        0 0 56px color-mix(in srgb, var(--gf-finish-glow) 32%, transparent);
    }

    #${PANEL_ID}.gf-panel-finish--icon,
    #${PANEL_ID}.gf-panel-finish--founder {
      --gf-hc-shine-opacity: 0.42;
      --gf-panel-ring:
        inset 0 0 0 1px color-mix(in srgb, var(--gf-finish-accent) 68%, transparent),
        inset 0 0 28px color-mix(in srgb, var(--gf-finish-soft) 50%, transparent);
      --gf-panel-outer-glow:
        0 0 30px color-mix(in srgb, var(--gf-finish-glow) 80%, transparent),
        0 0 60px color-mix(in srgb, var(--gf-finish-glow) 36%, transparent);
    }

    #${PANEL_ID}.gf-panel-finish--gold .gf-panel-theme-fx__shine,
    #${PANEL_ID}.gf-panel-finish--totw .gf-panel-theme-fx__shine,
    #${PANEL_ID}.gf-panel-finish--toty .gf-panel-theme-fx__shine,
    #${PANEL_ID}.gf-panel-finish--icon .gf-panel-theme-fx__shine,
    #${PANEL_ID}.gf-panel-finish--founder .gf-panel-theme-fx__shine {
      animation: gf-hc-shine-sweep 1.8s ease-in-out 1 forwards;
    }

    #${PANEL_ID}.gf-panel-finish--totw {
      animation: gf-panel-pulse-totw 2.4s ease-in-out infinite;
    }

    #${PANEL_ID}.gf-panel-finish--icon {
      animation: gf-panel-pulse-icon 2.8s ease-in-out infinite;
    }

    #${PANEL_ID}.gf-panel-finish--founder {
      animation: gf-panel-pulse-founder 2.2s ease-in-out infinite;
    }

    @keyframes gf-panel-pulse-totw {
      0%, 100% {
        box-shadow:
          0 0 20px color-mix(in srgb, var(--gf-finish-glow) 50%, transparent),
          0 0 36px color-mix(in srgb, var(--gf-finish-glow) 20%, transparent),
          inset 0 0 0 1px color-mix(in srgb, var(--gf-finish-accent) 50%, transparent),
          0 8px 24px rgba(1, 4, 9, 0.1);
      }
      50% {
        box-shadow:
          0 0 32px color-mix(in srgb, var(--gf-finish-glow) 80%, transparent),
          0 0 56px color-mix(in srgb, var(--gf-finish-glow) 36%, transparent),
          inset 0 0 0 1px color-mix(in srgb, var(--gf-finish-accent) 72%, transparent),
          0 10px 28px rgba(1, 4, 9, 0.14);
      }
    }

    @keyframes gf-panel-pulse-icon {
      0%, 100% {
        box-shadow:
          0 0 26px color-mix(in srgb, var(--gf-finish-glow) 55%, transparent),
          0 0 46px color-mix(in srgb, var(--gf-finish-accent) 24%, transparent),
          inset 0 0 22px color-mix(in srgb, var(--gf-finish-soft) 38%, transparent),
          0 8px 24px rgba(1, 4, 9, 0.12);
      }
      50% {
        box-shadow:
          0 0 40px color-mix(in srgb, var(--gf-finish-glow) 88%, transparent),
          0 0 68px color-mix(in srgb, var(--gf-finish-accent) 42%, transparent),
          inset 0 0 34px color-mix(in srgb, var(--gf-finish-soft) 52%, transparent),
          0 12px 30px rgba(1, 4, 9, 0.16);
      }
    }

    @keyframes gf-panel-pulse-founder {
      0%, 100% {
        box-shadow:
          0 0 28px color-mix(in srgb, var(--gf-finish-glow) 60%, transparent),
          0 0 50px color-mix(in srgb, var(--gf-finish-accent) 26%, transparent),
          inset 0 0 24px color-mix(in srgb, var(--gf-finish-soft) 42%, transparent),
          0 8px 24px rgba(1, 4, 9, 0.12);
      }
      50% {
        box-shadow:
          0 0 44px color-mix(in srgb, var(--gf-finish-glow) 92%, transparent),
          0 0 74px color-mix(in srgb, var(--gf-finish-accent) 46%, transparent),
          inset 0 0 38px color-mix(in srgb, var(--gf-finish-soft) 58%, transparent),
          0 12px 32px rgba(1, 4, 9, 0.18);
      }
    }

    .gf-panel__inner {
      position: relative;
      z-index: 1;
    }

    .gf-panel__head {
      display: flex;
      align-items: center;
      gap: 12px;
      padding: 14px 14px 12px;
      border-bottom: 1px solid color-mix(in srgb, var(--gf-finish-accent, #CD7F32) 22%, transparent);
      background: linear-gradient(
        180deg,
        color-mix(in srgb, var(--gf-finish-soft, rgba(205,127,50,0.16)) 55%, transparent),
        transparent
      );
    }

    .gf-panel__ovr {
      flex: 0 0 auto;
      min-width: 56px;
      padding: 9px 11px;
      border-radius: 12px;
      background:
        linear-gradient(
          145deg,
          var(--gf-finish-shine, rgba(255,255,255,0.35)),
          var(--gf-finish-accent, #CD7F32) 40%,
          var(--gf-finish-deep, #5a3412)
        );
      color: var(--gf-finish-ink, #2A1A0C);
      text-align: center;
      line-height: 1.05;
      box-shadow:
        inset 0 1px 0 color-mix(in srgb, var(--gf-finish-shine) 55%, transparent),
        0 0 0 1px color-mix(in srgb, var(--gf-finish-deep) 35%, transparent),
        var(--gf-panel-ovr-glow, none);
    }

    #${PANEL_ID}.gf-panel-finish--silver .gf-panel__ovr,
    #${PANEL_ID}.gf-panel-finish--gold .gf-panel__ovr {
      --gf-panel-ovr-glow: 0 0 14px color-mix(in srgb, var(--gf-finish-glow) 55%, transparent);
    }

    #${PANEL_ID}.gf-panel-finish--totw .gf-panel__ovr,
    #${PANEL_ID}.gf-panel-finish--toty .gf-panel__ovr,
    #${PANEL_ID}.gf-panel-finish--icon .gf-panel__ovr,
    #${PANEL_ID}.gf-panel-finish--founder .gf-panel__ovr {
      --gf-panel-ovr-glow:
        0 0 18px color-mix(in srgb, var(--gf-finish-glow) 75%, transparent),
        0 0 30px color-mix(in srgb, var(--gf-finish-glow) 35%, transparent);
    }

    .gf-panel__ovr-value {
      display: block;
      font-size: 24px;
      font-weight: 800;
      letter-spacing: -0.03em;
      font-variant-numeric: tabular-nums;
      text-shadow: 0 1px 0 color-mix(in srgb, var(--gf-finish-shine) 40%, transparent);
    }

    .gf-panel__ovr-label {
      display: block;
      font-size: 10px;
      font-weight: 700;
      letter-spacing: 0.08em;
      opacity: 0.8;
      text-transform: uppercase;
    }

    .gf-panel__meta {
      min-width: 0;
      flex: 1;
    }

    .gf-panel__title-row {
      display: flex;
      flex-wrap: wrap;
      align-items: center;
      gap: 6px 8px;
    }

    .gf-panel__name {
      font-size: 15px;
      font-weight: 700;
      color: var(--fgColor-default, var(--color-fg-default, #1f2328));
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }

    .gf-chip {
      display: inline-flex;
      align-items: center;
      gap: 4px;
      padding: 2px 8px;
      border-radius: 999px;
      font-size: 11px;
      font-weight: 700;
      letter-spacing: 0.02em;
      border: 1px solid color-mix(in srgb, var(--gf-finish-accent, #CD7F32) 50%, transparent);
      background: color-mix(in srgb, var(--gf-finish-accent, #CD7F32) 16%, transparent);
      color: var(--fgColor-default, var(--color-fg-default, #1f2328));
      text-transform: uppercase;
    }

    #${PANEL_ID}.gf-panel-finish--gold .gf-chip,
    #${PANEL_ID}.gf-panel-finish--totw .gf-chip,
    #${PANEL_ID}.gf-panel-finish--toty .gf-chip,
    #${PANEL_ID}.gf-panel-finish--icon .gf-chip,
    #${PANEL_ID}.gf-panel-finish--founder .gf-chip {
      box-shadow: 0 0 8px color-mix(in srgb, var(--gf-finish-glow) 28%, transparent);
    }

    .gf-panel__blurb {
      margin: 5px 0 0;
      font-size: 12px;
      color: var(--fgColor-muted, var(--color-fg-muted, #656d76));
      line-height: 1.4;
    }

    .gf-panel__body {
      padding: 12px 14px 14px;
    }

    .gf-stats {
      display: grid;
      grid-template-columns: repeat(3, minmax(0, 1fr));
      gap: 6px;
      margin: 0 0 12px;
    }

    .gf-stat {
      border-radius: 10px;
      padding: 8px 8px;
      text-align: center;
      background: color-mix(
        in srgb,
        var(--gf-finish-soft, rgba(205,127,50,0.16)) 32%,
        var(--bgColor-muted, var(--color-canvas-subtle, #f6f8fa))
      );
      border: 1px solid color-mix(in srgb, var(--gf-finish-accent, #CD7F32) 20%, transparent);
    }

    #${PANEL_ID}.gf-panel-finish--toty .gf-stat,
    #${PANEL_ID}.gf-panel-finish--icon .gf-stat,
    #${PANEL_ID}.gf-panel-finish--founder .gf-stat {
      border-color: color-mix(in srgb, var(--gf-finish-accent) 38%, transparent);
      box-shadow: inset 0 0 12px color-mix(in srgb, var(--gf-finish-soft) 38%, transparent);
    }

    .gf-stat__value {
      display: block;
      font-size: 16px;
      font-weight: 800;
      font-variant-numeric: tabular-nums;
      letter-spacing: -0.02em;
      color: var(--fgColor-default, var(--color-fg-default, #1f2328));
    }

    .gf-stat__key {
      display: block;
      margin-top: 1px;
      font-size: 10px;
      font-weight: 700;
      letter-spacing: 0.06em;
      color: var(--fgColor-muted, var(--color-fg-muted, #656d76));
    }

    .gf-attrs {
      display: grid;
      gap: 6px;
      margin: 0 0 12px;
      padding: 10px 11px;
      border-radius: 10px;
      font-size: 12px;
      color: var(--fgColor-default, var(--color-fg-default, #1f2328));
      background: color-mix(
        in srgb,
        var(--gf-finish-soft, rgba(205,127,50,0.16)) 18%,
        var(--bgColor-muted, var(--color-canvas-subtle, #f6f8fa))
      );
      border: 1px solid color-mix(in srgb, var(--gf-finish-accent, #CD7F32) 14%, transparent);
    }

    .gf-attrs__row {
      display: flex;
      justify-content: space-between;
      gap: 10px;
    }

    .gf-attrs__label {
      color: var(--fgColor-muted, var(--color-fg-muted, #656d76));
    }

    .gf-attrs__value {
      font-weight: 600;
      text-align: right;
      font-variant-numeric: tabular-nums;
    }

    .gf-playstyles {
      display: flex;
      flex-wrap: wrap;
      gap: 5px;
      margin: 0 0 12px;
    }

    .gf-playstyle {
      font-size: 11px;
      font-weight: 600;
      padding: 3px 8px;
      border-radius: 999px;
      background: var(--bgColor-default, var(--color-canvas-default, #fff));
      border: 1px solid var(--borderColor-default, var(--color-border-default, #d0d7de));
      color: var(--fgColor-default, var(--color-fg-default, #1f2328));
    }

    .gf-playstyle.is-plus {
      border-color: color-mix(in srgb, var(--gf-finish-accent, #CD7F32) 55%, transparent);
      background: color-mix(in srgb, var(--gf-finish-accent, #CD7F32) 14%, transparent);
      box-shadow: 0 0 8px color-mix(in srgb, var(--gf-finish-glow) 22%, transparent);
    }


    .gf-actions {
      display: flex;
      flex-wrap: wrap;
      gap: 8px;
    }

    .gf-btn-link {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      gap: 6px;
      padding: 7px 12px;
      border-radius: 8px;
      font-size: 12px;
      font-weight: 600;
      text-decoration: none !important;
      border: 1px solid var(--borderColor-default, var(--color-border-default, #d0d7de));
      background: var(--bgColor-default, var(--color-canvas-default, #fff));
      color: var(--fgColor-default, var(--color-fg-default, #1f2328)) !important;
      transition: background 0.15s ease, box-shadow 0.15s ease;
    }

    .gf-btn-link:hover {
      background: var(--control-transparent-bgColor-hover, rgba(208,215,222,0.32));
    }

    .gf-btn-link--primary {
      border-color: transparent;
      background:
        linear-gradient(
          145deg,
          var(--gf-finish-shine, rgba(255,255,255,0.35)),
          var(--gf-finish-accent, #CD7F32) 45%,
          var(--gf-finish-deep, #5a3412)
        );
      color: var(--gf-finish-ink, #2A1A0C) !important;
      box-shadow: 0 0 14px color-mix(in srgb, var(--gf-finish-glow) 38%, transparent);
    }

    .gf-btn-link--primary:hover {
      filter: brightness(1.06);
      background:
        linear-gradient(
          145deg,
          var(--gf-finish-shine, rgba(255,255,255,0.35)),
          var(--gf-finish-accent, #CD7F32) 45%,
          var(--gf-finish-deep, #5a3412)
        );
    }

    .gf-panel__status {
      padding: 16px 14px;
      font-size: 13px;
      color: var(--fgColor-muted, var(--color-fg-muted, #656d76));
    }

    .gf-panel__status.is-error {
      color: var(--fgColor-danger, var(--color-danger-fg, #d1242f));
    }

    #${PANEL_ID} .gf-panel-skel .gf-skel {
      display: block;
      border-radius: 6px;
      background: linear-gradient(
        90deg,
        color-mix(in srgb, var(--fgColor-muted, #656d76) 10%, transparent) 0%,
        color-mix(in srgb, var(--fgColor-muted, #656d76) 22%, transparent) 45%,
        color-mix(in srgb, var(--fgColor-muted, #656d76) 10%, transparent) 90%
      );
      background-size: 220% 100%;
      animation: gf-skel-shimmer 1.35s ease-in-out infinite;
    }

    #${PANEL_ID} .gf-skel--panel-ovr {
      flex: 0 0 auto;
      width: 56px;
      height: 50px;
      border-radius: 12px;
    }

    #${PANEL_ID} .gf-skel--panel-name {
      width: 42%;
      height: 14px;
      border-radius: 4px;
    }

    #${PANEL_ID} .gf-skel--panel-chip {
      width: 48px;
      height: 18px;
      border-radius: 999px;
    }

    #${PANEL_ID} .gf-skel--panel-blurb {
      width: 78%;
      height: 11px;
      margin-top: 8px;
    }

    #${PANEL_ID} .gf-skel--panel-stat {
      height: 48px;
      border-radius: 10px;
    }

    #${PANEL_ID} .gf-skel--panel-attr {
      height: 12px;
      border-radius: 4px;
    }

    #${PANEL_ID} .gf-skel--panel-btn {
      width: 108px;
      height: 30px;
      border-radius: 8px;
    }

    #${PANEL_ID} .gf-skel--panel-btn-sm {
      width: 64px;
    }

    .Popover-message.gf-hc-themed {
      position: relative;
      isolation: isolate;
      border-radius: 16px !important;
      border-color: color-mix(
        in srgb,
        var(--gf-finish-accent, #CD7F32) 58%,
        var(--borderColor-default, #d0d7de)
      ) !important;
      background:
        radial-gradient(
          120% 80% at 0% 0%,
          var(--gf-finish-soft, rgba(205,127,50,0.16)),
          transparent 55%
        ),
        radial-gradient(
          90% 70% at 100% 100%,
          color-mix(in srgb, var(--gf-finish-glow, rgba(205,127,50,0.28)) 35%, transparent),
          transparent 60%
        ),
        var(--bgColor-default, var(--color-canvas-default, #fff)) !important;
      box-shadow:
        var(--gf-hc-outer-glow, 0 0 0 transparent),
        var(--gf-hc-ring, 0 0 0 1px transparent),
        0 10px 28px rgba(1, 4, 9, 0.2) !important;
      transition: box-shadow 0.25s ease, border-color 0.25s ease, background 0.25s ease;
    }

    .Popover-message.gf-hc-themed > .gf-hc-theme-fx {
      position: absolute;
      inset: 0;
      border-radius: inherit;
      overflow: hidden;
      pointer-events: none;
      z-index: 0;
    }

    .Popover-message.gf-hc-themed > .gf-hc-theme-fx + * {
      position: relative;
      z-index: 1;
    }

    .gf-hc-theme-fx__shine {
      position: absolute;
      inset: 0;
      background: linear-gradient(
        115deg,
        transparent 35%,
        var(--gf-finish-shine, rgba(255,255,255,0.35)) 48%,
        transparent 62%
      );
      background-size: 220% 100%;
      background-position: 120% 0;
      opacity: 0;
    }

    .Popover-message.gf-hc-finish--bronze {
      --gf-hc-shine-opacity: 0;
      --gf-hc-ring: inset 0 0 0 1px color-mix(in srgb, var(--gf-finish-accent) 28%, transparent);
      --gf-hc-outer-glow: 0 0 0 transparent;
    }

    .Popover-message.gf-hc-finish--silver {
      --gf-hc-shine-opacity: 0.18;
      --gf-hc-ring: inset 0 0 0 1px color-mix(in srgb, var(--gf-finish-accent) 40%, transparent);
      --gf-hc-outer-glow: 0 0 16px color-mix(in srgb, var(--gf-finish-glow) 45%, transparent);
    }

    .Popover-message.gf-hc-finish--gold {
      --gf-hc-shine-opacity: 0.32;
      --gf-hc-ring: inset 0 0 0 1px color-mix(in srgb, var(--gf-finish-accent) 55%, transparent);
      --gf-hc-outer-glow:
        0 0 22px color-mix(in srgb, var(--gf-finish-glow) 70%, transparent),
        0 0 40px color-mix(in srgb, var(--gf-finish-glow) 28%, transparent);
    }

    .Popover-message.gf-hc-finish--totw {
      --gf-hc-shine-opacity: 0.28;
      --gf-hc-ring: inset 0 0 0 1px color-mix(in srgb, var(--gf-finish-accent) 60%, transparent);
      --gf-hc-outer-glow:
        0 0 24px color-mix(in srgb, var(--gf-finish-glow) 75%, transparent),
        0 0 48px color-mix(in srgb, var(--gf-finish-glow) 30%, transparent);
    }

    .Popover-message.gf-hc-finish--toty {
      --gf-hc-shine-opacity: 0.38;
      --gf-hc-ring: inset 0 0 0 1px color-mix(in srgb, var(--gf-finish-accent) 65%, transparent);
      --gf-hc-outer-glow:
        0 0 28px color-mix(in srgb, var(--gf-finish-glow) 80%, transparent),
        0 0 56px color-mix(in srgb, var(--gf-finish-glow) 35%, transparent);
    }

    .Popover-message.gf-hc-finish--icon,
    .Popover-message.gf-hc-finish--founder {
      --gf-hc-shine-opacity: 0.45;
      --gf-hc-ring:
        inset 0 0 0 1px color-mix(in srgb, var(--gf-finish-accent) 70%, transparent),
        inset 0 0 28px color-mix(in srgb, var(--gf-finish-soft) 55%, transparent);
      --gf-hc-outer-glow:
        0 0 32px color-mix(in srgb, var(--gf-finish-glow) 85%, transparent),
        0 0 64px color-mix(in srgb, var(--gf-finish-glow) 40%, transparent);
    }

    .Popover-message.gf-hc-finish--gold .gf-hc-theme-fx__shine,
    .Popover-message.gf-hc-finish--totw .gf-hc-theme-fx__shine,
    .Popover-message.gf-hc-finish--toty .gf-hc-theme-fx__shine,
    .Popover-message.gf-hc-finish--icon .gf-hc-theme-fx__shine,
    .Popover-message.gf-hc-finish--founder .gf-hc-theme-fx__shine {
      animation: gf-hc-shine-sweep 1.8s ease-in-out 1 forwards;
    }

    .Popover-message.gf-hc-finish--totw {
      animation: gf-hc-pulse-totw 2.4s ease-in-out infinite;
    }

    .Popover-message.gf-hc-finish--icon {
      animation: gf-hc-pulse-icon 2.8s ease-in-out infinite;
    }

    .Popover-message.gf-hc-finish--founder {
      animation: gf-hc-pulse-founder 2.2s ease-in-out infinite;
    }

    @keyframes gf-hc-shine-sweep {
      0% { background-position: 130% 0; opacity: 0; }
      12% { opacity: var(--gf-hc-shine-opacity, 0.3); }
      55% {
        background-position: -30% 0;
        opacity: calc(var(--gf-hc-shine-opacity, 0.3) * 1.15);
      }
      100% { background-position: -30% 0; opacity: 0; }
    }

    @keyframes gf-hc-pulse-totw {
      0%, 100% {
        box-shadow:
          0 0 22px color-mix(in srgb, var(--gf-finish-glow) 55%, transparent),
          0 0 40px color-mix(in srgb, var(--gf-finish-glow) 22%, transparent),
          inset 0 0 0 1px color-mix(in srgb, var(--gf-finish-accent) 55%, transparent),
          0 10px 28px rgba(1, 4, 9, 0.2);
      }
      50% {
        box-shadow:
          0 0 34px color-mix(in srgb, var(--gf-finish-glow) 85%, transparent),
          0 0 60px color-mix(in srgb, var(--gf-finish-glow) 40%, transparent),
          inset 0 0 0 1px color-mix(in srgb, var(--gf-finish-accent) 75%, transparent),
          0 12px 32px rgba(1, 4, 9, 0.24);
      }
    }

    @keyframes gf-hc-pulse-icon {
      0%, 100% {
        box-shadow:
          0 0 28px color-mix(in srgb, var(--gf-finish-glow) 60%, transparent),
          0 0 50px color-mix(in srgb, var(--gf-finish-accent) 28%, transparent),
          inset 0 0 24px color-mix(in srgb, var(--gf-finish-soft) 40%, transparent),
          0 10px 28px rgba(1, 4, 9, 0.22);
      }
      50% {
        box-shadow:
          0 0 42px color-mix(in srgb, var(--gf-finish-glow) 90%, transparent),
          0 0 72px color-mix(in srgb, var(--gf-finish-accent) 45%, transparent),
          inset 0 0 36px color-mix(in srgb, var(--gf-finish-soft) 55%, transparent),
          0 14px 34px rgba(1, 4, 9, 0.26);
      }
    }

    @keyframes gf-hc-pulse-founder {
      0%, 100% {
        box-shadow:
          0 0 30px color-mix(in srgb, var(--gf-finish-glow) 65%, transparent),
          0 0 54px color-mix(in srgb, var(--gf-finish-accent) 30%, transparent),
          inset 0 0 26px color-mix(in srgb, var(--gf-finish-soft) 45%, transparent),
          0 10px 28px rgba(1, 4, 9, 0.22);
      }
      50% {
        box-shadow:
          0 0 46px color-mix(in srgb, var(--gf-finish-glow) 95%, transparent),
          0 0 78px color-mix(in srgb, var(--gf-finish-accent) 48%, transparent),
          inset 0 0 40px color-mix(in srgb, var(--gf-finish-soft) 60%, transparent),
          0 14px 36px rgba(1, 4, 9, 0.28);
      }
    }

    #${HOVERCARD_BLOCK_ID} {
      position: relative;
      z-index: 1;
      margin-top: 12px;
      padding: 12px 10px 10px;
      margin-left: -4px;
      margin-right: -4px;
      border-radius: 14px;
      border-top: 1px solid color-mix(in srgb, var(--gf-finish-accent, #CD7F32) 35%, transparent);
      background:
        linear-gradient(
          180deg,
          color-mix(in srgb, var(--gf-finish-soft, rgba(205,127,50,0.16)) 70%, transparent),
          transparent 85%
        );
      font-family: var(--gf-font);
      box-shadow: var(--gf-hc-block-glow, none);
    }

    #${HOVERCARD_BLOCK_ID}.gf-hc-finish--gold,
    #${HOVERCARD_BLOCK_ID}.gf-hc-finish--totw,
    #${HOVERCARD_BLOCK_ID}.gf-hc-finish--toty {
      --gf-hc-block-glow: inset 0 0 20px color-mix(in srgb, var(--gf-finish-soft) 45%, transparent);
    }

    #${HOVERCARD_BLOCK_ID}.gf-hc-finish--icon,
    #${HOVERCARD_BLOCK_ID}.gf-hc-finish--founder {
      --gf-hc-block-glow:
        inset 0 0 28px color-mix(in srgb, var(--gf-finish-soft) 60%, transparent),
        0 0 18px color-mix(in srgb, var(--gf-finish-glow) 25%, transparent);
    }

    #${HOVERCARD_BLOCK_ID} .gf-hc__head {
      display: flex;
      align-items: center;
      gap: 10px;
      margin-bottom: 8px;
    }

    #${HOVERCARD_BLOCK_ID} .gf-hc__ovr {
      flex: 0 0 auto;
      min-width: 44px;
      padding: 6px 8px;
      border-radius: 8px;
      background:
        linear-gradient(
          145deg,
          var(--gf-finish-shine, rgba(255,255,255,0.35)),
          var(--gf-finish-accent, #CD7F32) 40%,
          var(--gf-finish-deep, #5a3412)
        );
      color: var(--gf-finish-ink, #2A1A0C);
      text-align: center;
      line-height: 1.05;
      box-shadow:
        inset 0 1px 0 color-mix(in srgb, var(--gf-finish-shine) 55%, transparent),
        0 0 0 1px color-mix(in srgb, var(--gf-finish-deep) 35%, transparent),
        var(--gf-hc-ovr-glow, none);
    }

    #${HOVERCARD_BLOCK_ID}.gf-hc-finish--silver .gf-hc__ovr,
    #${HOVERCARD_BLOCK_ID}.gf-hc-finish--gold .gf-hc__ovr {
      --gf-hc-ovr-glow: 0 0 12px color-mix(in srgb, var(--gf-finish-glow) 55%, transparent);
    }

    #${HOVERCARD_BLOCK_ID}.gf-hc-finish--totw .gf-hc__ovr,
    #${HOVERCARD_BLOCK_ID}.gf-hc-finish--toty .gf-hc__ovr,
    #${HOVERCARD_BLOCK_ID}.gf-hc-finish--icon .gf-hc__ovr,
    #${HOVERCARD_BLOCK_ID}.gf-hc-finish--founder .gf-hc__ovr {
      --gf-hc-ovr-glow:
        0 0 16px color-mix(in srgb, var(--gf-finish-glow) 75%, transparent),
        0 0 28px color-mix(in srgb, var(--gf-finish-glow) 35%, transparent);
    }

    #${HOVERCARD_BLOCK_ID} .gf-hc__ovr-value {
      display: block;
      font-size: 18px;
      font-weight: 800;
      letter-spacing: -0.03em;
      font-variant-numeric: tabular-nums;
      text-shadow: 0 1px 0 color-mix(in srgb, var(--gf-finish-shine) 40%, transparent);
    }

    #${HOVERCARD_BLOCK_ID} .gf-hc__ovr-label {
      display: block;
      font-size: 9px;
      font-weight: 700;
      letter-spacing: 0.08em;
      text-transform: uppercase;
      opacity: 0.8;
    }

    #${HOVERCARD_BLOCK_ID} .gf-hc__meta {
      min-width: 0;
      flex: 1;
    }

    #${HOVERCARD_BLOCK_ID} .gf-hc__chips {
      display: flex;
      flex-wrap: wrap;
      gap: 5px;
      margin-bottom: 2px;
    }

    #${HOVERCARD_BLOCK_ID} .gf-chip {
      border-color: color-mix(in srgb, var(--gf-finish-accent, #CD7F32) 50%, transparent);
      background: color-mix(in srgb, var(--gf-finish-accent, #CD7F32) 16%, transparent);
    }

    #${HOVERCARD_BLOCK_ID}.gf-hc-finish--gold .gf-chip,
    #${HOVERCARD_BLOCK_ID}.gf-hc-finish--totw .gf-chip,
    #${HOVERCARD_BLOCK_ID}.gf-hc-finish--toty .gf-chip,
    #${HOVERCARD_BLOCK_ID}.gf-hc-finish--icon .gf-chip,
    #${HOVERCARD_BLOCK_ID}.gf-hc-finish--founder .gf-chip {
      box-shadow: 0 0 8px color-mix(in srgb, var(--gf-finish-glow) 30%, transparent);
    }

    #${HOVERCARD_BLOCK_ID} .gf-hc__blurb {
      margin: 0;
      font-size: 11px;
      line-height: 1.35;
      color: var(--fgColor-muted, var(--color-fg-muted, #656d76));
    }

    #${HOVERCARD_BLOCK_ID} .gf-hc__stats {
      display: grid;
      grid-template-columns: repeat(6, minmax(0, 1fr));
      gap: 4px;
      margin: 0 0 8px;
    }

    #${HOVERCARD_BLOCK_ID} .gf-hc__stat {
      text-align: center;
      padding: 5px 2px;
      border-radius: 6px;
      background: color-mix(
        in srgb,
        var(--gf-finish-soft, rgba(205,127,50,0.16)) 35%,
        var(--bgColor-muted, var(--color-canvas-subtle, #f6f8fa))
      );
      border: 1px solid color-mix(in srgb, var(--gf-finish-accent, #CD7F32) 22%, transparent);
    }

    #${HOVERCARD_BLOCK_ID}.gf-hc-finish--toty .gf-hc__stat,
    #${HOVERCARD_BLOCK_ID}.gf-hc-finish--icon .gf-hc__stat,
    #${HOVERCARD_BLOCK_ID}.gf-hc-finish--founder .gf-hc__stat {
      border-color: color-mix(in srgb, var(--gf-finish-accent) 40%, transparent);
      box-shadow: inset 0 0 10px color-mix(in srgb, var(--gf-finish-soft) 40%, transparent);
    }

    #${HOVERCARD_BLOCK_ID} .gf-hc__stat-value {
      display: block;
      font-size: 13px;
      font-weight: 800;
      font-variant-numeric: tabular-nums;
      color: var(--fgColor-default, var(--color-fg-default, #1f2328));
    }

    #${HOVERCARD_BLOCK_ID} .gf-hc__stat-key {
      display: block;
      font-size: 9px;
      font-weight: 700;
      letter-spacing: 0.04em;
      color: var(--fgColor-muted, var(--color-fg-muted, #656d76));
    }

    #${HOVERCARD_BLOCK_ID} .gf-hc__actions {
      display: flex;
      flex-wrap: wrap;
      gap: 6px;
    }

    #${HOVERCARD_BLOCK_ID} .gf-hc__link {
      display: inline-flex;
      align-items: center;
      padding: 4px 8px;
      border-radius: 6px;
      font-size: 11px;
      font-weight: 600;
      text-decoration: none !important;
      border: 1px solid var(--borderColor-default, var(--color-border-default, #d0d7de));
      background: var(--bgColor-default, var(--color-canvas-default, #fff));
      color: var(--fgColor-default, var(--color-fg-default, #1f2328)) !important;
    }

    #${HOVERCARD_BLOCK_ID} .gf-hc__link--primary {
      border-color: transparent;
      background:
        linear-gradient(
          145deg,
          var(--gf-finish-shine, rgba(255,255,255,0.35)),
          var(--gf-finish-accent, #CD7F32) 45%,
          var(--gf-finish-deep, #5a3412)
        );
      color: var(--gf-finish-ink, #2A1A0C) !important;
      box-shadow: 0 0 12px color-mix(in srgb, var(--gf-finish-glow) 40%, transparent);
    }

    #${HOVERCARD_BLOCK_ID} .gf-hc__status {
      font-size: 12px;
      color: var(--fgColor-muted, var(--color-fg-muted, #656d76));
    }

    #${HOVERCARD_BLOCK_ID} .gf-hc__status.is-error {
      color: var(--fgColor-danger, var(--color-danger-fg, #d1242f));
    }

    #${HOVERCARD_BLOCK_ID} .gf-skel {
      display: block;
      border-radius: 6px;
      background: linear-gradient(
        90deg,
        color-mix(in srgb, var(--fgColor-muted, #656d76) 10%, transparent) 0%,
        color-mix(in srgb, var(--fgColor-muted, #656d76) 22%, transparent) 45%,
        color-mix(in srgb, var(--fgColor-muted, #656d76) 10%, transparent) 90%
      );
      background-size: 220% 100%;
      animation: gf-skel-shimmer 1.35s ease-in-out infinite;
    }

    #${HOVERCARD_BLOCK_ID} .gf-skel--ovr {
      flex: 0 0 auto;
      width: 44px;
      height: 42px;
      border-radius: 8px;
    }

    #${HOVERCARD_BLOCK_ID} .gf-skel--chip {
      width: 52px;
      height: 18px;
      border-radius: 999px;
    }

    #${HOVERCARD_BLOCK_ID} .gf-skel--blurb {
      width: 88%;
      height: 10px;
      margin-top: 6px;
    }

    #${HOVERCARD_BLOCK_ID} .gf-skel--blurb-short {
      width: 62%;
      margin-top: 5px;
    }

    #${HOVERCARD_BLOCK_ID} .gf-skel--stat {
      height: 36px;
      border-radius: 6px;
    }

    #${HOVERCARD_BLOCK_ID} .gf-skel--btn {
      width: 92px;
      height: 24px;
      border-radius: 6px;
    }

    #${HOVERCARD_BLOCK_ID} .gf-skel--btn-sm {
      width: 48px;
    }

    @keyframes gf-skel-shimmer {
      0% { background-position: 100% 0; }
      100% { background-position: -100% 0; }
    }

    @media (prefers-reduced-motion: reduce) {
      .Popover-message.gf-hc-themed,
      .Popover-message.gf-hc-themed .gf-hc-theme-fx__shine {
        animation: none !important;
      }

      #${PANEL_ID},
      #${PANEL_ID} .gf-panel-theme-fx__shine {
        animation: none !important;
      }

      #${HOVERCARD_BLOCK_ID} .gf-skel,
      #${PANEL_ID} .gf-skel {
        animation: none !important;
        background: color-mix(in srgb, var(--fgColor-muted, #656d76) 14%, transparent);
      }
    }

    /* FIFA theme: metallic finish colors like FUT cards, no glow / shine / pulse */
    html.gf-card-theme-fifa #${PANEL_ID},
    html.gf-card-theme-fifa .Popover-message.gf-hc-themed {
      --gf-panel-outer-glow: 0 0 0 transparent !important;
      --gf-panel-ring: 0 0 0 transparent !important;
      --gf-panel-ovr-glow: none !important;
      --gf-hc-outer-glow: 0 0 0 transparent !important;
      --gf-hc-ring: 0 0 0 transparent !important;
      --gf-hc-ovr-glow: none !important;
      --gf-hc-block-glow: none !important;
      --gf-hc-shine-opacity: 0 !important;
      animation: none !important;
    }

    html.gf-card-theme-fifa #${PANEL_ID} .gf-panel-theme-fx,
    html.gf-card-theme-fifa .Popover-message.gf-hc-themed > .gf-hc-theme-fx,
    html.gf-card-theme-fifa .gf-panel-theme-fx__shine,
    html.gf-card-theme-fifa .gf-hc-theme-fx__shine {
      display: none !important;
    }

    html.gf-card-theme-fifa #${PANEL_ID}.gf-panel-finish--bronze,
    html.gf-card-theme-fifa .Popover-message.gf-hc-finish--bronze {
      --gf-fifa-ink: #2A1810;
      --gf-fifa-muted: #6B4A32;
      --gf-fifa-border: #8B5A2B;
      --gf-fifa-ovr-top: #D4A574;
      --gf-fifa-ovr-bot: #8B5A2B;
      --gf-fifa-ovr-ink: #1F120A;
      --gf-fifa-stat: rgba(139, 90, 43, 0.18);
      --gf-fifa-chip: rgba(139, 90, 43, 0.22);
      background: linear-gradient(165deg, #E8C9A0 0%, #C9956C 42%, #A67C52 100%) !important;
      border-color: var(--gf-fifa-border) !important;
      color: var(--gf-fifa-ink);
      box-shadow: inset 0 1px 0 rgba(255, 240, 220, 0.45), 0 2px 8px rgba(90, 50, 20, 0.18) !important;
    }

    html.gf-card-theme-fifa #${PANEL_ID}.gf-panel-finish--silver,
    html.gf-card-theme-fifa .Popover-message.gf-hc-finish--silver {
      --gf-fifa-ink: #1A1E24;
      --gf-fifa-muted: #5A6270;
      --gf-fifa-border: #8A93A0;
      --gf-fifa-ovr-top: #E8ECF0;
      --gf-fifa-ovr-bot: #8A93A0;
      --gf-fifa-ovr-ink: #1A1E24;
      --gf-fifa-stat: rgba(90, 98, 112, 0.16);
      --gf-fifa-chip: rgba(90, 98, 112, 0.2);
      background: linear-gradient(165deg, #F2F4F7 0%, #C5CBD4 45%, #9AA3B0 100%) !important;
      border-color: var(--gf-fifa-border) !important;
      color: var(--gf-fifa-ink);
      box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.7), 0 2px 8px rgba(40, 50, 70, 0.14) !important;
    }

    html.gf-card-theme-fifa #${PANEL_ID}.gf-panel-finish--gold,
    html.gf-card-theme-fifa .Popover-message.gf-hc-finish--gold {
      --gf-fifa-ink: #2A2008;
      --gf-fifa-muted: #7A6520;
      --gf-fifa-border: #C9A227;
      --gf-fifa-ovr-top: #FFE28A;
      --gf-fifa-ovr-bot: #C9A227;
      --gf-fifa-ovr-ink: #2A2008;
      --gf-fifa-stat: rgba(201, 162, 39, 0.22);
      --gf-fifa-chip: rgba(201, 162, 39, 0.28);
      background: linear-gradient(165deg, #FFE9A8 0%, #E8C547 42%, #C9A227 100%) !important;
      border-color: var(--gf-fifa-border) !important;
      color: var(--gf-fifa-ink);
      box-shadow: inset 0 1px 0 rgba(255, 248, 220, 0.65), 0 2px 8px rgba(120, 90, 20, 0.16) !important;
    }

    html.gf-card-theme-fifa #${PANEL_ID}.gf-panel-finish--totw,
    html.gf-card-theme-fifa .Popover-message.gf-hc-finish--totw {
      --gf-fifa-ink: #F5F5F5;
      --gf-fifa-muted: #B0B0B0;
      --gf-fifa-border: #E03E52;
      --gf-fifa-ovr-top: #F0D060;
      --gf-fifa-ovr-bot: #C9A227;
      --gf-fifa-ovr-ink: #1A1405;
      --gf-fifa-stat: rgba(224, 62, 82, 0.22);
      --gf-fifa-chip: rgba(224, 62, 82, 0.28);
      background: linear-gradient(165deg, #3A3A3A 0%, #1E1E1E 50%, #121212 100%) !important;
      border-color: var(--gf-fifa-border) !important;
      color: var(--gf-fifa-ink);
      box-shadow: inset 0 0 0 1px rgba(224, 62, 82, 0.35), 0 2px 10px rgba(0, 0, 0, 0.35) !important;
    }

    html.gf-card-theme-fifa #${PANEL_ID}.gf-panel-finish--toty,
    html.gf-card-theme-fifa .Popover-message.gf-hc-finish--toty {
      --gf-fifa-ink: #E8F0FF;
      --gf-fifa-muted: #9BB4DE;
      --gf-fifa-border: #3B7AFF;
      --gf-fifa-ovr-top: #7EB0FF;
      --gf-fifa-ovr-bot: #2A5FD4;
      --gf-fifa-ovr-ink: #0A1630;
      --gf-fifa-stat: rgba(59, 122, 255, 0.28);
      --gf-fifa-chip: rgba(59, 122, 255, 0.32);
      background: linear-gradient(165deg, #1A3A6E 0%, #0B1B3D 55%, #071228 100%) !important;
      border-color: var(--gf-fifa-border) !important;
      color: var(--gf-fifa-ink);
      box-shadow: inset 0 0 0 1px rgba(59, 122, 255, 0.4), 0 2px 10px rgba(8, 20, 50, 0.4) !important;
    }

    html.gf-card-theme-fifa #${PANEL_ID}.gf-panel-finish--icon,
    html.gf-card-theme-fifa .Popover-message.gf-hc-finish--icon {
      --gf-fifa-ink: #F5E6C8;
      --gf-fifa-muted: #C4B08A;
      --gf-fifa-border: #F3D688;
      --gf-fifa-ovr-top: #F3D688;
      --gf-fifa-ovr-bot: #B8944A;
      --gf-fifa-ovr-ink: #2A1A45;
      --gf-fifa-stat: rgba(180, 120, 255, 0.22);
      --gf-fifa-chip: rgba(243, 214, 136, 0.28);
      background: linear-gradient(165deg, #4A2A7A 0%, #2A1A4A 50%, #1A0F30 100%) !important;
      border-color: var(--gf-fifa-border) !important;
      color: var(--gf-fifa-ink);
      box-shadow: inset 0 0 0 1px rgba(243, 214, 136, 0.35), 0 2px 10px rgba(30, 15, 60, 0.4) !important;
    }

    html.gf-card-theme-fifa #${PANEL_ID}.gf-panel-finish--founder,
    html.gf-card-theme-fifa .Popover-message.gf-hc-finish--founder {
      --gf-fifa-ink: #FFE4EC;
      --gf-fifa-muted: #E0A0B0;
      --gf-fifa-border: #FF5A7A;
      --gf-fifa-ovr-top: #FF8AA0;
      --gf-fifa-ovr-bot: #D43055;
      --gf-fifa-ovr-ink: #3A0A18;
      --gf-fifa-stat: rgba(255, 90, 122, 0.28);
      --gf-fifa-chip: rgba(255, 90, 122, 0.32);
      background: linear-gradient(165deg, #5A2030 0%, #3A0A18 55%, #250610 100%) !important;
      border-color: var(--gf-fifa-border) !important;
      color: var(--gf-fifa-ink);
      box-shadow: inset 0 0 0 1px rgba(255, 90, 122, 0.4), 0 2px 10px rgba(40, 8, 18, 0.4) !important;
    }

    html.gf-card-theme-fifa #${PANEL_ID} .gf-panel__head {
      border-bottom-color: color-mix(in srgb, var(--gf-fifa-border, #8B5A2B) 45%, transparent) !important;
      background: linear-gradient(
        180deg,
        color-mix(in srgb, var(--gf-fifa-ovr-top, #D4A574) 22%, transparent),
        transparent
      ) !important;
    }

    html.gf-card-theme-fifa #${PANEL_ID} .gf-panel__name,
    html.gf-card-theme-fifa #${PANEL_ID} .gf-stat__value,
    html.gf-card-theme-fifa #${PANEL_ID} .gf-attrs,
    html.gf-card-theme-fifa #${PANEL_ID} .gf-attrs__value,
    html.gf-card-theme-fifa #${HOVERCARD_BLOCK_ID} .gf-hc__stat-value {
      color: var(--gf-fifa-ink, inherit) !important;
    }

    html.gf-card-theme-fifa #${PANEL_ID} .gf-panel__blurb,
    html.gf-card-theme-fifa #${PANEL_ID} .gf-stat__key,
    html.gf-card-theme-fifa #${PANEL_ID} .gf-attrs__label,
    html.gf-card-theme-fifa #${HOVERCARD_BLOCK_ID} .gf-hc__blurb,
    html.gf-card-theme-fifa #${HOVERCARD_BLOCK_ID} .gf-hc__stat-key {
      color: var(--gf-fifa-muted, inherit) !important;
    }

    html.gf-card-theme-fifa #${PANEL_ID} .gf-panel__ovr,
    html.gf-card-theme-fifa #${HOVERCARD_BLOCK_ID} .gf-hc__ovr {
      background: linear-gradient(180deg, var(--gf-fifa-ovr-top), var(--gf-fifa-ovr-bot)) !important;
      color: var(--gf-fifa-ovr-ink) !important;
      box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, 0.35),
        0 0 0 1px color-mix(in srgb, var(--gf-fifa-border) 55%, #000) !important;
      text-shadow: none !important;
    }

    html.gf-card-theme-fifa #${PANEL_ID} .gf-panel__ovr-value,
    html.gf-card-theme-fifa #${HOVERCARD_BLOCK_ID} .gf-hc__ovr-value {
      text-shadow: none !important;
      color: inherit !important;
    }

    html.gf-card-theme-fifa #${PANEL_ID} .gf-chip,
    html.gf-card-theme-fifa #${HOVERCARD_BLOCK_ID} .gf-chip,
    html.gf-card-theme-fifa .gf-playstyle.is-plus {
      box-shadow: none !important;
      border-color: color-mix(in srgb, var(--gf-fifa-border) 70%, transparent) !important;
      background: var(--gf-fifa-chip) !important;
      color: var(--gf-fifa-ink) !important;
    }

    html.gf-card-theme-fifa .gf-playstyle:not(.is-plus) {
      border-color: color-mix(in srgb, var(--gf-fifa-border) 40%, transparent) !important;
      background: color-mix(in srgb, var(--gf-fifa-ink) 6%, transparent) !important;
      color: var(--gf-fifa-ink) !important;
    }

    html.gf-card-theme-fifa #${PANEL_ID} .gf-stat,
    html.gf-card-theme-fifa #${HOVERCARD_BLOCK_ID} .gf-hc__stat {
      box-shadow: none !important;
      border-color: color-mix(in srgb, var(--gf-fifa-border) 40%, transparent) !important;
      background: var(--gf-fifa-stat) !important;
    }

    html.gf-card-theme-fifa #${PANEL_ID} .gf-attrs {
      box-shadow: none !important;
      border-color: color-mix(in srgb, var(--gf-fifa-border) 35%, transparent) !important;
      background: var(--gf-fifa-stat) !important;
    }

    html.gf-card-theme-fifa #${HOVERCARD_BLOCK_ID} {
      border-top-color: color-mix(in srgb, var(--gf-fifa-border) 50%, transparent) !important;
      background: linear-gradient(
        180deg,
        color-mix(in srgb, var(--gf-fifa-ovr-top, transparent) 18%, transparent),
        transparent 80%
      ) !important;
      box-shadow: none !important;
    }

    html.gf-card-theme-fifa #${PANEL_ID} .gf-btn-link {
      border-color: color-mix(in srgb, var(--gf-fifa-border) 45%, transparent) !important;
      background: color-mix(in srgb, var(--gf-fifa-ink) 8%, transparent) !important;
      color: var(--gf-fifa-ink) !important;
    }

    html.gf-card-theme-fifa #${PANEL_ID} .gf-btn-link:hover {
      background: color-mix(in srgb, var(--gf-fifa-ink) 14%, transparent) !important;
    }

    html.gf-card-theme-fifa #${HOVERCARD_BLOCK_ID} .gf-hc__link {
      border-color: color-mix(in srgb, var(--gf-fifa-border) 45%, transparent) !important;
      background: color-mix(in srgb, var(--gf-fifa-ink) 8%, transparent) !important;
      color: var(--gf-fifa-ink) !important;
    }

    html.gf-card-theme-fifa #${PANEL_ID} .gf-btn-link--primary,
    html.gf-card-theme-fifa #${HOVERCARD_BLOCK_ID} .gf-hc__link--primary {
      border-color: transparent !important;
      background: linear-gradient(180deg, var(--gf-fifa-ovr-top), var(--gf-fifa-ovr-bot)) !important;
      color: var(--gf-fifa-ovr-ink) !important;
      box-shadow: none !important;
      filter: none !important;
    }

    html.gf-card-theme-fifa #${PANEL_ID} .gf-btn-link--primary:hover,
    html.gf-card-theme-fifa #${HOVERCARD_BLOCK_ID} .gf-hc__link--primary:hover {
      filter: brightness(1.05) !important;
      background: linear-gradient(180deg, var(--gf-fifa-ovr-top), var(--gf-fifa-ovr-bot)) !important;
    }

    /* Neon theme: dark glass + finish-colored neon glow */
    html.gf-card-theme-neon #${PANEL_ID},
    html.gf-card-theme-neon .Popover-message.gf-hc-themed {
      --gf-neon: #FF9F43;
      --gf-neon-ink: #FFE8D0;
      --gf-neon-muted: #B89878;
      --gf-panel-outer-glow: 0 0 0 transparent !important;
      --gf-panel-ring: 0 0 0 transparent !important;
      --gf-panel-ovr-glow: none !important;
      --gf-hc-outer-glow: 0 0 0 transparent !important;
      --gf-hc-ring: 0 0 0 transparent !important;
      --gf-hc-ovr-glow: none !important;
      --gf-hc-block-glow: none !important;
      --gf-hc-shine-opacity: 0 !important;
      animation: none !important;
      color: var(--gf-neon-ink);
      border-color: color-mix(in srgb, var(--gf-neon) 75%, #fff) !important;
      background:
        radial-gradient(120% 80% at 0% 0%, color-mix(in srgb, var(--gf-neon) 28%, transparent), transparent 55%),
        radial-gradient(90% 70% at 100% 100%, color-mix(in srgb, var(--gf-neon) 18%, transparent), transparent 60%),
        linear-gradient(165deg, #161622 0%, #0B0B14 100%) !important;
      box-shadow:
        0 0 0 1px color-mix(in srgb, var(--gf-neon) 55%, transparent),
        0 0 18px color-mix(in srgb, var(--gf-neon) 45%, transparent),
        0 0 42px color-mix(in srgb, var(--gf-neon) 22%, transparent),
        inset 0 0 28px color-mix(in srgb, var(--gf-neon) 10%, transparent) !important;
    }

    html.gf-card-theme-neon #${PANEL_ID}.gf-panel-finish--bronze,
    html.gf-card-theme-neon .Popover-message.gf-hc-finish--bronze {
      --gf-neon: #FF9F43;
      --gf-neon-ink: #FFE8D0;
      --gf-neon-muted: #C4A07A;
    }

    html.gf-card-theme-neon #${PANEL_ID}.gf-panel-finish--silver,
    html.gf-card-theme-neon .Popover-message.gf-hc-finish--silver {
      --gf-neon: #B8C4FF;
      --gf-neon-ink: #EEF1FF;
      --gf-neon-muted: #9AA3C8;
    }

    html.gf-card-theme-neon #${PANEL_ID}.gf-panel-finish--gold,
    html.gf-card-theme-neon .Popover-message.gf-hc-finish--gold {
      --gf-neon: #FFD60A;
      --gf-neon-ink: #FFF6C8;
      --gf-neon-muted: #C9B45A;
    }

    html.gf-card-theme-neon #${PANEL_ID}.gf-panel-finish--totw,
    html.gf-card-theme-neon .Popover-message.gf-hc-finish--totw {
      --gf-neon: #FF2E63;
      --gf-neon-ink: #FFD6E0;
      --gf-neon-muted: #D08098;
    }

    html.gf-card-theme-neon #${PANEL_ID}.gf-panel-finish--toty,
    html.gf-card-theme-neon .Popover-message.gf-hc-finish--toty {
      --gf-neon: #00F0FF;
      --gf-neon-ink: #D7FBFF;
      --gf-neon-muted: #74B8C4;
    }

    html.gf-card-theme-neon #${PANEL_ID}.gf-panel-finish--icon,
    html.gf-card-theme-neon .Popover-message.gf-hc-finish--icon {
      --gf-neon: #C77DFF;
      --gf-neon-ink: #F3E6FF;
      --gf-neon-muted: #B090D0;
    }

    html.gf-card-theme-neon #${PANEL_ID}.gf-panel-finish--founder,
    html.gf-card-theme-neon .Popover-message.gf-hc-finish--founder {
      --gf-neon: #FF6BCB;
      --gf-neon-ink: #FFE3F4;
      --gf-neon-muted: #D090B8;
    }

    html.gf-card-theme-neon #${PANEL_ID} .gf-panel-theme-fx,
    html.gf-card-theme-neon .Popover-message.gf-hc-themed > .gf-hc-theme-fx {
      display: block !important;
    }

    html.gf-card-theme-neon .gf-panel-theme-fx__shine,
    html.gf-card-theme-neon .gf-hc-theme-fx__shine {
      display: block !important;
      animation: none !important;
      background: radial-gradient(
        60% 50% at 50% 0%,
        color-mix(in srgb, var(--gf-neon) 35%, transparent),
        transparent 70%
      ) !important;
      background-size: 100% 100% !important;
      background-position: 0 0 !important;
      opacity: 0.7 !important;
    }

    html.gf-card-theme-neon #${PANEL_ID}.gf-panel-finish--totw,
    html.gf-card-theme-neon #${PANEL_ID}.gf-panel-finish--toty,
    html.gf-card-theme-neon #${PANEL_ID}.gf-panel-finish--icon,
    html.gf-card-theme-neon #${PANEL_ID}.gf-panel-finish--founder,
    html.gf-card-theme-neon .Popover-message.gf-hc-finish--totw,
    html.gf-card-theme-neon .Popover-message.gf-hc-finish--toty,
    html.gf-card-theme-neon .Popover-message.gf-hc-finish--icon,
    html.gf-card-theme-neon .Popover-message.gf-hc-finish--founder {
      animation: gf-neon-pulse 2.6s ease-in-out infinite !important;
    }

    @keyframes gf-neon-pulse {
      0%, 100% {
        box-shadow:
          0 0 0 1px color-mix(in srgb, var(--gf-neon) 55%, transparent),
          0 0 16px color-mix(in srgb, var(--gf-neon) 40%, transparent),
          0 0 36px color-mix(in srgb, var(--gf-neon) 18%, transparent),
          inset 0 0 24px color-mix(in srgb, var(--gf-neon) 8%, transparent);
      }
      50% {
        box-shadow:
          0 0 0 1px color-mix(in srgb, var(--gf-neon) 80%, transparent),
          0 0 26px color-mix(in srgb, var(--gf-neon) 65%, transparent),
          0 0 56px color-mix(in srgb, var(--gf-neon) 32%, transparent),
          inset 0 0 34px color-mix(in srgb, var(--gf-neon) 14%, transparent);
      }
    }

    html.gf-card-theme-neon #${PANEL_ID} .gf-panel__head {
      border-bottom-color: color-mix(in srgb, var(--gf-neon) 35%, transparent) !important;
      background: linear-gradient(
        180deg,
        color-mix(in srgb, var(--gf-neon) 16%, transparent),
        transparent
      ) !important;
    }

    html.gf-card-theme-neon #${PANEL_ID} .gf-panel__name,
    html.gf-card-theme-neon #${PANEL_ID} .gf-stat__value,
    html.gf-card-theme-neon #${PANEL_ID} .gf-attrs,
    html.gf-card-theme-neon #${PANEL_ID} .gf-attrs__value,
    html.gf-card-theme-neon #${HOVERCARD_BLOCK_ID} .gf-hc__stat-value {
      color: var(--gf-neon-ink) !important;
    }

    html.gf-card-theme-neon #${PANEL_ID} .gf-panel__blurb,
    html.gf-card-theme-neon #${PANEL_ID} .gf-stat__key,
    html.gf-card-theme-neon #${PANEL_ID} .gf-attrs__label,
    html.gf-card-theme-neon #${HOVERCARD_BLOCK_ID} .gf-hc__blurb,
    html.gf-card-theme-neon #${HOVERCARD_BLOCK_ID} .gf-hc__stat-key {
      color: var(--gf-neon-muted) !important;
    }

    html.gf-card-theme-neon #${PANEL_ID} .gf-panel__ovr,
    html.gf-card-theme-neon #${HOVERCARD_BLOCK_ID} .gf-hc__ovr {
      background: color-mix(in srgb, var(--gf-neon) 18%, #0A0A12) !important;
      color: var(--gf-neon) !important;
      box-shadow:
        0 0 0 1px color-mix(in srgb, var(--gf-neon) 70%, transparent),
        0 0 14px color-mix(in srgb, var(--gf-neon) 55%, transparent),
        inset 0 0 12px color-mix(in srgb, var(--gf-neon) 18%, transparent) !important;
      text-shadow: 0 0 10px color-mix(in srgb, var(--gf-neon) 70%, transparent) !important;
    }

    html.gf-card-theme-neon #${PANEL_ID} .gf-panel__ovr-value,
    html.gf-card-theme-neon #${PANEL_ID} .gf-panel__ovr-label,
    html.gf-card-theme-neon #${HOVERCARD_BLOCK_ID} .gf-hc__ovr-value,
    html.gf-card-theme-neon #${HOVERCARD_BLOCK_ID} .gf-hc__ovr-label {
      color: inherit !important;
      text-shadow: inherit !important;
    }

    html.gf-card-theme-neon #${PANEL_ID} .gf-chip,
    html.gf-card-theme-neon #${HOVERCARD_BLOCK_ID} .gf-chip,
    html.gf-card-theme-neon .gf-playstyle.is-plus {
      border-color: color-mix(in srgb, var(--gf-neon) 65%, transparent) !important;
      background: color-mix(in srgb, var(--gf-neon) 14%, transparent) !important;
      color: var(--gf-neon-ink) !important;
      box-shadow: 0 0 10px color-mix(in srgb, var(--gf-neon) 28%, transparent) !important;
    }

    html.gf-card-theme-neon .gf-playstyle:not(.is-plus) {
      border-color: color-mix(in srgb, var(--gf-neon) 35%, transparent) !important;
      background: color-mix(in srgb, var(--gf-neon) 8%, transparent) !important;
      color: var(--gf-neon-ink) !important;
    }

    html.gf-card-theme-neon #${PANEL_ID} .gf-stat,
    html.gf-card-theme-neon #${HOVERCARD_BLOCK_ID} .gf-hc__stat,
    html.gf-card-theme-neon #${PANEL_ID} .gf-attrs {
      border-color: color-mix(in srgb, var(--gf-neon) 35%, transparent) !important;
      background: color-mix(in srgb, var(--gf-neon) 10%, #0A0A12) !important;
      box-shadow: inset 0 0 12px color-mix(in srgb, var(--gf-neon) 8%, transparent) !important;
    }

    html.gf-card-theme-neon #${HOVERCARD_BLOCK_ID} {
      border-top-color: color-mix(in srgb, var(--gf-neon) 40%, transparent) !important;
      background: linear-gradient(
        180deg,
        color-mix(in srgb, var(--gf-neon) 14%, transparent),
        transparent 85%
      ) !important;
      box-shadow: none !important;
    }

    html.gf-card-theme-neon #${PANEL_ID} .gf-btn-link,
    html.gf-card-theme-neon #${HOVERCARD_BLOCK_ID} .gf-hc__link {
      border-color: color-mix(in srgb, var(--gf-neon) 45%, transparent) !important;
      background: color-mix(in srgb, var(--gf-neon) 10%, transparent) !important;
      color: var(--gf-neon-ink) !important;
    }

    html.gf-card-theme-neon #${PANEL_ID} .gf-btn-link:hover,
    html.gf-card-theme-neon #${HOVERCARD_BLOCK_ID} .gf-hc__link:hover {
      background: color-mix(in srgb, var(--gf-neon) 18%, transparent) !important;
    }

    html.gf-card-theme-neon #${PANEL_ID} .gf-btn-link--primary,
    html.gf-card-theme-neon #${HOVERCARD_BLOCK_ID} .gf-hc__link--primary {
      border-color: transparent !important;
      background: color-mix(in srgb, var(--gf-neon) 22%, #0A0A12) !important;
      color: var(--gf-neon) !important;
      box-shadow:
        0 0 0 1px color-mix(in srgb, var(--gf-neon) 60%, transparent),
        0 0 16px color-mix(in srgb, var(--gf-neon) 40%, transparent) !important;
      text-shadow: 0 0 8px color-mix(in srgb, var(--gf-neon) 50%, transparent);
      filter: none !important;
    }

    html.gf-card-theme-neon #${PANEL_ID} .gf-btn-link--primary:hover,
    html.gf-card-theme-neon #${HOVERCARD_BLOCK_ID} .gf-hc__link--primary:hover {
      filter: brightness(1.08) !important;
      background: color-mix(in srgb, var(--gf-neon) 28%, #0A0A12) !important;
    }

    @media (prefers-reduced-motion: reduce) {
      html.gf-card-theme-neon #${PANEL_ID},
      html.gf-card-theme-neon .Popover-message.gf-hc-themed {
        animation: none !important;
      }
    }

    /* GitHub theme: Primer tokens, no glow / shine / finish flash */
    html.gf-card-theme-github #${PANEL_ID},
    html.gf-card-theme-github .Popover-message.gf-hc-themed {
      --gf-panel-outer-glow: 0 0 0 transparent !important;
      --gf-panel-ring: 0 0 0 transparent !important;
      --gf-panel-ovr-glow: none !important;
      --gf-hc-outer-glow: 0 0 0 transparent !important;
      --gf-hc-ring: 0 0 0 transparent !important;
      --gf-hc-ovr-glow: none !important;
      --gf-hc-block-glow: none !important;
      --gf-hc-shine-opacity: 0 !important;
      animation: none !important;
      color: var(--fgColor-default, var(--color-fg-default, #1f2328));
      border-color: var(--borderColor-default, var(--color-border-default, #d0d7de)) !important;
      border-radius: 6px !important;
      background: var(--bgColor-default, var(--color-canvas-default, #fff)) !important;
      box-shadow: none !important;
    }

    html.gf-card-theme-github #${PANEL_ID} .gf-panel-theme-fx,
    html.gf-card-theme-github .Popover-message.gf-hc-themed > .gf-hc-theme-fx,
    html.gf-card-theme-github .gf-panel-theme-fx__shine,
    html.gf-card-theme-github .gf-hc-theme-fx__shine {
      display: none !important;
    }

    html.gf-card-theme-github #${PANEL_ID} .gf-panel__head {
      background: transparent !important;
      border-bottom-color: var(--borderColor-muted, var(--color-border-muted, rgba(27,31,36,0.15))) !important;
      padding: 12px;
    }

    html.gf-card-theme-github #${PANEL_ID} .gf-panel__name,
    html.gf-card-theme-github #${PANEL_ID} .gf-stat__value,
    html.gf-card-theme-github #${PANEL_ID} .gf-attrs,
    html.gf-card-theme-github #${PANEL_ID} .gf-attrs__value,
    html.gf-card-theme-github #${HOVERCARD_BLOCK_ID} .gf-hc__stat-value {
      color: var(--fgColor-default, var(--color-fg-default, #1f2328)) !important;
    }

    html.gf-card-theme-github #${PANEL_ID} .gf-panel__blurb,
    html.gf-card-theme-github #${PANEL_ID} .gf-stat__key,
    html.gf-card-theme-github #${PANEL_ID} .gf-attrs__label,
    html.gf-card-theme-github #${HOVERCARD_BLOCK_ID} .gf-hc__blurb,
    html.gf-card-theme-github #${HOVERCARD_BLOCK_ID} .gf-hc__stat-key {
      color: var(--fgColor-muted, var(--color-fg-muted, #656d76)) !important;
    }

    html.gf-card-theme-github #${PANEL_ID} .gf-panel__ovr,
    html.gf-card-theme-github #${HOVERCARD_BLOCK_ID} .gf-hc__ovr {
      background: color-mix(
        in srgb,
        var(--gf-finish-accent, #656d76) 20%,
        var(--bgColor-muted, var(--color-canvas-subtle, #f6f8fa))
      ) !important;
      color: var(--gf-finish-accent, var(--fgColor-default, #1f2328)) !important;
      border: 1px solid color-mix(
        in srgb,
        var(--gf-finish-accent, #656d76) 70%,
        var(--borderColor-default, var(--color-border-default, #d0d7de))
      ) !important;
      border-radius: 6px !important;
      box-shadow: none !important;
      min-width: 48px;
      padding: 6px 8px;
    }

    html.gf-card-theme-github #${PANEL_ID} .gf-panel__ovr-value,
    html.gf-card-theme-github #${HOVERCARD_BLOCK_ID} .gf-hc__ovr-value {
      text-shadow: none !important;
      font-weight: 700;
      letter-spacing: -0.02em;
      color: var(--gf-finish-accent, var(--fgColor-default, #1f2328)) !important;
    }

    html.gf-card-theme-github #${PANEL_ID} .gf-panel__ovr-label,
    html.gf-card-theme-github #${HOVERCARD_BLOCK_ID} .gf-hc__ovr-label {
      opacity: 0.9;
      color: var(--gf-finish-accent, var(--fgColor-muted, #656d76)) !important;
      font-weight: 600;
    }

    html.gf-card-theme-github #${PANEL_ID} .gf-chip,
    html.gf-card-theme-github #${HOVERCARD_BLOCK_ID} .gf-chip,
    html.gf-card-theme-github .gf-playstyle.is-plus {
      box-shadow: none !important;
      border-radius: 2em !important;
      border-color: var(--borderColor-default, var(--color-border-default, #d0d7de)) !important;
      background: var(--bgColor-muted, var(--color-canvas-subtle, #f6f8fa)) !important;
      color: var(--fgColor-default, var(--color-fg-default, #1f2328)) !important;
    }

    html.gf-card-theme-github #${PANEL_ID} .gf-chip--finish,
    html.gf-card-theme-github #${HOVERCARD_BLOCK_ID} .gf-chip--finish {
      border-color: color-mix(
        in srgb,
        var(--gf-finish-accent, #656d76) 28%,
        var(--borderColor-default, #d0d7de)
      ) !important;
      background: color-mix(
        in srgb,
        var(--gf-finish-accent, #656d76) 8%,
        var(--bgColor-muted, #f6f8fa)
      ) !important;
    }

    html.gf-card-theme-github #${PANEL_ID} .gf-stat,
    html.gf-card-theme-github #${HOVERCARD_BLOCK_ID} .gf-hc__stat {
      box-shadow: none !important;
      border-color: var(--borderColor-muted, var(--color-border-muted, rgba(27,31,36,0.15))) !important;
      background: var(--bgColor-muted, var(--color-canvas-subtle, #f6f8fa)) !important;
      border-radius: 6px !important;
    }

    html.gf-card-theme-github #${PANEL_ID} .gf-attrs {
      box-shadow: none !important;
      border-color: var(--borderColor-muted, var(--color-border-muted, rgba(27,31,36,0.15))) !important;
      background: var(--bgColor-muted, var(--color-canvas-subtle, #f6f8fa)) !important;
      border-radius: 6px !important;
    }

    html.gf-card-theme-github #${HOVERCARD_BLOCK_ID} {
      border-top-color: var(--borderColor-muted, var(--color-border-muted, rgba(27,31,36,0.15))) !important;
      background: transparent !important;
      box-shadow: none !important;
    }

    html.gf-card-theme-github #${PANEL_ID} .gf-btn-link,
    html.gf-card-theme-github #${HOVERCARD_BLOCK_ID} .gf-hc__link {
      border-color: var(--borderColor-default, var(--color-border-default, #d0d7de)) !important;
      background: var(--button-default-bgColor-rest, var(--color-btn-bg, #f6f8fa)) !important;
      color: var(--fgColor-default, var(--color-fg-default, #1f2328)) !important;
      border-radius: 6px !important;
      box-shadow: none !important;
      filter: none !important;
    }

    html.gf-card-theme-github #${PANEL_ID} .gf-btn-link:hover,
    html.gf-card-theme-github #${HOVERCARD_BLOCK_ID} .gf-hc__link:hover {
      background: var(--button-default-bgColor-hover, var(--color-btn-hover-bg, #f3f4f6)) !important;
      border-color: var(--button-default-borderColor-hover, var(--color-btn-hover-border, #d0d7de)) !important;
      filter: none !important;
    }

    html.gf-card-theme-github #${PANEL_ID} .gf-btn-link--primary,
    html.gf-card-theme-github #${HOVERCARD_BLOCK_ID} .gf-hc__link--primary {
      border-color: var(--button-primary-borderColor-rest, rgba(31, 35, 40, 0.15)) !important;
      background: var(--button-primary-bgColor-rest, var(--color-btn-primary-bg, #1f883d)) !important;
      color: var(--button-primary-fgColor-rest, var(--color-btn-primary-text, #fff)) !important;
      box-shadow: none !important;
      filter: none !important;
    }

    html.gf-card-theme-github #${PANEL_ID} .gf-btn-link--primary:hover,
    html.gf-card-theme-github #${HOVERCARD_BLOCK_ID} .gf-hc__link--primary:hover {
      background: var(--button-primary-bgColor-hover, var(--color-btn-primary-hover-bg, #1a7f37)) !important;
      border-color: var(--button-primary-borderColor-hover, rgba(31, 35, 40, 0.15)) !important;
      filter: none !important;
    }

    html.gf-card-theme-github #${PANEL_ID} .gf-playstyle,
    html.gf-card-theme-github #${HOVERCARD_BLOCK_ID} .gf-playstyle {
      border-color: var(--borderColor-muted, rgba(27,31,36,0.15)) !important;
      background: var(--bgColor-muted, #f6f8fa) !important;
      color: var(--fgColor-default, #1f2328) !important;
      box-shadow: none !important;
    }

    #gf-user-menu-item .gf-nav-dot {
      width: 7px;
      height: 7px;
      border-radius: 50%;
      background: var(--fgColor-muted, #8b949e);
      display: inline-block;
      flex-shrink: 0;
    }

    #gf-user-menu-item .gf-nav-dot.is-on {
      background: #3fb950;
    }

    .gf-settings-panel {
      position: fixed;
      z-index: 10000;
      width: 360px;
      max-width: calc(100vw - 16px);
      border-radius: 12px;
      border: 1px solid var(--borderColor-default, var(--color-border-default, #d0d7de));
      background: var(--bgColor-default, var(--color-canvas-default, #fff));
      box-shadow: 0 16px 40px rgba(1,4,9,0.28);
      font-family: var(--gf-font);
      color: var(--fgColor-default, var(--color-fg-default, #1f2328));
    }

    .gf-settings-panel[hidden] { display: none !important; }

    .gf-settings-panel__header {
      display: flex;
      justify-content: space-between;
      gap: 12px;
      padding: 14px 14px 10px;
      border-bottom: 1px solid var(--borderColor-muted, rgba(27,31,36,0.08));
    }

    .gf-settings-panel__title {
      font-size: 15px;
      font-weight: 700;
    }

    .gf-settings-panel__subtitle {
      margin-top: 2px;
      font-size: 12px;
      color: var(--fgColor-muted, var(--color-fg-muted, #656d76));
    }

    .gf-settings-panel__version {
      margin-top: 4px;
      font-size: 11px;
      font-weight: 600;
      font-variant-numeric: tabular-nums;
      letter-spacing: 0.02em;
      color: var(--fgColor-muted, var(--color-fg-muted, #656d76));
    }

    .gf-cache-stats {
      margin: 0 0 12px;
      padding: 10px 11px;
      border-radius: 8px;
      border: 1px solid var(--borderColor-muted, rgba(27,31,36,0.08));
      background: var(--bgColor-muted, var(--color-canvas-subtle, #f6f8fa));
    }

    .gf-cache-stats__count {
      font-size: 13px;
      font-weight: 600;
      color: var(--fgColor-default, var(--color-fg-default, #1f2328));
    }

    .gf-cache-stats__storage {
      margin: 4px 0 0;
      font-size: 12px;
      font-variant-numeric: tabular-nums;
      color: var(--fgColor-muted, var(--color-fg-muted, #656d76));
    }

    .gf-cache-stats__bar {
      margin-top: 8px;
      height: 8px;
      border-radius: 999px;
      overflow: hidden;
      background: color-mix(in srgb, var(--fgColor-muted, #656d76) 16%, transparent);
    }

    .gf-cache-stats__bar-fill {
      height: 100%;
      width: 100%;
      border-radius: inherit;
      background: #3fb950;
      transition: width 0.25s ease, background 0.25s ease;
    }

    .gf-cache-stats__bar.is-warn .gf-cache-stats__bar-fill {
      background: #d29922;
    }

    .gf-cache-stats__bar.is-full .gf-cache-stats__bar-fill {
      background: #cf222e;
    }

    .gf-cache-stats__hint {
      margin: 6px 0 0;
    }

    .gf-settings-panel__close {
      border: 0;
      background: transparent;
      font-size: 20px;
      line-height: 1;
      cursor: pointer;
      color: var(--fgColor-muted, #656d76);
    }

    .gf-settings-panel__section {
      padding: 12px 14px;
    }

    .gf-settings-panel__section-title {
      margin-bottom: 8px;
      font-size: 11px;
      font-weight: 700;
      letter-spacing: 0.06em;
      text-transform: uppercase;
      color: var(--fgColor-muted, #656d76);
    }

    .gf-field {
      display: grid;
      gap: 6px;
      margin-bottom: 8px;
    }

    .gf-field__label {
      font-size: 12px;
      font-weight: 600;
    }

    .gf-field input[type="number"],
    .gf-field select {
      width: 100%;
      padding: 7px 9px;
      border-radius: 6px;
      border: 1px solid var(--borderColor-default, #d0d7de);
      background: var(--bgColor-default, #fff);
      color: inherit;
    }

    .gf-hint {
      margin: 0 0 8px;
      font-size: 12px;
      color: var(--fgColor-muted, #656d76);
      line-height: 1.35;
    }

    .gf-switch {
      display: flex;
      align-items: center;
      gap: 10px;
      cursor: pointer;
      font-size: 13px;
      font-weight: 600;
    }

    .gf-switch input { accent-color: #238636; }

    .gf-pill {
      margin-left: auto;
      font-size: 11px;
      font-weight: 700;
      padding: 2px 7px;
      border-radius: 999px;
      background: var(--bgColor-muted, #f6f8fa);
      color: var(--fgColor-muted, #656d76);
    }

    .gf-pill.is-on {
      background: rgba(46,160,67,0.15);
      color: #1a7f37;
    }

    .gf-row {
      display: flex;
      align-items: center;
      gap: 10px;
    }

    .gf-settings-panel__divider {
      height: 1px;
      background: var(--borderColor-muted, rgba(27,31,36,0.08));
      margin: 0 14px;
    }

    .gf-settings-panel__footer {
      padding: 12px 14px 14px;
    }

    .gf-settings-panel__footer-actions {
      display: flex;
      flex-wrap: wrap;
      gap: 8px;
    }

    .gf-btn {
      appearance: none;
      border: 1px solid var(--borderColor-default, #d0d7de);
      background: var(--bgColor-muted, #f6f8fa);
      color: inherit;
      border-radius: 6px;
      padding: 7px 10px;
      font-size: 12px;
      font-weight: 600;
      cursor: pointer;
    }

    .gf-btn--ghost { background: transparent; }
    .gf-btn--danger {
      border-color: rgba(209,36,47,0.35);
      color: #cf222e;
      background: rgba(209,36,47,0.06);
    }
    .gf-btn--green {
      border-color: transparent;
      background: #238636;
      color: #fff;
    }

    .gf-cache-status {
      min-height: 1.2em;
      margin: 6px 0 0;
      font-size: 12px;
      color: var(--fgColor-muted, #656d76);
    }

    .gf-settings-panel__footer-divider {
      height: 1px;
      margin: 12px 0;
      background: var(--borderColor-muted, rgba(27,31,36,0.08));
    }

    .gf-settings-panel__repo {
      display: grid;
      gap: 2px;
      text-decoration: none !important;
      color: inherit !important;
    }

    .gf-settings-panel__repo-title { font-size: 13px; font-weight: 700; }
    .gf-settings-panel__repo-desc {
      font-size: 12px;
      color: var(--fgColor-muted, #656d76);
    }

    @media (prefers-reduced-motion: reduce) {
      #${PANEL_ID}, #${HOVERCARD_BLOCK_ID}, .gf-btn-link { transition: none !important; }
    }
  `);

  function normalizeFinish(finish) {
    const key = String(finish || 'bronze').toLowerCase();
    return FINISH_KEYS.includes(key) ? key : 'bronze';
  }

  function applyFinishVars(el, finish) {
    const meta = finishMeta(finish);
    el.style.setProperty('--gf-finish-accent', meta.accent);
    el.style.setProperty('--gf-finish-ink', meta.ink);
    el.style.setProperty('--gf-finish-soft', meta.soft);
    el.style.setProperty('--gf-finish-glow', meta.glow);
    el.style.setProperty('--gf-finish-deep', meta.deep);
    el.style.setProperty('--gf-finish-shine', meta.shine);
  }

  function clearFinishClasses(el) {
    if (!el?.classList) return;
    el.classList.remove('gf-hc-themed');
    for (const cls of [...el.classList]) {
      if (FINISH_CLASS_RE.test(cls)) el.classList.remove(cls);
    }
  }

  function clearHovercardTheme(popover) {
    const message = popover?.querySelector?.('.Popover-message') || popover;
    if (!(message instanceof HTMLElement)) return;
    clearFinishClasses(message);
    delete message.dataset.gfFinish;
    message.querySelector('.gf-hc-theme-fx')?.remove();
    for (const key of [
      '--gf-finish-accent',
      '--gf-finish-ink',
      '--gf-finish-soft',
      '--gf-finish-glow',
      '--gf-finish-deep',
      '--gf-finish-shine',
    ]) {
      message.style.removeProperty(key);
    }
  }

  function ensureHovercardThemeFx(message) {
    let fx = message.querySelector(':scope > .gf-hc-theme-fx');
    if (!fx) {
      fx = document.createElement('div');
      fx.className = 'gf-hc-theme-fx';
      fx.setAttribute('aria-hidden', 'true');
      message.insertBefore(fx, message.firstChild);
    }
    fx.innerHTML = '<div class="gf-hc-theme-fx__shine"></div>';
    return fx;
  }

  function applyHovercardTheme(popover, finish) {
    const message = popover?.querySelector?.('.Popover-message');
    if (!(message instanceof HTMLElement)) return;
    const key = normalizeFinish(finish);
    clearFinishClasses(message);
    message.classList.add('gf-hc-themed', `gf-hc-finish--${key}`);
    message.dataset.gfFinish = key;
    applyFinishVars(message, key);
    ensureHovercardThemeFx(message);
  }

  function renderStars(count) {
    const n = Math.max(0, Math.min(5, Number(count) || 0));
    return '★'.repeat(n) + '☆'.repeat(5 - n);
  }

  function buildProfilePanel(card) {
    const root = document.createElement('div');
    root.id = PANEL_ID;
    const finish = normalizeFinish(card.finish);
    root.classList.add(`gf-panel-finish--${finish}`);
    applyFinishVars(root, finish);
    root.dataset.gfFinish = finish;

    const report = card.report || {};
    const work = report.workRate || {};
    const playstyles = Array.isArray(report.playstyles) ? report.playstyles : [];
    const finishLabel = card.finishLabel || String(card.finish || '').toUpperCase();
    const cardUrl = `${SITE_BASE}/${encodeURIComponent(card.login)}`;
    const duelUrl = buildDuelUrl(card.login);
    const statsHtml = STAT_ORDER.map(
      ([key, label]) => `
        <div class="gf-stat">
          <span class="gf-stat__value">${escapeHtml(card.stats?.[key] ?? '—')}</span>
          <span class="gf-stat__key">${label}</span>
        </div>`
    ).join('');

    const playstylesHtml = playstyles.length
      ? `<div class="gf-playstyles" aria-label="${escapeHtml(t('playstyles'))}">
          ${playstyles
            .map(
              (ps) =>
                `<span class="gf-playstyle${ps.plus ? ' is-plus' : ''}" title="${escapeHtml(ps.reason || '')}">${escapeHtml(ps.name)}${ps.plus ? '+' : ''}</span>`
            )
            .join('')}
        </div>`
      : '';


    root.innerHTML = `
      <div class="gf-panel-theme-fx" aria-hidden="true"><div class="gf-panel-theme-fx__shine"></div></div>
      <div class="gf-panel__inner">
        <div class="gf-panel__head">
          <div class="gf-panel__ovr" title="${escapeHtml(t('overall'))}">
            <span class="gf-panel__ovr-value">${escapeHtml(card.overall)}</span>
            <span class="gf-panel__ovr-label">${escapeHtml(t('overall'))}</span>
          </div>
          <div class="gf-panel__meta">
            <div class="gf-panel__title-row">
              <span class="gf-panel__name">${escapeHtml(card.name || card.login)}</span>
              <span class="gf-chip">${escapeHtml(card.position || '—')}</span>
              <span class="gf-chip gf-chip--finish">${escapeHtml(finishLabel)}</span>
            </div>
            <p class="gf-panel__blurb">${escapeHtml(card.archetype || '')}${card.archetypeBlurb ? ` — ${escapeHtml(card.archetypeBlurb)}` : ''}</p>
          </div>
        </div>
        <div class="gf-panel__body">
          <div class="gf-stats">${statsHtml}</div>
          <div class="gf-attrs">
            <div class="gf-attrs__row"><span class="gf-attrs__label">${escapeHtml(t('skillMoves'))}</span><span class="gf-attrs__value">${escapeHtml(renderStars(report.skillMoves))}</span></div>
            <div class="gf-attrs__row"><span class="gf-attrs__label">${escapeHtml(t('weakFoot'))}</span><span class="gf-attrs__value">${escapeHtml(renderStars(report.weakFoot))}</span></div>
            <div class="gf-attrs__row"><span class="gf-attrs__label">${escapeHtml(t('workRate'))}</span><span class="gf-attrs__value">${escapeHtml(`${work.attack || '—'} / ${work.defense || '—'}`)}</span></div>
            <div class="gf-attrs__row"><span class="gf-attrs__label">${escapeHtml(t('style'))}</span><span class="gf-attrs__value">${escapeHtml(report.style || '—')}</span></div>
            ${
              card.topLanguage
                ? `<div class="gf-attrs__row"><span class="gf-attrs__label">${escapeHtml(t('language'))}</span><span class="gf-attrs__value">${escapeHtml(card.topLanguage)}</span></div>`
                : ''
            }
          </div>
          ${playstylesHtml}
          <div class="gf-actions">
            <a class="gf-btn-link gf-btn-link--primary" href="${escapeHtml(cardUrl)}" target="_blank" rel="noopener noreferrer">${escapeHtml(t('openReport'))}</a>
            <a class="gf-btn-link" href="${escapeHtml(duelUrl)}" target="_blank" rel="noopener noreferrer">${escapeHtml(t('duel'))}</a>
          </div>
        </div>
      </div>
    `;
    return root;
  }

  function buildLoadingPanel() {
    const root = document.createElement('div');
    root.id = PANEL_ID;
    root.dataset.gfState = 'loading';
    root.innerHTML = `
      <div class="gf-panel__inner gf-panel-skel" role="status" aria-busy="true" aria-label="${escapeHtml(t('loading'))}">
        <div class="gf-panel__head">
          <div class="gf-skel gf-skel--panel-ovr" aria-hidden="true"></div>
          <div class="gf-panel__meta">
            <div class="gf-panel__title-row">
              <span class="gf-skel gf-skel--panel-name" aria-hidden="true"></span>
              <span class="gf-skel gf-skel--panel-chip" aria-hidden="true"></span>
              <span class="gf-skel gf-skel--panel-chip" aria-hidden="true"></span>
            </div>
            <div class="gf-skel gf-skel--panel-blurb" aria-hidden="true"></div>
          </div>
        </div>
        <div class="gf-panel__body">
          <div class="gf-stats">
            <div class="gf-skel gf-skel--panel-stat" aria-hidden="true"></div>
            <div class="gf-skel gf-skel--panel-stat" aria-hidden="true"></div>
            <div class="gf-skel gf-skel--panel-stat" aria-hidden="true"></div>
            <div class="gf-skel gf-skel--panel-stat" aria-hidden="true"></div>
            <div class="gf-skel gf-skel--panel-stat" aria-hidden="true"></div>
            <div class="gf-skel gf-skel--panel-stat" aria-hidden="true"></div>
          </div>
          <div class="gf-attrs">
            <div class="gf-skel gf-skel--panel-attr" aria-hidden="true" style="width:100%"></div>
            <div class="gf-skel gf-skel--panel-attr" aria-hidden="true" style="width:92%"></div>
            <div class="gf-skel gf-skel--panel-attr" aria-hidden="true" style="width:86%"></div>
            <div class="gf-skel gf-skel--panel-attr" aria-hidden="true" style="width:78%"></div>
          </div>
          <div class="gf-actions">
            <span class="gf-skel gf-skel--panel-btn" aria-hidden="true"></span>
            <span class="gf-skel gf-skel--panel-btn gf-skel--panel-btn-sm" aria-hidden="true"></span>
          </div>
        </div>
      </div>
    `;
    return root;
  }

  function buildStatusPanel(text, isError) {
    const root = document.createElement('div');
    root.id = PANEL_ID;
    root.innerHTML = `<div class="gf-panel__status${isError ? ' is-error' : ''}">${escapeHtml(text)}</div>`;
    return root;
  }

  function findProfileMount() {
    const area = document.querySelector('.js-profile-editable-area');
    if (!area) return null;
    const followBlock = area.querySelector('.flex-order-1.flex-md-order-none');
    if (followBlock) return { parent: area, before: followBlock.nextSibling };
    const details = area.querySelector('.vcard-details');
    if (details) return { parent: area, before: details };
    return { parent: area, before: null };
  }

  function prefersReducedMotion() {
    return window.matchMedia('(prefers-reduced-motion: reduce)').matches;
  }

  function revealProfilePanel(node, fromHeight) {
    if (!(node instanceof HTMLElement)) return;
    if (prefersReducedMotion()) return;

    const startH = Math.max(0, Number(fromHeight) || 0);
    node.style.overflow = 'hidden';
    node.style.height = 'auto';
    const endH = Math.round(node.getBoundingClientRect().height);
    const startMargin = startH < 1 ? 0 : 16;
    const endMargin = 16;

    if (Math.abs(endH - startH) < 2 && startMargin === endMargin) {
      node.style.height = '';
      node.style.overflow = '';
      node.style.marginBottom = '';
      node.style.opacity = '';
      return;
    }

    node.classList.add('is-expanding');
    node.style.height = `${startH}px`;
    node.style.marginBottom = `${startMargin}px`;
    if (startH < 1) node.style.opacity = '0';
    void node.offsetHeight;

    node.style.height = `${endH}px`;
    node.style.marginBottom = `${endMargin}px`;
    node.style.opacity = '1';

    let settled = false;
    const settle = () => {
      if (settled) return;
      settled = true;
      node.classList.remove('is-expanding');
      node.style.height = '';
      node.style.overflow = '';
      node.style.marginBottom = '';
      node.style.opacity = '';
      node.removeEventListener('transitionend', onEnd);
    };
    const onEnd = (event) => {
      if (event.target !== node) return;
      if (event.propertyName !== 'height' && event.propertyName !== 'margin-bottom') return;
      settle();
    };
    node.addEventListener('transitionend', onEnd);
    window.setTimeout(settle, 550);
  }

  function mountProfilePanel(node) {
    const existing = document.getElementById(PANEL_ID);
    const fromHeight = existing ? existing.getBoundingClientRect().height : 0;
    if (existing) existing.remove();
    const mount = findProfileMount();
    if (!mount) return false;
    mount.parent.insertBefore(node, mount.before);
    requestAnimationFrame(() => {
      requestAnimationFrame(() => revealProfilePanel(node, fromHeight));
    });
    return true;
  }

  async function hydrateProfile(username) {
    if (!document.getElementById(PANEL_ID)) {
      mountProfilePanel(buildLoadingPanel());
    }

    try {
      const card = await fetchCard(username);
      if (getProfileUsername()?.toLowerCase() !== username.toLowerCase()) return;
      if (!card) {
        mountProfilePanel(buildStatusPanel(t('notFound'), false));
        return;
      }
      mountProfilePanel(buildProfilePanel(card));
    } catch {
      if (getProfileUsername()?.toLowerCase() === username.toLowerCase()) {
        mountProfilePanel(buildStatusPanel(t('loadError'), true));
      }
    }
  }

  function getHovercardLogin(popover) {
    const hydro = popover.querySelector('[data-hydro-view]');
    if (hydro) {
      try {
        const data = JSON.parse(hydro.getAttribute('data-hydro-view') || '');
        const login = data?.payload?.card_user_login;
        if (login && isValidUsername(login)) return login;
      } catch {
        /* ignore */
      }
    }

    const avatar = popover.querySelector('a.user-hovercard-avatar, img.user-hovercard-avatar-image');
    if (avatar) {
      const href = avatar.getAttribute('href') || avatar.closest('a')?.getAttribute('href');
      const fromHref = href ? extractUsernameFromHref(href) : null;
      if (fromHref) return fromHref;
      const alt = avatar.getAttribute('alt') || '';
      const m = alt.match(/^@?([A-Za-z0-9-]{1,39})$/);
      if (m && isValidUsername(m[1])) return m[1];
    }

    const loginLink = popover.querySelector('section[aria-label="User login and name"] a.Link--primary');
    if (loginLink) {
      const fromHref = extractUsernameFromHref(loginLink.href);
      if (fromHref) return fromHref;
    }

    return null;
  }

  function findHovercardMount(popover) {
    const hydro = popover.querySelector('[data-hydro-view]');
    if (hydro) return hydro;
    return popover.querySelector('.Popover-message > div > div') || popover.querySelector('.Popover-message');
  }

  function isVisibleHovercard(popover) {
    if (!popover || !(popover instanceof HTMLElement)) return false;
    if (popover.style.display === 'none') return false;
    const style = window.getComputedStyle(popover);
    return style.display !== 'none' && style.visibility !== 'hidden';
  }

  function renderHovercardContent(block, card) {
    const finish = normalizeFinish(card.finish);
    clearFinishClasses(block);
    block.classList.add(`gf-hc-finish--${finish}`);
    applyFinishVars(block, finish);
    block.dataset.gfFinish = finish;

    const finishLabel = card.finishLabel || finish.toUpperCase();
    const cardUrl = `${SITE_BASE}/${encodeURIComponent(card.login)}`;
    const duelUrl = buildDuelUrl(card.login);
    const statsHtml = STAT_ORDER.map(
      ([key, label]) => `
        <div class="gf-hc__stat">
          <span class="gf-hc__stat-value">${escapeHtml(card.stats?.[key] ?? '—')}</span>
          <span class="gf-hc__stat-key">${label}</span>
        </div>`
    ).join('');

    block.innerHTML = `
      <div class="gf-hc__head">
        <div class="gf-hc__ovr" title="${escapeHtml(t('overall'))}">
          <span class="gf-hc__ovr-value">${escapeHtml(card.overall)}</span>
          <span class="gf-hc__ovr-label">${escapeHtml(t('overall'))}</span>
        </div>
        <div class="gf-hc__meta">
          <div class="gf-hc__chips">
            <span class="gf-chip">${escapeHtml(card.position || '—')}</span>
            <span class="gf-chip gf-chip--finish">${escapeHtml(finishLabel)}</span>
            ${card.topLanguage ? `<span class="gf-chip">${escapeHtml(card.topLanguage)}</span>` : ''}
          </div>
          <p class="gf-hc__blurb">${escapeHtml(card.archetype || '')}${
            card.archetypeBlurb ? ` — ${escapeHtml(card.archetypeBlurb)}` : ''
          }</p>
        </div>
      </div>
      <div class="gf-hc__stats">${statsHtml}</div>
      <div class="gf-hc__actions">
        <a class="gf-hc__link gf-hc__link--primary" href="${escapeHtml(cardUrl)}" target="_blank" rel="noopener noreferrer">${escapeHtml(t('openReport'))}</a>
        <a class="gf-hc__link" href="${escapeHtml(duelUrl)}" target="_blank" rel="noopener noreferrer">${escapeHtml(t('duel'))}</a>
      </div>
    `;

    const popover = block.closest('.Popover.js-hovercard-content');
    if (popover) applyHovercardTheme(popover, finish);
  }

  function renderHovercardSkeleton() {
    return `
      <div class="gf-hc__skel" role="status" aria-busy="true" aria-label="${escapeHtml(t('loading'))}">
        <div class="gf-hc__head">
          <div class="gf-skel gf-skel--ovr" aria-hidden="true"></div>
          <div class="gf-hc__meta">
            <div class="gf-hc__chips">
              <span class="gf-skel gf-skel--chip" aria-hidden="true"></span>
              <span class="gf-skel gf-skel--chip" aria-hidden="true"></span>
            </div>
            <div class="gf-skel gf-skel--blurb" aria-hidden="true"></div>
            <div class="gf-skel gf-skel--blurb gf-skel--blurb-short" aria-hidden="true"></div>
          </div>
        </div>
        <div class="gf-hc__stats">
          <div class="gf-skel gf-skel--stat" aria-hidden="true"></div>
          <div class="gf-skel gf-skel--stat" aria-hidden="true"></div>
          <div class="gf-skel gf-skel--stat" aria-hidden="true"></div>
          <div class="gf-skel gf-skel--stat" aria-hidden="true"></div>
          <div class="gf-skel gf-skel--stat" aria-hidden="true"></div>
          <div class="gf-skel gf-skel--stat" aria-hidden="true"></div>
        </div>
        <div class="gf-hc__actions">
          <span class="gf-skel gf-skel--btn" aria-hidden="true"></span>
          <span class="gf-skel gf-skel--btn gf-skel--btn-sm" aria-hidden="true"></span>
        </div>
      </div>
    `;
  }

  async function hydrateHovercardBlock(block, login) {
    const seq = ++hovercardSeq;
    block.dataset.gfLogin = login.toLowerCase();
    block.dataset.gfState = 'loading';
    block.innerHTML = renderHovercardSkeleton();

    try {
      const card = await fetchCard(login);
      if (seq !== hovercardSeq) return;
      if (block.dataset.gfLogin !== login.toLowerCase()) return;
      if (!document.contains(block)) return;
      if (!card) {
        block.dataset.gfState = 'done';
        block.innerHTML = `<div class="gf-hc__status">${escapeHtml(t('notFound'))}</div>`;
        return;
      }
      renderHovercardContent(block, card);
      block.dataset.gfState = 'ready';
    } catch {
      if (seq !== hovercardSeq) return;
      if (!document.contains(block)) return;
      block.dataset.gfState = 'done';
      block.innerHTML = `<div class="gf-hc__status is-error">${escapeHtml(t('loadError'))}</div>`;
    }
  }

  function injectIntoHovercard(popover) {
    if (!settings.showHovercard) {
      popover.querySelector(`#${HOVERCARD_BLOCK_ID}`)?.remove();
      clearHovercardTheme(popover);
      return;
    }
    if (!isVisibleHovercard(popover)) {
      clearHovercardTheme(popover);
      return;
    }
    if (!popover.querySelector('.user-hovercard-avatar, [data-hydro-view*="user-hovercard"]')) {
      clearHovercardTheme(popover);
      return;
    }

    const login = getHovercardLogin(popover);
    if (!login) return;

    const mount = findHovercardMount(popover);
    if (!mount) return;

    let block = mount.querySelector(`#${HOVERCARD_BLOCK_ID}`);
    if (
      block &&
      block.dataset.gfLogin === login.toLowerCase() &&
      (block.dataset.gfState === 'loading' ||
        block.dataset.gfState === 'ready' ||
        block.dataset.gfState === 'done')
    ) {
      // Re-apply theme if GitHub rebuilt the Popover-message chrome
      if (block.dataset.gfState === 'ready' && block.dataset.gfFinish) {
        const message = popover.querySelector('.Popover-message');
        if (message && message.dataset.gfFinish !== block.dataset.gfFinish) {
          applyHovercardTheme(popover, block.dataset.gfFinish);
        }
      }
      return;
    }

    if (!block) {
      block = document.createElement('div');
      block.id = HOVERCARD_BLOCK_ID;
      mount.appendChild(block);
    }

    hydrateHovercardBlock(block, login);
  }

  function scanHovercards() {
    document.querySelectorAll('.Popover.js-hovercard-content').forEach((popover) => {
      injectIntoHovercard(popover);
    });
  }

  function ensureHovercardObserver() {
    if (hovercardObserver) return;
    let timer = null;
    hovercardObserver = new MutationObserver((mutations) => {
      let relevant = false;
      for (const mutation of mutations) {
        const target = mutation.target;
        if (target instanceof Element) {
          if (
            target.classList?.contains('js-hovercard-content') ||
            target.classList?.contains('Popover-message') ||
            target.closest?.('.Popover.js-hovercard-content')
          ) {
            relevant = true;
            break;
          }
        }
        for (const node of mutation.addedNodes) {
          if (!(node instanceof Element)) continue;
          if (
            node.classList?.contains('js-hovercard-content') ||
            node.querySelector?.('.js-hovercard-content, .user-hovercard-avatar')
          ) {
            relevant = true;
            break;
          }
        }
        if (relevant) break;
      }
      if (!relevant) return;
      if (timer) clearTimeout(timer);
      timer = setTimeout(() => {
        timer = null;
        scanHovercards();
      }, 50);
    });
    hovercardObserver.observe(document.body, {
      childList: true,
      subtree: true,
      attributes: true,
      attributeFilter: ['style', 'class'],
    });
  }

  function scanPage() {
    const username = getProfileUsername();
    if (username) {
      const existing = document.getElementById(PANEL_ID);
      const currentLogin = existing?.querySelector('.gf-panel__name')?.textContent?.trim();
      if (!existing || (existing.dataset.gfUser || '').toLowerCase() !== username.toLowerCase()) {
        if (existing) existing.remove();
        const loading = buildLoadingPanel();
        loading.dataset.gfUser = username;
        mountProfilePanel(loading);
        hydrateProfile(username).then(() => {
          const panel = document.getElementById(PANEL_ID);
          if (panel) panel.dataset.gfUser = username;
        });
      } else if (!currentLogin && existing.dataset.gfState !== 'loading' && !existing.querySelector('.gf-panel__status')) {
        hydrateProfile(username);
      }
    } else {
      document.getElementById(PANEL_ID)?.remove();
    }

    scanHovercards();
    ensureUserMenuItem();
  }

  function scheduleScan() {
    if (scanTimer) clearTimeout(scanTimer);
    scanTimer = setTimeout(() => {
      scanTimer = null;
      scanPage();
    }, SCAN_DEBOUNCE_MS);
  }

  function getGlobalUserMenu() {
    const header = document.getElementById('global-nav-user-menu-header');
    if (header) {
      const dialog = header.closest('[role="dialog"]');
      if (dialog) return dialog;
    }
    return document.querySelector(
      '[role="dialog"][aria-labelledby="global-nav-user-menu-header"]'
    );
  }

  function closeGlobalUserMenu() {
    const menu = getGlobalUserMenu();
    if (!menu) return;

    const closeBtn = menu.querySelector('[data-component="Dialog.CloseButton"]');
    if (closeBtn instanceof HTMLElement && closeBtn.offsetParent !== null) {
      closeBtn.click();
      return;
    }

    const triggers = document.querySelectorAll('header button[aria-expanded="true"], .AppHeader button[aria-expanded="true"]');
    for (const trigger of triggers) {
      if (!(trigger instanceof HTMLElement)) continue;
      trigger.click();
      if (!getGlobalUserMenu()) return;
    }

    menu.dispatchEvent(
      new KeyboardEvent('keydown', { key: 'Escape', bubbles: true, cancelable: true })
    );
  }

  function settingsAreCustomized() {
    return (
      settings.cacheHours !== DEFAULT_SETTINGS.cacheHours ||
      settings.showHovercard !== DEFAULT_SETTINGS.showHovercard ||
      normalizeCardTheme(settings.cardTheme) !== DEFAULT_SETTINGS.cardTheme ||
      normalizeUiLocale(settings.locale) !== DEFAULT_SETTINGS.locale
    );
  }

  function ensureUserMenuItem() {
    const menu = getGlobalUserMenu();
    if (!menu) return null;
    if (menu.querySelector('#gf-user-menu-item')) {
      updateSettingsMenuState();
      return menu.querySelector('#gf-user-menu-item');
    }

    const list = menu.querySelector('ul[data-component="ActionList"]');
    if (!list) return null;

    const buttonItems = [...list.querySelectorAll('li[data-component="ActionList.Item"]')].filter(
      (li) => li.querySelector(':scope > button')
    );
    // Prefer a later action button (e.g. Feature preview) over the status row.
    const sampleLi = buttonItems[buttonItems.length - 1] || buttonItems[0];
    if (!sampleLi) return null;

    const li = /** @type {HTMLElement} */ (sampleLi.cloneNode(true));
    li.id = 'gf-user-menu-item';
    li.removeAttribute('hidden');
    li.classList.remove('hide-whenRegular', 'd-md-none', 'd-lg-none');

    const btn = li.querySelector('button');
    if (!(btn instanceof HTMLButtonElement)) return null;
    btn.removeAttribute('id');
    btn.removeAttribute('aria-labelledby');
    btn.removeAttribute('aria-describedby');
    btn.removeAttribute('aria-expanded');
    btn.removeAttribute('aria-haspopup');
    btn.type = 'button';

    const label = li.querySelector('[data-component="ActionList.Item.Label"]');
    if (label) {
      label.textContent = t('navMenuItem');
      label.removeAttribute('id');
    }

    let visual = li.querySelector('[data-component="ActionList.LeadingVisual"]');
    if (!visual) {
      visual = document.createElement('span');
      visual.setAttribute('data-component', 'ActionList.LeadingVisual');
      visual.className =
        sampleLi.querySelector('[data-component="ActionList.LeadingVisual"]')?.className ||
        'prc-ActionList-LeadingVisual-NBr28 prc-ActionList-VisualWrap-bdCsS';
      const spacer = btn.querySelector('[class*="Spacer"]');
      if (spacer?.nextSibling) btn.insertBefore(visual, spacer.nextSibling);
      else btn.insertBefore(visual, btn.firstChild);
    }

    visual.innerHTML =
      '<svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align: text-bottom">' +
      '<path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0Zm0 1.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13Z"/>' +
      '<path d="M8 3.25a.75.75 0 0 1 .67.415l.9 1.8 1.99.29a.75.75 0 0 1 .416 1.279l-1.44 1.404.34 1.982a.75.75 0 0 1-1.088.791L8 10.347l-1.788.94a.75.75 0 0 1-1.088-.79l.34-1.983-1.44-1.404a.75.75 0 0 1 .416-1.28l1.99-.289.9-1.8A.75.75 0 0 1 8 3.25Z"/>' +
      '</svg>';


    let trailing = li.querySelector('[data-component="ActionList.TrailingVisual"]');
    const sub = li.querySelector('[data-component="ActionList.Item--DividerContainer"]');
    if (!trailing && sub) {
      trailing = document.createElement('span');
      trailing.setAttribute('data-component', 'ActionList.TrailingVisual');
      trailing.className =
        sampleLi.querySelector('[data-component="ActionList.TrailingVisual"]')?.className ||
        'prc-ActionList-TrailingVisual-jwT9C prc-ActionList-VisualWrap-bdCsS';
      sub.appendChild(trailing);
    }
    if (trailing) {
      trailing.innerHTML =
        '<span class="gf-nav-dot" id="gf-settings-dot" aria-hidden="true"></span>';
    }

    btn.addEventListener('click', (e) => {
      e.preventDefault();
      e.stopPropagation();
      closeGlobalUserMenu();
      window.setTimeout(() => togglePanel(true), 50);
    });

    const settingsLink = [...list.querySelectorAll('a[href]')].find((a) => {
      try {
        return new URL(a.href, location.origin).pathname === '/settings/profile';
      } catch {
        return a.getAttribute('href') === '/settings/profile';
      }
    });
    const settingsLi = settingsLink?.closest('li');
    const signOutLink = [...list.querySelectorAll('a[href]')].find((a) => {
      try {
        return new URL(a.href, location.origin).pathname === '/logout';
      } catch {
        return a.getAttribute('href') === '/logout';
      }
    });
    const signOutLi = signOutLink?.closest('li');

    if (settingsLi) {
      settingsLi.after(li);
    } else if (signOutLi) {
      signOutLi.before(li);
    } else {
      list.appendChild(li);
    }

    ensurePanel();
    updateSettingsMenuState();
    return li;
  }

  function updateSettingsMenuState() {
    const dot = document.getElementById('gf-settings-dot');
    if (!dot) return;
    const customized = settingsAreCustomized();
    dot.classList.toggle('is-on', customized);
    dot.title = customized ? t('on') : t('off');
  }

  function ensurePanel() {
    if (document.getElementById('gf-panel')) return;

    const panel = document.createElement('div');
    panel.id = 'gf-panel';
    panel.className = 'gf-settings-panel';
    panel.hidden = true;
    panel.innerHTML = `
      <div class="gf-settings-panel__header">
        <div>
          <div class="gf-settings-panel__title">${escapeHtml(t('panelTitle'))}</div>
          <div class="gf-settings-panel__subtitle">${escapeHtml(t('panelSubtitle'))}</div>
          <div class="gf-settings-panel__version">${escapeHtml(t('version', { version: SCRIPT_VERSION }))}</div>
        </div>
        <button type="button" class="gf-settings-panel__close" data-gf="close" aria-label="${escapeHtml(t('close'))}">×</button>
      </div>

      <div class="gf-settings-panel__section">
        <div class="gf-settings-panel__section-title">${escapeHtml(t('sectionDisplay'))}</div>
        <label class="gf-field">
          <span class="gf-field__label">${escapeHtml(t('uiLanguage'))}</span>
          <select id="gf-ui-locale">
            <option value="auto">${escapeHtml(t('uiLanguageAuto'))}</option>
            ${SUPPORTED_LOCALES.map(
              (code) =>
                `<option value="${code}">${escapeHtml(LOCALE_NATIVE_NAMES[code] || code)}</option>`
            ).join('')}
          </select>
        </label>
        <p class="gf-hint">${escapeHtml(t('uiLanguageHint'))}</p>
        <label class="gf-field">
          <span class="gf-field__label">${escapeHtml(t('cardTheme'))}</span>
          <select id="gf-card-theme">
            <option value="standard">${escapeHtml(t('cardThemeStandard'))}</option>
            <option value="github">${escapeHtml(t('cardThemeGithub'))}</option>
            <option value="fifa">${escapeHtml(t('cardThemeFifa'))}</option>
            <option value="neon">${escapeHtml(t('cardThemeNeon'))}</option>
          </select>
        </label>
        <p class="gf-hint">${escapeHtml(t('cardThemeHint'))}</p>
        <div class="gf-row" style="margin-bottom:10px">
          <label class="gf-switch">
            <input type="checkbox" id="gf-show-hovercard" />
            <span>${escapeHtml(t('showHovercard'))}</span>
          </label>
          <span class="gf-pill" id="gf-show-hovercard-pill">${escapeHtml(t('off'))}</span>
        </div>
        <p class="gf-hint">${escapeHtml(t('showHovercardHint'))}</p>
      </div>

      <div class="gf-settings-panel__divider"></div>

      <div class="gf-settings-panel__section">
        <div class="gf-settings-panel__section-title">${escapeHtml(t('sectionCache'))}</div>
        <div class="gf-cache-stats" id="gf-cache-stats">
          <div class="gf-cache-stats__count" id="gf-cache-count"></div>
          <p class="gf-cache-stats__storage" id="gf-cache-storage"></p>
          <div
            class="gf-cache-stats__bar"
            id="gf-cache-bar"
            role="progressbar"
            aria-valuemin="0"
            aria-valuemax="100"
            aria-valuenow="100"
            aria-label="${escapeHtml(t('cacheStorageHint', { budget: formatBytes(CACHE_BUDGET_BYTES) }))}"
          >
            <div class="gf-cache-stats__bar-fill" id="gf-cache-bar-fill"></div>
          </div>
          <p class="gf-hint gf-cache-stats__hint">${escapeHtml(t('cacheStorageHint', { budget: formatBytes(CACHE_BUDGET_BYTES) }))}</p>
        </div>
        <label class="gf-field">
          <span class="gf-field__label">${escapeHtml(t('cacheHours'))}</span>
          <input type="number" id="gf-cache-hours" min="0" max="${CACHE_HOURS_MAX}" step="1" placeholder="12" inputmode="numeric" />
        </label>
        <p class="gf-hint">${escapeHtml(t('cacheHoursHint'))}</p>
        <button type="button" class="gf-btn gf-btn--danger" data-gf="clear-cache">${escapeHtml(t('clearCache'))}</button>
        <p class="gf-hint">${escapeHtml(t('cacheClearHint'))}</p>
        <p class="gf-cache-status" id="gf-cache-status" aria-live="polite"></p>
      </div>

      <div class="gf-settings-panel__footer">
        <div class="gf-settings-panel__footer-actions">
          <button type="button" class="gf-btn gf-btn--ghost" data-gf="close">${escapeHtml(t('cancel'))}</button>
          <button type="button" class="gf-btn" data-gf="save">${escapeHtml(t('save'))}</button>
          <button type="button" class="gf-btn gf-btn--green" data-gf="save-run">${escapeHtml(t('saveReload'))}</button>
        </div>
        <div class="gf-settings-panel__footer-divider" role="separator"></div>
        <a class="gf-settings-panel__repo" href="${REPO_URL}" target="_blank" rel="noopener noreferrer">
          <span class="gf-settings-panel__repo-title">${escapeHtml(t('repoLink'))}</span>
          <span class="gf-settings-panel__repo-desc">${escapeHtml(t('repoAbout'))}</span>
        </a>
      </div>
    `;
    document.body.appendChild(panel);

    panel.addEventListener('click', (e) => e.stopPropagation());
    panel.querySelectorAll('[data-gf="close"]').forEach((el) =>
      el.addEventListener('click', () => togglePanel(false))
    );
    panel.querySelector('[data-gf="save"]').addEventListener('click', () => {
      const localeChanged = persistPanelForm();
      if (localeChanged) {
        location.reload();
        return;
      }
      togglePanel(false);
    });
    panel.querySelector('[data-gf="save-run"]').addEventListener('click', () => {
      persistPanelForm();
      togglePanel(false);
      location.reload();
    });
    panel.querySelector('[data-gf="clear-cache"]').addEventListener('click', () => {
      const count = clearCardCache();
      const status = panel.querySelector('#gf-cache-status');
      if (status) status.textContent = count > 0 ? t('cacheCleared', { count }) : t('cacheEmpty');
      updateCacheStatsUI();
    });

    panel.querySelector('#gf-show-hovercard').addEventListener('change', syncDisplayPills);

    document.addEventListener('click', (e) => {
      if (!panelOpen) return;
      const menuItem = document.getElementById('gf-user-menu-item');
      if (
        panel.contains(/** @type {Node} */ (e.target)) ||
        menuItem?.contains(/** @type {Node} */ (e.target))
      ) {
        return;
      }
      togglePanel(false);
    });
    document.addEventListener('keydown', (e) => {
      if (e.key === 'Escape' && panelOpen) togglePanel(false);
    });
  }

  function syncDisplayPills() {
    const panel = document.getElementById('gf-panel');
    if (!panel) return;
    const hoverOn = panel.querySelector('#gf-show-hovercard').checked;
    const hoverPill = panel.querySelector('#gf-show-hovercard-pill');
    hoverPill.textContent = hoverOn ? t('on') : t('off');
    hoverPill.classList.toggle('is-on', hoverOn);
  }

  function fillPanelForm() {
    const panel = document.getElementById('gf-panel');
    if (!panel) return;
    panel.querySelector('#gf-ui-locale').value = normalizeUiLocale(settings.locale);
    panel.querySelector('#gf-show-hovercard').checked = settings.showHovercard !== false;
    panel.querySelector('#gf-card-theme').value = normalizeCardTheme(settings.cardTheme);
    panel.querySelector('#gf-cache-hours').value = String(normalizeCacheHours(settings.cacheHours));
    const status = panel.querySelector('#gf-cache-status');
    if (status) status.textContent = '';
    syncDisplayPills();
    updateCacheStatsUI();
  }

  /** @returns {boolean} true if UI locale preference changed (caller should reload) */
  function persistPanelForm() {
    const panel = document.getElementById('gf-panel');
    if (!panel) return false;
    const prevLocale = normalizeUiLocale(settings.locale);
    saveSettings({
      locale: panel.querySelector('#gf-ui-locale').value,
      showHovercard: panel.querySelector('#gf-show-hovercard').checked,
      cardTheme: panel.querySelector('#gf-card-theme').value,
      cacheHours: normalizeCacheHours(panel.querySelector('#gf-cache-hours').value),
    });
    return normalizeUiLocale(settings.locale) !== prevLocale;
  }

  function togglePanel(force) {
    ensurePanel();
    const panel = document.getElementById('gf-panel');
    if (!panel) return;

    panelOpen = typeof force === 'boolean' ? force : !panelOpen;
    panel.hidden = !panelOpen;

    if (panelOpen) {
      fillPanelForm();
      positionPanel();
    }
  }

  function positionPanel() {
    const panel = document.getElementById('gf-panel');
    if (!panel) return;

    const width = 360;
    const anchor =
      document.getElementById('gf-user-menu-item') ||
      getGlobalUserMenu() ||
      document.querySelector('header .AppHeader-user, header [data-component="Avatar"], header img.avatar');

    let left;
    let top;
    if (anchor) {
      const rect = anchor.getBoundingClientRect();
      left = rect.right - width;
      top = rect.bottom + 8;
      if (top < 56) top = 56;
    } else {
      left = window.innerWidth - width - 16;
      top = 56;
    }

    if (left < 8) left = 8;
    if (left + width > window.innerWidth - 8) left = window.innerWidth - width - 8;
    if (top + 40 > window.innerHeight - 8) top = Math.max(8, window.innerHeight - 40);

    panel.style.top = `${Math.round(top)}px`;
    panel.style.left = `${Math.round(left)}px`;
  }

  function onSoftNavigation() {
    scheduleScan();
    ensureUserMenuItem();
  }

  function init() {
    loadMemoryCache();
    applyCardTheme();
    window.addEventListener('pagehide', persistCacheNow);
    ensurePanel();
    ensureUserMenuItem();

    if (typeof GM_registerMenuCommand === 'function') {
      GM_registerMenuCommand(t('menuSettings'), () => {
        togglePanel(true);
      });
    }

    scheduleScan();
    ensureHovercardObserver();

    mutationObserver = new MutationObserver((mutations) => {
      let relevant = false;
      for (const mutation of mutations) {
        if (mutation.type !== 'childList') continue;
        for (const node of mutation.addedNodes) {
          if (!(node instanceof Element)) continue;
          if (
            node.id === PANEL_ID ||
            node.id === 'gf-panel' ||
            node.id === 'gf-user-menu-item' ||
            node.id === HOVERCARD_BLOCK_ID
          ) {
            continue;
          }
          if (
            node.id === 'global-nav-user-menu-header' ||
            node.getAttribute?.('aria-labelledby') === 'global-nav-user-menu-header' ||
            (node.matches?.('ul[data-component="ActionList"]') && getGlobalUserMenu()?.contains(node)) ||
            node.querySelector?.(
              '#global-nav-user-menu-header, [aria-labelledby="global-nav-user-menu-header"]'
            )
          ) {
            ensureUserMenuItem();
            continue;
          }
          if (
            node.matches?.(
              '.js-profile-editable-area, .Layout-sidebar, .Popover.js-hovercard-content, main'
            ) ||
            node.querySelector?.(
              '.js-profile-editable-area, .Popover.js-hovercard-content'
            )
          ) {
            relevant = true;
            break;
          }
        }
        if (relevant) break;
      }
      if (!relevant) return;
      scheduleScan();
    });
    mutationObserver.observe(document.body, { childList: true, subtree: true });

    document.addEventListener('turbo:load', onSoftNavigation);
    document.addEventListener('turbo:render', onSoftNavigation);
    document.addEventListener('pjax:end', onSoftNavigation);
    document.addEventListener('soft-nav:success', onSoftNavigation);
    window.addEventListener('popstate', onSoftNavigation);
  }

  init();
})();