/* NutriDMS, User Manual data
   Every section corresponds to a page in the API console.
   For each section we define:
   - id, title, icon
   - intro: 1-2 sentences
   - illustration: a React-component preview (defined in manual.jsx, keyed by id)
   - controls: every button / control on the page with what it does + deep-link
   - workflows: numbered step-by-step common tasks
   - tips: short callouts
*/

const MANUAL_SECTIONS = [
  {
    group: "Get started",
    items: [
      {
        id: "intro",
        title: "Welcome to NutriDMS",
        icon: "compass",
        intro: "NutriDMS is the nutrition-API infrastructure that powers calorie trackers, meal planners, fitness apps, restaurants, POS systems, and healthcare workflows. This manual explains every page of the API Console, every button, and the common end-to-end flows.",
        bullets: [
          { ic: "rocket",       t: "Production-ready APIs",      s: "Ingredient lookup, recipe analyze, allergens, labels, used by 800+ apps." },
          { ic: "shield-check", t: "Enterprise governance",      s: "Multi-tenant workspaces, audit logs, SCIM, SSO/SAML, regional residency." },
          { ic: "lightbulb",     t: "Loraa.ai + Health Rules",    s: "Bolt-on AI nutrition + clinical-grade compliance, billed separately." },
          { ic: "code-2",       t: "Mobile-first SDKs",          s: "iOS / Android publishable keys, scoped to your bundle ID." },
        ],
        workflows: [
          { t: "Get to your first API call in 5 minutes",
            steps: [
              "Open the dashboard, select <strong>Sandbox</strong> from the top env switcher",
              "Go to <a href='api-dashboard.html?view=keys'>API Keys</a> and create a Mobile key, pick your bundle ID",
              "Copy the cURL snippet from the reveal modal",
              "Run it against <code>/v1/ingredients/lookup</code>, you'll get 200 OK with sample data",
              "Verify in <a href='api-dashboard.html?view=logs'>Logs</a>: your request shows up live",
            ],
          },
        ],
        deepLink: { label: "Open the dashboard", href: "api-dashboard.html" },
      },
      {
        id: "global-chrome",
        title: "The console layout",
        icon: "layout-grid",
        intro: "Every page sits inside the same three-zone shell: sidebar (workspace + navigation), topbar (env switcher + utilities), and main content. These don't change as you move around.",
        illustration: "chrome",
        controls: [
          { ic: "chevrons-left", t: "Collapse sidebar",            s: "Hides text labels. Hover to preview. State persists across sessions." },
          { ic: "chevrons-up-down", t: "Workspace switcher",       s: "Top-left card. Click to jump between Acme, Production, Sandbox, EU, etc. Each workspace has isolated keys, billing, audit." },
          { ic: "circle-dot",    t: "Sandbox / Production toggle", s: "Top-right of the page. Switches the entire console's environment. Logs, keys, and usage all re-filter." },
          { ic: "globe",         t: "Language",                    s: "EN / ES / FR / DE. Localises the entire UI; doesn't change API responses." },
          { ic: "moon",          t: "Theme toggle",                s: "Light / dark. Saved to localStorage." },
          { ic: "bell",          t: "Notifications",               s: "Surfaces quota warnings, failed webhooks, expiring keys, member invites." },
          { ic: "book-open",     t: "Docs",                        s: "Opens the OpenAPI reference in a new tab." },
        ],
        deepLink: { label: "Open the dashboard", href: "api-dashboard.html" },
      },
    ],
  },
  {
    group: "Console pages",
    items: [
      {
        id: "overview",
        title: "Overview",
        icon: "layout-grid",
        intro: "Your at-a-glance home, current plan, usage burn rate, failed-request rate, daily-call chart, production-access gates, and shortcuts to the rest of the console.",
        illustration: "overview",
        controls: [
          { ic: "alert-triangle",  t: "Quota banner",          s: "Appears when you've hit 50%, 80%, or projected overage. Dismiss or upgrade right from the banner." },
          { ic: "package",         t: "Current plan card",     s: "Plan name + billing cadence. Click to jump to Billing." },
          { ic: "activity",        t: "Monthly usage card",    s: "Calls used / quota with progress bar. Updates every ~30s." },
          { ic: "zap",             t: "Usage remaining",       s: "Calls left + days to renewal." },
          { ic: "credit-card",     t: "Current bill",          s: "Base + add-ons + estimated overage." },
          { ic: "trending-up",     t: "Estimated overage",     s: "Linear projection of overage in the current cycle." },
          { ic: "key-round",       t: "Active keys",           s: "Count of unrevoked keys + last rotation age." },
          { ic: "alert-octagon",   t: "Failed requests",       s: "% of requests returning ≥ 400. Trend arrow vs last week." },
          { ic: "calendar",        t: "Next billing date",     s: "Renewal date + card on file." },
          { ic: "shield-check",    t: "Production-access gates",s: "Four gates: verified business email, Stripe card, accepted agreements, use-case verified. All four green = production unlocked." },
          { ic: "bar-chart-3",     t: "Daily requests chart",   s: "30-day bar chart with successful / throttled / failed segments. Range buttons in the card header." },
          { ic: "list",            t: "Top endpoints",          s: "Calls by endpoint with share %. Hot endpoints surface latency issues fast." },
          { ic: "shield-check",    t: "Compliance posture",     s: "USDA mappings, FDA workflows, audit retention, residency, SSO/SAML, SOC 2 roadmap." },
          { ic: "graduation-cap",  t: "Student program card",   s: "40% off Starter / Growth, links to the application." },
          { ic: "building-2",      t: "Contact sales card",     s: "Talk to sales for Business / Enterprise + custom infra." },
        ],
        deepLink: { label: "Open Overview", href: "api-dashboard.html?view=overview" },
      },
      {
        id: "usage",
        title: "Usage",
        icon: "activity",
        intro: "Drill into how many calls you're making, who's making them, and where they're slow. Driven by the same metering pipeline that produces your invoice.",
        illustration: "usage",
        controls: [
          { ic: "calendar-days",   t: "Range chips",         s: "Today / 7 days / 30 days / Cycle / Custom. Drives all stats and the chart." },
          { ic: "activity",        t: "Total / Successful / Failed / Avg latency stats", s: "Top KPI strip. Recomputed live on range change." },
          { ic: "bar-chart-3",     t: "Daily usage chart",   s: "Stacked bars by status class. Hover for exact numbers." },
          { ic: "filter",          t: "Breakdown filter",    s: "Pivot the breakdown table by endpoint / API key / project." },
        ],
        tips: [
          "Use <strong>Cycle</strong> to see exactly what will land on your next invoice.",
          "Errors here ≠ Errors in Logs, Usage is sampled at 30-second resolution; Logs are per-request.",
        ],
        deepLink: { label: "Open Usage", href: "api-dashboard.html?view=usage" },
      },
      {
        id: "keys",
        title: "API Keys",
        icon: "key-round",
        intro: "Sandbox and Production are isolated tenants. Generate scoped keys per environment, per platform, per app. Server keys (sk_*) hold full scope and must stay on your backend. Mobile keys (pk_*) ship inside your app and are restricted by bundle ID + referrer.",
        illustration: "keys",
        controls: [
          { ic: "server",        t: "Environment cards",       s: "Two top cards, Sandbox + Production. Show base URL, P50 latency, 30-day uptime, key count, calls today. Click 'Switch' to filter the table below." },
          { ic: "copy",          t: "Copy base URL",           s: "Each env card has a copy button next to its API base URL." },
          { ic: "play",          t: "Open playground",         s: "Sandbox env card → jumps to the interactive API sandbox." },
          { ic: "plus",          t: "+ Create API key",        s: "Opens the 5-step modal: Key type → Identity → Scopes → Limits → Generate." },
          { ic: "smartphone",    t: "Mobile / Client key type",s: "Publishable key (pk_*) safe to ship in iOS / Android / web apps. Restricted to your bundle ID + Play package." },
          { ic: "server",        t: "Server key type",         s: "Secret key (sk_*), full scope. Never bundle in mobile or client-side code." },
          { ic: "webhook",       t: "Webhook signing key",     s: "HMAC signing key (whsec_*), used only to verify incoming webhook payloads." },
          { ic: "list-checks",   t: "Scoped permissions",      s: "Per-resource toggles: ingredients.read, recipes.analyze, allergens.detect, labels.generate, plus Loraa.ai / Health Rules / Custom Tools when those add-ons are active." },
          { ic: "globe-lock",    t: "IP allowlist",            s: "Server keys only. Comma-separated CIDRs. Calls from outside the allowlist return 401." },
          { ic: "smartphone",    t: "Bundle ID restriction",   s: "Mobile keys only. App requests are validated server-side against the iOS bundle / Android package you provided." },
          { ic: "clock",         t: "Expiry",                  s: "Never / 30d / 90d (recommended) / 180d / 1y. Email reminder 7 days before expiry." },
          { ic: "eye",           t: "Reveal key",              s: "On the reveal screen, eye toggles between masked and full key. The key is only ever shown once." },
          { ic: "copy",          t: "Copy key",                s: "One-click copy with success confirmation. Audit-logged." },
          { ic: "code-2",        t: "Language tabs",           s: "On reveal: Swift / Kotlin / React Native / cURL for mobile keys; Node / Python / Ruby / cURL for server keys. Snippets pre-populated with your key + base URL." },
          { ic: "rotate-cw",     t: "Rotate (table row)",      s: "Generate a new key, keep the same scope, and 24h grace period to migrate." },
          { ic: "settings-2",    t: "Edit (table row)",        s: "Change scopes, rate limits, allowlists, without minting a new key." },
          { ic: "trash-2",       t: "Revoke (table row)",      s: "Immediately revokes the key. Calls with it return 401 from the next request onward." },
        ],
        workflows: [
          { t: "Ship a key inside your iOS app",
            steps: [
              "Click <strong>+ Create API key</strong>",
              "Pick <strong>Mobile / Client key</strong> on step 1",
              "Set environment to <strong>Production</strong>, enter your iOS bundle ID (e.g. <code>com.acme.macropal</code>)",
              "Select scopes: <code>ingredients.read</code>, <code>recipes.analyze</code>, <code>allergens.detect</code>",
              "Skip IP allowlist (mobile clients have dynamic IPs); set a monthly cap",
              "Generate, copy the Swift snippet and paste into your AppDelegate",
            ],
          },
        ],
        deepLink: { label: "Open API Keys", href: "api-dashboard.html?view=keys" },
      },
      {
        id: "health-tools",
        title: "Custom Health Tools",
        icon: "shield-check",
        intro: "Compose your own validation logic on top of NutriDMS, sodium thresholds, custom allergen lists, glycemic-load weighting. Each tool becomes a live API endpoint at <code>/v1/tools/custom/{slug}/run</code> that your mobile or backend apps can call with a scoped key.",
        illustration: "health-tools",
        controls: [
          { ic: "plus",            t: "+ New custom tool",       s: "Opens the builder modal." },
          { ic: "list-checks",     t: "Compose tab",             s: "Pick rule templates (sodium, sugar, caffeine, glycemic load, allergen list, macro ratio, ingredient banlist, pregnancy-safe). Each adds an editable WHEN/THEN row." },
          { ic: "play",            t: "Test tab",                s: "Side-by-side sample request + computed response with findings array. Validate before publishing." },
          { ic: "code-2",          t: "Endpoint & Keys tab",     s: "Shows the live endpoint URL with copy button. Bind / unbind keys. Swift install snippet pre-populated." },
          { ic: "rocket",          t: "Publish endpoint",        s: "Promotes a draft tool to live. Generates an audit-log entry." },
          { ic: "trash-2",         t: "Delete tool",             s: "Soft-delete with 30-day undo. Calls during the window return 410 Gone." },
        ],
        tips: [
          "Rules evaluate top-to-bottom. The first rule with severity <code>block</code> short-circuits and returns 422.",
          "<strong>Mobile keys</strong> can call custom tools, perfect for shipping client-specific compliance into your app.",
        ],
        deepLink: { label: "Open Custom Health Tools", href: "api-dashboard.html?view=health-tools" },
      },
      {
        id: "logs",
        title: "Logs",
        icon: "file-clock",
        intro: "Live API request stream, searchable, exportable, retained 30 days on Growth (90 days on Business, 365 on Enterprise). Each row is a single request with all context attached.",
        illustration: "logs",
        controls: [
          { ic: "circle-dot",      t: "Env switch (top + page)",s: "Switching env reloads the log stream for that environment. The in-page Sandbox / Production cards mirror the topbar." },
          { ic: "download",        t: "Export CSV",             s: "Downloads the currently-filtered rows. Headers: time, method, endpoint, key, status, latency, ip, request_id." },
          { ic: "play",            t: "Tail live",              s: "Streams new requests as they happen. Click again to stop. New rows slide in green for 350ms." },
          { ic: "filter",          t: "Status chips",           s: "All / Successful / Errors, pre-filter for 4xx/5xx triage." },
          { ic: "list",            t: "Method dropdown",        s: "GET / POST / PUT / DELETE." },
          { ic: "timer",           t: "Latency dropdown",       s: "&lt; 1s / ≥ 1s, surface slow requests." },
          { ic: "search",          t: "Search box",             s: "Matches endpoint, status code, IP, key name, or request ID. AND-combined with chips." },
          { ic: "x",               t: "Clear filters chip",     s: "Appears when any filter is active. Resets all at once." },
          { ic: "rectangle-list",  t: "Click a row",            s: "Opens a side drawer with full request + response preview, metadata grid, and replay action." },
          { ic: "copy",            t: "Copy as JSON (drawer)",  s: "Copies the full row + request + response to clipboard." },
          { ic: "play-circle",     t: "Replay in sandbox",      s: "Opens the playground with the same payload pre-filled. Sandbox-only." },
        ],
        tips: [
          "Failed requests are highlighted in red. Click into any 5xx to see the reference ID, use it when contacting support.",
          "Tailing live <em>does not</em> count against retention. Tail freely during incidents.",
        ],
        deepLink: { label: "Open Logs", href: "api-dashboard.html?view=logs" },
      },
      {
        id: "billing",
        title: "Billing",
        icon: "credit-card",
        intro: "Plan, usage, payments, invoices. Stripe-backed, we never see your raw card.",
        illustration: "billing",
        controls: [
          { ic: "package",         t: "Current plan card",      s: "Shows plan name, base + overage + add-on subtotals, projected next bill, downgrade and add-call-pack actions." },
          { ic: "arrow-up-circle", t: "Upgrade plan",           s: "Opens the plan picker (Growth → Business → Enterprise) with prorated upgrade math." },
          { ic: "credit-card",     t: "Payment method card",    s: "Shows masked card with brand. Update button opens Stripe-hosted card form." },
          { ic: "building-2",      t: "Update billing address", s: "For tax + compliance. Required if you change country." },
          { ic: "file-text",       t: "Invoice history table",  s: "All paid invoices with period, date, overage, amount, status." },
          { ic: "download",        t: "Download invoice",       s: "Per-row PDF download. Audit-logged." },
          { ic: "mail",            t: "Email invoice",          s: "Send a copy to billing contact." },
          { ic: "download",        t: "Export all",             s: "ZIP of all invoice PDFs + a CSV manifest." },
        ],
        deepLink: { label: "Open Billing", href: "api-dashboard.html?view=billing" },
      },
      {
        id: "team",
        title: "Team & Roles",
        icon: "users",
        intro: "Invite teammates, assign roles, and control what each person can do. Six PRD roles, Owner, Admin, Developer, Billing Manager, Compliance Reviewer, Analyst. SCIM / SSO ready on Enterprise.",
        illustration: "team",
        controls: [
          { ic: "user-plus",       t: "+ Invite member",        s: "Opens the 5-step enterprise invite flow." },
          { ic: "users",           t: "Add people (step 1)",    s: "Paste many emails or upload a CSV. Verified-domain addresses get a green chip; external ones get a warning chip." },
          { ic: "link",            t: "SCIM tab",               s: "Enterprise feature. Shows endpoint URL + bearer for Okta / Azure AD / JumpCloud / Google Workspace." },
          { ic: "shield",          t: "Role (step 2)",          s: "Pick one of six roles. Live preview shows what's Allowed vs Denied for the chosen role." },
          { ic: "boxes",           t: "Workspaces (step 3)",    s: "Restrict members to specific workspaces. At least one required." },
          { ic: "shield-check",    t: "Require MFA (step 3)",   s: "Members must enrol in TOTP / WebAuthn before accessing the console." },
          { ic: "globe-lock",      t: "IP allowlist (step 3)",  s: "Enterprise, restricts member sign-in by IP / CIDR." },
          { ic: "clock",           t: "Invite expiry (step 3)", s: "24h (most secure) / 7d (default) / 30d / never." },
          { ic: "send",            t: "Notify via (step 4)",    s: "Email, Slack DM, or copy magic link." },
          { ic: "message-square",  t: "Custom welcome (step 4)",s: "Markdown-supported message that appears in the invitation email." },
          { ic: "check-check",     t: "Review (step 5)",        s: "Recipients, role, workspaces, security, delivery, all summarised." },
          { ic: "settings-2",      t: "Edit role (row)",        s: "Per-member role change. Audit-logged." },
          { ic: "user-x",          t: "Remove (row)",           s: "Revoke all sessions immediately." },
        ],
        deepLink: { label: "Open Team & Roles", href: "api-dashboard.html?view=team" },
      },
      {
        id: "webhooks",
        title: "Webhooks",
        icon: "webhook",
        intro: "Subscribe to NutriDMS events and route them to Slack, your backend, or any HTTPS endpoint. All seven event types, <code>ingredient.verified</code>, <code>recipe.analyzed</code>, <code>allergen.detected</code>, <code>health_rule.failed</code>, <code>usage.limit_warning</code>, <code>invoice.created</code>, <code>api_key.rotated</code>.",
        illustration: "webhooks",
        controls: [
          { ic: "plus",            t: "+ New webhook",          s: "Opens the configuration drawer: URL, secret, events, retry policy." },
          { ic: "grid-3x3",        t: "Supported events grid",  s: "Catalogue of all 7 event types. Each card shows the event code, label, and current subscriber count." },
          { ic: "book-open",       t: "Payload reference",      s: "Opens docs for the payload schema of every event." },
          { ic: "zap",             t: "Test (row)",             s: "Fires a synthetic event of each subscribed type to the endpoint. Useful for verifying signature handling." },
          { ic: "settings-2",      t: "Edit (row)",             s: "Update URL, secret, or events without dropping in-flight deliveries." },
          { ic: "trash-2",         t: "Delete (row)",           s: "Removes the subscription. Pending retries are cancelled." },
        ],
        tips: [
          "All payloads are signed with HMAC-SHA256 in the <code>NutriDMS-Signature</code> header. Always verify before processing.",
          "Failed deliveries retry with exponential backoff up to <strong>24h</strong>. The Healthy / Degraded pill tracks 7-day success rate.",
        ],
        deepLink: { label: "Open Webhooks", href: "api-dashboard.html?view=webhooks" },
      },
      {
        id: "settings",
        title: "Settings",
        icon: "settings",
        intro: "Organization name, default environment, usage alerts, security defaults, data region.",
        illustration: "settings",
        controls: [
          { ic: "building-2",      t: "Organization name",   s: "How your workspace appears in invoices and emails." },
          { ic: "server",          t: "Default environment", s: "Sandbox or Production, new keys created from CLI / SDK default to this." },
          { ic: "bell",            t: "Usage alerts",        s: "50% / 80% / overage-start / hard-cap toggles. Sent to billing contact + Slack if connected." },
          { ic: "shield-check",    t: "Security defaults",   s: "90-day rotation requirement, production-key approval, IP allowlist enforcement." },
          { ic: "globe",           t: "Region",              s: "Data residency for logs + metadata. Locked once production traffic starts." },
        ],
        deepLink: { label: "Open Settings", href: "api-dashboard.html?view=settings" },
      },
    ],
  },
  {
    group: "Reference",
    items: [
      {
        id: "glossary",
        title: "Glossary",
        icon: "book",
        intro: "Common terms you'll encounter in the dashboard, billing, and API responses.",
        glossary: [
          { t: "Workspace",     s: "An isolated tenant, its own keys, billing, logs, members, audit. You can have many; switch via the top-left card." },
          { t: "Environment",   s: "Sandbox or Production. Each has its own base URL, key prefix, and rate limits." },
          { t: "Scope",         s: "A permission attached to a key (e.g. <code>recipes.analyze</code>). Keys can only call endpoints they're scoped for." },
          { t: "Quota",         s: "Your plan's included monthly call count. Going over triggers overage billing at the plan's per-call rate." },
          { t: "Overage",       s: "Calls beyond your plan's quota, billed at the plan's per-call rate (e.g. $0.004 on Growth)." },
          { t: "Add-on",        s: "Loraa.ai / Health Rules / Recipe Media, billed separately on top of base plan." },
          { t: "Custom tool",   s: "Your own validation logic composed of rule templates. Exposed as a callable endpoint." },
          { t: "Tail live",     s: "Stream new log entries in real-time. Doesn't count against retention." },
          { t: "Bundle ID",     s: "Your iOS app's reverse-DNS identifier (e.g. <code>com.acme.macropal</code>). Mobile keys are restricted to this." },
          { t: "Rate limit",    s: "Requests-per-second cap, enforced per-key. Bursts above it return <code>429 Too Many Requests</code> with <code>Retry-After</code>." },
          { t: "SCIM",          s: "System for Cross-domain Identity Management, auto-provisions users from your IdP (Okta, Azure AD, JumpCloud)." },
          { t: "WORM",          s: "Write-Once-Read-Many. Our audit logs are stored in WORM mode, immutable for compliance." },
        ],
      },
      {
        id: "errors",
        title: "Error codes",
        icon: "alert-octagon",
        intro: "Every error response includes a stable <code>error</code> code, a human <code>message</code>, and a <code>request_id</code> you can quote to support.",
        errors: [
          { code: "400", err: "bad_request",          s: "Required field missing or wrong type. Check the message." },
          { code: "401", err: "unauthorized",         s: "Key is invalid, revoked, or missing. Reissue from API Keys." },
          { code: "402", err: "subscription_required",s: "Endpoint requires an add-on. Activate Loraa.ai / Health Rules / Recipe Media in Billing." },
          { code: "403", err: "forbidden",            s: "Key lacks the required scope. Edit the key and toggle the scope on." },
          { code: "404", err: "not_found",            s: "Resource doesn't exist or is in a different workspace." },
          { code: "422", err: "validation_failed",    s: "Custom Health Tool returned a <code>block</code> severity finding. Check <code>findings[]</code>." },
          { code: "429", err: "rate_limited",         s: "Exceeded req/sec cap. Honour <code>Retry-After</code> header." },
          { code: "500", err: "internal_error",       s: "Our problem, not yours. Reference the <code>request_id</code> when contacting support." },
        ],
      },
    ],
  },
];

Object.assign(window, { MANUAL_SECTIONS });
