(function () {
  const TUTORIALS = {
    "setup-gate": {
      advanced: {
        title: "Advanced Workflow Setup",
        body: "The main tools stay locked until Windows Long Paths, the AC EVO Game Root, fully extracted game resources, Storage Health and Car Analysis are ready. This prevents Advanced file operations from starting with an incomplete runtime or workspace.",
      },
      official: {
        title: "Official Workflow Setup",
        body: "Complete Windows Long Paths and the three Official setup steps to unlock this workflow. Official Runtime may restore content.kspkg, switch LiveryLab-managed SavedCars and remove Advanced Safety hooks after confirmation. Preview preparation only reads the required packaged resources into local LiveryLab storage.",
      },
    },
    "setup-long-paths": {
      title: "Windows Long Paths",
      body: "Required for both workflows. LiveryLab automatically verifies that the running app can create, rename and delete files beyond the legacy 259-character limit. If the test fails, use the included BAT helper or the manual Windows instructions before continuing.",
    },
    "setup-document-root": {
      advanced: {
        title: "AC EVO Game Root",
        body: "Choose the AC EVO installation root here. LiveryLab reads car data from this folder and only writes to game files through explicit actions such as Activate in Game.",
      },
      official: {
        title: "AC EVO Game Folder",
        body: "Select the AC EVO installation folder that contains the AC EVO content package, then save it. A valid renamed content.kspkg is recognized as well. LiveryLab reads the packaged car resources required for Official projects while generated files remain in LiveryLab-managed storage.",
      },
    },
    "setup-extract-package": {
      title: "Extract Advanced Game Resources",
      body: "The Advanced workflow requires a complete content.kspkg extraction so LiveryLab can inspect and modify loose car resources. Keep at least 72 GB free and allow roughly 15-20 minutes. After extraction, content.kspkg is disabled or renamed so AC EVO uses the loose content. Run this step again after game updates change the package.",
    },
    "setup-storage-health": {
      title: "Storage Health",
      body: "Run this check to verify LiveryLab folders, game write access and texture conversion tools before you start creating or syncing liveries.",
    },
    "setup-car-analysis": {
      title: "Car Analysis",
      body: "This scan classifies cars as Ready or Unsupported so the app can guide the right livery workflow for each car.",
    },
    "setup-official-runtime": {
      title: "Prepare Official Runtime",
      body: "Ensures content.kspkg is active, switches LiveryLab-managed SavedCars to the Official workspace and removes Advanced LiveryLab Safety hooks when needed. Changes are shown for confirmation first. Existing extracted content remains available for a later switch back to Advanced.",
    },
    "setup-official-car-resource-extract": {
      title: "Official Preview Resources",
      body: "The Official creator needs car metadata, models, materials and textures that are stored inside content.kspkg. LiveryLab temporarily extracts only those required entries into its local workspace and prepares reusable 3D models, UV templates, AO textures and thumbnails. This is not a full game extraction, does not modify AC EVO and can take around 10 minutes.",
    },
    "setup-official-prepare-resources": {
      title: "Prepare Preview Resources",
      body: "Starts the partial package extraction and local preview preparation for the Official car catalog. The first run can take around 10 minutes depending on system speed. You can cancel and continue later; temporary source files remain in the local LiveryLab cache until preparation completes successfully.",
    },
    "skin-creator-template-start": {
      title: "Source design",
      body: "Start with an existing AC EVO .cardesign file. It is the key source file LiveryLab uses to trace the matching .design, actor, visual preset, mechanical preset and car final state.",
    },
    "skin-creator-cardesign": {
      title: ".cardesign file",
      body: "This file is essential. In the file browser, green workflow hints point you toward usable skin templates. The typical target is content\\cars\\<car_id>\\skins\\<design_id>.cardesign.",
    },
    "skin-creator-compatibility": {
      title: "Template status",
      body: "Ready templates can be used for the livery workflow, including templates where LiveryLab generates the skin-local setup. Unsupported means the selected .cardesign is missing part of the preset chain or required texture setup.",
    },
    "skin-creator-advanced-files": {
      title: "Advanced template files",
      body: "These linked files are auto-filled from the .cardesign whenever possible. Open them only when you need to inspect or correct the detected actor, visual, mechanical or final-state chain.",
    },
    "skin-creator-identity": {
      advanced: {
        title: "Livery identity",
        body: "The livery name is the readable label. LiveryLab derives a stable Skin ID from it for folders and internal references, so choose a name before creating the skin.",
      },
      official: {
        title: "Official Livery Identity",
        body: "The livery name is used inside LiveryLab and to generate the technical Skin ID and ExternalLiveries folder name. AC EVO does not currently display this custom livery name in game. Author and description are optional project and package metadata. Choose the final name before creating the project.",
      },
    },
    "skin-creator-actions": {
      advanced: {
        title: "Create skin",
        body: "Analyze checks the selected template. Create Skin builds the local project and new livery files; it does not activate the skin in AC EVO until you use Activate or Update in Game from My Liveries.",
      },
      official: {
        title: "Create Official Project",
        body: "Creates an editable local workspace in OfficialLiveryProjects with external_livery.json, a blank EXT_Skin_C.png and a prepared garage SavedCar. Nothing is written to Saved Games or the AC EVO installation during project creation. Edit the texture first and then use Activate in Game. After activation, you will find the corresponding car and livery in your AC EVO garage.",
      },
    },
    "skin-creator-official-car-catalog": {
      title: "Choose an Official Car",
      body: "This catalog shows cars with prepared Official resources and at least one variant compatible with AC EVO ExternalLiveries. Select the car you want to create the livery for. Use the star to keep frequently used cars in Favorites.",
    },
    "skin-creator-official-saved-car": {
      title: "Automatic Garage SavedCar",
      body: "LiveryLab generates a matching garage SavedCar from the selected vehicle variant and stores it inside the local project. It is installed in Saved Games only when you first choose Activate in Game. Creating the project does not modify your AC EVO garage.",
    },
    "skin-creator-official-preview-resources": {
      title: "3D Workflow Resources",
      body: "These prepared resources provide the car model, UV layout and other assets used by Layer Studio and the live 3D Preview. If they are not ready, return to Setup, prepare the Official Preview Resources and then refresh the car list.",
    },
    "skin-creator-official-vehicle-variant": {
      title: "Vehicle Variant / Trim",
      body: "Choose the vehicle configuration this livery should use in the garage. The selected mechanical, visual and car-state references are used to generate the matching SavedCar. This selection does not install anything or change the livery artwork.",
    },
    "preview3d-setup": {
      title: "3D setup",
      body: "This setup screen stores the model, live texture and optional AO texture used by the older 3D Preview pipeline. My Liveries can also open the prepared livery preview directly.",
    },
    "preview3d-source-files": {
      title: "Preview sources",
      body: "Choose a .glb or .gltf model and the PNG texture you want to inspect. Auto-refresh watches the PNG so external paint changes can appear in the preview workflow.",
    },
    "preview3d-live-view": {
      title: "Live preview",
      body: "This area shows the loaded model and current texture. Use Load 3D view after saving setup, or open a prepared preview from My Liveries for the richer livery workspace.",
    },
    "preview3d-view-menu": {
      title: "View options",
      body: "Show or hide the exterior model, rims, floor and scene presets without changing the livery files. These options are only for the preview view.",
    },
    "preview3d-texture-menu": {
      title: "Texture view",
      body: "Switch between livery texture channels and reload the current texture after editing. EXT_SKIN_C is the main color layer; EXT_Skin_D is used for material masks where available.",
    },
    "preview3d-material-menu": {
      title: "Material tools",
      body: "Paint Finish and material tools help inspect how the livery will read on the car. Saving material changes can affect local skin material data, so use them deliberately.",
    },
    "preview3d-numberplate-panel": {
      title: "Numberplate placement",
      body: "This editor is for previewing and saving numberplate placement changes locally. Use Apply Saved Placements to Skin before updating the active livery in game.",
    },
    "drivers-create": {
      title: "Create driver profile",
      body: "Driver profiles are reusable local driver asset sets. Start from a supported My Skin so LiveryLab can copy the correct helmet, suit, gloves and visor structure.",
    },
    "drivers-list": {
      title: "Driver library",
      body: "Saved profiles live in the local DriverProfiles library. They can be selected by supported skins and are included when exported packages need them.",
    },
    "drivers-detail": {
      title: "Driver detail",
      body: "The detail panel shows the selected profile and its editable assets. Changes stay local until a skin using the profile is activated or updated in game.",
    },
    "drivers-preview-3d": {
      title: "Driver 3D preview",
      body: "Opens the driver preview for this profile when PNG sources are available. Use it to check helmet, suit, gloves and visor changes before syncing skins.",
    },
    "drivers-save-appearance": {
      title: "Save appearance",
      body: "Stores local appearance and color edits for this driver profile. Skins using the profile may need Update in Game before the change appears in AC EVO.",
    },
    "drivers-project-folder": {
      title: "Driver project folder",
      body: "Opens the editable driver project files, including PNG sources and metadata. Keep this folder if you want to preserve or back up editable driver work.",
    },
    "drivers-export-package": {
      title: "Export driver package",
      body: "Creates a portable package for this driver profile and its supported project assets so it can be shared or reinstalled later.",
    },
    "drivers-remove": {
      title: "Remove driver profile",
      body: "Removes the local driver profile from LiveryLab. Check which skins use it before deleting, because those skins may fall back to default driver assets.",
    },
    "tyres-library": {
      title: "Tyre brand library",
      body: "Tyre brands are local reusable assets. A skin can reference one brand, and LiveryLab copies the generated tyre textures into AC EVO during Update in Game.",
    },
    "tyres-template-packages": {
      title: "Tyre packages",
      body: "Import and Export move saved tyre brand templates. Download Tyre Brand Template gives you source files for building slick and blur PNGs outside LiveryLab.",
    },
    "tyres-preview": {
      title: "Tyre preview",
      body: "The preview shows the slick and blur tyre textures generated from your PNG inputs. Use it to check that the sidewall branding reads correctly before saving.",
    },
    "tyres-editor": {
      title: "Tyre editor",
      body: "Choose a base template, provide slick and blur color PNGs, and optionally add a square brand mark. Save Template stores the result in LiveryLab local storage.",
    },
    "tyres-png-inputs": {
      title: "Slick and blur PNGs",
      body: "Choose the two tyre sidewall source PNGs. Slick is the normal tyre texture; blur is the motion version used by the game.",
    },
    "tyres-mark-input": {
      title: "Brand mark",
      body: "An optional square PNG can be used as the brand mark source. It helps keep a reusable logo separate from the full tyre sidewall textures.",
    },
    "tyres-save-template": {
      title: "Save tyre template",
      body: "Save Template stores the generated tyre brand locally. Skins only receive the tyre textures after you assign the brand and update the skin in game.",
    },
    "custom-grids-library": {
      title: "Grid presets",
      body: "Custom Grids are local race-grid presets built from registered My Liveries. They help rebuild or share a lineup without editing every livery again.",
    },
    "custom-grids-actions": {
      title: "Grid actions",
      body: "New Grid creates a local preset. Export and Import move grid presets as packages so they can be shared or restored later.",
    },
    "custom-grids-detail": {
      title: "Grid detail",
      body: "The detail view contains the grid entries and per-entry settings. Entries usually come from My Liveries, so the livery library is the source for selectable skins.",
    },
    "custom-grids-ai-spec": {
      title: "AI vehicle spec",
      body: "Standard works for every grid entry. Endurance is only available when the selected car has compatible Endurance or Lumirank parts; unsupported entries fall back to Standard.",
    },
    "online-league-import-pack": {
      title: "Import League Pack",
      body: "Choose a LiveryLab League ZIP here. LiveryLab inspects it before import and stores it in the local League library; importing does not activate or write its liveries to AC EVO.",
    },
    "online-league-installed-packs": {
      title: "Installed Packs",
      body: "Activate deploys the pack to AC EVO's ExternalLiveries folder for online sessions. Deactivate preserves liveries still used by another pack or already installed as normal liveries. Delete permanently removes the imported pack and any liveries owned only by it after confirmation.",
    },
    "online-league-saved-drafts": {
      title: "Saved Pack Drafts",
      body: "Drafts are local organizer projects kept separate from My Liveries and installed packs. Create a new pack or select a saved draft to continue editing its details and livery list.",
    },
    "online-league-pack-liveries": {
      title: "Pack Liveries",
      body: "Add exported Official livery ZIPs, or one direct ExternalLiveries folder at a time. Advanced liveries, SavedCars and unsupported files are rejected. Preflight checks every entry and reports warnings or blocking errors.",
    },
    "online-league-build-pack": {
      title: "Build League Pack",
      body: "Build Pack exports a distributable League ZIP containing ExternalLiveries only. It does not include Garage SavedCars or write to AC EVO. Errors always block export; enable Include warnings only to accept non-blocking warnings.",
    },
    "numberplate-library": {
      title: "Numberplate templates",
      body: "Templates store reusable baked numberplate setups with backgrounds and font data. They stay in LiveryLab storage and can be exported or imported as packages.",
    },
    "numberplate-template-packages": {
      title: "Template packages",
      body: "Import and Export move saved numberplate templates as reusable packages. Download numberplate template gives you a blank image source for creating new backgrounds outside LiveryLab.",
    },
    "numberplate-preview": {
      title: "Baked preview",
      body: "These previews show the left door, right door and hood PNG output before export. Use them to check number placement, scale, spacing and color.",
    },
    "numberplate-editor": {
      title: "PNG inputs",
      body: "Choose square background PNGs for the surfaces and a 1024x512 font PNG. LiveryLab bakes the start number onto exported PNGs for your paint workflow.",
    },
    "numberplate-background-inputs": {
      title: "Surface backgrounds",
      body: "Use square PNG backgrounds for left door, right door and hood. They are local template sources; they are not written into AC EVO by themselves.",
    },
    "numberplate-font-input": {
      title: "Baked number font",
      body: "Use a 1024x512 PNG font atlas for the digits. LiveryLab combines this font with the selected backgrounds when exporting baked numberplate PNGs.",
    },
    "numberplate-text-controls": {
      title: "Number layout",
      body: "Adjust text position, scale, spacing, color and alpha here. These values affect the baked PNG export, not a live in-game numberplate material.",
    },
    "numberplate-actions": {
      title: "Save and export",
      body: "Save Template stores the reusable setup in LiveryLab. Export PNGs creates baked graphics for your paint workflow; place those PNGs on the livery texture in your image editor.",
    },
    "layer-studio-actions": {
      title: "Layer Studio actions",
      body: "Save Layers stores the editable layer document. Update Texture bakes the current layer stack into the preview texture; game-visible changes still need to be saved or exported and updated from My Liveries.",
    },
    "layer-studio-layers": {
      title: "Layer stack",
      body: "This list is the editable layer document for the selected texture surface. Select layers here to edit their position, colors, masks or grouping.",
    },
    "layer-studio-tools": {
      title: "2D tools",
      body: "Use these tools to place PNGs, draw shapes, create text and edit layer geometry directly on the texture canvas.",
    },
    "layer-studio-properties": {
      title: "Layer properties",
      body: "These fields edit the selected layer. Values are saved with the Layer Studio project and are only baked into the texture when you update or export.",
    },
    "layer-studio-preview": {
      title: "3D live preview",
      body: "The 3D view lets you check the baked texture on the car while editing. It is a preview surface, not an automatic game activation.",
    },
    "settings-official-trash-overview": {
      title: "Official Livery Trash",
      body: "This area lists editable Official projects and read-only library copies that were moved to LiveryLab-managed trash after removal from My Liveries. It does not list liveries that were only deactivated. Actions here affect local LiveryLab storage only.",
    },
    "settings-official-trash-list": {
      title: "Deleted Official Liveries",
      body: "Select an entry to review its deletion date, car, storage role and restore status. Project files identifies an editable project; Local files identifies a read-only library copy. Restore is blocked if the original target already exists or the trash entry is incomplete.",
    },
    "settings-official-trash-open": {
      title: "Open Selected Trash Folder",
      body: "Opens the LiveryLab-managed trash folder for the selected entry in File Explorer. This does not restore or change the livery. Manual changes inside this folder may prevent LiveryLab from restoring it.",
    },
    "settings-official-trash-restore": {
      title: "Restore Official Livery",
      body: "Moves the stored project or library copy back to its original local folder and registers it in My Liveries again. The restored livery remains inactive and nothing is written to Saved Games or AC EVO. Use Activate in Game when you want to install it again.",
    },
    "settings-official-trash-delete": {
      title: "Delete Selected Permanently",
      body: "Permanently deletes the selected trash entry, including its stored Official project or library files and trash manifest. It cannot be restored through LiveryLab afterwards. This does not modify Saved Games or the AC EVO installation.",
    },
    "settings-official-trash-delete-all": {
      title: "Delete All Permanently",
      body: "Permanently deletes every listed Official trash entry and its stored local files. Entries that cannot be deleted are reported individually. This action does not modify Saved Games or AC EVO files.",
    },
    "settings-transfer": {
      advanced: {
        title: "Backup and transfer",
        body: "This creates or imports a portable ZIP for LiveryLab workspace data such as settings, local skins, driver profiles, tyre brands, grids and numberplate templates.",
      },
      official: {
        title: "Official Workspace Transfer",
        body: "Use Workspace Transfer for a broader backup or move of LiveryLab data. It can preserve read-only Official libraries, editable Official projects, their required SavedCars, settings and selected project data.",
      },
    },
    "settings-transfer-export": {
      advanced: {
        title: "Transfer export",
        body: "Choose which local data should go into the transfer ZIP and where to write it. Export does not touch AC EVO game files.",
      },
      official: {
        title: "Export Official Workspace",
        body: "Select the categories and individual liveries to include, then review the export summary. The ZIP is written to the selected local folder and does not modify Saved Games or the AC EVO installation.",
      },
    },
    "settings-transfer-import": {
      advanced: {
        title: "Transfer import",
        body: "Choose a transfer ZIP and inspect it first. Import Selected only unlocks after inspection, because imported data can replace local LiveryLab library entries.",
      },
      official: {
        title: "Inspect Workspace Transfer",
        body: "Choose a Workspace Transfer ZIP and inspect it before importing. Inspection lists its available categories without changing local data. Imported categories may replace existing LiveryLab entries.",
      },
    },
    "settings-transfer-import-action": {
      advanced: {
        title: "Import selected",
        body: "This imports the checked categories from the inspected transfer package. LiveryLab keeps import backups in its own data area before replacing local entries.",
      },
      official: {
        title: "Import Selected Workspace Data",
        body: "Imports only the selected categories from the inspected ZIP. LiveryLab creates local backups, restores Official project and library roles, and adjusts portable project paths for this installation. Liveries remain inactive until you activate them from My Liveries.",
      },
    },
    "skin-pack-overview": {
      advanced: {
        title: "Skin Pack",
        body: "Skin packs are for sharing selected My Liveries entries without moving the whole workspace. They restore categories and known livery dependencies, but they are narrower than a Workspace Transfer.",
      },
      official: {
        title: "Official Skin Pack",
        body: "A Skin Pack bundles all liveries from one Official My Liveries category for sharing. It preserves category assignments and supported livery data, but it is narrower than a Workspace Transfer and does not activate any liveries.",
      },
    },
    "skin-pack-export": {
      advanced: {
        title: "Export skin pack",
        body: "Choose one My Liveries category and an export folder. LiveryLab creates a shareable ZIP with the selected liveries and known dependencies; it does not change AC EVO game files.",
      },
      official: {
        title: "Export Official Skin Pack",
        body: "Choose one Official My Liveries category and an export folder. LiveryLab creates a ZIP containing the liveries in that category and the supported dependencies it can identify. The export does not modify Saved Games or AC EVO.",
      },
    },
    "skin-pack-import": {
      advanced: {
        title: "Import skin pack",
        body: "Use this for skin-pack ZIPs that contain My Liveries only. Inspect the ZIP first so LiveryLab can show what will be imported before adding it to your local library.",
      },
      official: {
        title: "Inspect Official Skin Pack",
        body: "Choose a Skin Pack ZIP and inspect it first. Inspection verifies that the ZIP contains My Liveries data only and shows what can be imported without changing local files.",
      },
    },
    "skin-pack-import-action": {
      advanced: {
        title: "Import inspected pack",
        body: "Import becomes available after inspection. Imported liveries are added to My Liveries with their categories restored where possible.",
      },
      official: {
        title: "Import Official Skin Pack",
        body: "Imports the inspected liveries and restores their category assignments and Official storage roles where possible. LiveryLab backs up local entries before replacing them. Imported liveries are not activated automatically.",
      },
    },
    "my-skins-detail-head": {
      advanced: {
        title: "Skin detail",
        body: "This header shows the selected livery, its car and the current local/game state. Badges here tell you whether the skin is active, needs an update or is read-only.",
      },
      official: {
        title: "Official Livery Status",
        body: "Shows the selected livery, its assigned car and its current local and game state. Status badges indicate whether the livery is active, read-only or needs to be updated in Saved Games.",
      },
    },
    "my-skins-library": {
      advanced: {
        title: "Livery Library",
        body: "This list contains the liveries registered with LiveryLab. Select a livery to preview it, review its status and access the available project and game actions.",
      },
      official: {
        title: "Official Livery Library",
        body: "This list contains editable Official projects and read-only Official liveries installed or detected locally. Select a livery to preview it, review its status and access the available game actions.",
      },
    },
    "my-skins-install-livery": {
      title: "Install Livery",
      body: "Opens Import / Export for installing a LiveryLab package. Imported liveries are added locally first and are not activated in AC EVO until you choose Activate in Game.",
    },
    "my-skins-preview-3d": {
      advanced: {
        title: "3D Livery Preview",
        body: "Opens the local preview workflow for this livery. It prepares preview data from the selected skin without activating anything in AC EVO.",
      },
      official: {
        title: "Live 3D Preview",
        body: "Use this view while editing the livery textures in an external image editor such as Photoshop, GIMP or Affinity Photo. It displays the PNG textures directly from the Official project folder and automatically reloads saved changes on the 3D car. Previewing does not activate or update the livery in AC EVO.",
      },
    },
    "my-skins-preview-3d-read-only": {
      title: "3D Livery Preview",
      body: "Inspect this read-only livery on the 3D car. The preview uses its local library textures, but they cannot be edited or live-reloaded as an Official project.",
    },
    "my-skins-layer-studio": {
      advanced: {
        title: "Layer Studio",
        body: "Opens the editable Layer Studio project for this livery when available. Use it for layered PNG-based livery work; changes stay local until you save, export and update the skin in game.",
      },
      official: {
        title: "Edit in Layer Studio",
        body: "Opens the editable layer project for this Official livery. Changes remain in OfficialLiveryProjects until they are saved and deployed with Update in Game.",
      },
    },
    "my-skins-start-game": {
      title: "Start game",
      body: "Starts AC EVO through Steam. Steam must be running and logged in for this button to work.",
    },
    "my-skins-activate-game": {
      advanced: {
        title: "Activate or update",
        body: "Syncs the local livery state into the AC EVO game folder. LiveryLab shows write confirmations and uses its backup-aware game-write workflow for game-facing changes.",
      },
      official: {
        title: "Activate, Update or Deactivate",
        body: "Activate deploys external_livery.json and its referenced PNG files to Saved Games and restores or installs the matching garage SavedCar. After activation, open Vehicles → My Cars to find the livery. Official External Liveries do not appear in Vehicle Hub, and AC EVO does not currently display the custom livery name. Update redeploys local changes. Deactivate moves the deployment and SavedCar into LiveryLab-managed disabled storage so they can be restored later.",
      },
    },
    "my-skins-project-folder": {
      advanced: {
        title: "Project folder",
        body: "Opens the editable LiveryProjects folder for this skin. This folder contains project source files, exported PNG textures, Layer Studio data, thumbnails and metadata, so it is the main place to keep or back up editable work.",
      },
      official: {
        title: "Official Project Folder",
        body: "Opens the editable source folder in OfficialLiveryProjects. This folder contains the project PNG textures, Layer Studio data, thumbnail and metadata. Opening it does not change the active Saved Games deployment.",
      },
    },
    "my-skins-export-package": {
      advanced: {
        title: "Export package",
        body: "Creates a portable ZIP package for sharing or transfer. Package export stays local and includes supported dependencies such as tyres or driver profiles when needed.",
      },
      official: {
        title: "Export Official Package",
        body: "Creates a portable Official livery package from the editable project. The exported package remains local and does not activate or update the livery in AC EVO.",
      },
    },
    "my-skins-remove": {
      advanced: {
        title: "Remove tools",
        body: "Opens removal actions for this livery. Use these when you want to deactivate, remove from game, move to trash or clean up local data intentionally.",
      },
      official: {
        title: "Remove Official Livery",
        body: "Opens the removal confirmation for this livery. An active Official livery is deactivated first. Depending on the available option, its local library or project files can then be moved to LiveryLab-managed trash.",
      },
    },
    "my-skins-runtime-guard": {
      official: {
        title: "Official Runtime Required",
        body: "Official game actions require an active content.kspkg and accessible Saved Games folders. Resolve the setup warning before using Activate, Update or Deactivate. Local project files remain unchanged while these actions are blocked.",
      },
      default: {
        title: "Game Actions Unavailable",
        body: "Resolve the displayed setup or runtime warning before using game-facing actions. Local project files remain unchanged while these actions are blocked.",
      },
    },
    "my-skins-read-only": {
      advanced: {
        title: "Read-only livery",
        body: "Installed package skins keep creator-authored metadata and assets locked. You can still preview, activate, deactivate or remove them.",
      },
      official: {
        title: "Read-only Official Livery",
        body: "This is an installed or detected library copy, not an editable project. You can preview, activate, deactivate or remove it, but its source textures and metadata cannot be edited.",
      },
    },
    "my-skins-game-update": {
      advanced: {
        title: "Update needed",
        body: "Local settings have changed after the last game sync. Use Update in Game when you want the current local state to appear in AC EVO.",
      },
      official: {
        title: "Official Update Required",
        body: "A deployable project file or setting has changed since the livery was activated. Use Update in Game to redeploy the current external_livery.json and PNG files to Saved Games.",
      },
    },
    "my-skins-road-plate-missing": {
      title: "Missing road plate source",
      body: "This road-car livery expects a custom rear plate project texture, but the source file is missing. Restore the project file before activating or updating the skin.",
    },
    "my-skins-project-assets-missing": {
      title: "Missing project assets",
      body: "Critical project files are missing. LiveryLab blocks activation because the local skin cannot be rebuilt safely without these source assets.",
    },
    "my-skins-project-assets-warning": {
      title: "Project asset warning",
      body: "Some optional project files are missing or unusual. Review the project folder before updating the skin if you expect those assets to be part of the livery.",
    },
    "my-skins-edit-section": {
      advanced: {
        title: "Edit skin",
        body: "Edit local metadata for created/project skins. The preview uses the project's livery_thumbnail.png; replace that file in the project folder or import an AC EVO snapshot.",
      },
      official: {
        title: "Official Livery Details",
        body: "Editable Official projects can store an author, description, category and local thumbnail. Read-only library entries show their metadata without editing. Changing these details does not activate the livery.",
      },
    },
    "my-skins-save-project-metadata": {
      title: "Save Project Metadata",
      body: "Saves the author and description in the local Official project. This does not activate the livery or modify the files in Saved Games.",
    },
    "my-skins-save-edit": {
      title: "Save local edits",
      body: "Saves display name changes to the local My Liveries entry. It does not activate or update the skin in AC EVO by itself.",
    },
    "my-skins-save-category": {
      title: "Save category",
      body: "Stores this livery's My Liveries category. Categories also drive Skin Pack export groups, so keeping them tidy makes sharing packs easier.",
    },
    "my-skins-ace-thumbnail": {
      advanced: {
        title: "AC EVO thumbnail",
        body: "AC EVO creates its own skin snapshot after a car or livery has been saved in the garage and has been customized. Refresh only checks availability and reloads the status; Use AC EVO Thumbnail imports the AC EVO snapshot into the project livery_thumbnail.png.",
      },
      official: {
        title: "AC EVO Garage Thumbnail",
        body: "After activation, open the corresponding garage car in AC EVO, change at least one customization option and apply or save it so EVO writes a new snapshot. Return to LiveryLab, select Refresh and then use Use AC EVO Thumbnail to copy it into the editable project.",
      },
    },
    "my-skins-tyres-driver-section": {
      title: "Tyres and driver",
      body: "Assign reusable tyre brands and driver profiles to supported local skins. Active skins may need Update in Game after saving these choices.",
    },
    "my-skins-save-tyres": {
      title: "Save tyres",
      body: "Stores the selected tyre brand for this livery. If the skin is active, LiveryLab will mark it for an Update in Game when needed.",
    },
    "my-skins-save-driver": {
      title: "Save driver",
      body: "Stores the selected driver profile for supported cars. The choice remains local until the skin is activated or updated in game.",
    },
    "my-skins-numberplate-section": {
      title: "Numberplate",
      body: "Choose whether this skin uses its AC EVO default numberplate or no numberplate. Current release workflows keep numberplate editing local and conservative.",
    },
    "my-skins-save-numberplate": {
      title: "Save numberplate",
      body: "Saves the local numberplate state for this livery. Active skins may need Update in Game before the change is visible in AC EVO.",
    },
    "my-skins-storage-mode": {
      title: "Storage mode",
      body: "Shows why this livery is editable or read-only and which storage policy applies to it.",
    },
    "livery-import-overview": {
      advanced: {
        title: "Livery Import",
        body: "Import portable LiveryLab ZIP packages into My Liveries. This screen is for finished shared liveries, not editable project workspaces.",
      },
      official: {
        title: "Official Import / Export",
        body: "Use Single Livery Package for one livery, Skin Pack for one My Liveries category and Workspace Transfer for a broader LiveryLab backup. Imported liveries remain local and are not activated in AC EVO automatically.",
      },
    },
    "livery-import-zip": {
      title: "Package ZIP",
      body: "Choose the exported LiveryLab ZIP package here. Select the ZIP file itself, not an extracted folder.",
    },
    "livery-import-action": {
      advanced: {
        title: "Import package",
        body: "Imported livery packages are read-only. You can preview, activate, deactivate or remove them, but editing remains locked. Use Backup & Transfer to move a full editable workspace.",
      },
      official: {
        title: "Import Official Livery Package",
        body: "Imports the selected package into Official My Liveries. Read-only packages remain locked, editable Official packages restore their project workspace, and compatible Advanced packages can be converted into a new Official project. Importing does not activate the livery in AC EVO.",
      },
    },
  };

  let enabled = false;
  let initialized = false;
  let activeElement = null;
  let pinnedElement = null;
  let tooltip = null;

  function qs(selector) {
    return document.querySelector(selector);
  }

  function ensureTooltip() {
    if (tooltip) return tooltip;
    tooltip = document.createElement("div");
    tooltip.id = "tutorialModeTooltip";
    tooltip.className = "tutorial-mode-tooltip";
    tooltip.setAttribute("role", "tooltip");
    tooltip.hidden = true;
    tooltip.innerHTML = '<strong></strong><p></p>';
    document.body.appendChild(tooltip);
    return tooltip;
  }

  function tutorialFor(element) {
    const id = element?.getAttribute?.("data-tutorial-id") || "";
    const tutorial = TUTORIALS[id] || null;
    if (!tutorial) return null;
    const workflow = document.body?.dataset?.workflowScope === "official" ? "official" : "advanced";
    return tutorial[workflow] || tutorial.default || tutorial;
  }

  function setToggleState() {
    const button = qs("#tutorialModeToggle");
    if (!button) return;
    button.classList.toggle("is-active", enabled);
    button.setAttribute("aria-pressed", enabled ? "true" : "false");
    button.setAttribute("title", enabled ? "Hide setup guide" : "Show setup guide");
  }

  function setEnabled(nextEnabled, options = {}) {
    enabled = Boolean(nextEnabled);
    document.documentElement.classList.toggle("is-tutorial-mode", enabled);
    document.body?.toggleAttribute("data-tutorial-mode", enabled);
    setToggleState();
    if (!enabled) hideTooltip(true);
    if (options.persist) persistEnabled();
  }

  async function persistEnabled() {
    const api = window.pywebview?.api;
    if (typeof api?.save_tutorial_mode_enabled !== "function") return;
    try {
      const result = await api.save_tutorial_mode_enabled(enabled);
      if (!result?.ok) {
        console.debug("Tutorial mode preference was not persisted", result?.message || result);
      }
    } catch (error) {
      console.debug("Tutorial mode preference was not persisted", error);
    }
  }

  function positionTooltip(target) {
    if (!tooltip || tooltip.hidden || !target) return;
    const rect = target.getBoundingClientRect();
    const margin = 12;
    const maxLeft = Math.max(margin, window.innerWidth - tooltip.offsetWidth - margin);
    const left = Math.min(Math.max(rect.left, margin), maxLeft);
    let top = rect.top - tooltip.offsetHeight - margin;
    if (top < margin) top = rect.bottom + margin;
    const maxTop = Math.max(margin, window.innerHeight - tooltip.offsetHeight - margin);
    tooltip.style.left = `${left}px`;
    tooltip.style.top = `${Math.min(Math.max(top, margin), maxTop)}px`;
  }

  function showTooltip(target, options = {}) {
    if (!enabled || !target) return;
    const tutorial = tutorialFor(target);
    if (!tutorial) return;
    activeElement?.classList.remove("is-tutorial-focus");
    activeElement = target;
    if (options.pin) pinnedElement = target;
    const node = ensureTooltip();
    node.querySelector("strong").textContent = tutorial.title;
    node.querySelector("p").textContent = tutorial.body;
    node.hidden = false;
    target.classList.add("is-tutorial-focus");
    positionTooltip(target);
  }

  function hideTooltip(force = false) {
    if (!force && pinnedElement) return;
    activeElement?.classList.remove("is-tutorial-focus");
    activeElement = null;
    pinnedElement = null;
    if (tooltip) tooltip.hidden = true;
  }

  function closestTutorialElement(eventTarget) {
    return eventTarget?.closest?.("[data-tutorial-id]");
  }

  function wireEvents() {
    if (initialized) return;
    initialized = true;
    qs("#tutorialModeToggle")?.addEventListener("click", () => {
      setEnabled(!enabled, { persist: true });
    });
    document.addEventListener("pointerover", (event) => {
      const target = closestTutorialElement(event.target);
      if (!target || !tutorialFor(target)) return;
      showTooltip(target);
    });
    document.addEventListener("pointerout", (event) => {
      const target = closestTutorialElement(event.target);
      if (!target || target.contains(event.relatedTarget)) return;
      if (pinnedElement === target) return;
      hideTooltip();
    });
    document.addEventListener("focusin", (event) => {
      const target = closestTutorialElement(event.target);
      if (target) showTooltip(target);
    });
    document.addEventListener("focusout", () => hideTooltip());
    document.addEventListener("click", (event) => {
      const target = closestTutorialElement(event.target);
      if (!enabled || !target || !tutorialFor(target)) {
        if (!tooltip?.contains(event.target) && event.target?.id !== "tutorialModeToggle") hideTooltip(true);
        return;
      }
      const interactive = event.target?.closest?.("button, a, input, select, textarea, label");
      if (interactive) {
        if (pinnedElement && pinnedElement !== target) hideTooltip(true);
        showTooltip(target);
        return;
      }
      const shouldPin = pinnedElement !== target;
      hideTooltip(true);
      showTooltip(target, { pin: shouldPin });
    });
    window.addEventListener("resize", () => positionTooltip(pinnedElement || activeElement));
    window.addEventListener("scroll", () => positionTooltip(pinnedElement || activeElement), true);
  }

  function init(settings = {}) {
    wireEvents();
    ensureTooltip();
    setEnabled(Boolean(settings.tutorialModeEnabled), { persist: false });
  }

  window.LiveryLabTutorialMode = {
    init,
    setEnabled,
  };
})();
