diff --git a/locale/ui_en.properties b/locale/ui_en.properties
index b5f3de2..7d1bed4 100644
--- a/locale/ui_en.properties
+++ b/locale/ui_en.properties
@@ -57,20 +57,20 @@ mods/catalog_export = Export to Catalog
mods/catalog_title = Export Catalog Entry
mods/catalog_download_url = Download URL
mods/catalog_category = Category
-mods/category_story = Story
-mods/category_characters = Characters
-mods/category_gameplay = Gameplay
-mods/category_visual = Visual
-mods/category_audio = Audio
-mods/category_ui = UI
-mods/category_locale = Locale
-mods/category_library = Library
-mods/category_engine = Engine
-mods/category_overhaul = Overhaul
-mods/category_tools = Tools
-mods/category_editor = Editor
-mods/category_debug = Debug
-mods/category_other = Other
+mod_category/story = Story
+mod_category/characters = Characters
+mod_category/gameplay = Gameplay
+mod_category/visual = Visual
+mod_category/audio = Audio
+mod_category/ui = UI
+mod_category/locale = Locale
+mod_category/library = Library
+mod_category/engine = Engine
+mod_category/overhaul = Overhaul
+mod_category/tools = Tools
+mod_category/editor = Editor
+mod_category/debug = Debug
+mod_category/other = Other
mods/catalog_tags = Tags (comma-separated)
mods/catalog_changelog = Changelog
mods/catalog_status = Status
@@ -269,3 +269,23 @@ tools/menu_title = Tools
# --- Development cover ---
ui/cover/in_development = In development
+
+mod_categories/title = Categories
+mod_categories/code = Category, e.g. RPG — Gear
+mod_categories/add = Add
+mod_categories/primary = Primary category
+mod_categories/suggestions = Choose a category…
+mod_categories/save = Save categories
+mod_categories/saved = Categories saved to manifest.json.
+mod_categories/development = Saved in the development mod before packaging.
+mod_categories/readonly = Categories of installed packages and catalog entries are read-only. Edit the development folder.
+mod_categories/pending = Add the typed category or clear the input before continuing.
+
+mod_categories/hint_code = Enter any category name; spelling is preserved.
+mod_categories/hint_suggestions = Choose a category from installed mods, catalogs or the base suggestions.
+mod_categories/hint_primary = The primary category appears on the card and determines its group. It is saved first.
+mod_categories/hint_add = Add the entered category.
+mod_categories/hint_base = Include or remove this category.
+mod_categories/hint_remove = Remove this custom category.
+
+mod_categories/hint_filter = Show mods with this category:
diff --git a/locale/ui_es.properties b/locale/ui_es.properties
index d123637..5072726 100644
--- a/locale/ui_es.properties
+++ b/locale/ui_es.properties
@@ -57,20 +57,20 @@ mods/catalog_export = Exportar al catálogo
mods/catalog_title = Exportar entrada del catálogo
mods/catalog_download_url = URL de descarga
mods/catalog_category = Categoría
-mods/category_story = Historia
-mods/category_characters = Personajes
-mods/category_gameplay = Jugabilidad
-mods/category_visual = Visual
-mods/category_audio = Audio
-mods/category_ui = Interfaz
-mods/category_locale = Idioma
-mods/category_library = Biblioteca
-mods/category_engine = Motor
-mods/category_overhaul = Conversión total
-mods/category_tools = Herramientas
-mods/category_editor = Editor
-mods/category_debug = Depuración
-mods/category_other = Otros
+mod_category/story = Historia
+mod_category/characters = Personajes
+mod_category/gameplay = Jugabilidad
+mod_category/visual = Visual
+mod_category/audio = Audio
+mod_category/ui = Interfaz
+mod_category/locale = Idioma
+mod_category/library = Biblioteca
+mod_category/engine = Motor
+mod_category/overhaul = Conversión total
+mod_category/tools = Herramientas
+mod_category/editor = Editor
+mod_category/debug = Depuración
+mod_category/other = Otros
mods/catalog_tags = Etiquetas (separadas por comas)
mods/catalog_changelog = Cambios
mods/catalog_status = Estado
diff --git a/locale/ui_ja.properties b/locale/ui_ja.properties
index 833281f..9f7c4f9 100644
--- a/locale/ui_ja.properties
+++ b/locale/ui_ja.properties
@@ -57,20 +57,20 @@ mods/catalog_export = カタログに書き出す
mods/catalog_title = カタログ項目を書き出す
mods/catalog_download_url = ダウンロード URL
mods/catalog_category = カテゴリー
-mods/category_story = ストーリー
-mods/category_characters = キャラクター
-mods/category_gameplay = ゲームプレイ
-mods/category_visual = ビジュアル
-mods/category_audio = オーディオ
-mods/category_ui = UI
-mods/category_locale = 言語
-mods/category_library = ライブラリ
-mods/category_engine = エンジン
-mods/category_overhaul = 大型改造
-mods/category_tools = ツール
-mods/category_editor = エディター
-mods/category_debug = デバッグ
-mods/category_other = その他
+mod_category/story = ストーリー
+mod_category/characters = キャラクター
+mod_category/gameplay = ゲームプレイ
+mod_category/visual = ビジュアル
+mod_category/audio = オーディオ
+mod_category/ui = UI
+mod_category/locale = 言語
+mod_category/library = ライブラリ
+mod_category/engine = エンジン
+mod_category/overhaul = 大型改造
+mod_category/tools = ツール
+mod_category/editor = エディター
+mod_category/debug = デバッグ
+mod_category/other = その他
mods/catalog_tags = タグ(カンマ区切り)
mods/catalog_changelog = 変更履歴
mods/catalog_status = 状態
diff --git a/locale/ui_ko.properties b/locale/ui_ko.properties
index 7c4a6d6..aac262a 100644
--- a/locale/ui_ko.properties
+++ b/locale/ui_ko.properties
@@ -57,20 +57,20 @@ mods/catalog_export = 카탈로그로 내보내기
mods/catalog_title = 카탈로그 항목 내보내기
mods/catalog_download_url = 다운로드 URL
mods/catalog_category = 분류
-mods/category_story = 스토리
-mods/category_characters = 캐릭터
-mods/category_gameplay = 게임플레이
-mods/category_visual = 비주얼
-mods/category_audio = 오디오
-mods/category_ui = UI
-mods/category_locale = 언어
-mods/category_library = 라이브러리
-mods/category_engine = 엔진
-mods/category_overhaul = 대규모 개편
-mods/category_tools = 도구
-mods/category_editor = 에디터
-mods/category_debug = 디버그
-mods/category_other = 기타
+mod_category/story = 스토리
+mod_category/characters = 캐릭터
+mod_category/gameplay = 게임플레이
+mod_category/visual = 비주얼
+mod_category/audio = 오디오
+mod_category/ui = UI
+mod_category/locale = 언어
+mod_category/library = 라이브러리
+mod_category/engine = 엔진
+mod_category/overhaul = 대규모 개편
+mod_category/tools = 도구
+mod_category/editor = 에디터
+mod_category/debug = 디버그
+mod_category/other = 기타
mods/catalog_tags = 태그 (쉼표로 구분)
mods/catalog_changelog = 변경 기록
mods/catalog_status = 상태
diff --git a/locale/ui_ru.properties b/locale/ui_ru.properties
index f985478..cb9e450 100644
--- a/locale/ui_ru.properties
+++ b/locale/ui_ru.properties
@@ -57,20 +57,20 @@ mods/catalog_export = Экспорт в каталог
mods/catalog_title = Экспорт записи каталога
mods/catalog_download_url = URL скачивания
mods/catalog_category = Категория
-mods/category_story = Сюжет
-mods/category_characters = Персонажи
-mods/category_gameplay = Геймплей
-mods/category_visual = Визуал
-mods/category_audio = Аудио
-mods/category_ui = Интерфейс
-mods/category_locale = Перевод
-mods/category_library = Библиотека
-mods/category_engine = Движок
-mods/category_overhaul = Тотальная конверсия
-mods/category_tools = Инструменты
-mods/category_editor = Редактор
-mods/category_debug = Отладка
-mods/category_other = Прочее
+mod_category/story = Сюжет
+mod_category/characters = Персонажи
+mod_category/gameplay = Геймплей
+mod_category/visual = Визуал
+mod_category/audio = Аудио
+mod_category/ui = Интерфейс
+mod_category/locale = Перевод
+mod_category/library = Библиотека
+mod_category/engine = Движок
+mod_category/overhaul = Тотальная конверсия
+mod_category/tools = Инструменты
+mod_category/editor = Редактор
+mod_category/debug = Отладка
+mod_category/other = Прочее
mods/catalog_tags = Теги (через запятую)
mods/catalog_changelog = Список изменений
mods/catalog_status = Статус
@@ -269,3 +269,23 @@ tools/menu_title = Инструменты
# --- Development cover ---
ui/cover/in_development = В разработке
+
+mod_categories/title = Категории
+mod_categories/code = Категория, например RPG — оружие
+mod_categories/add = Добавить
+mod_categories/primary = Основная категория
+mod_categories/suggestions = Выбрать категорию…
+mod_categories/save = Сохранить категории
+mod_categories/saved = Категории сохранены в manifest.json.
+mod_categories/development = Сохраняются в папке разработки мода до упаковки.
+mod_categories/readonly = Категории установленных пакетов и записей каталога доступны для чтения. Правьте папку разработки.
+mod_categories/pending = Добавьте набранную категорию или очистите поле перед продолжением.
+
+mod_categories/hint_code = Введите любое название категории; написание сохраняется.
+mod_categories/hint_suggestions = Выберите категорию из установленных модов, каталогов или базовых подсказок.
+mod_categories/hint_primary = Основная категория показывается в карточке и определяет её группу. Сохраняется первой.
+mod_categories/hint_add = Добавить введённую категорию.
+mod_categories/hint_base = Добавить или убрать эту категорию.
+mod_categories/hint_remove = Убрать эту свою категорию.
+
+mod_categories/hint_filter = Показать моды с этой категорией:
diff --git a/locale/ui_vi.properties b/locale/ui_vi.properties
index 13fb7ca..ae9d053 100644
--- a/locale/ui_vi.properties
+++ b/locale/ui_vi.properties
@@ -57,20 +57,20 @@ mods/catalog_export = Xuất sang danh mục
mods/catalog_title = Xuất mục danh mục
mods/catalog_download_url = URL tải xuống
mods/catalog_category = Thể loại
-mods/category_story = Cốt truyện
-mods/category_characters = Nhân vật
-mods/category_gameplay = Lối chơi
-mods/category_visual = Hình ảnh
-mods/category_audio = Âm thanh
-mods/category_ui = Giao diện
-mods/category_locale = Ngôn ngữ
-mods/category_library = Thư viện
-mods/category_engine = Engine
-mods/category_overhaul = Đại tu
-mods/category_tools = Công cụ
-mods/category_editor = Trình sửa
-mods/category_debug = Gỡ lỗi
-mods/category_other = Khác
+mod_category/story = Cốt truyện
+mod_category/characters = Nhân vật
+mod_category/gameplay = Lối chơi
+mod_category/visual = Hình ảnh
+mod_category/audio = Âm thanh
+mod_category/ui = Giao diện
+mod_category/locale = Ngôn ngữ
+mod_category/library = Thư viện
+mod_category/engine = Bộ máy
+mod_category/overhaul = Đại tu
+mod_category/tools = Công cụ
+mod_category/editor = Trình sửa
+mod_category/debug = Gỡ lỗi
+mod_category/other = Khác
mods/catalog_tags = Thẻ (cách nhau bằng dấu phẩy)
mods/catalog_changelog = Nhật ký thay đổi
mods/catalog_status = Trạng thái
diff --git a/locale/ui_zh.properties b/locale/ui_zh.properties
index abcd2df..d22fe8c 100644
--- a/locale/ui_zh.properties
+++ b/locale/ui_zh.properties
@@ -57,20 +57,20 @@ mods/catalog_export = 导出到目录
mods/catalog_title = 导出目录条目
mods/catalog_download_url = 下载 URL
mods/catalog_category = 分类
-mods/category_story = 剧情
-mods/category_characters = 角色
-mods/category_gameplay = 玩法
-mods/category_visual = 视觉
-mods/category_audio = 音频
-mods/category_ui = 界面
-mods/category_locale = 语言
-mods/category_library = 库
-mods/category_engine = 引擎
-mods/category_overhaul = 大型改动
-mods/category_tools = 工具
-mods/category_editor = 编辑器
-mods/category_debug = 调试
-mods/category_other = 其他
+mod_category/story = 剧情
+mod_category/characters = 角色
+mod_category/gameplay = 玩法
+mod_category/visual = 视觉
+mod_category/audio = 音频
+mod_category/ui = 界面
+mod_category/locale = 语言
+mod_category/library = 库
+mod_category/engine = 引擎
+mod_category/overhaul = 大型改动
+mod_category/tools = 工具
+mod_category/editor = 编辑器
+mod_category/debug = 调试
+mod_category/other = 其他
mods/catalog_tags = 标签(逗号分隔)
mods/catalog_changelog = 更新日志
mods/catalog_status = 状态
diff --git a/manifest.json b/manifest.json
index edff27e..846b807 100644
--- a/manifest.json
+++ b/manifest.json
@@ -4,7 +4,7 @@
"version": "0.1.0",
"author": "ct",
"description": "The interface layer every game shares: the toolbar, the in-game menu, the save indicator, notifications and the common look of panels, buttons and lists.",
- "category": "ui",
+ "categories": ["ui"],
"depends": [],
"sources": [
"src/**/*.cs"
diff --git a/scenes/components/mod_category_editor.tscn b/scenes/components/mod_category_editor.tscn
new file mode 100644
index 0000000..0375509
--- /dev/null
+++ b/scenes/components/mod_category_editor.tscn
@@ -0,0 +1,57 @@
+[gd_scene format=3]
+
+[ext_resource type="Script" path="src/View/ModCategoryEditor.cs" id="1"]
+
+[node name="ModCategoryEditor" type="Control"]
+custom_minimum_size = Vector2(440, 260)
+size_flags_horizontal = 3
+script = ExtResource("1")
+
+[node name="Layout" type="VBoxContainer" parent="."]
+layout_mode = 1
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+theme_override_constants/separation = 4
+
+[node name="Caption" type="Label" parent="Layout"]
+layout_mode = 2
+text = "mod_categories/title"
+
+[node name="Base" type="GridContainer" parent="Layout"]
+layout_mode = 2
+columns = 4
+
+[node name="Custom" type="HFlowContainer" parent="Layout"]
+layout_mode = 2
+
+[node name="Input" type="HBoxContainer" parent="Layout"]
+layout_mode = 2
+
+[node name="Code" type="LineEdit" parent="Layout/Input"]
+layout_mode = 2
+size_flags_horizontal = 3
+placeholder_text = "mod_categories/code"
+
+[node name="Add" type="Button" parent="Layout/Input"]
+layout_mode = 2
+text = "mod_categories/add"
+
+[node name="Suggestions" type="OptionButton" parent="Layout"]
+layout_mode = 2
+fit_to_longest_item = false
+
+[node name="PrimaryRow" type="HBoxContainer" parent="Layout"]
+layout_mode = 2
+
+[node name="Caption" type="Label" parent="Layout/PrimaryRow"]
+layout_mode = 2
+text = "mod_categories/primary"
+
+[node name="Primary" type="OptionButton" parent="Layout/PrimaryRow"]
+layout_mode = 2
+fit_to_longest_item = false
+text_overrun_behavior = 3
+size_flags_horizontal = 3
diff --git a/src/View/ModCategoryEditor.cs b/src/View/ModCategoryEditor.cs
new file mode 100644
index 0000000..2624748
--- /dev/null
+++ b/src/View/ModCategoryEditor.cs
@@ -0,0 +1,165 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Cthangover.Core.Mods;
+using Cthangover.Core.Scenes;
+using Cthangover.Core.Utils;
+using Cthangover.Mods.Interface.Base.Lists;
+using Godot;
+
+namespace Cthangover.Mods.Interface.View
+{
+
+/// Shared ordered category editor. Base checkboxes, custom chips, code completion and primary choice edit the same list.
+public partial class ModCategoryEditor : ModWidget
+{
+ private readonly List selected = new();
+ private readonly List known = new();
+ private readonly Dictionary checks = new(ModCategories.Comparer);
+ private LineEdit input;
+ private OptionButton suggestions;
+ private OptionButton primary;
+ private bool refreshing;
+ private bool editable = true;
+
+ public event Action Changed;
+ /// Snapshot in publishing order; choosing the primary moves it to the first position.
+ public List Categories => new(selected);
+ public bool HasPendingInput => !string.IsNullOrWhiteSpace(input?.Text);
+
+ public static ModCategoryEditor Create(IEnumerable categories)
+ {
+ var editor = TscnScenes.LoadAndBuild("scenes/components/mod_category_editor.tscn") as ModCategoryEditor
+ ?? throw new InvalidOperationException("Category editor scene unavailable");
+ editor.SetCategories(categories);
+ return editor;
+ }
+
+ public static string ProjectRoot => GameEnvironment.IsRuntime ? GamePaths.Globalize("res://") : System.IO.Directory.GetCurrentDirectory();
+
+ public void SetCategories(IEnumerable categories)
+ {
+ EnsureConstructed();
+ selected.Clear();
+ selected.AddRange(ModCategories.Effective(categories));
+ known.Clear();
+ known.AddRange(ModCategories.Normalize(ModCategoryNames.Known().Concat(selected)));
+ Refresh();
+ }
+
+ public void SetEditable(bool value)
+ {
+ editable = value;
+ EnsureConstructed();
+ Refresh();
+ }
+
+ protected override void Construct()
+ {
+ input = GetNode("Layout/Input/Code");
+ suggestions = GetNode("Layout/Suggestions");
+ primary = GetNode("Layout/PrimaryRow/Primary");
+ input.TooltipText = Tr("mod_categories/hint_code");
+ suggestions.TooltipText = Tr("mod_categories/hint_suggestions");
+ primary.TooltipText = Tr("mod_categories/hint_primary");
+ GetNode