{
  "version": "0.2.0-preview.1",
  "content_digest": "70ac710f4d22dce040e7ac593379ba8aca9dcb59a0b9c0f839819cae0e2bb721",
  "status": "preview",
  "authority": {
    "repository": "cloakedinc/design",
    "path": "packages/design-system",
    "catalog": "packages/design-system/catalog.json",
    "status": "preview"
  },
  "provenance": {
    "repo": "cloakedinc/automation",
    "commit": "f96f416e1c3bfbfaffcd155a88b87b18b8bb25f1",
    "path": "packages/design-system",
    "imported_spec_status": "approved"
  },
  "adaptations": [
    {
      "id": "button-content-gap",
      "status": "preview",
      "description": "Use the specification's 4px content gap instead of the inherited 8px implementation gap."
    },
    {
      "id": "keyboard-focus",
      "status": "preview",
      "description": "Add visible Button and Input keyboard focus and an overridable inset focus default for shared button resets, including FAQ cards and ListItem rows."
    },
    {
      "id": "supporting-text-contrast",
      "status": "preview",
      "description": "Map light secondary text to the existing grey-04-strong primitive for readable helper text on white and cream."
    },
    {
      "id": "danger-text-contrast",
      "status": "preview",
      "description": "Separate readable danger text/borders from destructive fills; preserve the primary danger-button fill and label pair."
    },
    {
      "id": "preview-status",
      "status": "preview",
      "description": "Local components, specs and token adaptations await human sign-off; upstream approved status is provenance only."
    },
    {
      "id": "motion-comparison-accessibility",
      "status": "preview",
      "description": "Preserve the original MotionShowcase comparisons while requiring explicit replay, responding to live reduced-motion changes, and keeping duration tracks usable on small screens."
    },
    {
      "id": "list-item-ownership",
      "status": "preview",
      "description": "List owns listitem wrappers for its content rows, while section labels stay outside the row count and standalone rows retain their existing semantics."
    },
    {
      "id": "card-delta-text-contrast",
      "status": "preview",
      "description": "Mix Card.Delta foregrounds from 60% existing tone solid and 40% primary text for readable contrast in both themes; preserve the four original tone fills."
    },
    {
      "id": "carousel-keyboard-access",
      "status": "preview",
      "description": "Keep all native-scrolling carousel slide controls exposed to assistive technology and keyboard navigation; pause autoplay while focus is inside the carousel."
    }
  ],
  "id": "linechart",
  "name": "LineChart",
  "category": "Visualizations",
  "contract_status": "preview",
  "contract_kind": "source-derived",
  "review": {
    "local_status": "not-reviewed",
    "source_approval": null,
    "imported_spec_status": "approved",
    "spec_origin": "imported-adapted",
    "local_spec_source_status": "approved",
    "imported_source_revision": "f96f416e1c3bfbfaffcd155a88b87b18b8bb25f1",
    "note": "Inherited specification status is provenance, not approval of the current local implementation or extracted contract."
  },
  "approval": "required",
  "visual_reference": {
    "stories": [
      {
        "id": "cloaked-design-system-visualizations-linechart--default",
        "name": "Default",
        "title": "Cloaked Design System/Visualizations/LineChart",
        "exportName": "Default",
        "source_path": "packages/design-system/src/components/visualizations/LineChart/LineChart.stories.tsx",
        "source_digest": "ba92cb90ba71208f429fa4c43249813dfb3f3847977edb7f636f22e072675d2c",
        "status": "preview",
        "local_url": "/storybook/iframe.html?id=cloaked-design-system-visualizations-linechart--default&viewMode=story"
      },
      {
        "id": "cloaked-design-system-visualizations-linechart--single-series",
        "name": "Single Series",
        "title": "Cloaked Design System/Visualizations/LineChart",
        "exportName": "SingleSeries",
        "source_path": "packages/design-system/src/components/visualizations/LineChart/LineChart.stories.tsx",
        "source_digest": "ba92cb90ba71208f429fa4c43249813dfb3f3847977edb7f636f22e072675d2c",
        "status": "preview",
        "local_url": "/storybook/iframe.html?id=cloaked-design-system-visualizations-linechart--single-series&viewMode=story"
      },
      {
        "id": "cloaked-design-system-visualizations-linechart--secondary-tone",
        "name": "Secondary Tone",
        "title": "Cloaked Design System/Visualizations/LineChart",
        "exportName": "SecondaryTone",
        "source_path": "packages/design-system/src/components/visualizations/LineChart/LineChart.stories.tsx",
        "source_digest": "ba92cb90ba71208f429fa4c43249813dfb3f3847977edb7f636f22e072675d2c",
        "status": "preview",
        "local_url": "/storybook/iframe.html?id=cloaked-design-system-visualizations-linechart--secondary-tone&viewMode=story"
      },
      {
        "id": "cloaked-design-system-visualizations-linechart--ghost-series",
        "name": "Ghost Series",
        "title": "Cloaked Design System/Visualizations/LineChart",
        "exportName": "GhostSeries",
        "source_path": "packages/design-system/src/components/visualizations/LineChart/LineChart.stories.tsx",
        "source_digest": "ba92cb90ba71208f429fa4c43249813dfb3f3847977edb7f636f22e072675d2c",
        "status": "preview",
        "local_url": "/storybook/iframe.html?id=cloaked-design-system-visualizations-linechart--ghost-series&viewMode=story"
      },
      {
        "id": "cloaked-design-system-visualizations-linechart--tone-matrix",
        "name": "Tone Matrix",
        "title": "Cloaked Design System/Visualizations/LineChart",
        "exportName": "ToneMatrix",
        "source_path": "packages/design-system/src/components/visualizations/LineChart/LineChart.stories.tsx",
        "source_digest": "ba92cb90ba71208f429fa4c43249813dfb3f3847977edb7f636f22e072675d2c",
        "status": "preview",
        "local_url": "/storybook/iframe.html?id=cloaked-design-system-visualizations-linechart--tone-matrix&viewMode=story"
      },
      {
        "id": "cloaked-design-system-visualizations-linechart--many-series",
        "name": "Many Series",
        "title": "Cloaked Design System/Visualizations/LineChart",
        "exportName": "ManySeries",
        "source_path": "packages/design-system/src/components/visualizations/LineChart/LineChart.stories.tsx",
        "source_digest": "ba92cb90ba71208f429fa4c43249813dfb3f3847977edb7f636f22e072675d2c",
        "status": "preview",
        "local_url": "/storybook/iframe.html?id=cloaked-design-system-visualizations-linechart--many-series&viewMode=story"
      },
      {
        "id": "cloaked-design-system-visualizations-linechart--empty",
        "name": "Empty",
        "title": "Cloaked Design System/Visualizations/LineChart",
        "exportName": "Empty",
        "source_path": "packages/design-system/src/components/visualizations/LineChart/LineChart.stories.tsx",
        "source_digest": "ba92cb90ba71208f429fa4c43249813dfb3f3847977edb7f636f22e072675d2c",
        "status": "preview",
        "local_url": "/storybook/iframe.html?id=cloaked-design-system-visualizations-linechart--empty&viewMode=story"
      },
      {
        "id": "cloaked-design-system-visualizations-linechart--single-point",
        "name": "Single Point",
        "title": "Cloaked Design System/Visualizations/LineChart",
        "exportName": "SinglePoint",
        "source_path": "packages/design-system/src/components/visualizations/LineChart/LineChart.stories.tsx",
        "source_digest": "ba92cb90ba71208f429fa4c43249813dfb3f3847977edb7f636f22e072675d2c",
        "status": "preview",
        "local_url": "/storybook/iframe.html?id=cloaked-design-system-visualizations-linechart--single-point&viewMode=story"
      },
      {
        "id": "cloaked-design-system-visualizations-linechart--smoothed-and-trimmed",
        "name": "Smoothed And Trimmed",
        "title": "Cloaked Design System/Visualizations/LineChart",
        "exportName": "SmoothedAndTrimmed",
        "source_path": "packages/design-system/src/components/visualizations/LineChart/LineChart.stories.tsx",
        "source_digest": "ba92cb90ba71208f429fa4c43249813dfb3f3847977edb7f636f22e072675d2c",
        "status": "preview",
        "local_url": "/storybook/iframe.html?id=cloaked-design-system-visualizations-linechart--smoothed-and-trimmed&viewMode=story"
      },
      {
        "id": "cloaked-design-system-visualizations-linechart--dark-theme",
        "name": "Dark Theme",
        "title": "Cloaked Design System/Visualizations/LineChart",
        "exportName": "DarkTheme",
        "source_path": "packages/design-system/src/components/visualizations/LineChart/LineChart.stories.tsx",
        "source_digest": "ba92cb90ba71208f429fa4c43249813dfb3f3847977edb7f636f22e072675d2c",
        "status": "preview",
        "local_url": "/storybook/iframe.html?id=cloaked-design-system-visualizations-linechart--dark-theme&viewMode=story"
      }
    ],
    "name": "LineChart",
    "id": "linechart",
    "category": "Visualizations"
  },
  "stories_source": {
    "path": "packages/design-system/src/components/visualizations/LineChart/LineChart.stories.tsx",
    "code": "import React from 'react';\nimport type { Meta, StoryObj } from '@storybook/react-vite';\nimport { LineChart } from './LineChart';\nimport { HStack } from '../../layout/HStack/HStack';\nimport { VStack } from '../../layout/VStack/VStack';\nimport { Text } from '../../primitives/Text/Text';\nimport { RISK_TONES } from '../../../styles/riskTone';\nimport { SERIES_TONES } from '../../../styles/seriesTone';\nimport { disabledControl } from '../../../storybook/controlOptions';\nimport type { DataVisualizationSeries, DataVisualizationTone } from '../types';\n\nconst ALL_TONES = [...SERIES_TONES, ...RISK_TONES] as const satisfies readonly DataVisualizationTone[];\n\nconst series: DataVisualizationSeries[] = [\n    { id: 'full_name', tone: 'good', values: [4, 10, 18, 28, 41, 58, 76, 96, 118, 140, 164, 190] },\n    { id: 'email_addresses', tone: 'brand', values: [2, 6, 14, 25, 38, 52, 68, 85, 104, 126, 142, 168] },\n    { id: 'addresses', tone: 'excellent', values: [1, 4, 10, 18, 30, 42, 58, 72, 86, 98, 110, 128] },\n    { id: 'phone_numbers', tone: 'fair', values: [0, 3, 7, 13, 22, 30, 39, 48, 56, 63, 71, 80] },\n    { id: 'relatives', tone: 'high', values: [0, 1, 4, 9, 14, 20, 27, 34, 42, 50, 58, 68] },\n];\n\nconst manySeries: DataVisualizationSeries[] = [\n    ...series,\n    { id: 'aliases', tone: 'critical', values: [0, 2, 5, 11, 19, 27, 36, 46, 57, 69, 82, 96] },\n    { id: 'usernames', tone: 'primary', values: [3, 8, 16, 24, 34, 47, 59, 73, 88, 104, 121, 139] },\n];\n\nconst rising = [4, 10, 18, 28, 41, 58, 76, 96, 118, 140, 164, 190];\n\nconst meta: Meta<typeof LineChart> = {\n    title: 'Cloaked Design System/Visualizations/LineChart',\n    component: LineChart,\n    parameters: {\n        a11y: { test: 'error' },\n        docs: {\n            description: {\n                component:\n                    'One or more smoothed trend lines over time — the chart for a continuous trajectory ' +\n                    'and for overlaying several series at once. Prefer it over `BarChart` when the shape ' +\n                    'of the trend matters more than discrete magnitudes and there is no scrubbing; over ' +\n                    '`CategoryBars` when the x-axis is time, not categories. Distinguish `series` with ' +\n                    '`tone` — the 3 non-semantic `SERIES_TONES` (`brand`/`primary`/`secondary`) for ' +\n                    'neutral multi-line identity, or the 5 `RISK_TONES` (`excellent`→`critical`) when ' +\n                    'severity carries meaning; set `color` for an explicit hue outside the tone system. ' +\n                    'Pass `ghostSeries` for a projected or comparison baseline: ghosts auto-dash and dim, ' +\n                    'or set `dashed` yourself. `maxPoints` and `smoothingWindow` trim and smooth noisy ' +\n                    'input. Use `MetricLineChartCard` when you want this wrapped with a headline value + ' +\n                    'stat delta in a Card.',\n            },\n        },\n    },\n    argTypes: {\n        series: { ...disabledControl, description: 'Primary lines; each item has `values` plus a `tone` or `color`.' },\n        ghostSeries: {\n            ...disabledControl,\n            description: 'Comparison/projected lines drawn dimmed and dashed behind `series`.',\n        },\n        maxPoints: {\n            control: { type: 'number', min: 2, max: 120, step: 1 },\n            description: 'Downsample cap per series (default 12); longer inputs are evenly sampled.',\n        },\n        smoothingWindow: {\n            control: { type: 'number', min: 1, max: 12, step: 1 },\n            description: 'Moving-average window applied before downsampling (default 3); 1 disables smoothing.',\n        },\n        ariaLabel: { control: 'text', description: 'Accessible label; sets `role=\"img\"`.' },\n        testId: { control: 'text', description: 'Test selector on the `svg` root.' },\n    },\n};\nexport default meta;\ntype Story = StoryObj<typeof LineChart>;\n\nexport const Default: Story = { args: { series, ariaLabel: 'Metric totals over time' } };\n\nexport const SingleSeries: Story = {\n    parameters: { docs: { description: { story: 'One line — the sparkline case.' } } },\n    args: { series: [series[0]], ariaLabel: 'Single metric trend' },\n};\n\nexport const SecondaryTone: Story = {\n    parameters: {\n        docs: {\n            description: {\n                story: 'The `secondary` SeriesTone paired with `brand` — the muted second line for neutral two-series charts.',\n            },\n        },\n    },\n    args: {\n        series: [\n            { id: 'brand', tone: 'brand', values: rising },\n            { id: 'secondary', tone: 'secondary', values: [2, 5, 9, 16, 24, 33, 43, 54, 66, 79, 93, 108] },\n        ],\n        ariaLabel: 'Brand and secondary trend',\n    },\n};\n\nexport const GhostSeries: Story = {\n    parameters: {\n        docs: {\n            description: {\n                story: 'A solid `series` over a dashed, dimmed `ghostSeries` baseline — the projected/comparison pattern.',\n            },\n        },\n    },\n    args: {\n        series: [{ id: 'actual', tone: 'brand', values: rising }],\n        ghostSeries: [\n            {\n                id: 'projected',\n                tone: 'brand',\n                dashed: true,\n                values: [6, 14, 24, 36, 50, 66, 84, 104, 126, 150, 176, 204],\n            },\n        ],\n        ariaLabel: 'Actual vs projected trend',\n    },\n};\n\nexport const ToneMatrix: Story = {\n    parameters: {\n        docs: {\n            description: {\n                story: 'Every `tone` — the 3 `SERIES_TONES` then the 5 `RISK_TONES` — each on an identical rising line.',\n            },\n        },\n    },\n    render: () => (\n        <VStack gap={12}>\n            {ALL_TONES.map(tone => (\n                <HStack key={tone} gap={12} align='center'>\n                    <div style={{ width: 80 }}>\n                        <Text variant='body-small' color='secondary'>\n                            {tone}\n                        </Text>\n                    </div>\n                    <div style={{ flex: 1 }}>\n                        <LineChart series={[{ id: tone, tone, values: rising }]} ariaLabel={`${tone} tone trend`} />\n                    </div>\n                </HStack>\n            ))}\n        </VStack>\n    ),\n};\n\nexport const ManySeries: Story = {\n    parameters: { docs: { description: { story: 'Seven overlaid series spanning both tone families.' } } },\n    args: { series: manySeries, ariaLabel: 'Many metric trends' },\n};\n\nexport const Empty: Story = {\n    parameters: { docs: { description: { story: 'No series — renders nothing; gate on an EmptyState upstream.' } } },\n    args: { series: [], ariaLabel: 'Empty metric trend' },\n};\n\nexport const SinglePoint: Story = {\n    parameters: { docs: { description: { story: 'A one-point series cannot form a line, so it is dropped.' } } },\n    args: { series: [{ id: 'single', values: [12] }], ariaLabel: 'Single point metric trend' },\n};\n\nexport const SmoothedAndTrimmed: Story = {\n    parameters: {\n        docs: { description: { story: '`maxPoints={6}` + `smoothingWindow={5}` — heavy downsample and smoothing.' } },\n    },\n    args: { series: manySeries, maxPoints: 6, smoothingWindow: 5, ariaLabel: 'Smoothed metric trends' },\n};\n\nexport const DarkTheme: Story = {\n    args: { series, ariaLabel: 'Metric totals over time' },\n    globals: { theme: 'dark' },\n};\n"
  },
  "specification": {
    "$schema": "../../../specs/component-spec.schema.json",
    "identity": {
      "name": "LineChart",
      "status": "preview",
      "version": "1.0.0",
      "summary": "One or more smoothed trend lines over time, with tone-driven series colors and optional dimmed, dashed ghost baselines for projections or comparisons."
    },
    "parts": [
      {
        "id": "plot",
        "label": "Plot",
        "description": "The SVG canvas that stretches the trend paths to fill its box.",
        "required": true
      },
      {
        "id": "series-line",
        "label": "Series line",
        "description": "A solid trend line colored by tone or explicit color."
      },
      {
        "id": "ghost-line",
        "label": "Ghost line",
        "description": "A dimmed, dashed comparison or projection line behind the series."
      }
    ],
    "allowedDesignChoices": {
      "variants": {
        "base": {
          "label": "Base",
          "description": "Series data and tone change the reading without changing the plot treatment."
        }
      },
      "sizes": {}
    },
    "variants": [
      {
        "id": "base",
        "label": "Base",
        "description": "A stretched SVG plot rendering one or more tone-colored trend lines.",
        "platforms": [
          "ios",
          "android",
          "web"
        ]
      }
    ],
    "sizes": [],
    "measurements": [
      {
        "id": "plot-height",
        "label": "Plot height",
        "kind": "exact",
        "token": "--cds-size-80",
        "value": 80,
        "unit": "px",
        "appliesTo": [
          "plot"
        ]
      },
      {
        "id": "dash-gap",
        "label": "Dashed line gap",
        "kind": "exact",
        "token": "--cds-size-4",
        "value": 4,
        "unit": "px",
        "appliesTo": [
          "ghost-line"
        ],
        "notes": "The dashed stroke pairs an --cds-size-8 dash with this --cds-size-4 gap."
      }
    ],
    "layout": {
      "alignment": "The plot fills the container width and its fixed height, stretching paths to the box.",
      "flow": "All series and ghost lines share one non-uniformly scaled SVG plot.",
      "notes": [
        "The plot uses a non-uniform aspect ratio, so lines scale to fill rather than preserve shape."
      ]
    },
    "typographyAndColor": {
      "typography": [
        {
          "label": "Adjacent caption",
          "description": "Surrounding axis or legend labels use the body-small ramp; the plot draws no text itself.",
          "token": "--cds-type-body-small-size"
        }
      ],
      "colors": [
        {
          "label": "Default line",
          "description": "A series with no tone or color falls back to primary text.",
          "token": "--cds-text-primary"
        },
        {
          "label": "Brand series",
          "description": "The brand series tone for neutral multi-line identity.",
          "token": "--cds-brand"
        },
        {
          "label": "Low-risk series",
          "description": "The good risk tone for severity-carrying series.",
          "token": "--cds-risk-good"
        },
        {
          "label": "High-risk series",
          "description": "The critical risk tone for severity-carrying series.",
          "token": "--cds-risk-critical"
        }
      ]
    },
    "states": [
      {
        "id": "single",
        "label": "Single series",
        "description": "One line renders the sparkline case."
      },
      {
        "id": "multi",
        "label": "Multiple series",
        "description": "Several tone-distinguished lines overlay in one plot."
      },
      {
        "id": "ghosted",
        "label": "Ghosted",
        "description": "A solid series sits over a dimmed, dashed ghost baseline."
      },
      {
        "id": "empty",
        "label": "Empty",
        "description": "No renderable series, so nothing is drawn and an upstream empty state should show."
      }
    ],
    "behavior": [
      {
        "label": "Two-point minimum",
        "description": "A series needs at least two points to form a line; single points are dropped."
      },
      {
        "label": "Tone or color",
        "description": "Distinguish series with a tone; set an explicit color for hues outside the tone system."
      },
      {
        "label": "Trim and smooth",
        "description": "maxPoints downsamples long inputs and smoothingWindow applies a moving average."
      }
    ],
    "accessibility": [
      {
        "label": "Meaningful chart",
        "description": "Pass an accessible label so the plot is announced as a meaningful image."
      },
      {
        "label": "Decorative chart",
        "description": "Omit the label to hide the plot from assistive technology when nearby text carries the trend."
      }
    ],
    "contentAdaptation": [
      {
        "label": "Trend over magnitude",
        "description": "Prefer LineChart when the shape of the trend matters more than discrete bar magnitudes."
      },
      {
        "label": "Ghost baselines",
        "description": "Use ghost series for a projected or comparison baseline behind the primary lines."
      }
    ],
    "motionHaptics": {
      "motion": [
        {
          "label": "No intrinsic motion",
          "description": "The plot does not animate on mount; a parent may transition the whole chart."
        }
      ],
      "haptics": [
        {
          "label": "No feedback",
          "description": "The chart is a display and requests no haptic feedback."
        }
      ]
    },
    "platformDifferences": []
  },
  "specification_source": "packages/design-system/src/components/visualizations/LineChart/LineChart.spec.json",
  "guidance": {
    "summary": "One or more smoothed trend lines over time, with tone-driven series colors and optional dimmed, dashed ghost baselines for projections or comparisons.",
    "guidance": [
      {
        "heading": "Overview",
        "body": "One or more smoothed trend lines rendered as a plain SVG — the shape of a metric over time."
      },
      {
        "heading": "When to use",
        "body": "Reach for LineChart when the data is a continuous trajectory and the _shape_ of the trend\nmatters more than exact per-bucket magnitudes — especially when overlaying several series to\ncompare their trajectories. Distinguish series with `tone` (the neutral `SERIES_TONES` for\nidentity, or the `RISK_TONES` when severity carries meaning) or an explicit `color`.\n\nPick `BarChart` instead when the reader must scrub discrete time buckets or read exact values;\n`CategoryBars` when the x-axis is a set of named categories rather than time; `HalfGauge` or\n`RiskMeter` for a single bounded score. When you want this line wrapped with a headline value\nand a stat delta in a Card, use `MetricLineChartCard` rather than composing it yourself.\n\nNot currently consumed by the app — the exposures trend view ships a bespoke D3-based line\nchart. This is the design-system primitive to migrate toward."
      },
      {
        "heading": "Comparison baseline",
        "body": "Pass `ghostSeries` for a projected or comparison line — it auto-dashes and dims behind the\nsolid `series`."
      }
    ],
    "usage": [],
    "examples": [],
    "source": "packages/design-system/src/components/visualizations/LineChart/LineChart.mdx",
    "status": "local-preview",
    "note": "Guidance is read from local documentation, originally imported from the frozen source. Platform assertions in guidance are not parity verification."
  },
  "links": {
    "human": "/component-linechart",
    "json": "/data/visual/components/linechart.json",
    "storybook": "/storybook/?path=/story/cloaked-design-system-visualizations-linechart--default"
  }
}
