{
  "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": "flag",
  "name": "Flag",
  "category": "Primitives",
  "summary": "A country flag as a circular mark, drawn from vendored artwork so it is consistent across platforms and controllable in a flat interface.",
  "documentation": {
    "summary": "A country flag as a circular mark, drawn from vendored artwork so it is consistent across platforms and controllable in a flat interface.",
    "guidance": [
      {
        "heading": "Overview",
        "body": "A country flag as a circular mark, keyed by ISO 3166-1 alpha-2 code."
      },
      {
        "heading": "Why not the flag emoji",
        "body": "Emoji flags are drawn by the platform, so they arrive glossy and waving in an otherwise flat\ninterface, at a size and baseline the design system cannot control. On iOS they at least render;\non Windows there are no flag glyphs at all and the browser falls back to showing the two letters.\n\nThe deciding reason here is internal consistency: the iOS app has always shipped circular flag\nartwork, so emoji in the webview made one product look like two."
      },
      {
        "heading": "Use it for places, not languages",
        "body": "A flag names a country or a server location. It does not name a language — the same language spans\nmany countries, and picking one country's flag for it is both inaccurate and easy to take badly.\n\nKeep the place named in text beside the mark. A flag on its own is ambiguous to plenty of readers,\nwhich is also why `label` is optional: when the adjacent text already says \"Amsterdam\", the flag is\ndecorative and should be hidden from assistive technology rather than announced twice."
      },
      {
        "heading": "The ring is load-bearing",
        "body": "Several flags are mostly white — Japan, Poland, Finland. Without a hairline ring they dissolve into\na light card, and Japan in particular reads as a red dot floating in space."
      },
      {
        "heading": "Codes come from payloads",
        "body": "`code` is a plain string rather than a union, because country codes arrive from backend responses\nand native bridge payloads. An unrecognized code renders nothing, so a country we have no artwork\nfor costs a mark instead of breaking the row. Narrow with `isFlagCode` when the caller wants to\nrender a fallback instead."
      },
      {
        "heading": "Artwork",
        "body": "Vendored from [circle-flags](https://github.com/HatScripts/circle-flags) (MIT), covering the 89\ncountries the VPN catalog can return. `scripts/generateFlagRegistry.ts` bakes them into shape data\nat build time, stripping each source file's circular mask — every file uses the same mask id, so\ninlining two would make the second resolve against the first. `Flag` restores the circle with\n`border-radius`, which is also what makes room for the ring. The whole set is 89 flags in 329\nshapes, about 10 KB gzipped."
      }
    ],
    "usage": [],
    "examples": [],
    "source": "packages/design-system/src/components/primitives/Flag/Flag.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."
  },
  "source": {
    "path": "packages/design-system/src/components/primitives/Flag/Flag.tsx",
    "code": "import React from 'react';\nimport { cn } from '../../../utilities';\nimport { FLAG_ARTWORK, FLAG_CODES, type FlagCode, type FlagShape } from './flagArtwork.generated';\nimport styles from './Flag.module.scss';\n\nexport { FLAG_CODES };\nexport type { FlagCode };\n\n/**\n * Rendered flag scale. Matches `Avatar`'s scale names because a flag reads as the same kind of\n * circular mark.\n */\nexport type FlagSize = 'sm' | 'md' | 'lg';\n\n/**\n * Props for a country flag mark.\n */\nexport interface FlagProps {\n    /**\n     * ISO 3166-1 alpha-2 country code, any casing. Deliberately a plain string: codes arrive from\n     * backend and bridge payloads, and an unknown one renders nothing rather than breaking a row.\n     */\n    code: string;\n    /** Rendered scale. */\n    size: FlagSize;\n    /**\n     * Accessible label, e.g. the country name. Without one the flag is hidden from assistive tech —\n     * correct when the country is already named in adjacent text, which is the common case.\n     */\n    label?: string;\n    className?: string;\n    /** Optional test selector. */\n    testId?: string;\n}\n\n/**\n * Narrows an untrusted string to a country we ship artwork for, so callers can branch before\n * rendering.\n *\n * @param value - Candidate country code from an untyped source; case-insensitive.\n * @returns Whether a flag exists for it; inherited object properties are rejected.\n */\nexport function isFlagCode(value: unknown): value is FlagCode {\n    if (typeof value !== 'string') return false;\n\n    return Object.prototype.hasOwnProperty.call(FLAG_ARTWORK, value.toLowerCase());\n}\n\n/**\n * A country flag as a circular mark.\n *\n * Vendored artwork rather than the flag emoji: emoji flags are drawn by the platform, so they\n * arrive glossy and waving in a flat interface, at a size and baseline we cannot control. This also\n * matches the iOS app, which has always used circular flag artwork.\n *\n * An unrecognized `code` renders nothing — check with `isFlagCode` when the caller needs a fallback.\n */\nexport function Flag({ code, size, label, className, testId }: FlagProps) {\n    if (!isFlagCode(code)) return null;\n\n    return (\n        <svg\n            className={cn(styles.flag, styles[`size-${size}`], className)}\n            viewBox='0 0 512 512'\n            role={label ? 'img' : undefined}\n            aria-label={label}\n            aria-hidden={label ? undefined : true}\n            focusable='false'\n            data-testid={testId}\n        >\n            {FLAG_ARTWORK[code.toLowerCase() as FlagCode].map(renderShape)}\n        </svg>\n    );\n}\n\n/**\n * Draws one generated shape. Index keys are safe here: the artwork is baked at build time, so a\n * flag's shape list never reorders.\n */\nfunction renderShape(shape: FlagShape, index: number): React.ReactElement {\n    if (shape.e === 'c') {\n        return <circle key={index} cx={shape.cx} cy={shape.cy} r={shape.r} fill={shape.f} />;\n    }\n    if (shape.e === 'r') {\n        return (\n            <rect\n                key={index}\n                x={shape.x}\n                y={shape.y}\n                width={shape.width}\n                height={shape.height}\n                rx={shape.rx}\n                ry={shape.ry}\n                fill={shape.f}\n            />\n        );\n    }\n\n    return <path key={index} d={shape.d} fill={shape.f} />;\n}\n"
  },
  "spec": {
    "$schema": "../../../specs/component-spec.schema.json",
    "identity": {
      "name": "Flag",
      "status": "preview",
      "version": "1.0.0",
      "summary": "A country flag as a circular mark, drawn from vendored artwork so it is consistent across platforms and controllable in a flat interface."
    },
    "parts": [
      {
        "id": "artwork",
        "label": "Artwork",
        "description": "The flag geometry, clipped to a circle.",
        "required": true
      },
      {
        "id": "ring",
        "label": "Ring",
        "description": "Hairline inset ring that keeps white-field flags from dissolving into a light surface.",
        "required": true
      }
    ],
    "allowedDesignChoices": {
      "variants": {
        "base": {
          "label": "Base",
          "description": "One treatment; the country changes the artwork, not the styling."
        }
      },
      "sizes": {
        "sm": {
          "label": "Small",
          "description": "Inline with body and body-small text."
        },
        "md": {
          "label": "Medium",
          "description": "List rows and compact headers."
        },
        "lg": {
          "label": "Large",
          "description": "Leading mark on a row or card."
        }
      }
    },
    "variants": [
      {
        "id": "base",
        "label": "Base",
        "description": "A circular flag mark.",
        "platforms": [
          "ios",
          "android",
          "web"
        ]
      }
    ],
    "sizes": [
      {
        "id": "sm",
        "label": "Small",
        "description": "16px."
      },
      {
        "id": "md",
        "label": "Medium",
        "description": "20px."
      },
      {
        "id": "lg",
        "label": "Large",
        "description": "24px."
      }
    ],
    "measurements": [
      {
        "id": "size-sm",
        "label": "Small diameter",
        "kind": "exact",
        "token": "--cds-size-16",
        "value": 16,
        "unit": "px",
        "appliesTo": [
          "artwork"
        ]
      },
      {
        "id": "size-md",
        "label": "Medium diameter",
        "kind": "exact",
        "token": "--cds-size-20",
        "value": 20,
        "unit": "px",
        "appliesTo": [
          "artwork"
        ]
      },
      {
        "id": "size-lg",
        "label": "Large diameter",
        "kind": "exact",
        "token": "--cds-size-24",
        "value": 24,
        "unit": "px",
        "appliesTo": [
          "artwork"
        ]
      },
      {
        "id": "ring-width",
        "label": "Ring width",
        "kind": "exact",
        "token": "--cds-border-width-hairline",
        "value": 0.5,
        "unit": "px",
        "appliesTo": [
          "ring"
        ]
      }
    ],
    "layout": {
      "alignment": "Inline-block, nudged up slightly so it centers against adjacent text rather than sitting on the baseline.",
      "flow": "A fixed-size circular mark; it never stretches to its container.",
      "notes": [
        "The artwork is a full square clipped to a circle in CSS. The vendored source set masks itself with an id that is identical in every file, so inlining the mask would collide across instances."
      ]
    },
    "typographyAndColor": {
      "typography": [],
      "colors": [
        {
          "label": "Ring",
          "description": "Hairline ring around the artwork.",
          "token": "--cds-divider"
        }
      ]
    },
    "states": [
      {
        "id": "known",
        "label": "Known country",
        "description": "A country with vendored artwork renders its flag."
      },
      {
        "id": "unknown",
        "label": "Unknown country",
        "description": "An unrecognized code renders nothing, so a missing flag costs a mark rather than breaking the row."
      }
    ],
    "behavior": [
      {
        "label": "Case-insensitive codes",
        "description": "Codes are matched lowercased, so bridge and backend casing both resolve."
      },
      {
        "label": "Untrusted input",
        "description": "The code prop is a plain string because codes arrive from payloads; isFlagCode narrows it when a caller needs a fallback."
      }
    ],
    "accessibility": [
      {
        "label": "Named country",
        "description": "Pass a label when the flag is the only indication of the country, so it is announced as a meaningful image."
      },
      {
        "label": "Decorative flag",
        "description": "Omit the label when adjacent text already names the country; the flag is then hidden from assistive technology."
      }
    ],
    "contentAdaptation": [
      {
        "label": "Pair with the country name",
        "description": "A flag alone is ambiguous to many readers; keep the country or city in text beside it."
      },
      {
        "label": "Not for language",
        "description": "Use a flag for a country or a server location, never to indicate a language."
      }
    ],
    "motionHaptics": {
      "motion": [
        {
          "label": "Static",
          "description": "The mark does not animate."
        }
      ],
      "haptics": [
        {
          "label": "No feedback",
          "description": "The flag is a display and requests no haptic feedback."
        }
      ]
    },
    "platformDifferences": []
  },
  "spec_source": "packages/design-system/src/components/primitives/Flag/Flag.spec.json",
  "guidance_source": {
    "path": "packages/design-system/src/components/primitives/Flag/Flag.mdx",
    "code": "import { Meta, Canvas, Controls } from '@storybook/addon-docs/blocks';\nimport { ComponentSpec } from '../../../../.storybook/blocks';\nimport * as Stories from './Flag.stories';\nimport flagSpec from './Flag.spec.json';\n\n<Meta of={Stories} />\n\n# Flag\n\nA country flag as a circular mark, keyed by ISO 3166-1 alpha-2 code.\n\n<Canvas of={Stories.Default} />\n\n## Why not the flag emoji\n\nEmoji flags are drawn by the platform, so they arrive glossy and waving in an otherwise flat\ninterface, at a size and baseline the design system cannot control. On iOS they at least render;\non Windows there are no flag glyphs at all and the browser falls back to showing the two letters.\n\nThe deciding reason here is internal consistency: the iOS app has always shipped circular flag\nartwork, so emoji in the webview made one product look like two.\n\n## Use it for places, not languages\n\nA flag names a country or a server location. It does not name a language — the same language spans\nmany countries, and picking one country's flag for it is both inaccurate and easy to take badly.\n\nKeep the place named in text beside the mark. A flag on its own is ambiguous to plenty of readers,\nwhich is also why `label` is optional: when the adjacent text already says \"Amsterdam\", the flag is\ndecorative and should be hidden from assistive technology rather than announced twice.\n\n<Canvas of={Stories.Inline} />\n\n## The ring is load-bearing\n\nSeveral flags are mostly white — Japan, Poland, Finland. Without a hairline ring they dissolve into\na light card, and Japan in particular reads as a red dot floating in space.\n\n<Canvas of={Stories.WhiteFieldFlags} />\n\n## Codes come from payloads\n\n`code` is a plain string rather than a union, because country codes arrive from backend responses\nand native bridge payloads. An unrecognized code renders nothing, so a country we have no artwork\nfor costs a mark instead of breaking the row. Narrow with `isFlagCode` when the caller wants to\nrender a fallback instead.\n\n<Canvas of={Stories.UnknownCode} />\n\n## Artwork\n\nVendored from [circle-flags](https://github.com/HatScripts/circle-flags) (MIT), covering the 89\ncountries the VPN catalog can return. `scripts/generateFlagRegistry.ts` bakes them into shape data\nat build time, stripping each source file's circular mask — every file uses the same mask id, so\ninlining two would make the second resolve against the first. `Flag` restores the circle with\n`border-radius`, which is also what makes room for the ring. The whole set is 89 flags in 329\nshapes, about 10 KB gzipped.\n\n## Design Guidelines\n\n<ComponentSpec spec={flagSpec} />\n\n## Props\n\n<Controls of={Stories.Default} />\n"
  },
  "props": [
    {
      "name": "code",
      "type": "string",
      "declared_type": "string",
      "required": true,
      "description": "ISO 3166-1 alpha-2 country code, any casing. Deliberately a plain string: codes arrive from\nbackend and bridge payloads, and an unknown one renders nothing rather than breaking a row.",
      "source": {
        "path": "packages/design-system/src/components/primitives/Flag/Flag.tsx",
        "line": 23
      }
    },
    {
      "name": "size",
      "type": "FlagSize",
      "declared_type": "FlagSize",
      "required": true,
      "description": "Rendered scale.",
      "source": {
        "path": "packages/design-system/src/components/primitives/Flag/Flag.tsx",
        "line": 25
      },
      "values": [
        "lg",
        "md",
        "sm"
      ],
      "values_complete": true
    },
    {
      "name": "label",
      "type": "string | undefined",
      "declared_type": "string",
      "required": false,
      "description": "Accessible label, e.g. the country name. Without one the flag is hidden from assistive tech —\ncorrect when the country is already named in adjacent text, which is the common case.",
      "source": {
        "path": "packages/design-system/src/components/primitives/Flag/Flag.tsx",
        "line": 30
      }
    },
    {
      "name": "className",
      "type": "string | undefined",
      "declared_type": "string",
      "required": false,
      "description": "",
      "source": {
        "path": "packages/design-system/src/components/primitives/Flag/Flag.tsx",
        "line": 31
      }
    },
    {
      "name": "testId",
      "type": "string | undefined",
      "declared_type": "string",
      "required": false,
      "description": "Optional test selector.",
      "source": {
        "path": "packages/design-system/src/components/primitives/Flag/Flag.tsx",
        "line": 33
      }
    }
  ],
  "prop_shapes": {},
  "examples": [],
  "tokens": [
    {
      "name": "--cds-size-16",
      "light": "16px",
      "dark": "16px"
    },
    {
      "name": "--cds-size-20",
      "light": "20px",
      "dark": "20px"
    },
    {
      "name": "--cds-size-24",
      "light": "24px",
      "dark": "24px"
    },
    {
      "name": "--cds-border-width-hairline",
      "light": "0.5px",
      "dark": "0.5px"
    },
    {
      "name": "--cds-divider",
      "light": "#e0ddd6",
      "dark": "#ffffff1a"
    }
  ],
  "visual_reference": {
    "stories": [
      {
        "id": "cloaked-design-system-primitives-flag--default",
        "name": "Default",
        "title": "Cloaked Design System/Primitives/Flag",
        "exportName": "Default",
        "source_path": "packages/design-system/src/components/primitives/Flag/Flag.stories.tsx",
        "source_digest": "499e7f88e45299581e11a5e792fd64cf6b79fb863d2cbda5adfa6c4dd697266c",
        "status": "preview",
        "local_url": "/storybook/iframe.html?id=cloaked-design-system-primitives-flag--default&viewMode=story"
      },
      {
        "id": "cloaked-design-system-primitives-flag--sizes",
        "name": "Sizes",
        "title": "Cloaked Design System/Primitives/Flag",
        "exportName": "Sizes",
        "source_path": "packages/design-system/src/components/primitives/Flag/Flag.stories.tsx",
        "source_digest": "499e7f88e45299581e11a5e792fd64cf6b79fb863d2cbda5adfa6c4dd697266c",
        "status": "preview",
        "local_url": "/storybook/iframe.html?id=cloaked-design-system-primitives-flag--sizes&viewMode=story"
      },
      {
        "id": "cloaked-design-system-primitives-flag--white-field-flags",
        "name": "White Field Flags",
        "title": "Cloaked Design System/Primitives/Flag",
        "exportName": "WhiteFieldFlags",
        "source_path": "packages/design-system/src/components/primitives/Flag/Flag.stories.tsx",
        "source_digest": "499e7f88e45299581e11a5e792fd64cf6b79fb863d2cbda5adfa6c4dd697266c",
        "status": "preview",
        "local_url": "/storybook/iframe.html?id=cloaked-design-system-primitives-flag--white-field-flags&viewMode=story"
      },
      {
        "id": "cloaked-design-system-primitives-flag--inline",
        "name": "Inline",
        "title": "Cloaked Design System/Primitives/Flag",
        "exportName": "Inline",
        "source_path": "packages/design-system/src/components/primitives/Flag/Flag.stories.tsx",
        "source_digest": "499e7f88e45299581e11a5e792fd64cf6b79fb863d2cbda5adfa6c4dd697266c",
        "status": "preview",
        "local_url": "/storybook/iframe.html?id=cloaked-design-system-primitives-flag--inline&viewMode=story"
      },
      {
        "id": "cloaked-design-system-primitives-flag--unknown-code",
        "name": "Unknown Code",
        "title": "Cloaked Design System/Primitives/Flag",
        "exportName": "UnknownCode",
        "source_path": "packages/design-system/src/components/primitives/Flag/Flag.stories.tsx",
        "source_digest": "499e7f88e45299581e11a5e792fd64cf6b79fb863d2cbda5adfa6c4dd697266c",
        "status": "preview",
        "local_url": "/storybook/iframe.html?id=cloaked-design-system-primitives-flag--unknown-code&viewMode=story"
      },
      {
        "id": "cloaked-design-system-primitives-flag--dark-theme",
        "name": "Dark Theme",
        "title": "Cloaked Design System/Primitives/Flag",
        "exportName": "DarkTheme",
        "source_path": "packages/design-system/src/components/primitives/Flag/Flag.stories.tsx",
        "source_digest": "499e7f88e45299581e11a5e792fd64cf6b79fb863d2cbda5adfa6c4dd697266c",
        "status": "preview",
        "local_url": "/storybook/iframe.html?id=cloaked-design-system-primitives-flag--dark-theme&viewMode=story"
      }
    ],
    "name": "Flag",
    "id": "flag",
    "category": "Primitives"
  },
  "stories": [
    {
      "id": "cloaked-design-system-primitives-flag--default",
      "name": "Default",
      "title": "Cloaked Design System/Primitives/Flag",
      "exportName": "Default",
      "source_path": "packages/design-system/src/components/primitives/Flag/Flag.stories.tsx",
      "source_digest": "499e7f88e45299581e11a5e792fd64cf6b79fb863d2cbda5adfa6c4dd697266c",
      "status": "preview",
      "local_url": "/storybook/iframe.html?id=cloaked-design-system-primitives-flag--default&viewMode=story"
    },
    {
      "id": "cloaked-design-system-primitives-flag--sizes",
      "name": "Sizes",
      "title": "Cloaked Design System/Primitives/Flag",
      "exportName": "Sizes",
      "source_path": "packages/design-system/src/components/primitives/Flag/Flag.stories.tsx",
      "source_digest": "499e7f88e45299581e11a5e792fd64cf6b79fb863d2cbda5adfa6c4dd697266c",
      "status": "preview",
      "local_url": "/storybook/iframe.html?id=cloaked-design-system-primitives-flag--sizes&viewMode=story"
    },
    {
      "id": "cloaked-design-system-primitives-flag--white-field-flags",
      "name": "White Field Flags",
      "title": "Cloaked Design System/Primitives/Flag",
      "exportName": "WhiteFieldFlags",
      "source_path": "packages/design-system/src/components/primitives/Flag/Flag.stories.tsx",
      "source_digest": "499e7f88e45299581e11a5e792fd64cf6b79fb863d2cbda5adfa6c4dd697266c",
      "status": "preview",
      "local_url": "/storybook/iframe.html?id=cloaked-design-system-primitives-flag--white-field-flags&viewMode=story"
    },
    {
      "id": "cloaked-design-system-primitives-flag--inline",
      "name": "Inline",
      "title": "Cloaked Design System/Primitives/Flag",
      "exportName": "Inline",
      "source_path": "packages/design-system/src/components/primitives/Flag/Flag.stories.tsx",
      "source_digest": "499e7f88e45299581e11a5e792fd64cf6b79fb863d2cbda5adfa6c4dd697266c",
      "status": "preview",
      "local_url": "/storybook/iframe.html?id=cloaked-design-system-primitives-flag--inline&viewMode=story"
    },
    {
      "id": "cloaked-design-system-primitives-flag--unknown-code",
      "name": "Unknown Code",
      "title": "Cloaked Design System/Primitives/Flag",
      "exportName": "UnknownCode",
      "source_path": "packages/design-system/src/components/primitives/Flag/Flag.stories.tsx",
      "source_digest": "499e7f88e45299581e11a5e792fd64cf6b79fb863d2cbda5adfa6c4dd697266c",
      "status": "preview",
      "local_url": "/storybook/iframe.html?id=cloaked-design-system-primitives-flag--unknown-code&viewMode=story"
    },
    {
      "id": "cloaked-design-system-primitives-flag--dark-theme",
      "name": "Dark Theme",
      "title": "Cloaked Design System/Primitives/Flag",
      "exportName": "DarkTheme",
      "source_path": "packages/design-system/src/components/primitives/Flag/Flag.stories.tsx",
      "source_digest": "499e7f88e45299581e11a5e792fd64cf6b79fb863d2cbda5adfa6c4dd697266c",
      "status": "preview",
      "local_url": "/storybook/iframe.html?id=cloaked-design-system-primitives-flag--dark-theme&viewMode=story"
    }
  ],
  "stories_source": {
    "path": "packages/design-system/src/components/primitives/Flag/Flag.stories.tsx",
    "code": "import React from 'react';\nimport type { Meta, StoryObj } from '@storybook/react-vite';\nimport { Flag } from './Flag';\n\nconst meta: Meta<typeof Flag> = {\n    title: 'Cloaked Design System/Primitives/Flag',\n    component: Flag,\n    parameters: {\n        a11y: { test: 'error' },\n        docs: {\n            description: {\n                component:\n                    'A country flag as a circular mark, drawn from vendored artwork keyed by ISO 3166-1 ' +\n                    'alpha-2 code. Use it for a country or a server location, never for a language, and keep ' +\n                    'the place named in adjacent text — a flag alone is ambiguous to many readers. Omit ' +\n                    '`label` when the surrounding text already names the country, which hides the mark from ' +\n                    'assistive technology. An unrecognized `code` renders nothing; narrow with `isFlagCode` ' +\n                    'when a caller needs a fallback.',\n            },\n        },\n    },\n    argTypes: {\n        code: { control: 'text', description: 'ISO 3166-1 alpha-2 country code, any casing.' },\n        size: { control: 'inline-radio', options: ['sm', 'md', 'lg'], description: 'Rendered scale.' },\n        label: { control: 'text', description: 'Accessible label; without it the flag is decorative.' },\n        testId: { control: 'text', description: 'Test selector on the mark.' },\n    },\n};\nexport default meta;\ntype Story = StoryObj<typeof Flag>;\n\nexport const Default: Story = { args: { code: 'nl', size: 'md', label: 'Netherlands' } };\n\nexport const Sizes: Story = {\n    parameters: { docs: { description: { story: 'The three scales, alongside body text for alignment.' } } },\n    render: () => (\n        <div style={{ display: 'flex', alignItems: 'center', gap: 'var(--cds-space-16)' }}>\n            <Flag code='ca' size='sm' label='Canada' />\n            <Flag code='ca' size='md' label='Canada' />\n            <Flag code='ca' size='lg' label='Canada' />\n        </div>\n    ),\n};\n\nexport const WhiteFieldFlags: Story = {\n    parameters: {\n        docs: {\n            description: {\n                story:\n                    'Japan, Poland, and Finland are mostly white. The hairline ring is what keeps them from ' +\n                    'dissolving into a light surface and reading as a floating red dot.',\n            },\n        },\n    },\n    render: () => (\n        <div style={{ display: 'flex', alignItems: 'center', gap: 'var(--cds-space-16)' }}>\n            <Flag code='jp' size='lg' label='Japan' />\n            <Flag code='pl' size='lg' label='Poland' />\n            <Flag code='fi' size='lg' label='Finland' />\n        </div>\n    ),\n};\n\nexport const Inline: Story = {\n    parameters: {\n        docs: { description: { story: 'Sitting inline with text, which is how the VPN surfaces use it.' } },\n    },\n    render: () => (\n        <span style={{ display: 'inline-flex', alignItems: 'center', gap: 'var(--cds-space-8)' }}>\n            <Flag code='nl' size='sm' />\n            <span style={{ color: 'var(--cds-text-secondary)' }}>Amsterdam</span>\n        </span>\n    ),\n};\n\nexport const UnknownCode: Story = {\n    parameters: {\n        docs: { description: { story: 'An unrecognized code renders nothing rather than a broken mark.' } },\n    },\n    args: { code: 'zz', size: 'md' },\n};\n\nexport const DarkTheme: Story = {\n    globals: { theme: 'dark' },\n    args: { code: 'jp', size: 'lg', label: 'Japan' },\n};\n"
  },
  "links": {
    "human": "/component-flag",
    "json": "/data/components/flag.json",
    "markdown": "/data/components/flag.md",
    "storybook": "/storybook/?path=/story/cloaked-design-system-primitives-flag--default"
  },
  "contract_status": "preview",
  "contract_kind": "source-derived",
  "approval": "required",
  "api": {
    "method": "typescript-type-checker",
    "typescript_version": "5.9.3",
    "public_export": "Flag",
    "public_path": "Flag",
    "import_path": "@cloakedinc/design-system",
    "root_kind": "component",
    "entrypoints": [
      {
        "name": "Flag",
        "signature": 1,
        "visibility": "public",
        "source": {
          "path": "packages/design-system/src/components/primitives/Flag/Flag.tsx",
          "line": 58
        },
        "props_type": "FlagProps",
        "props": [
          {
            "name": "code",
            "type": "string",
            "declared_type": "string",
            "required": true,
            "description": "ISO 3166-1 alpha-2 country code, any casing. Deliberately a plain string: codes arrive from\nbackend and bridge payloads, and an unknown one renders nothing rather than breaking a row.",
            "source": {
              "path": "packages/design-system/src/components/primitives/Flag/Flag.tsx",
              "line": 23
            }
          },
          {
            "name": "size",
            "type": "FlagSize",
            "declared_type": "FlagSize",
            "required": true,
            "description": "Rendered scale.",
            "source": {
              "path": "packages/design-system/src/components/primitives/Flag/Flag.tsx",
              "line": 25
            },
            "values": [
              "lg",
              "md",
              "sm"
            ],
            "values_complete": true
          },
          {
            "name": "label",
            "type": "string | undefined",
            "declared_type": "string",
            "required": false,
            "description": "Accessible label, e.g. the country name. Without one the flag is hidden from assistive tech —\ncorrect when the country is already named in adjacent text, which is the common case.",
            "source": {
              "path": "packages/design-system/src/components/primitives/Flag/Flag.tsx",
              "line": 30
            }
          },
          {
            "name": "className",
            "type": "string | undefined",
            "declared_type": "string",
            "required": false,
            "description": "",
            "source": {
              "path": "packages/design-system/src/components/primitives/Flag/Flag.tsx",
              "line": 31
            }
          },
          {
            "name": "testId",
            "type": "string | undefined",
            "declared_type": "string",
            "required": false,
            "description": "Optional test selector.",
            "source": {
              "path": "packages/design-system/src/components/primitives/Flag/Flag.tsx",
              "line": 33
            }
          }
        ],
        "branches": [],
        "constraints": [],
        "extraction_status": "extracted"
      }
    ],
    "type_sources": [
      {
        "path": "packages/design-system/src/components/primitives/Flag/Flag.tsx",
        "line": 13,
        "name": "FlagSize",
        "code": "export type FlagSize = 'sm' | 'md' | 'lg';"
      },
      {
        "path": "packages/design-system/src/components/primitives/Flag/Flag.tsx",
        "line": 18,
        "name": "FlagProps",
        "code": "export interface FlagProps {\n    /**\n     * ISO 3166-1 alpha-2 country code, any casing. Deliberately a plain string: codes arrive from\n     * backend and bridge payloads, and an unknown one renders nothing rather than breaking a row.\n     */\n    code: string;\n    /** Rendered scale. */\n    size: FlagSize;\n    /**\n     * Accessible label, e.g. the country name. Without one the flag is hidden from assistive tech —\n     * correct when the country is already named in adjacent text, which is the common case.\n     */\n    label?: string;\n    className?: string;\n    /** Optional test selector. */\n    testId?: string;\n}"
      }
    ],
    "defaults_policy": "Only explicit destructured parameter initializers are extracted. Other runtime defaults remain in implementation source."
  },
  "platforms": {
    "implemented": [
      "web"
    ],
    "native": "Imported design guidance only; no native implementation or parity verification in this preview.",
    "react": {
      "implementation": "local",
      "status": "preview",
      "parity": "web-reference"
    },
    "vue": {
      "implementation": "absent",
      "parity": "not-verified",
      "status": "reference-only"
    },
    "swift": {
      "implementation": "absent",
      "parity": "not-verified",
      "status": "reference-only"
    },
    "kotlin": {
      "implementation": "absent",
      "parity": "not-verified",
      "status": "reference-only"
    }
  },
  "missing_facts": [
    {
      "code": "human-review-pending",
      "detail": "This local preview has no recorded human design or engineering sign-off."
    },
    {
      "code": "platform-parity-unverified",
      "detail": "Vue, Swift and Kotlin implementations are absent from this package; platform parity has not been verified."
    },
    {
      "code": "figma-mapping-unverified",
      "detail": "No current component-level Figma node and immutable revision have been verified for this contract."
    }
  ],
  "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."
  }
}
