{
  "id": "Szelm1dSKH9lUyGB",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Monthly AI SEO Content Engine: 34 Assets to WordPress, LinkedIn & Socials",
  "tags": [],
  "nodes": [
    {
      "id": "d14b741c-9077-42e3-b739-fd6f676d2967",
      "name": "\ud83d\udccb Template \u00b7 Overview",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1296,
        3424
      ],
      "parameters": {
        "width": 976,
        "height": 2654,
        "content": "## Monthly AI SEO Content Engine: 34 Assets to WordPress, LinkedIn & Socials\n\n### Who it's for\nMarketing agencies, SEO consultants, and brand owners looking to automate a high-volume, multi-platform content strategy while strictly maintaining brand voice.\n\n### What it does\nThis workflow is an end-to-end content engine. It generates a comprehensive brand strategy, then automatically writes, formats, and publishes 34 monthly assets (SEO blogs, LinkedIn posts, social media updates, newsletters, and long-form guides) across multiple platforms.\n\n### How it works\n- **Strategy:** Collects business context via an n8n form and uses Google Gemini to save a master brand strategy document to Google Drive.\n- **Generation:** Analyzes your Google Analytics data and Google Trends, writes 34 targeted content pieces, and compiles them into a formatted Word (.docx) package.\n- **Publishing:** Extracts the generated text, creates custom AI images for each piece using Gemini Flash Image, and staggers the publishing schedule across WordPress, LinkedIn, Facebook, and Instagram.\n\n### How to set up\n1. Run the Strategy pipeline via the Form Trigger to generate your brand's Markdown file.\n2. In the Generation pipeline, update the `Config: Pipeline B` node with your Google Analytics Property ID, notification email, the Drive URL of your Markdown file, and your preferred Google Trends geographic and language codes.\n3. In the Publishing pipeline, update `Config: Pipeline C` with your Facebook Page ID, Instagram ID, WordPress domain, S3 Bucket and Folder name and a notification email address.\n4. Test manually using the trigger nodes before enabling the Schedule triggers.\n\n### Requirements\n- **n8n version 1.60+** (required for the node types used in this template).\n- **AWS S3 bucket with public-read access** (required to host images for Instagram publishing).\n- Google Gemini API credentials (budget for ~100k-150k output tokens per monthly run).\n- Google Workspace (Analytics, Drive, Gmail).\n- WordPress site with Basic Auth enabled.\n- LinkedIn account, Facebook Page, and Instagram Business account.\n\n### How to customize the workflow\n- Modify the Schedule trigger cron expressions to publish weekly instead of monthly.\n- Adjust the prompt templates inside the Code nodes to change the content formats or output volume."
      },
      "typeVersion": 1
    },
    {
      "id": "8a0ee76c-ec80-4570-abed-b6dcc1a1dc3e",
      "name": "Company Data Form",
      "type": "n8n-nodes-base.formTrigger",
      "position": [
        2448,
        3664
      ],
      "parameters": {
        "options": {},
        "formTitle": "Master Business Context Generator",
        "formFields": {
          "values": [
            {
              "fieldLabel": "Company Name",
              "requiredField": true
            },
            {
              "fieldLabel": "Industry",
              "requiredField": true
            },
            {
              "fieldLabel": "Primary Services (Comma Separated)",
              "requiredField": true
            },
            {
              "fieldType": "textarea",
              "fieldLabel": "Mission",
              "requiredField": true
            },
            {
              "fieldType": "textarea",
              "fieldLabel": "Vision",
              "requiredField": true
            },
            {
              "fieldLabel": "Tagline",
              "requiredField": true
            },
            {
              "fieldType": "textarea",
              "fieldLabel": "Core Services (Format: Name: Description, one per line)"
            },
            {
              "fieldType": "textarea",
              "fieldLabel": "Target Audience (Format: Persona: Role, one per line)"
            },
            {
              "fieldType": "textarea",
              "fieldLabel": "Client Problems (One per line)"
            },
            {
              "fieldType": "textarea",
              "fieldLabel": "Why Choose Us (One per line)"
            }
          ]
        },
        "formDescription": "Fill in your company details to auto-generate a 16-section AI strategy document."
      },
      "typeVersion": 2.2
    },
    {
      "id": "134ad88a-44d2-4ffc-abc6-53c7e8a62c5a",
      "name": "Build Prompt",
      "type": "n8n-nodes-base.code",
      "position": [
        2704,
        3664
      ],
      "parameters": {
        "jsCode": "const schemaDescription = `\\nYou must return a single valid JSON object matching this exact structure.\\nNo preamble, no markdown fences, no explanation \u2014 only the raw JSON.\\n\\nRequired top-level keys and their types:\\n\\ncompany_overview: object with keys:\\n  name (string), industry (string), primary_services (array of strings),\\n  mission (string), vision (string), tagline (string)\\n\\ncore_services: array of objects, each with:\\n  name (string), description (string), key_deliverables (array of strings),\\n  key_topics (array of strings), client_outcomes (array of strings)\\n\\ntarget_audience: array of objects, each with:\\n  persona_name (string), role (string), company_type (string),\\n  pain_point (string), goal (string), buys_service (string)\\n\\nprimary_client_types: array of objects, each with:\\n  type (string), description (string), pain_points (array of strings)\\n\\ncustomer_pain_points: array of strings\\n\\nvalue_propositions: object with:\\n  reasons_clients_choose_us (array of strings), differentiators (array of strings)\\n\\ncompetitor_differentiation: object with:\\n  vs_large_consulting_firms (array of strings),\\n  vs_generic_agencies (array of strings),\\n  vs_diy_tools (array of strings),\\n  key_positioning_statement (string)\\n\\nbrand_voice: object with:\\n  tone (array of strings), messaging_themes (array of strings),\\n  use_language_like (array of strings), avoid_language_like (array of strings)\\n\\nprohibited_phrases: array of strings\\n\\nkey_content_topics: array of objects, each with:\\n  service_name (string), topics (array of strings)\\n\\nseo_keywords: object with:\\n  primary (array of strings), secondary (array of strings), long_tail (array of strings)\\n\\ncontent_strategy: object with:\\n  monthly_targets: object with keys blogs (integer), linkedin_posts (integer),\\n    educational_social_posts (integer), email_newsletters (integer), long_form_guides (integer)\\n  content_pillars (array of strings)\\n\\nmarketing_channels: object with:\\n  primary (array of strings), secondary (array of strings)\\n\\nindustry_trends: array of strings\\n\\ntechnical_integrations: array of strings\\n\\ninternal_workflow: array of objects, each with:\\n  role (string), responsibility (string)\\n\\nFill every field thoroughly. No empty strings. No placeholders.\\n`;\nconst input = $input.first().json;\nconst textToArray = (text) => {\n  if (!text) return [];\n  return text.split('\\n').map(l => l.trim()).filter(l => l.length > 0);\n};\nconst parseKeyValue = (text, keyName, valName) => {\n  return textToArray(text).map(line => {\n    const parts = line.split(':');\n    return {  [keyName]: parts[0]?.trim() || '',  [valName]: parts[1]?.trim() || ''};\n  }).filter(item => item[keyName]);\n};\nconst coreServices = parseKeyValue(input['Core Services (Format: Name: Description, one per line)'], 'name', 'description');\nconst targetAudience = parseKeyValue(input['Target Audience (Format: Persona: Role, one per line)'], 'persona_name', 'role');\nconst clientProblems = textToArray(input['Client Problems (One per line)']);\nconst whyChooseUs = textToArray(input['Why Choose Us (One per line)']);\n\nconst userMessage = `Generate a complete Master Business Context document based on the company details below.\\n\\nCompany Name: ${input['Company Name']}\\nIndustry: ${input['Industry']}\\nPrimary Service: ${input['Primary Services']}\\nMission: ${input['Mission']}\\nVision: ${input['Vision']}\\nTagline: ${input['Tagline']}\\n\\nCore Services:\\n${JSON.stringify(coreServices)}\\n\\nTarget Audience Names/Roles:\\n${JSON.stringify(targetAudience)}\\n\\nCommon Problems Clients Face:\\n${JSON.stringify(clientProblems)}\\n\\nWhy Clients Choose Us:\\n${JSON.stringify(whyChooseUs)}`;\n\nconst prompt = {\n  systemInstruction: `You are a professional business content writer specializing in AI consulting companies.\\nYour job is to generate complete, structured Master Business Context documents.\\nAlways write in a confident, expert, and approachable tone.\\nNever use generic clich\u00e9s like \"game-changer\", \"leverage\", \"seamless\", \"cutting-edge\",\\n\"revolutionize\", \"unlock potential\", \"synergy\", \"best-in-class\", \"holistic approach\".\\nMake every section specific and actionable \u2014 no filler content.\\n\\n${schemaDescription}`,\n  userMessage,\n  \"generationConfig\": {\n    \"temperature\": 0.4,\n    \"maxOutputTokens\": 8192,\n    \"responseMimeType\": \"application/json\"\n  }\n};\nreturn { json: prompt };"
      },
      "typeVersion": 2
    },
    {
      "id": "11dfc5c1-3a29-4982-927d-71a74b5a62d0",
      "name": "Parse Response",
      "type": "n8n-nodes-base.code",
      "position": [
        3312,
        3664
      ],
      "parameters": {
        "jsCode": "const items = $input.first().json\nconst text = items.content?.parts?.[0]?.text ?? '';\nconst cleanJson = text.replace(/```json|```/g, \"\").trim();\nconst response = JSON.parse(cleanJson)\nreturn {response}"
      },
      "typeVersion": 2
    },
    {
      "id": "35c2a2f6-d1dc-4d14-9bc0-adfd82a45963",
      "name": "Format to Markdown",
      "type": "n8n-nodes-base.code",
      "position": [
        3600,
        3664
      ],
      "parameters": {
        "jsCode": "const inputJson = [$input.first().json];\n\nfunction generateMarkdownFromData(jsonData) {\n  const data = jsonData[0].response;\n  let md = \"# AI Agency \u2013 Master Business Context\\n\";\n  md += \"Version: 2.0\\n\";\n  md += `Last Updated: ${new Date().getFullYear()}\\n\\n---\\n\\n`;\n  const renderList = (items) => items.map(item => `- ${item}`).join('\\n');\n\n  if (data.company_overview) {\n    const co = data.company_overview;\n    md += `# Company Overview\\n\\nCompany Name: ${co.name}\\nIndustry: ${co.industry}\\nPrimary Services: ${co.primary_services.join(', ')}\\n\\nMission:\\n${co.mission}\\n\\nVision:\\n${co.vision}\\n\\nTagline:\\n${co.tagline}\\n\\n---\\n\\n`;\n  }\n  if (data.core_services) {\n    md += `# Core Services\\n\\n`;\n    data.core_services.forEach((svc, i) => {\n      md += `## ${i + 1}. ${svc.name}\\n\\nDescription:\\n${svc.description}\\n\\n`;\n      if (svc.key_deliverables) md += `Key Deliverables:\\n${renderList(svc.key_deliverables)}\\n\\n`;\n      if (svc.key_topics) md += `Key Topics:\\n${renderList(svc.key_topics)}\\n\\n`;\n      if (svc.client_outcomes) md += `Client Outcomes:\\n${renderList(svc.client_outcomes)}\\n\\n`;\n      md += `---\\n\\n`;\n    });\n  }\n  if (data.target_audience) {\n    md += `# Target Audience\\n\\n## Client Personas\\n\\n`;\n    data.target_audience.forEach((aud, i) => {\n      md += `### Persona ${i + 1} \u2013 ${aud.persona_name}\\nRole: ${aud.role}\\nCompany: ${aud.company_type}\\nPain: ${aud.pain_point}\\nGoal: ${aud.goal}\\nBuys: ${aud.buys_service}\\n\\n`;\n    });\n    md += `---\\n\\n`;\n  }\n  if (data.primary_client_types) {\n    md += `# Primary Client Types\\n\\n`;\n    data.primary_client_types.forEach((c, i) => {\n      md += `## ${i + 1}. ${c.type}\\n${c.description}\\n\\nPain Points:\\n${renderList(c.pain_points)}\\n\\n`;\n    });\n    md += `---\\n\\n`;\n  }\n  if (data.customer_pain_points) md += `# Customer Pain Points\\n\\n${renderList(data.customer_pain_points)}\\n\\n---\\n\\n`;\n  if (data.value_propositions) {\n    md += `# Value Propositions\\n\\nWhy Clients Choose Us:\\n${renderList(data.value_propositions.reasons_clients_choose_us)}\\n\\nDifferentiators:\\n${renderList(data.value_propositions.differentiators)}\\n\\n---\\n\\n`;\n  }\n  if (data.competitor_differentiation) {\n    const cd = data.competitor_differentiation;\n    md += `# Competitor Differentiation\\n\\nvs. Large Consulting Firms:\\n${renderList(cd.vs_large_consulting_firms)}\\n\\nvs. Generic IT Agencies:\\n${renderList(cd.vs_generic_agencies)}\\n\\nvs. DIY/Pure Automation Tools:\\n${renderList(cd.vs_diy_tools)}\\n\\nKey Positioning Statement:\\n${cd.key_positioning_statement}\\n\\n---\\n\\n`;\n  }\n  if (data.brand_voice) {\n    const bv = data.brand_voice;\n    md += `# Brand Voice & Messaging\\n\\nTone:\\n${renderList(bv.tone)}\\n\\nMessaging Themes:\\n${renderList(bv.messaging_themes)}\\n\\nUse language like this:\\n${renderList(bv.use_language_like)}\\n\\nAvoid language like this:\\n${renderList(bv.avoid_language_like)}\\n\\n---\\n\\n`;\n  }\n  if (data.prohibited_phrases) md += `# Prohibited Phrases & Clich\u00e9s\\n\\n${renderList(data.prohibited_phrases)}\\n\\n---\\n\\n`;\n  if (data.key_content_topics) {\n    md += `# Key Content Topics\\n\\n`;\n    data.key_content_topics.forEach(tg => { md += `## ${tg.service_name} Topics\\n${renderList(tg.topics)}\\n\\n`; });\n    md += `---\\n\\n`;\n  }\n  if (data.seo_keywords) {\n    const seo = data.seo_keywords;\n    md += `# SEO Keywords\\n\\nPrimary:\\n${renderList(seo.primary)}\\n\\nSecondary:\\n${renderList(seo.secondary)}\\n\\nLong-Tail:\\n${renderList(seo.long_tail)}\\n\\n---\\n\\n`;\n  }\n  if (data.content_strategy) {\n    const cs = data.content_strategy;\n    md += `# Content Strategy\\n\\n## Monthly Content Targets\\nBlogs: ${cs.monthly_targets.blogs}\\nLinkedIn Posts: ${cs.monthly_targets.linkedin_posts}\\nEducational Social Posts: ${cs.monthly_targets.educational_social_posts}\\nEmail Newsletters: ${cs.monthly_targets.email_newsletters}\\nLong-Form Guides: ${cs.monthly_targets.long_form_guides}\\n\\n## Content Pillars\\n`;\n    cs.content_pillars.forEach((p, i) => { md += `${i + 1}. ${p}\\n`; });\n    md += `\\n---\\n\\n`;\n  }\n  if (data.marketing_channels) {\n    md += `# Marketing Channels\\n\\nPrimary:\\n${renderList(data.marketing_channels.primary)}\\n\\nSecondary:\\n${renderList(data.marketing_channels.secondary)}\\n\\n---\\n\\n`;\n  }\n  if (data.industry_trends) md += `# Industry Trends\\n\\n${renderList(data.industry_trends)}\\n\\n---\\n\\n`;\n  if (data.technical_integrations) md += `# Technical Integrations\\n\\n${renderList(data.technical_integrations)}\\n\\n---\\n\\n`;\n  if (data.internal_workflow) {\n    md += `# Internal Workflow\\n\\n## Team Roles\\n\\n`;\n    data.internal_workflow.forEach(m => { md += `${m.role}:\\n${m.responsibility}\\n\\n`; });\n    md += `---\\n\\n`;\n  }\n  md += `# End of File\\n`;\n  return md;\n}\n\nconst finalMarkdown = generateMarkdownFromData(inputJson);\nreturn {data: finalMarkdown}"
      },
      "typeVersion": 2
    },
    {
      "id": "48658195-a7a4-41e8-ba85-a33abc1afa0f",
      "name": "Export MD File",
      "type": "n8n-nodes-base.convertToFile",
      "position": [
        3904,
        3664
      ],
      "parameters": {
        "options": {
          "fileName": "={{ $('Parse Response').item.json.response.company_overview.name }} AI Context.md"
        },
        "operation": "toText",
        "sourceProperty": "data"
      },
      "typeVersion": 1.1
    },
    {
      "id": "3e226295-f40e-42f9-af7a-d8137517d884",
      "name": "Save to Drive",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        4224,
        3664
      ],
      "parameters": {
        "name": "={{ $binary.data.fileName }}",
        "driveId": {
          "__rl": true,
          "mode": "list",
          "value": "My Drive",
          "cachedResultUrl": "https://drive.google.com/drive/my-drive",
          "cachedResultName": "My Drive"
        },
        "options": {},
        "folderId": {
          "__rl": true,
          "mode": "list",
          "value": "root",
          "cachedResultUrl": "https://drive.google.com/drive",
          "cachedResultName": "/ (Root folder)"
        }
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "4e36a718-23ca-4a07-b076-54b9a6c9de46",
      "name": "Fetch GA Data",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueRegularOutput",
      "position": [
        3280,
        4224
      ],
      "parameters": {
        "url": "=https://analyticsdata.googleapis.com/v1beta/properties/{{ $json.property_id }}:runReport",
        "method": "POST",
        "options": {},
        "jsonBody": "{\n  \"dateRanges\": [{\"startDate\": \"30daysAgo\", \"endDate\": \"today\"}],\n  \"dimensions\": [{\"name\": \"pagePath\"}, {\"name\": \"pageTitle\"}],\n  \"metrics\": [{\"name\": \"sessions\"}, {\"name\": \"bounceRate\"}, {\"name\": \"averageSessionDuration\"}],\n  \"orderBys\": [{\"metric\": {\"metricName\": \"sessions\"}, \"desc\": true}]\n}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "googleAnalyticsOAuth2"
      },
      "credentials": {
        "googleAnalyticsOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2,
      "alwaysOutputData": true
    },
    {
      "id": "4585b237-ff17-4d8d-877e-fdee2435c911",
      "name": "Fetch Trending Topics",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueErrorOutput",
      "position": [
        3280,
        4448
      ],
      "parameters": {
        "url": "=https://trends.google.com/trending/rss?geo={{ $('Config: Pipeline B').item.json.trends_geo }}&hl={{ $('Config: Pipeline B').item.json.trends_lang }}",
        "options": {
          "response": {
            "response": {
              "responseFormat": "text",
              "outputPropertyName": "trends_data"
            }
          }
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "40ed2e5d-0802-4be8-8413-02f0da9fdede",
      "name": "Merge Data Sources",
      "type": "n8n-nodes-base.merge",
      "position": [
        4000,
        4224
      ],
      "parameters": {
        "numberInputs": 3
      },
      "typeVersion": 3,
      "alwaysOutputData": true
    },
    {
      "id": "f6edf885-aa38-4601-9a95-6a13388ee6a6",
      "name": "Compress Brand Context",
      "type": "n8n-nodes-base.code",
      "position": [
        4352,
        4240
      ],
      "parameters": {
        "jsCode": "const items = $input.all();\nconst mdItem      = items.find(i => i.json.master_data !== undefined);\nconst gaItem      = items.find(i => i.json.rows !== undefined || i.json.error !== undefined);\nconst trendsItem  = items.find(i => i.json.trends_data !== undefined);\nconst md     = mdItem?.json?.master_data ?? '';\nconst ga     = gaItem?.json ?? {};\nconst trends = trendsItem?.json?.trends_data ?? '';\nif (!md) throw new Error('Fetch Master MD returned empty \u2014 check the URL and HTTP node.');\nfunction extractCompanyName(md) {\n  const overview = extractSection(md, 'Company Overview');\n  if (!overview) return '';\n\n  const match = overview.match(/Company Name:\\s*(.*)/i);\n  return match ? match[1].trim() : '';\n}\nfunction extractSection(text, heading) {\n  const chunks = text.split(/\\n(?=# )/);\n  for (const chunk of chunks) {\n    const firstLine = chunk.split('\\n')[0].trim();\n    const title = firstLine.replace(/^#+\\s*/, '');\n    if (title.toLowerCase() === heading.toLowerCase()) {\n      return chunk.trim();\n    }\n  }\n  return '';\n}\nconst compressed = [\n  extractSection(md, 'Core Services'),\n  extractSection(md, 'Target Audience'),\n  extractSection(md, 'SEO Keywords'),\n  extractSection(md, 'Prohibited Phrases & Clich\u00e9s'),\n  extractSection(md, 'Brand Voice & Messaging')\n].filter(Boolean).join('\\n\\n---\\n\\n');\nconst gaRows = ga.rows ?? [];\nconst top5Sessions = gaRows\n  .slice(0, 5)\n  .map(r => `${r.dimensionValues?.[1]?.value ?? 'Unknown'}: ${r.metricValues?.[0]?.value ?? 0} sessions`)\n  .join('\\n');\nconst top5Bounce = [...gaRows]\n  .sort((a, b) => parseFloat(b.metricValues?.[1]?.value ?? 0) - parseFloat(a.metricValues?.[1]?.value ?? 0))\n  .slice(0, 5)\n  .map(r => `${r.dimensionValues?.[1]?.value ?? 'Unknown'}: ${(parseFloat(r.metricValues?.[1]?.value ?? 0) * 100).toFixed(0)}% bounce`)\n  .join('\\n');\nconst gaSummary = gaRows.length > 0\n  ? `Top pages by sessions:\\n${top5Sessions}\\n\\nHigh-bounce pages (content gaps):\\n${top5Bounce}`\n  : 'Analytics data unavailable \u2014 proceed without gap analysis';\nconst AI_KEYWORDS = [\n  'ai', 'artificial intelligence', 'machine learning', 'ml', 'llm',\n  'automation', 'automat', 'chatgpt', 'generative', 'genai', 'gpt',\n  'agentic', 'agent', 'copilot', 'workflow', 'saas', 'digital',\n  'enterprise software', 'productivity', 'cloud', 'data analytics',\n  'prompt', 'openai', 'gemini', 'claude', 'chatbot', 'robotic',\n  'rpa', 'nlp', 'deep learning', 'neural', 'digital transformation',\n  'business automation', 'ai tools', 'ai strategy', 'technology'\n];\nfunction parseTrendItems(xml) {\n  const items = [];\n  const itemRe = /<item>([\\s\\S]*?)<\\/item>/g;\n  let m;\n  while ((m = itemRe.exec(xml)) !== null) {\n    const itemXml = m[1];\n    const titleM   = itemXml.match(/<title>(?:<!\\[CDATA\\[)?(.*?)(?:\\]\\]>)?<\\/title>/);\n    const trafficM = itemXml.match(/<ht:approx_traffic>(.*?)<\\/ht:approx_traffic>/);\n    const newsTitles = [...itemXml.matchAll(/<ht:news_item_title>(?:<!\\[CDATA\\[)?(.*?)(?:\\]\\]>)?<\\/ht:news_item_title>/g)]\n      .map(n => n[1].trim());\n    if (titleM) {\n      items.push({\n        title:       titleM[1].trim(),\n        traffic:     trafficM ? parseInt(trafficM[1].replace(/[^0-9]/g, '')) || 0 : 0,\n        newsTitles\n      });\n    }\n  }\n  return items;\n}\nfunction isRelevant(item) {\n  const searchText = (item.title + ' ' + item.newsTitles.join(' ')).toLowerCase();\n  return AI_KEYWORDS.some(kw => searchText.includes(kw));\n}\nconst allTrends   = parseTrendItems(trends);\nconst aiTrends    = allTrends.filter(isRelevant).sort((a, b) => b.traffic - a.traffic);\nconst topAiTrends = aiTrends.slice(0, 8);\nlet trendsSummary;\nif (topAiTrends.length > 0) {\n  const lines = topAiTrends.map(t => {\n    const traffic = t.traffic >= 1000 ? `${(t.traffic/1000).toFixed(0)}k+` : `${t.traffic}+`;\n    const context = t.newsTitles[0] ? ` \u2014 \"${t.newsTitles[0].slice(0, 80)}\"` : '';\n    return `  \u2022 ${t.title} (${traffic} searches)${context}`;\n  }).join('\\n');\n  trendsSummary = `AI & tech topics trending in India right now:\\n${lines}`;\n} else {\n  trendsSummary = `No AI/tech topics in today's Google Trends India feed (trending topics are unrelated: ${allTrends.slice(0,5).map(t => t.title).join(', ')}). Use evergreen AI business topics relevant to Indian enterprises instead.`;\n}\nconst BATCH_SECTIONS  = ['Core Services', 'Target Audience', 'Customer Pain Points', 'Value Propositions', 'Key Content Topics'];\nconst GUIDES_SECTIONS = [...BATCH_SECTIONS, 'Competitor Differentiation'];\nconst batchWritingContext  = BATCH_SECTIONS.map(s  => extractSection(md, s)).filter(Boolean).join('\\n\\n');\nconst guidesWritingContext = GUIDES_SECTIONS.map(s => extractSection(md, s)).filter(Boolean).join('\\n\\n');\nconst toneBlock = ['Brand Voice & Messaging', 'Prohibited Phrases & Clich\u00e9s']\n  .map(s => extractSection(md, s)).filter(Boolean).join('\\n\\n');\n\nconst companyName = extractCompanyName(md);\nreturn [{\n  json: {\n    companyName: companyName,\n    compressed_brand:      compressed,\n    full_brand:            md,\n    batch_writing_context: batchWritingContext,\n    guides_writing_context: guidesWritingContext,\n    tone_block:            toneBlock,\n    ga_summary:            gaSummary,\n    trends_summary:        trendsSummary,\n    trends_ai_count:       topAiTrends.length,\n    trends_total_count:    allTrends.length,\n    run_date:              new Date().toISOString().split('T')[0]\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "1e6f1d6b-5979-4e36-8d31-2ca1dcf0644a",
      "name": "Build Content Plan Prompt",
      "type": "n8n-nodes-base.code",
      "position": [
        4624,
        4240
      ],
      "parameters": {
        "jsCode": "const compressedBrand = $input.first().json.compressed_brand;\nconst companyName = $input.first().json.companyName;\nconst gaSummary = $input.first().json.ga_summary;\nconst trendsSummary = $input.first().json.trends_summary;\n\nconst prompt = {\n  \"systemInstruction\": \"You are a senior AI content strategist. Return ONLY valid JSON with no preamble, no markdown fences, and no explanation.\",\n  \"userMessage\": `You are planning monthly AI marketing content for ${companyName} \u2014 an IT consulting agency with four service pillars: AI Strategy Consulting, AI Training & Fluency, Agentic AI Systems, Business Automation.\\n\\nBrand context (compressed):\\n${compressedBrand}\\n\\nWebsite analytics summary:\\n${gaSummary}\\n\\nTrending topics this month:\\n${trendsSummary}\\n\\nInstructions:\\n- Use analytics high-bounce pages to identify content gaps \u2014 prioritize filling those gaps.\\n- Use trending topics to rank ideas by rising search interest.\\n- Distribute content evenly across all 4 pillars. No pillar should have more than 2 blog topics.\\n- Blog primary keywords must be search-viable and non-branded.\\n- LinkedIn hooks must be specific \u2014 no openers starting with \"AI is transforming...\" or \"In today's world...\".\\n- Long-tail keywords must include intent signals: \"how to\", \"for enterprise\", \"ROI of\", or comparison terms.\\n- Never use these phrases: game-changer, leverage, unlock potential, cutting-edge, seamless, robust, disruptive.\\n\\nReturn ONLY this JSON schema \u2014 no other text:\\n{\\n  \"strategy_overview\": \"2-3 sentence summary citing specific gaps or trends identified\",\\n  \"blog_topics\": [\\n    {\"title\": \"\", \"primary_keyword\": \"\", \"content_pillar\": \"AI Strategy|AI Training|Agentic AI|Automation\", \"target_persona\": \"CTO|Operations Leader|Innovation Builder|L&D Manager\"}\\n  ],\\n  \"linkedin_posts\": [\\n    {\"topic\": \"\", \"hook\": \"\", \"content_pillar\": \"AI Strategy|AI Training|Agentic AI|Automation\"}\\n  ],\\n  \"social_posts\": [\\n    {\"topic\": \"\", \"format\": \"tip|stat|question|checklist\"}\\n  ],\\n  \"email_topics\": [\\n    {\"subject\": \"\", \"content_pillar\": \"AI Strategy|AI Training|Agentic AI|Automation\"}\\n  ],\\n  \"guides\": [\\n    {\"title\": \"\", \"content_pillar\": \"AI Strategy|AI Training|Agentic AI|Automation\"}\\n  ],\\n  \"keyword_clusters\": {\\n    \"ai_strategy\": [],\\n    \"agentic_ai\": [],\\n    \"automation\": [],\\n    \"ai_training\": []\\n  },\\n  \"long_tail_keywords\": []\\n}\\n\\nCounts required: 6 blog_topics, 12 linkedin_posts, 8 social_posts, 4 email_topics, 4 guides, 5-8 terms per keyword cluster, 10 long_tail_keywords.`,\n  \"generationConfig\": {\n    \"temperature\": 0.4,\n    \"maxOutputTokens\": 8192,\n    \"responseMimeType\": \"application/json\",\n    thinkingConfig: {\n      thinkingBudget: 0\n    }\n  }\n};\n\nreturn { json: prompt };"
      },
      "typeVersion": 2
    },
    {
      "id": "8a55e57d-5144-4c38-814e-a7e52d8896bb",
      "name": "Validate Content Plan",
      "type": "n8n-nodes-base.code",
      "position": [
        2384,
        4768
      ],
      "parameters": {
        "jsCode": "const response = $input.all()[0].json;\nif (response?.error) {\n  throw new Error('Gemini API error: ' + JSON.stringify(response.error));\n}\nconst rawText = response?.content?.parts?.[0]?.text ?? '';\nconst finishReason = response?.finish_reason ?? 'UNKNOWN';\nif (!rawText) {\n  throw new Error('Gemini returned empty content. Full response: ' + JSON.stringify(response).slice(0, 500));\n}\nlet text = rawText.replace(/^```json\\s*/m, '').replace(/\\s*```$/m, '').trim();\nif ((text.startsWith('\"') && text.endsWith('\"')) ||\n    (text.startsWith(\"'\") && text.endsWith(\"'\"))) {\n  text = text.slice(1, -1)\n    .replace(/\\\\\"/g, '\"')\n    .replace(/\\\\n/g, '\\n')\n    .replace(/\\\\\\\\/g, '\\\\');\n}\nlet plan = null;\nlet parseError = null;\ntry {\n  plan = JSON.parse(text);\n  if (typeof plan === 'string') {\n    plan = JSON.parse(plan);\n  }\n} catch (e) {\n  parseError = e.message;\n  plan = null;\n}\nif (!plan || typeof plan !== 'object' || Array.isArray(plan)) {\n  function extractArray(src, key) {\n    const re = new RegExp('\"' + key + '\"\\\\s*:\\\\s*(\\\\[[\\\\s\\\\S]*?\\\\])(?=\\\\s*[,}])', '');\n    const m = src.match(re);\n    if (m) {\n      try { return JSON.parse(m[1]); } catch (e) { return null; }\n    }\n    return null;\n  }\n  function extractString(src, key) {\n    const re = new RegExp('\"' + key + '\"\\\\s*:\\\\s*\"((?:[^\"\\\\\\\\]|\\\\\\\\.)*)\"');\n    const m = src.match(re);\n    return m ? m[1] : null;\n  }\n  plan = {\n    strategy_overview:  extractString(text, 'strategy_overview') || 'Strategy overview unavailable (response truncated)',\n    blog_topics:        extractArray(text, 'blog_topics')        || [],\n    linkedin_posts:     extractArray(text, 'linkedin_posts')     || [],\n    social_posts:       extractArray(text, 'social_posts')       || [],\n    email_topics:       extractArray(text, 'email_topics')       || [],\n    guides:             extractArray(text, 'guides')             || [],\n    keyword_clusters:   extractArray(text, 'keyword_clusters')   || {},\n    long_tail_keywords: extractArray(text, 'long_tail_keywords') || []\n  };\n}\nconst required = [\n  ['blog_topics', 6],\n  ['linkedin_posts', 12],\n  ['social_posts', 8],\n  ['email_topics', 4],\n  ['guides', 4]\n];\nconst failures = required\n  .filter(([key, count]) => !Array.isArray(plan[key]) || plan[key].length < count)\n  .map(([key, count]) => key + ': expected ' + count + ', got ' + (plan[key]?.length ?? 0));\nif (failures.length > 0) {\n  const hint = finishReason === 'MAX_TOKENS'\n    ? ' Gemini hit MAX_TOKENS \u2014 increase maxOutputTokens or reduce prompt size.'\n    : '';\n  throw new Error(\n    'Content plan validation failed:' + hint + '\\n' +\n    failures.join('\\n') +\n    '\\n\\nfinishReason: ' + finishReason +\n    '\\nRaw output (first 600 chars):\\n' + rawText.slice(0, 600)\n  );\n}\nreturn [{ json: { content_plan: plan, finish_reason: finishReason } }];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "d82125b3-5f3a-4df6-8ddc-648d7a7c13e1",
      "name": "Build Batch Prompt",
      "type": "n8n-nodes-base.code",
      "position": [
        2672,
        4688
      ],
      "parameters": {
        "jsCode": "const companyName = $('Compress Brand Context').first().json.companyName;\nconst plan             = $('Validate Content Plan').first().json.content_plan;\nconst batchContext     = $('Compress Brand Context').first().json.batch_writing_context;\nconst toneBlock        = $('Compress Brand Context').first().json.tone_block;\n\nconst blogTopics    = JSON.stringify(plan.blog_topics,    null, 2);\nconst linkedinPosts = JSON.stringify(plan.linkedin_posts, null, 2);\nconst socialPosts   = JSON.stringify(plan.social_posts,   null, 2);\nconst emailTopics   = JSON.stringify(plan.email_topics,   null, 2);\n\nconst user_prompt = `Brand context:\n${batchContext}\n\nYou will write four content types in sequence. Separate each type with EXACTLY this delimiter on its own line: ===SECTION: [TYPE]===\n\n---\n===SECTION: BLOGS===\n\nWrite all 6 SEO blog articles for these topics:\n${blogTopics}\n\nFor each article include:\n- SEO title (primary keyword used naturally, not forced)\n- Meta description (150-160 characters)\n- Introduction (150 words \u2014 frame the business problem clearly)\n- 4-5 H2 sections with H3 subheadings where appropriate\n- Real business scenarios (no invented company names)\n- Practical implementation steps a reader can act on\n- 5-point key takeaways\n- Soft CTA for [Your Brand] consulting (2-3 sentences, non-pushy)\n- Length: 1200-1500 words each\n- Separate articles with: --- ARTICLE BREAK ---\n- Label each: ARTICLE 1: [Title], ARTICLE 2: [Title], etc.\n\n===SECTION: LINKEDIN===\n\nWrite all 12 LinkedIn thought leadership posts for these topics:\n${linkedinPosts}\n\nFor each post include:\n- Opening hook (specific question, stat, or bold statement \u2014 NOT \"AI is transforming...\" or \"In today's world...\")\n- 150-250 words of practical insight\n- 1 clear, actionable takeaway\n- 5-8 relevant hashtags\n- First-person voice as a senior AI consultant\n- Mix formats across the 12: some narrative, some list-style, some question-driven\n- Separate with: --- POST BREAK ---\n- Label each: POST 1, POST 2, etc.\n\n===SECTION: SOCIAL===\n\nWrite all 8 educational social media posts for these topics:\n${socialPosts}\n\nFor each post include:\n- Engaging hook\n- Core content 80-120 words matching the plan format (tip/stat/question/checklist)\n- 1 practical insight the reader can use immediately\n- 4-6 hashtags\n- Separate with: --- POST BREAK ---\n- Label each: SOCIAL 1 [FORMAT], SOCIAL 2 [FORMAT], etc.\n\n===SECTION: EMAILS===\n\nWrite all 4 email newsletters for these topics:\n${emailTopics}\n\nFor each newsletter include:\n- Subject line (under 50 characters, no clickbait)\n- Preview text (under 90 characters)\n- Opening hook (2-3 sentences that earn the read)\n- Main content (300-400 words: insight, trend, or how-to)\n- Secondary block: brief tip or resource placeholder\n- Soft CTA (conversation invite, guide link, or free assessment offer)\n- Sign-off from [Your Brand] team\n- Separate with: --- EMAIL BREAK ---\n- Label each: EMAIL 1, EMAIL 2, etc.`\n\nconst systemInstruction = `You are a professional AI content writer for ${companyName}.\n\n## CRITICAL: OUTPUT STRUCTURE\nYou MUST return a single valid JSON object. No markdown, no backticks, no explanation outside the JSON.\nThe JSON must follow this exact structure:\n\n{\n  \"blog_articles\": [\n    {\n      \"article_title\": \"ARTICLE 1: [Title]\",\n      \"seo_title\": \"string\",\n      \"meta_description\": \"string (150-160 chars)\",\n      \"introduction\": \"string\",\n      \"sections\": [\n        {\n          \"h2\": \"string\",\n          \"h3\": \"string\",\n          \"content\": \"string\"\n        }\n      ],\n      \"key_takeaways\": [\"string\", \"string\", \"string\", \"string\", \"string\"],\n      \"call_to_action\": \"string\",\n      \"word_count\": 0\n    }\n  ],\n  \"linkedin_posts\": [\n    {\n      \"post_number\": \"POST 1\",\n      \"topic\": \"string\",\n      \"hook\": \"string\",\n      \"body\": \"string\",\n      \"takeaway\": \"string\",\n      \"hashtags\": [\"string\"]\n    }\n  ],\n  \"social_posts\": [\n    {\n      \"post_number\": \"SOCIAL 1\",\n      \"format\": \"tip | stat | question | checklist\",\n      \"topic\": \"string\",\n      \"hook\": \"string\",\n      \"content\": \"string\",\n      \"insight\": \"string\",\n      \"hashtags\": [\"string\"]\n    }\n  ],\n  \"email_newsletters\": [\n    {\n      \"email_number\": \"EMAIL 1\",\n      \"subject_line\": \"string (under 50 chars)\",\n      \"preview_text\": \"string (under 90 chars)\",\n      \"opening_hook\": \"string\",\n      \"main_content\": \"string\",\n      \"secondary_block\": \"string\",\n      \"call_to_action\": \"string\",\n      \"sign_off\": \"string\"\n    }\n  ]\n}\n\nRules:\n- blog_articles must have exactly 6 items\n- linkedin_posts must have exactly 12 items\n- social_posts must have exactly 8 items\n- email_newsletters must have exactly 4 items\n- All strings must be properly escaped for JSON\n- Do NOT include ===SECTION=== delimiters inside the JSON\n- Do NOT wrap the JSON in markdown code blocks`;\n\nconst prompt = {\n    \"systemInstruction\": systemInstruction,\n    \"userMessage\": user_prompt,\n    generationConfig: {\n    temperature: 0.75,\n    maxOutputTokens: 120000,\n    thinkingConfig: {\n      thinkingBudget: 0\n    }\n  }\n};\n\nreturn { json: prompt };"
      },
      "typeVersion": 2
    },
    {
      "id": "9fefd545-80da-4cb5-8641-ee47bb24911b",
      "name": "Build Guides Prompt",
      "type": "n8n-nodes-base.code",
      "position": [
        2672,
        4912
      ],
      "parameters": {
        "jsCode": "const companyName = $('Compress Brand Context').first().json.companyName;\nconst plan          = $('Validate Content Plan').first().json.content_plan;\nconst guidesContext = $('Compress Brand Context').first().json.guides_writing_context;\nconst toneBlock     = $('Compress Brand Context').first().json.tone_block;\n\nconst guideTopics = JSON.stringify(plan.guides, null, 2);\nconst user_prompt = `Brand context:\n${guidesContext}\n\n---\n\nWrite all 4 AI guides for these topics:\n${guideTopics}\n\nEach guide must include:\n- Title and subtitle\n- Executive summary (100 words)\n- 5-7 structured H2 sections\n- A framework or decision model where applicable\n- 2-3 realistic business scenarios (no invented company names)\n- Common mistakes section\n- Recommended next steps (numbered list)\n- How [Your Brand] can help (2-3 sentences, brief and non-pushy)\n\nTarget length: 1800-2000 words each.\nSeparate each guide with: --- GUIDE BREAK ---\nLabel each: GUIDE 1: [Title], GUIDE 2: [Title], etc.`\nconst prompt = {\n  \"systemInstruction\": `You are a senior AI strategist and writer for ${companyName}.\nWrite authoritative, practical guides for business leaders making investment decisions.\nTone: direct, data-informed, results-focused.\n\nTONE & VOICE:\n${toneBlock}`,\n  \"userMessage\": user_prompt,\n  generationConfig: {\n    temperature: 0.6,\n    maxOutputTokens: 8192,\n    thinkingConfig: {\n      thinkingBudget: 0\n    }\n  }\n};\n\nreturn { json: prompt };"
      },
      "typeVersion": 2
    },
    {
      "id": "bcb8143c-5f0d-4088-9031-674d86cf3e6e",
      "name": "Parse Content Sections",
      "type": "n8n-nodes-base.code",
      "position": [
        3392,
        4688
      ],
      "parameters": {
        "jsCode": "const response = $input.first().json;\nif (response?.error) {\n  throw new Error('Gemini batch call API error: ' + JSON.stringify(response.error));\n}\n\n// Gemini node in n8n may return parsed JSON directly or as a text string\nlet parsed;\n\nif (response.blog_articles || response.linkedin_posts) {\n  // n8n already parsed the JSON (responseMimeType: application/json)\n  parsed = response;\n} else {\n  // Fallback: extract raw text and parse manually\n  const raw = response?.[0]?.content?.parts?.[0]?.text\n           ?? response?.content?.parts?.[0]?.text\n           ?? '';\n\n  if (!raw) {\n    throw new Error('Gemini: Write Batch Content returned empty. Check API key, quota, and node output.');\n  }\n\n  try {\n    const clean = raw.replace(/```json|```/g, '').trim();\n    parsed = JSON.parse(clean);\n  } catch (e) {\n    throw new Error('Failed to parse Gemini JSON response: ' + e.message + '\\n\\nRaw preview: ' + raw.substring(0, 300));\n  }\n}\n\n// Validate expected sections\nconst warnings = [];\nif (!Array.isArray(parsed.blog_articles)     || parsed.blog_articles.length === 0)     warnings.push('blog_articles missing or empty');\nif (!Array.isArray(parsed.linkedin_posts)    || parsed.linkedin_posts.length === 0)     warnings.push('linkedin_posts missing or empty');\nif (!Array.isArray(parsed.social_posts)      || parsed.social_posts.length === 0)       warnings.push('social_posts missing or empty');\nif (!Array.isArray(parsed.email_newsletters) || parsed.email_newsletters.length === 0)  warnings.push('email_newsletters missing or empty');\n\n// Validate counts\nif (parsed.blog_articles?.length     !== 6)  warnings.push(`blog_articles count is ${parsed.blog_articles?.length}, expected 6`);\nif (parsed.linkedin_posts?.length    !== 12) warnings.push(`linkedin_posts count is ${parsed.linkedin_posts?.length}, expected 12`);\nif (parsed.social_posts?.length      !== 8)  warnings.push(`social_posts count is ${parsed.social_posts?.length}, expected 8`);\nif (parsed.email_newsletters?.length !== 4)  warnings.push(`email_newsletters count is ${parsed.email_newsletters?.length}, expected 4`);\n\nif (warnings.length > 0) {\n  console.warn('Parse Batch Sections warnings: ' + warnings.join(', '));\n}\n\nreturn [{\n  json: {\n    blog_articles:     parsed.blog_articles     ?? [],\n    linkedin_posts:    parsed.linkedin_posts     ?? [],\n    social_posts:      parsed.social_posts       ?? [],\n    email_newsletters: parsed.email_newsletters  ?? [],\n    content_plan:      $('Validate Content Plan').first().json.content_plan,\n    parse_warnings:    warnings\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "ff3bde36-74a1-4533-b699-edb25e226210",
      "name": "Extract Guides",
      "type": "n8n-nodes-base.code",
      "position": [
        3392,
        4912
      ],
      "parameters": {
        "jsCode": "const response = $input.first().json;\nif (response?.error) {\n  throw new Error('Gemini guides call API error: ' + JSON.stringify(response.error));\n}\nconst guidesText = response?.content?.parts?.[0]?.text ?? '[MISSING: Guides \u2014 Gemini: Write Guides returned empty. Check API key and token limits.]';\nreturn [{ json: { ai_guides: guidesText } }];"
      },
      "typeVersion": 2
    },
    {
      "id": "ef563ded-5e36-47a6-9c0b-ef2653bc3e02",
      "name": "Merge Content Output",
      "type": "n8n-nodes-base.merge",
      "position": [
        3776,
        4816
      ],
      "parameters": {},
      "typeVersion": 3,
      "alwaysOutputData": true
    },
    {
      "id": "3493f35d-f97e-498a-b7ab-0c747300017b",
      "name": "Build DOCX",
      "type": "n8n-nodes-base.code",
      "position": [
        4176,
        4816
      ],
      "parameters": {
        "jsCode": "let inp = {};\ntry { inp = $input.first().json || {}; } catch(e) { inp = {}; }\n\nconst docTitle  = inp.doc_title        || 'AI Content Package';\nconst runDate   = inp.run_date         || new Date().toLocaleDateString('en-IN',{month:'long',year:'numeric'});\nconst plan      = inp.content_plan     || {};\nconst assembled = inp.assembled_content || '';\n\nconst NAVY='1E3A5F', BLUE='2E75B6', LBLUE='EBF3FB', ALT='F5F7FA';\nconst BODY='444444', MUTED='777777', WHITE='FFFFFF', CHARCOAL='2B2B2B';\n\nconst esc = s => String(s||'').replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;');\n\nfunction rPr(o){\n  o=o||{};\n  return `<w:rPr>${o.bold?'<w:b/>':''}${o.italic?'<w:i/>':''}<w:color w:val=\"${o.color||BODY}\"/><w:sz w:val=\"${o.size||22}\"/><w:szCs w:val=\"${o.size||22}\"/><w:rFonts w:ascii=\"${o.font||'Calibri'}\" w:hAnsi=\"${o.font||'Calibri'}\" w:cs=\"${o.font||'Calibri'}\"/></w:rPr>`;\n}\n\nfunction run(text,o){ return `<w:r>${rPr(o)}<w:t xml:space=\"preserve\">${esc(text)}</w:t></w:r>`; }\n\nfunction para(runs,o){\n  o=o||{};\n  const sb=o.spaceBefore!==undefined?o.spaceBefore:60, sa=o.spaceAfter!==undefined?o.spaceAfter:60;\n  const jc=o.align?`<w:jc w:val=\"${o.align}\"/>`:'';\n  const sp=`<w:spacing w:before=\"${sb}\" w:after=\"${sa}\"/>`;\n  const bd=o.borderBottom?`<w:pBdr><w:bottom w:val=\"single\" w:sz=\"8\" w:space=\"4\" w:color=\"${o.borderBottom}\"/></w:pBdr>`:'';\n  return `<w:p><w:pPr>${bd}${sp}${jc}</w:pPr>${Array.isArray(runs)?runs.join(''):runs}</w:p>`;\n}\n\nconst h1 = t => para(run(t,{bold:true,color:NAVY,size:32}),{spaceBefore:240,spaceAfter:80,borderBottom:BLUE});\nconst h2 = t => para(run(t,{bold:true,color:BLUE,size:26}),{spaceBefore:160,spaceAfter:60});\nconst h3 = t => para(run(t,{bold:true,color:CHARCOAL,size:24}),{spaceBefore:140,spaceAfter:40});\nconst h4 = t => para(run(t,{bold:true,color:BODY,size:22}),{spaceBefore:100,spaceAfter:30});\nconst bodyP  = t => para(run(t,{color:BODY,size:22}),{spaceBefore:40,spaceAfter:40});\nconst mutedP = t => para(run(t,{color:MUTED,size:20,italic:true}),{spaceBefore:40,spaceAfter:40});\nconst bulletP = t => `<w:p><w:pPr><w:numPr><w:ilvl w:val=\"0\"/><w:numId w:val=\"1\"/></w:numPr><w:spacing w:before=\"40\" w:after=\"40\"/></w:pPr>${run(t,{color:BODY,size:22})}</w:p>`;\nconst numP    = (t,nid) => `<w:p><w:pPr><w:numPr><w:ilvl w:val=\"0\"/><w:numId w:val=\"${nid||2}\"/></w:numPr><w:spacing w:before=\"40\" w:after=\"40\"/></w:pPr>${run(t,{color:BODY,size:22})}</w:p>`;\nconst spacerP  = () => `<w:p><w:pPr><w:spacing w:before=\"40\" w:after=\"40\"/></w:pPr></w:p>`;\nconst pgBreak  = () => `<w:p><w:r><w:br w:type=\"page\"/></w:r></w:p>`;\nconst dividerP = () => `<w:p><w:pPr><w:pBdr><w:bottom w:val=\"single\" w:sz=\"2\" w:space=\"2\" w:color=\"${LBLUE}\"/></w:pBdr><w:spacing w:before=\"80\" w:after=\"80\"/></w:pPr></w:p>`;\nconst labelValueP = (label,value) => `<w:p><w:pPr><w:spacing w:before=\"40\" w:after=\"40\"/></w:pPr>${run(label+': ',{bold:true,color:NAVY,size:22})}${run(value,{color:BODY,size:22})}</w:p>`;\nconst takeawayP = value => `<w:p><w:pPr><w:spacing w:before=\"80\" w:after=\"80\"/><w:shd w:val=\"clear\" w:color=\"auto\" w:fill=\"${LBLUE}\"/></w:pPr>${run('Actionable Takeaway: ',{bold:true,color:NAVY,size:20})}${run(value,{color:CHARCOAL,size:20})}</w:p>`;\n\nfunction cell(text,width,fill,bold,color){\n  fill=fill||WHITE; bold=bold||false; color=color||CHARCOAL;\n  const shd=`<w:shd w:val=\"clear\" w:color=\"auto\" w:fill=\"${fill}\"/>`;\n  const bdr=`<w:tcBorders><w:top w:val=\"single\" w:sz=\"2\" w:color=\"D0D9E3\"/><w:bottom w:val=\"single\" w:sz=\"2\" w:color=\"D0D9E3\"/><w:left w:val=\"single\" w:sz=\"2\" w:color=\"D0D9E3\"/><w:right w:val=\"single\" w:sz=\"2\" w:color=\"D0D9E3\"/></w:tcBorders>`;\n  const mar=`<w:tcMar><w:top w:w=\"80\" w:type=\"dxa\"/><w:bottom w:w=\"80\" w:type=\"dxa\"/><w:left w:w=\"140\" w:type=\"dxa\"/><w:right w:w=\"140\" w:type=\"dxa\"/></w:tcMar>`;\n  const p=para(run(text,{bold,color,size:20}),{spaceBefore:0,spaceAfter:0});\n  return `<w:tc><w:tcPr><w:tcW w:w=\"${width}\" w:type=\"dxa\"/>${bdr}${shd}${mar}</w:tcPr>${p}</w:tc>`;\n}\nconst hCell = (t,w) => cell(t,w,NAVY,true,WHITE);\nconst trow  = cells => `<w:tr>${cells.join('')}</w:tr>`;\nconst tbl   = (W,cols,rows) => {\n  const grid=cols.map(w=>`<w:gridCol w:w=\"${w}\"/>`).join('');\n  return `<w:tbl><w:tblPr><w:tblW w:w=\"${W}\" w:type=\"dxa\"/><w:tblLayout w:type=\"fixed\"/><w:tblCellMar><w:top w:w=\"0\" w:type=\"dxa\"/><w:bottom w:w=\"0\" w:type=\"dxa\"/></w:tblCellMar></w:tblPr><w:tblGrid>${grid}</w:tblGrid>${rows.join('')}</w:tbl>`;\n};\n\nfunction cover(){\n  const nob=`<w:tcBorders><w:top w:val=\"none\"/><w:bottom w:val=\"none\"/><w:left w:val=\"none\"/><w:right w:val=\"none\"/></w:tcBorders>`;\n  const mar=`<w:tcMar><w:top w:w=\"300\" w:type=\"dxa\"/><w:bottom w:w=\"300\" w:type=\"dxa\"/><w:left w:w=\"400\" w:type=\"dxa\"/><w:right w:w=\"400\" w:type=\"dxa\"/></w:tcMar>`;\n  const c1=`<w:tc><w:tcPr><w:tcW w:w=\"9360\" w:type=\"dxa\"/>${nob}<w:shd w:val=\"clear\" w:color=\"auto\" w:fill=\"${NAVY}\"/>${mar}</w:tcPr>`\n    +para(run('[YOUR COMPANY NAME]',{bold:true,color:WHITE,size:52}),{spaceBefore:0,spaceAfter:80})\n    +para(run('AI Content Pipeline \\u2014 Monthly Package',{color:'BDD7EE',size:28}),{spaceBefore:0,spaceAfter:0})\n    +`</w:tc>`;\n  const c2=`<w:tc><w:tcPr><w:tcW w:w=\"9360\" w:type=\"dxa\"/>${nob}<w:shd w:val=\"clear\" w:color=\"auto\" w:fill=\"${LBLUE}\"/>${mar}</w:tcPr>`\n    +para(run('Generated: '+runDate+'  |  Pipeline: Optimized',{color:BLUE,size:22}),{spaceBefore:0,spaceAfter:60})\n    +para(run('Powered by n8n Automation',{color:MUTED,size:20}),{spaceBefore:0,spaceAfter:0})\n    +`</w:tc>`;\n  return tbl(9360,[9360],[trow([c1])])+tbl(9360,[9360],[trow([c2])])+spacerP();\n}\n\nfunction summaryTbl(){\n  const d=[\n    ['SEO Blog Articles','6'],\n    ['LinkedIn Thought Leadership Posts','12'],\n    ['Educational Social Media Posts','8'],\n    ['Email Newsletter Campaigns','4'],\n    ['AI Strategy & Automation Guides','4'],\n    ['TOTAL','34']\n  ];\n  return tbl(9360,[7200,2160],[\n    trow([hCell('Content Type',7200),hCell('Count',2160)]),\n    ...d.map(([t,c],i)=>trow([\n      cell(t,7200,i%2?ALT:WHITE,t==='TOTAL',t==='TOTAL'?NAVY:CHARCOAL),\n      cell(c,2160,i%2?ALT:WHITE,true,BLUE)\n    ]))\n  ]);\n}\n\nfunction tocTbl(){\n  const rows=[\n    ['1','Monthly Content Strategy Overview'],\n    ['2','SEO Blog Articles (6)'],\n    ['3','LinkedIn Thought Leadership Posts (12)'],\n    ['4','Educational Social Media Posts (8)'],\n    ['5','Email Newsletter Campaigns (4)'],\n    ['6','AI Strategy & Automation Guides (4)'],\n    ['7','Keyword Clusters & Long-Tail Keywords']\n  ];\n  return tbl(9360,[720,8640],[\n    trow([hCell('#',720),hCell('Section',8640)]),\n    ...rows.map(([n,s],i)=>trow([\n      cell(n,720,i%2?ALT:WHITE,true,BLUE),\n      cell(s,8640,i%2?ALT:WHITE)\n    ]))\n  ]);\n}\n\nfunction blogSummaryTbl(){\n  const items=plan.blog_topics||[];\n  if(!items.length) return '';\n  return tbl(9360,[5040,2160,2160],[\n    trow([hCell('Blog Title',5040),hCell('Keyword',2160),hCell('Pillar',2160)]),\n    ...items.map((b,i)=>trow([\n      cell(b.title||'',5040,i%2?ALT:WHITE),\n      cell(b.primary_keyword||'',2160,i%2?ALT:WHITE,false,BLUE),\n      cell(b.content_pillar||'',2160,i%2?ALT:WHITE,false,MUTED)\n    ]))\n  ]);\n}\n\nfunction kwTbl(){\n  const entries=Object.entries(plan.keyword_clusters||{});\n  if(!entries.length) return '';\n  return tbl(9360,[2400,6960],[\n    trow([hCell('Pillar',2400),hCell('Keywords',6960)]),\n    ...entries.map(([p,t],i)=>trow([\n      cell(p.replace(/_/g,' ').toUpperCase(),2400,LBLUE,true,NAVY),\n      cell(Array.isArray(t)?t.join(', '):'',6960,i%2?ALT:WHITE)\n    ]))\n  ]);\n}\n\nfunction ltkTbl(){\n  const ltk=plan.long_tail_keywords||[];\n  if(!ltk.length) return '';\n  return tbl(9360,[720,8640],[\n    trow([hCell('#',720),hCell('Keyword',8640)]),\n    ...ltk.map((k,i)=>trow([\n      cell(String(i+1),720,i%2?ALT:WHITE,true,BLUE),\n      cell(k,8640,i%2?ALT:WHITE)\n    ]))\n  ]);\n}\n\nlet gNumId=2;\n\nfunction parseMdTable(lines, startIdx){\n  const tableLines=[];\n  let i=startIdx;\n  while(i<lines.length && lines[i].trim().startsWith('|')){\n    tableLines.push(lines[i].trim());\n    i++;\n  }\n  if(tableLines.length<2) return {xml:'',endIdx:startIdx+1};\n\n  const headerCells=tableLines[0].split('|').map(c=>c.trim()).filter(c=>c.length>0);\n  const dataRows=[];\n  for(let r=2;r<tableLines.length;r++){\n    const cells=tableLines[r].split('|').map(c=>c.trim()).filter(c=>c.length>0);\n    if(cells.length>0) dataRows.push(cells);\n  }\n\n  const numCols=headerCells.length;\n  const colW=Math.floor(9360/numCols);\n  const cols=Array(numCols).fill(colW);\n  cols[numCols-1]=9360-colW*(numCols-1);\n\n  const grid=cols.map(w=>`<w:gridCol w:w=\"${w}\"/>`).join('');\n  const hdrRow=trow(headerCells.map((c,ci)=>hCell(c.replace(/\\*\\*(.+?)\\*\\*/g,'$1'),cols[ci])));\n  const dataRowsXml=dataRows.map((row,ri)=>\n    trow(cols.map((_,ci)=>{\n      const txt=(row[ci]||'').replace(/\\*\\*(.+?)\\*\\*/g,'$1').replace(/^:?-+:?$/,'');\n      return cell(txt,cols[ci],ri%2?ALT:WHITE);\n    }))\n  );\n  const xml=`<w:tbl><w:tblPr><w:tblW w:w=\"9360\" w:type=\"dxa\"/><w:tblLayout w:type=\"fixed\"/><w:tblCellMar><w:top w:w=\"0\" w:type=\"dxa\"/><w:bottom w:w=\"0\" w:type=\"dxa\"/></w:tblCellMar></w:tblPr><w:tblGrid>${grid}</w:tblGrid>${hdrRow}${dataRowsXml.join('')}</w:tbl>`;\n  return {xml, endIdx:i};\n}\n\nfunction renderContent(text){\n  if(!text) return spacerP();\n  const out=[];\n  const lines=text.split('\\n');\n  let i=0;\n  let prevWasNum=false;\n  while(i<lines.length){\n    const line=lines[i];\n    const t=line.trim();\n\n    if(t.startsWith('|') && t.endsWith('|') && t.length>2){\n      const result=parseMdTable(lines,i);\n      if(result.xml){ out.push(spacerP(),result.xml,spacerP()); i=result.endIdx; continue; }\n    }\n    i++;\n\n    if(!t||/^[=\u2500\\-]{10,}$/.test(t)){ continue; }\n    if(/^\\d+\\.\\s+[A-Z][A-Z\\s&]+$/.test(t)){ continue; }\n    if(/^[{\\[\\]},]/.test(t)){ continue; }\n    if(/^\"[a-z_]+\"\\s*:/.test(t)){ continue; }\n    if(/^\"[^\"]+\",?$/.test(t) && !t.includes(' \\u2014 ') && !t.includes(': ')){ continue; }\n    if(/^\\|[-:\\s|]+\\|$/.test(t)){ continue; }\n    if(/^[+\\-]{4,}/.test(t)){ continue; }\n    if(/^`{3}/.test(t)){ continue; }\n    if(/^[\\s|^v<>+\\-]+$/.test(t) && /[|^v<>+]/.test(t) && !t.includes(':')){ continue; }\n\n    if(t.startsWith('#### ')){ out.push(h4(t.slice(5))); continue; }\n    if(t.startsWith('### ')){ out.push(h3(t.slice(4))); continue; }\n    if(t.startsWith('## ')){ out.push(h2(t.slice(3))); continue; }\n\n    if(/^--- (ARTICLE|POST|EMAIL|GUIDE) BREAK ---$/i.test(t)){ out.push(dividerP()); continue; }\n    if(/^(ARTICLE|POST|SOCIAL|EMAIL|GUIDE)\\s+\\d+/i.test(t)){\n      out.push(h2(t)); prevWasNum=false;\n      continue;\n    }\n\n    if(t.startsWith('Meta description:') || t.startsWith('SEO Title:')){ out.push(mutedP(t)); continue; }\n\n    if(t==='Introduction' || t==='Introduction:'){\n      out.push(para(run('Introduction',{bold:true,color:BLUE,size:22}),{spaceBefore:120,spaceAfter:40}));\n      continue;\n    }\n    if(t==='Key Takeaways' || t==='Key Takeaways:'){\n      out.push(para(run('Key Takeaways',{bold:true,color:NAVY,size:22}),{spaceBefore:160,spaceAfter:60,borderBottom:LBLUE}));\n      continue;\n    }\n    if(t.startsWith('Executive Summary:') || t==='Executive Summary'){\n      out.push(para(run('Executive Summary',{bold:true,color:NAVY,size:22}),{spaceBefore:160,spaceAfter:60,borderBottom:LBLUE}));\n      continue;\n    }\n    if(/^(Subject|Preview Text|Preview text):/.test(t)){\n      const ci=t.indexOf(':');\n      out.push(labelValueP(t.slice(0,ci),t.slice(ci+1).trim()));\n      continue;\n    }\n    if(t.startsWith('Actionable Takeaway:')){\n      out.push(takeawayP(t.slice(20).trim()));\n      continue;\n    }\n    if(t.startsWith('Quick Tip:')){\n      out.push(`<w:p><w:pPr><w:spacing w:before=\"80\" w:after=\"80\"/><w:shd w:val=\"clear\" w:color=\"auto\" w:fill=\"${LBLUE}\"/></w:pPr>${run('Quick Tip: ',{bold:true,color:NAVY,size:20})}${run(t.slice(10).trim(),{color:CHARCOAL,size:20})}</w:p>`);\n      continue;\n    }\n    if(t.startsWith('How [Your Brand] Can Help') || t.startsWith('How [Your Company Name] Can Help:')){\n      out.push(para(run('How [Your Brand] Can Help',{bold:true,color:NAVY,size:22}),{spaceBefore:160,spaceAfter:60,borderBottom:BLUE}));\n      continue;\n    }\n    if(t.startsWith('Recommended Next Steps') || t.startsWith('Recommended Next Steps:')){\n      out.push(para(run('Recommended Next Steps',{bold:true,color:NAVY,size:22}),{spaceBefore:160,spaceAfter:60,borderBottom:BLUE}));\n      continue;\n    }\n\n    if(/^\\d+[\\.\\)]\\s/.test(t)){\n      if(!prevWasNum){ gNumId++; if(gNumId>51) gNumId=3; }\n      prevWasNum=true;\n      out.push(numP(t.replace(/^\\d+[\\.\\)]\\s+/,'').replace(/\\*\\*(.+?)\\*\\*/g,'$1'), gNumId));\n      continue;\n    }\n    if(/^[\\*\\-\\u2022]\\s/.test(t)){ out.push(bulletP(t.slice(2).replace(/\\*\\*(.+?)\\*\\*/g,'$1'))); continue; }\n\n    if(t.startsWith('#') && t.includes(' ') && !t.startsWith('##')){\n      out.push(para(run(t,{color:BLUE,size:20,italic:true}),{spaceBefore:40,spaceAfter:80}));\n      continue;\n    }\n\n    if(/^(Sincerely|Best regards),?$/.test(t)){\n      out.push(para(run(t,{color:MUTED,size:22,italic:true}),{spaceBefore:80,spaceAfter:20}));\n      continue;\n    }\n    if(t==='The [Your Brand] Team'){\n      out.push(para(run(t,{bold:true,color:NAVY,size:22}),{spaceBefore:0,spaceAfter:80}));\n      continue;\n    }\n\n    prevWasNum=false; out.push(bodyP(t.replace(/\\*\\*(.+?)\\*\\*/g,'$1')));\n  }\n  return out.join('');\n}\n\nfunction getSection(text, num){\n  const parts = text.split(/\\n+={10,}\\n+/);\n  for(const part of parts){\n    if(part.trim().split('\\n')[0].trim().match(new RegExp('^'+num+'\\\\.\\\\s'))){\n      let body = part.trim()\n        .replace(/^[^\\n]+\\n+[-\u2500]{5,}[^\\n]*\\n+/, '')\n        .trim();\n      if(body.startsWith('{') || body.startsWith('\"')){\n        body = body.replace(/^[\\s\\S]*?\\}\\s*\\n/, '').trim();\n      }\n      return body;\n    }\n  }\n  return '';\n}\n\nfunction getStrategy(text){\n  const parts = text.split(/\\n+={10,}\\n+/);\n  for(const part of parts){\n    if(part.trim().split('\\n')[0].trim().startsWith('1. MONTHLY')){\n      let body = part.trim()\n        .replace(/^[^\\n]+\\n+[-\u2500]{5,}[^\\n]*\\n+/, '')\n        .trim();\n      body = body.replace(/^[\\s\\S]*?\\}\\s*\\n/, '').trim();\n      return body;\n    }\n  }\n  return '';\n}\n\nfunction linkedinSummaryTbl(){\n  const posts=plan.linkedin_posts||[];\n  if(!posts.length) return '';\n  return tbl(9360,[3120,4680,1560],[\n    trow([hCell('Topic',3120),hCell('Hook Preview',4680),hCell('Pillar',1560)]),\n    ...posts.map((p,i)=>{\n      const hook=p.hook||'';\n      return trow([\n        cell(p.topic||'',3120,i%2?ALT:WHITE),\n        cell(hook,4680,i%2?ALT:WHITE,false,BLUE),\n        cell((p.content_pillar||'').replace(' & Fluency','').replace(' Systems',''),1560,i%2?ALT:WHITE,false,MUTED)\n      ]);\n    })\n  ]);\n}\nfunction socialSummaryTbl(){\n  const posts=plan.social_posts||[];\n  if(!posts.length) return '';\n  return tbl(9360,[7800,1560],[\n    trow([hCell('Topic',7800),hCell('Format',1560)]),\n    ...posts.map((p,i)=>trow([\n      cell(p.topic||'',7800,i%2?ALT:WHITE),\n      cell(p.format||'',1560,i%2?ALT:WHITE,false,BLUE)\n    ]))\n  ]);\n}\nfunction emailSummaryTbl(){\n  const emails=plan.email_topics||[];\n  if(!emails.length) return '';\n  return tbl(9360,[7200,2160],[\n    trow([hCell('Subject Line',7200),hCell('Pillar',2160)]),\n    ...emails.map((e,i)=>trow([\n      cell(e.subject||'',7200,i%2?ALT:WHITE),\n      cell((e.content_pillar||'').replace(' & Fluency','').replace(' Systems',''),2160,i%2?ALT:WHITE,false,BLUE)\n    ]))\n  ]);\n}\nfunction guidesSummaryTbl(){\n  const guides=plan.guides||[];\n  if(!guides.length) return '';\n  return tbl(9360,[7200,2160],[\n    trow([hCell('Guide Title',7200),hCell('Pillar',2160)]),\n    ...guides.map((g,i)=>trow([\n      cell(g.title||'',7200,i%2?ALT:WHITE),\n      cell((g.content_pillar||'').replace(' & Fluency','').replace(' Systems',''),2160,i%2?ALT:WHITE,false,BLUE)\n    ]))\n  ]);\n}\n\nconst bodyXml=[\n  cover(),\n  h1('Table of Contents'), tocTbl(), dividerP(),\n  h1('1. Monthly Content Strategy Overview'),\n  `<w:p><w:pPr><w:spacing w:before=\"80\" w:after=\"80\"/><w:shd w:val=\"clear\" w:color=\"auto\" w:fill=\"${LBLUE}\"/></w:pPr>${run('Strategy Overview',{bold:true,color:NAVY,size:22})}</w:p>`,\n  bodyP(plan.strategy_overview||''),\n  spacerP(),\n  dividerP(),\n  h1('2. SEO Blog Articles'),\n  blogSummaryTbl(), dividerP(),\n  renderContent(getSection(assembled,'2')), dividerP(),\n  h1('3. LinkedIn Thought Leadership Posts'),\n  linkedinSummaryTbl(), dividerP(),\n  renderContent(getSection(assembled,'3')), dividerP(),\n  h1('4. Educational Social Media Posts'),\n  socialSummaryTbl(), dividerP(),\n  renderContent(getSection(assembled,'4')), dividerP(),\n  h1('5. Email Newsletter Campaigns'),\n  emailSummaryTbl(), dividerP(),\n  renderContent(getSection(assembled,'5')), dividerP(),\n  h1('6. AI Strategy & Automation Guides'),\n  guidesSummaryTbl(), dividerP(),\n  renderContent(getSection(assembled,'6')), dividerP(),\n  h1('7. Keyword Clusters & Long-Tail Keywords'),\n  h2('Keyword Clusters'), kwTbl(),\n  h2('Long-Tail Keywords'), ltkTbl(),\n].join('');\n\nconst xmlFiles={\n'[Content_Types].xml':'<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><Types xmlns=\"http://schemas.openxmlformats.org/package/2006/content-types\"><Default Extension=\"rels\" ContentType=\"application/vnd.openxmlformats-package.relationships+xml\"/><Default Extension=\"xml\" ContentType=\"application/xml\"/><Override PartName=\"/word/document.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml\"/><Override PartName=\"/word/styles.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml\"/><Override PartName=\"/word/numbering.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml\"/><Override PartName=\"/word/header1.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml\"/><Override PartName=\"/word/footer1.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml\"/></Types>',\n'_rels/.rels':'<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\"><Relationship Id=\"rId1\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument\" Target=\"word/document.xml\"/></Relationships>',\n'word/_rels/document.xml.rels':'<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\"><Relationship Id=\"rId1\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles\" Target=\"styles.xml\"/><Relationship Id=\"rId2\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering\" Target=\"numbering.xml\"/><Relationship Id=\"rId8\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/header\" Target=\"header1.xml\"/><Relationship Id=\"rId9\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer\" Target=\"footer1.xml\"/></Relationships>',\n'word/styles.xml':'<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><w:styles xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\"><w:docDefaults><w:rPrDefault><w:rPr><w:rFonts w:ascii=\"Calibri\" w:hAnsi=\"Calibri\" w:cs=\"Calibri\"/><w:sz w:val=\"22\"/><w:szCs w:val=\"22\"/><w:color w:val=\"444444\"/></w:rPr></w:rPrDefault></w:docDefaults><w:style w:type=\"paragraph\" w:styleId=\"Normal\"><w:name w:val=\"Normal\"/><w:rPr><w:rFonts w:ascii=\"Calibri\" w:hAnsi=\"Calibri\"/><w:sz w:val=\"22\"/></w:rPr></w:style></w:styles>',\n'word/numbering.xml':`<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><w:numbering xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\"><w:abstractNum w:abstractNumId=\"0\"><w:lvl w:ilvl=\"0\"><w:start w:val=\"1\"/><w:numFmt w:val=\"bullet\"/><w:lvlText w:val=\"\u2022\"/><w:lvlJc w:val=\"left\"/><w:pPr><w:ind w:left=\"720\" w:hanging=\"360\"/></w:pPr><w:rPr><w:rFonts w:ascii=\"Symbol\" w:hAnsi=\"Symbol\"/></w:rPr></w:lvl></w:abstractNum><w:abstractNum w:abstractNumId=\"1\"><w:lvl w:ilvl=\"0\"><w:start w:val=\"1\"/><w:numFmt w:val=\"decimal\"/><w:lvlText w:val=\"%1.\"/><w:lvlJc w:val=\"left\"/><w:pPr><w:ind w:left=\"720\" w:hanging=\"360\"/></w:pPr></w:lvl></w:abstractNum><w:num w:numId=\"1\"><w:abstractNumId w:val=\"0\"/></w:num><w:num w:numId=\"2\"><w:abstractNumId w:val=\"1\"/><w:lvlOverride w:ilvl=\"0\"><w:startOverride w:val=\"1\"/></w:lvlOverride></w:num><w:num w:numId=\"3\"><w:abstractNumId w:val=\"1\"/><w:lvlOverride w:ilvl=\"0\"><w:startOverride w:val=\"1\"/></w:lvlOverride></w:num><w:num w:numId=\"4\"><w:abstractNumId w:val=\"1\"/><w:lvlOverride w:ilvl=\"0\"><w:startOverride w:val=\"1\"/></w:lvlOverride></w:num><w:num w:numId=\"5\"><w:abstractNumId w:val=\"1\"/><w:lvlOverride w:ilvl=\"0\"><w:startOverride w:val=\"1\"/></w:lvlOverride></w:num><w:num w:numId=\"6\"><w:abstractNumId w:val=\"1\"/><w:lvlOverride w:ilvl=\"0\"><w:startOverride w:val=\"1\"/></w:lvlOverride></w:num><w:num w:numId=\"7\"><w:abstractNumId w:val=\"1\"/><w:lvlOverride w:ilvl=\"0\"><w:startOverride w:val=\"1\"/></w:lvlOverride></w:num><w:num w:numId=\"8\"><w:abstractNumId w:val=\"1\"/><w:lvlOverride w:ilvl=\"0\"><w:startOverride w:val=\"1\"/></w:lvlOverride></w:num><w:num w:numId=\"9\"><w:abstractNumId w:val=\"1\"/><w:lvlOverride w:ilvl=\"0\"><w:startOverride w:val=\"1\"/></w:lvlOverride></w:num><w:num w:numId=\"10\"><w:abstractNumId w:val=\"1\"/><w:lvlOverride w:ilvl=\"0\"><w:startOverride w:val=\"1\"/></w:lvlOverride></w:num><w:num w:numId=\"11\"><w:abstractNumId w:val=\"1\"/><w:lvlOverride w:ilvl=\"0\"><w:startOverride w:val=\"1\"/></w:lvlOverride></w:num><w:num w:numId=\"12\"><w:abstractNumId w:val=\"1\"/><w:lvlOverride w:ilvl=\"0\"><w:startOverride w:val=\"1\"/></w:lvlOverride></w:num><w:num w:numId=\"13\"><w:abstractNumId w:val=\"1\"/><w:lvlOverride w:ilvl=\"0\"><w:startOverride w:val=\"1\"/></w:lvlOverride></w:num><w:num w:numId=\"14\"><w:abstractNumId w:val=\"1\"/><w:lvlOverride w:ilvl=\"0\"><w:startOverride w:val=\"1\"/></w:lvlOverride></w:num><w:num w:numId=\"15\"><w:abstractNumId w:val=\"1\"/><w:lvlOverride w:ilvl=\"0\"><w:startOverride w:val=\"1\"/></w:lvlOverride></w:num><w:num w:numId=\"16\"><w:abstractNumId w:val=\"1\"/><w:lvlOverride w:ilvl=\"0\"><w:startOverride w:val=\"1\"/></w:lvlOverride></w:num><w:num w:numId=\"17\"><w:abstractNumId w:val=\"1\"/><w:lvlOverride w:ilvl=\"0\"><w:startOverride w:val=\"1\"/></w:lvlOverride></w:num><w:num w:numId=\"18\"><w:abstractNumId w:val=\"1\"/><w:lvlOverride w:ilvl=\"0\"><w:startOverride w:val=\"1\"/></w:lvlOverride></w:num><w:num w:numId=\"19\"><w:abstractNumId w:val=\"1\"/><w:lvlOverride w:ilvl=\"0\"><w:startOverride w:val=\"1\"/></w:lvlOverride></w:num><w:num w:numId=\"20\"><w:abstractNumId w:val=\"1\"/><w:lvlOverride w:ilvl=\"0\"><w:startOverride w:val=\"1\"/></w:lvlOverride></w:num><w:num w:numId=\"21\"><w:abstractNumId w:val=\"1\"/><w:lvlOverride w:ilvl=\"0\"><w:startOverride w:val=\"1\"/></w:lvlOverride></w:num><w:num w:numId=\"22\"><w:abstractNumId w:val=\"1\"/><w:lvlOverride w:ilvl=\"0\"><w:startOverride w:val=\"1\"/></w:lvlOverride></w:num><w:num w:numId=\"23\"><w:abstractNumId w:val=\"1\"/><w:lvlOverride w:ilvl=\"0\"><w:startOverride w:val=\"1\"/></w:lvlOverride></w:num><w:num w:numId=\"24\"><w:abstractNumId w:val=\"1\"/><w:lvlOverride w:ilvl=\"0\"><w:startOverride w:val=\"1\"/></w:lvlOverride></w:num><w:num w:numId=\"25\"><w:abstractNumId w:val=\"1\"/><w:lvlOverride w:ilvl=\"0\"><w:startOverride w:val=\"1\"/></w:lvlOverride></w:num><w:num w:numId=\"26\"><w:abstractNumId w:val=\"1\"/><w:lvlOverride w:ilvl=\"0\"><w:startOverride w:val=\"1\"/></w:lvlOverride></w:num><w:num w:numId=\"27\"><w:abstractNumId w:val=\"1\"/><w:lvlOverride w:ilvl=\"0\"><w:startOverride w:val=\"1\"/></w:lvlOverride></w:num><w:num w:numId=\"28\"><w:abstractNumId w:val=\"1\"/><w:lvlOverride w:ilvl=\"0\"><w:startOverride w:val=\"1\"/></w:lvlOverride></w:num><w:num w:numId=\"29\"><w:abstractNumId w:val=\"1\"/><w:lvlOverride w:ilvl=\"0\"><w:startOverride w:val=\"1\"/></w:lvlOverride></w:num><w:num w:numId=\"30\"><w:abstractNumId w:val=\"1\"/><w:lvlOverride w:ilvl=\"0\"><w:startOverride w:val=\"1\"/></w:lvlOverride></w:num><w:num w:numId=\"31\"><w:abstractNumId w:val=\"1\"/><w:lvlOverride w:ilvl=\"0\"><w:startOverride w:val=\"1\"/></w:lvlOverride></w:num><w:num w:numId=\"32\"><w:abstractNumId w:val=\"1\"/><w:lvlOverride w:ilvl=\"0\"><w:startOverride w:val=\"1\"/></w:lvlOverride></w:num><w:num w:numId=\"33\"><w:abstractNumId w:val=\"1\"/><w:lvlOverride w:ilvl=\"0\"><w:startOverride w:val=\"1\"/></w:lvlOverride></w:num><w:num w:numId=\"34\"><w:abstractNumId w:val=\"1\"/><w:lvlOverride w:ilvl=\"0\"><w:startOverride w:val=\"1\"/></w:lvlOverride></w:num><w:num w:numId=\"35\"><w:abstractNumId w:val=\"1\"/><w:lvlOverride w:ilvl=\"0\"><w:startOverride w:val=\"1\"/></w:lvlOverride></w:num><w:num w:numId=\"36\"><w:abstractNumId w:val=\"1\"/><w:lvlOverride w:ilvl=\"0\"><w:startOverride w:val=\"1\"/></w:lvlOverride></w:num><w:num w:numId=\"37\"><w:abstractNumId w:val=\"1\"/><w:lvlOverride w:ilvl=\"0\"><w:startOverride w:val=\"1\"/></w:lvlOverride></w:num><w:num w:numId=\"38\"><w:abstractNumId w:val=\"1\"/><w:lvlOverride w:ilvl=\"0\"><w:startOverride w:val=\"1\"/></w:lvlOverride></w:num><w:num w:numId=\"39\"><w:abstractNumId w:val=\"1\"/><w:lvlOverride w:ilvl=\"0\"><w:startOverride w:val=\"1\"/></w:lvlOverride></w:num><w:num w:numId=\"40\"><w:abstractNumId w:val=\"1\"/><w:lvlOverride w:ilvl=\"0\"><w:startOverride w:val=\"1\"/></w:lvlOverride></w:num><w:num w:numId=\"41\"><w:abstractNumId w:val=\"1\"/><w:lvlOverride w:ilvl=\"0\"><w:startOverride w:val=\"1\"/></w:lvlOverride></w:num><w:num w:numId=\"42\"><w:abstractNumId w:val=\"1\"/><w:lvlOverride w:ilvl=\"0\"><w:startOverride w:val=\"1\"/></w:lvlOverride></w:num><w:num w:numId=\"43\"><w:abstractNumId w:val=\"1\"/><w:lvlOverride w:ilvl=\"0\"><w:startOverride w:val=\"1\"/></w:lvlOverride></w:num><w:num w:numId=\"44\"><w:abstractNumId w:val=\"1\"/><w:lvlOverride w:ilvl=\"0\"><w:startOverride w:val=\"1\"/></w:lvlOverride></w:num><w:num w:numId=\"45\"><w:abstractNumId w:val=\"1\"/><w:lvlOverride w:ilvl=\"0\"><w:startOverride w:val=\"1\"/></w:lvlOverride></w:num><w:num w:numId=\"46\"><w:abstractNumId w:val=\"1\"/><w:lvlOverride w:ilvl=\"0\"><w:startOverride w:val=\"1\"/></w:lvlOverride></w:num><w:num w:numId=\"47\"><w:abstractNumId w:val=\"1\"/><w:lvlOverride w:ilvl=\"0\"><w:startOverride w:val=\"1\"/></w:lvlOverride></w:num><w:num w:numId=\"48\"><w:abstractNumId w:val=\"1\"/><w:lvlOverride w:ilvl=\"0\"><w:startOverride w:val=\"1\"/></w:lvlOverride></w:num><w:num w:numId=\"49\"><w:abstractNumId w:val=\"1\"/><w:lvlOverride w:ilvl=\"0\"><w:startOverride w:val=\"1\"/></w:lvlOverride></w:num><w:num w:numId=\"50\"><w:abstractNumId w:val=\"1\"/><w:lvlOverride w:ilvl=\"0\"><w:startOverride w:val=\"1\"/></w:lvlOverride></w:num><w:num w:numId=\"51\"><w:abstractNumId w:val=\"1\"/><w:lvlOverride w:ilvl=\"0\"><w:startOverride w:val=\"1\"/></w:lvlOverride></w:num></w:numbering>`,\n'[Content_Types].xml':'<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><Types xmlns=\"http://schemas.openxmlformats.org/package/2006/content-types\"><Default Extension=\"rels\" ContentType=\"application/vnd.openxmlformats-package.relationships+xml\"/><Default Extension=\"xml\" ContentType=\"application/xml\"/><Override PartName=\"/word/document.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml\"/><Override PartName=\"/word/styles.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml\"/><Override PartName=\"/word/numbering.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml\"/><Override PartName=\"/word/header1.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml\"/><Override PartName=\"/word/footer1.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml\"/></Types>',\n'_rels/.rels':'<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\"><Relationship Id=\"rId1\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument\" Target=\"word/document.xml\"/></Relationships>',\n'word/_rels/document.xml.rels':'<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\"><Relationship Id=\"rId1\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles\" Target=\"styles.xml\"/><Relationship Id=\"rId2\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering\" Target=\"numbering.xml\"/><Relationship Id=\"rId8\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/header\" Target=\"header1.xml\"/><Relationship Id=\"rId9\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer\" Target=\"footer1.xml\"/></Relationships>',\n'word/styles.xml':'<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><w:styles xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\"><w:docDefaults><w:rPrDefault><w:rPr><w:rFonts w:ascii=\"Calibri\" w:hAnsi=\"Calibri\" w:cs=\"Calibri\"/><w:sz w:val=\"22\"/><w:szCs w:val=\"22\"/><w:color w:val=\"444444\"/></w:rPr></w:rPrDefault></w:docDefaults><w:style w:type=\"paragraph\" w:styleId=\"Normal\"><w:name w:val=\"Normal\"/><w:rPr><w:rFonts w:ascii=\"Calibri\" w:hAnsi=\"Calibri\"/><w:sz w:val=\"22\"/></w:rPr></w:style></w:styles>',\n'word/header1.xml':'<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><w:hdr xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\"><w:p><w:pPr><w:pBdr><w:bottom w:val=\"single\" w:sz=\"4\" w:space=\"4\" w:color=\"2E75B6\"/></w:pBdr><w:spacing w:before=\"0\" w:after=\"80\"/></w:pPr><w:r><w:rPr><w:b/><w:color w:val=\"1E3A5F\"/><w:sz w:val=\"18\"/><w:rFonts w:ascii=\"Calibri\" w:hAnsi=\"Calibri\"/></w:rPr><w:t xml:space=\"preserve\">[Your Company Name]  |  AI Content Pipeline  |  </w:t></w:r><w:r><w:rPr><w:color w:val=\"777777\"/><w:sz w:val=\"18\"/><w:rFonts w:ascii=\"Calibri\" w:hAnsi=\"Calibri\"/></w:rPr><w:t>'+esc(runDate)+'</w:t></w:r></w:p></w:hdr>',\n'word/footer1.xml':`<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><w:ftr xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\"><w:p><w:pPr><w:jc w:val=\"center\"/><w:pBdr><w:top w:val=\"single\" w:sz=\"4\" w:space=\"4\" w:color=\"2E75B6\"/></w:pBdr></w:pPr><w:r><w:rPr><w:color w:val=\"777777\"/><w:sz w:val=\"18\"/><w:rFonts w:ascii=\"Calibri\" w:hAnsi=\"Calibri\"/></w:rPr><w:t xml:space=\"preserve\">Confidential \\u2014 [Your Company Name]  |  Page </w:t></w:r><w:r><w:rPr><w:color w:val=\"777777\"/><w:sz w:val=\"18\"/></w:rPr><w:fldChar w:fldCharType=\"begin\"/></w:r><w:r><w:rPr><w:color w:val=\"777777\"/><w:sz w:val=\"18\"/></w:rPr><w:instrText> PAGE </w:instrText></w:r><w:r><w:rPr><w:color w:val=\"777777\"/><w:sz w:val=\"18\"/></w:rPr><w:fldChar w:fldCharType=\"end\"/></w:r></w:p></w:ftr>`,\n'word/document.xml':`<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><w:document xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\" xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\"><w:body>${bodyXml}<w:sectPr><w:headerReference w:type=\"default\" r:id=\"rId8\"/><w:footerReference w:type=\"default\" r:id=\"rId9\"/><w:pgSz w:w=\"12240\" w:h=\"15840\"/><w:pgMar w:top=\"1440\" w:right=\"1440\" w:bottom=\"1440\" w:left=\"1440\" w:header=\"720\" w:footer=\"720\" w:gutter=\"0\"/></w:sectPr></w:body></w:document>`\n};\n\nfunction strToBytes(str){\n  const out=[];\n  for(let i=0;i<str.length;i++){\n    let c=str.charCodeAt(i);\n    if(c>=0xD800 && c<=0xDBFF){\n      const hi=c, lo=str.charCodeAt(i+1);\n      if(lo>=0xDC00 && lo<=0xDFFF){\n        c=0x10000+((hi-0xD800)<<10)+(lo-0xDC00);\n        i++; \n      }\n    }\n    if(c<0x80){             out.push(c); }\n    else if(c<0x800){       out.push(0xC0|(c>>6),  0x80|(c&0x3F)); }\n    else if(c<0x10000){     out.push(0xE0|(c>>12), 0x80|((c>>6)&0x3F), 0x80|(c&0x3F)); }\n    else{                   out.push(0xF0|(c>>18), 0x80|((c>>12)&0x3F), 0x80|((c>>6)&0x3F), 0x80|(c&0x3F)); }\n  }\n  return out;\n}\n\nfunction crc32(bytes){\n  const t=[];\n  for(let i=0;i<256;i++){let x=i;for(let j=0;j<8;j++)x=(x&1)?(0xEDB88320^(x>>>1)):(x>>>1);t[i]=x;}\n  let c=0xFFFFFFFF;\n  for(let i=0;i<bytes.length;i++) c=t[(c^bytes[i])&0xFF]^(c>>>8);\n  return(c^0xFFFFFFFF)>>>0;\n}\n\nconst u16 = n => [n&0xFF,(n>>8)&0xFF];\nconst u32 = n => [n&0xFF,(n>>8)&0xFF,(n>>16)&0xFF,(n>>24)&0xFF];\n\nfunction buildZip(fileMap){\n  const entries=Object.entries(fileMap);\n  const locals=[],central=[];\n  let offset=0;\n  for(const[name,content] of entries){\n    const nb=strToBytes(name), d=strToBytes(content), crc=crc32(d), sz=d.length;\n    const loc=[0x50,0x4B,0x03,0x04,...u16(20),...u16(0),...u16(0),...u16(0),...u16(0),...u32(crc),...u32(sz),...u32(sz),...u16(nb.length),...u16(0),...nb,...d];\n    central.push([0x50,0x4B,0x01,0x02,...u16(20),...u16(20),...u16(0),...u16(0),...u16(0),...u16(0),...u32(crc),...u32(sz),...u32(sz),...u16(nb.length),...u16(0),...u16(0),...u16(0),...u16(0),...u32(0),...u32(offset),...nb]);\n    locals.push(loc);\n    offset+=loc.length;\n  }\n  const cf=central.flat();\n  const eocd=[0x50,0x4B,0x05,0x06,...u16(0),...u16(0),...u16(entries.length),...u16(entries.length),...u32(cf.length),...u32(offset),...u16(0)];\n  const all=[...locals.flat(),...cf,...eocd];\n\n  const B64='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';\n  let b64='';\n  const len=all.length;\n  for(let i=0;i<len;i+=3){\n    const b0=all[i], b1=i+1<len?all[i+1]:0, b2=i+2<len?all[i+2]:0;\n    b64+=B64[b0>>2]+B64[((b0&3)<<4)|(b1>>4)]+B64[((b1&15)<<2)|(b2>>6)]+B64[b2&63];\n  }\n  const pad=len%3;\n  if(pad===1)      b64=b64.slice(0,-2)+'==';\n  else if(pad===2) b64=b64.slice(0,-1)+'=';\n  return b64;\n}\n\nconst base64Zip = buildZip(xmlFiles);\nconst fileName  = 'Content_Package_'+runDate.replace(/\\s/g,'_')+'.docx';\n\nreturn [{\n  json:   { doc_title:docTitle, run_date:runDate, file_name:fileName, warnings:inp.warnings||[] },\n  binary: { data:{ data:base64Zip, mimeType:'application/vnd.openxmlformats-officedocument.wordprocessingml.document', fileName }}\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "115a969b-9927-4db9-bfe4-0ff1e4125ef0",
      "name": "Upload to Drive",
      "type": "n8n-nodes-base.googleDrive",
      "onError": "continueErrorOutput",
      "position": [
        4352,
        4816
      ],
      "parameters": {
        "name": "={{ $json.file_name }}",
        "driveId": {
          "__rl": true,
          "mode": "list",
          "value": "My Drive"
        },
        "options": {},
        "folderId": {
          "__rl": true,
          "mode": "list",
          "value": "root",
          "cachedResultUrl": "https://drive.google.com/drive",
          "cachedResultName": "/ (Root folder)"
        }
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "a2ecf1f7-26ac-4212-b8e2-3adc3037f10e",
      "name": "Search Drive for DOCX",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        3040,
        5552
      ],
      "parameters": {
        "filter": {
          "driveId": {
            "mode": "list",
            "value": "My Drive"
          },
          "folderId": {
            "__rl": true,
            "mode": "list",
            "value": "root",
            "cachedResultUrl": "https://drive.google.com/drive",
            "cachedResultName": "/ (Root folder)"
          },
          "whatToSearch": "files"
        },
        "options": {},
        "resource": "fileFolder",
        "queryString": "=Content_Package_{{ $now.toFormat('MMMM_yyyy') }}.docx"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "0958ccaa-e9de-4001-8492-df16f5144fa8",
      "name": "Has DOCX Files?",
      "type": "n8n-nodes-base.if",
      "position": [
        3248,
        5552
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "cond_003",
              "operator": {
                "type": "number",
                "operation": "gt"
              },
              "leftValue": "={{ $input.all().length }}",
              "rightValue": 0
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "05665204-45ce-484a-8313-84acdf4b20f3",
      "name": "Download DOCX",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        3488,
        5424
      ],
      "parameters": {
        "fileId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $json.id }}"
        },
        "options": {},
        "operation": "download"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "83a740db-1340-499d-93f6-7b7599fed632",
      "name": "Prepare DOCX Archive",
      "type": "n8n-nodes-base.code",
      "position": [
        3680,
        5424
      ],
      "parameters": {
        "jsCode": "const item = $input.item;\nconst binaryPropertyName = 'data';\nif (item.binary && item.binary[binaryPropertyName]) {\n  item.binary[binaryPropertyName].fileName = item.binary[binaryPropertyName].fileName.replace(/\\.docx$/i, '.zip');\n  item.binary[binaryPropertyName].fileExtension = 'zip';\n  item.binary[binaryPropertyName].mimeType = 'application/zip';\n}\nreturn item;"
      },
      "typeVersion": 2
    },
    {
      "id": "8a10e0b9-d580-410c-ae1f-34488d22fc2f",
      "name": "Unzip DOCX",
      "type": "n8n-nodes-base.compression",
      "position": [
        3888,
        5424
      ],
      "parameters": {},
      "typeVersion": 1.1
    },
    {
      "id": "5d4a1722-c109-4419-a1ce-fa8f1ae21080",
      "name": "Extract XML Text",
      "type": "n8n-nodes-base.code",
      "position": [
        4112,
        5424
      ],
      "parameters": {
        "jsCode": "const returnItems = [];\nconst items = $input.all();\nfor (let i = 0; i < items.length; i++) {\n  const item = items[i];\n  let extractedText = '';\n  const originalFileName = item.json.name || `File_${i + 1}`;\n  if (item.binary) {\n    const binaryKeys = Object.keys(item.binary);\n    let targetKey = null;\n    for (const key of binaryKeys) {\n      if (item.binary[key].fileName === 'document.xml') {\n        targetKey = key;\n        break;\n      }\n    }\n    if (targetKey) {\n      try {\n        const buffer = await this.helpers.getBinaryDataBuffer(i, targetKey);\n        const xmlString = buffer.toString('utf8');\n        extractedText = xmlString\n          .replace(/<w:p[ >]/g, '\\n<w:p ')\n          .replace(/<[^>]+>/g, '')\n          .replace(/&amp;/g, '&')\n          .replace(/&lt;/g, '<')\n          .replace(/&gt;/g, '>')\n          .replace(/&quot;/g, '\"')\n          .replace(/&apos;/g, \"'\")\n          .replace(/\\n{3,}/g, '\\n\\n')\n          .trim();\n      } catch (error) {\n        extractedText = '[Error reading file buffer: ' + error.message + ']';\n      }\n    }\n  }\n  returnItems.push({\n    json: {\n      text: extractedText,\n      fileName: originalFileName,\n      charCount: extractedText.length\n    }\n  });\n}\nreturn returnItems;"
      },
      "typeVersion": 2
    },
    {
      "id": "b5464c15-ce57-4ea7-83a7-f08b9e5231ae",
      "name": "Process Blog Articles",
      "type": "n8n-nodes-base.code",
      "position": [
        4368,
        5424
      ],
      "parameters": {
        "jsCode": "const returnItems = [];\nconst items = $input.all();\nconst now = new Date();\nconst convertToHtml = (text) => {\n  const lines = text.split('\\n');\n  let html = '';\n  for (let i = 0; i < lines.length; i++) {\n    const line = lines[i].trim();\n    if (!line) continue;\n    if (/^(Step\\s+\\d+|What|How|Why|When)/i.test(line) || line.endsWith('?')) {\n      html += `<h3>${line}</h3>\\n`;\n    } else {\n      html += `<p>${line}</p>\\n`;\n    }\n  }\n  return html.trim();\n};\nlet articleIndex = 0;\n\nconst MIN_BUFFER_SECONDS = 15 * 60; // 15 min safety margin\nconst MAX_SCHEDULE_SECONDS = 74 * 24 * 60 * 60; // <75 days\nconst nowTs = Math.floor(Date.now() / 1000);\nconst clampTs = (ts) => Math.min(\n  Math.max(ts, nowTs + MIN_BUFFER_SECONDS),\n  nowTs + MAX_SCHEDULE_SECONDS\n);\n\nfor (const item of items) {\n  const chunks = item.json.text.split(/(?=ARTICLE\\s+\\d+\\s*:)/i);\n  for (const chunk of chunks) {\n    const block = chunk.trim();\n    const articleMatch = block.match(/^ARTICLE\\s+(\\d+)\\s*:\\s*(.+)/i);\n    if (articleMatch) {\n      const articleTitle = articleMatch[2].split('\\n')[0].trim();\n      const scheduledDate = new Date(now.getFullYear(), now.getMonth(), 2 + (articleIndex * 5), 9, 0, 0);\n      returnItems.push({\n        json: {\n          title: articleTitle,\n          bodyHtml: convertToHtml(block),\n          scheduledDate: scheduledDate.toISOString(),\n          scheduledTimestamp: clampTs(Math.floor(scheduledDate.getTime() / 1000))\n        }\n      });\n      articleIndex++;\n    }\n  }\n}\nreturn returnItems;"
      },
      "typeVersion": 2
    },
    {
      "id": "f405f814-b79f-4cb1-88d7-ac3e8b58df6a",
      "name": "Upload to WP Media",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        5104,
        5424
      ],
      "parameters": {
        "url": "={{ $('Config: Pipeline C').item.json.wordpress_domain }}/wp-json/wp/v2/media",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "contentType": "binaryData",
        "jsonHeaders": "={ \"Content-Disposition\": \"attachment; filename=\\\"{{ $binary.data.fileName }}\\\"\", \"Content-Type\": \"{{ $binary.data.mimeType }}\" }",
        "sendHeaders": true,
        "authentication": "genericCredentialType",
        "specifyHeaders": "json",
        "genericAuthType": "httpBasicAuth",
        "inputDataFieldName": "data"
      },
      "credentials": {
        "httpBasicAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "a9f2041b-ab5c-4c20-a703-51b08981b838",
      "name": "Publish Blog Post",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueRegularOutput",
      "position": [
        5360,
        5424
      ],
      "parameters": {
        "url": "={{ $('Config: Pipeline C').item.json.wordpress_domain }}/wp-json/wp/v2/posts",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "authentication": "genericCredentialType",
        "bodyParameters": {
          "parameters": [
            {
              "name": "featured_media",
              "value": "={{ $json.id }}"
            },
            {
              "name": "title",
              "value": "={{ $('Process Blog Articles').item.json.title }}"
            },
            {
              "name": "content",
              "value": "={{ $('Process Blog Articles').item.json.bodyHtml }}"
            },
            {
              "name": "status",
              "value": "future"
            },
            {
              "name": "date",
              "value": "={{ $('Process Blog Articles').item.json.scheduledDate }}"
            }
          ]
        },
        "genericAuthType": "httpBasicAuth"
      },
      "credentials": {
        "httpBasicAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "260a03c8-17fc-42f1-b1a9-413cb216ebca",
      "name": "Process LinkedIn Posts",
      "type": "n8n-nodes-base.code",
      "position": [
        4368,
        5616
      ],
      "parameters": {
        "jsCode": "const text = $input.first().json.text;\nconst linkedInPosts = [];\nconst now = new Date();\nconst linkedInRegex = /POST \\d+:\\n(.*?)\\n([\\s\\S]*?)(?=\\nPOST \\d+:|\\n\\d+\\.\\s|(\\n)?$)/g;\nlet match; let postIndex = 0;\n\nconst MIN_BUFFER_SECONDS = 15 * 60; // 15 min safety margin\nconst MAX_SCHEDULE_SECONDS = 74 * 24 * 60 * 60; // <75 days\nconst nowTs = Math.floor(Date.now() / 1000);\nconst clampTs = (ts) => Math.min(\n  Math.max(ts, nowTs + MIN_BUFFER_SECONDS),\n  nowTs + MAX_SCHEDULE_SECONDS\n);\n\nwhile ((match = linkedInRegex.exec(text)) !== null) {\n  const topic = match[1].trim();\n  const content = match[2].trim();\n  if (topic && content) {\n    const scheduledDate = new Date(now.getFullYear(), now.getMonth(), 2 + (postIndex * 5), 10, 0, 0);\n    linkedInPosts.push({ json: { topic, content, scheduledDate: scheduledDate.toISOString(), scheduledTimestamp: clampTs(Math.floor(scheduledDate.getTime() / 1000)) } });\n    postIndex++;\n  }\n}\nreturn linkedInPosts;"
      },
      "typeVersion": 2
    },
    {
      "id": "fa43af84-aff0-40f4-a1a4-9468647f7cd1",
      "name": "Post to LinkedIn",
      "type": "n8n-nodes-base.linkedIn",
      "position": [
        5104,
        5616
      ],
      "parameters": {
        "text": "={{ $('Process LinkedIn Posts').item.json.content }}",
        "person": "={{ $('Get LinkedIn User Info').item.json.sub}}",
        "additionalFields": {},
        "shareMediaCategory": "IMAGE"
      },
      "credentials": {
        "linkedInOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "8ce9e6d6-43b7-41c5-9185-a066d499f71f",
      "name": "Process Social Posts",
      "type": "n8n-nodes-base.code",
      "position": [
        4368,
        5824
      ],
      "parameters": {
        "jsCode": "const text = $input.first().json.text;\nconst educationalPosts = [];\nconst socialRegex = /SOCIAL \\d+:\\s*(.*?)\\n([\\s\\S]*?)(?=\\nSOCIAL \\d+:|\\n5\\. Email|(\\n)?$)/g;\nlet match;\nconst now = new Date();\nlet postIndex = 0;\n\nconst MIN_BUFFER_SECONDS = 15 * 60; // 15 min safety margin\nconst MAX_SCHEDULE_SECONDS = 74 * 24 * 60 * 60; // <75 days\nconst nowTs = Math.floor(Date.now() / 1000);\nconst clampTs = (ts) => Math.min(\n  Math.max(ts, nowTs + MIN_BUFFER_SECONDS),\n  nowTs + MAX_SCHEDULE_SECONDS\n);\n\nwhile ((match = socialRegex.exec(text)) !== null) {\n  const type = match[1].trim();\n  let content = match[2].trim();\n  if (type && content) {\n      const scheduledDate = new Date(now.getFullYear(),now.getMonth(), 2 + (postIndex * 5), 10, 0, 0);\n    educationalPosts.push({\n      json: {\n        type: type,\n        content: content,\n        scheduledDate: scheduledDate.toISOString(),\n        scheduledTimestamp: clampTs(Math.floor(scheduledDate.getTime() / 1000))\n      }\n    });\n    postIndex++;\n  }\n}\nreturn educationalPosts;"
      },
      "typeVersion": 2
    },
    {
      "id": "9c5ad9b6-df2a-42e2-a4f4-55b4967eed52",
      "name": "Post to Facebook",
      "type": "n8n-nodes-base.facebookGraphApi",
      "onError": "continueRegularOutput",
      "position": [
        5488,
        5792
      ],
      "parameters": {
        "edge": "feed",
        "node": "={{ $('Config: Pipeline C').first().json.facebook_page_id }}",
        "options": {
          "queryParameters": {
            "parameter": [
              {
                "name": "link",
                "value": "={{ $('Save Image into S3 Bucket').first().json.Location }}"
              },
              {
                "name": "message",
                "value": "={{ $('Process Social Posts').item.json.content }}"
              },
              {
                "name": "scheduled_publish_time",
                "value": "={{ $('Process Social Posts').item.json.scheduledTimestamp }}"
              },
              {
                "name": "published",
                "value": "false"
              }
            ]
          }
        },
        "graphApiVersion": "v23.0",
        "httpRequestMethod": "POST"
      },
      "credentials": {
        "facebookGraphApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "3ca7e419-35bf-4a31-8351-592dae69eac6",
      "name": "Create Instagram Container",
      "type": "n8n-nodes-base.facebookGraphApi",
      "onError": "continueRegularOutput",
      "position": [
        5488,
        5952
      ],
      "parameters": {
        "edge": "media",
        "node": "={{ $('Config: Pipeline C').first().json.instagram_id }}",
        "options": {
          "queryParameters": {
            "parameter": [
              {
                "name": "image_url",
                "value": "={{ $('Save Image into S3 Bucket').first().json.Location }}"
              },
              {
                "name": "caption",
                "value": "={{ $('Process Social Posts').item.json.content }}"
              },
              {
                "name": "scheduled_publish_time",
                "value": "={{ $('Process Social Posts').item.json.scheduledTimestamp }}"
              },
              {
                "name": "media_type",
                "value": "IMAGE"
              }
            ]
          }
        },
        "graphApiVersion": "v23.0",
        "httpRequestMethod": "POST"
      },
      "credentials": {
        "facebookGraphApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "99970263-5d16-47f2-b885-0b1fc1d9049b",
      "name": "Publish to Instagram",
      "type": "n8n-nodes-base.facebookGraphApi",
      "onError": "continueRegularOutput",
      "position": [
        5728,
        5952
      ],
      "parameters": {
        "edge": "media_publish",
        "node": "={{ $('Config: Pipeline C').first().json.instagram_id }}",
        "options": {
          "queryParameters": {
            "parameter": [
              {
                "name": "creation_id",
                "value": "={{ $json.id }}"
              }
            ]
          }
        },
        "graphApiVersion": "v23.0",
        "httpRequestMethod": "POST"
      },
      "credentials": {
        "facebookGraphApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "e0b76ce5-f245-4f66-acd0-b6f05b45c7e8",
      "name": "Sticky Note A1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2304,
        3440
      ],
      "parameters": {
        "color": 4,
        "width": 3424,
        "height": 424,
        "content": "## Pipeline A: Strategy Generation\nTrigger this pipeline via the Form URL to input your company details.\nGemini will generate a master business context document and save it to the root of your Google Drive.\nGrab the URL of that generated file to use in Pipeline B."
      },
      "typeVersion": 1
    },
    {
      "id": "cd410ff2-45f7-4304-82b8-0badf7dea3c0",
      "name": "Sticky Note B1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2304,
        3872
      ],
      "parameters": {
        "color": 5,
        "width": 3428,
        "height": 1284,
        "content": "## Pipeline B: Content Generation & Assembly\nRun Pipeline A first to produce your brand strategy Markdown.\nThen paste its Drive URL into Config: Pipeline B before triggering this pipeline.\nExpected runtime: ~8\u201312 minutes. Tokens: ~100k\u2013150k per run."
      },
      "typeVersion": 1
    },
    {
      "id": "5c25f529-921e-43b6-aec3-4f3f2c7c27d5",
      "name": "Sticky Note C1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2304,
        5200
      ],
      "parameters": {
        "color": 6,
        "width": 3812,
        "height": 984,
        "content": "## Pipeline C: Multi-Platform Publishing\nEnsure Pipeline B has completed successfully and the styled DOCX package exists in your Google Drive root.\nConfigure WordPress, social media IDs, and your S3 bucket details in Config: Pipeline C before running.\nGenerates custom AI images and safely schedules posts across all platforms."
      },
      "typeVersion": 1
    },
    {
      "id": "159e249c-9f17-47a0-8b90-9f15cd984778",
      "name": "Log Errors",
      "type": "n8n-nodes-base.code",
      "position": [
        4880,
        4800
      ],
      "parameters": {
        "jsCode": "const errorNodes = [];\nconst emailOut = $input.first()?.json;\nif (emailOut?.error) {\n  errorNodes.push({ node: 'Send Notification Email', error: String(emailOut.error) });\n}\nif (emailOut?.statusCode && emailOut.statusCode >= 400) {\n  errorNodes.push({ node: 'Send Notification Email', error: `HTTP ${emailOut.statusCode}` });\n}\ntry {\n  const uploadOut = $('Upload to Drive').first()?.json;\n  if (uploadOut?.error) {\n    errorNodes.push({ node: 'Upload DOCX to Google Drive', error: String(uploadOut.error) });\n  }\n} catch(e) {}\ntry {\n  const docxOut = $('Build DOCX').first()?.json;\n  if (docxOut?.error) {\n    errorNodes.push({ node: 'Generate Styled DOCX', error: String(docxOut.error) });\n  }\n} catch(e) { }\ntry {\n  const assembleOut = $('Merge Content Output').first()?.json;\n  if (assembleOut?.error) {\n    errorNodes.push({ node: 'Assemble Document', error: String(assembleOut.error) });\n  }\n  if (!assembleOut?.assembled_content) {\n    errorNodes.push({ node: 'Assemble Document', error: 'assembled_content is empty' });\n  }\n} catch(e) { }\ntry {\n  const planOut = $('Generate Content Plan').first()?.json;\n  if (planOut?.error) {\n    errorNodes.push({ node: 'Generate Content Plan', error: JSON.stringify(planOut.error) });\n  }\n} catch(e) { }\ntry {\n  const batchOut = $('Write Batch Content').first()?.json;\n  if (batchOut?.error) {\n    errorNodes.push({ node: 'Write Batch Content', error: JSON.stringify(batchOut.error) });\n  }\n} catch(e) { }\ntry {\n  const guidesOut = $('Write Guides').first()?.json;\n  if (guidesOut?.error) {\n    errorNodes.push({ node: 'Write Guides', error: JSON.stringify(guidesOut.error) });\n  }\n} catch(e) { }\nif (errorNodes.length > 0) {\n  console.log('Pipeline errors detected:', JSON.stringify(errorNodes));\n}\nreturn [{\n  json: {\n    status: errorNodes.length === 0 ? 'SUCCESS' : 'COMPLETED_WITH_ERRORS',\n    errors: errorNodes,\n    error_count: errorNodes.length,\n    completed_at: new Date().toISOString()\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "d130da7a-daa7-4d1e-bb84-f11305cb1c59",
      "name": "Any Errors?",
      "type": "n8n-nodes-base.if",
      "position": [
        5120,
        4800
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "err-check",
              "operator": {
                "type": "number",
                "operation": "gt"
              },
              "leftValue": "={{ $json.error_count }}",
              "rightValue": 0
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "aa4642a1-dc40-4f00-9877-d9bc80134a82",
      "name": "Send Error Alerts",
      "type": "n8n-nodes-base.gmail",
      "position": [
        5392,
        4736
      ],
      "parameters": {
        "sendTo": "={{ $('Config: Pipeline B').item.json.notification_email }}",
        "message": "=<div style=\"font-family: Arial, sans-serif; max-width: 600px;\">\n  <div style=\"background: #DC2626; padding: 20px; border-radius: 8px 8px 0 0;\">\n    <h2 style=\"color: white; margin: 0;\">Pipeline Error</h2>\n    <p style=\"color: rgba(255,255,255,0.85); margin: 4px 0 0;\">[Your Company Name] \u2013 AI Content Pipeline</p>\n  </div>\n  <div style=\"background: #FEF2F2; padding: 24px; border-radius: 0 0 8px 8px; border: 1px solid #FECACA;\">\n    <p style=\"color: #991B1B; font-weight: bold;\">{{ $json.error_count }} error(s) detected at {{ $json.completed_at }}</p>\n    <pre style=\"background: #fff; padding: 12px; border-radius: 6px; font-size: 12px; border: 1px solid #FECACA; overflow-x: auto;\">{{ JSON.stringify($json.errors, null, 2) }}</pre>\n  </div>\n</div>",
        "options": {},
        "subject": "={{ '\u274c Content Pipeline Error \u2013 ' + new Date().toLocaleDateString('en-IN', {month: 'long', year: 'numeric'}) }}"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "a36105a7-2610-4740-874b-62aaffee3274",
      "name": "Pipeline Success",
      "type": "n8n-nodes-base.set",
      "position": [
        5392,
        4896
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "final-status",
              "name": "pipeline_status",
              "type": "string",
              "value": "SUCCESS \u2013 Optimized pipeline completed."
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "e71a8e5b-91d5-4f6e-affd-a9f9ab8fc0f5",
      "name": "Sticky Note - Data Ingestion",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3184,
        3936
      ],
      "parameters": {
        "color": 2,
        "width": 1286,
        "height": 650,
        "content": "### \ud83d\udd0d Data Ingestion & Validation\nFetches contextual brand data, website analytics, and current Google trends to inform the generation."
      },
      "typeVersion": 1
    },
    {
      "id": "be7ddee2-041a-4eac-8e1e-838bb47311b9",
      "name": "Sticky Note - LLM Generation",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2336,
        4624
      ],
      "parameters": {
        "color": 3,
        "width": 1500,
        "height": 450,
        "content": "### \ud83e\udde0 LLM Generation Pipeline\nPrompts the LLM to build a strategy and generate massive batches of content across various formats."
      },
      "typeVersion": 1
    },
    {
      "id": "7fe30905-884a-43a3-acf6-a50fc7788377",
      "name": "Sticky Note - Document Assembly",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3936,
        4752
      ],
      "parameters": {
        "color": 4,
        "width": 788,
        "height": 250,
        "content": "### \ud83d\udcc4 Document Assembly & Storage\nCompiles raw text into a formatted DOCX and stores it in Google Drive for review."
      },
      "typeVersion": 1
    },
    {
      "id": "5c185bb0-e314-4035-9ade-5440ae899963",
      "name": "Sticky Note - Publishing",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        4704,
        5328
      ],
      "parameters": {
        "color": 5,
        "width": 1300,
        "height": 780,
        "content": "### \ud83d\ude80 Social & CMS Publishing Engine\nGenerates visuals via AI and schedules everything to WordPress, LinkedIn, Facebook, and Instagram."
      },
      "typeVersion": 1
    },
    {
      "id": "5f5833dc-6816-4f70-8fc5-ebdddd3677b8",
      "name": "Sticky Note - File Extraction",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2992,
        5344
      ],
      "parameters": {
        "color": 3,
        "width": 1054,
        "height": 382,
        "content": "### \ud83d\uddc2\ufe0f File Extraction & Parsing\nLocates the latest generated DOCX package in Drive, downloads, unzips, and extracts the raw XML text for the publisher to process."
      },
      "typeVersion": 1
    },
    {
      "id": "7da9bc3b-a5de-4f9f-a010-3561475d1430",
      "name": "Sticky Note - Error Handling",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        4768,
        4672
      ],
      "parameters": {
        "color": 7,
        "width": 866,
        "height": 446,
        "content": "### \ud83d\udea8 Error Handling & Notifications\nChecks the pipeline execution status and sends out summary success or error alerts via Gmail."
      },
      "typeVersion": 1
    },
    {
      "id": "e3de5db9-1a26-48c5-9cb3-f858db11b3b9",
      "name": "Save Image into S3 Bucket",
      "type": "n8n-nodes-base.awsS3",
      "position": [
        5120,
        5824
      ],
      "parameters": {
        "fileName": "={{ $binary.data.fileName }}",
        "operation": "upload",
        "bucketName": "={{ $('Config: Pipeline C').first().json.s3_bucket_name }}",
        "additionalFields": {
          "acl": "publicRead",
          "parentFolderKey": "{{ $('Config: Pipeline C').first().json.s3_bucket_folder_name }}"
        }
      },
      "typeVersion": 2
    },
    {
      "id": "1752177b-7126-4449-8450-76b9f34a332b",
      "name": "Config: Pipeline B",
      "type": "n8n-nodes-base.set",
      "position": [
        2624,
        4224
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "96d4b33c-6f3f-438d-b655-47f7fa87cece",
              "name": "gdrive_business_context_url",
              "type": "string",
              "value": "PASTE_DRIVE_MD_FILE_URL_HERE"
            },
            {
              "id": "97e8503f-a828-4a9f-990f-c44da34f5cc8",
              "name": "property_id",
              "type": "string",
              "value": "PASTE_GA4_PROPERTY_ID_HERE"
            },
            {
              "id": "e3c9f338-ff15-402e-b018-297a1107b86d",
              "name": "notification_email",
              "type": "string",
              "value": "PASTE_YOUR_EMAIL_HERE"
            },
            {
              "id": "105d634f-d86b-45db-98a5-da15b4a83cb4",
              "name": "trends_geo",
              "type": "string",
              "value": "IN"
            },
            {
              "id": "d25f430e-b450-4832-9d94-4bf18b458dfc",
              "name": "trends_lang",
              "type": "string",
              "value": "en-IN"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "74d7e3b9-1ad0-43d5-83e1-43700630ae07",
      "name": "Generate Strategy",
      "type": "@n8n/n8n-nodes-langchain.googleGemini",
      "position": [
        2928,
        3664
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "models/gemini-2.5-flash",
          "cachedResultName": "models/gemini-2.5-flash"
        },
        "options": {
          "temperature": "={{ $json.generationConfig.temperature }}",
          "systemMessage": "={{ $json.systemInstruction }}",
          "maxOutputTokens": "={{ $json.generationConfig.maxOutputTokens }}"
        },
        "messages": {
          "values": [
            {
              "content": "={{ $json.userMessage }}"
            }
          ]
        },
        "jsonOutput": true,
        "builtInTools": {}
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "52580894-22c9-40bc-97b9-314458fec620",
      "name": "Generate Content Plan",
      "type": "@n8n/n8n-nodes-langchain.googleGemini",
      "position": [
        4896,
        4240
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "models/gemini-2.5-flash",
          "cachedResultName": "models/gemini-2.5-flash"
        },
        "options": {
          "temperature": "={{ $json.generationConfig.temperature }}",
          "systemMessage": "={{ $json.systemInstruction }}",
          "maxOutputTokens": "={{ $json.generationConfig.maxOutputTokens }}"
        },
        "messages": {
          "values": [
            {
              "content": "={{ $json.userMessage }}"
            }
          ]
        },
        "jsonOutput": true,
        "builtInTools": {}
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "642dc5d8-d2f8-454a-a63f-e4217398a0ce",
      "name": "Write Batch Content",
      "type": "@n8n/n8n-nodes-langchain.googleGemini",
      "position": [
        2944,
        4688
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "models/gemini-2.5-flash",
          "cachedResultName": "models/gemini-2.5-flash"
        },
        "options": {
          "temperature": "={{ $json.generationConfig.temperature }}",
          "systemMessage": "={{ $json.systemInstruction }}",
          "maxOutputTokens": "={{ $json.generationConfig.maxOutputTokens }}"
        },
        "messages": {
          "values": [
            {
              "content": "={{ $json.userMessage }}"
            }
          ]
        },
        "jsonOutput": true,
        "builtInTools": {}
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "afe71865-f65b-4d81-8862-01e7c037983c",
      "name": "Write Guides",
      "type": "@n8n/n8n-nodes-langchain.googleGemini",
      "position": [
        2944,
        4912
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "models/gemini-2.5-flash",
          "cachedResultName": "models/gemini-2.5-flash"
        },
        "options": {
          "temperature": "={{ $json.generationConfig.temperature }}",
          "systemMessage": "={{ $json.systemInstruction }}",
          "maxOutputTokens": "={{ $json.generationConfig.maxOutputTokens }}"
        },
        "messages": {
          "values": [
            {
              "content": "={{ $json.userMessage }}"
            }
          ]
        },
        "jsonOutput": true,
        "builtInTools": {}
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "1a335a1e-dc5f-4854-bd11-ef7e7eb0324c",
      "name": "Config: Pipeline C",
      "type": "n8n-nodes-base.set",
      "position": [
        2640,
        5552
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "ce986d5a-26a8-4a04-b6bd-84cc3e96ad27",
              "name": "facebook_page_id",
              "type": "string",
              "value": "PASTE_FB_PAGE_ID_HERE"
            },
            {
              "id": "bf11a2e3-8fbd-4b3f-b78e-2ad426161d27",
              "name": "instagram_id",
              "type": "string",
              "value": "PASTE_IG_BUSINESS_ID_HERE"
            },
            {
              "id": "6e547068-05e6-40fd-b4e3-17dfedc8f58d",
              "name": "wordpress_domain",
              "type": "string",
              "value": "https://yourwebsite.com"
            },
            {
              "id": "5c35dffd-d5e0-439f-9fe6-5d7458ed05f7",
              "name": "s3_bucket_name",
              "type": "string",
              "value": "PASTE_S3_BUCKET_NAME"
            },
            {
              "id": "58211aa5-04b8-49f5-8b40-4be3bfe007c9",
              "name": "s3_bucket_folder_name",
              "type": "string",
              "value": "PASTE_S3_BUCKET_FOLDER_NAME"
            },
            {
              "id": "db176d37-4f98-4d90-ba32-cbb617db8b33",
              "name": "notification_email",
              "type": "string",
              "value": "PASTE_NOTIFICATION_GMAIL_HERE"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "f66e1923-fe90-4490-ba9e-f6e2ac483780",
      "name": "Generate Social Image",
      "type": "@n8n/n8n-nodes-langchain.googleGemini",
      "position": [
        4816,
        5824
      ],
      "parameters": {
        "prompt": "=A photorealistic shot of {{$json.content}}\"",
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "models/gemini-2.5-flash-image",
          "cachedResultName": "models/gemini-2.5-flash-image (Nano Banana)"
        },
        "options": {
          "sampleCount": 1,
          "binaryPropertyOutput": "data"
        },
        "resource": "image"
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "cbbbc62a-1bb7-401a-b8c9-6ba35baf76a1",
      "name": "Generate Blog Image",
      "type": "@n8n/n8n-nodes-langchain.googleGemini",
      "position": [
        4816,
        5424
      ],
      "parameters": {
        "prompt": "=A photorealistic shot of {{$json.title}}\"",
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "models/gemini-2.5-flash-image",
          "cachedResultName": "models/gemini-2.5-flash-image (Nano Banana)"
        },
        "options": {
          "sampleCount": 1,
          "binaryPropertyOutput": "data"
        },
        "resource": "image"
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "e85b8863-e39a-4470-a22e-9da47bf7f692",
      "name": "Generate LinkedIn Image",
      "type": "@n8n/n8n-nodes-langchain.googleGemini",
      "position": [
        4816,
        5616
      ],
      "parameters": {
        "prompt": "=A photorealistic shot of {{$json.topic}}\"",
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "models/gemini-2.5-flash-image",
          "cachedResultName": "models/gemini-2.5-flash-image (Nano Banana)"
        },
        "options": {
          "sampleCount": 1,
          "binaryPropertyOutput": "data"
        },
        "resource": "image"
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "870a3367-e644-4cc5-be0e-40d2efe4412f",
      "name": "Trigger: Pipeline B",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        2432,
        4224
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "40e90898-040a-45d5-8834-f1555cb1dd02",
      "name": "Loop Over Blogs",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        4576,
        5424
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "b7b1ecf5-6027-4842-aa5e-490849c3ed3d",
      "name": "Loop Over Social Posts",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        4576,
        5824
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "c7bb0d32-cbad-4d78-bde5-59ef84b27ee3",
      "name": "Loop Over LinkedIn Posts",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        4576,
        5616
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "addc946e-cd13-487f-ad5f-de57fc9f793c",
      "name": "Wait After Blog Publish",
      "type": "n8n-nodes-base.wait",
      "position": [
        5568,
        5424
      ],
      "parameters": {},
      "typeVersion": 1.1
    },
    {
      "id": "6715f7ac-f9cf-41f7-a33b-5078a0a249a6",
      "name": "Wait After LinkedIn Post Publish",
      "type": "n8n-nodes-base.wait",
      "position": [
        5312,
        5616
      ],
      "parameters": {},
      "typeVersion": 1.1
    },
    {
      "id": "91f362fa-aabe-4b64-ad32-626cf67e59d3",
      "name": "Wait After Social Posts Publish",
      "type": "n8n-nodes-base.wait",
      "position": [
        5888,
        5856
      ],
      "parameters": {},
      "typeVersion": 1.1
    },
    {
      "id": "a4aae9d5-56d2-4d94-b550-55c7bea9e202",
      "name": "Get LinkedIn User Info",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        2816,
        5552
      ],
      "parameters": {
        "url": "https://api.linkedin.com/v2/userinfo",
        "options": {},
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "linkedInOAuth2Api"
      },
      "credentials": {
        "linkedInOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "a6398058-e54c-4479-a621-d7b1e9fbf228",
      "name": "Fetch Brand Context",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        3280,
        4016
      ],
      "parameters": {
        "fileId": {
          "__rl": true,
          "mode": "url",
          "value": "={{ $json.gdrive_business_context_url }}"
        },
        "options": {},
        "operation": "download"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "465defbd-88eb-4b25-a50f-15df1fb692be",
      "name": "Convert Context Binary to Text",
      "type": "n8n-nodes-base.extractFromFile",
      "position": [
        3584,
        4080
      ],
      "parameters": {
        "options": {},
        "operation": "text",
        "destinationKey": "master_data"
      },
      "typeVersion": 1.1
    },
    {
      "id": "6ac9156c-f964-428e-9145-85027ef83764",
      "name": "Send Notification Email",
      "type": "n8n-nodes-base.gmail",
      "position": [
        4576,
        4800
      ],
      "parameters": {
        "sendTo": "={{ $('Config: Pipeline B').item.json.notification_email }}",
        "message": "=<div style=\"font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;\">\n  <div style=\"background: #1E3A5F; padding: 24px; border-radius: 8px 8px 0 0;\">\n    <h2 style=\"color: white; margin: 0;\">[Your Company Name]</h2>\n    <p style=\"color: rgba(255,255,255,0.75); margin: 4px 0 0;\">Monthly AI Content Pipeline</p>\n  </div>\n  <div style=\"background: #F8FAFC; padding: 24px; border-radius: 0 0 8px 8px; border: 1px solid #E2E8F0;\">\n    <h3 style=\"color: #1E3A5F;\">Your styled .docx package for {{ $('Build DOCX').item.json.run_date }} is ready.</h3>\n    <p style=\"color: #475569;\">A formatted Word document has been uploaded to Google Drive.</p>\n    <a href=\"https://drive.google.com/file/d/{{ $json.id }}\" style=\"display: inline-block; background: #1E3A5F; color: white; padding: 12px 24px; border-radius: 6px; text-decoration: none; font-weight: bold; margin-top: 8px;\">Open Styled DOCX in Drive \u2192</a>\n  </div>\n</div>",
        "options": {},
        "subject": "={{ '\u2705 Styled AI Content Package Ready \u2013 ' + $('Build DOCX').item.json.run_date }}"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "14c05913-9cb6-4798-a5c2-f09628775329",
      "name": "Trigger: Pipeline C",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        2432,
        5552
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "months",
              "triggerAtHour": 9
            }
          ]
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "e3bb1fc1-9792-4234-bc0a-9430f3273b7b",
      "name": "Assembled Doc",
      "type": "n8n-nodes-base.code",
      "position": [
        4000,
        4816
      ],
      "parameters": {
        "jsCode": "// \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// Assemble Document \u2014 CODE NODE (no AI call)\n// Replaces: Gemini: Assemble Doc (was call 7)\n// Document assembly is deterministic formatting \u2014 pure JavaScript.\n// Zero cost, zero latency, no hallucination risk.\n// \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst companyName = $('Compress Brand Context').first().json.companyName;\nconst batchData   = $('Parse Content Sections').first().json;\nconst guidesData  = $('Extract Guides').first().json;\nconst plan        = batchData.content_plan;\nconst runDate     = new Date().toLocaleDateString('en-IN', { month: 'long', year: 'numeric' });\nconst runDateUpper = runDate.toUpperCase();\n\nconst div  = '\\n\\n' + '='.repeat(60) + '\\n\\n';\nconst line = '\u2500'.repeat(45);\n\n// Build keyword clusters summary\nlet kwSummary = '';\nif (plan.keyword_clusters) {\n  kwSummary = Object.entries(plan.keyword_clusters)\n    .map(([pillar, terms]) => `  ${pillar.replace(/_/g,' ').toUpperCase()}: ${Array.isArray(terms) ? terms.join(', ') : 'N/A'}`)\n    .join('\\n');\n}\n\nconst toc =\n`TABLE OF CONTENTS\n${line}\n1. Monthly Content Strategy Overview\n2. SEO Blog Articles (6)\n3. LinkedIn Thought Leadership Posts (12)\n4. Educational Social Media Posts (8)\n5. Email Newsletter Campaigns (4)\n6. AI Strategy & Automation Guides (4)\n7. Keyword Clusters & Long-Tail Keywords\n${line}\nGenerated: ${runDate} | Pipeline: Tricore Infotech n8n (Optimized)`;\n\nconst assetSummary =\n`ASSET SUMMARY\n${line}\nSEO Blog Articles .......... 6\nLinkedIn Posts ............. 12\nSocial Media Posts ......... 8\nEmail Newsletters .......... 4\nAI Guides .................. 4\n${line}\nTotal pieces ............... 34\n\nStrategy overview: ${plan.strategy_overview ?? 'See plan JSON below'}`;\n\nconst keywordSection =\n`KEYWORD CLUSTERS\n${line}\n${kwSummary}\n\nLONG-TAIL KEYWORDS\n${line}\n${Array.isArray(plan.long_tail_keywords) ? plan.long_tail_keywords.map((k, i) => `${i+1}. ${k}`).join('\\n') : 'N/A'}`;\n\nconst warnings = batchData.parse_warnings ?? [];\nconst warningBlock = warnings.length > 0\n  ? `\\n\\n\u26a0 PIPELINE WARNINGS\\n${line}\\n${warnings.join('\\n')}\\n`\n  : '';\n\nconst assembled = [\n  `${companyName} \u2014 AI CONTENT PACKAGE \u2014 ${runDateUpper}`,\n  div,\n  toc,\n  div,\n  assetSummary,\n  warningBlock,\n  div,\n  '1. MONTHLY CONTENT STRATEGY OVERVIEW',\n  line,\n  JSON.stringify(plan, null, 2),\n  div,\n  '2. SEO BLOG ARTICLES',\n  line,\n  batchData.blog_articles,\n  div,\n  '3. LINKEDIN THOUGHT LEADERSHIP POSTS',\n  line,\n  batchData.linkedin_posts,\n  div,\n  '4. EDUCATIONAL SOCIAL MEDIA POSTS',\n  line,\n  batchData.social_posts,\n  div,\n  '5. EMAIL NEWSLETTER CAMPAIGNS',\n  line,\n  batchData.email_newsletters,\n  div,\n  '6. AI STRATEGY & AUTOMATION GUIDES',\n  line,\n  guidesData.ai_guides,\n  div,\n  '7. KEYWORD CLUSTERS & LONG-TAIL KEYWORDS',\n  line,\n  keywordSection\n].join('\\n\\n');\n\nreturn [{\n  json: {\n    assembled_content: assembled,\n    doc_title: `${companyName} \u2013 AI Content Package \u2013 ${runDate}`,\n    run_date: runDate,\n    char_count: assembled.length,\n    warnings: warnings,\n    content_plan: plan\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "a31eccd9-0bea-437c-9e3c-d907fc8f4b85",
      "name": "Error Notification",
      "type": "n8n-nodes-base.gmail",
      "position": [
        3504,
        5616
      ],
      "parameters": {
        "sendTo": "={{ $('Config: Pipeline C').item.json.notification_email }}",
        "message": "Hi,  Pipeline C ran but could not proceed because no DOCX files were found in the expected location.  This usually means Pipeline B has not been run yet, or it did not produce any output.  Action required: 1. Confirm Pipeline B has completed successfully. 2. Verify DOCX files exist in the expected directory/folder. 3. Re-run Pipeline C once the files are in place.  If Pipeline B did run and you still see this message, please check the Pipeline B logs for errors.  \u2014 Automated Workflow Notification",
        "options": {},
        "subject": "\u26a0\ufe0f Pipeline C Skipped \u2014 No DOCX Files Found",
        "emailType": "text"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "1debaa29-8cf6-4861-8339-8011d8a1ff2e",
  "connections": {
    "Build DOCX": {
      "main": [
        [
          {
            "node": "Upload to Drive",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Log Errors": {
      "main": [
        [
          {
            "node": "Any Errors?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Unzip DOCX": {
      "main": [
        [
          {
            "node": "Extract XML Text",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Any Errors?": {
      "main": [
        [
          {
            "node": "Send Error Alerts",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Pipeline Success",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Prompt": {
      "main": [
        [
          {
            "node": "Generate Strategy",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Write Guides": {
      "main": [
        [
          {
            "node": "Extract Guides",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Assembled Doc": {
      "main": [
        [
          {
            "node": "Build DOCX",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Download DOCX": {
      "main": [
        [
          {
            "node": "Prepare DOCX Archive",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch GA Data": {
      "main": [
        [
          {
            "node": "Merge Data Sources",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Export MD File": {
      "main": [
        [
          {
            "node": "Save to Drive",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Guides": {
      "main": [
        [
          {
            "node": "Merge Content Output",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Parse Response": {
      "main": [
        [
          {
            "node": "Format to Markdown",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Has DOCX Files?": {
      "main": [
        [
          {
            "node": "Download DOCX",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Error Notification",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Blogs": {
      "main": [
        [],
        [
          {
            "node": "Generate Blog Image",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Upload to Drive": {
      "main": [
        [
          {
            "node": "Send Notification Email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract XML Text": {
      "main": [
        [
          {
            "node": "Process Blog Articles",
            "type": "main",
            "index": 0
          },
          {
            "node": "Process LinkedIn Posts",
            "type": "main",
            "index": 0
          },
          {
            "node": "Process Social Posts",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Post to Facebook": {
      "main": [
        [
          {
            "node": "Wait After Social Posts Publish",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Post to LinkedIn": {
      "main": [
        [
          {
            "node": "Wait After LinkedIn Post Publish",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Company Data Form": {
      "main": [
        [
          {
            "node": "Build Prompt",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Strategy": {
      "main": [
        [
          {
            "node": "Parse Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Publish Blog Post": {
      "main": [
        [
          {
            "node": "Wait After Blog Publish",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Batch Prompt": {
      "main": [
        [
          {
            "node": "Write Batch Content",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Config: Pipeline B": {
      "main": [
        [
          {
            "node": "Fetch Trending Topics",
            "type": "main",
            "index": 0
          },
          {
            "node": "Fetch GA Data",
            "type": "main",
            "index": 0
          },
          {
            "node": "Fetch Brand Context",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Config: Pipeline C": {
      "main": [
        [
          {
            "node": "Get LinkedIn User Info",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format to Markdown": {
      "main": [
        [
          {
            "node": "Export MD File",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge Data Sources": {
      "main": [
        [
          {
            "node": "Compress Brand Context",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Upload to WP Media": {
      "main": [
        [
          {
            "node": "Publish Blog Post",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Guides Prompt": {
      "main": [
        [
          {
            "node": "Write Guides",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Brand Context": {
      "main": [
        [
          {
            "node": "Convert Context Binary to Text",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Blog Image": {
      "main": [
        [
          {
            "node": "Upload to WP Media",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Trigger: Pipeline B": {
      "main": [
        [
          {
            "node": "Config: Pipeline B",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Trigger: Pipeline C": {
      "main": [
        [
          {
            "node": "Config: Pipeline C",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Write Batch Content": {
      "main": [
        [
          {
            "node": "Parse Content Sections",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge Content Output": {
      "main": [
        [
          {
            "node": "Assembled Doc",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare DOCX Archive": {
      "main": [
        [
          {
            "node": "Unzip DOCX",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Process Social Posts": {
      "main": [
        [
          {
            "node": "Loop Over Social Posts",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Publish to Instagram": {
      "main": [
        [
          {
            "node": "Wait After Social Posts Publish",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Trending Topics": {
      "main": [
        [
          {
            "node": "Merge Data Sources",
            "type": "main",
            "index": 2
          }
        ]
      ]
    },
    "Generate Content Plan": {
      "main": [
        [
          {
            "node": "Validate Content Plan",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Social Image": {
      "main": [
        [
          {
            "node": "Save Image into S3 Bucket",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Process Blog Articles": {
      "main": [
        [
          {
            "node": "Loop Over Blogs",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Search Drive for DOCX": {
      "main": [
        [
          {
            "node": "Has DOCX Files?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Validate Content Plan": {
      "main": [
        [
          {
            "node": "Build Batch Prompt",
            "type": "main",
            "index": 0
          },
          {
            "node": "Build Guides Prompt",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Compress Brand Context": {
      "main": [
        [
          {
            "node": "Build Content Plan Prompt",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get LinkedIn User Info": {
      "main": [
        [
          {
            "node": "Search Drive for DOCX",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Social Posts": {
      "main": [
        [],
        [
          {
            "node": "Generate Social Image",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Content Sections": {
      "main": [
        [
          {
            "node": "Merge Content Output",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Process LinkedIn Posts": {
      "main": [
        [
          {
            "node": "Loop Over LinkedIn Posts",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate LinkedIn Image": {
      "main": [
        [
          {
            "node": "Post to LinkedIn",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Notification Email": {
      "main": [
        [
          {
            "node": "Log Errors",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait After Blog Publish": {
      "main": [
        [
          {
            "node": "Loop Over Blogs",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over LinkedIn Posts": {
      "main": [
        [],
        [
          {
            "node": "Generate LinkedIn Image",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Content Plan Prompt": {
      "main": [
        [
          {
            "node": "Generate Content Plan",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Save Image into S3 Bucket": {
      "main": [
        [
          {
            "node": "Create Instagram Container",
            "type": "main",
            "index": 0
          },
          {
            "node": "Post to Facebook",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Instagram Container": {
      "main": [
        [
          {
            "node": "Publish to Instagram",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Convert Context Binary to Text": {
      "main": [
        [
          {
            "node": "Merge Data Sources",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait After Social Posts Publish": {
      "main": [
        [
          {
            "node": "Loop Over Social Posts",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait After LinkedIn Post Publish": {
      "main": [
        [
          {
            "node": "Loop Over LinkedIn Posts",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}