{
  "name": "InfoSection",
  "type": "component",
  "description": "A titled information section: a decorative icon, a 16/24 title, and a body whose gap is the one thing that varies.",
  "export": "InfoSection",
  "path": "@gtmi/strix-react/molecules/info-section",
  "props": [
    {
      "name": "title",
      "type": "ReactNode",
      "required": true,
      "description": "Header text."
    },
    {
      "name": "titleAs",
      "type": "h2 | h3 | h4 | h5 | h6",
      "description": "Heading level wrapped around the title, in a display:contents wrapper so it joins the document outline without adding a layout box. No level is assumed by default: guessing produces a wrong outline that nothing downstream will catch."
    },
    {
      "name": "icon",
      "type": "ReactNode",
      "description": "Decorative leading glyph, rendered aria-hidden because the title already names the section."
    },
    {
      "name": "density",
      "type": "tight | default | loose",
      "default": "default",
      "description": "Gap between header and body: 8px, 12px, 16px. This is the only axis on which Figma's five sections differ. NOT the gap between the body's own children, which is fixed at 12px \u2014 the prop used to be applied there instead, which inverted the axis and left every one of the five sections wrong in at least one of its two gaps."
    },
    {
      "name": "disabled",
      "type": "boolean",
      "default": "false",
      "description": "Dims title and icon and sets aria-disabled. Conveys state only; a section is not a control."
    },
    {
      "name": "children",
      "type": "ReactNode",
      "description": "The body. The body element is omitted entirely when there is nothing to put in it, so an empty section does not contribute a stray gap."
    },
    {
      "name": "className",
      "type": "string",
      "description": "Merged through cn(), so a caller's utility wins."
    },
    {
      "name": "badge",
      "type": "ReactNode",
      "description": "Optional status chip beside the title \u2014 Figma's `Show Badge`, off by default. A slot rather than a string, because the chip is `Badge` and the caller picks its variant; `Profile-section` draws it as size=\"small\" variant=\"error\" reading \"Analyzing\"."
    }
  ],
  "ai_tags": ["information", "panel", "section", "header", "cintel", "conversation-intelligence"],
  "tokens_used": [
    "--color-icon-disabled",
    "--color-icon-section",
    "--color-text-disabled",
    "--color-text-section-title",
    "--spacing-gap-200",
    "--spacing-gap-250",
    "--spacing-gap-300",
    "--text-size-body-medium"
  ],
  "figma": {
    "file": "85sD2HI8wksP9Y7uDmJ9DK",
    "fileName": "Multi product demo",
    "node": "967:20788",
    "component": "Section Header",
    "composedBy": {
      "Profile": "836:6991 (density default, 5 InfoRow)",
      "Live intelligence": "836:7042 (density default, 2 InfoRow) \u2014 GTM-990 calls this 'Operators'",
      "Under the hood": "836:7151 (density loose, 3 ToolCall)",
      "Observations": "836:7614 (density tight)",
      "Summary": "836:7604 (density tight)"
    }
  },
  "notes": "CORRECTED against Figma Dev Mode in two places, both of which this manifest already described correctly while the code did something else. (1) The title rendered `subhead-m` (22/32 at 500) against the header's 16/24 Semibold; Dev Mode names the composite style `Paragraph/medium-semibold`, where REST returns only the leaf size and weight variables. Now `body-m-semibold`, and --text-size-subhead-medium is out of tokens_used. Same divergence SectionTitle was corrected for, in the header it was extracted from. (2) `density` was applied to the gap between the body's children while the root's header-to-body gap sat pinned at 8px -- the axis inverted, so all five sections were wrong there. Figma varies the header-to-body gap and holds the inner list at 12. The density tests read the body element, the same box the bug styled, which is why a wrong axis looked right; they now assert on the root, with a fourth test pinning the body gap as invariant. Both corrections mutation-tested and measured in a browser.\n\nThis one component carries five of GTM-990's items. Profile, Live intelligence, Under the hood, Observations and Summary are all a Section Header over a body at 401-414px wide, and the header is byte-identical across all five: 24px tall, 8px internal gap, brand-red icon, 16/24 title. The only difference between them is the header-to-body gap \u2014 8, 12 or 16 \u2014 so that became `density` and the five sections are compositions rather than components. Building them separately would have duplicated the header five times.\n\nTwo colour decisions, both measured, because the Figma file is authored dark-only and its palette is unverified in light. (1) The title: Figma's `color/gray/gray-100` #dde0e6 measures 1.32:1 on the light surface and is unusable; --color-text-primary inverts per theme at 19.37:1 / 17.85:1. (2) The icon: Figma binds `color/brand/twilio-red` #db132a, which measures 5.07:1 light and 3.52:1 dark \u2014 over WCAG 1.4.11's 3:1 for a non-text graphic in both themes, and it would fail 4.5:1 as text, so do not reuse it for a label. The token is --color-icon-accent and NOT --color-icon-destructive: both clear 3:1, so this is a decision about meaning. The red is Twilio brand; a destructive token would announce danger on every section header and be wrong the moment something genuinely destructive appeared beside it. Recorded as Decision 4 in docs/superpowers/plans/2026-07-31-0.1.2-gtm-990-plan.md.\n\nThe contrast tests derive the title ink and the icon fill from their own separate cva functions rather than collecting both and splitting the result by token name. The first version did the latter \u2014 filtering on `--color-text*` and `--color-icon*` prefixes \u2014 and was vacuous: any token matching neither prefix fell out of both groups unmeasured, and it passed with the title mutated to `text-highlight` (1.84:1 on the light page). The role is known from which style function produced it and never needs to be inferred from the name.\n\nEnabled sections carry no aria-disabled attribute at all rather than aria-disabled=\"false\", because the two are not equivalent to every assistive technology and a section is not a control.\n\n`titleAs` uses the same display:contents idiom as CollapsiblePanel, for the same reason.\n\nMOVED TO src/molecules IN 0.5.0: Figma files the five text molecules that share this shape under Molecules.\n\nTHE ICON TOKEN ARGUED FOR ONE COLOUR AND NAMED ANOTHER. This file's own docblock read \"Figma binds color/brand/twilio-red (#db132a) ... the token is --color-icon-accent and NOT --color-icon-destructive ... the red is Twilio brand\". The reasoning is right and --color-icon-accent resolves to --palette-primary-300 #9ec1fd, A BLUE. Now --color-icon-section, which carries #db132a at 3.82:1 on the page -- over 1.4.11's 3:1 for a graphic, under 4.5, so it must never carry text. Verified from the exported SVG (fill=\"#DB132A\").\n\nThe test could not catch it because it named the token too: expect(iconInks).toContain('--color-icon-accent') is true of a component rendering a blue. It resolves the hex now.\n\nTHE TITLE IS gray-100 #dde0e6 at 14.64:1, one ramp step off white. It was --color-text-primary, which is color/brand/white at 19.37:1 -- brighter than Figma draws.\n\nA BADGE SLOT WAS MISSING. Figma's Section Header carries an optional Show Badge, off by default, which Profile-section draws as \"Analyzing\". It is Badge size=\"small\" variant=\"error\" exactly: the rgba(239,34,58,0.2) tint composites to #301129, white on it is 16.96:1, and the fill is 1.14:1 against the page -- .badge's already-logged conflict rather than a new one. Nothing needed building. The header is flex-wrap, which is Figma's own, so icon + long title + badge reflow at 320px rather than overflow."
}
