/* app-data.jsx — Lucide-style icons + site content. Exported to window. */
const { createElement: h } = React;

// generic stroke-icon factory
function svg(paths, opts) {
  opts = opts || {};
  return (props) => h('svg', Object.assign({
    viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor',
    strokeWidth: opts.w || 2, strokeLinecap: 'round', strokeLinejoin: 'round',
  }, props), paths.map((d, i) => h('path', { key: i, d })));
}
function raw(children, vb) {
  return (props) => h('svg', Object.assign({ viewBox: vb || '0 0 24 24', fill: 'none' }, props), children);
}

const Icons = {
  ArrowRight: svg(['M5 12h14', 'm12 5 7 7-7 7']),
  ArrowDown: svg(['M12 5v14', 'm5 12 7 7 7-7']),
  ChevronDown: svg(['m6 9 6 6 6-6']),
  ChevronLeft: svg(['m15 18-6-6 6-6']),
  ChevronRight: svg(['m9 18 6-6-6-6']),
  Check: svg(['M20 6 9 17l-5-5']),
  CheckCircle: svg(['M21.8 10A10 10 0 1 1 12 2.2', 'm9 11 3 3L22 4'], { w: 2 }),
  Search: svg(['m21 21-4.3-4.3', 'M11 19a8 8 0 1 0 0-16 8 8 0 0 0 0 16z']),
  Bell: svg(['M10.3 21a1.94 1.94 0 0 0 3.4 0', 'M3.3 18A1 1 0 0 1 4 16.3c1.3-1.2 1.8-2 1.8-4.3a6.2 6.2 0 0 1 12.4 0c0 2.3.5 3.1 1.8 4.3a1 1 0 0 1 .7 1.7z']),
  Layers: svg(['m12.8 2.5 8.3 4.2a1 1 0 0 1 0 1.8l-8.3 4.2a1.8 1.8 0 0 1-1.6 0L2.9 8.5a1 1 0 0 1 0-1.8l8.3-4.2a1.8 1.8 0 0 1 1.6 0z', 'm22 17.7-9.2 4.6a1.8 1.8 0 0 1-1.6 0L2 17.7', 'm22 12.7-9.2 4.6a1.8 1.8 0 0 1-1.6 0L2 12.7']),
  Workflow: svg(['M14 4h5a1 1 0 0 1 1 1v3a1 1 0 0 1-1 1h-5a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1z', 'M5 15h5a1 1 0 0 1 1 1v3a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1v-3a1 1 0 0 1 1-1z', 'M7 9v3a2 2 0 0 0 2 2h7']),
  Wrench: svg(['M14.7 6.3a4 4 0 0 1-5.2 5.2L4 17v3h3l5.5-5.5a4 4 0 0 1 5.2-5.2l-2.8 2.8-1.7-1.7 2.8-2.8a4 4 0 0 0-1.3-.3z']),
  Code: svg(['m18 16 4-4-4-4', 'm6 8-4 4 4 4', 'm14.5 4-5 16']),
  BarChart: svg(['M3 3v17a1 1 0 0 0 1 1h17', 'M8 16V11', 'M13 16V8', 'M18 16v-3']),
  Sparkles: svg(['M11.3 3.3a.6.6 0 0 1 1.1 0l1.9 4.4 4.4 1.9a.6.6 0 0 1 0 1.1l-4.4 1.9-1.9 4.4a.6.6 0 0 1-1.1 0l-1.9-4.4-4.4-1.9a.6.6 0 0 1 0-1.1l4.4-1.9z', 'M19 15.5l.7 1.6 1.6.7-1.6.7-.7 1.6-.7-1.6-1.6-.7 1.6-.7z']),
  FileCheck: svg(['M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z', 'M14 2v6h6', 'm9 15 2 2 4-4']),
  Ruler: svg(['M21.3 15.3 8.7 2.7a1 1 0 0 0-1.4 0L2.7 7.3a1 1 0 0 0 0 1.4l12.6 12.6a1 1 0 0 0 1.4 0l4.6-4.6a1 1 0 0 0 0-1.4z', 'm14.5 12.5-2 2', 'm11.5 9.5-2 2', 'm8.5 6.5-2 2', 'm17.5 15.5-2 2']),
  AlertTriangle: svg(['m21.7 18-8-14a2 2 0 0 0-3.4 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.7-3z', 'M12 9v4', 'M12 17h.01']),
  Repeat: svg(['m17 2 4 4-4 4', 'M3 11v-1a4 4 0 0 1 4-4h14', 'm7 22-4-4 4-4', 'M21 13v1a4 4 0 0 1-4 4H3']),
  Cap: svg(['M22 10 12 5 2 10l10 5 10-5z', 'M6 12v5c0 1.7 2.7 3 6 3s6-1.3 6-3v-5']),
  ClipboardCheck: svg(['M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2', 'M9 2h6a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1H9a1 1 0 0 1-1-1V3a1 1 0 0 1 1-1z', 'm9 14 2 2 4-4']),
  Lock: svg(['M5 11h14a1 1 0 0 1 1 1v8a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1v-8a1 1 0 0 1 1-1z', 'M8 11V7a4 4 0 0 1 8 0v4']),
  Shield: svg(['M20 13c0 5-3.5 7.5-7.7 9a1 1 0 0 1-.6 0C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.2-2.7a1 1 0 0 1 1.5 0C14.5 3.8 17 5 19 5a1 1 0 0 1 1 1z', 'm9 12 2 2 4-4']),
  Zap: svg(['M4 14a1 1 0 0 1-.8-1.6l9-10a.5.5 0 0 1 .9.4L11.5 10H20a1 1 0 0 1 .8 1.6l-9 10a.5.5 0 0 1-.9-.4l1.6-7.2z']),
  Quote: svg(['M3 21c3 0 7-1 7-8V5a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2h2', 'M15 21c3 0 7-1 7-8V5a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2h2']),
  FileText: svg(['M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z', 'M14 2v6h6', 'M9 13h6', 'M9 17h6']),
  FileX: svg(['M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z', 'M14 2v6h6', 'm9.5 12.5 5 5', 'm14.5 12.5-5 5']),
  Boxes: svg(['M2.97 12.92A2 2 0 0 0 2 14.63v3.24a2 2 0 0 0 .97 1.71l3 1.8a2 2 0 0 0 2.06 0L12 19v-5.5l-5-3-4.03 2.42z', 'm7 16.5-4.74-2.85', 'm7 16.5 5-3', 'M7 16.5v5.17', 'M12 13.5V19l3.97 2.38a2 2 0 0 0 2.06 0l3-1.8a2 2 0 0 0 .97-1.71v-3.24a2 2 0 0 0-.97-1.71L17 10.5l-5 3z', 'm17 16.5-5-3', 'm17 16.5 4.74-2.85', 'M17 16.5v5.17', 'M7.97 4.42A2 2 0 0 0 7 6.13v4.37l5 3 5-3V6.13a2 2 0 0 0-.97-1.71l-3-1.8a2 2 0 0 0-2.06 0l-3 1.8z', 'M12 8 7.26 5.15', 'm12 8 4.74-2.85', 'M12 13.5V8']),
  Cpu: svg(['M6 6h12a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2z', 'M9 9h6v6H9z', 'M15 2v2', 'M9 2v2', 'M15 20v2', 'M9 20v2', 'M20 9h2', 'M20 14h2', 'M2 9h2', 'M2 14h2']),
  Plug: svg(['M9 2v6', 'M15 2v6', 'M7 8h10v3a5 5 0 0 1-10 0z', 'M12 16v4', 'M9 22h6']),
  Link: svg(['M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71', 'M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71']),
  History: svg(['M3 3v5h5', 'M3.05 13A9 9 0 1 0 6 5.3L3 8', 'M12 7v5l4 2']),
  Plus: svg(['M12 5v14', 'M5 12h14']),
  Menu: svg(['M4 6h16', 'M4 12h16', 'M4 18h16']),
  Clock: svg(['M12 21a9 9 0 1 0 0-18 9 9 0 0 0 0 18z', 'M12 7v5l3 2']),
  GitBranch: svg(['M6 3v12', 'M18 9a3 3 0 1 0 0-6 3 3 0 0 0 0 6z', 'M6 21a3 3 0 1 0 0-6 3 3 0 0 0 0 6z', 'M15 6a9 9 0 0 1-9 9']),
  Rocket: svg(['M4.5 16.5c-1.5 1.26-2 5-2 5s3.74-.5 5-2c.71-.84.7-2.13-.09-2.91a2.18 2.18 0 0 0-2.91-.09z', 'M12 15l-3-3a22 22 0 0 1 2-3.95A12.88 12.88 0 0 1 22 2c0 2.72-.78 7.5-6 11a22.35 22.35 0 0 1-4 2z', 'M9 12H4s.55-3.03 2-4c1.62-1.08 5 0 5 0', 'M12 15v5s3.03-.55 4-2c1.08-1.62 0-5 0-5']),
  Robot: svg(['M6 8h12a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2v-8a2 2 0 0 1 2-2z', 'M12 8V5', 'M12 5a1.6 1.6 0 1 0 0-3.2 1.6 1.6 0 0 0 0 3.2z', 'M9.5 13v1.6', 'M14.5 13v1.6', 'M4 14.5H2.4', 'M21.6 14.5H20']),
  Handshake: svg(['m11 17 2 2a1 1 0 1 0 3-3', 'm14 14 2.5 2.5a1 1 0 1 0 3-3l-3.88-3.88a3 3 0 0 0-4.24 0l-.88.88a1 1 0 1 1-3-3l2.81-2.81a5.79 5.79 0 0 1 7.06-.87l.47.28a2 2 0 0 0 1.42.25L21 4', 'm21 3 1 11h-2', 'M3 3 2 14l6.5 6.5a1 1 0 1 0 3-3', 'M3 4h8']),
  Beaker: svg(['M9 2v6.6a1 1 0 0 1-.18.57L4.2 16a1 1 0 0 0 .82 1.57h13.96a1 1 0 0 0 .82-1.57l-4.62-6.83a1 1 0 0 1-.18-.57V2', 'M8 2h8', 'M7.5 13h9']),
  Eye: svg(['M2.06 12.35a1 1 0 0 1 0-.7 10.8 10.8 0 0 1 19.88 0 1 1 0 0 1 0 .7 10.8 10.8 0 0 1-19.88 0z', 'M12 15a3 3 0 1 0 0-6 3 3 0 0 0 0 6z']),
  Linkedin: raw([h('path', { key: 0, d: 'M4.98 3.5A2.5 2.5 0 1 1 0 3.5a2.5 2.5 0 0 1 4.98 0zM.5 8h4V24h-4zM8 8h3.8v2.2h.05c.53-1 1.83-2.2 3.77-2.2 4.03 0 4.78 2.65 4.78 6.1V24h-4v-6.9c0-1.65-.03-3.77-2.3-3.77-2.3 0-2.65 1.8-2.65 3.65V24H8z', fill: 'currentColor' })]),
  X: raw([h('path', { key: 0, d: 'M18.9 1.5h3.68l-8.04 9.19L24 22.5h-7.4l-5.8-7.58-6.63 7.58H.49l8.6-9.83L0 1.5h7.59l5.24 6.93zM17.6 20.3h2.04L6.49 3.6H4.3z', fill: 'currentColor' })]),
  Github: raw([h('path', { key: 0, d: 'M12 2C6.48 2 2 6.58 2 12.25c0 4.53 2.87 8.37 6.84 9.73.5.1.68-.22.68-.49l-.01-1.7c-2.78.62-3.37-1.36-3.37-1.36-.46-1.18-1.11-1.5-1.11-1.5-.91-.63.07-.62.07-.62 1 .07 1.53 1.06 1.53 1.06.9 1.57 2.34 1.12 2.91.85.09-.66.35-1.12.63-1.37-2.22-.26-4.55-1.14-4.55-5.06 0-1.12.39-2.03 1.03-2.75-.1-.26-.45-1.3.1-2.71 0 0 .84-.28 2.75 1.05a9.3 9.3 0 0 1 5 0c1.91-1.33 2.75-1.05 2.75-1.05.55 1.41.2 2.45.1 2.71.64.72 1.03 1.63 1.03 2.75 0 3.93-2.34 4.8-4.57 5.05.36.32.68.94.68 1.9l-.01 2.82c0 .27.18.6.69.49A10.26 10.26 0 0 0 22 12.25C22 6.58 17.52 2 12 2z', fill: 'currentColor' })]),
};

// Qity bracket-Q mark (from DS svg), recolorable via currentColor
const QMark = (props) => h('svg', Object.assign({ viewBox: '0 0 25 29', fill: 'none' }, props),
  h('path', { d: 'M 24.999 28.202 C 25.032 27.71 24.497 27.25 23.829 27.25 C 21.19 27.219 18.951 26.544 14.274 23.32 C 14.073 23.197 14.006 23.105 14.006 23.013 C 14.006 22.89 14.24 22.829 14.541 22.767 C 20.521 21.785 24.464 17.486 24.464 11.499 C 24.464 4.837 19.285 0.047 12.336 0.047 C 5.386 0.047 0.174 4.837 0.174 11.499 C 0.174 16.872 3.315 20.772 7.925 22.276 C 9.763 22.859 10.732 23.074 12.336 24.21 C 16.011 26.789 19.519 28.969 23.662 29 C 24.598 29 24.932 28.724 24.999 28.202 Z M 12.336 21.171 C 6.823 21.171 2.379 17.333 2.379 11.499 C 2.379 8.859 -1.129 2.657 0.375 0.999 C 2.212 -1.028 9.295 1.736 12.336 1.736 C 15.343 1.736 22.092 -1.335 23.929 0.692 C 25.433 2.35 22.292 8.859 22.292 11.499 C 22.292 17.333 17.849 21.171 12.336 21.171 Z', fill: 'currentColor' }));

/* ---------- Content ---------- */
const PILLARS = [
  { n: '01', icon: 'Handshake', title: 'Goodbye fragmented tools', body: 'One source of truth for every quality record. No more fragmented Word docs, Excel matrices, or email attachments — evidence flows directly from your team\u2019s work in Jira.' },
  { n: '02', icon: 'Robot', title: 'Pipeline automations', body: 'Generate regulatory evidence from your source code and build pipeline. Update design documents, specs, tests, SBOM, vulnerabilities — keep source code and documentation in sync.' },
  { n: '03', icon: 'Sparkles', title: 'AI agents', body: 'Special-purpose AI agents designed by industry experts, based on best practices, aware of regulations.\nWorks with Rovo - Atlassian\u2019s built-in AI, Claude, Gemini and ChatGPT.' },
];

const MODULES = [
  { icon: 'FileCheck', tile: 'doc-control', tint: 'P', title: 'Document Control', blurb: 'Version control, approval workflows, and audit trails for every controlled document.', feats: ['Peer and QA approval cycles', 'Part 11 e-signatures with OTP email', 'Scheduled periodic reviews'] },
  { icon: 'Ruler', tile: 'design-control', tint: 'B', title: 'Design Control', blurb: 'Manage and trace stakeholder needs, requirements, specifications, tests.', feats: ['Auto-generated design traceability matrix', 'Identifies traceability gaps and orphaned items', 'Link to products, parts, software items'] },
  { icon: 'AlertTriangle', tile: 'risk', tint: 'R', title: 'Safety Risks', blurb: 'Identify, assess, and mitigate risk on the work item itself. ISO 14971 ready.', feats: ['Safety characteristics & hazard analysis', 'Design, process & use risks', 'Live risk register & matrices'] },
  { icon: 'Repeat', tile: 'plm', tint: 'T', title: 'Product Lifecycle', blurb: 'From concept to end-of-life \u2014 phase and status visibility, plus BOM, parts and components.', feats: ['Phase / gate tracking', 'BOM, parts & component management', 'Change management'] },
  { icon: 'Cap', tile: 'training', tint: 'G', title: 'Training', blurb: 'Role and curricula-based training with verification of effectiveness.', feats: ['Role-based training plans', 'Competency dashboards', 'Read-and-understood sign-off'] },
  { icon: 'ClipboardCheck', tile: 'quality-events', tint: 'Y', title: 'Quality Events', blurb: 'Manage CAPA, nonconformities, deviations and concessions.', feats: ['CAPA with corrective & preventive actions', 'Nonconformity, deviation & concession records', 'Always-on evidence collection'] },
];

const FLOW = [
  { stage: 'Design', n: '1', tools: [{ nm: 'Figma', c: '#F24E1E', l: 'F' }, { nm: 'Altium', c: '#A5915F', l: 'A' }, { nm: 'Solidworks', c: '#E1141E', l: 'S' }] },
  { stage: 'Develop', n: '2', tools: [{ nm: 'GitHub', c: '#1B1F24', l: 'G' }, { nm: 'GitLab', c: '#FC6D26', l: 'G' }, { nm: 'Bitbucket', c: '#0052CC', l: 'B' }] },
  { stage: 'Verify', n: '3', tools: [{ nm: 'CI/CD pipelines', c: '#2684FF', l: 'CI' }, { nm: 'Aikido security', c: '#5C2D91', l: 'Ai' }, { nm: 'SBOM & scans', c: '#36B37E', l: 'S' }] },
  { stage: 'Comply', n: '4', dest: true, tools: [{ nm: 'Jira & Confluence', c: '#2684FF', l: 'J' }, { nm: 'Rovo · Claude · ChatGPT · Gemini', c: '#6554C0', l: 'AI' }, { nm: 'Qity on Jira & Confluence', c: '#0C7A48', l: 'Q', q: true }] },
];

const INTG_GROUPS = [
  { cat: 'Design', tools: FLOW[0].tools },
  { cat: 'Develop', tools: FLOW[1].tools },
  { cat: 'Security & CI/CD', tools: FLOW[2].tools },
  { cat: 'Atlassian + AI', tools: FLOW[3].tools },
];

const USECASES = [
  {
    id: 'eng', tab: 'Engineering', tabIcon: 'Code',
    prob: '',
    title: 'Manage design and risks in your everyday Jira agile workflow.',
    body: 'Manage design controls right inside the Jira agile workflow your engineers already use \u2014 connected to Figma, Altium, Solidworks, GitHub and more.\nYour CI pipelines produce regulatory evidence automatically, with source code as the source of truth, maintaining consistency between code and documentation.',
    benefits: ['Trace stakeholder needs, requirements, specifications and tests', 'Integrated with the tools you already use', 'CI pipelines produce regulatory records', 'Source code is the source of truth'],
    visual: 'shot', shot: 'assets/shots/design-control.png', shotLabel: 'Design Control \u2014 Jira',
  },
  {
    id: 'quality', tab: 'Quality', tabIcon: 'ClipboardCheck',
    prob: '',
    title: 'Audit-ready every day \u2014 not just during audit prep.',
    body: 'Manual traceability matrices, version chaos, documents scattered across email and SharePoint. Qity generates traceability from Jira automatically, so you\u2019re audit-ready the moment anyone asks.',
    benefits: ['Audit-ready at any moment', 'No more manual traceability matrices', 'A single, real-time source of truth'],
    visual: 'shot', shot: 'assets/shots/quality-events.png', shotLabel: 'Quality Events · CAPA — Jira',
  },
  {
    id: 'pm', tab: 'Management', tabIcon: 'BarChart',
    prob: '',
    title: 'Free your teams to focus on what really matters \u2014 the product.',
    body: 'When compliance is a by-product of everyday work, teams stop firefighting paperwork and get back to innovating, building and shipping. Every requirement, risk, test and change is a native Jira item, so regulatory evidence accrues automatically as the work happens.\nTrack it all in Gantt charts, dashboards and management summaries \u2014 and keep every team aligned to shared goals and milestones.',
    benefits: ['Teams freed from compliance overhead', 'Everything tracked as native Jira items', 'Gantt charts, dashboards & management summaries', 'Teams aligned to goals and milestones'],
    visual: 'shot', shot: 'assets/shots/product-lifecycle.png', shotLabel: 'Product Lifecycle \u2014 Jira', focal: 'top right',
  },
];

const TESTIMONIALS = [
  {
    quote: 'Qity transformed our workflow by making connections between design controls, risk and change management instantly visible in one ecosystem \u2014 eliminating hours of manual traceability work. Real-time visibility keeps us confident and audit-ready at any moment.',
    name: 'Rien De Wachter',
    role: 'Quality Assurance & Regulatory Affairs Manager at Mantyx',
    avatar: 'assets/avatar-rien.png',
    stats: [{ num: 'Zero', lbl: 'Hours spent maintaining traceability matrices' }, { num: 'Anytime', lbl: 'Audit-ready with real-time traceability' }],
  },
  {
    quote: 'We used to manage risk in disparate spreadsheets. Qity changed that: hazards, harms, safety characteristics, risk controls, and verification are fully traceable and always up to date \u2014 so when a regulatory review comes, we\u2019re ready.',
    name: 'Dan Scherrer',
    role: 'COO at Wyss Zurich',
    avatar: 'assets/avatar-dan.jpeg',
    stats: [{ num: '100%', lbl: 'Requirements traced to tests & risks' }, { num: '1', lbl: 'Source of truth across the QMS' }],
  },
  {
    quote: 'Our quality system finally lives where the work happens. Documents, training and change records connect automatically, so our small team stays compliant without drowning in admin \u2014 and reviewers always know exactly what changed and why.',
    name: 'In\u00e8s Lejeune',
    role: 'Head of Quality Assurance at Agricells',
    avatar: 'assets/avatar-ines.jpeg',
    stats: [{ num: 'One', lbl: 'Connected system for docs, training & change' }, { num: 'Hours saved', lbl: 'Every week on quality admin' }],
  },
  {
    quote: 'Qity digitized our lab workflow \u2014 protocols and results now flow straight into our quality processes, deviations and nonconformities are captured as they happen. Quality became part of the daily workflow.',
    name: 'Kevin Braeckmans',
    role: 'CEO & co-founder at Trince',
    avatar: 'assets/avatar-kevin.jpeg',
    stats: [{ num: 'One', lbl: 'Digital flow from lab bench to quality record' }, { num: 'At the source', lbl: 'Deviations & nonconformities captured as they happen' }],
  },
];

const STANDARDS = [
  { label: 'ISO 9001', img: 'iso' },
  { label: 'ISO 13485', img: 'iso' },
  { label: 'ISO 27001', img: 'iso' },
  { label: 'EU MDR / IVDR', img: 'eu' },
  { label: 'GDPR', img: 'eu' },
  { label: 'FDA', img: 'fda' },
  { label: 'GxP', icon: 'Beaker' },
];

const NAV_LINKS = [
  { label: 'Products', href: '#product' },
  { label: 'Integrations', href: '#compliance' },
  { label: 'Smart docs', href: '#documents' },
  { label: 'Use cases', href: '#usecases' },
  { label: 'Customers', href: '#customers' },
];

const FAQS = [
  { q: 'What is the price of the apps?', a: 'Pricing depends on the Qity apps you choose, the size of your Atlassian site, and the level of implementation or migration support you need. Contact us for a quote.' },
  { q: 'Can the data from my existing quality system be migrated?', a: 'In most cases, yes. Data from an existing quality system can usually be assessed, mapped, cleaned, and migrated into the Qity apps, depending on the source system\u2019s structure, quality, and export options.\nAlternatively, planning and documenting the transition to a new system may suffice, transferring active projects and archiving inactive ones. We would be happy to devise a plan together.' },
  { q: 'Can my Word files be migrated?', a: 'Yes, Word documents can usually be migrated, but the best approach depends on the intended use. They may be converted into Confluence pages for controlled, searchable content, or kept as attachments where the original file format must be preserved.' },
  { q: 'Which file types are supported?', a: 'Qity can support any file type. Because we run on Atlassian Cloud, files are typically managed as Jira and Confluence attachments, so teams can store, share, and collaborate on everything from Office documents and PDFs to images and exports.' },
  { q: 'Are Qity\u2019s apps validated?', a: 'Qity is designed for regulated quality environments, with validation responsibilities shared between Qity and the customer. Each new release comes with release notes, and Qity can provide functional test plans and test reports on demand, for example in preparation for an audit. Each Qity app also includes a built-in automated IQ. When custom configuration changes are made, such as workflows, fields, or screens, those changes require validation; Qity can provide this as a service. To support customers, Qity also provides guidance documentation, checklists, and templates.' },
  { q: 'Are the apps FDA 21 CFR Part 11 compliant?', a: 'Qity apps support FDA 21 CFR Part 11 compliant electronic signatures through email one-time password (OTP). Part 11 compliance also depends on the system being configured and operated with the right controls, including unique user accounts, access management, audit trails, controlled records, appropriate procedures, and validation for the customer\u2019s intended use. Qity offers a guidance document and checklist.' },
  { q: 'Do I need a paid Jira & Confluence subscription?', a: 'Yes. Qity is built on the Atlassian Cloud platform, so customers need an Atlassian Cloud site with the Jira and/or Confluence products required by the selected Qity apps. In practice, most business deployments use paid Atlassian plans to access the administration, storage, security, audit, support, and governance features needed for professional or regulated use. For companies that are in a commercial phase and operating in regulated environments, we recommend Premium subscriptions.' },
  { q: 'Is customer support included in the license fee?', a: 'Basic support is available through the support portal and focuses on app installation, usage guidance, and reporting issues or bugs. Additional Premium support packages can be purchased for personalized services, such as data migration, customization, implementation or validation of the quality system.' },
  { q: 'Where is my data stored?', a: 'All Qity apps bear the \u201cRuns on Atlassian\u201d badge, which means that all data is stored in Atlassian Cloud. Atlassian Cloud offers data residency controls for supported products, allowing eligible product data to be pinned to specific regions such as the EU, US, Australia, Canada, Germany, Japan, Singapore, South Korea, Switzerland, India, or the UK, depending on the product and plan.' },
  { q: 'Will my data be used to train the AI models?', a: 'Qity relies on Atlassian AI only, including Rovo and Forge LLM. Customer data is not used to train AI models unless customers explicitly choose to provide feedback or otherwise opt in where applicable. Data is retained only for as long as needed to provide the service, in line with customer and administrator settings and applicable contractual, legal, and compliance requirements.' },
  { q: 'Will I receive software updates?', a: 'Yes. Atlassian Cloud is regularly updated by Atlassian, so customers receive platform improvements, security updates, and new features without managing servers. Qity app updates are delivered through the cloud model, helping customers stay current with product improvements and fixes. Qity provides release notes and advance notice for major changes. Soon, the built-in IQ can also be scheduled to run periodically, automatically re-verifying the integrity and configuration of the installed apps. For validated customers, Qity can provide guidance on Atlassian release tracks and the use of sandboxes to assess changes before they are introduced in production.' },
  { q: 'Why would I want our quality system on Atlassian Cloud?', a: 'As one of the industry leaders in work management, Atlassian Cloud provides a modern, secure, and scalable foundation. It combines collaboration, documentation, workflow automation, permissions, auditability, integrations, and enterprise administration in a platform many teams already use. This means quality processes can be closer to day-to-day work, easier to adopt, and faster to improve, while still supporting the controls needed for regulated environments.' },
];

/* ---------- Traceability graph (Rovo-style flow animation) ---------- */
// Atlassian Rovo flow palette — multi-hue, used for the animated connection comets
const ROVO = ['#00B8D9', '#1D7AFC', '#8270DB', '#DA62AC', '#2ABB7F', '#FF8F73', '#9F8FEF', '#1D9AAA'];

// canvas is authored on a 1060 x 620 viewBox; positions below are in those units
const TRACE_VB = { w: 1060, h: 620 };

const TRACE_TOOLS = [
  { id: 'claude', nm: 'Claude', c: '#D97757', l: 'C', img: 'claude', x: 156, y: 82 },
  { id: 'figma', nm: 'Figma', c: '#F24E1E', l: 'F', img: 'figma', x: 232, y: 150 },
  { id: 'altium', nm: 'Altium', c: '#A5915F', l: 'A', img: 'altium', x: 140, y: 224 },
  { id: 'solidworks', nm: 'Solidworks', c: '#E1141E', l: 'S', img: 'solidworks', x: 248, y: 296 },
  { id: 'aikido', nm: 'Aikido', c: '#5C2D91', l: 'Ai', img: 'aikido', x: 150, y: 372 },
  { id: 'bitbucket', nm: 'Bitbucket', c: '#0052CC', l: 'B', img: 'bitbucket', x: 244, y: 452 },
  { id: 'github', nm: 'GitHub', c: '#1B1F24', l: 'G', img: 'github', x: 150, y: 520 },
];

const TRACE_NODES = [
  { id: 'complaint', label: 'Complaint', icon: 'customer', c: '#FF7452', x: 318, y: 520 },
  { id: 'nonconformity', label: 'Nonconformity', icon: 'nonconformity', c: '#FF5630', x: 486, y: 548 },
  { id: 'capa', label: 'CAPA', icon: 'capa', c: '#FF5630', x: 650, y: 432 },
  { id: 'risk', label: 'Risk', icon: 'risk', c: '#FF8B00', x: 596, y: 300 },
  { id: 'requirement', label: 'Requirement', icon: 'requirement', c: '#6554C0', x: 384, y: 150 },
  { id: 'specification', label: 'Specification', icon: 'specification', c: '#2684FF', x: 566, y: 116 },
  { id: 'test', label: 'Test', icon: 'test', c: '#36B37E', x: 760, y: 150 },
  { id: 'release', label: 'Release', lucide: 'Rocket', c: '#22A06B', x: 940, y: 122 },
  { id: 'stakeholder', label: 'Stakeholder Need', icon: 'stakeholder-need', c: '#DA62AC', x: 300, y: 304 },
  { id: 'bom', label: 'BOM', icon: 'bom', c: '#2684FF', x: 452, y: 424 },
  { id: 'document', label: 'Document', icon: 'document', c: '#2684FF', x: 822, y: 312 },
  { id: 'file', label: 'Files', lucide: 'FileText', c: '#5E6C84', x: 788, y: 470 },
  { id: 'change', label: 'Engineering Change', icon: 'change', c: '#FF8B00', x: 946, y: 452 },
];

/* Wide, clipped variant — same graph (ids/labels/edges reused) re-laid-out on a
   short, full-width canvas. A few nodes sit beyond the visible band so their
   connection lines run off-frame to elements that aren't on screen. */
const TRACE_VB_W = { w: 1660, h: 640 };

const TRACE_TOOLS_W = [
  { id: 'claude', nm: 'Claude', c: '#D97757', l: 'C', img: 'claude', x: 124, y: -6 },
  { id: 'figma', nm: 'Figma', c: '#F24E1E', l: 'F', img: 'figma', x: 214, y: 152 },
  { id: 'altium', nm: 'Altium', c: '#A5915F', l: 'A', img: 'altium', x: 72, y: 272 },
  { id: 'solidworks', nm: 'Solidworks', c: '#E1141E', l: 'S', img: 'solidworks', x: 224, y: 412 },
  { id: 'aikido', nm: 'Aikido', c: '#5C2D91', l: 'Ai', img: 'aikido', x: 96, y: 532 },
  { id: 'bitbucket', nm: 'Bitbucket', c: '#0052CC', l: 'B', img: 'bitbucket', x: 222, y: 600 },
  { id: 'github', nm: 'GitHub', c: '#1B1F24', l: 'G', img: 'github', x: 86, y: 724 },
];

const TRACE_NODES_W = [
  { id: 'complaint', label: 'Complaint', icon: 'customer', c: '#FF7452', x: 332, y: 548 },
  { id: 'stakeholder', label: 'Stakeholder Need', icon: 'stakeholder-need', c: '#DA62AC', x: 376, y: 104 },
  { id: 'nonconformity', label: 'Nonconformity', icon: 'nonconformity', c: '#FF5630', x: 482, y: 372 },
  { id: 'requirement', label: 'Requirement', icon: 'requirement', c: '#6554C0', x: 560, y: 226 },
  { id: 'risk', label: 'Risk', icon: 'risk', c: '#FF8B00', x: 652, y: 486 },
  { id: 'capa', label: 'CAPA', icon: 'capa', c: '#FF5630', x: 602, y: 614 },
  { id: 'bom', label: 'BOM', icon: 'bom', c: '#2684FF', x: 642, y: -22 },
  { id: 'specification', label: 'Specification', icon: 'specification', c: '#2684FF', x: 838, y: 316 },
  { id: 'test', label: 'Test', icon: 'test', c: '#36B37E', x: 1028, y: 150 },
  { id: 'document', label: 'Document', icon: 'document', c: '#2684FF', x: 1178, y: 496 },
  { id: 'release', label: 'Release', lucide: 'Rocket', c: '#22A06B', x: 1268, y: 92 },
  { id: 'file', label: 'Files', lucide: 'FileText', c: '#5E6C84', x: 1378, y: 588 },
  { id: 'change', label: 'Engineering Change', icon: 'change', c: '#FF8B00', x: 1612, y: 408 },
];

// directed edges [from, to]
const TRACE_EDGES = (() => {
  const e = [];
  // design + PLM tools feed Specification
  ['figma', 'altium', 'solidworks', 'aikido'].forEach((s) => e.push([s, 'specification']));
  // Claude (AI) connects to Requirement, Specification, Test
  ['requirement', 'specification', 'test'].forEach((d) => e.push(['claude', d]));
  // source control, CI/CD + security feed BOM, Risk, Test
  ['bitbucket', 'github', 'aikido'].forEach((s) => ['bom', 'risk', 'test'].forEach((d) => e.push([s, d])));
  // quality loop + forward traceability spine
  [['complaint', 'nonconformity'], ['nonconformity', 'capa'], ['capa', 'risk'], ['risk', 'requirement'],
  ['requirement', 'specification'], ['specification', 'test'], ['test', 'release']].forEach((p) => e.push(p));
  // document aggregation
  ['stakeholder', 'requirement', 'specification', 'test'].forEach((s) => e.push([s, 'document']));
  // engineering change
  ['document', 'file', 'bom'].forEach((s) => e.push([s, 'change']));
  // release also flows into Files and Engineering Change
  e.push(['release', 'file'], ['release', 'change']);
  return e;
})();

// Full work-type set for the 3D orbiting sphere. The first group keep the ids
// referenced by TRACE_EDGES (so tool→item relationships still resolve); the rest
// are decorative mass so the sphere reads as an near-infinite stream of work types.
const ORBIT_NODES = [
  { id: 'requirement', label: 'Requirement', icon: 'requirement', c: '#6554C0', conn: true },
  { id: 'audit', label: 'Audit', icon: 'audit', c: '#2684FF' },
  { id: 'risk', label: 'Risk', icon: 'risk', c: '#FF8B00', conn: true },
  { id: 'hazard', label: 'Hazard', icon: 'hazard', c: '#6554C0' },
  { id: 'specification', label: 'Specification', icon: 'specification', c: '#2684FF', conn: true },
  { id: 'deviation', label: 'Deviation', icon: 'deviation', c: '#FF5630' },
  { id: 'test', label: 'Test', icon: 'test', c: '#36B37E', conn: true },
  { id: 'inspection', label: 'Inspection', icon: 'inspection', c: '#36B37E' },
  { id: 'capa', label: 'CAPA', icon: 'capa', c: '#FF5630', conn: true },
  { id: 'finding', label: 'Finding', icon: 'finding', c: '#FF8B00' },
  { id: 'nonconformity', label: 'Nonconformity', icon: 'nonconformity', c: '#FF5630', conn: true },
  { id: 'calibration', label: 'Calibration', icon: 'calibration', c: '#36B37E' },
  { id: 'complaint', label: 'Complaint', icon: 'customer', c: '#FF7452', conn: true },
  { id: 'customer-property', label: 'Customer Property', icon: 'customer-property', c: '#FF7452' },
  { id: 'document', label: 'Document', icon: 'document', c: '#2684FF', conn: true },
  { id: 'clause', label: 'Clause', icon: 'clause', c: '#5E6C84' },
  { id: 'change', label: 'Engineering Change', icon: 'change', c: '#FF8B00', conn: true },
  { id: 'batch', label: 'Batch', icon: 'batch', c: '#00B8D9' },
  { id: 'stakeholder', label: 'Stakeholder Need', icon: 'stakeholder-need', c: '#DA62AC', conn: true },
  { id: 'nps', label: 'NPS', icon: 'nps', c: '#DA62AC' },
  { id: 'bom', label: 'BOM', icon: 'bom', c: '#2684FF', conn: true },
  { id: 'part', label: 'Part', icon: 'part', c: '#5E6C84' },
  { id: 'release', label: 'Release', icon: null, lucide: 'Rocket', c: '#22A06B', conn: true },
  { id: 'submission', label: 'Submission', icon: 'submission', c: '#1D7AFC' },
  { id: 'file', label: 'Files', icon: null, lucide: 'FileText', c: '#5E6C84', conn: true },
  { id: 'regulation', label: 'Regulation', icon: 'regulation', c: '#5E6C84' },
  { id: 'standard', label: 'Standard', icon: 'standard', c: '#2684FF' },
  { id: 'supplier', label: 'Supplier', icon: 'supplier', c: '#00B8D9' },
  { id: 'purchase', label: 'Purchase', icon: 'purchase', c: '#22A06B' },
  { id: 'order', label: 'Order', icon: 'order', c: '#2684FF' },
  { id: 'work-order', label: 'Work Order', icon: 'work-order', c: '#FF8B00' },
  { id: 'sw-item', label: 'SW Item', icon: 'sw-item', c: '#6554C0' },
  { id: 'soup', label: 'SOUP', icon: 'soup', c: '#8270DB' },
  { id: 'vulnerability', label: 'Vulnerability', icon: 'vulnerability', c: '#FF5630' },
  { id: 'product', label: 'Product', icon: 'product', c: '#2684FF' },
  { id: 'training-exam', label: 'Training Exam', icon: 'training-exam', c: '#FFAB00' },
  { id: 'training-record', label: 'Training Record', icon: 'training-record', c: '#36B37E' },
  { id: 'training-session', label: 'Training Session', icon: 'training-session', c: '#00B8D9' },
  { id: 'vial', label: 'Vial', icon: 'vial', c: '#DA62AC' },
  { id: 'liquid-sample', label: 'Liquid Sample', icon: 'liquid-sample', c: '#00B8D9' },
  { id: 'activity', label: 'Activity', icon: 'activity', c: '#6554C0' },
  { id: 'harm', label: 'Harm', icon: 'harm', c: '#FF5630' },
  { id: 'nonconformity-2', label: 'Nonconformity', icon: 'nonconformity-2', c: '#FF5630' },
];

Object.assign(window, {
  Icons, QMark, PILLARS, MODULES, FLOW, INTG_GROUPS, USECASES, TESTIMONIALS, STANDARDS, NAV_LINKS, FAQS,
  ROVO, TRACE_VB, TRACE_TOOLS, TRACE_NODES, TRACE_EDGES, ORBIT_NODES,
  TRACE_VB_W, TRACE_TOOLS_W, TRACE_NODES_W,
});
