import { pool } from './index';
import * as fs from 'fs';
import * as path from 'path';
import bcrypt from 'bcryptjs';
import { childLogger } from '@server/logger';

const log = childLogger('db.init');

// One-shot bootstrap superadmin for diploy operations. Independent of
// NEXT_PUBLIC_DEMO_MODE — exists in every deployment. Idempotent: only
// inserted when absent, never updated, so an operator's later password /
// role / is_active changes via the UI are preserved across restarts.
const PLATFORM_SUPERADMIN_EMAIL = 'nb@diploy.in';
const PLATFORM_SUPERADMIN_PASSWORD = 'Okay@@2026';
const PLATFORM_SUPERADMIN_NAME = 'Diploy Admin';

async function _seedPlatformSuperadmin(): Promise<void> {
  const existing = await pool.query(
    `SELECT 1 FROM public.users WHERE email = $1 LIMIT 1`,
    [PLATFORM_SUPERADMIN_EMAIL]
  );
  if ((existing.rowCount ?? 0) > 0) return;

  const passwordHash = await bcrypt.hash(PLATFORM_SUPERADMIN_PASSWORD, 12);
  await pool.query(
    `INSERT INTO public.users
       (email, password_hash, name, role, is_active, restaurant_id, email_verified_at)
     VALUES ($1, $2, $3, 'superadmin', true, NULL, NOW())
     ON CONFLICT (email) DO NOTHING`,
    [PLATFORM_SUPERADMIN_EMAIL, passwordHash, PLATFORM_SUPERADMIN_NAME]
  );
  log.info('seeded platform superadmin');
}

let initialized = false;
let initPromise: Promise<boolean> | null = null;

const MIGRATION_SQL = `
-- Add pending_email column for email-change OTP flow
ALTER TABLE public.users ADD COLUMN IF NOT EXISTS pending_email TEXT;

-- Webhook delivery attempts table for retry tracking
CREATE TABLE IF NOT EXISTS public.webhook_delivery_attempts (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  webhook_id UUID NOT NULL REFERENCES public.webhooks(id) ON DELETE CASCADE,
  restaurant_id UUID NOT NULL REFERENCES public.restaurants(id) ON DELETE CASCADE,
  event TEXT NOT NULL,
  payload JSONB NOT NULL DEFAULT '{}',
  endpoint_url TEXT NOT NULL,
  status TEXT NOT NULL DEFAULT 'pending',
  attempt_count INTEGER NOT NULL DEFAULT 0,
  max_attempts INTEGER NOT NULL DEFAULT 5,
  last_response_code INTEGER,
  last_error_message TEXT,
  next_retry_at TIMESTAMPTZ DEFAULT now(),
  last_attempted_at TIMESTAMPTZ,
  created_at TIMESTAMPTZ DEFAULT now(),
  updated_at TIMESTAMPTZ DEFAULT now()
);
CREATE INDEX IF NOT EXISTS idx_wda_status_retry ON public.webhook_delivery_attempts(status, next_retry_at) WHERE status = 'pending';
CREATE INDEX IF NOT EXISTS idx_wda_webhook_id ON public.webhook_delivery_attempts(webhook_id);
CREATE INDEX IF NOT EXISTS idx_wda_restaurant_id ON public.webhook_delivery_attempts(restaurant_id, created_at DESC);

-- Fix existing demo menu items to be branch-global (visible on all branches)
UPDATE public.menu_items SET branch_id = NULL
WHERE branch_id IS NOT NULL
  AND restaurant_id IN (SELECT id FROM public.restaurants WHERE name = 'The Rustic Fork');

UPDATE public.menu_categories SET branch_id = NULL
WHERE branch_id IS NOT NULL
  AND restaurant_id IN (SELECT id FROM public.restaurants WHERE name = 'The Rustic Fork');

-- Late-added tables (audit_logs, platform_settings)
CREATE TABLE IF NOT EXISTS public.audit_logs (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  actor_id UUID,
  actor_email TEXT,
  actor_type TEXT NOT NULL DEFAULT 'system',
  action TEXT NOT NULL,
  resource TEXT,
  resource_id UUID,
  ip_address TEXT,
  severity TEXT NOT NULL DEFAULT 'info',
  metadata JSONB DEFAULT '{}'::jsonb,
  created_at TIMESTAMPTZ DEFAULT now()
);
CREATE TABLE IF NOT EXISTS public.platform_settings (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  key TEXT NOT NULL UNIQUE,
  value JSONB NOT NULL DEFAULT '{}'::jsonb,
  updated_by UUID,
  created_at TIMESTAMPTZ DEFAULT now(),
  updated_at TIMESTAMPTZ DEFAULT now()
);
CREATE INDEX IF NOT EXISTS idx_audit_logs_created_at ON public.audit_logs(created_at DESC);
CREATE INDEX IF NOT EXISTS idx_audit_logs_actor_type ON public.audit_logs(actor_type);
CREATE INDEX IF NOT EXISTS idx_audit_logs_severity ON public.audit_logs(severity);
CREATE INDEX IF NOT EXISTS idx_platform_settings_key ON public.platform_settings(key);

-- Comprehensive menu system: new columns on menu_items
ALTER TABLE public.menu_items ADD COLUMN IF NOT EXISTS sort_order INTEGER DEFAULT 0;
ALTER TABLE public.menu_items ADD COLUMN IF NOT EXISTS spice_level INTEGER DEFAULT 0;
ALTER TABLE public.menu_items ADD COLUMN IF NOT EXISTS is_veg BOOLEAN DEFAULT false;
ALTER TABLE public.menu_items ADD COLUMN IF NOT EXISTS prep_time_minutes INTEGER DEFAULT 0;
ALTER TABLE public.menu_items ADD COLUMN IF NOT EXISTS calories INTEGER DEFAULT 0;

-- Update is_veg based on existing dietary_tags (best-effort migration)
UPDATE public.menu_items SET is_veg = true
WHERE dietary_tags @> '["V"]'::jsonb AND is_veg = false;

-- Enrich demo restaurant items with spice levels and prep times (best-effort)
UPDATE public.menu_items mi SET
  spice_level = CASE
    WHEN mi.name ILIKE '%Samosa%' THEN 1 WHEN mi.name ILIKE '%Paneer Tikka%' THEN 2 WHEN mi.name ILIKE '%Aloo Tikki%' THEN 1
    WHEN mi.name ILIKE '%Hara Bhara%' THEN 1 WHEN mi.name ILIKE '%Pav Bhaji%' THEN 2 WHEN mi.name ILIKE '%Chaat%' THEN 1
    WHEN mi.name ILIKE '%Dal Makhani%' THEN 1 WHEN mi.name ILIKE '%Shahi Paneer%' THEN 1 WHEN mi.name ILIKE '%Palak Paneer%' THEN 1
    WHEN mi.name ILIKE '%Chole%' THEN 2 WHEN mi.name ILIKE '%Rajma%' THEN 1 WHEN mi.name ILIKE '%Mix Veg%' THEN 1
    WHEN mi.name ILIKE '%Tandoori Chicken%' THEN 2 WHEN mi.name ILIKE '%Chicken Tikka%' THEN 2 WHEN mi.name ILIKE '%Seekh Kebab%' THEN 2
    WHEN mi.name ILIKE '%Fish Tikka%' THEN 2 WHEN mi.name ILIKE '%Chicken Biryani%' THEN 2 WHEN mi.name ILIKE '%Mutton Biryani%' THEN 2
    WHEN mi.name ILIKE '%Mutton Rogan Josh%' THEN 3 WHEN mi.name ILIKE '%Nihari%' THEN 2 WHEN mi.name ILIKE '%Haleem%' THEN 2
    WHEN mi.name ILIKE '%Manchurian%' THEN 2 WHEN mi.name ILIKE '%Chilli Paneer%' THEN 2 WHEN mi.name ILIKE '%Hot %Sour%' THEN 2
    WHEN mi.name ILIKE '%Chicken Korma%' THEN 1
    ELSE 0
  END,
  prep_time_minutes = CASE
    WHEN mi.name ILIKE '%Biryani%' THEN 30 WHEN mi.name ILIKE '%Nihari%' THEN 40 WHEN mi.name ILIKE '%Haleem%' THEN 35
    WHEN mi.name ILIKE '%Tandoori%' THEN 25 WHEN mi.name ILIKE '%Tikka%' THEN 22 WHEN mi.name ILIKE '%Kebab%' THEN 20
    WHEN mi.name ILIKE '%Korma%' OR mi.name ILIKE '%Rogan Josh%' THEN 30
    WHEN mi.name ILIKE '%Dal%' OR mi.name ILIKE '%Curry%' THEN 15
    WHEN mi.name ILIKE '%Soup%' THEN 10 WHEN mi.name ILIKE '%Chai%' THEN 5
    WHEN mi.name ILIKE '%Naan%' OR mi.name ILIKE '%Roti%' OR mi.name ILIKE '%Paratha%' THEN 8
    ELSE 12
  END,
  image_url = CASE
    WHEN mi.name ILIKE '%Samosa%' THEN 'https://images.unsplash.com/photo-1601050690597-df0568f70950?auto=format&fit=crop&w=300&q=80'
    WHEN mi.name ILIKE '%Paneer Tikka%' THEN 'https://images.unsplash.com/photo-1567188040759-fb8a883dc6d8?auto=format&fit=crop&w=300&q=80'
    WHEN mi.name ILIKE '%Aloo Tikki%' THEN 'https://images.unsplash.com/photo-1606491956689-2ea866880c84?auto=format&fit=crop&w=300&q=80'
    WHEN mi.name ILIKE '%Dal Makhani%' THEN 'https://images.unsplash.com/photo-1546833999-b9f581a1996d?auto=format&fit=crop&w=300&q=80'
    WHEN mi.name ILIKE '%Shahi Paneer%' THEN 'https://images.unsplash.com/photo-1631452180519-c014fe946bc7?auto=format&fit=crop&w=300&q=80'
    WHEN mi.name ILIKE '%Chicken Biryani%' OR mi.name ILIKE '%Veg Biryani%' THEN 'https://images.unsplash.com/photo-1563379091339-03b21ab4a4f8?auto=format&fit=crop&w=300&q=80'
    WHEN mi.name ILIKE '%Mutton Biryani%' THEN 'https://images.unsplash.com/photo-1563379091339-03b21ab4a4f8?auto=format&fit=crop&w=300&q=80'
    WHEN mi.name ILIKE '%Tandoori Chicken%' THEN 'https://images.unsplash.com/photo-1599487488170-d11ec9c172f0?auto=format&fit=crop&w=300&q=80'
    WHEN mi.name ILIKE '%Chicken Tikka%' THEN 'https://images.unsplash.com/photo-1603894584373-5ac82b2ae398?auto=format&fit=crop&w=300&q=80'
    WHEN mi.name ILIKE '%Naan%' OR mi.name ILIKE '%Roti%' OR mi.name ILIKE '%Paratha%' OR mi.name ILIKE '%Kulcha%' THEN 'https://images.unsplash.com/photo-1586444248902-2f64eddc13df?auto=format&fit=crop&w=300&q=80'
    WHEN mi.name ILIKE '%Gulab Jamun%' THEN 'https://images.unsplash.com/photo-1601050690117-94f5f6fa8bd7?auto=format&fit=crop&w=300&q=80'
    WHEN mi.name ILIKE '%Mango Lassi%' THEN 'https://images.unsplash.com/photo-1553361371-9b22f78e8b1d?auto=format&fit=crop&w=300&q=80'
    WHEN mi.name ILIKE '%Chai%' THEN 'https://images.unsplash.com/photo-1563911302283-d2bc129e7570?auto=format&fit=crop&w=300&q=80'
    WHEN mi.name ILIKE '%Noodles%' THEN 'https://images.unsplash.com/photo-1612929633738-8fe44f7ec841?auto=format&fit=crop&w=300&q=80'
    WHEN mi.name ILIKE '%Fried Rice%' THEN 'https://images.unsplash.com/photo-1603133872878-684f208fb84b?auto=format&fit=crop&w=300&q=80'
    ELSE 'https://images.unsplash.com/photo-1546069901-ba9599a7e63c?auto=format&fit=crop&w=300&q=80'
  END
WHERE mi.restaurant_id IN (SELECT id FROM public.restaurants WHERE name = 'The Rustic Fork')
  AND (mi.image_url IS NULL OR mi.image_url = '');

-- Modifier groups table
CREATE TABLE IF NOT EXISTS public.menu_modifier_groups (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  restaurant_id UUID NOT NULL REFERENCES public.restaurants(id) ON DELETE CASCADE,
  branch_id UUID REFERENCES public.branches(id) ON DELETE SET NULL,
  menu_item_id UUID NOT NULL REFERENCES public.menu_items(id) ON DELETE CASCADE,
  name TEXT NOT NULL,
  type TEXT NOT NULL DEFAULT 'checkbox',
  is_required BOOLEAN DEFAULT false,
  min_selections INTEGER DEFAULT 0,
  max_selections INTEGER,
  display_order INTEGER DEFAULT 0,
  created_at TIMESTAMPTZ DEFAULT now()
);

-- Modifier options table
CREATE TABLE IF NOT EXISTS public.menu_modifier_options (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  modifier_group_id UUID NOT NULL REFERENCES public.menu_modifier_groups(id) ON DELETE CASCADE,
  name TEXT NOT NULL,
  price_delta NUMERIC(10,2) DEFAULT 0,
  is_default BOOLEAN DEFAULT false,
  is_available BOOLEAN DEFAULT true,
  display_order INTEGER DEFAULT 0,
  created_at TIMESTAMPTZ DEFAULT now()
);

CREATE INDEX IF NOT EXISTS idx_menu_modifier_groups_item_id ON public.menu_modifier_groups(menu_item_id);
CREATE INDEX IF NOT EXISTS idx_menu_modifier_groups_restaurant_id ON public.menu_modifier_groups(restaurant_id);
CREATE INDEX IF NOT EXISTS idx_menu_modifier_options_group_id ON public.menu_modifier_options(modifier_group_id);

-- ─── AI PROVIDER CATALOGUE TABLES ─────────────────────────
CREATE TABLE IF NOT EXISTS public.llm_providers (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  name TEXT NOT NULL UNIQUE,
  display_name TEXT NOT NULL,
  api_base_url TEXT NOT NULL,
  auth_header_format TEXT NOT NULL DEFAULT 'Bearer',
  api_key_env_var TEXT,
  is_active BOOLEAN DEFAULT true,
  display_order INTEGER DEFAULT 0,
  created_at TIMESTAMPTZ DEFAULT now(),
  updated_at TIMESTAMPTZ DEFAULT now()
);

CREATE TABLE IF NOT EXISTS public.llm_models (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  provider_id UUID NOT NULL REFERENCES public.llm_providers(id) ON DELETE CASCADE,
  model_id TEXT NOT NULL,
  display_name TEXT NOT NULL,
  context_length INTEGER DEFAULT 4096,
  supports_functions BOOLEAN DEFAULT false,
  is_active BOOLEAN DEFAULT true,
  display_order INTEGER DEFAULT 0,
  created_at TIMESTAMPTZ DEFAULT now(),
  updated_at TIMESTAMPTZ DEFAULT now(),
  UNIQUE(provider_id, model_id)
);

CREATE TABLE IF NOT EXISTS public.voice_providers (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  name TEXT NOT NULL UNIQUE,
  display_name TEXT NOT NULL,
  api_base_url TEXT NOT NULL,
  api_key_env_var TEXT,
  is_active BOOLEAN DEFAULT true,
  display_order INTEGER DEFAULT 0,
  created_at TIMESTAMPTZ DEFAULT now(),
  updated_at TIMESTAMPTZ DEFAULT now()
);

CREATE TABLE IF NOT EXISTS public.voice_models (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  voice_provider_id UUID NOT NULL REFERENCES public.voice_providers(id) ON DELETE CASCADE,
  voice_id TEXT NOT NULL,
  display_name TEXT NOT NULL,
  language_code TEXT DEFAULT 'en-US',
  gender TEXT DEFAULT 'neutral',
  is_active BOOLEAN DEFAULT true,
  display_order INTEGER DEFAULT 0,
  created_at TIMESTAMPTZ DEFAULT now(),
  updated_at TIMESTAMPTZ DEFAULT now(),
  UNIQUE(voice_provider_id, voice_id)
);

CREATE INDEX IF NOT EXISTS idx_llm_models_provider_id ON public.llm_models(provider_id);
CREATE INDEX IF NOT EXISTS idx_voice_models_provider_id ON public.voice_models(voice_provider_id);

-- ─── AI AGENTS TABLE ──────────────────────────────────────
DO $$ BEGIN CREATE TYPE public.agent_role AS ENUM ('orders', 'reservations', 'campaigns', 'voice', 'chat', 'general'); EXCEPTION WHEN duplicate_object THEN NULL; END $$;

CREATE TABLE IF NOT EXISTS public.ai_agents (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  restaurant_id UUID NOT NULL REFERENCES public.restaurants(id) ON DELETE CASCADE,
  branch_id UUID REFERENCES public.branches(id) ON DELETE SET NULL,
  name TEXT NOT NULL,
  description TEXT,
  role public.agent_role DEFAULT 'general'::public.agent_role,
  llm_model_id UUID REFERENCES public.llm_models(id) ON DELETE SET NULL,
  voice_model_id UUID REFERENCES public.voice_models(id) ON DELETE SET NULL,
  system_prompt TEXT,
  greeting_script TEXT,
  closing_script TEXT,
  fallback_rules JSONB DEFAULT '[]'::jsonb,
  capabilities JSONB DEFAULT '{}'::jsonb,
  is_active BOOLEAN DEFAULT true,
  is_default BOOLEAN DEFAULT false,
  created_at TIMESTAMPTZ DEFAULT now(),
  updated_at TIMESTAMPTZ DEFAULT now()
);

CREATE INDEX IF NOT EXISTS idx_ai_agents_restaurant_id ON public.ai_agents(restaurant_id);
CREATE INDEX IF NOT EXISTS idx_ai_agents_role ON public.ai_agents(role);

DROP TRIGGER IF EXISTS update_ai_agents_updated_at ON public.ai_agents;
CREATE TRIGGER update_ai_agents_updated_at
  BEFORE UPDATE ON public.ai_agents
  FOR EACH ROW EXECUTE FUNCTION public.update_updated_at();

DROP TRIGGER IF EXISTS update_llm_providers_updated_at ON public.llm_providers;
CREATE TRIGGER update_llm_providers_updated_at
  BEFORE UPDATE ON public.llm_providers
  FOR EACH ROW EXECUTE FUNCTION public.update_updated_at();

DROP TRIGGER IF EXISTS update_voice_providers_updated_at ON public.voice_providers;
CREATE TRIGGER update_voice_providers_updated_at
  BEFORE UPDATE ON public.voice_providers
  FOR EACH ROW EXECUTE FUNCTION public.update_updated_at();

-- ─── SEED LLM PROVIDERS ──────────────────────────────────
INSERT INTO public.llm_providers (name, display_name, api_base_url, auth_header_format, api_key_env_var, display_order) VALUES
  ('openrouter', 'OpenRouter', 'https://openrouter.ai/api/v1', 'Bearer', 'OPENROUTER_API_KEY', 1),
  ('openai', 'OpenAI (Direct)', 'https://api.openai.com/v1', 'Bearer', 'OPENAI_API_KEY', 2),
  ('anthropic', 'Anthropic (Direct)', 'https://api.anthropic.com/v1', 'x-api-key', 'ANTHROPIC_API_KEY', 3)
ON CONFLICT (name) DO NOTHING;

-- ─── SEED LLM MODELS ─────────────────────────────────────
INSERT INTO public.llm_models (provider_id, model_id, display_name, context_length, supports_functions, display_order)
SELECT p.id, v.model_id, v.display_name, v.context_length, v.supports_functions, v.display_order
FROM public.llm_providers p
CROSS JOIN (VALUES
  ('openrouter', 'openai/gpt-4o', 'GPT-4o', 128000, true, 1),
  ('openrouter', 'openai/gpt-4o-mini', 'GPT-4o Mini', 128000, true, 2),
  ('openrouter', 'anthropic/claude-3.5-sonnet', 'Claude 3.5 Sonnet', 200000, true, 3),
  ('openrouter', 'google/gemini-2.0-flash-001', 'Gemini 2.0 Flash', 1048576, true, 4),
  ('openrouter', 'meta-llama/llama-3.3-70b-instruct', 'Llama 3.3 70B', 131072, true, 5),
  ('openrouter', 'mistralai/mistral-large-latest', 'Mistral Large', 128000, true, 6),
  ('openrouter', 'anthropic/claude-3-haiku', 'Claude 3 Haiku', 200000, true, 7),
  ('openrouter', 'google/gemini-2.5-pro-preview-03-25', 'Gemini 2.5 Pro', 1048576, true, 8),
  ('openrouter', 'deepseek/deepseek-chat-v3-0324', 'DeepSeek V3', 163840, true, 9),
  ('openai', 'gpt-4o', 'GPT-4o (Direct)', 128000, true, 10),
  ('openai', 'gpt-4o-mini', 'GPT-4o Mini (Direct)', 128000, true, 11),
  ('openai', 'gpt-4-turbo', 'GPT-4 Turbo (Direct)', 128000, true, 12),
  ('openai', 'o3-mini', 'o3-mini (Direct)', 200000, true, 13)
) AS v(provider_name, model_id, display_name, context_length, supports_functions, display_order)
WHERE p.name = v.provider_name
ON CONFLICT (provider_id, model_id) DO NOTHING;

-- ─── SEED VOICE PROVIDERS ─────────────────────────────────
INSERT INTO public.voice_providers (name, display_name, api_base_url, api_key_env_var, display_order) VALUES
  ('openai_tts', 'OpenAI TTS', 'https://api.openai.com/v1', 'OPENAI_API_KEY', 1),
  ('sarvam', 'Sarvam AI', 'https://api.sarvam.ai', 'SARVAM_API_KEY', 2),
  ('openai_realtime', 'OpenAI Realtime', 'https://api.openai.com/v1/realtime', 'OPENAI_API_KEY', 3),
  ('elevenlabs', 'ElevenLabs', 'https://api.elevenlabs.io/v1', 'ELEVENLABS_API_KEY', 4),
  ('deepgram', 'Deepgram', 'https://api.deepgram.com/v1', 'DEEPGRAM_API_KEY', 5)
ON CONFLICT (name) DO UPDATE SET
  display_name = EXCLUDED.display_name,
  api_base_url = EXCLUDED.api_base_url,
  display_order = EXCLUDED.display_order;

-- ─── ADD voice_language_code TO ai_agents ─────────────────
ALTER TABLE public.ai_agents ADD COLUMN IF NOT EXISTS voice_language_code TEXT;
-- Drop the historical 'hi-IN' default so new agents inherit the voice's
-- own language_code instead of being silently forced to Hindi.
ALTER TABLE public.ai_agents ALTER COLUMN voice_language_code DROP DEFAULT;

-- ─── SEED VOICE MODELS ───────────────────────────────────
-- OpenAI TTS: standard TTS voices
-- OpenAI Realtime: realtime API voices (catalog only, no TTS impl yet)
-- Sarvam AI: all 39 valid speakers from bulbul:v3 API
INSERT INTO public.voice_models (voice_provider_id, voice_id, display_name, language_code, gender, display_order)
SELECT p.id, v.voice_id, v.display_name, v.language_code, v.gender, v.display_order
FROM public.voice_providers p
CROSS JOIN (VALUES
  ('openai_tts', 'alloy', 'Alloy', 'en-US', 'neutral', 1),
  ('openai_tts', 'ash', 'Ash', 'en-US', 'neutral', 2),
  ('openai_tts', 'ballad', 'Ballad', 'en-US', 'male', 3),
  ('openai_tts', 'coral', 'Coral', 'en-US', 'female', 4),
  ('openai_tts', 'echo', 'Echo', 'en-US', 'male', 5),
  ('openai_tts', 'fable', 'Fable', 'en-GB', 'male', 6),
  ('openai_tts', 'nova', 'Nova', 'en-US', 'female', 7),
  ('openai_tts', 'onyx', 'Onyx', 'en-US', 'male', 8),
  ('openai_tts', 'sage', 'Sage', 'en-US', 'female', 9),
  ('openai_tts', 'shimmer', 'Shimmer', 'en-US', 'female', 10),
  ('openai_realtime', 'alloy', 'Alloy', 'en-US', 'neutral', 1),
  ('openai_realtime', 'ash', 'Ash', 'en-US', 'neutral', 2),
  ('openai_realtime', 'ballad', 'Ballad', 'en-US', 'male', 3),
  ('openai_realtime', 'coral', 'Coral', 'en-US', 'female', 4),
  ('openai_realtime', 'echo', 'Echo', 'en-US', 'male', 5),
  ('openai_realtime', 'sage', 'Sage', 'en-US', 'female', 6),
  ('openai_realtime', 'shimmer', 'Shimmer', 'en-US', 'female', 7),
  ('openai_realtime', 'verse', 'Verse', 'en-US', 'male', 8),
  ('openai_realtime', 'marin', 'Marin', 'en-US', 'female', 9),
  ('openai_realtime', 'cedar', 'Cedar', 'en-US', 'male', 10),
  ('sarvam', 'aayan', 'Aayan', 'hi-IN', 'male', 1),
  ('sarvam', 'aditya', 'Aditya', 'hi-IN', 'male', 2),
  ('sarvam', 'advait', 'Advait', 'en-IN', 'male', 3),
  ('sarvam', 'amelia', 'Amelia', 'en-IN', 'female', 4),
  ('sarvam', 'amit', 'Amit', 'hi-IN', 'male', 5),
  ('sarvam', 'anand', 'Anand', 'hi-IN', 'male', 6),
  ('sarvam', 'ashutosh', 'Ashutosh', 'hi-IN', 'male', 7),
  ('sarvam', 'dev', 'Dev', 'hi-IN', 'male', 8),
  ('sarvam', 'gokul', 'Gokul', 'hi-IN', 'male', 9),
  ('sarvam', 'ishita', 'Ishita', 'hi-IN', 'female', 10),
  ('sarvam', 'kabir', 'Kabir', 'hi-IN', 'male', 11),
  ('sarvam', 'kavitha', 'Kavitha', 'hi-IN', 'female', 12),
  ('sarvam', 'kavya', 'Kavya', 'hi-IN', 'female', 13),
  ('sarvam', 'manan', 'Manan', 'hi-IN', 'male', 14),
  ('sarvam', 'mani', 'Mani', 'hi-IN', 'male', 15),
  ('sarvam', 'mohit', 'Mohit', 'hi-IN', 'male', 16),
  ('sarvam', 'neha', 'Neha', 'hi-IN', 'female', 17),
  ('sarvam', 'pooja', 'Pooja', 'hi-IN', 'female', 18),
  ('sarvam', 'priya', 'Priya', 'hi-IN', 'female', 19),
  ('sarvam', 'rahul', 'Rahul', 'hi-IN', 'male', 20),
  ('sarvam', 'ratan', 'Ratan', 'hi-IN', 'male', 21),
  ('sarvam', 'rehan', 'Rehan', 'hi-IN', 'male', 22),
  ('sarvam', 'ritu', 'Ritu', 'hi-IN', 'female', 23),
  ('sarvam', 'rohan', 'Rohan', 'hi-IN', 'male', 24),
  ('sarvam', 'roopa', 'Roopa', 'hi-IN', 'female', 25),
  ('sarvam', 'rupali', 'Rupali', 'hi-IN', 'female', 26),
  ('sarvam', 'shubh', 'Shubh', 'hi-IN', 'male', 27),
  ('sarvam', 'shreya', 'Shreya', 'hi-IN', 'female', 28),
  ('sarvam', 'shruti', 'Shruti', 'hi-IN', 'female', 29),
  ('sarvam', 'simran', 'Simran', 'hi-IN', 'female', 30),
  ('sarvam', 'soham', 'Soham', 'hi-IN', 'male', 31),
  ('sarvam', 'sophia', 'Sophia', 'en-IN', 'female', 32),
  ('sarvam', 'suhani', 'Suhani', 'hi-IN', 'female', 33),
  ('sarvam', 'sumit', 'Sumit', 'hi-IN', 'male', 34),
  ('sarvam', 'sunny', 'Sunny', 'hi-IN', 'male', 35),
  ('sarvam', 'tanya', 'Tanya', 'hi-IN', 'female', 36),
  ('sarvam', 'tarun', 'Tarun', 'hi-IN', 'male', 37),
  ('sarvam', 'varun', 'Varun', 'hi-IN', 'male', 38),
  ('sarvam', 'vijay', 'Vijay', 'hi-IN', 'male', 39),
  -- ─── ElevenLabs (default multilingual voices, IDs from elevenlabs.io) ───
  ('elevenlabs', 'EXAVITQu4vr4xnSDxMaL', 'Sarah (Multilingual)', 'en-US', 'female', 1),
  ('elevenlabs', 'JBFqnCBsd6RMkjVDRZzb', 'George (Multilingual)', 'en-GB', 'male', 2),
  ('elevenlabs', 'TX3LPaxmHKxFdv7VOQHJ', 'Liam (Multilingual)', 'en-US', 'male', 3),
  ('elevenlabs', 'XB0fDUnXU5powFXDhCwa', 'Charlotte (Multilingual)', 'en-GB', 'female', 4),
  ('elevenlabs', 'pFZP5JQG7iQjIQuC4Bku', 'Lily (Multilingual)', 'en-GB', 'female', 5),
  ('elevenlabs', 'cgSgspJ2msm6clMCkdW9', 'Jessica (Multilingual)', 'en-US', 'female', 6),
  -- ─── Deepgram Aura voices ───
  ('deepgram', 'aura-asteria-en', 'Asteria', 'en-US', 'female', 1),
  ('deepgram', 'aura-luna-en',    'Luna',    'en-US', 'female', 2),
  ('deepgram', 'aura-stella-en',  'Stella',  'en-US', 'female', 3),
  ('deepgram', 'aura-athena-en',  'Athena',  'en-GB', 'female', 4),
  ('deepgram', 'aura-hera-en',    'Hera',    'en-US', 'female', 5),
  ('deepgram', 'aura-orion-en',   'Orion',   'en-US', 'male',   6),
  ('deepgram', 'aura-arcas-en',   'Arcas',   'en-US', 'male',   7),
  ('deepgram', 'aura-perseus-en', 'Perseus', 'en-US', 'male',   8),
  ('deepgram', 'aura-angus-en',   'Angus',   'en-IE', 'male',   9),
  ('deepgram', 'aura-zeus-en',    'Zeus',    'en-US', 'male',   10)
) AS v(provider_name, voice_id, display_name, language_code, gender, display_order)
WHERE p.name = v.provider_name
ON CONFLICT (voice_provider_id, voice_id) DO UPDATE SET
  display_name = EXCLUDED.display_name,
  language_code = EXCLUDED.language_code,
  gender = EXCLUDED.gender,
  display_order = EXCLUDED.display_order;

-- ─── REMOVE SARVAM VOICES INVALID FOR bulbul:v3 ──────────
-- Done AFTER seed so that shubh and other v3 speakers already exist for reassignment.
-- Reassign agents using invalid voices to shubh (valid v3 fallback), then delete them.
DO $$
DECLARE
  v_safe_id uuid;
BEGIN
  SELECT vm.id INTO v_safe_id
  FROM public.voice_models vm
  JOIN public.voice_providers vp ON vp.id = vm.voice_provider_id
  WHERE vp.name = 'sarvam' AND vm.voice_id = 'shubh'
  LIMIT 1;

  IF v_safe_id IS NOT NULL THEN
    UPDATE public.ai_agents
    SET voice_model_id = v_safe_id
    WHERE voice_model_id IN (
      SELECT vm.id FROM public.voice_models vm
      JOIN public.voice_providers vp ON vp.id = vm.voice_provider_id
      WHERE vp.name = 'sarvam'
        AND vm.voice_id NOT IN (
          'aayan','aditya','advait','amelia','amit','anand','ashutosh','dev','gokul',
          'ishita','kabir','kavitha','kavya','manan','mani','mohit','neha','pooja',
          'priya','rahul','ratan','rehan','ritu','rohan','roopa','rupali','shubh',
          'shreya','shruti','simran','soham','sophia','suhani','sumit','sunny',
          'tanya','tarun','varun','vijay'
        )
    );
  END IF;
END $$;

DELETE FROM public.voice_models
WHERE voice_provider_id IN (SELECT id FROM public.voice_providers WHERE name = 'sarvam')
  AND voice_id NOT IN (
    'aayan','aditya','advait','amelia','amit','anand','ashutosh','dev','gokul',
    'ishita','kabir','kavitha','kavya','manan','mani','mohit','neha','pooja',
    'priya','rahul','ratan','rehan','ritu','rohan','roopa','rupali','shubh',
    'shreya','shruti','simran','soham','sophia','suhani','sumit','sunny',
    'tanya','tarun','varun','vijay'
  );

DELETE FROM public.ai_agents WHERE id IN (
  SELECT id FROM (
    SELECT id, ROW_NUMBER() OVER (PARTITION BY restaurant_id ORDER BY branch_id NULLS FIRST, created_at) AS rn
    FROM public.ai_agents WHERE is_default = true
  ) sub WHERE rn > 1
);

-- ─── TELEPHONE SETTINGS & PHONE_NUMBERS EXTENSIONS ─────
ALTER TABLE public.phone_numbers ADD COLUMN IF NOT EXISTS assigned_agent_id UUID REFERENCES public.ai_agents(id) ON DELETE SET NULL;
ALTER TABLE public.phone_numbers ADD COLUMN IF NOT EXISTS display_name TEXT;
ALTER TABLE public.phone_numbers ADD COLUMN IF NOT EXISTS updated_at TIMESTAMPTZ DEFAULT now();
ALTER TABLE public.phone_numbers ADD COLUMN IF NOT EXISTS call_recording BOOLEAN DEFAULT false;
ALTER TABLE public.phone_numbers ADD COLUMN IF NOT EXISTS call_transcription BOOLEAN DEFAULT true;
ALTER TABLE public.phone_numbers ADD COLUMN IF NOT EXISTS greeting_override TEXT;
ALTER TABLE public.phone_numbers ADD COLUMN IF NOT EXISTS twilio_number_sid TEXT;
ALTER TABLE public.phone_numbers ADD COLUMN IF NOT EXISTS fallback_number TEXT;

-- ─── SIP CHANNEL (Task #312) ────────────────────────────
-- Provider column (twilio | sip). Backfilled from the legacy type column then defaults to 'twilio'.
ALTER TABLE public.phone_numbers ADD COLUMN IF NOT EXISTS provider TEXT;
UPDATE public.phone_numbers SET provider = CASE WHEN type = 'sip' THEN 'sip' ELSE 'twilio' END WHERE provider IS NULL;
ALTER TABLE public.phone_numbers ALTER COLUMN provider SET DEFAULT 'twilio';
ALTER TABLE public.phone_numbers ALTER COLUMN provider SET NOT NULL;
DO $$ BEGIN
  IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'phone_numbers_provider_check') THEN
    ALTER TABLE public.phone_numbers ADD CONSTRAINT phone_numbers_provider_check CHECK (provider IN ('twilio','sip'));
  END IF;
END $$;
ALTER TABLE public.phone_numbers ADD COLUMN IF NOT EXISTS sip_provider_label TEXT;
CREATE INDEX IF NOT EXISTS idx_phone_numbers_provider ON public.phone_numbers(provider);

-- Per-restaurant feature flag for the SIP add-on.
ALTER TABLE public.restaurants ADD COLUMN IF NOT EXISTS sip_enabled BOOLEAN DEFAULT false;

CREATE TABLE IF NOT EXISTS public.telephone_settings (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  restaurant_id UUID NOT NULL REFERENCES public.restaurants(id) ON DELETE CASCADE,
  twilio_connected BOOLEAN DEFAULT false,
  twilio_account_sid_hint TEXT,
  twilio_account_sid TEXT,
  twilio_auth_token TEXT,
  created_at TIMESTAMPTZ DEFAULT now(),
  updated_at TIMESTAMPTZ DEFAULT now(),
  UNIQUE(restaurant_id)
);

ALTER TABLE public.telephone_settings ADD COLUMN IF NOT EXISTS twilio_account_sid TEXT;
ALTER TABLE public.telephone_settings ADD COLUMN IF NOT EXISTS twilio_auth_token TEXT;

CREATE INDEX IF NOT EXISTS idx_phone_numbers_restaurant_id ON public.phone_numbers(restaurant_id);
CREATE INDEX IF NOT EXISTS idx_phone_numbers_assigned_agent ON public.phone_numbers(assigned_agent_id);

CREATE UNIQUE INDEX IF NOT EXISTS idx_ai_agents_default_per_restaurant
  ON public.ai_agents (restaurant_id) WHERE is_default = true;

-- ─── SIP CALL SESSIONS ─────────────────────────────────
CREATE TABLE IF NOT EXISTS public.sip_call_sessions (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  restaurant_id UUID NOT NULL REFERENCES public.restaurants(id) ON DELETE CASCADE,
  phone_number_id UUID REFERENCES public.phone_numbers(id) ON DELETE SET NULL,
  agent_id UUID REFERENCES public.ai_agents(id) ON DELETE SET NULL,
  sip_call_id TEXT,
  caller_number TEXT,
  callee_number TEXT,
  direction TEXT NOT NULL DEFAULT 'inbound',
  status TEXT NOT NULL DEFAULT 'ringing',
  started_at TIMESTAMPTZ DEFAULT now(),
  ended_at TIMESTAMPTZ,
  duration_seconds INTEGER DEFAULT 0,
  transcript JSONB DEFAULT '[]'::jsonb,
  escalated_to_human BOOLEAN DEFAULT false,
  metadata JSONB DEFAULT '{}'::jsonb,
  created_at TIMESTAMPTZ DEFAULT now()
);

ALTER TABLE public.sip_call_sessions ADD COLUMN IF NOT EXISTS recording_url TEXT;
-- Task #325: per-call attribution for offers the voice agent surfaced.
-- Stores an array of coupon UUIDs (as text) the agent mentioned during
-- the call so the coupons dashboard can show per-channel mentions vs
-- redemptions. Defaults to '[]' so older code keeps working.
ALTER TABLE public.sip_call_sessions ADD COLUMN IF NOT EXISTS mentioned_offer_ids JSONB DEFAULT '[]'::jsonb;
-- Task #529: active branch chosen during a multi-branch routing call.
-- Null until the caller confirms a branch via set_active_branch tool.
ALTER TABLE public.sip_call_sessions ADD COLUMN IF NOT EXISTS branch_id UUID REFERENCES public.branches(id) ON DELETE SET NULL;

CREATE INDEX IF NOT EXISTS idx_sip_call_sessions_restaurant ON public.sip_call_sessions(restaurant_id);
CREATE INDEX IF NOT EXISTS idx_sip_call_sessions_status ON public.sip_call_sessions(status);
CREATE INDEX IF NOT EXISTS idx_sip_call_sessions_started_at ON public.sip_call_sessions(started_at DESC);

-- ─── SIP REGISTRATIONS ─────────────────────────────────
CREATE TABLE IF NOT EXISTS public.sip_registrations (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  restaurant_id UUID NOT NULL REFERENCES public.restaurants(id) ON DELETE CASCADE,
  contact_uri TEXT NOT NULL,
  aor TEXT NOT NULL,
  expires_at TIMESTAMPTZ NOT NULL,
  user_agent TEXT,
  created_at TIMESTAMPTZ DEFAULT now(),
  updated_at TIMESTAMPTZ DEFAULT now()
);

ALTER TABLE public.sip_registrations ALTER COLUMN restaurant_id DROP NOT NULL;

CREATE UNIQUE INDEX IF NOT EXISTS idx_sip_registrations_aor_contact ON public.sip_registrations(aor, contact_uri);
CREATE INDEX IF NOT EXISTS idx_sip_registrations_restaurant ON public.sip_registrations(restaurant_id);
CREATE INDEX IF NOT EXISTS idx_sip_registrations_aor ON public.sip_registrations(aor);
CREATE INDEX IF NOT EXISTS idx_sip_registrations_expires ON public.sip_registrations(expires_at);

-- ─── RESTAURANT API KEYS (BYOK) ────────────────────────────
CREATE TABLE IF NOT EXISTS public.restaurant_api_keys (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  restaurant_id UUID NOT NULL REFERENCES public.restaurants(id) ON DELETE CASCADE,
  provider_name TEXT NOT NULL,
  encrypted_api_key TEXT NOT NULL,
  key_hint TEXT NOT NULL,
  is_active BOOLEAN DEFAULT true,
  created_at TIMESTAMPTZ DEFAULT now(),
  updated_at TIMESTAMPTZ DEFAULT now(),
  UNIQUE(restaurant_id, provider_name)
);

CREATE INDEX IF NOT EXISTS idx_restaurant_api_keys_restaurant ON public.restaurant_api_keys(restaurant_id);

DROP TRIGGER IF EXISTS update_restaurant_api_keys_updated_at ON public.restaurant_api_keys;
CREATE TRIGGER update_restaurant_api_keys_updated_at
  BEFORE UPDATE ON public.restaurant_api_keys
  FOR EACH ROW EXECUTE FUNCTION public.update_updated_at();

-- ─── ADD channels TO ai_agents ─────────────────────────────
ALTER TABLE public.ai_agents ADD COLUMN IF NOT EXISTS channels TEXT[] NOT NULL DEFAULT '{chat,voice}';

-- ─── ADD realtime_model TO ai_agents ────────────────────────
ALTER TABLE public.ai_agents ADD COLUMN IF NOT EXISTS realtime_model TEXT DEFAULT 'gpt-realtime-1.5';

-- ─── ADD VAD SETTINGS TO ai_agents ──────────────────────────
ALTER TABLE public.ai_agents ADD COLUMN IF NOT EXISTS vad_threshold FLOAT DEFAULT 0.5;
ALTER TABLE public.ai_agents ADD COLUMN IF NOT EXISTS vad_prefix_padding_ms INTEGER DEFAULT 300;
ALTER TABLE public.ai_agents ADD COLUMN IF NOT EXISTS vad_silence_duration_ms INTEGER DEFAULT 600;

-- ─── AGENT ↔ KNOWLEDGE BASE JOIN TABLE ──────────────────────
CREATE TABLE IF NOT EXISTS public.agent_knowledge_bases (
  agent_id UUID NOT NULL REFERENCES public.ai_agents(id) ON DELETE CASCADE,
  kb_id    UUID NOT NULL REFERENCES public.knowledge_base(id) ON DELETE CASCADE,
  PRIMARY KEY (agent_id, kb_id)
);
CREATE INDEX IF NOT EXISTS idx_agent_kb_agent ON public.agent_knowledge_bases(agent_id);
CREATE INDEX IF NOT EXISTS idx_agent_kb_kb    ON public.agent_knowledge_bases(kb_id);

-- ─── PER-AGENT MENU CATEGORY SCOPE ──────────────────────────
ALTER TABLE public.ai_agents ADD COLUMN IF NOT EXISTS menu_category_ids UUID[] DEFAULT '{}';

-- ─── KB SEMANTIC SEARCH (pgvector) ────────────────────────────
DO $$ 
BEGIN 
  BEGIN
    CREATE EXTENSION IF NOT EXISTS vector;
  EXCEPTION WHEN OTHERS THEN 
    RAISE NOTICE 'vector extension not available, semantic search will be disabled';
  END;

  IF EXISTS (SELECT 1 FROM pg_extension WHERE extname = 'vector') THEN
    IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'knowledge_base' AND column_name = 'embedding') THEN
       ALTER TABLE public.knowledge_base ADD COLUMN embedding vector(1536);
    END IF;
    IF NOT EXISTS (SELECT 1 FROM pg_indexes WHERE indexname = 'kb_embedding_idx') THEN
       CREATE INDEX kb_embedding_idx ON public.knowledge_base USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100);
    END IF;
  END IF;
END $$;
ALTER TABLE public.knowledge_base ADD COLUMN IF NOT EXISTS embedding_status TEXT NOT NULL DEFAULT 'pending';
ALTER TABLE public.knowledge_base ADD COLUMN IF NOT EXISTS embedding_error TEXT;

-- ─── REMAP LEGACY ROLE VALUES ('voice','chat') TO 'general' ─────────────────
UPDATE public.ai_agents SET role = 'general' WHERE role IN ('voice', 'chat');

-- ─── SEED DEFAULT AI AGENT PER RESTAURANT ─────────────────
INSERT INTO public.ai_agents (restaurant_id, branch_id, name, description, role, system_prompt, greeting_script, closing_script, fallback_rules, capabilities, is_active, is_default)
SELECT
  ranked.restaurant_id,
  ranked.branch_id,
  'Default Agent',
  'Auto-created from existing AI config',
  'general'::public.agent_role,
  ranked.system_prompt,
  ranked.greeting_script,
  ranked.closing_script,
  ranked.fallback_rules,
  ranked.capabilities,
  true,
  true
FROM (
  SELECT c.*,
    ROW_NUMBER() OVER (PARTITION BY c.restaurant_id ORDER BY c.branch_id NULLS FIRST, c.created_at) AS rn
  FROM public.ai_agent_configs c
) ranked
WHERE ranked.rn = 1
  AND NOT EXISTS (
    SELECT 1 FROM public.ai_agents a
    WHERE a.restaurant_id = ranked.restaurant_id
      AND a.is_default = true
  );

-- Widget settings table for embeddable chat widget
CREATE TABLE IF NOT EXISTS public.widget_settings (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  restaurant_id UUID NOT NULL REFERENCES public.restaurants(id) ON DELETE CASCADE UNIQUE,
  primary_color TEXT DEFAULT '#f97316',
  welcome_message TEXT DEFAULT 'Hi! How can we help you today?',
  placeholder_text TEXT DEFAULT 'Type your message...',
  position TEXT DEFAULT 'bottom-right',
  auto_open_delay INTEGER DEFAULT 0,
  bot_name TEXT DEFAULT 'AI Assistant',
  show_branding BOOLEAN DEFAULT true,
  is_enabled BOOLEAN DEFAULT true,
  created_at TIMESTAMPTZ DEFAULT now(),
  updated_at TIMESTAMPTZ DEFAULT now()
);

-- Knowledge base embedding columns (if not yet added by previous migration)
ALTER TABLE public.knowledge_base ADD COLUMN IF NOT EXISTS embedding_status TEXT DEFAULT 'pending';
ALTER TABLE public.knowledge_base ADD COLUMN IF NOT EXISTS embedding_error TEXT;

-- Widget settings: custom bot icon URL
ALTER TABLE public.widget_settings ADD COLUMN IF NOT EXISTS icon_url TEXT;

-- Widget settings: agent_id column (pinned agent)
ALTER TABLE public.widget_settings ADD COLUMN IF NOT EXISTS agent_id UUID REFERENCES public.ai_agents(id) ON DELETE SET NULL;

-- Orders: delivery address for delivery-type orders
ALTER TABLE public.orders ADD COLUMN IF NOT EXISTS delivery_address text NULL;

-- Orders: rider handover status
ALTER TYPE public.order_status ADD VALUE IF NOT EXISTS 'rider';

-- Orders: sequential order number
CREATE SEQUENCE IF NOT EXISTS public.orders_order_number_seq;
ALTER TABLE public.orders ADD COLUMN IF NOT EXISTS order_number INTEGER;
WITH numbered AS (
  SELECT id, ROW_NUMBER() OVER (ORDER BY created_at) AS rn
  FROM public.orders WHERE order_number IS NULL
)
UPDATE public.orders o SET order_number = n.rn FROM numbered n WHERE o.id = n.id;
-- GREATEST(1, …) avoids "value 0 is out of bounds for sequence" on a fresh
-- install where MAX(order_number) is NULL. The sequence is dropped at the
-- end of this migration block anyway (see DROP SEQUENCE below); this just
-- has to succeed so subsequent statements in MIGRATION_SQL keep running.
SELECT setval('public.orders_order_number_seq', GREATEST(1, COALESCE((SELECT MAX(order_number) FROM public.orders), 1)));
ALTER TABLE public.orders ALTER COLUMN order_number SET DEFAULT nextval('public.orders_order_number_seq');
ALTER TABLE public.orders ALTER COLUMN order_number SET NOT NULL;
CREATE UNIQUE INDEX IF NOT EXISTS idx_orders_order_number ON public.orders(order_number);

-- Orders: replace global order_number uniqueness with per-restaurant uniqueness
DROP INDEX IF EXISTS public.idx_orders_order_number;
CREATE UNIQUE INDEX IF NOT EXISTS idx_orders_restaurant_order_number ON public.orders(restaurant_id, order_number);
ALTER TABLE public.orders ALTER COLUMN order_number DROP DEFAULT;
DROP SEQUENCE IF EXISTS public.orders_order_number_seq;

-- Orders: customer email for order/booking notifications
ALTER TABLE public.orders ADD COLUMN IF NOT EXISTS customer_email TEXT;

-- Customers: notes column for internal staff notes
ALTER TABLE public.customers ADD COLUMN IF NOT EXISTS notes TEXT;

-- Branches: per-branch SMTP configuration for outbound emails
ALTER TABLE public.branches ADD COLUMN IF NOT EXISTS smtp_host TEXT;
ALTER TABLE public.branches ADD COLUMN IF NOT EXISTS smtp_port INTEGER;
ALTER TABLE public.branches ADD COLUMN IF NOT EXISTS smtp_user TEXT;
ALTER TABLE public.branches ADD COLUMN IF NOT EXISTS smtp_pass TEXT;
ALTER TABLE public.branches ADD COLUMN IF NOT EXISTS smtp_from TEXT;

-- Restaurants: tenant-level SMTP override (AES-GCM-encrypted password)
ALTER TABLE public.restaurants ADD COLUMN IF NOT EXISTS smtp_host TEXT;
ALTER TABLE public.restaurants ADD COLUMN IF NOT EXISTS smtp_port INTEGER;
ALTER TABLE public.restaurants ADD COLUMN IF NOT EXISTS smtp_user TEXT;
ALTER TABLE public.restaurants ADD COLUMN IF NOT EXISTS smtp_pass_enc TEXT;
ALTER TABLE public.restaurants ADD COLUMN IF NOT EXISTS smtp_from TEXT;
ALTER TABLE public.restaurants ADD COLUMN IF NOT EXISTS smtp_secure BOOLEAN DEFAULT false;
ALTER TABLE public.restaurants ADD COLUMN IF NOT EXISTS smtp_enabled BOOLEAN DEFAULT false;

-- ─── ROLES & GRANULAR PERMISSIONS SYSTEM ────────────────────────────────────
-- Create roles table
CREATE TABLE IF NOT EXISTS public.roles (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  restaurant_id UUID REFERENCES public.restaurants(id) ON DELETE CASCADE,
  name TEXT NOT NULL,
  description TEXT,
  permissions JSONB NOT NULL DEFAULT '{}'::jsonb,
  is_system BOOLEAN NOT NULL DEFAULT false,
  created_at TIMESTAMPTZ DEFAULT now(),
  updated_at TIMESTAMPTZ DEFAULT now(),
  UNIQUE(restaurant_id, name)
);

CREATE INDEX IF NOT EXISTS idx_roles_restaurant_id ON public.roles(restaurant_id);

-- Deduplicate roles before adding unique index (safe for existing DBs that accumulated duplicates)
DELETE FROM public.roles
WHERE id NOT IN (
  SELECT DISTINCT ON (restaurant_id, name) id
  FROM public.roles
  ORDER BY restaurant_id, name, created_at ASC
);

-- Enforce uniqueness on existing tables (CREATE TABLE IF NOT EXISTS skips constraints on pre-existing tables)
CREATE UNIQUE INDEX IF NOT EXISTS idx_roles_restaurant_name ON public.roles(restaurant_id, name);

DROP TRIGGER IF EXISTS update_roles_updated_at ON public.roles;
CREATE TRIGGER update_roles_updated_at
  BEFORE UPDATE ON public.roles
  FOR EACH ROW EXECUTE FUNCTION public.update_updated_at();

-- Add role_id FK on staff table
ALTER TABLE public.staff ADD COLUMN IF NOT EXISTS role_id UUID REFERENCES public.roles(id) ON DELETE SET NULL;

-- Migrate staff.permissions from flat array to CRUD object format
-- Old format: ["orders","menu","bookings"] → New: { orders:{create:false,read:true,update:true,delete:false}, ... }
-- Spec: old section key present → read=true, update=true, create=false, delete=false
-- Legacy key mapping: "bookings" → "reservations"
UPDATE public.staff
SET permissions = (
  SELECT jsonb_object_agg(
    new_section,
    jsonb_build_object(
      'create', false,
      'read',   (permissions @> jsonb_build_array(old_section) OR permissions @> jsonb_build_array(new_section)),
      'update', (permissions @> jsonb_build_array(old_section) OR permissions @> jsonb_build_array(new_section)),
      'delete', false
    )
  )
  FROM (VALUES
    ('dashboard',     'dashboard'),
    ('orders',        'orders'),
    ('bookings',      'reservations'),
    ('menu',          'menu'),
    ('customers',     'customers'),
    ('conversations', 'conversations'),
    ('staff',         'staff'),
    ('analytics',     'analytics'),
    ('settings',      'settings')
  ) AS mapping(old_section, new_section)
)
WHERE jsonb_typeof(permissions) = 'array';

-- ─── WEBHOOK DELIVERY LOGS: add response_body column ────
ALTER TABLE public.webhook_delivery_logs ADD COLUMN IF NOT EXISTS response_body TEXT;

-- ─── STRIPE COLUMNS: subscriptions & plans ──────────────
ALTER TABLE public.subscriptions ADD COLUMN IF NOT EXISTS stripe_customer_id TEXT;
ALTER TABLE public.subscriptions ADD COLUMN IF NOT EXISTS stripe_subscription_id TEXT;
ALTER TABLE public.subscriptions ADD COLUMN IF NOT EXISTS stripe_price_id TEXT;
ALTER TABLE public.plans ADD COLUMN IF NOT EXISTS stripe_price_id_monthly TEXT;
ALTER TABLE public.plans ADD COLUMN IF NOT EXISTS stripe_price_id_annual TEXT;

-- ─── SUBSCRIPTIONS: deduplicate, then enforce one row per restaurant ──────
DO $$
BEGIN
  IF NOT EXISTS (
    SELECT 1 FROM pg_constraint
    WHERE conname = 'subscriptions_restaurant_id_key'
      AND conrelid = 'public.subscriptions'::regclass
  ) THEN
    DELETE FROM public.subscriptions s
    WHERE id NOT IN (
      SELECT DISTINCT ON (restaurant_id) id
      FROM public.subscriptions
      ORDER BY restaurant_id, created_at DESC NULLS LAST
    );
    ALTER TABLE public.subscriptions ADD CONSTRAINT subscriptions_restaurant_id_key UNIQUE (restaurant_id);
  END IF;
END $$;
INSERT INTO public.subscriptions (restaurant_id)
SELECT r.id FROM public.restaurants r
WHERE NOT EXISTS (SELECT 1 FROM public.subscriptions s WHERE s.restaurant_id = r.id)
ON CONFLICT DO NOTHING;

-- ─── ALERT SETTINGS TABLE ────────────────────────────────
CREATE TABLE IF NOT EXISTS public.alert_settings (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  restaurant_id UUID NOT NULL REFERENCES public.restaurants(id) ON DELETE CASCADE,
  sound_enabled BOOLEAN NOT NULL DEFAULT true,
  volume INTEGER NOT NULL DEFAULT 70,
  auto_dismiss INTEGER NOT NULL DEFAULT 30,
  show_orders BOOLEAN NOT NULL DEFAULT true,
  show_bookings BOOLEAN NOT NULL DEFAULT true,
  show_ai_escalations BOOLEAN NOT NULL DEFAULT true,
  browser_notifications BOOLEAN NOT NULL DEFAULT false,
  created_at TIMESTAMPTZ DEFAULT now(),
  updated_at TIMESTAMPTZ DEFAULT now(),
  CONSTRAINT alert_settings_restaurant_unique UNIQUE (restaurant_id)
);
CREATE INDEX IF NOT EXISTS idx_alert_settings_restaurant_id ON public.alert_settings(restaurant_id);

-- Seed default system roles for every restaurant (idempotent via ON CONFLICT / NOT EXISTS)
DO $$
DECLARE
  r RECORD;
  owner_perms JSONB;
  manager_perms JSONB;
  supervisor_perms JSONB;
  waiter_perms JSONB;
  host_perms JSONB;
  kitchen_perms JSONB;
BEGIN
  owner_perms := '{"dashboard":{"create":true,"read":true,"update":true,"delete":true},"orders":{"create":true,"read":true,"update":true,"delete":true},"reservations":{"create":true,"read":true,"update":true,"delete":true},"ai_config":{"create":true,"read":true,"update":true,"delete":true},"knowledge_base":{"create":true,"read":true,"update":true,"delete":true},"chat_widget":{"create":true,"read":true,"update":true,"delete":true},"conversations":{"create":true,"read":true,"update":true,"delete":true},"telephone":{"create":true,"read":true,"update":true,"delete":true},"whatsapp":{"create":true,"read":true,"update":true,"delete":true},"menu":{"create":true,"read":true,"update":true,"delete":true},"customers":{"create":true,"read":true,"update":true,"delete":true},"loyalty":{"create":true,"read":true,"update":true,"delete":true},"storefront":{"create":true,"read":true,"update":true,"delete":true},"marketing":{"create":true,"read":true,"update":true,"delete":true},"gift_cards":{"create":true,"read":true,"update":true,"delete":true},"coupons":{"create":true,"read":true,"update":true,"delete":true},"staff":{"create":true,"read":true,"update":true,"delete":true},"branches":{"create":true,"read":true,"update":true,"delete":true},"analytics":{"create":true,"read":true,"update":true,"delete":true},"settings":{"create":true,"read":true,"update":true,"delete":true}}'::jsonb;
  manager_perms := '{"dashboard":{"create":false,"read":true,"update":false,"delete":false},"orders":{"create":true,"read":true,"update":true,"delete":true},"reservations":{"create":true,"read":true,"update":true,"delete":true},"ai_config":{"create":true,"read":true,"update":true,"delete":true},"knowledge_base":{"create":true,"read":true,"update":true,"delete":true},"chat_widget":{"create":false,"read":true,"update":true,"delete":false},"conversations":{"create":false,"read":true,"update":true,"delete":false},"telephone":{"create":false,"read":true,"update":true,"delete":false},"whatsapp":{"create":false,"read":true,"update":true,"delete":false},"menu":{"create":true,"read":true,"update":true,"delete":false},"customers":{"create":true,"read":true,"update":true,"delete":false},"loyalty":{"create":true,"read":true,"update":true,"delete":true},"storefront":{"create":false,"read":true,"update":true,"delete":false},"marketing":{"create":true,"read":true,"update":true,"delete":true},"gift_cards":{"create":true,"read":true,"update":true,"delete":true},"coupons":{"create":true,"read":true,"update":true,"delete":true},"staff":{"create":true,"read":true,"update":true,"delete":false},"branches":{"create":false,"read":true,"update":false,"delete":false},"analytics":{"create":false,"read":true,"update":false,"delete":false},"settings":{"create":false,"read":true,"update":true,"delete":false}}'::jsonb;
  supervisor_perms := '{"dashboard":{"create":false,"read":true,"update":false,"delete":false},"orders":{"create":true,"read":true,"update":true,"delete":false},"reservations":{"create":true,"read":true,"update":true,"delete":false},"ai_config":{"create":false,"read":true,"update":false,"delete":false},"knowledge_base":{"create":false,"read":true,"update":false,"delete":false},"chat_widget":{"create":false,"read":true,"update":false,"delete":false},"conversations":{"create":false,"read":true,"update":false,"delete":false},"telephone":{"create":false,"read":true,"update":false,"delete":false},"whatsapp":{"create":false,"read":true,"update":false,"delete":false},"menu":{"create":false,"read":true,"update":false,"delete":false},"customers":{"create":false,"read":true,"update":false,"delete":false},"loyalty":{"create":false,"read":true,"update":false,"delete":false},"storefront":{"create":false,"read":true,"update":false,"delete":false},"marketing":{"create":false,"read":true,"update":false,"delete":false},"gift_cards":{"create":false,"read":true,"update":false,"delete":false},"coupons":{"create":false,"read":true,"update":false,"delete":false},"staff":{"create":false,"read":true,"update":false,"delete":false},"branches":{"create":false,"read":true,"update":false,"delete":false},"analytics":{"create":false,"read":true,"update":false,"delete":false},"settings":{"create":false,"read":false,"update":false,"delete":false}}'::jsonb;
  waiter_perms := '{"dashboard":{"create":false,"read":true,"update":false,"delete":false},"orders":{"create":true,"read":true,"update":true,"delete":false},"reservations":{"create":false,"read":true,"update":false,"delete":false},"ai_config":{"create":false,"read":false,"update":false,"delete":false},"knowledge_base":{"create":false,"read":false,"update":false,"delete":false},"chat_widget":{"create":false,"read":false,"update":false,"delete":false},"conversations":{"create":false,"read":false,"update":false,"delete":false},"telephone":{"create":false,"read":false,"update":false,"delete":false},"whatsapp":{"create":false,"read":false,"update":false,"delete":false},"menu":{"create":false,"read":true,"update":false,"delete":false},"customers":{"create":false,"read":true,"update":false,"delete":false},"loyalty":{"create":false,"read":false,"update":false,"delete":false},"storefront":{"create":false,"read":false,"update":false,"delete":false},"marketing":{"create":false,"read":false,"update":false,"delete":false},"gift_cards":{"create":false,"read":false,"update":false,"delete":false},"coupons":{"create":false,"read":false,"update":false,"delete":false},"staff":{"create":false,"read":false,"update":false,"delete":false},"branches":{"create":false,"read":false,"update":false,"delete":false},"analytics":{"create":false,"read":false,"update":false,"delete":false},"settings":{"create":false,"read":false,"update":false,"delete":false}}'::jsonb;
  host_perms := '{"dashboard":{"create":false,"read":true,"update":false,"delete":false},"orders":{"create":false,"read":true,"update":false,"delete":false},"reservations":{"create":true,"read":true,"update":true,"delete":false},"ai_config":{"create":false,"read":false,"update":false,"delete":false},"knowledge_base":{"create":false,"read":false,"update":false,"delete":false},"chat_widget":{"create":false,"read":false,"update":false,"delete":false},"conversations":{"create":false,"read":false,"update":false,"delete":false},"telephone":{"create":false,"read":false,"update":false,"delete":false},"whatsapp":{"create":false,"read":false,"update":false,"delete":false},"menu":{"create":false,"read":true,"update":false,"delete":false},"customers":{"create":true,"read":true,"update":false,"delete":false},"loyalty":{"create":false,"read":true,"update":false,"delete":false},"storefront":{"create":false,"read":false,"update":false,"delete":false},"marketing":{"create":false,"read":false,"update":false,"delete":false},"gift_cards":{"create":false,"read":false,"update":false,"delete":false},"coupons":{"create":false,"read":false,"update":false,"delete":false},"staff":{"create":false,"read":false,"update":false,"delete":false},"branches":{"create":false,"read":false,"update":false,"delete":false},"analytics":{"create":false,"read":false,"update":false,"delete":false},"settings":{"create":false,"read":false,"update":false,"delete":false}}'::jsonb;
  kitchen_perms := '{"dashboard":{"create":false,"read":true,"update":false,"delete":false},"orders":{"create":false,"read":true,"update":true,"delete":false},"reservations":{"create":false,"read":false,"update":false,"delete":false},"ai_config":{"create":false,"read":false,"update":false,"delete":false},"knowledge_base":{"create":false,"read":false,"update":false,"delete":false},"chat_widget":{"create":false,"read":false,"update":false,"delete":false},"conversations":{"create":false,"read":false,"update":false,"delete":false},"telephone":{"create":false,"read":false,"update":false,"delete":false},"whatsapp":{"create":false,"read":false,"update":false,"delete":false},"menu":{"create":false,"read":true,"update":false,"delete":false},"customers":{"create":false,"read":false,"update":false,"delete":false},"loyalty":{"create":false,"read":false,"update":false,"delete":false},"storefront":{"create":false,"read":false,"update":false,"delete":false},"marketing":{"create":false,"read":false,"update":false,"delete":false},"gift_cards":{"create":false,"read":false,"update":false,"delete":false},"coupons":{"create":false,"read":false,"update":false,"delete":false},"staff":{"create":false,"read":false,"update":false,"delete":false},"branches":{"create":false,"read":false,"update":false,"delete":false},"analytics":{"create":false,"read":false,"update":false,"delete":false},"settings":{"create":false,"read":false,"update":false,"delete":false}}'::jsonb;

  FOR r IN SELECT id FROM public.restaurants LOOP
    INSERT INTO public.roles (restaurant_id, name, description, permissions, is_system)
    VALUES
      (r.id, 'Owner',         'Full access to all sections',                    owner_perms,      true),
      (r.id, 'Manager',       'Manage operations, staff and most settings',      manager_perms,    true),
      (r.id, 'Supervisor',    'Oversee daily operations and staff',              supervisor_perms, true),
      (r.id, 'Waiter',        'Handle orders and view menus',                   waiter_perms,     true),
      (r.id, 'Host',          'Manage reservations and greet customers',         host_perms,       true),
      (r.id, 'Kitchen Staff', 'View and update kitchen orders',                  kitchen_perms,    true)
    ON CONFLICT DO NOTHING;
  END LOOP;
END $$;

-- ─── ROLES: backfill 11 new permission sections (idempotent) ─────────────────
-- Merges new sections (all false) into existing roles/staff that predate this migration.
-- The WHERE NOT clause on permissions ? 'ai_config' guard ensures idempotency.

UPDATE public.roles
SET permissions = permissions || '{"ai_config":{"create":false,"read":false,"update":false,"delete":false},"knowledge_base":{"create":false,"read":false,"update":false,"delete":false},"chat_widget":{"create":false,"read":false,"update":false,"delete":false},"telephone":{"create":false,"read":false,"update":false,"delete":false},"whatsapp":{"create":false,"read":false,"update":false,"delete":false},"loyalty":{"create":false,"read":false,"update":false,"delete":false},"storefront":{"create":false,"read":false,"update":false,"delete":false},"marketing":{"create":false,"read":false,"update":false,"delete":false},"gift_cards":{"create":false,"read":false,"update":false,"delete":false},"coupons":{"create":false,"read":false,"update":false,"delete":false},"branches":{"create":false,"read":false,"update":false,"delete":false}}'::jsonb
WHERE jsonb_typeof(permissions) = 'object' AND NOT (permissions ? 'ai_config');

UPDATE public.staff
SET permissions = permissions || '{"ai_config":{"create":false,"read":false,"update":false,"delete":false},"knowledge_base":{"create":false,"read":false,"update":false,"delete":false},"chat_widget":{"create":false,"read":false,"update":false,"delete":false},"telephone":{"create":false,"read":false,"update":false,"delete":false},"whatsapp":{"create":false,"read":false,"update":false,"delete":false},"loyalty":{"create":false,"read":false,"update":false,"delete":false},"storefront":{"create":false,"read":false,"update":false,"delete":false},"marketing":{"create":false,"read":false,"update":false,"delete":false},"gift_cards":{"create":false,"read":false,"update":false,"delete":false},"coupons":{"create":false,"read":false,"update":false,"delete":false},"branches":{"create":false,"read":false,"update":false,"delete":false}}'::jsonb
WHERE jsonb_typeof(permissions) = 'object' AND NOT (permissions ? 'ai_config');

-- Apply correct per-role defaults for system roles (run every startup; idempotent via jsonb ||)
UPDATE public.roles
SET permissions = permissions || '{"ai_config":{"create":true,"read":true,"update":true,"delete":true},"knowledge_base":{"create":true,"read":true,"update":true,"delete":true},"chat_widget":{"create":true,"read":true,"update":true,"delete":true},"telephone":{"create":true,"read":true,"update":true,"delete":true},"whatsapp":{"create":true,"read":true,"update":true,"delete":true},"loyalty":{"create":true,"read":true,"update":true,"delete":true},"storefront":{"create":true,"read":true,"update":true,"delete":true},"marketing":{"create":true,"read":true,"update":true,"delete":true},"gift_cards":{"create":true,"read":true,"update":true,"delete":true},"coupons":{"create":true,"read":true,"update":true,"delete":true},"branches":{"create":true,"read":true,"update":true,"delete":true}}'::jsonb
WHERE is_system = true AND name = 'Owner';

UPDATE public.roles
SET permissions = permissions || '{"ai_config":{"create":true,"read":true,"update":true,"delete":true},"knowledge_base":{"create":true,"read":true,"update":true,"delete":true},"chat_widget":{"create":false,"read":true,"update":true,"delete":false},"telephone":{"create":false,"read":true,"update":true,"delete":false},"whatsapp":{"create":false,"read":true,"update":true,"delete":false},"loyalty":{"create":true,"read":true,"update":true,"delete":true},"storefront":{"create":false,"read":true,"update":true,"delete":false},"marketing":{"create":true,"read":true,"update":true,"delete":true},"gift_cards":{"create":true,"read":true,"update":true,"delete":true},"coupons":{"create":true,"read":true,"update":true,"delete":true},"branches":{"create":false,"read":true,"update":false,"delete":false}}'::jsonb
WHERE is_system = true AND name = 'Manager';

UPDATE public.roles
SET permissions = permissions || '{"ai_config":{"create":false,"read":true,"update":false,"delete":false},"knowledge_base":{"create":false,"read":true,"update":false,"delete":false},"chat_widget":{"create":false,"read":true,"update":false,"delete":false},"telephone":{"create":false,"read":true,"update":false,"delete":false},"whatsapp":{"create":false,"read":true,"update":false,"delete":false},"loyalty":{"create":false,"read":true,"update":false,"delete":false},"storefront":{"create":false,"read":true,"update":false,"delete":false},"marketing":{"create":false,"read":true,"update":false,"delete":false},"gift_cards":{"create":false,"read":true,"update":false,"delete":false},"coupons":{"create":false,"read":true,"update":false,"delete":false},"branches":{"create":false,"read":true,"update":false,"delete":false}}'::jsonb
WHERE is_system = true AND name = 'Supervisor';

-- Waiter, Host, Kitchen Staff: new sections already defaulted to false by the generic backfill.

-- Unique index on call_sid so ON CONFLICT works for Twilio webhook upserts
CREATE UNIQUE INDEX IF NOT EXISTS idx_call_logs_call_sid ON public.call_logs(call_sid);

-- Backfill call_logs from sip_call_sessions (one-time, idempotent)
-- Ensures historical Twilio calls appear in the Conversations → Call Logs UI
INSERT INTO public.call_logs (
  restaurant_id, call_sid, direction, from_number, to_number,
  status, duration_seconds, recording_url,
  ai_handled, escalated_to_human, started_at, ended_at, created_at, updated_at
)
SELECT
  cs.restaurant_id,
  cs.sip_call_id,
  cs.direction,
  cs.caller_number,
  cs.callee_number,
  cs.status,
  COALESCE(cs.duration_seconds, 0),
  cs.recording_url,
  NOT COALESCE(cs.escalated_to_human, false),
  COALESCE(cs.escalated_to_human, false),
  cs.started_at,
  cs.ended_at,
  cs.started_at,
  COALESCE(cs.ended_at, cs.started_at)
FROM public.sip_call_sessions cs
WHERE cs.sip_call_id IS NOT NULL
  AND NOT EXISTS (
    SELECT 1 FROM public.call_logs cl WHERE cl.call_sid = cs.sip_call_id
  );

-- ─── RESTAURANT CURRENCY COLUMN ────────────────────────────
ALTER TABLE public.restaurants ADD COLUMN IF NOT EXISTS cuisine_type TEXT;
ALTER TABLE public.restaurants ADD COLUMN IF NOT EXISTS phone TEXT;
ALTER TABLE public.restaurants ADD COLUMN IF NOT EXISTS address TEXT;
ALTER TABLE public.restaurants ADD COLUMN IF NOT EXISTS description TEXT;
ALTER TABLE public.restaurants ADD COLUMN IF NOT EXISTS seating_capacity INTEGER;
ALTER TABLE public.restaurants ADD COLUMN IF NOT EXISTS currency TEXT DEFAULT 'USD';
ALTER TABLE public.restaurants ADD COLUMN IF NOT EXISTS currency_set_at TIMESTAMPTZ;
ALTER TABLE public.restaurants ADD COLUMN IF NOT EXISTS currency_locked BOOLEAN DEFAULT false;

-- ─── SUBSCRIPTION TRIAL COLUMNS ─────────────────────────────
ALTER TABLE public.subscriptions ADD COLUMN IF NOT EXISTS trial_start TIMESTAMPTZ;
ALTER TABLE public.subscriptions ADD COLUMN IF NOT EXISTS trial_end TIMESTAMPTZ;

-- Task #309: Backfill legacy trial rows that were created before trial_end
-- was reliably populated. Without this, the gate (which now treats
-- status='trial' AND trial_end IS NULL as expired) would immediately lock
-- those operators out. We give them the same 14-day window measured from
-- their original created_at, which matches the default plans.trial_days.
UPDATE public.subscriptions
   SET trial_end = COALESCE(created_at, NOW()) + INTERVAL '14 days'
 WHERE status = 'trial'
   AND trial_end IS NULL;

-- Mirror the backfill onto trial_start so reporting stays consistent.
UPDATE public.subscriptions
   SET trial_start = COALESCE(created_at, NOW())
 WHERE status = 'trial'
   AND trial_start IS NULL;

-- Enforce the invariant going forward: a row in 'trial' status must carry
-- a trial_end. This closes the bypass class entirely instead of relying on
-- the gate's defensive check. Wrapped in a DO block so re-runs are no-ops.
DO $$
BEGIN
  IF NOT EXISTS (
    SELECT 1 FROM pg_constraint
     WHERE conname = 'subscriptions_trial_end_required'
  ) THEN
    ALTER TABLE public.subscriptions
      ADD CONSTRAINT subscriptions_trial_end_required
      CHECK (status <> 'trial' OR trial_end IS NOT NULL) NOT VALID;
    -- Validate separately so a single bad row surfaces clearly without
    -- aborting the rest of MIGRATION_SQL on legacy databases.
    BEGIN
      ALTER TABLE public.subscriptions
        VALIDATE CONSTRAINT subscriptions_trial_end_required;
    EXCEPTION WHEN check_violation THEN
      RAISE WARNING 'subscriptions_trial_end_required has unvalidated rows; backfill incomplete';
    END;
  END IF;
END $$;

-- ─── PLATFORM BRANDING DEFAULTS ──────────────────────────────
INSERT INTO public.platform_settings (key, value) VALUES
  ('site_logo_url',      '""'::jsonb),
  ('site_favicon_url',   '""'::jsonb),
  ('site_primary_color', '"#f97316"'::jsonb),
  ('site_font_family',   '"Inter"'::jsonb)
ON CONFLICT (key) DO NOTHING;

-- ─── SHORT DISPLAY ID ────────────────────────────────────────
ALTER TABLE public.restaurants ADD COLUMN IF NOT EXISTS display_id TEXT;
CREATE UNIQUE INDEX IF NOT EXISTS idx_restaurants_display_id ON public.restaurants(display_id);

-- Backfill existing rows using the same random charset as new inserts
DO $$
DECLARE
  rec    RECORD;
  chars  TEXT := 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789';
  new_id TEXT;
  cnt    INTEGER;
BEGIN
  FOR rec IN SELECT id FROM restaurants WHERE display_id IS NULL LOOP
    LOOP
      new_id := 'RST-';
      FOR i IN 1..7 LOOP
        new_id := new_id || substr(chars, (floor(random() * length(chars))::integer) + 1, 1);
      END LOOP;
      SELECT COUNT(*) INTO cnt FROM restaurants WHERE display_id = new_id;
      EXIT WHEN cnt = 0;
    END LOOP;
    UPDATE restaurants SET display_id = new_id WHERE id = rec.id;
  END LOOP;
END;
$$;

-- Trigger: auto-populate display_id on every INSERT (covers all creation paths)
CREATE OR REPLACE FUNCTION restaurants_auto_display_id() RETURNS TRIGGER AS $$
DECLARE
  chars TEXT := 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789';
  new_id TEXT;
  conflicts INTEGER;
BEGIN
  IF NEW.display_id IS NULL OR NEW.display_id = '' THEN
    LOOP
      new_id := 'RST-';
      FOR i IN 1..7 LOOP
        new_id := new_id || substr(chars, (floor(random() * length(chars))::integer) + 1, 1);
      END LOOP;
      SELECT COUNT(*) INTO conflicts FROM restaurants WHERE display_id = new_id;
      EXIT WHEN conflicts = 0;
    END LOOP;
    NEW.display_id := new_id;
  END IF;
  RETURN NEW;
END;
$$ LANGUAGE plpgsql;

DROP TRIGGER IF EXISTS restaurants_set_display_id ON public.restaurants;
CREATE TRIGGER restaurants_set_display_id
  BEFORE INSERT ON public.restaurants
  FOR EACH ROW EXECUTE FUNCTION restaurants_auto_display_id();

-- ─── MULTI-LANGUAGE TABLES (idempotent — CREATE IF NOT EXISTS) ───────────────
CREATE TABLE IF NOT EXISTS public.languages (
  id           UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  code         VARCHAR(16)  NOT NULL UNIQUE,
  name         VARCHAR(64)  NOT NULL,
  native_name  VARCHAR(64)  NOT NULL,
  flag_emoji   VARCHAR(8)   NOT NULL DEFAULT '',
  is_rtl       BOOLEAN      NOT NULL DEFAULT false,
  is_active    BOOLEAN      NOT NULL DEFAULT true,
  is_default   BOOLEAN      NOT NULL DEFAULT false,
  display_order INTEGER     NOT NULL DEFAULT 0,
  created_at   TIMESTAMPTZ  DEFAULT now(),
  updated_at   TIMESTAMPTZ  DEFAULT now()
);
CREATE INDEX IF NOT EXISTS idx_languages_code      ON public.languages(code);
CREATE INDEX IF NOT EXISTS idx_languages_is_active ON public.languages(is_active);

CREATE TABLE IF NOT EXISTS public.translation_keys (
  id            UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  key           VARCHAR(128)  NOT NULL UNIQUE,
  category      VARCHAR(64)   NOT NULL DEFAULT 'general',
  description   TEXT          NOT NULL DEFAULT '',
  default_value TEXT          NOT NULL DEFAULT '',
  created_at    TIMESTAMPTZ   DEFAULT now()
);
CREATE INDEX IF NOT EXISTS idx_translation_keys_key      ON public.translation_keys(key);
CREATE INDEX IF NOT EXISTS idx_translation_keys_category ON public.translation_keys(category);

CREATE TABLE IF NOT EXISTS public.translations (
  id          UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  lang_code   VARCHAR(16)  NOT NULL REFERENCES public.languages(code) ON DELETE CASCADE,
  key_id      UUID         NOT NULL REFERENCES public.translation_keys(id) ON DELETE CASCADE,
  value       TEXT         NOT NULL DEFAULT '',
  updated_at  TIMESTAMPTZ  DEFAULT now(),
  CONSTRAINT  translations_lang_key UNIQUE (lang_code, key_id)
);
CREATE INDEX IF NOT EXISTS idx_translations_lang_code ON public.translations(lang_code);
CREATE INDEX IF NOT EXISTS idx_translations_key_id    ON public.translations(key_id);

-- Add preferred_language to users if not already present
ALTER TABLE public.users ADD COLUMN IF NOT EXISTS preferred_language TEXT DEFAULT 'en';
ALTER TABLE public.users ADD COLUMN IF NOT EXISTS email_verified_at TIMESTAMPTZ;

-- One-shot backfill: clear the known-stale legacy diploy favicon upload
-- so the favicon route falls through to site_logo_url. Targeted to the
-- specific legacy filename so it never overwrites an operator's later choice.
UPDATE public.platform_settings
   SET value = '""'::jsonb, updated_at = now()
 WHERE key = 'site_favicon_url'
   AND value::text LIKE '%favicon-370b766a%';

-- Seed base languages (idempotent)
INSERT INTO public.languages (code, name, native_name, flag_emoji, is_rtl, is_active, is_default, display_order) VALUES
  ('en', 'English',  'English',  '🇬🇧', false, true, true,  0),
  ('hi', 'Hindi',    'हिंदी',    '🇮🇳', false, true, false, 1),
  ('de', 'German',   'Deutsch',  '🇩🇪', false, true, false, 2),
  ('fr', 'French',   'Français', '🇫🇷', false, true, false, 3),
  ('ru', 'Russian',  'Русский',  '🇷🇺', false, true, false, 4),
  ('ar', 'Arabic',   'العربية',  '🇸🇦', true,  true, false, 5)
ON CONFLICT (code) DO NOTHING;

-- ─── TRANSLATION KEY SEED (idempotent — full set, all categories) ───────────
INSERT INTO public.translation_keys (key, category, description, default_value) VALUES
  -- ── common ──
  ('common.save',              'common', 'Save button',           'Save'),
  ('common.cancel',            'common', 'Cancel button',         'Cancel'),
  ('common.delete',            'common', 'Delete button',         'Delete'),
  ('common.edit',              'common', 'Edit button',           'Edit'),
  ('common.add',               'common', 'Add button',            'Add'),
  ('common.create',            'common', 'Create button',         'Create'),
  ('common.update',            'common', 'Update button',         'Update'),
  ('common.confirm',           'common', 'Confirm button',        'Confirm'),
  ('common.close',             'common', 'Close button',          'Close'),
  ('common.back',              'common', 'Back button',           'Back'),
  ('common.next',              'common', 'Next button',           'Next'),
  ('common.search',            'common', 'Search placeholder',    'Search…'),
  ('common.filter',            'common', 'Filter label',          'Filter'),
  ('common.loading',           'common', 'Loading state',         'Loading…'),
  ('common.saving',            'common', 'Saving state',          'Saving…'),
  ('common.error',             'common', 'Generic error',         'Something went wrong. Please try again.'),
  ('common.success',           'common', 'Generic success',       'Changes saved successfully.'),
  ('common.noData',            'common', 'Empty state',           'No data available.'),
  ('common.view',              'common', 'View button',           'View'),
  ('common.manage',            'common', 'Manage button',         'Manage'),
  ('common.required',          'common', 'Required field note',   'Required'),
  ('common.optional',          'common', 'Optional field note',   'Optional'),
  ('common.yes',               'common', 'Yes',                   'Yes'),
  ('common.no',                'common', 'No',                    'No'),
  ('common.active',            'common', 'Active status',         'Active'),
  ('common.inactive',          'common', 'Inactive status',       'Inactive'),
  ('common.enabled',           'common', 'Enabled toggle',        'Enabled'),
  ('common.disabled',          'common', 'Disabled toggle',       'Disabled'),
  ('common.name',              'common', 'Name field',            'Name'),
  ('common.email',             'common', 'Email field',           'Email'),
  ('common.phone',             'common', 'Phone field',           'Phone'),
  ('common.address',           'common', 'Address field',         'Address'),
  ('common.status',            'common', 'Status label',          'Status'),
  ('common.date',              'common', 'Date label',            'Date'),
  ('common.time',              'common', 'Time label',            'Time'),
  ('common.actions',           'common', 'Actions column header', 'Actions'),
  ('common.total',             'common', 'Total label',           'Total'),
  ('common.type',              'common', 'Type label',            'Type'),
  ('common.description',       'common', 'Description label',     'Description'),
  ('common.notes',             'common', 'Notes label',           'Notes'),
  ('common.all',               'common', 'All filter option',     'All'),
  -- ── nav ──
  ('nav.dashboard',            'nav', 'Nav: Dashboard',         'Dashboard'),
  ('nav.orders',               'nav', 'Nav: Orders',            'Orders'),
  ('nav.reservations',         'nav', 'Nav: Reservations',      'Reservations'),
  ('nav.aiConfig',             'nav', 'Nav: AI Configuration',  'AI Configuration'),
  ('nav.knowledgeBase',        'nav', 'Nav: Knowledge Base',    'Knowledge Base'),
  ('nav.menu',                 'nav', 'Nav: Menu Management',   'Menu Management'),
  ('nav.customers',            'nav', 'Nav: Customers',         'Customers'),
  ('nav.staff',                'nav', 'Nav: Staff',             'Staff'),
  ('nav.branches',             'nav', 'Nav: Branches',          'Branch Management'),
  ('nav.conversations',        'nav', 'Nav: Conversations',     'Conversations'),
  ('nav.telephone',            'nav', 'Nav: Telephone',         'Telephone'),
  ('nav.widget',               'nav', 'Nav: Chat Widget',       'Chat Widget'),
  ('nav.analytics',            'nav', 'Nav: Analytics',         'Analytics'),
  ('nav.billing',              'nav', 'Nav: Billing',           'Billing'),
  ('nav.settings',             'nav', 'Nav: Settings',          'Settings'),
  ('nav.help',                 'nav', 'Nav: Help',              'Help'),
  ('nav.adminDashboard',       'nav', 'Nav: Admin Dashboard',   'Dashboard'),
  ('nav.adminRestaurants',     'nav', 'Nav: Admin Restaurants', 'Restaurants'),
  ('nav.adminBilling',         'nav', 'Nav: Admin Billing',     'Billing'),
  ('nav.adminAiSettings',      'nav', 'Nav: Admin AI Settings', 'AI Settings'),
  ('nav.adminAnalytics',       'nav', 'Nav: Admin Analytics',   'Analytics'),
  ('nav.adminSupport',         'nav', 'Nav: Admin Support',     'Support Tools'),
  ('nav.adminBranding',        'nav', 'Nav: Admin Branding',    'Branding'),
  ('nav.adminLanguages',       'nav', 'Nav: Admin Languages',   'Languages'),
  ('nav.signOut',              'nav', 'Sign out link',          'Sign Out'),
  ('nav.changePassword',       'nav', 'Change password link',   'Change Password'),
  -- ── auth ──
  ('auth.signIn',              'auth', 'Sign in heading',        'Welcome back'),
  ('auth.signInSub',           'auth', 'Sign in subheading',     'Sign in to your restaurant dashboard'),
  ('auth.signInBtn',           'auth', 'Sign in button',         'Sign in'),
  ('auth.signingIn',           'auth', 'Signing in state',       'Signing in...'),
  ('auth.signUp',              'auth', 'Sign up heading',        'Create your account'),
  ('auth.signUpSub',           'auth', 'Sign up subheading',     'Start your 14-day free trial — no credit card required'),
  ('auth.signUpBtn',           'auth', 'Sign up button',         'Create Account'),
  ('auth.emailLabel',          'auth', 'Email field label',      'Email address'),
  ('auth.emailPlaceholder',    'auth', 'Email placeholder',      'you@restaurant.com'),
  ('auth.passwordLabel',       'auth', 'Password field label',   'Password'),
  ('auth.passwordPlaceholder', 'auth', 'Password placeholder',   '••••••••'),
  ('auth.forgotPassword',      'auth', 'Forgot password link',   'Forgot password?'),
  ('auth.noAccount',           'auth', 'No account prompt',      'Don''t have an account?'),
  ('auth.createFree',          'auth', 'Create free link',       'Create one free'),
  ('auth.haveAccount',         'auth', 'Have account prompt',    'Already have an account?'),
  ('auth.signInLink',          'auth', 'Sign in link',           'Sign in'),
  ('auth.restaurantName',      'auth', 'Restaurant name field',  'Restaurant Name'),
  ('auth.ownerName',           'auth', 'Owner name field',       'Owner Name'),
  ('auth.emailRequired',       'auth', 'Email required error',   'Email address is required'),
  ('auth.emailInvalid',        'auth', 'Email invalid error',    'Please enter a valid email address'),
  ('auth.passwordRequired',    'auth', 'Password required error', 'Password is required'),
  ('auth.passwordTooShort',    'auth', 'Password too short error', 'Password must be at least 6 characters'),
  -- ── landing ──
  ('landing.heroTitle',        'landing', 'Landing hero title',       'AI-powered restaurant management, simplified.'),
  ('landing.heroSubtitle',     'landing', 'Landing hero subtitle',    'Handle orders, reservations, and customer conversations — all through one intelligent platform.'),
  ('landing.heroCta',          'landing', 'Hero CTA button',          'Get Started Free'),
  ('landing.heroSecondaryCta', 'landing', 'Hero secondary CTA',       'Watch Demo'),
  ('landing.features',         'landing', 'Features section title',   'Everything your restaurant needs'),
  ('landing.featuresSub',      'landing', 'Features section sub',     'From AI voice agents to analytics, we have everything to streamline your restaurant operations.'),
  ('landing.pricing',          'landing', 'Pricing section title',    'Simple, transparent pricing'),
  ('landing.pricingSub',       'landing', 'Pricing section sub',      'Choose the plan that fits your restaurant. Upgrade or downgrade at any time.'),
  ('landing.pricingMonthly',   'landing', 'Monthly billing toggle',   'Monthly'),
  ('landing.pricingAnnual',    'landing', 'Annual billing toggle',    'Annual'),
  ('landing.pricingSave',      'landing', 'Annual savings label',     'Save 20%'),
  ('landing.perMonth',         'landing', 'Per month label',          '/mo'),
  ('landing.startTrial',       'landing', 'Start trial button',       'Start Free Trial'),
  ('landing.contactSales',     'landing', 'Contact sales button',     'Contact Sales'),
  ('landing.navHome',          'landing', 'Nav: Home',                'Home'),
  ('landing.navFeatures',      'landing', 'Nav: Features',            'Features'),
  ('landing.navPricing',       'landing', 'Nav: Pricing',             'Pricing'),
  ('landing.navBlog',          'landing', 'Nav: Blog',                'Blog'),
  ('landing.navAbout',         'landing', 'Nav: About',               'About'),
  ('landing.navContact',       'landing', 'Nav: Contact',             'Contact'),
  ('landing.navLogin',         'landing', 'Nav: Login',               'Sign In'),
  ('landing.navSignup',        'landing', 'Nav: Sign Up',             'Get Started'),
  ('landing.footerTagline',    'landing', 'Footer tagline',           'AI-powered restaurant management, simplified.'),
  ('landing.footerCopyright',  'landing', 'Footer copyright',         'All rights reserved.'),
  -- ── dashboard ──
  ('dashboard.title',          'dashboard', 'Dashboard page title',        'Agent Overview'),
  ('dashboard.subtitle',       'dashboard', 'Dashboard page subtitle',     'Monitor your AI agent performance in real-time'),
  ('dashboard.totalOrders',    'dashboard', 'Total orders metric',         'Total Orders'),
  ('dashboard.aiResolved',     'dashboard', 'AI resolved metric',          'AI Resolved'),
  ('dashboard.activeConversations', 'dashboard', 'Active conversations metric', 'Active Conversations'),
  ('dashboard.avgResponse',    'dashboard', 'Avg response time metric',    'Avg Response Time'),
  ('dashboard.recentOrders',   'dashboard', 'Recent orders section',       'Recent Orders'),
  ('dashboard.upcomingBookings', 'dashboard', 'Upcoming bookings section', 'Upcoming Bookings'),
  ('dashboard.liveConversations', 'dashboard', 'Live conversations section', 'Live Conversations'),
  -- ── orders ──
  ('orders.title',             'orders', 'Orders page title',       'Order Management'),
  ('orders.subtitle',          'orders', 'Orders page subtitle',    'View and manage all incoming orders from your AI agents'),
  ('orders.newOrder',          'orders', 'New order button',        'New Order'),
  ('orders.orderNumber',       'orders', 'Order number column',     'Order #'),
  ('orders.customer',          'orders', 'Customer column',         'Customer'),
  ('orders.items',             'orders', 'Items column',            'Items'),
  ('orders.channel',           'orders', 'Channel column',          'Channel'),
  ('orders.deliveryType',      'orders', 'Delivery type column',    'Delivery Type'),
  ('orders.pending',           'orders', 'Pending status',          'Pending'),
  ('orders.confirmed',         'orders', 'Confirmed status',        'Confirmed'),
  ('orders.kitchen',           'orders', 'Kitchen status',          'In Kitchen'),
  ('orders.ready',             'orders', 'Ready status',            'Ready'),
  ('orders.delivered',         'orders', 'Delivered status',        'Delivered'),
  ('orders.completed',         'orders', 'Completed status',        'Completed'),
  ('orders.cancelled',         'orders', 'Cancelled status',        'Cancelled'),
  ('orders.escalated',         'orders', 'Escalated status',        'Escalated'),
  ('orders.dineIn',            'orders', 'Dine-in label',           'Dine-in'),
  ('orders.takeaway',          'orders', 'Takeaway label',          'Takeaway'),
  ('orders.delivery',          'orders', 'Delivery label',          'Delivery'),
  ('orders.emptyState',        'orders', 'Orders empty state',      'No orders yet. Orders placed through your AI agent will appear here.'),
  -- ── bookings ──
  ('bookings.title',           'bookings', 'Bookings page title',     'Reservation Management'),
  ('bookings.subtitle',        'bookings', 'Bookings page subtitle',  'Manage all table reservations and bookings'),
  ('bookings.newBooking',      'bookings', 'New booking button',      'New Reservation'),
  ('bookings.guestName',       'bookings', 'Guest name column',       'Guest'),
  ('bookings.partySize',       'bookings', 'Party size column',       'Party Size'),
  ('bookings.date',            'bookings', 'Date column',             'Date'),
  ('bookings.time',            'bookings', 'Time column',             'Time'),
  ('bookings.table',           'bookings', 'Table column',            'Table'),
  ('bookings.occasion',        'bookings', 'Occasion label',          'Occasion'),
  ('bookings.pending',         'bookings', 'Pending status',          'Pending'),
  ('bookings.confirmed',       'bookings', 'Confirmed status',        'Confirmed'),
  ('bookings.seated',          'bookings', 'Seated status',           'Seated'),
  ('bookings.completed',       'bookings', 'Completed status',        'Completed'),
  ('bookings.cancelled',       'bookings', 'Cancelled status',        'Cancelled'),
  ('bookings.noShow',          'bookings', 'No show status',          'No Show'),
  ('bookings.emptyState',      'bookings', 'Bookings empty state',    'No upcoming reservations. Bookings made through your AI agent will appear here.'),
  -- ── agent ──
  ('agent.title',              'agent', 'AI config page title',    'AI Configuration'),
  ('agent.subtitle',           'agent', 'AI config page subtitle', 'Configure your AI voice and chat agents'),
  ('agent.voiceAgent',         'agent', 'Voice agent label',       'Voice Agent'),
  ('agent.chatAgent',          'agent', 'Chat agent label',        'Chat Agent'),
  ('agent.systemPrompt',       'agent', 'System prompt label',     'System Prompt'),
  ('agent.greeting',           'agent', 'Greeting script label',   'Greeting Script'),
  ('agent.model',              'agent', 'AI model label',          'AI Model'),
  ('agent.voiceModel',         'agent', 'Voice model label',       'Voice Model'),
  ('agent.capabilities',       'agent', 'Capabilities label',      'Capabilities'),
  ('agent.fallback',           'agent', 'Fallback rules label',    'Fallback Rules'),
  ('agent.saveChanges',        'agent', 'Save changes button',     'Save Changes'),
  -- ── menu ──
  ('menu.title',               'menu', 'Menu page title',          'Menu Management'),
  ('menu.subtitle',            'menu', 'Menu page subtitle',       'Manage your restaurant menu items and categories'),
  ('menu.addItem',             'menu', 'Add item button',          'Add Item'),
  ('menu.addCategory',         'menu', 'Add category button',      'Add Category'),
  ('menu.itemName',            'menu', 'Item name field',          'Item Name'),
  ('menu.itemPrice',           'menu', 'Item price field',         'Price'),
  ('menu.itemDescription',     'menu', 'Item description field',   'Description'),
  ('menu.category',            'menu', 'Category label',           'Category'),
  ('menu.available',           'menu', 'Available toggle',         'Available'),
  ('menu.dietary',             'menu', 'Dietary tags label',       'Dietary Tags'),
  ('menu.emptyState',          'menu', 'Menu empty state',         'No menu items yet. Add your first item to get started.'),
  -- ── customers ──
  ('customers.title',          'customers', 'Customers page title',   'Customer CRM'),
  ('customers.subtitle',       'customers', 'Customers page subtitle', 'Manage your customer database and relationships'),
  ('customers.addCustomer',    'customers', 'Add customer button',     'Add Customer'),
  ('customers.totalVisits',    'customers', 'Total visits column',     'Total Visits'),
  ('customers.totalSpend',     'customers', 'Total spend column',      'Total Spend'),
  ('customers.tier',           'customers', 'Tier column',             'Tier'),
  ('customers.lastVisit',      'customers', 'Last visit column',       'Last Visit'),
  ('customers.preferences',    'customers', 'Preferences label',       'Preferences'),
  ('customers.emptyState',     'customers', 'Customers empty state',   'No customers yet. Customer data is collected automatically from orders and bookings.'),
  -- ── staff ──
  ('staff.title',              'staff', 'Staff page title',       'Staff Management'),
  ('staff.subtitle',           'staff', 'Staff page subtitle',    'Manage your team members and their permissions'),
  ('staff.addMember',          'staff', 'Add member button',      'Add Member'),
  ('staff.role',               'staff', 'Role column',             'Role'),
  ('staff.branch',             'staff', 'Branch column',           'Branch'),
  ('staff.lastActive',         'staff', 'Last active column',      'Last Active'),
  ('staff.permissions',        'staff', 'Permissions label',       'Permissions'),
  ('staff.emptyState',         'staff', 'Staff empty state',       'No staff members yet. Add your first team member to get started.'),
  -- ── settings ──
  ('settings.title',           'settings', 'Settings page title',   'Restaurant Settings'),
  ('settings.subtitle',        'settings', 'Settings page subtitle', 'Manage your restaurant profile, preferences, and configuration'),
  ('settings.profile',         'settings', 'Profile section',        'Restaurant Profile'),
  ('settings.contactInfo',     'settings', 'Contact info section',   'Contact Information'),
  ('settings.operatingHours',  'settings', 'Operating hours section', 'Operating Hours'),
  ('settings.currency',        'settings', 'Currency setting',        'Currency'),
  ('settings.timezone',        'settings', 'Timezone setting',        'Timezone'),
  ('settings.language',        'settings', 'Language setting',        'Interface Language'),
  ('settings.saveProfile',     'settings', 'Save profile button',     'Save Profile'),
  -- ── admin ──
  ('admin.dashboardTitle',     'admin', 'Admin dashboard title',        'Platform Dashboard'),
  ('admin.dashboardSub',       'admin', 'Admin dashboard subtitle',     'Monitor your platform at a glance'),
  ('admin.totalRestaurants',   'admin', 'Total restaurants metric',     'Total Restaurants'),
  ('admin.activeRestaurants',  'admin', 'Active restaurants metric',    'Active Restaurants'),
  ('admin.totalRevenue',       'admin', 'Total revenue metric',         'Total Revenue'),
  ('admin.restaurantsTitle',   'admin', 'Restaurants page title',       'Restaurants'),
  ('admin.restaurantsSub',     'admin', 'Restaurants page subtitle',    'Manage all restaurant tenants on the platform'),
  ('admin.billingTitle',       'admin', 'Billing page title',           'Billing & Plans'),
  ('admin.billingSub',         'admin', 'Billing page subtitle',        'Manage subscription plans and billing'),
  ('admin.aiSettingsTitle',    'admin', 'AI settings page title',       'AI Settings'),
  ('admin.aiSettingsSub',      'admin', 'AI settings page subtitle',    'Configure global AI providers and models'),
  ('admin.analyticsTitle',     'admin', 'Analytics page title',         'Platform Analytics'),
  ('admin.analyticsSub',       'admin', 'Analytics page subtitle',      'Monitor platform-wide usage and performance'),
  ('admin.supportTitle',       'admin', 'Support page title',           'Support Tools'),
  ('admin.supportSub',         'admin', 'Support page subtitle',        'Manage support tickets and assist restaurant owners'),
  ('admin.brandingTitle',      'admin', 'Branding page title',          'Branding'),
  ('admin.brandingSub',        'admin', 'Branding page subtitle',       'Customize platform identity, colors, and typography'),
  -- ── lang (admin languages UI) ──
  ('lang.title',               'admin', 'Languages page title',         'Languages'),
  ('lang.subtitle',            'admin', 'Languages page subtitle',      'Manage platform languages and translations'),
  ('lang.addLanguage',         'admin', 'Add language button',          'Add Language'),
  ('lang.editLanguage',        'admin', 'Edit language button',         'Edit Language'),
  ('lang.deleteLanguage',      'admin', 'Delete language button',       'Delete Language'),
  ('lang.editTranslations',    'admin', 'Edit translations button',     'Edit Translations'),
  ('lang.code',                'admin', 'Language code field',          'Language Code'),
  ('lang.name',                'admin', 'Language name field',          'Language Name'),
  ('lang.nativeName',          'admin', 'Native name field',            'Native Name'),
  ('lang.flagEmoji',           'admin', 'Flag emoji field',             'Flag Emoji'),
  ('lang.isRtl',               'admin', 'RTL toggle',                   'Right-to-Left (RTL)'),
  ('lang.isDefault',           'admin', 'Default language toggle',      'Default Language'),
  ('lang.copyFrom',            'admin', 'Copy translations from',       'Copy translations from'),
  ('lang.translationsFor',     'admin', 'Translations for language',    'Translations for'),
  ('lang.key',                 'admin', 'Translation key column',       'Key'),
  ('lang.category',            'admin', 'Category column',              'Category'),
  ('lang.defaultValue',        'admin', 'Default value column',         'Default (English)'),
  ('lang.translation',         'admin', 'Translation column',           'Translation'),
  ('lang.allCategories',       'admin', 'All categories filter',        'All Categories'),
  ('lang.saveTranslations',    'admin', 'Save translations button',     'Save Translations'),
  ('lang.deleteConfirm',       'admin', 'Delete language confirm',      'Are you sure you want to delete this language? All its translations will be permanently removed.'),
  ('lang.cannotDeleteDefault', 'admin', 'Cannot delete default error',  'Cannot delete the default language. Set another language as default first.'),
  ('lang.setAsDefault',        'admin', 'Set as default button',        'Set as Default'),
  ('lang.rtlBadge',            'admin', 'RTL badge label',              'RTL'),
  ('lang.defaultBadge',        'admin', 'Default badge label',          'Default'),
  -- ── widget ──
  ('widget.title',             'widget', 'Widget title',                'Chat with Us'),
  ('widget.subtitle',          'widget', 'Widget subtitle',             'We usually reply instantly'),
  ('widget.placeholder',       'widget', 'Input placeholder',           'Type a message...'),
  ('widget.send',              'widget', 'Send button',                 'Send'),
  ('widget.startChat',         'widget', 'Start chat button',           'Start Chat'),
  ('widget.endChat',           'widget', 'End chat button',             'End Chat'),
  ('widget.online',            'widget', 'Online status label',         'Online'),
  ('widget.offline',           'widget', 'Offline status label',        'Offline'),
  ('widget.typing',            'widget', 'Typing indicator',            'Typing...'),
  ('widget.welcomeMessage',    'widget', 'Welcome message',             'Hi there! How can I help you today?'),
  ('widget.errorMessage',      'widget', 'Error message',               'Something went wrong. Please try again.'),
  ('widget.nameLabel',         'widget', 'Name field label',            'Your Name'),
  ('widget.namePlaceholder',   'widget', 'Name field placeholder',      'Enter your name'),
  ('widget.emailLabel',        'widget', 'Email field label',           'Your Email'),
  ('widget.emailPlaceholder',  'widget', 'Email field placeholder',     'Enter your email'),
  ('widget.phoneLabel',        'widget', 'Phone field label',           'Your Phone'),
  ('widget.phonePlaceholder',  'widget', 'Phone field placeholder',     'Enter your phone number'),
  ('widget.startConversation', 'widget', 'Start conversation button',   'Start Conversation'),
  ('widget.poweredBy',         'widget', 'Powered by label',            'Powered by RestroAgent'),
  ('widget.minimize',          'widget', 'Minimize button tooltip',     'Minimize'),
  ('widget.close',             'widget', 'Close button tooltip',        'Close'),
  ('widget.newMessage',        'widget', 'New message label',           'New message'),
  ('widget.connected',         'widget', 'Connected status',            'Connected'),
  ('widget.reconnecting',      'widget', 'Reconnecting status',         'Reconnecting...'),
  ('widget.disconnected',      'widget', 'Disconnected status',         'Disconnected'),
  ('widget.voiceCall',         'widget', 'Voice call button',           'Call Us'),
  ('widget.endCall',           'widget', 'End call button',             'End Call'),
  ('widget.mute',              'widget', 'Mute button',                 'Mute'),
  ('widget.unmute',            'widget', 'Unmute button',               'Unmute'),
  ('widget.callConnected',     'widget', 'Call connected status',       'Call connected'),
  ('widget.callEnded',         'widget', 'Call ended status',           'Call ended'),
  ('analytics.title',          'analytics', 'Analytics page title',      'Analytics'),
  ('analytics.overview',       'analytics', 'Overview tab',              'Overview'),
  ('analytics.conversations',  'analytics', 'Conversations tab',         'Conversations'),
  ('analytics.voiceCalls',     'analytics', 'Voice calls tab',           'Voice Calls'),
  ('analytics.bookings',       'analytics', 'Bookings tab',              'Bookings'),
  ('analytics.orders',         'analytics', 'Orders tab',                'Orders'),
  ('analytics.totalChats',     'analytics', 'Total chats metric',        'Total Chats'),
  ('analytics.totalCalls',     'analytics', 'Total calls metric',        'Total Calls'),
  ('analytics.totalBookings',  'analytics', 'Total bookings metric',     'Total Bookings'),
  ('analytics.totalOrders',    'analytics', 'Total orders metric',       'Total Orders'),
  ('analytics.avgDuration',    'analytics', 'Avg call duration metric',  'Avg Call Duration'),
  ('analytics.resolutionRate', 'analytics', 'Resolution rate metric',    'Resolution Rate'),
  ('analytics.satisfaction',   'analytics', 'Customer satisfaction',     'Customer Satisfaction'),
  ('analytics.period',         'analytics', 'Time period selector',      'Time Period'),
  ('analytics.last7days',      'analytics', '7 days period',             'Last 7 Days'),
  ('analytics.last30days',     'analytics', '30 days period',            'Last 30 Days'),
  ('analytics.last90days',     'analytics', '90 days period',            'Last 90 Days'),
  ('analytics.custom',         'analytics', 'Custom period',             'Custom Range'),
  ('analytics.export',         'analytics', 'Export button',             'Export'),
  ('analytics.noData',         'analytics', 'No data message',           'No data for this period'),
  ('analytics.trend',          'analytics', 'Trend label',               'vs previous period'),
  ('analytics.peakHours',      'analytics', 'Peak hours label',          'Peak Hours'),
  ('analytics.topIntents',     'analytics', 'Top intents label',         'Top Intents'),
  ('analytics.channelBreakdown','analytics','Channel breakdown label',   'Channel Breakdown'),
  ('analytics.chat',           'analytics', 'Chat channel label',        'Chat'),
  ('analytics.voice',          'analytics', 'Voice channel label',       'Voice'),
  ('analytics.avgMessages',    'analytics', 'Avg messages per chat',     'Avg Messages/Chat'),
  ('analytics.handoffRate',    'analytics', 'Human handoff rate',        'Human Handoff Rate'),
  ('billing.title',            'billing', 'Billing page title',          'Billing & Subscription'),
  ('billing.currentPlan',      'billing', 'Current plan label',          'Current Plan'),
  ('billing.upgrade',          'billing', 'Upgrade button',              'Upgrade Plan'),
  ('billing.downgrade',        'billing', 'Downgrade button',            'Downgrade'),
  ('billing.cancel',           'billing', 'Cancel subscription',         'Cancel Subscription'),
  ('billing.renews',           'billing', 'Renewal date label',          'Renews on'),
  ('billing.expires',          'billing', 'Expiration date label',       'Expires on'),
  ('billing.monthly',          'billing', 'Monthly billing label',       'Monthly'),
  ('billing.annual',           'billing', 'Annual billing label',        'Annual'),
  ('billing.saveWithAnnual',   'billing', 'Annual savings label',        'Save 20% with annual billing'),
  ('billing.paymentMethod',    'billing', 'Payment method label',        'Payment Method'),
  ('billing.addCard',          'billing', 'Add card button',             'Add Card'),
  ('billing.updateCard',       'billing', 'Update card button',          'Update Card'),
  ('billing.invoices',         'billing', 'Invoices section title',      'Invoices'),
  ('billing.downloadInvoice',  'billing', 'Download invoice button',     'Download'),
  ('billing.invoiceDate',      'billing', 'Invoice date column',         'Date'),
  ('billing.invoiceAmount',    'billing', 'Invoice amount column',       'Amount'),
  ('billing.invoiceStatus',    'billing', 'Invoice status column',       'Status'),
  ('billing.paid',             'billing', 'Paid status label',           'Paid'),
  ('billing.unpaid',           'billing', 'Unpaid status label',         'Unpaid'),
  ('billing.free',             'billing', 'Free plan label',             'Free'),
  ('billing.starter',          'billing', 'Starter plan label',          'Starter'),
  ('billing.professional',     'billing', 'Professional plan label',     'Professional'),
  ('billing.enterprise',       'billing', 'Enterprise plan label',       'Enterprise'),
  ('billing.perMonth',         'billing', 'Per month label',             '/month'),
  ('billing.perYear',          'billing', 'Per year label',              '/year'),
  ('billing.currentPlanBadge', 'billing', 'Current plan badge',          'Current Plan'),
  ('billing.choosePlan',       'billing', 'Choose plan button',          'Choose Plan'),
  ('billing.contactSales',     'billing', 'Contact sales button',        'Contact Sales'),
  ('billing.usageLimits',      'billing', 'Usage limits section',        'Usage Limits'),
  ('billing.chatsUsed',        'billing', 'Chats used label',            'Chats Used'),
  ('billing.callMinutes',      'billing', 'Call minutes label',          'Call Minutes'),
  ('billing.agents',           'billing', 'Number of agents label',      'AI Agents'),
  ('billing.locations',        'billing', 'Locations label',             'Locations'),
  ('restaurant.profile',       'restaurant', 'Profile section title',    'Restaurant Profile'),
  ('restaurant.name',          'restaurant', 'Restaurant name field',    'Restaurant Name'),
  ('restaurant.description',   'restaurant', 'Description field',        'Description'),
  ('restaurant.cuisine',       'restaurant', 'Cuisine type field',       'Cuisine Type'),
  ('restaurant.address',       'restaurant', 'Address field',            'Address'),
  ('restaurant.city',          'restaurant', 'City field',               'City'),
  ('restaurant.country',       'restaurant', 'Country field',            'Country'),
  ('restaurant.phone',         'restaurant', 'Phone number field',       'Phone Number'),
  ('restaurant.website',       'restaurant', 'Website field',            'Website'),
  ('restaurant.logo',          'restaurant', 'Logo upload label',        'Restaurant Logo'),
  ('restaurant.uploadLogo',    'restaurant', 'Upload logo button',       'Upload Logo'),
  ('restaurant.businessHours', 'restaurant', 'Business hours section',   'Business Hours'),
  ('restaurant.monday',        'restaurant', 'Monday label',             'Monday'),
  ('restaurant.tuesday',       'restaurant', 'Tuesday label',            'Tuesday'),
  ('restaurant.wednesday',     'restaurant', 'Wednesday label',          'Wednesday'),
  ('restaurant.thursday',      'restaurant', 'Thursday label',           'Thursday'),
  ('restaurant.friday',        'restaurant', 'Friday label',             'Friday'),
  ('restaurant.saturday',      'restaurant', 'Saturday label',           'Saturday'),
  ('restaurant.sunday',        'restaurant', 'Sunday label',             'Sunday'),
  ('restaurant.open',          'restaurant', 'Open status label',        'Open'),
  ('restaurant.closed',        'restaurant', 'Closed status label',      'Closed'),
  ('restaurant.openTime',      'restaurant', 'Opening time label',       'Opening Time'),
  ('restaurant.closeTime',     'restaurant', 'Closing time label',       'Closing Time'),
  ('restaurant.timezone',      'restaurant', 'Timezone field',           'Timezone'),
  ('restaurant.capacity',      'restaurant', 'Seating capacity field',   'Seating Capacity'),
  ('restaurant.reservations',  'restaurant', 'Reservations toggle',      'Accept Reservations'),
  ('restaurant.saveProfile',   'restaurant', 'Save profile button',      'Save Profile'),
  ('restaurant.branding',      'restaurant', 'Branding section title',   'Branding'),
  ('restaurant.primaryColor',  'restaurant', 'Primary color field',      'Primary Color'),
  ('restaurant.accentColor',   'restaurant', 'Accent color field',       'Accent Color'),
  ('restaurant.fontFamily',    'restaurant', 'Font family field',        'Font Family'),
  ('notification.title',       'notification', 'Notifications title',    'Notifications'),
  ('notification.markAllRead', 'notification', 'Mark all read button',   'Mark All as Read'),
  ('notification.noNew',       'notification', 'No new notifications',   'No new notifications'),
  ('notification.viewAll',     'notification', 'View all link',          'View All'),
  ('notification.newBooking',  'notification', 'New booking alert',      'New booking received'),
  ('notification.newOrder',    'notification', 'New order alert',        'New order received'),
  ('notification.missedCall',  'notification', 'Missed call alert',      'Missed call from'),
  ('notification.agentOffline','notification', 'Agent offline alert',    'Agent went offline'),
  ('notification.agentOnline', 'notification', 'Agent online alert',     'Agent is online'),
  ('notification.lowBalance',  'notification', 'Low balance alert',      'Low account balance'),
  ('notification.settings',    'notification', 'Notification settings',  'Notification Settings'),
  ('notification.email',       'notification', 'Email notifications',    'Email Notifications'),
  ('notification.sms',         'notification', 'SMS notifications',      'SMS Notifications'),
  ('notification.push',        'notification', 'Push notifications',     'Push Notifications'),
  -- ── agent extra (non-duplicate unique keys) ──
  ('agent.name',               'agent', 'Agent name field',             'Agent Name'),
  ('agent.personality',        'agent', 'Personality field',            'Personality'),
  ('agent.language',           'agent', 'Agent language field',         'Language'),
  ('agent.voiceType',          'agent', 'Voice type field',             'Voice Type'),
  ('agent.greetingMessage',    'agent', 'Greeting message field',       'Greeting Message'),
  ('agent.fallbackMessage',    'agent', 'Fallback message field',       'Fallback Message'),
  ('agent.maxRetries',         'agent', 'Max retries field',            'Max Retries'),
  ('agent.escalationPrompt',   'agent', 'Escalation prompt field',      'Escalation Prompt'),
  ('agent.trainingData',       'agent', 'Training data section',        'Training Data'),
  ('agent.addFaq',             'agent', 'Add FAQ button',               'Add FAQ'),
  ('agent.question',           'agent', 'Question field',               'Question'),
  ('agent.answer',             'agent', 'Answer field',                 'Answer'),
  ('agent.saveAgent',          'agent', 'Save agent button',            'Save Agent'),
  ('agent.testAgent',          'agent', 'Test agent button',            'Test Agent'),
  ('agent.deployAgent',        'agent', 'Deploy agent button',          'Deploy Agent'),
  ('agent.status',             'agent', 'Agent status label',           'Status'),
  ('agent.active',             'agent', 'Active status',                'Active'),
  ('agent.paused',             'agent', 'Paused status',                'Paused'),
  ('agent.draft',              'agent', 'Draft status',                 'Draft'),
  -- ── menu extra (non-duplicate unique keys) ──
  ('menu.categories',          'menu', 'Menu categories label',         'Categories'),
  ('menu.items',               'menu', 'Menu items label',              'Items'),
  ('menu.itemCategory',        'menu', 'Item category field',           'Category'),
  ('menu.itemImage',           'menu', 'Item image field',              'Image'),
  ('menu.vegetarian',          'menu', 'Vegetarian label',              'Vegetarian'),
  ('menu.vegan',               'menu', 'Vegan label',                   'Vegan'),
  ('menu.glutenFree',          'menu', 'Gluten-free label',             'Gluten-Free'),
  ('menu.spicy',               'menu', 'Spicy label',                   'Spicy'),
  ('menu.popular',             'menu', 'Popular label',                 'Popular'),
  ('menu.saveMenu',            'menu', 'Save menu button',              'Save Menu'),
  ('menu.publishMenu',         'menu', 'Publish menu button',           'Publish Menu'),
  ('menu.previewMenu',         'menu', 'Preview menu button',           'Preview Menu')
ON CONFLICT (key) DO NOTHING;

-- ─── NEW TRANSLATION KEYS (i18n sweep) ──────────────────────
INSERT INTO public.translation_keys (key, category, description, default_value) VALUES
  ('admin.adminPanel', 'admin', 'Admin panel label', 'Admin Panel'),
  ('admin.aiSettings.adminPanel', 'admin', 'AI settings admin panel label', 'Admin Panel'),
  ('admin.aiSettings.adminPanelDesc', 'admin', 'AI settings admin panel desc', 'Changes apply platform-wide to all restaurants'),
  ('admin.aiSettings.badgeBeta', 'admin', 'Beta badge label', 'Beta'),
  ('admin.aiSettings.badgeRecommended', 'admin', 'Recommended badge label', 'Recommended'),
  ('admin.aiSettings.defaultParams', 'admin', 'Default model parameters section', 'Default Model Parameters'),
  ('admin.aiSettings.featureFlags', 'admin', 'Feature flags section', 'Feature Flags'),
  ('admin.aiSettings.flags.analyticsExport', 'admin', 'Analytics export flag', 'Analytics Export'),
  ('admin.aiSettings.flags.analyticsExportDesc', 'admin', 'Analytics export flag desc', 'Allow restaurants to export analytics data'),
  ('admin.aiSettings.flags.betaFeatures', 'admin', 'Beta features flag', 'Beta Features'),
  ('admin.aiSettings.flags.betaFeaturesDesc', 'admin', 'Beta features flag desc', 'Enable experimental features for testing'),
  ('admin.aiSettings.flags.chatAgent', 'admin', 'Chat agent flag', 'Chat Agent'),
  ('admin.aiSettings.flags.chatAgentDesc', 'admin', 'Chat agent flag desc', 'Enable chat/messaging AI for all restaurants'),
  ('admin.aiSettings.flags.customScripts', 'admin', 'Custom scripts flag', 'Custom Scripts'),
  ('admin.aiSettings.flags.customScriptsDesc', 'admin', 'Custom scripts flag desc', 'Allow restaurants to customize AI scripts'),
  ('admin.aiSettings.flags.multiBranch', 'admin', 'Multi-branch flag', 'Multi-Branch Support'),
  ('admin.aiSettings.flags.multiBranchDesc', 'admin', 'Multi-branch flag desc', 'Allow restaurants to manage multiple locations'),
  ('admin.aiSettings.flags.voiceAgent', 'admin', 'Voice agent flag', 'Voice Agent'),
  ('admin.aiSettings.flags.voiceAgentDesc', 'admin', 'Voice agent flag desc', 'Enable voice calling capability for all restaurants'),
  ('admin.aiSettings.flags.whatsapp', 'admin', 'WhatsApp flag', 'WhatsApp Integration'),
  ('admin.aiSettings.flags.whatsappDesc', 'admin', 'WhatsApp flag desc', 'Allow restaurants to connect WhatsApp Business'),
  ('admin.aiSettings.flags.whiteLabel', 'admin', 'White-label flag', 'White-Label Mode'),
  ('admin.aiSettings.flags.whiteLabelDesc', 'admin', 'White-label flag desc', 'Remove RestroAgent branding for enterprise clients'),
  ('admin.aiSettings.labelFallbackModel', 'admin', 'Fallback model label', 'Fallback Model'),
  ('admin.aiSettings.labelMaxTokens', 'admin', 'Max tokens label', 'Max Tokens (Default)'),
  ('admin.aiSettings.labelTemperature', 'admin', 'Temperature label', 'Default Temperature'),
  ('admin.aiSettings.labelTimeout', 'admin', 'Timeout label', 'Timeout (seconds)'),
  ('admin.aiSettings.modelConfig', 'admin', 'Model config section', 'Model Configuration'),
  ('admin.aiSettings.pageDesc', 'admin', 'AI settings page desc', 'Configure AI model defaults and platform-wide feature flags'),
  ('admin.aiSettings.pageTitle', 'admin', 'AI settings page title', 'AI Settings'),
  ('admin.aiSettings.rateLimitApi', 'admin', 'Rate limit API label', 'API calls per minute (per restaurant)'),
  ('admin.aiSettings.rateLimitEnterprise', 'admin', 'Rate limit enterprise label', 'Enterprise Plan — Conversations/mo'),
  ('admin.aiSettings.rateLimitPro', 'admin', 'Rate limit pro label', 'Pro Plan — Conversations/mo'),
  ('admin.aiSettings.rateLimitStarter', 'admin', 'Rate limit starter label', 'Starter Plan — Conversations/mo'),
  ('admin.aiSettings.rateLimitVoice', 'admin', 'Rate limit voice label', 'Concurrent voice calls (per restaurant)'),
  ('admin.aiSettings.rateLimits', 'admin', 'Rate limits section', 'Rate Limits'),
  ('admin.aiSettings.saveBtn', 'admin', 'Save button label', 'Save All Changes'),
  ('admin.aiSettings.tempBalanced', 'admin', 'Balanced temperature label', '0.7 (Balanced)'),
  ('admin.aiSettings.tempCreative', 'admin', 'Creative temperature label', '1.0 (Creative)'),
  ('admin.aiSettings.tempFocused', 'admin', 'Focused temperature label', '0.3 (Focused)'),
  ('admin.billing.activeBranches', 'admin', 'Active branches stat', 'Active Branches'),
  ('admin.billing.adminPanel', 'admin', 'Billing admin panel label', 'Admin Panel'),
  ('admin.billing.apiCallsThisMonth', 'admin', 'API calls this month stat', 'API Calls This Month'),
  ('admin.billing.headerAmount', 'admin', 'Amount column header', 'Amount'),
  ('admin.billing.headerDate', 'admin', 'Date column header', 'Date'),
  ('admin.billing.headerPlan', 'admin', 'Plan column header', 'Plan'),
  ('admin.billing.headerRestaurant', 'admin', 'Restaurant column header', 'Restaurant'),
  ('admin.billing.headerStatus', 'admin', 'Status column header', 'Status'),
  ('admin.billing.monthlyRevenue', 'admin', 'Monthly revenue stat', 'Monthly Revenue'),
  ('admin.billing.noInvoices', 'admin', 'No invoices message', 'No invoices found'),
  ('admin.billing.noPlans', 'admin', 'No plans message', 'No plans configured yet'),
  ('admin.billing.pageDesc', 'admin', 'Billing admin page desc', 'Manage plans, pricing, and subscription data'),
  ('admin.billing.pageTitle', 'admin', 'Billing admin page title', 'Billing Administration'),
  ('admin.billing.perMonth', 'admin', 'Per month label', '/mo'),
  ('admin.billing.subscribers', 'admin', 'Subscribers stat', 'Subscribers'),
  ('admin.billing.tabInvoices', 'admin', 'Invoices tab', 'Invoices'),
  ('admin.billing.tabPlans', 'admin', 'Plans tab', 'Plans'),
  ('admin.billing.tabUsage', 'admin', 'Usage tab', 'Usage'),
  ('admin.billing.totalConversations', 'admin', 'Total conversations stat', 'Total Conversations'),
  ('admin.billing.totalMrrStats', 'admin', 'Total MRR stat', 'Total MRR'),
  ('admin.billing.usageOverview', 'admin', 'Usage overview section', 'Usage Overview'),
  ('admin.blog.addBlock', 'admin', 'Add content block button', 'Add Block'),
  ('admin.blog.addTagPlaceholder', 'admin', 'Add tag input placeholder', 'Add tag…'),
  ('admin.blog.adminBannerSub', 'admin', 'Admin mode banner subtitle', 'Admin Mode'),
  ('admin.blog.adminPanel', 'admin', 'Blog admin panel label', 'Admin Panel'),
  ('admin.blog.allStatuses', 'admin', 'All statuses filter', 'All Statuses'),
  ('admin.blog.altTextPlaceholder', 'admin', 'Alt text placeholder', 'Describe the image for accessibility…'),
  ('admin.blog.articleContent', 'admin', 'Article content section', 'Article Content'),
  ('admin.blog.author', 'admin', 'Author label', 'Author'),
  ('admin.blog.authorBio', 'admin', 'Author bio label', 'Author Bio'),
  ('admin.blog.authorInitialsLabel', 'admin', 'Author initials label', 'Initials'),
  ('admin.blog.authorNameLabel', 'admin', 'Author name label', 'Full Name'),
  ('admin.blog.autoGenerate', 'admin', 'Auto-generate button', 'Auto-generate'),
  ('admin.blog.autoGeneratedFromTitle', 'admin', 'Auto-generated from title notice', 'Auto-generated from title'),
  ('admin.blog.backToBlog', 'admin', 'Back to blog button', 'Back to Blog'),
  ('admin.blog.blockFormatGuide', 'admin', 'Block format guide label', 'Format Guide'),
  ('admin.blog.blockquote', 'admin', 'Blockquote block type', 'Blockquote'),
  ('admin.blog.blockquoteGuide', 'admin', 'Blockquote format guide', 'Write the quote text. Source/author is optional on a new line.'),
  ('admin.blog.briefDescriptionPlaceholder', 'admin', 'Brief description placeholder', 'Brief description of the blog post…'),
  ('admin.blog.callout', 'admin', 'Callout block type', 'Callout'),
  ('admin.blog.calloutGuide', 'admin', 'Callout format guide', 'Short attention-grabbing notice. Supports icons (💡, ⚠️, ✅).'),
  ('admin.blog.cancel', 'admin', 'Cancel button', 'Cancel'),
  ('admin.blog.cannotBeUndone', 'admin', 'Cannot be undone warning', 'This action cannot be undone.'),
  ('admin.blog.cat.aiFeatures', 'admin', 'AI features category', 'AI Features'),
  ('admin.blog.cat.aiTech', 'admin', 'AI tech category', 'AI & Technology'),
  ('admin.blog.cat.caseStudies', 'admin', 'Case studies category', 'Case Studies'),
  ('admin.blog.cat.customerExp', 'admin', 'Customer experience category', 'Customer Experience'),
  ('admin.blog.cat.operations', 'admin', 'Operations category', 'Operations'),
  ('admin.blog.cat.productUpdates', 'admin', 'Product updates category', 'Product Updates'),
  ('admin.blog.categoryAndTags', 'admin', 'Category and tags section', 'Category & Tags'),
  ('admin.blog.categoryLabel', 'admin', 'Category label', 'Category'),
  ('admin.blog.charactersRecommended', 'admin', 'Characters recommended label', 'chars (recommended: 150–160)'),
  ('admin.blog.clearFilters', 'admin', 'Clear filters button', 'Clear Filters'),
  ('admin.blog.colActions', 'admin', 'Actions column header', 'Actions'),
  ('admin.blog.colAuthor', 'admin', 'Author column header', 'Author'),
  ('admin.blog.colCategory', 'admin', 'Category column header', 'Category'),
  ('admin.blog.colPublished', 'admin', 'Published column header', 'Published'),
  ('admin.blog.colStatus', 'admin', 'Status column header', 'Status'),
  ('admin.blog.colTitle', 'admin', 'Title column header', 'Title'),
  ('admin.blog.colViews', 'admin', 'Views column header', 'Views'),
  ('admin.blog.confirmDelete', 'admin', 'Confirm delete message', 'Are you sure you want to delete {{count}} post(s)?'),
  ('admin.blog.confirmDeleteSingle', 'admin', 'Confirm delete single message', 'Are you sure you want to delete'),
  ('admin.blog.confirmPublish', 'admin', 'Confirm publish message', 'Publish {{count}} selected post(s)?'),
  ('admin.blog.confirmUnpublish', 'admin', 'Confirm unpublish message', 'Unpublish {{count}} selected post(s)?'),
  ('admin.blog.content', 'admin', 'Content label', 'Content'),
  ('admin.blog.contentBlocksHelpText', 'admin', 'Content blocks help text', 'Add and arrange content blocks to build your article'),
  ('admin.blog.createANewBlogPost', 'admin', 'Create new blog post title', 'Create a New Blog Post'),
  ('admin.blog.creatingNewBlogPost', 'admin', 'Creating new blog post status', 'Creating new blog post'),
  ('admin.blog.csv.author', 'admin', 'CSV author column', 'Author'),
  ('admin.blog.csv.category', 'admin', 'CSV category column', 'Category'),
  ('admin.blog.csv.publishDate', 'admin', 'CSV publish date column', 'Publish Date'),
  ('admin.blog.csv.status', 'admin', 'CSV status column', 'Status'),
  ('admin.blog.csv.title', 'admin', 'CSV title column', 'Title'),
  ('admin.blog.csv.views', 'admin', 'CSV views column', 'Views'),
  ('admin.blog.delete', 'admin', 'Delete action label', 'Delete'),
  ('admin.blog.deletePost', 'admin', 'Delete post button', 'Delete Post'),
  ('admin.blog.deletePosts', 'admin', 'Delete posts button', 'Delete Posts'),
  ('admin.blog.draft', 'admin', 'Draft status label', 'Draft'),
  ('admin.blog.edit', 'admin', 'Edit action label', 'Edit'),
  ('admin.blog.editingExistingPost', 'admin', 'Editing existing post status', 'Editing existing post'),
  ('admin.blog.editPost', 'admin', 'Edit post button', 'Edit Post'),
  ('admin.blog.enterMetaDescriptionPlaceholder', 'admin', 'Meta description placeholder', 'Enter meta description…'),
  ('admin.blog.enterPostTitle', 'admin', 'Post title placeholder', 'Enter post title…'),
  ('admin.blog.enterSeoTitlePlaceholder', 'admin', 'SEO title placeholder', 'Enter SEO title…'),
  ('admin.blog.excerptPreview', 'admin', 'Excerpt preview section', 'Excerpt Preview'),
  ('admin.blog.excerptSubtitle', 'admin', 'Excerpt subtitle', 'Auto-generated from your first paragraph'),
  ('admin.blog.exportCsv', 'admin', 'Export CSV button', 'Export CSV'),
  ('admin.blog.faqList', 'admin', 'FAQ list block type', 'FAQ List'),
  ('admin.blog.faqListGuide', 'admin', 'FAQ list format guide', 'One FAQ per line: Q: your question? A: your answer.'),
  ('admin.blog.filterCategory', 'admin', 'Filter by category label', 'Category'),
  ('admin.blog.filters', 'admin', 'Filters section label', 'Filters'),
  ('admin.blog.filterStatus', 'admin', 'Filter by status label', 'Status'),
  ('admin.blog.fullNamePlaceholder', 'admin', 'Full name placeholder', 'Full name…'),
  ('admin.blog.googleSearchPreview', 'admin', 'Google search preview section', 'Google Search Preview'),
  ('admin.blog.heroImage', 'admin', 'Hero image section', 'Hero Image'),
  ('admin.blog.heroImageHelpText', 'admin', 'Hero image help text', 'Shown at the top of the article and in social shares'),
  ('admin.blog.heroImagePlaceholder', 'admin', 'Hero image URL placeholder', 'https://example.com/image.jpg'),
  ('admin.blog.initialsPlaceholder', 'admin', 'Initials placeholder', 'JD'),
  ('admin.blog.livePreviewHelpText', 'admin', 'Live preview help text', 'How this post will appear on the public blog'),
  ('admin.blog.metaDescriptionPreview', 'admin', 'Meta description preview', 'Meta Description'),
  ('admin.blog.min', 'admin', 'Minute abbreviation', 'min'),
  ('admin.blog.minRead', 'admin', 'Minutes read label', 'min read'),
  ('admin.blog.moveDown', 'admin', 'Move block down button', 'Move down'),
  ('admin.blog.moveUp', 'admin', 'Move block up button', 'Move up'),
  ('admin.blog.newPost', 'admin', 'New post button', 'New Post'),
  ('admin.blog.noPostsFound', 'admin', 'No posts found message', 'No posts found'),
  ('admin.blog.numberedList', 'admin', 'Numbered list block type', 'Numbered List'),
  ('admin.blog.numberedListGuide', 'admin', 'Numbered list format guide', 'One item per line. Numbers are added automatically.'),
  ('admin.blog.pageDesc', 'admin', 'Blog admin page desc', 'Write, edit, and publish blog content for the public site'),
  ('admin.blog.pageTitle', 'admin', 'Blog admin page title', 'Blog Manager'),
  ('admin.blog.paragraph', 'admin', 'Paragraph block type', 'Paragraph'),
  ('admin.blog.paragraphGuide', 'admin', 'Paragraph format guide', 'Write your paragraph text here. Supports **bold**, *italic*, and inline code syntax.'),
  ('admin.blog.postsSelected', 'admin', 'Posts selected label', '{{count}} post(s) selected'),
  ('admin.blog.publish', 'admin', 'Publish button', 'Publish'),
  ('admin.blog.publishDate', 'admin', 'Publish date label', 'Publish Date'),
  ('admin.blog.publishPosts', 'admin', 'Publish posts button', 'Publish Posts'),
  ('admin.blog.published', 'admin', 'Published status label', 'Published'),
  ('admin.blog.publishPost', 'admin', 'Publish post button', 'Publish Post'),
  ('admin.blog.readTimeLabel', 'admin', 'Read time label', 'Read time'),
  ('admin.blog.removeBlock', 'admin', 'Remove block button', 'Remove block'),
  ('admin.blog.save', 'admin', 'Save button', 'Save'),
  ('admin.blog.saveDraft', 'admin', 'Save draft button', 'Save Draft'),
  ('admin.blog.savePublish', 'admin', 'Save and publish button', 'Save & Publish'),
  ('admin.blog.searchPlaceholder', 'admin', 'Search posts placeholder', 'Search posts…'),
  ('admin.blog.seoSettings', 'admin', 'SEO settings section', 'SEO Settings'),
  ('admin.blog.seoTitle', 'admin', 'SEO title label', 'SEO Title'),
  ('admin.blog.sharePost', 'admin', 'Share post button', 'Share Post'),
  ('admin.blog.showLivePreview', 'admin', 'Show live preview toggle', 'Live Preview'),
  ('admin.blog.slug', 'admin', 'Slug label', 'Slug'),
  ('admin.blog.status', 'admin', 'Status label', 'Status'),
  ('admin.blog.subtitle', 'admin', 'Blog admin page subtitle', 'Manage blog posts'),
  ('admin.blog.tableImage', 'admin', 'Table image block type', 'Table + Image'),
  ('admin.blog.tableImageGuide', 'admin', 'Table image format guide', 'Column A | Column B'),
  ('admin.blog.tags', 'admin', 'Tags label', 'Tags'),
  ('admin.blog.title', 'admin', 'Title label', 'Title'),
  ('admin.blog.titleAndMeta', 'admin', 'Title and meta section', 'Title & Meta'),
  ('admin.blog.twoColumnText', 'admin', 'Two column text block type', 'Two-Column Text'),
  ('admin.blog.twoColumnTextGuide', 'admin', 'Two column text format guide', 'Column 1 text || Column 2 text'),
  ('admin.blog.typeToAddTag', 'admin', 'Type to add tag placeholder', 'Type and press Enter to add a tag'),
  ('admin.blog.unpublish', 'admin', 'Unpublish button', 'Unpublish'),
  ('admin.blog.unpublishPost', 'admin', 'Unpublish post button', 'Unpublish Post'),
  ('admin.blog.unpublishPosts', 'admin', 'Unpublish posts button', 'Unpublish Posts'),
  ('admin.blog.unsavedChanges', 'admin', 'Unsaved changes warning', 'Unsaved changes'),
  ('admin.blog.urlImagePlaceholder', 'admin', 'Image URL placeholder', 'Image URL'),
  ('admin.blog.urlLinkPlaceholder', 'admin', 'Link URL placeholder', 'https://…'),
  ('admin.blog.viewPost', 'admin', 'View post button', 'View Post'),
  ('admin.blog.visibilitySection', 'admin', 'Visibility section', 'Visibility'),
  ('admin.blog.wordCount', 'admin', 'Word count label', 'Words'),
  ('admin.blog.wordCountLabel', 'admin', 'Word count section label', 'Word Count'),
  ('admin.languages.actions.autoTranslate', 'admin', 'Auto-translate action', 'Auto-translate missing strings with AI'),
  ('admin.languages.actions.deleteLanguage', 'admin', 'Delete language action', 'Delete language'),
  ('admin.languages.actions.editLanguage', 'admin', 'Edit language action', 'Edit language'),
  ('admin.languages.actions.editTranslations', 'admin', 'Edit translations action', 'Edit translations'),
  ('admin.languages.actions.setDefault', 'admin', 'Set default language action', 'Set as default'),
  ('admin.languages.addLanguage', 'admin', 'Add language button', 'Add Language'),
  ('admin.languages.colCode', 'admin', 'Code column header', 'Code'),
  ('admin.languages.colLanguage', 'admin', 'Language column header', 'Language'),
  ('admin.languages.colTranslations', 'admin', 'Translations column header', 'Translations'),
  ('admin.languages.copyFrom', 'admin', 'Copy from label', 'Copy translations from'),
  ('admin.languages.deleteConfirm', 'admin', 'Delete language confirm message', 'Are you sure you want to delete'),
  ('admin.languages.deleteLanguage', 'admin', 'Delete language button', 'Delete Language'),
  ('admin.languages.deleteWarning', 'admin', 'Delete language warning', 'All its translations will be permanently removed.'),
  ('admin.languages.edit', 'admin', 'Edit label', 'Edit'),
  ('admin.languages.errors.addFailed', 'admin', 'Add language error', 'Failed to add language'),
  ('admin.languages.errors.aiTranslateFailed', 'admin', 'AI translate error', 'AI translation failed'),
  ('admin.languages.errors.aiTranslateServerFailed', 'admin', 'AI translate server error', 'AI translation failed — check server logs'),
  ('admin.languages.errors.allTranslated', 'admin', 'All translated message', 'All keys are already translated'),
  ('admin.languages.errors.deleteFailed', 'admin', 'Delete language error', 'Failed to delete language'),
  ('admin.languages.errors.fieldsRequired', 'admin', 'Required fields error', 'Code, name, and native name are required'),
  ('admin.languages.errors.loadFailed', 'admin', 'Load languages error', 'Failed to load languages'),
  ('admin.languages.errors.noChanges', 'admin', 'No changes message', 'No changes to save'),
  ('admin.languages.errors.saveTranslationsFailed', 'admin', 'Save translations error', 'Failed to save translations'),
  ('admin.languages.errors.setDefaultFailed', 'admin', 'Set default error', 'Failed to set default language'),
  ('admin.languages.errors.translationsLoadFailed', 'admin', 'Load translations error', 'Failed to load translations'),
  ('admin.languages.errors.updateFailed', 'admin', 'Update language error', 'Failed to update language'),
  ('admin.languages.flagEmoji', 'admin', 'Flag emoji label', 'Flag Emoji'),
  ('admin.languages.flagEmojiPlaceholder', 'admin', 'Flag emoji placeholder', 'e.g. 🇫🇷'),
  ('admin.languages.isRtl', 'admin', 'RTL toggle label', 'Right-to-Left (RTL)'),
  ('admin.languages.langCode', 'admin', 'Language code label', 'Language Code'),
  ('admin.languages.langCodePlaceholder', 'admin', 'Language code placeholder', 'e.g. fr'),
  ('admin.languages.name', 'admin', 'Language name label', 'Language Name'),
  ('admin.languages.namePlaceholder', 'admin', 'Language name placeholder', 'e.g. French'),
  ('admin.languages.nativeName', 'admin', 'Native name label', 'Native Name'),
  ('admin.languages.nativeNamePlaceholder', 'admin', 'Native name placeholder', 'e.g. Français'),
  ('admin.languages.noLanguages', 'admin', 'No languages message', 'No languages configured yet.'),
  ('admin.languages.saveChanges', 'admin', 'Save changes button', 'Save Changes'),
  ('admin.languages.success.added', 'admin', 'Language added success', 'Language "{{name}}" added'),
  ('admin.languages.success.aiTranslated', 'admin', 'AI translated success', 'AI translated {{count}} key(s) into {{lang}}'),
  ('admin.languages.success.defaultSet', 'admin', 'Default language set success', '"{{name}}" is now the default language'),
  ('admin.languages.success.deleted', 'admin', 'Language deleted success', 'Language "{{name}}" deleted'),
  ('admin.languages.success.translationsSaved', 'admin', 'Translations saved success', '{{count}} translation(s) saved'),
  ('admin.languages.success.updated', 'admin', 'Language updated success', 'Language updated'),
  ('admin.languages.subtitle', 'admin', 'Languages page subtitle', 'Manage platform languages and translations'),
  ('admin.languages.title', 'admin', 'Languages page title', 'Languages'),
  ('admin.languages.translationsFor', 'admin', 'Translations for label', 'Translations for {{lang}}'),
  ('billing.annual', 'billing', 'Annual billing option', 'Annual (save 20%)'),
  ('billing.billingCycle', 'billing', 'Billing cycle label', 'Billing Cycle'),
  ('billing.cardElementNotMounted', 'billing', 'Card element not mounted error', 'Card element not mounted'),
  ('billing.cardSetupFailed', 'billing', 'Card setup failed error', 'Card setup failed'),
  ('billing.checkoutCancelled', 'billing', 'Checkout cancelled message', 'Checkout was cancelled. No charges were made.'),
  ('billing.clickAddCardAbove', 'billing', 'Click add card above notice', 'Click "Add Card" above to save a payment method'),
  ('billing.createPlan', 'billing', 'Create plan button', 'Create Plan'),
  ('billing.editPlan', 'billing', 'Edit plan button', 'Edit Plan'),
  ('billing.failedToLoadData', 'billing', 'Failed to load data error', 'Failed to load billing data'),
  ('billing.failedToLoadInvoices', 'billing', 'Failed to load invoices error', 'Failed to load invoices'),
  ('billing.failedToLoadPaymentMethod', 'billing', 'Failed to load payment method error', 'Failed to load payment method'),
  ('billing.failedToOpenCancelPortal', 'billing', 'Failed to open cancel portal error', 'Failed to open cancellation portal'),
  ('billing.failedToOpenPortal', 'billing', 'Failed to open portal error', 'Failed to open payment portal'),
  ('billing.failedToStartCardUpdate', 'billing', 'Failed to start card update error', 'Failed to start card update'),
  ('billing.failedToStartCheckout', 'billing', 'Failed to start checkout error', 'Failed to start checkout'),
  ('billing.failedToUpdatePaymentMethod', 'billing', 'Failed to update payment method error', 'Failed to update payment method'),
  ('billing.features.analytics', 'billing', 'Advanced analytics feature', 'Advanced Analytics'),
  ('billing.features.analyticsDesc', 'billing', 'Advanced analytics feature desc', 'Detailed reports and insights'),
  ('billing.features.apiAccess', 'billing', 'API access feature', 'API Access'),
  ('billing.features.apiAccessDesc', 'billing', 'API access feature desc', 'REST API for integrations'),
  ('billing.features.bulkUpload', 'billing', 'Bulk upload feature', 'Bulk Menu Upload'),
  ('billing.features.bulkUploadDesc', 'billing', 'Bulk upload feature desc', 'AI-powered menu import'),
  ('billing.features.chatAgent', 'billing', 'Chat agent feature', 'Chat Agent'),
  ('billing.features.chatAgentDesc', 'billing', 'Chat agent feature desc', 'Web chat and messaging'),
  ('billing.features.customIntegrations', 'billing', 'Custom integrations feature', 'Custom Integrations'),
  ('billing.features.customIntegrationsDesc', 'billing', 'Custom integrations feature desc', 'POS and third-party integrations'),
  ('billing.features.knowledgeBase', 'billing', 'Knowledge base feature', 'Knowledge Base'),
  ('billing.features.knowledgeBaseDesc', 'billing', 'Knowledge base feature desc', 'Custom AI knowledge sources'),
  ('billing.features.multiBranch', 'billing', 'Multi-branch feature', 'Multi-Branch'),
  ('billing.features.multiBranchDesc', 'billing', 'Multi-branch feature desc', 'Multiple location support'),
  ('billing.features.prioritySupport', 'billing', 'Priority support feature', 'Priority Support'),
  ('billing.features.prioritySupportDesc', 'billing', 'Priority support feature desc', '24/7 dedicated support'),
  ('billing.features.voiceAgent', 'billing', 'Voice agent feature', 'Voice Agent'),
  ('billing.features.voiceAgentDesc', 'billing', 'Voice agent feature desc', 'AI-powered phone call handling'),
  ('billing.features.whiteLabel', 'billing', 'White label feature', 'White Label'),
  ('billing.features.whiteLabelDesc', 'billing', 'White label feature desc', 'Custom branding options'),
  ('billing.featuresEnabledCount', 'billing', 'Features enabled count', '{{count}} of {{total}} enabled'),
  ('billing.featuresIncluded', 'billing', 'Features included label', 'Features Included'),
  ('billing.freeTrialActive', 'billing', 'Free trial active label', 'Free trial active'),
  ('billing.invoiceHistory', 'billing', 'Invoice history section', 'Invoice History'),
  ('billing.invoicesWillAppear', 'billing', 'Invoices will appear notice', 'Invoices will appear here once your first billing cycle completes'),
  ('billing.loadingData', 'billing', 'Loading billing data message', 'Loading billing data…'),
  ('billing.maxAiQueries', 'billing', 'Max AI queries label', 'Max AI Queries/mo'),
  ('billing.maxAiQueriesPlaceholder', 'billing', 'Max AI queries placeholder', 'e.g. 2000'),
  ('billing.maxBranches', 'billing', 'Max branches label', 'Max Branches'),
  ('billing.maxBranchesPlaceholder', 'billing', 'Max branches placeholder', 'e.g. 3 (blank = unlimited)'),
  ('billing.maxOrders', 'billing', 'Max orders label', 'Max Orders/mo'),
  ('billing.maxOrdersPlaceholder', 'billing', 'Max orders placeholder', 'blank = unlimited'),
  ('billing.memberSince', 'billing', 'Member since label', 'Member Since'),
  ('billing.mo', 'billing', 'Month abbreviation', 'mo'),
  ('billing.nextBilling', 'billing', 'Next billing label', 'Next billing'),
  ('billing.noInvoicesYet', 'billing', 'No invoices yet message', 'No invoices yet'),
  ('billing.noPaymentMethodsOnFile', 'billing', 'No payment methods on file message', 'No payment methods on file'),
  ('billing.noPlan', 'billing', 'No plan label', 'No Plan'),
  ('billing.pastDue', 'billing', 'Past due status label', 'Past Due'),
  ('billing.paymentFailedDesc', 'billing', 'Payment failed description', 'Your last payment failed. Please update your payment method to avoid service interruption.'),
  ('billing.paymentMethods', 'billing', 'Payment methods section', 'Payment Methods'),
  ('billing.paymentMethodUpdated', 'billing', 'Payment method updated success', 'Payment method updated successfully'),
  ('billing.paymentPastDue', 'billing', 'Payment past due label', 'Payment past due'),
  ('billing.paymentSuccessful', 'billing', 'Payment successful message', 'Payment successful! Your subscription is now active.'),
  ('billing.planDetails', 'billing', 'Plan details section', 'Plan Details'),
  ('billing.planLimits', 'billing', 'Plan limits section', 'Plan Limits'),
  ('billing.planName', 'billing', 'Plan name label', 'Plan Name'),
  ('billing.plan', 'billing', 'Plan label', 'Plan'),
  ('billing.planPreview', 'billing', 'Plan preview section', 'Plan Preview'),
  ('billing.plans.enterprise', 'billing', 'Enterprise plan name', 'Enterprise'),
  ('billing.plans.growth', 'billing', 'Growth plan name', 'Growth'),
  ('billing.plans.pro', 'billing', 'Pro plan name', 'Pro'),
  ('billing.plans.starter', 'billing', 'Starter plan name', 'Starter'),
  ('billing.planStatus', 'billing', 'Plan status label', 'Plan Status'),
  ('billing.preview.aiQueriesCount', 'billing', 'AI queries count preview', '{{count}} AI queries/mo'),
  ('billing.preview.branchesCount', 'billing', 'Branches count preview', '{{count}} branches'),
  ('billing.preview.featuresCount', 'billing', 'Features count preview', '{{count}} features included'),
  ('billing.priceUsd', 'billing', 'Price USD label', 'Price (USD)'),
  ('billing.saveCard', 'billing', 'Save card button', 'Save Card'),
  ('billing.saveChanges', 'billing', 'Save changes button', 'Save Changes'),
  ('billing.status', 'billing', 'Status label', 'Status'),
  ('billing.stripeNotConfigured', 'billing', 'Stripe not configured error', 'Stripe is not configured. Please set NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY.'),
  ('billing.subscriptionStatus', 'billing', 'Subscription status label', 'Subscription status'),
  ('billing.subtitle', 'billing', 'Billing page subtitle', 'Manage your plan, usage, and payment details'),
  ('billing.tabInvoices', 'billing', 'Invoices tab', 'Invoices'),
  ('billing.tabOverview', 'billing', 'Overview tab', 'Overview'),
  ('billing.tabPayment', 'billing', 'Payment methods tab', 'Payment Methods'),
  ('billing.tabPlans', 'billing', 'Plans tab', 'Plans'),
  ('billing.trialDaysRemaining', 'billing', 'Trial days remaining label', '{{days}} day{{plural}} remaining · Trial ends {{date}}'),
  ('billing.trialEndedDesc', 'billing', 'Trial ended description', 'To continue using RestroAgent, please choose a plan below. All your data is safe and will be restored once you subscribe.'),
  ('billing.trialEndedTitle', 'billing', 'Trial ended title', 'Your 14-day free trial has ended'),
  ('billing.unitBranches', 'billing', 'Branches unit', 'branches'),
  ('billing.unitCalls', 'billing', 'Calls unit', 'calls'),
  ('billing.unitConversations', 'billing', 'Conversations unit', 'conversations'),
  ('billing.unitMinutes', 'billing', 'Minutes unit', 'minutes'),
  ('billing.addNewPlan', 'billing', 'Add new plan button', 'Add New Plan'),
  ('billing.addPaymentCard', 'billing', 'Add payment card button', 'Add Payment Card'),
  ('billing.activePlan', 'billing', 'Active plan label', 'Active Plan'),
  ('conversations.dateFrom', 'conversations', 'Date from label', 'Date from'),
  ('conversations.dateTo', 'conversations', 'Date to label', 'Date to'),
  ('menu.available', 'menu', 'Available status label', 'Available'),
  ('menu.hidden', 'menu', 'Hidden status label', 'Hidden'),
  ('menu.visible', 'menu', 'Visible status label', 'Visible'),
  ('menu.addCategory', 'menu', 'Add category button', 'Add Category'),
  ('menu.noCategoriesYet', 'menu', 'No categories yet message', 'No categories yet'),
  ('menu.searchItems', 'menu', 'Search items placeholder', 'Search items…'),
  ('menu.itemsCount', 'menu', 'Items count label', '{{count}} item(s)'),
  ('menu.tableHeaderItem', 'menu', 'Item column header', 'Item'),
  ('menu.tableHeaderPrice', 'menu', 'Price column header', 'Price'),
  ('menu.tableHeaderDetails', 'menu', 'Details column header', 'Details'),
  ('menu.tableHeaderAvailable', 'menu', 'Available column header', 'Available'),
  ('menu.tableHeaderCategory', 'menu', 'Category column header', 'Category'),
  ('menu.radio', 'menu', 'Radio button type label', 'Radio'),
  ('menu.checkbox', 'menu', 'Checkbox button type label', 'Checkbox'),
  ('menu.min', 'menu', 'Min label', 'Min'),
  ('menu.max', 'menu', 'Max label', 'Max'),
  ('menu.noLimit', 'menu', 'No limit placeholder', 'No limit'),
  ('menu.required', 'menu', 'Required label', 'Required'),
  ('menu.save', 'menu', 'Save button', 'Save'),
  ('menu.saveItemFirst', 'menu', 'Save item first notice', 'Save item first'),
  ('menu.optionName', 'menu', 'Option name placeholder', 'Option name'),
  ('menu.extraPrice', 'menu', 'Extra price placeholder', '₹ extra'),
  ('menu.deltaPrice', 'menu', 'Delta price placeholder', '₹ delta'),
  ('menu.def', 'menu', 'Default checkbox label', 'Def'),
  ('menu.default', 'menu', 'Default label', 'Default'),
  ('menu.free', 'menu', 'Free label', 'Free'),
  ('menu.noModifiersYet', 'menu', 'No modifiers yet message', 'No modifiers yet'),
  ('menu.updateItem', 'menu', 'Update item button', 'Update Item'),
  ('menu.createItem', 'menu', 'Create item button', 'Create Item'),
  ('menu.approve', 'menu', 'Approve action label', 'Approve'),
  ('menu.reject', 'menu', 'Reject action label', 'Reject'),
  ('menu.allCategories', 'menu', 'All categories option', 'All categories'),
  ('settings.setupGuide', 'settings', 'Setup guide label', 'Setup Guide'),
  ('settings.stepByStepInstructions', 'settings', 'Step by step instructions label', 'Step-by-step instructions'),
  ('settings.comingSoon', 'settings', 'Coming soon label', 'Coming Soon'),
  ('settings.marketplace.subtitle', 'settings', 'Marketplace subtitle', 'Connect with the apps and services you already use'),
  ('settings.marketplace.search_placeholder', 'settings', 'Marketplace search placeholder', 'Search integrations…'),
  ('settings.marketplace.popular', 'settings', 'Popular label', 'Popular'),
  ('settings.marketplace.title', 'settings', 'Marketplace title', 'Marketplace'),
  ('settings.marketplace.not_connected', 'settings', 'Not connected label', 'Not connected'),
  ('settings.marketplace.official_docs', 'settings', 'Official docs label', 'Official Documentation'),
  ('settings.marketplace.setup_guide', 'settings', 'Marketplace setup guide label', 'Setup Guide'),
  ('settings.marketplace.setup_guide_btn', 'settings', 'Marketplace setup guide button', 'Setup Guide'),
  ('settings.marketplace.step_by_step', 'settings', 'Step by step label', 'Step-by-step instructions'),
  ('settings.marketplace.try_different_search', 'settings', 'Try different search message', 'Try a different search or category'),
  ('settings.templates.description', 'settings', 'Templates page description', 'Customise automated messages sent to customers across all channels'),
  ('settings.templates.live_preview', 'settings', 'Templates live preview label', 'Live Preview'),
  ('settings.templates.placeholders', 'settings', 'Templates placeholders label', 'Variable Placeholders — click to insert, or copy'),
  ('settings.templates.preview_disclaimer', 'settings', 'Templates preview disclaimer', 'Variables replaced with example values'),
  ('settings.templates.reset_default', 'settings', 'Templates reset default button', 'Reset to Default'),
  ('settings.templates.save_template', 'settings', 'Templates save button', 'Save Template'),
  ('settings.templates.sms_segments', 'settings', 'Templates SMS segments label', 'SMS segments'),
  ('settings.templates.templates_list', 'settings', 'Templates list label', 'Templates'),
  ('settings.templates.title', 'settings', 'Templates page title', 'Message Templates'),
  ('widget.autoSelectedDefaultAgent', 'widget', 'Auto-selected default agent label', 'Auto-selected default agent'),
  ('widget.capabilities', 'widget', 'Widget capabilities section', 'Widget Capabilities'),
  ('widget.cap.aiChat', 'widget', 'AI chat capability', 'AI Chat'),
  ('widget.cap.aiChatDesc', 'widget', 'AI chat capability desc', 'Instant AI-powered responses'),
  ('widget.cap.anyWebsite', 'widget', 'Any website capability', 'Any Website'),
  ('widget.cap.anyWebsiteDesc', 'widget', 'Any website capability desc', 'Works on any HTML site'),
  ('widget.cap.knowledgeBase', 'widget', 'Knowledge base capability', 'Knowledge Base'),
  ('widget.cap.knowledgeBaseDesc', 'widget', 'Knowledge base capability desc', 'Answers from your KB'),
  ('widget.cap.mobileReady', 'widget', 'Mobile ready capability', 'Mobile Ready'),
  ('widget.cap.mobileReadyDesc', 'widget', 'Mobile ready capability desc', 'Full-screen on small screens'),
  ('widget.cap.orderTaking', 'widget', 'Order taking capability', 'Order Taking'),
  ('widget.cap.orderTakingDesc', 'widget', 'Order taking capability desc', 'Customers can place orders'),
  ('widget.cap.tableBooking', 'widget', 'Table booking capability', 'Table Booking'),
  ('widget.cap.tableBookingDesc', 'widget', 'Table booking capability desc', 'Reserve tables through chat'),
  ('widget.customAgent', 'widget', 'Custom agent label', 'Custom agent'),
  ('widget.livePreview', 'widget', 'Live preview label', 'Live widget preview'),
  ('widget.refresh', 'widget', 'Refresh button label', 'Refresh'),
  ('widget.reloadPreview', 'widget', 'Reload preview button', 'Reload preview'),
  ('widget.saveSettings', 'widget', 'Save settings button', 'Save Settings'),
  ('widget.setupSteps', 'widget', 'Setup steps section', 'Setup Steps'),
  ('widget.step1Desc', 'widget', 'Step 1 description', 'Use the copy button to copy your unique snippet'),
  ('widget.step1Title', 'widget', 'Step 1 title', 'Copy the embed code above'),
  ('widget.step2Desc', 'widget', 'Step 2 description', 'Add it to every page where you want the widget to appear'),
  ('widget.step2Title', 'widget', 'Step 2 title', 'Paste before </body> on your site'),
  ('widget.step3Desc', 'widget', 'Step 3 description', 'The widget loads automatically with your configured settings and chosen AI agent'),
  ('widget.step3Title', 'widget', 'Step 3 title', 'Save — done!'),
  ('widget.using', 'widget', 'Using label', 'Using')
ON CONFLICT (key) DO NOTHING;

-- ─── ADDITIONAL TRANSLATION KEYS (menuManagement + menu column fixes) ──────
INSERT INTO public.translation_keys (key, category, description, default_value) VALUES
  ('menu.addFirstMenuItemOrAdjustSearch', 'menu', 'Empty state message', 'Add your first menu item or adjust your search'),
  ('menu.categoryNamePlaceholder', 'menu', 'Category name placeholder', 'Category name *'),
  ('menu.colAvailable', 'menu', 'Available column header', 'Available'),
  ('menu.colCategory', 'menu', 'Category column header', 'Category'),
  ('menu.colDetails', 'menu', 'Details column header', 'Details'),
  ('menu.colItem', 'menu', 'Item column header', 'Item'),
  ('menu.colPrice', 'menu', 'Price column header', 'Price'),
  ('menu.item', 'menu', 'Item label', 'Item'),
  ('menu.items', 'menu', 'Items label', 'items'),
  ('menu.noMenuItemsFound', 'menu', 'No items found message', 'No menu items found'),
  ('menu.nonVeg', 'menu', 'Non-veg label', 'Non-Veg'),
  ('menu.searchItemsPlaceholder', 'menu', 'Search items placeholder', 'Search items…'),
  ('menu.vegetarian', 'menu', 'Vegetarian label', 'Vegetarian'),
  ('menuManagement.actions', 'menuManagement', 'Actions column header', 'Actions'),
  ('menuManagement.activeCategory', 'menuManagement', 'Active category label', 'Active Category'),
  ('menuManagement.activeCategoryDesc', 'menuManagement', 'Active category description', 'Category and its items are visible to customers'),
  ('menuManagement.addCategory', 'menuManagement', 'Add category button', 'Add Category'),
  ('menuManagement.addGroup', 'menuManagement', 'Add group button', 'Add Group'),
  ('menuManagement.addingApprovedItems', 'menuManagement', 'Adding approved items message', 'Adding approved items to your menu'),
  ('menuManagement.addItem', 'menuManagement', 'Add item button', 'Add Item'),
  ('menuManagement.addMenuItem', 'menuManagement', 'Add menu item button', 'Add Menu Item'),
  ('menuManagement.addModifier', 'menuManagement', 'Add modifier button', 'Add Modifier'),
  ('menuManagement.addModifierGroup', 'menuManagement', 'Add modifier group button', 'Add Modifier Group'),
  ('menuManagement.addNewCategory', 'menuManagement', 'Add new category button', 'Add New Category'),
  ('menuManagement.addNewItem', 'menuManagement', 'Add new item button', 'Add New Item'),
  ('menuManagement.addOption', 'menuManagement', 'Add option button', 'Add Option'),
  ('menuManagement.allItems', 'menuManagement', 'All items option', 'All items'),
  ('menuManagement.approveAll', 'menuManagement', 'Approve all button', 'Approve All Valid'),
  ('menuManagement.approved', 'menuManagement', 'Approved label', 'approved'),
  ('menuManagement.approvedCount', 'menuManagement', 'Approved count label', '{{count}} approved'),
  ('menuManagement.availability', 'menuManagement', 'Availability section', 'Availability'),
  ('menuManagement.availableHelpText', 'menuManagement', 'Available help text', 'When toggled off, customers cannot add this item to their cart'),
  ('menuManagement.availableOnMenu', 'menuManagement', 'Available on menu label', 'Available on Menu'),
  ('menuManagement.calories', 'menuManagement', 'Calories label', 'Calories'),
  ('menuManagement.category', 'menuManagement', 'Category label', 'Category'),
  ('menuManagement.categoryAdded', 'menuManagement', 'Category added success', 'Category added'),
  ('menuManagement.categoryDeleted', 'menuManagement', 'Category deleted success', 'Category deleted'),
  ('menuManagement.categoryDescription', 'menuManagement', 'Category description label', 'Category Description'),
  ('menuManagement.categoryDetails', 'menuManagement', 'Category details section', 'Category Details'),
  ('menuManagement.categoryLabel', 'menuManagement', 'Category label', 'Category'),
  ('menuManagement.categoryName', 'menuManagement', 'Category name label', 'Category Name'),
  ('menuManagement.categoryNamePlaceholder', 'menuManagement', 'Category name placeholder', 'Category name *'),
  ('menuManagement.categoryUpdated', 'menuManagement', 'Category updated success', 'Category updated'),
  ('menuManagement.checkbox', 'menuManagement', 'Checkbox type label', 'Checkbox'),
  ('menuManagement.createItem', 'menuManagement', 'Create item button', 'Create Item'),
  ('menuManagement.default', 'menuManagement', 'Default label', 'Default'),
  ('menuManagement.def', 'menuManagement', 'Def abbreviation', 'Def'),
  ('menuManagement.deleteCategory', 'menuManagement', 'Delete category button', 'Delete Category'),
  ('menuManagement.deleteItem', 'menuManagement', 'Delete item button', 'Delete Item'),
  ('menuManagement.deleteCategoryConfirm', 'menuManagement', 'Delete category confirm message', 'Delete "{{name}}" and all its items?'),
  ('menuManagement.deleteItemConfirm', 'menuManagement', 'Delete item confirm message', 'Delete "{{name}}" from your menu?'),
  ('menuManagement.deltaPrice', 'menuManagement', 'Delta price placeholder', '₹ delta'),
  ('menuManagement.description', 'menuManagement', 'Description label', 'Description'),
  ('menuManagement.descriptionPlaceholder', 'menuManagement', 'Description placeholder', 'Describe this item…'),
  ('menuManagement.dietaryInfo', 'menuManagement', 'Dietary info section', 'Dietary Info'),
  ('menuManagement.dragDropPrompt', 'menuManagement', 'Drag and drop prompt', 'Drag & drop or click to choose a CSV or JSON file'),
  ('menuManagement.editCategory', 'menuManagement', 'Edit category button', 'Edit Category'),
  ('menuManagement.editItem', 'menuManagement', 'Edit item button', 'Edit Item'),
  ('menuManagement.errors.addFailed', 'menuManagement', 'Add failed error', 'Failed to add item'),
  ('menuManagement.errors.deleteFailed', 'menuManagement', 'Delete failed error', 'Failed to delete'),
  ('menuManagement.errors.loadFailed', 'menuManagement', 'Load failed error', 'Failed to load menu'),
  ('menuManagement.errors.saveFailed', 'menuManagement', 'Save failed error', 'Failed to save changes'),
  ('menuManagement.extraPrice', 'menuManagement', 'Extra price placeholder', '₹ extra'),
  ('menuManagement.filterByCategory', 'menuManagement', 'Filter by category label', 'Filter by category'),
  ('menuManagement.free', 'menuManagement', 'Free label', 'Free'),
  ('menuManagement.gluten', 'menuManagement', 'Gluten label', 'Gluten'),
  ('menuManagement.helpText', 'menuManagement', 'Help text', 'Upload a CSV or JSON file to bulk-import menu items'),
  ('menuManagement.hidden', 'menuManagement', 'Hidden status', 'Hidden'),
  ('menuManagement.imageUrl', 'menuManagement', 'Image URL label', 'Image URL'),
  ('menuManagement.importItems', 'menuManagement', 'Import items button', 'Import Items'),
  ('menuManagement.inactive', 'menuManagement', 'Inactive label', 'Inactive'),
  ('menuManagement.inactiveCategory', 'menuManagement', 'Inactive category label', 'Inactive Category'),
  ('menuManagement.inactiveCategoryDesc', 'menuManagement', 'Inactive category description', 'Category is hidden from the menu'),
  ('menuManagement.invalidItems', 'menuManagement', 'Invalid items label', 'Invalid'),
  ('menuManagement.isVeg', 'menuManagement', 'Is veg label', 'Vegetarian'),
  ('menuManagement.item', 'menuManagement', 'Item label', 'Item'),
  ('menuManagement.itemDetails', 'menuManagement', 'Item details section', 'Item Details'),
  ('menuManagement.itemName', 'menuManagement', 'Item name label', 'Item Name'),
  ('menuManagement.itemNamePlaceholder', 'menuManagement', 'Item name placeholder', 'e.g. Margherita Pizza'),
  ('menuManagement.items', 'menuManagement', 'Items label', 'Items'),
  ('menuManagement.itemSaved', 'menuManagement', 'Item saved success', 'Item saved'),
  ('menuManagement.itemsCount', 'menuManagement', 'Items count label', '{{count}} item(s)'),
  ('menuManagement.loadingMenu', 'menuManagement', 'Loading menu message', 'Loading menu…'),
  ('menuManagement.max', 'menuManagement', 'Max label', 'Max'),
  ('menuManagement.min', 'menuManagement', 'Min label', 'Min'),
  ('menuManagement.modifierGroupName', 'menuManagement', 'Modifier group name label', 'Group Name'),
  ('menuManagement.modifierGroupNamePlaceholder', 'menuManagement', 'Modifier group name placeholder', 'e.g. Size, Extras, Spice level'),
  ('menuManagement.modifierGroups', 'menuManagement', 'Modifier groups section', 'Modifier Groups'),
  ('menuManagement.modifierName', 'menuManagement', 'Modifier name label', 'Modifier Name'),
  ('menuManagement.modifierPrice', 'menuManagement', 'Modifier price label', 'Price'),
  ('menuManagement.modifiers', 'menuManagement', 'Modifiers section', 'Modifiers'),
  ('menuManagement.newCategory', 'menuManagement', 'New category label', 'New Category'),
  ('menuManagement.noCategories', 'menuManagement', 'No categories message', 'No categories yet'),
  ('menuManagement.noCategoriesFound', 'menuManagement', 'No categories found message', 'No categories found'),
  ('menuManagement.noItems', 'menuManagement', 'No items message', 'No items yet'),
  ('menuManagement.noLimit', 'menuManagement', 'No limit placeholder', 'No limit'),
  ('menuManagement.noModifiers', 'menuManagement', 'No modifiers message', 'No modifiers yet'),
  ('menuManagement.nonVeg', 'menuManagement', 'Non-veg label', 'Non-Veg'),
  ('menuManagement.optionName', 'menuManagement', 'Option name placeholder', 'Option name'),
  ('menuManagement.pageTitle', 'menuManagement', 'Page title', 'Menu Management'),
  ('menuManagement.pending', 'menuManagement', 'Pending status', 'Pending'),
  ('menuManagement.pendingCount', 'menuManagement', 'Pending count label', '{{count}} pending review'),
  ('menuManagement.photo', 'menuManagement', 'Photo label', 'Photo'),
  ('menuManagement.prepTime', 'menuManagement', 'Prep time label', 'Prep Time (min)'),
  ('menuManagement.price', 'menuManagement', 'Price label', 'Price'),
  ('menuManagement.pricePlaceholder', 'menuManagement', 'Price placeholder', '0.00'),
  ('menuManagement.radio', 'menuManagement', 'Radio type label', 'Radio'),
  ('menuManagement.rejected', 'menuManagement', 'Rejected label', 'rejected'),
  ('menuManagement.rejectedCount', 'menuManagement', 'Rejected count label', '{{count}} rejected'),
  ('menuManagement.required', 'menuManagement', 'Required label', 'Required'),
  ('menuManagement.requiredHelpText', 'menuManagement', 'Required help text', 'Customer must make a selection'),
  ('menuManagement.save', 'menuManagement', 'Save button', 'Save'),
  ('menuManagement.saveItemFirst', 'menuManagement', 'Save item first notice', 'Save item first'),
  ('menuManagement.searchItems', 'menuManagement', 'Search items label', 'Search items…'),
  ('menuManagement.selectionType', 'menuManagement', 'Selection type label', 'Selection Type'),
  ('menuManagement.spiceLevel', 'menuManagement', 'Spice level label', 'Spice Level'),
  ('menuManagement.startOver', 'menuManagement', 'Start over button', 'Start Over'),
  ('menuManagement.status', 'menuManagement', 'Status label', 'Status'),
  ('menuManagement.step1', 'menuManagement', 'Upload step 1', 'Upload a CSV (columns: name, price, category, description) or JSON array'),
  ('menuManagement.step2', 'menuManagement', 'Upload step 2', 'Each row is parsed and shown for review'),
  ('menuManagement.step3', 'menuManagement', 'Upload step 3', 'Approve, edit, or reject individual items'),
  ('menuManagement.step4', 'menuManagement', 'Upload step 4', 'Approved items are saved to your menu instantly'),
  ('menuManagement.uncategorised', 'menuManagement', 'Uncategorised label', 'Uncategorised'),
  ('menuManagement.uncategorized', 'menuManagement', 'Uncategorized label', 'Uncategorized'),
  ('menuManagement.updateItem', 'menuManagement', 'Update item button', 'Update Item'),
  ('menuManagement.uploadAnother', 'menuManagement', 'Upload another button', 'Upload Another'),
  ('menuManagement.uploadComplete', 'menuManagement', 'Upload complete message', 'Upload complete!'),
  ('menuManagement.uploadFile', 'menuManagement', 'Upload file button', 'Upload File'),
  ('menuManagement.uploadItemPhoto', 'menuManagement', 'Upload item photo button', 'Upload item photo'),
  ('menuManagement.uploadLimits', 'menuManagement', 'Upload limits notice', 'JPG, PNG — max 5MB. Recommended: 800x600px'),
  ('menuManagement.uploadMenuFile', 'menuManagement', 'Upload menu file label', 'Upload your menu file'),
  ('menuManagement.uploadPrompt', 'menuManagement', 'Upload prompt', 'Drag & drop or click to choose a CSV or JSON file'),
  ('menuManagement.vegetarian', 'menuManagement', 'Vegetarian label', 'Vegetarian'),
  ('menuManagement.visibility', 'menuManagement', 'Visibility section', 'Visibility')
ON CONFLICT (key) DO NOTHING;


  -- ─── COMPREHENSIVE TRANSLATION KEYS (all dashboard pages) ──────────────────
  INSERT INTO public.translation_keys (key, category, description, default_value) VALUES
    ('phoneNumbers.agents.main', 'phoneNumbers', 'agents.main', 'Main Voice Agent'),
  ('phoneNumbers.agents.ukBranch', 'phoneNumbers', 'agents.ukBranch', 'UK Branch Agent'),
  ('phoneNumbers.agents.unassigned', 'phoneNumbers', 'agents.unassigned', 'Unassigned'),
  ('phoneNumbers.routing.voicemail', 'phoneNumbers', 'routing.voicemail', 'Ring for 30s then voicemail'),
  ('phoneNumbers.routing.fallback', 'phoneNumbers', 'routing.fallback', 'Ring for 30s then fallback number'),
  ('phoneNumbers.routing.alwaysVoicemail', 'phoneNumbers', 'routing.alwaysVoicemail', 'Always voicemail'),
  ('phoneNumbers.routing.alwaysForward', 'phoneNumbers', 'routing.alwaysForward', 'Always forward to fallback'),
  ('phoneNumbers.detail.backLink', 'phoneNumbers', 'detail.backLink', 'Back to Phone Numbers'),
  ('phoneNumbers.countries.us', 'phoneNumbers', 'countries.us', 'United States'),
  ('phoneNumbers.typePurchased', 'phoneNumbers', 'typePurchased', 'Purchased'),
  ('phoneNumbers.statusActive', 'phoneNumbers', 'statusActive', 'Active'),
  ('phoneNumbers.detail.monthlyCalls', 'phoneNumbers', 'detail.monthlyCalls', 'Monthly calls'),
  ('phoneNumbers.detail.assignTitle', 'phoneNumbers', 'detail.assignTitle', 'Assign to AI Agent'),
  ('phoneNumbers.detail.aiAgent', 'phoneNumbers', 'detail.aiAgent', 'AI Agent'),
  ('phoneNumbers.detail.aiAgentHint', 'phoneNumbers', 'detail.aiAgentHint', 'The selected AI agent will handle all inbound calls to this number.'),
  ('phoneNumbers.detail.routingTitle', 'phoneNumbers', 'detail.routingTitle', 'Call Routing Rules'),
  ('phoneNumbers.detail.whenUnanswered', 'phoneNumbers', 'detail.whenUnanswered', 'When AI cannot answer'),
  ('phoneNumbers.detail.fallbackNumber', 'phoneNumbers', 'detail.fallbackNumber', 'Fallback Phone Number'),
  ('phoneNumbers.detail.fallbackHint', 'phoneNumbers', 'detail.fallbackHint', 'Used when routing rule includes "fallback number"'),
  ('phoneNumbers.detail.voicemailTitle', 'phoneNumbers', 'detail.voicemailTitle', 'Voicemail'),
  ('phoneNumbers.detail.enableVoicemail', 'phoneNumbers', 'detail.enableVoicemail', 'Enable Voicemail'),
  ('phoneNumbers.detail.voicemailHint', 'phoneNumbers', 'detail.voicemailHint', 'Record voicemail when calls go unanswered'),
  ('common.saved', 'common', 'saved', 'Saved!'),
  ('phoneNumbers.detail.saveButton', 'phoneNumbers', 'detail.saveButton', 'Save Configuration'),
  ('phoneNumbers.purchasedSuccessfully', 'phoneNumbers', 'purchasedSuccessfully', 'Number purchased successfully!'),
  ('phoneNumbers.purchaseFailed', 'phoneNumbers', 'purchaseFailed', 'Purchase failed'),
  ('phoneNumbers.buy.successTitle', 'phoneNumbers', 'buy.successTitle', 'Number Purchased!'),
  ('phoneNumbers.buy.successMessage', 'phoneNumbers', 'buy.successMessage', 'Your new number is active and webhooks are configured:'),
  ('phoneNumbers.buy.manageNumbers', 'phoneNumbers', 'buy.manageNumbers', 'Manage Numbers'),
  ('phoneNumbers.buy.viewAllNumbers', 'phoneNumbers', 'buy.viewAllNumbers', 'View All Numbers'),
  ('phoneNumbers.buy.backLink', 'phoneNumbers', 'buy.backLink', 'Back to Phone Numbers'),
  ('phoneNumbers.buy.searchTitle', 'phoneNumbers', 'buy.searchTitle', 'Search Available Numbers'),
  ('phoneNumbers.buy.country', 'phoneNumbers', 'buy.country', 'Country'),
  ('phoneNumbers.buy.areaCode', 'phoneNumbers', 'buy.areaCode', 'Area Code (optional)'),
  ('phoneNumbers.buy.numberType', 'phoneNumbers', 'buy.numberType', 'Number Type'),
  ('phoneNumbers.buy.typeLocal', 'phoneNumbers', 'buy.typeLocal', 'Local'),
  ('phoneNumbers.buy.typeTollFree', 'phoneNumbers', 'buy.typeTollFree', 'Toll-Free'),
  ('phoneNumbers.buy.typeMobile', 'phoneNumbers', 'buy.typeMobile', 'Mobile'),
  ('phoneNumbers.buy.searching', 'phoneNumbers', 'buy.searching', 'Searching...'),
  ('phoneNumbers.buy.searchButton', 'phoneNumbers', 'buy.searchButton', 'Search Numbers'),
  ('phoneNumbers.buy.availableNumbers', 'phoneNumbers', 'buy.availableNumbers', 'Available Numbers'),
  ('phoneNumbers.buy.found', 'phoneNumbers', 'buy.found', 'found'),
  ('phoneNumbers.buy.noNumbersFound', 'phoneNumbers', 'buy.noNumbersFound', 'No numbers found. Try a different area code or country.'),
  ('phoneNumbers.buy.purchasing', 'phoneNumbers', 'buy.purchasing', 'Purchasing...'),
  ('phoneNumbers.buy.purchaseButton', 'phoneNumbers', 'buy.purchaseButton', 'Purchase'),
  ('phoneNumbers.sip.errors.displayNameRequired', 'phoneNumbers', 'sip.errors.displayNameRequired', 'Display name is required'),
  ('phoneNumbers.sip.errors.serverRequired', 'phoneNumbers', 'sip.errors.serverRequired', 'SIP server address is required'),
  ('phoneNumbers.sip.errors.serverInvalid', 'phoneNumbers', 'sip.errors.serverInvalid', 'Please enter a valid hostname or IP address'),
  ('phoneNumbers.sip.errors.usernameRequired', 'phoneNumbers', 'sip.errors.usernameRequired', 'SIP username is required'),
  ('phoneNumbers.sip.errors.passwordRequired', 'phoneNumbers', 'sip.errors.passwordRequired', 'SIP password is required'),
  ('phoneNumbers.sip.errors.passwordTooShort', 'phoneNumbers', 'sip.errors.passwordTooShort', 'Password must be at least 4 characters'),
  ('phoneNumbers.sip.errors.portRequired', 'phoneNumbers', 'sip.errors.portRequired', 'Port is required'),
  ('phoneNumbers.sip.errors.portInvalid', 'phoneNumbers', 'sip.errors.portInvalid', 'Port must be between 1 and 65535'),
  ('phoneNumbers.sip.backLink', 'phoneNumbers', 'sip.backLink', 'Back to Phone Numbers'),
  ('phoneNumbers.sip.infoTitle', 'phoneNumbers', 'sip.infoTitle', 'SIP Trunk Integration'),
  ('phoneNumbers.sip.infoText', 'phoneNumbers', 'sip.infoText', 'Use your existing SIP trunk from providers like Twilio, Vonage, Bandwidth, or any SIP-compatible provider. Your AI agent will use this number to make and receive calls.'),
  ('phoneNumbers.sip.configTitle', 'phoneNumbers', 'sip.configTitle', 'SIP Trunk Configuration'),
  ('phoneNumbers.sip.displayName', 'phoneNumbers', 'sip.displayName', 'Display Name'),
  ('phoneNumbers.sip.displayNameHint', 'phoneNumbers', 'sip.displayNameHint', 'A friendly name to identify this trunk'),
  ('phoneNumbers.sip.sipServer', 'phoneNumbers', 'sip.sipServer', 'SIP Server / Host'),
  ('phoneNumbers.sip.username', 'phoneNumbers', 'sip.username', 'Username'),
  ('phoneNumbers.sip.password', 'phoneNumbers', 'sip.password', 'Password'),
  ('phoneNumbers.sip.port', 'phoneNumbers', 'sip.port', 'Port'),
  ('phoneNumbers.sip.transport', 'phoneNumbers', 'sip.transport', 'Transport Protocol'),
  ('common.default', 'common', 'default', 'default'),
  ('phoneNumbers.sip.transportTls', 'phoneNumbers', 'sip.transportTls', 'encrypted'),
  ('phoneNumbers.sip.activeHint', 'phoneNumbers', 'sip.activeHint', 'Enable this SIP trunk for the AI agent'),
  ('phoneNumbers.sip.testTitle', 'phoneNumbers', 'sip.testTitle', 'Test Connection'),
  ('phoneNumbers.sip.testHint', 'phoneNumbers', 'sip.testHint', 'Verify your SIP credentials before saving'),
  ('common.testing', 'common', 'testing', 'Testing...'),
  ('phoneNumbers.sip.testButton', 'phoneNumbers', 'sip.testButton', 'Test Connection'),
  ('phoneNumbers.sip.testSuccess', 'phoneNumbers', 'sip.testSuccess', 'Connection successful! SIP trunk is reachable.'),
  ('phoneNumbers.sip.testFailed', 'phoneNumbers', 'sip.testFailed', 'Connection failed. Check your server address and credentials.'),
  ('phoneNumbers.sip.saveButton', 'phoneNumbers', 'sip.saveButton', 'Save SIP Trunk'),
  ('phoneNumbers.stats.totalNumbers', 'phoneNumbers', 'stats.totalNumbers', 'Total Numbers'),
  ('phoneNumbers.stats.active', 'phoneNumbers', 'stats.active', 'Active'),
  ('phoneNumbers.stats.monthlyCalls', 'phoneNumbers', 'stats.monthlyCalls', 'Monthly Calls'),
  ('phoneNumbers.stats.sipTrunks', 'phoneNumbers', 'stats.sipTrunks', 'SIP Trunks'),
  ('phoneNumbers.addSipTrunk', 'phoneNumbers', 'addSipTrunk', 'Add SIP Trunk'),
  ('phoneNumbers.buyPhoneNumber', 'phoneNumbers', 'buyPhoneNumber', 'Buy Phone Number'),
  ('phoneNumbers.loading', 'phoneNumbers', 'loading', 'Loading phone numbers…'),
  ('phoneNumbers.table.number', 'phoneNumbers', 'table.number', 'Number'),
  ('phoneNumbers.table.type', 'phoneNumbers', 'table.type', 'Type'),
  ('phoneNumbers.table.status', 'phoneNumbers', 'table.status', 'Status'),
  ('phoneNumbers.table.created', 'phoneNumbers', 'table.created', 'Created'),
  ('phoneNumbers.table.actions', 'phoneNumbers', 'table.actions', 'Actions'),
  ('phoneNumbers.typeSip', 'phoneNumbers', 'typeSip', 'SIP Trunk'),
  ('phoneNumbers.statusInactive', 'phoneNumbers', 'statusInactive', 'Inactive'),
  ('common.remove', 'common', 'remove', 'Remove'),
  ('phoneNumbers.noNumbersFound', 'phoneNumbers', 'noNumbersFound', 'No phone numbers found'),
  ('phoneNumbers.noNumbersHint', 'phoneNumbers', 'noNumbersHint', 'Buy a number or add a SIP trunk to get started'),
  ('phoneNumbers.infoTitle', 'phoneNumbers', 'infoTitle', 'How phone numbers work'),
  ('phoneNumbers.infoText', 'phoneNumbers', 'infoText', 'Purchased numbers are hosted by RestroAgent. SIP trunks use your existing telephony provider. Both types can be assigned to your AI voice agent to handle inbound and outbound calls.'),
  ('aiAgentConfig.active', 'aiAgentConfig', 'active', 'Active'),
  ('aiAgentConfig.inactive', 'aiAgentConfig', 'inactive', 'Inactive'),
  ('aiAgentConfig.edit', 'aiAgentConfig', 'edit', 'Edit'),
  ('aiAgentConfig.delete', 'aiAgentConfig', 'delete', 'Delete'),
  ('aiAgentConfig.preview.title', 'aiAgentConfig', 'preview.title', 'Agent Preview'),
  ('aiAgentConfig.preview.subtitle', 'aiAgentConfig', 'preview.subtitle', 'Preview how {{name}} will interact'),
  ('aiAgentConfig.preview.theAgent', 'aiAgentConfig', 'preview.theAgent', 'the agent'),
  ('aiAgentConfig.preview.systemPrompt', 'aiAgentConfig', 'preview.systemPrompt', 'System Prompt'),
  ('aiAgentConfig.preview.sampleFlow', 'aiAgentConfig', 'preview.sampleFlow', 'Sample flow'),
  ('aiAgentConfig.preview.sampleUserMsg', 'aiAgentConfig', 'preview.sampleUserMsg', 'Hi, can I place an order?'),
  ('aiAgentConfig.preview.empty', 'aiAgentConfig', 'preview.empty', 'Add a greeting or system prompt to see a preview'),
  ('aiAgentConfig.capabilities.order_taking', 'aiAgentConfig', 'capabilities.order_taking', 'Order Taking'),
  ('aiAgentConfig.capabilities.reservation_booking', 'aiAgentConfig', 'capabilities.reservation_booking', 'Reservation Booking'),
  ('aiAgentConfig.capabilities.escalation', 'aiAgentConfig', 'capabilities.escalation', 'Escalation to Human'),
  ('aiAgentConfig.errors.loadProviders', 'aiAgentConfig', 'errors.loadProviders', 'Failed to load providers: '),
  ('aiAgentConfig.errors.selectVoice', 'aiAgentConfig', 'errors.selectVoice', 'Select a voice first'),
  ('aiAgentConfig.errors.playbackFailed', 'aiAgentConfig', 'errors.playbackFailed', 'Audio playback failed'),
  ('aiAgentConfig.errors.previewFailed', 'aiAgentConfig', 'errors.previewFailed', 'Preview failed'),
  ('aiAgentConfig.syncSuccess', 'aiAgentConfig', 'syncSuccess', 'Synced {{count}} models from OpenRouter'),
  ('aiAgentConfig.errors.syncFailed', 'aiAgentConfig', 'errors.syncFailed', 'Sync failed'),
  ('aiAgentConfig.errors.nameRequired', 'aiAgentConfig', 'errors.nameRequired', 'Agent name is required'),
  ('aiAgentConfig.errors.channelRequired', 'aiAgentConfig', 'errors.channelRequired', 'At least one channel (Voice or Chat) must be enabled'),
  ('aiAgentConfig.agentUpdated', 'aiAgentConfig', 'agentUpdated', 'Agent updated'),
  ('aiAgentConfig.agentCreated', 'aiAgentConfig', 'agentCreated', 'Agent created'),
  ('aiAgentConfig.errors.saveFailed', 'aiAgentConfig', 'errors.saveFailed', 'Save failed'),
  ('aiAgentConfig.editAgent', 'aiAgentConfig', 'editAgent', 'Edit Agent'),
  ('aiAgentConfig.newAgent', 'aiAgentConfig', 'newAgent', 'New Agent'),
  ('aiAgentConfig.sections.identity', 'aiAgentConfig', 'sections.identity', 'Identity'),
  ('aiAgentConfig.agentName', 'aiAgentConfig', 'agentName', 'Agent Name *'),
  ('aiAgentConfig.placeholders.agentName', 'aiAgentConfig', 'placeholders.agentName', 'e.g. Orders Bot'),
  ('aiAgentConfig.description', 'aiAgentConfig', 'description', 'Description'),
  ('aiAgentConfig.setDefault', 'aiAgentConfig', 'setDefault', 'Set as default agent'),
  ('aiAgentConfig.sections.channels', 'aiAgentConfig', 'sections.channels', 'Channels'),
  ('aiAgentConfig.channelsSubtitle', 'aiAgentConfig', 'channelsSubtitle', 'Enable the channels this agent should handle. At least one must be active.'),
  ('aiAgentConfig.channelVoice', 'aiAgentConfig', 'channelVoice', 'Voice'),
  ('aiAgentConfig.channelVoiceDesc', 'aiAgentConfig', 'channelVoiceDesc', 'Phone calls & SIP'),
  ('aiAgentConfig.channelChat', 'aiAgentConfig', 'channelChat', 'Chat'),
  ('aiAgentConfig.channelChatDesc', 'aiAgentConfig', 'channelChatDesc', 'Web & in-app chat'),
  ('aiAgentConfig.sections.llm', 'aiAgentConfig', 'sections.llm', 'LLM Provider'),
  ('aiAgentConfig.llmModel', 'aiAgentConfig', 'llmModel', 'LLM Model'),
  ('aiAgentConfig.syncModelsTitle', 'aiAgentConfig', 'syncModelsTitle', 'Fetch latest models from OpenRouter API'),
  ('aiAgentConfig.syncing', 'aiAgentConfig', 'syncing', 'Syncing...'),
  ('aiAgentConfig.syncModels', 'aiAgentConfig', 'syncModels', 'Sync Models'),
  ('aiAgentConfig.placeholders.selectLlm', 'aiAgentConfig', 'placeholders.selectLlm', 'Select an LLM model'),
  ('aiAgentConfig.sections.voice', 'aiAgentConfig', 'sections.voice', 'Voice Provider'),
  ('aiAgentConfig.voiceProvider', 'aiAgentConfig', 'voiceProvider', 'Voice Provider'),
  ('aiAgentConfig.placeholders.selectProvider', 'aiAgentConfig', 'placeholders.selectProvider', 'Select a provider'),
  ('aiAgentConfig.voice', 'aiAgentConfig', 'voice', 'Voice'),
  ('aiAgentConfig.placeholders.selectVoice', 'aiAgentConfig', 'placeholders.selectVoice', 'Select a voice'),
  ('aiAgentConfig.stopPreview', 'aiAgentConfig', 'stopPreview', 'Stop preview'),
  ('aiAgentConfig.playPreview', 'aiAgentConfig', 'playPreview', 'Play voice preview'),
  ('aiAgentConfig.loading', 'aiAgentConfig', 'loading', 'Loading'),
  ('aiAgentConfig.stop', 'aiAgentConfig', 'stop', 'Stop'),
  ('aiAgentConfig.play', 'aiAgentConfig', 'play', 'Play'),
  ('aiAgentConfig.realtimeModel', 'aiAgentConfig', 'realtimeModel', 'Realtime Model'),
  ('aiAgentConfig.realtimeModels.best', 'aiAgentConfig', 'realtimeModels.best', 'GPT Realtime 1.5 — Best Quality'),
  ('aiAgentConfig.realtimeModels.mini', 'aiAgentConfig', 'realtimeModels.mini', 'GPT Realtime Mini — Cost-Efficient'),
  ('aiAgentConfig.realtimeModels.standard', 'aiAgentConfig', 'realtimeModels.standard', 'GPT Realtime (Standard)'),
  ('aiAgentConfig.realtimeModels.audio', 'aiAgentConfig', 'realtimeModels.audio', 'GPT Audio 1.5 — Audio-Optimised'),
  ('aiAgentConfig.sections.vad', 'aiAgentConfig', 'sections.vad', 'Voice Activity Detection'),
  ('aiAgentConfig.detectionThreshold', 'aiAgentConfig', 'detectionThreshold', 'Detection Threshold'),
  ('aiAgentConfig.moreSensitive', 'aiAgentConfig', 'moreSensitive', 'More sensitive (0)'),
  ('aiAgentConfig.lessSensitive', 'aiAgentConfig', 'lessSensitive', 'Less sensitive (1)'),
  ('aiAgentConfig.prefixPadding', 'aiAgentConfig', 'prefixPadding', 'Prefix Padding (ms)'),
  ('aiAgentConfig.prefixPaddingDesc', 'aiAgentConfig', 'prefixPaddingDesc', 'Audio kept before speech'),
  ('aiAgentConfig.silenceDuration', 'aiAgentConfig', 'silenceDuration', 'Silence Duration (ms)'),
  ('aiAgentConfig.silenceDurationDesc', 'aiAgentConfig', 'silenceDurationDesc', 'Pause before turn ends'),
  ('aiAgentConfig.sections.scripts', 'aiAgentConfig', 'sections.scripts', 'Scripts'),
  ('aiAgentConfig.greetingScript', 'aiAgentConfig', 'greetingScript', 'Greeting Script'),
  ('aiAgentConfig.closingScript', 'aiAgentConfig', 'closingScript', 'Closing Script'),
  ('aiAgentConfig.systemPrompt', 'aiAgentConfig', 'systemPrompt', 'System Prompt'),
  ('aiAgentConfig.sections.capabilities', 'aiAgentConfig', 'sections.capabilities', 'Capabilities'),
  ('aiAgentConfig.sections.fallback', 'aiAgentConfig', 'sections.fallback', 'Fallback Rules'),
  ('aiAgentConfig.addRule', 'aiAgentConfig', 'addRule', 'Add Rule'),
  ('aiAgentConfig.add', 'aiAgentConfig', 'add', 'Add'),
  ('aiAgentConfig.noFallbackRules', 'aiAgentConfig', 'noFallbackRules', 'No fallback rules configured. Add rules to handle edge cases.'),
  ('aiAgentConfig.save', 'aiAgentConfig', 'save', 'Save'),
  ('aiAgentConfig.cancel', 'aiAgentConfig', 'cancel', 'Cancel'),
  ('aiAgentConfig.saving', 'aiAgentConfig', 'saving', 'Saving...'),
  ('aiAgentConfig.updateAgent', 'aiAgentConfig', 'updateAgent', 'Update Agent'),
  ('aiAgentConfig.createAgent', 'aiAgentConfig', 'createAgent', 'Create Agent'),
  ('aiAgentConfig.placeholders.fallbackTrigger', 'aiAgentConfig', 'placeholders.fallbackTrigger', 'Trigger condition'),
  ('aiAgentConfig.placeholders.fallbackAction', 'aiAgentConfig', 'placeholders.fallbackAction', 'Action to take'),
  ('aiAgentConfig.priorities.high', 'aiAgentConfig', 'priorities.high', 'High'),
  ('aiAgentConfig.priorities.medium', 'aiAgentConfig', 'priorities.medium', 'Medium'),
  ('aiAgentConfig.priorities.low', 'aiAgentConfig', 'priorities.low', 'Low'),
  ('nav.aiConfiguration', 'nav', 'aiConfiguration', 'AI Agents'),
  ('nav.aiAgentsSubtitle', 'nav', 'aiAgentsSubtitle', 'Create and manage your AI agents'),
  ('agent.failedToLoad', 'agent', 'failedToLoad', 'Failed to load agents'),
  ('agent.failedToToggle', 'agent', 'failedToToggle', 'Failed to toggle'),
  ('agent.confirmDelete', 'agent', 'confirmDelete', 'Click delete again to confirm'),
  ('agent.deleted', 'agent', 'deleted', 'Agent deleted'),
  ('agent.failedToDelete', 'agent', 'failedToDelete', 'Failed to delete'),
  ('agent.searchPlaceholder', 'agent', 'searchPlaceholder', 'Search agents...'),
  ('agent.newAgent', 'agent', 'newAgent', 'New Agent'),
  ('agent.noAgentsYet', 'agent', 'noAgentsYet', 'No agents yet'),
  ('agent.noAgentsMatch', 'agent', 'noAgentsMatch', 'No agents match your search'),
  ('agent.createFirstAgent', 'agent', 'createFirstAgent', 'Create your first AI agent to get started'),
  ('common.tryDifferentSearch', 'common', 'tryDifferentSearch', 'Try a different search term'),
  ('agent.createAgent', 'agent', 'createAgent', 'Create Agent'),
  ('agent.createToPreview', 'agent', 'createToPreview', 'Create an agent to see a preview'),
  ('alertSettings.title', 'alertSettings', 'title', 'Alert Settings'),
  ('alertSettings.subtitle', 'alertSettings', 'subtitle', 'Configure real-time order and booking alert behavior'),
  ('alertSettings.errorLoad', 'alertSettings', 'errorLoad', 'Failed to load alert settings'),
  ('alertSettings.successSave', 'alertSettings', 'successSave', 'Alert settings saved'),
  ('alertSettings.errorSave', 'alertSettings', 'errorSave', 'Failed to save settings. Please try again.'),
  ('alertSettings.loading', 'alertSettings', 'loading', 'Loading settings…'),
  ('alertSettings.backToDashboard', 'alertSettings', 'backToDashboard', 'Back to Dashboard'),
  ('alertSettings.previewAlert', 'alertSettings', 'previewAlert', 'Preview Alert'),
  ('alertSettings.saving', 'alertSettings', 'saving', 'Saving…'),
  ('alertSettings.saved', 'alertSettings', 'saved', 'Saved!'),
  ('alertSettings.saveSettings', 'alertSettings', 'saveSettings', 'Save Settings'),
  ('alertSettings.soundNotifications', 'alertSettings', 'soundNotifications', 'Sound Notifications'),
  ('alertSettings.enableSoundAlerts', 'alertSettings', 'enableSoundAlerts', 'Enable Sound Alerts'),
  ('alertSettings.enableSoundAlertsDesc', 'alertSettings', 'enableSoundAlertsDesc', 'Play a sound when new alerts arrive'),
  ('alertSettings.alertVolume', 'alertSettings', 'alertVolume', 'Alert Volume'),
  ('alertSettings.autoDismissTimer', 'alertSettings', 'autoDismissTimer', 'Auto-Dismiss Timer'),
  ('alertSettings.dismissAlertsAfter', 'alertSettings', 'dismissAlertsAfter', 'Dismiss alerts after'),
  ('alertSettings.autoDismissDesc', 'alertSettings', 'autoDismissDesc', 'Alerts will automatically dismiss after {seconds} seconds if not acted upon'),
  ('alertSettings.alertTypes', 'alertSettings', 'alertTypes', 'Alert Types'),
  ('alertSettings.newOrders', 'alertSettings', 'newOrders', 'New Orders'),
  ('alertSettings.newOrdersDesc', 'alertSettings', 'newOrdersDesc', 'Show alert when a new order is placed'),
  ('alertSettings.newBookings', 'alertSettings', 'newBookings', 'New Bookings'),
  ('alertSettings.newBookingsDesc', 'alertSettings', 'newBookingsDesc', 'Show alert when a table is reserved'),
  ('alertSettings.aiEscalations', 'alertSettings', 'aiEscalations', 'AI Escalations'),
  ('alertSettings.aiEscalationsDesc', 'alertSettings', 'aiEscalationsDesc', 'Show alert when AI hands off to staff'),
  ('alertSettings.browserNotifications', 'alertSettings', 'browserNotifications', 'Browser Notifications'),
  ('alertSettings.enableBrowserNotifications', 'alertSettings', 'enableBrowserNotifications', 'Enable Browser Notifications'),
  ('alertSettings.enableBrowserNotificationsDesc', 'alertSettings', 'enableBrowserNotificationsDesc', 'Receive alerts even when the tab is not in focus'),
  ('alertSettings.browserNotificationsWarning', 'alertSettings', 'browserNotificationsWarning', 'Browser will request notification permission when you save these settings.'),
  ('alertSettings.demoOrderTitle', 'alertSettings', 'demoOrderTitle', '1 New Order'),
  ('alertSettings.demoOrderSubtitle', 'alertSettings', 'demoOrderSubtitle', 'Just placed'),
  ('alertSettings.demoOrderDetails', 'alertSettings', 'demoOrderDetails', '1 pending order awaiting confirmation'),
  ('period.today', 'period', 'today', 'today'),
  ('period.last7days', 'period', 'last7days', 'last 7 days'),
  ('period.thisMonthLabel', 'period', 'thisMonthLabel', 'this month'),
  ('period.last3months', 'period', 'last3months', 'last 3 months'),
  ('nav.analyticsSubtitle', 'nav', 'analyticsSubtitle', 'Revenue, orders, bookings, and AI performance'),
  ('analytics.totalRevenue', 'analytics', 'totalRevenue', 'Total Revenue'),
  ('analytics.reservations', 'analytics', 'reservations', 'Reservations'),
  ('analytics.aiResolution', 'analytics', 'aiResolution', 'AI Resolution'),
  ('period.thisWeek', 'period', 'thisWeek', 'This Week'),
  ('period.thisMonth', 'period', 'thisMonth', 'This Month'),
  ('period.last3Months', 'period', 'last3Months', 'Last 3 Months'),
  ('common.exportCSV', 'common', 'exportCSV', 'Export CSV'),
  ('analytics.revenueOrders', 'analytics', 'revenueOrders', 'Revenue & Orders'),
  ('analytics.noRevenueData', 'analytics', 'noRevenueData', 'No revenue data yet'),
  ('analytics.noRevenueDataSub', 'analytics', 'noRevenueDataSub', 'Data will appear as orders come in'),
  ('analytics.revenueLabel', 'analytics', 'revenueLabel', 'Revenue ($)'),
  ('analytics.ordersLabel', 'analytics', 'ordersLabel', 'Orders'),
  ('analytics.channelSplit', 'analytics', 'channelSplit', 'Channel Split'),
  ('analytics.noChannelData', 'analytics', 'noChannelData', 'No channel data yet'),
  ('analytics.noChannelDataSub', 'analytics', 'noChannelDataSub', 'Data appears as conversations start'),
  ('analytics.reservationsTrend', 'analytics', 'reservationsTrend', 'Reservations Trend'),
  ('period.last6months', 'period', 'last6months', 'Last 6 months'),
  ('analytics.noBookingData', 'analytics', 'noBookingData', 'No booking data yet'),
  ('analytics.noBookingDataSub', 'analytics', 'noBookingDataSub', 'Data appears as reservations are made'),
  ('analytics.bookingsLabel', 'analytics', 'bookingsLabel', 'Bookings'),
  ('analytics.cancellationsLabel', 'analytics', 'cancellationsLabel', 'Cancellations'),
  ('analytics.aiResolutionByHour', 'analytics', 'aiResolutionByHour', 'AI Resolution Rate by Hour'),
  ('analytics.noAIData', 'analytics', 'noAIData', 'No AI performance data yet'),
  ('analytics.noAIDataSub', 'analytics', 'noAIDataSub', 'Data appears as conversations are resolved'),
  ('analytics.resolutionPct', 'analytics', 'resolutionPct', 'Resolution %'),
  ('analytics.escalationPct', 'analytics', 'escalationPct', 'Escalation %'),
  ('analytics.revenueByChannel', 'analytics', 'revenueByChannel', 'Revenue by Channel'),
  ('analytics.noChannelRevenueData', 'analytics', 'noChannelRevenueData', 'No channel revenue data yet'),
  ('analytics.noChannelRevenueDataSub', 'analytics', 'noChannelRevenueDataSub', 'Data appears as orders come in through different channels'),
  ('analytics.topMenuItems', 'analytics', 'topMenuItems', 'Top Menu Items'),
  ('analytics.noItemData', 'analytics', 'noItemData', 'No item data yet'),
  ('analytics.noItemDataSub', 'analytics', 'noItemDataSub', 'Top items appear as orders are completed'),
  ('billing.usageConversations', 'billing', 'usageConversations', 'AI Conversations'),
  ('billing.usageVoiceMinutes', 'billing', 'usageVoiceMinutes', 'Voice Minutes'),
  ('billing.usageBranches', 'billing', 'usageBranches', 'Branches'),
  ('billing.usageApiCalls', 'billing', 'usageApiCalls', 'API Calls'),
  ('billing.viewPlansSubscribe', 'billing', 'viewPlansSubscribe', 'View Plans & Subscribe'),
  ('billing.updatePayment', 'billing', 'updatePayment', 'Update Payment'),
  ('billing.updatePaymentCard', 'billing', 'updatePaymentCard', 'Update Payment Card'),
  ('branchManagement.errorNameRequired', 'branchManagement', 'errorNameRequired', 'Branch name is required'),
  ('branchManagement.errorNameTooShort', 'branchManagement', 'errorNameTooShort', 'Name must be at least 2 characters'),
  ('branchManagement.errorAddressRequired', 'branchManagement', 'errorAddressRequired', 'Address is required'),
  ('branchManagement.errorAddressTooShort', 'branchManagement', 'errorAddressTooShort', 'Please enter a complete address'),
  ('branchManagement.errorPhoneInvalid', 'branchManagement', 'errorPhoneInvalid', 'Please enter a valid phone number'),
  ('branchManagement.editBranch', 'branchManagement', 'editBranch', 'Edit Branch'),
  ('branchManagement.addNewBranch', 'branchManagement', 'addNewBranch', 'Add New Branch'),
  ('branchManagement.cancel', 'branchManagement', 'cancel', 'Cancel'),
  ('branchManagement.saving', 'branchManagement', 'saving', 'Saving...'),
  ('branchManagement.saveChanges', 'branchManagement', 'saveChanges', 'Save Changes'),
  ('branchManagement.addBranch', 'branchManagement', 'addBranch', 'Add Branch'),
  ('branchManagement.branchInformation', 'branchManagement', 'branchInformation', 'Branch Information'),
  ('branchManagement.labelBranchName', 'branchManagement', 'labelBranchName', 'Branch Name *'),
  ('branchManagement.labelFullAddress', 'branchManagement', 'labelFullAddress', 'Full Address *'),
  ('branchManagement.labelPhone', 'branchManagement', 'labelPhone', 'Phone Number'),
  ('branchManagement.labelTimezone', 'branchManagement', 'labelTimezone', 'Timezone'),
  ('branchManagement.operatingHours', 'branchManagement', 'operatingHours', 'Operating Hours'),
  ('common.to', 'common', 'to', 'to'),
  ('common.closed', 'common', 'closed', 'Closed'),
  ('branchManagement.branchStatus', 'branchManagement', 'branchStatus', 'Branch Status'),
  ('branchManagement.activeBranch', 'branchManagement', 'activeBranch', 'Active Branch'),
  ('branchManagement.activeBranchDesc', 'branchManagement', 'activeBranchDesc', 'Branch is visible and accepting orders'),
  ('branchManagement.quickSummary', 'branchManagement', 'quickSummary', 'Quick Summary'),
  ('branchManagement.summaryOpenDays', 'branchManagement', 'summaryOpenDays', 'Open Days'),
  ('nav.branchesSubtitle', 'nav', 'branchesSubtitle', 'Manage restaurant locations and branches'),
  ('branch.failedToLoad', 'branch', 'failedToLoad', 'Failed to load branches'),
  ('branch.statusUpdated', 'branch', 'statusUpdated', 'Branch status updated'),
  ('branch.failedToUpdate', 'branch', 'failedToUpdate', 'Failed to update branch'),
  ('branch.added', 'branch', 'added', 'Branch added'),
  ('branch.failedToAdd', 'branch', 'failedToAdd', 'Failed to add branch'),
  ('branch.deleted', 'branch', 'deleted', 'Branch deleted'),
  ('branch.failedToDelete', 'branch', 'failedToDelete', 'Failed to delete branch'),
  ('branch.plural', 'branch', 'plural', 'branches'),
  ('branch.singular', 'branch', 'singular', 'branch'),
  ('branch.addBranch', 'branch', 'addBranch', 'Add Branch'),
  ('branch.addNewBranch', 'branch', 'addNewBranch', 'Add New Branch'),
  ('branch.namePlaceholder', 'branch', 'namePlaceholder', 'Branch name *'),
  ('branch.noBranches', 'branch', 'noBranches', 'No branches yet'),
  ('branch.addFirstBranch', 'branch', 'addFirstBranch', 'Add your first branch to get started'),
  ('changePassword.ruleMinChars', 'changePassword', 'ruleMinChars', 'At least 8 characters'),
  ('changePassword.ruleUppercase', 'changePassword', 'ruleUppercase', 'One uppercase letter'),
  ('changePassword.ruleNumber', 'changePassword', 'ruleNumber', 'One number'),
  ('changePassword.errorDefault', 'changePassword', 'errorDefault', 'Failed to change password'),
  ('changePassword.title', 'changePassword', 'title', 'Change Password'),
  ('changePassword.updatedTitle', 'changePassword', 'updatedTitle', 'Password Updated'),
  ('changePassword.updatedDesc', 'changePassword', 'updatedDesc', 'Your password has been changed successfully.'),
  ('changePassword.changeAgain', 'changePassword', 'changeAgain', 'Change again'),
  ('changePassword.currentPassword', 'changePassword', 'currentPassword', 'Current Password'),
  ('changePassword.currentPlaceholder', 'changePassword', 'currentPlaceholder', 'Enter current password'),
  ('changePassword.newPassword', 'changePassword', 'newPassword', 'New Password'),
  ('changePassword.newPlaceholder', 'changePassword', 'newPlaceholder', 'Enter new password'),
  ('changePassword.confirmPassword', 'changePassword', 'confirmPassword', 'Confirm New Password'),
  ('changePassword.confirmPlaceholder', 'changePassword', 'confirmPlaceholder', 'Confirm new password'),
  ('changePassword.mismatch', 'changePassword', 'mismatch', 'Passwords do not match'),
  ('changePassword.updating', 'changePassword', 'updating', 'Updating...'),
  ('changePassword.updateButton', 'changePassword', 'updateButton', 'Update Password'),
  ('conversations.failedToLoad', 'conversations', 'failedToLoad', 'Failed to load conversation: '),
  ('conversations.escalated', 'conversations', 'escalated', 'Escalated'),
  ('conversations.needsHuman', 'conversations', 'needsHuman', 'Needs human agent'),
  ('conversations.aiFallbackReply', 'conversations', 'aiFallbackReply', 'I understand. How can I help you further?'),
  ('conversations.takeoverHi', 'conversations', 'takeoverHi', 'Hi'),
  ('conversations.there', 'conversations', 'there', 'there'),
  ('conversations.takeoverSuccess', 'conversations', 'takeoverSuccess', 'You are now handling this conversation'),
  ('conversations.resolveMessage', 'conversations', 'resolveMessage', 'This conversation has been resolved. Thank you!'),
  ('conversations.resolveSuccess', 'conversations', 'resolveSuccess', 'Conversation resolved'),
  ('conversations.noPhone', 'conversations', 'noPhone', 'No phone number available for this customer'),
  ('conversations.callFailed', 'conversations', 'callFailed', 'Failed to initiate call'),
  ('conversations.calling', 'conversations', 'calling', 'Calling'),
  ('conversations.customer', 'conversations', 'customer', 'Customer'),
  ('conversations.activeNow', 'conversations', 'activeNow', 'Active now'),
  ('conversations.general', 'conversations', 'general', 'General'),
  ('conversations.callActive', 'conversations', 'callActive', 'Call active'),
  ('conversations.call', 'conversations', 'call', 'Call'),
  ('conversations.onCall', 'conversations', 'onCall', 'On Call'),
  ('conversations.callShort', 'conversations', 'callShort', 'Call'),
  ('conversations.takeOver', 'conversations', 'takeOver', 'Take Over'),
  ('conversations.agentMode', 'conversations', 'agentMode', 'Agent Mode'),
  ('conversations.resolve', 'conversations', 'resolve', 'Resolve'),
  ('conversations.aiHandling', 'conversations', 'aiHandling', 'AI Agent is handling this conversation'),
  ('conversations.model', 'conversations', 'model', 'Model'),
  ('conversations.avgConfidence', 'conversations', 'avgConfidence', 'Avg confidence'),
  ('conversations.aiThinking', 'conversations', 'aiThinking', 'AI is thinking...'),
  ('conversations.placeholderAgent', 'conversations', 'placeholderAgent', 'Type a message as agent...'),
  ('conversations.placeholderTest', 'conversations', 'placeholderTest', 'Type a customer message to test AI...'),
  ('conversations.customerLabel', 'conversations', 'customerLabel', 'Customer'),
  ('conversations.voice', 'conversations', 'voice', 'Voice'),
  ('conversations.chat', 'conversations', 'chat', 'Chat'),
  ('conversations.aiAgentConfig', 'conversations', 'aiAgentConfig', 'AI Agent Config'),
  ('conversations.modelLabel', 'conversations', 'modelLabel', 'Model'),
  ('conversations.styleLabel', 'conversations', 'styleLabel', 'Style'),
  ('conversations.statusLabel', 'conversations', 'statusLabel', 'Status'),
  ('conversations.humanAgent', 'conversations', 'humanAgent', 'Human Agent'),
  ('conversations.aiHandlingShort', 'conversations', 'aiHandlingShort', 'AI Handling'),
  ('conversations.conversationInfo', 'conversations', 'conversationInfo', 'Conversation Info'),
  ('conversations.topic', 'conversations', 'topic', 'Topic'),
  ('conversations.channel', 'conversations', 'channel', 'Channel'),
  ('conversations.status', 'conversations', 'status', 'Status'),
  ('conversations.messages', 'conversations', 'messages', 'Messages'),
  ('conversations.aiMessages', 'conversations', 'aiMessages', 'AI Messages'),
  ('conversations.actions', 'conversations', 'actions', 'Actions'),
  ('conversations.addTag', 'conversations', 'addTag', 'Add Tag'),
  ('conversations.escalatedToManager', 'conversations', 'escalatedToManager', 'Escalated to manager'),
  ('conversations.escalateToManager', 'conversations', 'escalateToManager', 'Escalate to Manager'),
  ('conversations.internalNotes', 'conversations', 'internalNotes', 'Internal Notes'),
  ('conversations.saveNote', 'conversations', 'saveNote', 'Save Note'),
  ('conversations.statusAI', 'conversations', 'statusAI', 'AI Handling'),
  ('conversations.statusHuman', 'conversations', 'statusHuman', 'Needs Agent'),
  ('conversations.statusResolved', 'conversations', 'statusResolved', 'Resolved'),
  ('table.rowsPerPage', 'table', 'rowsPerPage', 'Rows per page:'),
  ('table.noResults', 'table', 'noResults', '0 results'),
  ('table.page', 'table', 'page', 'Page'),
  ('table.of', 'table', 'of', 'of'),
  ('table.total', 'table', 'total', 'total'),
  ('table.previousPage', 'table', 'previousPage', 'Previous page'),
  ('table.nextPage', 'table', 'nextPage', 'Next page'),
  ('conversations.takenOver', 'conversations', 'takenOver', 'Chat taken over — you are now the assigned agent'),
  ('common.failedPrefix', 'common', 'failedPrefix', 'Failed: '),
  ('conversations.markedResolved', 'conversations', 'markedResolved', 'Conversation marked as resolved'),
  ('conversations.transcript', 'conversations', 'transcript', 'Transcript'),
  ('conversations.info', 'conversations', 'info', 'Info'),
  ('conversations.noTranscriptYet', 'conversations', 'noTranscriptYet', 'No transcript yet'),
  ('conversations.noMessagesYet', 'conversations', 'noMessagesYet', 'No messages yet'),
  ('conversations.agentLabel', 'conversations', 'agentLabel', 'Agent'),
  ('conversations.infoTopic', 'conversations', 'infoTopic', 'Topic'),
  ('conversations.topicGeneral', 'conversations', 'topicGeneral', 'General'),
  ('conversations.infoPhone', 'conversations', 'infoPhone', 'Phone'),
  ('conversations.infoEmail', 'conversations', 'infoEmail', 'Email'),
  ('conversations.infoChannel', 'conversations', 'infoChannel', 'Channel'),
  ('conversations.infoAssignedAgent', 'conversations', 'infoAssignedAgent', 'Assigned Agent'),
  ('conversations.none', 'conversations', 'none', 'None'),
  ('conversations.infoUnread', 'conversations', 'infoUnread', 'Unread Messages'),
  ('conversations.infoStarted', 'conversations', 'infoStarted', 'Started'),
  ('conversations.infoLastActivity', 'conversations', 'infoLastActivity', 'Last Activity'),
  ('conversations.aiConfidence', 'conversations', 'aiConfidence', 'AI Confidence'),
  ('conversations.agentActions', 'conversations', 'agentActions', 'Agent Actions'),
  ('conversations.takingOver', 'conversations', 'takingOver', 'Taking over…'),
  ('conversations.assignToMe', 'conversations', 'assignToMe', 'Assign to Me'),
  ('conversations.takeOverFromAI', 'conversations', 'takeOverFromAI', 'Take Over from AI'),
  ('conversations.resolving', 'conversations', 'resolving', 'Resolving…'),
  ('conversations.markAsResolved', 'conversations', 'markAsResolved', 'Mark as Resolved'),
  ('conversations.conversationClosed', 'conversations', 'conversationClosed', 'This conversation has been closed'),
  ('conversations.openFull', 'conversations', 'openFull', 'Open full conversation'),
  ('conversations.fullView', 'conversations', 'fullView', 'Full view'),
  ('calls.duration', 'calls', 'duration', 'Duration'),
  ('calls.from', 'calls', 'from', 'From'),
  ('calls.to', 'calls', 'to', 'To'),
  ('calls.aiHandled', 'calls', 'aiHandled', 'AI Handled'),
  ('calls.escalated', 'calls', 'escalated', 'Escalated'),
  ('calls.escalationReason', 'calls', 'escalationReason', 'Escalation Reason'),
  ('calls.callRecording', 'calls', 'callRecording', 'Call Recording'),
  ('common.download', 'common', 'download', 'Download'),
  ('conversations.noTranscriptAvailable', 'conversations', 'noTranscriptAvailable', 'No transcript available'),
  ('calls.viewLinkedConversation', 'calls', 'viewLinkedConversation', 'View linked conversation'),
  ('nav.conversationsSubtitle', 'nav', 'conversationsSubtitle', 'Manage AI and human-handled customer conversations'),
  ('calls.failedToLoad', 'calls', 'failedToLoad', 'Failed to load calls: '),
  ('common.undone', 'common', 'undone', 'Undone'),
  ('common.failed', 'common', 'failed', 'Failed'),
  ('conversations.needsAgentBanner', 'conversations', 'needsAgentBanner', 'Needs Agent'),
  ('conversations.conversationSingular', 'conversations', 'conversationSingular', 'conversation'),
  ('conversations.conversationPlural', 'conversations', 'conversationPlural', 'conversations'),
  ('conversations.awaits', 'conversations', 'awaits', 'awaits'),
  ('conversations.await', 'conversations', 'await', 'await'),
  ('conversations.humanAssistance', 'conversations', 'humanAssistance', 'human assistance'),
  ('conversations.bannerHint', 'conversations', 'bannerHint', 'Click "Take Over" to assign yourself or "Assign Me" to assist'),
  ('conversations.totalConversations', 'conversations', 'totalConversations', 'Total Conversations'),
  ('calls.totalCalls', 'calls', 'totalCalls', 'Total Calls'),
  ('calls.inbound', 'calls', 'inbound', 'Inbound'),
  ('conversations.needAgent', 'conversations', 'needAgent', 'Need Agent'),
  ('calls.outbound', 'calls', 'outbound', 'Outbound'),
  ('conversations.unread', 'conversations', 'unread', 'Unread'),
  ('calls.callLogs', 'calls', 'callLogs', 'Call Logs'),
  ('conversations.searchPlaceholder', 'conversations', 'searchPlaceholder', 'Search by name, topic or phone…'),
  ('calls.searchPlaceholder', 'calls', 'searchPlaceholder', 'Search by name or number…'),
  ('channel.chat', 'channel', 'chat', 'Chat'),
  ('channel.voice', 'channel', 'voice', 'Voice'),
  ('channel.whatsapp', 'channel', 'whatsapp', 'WhatsApp'),
  ('conversations.statusAIShort', 'conversations', 'statusAIShort', 'AI'),
  ('calls.completed', 'calls', 'completed', 'Completed'),
  ('calls.inProgress', 'calls', 'inProgress', 'In Progress'),
  ('calls.failed', 'calls', 'failed', 'Failed'),
  ('calls.missed', 'calls', 'missed', 'Missed'),
  ('common.refresh', 'common', 'refresh', 'Refresh'),
  ('common.export', 'common', 'export', 'Export'),
  ('conversations.colCustomer', 'conversations', 'colCustomer', 'Customer'),
  ('conversations.colChannel', 'conversations', 'colChannel', 'Channel'),
  ('conversations.colStatus', 'conversations', 'colStatus', 'Status'),
  ('conversations.colTopic', 'conversations', 'colTopic', 'Topic'),
  ('conversations.colAIConf', 'conversations', 'colAIConf', 'AI Conf'),
  ('conversations.colDate', 'conversations', 'colDate', 'Date / Time'),
  ('conversations.colLastActivity', 'conversations', 'colLastActivity', 'Last Activity'),
  ('conversations.noConversationsFound', 'conversations', 'noConversationsFound', 'No conversations found'),
  ('common.tryAdjustingFilters', 'common', 'tryAdjustingFilters', 'Try adjusting your filters'),
  ('conversations.assignMe', 'conversations', 'assignMe', 'Assign Me'),
  ('calls.direction', 'calls', 'direction', 'Direction'),
  ('calls.recording', 'calls', 'recording', 'Recording'),
  ('calls.handledBy', 'calls', 'handledBy', 'Handled By'),
  ('calls.noCallLogsFound', 'calls', 'noCallLogsFound', 'No call logs found'),
  ('calls.noCallLogsSub', 'calls', 'noCallLogsSub', 'Call logs from voice interactions will appear here'),
  ('conversations.human', 'conversations', 'human', 'Human'),
  ('common.selected', 'common', 'selected', 'selected'),
  ('conversations.changeStatus', 'conversations', 'changeStatus', 'Change Status'),
  ('conversations.escalateToHuman', 'conversations', 'escalateToHuman', 'Escalate to Human'),
  ('conversations.assign', 'conversations', 'assign', 'Assign'),
  ('conversations.deleteDescription', 'conversations', 'deleteDescription', 'This will permanently remove the selected conversations. This action cannot be undone.'),
  ('conversations.deleteConfirmLabel', 'conversations', 'deleteConfirmLabel', 'Delete Conversations'),
  ('customers.page_of', 'customers', 'page_of', 'Page'),
  ('customers.page_of_total', 'customers', 'page_of_total', 'of'),
  ('customers.total', 'customers', 'total', 'total'),
  ('customers.profile_title', 'customers', 'profile_title', 'Customer Profile'),
  ('customers.profile_subtitle', 'customers', 'profile_subtitle', 'Complete profile, order history, and reservations'),
  ('customers.load_orders_error', 'customers', 'load_orders_error', 'Failed to load orders'),
  ('customers.load_reservations_error', 'customers', 'load_reservations_error', 'Failed to load reservations'),
  ('customers.note_saved', 'customers', 'note_saved', 'Note saved'),
  ('customers.save_note_error', 'customers', 'save_note_error', 'Failed to save note'),
  ('customers.not_found', 'customers', 'not_found', 'Customer not found'),
  ('customers.back_to_list', 'customers', 'back_to_list', 'Back to Customers'),
  ('customers.member_since', 'customers', 'member_since', 'Member since'),
  ('customers.contact_info', 'customers', 'contact_info', 'Contact Info'),
  ('customers.no_contact_details', 'customers', 'no_contact_details', 'No contact details on record'),
  ('customers.total_orders', 'customers', 'total_orders', 'Total Orders'),
  ('customers.total_spent', 'customers', 'total_spent', 'Total Spent'),
  ('customers.avg_order_value', 'customers', 'avg_order_value', 'Avg Order Value'),
  ('customers.total_reservations', 'customers', 'total_reservations', 'Reservations'),
  ('customers.last_visit', 'customers', 'last_visit', 'Last Visit'),
  ('customers.total_visits', 'customers', 'total_visits', 'Total Visits'),
  ('customers.member_since_label', 'customers', 'member_since_label', 'Member Since'),
  ('customers.tags', 'customers', 'tags', 'Tags'),
  ('customers.internal_notes', 'customers', 'internal_notes', 'Internal Notes'),
  ('customers.edit_note', 'customers', 'edit_note', 'Edit'),
  ('customers.notes_placeholder', 'customers', 'notes_placeholder', 'Add internal notes about this customer...'),
  ('customers.save_note', 'customers', 'save_note', 'Save'),
  ('customers.cancel_note', 'customers', 'cancel_note', 'Cancel'),
  ('customers.no_notes', 'customers', 'no_notes', 'No notes yet. Click Edit to add notes.'),
  ('customers.orders', 'customers', 'orders', 'Orders'),
  ('customers.view_all', 'customers', 'view_all', 'View All'),
  ('customers.no_orders', 'customers', 'no_orders', 'No orders yet'),
  ('customers.order_no', 'customers', 'order_no', 'Order #'),
  ('customers.order_date', 'customers', 'order_date', 'Date'),
  ('customers.order_channel', 'customers', 'order_channel', 'Channel'),
  ('customers.order_items', 'customers', 'order_items', 'Items'),
  ('customers.order_total', 'customers', 'order_total', 'Total'),
  ('customers.order_status', 'customers', 'order_status', 'Status'),
  ('customers.reservations', 'customers', 'reservations', 'Reservations'),
  ('customers.no_reservations', 'customers', 'no_reservations', 'No reservations yet'),
  ('customers.booking_date', 'customers', 'booking_date', 'Date'),
  ('customers.booking_time', 'customers', 'booking_time', 'Time'),
  ('customers.booking_party', 'customers', 'booking_party', 'Party'),
  ('customers.booking_occasion', 'customers', 'booking_occasion', 'Occasion'),
  ('customers.booking_status', 'customers', 'booking_status', 'Status'),
  ('customers.booking_requests', 'customers', 'booking_requests', 'Special Requests'),
  ('common.page', 'common', 'page', 'Page'),
  ('common.of', 'common', 'of', 'of'),
  ('customers.loadError', 'customers', 'loadError', 'Failed to load customers'),
  ('customers.ordersLoadError', 'customers', 'ordersLoadError', 'Failed to load orders'),
  ('customers.bookingsLoadError', 'customers', 'bookingsLoadError', 'Failed to load reservations'),
  ('customers.added', 'customers', 'added', 'Customer added'),
  ('customers.addError', 'customers', 'addError', 'Failed to add customer'),
  ('customers.colCustomer', 'customers', 'colCustomer', 'Customer'),
  ('customers.colOrders', 'customers', 'colOrders', 'Orders'),
  ('customers.colTotalSpent', 'customers', 'colTotalSpent', 'Total Spent'),
  ('customers.colReservations', 'customers', 'colReservations', 'Reservations'),
  ('customers.colLastVisit', 'customers', 'colLastVisit', 'Last Visit'),
  ('customers.colMemberSince', 'customers', 'colMemberSince', 'Member Since'),
  ('customers.searchPlaceholder', 'customers', 'searchPlaceholder', 'Search by name, email, or phone…'),
  ('customers.addNewCustomer', 'customers', 'addNewCustomer', 'Add New Customer'),
  ('customers.fullNamePlaceholder', 'customers', 'fullNamePlaceholder', 'Full name *'),
  ('customers.noCustomers', 'customers', 'noCustomers', 'No customers found'),
  ('customers.noCustomersSub', 'customers', 'noCustomersSub', 'Customers appear when they interact with your AI agent or when you add them manually'),
  ('customers.customers', 'customers', 'customers', 'customers'),
  ('common.prev', 'common', 'prev', 'Prev'),
  ('customers.memberSince', 'customers', 'memberSince', 'Member since'),
  ('customers.noContactDetails', 'customers', 'noContactDetails', 'No contact details on record'),
  ('customers.statTotalOrders', 'customers', 'statTotalOrders', 'Total Orders'),
  ('customers.statTotalSpent', 'customers', 'statTotalSpent', 'Total Spent'),
  ('customers.statAvgOrder', 'customers', 'statAvgOrder', 'Avg Order'),
  ('customers.statReservations', 'customers', 'statReservations', 'Reservations'),
  ('customers.statLastVisit', 'customers', 'statLastVisit', 'Last Visit'),
  ('customers.statTotalVisits', 'customers', 'statTotalVisits', 'Total Visits'),
  ('common.viewAll', 'common', 'viewAll', 'View All'),
  ('customers.noOrders', 'customers', 'noOrders', 'No orders found'),
  ('customers.orderNum', 'customers', 'orderNum', 'Order #'),
  ('customers.items', 'customers', 'items', 'Items'),
  ('customers.noReservations', 'customers', 'noReservations', 'No reservations found'),
  ('customers.party', 'customers', 'party', 'Party'),
  ('customers.specialRequests', 'customers', 'specialRequests', 'Special Requests'),
  ('help.failedToLoad', 'help', 'failedToLoad', 'Failed to load tickets: '),
  ('help.you', 'help', 'you', 'You'),
  ('help.ticketSubmitted', 'help', 'ticketSubmitted', 'Support ticket submitted'),
  ('help.failedToSubmit', 'help', 'failedToSubmit', 'Failed to submit ticket: '),
  ('help.replySent', 'help', 'replySent', 'Reply sent'),
  ('help.failedToSendReply', 'help', 'failedToSendReply', 'Failed to send reply: '),
  ('help.backToTickets', 'help', 'backToTickets', 'Back to tickets'),
  ('help.raiseTicket', 'help', 'raiseTicket', 'Raise a Support Ticket'),
  ('help.subject', 'help', 'subject', 'Subject'),
  ('help.category', 'help', 'category', 'Category'),
  ('help.priority', 'help', 'priority', 'Priority'),
  ('help.priorityLow', 'help', 'priorityLow', 'Low'),
  ('help.priorityMedium', 'help', 'priorityMedium', 'Medium'),
  ('help.priorityHigh', 'help', 'priorityHigh', 'High'),
  ('help.priorityUrgent', 'help', 'priorityUrgent', 'Urgent'),
  ('help.description', 'help', 'description', 'Description'),
  ('help.submitTicket', 'help', 'submitTicket', 'Submit Ticket'),
  ('help.cancel', 'help', 'cancel', 'Cancel'),
  ('help.conversationThread', 'help', 'conversationThread', 'Conversation Thread'),
  ('help.noMessages', 'help', 'noMessages', 'No messages yet'),
  ('help.attachFile', 'help', 'attachFile', 'Attach file'),
  ('help.sendReply', 'help', 'sendReply', 'Send Reply'),
  ('help.ticketDetails', 'help', 'ticketDetails', 'Ticket Details'),
  ('help.statusLabel', 'help', 'statusLabel', 'Status'),
  ('help.priorityLabel', 'help', 'priorityLabel', 'Priority'),
  ('help.categoryLabel', 'help', 'categoryLabel', 'Category'),
  ('help.createdLabel', 'help', 'createdLabel', 'Created'),
  ('help.searchPlaceholder', 'help', 'searchPlaceholder', 'Search tickets...'),
  ('help.newTicket', 'help', 'newTicket', 'New Ticket'),
  ('help.noTickets', 'help', 'noTickets', 'No support tickets'),
  ('help.noTicketsDescription', 'help', 'noTicketsDescription', 'Create a ticket if you need help with anything'),
  ('help.catGettingStarted', 'help', 'catGettingStarted', 'Getting Started'),
  ('help.catAiAgent', 'help', 'catAiAgent', 'AI Agent'),
  ('help.catOrders', 'help', 'catOrders', 'Orders & Menu'),
  ('help.catBookings', 'help', 'catBookings', 'Table Bookings'),
  ('help.catSettings', 'help', 'catSettings', 'Settings & Config'),
  ('help.catTeam', 'help', 'catTeam', 'Staff & Team'),
  ('help.catAnalytics', 'help', 'catAnalytics', 'Analytics'),
  ('help.catIntegrations', 'help', 'catIntegrations', 'Integrations & API'),
  ('help.art1Title', 'help', 'art1Title', 'Quick Start: Setting up your AI Agent in 5 minutes'),
  ('help.art1Desc', 'help', 'art1Desc', 'Learn how to configure your AI agent for voice and chat, set up greeting scripts, and go live.'),
  ('help.readTime5', 'help', 'readTime5', '5 min'),
  ('help.art2Title', 'help', 'art2Title', 'How to train your AI with a custom Knowledge Base'),
  ('help.art2Desc', 'help', 'art2Desc', 'Upload documents, add FAQs, and link URLs to make your AI smarter about your restaurant.'),
  ('help.readTime8', 'help', 'readTime8', '8 min'),
  ('help.art3Title', 'help', 'art3Title', 'Configuring fallback rules and escalation paths'),
  ('help.art3Desc', 'help', 'art3Desc', 'Define what happens when the AI cannot resolve a customer query — escalate to staff or live chat.'),
  ('help.readTime6', 'help', 'readTime6', '6 min'),
  ('help.art4Title', 'help', 'art4Title', 'Managing orders and updating menu availability'),
  ('help.art4Desc', 'help', 'art4Desc', 'Accept, reject, and track orders in real time. Toggle item availability directly from the dashboard.'),
  ('help.readTime4', 'help', 'readTime4', '4 min'),
  ('help.art5Title', 'help', 'art5Title', 'Setting up table booking rules and time slots'),
  ('help.art5Desc', 'help', 'art5Desc', 'Configure party sizes, booking windows, and automatic confirmation messages.'),
  ('help.art6Title', 'help', 'art6Title', 'Adding and managing staff accounts with roles'),
  ('help.art6Desc', 'help', 'art6Desc', 'Create staff accounts, assign roles (manager, server, kitchen), and control permissions.'),
  ('help.art7Title', 'help', 'art7Title', 'Understanding your AI performance analytics'),
  ('help.art7Desc', 'help', 'art7Desc', 'Read resolution rates, escalation trends, and conversation quality metrics.'),
  ('help.readTime7', 'help', 'readTime7', '7 min'),
  ('help.art8Title', 'help', 'art8Title', 'Connecting a SIP trunk for AI voice calls'),
  ('help.art8Desc', 'help', 'art8Desc', 'Add your existing SIP trunk credentials and assign them to your AI voice agent.'),
  ('help.art9Title', 'help', 'art9Title', 'Webhook setup and event subscriptions'),
  ('help.art9Desc', 'help', 'art9Desc', 'Configure webhooks to push order, booking, and AI events to your own systems.'),
  ('help.readTime9', 'help', 'readTime9', '9 min'),
  ('help.art10Title', 'help', 'art10Title', 'Bulk menu upload with AI auto-detection'),
  ('help.art10Desc', 'help', 'art10Desc', 'Upload a PDF or image of your menu and let AI parse and populate items automatically.'),
  ('help.video1Title', 'help', 'video1Title', 'Complete Platform Walkthrough'),
  ('help.video2Title', 'help', 'video2Title', 'AI Agent Configuration Deep Dive'),
  ('help.video3Title', 'help', 'video3Title', 'Menu Management & Bulk Upload'),
  ('help.video4Title', 'help', 'video4Title', 'Webhooks & API Integration Guide'),
  ('help.faq1Q', 'help', 'faq1Q', 'How many AI calls are included in my plan?'),
  ('help.faq1A', 'help', 'faq1A', 'The Starter plan includes 500 AI calls/month. Growth includes 2,000 and Pro includes unlimited calls. Overages are billed at $0.02/call.'),
  ('help.faq2Q', 'help', 'faq2Q', 'Can I use my own phone number with the AI agent?'),
  ('help.faq2A', 'help', 'faq2A', 'Yes. You can add a SIP trunk with your existing number, or purchase a new local/toll-free number directly from the Phone Numbers module.'),
  ('help.faq3Q', 'help', 'faq3Q', 'What happens when the AI cannot answer a question?'),
  ('help.faq3A', 'help', 'faq3A', 'The AI follows your configured fallback rules — it can transfer to a live staff member, send a message, or escalate via the Conversations inbox.'),
  ('help.faq4Q', 'help', 'faq4Q', 'Is my customer data secure?'),
  ('help.faq4A', 'help', 'faq4A', 'All data is encrypted at rest and in transit. We are SOC 2 Type II compliant and GDPR-ready. You own your data and can export or delete it at any time.'),
  ('help.heroTitle', 'help', 'heroTitle', 'How can we help you?'),
  ('help.heroSubtitle', 'help', 'heroSubtitle', 'Search across 85+ articles, guides, and video tutorials'),
  ('help.videoGuides', 'help', 'videoGuides', 'Video Guides'),
  ('help.faqs', 'help', 'faqs', 'FAQs'),
  ('help.browseByCategory', 'help', 'browseByCategory', 'Browse by Category'),
  ('help.articleCount', 'help', 'articleCount', '{count} articles'),
  ('help.featuredArticles', 'help', 'featuredArticles', 'Featured Articles'),
  ('help.readTimeLabel', 'help', 'readTimeLabel', '{time} read'),
  ('help.helpfulCount', 'help', 'helpfulCount', '{count} found helpful'),
  ('help.searchResultsFor', 'help', 'searchResultsFor', 'Search results for "{query}"'),
  ('help.categoryArticles', 'help', 'categoryArticles', '{category} Articles'),
  ('help.allArticles', 'help', 'allArticles', 'All Articles'),
  ('help.clearFilters', 'help', 'clearFilters', 'Clear filters'),
  ('help.viewsCount', 'help', 'viewsCount', '{count} views'),
  ('help.noArticlesFound', 'help', 'noArticlesFound', 'No articles found'),
  ('help.noArticlesFoundDesc', 'help', 'noArticlesFoundDesc', 'Try a different search term or browse by category'),
  ('help.stillNeedHelp', 'help', 'stillNeedHelp', 'Still need help?'),
  ('help.supportResponseTime', 'help', 'supportResponseTime', 'Our support team typically responds within 2 hours on business days.'),
  ('help.openSupportTicket', 'help', 'openSupportTicket', 'Open a Support Ticket'),
  ('knowledgeBase.status.pending', 'knowledgeBase', 'status.pending', 'pending'),
  ('knowledgeBase.status.indexed', 'knowledgeBase', 'status.indexed', 'indexed'),
  ('knowledgeBase.status.indexing', 'knowledgeBase', 'status.indexing', 'indexing'),
  ('knowledgeBase.status.embeddingFailed', 'knowledgeBase', 'status.embeddingFailed', 'Embedding generation failed'),
  ('knowledgeBase.status.error', 'knowledgeBase', 'status.error', 'error'),
  ('knowledgeBase.failedToLoad', 'knowledgeBase', 'failedToLoad', 'Failed to load knowledge base'),
  ('knowledgeBase.failedToUploadFile', 'knowledgeBase', 'failedToUploadFile', 'Failed to upload'),
  ('knowledgeBase.filesUploaded', 'knowledgeBase', 'filesUploaded', '{{count}} file{{plural}} uploaded successfully'),
  ('knowledgeBase.urlAdded', 'knowledgeBase', 'urlAdded', 'URL added — crawling content...'),
  ('knowledgeBase.urlCrawled', 'knowledgeBase', 'urlCrawled', 'URL content crawled and indexed'),
  ('knowledgeBase.failedToCrawlUrl', 'knowledgeBase', 'failedToCrawlUrl', 'Failed to crawl URL'),
  ('knowledgeBase.failedToAddUrl', 'knowledgeBase', 'failedToAddUrl', 'Failed to add URL'),
  ('knowledgeBase.qaPairAdded', 'knowledgeBase', 'qaPairAdded', 'Q&A pair added'),
  ('knowledgeBase.failedToAddQA', 'knowledgeBase', 'failedToAddQA', 'Failed to add Q&A'),
  ('knowledgeBase.articleCreated', 'knowledgeBase', 'articleCreated', 'Article created'),
  ('knowledgeBase.failedToCreateArticle', 'knowledgeBase', 'failedToCreateArticle', 'Failed to create article'),
  ('knowledgeBase.failedToUpdate', 'knowledgeBase', 'failedToUpdate', 'Failed to update'),
  ('knowledgeBase.entryDeleted', 'knowledgeBase', 'entryDeleted', 'Entry deleted'),
  ('knowledgeBase.failedToDelete', 'knowledgeBase', 'failedToDelete', 'Failed to delete'),
  ('knowledgeBase.entryUpdated', 'knowledgeBase', 'entryUpdated', 'Entry updated'),
  ('knowledgeBase.failedToSave', 'knowledgeBase', 'failedToSave', 'Failed to save'),
  ('knowledgeBase.reindexing', 'knowledgeBase', 'reindexing', 'Re-indexing {{count}} entries for semantic search'),
  ('knowledgeBase.failedToReindex', 'knowledgeBase', 'failedToReindex', 'Failed to start re-indexing'),
  ('knowledgeBase.tabs.documents', 'knowledgeBase', 'tabs.documents', 'Documents'),
  ('knowledgeBase.tabs.urls', 'knowledgeBase', 'tabs.urls', 'Website URLs'),
  ('knowledgeBase.tabs.qa', 'knowledgeBase', 'tabs.qa', 'Q&A Pairs'),
  ('knowledgeBase.tabs.articles', 'knowledgeBase', 'tabs.articles', 'Articles'),
  ('knowledgeBase.reindex.indexing', 'knowledgeBase', 'reindex.indexing', 'Indexing…'),
  ('knowledgeBase.reindex.button', 'knowledgeBase', 'reindex.button', 'Re-index All'),
  ('knowledgeBase.documents.uploading.title', 'knowledgeBase', 'documents.uploading.title', 'Uploading and processing...'),
  ('knowledgeBase.documents.uploading.subtitle', 'knowledgeBase', 'documents.uploading.subtitle', 'Extracting text content from your files'),
  ('knowledgeBase.documents.dropzone.title', 'knowledgeBase', 'documents.dropzone.title', 'Drop files here or click to upload'),
  ('knowledgeBase.documents.dropzone.subtitle', 'knowledgeBase', 'documents.dropzone.subtitle', 'Supports PDF, TXT, JPEG, PNG — max 20MB per file'),
  ('knowledgeBase.documents.dropzone.button', 'knowledgeBase', 'documents.dropzone.button', 'Choose Files'),
  ('knowledgeBase.documents.listTitle', 'knowledgeBase', 'documents.listTitle', 'Uploaded Documents'),
  ('knowledgeBase.documents.pages', 'knowledgeBase', 'documents.pages', 'pages'),
  ('knowledgeBase.urls.add', 'knowledgeBase', 'urls.add', 'Add URL'),
  ('knowledgeBase.urls.formTitle', 'knowledgeBase', 'urls.formTitle', 'Add Website URL'),
  ('knowledgeBase.urls.adding', 'knowledgeBase', 'urls.adding', 'Adding...'),
  ('knowledgeBase.urls.submit', 'knowledgeBase', 'urls.submit', 'Add & Crawl'),
  ('knowledgeBase.urls.empty', 'knowledgeBase', 'urls.empty', 'No URLs added yet'),
  ('knowledgeBase.urls.crawling', 'knowledgeBase', 'urls.crawling', 'Crawling page content...'),
  ('knowledgeBase.qa.add', 'knowledgeBase', 'qa.add', 'Add Q&A Pair'),
  ('knowledgeBase.qa.formTitle', 'knowledgeBase', 'qa.formTitle', 'New Q&A Pair'),
  ('knowledgeBase.qa.questionLabel', 'knowledgeBase', 'qa.questionLabel', 'Question'),
  ('knowledgeBase.qa.questionPlaceholder', 'knowledgeBase', 'qa.questionPlaceholder', 'e.g. What are your opening hours?'),
  ('knowledgeBase.qa.answerLabel', 'knowledgeBase', 'qa.answerLabel', 'Answer'),
  ('knowledgeBase.qa.answerPlaceholder', 'knowledgeBase', 'qa.answerPlaceholder', 'Provide a clear, helpful answer...'),
  ('knowledgeBase.qa.save', 'knowledgeBase', 'qa.save', 'Save Pair'),
  ('knowledgeBase.qa.empty', 'knowledgeBase', 'qa.empty', 'No Q&A pairs yet'),
  ('knowledgeBase.articles.add', 'knowledgeBase', 'articles.add', 'New Article'),
  ('knowledgeBase.articles.formTitle', 'knowledgeBase', 'articles.formTitle', 'New Article'),
  ('knowledgeBase.articles.titleLabel', 'knowledgeBase', 'articles.titleLabel', 'Title'),
  ('knowledgeBase.articles.titlePlaceholder', 'knowledgeBase', 'articles.titlePlaceholder', 'e.g. Our Story, Special Events Policy'),
  ('knowledgeBase.articles.contentLabel', 'knowledgeBase', 'articles.contentLabel', 'Content'),
  ('knowledgeBase.articles.contentPlaceholder', 'knowledgeBase', 'articles.contentPlaceholder', 'Write your article content here. This will be searchable by your AI agent...'),
  ('knowledgeBase.articles.save', 'knowledgeBase', 'articles.save', 'Save Article'),
  ('knowledgeBase.articles.empty', 'knowledgeBase', 'articles.empty', 'No articles yet'),
  ('knowledgeBase.articles.emptySubtitle', 'knowledgeBase', 'articles.emptySubtitle', 'Write articles about your restaurant for the AI to reference'),
  ('menuManagement.saveChanges', 'menuManagement', 'saveChanges', 'Save Changes'),
  ('menuManagement.displayOrder', 'menuManagement', 'displayOrder', 'Display Order'),
  ('menuManagement.displayOrderDesc', 'menuManagement', 'displayOrderDesc', 'Lower numbers appear first in the menu'),
  ('menuManagement.editMenuItem', 'menuManagement', 'editMenuItem', 'Edit Menu Item'),
  ('menuManagement.manageMenuItemDetails', 'menuManagement', 'manageMenuItemDetails', 'Manage menu item details, pricing, and availability'),
  ('menuManagement.itemNameIsRequired', 'menuManagement', 'itemNameIsRequired', 'Item name is required'),
  ('menuManagement.nameMinLength', 'menuManagement', 'nameMinLength', 'Name must be at least 2 characters'),
  ('menuManagement.priceIsRequired', 'menuManagement', 'priceIsRequired', 'Price is required'),
  ('menuManagement.priceGreaterThanZero', 'menuManagement', 'priceGreaterThanZero', 'Please enter a valid price greater than 0'),
  ('menuManagement.selectCategory', 'menuManagement', 'selectCategory', 'Please select a category'),
  ('common.saveChanges', 'common', 'saveChanges', 'Save Changes'),
  ('menuManagement.itemNameLabel', 'menuManagement', 'itemNameLabel', 'Item Name *'),
  ('menuManagement.priceLabel', 'menuManagement', 'priceLabel', 'Price *'),
  ('menuManagement.selectCategoryPlaceholder', 'menuManagement', 'selectCategoryPlaceholder', 'Select category'),
  ('menuManagement.sortOrder', 'menuManagement', 'sortOrder', 'Sort Order'),
  ('menuManagement.dietaryTags', 'menuManagement', 'dietaryTags', 'Dietary Tags'),
  ('menuManagement.itemImage', 'menuManagement', 'itemImage', 'Item Image'),
  ('menuManagement.chooseImage', 'menuManagement', 'chooseImage', 'Choose Image'),
  ('menuManagement.preview', 'menuManagement', 'preview', 'Preview'),
  ('menuManagement.editModifierGroup', 'menuManagement', 'editModifierGroup', 'Edit Modifier Group'),
  ('menuManagement.modifierGroupSettings', 'menuManagement', 'modifierGroupSettings', 'Modifier Group Settings'),
  ('menuManagement.groupName', 'menuManagement', 'groupName', 'Group Name'),
  ('menuManagement.singleSelect', 'menuManagement', 'singleSelect', 'Single Select'),
  ('menuManagement.singleSelectDesc', 'menuManagement', 'singleSelectDesc', 'Customer picks one option'),
  ('menuManagement.multiSelect', 'menuManagement', 'multiSelect', 'Multi Select'),
  ('menuManagement.multiSelectDesc', 'menuManagement', 'multiSelectDesc', 'Customer picks multiple options'),
  ('menuManagement.minSelections', 'menuManagement', 'minSelections', 'Min Selections'),
  ('menuManagement.maxSelections', 'menuManagement', 'maxSelections', 'Max Selections'),
  ('menuManagement.optionsCount', 'menuManagement', 'optionsCount', 'Options ({{count}})'),
  ('menuManagement.requiredSelection', 'menuManagement', 'requiredSelection', 'Required Selection'),
  ('menuManagement.requiredSelectionDesc', 'menuManagement', 'requiredSelectionDesc', 'Customer must choose before adding to cart'),
  ('menuManagement.requiredLabel', 'menuManagement', 'requiredLabel', 'Required'),
  ('menuManagement.single', 'menuManagement', 'single', 'Single'),
  ('menuManagement.multi', 'menuManagement', 'multi', 'Multi'),
  ('menuManagement.missingItemName', 'menuManagement', 'missingItemName', 'Missing item name'),
  ('menuManagement.reviewItems', 'menuManagement', 'reviewItems', 'Review Items'),
  ('menuManagement.saving', 'menuManagement', 'saving', 'Saving'),
  ('menuManagement.complete', 'menuManagement', 'complete', 'Complete'),
  ('menuManagement.chooseFile', 'menuManagement', 'chooseFile', 'Choose File'),
  ('menuManagement.howItWorks', 'menuManagement', 'howItWorks', 'How it works'),
  ('menuManagement.itemsFound', 'menuManagement', 'itemsFound', '{{count}} items found'),
  ('menuManagement.rejectErrors', 'menuManagement', 'rejectErrors', 'Reject Errors'),
  ('common.approve', 'common', 'approve', 'Approve'),
  ('common.reject', 'common', 'reject', 'Reject'),
  ('menuManagement.saveApprovedItems', 'menuManagement', 'saveApprovedItems', 'Save {{count}} Approved Items'),
  ('menuManagement.savingMenuItems', 'menuManagement', 'savingMenuItems', 'Saving menu items…'),
  ('menuManagement.savingProgress', 'menuManagement', 'savingProgress', '{{progress}}% complete'),
  ('menuManagement.itemsSaved', 'menuManagement', 'itemsSaved', '{{count}} items saved'),
  ('menuManagement.itemsFailed', 'menuManagement', 'itemsFailed', '{{count}} failed'),
  ('menuManagement.saveResults', 'menuManagement', 'saveResults', 'Save Results'),
  ('menuManagement.saved', 'menuManagement', 'saved', 'Saved'),
  ('nav.menuManagement', 'nav', 'menuManagement', 'Menu Management'),
  ('nav.menuManagementSubtitle', 'nav', 'menuManagementSubtitle', 'Manage items, categories, modifiers and bulk uploads'),
  ('menuManagement.failedToLoad', 'menuManagement', 'failedToLoad', 'Failed to load menu'),
  ('common.failedToUpdate', 'common', 'failedToUpdate', 'Failed to update'),
  ('menuManagement.itemDeleted', 'menuManagement', 'itemDeleted', 'Item deleted'),
  ('menuManagement.itemNameRequired', 'menuManagement', 'itemNameRequired', 'Item name is required'),
  ('menuManagement.itemCreated', 'menuManagement', 'itemCreated', 'Item created'),
  ('menuManagement.itemUpdated', 'menuManagement', 'itemUpdated', 'Item updated'),
  ('menuManagement.saveFailed', 'menuManagement', 'saveFailed', 'Save failed'),
  ('menuManagement.itemNameStar', 'menuManagement', 'itemNameStar', 'Item Name *'),
  ('menuManagement.properties', 'menuManagement', 'properties', 'Properties'),
  ('menuManagement.spice', 'menuManagement', 'spice', 'Spice'),
  ('menuManagement.spiceNo', 'menuManagement', 'spiceNo', 'No Spice'),
  ('menuManagement.spiceMild', 'menuManagement', 'spiceMild', 'Mild'),
  ('menuManagement.spiceMedium', 'menuManagement', 'spiceMedium', 'Medium'),
  ('menuManagement.spiceHot', 'menuManagement', 'spiceHot', 'Hot'),
  ('menuManagement.groupNamePlaceholder', 'menuManagement', 'groupNamePlaceholder', 'Group name (e.g. Choose Size, Add-ons)'),
  ('menuManagement.radioPickOne', 'menuManagement', 'radioPickOne', 'Radio (Pick one)'),
  ('menuManagement.checkboxPickMany', 'menuManagement', 'checkboxPickMany', 'Checkbox (Pick many)'),
  ('menuManagement.create', 'menuManagement', 'create', 'Create'),
  ('menuManagement.noModifierGroups', 'menuManagement', 'noModifierGroups', 'No modifier groups yet. Add sizes, add-ons, or sides.'),
  ('menuManagement.priceDeltaPlaceholder', 'menuManagement', 'priceDeltaPlaceholder', '₹ delta'),
  ('menuManagement.defBadge', 'menuManagement', 'defBadge', 'Def'),
  ('menuManagement.saveItemFirstToAddModifierGroups', 'menuManagement', 'saveItemFirstToAddModifierGroups', 'Save item first to add modifier groups (sizes, add-ons, sides).'),
  ('common.savingDots', 'common', 'savingDots', 'Saving…'),
  ('menuManagement.failedToLoadModifierGroups', 'menuManagement', 'failedToLoadModifierGroups', 'Failed to load modifier groups'),
  ('menuManagement.selectItemAndEnterName', 'menuManagement', 'selectItemAndEnterName', 'Select an item and enter a group name'),
  ('menuManagement.groupUpdated', 'menuManagement', 'groupUpdated', 'Group updated'),
  ('menuManagement.failedToUpdateGroup', 'menuManagement', 'failedToUpdateGroup', 'Failed to update group'),
  ('menuManagement.groupDeleted', 'menuManagement', 'groupDeleted', 'Group deleted'),
  ('menuManagement.failedToDeleteGroup', 'menuManagement', 'failedToDeleteGroup', 'Failed to delete group'),
  ('menuManagement.failedToAddOption', 'menuManagement', 'failedToAddOption', 'Failed to add option'),
  ('menuManagement.optionUpdated', 'menuManagement', 'optionUpdated', 'Option updated'),
  ('menuManagement.failedToUpdateOption', 'menuManagement', 'failedToUpdateOption', 'Failed to update option'),
  ('menuManagement.failedToDeleteOption', 'menuManagement', 'failedToDeleteOption', 'Failed to delete option'),
  ('menuManagement.loadingModifierGroups', 'menuManagement', 'loadingModifierGroups', 'Loading modifier groups…'),
  ('menuManagement.newModifierGroup', 'menuManagement', 'newModifierGroup', 'New Modifier Group'),
  ('menuManagement.selectItemPlaceholder', 'menuManagement', 'selectItemPlaceholder', 'Select item…'),
  ('menuManagement.radioPickOneLong', 'menuManagement', 'radioPickOneLong', '⦿ Radio — pick one'),
  ('menuManagement.checkboxPickManyLong', 'menuManagement', 'checkboxPickManyLong', '☑ Checkbox — pick many'),
  ('menuManagement.createGroup', 'menuManagement', 'createGroup', 'Create Group'),
  ('menuManagement.noModifierGroupsYet', 'menuManagement', 'noModifierGroupsYet', 'No modifier groups yet'),
  ('menuManagement.noModifierGroupsDesc', 'menuManagement', 'noModifierGroupsDesc', 'Add sizes, add-ons, or side options for your menu items'),
  ('menuManagement.forItem', 'menuManagement', 'forItem', 'for: {{item}}'),
  ('menuManagement.defaultBadge', 'menuManagement', 'defaultBadge', 'Default'),
  ('menuManagement.optionNamePlaceholder', 'menuManagement', 'optionNamePlaceholder', 'Option name (e.g. Large)'),
  ('menuManagement.extraPricePlaceholder', 'menuManagement', 'extraPricePlaceholder', '₹ extra'),
  ('notifications.back_to_list', 'notifications', 'back_to_list', 'Back to Notifications'),
  ('notifications.saved', 'notifications', 'saved', 'Saved!'),
  ('notifications.saving', 'notifications', 'saving', 'Saving…'),
  ('notifications.save_preferences', 'notifications', 'save_preferences', 'Save Preferences'),
  ('notifications.channels', 'notifications', 'channels', 'Channels:'),
  ('notifications.channel_in_app', 'notifications', 'channel_in_app', 'In-App'),
  ('notifications.channel_email', 'notifications', 'channel_email', 'Email'),
  ('notifications.channel_sms', 'notifications', 'channel_sms', 'SMS'),
  ('notifications.loading_preferences', 'notifications', 'loading_preferences', 'Loading preferences…'),
  ('notifications.events_count', 'notifications', 'events_count', 'events'),
  ('notifications.event_column', 'notifications', 'event_column', 'Event'),
  ('notifications.typeOrders', 'notifications', 'typeOrders', 'Orders'),
  ('notifications.typeBookings', 'notifications', 'typeBookings', 'Bookings'),
  ('notifications.typeAi', 'notifications', 'typeAi', 'AI Alerts'),
  ('notifications.typeSystem', 'notifications', 'typeSystem', 'System'),
  ('notifications.typeBilling', 'notifications', 'typeBilling', 'Billing'),
  ('notifications.typeStaff', 'notifications', 'typeStaff', 'Staff'),
  ('notifications.errorLoad', 'notifications', 'errorLoad', 'Failed to load notifications: '),
  ('notifications.errorMarkAllRead', 'notifications', 'errorMarkAllRead', 'Failed to mark all read: '),
  ('notifications.errorMarkRead', 'notifications', 'errorMarkRead', 'Failed to mark read: '),
  ('notifications.errorDelete', 'notifications', 'errorDelete', 'Failed to delete notification: '),
  ('notifications.filterAll', 'notifications', 'filterAll', 'All'),
  ('notifications.markAllRead', 'notifications', 'markAllRead', 'Mark all read ({count})'),
  ('notifications.preferences', 'notifications', 'preferences', 'Preferences'),
  ('notifications.unreadMessage', 'notifications', 'unreadMessage', 'You have {count} unread notification{plural}'),
  ('notifications.noNotifications', 'notifications', 'noNotifications', 'No notifications'),
  ('notifications.markAsRead', 'notifications', 'markAsRead', 'Mark as read'),
  ('notifications.delete', 'notifications', 'delete', 'Delete'),
  ('orderManagement.load_error', 'orderManagement', 'load_error', 'Failed to load order'),
  ('orderManagement.update_status_error', 'orderManagement', 'update_status_error', 'Failed to update status'),
  ('orderManagement.not_found', 'orderManagement', 'not_found', 'Order not found'),
  ('orderManagement.back_to_list', 'orderManagement', 'back_to_list', 'Back to Orders'),
  ('orderManagement.edit_order', 'orderManagement', 'edit_order', 'Edit Order'),
  ('orderManagement.order_status', 'orderManagement', 'order_status', 'Order Status'),
  ('orderManagement.order_items', 'orderManagement', 'order_items', 'Order Items'),
  ('orderManagement.no_items', 'orderManagement', 'no_items', 'No items in this order'),
  ('orderManagement.subtotal', 'orderManagement', 'subtotal', 'Subtotal'),
  ('orderManagement.tax', 'orderManagement', 'tax', 'Tax (10%)'),
  ('orderManagement.total', 'orderManagement', 'total', 'Total'),
  ('orderManagement.special_note', 'orderManagement', 'special_note', 'Special Note'),
  ('orderManagement.customer', 'orderManagement', 'customer', 'Customer'),
  ('orderManagement.view_full_profile', 'orderManagement', 'view_full_profile', 'View Full Profile'),
  ('orderManagement.order_info', 'orderManagement', 'order_info', 'Order Info'),
  ('orderManagement.order_id', 'orderManagement', 'order_id', 'Order ID'),
  ('orderManagement.placed', 'orderManagement', 'placed', 'Placed'),
  ('orderManagement.channel', 'orderManagement', 'channel', 'Channel'),
  ('orderManagement.branch', 'orderManagement', 'branch', 'Branch'),
  ('orderManagement.branch_default', 'orderManagement', 'branch_default', 'Default'),
  ('orderManagement.loadFailed', 'orderManagement', 'loadFailed', 'Failed to load orders: '),
  ('orderManagement.statusUpdated', 'orderManagement', 'statusUpdated', 'Order status updated'),
  ('orderManagement.updateFailed', 'orderManagement', 'updateFailed', 'Failed to update order: '),
  ('orderManagement.bulkUpdateFailed', 'orderManagement', 'bulkUpdateFailed', 'Failed to update orders: '),
  ('orderManagement.deleteFailed', 'orderManagement', 'deleteFailed', 'Failed to delete orders: '),
  ('orderManagement.exported', 'orderManagement', 'exported', 'Orders exported'),
  ('orderManagement.searchPlaceholder', 'orderManagement', 'searchPlaceholder', 'Search by customer name...'),
  ('common.fromDate', 'common', 'fromDate', 'From date'),
  ('common.toDate', 'common', 'toDate', 'To date'),
  ('common.clearDates', 'common', 'clearDates', 'Clear dates'),
  ('orderManagement.changeStatus', 'orderManagement', 'changeStatus', 'Change Status'),
  ('common.refreshNow', 'common', 'refreshNow', 'Refresh now'),
  ('orderManagement.noOrdersFound', 'orderManagement', 'noOrdersFound', 'No orders found'),
  ('orderManagement.noOrdersDescription', 'orderManagement', 'noOrdersDescription', 'Orders will appear here when customers place them'),
  ('orderManagement.orderNum', 'orderManagement', 'orderNum', 'Order #'),
  ('orderManagement.type', 'orderManagement', 'type', 'Type'),
  ('orderManagement.items', 'orderManagement', 'items', 'Items'),
  ('orderManagement.status', 'orderManagement', 'status', 'Status'),
  ('orderManagement.placedAt', 'orderManagement', 'placedAt', 'Placed At'),
  ('orderManagement.deliveryType.dineIn', 'orderManagement', 'deliveryType.dineIn', '🍽️ Dine-In'),
  ('orderManagement.deliveryType.takeaway', 'orderManagement', 'deliveryType.takeaway', '🛍️ Takeaway'),
  ('orderManagement.deliveryType.delivery', 'orderManagement', 'deliveryType.delivery', '🚚 Delivery'),
  ('common.viewDetails', 'common', 'viewDetails', 'View details'),
  ('common.noItems', 'common', 'noItems', 'No items'),
  ('common.perPage', 'common', 'perPage', 'Per page:'),
  ('orderManagement.deleteConfirmTitle', 'orderManagement', 'deleteConfirmTitle', 'Delete Orders'),
  ('orderManagement.newOrderReceived', 'orderManagement', 'newOrderReceived', 'New Order Received!'),
  ('orderManagement.order', 'orderManagement', 'order', 'Order'),
  ('orderManagement.orders', 'orderManagement', 'orders', 'Orders'),
  ('common.dismiss', 'common', 'dismiss', 'Dismiss'),
  ('orderManagement.totalOrders', 'orderManagement', 'totalOrders', 'Total Orders'),
  ('orderManagement.totalOrdersSub', 'orderManagement', 'totalOrdersSub', '{count} orders total'),
  ('orderManagement.revenue', 'orderManagement', 'revenue', 'Revenue'),
  ('orderManagement.revenueSub', 'orderManagement', 'revenueSub', 'From completed orders'),
  ('orderManagement.pending', 'orderManagement', 'pending', 'Pending'),
  ('orderManagement.pendingSub', 'orderManagement', 'pendingSub', '{count} awaiting action'),
  ('orderManagement.cancelled', 'orderManagement', 'cancelled', 'Cancelled'),
  ('orderManagement.cancelledSub', 'orderManagement', 'cancelledSub', '{count} cancelled'),
  ('orderManagement.completed', 'orderManagement', 'completed', 'Completed'),
  ('orderManagement.completedSub', 'orderManagement', 'completedSub', '{rate}% completion rate'),
  ('orderManagement.completionRate', 'orderManagement', 'completionRate', 'Completion Rate'),
  ('orderManagement.completionRateSub', 'orderManagement', 'completionRateSub', 'Of all orders'),
  ('orderManagement.errorNoItems', 'orderManagement', 'errorNoItems', 'Order must have at least one item'),
  ('orderManagement.errorNoCustomerName', 'orderManagement', 'errorNoCustomerName', 'Customer name is required'),
  ('orderManagement.editOrderDescription', 'orderManagement', 'editOrderDescription', 'Changes will be marked as modified'),
  ('orderManagement.customerNamePlaceholder', 'orderManagement', 'customerNamePlaceholder', 'Customer name'),
  ('orderManagement.customerPhonePlaceholder', 'orderManagement', 'customerPhonePlaceholder', 'Phone number (optional)'),
  ('orderManagement.orderType', 'orderManagement', 'orderType', 'Order Type'),
  ('orderManagement.deliveryAddress', 'orderManagement', 'deliveryAddress', 'Delivery Address'),
  ('orderManagement.deliveryAddressPlaceholder', 'orderManagement', 'deliveryAddressPlaceholder', 'Enter delivery address'),
  ('orderManagement.tableNumber', 'orderManagement', 'tableNumber', 'Table Number'),
  ('orderManagement.tableNumberPlaceholder', 'orderManagement', 'tableNumberPlaceholder', 'e.g. 5'),
  ('orderManagement.addItem', 'orderManagement', 'addItem', 'Add Item'),
  ('orderManagement.itemNamePlaceholder', 'orderManagement', 'itemNamePlaceholder', 'Item name'),
  ('orderManagement.removeItem', 'orderManagement', 'removeItem', 'Remove item'),
  ('orderManagement.noItemsEdit', 'orderManagement', 'noItemsEdit', 'No items. Add at least one.'),
  ('orderManagement.specialInstructions', 'orderManagement', 'specialInstructions', 'Special Instructions'),
  ('orderManagement.specialInstructionsPlaceholder', 'orderManagement', 'specialInstructionsPlaceholder', 'Any special instructions...'),
  ('orderManagement.allowPopupsToPrint', 'orderManagement', 'allowPopupsToPrint', 'Please allow pop-ups to print'),
  ('orderManagement.dineIn', 'orderManagement', 'dineIn', 'Dine-In'),
  ('orderManagement.takeaway', 'orderManagement', 'takeaway', 'Takeaway'),
  ('orderManagement.delivery', 'orderManagement', 'delivery', 'Delivery'),
  ('orderManagement.restaurant', 'orderManagement', 'restaurant', 'Restaurant'),
  ('orderManagement.poweredByRestroAgent', 'orderManagement', 'poweredByRestroAgent', 'Powered by RestroAgent'),
  ('orderManagement.printed', 'orderManagement', 'printed', 'Printed'),
  ('orderManagement.table', 'orderManagement', 'table', 'Table'),
  ('orderManagement.thankYouForOrder', 'orderManagement', 'thankYouForOrder', 'Thank you for your order!'),
  ('orderManagement.haveGreatMeal', 'orderManagement', 'haveGreatMeal', 'Have a great meal 🙏'),
  ('orderManagement.printOrder', 'orderManagement', 'printOrder', 'Print order'),
  ('orderManagement.editOrder', 'orderManagement', 'editOrder', 'Edit order'),
  ('orderManagement.close', 'orderManagement', 'close', 'Close'),
  ('orderManagement.aiConfidenceScore', 'orderManagement', 'aiConfidenceScore', 'AI Confidence Score'),
  ('orderManagement.voiceOrder', 'orderManagement', 'voiceOrder', 'Voice Order'),
  ('orderManagement.na', 'orderManagement', 'na', 'N/A'),
  ('orderManagement.orderModifiedAfterAI', 'orderManagement', 'orderModifiedAfterAI', 'Order was modified after AI confirmation'),
  ('orderManagement.voice', 'orderManagement', 'voice', 'voice'),
  ('orderManagement.chat', 'orderManagement', 'chat', 'chat'),
  ('orderManagement.session', 'orderManagement', 'session', 'Session'),
  ('orderManagement.orderItems', 'orderManagement', 'orderItems', 'Order Items'),
  ('orderManagement.note', 'orderManagement', 'note', 'Note'),
  ('orderManagement.aiConversationSummary', 'orderManagement', 'aiConversationSummary', 'AI Conversation Summary'),
  ('orderManagement.openingFullTranscript', 'orderManagement', 'openingFullTranscript', 'Opening full transcript viewer'),
  ('orderManagement.viewFullTranscript', 'orderManagement', 'viewFullTranscript', 'View full transcript'),
  ('orderManagement.updateStatus', 'orderManagement', 'updateStatus', 'Update Status'),
  ('orderManagement.orderStatusUpdated', 'orderManagement', 'orderStatusUpdated', 'Order {orderId} status updated to {status}'),
  ('restApi.endpoints.listOrders', 'restApi', 'endpoints.listOrders', 'List all orders with filters and pagination'),
  ('restApi.endpoints.getOrder', 'restApi', 'endpoints.getOrder', 'Get a single order by ID'),
  ('restApi.endpoints.createOrder', 'restApi', 'endpoints.createOrder', 'Create a new order'),
  ('restApi.endpoints.updateOrder', 'restApi', 'endpoints.updateOrder', 'Update order status or details'),
  ('restApi.endpoints.listBookings', 'restApi', 'endpoints.listBookings', 'List all table bookings'),
  ('restApi.endpoints.createBooking', 'restApi', 'endpoints.createBooking', 'Create a new table booking'),
  ('restApi.endpoints.cancelBooking', 'restApi', 'endpoints.cancelBooking', 'Cancel a booking'),
  ('restApi.endpoints.listCustomers', 'restApi', 'endpoints.listCustomers', 'List all customers'),
  ('restApi.endpoints.getCustomer', 'restApi', 'endpoints.getCustomer', 'Get customer profile and order history'),
  ('restApi.endpoints.listMenuItems', 'restApi', 'endpoints.listMenuItems', 'List all menu items'),
  ('restApi.endpoints.createMenuItem', 'restApi', 'endpoints.createMenuItem', 'Create a new menu item'),
  ('restApi.endpoints.analyticsSummary', 'restApi', 'endpoints.analyticsSummary', 'Get revenue and order analytics summary'),
  ('restApi.endpoints.listConversations', 'restApi', 'endpoints.listConversations', 'List AI conversations'),
  ('restApi.endpoints.takeoverConversation', 'restApi', 'endpoints.takeoverConversation', 'Take over an AI conversation'),
  ('restApi.stats.activeKeys', 'restApi', 'stats.activeKeys', 'Active API Keys'),
  ('restApi.stats.monthlyCalls', 'restApi', 'stats.monthlyCalls', 'API Calls (Month)'),
  ('restApi.stats.apiVersion', 'restApi', 'stats.apiVersion', 'API Version'),
  ('restApi.stats.baseUrl', 'restApi', 'stats.baseUrl', 'Base URL'),
  ('restApi.newKey.title', 'restApi', 'newKey.title', 'API key generated — copy it now'),
  ('restApi.newKey.subtitle', 'restApi', 'newKey.subtitle', 'This is the only time you can see the full key.'),
  ('common.copy', 'common', 'copy', 'Copy'),
  ('restApi.usage.title', 'restApi', 'usage.title', 'API Usage — Last 7 Days'),
  ('restApi.keys.title', 'restApi', 'keys.title', 'API Keys'),
  ('restApi.keys.generate', 'restApi', 'keys.generate', 'Generate New Key'),
  ('restApi.addForm.title', 'restApi', 'addForm.title', 'Generate New API Key'),
  ('restApi.addForm.nameLabel', 'restApi', 'addForm.nameLabel', 'Key Name *'),
  ('restApi.addForm.namePlaceholder', 'restApi', 'addForm.namePlaceholder', 'e.g. My POS Integration'),
  ('restApi.addForm.permissionsLabel', 'restApi', 'addForm.permissionsLabel', 'Permissions'),
  ('restApi.addForm.submit', 'restApi', 'addForm.submit', 'Generate Key'),
  ('restApi.loading', 'restApi', 'loading', 'Loading API keys…'),
  ('restApi.noKeys.title', 'restApi', 'noKeys.title', 'No API keys yet'),
  ('restApi.noKeys.subtitle', 'restApi', 'noKeys.subtitle', 'Generate a key to start integrating with RestroAgent'),
  ('restApi.keys.revoked', 'restApi', 'keys.revoked', 'Revoked'),
  ('restApi.keys.created', 'restApi', 'keys.created', 'Created'),
  ('restApi.keys.lastUsed', 'restApi', 'keys.lastUsed', 'Last used:'),
  ('restApi.keys.callsMonth', 'restApi', 'keys.callsMonth', 'calls this month'),
  ('restApi.keys.revoke', 'restApi', 'keys.revoke', 'Revoke'),
  ('restApi.reference.title', 'restApi', 'reference.title', 'API Endpoint Reference'),
  ('restApi.reference.endpoints', 'restApi', 'reference.endpoints', 'endpoints'),
  ('restApi.reference.baseUrl', 'restApi', 'reference.baseUrl', 'Base URL:'),
  ('restApi.reference.baseUrlPrefix', 'restApi', 'reference.baseUrlPrefix', 'Base URL:'),
  ('restApi.reference.auth', 'restApi', 'reference.auth', 'Bearer token required'),
  ('dashboard.conversationFeed', 'dashboard', 'conversationFeed', 'Conversation Feed'),
  ('dashboard.recentAiSessions', 'dashboard', 'recentAiSessions', 'Recent AI Sessions'),
  ('dashboard.noConversations', 'dashboard', 'noConversations', 'No conversations'),
  ('dashboard.noConversationsYet', 'dashboard', 'noConversationsYet', 'No conversations yet'),
  ('dashboard.voiceAgent', 'dashboard', 'voiceAgent', 'Voice Agent'),
  ('dashboard.chatAgent', 'dashboard', 'chatAgent', 'Chat Agent'),
  ('dashboard.aiAgentStatus', 'dashboard', 'aiAgentStatus', 'AI Agent Status'),
  ('dashboard.unableToLoadConfig', 'dashboard', 'unableToLoadConfig', 'Unable to load agent config'),
  ('dashboard.checkAiConfig', 'dashboard', 'checkAiConfig', 'Check AI configuration in settings'),
  ('dashboard.model', 'dashboard', 'model', 'Model'),
  ('dashboard.allSystemsOperational', 'dashboard', 'allSystemsOperational', 'All Systems Operational'),
  ('dashboard.aiAgent', 'dashboard', 'aiAgent', 'AI Agent'),
  ('dashboard.active', 'dashboard', 'active', 'Active'),
  ('dashboard.calls', 'dashboard', 'calls', 'calls'),
  ('dashboard.chats', 'dashboard', 'chats', 'chats'),
  ('dashboard.confidence', 'dashboard', 'confidence', 'Confidence'),
  ('dashboard.noRecentIncidents', 'dashboard', 'noRecentIncidents', 'No recent incidents'),
  ('dashboard.agentDisabled', 'dashboard', 'agentDisabled', 'Agent disabled in config'),
  ('dashboard.total', 'dashboard', 'total', 'Total'),
  ('dashboard.voiceVsChatToday', 'dashboard', 'voiceVsChatToday', 'Voice vs Chat — Today'),
  ('dashboard.voiceVsChat7Days', 'dashboard', 'voiceVsChat7Days', 'Voice vs Chat — Last 7 Days'),
  ('dashboard.voiceVsChatMonth', 'dashboard', 'voiceVsChatMonth', 'Voice vs Chat — This Month'),
  ('dashboard.voiceVsChatLifetime', 'dashboard', 'voiceVsChatLifetime', 'Voice vs Chat — All Time'),
  ('dashboard.channelBreakdown', 'dashboard', 'channelBreakdown', 'Channel Breakdown'),
  ('dashboard.voice', 'dashboard', 'voice', 'Voice'),
  ('dashboard.chat', 'dashboard', 'chat', 'Chat'),
  ('dashboard.loadingChartData', 'dashboard', 'loadingChartData', 'Loading chart data...'),
  ('dashboard.noChannelData', 'dashboard', 'noChannelData', 'No channel data yet'),
  ('dashboard.channelBreakdownAppear', 'dashboard', 'channelBreakdownAppear', 'Channel breakdown will appear as orders come in'),
  ('dashboard.escalationMarkedHandled', 'dashboard', 'escalationMarkedHandled', 'Escalation marked as handled'),
  ('dashboard.escalationsRequiringAttention', 'dashboard', 'escalationsRequiringAttention', 'Escalations Requiring Attention'),
  ('dashboard.noEscalations', 'dashboard', 'noEscalations', 'No escalations right now'),
  ('dashboard.aiHandlingAutonomously', 'dashboard', 'aiHandlingAutonomously', 'Your AI agent is handling all conversations autonomously'),
  ('dashboard.needsHumanAttention', 'dashboard', 'needsHumanAttention', 'Needs human attention'),
  ('dashboard.dismissEscalation', 'dashboard', 'dismissEscalation', 'Dismiss escalation'),
  ('dashboard.takeOver', 'dashboard', 'takeOver', 'Take Over'),
  ('dashboard.ofAllConversations', 'dashboard', 'ofAllConversations', 'of all conversations'),
  ('dashboard.fullyResolvedByAi', 'dashboard', 'fullyResolvedByAi', 'fully resolved by AI'),
  ('period.7days', 'period', '7days', '7 Days'),
  ('period.allTime', 'period', 'allTime', 'All Time'),
  ('dashboard.agentResolutionRate', 'dashboard', 'agentResolutionRate', 'Agent Resolution Rate'),
  ('dashboard.aiResolvedNoHandoff', 'dashboard', 'aiResolvedNoHandoff', 'AI-resolved without human handoff'),
  ('dashboard.aiConfidence', 'dashboard', 'aiConfidence', 'AI Confidence'),
  ('dashboard.escalationRate', 'dashboard', 'escalationRate', 'Escalation Rate'),
  ('dashboard.needsAgent', 'dashboard', 'needsAgent', 'Needs Agent'),
  ('dashboard.totalOrderValueProcessed', 'dashboard', 'totalOrderValueProcessed', 'Total order value processed'),
  ('dashboard.activeEscalations', 'dashboard', 'activeEscalations', 'Active Escalations'),
  ('dashboard.convsNeedingAttention', 'dashboard', 'convsNeedingAttention', 'Conversations needing human attention'),
  ('dashboard.fullyFulfilledOrders', 'dashboard', 'fullyFulfilledOrders', 'Fully fulfilled orders'),
  ('dashboard.aiAccuracy', 'dashboard', 'aiAccuracy', 'AI Accuracy'),
  ('dashboard.hourlyActivityToday', 'dashboard', 'hourlyActivityToday', 'Hourly Activity — Today'),
  ('dashboard.ordersReservationsByHour', 'dashboard', 'ordersReservationsByHour', 'Orders & Reservations by Hour'),
  ('dashboard.liveData', 'dashboard', 'liveData', 'Live data'),
  ('common.loadingChartData', 'common', 'loadingChartData', 'Loading chart data...'),
  ('dashboard.noActivityToday', 'dashboard', 'noActivityToday', 'No activity yet today'),
  ('dashboard.noActivityTodayDesc', 'dashboard', 'noActivityTodayDesc', 'Orders and reservations will appear here as they come in'),
  ('dashboard.now', 'dashboard', 'now', 'Now'),
  ('dashboard.orders', 'dashboard', 'orders', 'Orders'),
  ('dashboard.reservations', 'dashboard', 'reservations', 'Reservations'),
  ('nav.agentOverview', 'nav', 'agentOverview', 'Agent Overview'),
  ('common.days.monday', 'common', 'days.monday', 'Monday'),
  ('common.days.tuesday', 'common', 'days.tuesday', 'Tuesday'),
  ('common.days.wednesday', 'common', 'days.wednesday', 'Wednesday'),
  ('common.days.thursday', 'common', 'days.thursday', 'Thursday'),
  ('common.days.friday', 'common', 'days.friday', 'Friday'),
  ('common.days.saturday', 'common', 'days.saturday', 'Saturday'),
  ('common.days.sunday', 'common', 'days.sunday', 'Sunday'),
  ('restaurantSettings.billing.usage.conversations', 'restaurantSettings', 'billing.usage.conversations', 'AI Conversations'),
  ('restaurantSettings.billing.usage.voiceMinutes', 'restaurantSettings', 'billing.usage.voiceMinutes', 'Voice Minutes'),
  ('restaurantSettings.billing.usage.branches', 'restaurantSettings', 'billing.usage.branches', 'Branches'),
  ('restaurantSettings.billing.usage.apiCalls', 'restaurantSettings', 'billing.usage.apiCalls', 'API Calls'),
  ('restaurantSettings.billing.usage.units.conversations', 'restaurantSettings', 'billing.usage.units.conversations', 'conversations'),
  ('restaurantSettings.billing.usage.units.voiceMinutes', 'restaurantSettings', 'billing.usage.units.voiceMinutes', 'minutes'),
  ('restaurantSettings.billing.usage.units.branches', 'restaurantSettings', 'billing.usage.units.branches', 'branches'),
  ('restaurantSettings.billing.usage.units.apiCalls', 'restaurantSettings', 'billing.usage.units.apiCalls', 'calls'),
  ('restaurantSettings.templates.vars.customerName', 'restaurantSettings', 'templates.vars.customerName', 'Customer Name'),
  ('restaurantSettings.templates.vars.orderId', 'restaurantSettings', 'templates.vars.orderId', 'Order ID'),
  ('restaurantSettings.templates.vars.orderItems', 'restaurantSettings', 'templates.vars.orderItems', 'Order Items'),
  ('restaurantSettings.templates.vars.orderTotal', 'restaurantSettings', 'templates.vars.orderTotal', 'Order Total'),
  ('restaurantSettings.templates.vars.estimatedTime', 'restaurantSettings', 'templates.vars.estimatedTime', 'Estimated Time'),
  ('restaurantSettings.templates.vars.restaurantName', 'restaurantSettings', 'templates.vars.restaurantName', 'Restaurant Name'),
  ('restaurantSettings.templates.vars.trackingLink', 'restaurantSettings', 'templates.vars.trackingLink', 'Tracking Link'),
  ('restaurantSettings.templates.vars.bookingId', 'restaurantSettings', 'templates.vars.bookingId', 'Booking ID'),
  ('restaurantSettings.templates.vars.bookingDate', 'restaurantSettings', 'templates.vars.bookingDate', 'Booking Date'),
  ('restaurantSettings.templates.vars.bookingTime', 'restaurantSettings', 'templates.vars.bookingTime', 'Booking Time'),
  ('restaurantSettings.templates.vars.partySize', 'restaurantSettings', 'templates.vars.partySize', 'Party Size'),
  ('restaurantSettings.templates.vars.tableNumber', 'restaurantSettings', 'templates.vars.tableNumber', 'Table Number'),
  ('restaurantSettings.templates.vars.restaurantAddress', 'restaurantSettings', 'templates.vars.restaurantAddress', 'Restaurant Address'),
  ('restaurantSettings.templates.vars.cancelLink', 'restaurantSettings', 'templates.vars.cancelLink', 'Cancel Link'),
  ('restaurantSettings.templates.vars.alertType', 'restaurantSettings', 'templates.vars.alertType', 'Alert Type'),
  ('restaurantSettings.templates.vars.alertMessage', 'restaurantSettings', 'templates.vars.alertMessage', 'Alert Message'),
  ('restaurantSettings.templates.vars.supportLink', 'restaurantSettings', 'templates.vars.supportLink', 'Support Link'),
  ('restaurantSettings.templates.orderConfirmation.label', 'restaurantSettings', 'templates.orderConfirmation.label', 'Order Confirmation'),
  ('restaurantSettings.templates.orderConfirmation.description', 'restaurantSettings', 'templates.orderConfirmation.description', 'Sent when a customer order is successfully placed.'),
  ('restaurantSettings.templates.bookingConfirmation.label', 'restaurantSettings', 'templates.bookingConfirmation.label', 'Booking Confirmation'),
  ('restaurantSettings.templates.bookingConfirmation.description', 'restaurantSettings', 'templates.bookingConfirmation.description', 'Sent when a table reservation is confirmed.'),
  ('restaurantSettings.templates.customerAlert.label', 'restaurantSettings', 'templates.customerAlert.label', 'Customer Alert'),
  ('restaurantSettings.templates.customerAlert.description', 'restaurantSettings', 'templates.customerAlert.description', 'Sent to notify customers about delays or updates.'),
  ('common.sms', 'common', 'sms', 'SMS'),
  ('common.whatsapp', 'common', 'whatsapp', 'WhatsApp'),
  ('common.inApp', 'common', 'inApp', 'In-App'),
  ('marketplace.square.name', 'marketplace', 'square.name', 'Square POS'),
  ('marketplace.square.description', 'marketplace', 'square.description', 'Sync orders, menu items, and inventory directly from your Square point-of-sale system.'),
  ('marketplace.square.step1.title', 'marketplace', 'square.step1.title', 'Create a Square Developer Account'),
  ('marketplace.square.step1.desc', 'marketplace', 'square.step1.desc', 'Go to developer.squareup.com and sign in with your Square account.'),
  ('marketplace.square.step2.title', 'marketplace', 'square.step2.title', 'Generate API Credentials'),
  ('marketplace.square.step2.desc', 'marketplace', 'square.step2.desc', 'Create a new application and copy your Application ID and Access Token.'),
  ('marketplace.square.step3.title', 'marketplace', 'square.step3.title', 'Enter Credentials in RestroAgent'),
  ('marketplace.square.step3.desc', 'marketplace', 'square.step3.desc', 'Paste your Application ID and Access Token and click Authorize.'),
  ('marketplace.square.step4.title', 'marketplace', 'square.step4.title', 'Select Location'),
  ('marketplace.square.step4.desc', 'marketplace', 'square.step4.desc', 'Choose which Square location to sync with this RestroAgent branch.'),
  ('marketplace.square.step5.title', 'marketplace', 'square.step5.title', 'Configure Sync Settings'),
  ('marketplace.square.step5.desc', 'marketplace', 'square.step5.desc', 'Choose what data to sync: menu items, inventory levels, orders, and customer data.'),
  ('marketplace.toast.name', 'marketplace', 'toast.name', 'Toast POS'),
  ('marketplace.toast.description', 'marketplace', 'toast.description', 'Connect Toast to automatically import your menu, manage orders, and track sales in real time.'),
  ('marketplace.toast.step1.title', 'marketplace', 'toast.step1.title', 'Access Toast Developer Portal'),
  ('marketplace.toast.step1.desc', 'marketplace', 'toast.step1.desc', 'Log in to your Toast account and navigate to Settings > Integrations > Developer Portal.'),
  ('marketplace.toast.step2.title', 'marketplace', 'toast.step2.title', 'Create an API Token'),
  ('marketplace.toast.step2.desc', 'marketplace', 'toast.step2.desc', 'Under API Access, generate a new token with read/write permissions.'),
  ('marketplace.toast.step3.title', 'marketplace', 'toast.step3.title', 'Copy Restaurant GUID'),
  ('marketplace.toast.step3.desc', 'marketplace', 'toast.step3.desc', 'Find your Restaurant GUID in Toast under Settings > Restaurant Information.'),
  ('marketplace.toast.step4.title', 'marketplace', 'toast.step4.title', 'Connect to RestroAgent'),
  ('marketplace.toast.step4.desc', 'marketplace', 'toast.step4.desc', 'Enter your API Token and Restaurant GUID and click Connect.'),
  ('marketplace.toast.step5.title', 'marketplace', 'toast.step5.title', 'Map Menu Categories'),
  ('marketplace.toast.step5.desc', 'marketplace', 'toast.step5.desc', 'Map your Toast menu categories to RestroAgent categories.'),
  ('marketplace.stripe.name', 'marketplace', 'stripe.name', 'Stripe Payments'),
  ('marketplace.stripe.description', 'marketplace', 'stripe.description', 'Accept online payments, manage subscriptions, and process refunds through Stripe.'),
  ('marketplace.stripe.step1.title', 'marketplace', 'stripe.step1.title', 'Log in to Stripe Dashboard'),
  ('marketplace.stripe.step1.desc', 'marketplace', 'stripe.step1.desc', 'Go to dashboard.stripe.com and navigate to Developers > API Keys.'),
  ('marketplace.stripe.step2.title', 'marketplace', 'stripe.step2.title', 'Copy Publishable & Secret Keys'),
  ('marketplace.stripe.step2.desc', 'marketplace', 'stripe.step2.desc', 'Copy both your Publishable Key and Secret Key.'),
  ('marketplace.stripe.step3.title', 'marketplace', 'stripe.step3.title', 'Add Keys to RestroAgent'),
  ('marketplace.stripe.step3.desc', 'marketplace', 'stripe.step3.desc', 'Paste both keys in the Stripe connection form.'),
  ('marketplace.stripe.step4.title', 'marketplace', 'stripe.step4.title', 'Configure Webhook Endpoint'),
  ('marketplace.stripe.step4.desc', 'marketplace', 'stripe.step4.desc', 'In Stripe, add a webhook endpoint pointing to your RestroAgent webhook URL.'),
  ('marketplace.stripe.step5.title', 'marketplace', 'stripe.step5.title', 'Test the Integration'),
  ('marketplace.stripe.step5.desc', 'marketplace', 'stripe.step5.desc', 'Use Stripe test mode to process a test payment.'),
  ('marketplace.doordash.name', 'marketplace', 'doordash.name', 'DoorDash Drive'),
  ('marketplace.doordash.description', 'marketplace', 'doordash.description', 'Dispatch delivery drivers on-demand through DoorDash Drive for your own online orders.'),
  ('marketplace.doordash.step1.title', 'marketplace', 'doordash.step1.title', 'Apply for DoorDash Drive Access'),
  ('marketplace.doordash.step1.desc', 'marketplace', 'doordash.step1.desc', 'Visit developer.doordash.com and apply for Drive API access.'),
  ('marketplace.doordash.step2.title', 'marketplace', 'doordash.step2.title', 'Get API Key'),
  ('marketplace.doordash.step2.desc', 'marketplace', 'doordash.step2.desc', 'Once approved, generate an API key under your application settings.'),
  ('marketplace.doordash.step3.title', 'marketplace', 'doordash.step3.title', 'Configure Delivery Zone'),
  ('marketplace.doordash.step3.desc', 'marketplace', 'doordash.step3.desc', 'Set your restaurant address and maximum delivery radius.'),
  ('marketplace.doordash.step4.title', 'marketplace', 'doordash.step4.title', 'Connect to RestroAgent'),
  ('marketplace.doordash.step4.desc', 'marketplace', 'doordash.step4.desc', 'Enter your API key and restaurant address in the DoorDash connection form.'),
  ('marketplace.doordash.step5.title', 'marketplace', 'doordash.step5.title', 'Set Dispatch Rules'),
  ('marketplace.doordash.step5.desc', 'marketplace', 'doordash.step5.desc', 'Configure when to auto-dispatch and set estimated prep times.'),
  ('marketplace.hubspot.name', 'marketplace', 'hubspot.name', 'HubSpot CRM'),
  ('marketplace.hubspot.description', 'marketplace', 'hubspot.description', 'Sync customer profiles, order history, and AI conversation data to HubSpot.'),
  ('marketplace.hubspot.step1.title', 'marketplace', 'hubspot.step1.title', 'Create a HubSpot Private App'),
  ('marketplace.hubspot.step1.desc', 'marketplace', 'hubspot.step1.desc', 'In HubSpot, go to Settings > Integrations > Private Apps and create a new app.'),
  ('marketplace.hubspot.step2.title', 'marketplace', 'hubspot.step2.title', 'Copy Access Token'),
  ('marketplace.hubspot.step2.desc', 'marketplace', 'hubspot.step2.desc', 'Copy the access token generated for your private app.'),
  ('marketplace.hubspot.step3.title', 'marketplace', 'hubspot.step3.title', 'Connect to RestroAgent'),
  ('marketplace.hubspot.step3.desc', 'marketplace', 'hubspot.step3.desc', 'Enter your API Key and Audience ID in the HubSpot connection form.'),
  ('marketplace.hubspot.step4.title', 'marketplace', 'hubspot.step4.title', 'Set Subscription Rules'),
  ('marketplace.hubspot.step4.desc', 'marketplace', 'hubspot.step4.desc', 'Choose which customer actions trigger a Mailchimp subscription.'),
  ('marketplace.twilio.name', 'marketplace', 'twilio.name', 'Twilio SMS'),
  ('marketplace.twilio.description', 'marketplace', 'twilio.description', 'Send SMS notifications for order confirmations, booking reminders, and customer alerts via Twilio.'),
  ('marketplace.twilio.step1.title', 'marketplace', 'twilio.step1.title', 'Create a Twilio Account'),
  ('marketplace.twilio.step1.desc', 'marketplace', 'twilio.step1.desc', 'Sign up at twilio.com and verify your phone number.'),
  ('marketplace.twilio.step2.title', 'marketplace', 'twilio.step2.title', 'Get Account SID and Auth Token'),
  ('marketplace.twilio.step2.desc', 'marketplace', 'twilio.step2.desc', 'From the Twilio Console dashboard, copy your Account SID and Auth Token.'),
  ('marketplace.twilio.step3.title', 'marketplace', 'twilio.step3.title', 'Purchase a Phone Number'),
  ('marketplace.twilio.step3.desc', 'marketplace', 'twilio.step3.desc', 'Buy a Twilio phone number to use as the sender for SMS messages.'),
  ('marketplace.twilio.step4.title', 'marketplace', 'twilio.step4.title', 'Connect to RestroAgent'),
  ('marketplace.twilio.step4.desc', 'marketplace', 'twilio.step4.desc', 'Enter your Account SID, Auth Token, and Twilio phone number.'),
  ('marketplace.google-analytics.name', 'marketplace', 'google-analytics.name', 'Google Analytics'),
  ('marketplace.google-analytics.description', 'marketplace', 'google-analytics.description', 'Track customer journeys, conversion funnels, and AI agent performance in Google Analytics 4.'),
  ('marketplace.ga.step1.title', 'marketplace', 'ga.step1.title', 'Create a GA4 Property'),
  ('marketplace.ga.step1.desc', 'marketplace', 'ga.step1.desc', 'In Google Analytics, create a new GA4 property for your restaurant.'),
  ('marketplace.ga.step2.title', 'marketplace', 'ga.step2.title', 'Get Measurement ID'),
  ('marketplace.ga.step2.desc', 'marketplace', 'ga.step2.desc', 'Go to Admin > Data Streams > Web and copy your Measurement ID.'),
  ('marketplace.ga.step3.title', 'marketplace', 'ga.step3.title', 'Enter Measurement ID'),
  ('marketplace.ga.step3.desc', 'marketplace', 'ga.step3.desc', 'Paste your Measurement ID in the Google Analytics connection form.'),
  ('marketplace.ga.step4.title', 'marketplace', 'ga.step4.title', 'Verify Data Flow'),
  ('marketplace.ga.step4.desc', 'marketplace', 'ga.step4.desc', 'Use the GA4 DebugView to confirm events are being received.'),
  ('marketplace.mailchimp.name', 'marketplace', 'mailchimp.name', 'Mailchimp'),
  ('marketplace.mailchimp.description', 'marketplace', 'mailchimp.description', 'Automatically add customers to Mailchimp lists and trigger email campaigns based on order behavior.'),
  ('marketplace.mailchimp.step1.title', 'marketplace', 'mailchimp.step1.title', 'Get Mailchimp API Key'),
  ('marketplace.mailchimp.step1.desc', 'marketplace', 'mailchimp.step1.desc', 'In Mailchimp, go to Account > Extras > API Keys and generate a new key.'),
  ('marketplace.mailchimp.step2.title', 'marketplace', 'mailchimp.step2.title', 'Find Your Audience ID'),
  ('marketplace.mailchimp.step2.desc', 'marketplace', 'mailchimp.step2.desc', 'Navigate to Audience > All Contacts > Settings to find your Audience ID.'),
  ('marketplace.mailchimp.step3.title', 'marketplace', 'mailchimp.step3.title', 'Connect in RestroAgent'),
  ('marketplace.mailchimp.step3.desc', 'marketplace', 'mailchimp.step3.desc', 'Enter your API Key and Audience ID in the Mailchimp connection form.'),
  ('currency.USD', 'currency', 'USD', 'US Dollar'),
  ('currency.EUR', 'currency', 'EUR', 'Euro'),
  ('currency.GBP', 'currency', 'GBP', 'British Pound'),
  ('currency.INR', 'currency', 'INR', 'Indian Rupee'),
  ('currency.AED', 'currency', 'AED', 'UAE Dirham'),
  ('currency.SAR', 'currency', 'SAR', 'Saudi Riyal'),
  ('currency.CAD', 'currency', 'CAD', 'Canadian Dollar'),
  ('currency.AUD', 'currency', 'AUD', 'Australian Dollar'),
  ('currency.SGD', 'currency', 'SGD', 'Singapore Dollar'),
  ('currency.MYR', 'currency', 'MYR', 'Malaysian Ringgit'),
  ('currency.THB', 'currency', 'THB', 'Thai Baht'),
  ('currency.PHP', 'currency', 'PHP', 'Philippine Peso'),
  ('currency.IDR', 'currency', 'IDR', 'Indonesian Rupiah'),
  ('currency.JPY', 'currency', 'JPY', 'Japanese Yen'),
  ('currency.KRW', 'currency', 'KRW', 'South Korean Won'),
  ('currency.CNY', 'currency', 'CNY', 'Chinese Yuan'),
  ('currency.HKD', 'currency', 'HKD', 'Hong Kong Dollar'),
  ('currency.TWD', 'currency', 'TWD', 'Taiwan Dollar'),
  ('currency.NZD', 'currency', 'NZD', 'New Zealand Dollar'),
  ('currency.ZAR', 'currency', 'ZAR', 'South African Rand'),
  ('currency.BRL', 'currency', 'BRL', 'Brazilian Real'),
  ('currency.MXN', 'currency', 'MXN', 'Mexican Peso'),
  ('currency.CLP', 'currency', 'CLP', 'Chilean Peso'),
  ('currency.COP', 'currency', 'COP', 'Colombian Peso'),
  ('currency.ARS', 'currency', 'ARS', 'Argentine Peso'),
  ('currency.PEN', 'currency', 'PEN', 'Peruvian Sol'),
  ('currency.TRY', 'currency', 'TRY', 'Turkish Lira'),
  ('currency.EGP', 'currency', 'EGP', 'Egyptian Pound'),
  ('currency.NGN', 'currency', 'NGN', 'Nigerian Naira'),
  ('currency.KES', 'currency', 'KES', 'Kenyan Shilling'),
  ('currency.GHS', 'currency', 'GHS', 'Ghanaian Cedi'),
  ('currency.PKR', 'currency', 'PKR', 'Pakistani Rupee'),
  ('currency.BDT', 'currency', 'BDT', 'Bangladeshi Taka'),
  ('currency.LKR', 'currency', 'LKR', 'Sri Lankan Rupee'),
  ('currency.NPR', 'currency', 'NPR', 'Nepalese Rupee'),
  ('currency.QAR', 'currency', 'QAR', 'Qatari Riyal'),
  ('currency.KWD', 'currency', 'KWD', 'Kuwaiti Dinar'),
  ('currency.BHD', 'currency', 'BHD', 'Bahraini Dinar'),
  ('currency.OMR', 'currency', 'OMR', 'Omani Rial'),
  ('currency.JOD', 'currency', 'JOD', 'Jordanian Dinar'),
  ('currency.CHF', 'currency', 'CHF', 'Swiss Franc'),
  ('currency.SEK', 'currency', 'SEK', 'Swedish Krona'),
  ('currency.NOK', 'currency', 'NOK', 'Norwegian Krone'),
  ('currency.DKK', 'currency', 'DKK', 'Danish Krone'),
  ('currency.PLN', 'currency', 'PLN', 'Polish Zloty'),
  ('currency.CZK', 'currency', 'CZK', 'Czech Koruna'),
  ('currency.HUF', 'currency', 'HUF', 'Hungarian Forint'),
  ('currency.RON', 'currency', 'RON', 'Romanian Leu'),
  ('currency.RUB', 'currency', 'RUB', 'Russian Ruble'),
  ('currency.UAH', 'currency', 'UAH', 'Ukrainian Hryvnia'),
  ('currency.ILS', 'currency', 'ILS', 'Israeli Shekel'),
  ('currency.VND', 'currency', 'VND', 'Vietnamese Dong'),
  ('currency.MMK', 'currency', 'MMK', 'Myanmar Kyat'),
  ('currency.KHR', 'currency', 'KHR', 'Cambodian Riel'),
  ('currency.LAK', 'currency', 'LAK', 'Lao Kip'),
  ('restaurantSettings.profile.nameRequired', 'restaurantSettings', 'profile.nameRequired', 'Restaurant name is required'),
  ('restaurantSettings.profile.savedSuccessfully', 'restaurantSettings', 'profile.savedSuccessfully', 'Profile saved successfully'),
  ('restaurantSettings.profile.failedToSave', 'restaurantSettings', 'profile.failedToSave', 'Failed to save profile'),
  ('restaurantSettings.alerts.failedToSave', 'restaurantSettings', 'alerts.failedToSave', 'Failed to save alert settings'),
  ('restaurantSettings.billing.payment.validation.cardholderRequired', 'restaurantSettings', 'billing.payment.validation.cardholderRequired', 'Cardholder name is required'),
  ('restaurantSettings.billing.payment.validation.cardNumberRequired', 'restaurantSettings', 'billing.payment.validation.cardNumberRequired', 'Card number is required'),
  ('restaurantSettings.billing.payment.validation.cardNumberInvalid', 'restaurantSettings', 'billing.payment.validation.cardNumberInvalid', 'Please enter a valid card number'),
  ('restaurantSettings.billing.payment.validation.expiryRequired', 'restaurantSettings', 'billing.payment.validation.expiryRequired', 'Expiry date is required'),
  ('restaurantSettings.billing.payment.validation.expiryFormat', 'restaurantSettings', 'billing.payment.validation.expiryFormat', 'Use MM / YY format'),
  ('restaurantSettings.billing.payment.validation.cvvRequired', 'restaurantSettings', 'billing.payment.validation.cvvRequired', 'CVV is required'),
  ('restaurantSettings.billing.payment.validation.cvvInvalid', 'restaurantSettings', 'billing.payment.validation.cvvInvalid', 'CVV must be 3 or 4 digits'),
  ('restaurantSettings.marketplace.categories.posSystems', 'restaurantSettings', 'marketplace.categories.posSystems', 'POS Systems'),
  ('restaurantSettings.marketplace.categories.paymentGateways', 'restaurantSettings', 'marketplace.categories.paymentGateways', 'Payment Gateways'),
  ('restaurantSettings.marketplace.categories.deliveryPlatforms', 'restaurantSettings', 'marketplace.categories.deliveryPlatforms', 'Delivery Platforms'),
  ('restaurantSettings.marketplace.categories.crmTools', 'restaurantSettings', 'marketplace.categories.crmTools', 'CRM Tools'),
  ('restaurantSettings.marketplace.categories.messaging', 'restaurantSettings', 'marketplace.categories.messaging', 'Messaging'),
  ('restaurantSettings.marketplace.categories.analytics', 'restaurantSettings', 'marketplace.categories.analytics', 'Analytics'),
  ('restaurantSettings.tabs.profile', 'restaurantSettings', 'tabs.profile', 'Profile'),
  ('restaurantSettings.tabs.hours', 'restaurantSettings', 'tabs.hours', 'Hours'),
  ('restaurantSettings.tabs.alerts', 'restaurantSettings', 'tabs.alerts', 'Alert Settings'),
  ('restaurantSettings.tabs.billing', 'restaurantSettings', 'tabs.billing', 'Billing'),
  ('restaurantSettings.tabs.notifications', 'restaurantSettings', 'tabs.notifications', 'Notifications'),
  ('restaurantSettings.tabs.templates', 'restaurantSettings', 'tabs.templates', 'Templates'),
  ('restaurantSettings.tabs.webhooks', 'restaurantSettings', 'tabs.webhooks', 'Webhooks'),
  ('restaurantSettings.tabs.restApi', 'restaurantSettings', 'tabs.restApi', 'Rest API'),
  ('restaurantSettings.tabs.providerKeys', 'restaurantSettings', 'tabs.providerKeys', 'AI Keys'),
  ('restaurantSettings.tabs.marketplace', 'restaurantSettings', 'tabs.marketplace', 'Marketplace'),
  ('restaurantSettings.profile.title', 'restaurantSettings', 'profile.title', 'Restaurant Profile'),
  ('restaurantSettings.profile.logo', 'restaurantSettings', 'profile.logo', 'Logo'),
  ('common.uploading', 'common', 'uploading', 'Uploading...'),
  ('restaurantSettings.profile.uploadLogo', 'restaurantSettings', 'profile.uploadLogo', 'Upload Logo'),
  ('restaurantSettings.profile.logoSubtitle', 'restaurantSettings', 'profile.logoSubtitle', 'PNG, JPG, GIF, WEBP up to 2MB'),
  ('restaurantSettings.profile.nameLabel', 'restaurantSettings', 'profile.nameLabel', 'Restaurant Name'),
  ('restaurantSettings.profile.namePlaceholder', 'restaurantSettings', 'profile.namePlaceholder', 'Restaurant name'),
  ('restaurantSettings.profile.cuisineLabel', 'restaurantSettings', 'profile.cuisineLabel', 'Cuisine Type'),
  ('restaurantSettings.profile.cuisinePlaceholder', 'restaurantSettings', 'profile.cuisinePlaceholder', 'e.g. Italian, Mexican, Contemporary American'),
  ('restaurantSettings.profile.phoneLabel', 'restaurantSettings', 'profile.phoneLabel', 'Phone Number'),
  ('restaurantSettings.profile.phonePlaceholder', 'restaurantSettings', 'profile.phonePlaceholder', '+1 (555) 000-0000'),
  ('restaurantSettings.profile.addressLabel', 'restaurantSettings', 'profile.addressLabel', 'Address'),
  ('restaurantSettings.profile.addressPlaceholder', 'restaurantSettings', 'profile.addressPlaceholder', 'Street address, city, state, zip'),
  ('restaurantSettings.profile.descriptionLabel', 'restaurantSettings', 'profile.descriptionLabel', 'Description'),
  ('restaurantSettings.profile.descriptionPlaceholder', 'restaurantSettings', 'profile.descriptionPlaceholder', 'Describe your restaurant...'),
  ('restaurantSettings.profile.seatingLabel', 'restaurantSettings', 'profile.seatingLabel', 'Seating Capacity'),
  ('restaurantSettings.profile.currencyLabel', 'restaurantSettings', 'profile.currencyLabel', 'Currency'),
  ('restaurantSettings.profile.currencyLocked', 'restaurantSettings', 'profile.currencyLocked', 'Currency is locked once set and cannot be changed. Contact support if needed.'),
  ('common.set', 'common', 'set', 'Set'),
  ('restaurantSettings.profile.currencyWarning', 'restaurantSettings', 'profile.currencyWarning', 'Choose carefully — currency cannot be changed after it is set'),
  ('restaurantSettings.profile.languageTitle', 'restaurantSettings', 'profile.languageTitle', 'Language Preference'),
  ('restaurantSettings.profile.languageSubtitle', 'restaurantSettings', 'profile.languageSubtitle', 'Choose the language for your dashboard interface'),
  ('restaurantSettings.hours.title', 'restaurantSettings', 'hours.title', 'Operating Hours'),
  ('restaurantSettings.alerts.subtitle', 'restaurantSettings', 'alerts.subtitle', 'Configure real-time order and booking alert behavior'),
  ('restaurantSettings.alerts.preview', 'restaurantSettings', 'alerts.preview', 'Preview Alert'),
  ('common.saveSettings', 'common', 'saveSettings', 'Save Settings'),
  ('restaurantSettings.alerts.sound.title', 'restaurantSettings', 'alerts.sound.title', 'Sound Notifications'),
  ('restaurantSettings.alerts.sound.enable', 'restaurantSettings', 'alerts.sound.enable', 'Enable Sound Alerts'),
  ('restaurantSettings.alerts.sound.enableSubtitle', 'restaurantSettings', 'alerts.sound.enableSubtitle', 'Play a sound when new alerts arrive'),
  ('restaurantSettings.alerts.sound.volume', 'restaurantSettings', 'alerts.sound.volume', 'Alert Volume'),
  ('restaurantSettings.alerts.dismiss.title', 'restaurantSettings', 'alerts.dismiss.title', 'Auto-Dismiss Timer'),
  ('restaurantSettings.alerts.dismiss.label', 'restaurantSettings', 'alerts.dismiss.label', 'Dismiss alerts after'),
  ('common.secondsShort', 'common', 'secondsShort', '{{sec}}s'),
  ('common.minutesShort', 'common', 'minutesShort', '{{min}}m'),
  ('restaurantSettings.alerts.dismiss.subtitle', 'restaurantSettings', 'alerts.dismiss.subtitle', 'Alerts will automatically dismiss after {{sec}} seconds if not acted upon'),
  ('restaurantSettings.alerts.types.title', 'restaurantSettings', 'alerts.types.title', 'Alert Types'),
  ('restaurantSettings.alerts.types.orders', 'restaurantSettings', 'alerts.types.orders', 'New Orders'),
  ('restaurantSettings.alerts.types.ordersSubtitle', 'restaurantSettings', 'alerts.types.ordersSubtitle', 'Show alert when a new order is placed'),
  ('restaurantSettings.alerts.types.bookings', 'restaurantSettings', 'alerts.types.bookings', 'New Bookings'),
  ('restaurantSettings.alerts.types.bookingsSubtitle', 'restaurantSettings', 'alerts.types.bookingsSubtitle', 'Show alert when a table is reserved'),
  ('restaurantSettings.alerts.types.aiEscalations', 'restaurantSettings', 'alerts.types.aiEscalations', 'AI Escalations'),
  ('restaurantSettings.alerts.types.aiEscalationsSubtitle', 'restaurantSettings', 'alerts.types.aiEscalationsSubtitle', 'Show alert when AI hands off to staff'),
  ('restaurantSettings.alerts.browser.title', 'restaurantSettings', 'alerts.browser.title', 'Browser Notifications'),
  ('restaurantSettings.alerts.browser.enable', 'restaurantSettings', 'alerts.browser.enable', 'Enable Browser Notifications'),
  ('restaurantSettings.alerts.browser.enableSubtitle', 'restaurantSettings', 'alerts.browser.enableSubtitle', 'Receive alerts even when the tab is not in focus'),
  ('restaurantSettings.alerts.browser.permissionNote', 'restaurantSettings', 'alerts.browser.permissionNote', 'Browser will request notification permission when you save these settings.'),
  ('restaurantSettings.billing.tabs.overview', 'restaurantSettings', 'billing.tabs.overview', 'Overview'),
  ('restaurantSettings.billing.tabs.plans', 'restaurantSettings', 'billing.tabs.plans', 'Plans'),
  ('restaurantSettings.billing.tabs.payment', 'restaurantSettings', 'billing.tabs.payment', 'Payment Methods'),
  ('restaurantSettings.billing.tabs.invoices', 'restaurantSettings', 'billing.tabs.invoices', 'Invoices'),
  ('restaurantSettings.billing.loading', 'restaurantSettings', 'billing.loading', 'Loading billing data…'),
  ('restaurantSettings.billing.planName', 'restaurantSettings', 'billing.planName', '{name} Plan'),
  ('restaurantSettings.billing.planPrice', 'restaurantSettings', 'billing.planPrice', '{price}/month'),
  ('restaurantSettings.billing.upgrade', 'restaurantSettings', 'billing.upgrade', 'Upgrade Plan'),
  ('restaurantSettings.billing.change', 'restaurantSettings', 'billing.change', 'Change Plan'),
  ('restaurantSettings.billing.usageTitle', 'restaurantSettings', 'billing.usageTitle', 'Usage This Month'),
  ('common.unlimited', 'common', 'unlimited', 'Unlimited'),
  ('restaurantSettings.billing.usage.ofLimit', 'restaurantSettings', 'billing.usage.ofLimit', 'of {{limit}} {{unit}}'),
  ('restaurantSettings.billing.usage.pctUsed', 'restaurantSettings', 'billing.usage.pctUsed', '{{pct}}% used'),
  ('restaurantSettings.billing.upgradeNow', 'restaurantSettings', 'billing.upgradeNow', 'Upgrade →'),
  ('restaurantSettings.billing.currentPlan', 'restaurantSettings', 'billing.currentPlan', 'Current Plan'),
  ('restaurantSettings.billing.plan', 'restaurantSettings', 'billing.plan', 'Plan'),
  ('restaurantSettings.billing.cycle.label', 'restaurantSettings', 'billing.cycle.label', 'Billing Cycle:'),
  ('common.monthly', 'common', 'monthly', 'monthly'),
  ('common.annual', 'common', 'annual', 'annual'),
  ('restaurantSettings.billing.features.branches', 'restaurantSettings', 'billing.features.branches', 'branches'),
  ('restaurantSettings.billing.features.conversations', 'restaurantSettings', 'billing.features.conversations', '{count} AI conversations/mo'),
  ('restaurantSettings.billing.features.voiceMinutes', 'restaurantSettings', 'billing.features.voiceMinutes', '{count} voice minutes'),
  ('restaurantSettings.billing.features.apiCalls', 'restaurantSettings', 'billing.features.apiCalls', '{count} API calls'),
  ('restaurantSettings.billing.popular', 'restaurantSettings', 'billing.popular', 'Most Popular'),
  ('common.mo', 'common', 'mo', 'mo'),
  ('restaurantSettings.billing.saveAnnual', 'restaurantSettings', 'billing.saveAnnual', 'Save ' || chr(36) || '{{amount}}/year'),
  ('common.upgrade', 'common', 'upgrade', 'Upgrade'),
  ('common.downgrade', 'common', 'downgrade', 'Downgrade'),
  ('restaurantSettings.billing.payment.title', 'restaurantSettings', 'billing.payment.title', 'Saved Payment Methods'),
  ('restaurantSettings.billing.payment.addCard', 'restaurantSettings', 'billing.payment.addCard', 'Add Card'),
  ('restaurantSettings.billing.payment.noMethods', 'restaurantSettings', 'billing.payment.noMethods', 'No payment methods on file'),
  ('restaurantSettings.billing.payment.noMethodsSubtitle', 'restaurantSettings', 'billing.payment.noMethodsSubtitle', 'Add a card to enable billing'),
  ('restaurantSettings.billing.payment.addForm.title', 'restaurantSettings', 'billing.payment.addForm.title', 'Add New Card'),
  ('restaurantSettings.billing.payment.addForm.cardholderName', 'restaurantSettings', 'billing.payment.addForm.cardholderName', 'Cardholder Name'),
  ('restaurantSettings.billing.payment.addForm.cardholderNamePlaceholder', 'restaurantSettings', 'billing.payment.addForm.cardholderNamePlaceholder', 'Name on card'),
  ('restaurantSettings.billing.payment.addForm.cardNumber', 'restaurantSettings', 'billing.payment.addForm.cardNumber', 'Card Number'),
  ('restaurantSettings.billing.payment.addForm.cardNumberPlaceholder', 'restaurantSettings', 'billing.payment.addForm.cardNumberPlaceholder', '1234 5678 9012 3456'),
  ('restaurantSettings.billing.payment.addForm.expiry', 'restaurantSettings', 'billing.payment.addForm.expiry', 'Expiry Date'),
  ('restaurantSettings.billing.payment.addForm.expiryPlaceholder', 'restaurantSettings', 'billing.payment.addForm.expiryPlaceholder', 'MM / YY'),
  ('restaurantSettings.billing.payment.addForm.cvv', 'restaurantSettings', 'billing.payment.addForm.cvv', 'CVV'),
  ('restaurantSettings.billing.payment.addForm.cvvPlaceholder', 'restaurantSettings', 'billing.payment.addForm.cvvPlaceholder', '•••'),
  ('restaurantSettings.billing.payment.addForm.securityNote', 'restaurantSettings', 'billing.payment.addForm.securityNote', 'Your card details are encrypted and stored securely.'),
  ('restaurantSettings.billing.payment.addForm.save', 'restaurantSettings', 'billing.payment.addForm.save', 'Save Card'),
  ('restaurantSettings.billing.invoices.title', 'restaurantSettings', 'billing.invoices.title', 'Invoice History'),
  ('restaurantSettings.billing.invoices.noInvoices', 'restaurantSettings', 'billing.invoices.noInvoices', 'No invoices yet'),
  ('restaurantSettings.billing.invoices.noInvoicesSubtitle', 'restaurantSettings', 'billing.invoices.noInvoicesSubtitle', 'Invoices will appear here once billing is active'),
  ('restaurantSettings.notifications.loading', 'restaurantSettings', 'notifications.loading', 'Loading preferences…'),
  ('restaurantSettings.notifications.save', 'restaurantSettings', 'notifications.save', 'Save Preferences'),
  ('restaurantSettings.templates.title', 'restaurantSettings', 'templates.title', 'Templates'),
  ('common.soon', 'common', 'soon', 'Soon'),
  ('common.preview', 'common', 'preview', 'Preview'),
  ('restaurantSettings.templates.variables.title', 'restaurantSettings', 'templates.variables.title', 'Variable Placeholders — click to insert, or copy'),
  ('restaurantSettings.templates.editor.placeholder', 'restaurantSettings', 'templates.editor.placeholder', 'Enter your message template here...'),
  ('restaurantSettings.templates.charCount', 'restaurantSettings', 'templates.charCount', '{{count}} characters'),
  ('restaurantSettings.templates.smsSegments', 'restaurantSettings', 'templates.smsSegments', '{{count}} SMS segments'),
  ('restaurantSettings.templates.save', 'restaurantSettings', 'templates.save', 'Save Template'),
  ('restaurantSettings.templates.reset', 'restaurantSettings', 'templates.reset', 'Reset to Default'),
  ('restaurantSettings.templates.preview.title', 'restaurantSettings', 'templates.preview.title', 'Live Preview'),
  ('restaurantSettings.templates.preview.subtitle', 'restaurantSettings', 'templates.preview.subtitle', 'Variables replaced with example values'),
  ('common.restaurantName', 'common', 'restaurantName', 'The Rustic Fork'),
  ('common.notification', 'common', 'notification', 'Notification'),
  ('restaurantSettings.webhooks.stats.active', 'restaurantSettings', 'webhooks.stats.active', 'Active Endpoints'),
  ('restaurantSettings.webhooks.stats.deliveries', 'restaurantSettings', 'webhooks.stats.deliveries', 'Total Deliveries'),
  ('restaurantSettings.webhooks.stats.failed', 'restaurantSettings', 'webhooks.stats.failed', 'Failed (24h)'),
  ('restaurantSettings.webhooks.stats.successRate', 'restaurantSettings', 'webhooks.stats.successRate', 'Avg Success Rate'),
  ('restaurantSettings.webhooks.title', 'restaurantSettings', 'webhooks.title', 'Webhook Endpoints'),
  ('restaurantSettings.webhooks.add', 'restaurantSettings', 'webhooks.add', 'Add Endpoint'),
  ('restaurantSettings.webhooks.addForm.title', 'restaurantSettings', 'webhooks.addForm.title', 'New Webhook Endpoint'),
  ('restaurantSettings.webhooks.addForm.url', 'restaurantSettings', 'webhooks.addForm.url', 'Endpoint URL *'),
  ('restaurantSettings.webhooks.addForm.urlPlaceholder', 'restaurantSettings', 'webhooks.addForm.urlPlaceholder', 'https://your-app.com/webhooks'),
  ('restaurantSettings.webhooks.addForm.events', 'restaurantSettings', 'webhooks.addForm.events', 'Subscribe to Events *'),
  ('restaurantSettings.webhooks.addForm.save', 'restaurantSettings', 'webhooks.addForm.save', 'Save Endpoint'),
  ('restaurantSettings.webhooks.loading', 'restaurantSettings', 'webhooks.loading', 'Loading webhooks…'),
  ('restaurantSettings.webhooks.empty', 'restaurantSettings', 'webhooks.empty', 'No webhook endpoints yet. Add one above.'),
  ('restaurantSettings.webhooks.secret', 'restaurantSettings', 'webhooks.secret', 'Secret:'),
  ('restaurantSettings.webhooks.stats', 'restaurantSettings', 'webhooks.stats', '{{rate}}% success · {{deliveries}} deliveries'),
  ('common.deactivate', 'common', 'deactivate', 'Deactivate'),
  ('common.activate', 'common', 'activate', 'Activate'),
  ('restaurantSettings.webhooks.logs.title', 'restaurantSettings', 'webhooks.logs.title', 'Delivery Logs'),
  ('restaurantSettings.webhooks.logs.loading', 'restaurantSettings', 'webhooks.logs.loading', 'Loading logs…'),
  ('restaurantSettings.webhooks.logs.empty', 'restaurantSettings', 'webhooks.logs.empty', 'No delivery logs yet. Logs will appear here as events are triggered.'),
  ('restaurantSettings.webhooks.logs.headers.event', 'restaurantSettings', 'webhooks.logs.headers.event', 'Event'),
  ('restaurantSettings.webhooks.logs.headers.endpoint', 'restaurantSettings', 'webhooks.logs.headers.endpoint', 'Endpoint'),
  ('restaurantSettings.webhooks.logs.headers.status', 'restaurantSettings', 'webhooks.logs.headers.status', 'Status'),
  ('restaurantSettings.webhooks.logs.headers.response', 'restaurantSettings', 'webhooks.logs.headers.response', 'Response'),
  ('restaurantSettings.webhooks.logs.headers.duration', 'restaurantSettings', 'webhooks.logs.headers.duration', 'Duration'),
  ('restaurantSettings.webhooks.logs.headers.timestamp', 'restaurantSettings', 'webhooks.logs.headers.timestamp', 'Timestamp'),
  ('common.failure', 'common', 'failure', 'failure'),
  ('restaurantSettings.apiKeys.generatedBanner', 'restaurantSettings', 'apiKeys.generatedBanner', 'API key generated — copy it now'),
  ('restaurantSettings.apiKeys.onlyTimeToSee', 'restaurantSettings', 'apiKeys.onlyTimeToSee', 'This is the only time you will see the full key.'),
  ('restaurantSettings.apiKeys.stats.activeKeys', 'restaurantSettings', 'apiKeys.stats.activeKeys', 'Active API Keys'),
  ('restaurantSettings.apiKeys.stats.callsMonth', 'restaurantSettings', 'apiKeys.stats.callsMonth', 'API Calls (Month)'),
  ('restaurantSettings.apiKeys.stats.version', 'restaurantSettings', 'apiKeys.stats.version', 'API Version'),
  ('restaurantSettings.apiKeys.stats.baseUrl', 'restaurantSettings', 'apiKeys.stats.baseUrl', 'Base URL'),
  ('restaurantSettings.apiKeys.usageChart', 'restaurantSettings', 'apiKeys.usageChart', 'API Usage — Last 7 Days'),
  ('restaurantSettings.apiKeys.sectionHeading', 'restaurantSettings', 'apiKeys.sectionHeading', 'API Keys'),
  ('restaurantSettings.apiKeys.generateNew', 'restaurantSettings', 'apiKeys.generateNew', 'Generate New Key'),
  ('restaurantSettings.apiKeys.addForm.heading', 'restaurantSettings', 'apiKeys.addForm.heading', 'Generate New API Key'),
  ('restaurantSettings.apiKeys.addForm.nameLabel', 'restaurantSettings', 'apiKeys.addForm.nameLabel', 'Key Name *'),
  ('restaurantSettings.apiKeys.addForm.namePlaceholder', 'restaurantSettings', 'apiKeys.addForm.namePlaceholder', 'e.g. My POS Integration'),
  ('restaurantSettings.apiKeys.addForm.permissionsLabel', 'restaurantSettings', 'apiKeys.addForm.permissionsLabel', 'Permissions *'),
  ('restaurantSettings.apiKeys.generateKeyBtn', 'restaurantSettings', 'apiKeys.generateKeyBtn', 'Generate Key'),
  ('restaurantSettings.apiKeys.loading', 'restaurantSettings', 'apiKeys.loading', 'Loading API keys…'),
  ('restaurantSettings.apiKeys.emptyState', 'restaurantSettings', 'apiKeys.emptyState', 'No API keys yet. Generate one above.'),
  ('restaurantSettings.apiKeys.revokedBadge', 'restaurantSettings', 'apiKeys.revokedBadge', 'Revoked'),
  ('restaurantSettings.apiKeys.created', 'restaurantSettings', 'apiKeys.created', 'Created'),
  ('restaurantSettings.apiKeys.lastUsed', 'restaurantSettings', 'apiKeys.lastUsed', 'Last used'),
  ('restaurantSettings.apiKeys.callsThisMonth', 'restaurantSettings', 'apiKeys.callsThisMonth', 'calls this month'),
  ('restaurantSettings.apiKeys.revokeBtn', 'restaurantSettings', 'apiKeys.revokeBtn', 'Revoke'),
  ('restaurantSettings.marketplace.title', 'restaurantSettings', 'marketplace.title', 'Marketplace'),
  ('restaurantSettings.marketplace.subtitle', 'restaurantSettings', 'marketplace.subtitle', 'Connect your favourite tools and platforms to RestroAgent'),
  ('restaurantSettings.marketplace.connected', 'restaurantSettings', 'marketplace.connected', 'connected'),
  ('restaurantSettings.marketplace.searchPlaceholder', 'restaurantSettings', 'marketplace.searchPlaceholder', 'Search integrations...'),
  ('restaurantSettings.marketplace.noIntegrations', 'restaurantSettings', 'marketplace.noIntegrations', 'No integrations found'),
  ('restaurantSettings.marketplace.noIntegrationsSubtitle', 'restaurantSettings', 'marketplace.noIntegrationsSubtitle', 'Try a different search or category'),
  ('restaurantSettings.marketplace.popular', 'restaurantSettings', 'marketplace.popular', 'Popular'),
  ('restaurantSettings.marketplace.notConnected', 'restaurantSettings', 'marketplace.notConnected', 'Not connected'),
  ('restaurantSettings.marketplace.setupGuide', 'restaurantSettings', 'marketplace.setupGuide', 'Setup Guide'),
  ('restaurantSettings.marketplace.guide', 'restaurantSettings', 'marketplace.guide', 'Guide'),
  ('settings.marketplace.connect_favorite', 'settings', 'marketplace.connect_favorite', 'Connect your favourite tools and platforms to RestroAgent'),
  ('settings.marketplace.connected', 'settings', 'marketplace.connected', 'connected'),
  ('settings.marketplace.category_all', 'settings', 'marketplace.category_all', 'All'),
  ('settings.marketplace.no_integrations', 'settings', 'marketplace.no_integrations', 'No integrations found'),
  ('settings.marketplace.guide', 'settings', 'marketplace.guide', 'Guide'),
  ('common.coming_soon', 'common', 'coming_soon', 'Coming Soon'),
  ('common.loading_templates', 'common', 'loading_templates', 'Loading templates…'),
  ('common.insert', 'common', 'insert', 'Insert'),
  ('common.characters', 'common', 'characters', 'characters'),
  ('common.chars', 'common', 'chars', 'chars'),
  ('staff.fullNameIsRequired', 'staff', 'fullNameIsRequired', 'Full name is required'),
  ('staff.nameMustBeAtLeast2Characters', 'staff', 'nameMustBeAtLeast2Characters', 'Name must be at least 2 characters'),
  ('staff.emailAddressIsRequired', 'staff', 'emailAddressIsRequired', 'Email address is required'),
  ('staff.pleaseEnterAValidEmailAddress', 'staff', 'pleaseEnterAValidEmailAddress', 'Please enter a valid email address'),
  ('staff.pleaseSelectARole', 'staff', 'pleaseSelectARole', 'Please select a role'),
  ('staff.pleaseAssignABranch', 'staff', 'pleaseAssignABranch', 'Please assign a branch'),
  ('staff.editStaffMember', 'staff', 'editStaffMember', 'Edit Staff Member'),
  ('staff.addNewStaffMember', 'staff', 'addNewStaffMember', 'Add New Staff Member'),
  ('staff.addStaff', 'staff', 'addStaff', 'Add Staff'),
  ('staff.personalInformation', 'staff', 'personalInformation', 'Personal Information'),
  ('staff.fullName', 'staff', 'fullName', 'Full Name'),
  ('staff.placeholderName', 'staff', 'placeholderName', 'John Smith'),
  ('staff.emailAddress', 'staff', 'emailAddress', 'Email Address'),
  ('staff.placeholderEmail', 'staff', 'placeholderEmail', 'john@restaurant.com'),
  ('staff.selectRole', 'staff', 'selectRole', 'Select role'),
  ('staff.branchAssignment', 'staff', 'branchAssignment', 'Branch Assignment'),
  ('staff.selectBranch', 'staff', 'selectBranch', 'Select branch'),
  ('staff.enabled', 'staff', 'enabled', 'enabled'),
  ('staff.accountStatus', 'staff', 'accountStatus', 'Account Status'),
  ('staff.activeAccount', 'staff', 'activeAccount', 'Active Account'),
  ('staff.activeAccountDesc', 'staff', 'activeAccountDesc', 'Staff can log in and access the system'),
  ('staff.roleSummary', 'staff', 'roleSummary', 'Role Summary'),
  ('staff.permissionsEnabled', 'staff', 'permissionsEnabled', 'permissions enabled'),
  ('staff.sections.dashboard', 'staff', 'sections.dashboard', 'Dashboard'),
  ('staff.sections.orders', 'staff', 'sections.orders', 'Orders'),
  ('staff.sections.reservations', 'staff', 'sections.reservations', 'Reservations'),
  ('staff.sections.menu', 'staff', 'sections.menu', 'Menu'),
  ('staff.sections.customers', 'staff', 'sections.customers', 'Customers'),
  ('staff.sections.conversations', 'staff', 'sections.conversations', 'Conversations'),
  ('staff.sections.staff', 'staff', 'sections.staff', 'Staff'),
  ('staff.sections.analytics', 'staff', 'sections.analytics', 'Analytics'),
  ('staff.sections.settings', 'staff', 'sections.settings', 'Settings'),
  ('staff.crud.create', 'staff', 'crud.create', 'Create'),
  ('staff.crud.createAbbr', 'staff', 'crud.createAbbr', 'C'),
  ('staff.crud.read', 'staff', 'crud.read', 'Read'),
  ('staff.crud.readAbbr', 'staff', 'crud.readAbbr', 'R'),
  ('staff.crud.update', 'staff', 'crud.update', 'Update'),
  ('staff.crud.updateAbbr', 'staff', 'crud.updateAbbr', 'U'),
  ('staff.crud.delete', 'staff', 'crud.delete', 'Delete'),
  ('staff.crud.deleteAbbr', 'staff', 'crud.deleteAbbr', 'D'),
  ('staff.matrix.section', 'staff', 'matrix.section', 'Section'),
  ('staff.errors.roleNameRequired', 'staff', 'errors.roleNameRequired', 'Role name is required'),
  ('staff.roleCreated', 'staff', 'roleCreated', 'Role created'),
  ('staff.roleUpdated', 'staff', 'roleUpdated', 'Role updated'),
  ('staff.errors.saveRoleFailed', 'staff', 'errors.saveRoleFailed', 'Failed to save role'),
  ('staff.newRole', 'staff', 'newRole', 'New Role'),
  ('staff.editRole', 'staff', 'editRole', 'Edit Role: {{name}}'),
  ('staff.ownerRoleDesc', 'staff', 'ownerRoleDesc', 'Owner role is read-only — all permissions are always enabled'),
  ('staff.roleNameLabel', 'staff', 'roleNameLabel', 'Role Name *'),
  ('staff.placeholders.roleName', 'staff', 'placeholders.roleName', 'e.g. Cashier'),
  ('staff.descriptionLabel', 'staff', 'descriptionLabel', 'Description'),
  ('staff.placeholders.roleDescription', 'staff', 'placeholders.roleDescription', 'Short description of this role'),
  ('staff.permissionsTitle', 'staff', 'permissionsTitle', 'Permissions'),
  ('staff.permissionsLegend', 'staff', 'permissionsLegend', 'C = Create  R = Read  U = Update  D = Delete'),
  ('staff.saving', 'staff', 'saving', 'Saving…'),
  ('staff.saveRole', 'staff', 'saveRole', 'Save Role'),
  ('staff.cancel', 'staff', 'cancel', 'Cancel'),
  ('staff.close', 'staff', 'close', 'Close'),
  ('staff.errors.nameRequired', 'staff', 'errors.nameRequired', 'Name is required'),
  ('staff.staffAdded', 'staff', 'staffAdded', 'Staff member added'),
  ('staff.staffUpdated', 'staff', 'staffUpdated', 'Staff member updated'),
  ('staff.errors.saveStaffFailed', 'staff', 'errors.saveStaffFailed', 'Failed to save staff member'),
  ('staff.addStaffMember', 'staff', 'addStaffMember', 'Add Staff Member'),
  ('staff.editStaff', 'staff', 'editStaff', 'Edit: {{name}}'),
  ('staff.fullNameLabel', 'staff', 'fullNameLabel', 'Full Name *'),
  ('staff.placeholders.fullName', 'staff', 'placeholders.fullName', 'Full name'),
  ('staff.emailLabel', 'staff', 'emailLabel', 'Email'),
  ('staff.placeholders.email', 'staff', 'placeholders.email', 'Email address'),
  ('staff.roleLabel', 'staff', 'roleLabel', 'Role'),
  ('staff.customPermissions', 'staff', 'customPermissions', 'Custom permissions'),
  ('staff.noRoleAssigned', 'staff', 'noRoleAssigned', 'No role assigned'),
  ('staff.systemRole', 'staff', 'systemRole', 'System'),
  ('staff.rolePermissionsDesc', 'staff', 'rolePermissionsDesc', 'Permissions pre-filled from {{name}} role — you can customise below.'),
  ('staff.resetToDefaults', 'staff', 'resetToDefaults', 'Reset to {{name}} defaults'),
  ('staff.save', 'staff', 'save', 'Save'),
  ('staff.pageTitle', 'staff', 'pageTitle', 'Staff & Team'),
  ('staff.pageSubtitle', 'staff', 'pageSubtitle', 'Manage roles, permissions, and staff accounts'),
  ('staff.errors.loadStaff', 'staff', 'errors.loadStaff', 'Failed to load staff: '),
  ('staff.errors.loadRoles', 'staff', 'errors.loadRoles', 'Failed to load roles: '),
  ('staff.statusUpdated', 'staff', 'statusUpdated', 'Staff status updated'),
  ('staff.errors.updateStaff', 'staff', 'errors.updateStaff', 'Failed to update staff: '),
  ('staff.staffRemoved', 'staff', 'staffRemoved', 'Staff member removed'),
  ('staff.errors.deleteStaff', 'staff', 'errors.deleteStaff', 'Failed to delete staff: '),
  ('staff.errors.deleteSystemRole', 'staff', 'errors.deleteSystemRole', 'System roles cannot be deleted'),
  ('staff.roleDeleted', 'staff', 'roleDeleted', 'Role deleted'),
  ('staff.errors.deleteRoleFailed', 'staff', 'errors.deleteRoleFailed', 'Failed to delete role'),
  ('staff.customRoleName', 'staff', 'customRoleName', '{{name}} (Custom)'),
  ('staff.defaultRoleName', 'staff', 'defaultRoleName', 'Staff'),
  ('staff.tabs.members', 'staff', 'tabs.members', 'Team Members'),
  ('staff.tabs.roles', 'staff', 'tabs.roles', 'Roles & Permissions'),
  ('staff.placeholders.searchStaff', 'staff', 'placeholders.searchStaff', 'Search staff…'),
  ('staff.noStaffMembers', 'staff', 'noStaffMembers', 'No staff members yet'),
  ('staff.addFirstMember', 'staff', 'addFirstMember', 'Add your first team member to get started'),
  ('staff.table.staffMember', 'staff', 'table.staffMember', 'Staff Member'),
  ('staff.table.role', 'staff', 'table.role', 'Role'),
  ('staff.table.permissions', 'staff', 'table.permissions', 'Permissions'),
  ('staff.table.status', 'staff', 'table.status', 'Status'),
  ('staff.table.lastActive', 'staff', 'table.lastActive', 'Last Active'),
  ('staff.edit', 'staff', 'edit', 'Edit'),
  ('staff.delete', 'staff', 'delete', 'Delete'),
  ('staff.noRoles', 'staff', 'noRoles', 'No roles yet'),
  ('staff.createFirstRole', 'staff', 'createFirstRole', 'Create a role to define permission sets for your staff'),
  ('staff.systemBadge', 'staff', 'systemBadge', 'System'),
  ('staff.fullAccessBadge', 'staff', 'fullAccessBadge', 'Full Access'),
  ('staff.noPermissions', 'staff', 'noPermissions', 'No permissions assigned'),
  ('staff.members', 'staff', 'members', 'members'),
  ('staff.member', 'staff', 'member', 'member'),
  ('staff.viewRole', 'staff', 'viewRole', 'View role'),
  ('staff.editRoleTitle', 'staff', 'editRoleTitle', 'Edit role'),
  ('staff.deleteRole', 'staff', 'deleteRole', 'Delete role'),
  ('staff.addNewRole', 'staff', 'addNewRole', 'Add New Role'),
  ('tableBooking.booking', 'tableBooking', 'booking', 'Booking'),
  ('tableBooking.editBooking', 'tableBooking', 'editBooking', 'Edit Booking'),
  ('tableBooking.bookingDetails', 'tableBooking', 'bookingDetails', 'Booking Details'),
  ('tableBooking.partySize', 'tableBooking', 'partySize', 'Party Size'),
  ('tableBooking.guests', 'tableBooking', 'guests', 'guests'),
  ('tableBooking.duration', 'tableBooking', 'duration', 'Duration'),
  ('tableBooking.table', 'tableBooking', 'table', 'Table'),
  ('tableBooking.channel', 'tableBooking', 'channel', 'Channel'),
  ('tableBooking.specialRequests', 'tableBooking', 'specialRequests', 'Special Requests'),
  ('tableBooking.updateStatus', 'tableBooking', 'updateStatus', 'Update Status'),
  ('conversations.aiConversation', 'conversations', 'aiConversation', 'AI Conversation'),
  ('customers.customer', 'customers', 'customer', 'Customer'),
  ('customers.viewFullProfile', 'customers', 'viewFullProfile', 'View Full Profile'),
  ('tableBooking.bookingInfo', 'tableBooking', 'bookingInfo', 'Booking Info'),
  ('tableBooking.bookingId', 'tableBooking', 'bookingId', 'Booking ID'),
  ('tableBooking.bookedAt', 'tableBooking', 'bookedAt', 'Booked'),
  ('branchManagement.branch', 'branchManagement', 'branch', 'Branch'),
  ('tableBooking.reservationsByTimeSlot', 'tableBooking', 'reservationsByTimeSlot', 'Reservations by time slot'),
  ('common.current', 'common', 'current', 'Current'),
  ('tableBooking.noReservationsToday', 'tableBooking', 'noReservationsToday', 'No reservations today'),
  ('tableBooking.bookingsWillAppearHere', 'tableBooking', 'bookingsWillAppearHere', 'Bookings will appear here as they are made'),
  ('tableBooking.covers', 'tableBooking', 'covers', 'covers'),
  ('tableBooking.status.processing', 'tableBooking', 'status.processing', 'AI Processing'),
  ('tableBooking.status.confirmed', 'tableBooking', 'status.confirmed', 'Confirmed'),
  ('tableBooking.status.reminderSent', 'tableBooking', 'status.reminderSent', 'Reminder Sent'),
  ('tableBooking.status.seated', 'tableBooking', 'status.seated', 'Seated'),
  ('tableBooking.status.noShow', 'tableBooking', 'status.noShow', 'No Show'),
  ('tableBooking.status.cancelled', 'tableBooking', 'status.cancelled', 'Cancelled'),
  ('tableBooking.vip', 'tableBooking', 'vip', 'VIP'),
  ('tableBooking.printing', 'tableBooking', 'printing', 'Printing booking {id}'),
  ('tableBooking.printTitle', 'tableBooking', 'printTitle', 'Print booking'),
  ('tableBooking.editing', 'tableBooking', 'editing', 'Edit booking {id}'),
  ('tableBooking.editTitle', 'tableBooking', 'editTitle', 'Edit booking'),
  ('tableBooking.aiConfidence', 'tableBooking', 'aiConfidence', 'AI Confidence Score'),
  ('tableBooking.voiceBooking', 'tableBooking', 'voiceBooking', 'Voice Booking'),
  ('tableBooking.guestDetails', 'tableBooking', 'guestDetails', 'Guest Details'),
  ('tableBooking.vipGuest', 'tableBooking', 'vipGuest', 'VIP Guest'),
  ('tableBooking.guestsCount', 'tableBooking', 'guestsCount', '{{count}} guests'),
  ('tableBooking.channels.voice', 'tableBooking', 'channels.voice', 'Voice'),
  ('tableBooking.channels.chat', 'tableBooking', 'channels.chat', 'Chat'),
  ('tableBooking.reservationDetails', 'tableBooking', 'reservationDetails', 'Reservation Details'),
  ('tableBooking.date', 'tableBooking', 'date', 'Date'),
  ('tableBooking.time', 'tableBooking', 'time', 'Time'),
  ('tableBooking.specialOccasion', 'tableBooking', 'specialOccasion', 'Special Occasion'),
  ('tableBooking.dietaryRequirements', 'tableBooking', 'dietaryRequirements', 'Dietary Requirements'),
  ('tableBooking.aiNotes', 'tableBooking', 'aiNotes', 'AI Booking Notes'),
  ('tableBooking.openingTranscript', 'tableBooking', 'openingTranscript', 'Opening full transcript viewer'),
  ('tableBooking.viewFullTranscript', 'tableBooking', 'viewFullTranscript', 'View full transcript'),
  ('tableBooking.confirmation', 'tableBooking', 'confirmation', 'Confirmation'),
  ('tableBooking.reminderSent', 'tableBooking', 'reminderSent', 'Reminder Sent'),
  ('common.notYet', 'common', 'notYet', 'Not yet'),
  ('tableBooking.sentVia', 'tableBooking', 'sentVia', 'Sent via'),
  ('common.both', 'common', 'both', 'Both'),
  ('tableBooking.reminderSentTo', 'tableBooking', 'reminderSentTo', 'Reminder sent to {{name}}'),
  ('tableBooking.sendReminderNow', 'tableBooking', 'sendReminderNow', 'Send Reminder Now'),
  ('tableBooking.statusUpdated', 'tableBooking', 'statusUpdated', 'Booking {id} status updated to {status}'),
  ('common.none', 'common', 'none', 'None'),
  ('tableBooking.summary.nextSub', 'tableBooking', 'summary.nextSub', '{{name}} · {{count}} guests'),
  ('tableBooking.summary.noUpcoming', 'tableBooking', 'summary.noUpcoming', 'No upcoming'),
  ('tableBooking.summary.totalToday', 'tableBooking', 'summary.totalToday', 'Total Bookings Today'),
  ('tableBooking.summary.totalSub', 'tableBooking', 'summary.totalSub', '{{count}} reservations'),
  ('tableBooking.summary.coversToday', 'tableBooking', 'summary.coversToday', 'Covers Today'),
  ('tableBooking.summary.coversSub', 'tableBooking', 'summary.coversSub', '{{count}} confirmed tables'),
  ('tableBooking.summary.nextReservation', 'tableBooking', 'summary.nextReservation', 'Next Reservation'),
  ('tableBooking.summary.confirmedSub', 'tableBooking', 'summary.confirmedSub', 'Confirmed for today'),
  ('tableBooking.summary.noShowsToday', 'tableBooking', 'summary.noShowsToday', 'No-Shows Today'),
  ('tableBooking.summary.noShowsSub', 'tableBooking', 'summary.noShowsSub', '{{count}} no-show{{plural}}'),
  ('tableBooking.summary.remindersSent', 'tableBooking', 'summary.remindersSent', 'Reminders Sent'),
  ('tableBooking.summary.pendingSub', 'tableBooking', 'summary.pendingSub', '{{count}} pending'),
  ('tableBooking.tabs.all', 'tableBooking', 'tabs.all', 'All'),
  ('tableBooking.status.pending', 'tableBooking', 'status.pending', 'Pending'),
  ('tableBooking.status.escalated', 'tableBooking', 'status.escalated', 'Escalated'),
  ('tableBooking.status.completed', 'tableBooking', 'status.completed', 'Completed'),
  ('bookings.failedToLoad', 'bookings', 'failedToLoad', 'Failed to load bookings'),
  ('bookings.statusUpdated', 'bookings', 'statusUpdated', 'Booking status updated'),
  ('bookings.failedToUpdate', 'bookings', 'failedToUpdate', 'Failed to update booking'),
  ('bookings.failedToDelete', 'bookings', 'failedToDelete', 'Failed to delete bookings'),
  ('bookings.csv.id', 'bookings', 'csv.id', 'ID'),
  ('bookings.csv.guest', 'bookings', 'csv.guest', 'Guest'),
  ('bookings.csv.partySize', 'bookings', 'csv.partySize', 'Party Size'),
  ('bookings.csv.date', 'bookings', 'csv.date', 'Date'),
  ('bookings.csv.time', 'bookings', 'csv.time', 'Time'),
  ('bookings.csv.table', 'bookings', 'csv.table', 'Table'),
  ('bookings.csv.status', 'bookings', 'csv.status', 'Status'),
  ('bookings.csv.channel', 'bookings', 'csv.channel', 'Channel'),
  ('bookings.exported', 'bookings', 'exported', 'Bookings exported'),
  ('tableBooking.newReservation', 'tableBooking', 'newReservation', 'New Reservation'),
  ('tableBooking.newReservationSub', 'tableBooking', 'newReservationSub', '{{count}} guests · {{date}} {{time}}'),
  ('tableBooking.viewBooking', 'tableBooking', 'viewBooking', 'View Booking'),
  ('tableBooking.searchPlaceholder', 'tableBooking', 'searchPlaceholder', 'Search by guest name...'),
  ('common.selectedCount', 'common', 'selectedCount', '{{count}} selected'),
  ('common.exportCsv', 'common', 'exportCsv', 'Export CSV'),
  ('tableBooking.noBookingsFound', 'tableBooking', 'noBookingsFound', 'No bookings found'),
  ('tableBooking.noBookingsSub', 'tableBooking', 'noBookingsSub', 'Bookings will appear here when customers make reservations'),
  ('tableBooking.cols.guest', 'tableBooking', 'cols.guest', 'Guest'),
  ('tableBooking.cols.party', 'tableBooking', 'cols.party', 'Party'),
  ('tableBooking.cols.dateTime', 'tableBooking', 'cols.dateTime', 'Date & Time'),
  ('tableBooking.cols.table', 'tableBooking', 'cols.table', 'Table'),
  ('tableBooking.cols.channel', 'tableBooking', 'cols.channel', 'Channel'),
  ('tableBooking.cols.status', 'tableBooking', 'cols.status', 'Status'),
  ('common.paginationInfo', 'common', 'paginationInfo', 'Showing {start}–{end} of {total}'),
  ('tableBooking.deleteTitle', 'tableBooking', 'deleteTitle', 'Delete Bookings'),
  ('tableBooking.deleteConfirm', 'tableBooking', 'deleteConfirm', 'Are you sure you want to delete {{count}} booking{{plural}}? This cannot be undone.'),
  ('webhooks.validation.urlRequired', 'webhooks', 'validation.urlRequired', 'Endpoint URL is required'),
  ('webhooks.validation.urlProtocol', 'webhooks', 'validation.urlProtocol', 'URL must use HTTP or HTTPS protocol'),
  ('webhooks.validation.urlInvalid', 'webhooks', 'validation.urlInvalid', 'Please enter a valid URL (e.g. https://your-app.com/webhooks)'),
  ('webhooks.validation.eventsRequired', 'webhooks', 'validation.eventsRequired', 'Please select at least one event'),
  ('webhooks.error.saveFailed', 'webhooks', 'error.saveFailed', 'Failed to save webhook'),
  ('webhooks.error.deleteFailed', 'webhooks', 'error.deleteFailed', 'Failed to delete webhook'),
  ('webhooks.error.updateFailed', 'webhooks', 'error.updateFailed', 'Failed to update webhook'),
  ('webhooks.stats.activeEndpoints', 'webhooks', 'stats.activeEndpoints', 'Active Endpoints'),
  ('webhooks.stats.totalEndpoints', 'webhooks', 'stats.totalEndpoints', 'Total Endpoints'),
  ('webhooks.stats.totalDeliveries', 'webhooks', 'stats.totalDeliveries', 'Total Deliveries'),
  ('webhooks.stats.avgSuccessRate', 'webhooks', 'stats.avgSuccessRate', 'Avg Success Rate'),
  ('webhooks.endpoints.title', 'webhooks', 'endpoints.title', 'Webhook Endpoints'),
  ('webhooks.endpoints.add', 'webhooks', 'endpoints.add', 'Add Endpoint'),
  ('webhooks.addForm.title', 'webhooks', 'addForm.title', 'New Webhook Endpoint'),
  ('webhooks.addForm.urlLabel', 'webhooks', 'addForm.urlLabel', 'Endpoint URL *'),
  ('webhooks.addForm.eventsLabel', 'webhooks', 'addForm.eventsLabel', 'Subscribe to Events *'),
  ('webhooks.addForm.submit', 'webhooks', 'addForm.submit', 'Save Endpoint'),
  ('webhooks.loading', 'webhooks', 'loading', 'Loading webhooks…'),
  ('webhooks.noEndpoints.title', 'webhooks', 'noEndpoints.title', 'No webhook endpoints configured'),
  ('webhooks.noEndpoints.subtitle', 'webhooks', 'noEndpoints.subtitle', 'Add an endpoint to start receiving event notifications'),
  ('webhooks.endpoints.toggleStatus', 'webhooks', 'endpoints.toggleStatus', 'Click to toggle status'),
  ('webhooks.endpoints.secretLabel', 'webhooks', 'endpoints.secretLabel', 'Secret:'),
  ('common.copySecret', 'common', 'copySecret', 'Copy secret'),
  ('webhooks.endpoints.created', 'webhooks', 'endpoints.created', 'Created'),
  ('webhooks.logs.title', 'webhooks', 'logs.title', 'Delivery Logs'),
  ('webhooks.logs.loading', 'webhooks', 'logs.loading', 'Loading logs…'),
  ('webhooks.logs.empty', 'webhooks', 'logs.empty', 'No delivery logs yet. Logs will appear here as events are triggered.'),
  ('webhooks.logs.table.event', 'webhooks', 'logs.table.event', 'Event'),
  ('webhooks.logs.table.endpoint', 'webhooks', 'logs.table.endpoint', 'Endpoint'),
  ('webhooks.logs.table.status', 'webhooks', 'logs.table.status', 'Status'),
  ('webhooks.logs.table.response', 'webhooks', 'logs.table.response', 'Response'),
  ('webhooks.logs.table.duration', 'webhooks', 'logs.table.duration', 'Duration'),
  ('webhooks.logs.table.timestamp', 'webhooks', 'logs.table.timestamp', 'Timestamp'),
  ('billing.visibleToCustomers', 'billing', 'visibleToCustomers', 'Visible to new customers'),
  ('billing.yr', 'billing', 'yr', 'yr'),
  ('blog.categories.aiFeatures', 'blog', 'categories.aiFeatures', 'AI Features'),
  ('blog.categories.aiTechnology', 'blog', 'categories.aiTechnology', 'AI & Technology'),
  ('blog.categories.caseStudies', 'blog', 'categories.caseStudies', 'Case Studies'),
  ('blog.categories.restaurantOps', 'blog', 'categories.restaurantOps', 'Restaurant Operations'),
  ('blog.categories.customerExp', 'blog', 'categories.customerExp', 'Customer Experience'),
  ('blog.categories.productUpdates', 'blog', 'categories.productUpdates', 'Product Updates'),
  ('blog.blocks.paragraph', 'blog', 'blocks.paragraph', 'Paragraph'),
  ('blog.blocks.heading2', 'blog', 'blocks.heading2', 'Heading 2'),
  ('blog.blocks.heading3', 'blog', 'blocks.heading3', 'Heading 3'),
  ('blog.blocks.calloutOrange', 'blog', 'blocks.calloutOrange', 'Callout Box (Orange)'),
  ('blog.blocks.calloutTeal', 'blog', 'blocks.calloutTeal', 'Callout Box (Teal)'),
  ('blog.blocks.statsGrid', 'blog', 'blocks.statsGrid', 'Stats Grid (3 cols)'),
  ('blog.blocks.stepList', 'blog', 'blocks.stepList', 'Step List'),
  ('blog.blocks.blockquote', 'blog', 'blocks.blockquote', 'Blockquote'),
  ('blog.blocks.faqList', 'blog', 'blocks.faqList', 'FAQ List'),
  ('blog.blocks.tagsList', 'blog', 'blocks.tagsList', 'Tags'),
  ('blog.placeholders.paragraph', 'blog', 'placeholders.paragraph', 'Write your paragraph here...'),
  ('blog.placeholders.heading2', 'blog', 'placeholders.heading2', 'Section heading...'),
  ('blog.placeholders.heading3', 'blog', 'placeholders.heading3', 'Sub-heading...'),
  ('blog.placeholders.callout', 'blog', 'placeholders.callout', 'Key Insight | Write your callout text here...'),
  ('blog.placeholders.statsGrid', 'blog', 'placeholders.statsGrid', '23% | Calls missed during peak hours\n4.2min | Average hold time\n8.3% | Order error rate'),
  ('blog.placeholders.stepList', 'blog', 'placeholders.stepList', '01 | Step title | Step description\n02 | Step title | Step description'),
  ('blog.placeholders.blockquote', 'blog', 'placeholders.blockquote', '"Quote text here" | Author Name | Author Title'),
  ('blog.placeholders.faqList', 'blog', 'placeholders.faqList', 'Question 1? | Answer 1\nQuestion 2? | Answer 2'),
  ('blog.placeholders.tagsList', 'blog', 'placeholders.tagsList', 'AI Ordering, Restaurant Tech, Revenue Growth'),
  ('admin.blog.updateAndRepublish', 'admin', 'blog.updateAndRepublish', 'Update and republish your post'),
  ('admin.blog.scheduled', 'admin', 'blog.scheduled', 'Scheduled'),
  ('admin.blog.saved', 'admin', 'blog.saved', 'Saved!'),
  ('admin.blog.updatePost', 'admin', 'blog.updatePost', 'Update Post'),
  ('admin.blog.savePost', 'admin', 'blog.savePost', 'Save Post'),
  ('admin.blog.preview', 'admin', 'blog.preview', 'Preview'),
  ('admin.blog.seo', 'admin', 'blog.seo', 'SEO'),
  ('admin.blog.postTitle', 'admin', 'blog.postTitle', 'Post Title'),
  ('admin.blog.seoMetaTitle', 'admin', 'blog.seoMetaTitle', 'SEO Meta Title'),
  ('admin.blog.recommended5060Chars', 'admin', 'blog.recommended5060Chars', 'Recommended: 50-60 characters'),
  ('admin.blog.seoMetaDescription', 'admin', 'blog.seoMetaDescription', 'SEO Meta Description'),
  ('admin.blog.recommended150160Chars', 'admin', 'blog.recommended150160Chars', 'Recommended: 150-160 characters'),
  ('admin.blog.postTitlePreview', 'admin', 'blog.postTitlePreview', 'Post Title'),
  ('admin.blog.publishSettings', 'admin', 'blog.publishSettings', 'Publish Settings'),
  ('admin.blog.scheduleDateTime', 'admin', 'blog.scheduleDateTime', 'Schedule Date & Time'),
  ('admin.blog.readingTime', 'admin', 'blog.readingTime', 'Reading time'),
  ('admin.blog.selectCategoryPlaceholder', 'admin', 'blog.selectCategoryPlaceholder', 'Select category...'),
  ('admin.blog.shortBioPlaceholder', 'admin', 'blog.shortBioPlaceholder', 'Short bio shown at the bottom of the post...'),
  ('admin.blog.tealCallout', 'admin', 'blog.tealCallout', 'Teal Callout'),
  ('admin.blog.tealCalloutGuide', 'admin', 'blog.tealCalloutGuide', 'Title | Item 1↵Item 2'),
  ('admin.blog.statsGrid', 'admin', 'blog.statsGrid', 'Stats Grid'),
  ('admin.blog.statsGridGuide', 'admin', 'blog.statsGridGuide', 'Value | Label↵Value | Label'),
  ('admin.blog.stepList', 'admin', 'blog.stepList', 'Step List'),
  ('admin.blog.stepListGuide', 'admin', 'blog.stepListGuide', '01 | Title | Desc↵02 | Title | Desc'),
  ('admin.blog.status.published', 'admin', 'blog.status.published', 'Published'),
  ('admin.blog.status.draft', 'admin', 'blog.status.draft', 'Draft'),
  ('admin.blog.status.scheduled', 'admin', 'blog.status.scheduled', 'Scheduled'),
  ('admin.blog.statTotalPosts', 'admin', 'blog.statTotalPosts', 'Total Posts'),
  ('admin.blog.statPublished', 'admin', 'blog.statPublished', 'Published'),
  ('admin.blog.statDrafts', 'admin', 'blog.statDrafts', 'Drafts'),
  ('admin.blog.statTotalViews', 'admin', 'blog.statTotalViews', 'Total Views'),
  ('admin.blog.selected', 'admin', 'blog.selected', 'selected'),
  ('admin.blog.showing', 'admin', 'blog.showing', 'Showing'),
  ('admin.blog.of', 'admin', 'blog.of', 'of'),
  ('admin.blog.posts', 'admin', 'blog.posts', 'posts'),
  ('common.today', 'common', 'today', 'Today'),
  ('common.oneDayAgo', 'common', 'oneDayAgo', '1 day ago'),
  ('common.daysAgo', 'common', 'daysAgo', '{{n}} days ago'),
  ('common.weeksAgo', 'common', 'weeksAgo', '{{n}} week{{s}} ago'),
  ('common.monthsAgo', 'common', 'monthsAgo', '{{n}} month{{s}} ago'),
  ('admin.dashboard', 'admin', 'dashboard', 'Admin Dashboard'),
  ('admin.platformMetrics', 'admin', 'platformMetrics', 'Platform-wide metrics and health'),
  ('admin.mrr', 'admin', 'mrr', 'Monthly Recurring Revenue'),
  ('admin.totalConversations', 'admin', 'totalConversations', 'Total AI Conversations'),
  ('admin.churnRate', 'admin', 'churnRate', 'Churn Rate'),
  ('admin.viewingPlatformData', 'admin', 'viewingPlatformData', 'You are viewing platform-wide data as SaaS owner'),
  ('admin.mrrGrowth', 'admin', 'mrrGrowth', 'MRR Growth'),
  ('common.mrr', 'common', 'mrr', 'MRR'),
  ('admin.noMrrData', 'admin', 'noMrrData', 'No MRR data yet'),
  ('admin.recentlyOnboarded', 'admin', 'recentlyOnboarded', 'Recently Onboarded'),
  ('common.restaurant', 'common', 'restaurant', 'Restaurant'),
  ('common.joined', 'common', 'joined', 'Joined'),
  ('admin.noRestaurantsYet', 'admin', 'noRestaurantsYet', 'No restaurants onboarded yet'),
  ('admin.platformAnalytics.totalConversations', 'admin', 'platformAnalytics.totalConversations', 'Total Conversations'),
  ('admin.platformAnalytics.todayConversations', 'admin', 'platformAnalytics.todayConversations', 'Today''s Conversations'),
  ('admin.platformAnalytics.totalApiCalls', 'admin', 'platformAnalytics.totalApiCalls', 'Total API Calls'),
  ('admin.platformAnalytics.avgCallDuration', 'admin', 'platformAnalytics.avgCallDuration', 'Avg Call Duration'),
  ('admin.platformAnalytics.voiceCalls14d', 'admin', 'platformAnalytics.voiceCalls14d', 'Voice Calls (14d)'),
  ('admin.platformAnalytics.escalationRate', 'admin', 'platformAnalytics.escalationRate', 'Escalation Rate'),
  ('admin.platformAnalytics.adminPanel', 'admin', 'platformAnalytics.adminPanel', 'Admin Panel'),
  ('admin.platformAnalytics.adminPanelDesc', 'admin', 'platformAnalytics.adminPanelDesc', 'Platform-wide performance metrics'),
  ('admin.platformAnalytics.convTrendTitle', 'admin', 'platformAnalytics.convTrendTitle', 'Conversation Trend (Last 14 Days)'),
  ('admin.platformAnalytics.noConvData', 'admin', 'platformAnalytics.noConvData', 'No conversation data yet'),
  ('admin.platformAnalytics.avgCallDurationTitle', 'admin', 'platformAnalytics.avgCallDurationTitle', 'Avg Call Duration (Last 14 Days)'),
  ('admin.platformAnalytics.noCallData', 'admin', 'platformAnalytics.noCallData', 'No call data yet'),
  ('admin.platformAnalytics.convStatusTitle', 'admin', 'platformAnalytics.convStatusTitle', 'Conversation Status Breakdown (14d)'),
  ('admin.restaurants.trialExpired', 'admin', 'restaurants.trialExpired', 'Trial expired'),
  ('admin.restaurants.expiresToday', 'admin', 'restaurants.expiresToday', 'Expires today'),
  ('admin.restaurants.errorLoad', 'admin', 'restaurants.errorLoad', 'Failed to load restaurant'),
  ('admin.restaurants.alertSaved', 'admin', 'restaurants.alertSaved', 'Alert settings saved'),
  ('admin.restaurants.errorSaveAlerts', 'admin', 'restaurants.errorSaveAlerts', 'Failed to save alert settings'),
  ('admin.restaurants.planUpdated', 'admin', 'restaurants.planUpdated', 'Plan updated'),
  ('admin.restaurants.trialRevoked', 'admin', 'restaurants.trialRevoked', 'Trial revoked'),
  ('admin.restaurants.errorUpdateSubscription', 'admin', 'restaurants.errorUpdateSubscription', 'Failed to update subscription'),
  ('admin.restaurants.errorEnterView', 'admin', 'restaurants.errorEnterView', 'Failed to enter restaurant view'),
  ('admin.restaurants.loading', 'admin', 'restaurants.loading', 'Loading restaurant…'),
  ('admin.restaurants.notFound', 'admin', 'restaurants.notFound', 'Restaurant not found'),
  ('admin.restaurants.backToList', 'admin', 'restaurants.backToList', 'Back to list'),
  ('admin.restaurants.enterAsRestaurant', 'admin', 'restaurants.enterAsRestaurant', 'Enter as Restaurant'),
  ('admin.restaurants.suspend', 'admin', 'restaurants.suspend', 'Suspend'),
  ('admin.restaurants.activate', 'admin', 'restaurants.activate', 'Activate'),
  ('admin.restaurants.profile', 'admin', 'restaurants.profile', 'Restaurant Profile'),
  ('admin.restaurants.labelOwner', 'admin', 'restaurants.labelOwner', 'Owner'),
  ('admin.restaurants.labelEmail', 'admin', 'restaurants.labelEmail', 'Email'),
  ('admin.restaurants.labelPhone', 'admin', 'restaurants.labelPhone', 'Phone'),
  ('admin.restaurants.labelCuisine', 'admin', 'restaurants.labelCuisine', 'Cuisine'),
  ('admin.restaurants.labelAddress', 'admin', 'restaurants.labelAddress', 'Address'),
  ('admin.restaurants.labelCapacity', 'admin', 'restaurants.labelCapacity', 'Seating Capacity'),
  ('admin.restaurants.labelJoined', 'admin', 'restaurants.labelJoined', 'Joined'),
  ('admin.restaurants.labelId', 'admin', 'restaurants.labelId', 'Restaurant ID'),
  ('admin.restaurants.branches', 'admin', 'restaurants.branches', 'Branches'),
  ('admin.restaurants.noBranches', 'admin', 'restaurants.noBranches', 'No branches found.'),
  ('admin.restaurants.statusActive', 'admin', 'restaurants.statusActive', 'active'),
  ('admin.restaurants.statusInactive', 'admin', 'restaurants.statusInactive', 'inactive'),
  ('admin.restaurants.alertSettingsOverride', 'admin', 'restaurants.alertSettingsOverride', 'Alert Settings Override'),
  ('admin.restaurants.saved', 'admin', 'restaurants.saved', 'Saved!'),
  ('admin.restaurants.save', 'admin', 'restaurants.save', 'Save'),
  ('admin.restaurants.loadingAlerts', 'admin', 'restaurants.loadingAlerts', 'Loading alert settings…'),
  ('admin.restaurants.orderAlerts', 'admin', 'restaurants.orderAlerts', 'Order Alerts'),
  ('admin.restaurants.bookingAlerts', 'admin', 'restaurants.bookingAlerts', 'Booking Alerts'),
  ('admin.restaurants.aiEscalations', 'admin', 'restaurants.aiEscalations', 'AI Escalations'),
  ('admin.restaurants.browserNotifications', 'admin', 'restaurants.browserNotifications', 'Browser Notifications'),
  ('admin.restaurants.soundEnabled', 'admin', 'restaurants.soundEnabled', 'Sound Enabled'),
  ('admin.restaurants.volume', 'admin', 'restaurants.volume', 'Volume'),
  ('admin.restaurants.autoDismiss', 'admin', 'restaurants.autoDismiss', 'Auto-dismiss after:'),
  ('admin.restaurants.errorLoadAlerts', 'admin', 'restaurants.errorLoadAlerts', 'Unable to load alert settings.'),
  ('admin.restaurants.subscription', 'admin', 'restaurants.subscription', 'Subscription'),
  ('admin.restaurants.noPlan', 'admin', 'restaurants.noPlan', 'No Plan'),
  ('admin.restaurants.free', 'admin', 'restaurants.free', 'Free'),
  ('admin.restaurants.labelStatus', 'admin', 'restaurants.labelStatus', 'Status'),
  ('admin.restaurants.labelTrialStart', 'admin', 'restaurants.labelTrialStart', 'Trial Started'),
  ('admin.restaurants.labelTrialEnd', 'admin', 'restaurants.labelTrialEnd', 'Trial Ends'),
  ('admin.restaurants.labelNextBilling', 'admin', 'restaurants.labelNextBilling', 'Next Billing'),
  ('admin.restaurants.trialStatus', 'admin', 'restaurants.trialStatus', 'Trial Status'),
  ('admin.restaurants.trialManagement', 'admin', 'restaurants.trialManagement', 'Trial Management'),
  ('admin.restaurants.plan', 'admin', 'restaurants.plan', 'Plan'),
  ('admin.restaurants.keepCurrentPlan', 'admin', 'restaurants.keepCurrentPlan', 'Keep current plan'),
  ('admin.restaurants.savePlanChange', 'admin', 'restaurants.savePlanChange', 'Save Plan Change'),
  ('admin.restaurants.trialDuration', 'admin', 'restaurants.trialDuration', 'Trial Duration (days)'),
  ('admin.restaurants.grantTrial', 'admin', 'restaurants.grantTrial', 'Grant Trial'),
  ('admin.restaurants.revokeTrial', 'admin', 'restaurants.revokeTrial', 'Revoke Trial'),
  ('admin.restaurants.usage', 'admin', 'restaurants.usage', 'Usage'),
  ('admin.restaurants.usageAiQueries', 'admin', 'restaurants.usageAiQueries', 'AI Queries / API Calls'),
  ('admin.restaurants.usageConversations', 'admin', 'restaurants.usageConversations', 'Conversations'),
  ('admin.restaurants.usageOrders', 'admin', 'restaurants.usageOrders', 'Orders'),
  ('admin.restaurants.usageBranches', 'admin', 'restaurants.usageBranches', 'Branches'),
  ('admin.restaurants.recentActivity', 'admin', 'restaurants.recentActivity', 'Recent Activity'),
  ('admin.restaurants.expired', 'admin', 'restaurants.expired', 'Expired'),
  ('admin.restaurants.daysLeft', 'admin', 'restaurants.daysLeft', '{days}d left'),
  ('admin.restaurants.restaurantNameRequired', 'admin', 'restaurants.restaurantNameRequired', 'Restaurant name is required'),
  ('admin.restaurants.ownerEmailRequired', 'admin', 'restaurants.ownerEmailRequired', 'Owner email is required'),
  ('admin.restaurants.invalidEmail', 'admin', 'restaurants.invalidEmail', 'Invalid email address'),
  ('admin.restaurants.passwordLength', 'admin', 'restaurants.passwordLength', 'Password must be at least 8 characters'),
  ('admin.restaurants.failedToCreate', 'admin', 'restaurants.failedToCreate', 'Failed to create restaurant'),
  ('admin.restaurants.createdWithPass', 'admin', 'restaurants.createdWithPass', 'Restaurant "{name}" created ({id}). Temp password: {pwd}'),
  ('admin.restaurants.created', 'admin', 'restaurants.created', 'Restaurant "{name}" created ({id})'),
  ('admin.restaurants.onboardRestaurant', 'admin', 'restaurants.onboardRestaurant', 'Onboard Restaurant'),
  ('admin.restaurants.onboardDescription', 'admin', 'restaurants.onboardDescription', 'Create a new restaurant account with a 14-day trial.'),
  ('admin.restaurants.restaurantName', 'admin', 'restaurants.restaurantName', 'Restaurant Name'),
  ('admin.restaurants.restaurantNamePlaceholder', 'admin', 'restaurants.restaurantNamePlaceholder', 'e.g. The Rustic Fork'),
  ('admin.restaurants.ownerName', 'admin', 'restaurants.ownerName', 'Owner Name'),
  ('admin.restaurants.ownerNamePlaceholder', 'admin', 'restaurants.ownerNamePlaceholder', 'e.g. Jane Smith'),
  ('admin.restaurants.ownerEmail', 'admin', 'restaurants.ownerEmail', 'Owner Email'),
  ('admin.restaurants.ownerEmailPlaceholder', 'admin', 'restaurants.ownerEmailPlaceholder', 'owner@restaurant.com'),
  ('admin.restaurants.ownerPassword', 'admin', 'restaurants.ownerPassword', 'Owner Password'),
  ('admin.restaurants.optionalAutoGenerated', 'admin', 'restaurants.optionalAutoGenerated', 'optional — auto-generated if blank'),
  ('admin.restaurants.passwordPlaceholder', 'admin', 'restaurants.passwordPlaceholder', 'Leave blank to auto-generate'),
  ('admin.restaurants.cancel', 'admin', 'restaurants.cancel', 'Cancel'),
  ('admin.restaurants.creating', 'admin', 'restaurants.creating', 'Creating…'),
  ('admin.restaurants.createRestaurant', 'admin', 'restaurants.createRestaurant', 'Create Restaurant'),
  ('admin.restaurants.pageTitle', 'admin', 'restaurants.pageTitle', 'Restaurant Management'),
  ('admin.restaurants.pageDescription', 'admin', 'restaurants.pageDescription', 'Onboard, suspend, and manage all tenants'),
  ('admin.restaurants.failedToLoad', 'admin', 'restaurants.failedToLoad', 'Failed to load restaurants'),
  ('admin.restaurants.adminPanel', 'admin', 'restaurants.adminPanel', 'Admin Panel'),
  ('admin.restaurants.loadingDots', 'admin', 'restaurants.loadingDots', 'Loading…'),
  ('admin.restaurants.managingCount', 'admin', 'restaurants.managingCount', 'Managing {count} restaurant account{plural}'),
  ('admin.restaurants.searchPlaceholder', 'admin', 'restaurants.searchPlaceholder', 'Search by name, owner, email, ID…'),
  ('admin.restaurants.onboard', 'admin', 'restaurants.onboard', 'Onboard'),
  ('admin.restaurants.loadingRestaurants', 'admin', 'restaurants.loadingRestaurants', 'Loading restaurants…'),
  ('admin.restaurants.noRestaurantsFound', 'admin', 'restaurants.noRestaurantsFound', 'No restaurants found.'),
  ('admin.restaurants.view', 'admin', 'restaurants.view', 'View'),
  ('admin.restaurants.reactivate', 'admin', 'restaurants.reactivate', 'Reactivate'),
  ('common.info', 'common', 'info', 'Info'),
  ('common.warning', 'common', 'warning', 'Warning'),
  ('common.critical', 'common', 'critical', 'Critical'),
  ('support.eventDetails', 'support', 'eventDetails', 'Event Details'),
  ('support.eventType', 'support', 'eventType', 'Event Type'),
  ('support.timestamp', 'support', 'timestamp', 'Timestamp'),
  ('support.restaurant', 'support', 'restaurant', 'Restaurant'),
  ('support.branch', 'support', 'branch', 'Branch'),
  ('support.ipAddress', 'support', 'ipAddress', 'IP Address'),
  ('support.logId', 'support', 'logId', 'Log ID'),
  ('support.stateChanges', 'support', 'stateChanges', 'State Changes'),
  ('support.before', 'support', 'before', 'Before'),
  ('support.nullNewRecord', 'support', 'nullNewRecord', 'null (new record)'),
  ('support.after', 'support', 'after', 'After'),
  ('support.nullRecordDeleted', 'support', 'nullRecordDeleted', 'null (record deleted)'),
  ('support.clientInformation', 'support', 'clientInformation', 'Client Information'),
  ('support.actor', 'support', 'actor', 'Actor'),
  ('support.email', 'support', 'email', 'Email'),
  ('support.userId', 'support', 'userId', 'User ID'),
  ('support.target', 'support', 'target', 'Target'),
  ('support.type', 'support', 'type', 'Type'),
  ('support.name', 'support', 'name', 'Name'),
  ('support.id', 'support', 'id', 'ID'),
  ('support.actions', 'support', 'actions', 'Actions'),
  ('support.exportAsJson', 'support', 'exportAsJson', 'Export as JSON'),
  ('support.viewRelatedEvents', 'support', 'viewRelatedEvents', 'View Related Events'),
  ('admin.support.pageTitle', 'admin', 'support.pageTitle', 'Support Tools'),
  ('admin.support.pageDescription', 'admin', 'support.pageDescription', 'Impersonate restaurants and view audit logs'),
  ('admin.support.impersonationFailed', 'admin', 'support.impersonationFailed', 'Impersonation failed'),
  ('admin.support.nowViewingAs', 'admin', 'support.nowViewingAs', 'Now viewing as {name}'),
  ('admin.support.failedToImpersonate', 'admin', 'support.failedToImpersonate', 'Failed to impersonate restaurant'),
  ('admin.support.failedToLoadData', 'admin', 'support.failedToLoadData', 'Failed to load support data'),
  ('admin.support.failedToLoadTools', 'admin', 'support.failedToLoadTools', 'Failed to load support tools'),
  ('admin.support.retrying', 'admin', 'support.retrying', 'Retrying…'),
  ('admin.support.retry', 'admin', 'support.retry', 'Retry'),
  ('admin.support.adminPanel', 'admin', 'support.adminPanel', 'Admin Panel'),
  ('admin.support.actionsLogged', 'admin', 'support.actionsLogged', 'All actions in this panel are logged'),
  ('admin.support.tab.impersonate', 'admin', 'support.tab.impersonate', 'Impersonate Restaurant'),
  ('admin.support.tab.audit', 'admin', 'support.tab.audit', 'Audit Logs'),
  ('admin.support.impersonatingHeader', 'admin', 'support.impersonatingHeader', 'Impersonating: {name} — You are viewing their dashboard'),
  ('admin.support.exitSession', 'admin', 'support.exitSession', 'Exit Session'),
  ('admin.support.impersonate', 'admin', 'support.impersonate', 'Impersonate'),
  ('admin.support.noRestaurantsFound', 'admin', 'support.noRestaurantsFound', 'No restaurants found'),
  ('admin.support.searchAuditPlaceholder', 'admin', 'support.searchAuditPlaceholder', 'Search by actor, action, resource…'),
  ('admin.support.noAuditLogs', 'admin', 'support.noAuditLogs', 'No audit logs recorded yet'),
  ('admin.branding.uploadFailed', 'admin', 'branding.uploadFailed', 'Upload failed'),
  ('admin.branding.uploaded', 'admin', 'branding.uploaded', '{label} uploaded'),
  ('admin.branding.uploading', 'admin', 'branding.uploading', 'Uploading…'),
  ('admin.branding.upload', 'admin', 'branding.upload', 'Upload'),
  ('admin.branding.preview', 'admin', 'branding.preview', 'Preview'),
  ('admin.branding.remove', 'admin', 'branding.remove', 'Remove'),
  ('admin.branding.pageTitle', 'admin', 'branding.pageTitle', 'Branding'),
  ('admin.branding.pageDescription', 'admin', 'branding.pageDescription', 'Customize platform identity, colors, and typography'),
  ('admin.branding.failedToLoad', 'admin', 'branding.failedToLoad', 'Failed to load branding settings'),
  ('admin.branding.saved', 'admin', 'branding.saved', 'Branding settings saved'),
  ('admin.branding.failedToSave', 'admin', 'branding.failedToSave', 'Failed to save branding'),
  ('admin.branding.identity', 'admin', 'branding.identity', 'Identity'),
  ('admin.branding.identityDescription', 'admin', 'branding.identityDescription', 'Logo and favicon shown across the platform and public pages'),
  ('admin.branding.platformLogo', 'admin', 'branding.platformLogo', 'Platform Logo'),
  ('admin.branding.platformLogoHint', 'admin', 'branding.platformLogoHint', 'Shown in the navbar, login page, and sidebar. SVG or PNG recommended.'),
  ('admin.branding.favicon', 'admin', 'branding.favicon', 'Favicon'),
  ('admin.branding.faviconHint', 'admin', 'branding.faviconHint', 'Browser tab icon. PNG 32×32 or WEBP recommended. Provide a URL for ICO/SVG.'),
  ('admin.branding.siteInfo', 'admin', 'branding.siteInfo', 'Site Info'),
  ('admin.branding.siteInfoDescription', 'admin', 'branding.siteInfoDescription', 'Title and tagline shown in browser tabs and public pages'),
  ('admin.branding.siteTitle', 'admin', 'branding.siteTitle', 'Site Title'),
  ('admin.branding.tagline', 'admin', 'branding.tagline', 'Tagline'),
  ('admin.branding.browserTabPreview', 'admin', 'branding.browserTabPreview', 'Browser tab preview'),
  ('admin.branding.appearance', 'admin', 'branding.appearance', 'Appearance'),
  ('admin.branding.appearanceDescription', 'admin', 'branding.appearanceDescription', 'Primary brand color used across landing pages, buttons, and accents'),
  ('admin.branding.openColorPicker', 'admin', 'branding.openColorPicker', 'Open color picker'),
  ('admin.branding.typography', 'admin', 'branding.typography', 'Typography'),
  ('admin.branding.typographyDescription', 'admin', 'branding.typographyDescription', 'Primary typeface applied to the landing pages and public-facing UI'),
  ('admin.branding.typographyPreview', 'admin', 'branding.typographyPreview', 'Preview: The quick brown fox jumps over the lazy dog.'),
  ('admin.branding.saveNotice', 'admin', 'branding.saveNotice', 'Changes apply to public-facing pages after save.'),
  ('admin.branding.saving', 'admin', 'branding.saving', 'Saving…'),
  ('admin.branding.saveBranding', 'admin', 'branding.saveBranding', 'Save Branding'),
  ('common.loadingDots', 'common', 'loadingDots', 'Loading…'),
  ('admin.languages.keysTotal', 'admin', 'languages.keysTotal', 'keys total'),
  ('admin.languages.searchKeys', 'admin', 'languages.searchKeys', 'Search keys…'),
  ('admin.languages.allCategories', 'admin', 'languages.allCategories', 'All Categories'),
  ('admin.languages.unsavedChanges', 'admin', 'languages.unsavedChanges', 'unsaved change(s)'),
  ('common.saveNow', 'common', 'saveNow', 'Save Now'),
  ('admin.languages.saveTranslations', 'admin', 'languages.saveTranslations', 'Save Translations'),
  ('admin.languages.form.code', 'admin', 'languages.form.code', 'Language Code'),
  ('admin.languages.form.codeHint', 'admin', 'languages.form.codeHint', '2-5 lowercase letters, e.g. en, fr, zh'),
  ('admin.languages.form.name', 'admin', 'languages.form.name', 'Language Name'),
  ('admin.languages.form.nativeName', 'admin', 'languages.form.nativeName', 'Native Name'),
  ('admin.languages.form.flag', 'admin', 'languages.form.flag', 'Flag Emoji'),
  ('admin.languages.form.rtl', 'admin', 'languages.form.rtl', 'Right-to-Left (RTL)'),
  ('admin.languages.form.copyFrom', 'admin', 'languages.form.copyFrom', 'Copy translations from'),
  ('telephone.failedToLoad', 'telephone', 'failedToLoad', 'Failed to load: {{error}}'),
  ('telephone.sipFormRequired', 'telephone', 'sipFormRequired', 'Display name, SIP server, and username are required'),
  ('telephone.sipLineCreated', 'telephone', 'sipLineCreated', 'SIP line created'),
  ('telephone.createFailed', 'telephone', 'createFailed', 'Create failed'),
  ('telephone.sipLineUpdated', 'telephone', 'sipLineUpdated', 'SIP line updated'),
  ('telephone.updateFailed', 'telephone', 'updateFailed', 'Update failed'),
  ('telephone.sipLineDeleted', 'telephone', 'sipLineDeleted', 'SIP line deleted'),
  ('telephone.deleteFailed', 'telephone', 'deleteFailed', 'Delete failed'),
  ('telephone.soon', 'telephone', 'soon', 'Coming Soon'),
  ('telephone.sipLinesComingSoon', 'telephone', 'sipLinesComingSoon', 'SIP Lines — Coming Soon'),
  ('telephone.sipComingSoonDesc', 'telephone', 'sipComingSoonDesc', 'Direct SIP trunk integration is under active development. You will be able to connect your existing PBX or VoIP infrastructure, register SIP trunks, assign AI agents per DID, and monitor registration status in real time.'),
  ('telephone.sipContactSupport', 'telephone', 'sipContactSupport', 'Contact your account manager to be notified when SIP Lines become available.'),
  ('telephone.sipTrunkReg', 'telephone', 'sipTrunkReg', 'SIP Trunk Registration'),
  ('telephone.sipTrunkRegDesc', 'telephone', 'sipTrunkRegDesc', 'Connect any SIP-compatible PBX or carrier'),
  ('telephone.perDidRouting', 'telephone', 'perDidRouting', 'Per-DID Agent Routing'),
  ('telephone.perDidRoutingDesc', 'telephone', 'perDidRoutingDesc', 'Route each number to a different AI agent'),
  ('telephone.liveMonitoring', 'telephone', 'liveMonitoring', 'Live Status Monitoring'),
  ('telephone.liveMonitoringDesc', 'telephone', 'liveMonitoringDesc', 'See registration state and call activity'),
  ('telephone.sipDesc', 'telephone', 'sipDesc', 'Connect existing PBX or VoIP infrastructure via SIP.'),
  ('telephone.addSipLine', 'telephone', 'addSipLine', 'Add SIP Line'),
  ('telephone.editSipLine', 'telephone', 'editSipLine', 'Edit SIP Line'),
  ('telephone.newSipLine', 'telephone', 'newSipLine', 'New SIP Line'),
  ('telephone.sipDisplayName', 'telephone', 'sipDisplayName', 'Display Name *'),
  ('telephone.sipDisplayNamePlaceholder', 'telephone', 'sipDisplayNamePlaceholder', 'e.g. Main Line'),
  ('telephone.sipServer', 'telephone', 'sipServer', 'SIP Server / Domain *'),
  ('telephone.sipUsername', 'telephone', 'sipUsername', 'SIP Username *'),
  ('telephone.sipPassword', 'telephone', 'sipPassword', 'SIP Password'),
  ('telephone.sipPasswordKeep', 'telephone', 'sipPasswordKeep', 'Leave blank to keep'),
  ('telephone.sipPasswordPlaceholder', 'telephone', 'sipPasswordPlaceholder', 'Password'),
  ('telephone.sipOutboundProxy', 'telephone', 'sipOutboundProxy', 'Outbound Proxy (Optional)'),
  ('telephone.assignToAgent', 'telephone', 'assignToAgent', 'Assign to Agent'),
  ('telephone.noAgentAssigned', 'telephone', 'noAgentAssigned', 'No agent assigned'),
  ('telephone.saving', 'telephone', 'saving', 'Saving...'),
  ('telephone.update', 'telephone', 'update', 'Update'),
  ('telephone.create', 'telephone', 'create', 'Create'),
  ('telephone.cancel', 'telephone', 'cancel', 'Cancel'),
  ('telephone.noSipLines', 'telephone', 'noSipLines', 'No SIP lines configured'),
  ('telephone.noSipLinesDesc', 'telephone', 'noSipLinesDesc', 'Add your first SIP line to connect your PBX system.'),
  ('telephone.sipLine', 'telephone', 'sipLine', 'SIP Line'),
  ('telephone.edit', 'telephone', 'edit', 'Edit'),
  ('telephone.delete', 'telephone', 'delete', 'Delete'),
  ('telephone.enterTransferNumber', 'telephone', 'enterTransferNumber', 'Enter a transfer number'),
  ('telephone.callTransferred', 'telephone', 'callTransferred', 'Call transferred'),
  ('telephone.transferFailed', 'telephone', 'transferFailed', 'Transfer failed'),
  ('telephone.conferenceCallingStaff', 'telephone', 'conferenceCallingStaff', 'Conference created. Calling staff at {{number}}.'),
  ('telephone.conferenceStaffFailed', 'telephone', 'conferenceStaffFailed', 'Conference created but failed to call staff. Try entering a number manually.'),
  ('telephone.conferenceCreated', 'telephone', 'conferenceCreated', 'Conference created: {{name}}. Enter a staff number or set a fallback number on the phone line.'),
  ('telephone.conferenceFailed', 'telephone', 'conferenceFailed', 'Conference failed'),
  ('telephone.callHistory', 'telephone', 'callHistory', 'Call History'),
  ('telephone.filterAll', 'telephone', 'filterAll', 'All'),
  ('telephone.filterActive', 'telephone', 'filterActive', 'Active'),
  ('telephone.filterCompleted', 'telephone', 'filterCompleted', 'Completed'),
  ('telephone.noCallsFound', 'telephone', 'noCallsFound', 'No calls found'),
  ('telephone.statusActive', 'telephone', 'statusActive', 'active'),
  ('telephone.statusRinging', 'telephone', 'statusRinging', 'ringing'),
  ('telephone.statusCompleted', 'telephone', 'statusCompleted', 'completed'),
  ('telephone.escalatedToHuman', 'telephone', 'escalatedToHuman', 'Escalated to human'),
  ('telephone.directionInbound', 'telephone', 'directionInbound', 'inbound'),
  ('telephone.directionOutbound', 'telephone', 'directionOutbound', 'outbound'),
  ('telephone.transferCall', 'telephone', 'transferCall', 'Transfer call'),
  ('telephone.transfer', 'telephone', 'transfer', 'Transfer'),
  ('telephone.createConference', 'telephone', 'createConference', 'Create conference'),
  ('telephone.conference', 'telephone', 'conference', 'Conference'),
  ('telephone.staffNumberPlaceholder', 'telephone', 'staffNumberPlaceholder', 'Staff phone number (optional, uses fallback)'),
  ('telephone.startConference', 'telephone', 'startConference', 'Start Conference'),
  ('telephone.conferenceWithName', 'telephone', 'conferenceWithName', 'Conference: {{name}}'),
  ('telephone.callingStaffAt', 'telephone', 'callingStaffAt', 'Calling staff at {{number}}...'),
  ('telephone.failedToCallStaff', 'telephone', 'failedToCallStaff', 'Failed to call staff. Use the Conference button to try again with a different number.'),
  ('telephone.conferenceIsLive', 'telephone', 'conferenceIsLive', 'Conference is live. Use the Conference button above to dial a staff member in, or set a fallback number on the phone line.'),
  ('telephone.dismiss', 'telephone', 'dismiss', 'Dismiss'),
  ('telephone.twilioCredentialsRequired', 'telephone', 'twilioCredentialsRequired', 'Both Account SID and Auth Token are required'),
  ('telephone.twilioConnectedSuccess', 'telephone', 'twilioConnectedSuccess', 'Twilio connected successfully'),
  ('telephone.failedToConnect', 'telephone', 'failedToConnect', 'Failed to connect'),
  ('telephone.connectionFailed', 'telephone', 'connectionFailed', 'Connection failed'),
  ('telephone.twilioDisconnected', 'telephone', 'twilioDisconnected', 'Twilio disconnected'),
  ('telephone.failed', 'telephone', 'failed', 'Failed'),
  ('telephone.copiedToClipboard', 'telephone', 'copiedToClipboard', 'Copied to clipboard'),
  ('telephone.outboundCallMissingInfo', 'telephone', 'outboundCallMissingInfo', 'Enter a number and select a from number'),
  ('telephone.callInitiated', 'telephone', 'callInitiated', 'Call initiated (SID: {{sid}}...)'),
  ('telephone.failedToMakeCall', 'telephone', 'failedToMakeCall', 'Failed to make call'),
  ('telephone.outboundCalls', 'telephone', 'outboundCalls', 'Outbound Calls'),
  ('telephone.makeCall', 'telephone', 'makeCall', 'Make Call'),
  ('telephone.newOutboundCall', 'telephone', 'newOutboundCall', 'New Outbound Call'),
  ('telephone.toNumber', 'telephone', 'toNumber', 'To Number'),
  ('telephone.fromNumber', 'telephone', 'fromNumber', 'From Number'),
  ('telephone.selectNumber', 'telephone', 'selectNumber', 'Select a number'),
  ('telephone.calling', 'telephone', 'calling', 'Calling...'),
  ('telephone.callNow', 'telephone', 'callNow', 'Call Now'),
  ('telephone.twilioConnection', 'telephone', 'twilioConnection', 'Twilio Connection'),
  ('telephone.connected', 'telephone', 'connected', 'Connected'),
  ('telephone.notConnected', 'telephone', 'notConnected', 'Not connected'),
  ('telephone.disconnect', 'telephone', 'disconnect', 'Disconnect'),
  ('telephone.connectTwilio', 'telephone', 'connectTwilio', 'Connect Twilio'),
  ('telephone.accountSid', 'telephone', 'accountSid', 'Account SID'),
  ('telephone.authToken', 'telephone', 'authToken', 'Auth Token'),
  ('telephone.authTokenPlaceholder', 'telephone', 'authTokenPlaceholder', 'Your Twilio Auth Token'),
  ('telephone.credentialsDesc', 'telephone', 'credentialsDesc', 'Credentials are verified with Twilio and stored encrypted. The connection can be disconnected at any time which clears stored credentials.'),
  ('telephone.verifying', 'telephone', 'verifying', 'Verifying...'),
  ('telephone.connect', 'telephone', 'connect', 'Connect'),
  ('telephone.webhookUrls', 'telephone', 'webhookUrls', 'Webhook URLs'),
  ('telephone.webhookDesc', 'telephone', 'webhookDesc', 'These webhooks are automatically configured when you assign an agent to a number. For manual setup, use these URLs in your Twilio Console.'),
  ('telephone.voiceWebhook', 'telephone', 'voiceWebhook', 'Voice Webhook (POST)'),
  ('telephone.statusCallback', 'telephone', 'statusCallback', 'Call Status Callback (POST)'),
  ('telephone.copyUrl', 'telephone', 'copyUrl', 'Copy URL'),
  ('telephone.agentAssignmentUpdated', 'telephone', 'agentAssignmentUpdated', 'Agent assignment updated'),
  ('telephone.failedToAssignAgent', 'telephone', 'failedToAssignAgent', 'Failed to assign agent'),
  ('telephone.numberDeactivated', 'telephone', 'numberDeactivated', 'Number deactivated'),
  ('telephone.numberActivated', 'telephone', 'numberActivated', 'Number activated'),
  ('telephone.failedToToggle', 'telephone', 'failedToToggle', 'Failed to toggle'),
  ('telephone.settingUpdated', 'telephone', 'settingUpdated', 'Setting updated'),
  ('telephone.failedToUpdate', 'telephone', 'failedToUpdate', 'Failed to update'),
  ('telephone.phoneNumbers', 'telephone', 'phoneNumbers', 'Phone Numbers'),
  ('telephone.noPhoneNumbers', 'telephone', 'noPhoneNumbers', 'No phone numbers'),
  ('telephone.twilioSyncDesc', 'telephone', 'twilioSyncDesc', 'Your Twilio numbers will be synced automatically. Purchase numbers in the Twilio Console.'),
  ('telephone.connectTwilioFirstDesc', 'telephone', 'connectTwilioFirstDesc', 'Connect Twilio first to sync and manage your phone numbers.'),
  ('telephone.branch', 'telephone', 'branch', 'Branch'),
  ('telephone.deactivate', 'telephone', 'deactivate', 'Deactivate'),
  ('telephone.activate', 'telephone', 'activate', 'Activate'),
  ('telephone.callSettings', 'telephone', 'callSettings', 'Call settings'),
  ('telephone.callRecording', 'telephone', 'callRecording', 'Call Recording'),
  ('telephone.callTranscription', 'telephone', 'callTranscription', 'Call Transcription'),
  ('telephone.branchAssignment', 'telephone', 'branchAssignment', 'Branch Assignment'),
  ('telephone.allBranches', 'telephone', 'allBranches', 'All branches (restaurant-wide)'),
  ('telephone.branchAssignmentDesc', 'telephone', 'branchAssignmentDesc', 'Orders and bookings from calls on this number will be attributed to the selected branch.'),
  ('telephone.fallbackNumber', 'telephone', 'fallbackNumber', 'Fallback / Transfer Number'),
  ('telephone.fallbackPlaceholder', 'telephone', 'fallbackPlaceholder', '+1234567890 — calls transfer here on escalation'),
  ('telephone.twilio', 'telephone', 'twilio', 'Twilio'),
  ('telephone.sipLines', 'telephone', 'sipLines', 'SIP Lines'),
  ('telephone.title', 'telephone', 'title', 'Telephone'),
  ('telephone.subtitle', 'telephone', 'subtitle', 'Manage voice channels, connect Twilio numbers or SIP trunks to your AI agents.'),
  ('widgetSettings.title', 'widgetSettings', 'title', 'Chat Widget'),
  ('widgetSettings.subtitle', 'widgetSettings', 'subtitle', 'Embed an AI chat assistant on your restaurant website'),
  ('widgetSettings.saved', 'widgetSettings', 'saved', 'Widget settings saved'),
  ('widgetSettings.failedToSave', 'widgetSettings', 'failedToSave', 'Failed to save'),
  ('widgetSettings.imageTooLarge', 'widgetSettings', 'imageTooLarge', 'Image must be 2 MB or smaller'),
  ('widgetSettings.iconUploaded', 'widgetSettings', 'iconUploaded', 'Icon uploaded — save to apply'),
  ('widgetSettings.embedCopied', 'widgetSettings', 'embedCopied', 'Embed code copied!'),
  ('widgetSettings.tabs.appearance', 'widgetSettings', 'tabs.appearance', 'Appearance'),
  ('widgetSettings.tabs.behavior', 'widgetSettings', 'tabs.behavior', 'AI Agent'),
  ('widgetSettings.tabs.installation', 'widgetSettings', 'tabs.installation', 'Embed'),
  ('widgetSettings.status.enabled', 'widgetSettings', 'status.enabled', 'Widget is enabled'),
  ('widgetSettings.status.disabled', 'widgetSettings', 'status.disabled', 'Widget is disabled'),
  ('widgetSettings.status.enabledSubtitle', 'widgetSettings', 'status.enabledSubtitle', 'Visitors on your website will see the chat bubble'),
  ('widgetSettings.status.disabledSubtitle', 'widgetSettings', 'status.disabledSubtitle', 'The widget will not appear on your website'),
  ('widgetSettings.appearance.brandingTitle', 'widgetSettings', 'appearance.brandingTitle', 'Branding'),
  ('widgetSettings.appearance.botNameLabel', 'widgetSettings', 'appearance.botNameLabel', 'Bot / Widget Name'),
  ('widgetSettings.appearance.botNamePlaceholder', 'widgetSettings', 'appearance.botNamePlaceholder', 'AI Assistant'),
  ('widgetSettings.appearance.botNameSubtitle', 'widgetSettings', 'appearance.botNameSubtitle', 'Displayed in the chat header'),
  ('widgetSettings.appearance.botIconLabel', 'widgetSettings', 'appearance.botIconLabel', 'Bot Icon'),
  ('widgetSettings.appearance.botIconAlt', 'widgetSettings', 'appearance.botIconAlt', 'Bot icon'),
  ('widgetSettings.appearance.uploadIcon', 'widgetSettings', 'appearance.uploadIcon', 'Upload Icon'),
  ('widgetSettings.appearance.iconSubtitle', 'widgetSettings', 'appearance.iconSubtitle', 'PNG, JPEG, GIF or WEBP · Max 2 MB · Save to apply'),
  ('widgetSettings.appearance.accentColorLabel', 'widgetSettings', 'appearance.accentColorLabel', 'Accent Color'),
  ('widgetSettings.appearance.positionLabel', 'widgetSettings', 'appearance.positionLabel', 'Widget Position'),
  ('widgetSettings.appearance.bottomRight', 'widgetSettings', 'appearance.bottomRight', '↘ Bottom Right'),
  ('widgetSettings.appearance.bottomLeft', 'widgetSettings', 'appearance.bottomLeft', '↙ Bottom Left'),
  ('widgetSettings.appearance.messagingTitle', 'widgetSettings', 'appearance.messagingTitle', 'Messaging'),
  ('widgetSettings.appearance.welcomeMessageLabel', 'widgetSettings', 'appearance.welcomeMessageLabel', 'Welcome Message'),
  ('widgetSettings.appearance.welcomeMessagePlaceholder', 'widgetSettings', 'appearance.welcomeMessagePlaceholder', 'Hi! How can we help you today?'),
  ('widgetSettings.appearance.placeholderLabel', 'widgetSettings', 'appearance.placeholderLabel', 'Input Placeholder'),
  ('widgetSettings.appearance.placeholderPlaceholder', 'widgetSettings', 'appearance.placeholderPlaceholder', 'Type your message...'),
  ('widgetSettings.appearance.autoOpenLabel', 'widgetSettings', 'appearance.autoOpenLabel', 'Auto-open Delay'),
  ('widgetSettings.appearance.autoOpenSubtitle', 'widgetSettings', 'appearance.autoOpenSubtitle', '0 disables auto-open'),
  ('common.off', 'common', 'off', 'Off'),
  ('widgetSettings.agent.selectTitle', 'widgetSettings', 'agent.selectTitle', 'Select AI Agent'),
  ('widgetSettings.agent.selectSubtitle', 'widgetSettings', 'agent.selectSubtitle', 'Choose which AI agent powers this chat widget. Only active agents with the "chat" channel are shown.'),
  ('widgetSettings.agent.noAgentsTitle', 'widgetSettings', 'agent.noAgentsTitle', 'No chat agents configured'),
  ('widgetSettings.agent.noAgentsSubtitle', 'widgetSettings', 'agent.noAgentsSubtitle', 'Go to AI Agent Config and create an agent with the "chat" channel enabled, then return here to select it.'),
  ('widgetSettings.agent.autoSelect', 'widgetSettings', 'agent.autoSelect', 'Auto-select (Recommended)'),
  ('widgetSettings.agent.autoSelectSubtitle', 'widgetSettings', 'agent.autoSelectSubtitle', 'Automatically uses your default chat agent. Best for most restaurants.'),
  ('widgetSettings.agent.pinnedTitle', 'widgetSettings', 'agent.pinnedTitle', 'Pinned Agent Active'),
  ('widgetSettings.agent.pinnedSubtitle', 'widgetSettings', 'agent.pinnedSubtitle', 'All widget conversations will use {name}. Save to apply.')

  ON CONFLICT (key) DO NOTHING;

  
  -- ─── FINAL REMAINING TRANSLATION KEYS ──────────────────────
  INSERT INTO public.translation_keys (key, category, description, default_value) VALUES
    ('marketplace.google-analytics.description', 'marketplace', 'google-analytics.description', 'Track customer journeys, conversion funnels, and AI agent performance in Google Analytics 4.'),
  ('marketplace.google-analytics.name', 'marketplace', 'google-analytics.name', 'Google Analytics')

  ON CONFLICT (key) DO NOTHING;

  -- ─── BRANCH TIMEZONE TRANSLATION KEYS ──────────────────────
  INSERT INTO public.translation_keys (key, category, description, default_value) VALUES
    ('branch.timezone.label',     'branch', 'Timezone selector label', 'Timezone'),
    ('branch.timezone.hint',      'branch', 'Timezone selector hint',  'All operating hours are interpreted in this timezone.'),
    ('branch.timezone.search',    'branch', 'Timezone search placeholder', 'Search timezone…'),
    ('branch.timezone.noMatches', 'branch', 'Timezone search no-results label', 'No matches'),
    ('restaurantSettings.hours.timezoneNote', 'restaurantSettings', 'Hours tab timezone note', 'Hours are in {{tz}}. Change timezone in branch settings.')

  ON CONFLICT (key) DO NOTHING;

  
  -- ─── LANDING + AUTH TRANSLATION KEYS ──────────────────────
  INSERT INTO public.translation_keys (key, category, description, default_value) VALUES
    ('auth.accountDetails', 'auth', 'accountDetails', 'Account Details'),
  ('auth.alreadyHaveAccount', 'auth', 'alreadyHaveAccount', 'Already have an account?'),
  ('auth.byCreating', 'auth', 'byCreating', 'By creating an account you agree to our'),
  ('auth.clickToAutoFill', 'auth', 'clickToAutoFill', 'click to auto-fill'),
  ('auth.createAccount', 'auth', 'createAccount', 'Create your account'),
  ('auth.creatingAccount', 'auth', 'creatingAccount', 'Creating account...'),
  ('auth.demoAdminPanel', 'auth', 'demoAdminPanel', 'Admin Panel'),
  ('auth.demoCredentials', 'auth', 'demoCredentials', 'Demo Credentials'),
  ('auth.demoLoginFailed', 'auth', 'demoLoginFailed', 'Demo login failed. Please try again.'),
  ('auth.demoRestaurantOwner', 'auth', 'demoRestaurantOwner', 'Restaurant Owner'),
  ('auth.emailAddress', 'auth', 'emailAddress', 'Email Address'),
  ('auth.email', 'auth', 'email', 'Email'),
  ('auth.invalidCredentials', 'auth', 'invalidCredentials', 'Invalid email or password. Please try again.'),
  ('auth.loginHeroSubtitle', 'auth', 'loginHeroSubtitle', 'Handle orders, reservations, and customer conversations — all through one intelligent platform.'),
  ('auth.loginHeroTitle1', 'auth', 'loginHeroTitle1', 'AI-powered restaurant'),
  ('auth.loginHeroTitle2', 'auth', 'loginHeroTitle2', 'management, simplified.'),
  ('auth.minTwoChars', 'auth', 'minTwoChars', 'Must be at least 2 characters'),
  ('auth.ownerNamePlaceholder', 'auth', 'ownerNamePlaceholder', 'Marco Khalid'),
  ('auth.ownerNameRequired', 'auth', 'ownerNameRequired', 'Owner name is required'),
  ('auth.passwordMin8', 'auth', 'passwordMin8', 'Password must be at least 8 characters'),
  ('auth.passwordMinLength', 'auth', 'passwordMinLength', 'Password must be at least 6 characters'),
  ('auth.passwordMinPlaceholder', 'auth', 'passwordMinPlaceholder', 'Min 8 characters'),
  ('auth.password', 'auth', 'password', 'Password'),
  ('auth.privacyPolicy', 'auth', 'privacyPolicy', 'Privacy Policy'),
  ('auth.pwCheck8chars', 'auth', 'pwCheck8chars', '8+ characters'),
  ('auth.pwCheckNumber', 'auth', 'pwCheckNumber', 'Number'),
  ('auth.pwCheckUppercase', 'auth', 'pwCheckUppercase', 'Uppercase letter'),
  ('auth.pwFair', 'auth', 'pwFair', 'Fair'),
  ('auth.pwStrong', 'auth', 'pwStrong', 'Strong'),
  ('auth.pwWeak', 'auth', 'pwWeak', 'Weak'),
  ('auth.registrationFailed', 'auth', 'registrationFailed', 'Registration failed. Please try again.'),
  ('auth.restaurantNamePlaceholder', 'auth', 'restaurantNamePlaceholder', 'The Rustic Fork'),
  ('auth.restaurantNameRequired', 'auth', 'restaurantNameRequired', 'Restaurant name is required'),
  ('auth.signInToDashboard', 'auth', 'signInToDashboard', 'Sign in to your restaurant dashboard'),
  ('auth.startFreeTrial', 'auth', 'startFreeTrial', 'Start Free Trial'),
  ('auth.statOrdersProcessed', 'auth', 'statOrdersProcessed', 'Orders Processed'),
  ('auth.statResolutionRate', 'auth', 'statResolutionRate', 'AI Resolution Rate'),
  ('auth.statResponseTime', 'auth', 'statResponseTime', 'Avg Response Time'),
  ('auth.termsOfService', 'auth', 'termsOfService', 'Terms of Service'),
  ('auth.trialNoCard', 'auth', 'trialNoCard', 'Start your 14-day free trial — no credit card required'),
  ('auth.welcomeBack', 'auth', 'welcomeBack', 'Welcome back'),
  ('billing.feature1Branch', 'billing', 'feature1Branch', '1 branch'),
  ('billing.feature2000Queries', 'billing', 'feature2000Queries', '2,000 AI queries/mo'),
  ('billing.feature3Branches', 'billing', 'feature3Branches', '3 branches'),
  ('billing.feature500Queries', 'billing', 'feature500Queries', '500 AI queries/mo'),
  ('billing.featureAdvancedAnalytics', 'billing', 'featureAdvancedAnalytics', 'Advanced analytics'),
  ('billing.featureAllChannels', 'billing', 'featureAllChannels', 'All channels'),
  ('billing.featureBasicAnalytics', 'billing', 'featureBasicAnalytics', 'Basic analytics'),
  ('billing.featureChatAgent', 'billing', 'featureChatAgent', 'Chat agent'),
  ('billing.featureCustomIntegrations', 'billing', 'featureCustomIntegrations', 'Custom integrations'),
  ('billing.featureDedicatedSupport', 'billing', 'featureDedicatedSupport', 'Dedicated support'),
  ('billing.featurePrioritySupport', 'billing', 'featurePrioritySupport', 'Priority support'),
  ('billing.featureUnlimitedBranches', 'billing', 'featureUnlimitedBranches', 'Unlimited branches'),
  ('billing.featureUnlimitedQueries', 'billing', 'featureUnlimitedQueries', 'Unlimited AI queries'),
  ('billing.featureVoiceChat', 'billing', 'featureVoiceChat', 'Voice + Chat agents'),
  ('billing.growth', 'billing', 'growth', 'Growth'),
  ('billing.popular', 'billing', 'popular', 'Popular'),
  ('common.and', 'common', 'and', 'and'),
  ('common.emailPlaceholder', 'common', 'emailPlaceholder', 'your@email.com'),
  ('common.toggleTheme', 'common', 'toggleTheme', 'Toggle theme'),
  ('common.use', 'common', 'use', 'Use'),
  ('landing.about.cta.contact_us', 'landing', 'about.cta.contact_us', 'Contact Us'),
  ('landing.about.cta.start_trial', 'landing', 'about.cta.start_trial', 'Start Free Trial'),
  ('landing.about.cta.title', 'landing', 'about.cta.title', 'Join us in reshaping restaurant communication'),
  ('landing.about.hero.badge', 'landing', 'about.hero.badge', 'Our story'),
  ('landing.about.hero.title_p1', 'landing', 'about.hero.title_p1', 'We built the AI we wished'),
  ('landing.about.hero.title_p2', 'landing', 'about.hero.title_p2', 'restaurants had.'),
  ('landing.about.journey.badge', 'landing', 'about.journey.badge', 'Our journey'),
  ('landing.about.journey.title', 'landing', 'about.journey.title', 'From idea to industry'),
  ('landing.about.mission.desc', 'landing', 'about.mission.desc', 'To make every restaurant — from a 10-seat family bistro to a 200-location chain — capable of delivering perfect customer communication at any scale, without hiring more staff.'),
  ('landing.about.mission.title', 'landing', 'about.mission.title', 'Our Mission'),
  ('landing.about.values.badge', 'landing', 'about.values.badge', 'What we believe'),
  ('landing.about.values.title', 'landing', 'about.values.title', 'Our values'),
  ('landing.about.vision.desc', 'landing', 'about.vision.desc', 'A world where no restaurant ever misses an order, a booking, or a customer question — because intelligent AI handles every interaction with the warmth and accuracy of your best employee.'),
  ('landing.about.vision.title', 'landing', 'about.vision.title', 'Our Vision'),
  ('landing.allRightsReserved', 'landing', 'allRightsReserved', 'All rights reserved.'),
  ('landing.blog.categories.ai_features', 'landing', 'blog.categories.ai_features', 'AI Features'),
  ('landing.blog.categories.ai_tech', 'landing', 'blog.categories.ai_tech', 'AI & Technology'),
  ('landing.blog.categories.all', 'landing', 'blog.categories.all', 'All'),
  ('landing.blog.categories.analytics', 'landing', 'blog.categories.analytics', 'Analytics'),
  ('landing.blog.categories.bookings', 'landing', 'blog.categories.bookings', 'Bookings'),
  ('landing.blog.categories.case_studies', 'landing', 'blog.categories.case_studies', 'Case Studies'),
  ('landing.blog.categories.cx', 'landing', 'blog.categories.cx', 'Customer Experience'),
  ('landing.blog.categories.ops', 'landing', 'blog.categories.ops', 'Restaurant Operations'),
  ('landing.blog.categories.updates', 'landing', 'blog.categories.updates', 'Product Updates'),
  ('landing.blog.featured.badge', 'landing', 'blog.featured.badge', 'Featured'),
  ('landing.blog.hero.description', 'landing', 'blog.hero.description', 'Research, case studies, and practical guides for restaurants using AI.'),
  ('landing.blog.hero.subtitle', 'landing', 'blog.hero.subtitle', 'The RestroAgent Blog'),
  ('landing.blog.hero.title', 'landing', 'blog.hero.title', 'Insights for restaurant operators'),
  ('landing.blog.load_more', 'landing', 'blog.load_more', 'Load more articles'),
  ('landing.blog.post1.date', 'landing', 'blog.post1.date', 'Mar 10, 2026'),
  ('landing.blog.post1.readTime', 'landing', 'blog.post1.readTime', '6 min read'),
  ('landing.blog.post1.title', 'landing', 'blog.post1.title', 'How Bella Napoli Reduced Missed Orders by 100% with AI Voice'),
  ('landing.blog.post2.date', 'landing', 'blog.post2.date', 'Mar 5, 2026'),
  ('landing.blog.post2.excerpt', 'landing', 'blog.post2.excerpt', 'We analyzed 50,000 missed calls across 500 restaurants. The average restaurant loses $2,400/month to unanswered phones.'),
  ('landing.blog.post2.readTime', 'landing', 'blog.post2.readTime', '8 min read'),
  ('landing.blog.post3.date', 'landing', 'blog.post3.date', 'Feb 28, 2026'),
  ('landing.blog.post3.readTime', 'landing', 'blog.post3.readTime', '5 min read'),
  ('landing.blog.post3.title', 'landing', 'blog.post3.title', 'Why Multilingual AI is Non-Negotiable for Modern Restaurants'),
  ('landing.blog.post4.date', 'landing', 'blog.post4.date', 'Feb 20, 2026'),
  ('landing.blog.post4.excerpt', 'landing', 'blog.post4.excerpt', 'Our biggest product update yet. The AI now detects customer frustration in real-time and escalates before the situation escalates.'),
  ('landing.blog.post4.readTime', 'landing', 'blog.post4.readTime', '4 min read'),
  ('landing.blog.post4.title', 'landing', 'blog.post4.title', 'RestroAgent 3.0: Introducing Real-Time Sentiment Analysis'),
  ('landing.blog.post5.date', 'landing', 'blog.post5.date', 'Feb 14, 2026'),
  ('landing.blog.post5.readTime', 'landing', 'blog.post5.readTime', '7 min read'),
  ('landing.blog.post5.title', 'landing', 'blog.post5.title', 'How to Train Your AI Agent to Sound Like Your Restaurant'),
  ('landing.blog.post6.date', 'landing', 'blog.post6.date', 'Feb 7, 2026'),
  ('landing.blog.post6.excerpt', 'landing', 'blog.post6.excerpt', 'How a family-owned Indian restaurant group scaled to 8 locations without adding a single admin staff member.'),
  ('landing.blog.post6.readTime', 'landing', 'blog.post6.readTime', '9 min read'),
  ('landing.blog.post7.date', 'landing', 'blog.post7.date', 'Jan 30, 2026'),
  ('landing.blog.post7.excerpt', 'landing', 'blog.post7.excerpt', 'Data from 2,400 restaurants shows that restaurants offering both voice and chat AI see 34% higher order volume than single-channel operators.'),
  ('landing.blog.post7.readTime', 'landing', 'blog.post7.readTime', '6 min read'),
  ('landing.blog.post7.title', 'landing', 'blog.post7.title', 'The Future of Restaurant Ordering: Voice, Chat, or Both?'),
  ('landing.blog.post8.date', 'landing', 'blog.post8.date', 'Jan 22, 2026'),
  ('landing.blog.post8.readTime', 'landing', 'blog.post8.readTime', '5 min read'),
  ('landing.blog.post8.title', 'landing', 'blog.post8.title', 'Table Booking Abandonment: Why 60% of Reservations Never Complete'),
  ('landing.blog.post.actions.save', 'landing', 'blog.post.actions.save', 'Save'),
  ('landing.blog.post.actions.share', 'landing', 'blog.post.actions.share', 'Share'),
  ('landing.blog.post.author.badge', 'landing', 'blog.post.author.badge', 'Author'),
  ('landing.blog.post.author.bio', 'landing', 'blog.post.author.bio', 'Alex has spent 8 years at the intersection of hospitality and technology. Before RestroAgent, he led product at two restaurant tech startups and spent 3 years as a restaurant operator himself.'),
  ('landing.blog.post.author.role', 'landing', 'blog.post.author.role', 'Head of Product, RestroAgent'),
  ('landing.blog.post.breadcrumb.blog', 'landing', 'blog.post.breadcrumb.blog', 'Blog'),
  ('landing.blog.post.breadcrumb.current', 'landing', 'blog.post.breadcrumb.current', 'AI Voice Ordering'),
  ('landing.blog.post.breadcrumb.home', 'landing', 'blog.post.breadcrumb.home', 'Home'),
  ('landing.blog.post.callout.label', 'landing', 'blog.post.callout.label', 'Key Insight'),
  ('landing.blog.post.callout.text', 'landing', 'blog.post.callout.text', 'Restaurants using AI voice ordering report an average of 0 missed calls during peak hours, compared to a 30-40% miss rate for manually-staffed phone lines.'),
  ('landing.blog.post.concerns.q2.a', 'landing', 'blog.post.concerns.q2.a', 'The AI handles modifications and special requests natively. For complaints or situations requiring human judgment, it escalates to a staff member in under 3 seconds.'),
  ('landing.blog.post.concerns.q2.q', 'landing', 'blog.post.concerns.q2.q', 'What about complex orders or complaints?'),
  ('landing.blog.post.concerns.q3.q', 'landing', 'blog.post.concerns.q3.q', 'What if the AI makes a mistake?'),
  ('landing.blog.post.concerns.title', 'landing', 'blog.post.concerns.title', 'Addressing Common Concerns'),
  ('landing.blog.post.conclusion.p1', 'landing', 'blog.post.conclusion.p1', 'AI voice ordering has moved from a novelty to a necessity for competitive restaurants. The data is clear: restaurants that adopt AI phone ordering capture more revenue, reduce staff stress, and deliver a better customer experience.'),
  ('landing.blog.post.conclusion.title', 'landing', 'blog.post.conclusion.title', 'Conclusion'),
  ('landing.blog.post.cta.footer', 'landing', 'blog.post.cta.footer', 'No credit card required. Setup takes under 2 minutes.'),
  ('landing.blog.post.cta.primary', 'landing', 'blog.post.cta.primary', 'Start your 14-day free trial'),
  ('landing.blog.post.cta.secondary', 'landing', 'blog.post.cta.secondary', 'Schedule a demo'),
  ('landing.blog.post.cta.subtitle', 'landing', 'blog.post.cta.subtitle', 'Join 2,400+ restaurants using RestroAgent to capture every call, increase revenue, and free up their staff.'),
  ('landing.blog.post.cta.title', 'landing', 'blog.post.cta.title', 'Stop missing phone orders today.'),
  ('landing.blog.post.hero.image_label', 'landing', 'blog.post.hero.image_label', 'AI Voice Ordering in Action'),
  ('landing.blog.post.how_it_works.step1.desc', 'landing', 'blog.post.how_it_works.step1.desc', 'The AI answers instantly — no hold music, no "please wait." It greets the customer using your restaurant''s name and personality.'),
  ('landing.blog.post.how_it_works.step1.title', 'landing', 'blog.post.how_it_works.step1.title', 'Customer calls your number'),
  ('landing.blog.post.how_it_works.step2.desc', 'landing', 'blog.post.how_it_works.step2.desc', 'The AI understands complex requests like "I''d like the pasta but without mushrooms and can you add extra parmesan?" — just like a human would.'),
  ('landing.blog.post.how_it_works.step2.title', 'landing', 'blog.post.how_it_works.step2.title', 'Natural conversation'),
  ('landing.blog.post.how_it_works.step3.desc', 'landing', 'blog.post.how_it_works.step3.desc', 'The AI reads back the complete order, confirms the total, and asks for payment or pickup/delivery details.'),
  ('landing.blog.post.how_it_works.step3.title', 'landing', 'blog.post.how_it_works.step3.title', 'Order confirmation'),
  ('landing.blog.post.how_it_works.step4.desc', 'landing', 'blog.post.how_it_works.step4.desc', 'The confirmed order fires directly to your POS or kitchen display system. No manual entry, no errors.'),
  ('landing.blog.post.how_it_works.step4.title', 'landing', 'blog.post.how_it_works.step4.title', 'Instant kitchen notification'),
  ('landing.blog.post.how_it_works.title', 'landing', 'blog.post.how_it_works.title', 'How AI Voice Ordering Works'),
  ('landing.blog.post.implementation.item1', 'landing', 'blog.post.implementation.item1', 'Your current menu (PDF, image, or POS export)'),
  ('landing.blog.post.implementation.item2', 'landing', 'blog.post.implementation.item2', 'Your phone number (we handle the forwarding)'),
  ('landing.blog.post.implementation.item4', 'landing', 'blog.post.implementation.item4', 'Optional: POS integration credentials'),
  ('landing.blog.post.implementation.p1', 'landing', 'blog.post.implementation.p1', 'Getting started with AI voice ordering is simpler than most restaurant owners expect. The entire setup process takes under 2 hours and requires no technical expertise.'),
  ('landing.blog.post.implementation.title', 'landing', 'blog.post.implementation.title', 'Implementation Guide'),
  ('landing.blog.post.meta.date', 'landing', 'blog.post.meta.date', 'March 12, 2026'),
  ('landing.blog.post.meta.readTime', 'landing', 'blog.post.meta.readTime', '8 min read'),
  ('landing.blog.post.newsletter.button', 'landing', 'blog.post.newsletter.button', 'Subscribe'),
  ('landing.blog.post.newsletter.desc', 'landing', 'blog.post.newsletter.desc', 'Get the latest restaurant tech insights delivered to your inbox.'),
  ('landing.blog.post.newsletter.footer', 'landing', 'blog.post.newsletter.footer', 'Join 4,500+ restaurant leaders.'),
  ('landing.blog.post.newsletter.placeholder', 'landing', 'blog.post.newsletter.placeholder', 'Your email'),
  ('landing.blog.post.newsletter.title', 'landing', 'blog.post.newsletter.title', 'Stay Ahead'),
  ('landing.blog.post.problem.p1', 'landing', 'blog.post.problem.p1', 'Traditional phone ordering creates a bottleneck that costs restaurants in three distinct ways: missed revenue from unanswered calls, reduced service quality when staff are pulled away from tables, and human error in order-taking.'),
  ('landing.blog.post.problem.stats.error', 'landing', 'blog.post.problem.stats.error', 'Order error rate (human)'),
  ('landing.blog.post.problem.stats.hold', 'landing', 'blog.post.problem.stats.hold', 'Average hold time before hang-up'),
  ('landing.blog.post.problem.stats.missed', 'landing', 'blog.post.problem.stats.missed', 'Calls missed during peak hours'),
  ('landing.blog.post.problem.title', 'landing', 'blog.post.problem.title', 'The Problem with Traditional Phone Orders'),
  ('landing.blog.post.related.subtitle', 'landing', 'blog.post.related.subtitle', 'More insights on restaurant technology and operations.'),
  ('landing.blog.post.related.title', 'landing', 'blog.post.related.title', 'Keep Reading'),
  ('landing.blog.post.related.view_all', 'landing', 'blog.post.related.view_all', 'View all articles'),
  ('landing.blog.post.results.author_role', 'landing', 'blog.post.results.author_role', 'Owner, Bella Napoli, New York'),
  ('landing.blog.post.results.p1', 'landing', 'blog.post.results.p1', 'After analyzing 12 months of data across 2,400+ restaurants, the numbers speak for themselves.'),
  ('landing.blog.post.results.quote', 'landing', 'blog.post.results.quote', '"We went from missing 30% of phone orders during rush hour to zero missed calls. The ROI was clear within the first week. I wish we''d done this years ago."'),
  ('landing.blog.post.results.title', 'landing', 'blog.post.results.title', 'Real-World Results'),
  ('landing.blog.post.stats.resolution.context', 'landing', 'blog.post.stats.resolution.context', 'Industry avg: 72%'),
  ('landing.blog.post.stats.resolution.label', 'landing', 'blog.post.stats.resolution.label', 'AI Resolution Rate'),
  ('landing.blog.post.stats.revenue.context', 'landing', 'blog.post.stats.revenue.context', 'across 2,400+ restaurants'),
  ('landing.blog.post.stats.revenue.label', 'landing', 'blog.post.stats.revenue.label', 'Avg Revenue Lift'),
  ('landing.blog.post.subtitle', 'landing', 'blog.post.subtitle', 'A deep dive into how AI-powered phone ordering is eliminating missed calls, reducing staff workload, and adding thousands in monthly revenue for restaurants of all sizes.'),
  ('landing.blog.post.title', 'landing', 'blog.post.title', 'How AI Voice Ordering Helped 2,400+ Restaurants Capture Every Call'),
  ('landing.blog.post.toc.concerns', 'landing', 'blog.post.toc.concerns', 'Addressing Common Concerns'),
  ('landing.blog.post.toc.conclusion', 'landing', 'blog.post.toc.conclusion', 'Conclusion'),
  ('landing.blog.post.toc.how_it_works', 'landing', 'blog.post.toc.how_it_works', 'How AI Voice Ordering Works'),
  ('landing.blog.post.toc.implementation', 'landing', 'blog.post.toc.implementation', 'Implementation Guide'),
  ('landing.blog.post.toc.introduction', 'landing', 'blog.post.toc.introduction', 'Introduction'),
  ('landing.blog.post.toc.problem', 'landing', 'blog.post.toc.problem', 'The Problem with Traditional Phone Orders'),
  ('landing.blog.post.toc.results', 'landing', 'blog.post.toc.results', 'Real-World Results'),
  ('landing.blog.post.toc.title', 'landing', 'blog.post.toc.title', 'In this article'),
  ('landing.blog.read_article', 'landing', 'blog.read_article', 'Read article'),
  ('landing.blog.related1.date', 'landing', 'blog.related1.date', 'Mar 8, 2026'),
  ('landing.blog.related1.excerpt', 'landing', 'blog.related1.excerpt', 'Automated SMS and WhatsApp reminders that adapt to customer behavior patterns can dramatically cut no-show rates.'),
  ('landing.blog.related1.readTime', 'landing', 'blog.related1.readTime', '5 min read'),
  ('landing.blog.related1.title', 'landing', 'blog.related1.title', 'How to Reduce No-Shows by 40% with AI-Powered Reminders'),
  ('landing.blog.related2.date', 'landing', 'blog.related2.date', 'Mar 1, 2026'),
  ('landing.blog.related2.excerpt', 'landing', 'blog.related2.excerpt', 'How restaurants are using AI to serve customers in 30+ languages without hiring multilingual staff.'),
  ('landing.blog.related2.readTime', 'landing', 'blog.related2.readTime', '7 min read'),
  ('landing.blog.related2.title', 'landing', 'blog.related2.title', 'Serving Every Customer: Multilingual AI for Modern Restaurants'),
  ('landing.blog.related3.date', 'landing', 'blog.related3.date', 'Feb 22, 2026'),
  ('landing.blog.related3.excerpt', 'landing', 'blog.related3.excerpt', 'Understanding peak hours, customer lifetime value, and order patterns to make smarter business decisions.'),
  ('landing.blog.related3.readTime', 'landing', 'blog.related3.readTime', '9 min read'),
  ('landing.blog.tags.case_study', 'landing', 'blog.tags.case_study', 'Case Study'),
  ('landing.blog.tags.guide', 'landing', 'blog.tags.guide', 'Guide'),
  ('landing.blog.tags.insights', 'landing', 'blog.tags.insights', 'Insights'),
  ('landing.blog.tags.product', 'landing', 'blog.tags.product', 'Product'),
  ('landing.blog.tags.research', 'landing', 'blog.tags.research', 'Research'),
  ('landing.builtForRestaurants', 'landing', 'builtForRestaurants', 'Built for restaurants that take hospitality seriously.'),
  ('landing.contact.demo.title', 'landing', 'contact.demo.title', '🚀 Want a live demo?'),
  ('landing.contact.form.email_label', 'landing', 'contact.form.email_label', 'Email Address *'),
  ('landing.contact.form.email_placeholder', 'landing', 'contact.form.email_placeholder', 'marco@restaurant.com'),
  ('landing.contact.form.message_label', 'landing', 'contact.form.message_label', 'Message *'),
  ('landing.contact.form.name_label', 'landing', 'contact.form.name_label', 'Full Name *'),
  ('landing.contact.form.name_placeholder', 'landing', 'contact.form.name_placeholder', 'Marco Rossi'),
  ('landing.contact.form.sending', 'landing', 'contact.form.sending', 'Sending...'),
  ('landing.contact.form.subject_billing', 'landing', 'contact.form.subject_billing', 'Billing question'),
  ('landing.contact.form.subject_default', 'landing', 'contact.form.subject_default', 'Select a topic...'),
  ('landing.contact.form.subject_demo', 'landing', 'contact.form.subject_demo', 'Request a demo'),
  ('landing.contact.form.subject_general', 'landing', 'contact.form.subject_general', 'General question'),
  ('landing.contact.form.subject_label', 'landing', 'contact.form.subject_label', 'Subject *'),
  ('landing.contact.form.subject_partnership', 'landing', 'contact.form.subject_partnership', 'Partnership inquiry'),
  ('landing.contact.form.subject_support', 'landing', 'contact.form.subject_support', 'Technical support'),
  ('landing.contact.form.submit', 'landing', 'contact.form.submit', 'Send Message'),
  ('landing.contact.form.title', 'landing', 'contact.form.title', 'Send us a message'),
  ('landing.contact.hero.badge', 'landing', 'contact.hero.badge', 'Get in touch'),
  ('landing.contact.hero.subtitle', 'landing', 'contact.hero.subtitle', 'Whether you have a question, need a demo, or just want to say hi — our team responds within 4 hours.'),
  ('landing.contact.info.email', 'landing', 'contact.info.email', 'Email'),
  ('landing.contact.info.hq', 'landing', 'contact.info.hq', 'Headquarters'),
  ('landing.contact.info.phone_hours', 'landing', 'contact.info.phone_hours', 'Mon–Fri, 9am–6pm CET'),
  ('landing.contact.info.phone', 'landing', 'contact.info.phone', 'Phone'),
  ('landing.contact.info.response_critical', 'landing', 'contact.info.response_critical', 'Critical issues: < 1 hour'),
  ('landing.contact.info.response_normal', 'landing', 'contact.info.response_normal', '< 4 hours during business hours'),
  ('landing.contact.info.response', 'landing', 'contact.info.response', 'Response time'),
  ('landing.contact.success.title', 'landing', 'contact.success.title', 'Message sent!'),
  ('landing.cookie.footer.questions', 'landing', 'cookie.footer.questions', 'Questions about our cookie practices?'),
  ('landing.cookie.hero.date', 'landing', 'cookie.hero.date', 'April 1, 2026'),
  ('landing.cookie.hero.desc', 'landing', 'cookie.hero.desc', 'This policy explains how RestroAgent uses cookies and similar tracking technologies on our platform and website.'),
  ('landing.cookie.hero.title', 'landing', 'cookie.hero.title', 'Cookie Policy'),
  ('landing.cookiePolicy', 'landing', 'cookiePolicy', 'Cookie Policy'),
  ('landing.cookie.types.title', 'landing', 'cookie.types.title', 'Types of Cookies We Use'),
  ('landing.faq.cta.contact_support', 'landing', 'faq.cta.contact_support', 'Contact Support'),
  ('landing.faq.cta.subtitle', 'landing', 'faq.cta.subtitle', 'Our team responds within 4 hours during business hours.'),
  ('landing.faq.cta.title', 'landing', 'faq.cta.title', 'Still have questions?'),
  ('landing.faq.hero.badge', 'landing', 'faq.hero.badge', 'Help center'),
  ('landing.faq.hero.contact_link', 'landing', 'faq.hero.contact_link', 'Contact us.'),
  ('landing.faq.hero.title', 'landing', 'faq.hero.title', 'Frequently Asked Questions'),
  ('landing.footerCareers', 'landing', 'footerCareers', 'Careers'),
  ('landing.footerChangelog', 'landing', 'footerChangelog', 'Changelog'),
  ('landing.footerCompany', 'landing', 'footerCompany', 'Company'),
  ('landing.footerIntegrations', 'landing', 'footerIntegrations', 'Integrations'),
  ('landing.footerLegal', 'landing', 'footerLegal', 'Legal'),
  ('landing.footerProduct', 'landing', 'footerProduct', 'Product'),
  ('landing.getStarted', 'landing', 'getStarted', 'Get Started'),
  ('landing.home.caseStudiesBadge', 'landing', 'home.caseStudiesBadge', 'Customer success'),
  ('landing.home.caseStudiesCTA', 'landing', 'home.caseStudiesCTA', 'See more stories'),
  ('landing.home.caseStudiesSub', 'landing', 'home.caseStudiesSub', 'See how restaurants like yours transformed operations and grew revenue with RestroAgent.'),
  ('landing.home.caseStudiesTitle', 'landing', 'home.caseStudiesTitle', 'Real restaurants, real results'),
  ('landing.home.caseStudy1Highlight', 'landing', 'home.caseStudy1Highlight', '$13K extra revenue per month'),
  ('landing.home.caseStudy1Quote', 'landing', 'home.caseStudy1Quote', 'We went from missing 30% of phone orders during rush hour to zero missed calls. The ROI was clear within the first week.'),
  ('landing.home.caseStudy2Highlight', 'landing', 'home.caseStudy2Highlight', '$96K revenue lift in 90 days'),
  ('landing.home.caseStudy2Quote', 'landing', 'home.caseStudy2Quote', 'Managing 8 branches from one dashboard changed everything. Staff now focus on guests, not phones. Revenue up 31% in 3 months.'),
  ('landing.home.caseStudy3Highlight', 'landing', 'home.caseStudy3Highlight', '73% more online orders captured'),
  ('landing.home.caseStudy3Quote', 'landing', 'home.caseStudy3Quote', 'The multilingual support is incredible. Our Mandarin and English customers both get flawless service. Setup took one afternoon.'),
  ('landing.home.faqA1', 'landing', 'home.faqA1', 'Most restaurants are live within 2 hours. You connect your menu, set your preferences, and point your phone number — we handle the rest. No developers needed.'),
  ('landing.home.faqA2', 'landing', 'home.faqA2', 'RestroAgent supports 40+ languages including English, Spanish, Mandarin, French, Arabic, Portuguese, Japanese, and more. Language detection is fully automatic.'),
  ('landing.home.faqA4', 'landing', 'home.faqA4', 'The AI escalates gracefully — it alerts your staff via SMS or hands the call to a human team member. No customer ever gets left with an unanswered question.'),
  ('landing.home.faqA5', 'landing', 'home.faqA5', 'No contracts, no lock-in. All plans are billed monthly and you can cancel any time. Annual plans are available at a 20% discount.'),
  ('landing.home.faqA6', 'landing', 'home.faqA6', 'Absolutely. You control the tone, personality, greetings, upsell scripts, fallback messages, and brand language. The AI sounds exactly like your restaurant, not a generic bot.'),
  ('landing.home.faqA7', 'landing', 'home.faqA7', 'Plans start at $99/month per location. Multi-branch packages offer significant discounts — the Enterprise plan covers unlimited branches with a single flat fee. See our pricing page for details.'),
  ('landing.home.faqA8', 'landing', 'home.faqA8', 'Yes — all data is encrypted at rest and in transit using AES-256. We are SOC 2 Type II compliant and GDPR-ready. We never sell or share customer data with third parties.'),
  ('landing.home.faqBadge', 'landing', 'home.faqBadge', 'Got questions?'),
  ('landing.home.faqCTA', 'landing', 'home.faqCTA', 'Talk to our team'),
  ('landing.home.faqFooter', 'landing', 'home.faqFooter', 'Still have questions?'),
  ('landing.home.faqQ1', 'landing', 'home.faqQ1', 'How quickly can RestroAgent be set up?'),
  ('landing.home.faqQ2', 'landing', 'home.faqQ2', 'What languages does the AI support?'),
  ('landing.home.faqQ3', 'landing', 'home.faqQ3', 'Does it integrate with my existing POS?'),
  ('landing.home.faqQ4', 'landing', 'home.faqQ4', 'What happens if the AI can''t answer a question?'),
  ('landing.home.faqQ5', 'landing', 'home.faqQ5', 'Is there a contract or minimum commitment?'),
  ('landing.home.faqQ6', 'landing', 'home.faqQ6', 'Can I customise what the AI says and how it sounds?'),
  ('landing.home.faqQ7', 'landing', 'home.faqQ7', 'How does pricing work for multiple locations?'),
  ('landing.home.faqQ8', 'landing', 'home.faqQ8', 'Is customer data secure and private?'),
  ('landing.home.faqSub', 'landing', 'home.faqSub', 'Everything you need to know before getting started.'),
  ('landing.home.faqTitle', 'landing', 'home.faqTitle', 'Frequently asked questions'),
  ('landing.home.feat1Badge', 'landing', 'home.feat1Badge', '98.7% accuracy'),
  ('landing.home.feat1Desc', 'landing', 'home.feat1Desc', 'Natural phone conversations that take orders, handle modifications, and upsell — in any language, any accent.'),
  ('landing.home.feat1Title', 'landing', 'home.feat1Title', 'AI Voice Agent'),
  ('landing.home.feat2Badge', 'landing', 'home.feat2Badge', '< 1.2s response'),
  ('landing.home.feat2Chat1', 'landing', 'home.feat2Chat1', 'Do you have vegan options?'),
  ('landing.home.feat2Chat2', 'landing', 'home.feat2Chat2', 'Book a table for 4 on Saturday?'),
  ('landing.home.feat2Chat3', 'landing', 'home.feat2Chat3', 'What are your opening hours?'),
  ('landing.home.feat2Desc', 'landing', 'home.feat2Desc', 'AI-powered conversations across every channel — 24/7, instant, accurate.'),
  ('landing.home.feat2Title', 'landing', 'home.feat2Title', 'Conversations'),
  ('landing.home.feat3Badge', 'landing', 'home.feat3Badge', '40% fewer no-shows'),
  ('landing.home.feat3Desc', 'landing', 'home.feat3Desc', 'Real-time table availability, automated confirmations, and smart reminder sequences.'),
  ('landing.home.feat3Label', 'landing', 'home.feat3Label', 'Friday evening — open slots'),
  ('landing.home.feat3Status1', 'landing', 'home.feat3Status1', 'Booked'),
  ('landing.home.feat3Status2', 'landing', 'home.feat3Status2', 'Few left'),
  ('landing.home.feat3Status3', 'landing', 'home.feat3Status3', 'Open'),
  ('landing.home.feat3Title', 'landing', 'home.feat3Title', 'Reservations'),
  ('landing.home.feat4Badge', 'landing', 'home.feat4Badge', 'Live dashboards'),
  ('landing.home.feat4Desc', 'landing', 'home.feat4Desc', 'Deep insights into order patterns, peak hours, and customer lifetime value.'),
  ('landing.home.feat4Title', 'landing', 'home.feat4Title', 'Analytics'),
  ('landing.home.feat5Badge', 'landing', 'home.feat5Badge', 'Unlimited branches'),
  ('landing.home.feat5Desc', 'landing', 'home.feat5Desc', 'One dashboard for all your locations — unified menu, staff, and analytics.'),
  ('landing.home.feat5Label', 'landing', 'home.feat5Label', 'All branches online'),
  ('landing.home.feat5Title', 'landing', 'home.feat5Title', 'Multi-Branch'),
  ('landing.home.feat6Badge', 'landing', 'home.feat6Badge', 'Real-time sync'),
  ('landing.home.feat6Desc', 'landing', 'home.feat6Desc', 'Track every order from placement to delivery. AI flags delays, manages modifications, and keeps the kitchen in sync.'),
  ('landing.home.feat6Step1', 'landing', 'home.feat6Step1', 'New order received'),
  ('landing.home.feat6Step2', 'landing', 'home.feat6Step2', 'Kitchen notified'),
  ('landing.home.feat6Step3', 'landing', 'home.feat6Step3', 'Ready for pickup'),
  ('landing.home.feat6Title', 'landing', 'home.feat6Title', 'Order Management'),
  ('landing.home.featuresBadge', 'landing', 'home.featuresBadge', 'Platform capabilities'),
  ('landing.home.featuresSub', 'landing', 'home.featuresSub', 'Every feature designed around how restaurants actually work — from single-location diners to multi-branch chains.'),
  ('landing.home.featuresTitle', 'landing', 'home.featuresTitle', 'Built for restaurants, not call centers'),
  ('landing.home.finalCtaBadge', 'landing', 'home.finalCtaBadge', '14-day free trial · No credit card'),
  ('landing.home.finalCtaFooter', 'landing', 'home.finalCtaFooter', 'Cancel anytime · Setup in 2 hours · 24/7 support'),
  ('landing.home.finalCtaPrimary', 'landing', 'home.finalCtaPrimary', 'Start Your Free Trial'),
  ('landing.home.finalCtaSecondary', 'landing', 'home.finalCtaSecondary', 'Talk to Sales'),
  ('landing.home.finalCtaSub', 'landing', 'home.finalCtaSub', 'Join 2,400+ restaurants using RestroAgent to handle every call, chat, and booking — automatically.'),
  ('landing.home.finalCtaTitle', 'landing', 'home.finalCtaTitle', 'Stop missing orders. Start growing revenue.'),
  ('landing.home.heroBadge', 'landing', 'home.heroBadge', 'Trusted by 2,400+ restaurants worldwide'),
  ('landing.home.heroCtaPricing', 'landing', 'home.heroCtaPricing', 'View Pricing'),
  ('landing.home.heroCtaStart', 'landing', 'home.heroCtaStart', 'Start Free Trial'),
  ('landing.home.heroSub', 'landing', 'home.heroSub', 'AI voice and chat agents built for restaurants — they take orders, manage bookings, and handle customer queries around the clock, in any language.'),
  ('landing.home.heroTitleLine1', 'landing', 'home.heroTitleLine1', 'Every call answered.'),
  ('landing.home.heroTitleLine2', 'landing', 'home.heroTitleLine2', 'Every order captured.'),
  ('landing.home.heroTitleLine3', 'landing', 'home.heroTitleLine3', 'Zero hold times.'),
  ('landing.home.heroTrust1', 'landing', 'home.heroTrust1', 'No credit card required'),
  ('landing.home.heroTrust2', 'landing', 'home.heroTrust2', '14-day free trial'),
  ('landing.home.heroTrust3', 'landing', 'home.heroTrust3', 'Live in 2 hours'),
  ('landing.home.howBadge', 'landing', 'home.howBadge', 'Simple setup'),
  ('landing.home.howStep1Desc', 'landing', 'home.howStep1Desc', 'Import from your POS or upload a PDF. We parse and structure it automatically.'),
  ('landing.home.howStep1Title', 'landing', 'home.howStep1Title', 'Connect your menu'),
  ('landing.home.howStep2Title', 'landing', 'home.howStep2Title', 'Train the AI'),
  ('landing.home.howStep3Desc', 'landing', 'home.howStep3Desc', 'Point your phone number to RestroAgent and activate your channels. Takes 5 minutes, no downtime.'),
  ('landing.home.howStep3Title', 'landing', 'home.howStep3Title', 'Go live instantly'),
  ('landing.home.howSub', 'landing', 'home.howSub', 'No technical expertise needed. We handle the heavy lifting so you can focus on your guests.'),
  ('landing.home.howTitle', 'landing', 'home.howTitle', 'Live in under 2 hours'),
  ('landing.home.integrationLabel', 'landing', 'home.integrationLabel', 'Connects with your existing tools'),
  ('landing.home.integrationsBadge', 'landing', 'home.integrationsBadge', 'Ecosystem'),
  ('landing.home.integrationsCTA', 'landing', 'home.integrationsCTA', 'See all integrations'),
  ('landing.home.integrationsSub', 'landing', 'home.integrationsSub', 'Connect to 50+ POS systems, delivery platforms, and payment processors. No rip-and-replace required.'),
  ('landing.home.integrationsTitle', 'landing', 'home.integrationsTitle', 'Works with your entire stack'),
  ('landing.home.liveEvent1', 'landing', 'home.liveEvent1', 'Table 7 — Order placed: Margherita ×2, Tiramisu ×1'),
  ('landing.home.liveEvent2', 'landing', 'home.liveEvent2', 'Phone booking confirmed: Friday 7pm, 4 guests'),
  ('landing.home.liveEvent3', 'landing', 'home.liveEvent3', 'WhatsApp: Gluten-free query answered in 1.1s'),
  ('landing.home.liveEvent4', 'landing', 'home.liveEvent4', 'DoorDash order captured: $38.50'),
  ('landing.home.liveEvent5', 'landing', 'home.liveEvent5', 'Reservation reminder sent — 0 no-shows today'),
  ('landing.home.liveEvent6', 'landing', 'home.liveEvent6', 'Upsell accepted: dessert added to Table 3 order'),
  ('landing.home.metricAIResolutionRate', 'landing', 'home.metricAIResolutionRate', 'AI Resolution Rate'),
  ('landing.home.metricLanguagesSupported', 'landing', 'home.metricLanguagesSupported', 'Languages Supported'),
  ('landing.home.metricMissedCalls', 'landing', 'home.metricMissedCalls', 'Missed Calls'),
  ('landing.home.metricMonthlyRevenue', 'landing', 'home.metricMonthlyRevenue', 'Monthly Revenue'),
  ('landing.home.metricOnlineOrders', 'landing', 'home.metricOnlineOrders', 'Online Orders'),
  ('landing.home.metricQuarterlyRevenue', 'landing', 'home.metricQuarterlyRevenue', 'Quarterly Revenue'),
  ('landing.home.metricStaffPhoneTime', 'landing', 'home.metricStaffPhoneTime', 'Staff Phone Time'),
  ('landing.home.mockCallsStat', 'landing', 'home.mockCallsStat', 'Zero missed calls'),
  ('landing.home.mockKpi1', 'landing', 'home.mockKpi1', 'Active Orders'),
  ('landing.home.mockKpi2', 'landing', 'home.mockKpi2', 'AI Handled'),
  ('landing.home.mockKpi3', 'landing', 'home.mockKpi3', 'Avg Response'),
  ('landing.home.mockLiveDashboard', 'landing', 'home.mockLiveDashboard', 'Live Dashboard'),
  ('landing.home.mockMsg1Name', 'landing', 'home.mockMsg1Name', 'Table 7 — Dine-in'),
  ('landing.home.mockMsg1Text', 'landing', 'home.mockMsg1Text', 'Order confirmed: Pasta Carbonara × 2, Tiramisu × 1'),
  ('landing.home.mockMsg2Name', 'landing', 'home.mockMsg2Name', 'Phone +1 (555) 0142'),
  ('landing.home.mockMsg2Text', 'landing', 'home.mockMsg2Text', 'Booking for 4 on Friday 7pm — confirmed & SMS sent'),
  ('landing.home.mockMsg3Name', 'landing', 'home.mockMsg3Name', 'WhatsApp +44 7700'),
  ('landing.home.mockMsg3Text', 'landing', 'home.mockMsg3Text', 'Asking about gluten-free options — AI responding...'),
  ('landing.home.mockRevLabel', 'landing', 'home.mockRevLabel', 'Revenue today'),
  ('landing.home.mockRevStat', 'landing', 'home.mockRevStat', '↑ 23% vs yesterday'),
  ('landing.home.mockTime1', 'landing', 'home.mockTime1', '2s ago'),
  ('landing.home.mockTime2', 'landing', 'home.mockTime2', '18s ago'),
  ('landing.home.mockTime3', 'landing', 'home.mockTime3', '34s ago'),
  ('landing.home.mockTimeframe', 'landing', 'home.mockTimeframe', 'Last 30 days'),
  ('landing.home.testimonial2Quote', 'landing', 'home.testimonial2Quote', 'Managing 8 branches from one dashboard changed everything. Staff focus on guests, not phones. Revenue up 31% in 3 months. The ROI was undeniable from week one.'),
  ('landing.home.testimonial3Quote', 'landing', 'home.testimonial3Quote', 'The multilingual support is incredible. Our Mandarin and English customers both get flawless service. Setup took one afternoon.'),
  ('landing.home.testimonial4Quote', 'landing', 'home.testimonial4Quote', 'Within a week, online orders were up 40% because the AI upsells naturally. It suggested desserts better than our best server.'),
  ('landing.home.testimonialsBadge', 'landing', 'home.testimonialsBadge', 'Customer stories'),
  ('landing.home.testimonialsSub', 'landing', 'home.testimonialsSub', 'Real results from real restaurants — no cherry-picked metrics.'),
  ('landing.home.testimonialsTitle', 'landing', 'home.testimonialsTitle', 'Restaurant owners love it'),
  ('landing.legal.badge', 'landing', 'legal.badge', 'Legal'),
  ('landing.legal.cookie', 'landing', 'legal.cookie', 'Cookie Policy'),
  ('landing.legal.footer.contact_us', 'landing', 'legal.footer.contact_us', 'Contact Us'),
  ('landing.legal.last_updated', 'landing', 'legal.last_updated', 'Last updated'),
  ('landing.legal.privacy', 'landing', 'legal.privacy', 'Privacy Policy'),
  ('landing.legal.refund', 'landing', 'legal.refund', 'Refund Policy'),
  ('landing.legal.terms', 'landing', 'legal.terms', 'Terms of Service'),
  ('landing.pricing.contact_sales', 'landing', 'pricing.contact_sales', 'Contact us for pricing →'),
  ('landing.pricing.cta.badge', 'landing', 'pricing.cta.badge', 'Start today'),
  ('landing.pricing.cta.start_trial', 'landing', 'pricing.cta.start_trial', 'Start Free Trial'),
  ('landing.pricing.cta.subtitle', 'landing', 'pricing.cta.subtitle', 'Start your 14-day free trial. No credit card required. Cancel anytime.'),
  ('landing.pricing.cta.talk_to_sales', 'landing', 'pricing.cta.talk_to_sales', 'Talk to Sales'),
  ('landing.pricing.cta.title', 'landing', 'pricing.cta.title', 'Ready to transform your restaurant?'),
  ('landing.pricing.empty', 'landing', 'pricing.empty', 'No plans are currently available. Please check back soon.'),
  ('landing.pricing.faq.badge', 'landing', 'pricing.faq.badge', 'Got questions?'),
  ('landing.pricing.faq.title', 'landing', 'pricing.faq.title', 'Frequently asked'),
  ('landing.pricing.hero.badge', 'landing', 'pricing.hero.badge', 'Simple pricing'),
  ('landing.pricing.hero.subtitle', 'landing', 'pricing.hero.subtitle', 'All plans include a 14-day free trial. No credit card required.'),
  ('landing.pricing.hero.title_p1', 'landing', 'pricing.hero.title_p1', 'Pay for what you use.'),
  ('landing.pricing.hero.title_p2', 'landing', 'pricing.hero.title_p2', 'Nothing more.'),
  ('landing.pricing.info.part1', 'landing', 'pricing.info.part1', 'All plans include a'),
  ('landing.pricing.info.part2', 'landing', 'pricing.info.part2', 'onboarding support, and access to our knowledge base. Enterprise customers get a dedicated account manager and custom SLA.'),
  ('landing.pricing.info.trial', 'landing', 'pricing.info.trial', '14-day free trial'),
  ('landing.pricing.plan.billed_annually', 'landing', 'pricing.plan.billed_annually', 'Billed annually'),
  ('landing.pricing.plan.contact_sales', 'landing', 'pricing.plan.contact_sales', 'Contact Sales'),
  ('landing.pricing.plan.no_card', 'landing', 'pricing.plan.no_card', 'No credit card required'),
  ('landing.pricing.plan.per_month', 'landing', 'pricing.plan.per_month', '/mo'),
  ('landing.pricing.plan.per_year', 'landing', 'pricing.plan.per_year', 'yr'),
  ('landing.pricing.plan.start_trial', 'landing', 'pricing.plan.start_trial', 'Start Free Trial'),
  ('landing.pricing.talk_to_sales', 'landing', 'pricing.talk_to_sales', 'Talk to sales →'),
  ('landing.pricing.toggle.annual', 'landing', 'pricing.toggle.annual', 'Annual'),
  ('landing.pricing.toggle.monthly', 'landing', 'pricing.toggle.monthly', 'Monthly'),
  ('landing.pricing.toggle.save', 'landing', 'pricing.toggle.save', 'Save 20%'),
  ('landing.privacy.footer.questions', 'landing', 'privacy.footer.questions', 'Questions about your privacy or data?'),
  ('landing.privacy.hero.date', 'landing', 'privacy.hero.date', 'April 1, 2026'),
  ('landing.privacy.hero.desc', 'landing', 'privacy.hero.desc', 'At RestroAgent, your privacy matters. This policy explains how we collect, use, and protect your information when you use our platform.'),
  ('landing.privacy.hero.title', 'landing', 'privacy.hero.title', 'Privacy Policy'),
  ('landing.privacyPolicy', 'landing', 'privacyPolicy', 'Privacy Policy'),
  ('landing.refund.footer.contact_support', 'landing', 'refund.footer.contact_support', 'Contact Billing Support'),
  ('landing.refund.footer.questions', 'landing', 'refund.footer.questions', 'Need a refund or have billing questions?'),
  ('landing.refund.footer.response_time', 'landing', 'refund.footer.response_time', 'Our team responds within one business day.'),
  ('landing.refund.guarantee.desc', 'landing', 'refund.guarantee.desc', 'Not satisfied? Email us within 30 days of your first payment for a full refund. No contracts, no hassle.'),
  ('landing.refund.guarantee.title', 'landing', 'refund.guarantee.title', '30-Day Money-Back Guarantee'),
  ('landing.refund.hero.date', 'landing', 'refund.hero.date', 'April 1, 2026'),
  ('landing.refund.hero.title', 'landing', 'refund.hero.title', 'Refund Policy'),
  ('landing.refundPolicy', 'landing', 'refundPolicy', 'Refund Policy'),
  ('landing.stayUpdated', 'landing', 'stayUpdated', 'Stay updated'),
  ('landing.terms.footer.questions', 'landing', 'terms.footer.questions', 'Have questions about our terms?'),
  ('landing.terms.hero.date', 'landing', 'terms.hero.date', 'April 1, 2026'),
  ('landing.terms.hero.desc', 'landing', 'terms.hero.desc', 'Please read these Terms of Service carefully before using RestroAgent. These terms govern your use of our platform and services.'),
  ('landing.terms.hero.title', 'landing', 'terms.hero.title', 'Terms of Service'),
  ('landing.termsOfService', 'landing', 'termsOfService', 'Terms of Service'),
  ('nav.about', 'nav', 'about', 'About'),
  ('nav.contact', 'nav', 'contact', 'Contact'),
  ('nav.faq', 'nav', 'faq', 'FAQ'),
  ('nav.features', 'nav', 'features', 'Features'),
  ('nav.pricing', 'nav', 'pricing', 'Pricing')

  ON CONFLICT (key) DO NOTHING;

  
  -- ─── NEW KEYS FROM LATEST CHANGES ──────────────────────
  INSERT INTO public.translation_keys (key, category, description, default_value) VALUES
    ('admin.languages.badge.default', 'admin', 'languages.badge.default', 'DEFAULT'),
  ('admin.languages.badge.rtl', 'admin', 'languages.badge.rtl', 'RTL'),
  ('admin.languages.actions.autoTranslateUnavailable', 'admin', 'languages.actions.autoTranslateUnavailable', 'OPENAI_API_KEY is not configured')

  ON CONFLICT (key) DO NOTHING;

  
  -- ─── ONBOARDING PAGE TRANSLATION KEYS ──────────────────────
  INSERT INTO public.translation_keys (key, category, description, default_value) VALUES
    ('onboarding.step1.title', 'onboarding', 'step1.title', 'Restaurant Profile'),
  ('onboarding.step1.desc', 'onboarding', 'step1.desc', 'Tell us about your restaurant'),
  ('onboarding.step2.title', 'onboarding', 'step2.title', 'Branch Setup'),
  ('onboarding.step2.desc', 'onboarding', 'step2.desc', 'Set up your first location'),
  ('onboarding.step3.title', 'onboarding', 'step3.title', 'Menu Intro'),
  ('onboarding.step3.desc', 'onboarding', 'step3.desc', 'Add your first menu items'),
  ('onboarding.step4.title', 'onboarding', 'step4.title', 'AI Agent'),
  ('onboarding.step4.desc', 'onboarding', 'step4.desc', 'Configure your AI assistant'),
  ('onboarding.stepOf', 'onboarding', 'stepOf', 'Step {{current}} of {{total}}'),
  ('onboarding.step1.subtitle', 'onboarding', 'step1.subtitle', 'Basic information about your restaurant'),
  ('onboarding.restaurantName', 'onboarding', 'restaurantName', 'Restaurant Name'),
  ('onboarding.restaurantNamePlaceholder', 'onboarding', 'restaurantNamePlaceholder', 'The Rustic Fork'),
  ('onboarding.cuisineType', 'onboarding', 'cuisineType', 'Cuisine Type'),
  ('onboarding.selectCuisine', 'onboarding', 'selectCuisine', 'Select cuisine type'),
  ('onboarding.cuisine.italian', 'onboarding', 'cuisine.italian', 'Italian'),
  ('onboarding.cuisine.american', 'onboarding', 'cuisine.american', 'American'),
  ('onboarding.cuisine.asianFusion', 'onboarding', 'cuisine.asianFusion', 'Asian Fusion'),
  ('onboarding.cuisine.mexican', 'onboarding', 'cuisine.mexican', 'Mexican'),
  ('onboarding.cuisine.mediterranean', 'onboarding', 'cuisine.mediterranean', 'Mediterranean'),
  ('onboarding.cuisine.other', 'onboarding', 'cuisine.other', 'Other'),
  ('onboarding.phoneNumber', 'onboarding', 'phoneNumber', 'Phone Number'),
  ('onboarding.website', 'onboarding', 'website', 'Website (optional)'),
  ('onboarding.step2.heading', 'onboarding', 'step2.heading', 'First Branch Setup'),
  ('onboarding.step2.subtitle', 'onboarding', 'step2.subtitle', 'Set up your primary location'),
  ('onboarding.branchName', 'onboarding', 'branchName', 'Branch Name'),
  ('onboarding.branchNamePlaceholder', 'onboarding', 'branchNamePlaceholder', 'Main Branch / Downtown'),
  ('onboarding.address', 'onboarding', 'address', 'Address'),
  ('onboarding.addressPlaceholder', 'onboarding', 'addressPlaceholder', '123 Main Street, City, State'),
  ('onboarding.timezone', 'onboarding', 'timezone', 'Timezone'),
  ('onboarding.tz.pacific', 'onboarding', 'tz.pacific', 'Pacific Time (PT)'),
  ('onboarding.tz.mountain', 'onboarding', 'tz.mountain', 'Mountain Time (MT)'),
  ('onboarding.tz.central', 'onboarding', 'tz.central', 'Central Time (CT)'),
  ('onboarding.tz.eastern', 'onboarding', 'tz.eastern', 'Eastern Time (ET)'),
  ('onboarding.openingTime', 'onboarding', 'openingTime', 'Opening Time'),
  ('onboarding.closingTime', 'onboarding', 'closingTime', 'Closing Time'),
  ('onboarding.step3.heading', 'onboarding', 'step3.heading', 'Menu Setup'),
  ('onboarding.step3.subtitle', 'onboarding', 'step3.subtitle', 'Choose how you want to add your menu'),
  ('onboarding.menu.manual', 'onboarding', 'menu.manual', 'Add manually'),
  ('onboarding.menu.manualDesc', 'onboarding', 'menu.manualDesc', 'Enter items one by one using our menu editor'),
  ('onboarding.menu.bulk', 'onboarding', 'menu.bulk', 'Bulk upload with AI'),
  ('onboarding.menu.bulkDesc', 'onboarding', 'menu.bulkDesc', 'Upload a PDF, image, or CSV — AI will extract items automatically'),
  ('onboarding.menu.later', 'onboarding', 'menu.later', 'Skip for now'),
  ('onboarding.menu.laterDesc', 'onboarding', 'menu.laterDesc', 'Set up your menu later from Menu Management'),
  ('common.recommended', 'common', 'recommended', 'Recommended'),
  ('onboarding.step4.heading', 'onboarding', 'step4.heading', 'Configure AI Agent'),
  ('onboarding.step4.subtitle', 'onboarding', 'step4.subtitle', 'Personalize your AI assistant'),
  ('onboarding.agentName', 'onboarding', 'agentName', 'Agent Name'),
  ('onboarding.agentNameHint', 'onboarding', 'agentNameHint', 'Customers will see this name in conversations'),
  ('onboarding.conversationStyle', 'onboarding', 'conversationStyle', 'Conversation Style'),
  ('onboarding.style.friendly', 'onboarding', 'style.friendly', 'Friendly'),
  ('onboarding.style.professional', 'onboarding', 'style.professional', 'Professional'),
  ('onboarding.style.concise', 'onboarding', 'style.concise', 'Concise'),
  ('onboarding.enableChannels', 'onboarding', 'enableChannels', 'Enable Channels'),
  ('onboarding.channel.voice', 'onboarding', 'channel.voice', 'Voice Agent'),
  ('onboarding.channel.voiceDesc', 'onboarding', 'channel.voiceDesc', 'Handle inbound phone calls'),
  ('onboarding.channel.chat', 'onboarding', 'channel.chat', 'Chat Agent'),
  ('onboarding.channel.chatDesc', 'onboarding', 'channel.chatDesc', 'Web chat & messaging apps'),
  ('common.continue', 'common', 'continue', 'Continue'),
  ('onboarding.goToDashboard', 'onboarding', 'goToDashboard', 'Go to Dashboard')

  ON CONFLICT (key) DO NOTHING;

  
  -- ─── FINAL 5 REMAINING KEYS ──────────────────────
  INSERT INTO public.translation_keys (key, category, description, default_value) VALUES
    ('billing.statusActive', 'billing', 'statusActive', 'Active'),
  ('billing.statusTrial', 'billing', 'statusTrial', 'Trial'),
  ('billing.statusCancelled', 'billing', 'statusCancelled', 'Cancelled'),
  ('marketplace.google-analytics.name', 'marketplace', 'google-analytics.name', 'Google Analytics'),
  ('marketplace.google-analytics.description', 'marketplace', 'google-analytics.description', 'Track customer journeys, conversion funnels, and AI agent performance in Google Analytics 4.')

  ON CONFLICT (key) DO NOTHING;

  
  -- ─── FINAL SWEEP — ALL REMAINING KEYS ──────────────────────
  INSERT INTO public.translation_keys (key, category, description, default_value) VALUES
    ('forgotPassword.failedToProcess', 'forgotPassword', 'failedToProcess', 'Failed to process request'),
  ('forgotPassword.failedToSend', 'forgotPassword', 'failedToSend', 'Failed to send reset link. Please try again.'),
  ('forgotPassword.title', 'forgotPassword', 'title', 'Reset your password'),
  ('forgotPassword.sendingDots', 'forgotPassword', 'sendingDots', 'Sending...'),
  ('forgotPassword.sendLink', 'forgotPassword', 'sendLink', 'Send Reset Link'),
  ('forgotPassword.sentTitle', 'forgotPassword', 'sentTitle', 'Reset link ready'),
  ('forgotPassword.clickBelow', 'forgotPassword', 'clickBelow', 'Click the button below to reset your password. The link expires in 30 minutes.'),
  ('forgotPassword.resetNow', 'forgotPassword', 'resetNow', 'Reset Password Now'),
  ('forgotPassword.ifAccountExists', 'forgotPassword', 'ifAccountExists', 'If an account exists with'),
  ('forgotPassword.linkGenerated', 'forgotPassword', 'linkGenerated', ', a reset link has been generated.'),
  ('forgotPassword.needNew', 'forgotPassword', 'needNew', 'Need a new link?'),
  ('forgotPassword.tryAgain', 'forgotPassword', 'tryAgain', 'Try again'),
  ('auth.backToSignIn', 'auth', 'backToSignIn', 'Back to sign in'),
  ('auth.rule.minChars', 'auth', 'rule.minChars', 'At least 8 characters'),
  ('auth.rule.uppercase', 'auth', 'rule.uppercase', 'One uppercase letter'),
  ('auth.rule.number', 'auth', 'rule.number', 'One number'),
  ('resetPassword.noToken', 'resetPassword', 'noToken', 'Reset token is missing. Please use the link from your email.'),
  ('resetPassword.failedToUpdate', 'resetPassword', 'failedToUpdate', 'Failed to update password'),
  ('resetPassword.failedToUpdateTryAgain', 'resetPassword', 'failedToUpdateTryAgain', 'Failed to update password. Please try again.'),
  ('resetPassword.title', 'resetPassword', 'title', 'Set new password'),
  ('resetPassword.subtitle', 'resetPassword', 'subtitle', 'Choose a strong password for your account.'),
  ('resetPassword.noTokenWarning', 'resetPassword', 'noTokenWarning', 'No reset token found. Please use the link from your password reset email.'),
  ('resetPassword.newPassword', 'resetPassword', 'newPassword', 'New Password'),
  ('resetPassword.confirmPassword', 'resetPassword', 'confirmPassword', 'Confirm Password'),
  ('resetPassword.noMatch', 'resetPassword', 'noMatch', 'Passwords do not match'),
  ('resetPassword.updatingDots', 'resetPassword', 'updatingDots', 'Updating...'),
  ('resetPassword.updatePassword', 'resetPassword', 'updatePassword', 'Update Password'),
  ('resetPassword.successTitle', 'resetPassword', 'successTitle', 'Password updated!'),
  ('resetPassword.successDesc', 'resetPassword', 'successDesc', 'Your password has been changed successfully.'),
  ('auth.signInNow', 'auth', 'signInNow', 'Sign in now'),
  ('billing.colInvoice', 'billing', 'colInvoice', 'Invoice'),
  ('billing.colDate', 'billing', 'colDate', 'Date'),
  ('billing.colAmount', 'billing', 'colAmount', 'Amount'),
  ('billing.colDownload', 'billing', 'colDownload', 'Download'),
  ('marketplace.google-analytics.name', 'marketplace', 'google-analytics.name', 'Google Analytics'),
  ('marketplace.google-analytics.description', 'marketplace', 'google-analytics.description', 'Track customer journeys, conversion funnels, and AI agent performance in Google Analytics 4.'),
  ('widgetSettings.previewHint', 'widgetSettings', 'previewHint', 'Save settings, then click Refresh to preview changes'),
  ('widgetSettings.configSummary', 'widgetSettings', 'configSummary', 'Configuration'),
  ('widgetSettings.position', 'widgetSettings', 'position', 'Position'),
  ('widgetSettings.position.bottomRight', 'widgetSettings', 'position.bottomRight', '↘ Bottom Right'),
  ('widgetSettings.position.bottomLeft', 'widgetSettings', 'position.bottomLeft', '↙ Bottom Left'),
  ('widgetSettings.autoOpen', 'widgetSettings', 'autoOpen', 'Auto-open'),
  ('widgetSettings.autoOpenAfter', 'widgetSettings', 'autoOpenAfter', 'After {{sec}}s'),
  ('widgetSettings.aiAgent', 'widgetSettings', 'aiAgent', 'AI Agent'),
  ('widgetSettings.botIcon', 'widgetSettings', 'botIcon', 'Bot Icon'),
  ('widgetSettings.botIconCustom', 'widgetSettings', 'botIconCustom', 'Custom'),
  ('widgetSettings.botIconDefault', 'widgetSettings', 'botIconDefault', 'Default emoji')

  ON CONFLICT (key) DO NOTHING;

  
  -- ─── DYNAMIC LANDING / LEGAL PAGE KEYS ──────────────────────
  INSERT INTO public.translation_keys (key, category, description, default_value) VALUES
    ('landing.privacy.section.1.title', 'landing', 'privacy.section.1.title', '1. Information We Collect'),
  ('landing.privacy.section.1.content', 'landing', 'privacy.section.1.content', 'We collect information you provide directly to us, such as when you create an account (name, email, password), set up your restaurant profile (restaurant name, address, cuisine type, phone number), upload menus and knowledge base documents, and contact our support team. We also collect usage data automatically, including log data, device information, IP addresses, pages visited, and features used. Payment information is processed by our third-party payment processor and we do not store full card details.'),
  ('landing.privacy.section.2.title', 'landing', 'privacy.section.2.title', '2. Customer Data (Your Restaurant''s Data)'),
  ('landing.privacy.section.2.content', 'landing', 'privacy.section.2.content', 'When your AI agent interacts with your customers, we process that conversation data on your behalf. This "Customer Data" — including customer names, phone numbers, order details, and conversation transcripts — belongs to you. We act as a data processor, not a data controller, for Customer Data. We process it only to provide the Service and do not use it for our own purposes, including training our AI models, without your explicit consent.'),
  ('landing.privacy.section.3.title', 'landing', 'privacy.section.3.title', '3. How We Use Your Information'),
  ('landing.privacy.section.3.content', 'landing', 'privacy.section.3.content', 'We use the information we collect to: provide, maintain, and improve the Service; process transactions and send related information; send technical notices, updates, security alerts, and support messages; respond to comments and questions; monitor and analyze usage patterns to improve the Service; detect and prevent fraud and abuse; and comply with legal obligations.'),
  ('landing.privacy.section.4.title', 'landing', 'privacy.section.4.title', '4. Information Sharing'),
  ('landing.privacy.section.4.content', 'landing', 'privacy.section.4.content', 'We do not sell, trade, or rent your personal information to third parties for marketing purposes. We may share information with: service providers who assist in our operations (hosting, payment processing, analytics) under confidentiality agreements; business partners with your consent; law enforcement when required by law; and in connection with a merger, acquisition, or sale of assets (with notice to you).'),
  ('landing.privacy.section.5.title', 'landing', 'privacy.section.5.title', '5. Data Retention'),
  ('landing.privacy.section.5.content', 'landing', 'privacy.section.5.content', 'We retain your account data for as long as your account is active or as needed to provide the Service. Conversation transcripts are retained for 90 days by default; you can configure this in your account settings. Call recordings (if enabled) are retained for 30 days unless you specify otherwise. Upon account cancellation, we delete your data within 30 days. You can request deletion at any time.'),
  ('landing.privacy.section.6.title', 'landing', 'privacy.section.6.title', '6. Security'),
  ('landing.privacy.section.6.content', 'landing', 'privacy.section.6.content', 'We implement industry-standard security measures including TLS 1.3 encryption for data in transit, AES-256 encryption for data at rest, regular security audits, and role-based access controls. We are SOC 2 Type II certified. However, no method of transmission over the Internet is 100% secure, and we cannot guarantee absolute security.'),
  ('landing.privacy.section.7.title', 'landing', 'privacy.section.7.title', '7. Your Rights'),
  ('landing.privacy.section.7.content', 'landing', 'privacy.section.7.content', 'Depending on your location, you may have rights to: access the personal information we hold about you; correct inaccurate data; request deletion of your data; restrict or object to processing; data portability; and withdraw consent. To exercise these rights, contact us at {support_email}. We will respond within 30 days.'),
  ('landing.privacy.section.8.title', 'landing', 'privacy.section.8.title', '8. GDPR Compliance'),
  ('landing.privacy.section.8.content', 'landing', 'privacy.section.8.content', 'For users in the European Economic Area (EEA), we process your data under the following legal bases: contract performance (to provide the Service you signed up for), legitimate interests (to improve the Service and prevent fraud), consent (for marketing communications), and legal obligation. You have the right to lodge a complaint with your local data protection authority.'),
  ('landing.privacy.section.9.title', 'landing', 'privacy.section.9.title', '9. Cookies'),
  ('landing.privacy.section.9.content', 'landing', 'privacy.section.9.content', 'We use cookies and similar tracking technologies. For detailed information, please see our Cookie Policy. You can control cookie settings through your browser or our cookie consent tool.'),
  ('landing.privacy.section.10.title', 'landing', 'privacy.section.10.title', '10. Children''s Privacy'),
  ('landing.privacy.section.10.content', 'landing', 'privacy.section.10.content', 'The Service is not directed to children under 16. We do not knowingly collect personal information from children under 16. If we learn that we have collected such information, we will delete it promptly.'),
  ('landing.privacy.section.11.title', 'landing', 'privacy.section.11.title', '11. International Transfers'),
  ('landing.privacy.section.11.content', 'landing', 'privacy.section.11.content', 'Your information may be transferred to and processed in countries other than your own. We ensure appropriate safeguards are in place for such transfers, including Standard Contractual Clauses where required.'),
  ('landing.privacy.section.12.title', 'landing', 'privacy.section.12.title', '12. Changes to This Policy'),
  ('landing.privacy.section.12.content', 'landing', 'privacy.section.12.content', 'We may update this Privacy Policy from time to time. We will notify you of material changes by email or through the Service at least 30 days before they take effect. Continued use of the Service constitutes acceptance of the updated policy.'),
  ('landing.privacy.section.13.title', 'landing', 'privacy.section.13.title', '13. Contact Us'),
  ('landing.privacy.section.13.content', 'landing', 'privacy.section.13.content', 'If you have questions about this Privacy Policy or our privacy practices, contact our Data Protection Officer at {support_email}. For requests related to your personal data, please use the privacy request form in your account settings.'),
  ('landing.terms.section.1.title', 'landing', 'terms.section.1.title', '1. Acceptance of Terms'),
  ('landing.terms.section.1.content', 'landing', 'terms.section.1.content', 'By accessing or using RestroAgent ("the Service"), you agree to be bound by these Terms of Service ("Terms"). If you do not agree to these Terms, you may not access or use the Service. These Terms apply to all visitors, users, and others who access the Service.'),
  ('landing.terms.section.2.title', 'landing', 'terms.section.2.title', '2. Description of Service'),
  ('landing.terms.section.2.content', 'landing', 'terms.section.2.content', 'RestroAgent provides an AI-powered platform for restaurant management, including voice and chat order-taking agents, table booking management, customer communication tools, analytics, and related services. Features available to you depend on your subscription plan.'),
  ('landing.terms.section.3.title', 'landing', 'terms.section.3.title', '3. Account Registration'),
  ('landing.terms.section.3.content', 'landing', 'terms.section.3.content', 'To use the Service, you must create an account. You agree to provide accurate, current, and complete information and to keep this information updated. You are responsible for maintaining the confidentiality of your account credentials and for all activities that occur under your account. You must notify us immediately of any unauthorized use of your account.'),
  ('landing.terms.section.4.title', 'landing', 'terms.section.4.title', '4. Subscription Plans and Billing'),
  ('landing.terms.section.4.content', 'landing', 'terms.section.4.content', 'RestroAgent offers paid subscription plans billed monthly or annually. By subscribing, you authorize us to charge your payment method on a recurring basis. All fees are non-refundable except as stated in our Refund Policy. We reserve the right to change pricing with 30 days'' notice. Downgrading your plan may result in loss of features or data.'),
  ('landing.terms.section.5.title', 'landing', 'terms.section.5.title', '5. Free Trial'),
  ('landing.terms.section.5.content', 'landing', 'terms.section.5.content', 'We offer a 14-day free trial for new accounts. No credit card is required to start a trial. At the end of the trial period, you must subscribe to a paid plan to continue using the Service. We may modify or discontinue the free trial at any time.'),
  ('landing.terms.section.6.title', 'landing', 'terms.section.6.title', '6. Acceptable Use'),
  ('landing.terms.section.6.content', 'landing', 'terms.section.6.content', 'You agree not to use the Service to: (a) violate any applicable law or regulation; (b) infringe the rights of any third party; (c) transmit harmful, offensive, or misleading content; (d) attempt to gain unauthorized access to any part of the Service; (e) use the Service for any competitive intelligence or benchmarking purposes; or (f) reverse-engineer or attempt to extract the source code of the Service.'),
  ('landing.terms.section.7.title', 'landing', 'terms.section.7.title', '7. Data and Privacy'),
  ('landing.terms.section.7.content', 'landing', 'terms.section.7.content', 'Your use of the Service is also governed by our Privacy Policy. You retain ownership of all data you upload or generate through the Service ("Customer Data"). You grant us a limited license to process Customer Data solely to provide the Service. We do not sell or share Customer Data with third parties for marketing purposes.'),
  ('landing.terms.section.8.title', 'landing', 'terms.section.8.title', '8. Intellectual Property'),
  ('landing.terms.section.8.content', 'landing', 'terms.section.8.content', 'The Service, including its software, design, text, graphics, and other content, is owned by RestroAgent and protected by intellectual property laws. You may not copy, modify, distribute, sell, or lease any part of the Service without our written permission.'),
  ('landing.terms.section.9.title', 'landing', 'terms.section.9.title', '9. Disclaimers'),
  ('landing.terms.section.9.content', 'landing', 'terms.section.9.content', 'THE SERVICE IS PROVIDED "AS IS" WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED. WE DO NOT WARRANT THAT THE SERVICE WILL BE UNINTERRUPTED, ERROR-FREE, OR FREE OF VIRUSES. AI-GENERATED RESPONSES MAY CONTAIN ERRORS; YOU REMAIN RESPONSIBLE FOR VERIFYING ORDER ACCURACY.'),
  ('landing.terms.section.10.title', 'landing', 'terms.section.10.title', '10. Limitation of Liability'),
  ('landing.terms.section.10.content', 'landing', 'terms.section.10.content', 'TO THE FULLEST EXTENT PERMITTED BY LAW, RESTROAGENT SHALL NOT BE LIABLE FOR ANY INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL, OR PUNITIVE DAMAGES ARISING FROM YOUR USE OF THE SERVICE. OUR TOTAL LIABILITY SHALL NOT EXCEED THE AMOUNT YOU PAID US IN THE TWELVE MONTHS PRECEDING THE CLAIM.'),
  ('landing.terms.section.11.title', 'landing', 'terms.section.11.title', '11. Termination'),
  ('landing.terms.section.11.content', 'landing', 'terms.section.11.content', 'You may cancel your account at any time from your account settings. We may suspend or terminate your account if you violate these Terms. Upon termination, your right to use the Service ceases immediately and we will delete your data within 30 days in accordance with our Privacy Policy.'),
  ('landing.terms.section.12.title', 'landing', 'terms.section.12.title', '12. Changes to Terms'),
  ('landing.terms.section.12.content', 'landing', 'terms.section.12.content', 'We may update these Terms from time to time. We will notify you of material changes by email or through the Service. Continued use of the Service after the effective date of changes constitutes acceptance of the new Terms.'),
  ('landing.terms.section.13.title', 'landing', 'terms.section.13.title', '13. Governing Law'),
  ('landing.terms.section.13.content', 'landing', 'terms.section.13.content', 'These Terms are governed by and construed in accordance with applicable law. Any disputes shall be resolved through binding arbitration, except for disputes involving intellectual property rights which may be brought in a court of competent jurisdiction.'),
  ('landing.terms.section.14.title', 'landing', 'terms.section.14.title', '14. Contact'),
  ('landing.terms.section.14.content', 'landing', 'terms.section.14.content', 'If you have questions about these Terms, contact us at {support_email}.'),
  ('landing.refund.section.1.title', 'landing', 'refund.section.1.title', '1. Money-Back Guarantee'),
  ('landing.refund.section.1.content', 'landing', 'refund.section.1.content', 'RestroAgent offers a 30-day money-back guarantee on all paid subscription plans. If you are not satisfied with the Service for any reason within the first 30 days of your paid subscription, contact us and we will issue a full refund — no questions asked. This guarantee applies to your first payment on a new paid plan.'),
  ('landing.refund.section.2.title', 'landing', 'refund.section.2.title', '2. Eligibility'),
  ('landing.refund.section.2.content', 'landing', 'refund.section.2.content', 'To be eligible for a refund under our money-back guarantee, you must: (a) be within 30 days of your first payment on the plan; (b) contact us at {support_email} with your account email and reason for the refund request; and (c) have complied with our Terms of Service during your subscription period.'),
  ('landing.refund.section.3.title', 'landing', 'refund.section.3.title', '3. Subscription Cancellations'),
  ('landing.refund.section.3.content', 'landing', 'refund.section.3.content', 'You may cancel your subscription at any time from your account settings under Billing. When you cancel: your subscription remains active until the end of the current billing period; you will not be charged again after the current period ends; you will not receive a prorated refund for the unused portion of the current billing period (except as covered by the 30-day guarantee).'),
  ('landing.refund.section.4.title', 'landing', 'refund.section.4.title', '4. Annual Plans'),
  ('landing.refund.section.4.content', 'landing', 'refund.section.4.content', 'If you subscribed to an annual plan and cancel within the first 30 days, you are eligible for a full refund of your annual payment under our money-back guarantee. After 30 days, annual subscriptions are non-refundable, but you may continue using the Service until the end of the annual period.'),
  ('landing.refund.section.5.title', 'landing', 'refund.section.5.title', '5. Plan Downgrades'),
  ('landing.refund.section.5.content', 'landing', 'refund.section.5.content', 'If you downgrade from a higher-tier plan to a lower-tier plan, the change will take effect at the start of your next billing cycle. There are no refunds or credits for the difference in price during the current billing period. Feature access will change at the start of the new billing cycle.'),
  ('landing.refund.section.6.title', 'landing', 'refund.section.6.title', '6. Non-Refundable Items'),
  ('landing.refund.section.6.content', 'landing', 'refund.section.6.content', 'The following are not eligible for refunds: setup fees (if applicable for custom enterprise plans); usage-based overage charges; add-on purchases beyond the standard subscription; payments made more than 30 days prior (except for documented service failures); and accounts suspended for Terms of Service violations.'),
  ('landing.refund.section.7.title', 'landing', 'refund.section.7.title', '7. Service Credits'),
  ('landing.refund.section.7.content', 'landing', 'refund.section.7.content', 'In cases of documented service outages or failures that exceed our published SLA thresholds, eligible customers may receive service credits applied to future billing cycles. Credits are calculated based on the duration and severity of the outage and are subject to our SLA terms. Service credits are not cash refunds.'),
  ('landing.refund.section.8.title', 'landing', 'refund.section.8.title', '8. How to Request a Refund'),
  ('landing.refund.section.8.content', 'landing', 'refund.section.8.content', 'To request a refund, email {support_email} with: your account email address, the date of the charge you wish to refund, and a brief reason for your request. We will process eligible refunds within 5-10 business days. Refunds are returned to the original payment method.'),
  ('landing.refund.section.9.title', 'landing', 'refund.section.9.title', '9. Changes to This Policy'),
  ('landing.refund.section.9.content', 'landing', 'refund.section.9.content', 'We reserve the right to modify this Refund Policy at any time. Changes will be posted on this page with an updated "last updated" date. For existing subscribers, the policy in effect at the time of your most recent payment will apply to that payment.'),
  ('landing.refund.section.10.title', 'landing', 'refund.section.10.title', '10. Contact'),
  ('landing.refund.section.10.content', 'landing', 'refund.section.10.content', 'For refund requests and billing questions, contact us at {support_email}. Our billing team responds within one business day.'),
  ('landing.cookie.section.1.title', 'landing', 'cookie.section.1.title', 'What Are Cookies?'),
  ('landing.cookie.section.1.content', 'landing', 'cookie.section.1.content', 'Cookies are small text files that are placed on your device when you visit a website. They are widely used to make websites work efficiently and to provide information to website owners. Cookies allow us to remember your preferences, understand how you use our Service, and improve your experience.'),
  ('landing.cookie.section.2.title', 'landing', 'cookie.section.2.title', 'How We Use Cookies'),
  ('landing.cookie.section.2.content', 'landing', 'cookie.section.2.content', 'RestroAgent uses cookies primarily to maintain your login session and remember your preferences (such as dark mode). We use minimal tracking on our core platform, focusing only on what is strictly necessary to deliver a reliable service. Our public marketing website uses additional analytics cookies to understand how visitors find and use our site.'),
  ('landing.cookie.section.3.title', 'landing', 'cookie.section.3.title', 'Third-Party Cookies'),
  ('landing.cookie.section.3.content', 'landing', 'cookie.section.3.content', 'Some cookies are placed by third-party services that appear on our pages. These include our payment processor (Stripe), error monitoring service, and where applicable, our analytics provider. These third parties have their own privacy policies and cookie practices.'),
  ('landing.cookie.section.4.title', 'landing', 'cookie.section.4.title', 'Cookie Duration'),
  ('landing.cookie.section.4.content', 'landing', 'cookie.section.4.content', 'Session cookies are deleted when you close your browser. Persistent cookies remain on your device for a set period: authentication cookies last up to 7 days, theme preference cookies last up to 1 year, and analytics cookies typically last up to 2 years.'),
  ('landing.cookie.section.5.title', 'landing', 'cookie.section.5.title', 'Managing Cookies'),
  ('landing.cookie.section.5.content', 'landing', 'cookie.section.5.content', 'You can control and/or delete cookies as you wish. You can delete all cookies that are already on your computer and you can set most browsers to prevent them from being placed. However, if you do this, you may have to manually adjust some preferences every time you visit and some services and functionalities may not work.'),
  ('landing.cookie.section.6.title', 'landing', 'cookie.section.6.title', 'Changes to This Policy'),
  ('landing.cookie.section.6.content', 'landing', 'cookie.section.6.content', 'We may update this Cookie Policy from time to time to reflect changes in the cookies we use or for other operational, legal, or regulatory reasons. Please revisit this policy regularly to stay informed about our use of cookies.'),
  ('landing.cookie.type.0.name', 'landing', 'cookie.type.0.name', 'Strictly Necessary'),
  ('landing.cookie.type.0.badge', 'landing', 'cookie.type.0.badge', 'Always Active'),
  ('landing.cookie.type.0.desc', 'landing', 'cookie.type.0.desc', 'These cookies are essential for the website to function and cannot be switched off.'),
  ('landing.cookie.type.1.name', 'landing', 'cookie.type.1.name', 'Performance & Analytics'),
  ('landing.cookie.type.1.badge', 'landing', 'cookie.type.1.badge', 'Optional'),
  ('landing.cookie.type.1.desc', 'landing', 'cookie.type.1.desc', 'These cookies allow us to count visits and understand how visitors interact with the Service.'),
  ('landing.cookie.type.2.name', 'landing', 'cookie.type.2.name', 'Functional'),
  ('landing.cookie.type.2.badge', 'landing', 'cookie.type.2.badge', 'Optional'),
  ('landing.cookie.type.2.desc', 'landing', 'cookie.type.2.desc', 'These cookies enable enhanced functionality and personalization, such as remembering your theme preference.'),
  ('landing.cookie.type.3.name', 'landing', 'cookie.type.3.name', 'Marketing'),
  ('landing.cookie.type.3.badge', 'landing', 'cookie.type.3.badge', 'Optional'),
  ('landing.cookie.type.3.desc', 'landing', 'cookie.type.3.desc', 'These cookies may be set by our advertising partners to build a profile of your interests.'),
  ('landing.about.timeline.2021.title', 'landing', 'about.timeline.2021.title', 'The problem'),
  ('landing.about.timeline.2021.desc', 'landing', 'about.timeline.2021.desc', 'Arjun and Lena watch a family-run restaurant lose 40% of phone orders during Friday dinner rush. The idea is born.'),
  ('landing.about.timeline.2022.title', 'landing', 'about.timeline.2022.title', 'First prototype'),
  ('landing.about.timeline.2022.desc', 'landing', 'about.timeline.2022.desc', 'Built a voice AI that could take pizza orders. Tested with 3 local restaurants in Berlin. 94% order accuracy from day one.'),
  ('landing.about.timeline.2023.title', 'landing', 'about.timeline.2023.title', 'Seed funding'),
  ('landing.about.timeline.2023.desc', 'landing', 'about.timeline.2023.desc', 'Raised $4.2M seed round. Expanded to 200 restaurants across Europe. Launched WhatsApp and SMS chat agents.'),
  ('landing.about.timeline.2024.title', 'landing', 'about.timeline.2024.title', 'Global expansion'),
  ('landing.about.timeline.2024.desc', 'landing', 'about.timeline.2024.desc', 'Crossed 1,000 restaurant milestone. Launched in North America and Southeast Asia. Added 15 language support.'),
  ('landing.about.timeline.2025.title', 'landing', 'about.timeline.2025.title', 'Series A'),
  ('landing.about.timeline.2025.desc', 'landing', 'about.timeline.2025.desc', 'Raised $18M Series A. Launched multi-branch management, advanced analytics, and enterprise tier.'),
  ('landing.about.timeline.2026.title', 'landing', 'about.timeline.2026.title', 'Today'),
  ('landing.about.timeline.2026.desc', 'landing', 'about.timeline.2026.desc', '2,400+ restaurants. 18M+ orders processed. Building the future of restaurant-customer communication.'),
  ('landing.about.values.0.title', 'landing', 'about.values.0.title', 'Accuracy over speed'),
  ('landing.about.values.0.desc', 'landing', 'about.values.0.desc', 'We''d rather take an extra second to get the order right than rush and get it wrong. Every missed item costs a restaurant real money.'),
  ('landing.about.values.1.title', 'landing', 'about.values.1.title', 'Restaurants first'),
  ('landing.about.values.1.desc', 'landing', 'about.values.1.desc', 'Every feature we build starts with a real restaurant problem. We talk to operators weekly, not quarterly.'),
  ('landing.about.values.2.title', 'landing', 'about.values.2.title', 'Language is not a barrier'),
  ('landing.about.values.2.desc', 'landing', 'about.values.2.desc', 'A restaurant in Tokyo and one in São Paulo deserve the same quality AI. We invest heavily in multilingual accuracy.'),
  ('landing.about.values.3.title', 'landing', 'about.values.3.title', 'Privacy by design'),
  ('landing.about.values.3.desc', 'landing', 'about.values.3.desc', 'Customer data belongs to the restaurant, not us. We never sell data, never train on customer conversations without consent.'),
  ('landing.faq.category.GettingStarted', 'landing', 'faq.category.GettingStarted', 'Getting Started'),
  ('landing.faq.category.AIAccuracy', 'landing', 'faq.category.AIAccuracy', 'AI & Accuracy'),
  ('landing.faq.category.Integrations', 'landing', 'faq.category.Integrations', 'Integrations'),
  ('landing.faq.category.PricingBilling', 'landing', 'faq.category.PricingBilling', 'Pricing & Billing'),
  ('landing.faq.category.SecurityPrivacy', 'landing', 'faq.category.SecurityPrivacy', 'Security & Privacy'),
  ('landing.faq.items.GettingStarted.0.q', 'landing', 'faq.items.GettingStarted.0.q', 'How quickly can I get RestroAgent running?'),
  ('landing.faq.items.GettingStarted.0.a', 'landing', 'faq.items.GettingStarted.0.a', 'Most restaurants are fully live within 2 hours. The process: upload your menu (or connect your POS), configure your AI personality, and forward your phone number. Our onboarding team guides you through every step.'),
  ('landing.faq.items.GettingStarted.1.q', 'landing', 'faq.items.GettingStarted.1.q', 'Do I need any technical knowledge?'),
  ('landing.faq.items.GettingStarted.1.a', 'landing', 'faq.items.GettingStarted.1.a', 'None at all. If you can use a smartphone, you can set up RestroAgent. We''ve designed the entire process to be handled by restaurant owners and managers, not IT teams.'),
  ('landing.faq.items.GettingStarted.2.q', 'landing', 'faq.items.GettingStarted.2.q', 'What do I need to get started?'),
  ('landing.faq.items.GettingStarted.2.a', 'landing', 'faq.items.GettingStarted.2.a', 'Just your menu (PDF, image, or POS export), your phone number, and 2 hours. We handle everything else.'),
  ('landing.faq.items.GettingStarted.3.q', 'landing', 'faq.items.GettingStarted.3.q', 'Is there a free trial?'),
  ('landing.faq.items.GettingStarted.3.a', 'landing', 'faq.items.GettingStarted.3.a', 'Yes — 14 days, full access to all features on your chosen plan. No credit card required to start.'),
  ('landing.faq.items.AIAccuracy.0.q', 'landing', 'faq.items.AIAccuracy.0.q', 'How accurate is the AI at taking orders?'),
  ('landing.faq.items.AIAccuracy.0.a', 'landing', 'faq.items.AIAccuracy.0.a', 'Our average order accuracy is 98.7% across all restaurants. The AI is trained specifically on restaurant ordering patterns and asks clarifying questions when unsure rather than guessing.'),
  ('landing.faq.items.AIAccuracy.1.q', 'landing', 'faq.items.AIAccuracy.1.q', 'Can the AI handle complex orders with modifications?'),
  ('landing.faq.items.AIAccuracy.1.a', 'landing', 'faq.items.AIAccuracy.1.a', 'Yes. The AI handles substitutions, allergies, cooking preferences, combo modifications, and multi-item orders. It''s been trained on millions of real restaurant conversations.'),
  ('landing.faq.items.AIAccuracy.2.q', 'landing', 'faq.items.AIAccuracy.2.q', 'What happens when the AI can''t handle a request?'),
  ('landing.faq.items.AIAccuracy.2.a', 'landing', 'faq.items.AIAccuracy.2.a', 'The AI escalates to a human staff member via real-time alert on your dashboard and mobile app. You set the escalation rules — we never leave a customer without a response.'),
  ('landing.faq.items.AIAccuracy.3.q', 'landing', 'faq.items.AIAccuracy.3.q', 'Does the AI learn from my restaurant over time?'),
  ('landing.faq.items.AIAccuracy.3.a', 'landing', 'faq.items.AIAccuracy.3.a', 'Yes. The AI improves based on corrections you make and feedback from your customers. After 30 days, most restaurants see a 15-20% improvement in accuracy.'),
  ('landing.faq.items.Integrations.0.q', 'landing', 'faq.items.Integrations.0.q', 'Which POS systems do you integrate with?'),
  ('landing.faq.items.Integrations.0.a', 'landing', 'faq.items.Integrations.0.a', 'We integrate with 50+ POS systems including Square, Toast, Clover, Lightspeed, Revel, TouchBistro, and more. If yours isn''t listed, contact us — we can usually build the integration within 2 weeks.'),
  ('landing.faq.items.Integrations.1.q', 'landing', 'faq.items.Integrations.1.q', 'Can I connect to delivery platforms?'),
  ('landing.faq.items.Integrations.1.a', 'landing', 'faq.items.Integrations.1.a', 'Yes. We integrate with Uber Eats, DoorDash, Grubhub, Deliveroo, and more. Orders from all channels flow into a single dashboard.'),
  ('landing.faq.items.Integrations.2.q', 'landing', 'faq.items.Integrations.2.q', 'What payment processors do you support?'),
  ('landing.faq.items.Integrations.2.a', 'landing', 'faq.items.Integrations.2.a', 'Stripe, Square, PayPal, Braintree, and most major processors. Payment collection happens through your existing processor — we don''t touch your money.'),
  ('landing.faq.items.Integrations.3.q', 'landing', 'faq.items.Integrations.3.q', 'Can I use my existing phone number?'),
  ('landing.faq.items.Integrations.3.a', 'landing', 'faq.items.Integrations.3.a', 'Yes. You simply forward your existing number to RestroAgent. Customers call the same number they always have.'),
  ('landing.faq.items.PricingBilling.0.q', 'landing', 'faq.items.PricingBilling.0.q', 'Can I change my plan at any time?'),
  ('landing.faq.items.PricingBilling.0.a', 'landing', 'faq.items.PricingBilling.0.a', 'Yes. Upgrades take effect immediately; downgrades apply at the next billing cycle. There are no long-term contracts on monthly plans.'),
  ('landing.faq.items.PricingBilling.1.q', 'landing', 'faq.items.PricingBilling.1.q', 'What counts as a "conversation"?'),
  ('landing.faq.items.PricingBilling.1.a', 'landing', 'faq.items.PricingBilling.1.a', 'A conversation is a single continuous interaction with one customer — whether it''s a 2-message order or a 20-message booking with modifications. Starter plan includes 500/month; Growth and Enterprise are unlimited.'),
  ('landing.faq.items.PricingBilling.2.q', 'landing', 'faq.items.PricingBilling.2.q', 'Do you offer discounts for multiple locations?'),
  ('landing.faq.items.PricingBilling.2.a', 'landing', 'faq.items.PricingBilling.2.a', 'Yes. Enterprise plan covers unlimited locations at a flat rate. For 3-10 locations, contact us for a custom Growth plan quote.'),
  ('landing.faq.items.PricingBilling.3.q', 'landing', 'faq.items.PricingBilling.3.q', 'Is there a setup fee?'),
  ('landing.faq.items.PricingBilling.3.a', 'landing', 'faq.items.PricingBilling.3.a', 'No setup fees on any plan. You pay only the monthly or annual subscription.'),
  ('landing.faq.items.SecurityPrivacy.0.q', 'landing', 'faq.items.SecurityPrivacy.0.q', 'Is customer data secure?'),
  ('landing.faq.items.SecurityPrivacy.0.a', 'landing', 'faq.items.SecurityPrivacy.0.a', 'Yes. All data is encrypted in transit (TLS 1.3) and at rest (AES-256). We''re GDPR compliant and SOC 2 Type II certified.'),
  ('landing.faq.items.SecurityPrivacy.1.q', 'landing', 'faq.items.SecurityPrivacy.1.q', 'Do you sell customer data?'),
  ('landing.faq.items.SecurityPrivacy.1.a', 'landing', 'faq.items.SecurityPrivacy.1.a', 'Never. Customer data belongs to you, the restaurant. We never sell, share, or use your customer data for any purpose other than providing the service.'),
  ('landing.faq.items.SecurityPrivacy.2.q', 'landing', 'faq.items.SecurityPrivacy.2.q', 'Are conversations recorded?'),
  ('landing.faq.items.SecurityPrivacy.2.a', 'landing', 'faq.items.SecurityPrivacy.2.a', 'Voice calls are transcribed (not stored as audio by default). You can enable call recording for quality assurance. All recordings are stored in your account and can be deleted at any time.'),
  ('landing.faq.items.SecurityPrivacy.3.q', 'landing', 'faq.items.SecurityPrivacy.3.q', 'Can I delete my data?'),
  ('landing.faq.items.SecurityPrivacy.3.a', 'landing', 'faq.items.SecurityPrivacy.3.a', 'Yes. You can export or delete all your data at any time from your account settings. Upon cancellation, data is deleted within 30 days.')

  ON CONFLICT (key) DO NOTHING;

  
  -- ─── ADDITIONAL KEYS SWEEP ──────────────────────────────────
  INSERT INTO public.translation_keys (key, category, description, default_value) VALUES
    ('onboarding.phonePlaceholder', 'onboarding', 'phonePlaceholder', '+1 (555) 000-0000'),
  ('onboarding.websitePlaceholder', 'onboarding', 'websitePlaceholder', 'www.yourrestaurant.com'),
  ('onboarding.agentNamePlaceholder', 'onboarding', 'agentNamePlaceholder', 'Alex'),
  ('knowledgeBase.urlPlaceholder', 'knowledgeBase', 'urlPlaceholder', 'https://yourrestaurant.com/page'),
  ('menuItem.imageUrlPlaceholder', 'menuItem', 'imageUrlPlaceholder', 'https://images.unsplash.com/…'),
  ('webhooks.urlPlaceholder', 'webhooks', 'urlPlaceholder', 'https://your-app.com/webhooks'),
  ('blog.heroImagePlaceholder', 'blog', 'heroImagePlaceholder', 'https://example.com/hero-image.jpg'),
  ('admin.branding.imageUrlPlaceholder', 'admin', 'branding.imageUrlPlaceholder', 'https://example.com/image.png'),
  ('admin.branding.siteTitlePlaceholder', 'admin', 'branding.siteTitlePlaceholder', 'RestroAgent'),
  ('admin.branding.taglinePlaceholder', 'admin', 'branding.taglinePlaceholder', 'AI-powered restaurant management, simplified.'),
  ('telephone.sipServerPlaceholder', 'telephone', 'sipServerPlaceholder', 'sip.provider.com'),
  ('telephone.sipUsernamePlaceholder', 'telephone', 'sipUsernamePlaceholder', 'user123'),
  ('telephone.sipProxyPlaceholder', 'telephone', 'sipProxyPlaceholder', 'proxy.provider.com:5060'),
  ('telephone.accountSidPlaceholder', 'telephone', 'accountSidPlaceholder', 'ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx')

  ON CONFLICT (key) DO NOTHING;

  -- ─── MISSING KEYS SWEEP — ALL UNREGISTERED t() KEYS ──────────────────
  INSERT INTO public.translation_keys (key, category, description, default_value) VALUES
    ('admin.activeRestaurants', 'admin', 'activeRestaurants', 'Active Restaurants'),
    ('admin.platformAnalytics.chartAvgDuration', 'admin', 'platformAnalytics chartAvgDuration', 'Avg Duration (s)'),
    ('admin.platformAnalytics.chartConversations', 'admin', 'platformAnalytics chartConversations', 'Conversations'),
    ('admin.platformAnalytics.chartCount', 'admin', 'platformAnalytics chartCount', 'Count'),
    ('admin.platformAnalytics.pageDesc', 'admin', 'platformAnalytics pageDesc', 'Usage trends and performance'),
    ('admin.platformAnalytics.pageTitle', 'admin', 'platformAnalytics pageTitle', 'Platform Analytics'),
    ('admin.restaurants.detailSubtitle', 'admin', 'restaurants detailSubtitle', 'Full restaurant profile and management'),
    ('admin.restaurants.detailTitle', 'admin', 'restaurants detailTitle', 'Restaurant Detail'),
    ('admin.restaurants.trialGranted', 'admin', 'restaurants trialGranted', 'Trial granted for {{days}} days'),
    ('aiAgentConfig.placeholders.closingScript', 'aiAgentConfig', 'placeholders closingScript', 'Thank you for choosing us...'),
    ('aiAgentConfig.placeholders.description', 'aiAgentConfig', 'placeholders description', 'Short description of this agent''s purpose'),
    ('aiAgentConfig.placeholders.greetingScript', 'aiAgentConfig', 'placeholders greetingScript', 'Hello! Welcome to our restaurant...'),
    ('aiAgentConfig.placeholders.systemPrompt', 'aiAgentConfig', 'placeholders systemPrompt', 'You are a helpful restaurant assistant. Always be polite and focus on menu recommendations...'),
    ('aiAgentConfig.preview.sampleAgentMsg', 'aiAgentConfig', 'preview sampleAgentMsg', 'Sure! I''d be happy to help. What would you like to order today?'),
    ('aiAgentConfig.vadSubtitle', 'aiAgentConfig', 'vadSubtitle', 'Controls how the AI detects when you''ve finished speaking. Lower threshold = more sensitive.'),
    ('analytics.totalOrders', 'analytics', 'totalOrders', 'Total Orders'),
    ('auth.createFree', 'auth', 'createFree', 'Create one free'),
    ('auth.emailInvalid', 'auth', 'emailInvalid', 'Please enter a valid email address'),
    ('auth.emailPlaceholder', 'auth', 'emailPlaceholder', 'you@restaurant.com'),
    ('auth.emailRequired', 'auth', 'emailRequired', 'Email address is required'),
    ('auth.forgotPassword', 'auth', 'forgotPassword', 'Forgot password?'),
    ('auth.noAccount', 'auth', 'noAccount', 'Don''t have an account?'),
    ('auth.ownerName', 'auth', 'ownerName', 'Owner / Manager Name'),
    ('auth.passwordRequired', 'auth', 'passwordRequired', 'Password is required'),
    ('auth.restaurantName', 'auth', 'restaurantName', 'Restaurant Name'),
    ('auth.signIn', 'auth', 'signIn', 'Sign in'),
    ('auth.signingIn', 'auth', 'signingIn', 'Signing in...'),
    ('billing.addCard', 'billing', 'addCard', 'Add Card'),
    ('billing.addPlan', 'billing', 'addPlan', 'Add Plan'),
    ('billing.cancel', 'billing', 'cancel', 'Cancel'),
    ('billing.choosePlan', 'billing', 'choosePlan', 'Choose a Plan'),
    ('billing.currentPlan', 'billing', 'currentPlan', 'Current Plan'),
    ('billing.enterprise', 'billing', 'enterprise', 'Enterprise'),
    ('billing.monthly', 'billing', 'monthly', 'Monthly'),
    ('billing.planDescription', 'billing', 'planDescription', 'Configure subscription plan details and features'),
    ('billing.planNamePlaceholder', 'billing', 'planNamePlaceholder', 'e.g. Starter, Growth, Enterprise'),
    ('billing.starter', 'billing', 'starter', 'Starter'),
    ('billing.title', 'billing', 'title', 'Billing & Subscription'),
    ('billing.updateCard', 'billing', 'updateCard', 'Update Card'),
    ('billing.upgrade', 'billing', 'upgrade', 'Upgrade'),
    ('blog.placeholders.tealCallout', 'blog', 'placeholders tealCallout', 'What you''ll need | Item 1\nItem 2\nItem 3'),
    ('branchManagement.manageSubtitle', 'branchManagement', 'manageSubtitle', 'Manage branch details and operating hours'),
    ('branchManagement.placeholderAddress', 'branchManagement', 'placeholderAddress', '123 Main Street, City, State, ZIP'),
    ('branchManagement.placeholderBranchName', 'branchManagement', 'placeholderBranchName', 'e.g. The Rustic Fork — Sunset'),
    ('branchManagement.summaryDaysValue', 'branchManagement', 'summaryDaysValue', '{{count}} days/week'),
    ('calls.exported', 'calls', 'exported', 'Exported {{count}} call logs'),
    ('changePassword.description', 'changePassword', 'description', 'Update your account password'),
    ('changePassword.subtitle', 'changePassword', 'subtitle', 'Secure your account with a strong password'),
    ('common.actions', 'common', 'actions', 'Actions'),
    ('common.active', 'common', 'active', 'Active'),
    ('common.address', 'common', 'address', 'Address'),
    ('common.all', 'common', 'all', 'All'),
    ('common.back', 'common', 'back', 'Back'),
    ('common.cancel', 'common', 'cancel', 'Cancel'),
    ('common.close', 'common', 'close', 'Close'),
    ('common.confirm', 'common', 'confirm', 'Confirm'),
    ('common.copy_tag', 'common', 'copy_tag', 'Copy'),
    ('common.date', 'common', 'date', 'Date'),
    ('common.delete', 'common', 'delete', 'Delete'),
    ('common.disabled', 'common', 'disabled', 'Disabled'),
    ('common.edit', 'common', 'edit', 'Edit'),
    ('common.email', 'common', 'email', 'Email'),
    ('common.enabled', 'common', 'enabled', 'Enabled'),
    ('common.inactive', 'common', 'inactive', 'Inactive'),
    ('common.loading', 'common', 'loading', 'Loading...'),
    ('common.name', 'common', 'name', 'Name'),
    ('common.next', 'common', 'next', 'Next'),
    ('common.no', 'common', 'no', 'No'),
    ('common.notes', 'common', 'notes', 'Notes'),
    ('common.paginationShowing', 'common', 'paginationShowing', 'Showing {{from}}–{{to}} of {{total}}'),
    ('common.phone', 'common', 'phone', 'Phone'),
    ('common.save', 'common', 'save', 'Save'),
    ('common.saving', 'common', 'saving', 'Saving...'),
    ('common.status', 'common', 'status', 'Status'),
    ('common.success', 'common', 'success', 'success'),
    ('common.time', 'common', 'time', 'Time'),
    ('common.total', 'common', 'total', 'total'),
    ('common.view', 'common', 'view', 'View'),
    ('common.yes', 'common', 'yes', 'Yes'),
    ('conversations.bulkAssigned', 'conversations', 'bulkAssigned', '{{count}} conversations assigned'),
    ('conversations.bulkDeleted', 'conversations', 'bulkDeleted', '{{count}} conversations deleted'),
    ('conversations.bulkEscalated', 'conversations', 'bulkEscalated', '{{count}} conversations escalated'),
    ('conversations.bulkResolved', 'conversations', 'bulkResolved', '{{count}} conversations resolved'),
    ('conversations.deleteTitle', 'conversations', 'deleteTitle', 'Delete Conversation'),
    ('conversations.exported', 'conversations', 'exported', 'Conversations exported'),
    ('conversations.liveChat', 'conversations', 'liveChat', 'Live Chat'),
    ('conversations.loadingConversation', 'conversations', 'loadingConversation', 'Loading conversation...'),
    ('conversations.notePlaceholder', 'conversations', 'notePlaceholder', 'Add a note about this conversation...'),
    ('conversations.takeoverMessage', 'conversations', 'takeoverMessage', 'You have taken over this conversation'),
    ('customers.addCustomer', 'customers', 'addCustomer', 'Add Customer'),
    ('customers.preferences', 'customers', 'preferences', 'Preferences'),
    ('customers.subtitle', 'customers', 'subtitle', 'Profiles, order history, and reservations'),
    ('dashboard.activeCount', 'dashboard', 'activeCount', '{{count}} active'),
    ('dashboard.aiOrdersWithPeriod', 'dashboard', 'aiOrdersWithPeriod', 'AI Orders — {{period}}'),
    ('dashboard.avgConfidenceWithPeriod', 'dashboard', 'avgConfidenceWithPeriod', 'Average confidence — {{period}}'),
    ('dashboard.bookingSubOther', 'dashboard', 'bookingSubOther', '{{confirmed}} confirmed'),
    ('dashboard.bookingSubToday', 'dashboard', 'bookingSubToday', '{{confirmed}} confirmed · {{tomorrow}} tomorrow'),
    ('dashboard.escalatedCount', 'dashboard', 'escalatedCount', '{{count}} Escalated'),
    ('dashboard.escalationCountLast24h', 'dashboard', 'escalationCountLast24h', '{{count}} escalations in last 24h'),
    ('dashboard.noFilteredConversations', 'dashboard', 'noFilteredConversations', 'No {{filter}} conversations'),
    ('dashboard.ordersCompletedWithPeriod', 'dashboard', 'ordersCompletedWithPeriod', 'Orders Completed — {{period}}'),
    ('dashboard.ordersSubValue', 'dashboard', 'ordersSubValue', '{{voice}} via voice · {{chat}} via chat'),
    ('dashboard.reservationsWithPeriod', 'dashboard', 'reservationsWithPeriod', 'Reservations — {{period}}'),
    ('dashboard.revenueViaAiWithPeriod', 'dashboard', 'revenueViaAiWithPeriod', 'Revenue via AI — {{period}}'),
    ('forgotPassword.subtitle', 'forgotPassword', 'subtitle', 'Enter the email address associated with your account and we''ll send you a reset link.'),
    ('help.descriptionPlaceholder', 'help', 'descriptionPlaceholder', 'Describe the issue in detail...'),
    ('help.replyPlaceholder', 'help', 'replyPlaceholder', 'Type your reply here...'),
    ('help.subjectPlaceholder', 'help', 'subjectPlaceholder', 'Brief description of the issue'),
    ('help.subtitle', 'help', 'subtitle', 'Browse articles, guides, and raise a support ticket'),
    ('help.supportTickets', 'help', 'supportTickets', 'Support Tickets'),
    ('help.ticketsDescription', 'help', 'ticketsDescription', 'View and manage your open support requests'),
    ('help.title', 'help', 'title', 'Help Center'),
    ('knowledgeBase.reindex.title', 'knowledgeBase', 'reindex.title', 'Re-index all knowledge base entries for semantic search'),
    ('knowledgeBase.subtitle', 'knowledgeBase', 'subtitle', 'Manage AI knowledge sources — documents, URLs, and Q&A pairs'),
    ('knowledgeBase.title', 'knowledgeBase', 'title', 'Knowledge Base'),
    ('landing.about.cta.subtitle', 'landing', 'about.cta.subtitle', 'Whether you''re a restaurant owner or a talented engineer — we''d love to hear from you.'),
    ('landing.about.hero.subtitle', 'landing', 'about.hero.subtitle', 'RestroAgent started when two engineers watched a great restaurant lose customers because no one could answer the phone. That shouldn''t happen in 2026.'),
    ('landing.blog.post1.excerpt', 'landing', 'blog.post1.excerpt', 'A single-location pizzeria in Munich was losing 30% of phone orders during Friday dinner rush. Here''s how they fixed it in one afternoon.'),
    ('landing.blog.post2.title', 'landing', 'blog.post2.title', 'The Real Cost of a Missed Phone Order (It''s More Than You Think)'),
    ('landing.blog.post3.excerpt', 'landing', 'blog.post3.excerpt', 'In cities like London, Toronto, and Singapore, 40% of restaurant customers prefer to order in their native language. Here''s how to serve them.'),
    ('landing.blog.post5.excerpt', 'landing', 'blog.post5.excerpt', 'A step-by-step guide to customizing your AI''s personality, tone, and responses to match your brand voice perfectly.'),
    ('landing.blog.post6.title', 'landing', 'blog.post6.title', 'Spice Garden''s Journey: From 1 to 8 Locations with One Dashboard'),
    ('landing.blog.post8.excerpt', 'landing', 'blog.post8.excerpt', 'Most restaurant booking flows have 3-5 unnecessary steps. Here''s how AI reduces abandonment by 60%.'),
    ('landing.blog.post.concerns.q1.a', 'landing', 'blog.post.concerns.q1.a', 'The AI is transparent about being an automated system when asked directly. However, most customers simply don''t ask — they just want their order taken quickly and accurately.'),
    ('landing.blog.post.concerns.q1.q', 'landing', 'blog.post.concerns.q1.q', 'Will customers know they''re talking to an AI?'),
    ('landing.blog.post.concerns.q3.a', 'landing', 'blog.post.concerns.q3.a', 'The AI''s order accuracy rate is 98.7% — significantly higher than the human average of 91.7%. Every order is confirmed with the customer before being sent to the kitchen.'),
    ('landing.blog.post.conclusion.p2', 'landing', 'blog.post.conclusion.p2', 'The question is no longer whether AI voice ordering works — it''s whether your restaurant can afford to wait any longer to implement it.'),
    ('landing.blog.post.how_it_works.p1', 'landing', 'blog.post.how_it_works.p1', 'Modern AI voice ordering systems use large language models fine-tuned on restaurant-specific data to understand natural speech, handle complex order modifications, and respond in the customer''s preferred language.'),
    ('landing.blog.post.implementation.item3', 'landing', 'blog.post.implementation.item3', '15 minutes to review and approve the AI''s responses'),
    ('landing.blog.post.implementation.list_title', 'landing', 'blog.post.implementation.list_title', 'What you''ll need to get started'),
    ('landing.blog.post.intro.p1', 'landing', 'blog.post.intro.p1', 'Every restaurant owner knows the feeling: it''s Friday night, the dining room is packed, the kitchen is firing on all cylinders — and the phone won''t stop ringing. Your best server is stuck answering calls instead of serving tables. Orders get missed. Customers hang up frustrated. Revenue walks out the door.'),
    ('landing.blog.post.intro.p2', 'landing', 'blog.post.intro.p2', 'This is the problem that AI voice ordering was built to solve. And after analyzing data from over 2,400 restaurants using RestroAgent, the results are clear: AI-powered phone ordering isn''t just a convenience — it''s a competitive advantage.'),
    ('landing.blog.post.problem.p2', 'landing', 'blog.post.problem.p2', 'Our research found that the average restaurant misses 23% of incoming calls during peak hours. For a restaurant doing $50K/month in phone orders, that''s over $11,500 in lost revenue every single month.'),
    ('landing.blog.related3.title', 'landing', 'blog.related3.title', 'The Restaurant Owner''s Guide to Revenue Analytics in 2026'),
    ('landing.contact.demo.desc', 'landing', 'contact.demo.desc', 'Book a 30-minute call and we''ll show you RestroAgent live with your menu. No commitment required.'),
    ('landing.contact.form.message_placeholder', 'landing', 'contact.form.message_placeholder', 'Tell us about your restaurant and what you''re looking for...'),
    ('landing.contact.hero.title', 'landing', 'contact.hero.title', 'We''d love to hear from you'),
    ('landing.contact.success.subtitle', 'landing', 'contact.success.subtitle', 'We''ll get back to you within 4 hours during business hours.'),
    ('landing.cookie.type.Functional.badge', 'landing', 'cookie.type.Functional.badge', 'Optional'),
    ('landing.cookie.type.Functional.desc', 'landing', 'cookie.type.Functional.desc', 'These cookies enable enhanced functionality and personalization, such as remembering your theme preference (dark/light mode) and display settings.'),
    ('landing.cookie.type.Functional.example.0', 'landing', 'cookie.type.Functional.example.0', 'ra-theme — stores your dark/light mode preference'),
    ('landing.cookie.type.Functional.example.1', 'landing', 'cookie.type.Functional.example.1', 'Sidebar collapse state'),
    ('landing.cookie.type.Functional.example.2', 'landing', 'cookie.type.Functional.example.2', 'Language preferences'),
    ('landing.cookie.type.Functional.name', 'landing', 'cookie.type.Functional.name', 'Functional'),
    ('landing.cookie.type.Marketing.badge', 'landing', 'cookie.type.Marketing.badge', 'Optional'),
    ('landing.cookie.type.Marketing.desc', 'landing', 'cookie.type.Marketing.desc', 'These cookies may be set by our advertising partners to build a profile of your interests and show relevant ads on other sites. We do not use these cookies on our core platform — only on our public marketing website.'),
    ('landing.cookie.type.Marketing.example.0', 'landing', 'cookie.type.Marketing.example.0', 'Referral source tracking'),
    ('landing.cookie.type.Marketing.example.1', 'landing', 'cookie.type.Marketing.example.1', 'Campaign attribution'),
    ('landing.cookie.type.Marketing.name', 'landing', 'cookie.type.Marketing.name', 'Marketing'),
    ('landing.cookie.type.PerformanceAnalytics.badge', 'landing', 'cookie.type.PerformanceAnalytics.badge', 'Optional'),
    ('landing.cookie.type.PerformanceAnalytics.desc', 'landing', 'cookie.type.PerformanceAnalytics.desc', 'These cookies allow us to count visits and understand how visitors interact with the Service, so we can measure and improve performance. All information collected is aggregated and anonymous.'),
    ('landing.cookie.type.PerformanceAnalytics.example.0', 'landing', 'cookie.type.PerformanceAnalytics.example.0', 'Anonymous page view tracking'),
    ('landing.cookie.type.PerformanceAnalytics.example.1', 'landing', 'cookie.type.PerformanceAnalytics.example.1', 'Feature usage analytics'),
    ('landing.cookie.type.PerformanceAnalytics.example.2', 'landing', 'cookie.type.PerformanceAnalytics.example.2', 'Error monitoring'),
    ('landing.cookie.type.PerformanceAnalytics.name', 'landing', 'cookie.type.PerformanceAnalytics.name', 'Performance & Analytics'),
    ('landing.cookie.type.StrictlyNecessary.badge', 'landing', 'cookie.type.StrictlyNecessary.badge', 'Always Active'),
    ('landing.cookie.type.StrictlyNecessary.desc', 'landing', 'cookie.type.StrictlyNecessary.desc', 'These cookies are essential for the website to function and cannot be switched off. They are set in response to actions you take, such as logging in, setting your privacy preferences, or filling in forms.'),
    ('landing.cookie.type.StrictlyNecessary.example.0', 'landing', 'cookie.type.StrictlyNecessary.example.0', 'restroagent_session — authentication session cookie'),
    ('landing.cookie.type.StrictlyNecessary.example.1', 'landing', 'cookie.type.StrictlyNecessary.example.1', 'sub_gate — subscription status cache (5-minute TTL)'),
    ('landing.cookie.type.StrictlyNecessary.example.2', 'landing', 'cookie.type.StrictlyNecessary.example.2', 'CSRF tokens — security protection'),
    ('landing.cookie.type.StrictlyNecessary.name', 'landing', 'cookie.type.StrictlyNecessary.name', 'Strictly Necessary'),
    ('landing.faq.hero.subtitle', 'landing', 'faq.hero.subtitle', 'Everything you need to know about RestroAgent. Can''t find your answer?'),
    ('landing.footerTagline', 'landing', 'footerTagline', 'AI-powered voice and chat agents that handle orders, bookings, and customer queries — so your staff can focus on hospitality.'),
    ('landing.home.faqA3', 'landing', 'home.faqA3', 'Yes — we integrate natively with Toast, Square, Clover, Lightspeed, and 50+ other POS systems. If yours isn''t listed, contact us and we''ll build the connector at no extra cost.'),
    ('landing.home.howStep2Desc', 'landing', 'home.howStep2Desc', 'Add your restaurant''s personality, special instructions, and common FAQs.'),
    ('landing.home.testimonial1Quote', 'landing', 'home.testimonial1Quote', 'We went from missing 30% of phone orders during rush hour to zero missed calls. The AI handles it perfectly — even our regulars can''t tell the difference.'),
    ('landing.refund.hero.desc', 'landing', 'refund.hero.desc', 'We stand behind RestroAgent. If you''re not happy in your first 30 days, we''ll give you a full refund — no questions asked.'),
    ('menuManagement.modifierGroupDescription', 'menuManagement', 'modifierGroupDescription', 'Configure modifier options for menu items'),
    ('nav.analytics', 'nav', 'analytics', 'Analytics & Reports'),
    ('nav.branches', 'nav', 'branches', 'Branch Management'),
    ('nav.conversations', 'nav', 'conversations', 'Conversations'),
    ('nav.customers', 'nav', 'customers', 'Customer Management'),
    ('nav.orders', 'nav', 'orders', 'Order Management'),
    ('nav.reservations', 'nav', 'reservations', 'Table Booking Management'),
    ('notifications.caughtUp', 'notifications', 'caughtUp', 'You''re all caught up!'),
    ('notifications.preferences_subtitle', 'notifications', 'preferences_subtitle', 'Control how and when you receive notifications'),
    ('notifications.preferences_title', 'notifications', 'preferences_title', 'Notification Preferences'),
    ('notifications.subtitle', 'notifications', 'subtitle', 'All your alerts and updates in one place'),
    ('notifications.title', 'notifications', 'title', 'Notification Center'),
    ('orderManagement.bulkStatusUpdated', 'orderManagement', 'bulkStatusUpdated', '{{count}} orders updated'),
    ('orderManagement.deleteConfirmDescription', 'orderManagement', 'deleteConfirmDescription', 'This action cannot be undone. The order will be permanently deleted.'),
    ('orderManagement.deletedTitle', 'orderManagement', 'deletedTitle', 'Order deleted'),
    ('orderManagement.details_title', 'orderManagement', 'details_title', 'Order Details'),
    ('orderManagement.editOrderTitle', 'orderManagement', 'editOrderTitle', 'Edit Order'),
    ('orderManagement.itemCount', 'orderManagement', 'itemCount', '{{count}} item{{plural}}'),
    ('orderManagement.loading', 'orderManagement', 'loading', 'Loading orders...'),
    ('orderManagement.newOrdersAttention', 'orderManagement', 'newOrdersAttention', 'new orders need attention'),
    ('orderManagement.newOrdersReceived', 'orderManagement', 'newOrdersReceived', 'New orders received'),
    ('orderManagement.orderUpdatedToast', 'orderManagement', 'orderUpdatedToast', 'Order updated'),
    ('orderManagement.selectedCount', 'orderManagement', 'selectedCount', '{{count}} selected'),
    ('orderManagement.status_updated', 'orderManagement', 'status_updated', 'Status updated'),
    ('phoneNumbers.buy.areaCodePlaceholder', 'phoneNumbers', 'buy.areaCodePlaceholder', 'e.g. 415'),
    ('phoneNumbers.buy.subtitle', 'phoneNumbers', 'buy.subtitle', 'Search and purchase a phone number to assign to your AI agent'),
    ('phoneNumbers.buy.title', 'phoneNumbers', 'buy.title', 'Buy Phone Number'),
    ('phoneNumbers.deleteConfirm', 'phoneNumbers', 'deleteConfirm', 'Delete Number'),
    ('phoneNumbers.deleteDescription', 'phoneNumbers', 'deleteDescription', 'This will permanently remove the phone number from your account.'),
    ('phoneNumbers.deleteTitle', 'phoneNumbers', 'deleteTitle', 'Delete Phone Number'),
    ('phoneNumbers.detail.subtitle', 'phoneNumbers', 'detail.subtitle', 'Manage phone number settings and agent assignment'),
    ('phoneNumbers.searchPlaceholder', 'phoneNumbers', 'searchPlaceholder', 'Search numbers...'),
    ('phoneNumbers.sip.displayNamePlaceholder', 'phoneNumbers', 'sip.displayNamePlaceholder', 'e.g. Main SIP Trunk'),
    ('phoneNumbers.sip.passwordPlaceholder', 'phoneNumbers', 'sip.passwordPlaceholder', 'SIP account password'),
    ('phoneNumbers.sip.sipServerPlaceholder', 'phoneNumbers', 'sip.sipServerPlaceholder', 'sip.provider.com:5060'),
    ('phoneNumbers.sip.subtitle', 'phoneNumbers', 'sip.subtitle', 'Connect an existing SIP trunk to your AI voice agent'),
    ('phoneNumbers.sip.title', 'phoneNumbers', 'sip.title', 'SIP Trunk Configuration'),
    ('phoneNumbers.sip.usernamePlaceholder', 'phoneNumbers', 'sip.usernamePlaceholder', 'SIP username or extension'),
    ('phoneNumbers.subtitle', 'phoneNumbers', 'subtitle', 'Manage phone numbers assigned to your AI voice agent'),
    ('phoneNumbers.title', 'phoneNumbers', 'title', 'Phone Numbers'),
    ('restApi.subtitle', 'restApi', 'subtitle', 'Manage API keys and integrate RestroAgent with your systems'),
    ('restApi.title', 'restApi', 'title', 'REST API'),
    ('restaurantSettings.subtitle', 'restaurantSettings', 'subtitle', 'Profile, hours, notifications, and integrations'),
    ('restaurantSettings.title', 'restaurantSettings', 'title', 'Restaurant Settings'),
    ('settings.templates.subtitle', 'settings', 'templates.subtitle', 'Manage response templates'),
    ('settings.templates.textarea_placeholder', 'settings', 'templates.textarea_placeholder', 'Enter your message template here...'),
    ('staff.manageTeamMemberDetailsAndPermissions', 'staff', 'manageTeamMemberDetailsAndPermissions', 'Manage team member details and permissions'),
    ('staff.permissions', 'staff', 'permissions', 'Permissions'),
    ('staff.role', 'staff', 'role', 'Role'),
    ('support.auditLogDetail', 'support', 'auditLogDetail', 'Audit Log Detail'),
    ('support.auditLogDetailDescription', 'support', 'auditLogDetailDescription', 'Full event details and state changes'),
    ('tableBooking.fullBookingDetailsAndCustomerInfo', 'tableBooking', 'fullBookingDetailsAndCustomerInfo', 'Full booking details and customer information'),
    ('tableBooking.tonightsTimeline', 'tableBooking', 'tonightsTimeline', 'Tonight''s Timeline'),
    ('webhooks.subtitle', 'webhooks', 'subtitle', 'Configure webhook endpoints to push events to third-party systems'),
    ('webhooks.title', 'webhooks', 'title', 'Webhooks'),
    ('landing.home.card7Badge', 'landing', 'home.card7Badge', 'Always learning'),
    ('landing.home.card7Title', 'landing', 'home.card7Title', 'Knowledge Base'),
    ('landing.home.card7Desc', 'landing', 'home.card7Desc', 'Train the AI on your menu, allergens, hours, and FAQs — it answers every customer question accurately.'),
    ('landing.home.card7Q', 'landing', 'home.card7Q', 'Do you have gluten-free pasta?'),
    ('landing.home.card7A', 'landing', 'home.card7A', 'Yes! Our GF penne is available for all pasta dishes. Want to see the full gluten-free menu? 🍝'),
    ('landing.home.card7Tag1', 'landing', 'home.card7Tag1', 'Menu & Prices'),
    ('landing.home.card7Tag2', 'landing', 'home.card7Tag2', 'Allergens'),
    ('landing.home.card7Tag3', 'landing', 'home.card7Tag3', 'Hours'),
    ('landing.home.card7Tag4', 'landing', 'home.card7Tag4', 'Specials'),
    ('landing.home.card7Tag5', 'landing', 'home.card7Tag5', 'Policies'),
    ('landing.home.card8Badge', 'landing', 'home.card8Badge', '99.9% delivery rate'),
    ('landing.home.card8Title', 'landing', 'home.card8Title', 'WhatsApp & SMS'),
    ('landing.home.card8Desc', 'landing', 'home.card8Desc', 'Reach customers on WhatsApp and SMS — order confirmations, booking reminders, and AI chat, automatically.'),
    ('landing.home.card8Whatsapp', 'landing', 'home.card8Whatsapp', 'Order #2847 confirmed! 🎉 Table 7 at 7:00 PM. See you tonight!'),
    ('landing.home.card8SmsLabel', 'landing', 'home.card8SmsLabel', 'SMS Reminder'),
    ('landing.home.card8Sms', 'landing', 'home.card8Sms', 'Hi Sarah, your booking at Bella Napoli is in 2 hours. Reply CANCEL to cancel. 📍 42 Main St'),
    ('landing.home.stat1Label', 'landing', 'home.stat1Label', 'Restaurants'),
    ('landing.home.stat1Sub', 'landing', 'home.stat1Sub', 'across 40+ countries'),
    ('landing.home.stat2Label', 'landing', 'home.stat2Label', 'Orders Processed'),
    ('landing.home.stat2Sub', 'landing', 'home.stat2Sub', 'this year alone'),
    ('landing.home.stat3Label', 'landing', 'home.stat3Label', 'Uptime SLA'),
    ('landing.home.stat3Sub', 'landing', 'home.stat3Sub', 'guaranteed'),
    ('landing.home.stat4Label', 'landing', 'home.stat4Label', 'Revenue Lift'),
    ('landing.home.stat4Sub', 'landing', 'home.stat4Sub', 'average across customers'),
    ('landing.home.liveLabel', 'landing', 'home.liveLabel', 'Live'),
    ('landing.home.verifiedBadge', 'landing', 'home.verifiedBadge', 'Verified'),
    ('landing.contact.info.hq_name', 'landing', 'contact.info.hq_name', 'RestroAgent GmbH'),
    ('landing.contact.info.hq_street', 'landing', 'contact.info.hq_street', 'Friedrichstraße 123'),
    ('landing.contact.info.hq_city', 'landing', 'contact.info.hq_city', '10117 Berlin, Germany'),
    ('landing.contact.info.email_hello', 'landing', 'contact.info.email_hello', 'hello@restroagent.ai'),
    ('landing.contact.info.email_support', 'landing', 'contact.info.email_support', 'support@restroagent.ai'),
    ('landing.contact.info.phone_number', 'landing', 'contact.info.phone_number', '+49 30 1234 5678')
  ON CONFLICT (key) DO NOTHING;

  -- ─── PRICING PAGE — PLAN BADGES / HIGHLIGHTS / MISSING / FAQ ──────────
  INSERT INTO public.translation_keys (key, category, description, default_value) VALUES
    ('landing.pricing.plan.badge.mostPopular', 'landing', 'pricing plan badge mostPopular', 'Most Popular'),
    ('landing.pricing.plan.badge.bestValue', 'landing', 'pricing plan badge bestValue', 'Best Value'),
    ('landing.pricing.plan.highlight.growth', 'landing', 'pricing plan highlight growth', 'Most chosen by growing restaurants'),
    ('landing.pricing.plan.missing.multiBranch', 'landing', 'pricing plan missing multiBranch', 'Multi-branch'),
    ('landing.pricing.plan.missing.customAI', 'landing', 'pricing plan missing customAI', 'Custom AI personality'),
    ('landing.pricing.plan.missing.prioritySupport', 'landing', 'pricing plan missing prioritySupport', 'Priority support'),
    ('landing.pricing.plan.missing.apiAccess', 'landing', 'pricing plan missing apiAccess', 'API access'),
    ('landing.pricing.plan.missing.whiteLabel', 'landing', 'pricing plan missing whiteLabel', 'White-label'),
    ('landing.pricing.plan.missing.multiBranch3', 'landing', 'pricing plan missing multiBranch3', 'Multi-branch (up to 3)'),
    ('landing.pricing.faq.cat.billing', 'landing', 'pricing faq category billing', 'Billing'),
    ('landing.pricing.faq.cat.technical', 'landing', 'pricing faq category technical', 'Technical'),
    ('landing.pricing.faq.cat.aiAccuracy', 'landing', 'pricing faq category aiAccuracy', 'AI & Accuracy'),
    ('landing.pricing.faq.billing.q1', 'landing', 'pricing faq billing q1', 'Can I change plans at any time?'),
    ('landing.pricing.faq.billing.a1', 'landing', 'pricing faq billing a1', 'Yes. You can upgrade or downgrade at any time. Upgrades take effect immediately; downgrades apply at the next billing cycle.'),
    ('landing.pricing.faq.billing.q2', 'landing', 'pricing faq billing q2', 'What happens after my free trial?'),
    ('landing.pricing.faq.billing.a2', 'landing', 'pricing faq billing a2', 'After 14 days, you''ll be asked to choose a plan. We''ll remind you 3 days before the trial ends. No charges without your explicit consent.'),
    ('landing.pricing.faq.billing.q3', 'landing', 'pricing faq billing q3', 'Do you offer refunds?'),
    ('landing.pricing.faq.billing.a3', 'landing', 'pricing faq billing a3', 'We offer a 30-day money-back guarantee on all paid plans. No questions asked.'),
    ('landing.pricing.faq.technical.q1', 'landing', 'pricing faq technical q1', 'How long does setup take?'),
    ('landing.pricing.faq.technical.a1', 'landing', 'pricing faq technical a1', 'Most restaurants are live within 2 hours. We handle the technical setup; you just need to forward your phone number and upload your menu.'),
    ('landing.pricing.faq.technical.q2', 'landing', 'pricing faq technical q2', 'Does it work with my existing POS?'),
    ('landing.pricing.faq.technical.a2', 'landing', 'pricing faq technical a2', 'We integrate with 50+ POS systems including Square, Toast, Clover, Lightspeed, and more. If yours isn''t listed, contact us — we can usually build it.'),
    ('landing.pricing.faq.technical.q3', 'landing', 'pricing faq technical q3', 'What languages does the AI support?'),
    ('landing.pricing.faq.technical.a3', 'landing', 'pricing faq technical a3', 'Growth plan supports 15 languages. Enterprise supports 30+. The AI automatically detects the customer''s language and responds accordingly.'),
    ('landing.pricing.faq.ai.q1', 'landing', 'pricing faq ai q1', 'How accurate is the AI at taking orders?'),
    ('landing.pricing.faq.ai.a1', 'landing', 'pricing faq ai a1', 'Our average order accuracy is 98.7% across all restaurants. The AI asks clarifying questions when unsure rather than guessing.'),
    ('landing.pricing.faq.ai.q2', 'landing', 'pricing faq ai q2', 'What happens when the AI can''t handle something?'),
    ('landing.pricing.faq.ai.a2', 'landing', 'pricing faq ai a2', 'The AI escalates to a human staff member via real-time alert. You set the escalation rules — we never leave a customer hanging.'),
    ('landing.pricing.faq.ai.q3', 'landing', 'pricing faq ai q3', 'Can I customize what the AI says?'),
    ('landing.pricing.faq.ai.a3', 'landing', 'pricing faq ai a3', 'Yes. On Growth and Enterprise plans, you can set the AI''s name, personality, tone, and specific responses for common scenarios.'),
    ('admin.aiSettings.modelGpt4oMini', 'admin', 'aiSettings model gpt4o mini label', 'GPT-4o Mini'),
    ('admin.aiSettings.modelClaudeHaiku', 'admin', 'aiSettings model claude haiku label', 'Claude Haiku')
  ON CONFLICT (key) DO NOTHING;

  -- ─── FAQ PAGE — CATEGORY KEYS (new key names) ──────────
  INSERT INTO public.translation_keys (key, category, description, default_value) VALUES
    ('landing.faq.category.GettingStarted', 'landing', 'faq category getting started', 'Getting Started'),
    ('landing.faq.category.AIAccuracy', 'landing', 'faq category ai accuracy', 'AI & Accuracy'),
    ('landing.faq.category.Integrations', 'landing', 'faq category integrations', 'Integrations'),
    ('landing.faq.category.PricingBilling', 'landing', 'faq category pricing billing', 'Pricing & Billing'),
    ('landing.faq.category.SecurityPrivacy', 'landing', 'faq category security privacy', 'Security & Privacy'),
    ('landing.faq.items.GettingStarted.0.q', 'landing', 'faq gs q0', 'How quickly can I get RestroAgent running?'),
    ('landing.faq.items.GettingStarted.0.a', 'landing', 'faq gs a0', 'Most restaurants are fully live within 2 hours. The process: upload your menu (or connect your POS), configure your AI personality, and forward your phone number. Our onboarding team guides you through every step.'),
    ('landing.faq.items.GettingStarted.1.q', 'landing', 'faq gs q1', 'Do I need any technical knowledge?'),
    ('landing.faq.items.GettingStarted.1.a', 'landing', 'faq gs a1', 'None at all. If you can use a smartphone, you can set up RestroAgent. We''ve designed the entire process to be handled by restaurant owners and managers, not IT teams.'),
    ('landing.faq.items.GettingStarted.2.q', 'landing', 'faq gs q2', 'What do I need to get started?'),
    ('landing.faq.items.GettingStarted.2.a', 'landing', 'faq gs a2', 'Just your menu (PDF, image, or POS export), your phone number, and 2 hours. We handle everything else.'),
    ('landing.faq.items.GettingStarted.3.q', 'landing', 'faq gs q3', 'Is there a free trial?'),
    ('landing.faq.items.GettingStarted.3.a', 'landing', 'faq gs a3', 'Yes — 14 days, full access to all features on your chosen plan. No credit card required to start.'),
    ('landing.faq.items.AIAccuracy.0.q', 'landing', 'faq ai q0', 'How accurate is the AI at taking orders?'),
    ('landing.faq.items.AIAccuracy.0.a', 'landing', 'faq ai a0', 'Our average order accuracy is 98.7% across all restaurants. The AI is trained specifically on restaurant ordering patterns and asks clarifying questions when unsure rather than guessing.'),
    ('landing.faq.items.AIAccuracy.1.q', 'landing', 'faq ai q1', 'Can the AI handle complex orders with modifications?'),
    ('landing.faq.items.AIAccuracy.1.a', 'landing', 'faq ai a1', 'Yes. The AI handles substitutions, allergies, cooking preferences, combo modifications, and multi-item orders. It''s been trained on millions of real restaurant conversations.'),
    ('landing.faq.items.AIAccuracy.2.q', 'landing', 'faq ai q2', 'What happens when the AI can''t handle a request?'),
    ('landing.faq.items.AIAccuracy.2.a', 'landing', 'faq ai a2', 'The AI escalates to a human staff member via real-time alert on your dashboard and mobile app. You set the escalation rules — we never leave a customer without a response.'),
    ('landing.faq.items.AIAccuracy.3.q', 'landing', 'faq ai q3', 'Does the AI learn from my restaurant over time?'),
    ('landing.faq.items.AIAccuracy.3.a', 'landing', 'faq ai a3', 'Yes. The AI improves based on corrections you make and feedback from your customers. After 30 days, most restaurants see a 15-20% improvement in accuracy.'),
    ('landing.faq.items.Integrations.0.q', 'landing', 'faq int q0', 'Which POS systems do you integrate with?'),
    ('landing.faq.items.Integrations.0.a', 'landing', 'faq int a0', 'We integrate with 50+ POS systems including Square, Toast, Clover, Lightspeed, Revel, TouchBistro, and more. If yours isn''t listed, contact us — we can usually build the integration within 2 weeks.'),
    ('landing.faq.items.Integrations.1.q', 'landing', 'faq int q1', 'Can I connect to delivery platforms?'),
    ('landing.faq.items.Integrations.1.a', 'landing', 'faq int a1', 'Yes. We integrate with Uber Eats, DoorDash, Grubhub, Deliveroo, and more. Orders from all channels flow into a single dashboard.'),
    ('landing.faq.items.Integrations.2.q', 'landing', 'faq int q2', 'What payment processors do you support?'),
    ('landing.faq.items.Integrations.2.a', 'landing', 'faq int a2', 'Stripe, Square, PayPal, Braintree, and most major processors. Payment collection happens through your existing processor — we don''t touch your money.'),
    ('landing.faq.items.Integrations.3.q', 'landing', 'faq int q3', 'Can I use my existing phone number?'),
    ('landing.faq.items.Integrations.3.a', 'landing', 'faq int a3', 'Yes. You simply forward your existing number to RestroAgent. Customers call the same number they always have.'),
    ('landing.faq.items.PricingBilling.0.q', 'landing', 'faq pb q0', 'Can I change my plan at any time?'),
    ('landing.faq.items.PricingBilling.0.a', 'landing', 'faq pb a0', 'Yes. Upgrades take effect immediately; downgrades apply at the next billing cycle. There are no long-term contracts on monthly plans.'),
    ('landing.faq.items.PricingBilling.1.q', 'landing', 'faq pb q1', 'What counts as a "conversation"?'),
    ('landing.faq.items.PricingBilling.1.a', 'landing', 'faq pb a1', 'A conversation is a single continuous interaction with one customer — whether it''s a 2-message order or a 20-message booking with modifications. Starter plan includes 500/month; Growth and Enterprise are unlimited.'),
    ('landing.faq.items.PricingBilling.2.q', 'landing', 'faq pb q2', 'Do you offer discounts for multiple locations?'),
    ('landing.faq.items.PricingBilling.2.a', 'landing', 'faq pb a2', 'Yes. Enterprise plan covers unlimited locations at a flat rate. For 3-10 locations, contact us for a custom Growth plan quote.'),
    ('landing.faq.items.PricingBilling.3.q', 'landing', 'faq pb q3', 'Is there a setup fee?'),
    ('landing.faq.items.PricingBilling.3.a', 'landing', 'faq pb a3', 'No setup fees on any plan. You pay only the monthly or annual subscription.'),
    ('landing.faq.items.SecurityPrivacy.0.q', 'landing', 'faq sp q0', 'Is customer data secure?'),
    ('landing.faq.items.SecurityPrivacy.0.a', 'landing', 'faq sp a0', 'Yes. All data is encrypted in transit (TLS 1.3) and at rest (AES-256). We''re GDPR compliant and SOC 2 Type II certified.'),
    ('landing.faq.items.SecurityPrivacy.1.q', 'landing', 'faq sp q1', 'Do you sell customer data?'),
    ('landing.faq.items.SecurityPrivacy.1.a', 'landing', 'faq sp a1', 'Never. Customer data belongs to you, the restaurant. We never sell, share, or use your customer data for any purpose other than providing the service.'),
    ('landing.faq.items.SecurityPrivacy.2.q', 'landing', 'faq sp q2', 'Are conversations recorded?'),
    ('landing.faq.items.SecurityPrivacy.2.a', 'landing', 'faq sp a2', 'Voice calls are transcribed (not stored as audio by default). You can enable call recording for quality assurance. All recordings are stored in your account and can be deleted at any time.'),
    ('landing.faq.items.SecurityPrivacy.3.q', 'landing', 'faq sp q3', 'Can I delete my data?'),
    ('landing.faq.items.SecurityPrivacy.3.a', 'landing', 'faq sp a3', 'Yes. You can export or delete all your data at any time from your account settings. Upon cancellation, data is deleted within 30 days.')
  ON CONFLICT (key) DO NOTHING;

  -- ─── BATCH 7: Integration logos, case study data, testimonial data, blog content ───
INSERT INTO public.translation_keys (key, category, description, default_value) VALUES
    ('landing.home.intLogo1', 'landing', 'Integration logo 1', 'Uber Eats'),
    ('landing.home.intLogo2', 'landing', 'Integration logo 2', 'DoorDash'),
    ('landing.home.intLogo3', 'landing', 'Integration logo 3', 'Grubhub'),
    ('landing.home.intLogo4', 'landing', 'Integration logo 4', 'Square POS'),
    ('landing.home.intLogo5', 'landing', 'Integration logo 5', 'Toast POS'),
    ('landing.home.intLogo6', 'landing', 'Integration logo 6', 'Stripe'),
    ('landing.home.intLogo7', 'landing', 'Integration logo 7', 'Twilio'),
    ('landing.home.intLogo8', 'landing', 'Integration logo 8', 'OpenTable'),
    ('landing.home.intLogo9', 'landing', 'Integration logo 9', 'Resy'),
    ('landing.home.intLogo10', 'landing', 'Integration logo 10', 'Clover'),
    ('landing.home.intLogo11', 'landing', 'Integration logo 11', 'Lightspeed'),
    ('landing.home.intLogo12', 'landing', 'Integration logo 12', 'Yelp'),
    ('landing.home.cs1Restaurant', 'landing', 'Case study 1 restaurant name', 'Bella Napoli'),
    ('landing.home.cs1Location', 'landing', 'Case study 1 location', 'New York, NY · 1 location'),
    ('landing.home.cs1Plan', 'landing', 'Case study 1 plan', 'Growth Plan'),
    ('landing.home.cs1Author', 'landing', 'Case study 1 author', 'Marco Rossi, Owner'),
    ('landing.home.cs2Restaurant', 'landing', 'Case study 2 restaurant name', 'Spice Garden Group'),
    ('landing.home.cs2Location', 'landing', 'Case study 2 location', 'Chicago, IL · 8 locations'),
    ('landing.home.cs2Plan', 'landing', 'Case study 2 plan', 'Enterprise Plan'),
    ('landing.home.cs2Author', 'landing', 'Case study 2 author', 'Priya Sharma, General Manager'),
    ('landing.home.cs3Restaurant', 'landing', 'Case study 3 restaurant name', 'Dragon Palace Group'),
    ('landing.home.cs3Location', 'landing', 'Case study 3 location', 'San Francisco, CA · 3 locations'),
    ('landing.home.cs3Plan', 'landing', 'Case study 3 plan', 'Enterprise Plan'),
    ('landing.home.cs3Author', 'landing', 'Case study 3 author', 'James Chen, CEO'),
    ('landing.home.t1Name', 'landing', 'Testimonial 1 name', 'Marco Rossi'),
    ('landing.home.t1Role', 'landing', 'Testimonial 1 role', 'Owner, Bella Napoli'),
    ('landing.home.t1Plan', 'landing', 'Testimonial 1 plan', 'Growth Plan'),
    ('landing.home.t2Name', 'landing', 'Testimonial 2 name', 'Priya Sharma'),
    ('landing.home.t2Role', 'landing', 'Testimonial 2 role', 'GM, Spice Garden (8 locations)'),
    ('landing.home.t2Plan', 'landing', 'Testimonial 2 plan', 'Enterprise Plan'),
    ('landing.home.t3Name', 'landing', 'Testimonial 3 name', 'James Chen'),
    ('landing.home.t3Role', 'landing', 'Testimonial 3 role', 'CEO, Dragon Palace Group'),
    ('landing.home.t3Plan', 'landing', 'Testimonial 3 plan', 'Enterprise Plan'),
    ('landing.home.t4Name', 'landing', 'Testimonial 4 name', 'Sofia Andrade'),
    ('landing.home.t4Role', 'landing', 'Testimonial 4 role', 'Owner, Casa Mia'),
    ('landing.home.t4Plan', 'landing', 'Testimonial 4 plan', 'Starter Plan'),
    ('admin.blog.post1.title', 'admin', 'Blog post 1 title', 'How AI Voice Ordering Helped 2,400+ Restaurants Capture Every Call'),
    ('admin.blog.post1.author', 'admin', 'Blog post 1 author', 'Alex Rivera'),
    ('admin.blog.post2.title', 'admin', 'Blog post 2 title', 'How Bella Napoli Reduced Missed Orders by 100% with AI Voice'),
    ('admin.blog.post2.author', 'admin', 'Blog post 2 author', 'Yuki Tanaka'),
    ('admin.blog.post3.title', 'admin', 'Blog post 3 title', 'The Real Cost of a Missed Phone Order'),
    ('admin.blog.post3.author', 'admin', 'Blog post 3 author', 'Carlos Vega'),
    ('admin.blog.post4.title', 'admin', 'Blog post 4 title', 'Why Multilingual AI is Non-Negotiable for Modern Restaurants'),
    ('admin.blog.post4.author', 'admin', 'Blog post 4 author', 'Amara Osei'),
    ('admin.blog.post5.title', 'admin', 'Blog post 5 title', 'RestroAgent 3.0: Introducing Real-Time Sentiment Analysis'),
    ('admin.blog.post5.author', 'admin', 'Blog post 5 author', 'Lena Fischer'),
    ('admin.blog.post6.title', 'admin', 'Blog post 6 title', 'How to Train Your AI Agent to Sound Like Your Restaurant'),
    ('admin.blog.post6.author', 'admin', 'Blog post 6 author', 'Sophie Laurent'),
    ('admin.blog.post7.title', 'admin', 'Blog post 7 title', 'The Future of Restaurant Ordering: Voice, Chat, or Both?'),
    ('admin.blog.post7.author', 'admin', 'Blog post 7 author', 'Arjun Mehta'),
    ('admin.blog.post8.title', 'admin', 'Blog post 8 title', 'Table Booking Abandonment: Why 60% of Reservations Never Complete'),
    ('admin.blog.post8.author', 'admin', 'Blog post 8 author', 'Carlos Vega'),
    ('admin.blog.tag.ai', 'admin', 'Blog tag AI', 'AI'),
    ('admin.blog.tag.voice', 'admin', 'Blog tag Voice', 'Voice'),
    ('admin.blog.tag.revenue', 'admin', 'Blog tag Revenue', 'Revenue'),
    ('admin.blog.tag.caseStudy', 'admin', 'Blog tag Case Study', 'Case Study'),
    ('admin.blog.tag.research', 'admin', 'Blog tag Research', 'Research'),
    ('admin.blog.tag.multilingual', 'admin', 'Blog tag Multilingual', 'Multilingual'),
    ('admin.blog.tag.product', 'admin', 'Blog tag Product', 'Product'),
    ('admin.blog.tag.sentiment', 'admin', 'Blog tag Sentiment', 'Sentiment'),
    ('admin.blog.tag.guide', 'admin', 'Blog tag Guide', 'Guide'),
    ('admin.blog.tag.bookings', 'admin', 'Blog tag Bookings', 'Bookings'),
    ('admin.blog.tag.insights', 'admin', 'Blog tag Insights', 'Insights'),
    ('admin.blog.sample.title', 'admin', 'Blog sample title', 'How AI Voice Ordering Helped 2,400+ Restaurants Capture Every Call'),
    ('admin.blog.sample.excerpt', 'admin', 'Blog sample excerpt', 'A deep dive into how AI-powered phone ordering is eliminating missed calls, reducing staff workload, and adding thousands in monthly revenue for restaurants of all sizes.'),
    ('admin.blog.sample.tag1', 'admin', 'Blog sample tag 1', 'AI Ordering'),
    ('admin.blog.sample.tag2', 'admin', 'Blog sample tag 2', 'Restaurant Tech'),
    ('admin.blog.sample.tag3', 'admin', 'Blog sample tag 3', 'Revenue Growth'),
    ('admin.blog.sample.authorName', 'admin', 'Blog sample author name', 'Alex Rivera'),
    ('admin.blog.sample.authorBio', 'admin', 'Blog sample author bio', 'Alex has spent 8 years at the intersection of hospitality and technology. Before RestroAgent, he led product at two restaurant tech startups.'),
    ('admin.blog.sample.block.intro', 'admin', 'Blog sample intro paragraph', 'Every restaurant owner knows the feeling: it''s Friday night, the dining room is packed, the kitchen is firing on all cylinders — and the phone won''t stop ringing.'),
    ('admin.blog.sample.block.callout1', 'admin', 'Blog sample callout 1', 'Key Insight | Restaurants using AI voice ordering report an average of zero missed calls during peak hours, compared to a 30-40% miss rate for manually-staffed phone lines.'),
    ('admin.blog.sample.block.h2problem', 'admin', 'Blog sample h2 problem', 'The Problem with Traditional Phone Orders'),
    ('admin.blog.sample.block.problem', 'admin', 'Blog sample problem paragraph', 'Traditional phone ordering creates a bottleneck that costs restaurants in three distinct ways: missed revenue from unanswered calls, reduced service quality when staff are pulled away from tables, and human error in order-taking.'),
    ('admin.blog.sample.block.stats', 'admin', 'Blog sample stats', '23% | Calls missed during peak hours'),
    ('admin.blog.sample.block.h2how', 'admin', 'Blog sample h2 how', 'How AI Voice Ordering Works'),
    ('admin.blog.sample.block.steps', 'admin', 'Blog sample step list', '01 | Customer calls your number | The AI answers instantly'),
    ('admin.blog.sample.block.h2results', 'admin', 'Blog sample h2 results', 'Real-World Results'),
    ('admin.blog.sample.block.quote', 'admin', 'Blog sample blockquote', '"We went from missing 30% of phone orders during rush hour to zero missed calls. The ROI was clear within the first week." | Marco Rossi | Owner, Bella Napoli, New York'),
    ('admin.blog.sample.block.h2impl', 'admin', 'Blog sample h2 implementation', 'Implementation Guide'),
    ('admin.blog.sample.block.callout2', 'admin', 'Blog sample callout 2', 'What you''ll need to get started | Your current menu'),
    ('admin.blog.sample.block.h2concerns', 'admin', 'Blog sample h2 concerns', 'Addressing Common Concerns'),
    ('admin.blog.sample.block.faq', 'admin', 'Blog sample FAQ', 'Will customers know they''re talking to an AI? | The AI is transparent about being an automated system.'),
    ('admin.blog.sample.block.h2conclusion', 'admin', 'Blog sample h2 conclusion', 'Conclusion'),
    ('admin.blog.sample.block.conclusion', 'admin', 'Blog sample conclusion', 'AI voice ordering has moved from a novelty to a necessity for competitive restaurants.'),
    ('admin.languages.form.codePlaceholder', 'admin', 'Language code input placeholder', 'e.g. fr'),
    ('admin.languages.form.namePlaceholder', 'admin', 'Language name input placeholder', 'e.g. French'),
    ('admin.languages.form.nativeNamePlaceholder', 'admin', 'Language native name input placeholder', 'e.g. Français'),
    ('admin.languages.form.flagPlaceholder', 'admin', 'Language flag emoji input placeholder', 'e.g. 🇫🇷')
  ON CONFLICT (key) DO NOTHING;

-- ─── PLANS TABLE — late-added columns ──────────────────────────
ALTER TABLE public.plans ADD COLUMN IF NOT EXISTS stripe_product_id TEXT;
ALTER TABLE public.plans ADD COLUMN IF NOT EXISTS description TEXT;
ALTER TABLE public.plans ADD COLUMN IF NOT EXISTS trial_days INTEGER DEFAULT 14;
ALTER TABLE public.plans ADD COLUMN IF NOT EXISTS slug TEXT;
UPDATE public.plans SET slug = LOWER(name) WHERE slug IS NULL;
CREATE UNIQUE INDEX IF NOT EXISTS idx_plans_slug ON public.plans(slug);

  -- Migration: rewrite Reservations translation strings that were seeded with single-brace
-- placeholders ({var}) to the double-brace convention ({{var}}) used by the t() helper.
-- Idempotent: matches only the exact legacy single-brace text.
WITH legacy(key, old_value, new_value) AS (
  VALUES
    ('tableBooking.summary.nextSub',     '{name} · {count} guests',                                                  '{{name}} · {{count}} guests'),
    ('tableBooking.summary.totalSub',    '{count} reservations',                                                     '{{count}} reservations'),
    ('tableBooking.summary.coversSub',   '{count} confirmed tables',                                                 '{{count}} confirmed tables'),
    ('tableBooking.summary.noShowsSub',  '{count} no-show{plural}',                                                  '{{count}} no-show{{plural}}'),
    ('tableBooking.summary.pendingSub',  '{count} pending',                                                          '{{count}} pending'),
    ('tableBooking.guestsCount',         '{count} guests',                                                           '{{count}} guests'),
    ('tableBooking.reminderSentTo',      'Reminder sent to {name}',                                                  'Reminder sent to {{name}}'),
    ('tableBooking.newReservationSub',   '{count} guests · {date} {time}',                                           '{{count}} guests · {{date}} {{time}}'),
    ('tableBooking.deleteConfirm',       'Are you sure you want to delete {count} booking{plural}? This cannot be undone.', 'Are you sure you want to delete {{count}} booking{{plural}}? This cannot be undone.'),
    ('common.selectedCount',             '{count} selected',                                                         '{{count}} selected')
)
UPDATE public.translation_keys tk
SET default_value = legacy.new_value
FROM legacy
WHERE tk.key = legacy.key AND tk.default_value = legacy.old_value;

WITH legacy(key, old_value, new_value) AS (
  VALUES
    ('tableBooking.summary.nextSub',     '{name} · {count} guests',                                                  '{{name}} · {{count}} guests'),
    ('tableBooking.summary.totalSub',    '{count} reservations',                                                     '{{count}} reservations'),
    ('tableBooking.summary.coversSub',   '{count} confirmed tables',                                                 '{{count}} confirmed tables'),
    ('tableBooking.summary.noShowsSub',  '{count} no-show{plural}',                                                  '{{count}} no-show{{plural}}'),
    ('tableBooking.summary.pendingSub',  '{count} pending',                                                          '{{count}} pending'),
    ('tableBooking.guestsCount',         '{count} guests',                                                           '{{count}} guests'),
    ('tableBooking.reminderSentTo',      'Reminder sent to {name}',                                                  'Reminder sent to {{name}}'),
    ('tableBooking.newReservationSub',   '{count} guests · {date} {time}',                                           '{{count}} guests · {{date}} {{time}}'),
    ('tableBooking.deleteConfirm',       'Are you sure you want to delete {count} booking{plural}? This cannot be undone.', 'Are you sure you want to delete {{count}} booking{{plural}}? This cannot be undone.'),
    ('common.selectedCount',             '{count} selected',                                                         '{{count}} selected')
)
UPDATE public.translations t
SET value = legacy.new_value, updated_at = now()
FROM public.translation_keys tk, legacy
WHERE t.key_id = tk.id
  AND tk.key = legacy.key
  AND t.value = legacy.old_value;

  -- Seed English translations from default_value (idempotent)
-- Only English is seeded; other languages remain empty until translated via the admin UI or AI translate.
INSERT INTO public.translations (lang_code, key_id, value)
SELECT 'en', tk.id, COALESCE(tk.default_value, '')
FROM public.translation_keys tk
WHERE NOT EXISTS (
  SELECT 1 FROM public.translations t2
  WHERE t2.key_id = tk.id AND t2.lang_code = 'en'
)
ON CONFLICT (lang_code, key_id) DO NOTHING;

-- Task #204: Email OTP, branded templates, outbox/digest worker
CREATE TABLE IF NOT EXISTS public.email_otps (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  email TEXT NOT NULL,
  code_hash TEXT NOT NULL,
  purpose TEXT NOT NULL,
  expires_at TIMESTAMPTZ NOT NULL,
  attempts INTEGER NOT NULL DEFAULT 0,
  last_resend_at TIMESTAMPTZ,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  consumed_at TIMESTAMPTZ
);
CREATE INDEX IF NOT EXISTS idx_email_otps_email_purpose ON public.email_otps(email, purpose, created_at DESC);

CREATE TABLE IF NOT EXISTS public.pending_signups (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  email TEXT NOT NULL UNIQUE,
  payload JSONB NOT NULL,
  expires_at TIMESTAMPTZ NOT NULL,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE TABLE IF NOT EXISTS public.email_templates (
  key TEXT PRIMARY KEY,
  subject TEXT NOT NULL,
  html TEXT NOT NULL,
  updated_by UUID,
  updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE TABLE IF NOT EXISTS public.email_outbox (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  restaurant_id UUID,
  branch_id UUID,
  recipient TEXT NOT NULL,
  template_key TEXT NOT NULL,
  payload JSONB NOT NULL DEFAULT '{}'::jsonb,
  channel TEXT NOT NULL DEFAULT 'immediate',
  kind TEXT,
  status TEXT NOT NULL DEFAULT 'queued',
  scheduled_for TIMESTAMPTZ NOT NULL DEFAULT now(),
  attempts INTEGER NOT NULL DEFAULT 0,
  last_error TEXT,
  sent_at TIMESTAMPTZ,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX IF NOT EXISTS idx_email_outbox_due ON public.email_outbox(status, scheduled_for);
CREATE INDEX IF NOT EXISTS idx_email_outbox_restaurant ON public.email_outbox(restaurant_id, scheduled_for, status);
CREATE INDEX IF NOT EXISTS idx_email_outbox_recipient ON public.email_outbox(recipient, created_at DESC);

ALTER TABLE public.restaurants ADD COLUMN IF NOT EXISTS notification_mode TEXT NOT NULL DEFAULT 'digest';

-- Task #212: WhatsApp Business — per-branch credentials & message log.
-- access_token / app_secret are AES-256-GCM encrypted before insert; the
-- other columns are public identifiers or non-secret handshake values.
CREATE TABLE IF NOT EXISTS public.branch_whatsapp_credentials (
  branch_id UUID PRIMARY KEY REFERENCES public.branches(id) ON DELETE CASCADE,
  restaurant_id UUID NOT NULL REFERENCES public.restaurants(id) ON DELETE CASCADE,
  phone_number_id TEXT NOT NULL,
  waba_id TEXT,
  display_name TEXT,
  access_token_encrypted TEXT NOT NULL,
  app_secret_encrypted TEXT,
  verify_token TEXT NOT NULL,
  is_active BOOLEAN NOT NULL DEFAULT true,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- Secure-by-default: when app_secret is not yet supplied (initial Meta
-- integration flow) the webhook accepts unsigned POSTs only until this
-- timestamp passes. Set to NOW()+24h on first save; cleared the moment
-- an app_secret is provided. After expiry, unsigned POSTs are rejected.
ALTER TABLE public.branch_whatsapp_credentials
  ADD COLUMN IF NOT EXISTS unsigned_grace_until TIMESTAMPTZ;
ALTER TABLE public.branch_whatsapp_credentials
  ADD COLUMN IF NOT EXISTS whatsapp_phone_number TEXT;
-- Task #473: Track when the template cache was last successfully synced for a
-- branch. Set even when Meta returns zero approved templates so the UI can
-- distinguish "never synced" from "synced but no approved templates yet".
ALTER TABLE public.branch_whatsapp_credentials
  ADD COLUMN IF NOT EXISTS templates_synced_at TIMESTAMPTZ;
CREATE INDEX IF NOT EXISTS idx_bwa_creds_restaurant ON public.branch_whatsapp_credentials(restaurant_id);
CREATE INDEX IF NOT EXISTS idx_bwa_creds_phone_number_id ON public.branch_whatsapp_credentials(phone_number_id);

CREATE TABLE IF NOT EXISTS public.whatsapp_message_log (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  branch_id UUID NOT NULL REFERENCES public.branches(id) ON DELETE CASCADE,
  restaurant_id UUID NOT NULL REFERENCES public.restaurants(id) ON DELETE CASCADE,
  conversation_id UUID,
  direction TEXT NOT NULL CHECK (direction IN ('inbound','outbound')),
  wa_message_id TEXT,
  from_e164 TEXT,
  to_e164 TEXT,
  body TEXT,
  message_type TEXT,
  status TEXT NOT NULL DEFAULT 'received',
  error TEXT,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- Idempotency: drop any inbound duplicate that re-uses the same wa_message_id
-- (Meta replays delivery on transient failures). Partial unique index lets us
-- log multiple outbound rows without a Meta id (we set wa_message_id NULL on
-- send-failed rows).
CREATE UNIQUE INDEX IF NOT EXISTS uniq_whatsapp_inbound_msg
  ON public.whatsapp_message_log (branch_id, wa_message_id)
  WHERE wa_message_id IS NOT NULL AND direction = 'inbound';
CREATE INDEX IF NOT EXISTS idx_whatsapp_log_branch_created
  ON public.whatsapp_message_log (branch_id, created_at DESC);
CREATE INDEX IF NOT EXISTS idx_whatsapp_log_restaurant_created
  ON public.whatsapp_message_log (restaurant_id, created_at DESC);

-- Task #472: WhatsApp template cache — local copy of Meta-approved HSMs synced
-- via the Graph API. Used by the Campaign wizard template picker.
CREATE TABLE IF NOT EXISTS public.whatsapp_templates (
  id            UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  restaurant_id UUID NOT NULL REFERENCES public.restaurants(id) ON DELETE CASCADE,
  branch_id     UUID NOT NULL REFERENCES public.branches(id)    ON DELETE CASCADE,
  name          TEXT NOT NULL,
  language      TEXT NOT NULL,
  status        TEXT NOT NULL DEFAULT 'APPROVED',
  components    JSONB NOT NULL DEFAULT '[]'::jsonb,
  synced_at     TIMESTAMPTZ NOT NULL DEFAULT now(),
  UNIQUE (branch_id, name, language)
);
CREATE INDEX IF NOT EXISTS idx_whatsapp_templates_branch
  ON public.whatsapp_templates (branch_id, name);
CREATE INDEX IF NOT EXISTS idx_whatsapp_templates_restaurant
  ON public.whatsapp_templates (restaurant_id);

-- ─── TASK #213: STOREFRONT (QR DINE-IN) ──────────────────────────────────────
-- Slugs for public storefront URLs
ALTER TABLE public.restaurants ADD COLUMN IF NOT EXISTS slug TEXT;
ALTER TABLE public.branches    ADD COLUMN IF NOT EXISTS slug TEXT;
CREATE UNIQUE INDEX IF NOT EXISTS idx_restaurants_slug ON public.restaurants(slug);
CREATE UNIQUE INDEX IF NOT EXISTS idx_branches_restaurant_slug ON public.branches(restaurant_id, slug);

-- Storefront flags on branches
ALTER TABLE public.branches ADD COLUMN IF NOT EXISTS storefront_enabled BOOLEAN NOT NULL DEFAULT false;
ALTER TABLE public.branches ADD COLUMN IF NOT EXISTS accepts_dine_in   BOOLEAN NOT NULL DEFAULT true;
ALTER TABLE public.branches ADD COLUMN IF NOT EXISTS accepts_takeaway  BOOLEAN NOT NULL DEFAULT true;
ALTER TABLE public.branches ADD COLUMN IF NOT EXISTS accepts_delivery  BOOLEAN NOT NULL DEFAULT false;
ALTER TABLE public.branches ADD COLUMN IF NOT EXISTS min_order_value   NUMERIC(10,2) NOT NULL DEFAULT 0;
ALTER TABLE public.branches ADD COLUMN IF NOT EXISTS qr_style_json     JSONB NOT NULL DEFAULT '{}'::jsonb;
ALTER TABLE public.branches ADD COLUMN IF NOT EXISTS storefront_message TEXT;

-- Per-table records (each printable QR)
CREATE TABLE IF NOT EXISTS public.restaurant_tables (
  id            UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  restaurant_id UUID NOT NULL REFERENCES public.restaurants(id) ON DELETE CASCADE,
  branch_id     UUID NOT NULL REFERENCES public.branches(id)    ON DELETE CASCADE,
  table_number  TEXT NOT NULL,
  label         TEXT,
  capacity      INTEGER NOT NULL DEFAULT 2,
  qr_style_json JSONB NOT NULL DEFAULT '{}'::jsonb,
  is_active     BOOLEAN NOT NULL DEFAULT true,
  created_at    TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at    TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE UNIQUE INDEX IF NOT EXISTS idx_tables_branch_number
  ON public.restaurant_tables (branch_id, table_number);
CREATE INDEX IF NOT EXISTS idx_tables_restaurant
  ON public.restaurant_tables (restaurant_id);
ALTER TABLE public.restaurant_tables ADD COLUMN IF NOT EXISTS zone TEXT;
CREATE INDEX IF NOT EXISTS idx_tables_branch_zone
  ON public.restaurant_tables (branch_id, zone) WHERE zone IS NOT NULL;

-- Order intake provenance / structured delivery address
DO $$ BEGIN
  IF NOT EXISTS (SELECT 1 FROM pg_type t JOIN pg_enum e ON t.oid = e.enumtypid
                 WHERE t.typname = 'channel_type' AND e.enumlabel = 'storefront') THEN
    ALTER TYPE public.channel_type ADD VALUE 'storefront';
  END IF;
END $$;
ALTER TABLE public.orders ADD COLUMN IF NOT EXISTS source TEXT;
ALTER TABLE public.orders ADD COLUMN IF NOT EXISTS delivery_address_json JSONB;
ALTER TABLE public.orders ADD COLUMN IF NOT EXISTS table_id UUID REFERENCES public.restaurant_tables(id) ON DELETE SET NULL;
CREATE INDEX IF NOT EXISTS idx_orders_source ON public.orders(source);
CREATE INDEX IF NOT EXISTS idx_orders_table  ON public.orders(table_id);

-- Auto-slug helper: lowercase, hyphenated, fall back to short uuid suffix on collision
CREATE OR REPLACE FUNCTION public._storefront_slugify(src TEXT) RETURNS TEXT AS $$
DECLARE
  s TEXT;
BEGIN
  s := lower(coalesce(src, ''));
  s := regexp_replace(s, '[^a-z0-9]+', '-', 'g');
  s := regexp_replace(s, '(^-+|-+$)', '', 'g');
  IF s = '' THEN s := 'r'; END IF;
  RETURN s;
END;
$$ LANGUAGE plpgsql IMMUTABLE;

-- Backfill restaurant slugs
DO $$
DECLARE rec RECORD; base TEXT; cand TEXT; n INT;
BEGIN
  FOR rec IN SELECT id, name FROM public.restaurants WHERE slug IS NULL OR slug = '' LOOP
    base := public._storefront_slugify(rec.name);
    cand := base;
    n := 1;
    WHILE EXISTS (SELECT 1 FROM public.restaurants WHERE slug = cand AND id <> rec.id) LOOP
      n := n + 1;
      cand := base || '-' || n;
    END LOOP;
    UPDATE public.restaurants SET slug = cand WHERE id = rec.id;
  END LOOP;
END $$;

-- Backfill branch slugs (unique within restaurant)
DO $$
DECLARE rec RECORD; base TEXT; cand TEXT; n INT;
BEGIN
  FOR rec IN SELECT id, name, restaurant_id FROM public.branches WHERE slug IS NULL OR slug = '' LOOP
    base := public._storefront_slugify(rec.name);
    cand := base;
    n := 1;
    WHILE EXISTS (SELECT 1 FROM public.branches WHERE slug = cand AND restaurant_id = rec.restaurant_id AND id <> rec.id) LOOP
      n := n + 1;
      cand := base || '-' || n;
    END LOOP;
    UPDATE public.branches SET slug = cand WHERE id = rec.id;
  END LOOP;
END $$;

-- ─── TASK #215: MARKETING AUTOMATION (WHATSAPP + EMAIL BROADCASTS) ───────────
-- Per-customer marketing prefs (kept on customers row to avoid an extra join
-- on every audience evaluation). opt_out flips on STOP keyword (WhatsApp) or
-- email unsubscribe link.
ALTER TABLE public.customers ADD COLUMN IF NOT EXISTS marketing_opt_out BOOLEAN NOT NULL DEFAULT false;
ALTER TABLE public.customers ADD COLUMN IF NOT EXISTS opt_out_at        TIMESTAMPTZ;
ALTER TABLE public.customers ADD COLUMN IF NOT EXISTS opt_out_reason    TEXT;
ALTER TABLE public.customers ADD COLUMN IF NOT EXISTS last_campaign_id  UUID;
ALTER TABLE public.customers ADD COLUMN IF NOT EXISTS last_campaign_at  TIMESTAMPTZ;
CREATE INDEX IF NOT EXISTS idx_customers_marketing_optout
  ON public.customers (restaurant_id, marketing_opt_out);

-- Saved audience segments (rules JSON; evaluated to a recipient list at
-- preview/launch time — segments are never materialized).
CREATE TABLE IF NOT EXISTS public.marketing_segments (
  id            UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  restaurant_id UUID NOT NULL REFERENCES public.restaurants(id) ON DELETE CASCADE,
  name          TEXT NOT NULL,
  description   TEXT,
  rules         JSONB NOT NULL DEFAULT '{}'::jsonb,
  created_by    UUID,
  created_at    TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at    TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX IF NOT EXISTS idx_marketing_segments_restaurant
  ON public.marketing_segments (restaurant_id, created_at DESC);

-- Campaigns. channel = 'email' | 'whatsapp'. status lifecycle:
-- draft → scheduled → sending → completed (or cancelled / failed).
CREATE TABLE IF NOT EXISTS public.marketing_campaigns (
  id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  restaurant_id   UUID NOT NULL REFERENCES public.restaurants(id) ON DELETE CASCADE,
  branch_id       UUID REFERENCES public.branches(id) ON DELETE SET NULL,
  segment_id      UUID REFERENCES public.marketing_segments(id) ON DELETE SET NULL,
  /* snapshot of segment rules at launch — segment edits don't retro-affect
     in-flight campaigns. */
  audience_rules  JSONB NOT NULL DEFAULT '{}'::jsonb,
  name            TEXT NOT NULL,
  channel         TEXT NOT NULL CHECK (channel IN ('email','whatsapp')),
  /* email payload */
  subject         TEXT,
  body_html       TEXT,
  /* whatsapp payload */
  template_name   TEXT,
  template_lang   TEXT,
  template_vars   JSONB DEFAULT '[]'::jsonb,
  /* scheduling */
  status          TEXT NOT NULL DEFAULT 'draft'
                    CHECK (status IN ('draft','scheduled','sending','completed','cancelled','failed')),
  scheduled_at    TIMESTAMPTZ,
  ignore_quiet_hours BOOLEAN NOT NULL DEFAULT false,
  /* aggregates (best-effort; report computes from deliveries when needed) */
  audience_count  INTEGER NOT NULL DEFAULT 0,
  sent_count      INTEGER NOT NULL DEFAULT 0,
  failed_count    INTEGER NOT NULL DEFAULT 0,
  opt_out_count   INTEGER NOT NULL DEFAULT 0,
  created_by      UUID,
  created_at      TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at      TIMESTAMPTZ NOT NULL DEFAULT now(),
  started_at      TIMESTAMPTZ,
  completed_at    TIMESTAMPTZ,
  last_error      TEXT
);
CREATE INDEX IF NOT EXISTS idx_marketing_campaigns_restaurant
  ON public.marketing_campaigns (restaurant_id, created_at DESC);
CREATE INDEX IF NOT EXISTS idx_marketing_campaigns_status
  ON public.marketing_campaigns (status, scheduled_at);

-- Per-recipient delivery rows (one per customer per campaign).
-- status: queued → sending → sent | failed | skipped (skipped = opted out
-- between fan-out and dispatch, or no contact info for the channel).
CREATE TABLE IF NOT EXISTS public.campaign_deliveries (
  id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  campaign_id     UUID NOT NULL REFERENCES public.marketing_campaigns(id) ON DELETE CASCADE,
  restaurant_id   UUID NOT NULL REFERENCES public.restaurants(id) ON DELETE CASCADE,
  customer_id     UUID REFERENCES public.customers(id) ON DELETE SET NULL,
  channel         TEXT NOT NULL CHECK (channel IN ('email','whatsapp')),
  recipient       TEXT NOT NULL, /* email or E.164 phone */
  status          TEXT NOT NULL DEFAULT 'queued'
                    CHECK (status IN ('queued','sending','sent','failed','skipped')),
  attempts        INTEGER NOT NULL DEFAULT 0,
  provider_message_id TEXT,
  last_error      TEXT,
  scheduled_for   TIMESTAMPTZ NOT NULL DEFAULT now(),
  sent_at         TIMESTAMPTZ,
  created_at      TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at      TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX IF NOT EXISTS idx_campaign_deliveries_campaign
  ON public.campaign_deliveries (campaign_id, status);
CREATE INDEX IF NOT EXISTS idx_campaign_deliveries_due
  ON public.campaign_deliveries (status, scheduled_for)
  WHERE status IN ('queued','sending');
CREATE UNIQUE INDEX IF NOT EXISTS idx_campaign_deliveries_unique
  ON public.campaign_deliveries (campaign_id, customer_id, recipient);

-- ============================================================================
-- Loyalty program — points, tiers, ledger (task #217)
-- ============================================================================

CREATE TABLE IF NOT EXISTS public.loyalty_settings (
  restaurant_id UUID PRIMARY KEY REFERENCES public.restaurants(id) ON DELETE CASCADE,
  enabled BOOLEAN NOT NULL DEFAULT false,
  earn_mode TEXT NOT NULL DEFAULT 'per_dollar' CHECK (earn_mode IN ('per_dollar','per_order','per_item')),
  earn_rate NUMERIC(10,4) NOT NULL DEFAULT 1,
  redeem_points_per_unit INTEGER NOT NULL DEFAULT 100,
  redeem_unit_value NUMERIC(10,2) NOT NULL DEFAULT 5,
  expiry_months INTEGER,
  min_redeem_points INTEGER NOT NULL DEFAULT 100,
  eligibility_order_types JSONB NOT NULL DEFAULT '["dine-in","takeaway","delivery"]'::jsonb,
  eligibility_channels JSONB NOT NULL DEFAULT '["chat","voice","whatsapp","storefront"]'::jsonb,
  tier_threshold_mode TEXT NOT NULL DEFAULT 'lifetime_points' CHECK (tier_threshold_mode IN ('lifetime_points','rolling_12mo_spend')),
  notify_on_earn BOOLEAN NOT NULL DEFAULT true,
  notify_on_tier_up BOOLEAN NOT NULL DEFAULT true,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- Task #229: notification toggles for points-earned / tier-up emails
ALTER TABLE public.loyalty_settings ADD COLUMN IF NOT EXISTS notify_on_earn BOOLEAN NOT NULL DEFAULT true;
ALTER TABLE public.loyalty_settings ADD COLUMN IF NOT EXISTS notify_on_tier_up BOOLEAN NOT NULL DEFAULT true;

CREATE TABLE IF NOT EXISTS public.loyalty_tiers (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  restaurant_id UUID NOT NULL REFERENCES public.restaurants(id) ON DELETE CASCADE,
  name TEXT NOT NULL,
  threshold NUMERIC(12,2) NOT NULL DEFAULT 0,
  earn_multiplier NUMERIC(6,3) NOT NULL DEFAULT 1,
  auto_discount_pct NUMERIC(5,2) NOT NULL DEFAULT 0,
  free_delivery BOOLEAN NOT NULL DEFAULT false,
  perks_text TEXT,
  badge_color TEXT,
  display_order INTEGER NOT NULL DEFAULT 0,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX IF NOT EXISTS idx_loyalty_tiers_restaurant ON public.loyalty_tiers(restaurant_id, threshold);

CREATE TABLE IF NOT EXISTS public.customer_points (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  restaurant_id UUID NOT NULL REFERENCES public.restaurants(id) ON DELETE CASCADE,
  customer_id UUID NOT NULL REFERENCES public.customers(id) ON DELETE CASCADE,
  balance INTEGER NOT NULL DEFAULT 0,
  lifetime_points INTEGER NOT NULL DEFAULT 0,
  rolling_12mo_spend NUMERIC(12,2) NOT NULL DEFAULT 0,
  tier_id UUID REFERENCES public.loyalty_tiers(id) ON DELETE SET NULL,
  updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  CONSTRAINT customer_points_unique UNIQUE (restaurant_id, customer_id)
);
CREATE INDEX IF NOT EXISTS idx_customer_points_restaurant ON public.customer_points(restaurant_id);

CREATE TABLE IF NOT EXISTS public.points_ledger (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  restaurant_id UUID NOT NULL REFERENCES public.restaurants(id) ON DELETE CASCADE,
  customer_id UUID NOT NULL REFERENCES public.customers(id) ON DELETE CASCADE,
  type TEXT NOT NULL CHECK (type IN ('earn','redeem','adjust','expire','reverse')),
  points INTEGER NOT NULL,
  order_id UUID REFERENCES public.orders(id) ON DELETE SET NULL,
  reason TEXT,
  expires_at TIMESTAMPTZ,
  created_by UUID REFERENCES public.users(id) ON DELETE SET NULL,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX IF NOT EXISTS idx_points_ledger_customer ON public.points_ledger(restaurant_id, customer_id, created_at DESC);
CREATE INDEX IF NOT EXISTS idx_points_ledger_expiry ON public.points_ledger(expires_at) WHERE type = 'earn' AND expires_at IS NOT NULL;
-- Prevent double-earning the same order
CREATE UNIQUE INDEX IF NOT EXISTS uq_points_ledger_earn_order ON public.points_ledger(order_id) WHERE type = 'earn' AND order_id IS NOT NULL;

-- Extend orders with loyalty fields
ALTER TABLE public.orders ADD COLUMN IF NOT EXISTS loyalty_points_earned INTEGER NOT NULL DEFAULT 0;
ALTER TABLE public.orders ADD COLUMN IF NOT EXISTS loyalty_points_redeemed INTEGER NOT NULL DEFAULT 0;
ALTER TABLE public.orders ADD COLUMN IF NOT EXISTS loyalty_discount NUMERIC(10,2) NOT NULL DEFAULT 0;

-- =============================================================================
-- Task #218: Gift cards (issuance, redemption, branded vouchers)
--   * gift_card_settings: 1 row per restaurant (denominations, expiry,
--                         branding template, redemption rule, stack flags)
--   * gift_cards:        each issued card (hashed code, balance, recipient,
--                         status, expiry); the same card works at every
--                         branch of the restaurant.
--   * gift_card_ledger:  audit row written for every balance change
--                         (issuance, redemption, void, refund).
-- =============================================================================
CREATE TABLE IF NOT EXISTS public.gift_card_settings (
  restaurant_id UUID PRIMARY KEY REFERENCES public.restaurants(id) ON DELETE CASCADE,
  enabled BOOLEAN NOT NULL DEFAULT true,
  denominations JSONB NOT NULL DEFAULT '[10,25,50,100]'::jsonb,
  custom_amount_enabled BOOLEAN NOT NULL DEFAULT true,
  custom_min NUMERIC(10,2) NOT NULL DEFAULT 5,
  custom_max NUMERIC(10,2) NOT NULL DEFAULT 500,
  currency TEXT,
  default_expiry_months INTEGER,
  code_length INTEGER NOT NULL DEFAULT 12,
  code_prefix TEXT NOT NULL DEFAULT 'GC',
  brand_logo_url TEXT,
  brand_primary_color TEXT NOT NULL DEFAULT '#f97316',
  message_template TEXT NOT NULL DEFAULT 'You have received a gift card!',
  email_from_line TEXT,
  redemption_rule TEXT NOT NULL DEFAULT 'subtotal'
    CHECK (redemption_rule IN ('subtotal','total')),
  stack_with_coupons BOOLEAN NOT NULL DEFAULT true,
  stack_with_loyalty BOOLEAN NOT NULL DEFAULT true,
  show_full_code_on_voucher BOOLEAN NOT NULL DEFAULT true,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE TABLE IF NOT EXISTS public.gift_cards (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  restaurant_id UUID NOT NULL REFERENCES public.restaurants(id) ON DELETE CASCADE,
  code_hash TEXT NOT NULL,
  code_last4 TEXT NOT NULL,
  code_prefix TEXT NOT NULL DEFAULT 'GC',
  original_amount NUMERIC(10,2) NOT NULL,
  balance NUMERIC(10,2) NOT NULL,
  currency TEXT NOT NULL,
  recipient_name TEXT NOT NULL,
  recipient_email TEXT,
  sender_name TEXT,
  sender_email TEXT,
  personal_message TEXT,
  status TEXT NOT NULL DEFAULT 'active'
    CHECK (status IN ('active','redeemed','expired','void')),
  issued_by_user_id UUID,
  issued_branch_id UUID REFERENCES public.branches(id) ON DELETE SET NULL,
  expires_at TIMESTAMPTZ,
  voided_at TIMESTAMPTZ,
  void_reason TEXT,
  last_used_at TIMESTAMPTZ,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE UNIQUE INDEX IF NOT EXISTS idx_gift_cards_code_hash ON public.gift_cards(code_hash);
CREATE INDEX IF NOT EXISTS idx_gift_cards_restaurant ON public.gift_cards(restaurant_id, created_at DESC);
CREATE INDEX IF NOT EXISTS idx_gift_cards_status ON public.gift_cards(restaurant_id, status);

CREATE TABLE IF NOT EXISTS public.gift_card_ledger (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  gift_card_id UUID NOT NULL REFERENCES public.gift_cards(id) ON DELETE CASCADE,
  restaurant_id UUID NOT NULL REFERENCES public.restaurants(id) ON DELETE CASCADE,
  branch_id UUID REFERENCES public.branches(id) ON DELETE SET NULL,
  order_id UUID REFERENCES public.orders(id) ON DELETE SET NULL,
  entry_type TEXT NOT NULL
    CHECK (entry_type IN ('issuance','redemption','void','refund')),
  amount NUMERIC(10,2) NOT NULL,
  balance_after NUMERIC(10,2) NOT NULL,
  note TEXT,
  by_user_id UUID,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX IF NOT EXISTS idx_gift_card_ledger_card ON public.gift_card_ledger(gift_card_id, created_at DESC);
CREATE INDEX IF NOT EXISTS idx_gift_card_ledger_restaurant ON public.gift_card_ledger(restaurant_id, created_at DESC);
CREATE INDEX IF NOT EXISTS idx_gift_card_ledger_order ON public.gift_card_ledger(order_id);

-- Track gift-card amount applied to each order (so receipts can show it)
ALTER TABLE public.orders ADD COLUMN IF NOT EXISTS gift_card_applied NUMERIC(10,2) NOT NULL DEFAULT 0;
ALTER TABLE public.orders ADD COLUMN IF NOT EXISTS gift_card_id UUID REFERENCES public.gift_cards(id) ON DELETE SET NULL;

-- ─── TASK #214: COUPONS & DISCOUNT CODES (BRANCH-SCOPED) ─────────────────────
CREATE TABLE IF NOT EXISTS public.coupons (
  id                       UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  restaurant_id            UUID NOT NULL REFERENCES public.restaurants(id) ON DELETE CASCADE,
  branch_id                UUID NOT NULL REFERENCES public.branches(id)    ON DELETE CASCADE,
  code                     TEXT NOT NULL,
  display_name             TEXT,
  description              TEXT,
  -- 'percent' | 'fixed' | 'bogo'
  type                     TEXT NOT NULL,
  value                    NUMERIC(10,2) NOT NULL DEFAULT 0,
  -- BOGO config: {buy_target_type, buy_target_id, get_target_type, get_target_id, get_discount_kind, get_discount_percent}
  bogo_config              JSONB NOT NULL DEFAULT '{}'::jsonb,
  valid_from               TIMESTAMPTZ,
  valid_until              TIMESTAMPTZ,
  total_redemption_cap     INTEGER,
  per_customer_cap         INTEGER,
  min_order_value          NUMERIC(10,2) NOT NULL DEFAULT 0,
  applicable_order_types   TEXT[] NOT NULL DEFAULT ARRAY['dine-in','takeaway','delivery']::text[],
  applicable_channels      TEXT[] NOT NULL DEFAULT ARRAY['chat','whatsapp','storefront']::text[],
  applicable_branches      UUID[] NOT NULL DEFAULT ARRAY[]::uuid[],
  stack_with_loyalty       BOOLEAN NOT NULL DEFAULT true,
  stack_with_gift_card     BOOLEAN NOT NULL DEFAULT true,
  -- 'active' | 'archived'
  status                   TEXT NOT NULL DEFAULT 'active',
  created_at               TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at               TIMESTAMPTZ NOT NULL DEFAULT now(),
  CHECK (type IN ('percent','fixed','bogo')),
  CHECK (status IN ('active','archived'))
);
-- Code is case-insensitive unique within branch
CREATE UNIQUE INDEX IF NOT EXISTS uniq_coupons_branch_code
  ON public.coupons (branch_id, lower(code));
CREATE INDEX IF NOT EXISTS idx_coupons_restaurant ON public.coupons(restaurant_id);
CREATE INDEX IF NOT EXISTS idx_coupons_status     ON public.coupons(status);

CREATE TABLE IF NOT EXISTS public.coupon_redemptions (
  id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  coupon_id       UUID NOT NULL REFERENCES public.coupons(id)  ON DELETE CASCADE,
  order_id        UUID REFERENCES public.orders(id)            ON DELETE SET NULL,
  restaurant_id   UUID NOT NULL REFERENCES public.restaurants(id) ON DELETE CASCADE,
  branch_id       UUID NOT NULL REFERENCES public.branches(id)    ON DELETE CASCADE,
  customer_id     UUID REFERENCES public.customers(id)         ON DELETE SET NULL,
  channel         TEXT NOT NULL,
  discount_amount NUMERIC(10,2) NOT NULL DEFAULT 0,
  created_at      TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX IF NOT EXISTS idx_coupon_redemptions_coupon
  ON public.coupon_redemptions(coupon_id, created_at DESC);
CREATE INDEX IF NOT EXISTS idx_coupon_redemptions_branch
  ON public.coupon_redemptions(branch_id, created_at DESC);
CREATE INDEX IF NOT EXISTS idx_coupon_redemptions_customer
  ON public.coupon_redemptions(coupon_id, customer_id) WHERE customer_id IS NOT NULL;

-- Track applied coupon on each order
ALTER TABLE public.orders ADD COLUMN IF NOT EXISTS coupon_id UUID REFERENCES public.coupons(id) ON DELETE SET NULL;
ALTER TABLE public.orders ADD COLUMN IF NOT EXISTS coupon_code TEXT;
ALTER TABLE public.orders ADD COLUMN IF NOT EXISTS discount_amount NUMERIC(10,2) NOT NULL DEFAULT 0;
CREATE INDEX IF NOT EXISTS idx_orders_coupon ON public.orders(coupon_id) WHERE coupon_id IS NOT NULL;

-- ─── Task #238: Marketing bug-fix schema (additive, idempotent) ─────────────

-- Customer lifetime aggregate timestamp (visits/spend columns already exist)
ALTER TABLE public.customers ADD COLUMN IF NOT EXISTS last_order_at TIMESTAMPTZ;
CREATE INDEX IF NOT EXISTS idx_customers_last_order_at
  ON public.customers (restaurant_id, last_order_at DESC NULLS LAST);

-- Task #323: track every interaction touchpoint (voice / chat / whatsapp).
-- Bumped on every find-or-create-by-phone match so the personalization
-- layer can answer "when did we last hear from this caller?".
ALTER TABLE public.customers ADD COLUMN IF NOT EXISTS last_seen_at TIMESTAMPTZ;

-- Group sibling marketing campaigns (e.g. an Email + WhatsApp pair launched
-- together) so the operator can view a combined report.
ALTER TABLE public.marketing_campaigns ADD COLUMN IF NOT EXISTS launch_group_id UUID;
CREATE INDEX IF NOT EXISTS idx_marketing_campaigns_launch_group
  ON public.marketing_campaigns (launch_group_id) WHERE launch_group_id IS NOT NULL;

-- Task #239: when a saved audience is deleted while a non-completed campaign
-- references it, the campaign keeps its snapshotted audience_rules but the
-- segment_id link disappears. Track the deletion timestamp so the campaigns
-- list can surface a "segment deleted" badge instead of failing silently.
ALTER TABLE public.marketing_campaigns ADD COLUMN IF NOT EXISTS segment_deleted_at TIMESTAMPTZ;

-- Task #240: per-campaign throttle controls. NULL = no per-campaign cap;
-- the existing per-(branch, channel) batch cap still applies. The dispatcher
-- enforces both, taking the stricter of the two before claiming work.
ALTER TABLE public.marketing_campaigns ADD COLUMN IF NOT EXISTS max_per_minute INTEGER;
ALTER TABLE public.marketing_campaigns ADD COLUMN IF NOT EXISTS max_per_hour   INTEGER;

-- Per-branch quiet hours overrides (defaults preserve existing 22-08 behavior)
ALTER TABLE public.branches ADD COLUMN IF NOT EXISTS quiet_hours_enabled BOOLEAN NOT NULL DEFAULT true;
ALTER TABLE public.branches ADD COLUMN IF NOT EXISTS quiet_hours_start INTEGER NOT NULL DEFAULT 22;
ALTER TABLE public.branches ADD COLUMN IF NOT EXISTS quiet_hours_end   INTEGER NOT NULL DEFAULT 8;

-- Flag to indicate the branch name was manually customised by the user.
-- When true, cascading restaurant renames will leave this branch name unchanged.
ALTER TABLE public.branches ADD COLUMN IF NOT EXISTS name_customized BOOLEAN NOT NULL DEFAULT false;
DO $$ BEGIN
  -- Defensive bounds — silently clamp any pre-existing out-of-range value.
  UPDATE public.branches SET quiet_hours_start = LEAST(GREATEST(quiet_hours_start, 0), 23)
    WHERE quiet_hours_start < 0 OR quiet_hours_start > 23;
  UPDATE public.branches SET quiet_hours_end   = LEAST(GREATEST(quiet_hours_end,   0), 23)
    WHERE quiet_hours_end   < 0 OR quiet_hours_end   > 23;
END $$;

-- One-shot backfill for total_visits / total_spend / last_order_at from the
-- orders pipeline. Idempotent: only updates customers whose stored aggregates
-- are out of sync with the live computation, so re-running on each boot is
-- effectively free once everything matches.
DO $$ BEGIN
  IF EXISTS (
    SELECT 1 FROM information_schema.columns
    WHERE table_schema='public' AND table_name='orders' AND column_name='customer_id'
  ) THEN
    UPDATE public.customers c SET
      total_visits  = sub.visits,
      total_spend   = sub.spend,
      last_order_at = sub.last_at,
      updated_at    = NOW()
    FROM (
      SELECT o.customer_id, o.restaurant_id,
             COUNT(*)::int       AS visits,
             COALESCE(SUM(total),0) AS spend,
             MAX(o.created_at)   AS last_at
      FROM public.orders o
      WHERE o.status IN ('completed','delivered') AND o.customer_id IS NOT NULL
      GROUP BY o.customer_id, o.restaurant_id
    ) sub
    WHERE sub.customer_id  = c.id
      AND sub.restaurant_id = c.restaurant_id
      AND (
            COALESCE(c.total_visits, 0) IS DISTINCT FROM sub.visits
         OR COALESCE(c.total_spend,  0) IS DISTINCT FROM sub.spend
         OR c.last_order_at            IS DISTINCT FROM sub.last_at
      );
  END IF;
END $$;

-- Task #253: branch isolation for marketing.
-- Saved audiences were restaurant-scoped, so a branch-scoped staff user could
-- list / edit / target every other branch's segments. Add a nullable branch_id
-- so segments may be either restaurant-wide (NULL — owners only) or pinned
-- to a specific branch (visible to that branch's staff only). NULL preserves
-- the historical behaviour for any pre-existing rows.
ALTER TABLE public.marketing_segments
  ADD COLUMN IF NOT EXISTS branch_id UUID REFERENCES public.branches(id) ON DELETE SET NULL;
CREATE INDEX IF NOT EXISTS idx_marketing_segments_branch
  ON public.marketing_segments (restaurant_id, branch_id);

-- Task #287: unique audience name per restaurant (case-insensitive).
-- The new Edit button (#280) made it trivial to rename an audience to clash
-- with another. Defuse pre-existing duplicates first by appending the row's
-- short id suffix so the unique index can be created cleanly. Re-runnable.
WITH dups AS (
  SELECT id,
         row_number() OVER (
           PARTITION BY restaurant_id, lower(name)
           ORDER BY created_at, id
         ) AS rn
    FROM public.marketing_segments
)
UPDATE public.marketing_segments ms
   SET name = ms.name || ' (' || substr(ms.id::text, 1, 6) || ')'
  FROM dups
 WHERE ms.id = dups.id AND dups.rn > 1;

CREATE UNIQUE INDEX IF NOT EXISTS uniq_marketing_segments_restaurant_name
  ON public.marketing_segments (restaurant_id, lower(name));

-- ============================================================================
-- TASK #290: RESERVATION SYSTEM V2
--
-- Adds booking duration / buffer, real start_at / end_at timestamps, a real
-- foreign key to restaurant_tables, and a Postgres EXCLUDE USING gist
-- constraint that makes overlapping bookings on the same table impossible at
-- the database level (race-free, not application-checked).
-- ============================================================================

-- Per-restaurant defaults: how long a reservation lasts and how much buffer
-- (turnover time) we leave between sittings on the same table.
ALTER TABLE public.restaurants
  ADD COLUMN IF NOT EXISTS default_booking_duration_min INTEGER NOT NULL DEFAULT 90;
ALTER TABLE public.restaurants
  ADD COLUMN IF NOT EXISTS default_booking_buffer_min   INTEGER NOT NULL DEFAULT 15;

-- New booking columns. start_at / end_at are the source of truth for
-- occupancy windows (TIMESTAMPTZ — restaurant-local times converted to UTC
-- on the way in). duration_min / buffer_min preserve the inputs.
ALTER TABLE public.bookings ADD COLUMN IF NOT EXISTS start_at     TIMESTAMPTZ;
ALTER TABLE public.bookings ADD COLUMN IF NOT EXISTS end_at       TIMESTAMPTZ;
ALTER TABLE public.bookings ADD COLUMN IF NOT EXISTS duration_min INTEGER NOT NULL DEFAULT 90;
ALTER TABLE public.bookings ADD COLUMN IF NOT EXISTS buffer_min   INTEGER NOT NULL DEFAULT 15;
ALTER TABLE public.bookings
  ADD COLUMN IF NOT EXISTS table_id UUID REFERENCES public.restaurant_tables(id) ON DELETE SET NULL;

-- An earlier iteration of this migration created start_at / end_at as
-- TIMESTAMP (without time zone). Promote them to TIMESTAMPTZ if needed.
-- Existing values are reinterpreted as UTC, which matches how the service
-- writes them via Date.toISOString().
DO $$ BEGIN
  IF EXISTS (
    SELECT 1 FROM information_schema.columns
     WHERE table_schema = 'public' AND table_name = 'bookings'
       AND column_name = 'start_at' AND data_type = 'timestamp without time zone'
  ) THEN
    ALTER TABLE public.bookings DROP CONSTRAINT IF EXISTS no_table_overlap;
    ALTER TABLE public.bookings
      ALTER COLUMN start_at TYPE TIMESTAMPTZ USING start_at AT TIME ZONE 'UTC';
    ALTER TABLE public.bookings
      ALTER COLUMN end_at   TYPE TIMESTAMPTZ USING end_at   AT TIME ZONE 'UTC';
  END IF;
END $$;

CREATE INDEX IF NOT EXISTS idx_bookings_start_at        ON public.bookings(start_at);
CREATE INDEX IF NOT EXISTS idx_bookings_table_id        ON public.bookings(table_id);
CREATE INDEX IF NOT EXISTS idx_bookings_branch_start_at ON public.bookings(branch_id, start_at);

-- Best-effort backfill for legacy rows that only carry booking_date +
-- booking_time. Handles both 24-hour ("19:00", "19:00:00") and 12-hour
-- ("7:00 PM", "7:00pm") formats; rows with un-parseable times stay NULL
-- and simply don't participate in the overlap constraint.
UPDATE public.bookings
   SET start_at = CASE
         WHEN booking_time ~ '^[0-9]{1,2}:[0-9]{2}(:[0-9]{2})?$'
           THEN (booking_date::text || ' ' || booking_time)::timestamptz
         WHEN booking_time ~* '^[0-9]{1,2}:[0-9]{2}\s*(am|pm)$'
           THEN to_timestamp(
                  booking_date::text || ' ' || upper(regexp_replace(booking_time, '\s+', '', 'g')),
                  'YYYY-MM-DD HH12:MIAM'
                )::timestamptz
         ELSE NULL
       END,
       end_at = CASE
         WHEN booking_time ~ '^[0-9]{1,2}:[0-9]{2}(:[0-9]{2})?$'
           THEN (booking_date::text || ' ' || booking_time)::timestamptz
                + make_interval(mins => COALESCE(duration_min, 90))
         WHEN booking_time ~* '^[0-9]{1,2}:[0-9]{2}\s*(am|pm)$'
           THEN to_timestamp(
                  booking_date::text || ' ' || upper(regexp_replace(booking_time, '\s+', '', 'g')),
                  'YYYY-MM-DD HH12:MIAM'
                )::timestamptz + make_interval(mins => COALESCE(duration_min, 90))
         ELSE NULL
       END
 WHERE start_at IS NULL
   AND booking_date IS NOT NULL
   AND booking_time IS NOT NULL;

-- btree_gist lets us combine UUID equality with tstzrange overlap in a
-- single EXCLUDE constraint. The buffered range is built by an IMMUTABLE
-- wrapper so the index expression is index-safe even though the underlying
-- (timestamptz + interval) operator is only marked STABLE in pg_proc.
CREATE EXTENSION IF NOT EXISTS btree_gist;

CREATE OR REPLACE FUNCTION public.bookings_window(
  s timestamptz, e timestamptz, buf integer
) RETURNS tstzrange AS $$
  SELECT tstzrange(s, e + make_interval(mins => buf), '[)')
$$ LANGUAGE sql IMMUTABLE;

DO $$ BEGIN
  IF NOT EXISTS (
    SELECT 1 FROM pg_constraint WHERE conname = 'no_table_overlap'
  ) THEN
    ALTER TABLE public.bookings
      ADD CONSTRAINT no_table_overlap
      EXCLUDE USING gist (
        table_id WITH =,
        public.bookings_window(start_at, end_at, buffer_min) WITH &&
      )
      WHERE (
        table_id IS NOT NULL
        AND status NOT IN ('cancelled', 'noshow')
        AND start_at IS NOT NULL
        AND end_at IS NOT NULL
      );
  END IF;
EXCEPTION
  WHEN duplicate_object THEN NULL;
  WHEN duplicate_table  THEN NULL;
END $$;

-- ============================================================================
-- Task #291: Advanced menu availability
--   * Real-time stock toggle + optional finite stock_count
--   * Per-item and per-category time-based schedules (JSONB array of windows)
--   * Branch-level item availability via override table
-- All migrations idempotent. No drizzle-kit / db:push.
-- ============================================================================

ALTER TABLE public.menu_items
  ADD COLUMN IF NOT EXISTS is_in_stock BOOLEAN NOT NULL DEFAULT true;
ALTER TABLE public.menu_items
  ADD COLUMN IF NOT EXISTS stock_count INTEGER;
ALTER TABLE public.menu_items
  ADD COLUMN IF NOT EXISTS schedule JSONB;

ALTER TABLE public.menu_categories
  ADD COLUMN IF NOT EXISTS schedule JSONB;

CREATE TABLE IF NOT EXISTS public.menu_item_branch_availability (
  menu_item_id UUID NOT NULL REFERENCES public.menu_items(id) ON DELETE CASCADE,
  branch_id    UUID NOT NULL REFERENCES public.branches(id)   ON DELETE CASCADE,
  is_available BOOLEAN NOT NULL DEFAULT true,
  created_at   TIMESTAMPTZ DEFAULT now(),
  updated_at   TIMESTAMPTZ DEFAULT now(),
  PRIMARY KEY (menu_item_id, branch_id)
);

CREATE INDEX IF NOT EXISTS idx_mibav_branch_id
  ON public.menu_item_branch_availability (branch_id);
CREATE INDEX IF NOT EXISTS idx_menu_items_in_stock
  ON public.menu_items (restaurant_id, is_in_stock) WHERE is_in_stock = false;

-- ============================================================================
-- Task #295: Inventory low-stock alerts + daily auto-reset
--   * low_stock_threshold:     when stock_count crosses this value, fire an
--                              owner alert (email + in-app), at most once per
--                              24h (last_low_stock_alert_at gates re-fires).
--   * daily_reset_count:       at local midnight, reset stock_count back to
--                              this target. NULL = no daily reset.
--   * last_reset_at:           per-item stamp so the worker only resets each
--                              item once per local day.
--   * last_low_stock_alert_at: rate-limit owner-facing low-stock alerts.
--   * auto_disabled_at_zero:   true when is_in_stock=false was flipped by the
--                              decrement path (stock hit 0). Reset clears the
--                              flag and re-enables only items it had auto-
--                              disabled — manual "off" stays off.
-- All migrations idempotent. No drizzle-kit / db:push.
-- ============================================================================
ALTER TABLE public.menu_items
  ADD COLUMN IF NOT EXISTS low_stock_threshold INTEGER;
ALTER TABLE public.menu_items
  ADD COLUMN IF NOT EXISTS daily_reset_count INTEGER;
ALTER TABLE public.menu_items
  ADD COLUMN IF NOT EXISTS last_reset_at TIMESTAMPTZ;
ALTER TABLE public.menu_items
  ADD COLUMN IF NOT EXISTS last_low_stock_alert_at TIMESTAMPTZ;
ALTER TABLE public.menu_items
  ADD COLUMN IF NOT EXISTS auto_disabled_at_zero BOOLEAN NOT NULL DEFAULT false;

CREATE INDEX IF NOT EXISTS idx_menu_items_daily_reset
  ON public.menu_items (restaurant_id)
  WHERE daily_reset_count IS NOT NULL;

INSERT INTO public.translation_keys (key, category, description, default_value) VALUES
    ('menuManagement.lowStockThreshold',     'menuManagement', 'Low-stock threshold field', 'Low-stock threshold'),
    ('menuManagement.lowStockThresholdHelp', 'menuManagement', 'Threshold help text',       'Email + dashboard alert when stock drops to this value. Leave blank to disable.'),
    ('menuManagement.dailyResetCount',       'menuManagement', 'Daily reset target field',  'Daily reset target'),
    ('menuManagement.dailyResetCountHelp',   'menuManagement', 'Daily reset help text',     'At local midnight, stock resets to this number. Leave blank to disable.'),
    ('menuManagement.thresholdAboveReset',   'menuManagement', 'Threshold validation',      'Low-stock threshold must be at most the daily reset target.'),
    ('menuManagement.inventory',             'menuManagement', 'Inventory section header',  'Inventory'),
    ('menuManagement.thresholdShort',        'menuManagement', 'Inline threshold label',    'Alert ≤'),
    ('menuManagement.dailyResetShort',       'menuManagement', 'Inline daily-reset label',  'Daily reset'),
    ('menuManagement.lastResetAt',           'menuManagement', 'Last-reset row label',      'Last reset'),
    ('menuManagement.lastResetNever',        'menuManagement', 'Never reset placeholder',   'Never'),
    ('menuManagement.lowStockNotificationTitle', 'menuManagement', 'Low-stock notif title', 'Low stock: {{itemName}}'),
    ('menuManagement.lowStockNotificationBody',  'menuManagement', 'Low-stock notif body',  '{{itemName}} has {{stockRemaining}} left (alert at {{threshold}}).'),
    ('menuManagement.soldOutNotificationTitle',  'menuManagement', 'Sold-out notif title',  'Sold out: {{itemName}}'),
    ('menuManagement.soldOutNotificationBody',   'menuManagement', 'Sold-out notif body',   '{{itemName}} is now sold out. Restock or 86 the item.'),
    ('menuManagement.defaultLowStockThreshold',     'menuManagement', 'Default threshold field', 'Default low-stock threshold'),
    ('menuManagement.defaultLowStockThresholdHelp', 'menuManagement', 'Default threshold help', 'Used for items that do not set their own threshold. Set to 0 to disable defaults.'),
    ('restaurantSettings.profile.defaultLowStockThresholdLabel', 'restaurantSettings', 'Settings: default low-stock threshold label', 'Default low-stock alert threshold'),
    ('restaurantSettings.profile.defaultLowStockThresholdHint',  'restaurantSettings', 'Settings: default low-stock threshold hint',  'Used for items without a custom threshold. Set to 0 to disable low-stock alerts by default.')
  ON CONFLICT (key) DO NOTHING;

-- ============================================================================
-- Task #298: low-stock + sold-out alerts to branch managers
--   * restaurants.default_low_stock_threshold: fallback threshold when an
--     item leaves low_stock_threshold NULL. Default 5. Set to 0 to disable
--     fallback alerts globally.
--   * menu_items.last_sold_out_alert_at: separate 24h cooldown for the new
--     "sold out" alert that fires whenever stock_count crosses 0 regardless
--     of the configured threshold.
-- All migrations idempotent.
-- ============================================================================
ALTER TABLE public.restaurants
  ADD COLUMN IF NOT EXISTS default_low_stock_threshold INTEGER NOT NULL DEFAULT 5;
ALTER TABLE public.menu_items
  ADD COLUMN IF NOT EXISTS last_sold_out_alert_at TIMESTAMPTZ;

-- ============================================================================
-- Task #296: Public REST API v1 — api_keys table
--   Stores hashed bearer tokens (rsk_<64 hex>) issued by /api/api-keys.
--   key_hash is sha256(rawKey) — the raw token is shown to the operator
--   exactly once at creation time and never persisted.
--   calls_this_month resets when current_period_start rolls into a new month;
--   the reset is performed inline by the withApiKey middleware so we don't
--   need a cron job.
-- ============================================================================
CREATE TABLE IF NOT EXISTS public.api_keys (
  id                    UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  restaurant_id         UUID NOT NULL REFERENCES public.restaurants(id) ON DELETE CASCADE,
  name                  TEXT NOT NULL,
  key_hash              TEXT NOT NULL,
  key_preview           TEXT NOT NULL,
  permissions           JSONB NOT NULL DEFAULT '[]'::jsonb,
  status                TEXT NOT NULL DEFAULT 'active',
  calls_this_month      INTEGER NOT NULL DEFAULT 0,
  current_period_start  TIMESTAMPTZ,
  last_used_at          TIMESTAMPTZ,
  created_at            TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at            TIMESTAMPTZ NOT NULL DEFAULT now()
);
ALTER TABLE public.api_keys ADD COLUMN IF NOT EXISTS current_period_start TIMESTAMPTZ;
ALTER TABLE public.api_keys ADD COLUMN IF NOT EXISTS updated_at           TIMESTAMPTZ NOT NULL DEFAULT now();
CREATE UNIQUE INDEX IF NOT EXISTS idx_api_keys_key_hash      ON public.api_keys (key_hash);
CREATE INDEX        IF NOT EXISTS idx_api_keys_restaurant_id ON public.api_keys (restaurant_id);
CREATE INDEX        IF NOT EXISTS idx_api_keys_status        ON public.api_keys (status) WHERE status = 'active';

-- ─── MENU AVAILABILITY AUDIT LOG (Task #299) ──────────────
-- Tracks every change to availability-affecting fields on menu_items
-- (is_in_stock, stock_count, schedule, is_available), menu_categories
-- (schedule, is_active) and per-branch overrides
-- (menu_item_branch_availability). One row per (entity, field) change so
-- "why was X unavailable last night?" can be answered without diffing
-- whole records. Foreign keys are intentionally omitted so we never lose
-- history if a row is later deleted.
CREATE TABLE IF NOT EXISTS public.menu_audit_log (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  restaurant_id UUID NOT NULL,
  branch_id UUID,
  menu_item_id UUID,
  menu_category_id UUID,
  actor_user_id UUID,
  actor_email TEXT,
  action TEXT NOT NULL,
  field TEXT,
  before_value JSONB,
  after_value JSONB,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX IF NOT EXISTS idx_menu_audit_log_item        ON public.menu_audit_log(menu_item_id, created_at DESC);
CREATE INDEX IF NOT EXISTS idx_menu_audit_log_category    ON public.menu_audit_log(menu_category_id, created_at DESC);
CREATE INDEX IF NOT EXISTS idx_menu_audit_log_restaurant  ON public.menu_audit_log(restaurant_id, created_at DESC);

-- ============================================================================
-- Missing translation keys audit — 788 keys used in source but absent from DB
-- All namespaces: admin, analytics, landing, marketing, storefront, etc.
-- English values auto-seeded from default_value by the existing query above.
-- ============================================================================
INSERT INTO public.translation_keys (key, category, description, default_value) VALUES
('admin.bookings.adminNote', 'admin', 'admin.bookings.adminNote', 'Read-only view of all table bookings across all restaurants'),
('admin.bookings.aiNotes', 'admin', 'admin.bookings.aiNotes', 'AI Notes'),
('admin.bookings.cancelled', 'admin', 'admin.bookings.cancelled', 'Cancelled'),
('admin.bookings.confidence', 'admin', 'admin.bookings.confidence', 'Confidence'),
('admin.bookings.confirmed', 'admin', 'admin.bookings.confirmed', 'Confirmed'),
('admin.bookings.dateTime', 'admin', 'admin.bookings.dateTime', 'Date & Time'),
('admin.bookings.dietaryNeeds', 'admin', 'admin.bookings.dietaryNeeds', 'Dietary Needs'),
('admin.bookings.guest', 'admin', 'admin.bookings.guest', 'Guest'),
('admin.bookings.guests', 'admin', 'admin.bookings.guests', 'guests'),
('admin.bookings.metadata', 'admin', 'admin.bookings.metadata', 'Metadata'),
('admin.bookings.noBookings', 'admin', 'admin.bookings.noBookings', 'No bookings found'),
('admin.bookings.noShow', 'admin', 'admin.bookings.noShow', 'No-shows'),
('admin.bookings.notes', 'admin', 'admin.bookings.notes', 'Notes'),
('admin.bookings.occasion', 'admin', 'admin.bookings.occasion', 'Occasion'),
('admin.bookings.of', 'admin', 'admin.bookings.of', 'of'),
('admin.bookings.page', 'admin', 'admin.bookings.page', 'Page'),
('admin.bookings.pageDesc', 'admin', 'admin.bookings.pageDesc', 'All reservations across every restaurant and branch'),
('admin.bookings.pageTitle', 'admin', 'admin.bookings.pageTitle', 'Table Bookings'),
('admin.bookings.partySize', 'admin', 'admin.bookings.partySize', 'Party Size'),
('admin.bookings.pending', 'admin', 'admin.bookings.pending', 'Pending'),
('admin.bookings.reservationDetails', 'admin', 'admin.bookings.reservationDetails', 'Reservation Details'),
('admin.bookings.restaurant', 'admin', 'admin.bookings.restaurant', 'Restaurant'),
('admin.bookings.results', 'admin', 'admin.bookings.results', 'bookings'),
('admin.bookings.searchPlaceholder', 'admin', 'admin.bookings.searchPlaceholder', 'Search by guest name, phone, or email…'),
('admin.bookings.seated', 'admin', 'admin.bookings.seated', 'Seated'),
('admin.bookings.specialRequests', 'admin', 'admin.bookings.specialRequests', 'Special Requests'),
('admin.bookings.table', 'admin', 'admin.bookings.table', 'Table'),
('admin.bookings.today', 'admin', 'admin.bookings.today', 'Today'),
('admin.bookings.total', 'admin', 'admin.bookings.total', 'Total'),
('admin.bookings.zone', 'admin', 'admin.bookings.zone', 'Zone'),
('admin.branding.clearFavicon', 'admin', 'admin.branding.clearFavicon', 'Clear favicon (use logo)'),
('admin.branding.clearFaviconHint', 'admin', 'admin.branding.clearFaviconHint', 'Removes the custom favicon so the platform logo is used in browser tabs'),
('admin.branding.marketingUrl', 'admin', 'admin.branding.marketingUrl', 'Marketing Site URL'),
('admin.branding.marketingUrlHint', 'admin', 'admin.branding.marketingUrlHint', 'Used by the '),
('admin.branding.marketingUrlPlaceholder', 'admin', 'admin.branding.marketingUrlPlaceholder', 'https://your-site.com'),
('admin.branding.supportEmail', 'admin', 'admin.branding.supportEmail', 'Support Email'),
('admin.branding.supportEmailHint', 'admin', 'admin.branding.supportEmailHint', 'Used in legal pages, support links, and outbound email '),
('admin.branding.supportEmailPlaceholder', 'admin', 'admin.branding.supportEmailPlaceholder', 'support@example.com'),
('admin.demoMode.description', 'admin', 'admin.demoMode.description', 'Show public /demo and demo discoverability (login hints, home CTA, self-bootstrap seeding).'),
('admin.demoMode.envWriteDisabled', 'admin', 'admin.demoMode.envWriteDisabled', 'Editing the .env file is disabled on this deployment (DISABLE_ENV_WRITE=1).'),
('admin.demoMode.failedToSave', 'admin', 'admin.demoMode.failedToSave', 'Failed to update Demo Mode'),
('admin.demoMode.help', 'admin', 'admin.demoMode.help', 'When on, the public /demo page is reachable, demo credentials appear on the login screen, and the home hero shows a "See it in action" CTA. Leave off for buyer deployments.'),
('admin.demoMode.restartBanner', 'admin', 'admin.demoMode.restartBanner', 'admin.demoMode.restartBanner'),
('admin.demoMode.restartFailedBanner', 'admin', 'admin.demoMode.restartFailedBanner', 'Auto-restart did not complete in time. Please restart the workflow manually for the change to take effect.'),
('admin.demoMode.restartingBanner', 'admin', 'admin.demoMode.restartingBanner', 'Restarting server… this usually takes a few seconds. The page will reload automatically when ready.'),
('admin.demoMode.restartTimeout', 'admin', 'admin.demoMode.restartTimeout', 'Server did not respond after restart. Please restart the workflow manually.'),
('admin.demoMode.saved', 'admin', 'admin.demoMode.saved', 'Saved. Restart (and on production, rebuild) the server for the change to take effect.'),
('admin.demoMode.title', 'admin', 'admin.demoMode.title', 'Demo Mode'),
('admin.exitImpersonation', 'admin', 'admin.exitImpersonation', 'Exit & Return to Admin'),
('admin.impersonating', 'admin', 'admin.impersonating', 'Impersonating'),
('admin.languages.actions.exportTranslations', 'admin', 'admin.languages.actions.exportTranslations', 'Export translations as JSON'),
('admin.languages.actions.importTranslations', 'admin', 'admin.languages.actions.importTranslations', 'Import translations from JSON'),
('admin.languages.errors.exportFailed', 'admin', 'admin.languages.errors.exportFailed', 'Export failed'),
('admin.languages.errors.importFailed', 'admin', 'admin.languages.errors.importFailed', 'Import failed'),
('admin.languages.errors.importInvalidFormat', 'admin', 'admin.languages.errors.importInvalidFormat', 'Import failed: file does not contain a valid translations export'),
('admin.languages.errors.importInvalidJson', 'admin', 'admin.languages.errors.importInvalidJson', 'Import failed: invalid JSON file'),
('admin.languages.success.exported', 'admin', 'admin.languages.success.exported', 'admin.languages.success.exported'),
('admin.languages.success.imported', 'admin', 'admin.languages.success.imported', 'Imported {{count}} translation(s) into '),
('admin.orders.active', 'admin', 'admin.orders.active', 'Active'),
('admin.orders.adminNote', 'admin', 'admin.orders.adminNote', 'Read-only view of all orders across all restaurants'),
('admin.orders.cancelled', 'admin', 'admin.orders.cancelled', 'Cancelled'),
('admin.orders.completed', 'admin', 'admin.orders.completed', 'Completed'),
('admin.orders.customer', 'admin', 'admin.orders.customer', 'Customer'),
('admin.orders.deliveryAddress', 'admin', 'admin.orders.deliveryAddress', 'Delivery Address'),
('admin.orders.discount', 'admin', 'admin.orders.discount', 'Discount'),
('admin.orders.giftCard', 'admin', 'admin.orders.giftCard', 'Gift card'),
('admin.orders.giftCardBalance', 'admin', 'admin.orders.giftCardBalance', 'Gift card balance'),
('admin.orders.items', 'admin', 'admin.orders.items', 'Items'),
('admin.orders.metadata', 'admin', 'admin.orders.metadata', 'Metadata'),
('admin.orders.modificationNote', 'admin', 'admin.orders.modificationNote', 'Modification Note'),
('admin.orders.noOrders', 'admin', 'admin.orders.noOrders', 'No orders found'),
('admin.orders.of', 'admin', 'admin.orders.of', 'of'),
('admin.orders.orderHash', 'admin', 'admin.orders.orderHash', 'Order'),
('admin.orders.page', 'admin', 'admin.orders.page', 'Page'),
('admin.orders.pageDesc', 'admin', 'admin.orders.pageDesc', 'All orders across every restaurant and branch'),
('admin.orders.pageTitle', 'admin', 'admin.orders.pageTitle', 'Orders'),
('admin.orders.pending', 'admin', 'admin.orders.pending', 'Pending'),
('admin.orders.restaurant', 'admin', 'admin.orders.restaurant', 'Restaurant'),
('admin.orders.results', 'admin', 'admin.orders.results', 'orders'),
('admin.orders.revenue', 'admin', 'admin.orders.revenue', 'Revenue'),
('admin.orders.searchPlaceholder', 'admin', 'admin.orders.searchPlaceholder', 'Search by customer name, phone, or order number…'),
('admin.orders.specialInstructions', 'admin', 'admin.orders.specialInstructions', 'Special Instructions'),
('admin.orders.subtotal', 'admin', 'admin.orders.subtotal', 'Subtotal'),
('admin.orders.tableNumber', 'admin', 'admin.orders.tableNumber', 'Table Number'),
('admin.orders.tax', 'admin', 'admin.orders.tax', 'Tax'),
('admin.orders.total', 'admin', 'admin.orders.total', 'Total'),
('admin.orders.totalOrders', 'admin', 'admin.orders.totalOrders', 'Total Orders'),
('admin.orders.totalPaid', 'admin', 'admin.orders.totalPaid', 'Total paid'),
('admin.platform', 'admin', 'admin.platform', 'Platform'),
('admin.platformKeys.adminNote', 'admin', 'admin.platformKeys.adminNote', 'Keys stored here are used for platform-level operations (e.g. AI translation)'),
('admin.platformKeys.currentKey', 'admin', 'admin.platformKeys.currentKey', 'Current key'),
('admin.platformKeys.keyNote', 'admin', 'admin.platformKeys.keyNote', 'The full key is never displayed after saving. Only the first and last 4 characters are shown as a hint.'),
('admin.platformKeys.labelReplace', 'admin', 'admin.platformKeys.labelReplace', 'Replace API Key'),
('admin.platformKeys.labelSet', 'admin', 'admin.platformKeys.labelSet', 'Set API Key'),
('admin.platformKeys.openaiCard', 'admin', 'admin.platformKeys.openaiCard', 'OpenAI API Key'),
('admin.platformKeys.openaiDesc', 'admin', 'admin.platformKeys.openaiDesc', 'Used for AI-powered translation in the Languages page. Restaurant owners use their own keys for chat/voice agents.'),
('admin.platformKeys.pageDesc', 'admin', 'admin.platformKeys.pageDesc', 'API keys used for platform-level operations'),
('admin.platformKeys.pageTitle', 'admin', 'admin.platformKeys.pageTitle', 'Platform Keys'),
('admin.platformKeys.saveBtn', 'admin', 'admin.platformKeys.saveBtn', 'Save Key'),
('admin.platformKeys.saveStripeKeys', 'admin', 'admin.platformKeys.saveStripeKeys', 'Save Stripe Keys'),
('admin.platformKeys.stripeCard', 'admin', 'admin.platformKeys.stripeCard', 'Stripe Keys'),
('admin.platformKeys.stripeCardDesc', 'admin', 'admin.platformKeys.stripeCardDesc', 'Used for billing, subscriptions, and Stripe.js checkout. Enter one or both keys and save together.'),
('admin.platformKeys.stripePubCard', 'admin', 'admin.platformKeys.stripePubCard', 'Stripe Publishable Key'),
('admin.platformKeys.stripePubDesc', 'admin', 'admin.platformKeys.stripePubDesc', 'Safe to expose to the browser. Used for initializing Stripe.js on the checkout page.'),
('admin.platformKeys.stripeSecretCard', 'admin', 'admin.platformKeys.stripeSecretCard', 'Stripe Secret Key'),
('admin.platformKeys.stripeSecretDesc', 'admin', 'admin.platformKeys.stripeSecretDesc', 'Used for creating Stripe products, prices, and processing subscriptions. Keep this confidential.'),
('admin.switchToAdmin', 'admin', 'admin.switchToAdmin', 'Switch to Admin Panel'),
('admin.switchToRestaurant', 'admin', 'admin.switchToRestaurant', 'Switch to Restaurant'),
('admin.title', 'admin', 'admin.title', 'Admin Panel'),
('adminNotifications.emptyDesc', 'notifications', 'adminNotifications.emptyDesc', 'Platform-wide notifications will appear here. This feature is coming soon.'),
('adminNotifications.emptyTitle', 'notifications', 'adminNotifications.emptyTitle', 'Admin Notifications'),
('adminNotifications.subtitle', 'notifications', 'adminNotifications.subtitle', 'Platform-wide alerts and system notifications'),
('adminNotifications.title', 'notifications', 'adminNotifications.title', 'Notifications'),
('aiAgentConfig.errors.testFailed', 'ai_agent', 'aiAgentConfig.errors.testFailed', 'Test chat failed'),
('aiAgentConfig.errors.verifyFailed', 'ai_agent', 'aiAgentConfig.errors.verifyFailed', 'Verification failed'),
('aiAgentConfig.knowledgeSubtitle', 'ai_agent', 'aiAgentConfig.knowledgeSubtitle', 'Limit which knowledge base entries this agent can search. Leave empty to use the entire restaurant knowledge base.'),
('aiAgentConfig.menuScopeAll', 'ai_agent', 'aiAgentConfig.menuScopeAll', 'All menu items'),
('aiAgentConfig.menuScopeSpecific', 'ai_agent', 'aiAgentConfig.menuScopeSpecific', 'Specific categories'),
('aiAgentConfig.menuScopeSubtitle', 'ai_agent', 'aiAgentConfig.menuScopeSubtitle', 'Choose whether this agent can sell from the entire menu or only a specific set of categories.'),
('aiAgentConfig.noKbEntries', 'ai_agent', 'aiAgentConfig.noKbEntries', 'No knowledge base entries yet — add entries from the Knowledge Base page.'),
('aiAgentConfig.noMenuCategories', 'ai_agent', 'aiAgentConfig.noMenuCategories', 'No menu categories configured.'),
('aiAgentConfig.searchModels', 'ai_agent', 'aiAgentConfig.searchModels', 'Search models…'),
('aiAgentConfig.sections.knowledge', 'ai_agent', 'aiAgentConfig.sections.knowledge', 'Knowledge Base'),
('aiAgentConfig.sections.menuScope', 'ai_agent', 'aiAgentConfig.sections.menuScope', 'Menu Category Scope'),
('aiAgentConfig.sections.test', 'ai_agent', 'aiAgentConfig.sections.test', 'Test Agent'),
('aiAgentConfig.testEmpty', 'ai_agent', 'aiAgentConfig.testEmpty', 'Send a test message to chat with this agent — orders/bookings created here are real.'),
('aiAgentConfig.testPlaceholder', 'ai_agent', 'aiAgentConfig.testPlaceholder', 'Type a test message…'),
('aiAgentConfig.testSend', 'ai_agent', 'aiAgentConfig.testSend', 'Send'),
('aiAgentConfig.testThinking', 'ai_agent', 'aiAgentConfig.testThinking', 'Thinking…'),
('aiAgentConfig.verifying', 'ai_agent', 'aiAgentConfig.verifying', 'Verifying…'),
('aiAgentConfig.verifyOk', 'ai_agent', 'aiAgentConfig.verifyOk', 'OpenRouter key verified ({{ms}} ms)'),
('aiAgentConfig.verifyOkInline', 'ai_agent', 'aiAgentConfig.verifyOkInline', 'OK · {{ms}} ms'),
('aiAgentConfig.verifyOpenRouter', 'ai_agent', 'aiAgentConfig.verifyOpenRouter', 'Verify OpenRouter Key'),
('aiAgentConfig.verifyOpenRouterTitle', 'ai_agent', 'aiAgentConfig.verifyOpenRouterTitle', 'Probe your OpenRouter API key'),
('aiAgentConfig.voiceLanguage', 'ai_agent', 'aiAgentConfig.voiceLanguage', 'Voice Language'),
('aiAgentConfig.voiceLanguageNote', 'ai_agent', 'aiAgentConfig.voiceLanguageNote', 'This voice speaks {{lang}}; the agent will respond in this language.'),
('analytics.avgDiscountPerRedemption', 'analytics', 'analytics.avgDiscountPerRedemption', 'Avg Discount / Redemption'),
('analytics.balance', 'analytics', 'analytics.balance', 'Balance'),
('analytics.byLifetimePoints', 'analytics', 'analytics.byLifetimePoints', 'by lifetime points'),
('analytics.customers', 'analytics', 'analytics.customers', 'Customers'),
('analytics.earned', 'analytics', 'analytics.earned', 'Earned'),
('analytics.last30Days', 'analytics', 'analytics.last30Days', 'Last 30 days'),
('analytics.last90Days', 'analytics', 'analytics.last90Days', 'Last 90 days'),
('analytics.lifetime', 'analytics', 'analytics.lifetime', 'Lifetime'),
('analytics.loyaltySection', 'analytics', 'analytics.loyaltySection', 'Loyalty Performance'),
('analytics.loyaltyUnavailable', 'analytics', 'analytics.loyaltyUnavailable', 'Loyalty data unavailable'),
('analytics.loyaltyUnavailableSub', 'analytics', 'analytics.loyaltyUnavailableSub', 'Enable the loyalty program to start tracking performance'),
('analytics.members', 'analytics', 'analytics.members', 'Members'),
('analytics.noLoyalCustomers', 'analytics', 'analytics.noLoyalCustomers', 'No loyal customers yet'),
('analytics.noLoyalCustomersSub', 'analytics', 'analytics.noLoyalCustomersSub', 'Customers appear here once they start earning points'),
('analytics.nonMembers', 'analytics', 'analytics.nonMembers', 'Non-members'),
('analytics.noRepeatData', 'analytics', 'analytics.noRepeatData', 'Not enough data yet'),
('analytics.noTierData', 'analytics', 'analytics.noTierData', 'No tier data yet'),
('analytics.noTierDataSub', 'analytics', 'analytics.noTierDataSub', 'Tiers populate as customers earn points'),
('analytics.pointsEarnedRedeemed', 'analytics', 'analytics.pointsEarnedRedeemed', 'Earned vs Redeemed'),
('analytics.pointsOutstanding', 'analytics', 'analytics.pointsOutstanding', 'Points Outstanding'),
('analytics.redeemed', 'analytics', 'analytics.redeemed', 'Redeemed'),
('analytics.redemptionRate', 'analytics', 'analytics.redemptionRate', 'Redemption Rate'),
('analytics.redemptions', 'analytics', 'analytics.redemptions', 'redemptions'),
('analytics.repeatCustomerLift', 'analytics', 'analytics.repeatCustomerLift', 'Repeat-customer lift (90d)'),
('analytics.tierDistribution', 'analytics', 'analytics.tierDistribution', 'Tier Distribution'),
('analytics.topLoyalCustomers', 'analytics', 'analytics.topLoyalCustomers', 'Top Loyal Customers'),
('analytics.wallets', 'analytics', 'analytics.wallets', 'wallets'),
('auth.logOut', 'auth', 'auth.logOut', 'Log Out'),
('auth.platformAdmin', 'auth', 'auth.platformAdmin', 'Platform Admin'),
('auth.restaurantOwner', 'auth', 'auth.restaurantOwner', 'Restaurant Owner'),
('billing.featureNotIncludedDesc', 'billing', 'billing.featureNotIncludedDesc', 'The feature you tried to access requires a higher plan. Upgrade your subscription to unlock it.'),
('billing.featureNotIncludedTitle', 'billing', 'billing.featureNotIncludedTitle', 'Feature not included in your plan'),
('billing.features.storefront', 'billing', 'billing.features.storefront', 'QR Storefront'),
('billing.features.storefrontDesc', 'billing', 'billing.features.storefrontDesc', 'Per-table QR codes & customer-facing storefront for dine-in / takeaway'),
('billing.features.whatsappAgent', 'billing', 'billing.features.whatsappAgent', 'WhatsApp Agent'),
('billing.features.whatsappAgentDesc', 'billing', 'billing.features.whatsappAgentDesc', 'WhatsApp Business inbound + outbound via Meta Cloud API'),
('billing.proPlan', 'billing', 'billing.proPlan', 'Pro Plan'),
('billing.viewPlansUpgrade', 'billing', 'billing.viewPlansUpgrade', 'View Plans & Upgrade'),
('branch.quietHours.editTooltip', 'branch', 'branch.quietHours.editTooltip', 'Edit quiet hours'),
('branch.quietHours.enabled', 'branch', 'branch.quietHours.enabled', 'Quiet hours enabled'),
('branch.quietHours.from', 'branch', 'branch.quietHours.from', 'From'),
('branch.quietHours.help', 'branch', 'branch.quietHours.help', 'Marketing campaigns sent from this branch are paused during the quiet window. Wraps midnight (e.g. 22:00 → 08:00).'),
('branch.quietHours.invalidWindow', 'branch', 'branch.quietHours.invalidWindow', 'Start and end hour cannot be identical when quiet hours are enabled.'),
('branch.quietHours.off', 'branch', 'branch.quietHours.off', 'off'),
('branch.quietHours.saved', 'branch', 'branch.quietHours.saved', 'Quiet hours saved'),
('branch.quietHours.saveFailed', 'branch', 'branch.quietHours.saveFailed', 'Failed to save quiet hours'),
('branch.quietHours.to', 'branch', 'branch.quietHours.to', 'to'),
('branch.quietHours.tooltip', 'branch', 'branch.quietHours.tooltip', 'Marketing quiet hours'),
('common.configured', 'common', 'common.configured', 'Configured'),
('common.deleted', 'common', 'common.deleted', 'Deleted'),
('common.exit', 'common', 'common.exit', 'Exit'),
('common.failedToSave', 'common', 'common.failedToSave', 'Failed to save'),
('common.goToHomepage', 'common', 'common.goToHomepage', 'Go to homepage'),
('common.hrAgo', 'common', 'common.hrAgo', '{{count}} hr ago'),
('common.justNow', 'common', 'common.justNow', 'just now'),
('common.loadFailed', 'common', 'common.loadFailed', 'Failed to load'),
('common.menu', 'common', 'common.menu', 'Menu'),
('common.minAgo', 'common', 'common.minAgo', '{{count}} min ago'),
('common.notSet', 'common', 'common.notSet', 'Not set'),
('common.saveFailed', 'common', 'common.saveFailed', 'Save failed'),
('common.user', 'common', 'common.user', 'User'),
('common.website', 'common', 'common.website', 'Website'),
('coupons.subtitle', 'coupons', 'coupons.subtitle', 'Create branch-level promo codes for chat, WhatsApp and your storefront.'),
('customers.colLoyalty', 'customers', 'customers.colLoyalty', 'Loyalty'),
('customers.markedOptIn', 'customers', 'customers.markedOptIn', 'Customer re-subscribed to marketing'),
('customers.markedOptOut', 'customers', 'customers.markedOptOut', 'Customer opted out of marketing'),
('customers.marketingPrefs', 'customers', 'customers.marketingPrefs', 'Marketing messages'),
('customers.optedIn', 'customers', 'customers.optedIn', 'Opted in'),
('customers.optedOut', 'customers', 'customers.optedOut', 'Opted out'),
('customers.optOut', 'customers', 'customers.optOut', 'Opt out'),
('customers.points_earned_short', 'customers', 'customers.points_earned_short', 'earned'),
('customers.points_redeemed_short', 'customers', 'customers.points_redeemed_short', 'redeemed'),
('customers.pts', 'customers', 'customers.pts', 'pts'),
('customers.reSubscribe', 'customers', 'customers.reSubscribe', 'Re-subscribe'),
('dashboard.lowStock.count', 'dashboard', 'dashboard.lowStock.count', 'dashboard.lowStock.count'),
('dashboard.lowStock.empty', 'dashboard', 'dashboard.lowStock.empty', 'Every item is fully stocked'),
('dashboard.lowStock.invalidTarget', 'dashboard', 'dashboard.lowStock.invalidTarget', 'Please enter a non-negative whole number.'),
('dashboard.lowStock.resetLabel', 'dashboard', 'dashboard.lowStock.resetLabel', 'Daily reset'),
('dashboard.lowStock.restock', 'dashboard', 'dashboard.lowStock.restock', 'Restock'),
('dashboard.lowStock.restocked', 'dashboard', 'dashboard.lowStock.restocked', 'dashboard.lowStock.restocked'),
('dashboard.lowStock.restocking', 'dashboard', 'dashboard.lowStock.restocking', 'Restocking…'),
('dashboard.lowStock.restockPrompt', 'dashboard', 'dashboard.lowStock.restockPrompt', 'Restock (enter quantity)'),
('dashboard.lowStock.restockTo', 'dashboard', 'dashboard.lowStock.restockTo', 'dashboard.lowStock.restockTo'),
('dashboard.lowStock.soldOut', 'dashboard', 'dashboard.lowStock.soldOut', 'Sold out'),
('dashboard.lowStock.stockLabel', 'dashboard', 'dashboard.lowStock.stockLabel', 'Stock'),
('dashboard.lowStock.thresholdLabel', 'dashboard', 'dashboard.lowStock.thresholdLabel', 'Threshold'),
('dashboard.lowStock.title', 'dashboard', 'dashboard.lowStock.title', 'Low-Stock Items'),
('featureGuard.notIncluded', 'feature_guard', 'featureGuard.notIncluded', 'Not included in your plan'),
('featureGuard.upgradePrompt', 'feature_guard', 'featureGuard.upgradePrompt', 'Upgrade your subscription to access this feature.'),
('featureGuard.viewPlans', 'feature_guard', 'featureGuard.viewPlans', 'View Plans'),
('help.prioritySupportResponseTime', 'help', 'help.prioritySupportResponseTime', 'You have Priority Support — our team will respond within 1 hour.'),
('help.prioritySupportUpsell', 'help', 'help.prioritySupportUpsell', 'Get Priority Support'),
('help.prioritySupportUpsellDesc', 'help', 'help.prioritySupportUpsellDesc', 'Upgrade your plan for faster response times and dedicated support.'),
('help.upgradePlan', 'help', 'help.upgradePlan', 'Upgrade Plan'),
('landing.careers.badge', 'landing', 'landing.careers.badge', 'Careers'),
('landing.careers.openCta', 'landing', 'landing.careers.openCta', 'Get in touch'),
('landing.careers.openSub', 'landing', 'landing.careers.openSub', 'We hire deliberately. If you think you'),
('landing.careers.openTitle', 'landing', 'landing.careers.openTitle', 'No open roles right now'),
('landing.careers.sub', 'landing', 'landing.careers.sub', 'We are a small, distributed team building the AI back-of-house every restaurant deserves. Join us.'),
('landing.careers.title', 'landing', 'landing.careers.title', 'Help us reshape restaurant operations'),
('landing.careers.v1Body', 'landing', 'landing.careers.v1Body', 'We build for restaurants because we love restaurants. Empathy beats ego.'),
('landing.careers.v1Title', 'landing', 'landing.careers.v1Title', 'Hospitality first'),
('landing.careers.v2Body', 'landing', 'landing.careers.v2Body', 'A small team across 9 timezones. We optimise for outcomes, not hours online.'),
('landing.careers.v2Title', 'landing', 'landing.careers.v2Title', 'Remote, async, global'),
('landing.careers.v3Body', 'landing', 'landing.careers.v3Body', 'Every hire owns a problem end to end — from spec to ship to support.'),
('landing.careers.v3Title', 'landing', 'landing.careers.v3Title', 'Ownership culture'),
('landing.changelog.e1Body', 'landing', 'landing.changelog.e1Body', 'View, assign, and reply across every branch from one consolidated conversations view.'),
('landing.changelog.e1Date', 'landing', 'landing.changelog.e1Date', 'April 18, 2026'),
('landing.changelog.e1Title', 'landing', 'landing.changelog.e1Title', 'Multi-branch unified inbox'),
('landing.changelog.e2Body', 'landing', 'landing.changelog.e2Body', 'Resolved an edge case where modifier-only menu updates were not propagating to Toast.'),
('landing.changelog.e2Date', 'landing', 'landing.changelog.e2Date', 'April 4, 2026'),
('landing.changelog.e2Title', 'landing', 'landing.changelog.e2Title', 'POS sync reliability'),
('landing.changelog.e3Body', 'landing', 'landing.changelog.e3Body', 'Pre-built greetings, upsells, and fallback scripts you can drop into your AI agent in one click.'),
('landing.changelog.e3Date', 'landing', 'landing.changelog.e3Date', 'March 22, 2026'),
('landing.changelog.e3Title', 'landing', 'landing.changelog.e3Title', 'Voice prompt library'),
('landing.changelog.e4Body', 'landing', 'landing.changelog.e4Body', 'Completed our annual third-party audit with zero exceptions. New report available on request.'),
('landing.changelog.e4Date', 'landing', 'landing.changelog.e4Date', 'March 8, 2026'),
('landing.changelog.e4Title', 'landing', 'landing.changelog.e4Title', 'SOC 2 Type II re-attestation'),
('landing.changelog.e5Body', 'landing', 'landing.changelog.e5Body', 'Native WhatsApp inbox with template messaging, media, and AI auto-reply.'),
('landing.changelog.e5Date', 'landing', 'landing.changelog.e5Date', 'February 14, 2026'),
('landing.changelog.e5Title', 'landing', 'landing.changelog.e5Title', 'WhatsApp Business API channel'),
('landing.changelog.sub', 'landing', 'landing.changelog.sub', 'New features, fixes, and platform improvements — shipped continuously.'),
('landing.changelog.tagFeature', 'landing', 'landing.changelog.tagFeature', 'Feature'),
('landing.changelog.tagFix', 'landing', 'landing.changelog.tagFix', 'Fix'),
('landing.changelog.tagSecurity', 'landing', 'landing.changelog.tagSecurity', 'Security'),
('landing.changelog.title', 'landing', 'landing.changelog.title', 'Changelog'),
('landing.cmp.row1', 'landing', 'landing.cmp.row1', 'AI voice agent (multilingual)'),
('landing.cmp.row1g', 'landing', 'landing.cmp.row1g', 'English only'),
('landing.cmp.row2', 'landing', 'landing.cmp.row2', 'Unified chat + voice + WhatsApp'),
('landing.cmp.row2l', 'landing', 'landing.cmp.row2l', 'Phone only'),
('landing.cmp.row3', 'landing', 'landing.cmp.row3', 'Native POS integrations'),
('landing.cmp.row3l', 'landing', 'landing.cmp.row3l', 'Manual entry'),
('landing.cmp.row3r', 'landing', 'landing.cmp.row3r', '50+ POS systems'),
('landing.cmp.row4', 'landing', 'landing.cmp.row4', 'Real-time menu sync'),
('landing.cmp.row5', 'landing', 'landing.cmp.row5', 'Multi-branch dashboard'),
('landing.cmp.row5g', 'landing', 'landing.cmp.row5g', 'Add-on fee'),
('landing.cmp.row6', 'landing', 'landing.cmp.row6', 'Setup time'),
('landing.cmp.row6g', 'landing', 'landing.cmp.row6g', '1 week'),
('landing.cmp.row6l', 'landing', 'landing.cmp.row6l', '2–4 weeks'),
('landing.cmp.row6r', 'landing', 'landing.cmp.row6r', 'Under 2 hours'),
('landing.cmp.row7', 'landing', 'landing.cmp.row7', 'Per-call pricing'),
('landing.cmp.row7g', 'landing', 'landing.cmp.row7g', '$0.20/min'),
('landing.cmp.row7l', 'landing', 'landing.cmp.row7l', '$0.45/call'),
('landing.cmp.row7r', 'landing', 'landing.cmp.row7r', 'Flat monthly'),
('landing.cmp.row8', 'landing', 'landing.cmp.row8', 'White-label & self-host'),
('landing.complianceLine', 'landing', 'landing.complianceLine', 'SOC 2 Type II audited · GDPR-ready · PCI-DSS via Stripe.'),
('landing.footerBlog', 'landing', 'landing.footerBlog', 'Blog'),
('landing.footerResources', 'landing', 'landing.footerResources', 'Resources'),
('landing.footerSecurity', 'landing', 'landing.footerSecurity', 'Security'),
('landing.home.caseMetric1Label', 'landing', 'landing.home.caseMetric1Label', 'Staff phone time'),
('landing.home.caseMetric2Label', 'landing', 'landing.home.caseMetric2Label', 'AI resolution rate'),
('landing.home.caseMetric2Sub', 'landing', 'landing.home.caseMetric2Sub', 'across all calls'),
('landing.home.caseMetric3Label', 'landing', 'landing.home.caseMetric3Label', 'Revenue lift'),
('landing.home.caseStudyQuote', 'landing', 'landing.home.caseStudyQuote', 'Managing 8 branches from one dashboard changed everything. Staff focus on guests, not phones. Revenue up 31% in 3 months.'),
('landing.home.cmpBadge', 'landing', 'landing.home.cmpBadge', 'Comparison'),
('landing.home.cmpColFeature', 'landing', 'landing.home.cmpColFeature', 'Capability'),
('landing.home.cmpColGeneric', 'landing', 'landing.home.cmpColGeneric', 'Generic AI'),
('landing.home.cmpColLegacy', 'landing', 'landing.home.cmpColLegacy', 'Legacy'),
('landing.home.cmpColRA', 'landing', 'landing.home.cmpColRA', 'RestroAgent'),
('landing.home.cmpSub', 'landing', 'landing.home.cmpSub', 'A side-by-side look at how RestroAgent compares to legacy answering services and generic AI bots.'),
('landing.home.cmpTitle', 'landing', 'landing.home.cmpTitle', 'Why teams pick RestroAgent'),
('landing.home.feat8Desc', 'landing', 'landing.home.feat8Desc', '40+ languages, automatic detection. Mandarin and English customers get the same flawless service.'),
('landing.home.feat8Title', 'landing', 'landing.home.feat8Title', 'Multilingual'),
('landing.home.flowCh1', 'landing', 'landing.home.flowCh1', 'Phone'),
('landing.home.flowCh2', 'landing', 'landing.home.flowCh2', 'WhatsApp'),
('landing.home.flowCh3', 'landing', 'landing.home.flowCh3', 'Web chat'),
('landing.home.flowInboxTitle', 'landing', 'landing.home.flowInboxTitle', 'Unified inbox'),
('landing.home.flowItem1Msg', 'landing', 'landing.home.flowItem1Msg', 'Order: Pasta Carbonara × 2'),
('landing.home.flowItem1Name', 'landing', 'landing.home.flowItem1Name', 'Table 7 — Dine-in'),
('landing.home.flowItem2Msg', 'landing', 'landing.home.flowItem2Msg', 'Booking for 4 — Friday 7pm'),
('landing.home.flowItem2Name', 'landing', 'landing.home.flowItem2Name', '+1 (555) 0142'),
('landing.home.flowItem3Msg', 'landing', 'landing.home.flowItem3Msg', 'Asking about gluten-free menu'),
('landing.home.flowItem3Name', 'landing', 'landing.home.flowItem3Name', 'Web visitor'),
('landing.home.flowLive', 'landing', 'landing.home.flowLive', 'Live'),
('landing.home.flowVia1', 'landing', 'landing.home.flowVia1', 'via Phone'),
('landing.home.flowVia2', 'landing', 'landing.home.flowVia2', 'via WhatsApp'),
('landing.home.flowVia3', 'landing', 'landing.home.flowVia3', 'via Web chat'),
('landing.home.heroChip1', 'landing', 'landing.home.heroChip1', 'Always-On AI'),
('landing.home.heroChip2', 'landing', 'landing.home.heroChip2', 'Regional Languages'),
('landing.home.heroCtaContact', 'landing', 'landing.home.heroCtaContact', 'Talk to sales'),
('landing.home.heroCtaDemo', 'landing', 'landing.home.heroCtaDemo', 'See live demo'),
('landing.home.heroTitleBrand', 'landing', 'landing.home.heroTitleBrand', 'restaurants'),
('landing.home.heroTitlePre', 'landing', 'landing.home.heroTitlePre', 'AI agents that answer every call for'),
('landing.home.heroTrustLine', 'landing', 'landing.home.heroTrustLine', 'No credit card required · 14-day free trial · Live in 2 hours'),
('landing.home.howEyebrow', 'landing', 'landing.home.howEyebrow', 'How it works'),
('landing.home.logoWallLabel', 'landing', 'landing.home.logoWallLabel', 'Trusted by 2,400+ restaurants worldwide'),
('landing.home.previewEyebrow', 'landing', 'landing.home.previewEyebrow', 'One workspace'),
('landing.home.previewSub', 'landing', 'landing.home.previewSub', 'Phone calls, web chat, and messaging streams flow into a single live dashboard your team can watch at a glance.'),
('landing.home.previewTitle', 'landing', 'landing.home.previewTitle', 'Every channel, every order — in one view'),
('landing.home.roiCta', 'landing', 'landing.home.roiCta', 'Start free trial'),
('landing.home.roiDisclaimer', 'landing', 'landing.home.roiDisclaimer', 'Estimate based on industry averages.'),
('landing.home.roiEyebrow', 'landing', 'landing.home.roiEyebrow', 'ROI calculator'),
('landing.home.roiInput1', 'landing', 'landing.home.roiInput1', 'Monthly inbound calls'),
('landing.home.roiInput2', 'landing', 'landing.home.roiInput2', 'Currently missed'),
('landing.home.roiInput3', 'landing', 'landing.home.roiInput3', 'Average order value'),
('landing.home.roiResultLabel', 'landing', 'landing.home.roiResultLabel', 'Recovered with RestroAgent'),
('landing.home.roiResultSub', 'landing', 'landing.home.roiResultSub', 'Based on capturing every missed call at your average order value. Estimate uses industry averages — most restaurants see more.'),
('landing.home.roiSub', 'landing', 'landing.home.roiSub', 'A few quick numbers — find out how much revenue RestroAgent recovers every month.'),
('landing.home.roiTitle', 'landing', 'landing.home.roiTitle', 'See what missed calls are costing you'),
('landing.int.catAnalytics', 'landing', 'landing.int.catAnalytics', 'Reservations'),
('landing.int.catDelivery', 'landing', 'landing.int.catDelivery', 'Delivery'),
('landing.int.catMessaging', 'landing', 'landing.int.catMessaging', 'Messaging'),
('landing.int.catPayments', 'landing', 'landing.int.catPayments', 'Payments'),
('landing.int.catPos', 'landing', 'landing.int.catPos', 'Point of Sale'),
('landing.int.catTelephony', 'landing', 'landing.int.catTelephony', 'Telephony'),
('landing.int.clover', 'landing', 'landing.int.clover', 'Clover'),
('landing.int.cloverDesc', 'landing', 'landing.int.cloverDesc', 'Live menu sync and order routing for Clover.'),
('landing.int.deliveroo', 'landing', 'landing.int.deliveroo', 'Deliveroo'),
('landing.int.deliverooDesc', 'landing', 'landing.int.deliverooDesc', 'Deliveroo dispatch & menu sync (UK/EU).'),
('landing.int.doordash', 'landing', 'landing.int.doordash', 'DoorDash'),
('landing.int.doordashDesc', 'landing', 'landing.int.doordashDesc', 'Unified DoorDash orders in one inbox.'),
('landing.int.grubhub', 'landing', 'landing.int.grubhub', 'Grubhub'),
('landing.int.grubhubDesc', 'landing', 'landing.int.grubhubDesc', 'Grubhub menu publishing and order intake.'),
('landing.int.lightspeed', 'landing', 'landing.int.lightspeed', 'Lightspeed'),
('landing.int.lightspeedDesc', 'landing', 'landing.int.lightspeedDesc', 'Lightspeed Restaurant menu, modifiers & tabs.'),
('landing.int.messenger', 'landing', 'landing.int.messenger', 'Messenger'),
('landing.int.messengerDesc', 'landing', 'landing.int.messengerDesc', 'Reply to Facebook Messenger DMs with AI.'),
('landing.int.opentable', 'landing', 'landing.int.opentable', 'OpenTable'),
('landing.int.opentableDesc', 'landing', 'landing.int.opentableDesc', 'OpenTable bookings synced to AI confirmations.'),
('landing.int.paypal', 'landing', 'landing.int.paypal', 'PayPal'),
('landing.int.paypalDesc', 'landing', 'landing.int.paypalDesc', 'PayPal checkout for online & phone orders.'),
('landing.int.resy', 'landing', 'landing.int.resy', 'Resy'),
('landing.int.resyDesc', 'landing', 'landing.int.resyDesc', 'Resy reservations with smart reminders.'),
('landing.int.square', 'landing', 'landing.int.square', 'Square'),
('landing.int.squareDesc', 'landing', 'landing.int.squareDesc', 'Push AI orders straight to your Square POS.'),
('landing.int.stripe', 'landing', 'landing.int.stripe', 'Stripe'),
('landing.int.stripeDesc', 'landing', 'landing.int.stripeDesc', 'Take deposits and pre-orders via Stripe links.'),
('landing.int.toast', 'landing', 'landing.int.toast', 'Toast POS'),
('landing.int.toastDesc', 'landing', 'landing.int.toastDesc', 'Two-way menu & order sync with Toast tickets.'),
('landing.int.twilio', 'landing', 'landing.int.twilio', 'Twilio'),
('landing.int.twilioDesc', 'landing', 'landing.int.twilioDesc', 'Bring your own Twilio number for AI calls.'),
('landing.int.uberEats', 'landing', 'landing.int.uberEats', 'Uber Eats'),
('landing.int.uberEatsDesc', 'landing', 'landing.int.uberEatsDesc', 'Auto-accept and sync Uber Eats orders.'),
('landing.int.vonage', 'landing', 'landing.int.vonage', 'Vonage'),
('landing.int.vonageDesc', 'landing', 'landing.int.vonageDesc', 'Vonage SIP routing for inbound voice agents.'),
('landing.int.whatsapp', 'landing', 'landing.int.whatsapp', 'WhatsApp'),
('landing.int.whatsappDesc', 'landing', 'landing.int.whatsappDesc', 'Official WhatsApp Business API messaging.'),
('landing.integrationsPage.badge', 'landing', 'landing.integrationsPage.badge', 'Ecosystem'),
('landing.integrationsPage.cta1Link', 'landing', 'landing.integrationsPage.cta1Link', 'Request an integration'),
('landing.integrationsPage.cta1Sub', 'landing', 'landing.integrationsPage.cta1Sub', 'We build new connectors at no extra cost. Tell us what you use and we'),
('landing.integrationsPage.cta1Title', 'landing', 'landing.integrationsPage.cta1Title', 'Don'),
('landing.integrationsPage.cta2Link', 'landing', 'landing.integrationsPage.cta2Link', 'Read our security docs'),
('landing.integrationsPage.cta2Sub', 'landing', 'landing.integrationsPage.cta2Sub', 'OAuth, webhooks, retries, and idempotent syncs — built for production restaurants.'),
('landing.integrationsPage.cta2Title', 'landing', 'landing.integrationsPage.cta2Title', 'Enterprise-grade reliability'),
('landing.integrationsPage.sub', 'landing', 'landing.integrationsPage.sub', 'Native integrations with 50+ POS, delivery, telephony, messaging, and payment platforms — no rip-and-replace required.'),
('landing.integrationsPage.title', 'landing', 'landing.integrationsPage.title', 'Connects with your entire stack'),
('landing.logos.bella', 'landing', 'landing.logos.bella', 'Bella Napoli'),
('landing.logos.casa', 'landing', 'landing.logos.casa', 'Casa Mia'),
('landing.logos.dragon', 'landing', 'landing.logos.dragon', 'Dragon Palace'),
('landing.logos.harbor', 'landing', 'landing.logos.harbor', 'Harbor Grill'),
('landing.logos.olive', 'landing', 'landing.logos.olive', 'Olive & Vine'),
('landing.logos.sakura', 'landing', 'landing.logos.sakura', 'Sakura Sushi'),
('landing.logos.spice', 'landing', 'landing.logos.spice', 'Spice Garden'),
('landing.logos.taco', 'landing', 'landing.logos.taco', 'Taco Libre'),
('landing.sec.aes', 'landing', 'landing.sec.aes', 'AES-256'),
('landing.sec.aesSub', 'landing', 'landing.sec.aesSub', 'Encryption at rest'),
('landing.sec.gdpr', 'landing', 'landing.sec.gdpr', 'GDPR Ready'),
('landing.sec.gdprSub', 'landing', 'landing.sec.gdprSub', 'EU data residency'),
('landing.sec.pci', 'landing', 'landing.sec.pci', 'PCI DSS'),
('landing.sec.pciSub', 'landing', 'landing.sec.pciSub', 'Stripe-backed payments'),
('landing.sec.soc2', 'landing', 'landing.sec.soc2', 'SOC 2 Type II'),
('landing.sec.soc2Sub', 'landing', 'landing.sec.soc2Sub', 'Audited annually'),
('landing.sec.tls', 'landing', 'landing.sec.tls', 'TLS 1.3'),
('landing.sec.tlsSub', 'landing', 'landing.sec.tlsSub', 'Encryption in transit'),
('landing.sec.uptime', 'landing', 'landing.sec.uptime', '99.9% Uptime'),
('landing.sec.uptimeSub', 'landing', 'landing.sec.uptimeSub', 'SLA-backed'),
('landing.securityPage.badge', 'landing', 'landing.securityPage.badge', 'Trust & Security'),
('landing.securityPage.p1Body', 'landing', 'landing.securityPage.p1Body', 'AES-256 at rest, TLS 1.3 in transit. All customer data encrypted with per-tenant keys.'),
('landing.securityPage.p1Title', 'landing', 'landing.securityPage.p1Title', 'Encryption everywhere'),
('landing.securityPage.p2Body', 'landing', 'landing.securityPage.p2Body', 'SSO, SAML, role-based permissions, and full audit trails on every staff action.'),
('landing.securityPage.p2Title', 'landing', 'landing.securityPage.p2Title', 'Identity & access'),
('landing.securityPage.p3Body', 'landing', 'landing.securityPage.p3Body', 'Multi-region failover, daily encrypted backups, 99.9% uptime SLA, and disaster-recovery drills.'),
('landing.securityPage.p3Title', 'landing', 'landing.securityPage.p3Title', 'Resilient infrastructure'),
('landing.securityPage.p4Body', 'landing', 'landing.securityPage.p4Body', 'SOC 2 Type II audited annually. GDPR-ready. Pen-tested by a third-party every six months.'),
('landing.securityPage.p4Title', 'landing', 'landing.securityPage.p4Title', 'Compliance & audits'),
('landing.securityPage.p5Body', 'landing', 'landing.securityPage.p5Body', 'Customer data is never sold or shared. PII is redacted in logs. You can delete data on request.'),
('landing.securityPage.p5Title', 'landing', 'landing.securityPage.p5Title', 'Privacy by default'),
('landing.securityPage.p6Body', 'landing', 'landing.securityPage.p6Body', 'A clear vulnerability disclosure policy and a private bounty program for security researchers.'),
('landing.securityPage.p6Title', 'landing', 'landing.securityPage.p6Title', 'Responsible disclosure'),
('landing.securityPage.requestCta', 'landing', 'landing.securityPage.requestCta', 'Request security documentation'),
('landing.securityPage.requestDocs', 'landing', 'landing.securityPage.requestDocs', 'Need our SOC 2 report, DPA, or pen-test summary?'),
('landing.securityPage.sub', 'landing', 'landing.securityPage.sub', 'Every restaurant we serve trusts us with their orders, their guests, and their reputation. Here is how we earn that trust.'),
('landing.securityPage.title', 'landing', 'landing.securityPage.title', 'Security you can audit'),
('loyalty.subtitle', 'loyalty', 'loyalty.subtitle', 'Reward repeat customers with points, tiers, and perks'),
('loyalty.title', 'loyalty', 'loyalty.title', 'Loyalty Program'),
('marketing.audience.activeWithin', 'marketing', 'marketing.audience.activeWithin', 'Active in the last'),
('marketing.audience.branches', 'marketing', 'marketing.audience.branches', 'Where they ordered'),
('marketing.audience.branchesShort', 'marketing', 'marketing.audience.branchesShort', 'branches'),
('marketing.audience.channel', 'marketing', 'marketing.audience.channel', 'Channel'),
('marketing.audience.channelAny', 'marketing', 'marketing.audience.channelAny', 'Any reachable channel'),
('marketing.audience.channelEmail', 'marketing', 'marketing.audience.channelEmail', 'Email only'),
('marketing.audience.channelWhatsapp', 'marketing', 'marketing.audience.channelWhatsapp', 'WhatsApp only'),
('marketing.audience.confirmDeleteMore', 'marketing', 'marketing.audience.confirmDeleteMore', '…and {n} more'),
('marketing.audience.customActive', 'marketing', 'marketing.audience.customActive', 'Custom: {v}'),
('marketing.audience.customEllipsis', 'marketing', 'marketing.audience.customEllipsis', 'Custom…'),
('marketing.audience.deleted', 'marketing', 'marketing.audience.deleted', 'Audience deleted'),
('marketing.audience.deleteFailed', 'marketing', 'marketing.audience.deleteFailed', 'Failed to delete audience'),
('marketing.audience.descriptionOptional', 'marketing', 'marketing.audience.descriptionOptional', 'Description (optional)'),
('marketing.audience.editTitle', 'marketing', 'marketing.audience.editTitle', 'Edit audience'),
('marketing.audience.lastDays', 'marketing', 'marketing.audience.lastDays', 'last'),
('marketing.audience.loadFailed', 'marketing', 'marketing.audience.loadFailed', 'Failed to load segments'),
('marketing.audience.minSpend', 'marketing', 'marketing.audience.minSpend', 'Min lifetime spend'),
('marketing.audience.minVisits', 'marketing', 'marketing.audience.minVisits', 'Min lifetime visits'),
('marketing.audience.namePlaceholder', 'marketing', 'marketing.audience.namePlaceholder', 'e.g. VIP regulars'),
('marketing.audience.nameRequired', 'marketing', 'marketing.audience.nameRequired', 'Audience name is required'),
('marketing.audience.new', 'marketing', 'marketing.audience.new', 'New audience'),
('marketing.audience.previewSuffix', 'marketing', 'marketing.audience.previewSuffix', 'reachable customers'),
('marketing.audience.quickStart', 'marketing', 'marketing.audience.quickStart', 'Quick start'),
('marketing.audience.resetBlank', 'marketing', 'marketing.audience.resetBlank', 'Reset to blank'),
('marketing.audience.save', 'marketing', 'marketing.audience.save', 'Save audience'),
('marketing.audience.saved', 'marketing', 'marketing.audience.saved', 'Audience saved'),
('marketing.audience.saveFailed', 'marketing', 'marketing.audience.saveFailed', 'Failed to save audience'),
('marketing.audience.sectionBehaviour', 'marketing', 'marketing.audience.sectionBehaviour', 'Customer behaviour'),
('marketing.audience.sectionReach', 'marketing', 'marketing.audience.sectionReach', 'How to reach them'),
('marketing.audience.spend', 'marketing', 'marketing.audience.spend', 'spend'),
('marketing.audience.subtitle', 'marketing', 'marketing.audience.subtitle', 'Saved customer segments for marketing campaigns'),
('marketing.audience.tags', 'marketing', 'marketing.audience.tags', 'Customer tags (any of)'),
('marketing.audience.tagsAdd', 'marketing', 'marketing.audience.tagsAdd', 'Add'),
('marketing.audience.tagsShort', 'marketing', 'marketing.audience.tagsShort', 'tags'),
('marketing.audience.title', 'marketing', 'marketing.audience.title', 'Audiences'),
('marketing.audience.update', 'marketing', 'marketing.audience.update', 'Update audience'),
('marketing.audience.updated', 'marketing', 'marketing.audience.updated', 'Audience updated'),
('marketing.audience.usePreset', 'marketing', 'marketing.audience.usePreset', 'Use preset'),
('marketing.audience.visits', 'marketing', 'marketing.audience.visits', 'visits'),
('marketing.audience.zeroHint', 'marketing', 'marketing.audience.zeroHint', 'No matches yet — loosen a filter, or'),
('marketing.audience.zeroHintLink', 'marketing', 'marketing.audience.zeroHintLink', 'add customers'),
('marketing.campaign.advancedToggle', 'marketing', 'marketing.campaign.advancedToggle', 'Advanced'),
('marketing.campaign.audience', 'marketing', 'marketing.campaign.audience', 'Audience'),
('marketing.campaign.bothHint', 'marketing', 'marketing.campaign.bothHint', 'Two linked campaigns will be created — one per channel — sharing a single report.'),
('marketing.campaign.bothNote', 'marketing', 'marketing.campaign.bothNote', 'Two campaigns will be created and linked. Their reports merge into one view.'),
('marketing.campaign.branchHint', 'marketing', 'marketing.campaign.branchHint', 'WhatsApp credentials are configured per branch. Pick the branch whose WhatsApp number should appear as the sender.'),
('marketing.campaign.branchRequired', 'marketing', 'marketing.campaign.branchRequired', 'Pick a branch — WhatsApp credentials live on the branch row'),
('marketing.campaign.cancelFailed', 'marketing', 'marketing.campaign.cancelFailed', 'Cancel failed'),
('marketing.campaign.cancelled', 'marketing', 'marketing.campaign.cancelled', 'Campaign cancelled'),
('marketing.campaign.channel', 'marketing', 'marketing.campaign.channel', 'Channel'),
('marketing.campaign.channelBoth', 'marketing', 'marketing.campaign.channelBoth', 'Email + WhatsApp'),
('marketing.campaign.chooseBranch', 'marketing', 'marketing.campaign.chooseBranch', '— Choose a branch —'),
('marketing.campaign.confirmCancel', 'marketing', 'marketing.campaign.confirmCancel', 'Cancel this broadcast? Queued deliveries will be skipped.'),
('marketing.campaign.confirmDelete', 'marketing', 'marketing.campaign.confirmDelete', 'Delete this campaign?'),
('marketing.campaign.customers', 'marketing', 'marketing.campaign.customers', 'customers'),
('marketing.campaign.defineRules', 'marketing', 'marketing.campaign.defineRules', '— Define rules below —'),
('marketing.campaign.deleteFailed', 'marketing', 'marketing.campaign.deleteFailed', 'Delete failed'),
('marketing.campaign.eitherChannel', 'marketing', 'marketing.campaign.eitherChannel', 'either channel'),
('marketing.campaign.emailBody', 'marketing', 'marketing.campaign.emailBody', 'HTML body'),
('marketing.campaign.emailBodyPlaceholder', 'marketing', 'marketing.campaign.emailBodyPlaceholder', '<p>Hi! Here'),
('marketing.campaign.emailContentRequired', 'marketing', 'marketing.campaign.emailContentRequired', 'Email subject and body are required'),
('marketing.campaign.emailSection', 'marketing', 'marketing.campaign.emailSection', 'Email content'),
('marketing.campaign.emailSubject', 'marketing', 'marketing.campaign.emailSubject', 'Subject'),
('marketing.campaign.empty', 'marketing', 'marketing.campaign.empty', 'No campaigns yet.'),
('marketing.campaign.emptyAudienceDeleted', 'marketing', 'marketing.campaign.emptyAudienceDeleted', 'No campaigns with a deleted audience — nothing to clean up.'),
('marketing.campaign.filterAudienceDeleted', 'marketing', 'marketing.campaign.filterAudienceDeleted', 'Audience deleted only'),
('marketing.campaign.ignoreQuiet', 'marketing', 'marketing.campaign.ignoreQuiet', 'Ignore branch quiet hours (defaults to 10 PM – 8 AM local, configurable per branch)'),
('marketing.campaign.intro', 'marketing', 'marketing.campaign.intro', 'Marketing broadcasts respect customer opt-outs and branch quiet hours by default.'),
('marketing.campaign.launchAction', 'marketing', 'marketing.campaign.launchAction', 'Launch'),
('marketing.campaign.launched', 'marketing', 'marketing.campaign.launched', 'Campaign launched — dispatcher will start sending shortly'),
('marketing.campaign.launchedBoth', 'marketing', 'marketing.campaign.launchedBoth', 'Email + WhatsApp campaigns launched — they will send shortly.'),
('marketing.campaign.launchFailed', 'marketing', 'marketing.campaign.launchFailed', 'Failed to launch'),
('marketing.campaign.launchPartial', 'marketing', 'marketing.campaign.launchPartial', 'Some siblings failed to launch — review the campaign list.'),
('marketing.campaign.linked', 'marketing', 'marketing.campaign.linked', 'linked'),
('marketing.campaign.linkedTooltip', 'marketing', 'marketing.campaign.linkedTooltip', 'Part of a linked Email + WhatsApp launch'),
('marketing.campaign.loadFailed', 'marketing', 'marketing.campaign.loadFailed', 'Failed to load campaigns'),
('marketing.campaign.maxPerHour', 'marketing', 'marketing.campaign.maxPerHour', 'Max messages per hour'),
('marketing.campaign.maxPerMinute', 'marketing', 'marketing.campaign.maxPerMinute', 'Max messages per minute'),
('marketing.campaign.name', 'marketing', 'marketing.campaign.name', 'Campaign name'),
('marketing.campaign.namePlaceholder', 'marketing', 'marketing.campaign.namePlaceholder', 'e.g. October VIP discount'),
('marketing.campaign.nameRequired', 'marketing', 'marketing.campaign.nameRequired', 'Campaign name is required'),
('marketing.campaign.new', 'marketing', 'marketing.campaign.new', 'New campaign'),
('marketing.campaign.newTitle', 'marketing', 'marketing.campaign.newTitle', 'New campaign'),
('marketing.campaign.noBranches', 'marketing', 'marketing.campaign.noBranches', 'No branches available'),
('marketing.campaign.noCap', 'marketing', 'marketing.campaign.noCap', 'No cap'),
('marketing.campaign.notScheduled', 'marketing', 'marketing.campaign.notScheduled', 'not scheduled'),
('marketing.campaign.of', 'marketing', 'marketing.campaign.of', 'of'),
('marketing.campaign.reachableVia', 'marketing', 'marketing.campaign.reachableVia', 'Reachable customers via'),
('marketing.campaign.report', 'marketing', 'marketing.campaign.report', 'Report'),
('marketing.campaign.segmentDeleted', 'marketing', 'marketing.campaign.segmentDeleted', 'audience deleted'),
('marketing.campaign.segmentDeletedTooltip', 'marketing', 'marketing.campaign.segmentDeletedTooltip', 'The saved audience for this campaign was deleted. Sending continues against the snapshotted rules taken at the time of deletion.'),
('marketing.campaign.send', 'marketing', 'marketing.campaign.send', 'Send'),
('marketing.campaign.sendFromBranch', 'marketing', 'marketing.campaign.sendFromBranch', 'Send from branch'),
('marketing.campaign.sendLater', 'marketing', 'marketing.campaign.sendLater', 'Schedule for…'),
('marketing.campaign.sendNow', 'marketing', 'marketing.campaign.sendNow', 'Immediately'),
('marketing.campaign.stepAudience', 'marketing', 'marketing.campaign.stepAudience', 'Audience'),
('marketing.campaign.stepChannel', 'marketing', 'marketing.campaign.stepChannel', 'Channel'),
('marketing.campaign.stepContent', 'marketing', 'marketing.campaign.stepContent', 'Content'),
('marketing.campaign.stepOf', 'marketing', 'marketing.campaign.stepOf', 'Step'),
('marketing.campaign.stepReview', 'marketing', 'marketing.campaign.stepReview', 'Review & schedule'),
('marketing.campaign.subtitle', 'marketing', 'marketing.campaign.subtitle', 'Email and WhatsApp marketing broadcasts'),
('marketing.campaign.templateLang', 'marketing', 'marketing.campaign.templateLang', 'Language code'),
('marketing.campaign.templateName', 'marketing', 'marketing.campaign.templateName', 'Template name'),
('marketing.campaign.templateRequired', 'marketing', 'marketing.campaign.templateRequired', 'WhatsApp template name is required'),
('marketing.campaign.templateVars', 'marketing', 'marketing.campaign.templateVars', 'Body variables (comma-separated, in order)'),
('marketing.campaign.templateVarsPlaceholder', 'marketing', 'marketing.campaign.templateVarsPlaceholder', 'e.g. Pizza Palace, 20%, 31 Dec'),
('marketing.campaign.test', 'marketing', 'marketing.campaign.test', 'Test'),
('marketing.campaign.throttleHint', 'marketing', 'marketing.campaign.throttleHint', 'Cap how fast this campaign sends so a big audience doesn'),
('marketing.campaign.title', 'marketing', 'marketing.campaign.title', 'Campaigns'),
('marketing.campaign.unsubscribeNote', 'marketing', 'marketing.campaign.unsubscribeNote', 'An unsubscribe footer + List-Unsubscribe header are added automatically.'),
('marketing.campaign.useAudience', 'marketing', 'marketing.campaign.useAudience', 'Use a saved audience'),
('marketing.campaign.whatsappHsmNote', 'marketing', 'marketing.campaign.whatsappHsmNote', 'WhatsApp marketing requires a pre-approved template (HSM). Approve one in Meta Business Manager first.'),
('marketing.campaign.whatsappSection', 'marketing', 'marketing.campaign.whatsappSection', 'WhatsApp content'),
('marketing.report.combined', 'marketing', 'marketing.report.combined', 'combined Email + WhatsApp'),
('marketing.report.failed', 'marketing', 'marketing.report.failed', 'Report failed'),
('marketing.report.noDeliveries', 'marketing', 'marketing.report.noDeliveries', 'No deliveries yet.'),
('marketing.report.queued', 'marketing', 'marketing.report.queued', 'Queued'),
('marketing.report.recent', 'marketing', 'marketing.report.recent', 'Recent deliveries'),
('marketing.report.sending', 'marketing', 'marketing.report.sending', 'Sending'),
('marketing.report.sent', 'marketing', 'marketing.report.sent', 'Sent'),
('marketing.report.skipped', 'marketing', 'marketing.report.skipped', 'Skipped'),
('marketing.report.title', 'marketing', 'marketing.report.title', 'Campaign report'),
('marketing.test.emailIntro', 'marketing', 'marketing.test.emailIntro', 'Enter the email address that should receive this test. Leave blank to use your account email.'),
('marketing.test.failed', 'marketing', 'marketing.test.failed', 'Test failed'),
('marketing.test.send', 'marketing', 'marketing.test.send', 'Send test'),
('marketing.test.sent', 'marketing', 'marketing.test.sent', 'Test message dispatched'),
('marketing.test.title', 'marketing', 'marketing.test.title', 'Send test'),
('marketing.test.whatsappIntro', 'marketing', 'marketing.test.whatsappIntro', 'Enter a WhatsApp phone number (with country code, e.g. +14155551234) for the test message.'),
('menu.alwaysAvailable', 'menu', 'menu.alwaysAvailable', 'Always'),
('menu.categoryScheduleHelp', 'menu', 'menu.categoryScheduleHelp', 'Limit when items in this category are orderable. Times are in the branch timezone.'),
('menu.colStock', 'menu', 'menu.colStock', 'Stock'),
('menu.editSchedule', 'menu', 'menu.editSchedule', 'Edit schedule'),
('menu.scheduled', 'menu', 'menu.scheduled', 'Scheduled'),
('menu.stockCountHelp', 'menu', 'menu.stockCountHelp', 'Blank = unlimited'),
('menu.stockToggle', 'menu', 'menu.stockToggle', 'Toggle in-stock'),
('menuManagement.branchAvailability', 'menu', 'menuManagement.branchAvailability', 'Branch availability'),
('menuManagement.disabled', 'menu', 'menuManagement.disabled', 'Disabled'),
('menuManagement.inStock', 'menu', 'menuManagement.inStock', 'In stock'),
('menuManagement.schedule', 'menu', 'menuManagement.schedule', 'Schedule'),
('menuManagement.scheduleHelp', 'menu', 'menuManagement.scheduleHelp', 'Limit when this item is orderable. Times are in the branch timezone.'),
('menuManagement.scheduleUpdated', 'menu', 'menuManagement.scheduleUpdated', 'Schedule updated'),
('menuManagement.stock', 'menu', 'menuManagement.stock', 'Stock'),
('menuManagement.stockCount', 'menu', 'menuManagement.stockCount', 'Stock count'),
('menuManagement.stockCountHelp', 'menu', 'menuManagement.stockCountHelp', 'Leave blank for unlimited. Auto-decrements per order.'),
('menuManagement.unlimited', 'menu', 'menuManagement.unlimited', 'Unlimited'),
('menuManagement.upload', 'menu', 'menuManagement.upload', 'Upload'),
('nav.adminBookings', 'nav', 'nav.adminBookings', 'Table Bookings'),
('nav.adminOrders', 'nav', 'nav.adminOrders', 'Orders'),
('nav.aiAgent', 'nav', 'nav.aiAgent', 'AI Agent'),
('nav.audiences', 'nav', 'nav.audiences', 'Audiences'),
('nav.branding', 'nav', 'nav.branding', 'Branding'),
('nav.campaigns', 'nav', 'nav.campaigns', 'Campaigns'),
('nav.channels', 'nav', 'nav.channels', 'Channels'),
('nav.changeLanguage', 'nav', 'nav.changeLanguage', 'Change language'),
('nav.chatWidget', 'nav', 'nav.chatWidget', 'Chat Widget'),
('nav.coupons', 'nav', 'nav.coupons', 'Coupons'),
('nav.demo', 'nav', 'nav.demo', 'Demo'),
('nav.emailLog', 'nav', 'nav.emailLog', 'Email Log'),
('nav.emailSettings', 'nav', 'nav.emailSettings', 'Email (SMTP)'),
('nav.emailSmtp', 'nav', 'nav.emailSmtp', 'Email (SMTP)'),
('nav.emailTemplates', 'nav', 'nav.emailTemplates', 'Email Templates'),
('nav.giftCards', 'nav', 'nav.giftCards', 'Gift Cards'),
('nav.growth', 'nav', 'nav.growth', 'Growth'),
('nav.insights', 'nav', 'nav.insights', 'Insights'),
('nav.language', 'nav', 'nav.language', 'Language'),
('nav.languages', 'nav', 'nav.languages', 'Languages'),
('nav.loyalty', 'nav', 'nav.loyalty', 'Loyalty Program'),
('nav.manage', 'nav', 'nav.manage', 'Manage'),
('nav.marketing', 'nav', 'nav.marketing', 'Marketing'),
('nav.operations', 'nav', 'nav.operations', 'Operations'),
('nav.overview', 'nav', 'nav.overview', 'Overview'),
('nav.platformKeys', 'nav', 'nav.platformKeys', 'Platform Keys'),
('nav.restaurant', 'nav', 'nav.restaurant', 'Restaurant'),
('nav.restaurants', 'nav', 'nav.restaurants', 'Restaurants'),
('nav.storefront', 'nav', 'nav.storefront', 'QR Storefront'),
('nav.support', 'nav', 'nav.support', 'Support Tools'),
('nav.upgradeRequired', 'nav', 'nav.upgradeRequired', 'upgrade required'),
('nav.whatsapp', 'nav', 'nav.whatsapp', 'WhatsApp'),
('onboarding.city', 'onboarding', 'onboarding.city', 'City'),
('onboarding.cityPlaceholder', 'onboarding', 'onboarding.cityPlaceholder', 'San Francisco'),
('onboarding.continueAnyway', 'onboarding', 'onboarding.continueAnyway', 'Continue anyway'),
('onboarding.country', 'onboarding', 'onboarding.country', 'Country'),
('onboarding.postalCode', 'onboarding', 'onboarding.postalCode', 'Postal Code'),
('onboarding.postalCodePlaceholder', 'onboarding', 'onboarding.postalCodePlaceholder', '94105'),
('onboarding.region', 'onboarding', 'onboarding.region', 'State / Region'),
('onboarding.regionPlaceholder', 'onboarding', 'onboarding.regionPlaceholder', 'CA'),
('onboarding.saveFailed', 'onboarding', 'onboarding.saveFailed', 'Could not save your details, but you can continue and edit them later from Settings.'),
('onboarding.saving', 'onboarding', 'onboarding.saving', 'Saving…'),
('onboarding.selectCountry', 'onboarding', 'onboarding.selectCountry', 'Select a country'),
('onboarding.streetAddress', 'onboarding', 'onboarding.streetAddress', 'Street Address'),
('onboarding.streetAddress2', 'onboarding', 'onboarding.streetAddress2', 'Apt / Suite / Unit (optional)'),
('onboarding.streetAddress2Placeholder', 'onboarding', 'onboarding.streetAddress2Placeholder', 'Suite 200'),
('onboarding.streetAddressPlaceholder', 'onboarding', 'onboarding.streetAddressPlaceholder', '123 Main Street'),
('orderManagement.coupon', 'orders', 'orderManagement.coupon', 'Coupon'),
('orderManagement.discount', 'orders', 'orderManagement.discount', 'Discount'),
('orderManagement.giftCard', 'orders', 'orderManagement.giftCard', 'Gift card'),
('orderManagement.giftCardBalance', 'orders', 'orderManagement.giftCardBalance', 'Gift card balance'),
('orderManagement.loyaltyPoints', 'orders', 'orderManagement.loyaltyPoints', 'Loyalty points'),
('orderManagement.manual', 'orders', 'orderManagement.manual', 'manual'),
('orderManagement.placedDirectly', 'orders', 'orderManagement.placedDirectly', 'Direct order'),
('orderManagement.placedManually', 'orders', 'orderManagement.placedManually', 'Manually entered'),
('orderManagement.placedViaPos', 'orders', 'orderManagement.placedViaPos', 'Placed via POS'),
('orderManagement.placedViaStorefront', 'orders', 'orderManagement.placedViaStorefront', 'Placed via QR Storefront'),
('orderManagement.placedViaWhatsApp', 'orders', 'orderManagement.placedViaWhatsApp', 'Placed via WhatsApp'),
('orderManagement.pointsAfterCompletion', 'orders', 'orderManagement.pointsAfterCompletion', 'Points will be credited once the order is completed.'),
('orderManagement.pointsBadgeBoth', 'orders', 'orderManagement.pointsBadgeBoth', 'orderManagement.pointsBadgeBoth'),
('orderManagement.pointsBadgeEarned', 'orders', 'orderManagement.pointsBadgeEarned', 'orderManagement.pointsBadgeEarned'),
('orderManagement.pointsBadgeRedeemed', 'orders', 'orderManagement.pointsBadgeRedeemed', 'orderManagement.pointsBadgeRedeemed'),
('orderManagement.pointsEarned', 'orders', 'orderManagement.pointsEarned', 'orderManagement.pointsEarned'),
('orderManagement.pointsProjected', 'orders', 'orderManagement.pointsProjected', 'orderManagement.pointsProjected'),
('orderManagement.pointsRedeemed', 'orders', 'orderManagement.pointsRedeemed', 'orderManagement.pointsRedeemed'),
('orderManagement.pos', 'orders', 'orderManagement.pos', 'POS'),
('orderManagement.storefront', 'orders', 'orderManagement.storefront', 'storefront'),
('orderManagement.totalPaid', 'orders', 'orderManagement.totalPaid', 'Total paid'),
('orderManagement.whatsapp', 'orders', 'orderManagement.whatsapp', 'WhatsApp'),
('phoneNumbers.providerSip', 'phone_numbers', 'phoneNumbers.providerSip', 'SIP / jambonz'),
('phoneNumbers.providerTwilio', 'phone_numbers', 'phoneNumbers.providerTwilio', 'Twilio'),
('phoneNumbers.table.provider', 'phone_numbers', 'phoneNumbers.table.provider', 'Provider'),
('providerKeys.active', 'provider_keys', 'providerKeys.active', 'Active'),
('providerKeys.addKey', 'provider_keys', 'providerKeys.addKey', 'Add Key'),
('providerKeys.byok.description', 'provider_keys', 'providerKeys.byok.description', 'Add your own API keys for AI providers. Keys are encrypted at rest using AES-256-GCM.'),
('providerKeys.byok.title', 'provider_keys', 'providerKeys.byok.title', 'Bring Your Own Keys (BYOK)'),
('providerKeys.errors.delete', 'provider_keys', 'providerKeys.errors.delete', 'Failed to delete key'),
('providerKeys.errors.load', 'provider_keys', 'providerKeys.errors.load', 'Failed to load API keys'),
('providerKeys.errors.save', 'provider_keys', 'providerKeys.errors.save', 'Failed to save key'),
('providerKeys.keyPlaceholder', 'provider_keys', 'providerKeys.keyPlaceholder', 'Enter your {name} API key'),
('providerKeys.loading', 'provider_keys', 'providerKeys.loading', 'Loading API keys...'),
('providerKeys.removeKey', 'provider_keys', 'providerKeys.removeKey', 'Remove key'),
('providerKeys.removeModal.confirm', 'provider_keys', 'providerKeys.removeModal.confirm', 'Remove'),
('providerKeys.removeModal.message', 'provider_keys', 'providerKeys.removeModal.message', 'Are you sure you want to remove this API key? This provider will stop working for your restaurant.'),
('providerKeys.removeModal.title', 'provider_keys', 'providerKeys.removeModal.title', 'Remove API Key'),
('providerKeys.success.removed', 'provider_keys', 'providerKeys.success.removed', '{name} key removed'),
('providerKeys.success.saved', 'provider_keys', 'providerKeys.success.saved', '{name} key saved'),
('providerKeys.systemDefault', 'provider_keys', 'providerKeys.systemDefault', 'System Default'),
('providerKeys.update', 'provider_keys', 'providerKeys.update', 'Update'),
('restApi.reference.openapi', 'api', 'restApi.reference.openapi', 'OpenAPI spec'),
('restaurantSettings.billing.checkoutFailed', 'restaurant_settings', 'restaurantSettings.billing.checkoutFailed', 'Failed to start checkout'),
('restaurantSettings.billing.features.apiCallsUnit', 'restaurant_settings', 'restaurantSettings.billing.features.apiCallsUnit', 'API calls/min'),
('restaurantSettings.billing.features.conversationsUnit', 'restaurant_settings', 'restaurantSettings.billing.features.conversationsUnit', 'AI conversations/mo'),
('restaurantSettings.billing.features.voiceCallsUnit', 'restaurant_settings', 'restaurantSettings.billing.features.voiceCallsUnit', 'concurrent voice calls'),
('restaurantSettings.billing.stripeNotConfigured', 'restaurant_settings', 'restaurantSettings.billing.stripeNotConfigured', 'Stripe is not configured. Please contact support to upgrade your plan.'),
('restaurantSettings.profile.bookingBufferHint', 'restaurant_settings', 'restaurantSettings.profile.bookingBufferHint', 'Time kept clear between consecutive bookings on the same table.'),
('restaurantSettings.profile.bookingBufferLabel', 'restaurant_settings', 'restaurantSettings.profile.bookingBufferLabel', 'Default turnover buffer (minutes)'),
('restaurantSettings.profile.bookingDurationHint', 'restaurant_settings', 'restaurantSettings.profile.bookingDurationHint', 'How long a reservation occupies a table by default.'),
('restaurantSettings.profile.bookingDurationLabel', 'restaurant_settings', 'restaurantSettings.profile.bookingDurationLabel', 'Default booking duration (minutes)'),
('restaurantSettings.tabs.emailSmtp', 'restaurant_settings', 'restaurantSettings.tabs.emailSmtp', 'Email (SMTP)'),
('settings.changePassword', 'settings', 'settings.changePassword', 'Change Password'),
('sidebar.defaultRestaurantName', 'nav', 'sidebar.defaultRestaurantName', 'My Restaurant'),
('sidebar.defaultUserName', 'nav', 'sidebar.defaultUserName', 'User'),
('smtp.actions.clear', 'smtp', 'smtp.actions.clear', 'Clear'),
('smtp.description', 'smtp', 'smtp.description', 'Configure outbound SMTP per branch for order & booking confirmation emails.'),
('smtp.errors.clearFailed', 'smtp', 'smtp.errors.clearFailed', 'Clear failed'),
('smtp.errors.failedToClear', 'smtp', 'smtp.errors.failedToClear', 'Failed to clear'),
('smtp.errors.loadBranch', 'smtp', 'smtp.errors.loadBranch', 'Failed to load branch SMTP settings'),
('smtp.fields.fromAddress', 'smtp', 'smtp.fields.fromAddress', 'From Address'),
('smtp.fields.fromPlaceholder', 'smtp', 'smtp.fields.fromPlaceholder', 'noreply@example.com (optional, defaults to username)'),
('smtp.fields.host', 'smtp', 'smtp.fields.host', 'SMTP Host'),
('smtp.fields.password', 'smtp', 'smtp.fields.password', 'Password'),
('smtp.fields.passwordKeep', 'smtp', 'smtp.fields.passwordKeep', 'Leave blank to keep existing password'),
('smtp.fields.passwordPlaceholder', 'smtp', 'smtp.fields.passwordPlaceholder', 'SMTP password or app password'),
('smtp.fields.port', 'smtp', 'smtp.fields.port', 'Port'),
('smtp.fields.username', 'smtp', 'smtp.fields.username', 'Username'),
('smtp.label', 'smtp', 'smtp.label', 'Email (SMTP)'),
('smtp.loadingBranches', 'smtp', 'smtp.loadingBranches', 'Loading branches…'),
('smtp.selectBranch', 'smtp', 'smtp.selectBranch', '— Select a branch —'),
('smtp.success.saved', 'smtp', 'smtp.success.saved', 'SMTP settings saved'),
('social.github', 'social', 'social.github', 'GitHub'),
('social.linkedin', 'social', 'social.linkedin', 'LinkedIn'),
('social.twitter', 'social', 'social.twitter', 'Twitter / X'),
('social.youtube', 'social', 'social.youtube', 'YouTube'),
('storefront.editor.backToList', 'storefront', 'storefront.editor.backToList', 'Back to QR Storefront'),
('storefront.editor.banner', 'storefront', 'storefront.editor.banner', 'Storefront banner message'),
('storefront.editor.bannerPlaceholder', 'storefront', 'storefront.editor.bannerPlaceholder', 'Holiday hours, special promo, etc.'),
('storefront.editor.delivery', 'storefront', 'storefront.editor.delivery', 'Accept delivery'),
('storefront.editor.dineIn', 'storefront', 'storefront.editor.dineIn', 'Accept dine-in (QR table)'),
('storefront.editor.downloadPdf', 'storefront', 'storefront.editor.downloadPdf', 'Print-ready PDF'),
('storefront.editor.enabled', 'storefront', 'storefront.editor.enabled', 'Storefront enabled'),
('storefront.editor.manageTables', 'storefront', 'storefront.editor.manageTables', 'Manage tables'),
('storefront.editor.minOrder', 'storefront', 'storefront.editor.minOrder', 'Minimum order'),
('storefront.editor.notFound', 'storefront', 'storefront.editor.notFound', 'Branch not found'),
('storefront.editor.openPublic', 'storefront', 'storefront.editor.openPublic', 'Open public storefront'),
('storefront.editor.payInPersonNote', 'storefront', 'storefront.editor.payInPersonNote', 'Storefront orders are pay-in-person (cash on delivery / pay at counter).'),
('storefront.editor.pdfFailed', 'storefront', 'storefront.editor.pdfFailed', 'Failed to generate PDF'),
('storefront.editor.qrCaption', 'storefront', 'storefront.editor.qrCaption', 'Branch storefront'),
('storefront.editor.qrDesignHelp', 'storefront', 'storefront.editor.qrDesignHelp', 'This style is used for every table QR card and the printed PDF. Changes preview live.'),
('storefront.editor.qrDesignTitle', 'storefront', 'storefront.editor.qrDesignTitle', 'QR design'),
('storefront.editor.restaurantSlugMissing', 'storefront', 'storefront.editor.restaurantSlugMissing', 'Set a restaurant slug in Settings before designing the QR.'),
('storefront.editor.save', 'storefront', 'storefront.editor.save', 'Save storefront & QR'),
('storefront.editor.saved', 'storefront', 'storefront.editor.saved', 'Storefront saved'),
('storefront.editor.savePublishFirst', 'storefront', 'storefront.editor.savePublishFirst', 'Save the storefront with a valid slug first.'),
('storefront.editor.settingsTitle', 'storefront', 'storefront.editor.settingsTitle', 'Storefront settings'),
('storefront.editor.slug', 'storefront', 'storefront.editor.slug', 'Branch slug'),
('storefront.editor.slugHelp', 'storefront', 'storefront.editor.slugHelp', 'Used in the public URL — lowercase letters, digits, hyphens.'),
('storefront.editor.slugInvalid', 'storefront', 'storefront.editor.slugInvalid', 'Slug must be lowercase letters, digits and hyphens (e.g. downtown).'),
('storefront.editor.slugPlaceholder', 'storefront', 'storefront.editor.slugPlaceholder', 'downtown'),
('storefront.editor.subtitle', 'storefront', 'storefront.editor.subtitle', 'Design the QR and storefront for this branch'),
('storefront.editor.takeaway', 'storefront', 'storefront.editor.takeaway', 'Accept takeaway / pickup'),
('storefront.editor.title', 'storefront', 'storefront.editor.title', 'QR Storefront'),
('storefront.gate.cta', 'storefront', 'storefront.gate.cta', 'View plans & upgrade'),
('storefront.gate.notSignedInEdit', 'storefront', 'storefront.gate.notSignedInEdit', 'You need to be signed in to a restaurant to edit the QR Storefront.'),
('storefront.gate.notSignedInView', 'storefront', 'storefront.gate.notSignedInView', 'You need to be signed in to a restaurant to view the QR Storefront.'),
('storefront.gate.title', 'storefront', 'storefront.gate.title', 'QR Storefront is not in your plan'),
('storefront.hub.createBranch', 'storefront', 'storefront.hub.createBranch', 'Create one in Branches'),
('storefront.hub.disabled', 'storefront', 'storefront.hub.disabled', 'Disabled'),
('storefront.hub.empty', 'storefront', 'storefront.hub.empty', 'No branches yet.'),
('storefront.hub.enabled', 'storefront', 'storefront.hub.enabled', 'Enabled'),
('storefront.hub.first', 'storefront', 'storefront.hub.first', 'first.'),
('storefront.hub.intro', 'storefront', 'storefront.hub.intro', 'Choose a branch to design its QR, edit storefront settings, and download print-ready cards.'),
('storefront.hub.needsSetup', 'storefront', 'storefront.hub.needsSetup', 'Needs setup'),
('storefront.hub.noSlug', 'storefront', 'storefront.hub.noSlug', 'no slug'),
('storefront.hub.openEditor', 'storefront', 'storefront.hub.openEditor', 'Edit QR & storefront'),
('storefront.hub.preview', 'storefront', 'storefront.hub.preview', 'Preview'),
('storefront.hub.qrAlt', 'storefront', 'storefront.hub.qrAlt', 'QR code'),
('storefront.hub.restaurantSlugMissing', 'storefront', 'storefront.hub.restaurantSlugMissing', 'Set restaurant slug'),
('storefront.hub.setUp', 'storefront', 'storefront.hub.setUp', 'Set up'),
('storefront.hub.subtitle', 'storefront', 'storefront.hub.subtitle', 'Per-table QR codes and customer-facing storefront'),
('storefront.hub.title', 'storefront', 'storefront.hub.title', 'QR Storefront'),
('tableBooking.createBooking', 'table_booking', 'tableBooking.createBooking', 'Create booking'),
('tableBooking.guestName', 'table_booking', 'tableBooking.guestName', 'Guest name'),
('tableBooking.guestNamePlaceholder', 'table_booking', 'tableBooking.guestNamePlaceholder', 'e.g. Walk-in / Smith'),
('tableBooking.guestRequired', 'table_booking', 'tableBooking.guestRequired', 'Guest name is required'),
('tableBooking.loadFailed', 'table_booking', 'tableBooking.loadFailed', 'Failed to load timeline'),
('tableBooking.newBooking', 'table_booking', 'tableBooking.newBooking', 'New booking'),
('tableBooking.tableLabel', 'table_booking', 'tableBooking.tableLabel', 'Table'),
('tableBooking.timeline.day', 'table_booking', 'tableBooking.timeline.day', 'Day'),
('tableBooking.timeline.nextDay', 'table_booking', 'tableBooking.timeline.nextDay', 'Next day'),
('tableBooking.timeline.noTables', 'table_booking', 'tableBooking.timeline.noTables', 'No active tables. Add tables in the Tables section first.'),
('tableBooking.timeline.prevDay', 'table_booking', 'tableBooking.timeline.prevDay', 'Previous day'),
('tableBooking.timeline.title', 'table_booking', 'tableBooking.timeline.title', 'Floor timeline'),
('tableBooking.timeline.unassigned', 'table_booking', 'tableBooking.timeline.unassigned', '{count} booking(s) without a table — drag onto the grid to assign.'),
('tableBooking.timeline.week', 'table_booking', 'tableBooking.timeline.week', 'Week'),
('tableBooking.walkInCreated', 'table_booking', 'tableBooking.walkInCreated', 'Booking created'),
('tables.banner.editStorefront', 'tables', 'tables.banner.editStorefront', 'Edit QR design & storefront settings'),
('tables.banner.movedTo', 'tables', 'tables.banner.movedTo', '— moved to QR Storefront'),
('tables.banner.open', 'tables', 'tables.banner.open', 'Open'),
('topbar.agentOnline', 'topbar', 'topbar.agentOnline', 'Agent Online'),
('topbar.allBranches', 'topbar', 'topbar.allBranches', 'All Branches'),
('topbar.allBranchesDesc', 'topbar', 'topbar.allBranchesDesc', 'Restaurant-wide view'),
('topbar.changePassword', 'topbar', 'topbar.changePassword', 'Change Password'),
('topbar.logOut', 'topbar', 'topbar.logOut', 'Log Out'),
('topbar.manageBranches', 'topbar', 'topbar.manageBranches', 'Manage Branches →'),
('topbar.markAllRead', 'topbar', 'topbar.markAllRead', 'Mark all read'),
('topbar.new', 'topbar', 'topbar.new', 'new'),
('topbar.noNotifications', 'topbar', 'topbar.noNotifications', 'No notifications yet'),
('topbar.notifications', 'topbar', 'topbar.notifications', 'Notifications'),
('topbar.platformOnline', 'topbar', 'topbar.platformOnline', 'Platform Online'),
('topbar.selectBranch', 'topbar', 'topbar.selectBranch', 'Select Branch'),
('topbar.settings', 'topbar', 'topbar.settings', 'Settings'),
('topbar.switchBranch', 'topbar', 'topbar.switchBranch', 'Switch Branch'),
('topbar.toggleMenu', 'topbar', 'topbar.toggleMenu', 'Toggle menu'),
('topbar.viewAllNotifications', 'topbar', 'topbar.viewAllNotifications', 'View all notifications'),
('verify.alreadySent', 'verify', 'verify.alreadySent', 'A code was just sent — check your inbox.'),
('verify.button', 'verify', 'verify.button', 'Verify & continue'),
('verify.changeEmail', 'verify', 'verify.changeEmail', 'Change email'),
('verify.didntReceive', 'verify', 'verify.didntReceive', 'Didn'),
('verify.expiresIn', 'verify', 'verify.expiresIn', 'It expires in 10 minutes.'),
('verify.failed', 'verify', 'verify.failed', 'Verification failed. Please try again.'),
('verify.invalidCode', 'verify', 'verify.invalidCode', 'Enter the 6-digit code from your email'),
('verify.resend', 'verify', 'verify.resend', 'Resend code'),
('verify.resendIn', 'verify', 'verify.resendIn', 'Resend in'),
('verify.resent', 'verify', 'verify.resent', 'A new code is on its way.'),
('verify.sentTo', 'verify', 'verify.sentTo', 'We sent a 6-digit code to'),
('verify.title', 'verify', 'verify.title', 'Verify your email'),
('whatsapp.branches', 'whatsapp', 'whatsapp.branches', 'Branches'),
('whatsapp.creds.help', 'whatsapp', 'whatsapp.creds.help', 'Find these in your WhatsApp Business app: Phone Number ID and WABA ID under API Setup, Access Token under System Users, and App Secret under Basic Settings.'),
('whatsapp.creds.title', 'whatsapp', 'whatsapp.creds.title', 'Step 2 — Save your Meta credentials'),
('whatsapp.noBranches', 'whatsapp', 'whatsapp.noBranches', 'You need at least one active branch before connecting WhatsApp.'),
('whatsapp.subtitle', 'whatsapp', 'whatsapp.subtitle', 'Connect each branch to a Meta WhatsApp Business phone number. Customers will chat with your AI agent over WhatsApp.'),
('whatsapp.title', 'whatsapp', 'whatsapp.title', 'WhatsApp Business'),
('whatsapp.webhook.help', 'whatsapp', 'whatsapp.webhook.help', 'Paste these into your WhatsApp Business app under Webhooks, then subscribe to the "messages" field.'),
('whatsapp.webhook.title', 'whatsapp', 'whatsapp.webhook.title', 'Step 1 — Configure Meta webhook'),
('account.changeEmail',           'account', 'Change email section header',       'Change email'),
('account.currentEmail',          'account', 'Current email label',               'Current email'),
('account.newEmail',              'account', 'New email input label',              'New email address'),
('account.newEmailPlaceholder',   'account', 'New email placeholder',              'you@example.com'),
('account.sendCode',              'account', 'Send OTP button',                   'Send verification code'),
('account.codeSent',              'account', 'Code sent notice',                  'A 6-digit code was sent to {{email}}'),
('account.enterCode',             'account', 'OTP input label',                   'Verification code'),
('account.confirmEmail',          'account', 'Confirm email button',              'Confirm new email'),
('account.emailUpdated',          'account', 'Success toast',                     'Email updated successfully'),
('account.emailTaken',            'account', 'Email already taken error',         'This email is already in use'),
('account.invalidCode',           'account', 'Wrong OTP error',                   'Invalid or expired code'),
('account.changeEmailBack',       'account', 'Back link label',                   'Use a different email'),
('admin.users.changeEmail',       'admin',   'Admin: change user email label',    'Change email'),
('admin.users.emailUpdated',      'admin',   'Admin: email updated toast',        'Email updated'),
('admin.users.emailUpdateFailed', 'admin',   'Admin: email update failure',       'Failed to update email'),
('account.sendCodeError',         'account', 'Error sending verification code',   'Failed to send verification code')
ON CONFLICT (key) DO NOTHING;

-- Fix single-brace placeholders that prevent {{key}} interpolation in t()
UPDATE public.translation_keys SET default_value = '{{sec}}s'  WHERE key = 'common.secondsShort'                     AND default_value = '{sec}s';
UPDATE public.translation_keys SET default_value = '{{min}}m'  WHERE key = 'common.minutesShort'                     AND default_value = '{min}m';
UPDATE public.translation_keys SET default_value = 'Alerts will automatically dismiss after {{sec}} seconds if not acted upon' WHERE key = 'restaurantSettings.alerts.dismiss.subtitle' AND default_value = 'Alerts will automatically dismiss after {sec} seconds if not acted upon';
-- Also fix any translations seeded from the old default_value (translations table uses key_id FK)
UPDATE public.translations t SET value = '{{sec}}s'  FROM public.translation_keys tk WHERE t.key_id = tk.id AND tk.key = 'common.secondsShort'                     AND t.value = '{sec}s';
UPDATE public.translations t SET value = '{{min}}m'  FROM public.translation_keys tk WHERE t.key_id = tk.id AND tk.key = 'common.minutesShort'                     AND t.value = '{min}m';
UPDATE public.translations t SET value = 'Alerts will automatically dismiss after {{sec}} seconds if not acted upon' FROM public.translation_keys tk WHERE t.key_id = tk.id AND tk.key = 'restaurantSettings.alerts.dismiss.subtitle' AND t.value = 'Alerts will automatically dismiss after {sec} seconds if not acted upon';

-- Fix single-brace placeholders in billing, templates, and webhooks
-- (billing.features.branches: replaces legacy '{count} branch{s}' with plain 'branches')
UPDATE public.translation_keys SET default_value = 'of {{limit}} {{unit}}' WHERE key = 'restaurantSettings.billing.usage.ofLimit' AND default_value = 'of {limit} {unit}';
UPDATE public.translation_keys SET default_value = '{{pct}}% used' WHERE key = 'restaurantSettings.billing.usage.pctUsed' AND default_value = '{pct}% used';
UPDATE public.translation_keys SET default_value = 'Save ' || chr(36) || '{{amount}}/year' WHERE key = 'restaurantSettings.billing.saveAnnual' AND default_value LIKE 'Save%{amount}/year';
UPDATE public.translation_keys SET default_value = 'branches' WHERE key = 'restaurantSettings.billing.features.branches' AND default_value = '{count} branch{s}';
UPDATE public.translation_keys SET default_value = '{{count}} characters' WHERE key = 'restaurantSettings.templates.charCount' AND default_value = '{count} characters';
UPDATE public.translation_keys SET default_value = '{{count}} SMS segments' WHERE key = 'restaurantSettings.templates.smsSegments' AND default_value = '{count} SMS segments';
UPDATE public.translation_keys SET default_value = '{{rate}}% success · {{deliveries}} deliveries' WHERE key = 'restaurantSettings.webhooks.stats' AND default_value = '{rate}% success · {deliveries} deliveries';
-- Also fix any translated values seeded from the old default_value
UPDATE public.translations t SET value = 'of {{limit}} {{unit}}' FROM public.translation_keys tk WHERE t.key_id = tk.id AND tk.key = 'restaurantSettings.billing.usage.ofLimit' AND t.value = 'of {limit} {unit}';
UPDATE public.translations t SET value = '{{pct}}% used' FROM public.translation_keys tk WHERE t.key_id = tk.id AND tk.key = 'restaurantSettings.billing.usage.pctUsed' AND t.value = '{pct}% used';
UPDATE public.translations t SET value = 'Save ' || chr(36) || '{{amount}}/year' FROM public.translation_keys tk WHERE t.key_id = tk.id AND tk.key = 'restaurantSettings.billing.saveAnnual' AND t.value LIKE 'Save%{amount}/year';
UPDATE public.translations t SET value = 'branches' FROM public.translation_keys tk WHERE t.key_id = tk.id AND tk.key = 'restaurantSettings.billing.features.branches' AND t.value = '{count} branch{s}';
UPDATE public.translations t SET value = '{{count}} characters' FROM public.translation_keys tk WHERE t.key_id = tk.id AND tk.key = 'restaurantSettings.templates.charCount' AND t.value = '{count} characters';
UPDATE public.translations t SET value = '{{count}} SMS segments' FROM public.translation_keys tk WHERE t.key_id = tk.id AND tk.key = 'restaurantSettings.templates.smsSegments' AND t.value = '{count} SMS segments';
UPDATE public.translations t SET value = '{{rate}}% success · {{deliveries}} deliveries' FROM public.translation_keys tk WHERE t.key_id = tk.id AND tk.key = 'restaurantSettings.webhooks.stats' AND t.value = '{rate}% success · {deliveries} deliveries';

-- Seed translated values for nav section headers in all supported non-English locales
INSERT INTO public.translations (lang_code, key_id, value)
SELECT l.lang_code, tk.id, l.value
FROM public.translation_keys tk
JOIN (VALUES
  ('hi', 'nav.channels',  'चैनल'),
  ('de', 'nav.channels',  'Kanäle'),
  ('fr', 'nav.channels',  'Canaux'),
  ('ru', 'nav.channels',  'Каналы'),
  ('ar', 'nav.channels',  'القنوات'),
  ('hi', 'nav.growth',    'विकास'),
  ('de', 'nav.growth',    'Wachstum'),
  ('fr', 'nav.growth',    'Croissance'),
  ('ru', 'nav.growth',    'Рост'),
  ('ar', 'nav.growth',    'النمو'),
  ('hi', 'nav.manage',    'प्रबंधन'),
  ('de', 'nav.manage',    'Verwalten'),
  ('fr', 'nav.manage',    'Gérer'),
  ('ru', 'nav.manage',    'Управление'),
  ('ar', 'nav.manage',    'الإدارة'),
  ('hi', 'nav.overview',  'अवलोकन'),
  ('de', 'nav.overview',  'Übersicht'),
  ('fr', 'nav.overview',  'Aperçu'),
  ('ru', 'nav.overview',  'Обзор'),
  ('ar', 'nav.overview',  'نظرة عامة')
) AS l(lang_code, key, value) ON l.key = tk.key
ON CONFLICT (lang_code, key_id) DO NOTHING;

-- Task #320: Non-English translations for restored homepage sections
-- (stats band, how-it-works, channels→inbox flow, preview, ROI calculator, mock dashboard)
-- Supports: hi (Hindi), de (German), fr (French), ru (Russian), ar (Arabic)
INSERT INTO public.translations (lang_code, key_id, value)
SELECT v.lang, tk.id, v.val
FROM (VALUES
  -- ── Stats band ──────────────────────────────────────────────────────────
  ('hi', 'landing.home.stat1Label', 'दुनिया भर के रेस्तरां'),
  ('de', 'landing.home.stat1Label', 'Restaurants weltweit'),
  ('fr', 'landing.home.stat1Label', 'Restaurants dans le monde'),
  ('ru', 'landing.home.stat1Label', 'Ресторанов по всему миру'),
  ('ar', 'landing.home.stat1Label', 'مطاعم حول العالم'),

  ('hi', 'landing.home.stat1Sub', '40+ देशों में'),
  ('de', 'landing.home.stat1Sub', 'In über 40 Ländern'),
  ('fr', 'landing.home.stat1Sub', 'Dans plus de 40 pays'),
  ('ru', 'landing.home.stat1Sub', 'В более чем 40 странах'),
  ('ar', 'landing.home.stat1Sub', 'عبر أكثر من 40 دولة'),

  ('hi', 'landing.home.stat2Label', 'कॉल संभाले गए'),
  ('de', 'landing.home.stat2Label', 'Anrufe bearbeitet'),
  ('fr', 'landing.home.stat2Label', 'Appels traités'),
  ('ru', 'landing.home.stat2Label', 'Звонков обработано'),
  ('ar', 'landing.home.stat2Label', 'المكالمات المُعالجة'),

  ('hi', 'landing.home.stat2Sub', 'कोई भी मिस नहीं, हर बार'),
  ('de', 'landing.home.stat2Sub', 'Keiner verpasst, jedes Mal'),
  ('fr', 'landing.home.stat2Sub', 'Aucun manqué, à chaque fois'),
  ('ru', 'landing.home.stat2Sub', 'Ни одного пропущенного'),
  ('ar', 'landing.home.stat2Sub', 'لا يفوتنا أي مكالمة'),

  ('hi', 'landing.home.stat3Label', 'AI समाधान दर'),
  ('de', 'landing.home.stat3Label', 'KI-Lösungsrate'),
  ('fr', 'landing.home.stat3Label', 'Taux de résolution IA'),
  ('ru', 'landing.home.stat3Label', 'Решений без участия человека'),
  ('ar', 'landing.home.stat3Label', 'معدل حل الذكاء الاصطناعي'),

  ('hi', 'landing.home.stat3Sub', 'कोई इंसान नहीं चाहिए'),
  ('de', 'landing.home.stat3Sub', 'Kein Mensch nötig'),
  ('fr', 'landing.home.stat3Sub', 'Sans intervention humaine'),
  ('ru', 'landing.home.stat3Sub', 'Без участия человека'),
  ('ar', 'landing.home.stat3Sub', 'دون الحاجة إلى إنسان'),

  ('hi', 'landing.home.stat4Label', 'औसत प्रतिक्रिया समय'),
  ('de', 'landing.home.stat4Label', 'Ø Antwortzeit'),
  ('fr', 'landing.home.stat4Label', 'Temps de réponse moyen'),
  ('ru', 'landing.home.stat4Label', 'Среднее время ответа'),
  ('ar', 'landing.home.stat4Label', 'متوسط وقت الاستجابة'),

  ('hi', 'landing.home.stat4Sub', 'किसी भी कर्मचारी से तेज़'),
  ('de', 'landing.home.stat4Sub', 'Schneller als jeder Mitarbeiter'),
  ('fr', 'landing.home.stat4Sub', 'Plus rapide que tout employé'),
  ('ru', 'landing.home.stat4Sub', 'Быстрее любого сотрудника'),
  ('ar', 'landing.home.stat4Sub', 'أسرع من أي موظف'),

  -- ── How it works ────────────────────────────────────────────────────────
  ('hi', 'landing.home.howEyebrow', 'यह कैसे काम करता है'),
  ('de', 'landing.home.howEyebrow', 'Wie es funktioniert'),
  ('fr', 'landing.home.howEyebrow', 'Comment ça marche'),
  ('ru', 'landing.home.howEyebrow', 'Как это работает'),
  ('ar', 'landing.home.howEyebrow', 'كيف يعمل'),

  ('hi', 'landing.home.howTitle', 'दो घंटे में लाइव, दो महीने नहीं'),
  ('de', 'landing.home.howTitle', 'In zwei Stunden live, nicht zwei Monate'),
  ('fr', 'landing.home.howTitle', 'Opérationnel en deux heures, pas deux mois'),
  ('ru', 'landing.home.howTitle', 'Запуск за два часа, а не за два месяца'),
  ('ar', 'landing.home.howTitle', 'انطلق في ساعتين لا شهرين'),

  ('hi', 'landing.home.howSub', 'पूरी तरह से स्वचालित फ्रंट-ऑफ-हाउस के लिए तीन सरल चरण — कनेक्ट करें, प्रशिक्षित करें, लाइव हों।'),
  ('de', 'landing.home.howSub', 'Drei einfache Schritte zu einem vollautomatischen Frontbereich — verbinden, trainieren, live gehen.'),
  ('fr', 'landing.home.howSub', 'Trois étapes simples pour un service entièrement automatisé — connecter, former, lancer.'),
  ('ru', 'landing.home.howSub', 'Три простых шага к полностью автоматизированному приёму гостей — подключитесь, обучите, запускайте.'),
  ('ar', 'landing.home.howSub', 'ثلاث خطوات بسيطة لأتمتة كاملة في الواجهة — اتصل، درّب، انطلق.'),

  ('hi', 'landing.home.howStep1Title', 'कनेक्ट करें'),
  ('de', 'landing.home.howStep1Title', 'Verbinden'),
  ('fr', 'landing.home.howStep1Title', 'Connecter'),
  ('ru', 'landing.home.howStep1Title', 'Подключение'),
  ('ar', 'landing.home.howStep1Title', 'اتصال'),

  ('hi', 'landing.home.howStep1Desc', 'मिनटों में अपना फोन नंबर, POS और मेनू प्लग इन करें — कोई डेवलपर की आवश्यकता नहीं।'),
  ('de', 'landing.home.howStep1Desc', 'Verbinden Sie Ihre Telefonnummer, POS und Speisekarte in Minuten — keine Entwickler erforderlich.'),
  ('fr', 'landing.home.howStep1Desc', 'Connectez votre numéro de téléphone, votre POS et votre menu en quelques minutes — sans développeur.'),
  ('ru', 'landing.home.howStep1Desc', 'Подключите телефонный номер, кассу и меню за несколько минут — без разработчиков.'),
  ('ar', 'landing.home.howStep1Desc', 'قم بتوصيل رقم هاتفك ونقطة البيع وقائمة الطعام في دقائق — دون الحاجة إلى مطورين.'),

  ('hi', 'landing.home.howStep2Title', 'प्रशिक्षण'),
  ('de', 'landing.home.howStep2Title', 'Trainieren'),
  ('fr', 'landing.home.howStep2Title', 'Former'),
  ('ru', 'landing.home.howStep2Title', 'Обучение'),
  ('ar', 'landing.home.howStep2Title', 'تدريب'),

  ('hi', 'landing.home.howStep2Desc', 'मेनू, घंटे और FAQ अपलोड करें। AI स्वचालित रूप से आपकी ब्रांड आवाज़ और नीतियां सीखता है।'),
  ('de', 'landing.home.howStep2Desc', 'Laden Sie Speisekarten, Öffnungszeiten und FAQs hoch. Die KI lernt automatisch Ihre Markenstimme und Richtlinien.'),
  ('fr', 'landing.home.howStep2Desc', 'Téléchargez vos menus, horaires et FAQ. L''IA apprend automatiquement votre voix de marque et vos politiques.'),
  ('ru', 'landing.home.howStep2Desc', 'Загрузите меню, часы работы и FAQ. ИИ автоматически обучается вашему фирменному стилю и политикам.'),
  ('ar', 'landing.home.howStep2Desc', 'ارفع القوائم وساعات العمل والأسئلة الشائعة. يتعلم الذكاء الاصطناعي أسلوب علامتك وسياساتك تلقائياً.'),

  ('hi', 'landing.home.howStep3Title', 'लाइव हों'),
  ('de', 'landing.home.howStep3Title', 'Live gehen'),
  ('fr', 'landing.home.howStep3Title', 'Lancer'),
  ('ru', 'landing.home.howStep3Title', 'Запуск'),
  ('ar', 'landing.home.howStep3Title', 'انطلق الآن'),

  ('hi', 'landing.home.howStep3Desc', 'स्विच पलटें। हर कॉल, चैट और बुकिंग का जवाब चौबीसों घंटे दिया जाता है — किसी भी भाषा में।'),
  ('de', 'landing.home.howStep3Desc', 'Schalten Sie ein. Jeder Anruf, Chat und jede Buchung wird rund um die Uhr beantwortet — in jeder Sprache.'),
  ('fr', 'landing.home.howStep3Desc', 'Activez le système. Chaque appel, chat et réservation reçoit une réponse 24h/24 — dans toutes les langues.'),
  ('ru', 'landing.home.howStep3Desc', 'Включите систему. Каждый звонок, чат и бронирование обрабатываются круглосуточно — на любом языке.'),
  ('ar', 'landing.home.howStep3Desc', 'افتح المفتاح. كل مكالمة ومحادثة وحجز يُجاب عليه على مدار الساعة — بأي لغة.'),

  -- ── Channels → Inbox flow ───────────────────────────────────────────────
  ('hi', 'landing.home.flowCh1', 'फोन'),
  ('de', 'landing.home.flowCh1', 'Telefon'),
  ('fr', 'landing.home.flowCh1', 'Téléphone'),
  ('ru', 'landing.home.flowCh1', 'Телефон'),
  ('ar', 'landing.home.flowCh1', 'هاتف'),

  ('hi', 'landing.home.flowCh2', 'व्हाट्सऐप'),
  ('de', 'landing.home.flowCh2', 'WhatsApp'),
  ('fr', 'landing.home.flowCh2', 'WhatsApp'),
  ('ru', 'landing.home.flowCh2', 'WhatsApp'),
  ('ar', 'landing.home.flowCh2', 'واتساب'),

  ('hi', 'landing.home.flowCh3', 'वेब चैट'),
  ('de', 'landing.home.flowCh3', 'Web-Chat'),
  ('fr', 'landing.home.flowCh3', 'Chat web'),
  ('ru', 'landing.home.flowCh3', 'Веб-чат'),
  ('ar', 'landing.home.flowCh3', 'دردشة الويب'),

  ('hi', 'landing.home.flowInboxTitle', 'एकीकृत इनबॉक्स'),
  ('de', 'landing.home.flowInboxTitle', 'Einheitlicher Posteingang'),
  ('fr', 'landing.home.flowInboxTitle', 'Boîte de réception unifiée'),
  ('ru', 'landing.home.flowInboxTitle', 'Единый почтовый ящик'),
  ('ar', 'landing.home.flowInboxTitle', 'صندوق وارد موحّد'),

  ('hi', 'landing.home.flowItem1Name', 'टेबल 7 — डाइन-इन'),
  ('de', 'landing.home.flowItem1Name', 'Tisch 7 — Restaurant'),
  ('fr', 'landing.home.flowItem1Name', 'Table 7 — Sur place'),
  ('ru', 'landing.home.flowItem1Name', 'Стол 7 — Посещение'),
  ('ar', 'landing.home.flowItem1Name', 'طاولة 7 — تناول داخلي'),

  ('hi', 'landing.home.flowItem1Msg', 'ऑर्डर: पास्ता कार्बोनारा × 2'),
  ('de', 'landing.home.flowItem1Msg', 'Bestellung: Pasta Carbonara × 2'),
  ('fr', 'landing.home.flowItem1Msg', 'Commande : Pasta Carbonara × 2'),
  ('ru', 'landing.home.flowItem1Msg', 'Заказ: Паста Карбонара × 2'),
  ('ar', 'landing.home.flowItem1Msg', 'طلب: باستا كاربونارا × 2'),

  ('hi', 'landing.home.flowItem2Name', '+1 (555) 0142'),
  ('de', 'landing.home.flowItem2Name', '+1 (555) 0142'),
  ('fr', 'landing.home.flowItem2Name', '+1 (555) 0142'),
  ('ru', 'landing.home.flowItem2Name', '+1 (555) 0142'),
  ('ar', 'landing.home.flowItem2Name', '+1 (555) 0142'),

  ('hi', 'landing.home.flowItem2Msg', '4 के लिए बुकिंग — शुक्रवार शाम 7 बजे'),
  ('de', 'landing.home.flowItem2Msg', 'Reservierung für 4 — Freitag 19 Uhr'),
  ('fr', 'landing.home.flowItem2Msg', 'Réservation pour 4 — Vendredi 19h'),
  ('ru', 'landing.home.flowItem2Msg', 'Бронирование на 4 — Пятница 19:00'),
  ('ar', 'landing.home.flowItem2Msg', 'حجز لـ 4 — الجمعة 7 مساءً'),

  ('hi', 'landing.home.flowItem3Name', 'वेब विज़िटर'),
  ('de', 'landing.home.flowItem3Name', 'Web-Besucher'),
  ('fr', 'landing.home.flowItem3Name', 'Visiteur web'),
  ('ru', 'landing.home.flowItem3Name', 'Посетитель сайта'),
  ('ar', 'landing.home.flowItem3Name', 'زائر الويب'),

  ('hi', 'landing.home.flowItem3Msg', 'ग्लूटेन-फ्री मेनू के बारे में पूछ रहे हैं'),
  ('de', 'landing.home.flowItem3Msg', 'Fragt nach glutenfreier Speisekarte'),
  ('fr', 'landing.home.flowItem3Msg', 'Demande sur le menu sans gluten'),
  ('ru', 'landing.home.flowItem3Msg', 'Спрашивает о безглютеновом меню'),
  ('ar', 'landing.home.flowItem3Msg', 'يسأل عن قائمة الطعام الخالية من الغلوتين'),

  ('hi', 'landing.home.flowLive', 'लाइव'),
  ('de', 'landing.home.flowLive', 'Live'),
  ('fr', 'landing.home.flowLive', 'En direct'),
  ('ru', 'landing.home.flowLive', 'Онлайн'),
  ('ar', 'landing.home.flowLive', 'مباشر'),

  ('hi', 'landing.home.flowVia1', 'फोन द्वारा'),
  ('de', 'landing.home.flowVia1', 'per Telefon'),
  ('fr', 'landing.home.flowVia1', 'par téléphone'),
  ('ru', 'landing.home.flowVia1', 'по телефону'),
  ('ar', 'landing.home.flowVia1', 'عبر الهاتف'),

  ('hi', 'landing.home.flowVia2', 'व्हाट्सऐप द्वारा'),
  ('de', 'landing.home.flowVia2', 'per WhatsApp'),
  ('fr', 'landing.home.flowVia2', 'par WhatsApp'),
  ('ru', 'landing.home.flowVia2', 'через WhatsApp'),
  ('ar', 'landing.home.flowVia2', 'عبر واتساب'),

  ('hi', 'landing.home.flowVia3', 'वेब चैट द्वारा'),
  ('de', 'landing.home.flowVia3', 'per Web-Chat'),
  ('fr', 'landing.home.flowVia3', 'par chat web'),
  ('ru', 'landing.home.flowVia3', 'через веб-чат'),
  ('ar', 'landing.home.flowVia3', 'عبر دردشة الويب'),

  -- ── Preview section ─────────────────────────────────────────────────────
  ('hi', 'landing.home.previewEyebrow', 'एक वर्कस्पेस'),
  ('de', 'landing.home.previewEyebrow', 'Ein Arbeitsbereich'),
  ('fr', 'landing.home.previewEyebrow', 'Un espace de travail'),
  ('ru', 'landing.home.previewEyebrow', 'Единое рабочее пространство'),
  ('ar', 'landing.home.previewEyebrow', 'مساحة عمل واحدة'),

  ('hi', 'landing.home.previewTitle', 'हर चैनल, हर ऑर्डर — एक नज़र में'),
  ('de', 'landing.home.previewTitle', 'Jeder Kanal, jede Bestellung — in einer Ansicht'),
  ('fr', 'landing.home.previewTitle', 'Chaque canal, chaque commande — en un coup d''œil'),
  ('ru', 'landing.home.previewTitle', 'Каждый канал, каждый заказ — в одном окне'),
  ('ar', 'landing.home.previewTitle', 'كل قناة، كل طلب — في عرض واحد'),

  ('hi', 'landing.home.previewSub', 'फोन कॉल, वेब चैट और मैसेजिंग स्ट्रीम एक लाइव डैशबोर्ड में आते हैं जिसे आपकी टीम एक नज़र में देख सकती है।'),
  ('de', 'landing.home.previewSub', 'Telefonanrufe, Web-Chat und Nachrichten laufen in einem einzigen Live-Dashboard zusammen, das Ihr Team auf einen Blick sehen kann.'),
  ('fr', 'landing.home.previewSub', 'Les appels, le chat web et les messages affluent dans un tableau de bord en direct que votre équipe peut consulter d''un coup d''œil.'),
  ('ru', 'landing.home.previewSub', 'Телефонные звонки, веб-чат и сообщения поступают в единый интерактивный дашборд, который ваша команда видит с первого взгляда.'),
  ('ar', 'landing.home.previewSub', 'تتدفق المكالمات الهاتفية والدردشة على الويب ورسائل التواصل إلى لوحة تحكم مباشرة يمكن لفريقك مراقبتها بلمحة.'),

  -- ── ROI calculator ──────────────────────────────────────────────────────
  ('hi', 'landing.home.roiEyebrow', 'ROI कैलकुलेटर'),
  ('de', 'landing.home.roiEyebrow', 'ROI-Rechner'),
  ('fr', 'landing.home.roiEyebrow', 'Calculateur de ROI'),
  ('ru', 'landing.home.roiEyebrow', 'Калькулятор ROI'),
  ('ar', 'landing.home.roiEyebrow', 'حاسبة العائد على الاستثمار'),

  ('hi', 'landing.home.roiTitle', 'देखें कि छूटी हुई कॉल आपको कितनी महंगी पड़ रही हैं'),
  ('de', 'landing.home.roiTitle', 'Sehen Sie, was verpasste Anrufe Sie kosten'),
  ('fr', 'landing.home.roiTitle', 'Découvrez ce que vous coûtent les appels manqués'),
  ('ru', 'landing.home.roiTitle', 'Узнайте, сколько вам стоят пропущенные звонки'),
  ('ar', 'landing.home.roiTitle', 'اكتشف تكلفة المكالمات الفائتة'),

  ('hi', 'landing.home.roiSub', 'कुछ त्वरित नंबर — पता लगाएं कि RestroAgent हर महीने कितना राजस्व वापस लाता है।'),
  ('de', 'landing.home.roiSub', 'Ein paar schnelle Zahlen — finden Sie heraus, wie viel Umsatz RestroAgent jeden Monat zurückgewinnt.'),
  ('fr', 'landing.home.roiSub', 'Quelques chiffres rapides — découvrez combien de revenus RestroAgent récupère chaque mois.'),
  ('ru', 'landing.home.roiSub', 'Несколько быстрых цифр — узнайте, сколько выручки RestroAgent возвращает каждый месяц.'),
  ('ar', 'landing.home.roiSub', 'بضعة أرقام سريعة — اكتشف كم من الإيرادات يستعيدها RestroAgent كل شهر.'),

  ('hi', 'landing.home.roiInput1', 'मासिक आने वाली कॉल'),
  ('de', 'landing.home.roiInput1', 'Monatliche eingehende Anrufe'),
  ('fr', 'landing.home.roiInput1', 'Appels entrants mensuels'),
  ('ru', 'landing.home.roiInput1', 'Входящих звонков в месяц'),
  ('ar', 'landing.home.roiInput1', 'المكالمات الواردة شهرياً'),

  ('hi', 'landing.home.roiInput2', 'वर्तमान में छूटे हुए'),
  ('de', 'landing.home.roiInput2', 'Aktuell verpasst'),
  ('fr', 'landing.home.roiInput2', 'Actuellement manqués'),
  ('ru', 'landing.home.roiInput2', 'Сейчас пропускается'),
  ('ar', 'landing.home.roiInput2', 'الفائتة حالياً'),

  ('hi', 'landing.home.roiInput3', 'औसत ऑर्डर मूल्य'),
  ('de', 'landing.home.roiInput3', 'Durchschnittlicher Bestellwert'),
  ('fr', 'landing.home.roiInput3', 'Valeur moyenne de commande'),
  ('ru', 'landing.home.roiInput3', 'Средняя стоимость заказа'),
  ('ar', 'landing.home.roiInput3', 'متوسط قيمة الطلب'),

  ('hi', 'landing.home.roiResultLabel', 'RestroAgent के साथ रिकवर किया गया'),
  ('de', 'landing.home.roiResultLabel', 'Mit RestroAgent zurückgewonnen'),
  ('fr', 'landing.home.roiResultLabel', 'Récupéré avec RestroAgent'),
  ('ru', 'landing.home.roiResultLabel', 'Возвращено с RestroAgent'),
  ('ar', 'landing.home.roiResultLabel', 'يُستعاد مع RestroAgent'),

  ('hi', 'landing.home.roiResultSub', 'आपके औसत ऑर्डर मूल्य पर हर छूटी हुई कॉल को कैप्चर करने पर आधारित। अनुमान उद्योग औसत का उपयोग करता है — अधिकांश रेस्तरां अधिक देखते हैं।'),
  ('de', 'landing.home.roiResultSub', 'Basierend auf der Erfassung jedes verpassten Anrufs zum durchschnittlichen Bestellwert. Schätzung verwendet Branchendurchschnitte — die meisten Restaurants sehen mehr.'),
  ('fr', 'landing.home.roiResultSub', 'Basé sur la capture de chaque appel manqué à votre valeur de commande moyenne. L''estimation utilise les moyennes du secteur — la plupart des restaurants voient plus.'),
  ('ru', 'landing.home.roiResultSub', 'Рассчитано из захвата каждого пропущенного звонка по средней стоимости заказа. Оценка основана на отраслевых средних — большинство ресторанов видит больше.'),
  ('ar', 'landing.home.roiResultSub', 'استناداً إلى التقاط كل مكالمة فائتة بمتوسط قيمة طلبك. يستخدم التقدير متوسطات الصناعة — معظم المطاعم ترى أكثر.'),

  ('hi', 'landing.home.roiCta', 'मुफ्त ट्रायल शुरू करें'),
  ('de', 'landing.home.roiCta', 'Kostenlose Testversion starten'),
  ('fr', 'landing.home.roiCta', 'Démarrer l''essai gratuit'),
  ('ru', 'landing.home.roiCta', 'Начать бесплатный пробный период'),
  ('ar', 'landing.home.roiCta', 'ابدأ التجربة المجانية'),

  ('hi', 'landing.home.roiDisclaimer', 'उद्योग औसत पर आधारित अनुमान।'),
  ('de', 'landing.home.roiDisclaimer', 'Schätzung basierend auf Branchendurchschnittswerten.'),
  ('fr', 'landing.home.roiDisclaimer', 'Estimation basée sur les moyennes du secteur.'),
  ('ru', 'landing.home.roiDisclaimer', 'Оценка основана на отраслевых средних.'),
  ('ar', 'landing.home.roiDisclaimer', 'تقدير مبني على متوسطات الصناعة.'),

  -- ── Mock dashboard / logo wall ──────────────────────────────────────────
  ('hi', 'landing.home.logoWallLabel', 'दुनिया भर के 2,400+ रेस्तरां द्वारा विश्वसनीय'),
  ('de', 'landing.home.logoWallLabel', 'Vertraut von 2.400+ Restaurants weltweit'),
  ('fr', 'landing.home.logoWallLabel', 'Approuvé par plus de 2 400 restaurants dans le monde'),
  ('ru', 'landing.home.logoWallLabel', 'Доверяют 2 400+ ресторанов по всему миру'),
  ('ar', 'landing.home.logoWallLabel', 'موثوق به من قِبل أكثر من 2400 مطعم حول العالم'),

  ('hi', 'landing.home.mockLiveDashboard', 'लाइव डैशबोर्ड'),
  ('de', 'landing.home.mockLiveDashboard', 'Live-Dashboard'),
  ('fr', 'landing.home.mockLiveDashboard', 'Tableau de bord en direct'),
  ('ru', 'landing.home.mockLiveDashboard', 'Интерактивный дашборд'),
  ('ar', 'landing.home.mockLiveDashboard', 'لوحة تحكم مباشرة'),

  ('hi', 'landing.home.mockKpi1', 'सक्रिय ऑर्डर'),
  ('de', 'landing.home.mockKpi1', 'Aktive Bestellungen'),
  ('fr', 'landing.home.mockKpi1', 'Commandes actives'),
  ('ru', 'landing.home.mockKpi1', 'Активных заказов'),
  ('ar', 'landing.home.mockKpi1', 'الطلبات النشطة'),

  ('hi', 'landing.home.mockKpi2', 'AI द्वारा संभाला गया'),
  ('de', 'landing.home.mockKpi2', 'KI-bearbeitet'),
  ('fr', 'landing.home.mockKpi2', 'Traité par IA'),
  ('ru', 'landing.home.mockKpi2', 'Обработано ИИ'),
  ('ar', 'landing.home.mockKpi2', 'معالجة الذكاء الاصطناعي'),

  ('hi', 'landing.home.mockKpi3', 'औसत प्रतिक्रिया'),
  ('de', 'landing.home.mockKpi3', 'Ø Antwortzeit'),
  ('fr', 'landing.home.mockKpi3', 'Rép. moyenne'),
  ('ru', 'landing.home.mockKpi3', 'Сред. ответ'),
  ('ar', 'landing.home.mockKpi3', 'متوسط الاستجابة'),

  ('hi', 'landing.home.mockMsg1Name', 'टेबल 7 — डाइन-इन'),
  ('de', 'landing.home.mockMsg1Name', 'Tisch 7 — Restaurant'),
  ('fr', 'landing.home.mockMsg1Name', 'Table 7 — Sur place'),
  ('ru', 'landing.home.mockMsg1Name', 'Стол 7 — Посещение'),
  ('ar', 'landing.home.mockMsg1Name', 'طاولة 7 — تناول داخلي'),

  ('hi', 'landing.home.mockMsg1Text', 'ऑर्डर की पुष्टि: पास्ता कार्बोनारा × 2, तिरामिसू × 1'),
  ('de', 'landing.home.mockMsg1Text', 'Bestellung bestätigt: Pasta Carbonara × 2, Tiramisu × 1'),
  ('fr', 'landing.home.mockMsg1Text', 'Commande confirmée : Pasta Carbonara × 2, Tiramisu × 1'),
  ('ru', 'landing.home.mockMsg1Text', 'Заказ подтверждён: Паста Карбонара × 2, Тирамису × 1'),
  ('ar', 'landing.home.mockMsg1Text', 'تأكيد الطلب: باستا كاربونارا × 2، تيراميسو × 1'),

  ('hi', 'landing.home.mockMsg2Name', 'फोन +1 (555) 0142'),
  ('de', 'landing.home.mockMsg2Name', 'Telefon +1 (555) 0142'),
  ('fr', 'landing.home.mockMsg2Name', 'Téléphone +1 (555) 0142'),
  ('ru', 'landing.home.mockMsg2Name', 'Телефон +1 (555) 0142'),
  ('ar', 'landing.home.mockMsg2Name', 'هاتف +1 (555) 0142'),

  ('hi', 'landing.home.mockMsg2Text', 'शुक्रवार शाम 7 बजे 4 के लिए बुकिंग — पुष्टि हो गई'),
  ('de', 'landing.home.mockMsg2Text', 'Reservierung für 4 am Freitag um 19 Uhr — bestätigt'),
  ('fr', 'landing.home.mockMsg2Text', 'Réservation pour 4 vendredi 19h — confirmée'),
  ('ru', 'landing.home.mockMsg2Text', 'Бронирование на 4 в пятницу в 19:00 — подтверждено'),
  ('ar', 'landing.home.mockMsg2Text', 'حجز لـ 4 الجمعة 7 مساءً — مؤكد'),

  ('hi', 'landing.home.mockMsg3Name', 'वेब चैट'),
  ('de', 'landing.home.mockMsg3Name', 'Web-Chat'),
  ('fr', 'landing.home.mockMsg3Name', 'Chat web'),
  ('ru', 'landing.home.mockMsg3Name', 'Веб-чат'),
  ('ar', 'landing.home.mockMsg3Name', 'دردشة الويب'),

  ('hi', 'landing.home.mockMsg3Text', 'ग्लूटेन-फ्री विकल्पों के बारे में पूछ रहे हैं — AI जवाब दे रहा है'),
  ('de', 'landing.home.mockMsg3Text', 'Fragt nach glutenfreien Optionen — KI antwortet'),
  ('fr', 'landing.home.mockMsg3Text', 'Demande sur les options sans gluten — IA en cours de réponse'),
  ('ru', 'landing.home.mockMsg3Text', 'Спрашивает о безглютеновых блюдах — ИИ отвечает'),
  ('ar', 'landing.home.mockMsg3Text', 'يسأل عن خيارات خالية من الغلوتين — الذكاء الاصطناعي يرد'),

  ('hi', 'landing.home.mockTime1', '2 से.'),
  ('de', 'landing.home.mockTime1', '2 Sek.'),
  ('fr', 'landing.home.mockTime1', '2 s'),
  ('ru', 'landing.home.mockTime1', '2 с'),
  ('ar', 'landing.home.mockTime1', '2 ث'),

  ('hi', 'landing.home.mockTime2', '18 से.'),
  ('de', 'landing.home.mockTime2', '18 Sek.'),
  ('fr', 'landing.home.mockTime2', '18 s'),
  ('ru', 'landing.home.mockTime2', '18 с'),
  ('ar', 'landing.home.mockTime2', '18 ث'),

  ('hi', 'landing.home.mockTime3', '34 से.'),
  ('de', 'landing.home.mockTime3', '34 Sek.'),
  ('fr', 'landing.home.mockTime3', '34 s'),
  ('ru', 'landing.home.mockTime3', '34 с'),
  ('ar', 'landing.home.mockTime3', '34 ث'),

  ('hi', 'landing.home.mockCallsStat', 'कोई भी कॉल मिस नहीं'),
  ('de', 'landing.home.mockCallsStat', 'Keine verpassten Anrufe'),
  ('fr', 'landing.home.mockCallsStat', 'Zéro appel manqué'),
  ('ru', 'landing.home.mockCallsStat', 'Ни одного пропущенного звонка'),
  ('ar', 'landing.home.mockCallsStat', 'لا توجد مكالمات فائتة'),

  ('hi', 'landing.home.mockTimeframe', 'पिछले 30 दिन'),
  ('de', 'landing.home.mockTimeframe', 'Letzte 30 Tage'),
  ('fr', 'landing.home.mockTimeframe', '30 derniers jours'),
  ('ru', 'landing.home.mockTimeframe', 'Последние 30 дней'),
  ('ar', 'landing.home.mockTimeframe', 'آخر 30 يوماً'),

  ('hi', 'landing.home.mockRevLabel', 'आज का राजस्व'),
  ('de', 'landing.home.mockRevLabel', 'Umsatz heute'),
  ('fr', 'landing.home.mockRevLabel', 'Revenus aujourd''hui'),
  ('ru', 'landing.home.mockRevLabel', 'Выручка сегодня'),
  ('ar', 'landing.home.mockRevLabel', 'الإيرادات اليوم'),

  ('hi', 'landing.home.mockRevStat', '↑ 23% कल की तुलना में'),
  ('de', 'landing.home.mockRevStat', '↑ 23 % vs. gestern'),
  ('fr', 'landing.home.mockRevStat', '↑ 23 % par rapport à hier'),
  ('ru', 'landing.home.mockRevStat', '↑ 23% к вчерашнему'),
  ('ar', 'landing.home.mockRevStat', '↑ 23% مقارنة بالأمس')
) AS v(lang, key, val)
JOIN public.translation_keys tk ON tk.key = v.key
ON CONFLICT (lang_code, key_id) DO NOTHING;

-- ─── TASK #386: MULTI-GATEWAY BILLING ────────────────────────────────────────

-- plan_prices join table: per-currency pricing for each plan
CREATE TABLE IF NOT EXISTS public.plan_prices (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  plan_id UUID NOT NULL REFERENCES public.plans(id) ON DELETE CASCADE,
  currency_code VARCHAR(3) NOT NULL,
  price_monthly NUMERIC(10,2) NOT NULL DEFAULT 0,
  price_annual NUMERIC(10,2) NOT NULL DEFAULT 0,
  created_at TIMESTAMPTZ DEFAULT now(),
  UNIQUE(plan_id, currency_code)
);
CREATE INDEX IF NOT EXISTS idx_plan_prices_plan_id ON public.plan_prices(plan_id);
CREATE INDEX IF NOT EXISTS idx_plan_prices_currency ON public.plan_prices(currency_code);

-- Seed default USD prices from existing plan rows (idempotent)
INSERT INTO public.plan_prices (plan_id, currency_code, price_monthly, price_annual)
SELECT id, 'USD', price_monthly, price_annual FROM public.plans WHERE is_active = true
ON CONFLICT (plan_id, currency_code) DO NOTHING;

-- Razorpay and gateway fields on subscriptions
ALTER TABLE public.subscriptions ADD COLUMN IF NOT EXISTS razorpay_subscription_id TEXT;
ALTER TABLE public.subscriptions ADD COLUMN IF NOT EXISTS razorpay_customer_id TEXT;
ALTER TABLE public.subscriptions ADD COLUMN IF NOT EXISTS billing_contact_email TEXT;

-- razorpay_payments: stores verified Razorpay one-time payments for invoice history
CREATE TABLE IF NOT EXISTS public.razorpay_payments (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  restaurant_id UUID NOT NULL REFERENCES public.restaurants(id) ON DELETE CASCADE,
  plan_id UUID REFERENCES public.plans(id) ON DELETE SET NULL,
  billing_cycle VARCHAR(10) NOT NULL DEFAULT 'monthly',
  razorpay_order_id TEXT NOT NULL UNIQUE,
  razorpay_payment_id TEXT NOT NULL,
  amount NUMERIC(10,2) NOT NULL,
  currency VARCHAR(3) NOT NULL DEFAULT 'INR',
  status TEXT NOT NULL DEFAULT 'paid',
  created_at TIMESTAMPTZ DEFAULT now()
);
CREATE INDEX IF NOT EXISTS idx_razorpay_payments_restaurant ON public.razorpay_payments(restaurant_id);

-- Grace period dunning: track when subscription first went past_due
ALTER TABLE public.subscriptions ADD COLUMN IF NOT EXISTS overdue_at TIMESTAMPTZ;
DO $$ BEGIN ALTER TYPE public.plan_status ADD VALUE IF NOT EXISTS 'suspended'; EXCEPTION WHEN others THEN NULL; END $$;

-- Task #393: Razorpay Subscriptions API plan IDs
ALTER TABLE public.plans ADD COLUMN IF NOT EXISTS razorpay_plan_id_monthly TEXT;
ALTER TABLE public.plans ADD COLUMN IF NOT EXISTS razorpay_plan_id_annual TEXT;

-- WhatsApp per-WABA send-rate cap (msgs/sec). Operators set this to match
-- their Meta WABA tier (10 = safe default for unverified accounts).
ALTER TABLE public.branches ADD COLUMN IF NOT EXISTS whatsapp_send_rate INTEGER NOT NULL DEFAULT 10;

-- Task #497: extend channel_type for POS / delivery-platform integration
DO $$ BEGIN
  IF NOT EXISTS (SELECT 1 FROM pg_type t JOIN pg_enum e ON t.oid = e.enumtypid
                 WHERE t.typname = 'channel_type' AND e.enumlabel = 'pos') THEN
    ALTER TYPE public.channel_type ADD VALUE 'pos';
  END IF;
END $$;
DO $$ BEGIN
  IF NOT EXISTS (SELECT 1 FROM pg_type t JOIN pg_enum e ON t.oid = e.enumtypid
                 WHERE t.typname = 'channel_type' AND e.enumlabel = 'zomato') THEN
    ALTER TYPE public.channel_type ADD VALUE 'zomato';
  END IF;
END $$;
DO $$ BEGIN
  IF NOT EXISTS (SELECT 1 FROM pg_type t JOIN pg_enum e ON t.oid = e.enumtypid
                 WHERE t.typname = 'channel_type' AND e.enumlabel = 'swiggy') THEN
    ALTER TYPE public.channel_type ADD VALUE 'swiggy';
  END IF;
END $$;
DO $$ BEGIN
  IF NOT EXISTS (SELECT 1 FROM pg_type t JOIN pg_enum e ON t.oid = e.enumtypid
                 WHERE t.typname = 'channel_type' AND e.enumlabel = 'online') THEN
    ALTER TYPE public.channel_type ADD VALUE 'online';
  END IF;
END $$;
`;


async function _syncStripePriceIds(): Promise<void> {
  const planEnvMap: Record<string, { monthly?: string; annual?: string }> = {
    Starter: { monthly: process.env.STRIPE_PRICE_ID_STARTER_MONTHLY, annual: process.env.STRIPE_PRICE_ID_STARTER_ANNUAL },
    Growth: { monthly: process.env.STRIPE_PRICE_ID_GROWTH_MONTHLY, annual: process.env.STRIPE_PRICE_ID_GROWTH_ANNUAL },
    Pro: { monthly: process.env.STRIPE_PRICE_ID_PRO_MONTHLY, annual: process.env.STRIPE_PRICE_ID_PRO_ANNUAL },
    Enterprise: { monthly: process.env.STRIPE_PRICE_ID_ENTERPRISE_MONTHLY, annual: process.env.STRIPE_PRICE_ID_ENTERPRISE_ANNUAL },
  };
  for (const [planName, ids] of Object.entries(planEnvMap)) {
    if (ids.monthly || ids.annual) {
      await pool.query(
        `UPDATE public.plans SET
           stripe_price_id_monthly = COALESCE($2, stripe_price_id_monthly),
           stripe_price_id_annual  = COALESCE($3, stripe_price_id_annual)
         WHERE name = $1`,
        [planName, ids.monthly ?? null, ids.annual ?? null]
      );
    }
  }
}

const PLAN_DEFAULTS: Array<{
  name: string; slug: string; description: string; price_monthly: number; price_annual: number;
  features: string[]; limits: Record<string, number>;
}> = [
    {
      name: 'Starter',
      slug: 'starter',
      description: 'Essential AI chat features for small restaurants',
      price_monthly: 49, price_annual: 470,
      features: ['chat_agent'],
      limits: { conversations_per_month: 500, api_calls_per_minute: 10, max_branches: 1 },
    },
    {
      name: 'Growth',
      slug: 'growth',
      description: 'Chat, voice, and analytics for growing restaurants',
      price_monthly: 149, price_annual: 1430,
      features: ['chat_agent', 'voice_agent', 'whatsapp_agent', 'storefront', 'analytics', 'multi_branch', 'loyalty', 'coupons'],
      limits: { conversations_per_month: 2000, api_calls_per_minute: 30, concurrent_voice_calls: 2, max_branches: 3 },
    },
    {
      name: 'Pro',
      slug: 'pro',
      description: 'Advanced features for established restaurants',
      price_monthly: 249, price_annual: 2390,
      features: ['chat_agent', 'voice_agent', 'whatsapp_agent', 'storefront', 'multi_branch', 'analytics', 'knowledge_base', 'marketing', 'loyalty', 'gift_cards', 'coupons'],
      limits: { conversations_per_month: 5000, api_calls_per_minute: 60, concurrent_voice_calls: 5, max_branches: 5 },
    },
    {
      name: 'Enterprise',
      slug: 'enterprise',
      description: 'Full platform for restaurant groups and chains',
      price_monthly: 399, price_annual: 3830,
      features: ['chat_agent', 'voice_agent', 'whatsapp_agent', 'storefront', 'multi_branch', 'analytics', 'knowledge_base', 'bulk_upload', 'priority_support', 'marketing', 'loyalty', 'gift_cards', 'coupons'],
      limits: { conversations_per_month: -1, api_calls_per_minute: 100, concurrent_voice_calls: 10, max_branches: -1 },
    },
  ];

async function _seedDefaultPlans(): Promise<void> {
  for (const plan of PLAN_DEFAULTS) {
    await pool.query(
      `INSERT INTO public.plans (name, slug, description, price_monthly, price_annual, features, limits, is_active)
       SELECT $1, $2, $3, $4, $5, $6::jsonb, $7::jsonb, true
       WHERE NOT EXISTS (SELECT 1 FROM public.plans WHERE name = $1)`,
      [plan.name, plan.slug, plan.description, plan.price_monthly, plan.price_annual,
      JSON.stringify(plan.features), JSON.stringify(plan.limits)]
    );
    await pool.query(
      `UPDATE public.plans
       SET features = (
         SELECT jsonb_agg(DISTINCT elem)
         FROM (
           SELECT jsonb_array_elements_text(features) AS elem
           UNION
           SELECT jsonb_array_elements_text($2::jsonb) AS elem
         ) merged
       )
       WHERE name = $1
         AND NOT (features @> $2::jsonb)`,
      [plan.name, JSON.stringify(plan.features)]
    );
  }
}

async function _runInit(): Promise<boolean> {
  try {
    const result = await pool.query(
      `SELECT EXISTS (SELECT FROM information_schema.tables WHERE table_schema = 'public' AND table_name = 'plans')`
    );

    if (result.rows[0]?.exists) {
      // Use DO blocks for Postgres < 13 compatibility (ADD VALUE IF NOT EXISTS is PG 13+)
      await pool.query(`
        DO $$ 
        BEGIN 
          IF NOT EXISTS (SELECT 1 FROM pg_type t JOIN pg_enum e ON t.oid = e.enumtypid WHERE t.typname = 'user_role' AND e.enumlabel = 'superadmin') THEN
            ALTER TYPE public.user_role ADD VALUE 'superadmin';
          END IF;
          IF NOT EXISTS (SELECT 1 FROM pg_type t JOIN pg_enum e ON t.oid = e.enumtypid WHERE t.typname = 'user_role' AND e.enumlabel = 'support') THEN
            ALTER TYPE public.user_role ADD VALUE 'support';
          END IF;
        END $$;
      `);

      try {
        await pool.query(MIGRATION_SQL);
      } catch (migErr) {
        log.error({ err: migErr }, 'DB migration script error (some parts may have failed)');
        // We continue because even if one update fails (e.g. column already added), we want other seeds to run.
      }

      await _syncStripePriceIds();
      await _seedDefaultPlans();
      await _seedPlatformSuperadmin();
      try { (await import('@server/services/email/outbox.service')).startWorker(); } catch (e) { log.warn({ err: e }, 'DB: email outbox worker boot failed'); }
      try { (await import('@server/services/marketing/dispatcher')).startDispatcher(); } catch (e) { log.warn({ err: e }, 'DB: marketing dispatcher boot failed'); }
      try { (await import('@server/services/loyalty.service')).startExpiryWorker(); } catch (e) { log.warn({ err: e }, 'DB: loyalty expiry worker boot failed'); }
      try { (await import('@server/services/inventory.service')).startInventoryResetWorker(); } catch (e) { log.warn({ err: e }, 'DB: inventory reset worker boot failed'); }
      try { (await import('@server/services/webhooks.service')).startWebhookRetryWorker(); } catch (e) { log.warn({ err: e }, 'DB: webhook retry worker boot failed'); }
      initialized = true;
      return true;
    }

    const schemaPath = path.join(process.cwd(), 'src', 'server', 'db', 'schema.sql');
    const schemaSql = fs.readFileSync(schemaPath, 'utf-8');

    await pool.query(schemaSql);
    await pool.query(MIGRATION_SQL);
    await _syncStripePriceIds();
    await _seedDefaultPlans();
    await _seedPlatformSuperadmin();
    try { (await import('@server/services/email/outbox.service')).startWorker(); } catch (e) { log.warn({ err: e }, 'DB: email outbox worker boot failed'); }
    try { (await import('@server/services/marketing/dispatcher')).startDispatcher(); } catch (e) { log.warn({ err: e }, 'DB: marketing dispatcher boot failed'); }
    try { (await import('@server/services/loyalty.service')).startExpiryWorker(); } catch (e) { log.warn({ err: e }, 'DB: loyalty expiry worker boot failed'); }
    try { (await import('@server/services/inventory.service')).startInventoryResetWorker(); } catch (e) { log.warn({ err: e }, 'DB: inventory reset worker boot failed'); }
    try { (await import('@server/services/webhooks.service')).startWebhookRetryWorker(); } catch (e) { log.warn({ err: e }, 'DB: webhook retry worker boot failed'); }

    initialized = true;
    log.info('schema initialized successfully');
    return true;
  } catch (error) {
    log.error({ err: error }, 'DB CRITICAL: schema initialization failed');
    return false;
  }
}

export async function initDatabase(): Promise<boolean> {
  if (initialized) return true;
  if (!initPromise) {
    initPromise = _runInit();
  }
  return initPromise;
}
