{"spec_id":"line-styled","library":"muix","language":"javascript","code":"// anyplot.ai\n// line-styled: Styled Line Plot\n// Library: muix 7.29.1 | JavaScript 22.23.2\n// Quality: 91/100 | Created: 2026-09-05\nimport {\n  LineChart,\n  lineElementClasses,\n  getLineElementUtilityClass,\n} from \"@mui/x-charts/LineChart\";\nimport { ChartsReferenceLine } from \"@mui/x-charts/ChartsReferenceLine\";\n\nconst t = window.ANYPLOT_TOKENS;\n\n// --- Data (in-memory, deterministic mulberry32 PRNG) ------------------------\nfunction mulberry32(seed: number) {\n  return () => {\n    seed |= 0;\n    seed = (seed + 0x6d2b79f5) | 0;\n    let x = Math.imul(seed ^ (seed >>> 15), 1 | seed);\n    x = (x + Math.imul(x ^ (x >>> 7), 61 | x)) ^ x;\n    return ((x ^ (x >>> 14)) >>> 0) / 4294967296;\n  };\n}\nconst rand = mulberry32(42);\n\nconst MINUTES = Array.from({ length: 60 }, (_, i) => i);\n\nconst p50: number[] = [];\nconst p90: number[] = [];\nconst p99: number[] = [];\nconst p999: number[] = [];\nlet baseline = 42;\nfor (let i = 0; i < MINUTES.length; i += 1) {\n  baseline += (rand() - 0.5) * 4;\n  baseline = Math.min(58, Math.max(32, baseline));\n  const tailGap = 14 + rand() * 8;\n  const deepTailGap = 30 + rand() * 14 + Math.sin(i / 6) * 6;\n  const spike = i % 17 === 0 ? 55 + rand() * 35 : rand() * 10;\n  p50.push(Math.round(baseline * 10) / 10);\n  p90.push(Math.round((baseline + tailGap) * 10) / 10);\n  p99.push(Math.round((baseline + tailGap + deepTailGap) * 10) / 10);\n  p999.push(Math.round((baseline + tailGap + deepTailGap + spike) * 10) / 10);\n}\n\n// The single largest tail-latency spike is the focal point of the story\n// (called out with a reference line below) — find it once, up front.\nlet peakIndex = 0;\nfor (let i = 1; i < p999.length; i += 1) {\n  if (p999[i] > p999[peakIndex]) peakIndex = i;\n}\nconst peakMinute = MINUTES[peakIndex];\nconst peakValue = p999[peakIndex];\n\n// Standard line styles mapped to series, so the chart stays legible when\n// printed in monochrome (spec: solid, dashed, dotted, dash-dot). p99's dots\n// are a touch denser/thicker than a minimal dotted pattern so they stay\n// visible where p99 and p99.9 cross, and at small (mobile) render scale.\nconst SERIES = [\n  { id: \"p50\", label: \"p50 latency\", dash: \"none\" },\n  { id: \"p90\", label: \"p90 latency\", dash: \"11 7\" },\n  { id: \"p99\", label: \"p99 latency\", dash: \"3 5\" },\n  { id: \"p999\", label: \"p99.9 latency\", dash: \"13 5 2 5\" },\n];\n\n// Consistent line width across styles; strokeDasharray keyed per series id\n// via the utility class MUI X attaches to each line's root element.\nconst lineSx = {\n  [`.${lineElementClasses.root}`]: { strokeWidth: 3 },\n  ...Object.fromEntries(\n    SERIES.map((s) => [\n      `.${getLineElementUtilityClass(`series-${s.id}`)}`,\n      { strokeDasharray: s.dash },\n    ]),\n  ),\n};\n\n// Custom legend swatch: a short dashed line sample next to the series name.\n// MUI X's built-in legend only draws color squares (no dash preview) and its\n// bottom-anchored position ignores the chart's own margin, so a plain HTML\n// row below the chart both fixes the layout and shows the actual line style.\nfunction LegendRow({ topGap }: { topGap: number }) {\n  return (\n    <div\n      style={{\n        display: \"flex\",\n        justifyContent: \"center\",\n        alignItems: \"center\",\n        gap: 32,\n        paddingTop: topGap,\n        fontFamily: \"system-ui, sans-serif\",\n      }}\n    >\n      {SERIES.map((s, i) => (\n        <div\n          key={s.id}\n          style={{ display: \"flex\", alignItems: \"center\", gap: 8 }}\n        >\n          <svg width={40} height={14}>\n            <line\n              x1={0}\n              y1={7}\n              x2={40}\n              y2={7}\n              stroke={t.palette[i]}\n              strokeWidth={3}\n              strokeDasharray={s.dash}\n            />\n          </svg>\n          <span style={{ fontSize: 14, color: t.inkSoft }}>{s.label}</span>\n        </div>\n      ))}\n    </div>\n  );\n}\n\n// --- Chart (default-exported component — the harness mounts it) -------------\nexport default function Chart() {\n  const { width, height } = window.ANYPLOT_SIZE;\n  const titleHeight = 56;\n  const legendHeight = 48;\n  const chartHeight = height - titleHeight - legendHeight;\n\n  return (\n    <div style={{ width, height, display: \"flex\", flexDirection: \"column\" }}>\n      <div\n        style={{\n          height: titleHeight,\n          display: \"flex\",\n          alignItems: \"center\",\n          paddingLeft: 8,\n          fontSize: 22,\n          fontWeight: 500,\n          color: t.ink,\n          fontFamily: \"system-ui, sans-serif\",\n        }}\n      >\n        line-styled · javascript · muix · anyplot.ai\n      </div>\n      <LineChart\n        width={width}\n        height={chartHeight}\n        skipAnimation\n        dataset={MINUTES.map((minute, i) => ({\n          minute,\n          p50: p50[i],\n          p90: p90[i],\n          p99: p99[i],\n          p999: p999[i],\n        }))}\n        xAxis={[\n          {\n            dataKey: \"minute\",\n            label: \"Time (minutes)\",\n            scaleType: \"linear\",\n            labelStyle: { fontSize: 16, fill: t.ink },\n            tickLabelStyle: { fontSize: 14, fill: t.inkSoft },\n          },\n        ]}\n        yAxis={[\n          {\n            label: \"Response Latency (ms)\",\n            // MUI X positions the axis label at a fixed `tickFontSize + tickSize\n            // + 10` offset from the axis line, independent of how wide the tick\n            // numbers actually render — with 3-digit ticks (up to \"190\") the\n            // real default collides with the label. `tickFontSize` only feeds\n            // that offset math here since `tickLabelStyle.fontSize` below wins\n            // for the rendered numbers, so bumping it clears the collision\n            // without changing the tick numbers' visual size.\n            tickFontSize: 34,\n            labelStyle: { fontSize: 16, fill: t.ink },\n            tickLabelStyle: { fontSize: 14, fill: t.inkSoft },\n          },\n        ]}\n        series={SERIES.map((s, i) => ({\n          id: s.id,\n          dataKey: s.id,\n          label: s.label,\n          color: t.palette[i],\n          curve: \"monotoneX\",\n          showMark: false,\n        }))}\n        grid={{ horizontal: true }}\n        margin={{ top: 20, right: 32, bottom: 64, left: 96 }}\n        slots={{ legend: () => null }}\n        sx={{\n          ...lineSx,\n          \"& .MuiChartsAxisLine\": { stroke: t.inkSoft },\n          \"& .MuiChartsAxisTick\": { stroke: t.inkSoft },\n        }}\n      >\n        {/* Focal-point touch: mark the single largest tail-latency spike\n            instead of leaving the p99.9 story purely implicit. */}\n        <ChartsReferenceLine\n          x={peakMinute}\n          label={`peak p99.9 · ${peakValue}ms`}\n          labelAlign=\"start\"\n          spacing={{ x: -150, y: 10 }}\n          lineStyle={{ stroke: t.inkSoft, strokeDasharray: \"4 4\" }}\n          labelStyle={{ fontSize: 13, fill: t.inkSoft }}\n        />\n      </LineChart>\n      <LegendRow topGap={legendHeight - 14 - 8} />\n    </div>\n  );\n}\n"}