QB / ESX

Agency-Pad

Tablet resource for FiveM running AgencyOS with a full app ecosystem. Apps can be registered via config.lua with custom icons, colors, and store descriptions. Supports custom NUI screens, Lua client/server logic, NUI callbacks, modal dialogs, and notifications. Apps can be pre-installed or available via an in-app store.

v26.4Paid3 Pages
Agency-Pad

01 Configuration

Complete config.lua for Agency-Pad. All options documented via inline comments.

Download config.lua
--[[
    Agency Pad - Configuration
    (c) Agency Scripts

    Framework Options:
    - 'auto'          : Automatically detect QBCore or ESX (default)
    - 'qb'            : Force QBCore
    - 'esx'           : Force ESX
    - 'oxide-banking' : Alias for QBCore + Oxide banking mode

    Banking Options:
    - 'framework'     : Use native framework money handling (default)
    - 'oxide-banking' : Use Oxide Banking integration mode (QBCore only)
]]

AgencyPadConfig = {}

-------------------------------------------------------------------------------
-- FRAMEWORK
-------------------------------------------------------------------------------
AgencyPadConfig.Framework = 'auto'

-------------------------------------------------------------------------------
-- BANKING
-------------------------------------------------------------------------------
AgencyPadConfig.Banking = 'framework' -- 'framework' | 'oxide-banking'
AgencyPadConfig.InvoiceProvider = 'builtin' -- 'builtin' (default - works on both Phone + Pad) | 'auto' | 'okokBilling'

-------------------------------------------------------------------------------
-- GENERAL
-------------------------------------------------------------------------------
AgencyPadConfig.PadItem = 'tablet'         -- Item name that the player needs in inventory
AgencyPadConfig.PadOpenKey = 'K'                -- Keybind to open the tablet (FiveM key name, e.g. 'UP', 'M', 'F1')
AgencyPadConfig.PadAgencyAIKey = 'I'            -- Keybind to open AgencyAI directly (e.g. 'I', 'F2', etc.)
AgencyPadConfig.EnableAgencyAI = true         -- Set to false to completely disable AgencyAI (removes app and keybind)
AgencyPadConfig.EnableAIPickupApp = true      -- Driverless pickup app toggle (true = app enabled by default)
AgencyPadConfig.EnableAIPickupViaAgencyAI = true -- AgencyAI pickup intent toggle (independent from app availability)
AgencyPadConfig.EnableMoneyGames = true       -- Toggle paid gambling-style apps (Dice, Coin Flip, Lucky Slots, Roulette)
AgencyPadConfig.UseAgencyHUD = true           -- Enable Agency-HUD integration hooks (events/state sync)
AgencyPadConfig.SyncAgencyHUD = true          -- Sync phone open/close state to Agency-HUD (events + statebag + exports)
AgencyPadConfig.PerformanceModeDefault = false -- Performance mode default (true/false)
AgencyPadConfig.PadAnswerKey = 'Y'
AgencyPadConfig.PadDeclineKey = 'J'
AgencyPadConfig.AllowMovement = false
AgencyPadConfig.DefaultLanguage = 'en'       -- Default language: 'en', 'de', 'fr', 'es', 'tr', 'pl'
AgencyPadConfig.PadDataStorageMode = 'phone'    -- 'phone' = scoped by phone number, 'person' = scoped by identifier
AgencyPadConfig.AutoApplySqlSchema = true      -- Auto-create the SQL schema from agency-pad.sql on resource start

-------------------------------------------------------------------------------
-- MDT SYSTEM
-------------------------------------------------------------------------------
AgencyPadConfig.EnableMDT = true             -- Set to false to disable the entire MDT system for Police/EMS

-------------------------------------------------------------------------------
-- CRYPTO MARKET SETTINGS
-------------------------------------------------------------------------------
-- Configure cryptocurrency markets (prices update dynamically in-game)
-- basePrice: Starting price in dollars
-- volatility: Price fluctuation rate (0.05 = 5% change per update)
-- realCrypto: Real-world cryptocurrency this is based on (for display)
AgencyPadConfig.CryptoMarkets = {
    {
        id = 'digicoin',
        name = 'DigiCoin',
        symbol = 'DGC',
        icon = '₿',
        color = '#f7931a',
        basePrice = 45000,
        volatility = 0.05,
        realCrypto = 'Bitcoin'
    },
    {
        id = 'etherchain',
        name = 'EtherChain',
        symbol = 'ETC',
        icon = '⟠',
        color = '#627eea',
        basePrice = 2800,
        volatility = 0.08,
        realCrypto = 'Ethereum'
    },
    {
        id = 'litemark',
        name = 'LiteMark',
        symbol = 'LTM',
        icon = 'Ł',
        color = '#345d9d',
        basePrice = 150,
        volatility = 0.12,
        realCrypto = 'Litecoin'
    },
    {
        id = 'ripplenet',
        name = 'RippleNet',
        symbol = 'RPN',
        icon = '✕',
        color = '#00aae4',
        basePrice = 0.85,
        volatility = 0.15,
        realCrypto = 'XRP'
    },
    {
        id = 'cardania',
        name = 'Cardania',
        symbol = 'CDA',
        icon = '₳',
        color = '#0033ad',
        basePrice = 1.25,
        volatility = 0.13,
        realCrypto = 'Cardano'
    }
}

-- Crypto update interval (milliseconds) - how often prices update
AgencyPadConfig.CryptoUpdateInterval = 10000  -- 10 seconds (also used for stocks)

-- Default buy/sell amount per transaction
AgencyPadConfig.CryptoTradeAmount = 0.1

-------------------------------------------------------------------------------
-- AGENCY AI SUPER MODE
-- Enable enhanced AI responses by connecting to a real AI API.
-- Supported providers: 'openrouter', 'grok' (alias: 'qrok')
-- Users activate Super Mode inside the AgencyAI app via the ⚡ button.
-- If no key is set, AgencyAI uses built-in offline responses.
-------------------------------------------------------------------------------
AgencyPadConfig.AIProvider = 'openrouter'   -- 'openrouter' | 'grok' | 'qrok'
AgencyPadConfig.AIFallbackProvider = 'grok' -- Optional fallback provider when primary key is missing

-- OpenRouter (recommended for free models)
AgencyPadConfig.AIOpenRouterKey = '' -- https://openrouter.ai/keys
AgencyPadConfig.AIOpenRouterModel = 'mistralai/mistral-small-3.2-24b-instruct:free'

-- Grok / xAI
AgencyPadConfig.AIGrokKey = '' -- https://console.x.ai/
AgencyPadConfig.AIGrokModel = 'grok-3-mini-beta'

-- Legacy key (still supported as fallback for compatibility)
AgencyPadConfig.AIApiKey = ''

-- Rate Limiting: max tokens a single player can use per day.
-- Set to 0 for UNLIMITED usage (no daily cap).
-- Example: 10000 = roughly 30-50 AI messages per day per player.
AgencyPadConfig.AIMaxTokensPerDay     = 0      -- 0 = unlimited
AgencyPadConfig.AIMaxTokensPerMessage = 300    -- max tokens per single AI response

-------------------------------------------------------------------------------
-- YOUTUBE / MEDIA API
-- Required for VidFlow (Video) and Music apps
-- Create your API key at: https://console.cloud.google.com
-- 1. Create a project → Enable "YouTube Data API v3"
-- 2. Create an API key under Credentials
-- 3. Paste the key below
-------------------------------------------------------------------------------
AgencyPadConfig.YouTubeAPIKey = 'AIzaSyDwO9WalMS0I7-_SQCCTOVobY3UZrc4igQ'
AgencyPadConfig.VidFlowDefaultChannelUrl = 'https://www.youtube.com/@tdyskyyt' -- Default VidFlow homepage channel
AgencyPadConfig.MusicSyncRadius = 30.0  -- Radius (meters) for nearby players to hear music
AgencyPadConfig.MusicMaxVolume = 0.5    -- Max volume for synced music (0.0-1.0)

-------------------------------------------------------------------------------
-- CALL SETTINGS
-------------------------------------------------------------------------------
AgencyPadConfig.CallTimeout = 30
AgencyPadConfig.CallRingInterval = 4000
AgencyPadConfig.CallMaxRings = 10

-------------------------------------------------------------------------------
-- VOICE SYSTEM
-- Controls which voice resource is used for phone call audio.
-- 'auto'         = Automatically detect running voice resource (recommended)
-- 'pma-voice'    = Force pma-voice
-- 'saltychat'    = Force SaltyChat
-- 'mumble-voip'  = Force mumble-voip (FiveM built-in Mumble wrapper)
-- 'tokovoip'     = Force TokoVOIP
-------------------------------------------------------------------------------
AgencyPadConfig.VoiceSystem = 'auto'

-------------------------------------------------------------------------------
-- REAL-TIME STREAMING / VIDEO CALLS
-- Cloudflare TURN is the default transport for Pictogram live streams and
-- FaceZoom video sessions.
--
-- The API token is used server-side to generate short-lived TURN credentials.
-- Do not expose the token to the browser or to public client-side scripts.
-- Sign up here: https://dash.cloudflare.com/sign-up/realtime/turn
-- Create your TURN app / token here after signup:
-- https://dash.cloudflare.com/?to=/:account/realtime/turn
-- You need the TURN Token ID and the API Token from the Cloudflare dashboard.
-------------------------------------------------------------------------------
AgencyPadConfig.StreamTransport = 'cloudflare-turn' -- 'cloudflare-turn'
AgencyPadConfig.CloudflareTurnEnabled = true
AgencyPadConfig.CloudflareTurnName = 'tight-hall-3dd2'
AgencyPadConfig.CloudflareTurnTokenId = '041fc2144ccdfc91dd636591da737c03'
AgencyPadConfig.CloudflareTurnApiToken = '3c1b82b7b89941057619efa6f51bc0fcffbf36b2efe4c04f667952111046efcf'
AgencyPadConfig.CloudflareTurnApiUrl = 'https://rtc.live.cloudflare.com/v1/turn/keys/%s/credentials/generate-ice-servers'
AgencyPadConfig.CloudflareTurnCredentialTTL = 43200 -- Seconds

-------------------------------------------------------------------------------
-- NOTIFICATION
-------------------------------------------------------------------------------
AgencyPadConfig.NotifyDuration = 5000

-- Use Agency-Notify as the default notification system
-- Free download: https://agency-script.tebex.io/package/6937769
AgencyPadConfig.UseAgencyNotify = true

-------------------------------------------------------------------------------
-- AGENCY REPORTS (Report App)
-- Integrates Agency Reports providers to let players submit reports from the phone
-- Free download: https://agency-script.tebex.io/package/6959744
-------------------------------------------------------------------------------
AgencyPadConfig.UseAgencyReports = true
AgencyPadConfig.AgencyReportsProvider = 'v2' -- 'v2' | 'v2_ad_free' | 'legacy' | 'auto'
AgencyPadConfig.AgencyReportsCommand = 'areport'

-- Opens the external Agency-LifeInvaderV2 UI instead of the internal phone app.
AgencyPadConfig.EnableLifeInvaderV2Integration = false

-- Fast navigation categories used inside the Maps app.
-- Each entry can point to one or more GTA blip sprites and is used to find the nearest matching destination.
AgencyPadConfig.MapFastNavEntries = {
    { id = 'gas',      labelKey = 'maps_gas_station',    icon = 'fa-gas-pump',             color = '#0a84ff', sprites = { 361 } },
    { id = 'market',   labelKey = 'maps_market',         icon = 'fa-basket-shopping',      color = '#ff9500', sprites = { 52, 77, 102 } },
    { id = 'atm',      labelKey = 'maps_atm',            icon = 'fa-credit-card',          color = '#30d158', sprites = { 277 } },
    { id = 'clothing', labelKey = 'maps_clothing_store', icon = 'fa-shirt',                color = '#bf5af2', sprites = { 73 } },
    { id = 'tattoo',   labelKey = 'maps_tattoo_parlor',  icon = 'fa-wand-magic-sparkles',  color = '#ff9f0a', sprites = { 75 } },
    { id = 'barber',   labelKey = 'maps_barber',         icon = 'fa-scissors',             color = '#5e72eb', sprites = { 71 } },
    { id = 'bar',      labelKey = 'maps_bar',            icon = 'fa-martini-glass-citrus', color = '#ff7a00', sprites = { 93 } },
}

-------------------------------------------------------------------------------
-- SECURITY (Face Unlock / Lock Screen)
-------------------------------------------------------------------------------
AgencyPadConfig.FaceIdDefault = false        -- Default Face Unlock state for new players
AgencyPadConfig.FaceIdAnimDuration = 2600    -- Face Unlock animation duration (ms)
AgencyPadConfig.LockScreenEnabled = true     -- Allow lock screen feature

-------------------------------------------------------------------------------
-- DIALER (Phone / Calls)
-------------------------------------------------------------------------------
AgencyPadConfig.DialerEmergencyNumber = '911'   -- Emergency number
AgencyPadConfig.DialerTestNumber = '511'        -- Always-answered local test line for call checks (set empty string to disable)
AgencyPadConfig.DialerShowRecents = true         -- Show recent calls tab
AgencyPadConfig.DialerMaxRecents = 20            -- Max recent calls to display

-------------------------------------------------------------------------------
-- DISPATCH SYSTEM (MDT Integration)
-- Controls how emergency calls/SMS are routed to police/EMS.
-- 'internal' = Use the phone's built-in dispatch system (default)
-- 'cd_dispatch' = cd_dispatch by Codesign
-- 'ps-dispatch' = ps-dispatch by Project Sloth
-- 'qs-dispatch' = qs-dispatch by Quasar
-- 'core_dispatch' = core_dispatch
-- 'custom' = Custom dispatch (fires event: agency-pad:dispatch:custom)
-------------------------------------------------------------------------------
AgencyPadConfig.DispatchSystem = 'internal'

-- Dispatch categories for internal system
AgencyPadConfig.DispatchCodes = {
    ['911']  = { type = 'emergency', priority = 'high',   label = 'Emergency Call',    departments = {'police', 'ems'} },
    ['110']  = { type = 'police',    priority = 'high',   label = 'Police Emergency',  departments = {'police'} },
    ['112']  = { type = 'ems',       priority = 'high',   label = 'Medical Emergency', departments = {'ems'} },
}

-- How long dispatches stay active (seconds, 0 = until manually cleared)
AgencyPadConfig.DispatchTimeout = 300

-- Store dispatch history in database (requires oxmysql)
AgencyPadConfig.DispatchSaveHistory = true

-------------------------------------------------------------------------------
-- BUZZ (Messages)
-------------------------------------------------------------------------------
AgencyPadConfig.BuzzMaxMessages = 50             -- Max messages per chat to load
AgencyPadConfig.BuzzAllowDelete = true           -- Allow deleting messages
AgencyPadConfig.BuzzShowTimestamps = true        -- Show timestamps on messages

-------------------------------------------------------------------------------
-- CONTACTS
-------------------------------------------------------------------------------
AgencyPadConfig.ContactsMaxCount = 100           -- Max contacts per player
AgencyPadConfig.ContactsAllowShare = true        -- Allow sharing contact info
AgencyPadConfig.ContactsDefaultSort = 'name'     -- Sort by: 'name' or 'recent'

-------------------------------------------------------------------------------
-- SNAP (Camera)
-------------------------------------------------------------------------------
-- Media storage provider used by the phone camera uploads.
-- Available values:
--   'fivemanage' = uploads to FiveManage (recommended)
--   'discord'    = uploads directly to a Discord webhook
--
-- Discord webhook attachments can expire, be deleted, or become unavailable over time.
-- That means older phone photos may disappear from gallery, posts, or stories later on.
-- For long-term media storage you should use FiveManage.
AgencyPadConfig.MediaStorageProvider = 'fivemanage'

-- FiveManage upload configuration.
-- Default upload endpoint: https://api.fivemanage.com/api/v3/file
-- The phone camera uploads the screenshot and stores the returned public URL in the database.
AgencyPadConfig.FiveManageApiUrl = 'https://api.fivemanage.com/api/v3/file'
AgencyPadConfig.FiveManageApiKey = 'u2WwwPyZUMnMVXrN0Xb0qK8IaWlM0lpi'

-- Discord webhook upload configuration.
-- Create a Discord webhook in your server:
--   1. Go to your Discord server → Channel Settings → Integrations → Webhooks
--   2. Click "New Webhook", name it (e.g. "Phone Screenshots"), choose a channel
--   3. Copy the Webhook URL and paste it below
-- The phone camera will POST screenshots as image attachments to this webhook when
-- AgencyPadConfig.MediaStorageProvider = 'discord'.
-- Leave empty ('') to disable Discord uploads.
-- Example: 'https://discord.com/api/webhooks/1234567890/abcdefg...'
AgencyPadConfig.ScreenshotWebhook = 'https://discord.com/api/webhooks/1472322564935127276/pUvnMVEyHATAUjHA-qPBJk5_3yDn-G2C5eJraufDAafYC4ka0UF_zazCKyv8o4UekMRz'
AgencyPadConfig.CameraMaxPhotos = 50             -- Max photos in gallery
AgencyPadConfig.CameraQuality = 0.85             -- Screenshot JPEG quality (0-1)

-------------------------------------------------------------------------------
-- POSTBOX (Mail)
-------------------------------------------------------------------------------
AgencyPadConfig.PostboxLoadHours = 72
AgencyPadConfig.PostboxMaxMails = 50             -- Max mails to display
AgencyPadConfig.PostboxAllowDelete = true        -- Allow deleting mails
AgencyPadConfig.PostboxMaxAccounts = 5           -- Max mailbox accounts per player
AgencyPadConfig.PostboxDefaultDomain = 'agencyg.de' -- Default mailbox domain (players choose the local part themselves)

-------------------------------------------------------------------------------
-- WALLET (Bank)
-------------------------------------------------------------------------------
AgencyPadConfig.WalletMinTransfer = 1            -- Minimum transfer amount
AgencyPadConfig.WalletMaxTransfer = 1000000      -- Maximum transfer amount
AgencyPadConfig.WalletShowHistory = false        -- Show transaction history (future)
AgencyPadConfig.WalletCurrency = '$'             -- Currency symbol

-- Agency Pay fixed-term deposits (2-5% configurable rates)
AgencyPadConfig.WalletFixedTerms = {
    { id = 'fd_7',  label = '7 Days',  days = 7,  interest = 2.0 },
    { id = 'fd_14', label = '14 Days', days = 14, interest = 3.0 },
    { id = 'fd_30', label = '30 Days', days = 30, interest = 5.0 },
}

-------------------------------------------------------------------------------
-- AGENCY PAY TERMINALS
-- Configurable nearby payment terminals used by Agency Pay quick launch,
-- quick-key detection and Agency Pay checkout.
-- coords: x, y, z, w (w optional heading)
-- amount: charged via Agency Pay / bank
-- reward: optional test reward granted after a validated successful payment
-------------------------------------------------------------------------------
AgencyPadConfig.AgencyPayTerminals = {
    {
        id = 'agency_water_terminal_1',
        coords = { x = 27.5543, y = -1343.0767, z = 29.4970, w = 0.6853 },
        radius = 2.6,
        merchant = 'Agency Water Terminal',
        title = 'Agency Pay',
        subtitle = 'Tap to buy a bottle of water',
        label = 'Water Bottle',
        amount = 1.00,
        currency = '$',
        icon = 'fa-solid fa-bottle-water',
        accent = '#5ac8fa',
        manualConfirm = true,
        autoStart = false,
        showMarker = true,
        markerDistance = 18.0,
        textDistance = 6.0,
        markerType = 1,
        markerScale = 0.34,
        markerColor = { r = 90, g = 200, b = 250, a = 185 },
        markerBob = true,
        showBlip = false,
        metadata = {
            terminalId = 'agency_water_terminal_1',
            rewardLabel = 'Water',
        },
        reward = {
            item = 'water',
            amount = 1,
        },
        serverEvent = 'agency-pad:server:handleAgencyPayTerminalPurchase',
    },
}

-------------------------------------------------------------------------------
-- GALLERY (Photos)
-------------------------------------------------------------------------------
AgencyPadConfig.GalleryMaxPhotos = 50            -- Max photos per player
AgencyPadConfig.GalleryColumnsCount = 3          -- Grid columns (2, 3, or 4)

-------------------------------------------------------------------------------
-- AGENCY CLOUD
-------------------------------------------------------------------------------
AgencyPadConfig.AgencyCloud = {
    Enabled = true,
    GalleryAutoSyncDefault = false,
    Personal = {
        Label = 'Personal Cloud',
        BaseStorageMB = 200,
        BaseAssetLimit = 50,
        PurchaseStorageMB = 250,
        PurchaseAssetCount = 25,
        PurchasePrice = 5000,
        MaxStorageMB = 5000,
        MaxAssetLimit = 1000,
        GallerySavePrice = 150,
        DocumentSavePrice = 60,
        AllowGalleryAssets = true,
        AllowDocuments = true,
        StorageTiers = {
            { id = 'plus', label = 'Plus', storageMb = 250, assetCount = 25, price = 5000 },
            { id = 'pro', label = 'Pro', storageMb = 750, assetCount = 75, price = 12000 },
            { id = 'vault', label = 'Vault', storageMb = 1500, assetCount = 160, price = 22000 },
        },
    },
    Company = {
        Label = 'Company Cloud',
        BossOnly = true,
        BaseStorageMB = 1000,
        BaseAssetLimit = 150,
        PurchaseStorageMB = 1000,
        PurchaseAssetCount = 100,
        PurchasePrice = 25000,
        MaxStorageMB = 20000,
        MaxAssetLimit = 5000,
        GallerySavePrice = 350,
        DocumentSavePrice = 180,
        AllowGalleryAssets = true,
        AllowDocuments = true,
        StorageTiers = {
            { id = 'team', label = 'Team', storageMb = 1000, assetCount = 100, price = 25000 },
            { id = 'division', label = 'Division', storageMb = 2500, assetCount = 280, price = 52000 },
            { id = 'enterprise', label = 'Enterprise', storageMb = 5000, assetCount = 650, price = 95000 },
        },
    },
    DefaultGalleryStorageBytes = 2000000,
    DefaultDocumentStorageBytes = 102400,
}

-------------------------------------------------------------------------------
-- DARKNET MARKET
-- Items available on the darknet marketplace.
-- btcPrice: Price in BTC (DigiCoin equivalent)
-- item: Item name to give player (framework item)
-- amount: How many of the item to give
-- desc: Description shown in the app
-- pickupLocations: Random locations where the dead drop can spawn.
--   The server picks one at random and sets a GPS waypoint for the buyer.
--   Add/remove locations as needed for your server map.
-------------------------------------------------------------------------------
AgencyPadConfig.DarknetItems = {
    {
        id = 'lockpick',
        label = 'Advanced Lockpick',
        desc = 'Military-grade lockpick. Untraceable.',
        btcPrice = 0.002,
        item = 'advancedlockpick',
        amount = 1,
    },
    {
        id = 'vpn',
        label = 'Burner VPN',
        desc = 'Anonymous VPN tunnel. Single use.',
        btcPrice = 0.001,
        item = 'vpn',
        amount = 1,
    },
    {
        id = 'radio',
        label = 'Encrypted Radio',
        desc = 'Frequency-hopping encrypted radio device.',
        btcPrice = 0.003,
        item = 'radio',
        amount = 1,
    },
    {
        id = 'armor',
        label = 'Kevlar Vest',
        desc = 'Level III body armor. No serial numbers.',
        btcPrice = 0.005,
        item = 'armor',
        amount = 1,
    },
}

-- Pickup (dead drop) locations where purchased items can be collected.
-- The server randomly picks one of these for each purchase.
-- Players get a GPS waypoint and must go there to pick up the item from a dumpster/trash can.
AgencyPadConfig.DarknetPickupLocations = {
    { x = 126.42,   y = -1282.71, z = 29.27,  label = 'Strawberry Alley' },
    { x = -587.53,  y = -1064.37, z = 22.34,  label = 'La Mesa Backstreet' },
    { x = 373.24,   y = -826.52,  z = 29.30,  label = 'Mission Row Dumpster' },
    { x = -1205.42, y = -906.28,  z = 12.33,  label = 'Vespucci Canal' },
    { x = 1137.86,  y = -982.34,  z = 46.42,  label = 'Murrieta Heights' },
    { x = -46.83,   y = -1758.64, z = 29.42,  label = 'Davis Industrial' },
}

-------------------------------------------------------------------------------
-- GARAGE
-- GarageSystem: Which garage script to use for vehicle data.
-- 'auto'                = Auto-detect (tries okokGarage, cd_garage, md-garage, qb-garages, qbx_garages,
--                           jg-advancedgarages, qs-advancedgarages, renewed-garage, loaf_garage, then DB fallback)
-- 'md-garage'           = Force md-garage
-- 'okokGarage'          = Force okokGarage (also accepts okokgarage)
-- 'cd_garage'           = Force cd_garage
-- 'qb-garages'          = Force qb-garages
-- 'qbx_garages'         = Force qbx_garages
-- 'jg-advancedgarages'  = Force jg-advancedgarages
-- 'qs-advancedgarages'  = Force qs-advancedgarages / qs-garages
-- 'renewed-garage'      = Force Renewed-Garage
-- 'loaf_garage'         = Force loaf_garage
-------------------------------------------------------------------------------
AgencyPadConfig.GarageSystem = 'auto'            -- Garage script to use ('auto' or script name)
AgencyPadConfig.GarageSpawnCost = 200           -- Cost to spawn a vehicle ($)
AgencyPadConfig.GarageMaxSpawned = 3            -- Max vehicles out at once per player
AgencyPadConfig.GarageCooldown = 120            -- Cooldown in seconds between vehicle requests (0 = disabled)

-- Autonomous pickup ride settings (driverless visual taxi)
AgencyPadConfig.AIPickupVehicleModel = 'stretch' -- GTA limousine look
AgencyPadConfig.AIPickupVehicleOptions = {
    { model = 'stretch', label = 'Agency Limo' },
    { model = 'neon', label = 'AgencyAI E-Sport 4S' },
    { model = 'raiden', label = 'AgencyAI Executive EV' },
}
AgencyPadConfig.AIPickupCruiseSpeed = 22.0
AgencyPadConfig.AIPickupPickupSpeed = 34.0 -- Faster approach speed while coming to player
AgencyPadConfig.AIPickupArrivalRadius = 18.0
AgencyPadConfig.AIPickupDropoffRadius = 22.0
AgencyPadConfig.AIPickupBoardingRadius = 12.0 -- Radius to press E and enter rear seats
AgencyPadConfig.AIPickupUseInvisibleDriver = true
AgencyPadConfig.AIPickupIgnoreTrafficToPickup = true -- Ignore traffic rules while driving to pickup
AgencyPadConfig.AIPickupBaseFare = 500 -- Minimum order cost (charged on request)
AgencyPadConfig.AIPickupCostPerKm = 100 -- Live billing per started kilometer during trip

-------------------------------------------------------------------------------
-- eSIM CARRIER PLANS
-- Players must choose a carrier to download apps, make calls, and send messages.
-- Each carrier has different speeds (affects app downloads, browser loading, Buzz latency, mail sending, and social posting delays), call/message limits.
-- speed: 1-5 (1=slowest, 5=fastest) - used as the full simulated network profile for the phone, no antenna / zone system required
-- calls: 'unlimited' or number (max calls per restart)
-- messages: 'unlimited' or number (max messages per restart)
-- price: monthly cost deducted from bank (for RP display only)
-------------------------------------------------------------------------------
AgencyPadConfig.CarrierPlans = {
    {
        id       = 'fleeca_mobile',
        name     = 'Fleeca Mobile',
        icon     = 'fa-solid fa-signal',
        color    = '#34c759',
        speed    = 2,
        calls    = 50,
        messages = 100,
        price    = 30,
    },
    {
        id       = 'maze_telecom',
        name     = 'Maze Telecom',
        icon     = 'fa-solid fa-tower-cell',
        color    = '#007aff',
        speed    = 3,
        calls    = 'unlimited',
        messages = 200,
        price    = 50,
    },
    {
        id       = 'lifeinvader_net',
        name     = 'LifeInvader Net',
        icon     = 'fa-solid fa-wifi',
        color    = '#5856d6',
        speed    = 4,
        calls    = 'unlimited',
        messages = 'unlimited',
        price    = 80,
    },
    {
        id       = 'lossantos_5g',
        name     = 'LS 5G Ultra',
        icon     = 'fa-solid fa-bolt',
        color    = '#ff9500',
        speed    = 5,
        calls    = 'unlimited',
        messages = 'unlimited',
        price    = 120,
    },
}

-------------------------------------------------------------------------------
-- BROWSER APP
-- Default bookmarks shown on the browser start page.
-- The in-phone browser uses FiveM/NUI webviews. Some websites with Cloudflare,
-- strict anti-bot checks, X-Frame-Options or CSP frame restrictions may still fail
-- to load there even when Agency Pad is configured correctly. That limitation is
-- caused by the FiveM webview / remote website policy, not by Agency Pad itself.
-------------------------------------------------------------------------------
AgencyPadConfig.BrowserBookmarks = {
    { name = 'Agency', url = 'https://agencyg.de', icon = 'fa-solid fa-globe', color = '#007aff' },
    { name = 'Agency Docs', url = 'https://docs.agencyg.de', icon = 'fa-solid fa-book-open', color = '#34c759' },
}

-- Leave this empty to allow all websites by default.
-- Add hosts here only if you want to restrict the browser to a curated profile.
AgencyPadConfig.BrowserAllowedWebsites = {
}

-- Optional proxy template for websites that refuse direct in-app iframe loading.
-- This can help with websites that sit behind Cloudflare or other strict web
-- protection layers, but only if your proxy service rewrites and serves them in
-- a FiveM-compatible way.
-- Supported placeholders:
--   {url}  = URL-encoded target URL
--   {raw}  = raw target URL
--   {host} = URL-encoded target host
AgencyPadConfig.BrowserProxyTemplate = ''

-- Proxy mode:
-- 'hosts' = only hosts listed in BrowserProxyHosts use the proxy (default)
-- 'all'   = all browser websites use the proxy template
AgencyPadConfig.BrowserProxyMode = 'hosts'

-- Hosts that should load through BrowserProxyTemplate when BrowserProxyMode = 'hosts'.
AgencyPadConfig.BrowserProxyHosts = {
    -- 'docs.agencyg.de',
    -- 'games.agencyg.de',
}

-- Dedicated Agency Pad games platform loaded as an exclusive fullscreen app.
AgencyPadConfig.GamesHubUrl = 'https://games.agencyg.de'

-------------------------------------------------------------------------------
-- DISCORD WEBHOOKS (Logging)
-------------------------------------------------------------------------------
-- Discord webhooks for logging phone activity to your Discord server.
-- Create a webhook for each log type you want to track:
--   Discord Server → Channel Settings → Integrations → Webhooks → New Webhook
-- Leave empty ('') to disable that specific log.
-- Each webhook will receive embedded messages with player info and action details.
AgencyPadConfig.Webhooks = {
    -- Phone activity logs
    Calls       = '',  -- Logs all phone calls (caller, receiver, duration)
    Messages    = '',  -- Logs sent messages (sender, receiver, content)
    Transfers   = '',  -- Logs bank transfers (sender, receiver, amount)
    Reports     = '',  -- Logs player reports (reporter, reason, details)

    -- Social activity logs
    Mail        = '',  -- Logs sent mail (sender, receiver, subject)

    -- App activity logs
    AppInstalls = '',  -- Logs app installs/uninstalls (player, app name)
    Screenshots = '',  -- Logs camera screenshots (player, image URL) — uses ScreenshotWebhook above if this is empty
    Gambling    = '',  -- Logs game results (player, game, bet, win/loss, amount)

    -- Vehicle / Garage logs
    Garage      = '',  -- Logs vehicle spawns (player, model, plate, cost)

    -- Agency Drop logs
    AirDrop     = '',  -- Logs Agency Drop shares (sender, receiver, item/contact)
}

-------------------------------------------------------------------------------
-- AGENCY EATS (Delivery App)
-- Restaurant pickup locations for the delivery job.
-- Players must drive to these coords to pick up orders.
-------------------------------------------------------------------------------
AgencyPadConfig.EatsRestaurants = {
    { name = 'Burger Shot',    x = -1196.42, y = -891.35,  z = 14.0  },
    { name = "Cluckin' Bell",  x = -72.68,   y = 6253.11,  z = 31.09 },
    { name = 'Pizza This',     x = 540.66,   y = 101.25,   z = 96.44 },
    { name = 'Bean Machine',   x = -628.16,  y = 236.60,   z = 81.97 },
    { name = 'Up-n-Atom',      x = 89.95,    y = 289.42,   z = 110.21 },
    { name = 'Taco Bomb',      x = 12.04,    y = -1605.57, z = 29.37 },
}

-- Delivery pay: distance-based ($ per kilometer driven)
AgencyPadConfig.EatsPayPerKm = 20
-- Minimum / maximum delivery pay (caps)
AgencyPadConfig.EatsPayMin = 15
AgencyPadConfig.EatsPayMax = 200

-- Pickup radius: how close the player must be to mark order as picked up (meters)
AgencyPadConfig.EatsPickupRadius = 15.0

-------------------------------------------------------------------------------
-- JOB-SPECIFIC APPS
-- Configure which framework job names correspond to each job app.
-- Players with these jobs can see and download the respective apps.
-- Add or remove job names as needed for your server.
-------------------------------------------------------------------------------
-- MDT Discord links (leave empty to hide the button)
AgencyPadConfig.PoliceMDTDiscord = 'https://discord.gg/RTax3aBMUs'
AgencyPadConfig.EMSMDTDiscord    = 'https://discord.gg/RTax3aBMUs'

-- Department Organization Management
-- Each department has its own email, bank account, ranks with salaries
AgencyPadConfig.DepartmentOrgs = {
    police = {
        label       = 'Police Department',
        email       = '[email protected]',
        bankUnlimited = true,
        bankStartBalance = 0,
        ranks = {
            { grade = 0, label = 'Cadet',       salary = 1500 },
            { grade = 1, label = 'Officer',     salary = 2500 },
            { grade = 2, label = 'Sergeant',    salary = 3500 },
            { grade = 3, label = 'Lieutenant',  salary = 4500 },
            { grade = 4, label = 'Captain',     salary = 5500 },
            { grade = 5, label = 'Chief',       salary = 7000, isBoss = true },
        },
    },
    ems = {
        label       = 'Emergency Medical Services',
        email       = '[email protected]',
        bankUnlimited = true,
        bankStartBalance = 0,
        ranks = {
            { grade = 0, label = 'Trainee',     salary = 1200 },
            { grade = 1, label = 'Paramedic',   salary = 2200 },
            { grade = 2, label = 'Doctor',      salary = 3200 },
            { grade = 3, label = 'Supervisor',  salary = 4200 },
            { grade = 4, label = 'Chief Doctor', salary = 5500, isBoss = true },
        },
    },
    mechanic = {
        label       = 'Mechanic Shop',
        email       = '[email protected]',
        bankUnlimited = false,
        bankStartBalance = 50000,
        ranks = {
            { grade = 0, label = 'Apprentice',  salary = 1000 },
            { grade = 1, label = 'Mechanic',    salary = 2000 },
            { grade = 2, label = 'Senior',      salary = 3000 },
            { grade = 3, label = 'Manager',     salary = 4000, isBoss = true },
        },
    },
}

AgencyPadConfig.JobApps = {
    police = {
        appId    = 'police_mdt',
        jobNames = {'police', 'pd', 'lspd', 'bcso', 'sheriff'},
    },
    ems = {
        appId    = 'ems_mdt',
        jobNames = {'ambulance', 'ems', 'doctor', 'medic', 'fire'},
    },
    mechanic = {
        appId    = 'mechanic_mdt',
        jobNames = {'mechanic', 'adac', 'bennys', 'lscustoms', 'tuner'},
    },
}

-------------------------------------------------------------------------------
-- JOBS APP LISTINGS
-- Used by the "Jobs" app (employment).
-- You can fully edit/remove/add entries here.
-- Fields:
--  id, title, company, location, salary, type, description, color, x, y, phone
-------------------------------------------------------------------------------
-- Employment listings are now dynamically populated from the Business App.
-- Players can post job listings through their businesses.
-- You can still add static listings below if needed (they will appear alongside business listings).
AgencyPadConfig.EmploymentListings = {
    -- Static listings (optional, add your own here)
    -- Business-created listings are loaded dynamically from the database
}

-------------------------------------------------------------------------------
-- BUSINESS MANAGEMENT APP
-- Allows players to create and manage their own companies.
-- Backend options:
--   'default'         : Built-in Agency business system (standalone, DB-based)
--   'qb-management'   : Integrates with qb-management
--   'ren-businesses'  : Integrates with ren-businesses
--   'qb-businesses'   : Integrates with qb-businesses (Renewed)
-------------------------------------------------------------------------------
AgencyPadConfig.EnableBusinessApp = true
AgencyPadConfig.EnableGangsApp = true
AgencyPadConfig.BusinessBackend = 'default'      -- 'default' | 'qb-management' | 'ren-businesses' | 'qb-businesses'
AgencyPadConfig.BusinessCreationCost = 50000     -- Cost ($) to register a new business
AgencyPadConfig.BusinessMaxPerPlayer = 3         -- Max businesses a player can own
AgencyPadConfig.BusinessMaxEmployees = 20        -- Max employees per business
AgencyPadConfig.BusinessCategories = {
    { id = 'retail',       label = 'Retail Store',     icon = 'fa-store',        color = '#ff9500' },
    { id = 'food',         label = 'Food & Drink',     icon = 'fa-utensils',     color = '#ff3b30' },
    { id = 'services',     label = 'Services',         icon = 'fa-briefcase',    color = '#007aff' },
    { id = 'automotive',   label = 'Automotive',       icon = 'fa-car',          color = '#5856d6' },
    { id = 'nightlife',    label = 'Nightlife',        icon = 'fa-champagne-glasses', color = '#af52de' },
    { id = 'realestate',   label = 'Real Estate',      icon = 'fa-building',     color = '#30d158' },
    { id = 'tech',         label = 'Technology',       icon = 'fa-microchip',    color = '#5ac8fa' },
    { id = 'other',        label = 'Other',            icon = 'fa-ellipsis',     color = '#8e8e93' },
}

-- Family/Gang settings
AgencyPadConfig.FamilyCreationCost = 25000        -- Cost ($) to create a family
AgencyPadConfig.GangCreationCost = 35000          -- Cost ($) to create a gang
AgencyPadConfig.FamilyMaxPerPlayer = 1            -- Max families a player can lead
AgencyPadConfig.GangMaxPerPlayer = 1              -- Max gangs a player can lead
AgencyPadConfig.FamilyMaxMembers = 30             -- Max members per family (base, level 1)
AgencyPadConfig.GangMaxMembers = 25               -- Max members per gang (base, level 1)

-- ═══════════════════════════════════════════════════════════════
-- LEVEL SYSTEM (Businesses, Gangs, Families)
-- Every organization starts at level 1. Leaders can pay a one-time
-- upgrade fee (deducted from the organization bank) to advance to
-- the next level, which unlocks more member slots and perks.
-- ═══════════════════════════════════════════════════════════════
AgencyPadConfig.EnableLevelSystem = true

-- Business level tiers
AgencyPadConfig.BusinessLevels = {
    { level = 1, label = 'Startup',     upgradeCost = 0,       maxMembers = 20, perks = { 'Basic business features' } },
    { level = 2, label = 'Growing',     upgradeCost = 100000,  maxMembers = 30, perks = { '+10 employee slots', 'Extended product catalog' } },
    { level = 3, label = 'Established', upgradeCost = 250000,  maxMembers = 45, perks = { '+15 employee slots', 'Advanced analytics', 'Featured in Yellow Pages' } },
    { level = 4, label = 'Corporate',   upgradeCost = 500000,  maxMembers = 65, perks = { '+20 employee slots', 'Multi-location POS', 'Priority support' } },
    { level = 5, label = 'Empire',      upgradeCost = 1000000, maxMembers = 100, perks = { '+35 employee slots', 'Custom branding', 'VIP listings', 'Max prestige' } },
}

-- Gang level tiers
AgencyPadConfig.GangLevels = {
    { level = 1, label = 'Street Crew',   upgradeCost = 0,       maxMembers = 25, perks = { 'Basic gang features' } },
    { level = 2, label = 'Rising Crew',   upgradeCost = 75000,   maxMembers = 35, perks = { '+10 member slots', '+1 active mission slot' } },
    { level = 3, label = 'Syndicate',     upgradeCost = 200000,  maxMembers = 50, perks = { '+15 member slots', 'Higher mission rewards (+10%)' } },
    { level = 4, label = 'Cartel',        upgradeCost = 450000,  maxMembers = 70, perks = { '+20 member slots', 'Priority darknet listings', '+25% mission rewards' } },
    { level = 5, label = 'Kingpin',       upgradeCost = 900000,  maxMembers = 100, perks = { '+30 member slots', 'All missions unlocked', '+50% mission rewards' } },
}

-- Family level tiers
AgencyPadConfig.FamilyLevels = {
    { level = 1, label = 'Associates',    upgradeCost = 0,       maxMembers = 30, perks = { 'Basic family features' } },
    { level = 2, label = 'Crew',          upgradeCost = 80000,   maxMembers = 40, perks = { '+10 member slots', '+1 active mission slot' } },
    { level = 3, label = 'Regime',        upgradeCost = 220000,  maxMembers = 55, perks = { '+15 member slots', 'Advanced ranks unlocked' } },
    { level = 4, label = 'Dynasty',       upgradeCost = 475000,  maxMembers = 75, perks = { '+20 member slots', 'Priority darknet listings' } },
    { level = 5, label = 'Cosa Nostra',   upgradeCost = 950000,  maxMembers = 110, perks = { '+35 member slots', 'Elite mission pool', '+50% mission rewards' } },
}

-- Mission reward multipliers per level (used by server when computing rewards)
AgencyPadConfig.LevelMissionRewardMultipliers = { 1.0, 1.0, 1.1, 1.25, 1.5 }

-- ═══════════════════════════════════════════════════════════════
-- HOURLY PAYROLL
-- Salaries are defined PER HOUR (not per day). Employees with a
-- salary are auto-paid every hour of in-game time. Payroll is
-- deducted from the org bank balance; if the balance is too low
-- the payout is skipped until funds are available.
-- ═══════════════════════════════════════════════════════════════
AgencyPadConfig.EnableHourlyPayroll = true
AgencyPadConfig.PayrollIntervalSeconds = 3600     -- Pay every 3600s (1 hour)

-- Admin: ACE permission required to use admin functions (create for others, manage all orgs)
AgencyPadConfig.BusinessAdminAce = 'command'      -- Players with this ACE can use admin panel

-- ═══════════════════════════════════════════════════════════════
-- RANKS & PERMISSIONS SYSTEM
-- Each business/gang/family has configurable ranks with individual permissions
-- Owners automatically get all permissions
-- Players can create custom ranks in the Business App
-- ═══════════════════════════════════════════════════════════════

-- All available permissions (used by the UI to show checkboxes)
-- Permission keys are also checked server-side for every action
AgencyPadConfig.AvailablePermissions = {
    -- Member management
    { id = 'hire_members',       label = 'Hire Members',         category = 'members', icon = 'fa-user-plus' },
    { id = 'fire_members',       label = 'Fire Members',         category = 'members', icon = 'fa-user-minus' },
    { id = 'promote_members',    label = 'Promote Members',      category = 'members', icon = 'fa-angles-up' },
    { id = 'edit_ranks',         label = 'Manage Ranks',         category = 'members', icon = 'fa-user-gear' },
    -- Finances
    { id = 'view_balance',       label = 'View Balance',         category = 'finances', icon = 'fa-eye' },
    { id = 'deposit_money',      label = 'Deposit Money',        category = 'finances', icon = 'fa-arrow-down' },
    { id = 'withdraw_money',     label = 'Withdraw Money',       category = 'finances', icon = 'fa-arrow-up' },
    { id = 'view_history',       label = 'View Transaction History', category = 'finances', icon = 'fa-clock-rotate-left' },
    -- Products & POS (business only)
    { id = 'manage_products',    label = 'Manage Products',      category = 'business', icon = 'fa-box' },
    { id = 'use_pos',            label = 'Use Cash Register',    category = 'business', icon = 'fa-cash-register' },
    { id = 'create_invoices',    label = 'Create Invoices',      category = 'business', icon = 'fa-file-invoice-dollar' },
    -- Settings
    { id = 'edit_settings',      label = 'Edit Settings',        category = 'settings', icon = 'fa-gear' },
    { id = 'edit_logo',          label = 'Change Logo',          category = 'settings', icon = 'fa-image' },
    { id = 'delete_org',         label = 'Delete Organization',  category = 'settings', icon = 'fa-trash' },
    -- Job listings
    { id = 'manage_listings',    label = 'Manage Job Listings',  category = 'jobs', icon = 'fa-bullhorn' },
    { id = 'review_applications', label = 'Review Applications', category = 'jobs', icon = 'fa-file-circle-check' },
    -- Gang/Family specific
    { id = 'start_missions',     label = 'Start Missions',       category = 'gang', icon = 'fa-crosshairs' },
    { id = 'complete_missions',  label = 'Complete Missions',    category = 'gang', icon = 'fa-circle-check' },
    { id = 'darknet_services',   label = 'Manage Darknet Services', category = 'gang', icon = 'fa-user-secret' },
    -- Services (business)
    { id = 'manage_services',    label = 'Manage Services',      category = 'business', icon = 'fa-briefcase' },
}

-- ═══════════════════════════════════════════════════════════════
-- Default Rank Templates (applied when a new org is created)
-- Each org gets these starter ranks; owners can add/edit/remove ranks
-- The first rank is the "entry" rank for new members (grade 0)
-- The last rank (with isLeader=true) gets ALL permissions
-- ═══════════════════════════════════════════════════════════════
AgencyPadConfig.DefaultBusinessRanks = {
    { id = 'trainee',  label = 'Trainee',     grade = 0, isLeader = false, color = '#8e8e93', salary = 0, permissions = { 'view_balance', 'use_pos' } },
    { id = 'employee', label = 'Employee',    grade = 1, isLeader = false, color = '#64d2ff', salary = 0, permissions = { 'view_balance', 'use_pos', 'create_invoices' } },
    { id = 'senior',   label = 'Senior',      grade = 2, isLeader = false, color = '#30d158', salary = 0, permissions = { 'view_balance', 'use_pos', 'create_invoices', 'manage_products', 'view_history' } },
    { id = 'manager',  label = 'Manager',     grade = 3, isLeader = false, color = '#af52de', salary = 0, permissions = { 'hire_members', 'promote_members', 'view_balance', 'deposit_money', 'withdraw_money', 'view_history', 'manage_products', 'use_pos', 'create_invoices', 'manage_listings', 'review_applications', 'manage_services' } },
    { id = 'owner',    label = 'Owner',       grade = 4, isLeader = true,  color = '#ffd60a', salary = 0, permissions = { '*' } }, -- '*' = all permissions
}

AgencyPadConfig.DefaultGangRanks = {
    { id = 'hang_around',  label = 'Hang Around',  grade = 0, isLeader = false, color = '#8e8e93', salary = 0, permissions = { 'view_balance' } },
    { id = 'prospect',     label = 'Prospect',     grade = 1, isLeader = false, color = '#ff9500', salary = 0, permissions = { 'view_balance', 'start_missions' } },
    { id = 'member',       label = 'Member',       grade = 2, isLeader = false, color = '#ff453a', salary = 0, permissions = { 'view_balance', 'start_missions', 'complete_missions' } },
    { id = 'enforcer',     label = 'Enforcer',     grade = 3, isLeader = false, color = '#bf5af2', salary = 0, permissions = { 'view_balance', 'start_missions', 'complete_missions', 'darknet_services', 'hire_members' } },
    { id = 'underboss',    label = 'Underboss',    grade = 4, isLeader = false, color = '#64d2ff', salary = 0, permissions = { 'hire_members', 'fire_members', 'promote_members', 'view_balance', 'deposit_money', 'withdraw_money', 'view_history', 'start_missions', 'complete_missions', 'darknet_services', 'manage_listings' } },
    { id = 'boss',         label = 'Boss',         grade = 5, isLeader = true,  color = '#ffd60a', salary = 0, permissions = { '*' } },
}

AgencyPadConfig.DefaultFamilyRanks = {
    { id = 'associate',    label = 'Associate',    grade = 0, isLeader = false, color = '#8e8e93', salary = 0, permissions = { 'view_balance' } },
    { id = 'soldier',      label = 'Soldier',      grade = 1, isLeader = false, color = '#ff9500', salary = 0, permissions = { 'view_balance', 'start_missions' } },
    { id = 'caporegime',   label = 'Caporegime',   grade = 2, isLeader = false, color = '#ff453a', salary = 0, permissions = { 'view_balance', 'start_missions', 'complete_missions', 'darknet_services' } },
    { id = 'consigliere',  label = 'Consigliere',  grade = 3, isLeader = false, color = '#bf5af2', salary = 0, permissions = { 'hire_members', 'promote_members', 'view_balance', 'view_history', 'start_missions', 'complete_missions', 'darknet_services', 'manage_listings' } },
    { id = 'underboss',    label = 'Underboss',    grade = 4, isLeader = false, color = '#64d2ff', salary = 0, permissions = { 'hire_members', 'fire_members', 'promote_members', 'view_balance', 'deposit_money', 'withdraw_money', 'view_history', 'start_missions', 'complete_missions', 'darknet_services', 'manage_listings', 'review_applications' } },
    { id = 'don',          label = 'Don',          grade = 5, isLeader = true,  color = '#ffd60a', salary = 0, permissions = { '*' } },
}

-- Gang Missions: tasks that gang members can start and complete for rewards
-- Set to false to disable the missions system entirely
AgencyPadConfig.EnableGangMissions = true
AgencyPadConfig.GangMaxActiveMissions = 2           -- Max concurrent missions per gang
AgencyPadConfig.GangMissionsPerDay = 3              -- How many missions are offered per day (from the pool)
-- Daily mission reset hour (0–23, server local time). Missions rotate every day
-- at this hour. Default: 6 (6 AM). Same rotation applies to gangs AND families.
AgencyPadConfig.GangMissionResetHour = 6

-- ═══════════════════════════════════════════════════════════════
-- GANG MISSIONS (20 unique missions for Gangs)
-- Each mission has objectives, reward, difficulty, and timing
-- Players get 3 random missions per day from this pool
-- ═══════════════════════════════════════════════════════════════
AgencyPadConfig.GangMissions = {
    {
        id = 'supply_run', label = 'Supply Run',
        description = 'Hit a weapons dealer\'s warehouse and steal crates of merchandise.',
        icon = 'fa-truck-fast', color = '#ff9500',
        difficulty = 'easy', reward = 8000, xp = 50,
        cooldown = 1800, duration = 900,
        objectives = { 'Locate warehouse', 'Steal 5 crates', 'Deliver to stash' },
        minMembers = 2,
    },
    {
        id = 'territory_takeover', label = 'Territory Takeover',
        description = 'Push out a rival crew from their block and claim it for your gang.',
        icon = 'fa-map-location-dot', color = '#ff453a',
        difficulty = 'medium', reward = 15000, xp = 100,
        cooldown = 5400, duration = 1500,
        objectives = { 'Eliminate 10 rivals', 'Hold zone for 10 minutes', 'Tag 3 walls' },
        minMembers = 3,
    },
    {
        id = 'heist_prep', label = 'Heist Preparation',
        description = 'Gather intel, weapons and a getaway vehicle for a major operation.',
        icon = 'fa-binoculars', color = '#af52de',
        difficulty = 'medium', reward = 18000, xp = 120,
        cooldown = 7200, duration = 1800,
        objectives = { 'Photograph security (3 locations)', 'Acquire weapons cache', 'Steal getaway vehicle' },
        minMembers = 2,
    },
    {
        id = 'street_race', label = 'Street Race',
        description = 'Organize a high-stakes underground street race and place first.',
        icon = 'fa-flag-checkered', color = '#5ac8fa',
        difficulty = 'easy', reward = 6500, xp = 40,
        cooldown = 1200, duration = 720,
        objectives = { 'Recruit 3 racers', 'Complete circuit', 'Finish 1st place' },
        minMembers = 1,
    },
    {
        id = 'protection_racket', label = 'Protection Racket',
        description = 'Collect "protection fees" from 5 local businesses.',
        icon = 'fa-hand-holding-dollar', color = '#30d158',
        difficulty = 'easy', reward = 10000, xp = 60,
        cooldown = 3600, duration = 1200,
        objectives = { 'Visit 5 businesses', 'Intimidate owners', 'Collect $10.000' },
        minMembers = 2,
    },
    {
        id = 'smuggling_run', label = 'Smuggling Run',
        description = 'Smuggle contraband across the city without being caught by police.',
        icon = 'fa-box', color = '#ff375f',
        difficulty = 'medium', reward = 14000, xp = 90,
        cooldown = 5400, duration = 1500,
        objectives = { 'Pick up package', 'Avoid police (max 1 star)', 'Deliver to buyer' },
        minMembers = 2,
    },
    {
        id = 'chop_shop', label = 'Chop Shop Delivery',
        description = 'Steal 3 high-end vehicles and deliver them to the chop shop.',
        icon = 'fa-car-burst', color = '#ff6b35',
        difficulty = 'medium', reward = 22000, xp = 140,
        cooldown = 7200, duration = 2100,
        objectives = { 'Steal 3 luxury cars', 'Strip vehicles', 'Deliver parts' },
        minMembers = 3,
    },
    {
        id = 'drug_distribution', label = 'Drug Distribution',
        description = 'Distribute product to 8 street dealers across the city.',
        icon = 'fa-prescription-bottle', color = '#bf5af2',
        difficulty = 'hard', reward = 28000, xp = 180,
        cooldown = 9000, duration = 2700,
        objectives = { 'Pick up product (3 locations)', 'Deliver to 8 dealers', 'Return profits to stash' },
        minMembers = 3,
    },
    {
        id = 'arms_deal', label = 'Arms Deal',
        description = 'Broker a weapons deal with an out-of-town buyer.',
        icon = 'fa-gun', color = '#ff9f0a',
        difficulty = 'hard', reward = 35000, xp = 220,
        cooldown = 10800, duration = 3000,
        objectives = { 'Meet contact', 'Show merchandise', 'Complete transaction', 'Escape buyer location' },
        minMembers = 3,
    },
    {
        id = 'jewelry_heist', label = 'Jewelry Heist',
        description = 'Rob a high-end jewelry store during business hours.',
        icon = 'fa-gem', color = '#64d2ff',
        difficulty = 'hard', reward = 42000, xp = 260,
        cooldown = 14400, duration = 2400,
        objectives = { 'Enter store', 'Smash display cases', 'Grab 6 items', 'Escape with loot' },
        minMembers = 4,
    },
    {
        id = 'gas_station_robbery', label = 'Gas Station Robbery',
        description = 'Rob 3 gas stations in a single run.',
        icon = 'fa-gas-pump', color = '#ff6482',
        difficulty = 'easy', reward = 7500, xp = 45,
        cooldown = 2400, duration = 900,
        objectives = { 'Rob 3 gas stations', 'Evade police', 'Deliver cash' },
        minMembers = 1,
    },
    {
        id = 'bank_robbery', label = 'Bank Robbery',
        description = 'Full bank robbery — coordination, speed and firepower.',
        icon = 'fa-building-columns', color = '#ffd60a',
        difficulty = 'extreme', reward = 85000, xp = 500,
        cooldown = 21600, duration = 3600,
        objectives = { 'Breach vault', 'Neutralize security', 'Grab cash bags', 'Escape the city' },
        minMembers = 4,
    },
    {
        id = 'cargo_hijack', label = 'Cargo Hijack',
        description = 'Hijack an armored cargo truck and strip it of valuables.',
        icon = 'fa-truck', color = '#ff453a',
        difficulty = 'hard', reward = 32000, xp = 200,
        cooldown = 9000, duration = 2400,
        objectives = { 'Locate cargo truck', 'Disable driver', 'Crack cargo hold', 'Escape with goods' },
        minMembers = 3,
    },
    {
        id = 'diamond_exchange', label = 'Diamond Exchange',
        description = 'Trade stolen diamonds with a shady fence at multiple drop points.',
        icon = 'fa-diamond', color = '#5ac8fa',
        difficulty = 'medium', reward = 24000, xp = 150,
        cooldown = 7200, duration = 1800,
        objectives = { 'Meet fence', 'Visit 3 drop points', 'Complete exchange' },
        minMembers = 2,
    },
    {
        id = 'cartel_meeting', label = 'Cartel Meeting',
        description = 'Attend a dangerous meeting with a Mexican cartel representative.',
        icon = 'fa-skull', color = '#8e8e93',
        difficulty = 'extreme', reward = 55000, xp = 350,
        cooldown = 14400, duration = 3000,
        objectives = { 'Travel to meeting', 'Negotiate terms', 'Survive potential ambush', 'Return with contract' },
        minMembers = 4,
    },
    {
        id = 'street_fight', label = 'Underground Fight Club',
        description = 'Win 3 bare-knuckle fights at an underground fighting ring.',
        icon = 'fa-hand-fist', color = '#ff375f',
        difficulty = 'medium', reward = 12000, xp = 80,
        cooldown = 3600, duration = 1500,
        objectives = { 'Enter fight club', 'Win 3 matches', 'Collect winnings' },
        minMembers = 1,
    },
    {
        id = 'recruit_enforcer', label = 'Recruit Enforcer',
        description = 'Find and recruit a new enforcer for your gang.',
        icon = 'fa-user-plus', color = '#30d158',
        difficulty = 'easy', reward = 5000, xp = 30,
        cooldown = 1800, duration = 600,
        objectives = { 'Find candidate', 'Test loyalty', 'Recruit to gang' },
        minMembers = 1,
    },
    {
        id = 'sabotage_rival', label = 'Sabotage Rival',
        description = 'Sabotage a rival gang\'s operations by destroying their supply.',
        icon = 'fa-bomb', color = '#ff9500',
        difficulty = 'hard', reward = 30000, xp = 190,
        cooldown = 10800, duration = 2400,
        objectives = { 'Locate rival stash', 'Plant explosives', 'Destroy supply', 'Escape undetected' },
        minMembers = 3,
    },
    {
        id = 'prison_break', label = 'Prison Break',
        description = 'Break out a captured gang member from Bolingbroke Penitentiary.',
        icon = 'fa-jail', color = '#af52de',
        difficulty = 'extreme', reward = 65000, xp = 420,
        cooldown = 18000, duration = 3600,
        objectives = { 'Gather breakout gear', 'Infiltrate prison', 'Extract member', 'Escape manhunt' },
        minMembers = 5,
    },
    {
        id = 'assassination', label = 'Assassination Contract',
        description = 'Eliminate a high-profile target for an anonymous client.',
        icon = 'fa-crosshairs', color = '#ff3b30',
        difficulty = 'extreme', reward = 75000, xp = 450,
        cooldown = 18000, duration = 3000,
        objectives = { 'Identify target', 'Track movement', 'Eliminate target', 'Clean exit' },
        minMembers = 2,
    },
}

-- ═══════════════════════════════════════════════════════════════
-- FAMILY MISSIONS (20 unique missions for Families — more business-focused)
-- Families operate more like organized crime, less street-level chaos
-- ═══════════════════════════════════════════════════════════════
AgencyPadConfig.FamilyMissions = {
    {
        id = 'laundering_operation', label = 'Money Laundering',
        description = 'Launder $50k of dirty money through legitimate businesses.',
        icon = 'fa-money-bill-transfer', color = '#30d158',
        difficulty = 'medium', reward = 20000, xp = 130,
        cooldown = 5400, duration = 1800,
        objectives = { 'Deposit at 3 businesses', 'Collect clean money', 'Return to capo' },
        minMembers = 2,
    },
    {
        id = 'bribe_official', label = 'Bribe Official',
        description = 'Pay off a corrupt city official to look the other way.',
        icon = 'fa-user-tie', color = '#ffd60a',
        difficulty = 'easy', reward = 12000, xp = 75,
        cooldown = 3600, duration = 900,
        objectives = { 'Meet official', 'Hand over briefcase', 'Secure favor' },
        minMembers = 1,
    },
    {
        id = 'import_export', label = 'Import/Export Scheme',
        description = 'Coordinate a smuggling operation with shipping containers.',
        icon = 'fa-ship', color = '#0a84ff',
        difficulty = 'hard', reward = 38000, xp = 240,
        cooldown = 10800, duration = 2700,
        objectives = { 'Meet shipping contact', 'Inspect containers', 'Transport goods', 'Deliver to warehouse' },
        minMembers = 3,
    },
    {
        id = 'insurance_fraud', label = 'Insurance Fraud',
        description = 'Stage an accident to collect insurance payout.',
        icon = 'fa-file-contract', color = '#ff9f0a',
        difficulty = 'easy', reward = 9500, xp = 55,
        cooldown = 2400, duration = 1200,
        objectives = { 'Stage scene', 'File claim', 'Collect payout' },
        minMembers = 2,
    },
    {
        id = 'loan_shark_collection', label = 'Loan Shark Collection',
        description = 'Collect overdue debts from 6 delinquent clients.',
        icon = 'fa-sack-dollar', color = '#32ade6',
        difficulty = 'medium', reward = 16000, xp = 100,
        cooldown = 3600, duration = 1500,
        objectives = { 'Visit 6 debtors', 'Collect payments', 'Return with cash' },
        minMembers = 2,
    },
    {
        id = 'underground_casino', label = 'Underground Casino',
        description = 'Run an illegal high-stakes poker night.',
        icon = 'fa-dice', color = '#af52de',
        difficulty = 'medium', reward = 22000, xp = 140,
        cooldown = 5400, duration = 1800,
        objectives = { 'Set up venue', 'Recruit 6 players', 'Run the house', 'Collect profits' },
        minMembers = 2,
    },
    {
        id = 'forgery_ring', label = 'Forgery Ring',
        description = 'Produce and sell forged documents to clients.',
        icon = 'fa-stamp', color = '#64d2ff',
        difficulty = 'medium', reward = 18000, xp = 110,
        cooldown = 5400, duration = 1500,
        objectives = { 'Gather blank docs', 'Forge signatures', 'Sell to 4 buyers' },
        minMembers = 2,
    },
    {
        id = 'construction_extortion', label = 'Construction Extortion',
        description = 'Force a construction company to pay "safety fees".',
        icon = 'fa-helmet-safety', color = '#ff9500',
        difficulty = 'hard', reward = 28000, xp = 170,
        cooldown = 7200, duration = 2100,
        objectives = { 'Visit 3 sites', 'Demonstrate power', 'Collect protection fees' },
        minMembers = 3,
    },
    {
        id = 'art_theft', label = 'Art Theft',
        description = 'Steal a valuable painting from a private gallery.',
        icon = 'fa-palette', color = '#bf5af2',
        difficulty = 'hard', reward = 45000, xp = 280,
        cooldown = 10800, duration = 2400,
        objectives = { 'Study gallery security', 'Bypass alarms', 'Extract painting', 'Meet buyer' },
        minMembers = 3,
    },
    {
        id = 'yacht_party', label = 'Yacht Party',
        description = 'Host a high-end yacht party to network with VIP clients.',
        icon = 'fa-sailboat', color = '#5ac8fa',
        difficulty = 'easy', reward = 8000, xp = 50,
        cooldown = 3600, duration = 1500,
        objectives = { 'Book yacht', 'Invite 8 VIPs', 'Close 3 deals' },
        minMembers = 2,
    },
    {
        id = 'wine_smuggling', label = 'Wine Smuggling',
        description = 'Smuggle rare vintage wines through customs.',
        icon = 'fa-wine-bottle', color = '#ff375f',
        difficulty = 'medium', reward = 19000, xp = 120,
        cooldown = 5400, duration = 1800,
        objectives = { 'Meet supplier', 'Bribe customs', 'Deliver to cellars' },
        minMembers = 2,
    },
    {
        id = 'stock_manipulation', label = 'Stock Manipulation',
        description = 'Pump and dump a small cap stock for massive profits.',
        icon = 'fa-chart-line', color = '#30d158',
        difficulty = 'hard', reward = 50000, xp = 320,
        cooldown = 14400, duration = 3000,
        objectives = { 'Identify target stock', 'Coordinate buying', 'Pump price', 'Sell peak', 'Cover tracks' },
        minMembers = 3,
    },
    {
        id = 'political_blackmail', label = 'Political Blackmail',
        description = 'Gather compromising material on a politician.',
        icon = 'fa-envelope', color = '#ff9500',
        difficulty = 'extreme', reward = 70000, xp = 430,
        cooldown = 18000, duration = 3600,
        objectives = { 'Stake out target', 'Photograph meetings', 'Confront politician', 'Extract payment' },
        minMembers = 3,
    },
    {
        id = 'luxury_car_ring', label = 'Luxury Car Ring',
        description = 'Export stolen luxury cars through container shipping.',
        icon = 'fa-car-side', color = '#ff453a',
        difficulty = 'hard', reward = 48000, xp = 300,
        cooldown = 10800, duration = 2700,
        objectives = { 'Steal 4 luxury cars', 'Ship to container', 'Bribe dock workers', 'Confirm delivery' },
        minMembers = 4,
    },
    {
        id = 'diplomatic_favor', label = 'Diplomatic Favor',
        description = 'Complete a discreet task for a foreign diplomat.',
        icon = 'fa-briefcase', color = '#8e8e93',
        difficulty = 'medium', reward = 25000, xp = 160,
        cooldown = 7200, duration = 1800,
        objectives = { 'Meet diplomat', 'Retrieve package', 'Hand to contact' },
        minMembers = 2,
    },
    {
        id = 'casino_robbery', label = 'Casino Vault Heist',
        description = 'Hit the Diamond Casino vault during off-hours.',
        icon = 'fa-vault', color = '#ffd60a',
        difficulty = 'extreme', reward = 95000, xp = 600,
        cooldown = 21600, duration = 3600,
        objectives = { 'Infiltrate casino', 'Crack vault', 'Grab cash', 'Escape casino', 'Reach safehouse' },
        minMembers = 5,
    },
    {
        id = 'tax_fraud', label = 'Tax Fraud Scheme',
        description = 'File fraudulent tax returns through shell companies.',
        icon = 'fa-file-invoice-dollar', color = '#5ac8fa',
        difficulty = 'medium', reward = 26000, xp = 165,
        cooldown = 7200, duration = 2100,
        objectives = { 'Set up shell co.', 'Forge documents', 'File returns', 'Collect refunds' },
        minMembers = 2,
    },
    {
        id = 'witness_intimidation', label = 'Witness Intimidation',
        description = 'Silence a witness before they can testify.',
        icon = 'fa-user-secret', color = '#ff3b30',
        difficulty = 'hard', reward = 40000, xp = 250,
        cooldown = 10800, duration = 2400,
        objectives = { 'Locate witness', 'Send warning', 'Ensure silence' },
        minMembers = 2,
    },
    {
        id = 'black_market_auction', label = 'Black Market Auction',
        description = 'Host an invitation-only auction for stolen goods.',
        icon = 'fa-gavel', color = '#bf5af2',
        difficulty = 'hard', reward = 52000, xp = 340,
        cooldown = 14400, duration = 3000,
        objectives = { 'Secure venue', 'Invite 6 buyers', 'Run 5 auction lots', 'Collect payments' },
        minMembers = 3,
    },
    {
        id = 'federal_payoff', label = 'Federal Payoff',
        description = 'Pay off a federal agent to drop an investigation.',
        icon = 'fa-shield-halved', color = '#0a84ff',
        difficulty = 'extreme', reward = 80000, xp = 500,
        cooldown = 21600, duration = 3000,
        objectives = { 'Meet agent', 'Hand over cash', 'Confirm file destroyed', 'Disappear' },
        minMembers = 3,
    },
}

-------------------------------------------------------------------------------
-- APP STORE
-------------------------------------------------------------------------------
AgencyPadConfig.AppStoreEnabled = true           -- Enable the app store
AgencyPadConfig.AppStorePersist = true           -- Persist installs in localStorage

-------------------------------------------------------------------------------
-- APPLICATIONS
--
-- installed : true = pre-installed on home screen, false = available in Store
-- enabled   : true = visible (either on home or in store), false = hidden
--
-- Users can add custom apps by creating files in the apps/ folder.
-- See apps/README.md for documentation.
-------------------------------------------------------------------------------
AgencyPadConfig.Apps = {
    -- ═══════════════════════════════════════════════════════════
    -- PRE-INSTALLED APPS (on home screen by default)
    -- ═══════════════════════════════════════════════════════════
    {
        id        = "dialer",
        label     = "Phone",
        icon      = "fa-solid fa-phone",
        color     = "#4cd964",
        colorDark = "#34c759",
        slot      = 1,
        installed = true,
        enabled   = true,
    },
    {
        id        = "buzz",
        label     = "Buzz",
        icon      = "fa-solid fa-comment",
        color     = "#34c759",
        colorDark = "#28a745",
        slot      = 2,
        installed = true,
        enabled   = true,
    },
    {
        id        = "contacts",
        label     = "Contacts",
        icon      = "fa-solid fa-user-group",
        color     = "#ff9500",
        colorDark = "#e08600",
        slot      = 3,
        installed = true,
        enabled   = true,
    },
    {
        id        = "snap",
        label     = "Camera",
        icon      = "fa-solid fa-camera",
        color     = "#8e8e93",
        colorDark = "#636366",
        slot      = 4,
        installed = true,
        enabled   = true,
    },
    {
        id        = "postbox",
        label     = "Mail",
        icon      = "fa-solid fa-envelope",
        color     = "#5ac8fa",
        colorDark = "#32ade6",
        slot      = 6,
        installed = true,
        enabled   = true,
    },
    {
        id        = "wallet",
        label     = "Wallet",
        icon      = "fa-solid fa-wallet",
        color     = "#007aff",
        colorDark = "#0056cc",
        slot      = 7,
        installed = true,
        enabled   = true,
    },
    {
        id        = "gallery",
        label     = "Photos",
        icon      = "fa-solid fa-images",
        color     = "#ff2d55",
        colorDark = "#d6204a",
        slot      = 8,
        installed = true,
        enabled   = true,
    },
    {
        id        = "report",
        label     = "Agency Reports",
        icon      = "fa-solid fa-flag",
        color     = "#ff3b30",
        colorDark = "#d63025",
        slot      = 9,
        installed = true,
        enabled   = true,
    },
    {
        id        = "settings",
        label     = "Settings",
        icon      = "fa-solid fa-gear",
        color     = "#8e8e93",
        colorDark = "#636366",
        slot      = 10,
        installed = true,
        enabled   = true,
    },
    {
        id        = "agencyai",
        label     = "AgencyAI",
        icon      = "fa-solid fa-wand-magic-sparkles",
        color     = "#af52de",
        colorDark = "#5856d6",
        slot      = 11,
        installed = true,
        enabled   = true,
    },
    {
        id        = "appstore",
        label     = "Store",
        icon      = "fa-solid fa-bag-shopping",
        color     = "#007aff",
        colorDark = "#0056cc",
        slot      = 12,
        installed = true,
        enabled   = true,
    },

    {
        id        = "agencycloud",
        label     = "AgencyCloud",
        icon      = "fa-solid fa-cloud",
        color     = "#4cc6ff",
        colorDark = "#0a84ff",
        category  = "productivity",
        slot      = 13,
        installed = true,
        enabled   = true,
        storeDesc = "Your personal and company cloud storage. Sync files, photos, and documents across all your Agency devices.",
        features  = {"Personal & company storage", "Cross-device sync", "Photo gallery backup", "Document management", "Storage tier upgrades"},
    },

    -- ═══════════════════════════════════════════════════════════
    -- STORE APPS (must be installed via the Store app first)
    -- ═══════════════════════════════════════════════════════════
    {
        id        = "calculator",
        label     = "Calculator",
        icon      = "fa-solid fa-calculator",
        color     = "#ff9500",
        colorDark = "#e08600",
        category  = "productivity",
        slot      = 13,
        installed = true,
        enabled   = true,
        storeDesc = "A powerful calculator app for quick calculations on the go.",
        features  = {"Basic arithmetic operations", "Percentage calculations", "AgencyOS26.4-style interface", "Instant results"},
    },
    {
        id        = "clock",
        label     = "Clock",
        icon      = "fa-solid fa-clock",
        color     = "#000000",
        colorDark = "#1c1c1e",
        category  = "productivity",
        slot      = 14,
        installed = true,
        enabled   = true,
        storeDesc = "Keep track of time with world clocks, alarms, stopwatch, and timers.",
        features  = {"World clock display", "Stopwatch with precision timing", "Multiple alarms", "Timer functionality"},
    },
    {
        id        = "notes",
        label     = "Notes",
        icon      = "fa-solid fa-note-sticky",
        color     = "#ffcc00",
        colorDark = "#e6b800",
        category  = "productivity",
        slot      = 15,
        installed = true,
        enabled   = true,
        storeDesc = "Jot down ideas, tasks, and reminders instantly.",
        features  = {"Quick note creation", "Persistent storage", "Easy organization", "Simple interface"},
    },
    {
        id        = "weather",
        label     = "Weather",
        icon      = "fa-solid fa-cloud-sun",
        color     = "#5ac8fa",
        colorDark = "#32ade6",
        category  = "productivity",
        slot      = 16,
        installed = true,
        enabled   = true,
        storeDesc = "Stay informed about current weather conditions in Los Santos.",
        features  = {"Real-time weather display", "Temperature info", "Current conditions", "Location-based data"},
    },
    {
        id        = "compass",
        label     = "Compass",
        icon      = "fa-solid fa-compass",
        color     = "#ff3b30",
        colorDark = "#d63025",
        category  = "navigation",
        slot      = 17,
        installed = true,
        enabled   = false,
        storeDesc = "Navigate the city with an accurate digital compass.",
        features  = {"Real-time heading direction", "Accurate navigation", "Always accessible", "Minimal interface"},
    },
    {
        id        = "radio",
        label     = "Radio",
        icon      = "fa-solid fa-radio",
        color     = "#ff6b6b",
        colorDark = "#d94848",
        category  = "utilities",
        slot      = 18,
        installed = false,
        enabled   = false, -- Agency-Phone exclusive
        storeDesc = "Connect to various radio channels and communicate on the go.",
        features  = {"Multiple frequency channels", "Quick channel switching", "Clear audio", "Emergency frequencies"},
    },
    -- Flashlight removed: now available in Quick Settings (swipe down top-right)
    {
        id        = "gameshub",
        label     = "GamesHub",
        category  = "games",
        icon      = "fa-solid fa-gamepad",
        color     = "#7c5cff",
        colorDark = "#4f46e5",
        slot      = 19,
        installed = true,
        enabled   = true,
        storeDesc = "Agency Pad exclusive game platform with direct fullscreen access to the Agency arcade catalog.",
        features  = {"Agency Pad exclusive", "Direct platform access", "Fullscreen launcher feel", "Built for the tablet display"},
    },
    {
        id        = "speedometer",
        label     = "Speedo",
        icon      = "fa-solid fa-gauge-high",
        color     = "#ff2d55",
        colorDark = "#d6204a",
        category  = "navigation",
        slot      = 20,
        installed = false,
        enabled   = false,
        storeDesc = "Monitor your vehicle's speed with a digital speedometer.",
        features  = {"Real-time speed display", "Multiple unit options", "GPS speed tracking", "Always visible"},
    },
    {
        id        = "gps",
        label     = "Maps",
        icon      = "fa-solid fa-map-location-dot",
        color     = "#34c759",
        colorDark = "#28a745",
        category  = "navigation",
        slot      = 21,
        installed = false,
        enabled   = true,
        storeDesc = "Navigate Los Santos with GPS waypoints and route planning.",
        features  = {"Set custom waypoints", "Route guidance", "Real-time navigation", "Location sharing"},
    },
    {
        id        = "crypto",
        label     = "Crypto",
        icon      = "fa-brands fa-bitcoin",
        color     = "#f7931a",
        colorDark = "#d97c0e",
        slot      = 22,
        installed = false,
        enabled   = true,
        storeDesc = "Buy, sell, and track cryptocurrency markets in real-time.",
        features  = {"Live market prices", "Portfolio tracking", "Trading functionality", "Transaction history"},
    },
    {
        id        = "stocks",
        label     = "Stocks",
        icon      = "fa-solid fa-chart-line",
        color     = "#007aff",
        colorDark = "#0056cc",
        slot      = 33,
        installed = false,
        enabled   = true,
        storeDesc = "Trade stocks of Los Santos companies and build your portfolio.",
        features  = {"8 Los Santos companies", "Real-time price updates", "Buy/sell shares", "Portfolio tracking"},
        category  = "finance",
    },
    {
        id        = "agency_tycoon",
        label     = "Agency Tycoon",
        category  = "games",
        icon      = "fa-solid fa-building",
        color     = "#1fb6ff",
        colorDark = "#0f7ac7",
        slot      = 23,
        installed = false,
        enabled   = true,
        storeDesc = "Pad-exclusive executive tycoon with contract chains, summit boosts, eight divisions and milestone rewards.",
        features  = {"Agency Pad exclusive", "Eight expandable divisions", "Summits, campaigns and contract chains", "Offline revenue and milestone payouts"},
    },
    {
        id        = "dice",
        label     = "Dice Game",
        category  = "games",
        icon      = "fa-solid fa-dice",
        color     = "#ff2d55",
        colorDark = "#d6204a",
        slot      = 55,
        installed = false,
        enabled   = false,
        storeDesc = "Roll dice against other players. Classic gambling game.",
        features  = {"1v1 dice duels", "Customizable bet amounts", "Roll history", "Fair random rolls"},
    },
    {
        id        = "darkweb",
        label     = "Darknet",
        icon      = "fa-solid fa-skull-crossbones",
        color     = "#1c1c1e",
        colorDark = "#000000",
        category  = "darknet",
        slot      = 24,
        installed = false,
        enabled   = true,
        storeDesc = "Access the underground market. Anonymous and untraceable.",
        features  = {"Anonymous browsing", "Encrypted transactions", "Black market access", "High-risk items"},
    },
    {
        id        = "racing",
        label     = "Races",
        icon      = "fa-solid fa-flag-checkered",
        color     = "#ff9500",
        colorDark = "#e08600",
        category  = "services",
        slot      = 25,
        installed = false,
        enabled   = true,
        storeDesc = "Compete in street races and track your best times.",
        features  = {"Create custom races", "Join active races", "Leaderboards", "Race statistics"},
    },
    -- Music app moved to MEDIA APPS section below (YouTube API powered)
    {
        id        = "services",
        label     = "Services",
        icon      = "fa-solid fa-book-open",
        color     = "#ffd60a",
        colorDark = "#d4a800",
        category  = "utilities",
        slot      = 27,
        installed = false,
        enabled   = true,
        storeDesc = "Request taxis, mechanics, and various city services.",
        features  = {"Taxi services", "Mechanic calls", "Emergency services", "Quick booking"},
    },
    {
        id        = "aipickup",
        label     = "AutoRide",
        icon      = "fa-solid fa-car-side",
        color     = "#00c7be",
        colorDark = "#0a84ff",
        category  = "services",
        slot      = 26,
        installed = true,
        enabled   = true,
        storeDesc = "AgencyAI-powered limousine pickup and autonomous dropoff service.",
        features  = {"Driverless AgencyAI 4-seat limousine", "Pickup at your location", "Set waypoint before or during ride", "Autonomous routing to destination"},
    },
    {
        id        = "food",
        label     = "AgencyEats",
        icon      = "fa-solid fa-burger",
        color     = "#ff3b30",
        colorDark = "#d62020",
        category  = "services",
        slot      = 28,
        installed = false,
        enabled   = false, -- Agency-Phone exclusive
        storeDesc = "Order food from local restaurants and get it delivered to your location.",
        features  = {"Browse menus", "Place orders", "Track delivery", "Restaurant ratings"},
    },
    {
        id        = "invoices",
        label     = "Invoices",
        category  = "finance",
        icon      = "fa-solid fa-file-invoice-dollar",
        color     = "#30d158",
        colorDark = "#28b54c",
        slot      = 29,
        installed = false,
        enabled   = true,
        storeDesc = "Manage and pay your invoices and outstanding bills.",
        features  = {"View pending bills", "Pay invoices", "Transaction history", "Payment reminders"},
    },
    {
        id        = "employment",
        label     = "Jobs",
        category  = "utilities",
        icon      = "fa-solid fa-briefcase",
        color     = "#007aff",
        colorDark = "#0056cc",
        slot      = 30,
        installed = false,
        enabled   = true,
        storeDesc = "Find employment opportunities and manage your career.",
        features  = {"Job listings", "Application tracking", "Career information", "Salary details"},
    },
    {
        id        = "garage",
        label     = "Garage",
        category  = "utilities",
        icon      = "fa-solid fa-warehouse",
        color     = "#5856d6",
        colorDark = "#4240b0",
        slot      = 32,
        installed = true,
        enabled   = true,
        storeDesc = "Access and manage your stored vehicles and garage.",
        features  = {"Vehicle storage", "Quick spawn", "Vehicle information", "Garage locations"},
    },
    {
        id        = "tictactoe",
        label     = "Tic Tac Toe",
        category  = "games",
        icon      = "fa-solid fa-table-cells",
        color     = "#7c5cff",
        colorDark = "#4d2dd1",
        slot      = 37,
        installed = false,
        enabled   = true,
        storeDesc = "A polished pad-exclusive Tic Tac Toe board with solo play, local duels and reactive AgencyAI opponents.",
        features  = {"Agency Pad exclusive", "Solo and local duel modes", "Three AI difficulty levels", "Landscape tablet board layout"},
    },
    {
        id        = "coinflip",
        label     = "Coin Flip",
        category  = "games",
        icon      = "fa-solid fa-coins",
        color     = "#ffcc00",
        colorDark = "#e6b800",
        slot      = 56,
        installed = false,
        enabled   = false,
        storeDesc = "Flip a coin and bet against other players. Heads or tails?",
        features  = {"Heads or tails betting", "Fair coin flip", "Bet against players", "Flip history"},
    },
    {
        id        = "slots",
        label     = "Lucky Slots",
        category  = "games",
        icon      = "fa-solid fa-clover",
        color     = "#34c759",
        colorDark = "#28a745",
        slot      = 38,
        installed = false,
        enabled   = true,
        storeDesc = "Try your luck at the slot machine. Match symbols to win big!",
        features  = {"Classic slot machine", "Multiple symbol combos", "Win multipliers", "Jackpot system"},
    },
    {
        id        = "roulette",
        label     = "Roulette",
        category  = "games",
        icon      = "fa-solid fa-circle-dot",
        color     = "#ff3b30",
        colorDark = "#d63025",
        slot      = 39,
        installed = false,
        enabled   = true,
        storeDesc = "Place your bets on the roulette wheel. Red, black, or green?",
        features  = {"Red/Black/Green bets", "Number betting", "Realistic wheel spin", "Payout system"},
    },

    {
        id        = "flappybird",
        label     = "Sky Hopper",
        icon      = "fa-solid fa-dove",
        color     = "#4cd964",
        colorDark = "#3bb54a",
        slot      = 40,
        installed = false,
        enabled   = true,
        category  = "games",
        storeDesc = "A skyline glide challenge with precise taps, pipe runs and high-score chasing.",
        features  = {"Classic gameplay", "High score tracking", "Smooth animations", "Addictive fun"},
    },
    {
        id        = "game2048",
        label     = "2048",
        icon      = "fa-solid fa-border-all",
        color     = "#f59563",
        colorDark = "#e07840",
        slot      = 41,
        installed = false,
        enabled   = true,
        category  = "games",
        storeDesc = "Slide numbered tiles to combine them and reach 2048!",
        features  = {"Number puzzle", "Swipe controls", "Score tracking", "Addictive gameplay"},
    },

    -- ═══════════════════════════════════════════════════════════
    -- MEDIA APPS (YouTube API powered)
    -- ═══════════════════════════════════════════════════════════
    {
        id        = "vidflow",
        label     = "VidFlow",
        icon      = "fa-solid fa-play",
        category  = "media",
        color     = "#ff2d55",
        colorDark = "#d6204a",
        slot      = 34,
        installed = false,
        enabled   = true,
        storeDesc = "Watch and discover videos from around the world.",
        features  = {"Search millions of videos", "In-app video player", "Trending content", "Share with friends"},
    },
    {
        id        = "music",
        label     = "Music",
        icon      = "fa-solid fa-music",
        color     = "#fc3c44",
        colorDark = "#d43039",
        category  = "media",
        slot      = 5,
        installed = true,
        enabled   = true,
        storeDesc = "Listen to music and share it with people nearby.",
        features  = {"Search songs", "Paste any media link", "Nearby players hear your music", "Favorites & queue"},
    },

    -- ═══════════════════════════════════════════════════════════
    -- JOB-SPECIFIC APPS (restricted by player job)
    -- ═══════════════════════════════════════════════════════════
    {
        id           = "police_mdt",
        label        = "Police MDT",
        icon         = "fa-solid fa-shield-halved",
        color        = "#007aff",
        colorDark    = "#0056cc",
        category     = "utilities",
        slot         = 50,
        installed    = false,
        enabled      = true,
        requiresJob  = true,
        storeDesc    = "Mobile Data Terminal for law enforcement. View dispatches, track units, and manage calls.",
        features     = {"Live dispatch feed", "Unit GPS tracking", "Emergency call management", "Suspect database"},
    },
    {
        id           = "ems_mdt",
        label        = "EMS MDT",
        icon         = "fa-solid fa-heart-pulse",
        color        = "#ff3b30",
        colorDark    = "#d63025",
        category     = "utilities",
        slot         = 51,
        installed    = false,
        enabled      = true,
        requiresJob  = true,
        storeDesc    = "Emergency Medical Services terminal. Respond to medical emergencies and coordinate with your team.",
        features     = {"Medical emergency alerts", "Team GPS tracking", "Patient information", "Hospital routing"},
    },
    {
        id           = "mechanic_mdt",
        label        = "Mechanic MDT",
        icon         = "fa-solid fa-wrench",
        color        = "#ff9500",
        colorDark    = "#e08600",
        category     = "utilities",
        slot         = 52,
        installed    = false,
        enabled      = true,
        requiresJob  = true,
        storeDesc    = "Mobile Data Terminal for mechanic shops. Manage dispatches, units, personnel, and create invoices with Agency-Pay.",
        features     = {"Live dispatch feed", "Unit & personnel management", "Invoice creation with Agency-Pay", "Service history tracking", "Knowledge base"},
    },

    -- ═══════════════════════════════════════════════════════════
    -- SOCIAL APPS (require login)
    -- ═══════════════════════════════════════════════════════════
    {
        id        = "pictogram",
        label     = "Pictogram",
        category  = "social",
        icon      = "fa-solid fa-camera-retro",
        color     = "#E1306C",
        colorDark = "#C13584",
        slot      = 42,
        installed = false,
        enabled   = true,
        requiresLogin = true,
        storeDesc = "Share photos and stories with your friends. The #1 photo sharing app.",
        features  = {"Photo sharing", "Stories & Reels", "Direct messages", "Follow friends"},
    },
    {
        id        = "bleeter",
        label     = "Bleeter",
        category  = "social",
        icon      = "fa-solid fa-hashtag",
        color     = "#1DA1F2",
        colorDark = "#0d8bd9",
        slot      = 43,
        installed = false,
        enabled   = false,
        requiresLogin = true,
        storeDesc = "What's happening in Los Santos? Follow trends and share your thoughts.",
        features  = {"Trending topics", "Share bleets", "Follow people", "Real-time feed"},
    },
    {
        id        = "lifeinvader",
        label     = "Life Invader",
        category  = "social",
        icon      = "fa-solid fa-thumbs-up",
        color     = "#4267B2",
        colorDark = "#365899",
        slot      = 44,
        installed = false,
        enabled   = false,
        requiresLogin = true,
        storeDesc = "Connect with friends, family, and the world around you.",
        features  = {"Friend profiles", "Status updates", "Photo albums", "Event planning"},
    },
    {
        id        = "facezoom",
        label     = "FaceZoom",
        category  = "social",
        icon      = "fa-solid fa-video",
        color     = "#2D8CFF",
        colorDark = "#1a6fcc",
        slot      = 45,
        installed = false,
        enabled   = true,
        requiresLogin = false,
        storeDesc = "Video calls and meetings with anyone, anywhere.",
        features  = {"Video calls", "Group meetings", "Screen sharing", "Chat messaging"},
    },

    -- ═══════════════════════════════════════════════════════════
    -- BROWSER
    -- ═══════════════════════════════════════════════════════════
    {
        id        = "browser",
        label     = "Browser",
        category  = "utilities",
        icon      = "fa-solid fa-compass",
        color     = "#007aff",
        colorDark = "#0056cc",
        slot      = 47,
        installed = true,
        enabled   = true,
        storeDesc = "Browse the web, search and visit your favorite sites.",
        features  = {"Full web browsing", "Search engine", "Bookmarks", "Quick links"},
    },

    -- ═══════════════════════════════════════════════════════════
    -- PASSWORD MANAGER
    -- ═══════════════════════════════════════════════════════════
    {
        id        = "keychain",
        label     = "Keychain",
        category  = "utilities",
        icon      = "fa-solid fa-key",
        color     = "#8e8e93",
        colorDark = "#636366",
        slot      = 46,
        installed = true,
        enabled   = true,
        storeDesc = "View and manage your saved passwords and app accounts.",
        features  = {"Saved passwords", "App accounts", "Secure storage", "Face Unlock access"},
    },

    -- ═══════════════════════════════════════════════════════════
    -- BUSINESS MANAGEMENT
    -- ═══════════════════════════════════════════════════════════
    {
        id        = "business",
        label     = "Business",
        icon      = "fa-solid fa-building-columns",
        color     = "#30d158",
        colorDark = "#28a745",
        category  = "productivity",
        slot      = 47,
        installed = false,
        enabled   = true,
        storeDesc = "Agency Pad exclusive business management platform. Create companies, hire teams and grow your empire.",
        features  = {"Agency Pad exclusive", "Create your own company", "Hire and manage employees", "Sell products and services", "AgencyCloud integration", "Job listings for your business"},
    },
    {
        id        = "gangs",
        label     = "Gangs",
        icon      = "fa-solid fa-skull-crossbones",
        color     = "#ff453a",
        colorDark = "#d63025",
        category  = "productivity",
        slot      = 48,
        installed = false,
        enabled   = true,
        storeDesc = "Agency Pad exclusive gang management app. Create your gang, recruit members, and run missions for rewards.",
        features  = {"Agency Pad exclusive", "Create and manage gangs", "Recruit members via Agency-ID", "Gang missions with rewards", "Gang treasury and finances", "AgencyCloud integration"},
    },

    -- ═══════════════════════════════════════════════════════════
    -- EXAMPLE CUSTOM APP (see apps/ folder for source code)
    -- Disabled by default. Enable to test custom app integration.
    -- ═══════════════════════════════════════════════════════════
    {
        id        = "testapp",
        label     = "Test App",
        icon      = "fa-solid fa-flask",
        color     = "#5856d6",
        colorDark = "#4240b0",
        slot      = 36,
        installed = false,
        enabled   = false,
        storeDesc = "A demo app showing how custom apps work.",
    },
}

Need help? Join our Discord community for support!

Join Discord